authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-02-02 17:09:27-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-02-02 17:09:27-05:00
logc0b37e8514a26f56e3596f86b01771b1ae2bf299
treeb24c7fd04b2e8582d4e79455455e740ef58ca864
parent8b1c6d8b76ad1861f963fc7a2a079af5d8729a70

add try expression

See #83

12 files changed, 330 insertions(+), 89 deletions(-)

doc/langref.md+3-1
...@@ -69,7 +69,7 @@ AssignmentExpression = UnwrapExpression AssignmentOperator UnwrapExpression | Un...@@ -69,7 +69,7 @@ AssignmentExpression = UnwrapExpression AssignmentOperator UnwrapExpression | Un
6969
70AssignmentOperator = "=" | "*=" | "/=" | "%=" | "+=" | "-=" | "<<=" | ">>=" | "&=" | "^=" | "|=" | "&&=" | "||=" | "*%=" | "+%=" | "-%=" | "<<%="70AssignmentOperator = "=" | "*=" | "/=" | "%=" | "+=" | "-=" | "<<=" | ">>=" | "&=" | "^=" | "|=" | "&&=" | "||=" | "*%=" | "+%=" | "-%=" | "<<%="
7171
72BlockExpression = IfExpression | Block | WhileExpression | ForExpression | SwitchExpression | CompTimeExpression72BlockExpression = IfExpression | Block | WhileExpression | ForExpression | SwitchExpression | CompTimeExpression | TryExpression
7373
74CompTimeExpression = option("comptime") Expression74CompTimeExpression = option("comptime") Expression
7575
...@@ -93,6 +93,8 @@ IfExpression = IfVarExpression | IfBoolExpression...@@ -93,6 +93,8 @@ IfExpression = IfVarExpression | IfBoolExpression
9393
94IfBoolExpression = "if" "(" Expression ")" Expression option(Else)94IfBoolExpression = "if" "(" Expression ")" Expression option(Else)
9595
96TryExpression = "try" "(" ("const" | "var") option("*") Symbol "=" Expression ")" Expression option("else" option("|" Symbol "|") Expression)
97
96IfVarExpression = "if" "(" ("const" | "var") option("*") Symbol option(":" TypeExpr) "?=" Expression ")" Expression Option(Else)98IfVarExpression = "if" "(" ("const" | "var") option("*") Symbol option(":" TypeExpr) "?=" Expression ")" Expression Option(Else)
9799
98Else = "else" Expression100Else = "else" Expression
doc/vim/syntax/zig.vim+1-1
...@@ -11,7 +11,7 @@ let b:current_syntax = "zig"...@@ -11,7 +11,7 @@ let b:current_syntax = "zig"
11syn keyword zigStorage const var extern export pub noalias inline comptime nakedcc coldcc11syn keyword zigStorage const var extern export pub noalias inline comptime nakedcc coldcc
12syn keyword zigStructure struct enum union12syn keyword zigStructure struct enum union
13syn keyword zigStatement goto break return continue asm defer13syn keyword zigStatement goto break return continue asm defer
14syn keyword zigConditional if else switch14syn keyword zigConditional if else switch try
15syn keyword zigRepeat while for15syn keyword zigRepeat while for
1616
17syn keyword zigConstant null undefined zeroes this17syn keyword zigConstant null undefined zeroes this
src/all_types.hpp+12
...@@ -299,6 +299,7 @@ enum NodeType {...@@ -299,6 +299,7 @@ enum NodeType {
299 NodeTypeErrorType,299 NodeTypeErrorType,
300 NodeTypeTypeLiteral,300 NodeTypeTypeLiteral,
301 NodeTypeVarLiteral,301 NodeTypeVarLiteral,
302 NodeTypeTryExpr,
302};303};
303304
304struct AstNodeRoot {305struct AstNodeRoot {
...@@ -511,6 +512,16 @@ struct AstNodeIfBoolExpr {...@@ -511,6 +512,16 @@ struct AstNodeIfBoolExpr {
511 AstNode *else_node; // null, block node, or other if expr node512 AstNode *else_node; // null, block node, or other if expr node
512};513};
513514
515struct AstNodeTryExpr {
516 bool var_is_const;
517 Buf *var_symbol;
518 bool var_is_ptr;
519 AstNode *target_node;
520 AstNode *then_node;
521 AstNode *else_node;
522 Buf *err_symbol;
523};
524
514struct AstNodeIfVarExpr {525struct AstNodeIfVarExpr {
515 AstNodeVariableDeclaration var_decl;526 AstNodeVariableDeclaration var_decl;
516 AstNode *then_block;527 AstNode *then_block;
...@@ -721,6 +732,7 @@ struct AstNode {...@@ -721,6 +732,7 @@ struct AstNode {
721 AstNodeUse use;732 AstNodeUse use;
722 AstNodeIfBoolExpr if_bool_expr;733 AstNodeIfBoolExpr if_bool_expr;
723 AstNodeIfVarExpr if_var_expr;734 AstNodeIfVarExpr if_var_expr;
735 AstNodeTryExpr try_expr;
724 AstNodeWhileExpr while_expr;736 AstNodeWhileExpr while_expr;
725 AstNodeForExpr for_expr;737 AstNodeForExpr for_expr;
726 AstNodeSwitchExpr switch_expr;738 AstNodeSwitchExpr switch_expr;
src/analyze.cpp+1
...@@ -1769,6 +1769,7 @@ void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node) {...@@ -1769,6 +1769,7 @@ void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node) {
1769 case NodeTypeErrorType:1769 case NodeTypeErrorType:
1770 case NodeTypeTypeLiteral:1770 case NodeTypeTypeLiteral:
1771 case NodeTypeVarLiteral:1771 case NodeTypeVarLiteral:
1772 case NodeTypeTryExpr:
1772 zig_unreachable();1773 zig_unreachable();
1773 }1774 }
1774}1775}
src/ast_render.cpp+21
...@@ -223,6 +223,8 @@ static const char *node_type_str(NodeType node_type) {...@@ -223,6 +223,8 @@ static const char *node_type_str(NodeType node_type) {
223 return "TypeLiteral";223 return "TypeLiteral";
224 case NodeTypeVarLiteral:224 case NodeTypeVarLiteral:
225 return "VarLiteral";225 return "VarLiteral";
226 case NodeTypeTryExpr:
227 return "TryExpr";
226 }228 }
227 zig_unreachable();229 zig_unreachable();
228}230}
...@@ -769,6 +771,25 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {...@@ -769,6 +771,25 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {
769 }771 }
770 break;772 break;
771 }773 }
774 case NodeTypeTryExpr:
775 {
776 const char *var_str = node->data.try_expr.var_is_const ? "const" : "var";
777 const char *var_name = buf_ptr(node->data.try_expr.var_symbol);
778 const char *ptr_str = node->data.try_expr.var_is_ptr ? "*" : "";
779 fprintf(ar->f, "try (%s %s%s", var_str, ptr_str, var_name);
780 fprintf(ar->f, " = ");
781 render_node_grouped(ar, node->data.try_expr.target_node);
782 fprintf(ar->f, ") ");
783 render_node_grouped(ar, node->data.try_expr.then_node);
784 if (node->data.try_expr.else_node) {
785 fprintf(ar->f, " else ");
786 if (node->data.try_expr.err_symbol) {
787 fprintf(ar->f, "|%s| ", buf_ptr(node->data.try_expr.err_symbol));
788 }
789 render_node_grouped(ar, node->data.try_expr.else_node);
790 }
791 break;
792 }
772 case NodeTypeSwitchExpr:793 case NodeTypeSwitchExpr:
773 {794 {
774 AstNodeSwitchExpr *switch_expr = &node->data.switch_expr;795 AstNodeSwitchExpr *switch_expr = &node->data.switch_expr;
src/ir.cpp+94
...@@ -4748,6 +4748,98 @@ static IrInstruction *ir_gen_if_var_expr(IrBuilder *irb, Scope *scope, AstNode *...@@ -4748,6 +4748,98 @@ static IrInstruction *ir_gen_if_var_expr(IrBuilder *irb, Scope *scope, AstNode *
4748 return ir_build_phi(irb, scope, node, 2, incoming_blocks, incoming_values);4748 return ir_build_phi(irb, scope, node, 2, incoming_blocks, incoming_values);
4749}4749}
47504750
4751static IrInstruction *ir_gen_try_expr(IrBuilder *irb, Scope *scope, AstNode *node) {
4752 assert(node->type == NodeTypeTryExpr);
4753
4754 AstNode *target_node = node->data.try_expr.target_node;
4755 AstNode *then_node = node->data.try_expr.then_node;
4756 AstNode *else_node = node->data.try_expr.else_node;
4757 bool var_is_ptr = node->data.try_expr.var_is_ptr;
4758 bool var_is_const = node->data.try_expr.var_is_const;
4759 Buf *var_symbol = node->data.try_expr.var_symbol;
4760 Buf *err_symbol = node->data.try_expr.err_symbol;
4761
4762 IrInstruction *err_val_ptr = ir_gen_node_extra(irb, target_node, scope, LValPurposeAddressOf);
4763 if (err_val_ptr == irb->codegen->invalid_instruction)
4764 return err_val_ptr;
4765
4766 IrInstruction *err_val = ir_build_load_ptr(irb, scope, node, err_val_ptr);
4767 IrInstruction *is_err = ir_build_test_err(irb, scope, node, err_val);
4768
4769 IrBasicBlock *ok_block = ir_build_basic_block(irb, scope, "TryOk");
4770 IrBasicBlock *else_block = ir_build_basic_block(irb, scope, "TryElse");
4771 IrBasicBlock *endif_block = ir_build_basic_block(irb, scope, "TryEnd");
4772
4773 IrInstruction *is_comptime;
4774 if (ir_should_inline(irb->exec, scope)) {
4775 is_comptime = ir_build_const_bool(irb, scope, node, true);
4776 } else {
4777 is_comptime = ir_build_test_comptime(irb, scope, node, is_err);
4778 }
4779 ir_build_cond_br(irb, scope, node, is_err, else_block, ok_block, is_comptime);
4780
4781 ir_set_cursor_at_end(irb, ok_block);
4782
4783 Scope *var_scope;
4784 if (var_symbol) {
4785 IrInstruction *var_type = nullptr;
4786 bool is_shadowable = false;
4787 VariableTableEntry *var = ir_create_var(irb, node, scope,
4788 var_symbol, var_is_const, var_is_const, is_shadowable, is_comptime);
4789
4790 IrInstruction *var_ptr_value = ir_build_unwrap_err_payload(irb, scope, node, err_val_ptr, false);
4791 IrInstruction *var_value = var_is_ptr ? var_ptr_value : ir_build_load_ptr(irb, scope, node, var_ptr_value);
4792 ir_build_var_decl(irb, scope, node, var, var_type, var_value);
4793 var_scope = var->child_scope;
4794 } else {
4795 var_scope = scope;
4796 }
4797 IrInstruction *then_expr_result = ir_gen_node(irb, then_node, var_scope);
4798 if (then_expr_result == irb->codegen->invalid_instruction)
4799 return then_expr_result;
4800 IrBasicBlock *after_then_block = irb->current_basic_block;
4801 if (!instr_is_unreachable(then_expr_result))
4802 ir_mark_gen(ir_build_br(irb, scope, node, endif_block, is_comptime));
4803
4804 ir_set_cursor_at_end(irb, else_block);
4805
4806 IrInstruction *else_expr_result;
4807 if (else_node) {
4808 Scope *err_var_scope;
4809 if (err_symbol) {
4810 IrInstruction *var_type = nullptr;
4811 bool is_shadowable = false;
4812 bool is_const = true;
4813 VariableTableEntry *var = ir_create_var(irb, node, scope,
4814 err_symbol, is_const, is_const, is_shadowable, is_comptime);
4815
4816 IrInstruction *var_value = ir_build_unwrap_err_code(irb, scope, node, err_val_ptr);
4817 ir_build_var_decl(irb, scope, node, var, var_type, var_value);
4818 err_var_scope = var->child_scope;
4819 } else {
4820 err_var_scope = scope;
4821 }
4822 else_expr_result = ir_gen_node(irb, else_node, err_var_scope);
4823 if (else_expr_result == irb->codegen->invalid_instruction)
4824 return else_expr_result;
4825 } else {
4826 else_expr_result = ir_build_const_void(irb, scope, node);
4827 }
4828 IrBasicBlock *after_else_block = irb->current_basic_block;
4829 if (!instr_is_unreachable(else_expr_result))
4830 ir_mark_gen(ir_build_br(irb, scope, node, endif_block, is_comptime));
4831
4832 ir_set_cursor_at_end(irb, endif_block);
4833 IrInstruction **incoming_values = allocate<IrInstruction *>(2);
4834 incoming_values[0] = then_expr_result;
4835 incoming_values[1] = else_expr_result;
4836 IrBasicBlock **incoming_blocks = allocate<IrBasicBlock *>(2);
4837 incoming_blocks[0] = after_then_block;
4838 incoming_blocks[1] = after_else_block;
4839
4840 return ir_build_phi(irb, scope, node, 2, incoming_blocks, incoming_values);
4841}
4842
4751static bool ir_gen_switch_prong_expr(IrBuilder *irb, Scope *scope, AstNode *switch_node, AstNode *prong_node,4843static bool ir_gen_switch_prong_expr(IrBuilder *irb, Scope *scope, AstNode *switch_node, AstNode *prong_node,
4752 IrBasicBlock *end_block, IrInstruction *is_comptime, IrInstruction *target_value_ptr, IrInstruction *prong_value,4844 IrBasicBlock *end_block, IrInstruction *is_comptime, IrInstruction *target_value_ptr, IrInstruction *prong_value,
4753 ZigList<IrBasicBlock *> *incoming_blocks, ZigList<IrInstruction *> *incoming_values)4845 ZigList<IrBasicBlock *> *incoming_blocks, ZigList<IrInstruction *> *incoming_values)
...@@ -5291,6 +5383,8 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop...@@ -5291,6 +5383,8 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop
5291 return ir_lval_wrap(irb, scope, ir_gen_var_literal(irb, scope, node), lval);5383 return ir_lval_wrap(irb, scope, ir_gen_var_literal(irb, scope, node), lval);
5292 case NodeTypeIfVarExpr:5384 case NodeTypeIfVarExpr:
5293 return ir_lval_wrap(irb, scope, ir_gen_if_var_expr(irb, scope, node), lval);5385 return ir_lval_wrap(irb, scope, ir_gen_if_var_expr(irb, scope, node), lval);
5386 case NodeTypeTryExpr:
5387 return ir_lval_wrap(irb, scope, ir_gen_try_expr(irb, scope, node), lval);
5294 case NodeTypeSwitchExpr:5388 case NodeTypeSwitchExpr:
5295 return ir_lval_wrap(irb, scope, ir_gen_switch_expr(irb, scope, node), lval);5389 return ir_lval_wrap(irb, scope, ir_gen_switch_expr(irb, scope, node), lval);
5296 case NodeTypeGoto:5390 case NodeTypeGoto:
src/parser.cpp+75-1
...@@ -623,6 +623,71 @@ static AstNode *ast_parse_comptime_expr(ParseContext *pc, size_t *token_index, b...@@ -623,6 +623,71 @@ static AstNode *ast_parse_comptime_expr(ParseContext *pc, size_t *token_index, b
623 return node;623 return node;
624}624}
625625
626/*
627TryExpression = "try" "(" ("const" | "var") option("*") Symbol "=" Expression ")" Expression option("else" option("|" Symbol "|") Expression)
628*/
629static AstNode *ast_parse_try_expr(ParseContext *pc, size_t *token_index, bool mandatory) {
630 Token *try_token = &pc->tokens->at(*token_index);
631 if (try_token->id == TokenIdKeywordTry) {
632 *token_index += 1;
633 } else if (mandatory) {
634 ast_expect_token(pc, try_token, TokenIdKeywordTry);
635 zig_unreachable();
636 } else {
637 return nullptr;
638 }
639
640 AstNode *node = ast_create_node(pc, NodeTypeTryExpr, try_token);
641
642 ast_eat_token(pc, token_index, TokenIdLParen);
643
644 Token *var_token = &pc->tokens->at(*token_index);
645 if (var_token->id == TokenIdKeywordVar) {
646 node->data.try_expr.var_is_const = false;
647 *token_index += 1;
648 } else if (var_token->id == TokenIdKeywordConst) {
649 node->data.try_expr.var_is_const = true;
650 *token_index += 1;
651 } else {
652 ast_invalid_token_error(pc, var_token);
653 }
654
655 Token *star_token = &pc->tokens->at(*token_index);
656 if (star_token->id == TokenIdStar) {
657 node->data.try_expr.var_is_ptr = true;
658 *token_index += 1;
659 }
660
661 Token *var_name_tok = ast_eat_token(pc, token_index, TokenIdSymbol);
662 node->data.try_expr.var_symbol = token_buf(var_name_tok);
663
664 ast_eat_token(pc, token_index, TokenIdEq);
665
666 node->data.try_expr.target_node = ast_parse_expression(pc, token_index, true);
667
668 ast_eat_token(pc, token_index, TokenIdRParen);
669
670 node->data.try_expr.then_node = ast_parse_expression(pc, token_index, true);
671
672 Token *else_token = &pc->tokens->at(*token_index);
673 if (else_token->id != TokenIdKeywordElse)
674 return node;
675
676 *token_index += 1;
677 Token *open_bar_tok = &pc->tokens->at(*token_index);
678 if (open_bar_tok->id == TokenIdBinOr) {
679 *token_index += 1;
680
681 Token *err_name_tok = ast_eat_token(pc, token_index, TokenIdSymbol);
682 node->data.try_expr.err_symbol = token_buf(err_name_tok);
683
684 ast_eat_token(pc, token_index, TokenIdBinOr);
685 }
686
687 node->data.try_expr.else_node = ast_parse_expression(pc, token_index, true);
688 return node;
689}
690
626/*691/*
627PrimaryExpression = Number | String | CharLiteral | KeywordLiteral | GroupedExpression | GotoExpression | BlockExpression | Symbol | ("@" Symbol FnCallExpression) | ArrayType | (option("extern") FnProto) | AsmExpression | ("error" "." Symbol) | ContainerDecl692PrimaryExpression = Number | String | CharLiteral | KeywordLiteral | GroupedExpression | GotoExpression | BlockExpression | Symbol | ("@" Symbol FnCallExpression) | ArrayType | (option("extern") FnProto) | AsmExpression | ("error" "." Symbol) | ContainerDecl
628KeywordLiteral = "true" | "false" | "null" | "break" | "continue" | "undefined" | "error" | "type" | "this"693KeywordLiteral = "true" | "false" | "null" | "break" | "continue" | "undefined" | "error" | "type" | "this"
...@@ -1775,7 +1840,7 @@ static AstNode *ast_parse_switch_expr(ParseContext *pc, size_t *token_index, boo...@@ -1775,7 +1840,7 @@ static AstNode *ast_parse_switch_expr(ParseContext *pc, size_t *token_index, boo
1775}1840}
17761841
1777/*1842/*
1778BlockExpression = IfExpression | Block | WhileExpression | ForExpression | SwitchExpression | CompTimeExpression1843BlockExpression = IfExpression | Block | WhileExpression | ForExpression | SwitchExpression | CompTimeExpression | TryExpression
1779*/1844*/
1780static AstNode *ast_parse_block_expr(ParseContext *pc, size_t *token_index, bool mandatory) {1845static AstNode *ast_parse_block_expr(ParseContext *pc, size_t *token_index, bool mandatory) {
1781 Token *token = &pc->tokens->at(*token_index);1846 Token *token = &pc->tokens->at(*token_index);
...@@ -1804,6 +1869,10 @@ static AstNode *ast_parse_block_expr(ParseContext *pc, size_t *token_index, bool...@@ -1804,6 +1869,10 @@ static AstNode *ast_parse_block_expr(ParseContext *pc, size_t *token_index, bool
1804 if (comptime_node)1869 if (comptime_node)
1805 return comptime_node;1870 return comptime_node;
18061871
1872 AstNode *try_node = ast_parse_try_expr(pc, token_index, false);
1873 if (try_node)
1874 return try_node;
1875
1807 if (mandatory)1876 if (mandatory)
1808 ast_invalid_token_error(pc, token);1877 ast_invalid_token_error(pc, token);
18091878
...@@ -2555,6 +2624,11 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont...@@ -2555,6 +2624,11 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont
2555 visit_field(&node->data.if_var_expr.then_block, visit, context);2624 visit_field(&node->data.if_var_expr.then_block, visit, context);
2556 visit_field(&node->data.if_var_expr.else_node, visit, context);2625 visit_field(&node->data.if_var_expr.else_node, visit, context);
2557 break;2626 break;
2627 case NodeTypeTryExpr:
2628 visit_field(&node->data.try_expr.target_node, visit, context);
2629 visit_field(&node->data.try_expr.then_node, visit, context);
2630 visit_field(&node->data.try_expr.else_node, visit, context);
2631 break;
2558 case NodeTypeWhileExpr:2632 case NodeTypeWhileExpr:
2559 visit_field(&node->data.while_expr.condition, visit, context);2633 visit_field(&node->data.while_expr.condition, visit, context);
2560 visit_field(&node->data.while_expr.body, visit, context);2634 visit_field(&node->data.while_expr.body, visit, context);
src/tokenizer.cpp+86-84
...@@ -134,6 +134,7 @@ static const struct ZigKeyword zig_keywords[] = {...@@ -134,6 +134,7 @@ static const struct ZigKeyword zig_keywords[] = {
134 {"switch", TokenIdKeywordSwitch},134 {"switch", TokenIdKeywordSwitch},
135 {"this", TokenIdKeywordThis},135 {"this", TokenIdKeywordThis},
136 {"true", TokenIdKeywordTrue},136 {"true", TokenIdKeywordTrue},
137 {"try", TokenIdKeywordTry},
137 {"type", TokenIdKeywordType},138 {"type", TokenIdKeywordType},
138 {"undefined", TokenIdKeywordUndefined},139 {"undefined", TokenIdKeywordUndefined},
139 {"union", TokenIdKeywordUnion},140 {"union", TokenIdKeywordUnion},
...@@ -1444,108 +1445,109 @@ void tokenize(Buf *buf, Tokenization *out) {...@@ -1444,108 +1445,109 @@ void tokenize(Buf *buf, Tokenization *out) {
14441445
1445const char * token_name(TokenId id) {1446const char * token_name(TokenId id) {
1446 switch (id) {1447 switch (id) {
1447 case TokenIdEof: return "EOF";1448 case TokenIdAmpersand: return "&";
1448 case TokenIdSymbol: return "Symbol";
1449 case TokenIdKeywordFn: return "fn";
1450 case TokenIdKeywordConst: return "const";
1451 case TokenIdKeywordVar: return "var";
1452 case TokenIdKeywordReturn: return "return";
1453 case TokenIdKeywordExtern: return "extern";
1454 case TokenIdKeywordPub: return "pub";
1455 case TokenIdKeywordExport: return "export";
1456 case TokenIdKeywordUse: return "use";
1457 case TokenIdKeywordTrue: return "true";
1458 case TokenIdKeywordFalse: return "false";
1459 case TokenIdKeywordIf: return "if";
1460 case TokenIdKeywordElse: return "else";
1461 case TokenIdKeywordGoto: return "goto";
1462 case TokenIdKeywordVolatile: return "volatile";
1463 case TokenIdKeywordAsm: return "asm";
1464 case TokenIdKeywordStruct: return "struct";
1465 case TokenIdKeywordEnum: return "enum";
1466 case TokenIdKeywordUnion: return "union";
1467 case TokenIdKeywordWhile: return "while";
1468 case TokenIdKeywordFor: return "for";
1469 case TokenIdKeywordContinue: return "continue";
1470 case TokenIdKeywordBreak: return "break";
1471 case TokenIdKeywordNull: return "null";
1472 case TokenIdKeywordNoAlias: return "noalias";
1473 case TokenIdKeywordSwitch: return "switch";
1474 case TokenIdKeywordUndefined: return "undefined";
1475 case TokenIdKeywordThis: return "this";
1476 case TokenIdKeywordError: return "error";
1477 case TokenIdKeywordType: return "type";
1478 case TokenIdKeywordInline: return "inline";
1479 case TokenIdKeywordCompTime: return "comptime";
1480 case TokenIdKeywordDefer: return "defer";
1481 case TokenIdKeywordColdCC: return "coldcc";
1482 case TokenIdKeywordNakedCC: return "nakedcc";
1483 case TokenIdLParen: return "(";
1484 case TokenIdRParen: return ")";
1485 case TokenIdComma: return ",";
1486 case TokenIdStar: return "*";
1487 case TokenIdStarStar: return "**";
1488 case TokenIdLBrace: return "{";
1489 case TokenIdRBrace: return "}";
1490 case TokenIdLBracket: return "[";
1491 case TokenIdRBracket: return "]";
1492 case TokenIdStringLiteral: return "StringLiteral";
1493 case TokenIdCharLiteral: return "CharLiteral";
1494 case TokenIdSemicolon: return ";";
1495 case TokenIdNumberLiteral: return "NumberLiteral";
1496 case TokenIdPlus: return "+";
1497 case TokenIdPlusPlus: return "++";
1498 case TokenIdColon: return ":";
1499 case TokenIdArrow: return "->";1449 case TokenIdArrow: return "->";
1500 case TokenIdFatArrow: return "=>";1450 case TokenIdAtSign: return "@";
1501 case TokenIdDash: return "-";1451 case TokenIdBang: return "!";
1502 case TokenIdNumberSign: return "#";
1503 case TokenIdBinOr: return "|";1452 case TokenIdBinOr: return "|";
1504 case TokenIdAmpersand: return "&";
1505 case TokenIdBinXor: return "^";1453 case TokenIdBinXor: return "^";
1506 case TokenIdBoolOr: return "||";1454 case TokenIdBitAndEq: return "&=";
1507 case TokenIdBoolAnd: return "&&";1455 case TokenIdBitOrEq: return "|=";
1508 case TokenIdEq: return "=";1456 case TokenIdBitShiftLeft: return "<<";
1509 case TokenIdTimesEq: return "*=";
1510 case TokenIdDivEq: return "/=";
1511 case TokenIdModEq: return "%=";
1512 case TokenIdPlusEq: return "+=";
1513 case TokenIdMinusEq: return "-=";
1514 case TokenIdBitShiftLeftEq: return "<<=";1457 case TokenIdBitShiftLeftEq: return "<<=";
1458 case TokenIdBitShiftLeftPercent: return "<<%";
1459 case TokenIdBitShiftLeftPercentEq: return "<<%=";
1460 case TokenIdBitShiftRight: return ">>";
1515 case TokenIdBitShiftRightEq: return ">>=";1461 case TokenIdBitShiftRightEq: return ">>=";
1516 case TokenIdBitAndEq: return "&=";
1517 case TokenIdBitXorEq: return "^=";1462 case TokenIdBitXorEq: return "^=";
1518 case TokenIdBitOrEq: return "|=";1463 case TokenIdBoolAnd: return "&&";
1519 case TokenIdBoolAndEq: return "&&=";1464 case TokenIdBoolAndEq: return "&&=";
1465 case TokenIdBoolOr: return "||";
1520 case TokenIdBoolOrEq: return "||=";1466 case TokenIdBoolOrEq: return "||=";
1521 case TokenIdBang: return "!";1467 case TokenIdCharLiteral: return "CharLiteral";
1522 case TokenIdTilde: return "~";
1523 case TokenIdCmpEq: return "==";1468 case TokenIdCmpEq: return "==";
1524 case TokenIdCmpNotEq: return "!=";1469 case TokenIdCmpGreaterOrEq: return ">=";
1525 case TokenIdCmpLessThan: return "<";
1526 case TokenIdCmpGreaterThan: return ">";1470 case TokenIdCmpGreaterThan: return ">";
1527 case TokenIdCmpLessOrEq: return "<=";1471 case TokenIdCmpLessOrEq: return "<=";
1528 case TokenIdCmpGreaterOrEq: return ">=";1472 case TokenIdCmpLessThan: return "<";
1529 case TokenIdBitShiftLeft: return "<<";1473 case TokenIdCmpNotEq: return "!=";
1530 case TokenIdBitShiftRight: return ">>";1474 case TokenIdColon: return ":";
1531 case TokenIdSlash: return "/";1475 case TokenIdComma: return ",";
1532 case TokenIdPercent: return "%";1476 case TokenIdDash: return "-";
1533 case TokenIdPercentPercent: return "%%";1477 case TokenIdDivEq: return "/=";
1534 case TokenIdDot: return ".";1478 case TokenIdDot: return ".";
1479 case TokenIdDoubleQuestion: return "??";
1535 case TokenIdEllipsis: return "...";1480 case TokenIdEllipsis: return "...";
1481 case TokenIdEof: return "EOF";
1482 case TokenIdEq: return "=";
1483 case TokenIdFatArrow: return "=>";
1484 case TokenIdKeywordAsm: return "asm";
1485 case TokenIdKeywordBreak: return "break";
1486 case TokenIdKeywordColdCC: return "coldcc";
1487 case TokenIdKeywordCompTime: return "comptime";
1488 case TokenIdKeywordConst: return "const";
1489 case TokenIdKeywordContinue: return "continue";
1490 case TokenIdKeywordDefer: return "defer";
1491 case TokenIdKeywordElse: return "else";
1492 case TokenIdKeywordEnum: return "enum";
1493 case TokenIdKeywordError: return "error";
1494 case TokenIdKeywordExport: return "export";
1495 case TokenIdKeywordExtern: return "extern";
1496 case TokenIdKeywordFalse: return "false";
1497 case TokenIdKeywordFn: return "fn";
1498 case TokenIdKeywordFor: return "for";
1499 case TokenIdKeywordGoto: return "goto";
1500 case TokenIdKeywordIf: return "if";
1501 case TokenIdKeywordInline: return "inline";
1502 case TokenIdKeywordNakedCC: return "nakedcc";
1503 case TokenIdKeywordNoAlias: return "noalias";
1504 case TokenIdKeywordNull: return "null";
1505 case TokenIdKeywordPub: return "pub";
1506 case TokenIdKeywordReturn: return "return";
1507 case TokenIdKeywordStruct: return "struct";
1508 case TokenIdKeywordSwitch: return "switch";
1509 case TokenIdKeywordThis: return "this";
1510 case TokenIdKeywordTrue: return "true";
1511 case TokenIdKeywordTry: return "try";
1512 case TokenIdKeywordType: return "type";
1513 case TokenIdKeywordUndefined: return "undefined";
1514 case TokenIdKeywordUnion: return "union";
1515 case TokenIdKeywordUse: return "use";
1516 case TokenIdKeywordVar: return "var";
1517 case TokenIdKeywordVolatile: return "volatile";
1518 case TokenIdKeywordWhile: return "while";
1519 case TokenIdLBrace: return "{";
1520 case TokenIdLBracket: return "[";
1521 case TokenIdLParen: return "(";
1536 case TokenIdMaybe: return "?";1522 case TokenIdMaybe: return "?";
1537 case TokenIdDoubleQuestion: return "??";
1538 case TokenIdMaybeAssign: return "?=";1523 case TokenIdMaybeAssign: return "?=";
1539 case TokenIdAtSign: return "@";1524 case TokenIdMinusEq: return "-=";
1525 case TokenIdMinusPercent: return "-%";
1526 case TokenIdMinusPercentEq: return "-%=";
1527 case TokenIdModEq: return "%=";
1528 case TokenIdNumberLiteral: return "NumberLiteral";
1529 case TokenIdNumberSign: return "#";
1530 case TokenIdPercent: return "%";
1540 case TokenIdPercentDot: return "%.";1531 case TokenIdPercentDot: return "%.";
1541 case TokenIdTimesPercent: return "*%";1532 case TokenIdPercentPercent: return "%%";
1542 case TokenIdTimesPercentEq: return "*%=";1533 case TokenIdPlus: return "+";
1534 case TokenIdPlusEq: return "+=";
1543 case TokenIdPlusPercent: return "+%";1535 case TokenIdPlusPercent: return "+%";
1544 case TokenIdPlusPercentEq: return "+%=";1536 case TokenIdPlusPercentEq: return "+%=";
1545 case TokenIdMinusPercent: return "-%";1537 case TokenIdPlusPlus: return "++";
1546 case TokenIdMinusPercentEq: return "-%=";1538 case TokenIdRBrace: return "}";
1547 case TokenIdBitShiftLeftPercent: return "<<%";1539 case TokenIdRBracket: return "]";
1548 case TokenIdBitShiftLeftPercentEq: return "<<%=";1540 case TokenIdRParen: return ")";
1541 case TokenIdSemicolon: return ";";
1542 case TokenIdSlash: return "/";
1543 case TokenIdStar: return "*";
1544 case TokenIdStarStar: return "**";
1545 case TokenIdStringLiteral: return "StringLiteral";
1546 case TokenIdSymbol: return "Symbol";
1547 case TokenIdTilde: return "~";
1548 case TokenIdTimesEq: return "*=";
1549 case TokenIdTimesPercent: return "*%";
1550 case TokenIdTimesPercentEq: return "*%=";
1549 }1551 }
1550 return "(invalid token)";1552 return "(invalid token)";
1551}1553}
src/tokenizer.hpp+1
...@@ -25,6 +25,7 @@ enum TokenId {...@@ -25,6 +25,7 @@ enum TokenId {
25 TokenIdKeywordTrue,25 TokenIdKeywordTrue,
26 TokenIdKeywordFalse,26 TokenIdKeywordFalse,
27 TokenIdKeywordIf,27 TokenIdKeywordIf,
28 TokenIdKeywordTry,
28 TokenIdKeywordElse,29 TokenIdKeywordElse,
29 TokenIdKeywordGoto,30 TokenIdKeywordGoto,
30 TokenIdKeywordAsm,31 TokenIdKeywordAsm,
std/debug.zig+2-2
...@@ -9,8 +9,8 @@ error MissingDebugInfo;...@@ -9,8 +9,8 @@ error MissingDebugInfo;
9error InvalidDebugInfo;9error InvalidDebugInfo;
10error UnsupportedDebugInfo;10error UnsupportedDebugInfo;
1111
12pub fn assert(b: bool) {12pub fn assert(ok: bool) {
13 if (!b) @unreachable()13 if (!ok) @unreachable()
14}14}
1515
16pub fn printStackTrace() -> %void {16pub fn printStackTrace() -> %void {
test/cases/try.zig created+33
...@@ -0,0 +1,33 @@
1const assert = @import("std").debug.assert;
2
3fn tryOnErrorUnion() {
4 @setFnTest(this);
5
6 const x = try (const val = returnsTen()) {
7 val + 1
8 } else |err| switch (err) {
9 error.ItBroke, error.NoMem => 1,
10 error.CrappedOut => i32(2),
11 };
12 assert(x == 11);
13}
14
15fn tryOnErrorUnionComptime() {
16 @setFnTest(this);
17
18 comptime {
19 const x = try (const val = returnsTen()) {
20 val + 1
21 } else |err| switch (err) {
22 error.ItBroke, error.NoMem => 1,
23 error.CrappedOut => i32(2),
24 };
25 assert(x == 11);
26 }
27}
28error ItBroke;
29error NoMem;
30error CrappedOut;
31fn returnsTen() -> %i32 {
32 10
33}
test/self_hosted.zig+1
...@@ -28,6 +28,7 @@ const test_switch = @import("cases/switch.zig");...@@ -28,6 +28,7 @@ const test_switch = @import("cases/switch.zig");
28const test_switch_prong_err_enum = @import("cases/switch_prong_err_enum.zig");28const test_switch_prong_err_enum = @import("cases/switch_prong_err_enum.zig");
29const test_switch_prong_implicit_cast = @import("cases/switch_prong_implicit_cast.zig");29const test_switch_prong_implicit_cast = @import("cases/switch_prong_implicit_cast.zig");
30const test_this = @import("cases/this.zig");30const test_this = @import("cases/this.zig");
31const test_try = @import("cases/try.zig");
31const test_undefined = @import("cases/undefined.zig");32const test_undefined = @import("cases/undefined.zig");
32const test_var_args = @import("cases/var_args.zig");33const test_var_args = @import("cases/var_args.zig");
33const test_while = @import("cases/while.zig");34const test_while = @import("cases/while.zig");