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.
4141 provide a tag or sha1).
4242 * Include documentation generator.
4343 * 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
4551### Current Status
4652
doc/langref.md+1-3
......@@ -126,12 +126,10 @@ AdditionExpression : MultiplyExpression AdditionOperator AdditionExpression | Mu
126126
127127AdditionOperator : token(Plus) | token(Minus)
128128
129MultiplyExpression : CastExpression MultiplyOperator MultiplyExpression | CastExpression
129MultiplyExpression : PrefixOpExpression MultiplyOperator MultiplyExpression | PrefixOpExpression
130130
131131MultiplyOperator : token(Star) | token(Slash) | token(Percent)
132132
133CastExpression : CastExpression token(as) PrimaryExpression | PrefixOpExpression
134
135133PrefixOpExpression : PrefixOp PrefixOpExpression | SuffixOpExpression
136134
137135SuffixOpExpression : PrimaryExpression option(FnCallExpression | ArrayAccessExpression | FieldAccessExpression | SliceExpression | ContainerInitExpression)
doc/vim/syntax/zig.vim-1
......@@ -7,7 +7,6 @@ if exists("b:current_syntax")
77 finish
88endif
99
10syn keyword zigOperator as
1110syn keyword zigStorage const var extern volatile export pub noalias
1211syn keyword zigStructure struct enum type
1312syn 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 => {
77 print_str("Welcome to the Guess Number Game in Zig.\n");
88
99 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));
1111 if (err != @sizeof(u32)) {
1212 // TODO full error message
1313 fprint_str(stderr_fileno, "unable to get random bytes\n");
src/all_types.hpp+32-11
......@@ -106,7 +106,6 @@ enum NodeType {
106106 NodeTypeReturnExpr,
107107 NodeTypeVariableDeclaration,
108108 NodeTypeBinOpExpr,
109 NodeTypeCastExpr,
110109 NodeTypeNumberLiteral,
111110 NodeTypeStringLiteral,
112111 NodeTypeCharLiteral,
......@@ -272,6 +271,8 @@ struct AstNodeFnCallExpr {
272271 BuiltinFnEntry *builtin_fn;
273272 Expr resolved_expr;
274273 NumLitCodeGen resolved_num_lit;
274 Cast cast;
275 FnTableEntry *fn_entry;
275276};
276277
277278struct AstNodeArrayAccessExpr {
......@@ -320,15 +321,6 @@ struct AstNodeRootExportDecl {
320321 ZigList<AstNode *> *directives;
321322};
322323
323struct AstNodeCastExpr {
324 AstNode *expr;
325 AstNode *type;
326
327 // populated by semantic analyzer
328 Cast cast;
329 Expr resolved_expr;
330};
331
332324enum PrefixOp {
333325 PrefixOpInvalid,
334326 PrefixOpBoolNot,
......@@ -541,6 +533,9 @@ struct AstNodeSymbolExpr {
541533
542534 // populated by semantic analyzer
543535 Expr resolved_expr;
536 VariableTableEntry *variable;
537 TypeTableEntry *meta_type;
538 FnTableEntry *fn_entry;
544539};
545540
546541struct AstNodeBoolLiteral {
......@@ -588,7 +583,6 @@ struct AstNode {
588583 AstNodeBinOpExpr bin_op_expr;
589584 AstNodeExternBlock extern_block;
590585 AstNodeDirective directive;
591 AstNodeCastExpr cast_expr;
592586 AstNodePrefixOpExpr prefix_op_expr;
593587 AstNodeFnCallExpr fn_call_expr;
594588 AstNodeArrayAccessExpr array_access_expr;
......@@ -693,6 +687,12 @@ struct TypeTableEntryEnum {
693687 bool reported_infinite_err;
694688};
695689
690struct TypeTableEntryFn {
691 TypeTableEntry *return_type;
692 TypeTableEntry **param_types;
693 int param_count;
694};
695
696696enum TypeTableEntryId {
697697 TypeTableEntryIdInvalid,
698698 TypeTableEntryIdMetaType,
......@@ -707,6 +707,7 @@ enum TypeTableEntryId {
707707 TypeTableEntryIdNumberLiteral,
708708 TypeTableEntryIdMaybe,
709709 TypeTableEntryIdEnum,
710 TypeTableEntryIdFn,
710711};
711712
712713struct TypeTableEntry {
......@@ -728,6 +729,7 @@ struct TypeTableEntry {
728729 TypeTableEntryMaybe maybe;
729730 TypeTableEntryEnum enumeration;
730731 TypeTableEntryMetaType meta_type;
732 TypeTableEntryFn fn;
731733 } data;
732734
733735 // use these fields to make sure we don't duplicate type table entries for the same type
......@@ -781,6 +783,7 @@ struct FnTableEntry {
781783 ZigList<BlockContext *> all_block_contexts;
782784 TypeTableEntry *member_of_struct;
783785 Buf symbol_name;
786 TypeTableEntry *type_entry; // function type
784787
785788 // reminder: hash tables must be initialized before use
786789 HashMap<Buf *, LabelTableEntry *, buf_hash, buf_eql_buf> label_table;
......@@ -913,4 +916,22 @@ struct BlockContext {
913916 LLVMZigDIScope *di_scope;
914917};
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
916937#endif
src/analyze.cpp+405-242
......@@ -13,8 +13,8 @@
1313
1414static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import, BlockContext *context,
1515 TypeTableEntry *expected_type, AstNode *node);
16static TypeTableEntry *eval_const_expr(CodeGen *g, BlockContext *context,
17 AstNode *node, AstNodeNumberLiteral *out_number_literal);
16static void eval_const_expr(CodeGen *g, BlockContext *context,
17 AstNode *node, ConstExprValue *out_val);
1818static VariableTableEntry *analyze_variable_declaration(CodeGen *g, ImportTableEntry *import,
1919 BlockContext *context, TypeTableEntry *expected_type, AstNode *node);
2020static void resolve_struct_type(CodeGen *g, ImportTableEntry *import, TypeTableEntry *struct_type);
......@@ -32,8 +32,6 @@ static AstNode *first_executing_node(AstNode *node) {
3232 return first_executing_node(node->data.slice_expr.array_ref_expr);
3333 case NodeTypeFieldAccessExpr:
3434 return first_executing_node(node->data.field_access_expr.struct_expr);
35 case NodeTypeCastExpr:
36 return first_executing_node(node->data.cast_expr.expr);
3735 case NodeTypeRoot:
3836 case NodeTypeRootExportDecl:
3937 case NodeTypeFnProto:
......@@ -125,6 +123,7 @@ TypeTableEntry *new_type_table_entry(TypeTableEntryId id) {
125123 case TypeTableEntryIdArray:
126124 case TypeTableEntryIdNumberLiteral:
127125 case TypeTableEntryIdMaybe:
126 case TypeTableEntryIdFn:
128127 // nothing to init
129128 break;
130129 case TypeTableEntryIdStruct:
......@@ -357,63 +356,74 @@ static TypeTableEntry *analyze_type_expr(CodeGen *g, ImportTableEntry *import, B
357356 }
358357}
359358
360
361static TypeTableEntry *eval_const_expr_bin_op(CodeGen *g, BlockContext *context,
362 AstNode *node, AstNodeNumberLiteral *out_number_literal)
359static void eval_const_expr_bin_op(CodeGen *g, BlockContext *context,
360 AstNode *node, ConstExprValue *out_val)
363361{
364 AstNodeNumberLiteral op1_lit;
365 AstNodeNumberLiteral op2_lit;
366 TypeTableEntry *op1_type = eval_const_expr(g, context, node->data.bin_op_expr.op1, &op1_lit);
367 TypeTableEntry *op2_type = eval_const_expr(g, context, node->data.bin_op_expr.op1, &op2_lit);
368
369 if (op1_type->id == TypeTableEntryIdInvalid ||
370 op2_type->id == TypeTableEntryIdInvalid)
371 {
372 return g->builtin_types.entry_invalid;
362 AstNode *op1_node = node->data.bin_op_expr.op1;
363 AstNode *op2_node = node->data.bin_op_expr.op2;
364 ConstExprValue op1_val = {0};
365 ConstExprValue op2_val = {0};
366 eval_const_expr(g, context, op1_node, &op1_val);
367 eval_const_expr(g, context, op2_node, &op2_val);
368
369 if (!op1_val.ok || !op2_val.ok) {
370 return;
373371 }
374372
373 TypeTableEntry *op1_type = get_resolved_expr(op1_node)->type_entry;
374 TypeTableEntry *op2_type = get_resolved_expr(op2_node)->type_entry;
375
375376 // TODO complete more of this function instead of returning invalid
376377 // returning invalid makes the "unable to evaluate constant expression" error
377378
378379 switch (node->data.bin_op_expr.bin_op) {
379380 case BinOpTypeCmpNotEq:
380381 {
381 if (is_num_lit_unsigned(op1_lit.kind) &&
382 is_num_lit_unsigned(op2_lit.kind))
382 if (op1_type->id == TypeTableEntryIdInt &&
383 op2_type->id == TypeTableEntryIdInt)
383384 {
384 out_number_literal->kind = NumLitU8;
385 out_number_literal->overflow = false;
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;
385 out_val->data.x_bool = (op1_val.data.x_uint == op2_val.data.x_uint);
386 out_val->ok = true;
390387 }
388 break;
391389 }
392390 case BinOpTypeCmpLessThan:
393391 {
394 if (is_num_lit_unsigned(op1_lit.kind) &&
395 is_num_lit_unsigned(op2_lit.kind))
392 if (op1_type->id == TypeTableEntryIdInt &&
393 op2_type->id == TypeTableEntryIdInt)
396394 {
397 out_number_literal->kind = NumLitU8;
398 out_number_literal->overflow = false;
399 out_number_literal->data.x_uint = (op1_lit.data.x_uint < op2_lit.data.x_uint);
400 return get_resolved_expr(node)->type_entry;
401 } else {
402 return g->builtin_types.entry_invalid;
395 if (op1_type->data.integral.is_signed &&
396 op2_type->data.integral.is_signed)
397 {
398 out_val->data.x_bool = (op1_val.data.x_int < op2_val.data.x_int);
399 out_val->ok = true;
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 }
403406 }
407 break;
404408 }
405409 case BinOpTypeMod:
406410 {
407 if (is_num_lit_unsigned(op1_lit.kind) &&
408 is_num_lit_unsigned(op2_lit.kind))
411 if (op1_type->id == TypeTableEntryIdInt &&
412 op2_type->id == TypeTableEntryIdInt)
409413 {
410 out_number_literal->kind = NumLitU64;
411 out_number_literal->overflow = false;
412 out_number_literal->data.x_uint = (op1_lit.data.x_uint % op2_lit.data.x_uint);
413 return get_resolved_expr(node)->type_entry;
414 } else {
415 return g->builtin_types.entry_invalid;
414 if (op1_type->data.integral.is_signed &&
415 op2_type->data.integral.is_signed)
416 {
417 out_val->data.x_int = op1_val.data.x_int % op2_val.data.x_int;
418 out_val->ok = true;
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 }
416425 }
426 break;
417427 }
418428 case BinOpTypeBoolOr:
419429 case BinOpTypeBoolAnd:
......@@ -431,7 +441,7 @@ static TypeTableEntry *eval_const_expr_bin_op(CodeGen *g, BlockContext *context,
431441 case BinOpTypeMult:
432442 case BinOpTypeDiv:
433443 case BinOpTypeUnwrapMaybe:
434 return g->builtin_types.entry_invalid;
444 break;
435445 case BinOpTypeInvalid:
436446 case BinOpTypeAssign:
437447 case BinOpTypeAssignTimes:
......@@ -448,31 +458,23 @@ static TypeTableEntry *eval_const_expr_bin_op(CodeGen *g, BlockContext *context,
448458 case BinOpTypeAssignBoolOr:
449459 zig_unreachable();
450460 }
451 zig_unreachable();
452461}
453462
454static TypeTableEntry *eval_const_expr_fn_call(CodeGen *g, BlockContext *context,
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
463static void eval_const_expr_builtin(CodeGen *g, BlockContext *context, AstNode *node, ConstExprValue *out_val) {
461464 switch (node->data.fn_call_expr.builtin_fn->id) {
462465 case BuiltinFnIdInvalid:
463466 zig_unreachable();
464467 case BuiltinFnIdArithmeticWithOverflow:
465468 case BuiltinFnIdMemcpy:
466469 case BuiltinFnIdMemset:
467 return g->builtin_types.entry_invalid;
470 break;
468471 case BuiltinFnIdSizeof:
469472 {
470473 AstNode *type_node = node->data.fn_call_expr.params.at(0);
471474 TypeTableEntry *target_type = unwrapped_node_type(type_node);
472 out_number_literal->overflow = false;
473 out_number_literal->data.x_uint = target_type->size_in_bits / 8;
474 out_number_literal->kind = get_number_literal_kind_unsigned(out_number_literal->data.x_uint);
475 return get_resolved_expr(node)->type_entry;
475 out_val->data.x_uint = target_type->size_in_bits / 8;
476 out_val->ok = true;
477 break;
476478 }
477479 case BuiltinFnIdMaxValue:
478480 case BuiltinFnIdMinValue:
......@@ -480,43 +482,154 @@ static TypeTableEntry *eval_const_expr_fn_call(CodeGen *g, BlockContext *context
480482 case BuiltinFnIdValueCount:
481483 zig_panic("TODO eval_const_expr_fn_call value_count");
482484 case BuiltinFnIdTypeof:
483 return get_resolved_expr(node)->type_entry;
485 // TODO
486 out_val->ok = true;
487 break;
484488 }
485 zig_unreachable();
486489}
487490
488static TypeTableEntry *eval_const_expr(CodeGen *g, BlockContext *context,
489 AstNode *node, AstNodeNumberLiteral *out_number_literal)
491static void eval_const_expr_fn_call_known(CodeGen *g, BlockContext *context,
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)
490544{
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) {
491578 switch (node->type) {
492579 case NodeTypeNumberLiteral:
493 *out_number_literal = node->data.number_literal;
494 return get_resolved_expr(node)->type_entry;
580 {
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 }
495590 case NodeTypeBoolLiteral:
496 out_number_literal->data.x_uint = node->data.bool_literal.value ? 1 : 0;
497 return get_resolved_expr(node)->type_entry;
591 out_val->data.x_uint = node->data.bool_literal.value ? 1 : 0;
592 out_val->ok = true;
593 break;
498594 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;
500598 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;
502601 case NodeTypeSymbol:
503602 {
504 VariableTableEntry *var = find_variable(context, &node->data.symbol_expr.symbol);
505 assert(var);
506 AstNode *decl_node = var->decl_node;
507 AstNode *expr_node = decl_node->data.variable_declaration.expr;
508 if (expr_node) {
509 BlockContext *next_context = get_resolved_expr(expr_node)->block_context;
510 return eval_const_expr(g, next_context, expr_node, out_number_literal);
603 VariableTableEntry *var = node->data.symbol_expr.variable;
604 if (var) {
605 if (var->is_const) {
606 AstNode *decl_node = var->decl_node;
607 if (decl_node->type == NodeTypeVariableDeclaration) {
608 AstNode *expr_node = decl_node->data.variable_declaration.expr;
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;
511620 } else {
512 // can't eval it
513 return g->builtin_types.entry_invalid;
621 zig_unreachable();
514622 }
623 break;
515624 }
516625 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;
518631 default:
519 return g->builtin_types.entry_invalid;
632 break;
520633 }
521634}
522635
......@@ -550,11 +663,30 @@ static void resolve_function_proto(CodeGen *g, AstNode *node, FnTableEntry *fn_t
550663 }
551664 }
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) {
554678 AstNode *child = node->data.fn_proto.params.at(i);
555679 assert(child->type == NodeTypeParamDecl);
556680 TypeTableEntry *type_entry = analyze_type_expr(g, import, import->block_context,
557681 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
559691 if (type_entry->id == TypeTableEntryIdUnreachable) {
560692 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
567699 }
568700 }
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 }
571710}
572711
573712static 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
10581197 case NodeTypeBoolLiteral:
10591198 case NodeTypeNullLiteral:
10601199 case NodeTypeSymbol:
1061 case NodeTypeCastExpr:
10621200 case NodeTypePrefixOpExpr:
10631201 case NodeTypeIfBoolExpr:
10641202 case NodeTypeIfVarExpr:
......@@ -1116,6 +1254,7 @@ static bool num_lit_fits_in_other_type(CodeGen *g, TypeTableEntry *literal_type,
11161254 case TypeTableEntryIdStruct:
11171255 case TypeTableEntryIdEnum:
11181256 case TypeTableEntryIdMetaType:
1257 case TypeTableEntryIdFn:
11191258 return false;
11201259 case TypeTableEntryIdInt:
11211260 if (is_num_lit_unsigned(num_lit)) {
......@@ -1703,17 +1842,28 @@ static TypeTableEntry *analyze_symbol_expr(CodeGen *g, ImportTableEntry *import,
17031842
17041843 auto primitive_table_entry = g->primitive_type_table.maybe_get(variable_name);
17051844 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;
17071848 }
17081849
17091850 VariableTableEntry *var = find_variable(context, variable_name);
17101851 if (var) {
1852 node->data.symbol_expr.variable = var;
17111853 return var->type;
17121854 }
17131855
17141856 TypeTableEntry *container_type = find_container(context, variable_name);
17151857 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;
17171867 }
17181868
17191869 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) {
17811931 zig_unreachable();
17821932}
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
18431934enum LValPurpose {
18441935 LValPurposeAssign,
18451936 LValPurposeAddressOf,
......@@ -2153,17 +2244,11 @@ static TypeTableEntry *analyze_array_type(CodeGen *g, ImportTableEntry *import,
21532244 return g->builtin_types.entry_invalid;
21542245 }
21552246
2156 AstNodeNumberLiteral number_literal;
2157 TypeTableEntry *resolved_type = eval_const_expr(g, context, size_node, &number_literal);
2247 ConstExprValue const_val = {0};
2248 eval_const_expr(g, context, size_node, &const_val);
21582249
2159 if (resolved_type->id == TypeTableEntryIdInt) {
2160 if (resolved_type->data.integral.is_signed) {
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 }
2250 if (const_val.ok) {
2251 return get_meta_type(g, get_array_type(g, import, child_type, const_val.data.x_uint));
21672252 } else {
21682253 add_node_error(g, size_node,
21692254 buf_create_from_str("unable to resolve constant expression"));
......@@ -2195,12 +2280,11 @@ static TypeTableEntry *analyze_while_expr(CodeGen *g, ImportTableEntry *import,
21952280 } else {
21962281 // if the condition is a simple constant expression and there are no break statements
21972282 // then the return type is unreachable
2198 AstNodeNumberLiteral number_literal;
2199 TypeTableEntry *resolved_type = eval_const_expr(g, context, condition_node, &number_literal);
2200 if (resolved_type->id != TypeTableEntryIdInvalid) {
2201 assert(resolved_type->id == TypeTableEntryIdBool);
2202 bool constant_cond_value = number_literal.data.x_uint;
2203 if (constant_cond_value) {
2283 ConstExprValue const_val = {0};
2284 eval_const_expr(g, context, condition_node, &const_val);
2285
2286 if (const_val.ok) {
2287 if (const_val.data.x_bool) {
22042288 node->data.while_expr.condition_always_true = true;
22052289 if (!node->data.while_expr.contains_break) {
22062290 expr_return_type = g->builtin_types.entry_unreachable;
......@@ -2305,6 +2389,73 @@ static TypeTableEntry *analyze_min_max_value(CodeGen *g, ImportTableEntry *impor
23052389 }
23062390}
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
23082459static TypeTableEntry *analyze_builtin_fn_call_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
23092460 TypeTableEntry *expected_type, AstNode *node)
23102461{
......@@ -2458,25 +2609,93 @@ static TypeTableEntry *analyze_builtin_fn_call_expr(CodeGen *g, ImportTableEntry
24582609 }
24592610}
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
24612663static TypeTableEntry *analyze_fn_call_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
24622664 TypeTableEntry *expected_type, AstNode *node)
24632665{
24642666 AstNode *fn_ref_expr = node->data.fn_call_expr.fn_ref_expr;
2465 TypeTableEntry *struct_type = nullptr;
2466 HashMap<Buf *, FnTableEntry *, buf_hash, buf_eql_buf> *fn_table = &import->fn_table;
2467 AstNode *first_param_expr = nullptr;
2468 Buf *name;
2667
2668 if (node->data.fn_call_expr.is_builtin) {
2669 return analyze_builtin_fn_call_expr(g, import, context, expected_type, node);
2670 }
24692671
24702672 if (fn_ref_expr->type == NodeTypeFieldAccessExpr) {
2471 first_param_expr = fn_ref_expr->data.field_access_expr.struct_expr;
2472 struct_type = analyze_expression(g, import, context, nullptr, first_param_expr);
2473 name = &fn_ref_expr->data.field_access_expr.field_name;
2474 if (struct_type->id == TypeTableEntryIdStruct) {
2475 fn_table = &struct_type->data.structure.fn_table;
2476 } else if (struct_type->id == TypeTableEntryIdPointer &&
2477 struct_type->data.pointer.child_type->id == TypeTableEntryIdStruct)
2673 AstNode *first_param_expr = fn_ref_expr->data.field_access_expr.struct_expr;
2674 TypeTableEntry *struct_type = analyze_expression(g, import, context, nullptr, first_param_expr);
2675 Buf *name = &fn_ref_expr->data.field_access_expr.field_name;
2676 if (struct_type->id == TypeTableEntryIdStruct ||
2677 (struct_type->id == TypeTableEntryIdPointer &&
2678 struct_type->data.pointer.child_type->id == TypeTableEntryIdStruct))
24782679 {
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 }
24802699 } else if (struct_type->id == TypeTableEntryIdInvalid) {
24812700 return struct_type;
24822701 } else if (struct_type->id == TypeTableEntryIdMetaType &&
......@@ -2505,74 +2724,31 @@ static TypeTableEntry *analyze_fn_call_expr(CodeGen *g, ImportTableEntry *import
25052724 buf_sprintf("member reference base type not struct or enum"));
25062725 return g->builtin_types.entry_invalid;
25072726 }
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;
25172727 }
25182728
2519 auto entry = fn_table->maybe_get(name);
2520
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
2729 TypeTableEntry *invoke_type_entry = analyze_expression(g, import, context, nullptr, fn_ref_expr);
2730 if (invoke_type_entry->id == TypeTableEntryIdInvalid) {
25302731 return g->builtin_types.entry_invalid;
2531 } else {
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 }
2732 }
25432733
2544 if (fn_proto->is_var_args) {
2545 if (actual_param_count < expected_param_count) {
2546 add_node_error(g, node,
2547 buf_sprintf("expected at least %d arguments, got %d",
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 }
2734 // use constant expression evaluator to figure out the function at compile time.
2735 // otherwise we treat this as a function pointer.
2736 ConstExprValue const_val = {0};
2737 eval_const_expr(g, context, fn_ref_expr, &const_val);
25552738
2556 // analyze each parameter. in the case of a method, we already analyzed the
2557 // first parameter in order to figure out which struct we were calling a method on.
2558 for (int i = 0; i < node->data.fn_call_expr.params.length; i += 1) {
2559 AstNode *child = node->data.fn_call_expr.params.at(i);
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 }
2739 if (!const_val.ok) {
2740 add_node_error(g, node, buf_sprintf("function pointers not yet supported"));
2741 return g->builtin_types.entry_invalid;
2742 }
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;
25762752 }
25772753}
25782754
......@@ -2847,9 +3023,6 @@ static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import,
28473023 case NodeTypeSymbol:
28483024 return_type = analyze_symbol_expr(g, import, context, expected_type, node);
28493025 break;
2850 case NodeTypeCastExpr:
2851 return_type = analyze_cast_expr(g, import, context, expected_type, node);
2852 break;
28533026 case NodeTypePrefixOpExpr:
28543027 return_type = analyze_prefix_op_expr(g, import, context, expected_type, node);
28553028 break;
......@@ -3008,7 +3181,6 @@ static void analyze_top_level_decl(CodeGen *g, ImportTableEntry *import, AstNode
30083181 case NodeTypeBoolLiteral:
30093182 case NodeTypeNullLiteral:
30103183 case NodeTypeSymbol:
3011 case NodeTypeCastExpr:
30123184 case NodeTypePrefixOpExpr:
30133185 case NodeTypeIfBoolExpr:
30143186 case NodeTypeIfVarExpr:
......@@ -3060,10 +3232,6 @@ static void collect_expr_decl_deps(CodeGen *g, ImportTableEntry *import, AstNode
30603232 case NodeTypeReturnExpr:
30613233 collect_expr_decl_deps(g, import, node->data.return_expr.expr, decl_node);
30623234 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;
30673235 case NodeTypePrefixOpExpr:
30683236 collect_expr_decl_deps(g, import, node->data.prefix_op_expr.primary_expr, decl_node);
30693237 break;
......@@ -3331,7 +3499,6 @@ static void detect_top_level_decl_deps(CodeGen *g, ImportTableEntry *import, Ast
33313499 case NodeTypeBoolLiteral:
33323500 case NodeTypeNullLiteral:
33333501 case NodeTypeSymbol:
3334 case NodeTypeCastExpr:
33353502 case NodeTypePrefixOpExpr:
33363503 case NodeTypeIfBoolExpr:
33373504 case NodeTypeIfVarExpr:
......@@ -3504,8 +3671,6 @@ Expr *get_resolved_expr(AstNode *node) {
35043671 return &node->data.return_expr.resolved_expr;
35053672 case NodeTypeBinOpExpr:
35063673 return &node->data.bin_op_expr.resolved_expr;
3507 case NodeTypeCastExpr:
3508 return &node->data.cast_expr.resolved_expr;
35093674 case NodeTypePrefixOpExpr:
35103675 return &node->data.prefix_op_expr.resolved_expr;
35113676 case NodeTypeFnCallExpr:
......@@ -3577,7 +3742,6 @@ NumLitCodeGen *get_resolved_num_lit(AstNode *node) {
35773742 return &node->data.fn_call_expr.resolved_num_lit;
35783743 case NodeTypeReturnExpr:
35793744 case NodeTypeBinOpExpr:
3580 case NodeTypeCastExpr:
35813745 case NodeTypePrefixOpExpr:
35823746 case NodeTypeArrayAccessExpr:
35833747 case NodeTypeSliceExpr:
......@@ -3627,7 +3791,6 @@ TopLevelDecl *get_resolved_top_level_decl(AstNode *node) {
36273791 case NodeTypeNumberLiteral:
36283792 case NodeTypeReturnExpr:
36293793 case NodeTypeBinOpExpr:
3630 case NodeTypeCastExpr:
36313794 case NodeTypePrefixOpExpr:
36323795 case NodeTypeFnCallExpr:
36333796 case NodeTypeArrayAccessExpr:
src/codegen.cpp+28-38
......@@ -71,6 +71,8 @@ static LLVMValueRef gen_var_decl_raw(CodeGen *g, AstNode *source_node, AstNodeVa
7171static LLVMValueRef gen_assign_raw(CodeGen *g, AstNode *source_node, BinOpType bin_op,
7272 LLVMValueRef target_ref, LLVMValueRef value,
7373 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);
7476
7577static TypeTableEntry *get_type_for_type_node(AstNode *node) {
7678 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
381383 }
382384}
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
385402static LLVMValueRef gen_fn_call_expr(CodeGen *g, AstNode *node) {
386403 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;
389412 AstNode *fn_ref_expr = node->data.fn_call_expr.fn_ref_expr;
390 TypeTableEntry *struct_type;
391 AstNode *first_param_expr;
413 TypeTableEntry *struct_type = nullptr;
414 AstNode *first_param_expr = nullptr;
392415 if (fn_ref_expr->type == NodeTypeFieldAccessExpr) {
393 Buf *name = &fn_ref_expr->data.field_access_expr.field_name;
394416 first_param_expr = fn_ref_expr->data.field_access_expr.struct_expr;
395417 struct_type = get_expr_type(first_param_expr);
396418 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;
398420 } else if (struct_type->id == TypeTableEntryIdPointer) {
399421 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;
401423 } else if (struct_type->id == TypeTableEntryIdMetaType &&
402424 struct_type->data.meta_type.child_type->id == TypeTableEntryIdEnum)
403425 {
......@@ -414,24 +436,8 @@ static LLVMValueRef gen_fn_call_expr(CodeGen *g, AstNode *node) {
414436 } else {
415437 zig_unreachable();
416438 }
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();
432439 }
433440
434
435441 assert(fn_table_entry->proto_node->type == NodeTypeFnProto);
436442 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
863869 zig_unreachable();
864870}
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
880872static LLVMValueRef gen_arithmetic_bin_op(CodeGen *g, AstNode *source_node,
881873 LLVMValueRef val1, LLVMValueRef val2,
882874 TypeTableEntry *op1_type, TypeTableEntry *op2_type,
......@@ -1810,8 +1802,6 @@ static LLVMValueRef gen_expr_no_cast(CodeGen *g, AstNode *node) {
18101802 return gen_return_expr(g, node);
18111803 case NodeTypeVariableDeclaration:
18121804 return gen_var_decl_expr(g, node);
1813 case NodeTypeCastExpr:
1814 return gen_cast_expr(g, node);
18151805 case NodeTypePrefixOpExpr:
18161806 return gen_prefix_op_expr(g, node);
18171807 case NodeTypeFnCallExpr:
src/parser.cpp+3-34
......@@ -99,8 +99,6 @@ const char *node_type_str(NodeType node_type) {
9999 return "ReturnExpr";
100100 case NodeTypeVariableDeclaration:
101101 return "VariableDeclaration";
102 case NodeTypeCastExpr:
103 return "CastExpr";
104102 case NodeTypeNumberLiteral:
105103 return "NumberLiteral";
106104 case NodeTypeStringLiteral:
......@@ -265,12 +263,6 @@ void ast_print(AstNode *node, int indent) {
265263 case NodeTypeDirective:
266264 fprintf(stderr, "%s\n", node_type_str(node->type));
267265 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;
274266 case NodeTypePrefixOpExpr:
275267 fprintf(stderr, "%s %s\n", node_type_str(node->type),
276268 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
16041596}
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
16301599static BinOpType tok_to_mult_op(Token *token) {
16311600 switch (token->id) {
16321601 case TokenIdStar: return BinOpTypeMult;
......@@ -1654,10 +1623,10 @@ static BinOpType ast_parse_mult_op(ParseContext *pc, int *token_index, bool mand
16541623}
16551624
16561625/*
1657MultiplyExpression : CastExpression MultiplyOperator MultiplyExpression | CastExpression
1626MultiplyExpression : PrefixOpExpression MultiplyOperator MultiplyExpression | PrefixOpExpression
16581627*/
16591628static 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);
16611630 if (!operand_1)
16621631 return nullptr;
16631632
......@@ -1667,7 +1636,7 @@ static AstNode *ast_parse_mult_expr(ParseContext *pc, int *token_index, bool man
16671636 if (mult_op == BinOpTypeInvalid)
16681637 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
16721641 AstNode *node = ast_create_node(pc, NodeTypeBinOpExpr, token);
16731642 node->data.bin_op_expr.op1 = operand_1;
src/tokenizer.cpp-3
......@@ -211,8 +211,6 @@ static void end_token(Tokenize *t) {
211211 t->cur_tok->id = TokenIdKeywordPub;
212212 } else if (mem_eql_str(token_mem, token_len, "export")) {
213213 t->cur_tok->id = TokenIdKeywordExport;
214 } else if (mem_eql_str(token_mem, token_len, "as")) {
215 t->cur_tok->id = TokenIdKeywordAs;
216214 } else if (mem_eql_str(token_mem, token_len, "use")) {
217215 t->cur_tok->id = TokenIdKeywordUse;
218216 } else if (mem_eql_str(token_mem, token_len, "true")) {
......@@ -1019,7 +1017,6 @@ const char * token_name(TokenId id) {
10191017 case TokenIdKeywordExtern: return "extern";
10201018 case TokenIdKeywordPub: return "pub";
10211019 case TokenIdKeywordExport: return "export";
1022 case TokenIdKeywordAs: return "as";
10231020 case TokenIdKeywordUse: return "use";
10241021 case TokenIdKeywordTrue: return "true";
10251022 case TokenIdKeywordFalse: return "false";
src/tokenizer.hpp-1
......@@ -20,7 +20,6 @@ enum TokenId {
2020 TokenIdKeywordExtern,
2121 TokenIdKeywordPub,
2222 TokenIdKeywordExport,
23 TokenIdKeywordAs,
2423 TokenIdKeywordUse,
2524 TokenIdKeywordTrue,
2625 TokenIdKeywordFalse,
std/rand.zig+4-4
......@@ -13,7 +13,7 @@ pub struct Rand {
1313 var i : @typeof(ARRAY_SIZE) = 1;
1414 while (i < ARRAY_SIZE) {
1515 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);
1717 i += 1;
1818 }
1919 }
......@@ -41,7 +41,7 @@ pub struct Rand {
4141 var bytes_left = r.get_bytes_aligned(buf);
4242 if (bytes_left > 0) {
4343 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();
4545 while (bytes_left > 0) {
4646 buf[buf.len - bytes_left] = rand_val_array[@sizeof(u32) - bytes_left];
4747 bytes_left -= 1;
......@@ -59,7 +59,7 @@ pub struct Rand {
5959
6060 while (true) {
6161 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));
6363 if (rand_val < upper_bound) {
6464 return start + (rand_val % range);
6565 }
......@@ -85,7 +85,7 @@ pub struct Rand {
8585 fn get_bytes_aligned(r: &Rand, buf: []u8) usize => {
8686 var bytes_left = buf.len;
8787 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();
8989 bytes_left -= @sizeof(u32);
9090 }
9191 return bytes_left;
std/std.zig+4-4
......@@ -43,7 +43,7 @@ pub fn readline(buf: []u8, out_len: &usize) bool => {
4343 if (amt_read < 0) {
4444 return true;
4545 }
46 *out_len = amt_read as usize;
46 *out_len = usize(amt_read);
4747 return false;
4848}
4949
......@@ -94,9 +94,9 @@ const max_u64_base10_digits: usize = 20;
9494fn buf_print_i64(out_buf: []u8, x: i64) usize => {
9595 if (x < 0) {
9696 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);
9898 } else {
99 return buf_print_u64(out_buf, x as u64);
99 return buf_print_u64(out_buf, u64(x));
100100 }
101101}
102102
......@@ -108,7 +108,7 @@ fn buf_print_u64(out_buf: []u8, x: u64) usize => {
108108 while (true) {
109109 const digit = a % 10;
110110 index -= 1;
111 buf[index] = '0' + (digit as u8);
111 buf[index] = '0' + u8(digit);
112112 a /= 10;
113113 if (a == 0)
114114 break;
std/syscall.zig+4-5
......@@ -18,19 +18,18 @@ fn syscall3(number: usize, arg1: usize, arg2: usize, arg3: usize) usize => {
1818}
1919
2020pub fn read(fd: isize, buf: &u8, count: usize) isize => {
21 syscall3(SYS_read, fd as usize, buf as usize, count) as isize
21 isize(syscall3(SYS_read, usize(fd), usize(buf), count))
2222}
2323
2424pub fn write(fd: isize, buf: &const u8, count: usize) isize => {
25 syscall3(SYS_write, fd as usize, buf as usize, count) as isize
25 isize(syscall3(SYS_write, usize(fd), usize(buf), count))
2626}
2727
2828pub fn exit(status: i32) unreachable => {
29 syscall1(SYS_exit, status as usize);
29 syscall1(SYS_exit, usize(status));
3030 unreachable{}
3131}
3232
3333pub fn getrandom(buf: &u8, count: usize, flags: u32) isize => {
34 syscall3(SYS_getrandom, buf as usize, count, flags as usize) as isize
34 isize(syscall3(SYS_getrandom, usize(buf), count, usize(flags)))
3535}
36
test/run_tests.cpp+45-45
......@@ -272,7 +272,7 @@ use "std.zig";
272272
273273pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => {
274274 const a : i32 = 1;
275 const b = 2 as i32;
275 const b = i32(2);
276276 if (a + b == 3) {
277277 print_str("OK\n");
278278 }
......@@ -302,7 +302,7 @@ pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => {
302302 }
303303
304304 const c = {
305 const no_conflict = 10 as i32;
305 const no_conflict = i32(10);
306306 no_conflict
307307 };
308308 if (c == 10) { print_str("OK 2\n"); }
......@@ -358,7 +358,7 @@ pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => {
358358 var zero : i32 = 0;
359359 if (zero == 0) { print_str("zero\n"); }
360360
361 var i = 0 as i32;
361 var i = i32(0);
362362loop_start:
363363 if (i == 3) {
364364 goto done;
......@@ -384,7 +384,7 @@ pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => {
384384 }
385385
386386 i = 0;
387 var accumulator = 0 as u32;
387 var accumulator = u32(0);
388388 while (i < 5) {
389389 accumulator += array[i];
390390
......@@ -430,9 +430,9 @@ pub fn main(argc : isize, argv : &&u8, env : &&u8) i32 => {
430430 if (90 >> 1 >> 2 != 90 >> 3) { print_str("BAD 7\n"); }
431431 if (100 - 1 + 1000 != 1099) { print_str("BAD 8\n"); }
432432 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"); }
434434 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
437437 print_str("OK\n");
438438 return 0;
......@@ -495,82 +495,82 @@ export fn main(argc : isize, argv : &&u8, env : &&u8) i32 => {
495495 printf(c"\n");
496496
497497 printf(c"0: %llu\n",
498 0 as u64);
498 u64(0));
499499 printf(c"320402575052271: %llu\n",
500 320402575052271 as u64);
500 u64(320402575052271));
501501 printf(c"0x01236789abcdef: %llu\n",
502 0x01236789abcdef as u64);
502 u64(0x01236789abcdef));
503503 printf(c"0xffffffffffffffff: %llu\n",
504 0xffffffffffffffff as u64);
504 u64(0xffffffffffffffff));
505505 printf(c"0x000000ffffffffffffffff: %llu\n",
506 0x000000ffffffffffffffff as u64);
506 u64(0x000000ffffffffffffffff));
507507 printf(c"0o1777777777777777777777: %llu\n",
508 0o1777777777777777777777 as u64);
508 u64(0o1777777777777777777777));
509509 printf(c"0o0000001777777777777777777777: %llu\n",
510 0o0000001777777777777777777777 as u64);
510 u64(0o0000001777777777777777777777));
511511 printf(c"0b1111111111111111111111111111111111111111111111111111111111111111: %llu\n",
512 0b1111111111111111111111111111111111111111111111111111111111111111 as u64);
512 u64(0b1111111111111111111111111111111111111111111111111111111111111111));
513513 printf(c"0b0000001111111111111111111111111111111111111111111111111111111111111111: %llu\n",
514 0b0000001111111111111111111111111111111111111111111111111111111111111111 as u64);
514 u64(0b0000001111111111111111111111111111111111111111111111111111111111111111));
515515
516516 printf(c"\n");
517517
518518 printf(c"0.0: %a\n",
519 0.0 as f64);
519 f64(0.0));
520520 printf(c"0e0: %a\n",
521 0e0 as f64);
521 f64(0e0));
522522 printf(c"0.0e0: %a\n",
523 0.0e0 as f64);
523 f64(0.0e0));
524524 printf(c"000000000000000000000000000000000000000000000000000000000.0e0: %a\n",
525 000000000000000000000000000000000000000000000000000000000.0e0 as f64);
525 f64(000000000000000000000000000000000000000000000000000000000.0e0));
526526 printf(c"0.000000000000000000000000000000000000000000000000000000000e0: %a\n",
527 0.000000000000000000000000000000000000000000000000000000000e0 as f64);
527 f64(0.000000000000000000000000000000000000000000000000000000000e0));
528528 printf(c"0.0e000000000000000000000000000000000000000000000000000000000: %a\n",
529 0.0e000000000000000000000000000000000000000000000000000000000 as f64);
529 f64(0.0e000000000000000000000000000000000000000000000000000000000));
530530 printf(c"1.0: %a\n",
531 1.0 as f64);
531 f64(1.0));
532532 printf(c"10.0: %a\n",
533 10.0 as f64);
533 f64(10.0));
534534 printf(c"10.5: %a\n",
535 10.5 as f64);
535 f64(10.5));
536536 printf(c"10.5e5: %a\n",
537 10.5e5 as f64);
537 f64(10.5e5));
538538 printf(c"10.5e+5: %a\n",
539 10.5e+5 as f64);
539 f64(10.5e+5));
540540 printf(c"50.0e-2: %a\n",
541 50.0e-2 as f64);
541 f64(50.0e-2));
542542 printf(c"50e-2: %a\n",
543 50e-2 as f64);
543 f64(50e-2));
544544
545545 printf(c"\n");
546546
547547 printf(c"0x1.0: %a\n",
548 0x1.0 as f64);
548 f64(0x1.0));
549549 printf(c"0x10.0: %a\n",
550 0x10.0 as f64);
550 f64(0x10.0));
551551 printf(c"0x100.0: %a\n",
552 0x100.0 as f64);
552 f64(0x100.0));
553553 printf(c"0x103.0: %a\n",
554 0x103.0 as f64);
554 f64(0x103.0));
555555 printf(c"0x103.7: %a\n",
556 0x103.7 as f64);
556 f64(0x103.7));
557557 printf(c"0x103.70: %a\n",
558 0x103.70 as f64);
558 f64(0x103.70));
559559 printf(c"0x103.70p4: %a\n",
560 0x103.70p4 as f64);
560 f64(0x103.70p4));
561561 printf(c"0x103.70p5: %a\n",
562 0x103.70p5 as f64);
562 f64(0x103.70p5));
563563 printf(c"0x103.70p+5: %a\n",
564 0x103.70p+5 as f64);
564 f64(0x103.70p+5));
565565 printf(c"0x103.70p-5: %a\n",
566 0x103.70p-5 as f64);
566 f64(0x103.70p-5));
567567
568568 printf(c"\n");
569569
570570 printf(c"0b10100.00010e0: %a\n",
571 0b10100.00010e0 as f64);
571 f64(0b10100.00010e0));
572572 printf(c"0o10700.00010e0: %a\n",
573 0o10700.00010e0 as f64);
573 f64(0o10700.00010e0));
574574
575575 return 0;
576576}
......@@ -818,7 +818,7 @@ pub fn main(argc : isize, argv : &&u8, env : &&u8) i32 => {
818818use "std.zig";
819819
820820pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => {
821 var x = 3 as i32;
821 var x = i32(3);
822822 const y = &x;
823823
824824 *y += 1;
......@@ -1116,7 +1116,7 @@ fn a() i32 => {}
11161116fn a() => {
11171117 b();
11181118}
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
11211121 add_compile_fail_case("wrong number of arguments", R"SOURCE(
11221122fn a() => {
......@@ -1282,7 +1282,7 @@ fn f() => {
12821282 add_compile_fail_case("missing else clause", R"SOURCE(
12831283fn f() => {
12841284 const x : i32 = if (true) { 1 };
1285 const y = if (true) { 1 as i32 };
1285 const y = if (true) { i32(1) };
12861286}
12871287 )SOURCE", 2, ".tmp_source.zig:3:21: error: expected type 'i32', got 'void'",
12881288 ".tmp_source.zig:4:15: error: incompatible types: 'i32' and 'void'");
......@@ -1383,9 +1383,9 @@ fn f() => {
13831383
13841384 add_compile_fail_case("cast unreachable", R"SOURCE(
13851385fn f() i32 => {
1386 (return 1) as i32
1386 i32(return 1)
13871387}
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
13901390 add_compile_fail_case("invalid builtin fn", R"SOURCE(
13911391fn f() @bogus(foo) => {