authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-01-14 02:52:33-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-01-14 02:52:33-07:00
log5f9ecb8566645f16ff9bf8527c92c7db9baf9719
tree539e1d309e50a96ee243623e0788fb5cca4a5efe
parentd121ed961ac9fa58a5a6e2695dc62dbb01c60523

instead of 'as' to cast, call type as function


14 files changed, 533 insertions(+), 392 deletions(-)

README.md+6
...@@ -41,6 +41,12 @@ compromises backward compatibility....@@ -41,6 +41,12 @@ compromises backward compatibility.
41 provide a tag or sha1).41 provide a tag or sha1).
42 * Include documentation generator.42 * Include documentation generator.
43 * Shebang line OK so language can be used for "scripting" as well.43 * Shebang line OK so language can be used for "scripting" as well.
44 * Have the compiler run continuously, watching the file system for source
45 changes and automatically perform multithreaded compilation to build projects
46 quickly.
47 * Hot code swapping. When integrated with the previous feature, you could
48 press "save" in your editor and see the change immediately in your running
49 software.
4450
45### Current Status51### Current Status
4652
doc/langref.md+1-3
...@@ -126,12 +126,10 @@ AdditionExpression : MultiplyExpression AdditionOperator AdditionExpression | Mu...@@ -126,12 +126,10 @@ AdditionExpression : MultiplyExpression AdditionOperator AdditionExpression | Mu
126126
127AdditionOperator : token(Plus) | token(Minus)127AdditionOperator : token(Plus) | token(Minus)
128128
129MultiplyExpression : CastExpression MultiplyOperator MultiplyExpression | CastExpression129MultiplyExpression : PrefixOpExpression MultiplyOperator MultiplyExpression | PrefixOpExpression
130130
131MultiplyOperator : token(Star) | token(Slash) | token(Percent)131MultiplyOperator : token(Star) | token(Slash) | token(Percent)
132132
133CastExpression : CastExpression token(as) PrimaryExpression | PrefixOpExpression
134
135PrefixOpExpression : PrefixOp PrefixOpExpression | SuffixOpExpression133PrefixOpExpression : PrefixOp PrefixOpExpression | SuffixOpExpression
136134
137SuffixOpExpression : PrimaryExpression option(FnCallExpression | ArrayAccessExpression | FieldAccessExpression | SliceExpression | ContainerInitExpression)135SuffixOpExpression : PrimaryExpression option(FnCallExpression | ArrayAccessExpression | FieldAccessExpression | SliceExpression | ContainerInitExpression)
doc/vim/syntax/zig.vim-1
...@@ -7,7 +7,6 @@ if exists("b:current_syntax")...@@ -7,7 +7,6 @@ if exists("b:current_syntax")
7 finish7 finish
8endif8endif
99
10syn keyword zigOperator as
11syn keyword zigStorage const var extern volatile export pub noalias10syn keyword zigStorage const var extern volatile export pub noalias
12syn keyword zigStructure struct enum type11syn keyword zigStructure struct enum type
13syn keyword zigStatement goto break return continue asm12syn keyword zigStatement goto break return continue asm
example/guess_number/main.zig+1-1
...@@ -7,7 +7,7 @@ pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => {...@@ -7,7 +7,7 @@ pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => {
7 print_str("Welcome to the Guess Number Game in Zig.\n");7 print_str("Welcome to the Guess Number Game in Zig.\n");
88
9 var seed : u32;9 var seed : u32;
10 const err = os_get_random_bytes(&seed as (&u8), @sizeof(u32));10 const err = os_get_random_bytes((&u8)(&seed), @sizeof(u32));
11 if (err != @sizeof(u32)) {11 if (err != @sizeof(u32)) {
12 // TODO full error message12 // TODO full error message
13 fprint_str(stderr_fileno, "unable to get random bytes\n");13 fprint_str(stderr_fileno, "unable to get random bytes\n");
src/all_types.hpp+32-11
...@@ -106,7 +106,6 @@ enum NodeType {...@@ -106,7 +106,6 @@ enum NodeType {
106 NodeTypeReturnExpr,106 NodeTypeReturnExpr,
107 NodeTypeVariableDeclaration,107 NodeTypeVariableDeclaration,
108 NodeTypeBinOpExpr,108 NodeTypeBinOpExpr,
109 NodeTypeCastExpr,
110 NodeTypeNumberLiteral,109 NodeTypeNumberLiteral,
111 NodeTypeStringLiteral,110 NodeTypeStringLiteral,
112 NodeTypeCharLiteral,111 NodeTypeCharLiteral,
...@@ -272,6 +271,8 @@ struct AstNodeFnCallExpr {...@@ -272,6 +271,8 @@ struct AstNodeFnCallExpr {
272 BuiltinFnEntry *builtin_fn;271 BuiltinFnEntry *builtin_fn;
273 Expr resolved_expr;272 Expr resolved_expr;
274 NumLitCodeGen resolved_num_lit;273 NumLitCodeGen resolved_num_lit;
274 Cast cast;
275 FnTableEntry *fn_entry;
275};276};
276277
277struct AstNodeArrayAccessExpr {278struct AstNodeArrayAccessExpr {
...@@ -320,15 +321,6 @@ struct AstNodeRootExportDecl {...@@ -320,15 +321,6 @@ struct AstNodeRootExportDecl {
320 ZigList<AstNode *> *directives;321 ZigList<AstNode *> *directives;
321};322};
322323
323struct AstNodeCastExpr {
324 AstNode *expr;
325 AstNode *type;
326
327 // populated by semantic analyzer
328 Cast cast;
329 Expr resolved_expr;
330};
331
332enum PrefixOp {324enum PrefixOp {
333 PrefixOpInvalid,325 PrefixOpInvalid,
334 PrefixOpBoolNot,326 PrefixOpBoolNot,
...@@ -541,6 +533,9 @@ struct AstNodeSymbolExpr {...@@ -541,6 +533,9 @@ struct AstNodeSymbolExpr {
541533
542 // populated by semantic analyzer534 // populated by semantic analyzer
543 Expr resolved_expr;535 Expr resolved_expr;
536 VariableTableEntry *variable;
537 TypeTableEntry *meta_type;
538 FnTableEntry *fn_entry;
544};539};
545540
546struct AstNodeBoolLiteral {541struct AstNodeBoolLiteral {
...@@ -588,7 +583,6 @@ struct AstNode {...@@ -588,7 +583,6 @@ struct AstNode {
588 AstNodeBinOpExpr bin_op_expr;583 AstNodeBinOpExpr bin_op_expr;
589 AstNodeExternBlock extern_block;584 AstNodeExternBlock extern_block;
590 AstNodeDirective directive;585 AstNodeDirective directive;
591 AstNodeCastExpr cast_expr;
592 AstNodePrefixOpExpr prefix_op_expr;586 AstNodePrefixOpExpr prefix_op_expr;
593 AstNodeFnCallExpr fn_call_expr;587 AstNodeFnCallExpr fn_call_expr;
594 AstNodeArrayAccessExpr array_access_expr;588 AstNodeArrayAccessExpr array_access_expr;
...@@ -693,6 +687,12 @@ struct TypeTableEntryEnum {...@@ -693,6 +687,12 @@ struct TypeTableEntryEnum {
693 bool reported_infinite_err;687 bool reported_infinite_err;
694};688};
695689
690struct TypeTableEntryFn {
691 TypeTableEntry *return_type;
692 TypeTableEntry **param_types;
693 int param_count;
694};
695
696enum TypeTableEntryId {696enum TypeTableEntryId {
697 TypeTableEntryIdInvalid,697 TypeTableEntryIdInvalid,
698 TypeTableEntryIdMetaType,698 TypeTableEntryIdMetaType,
...@@ -707,6 +707,7 @@ enum TypeTableEntryId {...@@ -707,6 +707,7 @@ enum TypeTableEntryId {
707 TypeTableEntryIdNumberLiteral,707 TypeTableEntryIdNumberLiteral,
708 TypeTableEntryIdMaybe,708 TypeTableEntryIdMaybe,
709 TypeTableEntryIdEnum,709 TypeTableEntryIdEnum,
710 TypeTableEntryIdFn,
710};711};
711712
712struct TypeTableEntry {713struct TypeTableEntry {
...@@ -728,6 +729,7 @@ struct TypeTableEntry {...@@ -728,6 +729,7 @@ struct TypeTableEntry {
728 TypeTableEntryMaybe maybe;729 TypeTableEntryMaybe maybe;
729 TypeTableEntryEnum enumeration;730 TypeTableEntryEnum enumeration;
730 TypeTableEntryMetaType meta_type;731 TypeTableEntryMetaType meta_type;
732 TypeTableEntryFn fn;
731 } data;733 } data;
732734
733 // use these fields to make sure we don't duplicate type table entries for the same type735 // use these fields to make sure we don't duplicate type table entries for the same type
...@@ -781,6 +783,7 @@ struct FnTableEntry {...@@ -781,6 +783,7 @@ struct FnTableEntry {
781 ZigList<BlockContext *> all_block_contexts;783 ZigList<BlockContext *> all_block_contexts;
782 TypeTableEntry *member_of_struct;784 TypeTableEntry *member_of_struct;
783 Buf symbol_name;785 Buf symbol_name;
786 TypeTableEntry *type_entry; // function type
784787
785 // reminder: hash tables must be initialized before use788 // reminder: hash tables must be initialized before use
786 HashMap<Buf *, LabelTableEntry *, buf_hash, buf_eql_buf> label_table;789 HashMap<Buf *, LabelTableEntry *, buf_hash, buf_eql_buf> label_table;
...@@ -913,4 +916,22 @@ struct BlockContext {...@@ -913,4 +916,22 @@ struct BlockContext {
913 LLVMZigDIScope *di_scope;916 LLVMZigDIScope *di_scope;
914};917};
915918
919struct ConstExprValue {
920 bool ok; // true if constant expression evalution worked
921 bool depends_on_compile_var;
922
923 union {
924 uint64_t x_uint;
925 int64_t x_int;
926 double x_float;
927 bool x_bool;
928 FnTableEntry *x_fn;
929 TypeTableEntry *x_type;
930 struct {
931 bool is_null;
932 ConstExprValue *child_val;
933 } x_maybe;
934 } data;
935};
936
916#endif937#endif
src/analyze.cpp+405-242
...@@ -13,8 +13,8 @@...@@ -13,8 +13,8 @@
1313
14static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import, BlockContext *context,14static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import, BlockContext *context,
15 TypeTableEntry *expected_type, AstNode *node);15 TypeTableEntry *expected_type, AstNode *node);
16static TypeTableEntry *eval_const_expr(CodeGen *g, BlockContext *context,16static void eval_const_expr(CodeGen *g, BlockContext *context,
17 AstNode *node, AstNodeNumberLiteral *out_number_literal);17 AstNode *node, ConstExprValue *out_val);
18static VariableTableEntry *analyze_variable_declaration(CodeGen *g, ImportTableEntry *import,18static VariableTableEntry *analyze_variable_declaration(CodeGen *g, ImportTableEntry *import,
19 BlockContext *context, TypeTableEntry *expected_type, AstNode *node);19 BlockContext *context, TypeTableEntry *expected_type, AstNode *node);
20static void resolve_struct_type(CodeGen *g, ImportTableEntry *import, TypeTableEntry *struct_type);20static void resolve_struct_type(CodeGen *g, ImportTableEntry *import, TypeTableEntry *struct_type);
...@@ -32,8 +32,6 @@ static AstNode *first_executing_node(AstNode *node) {...@@ -32,8 +32,6 @@ static AstNode *first_executing_node(AstNode *node) {
32 return first_executing_node(node->data.slice_expr.array_ref_expr);32 return first_executing_node(node->data.slice_expr.array_ref_expr);
33 case NodeTypeFieldAccessExpr:33 case NodeTypeFieldAccessExpr:
34 return first_executing_node(node->data.field_access_expr.struct_expr);34 return first_executing_node(node->data.field_access_expr.struct_expr);
35 case NodeTypeCastExpr:
36 return first_executing_node(node->data.cast_expr.expr);
37 case NodeTypeRoot:35 case NodeTypeRoot:
38 case NodeTypeRootExportDecl:36 case NodeTypeRootExportDecl:
39 case NodeTypeFnProto:37 case NodeTypeFnProto:
...@@ -125,6 +123,7 @@ TypeTableEntry *new_type_table_entry(TypeTableEntryId id) {...@@ -125,6 +123,7 @@ TypeTableEntry *new_type_table_entry(TypeTableEntryId id) {
125 case TypeTableEntryIdArray:123 case TypeTableEntryIdArray:
126 case TypeTableEntryIdNumberLiteral:124 case TypeTableEntryIdNumberLiteral:
127 case TypeTableEntryIdMaybe:125 case TypeTableEntryIdMaybe:
126 case TypeTableEntryIdFn:
128 // nothing to init127 // nothing to init
129 break;128 break;
130 case TypeTableEntryIdStruct:129 case TypeTableEntryIdStruct:
...@@ -357,63 +356,74 @@ static TypeTableEntry *analyze_type_expr(CodeGen *g, ImportTableEntry *import, B...@@ -357,63 +356,74 @@ static TypeTableEntry *analyze_type_expr(CodeGen *g, ImportTableEntry *import, B
357 }356 }
358}357}
359358
360359static void eval_const_expr_bin_op(CodeGen *g, BlockContext *context,
361static TypeTableEntry *eval_const_expr_bin_op(CodeGen *g, BlockContext *context,360 AstNode *node, ConstExprValue *out_val)
362 AstNode *node, AstNodeNumberLiteral *out_number_literal)
363{361{
364 AstNodeNumberLiteral op1_lit;362 AstNode *op1_node = node->data.bin_op_expr.op1;
365 AstNodeNumberLiteral op2_lit;363 AstNode *op2_node = node->data.bin_op_expr.op2;
366 TypeTableEntry *op1_type = eval_const_expr(g, context, node->data.bin_op_expr.op1, &op1_lit);364 ConstExprValue op1_val = {0};
367 TypeTableEntry *op2_type = eval_const_expr(g, context, node->data.bin_op_expr.op1, &op2_lit);365 ConstExprValue op2_val = {0};
368366 eval_const_expr(g, context, op1_node, &op1_val);
369 if (op1_type->id == TypeTableEntryIdInvalid ||367 eval_const_expr(g, context, op2_node, &op2_val);
370 op2_type->id == TypeTableEntryIdInvalid)368
371 {369 if (!op1_val.ok || !op2_val.ok) {
372 return g->builtin_types.entry_invalid;370 return;
373 }371 }
374372
373 TypeTableEntry *op1_type = get_resolved_expr(op1_node)->type_entry;
374 TypeTableEntry *op2_type = get_resolved_expr(op2_node)->type_entry;
375
375 // TODO complete more of this function instead of returning invalid376 // TODO complete more of this function instead of returning invalid
376 // returning invalid makes the "unable to evaluate constant expression" error377 // returning invalid makes the "unable to evaluate constant expression" error
377378
378 switch (node->data.bin_op_expr.bin_op) {379 switch (node->data.bin_op_expr.bin_op) {
379 case BinOpTypeCmpNotEq:380 case BinOpTypeCmpNotEq:
380 {381 {
381 if (is_num_lit_unsigned(op1_lit.kind) &&382 if (op1_type->id == TypeTableEntryIdInt &&
382 is_num_lit_unsigned(op2_lit.kind))383 op2_type->id == TypeTableEntryIdInt)
383 {384 {
384 out_number_literal->kind = NumLitU8;385 out_val->data.x_bool = (op1_val.data.x_uint == op2_val.data.x_uint);
385 out_number_literal->overflow = false;386 out_val->ok = true;
386 out_number_literal->data.x_uint = (op1_lit.data.x_uint != op2_lit.data.x_uint);
387 return get_resolved_expr(node)->type_entry;
388 } else {
389 return g->builtin_types.entry_invalid;
390 }387 }
388 break;
391 }389 }
392 case BinOpTypeCmpLessThan:390 case BinOpTypeCmpLessThan:
393 {391 {
394 if (is_num_lit_unsigned(op1_lit.kind) &&392 if (op1_type->id == TypeTableEntryIdInt &&
395 is_num_lit_unsigned(op2_lit.kind))393 op2_type->id == TypeTableEntryIdInt)
396 {394 {
397 out_number_literal->kind = NumLitU8;395 if (op1_type->data.integral.is_signed &&
398 out_number_literal->overflow = false;396 op2_type->data.integral.is_signed)
399 out_number_literal->data.x_uint = (op1_lit.data.x_uint < op2_lit.data.x_uint);397 {
400 return get_resolved_expr(node)->type_entry;398 out_val->data.x_bool = (op1_val.data.x_int < op2_val.data.x_int);
401 } else {399 out_val->ok = true;
402 return g->builtin_types.entry_invalid;400 } else if (!op1_type->data.integral.is_signed &&
401 !op2_type->data.integral.is_signed)
402 {
403 out_val->data.x_bool = (op1_val.data.x_uint < op2_val.data.x_uint);
404 out_val->ok = true;
405 }
403 }406 }
407 break;
404 }408 }
405 case BinOpTypeMod:409 case BinOpTypeMod:
406 {410 {
407 if (is_num_lit_unsigned(op1_lit.kind) &&411 if (op1_type->id == TypeTableEntryIdInt &&
408 is_num_lit_unsigned(op2_lit.kind))412 op2_type->id == TypeTableEntryIdInt)
409 {413 {
410 out_number_literal->kind = NumLitU64;414 if (op1_type->data.integral.is_signed &&
411 out_number_literal->overflow = false;415 op2_type->data.integral.is_signed)
412 out_number_literal->data.x_uint = (op1_lit.data.x_uint % op2_lit.data.x_uint);416 {
413 return get_resolved_expr(node)->type_entry;417 out_val->data.x_int = op1_val.data.x_int % op2_val.data.x_int;
414 } else {418 out_val->ok = true;
415 return g->builtin_types.entry_invalid;419 } else if (!op1_type->data.integral.is_signed &&
420 !op2_type->data.integral.is_signed)
421 {
422 out_val->data.x_uint = op1_val.data.x_uint % op2_val.data.x_uint;
423 out_val->ok = true;
424 }
416 }425 }
426 break;
417 }427 }
418 case BinOpTypeBoolOr:428 case BinOpTypeBoolOr:
419 case BinOpTypeBoolAnd:429 case BinOpTypeBoolAnd:
...@@ -431,7 +441,7 @@ static TypeTableEntry *eval_const_expr_bin_op(CodeGen *g, BlockContext *context,...@@ -431,7 +441,7 @@ static TypeTableEntry *eval_const_expr_bin_op(CodeGen *g, BlockContext *context,
431 case BinOpTypeMult:441 case BinOpTypeMult:
432 case BinOpTypeDiv:442 case BinOpTypeDiv:
433 case BinOpTypeUnwrapMaybe:443 case BinOpTypeUnwrapMaybe:
434 return g->builtin_types.entry_invalid;444 break;
435 case BinOpTypeInvalid:445 case BinOpTypeInvalid:
436 case BinOpTypeAssign:446 case BinOpTypeAssign:
437 case BinOpTypeAssignTimes:447 case BinOpTypeAssignTimes:
...@@ -448,31 +458,23 @@ static TypeTableEntry *eval_const_expr_bin_op(CodeGen *g, BlockContext *context,...@@ -448,31 +458,23 @@ static TypeTableEntry *eval_const_expr_bin_op(CodeGen *g, BlockContext *context,
448 case BinOpTypeAssignBoolOr:458 case BinOpTypeAssignBoolOr:
449 zig_unreachable();459 zig_unreachable();
450 }460 }
451 zig_unreachable();
452}461}
453462
454static TypeTableEntry *eval_const_expr_fn_call(CodeGen *g, BlockContext *context,463static void eval_const_expr_builtin(CodeGen *g, BlockContext *context, AstNode *node, ConstExprValue *out_val) {
455 AstNode *node, AstNodeNumberLiteral *out_number_literal)
456{
457 if (!node->data.fn_call_expr.is_builtin) {
458 return g->builtin_types.entry_invalid;
459 }
460
461 switch (node->data.fn_call_expr.builtin_fn->id) {464 switch (node->data.fn_call_expr.builtin_fn->id) {
462 case BuiltinFnIdInvalid:465 case BuiltinFnIdInvalid:
463 zig_unreachable();466 zig_unreachable();
464 case BuiltinFnIdArithmeticWithOverflow:467 case BuiltinFnIdArithmeticWithOverflow:
465 case BuiltinFnIdMemcpy:468 case BuiltinFnIdMemcpy:
466 case BuiltinFnIdMemset:469 case BuiltinFnIdMemset:
467 return g->builtin_types.entry_invalid;470 break;
468 case BuiltinFnIdSizeof:471 case BuiltinFnIdSizeof:
469 {472 {
470 AstNode *type_node = node->data.fn_call_expr.params.at(0);473 AstNode *type_node = node->data.fn_call_expr.params.at(0);
471 TypeTableEntry *target_type = unwrapped_node_type(type_node);474 TypeTableEntry *target_type = unwrapped_node_type(type_node);
472 out_number_literal->overflow = false;475 out_val->data.x_uint = target_type->size_in_bits / 8;
473 out_number_literal->data.x_uint = target_type->size_in_bits / 8;476 out_val->ok = true;
474 out_number_literal->kind = get_number_literal_kind_unsigned(out_number_literal->data.x_uint);477 break;
475 return get_resolved_expr(node)->type_entry;
476 }478 }
477 case BuiltinFnIdMaxValue:479 case BuiltinFnIdMaxValue:
478 case BuiltinFnIdMinValue:480 case BuiltinFnIdMinValue:
...@@ -480,43 +482,154 @@ static TypeTableEntry *eval_const_expr_fn_call(CodeGen *g, BlockContext *context...@@ -480,43 +482,154 @@ static TypeTableEntry *eval_const_expr_fn_call(CodeGen *g, BlockContext *context
480 case BuiltinFnIdValueCount:482 case BuiltinFnIdValueCount:
481 zig_panic("TODO eval_const_expr_fn_call value_count");483 zig_panic("TODO eval_const_expr_fn_call value_count");
482 case BuiltinFnIdTypeof:484 case BuiltinFnIdTypeof:
483 return get_resolved_expr(node)->type_entry;485 // TODO
486 out_val->ok = true;
487 break;
484 }488 }
485 zig_unreachable();
486}489}
487490
488static TypeTableEntry *eval_const_expr(CodeGen *g, BlockContext *context,491static void eval_const_expr_fn_call_known(CodeGen *g, BlockContext *context,
489 AstNode *node, AstNodeNumberLiteral *out_number_literal)492 AstNode *node, ConstExprValue *out_val)
493{
494 // currently no functions can be constant expression evaluated,
495 // so we do nothing
496}
497
498static void eval_const_expr_fn_call_cast(CodeGen *g, BlockContext *context,
499 AstNode *node, ConstExprValue *out_val)
500{
501 assert(node->type == NodeTypeFnCallExpr);
502 AstNode *expr_node = node->data.fn_call_expr.params.at(0);
503 Cast *cast = &node->data.fn_call_expr.cast;
504 switch (cast->op) {
505 case CastOpNothing:
506 case CastOpPtrToInt:
507 case CastOpPointerReinterpret:
508 case CastOpIntWidenOrShorten:
509 {
510 eval_const_expr(g, context, expr_node, out_val);
511 break;
512 }
513 case CastOpMaybeWrap:
514 {
515 ConstExprValue *child_val = allocate<ConstExprValue>(1);
516 eval_const_expr(g, context, expr_node, child_val);
517 if (!child_val->ok) {
518 return;
519 }
520 out_val->data.x_maybe.child_val = child_val;
521 out_val->data.x_maybe.is_null = false;
522 out_val->ok = true;
523 break;
524 }
525 case CastOpToUnknownSizeArray:
526 zig_panic("TODO eval_const_expr CastOpToUnknownSizeArray");
527 }
528}
529
530static void eval_const_expr_fn_call(CodeGen *g, BlockContext *context,
531 AstNode *node, ConstExprValue *out_val)
532{
533 if (node->data.fn_call_expr.is_builtin) {
534 return eval_const_expr_builtin(g, context, node, out_val);
535 }
536 if (node->data.fn_call_expr.fn_entry) {
537 return eval_const_expr_fn_call_known(g, context, node, out_val);
538 }
539 return eval_const_expr_fn_call_cast(g, context, node, out_val);
540}
541
542static void eval_const_expr_prefix_op_expr(CodeGen *g, BlockContext *context, AstNode *node,
543 ConstExprValue *out_val)
490{544{
545 AstNode *expr_node = node->data.prefix_op_expr.primary_expr;
546 switch (node->data.prefix_op_expr.prefix_op) {
547 case PrefixOpInvalid:
548 zig_unreachable();
549 case PrefixOpBoolNot:
550 {
551 eval_const_expr(g, context, expr_node, out_val);
552 if (out_val->ok) {
553 out_val->data.x_bool = !out_val->data.x_bool;
554 }
555 break;
556 }
557 case PrefixOpBinNot:
558 break;
559 case PrefixOpNegation:
560 break;
561 case PrefixOpAddressOf:
562 {
563 if (get_resolved_expr(node)->type_entry->id == TypeTableEntryIdMetaType) {
564 eval_const_expr(g, context, expr_node, out_val);
565 }
566 break;
567 }
568 case PrefixOpConstAddressOf:
569 break;
570 case PrefixOpDereference:
571 break;
572 case PrefixOpMaybe:
573 break;
574 }
575}
576
577static void eval_const_expr(CodeGen *g, BlockContext *context, AstNode *node, ConstExprValue *out_val) {
491 switch (node->type) {578 switch (node->type) {
492 case NodeTypeNumberLiteral:579 case NodeTypeNumberLiteral:
493 *out_number_literal = node->data.number_literal;580 {
494 return get_resolved_expr(node)->type_entry;581 if (is_num_lit_unsigned(node->data.number_literal.kind)) {
582 out_val->data.x_uint = node->data.number_literal.data.x_uint;
583 out_val->ok = true;
584 } else if (is_num_lit_float(node->data.number_literal.kind)) {
585 out_val->data.x_uint = node->data.number_literal.data.x_float;
586 out_val->ok = true;
587 }
588 break;
589 }
495 case NodeTypeBoolLiteral:590 case NodeTypeBoolLiteral:
496 out_number_literal->data.x_uint = node->data.bool_literal.value ? 1 : 0;591 out_val->data.x_uint = node->data.bool_literal.value ? 1 : 0;
497 return get_resolved_expr(node)->type_entry;592 out_val->ok = true;
593 break;
498 case NodeTypeNullLiteral:594 case NodeTypeNullLiteral:
499 return get_resolved_expr(node)->type_entry;595 out_val->data.x_maybe.is_null = true;
596 out_val->ok = true;
597 break;
500 case NodeTypeBinOpExpr:598 case NodeTypeBinOpExpr:
501 return eval_const_expr_bin_op(g, context, node, out_number_literal);599 eval_const_expr_bin_op(g, context, node, out_val);
600 break;
502 case NodeTypeSymbol:601 case NodeTypeSymbol:
503 {602 {
504 VariableTableEntry *var = find_variable(context, &node->data.symbol_expr.symbol);603 VariableTableEntry *var = node->data.symbol_expr.variable;
505 assert(var);604 if (var) {
506 AstNode *decl_node = var->decl_node;605 if (var->is_const) {
507 AstNode *expr_node = decl_node->data.variable_declaration.expr;606 AstNode *decl_node = var->decl_node;
508 if (expr_node) {607 if (decl_node->type == NodeTypeVariableDeclaration) {
509 BlockContext *next_context = get_resolved_expr(expr_node)->block_context;608 AstNode *expr_node = decl_node->data.variable_declaration.expr;
510 return eval_const_expr(g, next_context, expr_node, out_number_literal);609 if (expr_node) {
610 BlockContext *next_context = get_resolved_expr(expr_node)->block_context;
611 eval_const_expr(g, next_context, expr_node, out_val);
612 }
613 }
614 }
615 } else if (node->data.symbol_expr.meta_type) {
616 out_val->ok = true;
617 } else if (node->data.symbol_expr.fn_entry) {
618 out_val->ok = true;
619 out_val->data.x_fn = node->data.symbol_expr.fn_entry;
511 } else {620 } else {
512 // can't eval it621 zig_unreachable();
513 return g->builtin_types.entry_invalid;
514 }622 }
623 break;
515 }624 }
516 case NodeTypeFnCallExpr:625 case NodeTypeFnCallExpr:
517 return eval_const_expr_fn_call(g, context, node, out_number_literal);626 eval_const_expr_fn_call(g, context, node, out_val);
627 break;
628 case NodeTypePrefixOpExpr:
629 eval_const_expr_prefix_op_expr(g, context, node, out_val);
630 break;
518 default:631 default:
519 return g->builtin_types.entry_invalid;632 break;
520 }633 }
521}634}
522635
...@@ -550,11 +663,30 @@ static void resolve_function_proto(CodeGen *g, AstNode *node, FnTableEntry *fn_t...@@ -550,11 +663,30 @@ static void resolve_function_proto(CodeGen *g, AstNode *node, FnTableEntry *fn_t
550 }663 }
551 }664 }
552665
553 for (int i = 0; i < node->data.fn_proto.params.length; i += 1) {666 int param_count = node->data.fn_proto.params.length;
667
668 TypeTableEntry *fn_type = new_type_table_entry(TypeTableEntryIdFn);
669 fn_type->data.fn.param_count = param_count;
670 fn_type->data.fn.param_types = allocate<TypeTableEntry*>(param_count);
671
672 fn_table_entry->type_entry = fn_type;
673
674 Buf *name = &node->data.fn_proto.name;
675 buf_resize(&fn_type->name, 0);
676 buf_appendf(&fn_type->name, "fn %s(", buf_ptr(name));
677 for (int i = 0; i < param_count; i += 1) {
554 AstNode *child = node->data.fn_proto.params.at(i);678 AstNode *child = node->data.fn_proto.params.at(i);
555 assert(child->type == NodeTypeParamDecl);679 assert(child->type == NodeTypeParamDecl);
556 TypeTableEntry *type_entry = analyze_type_expr(g, import, import->block_context,680 TypeTableEntry *type_entry = analyze_type_expr(g, import, import->block_context,
557 child->data.param_decl.type);681 child->data.param_decl.type);
682 fn_table_entry->type_entry->data.fn.param_types[i] = type_entry;
683
684 buf_appendf(&fn_type->name, "%s : %s",
685 buf_ptr(&child->data.param_decl.name), buf_ptr(&type_entry->name));
686
687 if (i + 1 < param_count) {
688 buf_appendf(&fn_type->name, ", ");
689 }
558690
559 if (type_entry->id == TypeTableEntryIdUnreachable) {691 if (type_entry->id == TypeTableEntryIdUnreachable) {
560 add_node_error(g, child->data.param_decl.type,692 add_node_error(g, child->data.param_decl.type,
...@@ -567,7 +699,14 @@ static void resolve_function_proto(CodeGen *g, AstNode *node, FnTableEntry *fn_t...@@ -567,7 +699,14 @@ static void resolve_function_proto(CodeGen *g, AstNode *node, FnTableEntry *fn_t
567 }699 }
568 }700 }
569701
570 analyze_type_expr(g, import, import->block_context, node->data.fn_proto.return_type);702 TypeTableEntry *return_type = analyze_type_expr(g, import, import->block_context,
703 node->data.fn_proto.return_type);
704 fn_table_entry->type_entry->data.fn.return_type = return_type;
705
706 buf_appendf(&fn_type->name, ")");
707 if (return_type->id != TypeTableEntryIdVoid) {
708 buf_appendf(&fn_type->name, " %s", buf_ptr(&return_type->name));
709 }
571}710}
572711
573static void preview_function_labels(CodeGen *g, AstNode *node, FnTableEntry *fn_table_entry) {712static void preview_function_labels(CodeGen *g, AstNode *node, FnTableEntry *fn_table_entry) {
...@@ -1058,7 +1197,6 @@ static void resolve_top_level_decl(CodeGen *g, ImportTableEntry *import, AstNode...@@ -1058,7 +1197,6 @@ static void resolve_top_level_decl(CodeGen *g, ImportTableEntry *import, AstNode
1058 case NodeTypeBoolLiteral:1197 case NodeTypeBoolLiteral:
1059 case NodeTypeNullLiteral:1198 case NodeTypeNullLiteral:
1060 case NodeTypeSymbol:1199 case NodeTypeSymbol:
1061 case NodeTypeCastExpr:
1062 case NodeTypePrefixOpExpr:1200 case NodeTypePrefixOpExpr:
1063 case NodeTypeIfBoolExpr:1201 case NodeTypeIfBoolExpr:
1064 case NodeTypeIfVarExpr:1202 case NodeTypeIfVarExpr:
...@@ -1116,6 +1254,7 @@ static bool num_lit_fits_in_other_type(CodeGen *g, TypeTableEntry *literal_type,...@@ -1116,6 +1254,7 @@ static bool num_lit_fits_in_other_type(CodeGen *g, TypeTableEntry *literal_type,
1116 case TypeTableEntryIdStruct:1254 case TypeTableEntryIdStruct:
1117 case TypeTableEntryIdEnum:1255 case TypeTableEntryIdEnum:
1118 case TypeTableEntryIdMetaType:1256 case TypeTableEntryIdMetaType:
1257 case TypeTableEntryIdFn:
1119 return false;1258 return false;
1120 case TypeTableEntryIdInt:1259 case TypeTableEntryIdInt:
1121 if (is_num_lit_unsigned(num_lit)) {1260 if (is_num_lit_unsigned(num_lit)) {
...@@ -1703,17 +1842,28 @@ static TypeTableEntry *analyze_symbol_expr(CodeGen *g, ImportTableEntry *import,...@@ -1703,17 +1842,28 @@ static TypeTableEntry *analyze_symbol_expr(CodeGen *g, ImportTableEntry *import,
17031842
1704 auto primitive_table_entry = g->primitive_type_table.maybe_get(variable_name);1843 auto primitive_table_entry = g->primitive_type_table.maybe_get(variable_name);
1705 if (primitive_table_entry) {1844 if (primitive_table_entry) {
1706 return get_meta_type(g, primitive_table_entry->value);1845 TypeTableEntry *meta_type = get_meta_type(g, primitive_table_entry->value);
1846 node->data.symbol_expr.meta_type = meta_type;
1847 return meta_type;
1707 }1848 }
17081849
1709 VariableTableEntry *var = find_variable(context, variable_name);1850 VariableTableEntry *var = find_variable(context, variable_name);
1710 if (var) {1851 if (var) {
1852 node->data.symbol_expr.variable = var;
1711 return var->type;1853 return var->type;
1712 }1854 }
17131855
1714 TypeTableEntry *container_type = find_container(context, variable_name);1856 TypeTableEntry *container_type = find_container(context, variable_name);
1715 if (container_type) {1857 if (container_type) {
1716 return get_meta_type(g, container_type);1858 TypeTableEntry *meta_type = get_meta_type(g, container_type);
1859 node->data.symbol_expr.meta_type = meta_type;
1860 return meta_type;
1861 }
1862
1863 auto fn_table_entry = import->fn_table.maybe_get(variable_name);
1864 if (fn_table_entry) {
1865 node->data.symbol_expr.fn_entry = fn_table_entry->value;
1866 return node->data.symbol_expr.fn_entry->type_entry;
1717 }1867 }
17181868
1719 add_node_error(g, node, buf_sprintf("use of undeclared identifier '%s'", buf_ptr(variable_name)));1869 add_node_error(g, node, buf_sprintf("use of undeclared identifier '%s'", buf_ptr(variable_name)));
...@@ -1781,65 +1931,6 @@ static bool is_op_allowed(TypeTableEntry *type, BinOpType op) {...@@ -1781,65 +1931,6 @@ static bool is_op_allowed(TypeTableEntry *type, BinOpType op) {
1781 zig_unreachable();1931 zig_unreachable();
1782}1932}
17831933
1784static TypeTableEntry *analyze_cast_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
1785 TypeTableEntry *expected_type, AstNode *node)
1786{
1787 assert(node->type == NodeTypeCastExpr);
1788
1789 TypeTableEntry *wanted_type = analyze_type_expr(g, import, context, node->data.cast_expr.type);
1790 TypeTableEntry *actual_type = analyze_expression(g, import, context, nullptr, node->data.cast_expr.expr);
1791
1792 if (wanted_type->id == TypeTableEntryIdInvalid ||
1793 actual_type->id == TypeTableEntryIdInvalid)
1794 {
1795 return g->builtin_types.entry_invalid;
1796 }
1797
1798 Cast *cast = &node->data.cast_expr.cast;
1799 cast->source_node = node;
1800 cast->after_type = wanted_type;
1801
1802 if ((wanted_type == g->builtin_types.entry_isize || wanted_type == g->builtin_types.entry_usize) &&
1803 actual_type->id == TypeTableEntryIdPointer)
1804 {
1805 cast->op = CastOpPtrToInt;
1806 return wanted_type;
1807 } else if (wanted_type->id == TypeTableEntryIdInt &&
1808 actual_type->id == TypeTableEntryIdInt)
1809 {
1810 cast->op = CastOpIntWidenOrShorten;
1811 return wanted_type;
1812 } else if (wanted_type->id == TypeTableEntryIdStruct &&
1813 wanted_type->data.structure.is_unknown_size_array &&
1814 actual_type->id == TypeTableEntryIdArray &&
1815 actual_type->data.array.child_type == wanted_type->data.structure.fields[0].type_entry)
1816 {
1817 cast->op = CastOpToUnknownSizeArray;
1818 context->cast_expr_alloca_list.append(cast);
1819 return wanted_type;
1820 } else if (actual_type->id == TypeTableEntryIdNumberLiteral &&
1821 num_lit_fits_in_other_type(g, actual_type, wanted_type))
1822 {
1823 AstNode *literal_node = node->data.cast_expr.expr;
1824 NumLitCodeGen *codegen_num_lit = get_resolved_num_lit(literal_node);
1825 assert(!codegen_num_lit->resolved_type);
1826 codegen_num_lit->resolved_type = wanted_type;
1827 cast->op = CastOpNothing;
1828 return wanted_type;
1829 } else if (actual_type->id == TypeTableEntryIdPointer &&
1830 wanted_type->id == TypeTableEntryIdPointer)
1831 {
1832 cast->op = CastOpPointerReinterpret;
1833 return wanted_type;
1834 } else {
1835 add_node_error(g, node,
1836 buf_sprintf("invalid cast from type '%s' to '%s'",
1837 buf_ptr(&actual_type->name),
1838 buf_ptr(&wanted_type->name)));
1839 return g->builtin_types.entry_invalid;
1840 }
1841}
1842
1843enum LValPurpose {1934enum LValPurpose {
1844 LValPurposeAssign,1935 LValPurposeAssign,
1845 LValPurposeAddressOf,1936 LValPurposeAddressOf,
...@@ -2153,17 +2244,11 @@ static TypeTableEntry *analyze_array_type(CodeGen *g, ImportTableEntry *import,...@@ -2153,17 +2244,11 @@ static TypeTableEntry *analyze_array_type(CodeGen *g, ImportTableEntry *import,
2153 return g->builtin_types.entry_invalid;2244 return g->builtin_types.entry_invalid;
2154 }2245 }
21552246
2156 AstNodeNumberLiteral number_literal;2247 ConstExprValue const_val = {0};
2157 TypeTableEntry *resolved_type = eval_const_expr(g, context, size_node, &number_literal);2248 eval_const_expr(g, context, size_node, &const_val);
21582249
2159 if (resolved_type->id == TypeTableEntryIdInt) {2250 if (const_val.ok) {
2160 if (resolved_type->data.integral.is_signed) {2251 return get_meta_type(g, get_array_type(g, import, child_type, const_val.data.x_uint));
2161 add_node_error(g, size_node,
2162 buf_create_from_str("array size must be unsigned integer"));
2163 return g->builtin_types.entry_invalid;
2164 } else {
2165 return get_meta_type(g, get_array_type(g, import, child_type, number_literal.data.x_uint));
2166 }
2167 } else {2252 } else {
2168 add_node_error(g, size_node,2253 add_node_error(g, size_node,
2169 buf_create_from_str("unable to resolve constant expression"));2254 buf_create_from_str("unable to resolve constant expression"));
...@@ -2195,12 +2280,11 @@ static TypeTableEntry *analyze_while_expr(CodeGen *g, ImportTableEntry *import,...@@ -2195,12 +2280,11 @@ static TypeTableEntry *analyze_while_expr(CodeGen *g, ImportTableEntry *import,
2195 } else {2280 } else {
2196 // if the condition is a simple constant expression and there are no break statements2281 // if the condition is a simple constant expression and there are no break statements
2197 // then the return type is unreachable2282 // then the return type is unreachable
2198 AstNodeNumberLiteral number_literal;2283 ConstExprValue const_val = {0};
2199 TypeTableEntry *resolved_type = eval_const_expr(g, context, condition_node, &number_literal);2284 eval_const_expr(g, context, condition_node, &const_val);
2200 if (resolved_type->id != TypeTableEntryIdInvalid) {2285
2201 assert(resolved_type->id == TypeTableEntryIdBool);2286 if (const_val.ok) {
2202 bool constant_cond_value = number_literal.data.x_uint;2287 if (const_val.data.x_bool) {
2203 if (constant_cond_value) {
2204 node->data.while_expr.condition_always_true = true;2288 node->data.while_expr.condition_always_true = true;
2205 if (!node->data.while_expr.contains_break) {2289 if (!node->data.while_expr.contains_break) {
2206 expr_return_type = g->builtin_types.entry_unreachable;2290 expr_return_type = g->builtin_types.entry_unreachable;
...@@ -2305,6 +2389,73 @@ static TypeTableEntry *analyze_min_max_value(CodeGen *g, ImportTableEntry *impor...@@ -2305,6 +2389,73 @@ static TypeTableEntry *analyze_min_max_value(CodeGen *g, ImportTableEntry *impor
2305 }2389 }
2306}2390}
23072391
2392static TypeTableEntry *analyze_cast_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
2393 AstNode *node, TypeTableEntry *invoke_type_entry)
2394{
2395 assert(node->type == NodeTypeFnCallExpr);
2396
2397 AstNode *fn_ref_expr = node->data.fn_call_expr.fn_ref_expr;
2398 int actual_param_count = node->data.fn_call_expr.params.length;
2399
2400 if (actual_param_count != 1) {
2401 add_node_error(g, fn_ref_expr, buf_sprintf("cast expression expects exactly one parameter"));
2402 return g->builtin_types.entry_invalid;
2403 }
2404
2405 AstNode *expr_node = node->data.fn_call_expr.params.at(0);
2406 TypeTableEntry *wanted_type = invoke_type_entry->data.meta_type.child_type;
2407 TypeTableEntry *actual_type = analyze_expression(g, import, context, nullptr, expr_node);
2408
2409 if (wanted_type->id == TypeTableEntryIdInvalid ||
2410 actual_type->id == TypeTableEntryIdInvalid)
2411 {
2412 return g->builtin_types.entry_invalid;
2413 }
2414
2415 Cast *cast = &node->data.fn_call_expr.cast;
2416 cast->source_node = node;
2417 cast->after_type = wanted_type;
2418
2419 if ((wanted_type == g->builtin_types.entry_isize || wanted_type == g->builtin_types.entry_usize) &&
2420 actual_type->id == TypeTableEntryIdPointer)
2421 {
2422 cast->op = CastOpPtrToInt;
2423 return wanted_type;
2424 } else if (wanted_type->id == TypeTableEntryIdInt &&
2425 actual_type->id == TypeTableEntryIdInt)
2426 {
2427 cast->op = CastOpIntWidenOrShorten;
2428 return wanted_type;
2429 } else if (wanted_type->id == TypeTableEntryIdStruct &&
2430 wanted_type->data.structure.is_unknown_size_array &&
2431 actual_type->id == TypeTableEntryIdArray &&
2432 actual_type->data.array.child_type == wanted_type->data.structure.fields[0].type_entry)
2433 {
2434 cast->op = CastOpToUnknownSizeArray;
2435 context->cast_expr_alloca_list.append(cast);
2436 return wanted_type;
2437 } else if (actual_type->id == TypeTableEntryIdNumberLiteral &&
2438 num_lit_fits_in_other_type(g, actual_type, wanted_type))
2439 {
2440 NumLitCodeGen *codegen_num_lit = get_resolved_num_lit(expr_node);
2441 assert(!codegen_num_lit->resolved_type);
2442 codegen_num_lit->resolved_type = wanted_type;
2443 cast->op = CastOpNothing;
2444 return wanted_type;
2445 } else if (actual_type->id == TypeTableEntryIdPointer &&
2446 wanted_type->id == TypeTableEntryIdPointer)
2447 {
2448 cast->op = CastOpPointerReinterpret;
2449 return wanted_type;
2450 } else {
2451 add_node_error(g, node,
2452 buf_sprintf("invalid cast from type '%s' to '%s'",
2453 buf_ptr(&actual_type->name),
2454 buf_ptr(&wanted_type->name)));
2455 return g->builtin_types.entry_invalid;
2456 }
2457}
2458
2308static TypeTableEntry *analyze_builtin_fn_call_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,2459static TypeTableEntry *analyze_builtin_fn_call_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
2309 TypeTableEntry *expected_type, AstNode *node)2460 TypeTableEntry *expected_type, AstNode *node)
2310{2461{
...@@ -2458,25 +2609,93 @@ static TypeTableEntry *analyze_builtin_fn_call_expr(CodeGen *g, ImportTableEntry...@@ -2458,25 +2609,93 @@ static TypeTableEntry *analyze_builtin_fn_call_expr(CodeGen *g, ImportTableEntry
2458 }2609 }
2459}2610}
24602611
2612static TypeTableEntry *analyze_fn_call_raw(CodeGen *g, ImportTableEntry *import, BlockContext *context,
2613 TypeTableEntry *expected_type, AstNode *node, FnTableEntry *fn_table_entry, TypeTableEntry *struct_type)
2614{
2615 assert(node->type == NodeTypeFnCallExpr);
2616
2617 node->data.fn_call_expr.fn_entry = fn_table_entry;
2618 assert(fn_table_entry->proto_node->type == NodeTypeFnProto);
2619 AstNodeFnProto *fn_proto = &fn_table_entry->proto_node->data.fn_proto;
2620
2621 // count parameters
2622 int expected_param_count = fn_proto->params.length;
2623 int actual_param_count = node->data.fn_call_expr.params.length;
2624
2625 if (struct_type) {
2626 actual_param_count += 1;
2627 }
2628
2629 if (fn_proto->is_var_args) {
2630 if (actual_param_count < expected_param_count) {
2631 add_node_error(g, node,
2632 buf_sprintf("expected at least %d arguments, got %d",
2633 expected_param_count, actual_param_count));
2634 }
2635 } else if (expected_param_count != actual_param_count) {
2636 add_node_error(g, node,
2637 buf_sprintf("expected %d arguments, got %d",
2638 expected_param_count, actual_param_count));
2639 }
2640
2641 // analyze each parameter. in the case of a method, we already analyzed the
2642 // first parameter in order to figure out which struct we were calling a method on.
2643 for (int i = 0; i < node->data.fn_call_expr.params.length; i += 1) {
2644 AstNode *child = node->data.fn_call_expr.params.at(i);
2645 // determine the expected type for each parameter
2646 TypeTableEntry *expected_param_type = nullptr;
2647 int fn_proto_i = i + (struct_type ? 1 : 0);
2648 if (fn_proto_i < fn_proto->params.length) {
2649 AstNode *param_decl_node = fn_proto->params.at(fn_proto_i);
2650 assert(param_decl_node->type == NodeTypeParamDecl);
2651 AstNode *param_type_node = param_decl_node->data.param_decl.type;
2652 TypeTableEntry *param_type_entry = get_resolved_expr(param_type_node)->type_entry;
2653 if (param_type_entry) {
2654 expected_param_type = unwrapped_node_type(param_type_node);
2655 }
2656 }
2657 analyze_expression(g, import, context, expected_param_type, child);
2658 }
2659
2660 return unwrapped_node_type(fn_proto->return_type);
2661}
2662
2461static TypeTableEntry *analyze_fn_call_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,2663static TypeTableEntry *analyze_fn_call_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
2462 TypeTableEntry *expected_type, AstNode *node)2664 TypeTableEntry *expected_type, AstNode *node)
2463{2665{
2464 AstNode *fn_ref_expr = node->data.fn_call_expr.fn_ref_expr;2666 AstNode *fn_ref_expr = node->data.fn_call_expr.fn_ref_expr;
2465 TypeTableEntry *struct_type = nullptr;2667
2466 HashMap<Buf *, FnTableEntry *, buf_hash, buf_eql_buf> *fn_table = &import->fn_table;2668 if (node->data.fn_call_expr.is_builtin) {
2467 AstNode *first_param_expr = nullptr;2669 return analyze_builtin_fn_call_expr(g, import, context, expected_type, node);
2468 Buf *name;2670 }
24692671
2470 if (fn_ref_expr->type == NodeTypeFieldAccessExpr) {2672 if (fn_ref_expr->type == NodeTypeFieldAccessExpr) {
2471 first_param_expr = fn_ref_expr->data.field_access_expr.struct_expr;2673 AstNode *first_param_expr = fn_ref_expr->data.field_access_expr.struct_expr;
2472 struct_type = analyze_expression(g, import, context, nullptr, first_param_expr);2674 TypeTableEntry *struct_type = analyze_expression(g, import, context, nullptr, first_param_expr);
2473 name = &fn_ref_expr->data.field_access_expr.field_name;2675 Buf *name = &fn_ref_expr->data.field_access_expr.field_name;
2474 if (struct_type->id == TypeTableEntryIdStruct) {2676 if (struct_type->id == TypeTableEntryIdStruct ||
2475 fn_table = &struct_type->data.structure.fn_table;2677 (struct_type->id == TypeTableEntryIdPointer &&
2476 } else if (struct_type->id == TypeTableEntryIdPointer &&2678 struct_type->data.pointer.child_type->id == TypeTableEntryIdStruct))
2477 struct_type->data.pointer.child_type->id == TypeTableEntryIdStruct)
2478 {2679 {
2479 fn_table = &struct_type->data.pointer.child_type->data.structure.fn_table;2680 TypeTableEntry *bare_struct_type = (struct_type->id == TypeTableEntryIdStruct) ?
2681 struct_type : struct_type->data.pointer.child_type;
2682
2683 auto table_entry = bare_struct_type->data.structure.fn_table.maybe_get(name);
2684 if (table_entry) {
2685 return analyze_fn_call_raw(g, import, context, expected_type, node,
2686 table_entry->value, bare_struct_type);
2687 } else {
2688 add_node_error(g, fn_ref_expr,
2689 buf_sprintf("no function named '%s' in '%s'",
2690 buf_ptr(name), buf_ptr(&bare_struct_type->name)));
2691 // still analyze the parameters, even though we don't know what to expect
2692 for (int i = 0; i < node->data.fn_call_expr.params.length; i += 1) {
2693 AstNode *child = node->data.fn_call_expr.params.at(i);
2694 analyze_expression(g, import, context, nullptr, child);
2695 }
2696
2697 return g->builtin_types.entry_invalid;
2698 }
2480 } else if (struct_type->id == TypeTableEntryIdInvalid) {2699 } else if (struct_type->id == TypeTableEntryIdInvalid) {
2481 return struct_type;2700 return struct_type;
2482 } else if (struct_type->id == TypeTableEntryIdMetaType &&2701 } else if (struct_type->id == TypeTableEntryIdMetaType &&
...@@ -2505,74 +2724,31 @@ static TypeTableEntry *analyze_fn_call_expr(CodeGen *g, ImportTableEntry *import...@@ -2505,74 +2724,31 @@ static TypeTableEntry *analyze_fn_call_expr(CodeGen *g, ImportTableEntry *import
2505 buf_sprintf("member reference base type not struct or enum"));2724 buf_sprintf("member reference base type not struct or enum"));
2506 return g->builtin_types.entry_invalid;2725 return g->builtin_types.entry_invalid;
2507 }2726 }
2508 } else if (fn_ref_expr->type == NodeTypeSymbol) {
2509 if (node->data.fn_call_expr.is_builtin) {
2510 return analyze_builtin_fn_call_expr(g, import, context, expected_type, node);
2511 }
2512 name = &fn_ref_expr->data.symbol_expr.symbol;
2513 } else {
2514 add_node_error(g, node,
2515 buf_sprintf("function pointers not yet supported"));
2516 return g->builtin_types.entry_invalid;
2517 }2727 }
25182728
2519 auto entry = fn_table->maybe_get(name);2729 TypeTableEntry *invoke_type_entry = analyze_expression(g, import, context, nullptr, fn_ref_expr);
25202730 if (invoke_type_entry->id == TypeTableEntryIdInvalid) {
2521 if (!entry) {
2522 add_node_error(g, fn_ref_expr,
2523 buf_sprintf("undefined function: '%s'", buf_ptr(name)));
2524 // still analyze the parameters, even though we don't know what to expect
2525 for (int i = 0; i < node->data.fn_call_expr.params.length; i += 1) {
2526 AstNode *child = node->data.fn_call_expr.params.at(i);
2527 analyze_expression(g, import, context, nullptr, child);
2528 }
2529
2530 return g->builtin_types.entry_invalid;2731 return g->builtin_types.entry_invalid;
2531 } else {2732 }
2532 FnTableEntry *fn_table_entry = entry->value;
2533 assert(fn_table_entry->proto_node->type == NodeTypeFnProto);
2534 AstNodeFnProto *fn_proto = &fn_table_entry->proto_node->data.fn_proto;
2535
2536 // count parameters
2537 int expected_param_count = fn_proto->params.length;
2538 int actual_param_count = node->data.fn_call_expr.params.length;
2539
2540 if (struct_type) {
2541 actual_param_count += 1;
2542 }
25432733
2544 if (fn_proto->is_var_args) {2734 // use constant expression evaluator to figure out the function at compile time.
2545 if (actual_param_count < expected_param_count) {2735 // otherwise we treat this as a function pointer.
2546 add_node_error(g, node,2736 ConstExprValue const_val = {0};
2547 buf_sprintf("expected at least %d arguments, got %d",2737 eval_const_expr(g, context, fn_ref_expr, &const_val);
2548 expected_param_count, actual_param_count));
2549 }
2550 } else if (expected_param_count != actual_param_count) {
2551 add_node_error(g, node,
2552 buf_sprintf("expected %d arguments, got %d",
2553 expected_param_count, actual_param_count));
2554 }
25552738
2556 // analyze each parameter. in the case of a method, we already analyzed the2739 if (!const_val.ok) {
2557 // first parameter in order to figure out which struct we were calling a method on.2740 add_node_error(g, node, buf_sprintf("function pointers not yet supported"));
2558 for (int i = 0; i < node->data.fn_call_expr.params.length; i += 1) {2741 return g->builtin_types.entry_invalid;
2559 AstNode *child = node->data.fn_call_expr.params.at(i);2742 }
2560 // determine the expected type for each parameter
2561 TypeTableEntry *expected_param_type = nullptr;
2562 int fn_proto_i = i + (struct_type ? 1 : 0);
2563 if (fn_proto_i < fn_proto->params.length) {
2564 AstNode *param_decl_node = fn_proto->params.at(fn_proto_i);
2565 assert(param_decl_node->type == NodeTypeParamDecl);
2566 AstNode *param_type_node = param_decl_node->data.param_decl.type;
2567 TypeTableEntry *param_type_entry = get_resolved_expr(param_type_node)->type_entry;
2568 if (param_type_entry) {
2569 expected_param_type = unwrapped_node_type(param_type_node);
2570 }
2571 }
2572 analyze_expression(g, import, context, expected_param_type, child);
2573 }
25742743
2575 return unwrapped_node_type(fn_proto->return_type);2744 if (invoke_type_entry->id == TypeTableEntryIdMetaType) {
2745 return analyze_cast_expr(g, import, context, node, invoke_type_entry);
2746 } else if (invoke_type_entry->id == TypeTableEntryIdFn) {
2747 return analyze_fn_call_raw(g, import, context, expected_type, node, const_val.data.x_fn, nullptr);
2748 } else {
2749 add_node_error(g, fn_ref_expr,
2750 buf_sprintf("type '%s' not a function", buf_ptr(&invoke_type_entry->name)));
2751 return g->builtin_types.entry_invalid;
2576 }2752 }
2577}2753}
25782754
...@@ -2847,9 +3023,6 @@ static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import,...@@ -2847,9 +3023,6 @@ static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import,
2847 case NodeTypeSymbol:3023 case NodeTypeSymbol:
2848 return_type = analyze_symbol_expr(g, import, context, expected_type, node);3024 return_type = analyze_symbol_expr(g, import, context, expected_type, node);
2849 break;3025 break;
2850 case NodeTypeCastExpr:
2851 return_type = analyze_cast_expr(g, import, context, expected_type, node);
2852 break;
2853 case NodeTypePrefixOpExpr:3026 case NodeTypePrefixOpExpr:
2854 return_type = analyze_prefix_op_expr(g, import, context, expected_type, node);3027 return_type = analyze_prefix_op_expr(g, import, context, expected_type, node);
2855 break;3028 break;
...@@ -3008,7 +3181,6 @@ static void analyze_top_level_decl(CodeGen *g, ImportTableEntry *import, AstNode...@@ -3008,7 +3181,6 @@ static void analyze_top_level_decl(CodeGen *g, ImportTableEntry *import, AstNode
3008 case NodeTypeBoolLiteral:3181 case NodeTypeBoolLiteral:
3009 case NodeTypeNullLiteral:3182 case NodeTypeNullLiteral:
3010 case NodeTypeSymbol:3183 case NodeTypeSymbol:
3011 case NodeTypeCastExpr:
3012 case NodeTypePrefixOpExpr:3184 case NodeTypePrefixOpExpr:
3013 case NodeTypeIfBoolExpr:3185 case NodeTypeIfBoolExpr:
3014 case NodeTypeIfVarExpr:3186 case NodeTypeIfVarExpr:
...@@ -3060,10 +3232,6 @@ static void collect_expr_decl_deps(CodeGen *g, ImportTableEntry *import, AstNode...@@ -3060,10 +3232,6 @@ static void collect_expr_decl_deps(CodeGen *g, ImportTableEntry *import, AstNode
3060 case NodeTypeReturnExpr:3232 case NodeTypeReturnExpr:
3061 collect_expr_decl_deps(g, import, node->data.return_expr.expr, decl_node);3233 collect_expr_decl_deps(g, import, node->data.return_expr.expr, decl_node);
3062 break;3234 break;
3063 case NodeTypeCastExpr:
3064 collect_expr_decl_deps(g, import, node->data.cast_expr.expr, decl_node);
3065 collect_expr_decl_deps(g, import, node->data.cast_expr.type, decl_node);
3066 break;
3067 case NodeTypePrefixOpExpr:3235 case NodeTypePrefixOpExpr:
3068 collect_expr_decl_deps(g, import, node->data.prefix_op_expr.primary_expr, decl_node);3236 collect_expr_decl_deps(g, import, node->data.prefix_op_expr.primary_expr, decl_node);
3069 break;3237 break;
...@@ -3331,7 +3499,6 @@ static void detect_top_level_decl_deps(CodeGen *g, ImportTableEntry *import, Ast...@@ -3331,7 +3499,6 @@ static void detect_top_level_decl_deps(CodeGen *g, ImportTableEntry *import, Ast
3331 case NodeTypeBoolLiteral:3499 case NodeTypeBoolLiteral:
3332 case NodeTypeNullLiteral:3500 case NodeTypeNullLiteral:
3333 case NodeTypeSymbol:3501 case NodeTypeSymbol:
3334 case NodeTypeCastExpr:
3335 case NodeTypePrefixOpExpr:3502 case NodeTypePrefixOpExpr:
3336 case NodeTypeIfBoolExpr:3503 case NodeTypeIfBoolExpr:
3337 case NodeTypeIfVarExpr:3504 case NodeTypeIfVarExpr:
...@@ -3504,8 +3671,6 @@ Expr *get_resolved_expr(AstNode *node) {...@@ -3504,8 +3671,6 @@ Expr *get_resolved_expr(AstNode *node) {
3504 return &node->data.return_expr.resolved_expr;3671 return &node->data.return_expr.resolved_expr;
3505 case NodeTypeBinOpExpr:3672 case NodeTypeBinOpExpr:
3506 return &node->data.bin_op_expr.resolved_expr;3673 return &node->data.bin_op_expr.resolved_expr;
3507 case NodeTypeCastExpr:
3508 return &node->data.cast_expr.resolved_expr;
3509 case NodeTypePrefixOpExpr:3674 case NodeTypePrefixOpExpr:
3510 return &node->data.prefix_op_expr.resolved_expr;3675 return &node->data.prefix_op_expr.resolved_expr;
3511 case NodeTypeFnCallExpr:3676 case NodeTypeFnCallExpr:
...@@ -3577,7 +3742,6 @@ NumLitCodeGen *get_resolved_num_lit(AstNode *node) {...@@ -3577,7 +3742,6 @@ NumLitCodeGen *get_resolved_num_lit(AstNode *node) {
3577 return &node->data.fn_call_expr.resolved_num_lit;3742 return &node->data.fn_call_expr.resolved_num_lit;
3578 case NodeTypeReturnExpr:3743 case NodeTypeReturnExpr:
3579 case NodeTypeBinOpExpr:3744 case NodeTypeBinOpExpr:
3580 case NodeTypeCastExpr:
3581 case NodeTypePrefixOpExpr:3745 case NodeTypePrefixOpExpr:
3582 case NodeTypeArrayAccessExpr:3746 case NodeTypeArrayAccessExpr:
3583 case NodeTypeSliceExpr:3747 case NodeTypeSliceExpr:
...@@ -3627,7 +3791,6 @@ TopLevelDecl *get_resolved_top_level_decl(AstNode *node) {...@@ -3627,7 +3791,6 @@ TopLevelDecl *get_resolved_top_level_decl(AstNode *node) {
3627 case NodeTypeNumberLiteral:3791 case NodeTypeNumberLiteral:
3628 case NodeTypeReturnExpr:3792 case NodeTypeReturnExpr:
3629 case NodeTypeBinOpExpr:3793 case NodeTypeBinOpExpr:
3630 case NodeTypeCastExpr:
3631 case NodeTypePrefixOpExpr:3794 case NodeTypePrefixOpExpr:
3632 case NodeTypeFnCallExpr:3795 case NodeTypeFnCallExpr:
3633 case NodeTypeArrayAccessExpr:3796 case NodeTypeArrayAccessExpr:
src/codegen.cpp+28-38
...@@ -71,6 +71,8 @@ static LLVMValueRef gen_var_decl_raw(CodeGen *g, AstNode *source_node, AstNodeVa...@@ -71,6 +71,8 @@ static LLVMValueRef gen_var_decl_raw(CodeGen *g, AstNode *source_node, AstNodeVa
71static LLVMValueRef gen_assign_raw(CodeGen *g, AstNode *source_node, BinOpType bin_op,71static LLVMValueRef gen_assign_raw(CodeGen *g, AstNode *source_node, BinOpType bin_op,
72 LLVMValueRef target_ref, LLVMValueRef value,72 LLVMValueRef target_ref, LLVMValueRef value,
73 TypeTableEntry *op1_type, TypeTableEntry *op2_type);73 TypeTableEntry *op1_type, TypeTableEntry *op2_type);
74static LLVMValueRef gen_bare_cast(CodeGen *g, AstNode *node, LLVMValueRef expr_val,
75 TypeTableEntry *actual_type, TypeTableEntry *wanted_type, Cast *cast_node);
74 76
75static TypeTableEntry *get_type_for_type_node(AstNode *node) {77static TypeTableEntry *get_type_for_type_node(AstNode *node) {
76 TypeTableEntry *meta_type_entry = get_resolved_expr(node)->type_entry;78 TypeTableEntry *meta_type_entry = get_resolved_expr(node)->type_entry;
...@@ -381,23 +383,43 @@ static LLVMValueRef gen_enum_value_expr(CodeGen *g, AstNode *node, TypeTableEntr...@@ -381,23 +383,43 @@ static LLVMValueRef gen_enum_value_expr(CodeGen *g, AstNode *node, TypeTableEntr
381 }383 }
382}384}
383385
386static LLVMValueRef gen_cast_expr(CodeGen *g, AstNode *node) {
387 assert(node->type == NodeTypeFnCallExpr);
388
389 AstNode *expr_node = node->data.fn_call_expr.params.at(0);
390
391 LLVMValueRef expr_val = gen_expr(g, expr_node);
392
393 TypeTableEntry *actual_type = get_expr_type(expr_node);
394 TypeTableEntry *wanted_type = get_expr_type(node);
395
396 Cast *cast_node = &node->data.fn_call_expr.cast;
397
398 return gen_bare_cast(g, node, expr_val, actual_type, wanted_type, cast_node);
399
400}
384401
385static LLVMValueRef gen_fn_call_expr(CodeGen *g, AstNode *node) {402static LLVMValueRef gen_fn_call_expr(CodeGen *g, AstNode *node) {
386 assert(node->type == NodeTypeFnCallExpr);403 assert(node->type == NodeTypeFnCallExpr);
387404
388 FnTableEntry *fn_table_entry;405 if (node->data.fn_call_expr.is_builtin) {
406 return gen_builtin_fn_call_expr(g, node);
407 } else if (node->data.fn_call_expr.cast.after_type) {
408 return gen_cast_expr(g, node);
409 }
410
411 FnTableEntry *fn_table_entry = node->data.fn_call_expr.fn_entry;
389 AstNode *fn_ref_expr = node->data.fn_call_expr.fn_ref_expr;412 AstNode *fn_ref_expr = node->data.fn_call_expr.fn_ref_expr;
390 TypeTableEntry *struct_type;413 TypeTableEntry *struct_type = nullptr;
391 AstNode *first_param_expr;414 AstNode *first_param_expr = nullptr;
392 if (fn_ref_expr->type == NodeTypeFieldAccessExpr) {415 if (fn_ref_expr->type == NodeTypeFieldAccessExpr) {
393 Buf *name = &fn_ref_expr->data.field_access_expr.field_name;
394 first_param_expr = fn_ref_expr->data.field_access_expr.struct_expr;416 first_param_expr = fn_ref_expr->data.field_access_expr.struct_expr;
395 struct_type = get_expr_type(first_param_expr);417 struct_type = get_expr_type(first_param_expr);
396 if (struct_type->id == TypeTableEntryIdStruct) {418 if (struct_type->id == TypeTableEntryIdStruct) {
397 fn_table_entry = struct_type->data.structure.fn_table.get(name);419 fn_table_entry = node->data.fn_call_expr.fn_entry;
398 } else if (struct_type->id == TypeTableEntryIdPointer) {420 } else if (struct_type->id == TypeTableEntryIdPointer) {
399 assert(struct_type->data.pointer.child_type->id == TypeTableEntryIdStruct);421 assert(struct_type->data.pointer.child_type->id == TypeTableEntryIdStruct);
400 fn_table_entry = struct_type->data.pointer.child_type->data.structure.fn_table.get(name);422 fn_table_entry = node->data.fn_call_expr.fn_entry;
401 } else if (struct_type->id == TypeTableEntryIdMetaType &&423 } else if (struct_type->id == TypeTableEntryIdMetaType &&
402 struct_type->data.meta_type.child_type->id == TypeTableEntryIdEnum)424 struct_type->data.meta_type.child_type->id == TypeTableEntryIdEnum)
403 {425 {
...@@ -414,24 +436,8 @@ static LLVMValueRef gen_fn_call_expr(CodeGen *g, AstNode *node) {...@@ -414,24 +436,8 @@ static LLVMValueRef gen_fn_call_expr(CodeGen *g, AstNode *node) {
414 } else {436 } else {
415 zig_unreachable();437 zig_unreachable();
416 }438 }
417 } else if (fn_ref_expr->type == NodeTypeSymbol) {
418 if (node->data.fn_call_expr.is_builtin) {
419 return gen_builtin_fn_call_expr(g, node);
420 }
421
422 // Assume that the expression evaluates to a simple name and return the buf
423 // TODO after we support function pointers we can make this generic
424 assert(fn_ref_expr->type == NodeTypeSymbol);
425 Buf *name = &fn_ref_expr->data.symbol_expr.symbol;
426
427 struct_type = nullptr;
428 first_param_expr = nullptr;
429 fn_table_entry = g->cur_fn->import_entry->fn_table.get(name);
430 } else {
431 zig_unreachable();
432 }439 }
433440
434
435 assert(fn_table_entry->proto_node->type == NodeTypeFnProto);441 assert(fn_table_entry->proto_node->type == NodeTypeFnProto);
436 AstNodeFnProto *fn_proto_data = &fn_table_entry->proto_node->data.fn_proto;442 AstNodeFnProto *fn_proto_data = &fn_table_entry->proto_node->data.fn_proto;
437443
...@@ -863,20 +869,6 @@ static LLVMValueRef gen_bare_cast(CodeGen *g, AstNode *node, LLVMValueRef expr_v...@@ -863,20 +869,6 @@ static LLVMValueRef gen_bare_cast(CodeGen *g, AstNode *node, LLVMValueRef expr_v
863 zig_unreachable();869 zig_unreachable();
864}870}
865871
866static LLVMValueRef gen_cast_expr(CodeGen *g, AstNode *node) {
867 assert(node->type == NodeTypeCastExpr);
868
869 LLVMValueRef expr_val = gen_expr(g, node->data.cast_expr.expr);
870
871 TypeTableEntry *actual_type = get_expr_type(node->data.cast_expr.expr);
872 TypeTableEntry *wanted_type = get_expr_type(node);
873
874 Cast *cast_node = &node->data.cast_expr.cast;
875
876 return gen_bare_cast(g, node, expr_val, actual_type, wanted_type, cast_node);
877
878}
879
880static LLVMValueRef gen_arithmetic_bin_op(CodeGen *g, AstNode *source_node,872static LLVMValueRef gen_arithmetic_bin_op(CodeGen *g, AstNode *source_node,
881 LLVMValueRef val1, LLVMValueRef val2,873 LLVMValueRef val1, LLVMValueRef val2,
882 TypeTableEntry *op1_type, TypeTableEntry *op2_type,874 TypeTableEntry *op1_type, TypeTableEntry *op2_type,
...@@ -1810,8 +1802,6 @@ static LLVMValueRef gen_expr_no_cast(CodeGen *g, AstNode *node) {...@@ -1810,8 +1802,6 @@ static LLVMValueRef gen_expr_no_cast(CodeGen *g, AstNode *node) {
1810 return gen_return_expr(g, node);1802 return gen_return_expr(g, node);
1811 case NodeTypeVariableDeclaration:1803 case NodeTypeVariableDeclaration:
1812 return gen_var_decl_expr(g, node);1804 return gen_var_decl_expr(g, node);
1813 case NodeTypeCastExpr:
1814 return gen_cast_expr(g, node);
1815 case NodeTypePrefixOpExpr:1805 case NodeTypePrefixOpExpr:
1816 return gen_prefix_op_expr(g, node);1806 return gen_prefix_op_expr(g, node);
1817 case NodeTypeFnCallExpr:1807 case NodeTypeFnCallExpr:
src/parser.cpp+3-34
...@@ -99,8 +99,6 @@ const char *node_type_str(NodeType node_type) {...@@ -99,8 +99,6 @@ const char *node_type_str(NodeType node_type) {
99 return "ReturnExpr";99 return "ReturnExpr";
100 case NodeTypeVariableDeclaration:100 case NodeTypeVariableDeclaration:
101 return "VariableDeclaration";101 return "VariableDeclaration";
102 case NodeTypeCastExpr:
103 return "CastExpr";
104 case NodeTypeNumberLiteral:102 case NodeTypeNumberLiteral:
105 return "NumberLiteral";103 return "NumberLiteral";
106 case NodeTypeStringLiteral:104 case NodeTypeStringLiteral:
...@@ -265,12 +263,6 @@ void ast_print(AstNode *node, int indent) {...@@ -265,12 +263,6 @@ void ast_print(AstNode *node, int indent) {
265 case NodeTypeDirective:263 case NodeTypeDirective:
266 fprintf(stderr, "%s\n", node_type_str(node->type));264 fprintf(stderr, "%s\n", node_type_str(node->type));
267 break;265 break;
268 case NodeTypeCastExpr:
269 fprintf(stderr, "%s\n", node_type_str(node->type));
270 ast_print(node->data.cast_expr.expr, indent + 2);
271 if (node->data.cast_expr.type)
272 ast_print(node->data.cast_expr.type, indent + 2);
273 break;
274 case NodeTypePrefixOpExpr:266 case NodeTypePrefixOpExpr:
275 fprintf(stderr, "%s %s\n", node_type_str(node->type),267 fprintf(stderr, "%s %s\n", node_type_str(node->type),
276 prefix_op_str(node->data.prefix_op_expr.prefix_op));268 prefix_op_str(node->data.prefix_op_expr.prefix_op));
...@@ -1604,29 +1596,6 @@ static AstNode *ast_parse_prefix_op_expr(ParseContext *pc, int *token_index, boo...@@ -1604,29 +1596,6 @@ static AstNode *ast_parse_prefix_op_expr(ParseContext *pc, int *token_index, boo
1604}1596}
16051597
16061598
1607/*
1608CastExpression : CastExpression token(as) PrimaryExpression | PrefixOpExpression
1609*/
1610static AstNode *ast_parse_cast_expression(ParseContext *pc, int *token_index, bool mandatory) {
1611 AstNode *operand_1 = ast_parse_prefix_op_expr(pc, token_index, mandatory);
1612 if (!operand_1)
1613 return nullptr;
1614
1615 while (true) {
1616 Token *as_kw = &pc->tokens->at(*token_index);
1617 if (as_kw->id != TokenIdKeywordAs)
1618 return operand_1;
1619 *token_index += 1;
1620
1621 AstNode *node = ast_create_node(pc, NodeTypeCastExpr, as_kw);
1622 node->data.cast_expr.expr = operand_1;
1623
1624 node->data.cast_expr.type = ast_parse_primary_expr(pc, token_index, true);
1625
1626 operand_1 = node;
1627 }
1628}
1629
1630static BinOpType tok_to_mult_op(Token *token) {1599static BinOpType tok_to_mult_op(Token *token) {
1631 switch (token->id) {1600 switch (token->id) {
1632 case TokenIdStar: return BinOpTypeMult;1601 case TokenIdStar: return BinOpTypeMult;
...@@ -1654,10 +1623,10 @@ static BinOpType ast_parse_mult_op(ParseContext *pc, int *token_index, bool mand...@@ -1654,10 +1623,10 @@ static BinOpType ast_parse_mult_op(ParseContext *pc, int *token_index, bool mand
1654}1623}
16551624
1656/*1625/*
1657MultiplyExpression : CastExpression MultiplyOperator MultiplyExpression | CastExpression1626MultiplyExpression : PrefixOpExpression MultiplyOperator MultiplyExpression | PrefixOpExpression
1658*/1627*/
1659static AstNode *ast_parse_mult_expr(ParseContext *pc, int *token_index, bool mandatory) {1628static AstNode *ast_parse_mult_expr(ParseContext *pc, int *token_index, bool mandatory) {
1660 AstNode *operand_1 = ast_parse_cast_expression(pc, token_index, mandatory);1629 AstNode *operand_1 = ast_parse_prefix_op_expr(pc, token_index, mandatory);
1661 if (!operand_1)1630 if (!operand_1)
1662 return nullptr;1631 return nullptr;
16631632
...@@ -1667,7 +1636,7 @@ static AstNode *ast_parse_mult_expr(ParseContext *pc, int *token_index, bool man...@@ -1667,7 +1636,7 @@ static AstNode *ast_parse_mult_expr(ParseContext *pc, int *token_index, bool man
1667 if (mult_op == BinOpTypeInvalid)1636 if (mult_op == BinOpTypeInvalid)
1668 return operand_1;1637 return operand_1;
16691638
1670 AstNode *operand_2 = ast_parse_cast_expression(pc, token_index, true);1639 AstNode *operand_2 = ast_parse_prefix_op_expr(pc, token_index, true);
16711640
1672 AstNode *node = ast_create_node(pc, NodeTypeBinOpExpr, token);1641 AstNode *node = ast_create_node(pc, NodeTypeBinOpExpr, token);
1673 node->data.bin_op_expr.op1 = operand_1;1642 node->data.bin_op_expr.op1 = operand_1;
src/tokenizer.cpp-3
...@@ -211,8 +211,6 @@ static void end_token(Tokenize *t) {...@@ -211,8 +211,6 @@ static void end_token(Tokenize *t) {
211 t->cur_tok->id = TokenIdKeywordPub;211 t->cur_tok->id = TokenIdKeywordPub;
212 } else if (mem_eql_str(token_mem, token_len, "export")) {212 } else if (mem_eql_str(token_mem, token_len, "export")) {
213 t->cur_tok->id = TokenIdKeywordExport;213 t->cur_tok->id = TokenIdKeywordExport;
214 } else if (mem_eql_str(token_mem, token_len, "as")) {
215 t->cur_tok->id = TokenIdKeywordAs;
216 } else if (mem_eql_str(token_mem, token_len, "use")) {214 } else if (mem_eql_str(token_mem, token_len, "use")) {
217 t->cur_tok->id = TokenIdKeywordUse;215 t->cur_tok->id = TokenIdKeywordUse;
218 } else if (mem_eql_str(token_mem, token_len, "true")) {216 } else if (mem_eql_str(token_mem, token_len, "true")) {
...@@ -1019,7 +1017,6 @@ const char * token_name(TokenId id) {...@@ -1019,7 +1017,6 @@ const char * token_name(TokenId id) {
1019 case TokenIdKeywordExtern: return "extern";1017 case TokenIdKeywordExtern: return "extern";
1020 case TokenIdKeywordPub: return "pub";1018 case TokenIdKeywordPub: return "pub";
1021 case TokenIdKeywordExport: return "export";1019 case TokenIdKeywordExport: return "export";
1022 case TokenIdKeywordAs: return "as";
1023 case TokenIdKeywordUse: return "use";1020 case TokenIdKeywordUse: return "use";
1024 case TokenIdKeywordTrue: return "true";1021 case TokenIdKeywordTrue: return "true";
1025 case TokenIdKeywordFalse: return "false";1022 case TokenIdKeywordFalse: return "false";
src/tokenizer.hpp-1
...@@ -20,7 +20,6 @@ enum TokenId {...@@ -20,7 +20,6 @@ enum TokenId {
20 TokenIdKeywordExtern,20 TokenIdKeywordExtern,
21 TokenIdKeywordPub,21 TokenIdKeywordPub,
22 TokenIdKeywordExport,22 TokenIdKeywordExport,
23 TokenIdKeywordAs,
24 TokenIdKeywordUse,23 TokenIdKeywordUse,
25 TokenIdKeywordTrue,24 TokenIdKeywordTrue,
26 TokenIdKeywordFalse,25 TokenIdKeywordFalse,
std/rand.zig+4-4
...@@ -13,7 +13,7 @@ pub struct Rand {...@@ -13,7 +13,7 @@ pub struct Rand {
13 var i : @typeof(ARRAY_SIZE) = 1;13 var i : @typeof(ARRAY_SIZE) = 1;
14 while (i < ARRAY_SIZE) {14 while (i < ARRAY_SIZE) {
15 const prev_value : u64 = r.array[i - 1];15 const prev_value : u64 = r.array[i - 1];
16 r.array[i] = ((prev_value ^ (prev_value << 30)) * 0x6c078965 + i) as u32;16 r.array[i] = u32((prev_value ^ (prev_value << 30)) * 0x6c078965 + i);
17 i += 1;17 i += 1;
18 }18 }
19 }19 }
...@@ -41,7 +41,7 @@ pub struct Rand {...@@ -41,7 +41,7 @@ pub struct Rand {
41 var bytes_left = r.get_bytes_aligned(buf);41 var bytes_left = r.get_bytes_aligned(buf);
42 if (bytes_left > 0) {42 if (bytes_left > 0) {
43 var rand_val_array : [@sizeof(u32)]u8;43 var rand_val_array : [@sizeof(u32)]u8;
44 *(rand_val_array.ptr as (&u32)) = r.get_u32();44 *((&u32)(rand_val_array.ptr)) = r.get_u32();
45 while (bytes_left > 0) {45 while (bytes_left > 0) {
46 buf[buf.len - bytes_left] = rand_val_array[@sizeof(u32) - bytes_left];46 buf[buf.len - bytes_left] = rand_val_array[@sizeof(u32) - bytes_left];
47 bytes_left -= 1;47 bytes_left -= 1;
...@@ -59,7 +59,7 @@ pub struct Rand {...@@ -59,7 +59,7 @@ pub struct Rand {
5959
60 while (true) {60 while (true) {
61 r.get_bytes_aligned(rand_val_array);61 r.get_bytes_aligned(rand_val_array);
62 const rand_val = *(rand_val_array.ptr as (&u64));62 const rand_val = *((&u64)(rand_val_array.ptr));
63 if (rand_val < upper_bound) {63 if (rand_val < upper_bound) {
64 return start + (rand_val % range);64 return start + (rand_val % range);
65 }65 }
...@@ -85,7 +85,7 @@ pub struct Rand {...@@ -85,7 +85,7 @@ pub struct Rand {
85 fn get_bytes_aligned(r: &Rand, buf: []u8) usize => {85 fn get_bytes_aligned(r: &Rand, buf: []u8) usize => {
86 var bytes_left = buf.len;86 var bytes_left = buf.len;
87 while (bytes_left >= 4) {87 while (bytes_left >= 4) {
88 *(&buf[buf.len - bytes_left] as (&u32)) = r.get_u32();88 *((&u32)(&buf[buf.len - bytes_left])) = r.get_u32();
89 bytes_left -= @sizeof(u32);89 bytes_left -= @sizeof(u32);
90 }90 }
91 return bytes_left;91 return bytes_left;
std/std.zig+4-4
...@@ -43,7 +43,7 @@ pub fn readline(buf: []u8, out_len: &usize) bool => {...@@ -43,7 +43,7 @@ pub fn readline(buf: []u8, out_len: &usize) bool => {
43 if (amt_read < 0) {43 if (amt_read < 0) {
44 return true;44 return true;
45 }45 }
46 *out_len = amt_read as usize;46 *out_len = usize(amt_read);
47 return false;47 return false;
48}48}
4949
...@@ -94,9 +94,9 @@ const max_u64_base10_digits: usize = 20;...@@ -94,9 +94,9 @@ const max_u64_base10_digits: usize = 20;
94fn buf_print_i64(out_buf: []u8, x: i64) usize => {94fn buf_print_i64(out_buf: []u8, x: i64) usize => {
95 if (x < 0) {95 if (x < 0) {
96 out_buf[0] = '-';96 out_buf[0] = '-';
97 return 1 + buf_print_u64(out_buf[1...], ((-(x + 1)) as u64) + 1);97 return 1 + buf_print_u64(out_buf[1...], u64(-(x + 1)) + 1);
98 } else {98 } else {
99 return buf_print_u64(out_buf, x as u64);99 return buf_print_u64(out_buf, u64(x));
100 }100 }
101}101}
102102
...@@ -108,7 +108,7 @@ fn buf_print_u64(out_buf: []u8, x: u64) usize => {...@@ -108,7 +108,7 @@ fn buf_print_u64(out_buf: []u8, x: u64) usize => {
108 while (true) {108 while (true) {
109 const digit = a % 10;109 const digit = a % 10;
110 index -= 1;110 index -= 1;
111 buf[index] = '0' + (digit as u8);111 buf[index] = '0' + u8(digit);
112 a /= 10;112 a /= 10;
113 if (a == 0)113 if (a == 0)
114 break;114 break;
std/syscall.zig+4-5
...@@ -18,19 +18,18 @@ fn syscall3(number: usize, arg1: usize, arg2: usize, arg3: usize) usize => {...@@ -18,19 +18,18 @@ fn syscall3(number: usize, arg1: usize, arg2: usize, arg3: usize) usize => {
18}18}
1919
20pub fn read(fd: isize, buf: &u8, count: usize) isize => {20pub fn read(fd: isize, buf: &u8, count: usize) isize => {
21 syscall3(SYS_read, fd as usize, buf as usize, count) as isize21 isize(syscall3(SYS_read, usize(fd), usize(buf), count))
22}22}
2323
24pub fn write(fd: isize, buf: &const u8, count: usize) isize => {24pub fn write(fd: isize, buf: &const u8, count: usize) isize => {
25 syscall3(SYS_write, fd as usize, buf as usize, count) as isize25 isize(syscall3(SYS_write, usize(fd), usize(buf), count))
26}26}
2727
28pub fn exit(status: i32) unreachable => {28pub fn exit(status: i32) unreachable => {
29 syscall1(SYS_exit, status as usize);29 syscall1(SYS_exit, usize(status));
30 unreachable{}30 unreachable{}
31}31}
3232
33pub fn getrandom(buf: &u8, count: usize, flags: u32) isize => {33pub fn getrandom(buf: &u8, count: usize, flags: u32) isize => {
34 syscall3(SYS_getrandom, buf as usize, count, flags as usize) as isize34 isize(syscall3(SYS_getrandom, usize(buf), count, usize(flags)))
35}35}
36
test/run_tests.cpp+45-45
...@@ -272,7 +272,7 @@ use "std.zig";...@@ -272,7 +272,7 @@ use "std.zig";
272272
273pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => {273pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => {
274 const a : i32 = 1;274 const a : i32 = 1;
275 const b = 2 as i32;275 const b = i32(2);
276 if (a + b == 3) {276 if (a + b == 3) {
277 print_str("OK\n");277 print_str("OK\n");
278 }278 }
...@@ -302,7 +302,7 @@ pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => {...@@ -302,7 +302,7 @@ pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => {
302 }302 }
303303
304 const c = {304 const c = {
305 const no_conflict = 10 as i32;305 const no_conflict = i32(10);
306 no_conflict306 no_conflict
307 };307 };
308 if (c == 10) { print_str("OK 2\n"); }308 if (c == 10) { print_str("OK 2\n"); }
...@@ -358,7 +358,7 @@ pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => {...@@ -358,7 +358,7 @@ pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => {
358 var zero : i32 = 0;358 var zero : i32 = 0;
359 if (zero == 0) { print_str("zero\n"); }359 if (zero == 0) { print_str("zero\n"); }
360360
361 var i = 0 as i32;361 var i = i32(0);
362loop_start:362loop_start:
363 if (i == 3) {363 if (i == 3) {
364 goto done;364 goto done;
...@@ -384,7 +384,7 @@ pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => {...@@ -384,7 +384,7 @@ pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => {
384 }384 }
385385
386 i = 0;386 i = 0;
387 var accumulator = 0 as u32;387 var accumulator = u32(0);
388 while (i < 5) {388 while (i < 5) {
389 accumulator += array[i];389 accumulator += array[i];
390390
...@@ -430,9 +430,9 @@ pub fn main(argc : isize, argv : &&u8, env : &&u8) i32 => {...@@ -430,9 +430,9 @@ pub fn main(argc : isize, argv : &&u8, env : &&u8) i32 => {
430 if (90 >> 1 >> 2 != 90 >> 3) { print_str("BAD 7\n"); }430 if (90 >> 1 >> 2 != 90 >> 3) { print_str("BAD 7\n"); }
431 if (100 - 1 + 1000 != 1099) { print_str("BAD 8\n"); }431 if (100 - 1 + 1000 != 1099) { print_str("BAD 8\n"); }
432 if (5 * 4 / 2 % 3 != 1) { print_str("BAD 9\n"); }432 if (5 * 4 / 2 % 3 != 1) { print_str("BAD 9\n"); }
433 if (5 as i32 as i32 != 5) { print_str("BAD 10\n"); }433 if (i32(i32(5)) != 5) { print_str("BAD 10\n"); }
434 if (!!false) { print_str("BAD 11\n"); }434 if (!!false) { print_str("BAD 11\n"); }
435 if (7 as i32 != --(7 as i32)) { print_str("BAD 12\n"); }435 if (i32(7) != --(i32(7))) { print_str("BAD 12\n"); }
436436
437 print_str("OK\n");437 print_str("OK\n");
438 return 0;438 return 0;
...@@ -495,82 +495,82 @@ export fn main(argc : isize, argv : &&u8, env : &&u8) i32 => {...@@ -495,82 +495,82 @@ export fn main(argc : isize, argv : &&u8, env : &&u8) i32 => {
495 printf(c"\n");495 printf(c"\n");
496496
497 printf(c"0: %llu\n",497 printf(c"0: %llu\n",
498 0 as u64);498 u64(0));
499 printf(c"320402575052271: %llu\n",499 printf(c"320402575052271: %llu\n",
500 320402575052271 as u64);500 u64(320402575052271));
501 printf(c"0x01236789abcdef: %llu\n",501 printf(c"0x01236789abcdef: %llu\n",
502 0x01236789abcdef as u64);502 u64(0x01236789abcdef));
503 printf(c"0xffffffffffffffff: %llu\n",503 printf(c"0xffffffffffffffff: %llu\n",
504 0xffffffffffffffff as u64);504 u64(0xffffffffffffffff));
505 printf(c"0x000000ffffffffffffffff: %llu\n",505 printf(c"0x000000ffffffffffffffff: %llu\n",
506 0x000000ffffffffffffffff as u64);506 u64(0x000000ffffffffffffffff));
507 printf(c"0o1777777777777777777777: %llu\n",507 printf(c"0o1777777777777777777777: %llu\n",
508 0o1777777777777777777777 as u64);508 u64(0o1777777777777777777777));
509 printf(c"0o0000001777777777777777777777: %llu\n",509 printf(c"0o0000001777777777777777777777: %llu\n",
510 0o0000001777777777777777777777 as u64);510 u64(0o0000001777777777777777777777));
511 printf(c"0b1111111111111111111111111111111111111111111111111111111111111111: %llu\n",511 printf(c"0b1111111111111111111111111111111111111111111111111111111111111111: %llu\n",
512 0b1111111111111111111111111111111111111111111111111111111111111111 as u64);512 u64(0b1111111111111111111111111111111111111111111111111111111111111111));
513 printf(c"0b0000001111111111111111111111111111111111111111111111111111111111111111: %llu\n",513 printf(c"0b0000001111111111111111111111111111111111111111111111111111111111111111: %llu\n",
514 0b0000001111111111111111111111111111111111111111111111111111111111111111 as u64);514 u64(0b0000001111111111111111111111111111111111111111111111111111111111111111));
515515
516 printf(c"\n");516 printf(c"\n");
517517
518 printf(c"0.0: %a\n",518 printf(c"0.0: %a\n",
519 0.0 as f64);519 f64(0.0));
520 printf(c"0e0: %a\n",520 printf(c"0e0: %a\n",
521 0e0 as f64);521 f64(0e0));
522 printf(c"0.0e0: %a\n",522 printf(c"0.0e0: %a\n",
523 0.0e0 as f64);523 f64(0.0e0));
524 printf(c"000000000000000000000000000000000000000000000000000000000.0e0: %a\n",524 printf(c"000000000000000000000000000000000000000000000000000000000.0e0: %a\n",
525 000000000000000000000000000000000000000000000000000000000.0e0 as f64);525 f64(000000000000000000000000000000000000000000000000000000000.0e0));
526 printf(c"0.000000000000000000000000000000000000000000000000000000000e0: %a\n",526 printf(c"0.000000000000000000000000000000000000000000000000000000000e0: %a\n",
527 0.000000000000000000000000000000000000000000000000000000000e0 as f64);527 f64(0.000000000000000000000000000000000000000000000000000000000e0));
528 printf(c"0.0e000000000000000000000000000000000000000000000000000000000: %a\n",528 printf(c"0.0e000000000000000000000000000000000000000000000000000000000: %a\n",
529 0.0e000000000000000000000000000000000000000000000000000000000 as f64);529 f64(0.0e000000000000000000000000000000000000000000000000000000000));
530 printf(c"1.0: %a\n",530 printf(c"1.0: %a\n",
531 1.0 as f64);531 f64(1.0));
532 printf(c"10.0: %a\n",532 printf(c"10.0: %a\n",
533 10.0 as f64);533 f64(10.0));
534 printf(c"10.5: %a\n",534 printf(c"10.5: %a\n",
535 10.5 as f64);535 f64(10.5));
536 printf(c"10.5e5: %a\n",536 printf(c"10.5e5: %a\n",
537 10.5e5 as f64);537 f64(10.5e5));
538 printf(c"10.5e+5: %a\n",538 printf(c"10.5e+5: %a\n",
539 10.5e+5 as f64);539 f64(10.5e+5));
540 printf(c"50.0e-2: %a\n",540 printf(c"50.0e-2: %a\n",
541 50.0e-2 as f64);541 f64(50.0e-2));
542 printf(c"50e-2: %a\n",542 printf(c"50e-2: %a\n",
543 50e-2 as f64);543 f64(50e-2));
544544
545 printf(c"\n");545 printf(c"\n");
546546
547 printf(c"0x1.0: %a\n",547 printf(c"0x1.0: %a\n",
548 0x1.0 as f64);548 f64(0x1.0));
549 printf(c"0x10.0: %a\n",549 printf(c"0x10.0: %a\n",
550 0x10.0 as f64);550 f64(0x10.0));
551 printf(c"0x100.0: %a\n",551 printf(c"0x100.0: %a\n",
552 0x100.0 as f64);552 f64(0x100.0));
553 printf(c"0x103.0: %a\n",553 printf(c"0x103.0: %a\n",
554 0x103.0 as f64);554 f64(0x103.0));
555 printf(c"0x103.7: %a\n",555 printf(c"0x103.7: %a\n",
556 0x103.7 as f64);556 f64(0x103.7));
557 printf(c"0x103.70: %a\n",557 printf(c"0x103.70: %a\n",
558 0x103.70 as f64);558 f64(0x103.70));
559 printf(c"0x103.70p4: %a\n",559 printf(c"0x103.70p4: %a\n",
560 0x103.70p4 as f64);560 f64(0x103.70p4));
561 printf(c"0x103.70p5: %a\n",561 printf(c"0x103.70p5: %a\n",
562 0x103.70p5 as f64);562 f64(0x103.70p5));
563 printf(c"0x103.70p+5: %a\n",563 printf(c"0x103.70p+5: %a\n",
564 0x103.70p+5 as f64);564 f64(0x103.70p+5));
565 printf(c"0x103.70p-5: %a\n",565 printf(c"0x103.70p-5: %a\n",
566 0x103.70p-5 as f64);566 f64(0x103.70p-5));
567567
568 printf(c"\n");568 printf(c"\n");
569569
570 printf(c"0b10100.00010e0: %a\n",570 printf(c"0b10100.00010e0: %a\n",
571 0b10100.00010e0 as f64);571 f64(0b10100.00010e0));
572 printf(c"0o10700.00010e0: %a\n",572 printf(c"0o10700.00010e0: %a\n",
573 0o10700.00010e0 as f64);573 f64(0o10700.00010e0));
574574
575 return 0;575 return 0;
576}576}
...@@ -818,7 +818,7 @@ pub fn main(argc : isize, argv : &&u8, env : &&u8) i32 => {...@@ -818,7 +818,7 @@ pub fn main(argc : isize, argv : &&u8, env : &&u8) i32 => {
818use "std.zig";818use "std.zig";
819819
820pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => {820pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => {
821 var x = 3 as i32;821 var x = i32(3);
822 const y = &x;822 const y = &x;
823823
824 *y += 1;824 *y += 1;
...@@ -1116,7 +1116,7 @@ fn a() i32 => {}...@@ -1116,7 +1116,7 @@ fn a() i32 => {}
1116fn a() => {1116fn a() => {
1117 b();1117 b();
1118}1118}
1119 )SOURCE", 1, ".tmp_source.zig:3:5: error: undefined function: 'b'");1119 )SOURCE", 1, ".tmp_source.zig:3:5: error: use of undeclared identifier 'b'");
11201120
1121 add_compile_fail_case("wrong number of arguments", R"SOURCE(1121 add_compile_fail_case("wrong number of arguments", R"SOURCE(
1122fn a() => {1122fn a() => {
...@@ -1282,7 +1282,7 @@ fn f() => {...@@ -1282,7 +1282,7 @@ fn f() => {
1282 add_compile_fail_case("missing else clause", R"SOURCE(1282 add_compile_fail_case("missing else clause", R"SOURCE(
1283fn f() => {1283fn f() => {
1284 const x : i32 = if (true) { 1 };1284 const x : i32 = if (true) { 1 };
1285 const y = if (true) { 1 as i32 };1285 const y = if (true) { i32(1) };
1286}1286}
1287 )SOURCE", 2, ".tmp_source.zig:3:21: error: expected type 'i32', got 'void'",1287 )SOURCE", 2, ".tmp_source.zig:3:21: error: expected type 'i32', got 'void'",
1288 ".tmp_source.zig:4:15: error: incompatible types: 'i32' and 'void'");1288 ".tmp_source.zig:4:15: error: incompatible types: 'i32' and 'void'");
...@@ -1383,9 +1383,9 @@ fn f() => {...@@ -1383,9 +1383,9 @@ fn f() => {
13831383
1384 add_compile_fail_case("cast unreachable", R"SOURCE(1384 add_compile_fail_case("cast unreachable", R"SOURCE(
1385fn f() i32 => {1385fn f() i32 => {
1386 (return 1) as i321386 i32(return 1)
1387}1387}
1388 )SOURCE", 1, ".tmp_source.zig:3:16: error: invalid cast from type 'unreachable' to 'i32'");1388 )SOURCE", 1, ".tmp_source.zig:3:8: error: invalid cast from type 'unreachable' to 'i32'");
13891389
1390 add_compile_fail_case("invalid builtin fn", R"SOURCE(1390 add_compile_fail_case("invalid builtin fn", R"SOURCE(
1391fn f() @bogus(foo) => {1391fn f() @bogus(foo) => {