authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-09-28 02:33:32-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-09-28 02:33:32-04:00
logb581da41f82cd1e19701030bf47675b426608adf
treebbfebb52858935e2e91ffabd8b0c2b02fb58ca27
parente5fd8efcb60cd0223a7dd5e5825d3b9efc006c2a

remove compiler directives

* add `setFnTest`, `setFnVisible`, `setFnStaticEval`, `setFnNoInline` builtin functions to replace previous directive functionality * add `coldcc` and `nakedcc` as keywords which can be used as part of a function prototype. * `setDebugSafety` builtin can be used to set debug safety features at a per block scope level. * closes #169

40 files changed, 812 insertions(+), 528 deletions(-)

doc/langref.md+6-6
...@@ -3,9 +3,11 @@...@@ -3,9 +3,11 @@
3## Grammar3## Grammar
44
5```5```
6Root = many(TopLevelDecl) "EOF"6Root = many(TopLevelItem) "EOF"
77
8TopLevelDecl = many(Directive) option(VisibleMod) (FnDef | ExternDecl | ContainerDecl | GlobalVarDecl | ErrorValueDecl | TypeDecl | UseDecl)8TopLevelItem = ErrorValueDecl | Block | TopLevelDecl
9
10TopLevelDecl = option(VisibleMod) (FnDef | ExternDecl | ContainerDecl | GlobalVarDecl | TypeDecl | UseDecl)
911
10TypeDecl = "type" Symbol "=" TypeExpr ";"12TypeDecl = "type" Symbol "=" TypeExpr ";"
1113
...@@ -17,7 +19,7 @@ VariableDeclaration = ("var" | "const") Symbol option(":" TypeExpr) "=" Expressi...@@ -17,7 +19,7 @@ VariableDeclaration = ("var" | "const") Symbol option(":" TypeExpr) "=" Expressi
1719
18ContainerDecl = ("struct" | "enum" | "union") Symbol option(ParamDeclList) "{" many(StructMember) "}"20ContainerDecl = ("struct" | "enum" | "union") Symbol option(ParamDeclList) "{" many(StructMember) "}"
1921
20StructMember = many(Directive) option(VisibleMod) (StructField | FnDef | GlobalVarDecl | ContainerDecl)22StructMember = (StructField | FnDef | GlobalVarDecl | ContainerDecl)
2123
22StructField = Symbol option(":" Expression) ",")24StructField = Symbol option(":" Expression) ",")
2325
...@@ -25,9 +27,7 @@ UseDecl = "use" Expression ";"...@@ -25,9 +27,7 @@ UseDecl = "use" Expression ";"
2527
26ExternDecl = "extern" (FnProto | VariableDeclaration) ";"28ExternDecl = "extern" (FnProto | VariableDeclaration) ";"
2729
28FnProto = "fn" option(Symbol) ParamDeclList option("->" TypeExpr)30FnProto = option("coldcc" | "nakedcc") "fn" option(Symbol) ParamDeclList option("->" TypeExpr)
29
30Directive = "#" Symbol "(" Expression ")"
3131
32VisibleMod = "pub" | "export"32VisibleMod = "pub" | "export"
3333
doc/vim/syntax/zig.vim+1-1
...@@ -8,7 +8,7 @@ if exists("b:current_syntax")...@@ -8,7 +8,7 @@ if exists("b:current_syntax")
8endif8endif
9let b:current_syntax = "zig"9let b:current_syntax = "zig"
1010
11syn keyword zigStorage const var extern export pub noalias inline noinline11syn keyword zigStorage const var extern export pub noalias inline nakedcc coldcc
12syn keyword zigStructure struct enum union12syn keyword zigStructure struct enum union
13syn keyword zigStatement goto break return continue asm defer13syn keyword zigStatement goto break return continue asm defer
14syn keyword zigConditional if else switch14syn keyword zigConditional if else switch
src/all_types.hpp+13-9
...@@ -129,7 +129,6 @@ enum TldResolution {...@@ -129,7 +129,6 @@ enum TldResolution {
129struct TopLevelDecl {129struct TopLevelDecl {
130 // populated by parser130 // populated by parser
131 Buf *name;131 Buf *name;
132 ZigList<AstNode *> *directives;
133 VisibMod visib_mod;132 VisibMod visib_mod;
134133
135 // populated by semantic analyzer134 // populated by semantic analyzer
...@@ -153,7 +152,6 @@ enum NodeType {...@@ -153,7 +152,6 @@ enum NodeType {
153 NodeTypeFnDecl,152 NodeTypeFnDecl,
154 NodeTypeParamDecl,153 NodeTypeParamDecl,
155 NodeTypeBlock,154 NodeTypeBlock,
156 NodeTypeDirective,
157 NodeTypeReturnExpr,155 NodeTypeReturnExpr,
158 NodeTypeDefer,156 NodeTypeDefer,
159 NodeTypeVariableDeclaration,157 NodeTypeVariableDeclaration,
...@@ -210,6 +208,8 @@ struct AstNodeFnProto {...@@ -210,6 +208,8 @@ struct AstNodeFnProto {
210 bool is_var_args;208 bool is_var_args;
211 bool is_extern;209 bool is_extern;
212 bool is_inline;210 bool is_inline;
211 bool is_coldcc;
212 bool is_nakedcc;
213213
214 // populated by semantic analyzer:214 // populated by semantic analyzer:
215215
...@@ -459,11 +459,6 @@ struct AstNodeFieldAccessExpr {...@@ -459,11 +459,6 @@ struct AstNodeFieldAccessExpr {
459 AstNode *container_init_expr_node;459 AstNode *container_init_expr_node;
460};460};
461461
462struct AstNodeDirective {
463 Buf *name;
464 AstNode *expr;
465};
466
467enum PrefixOp {462enum PrefixOp {
468 PrefixOpInvalid,463 PrefixOpInvalid,
469 PrefixOpBoolNot,464 PrefixOpBoolNot,
...@@ -802,7 +797,6 @@ struct AstNode {...@@ -802,7 +797,6 @@ struct AstNode {
802 AstNodeErrorValueDecl error_value_decl;797 AstNodeErrorValueDecl error_value_decl;
803 AstNodeBinOpExpr bin_op_expr;798 AstNodeBinOpExpr bin_op_expr;
804 AstNodeUnwrapErrorExpr unwrap_err_expr;799 AstNodeUnwrapErrorExpr unwrap_err_expr;
805 AstNodeDirective directive;
806 AstNodePrefixOpExpr prefix_op_expr;800 AstNodePrefixOpExpr prefix_op_expr;
807 AstNodeFnCallExpr fn_call_expr;801 AstNodeFnCallExpr fn_call_expr;
808 AstNodeArrayAccessExpr array_access_expr;802 AstNodeArrayAccessExpr array_access_expr;
...@@ -1109,10 +1103,14 @@ struct FnTableEntry {...@@ -1109,10 +1103,14 @@ struct FnTableEntry {
1109 WantPure want_pure;1103 WantPure want_pure;
1110 AstNode *want_pure_attr_node;1104 AstNode *want_pure_attr_node;
1111 AstNode *want_pure_return_type;1105 AstNode *want_pure_return_type;
1112 bool safety_off;
1113 FnInline fn_inline;1106 FnInline fn_inline;
1114 FnAnalState anal_state;1107 FnAnalState anal_state;
11151108
1109 AstNode *fn_no_inline_set_node;
1110 AstNode *fn_export_set_node;
1111 AstNode *fn_test_set_node;
1112 AstNode *fn_static_eval_set_node;
1113
1116 ZigList<AstNode *> cast_alloca_list;1114 ZigList<AstNode *> cast_alloca_list;
1117 ZigList<StructValExprCodeGen *> struct_val_expr_alloca_list;1115 ZigList<StructValExprCodeGen *> struct_val_expr_alloca_list;
1118 ZigList<VariableTableEntry *> variable_list;1116 ZigList<VariableTableEntry *> variable_list;
...@@ -1154,6 +1152,11 @@ enum BuiltinFnId {...@@ -1154,6 +1152,11 @@ enum BuiltinFnId {
1154 BuiltinFnIdTruncate,1152 BuiltinFnIdTruncate,
1155 BuiltinFnIdIntType,1153 BuiltinFnIdIntType,
1156 BuiltinFnIdUnreachable,1154 BuiltinFnIdUnreachable,
1155 BuiltinFnIdSetFnTest,
1156 BuiltinFnIdSetFnVisible,
1157 BuiltinFnIdSetFnStaticEval,
1158 BuiltinFnIdSetFnNoInline,
1159 BuiltinFnIdSetDebugSafety,
1157};1160};
11581161
1159struct BuiltinFnEntry {1162struct BuiltinFnEntry {
...@@ -1373,6 +1376,7 @@ struct BlockContext {...@@ -1373,6 +1376,7 @@ struct BlockContext {
1373 bool codegen_excluded;1376 bool codegen_excluded;
13741377
1375 bool safety_off;1378 bool safety_off;
1379 AstNode *safety_set_node;
1376};1380};
13771381
1378enum AtomicOrder {1382enum AtomicOrder {
src/analyze.cpp+231-96
...@@ -75,7 +75,6 @@ static AstNode *first_executing_node(AstNode *node) {...@@ -75,7 +75,6 @@ static AstNode *first_executing_node(AstNode *node) {
75 case NodeTypeFnDecl:75 case NodeTypeFnDecl:
76 case NodeTypeParamDecl:76 case NodeTypeParamDecl:
77 case NodeTypeBlock:77 case NodeTypeBlock:
78 case NodeTypeDirective:
79 case NodeTypeReturnExpr:78 case NodeTypeReturnExpr:
80 case NodeTypeDefer:79 case NodeTypeDefer:
81 case NodeTypeVariableDeclaration:80 case NodeTypeVariableDeclaration:
...@@ -1123,6 +1122,28 @@ static bool resolve_const_expr_bool(CodeGen *g, ImportTableEntry *import, BlockC...@@ -1123,6 +1122,28 @@ static bool resolve_const_expr_bool(CodeGen *g, ImportTableEntry *import, BlockC
1123 return true;1122 return true;
1124}1123}
11251124
1125static FnTableEntry *resolve_const_expr_fn(CodeGen *g, ImportTableEntry *import, BlockContext *context,
1126 AstNode **node)
1127{
1128 TypeTableEntry *resolved_type = analyze_expression(g, import, context, nullptr, *node);
1129
1130 if (resolved_type->id == TypeTableEntryIdInvalid) {
1131 return nullptr;
1132 } else if (resolved_type->id == TypeTableEntryIdFn) {
1133 ConstExprValue *const_val = &get_resolved_expr(*node)->const_val;
1134
1135 if (!const_val->ok) {
1136 add_node_error(g, *node, buf_sprintf("unable to evaluate constant expression"));
1137 return nullptr;
1138 }
1139
1140 return const_val->data.x_fn;
1141 } else {
1142 add_node_error(g, *node, buf_sprintf("expected function, got '%s'", buf_ptr(&resolved_type->name)));
1143 return nullptr;
1144 }
1145}
1146
1126static void resolve_function_proto(CodeGen *g, AstNode *node, FnTableEntry *fn_table_entry,1147static void resolve_function_proto(CodeGen *g, AstNode *node, FnTableEntry *fn_table_entry,
1127 ImportTableEntry *import, BlockContext *containing_context)1148 ImportTableEntry *import, BlockContext *containing_context)
1128{1149{
...@@ -1133,85 +1154,6 @@ static void resolve_function_proto(CodeGen *g, AstNode *node, FnTableEntry *fn_t...@@ -1133,85 +1154,6 @@ static void resolve_function_proto(CodeGen *g, AstNode *node, FnTableEntry *fn_t
1133 return;1154 return;
1134 }1155 }
11351156
1136 bool is_cold = false;
1137 bool is_naked = false;
1138 bool is_test = false;
1139 bool is_noinline = false;
1140
1141 if (fn_proto->top_level_decl.directives) {
1142 for (size_t i = 0; i < fn_proto->top_level_decl.directives->length; i += 1) {
1143 AstNode *directive_node = fn_proto->top_level_decl.directives->at(i);
1144 Buf *name = directive_node->data.directive.name;
1145
1146 if (buf_eql_str(name, "attribute")) {
1147 if (fn_table_entry->fn_def_node) {
1148 Buf *attr_name = resolve_const_expr_str(g, import, import->block_context,
1149 &directive_node->data.directive.expr);
1150 if (attr_name) {
1151 if (buf_eql_str(attr_name, "naked")) {
1152 is_naked = true;
1153 } else if (buf_eql_str(attr_name, "noinline")) {
1154 is_noinline = true;
1155 } else if (buf_eql_str(attr_name, "cold")) {
1156 is_cold = true;
1157 } else if (buf_eql_str(attr_name, "test")) {
1158 is_test = true;
1159 g->test_fn_count += 1;
1160 } else {
1161 add_node_error(g, directive_node,
1162 buf_sprintf("invalid function attribute: '%s'", buf_ptr(name)));
1163 }
1164 }
1165 } else {
1166 add_node_error(g, directive_node,
1167 buf_sprintf("invalid function attribute: '%s'", buf_ptr(name)));
1168 }
1169 } else if (buf_eql_str(name, "debug_safety")) {
1170 if (!fn_table_entry->fn_def_node) {
1171 add_node_error(g, directive_node,
1172 buf_sprintf("#debug_safety valid only on function definitions"));
1173 } else {
1174 bool enable;
1175 bool ok = resolve_const_expr_bool(g, import, import->block_context,
1176 &directive_node->data.directive.expr, &enable);
1177 if (ok && !enable) {
1178 fn_table_entry->safety_off = true;
1179 }
1180 }
1181 } else if (buf_eql_str(name, "condition")) {
1182 if (fn_proto->top_level_decl.visib_mod == VisibModExport) {
1183 bool include;
1184 bool ok = resolve_const_expr_bool(g, import, import->block_context,
1185 &directive_node->data.directive.expr, &include);
1186 if (ok && !include) {
1187 fn_proto->top_level_decl.visib_mod = VisibModPub;
1188 }
1189 } else {
1190 add_node_error(g, directive_node,
1191 buf_sprintf("#condition valid only on exported symbols"));
1192 }
1193 } else if (buf_eql_str(name, "static_eval_enable")) {
1194 if (!fn_table_entry->fn_def_node) {
1195 add_node_error(g, directive_node,
1196 buf_sprintf("#static_val_enable valid only on function definitions"));
1197 } else {
1198 bool enable;
1199 bool ok = resolve_const_expr_bool(g, import, import->block_context,
1200 &directive_node->data.directive.expr, &enable);
1201 if (!ok || !enable) {
1202 fn_table_entry->want_pure = WantPureFalse;
1203 } else if (ok && enable) {
1204 fn_table_entry->want_pure = WantPureTrue;
1205 fn_table_entry->want_pure_attr_node = directive_node->data.directive.expr;
1206 }
1207 }
1208 } else {
1209 add_node_error(g, directive_node,
1210 buf_sprintf("invalid directive: '%s'", buf_ptr(name)));
1211 }
1212 }
1213 }
1214
1215 bool is_internal = (fn_proto->top_level_decl.visib_mod != VisibModExport);1157 bool is_internal = (fn_proto->top_level_decl.visib_mod != VisibModExport);
1216 bool is_c_compat = !is_internal || fn_proto->is_extern;1158 bool is_c_compat = !is_internal || fn_proto->is_extern;
1217 fn_table_entry->internal_linkage = !is_c_compat;1159 fn_table_entry->internal_linkage = !is_c_compat;
...@@ -1219,24 +1161,17 @@ static void resolve_function_proto(CodeGen *g, AstNode *node, FnTableEntry *fn_t...@@ -1219,24 +1161,17 @@ static void resolve_function_proto(CodeGen *g, AstNode *node, FnTableEntry *fn_t
12191161
12201162
1221 TypeTableEntry *fn_type = analyze_fn_proto_type(g, import, containing_context, nullptr, node,1163 TypeTableEntry *fn_type = analyze_fn_proto_type(g, import, containing_context, nullptr, node,
1222 is_naked, is_cold, fn_table_entry);1164 fn_proto->is_nakedcc, fn_proto->is_coldcc, fn_table_entry);
12231165
1224 fn_table_entry->type_entry = fn_type;1166 fn_table_entry->type_entry = fn_type;
1225 fn_table_entry->is_test = is_test;
12261167
1227 if (fn_type->id == TypeTableEntryIdInvalid) {1168 if (fn_type->id == TypeTableEntryIdInvalid) {
1228 fn_proto->skip = true;1169 fn_proto->skip = true;
1229 return;1170 return;
1230 }1171 }
12311172
1232 if (fn_proto->is_inline && is_noinline) {1173 if (fn_proto->is_inline) {
1233 add_node_error(g, node, buf_sprintf("function is both inline and noinline"));
1234 fn_proto->skip = true;
1235 return;
1236 } else if (fn_proto->is_inline) {
1237 fn_table_entry->fn_inline = FnInlineAlways;1174 fn_table_entry->fn_inline = FnInlineAlways;
1238 } else if (is_noinline) {
1239 fn_table_entry->fn_inline = FnInlineNever;
1240 }1175 }
12411176
12421177
...@@ -1881,7 +1816,6 @@ static void resolve_top_level_decl(CodeGen *g, AstNode *node, bool pointer_only)...@@ -1881,7 +1816,6 @@ static void resolve_top_level_decl(CodeGen *g, AstNode *node, bool pointer_only)
1881 zig_panic("TODO resolve_top_level_decl NodeTypeUse");1816 zig_panic("TODO resolve_top_level_decl NodeTypeUse");
1882 break;1817 break;
1883 case NodeTypeFnDef:1818 case NodeTypeFnDef:
1884 case NodeTypeDirective:
1885 case NodeTypeParamDecl:1819 case NodeTypeParamDecl:
1886 case NodeTypeFnDecl:1820 case NodeTypeFnDecl:
1887 case NodeTypeReturnExpr:1821 case NodeTypeReturnExpr:
...@@ -2406,13 +2340,11 @@ BlockContext *new_block_context(AstNode *node, BlockContext *parent) {...@@ -2406,13 +2340,11 @@ BlockContext *new_block_context(AstNode *node, BlockContext *parent) {
2406 context->parent_loop_node = parent->parent_loop_node;2340 context->parent_loop_node = parent->parent_loop_node;
2407 context->c_import_buf = parent->c_import_buf;2341 context->c_import_buf = parent->c_import_buf;
2408 context->codegen_excluded = parent->codegen_excluded;2342 context->codegen_excluded = parent->codegen_excluded;
2409 context->safety_off = parent->safety_off;
2410 }2343 }
24112344
2412 if (node && node->type == NodeTypeFnDef) {2345 if (node && node->type == NodeTypeFnDef) {
2413 AstNode *fn_proto_node = node->data.fn_def.fn_proto;2346 AstNode *fn_proto_node = node->data.fn_def.fn_proto;
2414 context->fn_entry = fn_proto_node->data.fn_proto.fn_table_entry;2347 context->fn_entry = fn_proto_node->data.fn_proto.fn_table_entry;
2415 context->safety_off = context->fn_entry->safety_off;
2416 } else if (parent) {2348 } else if (parent) {
2417 context->fn_entry = parent->fn_entry;2349 context->fn_entry = parent->fn_entry;
2418 }2350 }
...@@ -5246,6 +5178,203 @@ static TypeTableEntry *analyze_int_type(CodeGen *g, ImportTableEntry *import,...@@ -5246,6 +5178,203 @@ static TypeTableEntry *analyze_int_type(CodeGen *g, ImportTableEntry *import,
52465178
5247}5179}
52485180
5181static TypeTableEntry *analyze_set_fn_test(CodeGen *g, ImportTableEntry *import,
5182 BlockContext *context, AstNode *node)
5183{
5184 AstNode **fn_node = &node->data.fn_call_expr.params.at(0);
5185 AstNode **value_node = &node->data.fn_call_expr.params.at(1);
5186
5187 FnTableEntry *fn_entry = resolve_const_expr_fn(g, import, context, fn_node);
5188 if (!fn_entry) {
5189 return g->builtin_types.entry_invalid;
5190 }
5191
5192 bool ok = resolve_const_expr_bool(g, import, context, value_node, &fn_entry->is_test);
5193 if (!ok) {
5194 return g->builtin_types.entry_invalid;
5195 }
5196
5197 if (fn_entry->fn_test_set_node) {
5198 ErrorMsg *msg = add_node_error(g, node, buf_sprintf("function test attribute set twice"));
5199 add_error_note(g, msg, fn_entry->fn_test_set_node, buf_sprintf("first set here"));
5200 return g->builtin_types.entry_invalid;
5201 }
5202 fn_entry->fn_test_set_node = node;
5203
5204 g->test_fn_count += 1;
5205 return g->builtin_types.entry_void;
5206}
5207
5208static TypeTableEntry *analyze_set_fn_no_inline(CodeGen *g, ImportTableEntry *import,
5209 BlockContext *context, AstNode *node)
5210{
5211 AstNode **fn_node = &node->data.fn_call_expr.params.at(0);
5212 AstNode **value_node = &node->data.fn_call_expr.params.at(1);
5213
5214 FnTableEntry *fn_entry = resolve_const_expr_fn(g, import, context, fn_node);
5215 if (!fn_entry) {
5216 return g->builtin_types.entry_invalid;
5217 }
5218
5219 bool is_noinline;
5220 bool ok = resolve_const_expr_bool(g, import, context, value_node, &is_noinline);
5221 if (!ok) {
5222 return g->builtin_types.entry_invalid;
5223 }
5224
5225 if (fn_entry->fn_no_inline_set_node) {
5226 ErrorMsg *msg = add_node_error(g, node, buf_sprintf("function no inline attribute set twice"));
5227 add_error_note(g, msg, fn_entry->fn_no_inline_set_node, buf_sprintf("first set here"));
5228 return g->builtin_types.entry_invalid;
5229 }
5230 fn_entry->fn_no_inline_set_node = node;
5231
5232 if (fn_entry->fn_inline == FnInlineAlways) {
5233 add_node_error(g, node, buf_sprintf("function is both inline and noinline"));
5234 fn_entry->proto_node->data.fn_proto.skip = true;
5235 return g->builtin_types.entry_invalid;
5236 } else if (is_noinline) {
5237 fn_entry->fn_inline = FnInlineNever;
5238 }
5239
5240 return g->builtin_types.entry_void;
5241}
5242
5243static TypeTableEntry *analyze_set_fn_static_eval(CodeGen *g, ImportTableEntry *import,
5244 BlockContext *context, AstNode *node)
5245{
5246 AstNode **fn_node = &node->data.fn_call_expr.params.at(0);
5247 AstNode **value_node = &node->data.fn_call_expr.params.at(1);
5248
5249 FnTableEntry *fn_entry = resolve_const_expr_fn(g, import, context, fn_node);
5250 if (!fn_entry) {
5251 return g->builtin_types.entry_invalid;
5252 }
5253
5254 bool want_static_eval;
5255 bool ok = resolve_const_expr_bool(g, import, context, value_node, &want_static_eval);
5256 if (!ok) {
5257 return g->builtin_types.entry_invalid;
5258 }
5259
5260 if (fn_entry->fn_static_eval_set_node) {
5261 ErrorMsg *msg = add_node_error(g, node, buf_sprintf("function static eval attribute set twice"));
5262 add_error_note(g, msg, fn_entry->fn_static_eval_set_node, buf_sprintf("first set here"));
5263 return g->builtin_types.entry_invalid;
5264 }
5265 fn_entry->fn_static_eval_set_node = node;
5266
5267 if (want_static_eval && !context->fn_entry->is_pure) {
5268 add_node_error(g, node, buf_sprintf("attribute appears too late within function"));
5269 return g->builtin_types.entry_invalid;
5270 }
5271
5272 if (want_static_eval) {
5273 fn_entry->want_pure = WantPureTrue;
5274 fn_entry->want_pure_attr_node = node;
5275 } else {
5276 fn_entry->want_pure = WantPureFalse;
5277 fn_entry->is_pure = false;
5278 }
5279
5280 return g->builtin_types.entry_void;
5281}
5282
5283static TypeTableEntry *analyze_set_fn_visible(CodeGen *g, ImportTableEntry *import,
5284 BlockContext *context, AstNode *node)
5285{
5286 AstNode **fn_node = &node->data.fn_call_expr.params.at(0);
5287 AstNode **value_node = &node->data.fn_call_expr.params.at(1);
5288
5289 FnTableEntry *fn_entry = resolve_const_expr_fn(g, import, context, fn_node);
5290 if (!fn_entry) {
5291 return g->builtin_types.entry_invalid;
5292 }
5293
5294 bool want_export;
5295 bool ok = resolve_const_expr_bool(g, import, context, value_node, &want_export);
5296 if (!ok) {
5297 return g->builtin_types.entry_invalid;
5298 }
5299
5300 if (fn_entry->fn_export_set_node) {
5301 ErrorMsg *msg = add_node_error(g, node, buf_sprintf("function visibility set twice"));
5302 add_error_note(g, msg, fn_entry->fn_export_set_node, buf_sprintf("first set here"));
5303 return g->builtin_types.entry_invalid;
5304 }
5305 fn_entry->fn_export_set_node = node;
5306
5307 AstNodeFnProto *fn_proto = &fn_entry->proto_node->data.fn_proto;
5308 if (fn_proto->top_level_decl.visib_mod != VisibModExport) {
5309 ErrorMsg *msg = add_node_error(g, node,
5310 buf_sprintf("function must be marked export to set function visibility"));
5311 add_error_note(g, msg, fn_entry->proto_node, buf_sprintf("function declared here"));
5312 return g->builtin_types.entry_void;
5313 }
5314 if (!want_export) {
5315 fn_proto->top_level_decl.visib_mod = VisibModPub;
5316 }
5317
5318 return g->builtin_types.entry_void;
5319}
5320
5321static TypeTableEntry *analyze_set_debug_safety(CodeGen *g, ImportTableEntry *import,
5322 BlockContext *parent_context, AstNode *node)
5323{
5324 AstNode **target_node = &node->data.fn_call_expr.params.at(0);
5325 AstNode **value_node = &node->data.fn_call_expr.params.at(1);
5326
5327 TypeTableEntry *target_type = analyze_expression(g, import, parent_context, nullptr, *target_node);
5328 BlockContext *target_context;
5329 ConstExprValue *const_val = &get_resolved_expr(*target_node)->const_val;
5330 if (target_type->id == TypeTableEntryIdInvalid) {
5331 return g->builtin_types.entry_invalid;
5332 }
5333 if (!const_val->ok) {
5334 add_node_error(g, *target_node, buf_sprintf("unable to evaluate constant expression"));
5335 return g->builtin_types.entry_invalid;
5336 }
5337 if (target_type->id == TypeTableEntryIdBlock) {
5338 target_context = const_val->data.x_block;
5339 } else if (target_type->id == TypeTableEntryIdFn) {
5340 target_context = const_val->data.x_fn->fn_def_node->data.fn_def.block_context;
5341 } else if (target_type->id == TypeTableEntryIdMetaType) {
5342 TypeTableEntry *type_arg = const_val->data.x_type;
5343 if (type_arg->id == TypeTableEntryIdStruct) {
5344 target_context = type_arg->data.structure.block_context;
5345 } else if (type_arg->id == TypeTableEntryIdEnum) {
5346 target_context = type_arg->data.enumeration.block_context;
5347 } else if (type_arg->id == TypeTableEntryIdUnion) {
5348 target_context = type_arg->data.unionation.block_context;
5349 } else {
5350 add_node_error(g, *target_node,
5351 buf_sprintf("expected scope reference, got type '%s'", buf_ptr(&type_arg->name)));
5352 return g->builtin_types.entry_invalid;
5353 }
5354 } else {
5355 add_node_error(g, *target_node,
5356 buf_sprintf("expected scope reference, got type '%s'", buf_ptr(&target_type->name)));
5357 return g->builtin_types.entry_invalid;
5358 }
5359
5360 bool want_debug_safety;
5361 bool ok = resolve_const_expr_bool(g, import, parent_context, value_node, &want_debug_safety);
5362 if (!ok) {
5363 return g->builtin_types.entry_invalid;
5364 }
5365
5366 if (target_context->safety_set_node) {
5367 ErrorMsg *msg = add_node_error(g, node, buf_sprintf("debug safety for scope set twice"));
5368 add_error_note(g, msg, target_context->safety_set_node, buf_sprintf("first set here"));
5369 return g->builtin_types.entry_invalid;
5370 }
5371 target_context->safety_set_node = node;
5372
5373 target_context->safety_off = !want_debug_safety;
5374
5375 return g->builtin_types.entry_void;
5376}
5377
5249static TypeTableEntry *analyze_builtin_fn_call_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,5378static TypeTableEntry *analyze_builtin_fn_call_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
5250 TypeTableEntry *expected_type, AstNode *node)5379 TypeTableEntry *expected_type, AstNode *node)
5251{5380{
...@@ -5607,6 +5736,16 @@ static TypeTableEntry *analyze_builtin_fn_call_expr(CodeGen *g, ImportTableEntry...@@ -5607,6 +5736,16 @@ static TypeTableEntry *analyze_builtin_fn_call_expr(CodeGen *g, ImportTableEntry
5607 return analyze_int_type(g, import, context, node);5736 return analyze_int_type(g, import, context, node);
5608 case BuiltinFnIdUnreachable:5737 case BuiltinFnIdUnreachable:
5609 return g->builtin_types.entry_unreachable;5738 return g->builtin_types.entry_unreachable;
5739 case BuiltinFnIdSetFnTest:
5740 return analyze_set_fn_test(g, import, context, node);
5741 case BuiltinFnIdSetFnNoInline:
5742 return analyze_set_fn_no_inline(g, import, context, node);
5743 case BuiltinFnIdSetFnStaticEval:
5744 return analyze_set_fn_static_eval(g, import, context, node);
5745 case BuiltinFnIdSetFnVisible:
5746 return analyze_set_fn_visible(g, import, context, node);
5747 case BuiltinFnIdSetDebugSafety:
5748 return analyze_set_debug_safety(g, import, context, node);
5610 }5749 }
5611 zig_unreachable();5750 zig_unreachable();
5612}5751}
...@@ -6876,7 +7015,6 @@ static TypeTableEntry *analyze_expression_pointer_only(CodeGen *g, ImportTableEn...@@ -6876,7 +7015,6 @@ static TypeTableEntry *analyze_expression_pointer_only(CodeGen *g, ImportTableEn
6876 break;7015 break;
6877 case NodeTypeSwitchProng:7016 case NodeTypeSwitchProng:
6878 case NodeTypeSwitchRange:7017 case NodeTypeSwitchRange:
6879 case NodeTypeDirective:
6880 case NodeTypeFnDecl:7018 case NodeTypeFnDecl:
6881 case NodeTypeParamDecl:7019 case NodeTypeParamDecl:
6882 case NodeTypeRoot:7020 case NodeTypeRoot:
...@@ -7109,7 +7247,6 @@ static void scan_decls(CodeGen *g, ImportTableEntry *import, BlockContext *conte...@@ -7109,7 +7247,6 @@ static void scan_decls(CodeGen *g, ImportTableEntry *import, BlockContext *conte
7109 // error value declarations do not depend on other top level decls7247 // error value declarations do not depend on other top level decls
7110 preview_error_value_decl(g, node);7248 preview_error_value_decl(g, node);
7111 break;7249 break;
7112 case NodeTypeDirective:
7113 case NodeTypeParamDecl:7250 case NodeTypeParamDecl:
7114 case NodeTypeFnDecl:7251 case NodeTypeFnDecl:
7115 case NodeTypeReturnExpr:7252 case NodeTypeReturnExpr:
...@@ -7418,7 +7555,6 @@ Expr *get_resolved_expr(AstNode *node) {...@@ -7418,7 +7555,6 @@ Expr *get_resolved_expr(AstNode *node) {
7418 case NodeTypeFnDef:7555 case NodeTypeFnDef:
7419 case NodeTypeFnDecl:7556 case NodeTypeFnDecl:
7420 case NodeTypeParamDecl:7557 case NodeTypeParamDecl:
7421 case NodeTypeDirective:
7422 case NodeTypeUse:7558 case NodeTypeUse:
7423 case NodeTypeContainerDecl:7559 case NodeTypeContainerDecl:
7424 case NodeTypeStructField:7560 case NodeTypeStructField:
...@@ -7469,7 +7605,6 @@ static TopLevelDecl *get_as_top_level_decl(AstNode *node) {...@@ -7469,7 +7605,6 @@ static TopLevelDecl *get_as_top_level_decl(AstNode *node) {
7469 case NodeTypeFnDecl:7605 case NodeTypeFnDecl:
7470 case NodeTypeParamDecl:7606 case NodeTypeParamDecl:
7471 case NodeTypeBlock:7607 case NodeTypeBlock:
7472 case NodeTypeDirective:
7473 case NodeTypeStringLiteral:7608 case NodeTypeStringLiteral:
7474 case NodeTypeCharLiteral:7609 case NodeTypeCharLiteral:
7475 case NodeTypeSymbol:7610 case NodeTypeSymbol:
src/ast_render.cpp-14
...@@ -141,8 +141,6 @@ static const char *node_type_str(NodeType node_type) {...@@ -141,8 +141,6 @@ static const char *node_type_str(NodeType node_type) {
141 return "ArrayAccessExpr";141 return "ArrayAccessExpr";
142 case NodeTypeSliceExpr:142 case NodeTypeSliceExpr:
143 return "SliceExpr";143 return "SliceExpr";
144 case NodeTypeDirective:
145 return "Directive";
146 case NodeTypeReturnExpr:144 case NodeTypeReturnExpr:
147 return "ReturnExpr";145 return "ReturnExpr";
148 case NodeTypeDefer:146 case NodeTypeDefer:
...@@ -416,13 +414,6 @@ static void render_node(AstRender *ar, AstNode *node) {...@@ -416,13 +414,6 @@ static void render_node(AstRender *ar, AstNode *node) {
416 }414 }
417 case NodeTypeFnDef:415 case NodeTypeFnDef:
418 {416 {
419 ZigList<AstNode *> *directives =
420 node->data.fn_def.fn_proto->data.fn_proto.top_level_decl.directives;
421 if (directives) {
422 for (size_t i = 0; i < directives->length; i += 1) {
423 render_node(ar, directives->at(i));
424 }
425 }
426 render_node(ar, node->data.fn_def.fn_proto);417 render_node(ar, node->data.fn_def.fn_proto);
427 fprintf(ar->f, " ");418 fprintf(ar->f, " ");
428 render_node(ar, node->data.fn_def.body);419 render_node(ar, node->data.fn_def.body);
...@@ -445,11 +436,6 @@ static void render_node(AstRender *ar, AstNode *node) {...@@ -445,11 +436,6 @@ static void render_node(AstRender *ar, AstNode *node) {
445 print_indent(ar);436 print_indent(ar);
446 fprintf(ar->f, "}");437 fprintf(ar->f, "}");
447 break;438 break;
448 case NodeTypeDirective:
449 fprintf(ar->f, "#%s(", buf_ptr(node->data.directive.name));
450 render_node(ar, node->data.directive.expr);
451 fprintf(ar->f, ")\n");
452 break;
453 case NodeTypeReturnExpr:439 case NodeTypeReturnExpr:
454 {440 {
455 const char *return_str = return_string(node->data.return_expr.kind);441 const char *return_str = return_string(node->data.return_expr.kind);
src/codegen.cpp+25-2
...@@ -352,8 +352,20 @@ static LLVMValueRef get_handle_value(CodeGen *g, AstNode *source_node, LLVMValue...@@ -352,8 +352,20 @@ static LLVMValueRef get_handle_value(CodeGen *g, AstNode *source_node, LLVMValue
352 }352 }
353}353}
354354
355static bool want_debug_safety_recursive(CodeGen *g, BlockContext *context) {
356 if (context->safety_set_node || !context->parent) {
357 return !context->safety_off;
358 }
359 context->safety_off = want_debug_safety_recursive(g, context->parent);
360 context->safety_set_node = context->parent->safety_set_node;
361 return !context->safety_off;
362}
363
355static bool want_debug_safety(CodeGen *g, AstNode *node) {364static bool want_debug_safety(CodeGen *g, AstNode *node) {
356 return !g->is_release_build && !node->block_context->safety_off;365 if (g->is_release_build) {
366 return false;
367 }
368 return want_debug_safety_recursive(g, node->block_context);
357}369}
358370
359static void gen_debug_safety_crash(CodeGen *g) {371static void gen_debug_safety_crash(CodeGen *g) {
...@@ -709,6 +721,13 @@ static LLVMValueRef gen_builtin_fn_call_expr(CodeGen *g, AstNode *node) {...@@ -709,6 +721,13 @@ static LLVMValueRef gen_builtin_fn_call_expr(CodeGen *g, AstNode *node) {
709 return gen_truncate(g, node);721 return gen_truncate(g, node);
710 case BuiltinFnIdUnreachable:722 case BuiltinFnIdUnreachable:
711 return gen_unreachable(g, node);723 return gen_unreachable(g, node);
724 case BuiltinFnIdSetFnTest:
725 case BuiltinFnIdSetFnVisible:
726 case BuiltinFnIdSetFnStaticEval:
727 case BuiltinFnIdSetFnNoInline:
728 case BuiltinFnIdSetDebugSafety:
729 // do nothing
730 return nullptr;
712 }731 }
713 zig_unreachable();732 zig_unreachable();
714}733}
...@@ -3617,7 +3636,6 @@ static LLVMValueRef gen_expr(CodeGen *g, AstNode *node) {...@@ -3617,7 +3636,6 @@ static LLVMValueRef gen_expr(CodeGen *g, AstNode *node) {
3617 case NodeTypeFnDef:3636 case NodeTypeFnDef:
3618 case NodeTypeFnDecl:3637 case NodeTypeFnDecl:
3619 case NodeTypeParamDecl:3638 case NodeTypeParamDecl:
3620 case NodeTypeDirective:
3621 case NodeTypeUse:3639 case NodeTypeUse:
3622 case NodeTypeContainerDecl:3640 case NodeTypeContainerDecl:
3623 case NodeTypeStructField:3641 case NodeTypeStructField:
...@@ -4880,6 +4898,11 @@ static void define_builtin_fns(CodeGen *g) {...@@ -4880,6 +4898,11 @@ static void define_builtin_fns(CodeGen *g) {
4880 create_builtin_fn_with_arg_count(g, BuiltinFnIdCompileErr, "compileError", 1);4898 create_builtin_fn_with_arg_count(g, BuiltinFnIdCompileErr, "compileError", 1);
4881 create_builtin_fn_with_arg_count(g, BuiltinFnIdIntType, "intType", 2);4899 create_builtin_fn_with_arg_count(g, BuiltinFnIdIntType, "intType", 2);
4882 create_builtin_fn_with_arg_count(g, BuiltinFnIdUnreachable, "unreachable", 0);4900 create_builtin_fn_with_arg_count(g, BuiltinFnIdUnreachable, "unreachable", 0);
4901 create_builtin_fn_with_arg_count(g, BuiltinFnIdSetFnTest, "setFnTest", 2);
4902 create_builtin_fn_with_arg_count(g, BuiltinFnIdSetFnVisible, "setFnVisible", 2);
4903 create_builtin_fn_with_arg_count(g, BuiltinFnIdSetFnStaticEval, "setFnStaticEval", 2);
4904 create_builtin_fn_with_arg_count(g, BuiltinFnIdSetFnNoInline, "setFnNoInline", 2);
4905 create_builtin_fn_with_arg_count(g, BuiltinFnIdSetDebugSafety, "setDebugSafety", 2);
4883}4906}
48844907
4885static void init(CodeGen *g, Buf *source_path) {4908static void init(CodeGen *g, Buf *source_path) {
src/eval.cpp+6-1
...@@ -963,6 +963,12 @@ static bool eval_fn_call_builtin(EvalFn *ef, AstNode *node, ConstExprValue *out_...@@ -963,6 +963,12 @@ static bool eval_fn_call_builtin(EvalFn *ef, AstNode *node, ConstExprValue *out_
963 case BuiltinFnIdCompileErr:963 case BuiltinFnIdCompileErr:
964 case BuiltinFnIdIntType:964 case BuiltinFnIdIntType:
965 zig_unreachable();965 zig_unreachable();
966 case BuiltinFnIdSetFnTest:
967 case BuiltinFnIdSetFnVisible:
968 case BuiltinFnIdSetFnStaticEval:
969 case BuiltinFnIdSetFnNoInline:
970 case BuiltinFnIdSetDebugSafety:
971 return false;
966 }972 }
967973
968 return false;974 return false;
...@@ -1398,7 +1404,6 @@ static bool eval_expr(EvalFn *ef, AstNode *node, ConstExprValue *out) {...@@ -1398,7 +1404,6 @@ static bool eval_expr(EvalFn *ef, AstNode *node, ConstExprValue *out) {
1398 case NodeTypeUse:1404 case NodeTypeUse:
1399 case NodeTypeAsmExpr:1405 case NodeTypeAsmExpr:
1400 case NodeTypeParamDecl:1406 case NodeTypeParamDecl:
1401 case NodeTypeDirective:
1402 case NodeTypeTypeDecl:1407 case NodeTypeTypeDecl:
1403 zig_unreachable();1408 zig_unreachable();
1404 }1409 }
src/parseh.cpp-1
...@@ -124,7 +124,6 @@ static AstNode *create_typed_var_decl_node(Context *c, bool is_const, const char...@@ -124,7 +124,6 @@ static AstNode *create_typed_var_decl_node(Context *c, bool is_const, const char
124 node->data.variable_declaration.is_const = is_const;124 node->data.variable_declaration.is_const = is_const;
125 node->data.variable_declaration.top_level_decl.visib_mod = c->visib_mod;125 node->data.variable_declaration.top_level_decl.visib_mod = c->visib_mod;
126 node->data.variable_declaration.expr = init_node;126 node->data.variable_declaration.expr = init_node;
127 node->data.variable_declaration.top_level_decl.directives = nullptr;
128 node->data.variable_declaration.type = type_node;127 node->data.variable_declaration.type = type_node;
129 normalize_parent_ptrs(node);128 normalize_parent_ptrs(node);
130 return node;129 return node;
src/parser.cpp+53-150
...@@ -211,8 +211,7 @@ static AstNode *ast_parse_if_expr(ParseContext *pc, size_t *token_index, bool ma...@@ -211,8 +211,7 @@ static AstNode *ast_parse_if_expr(ParseContext *pc, size_t *token_index, bool ma
211static AstNode *ast_parse_block_expr(ParseContext *pc, size_t *token_index, bool mandatory);211static AstNode *ast_parse_block_expr(ParseContext *pc, size_t *token_index, bool mandatory);
212static AstNode *ast_parse_unwrap_expr(ParseContext *pc, size_t *token_index, bool mandatory);212static AstNode *ast_parse_unwrap_expr(ParseContext *pc, size_t *token_index, bool mandatory);
213static AstNode *ast_parse_prefix_op_expr(ParseContext *pc, size_t *token_index, bool mandatory);213static AstNode *ast_parse_prefix_op_expr(ParseContext *pc, size_t *token_index, bool mandatory);
214static AstNode *ast_parse_fn_proto(ParseContext *pc, size_t *token_index, bool mandatory,214static AstNode *ast_parse_fn_proto(ParseContext *pc, size_t *token_index, bool mandatory, VisibMod visib_mod);
215 ZigList<AstNode*> *directives, VisibMod visib_mod);
216static AstNode *ast_parse_return_expr(ParseContext *pc, size_t *token_index);215static AstNode *ast_parse_return_expr(ParseContext *pc, size_t *token_index);
217static AstNode *ast_parse_grouped_expr(ParseContext *pc, size_t *token_index, bool mandatory);216static AstNode *ast_parse_grouped_expr(ParseContext *pc, size_t *token_index, bool mandatory);
218217
...@@ -233,39 +232,6 @@ static Token *ast_eat_token(ParseContext *pc, size_t *token_index, TokenId token...@@ -233,39 +232,6 @@ static Token *ast_eat_token(ParseContext *pc, size_t *token_index, TokenId token
233 return token;232 return token;
234}233}
235234
236/*
237Directive = "#" "Symbol" "(" Expression ")"
238*/
239static AstNode *ast_parse_directive(ParseContext *pc, size_t *token_index) {
240 Token *number_sign = ast_eat_token(pc, token_index, TokenIdNumberSign);
241
242 AstNode *node = ast_create_node(pc, NodeTypeDirective, number_sign);
243
244 Token *name_symbol = ast_eat_token(pc, token_index, TokenIdSymbol);
245
246 node->data.directive.name = token_buf(name_symbol);
247
248 node->data.directive.expr = ast_parse_grouped_expr(pc, token_index, true);
249
250 normalize_parent_ptrs(node);
251 return node;
252}
253
254static void ast_parse_directives(ParseContext *pc, size_t *token_index,
255 ZigList<AstNode *> *directives)
256{
257 for (;;) {
258 Token *token = &pc->tokens->at(*token_index);
259 if (token->id == TokenIdNumberSign) {
260 AstNode *directive_node = ast_parse_directive(pc, token_index);
261 directives->append(directive_node);
262 } else {
263 return;
264 }
265 }
266 zig_unreachable();
267}
268
269/*235/*
270TypeExpr = PrefixOpExpression | "var"236TypeExpr = PrefixOpExpression | "var"
271*/237*/
...@@ -686,7 +652,7 @@ static AstNode *ast_parse_primary_expr(ParseContext *pc, size_t *token_index, bo...@@ -686,7 +652,7 @@ static AstNode *ast_parse_primary_expr(ParseContext *pc, size_t *token_index, bo
686 return node;652 return node;
687 } else if (token->id == TokenIdKeywordExtern) {653 } else if (token->id == TokenIdKeywordExtern) {
688 *token_index += 1;654 *token_index += 1;
689 AstNode *node = ast_parse_fn_proto(pc, token_index, true, nullptr, VisibModPrivate);655 AstNode *node = ast_parse_fn_proto(pc, token_index, true, VisibModPrivate);
690 node->data.fn_proto.is_extern = true;656 node->data.fn_proto.is_extern = true;
691 return node;657 return node;
692 } else if (token->id == TokenIdAtSign) {658 } else if (token->id == TokenIdAtSign) {
...@@ -735,7 +701,7 @@ static AstNode *ast_parse_primary_expr(ParseContext *pc, size_t *token_index, bo...@@ -735,7 +701,7 @@ static AstNode *ast_parse_primary_expr(ParseContext *pc, size_t *token_index, bo
735 return array_type_node;701 return array_type_node;
736 }702 }
737703
738 AstNode *fn_proto_node = ast_parse_fn_proto(pc, token_index, false, nullptr, VisibModPrivate);704 AstNode *fn_proto_node = ast_parse_fn_proto(pc, token_index, false, VisibModPrivate);
739 if (fn_proto_node) {705 if (fn_proto_node) {
740 return fn_proto_node;706 return fn_proto_node;
741 }707 }
...@@ -1487,7 +1453,7 @@ static AstNode *ast_parse_defer_expr(ParseContext *pc, size_t *token_index) {...@@ -1487,7 +1453,7 @@ static AstNode *ast_parse_defer_expr(ParseContext *pc, size_t *token_index) {
1487VariableDeclaration : ("var" | "const") "Symbol" ("=" Expression | ":" PrefixOpExpression option("=" Expression))1453VariableDeclaration : ("var" | "const") "Symbol" ("=" Expression | ":" PrefixOpExpression option("=" Expression))
1488*/1454*/
1489static AstNode *ast_parse_variable_declaration_expr(ParseContext *pc, size_t *token_index, bool mandatory,1455static AstNode *ast_parse_variable_declaration_expr(ParseContext *pc, size_t *token_index, bool mandatory,
1490 ZigList<AstNode*> *directives, VisibMod visib_mod)1456 VisibMod visib_mod)
1491{1457{
1492 Token *first_token = &pc->tokens->at(*token_index);1458 Token *first_token = &pc->tokens->at(*token_index);
14931459
...@@ -1509,7 +1475,6 @@ static AstNode *ast_parse_variable_declaration_expr(ParseContext *pc, size_t *to...@@ -1509,7 +1475,6 @@ static AstNode *ast_parse_variable_declaration_expr(ParseContext *pc, size_t *to
15091475
1510 node->data.variable_declaration.is_const = is_const;1476 node->data.variable_declaration.is_const = is_const;
1511 node->data.variable_declaration.top_level_decl.visib_mod = visib_mod;1477 node->data.variable_declaration.top_level_decl.visib_mod = visib_mod;
1512 node->data.variable_declaration.top_level_decl.directives = directives;
15131478
1514 Token *name_token = ast_eat_token(pc, token_index, TokenIdSymbol);1479 Token *name_token = ast_eat_token(pc, token_index, TokenIdSymbol);
1515 node->data.variable_declaration.symbol = token_buf(name_token);1480 node->data.variable_declaration.symbol = token_buf(name_token);
...@@ -1985,8 +1950,7 @@ static AstNode *ast_parse_block(ParseContext *pc, size_t *token_index, bool mand...@@ -1985,8 +1950,7 @@ static AstNode *ast_parse_block(ParseContext *pc, size_t *token_index, bool mand
1985 if (statement_node) {1950 if (statement_node) {
1986 semicolon_expected = false;1951 semicolon_expected = false;
1987 } else {1952 } else {
1988 statement_node = ast_parse_variable_declaration_expr(pc, token_index, false,1953 statement_node = ast_parse_variable_declaration_expr(pc, token_index, false, VisibModPrivate);
1989 nullptr, VisibModPrivate);
1990 if (!statement_node) {1954 if (!statement_node) {
1991 statement_node = ast_parse_defer_expr(pc, token_index);1955 statement_node = ast_parse_defer_expr(pc, token_index);
1992 }1956 }
...@@ -2023,25 +1987,35 @@ static AstNode *ast_parse_block(ParseContext *pc, size_t *token_index, bool mand...@@ -2023,25 +1987,35 @@ static AstNode *ast_parse_block(ParseContext *pc, size_t *token_index, bool mand
2023}1987}
20241988
2025/*1989/*
2026FnProto = "fn" option("Symbol") ParamDeclList option("->" TypeExpr)1990FnProto = option("coldcc" | "nakedcc") "fn" option(Symbol) ParamDeclList option("->" TypeExpr)
2027*/1991*/
2028static AstNode *ast_parse_fn_proto(ParseContext *pc, size_t *token_index, bool mandatory,1992static AstNode *ast_parse_fn_proto(ParseContext *pc, size_t *token_index, bool mandatory, VisibMod visib_mod) {
2029 ZigList<AstNode*> *directives, VisibMod visib_mod)
2030{
2031 Token *first_token = &pc->tokens->at(*token_index);1993 Token *first_token = &pc->tokens->at(*token_index);
1994 Token *fn_token;
20321995
2033 if (first_token->id != TokenIdKeywordFn) {1996 bool is_coldcc = false;
2034 if (mandatory) {1997 bool is_nakedcc = false;
2035 ast_expect_token(pc, first_token, TokenIdKeywordFn);1998 if (first_token->id == TokenIdKeywordColdCC) {
2036 } else {1999 *token_index += 1;
2037 return nullptr;2000 fn_token = ast_eat_token(pc, token_index, TokenIdKeywordFn);
2038 }2001 is_coldcc = true;
2002 } else if (first_token->id == TokenIdKeywordNakedCC) {
2003 *token_index += 1;
2004 fn_token = ast_eat_token(pc, token_index, TokenIdKeywordFn);
2005 is_nakedcc = true;
2006 } else if (first_token->id == TokenIdKeywordFn) {
2007 fn_token = first_token;
2008 *token_index += 1;
2009 } else if (mandatory) {
2010 ast_expect_token(pc, first_token, TokenIdKeywordFn);
2011 } else {
2012 return nullptr;
2039 }2013 }
2040 *token_index += 1;
20412014
2042 AstNode *node = ast_create_node(pc, NodeTypeFnProto, first_token);2015 AstNode *node = ast_create_node(pc, NodeTypeFnProto, fn_token);
2043 node->data.fn_proto.top_level_decl.visib_mod = visib_mod;2016 node->data.fn_proto.top_level_decl.visib_mod = visib_mod;
2044 node->data.fn_proto.top_level_decl.directives = directives;2017 node->data.fn_proto.is_coldcc = is_coldcc;
2018 node->data.fn_proto.is_nakedcc = is_nakedcc;
20452019
2046 Token *fn_name = &pc->tokens->at(*token_index);2020 Token *fn_name = &pc->tokens->at(*token_index);
2047 if (fn_name->id == TokenIdSymbol) {2021 if (fn_name->id == TokenIdSymbol) {
...@@ -2068,9 +2042,7 @@ static AstNode *ast_parse_fn_proto(ParseContext *pc, size_t *token_index, bool m...@@ -2068,9 +2042,7 @@ static AstNode *ast_parse_fn_proto(ParseContext *pc, size_t *token_index, bool m
2068/*2042/*
2069FnDef = option("inline" | "extern") FnProto Block2043FnDef = option("inline" | "extern") FnProto Block
2070*/2044*/
2071static AstNode *ast_parse_fn_def(ParseContext *pc, size_t *token_index, bool mandatory,2045static AstNode *ast_parse_fn_def(ParseContext *pc, size_t *token_index, bool mandatory, VisibMod visib_mod) {
2072 ZigList<AstNode*> *directives, VisibMod visib_mod)
2073{
2074 Token *first_token = &pc->tokens->at(*token_index);2046 Token *first_token = &pc->tokens->at(*token_index);
2075 bool is_inline;2047 bool is_inline;
2076 bool is_extern;2048 bool is_extern;
...@@ -2087,7 +2059,7 @@ static AstNode *ast_parse_fn_def(ParseContext *pc, size_t *token_index, bool man...@@ -2087,7 +2059,7 @@ static AstNode *ast_parse_fn_def(ParseContext *pc, size_t *token_index, bool man
2087 is_extern = false;2059 is_extern = false;
2088 }2060 }
20892061
2090 AstNode *fn_proto = ast_parse_fn_proto(pc, token_index, mandatory, directives, visib_mod);2062 AstNode *fn_proto = ast_parse_fn_proto(pc, token_index, mandatory, visib_mod);
2091 if (!fn_proto) {2063 if (!fn_proto) {
2092 if (is_inline || is_extern) {2064 if (is_inline || is_extern) {
2093 *token_index -= 1;2065 *token_index -= 1;
...@@ -2115,9 +2087,7 @@ static AstNode *ast_parse_fn_def(ParseContext *pc, size_t *token_index, bool man...@@ -2115,9 +2087,7 @@ static AstNode *ast_parse_fn_def(ParseContext *pc, size_t *token_index, bool man
2115/*2087/*
2116ExternDecl = "extern" (FnProto | VariableDeclaration) ";"2088ExternDecl = "extern" (FnProto | VariableDeclaration) ";"
2117*/2089*/
2118static AstNode *ast_parse_extern_decl(ParseContext *pc, size_t *token_index, bool mandatory,2090static AstNode *ast_parse_extern_decl(ParseContext *pc, size_t *token_index, bool mandatory, VisibMod visib_mod) {
2119 ZigList<AstNode *> *directives, VisibMod visib_mod)
2120{
2121 Token *extern_kw = &pc->tokens->at(*token_index);2091 Token *extern_kw = &pc->tokens->at(*token_index);
2122 if (extern_kw->id != TokenIdKeywordExtern) {2092 if (extern_kw->id != TokenIdKeywordExtern) {
2123 if (mandatory) {2093 if (mandatory) {
...@@ -2128,7 +2098,7 @@ static AstNode *ast_parse_extern_decl(ParseContext *pc, size_t *token_index, boo...@@ -2128,7 +2098,7 @@ static AstNode *ast_parse_extern_decl(ParseContext *pc, size_t *token_index, boo
2128 }2098 }
2129 *token_index += 1;2099 *token_index += 1;
21302100
2131 AstNode *fn_proto_node = ast_parse_fn_proto(pc, token_index, false, directives, visib_mod);2101 AstNode *fn_proto_node = ast_parse_fn_proto(pc, token_index, false, visib_mod);
2132 if (fn_proto_node) {2102 if (fn_proto_node) {
2133 ast_eat_token(pc, token_index, TokenIdSemicolon);2103 ast_eat_token(pc, token_index, TokenIdSemicolon);
21342104
...@@ -2138,7 +2108,7 @@ static AstNode *ast_parse_extern_decl(ParseContext *pc, size_t *token_index, boo...@@ -2138,7 +2108,7 @@ static AstNode *ast_parse_extern_decl(ParseContext *pc, size_t *token_index, boo
2138 return fn_proto_node;2108 return fn_proto_node;
2139 }2109 }
21402110
2141 AstNode *var_decl_node = ast_parse_variable_declaration_expr(pc, token_index, false, directives, visib_mod);2111 AstNode *var_decl_node = ast_parse_variable_declaration_expr(pc, token_index, false, visib_mod);
2142 if (var_decl_node) {2112 if (var_decl_node) {
2143 ast_eat_token(pc, token_index, TokenIdSemicolon);2113 ast_eat_token(pc, token_index, TokenIdSemicolon);
21442114
...@@ -2155,9 +2125,7 @@ static AstNode *ast_parse_extern_decl(ParseContext *pc, size_t *token_index, boo...@@ -2155,9 +2125,7 @@ static AstNode *ast_parse_extern_decl(ParseContext *pc, size_t *token_index, boo
2155/*2125/*
2156UseDecl = "use" Expression ";"2126UseDecl = "use" Expression ";"
2157*/2127*/
2158static AstNode *ast_parse_use(ParseContext *pc, size_t *token_index,2128static AstNode *ast_parse_use(ParseContext *pc, size_t *token_index, VisibMod visib_mod) {
2159 ZigList<AstNode*> *directives, VisibMod visib_mod)
2160{
2161 Token *use_kw = &pc->tokens->at(*token_index);2129 Token *use_kw = &pc->tokens->at(*token_index);
2162 if (use_kw->id != TokenIdKeywordUse)2130 if (use_kw->id != TokenIdKeywordUse)
2163 return nullptr;2131 return nullptr;
...@@ -2165,7 +2133,6 @@ static AstNode *ast_parse_use(ParseContext *pc, size_t *token_index,...@@ -2165,7 +2133,6 @@ static AstNode *ast_parse_use(ParseContext *pc, size_t *token_index,
21652133
2166 AstNode *node = ast_create_node(pc, NodeTypeUse, use_kw);2134 AstNode *node = ast_create_node(pc, NodeTypeUse, use_kw);
2167 node->data.use.top_level_decl.visib_mod = visib_mod;2135 node->data.use.top_level_decl.visib_mod = visib_mod;
2168 node->data.use.top_level_decl.directives = directives;
2169 node->data.use.expr = ast_parse_expression(pc, token_index, true);2136 node->data.use.expr = ast_parse_expression(pc, token_index, true);
21702137
2171 ast_eat_token(pc, token_index, TokenIdSemicolon);2138 ast_eat_token(pc, token_index, TokenIdSemicolon);
...@@ -2175,13 +2142,11 @@ static AstNode *ast_parse_use(ParseContext *pc, size_t *token_index,...@@ -2175,13 +2142,11 @@ static AstNode *ast_parse_use(ParseContext *pc, size_t *token_index,
2175}2142}
21762143
2177/*2144/*
2178ContainerDecl = ("struct" | "enum" | "union") "Symbol" option(ParamDeclList) "{" many(StructMember) "}"2145ContainerDecl = ("struct" | "enum" | "union") Symbol option(ParamDeclList) "{" many(StructMember) "}"
2179StructMember = many(Directive) option(VisibleMod) (StructField | FnDef | GlobalVarDecl | ContainerDecl)2146StructMember = (StructField | FnDef | GlobalVarDecl | ContainerDecl)
2180StructField : "Symbol" option(":" Expression) ",")2147StructField = Symbol option(":" Expression) ",")
2181*/2148*/
2182static AstNode *ast_parse_container_decl(ParseContext *pc, size_t *token_index,2149static AstNode *ast_parse_container_decl(ParseContext *pc, size_t *token_index, VisibMod visib_mod) {
2183 ZigList<AstNode*> *directives, VisibMod visib_mod)
2184{
2185 Token *first_token = &pc->tokens->at(*token_index);2150 Token *first_token = &pc->tokens->at(*token_index);
21862151
2187 ContainerKind kind;2152 ContainerKind kind;
...@@ -2203,7 +2168,6 @@ static AstNode *ast_parse_container_decl(ParseContext *pc, size_t *token_index,...@@ -2203,7 +2168,6 @@ static AstNode *ast_parse_container_decl(ParseContext *pc, size_t *token_index,
2203 node->data.struct_decl.kind = kind;2168 node->data.struct_decl.kind = kind;
2204 node->data.struct_decl.name = token_buf(struct_name);2169 node->data.struct_decl.name = token_buf(struct_name);
2205 node->data.struct_decl.top_level_decl.visib_mod = visib_mod;2170 node->data.struct_decl.top_level_decl.visib_mod = visib_mod;
2206 node->data.struct_decl.top_level_decl.directives = directives;
22072171
2208 Token *paren_or_brace = &pc->tokens->at(*token_index);2172 Token *paren_or_brace = &pc->tokens->at(*token_index);
2209 if (paren_or_brace->id == TokenIdLParen) {2173 if (paren_or_brace->id == TokenIdLParen) {
...@@ -2217,10 +2181,6 @@ static AstNode *ast_parse_container_decl(ParseContext *pc, size_t *token_index,...@@ -2217,10 +2181,6 @@ static AstNode *ast_parse_container_decl(ParseContext *pc, size_t *token_index,
2217 }2181 }
22182182
2219 for (;;) {2183 for (;;) {
2220 Token *directive_token = &pc->tokens->at(*token_index);
2221 ZigList<AstNode *> *directive_list = allocate<ZigList<AstNode*>>(1);
2222 ast_parse_directives(pc, token_index, directive_list);
2223
2224 Token *visib_tok = &pc->tokens->at(*token_index);2184 Token *visib_tok = &pc->tokens->at(*token_index);
2225 VisibMod visib_mod;2185 VisibMod visib_mod;
2226 if (visib_tok->id == TokenIdKeywordPub) {2186 if (visib_tok->id == TokenIdKeywordPub) {
...@@ -2233,20 +2193,20 @@ static AstNode *ast_parse_container_decl(ParseContext *pc, size_t *token_index,...@@ -2233,20 +2193,20 @@ static AstNode *ast_parse_container_decl(ParseContext *pc, size_t *token_index,
2233 visib_mod = VisibModPrivate;2193 visib_mod = VisibModPrivate;
2234 }2194 }
22352195
2236 AstNode *fn_def_node = ast_parse_fn_def(pc, token_index, false, directive_list, visib_mod);2196 AstNode *fn_def_node = ast_parse_fn_def(pc, token_index, false, visib_mod);
2237 if (fn_def_node) {2197 if (fn_def_node) {
2238 node->data.struct_decl.decls.append(fn_def_node);2198 node->data.struct_decl.decls.append(fn_def_node);
2239 continue;2199 continue;
2240 }2200 }
22412201
2242 AstNode *var_decl_node = ast_parse_variable_declaration_expr(pc, token_index, false, directive_list, visib_mod);2202 AstNode *var_decl_node = ast_parse_variable_declaration_expr(pc, token_index, false, visib_mod);
2243 if (var_decl_node) {2203 if (var_decl_node) {
2244 ast_eat_token(pc, token_index, TokenIdSemicolon);2204 ast_eat_token(pc, token_index, TokenIdSemicolon);
2245 node->data.struct_decl.decls.append(var_decl_node);2205 node->data.struct_decl.decls.append(var_decl_node);
2246 continue;2206 continue;
2247 }2207 }
22482208
2249 AstNode *container_decl_node = ast_parse_container_decl(pc, token_index, directive_list, visib_mod);2209 AstNode *container_decl_node = ast_parse_container_decl(pc, token_index, visib_mod);
2250 if (container_decl_node) {2210 if (container_decl_node) {
2251 node->data.struct_decl.decls.append(container_decl_node);2211 node->data.struct_decl.decls.append(container_decl_node);
2252 continue;2212 continue;
...@@ -2255,10 +2215,6 @@ static AstNode *ast_parse_container_decl(ParseContext *pc, size_t *token_index,...@@ -2255,10 +2215,6 @@ static AstNode *ast_parse_container_decl(ParseContext *pc, size_t *token_index,
2255 Token *token = &pc->tokens->at(*token_index);2215 Token *token = &pc->tokens->at(*token_index);
22562216
2257 if (token->id == TokenIdRBrace) {2217 if (token->id == TokenIdRBrace) {
2258 if (directive_list->length > 0) {
2259 ast_error(pc, directive_token, "invalid directive");
2260 }
2261
2262 *token_index += 1;2218 *token_index += 1;
2263 break;2219 break;
2264 } else if (token->id == TokenIdSymbol) {2220 } else if (token->id == TokenIdSymbol) {
...@@ -2266,7 +2222,6 @@ static AstNode *ast_parse_container_decl(ParseContext *pc, size_t *token_index,...@@ -2266,7 +2222,6 @@ static AstNode *ast_parse_container_decl(ParseContext *pc, size_t *token_index,
2266 *token_index += 1;2222 *token_index += 1;
22672223
2268 field_node->data.struct_field.top_level_decl.visib_mod = visib_mod;2224 field_node->data.struct_field.top_level_decl.visib_mod = visib_mod;
2269 field_node->data.struct_field.top_level_decl.directives = directive_list;
2270 field_node->data.struct_field.name = token_buf(token);2225 field_node->data.struct_field.name = token_buf(token);
22712226
2272 Token *expr_or_comma = &pc->tokens->at(*token_index);2227 Token *expr_or_comma = &pc->tokens->at(*token_index);
...@@ -2293,9 +2248,7 @@ static AstNode *ast_parse_container_decl(ParseContext *pc, size_t *token_index,...@@ -2293,9 +2248,7 @@ static AstNode *ast_parse_container_decl(ParseContext *pc, size_t *token_index,
2293/*2248/*
2294ErrorValueDecl : "error" "Symbol" ";"2249ErrorValueDecl : "error" "Symbol" ";"
2295*/2250*/
2296static AstNode *ast_parse_error_value_decl(ParseContext *pc, size_t *token_index,2251static AstNode *ast_parse_error_value_decl(ParseContext *pc, size_t *token_index, VisibMod visib_mod) {
2297 ZigList<AstNode*> *directives, VisibMod visib_mod)
2298{
2299 Token *first_token = &pc->tokens->at(*token_index);2252 Token *first_token = &pc->tokens->at(*token_index);
23002253
2301 if (first_token->id != TokenIdKeywordError) {2254 if (first_token->id != TokenIdKeywordError) {
...@@ -2308,7 +2261,6 @@ static AstNode *ast_parse_error_value_decl(ParseContext *pc, size_t *token_index...@@ -2308,7 +2261,6 @@ static AstNode *ast_parse_error_value_decl(ParseContext *pc, size_t *token_index
23082261
2309 AstNode *node = ast_create_node(pc, NodeTypeErrorValueDecl, first_token);2262 AstNode *node = ast_create_node(pc, NodeTypeErrorValueDecl, first_token);
2310 node->data.error_value_decl.top_level_decl.visib_mod = visib_mod;2263 node->data.error_value_decl.top_level_decl.visib_mod = visib_mod;
2311 node->data.error_value_decl.top_level_decl.directives = directives;
2312 node->data.error_value_decl.name = token_buf(name_tok);2264 node->data.error_value_decl.name = token_buf(name_tok);
23132265
2314 normalize_parent_ptrs(node);2266 normalize_parent_ptrs(node);
...@@ -2318,9 +2270,7 @@ static AstNode *ast_parse_error_value_decl(ParseContext *pc, size_t *token_index...@@ -2318,9 +2270,7 @@ static AstNode *ast_parse_error_value_decl(ParseContext *pc, size_t *token_index
2318/*2270/*
2319TypeDecl = "type" "Symbol" "=" TypeExpr ";"2271TypeDecl = "type" "Symbol" "=" TypeExpr ";"
2320*/2272*/
2321static AstNode *ast_parse_type_decl(ParseContext *pc, size_t *token_index,2273static AstNode *ast_parse_type_decl(ParseContext *pc, size_t *token_index, VisibMod visib_mod) {
2322 ZigList<AstNode*> *directives, VisibMod visib_mod)
2323{
2324 Token *first_token = &pc->tokens->at(*token_index);2274 Token *first_token = &pc->tokens->at(*token_index);
23252275
2326 if (first_token->id != TokenIdKeywordType) {2276 if (first_token->id != TokenIdKeywordType) {
...@@ -2338,21 +2288,17 @@ static AstNode *ast_parse_type_decl(ParseContext *pc, size_t *token_index,...@@ -2338,21 +2288,17 @@ static AstNode *ast_parse_type_decl(ParseContext *pc, size_t *token_index,
2338 ast_eat_token(pc, token_index, TokenIdSemicolon);2288 ast_eat_token(pc, token_index, TokenIdSemicolon);
23392289
2340 node->data.type_decl.top_level_decl.visib_mod = visib_mod;2290 node->data.type_decl.top_level_decl.visib_mod = visib_mod;
2341 node->data.type_decl.top_level_decl.directives = directives;
23422291
2343 normalize_parent_ptrs(node);2292 normalize_parent_ptrs(node);
2344 return node;2293 return node;
2345}2294}
23462295
2347/*2296/*
2348TopLevelDecl = many(Directive) option(VisibleMod) (FnDef | ExternDecl | Import | ContainerDecl | GlobalVarDecl | ErrorValueDecl | CImportDecl | TypeDecl)2297TopLevelItem = ErrorValueDecl | Block | TopLevelDecl
2298TopLevelDecl = option(VisibleMod) (FnDef | ExternDecl | ContainerDecl | GlobalVarDecl | TypeDecl | UseDecl)
2349*/2299*/
2350static void ast_parse_top_level_decls(ParseContext *pc, size_t *token_index, ZigList<AstNode *> *top_level_decls) {2300static void ast_parse_top_level_decls(ParseContext *pc, size_t *token_index, ZigList<AstNode *> *top_level_decls) {
2351 for (;;) {2301 for (;;) {
2352 Token *directive_token = &pc->tokens->at(*token_index);
2353 ZigList<AstNode *> *directives = allocate<ZigList<AstNode*>>(1);
2354 ast_parse_directives(pc, token_index, directives);
2355
2356 Token *visib_tok = &pc->tokens->at(*token_index);2302 Token *visib_tok = &pc->tokens->at(*token_index);
2357 VisibMod visib_mod;2303 VisibMod visib_mod;
2358 if (visib_tok->id == TokenIdKeywordPub) {2304 if (visib_tok->id == TokenIdKeywordPub) {
...@@ -2365,61 +2311,56 @@ static void ast_parse_top_level_decls(ParseContext *pc, size_t *token_index, Zig...@@ -2365,61 +2311,56 @@ static void ast_parse_top_level_decls(ParseContext *pc, size_t *token_index, Zig
2365 visib_mod = VisibModPrivate;2311 visib_mod = VisibModPrivate;
2366 }2312 }
23672313
2368 AstNode *fn_def_node = ast_parse_fn_def(pc, token_index, false, directives, visib_mod);2314 AstNode *fn_def_node = ast_parse_fn_def(pc, token_index, false, visib_mod);
2369 if (fn_def_node) {2315 if (fn_def_node) {
2370 top_level_decls->append(fn_def_node);2316 top_level_decls->append(fn_def_node);
2371 continue;2317 continue;
2372 }2318 }
23732319
2374 AstNode *fn_proto_node = ast_parse_extern_decl(pc, token_index, false, directives, visib_mod);2320 AstNode *fn_proto_node = ast_parse_extern_decl(pc, token_index, false, visib_mod);
2375 if (fn_proto_node) {2321 if (fn_proto_node) {
2376 top_level_decls->append(fn_proto_node);2322 top_level_decls->append(fn_proto_node);
2377 continue;2323 continue;
2378 }2324 }
23792325
2380 AstNode *use_node = ast_parse_use(pc, token_index, directives, visib_mod);2326 AstNode *use_node = ast_parse_use(pc, token_index, visib_mod);
2381 if (use_node) {2327 if (use_node) {
2382 top_level_decls->append(use_node);2328 top_level_decls->append(use_node);
2383 continue;2329 continue;
2384 }2330 }
23852331
2386 AstNode *struct_node = ast_parse_container_decl(pc, token_index, directives, visib_mod);2332 AstNode *struct_node = ast_parse_container_decl(pc, token_index, visib_mod);
2387 if (struct_node) {2333 if (struct_node) {
2388 top_level_decls->append(struct_node);2334 top_level_decls->append(struct_node);
2389 continue;2335 continue;
2390 }2336 }
23912337
2392 AstNode *var_decl_node = ast_parse_variable_declaration_expr(pc, token_index, false,2338 AstNode *var_decl_node = ast_parse_variable_declaration_expr(pc, token_index, false, visib_mod);
2393 directives, visib_mod);
2394 if (var_decl_node) {2339 if (var_decl_node) {
2395 ast_eat_token(pc, token_index, TokenIdSemicolon);2340 ast_eat_token(pc, token_index, TokenIdSemicolon);
2396 top_level_decls->append(var_decl_node);2341 top_level_decls->append(var_decl_node);
2397 continue;2342 continue;
2398 }2343 }
23992344
2400 AstNode *error_value_node = ast_parse_error_value_decl(pc, token_index, directives, visib_mod);2345 AstNode *error_value_node = ast_parse_error_value_decl(pc, token_index, visib_mod);
2401 if (error_value_node) {2346 if (error_value_node) {
2402 top_level_decls->append(error_value_node);2347 top_level_decls->append(error_value_node);
2403 continue;2348 continue;
2404 }2349 }
24052350
2406 AstNode *type_decl_node = ast_parse_type_decl(pc, token_index, directives, visib_mod);2351 AstNode *type_decl_node = ast_parse_type_decl(pc, token_index, visib_mod);
2407 if (type_decl_node) {2352 if (type_decl_node) {
2408 top_level_decls->append(type_decl_node);2353 top_level_decls->append(type_decl_node);
2409 continue;2354 continue;
2410 }2355 }
24112356
2412 if (directives->length > 0) {
2413 ast_error(pc, directive_token, "invalid directive");
2414 }
2415
2416 return;2357 return;
2417 }2358 }
2418 zig_unreachable();2359 zig_unreachable();
2419}2360}
24202361
2421/*2362/*
2422Root : many(TopLevelDecl) token(EOF)2363Root = many(TopLevelItem) "EOF"
2423 */2364 */
2424static AstNode *ast_parse_root(ParseContext *pc, size_t *token_index) {2365static AstNode *ast_parse_root(ParseContext *pc, size_t *token_index) {
2425 AstNode *node = ast_create_node(pc, NodeTypeRoot, &pc->tokens->at(*token_index));2366 AstNode *node = ast_create_node(pc, NodeTypeRoot, &pc->tokens->at(*token_index));
...@@ -2471,7 +2412,6 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont...@@ -2471,7 +2412,6 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont
2471 break;2412 break;
2472 case NodeTypeFnProto:2413 case NodeTypeFnProto:
2473 visit_field(&node->data.fn_proto.return_type, visit, context);2414 visit_field(&node->data.fn_proto.return_type, visit, context);
2474 visit_node_list(node->data.fn_proto.top_level_decl.directives, visit, context);
2475 visit_node_list(&node->data.fn_proto.params, visit, context);2415 visit_node_list(&node->data.fn_proto.params, visit, context);
2476 break;2416 break;
2477 case NodeTypeFnDef:2417 case NodeTypeFnDef:
...@@ -2487,9 +2427,6 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont...@@ -2487,9 +2427,6 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont
2487 case NodeTypeBlock:2427 case NodeTypeBlock:
2488 visit_node_list(&node->data.block.statements, visit, context);2428 visit_node_list(&node->data.block.statements, visit, context);
2489 break;2429 break;
2490 case NodeTypeDirective:
2491 visit_field(&node->data.directive.expr, visit, context);
2492 break;
2493 case NodeTypeReturnExpr:2430 case NodeTypeReturnExpr:
2494 visit_field(&node->data.return_expr.expr, visit, context);2431 visit_field(&node->data.return_expr.expr, visit, context);
2495 break;2432 break;
...@@ -2497,12 +2434,10 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont...@@ -2497,12 +2434,10 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont
2497 visit_field(&node->data.defer.expr, visit, context);2434 visit_field(&node->data.defer.expr, visit, context);
2498 break;2435 break;
2499 case NodeTypeVariableDeclaration:2436 case NodeTypeVariableDeclaration:
2500 visit_node_list(node->data.variable_declaration.top_level_decl.directives, visit, context);
2501 visit_field(&node->data.variable_declaration.type, visit, context);2437 visit_field(&node->data.variable_declaration.type, visit, context);
2502 visit_field(&node->data.variable_declaration.expr, visit, context);2438 visit_field(&node->data.variable_declaration.expr, visit, context);
2503 break;2439 break;
2504 case NodeTypeTypeDecl:2440 case NodeTypeTypeDecl:
2505 visit_node_list(node->data.type_decl.top_level_decl.directives, visit, context);
2506 visit_field(&node->data.type_decl.child_type, visit, context);2441 visit_field(&node->data.type_decl.child_type, visit, context);
2507 break;2442 break;
2508 case NodeTypeErrorValueDecl:2443 case NodeTypeErrorValueDecl:
...@@ -2550,7 +2485,6 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont...@@ -2550,7 +2485,6 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont
2550 break;2485 break;
2551 case NodeTypeUse:2486 case NodeTypeUse:
2552 visit_field(&node->data.use.expr, visit, context);2487 visit_field(&node->data.use.expr, visit, context);
2553 visit_node_list(node->data.use.top_level_decl.directives, visit, context);
2554 break;2488 break;
2555 case NodeTypeBoolLiteral:2489 case NodeTypeBoolLiteral:
2556 // none2490 // none
...@@ -2626,11 +2560,9 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont...@@ -2626,11 +2560,9 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont
2626 case NodeTypeContainerDecl:2560 case NodeTypeContainerDecl:
2627 visit_node_list(&node->data.struct_decl.fields, visit, context);2561 visit_node_list(&node->data.struct_decl.fields, visit, context);
2628 visit_node_list(&node->data.struct_decl.decls, visit, context);2562 visit_node_list(&node->data.struct_decl.decls, visit, context);
2629 visit_node_list(node->data.struct_decl.top_level_decl.directives, visit, context);
2630 break;2563 break;
2631 case NodeTypeStructField:2564 case NodeTypeStructField:
2632 visit_field(&node->data.struct_field.type, visit, context);2565 visit_field(&node->data.struct_field.type, visit, context);
2633 visit_node_list(node->data.struct_field.top_level_decl.directives, visit, context);
2634 break;2566 break;
2635 case NodeTypeContainerInitExpr:2567 case NodeTypeContainerInitExpr:
2636 visit_field(&node->data.container_init_expr.type, visit, context);2568 visit_field(&node->data.container_init_expr.type, visit, context);
...@@ -2688,16 +2620,6 @@ static void clone_subtree_list_omit_inline_params(ZigList<AstNode *> *dest, ZigL...@@ -2688,16 +2620,6 @@ static void clone_subtree_list_omit_inline_params(ZigList<AstNode *> *dest, ZigL
2688 }2620 }
2689}2621}
26902622
2691static void clone_subtree_list_ptr(ZigList<AstNode *> **dest_ptr, ZigList<AstNode *> *src,
2692 uint32_t *next_node_index)
2693{
2694 if (src) {
2695 ZigList<AstNode *> *dest = allocate<ZigList<AstNode *>>(1);
2696 *dest_ptr = dest;
2697 clone_subtree_list(dest, src, next_node_index);
2698 }
2699}
2700
2701static void clone_subtree_field_special(AstNode **dest, AstNode *src, uint32_t *next_node_index,2623static void clone_subtree_field_special(AstNode **dest, AstNode *src, uint32_t *next_node_index,
2702 enum AstCloneSpecial special)2624 enum AstCloneSpecial special)
2703{2625{
...@@ -2713,10 +2635,6 @@ static void clone_subtree_field(AstNode **dest, AstNode *src, uint32_t *next_nod...@@ -2713,10 +2635,6 @@ static void clone_subtree_field(AstNode **dest, AstNode *src, uint32_t *next_nod
2713 return clone_subtree_field_special(dest, src, next_node_index, AstCloneSpecialNone);2635 return clone_subtree_field_special(dest, src, next_node_index, AstCloneSpecialNone);
2714}2636}
27152637
2716static void clone_subtree_tld(TopLevelDecl *dest, TopLevelDecl *src, uint32_t *next_node_index) {
2717 clone_subtree_list_ptr(&dest->directives, src->directives, next_node_index);
2718}
2719
2720AstNode *ast_clone_subtree_special(AstNode *old_node, uint32_t *next_node_index, enum AstCloneSpecial special) {2638AstNode *ast_clone_subtree_special(AstNode *old_node, uint32_t *next_node_index, enum AstCloneSpecial special) {
2721 AstNode *new_node = allocate_nonzero<AstNode>(1);2639 AstNode *new_node = allocate_nonzero<AstNode>(1);
2722 safe_memcpy(new_node, old_node, 1);2640 safe_memcpy(new_node, old_node, 1);
...@@ -2730,8 +2648,6 @@ AstNode *ast_clone_subtree_special(AstNode *old_node, uint32_t *next_node_index,...@@ -2730,8 +2648,6 @@ AstNode *ast_clone_subtree_special(AstNode *old_node, uint32_t *next_node_index,
2730 &old_node->data.root.top_level_decls, next_node_index);2648 &old_node->data.root.top_level_decls, next_node_index);
2731 break;2649 break;
2732 case NodeTypeFnProto:2650 case NodeTypeFnProto:
2733 clone_subtree_tld(&new_node->data.fn_proto.top_level_decl, &old_node->data.fn_proto.top_level_decl,
2734 next_node_index);
2735 clone_subtree_field(&new_node->data.fn_proto.return_type, old_node->data.fn_proto.return_type,2651 clone_subtree_field(&new_node->data.fn_proto.return_type, old_node->data.fn_proto.return_type,
2736 next_node_index);2652 next_node_index);
27372653
...@@ -2761,9 +2677,6 @@ AstNode *ast_clone_subtree_special(AstNode *old_node, uint32_t *next_node_index,...@@ -2761,9 +2677,6 @@ AstNode *ast_clone_subtree_special(AstNode *old_node, uint32_t *next_node_index,
2761 clone_subtree_list(&new_node->data.block.statements, &old_node->data.block.statements,2677 clone_subtree_list(&new_node->data.block.statements, &old_node->data.block.statements,
2762 next_node_index);2678 next_node_index);
2763 break;2679 break;
2764 case NodeTypeDirective:
2765 clone_subtree_field(&new_node->data.directive.expr, old_node->data.directive.expr, next_node_index);
2766 break;
2767 case NodeTypeReturnExpr:2680 case NodeTypeReturnExpr:
2768 clone_subtree_field(&new_node->data.return_expr.expr, old_node->data.return_expr.expr, next_node_index);2681 clone_subtree_field(&new_node->data.return_expr.expr, old_node->data.return_expr.expr, next_node_index);
2769 break;2682 break;
...@@ -2771,14 +2684,10 @@ AstNode *ast_clone_subtree_special(AstNode *old_node, uint32_t *next_node_index,...@@ -2771,14 +2684,10 @@ AstNode *ast_clone_subtree_special(AstNode *old_node, uint32_t *next_node_index,
2771 clone_subtree_field(&new_node->data.defer.expr, old_node->data.defer.expr, next_node_index);2684 clone_subtree_field(&new_node->data.defer.expr, old_node->data.defer.expr, next_node_index);
2772 break;2685 break;
2773 case NodeTypeVariableDeclaration:2686 case NodeTypeVariableDeclaration:
2774 clone_subtree_list_ptr(&new_node->data.variable_declaration.top_level_decl.directives,
2775 old_node->data.variable_declaration.top_level_decl.directives, next_node_index);
2776 clone_subtree_field(&new_node->data.variable_declaration.type, old_node->data.variable_declaration.type, next_node_index);2687 clone_subtree_field(&new_node->data.variable_declaration.type, old_node->data.variable_declaration.type, next_node_index);
2777 clone_subtree_field(&new_node->data.variable_declaration.expr, old_node->data.variable_declaration.expr, next_node_index);2688 clone_subtree_field(&new_node->data.variable_declaration.expr, old_node->data.variable_declaration.expr, next_node_index);
2778 break;2689 break;
2779 case NodeTypeTypeDecl:2690 case NodeTypeTypeDecl:
2780 clone_subtree_list_ptr(&new_node->data.type_decl.top_level_decl.directives,
2781 old_node->data.type_decl.top_level_decl.directives, next_node_index);
2782 clone_subtree_field(&new_node->data.type_decl.child_type, old_node->data.type_decl.child_type, next_node_index);2691 clone_subtree_field(&new_node->data.type_decl.child_type, old_node->data.type_decl.child_type, next_node_index);
2783 break;2692 break;
2784 case NodeTypeErrorValueDecl:2693 case NodeTypeErrorValueDecl:
...@@ -2832,8 +2741,6 @@ AstNode *ast_clone_subtree_special(AstNode *old_node, uint32_t *next_node_index,...@@ -2832,8 +2741,6 @@ AstNode *ast_clone_subtree_special(AstNode *old_node, uint32_t *next_node_index,
2832 break;2741 break;
2833 case NodeTypeUse:2742 case NodeTypeUse:
2834 clone_subtree_field(&new_node->data.use.expr, old_node->data.use.expr, next_node_index);2743 clone_subtree_field(&new_node->data.use.expr, old_node->data.use.expr, next_node_index);
2835 clone_subtree_list_ptr(&new_node->data.use.top_level_decl.directives,
2836 old_node->data.use.top_level_decl.directives, next_node_index);
2837 break;2744 break;
2838 case NodeTypeBoolLiteral:2745 case NodeTypeBoolLiteral:
2839 // none2746 // none
...@@ -2908,13 +2815,9 @@ AstNode *ast_clone_subtree_special(AstNode *old_node, uint32_t *next_node_index,...@@ -2908,13 +2815,9 @@ AstNode *ast_clone_subtree_special(AstNode *old_node, uint32_t *next_node_index,
2908 next_node_index);2815 next_node_index);
2909 clone_subtree_list(&new_node->data.struct_decl.decls, &old_node->data.struct_decl.decls,2816 clone_subtree_list(&new_node->data.struct_decl.decls, &old_node->data.struct_decl.decls,
2910 next_node_index);2817 next_node_index);
2911 clone_subtree_list_ptr(&new_node->data.struct_decl.top_level_decl.directives,
2912 old_node->data.struct_decl.top_level_decl.directives, next_node_index);
2913 break;2818 break;
2914 case NodeTypeStructField:2819 case NodeTypeStructField:
2915 clone_subtree_field(&new_node->data.struct_field.type, old_node->data.struct_field.type, next_node_index);2820 clone_subtree_field(&new_node->data.struct_field.type, old_node->data.struct_field.type, next_node_index);
2916 clone_subtree_list_ptr(&new_node->data.struct_field.top_level_decl.directives,
2917 old_node->data.struct_field.top_level_decl.directives, next_node_index);
2918 break;2821 break;
2919 case NodeTypeContainerInitExpr:2822 case NodeTypeContainerInitExpr:
2920 clone_subtree_field(&new_node->data.container_init_expr.type, old_node->data.container_init_expr.type, next_node_index);2823 clone_subtree_field(&new_node->data.container_init_expr.type, old_node->data.container_init_expr.type, next_node_index);
src/tokenizer.cpp+4
...@@ -109,6 +109,7 @@ struct ZigKeyword {...@@ -109,6 +109,7 @@ struct ZigKeyword {
109static const struct ZigKeyword zig_keywords[] = {109static const struct ZigKeyword zig_keywords[] = {
110 {"asm", TokenIdKeywordAsm},110 {"asm", TokenIdKeywordAsm},
111 {"break", TokenIdKeywordBreak},111 {"break", TokenIdKeywordBreak},
112 {"coldcc", TokenIdKeywordColdCC},
112 {"const", TokenIdKeywordConst},113 {"const", TokenIdKeywordConst},
113 {"continue", TokenIdKeywordContinue},114 {"continue", TokenIdKeywordContinue},
114 {"defer", TokenIdKeywordDefer},115 {"defer", TokenIdKeywordDefer},
...@@ -123,6 +124,7 @@ static const struct ZigKeyword zig_keywords[] = {...@@ -123,6 +124,7 @@ static const struct ZigKeyword zig_keywords[] = {
123 {"goto", TokenIdKeywordGoto},124 {"goto", TokenIdKeywordGoto},
124 {"if", TokenIdKeywordIf},125 {"if", TokenIdKeywordIf},
125 {"inline", TokenIdKeywordInline},126 {"inline", TokenIdKeywordInline},
127 {"nakedcc", TokenIdKeywordNakedCC},
126 {"noalias", TokenIdKeywordNoAlias},128 {"noalias", TokenIdKeywordNoAlias},
127 {"null", TokenIdKeywordNull},129 {"null", TokenIdKeywordNull},
128 {"pub", TokenIdKeywordPub},130 {"pub", TokenIdKeywordPub},
...@@ -1476,6 +1478,8 @@ const char * token_name(TokenId id) {...@@ -1476,6 +1478,8 @@ const char * token_name(TokenId id) {
1476 case TokenIdKeywordType: return "type";1478 case TokenIdKeywordType: return "type";
1477 case TokenIdKeywordInline: return "inline";1479 case TokenIdKeywordInline: return "inline";
1478 case TokenIdKeywordDefer: return "defer";1480 case TokenIdKeywordDefer: return "defer";
1481 case TokenIdKeywordColdCC: return "coldcc";
1482 case TokenIdKeywordNakedCC: return "nakedcc";
1479 case TokenIdLParen: return "(";1483 case TokenIdLParen: return "(";
1480 case TokenIdRParen: return ")";1484 case TokenIdRParen: return ")";
1481 case TokenIdComma: return ",";1485 case TokenIdComma: return ",";
src/tokenizer.hpp+2
...@@ -46,6 +46,8 @@ enum TokenId {...@@ -46,6 +46,8 @@ enum TokenId {
46 TokenIdKeywordInline,46 TokenIdKeywordInline,
47 TokenIdKeywordDefer,47 TokenIdKeywordDefer,
48 TokenIdKeywordThis,48 TokenIdKeywordThis,
49 TokenIdKeywordColdCC,
50 TokenIdKeywordNakedCC,
49 TokenIdLParen,51 TokenIdLParen,
50 TokenIdRParen,52 TokenIdRParen,
51 TokenIdComma,53 TokenIdComma,
std/bootstrap.zig+5-4
...@@ -13,9 +13,9 @@ const want_main_symbol = !want_start_symbol;...@@ -13,9 +13,9 @@ const want_main_symbol = !want_start_symbol;
13var argc: usize = undefined;13var argc: usize = undefined;
14var argv: &&u8 = undefined;14var argv: &&u8 = undefined;
1515
16#attribute("naked")16export nakedcc fn _start() -> unreachable {
17#condition(want_start_symbol)17 @setFnVisible(this, want_start_symbol);
18export fn _start() -> unreachable {18
19 switch (@compileVar("arch")) {19 switch (@compileVar("arch")) {
20 x86_64 => {20 x86_64 => {
21 argc = asm("mov (%%rsp), %[argc]": [argc] "=r" (-> usize));21 argc = asm("mov (%%rsp), %[argc]": [argc] "=r" (-> usize));
...@@ -44,8 +44,9 @@ fn callMainAndExit() -> unreachable {...@@ -44,8 +44,9 @@ fn callMainAndExit() -> unreachable {
44 linux.exit(0);44 linux.exit(0);
45}45}
4646
47#condition(want_main_symbol)
48export fn main(c_argc: i32, c_argv: &&u8) -> i32 {47export fn main(c_argc: i32, c_argv: &&u8) -> i32 {
48 @setFnVisible(this, want_main_symbol);
49
49 argc = usize(c_argc);50 argc = usize(c_argc);
50 argv = c_argv;51 argv = c_argv;
51 callMain() %% return 1;52 callMain() %% return 1;
std/builtin.zig+4-2
...@@ -1,8 +1,9 @@...@@ -1,8 +1,9 @@
1// These functions are provided when not linking against libc because LLVM1// These functions are provided when not linking against libc because LLVM
2// sometimes generates code that calls them.2// sometimes generates code that calls them.
33
4#debug_safety(false)
5export fn memset(dest: &u8, c: u8, n: usize) -> &u8 {4export fn memset(dest: &u8, c: u8, n: usize) -> &u8 {
5 @setDebugSafety(this, false);
6
6 var index: usize = 0;7 var index: usize = 0;
7 while (index != n) {8 while (index != n) {
8 dest[index] = c;9 dest[index] = c;
...@@ -11,8 +12,9 @@ export fn memset(dest: &u8, c: u8, n: usize) -> &u8 {...@@ -11,8 +12,9 @@ export fn memset(dest: &u8, c: u8, n: usize) -> &u8 {
11 return dest;12 return dest;
12}13}
1314
14#debug_safety(false)
15export fn memcpy(noalias dest: &u8, noalias src: &const u8, n: usize) -> &u8 {15export fn memcpy(noalias dest: &u8, noalias src: &const u8, n: usize) -> &u8 {
16 @setDebugSafety(this, false);
17
16 var index: usize = 0;18 var index: usize = 0;
17 while (index != n) {19 while (index != n) {
18 dest[index] = src[index];20 dest[index] = src[index];
std/compiler_rt.zig+10-6
...@@ -8,18 +8,19 @@ const udwords = [2]su_int;...@@ -8,18 +8,19 @@ const udwords = [2]su_int;
8const low = if (@compileVar("is_big_endian")) 1 else 0;8const low = if (@compileVar("is_big_endian")) 1 else 0;
9const high = 1 - low;9const high = 1 - low;
1010
11#debug_safety(false)
12export fn __udivdi3(a: du_int, b: du_int) -> du_int {11export fn __udivdi3(a: du_int, b: du_int) -> du_int {
12 @setDebugSafety(this, false);
13 return __udivmoddi4(a, b, null);13 return __udivmoddi4(a, b, null);
14}14}
1515
16#debug_safety(false)
17fn du_int_to_udwords(x: du_int) -> udwords {16fn du_int_to_udwords(x: du_int) -> udwords {
17 @setDebugSafety(this, false);
18 return *(&udwords)(&x);18 return *(&udwords)(&x);
19}19}
2020
21#debug_safety(false)
22export fn __udivmoddi4(a: du_int, b: du_int, maybe_rem: ?&du_int) -> du_int {21export fn __udivmoddi4(a: du_int, b: du_int, maybe_rem: ?&du_int) -> du_int {
22 @setDebugSafety(this, false);
23
23 const n_uword_bits = @sizeOf(su_int) * CHAR_BIT;24 const n_uword_bits = @sizeOf(su_int) * CHAR_BIT;
24 const n_udword_bits = @sizeOf(du_int) * CHAR_BIT;25 const n_udword_bits = @sizeOf(du_int) * CHAR_BIT;
25 var n = du_int_to_udwords(a);26 var n = du_int_to_udwords(a);
...@@ -203,15 +204,17 @@ export fn __udivmoddi4(a: du_int, b: du_int, maybe_rem: ?&du_int) -> du_int {...@@ -203,15 +204,17 @@ export fn __udivmoddi4(a: du_int, b: du_int, maybe_rem: ?&du_int) -> du_int {
203 return *(&du_int)(&q[0]);204 return *(&du_int)(&q[0]);
204}205}
205206
206#debug_safety(false)
207export fn __umoddi3(a: du_int, b: du_int) -> du_int {207export fn __umoddi3(a: du_int, b: du_int) -> du_int {
208 @setDebugSafety(this, false);
209
208 var r: du_int = undefined;210 var r: du_int = undefined;
209 __udivmoddi4(a, b, &r);211 __udivmoddi4(a, b, &r);
210 return r;212 return r;
211}213}
212214
213#attribute("test")
214fn test_umoddi3() {215fn test_umoddi3() {
216 @setFnTest(this, true);
217
215 test_one_umoddi3(0, 1, 0);218 test_one_umoddi3(0, 1, 0);
216 test_one_umoddi3(2, 1, 0);219 test_one_umoddi3(2, 1, 0);
217 test_one_umoddi3(0x8000000000000000, 1, 0x0);220 test_one_umoddi3(0x8000000000000000, 1, 0x0);
...@@ -224,8 +227,9 @@ fn test_one_umoddi3(a: du_int, b: du_int, expected_r: du_int) {...@@ -224,8 +227,9 @@ fn test_one_umoddi3(a: du_int, b: du_int, expected_r: du_int) {
224 assert(r == expected_r);227 assert(r == expected_r);
225}228}
226229
227#attribute("test")
228fn test_udivmoddi4() {230fn test_udivmoddi4() {
231 @setFnTest(this, true);
232
229 const cases = [][4]du_int {233 const cases = [][4]du_int {
230 []du_int{0x0000000000000000, 0x0000000000000001, 0x0000000000000000, 0x0000000000000000},234 []du_int{0x0000000000000000, 0x0000000000000001, 0x0000000000000000, 0x0000000000000000},
231 []du_int{0x0000000080000000, 0x0000000100000001, 0x0000000000000000, 0x0000000080000000},235 []du_int{0x0000000080000000, 0x0000000100000001, 0x0000000000000000, 0x0000000080000000},
std/cstr.zig+6-3
...@@ -126,8 +126,9 @@ pub struct CBuf {...@@ -126,8 +126,9 @@ pub struct CBuf {
126 }126 }
127}127}
128128
129#attribute("test")
130fn testSimpleCBuf() {129fn testSimpleCBuf() {
130 @setFnTest(this, true);
131
131 var buf = %%CBuf.initEmpty(&debug.global_allocator);132 var buf = %%CBuf.initEmpty(&debug.global_allocator);
132 assert(buf.len() == 0);133 assert(buf.len() == 0);
133 %%buf.appendCStr(c"hello");134 %%buf.appendCStr(c"hello");
...@@ -146,12 +147,14 @@ fn testSimpleCBuf() {...@@ -146,12 +147,14 @@ fn testSimpleCBuf() {
146 assert(buf.startsWithCBuf(&buf2));147 assert(buf.startsWithCBuf(&buf2));
147}148}
148149
149#attribute("test")
150fn testCompileTimeStrCmp() {150fn testCompileTimeStrCmp() {
151 @setFnTest(this, true);
152
151 assert(@constEval(cmp(c"aoeu", c"aoez") == -1));153 assert(@constEval(cmp(c"aoeu", c"aoez") == -1));
152}154}
153155
154#attribute("test")
155fn testCompileTimeStrLen() {156fn testCompileTimeStrLen() {
157 @setFnTest(this, true);
158
156 assert(@constEval(len(c"123456789") == 9));159 assert(@constEval(len(c"123456789") == 9));
157}160}
std/hash_map.zig+2-1
...@@ -230,8 +230,9 @@ pub struct SmallHashMap(K: type, V: type, hash: fn(key: K)->u32, eql: fn(a: K, b...@@ -230,8 +230,9 @@ pub struct SmallHashMap(K: type, V: type, hash: fn(key: K)->u32, eql: fn(a: K, b
230 }230 }
231}231}
232232
233#attribute("test")
234fn basicHashMapTest() {233fn basicHashMapTest() {
234 @setFnTest(this, true);
235
235 var map: HashMap(i32, i32, hash_i32, eql_i32) = undefined;236 var map: HashMap(i32, i32, hash_i32, eql_i32) = undefined;
236 map.init(&debug.global_allocator);237 map.init(&debug.global_allocator);
237 defer map.deinit();238 defer map.deinit();
std/io.zig+2-1
...@@ -423,8 +423,9 @@ fn bufPrintUnsigned(inline T: type, out_buf: []u8, x: T) -> usize {...@@ -423,8 +423,9 @@ fn bufPrintUnsigned(inline T: type, out_buf: []u8, x: T) -> usize {
423 return len;423 return len;
424}424}
425425
426#attribute("test")
427fn parseU64DigitTooBig() {426fn parseU64DigitTooBig() {
427 @setFnTest(this, true);
428
428 parseUnsigned(u64, "123a", 10) %% |err| {429 parseUnsigned(u64, "123a", 10) %% |err| {
429 if (err == error.InvalidChar) return;430 if (err == error.InvalidChar) return;
430 @unreachable();431 @unreachable();
std/list.zig+2-1
...@@ -49,8 +49,9 @@ pub struct List(T: type) {...@@ -49,8 +49,9 @@ pub struct List(T: type) {
49 }49 }
50}50}
5151
52#attribute("test")
53fn basicListTest() {52fn basicListTest() {
53 @setFnTest(this, true);
54
54 var list = List(i32).init(&debug.global_allocator);55 var list = List(i32).init(&debug.global_allocator);
55 defer list.deinit();56 defer list.deinit();
5657
std/mem.zig+1-1
...@@ -77,8 +77,8 @@ pub fn sliceAsInt(buf: []u8, is_be: bool, inline T: type) -> T {...@@ -77,8 +77,8 @@ pub fn sliceAsInt(buf: []u8, is_be: bool, inline T: type) -> T {
77 return result;77 return result;
78}78}
7979
80#attribute("test")
81fn testSliceAsInt() {80fn testSliceAsInt() {
81 @setFnTest(this, true);
82 {82 {
83 const buf = []u8{0x00, 0x00, 0x12, 0x34};83 const buf = []u8{0x00, 0x00, 0x12, 0x34};
84 const answer = sliceAsInt(buf[0...], true, u64);84 const answer = sliceAsInt(buf[0...], true, u64);
std/net.zig+8-4
...@@ -180,8 +180,9 @@ error Overflow;...@@ -180,8 +180,9 @@ error Overflow;
180error JunkAtEnd;180error JunkAtEnd;
181error Incomplete;181error Incomplete;
182182
183#static_eval_enable(false)
184fn parseIp6(buf: []const u8) -> %Address {183fn parseIp6(buf: []const u8) -> %Address {
184 @setFnStaticEval(this, false);
185
185 var result: Address = undefined;186 var result: Address = undefined;
186 result.family = linux.AF_INET6;187 result.family = linux.AF_INET6;
187 result.scope_id = 0;188 result.scope_id = 0;
...@@ -318,8 +319,9 @@ fn parseIp4(buf: []const u8) -> %u32 {...@@ -318,8 +319,9 @@ fn parseIp4(buf: []const u8) -> %u32 {
318}319}
319320
320321
321#attribute("test")
322fn testParseIp4() {322fn testParseIp4() {
323 @setFnTest(this, true);
324
323 assert(%%parseIp4("127.0.0.1") == endian.swapIfLe(u32, 0x7f000001));325 assert(%%parseIp4("127.0.0.1") == endian.swapIfLe(u32, 0x7f000001));
324 switch (parseIp4("256.0.0.1")) { Overflow => {}, else => @unreachable(), }326 switch (parseIp4("256.0.0.1")) { Overflow => {}, else => @unreachable(), }
325 switch (parseIp4("x.0.0.1")) { InvalidChar => {}, else => @unreachable(), }327 switch (parseIp4("x.0.0.1")) { InvalidChar => {}, else => @unreachable(), }
...@@ -328,8 +330,9 @@ fn testParseIp4() {...@@ -328,8 +330,9 @@ fn testParseIp4() {
328 switch (parseIp4("100..0.1")) { InvalidChar => {}, else => @unreachable(), }330 switch (parseIp4("100..0.1")) { InvalidChar => {}, else => @unreachable(), }
329}331}
330332
331#attribute("test")
332fn testParseIp6() {333fn testParseIp6() {
334 @setFnTest(this, true);
335
333 {336 {
334 const addr = %%parseIp6("FF01:0:0:0:0:0:0:FB");337 const addr = %%parseIp6("FF01:0:0:0:0:0:0:FB");
335 assert(addr.addr[0] == 0xff);338 assert(addr.addr[0] == 0xff);
...@@ -338,8 +341,9 @@ fn testParseIp6() {...@@ -338,8 +341,9 @@ fn testParseIp6() {
338 }341 }
339}342}
340343
341#attribute("test")
342fn testLookupSimpleIp() {344fn testLookupSimpleIp() {
345 @setFnTest(this, true);
346
343 {347 {
344 var addrs_buf: [5]Address = undefined;348 var addrs_buf: [5]Address = undefined;
345 const addrs = %%lookup("192.168.1.1", addrs_buf);349 const addrs = %%lookup("192.168.1.1", addrs_buf);
std/os.zig+1-2
...@@ -27,8 +27,7 @@ pub fn getRandomBytes(buf: []u8) -> %void {...@@ -27,8 +27,7 @@ pub fn getRandomBytes(buf: []u8) -> %void {
27 }27 }
28}28}
2929
30#attribute("cold")30pub coldcc fn abort() -> unreachable {
31pub fn abort() -> unreachable {
32 switch (@compileVar("os")) {31 switch (@compileVar("os")) {
33 linux, darwin => {32 linux, darwin => {
34 system.raise(system.SIGABRT);33 system.raise(system.SIGABRT);
std/rand.zig+6-3
...@@ -153,8 +153,9 @@ struct MersenneTwister(...@@ -153,8 +153,9 @@ struct MersenneTwister(
153 }153 }
154}154}
155155
156#attribute("test")
157fn testFloat32() {156fn testFloat32() {
157 @setFnTest(this, true);
158
158 var r: Rand = undefined;159 var r: Rand = undefined;
159 r.init(42);160 r.init(42);
160161
...@@ -165,8 +166,9 @@ fn testFloat32() {...@@ -165,8 +166,9 @@ fn testFloat32() {
165 }}166 }}
166}167}
167168
168#attribute("test")
169fn testMT19937_64() {169fn testMT19937_64() {
170 @setFnTest(this, true);
171
170 var rng: MT19937_64 = undefined;172 var rng: MT19937_64 = undefined;
171 rng.init(rand_test.mt64_seed);173 rng.init(rand_test.mt64_seed);
172 for (rand_test.mt64_data) |value| {174 for (rand_test.mt64_data) |value| {
...@@ -174,8 +176,9 @@ fn testMT19937_64() {...@@ -174,8 +176,9 @@ fn testMT19937_64() {
174 }176 }
175}177}
176178
177#attribute("test")
178fn testMT19937_32() {179fn testMT19937_32() {
180 @setFnTest(this, true);
181
179 var rng: MT19937_32 = undefined;182 var rng: MT19937_32 = undefined;
180 rng.init(rand_test.mt32_seed);183 rng.init(rand_test.mt32_seed);
181 for (rand_test.mt32_data) |value| {184 for (rand_test.mt32_data) |value| {
std/str.zig+3-2
...@@ -12,8 +12,9 @@ pub fn sliceEql(inline T: type, a: []const T, b: []const T) -> bool {...@@ -12,8 +12,9 @@ pub fn sliceEql(inline T: type, a: []const T, b: []const T) -> bool {
12 return true;12 return true;
13}13}
1414
15#attribute("test")15fn testStringEquality() {
16fn stringEquality() {16 @setFnTest(this, true);
17
17 assert(eql("abcd", "abcd"));18 assert(eql("abcd", "abcd"));
18 assert(!eql("abcdef", "abZdef"));19 assert(!eql("abcdef", "abZdef"));
19 assert(!eql("abcdefg", "abcdef"));20 assert(!eql("abcdefg", "abcdef"));
test/cases/const_slice_child.zig+10-5
...@@ -2,8 +2,9 @@ const assert = @import("std").debug.assert;...@@ -2,8 +2,9 @@ const assert = @import("std").debug.assert;
22
3var argv: &&const u8 = undefined;3var argv: &&const u8 = undefined;
44
5#attribute("test")
6fn constSliceChild() {5fn constSliceChild() {
6 @setFnTest(this, true);
7
7 const strs = ([]&const u8) {8 const strs = ([]&const u8) {
8 c"one",9 c"one",
9 c"two",10 c"two",
...@@ -13,16 +14,18 @@ fn constSliceChild() {...@@ -13,16 +14,18 @@ fn constSliceChild() {
13 bar(strs.len);14 bar(strs.len);
14}15}
1516
16#static_eval_enable(false)
17fn foo(args: [][]const u8) {17fn foo(args: [][]const u8) {
18 @setFnStaticEval(this, false);
19
18 assert(args.len == 3);20 assert(args.len == 3);
19 assert(streql(args[0], "one"));21 assert(streql(args[0], "one"));
20 assert(streql(args[1], "two"));22 assert(streql(args[1], "two"));
21 assert(streql(args[2], "three"));23 assert(streql(args[2], "three"));
22}24}
2325
24#static_eval_enable(false)
25fn bar(argc: usize) {26fn bar(argc: usize) {
27 @setFnStaticEval(this, false);
28
26 var args: [argc][]u8 = undefined;29 var args: [argc][]u8 = undefined;
27 for (args) |_, i| {30 for (args) |_, i| {
28 const ptr = argv[i];31 const ptr = argv[i];
...@@ -31,15 +34,17 @@ fn bar(argc: usize) {...@@ -31,15 +34,17 @@ fn bar(argc: usize) {
31 foo(args);34 foo(args);
32}35}
3336
34#static_eval_enable(false)
35fn strlen(ptr: &const u8) -> usize {37fn strlen(ptr: &const u8) -> usize {
38 @setFnStaticEval(this, false);
39
36 var count: usize = 0;40 var count: usize = 0;
37 while (ptr[count] != 0; count += 1) {}41 while (ptr[count] != 0; count += 1) {}
38 return count;42 return count;
39}43}
4044
41#static_eval_enable(false)
42fn streql(a: []const u8, b: []const u8) -> bool {45fn streql(a: []const u8, b: []const u8) -> bool {
46 @setFnStaticEval(this, false);
47
43 if (a.len != b.len) return false;48 if (a.len != b.len) return false;
44 for (a) |item, index| {49 for (a) |item, index| {
45 if (b[index] != item) return false;50 if (b[index] != item) return false;
test/cases/enum_to_int.zig+16-9
...@@ -8,17 +8,24 @@ enum Number {...@@ -8,17 +8,24 @@ enum Number {
8 Four,8 Four,
9}9}
1010
11#attribute("test")
12fn enumToInt() {11fn enumToInt() {
13 shouldEqual(Number.Zero, 0);12 @setFnTest(this, true);
14 shouldEqual(Number.One, 1);13
15 shouldEqual(Number.Two, 2);14 shouldEqual(false, Number.Zero, 0);
16 shouldEqual(Number.Three, 3);15 shouldEqual(false, Number.One, 1);
17 shouldEqual(Number.Four, 4);16 shouldEqual(false, Number.Two, 2);
17 shouldEqual(false, Number.Three, 3);
18 shouldEqual(false, Number.Four, 4);
19
20 shouldEqual(true, Number.Zero, 0);
21 shouldEqual(true, Number.One, 1);
22 shouldEqual(true, Number.Two, 2);
23 shouldEqual(true, Number.Three, 3);
24 shouldEqual(true, Number.Four, 4);
18}25}
1926
20// TODO add test with this disabled27fn shouldEqual(inline static_eval: bool, n: Number, expected: usize) {
21#static_eval_enable(false)28 @setFnStaticEval(this, static_eval);
22fn shouldEqual(n: Number, expected: usize) {29
23 assert(usize(n) == expected);30 assert(usize(n) == expected);
24}31}
test/cases/enum_with_members.zig+2-1
...@@ -15,8 +15,9 @@ enum ET {...@@ -15,8 +15,9 @@ enum ET {
15 }15 }
16}16}
1717
18#attribute("test")
19fn enumWithMembers() {18fn enumWithMembers() {
19 @setFnTest(this, true);
20
20 const a = ET.SINT { -42 };21 const a = ET.SINT { -42 };
21 const b = ET.UINT { 42 };22 const b = ET.UINT { 42 };
22 var buf: [20]u8 = undefined;23 var buf: [20]u8 = undefined;
test/cases/max_value_type.zig+2-1
...@@ -1,7 +1,8 @@...@@ -1,7 +1,8 @@
1const assert = @import("std").debug.assert;1const assert = @import("std").debug.assert;
22
3#attribute("test")
4fn maxValueType() {3fn maxValueType() {
4 @setFnTest(this, true);
5
5 // If the type of @maxValue(i32) was i32 then this implicit cast to6 // If the type of @maxValue(i32) was i32 then this implicit cast to
6 // u32 would not work. But since the value is a number literal,7 // u32 would not work. But since the value is a number literal,
7 // it works fine.8 // it works fine.
test/cases/maybe_return.zig+5-3
...@@ -1,15 +1,17 @@...@@ -1,15 +1,17 @@
1const assert = @import("std").debug.assert;1const assert = @import("std").debug.assert;
22
3#attribute("test")
4fn maybeReturn() {3fn maybeReturn() {
4 @setFnTest(this, true);
5
5 assert(??foo(1235));6 assert(??foo(1235));
6 assert(if (const _ ?= foo(null)) false else true);7 assert(if (const _ ?= foo(null)) false else true);
7 assert(!??foo(1234));8 assert(!??foo(1234));
8}9}
910
10// TODO add another function with static_eval_enable(true)11// TODO test static eval maybe return
11#static_eval_enable(false)
12fn foo(x: ?i32) -> ?bool {12fn foo(x: ?i32) -> ?bool {
13 @setFnStaticEval(this, false);
14
13 const value = ?return x;15 const value = ?return x;
14 return value > 1234;16 return value > 1234;
15}17}
test/cases/namespace_depends_on_compile_var/index.zig+2-1
...@@ -1,7 +1,8 @@...@@ -1,7 +1,8 @@
1const assert = @import("std").debug.assert;1const assert = @import("std").debug.assert;
22
3#attribute("test")
4fn namespaceDependsOnCompileVar() {3fn namespaceDependsOnCompileVar() {
4 @setFnTest(this, true);
5
5 if (some_namespace.a_bool) {6 if (some_namespace.a_bool) {
6 assert(some_namespace.a_bool);7 assert(some_namespace.a_bool);
7 } else {8 } else {
test/cases/pub_enum/index.zig+4-2
...@@ -1,16 +1,18 @@...@@ -1,16 +1,18 @@
1const assert = @import("std").debug.assert;1const assert = @import("std").debug.assert;
2const other = @import("other.zig");2const other = @import("other.zig");
33
4#attribute("test")
5fn pubEnum() {4fn pubEnum() {
5 @setFnTest(this, true);
6
6 pubEnumTest(other.APubEnum.Two);7 pubEnumTest(other.APubEnum.Two);
7}8}
8fn pubEnumTest(foo: other.APubEnum) {9fn pubEnumTest(foo: other.APubEnum) {
9 assert(foo == other.APubEnum.Two);10 assert(foo == other.APubEnum.Two);
10}11}
1112
12#attribute("test")
13fn castWithImportedSymbol() {13fn castWithImportedSymbol() {
14 @setFnTest(this, true);
15
14 assert(other.size_t(42) == 42);16 assert(other.size_t(42) == 42);
15}17}
1618
test/cases/return_type_type.zig+2-1
...@@ -10,8 +10,9 @@ pub struct SmallList(inline T: type, inline STATIC_SIZE: usize) {...@@ -10,8 +10,9 @@ pub struct SmallList(inline T: type, inline STATIC_SIZE: usize) {
10 prealloc_items: [STATIC_SIZE]T,10 prealloc_items: [STATIC_SIZE]T,
11}11}
1212
13#attribute("test")
14fn functionWithReturnTypeType() {13fn functionWithReturnTypeType() {
14 @setFnTest(this, true);
15
15 var list: List(i32) = undefined;16 var list: List(i32) = undefined;
16 var list2: List(i32) = undefined;17 var list2: List(i32) = undefined;
17 list.length = 10;18 list.length = 10;
test/cases/sizeof_and_typeof.zig+2-1
...@@ -1,7 +1,8 @@...@@ -1,7 +1,8 @@
1const assert = @import("std").debug.assert;1const assert = @import("std").debug.assert;
22
3#attribute("test")
4fn sizeofAndTypeOf() {3fn sizeofAndTypeOf() {
4 @setFnTest(this, true);
5
5 const y: @typeOf(x) = 120;6 const y: @typeOf(x) = 120;
6 assert(@sizeOf(@typeOf(y)) == 2);7 assert(@sizeOf(@typeOf(y)) == 2);
7}8}
test/cases/struct_contains_slice_of_itself.zig+2-1
...@@ -5,8 +5,9 @@ struct Node {...@@ -5,8 +5,9 @@ struct Node {
5 children: []Node,5 children: []Node,
6}6}
77
8#attribute("test")
9fn structContainsSliceOfItself() {8fn structContainsSliceOfItself() {
9 @setFnTest(this, true);
10
10 var nodes = []Node {11 var nodes = []Node {
11 Node {12 Node {
12 .payload = 1,13 .payload = 1,
test/cases/switch_prong_err_enum.zig+4-2
...@@ -14,16 +14,18 @@ enum FormValue {...@@ -14,16 +14,18 @@ enum FormValue {
14 Other: bool,14 Other: bool,
15}15}
1616
17#static_eval_enable(false)
18fn doThing(form_id: u64) -> %FormValue {17fn doThing(form_id: u64) -> %FormValue {
18 @setFnStaticEval(this, false);
19
19 return switch (form_id) {20 return switch (form_id) {
20 17 => FormValue.Address { %return readOnce() },21 17 => FormValue.Address { %return readOnce() },
21 else => error.InvalidDebugInfo,22 else => error.InvalidDebugInfo,
22 }23 }
23}24}
2425
25#attribute("test")
26fn switchProngReturnsErrorEnum() {26fn switchProngReturnsErrorEnum() {
27 @setFnTest(this, true);
28
27 %%doThing(17);29 %%doThing(17);
28 assert(read_count == 1);30 assert(read_count == 1);
29}31}
test/cases/switch_prong_implicit_cast.zig+4-2
...@@ -7,8 +7,9 @@ enum FormValue {...@@ -7,8 +7,9 @@ enum FormValue {
77
8error Whatever;8error Whatever;
99
10#static_eval_enable(false)
11fn foo(id: u64) -> %FormValue {10fn foo(id: u64) -> %FormValue {
11 @setFnStaticEval(this, false);
12
12 switch (id) {13 switch (id) {
13 2 => FormValue.Two { true },14 2 => FormValue.Two { true },
14 1 => FormValue.One,15 1 => FormValue.One,
...@@ -16,8 +17,9 @@ fn foo(id: u64) -> %FormValue {...@@ -16,8 +17,9 @@ fn foo(id: u64) -> %FormValue {
16 }17 }
17}18}
1819
19#attribute("test")
20fn switchProngImplicitCast() {20fn switchProngImplicitCast() {
21 @setFnTest(this, true);
22
21 const result = switch (%%foo(2)) {23 const result = switch (%%foo(2)) {
22 One => false,24 One => false,
23 Two => |x| x,25 Two => |x| x,
test/cases/this.zig+6-3
...@@ -25,13 +25,15 @@ fn factorial(x: i32) -> i32 {...@@ -25,13 +25,15 @@ fn factorial(x: i32) -> i32 {
25 }25 }
26}26}
2727
28#attribute("test")
29fn thisReferToModuleCallPrivateFn() {28fn thisReferToModuleCallPrivateFn() {
29 @setFnTest(this, true);
30
30 assert(module.add(1, 2) == 3);31 assert(module.add(1, 2) == 3);
31}32}
3233
33#attribute("test")
34fn thisReferToContainer() {34fn thisReferToContainer() {
35 @setFnTest(this, true);
36
35 var pt = Point(i32) {37 var pt = Point(i32) {
36 .x = 12,38 .x = 12,
37 .y = 34,39 .y = 34,
...@@ -41,7 +43,8 @@ fn thisReferToContainer() {...@@ -41,7 +43,8 @@ fn thisReferToContainer() {
41 assert(pt.y == 35);43 assert(pt.y == 35);
42}44}
4345
44#attribute("test")
45fn thisReferToFn() {46fn thisReferToFn() {
47 @setFnTest(this, true);
48
46 assert(factorial(5) == 120);49 assert(factorial(5) == 120);
47}50}
test/cases/var_params.zig+6-3
...@@ -1,7 +1,8 @@...@@ -1,7 +1,8 @@
1const assert = @import("std").debug.assert;1const assert = @import("std").debug.assert;
22
3#attribute("test")
4fn varParams() {3fn varParams() {
4 @setFnTest(this, true);
5
5 assert(max_i32(12, 34) == 34);6 assert(max_i32(12, 34) == 34);
6 assert(max_f64(1.2, 3.4) == 3.4);7 assert(max_f64(1.2, 3.4) == 3.4);
78
...@@ -21,12 +22,14 @@ fn max_f64(a: f64, b: f64) -> f64 {...@@ -21,12 +22,14 @@ fn max_f64(a: f64, b: f64) -> f64 {
21 max(a, b)22 max(a, b)
22}23}
2324
24#static_eval_enable(false)
25fn max_i32_noeval(a: i32, b: i32) -> i32 {25fn max_i32_noeval(a: i32, b: i32) -> i32 {
26 @setFnStaticEval(this, false);
27
26 max(a, b)28 max(a, b)
27}29}
2830
29#static_eval_enable(false)
30fn max_f64_noeval(a: f64, b: f64) -> f64 {31fn max_f64_noeval(a: f64, b: f64) -> f64 {
32 @setFnStaticEval(this, false);
33
31 max(a, b)34 max(a, b)
32}35}
test/cases/zeroes.zig+2-1
...@@ -7,8 +7,9 @@ struct Foo {...@@ -7,8 +7,9 @@ struct Foo {
7 d: ?i32,7 d: ?i32,
8}8}
99
10#attribute("test")
11fn initializing_a_struct_with_zeroes() {10fn initializing_a_struct_with_zeroes() {
11 @setFnTest(this, true);
12
12 const foo: Foo = zeroes;13 const foo: Foo = zeroes;
13 assert(foo.a == 0.0);14 assert(foo.a == 0.0);
14 assert(foo.b == 0);15 assert(foo.b == 0);
test/run_tests.cpp+40-28
...@@ -279,8 +279,9 @@ pub fn bar_function() {...@@ -279,8 +279,9 @@ pub fn bar_function() {
279 )SOURCE");279 )SOURCE");
280280
281 add_source_file(tc, "other.zig", R"SOURCE(281 add_source_file(tc, "other.zig", R"SOURCE(
282#static_eval_enable(false)
283pub fn foo_function() -> bool {282pub fn foo_function() -> bool {
283 @setFnStaticEval(this, false);
284
284 // this one conflicts with the one from foo285 // this one conflicts with the one from foo
285 return true;286 return true;
286}287}
...@@ -686,14 +687,6 @@ fn a() {}...@@ -686,14 +687,6 @@ fn a() {}
686fn a() {}687fn a() {}
687 )SOURCE", 1, ".tmp_source.zig:3:1: error: redefinition of 'a'");688 )SOURCE", 1, ".tmp_source.zig:3:1: error: redefinition of 'a'");
688689
689 add_compile_fail_case("bad directive", R"SOURCE(
690#bogus1("")
691extern fn b();
692#bogus2("")
693fn a() {}
694 )SOURCE", 2, ".tmp_source.zig:2:1: error: invalid directive: 'bogus1'",
695 ".tmp_source.zig:4:1: error: invalid directive: 'bogus2'");
696
697 add_compile_fail_case("unreachable with return", R"SOURCE(690 add_compile_fail_case("unreachable with return", R"SOURCE(
698fn a() -> unreachable {return;}691fn a() -> unreachable {return;}
699 )SOURCE", 1, ".tmp_source.zig:2:24: error: expected type 'unreachable', got 'void'");692 )SOURCE", 1, ".tmp_source.zig:2:24: error: expected type 'unreachable', got 'void'");
...@@ -1280,8 +1273,11 @@ struct Foo {...@@ -1280,8 +1273,11 @@ struct Foo {
1280 x: i32,1273 x: i32,
1281}1274}
1282const a = get_it();1275const a = get_it();
1283#static_eval_enable(false)1276fn get_it() -> Foo {
1284fn get_it() -> Foo { Foo {.x = 13} }1277 @setFnStaticEval(this, false);
1278 Foo {.x = 13}
1279}
1280
1285 )SOURCE", 1, ".tmp_source.zig:5:17: error: unable to evaluate constant expression");1281 )SOURCE", 1, ".tmp_source.zig:5:17: error: unable to evaluate constant expression");
12861282
1287 add_compile_fail_case("undeclared identifier error should mark fn as impure", R"SOURCE(1283 add_compile_fail_case("undeclared identifier error should mark fn as impure", R"SOURCE(
...@@ -1316,8 +1312,11 @@ fn foo() {...@@ -1316,8 +1312,11 @@ fn foo() {
1316 else => 3,1312 else => 3,
1317 };1313 };
1318}1314}
1319#static_eval_enable(false)1315fn bar() -> i32 {
1320fn bar() -> i32 { 2 }1316 @setFnStaticEval(this, false);
1317 2
1318}
1319
1321 )SOURCE", 1, ".tmp_source.zig:3:15: error: unable to infer expression type");1320 )SOURCE", 1, ".tmp_source.zig:3:15: error: unable to infer expression type");
13221321
1323 add_compile_fail_case("atomic orderings of cmpxchg", R"SOURCE(1322 add_compile_fail_case("atomic orderings of cmpxchg", R"SOURCE(
...@@ -1458,7 +1457,6 @@ pub struct SmallList(inline T: type, inline STATIC_SIZE: usize) {...@@ -1458,7 +1457,6 @@ pub struct SmallList(inline T: type, inline STATIC_SIZE: usize) {
1458 prealloc_items: [STATIC_SIZE]T,1457 prealloc_items: [STATIC_SIZE]T,
1459}1458}
14601459
1461#attribute("test")
1462fn function_with_return_type_type() {1460fn function_with_return_type_type() {
1463 var list: List(i32) = undefined;1461 var list: List(i32) = undefined;
1464 list.length = 10;1462 list.length = 10;
...@@ -1623,12 +1621,15 @@ pub fn main(args: [][]u8) -> %void {...@@ -1623,12 +1621,15 @@ pub fn main(args: [][]u8) -> %void {
1623 const a = []i32{1, 2, 3, 4};1621 const a = []i32{1, 2, 3, 4};
1624 baz(bar(a));1622 baz(bar(a));
1625}1623}
1626#static_eval_enable(false)
1627fn bar(a: []i32) -> i32 {1624fn bar(a: []i32) -> i32 {
1625 @setFnStaticEval(this, false);
1626
1628 a[4]1627 a[4]
1629}1628}
1630#static_eval_enable(false)1629fn baz(a: i32) {
1631fn baz(a: i32) {}1630 @setFnStaticEval(this, false);
1631}
1632
1632 )SOURCE");1633 )SOURCE");
16331634
1634 add_debug_safety_case("integer addition overflow", R"SOURCE(1635 add_debug_safety_case("integer addition overflow", R"SOURCE(
...@@ -1637,8 +1638,9 @@ pub fn main(args: [][]u8) -> %void {...@@ -1637,8 +1638,9 @@ pub fn main(args: [][]u8) -> %void {
1637 const x = add(65530, 10);1638 const x = add(65530, 10);
1638 if (x == 0) return error.Whatever;1639 if (x == 0) return error.Whatever;
1639}1640}
1640#static_eval_enable(false)
1641fn add(a: u16, b: u16) -> u16 {1641fn add(a: u16, b: u16) -> u16 {
1642 @setFnStaticEval(this, false);
1643
1642 a + b1644 a + b
1643}1645}
1644 )SOURCE");1646 )SOURCE");
...@@ -1649,8 +1651,9 @@ pub fn main(args: [][]u8) -> %void {...@@ -1649,8 +1651,9 @@ pub fn main(args: [][]u8) -> %void {
1649 const x = sub(10, 20);1651 const x = sub(10, 20);
1650 if (x == 0) return error.Whatever;1652 if (x == 0) return error.Whatever;
1651}1653}
1652#static_eval_enable(false)
1653fn sub(a: u16, b: u16) -> u16 {1654fn sub(a: u16, b: u16) -> u16 {
1655 @setFnStaticEval(this, false);
1656
1654 a - b1657 a - b
1655}1658}
1656 )SOURCE");1659 )SOURCE");
...@@ -1661,8 +1664,9 @@ pub fn main(args: [][]u8) -> %void {...@@ -1661,8 +1664,9 @@ pub fn main(args: [][]u8) -> %void {
1661 const x = mul(300, 6000);1664 const x = mul(300, 6000);
1662 if (x == 0) return error.Whatever;1665 if (x == 0) return error.Whatever;
1663}1666}
1664#static_eval_enable(false)
1665fn mul(a: u16, b: u16) -> u16 {1667fn mul(a: u16, b: u16) -> u16 {
1668 @setFnStaticEval(this, false);
1669
1666 a * b1670 a * b
1667}1671}
1668 )SOURCE");1672 )SOURCE");
...@@ -1673,8 +1677,9 @@ pub fn main(args: [][]u8) -> %void {...@@ -1673,8 +1677,9 @@ pub fn main(args: [][]u8) -> %void {
1673 const x = neg(-32768);1677 const x = neg(-32768);
1674 if (x == 0) return error.Whatever;1678 if (x == 0) return error.Whatever;
1675}1679}
1676#static_eval_enable(false)
1677fn neg(a: i16) -> i16 {1680fn neg(a: i16) -> i16 {
1681 @setFnStaticEval(this, false);
1682
1678 -a1683 -a
1679}1684}
1680 )SOURCE");1685 )SOURCE");
...@@ -1685,8 +1690,9 @@ pub fn main(args: [][]u8) -> %void {...@@ -1685,8 +1690,9 @@ pub fn main(args: [][]u8) -> %void {
1685 const x = shl(-16385, 1);1690 const x = shl(-16385, 1);
1686 if (x == 0) return error.Whatever;1691 if (x == 0) return error.Whatever;
1687}1692}
1688#static_eval_enable(false)
1689fn shl(a: i16, b: i16) -> i16 {1693fn shl(a: i16, b: i16) -> i16 {
1694 @setFnStaticEval(this, false);
1695
1690 a << b1696 a << b
1691}1697}
1692 )SOURCE");1698 )SOURCE");
...@@ -1697,8 +1703,9 @@ pub fn main(args: [][]u8) -> %void {...@@ -1697,8 +1703,9 @@ pub fn main(args: [][]u8) -> %void {
1697 const x = shl(0b0010111111111111, 3);1703 const x = shl(0b0010111111111111, 3);
1698 if (x == 0) return error.Whatever;1704 if (x == 0) return error.Whatever;
1699}1705}
1700#static_eval_enable(false)
1701fn shl(a: u16, b: u16) -> u16 {1706fn shl(a: u16, b: u16) -> u16 {
1707 @setFnStaticEval(this, false);
1708
1702 a << b1709 a << b
1703}1710}
1704 )SOURCE");1711 )SOURCE");
...@@ -1708,8 +1715,9 @@ error Whatever;...@@ -1708,8 +1715,9 @@ error Whatever;
1708pub fn main(args: [][]u8) -> %void {1715pub fn main(args: [][]u8) -> %void {
1709 const x = div0(999, 0);1716 const x = div0(999, 0);
1710}1717}
1711#static_eval_enable(false)
1712fn div0(a: i32, b: i32) -> i32 {1718fn div0(a: i32, b: i32) -> i32 {
1719 @setFnStaticEval(this, false);
1720
1713 a / b1721 a / b
1714}1722}
1715 )SOURCE");1723 )SOURCE");
...@@ -1720,8 +1728,9 @@ pub fn main(args: [][]u8) -> %void {...@@ -1720,8 +1728,9 @@ pub fn main(args: [][]u8) -> %void {
1720 const x = divExact(10, 3);1728 const x = divExact(10, 3);
1721 if (x == 0) return error.Whatever;1729 if (x == 0) return error.Whatever;
1722}1730}
1723#static_eval_enable(false)
1724fn divExact(a: i32, b: i32) -> i32 {1731fn divExact(a: i32, b: i32) -> i32 {
1732 @setFnStaticEval(this, false);
1733
1725 @divExact(a, b)1734 @divExact(a, b)
1726}1735}
1727 )SOURCE");1736 )SOURCE");
...@@ -1732,8 +1741,9 @@ pub fn main(args: [][]u8) -> %void {...@@ -1732,8 +1741,9 @@ pub fn main(args: [][]u8) -> %void {
1732 const x = widenSlice([]u8{1, 2, 3, 4, 5});1741 const x = widenSlice([]u8{1, 2, 3, 4, 5});
1733 if (x.len == 0) return error.Whatever;1742 if (x.len == 0) return error.Whatever;
1734}1743}
1735#static_eval_enable(false)
1736fn widenSlice(slice: []u8) -> []i32 {1744fn widenSlice(slice: []u8) -> []i32 {
1745 @setFnStaticEval(this, false);
1746
1737 ([]i32)(slice)1747 ([]i32)(slice)
1738}1748}
1739 )SOURCE");1749 )SOURCE");
...@@ -1744,8 +1754,9 @@ pub fn main(args: [][]u8) -> %void {...@@ -1744,8 +1754,9 @@ pub fn main(args: [][]u8) -> %void {
1744 const x = shorten_cast(200);1754 const x = shorten_cast(200);
1745 if (x == 0) return error.Whatever;1755 if (x == 0) return error.Whatever;
1746}1756}
1747#static_eval_enable(false)
1748fn shorten_cast(x: i32) -> i8 {1757fn shorten_cast(x: i32) -> i8 {
1758 @setFnStaticEval(this, false);
1759
1749 i8(x)1760 i8(x)
1750}1761}
1751 )SOURCE");1762 )SOURCE");
...@@ -1756,8 +1767,9 @@ pub fn main(args: [][]u8) -> %void {...@@ -1756,8 +1767,9 @@ pub fn main(args: [][]u8) -> %void {
1756 const x = unsigned_cast(-10);1767 const x = unsigned_cast(-10);
1757 if (x == 0) return error.Whatever;1768 if (x == 0) return error.Whatever;
1758}1769}
1759#static_eval_enable(false)
1760fn unsigned_cast(x: i32) -> u32 {1770fn unsigned_cast(x: i32) -> u32 {
1771 @setFnStaticEval(this, false);
1772
1761 u32(x)1773 u32(x)
1762}1774}
1763 )SOURCE");1775 )SOURCE");
test/self_hosted.zig+312-154
...@@ -19,12 +19,15 @@ const test_this = @import("cases/this.zig");...@@ -19,12 +19,15 @@ const test_this = @import("cases/this.zig");
19// normal comment19// normal comment
20/// this is a documentation comment20/// this is a documentation comment
21/// doc comment line 221/// doc comment line 2
22#attribute("test")22fn emptyFunctionWithComments() {
23fn emptyFunctionWithComments() {}23 @setFnTest(this, true);
24}
25
2426
2527
26#attribute("test")
27fn ifStatements() {28fn ifStatements() {
29 @setFnTest(this, true);
30
28 shouldBeEqual(1, 1);31 shouldBeEqual(1, 1);
29 firstEqlThird(2, 1, 2);32 firstEqlThird(2, 1, 2);
30}33}
...@@ -48,8 +51,9 @@ fn firstEqlThird(a: i32, b: i32, c: i32) {...@@ -48,8 +51,9 @@ fn firstEqlThird(a: i32, b: i32, c: i32) {
48}51}
4952
5053
51#attribute("test")
52fn params() {54fn params() {
55 @setFnTest(this, true);
56
53 assert(testParamsAdd(22, 11) == 33);57 assert(testParamsAdd(22, 11) == 33);
54}58}
55fn testParamsAdd(a: i32, b: i32) -> i32 {59fn testParamsAdd(a: i32, b: i32) -> i32 {
...@@ -57,8 +61,9 @@ fn testParamsAdd(a: i32, b: i32) -> i32 {...@@ -57,8 +61,9 @@ fn testParamsAdd(a: i32, b: i32) -> i32 {
57}61}
5862
5963
60#attribute("test")
61fn localVariables() {64fn localVariables() {
65 @setFnTest(this, true);
66
62 testLocVars(2);67 testLocVars(2);
63}68}
64fn testLocVars(b: i32) {69fn testLocVars(b: i32) {
...@@ -66,14 +71,16 @@ fn testLocVars(b: i32) {...@@ -66,14 +71,16 @@ fn testLocVars(b: i32) {
66 if (a + b != 3) @unreachable();71 if (a + b != 3) @unreachable();
67}72}
6873
69#attribute("test")
70fn boolLiterals() {74fn boolLiterals() {
75 @setFnTest(this, true);
76
71 assert(true);77 assert(true);
72 assert(!false);78 assert(!false);
73}79}
7480
75#attribute("test")
76fn voidParameters() {81fn voidParameters() {
82 @setFnTest(this, true);
83
77 voidFun(1, void{}, 2, {});84 voidFun(1, void{}, 2, {});
78}85}
79fn voidFun(a : i32, b : void, c : i32, d : void) {86fn voidFun(a : i32, b : void, c : i32, d : void) {
...@@ -83,8 +90,9 @@ fn voidFun(a : i32, b : void, c : i32, d : void) {...@@ -83,8 +90,9 @@ fn voidFun(a : i32, b : void, c : i32, d : void) {
83 return vv;90 return vv;
84}91}
8592
86#attribute("test")
87fn mutableLocalVariables() {93fn mutableLocalVariables() {
94 @setFnTest(this, true);
95
88 var zero : i32 = 0;96 var zero : i32 = 0;
89 assert(zero == 0);97 assert(zero == 0);
9098
...@@ -95,8 +103,9 @@ fn mutableLocalVariables() {...@@ -95,8 +103,9 @@ fn mutableLocalVariables() {
95 assert(i == 3);103 assert(i == 3);
96}104}
97105
98#attribute("test")
99fn arrays() {106fn arrays() {
107 @setFnTest(this, true);
108
100 var array : [5]u32 = undefined;109 var array : [5]u32 = undefined;
101110
102 var i : u32 = 0;111 var i : u32 = 0;
...@@ -120,8 +129,9 @@ fn getArrayLen(a: []u32) -> usize {...@@ -120,8 +129,9 @@ fn getArrayLen(a: []u32) -> usize {
120 a.len129 a.len
121}130}
122131
123#attribute("test")
124fn shortCircuit() {132fn shortCircuit() {
133 @setFnTest(this, true);
134
125 var hit_1 = false;135 var hit_1 = false;
126 var hit_2 = false;136 var hit_2 = false;
127 var hit_3 = false;137 var hit_3 = false;
...@@ -148,13 +158,15 @@ fn shortCircuit() {...@@ -148,13 +158,15 @@ fn shortCircuit() {
148 assert(hit_4);158 assert(hit_4);
149}159}
150160
151#static_eval_enable(false)
152fn assertRuntime(b: bool) {161fn assertRuntime(b: bool) {
162 @setFnStaticEval(this, false);
163
153 if (!b) @unreachable()164 if (!b) @unreachable()
154}165}
155166
156#attribute("test")
157fn modifyOperators() {167fn modifyOperators() {
168 @setFnTest(this, true);
169
158 var i : i32 = 0;170 var i : i32 = 0;
159 i += 5; assert(i == 5);171 i += 5; assert(i == 5);
160 i -= 2; assert(i == 3);172 i -= 2; assert(i == 3);
...@@ -171,8 +183,9 @@ fn modifyOperators() {...@@ -171,8 +183,9 @@ fn modifyOperators() {
171}183}
172184
173185
174#attribute("test")
175fn separateBlockScopes() {186fn separateBlockScopes() {
187 @setFnTest(this, true);
188
176 {189 {
177 const no_conflict : i32 = 5;190 const no_conflict : i32 = 5;
178 assert(no_conflict == 5);191 assert(no_conflict == 5);
...@@ -186,8 +199,9 @@ fn separateBlockScopes() {...@@ -186,8 +199,9 @@ fn separateBlockScopes() {
186}199}
187200
188201
189#attribute("test")
190fn voidStructFields() {202fn voidStructFields() {
203 @setFnTest(this, true);
204
191 const foo = VoidStructFieldsFoo {205 const foo = VoidStructFieldsFoo {
192 .a = void{},206 .a = void{},
193 .b = 1,207 .b = 1,
...@@ -204,8 +218,9 @@ struct VoidStructFieldsFoo {...@@ -204,8 +218,9 @@ struct VoidStructFieldsFoo {
204218
205219
206220
207#attribute("test")
208pub fn structs() {221pub fn structs() {
222 @setFnTest(this, true);
223
209 var foo : StructFoo = undefined;224 var foo : StructFoo = undefined;
210 @memset(&foo, 0, @sizeOf(StructFoo));225 @memset(&foo, 0, @sizeOf(StructFoo));
211 foo.a += 1;226 foo.a += 1;
...@@ -234,8 +249,9 @@ struct Val {...@@ -234,8 +249,9 @@ struct Val {
234 x: i32,249 x: i32,
235}250}
236251
237#attribute("test")
238fn structPointToSelf() {252fn structPointToSelf() {
253 @setFnTest(this, true);
254
239 var root : Node = undefined;255 var root : Node = undefined;
240 root.val.x = 1;256 root.val.x = 1;
241257
...@@ -248,8 +264,9 @@ fn structPointToSelf() {...@@ -248,8 +264,9 @@ fn structPointToSelf() {
248 assert(node.next.next.next.val.x == 1);264 assert(node.next.next.next.val.x == 1);
249}265}
250266
251#attribute("test")
252fn structByvalAssign() {267fn structByvalAssign() {
268 @setFnTest(this, true);
269
253 var foo1 : StructFoo = undefined;270 var foo1 : StructFoo = undefined;
254 var foo2 : StructFoo = undefined;271 var foo2 : StructFoo = undefined;
255272
...@@ -269,16 +286,18 @@ fn structInitializer() {...@@ -269,16 +286,18 @@ fn structInitializer() {
269const g1 : i32 = 1233 + 1;286const g1 : i32 = 1233 + 1;
270var g2 : i32 = 0;287var g2 : i32 = 0;
271288
272#attribute("test")
273fn globalVariables() {289fn globalVariables() {
290 @setFnTest(this, true);
291
274 assert(g2 == 0);292 assert(g2 == 0);
275 g2 = g1;293 g2 = g1;
276 assert(g2 == 1234);294 assert(g2 == 1234);
277}295}
278296
279297
280#attribute("test")
281fn whileLoop() {298fn whileLoop() {
299 @setFnTest(this, true);
300
282 var i : i32 = 0;301 var i : i32 = 0;
283 while (i < 4) {302 while (i < 4) {
284 i += 1;303 i += 1;
...@@ -295,8 +314,9 @@ fn whileLoop2() -> i32 {...@@ -295,8 +314,9 @@ fn whileLoop2() -> i32 {
295 }314 }
296}315}
297316
298#attribute("test")
299fn voidArrays() {317fn voidArrays() {
318 @setFnTest(this, true);
319
300 var array: [4]void = undefined;320 var array: [4]void = undefined;
301 array[0] = void{};321 array[0] = void{};
302 array[1] = array[2];322 array[1] = array[2];
...@@ -305,8 +325,9 @@ fn voidArrays() {...@@ -305,8 +325,9 @@ fn voidArrays() {
305}325}
306326
307327
308#attribute("test")
309fn threeExprInARow() {328fn threeExprInARow() {
329 @setFnTest(this, true);
330
310 assertFalse(false || false || false);331 assertFalse(false || false || false);
311 assertFalse(true && true && false);332 assertFalse(true && true && false);
312 assertFalse(1 | 2 | 4 != 7);333 assertFalse(1 | 2 | 4 != 7);
...@@ -325,8 +346,9 @@ fn assertFalse(b: bool) {...@@ -325,8 +346,9 @@ fn assertFalse(b: bool) {
325}346}
326347
327348
328#attribute("test")
329fn maybeType() {349fn maybeType() {
350 @setFnTest(this, true);
351
330 const x : ?bool = true;352 const x : ?bool = true;
331353
332 if (const y ?= x) {354 if (const y ?= x) {
...@@ -353,8 +375,9 @@ fn maybeType() {...@@ -353,8 +375,9 @@ fn maybeType() {
353}375}
354376
355377
356#attribute("test")
357fn enumType() {378fn enumType() {
379 @setFnTest(this, true);
380
358 const foo1 = EnumTypeFoo.One {13};381 const foo1 = EnumTypeFoo.One {13};
359 const foo2 = EnumTypeFoo.Two {EnumType { .x = 1234, .y = 5678, }};382 const foo2 = EnumTypeFoo.Two {EnumType { .x = 1234, .y = 5678, }};
360 const bar = EnumTypeBar.B;383 const bar = EnumTypeBar.B;
...@@ -387,8 +410,9 @@ enum EnumTypeBar {...@@ -387,8 +410,9 @@ enum EnumTypeBar {
387}410}
388411
389412
390#attribute("test")
391fn arrayLiteral() {413fn arrayLiteral() {
414 @setFnTest(this, true);
415
392 const hex_mult = []u16{4096, 256, 16, 1};416 const hex_mult = []u16{4096, 256, 16, 1};
393417
394 assert(hex_mult.len == 4);418 assert(hex_mult.len == 4);
...@@ -396,8 +420,9 @@ fn arrayLiteral() {...@@ -396,8 +420,9 @@ fn arrayLiteral() {
396}420}
397421
398422
399#attribute("test")
400fn constNumberLiteral() {423fn constNumberLiteral() {
424 @setFnTest(this, true);
425
401 const one = 1;426 const one = 1;
402 const eleven = ten + one;427 const eleven = ten + one;
403428
...@@ -406,8 +431,9 @@ fn constNumberLiteral() {...@@ -406,8 +431,9 @@ fn constNumberLiteral() {
406const ten = 10;431const ten = 10;
407432
408433
409#attribute("test")
410fn errorValues() {434fn errorValues() {
435 @setFnTest(this, true);
436
411 const a = i32(error.err1);437 const a = i32(error.err1);
412 const b = i32(error.err2);438 const b = i32(error.err2);
413 assert(a != b);439 assert(a != b);
...@@ -417,8 +443,9 @@ error err2;...@@ -417,8 +443,9 @@ error err2;
417443
418444
419445
420#attribute("test")
421fn fnCallOfStructField() {446fn fnCallOfStructField() {
447 @setFnTest(this, true);
448
422 assert(callStructField(Foo {.ptr = aFunc,}) == 13);449 assert(callStructField(Foo {.ptr = aFunc,}) == 13);
423}450}
424451
...@@ -434,8 +461,9 @@ fn callStructField(foo: Foo) -> i32 {...@@ -434,8 +461,9 @@ fn callStructField(foo: Foo) -> i32 {
434461
435462
436463
437#attribute("test")
438fn redefinitionOfErrorValuesAllowed() {464fn redefinitionOfErrorValuesAllowed() {
465 @setFnTest(this, true);
466
439 shouldBeNotEqual(error.AnError, error.SecondError);467 shouldBeNotEqual(error.AnError, error.SecondError);
440}468}
441error AnError;469error AnError;
...@@ -448,8 +476,9 @@ fn shouldBeNotEqual(a: error, b: error) {...@@ -448,8 +476,9 @@ fn shouldBeNotEqual(a: error, b: error) {
448476
449477
450478
451#attribute("test")
452fn constantEnumWithPayload() {479fn constantEnumWithPayload() {
480 @setFnTest(this, true);
481
453 var empty = AnEnumWithPayload.Empty;482 var empty = AnEnumWithPayload.Empty;
454 var full = AnEnumWithPayload.Full {13};483 var full = AnEnumWithPayload.Full {13};
455 shouldBeEmpty(empty);484 shouldBeEmpty(empty);
...@@ -476,8 +505,9 @@ enum AnEnumWithPayload {...@@ -476,8 +505,9 @@ enum AnEnumWithPayload {
476}505}
477506
478507
479#attribute("test")
480fn continueInForLoop() {508fn continueInForLoop() {
509 @setFnTest(this, true);
510
481 const array = []i32 {1, 2, 3, 4, 5};511 const array = []i32 {1, 2, 3, 4, 5};
482 var sum : i32 = 0;512 var sum : i32 = 0;
483 for (array) |x| {513 for (array) |x| {
...@@ -491,8 +521,9 @@ fn continueInForLoop() {...@@ -491,8 +521,9 @@ fn continueInForLoop() {
491}521}
492522
493523
494#attribute("test")
495fn castBoolToInt() {524fn castBoolToInt() {
525 @setFnTest(this, true);
526
496 const t = true;527 const t = true;
497 const f = false;528 const f = false;
498 assert(i32(t) == i32(1));529 assert(i32(t) == i32(1));
...@@ -506,8 +537,9 @@ fn nonConstCastBoolToInt(t: bool, f: bool) {...@@ -506,8 +537,9 @@ fn nonConstCastBoolToInt(t: bool, f: bool) {
506}537}
507538
508539
509#attribute("test")
510fn switchOnEnum() {540fn switchOnEnum() {
541 @setFnTest(this, true);
542
511 const fruit = Fruit.Orange;543 const fruit = Fruit.Orange;
512 nonConstSwitchOnEnum(fruit);544 nonConstSwitchOnEnum(fruit);
513}545}
...@@ -516,8 +548,9 @@ enum Fruit {...@@ -516,8 +548,9 @@ enum Fruit {
516 Orange,548 Orange,
517 Banana,549 Banana,
518}550}
519#static_eval_enable(false)
520fn nonConstSwitchOnEnum(fruit: Fruit) {551fn nonConstSwitchOnEnum(fruit: Fruit) {
552 @setFnStaticEval(this, false);
553
521 switch (fruit) {554 switch (fruit) {
522 Apple => @unreachable(),555 Apple => @unreachable(),
523 Orange => {},556 Orange => {},
...@@ -525,12 +558,14 @@ fn nonConstSwitchOnEnum(fruit: Fruit) {...@@ -525,12 +558,14 @@ fn nonConstSwitchOnEnum(fruit: Fruit) {
525 }558 }
526}559}
527560
528#attribute("test")
529fn switchStatement() {561fn switchStatement() {
562 @setFnTest(this, true);
563
530 nonConstSwitch(SwitchStatmentFoo.C);564 nonConstSwitch(SwitchStatmentFoo.C);
531}565}
532#static_eval_enable(false)
533fn nonConstSwitch(foo: SwitchStatmentFoo) {566fn nonConstSwitch(foo: SwitchStatmentFoo) {
567 @setFnStaticEval(this, false);
568
534 const val: i32 = switch (foo) {569 const val: i32 = switch (foo) {
535 A => 1,570 A => 1,
536 B => 2,571 B => 2,
...@@ -547,8 +582,9 @@ enum SwitchStatmentFoo {...@@ -547,8 +582,9 @@ enum SwitchStatmentFoo {
547}582}
548583
549584
550#attribute("test")
551fn switchProngWithVar() {585fn switchProngWithVar() {
586 @setFnTest(this, true);
587
552 switchProngWithVarFn(SwitchProngWithVarEnum.One {13});588 switchProngWithVarFn(SwitchProngWithVarEnum.One {13});
553 switchProngWithVarFn(SwitchProngWithVarEnum.Two {13.0});589 switchProngWithVarFn(SwitchProngWithVarEnum.Two {13.0});
554 switchProngWithVarFn(SwitchProngWithVarEnum.Meh);590 switchProngWithVarFn(SwitchProngWithVarEnum.Meh);
...@@ -558,8 +594,9 @@ enum SwitchProngWithVarEnum {...@@ -558,8 +594,9 @@ enum SwitchProngWithVarEnum {
558 Two: f32,594 Two: f32,
559 Meh,595 Meh,
560}596}
561#static_eval_enable(false)
562fn switchProngWithVarFn(a: SwitchProngWithVarEnum) {597fn switchProngWithVarFn(a: SwitchProngWithVarEnum) {
598 @setFnStaticEval(this, false);
599
563 switch(a) {600 switch(a) {
564 One => |x| {601 One => |x| {
565 if (x != 13) @unreachable();602 if (x != 13) @unreachable();
...@@ -574,13 +611,15 @@ fn switchProngWithVarFn(a: SwitchProngWithVarEnum) {...@@ -574,13 +611,15 @@ fn switchProngWithVarFn(a: SwitchProngWithVarEnum) {
574}611}
575612
576613
577#attribute("test")
578fn errReturnInAssignment() {614fn errReturnInAssignment() {
615 @setFnTest(this, true);
616
579 %%doErrReturnInAssignment();617 %%doErrReturnInAssignment();
580}618}
581619
582#static_eval_enable(false)
583fn doErrReturnInAssignment() -> %void {620fn doErrReturnInAssignment() -> %void {
621 @setFnStaticEval(this, false);
622
584 var x : i32 = undefined;623 var x : i32 = undefined;
585 x = %return makeANonErr();624 x = %return makeANonErr();
586}625}
...@@ -591,15 +630,17 @@ fn makeANonErr() -> %i32 {...@@ -591,15 +630,17 @@ fn makeANonErr() -> %i32 {
591630
592631
593632
594#attribute("test")
595fn rhsMaybeUnwrapReturn() {633fn rhsMaybeUnwrapReturn() {
634 @setFnTest(this, true);
635
596 const x = ?true;636 const x = ?true;
597 const y = x ?? return;637 const y = x ?? return;
598}638}
599639
600640
601#attribute("test")
602fn implicitCastFnUnreachableReturn() {641fn implicitCastFnUnreachableReturn() {
642 @setFnTest(this, true);
643
603 wantsFnWithVoid(fnWithUnreachable);644 wantsFnWithVoid(fnWithUnreachable);
604}645}
605646
...@@ -610,15 +651,17 @@ fn fnWithUnreachable() -> unreachable {...@@ -610,15 +651,17 @@ fn fnWithUnreachable() -> unreachable {
610}651}
611652
612653
613#attribute("test")
614fn explicitCastMaybePointers() {654fn explicitCastMaybePointers() {
655 @setFnTest(this, true);
656
615 const a: ?&i32 = undefined;657 const a: ?&i32 = undefined;
616 const b: ?&f32 = (?&f32)(a);658 const b: ?&f32 = (?&f32)(a);
617}659}
618660
619661
620#attribute("test")
621fn constExprEvalOnSingleExprBlocks() {662fn constExprEvalOnSingleExprBlocks() {
663 @setFnTest(this, true);
664
622 assert(constExprEvalOnSingleExprBlocksFn(1, true) == 3);665 assert(constExprEvalOnSingleExprBlocksFn(1, true) == 3);
623}666}
624667
...@@ -635,14 +678,16 @@ fn constExprEvalOnSingleExprBlocksFn(x: i32, b: bool) -> i32 {...@@ -635,14 +678,16 @@ fn constExprEvalOnSingleExprBlocksFn(x: i32, b: bool) -> i32 {
635}678}
636679
637680
638#attribute("test")
639fn builtinConstEval() {681fn builtinConstEval() {
682 @setFnTest(this, true);
683
640 const x : i32 = @constEval(1 + 2 + 3);684 const x : i32 = @constEval(1 + 2 + 3);
641 assert(x == @constEval(6));685 assert(x == @constEval(6));
642}686}
643687
644#attribute("test")
645fn slicing() {688fn slicing() {
689 @setFnTest(this, true);
690
646 var array : [20]i32 = undefined;691 var array : [20]i32 = undefined;
647692
648 array[5] = 1234;693 array[5] = 1234;
...@@ -659,8 +704,9 @@ fn slicing() {...@@ -659,8 +704,9 @@ fn slicing() {
659}704}
660705
661706
662#attribute("test")
663fn memcpyAndMemsetIntrinsics() {707fn memcpyAndMemsetIntrinsics() {
708 @setFnTest(this, true);
709
664 var foo : [20]u8 = undefined;710 var foo : [20]u8 = undefined;
665 var bar : [20]u8 = undefined;711 var bar : [20]u8 = undefined;
666712
...@@ -671,31 +717,36 @@ fn memcpyAndMemsetIntrinsics() {...@@ -671,31 +717,36 @@ fn memcpyAndMemsetIntrinsics() {
671}717}
672718
673719
674#attribute("test")720fn arrayDotLenConstExpr() {
675fn arrayDotLenConstExpr() { }721 @setFnTest(this, true);
722}
723
676struct ArrayDotLenConstExpr {724struct ArrayDotLenConstExpr {
677 y: [@constEval(some_array.len)]u8,725 y: [@constEval(some_array.len)]u8,
678}726}
679const some_array = []u8 {0, 1, 2, 3};727const some_array = []u8 {0, 1, 2, 3};
680728
681729
682#attribute("test")
683fn countLeadingZeroes() {730fn countLeadingZeroes() {
731 @setFnTest(this, true);
732
684 assert(@clz(u8, 0b00001010) == 4);733 assert(@clz(u8, 0b00001010) == 4);
685 assert(@clz(u8, 0b10001010) == 0);734 assert(@clz(u8, 0b10001010) == 0);
686 assert(@clz(u8, 0b00000000) == 8);735 assert(@clz(u8, 0b00000000) == 8);
687}736}
688737
689#attribute("test")
690fn countTrailingZeroes() {738fn countTrailingZeroes() {
739 @setFnTest(this, true);
740
691 assert(@ctz(u8, 0b10100000) == 5);741 assert(@ctz(u8, 0b10100000) == 5);
692 assert(@ctz(u8, 0b10001010) == 1);742 assert(@ctz(u8, 0b10001010) == 1);
693 assert(@ctz(u8, 0b00000000) == 8);743 assert(@ctz(u8, 0b00000000) == 8);
694}744}
695745
696746
697#attribute("test")
698fn multilineString() {747fn multilineString() {
748 @setFnTest(this, true);
749
699 const s1 =750 const s1 =
700 \\one751 \\one
701 \\two)752 \\two)
...@@ -705,8 +756,9 @@ fn multilineString() {...@@ -705,8 +756,9 @@ fn multilineString() {
705 assert(str.eql(s1, s2));756 assert(str.eql(s1, s2));
706}757}
707758
708#attribute("test")
709fn multilineCString() {759fn multilineCString() {
760 @setFnTest(this, true);
761
710 const s1 =762 const s1 =
711 c\\one763 c\\one
712 c\\two)764 c\\two)
...@@ -718,8 +770,9 @@ fn multilineCString() {...@@ -718,8 +770,9 @@ fn multilineCString() {
718770
719771
720772
721#attribute("test")
722fn simpleGenericFn() {773fn simpleGenericFn() {
774 @setFnTest(this, true);
775
723 assert(max(i32, 3, -1) == 3);776 assert(max(i32, 3, -1) == 3);
724 assert(max(f32, 0.123, 0.456) == 0.456);777 assert(max(f32, 0.123, 0.456) == 0.456);
725 assert(add(2, 3) == 5);778 assert(add(2, 3) == 5);
...@@ -734,8 +787,9 @@ fn add(inline a: i32, b: i32) -> i32 {...@@ -734,8 +787,9 @@ fn add(inline a: i32, b: i32) -> i32 {
734}787}
735788
736789
737#attribute("test")
738fn constantEqualFunctionPointers() {790fn constantEqualFunctionPointers() {
791 @setFnTest(this, true);
792
739 const alias = emptyFn;793 const alias = emptyFn;
740 assert(@constEval(emptyFn == alias));794 assert(@constEval(emptyFn == alias));
741}795}
...@@ -743,44 +797,50 @@ fn constantEqualFunctionPointers() {...@@ -743,44 +797,50 @@ fn constantEqualFunctionPointers() {
743fn emptyFn() {}797fn emptyFn() {}
744798
745799
746#attribute("test")
747fn genericMallocFree() {800fn genericMallocFree() {
801 @setFnTest(this, true);
802
748 const a = %%memAlloc(u8, 10);803 const a = %%memAlloc(u8, 10);
749 memFree(u8, a);804 memFree(u8, a);
750}805}
751const some_mem : [100]u8 = undefined;806const some_mem : [100]u8 = undefined;
752#static_eval_enable(false)
753fn memAlloc(inline T: type, n: usize) -> %[]T {807fn memAlloc(inline T: type, n: usize) -> %[]T {
808 @setFnStaticEval(this, false);
809
754 return (&T)(&some_mem[0])[0...n];810 return (&T)(&some_mem[0])[0...n];
755}811}
756fn memFree(inline T: type, mem: []T) { }812fn memFree(inline T: type, mem: []T) { }
757813
758814
759#attribute("test")
760fn callFnWithEmptyString() {815fn callFnWithEmptyString() {
816 @setFnTest(this, true);
817
761 acceptsString("");818 acceptsString("");
762}819}
763820
764fn acceptsString(foo: []u8) { }821fn acceptsString(foo: []u8) { }
765822
766823
767#attribute("test")
768fn hexEscape() {824fn hexEscape() {
825 @setFnTest(this, true);
826
769 assert(str.eql("\x68\x65\x6c\x6c\x6f", "hello"));827 assert(str.eql("\x68\x65\x6c\x6c\x6f", "hello"));
770}828}
771829
772830
773error AnError;831error AnError;
774error ALongerErrorName;832error ALongerErrorName;
775#attribute("test")
776fn errorNameString() {833fn errorNameString() {
834 @setFnTest(this, true);
835
777 assert(str.eql(@errorName(error.AnError), "AnError"));836 assert(str.eql(@errorName(error.AnError), "AnError"));
778 assert(str.eql(@errorName(error.ALongerErrorName), "ALongerErrorName"));837 assert(str.eql(@errorName(error.ALongerErrorName), "ALongerErrorName"));
779}838}
780839
781840
782#attribute("test")
783fn gotoAndLabels() {841fn gotoAndLabels() {
842 @setFnTest(this, true);
843
784 gotoLoop();844 gotoLoop();
785 assert(goto_counter == 10);845 assert(goto_counter == 10);
786}846}
...@@ -799,12 +859,14 @@ var goto_counter: i32 = 0;...@@ -799,12 +859,14 @@ var goto_counter: i32 = 0;
799859
800860
801861
802#attribute("test")
803fn gotoLeaveDeferScope() {862fn gotoLeaveDeferScope() {
863 @setFnTest(this, true);
864
804 testGotoLeaveDeferScope(true);865 testGotoLeaveDeferScope(true);
805}866}
806#static_eval_enable(false)
807fn testGotoLeaveDeferScope(b: bool) {867fn testGotoLeaveDeferScope(b: bool) {
868 @setFnStaticEval(this, false);
869
808 var it_worked = false;870 var it_worked = false;
809871
810 goto entry;872 goto entry;
...@@ -819,8 +881,9 @@ entry:...@@ -819,8 +881,9 @@ entry:
819}881}
820882
821883
822#attribute("test")
823fn castUndefined() {884fn castUndefined() {
885 @setFnTest(this, true);
886
824 const array: [100]u8 = undefined;887 const array: [100]u8 = undefined;
825 const slice = ([]u8)(array);888 const slice = ([]u8)(array);
826 testCastUndefined(slice);889 testCastUndefined(slice);
...@@ -828,8 +891,9 @@ fn castUndefined() {...@@ -828,8 +891,9 @@ fn castUndefined() {
828fn testCastUndefined(x: []u8) {}891fn testCastUndefined(x: []u8) {}
829892
830893
831#attribute("test")
832fn castSmallUnsignedToLargerSigned() {894fn castSmallUnsignedToLargerSigned() {
895 @setFnTest(this, true);
896
833 assert(castSmallUnsignedToLargerSigned1(200) == i16(200));897 assert(castSmallUnsignedToLargerSigned1(200) == i16(200));
834 assert(castSmallUnsignedToLargerSigned2(9999) == i64(9999));898 assert(castSmallUnsignedToLargerSigned2(9999) == i64(9999));
835}899}
...@@ -837,8 +901,9 @@ fn castSmallUnsignedToLargerSigned1(x: u8) -> i16 { x }...@@ -837,8 +901,9 @@ fn castSmallUnsignedToLargerSigned1(x: u8) -> i16 { x }
837fn castSmallUnsignedToLargerSigned2(x: u16) -> i64 { x }901fn castSmallUnsignedToLargerSigned2(x: u16) -> i64 { x }
838902
839903
840#attribute("test")
841fn implicitCastAfterUnreachable() {904fn implicitCastAfterUnreachable() {
905 @setFnTest(this, true);
906
842 assert(outer() == 1234);907 assert(outer() == 1234);
843}908}
844fn inner() -> i32 { 1234 }909fn inner() -> i32 { 1234 }
...@@ -847,8 +912,9 @@ fn outer() -> i64 {...@@ -847,8 +912,9 @@ fn outer() -> i64 {
847}912}
848913
849914
850#attribute("test")
851fn elseIfExpression() {915fn elseIfExpression() {
916 @setFnTest(this, true);
917
852 assert(elseIfExpressionF(1) == 1);918 assert(elseIfExpressionF(1) == 1);
853}919}
854fn elseIfExpressionF(c: u8) -> u8 {920fn elseIfExpressionF(c: u8) -> u8 {
...@@ -861,8 +927,9 @@ fn elseIfExpressionF(c: u8) -> u8 {...@@ -861,8 +927,9 @@ fn elseIfExpressionF(c: u8) -> u8 {
861 }927 }
862}928}
863929
864#attribute("test")
865fn errBinaryOperator() {930fn errBinaryOperator() {
931 @setFnTest(this, true);
932
866 const a = errBinaryOperatorG(true) %% 3;933 const a = errBinaryOperatorG(true) %% 3;
867 const b = errBinaryOperatorG(false) %% 3;934 const b = errBinaryOperatorG(false) %% 3;
868 assert(a == 3);935 assert(a == 3);
...@@ -877,16 +944,18 @@ fn errBinaryOperatorG(x: bool) -> %isize {...@@ -877,16 +944,18 @@ fn errBinaryOperatorG(x: bool) -> %isize {
877 }944 }
878}945}
879946
880#attribute("test")
881fn unwrapSimpleValueFromError() {947fn unwrapSimpleValueFromError() {
948 @setFnTest(this, true);
949
882 const i = %%unwrapSimpleValueFromErrorDo();950 const i = %%unwrapSimpleValueFromErrorDo();
883 assert(i == 13);951 assert(i == 13);
884}952}
885fn unwrapSimpleValueFromErrorDo() -> %isize { 13 }953fn unwrapSimpleValueFromErrorDo() -> %isize { 13 }
886954
887955
888#attribute("test")
889fn storeMemberFunctionInVariable() {956fn storeMemberFunctionInVariable() {
957 @setFnTest(this, true);
958
890 const instance = MemberFnTestFoo { .x = 1234, };959 const instance = MemberFnTestFoo { .x = 1234, };
891 const memberFn = MemberFnTestFoo.member;960 const memberFn = MemberFnTestFoo.member;
892 const result = memberFn(instance);961 const result = memberFn(instance);
...@@ -897,15 +966,17 @@ struct MemberFnTestFoo {...@@ -897,15 +966,17 @@ struct MemberFnTestFoo {
897 fn member(foo: MemberFnTestFoo) -> i32 { foo.x }966 fn member(foo: MemberFnTestFoo) -> i32 { foo.x }
898}967}
899968
900#attribute("test")
901fn callMemberFunctionDirectly() {969fn callMemberFunctionDirectly() {
970 @setFnTest(this, true);
971
902 const instance = MemberFnTestFoo { .x = 1234, };972 const instance = MemberFnTestFoo { .x = 1234, };
903 const result = MemberFnTestFoo.member(instance);973 const result = MemberFnTestFoo.member(instance);
904 assert(result == 1234);974 assert(result == 1234);
905}975}
906976
907#attribute("test")
908fn memberFunctions() {977fn memberFunctions() {
978 @setFnTest(this, true);
979
909 const r = MemberFnRand {.seed = 1234};980 const r = MemberFnRand {.seed = 1234};
910 assert(r.getSeed() == 1234);981 assert(r.getSeed() == 1234);
911}982}
...@@ -916,16 +987,18 @@ struct MemberFnRand {...@@ -916,16 +987,18 @@ struct MemberFnRand {
916 }987 }
917}988}
918989
919#attribute("test")
920fn staticFunctionEvaluation() {990fn staticFunctionEvaluation() {
991 @setFnTest(this, true);
992
921 assert(statically_added_number == 3);993 assert(statically_added_number == 3);
922}994}
923const statically_added_number = staticAdd(1, 2);995const statically_added_number = staticAdd(1, 2);
924fn staticAdd(a: i32, b: i32) -> i32 { a + b }996fn staticAdd(a: i32, b: i32) -> i32 { a + b }
925997
926998
927#attribute("test")
928fn staticallyInitalizedList() {999fn staticallyInitalizedList() {
1000 @setFnTest(this, true);
1001
929 assert(static_point_list[0].x == 1);1002 assert(static_point_list[0].x == 1);
930 assert(static_point_list[0].y == 2);1003 assert(static_point_list[0].y == 2);
931 assert(static_point_list[1].x == 3);1004 assert(static_point_list[1].x == 3);
...@@ -944,8 +1017,9 @@ fn makePoint(x: i32, y: i32) -> Point {...@@ -944,8 +1017,9 @@ fn makePoint(x: i32, y: i32) -> Point {
944}1017}
9451018
9461019
947#attribute("test")
948fn staticEvalRecursive() {1020fn staticEvalRecursive() {
1021 @setFnTest(this, true);
1022
949 assert(some_data.len == 21);1023 assert(some_data.len == 21);
950}1024}
951var some_data: [usize(fibbonaci(7))]u8 = undefined;1025var some_data: [usize(fibbonaci(7))]u8 = undefined;
...@@ -954,8 +1028,9 @@ fn fibbonaci(x: i32) -> i32 {...@@ -954,8 +1028,9 @@ fn fibbonaci(x: i32) -> i32 {
954 return fibbonaci(x - 1) + fibbonaci(x - 2);1028 return fibbonaci(x - 1) + fibbonaci(x - 2);
955}1029}
9561030
957#attribute("test")
958fn staticEvalWhile() {1031fn staticEvalWhile() {
1032 @setFnTest(this, true);
1033
959 assert(static_eval_while_number == 1);1034 assert(static_eval_while_number == 1);
960}1035}
961const static_eval_while_number = staticWhileLoop1();1036const static_eval_while_number = staticWhileLoop1();
...@@ -968,8 +1043,9 @@ fn staticWhileLoop2() -> i32 {...@@ -968,8 +1043,9 @@ fn staticWhileLoop2() -> i32 {
968 }1043 }
969}1044}
9701045
971#attribute("test")
972fn staticEvalListInit() {1046fn staticEvalListInit() {
1047 @setFnTest(this, true);
1048
973 assert(static_vec3.data[2] == 1.0);1049 assert(static_vec3.data[2] == 1.0);
974}1050}
975const static_vec3 = vec3(0.0, 0.0, 1.0);1051const static_vec3 = vec3(0.0, 0.0, 1.0);
...@@ -983,8 +1059,9 @@ pub fn vec3(x: f32, y: f32, z: f32) -> Vec3 {...@@ -983,8 +1059,9 @@ pub fn vec3(x: f32, y: f32, z: f32) -> Vec3 {
983}1059}
9841060
9851061
986#attribute("test")
987fn genericFnWithImplicitCast() {1062fn genericFnWithImplicitCast() {
1063 @setFnTest(this, true);
1064
988 assert(getFirstByte(u8, []u8 {13}) == 13);1065 assert(getFirstByte(u8, []u8 {13}) == 13);
989 assert(getFirstByte(u16, []u16 {0, 13}) == 0);1066 assert(getFirstByte(u16, []u16 {0, 13}) == 0);
990}1067}
...@@ -993,8 +1070,9 @@ fn getFirstByte(inline T: type, mem: []T) -> u8 {...@@ -993,8 +1070,9 @@ fn getFirstByte(inline T: type, mem: []T) -> u8 {
993 getByte((&u8)(&mem[0]))1070 getByte((&u8)(&mem[0]))
994}1071}
9951072
996#attribute("test")
997fn continueAndBreak() {1073fn continueAndBreak() {
1074 @setFnTest(this, true);
1075
998 runContinueAndBreakTest();1076 runContinueAndBreakTest();
999 assert(continue_and_break_counter == 8);1077 assert(continue_and_break_counter == 8);
1000}1078}
...@@ -1013,8 +1091,9 @@ fn runContinueAndBreakTest() {...@@ -1013,8 +1091,9 @@ fn runContinueAndBreakTest() {
1013}1091}
10141092
10151093
1016#attribute("test")
1017fn pointerDereferencing() {1094fn pointerDereferencing() {
1095 @setFnTest(this, true);
1096
1018 var x = i32(3);1097 var x = i32(3);
1019 const y = &x;1098 const y = &x;
10201099
...@@ -1024,16 +1103,18 @@ fn pointerDereferencing() {...@@ -1024,16 +1103,18 @@ fn pointerDereferencing() {
1024 assert(*y == 4);1103 assert(*y == 4);
1025}1104}
10261105
1027#attribute("test")
1028fn constantExpressions() {1106fn constantExpressions() {
1107 @setFnTest(this, true);
1108
1029 var array : [array_size]u8 = undefined;1109 var array : [array_size]u8 = undefined;
1030 assert(@sizeOf(@typeOf(array)) == 20);1110 assert(@sizeOf(@typeOf(array)) == 20);
1031}1111}
1032const array_size : u8 = 20;1112const array_size : u8 = 20;
10331113
10341114
1035#attribute("test")
1036fn minValueAndMaxValue() {1115fn minValueAndMaxValue() {
1116 @setFnTest(this, true);
1117
1037 assert(@maxValue(u8) == 255);1118 assert(@maxValue(u8) == 255);
1038 assert(@maxValue(u16) == 65535);1119 assert(@maxValue(u16) == 65535);
1039 assert(@maxValue(u32) == 4294967295);1120 assert(@maxValue(u32) == 4294967295);
...@@ -1055,8 +1136,9 @@ fn minValueAndMaxValue() {...@@ -1055,8 +1136,9 @@ fn minValueAndMaxValue() {
1055 assert(@minValue(i64) == -9223372036854775808);1136 assert(@minValue(i64) == -9223372036854775808);
1056}1137}
10571138
1058#attribute("test")
1059fn overflowIntrinsics() {1139fn overflowIntrinsics() {
1140 @setFnTest(this, true);
1141
1060 var result: u8 = undefined;1142 var result: u8 = undefined;
1061 assert(@addWithOverflow(u8, 250, 100, &result));1143 assert(@addWithOverflow(u8, 250, 100, &result));
1062 assert(!@addWithOverflow(u8, 100, 150, &result));1144 assert(!@addWithOverflow(u8, 100, 150, &result));
...@@ -1064,8 +1146,9 @@ fn overflowIntrinsics() {...@@ -1064,8 +1146,9 @@ fn overflowIntrinsics() {
1064}1146}
10651147
10661148
1067#attribute("test")
1068fn nestedArrays() {1149fn nestedArrays() {
1150 @setFnTest(this, true);
1151
1069 const array_of_strings = [][]u8 {"hello", "this", "is", "my", "thing"};1152 const array_of_strings = [][]u8 {"hello", "this", "is", "my", "thing"};
1070 for (array_of_strings) |s, i| {1153 for (array_of_strings) |s, i| {
1071 if (i == 0) assert(str.eql(s, "hello"));1154 if (i == 0) assert(str.eql(s, "hello"));
...@@ -1076,21 +1159,24 @@ fn nestedArrays() {...@@ -1076,21 +1159,24 @@ fn nestedArrays() {
1076 }1159 }
1077}1160}
10781161
1079#attribute("test")
1080fn intToPtrCast() {1162fn intToPtrCast() {
1163 @setFnTest(this, true);
1164
1081 const x = isize(13);1165 const x = isize(13);
1082 const y = (&u8)(x);1166 const y = (&u8)(x);
1083 const z = usize(y);1167 const z = usize(y);
1084 assert(z == 13);1168 assert(z == 13);
1085}1169}
10861170
1087#attribute("test")
1088fn stringConcatenation() {1171fn stringConcatenation() {
1172 @setFnTest(this, true);
1173
1089 assert(str.eql("OK" ++ " IT " ++ "WORKED", "OK IT WORKED"));1174 assert(str.eql("OK" ++ " IT " ++ "WORKED", "OK IT WORKED"));
1090}1175}
10911176
1092#attribute("test")
1093fn constantStructWithNegation() {1177fn constantStructWithNegation() {
1178 @setFnTest(this, true);
1179
1094 assert(vertices[0].x == -0.6);1180 assert(vertices[0].x == -0.6);
1095}1181}
1096struct Vertex {1182struct Vertex {
...@@ -1107,8 +1193,9 @@ const vertices = []Vertex {...@@ -1107,8 +1193,9 @@ const vertices = []Vertex {
1107};1193};
11081194
11091195
1110#attribute("test")
1111fn returnWithImplicitCastFromWhileLoop() {1196fn returnWithImplicitCastFromWhileLoop() {
1197 @setFnTest(this, true);
1198
1112 %%returnWithImplicitCastFromWhileLoopTest();1199 %%returnWithImplicitCastFromWhileLoopTest();
1113}1200}
1114fn returnWithImplicitCastFromWhileLoopTest() -> %void {1201fn returnWithImplicitCastFromWhileLoopTest() -> %void {
...@@ -1117,8 +1204,9 @@ fn returnWithImplicitCastFromWhileLoopTest() -> %void {...@@ -1117,8 +1204,9 @@ fn returnWithImplicitCastFromWhileLoopTest() -> %void {
1117 }1204 }
1118}1205}
11191206
1120#attribute("test")
1121fn returnStructByvalFromFunction() {1207fn returnStructByvalFromFunction() {
1208 @setFnTest(this, true);
1209
1122 const bar = makeBar(1234, 5678);1210 const bar = makeBar(1234, 5678);
1123 assert(bar.y == 5678);1211 assert(bar.y == 5678);
1124}1212}
...@@ -1133,8 +1221,9 @@ fn makeBar(x: i32, y: i32) -> Bar {...@@ -1133,8 +1221,9 @@ fn makeBar(x: i32, y: i32) -> Bar {
1133 }1221 }
1134}1222}
11351223
1136#attribute("test")
1137fn functionPointers() {1224fn functionPointers() {
1225 @setFnTest(this, true);
1226
1138 const fns = []@typeOf(fn1) { fn1, fn2, fn3, fn4, };1227 const fns = []@typeOf(fn1) { fn1, fn2, fn3, fn4, };
1139 for (fns) |f, i| {1228 for (fns) |f, i| {
1140 assert(f() == u32(i) + 5);1229 assert(f() == u32(i) + 5);
...@@ -1147,8 +1236,9 @@ fn fn4() -> u32 {8}...@@ -1147,8 +1236,9 @@ fn fn4() -> u32 {8}
11471236
11481237
11491238
1150#attribute("test")
1151fn staticallyInitalizedStruct() {1239fn staticallyInitalizedStruct() {
1240 @setFnTest(this, true);
1241
1152 st_init_str_foo.x += 1;1242 st_init_str_foo.x += 1;
1153 assert(st_init_str_foo.x == 14);1243 assert(st_init_str_foo.x == 14);
1154}1244}
...@@ -1158,8 +1248,9 @@ struct StInitStrFoo {...@@ -1158,8 +1248,9 @@ struct StInitStrFoo {
1158}1248}
1159var st_init_str_foo = StInitStrFoo { .x = 13, .y = true, };1249var st_init_str_foo = StInitStrFoo { .x = 13, .y = true, };
11601250
1161#attribute("test")
1162fn staticallyInitializedArrayLiteral() {1251fn staticallyInitializedArrayLiteral() {
1252 @setFnTest(this, true);
1253
1163 const y : [4]u8 = st_init_arr_lit_x;1254 const y : [4]u8 = st_init_arr_lit_x;
1164 assert(y[3] == 4);1255 assert(y[3] == 4);
1165}1256}
...@@ -1167,8 +1258,9 @@ const st_init_arr_lit_x = []u8{1,2,3,4};...@@ -1167,8 +1258,9 @@ const st_init_arr_lit_x = []u8{1,2,3,4};
11671258
11681259
11691260
1170#attribute("test")
1171fn pointerToVoidReturnType() {1261fn pointerToVoidReturnType() {
1262 @setFnTest(this, true);
1263
1172 %%testPointerToVoidReturnType();1264 %%testPointerToVoidReturnType();
1173}1265}
1174fn testPointerToVoidReturnType() -> %void {1266fn testPointerToVoidReturnType() -> %void {
...@@ -1181,8 +1273,9 @@ fn testPointerToVoidReturnType2() -> &void {...@@ -1181,8 +1273,9 @@ fn testPointerToVoidReturnType2() -> &void {
1181}1273}
11821274
11831275
1184#attribute("test")
1185fn callResultOfIfElseExpression() {1276fn callResultOfIfElseExpression() {
1277 @setFnTest(this, true);
1278
1186 assert(str.eql(f2(true), "a"));1279 assert(str.eql(f2(true), "a"));
1187 assert(str.eql(f2(false), "b"));1280 assert(str.eql(f2(false), "b"));
1188}1281}
...@@ -1193,8 +1286,9 @@ fn fA() -> []u8 { "a" }...@@ -1193,8 +1286,9 @@ fn fA() -> []u8 { "a" }
1193fn fB() -> []u8 { "b" }1286fn fB() -> []u8 { "b" }
11941287
11951288
1196#attribute("test")
1197fn constExpressionEvalHandlingOfVariables() {1289fn constExpressionEvalHandlingOfVariables() {
1290 @setFnTest(this, true);
1291
1198 var x = true;1292 var x = true;
1199 while (x) {1293 while (x) {
1200 x = false;1294 x = false;
...@@ -1203,8 +1297,9 @@ fn constExpressionEvalHandlingOfVariables() {...@@ -1203,8 +1297,9 @@ fn constExpressionEvalHandlingOfVariables() {
12031297
12041298
12051299
1206#attribute("test")
1207fn constantEnumInitializationWithDifferingSizes() {1300fn constantEnumInitializationWithDifferingSizes() {
1301 @setFnTest(this, true);
1302
1208 test3_1(test3_foo);1303 test3_1(test3_foo);
1209 test3_2(test3_bar);1304 test3_2(test3_bar);
1210}1305}
...@@ -1219,8 +1314,9 @@ struct Test3Point {...@@ -1219,8 +1314,9 @@ struct Test3Point {
1219}1314}
1220const test3_foo = Test3Foo.Three{Test3Point {.x = 3, .y = 4}};1315const test3_foo = Test3Foo.Three{Test3Point {.x = 3, .y = 4}};
1221const test3_bar = Test3Foo.Two{13};1316const test3_bar = Test3Foo.Two{13};
1222#static_eval_enable(false)
1223fn test3_1(f: Test3Foo) {1317fn test3_1(f: Test3Foo) {
1318 @setFnStaticEval(this, false);
1319
1224 switch (f) {1320 switch (f) {
1225 Three => |pt| {1321 Three => |pt| {
1226 assert(pt.x == 3);1322 assert(pt.x == 3);
...@@ -1229,8 +1325,9 @@ fn test3_1(f: Test3Foo) {...@@ -1229,8 +1325,9 @@ fn test3_1(f: Test3Foo) {
1229 else => @unreachable(),1325 else => @unreachable(),
1230 }1326 }
1231}1327}
1232#static_eval_enable(false)
1233fn test3_2(f: Test3Foo) {1328fn test3_2(f: Test3Foo) {
1329 @setFnStaticEval(this, false);
1330
1234 switch (f) {1331 switch (f) {
1235 Two => |x| {1332 Two => |x| {
1236 assert(x == 13);1333 assert(x == 13);
...@@ -1241,8 +1338,9 @@ fn test3_2(f: Test3Foo) {...@@ -1241,8 +1338,9 @@ fn test3_2(f: Test3Foo) {
12411338
12421339
12431340
1244#attribute("test")
1245fn whileWithContinueExpr() {1341fn whileWithContinueExpr() {
1342 @setFnTest(this, true);
1343
1246 var sum: i32 = 0;1344 var sum: i32 = 0;
1247 {var i: i32 = 0; while (i < 10; i += 1) {1345 {var i: i32 = 0; while (i < 10; i += 1) {
1248 if (i == 5) continue;1346 if (i == 5) continue;
...@@ -1252,38 +1350,47 @@ fn whileWithContinueExpr() {...@@ -1252,38 +1350,47 @@ fn whileWithContinueExpr() {
1252}1350}
12531351
12541352
1255#attribute("test")
1256fn forLoopWithPointerElemVar() {1353fn forLoopWithPointerElemVar() {
1354 @setFnTest(this, true);
1355
1257 const source = "abcdefg";1356 const source = "abcdefg";
1258 var target: [source.len]u8 = undefined;1357 var target: [source.len]u8 = undefined;
1259 @memcpy(&target[0], &source[0], source.len);1358 @memcpy(&target[0], &source[0], source.len);
1260 mangleString(target);1359 mangleString(target);
1261 assert(str.eql(target, "bcdefgh"));1360 assert(str.eql(target, "bcdefgh"));
1262}1361}
1263#static_eval_enable(false)
1264fn mangleString(s: []u8) {1362fn mangleString(s: []u8) {
1363 @setFnStaticEval(this, false);
1364
1265 for (s) |*c| {1365 for (s) |*c| {
1266 *c += 1;1366 *c += 1;
1267 }1367 }
1268}1368}
12691369
1270#attribute("test")
1271fn emptyStructMethodCall() {1370fn emptyStructMethodCall() {
1371 @setFnTest(this, true);
1372
1272 const es = EmptyStruct{};1373 const es = EmptyStruct{};
1273 assert(es.method() == 1234);1374 assert(es.method() == 1234);
1274}1375}
1275struct EmptyStruct {1376struct EmptyStruct {
1276 #static_eval_enable(false)1377 fn method(es: EmptyStruct) -> i32 {
1277 fn method(es: EmptyStruct) -> i32 { 1234 }1378 @setFnStaticEval(this, false);
1379 1234
1380 }
1381
1278}1382}
12791383
12801384
1281#attribute("test")1385fn @"weird function name"() {
1282fn @"weird function name"() { }1386 @setFnTest(this, true);
1387}
1388
12831389
12841390
1285#attribute("test")
1286fn returnEmptyStructFromFn() {1391fn returnEmptyStructFromFn() {
1392 @setFnTest(this, true);
1393
1287 testReturnEmptyStructFromFn();1394 testReturnEmptyStructFromFn();
1288 testReturnEmptyStructFromFnNoeval();1395 testReturnEmptyStructFromFnNoeval();
1289}1396}
...@@ -1291,13 +1398,15 @@ struct EmptyStruct2 {}...@@ -1291,13 +1398,15 @@ struct EmptyStruct2 {}
1291fn testReturnEmptyStructFromFn() -> EmptyStruct2 {1398fn testReturnEmptyStructFromFn() -> EmptyStruct2 {
1292 EmptyStruct2 {}1399 EmptyStruct2 {}
1293}1400}
1294#static_eval_enable(false)
1295fn testReturnEmptyStructFromFnNoeval() -> EmptyStruct2 {1401fn testReturnEmptyStructFromFnNoeval() -> EmptyStruct2 {
1402 @setFnStaticEval(this, false);
1403
1296 EmptyStruct2 {}1404 EmptyStruct2 {}
1297}1405}
12981406
1299#attribute("test")
1300fn passSliceOfEmptyStructToFn() {1407fn passSliceOfEmptyStructToFn() {
1408 @setFnTest(this, true);
1409
1301 assert(testPassSliceOfEmptyStructToFn([]EmptyStruct2{ EmptyStruct2{} }) == 1);1410 assert(testPassSliceOfEmptyStructToFn([]EmptyStruct2{ EmptyStruct2{} }) == 1);
1302}1411}
1303fn testPassSliceOfEmptyStructToFn(slice: []EmptyStruct2) -> usize {1412fn testPassSliceOfEmptyStructToFn(slice: []EmptyStruct2) -> usize {
...@@ -1305,8 +1414,9 @@ fn testPassSliceOfEmptyStructToFn(slice: []EmptyStruct2) -> usize {...@@ -1305,8 +1414,9 @@ fn testPassSliceOfEmptyStructToFn(slice: []EmptyStruct2) -> usize {
1305}1414}
13061415
13071416
1308#attribute("test")
1309fn pointerComparison() {1417fn pointerComparison() {
1418 @setFnTest(this, true);
1419
1310 const a = ([]u8)("a");1420 const a = ([]u8)("a");
1311 const b = &a;1421 const b = &a;
1312 assert(ptrEql(b, b));1422 assert(ptrEql(b, b));
...@@ -1315,15 +1425,17 @@ fn ptrEql(a: &[]u8, b: &[]u8) -> bool {...@@ -1315,15 +1425,17 @@ fn ptrEql(a: &[]u8, b: &[]u8) -> bool {
1315 a == b1425 a == b
1316}1426}
13171427
1318#attribute("test")
1319fn characterLiterals() {1428fn characterLiterals() {
1429 @setFnTest(this, true);
1430
1320 assert('\'' == single_quote);1431 assert('\'' == single_quote);
1321}1432}
1322const single_quote = '\'';1433const single_quote = '\'';
13231434
13241435
1325#attribute("test")
1326fn switchWithMultipleExpressions() {1436fn switchWithMultipleExpressions() {
1437 @setFnTest(this, true);
1438
1327 const x: i32 = switch (returnsFive()) {1439 const x: i32 = switch (returnsFive()) {
1328 1, 2, 3 => 1,1440 1, 2, 3 => 1,
1329 4, 5, 6 => 2,1441 4, 5, 6 => 2,
...@@ -1331,12 +1443,16 @@ fn switchWithMultipleExpressions() {...@@ -1331,12 +1443,16 @@ fn switchWithMultipleExpressions() {
1331 };1443 };
1332 assert(x == 2);1444 assert(x == 2);
1333}1445}
1334#static_eval_enable(false)1446fn returnsFive() -> i32 {
1335fn returnsFive() -> i32 { 5 }1447 @setFnStaticEval(this, false);
1448 5
1449}
1450
13361451
13371452
1338#attribute("test")
1339fn switchOnErrorUnion() {1453fn switchOnErrorUnion() {
1454 @setFnTest(this, true);
1455
1340 const x = switch (returnsTen()) {1456 const x = switch (returnsTen()) {
1341 Ok => |val| val + 1,1457 Ok => |val| val + 1,
1342 ItBroke, NoMem => 1,1458 ItBroke, NoMem => 1,
...@@ -1347,20 +1463,28 @@ fn switchOnErrorUnion() {...@@ -1347,20 +1463,28 @@ fn switchOnErrorUnion() {
1347error ItBroke;1463error ItBroke;
1348error NoMem;1464error NoMem;
1349error CrappedOut;1465error CrappedOut;
1350#static_eval_enable(false)1466fn returnsTen() -> %i32 {
1351fn returnsTen() -> %i32 { 10 }1467 @setFnStaticEval(this, false);
1468 10
1469}
1470
13521471
13531472
1354#attribute("test")
1355fn boolCmp() {1473fn boolCmp() {
1474 @setFnTest(this, true);
1475
1356 assert(testBoolCmp(true, false) == false);1476 assert(testBoolCmp(true, false) == false);
1357}1477}
1358#static_eval_enable(false)1478fn testBoolCmp(a: bool, b: bool) -> bool {
1359fn testBoolCmp(a: bool, b: bool) -> bool { a == b }1479 @setFnStaticEval(this, false);
1480 a == b
1481}
1482
13601483
13611484
1362#attribute("test")
1363fn takeAddressOfParameter() {1485fn takeAddressOfParameter() {
1486 @setFnTest(this, true);
1487
1364 testTakeAddressOfParameter(12.34);1488 testTakeAddressOfParameter(12.34);
1365 testTakeAddressOfParameterNoeval(12.34);1489 testTakeAddressOfParameterNoeval(12.34);
1366}1490}
...@@ -1368,20 +1492,23 @@ fn testTakeAddressOfParameter(f: f32) {...@@ -1368,20 +1492,23 @@ fn testTakeAddressOfParameter(f: f32) {
1368 const f_ptr = &f;1492 const f_ptr = &f;
1369 assert(*f_ptr == 12.34);1493 assert(*f_ptr == 12.34);
1370}1494}
1371#static_eval_enable(false)
1372fn testTakeAddressOfParameterNoeval(f: f32) {1495fn testTakeAddressOfParameterNoeval(f: f32) {
1496 @setFnStaticEval(this, false);
1497
1373 const f_ptr = &f;1498 const f_ptr = &f;
1374 assert(*f_ptr == 12.34);1499 assert(*f_ptr == 12.34);
1375}1500}
13761501
13771502
1378#attribute("test")
1379fn arrayMultOperator() {1503fn arrayMultOperator() {
1504 @setFnTest(this, true);
1505
1380 assert(str.eql("ab" ** 5, "ababababab"));1506 assert(str.eql("ab" ** 5, "ababababab"));
1381}1507}
13821508
1383#attribute("test")
1384fn stringEscapes() {1509fn stringEscapes() {
1510 @setFnTest(this, true);
1511
1385 assert(str.eql("\"", "\x22"));1512 assert(str.eql("\"", "\x22"));
1386 assert(str.eql("\'", "\x27"));1513 assert(str.eql("\'", "\x27"));
1387 assert(str.eql("\n", "\x0a"));1514 assert(str.eql("\n", "\x0a"));
...@@ -1391,12 +1518,14 @@ fn stringEscapes() {...@@ -1391,12 +1518,14 @@ fn stringEscapes() {
1391 assert(str.eql("\u1234\u0069", "\xe1\x88\xb4\x69"));1518 assert(str.eql("\u1234\u0069", "\xe1\x88\xb4\x69"));
1392}1519}
13931520
1394#attribute("test")
1395fn ifVarMaybePointer() {1521fn ifVarMaybePointer() {
1522 @setFnTest(this, true);
1523
1396 assert(shouldBeAPlus1(Particle {.a = 14, .b = 1, .c = 1, .d = 1}) == 15);1524 assert(shouldBeAPlus1(Particle {.a = 14, .b = 1, .c = 1, .d = 1}) == 15);
1397}1525}
1398#static_eval_enable(false)
1399fn shouldBeAPlus1(p: Particle) -> u64 {1526fn shouldBeAPlus1(p: Particle) -> u64 {
1527 @setFnStaticEval(this, false);
1528
1400 var maybe_particle: ?Particle = p;1529 var maybe_particle: ?Particle = p;
1401 if (const *particle ?= maybe_particle) {1530 if (const *particle ?= maybe_particle) {
1402 particle.a += 1;1531 particle.a += 1;
...@@ -1413,8 +1542,9 @@ struct Particle {...@@ -1413,8 +1542,9 @@ struct Particle {
1413 d: u64,1542 d: u64,
1414}1543}
14151544
1416#attribute("test")
1417fn assignToIfVarPtr() {1545fn assignToIfVarPtr() {
1546 @setFnTest(this, true);
1547
1418 var maybe_bool: ?bool = true;1548 var maybe_bool: ?bool = true;
14191549
1420 if (const *b ?= maybe_bool) {1550 if (const *b ?= maybe_bool) {
...@@ -1424,22 +1554,25 @@ fn assignToIfVarPtr() {...@@ -1424,22 +1554,25 @@ fn assignToIfVarPtr() {
1424 assert(??maybe_bool == false);1554 assert(??maybe_bool == false);
1425}1555}
14261556
1427#attribute("test")
1428fn cmpxchg() {1557fn cmpxchg() {
1558 @setFnTest(this, true);
1559
1429 var x: i32 = 1234;1560 var x: i32 = 1234;
1430 while (!@cmpxchg(&x, 1234, 5678, AtomicOrder.SeqCst, AtomicOrder.SeqCst)) {}1561 while (!@cmpxchg(&x, 1234, 5678, AtomicOrder.SeqCst, AtomicOrder.SeqCst)) {}
1431 assert(x == 5678);1562 assert(x == 5678);
1432}1563}
14331564
1434#attribute("test")
1435fn fence() {1565fn fence() {
1566 @setFnTest(this, true);
1567
1436 var x: i32 = 1234;1568 var x: i32 = 1234;
1437 @fence(AtomicOrder.SeqCst);1569 @fence(AtomicOrder.SeqCst);
1438 x = 5678;1570 x = 5678;
1439}1571}
14401572
1441#attribute("test")
1442fn unsignedWrapping() {1573fn unsignedWrapping() {
1574 @setFnTest(this, true);
1575
1443 testUnsignedWrappingEval(@maxValue(u32));1576 testUnsignedWrappingEval(@maxValue(u32));
1444 testUnsignedWrappingNoeval(@maxValue(u32));1577 testUnsignedWrappingNoeval(@maxValue(u32));
1445}1578}
...@@ -1449,16 +1582,18 @@ fn testUnsignedWrappingEval(x: u32) {...@@ -1449,16 +1582,18 @@ fn testUnsignedWrappingEval(x: u32) {
1449 const orig = zero -% 1;1582 const orig = zero -% 1;
1450 assert(orig == @maxValue(u32));1583 assert(orig == @maxValue(u32));
1451}1584}
1452#static_eval_enable(false)
1453fn testUnsignedWrappingNoeval(x: u32) {1585fn testUnsignedWrappingNoeval(x: u32) {
1586 @setFnStaticEval(this, false);
1587
1454 const zero = x +% 1;1588 const zero = x +% 1;
1455 assert(zero == 0);1589 assert(zero == 0);
1456 const orig = zero -% 1;1590 const orig = zero -% 1;
1457 assert(orig == @maxValue(u32));1591 assert(orig == @maxValue(u32));
1458}1592}
14591593
1460#attribute("test")
1461fn signedWrapping() {1594fn signedWrapping() {
1595 @setFnTest(this, true);
1596
1462 testSignedWrappingEval(@maxValue(i32));1597 testSignedWrappingEval(@maxValue(i32));
1463 testSignedWrappingNoeval(@maxValue(i32));1598 testSignedWrappingNoeval(@maxValue(i32));
1464}1599}
...@@ -1468,16 +1603,18 @@ fn testSignedWrappingEval(x: i32) {...@@ -1468,16 +1603,18 @@ fn testSignedWrappingEval(x: i32) {
1468 const max_val = min_val -% 1;1603 const max_val = min_val -% 1;
1469 assert(max_val == @maxValue(i32));1604 assert(max_val == @maxValue(i32));
1470}1605}
1471#static_eval_enable(false)
1472fn testSignedWrappingNoeval(x: i32) {1606fn testSignedWrappingNoeval(x: i32) {
1607 @setFnStaticEval(this, false);
1608
1473 const min_val = x +% 1;1609 const min_val = x +% 1;
1474 assert(min_val == @minValue(i32));1610 assert(min_val == @minValue(i32));
1475 const max_val = min_val -% 1;1611 const max_val = min_val -% 1;
1476 assert(max_val == @maxValue(i32));1612 assert(max_val == @maxValue(i32));
1477}1613}
14781614
1479#attribute("test")
1480fn negationWrapping() {1615fn negationWrapping() {
1616 @setFnTest(this, true);
1617
1481 testNegationWrappingEval(@minValue(i16));1618 testNegationWrappingEval(@minValue(i16));
1482 testNegationWrappingNoeval(@minValue(i16));1619 testNegationWrappingNoeval(@minValue(i16));
1483}1620}
...@@ -1486,15 +1623,17 @@ fn testNegationWrappingEval(x: i16) {...@@ -1486,15 +1623,17 @@ fn testNegationWrappingEval(x: i16) {
1486 const neg = -%x;1623 const neg = -%x;
1487 assert(neg == -32768);1624 assert(neg == -32768);
1488}1625}
1489#static_eval_enable(false)
1490fn testNegationWrappingNoeval(x: i16) {1626fn testNegationWrappingNoeval(x: i16) {
1627 @setFnStaticEval(this, false);
1628
1491 assert(x == -32768);1629 assert(x == -32768);
1492 const neg = -%x;1630 const neg = -%x;
1493 assert(neg == -32768);1631 assert(neg == -32768);
1494}1632}
14951633
1496#attribute("test")
1497fn shlWrapping() {1634fn shlWrapping() {
1635 @setFnTest(this, true);
1636
1498 testShlWrappingEval(@maxValue(u16));1637 testShlWrappingEval(@maxValue(u16));
1499 testShlWrappingNoeval(@maxValue(u16));1638 testShlWrappingNoeval(@maxValue(u16));
1500}1639}
...@@ -1502,22 +1641,25 @@ fn testShlWrappingEval(x: u16) {...@@ -1502,22 +1641,25 @@ fn testShlWrappingEval(x: u16) {
1502 const shifted = x <<% 1;1641 const shifted = x <<% 1;
1503 assert(shifted == 65534);1642 assert(shifted == 65534);
1504}1643}
1505#static_eval_enable(false)
1506fn testShlWrappingNoeval(x: u16) {1644fn testShlWrappingNoeval(x: u16) {
1645 @setFnStaticEval(this, false);
1646
1507 const shifted = x <<% 1;1647 const shifted = x <<% 1;
1508 assert(shifted == 65534);1648 assert(shifted == 65534);
1509}1649}
15101650
1511#attribute("test")
1512fn shlWithOverflow() {1651fn shlWithOverflow() {
1652 @setFnTest(this, true);
1653
1513 var result: u16 = undefined;1654 var result: u16 = undefined;
1514 assert(@shlWithOverflow(u16, 0b0010111111111111, 3, &result));1655 assert(@shlWithOverflow(u16, 0b0010111111111111, 3, &result));
1515 assert(!@shlWithOverflow(u16, 0b0010111111111111, 2, &result));1656 assert(!@shlWithOverflow(u16, 0b0010111111111111, 2, &result));
1516 assert(result == 0b1011111111111100);1657 assert(result == 0b1011111111111100);
1517}1658}
15181659
1519#attribute("test")
1520fn cStringConcatenation() {1660fn cStringConcatenation() {
1661 @setFnTest(this, true);
1662
1521 const a = c"OK" ++ c" IT " ++ c"WORKED";1663 const a = c"OK" ++ c" IT " ++ c"WORKED";
1522 const b = c"OK IT WORKED";1664 const b = c"OK IT WORKED";
15231665
...@@ -1530,8 +1672,9 @@ fn cStringConcatenation() {...@@ -1530,8 +1672,9 @@ fn cStringConcatenation() {
1530 assert(b[len] == 0);1672 assert(b[len] == 0);
1531}1673}
15321674
1533#attribute("test")
1534fn genericStruct() {1675fn genericStruct() {
1676 @setFnTest(this, true);
1677
1535 var a1 = GenNode(i32) {.value = 13, .next = null,};1678 var a1 = GenNode(i32) {.value = 13, .next = null,};
1536 var b1 = GenNode(bool) {.value = true, .next = null,};1679 var b1 = GenNode(bool) {.value = true, .next = null,};
1537 assert(a1.value == 13);1680 assert(a1.value == 13);
...@@ -1544,8 +1687,9 @@ struct GenNode(T: type) {...@@ -1544,8 +1687,9 @@ struct GenNode(T: type) {
1544 fn getVal(n: &const GenNode(T)) -> T { n.value }1687 fn getVal(n: &const GenNode(T)) -> T { n.value }
1545}1688}
15461689
1547#attribute("test")
1548fn castSliceToU8Slice() {1690fn castSliceToU8Slice() {
1691 @setFnTest(this, true);
1692
1549 assert(@sizeOf(i32) == 4);1693 assert(@sizeOf(i32) == 4);
1550 var big_thing_array = []i32{1, 2, 3, 4};1694 var big_thing_array = []i32{1, 2, 3, 4};
1551 const big_thing_slice: []i32 = big_thing_array;1695 const big_thing_slice: []i32 = big_thing_array;
...@@ -1565,26 +1709,31 @@ fn castSliceToU8Slice() {...@@ -1565,26 +1709,31 @@ fn castSliceToU8Slice() {
1565 assert(bytes[11] == @maxValue(u8));1709 assert(bytes[11] == @maxValue(u8));
1566}1710}
15671711
1568#attribute("test")
1569fn floatDivision() {1712fn floatDivision() {
1713 @setFnTest(this, true);
1714
1570 assert(fdiv32(12.0, 3.0) == 4.0);1715 assert(fdiv32(12.0, 3.0) == 4.0);
1571}1716}
1572#static_eval_enable(false)
1573fn fdiv32(a: f32, b: f32) -> f32 {1717fn fdiv32(a: f32, b: f32) -> f32 {
1718 @setFnStaticEval(this, false);
1719
1574 a / b1720 a / b
1575}1721}
15761722
1577#attribute("test")
1578fn exactDivision() {1723fn exactDivision() {
1724 @setFnTest(this, true);
1725
1579 assert(divExact(55, 11) == 5);1726 assert(divExact(55, 11) == 5);
1580}1727}
1581#static_eval_enable(false)
1582fn divExact(a: u32, b: u32) -> u32 {1728fn divExact(a: u32, b: u32) -> u32 {
1729 @setFnStaticEval(this, false);
1730
1583 @divExact(a, b)1731 @divExact(a, b)
1584}1732}
15851733
1586#attribute("test")
1587fn nullLiteralOutsideFunction() {1734fn nullLiteralOutsideFunction() {
1735 @setFnTest(this, true);
1736
1588 const is_null = if (const _ ?= here_is_a_null_literal.context) false else true;1737 const is_null = if (const _ ?= here_is_a_null_literal.context) false else true;
1589 assert(is_null);1738 assert(is_null);
1590}1739}
...@@ -1595,25 +1744,29 @@ const here_is_a_null_literal = SillyStruct {...@@ -1595,25 +1744,29 @@ const here_is_a_null_literal = SillyStruct {
1595 .context = null,1744 .context = null,
1596};1745};
15971746
1598#attribute("test")
1599fn truncate() {1747fn truncate() {
1748 @setFnTest(this, true);
1749
1600 assert(testTruncate(0x10fd) == 0xfd);1750 assert(testTruncate(0x10fd) == 0xfd);
1601}1751}
1602#static_eval_enable(false)
1603fn testTruncate(x: u32) -> u8 {1752fn testTruncate(x: u32) -> u8 {
1753 @setFnStaticEval(this, false);
1754
1604 @truncate(u8, x)1755 @truncate(u8, x)
1605}1756}
16061757
1607#attribute("test")
1608fn constDeclsInStruct() {1758fn constDeclsInStruct() {
1759 @setFnTest(this, true);
1760
1609 assert(GenericDataThing(3).count_plus_one == 4);1761 assert(GenericDataThing(3).count_plus_one == 4);
1610}1762}
1611struct GenericDataThing(count: isize) {1763struct GenericDataThing(count: isize) {
1612 const count_plus_one = count + 1;1764 const count_plus_one = count + 1;
1613}1765}
16141766
1615#attribute("test")
1616fn useGenericParamInGenericParam() {1767fn useGenericParamInGenericParam() {
1768 @setFnTest(this, true);
1769
1617 assert(aGenericFn(i32, 3, 4) == 7);1770 assert(aGenericFn(i32, 3, 4) == 7);
1618}1771}
1619fn aGenericFn(inline T: type, inline a: T, b: T) -> T {1772fn aGenericFn(inline T: type, inline a: T, b: T) -> T {
...@@ -1621,14 +1774,16 @@ fn aGenericFn(inline T: type, inline a: T, b: T) -> T {...@@ -1621,14 +1774,16 @@ fn aGenericFn(inline T: type, inline a: T, b: T) -> T {
1621}1774}
16221775
16231776
1624#attribute("test")
1625fn unsigned64BitDivision() {1777fn unsigned64BitDivision() {
1778 @setFnTest(this, true);
1779
1626 const result = div(1152921504606846976, 34359738365);1780 const result = div(1152921504606846976, 34359738365);
1627 assert(result.quotient == 33554432);1781 assert(result.quotient == 33554432);
1628 assert(result.remainder == 100663296);1782 assert(result.remainder == 100663296);
1629}1783}
1630#static_eval_enable(false)
1631fn div(a: u64, b: u64) -> DivResult {1784fn div(a: u64, b: u64) -> DivResult {
1785 @setFnStaticEval(this, false);
1786
1632 DivResult {1787 DivResult {
1633 .quotient = a / b,1788 .quotient = a / b,
1634 .remainder = a % b,1789 .remainder = a % b,
...@@ -1639,8 +1794,9 @@ struct DivResult {...@@ -1639,8 +1794,9 @@ struct DivResult {
1639 remainder: u64,1794 remainder: u64,
1640}1795}
16411796
1642#attribute("test")
1643fn intTypeBuiltin() {1797fn intTypeBuiltin() {
1798 @setFnTest(this, true);
1799
1644 assert(@intType(true, 8) == i8);1800 assert(@intType(true, 8) == i8);
1645 assert(@intType(true, 16) == i16);1801 assert(@intType(true, 16) == i16);
1646 assert(@intType(true, 32) == i32);1802 assert(@intType(true, 32) == i32);
...@@ -1670,16 +1826,18 @@ fn intTypeBuiltin() {...@@ -1670,16 +1826,18 @@ fn intTypeBuiltin() {
16701826
1671}1827}
16721828
1673#attribute("test")
1674fn intToEnum() {1829fn intToEnum() {
1830 @setFnTest(this, true);
1831
1675 testIntToEnumEval(3);1832 testIntToEnumEval(3);
1676 testIntToEnumNoeval(3);1833 testIntToEnumNoeval(3);
1677}1834}
1678fn testIntToEnumEval(x: i32) {1835fn testIntToEnumEval(x: i32) {
1679 assert(IntToEnumNumber(x) == IntToEnumNumber.Three);1836 assert(IntToEnumNumber(x) == IntToEnumNumber.Three);
1680}1837}
1681#static_eval_enable(false)
1682fn testIntToEnumNoeval(x: i32) {1838fn testIntToEnumNoeval(x: i32) {
1839 @setFnStaticEval(this, false);
1840
1683 assert(IntToEnumNumber(x) == IntToEnumNumber.Three);1841 assert(IntToEnumNumber(x) == IntToEnumNumber.Three);
1684}1842}
1685enum IntToEnumNumber {1843enum IntToEnumNumber {