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
137137 "${CMAKE_SOURCE_DIR}/std/test_runner.zig"
138138 "${CMAKE_SOURCE_DIR}/std/test_runner_libc.zig"
139139 "${CMAKE_SOURCE_DIR}/std/test_runner_nolibc.zig"
140 "${CMAKE_SOURCE_DIR}/std/std.zig"
140 "${CMAKE_SOURCE_DIR}/std/io.zig"
141141 "${CMAKE_SOURCE_DIR}/std/os.zig"
142142 "${CMAKE_SOURCE_DIR}/std/syscall.zig"
143143 "${CMAKE_SOURCE_DIR}/std/errno.zig"
144144 "${CMAKE_SOURCE_DIR}/std/rand.zig"
145145 "${CMAKE_SOURCE_DIR}/std/math.zig"
146 "${CMAKE_SOURCE_DIR}/std/index.zig"
146147)
147148
148149
doc/langref.md+2-6
......@@ -5,9 +5,7 @@
55```
66Root = many(TopLevelDecl) "EOF"
77
8TopLevelDecl = many(Directive) option(VisibleMod) (FnDef | ExternDecl | RootExportDecl | Import | ContainerDecl | GlobalVarDecl | ErrorValueDecl | CImportDecl | TypeDecl)
9
10CImportDecl = "c_import" Block
8TopLevelDecl = many(Directive) option(VisibleMod) (FnDef | ExternDecl | ContainerDecl | GlobalVarDecl | ErrorValueDecl | TypeDecl | UseDecl)
119
1210TypeDecl = "type" "Symbol" "=" TypeExpr ";"
1311
......@@ -23,9 +21,7 @@ StructMember = many(Directive) option(VisibleMod) (StructField | FnDef)
2321
2422StructField = "Symbol" option(":" Expression) ",")
2523
26Import = "import" "String" ";"
27
28RootExportDecl = "export" "Symbol" "String" ";"
24UseDecl = "use" Expression ";"
2925
3026ExternDecl = "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
88target-specific. Add logic for how to do function prototypes and function calls
99for 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
1313Update 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
1414syn keyword zigRepeat while for
1515
1616syn keyword zigConstant null undefined
17syn keyword zigKeyword fn import c_import
17syn keyword zigKeyword fn use
1818syn keyword zigType bool i8 u8 i16 u16 i32 u32 i64 u64 isize usize f32 f64 void unreachable type error
1919syn 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 @@
1export executable "guess_number";
2
3import "std.zig";
4import "rand.zig";
5import "os.zig";
1const std = @import("std");
2const io = std.io;
3const Rand = std.Rand;
4const os = std.os;
65
76pub 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
109 var seed : u32 = undefined;
1110 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
1615 const answer = rand.range_u64(0, 100) + 1;
1716
1817 while (true) {
19 %%stdout.printf("\nGuess a number between 1 and 100: ");
18 %%io.stdout.printf("\nGuess a number between 1 and 100: ");
2019 var line_buf : [20]u8 = undefined;
2120
22 const line_len = stdin.read(line_buf) %% |err| {
23 %%stdout.printf("Unable to read from stdin.\n");
21 const line_len = io.stdin.read(line_buf) %% |err| {
22 %%io.stdout.printf("Unable to read from stdin.\n");
2423 return err;
2524 };
2625
27 const guess = parse_u64(line_buf[0...line_len - 1], 10) %% {
28 %%stdout.printf("Invalid number.\n");
26 const guess = io.parse_u64(line_buf[0...line_len - 1], 10) %% {
27 %%io.stdout.printf("Invalid number.\n");
2928 continue;
3029 };
3130 if (guess > answer) {
32 %%stdout.printf("Guess lower.\n");
31 %%io.stdout.printf("Guess lower.\n");
3332 } else if (guess < answer) {
34 %%stdout.printf("Guess higher.\n");
33 %%io.stdout.printf("Guess higher.\n");
3534 } else {
36 %%stdout.printf("You win!\n");
35 %%io.stdout.printf("You win!\n");
3736 return;
3837 }
3938 }
example/hello_world/hello.zig+2-4
......@@ -1,7 +1,5 @@
1export executable "hello";
2
3import "std.zig";
1const io = @import("std").io;
42
53pub fn main(args: [][]u8) -> %void {
6 %%stdout.printf("Hello, world!\n");
4 %%io.stdout.printf("Hello, world!\n");
75}
example/hello_world/hello_libc.zig+2-7
......@@ -1,11 +1,6 @@
1#link("c")
2export executable "hello";
3
4c_import {
5 @c_include("stdio.h");
6}
1const c = @c_import(@c_include("stdio.h"));
72
83export fn main(argc: c_int, argv: &&u8) -> c_int {
9 printf(c"Hello, world!\n");
4 c.printf(c"Hello, world!\n");
105 return 0;
116}
src/all_types.hpp+63-75
......@@ -76,6 +76,7 @@ struct ConstExprValue {
7676 ConstStructValue x_struct;
7777 ConstArrayValue x_array;
7878 ConstPtrValue x_ptr;
79 ImportTableEntry *x_import;
7980 } data;
8081};
8182
......@@ -91,6 +92,7 @@ enum ReturnKnowledge {
9192struct Expr {
9293 TypeTableEntry *type_entry;
9394 ReturnKnowledge return_knowledge;
95 VariableTableEntry *variable;
9496
9597 LLVMValueRef const_llvm_val;
9698 ConstExprValue const_val;
......@@ -103,13 +105,30 @@ struct StructValExprCodeGen {
103105 AstNode *source_node;
104106};
105107
108enum VisibMod {
109 VisibModPrivate,
110 VisibModPub,
111 VisibModExport,
112};
113
114enum TldResolution {
115 TldResolutionUnresolved,
116 TldResolutionInvalid,
117 TldResolutionOk,
118};
119
106120struct TopLevelDecl {
107 // reminder: hash tables must be initialized before use
108 HashMap<Buf *, AstNode *, buf_hash, buf_eql_buf> deps;
121 // populated by parser
109122 Buf *name;
123 ZigList<AstNode *> *directives;
124 VisibMod visib_mod;
125
126 // populated by semantic analyzer
110127 ImportTableEntry *import;
111128 // 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;
113132};
114133
115134struct TypeEnumField {
......@@ -120,7 +139,6 @@ struct TypeEnumField {
120139
121140enum NodeType {
122141 NodeTypeRoot,
123 NodeTypeRootExportDecl,
124142 NodeTypeFnProto,
125143 NodeTypeFnDef,
126144 NodeTypeFnDecl,
......@@ -143,8 +161,7 @@ enum NodeType {
143161 NodeTypeArrayAccessExpr,
144162 NodeTypeSliceExpr,
145163 NodeTypeFieldAccessExpr,
146 NodeTypeImport,
147 NodeTypeCImport,
164 NodeTypeUse,
148165 NodeTypeBoolLiteral,
149166 NodeTypeNullLiteral,
150167 NodeTypeUndefinedLiteral,
......@@ -173,15 +190,8 @@ struct AstNodeRoot {
173190 ZigList<AstNode *> top_level_decls;
174191};
175192
176enum VisibMod {
177 VisibModPrivate,
178 VisibModPub,
179 VisibModExport,
180};
181
182193struct AstNodeFnProto {
183 ZigList<AstNode *> *directives; // can be null if no directives
184 VisibMod visib_mod;
194 TopLevelDecl top_level_decl;
185195 Buf name;
186196 ZigList<AstNode *> params;
187197 AstNode *return_type;
......@@ -191,13 +201,10 @@ struct AstNodeFnProto {
191201
192202 // populated by semantic analyzer:
193203
194 // the struct decl node this fn proto is inside. can be null.
195 AstNode *struct_node;
196204 // the function definition this fn proto is inside. can be null.
197205 AstNode *fn_def_node;
198206 FnTableEntry *fn_table_entry;
199207 bool skip;
200 TopLevelDecl top_level_decl;
201208 Expr resolved_expr;
202209};
203210
......@@ -263,41 +270,36 @@ struct AstNodeDefer {
263270};
264271
265272struct AstNodeVariableDeclaration {
273 TopLevelDecl top_level_decl;
266274 Buf symbol;
267275 bool is_const;
268276 bool is_extern;
269 VisibMod visib_mod;
270277 // one or both of type and expr will be non null
271278 AstNode *type;
272279 AstNode *expr;
273 ZigList<AstNode *> *directives;
274280
275281 // populated by semantic analyzer
276 TopLevelDecl top_level_decl;
277282 Expr resolved_expr;
278283 VariableTableEntry *variable;
279284};
280285
281286struct AstNodeTypeDecl {
282 VisibMod visib_mod;
283 ZigList<AstNode *> *directives;
287 TopLevelDecl top_level_decl;
284288 Buf symbol;
285289 AstNode *child_type;
286290
287291 // populated by semantic analyzer
288 TopLevelDecl top_level_decl;
289292 // if this is set, don't process the node; we've already done so
290293 // and here is the type (with id TypeTableEntryIdTypeDecl)
291294 TypeTableEntry *override_type;
295 TypeTableEntry *child_type_entry;
292296};
293297
294298struct AstNodeErrorValueDecl {
299 TopLevelDecl top_level_decl;
295300 Buf name;
296 VisibMod visib_mod;
297 ZigList<AstNode *> *directives;
298301
299302 // populated by semantic analyzer
300 TopLevelDecl top_level_decl;
301303 ErrorTableEntry *err;
302304};
303305
......@@ -430,12 +432,6 @@ struct AstNodeDirective {
430432 AstNode *expr;
431433};
432434
433struct AstNodeRootExportDecl {
434 Buf type;
435 Buf name;
436 ZigList<AstNode *> *directives;
437};
438
439435enum PrefixOp {
440436 PrefixOpInvalid,
441437 PrefixOpBoolNot,
......@@ -458,19 +454,8 @@ struct AstNodePrefixOpExpr {
458454 Expr resolved_expr;
459455};
460456
461struct AstNodeImport {
462 Buf path;
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;
457struct AstNodeUse {
458 AstNode *expr;
474459
475460 // populated by semantic analyzer
476461 TopLevelDecl top_level_decl;
......@@ -600,23 +585,21 @@ enum ContainerKind {
600585};
601586
602587struct AstNodeStructDecl {
588 TopLevelDecl top_level_decl;
603589 Buf name;
604590 ContainerKind kind;
605591 ZigList<AstNode *> fields;
606592 ZigList<AstNode *> fns;
607 ZigList<AstNode *> *directives;
608 VisibMod visib_mod;
609593
610594 // populated by semantic analyzer
595 BlockContext *block_context;
611596 TypeTableEntry *type_entry;
612 TopLevelDecl top_level_decl;
613597};
614598
615599struct AstNodeStructField {
600 TopLevelDecl top_level_decl;
616601 Buf name;
617602 AstNode *type;
618 ZigList<AstNode *> *directives;
619 VisibMod visib_mod;
620603};
621604
622605struct AstNodeStringLiteral {
......@@ -695,8 +678,6 @@ struct AstNodeSymbolExpr {
695678
696679 // populated by semantic analyzer
697680 Expr resolved_expr;
698 VariableTableEntry *variable;
699 FnTableEntry *fn_entry;
700681 // set this to instead of analyzing the node, pretend it's a type entry and it's this one.
701682 TypeTableEntry *override_type_entry;
702683 TypeEnumField *enum_field;
......@@ -750,7 +731,6 @@ struct AstNode {
750731 BlockContext *block_context;
751732 union {
752733 AstNodeRoot root;
753 AstNodeRootExportDecl root_export_decl;
754734 AstNodeFnDef fn_def;
755735 AstNodeFnDecl fn_decl;
756736 AstNodeFnProto fn_proto;
......@@ -768,8 +748,7 @@ struct AstNode {
768748 AstNodeFnCallExpr fn_call_expr;
769749 AstNodeArrayAccessExpr array_access_expr;
770750 AstNodeSliceExpr slice_expr;
771 AstNodeImport import;
772 AstNodeCImport c_import;
751 AstNodeUse use;
773752 AstNodeIfBoolExpr if_bool_expr;
774753 AstNodeIfVarExpr if_var_expr;
775754 AstNodeWhileExpr while_expr;
......@@ -868,8 +847,7 @@ struct TypeTableEntryStruct {
868847 uint64_t size_bytes;
869848 bool is_invalid; // true if any fields are invalid
870849 bool is_unknown_size_array;
871 // reminder: hash tables must be initialized before use
872 HashMap<Buf *, FnTableEntry *, buf_hash, buf_eql_buf> fn_table;
850 BlockContext *block_context;
873851
874852 // set this flag temporarily to detect infinite loops
875853 bool embedded_in_current;
......@@ -895,8 +873,7 @@ struct TypeTableEntryEnum {
895873 TypeTableEntry *tag_type;
896874 TypeTableEntry *union_type;
897875
898 // reminder: hash tables must be initialized before use
899 HashMap<Buf *, FnTableEntry *, buf_hash, buf_eql_buf> fn_table;
876 BlockContext *block_context;
900877
901878 // set this flag temporarily to detect infinite loops
902879 bool embedded_in_current;
......@@ -947,6 +924,7 @@ enum TypeTableEntryId {
947924 TypeTableEntryIdEnum,
948925 TypeTableEntryIdFn,
949926 TypeTableEntryIdTypeDecl,
927 TypeTableEntryIdNamespace,
950928};
951929
952930struct TypeTableEntry {
......@@ -979,26 +957,26 @@ struct TypeTableEntry {
979957 TypeTableEntry *error_parent;
980958};
981959
982struct ImporterInfo {
983 ImportTableEntry *import;
984 AstNode *source_node;
960struct PackageTableEntry {
961 Buf root_src_dir;
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;
985966};
986967
987968struct ImportTableEntry {
988969 AstNode *root;
989 Buf *path; // relative to root_source_dir
970 Buf *path; // relative to root_package->root_src_dir
971 PackageTableEntry *package;
990972 LLVMZigDIFile *di_file;
991973 Buf *source_code;
992974 ZigList<int> *line_offsets;
993975 BlockContext *block_context;
994 ZigList<ImporterInfo> importers;
995976 AstNode *c_import_node;
996977 bool any_imports_failed;
997978
998 // reminder: hash tables must be initialized before use
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;
979 ZigList<AstNode *> use_decls;
1002980};
1003981
1004982struct FnTableEntry {
......@@ -1008,14 +986,12 @@ struct FnTableEntry {
1008986 ImportTableEntry *import_entry;
1009987 // Required to be a pre-order traversal of the AST. (parents must come before children)
1010988 ZigList<BlockContext *> all_block_contexts;
1011 TypeTableEntry *member_of_struct;
1012989 Buf symbol_name;
1013990 TypeTableEntry *type_entry; // function type
1014991 bool is_inline;
1015992 bool internal_linkage;
1016993 bool is_extern;
1017994 bool is_test;
1018 uint32_t ref_count; // if this is 0 we don't have to codegen it
1019995
1020996 ZigList<AstNode *> cast_alloca_list;
1021997 ZigList<StructValExprCodeGen *> struct_val_expr_alloca_list;
......@@ -1042,6 +1018,8 @@ enum BuiltinFnId {
10421018 BuiltinFnIdConstEval,
10431019 BuiltinFnIdCtz,
10441020 BuiltinFnIdClz,
1021 BuiltinFnIdImport,
1022 BuiltinFnIdCImport,
10451023};
10461024
10471025struct BuiltinFnEntry {
......@@ -1061,17 +1039,22 @@ struct CodeGen {
10611039 LLVMZigDIBuilder *dbuilder;
10621040 LLVMZigDICompileUnit *compile_unit;
10631041
1064 ZigList<Buf *> lib_search_paths;
1065 ZigList<Buf *> link_libs;
1042 ZigList<Buf *> link_libs; // non-libc link libs
10661043
10671044 // reminder: hash tables must be initialized before use
10681045 HashMap<Buf *, ImportTableEntry *, buf_hash, buf_eql_buf> import_table;
10691046 HashMap<Buf *, BuiltinFnEntry *, buf_hash, buf_eql_buf> builtin_fn_table;
10701047 HashMap<Buf *, TypeTableEntry *, buf_hash, buf_eql_buf> primitive_type_table;
1071 HashMap<Buf *, AstNode *, buf_hash, buf_eql_buf> unresolved_top_level_decls;
10721048 HashMap<FnTypeId *, TypeTableEntry *, fn_type_id_hash, fn_type_id_eql> fn_type_table;
10731049 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
10751058 uint32_t next_unresolved_index;
10761059
10771060 struct {
......@@ -1095,6 +1078,7 @@ struct CodeGen {
10951078 TypeTableEntry *entry_unreachable;
10961079 TypeTableEntry *entry_type;
10971080 TypeTableEntry *entry_invalid;
1081 TypeTableEntry *entry_namespace;
10981082 TypeTableEntry *entry_num_lit_int;
10991083 TypeTableEntry *entry_num_lit_float;
11001084 TypeTableEntry *entry_undef;
......@@ -1126,7 +1110,8 @@ struct CodeGen {
11261110 LLVMTargetMachineRef target_machine;
11271111 LLVMZigDIFile *dummy_di_file;
11281112 bool is_native_target;
1129 Buf *root_source_dir;
1113 PackageTableEntry *root_package;
1114 PackageTableEntry *std_package;
11301115 Buf *root_out_name;
11311116 bool windows_subsystem_windows;
11321117 bool windows_subsystem_console;
......@@ -1176,6 +1161,8 @@ struct CodeGen {
11761161 ZigList<const char *> lib_dirs;
11771162
11781163 uint32_t test_fn_count;
1164
1165 bool check_unused;
11791166};
11801167
11811168struct VariableTableEntry {
......@@ -1202,7 +1189,8 @@ struct BlockContext {
12021189 AstNode *node;
12031190
12041191 // 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
12071195 // if the block is inside a function, this is the function it is in:
12081196 FnTableEntry *fn_entry;
src/analyze.cpp+669-897
......@@ -14,8 +14,10 @@
1414#include "config.h"
1515#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,
1818 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);
1921static VariableTableEntry *analyze_variable_declaration(CodeGen *g, ImportTableEntry *import,
2022 BlockContext *context, TypeTableEntry *expected_type, AstNode *node);
2123static void resolve_struct_type(CodeGen *g, ImportTableEntry *import, TypeTableEntry *struct_type);
......@@ -27,13 +29,18 @@ static TypeTableEntry *analyze_error_literal_expr(CodeGen *g, ImportTableEntry *
2729static TypeTableEntry *analyze_block_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
2830 TypeTableEntry *expected_type, AstNode *node);
2931static 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,
31 FnTableEntry *fn);
32static TypeTableEntry *resolve_expr_const_val_as_fn(CodeGen *g, AstNode *node, FnTableEntry *fn);
3233static TypeTableEntry *resolve_expr_const_val_as_type(CodeGen *g, AstNode *node, TypeTableEntry *type);
3334static TypeTableEntry *resolve_expr_const_val_as_unsigned_num_lit(CodeGen *g, AstNode *node,
3435 TypeTableEntry *expected_type, uint64_t x);
35static void detect_top_level_decl_deps(CodeGen *g, ImportTableEntry *import, AstNode *node);
36static void analyze_top_level_decls_root(CodeGen *g, ImportTableEntry *import, AstNode *node);
36static AstNode *find_decl(BlockContext *context, Buf *name);
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
3845static AstNode *first_executing_node(AstNode *node) {
3946 switch (node->type) {
......@@ -52,7 +59,6 @@ static AstNode *first_executing_node(AstNode *node) {
5259 case NodeTypeSwitchRange:
5360 return first_executing_node(node->data.switch_range.start);
5461 case NodeTypeRoot:
55 case NodeTypeRootExportDecl:
5662 case NodeTypeFnProto:
5763 case NodeTypeFnDef:
5864 case NodeTypeFnDecl:
......@@ -69,8 +75,7 @@ static AstNode *first_executing_node(AstNode *node) {
6975 case NodeTypeCharLiteral:
7076 case NodeTypeSymbol:
7177 case NodeTypePrefixOpExpr:
72 case NodeTypeImport:
73 case NodeTypeCImport:
78 case NodeTypeUse:
7479 case NodeTypeBoolLiteral:
7580 case NodeTypeNullLiteral:
7681 case NodeTypeUndefinedLiteral:
......@@ -109,43 +114,47 @@ ErrorMsg *add_node_error(CodeGen *g, AstNode *node, Buf *msg) {
109114 return err;
110115}
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
112129TypeTableEntry *new_type_table_entry(TypeTableEntryId id) {
113130 TypeTableEntry *entry = allocate<TypeTableEntry>(1);
114131 entry->arrays_by_size.init(2);
115132 entry->id = id;
133 return entry;
134}
116135
117 switch (id) {
118 case TypeTableEntryIdInvalid:
119 case TypeTableEntryIdMetaType:
120 case TypeTableEntryIdVoid:
121 case TypeTableEntryIdBool:
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
136static BlockContext **get_container_block_context_ptr(TypeTableEntry *type_entry) {
137 if (type_entry->id == TypeTableEntryIdStruct) {
138 return &type_entry->data.structure.block_context;
139 } else if (type_entry->id == TypeTableEntryIdEnum) {
140 return &type_entry->data.enumeration.block_context;
144141 }
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);
146154 return entry;
147155}
148156
157
149158static int bits_needed_for_unsigned(uint64_t x) {
150159 if (x <= UINT8_MAX) {
151160 return 8;
......@@ -182,6 +191,7 @@ static bool type_is_complete(TypeTableEntry *type_entry) {
182191 case TypeTableEntryIdPureError:
183192 case TypeTableEntryIdFn:
184193 case TypeTableEntryIdTypeDecl:
194 case TypeTableEntryIdNamespace:
185195 return true;
186196 }
187197 zig_unreachable();
......@@ -671,7 +681,7 @@ TypeTableEntry *get_partial_container_type(CodeGen *g, ImportTableEntry *import,
671681 ContainerKind kind, AstNode *decl_node, const char *name)
672682{
673683 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
676686 switch (kind) {
677687 case ContainerKindStruct:
......@@ -730,13 +740,19 @@ static TypeTableEntry *resolve_type(CodeGen *g, AstNode *node) {
730740 return const_val->data.x_type;
731741}
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
733751// Calls analyze_expression on node, and then resolve_type.
734752static TypeTableEntry *analyze_type_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
735753 AstNode *node)
736754{
737 AstNode **node_ptr = node->parent_field;
738 analyze_expression(g, import, context, nullptr, *node_ptr);
739 return resolve_type(g, *node_ptr);
755 return analyze_type_expr_pointer_only(g, import, context, node, false);
740756}
741757
742758static 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
750766 }
751767
752768 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);
754770 fn_type_id.is_naked = is_naked;
755771 fn_type_id.is_cold = is_cold;
756772 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
782798 case TypeTableEntryIdUndefLit:
783799 case TypeTableEntryIdMetaType:
784800 case TypeTableEntryIdUnreachable:
801 case TypeTableEntryIdNamespace:
785802 fn_proto->skip = true;
786803 add_node_error(g, child->data.param_decl.type,
787804 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
880897 bool is_naked = false;
881898 bool is_test = false;
882899
883 if (fn_proto->directives) {
884 for (int i = 0; i < fn_proto->directives->length; i += 1) {
885 AstNode *directive_node = fn_proto->directives->at(i);
900 if (fn_proto->top_level_decl.directives) {
901 for (int i = 0; i < fn_proto->top_level_decl.directives->length; i += 1) {
902 AstNode *directive_node = fn_proto->top_level_decl.directives->at(i);
886903 Buf *name = &directive_node->data.directive.name;
887904
888905 if (buf_eql_str(name, "attribute")) {
......@@ -907,12 +924,12 @@ static void resolve_function_proto(CodeGen *g, AstNode *node, FnTableEntry *fn_t
907924 buf_sprintf("invalid function attribute: '%s'", buf_ptr(name)));
908925 }
909926 } else if (buf_eql_str(name, "condition")) {
910 if (fn_proto->visib_mod == VisibModExport) {
927 if (fn_proto->top_level_decl.visib_mod == VisibModExport) {
911928 bool include;
912929 bool ok = resolve_const_expr_bool(g, import, import->block_context,
913930 &directive_node->data.directive.expr, &include);
914931 if (ok && !include) {
915 fn_proto->visib_mod = VisibModPub;
932 fn_proto->top_level_decl.visib_mod = VisibModPub;
916933 }
917934 } else {
918935 add_node_error(g, directive_node,
......@@ -925,12 +942,9 @@ static void resolve_function_proto(CodeGen *g, AstNode *node, FnTableEntry *fn_t
925942 }
926943 }
927944
928 bool is_internal = (fn_proto->visib_mod != VisibModExport);
945 bool is_internal = (fn_proto->top_level_decl.visib_mod != VisibModExport);
929946 bool is_c_compat = !is_internal || fn_proto->is_extern;
930947 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
972986 LLVMAddFunctionAttr(fn_table_entry->fn_value, LLVMNoUnwindAttribute);
973987 }
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);
986989 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
9871002 BlockContext *context = new_block_context(fn_table_entry->fn_def_node, import->block_context);
9881003 fn_table_entry->fn_def_node->data.fn_def.block_context = context;
9891004 context->di_scope = LLVMZigSubprogramToScope(subprogram);
......@@ -1295,59 +1310,43 @@ static void resolve_struct_type(CodeGen *g, ImportTableEntry *import, TypeTableE
12951310 struct_type->zero_bits = (debug_size_in_bits == 0);
12961311}
12971312
1298static void preview_fn_proto(CodeGen *g, ImportTableEntry *import,
1299 AstNode *proto_node)
1300{
1313static void get_fully_qualified_decl_name(Buf *buf, AstNode *decl_node, uint8_t sep) {
1314 TopLevelDecl *tld = get_as_top_level_decl(decl_node);
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) {
13011327 if (proto_node->data.fn_proto.skip) {
13021328 return;
13031329 }
1330
1331 AstNode *parent_decl = proto_node->data.fn_proto.top_level_decl.parent_decl;
1332
13041333 AstNode *fn_def_node = proto_node->data.fn_proto.fn_def_node;
1305 AstNode *struct_node = proto_node->data.fn_proto.struct_node;
13061334 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
13151336 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 }
13281338 if (!is_extern && proto_node->data.fn_proto.is_var_args) {
13291339 add_node_error(g, proto_node,
13301340 buf_sprintf("variadic arguments only allowed in extern functions"));
13311341 }
1332 if (skip) {
1333 return;
1334 }
13351342
13361343 FnTableEntry *fn_table_entry = allocate<FnTableEntry>(1);
13371344 fn_table_entry->import_entry = import;
13381345 fn_table_entry->proto_node = proto_node;
13391346 fn_table_entry->fn_def_node = fn_def_node;
13401347 fn_table_entry->is_extern = is_extern;
1341 fn_table_entry->member_of_struct = struct_type;
13421348
1343 if (struct_type) {
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 }
1349 get_fully_qualified_decl_name(&fn_table_entry->symbol_name, proto_node, '_');
13511350
13521351 g->fn_protos.append(fn_table_entry);
13531352
......@@ -1355,39 +1354,13 @@ static void preview_fn_proto(CodeGen *g, ImportTableEntry *import,
13551354 g->fn_defs.append(fn_table_entry);
13561355 }
13571356
1358 fn_table->put(proto_name, fn_table_entry);
1359
1360 bool is_main_fn = !struct_type && (import == g->root_import) && buf_eql_str(proto_name, "main");
1357 bool is_main_fn = !parent_decl && (import == g->root_import) && buf_eql_str(proto_name, "main");
13611358 if (is_main_fn) {
13621359 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);
13731360 }
13741361
13751362 proto_node->data.fn_proto.fn_table_entry = fn_table_entry;
13761363 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 }
13911364}
13921365
13931366static void preview_error_value_decl(CodeGen *g, AstNode *node) {
......@@ -1403,110 +1376,40 @@ static void preview_error_value_decl(CodeGen *g, AstNode *node) {
14031376 // duplicate error definitions allowed and they get the same value
14041377 err->value = existing_entry->value->value;
14051378 } else {
1379 assert(g->error_value_count < (1 << g->err_tag_type->data.integral.bit_count));
14061380 err->value = g->error_value_count;
14071381 g->error_value_count += 1;
14081382 g->error_table.put(&err->name, err);
14091383 }
14101384
14111385 node->data.error_value_decl.err = err;
1386 node->data.error_value_decl.top_level_decl.resolution = TldResolutionOk;
14121387}
14131388
1414static void resolve_error_value_decl(CodeGen *g, ImportTableEntry *import, AstNode *node) {
1415 assert(node->type == NodeTypeErrorValueDecl);
1416
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) {
1389static void resolve_top_level_decl(CodeGen *g, AstNode *node, bool pointer_only) {
1390 TopLevelDecl *tld = get_as_top_level_decl(node);
1391 if (tld->resolution != TldResolutionUnresolved) {
14421392 return;
14431393 }
1444
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 }
1394 if (pointer_only && node->type == NodeTypeStructDecl) {
14791395 return;
14801396 }
14811397
1482 if (g->verbose) {
1483 fprintf(stderr, "\nc_import:\n");
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}
1398 ImportTableEntry *import = tld->import;
1399 assert(import);
14941400
1495static void satisfy_dep(CodeGen *g, AstNode *node) {
1496 Buf *name = get_resolved_top_level_decl(node)->name;
1497 if (name) {
1498 g->unresolved_top_level_decls.maybe_remove(name);
1401 if (tld->dep_loop_flag) {
1402 add_node_error(g, node, buf_sprintf("'%s' depends on itself", buf_ptr(tld->name)));
1403 tld->resolution = TldResolutionInvalid;
1404 return;
1405 } else {
1406 tld->dep_loop_flag = true;
14991407 }
1500}
15011408
1502static void resolve_top_level_decl(CodeGen *g, ImportTableEntry *import, AstNode *node) {
15031409 switch (node->type) {
15041410 case NodeTypeFnProto:
15051411 preview_fn_proto(g, import, node);
15061412 break;
1507 case NodeTypeRootExportDecl:
1508 // handled earlier
1509 return;
15101413 case NodeTypeStructDecl:
15111414 {
15121415 TypeTableEntry *type_entry = node->data.struct_decl.type_entry;
......@@ -1526,8 +1429,10 @@ static void resolve_top_level_decl(CodeGen *g, ImportTableEntry *import, AstNode
15261429 }
15271430 case NodeTypeVariableDeclaration:
15281431 {
1529 VariableTableEntry *var = analyze_variable_declaration(g, import, import->block_context,
1530 nullptr, node);
1432 AstNodeVariableDeclaration *variable_declaration = &node->data.variable_declaration;
1433 VariableTableEntry *var = analyze_variable_declaration_raw(g, import, import->block_context,
1434 node, variable_declaration, false, node);
1435
15311436 g->global_vars.append(var);
15321437 break;
15331438 }
......@@ -1547,34 +1452,13 @@ static void resolve_top_level_decl(CodeGen *g, ImportTableEntry *import, AstNode
15471452 entry = get_typedecl_type(g, buf_ptr(decl_name), child_type);
15481453 }
15491454 }
1550
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
1455 node->data.type_decl.child_type_entry = entry;
15681456 break;
15691457 }
15701458 case NodeTypeErrorValueDecl:
1571 resolve_error_value_decl(g, import, node);
15721459 break;
1573 case NodeTypeImport:
1574 // nothing to do here
1575 return;
1576 case NodeTypeCImport:
1577 resolve_c_import_decl(g, import, node);
1460 case NodeTypeUse:
1461 zig_panic("TODO resolve_top_level_decl NodeTypeUse");
15781462 break;
15791463 case NodeTypeFnDef:
15801464 case NodeTypeDirective:
......@@ -1619,8 +1503,8 @@ static void resolve_top_level_decl(CodeGen *g, ImportTableEntry *import, AstNode
16191503 zig_unreachable();
16201504 }
16211505
1622
1623 satisfy_dep(g, node);
1506 tld->resolution = TldResolutionOk;
1507 tld->dep_loop_flag = false;
16241508}
16251509
16261510static FnTableEntry *get_context_fn_entry(BlockContext *context) {
......@@ -1656,6 +1540,7 @@ static bool type_has_codegen_value(TypeTableEntry *type_entry) {
16561540 case TypeTableEntryIdNumLitFloat:
16571541 case TypeTableEntryIdNumLitInt:
16581542 case TypeTableEntryIdUndefLit:
1543 case TypeTableEntryIdNamespace:
16591544 return false;
16601545
16611546 case TypeTableEntryIdBool:
......@@ -2063,7 +1948,8 @@ BlockContext *new_block_context(AstNode *node, BlockContext *parent) {
20631948 BlockContext *context = allocate<BlockContext>(1);
20641949 context->node = node;
20651950 context->parent = parent;
2066 context->variable_table.init(4);
1951 context->decl_table.init(1);
1952 context->var_table.init(1);
20671953
20681954 if (parent) {
20691955 context->parent_loop_node = parent->parent_loop_node;
......@@ -2085,23 +1971,28 @@ BlockContext *new_block_context(AstNode *node, BlockContext *parent) {
20851971 return context;
20861972}
20871973
2088static VariableTableEntry *find_variable(BlockContext *context, Buf *name, bool local_only) {
2089 while (context && (!local_only || context->fn_entry)) {
2090 auto entry = context->variable_table.maybe_get(name);
2091 if (entry)
1974static AstNode *find_decl(BlockContext *context, Buf *name) {
1975 while (context) {
1976 auto entry = context->decl_table.maybe_get(name);
1977 if (entry) {
20921978 return entry->value;
2093
1979 }
20941980 context = context->parent;
20951981 }
20961982 return nullptr;
20971983}
20981984
2099static TypeTableEntry *find_container(ImportTableEntry *import, Buf *name) {
2100 auto entry = import->type_table.maybe_get(name);
2101 if (entry)
2102 return entry->value;
2103 else
2104 return nullptr;
1985static VariableTableEntry *find_variable(CodeGen *g, BlockContext *orig_context, Buf *name) {
1986 BlockContext *context = orig_context;
1987 while (context) {
1988 auto entry = context->var_table.maybe_get(name);
1989 if (entry) {
1990 return entry->value;
1991 }
1992 context = context->parent;
1993 }
1994
1995 return nullptr;
21051996}
21061997
21071998static TypeEnumField *get_enum_field(TypeTableEntry *enum_type, Buf *name) {
......@@ -2155,6 +2046,7 @@ static TypeTableEntry *analyze_enum_value_expr(CodeGen *g, ImportTableEntry *imp
21552046
21562047static TypeStructField *find_struct_type_field(TypeTableEntry *type_entry, Buf *name) {
21572048 assert(type_entry->id == TypeTableEntryIdStruct);
2049 assert(type_entry->data.structure.complete);
21582050 for (uint32_t i = 0; i < type_entry->data.structure.src_field_count; i += 1) {
21592051 TypeStructField *field = &type_entry->data.structure.fields[i];
21602052 if (buf_eql_buf(field->name, name)) {
......@@ -2330,8 +2222,8 @@ static TypeTableEntry *analyze_field_access_expr(CodeGen *g, ImportTableEntry *i
23302222{
23312223 assert(node->type == NodeTypeFieldAccessExpr);
23322224
2333 AstNode *struct_expr_node = node->data.field_access_expr.struct_expr;
2334 TypeTableEntry *struct_type = analyze_expression(g, import, context, nullptr, struct_expr_node);
2225 AstNode **struct_expr_node = &node->data.field_access_expr.struct_expr;
2226 TypeTableEntry *struct_type = analyze_expression(g, import, context, nullptr, *struct_expr_node);
23352227 Buf *field_name = &node->data.field_access_expr.field_name;
23362228
23372229 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
23422234 TypeTableEntry *bare_struct_type = (struct_type->id == TypeTableEntryIdStruct) ?
23432235 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
23452241 node->data.field_access_expr.bare_struct_type = bare_struct_type;
23462242 node->data.field_access_expr.type_struct_field = find_struct_type_field(bare_struct_type, field_name);
23472243 if (node->data.field_access_expr.type_struct_field) {
23482244 return node->data.field_access_expr.type_struct_field->type_entry;
23492245 } else if (wrapped_in_fn_call) {
2350 auto table_entry = bare_struct_type->data.structure.fn_table.maybe_get(field_name);
2351 if (table_entry) {
2246 BlockContext *container_block_context = get_container_block_context(bare_struct_type);
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
23522256 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);
23542259 } 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'",
23562261 buf_ptr(field_name), buf_ptr(&bare_struct_type->name)));
23572262 return g->builtin_types.entry_invalid;
23582263 }
......@@ -2372,7 +2277,7 @@ static TypeTableEntry *analyze_field_access_expr(CodeGen *g, ImportTableEntry *i
23722277 return g->builtin_types.entry_invalid;
23732278 }
23742279 } 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
23772282 if (child_type->id == TypeTableEntryIdInvalid) {
23782283 return g->builtin_types.entry_invalid;
......@@ -2381,12 +2286,15 @@ static TypeTableEntry *analyze_field_access_expr(CodeGen *g, ImportTableEntry *i
23812286 } else if (child_type->id == TypeTableEntryIdEnum) {
23822287 return analyze_enum_value_expr(g, import, context, node, nullptr, child_type, field_name);
23832288 } else if (child_type->id == TypeTableEntryIdStruct) {
2384 auto entry = child_type->data.structure.fn_table.maybe_get(field_name);
2385 if (entry) {
2386 return resolve_expr_const_val_as_fn(g, node, context, entry->value);
2289 BlockContext *container_block_context = get_container_block_context(child_type);
2290 auto entry = container_block_context->decl_table.maybe_get(field_name);
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);
23872295 } else {
23882296 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'",
23902298 buf_ptr(&child_type->name), buf_ptr(field_name)));
23912299 return g->builtin_types.entry_invalid;
23922300 }
......@@ -2397,6 +2305,26 @@ static TypeTableEntry *analyze_field_access_expr(CodeGen *g, ImportTableEntry *i
23972305 buf_sprintf("type '%s' does not support field access", buf_ptr(&struct_type->name)));
23982306 return g->builtin_types.entry_invalid;
23992307 }
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 }
24002328 } else {
24012329 if (struct_type->id != TypeTableEntryIdInvalid) {
24022330 add_node_error(g, node,
......@@ -2500,12 +2428,7 @@ static TypeTableEntry *resolve_expr_const_val_as_other_expr(CodeGen *g, AstNode
25002428 return other_expr->type_entry;
25012429}
25022430
2503static TypeTableEntry *resolve_expr_const_val_as_fn(CodeGen *g, AstNode *node, BlockContext *context,
2504 FnTableEntry *fn)
2505{
2506 if (!context->codegen_excluded) {
2507 fn->ref_count += 1;
2508 }
2431static TypeTableEntry *resolve_expr_const_val_as_fn(CodeGen *g, AstNode *node, FnTableEntry *fn) {
25092432 Expr *expr = get_resolved_expr(node);
25102433 expr->const_val.ok = true;
25112434 expr->const_val.data.x_fn = fn;
......@@ -2635,7 +2558,7 @@ static TypeTableEntry *resolve_expr_const_val_as_bignum_op(CodeGen *g, AstNode *
26352558static TypeTableEntry *analyze_error_literal_expr(CodeGen *g, ImportTableEntry *import,
26362559 BlockContext *context, AstNode *node, Buf *err_name)
26372560{
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
26402563 if (err_table_entry) {
26412564 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 *
26472570 return g->builtin_types.entry_invalid;
26482571}
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
26512613static 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)
26532615{
26542616 if (node->data.symbol_expr.override_type_entry) {
26552617 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,
26622624 return resolve_expr_const_val_as_type(g, node, primitive_table_entry->value);
26632625 }
26642626
2665 VariableTableEntry *var = find_variable(context, variable_name, false);
2627 VariableTableEntry *var = find_variable(g, context, variable_name);
26662628 if (var) {
2667 node->data.symbol_expr.variable = 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);
2629 return analyze_var_ref(g, node, var);
26842630 }
26852631
2686 auto fn_table_entry = import->fn_table.maybe_get(variable_name);
2687 if (fn_table_entry) {
2688 assert(fn_table_entry->value->type_entry);
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);
2632 AstNode *decl_node = find_decl(context, variable_name);
2633 if (decl_node) {
2634 return analyze_decl_ref(g, node, decl_node, pointer_only);
26912635 }
26922636
26932637 if (import->any_imports_failed) {
......@@ -2760,18 +2704,21 @@ static TypeTableEntry *analyze_lvalue(CodeGen *g, ImportTableEntry *import, Bloc
27602704 TypeTableEntry *expected_rhs_type = nullptr;
27612705 lhs_node->block_context = block_context;
27622706 if (lhs_node->type == NodeTypeSymbol) {
2763 Buf *name = &lhs_node->data.symbol_expr.symbol;
2764 if (purpose == LValPurposeAddressOf) {
2765 expected_rhs_type = analyze_symbol_expr(g, import, block_context, nullptr, lhs_node);
2766 } else {
2767 VariableTableEntry *var = find_variable(block_context, name, false);
2707 bool pointer_only = purpose == LValPurposeAddressOf;
2708 expected_rhs_type = analyze_symbol_expr(g, import, block_context, nullptr, lhs_node, pointer_only);
2709 if (expected_rhs_type->id == TypeTableEntryIdInvalid) {
2710 return g->builtin_types.entry_invalid;
2711 }
2712 if (purpose != LValPurposeAddressOf) {
2713 Buf *name = &lhs_node->data.symbol_expr.symbol;
2714 VariableTableEntry *var = find_variable(g, block_context, name);
27682715 if (var) {
27692716 if (var->is_const) {
27702717 add_node_error(g, lhs_node, buf_sprintf("cannot assign to constant"));
27712718 expected_rhs_type = g->builtin_types.entry_invalid;
27722719 } else {
27732720 expected_rhs_type = var->type;
2774 lhs_node->data.symbol_expr.variable = var;
2721 get_resolved_expr(lhs_node)->variable = var;
27752722 }
27762723 } else {
27772724 add_node_error(g, lhs_node,
......@@ -3176,29 +3123,36 @@ static VariableTableEntry *add_local_var(CodeGen *g, AstNode *source_node, Impor
31763123
31773124 if (name) {
31783125 buf_init_from_buf(&variable_entry->name, name);
3179 VariableTableEntry *existing_var;
31803126
3181 existing_var = find_variable(context, name, context->fn_entry != nullptr);
3182
3183 if (existing_var) {
3184 add_node_error(g, source_node, buf_sprintf("redeclaration of variable '%s'", buf_ptr(name)));
3185 variable_entry->type = g->builtin_types.entry_invalid;
3186 } else {
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)));
3127 if (type_entry->id != TypeTableEntryIdInvalid) {
3128 VariableTableEntry *existing_var = find_variable(g, context, name);
3129 if (existing_var) {
3130 ErrorMsg *msg = add_node_error(g, source_node,
3131 buf_sprintf("redeclaration of variable '%s'", buf_ptr(name)));
3132 add_error_note(g, msg, existing_var->decl_node, buf_sprintf("previous declaration is here"));
31963133 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 }
31973150 }
31983151 }
31993152
3200 context->variable_table.put(&variable_entry->name, variable_entry);
3153 context->var_table.put(&variable_entry->name, variable_entry);
32013154 } else {
3155 // TODO replace _anon with @anon and make sure all tests still pass
32023156 buf_init_from_str(&variable_entry->name, "_anon");
32033157 }
32043158 if (context->fn_entry) {
......@@ -3248,10 +3202,10 @@ static TypeTableEntry *analyze_unwrap_error_expr(CodeGen *g, ImportTableEntry *i
32483202static VariableTableEntry *analyze_variable_declaration_raw(CodeGen *g, ImportTableEntry *import,
32493203 BlockContext *context, AstNode *source_node,
32503204 AstNodeVariableDeclaration *variable_declaration,
3251 bool expr_is_maybe)
3205 bool expr_is_maybe, AstNode *decl_node)
32523206{
32533207 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);
32553209 bool is_extern = variable_declaration->is_extern;
32563210
32573211 TypeTableEntry *explicit_type = nullptr;
......@@ -3312,22 +3266,6 @@ static VariableTableEntry *analyze_variable_declaration_raw(CodeGen *g, ImportTa
33123266
33133267 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
33313269 return var;
33323270}
33333271
......@@ -3335,7 +3273,7 @@ static VariableTableEntry *analyze_variable_declaration(CodeGen *g, ImportTableE
33353273 BlockContext *context, TypeTableEntry *expected_type, AstNode *node)
33363274{
33373275 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);
33393277}
33403278
33413279static TypeTableEntry *analyze_null_literal_expr(CodeGen *g, ImportTableEntry *import,
......@@ -3516,7 +3454,8 @@ static TypeTableEntry *analyze_for_expr(CodeGen *g, ImportTableEntry *import, Bl
35163454 AstNode *elem_var_node = node->data.for_expr.elem_node;
35173455 elem_var_node->block_context = child_context;
35183456 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
35213460 AstNode *index_var_node = node->data.for_expr.index_node;
35223461 if (index_var_node) {
......@@ -3673,7 +3612,8 @@ static TypeTableEntry *analyze_if_var_expr(CodeGen *g, ImportTableEntry *import,
36733612
36743613 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);
36773617 VariableTableEntry *var = node->data.if_var_expr.var_decl.variable;
36783618 if (var->type->id == TypeTableEntryIdInvalid) {
36793619 return g->builtin_types.entry_invalid;
......@@ -4069,39 +4009,178 @@ static TypeTableEntry *analyze_cast_expr(CodeGen *g, ImportTableEntry *import, B
40694009 return g->builtin_types.entry_invalid;
40704010}
40714011
4072static TypeTableEntry *analyze_builtin_fn_call_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
4073 TypeTableEntry *expected_type, AstNode *node)
4012static TypeTableEntry *resolve_expr_const_val_as_import(CodeGen *g, AstNode *node, ImportTableEntry *import) {
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)
40744021{
40754022 assert(node->type == NodeTypeFnCallExpr);
40764023
4077 AstNode *fn_ref_expr = node->data.fn_call_expr.fn_ref_expr;
4078 Buf *name = &fn_ref_expr->data.symbol_expr.symbol;
4079
4080 auto entry = g->builtin_fn_table.maybe_get(name);
4024 if (context != import->block_context) {
4025 add_node_error(g, node, buf_sprintf("@import valid only at top level scope"));
4026 return g->builtin_types.entry_invalid;
4027 }
40814028
4082 if (!entry) {
4083 add_node_error(g, node,
4084 buf_sprintf("invalid builtin function: '%s'", buf_ptr(name)));
4029 AstNode *first_param_node = node->data.fn_call_expr.params.at(0);
4030 Buf *import_target_str = resolve_const_expr_str(g, import, context, first_param_node->parent_field);
4031 if (!import_target_str) {
40854032 return g->builtin_types.entry_invalid;
40864033 }
40874034
4088 BuiltinFnEntry *builtin_fn = entry->value;
4089 int actual_param_count = node->data.fn_call_expr.params.length;
4035 Buf *import_target_path;
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) {
4094 add_node_error(g, node,
4095 buf_sprintf("expected %d arguments, got %d",
4096 builtin_fn->param_count, actual_param_count));
4054 Buf *import_code = buf_alloc();
4055 Buf *abs_full_path = buf_alloc();
4056 int err;
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"));
40974101 return g->builtin_types.entry_invalid;
40984102 }
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) {
4103 case BuiltinFnIdInvalid:
4104 zig_unreachable();
4106 BlockContext *child_context = new_block_context(node, parent_context);
4107 child_context->c_import_buf = buf_alloc();
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();
41054184 case BuiltinFnIdAddWithOverflow:
41064185 case BuiltinFnIdSubWithOverflow:
41074186 case BuiltinFnIdMulWithOverflow:
......@@ -4252,6 +4331,7 @@ static TypeTableEntry *analyze_builtin_fn_call_expr(CodeGen *g, ImportTableEntry
42524331 case TypeTableEntryIdNumLitFloat:
42534332 case TypeTableEntryIdNumLitInt:
42544333 case TypeTableEntryIdUndefLit:
4334 case TypeTableEntryIdNamespace:
42554335 add_node_error(g, expr_node,
42564336 buf_sprintf("type '%s' not eligible for @typeof", buf_ptr(&type_entry->name)));
42574337 return g->builtin_types.entry_invalid;
......@@ -4391,6 +4471,10 @@ static TypeTableEntry *analyze_builtin_fn_call_expr(CodeGen *g, ImportTableEntry
43914471 return g->builtin_types.entry_invalid;
43924472 }
43934473 }
4474 case BuiltinFnIdImport:
4475 return analyze_import(g, import, context, node);
4476 case BuiltinFnIdCImport:
4477 return analyze_c_import(g, import, context, node);
43944478
43954479 }
43964480 zig_unreachable();
......@@ -4456,12 +4540,7 @@ static TypeTableEntry *analyze_fn_call_raw(CodeGen *g, ImportTableEntry *import,
44564540
44574541 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
44634543 return analyze_fn_call_ptr(g, import, context, expected_type, node, fn_table_entry->type_entry, struct_type);
4464
44654544}
44664545
44674546static 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
45154594 }
45164595 } else if (child_type->id == TypeTableEntryIdStruct) {
45174596 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);
4519 if (entry) {
4520 return analyze_fn_call_raw(g, import, context, expected_type, node,
4521 entry->value, nullptr);
4597 BlockContext *container_block_context = get_container_block_context(child_type);
4598 auto entry = container_block_context->decl_table.maybe_get(field_name);
4599 AstNode *decl_node = entry ? 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);
45224607 } else {
45234608 add_node_error(g, node,
45244609 buf_sprintf("struct '%s' has no function called '%s'",
......@@ -4565,19 +4650,19 @@ static TypeTableEntry *analyze_prefix_op_expr(CodeGen *g, ImportTableEntry *impo
45654650 TypeTableEntry *expected_type, AstNode *node)
45664651{
45674652 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;
45694654 switch (prefix_op) {
45704655 case PrefixOpInvalid:
45714656 zig_unreachable();
45724657 case PrefixOpBoolNot:
45734658 {
45744659 TypeTableEntry *type_entry = analyze_expression(g, import, context, g->builtin_types.entry_bool,
4575 expr_node);
4660 *expr_node);
45764661 if (type_entry->id == TypeTableEntryIdInvalid) {
45774662 return g->builtin_types.entry_bool;
45784663 }
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;
45814666 if (!target_const_val->ok) {
45824667 return g->builtin_types.entry_bool;
45834668 }
......@@ -4588,7 +4673,7 @@ static TypeTableEntry *analyze_prefix_op_expr(CodeGen *g, ImportTableEntry *impo
45884673 case PrefixOpBinNot:
45894674 {
45904675 TypeTableEntry *expr_type = analyze_expression(g, import, context, expected_type,
4591 expr_node);
4676 *expr_node);
45924677 if (expr_type->id == TypeTableEntryIdInvalid) {
45934678 return expr_type;
45944679 } else if (expr_type->id == TypeTableEntryIdInt ||
......@@ -4596,7 +4681,7 @@ static TypeTableEntry *analyze_prefix_op_expr(CodeGen *g, ImportTableEntry *impo
45964681 {
45974682 return expr_type;
45984683 } 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'",
46004685 buf_ptr(&expr_type->name)));
46014686 return g->builtin_types.entry_invalid;
46024687 }
......@@ -4604,8 +4689,7 @@ static TypeTableEntry *analyze_prefix_op_expr(CodeGen *g, ImportTableEntry *impo
46044689 }
46054690 case PrefixOpNegation:
46064691 {
4607 TypeTableEntry *expr_type = analyze_expression(g, import, context, expected_type,
4608 expr_node);
4692 TypeTableEntry *expr_type = analyze_expression(g, import, context, expected_type, *expr_node);
46094693 if (expr_type->id == TypeTableEntryIdInvalid) {
46104694 return expr_type;
46114695 } else if ((expr_type->id == TypeTableEntryIdInt &&
......@@ -4614,7 +4698,7 @@ static TypeTableEntry *analyze_prefix_op_expr(CodeGen *g, ImportTableEntry *impo
46144698 expr_type->id == TypeTableEntryIdNumLitInt ||
46154699 expr_type->id == TypeTableEntryIdNumLitFloat)
46164700 {
4617 ConstExprValue *target_const_val = &get_resolved_expr(expr_node)->const_val;
4701 ConstExprValue *target_const_val = &get_resolved_expr(*expr_node)->const_val;
46184702 if (!target_const_val->ok) {
46194703 return expr_type;
46204704 }
......@@ -4635,12 +4719,13 @@ static TypeTableEntry *analyze_prefix_op_expr(CodeGen *g, ImportTableEntry *impo
46354719 bool is_const = (prefix_op == PrefixOpConstAddressOf);
46364720
46374721 TypeTableEntry *child_type = analyze_lvalue(g, import, context,
4638 expr_node, LValPurposeAddressOf, is_const);
4722 *expr_node, LValPurposeAddressOf, is_const);
46394723
46404724 if (child_type->id == TypeTableEntryIdInvalid) {
46414725 return g->builtin_types.entry_invalid;
46424726 } 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);
46444729 if (meta_type->id == TypeTableEntryIdInvalid) {
46454730 return g->builtin_types.entry_invalid;
46464731 } else if (meta_type->id == TypeTableEntryIdUnreachable) {
......@@ -4653,7 +4738,7 @@ static TypeTableEntry *analyze_prefix_op_expr(CodeGen *g, ImportTableEntry *impo
46534738 } else if (child_type->id == TypeTableEntryIdNumLitInt ||
46544739 child_type->id == TypeTableEntryIdNumLitFloat)
46554740 {
4656 add_node_error(g, expr_node,
4741 add_node_error(g, *expr_node,
46574742 buf_sprintf("unable to get address of type '%s'", buf_ptr(&child_type->name)));
46584743 return g->builtin_types.entry_invalid;
46594744 } else {
......@@ -4662,13 +4747,13 @@ static TypeTableEntry *analyze_prefix_op_expr(CodeGen *g, ImportTableEntry *impo
46624747 }
46634748 case PrefixOpDereference:
46644749 {
4665 TypeTableEntry *type_entry = analyze_expression(g, import, context, nullptr, expr_node);
4750 TypeTableEntry *type_entry = analyze_expression(g, import, context, nullptr, *expr_node);
46664751 if (type_entry->id == TypeTableEntryIdInvalid) {
46674752 return type_entry;
46684753 } else if (type_entry->id == TypeTableEntryIdPointer) {
46694754 return type_entry->data.pointer.child_type;
46704755 } else {
4671 add_node_error(g, expr_node,
4756 add_node_error(g, *expr_node,
46724757 buf_sprintf("indirection requires pointer operand ('%s' invalid)",
46734758 buf_ptr(&type_entry->name)));
46744759 return g->builtin_types.entry_invalid;
......@@ -4676,12 +4761,12 @@ static TypeTableEntry *analyze_prefix_op_expr(CodeGen *g, ImportTableEntry *impo
46764761 }
46774762 case PrefixOpMaybe:
46784763 {
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
46814766 if (type_entry->id == TypeTableEntryIdInvalid) {
46824767 return type_entry;
46834768 } else if (type_entry->id == TypeTableEntryIdMetaType) {
4684 TypeTableEntry *meta_type = resolve_type(g, expr_node);
4769 TypeTableEntry *meta_type = resolve_type(g, *expr_node);
46854770 if (meta_type->id == TypeTableEntryIdInvalid) {
46864771 return g->builtin_types.entry_invalid;
46874772 } else if (meta_type->id == TypeTableEntryIdUnreachable) {
......@@ -4691,10 +4776,10 @@ static TypeTableEntry *analyze_prefix_op_expr(CodeGen *g, ImportTableEntry *impo
46914776 return resolve_expr_const_val_as_type(g, node, get_maybe_type(g, meta_type));
46924777 }
46934778 } 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"));
46954780 return g->builtin_types.entry_invalid;
46964781 } 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;
46984783 TypeTableEntry *maybe_type = get_maybe_type(g, type_entry);
46994784 if (!target_const_val->ok) {
47004785 return maybe_type;
......@@ -4704,12 +4789,12 @@ static TypeTableEntry *analyze_prefix_op_expr(CodeGen *g, ImportTableEntry *impo
47044789 }
47054790 case PrefixOpError:
47064791 {
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
47094794 if (type_entry->id == TypeTableEntryIdInvalid) {
47104795 return type_entry;
47114796 } else if (type_entry->id == TypeTableEntryIdMetaType) {
4712 TypeTableEntry *meta_type = resolve_type(g, expr_node);
4797 TypeTableEntry *meta_type = resolve_type(g, *expr_node);
47134798 if (meta_type->id == TypeTableEntryIdInvalid) {
47144799 return meta_type;
47154800 } else if (meta_type->id == TypeTableEntryIdUnreachable) {
......@@ -4719,7 +4804,7 @@ static TypeTableEntry *analyze_prefix_op_expr(CodeGen *g, ImportTableEntry *impo
47194804 return resolve_expr_const_val_as_type(g, node, get_error_type(g, meta_type));
47204805 }
47214806 } 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"));
47234808 return g->builtin_types.entry_invalid;
47244809 } else {
47254810 // TODO eval const expr
......@@ -4729,28 +4814,28 @@ static TypeTableEntry *analyze_prefix_op_expr(CodeGen *g, ImportTableEntry *impo
47294814 }
47304815 case PrefixOpUnwrapError:
47314816 {
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
47344819 if (type_entry->id == TypeTableEntryIdInvalid) {
47354820 return type_entry;
47364821 } else if (type_entry->id == TypeTableEntryIdErrorUnion) {
47374822 return type_entry->data.error.child_type;
47384823 } else {
4739 add_node_error(g, expr_node,
4824 add_node_error(g, *expr_node,
47404825 buf_sprintf("expected error type, got '%s'", buf_ptr(&type_entry->name)));
47414826 return g->builtin_types.entry_invalid;
47424827 }
47434828 }
47444829 case PrefixOpUnwrapMaybe:
47454830 {
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
47484833 if (type_entry->id == TypeTableEntryIdInvalid) {
47494834 return type_entry;
47504835 } else if (type_entry->id == TypeTableEntryIdMaybe) {
47514836 return type_entry->data.maybe.child_type;
47524837 } else {
4753 add_node_error(g, expr_node,
4838 add_node_error(g, *expr_node,
47544839 buf_sprintf("expected maybe type, got '%s'", buf_ptr(&type_entry->name)));
47554840 return g->builtin_types.entry_invalid;
47564841 }
......@@ -5094,7 +5179,7 @@ static TypeTableEntry *analyze_asm_expr(CodeGen *g, ImportTableEntry *import, Bl
50945179 }
50955180 } else {
50965181 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);
50985183 if (var) {
50995184 asm_output->variable = var;
51005185 return var->type;
......@@ -5120,10 +5205,8 @@ static TypeTableEntry *analyze_goto(CodeGen *g, ImportTableEntry *import, BlockC
51205205 return g->builtin_types.entry_unreachable;
51215206}
51225207
5123// When you call analyze_expression, the node you pass might no longer be the child node
5124// you thought it was due to implicit casting rewriting the AST.
5125static TypeTableEntry *analyze_expression(CodeGen *g, ImportTableEntry *import, BlockContext *context,
5126 TypeTableEntry *expected_type, AstNode *node)
5208static TypeTableEntry *analyze_expression_pointer_only(CodeGen *g, ImportTableEntry *import,
5209 BlockContext *context, TypeTableEntry *expected_type, AstNode *node, bool pointer_only)
51275210{
51285211 assert(!expected_type || expected_type->id != TypeTableEntryIdInvalid);
51295212 TypeTableEntry *return_type = nullptr;
......@@ -5197,7 +5280,7 @@ static TypeTableEntry *analyze_expression(CodeGen *g, ImportTableEntry *import,
51975280 return_type = analyze_undefined_literal_expr(g, import, context, expected_type, node);
51985281 break;
51995282 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);
52015284 break;
52025285 case NodeTypePrefixOpExpr:
52035286 return_type = analyze_prefix_op_expr(g, import, context, expected_type, node);
......@@ -5235,10 +5318,8 @@ static TypeTableEntry *analyze_expression(CodeGen *g, ImportTableEntry *import,
52355318 case NodeTypeFnDecl:
52365319 case NodeTypeParamDecl:
52375320 case NodeTypeRoot:
5238 case NodeTypeRootExportDecl:
52395321 case NodeTypeFnDef:
5240 case NodeTypeImport:
5241 case NodeTypeCImport:
5322 case NodeTypeUse:
52425323 case NodeTypeLabel:
52435324 case NodeTypeStructDecl:
52445325 case NodeTypeStructField:
......@@ -5263,7 +5344,17 @@ static TypeTableEntry *analyze_expression(CodeGen *g, ImportTableEntry *import,
52635344 return resolved_type;
52645345}
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;
52675358 assert(node->type == NodeTypeFnDef);
52685359
52695360 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
52775368
52785369 BlockContext *context = node->data.fn_def.block_context;
52795370
5280 FnTableEntry *fn_table_entry = fn_proto_node->data.fn_proto.fn_table_entry;
52815371 TypeTableEntry *fn_type = fn_table_entry->type_entry;
52825372 AstNodeFnProto *fn_proto = &fn_proto_node->data.fn_proto;
52835373 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
53025392 add_node_error(g, param_decl_node, buf_sprintf("missing parameter name"));
53035393 }
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);
53065397 var->src_arg_index = i;
53075398 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
53155406 node->data.fn_def.implicit_return_type = block_return_type;
53165407}
53175408
5318static void analyze_top_level_decl(CodeGen *g, ImportTableEntry *import, AstNode *node) {
5319 switch (node->type) {
5320 case NodeTypeFnDef:
5321 analyze_top_level_fn_def(g, import, node);
5322 break;
5323 case NodeTypeStructDecl:
5324 {
5325 for (int i = 0; i < node->data.struct_decl.fns.length; i += 1) {
5326 AstNode *fn_def_node = node->data.struct_decl.fns.at(i);
5327 analyze_top_level_fn_def(g, import, fn_def_node);
5328 }
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();
5409static void add_top_level_decl(CodeGen *g, ImportTableEntry *import, BlockContext *block_context,
5410 AstNode *node, Buf *name)
5411{
5412 assert(import);
5413
5414 TopLevelDecl *tld = get_as_top_level_decl(node);
5415 tld->import = import;
5416 tld->name = name;
5417
5418 if (g->check_unused || g->is_test_build || tld->visib_mod == VisibModExport) {
5419 g->export_queue.append(node);
53805420 }
5381}
53825421
5383static void collect_expr_decl_deps(CodeGen *g, ImportTableEntry *import, AstNode *node,
5384 TopLevelDecl *decl_node)
5385{
5386 switch (node->type) {
5387 case NodeTypeNumberLiteral:
5388 case NodeTypeStringLiteral:
5389 case NodeTypeCharLiteral:
5390 case NodeTypeBoolLiteral:
5391 case NodeTypeNullLiteral:
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();
5422 node->block_context = block_context;
5423
5424 auto entry = block_context->decl_table.maybe_get(name);
5425 if (entry) {
5426 AstNode *other_decl_node = entry->value;
5427 ErrorMsg *msg = add_node_error(g, node, buf_sprintf("redefinition of '%s'", buf_ptr(name)));
5428 add_error_note(g, msg, other_decl_node, buf_sprintf("previous definition is here"));
5429 } else {
5430 block_context->decl_table.put(name, node);
55725431 }
55735432}
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) {
55765435 switch (node->type) {
55775436 case NodeTypeRoot:
55785437 for (int i = 0; i < import->root->data.root.top_level_decls.length; i += 1) {
55795438 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);
55815440 }
55825441 break;
55835442 case NodeTypeStructDecl:
55845443 {
55855444 Buf *name = &node->data.struct_decl.name;
5586 auto table_entry = g->primitive_type_table.maybe_get(name);
5587 if (!table_entry) {
5588 table_entry = import->type_table.maybe_get(name);
5589 }
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 }
5445 TypeTableEntry *container_type = get_partial_container_type(g, import,
5446 node->data.struct_decl.kind, node, buf_ptr(name));
5447 node->data.struct_decl.type_entry = container_type;
5448 add_top_level_decl(g, import, context, node, name);
56365449
56375450 // handle the member function definitions independently
56385451 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);
5640 AstNode *fn_proto_node = fn_def_node->data.fn_def.fn_proto;
5641 fn_proto_node->data.fn_proto.struct_node = node;
5642 detect_top_level_decl_deps(g, import, fn_def_node);
5452 AstNode *child_node = node->data.struct_decl.fns.at(i);
5453 get_as_top_level_decl(child_node)->parent_decl = node;
5454 BlockContext *child_context = get_container_block_context(container_type);
5455 scan_decls(g, import, child_context, child_node);
56435456 }
56445457
56455458 break;
56465459 }
56475460 case NodeTypeFnDef:
56485461 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);
56505463 break;
56515464 case NodeTypeVariableDeclaration:
56525465 {
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 }
56625466 Buf *name = &node->data.variable_declaration.symbol;
5663 decl_node->name = 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 }
5467 add_top_level_decl(g, import, context, node, name);
56705468 break;
56715469 }
56725470 case NodeTypeTypeDecl:
56735471 {
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
56795472 Buf *name = &node->data.type_decl.symbol;
5680 decl_node->name = 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 }
5473 add_top_level_decl(g, import, context, node, name);
56875474 break;
56885475 }
56895476 case NodeTypeFnProto:
......@@ -5695,60 +5482,22 @@ static void detect_top_level_decl_deps(CodeGen *g, ImportTableEntry *import, Ast
56955482 add_node_error(g, node, buf_sprintf("missing function name"));
56965483 break;
56975484 }
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);
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 }
5486 add_top_level_decl(g, import, context, node, fn_name);
57265487 break;
57275488 }
5728 case NodeTypeRootExportDecl:
5729 resolve_top_level_decl(g, import, node);
5730 break;
5731 case NodeTypeImport:
5732 // already taken care of
5733 break;
5734 case NodeTypeCImport:
5489 case NodeTypeUse:
57355490 {
5736 TopLevelDecl *decl_node = &node->data.c_import.top_level_decl;
5737 decl_node->deps.init(1);
5738 collect_expr_decl_deps(g, import, node->data.c_import.block, decl_node);
5739
5740 decl_node->name = buf_sprintf("c_import_%" PRIu32, node->create_index);
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 }
5491 TopLevelDecl *tld = get_as_top_level_decl(node);
5492 tld->import = import;
5493 node->block_context = context;
5494 g->use_queue.append(node);
5495 tld->import->use_decls.append(node);
57475496 break;
57485497 }
57495498 case NodeTypeErrorValueDecl:
57505499 // 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);
57525501 break;
57535502 case NodeTypeDirective:
57545503 case NodeTypeParamDecl:
......@@ -5792,152 +5541,176 @@ static void detect_top_level_decl_deps(CodeGen *g, ImportTableEntry *import, Ast
57925541 }
57935542}
57945543
5795static void recursive_resolve_decl(CodeGen *g, ImportTableEntry *import, AstNode *node) {
5796 auto it = get_resolved_top_level_decl(node)->deps.entry_iterator();
5797 for (;;) {
5798 auto *entry = it.next();
5799 if (!entry)
5800 break;
5544static void add_symbols_from_import(CodeGen *g, AstNode *src_use_node, AstNode *dst_use_node) {
5545 TopLevelDecl *tld = get_as_top_level_decl(dst_use_node);
5546 AstNode *use_target_node = src_use_node->data.use.expr;
5547 Expr *expr = get_resolved_expr(use_target_node);
58015548
5802 auto unresolved_entry = g->unresolved_top_level_decls.maybe_get(entry->key);
5803 if (!unresolved_entry) {
5804 continue;
5805 }
5549 if (expr->type_entry->id == TypeTableEntryIdInvalid) {
5550 return;
5551 }
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) {
5810 // dependency loop. we'll let the fact that it's not in the respective
5811 // table cause an error in resolve_top_level_decl.
5563 for (int i = 0; i < target_import->root->data.root.top_level_decls.length; i += 1) {
5564 AstNode *decl_node = target_import->root->data.root.top_level_decls.at(i);
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) {
58125570 continue;
58135571 }
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 flag
5816 TopLevelDecl *top_level_decl = get_resolved_top_level_decl(child_node);
5817 top_level_decl->in_current_deps = true;
5589 for (int i = 0; i < target_import->use_decls.length; i += 1) {
5590 AstNode *use_decl_node = target_import->use_decls.at(i);
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 flag
5822 top_level_decl->in_current_deps = false;
5823 }
5599static void resolve_use_decl(CodeGen *g, AstNode *node) {
5600 assert(node->type == NodeTypeUse);
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 }
58265612}
58275613
5828static void resolve_top_level_declarations_root(CodeGen *g, ImportTableEntry *import, AstNode *node) {
5829 assert(node->type == NodeTypeRoot);
5614ImportTableEntry *add_source_file(CodeGen *g, PackageTableEntry *package,
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) {
5832 // for the sake of determinism, find the element with the lowest
5833 // insert index and resolve that one.
5834 AstNode *decl_node = nullptr;
5835 auto it = g->unresolved_top_level_decls.entry_iterator();
5836 for (;;) {
5837 auto *entry = it.next();
5838 if (!entry)
5839 break;
5620 if (g->verbose) {
5621 fprintf(stderr, "\nOriginal Source (%s):\n", buf_ptr(full_path));
5622 fprintf(stderr, "----------------\n");
5623 fprintf(stderr, "%s\n", buf_ptr(source_code));
58405624
5841 AstNode *this_node = entry->value;
5842 if (!decl_node || this_node->create_index < decl_node->create_index) {
5843 decl_node = this_node;
5844 }
5625 fprintf(stderr, "\nTokens:\n");
5626 fprintf(stderr, "---------\n");
5627 }
58455628
5846 }
5847 // set temporary flag
5848 TopLevelDecl *top_level_decl = get_resolved_top_level_decl(decl_node);
5849 top_level_decl->in_current_deps = true;
5629 Tokenization tokenization = {0};
5630 tokenize(source_code, &tokenization);
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 flag
5854 top_level_decl->in_current_deps = false;
5636 print_err_msg(err, g->err_color);
5637 exit(1);
58555638 }
5856}
58575639
5858static void analyze_top_level_decls_root(CodeGen *g, ImportTableEntry *import, AstNode *node) {
5859 assert(node->type == NodeTypeRoot);
5640 if (g->verbose) {
5641 print_tokens(source_code, tokenization.tokens);
58605642
5861 for (int i = 0; i < node->data.root.top_level_decls.length; i += 1) {
5862 AstNode *child = node->data.root.top_level_decls.at(i);
5863 analyze_top_level_decl(g, import, child);
5643 fprintf(stderr, "\nAST:\n");
5644 fprintf(stderr, "------\n");
58645645 }
5865}
58665646
5867void semantic_analyze(CodeGen *g) {
5868 {
5869 auto it = g->import_table.entry_iterator();
5870 for (;;) {
5871 auto *entry = it.next();
5872 if (!entry)
5873 break;
5647 ImportTableEntry *import_entry = allocate<ImportTableEntry>(1);
5648 import_entry->package = package;
5649 import_entry->source_code = source_code;
5650 import_entry->line_offsets = tokenization.line_offsets;
5651 import_entry->path = full_path;
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) {
5878 AstNode *child = import->root->data.root.top_level_decls.at(i);
5879 if (child->type == NodeTypeImport) {
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 }
5660 import_entry->di_file = LLVMZigCreateFile(g->dbuilder, buf_ptr(src_basename), buf_ptr(src_dirname));
5661 g->import_table.put(abs_full_path, import_entry);
5662 g->import_queue.append(import_entry);
58885663
5889 ImportTableEntry *target_import = child->data.import.import;
5890 assert(target_import);
5664 import_entry->block_context = new_block_context(import_entry->root, nullptr);
5665 import_entry->block_context->di_scope = LLVMZigFileToScope(import_entry->di_file);
58915666
5892 target_import->importers.append({import, child});
5893 } else if (child->type == NodeTypeErrorValueDecl) {
5894 preview_error_value_decl(g, child);
5895 }
5667
5668 assert(import_entry->root->type == NodeTypeRoot);
5669 for (int decl_i = 0; decl_i < import_entry->root->data.root.top_level_decls.length; decl_i += 1) {
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;
58965681 }
58975682 }
58985683 }
58995684
5900 {
5901 g->err_tag_type = get_smallest_unsigned_int_type(g, g->error_value_count);
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 }
5685 return import_entry;
5686}
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);
5917 }
5695 for (; g->use_queue_index < g->use_queue.length; g->use_queue_index += 1) {
5696 AstNode *use_decl_node = g->use_queue.at(g->use_queue_index);
5697 preview_use_decl(g, use_decl_node);
59185698 }
59195699
5920 {
5921 auto it = g->import_table.entry_iterator();
5922 for (;;) {
5923 auto *entry = it.next();
5924 if (!entry)
5925 break;
5700 for (int i = 0; i < g->use_queue.length; i += 1) {
5701 AstNode *use_decl_node = g->use_queue.at(i);
5702 resolve_use_decl(g, use_decl_node);
5703 }
59265704
5927 ImportTableEntry *import = entry->value;
5928 resolve_top_level_declarations_root(g, import, import->root);
5929 }
5705 for (; g->export_queue_index < g->export_queue.length; g->export_queue_index += 1) {
5706 AstNode *decl_node = g->export_queue.at(g->export_queue_index);
5707 bool pointer_only = false;
5708 resolve_top_level_decl(g, decl_node, pointer_only);
59305709 }
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;
5939 analyze_top_level_decls_root(g, import, import->root);
5940 }
5711 for (int i = 0; i < g->fn_defs.length; i += 1) {
5712 FnTableEntry *fn_entry = g->fn_defs.at(i);
5713 analyze_fn_body(g, fn_entry);
59415714 }
59425715}
59435716
......@@ -6012,13 +5785,11 @@ Expr *get_resolved_expr(AstNode *node) {
60125785 case NodeTypeSwitchProng:
60135786 case NodeTypeSwitchRange:
60145787 case NodeTypeRoot:
6015 case NodeTypeRootExportDecl:
60165788 case NodeTypeFnDef:
60175789 case NodeTypeFnDecl:
60185790 case NodeTypeParamDecl:
60195791 case NodeTypeDirective:
6020 case NodeTypeImport:
6021 case NodeTypeCImport:
5792 case NodeTypeUse:
60225793 case NodeTypeStructDecl:
60235794 case NodeTypeStructField:
60245795 case NodeTypeStructValueField:
......@@ -6029,18 +5800,20 @@ Expr *get_resolved_expr(AstNode *node) {
60295800 zig_unreachable();
60305801}
60315802
6032TopLevelDecl *get_resolved_top_level_decl(AstNode *node) {
5803static TopLevelDecl *get_as_top_level_decl(AstNode *node) {
60335804 switch (node->type) {
60345805 case NodeTypeVariableDeclaration:
60355806 return &node->data.variable_declaration.top_level_decl;
60365807 case NodeTypeFnProto:
60375808 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;
60385811 case NodeTypeStructDecl:
60395812 return &node->data.struct_decl.top_level_decl;
60405813 case NodeTypeErrorValueDecl:
60415814 return &node->data.error_value_decl.top_level_decl;
6042 case NodeTypeCImport:
6043 return &node->data.c_import.top_level_decl;
5815 case NodeTypeUse:
5816 return &node->data.use.top_level_decl;
60445817 case NodeTypeTypeDecl:
60455818 return &node->data.type_decl.top_level_decl;
60465819 case NodeTypeNumberLiteral:
......@@ -6063,8 +5836,6 @@ TopLevelDecl *get_resolved_top_level_decl(AstNode *node) {
60635836 case NodeTypeAsmExpr:
60645837 case NodeTypeContainerInitExpr:
60655838 case NodeTypeRoot:
6066 case NodeTypeRootExportDecl:
6067 case NodeTypeFnDef:
60685839 case NodeTypeFnDecl:
60695840 case NodeTypeParamDecl:
60705841 case NodeTypeBlock:
......@@ -6072,7 +5843,6 @@ TopLevelDecl *get_resolved_top_level_decl(AstNode *node) {
60725843 case NodeTypeStringLiteral:
60735844 case NodeTypeCharLiteral:
60745845 case NodeTypeSymbol:
6075 case NodeTypeImport:
60765846 case NodeTypeBoolLiteral:
60775847 case NodeTypeNullLiteral:
60785848 case NodeTypeUndefinedLiteral:
......@@ -6140,6 +5910,7 @@ bool handle_is_ptr(TypeTableEntry *type_entry) {
61405910 case TypeTableEntryIdNumLitFloat:
61415911 case TypeTableEntryIdNumLitInt:
61425912 case TypeTableEntryIdUndefLit:
5913 case TypeTableEntryIdNamespace:
61435914 zig_unreachable();
61445915 case TypeTableEntryIdUnreachable:
61455916 case TypeTableEntryIdVoid:
......@@ -6257,6 +6028,7 @@ static TypeTableEntry *type_of_first_thing_in_memory(TypeTableEntry *type_entry)
62576028 case TypeTableEntryIdUnreachable:
62586029 case TypeTableEntryIdMetaType:
62596030 case TypeTableEntryIdVoid:
6031 case TypeTableEntryIdNamespace:
62606032 zig_unreachable();
62616033 case TypeTableEntryIdArray:
62626034 return type_of_first_thing_in_memory(type_entry->data.array.child_type);
src/analyze.hpp+5-1
......@@ -12,11 +12,11 @@
1212
1313void semantic_analyze(CodeGen *g);
1414ErrorMsg *add_node_error(CodeGen *g, AstNode *node, Buf *msg);
15ErrorMsg *add_error_note(CodeGen *g, ErrorMsg *parent_msg, AstNode *node, Buf *msg);
1516TypeTableEntry *new_type_table_entry(TypeTableEntryId id);
1617TypeTableEntry *get_pointer_to_type(CodeGen *g, TypeTableEntry *child_type, bool is_const);
1718BlockContext *new_block_context(AstNode *node, BlockContext *parent);
1819Expr *get_resolved_expr(AstNode *node);
19TopLevelDecl *get_resolved_top_level_decl(AstNode *node);
2020bool is_node_void_expr(AstNode *node);
2121TypeTableEntry **get_int_type_ptr(CodeGen *g, bool is_signed, int size_in_bits);
2222TypeTableEntry *get_int_type(CodeGen *g, bool is_signed, int size_in_bits);
......@@ -37,4 +37,8 @@ TypeTableEntry *get_underlying_type(TypeTableEntry *type_entry);
3737bool type_has_bits(TypeTableEntry *type_entry);
3838uint64_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
4044#endif
src/ast_render.cpp+21-33
......@@ -101,8 +101,6 @@ static const char *node_type_str(NodeType node_type) {
101101 switch (node_type) {
102102 case NodeTypeRoot:
103103 return "Root";
104 case NodeTypeRootExportDecl:
105 return "RootExportDecl";
106104 case NodeTypeFnDef:
107105 return "FnDef";
108106 case NodeTypeFnDecl:
......@@ -145,10 +143,8 @@ static const char *node_type_str(NodeType node_type) {
145143 return "Symbol";
146144 case NodeTypePrefixOpExpr:
147145 return "PrefixOpExpr";
148 case NodeTypeImport:
149 return "Import";
150 case NodeTypeCImport:
151 return "CImport";
146 case NodeTypeUse:
147 return "Use";
152148 case NodeTypeBoolLiteral:
153149 return "BoolLiteral";
154150 case NodeTypeNullLiteral:
......@@ -214,11 +210,6 @@ void ast_print(FILE *f, AstNode *node, int indent) {
214210 ast_print(f, child, indent + 2);
215211 }
216212 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;
222213 case NodeTypeFnDef:
223214 {
224215 fprintf(f, "%s\n", node_type_str(node->type));
......@@ -372,12 +363,9 @@ void ast_print(FILE *f, AstNode *node, int indent) {
372363 case NodeTypeSymbol:
373364 fprintf(f, "Symbol %s\n", buf_ptr(&node->data.symbol_expr.symbol));
374365 break;
375 case NodeTypeImport:
376 fprintf(f, "%s '%s'\n", node_type_str(node->type), buf_ptr(&node->data.import.path));
377 break;
378 case NodeTypeCImport:
366 case NodeTypeUse:
379367 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);
381369 break;
382370 case NodeTypeBoolLiteral:
383371 fprintf(f, "%s '%s'\n", node_type_str(node->type),
......@@ -556,7 +544,7 @@ static void render_node(AstRender *ar, AstNode *node) {
556544 print_indent(ar);
557545 render_node(ar, child);
558546
559 if (child->type == NodeTypeImport ||
547 if (child->type == NodeTypeUse ||
560548 child->type == NodeTypeVariableDeclaration ||
561549 child->type == NodeTypeTypeDecl ||
562550 child->type == NodeTypeErrorValueDecl ||
......@@ -567,12 +555,10 @@ static void render_node(AstRender *ar, AstNode *node) {
567555 fprintf(ar->f, "\n");
568556 }
569557 break;
570 case NodeTypeRootExportDecl:
571 zig_panic("TODO");
572558 case NodeTypeFnProto:
573559 {
574560 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);
576562 const char *extern_str = extern_string(node->data.fn_proto.is_extern);
577563 const char *inline_str = inline_string(node->data.fn_proto.is_inline);
578564 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) {
605591 break;
606592 }
607593 case NodeTypeFnDef:
608 if (node->data.fn_def.fn_proto->data.fn_proto.directives) {
609 for (int i = 0; i < node->data.fn_def.fn_proto->data.fn_proto.directives->length; i += 1) {
610 render_node(ar, node->data.fn_def.fn_proto->data.fn_proto.directives->at(i));
594 {
595 ZigList<AstNode *> *directives =
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 }
611601 }
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;
612606 }
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;
617607 case NodeTypeFnDecl:
618608 zig_panic("TODO");
619609 case NodeTypeParamDecl:
......@@ -642,7 +632,7 @@ static void render_node(AstRender *ar, AstNode *node) {
642632 zig_panic("TODO");
643633 case NodeTypeVariableDeclaration:
644634 {
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);
646636 const char *extern_str = extern_string(node->data.variable_declaration.is_extern);
647637 const char *var_name = buf_ptr(&node->data.variable_declaration.symbol);
648638 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) {
659649 }
660650 case NodeTypeTypeDecl:
661651 {
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);
663653 const char *var_name = buf_ptr(&node->data.type_decl.symbol);
664654 fprintf(ar->f, "%stype %s = ", pub_str, var_name);
665655 render_node(ar, node->data.type_decl.child_type);
......@@ -748,9 +738,7 @@ static void render_node(AstRender *ar, AstNode *node) {
748738 fprintf(ar->f, ".%s", buf_ptr(rhs));
749739 break;
750740 }
751 case NodeTypeImport:
752 zig_panic("TODO");
753 case NodeTypeCImport:
741 case NodeTypeUse:
754742 zig_panic("TODO");
755743 case NodeTypeBoolLiteral:
756744 zig_panic("TODO");
......@@ -785,7 +773,7 @@ static void render_node(AstRender *ar, AstNode *node) {
785773 case NodeTypeStructDecl:
786774 {
787775 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);
789777 const char *container_str = container_string(node->data.struct_decl.kind);
790778 fprintf(ar->f, "%s%s %s {\n", pub_str, container_str, struct_name);
791779 ar->indent += ar->indent_size;
src/codegen.cpp+95-252
......@@ -47,19 +47,30 @@ static void init_darwin_native(CodeGen *g) {
4747 }
4848}
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
5058CodeGen *codegen_create(Buf *root_source_dir, const ZigTarget *target) {
5159 CodeGen *g = allocate<CodeGen>(1);
5260 g->import_table.init(32);
5361 g->builtin_fn_table.init(32);
5462 g->primitive_type_table.init(32);
55 g->unresolved_top_level_decls.init(32);
5663 g->fn_type_table.init(32);
5764 g->error_table.init(16);
5865 g->is_release_build = false;
5966 g->is_test_build = false;
60 g->root_source_dir = root_source_dir;
6167 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
6374 if (target) {
6475 // cross compiling, so we can't rely on all the configured stuff since
6576 // that's for native compilation
......@@ -117,6 +128,10 @@ void codegen_set_verbose(CodeGen *g, bool verbose) {
117128 g->verbose = verbose;
118129}
119130
131void codegen_set_check_unused(CodeGen *g, bool check_unused) {
132 g->check_unused = check_unused;
133}
134
120135void codegen_set_errmsg_color(CodeGen *g, ErrColor err_color) {
121136 g->err_color = err_color;
122137}
......@@ -157,6 +172,14 @@ void codegen_add_lib_dir(CodeGen *g, const char *dir) {
157172 g->lib_dirs.append(dir);
158173}
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
160183void codegen_set_windows_subsystem(CodeGen *g, bool mwindows, bool mconsole) {
161184 g->windows_subsystem_windows = mwindows;
162185 g->windows_subsystem_console = mconsole;
......@@ -316,6 +339,8 @@ static LLVMValueRef gen_builtin_fn_call_expr(CodeGen *g, AstNode *node) {
316339 case BuiltinFnIdCInclude:
317340 case BuiltinFnIdCDefine:
318341 case BuiltinFnIdCUndef:
342 case BuiltinFnIdImport:
343 case BuiltinFnIdCImport:
319344 zig_unreachable();
320345 case BuiltinFnIdCtz:
321346 case BuiltinFnIdClz:
......@@ -844,7 +869,7 @@ static LLVMValueRef gen_field_ptr(CodeGen *g, AstNode *node, TypeTableEntry **ou
844869
845870 LLVMValueRef struct_ptr;
846871 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;
848873 assert(var);
849874
850875 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
9831008 }
9841009}
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
9861022static LLVMValueRef gen_field_access_expr(CodeGen *g, AstNode *node, bool is_lvalue) {
9871023 assert(node->type == NodeTypeFieldAccessExpr);
9881024
......@@ -1016,6 +1052,10 @@ static LLVMValueRef gen_field_access_expr(CodeGen *g, AstNode *node, bool is_lva
10161052 } else {
10171053 zig_unreachable();
10181054 }
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);
10191059 } else {
10201060 zig_unreachable();
10211061 }
......@@ -1027,7 +1067,7 @@ static LLVMValueRef gen_lvalue(CodeGen *g, AstNode *expr_node, AstNode *node,
10271067 LLVMValueRef target_ref;
10281068
10291069 if (node->type == NodeTypeSymbol) {
1030 VariableTableEntry *var = node->data.symbol_expr.variable;
1070 VariableTableEntry *var = get_resolved_expr(node)->variable;
10311071 assert(var);
10321072
10331073 *out_type_entry = var->type;
......@@ -2468,21 +2508,18 @@ static LLVMValueRef gen_var_decl_expr(CodeGen *g, AstNode *node) {
24682508
24692509static LLVMValueRef gen_symbol(CodeGen *g, AstNode *node) {
24702510 assert(node->type == NodeTypeSymbol);
2471 VariableTableEntry *variable = node->data.symbol_expr.variable;
2511 VariableTableEntry *variable = get_resolved_expr(node)->variable;
24722512 if (variable) {
2473 if (!type_has_bits(variable->type)) {
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 }
2513 return gen_variable(g, node, variable);
24812514 }
24822515
2516 zig_unreachable();
2517
2518 /* TODO delete
24832519 FnTableEntry *fn_entry = node->data.symbol_expr.fn_entry;
24842520 assert(fn_entry);
24852521 return fn_entry->fn_value;
2522 */
24862523}
24872524
24882525static LLVMValueRef gen_switch_expr(CodeGen *g, AstNode *node) {
......@@ -2703,14 +2740,12 @@ static LLVMValueRef gen_expr(CodeGen *g, AstNode *node) {
27032740 // caught by constant expression eval codegen
27042741 zig_unreachable();
27052742 case NodeTypeRoot:
2706 case NodeTypeRootExportDecl:
27072743 case NodeTypeFnProto:
27082744 case NodeTypeFnDef:
27092745 case NodeTypeFnDecl:
27102746 case NodeTypeParamDecl:
27112747 case NodeTypeDirective:
2712 case NodeTypeImport:
2713 case NodeTypeCImport:
2748 case NodeTypeUse:
27142749 case NodeTypeStructDecl:
27152750 case NodeTypeStructField:
27162751 case NodeTypeStructValueField:
......@@ -2891,6 +2926,7 @@ static LLVMValueRef gen_const_val(CodeGen *g, TypeTableEntry *type_entry, ConstE
28912926 case TypeTableEntryIdNumLitInt:
28922927 case TypeTableEntryIdUndefLit:
28932928 case TypeTableEntryIdVoid:
2929 case TypeTableEntryIdNamespace:
28942930 zig_unreachable();
28952931
28962932 }
......@@ -2943,14 +2979,14 @@ static bool skip_fn_codegen(CodeGen *g, FnTableEntry *fn_entry) {
29432979 if (fn_entry == g->main_fn) {
29442980 return true;
29452981 }
2946 return fn_entry->ref_count == 0;
2982 return false;
29472983 }
29482984
29492985 if (fn_entry->is_test) {
29502986 return true;
29512987 }
29522988
2953 return fn_entry->ref_count == 0;
2989 return false;
29542990}
29552991
29562992static LLVMValueRef gen_test_fn_val(CodeGen *g, FnTableEntry *fn_entry) {
......@@ -3296,6 +3332,12 @@ static void define_builtin_types(CodeGen *g) {
32963332 entry->zero_bits = true;
32973333 g->builtin_types.entry_invalid = entry;
32983334 }
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 }
32993341 {
33003342 TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdNumLitFloat);
33013343 buf_init_from_str(&entry->name, "(float literal)");
......@@ -3499,14 +3541,6 @@ static void define_builtin_types(CodeGen *g) {
34993541 g->builtin_types.entry_type = entry;
35003542 g->primitive_type_table.put(&entry->name, entry);
35013543 }
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
35113545 g->builtin_types.entry_u8 = get_int_type(g, false, 8);
35123546 g->builtin_types.entry_u16 = get_int_type(g, false, 16);
......@@ -3517,6 +3551,21 @@ static void define_builtin_types(CodeGen *g) {
35173551 g->builtin_types.entry_i32 = get_int_type(g, true, 32);
35183552 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
35203569 {
35213570 TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdEnum);
35223571 entry->zero_bits = true; // only allowed at compile time
......@@ -3685,12 +3734,11 @@ static void define_builtin_fns(CodeGen *g) {
36853734 create_builtin_fn_with_arg_count(g, BuiltinFnIdConstEval, "const_eval", 1);
36863735 create_builtin_fn_with_arg_count(g, BuiltinFnIdCtz, "ctz", 2);
36873736 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);
36883739}
36893740
36903741static 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
36943742 g->module = LLVMModuleCreateWithName(buf_ptr(source_path));
36953743
36963744 get_target_triple(&g->triple_str, &g->zig_target);
......@@ -3741,7 +3789,7 @@ static void init(CodeGen *g, Buf *source_path) {
37413789 const char *flags = "";
37423790 unsigned runtime_version = 0;
37433791 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),
37453793 buf_ptr(producer), is_optimized, flags, runtime_version,
37463794 "", 0, !g->strip_debug_symbols);
37473795
......@@ -3761,9 +3809,6 @@ void codegen_parseh(CodeGen *g, Buf *src_dirname, Buf *src_basename, Buf *source
37613809 ImportTableEntry *import = allocate<ImportTableEntry>(1);
37623810 import->source_code = source_code;
37633811 import->path = full_path;
3764 import->fn_table.init(32);
3765 import->type_table.init(8);
3766 import->error_table.init(8);
37673812 g->root_import = import;
37683813
37693814 init(g, full_path);
......@@ -3791,214 +3836,7 @@ void codegen_render_ast(CodeGen *g, FILE *f, int indent_size) {
37913836}
37923837
37933838
3794static int parse_version_string(Buf *buf, int *major, int *minor, int *patch) {
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) {
3839static ImportTableEntry *add_special_code(CodeGen *g, PackageTableEntry *package, const char *basename) {
40023840 Buf *std_dir = buf_create_from_str(ZIG_STD_DIR);
40033841 Buf *code_basename = buf_create_from_str(basename);
40043842 Buf path_to_code_src = BUF_INIT;
......@@ -4013,12 +3851,22 @@ static ImportTableEntry *add_special_code(CodeGen *g, const char *basename) {
40133851 zig_panic("unable to open '%s': %s", buf_ptr(&path_to_code_src), err_str(err));
40143852 }
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;
40173862}
40183863
40193864void codegen_add_root_code(CodeGen *g, Buf *src_dir, Buf *src_basename, Buf *source_code) {
40203865 Buf source_path = BUF_INIT;
40213866 os_path_join(src_dir, src_basename, &source_path);
3867
3868 buf_init_from_buf(&g->root_package->root_src_path, src_basename);
3869
40223870 init(g, &source_path);
40233871
40243872 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
40273875 zig_panic("unable to open '%s': %s", buf_ptr(&source_path), err_str(err));
40283876 }
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) {
4033 add_node_error(g, g->root_import->root,
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 }
3880 assert(g->root_out_name);
3881 assert(g->out_type != OutTypeUnknown);
40393882
40403883 if (!g->link_libc && !g->is_test_build) {
40413884 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");
40433886 }
40443887 }
40453888
......@@ -4120,7 +3963,7 @@ void codegen_generate_h_file(CodeGen *g) {
41203963 assert(proto_node->type == NodeTypeFnProto);
41213964 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)
41243967 continue;
41253968
41263969 Buf return_type_c = BUF_INIT;
src/codegen.hpp+2
......@@ -19,6 +19,7 @@ CodeGen *codegen_create(Buf *root_source_dir, const ZigTarget *target);
1919void codegen_set_clang_argv(CodeGen *codegen, const char **args, int len);
2020void codegen_set_is_release(CodeGen *codegen, bool is_release);
2121void codegen_set_is_test(CodeGen *codegen, bool is_test);
22void codegen_set_check_unused(CodeGen *codegen, bool check_unused);
2223
2324void codegen_set_is_static(CodeGen *codegen, bool is_static);
2425void codegen_set_strip(CodeGen *codegen, bool strip);
......@@ -34,6 +35,7 @@ void codegen_set_linker_path(CodeGen *g, Buf *linker_path);
3435void codegen_set_windows_subsystem(CodeGen *g, bool mwindows, bool mconsole);
3536void codegen_set_windows_unicode(CodeGen *g, bool municode);
3637void codegen_add_lib_dir(CodeGen *codegen, const char *dir);
38void codegen_add_link_lib(CodeGen *codegen, const char *lib);
3739void codegen_set_mlinker_version(CodeGen *g, Buf *darwin_linker_version);
3840void codegen_set_rdynamic(CodeGen *g, bool rdynamic);
3941void codegen_set_mmacosx_version_min(CodeGen *g, Buf *mmacosx_version_min);
src/errmsg.cpp+33-12
......@@ -4,36 +4,57 @@
44#include <stdio.h>
55
66#define RED "\x1b[31;1m"
7#define WHITE "\x1b[37;1m"
87#define GREEN "\x1b[32;1m"
8#define CYAN "\x1b[36;1m"
9#define WHITE "\x1b[37;1m"
910#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
1224 if (color == ErrColorOn || (color == ErrColorAuto && os_stderr_tty())) {
13 fprintf(stderr, WHITE "%s:%d:%d: " RED "error:" WHITE " %s" RESET "\n",
14 buf_ptr(err->path),
15 err->line_start + 1, err->column_start + 1,
16 buf_ptr(err->msg));
25 if (err_type == ErrTypeError) {
26 fprintf(stderr, WHITE "%s:%d:%d: " RED "error:" WHITE " %s" RESET "\n", path, line, col, text);
27 } else if (err_type == ErrTypeNote) {
28 fprintf(stderr, WHITE "%s:%d:%d: " CYAN "note:" WHITE " %s" RESET "\n", path, line, col, text);
29 } else {
30 zig_unreachable();
31 }
1732
1833 fprintf(stderr, "%s\n", buf_ptr(&err->line_buf));
1934 for (int i = 0; i < err->column_start; i += 1) {
2035 fprintf(stderr, " ");
2136 }
2237 fprintf(stderr, GREEN "^" RESET "\n");
23
2438 } else {
25 fprintf(stderr, "%s:%d:%d: error: %s\n",
26 buf_ptr(err->path),
27 err->line_start + 1, err->column_start + 1,
28 buf_ptr(err->msg));
39 if (err_type == ErrTypeError) {
40 fprintf(stderr, "%s:%d:%d: error: %s\n", path, line, col, text);
41 } else if (err_type == ErrTypeNote) {
42 fprintf(stderr, " %s:%d:%d: note: %s\n", path, line, col, text);
43 } else {
44 zig_unreachable();
45 }
2946 }
3047
3148 for (int i = 0; i < err->notes.length; i += 1) {
3249 ErrorMsg *note = err->notes.at(i);
33 print_err_msg(note, color);
50 print_err_msg_type(note, color, ErrTypeNote);
3451 }
3552}
3653
54void print_err_msg(ErrorMsg *err, ErrColor color) {
55 print_err_msg_type(err, color, ErrTypeError);
56}
57
3758void err_msg_add_note(ErrorMsg *parent, ErrorMsg *note) {
3859 parent->notes.append(note);
3960}
src/main.cpp+25-2
......@@ -18,8 +18,8 @@
1818static int usage(const char *arg0) {
1919 fprintf(stderr, "Usage: %s [command] [options]\n"
2020 "Commands:\n"
21 " build [source] create executable, object, or library from source\n"
22 " test [source] create and run a test build\n"
21 " build [sources] create executable, object, or library from source\n"
22 " test [sources] create and run a test build\n"
2323 " parseh [source] convert a c header file to zig extern declarations\n"
2424 " version print version number and exit\n"
2525 " targets list available compilation targets\n"
......@@ -40,6 +40,7 @@ static int usage(const char *arg0) {
4040 " -isystem [dir] add additional search path for other .h files\n"
4141 " -dirafter [dir] same as -isystem but do it last\n"
4242 " --library-path [dir] add a directory to the library search path\n"
43 " --library [lib] link against lib\n"
4344 " --target-arch [name] specify target architecture\n"
4445 " --target-os [name] specify target operating system\n"
4546 " --target-environ [name] specify target environment\n"
......@@ -50,6 +51,7 @@ static int usage(const char *arg0) {
5051 " -rdynamic add all symbols to the dynamic symbol table\n"
5152 " -mmacosx-version-min [ver] (darwin only) set Mac OS X deployment target\n"
5253 " -mios-version-min [ver] (darwin only) set iOS deployment target\n"
54 " --check-unused perform semantic analysis on unused declarations\n"
5355 , arg0);
5456 return EXIT_FAILURE;
5557}
......@@ -118,6 +120,7 @@ int main(int argc, char **argv) {
118120 const char *linker_path = nullptr;
119121 ZigList<const char *> clang_argv = {0};
120122 ZigList<const char *> lib_dirs = {0};
123 ZigList<const char *> link_libs = {0};
121124 int err;
122125 const char *target_arch = nullptr;
123126 const char *target_os = nullptr;
......@@ -129,6 +132,7 @@ int main(int argc, char **argv) {
129132 bool rdynamic = false;
130133 const char *mmacosx_version_min = nullptr;
131134 const char *mios_version_min = nullptr;
135 bool check_unused = false;
132136
133137 for (int i = 1; i < argc; i += 1) {
134138 char *arg = argv[i];
......@@ -150,6 +154,8 @@ int main(int argc, char **argv) {
150154 municode = true;
151155 } else if (strcmp(arg, "-rdynamic") == 0) {
152156 rdynamic = true;
157 } else if (strcmp(arg, "--check-unused") == 0) {
158 check_unused = true;
153159 } else if (i + 1 >= argc) {
154160 return usage(arg0);
155161 } else {
......@@ -198,6 +204,8 @@ int main(int argc, char **argv) {
198204 clang_argv.append(argv[i]);
199205 } else if (strcmp(arg, "--library-path") == 0) {
200206 lib_dirs.append(argv[i]);
207 } else if (strcmp(arg, "--library") == 0) {
208 link_libs.append(argv[i]);
201209 } else if (strcmp(arg, "--target-arch") == 0) {
202210 target_arch = argv[i];
203211 } else if (strcmp(arg, "--target-os") == 0) {
......@@ -258,6 +266,16 @@ int main(int argc, char **argv) {
258266 if (!in_file)
259267 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
261279 init_all_targets();
262280
263281 ZigTarget alloc_target;
......@@ -313,6 +331,8 @@ int main(int argc, char **argv) {
313331 codegen_set_is_release(g, is_release_build);
314332 codegen_set_is_test(g, cmd == CmdTest);
315333
334 codegen_set_check_unused(g, check_unused);
335
316336 codegen_set_clang_argv(g, clang_argv.items, clang_argv.length);
317337 codegen_set_strip(g, strip);
318338 codegen_set_is_static(g, is_static);
......@@ -342,6 +362,9 @@ int main(int argc, char **argv) {
342362 for (int i = 0; i < lib_dirs.length; i += 1) {
343363 codegen_add_lib_dir(g, lib_dirs.at(i));
344364 }
365 for (int i = 0; i < link_libs.length; i += 1) {
366 codegen_add_link_lib(g, link_libs.at(i));
367 }
345368
346369 codegen_set_windows_subsystem(g, mwindows, mconsole);
347370 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
121121 AstNode *node = create_node(c, NodeTypeVariableDeclaration);
122122 buf_init_from_str(&node->data.variable_declaration.symbol, var_name);
123123 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;
125125 node->data.variable_declaration.expr = init_node;
126 node->data.variable_declaration.directives = nullptr;
126 node->data.variable_declaration.top_level_decl.directives = nullptr;
127127 node->data.variable_declaration.type = type_node;
128128 normalize_parent_ptrs(node);
129129 return node;
......@@ -146,7 +146,7 @@ static AstNode *create_struct_field_node(Context *c, const char *name, AstNode *
146146 assert(type_node);
147147 AstNode *node = create_node(c, NodeTypeStructField);
148148 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;
150150 node->data.struct_field.type = type_node;
151151
152152 normalize_parent_ptrs(node);
......@@ -202,7 +202,7 @@ static AstNode *create_num_lit_signed(Context *c, int64_t x) {
202202static AstNode *create_type_decl_node(Context *c, const char *name, AstNode *child_type_node) {
203203 AstNode *node = create_node(c, NodeTypeTypeDecl);
204204 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;
206206 node->data.type_decl.child_type = child_type_node;
207207
208208 normalize_parent_ptrs(node);
......@@ -219,7 +219,7 @@ static AstNode *create_fn_proto_node(Context *c, Buf *name, TypeTableEntry *fn_t
219219 assert(fn_type->id == TypeTableEntryIdFn);
220220 AstNode *node = create_node(c, NodeTypeFnProto);
221221 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;
223223 buf_init_from_buf(&node->data.fn_proto.name, name);
224224 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) {
677677 buf_init_from_buf(&node->data.fn_proto.name, &fn_name);
678678
679679 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;
681681 node->data.fn_proto.is_var_args = fn_type->data.fn.fn_type_id.is_var_args;
682682 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) {
861861 AstNode *enum_node = create_node(c, NodeTypeStructDecl);
862862 buf_init_from_buf(&enum_node->data.struct_decl.name, full_type_name);
863863 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;
865865 enum_node->data.struct_decl.type_entry = enum_type;
866866
867867 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) {
10431043 AstNode *struct_node = create_node(c, NodeTypeStructDecl);
10441044 buf_init_from_buf(&struct_node->data.struct_decl.name, &struct_type->name);
10451045 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;
10471047 struct_node->data.struct_decl.type_entry = struct_type;
10481048
10491049 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 {
2020 ZigList<Token> *tokens;
2121 ImportTableEntry *owner;
2222 ErrColor err_color;
23 bool parsed_root_export;
2423 uint32_t *next_node_index;
2524};
2625
......@@ -1741,8 +1740,8 @@ static AstNode *ast_parse_variable_declaration_expr(ParseContext *pc, int *token
17411740 AstNode *node = ast_create_node(pc, NodeTypeVariableDeclaration, first_token);
17421741
17431742 node->data.variable_declaration.is_const = is_const;
1744 node->data.variable_declaration.visib_mod = visib_mod;
1745 node->data.variable_declaration.directives = directives;
1743 node->data.variable_declaration.top_level_decl.visib_mod = visib_mod;
1744 node->data.variable_declaration.top_level_decl.directives = directives;
17461745
17471746 Token *name_token = ast_eat_token(pc, token_index, TokenIdSymbol);
17481747 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
22512250 *token_index += 1;
22522251
22532252 AstNode *node = ast_create_node(pc, NodeTypeFnProto, first_token);
2254 node->data.fn_proto.visib_mod = visib_mod;
2255 node->data.fn_proto.directives = directives;
2253 node->data.fn_proto.top_level_decl.visib_mod = visib_mod;
2254 node->data.fn_proto.top_level_decl.directives = directives;
22562255
22572256 Token *fn_name = &pc->tokens->at(*token_index);
22582257 if (fn_name->id == TokenIdSymbol) {
......@@ -2345,76 +2344,23 @@ static AstNode *ast_parse_extern_decl(ParseContext *pc, int *token_index, bool m
23452344}
23462345
23472346/*
2348RootExportDecl : "export" "Symbol" "String" ";"
2347UseDecl = "use" Expression ";"
23492348*/
2350static AstNode *ast_parse_root_export_decl(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,
2349static AstNode *ast_parse_use(ParseContext *pc, int *token_index,
23822350 ZigList<AstNode*> *directives, VisibMod visib_mod)
23832351{
2384 Token *import_kw = &pc->tokens->at(*token_index);
2385 if (import_kw->id != TokenIdKeywordImport)
2352 Token *use_kw = &pc->tokens->at(*token_index);
2353 if (use_kw->id != TokenIdKeywordUse)
23862354 return nullptr;
23872355 *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
23912362 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
24182364 normalize_parent_ptrs(node);
24192365 return node;
24202366}
......@@ -2445,8 +2391,8 @@ static AstNode *ast_parse_struct_decl(ParseContext *pc, int *token_index,
24452391 AstNode *node = ast_create_node(pc, NodeTypeStructDecl, first_token);
24462392 node->data.struct_decl.kind = kind;
24472393 ast_buf_from_token(pc, struct_name, &node->data.struct_decl.name);
2448 node->data.struct_decl.visib_mod = visib_mod;
2449 node->data.struct_decl.directives = directives;
2394 node->data.struct_decl.top_level_decl.visib_mod = visib_mod;
2395 node->data.struct_decl.top_level_decl.directives = directives;
24502396
24512397 ast_eat_token(pc, token_index, TokenIdLBrace);
24522398
......@@ -2486,8 +2432,8 @@ static AstNode *ast_parse_struct_decl(ParseContext *pc, int *token_index,
24862432 AstNode *field_node = ast_create_node(pc, NodeTypeStructField, token);
24872433 *token_index += 1;
24882434
2489 field_node->data.struct_field.visib_mod = visib_mod;
2490 field_node->data.struct_field.directives = directive_list;
2435 field_node->data.struct_field.top_level_decl.visib_mod = visib_mod;
2436 field_node->data.struct_field.top_level_decl.directives = directive_list;
24912437
24922438 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,
25292475 ast_eat_token(pc, token_index, TokenIdSemicolon);
25302476
25312477 AstNode *node = ast_create_node(pc, NodeTypeErrorValueDecl, first_token);
2532 node->data.error_value_decl.visib_mod = visib_mod;
2533 node->data.error_value_decl.directives = directives;
2478 node->data.error_value_decl.top_level_decl.visib_mod = visib_mod;
2479 node->data.error_value_decl.top_level_decl.directives = directives;
25342480 ast_buf_from_token(pc, name_tok, &node->data.error_value_decl.name);
25352481
25362482 normalize_parent_ptrs(node);
......@@ -2559,15 +2505,15 @@ static AstNode *ast_parse_type_decl(ParseContext *pc, int *token_index,
25592505
25602506 ast_eat_token(pc, token_index, TokenIdSemicolon);
25612507
2562 node->data.type_decl.visib_mod = visib_mod;
2563 node->data.type_decl.directives = directives;
2508 node->data.type_decl.top_level_decl.visib_mod = visib_mod;
2509 node->data.type_decl.top_level_decl.directives = directives;
25642510
25652511 normalize_parent_ptrs(node);
25662512 return node;
25672513}
25682514
25692515/*
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)
25712517*/
25722518static void ast_parse_top_level_decls(ParseContext *pc, int *token_index, ZigList<AstNode *> *top_level_decls) {
25732519 for (;;) {
......@@ -2587,17 +2533,6 @@ static void ast_parse_top_level_decls(ParseContext *pc, int *token_index, ZigLis
25872533 visib_mod = VisibModPrivate;
25882534 }
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
26012536 AstNode *fn_def_node = ast_parse_fn_def(pc, token_index, false, directives, visib_mod);
26022537 if (fn_def_node) {
26032538 top_level_decls->append(fn_def_node);
......@@ -2610,15 +2545,9 @@ static void ast_parse_top_level_decls(ParseContext *pc, int *token_index, ZigLis
26102545 continue;
26112546 }
26122547
2613 AstNode *import_node = ast_parse_import(pc, token_index, directives, visib_mod);
2614 if (import_node) {
2615 top_level_decls->append(import_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);
2548 AstNode *use_node = ast_parse_use(pc, token_index, directives, visib_mod);
2549 if (use_node) {
2550 top_level_decls->append(use_node);
26222551 continue;
26232552 }
26242553
......@@ -2706,12 +2635,9 @@ void normalize_parent_ptrs(AstNode *node) {
27062635 case NodeTypeRoot:
27072636 set_list_fields(&node->data.root.top_level_decls);
27082637 break;
2709 case NodeTypeRootExportDecl:
2710 set_list_fields(node->data.root_export_decl.directives);
2711 break;
27122638 case NodeTypeFnProto:
27132639 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);
27152641 set_list_fields(&node->data.fn_proto.params);
27162642 break;
27172643 case NodeTypeFnDef:
......@@ -2737,12 +2663,12 @@ void normalize_parent_ptrs(AstNode *node) {
27372663 set_field(&node->data.defer.expr);
27382664 break;
27392665 case NodeTypeVariableDeclaration:
2740 set_list_fields(node->data.variable_declaration.directives);
2666 set_list_fields(node->data.variable_declaration.top_level_decl.directives);
27412667 set_field(&node->data.variable_declaration.type);
27422668 set_field(&node->data.variable_declaration.expr);
27432669 break;
27442670 case NodeTypeTypeDecl:
2745 set_list_fields(node->data.type_decl.directives);
2671 set_list_fields(node->data.type_decl.top_level_decl.directives);
27462672 set_field(&node->data.type_decl.child_type);
27472673 break;
27482674 case NodeTypeErrorValueDecl:
......@@ -2788,12 +2714,9 @@ void normalize_parent_ptrs(AstNode *node) {
27882714 case NodeTypeFieldAccessExpr:
27892715 set_field(&node->data.field_access_expr.struct_expr);
27902716 break;
2791 case NodeTypeImport:
2792 set_list_fields(node->data.import.directives);
2793 break;
2794 case NodeTypeCImport:
2795 set_list_fields(node->data.c_import.directives);
2796 set_field(&node->data.c_import.block);
2717 case NodeTypeUse:
2718 set_field(&node->data.use.expr);
2719 set_list_fields(node->data.use.top_level_decl.directives);
27972720 break;
27982721 case NodeTypeBoolLiteral:
27992722 // none
......@@ -2863,11 +2786,11 @@ void normalize_parent_ptrs(AstNode *node) {
28632786 case NodeTypeStructDecl:
28642787 set_list_fields(&node->data.struct_decl.fields);
28652788 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);
28672790 break;
28682791 case NodeTypeStructField:
28692792 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);
28712794 break;
28722795 case NodeTypeContainerInitExpr:
28732796 set_field(&node->data.container_init_expr.type);
src/tokenizer.cpp+4-7
......@@ -99,7 +99,7 @@
9999
100100const char * zig_keywords[] = {
101101 "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",
103103 "volatile", "struct", "enum", "while", "for", "continue", "break",
104104 "null", "noalias", "switch", "undefined", "error", "type", "inline",
105105 "defer",
......@@ -232,10 +232,8 @@ static void end_token(Tokenize *t) {
232232 t->cur_tok->id = TokenIdKeywordPub;
233233 } else if (mem_eql_str(token_mem, token_len, "export")) {
234234 t->cur_tok->id = TokenIdKeywordExport;
235 } else if (mem_eql_str(token_mem, token_len, "c_import")) {
236 t->cur_tok->id = TokenIdKeywordCImport;
237 } else if (mem_eql_str(token_mem, token_len, "import")) {
238 t->cur_tok->id = TokenIdKeywordImport;
235 } else if (mem_eql_str(token_mem, token_len, "use")) {
236 t->cur_tok->id = TokenIdKeywordUse;
239237 } else if (mem_eql_str(token_mem, token_len, "true")) {
240238 t->cur_tok->id = TokenIdKeywordTrue;
241239 } else if (mem_eql_str(token_mem, token_len, "false")) {
......@@ -1071,8 +1069,7 @@ const char * token_name(TokenId id) {
10711069 case TokenIdKeywordExtern: return "extern";
10721070 case TokenIdKeywordPub: return "pub";
10731071 case TokenIdKeywordExport: return "export";
1074 case TokenIdKeywordImport: return "import";
1075 case TokenIdKeywordCImport: return "c_import";
1072 case TokenIdKeywordUse: return "use";
10761073 case TokenIdKeywordTrue: return "true";
10771074 case TokenIdKeywordFalse: return "false";
10781075 case TokenIdKeywordIf: return "if";
src/tokenizer.hpp+1-2
......@@ -19,9 +19,8 @@ enum TokenId {
1919 TokenIdKeywordConst,
2020 TokenIdKeywordExtern,
2121 TokenIdKeywordPub,
22 TokenIdKeywordUse,
2223 TokenIdKeywordExport,
23 TokenIdKeywordImport,
24 TokenIdKeywordCImport,
2524 TokenIdKeywordTrue,
2625 TokenIdKeywordFalse,
2726 TokenIdKeywordIf,
std/bootstrap.zig+15-14
......@@ -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`
4// from the root source file as the symbol `zig_user_main`.
3const root = @import("@root");
4const syscall = @import("syscall.zig");
55
66const want_start_symbol = switch(@compile_var("os")) {
77 linux => true,
......@@ -26,7 +26,7 @@ export fn _start() -> unreachable {
2626 },
2727 else => unreachable{},
2828 }
29 call_main()
29 call_main_and_exit()
3030}
3131
3232fn strlen(ptr: &const u8) -> isize {
......@@ -37,23 +37,24 @@ fn strlen(ptr: &const u8) -> isize {
3737 return count;
3838}
3939
40fn call_main() -> unreachable {
40fn call_main() -> %void {
4141 var args: [argc][]u8 = undefined;
4242 for (args) |arg, i| {
4343 const ptr = argv[i];
4444 args[i] = ptr[0...strlen(ptr)];
4545 }
46 zig_user_main(args) %% exit(1);
47 exit(0);
46 return root.main(args);
47}
48
49fn call_main_and_exit() -> unreachable {
50 call_main() %% syscall.exit(1);
51 syscall.exit(0);
4852}
4953
5054#condition(want_main_symbol)
51export fn main(argc: i32, argv: &&u8) -> i32 {
52 var args: [argc][]u8 = undefined;
53 for (args) |arg, i| {
54 const ptr = argv[i];
55 args[i] = ptr[0...strlen(ptr)];
56 }
57 zig_user_main(args) %% return 1;
55export fn main(c_argc: i32, c_argv: &&u8) -> i32 {
56 argc = c_argc;
57 argv = c_argv;
58 call_main() %% return 1;
5859 return 0;
5960}
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 @@
1import "syscall.zig";
2import "errno.zig";
1const syscall = @import("syscall.zig");
2const errno = @import("errno.zig");
33
44pub error SigInterrupt;
55pub error Unexpected;
66
7pub fn os_get_random_bytes(buf: []u8) -> %void {
7pub fn get_random_bytes(buf: []u8) -> %void {
88 switch (@compile_var("os")) {
99 linux => {
10 const amt_got = getrandom(buf.ptr, buf.len, 0);
10 const amt_got = syscall.getrandom(buf.ptr, buf.len, 0);
1111 if (amt_got < 0) {
1212 return switch (-amt_got) {
13 EINVAL => unreachable{},
14 EFAULT => unreachable{},
15 EINTR => error.SigInterrupt,
16 else => error.Unexpected,
13 errno.EINVAL => unreachable{},
14 errno.EFAULT => unreachable{},
15 errno.EINTR => error.SigInterrupt,
16 else => error.Unexpected,
1717 }
1818 }
1919 },
std/rand.zig+14-14
......@@ -84,26 +84,26 @@ pub struct Rand {
8484 }
8585 return bytes_left;
8686 }
87}
8887
89/// Initialize random state with the given seed.
90pub fn rand_new(seed: u32) -> Rand {
91 var r: Rand = undefined;
92 r.index = 0;
93 r.array[0] = seed;
94 var i : isize = 1;
95 var prev_value: u64 = seed;
96 while (i < ARRAY_SIZE) {
97 r.array[i] = u32((prev_value ^ (prev_value << 30)) * 0x6c078965 + u32(i));
98 prev_value = r.array[i];
99 i += 1;
88 /// Initialize random state with the given seed.
89 pub fn init(seed: u32) -> Rand {
90 var r: Rand = undefined;
91 r.index = 0;
92 r.array[0] = seed;
93 var i : isize = 1;
94 var prev_value: u64 = seed;
95 while (i < ARRAY_SIZE) {
96 r.array[i] = u32((prev_value ^ (prev_value << 30)) * 0x6c078965 + u32(i));
97 prev_value = r.array[i];
98 i += 1;
99 }
100 return r;
100101 }
101 return r;
102102}
103103
104104#attribute("test")
105105fn test_float32() {
106 var r = rand_new(42);
106 var r = Rand.init(42);
107107
108108 // TODO for loop with range
109109 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 @@
1import "std.zig";
1const io = @import("std").io;
22
33struct TestFn {
44 name: []u8,
......@@ -9,19 +9,19 @@ extern var zig_test_fn_list: []TestFn;
99
1010pub fn run_tests() -> %void {
1111 for (zig_test_fn_list) |test_fn, i| {
12 %%stderr.print_str("Test ");
13 %%stderr.print_i64(i + 1);
14 %%stderr.print_str("/");
15 %%stderr.print_i64(zig_test_fn_list.len);
16 %%stderr.print_str(" ");
17 %%stderr.print_str(test_fn.name);
18 %%stderr.print_str("...");
19 %%stderr.flush();
12 %%io.stderr.print_str("Test ");
13 %%io.stderr.print_i64(i + 1);
14 %%io.stderr.print_str("/");
15 %%io.stderr.print_i64(zig_test_fn_list.len);
16 %%io.stderr.print_str(" ");
17 %%io.stderr.print_str(test_fn.name);
18 %%io.stderr.print_str("...");
19 %%io.stderr.flush();
2020
2121 test_fn.func();
2222
2323
24 %%stderr.print_str("OK\n");
25 %%stderr.flush();
24 %%io.stderr.print_str("OK\n");
25 %%io.stderr.flush();
2626 }
2727}
std/test_runner_libc.zig+2-2
......@@ -1,6 +1,6 @@
1import "test_runner.zig";
1const test_runner = @import("test_runner.zig");
22
33export fn main(argc: c_int, argv: &&u8) -> c_int {
4 run_tests() %% return -1;
4 test_runner.run_tests() %% return -1;
55 return 0;
66}
std/test_runner_nolibc.zig+2-2
......@@ -1,5 +1,5 @@
1import "test_runner.zig";
1const test_runner = @import("test_runner.zig");
22
33pub fn main(args: [][]u8) -> %void {
4 return run_tests();
4 return test_runner.run_tests();
55}
test/run_tests.cpp+323-326
......@@ -70,12 +70,20 @@ static TestCase *add_simple_case(const char *case_name, const char *source, cons
7070 test_case->compiler_args.append("--strip");
7171 test_case->compiler_args.append("--color");
7272 test_case->compiler_args.append("on");
73 test_case->compiler_args.append("--check-unused");
7374
7475 test_cases.append(test_case);
7576
7677 return test_case;
7778}
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
7987static TestCase *add_compile_fail_case(const char *case_name, const char *source, int count, ...) {
8088 va_list ap;
8189 va_start(ap, count);
......@@ -93,11 +101,19 @@ static TestCase *add_compile_fail_case(const char *case_name, const char *source
93101
94102 test_case->compiler_args.append("build");
95103 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
96111 test_case->compiler_args.append("--output");
97112 test_case->compiler_args.append(tmp_exe_path);
113
98114 test_case->compiler_args.append("--release");
99115 test_case->compiler_args.append("--strip");
100 //test_case->compiler_args.append("--verbose");
116 test_case->compiler_args.append("--check-unused");
101117
102118 test_cases.append(test_case);
103119
......@@ -134,43 +150,18 @@ static TestCase *add_parseh_case(const char *case_name, const char *source, int
134150}
135151
136152static void add_compiling_test_cases(void) {
137 add_simple_case("hello world with libc", R"SOURCE(
138#link("c")
139export executable "test";
140
141c_import {
142 @c_include("stdio.h");
143}
144
153 add_simple_case_libc("hello world with libc", R"SOURCE(
154const c = @c_import(@c_include("stdio.h"));
145155export fn main(argc: c_int, argv: &&u8) -> c_int {
146 puts(c"Hello, world!");
156 c.puts(c"Hello, world!");
147157 return 0;
148158}
149159 )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
170161 {
171162 TestCase *tc = add_simple_case("multiple files with private function", R"SOURCE(
172import "std.zig";
173import "foo.zig";
163use @import("std").io;
164use @import("foo.zig");
174165
175166pub fn main(args: [][]u8) -> %void {
176167 private_function();
......@@ -183,7 +174,7 @@ fn private_function() {
183174 )SOURCE", "OK 1\nOK 2\n");
184175
185176 add_source_file(tc, "foo.zig", R"SOURCE(
186import "std.zig";
177use @import("std").io;
187178
188179// purposefully conflicting function with main.zig
189180// but it's private so it should be OK
......@@ -199,8 +190,8 @@ pub fn print_text() {
199190
200191 {
201192 TestCase *tc = add_simple_case("import segregation", R"SOURCE(
202import "foo.zig";
203import "bar.zig";
193use @import("foo.zig");
194use @import("bar.zig");
204195
205196pub fn main(args: [][]u8) -> %void {
206197 foo_function();
......@@ -209,15 +200,15 @@ pub fn main(args: [][]u8) -> %void {
209200 )SOURCE", "OK\nOK\n");
210201
211202 add_source_file(tc, "foo.zig", R"SOURCE(
212import "std.zig";
203use @import("std").io;
213204pub fn foo_function() {
214205 %%stdout.printf("OK\n");
215206}
216207 )SOURCE");
217208
218209 add_source_file(tc, "bar.zig", R"SOURCE(
219import "other.zig";
220import "std.zig";
210use @import("other.zig");
211use @import("std").io;
221212
222213pub fn bar_function() {
223214 if (foo_function()) {
......@@ -234,8 +225,35 @@ pub fn foo_function() -> bool {
234225 )SOURCE");
235226 }
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
237255 add_simple_case("params", R"SOURCE(
238import "std.zig";
256const io = @import("std").io;
239257
240258fn add(a: i32, b: i32) -> i32 {
241259 a + b
......@@ -243,13 +261,13 @@ fn add(a: i32, b: i32) -> i32 {
243261
244262pub fn main(args: [][]u8) -> %void {
245263 if (add(22, 11) == 33) {
246 %%stdout.printf("pass\n");
264 %%io.stdout.printf("pass\n");
247265 }
248266}
249267 )SOURCE", "pass\n");
250268
251269 add_simple_case("void parameters", R"SOURCE(
252import "std.zig";
270const io = @import("std").io;
253271
254272pub fn main(args: [][]u8) -> %void {
255273 void_fun(1, void{}, 2);
......@@ -258,28 +276,28 @@ pub fn main(args: [][]u8) -> %void {
258276fn void_fun(a : i32, b : void, c : i32) {
259277 const v = b;
260278 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"); }
262280 return vv;
263281}
264282 )SOURCE", "OK\n");
265283
266284 add_simple_case("mutable local variables", R"SOURCE(
267import "std.zig";
285const io = @import("std").io;
268286
269287pub fn main(args: [][]u8) -> %void {
270288 var zero : i32 = 0;
271 if (zero == 0) { %%stdout.printf("zero\n"); }
289 if (zero == 0) { %%io.stdout.printf("zero\n"); }
272290
273291 var i = i32(0);
274292 while (i != 3) {
275 %%stdout.printf("loop\n");
293 %%io.stdout.printf("loop\n");
276294 i += 1;
277295 }
278296}
279297 )SOURCE", "zero\nloop\nloop\nloop\n");
280298
281299 add_simple_case("arrays", R"SOURCE(
282import "std.zig";
300const io = @import("std").io;
283301
284302pub fn main(args: [][]u8) -> %void {
285303 var array : [5]i32 = undefined;
......@@ -299,11 +317,11 @@ pub fn main(args: [][]u8) -> %void {
299317 }
300318
301319 if (accumulator == 15) {
302 %%stdout.printf("OK\n");
320 %%io.stdout.printf("OK\n");
303321 }
304322
305323 if (get_array_len(array) != 5) {
306 %%stdout.printf("BAD\n");
324 %%io.stdout.printf("BAD\n");
307325 }
308326}
309327fn get_array_len(a: []i32) -> isize {
......@@ -313,144 +331,139 @@ fn get_array_len(a: []i32) -> isize {
313331
314332
315333 add_simple_case("hello world without libc", R"SOURCE(
316import "std.zig";
334const io = @import("std").io;
317335
318336pub fn main(args: [][]u8) -> %void {
319 %%stdout.printf("Hello, world!\n");
337 %%io.stdout.printf("Hello, world!\n");
320338}
321339 )SOURCE", "Hello, world!\n");
322340
323341
324342 add_simple_case("short circuit", R"SOURCE(
325import "std.zig";
343const io = @import("std").io;
326344
327345pub fn main(args: [][]u8) -> %void {
328 if (true || { %%stdout.printf("BAD 1\n"); false }) {
329 %%stdout.printf("OK 1\n");
346 if (true || { %%io.stdout.printf("BAD 1\n"); false }) {
347 %%io.stdout.printf("OK 1\n");
330348 }
331 if (false || { %%stdout.printf("OK 2\n"); false }) {
332 %%stdout.printf("BAD 2\n");
349 if (false || { %%io.stdout.printf("OK 2\n"); false }) {
350 %%io.stdout.printf("BAD 2\n");
333351 }
334352
335 if (true && { %%stdout.printf("OK 3\n"); false }) {
336 %%stdout.printf("BAD 3\n");
353 if (true && { %%io.stdout.printf("OK 3\n"); false }) {
354 %%io.stdout.printf("BAD 3\n");
337355 }
338 if (false && { %%stdout.printf("BAD 4\n"); false }) {
356 if (false && { %%io.stdout.printf("BAD 4\n"); false }) {
339357 } else {
340 %%stdout.printf("OK 4\n");
358 %%io.stdout.printf("OK 4\n");
341359 }
342360}
343361 )SOURCE", "OK 1\nOK 2\nOK 3\nOK 4\n");
344362
345363 add_simple_case("modify operators", R"SOURCE(
346import "std.zig";
364const io = @import("std").io;
347365
348366pub fn main(args: [][]u8) -> %void {
349367 var i : i32 = 0;
350 i += 5; if (i != 5) { %%stdout.printf("BAD +=\n"); }
351 i -= 2; if (i != 3) { %%stdout.printf("BAD -=\n"); }
352 i *= 20; if (i != 60) { %%stdout.printf("BAD *=\n"); }
353 i /= 3; if (i != 20) { %%stdout.printf("BAD /=\n"); }
354 i %= 11; if (i != 9) { %%stdout.printf("BAD %=\n"); }
355 i <<= 1; if (i != 18) { %%stdout.printf("BAD <<=\n"); }
356 i >>= 2; if (i != 4) { %%stdout.printf("BAD >>=\n"); }
368 i += 5; if (i != 5) { %%io.stdout.printf("BAD +=\n"); }
369 i -= 2; if (i != 3) { %%io.stdout.printf("BAD -=\n"); }
370 i *= 20; if (i != 60) { %%io.stdout.printf("BAD *=\n"); }
371 i /= 3; if (i != 20) { %%io.stdout.printf("BAD /=\n"); }
372 i %= 11; if (i != 9) { %%io.stdout.printf("BAD %=\n"); }
373 i <<= 1; if (i != 18) { %%io.stdout.printf("BAD <<=\n"); }
374 i >>= 2; if (i != 4) { %%io.stdout.printf("BAD >>=\n"); }
357375 i = 6;
358 i &= 5; if (i != 4) { %%stdout.printf("BAD &=\n"); }
359 i ^= 6; if (i != 2) { %%stdout.printf("BAD ^=\n"); }
376 i &= 5; if (i != 4) { %%io.stdout.printf("BAD &=\n"); }
377 i ^= 6; if (i != 2) { %%io.stdout.printf("BAD ^=\n"); }
360378 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");
364382}
365383 )SOURCE", "OK\n");
366384
367 add_simple_case("number literals", R"SOURCE(
368#link("c")
369export executable "test";
370
371c_import {
372 @c_include("stdio.h");
373}
385 add_simple_case_libc("number literals", R"SOURCE(
386const c = @c_import(@c_include("stdio.h"));
374387
375388export 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",
379392 u64(0));
380 printf(c"320402575052271: %llu\n",
393 c.printf(c"320402575052271: %llu\n",
381394 u64(320402575052271));
382 printf(c"0x01236789abcdef: %llu\n",
395 c.printf(c"0x01236789abcdef: %llu\n",
383396 u64(0x01236789abcdef));
384 printf(c"0xffffffffffffffff: %llu\n",
397 c.printf(c"0xffffffffffffffff: %llu\n",
385398 u64(0xffffffffffffffff));
386 printf(c"0x000000ffffffffffffffff: %llu\n",
399 c.printf(c"0x000000ffffffffffffffff: %llu\n",
387400 u64(0x000000ffffffffffffffff));
388 printf(c"0o1777777777777777777777: %llu\n",
401 c.printf(c"0o1777777777777777777777: %llu\n",
389402 u64(0o1777777777777777777777));
390 printf(c"0o0000001777777777777777777777: %llu\n",
403 c.printf(c"0o0000001777777777777777777777: %llu\n",
391404 u64(0o0000001777777777777777777777));
392 printf(c"0b1111111111111111111111111111111111111111111111111111111111111111: %llu\n",
405 c.printf(c"0b1111111111111111111111111111111111111111111111111111111111111111: %llu\n",
393406 u64(0b1111111111111111111111111111111111111111111111111111111111111111));
394 printf(c"0b0000001111111111111111111111111111111111111111111111111111111111111111: %llu\n",
407 c.printf(c"0b0000001111111111111111111111111111111111111111111111111111111111111111: %llu\n",
395408 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",
400413 f64(0.0));
401 printf(c"0e0: %a\n",
414 c.printf(c"0e0: %a\n",
402415 f64(0e0));
403 printf(c"0.0e0: %a\n",
416 c.printf(c"0.0e0: %a\n",
404417 f64(0.0e0));
405 printf(c"000000000000000000000000000000000000000000000000000000000.0e0: %a\n",
418 c.printf(c"000000000000000000000000000000000000000000000000000000000.0e0: %a\n",
406419 f64(000000000000000000000000000000000000000000000000000000000.0e0));
407 printf(c"0.000000000000000000000000000000000000000000000000000000000e0: %a\n",
420 c.printf(c"0.000000000000000000000000000000000000000000000000000000000e0: %a\n",
408421 f64(0.000000000000000000000000000000000000000000000000000000000e0));
409 printf(c"0.0e000000000000000000000000000000000000000000000000000000000: %a\n",
422 c.printf(c"0.0e000000000000000000000000000000000000000000000000000000000: %a\n",
410423 f64(0.0e000000000000000000000000000000000000000000000000000000000));
411 printf(c"1.0: %a\n",
424 c.printf(c"1.0: %a\n",
412425 f64(1.0));
413 printf(c"10.0: %a\n",
426 c.printf(c"10.0: %a\n",
414427 f64(10.0));
415 printf(c"10.5: %a\n",
428 c.printf(c"10.5: %a\n",
416429 f64(10.5));
417 printf(c"10.5e5: %a\n",
430 c.printf(c"10.5e5: %a\n",
418431 f64(10.5e5));
419 printf(c"10.5e+5: %a\n",
432 c.printf(c"10.5e+5: %a\n",
420433 f64(10.5e+5));
421 printf(c"50.0e-2: %a\n",
434 c.printf(c"50.0e-2: %a\n",
422435 f64(50.0e-2));
423 printf(c"50e-2: %a\n",
436 c.printf(c"50e-2: %a\n",
424437 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",
429442 f64(0x1.0));
430 printf(c"0x10.0: %a\n",
443 c.printf(c"0x10.0: %a\n",
431444 f64(0x10.0));
432 printf(c"0x100.0: %a\n",
445 c.printf(c"0x100.0: %a\n",
433446 f64(0x100.0));
434 printf(c"0x103.0: %a\n",
447 c.printf(c"0x103.0: %a\n",
435448 f64(0x103.0));
436 printf(c"0x103.7: %a\n",
449 c.printf(c"0x103.7: %a\n",
437450 f64(0x103.7));
438 printf(c"0x103.70: %a\n",
451 c.printf(c"0x103.70: %a\n",
439452 f64(0x103.70));
440 printf(c"0x103.70p4: %a\n",
453 c.printf(c"0x103.70p4: %a\n",
441454 f64(0x103.70p4));
442 printf(c"0x103.70p5: %a\n",
455 c.printf(c"0x103.70p5: %a\n",
443456 f64(0x103.70p5));
444 printf(c"0x103.70p+5: %a\n",
457 c.printf(c"0x103.70p+5: %a\n",
445458 f64(0x103.70p+5));
446 printf(c"0x103.70p-5: %a\n",
459 c.printf(c"0x103.70p-5: %a\n",
447460 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",
452465 f64(0b10100.00010e0));
453 printf(c"0o10700.00010e0: %a\n",
466 c.printf(c"0o10700.00010e0: %a\n",
454467 f64(0o10700.00010e0));
455468
456469 return 0;
......@@ -496,7 +509,7 @@ export fn main(argc: c_int, argv: &&u8) -> c_int {
496509)OUTPUT");
497510
498511 add_simple_case("structs", R"SOURCE(
499import "std.zig";
512const io = @import("std").io;
500513
501514pub fn main(args: [][]u8) -> %void {
502515 var foo : Foo = undefined;
......@@ -506,12 +519,12 @@ pub fn main(args: [][]u8) -> %void {
506519 test_foo(foo);
507520 test_mutation(&foo);
508521 if (foo.c != 100) {
509 %%stdout.printf("BAD\n");
522 %%io.stdout.printf("BAD\n");
510523 }
511524 test_point_to_self();
512525 test_byval_assign();
513526 test_initializer();
514 %%stdout.printf("OK\n");
527 %%io.stdout.printf("OK\n");
515528}
516529struct Foo {
517530 a : i32,
......@@ -520,7 +533,7 @@ struct Foo {
520533}
521534fn test_foo(foo : Foo) {
522535 if (!foo.b) {
523 %%stdout.printf("BAD\n");
536 %%io.stdout.printf("BAD\n");
524537 }
525538}
526539fn test_mutation(foo : &Foo) {
......@@ -545,7 +558,7 @@ fn test_point_to_self() {
545558 root.next = &node;
546559
547560 if (node.next.next.next.val.x != 1) {
548 %%stdout.printf("BAD\n");
561 %%io.stdout.printf("BAD\n");
549562 }
550563}
551564fn test_byval_assign() {
......@@ -554,38 +567,38 @@ fn test_byval_assign() {
554567
555568 foo1.a = 1234;
556569
557 if (foo2.a != 0) { %%stdout.printf("BAD\n"); }
570 if (foo2.a != 0) { %%io.stdout.printf("BAD\n"); }
558571
559572 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"); }
562575}
563576fn test_initializer() {
564577 const val = Val { .x = 42 };
565 if (val.x != 42) { %%stdout.printf("BAD\n"); }
578 if (val.x != 42) { %%io.stdout.printf("BAD\n"); }
566579}
567580 )SOURCE", "OK\n");
568581
569582 add_simple_case("global variables", R"SOURCE(
570import "std.zig";
583const io = @import("std").io;
571584
572585const g1 : i32 = 1233 + 1;
573586var g2 : i32 = 0;
574587
575588pub fn main(args: [][]u8) -> %void {
576 if (g2 != 0) { %%stdout.printf("BAD\n"); }
589 if (g2 != 0) { %%io.stdout.printf("BAD\n"); }
577590 g2 = g1;
578 if (g2 != 1234) { %%stdout.printf("BAD\n"); }
579 %%stdout.printf("OK\n");
591 if (g2 != 1234) { %%io.stdout.printf("BAD\n"); }
592 %%io.stdout.printf("OK\n");
580593}
581594 )SOURCE", "OK\n");
582595
583596 add_simple_case("while loop", R"SOURCE(
584import "std.zig";
597const io = @import("std").io;
585598pub fn main(args: [][]u8) -> %void {
586599 var i : i32 = 0;
587600 while (i < 4) {
588 %%stdout.printf("loop\n");
601 %%io.stdout.printf("loop\n");
589602 i += 1;
590603 }
591604 g();
......@@ -601,11 +614,11 @@ fn f() -> i32 {
601614 )SOURCE", "loop\nloop\nloop\nloop\n");
602615
603616 add_simple_case("continue and break", R"SOURCE(
604import "std.zig";
617const io = @import("std").io;
605618pub fn main(args: [][]u8) -> %void {
606619 var i : i32 = 0;
607620 while (true) {
608 %%stdout.printf("loop\n");
621 %%io.stdout.printf("loop\n");
609622 i += 1;
610623 if (i < 4) {
611624 continue;
......@@ -616,11 +629,11 @@ pub fn main(args: [][]u8) -> %void {
616629 )SOURCE", "loop\nloop\nloop\nloop\n");
617630
618631 add_simple_case("implicit cast after unreachable", R"SOURCE(
619import "std.zig";
632const io = @import("std").io;
620633pub fn main(args: [][]u8) -> %void {
621634 const x = outer();
622635 if (x == 1234) {
623 %%stdout.printf("OK\n");
636 %%io.stdout.printf("OK\n");
624637 }
625638}
626639fn inner() -> i32 { 1234 }
......@@ -630,18 +643,18 @@ fn outer() -> isize {
630643 )SOURCE", "OK\n");
631644
632645 add_simple_case("@sizeof() and @typeof()", R"SOURCE(
633import "std.zig";
646const io = @import("std").io;
634647const x: u16 = 13;
635648const z: @typeof(x) = 19;
636649pub fn main(args: [][]u8) -> %void {
637650 const y: @typeof(x) = 120;
638 %%stdout.print_u64(@sizeof(@typeof(y)));
639 %%stdout.printf("\n");
651 %%io.stdout.print_u64(@sizeof(@typeof(y)));
652 %%io.stdout.printf("\n");
640653}
641654 )SOURCE", "2\n");
642655
643656 add_simple_case("member functions", R"SOURCE(
644import "std.zig";
657const io = @import("std").io;
645658struct Rand {
646659 seed: u32,
647660 pub fn get_seed(r: Rand) -> u32 {
......@@ -651,14 +664,14 @@ struct Rand {
651664pub fn main(args: [][]u8) -> %void {
652665 const r = Rand {.seed = 1234};
653666 if (r.get_seed() != 1234) {
654 %%stdout.printf("BAD seed\n");
667 %%io.stdout.printf("BAD seed\n");
655668 }
656 %%stdout.printf("OK\n");
669 %%io.stdout.printf("OK\n");
657670}
658671 )SOURCE", "OK\n");
659672
660673 add_simple_case("pointer dereferencing", R"SOURCE(
661import "std.zig";
674const io = @import("std").io;
662675
663676pub fn main(args: [][]u8) -> %void {
664677 var x = i32(3);
......@@ -667,93 +680,93 @@ pub fn main(args: [][]u8) -> %void {
667680 *y += 1;
668681
669682 if (x != 4) {
670 %%stdout.printf("BAD\n");
683 %%io.stdout.printf("BAD\n");
671684 }
672685 if (*y != 4) {
673 %%stdout.printf("BAD\n");
686 %%io.stdout.printf("BAD\n");
674687 }
675 %%stdout.printf("OK\n");
688 %%io.stdout.printf("OK\n");
676689}
677690 )SOURCE", "OK\n");
678691
679692 add_simple_case("constant expressions", R"SOURCE(
680import "std.zig";
693const io = @import("std").io;
681694
682695const ARRAY_SIZE : i8 = 20;
683696
684697pub fn main(args: [][]u8) -> %void {
685698 var array : [ARRAY_SIZE]u8 = undefined;
686 %%stdout.print_u64(@sizeof(@typeof(array)));
687 %%stdout.printf("\n");
699 %%io.stdout.print_u64(@sizeof(@typeof(array)));
700 %%io.stdout.printf("\n");
688701}
689702 )SOURCE", "20\n");
690703
691704 add_simple_case("@min_value() and @max_value()", R"SOURCE(
692import "std.zig";
705const io = @import("std").io;
693706pub fn main(args: [][]u8) -> %void {
694 %%stdout.printf("max u8: ");
695 %%stdout.print_u64(@max_value(u8));
696 %%stdout.printf("\n");
707 %%io.stdout.printf("max u8: ");
708 %%io.stdout.print_u64(@max_value(u8));
709 %%io.stdout.printf("\n");
697710
698 %%stdout.printf("max u16: ");
699 %%stdout.print_u64(@max_value(u16));
700 %%stdout.printf("\n");
711 %%io.stdout.printf("max u16: ");
712 %%io.stdout.print_u64(@max_value(u16));
713 %%io.stdout.printf("\n");
701714
702 %%stdout.printf("max u32: ");
703 %%stdout.print_u64(@max_value(u32));
704 %%stdout.printf("\n");
715 %%io.stdout.printf("max u32: ");
716 %%io.stdout.print_u64(@max_value(u32));
717 %%io.stdout.printf("\n");
705718
706 %%stdout.printf("max u64: ");
707 %%stdout.print_u64(@max_value(u64));
708 %%stdout.printf("\n");
719 %%io.stdout.printf("max u64: ");
720 %%io.stdout.print_u64(@max_value(u64));
721 %%io.stdout.printf("\n");
709722
710 %%stdout.printf("max i8: ");
711 %%stdout.print_i64(@max_value(i8));
712 %%stdout.printf("\n");
723 %%io.stdout.printf("max i8: ");
724 %%io.stdout.print_i64(@max_value(i8));
725 %%io.stdout.printf("\n");
713726
714 %%stdout.printf("max i16: ");
715 %%stdout.print_i64(@max_value(i16));
716 %%stdout.printf("\n");
727 %%io.stdout.printf("max i16: ");
728 %%io.stdout.print_i64(@max_value(i16));
729 %%io.stdout.printf("\n");
717730
718 %%stdout.printf("max i32: ");
719 %%stdout.print_i64(@max_value(i32));
720 %%stdout.printf("\n");
731 %%io.stdout.printf("max i32: ");
732 %%io.stdout.print_i64(@max_value(i32));
733 %%io.stdout.printf("\n");
721734
722 %%stdout.printf("max i64: ");
723 %%stdout.print_i64(@max_value(i64));
724 %%stdout.printf("\n");
735 %%io.stdout.printf("max i64: ");
736 %%io.stdout.print_i64(@max_value(i64));
737 %%io.stdout.printf("\n");
725738
726 %%stdout.printf("min u8: ");
727 %%stdout.print_u64(@min_value(u8));
728 %%stdout.printf("\n");
739 %%io.stdout.printf("min u8: ");
740 %%io.stdout.print_u64(@min_value(u8));
741 %%io.stdout.printf("\n");
729742
730 %%stdout.printf("min u16: ");
731 %%stdout.print_u64(@min_value(u16));
732 %%stdout.printf("\n");
743 %%io.stdout.printf("min u16: ");
744 %%io.stdout.print_u64(@min_value(u16));
745 %%io.stdout.printf("\n");
733746
734 %%stdout.printf("min u32: ");
735 %%stdout.print_u64(@min_value(u32));
736 %%stdout.printf("\n");
747 %%io.stdout.printf("min u32: ");
748 %%io.stdout.print_u64(@min_value(u32));
749 %%io.stdout.printf("\n");
737750
738 %%stdout.printf("min u64: ");
739 %%stdout.print_u64(@min_value(u64));
740 %%stdout.printf("\n");
751 %%io.stdout.printf("min u64: ");
752 %%io.stdout.print_u64(@min_value(u64));
753 %%io.stdout.printf("\n");
741754
742 %%stdout.printf("min i8: ");
743 %%stdout.print_i64(@min_value(i8));
744 %%stdout.printf("\n");
755 %%io.stdout.printf("min i8: ");
756 %%io.stdout.print_i64(@min_value(i8));
757 %%io.stdout.printf("\n");
745758
746 %%stdout.printf("min i16: ");
747 %%stdout.print_i64(@min_value(i16));
748 %%stdout.printf("\n");
759 %%io.stdout.printf("min i16: ");
760 %%io.stdout.print_i64(@min_value(i16));
761 %%io.stdout.printf("\n");
749762
750 %%stdout.printf("min i32: ");
751 %%stdout.print_i64(@min_value(i32));
752 %%stdout.printf("\n");
763 %%io.stdout.printf("min i32: ");
764 %%io.stdout.print_i64(@min_value(i32));
765 %%io.stdout.printf("\n");
753766
754 %%stdout.printf("min i64: ");
755 %%stdout.print_i64(@min_value(i64));
756 %%stdout.printf("\n");
767 %%io.stdout.printf("min i64: ");
768 %%io.stdout.print_i64(@min_value(i64));
769 %%io.stdout.printf("\n");
757770}
758771 )SOURCE",
759772 "max u8: 255\n"
......@@ -775,10 +788,10 @@ pub fn main(args: [][]u8) -> %void {
775788
776789
777790 add_simple_case("else if expression", R"SOURCE(
778import "std.zig";
791const io = @import("std").io;
779792pub fn main(args: [][]u8) -> %void {
780793 if (f(1) == 1) {
781 %%stdout.printf("OK\n");
794 %%io.stdout.printf("OK\n");
782795 }
783796}
784797fn f(c: u8) -> u8 {
......@@ -793,82 +806,82 @@ fn f(c: u8) -> u8 {
793806 )SOURCE", "OK\n");
794807
795808 add_simple_case("overflow intrinsics", R"SOURCE(
796import "std.zig";
809const io = @import("std").io;
797810pub fn main(args: [][]u8) -> %void {
798811 var result: u8 = undefined;
799812 if (!@add_with_overflow(u8, 250, 100, &result)) {
800 %%stdout.printf("BAD\n");
813 %%io.stdout.printf("BAD\n");
801814 }
802815 if (@add_with_overflow(u8, 100, 150, &result)) {
803 %%stdout.printf("BAD\n");
816 %%io.stdout.printf("BAD\n");
804817 }
805818 if (result != 250) {
806 %%stdout.printf("BAD\n");
819 %%io.stdout.printf("BAD\n");
807820 }
808 %%stdout.printf("OK\n");
821 %%io.stdout.printf("OK\n");
809822}
810823 )SOURCE", "OK\n");
811824
812825 add_simple_case("order-independent declarations", R"SOURCE(
813import "std.zig";
814const z = stdin_fileno;
826const io = @import("std").io;
827const z = io.stdin_fileno;
815828const x : @typeof(y) = 1234;
816829const y : u16 = 5678;
817830pub fn main(args: [][]u8) -> %void {
818 var x : i32 = print_ok(x);
831 var x_local : i32 = print_ok(x);
819832}
820833fn print_ok(val: @typeof(x)) -> @typeof(foo) {
821 %%stdout.printf("OK\n");
834 %%io.stdout.printf("OK\n");
822835 return 0;
823836}
824837const foo : i32 = 0;
825838 )SOURCE", "OK\n");
826839
827840 add_simple_case("nested arrays", R"SOURCE(
828import "std.zig";
841const io = @import("std").io;
829842
830843pub fn main(args: [][]u8) -> %void {
831844 const array_of_strings = [][]u8 {"hello", "this", "is", "my", "thing"};
832845 for (array_of_strings) |str| {
833 %%stdout.printf(str);
834 %%stdout.printf("\n");
846 %%io.stdout.printf(str);
847 %%io.stdout.printf("\n");
835848 }
836849}
837850 )SOURCE", "hello\nthis\nis\nmy\nthing\n");
838851
839852 add_simple_case("for loops", R"SOURCE(
840import "std.zig";
853const io = @import("std").io;
841854
842855pub fn main(args: [][]u8) -> %void {
843856 const array = []u8 {9, 8, 7, 6};
844857 for (array) |item| {
845 %%stdout.print_u64(item);
846 %%stdout.printf("\n");
858 %%io.stdout.print_u64(item);
859 %%io.stdout.printf("\n");
847860 }
848861 for (array) |item, index| {
849 %%stdout.print_i64(index);
850 %%stdout.printf("\n");
862 %%io.stdout.print_i64(index);
863 %%io.stdout.printf("\n");
851864 }
852865 const unknown_size: []u8 = array;
853866 for (unknown_size) |item| {
854 %%stdout.print_u64(item);
855 %%stdout.printf("\n");
867 %%io.stdout.print_u64(item);
868 %%io.stdout.printf("\n");
856869 }
857870 for (unknown_size) |item, index| {
858 %%stdout.print_i64(index);
859 %%stdout.printf("\n");
871 %%io.stdout.print_i64(index);
872 %%io.stdout.printf("\n");
860873 }
861874}
862875 )SOURCE", "9\n8\n7\n6\n0\n1\n2\n3\n9\n8\n7\n6\n0\n1\n2\n3\n");
863876
864877 add_simple_case("function pointers", R"SOURCE(
865import "std.zig";
878const io = @import("std").io;
866879
867880pub fn main(args: [][]u8) -> %void {
868881 const fns = []@typeof(fn1) { fn1, fn2, fn3, fn4, };
869882 for (fns) |f| {
870 %%stdout.print_u64(f());
871 %%stdout.printf("\n");
883 %%io.stdout.print_u64(f());
884 %%io.stdout.printf("\n");
872885 }
873886}
874887
......@@ -879,7 +892,7 @@ fn fn4() -> u32 {8}
879892 )SOURCE", "5\n6\n7\n8\n");
880893
881894 add_simple_case("statically initialized struct", R"SOURCE(
882import "std.zig";
895const io = @import("std").io;
883896struct Foo {
884897 x: i32,
885898 y: bool,
......@@ -888,38 +901,38 @@ var foo = Foo { .x = 13, .y = true, };
888901pub fn main(args: [][]u8) -> %void {
889902 foo.x += 1;
890903 if (foo.x != 14) {
891 %%stdout.printf("BAD\n");
904 %%io.stdout.printf("BAD\n");
892905 }
893906
894 %%stdout.printf("OK\n");
907 %%io.stdout.printf("OK\n");
895908}
896909 )SOURCE", "OK\n");
897910
898911 add_simple_case("statically initialized array literal", R"SOURCE(
899import "std.zig";
912const io = @import("std").io;
900913const x = []u8{1,2,3,4};
901914pub fn main(args: [][]u8) -> %void {
902915 const y : [4]u8 = x;
903916 if (y[3] != 4) {
904 %%stdout.printf("BAD\n");
917 %%io.stdout.printf("BAD\n");
905918 }
906919
907 %%stdout.printf("OK\n");
920 %%io.stdout.printf("OK\n");
908921}
909922 )SOURCE", "OK\n");
910923
911924 add_simple_case("return with implicit cast from while loop", R"SOURCE(
912import "std.zig";
925const io = @import("std").io;
913926pub fn main(args: [][]u8) -> %void {
914927 while (true) {
915 %%stdout.printf("OK\n");
928 %%io.stdout.printf("OK\n");
916929 return;
917930 }
918931}
919932 )SOURCE", "OK\n");
920933
921934 add_simple_case("return struct byval from function", R"SOURCE(
922import "std.zig";
935const io = @import("std").io;
923936struct Foo {
924937 x: i32,
925938 y: i32,
......@@ -933,14 +946,14 @@ fn make_foo(x: i32, y: i32) -> Foo {
933946pub fn main(args: [][]u8) -> %void {
934947 const foo = make_foo(1234, 5678);
935948 if (foo.y != 5678) {
936 %%stdout.printf("BAD\n");
949 %%io.stdout.printf("BAD\n");
937950 }
938 %%stdout.printf("OK\n");
951 %%io.stdout.printf("OK\n");
939952}
940953 )SOURCE", "OK\n");
941954
942955 add_simple_case("%% binary operator", R"SOURCE(
943import "std.zig";
956const io = @import("std").io;
944957error ItBroke;
945958fn g(x: bool) -> %isize {
946959 if (x) {
......@@ -953,24 +966,24 @@ pub fn main(args: [][]u8) -> %void {
953966 const a = g(true) %% 3;
954967 const b = g(false) %% 3;
955968 if (a != 3) {
956 %%stdout.printf("BAD\n");
969 %%io.stdout.printf("BAD\n");
957970 }
958971 if (b != 10) {
959 %%stdout.printf("BAD\n");
972 %%io.stdout.printf("BAD\n");
960973 }
961 %%stdout.printf("OK\n");
974 %%io.stdout.printf("OK\n");
962975}
963976 )SOURCE", "OK\n");
964977
965978 add_simple_case("string concatenation", R"SOURCE(
966import "std.zig";
979const io = @import("std").io;
967980pub fn main(args: [][]u8) -> %void {
968 %%stdout.printf("OK" ++ " IT " ++ "WORKED\n");
981 %%io.stdout.printf("OK" ++ " IT " ++ "WORKED\n");
969982}
970983 )SOURCE", "OK IT WORKED\n");
971984
972985 add_simple_case("constant struct with negation", R"SOURCE(
973import "std.zig";
986const io = @import("std").io;
974987struct Vertex {
975988 x: f32,
976989 y: f32,
......@@ -985,30 +998,30 @@ const vertices = []Vertex {
985998};
986999pub fn main(args: [][]u8) -> %void {
9871000 if (vertices[0].x != -0.6) {
988 %%stdout.printf("BAD\n");
1001 %%io.stdout.printf("BAD\n");
9891002 }
990 %%stdout.printf("OK\n");
1003 %%io.stdout.printf("OK\n");
9911004}
9921005 )SOURCE", "OK\n");
9931006
9941007 add_simple_case("int to ptr cast", R"SOURCE(
995import "std.zig";
1008const io = @import("std").io;
9961009pub fn main(args: [][]u8) -> %void {
9971010 const x = isize(13);
9981011 const y = (&u8)(x);
9991012 const z = usize(y);
10001013 if (z != 13) {
1001 %%stdout.printf("BAD\n");
1014 %%io.stdout.printf("BAD\n");
10021015 }
1003 %%stdout.printf("OK\n");
1016 %%io.stdout.printf("OK\n");
10041017}
10051018 )SOURCE", "OK\n");
10061019
10071020 add_simple_case("pointer to void return type", R"SOURCE(
1008import "std.zig";
1021const io = @import("std").io;
10091022const x = void{};
10101023fn f() -> &void {
1011 %%stdout.printf("OK\n");
1024 %%io.stdout.printf("OK\n");
10121025 return &x;
10131026}
10141027pub fn main(args: [][]u8) -> %void {
......@@ -1018,7 +1031,7 @@ pub fn main(args: [][]u8) -> %void {
10181031 )SOURCE", "OK\n");
10191032
10201033 add_simple_case("unwrap simple value from error", R"SOURCE(
1021import "std.zig";
1034const io = @import("std").io;
10221035fn do() -> %isize {
10231036 13
10241037}
......@@ -1026,14 +1039,14 @@ fn do() -> %isize {
10261039pub fn main(args: [][]u8) -> %void {
10271040 const i = %%do();
10281041 if (i != 13) {
1029 %%stdout.printf("BAD\n");
1042 %%io.stdout.printf("BAD\n");
10301043 }
1031 %%stdout.printf("OK\n");
1044 %%io.stdout.printf("OK\n");
10321045}
10331046 )SOURCE", "OK\n");
10341047
10351048 add_simple_case("store member function in variable", R"SOURCE(
1036import "std.zig";
1049const io = @import("std").io;
10371050struct Foo {
10381051 x: i32,
10391052 fn member(foo: Foo) -> i32 { foo.x }
......@@ -1043,14 +1056,14 @@ pub fn main(args: [][]u8) -> %void {
10431056 const member_fn = Foo.member;
10441057 const result = member_fn(instance);
10451058 if (result != 1234) {
1046 %%stdout.printf("BAD\n");
1059 %%io.stdout.printf("BAD\n");
10471060 }
1048 %%stdout.printf("OK\n");
1061 %%io.stdout.printf("OK\n");
10491062}
10501063 )SOURCE", "OK\n");
10511064
10521065 add_simple_case("call member function directly", R"SOURCE(
1053import "std.zig";
1066const io = @import("std").io;
10541067struct Foo {
10551068 x: i32,
10561069 fn member(foo: Foo) -> i32 { foo.x }
......@@ -1059,18 +1072,18 @@ pub fn main(args: [][]u8) -> %void {
10591072 const instance = Foo { .x = 1234, };
10601073 const result = Foo.member(instance);
10611074 if (result != 1234) {
1062 %%stdout.printf("BAD\n");
1075 %%io.stdout.printf("BAD\n");
10631076 }
1064 %%stdout.printf("OK\n");
1077 %%io.stdout.printf("OK\n");
10651078}
10661079 )SOURCE", "OK\n");
10671080
10681081 add_simple_case("call result of if else expression", R"SOURCE(
1069import "std.zig";
1082const io = @import("std").io;
10701083fn a() -> []u8 { "a\n" }
10711084fn b() -> []u8 { "b\n" }
10721085fn f(x: bool) {
1073 %%stdout.printf((if (x) a else b)());
1086 %%io.stdout.printf((if (x) a else b)());
10741087}
10751088pub fn main(args: [][]u8) -> %void {
10761089 f(true);
......@@ -1079,15 +1092,10 @@ pub fn main(args: [][]u8) -> %void {
10791092 )SOURCE", "a\nb\n");
10801093
10811094
1082 add_simple_case("expose function pointer to C land", R"SOURCE(
1083#link("c")
1084export executable "test";
1085
1086c_import {
1087 @c_include("stdlib.h");
1088}
1095 add_simple_case_libc("expose function pointer to C land", R"SOURCE(
1096const c = @c_import(@c_include("stdlib.h"));
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 {
10911099 const a_int = (&i32)(a ?? unreachable{});
10921100 const b_int = (&i32)(b ?? unreachable{});
10931101 if (*a_int < *b_int) {
......@@ -1102,11 +1110,11 @@ export fn compare_fn(a: ?&const c_void, b: ?&const c_void) -> c_int {
11021110export fn main(args: c_int, argv: &&u8) -> c_int {
11031111 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
11071115 for (array) |item, i| {
11081116 if (item != i) {
1109 abort();
1117 c.abort();
11101118 }
11111119 }
11121120
......@@ -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(
1120#link("c")
1121export executable "test";
1122c_import {
1123 @c_include("stdio.h");
1124}
1127 add_simple_case_libc("casting between float and integer types", R"SOURCE(
1128const c = @c_import(@c_include("stdio.h"));
11251129export fn main(argc: c_int, argv: &&u8) -> c_int {
11261130 const small: f32 = 3.25;
11271131 const x: f64 = small;
11281132 const y = i32(x);
11291133 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));
11311135 return 0;
11321136}
11331137 )SOURCE", "3.25\n3\n3.00\n-0.40\n");
11341138
11351139
11361140 add_simple_case("const expression eval handling of variables", R"SOURCE(
1137import "std.zig";
1141const io = @import("std").io;
11381142pub fn main(args: [][]u8) -> %void {
11391143 var x = true;
11401144 while (x) {
11411145 x = false;
11421146 }
1143 %%stdout.printf("OK\n");
1147 %%io.stdout.printf("OK\n");
11441148}
11451149 )SOURCE", "OK\n");
11461150
11471151
11481152 add_simple_case("incomplete struct parameter top level decl", R"SOURCE(
1149import "std.zig";
1153const io = @import("std").io;
11501154struct A {
11511155 b: B,
11521156}
......@@ -1159,7 +1163,7 @@ struct C {
11591163 x: i32,
11601164
11611165 fn d(c: C) {
1162 %%stdout.printf("OK\n");
1166 %%io.stdout.printf("OK\n");
11631167 }
11641168}
11651169
......@@ -1182,7 +1186,7 @@ pub fn main(args: [][]u8) -> %void {
11821186
11831187
11841188 add_simple_case("same named methods in incomplete struct", R"SOURCE(
1185import "std.zig";
1189const io = @import("std").io;
11861190
11871191struct Foo {
11881192 field1: Bar,
......@@ -1200,53 +1204,53 @@ pub fn main(args: [][]u8) -> %void {
12001204 const bar = Bar {.field2 = 13,};
12011205 const foo = Foo {.field1 = bar,};
12021206 if (!foo.method()) {
1203 %%stdout.printf("BAD\n");
1207 %%io.stdout.printf("BAD\n");
12041208 }
12051209 if (!bar.method()) {
1206 %%stdout.printf("BAD\n");
1210 %%io.stdout.printf("BAD\n");
12071211 }
1208 %%stdout.printf("OK\n");
1212 %%io.stdout.printf("OK\n");
12091213}
12101214 )SOURCE", "OK\n");
12111215
12121216
12131217 add_simple_case("defer with only fallthrough", R"SOURCE(
1214import "std.zig";
1218const io = @import("std").io;
12151219pub fn main(args: [][]u8) -> %void {
1216 %%stdout.printf("before\n");
1217 defer %%stdout.printf("defer1\n");
1218 defer %%stdout.printf("defer2\n");
1219 defer %%stdout.printf("defer3\n");
1220 %%stdout.printf("after\n");
1220 %%io.stdout.printf("before\n");
1221 defer %%io.stdout.printf("defer1\n");
1222 defer %%io.stdout.printf("defer2\n");
1223 defer %%io.stdout.printf("defer3\n");
1224 %%io.stdout.printf("after\n");
12211225}
12221226 )SOURCE", "before\nafter\ndefer3\ndefer2\ndefer1\n");
12231227
12241228
12251229 add_simple_case("defer with return", R"SOURCE(
1226import "std.zig";
1230const io = @import("std").io;
12271231pub fn main(args: [][]u8) -> %void {
1228 %%stdout.printf("before\n");
1229 defer %%stdout.printf("defer1\n");
1230 defer %%stdout.printf("defer2\n");
1232 %%io.stdout.printf("before\n");
1233 defer %%io.stdout.printf("defer1\n");
1234 defer %%io.stdout.printf("defer2\n");
12311235 if (args.len == 1) return;
1232 defer %%stdout.printf("defer3\n");
1233 %%stdout.printf("after\n");
1236 defer %%io.stdout.printf("defer3\n");
1237 %%io.stdout.printf("after\n");
12341238}
12351239 )SOURCE", "before\ndefer2\ndefer1\n");
12361240
12371241
12381242 add_simple_case("%defer and it fails", R"SOURCE(
1239import "std.zig";
1243const io = @import("std").io;
12401244pub fn main(args: [][]u8) -> %void {
12411245 do_test() %% return;
12421246}
12431247fn do_test() -> %void {
1244 %%stdout.printf("before\n");
1245 defer %%stdout.printf("defer1\n");
1246 %defer %%stdout.printf("deferErr\n");
1248 %%io.stdout.printf("before\n");
1249 defer %%io.stdout.printf("defer1\n");
1250 %defer %%io.stdout.printf("deferErr\n");
12471251 %return its_gonna_fail();
1248 defer %%stdout.printf("defer3\n");
1249 %%stdout.printf("after\n");
1252 defer %%io.stdout.printf("defer3\n");
1253 %%io.stdout.printf("after\n");
12501254}
12511255error IToldYouItWouldFail;
12521256fn its_gonna_fail() -> %void {
......@@ -1256,17 +1260,17 @@ fn its_gonna_fail() -> %void {
12561260
12571261
12581262 add_simple_case("%defer and it passes", R"SOURCE(
1259import "std.zig";
1263const io = @import("std").io;
12601264pub fn main(args: [][]u8) -> %void {
12611265 do_test() %% return;
12621266}
12631267fn do_test() -> %void {
1264 %%stdout.printf("before\n");
1265 defer %%stdout.printf("defer1\n");
1266 %defer %%stdout.printf("deferErr\n");
1268 %%io.stdout.printf("before\n");
1269 defer %%io.stdout.printf("defer1\n");
1270 %defer %%io.stdout.printf("deferErr\n");
12671271 %return its_gonna_pass();
1268 defer %%stdout.printf("defer3\n");
1269 %%stdout.printf("after\n");
1272 defer %%io.stdout.printf("defer3\n");
1273 %%io.stdout.printf("after\n");
12701274}
12711275fn its_gonna_pass() -> %void { }
12721276 )SOURCE", "before\nafter\ndefer3\ndefer1\n");
......@@ -1327,14 +1331,9 @@ fn a() {
13271331fn b() {}
13281332 )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
13351334 add_compile_fail_case("bad import", R"SOURCE(
1336import "bogus-does-not-exist.zig";
1337 )SOURCE", 1, ".tmp_source.zig:2:1: error: unable to find 'bogus-does-not-exist.zig'");
1335const bogus = @import("bogus-does-not-exist.zig");
1336 )SOURCE", 1, ".tmp_source.zig:2:15: error: unable to find 'bogus-does-not-exist.zig'");
13381337
13391338 add_compile_fail_case("undeclared identifier", R"SOURCE(
13401339fn a() {
......@@ -1450,13 +1449,13 @@ fn f() {
14501449
14511450 add_compile_fail_case("direct struct loop", R"SOURCE(
14521451struct 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
14551454 add_compile_fail_case("indirect struct loop", R"SOURCE(
14561455struct A { b : B, }
14571456struct B { c : C, }
14581457struct 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
14611460 add_compile_fail_case("invalid struct field", R"SOURCE(
14621461struct A { x : i32, }
......@@ -1568,7 +1567,7 @@ fn f() -> @bogus(foo) {
15681567 add_compile_fail_case("top level decl dependency loop", R"SOURCE(
15691568const a : @typeof(b) = 0;
15701569const 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
15731572 add_compile_fail_case("noalias on non pointer param", R"SOURCE(
15741573fn f(noalias x: i32) {}
......@@ -1589,8 +1588,11 @@ struct Bar {}
15891588fn f(Foo: i32) {
15901589 var Bar : i32 = undefined;
15911590}
1592 )SOURCE", 2, ".tmp_source.zig:5:6: error: variable shadows type 'Foo'",
1593 ".tmp_source.zig:6:5: error: variable shadows type 'Bar'");
1591 )SOURCE", 4,
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
15951597 add_compile_fail_case("multiple else prongs in a switch", R"SOURCE(
15961598fn f(x: u32) {
......@@ -1614,14 +1616,9 @@ fn f(s: []u8) -> []u8 {
16141616 )SOURCE", 1, ".tmp_source.zig:3:5: error: string concatenation requires constant expression");
16151617
16161618 add_compile_fail_case("c_import with bogus include", R"SOURCE(
1617c_import {
1618 @c_include("bogus.h");
1619}
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");
1619const c = @c_import(@c_include("bogus.h"));
1620 )SOURCE", 2, ".tmp_source.zig:2:11: error: C import failed",
1621 ".h:1:10: note: 'bogus.h' file not found");
16251622
16261623 add_compile_fail_case("address of number literal", R"SOURCE(
16271624const x = 3;
test/self_hosted.zig+2-1
......@@ -1,4 +1,5 @@
1import "test_std.zig";
1// test std library
2const std = @import("std");
23
34#attribute("test")
45fn empty_function() {}
test/test_std.zig deleted-1
......@@ -1 +0,0 @@
1import "std.zig";