authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-01-23 02:14:01-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-01-23 02:14:01-07:00
logc0ea9290c4576f2111c8fc6b2d448f278effd80e
treec4b789b675b0083b3d9c2e32550a0299f2546cf5
parent91d911007b8a12405c084cff53237ac26b1f2c5f

main returns %void


8 files changed, 254 insertions(+), 223 deletions(-)

example/cat/main.zig+1-4
...@@ -4,14 +4,11 @@ import "std.zig";...@@ -4,14 +4,11 @@ import "std.zig";
44
5// Things to do to make this work:5// Things to do to make this work:
6// * var args printing6// * var args printing
7// * %void type7// * update std API
8// * defer8// * defer
9// * %return9// * %return
10// * %% operator10// * %% operator
11// * make main return %void
12// * how to reference error values %.Invalid
13// * cast err type to string11// * cast err type to string
14// * update std API
1512
16pub %.Invalid;13pub %.Invalid;
1714
example/hello_world/hello.zig+1-2
...@@ -2,8 +2,7 @@ export executable "hello";...@@ -2,8 +2,7 @@ export executable "hello";
22
3import "std.zig";3import "std.zig";
44
5pub fn main(args: [][]u8) i32 => {5pub fn main(args: [][]u8) %void => {
6 //stderr.print_str("Hello, world!\n");6 //stderr.print_str("Hello, world!\n");
7 print_str("Hello, world!\n");7 print_str("Hello, world!\n");
8 return 0;
9}8}
example/hello_world/hello_libc.zig+1-1
...@@ -5,7 +5,7 @@ extern {...@@ -5,7 +5,7 @@ extern {
5 fn printf(__format: &const u8, ...) i32;5 fn printf(__format: &const u8, ...) i32;
6}6}
77
8export fn main(argc: i32, argv: &&u8, env: &&u8) i32 => {8export fn main(argc: i32, argv: &&u8) i32 => {
9 printf(c"Hello, world!\n");9 printf(c"Hello, world!\n");
10 return 0;10 return 0;
11}11}
src/all_types.hpp+7-1
...@@ -60,6 +60,11 @@ struct ConstPtrValue {...@@ -60,6 +60,11 @@ struct ConstPtrValue {
60 uint64_t len;60 uint64_t len;
61};61};
6262
63struct ConstErrValue {
64 ErrorTableEntry *err;
65 ConstExprValue *payload;
66};
67
63struct ConstExprValue {68struct ConstExprValue {
64 bool ok; // true if constant expression evalution worked69 bool ok; // true if constant expression evalution worked
65 bool depends_on_compile_var;70 bool depends_on_compile_var;
...@@ -70,8 +75,8 @@ struct ConstExprValue {...@@ -70,8 +75,8 @@ struct ConstExprValue {
70 bool x_bool;75 bool x_bool;
71 FnTableEntry *x_fn;76 FnTableEntry *x_fn;
72 TypeTableEntry *x_type;77 TypeTableEntry *x_type;
73 ErrorTableEntry *x_err;
74 ConstExprValue *x_maybe;78 ConstExprValue *x_maybe;
79 ConstErrValue x_err;
75 ConstEnumValue x_enum;80 ConstEnumValue x_enum;
76 ConstStructValue x_struct;81 ConstStructValue x_struct;
77 ConstArrayValue x_array;82 ConstArrayValue x_array;
...@@ -309,6 +314,7 @@ enum CastOp {...@@ -309,6 +314,7 @@ enum CastOp {
309 CastOpIntWidenOrShorten,314 CastOpIntWidenOrShorten,
310 CastOpToUnknownSizeArray,315 CastOpToUnknownSizeArray,
311 CastOpMaybeWrap,316 CastOpMaybeWrap,
317 CastOpErrorWrap,
312 CastOpPointerReinterpret,318 CastOpPointerReinterpret,
313 CastOpErrToInt,319 CastOpErrToInt,
314};320};
src/analyze.cpp+150-95
...@@ -1130,6 +1130,61 @@ static bool num_lit_fits_in_other_type(CodeGen *g, AstNode *literal_node, TypeTa...@@ -1130,6 +1130,61 @@ static bool num_lit_fits_in_other_type(CodeGen *g, AstNode *literal_node, TypeTa
1130 return false;1130 return false;
1131}1131}
11321132
1133static bool types_match_const_cast_only(TypeTableEntry *expected_type, TypeTableEntry *actual_type) {
1134 if (expected_type == actual_type)
1135 return true;
1136
1137 // pointer const
1138 if (expected_type->id == TypeTableEntryIdPointer &&
1139 actual_type->id == TypeTableEntryIdPointer &&
1140 (!actual_type->data.pointer.is_const || expected_type->data.pointer.is_const))
1141 {
1142 return types_match_const_cast_only(expected_type->data.pointer.child_type,
1143 actual_type->data.pointer.child_type);
1144 }
1145
1146 // unknown size array const
1147 if (expected_type->id == TypeTableEntryIdStruct &&
1148 actual_type->id == TypeTableEntryIdStruct &&
1149 expected_type->data.structure.is_unknown_size_array &&
1150 actual_type->data.structure.is_unknown_size_array &&
1151 (!actual_type->data.structure.fields[0].type_entry->data.pointer.is_const ||
1152 expected_type->data.structure.fields[0].type_entry->data.pointer.is_const))
1153 {
1154 return types_match_const_cast_only(
1155 expected_type->data.structure.fields[0].type_entry->data.pointer.child_type,
1156 actual_type->data.structure.fields[0].type_entry->data.pointer.child_type);
1157 }
1158
1159 // maybe
1160 if (expected_type->id == TypeTableEntryIdMaybe &&
1161 actual_type->id == TypeTableEntryIdMaybe)
1162 {
1163 return types_match_const_cast_only(
1164 expected_type->data.maybe.child_type,
1165 actual_type->data.maybe.child_type);
1166 }
1167
1168 // error
1169 if (expected_type->id == TypeTableEntryIdError &&
1170 actual_type->id == TypeTableEntryIdError)
1171 {
1172 return types_match_const_cast_only(
1173 expected_type->data.error.child_type,
1174 actual_type->data.error.child_type);
1175 }
1176
1177 // fn
1178 if (expected_type->id == TypeTableEntryIdFn &&
1179 actual_type->id == TypeTableEntryIdFn)
1180 {
1181 zig_panic("TODO types_match_const_cast_only for fns");
1182 }
1183
1184
1185 return false;
1186}
1187
1133static TypeTableEntry *determine_peer_type_compatibility(CodeGen *g, AstNode *parent_source_node,1188static TypeTableEntry *determine_peer_type_compatibility(CodeGen *g, AstNode *parent_source_node,
1134 AstNode **child_nodes, TypeTableEntry **child_types, int child_count)1189 AstNode **child_nodes, TypeTableEntry **child_types, int child_count)
1135{1190{
...@@ -1143,6 +1198,12 @@ static TypeTableEntry *determine_peer_type_compatibility(CodeGen *g, AstNode *pa...@@ -1143,6 +1198,12 @@ static TypeTableEntry *determine_peer_type_compatibility(CodeGen *g, AstNode *pa
1143 AstNode *cur_node = child_nodes[i];1198 AstNode *cur_node = child_nodes[i];
1144 if (cur_type->id == TypeTableEntryIdInvalid) {1199 if (cur_type->id == TypeTableEntryIdInvalid) {
1145 return cur_type;1200 return cur_type;
1201 } else if (types_match_const_cast_only(prev_type, cur_type)) {
1202 continue;
1203 } else if (types_match_const_cast_only(cur_type, prev_type)) {
1204 prev_type = cur_type;
1205 prev_node = cur_node;
1206 continue;
1146 } else if (prev_type->id == TypeTableEntryIdUnreachable) {1207 } else if (prev_type->id == TypeTableEntryIdUnreachable) {
1147 prev_type = cur_type;1208 prev_type = cur_type;
1148 prev_node = cur_node;1209 prev_node = cur_node;
...@@ -1163,6 +1224,16 @@ static TypeTableEntry *determine_peer_type_compatibility(CodeGen *g, AstNode *pa...@@ -1163,6 +1224,16 @@ static TypeTableEntry *determine_peer_type_compatibility(CodeGen *g, AstNode *pa
1163 prev_type = cur_type;1224 prev_type = cur_type;
1164 prev_node = cur_node;1225 prev_node = cur_node;
1165 }1226 }
1227 } else if (prev_type->id == TypeTableEntryIdError &&
1228 types_match_const_cast_only(prev_type->data.error.child_type, cur_type))
1229 {
1230 continue;
1231 } else if (cur_type->id == TypeTableEntryIdError &&
1232 types_match_const_cast_only(cur_type->data.error.child_type, prev_type))
1233 {
1234 prev_type = cur_type;
1235 prev_node = cur_node;
1236 continue;
1166 } else if (prev_type->id == TypeTableEntryIdNumLitFloat &&1237 } else if (prev_type->id == TypeTableEntryIdNumLitFloat &&
1167 cur_type->id == TypeTableEntryIdNumLitFloat)1238 cur_type->id == TypeTableEntryIdNumLitFloat)
1168 {1239 {
...@@ -1189,8 +1260,6 @@ static TypeTableEntry *determine_peer_type_compatibility(CodeGen *g, AstNode *pa...@@ -1189,8 +1260,6 @@ static TypeTableEntry *determine_peer_type_compatibility(CodeGen *g, AstNode *pa
1189 } else {1260 } else {
1190 return g->builtin_types.entry_invalid;1261 return g->builtin_types.entry_invalid;
1191 }1262 }
1192 } else if (prev_type == cur_type) {
1193 continue;
1194 } else {1263 } else {
1195 add_node_error(g, parent_source_node,1264 add_node_error(g, parent_source_node,
1196 buf_sprintf("incompatible types: '%s' and '%s'",1265 buf_sprintf("incompatible types: '%s' and '%s'",
...@@ -1202,61 +1271,6 @@ static TypeTableEntry *determine_peer_type_compatibility(CodeGen *g, AstNode *pa...@@ -1202,61 +1271,6 @@ static TypeTableEntry *determine_peer_type_compatibility(CodeGen *g, AstNode *pa
1202 return prev_type;1271 return prev_type;
1203}1272}
12041273
1205static bool types_match_const_cast_only(TypeTableEntry *expected_type, TypeTableEntry *actual_type) {
1206 if (expected_type == actual_type)
1207 return true;
1208
1209 // pointer const
1210 if (expected_type->id == TypeTableEntryIdPointer &&
1211 actual_type->id == TypeTableEntryIdPointer &&
1212 (!actual_type->data.pointer.is_const || expected_type->data.pointer.is_const))
1213 {
1214 return types_match_const_cast_only(expected_type->data.pointer.child_type,
1215 actual_type->data.pointer.child_type);
1216 }
1217
1218 // unknown size array const
1219 if (expected_type->id == TypeTableEntryIdStruct &&
1220 actual_type->id == TypeTableEntryIdStruct &&
1221 expected_type->data.structure.is_unknown_size_array &&
1222 actual_type->data.structure.is_unknown_size_array &&
1223 (!actual_type->data.structure.fields[0].type_entry->data.pointer.is_const ||
1224 expected_type->data.structure.fields[0].type_entry->data.pointer.is_const))
1225 {
1226 return types_match_const_cast_only(
1227 expected_type->data.structure.fields[0].type_entry->data.pointer.child_type,
1228 actual_type->data.structure.fields[0].type_entry->data.pointer.child_type);
1229 }
1230
1231 // maybe
1232 if (expected_type->id == TypeTableEntryIdMaybe &&
1233 actual_type->id == TypeTableEntryIdMaybe)
1234 {
1235 return types_match_const_cast_only(
1236 expected_type->data.maybe.child_type,
1237 actual_type->data.maybe.child_type);
1238 }
1239
1240 // error
1241 if (expected_type->id == TypeTableEntryIdError &&
1242 actual_type->id == TypeTableEntryIdError)
1243 {
1244 return types_match_const_cast_only(
1245 expected_type->data.error.child_type,
1246 actual_type->data.error.child_type);
1247 }
1248
1249 // fn
1250 if (expected_type->id == TypeTableEntryIdFn &&
1251 actual_type->id == TypeTableEntryIdFn)
1252 {
1253 zig_panic("TODO types_match_const_cast_only for fns");
1254 }
1255
1256
1257 return false;
1258}
1259
1260static bool types_match_with_implicit_cast(CodeGen *g, TypeTableEntry *expected_type,1274static bool types_match_with_implicit_cast(CodeGen *g, TypeTableEntry *expected_type,
1261 TypeTableEntry *actual_type, AstNode *literal_node, bool *reported_err)1275 TypeTableEntry *actual_type, AstNode *literal_node, bool *reported_err)
1262{1276{
...@@ -1272,6 +1286,14 @@ static bool types_match_with_implicit_cast(CodeGen *g, TypeTableEntry *expected_...@@ -1272,6 +1286,14 @@ static bool types_match_with_implicit_cast(CodeGen *g, TypeTableEntry *expected_
1272 return true;1286 return true;
1273 }1287 }
12741288
1289 // implicit conversion from error child type to error type
1290 if (expected_type->id == TypeTableEntryIdError &&
1291 types_match_with_implicit_cast(g, expected_type->data.error.child_type, actual_type,
1292 literal_node, reported_err))
1293 {
1294 return true;
1295 }
1296
1275 // implicit widening conversion1297 // implicit widening conversion
1276 if (expected_type->id == TypeTableEntryIdInt &&1298 if (expected_type->id == TypeTableEntryIdInt &&
1277 actual_type->id == TypeTableEntryIdInt &&1299 actual_type->id == TypeTableEntryIdInt &&
...@@ -1381,9 +1403,10 @@ static TypeTableEntry *resolve_peer_type_compatibility(CodeGen *g, ImportTableEn...@@ -1381,9 +1403,10 @@ static TypeTableEntry *resolve_peer_type_compatibility(CodeGen *g, ImportTableEn
1381 if (!child_nodes[i]) {1403 if (!child_nodes[i]) {
1382 continue;1404 continue;
1383 }1405 }
1384 Expr *expr = get_resolved_expr(child_nodes[i]);1406 AstNode **child_node = child_nodes[i]->parent_field;
1385 TypeTableEntry *resolved_type = resolve_type_compatibility(g, import, block_context,1407 TypeTableEntry *resolved_type = resolve_type_compatibility(g, import, block_context,
1386 child_nodes[i], expected_type, child_types[i]);1408 *child_node, expected_type, child_types[i]);
1409 Expr *expr = get_resolved_expr(*child_node);
1387 expr->type_entry = resolved_type;1410 expr->type_entry = resolved_type;
1388 add_global_const_expr(g, expr);1411 add_global_const_expr(g, expr);
1389 }1412 }
...@@ -1812,7 +1835,7 @@ static TypeTableEntry *resolve_expr_const_val_as_fn(CodeGen *g, AstNode *node, F...@@ -1812,7 +1835,7 @@ static TypeTableEntry *resolve_expr_const_val_as_fn(CodeGen *g, AstNode *node, F
1812static TypeTableEntry *resolve_expr_const_val_as_err(CodeGen *g, AstNode *node, ErrorTableEntry *err) {1835static TypeTableEntry *resolve_expr_const_val_as_err(CodeGen *g, AstNode *node, ErrorTableEntry *err) {
1813 Expr *expr = get_resolved_expr(node);1836 Expr *expr = get_resolved_expr(node);
1814 expr->const_val.ok = true;1837 expr->const_val.ok = true;
1815 expr->const_val.data.x_err = err;1838 expr->const_val.data.x_err.err = err;
1816 return get_error_type(g, g->builtin_types.entry_void);1839 return get_error_type(g, g->builtin_types.entry_void);
1817}1840}
18181841
...@@ -2868,10 +2891,18 @@ static void eval_const_expr_implicit_cast(CodeGen *g, AstNode *node, AstNode *ex...@@ -2868,10 +2891,18 @@ static void eval_const_expr_implicit_cast(CodeGen *g, AstNode *node, AstNode *ex
2868 const_val->data.x_maybe = other_val;2891 const_val->data.x_maybe = other_val;
2869 const_val->ok = true;2892 const_val->ok = true;
2870 break;2893 break;
2871 case CastOpErrToInt:2894 case CastOpErrorWrap:
2872 bignum_init_unsigned(&const_val->data.x_bignum, other_val->data.x_err->value);2895 const_val->data.x_err.err = nullptr;
2896 const_val->data.x_err.payload = other_val;
2873 const_val->ok = true;2897 const_val->ok = true;
2874 break;2898 break;
2899 case CastOpErrToInt:
2900 {
2901 uint64_t value = other_val->data.x_err.err ? other_val->data.x_err.err->value : 0;
2902 bignum_init_unsigned(&const_val->data.x_bignum, value);
2903 const_val->ok = true;
2904 break;
2905 }
2875 }2906 }
2876}2907}
28772908
...@@ -2965,6 +2996,25 @@ static TypeTableEntry *analyze_cast_expr(CodeGen *g, ImportTableEntry *import, B...@@ -2965,6 +2996,25 @@ static TypeTableEntry *analyze_cast_expr(CodeGen *g, ImportTableEntry *import, B
2965 }2996 }
2966 }2997 }
29672998
2999 // explicit cast from child type of error type to error type
3000 if (wanted_type->id == TypeTableEntryIdError) {
3001 if (types_match_const_cast_only(wanted_type->data.error.child_type, actual_type)) {
3002 node->data.fn_call_expr.cast_op = CastOpErrorWrap;
3003 eval_const_expr_implicit_cast(g, node, expr_node);
3004 return wanted_type;
3005 } else if (actual_type->id == TypeTableEntryIdNumLitInt ||
3006 actual_type->id == TypeTableEntryIdNumLitFloat)
3007 {
3008 if (num_lit_fits_in_other_type(g, expr_node, wanted_type->data.error.child_type)) {
3009 node->data.fn_call_expr.cast_op = CastOpErrorWrap;
3010 eval_const_expr_implicit_cast(g, node, expr_node);
3011 return wanted_type;
3012 } else {
3013 return g->builtin_types.entry_invalid;
3014 }
3015 }
3016 }
3017
2968 // explicit cast from number literal to another type3018 // explicit cast from number literal to another type
2969 if (actual_type->id == TypeTableEntryIdNumLitFloat ||3019 if (actual_type->id == TypeTableEntryIdNumLitFloat ||
2970 actual_type->id == TypeTableEntryIdNumLitInt)3020 actual_type->id == TypeTableEntryIdNumLitInt)
...@@ -3579,6 +3629,42 @@ static TypeTableEntry *analyze_string_literal_expr(CodeGen *g, ImportTableEntry...@@ -3579,6 +3629,42 @@ static TypeTableEntry *analyze_string_literal_expr(CodeGen *g, ImportTableEntry
3579 }3629 }
3580}3630}
35813631
3632static TypeTableEntry *analyze_block_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
3633 TypeTableEntry *expected_type, AstNode *node)
3634{
3635 BlockContext *child_context = new_block_context(node, context);
3636 node->data.block.block_context = child_context;
3637 TypeTableEntry *return_type = g->builtin_types.entry_void;
3638
3639 for (int i = 0; i < node->data.block.statements.length; i += 1) {
3640 AstNode *child = node->data.block.statements.at(i);
3641 if (child->type == NodeTypeLabel) {
3642 LabelTableEntry *label_entry = child->data.label.label_entry;
3643 assert(label_entry);
3644 label_entry->entered_from_fallthrough = (return_type->id != TypeTableEntryIdUnreachable);
3645 return_type = g->builtin_types.entry_void;
3646 continue;
3647 }
3648 if (return_type->id == TypeTableEntryIdUnreachable) {
3649 if (is_node_void_expr(child)) {
3650 // {unreachable;void;void} is allowed.
3651 // ignore void statements once we enter unreachable land.
3652 analyze_expression(g, import, context, g->builtin_types.entry_void, child);
3653 continue;
3654 }
3655 add_node_error(g, first_executing_node(child), buf_sprintf("unreachable code"));
3656 break;
3657 }
3658 bool is_last = (i == node->data.block.statements.length - 1);
3659 TypeTableEntry *passed_expected_type = is_last ? expected_type : nullptr;
3660 return_type = analyze_expression(g, import, child_context, passed_expected_type, child);
3661 if (!is_last && return_type->id == TypeTableEntryIdMetaType) {
3662 add_node_error(g, child, buf_sprintf("expected expression, found type"));
3663 }
3664 }
3665 return return_type;
3666}
3667
3582// When you call analyze_expression, the node you pass might no longer be the child node3668// When you call analyze_expression, the node you pass might no longer be the child node
3583// you thought it was due to implicit casting rewriting the AST.3669// you thought it was due to implicit casting rewriting the AST.
3584static TypeTableEntry *analyze_expression(CodeGen *g, ImportTableEntry *import, BlockContext *context,3670static TypeTableEntry *analyze_expression(CodeGen *g, ImportTableEntry *import, BlockContext *context,
...@@ -3587,39 +3673,8 @@ static TypeTableEntry *analyze_expression(CodeGen *g, ImportTableEntry *import,...@@ -3587,39 +3673,8 @@ static TypeTableEntry *analyze_expression(CodeGen *g, ImportTableEntry *import,
3587 TypeTableEntry *return_type = nullptr;3673 TypeTableEntry *return_type = nullptr;
3588 switch (node->type) {3674 switch (node->type) {
3589 case NodeTypeBlock:3675 case NodeTypeBlock:
3590 {3676 return_type = analyze_block_expr(g, import, context, expected_type, node);
3591 BlockContext *child_context = new_block_context(node, context);3677 break;
3592 node->data.block.block_context = child_context;
3593 return_type = g->builtin_types.entry_void;
3594
3595 for (int i = 0; i < node->data.block.statements.length; i += 1) {
3596 AstNode *child = node->data.block.statements.at(i);
3597 if (child->type == NodeTypeLabel) {
3598 LabelTableEntry *label_entry = child->data.label.label_entry;
3599 assert(label_entry);
3600 label_entry->entered_from_fallthrough = (return_type->id != TypeTableEntryIdUnreachable);
3601 return_type = g->builtin_types.entry_void;
3602 continue;
3603 }
3604 if (return_type->id == TypeTableEntryIdUnreachable) {
3605 if (is_node_void_expr(child)) {
3606 // {unreachable;void;void} is allowed.
3607 // ignore void statements once we enter unreachable land.
3608 analyze_expression(g, import, context, g->builtin_types.entry_void, child);
3609 continue;
3610 }
3611 add_node_error(g, first_executing_node(child), buf_sprintf("unreachable code"));
3612 break;
3613 }
3614 bool is_last = (i == node->data.block.statements.length - 1);
3615 TypeTableEntry *passed_expected_type = is_last ? expected_type : nullptr;
3616 return_type = analyze_expression(g, import, child_context, passed_expected_type, child);
3617 if (!is_last && return_type->id == TypeTableEntryIdMetaType) {
3618 add_node_error(g, child, buf_sprintf("expected expression, found type"));
3619 }
3620 }
3621 break;
3622 }
36233678
3624 case NodeTypeReturnExpr:3679 case NodeTypeReturnExpr:
3625 return_type = analyze_return_expr(g, import, context, expected_type, node);3680 return_type = analyze_return_expr(g, import, context, expected_type, node);
src/codegen.cpp+38-19
...@@ -268,6 +268,26 @@ static LLVMValueRef gen_enum_value_expr(CodeGen *g, AstNode *node, TypeTableEntr...@@ -268,6 +268,26 @@ static LLVMValueRef gen_enum_value_expr(CodeGen *g, AstNode *node, TypeTableEntr
268 }268 }
269}269}
270270
271static LLVMValueRef gen_widen_or_shorten(CodeGen *g, AstNode *source_node, TypeTableEntry *actual_type,
272 TypeTableEntry *wanted_type, LLVMValueRef expr_val)
273{
274 if (actual_type->size_in_bits == wanted_type->size_in_bits) {
275 return expr_val;
276 } else if (actual_type->size_in_bits < wanted_type->size_in_bits) {
277 if (actual_type->data.integral.is_signed) {
278 add_debug_source_node(g, source_node);
279 return LLVMBuildSExt(g->builder, expr_val, wanted_type->type_ref, "");
280 } else {
281 add_debug_source_node(g, source_node);
282 return LLVMBuildZExt(g->builder, expr_val, wanted_type->type_ref, "");
283 }
284 } else {
285 assert(actual_type->size_in_bits > wanted_type->size_in_bits);
286 add_debug_source_node(g, source_node);
287 return LLVMBuildTrunc(g->builder, expr_val, wanted_type->type_ref, "");
288 }
289}
290
271static LLVMValueRef gen_cast_expr(CodeGen *g, AstNode *node) {291static LLVMValueRef gen_cast_expr(CodeGen *g, AstNode *node) {
272 assert(node->type == NodeTypeFnCallExpr);292 assert(node->type == NodeTypeFnCallExpr);
273293
...@@ -288,7 +308,7 @@ static LLVMValueRef gen_cast_expr(CodeGen *g, AstNode *node) {...@@ -288,7 +308,7 @@ static LLVMValueRef gen_cast_expr(CodeGen *g, AstNode *node) {
288 case CastOpErrToInt:308 case CastOpErrToInt:
289 assert(actual_type->id == TypeTableEntryIdError);309 assert(actual_type->id == TypeTableEntryIdError);
290 if (actual_type->data.error.child_type->size_in_bits == 0) {310 if (actual_type->data.error.child_type->size_in_bits == 0) {
291 return expr_val;311 return gen_widen_or_shorten(g, node, g->err_tag_type, wanted_type, expr_val);
292 } else {312 } else {
293 zig_panic("TODO");313 zig_panic("TODO");
294 }314 }
...@@ -309,6 +329,13 @@ static LLVMValueRef gen_cast_expr(CodeGen *g, AstNode *node) {...@@ -309,6 +329,13 @@ static LLVMValueRef gen_cast_expr(CodeGen *g, AstNode *node) {
309329
310 return cast_expr->tmp_ptr;330 return cast_expr->tmp_ptr;
311 }331 }
332 case CastOpErrorWrap:
333 assert(wanted_type->id == TypeTableEntryIdError);
334 if (wanted_type->data.error.child_type->size_in_bits == 0) {
335 return LLVMConstNull(g->err_tag_type->type_ref);
336 } else {
337 zig_panic("TODO");
338 }
312 case CastOpPtrToInt:339 case CastOpPtrToInt:
313 add_debug_source_node(g, node);340 add_debug_source_node(g, node);
314 return LLVMBuildPtrToInt(g->builder, expr_val, wanted_type->type_ref, "");341 return LLVMBuildPtrToInt(g->builder, expr_val, wanted_type->type_ref, "");
...@@ -316,21 +343,7 @@ static LLVMValueRef gen_cast_expr(CodeGen *g, AstNode *node) {...@@ -316,21 +343,7 @@ static LLVMValueRef gen_cast_expr(CodeGen *g, AstNode *node) {
316 add_debug_source_node(g, node);343 add_debug_source_node(g, node);
317 return LLVMBuildBitCast(g->builder, expr_val, wanted_type->type_ref, "");344 return LLVMBuildBitCast(g->builder, expr_val, wanted_type->type_ref, "");
318 case CastOpIntWidenOrShorten:345 case CastOpIntWidenOrShorten:
319 if (actual_type->size_in_bits == wanted_type->size_in_bits) {346 return gen_widen_or_shorten(g, node, actual_type, wanted_type, expr_val);
320 return expr_val;
321 } else if (actual_type->size_in_bits < wanted_type->size_in_bits) {
322 if (actual_type->data.integral.is_signed) {
323 add_debug_source_node(g, node);
324 return LLVMBuildSExt(g->builder, expr_val, wanted_type->type_ref, "");
325 } else {
326 add_debug_source_node(g, node);
327 return LLVMBuildZExt(g->builder, expr_val, wanted_type->type_ref, "");
328 }
329 } else {
330 assert(actual_type->size_in_bits > wanted_type->size_in_bits);
331 add_debug_source_node(g, node);
332 return LLVMBuildTrunc(g->builder, expr_val, wanted_type->type_ref, "");
333 }
334 case CastOpToUnknownSizeArray:347 case CastOpToUnknownSizeArray:
335 {348 {
336 assert(cast_expr->tmp_ptr);349 assert(cast_expr->tmp_ptr);
...@@ -1279,7 +1292,7 @@ static LLVMValueRef gen_if_bool_expr_raw(CodeGen *g, AstNode *source_node, LLVMV...@@ -1279,7 +1292,7 @@ static LLVMValueRef gen_if_bool_expr_raw(CodeGen *g, AstNode *source_node, LLVMV
1279 return nullptr;1292 return nullptr;
1280 }1293 }
12811294
1282 assert(!use_expr_value);1295 assert(!use_expr_value || then_type->id == TypeTableEntryIdError);
12831296
1284 LLVMBasicBlockRef then_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "Then");1297 LLVMBasicBlockRef then_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "Then");
1285 LLVMBasicBlockRef endif_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "EndIf");1298 LLVMBasicBlockRef endif_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "EndIf");
...@@ -1292,7 +1305,12 @@ static LLVMValueRef gen_if_bool_expr_raw(CodeGen *g, AstNode *source_node, LLVMV...@@ -1292,7 +1305,12 @@ static LLVMValueRef gen_if_bool_expr_raw(CodeGen *g, AstNode *source_node, LLVMV
1292 LLVMBuildBr(g->builder, endif_block);1305 LLVMBuildBr(g->builder, endif_block);
12931306
1294 LLVMPositionBuilderAtEnd(g->builder, endif_block);1307 LLVMPositionBuilderAtEnd(g->builder, endif_block);
1295 return nullptr;1308
1309 if (use_expr_value) {
1310 return LLVMConstNull(g->err_tag_type->type_ref);
1311 } else {
1312 return nullptr;
1313 }
1296}1314}
12971315
1298static LLVMValueRef gen_if_bool_expr(CodeGen *g, AstNode *node) {1316static LLVMValueRef gen_if_bool_expr(CodeGen *g, AstNode *node) {
...@@ -2132,7 +2150,8 @@ static LLVMValueRef gen_const_val(CodeGen *g, TypeTableEntry *type_entry, ConstE...@@ -2132,7 +2150,8 @@ static LLVMValueRef gen_const_val(CodeGen *g, TypeTableEntry *type_entry, ConstE
2132 }2150 }
2133 } else if (type_entry->id == TypeTableEntryIdError) {2151 } else if (type_entry->id == TypeTableEntryIdError) {
2134 if (type_entry->data.error.child_type->size_in_bits == 0) {2152 if (type_entry->data.error.child_type->size_in_bits == 0) {
2135 return LLVMConstInt(g->err_tag_type->type_ref, const_val->data.x_err->value, false);2153 uint64_t value = const_val->data.x_err.err ? const_val->data.x_err.err->value : 0;
2154 return LLVMConstInt(g->err_tag_type->type_ref, value, false);
2136 } else {2155 } else {
2137 zig_panic("TODO");2156 zig_panic("TODO");
2138 }2157 }
std/bootstrap.zig+4-1
...@@ -29,5 +29,8 @@ fn call_main() unreachable => {...@@ -29,5 +29,8 @@ fn call_main() unreachable => {
29 const ptr = argv[i];29 const ptr = argv[i];
30 args[i] = ptr[0...strlen(ptr)];30 args[i] = ptr[0...strlen(ptr)];
31 }31 }
32 exit(main(args))32 // TODO: replace the i32 cast with:
33 // main(args) %% exit(1)
34 // exit(0)
35 exit(i32(main(args)))
33}36}
test/run_tests.cpp+52-100
...@@ -114,7 +114,7 @@ import "syscall.zig";...@@ -114,7 +114,7 @@ import "syscall.zig";
114fn empty_function_1() => {}114fn empty_function_1() => {}
115fn empty_function_2() => { return; }115fn empty_function_2() => { return; }
116116
117pub fn main(args: [][]u8) i32 => {117pub fn main(args: [][]u8) %void => {
118 empty_function_1();118 empty_function_1();
119 empty_function_2();119 empty_function_2();
120 this_is_a_function();120 this_is_a_function();
...@@ -136,9 +136,8 @@ fn another_function() => {}...@@ -136,9 +136,8 @@ fn another_function() => {}
136136
137/// this is a documentation comment137/// this is a documentation comment
138/// doc comment line 2138/// doc comment line 2
139pub fn main(args: [][]u8) i32 => {139pub fn main(args: [][]u8) %void => {
140 print_str(/* mid-line comment /* nested */ */ "OK\n");140 print_str(/* mid-line comment /* nested */ */ "OK\n");
141 return 0;
142}141}
143 )SOURCE", "OK\n");142 )SOURCE", "OK\n");
144143
...@@ -147,10 +146,9 @@ pub fn main(args: [][]u8) i32 => {...@@ -147,10 +146,9 @@ pub fn main(args: [][]u8) i32 => {
147import "std.zig";146import "std.zig";
148import "foo.zig";147import "foo.zig";
149148
150pub fn main(args: [][]u8) i32 => {149pub fn main(args: [][]u8) %void => {
151 private_function();150 private_function();
152 print_str("OK 2\n");151 print_str("OK 2\n");
153 return 0;
154}152}
155153
156fn private_function() => {154fn private_function() => {
...@@ -178,10 +176,9 @@ pub fn print_text() => {...@@ -178,10 +176,9 @@ pub fn print_text() => {
178import "foo.zig";176import "foo.zig";
179import "bar.zig";177import "bar.zig";
180178
181pub fn main(args: [][]u8) i32 => {179pub fn main(args: [][]u8) %void => {
182 foo_function();180 foo_function();
183 bar_function();181 bar_function();
184 return 0;
185}182}
186 )SOURCE", "OK\nOK\n");183 )SOURCE", "OK\nOK\n");
187184
...@@ -214,7 +211,7 @@ pub fn foo_function() bool => {...@@ -214,7 +211,7 @@ pub fn foo_function() bool => {
214 add_simple_case("if statements", R"SOURCE(211 add_simple_case("if statements", R"SOURCE(
215import "std.zig";212import "std.zig";
216213
217pub fn main(args: [][]u8) i32 => {214pub fn main(args: [][]u8) %void => {
218 if (1 != 0) {215 if (1 != 0) {
219 print_str("1 is true\n");216 print_str("1 is true\n");
220 } else {217 } else {
...@@ -228,7 +225,6 @@ pub fn main(args: [][]u8) i32 => {...@@ -228,7 +225,6 @@ pub fn main(args: [][]u8) i32 => {
228 if (!(0 != 0)) {225 if (!(0 != 0)) {
229 print_str("!0 is true\n");226 print_str("!0 is true\n");
230 }227 }
231 return 0;
232}228}
233 )SOURCE", "1 is true\n!0 is true\n");229 )SOURCE", "1 is true\n!0 is true\n");
234230
...@@ -239,11 +235,10 @@ fn add(a: i32, b: i32) i32 => {...@@ -239,11 +235,10 @@ fn add(a: i32, b: i32) i32 => {
239 a + b235 a + b
240}236}
241237
242pub fn main(args: [][]u8) i32 => {238pub fn main(args: [][]u8) %void => {
243 if (add(22, 11) == 33) {239 if (add(22, 11) == 33) {
244 print_str("pass\n");240 print_str("pass\n");
245 }241 }
246 return 0;
247}242}
248 )SOURCE", "pass\n");243 )SOURCE", "pass\n");
249244
...@@ -261,41 +256,38 @@ done:...@@ -261,41 +256,38 @@ done:
261 return;256 return;
262}257}
263258
264pub fn main(args: [][]u8) i32 => {259pub fn main(args: [][]u8) %void => {
265 loop(3);260 loop(3);
266 return 0;
267}261}
268 )SOURCE", "loop\nloop\nloop\n");262 )SOURCE", "loop\nloop\nloop\n");
269263
270 add_simple_case("local variables", R"SOURCE(264 add_simple_case("local variables", R"SOURCE(
271import "std.zig";265import "std.zig";
272266
273pub fn main(args: [][]u8) i32 => {267pub fn main(args: [][]u8) %void => {
274 const a : i32 = 1;268 const a : i32 = 1;
275 const b = i32(2);269 const b = i32(2);
276 if (a + b == 3) {270 if (a + b == 3) {
277 print_str("OK\n");271 print_str("OK\n");
278 }272 }
279 return 0;
280}273}
281 )SOURCE", "OK\n");274 )SOURCE", "OK\n");
282275
283 add_simple_case("bool literals", R"SOURCE(276 add_simple_case("bool literals", R"SOURCE(
284import "std.zig";277import "std.zig";
285278
286pub fn main(args: [][]u8) i32 => {279pub fn main(args: [][]u8) %void => {
287 if (true) { print_str("OK 1\n"); }280 if (true) { print_str("OK 1\n"); }
288 if (false) { print_str("BAD 1\n"); }281 if (false) { print_str("BAD 1\n"); }
289 if (!true) { print_str("BAD 2\n"); }282 if (!true) { print_str("BAD 2\n"); }
290 if (!false) { print_str("OK 2\n"); }283 if (!false) { print_str("OK 2\n"); }
291 return 0;
292}284}
293 )SOURCE", "OK 1\nOK 2\n");285 )SOURCE", "OK 1\nOK 2\n");
294286
295 add_simple_case("separate block scopes", R"SOURCE(287 add_simple_case("separate block scopes", R"SOURCE(
296import "std.zig";288import "std.zig";
297289
298pub fn main(args: [][]u8) i32 => {290pub fn main(args: [][]u8) %void => {
299 if (true) {291 if (true) {
300 const no_conflict : i32 = 5;292 const no_conflict : i32 = 5;
301 if (no_conflict == 5) { print_str("OK 1\n"); }293 if (no_conflict == 5) { print_str("OK 1\n"); }
...@@ -306,16 +298,14 @@ pub fn main(args: [][]u8) i32 => {...@@ -306,16 +298,14 @@ pub fn main(args: [][]u8) i32 => {
306 no_conflict298 no_conflict
307 };299 };
308 if (c == 10) { print_str("OK 2\n"); }300 if (c == 10) { print_str("OK 2\n"); }
309 return 0;
310}301}
311 )SOURCE", "OK 1\nOK 2\n");302 )SOURCE", "OK 1\nOK 2\n");
312303
313 add_simple_case("void parameters", R"SOURCE(304 add_simple_case("void parameters", R"SOURCE(
314import "std.zig";305import "std.zig";
315306
316pub fn main(args: [][]u8) i32 => {307pub fn main(args: [][]u8) %void => {
317 void_fun(1, void{}, 2);308 void_fun(1, void{}, 2);
318 return 0;
319}309}
320310
321fn void_fun(a : i32, b : void, c : i32) => {311fn void_fun(a : i32, b : void, c : i32) => {
...@@ -333,7 +323,7 @@ struct Foo {...@@ -333,7 +323,7 @@ struct Foo {
333 b : i32,323 b : i32,
334 c : void,324 c : void,
335}325}
336pub fn main(args: [][]u8) i32 => {326pub fn main(args: [][]u8) %void => {
337 const foo = Foo {327 const foo = Foo {
338 .a = void{},328 .a = void{},
339 .b = 1,329 .b = 1,
...@@ -346,7 +336,6 @@ pub fn main(args: [][]u8) i32 => {...@@ -346,7 +336,6 @@ pub fn main(args: [][]u8) i32 => {
346 print_str("BAD\n");336 print_str("BAD\n");
347 }337 }
348 print_str("OK\n");338 print_str("OK\n");
349 return 0;
350}339}
351340
352 )SOURCE", "OK\n");341 )SOURCE", "OK\n");
...@@ -354,7 +343,7 @@ pub fn main(args: [][]u8) i32 => {...@@ -354,7 +343,7 @@ pub fn main(args: [][]u8) i32 => {
354 add_simple_case("void arrays", R"SOURCE(343 add_simple_case("void arrays", R"SOURCE(
355import "std.zig";344import "std.zig";
356345
357pub fn main(args: [][]u8) i32 => {346pub fn main(args: [][]u8) %void => {
358 var array: [4]void;347 var array: [4]void;
359 array[0] = void{};348 array[0] = void{};
360 array[1] = array[2];349 array[1] = array[2];
...@@ -365,7 +354,6 @@ pub fn main(args: [][]u8) i32 => {...@@ -365,7 +354,6 @@ pub fn main(args: [][]u8) i32 => {
365 print_str("BAD\n");354 print_str("BAD\n");
366 }355 }
367 print_str("OK\n");356 print_str("OK\n");
368 return 0;
369}357}
370 )SOURCE", "OK\n");358 )SOURCE", "OK\n");
371359
...@@ -373,27 +361,22 @@ pub fn main(args: [][]u8) i32 => {...@@ -373,27 +361,22 @@ pub fn main(args: [][]u8) i32 => {
373 add_simple_case("mutable local variables", R"SOURCE(361 add_simple_case("mutable local variables", R"SOURCE(
374import "std.zig";362import "std.zig";
375363
376pub fn main(args: [][]u8) i32 => {364pub fn main(args: [][]u8) %void => {
377 var zero : i32 = 0;365 var zero : i32 = 0;
378 if (zero == 0) { print_str("zero\n"); }366 if (zero == 0) { print_str("zero\n"); }
379367
380 var i = i32(0);368 var i = i32(0);
381loop_start:369 while (i != 3) {
382 if (i == 3) {370 print_str("loop\n");
383 goto done;371 i += 1;
384 }372 }
385 print_str("loop\n");
386 i = i + 1;
387 goto loop_start;
388done:
389 return 0;
390}373}
391 )SOURCE", "zero\nloop\nloop\nloop\n");374 )SOURCE", "zero\nloop\nloop\nloop\n");
392375
393 add_simple_case("arrays", R"SOURCE(376 add_simple_case("arrays", R"SOURCE(
394import "std.zig";377import "std.zig";
395378
396pub fn main(args: [][]u8) i32 => {379pub fn main(args: [][]u8) %void => {
397 var array : [5]i32;380 var array : [5]i32;
398381
399 var i : i32 = 0;382 var i : i32 = 0;
...@@ -417,8 +400,6 @@ pub fn main(args: [][]u8) i32 => {...@@ -417,8 +400,6 @@ pub fn main(args: [][]u8) i32 => {
417 if (get_array_len(array) != 5) {400 if (get_array_len(array) != 5) {
418 print_str("BAD\n");401 print_str("BAD\n");
419 }402 }
420
421 return 0;
422}403}
423fn get_array_len(a: []i32) isize => {404fn get_array_len(a: []i32) isize => {
424 a.len405 a.len
...@@ -429,9 +410,8 @@ fn get_array_len(a: []i32) isize => {...@@ -429,9 +410,8 @@ fn get_array_len(a: []i32) isize => {
429 add_simple_case("hello world without libc", R"SOURCE(410 add_simple_case("hello world without libc", R"SOURCE(
430import "std.zig";411import "std.zig";
431412
432pub fn main(args: [][]u8) i32 => {413pub fn main(args: [][]u8) %void => {
433 print_str("Hello, world!\n");414 print_str("Hello, world!\n");
434 return 0;
435}415}
436 )SOURCE", "Hello, world!\n");416 )SOURCE", "Hello, world!\n");
437417
...@@ -439,7 +419,7 @@ pub fn main(args: [][]u8) i32 => {...@@ -439,7 +419,7 @@ pub fn main(args: [][]u8) i32 => {
439 add_simple_case("a + b + c", R"SOURCE(419 add_simple_case("a + b + c", R"SOURCE(
440import "std.zig";420import "std.zig";
441421
442pub fn main(args: [][]u8) i32 => {422pub fn main(args: [][]u8) %void => {
443 if (false || false || false) { print_str("BAD 1\n"); }423 if (false || false || false) { print_str("BAD 1\n"); }
444 if (true && true && false) { print_str("BAD 2\n"); }424 if (true && true && false) { print_str("BAD 2\n"); }
445 if (1 | 2 | 4 != 7) { print_str("BAD 3\n"); }425 if (1 | 2 | 4 != 7) { print_str("BAD 3\n"); }
...@@ -454,14 +434,13 @@ pub fn main(args: [][]u8) i32 => {...@@ -454,14 +434,13 @@ pub fn main(args: [][]u8) i32 => {
454 if (i32(7) != --(i32(7))) { print_str("BAD 12\n"); }434 if (i32(7) != --(i32(7))) { print_str("BAD 12\n"); }
455435
456 print_str("OK\n");436 print_str("OK\n");
457 return 0;
458}437}
459 )SOURCE", "OK\n");438 )SOURCE", "OK\n");
460439
461 add_simple_case("short circuit", R"SOURCE(440 add_simple_case("short circuit", R"SOURCE(
462import "std.zig";441import "std.zig";
463442
464pub fn main(args: [][]u8) i32 => {443pub fn main(args: [][]u8) %void => {
465 if (true || { print_str("BAD 1\n"); false }) {444 if (true || { print_str("BAD 1\n"); false }) {
466 print_str("OK 1\n");445 print_str("OK 1\n");
467 }446 }
...@@ -476,15 +455,13 @@ pub fn main(args: [][]u8) i32 => {...@@ -476,15 +455,13 @@ pub fn main(args: [][]u8) i32 => {
476 } else {455 } else {
477 print_str("OK 4\n");456 print_str("OK 4\n");
478 }457 }
479
480 return 0;
481}458}
482 )SOURCE", "OK 1\nOK 2\nOK 3\nOK 4\n");459 )SOURCE", "OK 1\nOK 2\nOK 3\nOK 4\n");
483460
484 add_simple_case("modify operators", R"SOURCE(461 add_simple_case("modify operators", R"SOURCE(
485import "std.zig";462import "std.zig";
486463
487pub fn main(args: [][]u8) i32 => {464pub fn main(args: [][]u8) %void => {
488 var i : i32 = 0;465 var i : i32 = 0;
489 i += 5; if (i != 5) { print_str("BAD +=\n"); }466 i += 5; if (i != 5) { print_str("BAD +=\n"); }
490 i -= 2; if (i != 3) { print_str("BAD -=\n"); }467 i -= 2; if (i != 3) { print_str("BAD -=\n"); }
...@@ -500,7 +477,6 @@ pub fn main(args: [][]u8) i32 => {...@@ -500,7 +477,6 @@ pub fn main(args: [][]u8) i32 => {
500 i |= 3; if (i != 7) { print_str("BAD |=\n"); }477 i |= 3; if (i != 7) { print_str("BAD |=\n"); }
501478
502 print_str("OK\n");479 print_str("OK\n");
503 return 0;
504}480}
505 )SOURCE", "OK\n");481 )SOURCE", "OK\n");
506482
...@@ -636,7 +612,7 @@ export fn main(argc: i32, argv: &&u8) i32 => {...@@ -636,7 +612,7 @@ export fn main(argc: i32, argv: &&u8) i32 => {
636 add_simple_case("structs", R"SOURCE(612 add_simple_case("structs", R"SOURCE(
637import "std.zig";613import "std.zig";
638614
639pub fn main(args: [][]u8) i32 => {615pub fn main(args: [][]u8) %void => {
640 var foo : Foo;616 var foo : Foo;
641 @memset(&foo, 0, @sizeof(Foo));617 @memset(&foo, 0, @sizeof(Foo));
642 foo.a += 1;618 foo.a += 1;
...@@ -650,7 +626,6 @@ pub fn main(args: [][]u8) i32 => {...@@ -650,7 +626,6 @@ pub fn main(args: [][]u8) i32 => {
650 test_byval_assign();626 test_byval_assign();
651 test_initializer();627 test_initializer();
652 print_str("OK\n");628 print_str("OK\n");
653 return 0;
654}629}
655struct Foo {630struct Foo {
656 a : i32,631 a : i32,
...@@ -711,23 +686,25 @@ import "std.zig";...@@ -711,23 +686,25 @@ import "std.zig";
711const g1 : i32 = 1233 + 1;686const g1 : i32 = 1233 + 1;
712var g2 : i32 = 0;687var g2 : i32 = 0;
713688
714pub fn main(args: [][]u8) i32 => {689pub fn main(args: [][]u8) %void => {
715 if (g2 != 0) { print_str("BAD\n"); }690 if (g2 != 0) { print_str("BAD\n"); }
716 g2 = g1;691 g2 = g1;
717 if (g2 != 1234) { print_str("BAD\n"); }692 if (g2 != 1234) { print_str("BAD\n"); }
718 print_str("OK\n");693 print_str("OK\n");
719 return 0;
720}694}
721 )SOURCE", "OK\n");695 )SOURCE", "OK\n");
722696
723 add_simple_case("while loop", R"SOURCE(697 add_simple_case("while loop", R"SOURCE(
724import "std.zig";698import "std.zig";
725pub fn main(args: [][]u8) i32 => {699pub fn main(args: [][]u8) %void => {
726 var i : i32 = 0;700 var i : i32 = 0;
727 while (i < 4) {701 while (i < 4) {
728 print_str("loop\n");702 print_str("loop\n");
729 i += 1;703 i += 1;
730 }704 }
705 g();
706}
707fn g() i32 => {
731 return f();708 return f();
732}709}
733fn f() i32 => {710fn f() i32 => {
...@@ -739,7 +716,7 @@ fn f() i32 => {...@@ -739,7 +716,7 @@ fn f() i32 => {
739716
740 add_simple_case("continue and break", R"SOURCE(717 add_simple_case("continue and break", R"SOURCE(
741import "std.zig";718import "std.zig";
742pub fn main(args: [][]u8) i32 => {719pub fn main(args: [][]u8) %void => {
743 var i : i32 = 0;720 var i : i32 = 0;
744 while (true) {721 while (true) {
745 print_str("loop\n");722 print_str("loop\n");
...@@ -749,13 +726,12 @@ pub fn main(args: [][]u8) i32 => {...@@ -749,13 +726,12 @@ pub fn main(args: [][]u8) i32 => {
749 }726 }
750 break;727 break;
751 }728 }
752 return 0;
753}729}
754 )SOURCE", "loop\nloop\nloop\nloop\n");730 )SOURCE", "loop\nloop\nloop\nloop\n");
755731
756 add_simple_case("maybe type", R"SOURCE(732 add_simple_case("maybe type", R"SOURCE(
757import "std.zig";733import "std.zig";
758pub fn main(args: [][]u8) i32 => {734pub fn main(args: [][]u8) %void => {
759 const x : ?bool = true;735 const x : ?bool = true;
760736
761 if (const y ?= x) {737 if (const y ?= x) {
...@@ -783,19 +759,16 @@ pub fn main(args: [][]u8) i32 => {...@@ -783,19 +759,16 @@ pub fn main(args: [][]u8) i32 => {
783 if (num != 13) {759 if (num != 13) {
784 print_str("BAD\n");760 print_str("BAD\n");
785 }761 }
786
787 return 0;
788}762}
789 )SOURCE", "x is true\n");763 )SOURCE", "x is true\n");
790764
791 add_simple_case("implicit cast after unreachable", R"SOURCE(765 add_simple_case("implicit cast after unreachable", R"SOURCE(
792import "std.zig";766import "std.zig";
793pub fn main(args: [][]u8) i32 => {767pub fn main(args: [][]u8) %void => {
794 const x = outer();768 const x = outer();
795 if (x == 1234) {769 if (x == 1234) {
796 print_str("OK\n");770 print_str("OK\n");
797 }771 }
798 return 0;
799}772}
800fn inner() i32 => { 1234 }773fn inner() i32 => { 1234 }
801fn outer() isize => {774fn outer() isize => {
...@@ -807,11 +780,10 @@ fn outer() isize => {...@@ -807,11 +780,10 @@ fn outer() isize => {
807import "std.zig";780import "std.zig";
808const x: u16 = 13;781const x: u16 = 13;
809const z: @typeof(x) = 19;782const z: @typeof(x) = 19;
810pub fn main(args: [][]u8) i32 => {783pub fn main(args: [][]u8) %void => {
811 const y: @typeof(x) = 120;784 const y: @typeof(x) = 120;
812 print_u64(@sizeof(@typeof(y)));785 print_u64(@sizeof(@typeof(y)));
813 print_str("\n");786 print_str("\n");
814 return 0;
815}787}
816 )SOURCE", "2\n");788 )SOURCE", "2\n");
817789
...@@ -823,20 +795,19 @@ struct Rand {...@@ -823,20 +795,19 @@ struct Rand {
823 r.seed795 r.seed
824 }796 }
825}797}
826pub fn main(args: [][]u8) i32 => {798pub fn main(args: [][]u8) %void => {
827 const r = Rand {.seed = 1234};799 const r = Rand {.seed = 1234};
828 if (r.get_seed() != 1234) {800 if (r.get_seed() != 1234) {
829 print_str("BAD seed\n");801 print_str("BAD seed\n");
830 }802 }
831 print_str("OK\n");803 print_str("OK\n");
832 return 0;
833}804}
834 )SOURCE", "OK\n");805 )SOURCE", "OK\n");
835806
836 add_simple_case("pointer dereferencing", R"SOURCE(807 add_simple_case("pointer dereferencing", R"SOURCE(
837import "std.zig";808import "std.zig";
838809
839pub fn main(args: [][]u8) i32 => {810pub fn main(args: [][]u8) %void => {
840 var x = i32(3);811 var x = i32(3);
841 const y = &x;812 const y = &x;
842813
...@@ -849,7 +820,6 @@ pub fn main(args: [][]u8) i32 => {...@@ -849,7 +820,6 @@ pub fn main(args: [][]u8) i32 => {
849 print_str("BAD\n");820 print_str("BAD\n");
850 }821 }
851 print_str("OK\n");822 print_str("OK\n");
852 return 0;
853}823}
854 )SOURCE", "OK\n");824 )SOURCE", "OK\n");
855825
...@@ -858,17 +828,16 @@ import "std.zig";...@@ -858,17 +828,16 @@ import "std.zig";
858828
859const ARRAY_SIZE : i8 = 20;829const ARRAY_SIZE : i8 = 20;
860830
861pub fn main(args: [][]u8) i32 => {831pub fn main(args: [][]u8) %void => {
862 var array : [ARRAY_SIZE]u8;832 var array : [ARRAY_SIZE]u8;
863 print_u64(@sizeof(@typeof(array)));833 print_u64(@sizeof(@typeof(array)));
864 print_str("\n");834 print_str("\n");
865 return 0;
866}835}
867 )SOURCE", "20\n");836 )SOURCE", "20\n");
868837
869 add_simple_case("@min_value() and @max_value()", R"SOURCE(838 add_simple_case("@min_value() and @max_value()", R"SOURCE(
870import "std.zig";839import "std.zig";
871pub fn main(args: [][]u8) i32 => {840pub fn main(args: [][]u8) %void => {
872 print_str("max u8: ");841 print_str("max u8: ");
873 print_u64(@max_value(u8));842 print_u64(@max_value(u8));
874 print_str("\n");843 print_str("\n");
...@@ -932,8 +901,6 @@ pub fn main(args: [][]u8) i32 => {...@@ -932,8 +901,6 @@ pub fn main(args: [][]u8) i32 => {
932 print_str("min i64: ");901 print_str("min i64: ");
933 print_i64(@min_value(i64));902 print_i64(@min_value(i64));
934 print_str("\n");903 print_str("\n");
935
936 return 0;
937}904}
938 )SOURCE",905 )SOURCE",
939 "max u8: 255\n"906 "max u8: 255\n"
...@@ -956,7 +923,7 @@ pub fn main(args: [][]u8) i32 => {...@@ -956,7 +923,7 @@ pub fn main(args: [][]u8) i32 => {
956923
957 add_simple_case("slicing", R"SOURCE(924 add_simple_case("slicing", R"SOURCE(
958import "std.zig";925import "std.zig";
959pub fn main(args: [][]u8) i32 => {926pub fn main(args: [][]u8) %void => {
960 var array : [20]i32;927 var array : [20]i32;
961928
962 array[5] = 1234;929 array[5] = 1234;
...@@ -977,18 +944,16 @@ pub fn main(args: [][]u8) i32 => {...@@ -977,18 +944,16 @@ pub fn main(args: [][]u8) i32 => {
977 }944 }
978945
979 print_str("OK\n");946 print_str("OK\n");
980 return 0;
981}947}
982 )SOURCE", "OK\n");948 )SOURCE", "OK\n");
983949
984950
985 add_simple_case("else if expression", R"SOURCE(951 add_simple_case("else if expression", R"SOURCE(
986import "std.zig";952import "std.zig";
987pub fn main(args: [][]u8) i32 => {953pub fn main(args: [][]u8) %void => {
988 if (f(1) == 1) {954 if (f(1) == 1) {
989 print_str("OK\n");955 print_str("OK\n");
990 }956 }
991 return 0;
992}957}
993fn f(c: u8) u8 => {958fn f(c: u8) u8 => {
994 if (c == 0) {959 if (c == 0) {
...@@ -1003,7 +968,7 @@ fn f(c: u8) u8 => {...@@ -1003,7 +968,7 @@ fn f(c: u8) u8 => {
1003968
1004 add_simple_case("overflow intrinsics", R"SOURCE(969 add_simple_case("overflow intrinsics", R"SOURCE(
1005import "std.zig";970import "std.zig";
1006pub fn main(args: [][]u8) i32 => {971pub fn main(args: [][]u8) %void => {
1007 var result: u8;972 var result: u8;
1008 if (!@add_with_overflow(u8, 250, 100, &result)) {973 if (!@add_with_overflow(u8, 250, 100, &result)) {
1009 print_str("BAD\n");974 print_str("BAD\n");
...@@ -1015,13 +980,12 @@ pub fn main(args: [][]u8) i32 => {...@@ -1015,13 +980,12 @@ pub fn main(args: [][]u8) i32 => {
1015 print_str("BAD\n");980 print_str("BAD\n");
1016 }981 }
1017 print_str("OK\n");982 print_str("OK\n");
1018 return 0;
1019}983}
1020 )SOURCE", "OK\n");984 )SOURCE", "OK\n");
1021985
1022 add_simple_case("memcpy and memset intrinsics", R"SOURCE(986 add_simple_case("memcpy and memset intrinsics", R"SOURCE(
1023import "std.zig";987import "std.zig";
1024pub fn main(args: [][]u8) i32 => {988pub fn main(args: [][]u8) %void => {
1025 var foo : [20]u8;989 var foo : [20]u8;
1026 var bar : [20]u8;990 var bar : [20]u8;
1027991
...@@ -1033,7 +997,6 @@ pub fn main(args: [][]u8) i32 => {...@@ -1033,7 +997,6 @@ pub fn main(args: [][]u8) i32 => {
1033 }997 }
1034998
1035 print_str("OK\n");999 print_str("OK\n");
1036 return 0;
1037}1000}
1038 )SOURCE", "OK\n");1001 )SOURCE", "OK\n");
10391002
...@@ -1042,8 +1005,8 @@ import "std.zig";...@@ -1042,8 +1005,8 @@ import "std.zig";
1042const z : @typeof(stdin_fileno) = 0;1005const z : @typeof(stdin_fileno) = 0;
1043const x : @typeof(y) = 1234;1006const x : @typeof(y) = 1234;
1044const y : u16 = 5678;1007const y : u16 = 5678;
1045pub fn main(args: [][]u8) i32 => {1008pub fn main(args: [][]u8) %void => {
1046 print_ok(x)1009 var x : i32 = print_ok(x);
1047}1010}
1048fn print_ok(val: @typeof(x)) @typeof(foo) => {1011fn print_ok(val: @typeof(x)) @typeof(foo) => {
1049 print_str("OK\n");1012 print_str("OK\n");
...@@ -1073,7 +1036,7 @@ enum Bar {...@@ -1073,7 +1036,7 @@ enum Bar {
1073 D,1036 D,
1074}1037}
10751038
1076pub fn main(args: [][]u8) i32 => {1039pub fn main(args: [][]u8) %void => {
1077 const foo1 = Foo.One(13);1040 const foo1 = Foo.One(13);
1078 const foo2 = Foo.Two(Point { .x = 1234, .y = 5678, });1041 const foo2 = Foo.Two(Point { .x = 1234, .y = 5678, });
1079 const bar = Bar.B;1042 const bar = Bar.B;
...@@ -1098,15 +1061,13 @@ pub fn main(args: [][]u8) i32 => {...@@ -1098,15 +1061,13 @@ pub fn main(args: [][]u8) i32 => {
1098 }1061 }
10991062
1100 print_str("OK\n");1063 print_str("OK\n");
1101
1102 return 0;
1103}1064}
1104 )SOURCE", "OK\n");1065 )SOURCE", "OK\n");
11051066
1106 add_simple_case("array literal", R"SOURCE(1067 add_simple_case("array literal", R"SOURCE(
1107import "std.zig";1068import "std.zig";
11081069
1109pub fn main(args: [][]u8) i32 => {1070pub fn main(args: [][]u8) %void => {
1110 const HEX_MULT = []u16{4096, 256, 16, 1};1071 const HEX_MULT = []u16{4096, 256, 16, 1};
11111072
1112 if (HEX_MULT.len != 4) {1073 if (HEX_MULT.len != 4) {
...@@ -1118,14 +1079,13 @@ pub fn main(args: [][]u8) i32 => {...@@ -1118,14 +1079,13 @@ pub fn main(args: [][]u8) i32 => {
1118 }1079 }
11191080
1120 print_str("OK\n");1081 print_str("OK\n");
1121 return 0;
1122}1082}
1123 )SOURCE", "OK\n");1083 )SOURCE", "OK\n");
11241084
1125 add_simple_case("nested arrays", R"SOURCE(1085 add_simple_case("nested arrays", R"SOURCE(
1126import "std.zig";1086import "std.zig";
11271087
1128pub fn main(args: [][]u8) i32 => {1088pub fn main(args: [][]u8) %void => {
1129 const array_of_strings = [][]u8 {"hello", "this", "is", "my", "thing"};1089 const array_of_strings = [][]u8 {"hello", "this", "is", "my", "thing"};
1130 var i: @typeof(array_of_strings.len) = 0;1090 var i: @typeof(array_of_strings.len) = 0;
1131 while (i < array_of_strings.len) {1091 while (i < array_of_strings.len) {
...@@ -1133,14 +1093,13 @@ pub fn main(args: [][]u8) i32 => {...@@ -1133,14 +1093,13 @@ pub fn main(args: [][]u8) i32 => {
1133 print_str("\n");1093 print_str("\n");
1134 i += 1;1094 i += 1;
1135 }1095 }
1136 return 0;
1137}1096}
1138 )SOURCE", "hello\nthis\nis\nmy\nthing\n");1097 )SOURCE", "hello\nthis\nis\nmy\nthing\n");
11391098
1140 add_simple_case("for loops", R"SOURCE(1099 add_simple_case("for loops", R"SOURCE(
1141import "std.zig";1100import "std.zig";
11421101
1143pub fn main(args: [][]u8) i32 => {1102pub fn main(args: [][]u8) %void => {
1144 const array = []u8 {9, 8, 7, 6};1103 const array = []u8 {9, 8, 7, 6};
1145 for (item, array) {1104 for (item, array) {
1146 print_u64(item);1105 print_u64(item);
...@@ -1159,20 +1118,18 @@ pub fn main(args: [][]u8) i32 => {...@@ -1159,20 +1118,18 @@ pub fn main(args: [][]u8) i32 => {
1159 print_i64(index);1118 print_i64(index);
1160 print_str("\n");1119 print_str("\n");
1161 }1120 }
1162 return 0;
1163}1121}
1164 )SOURCE", "9\n8\n7\n6\n0\n1\n2\n3\n9\n8\n7\n6\n0\n1\n2\n3\n");1122 )SOURCE", "9\n8\n7\n6\n0\n1\n2\n3\n9\n8\n7\n6\n0\n1\n2\n3\n");
11651123
1166 add_simple_case("function pointers", R"SOURCE(1124 add_simple_case("function pointers", R"SOURCE(
1167import "std.zig";1125import "std.zig";
11681126
1169pub fn main(args: [][]u8) i32 => {1127pub fn main(args: [][]u8) %void => {
1170 const fns = []@typeof(fn1) { fn1, fn2, fn3, fn4, };1128 const fns = []@typeof(fn1) { fn1, fn2, fn3, fn4, };
1171 for (f, fns) {1129 for (f, fns) {
1172 print_u64(f());1130 print_u64(f());
1173 print_str("\n");1131 print_str("\n");
1174 }1132 }
1175 return 0;
1176}1133}
11771134
1178fn fn1() u32 => {5}1135fn fn1() u32 => {5}
...@@ -1191,7 +1148,7 @@ enum Foo {...@@ -1191,7 +1148,7 @@ enum Foo {
1191 D,1148 D,
1192}1149}
11931150
1194pub fn main(args: [][]u8) i32 => {1151pub fn main(args: [][]u8) %void => {
1195 const foo = Foo.C;1152 const foo = Foo.C;
1196 const val: i32 = switch (foo) {1153 const val: i32 = switch (foo) {
1197 Foo.A => 1,1154 Foo.A => 1,
...@@ -1204,7 +1161,6 @@ pub fn main(args: [][]u8) i32 => {...@@ -1204,7 +1161,6 @@ pub fn main(args: [][]u8) i32 => {
1204 }1161 }
12051162
1206 print_str("OK\n");1163 print_str("OK\n");
1207 return 0;
1208}1164}
1209 )SOURCE", "OK\n");1165 )SOURCE", "OK\n");
12101166
...@@ -1213,7 +1169,7 @@ import "std.zig";...@@ -1213,7 +1169,7 @@ import "std.zig";
12131169
1214const ten = 10;1170const ten = 10;
12151171
1216pub fn main(args: [][]u8) i32 => {1172pub fn main(args: [][]u8) %void => {
1217 const one = 1;1173 const one = 1;
1218 const eleven = ten + one;1174 const eleven = ten + one;
12191175
...@@ -1222,7 +1178,6 @@ pub fn main(args: [][]u8) i32 => {...@@ -1222,7 +1178,6 @@ pub fn main(args: [][]u8) i32 => {
1222 }1178 }
12231179
1224 print_str("OK\n");1180 print_str("OK\n");
1225 return 0;
1226}1181}
1227 )SOURCE", "OK\n");1182 )SOURCE", "OK\n");
12281183
...@@ -1233,28 +1188,26 @@ struct Foo {...@@ -1233,28 +1188,26 @@ struct Foo {
1233 y: bool,1188 y: bool,
1234}1189}
1235var foo = Foo { .x = 13, .y = true, };1190var foo = Foo { .x = 13, .y = true, };
1236pub fn main(args: [][]u8) i32 => {1191pub fn main(args: [][]u8) %void => {
1237 foo.x += 1;1192 foo.x += 1;
1238 if (foo.x != 14) {1193 if (foo.x != 14) {
1239 print_str("BAD\n");1194 print_str("BAD\n");
1240 }1195 }
12411196
1242 print_str("OK\n");1197 print_str("OK\n");
1243 return 0;
1244}1198}
1245 )SOURCE", "OK\n");1199 )SOURCE", "OK\n");
12461200
1247 add_simple_case("statically initialized array literal", R"SOURCE(1201 add_simple_case("statically initialized array literal", R"SOURCE(
1248import "std.zig";1202import "std.zig";
1249const x = []u8{1,2,3,4};1203const x = []u8{1,2,3,4};
1250pub fn main(args: [][]u8) i32 => {1204pub fn main(args: [][]u8) %void => {
1251 const y : [4]u8 = x;1205 const y : [4]u8 = x;
1252 if (y[3] != 4) {1206 if (y[3] != 4) {
1253 print_str("BAD\n");1207 print_str("BAD\n");
1254 }1208 }
12551209
1256 print_str("OK\n");1210 print_str("OK\n");
1257 return 0;
1258}1211}
1259 )SOURCE", "OK\n");1212 )SOURCE", "OK\n");
12601213
...@@ -1262,7 +1215,7 @@ pub fn main(args: [][]u8) i32 => {...@@ -1262,7 +1215,7 @@ pub fn main(args: [][]u8) i32 => {
1262import "std.zig";1215import "std.zig";
1263%.err1;1216%.err1;
1264%.err2;1217%.err2;
1265pub fn main(args: [][]u8) i32 => {1218pub fn main(args: [][]u8) %void => {
1266 const a = i32(%.err1);1219 const a = i32(%.err1);
1267 const b = i32(%.err2);1220 const b = i32(%.err2);
1268 if (a == b) {1221 if (a == b) {
...@@ -1270,7 +1223,6 @@ pub fn main(args: [][]u8) i32 => {...@@ -1270,7 +1223,6 @@ pub fn main(args: [][]u8) i32 => {
1270 }1223 }
12711224
1272 print_str("OK\n");1225 print_str("OK\n");
1273 return 0;
1274}1226}
1275 )SOURCE", "OK\n");1227 )SOURCE", "OK\n");
12761228