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
6969
7070AssignmentOperator = "=" | "*=" | "/=" | "%=" | "+=" | "-=" | "<<=" | ">>=" | "&=" | "^=" | "|=" | "&&=" | "||=" | "*%=" | "+%=" | "-%=" | "<<%="
7171
72BlockExpression = IfExpression | Block | WhileExpression | ForExpression | SwitchExpression | CompTimeExpression
72BlockExpression = IfExpression | Block | WhileExpression | ForExpression | SwitchExpression | CompTimeExpression | TryExpression
7373
7474CompTimeExpression = option("comptime") Expression
7575
......@@ -93,6 +93,8 @@ IfExpression = IfVarExpression | IfBoolExpression
9393
9494IfBoolExpression = "if" "(" Expression ")" Expression option(Else)
9595
96TryExpression = "try" "(" ("const" | "var") option("*") Symbol "=" Expression ")" Expression option("else" option("|" Symbol "|") Expression)
97
9698IfVarExpression = "if" "(" ("const" | "var") option("*") Symbol option(":" TypeExpr) "?=" Expression ")" Expression Option(Else)
9799
98100Else = "else" Expression
doc/vim/syntax/zig.vim+1-1
......@@ -11,7 +11,7 @@ let b:current_syntax = "zig"
1111syn keyword zigStorage const var extern export pub noalias inline comptime nakedcc coldcc
1212syn keyword zigStructure struct enum union
1313syn keyword zigStatement goto break return continue asm defer
14syn keyword zigConditional if else switch
14syn keyword zigConditional if else switch try
1515syn keyword zigRepeat while for
1616
1717syn keyword zigConstant null undefined zeroes this
src/all_types.hpp+12
......@@ -299,6 +299,7 @@ enum NodeType {
299299 NodeTypeErrorType,
300300 NodeTypeTypeLiteral,
301301 NodeTypeVarLiteral,
302 NodeTypeTryExpr,
302303};
303304
304305struct AstNodeRoot {
......@@ -511,6 +512,16 @@ struct AstNodeIfBoolExpr {
511512 AstNode *else_node; // null, block node, or other if expr node
512513};
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
514525struct AstNodeIfVarExpr {
515526 AstNodeVariableDeclaration var_decl;
516527 AstNode *then_block;
......@@ -721,6 +732,7 @@ struct AstNode {
721732 AstNodeUse use;
722733 AstNodeIfBoolExpr if_bool_expr;
723734 AstNodeIfVarExpr if_var_expr;
735 AstNodeTryExpr try_expr;
724736 AstNodeWhileExpr while_expr;
725737 AstNodeForExpr for_expr;
726738 AstNodeSwitchExpr switch_expr;
src/analyze.cpp+1
......@@ -1769,6 +1769,7 @@ void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node) {
17691769 case NodeTypeErrorType:
17701770 case NodeTypeTypeLiteral:
17711771 case NodeTypeVarLiteral:
1772 case NodeTypeTryExpr:
17721773 zig_unreachable();
17731774 }
17741775}
src/ast_render.cpp+21
......@@ -223,6 +223,8 @@ static const char *node_type_str(NodeType node_type) {
223223 return "TypeLiteral";
224224 case NodeTypeVarLiteral:
225225 return "VarLiteral";
226 case NodeTypeTryExpr:
227 return "TryExpr";
226228 }
227229 zig_unreachable();
228230}
......@@ -769,6 +771,25 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {
769771 }
770772 break;
771773 }
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 }
772793 case NodeTypeSwitchExpr:
773794 {
774795 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 *
47484748 return ir_build_phi(irb, scope, node, 2, incoming_blocks, incoming_values);
47494749}
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
47514843static bool ir_gen_switch_prong_expr(IrBuilder *irb, Scope *scope, AstNode *switch_node, AstNode *prong_node,
47524844 IrBasicBlock *end_block, IrInstruction *is_comptime, IrInstruction *target_value_ptr, IrInstruction *prong_value,
47534845 ZigList<IrBasicBlock *> *incoming_blocks, ZigList<IrInstruction *> *incoming_values)
......@@ -5291,6 +5383,8 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop
52915383 return ir_lval_wrap(irb, scope, ir_gen_var_literal(irb, scope, node), lval);
52925384 case NodeTypeIfVarExpr:
52935385 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);
52945388 case NodeTypeSwitchExpr:
52955389 return ir_lval_wrap(irb, scope, ir_gen_switch_expr(irb, scope, node), lval);
52965390 case NodeTypeGoto:
src/parser.cpp+75-1
......@@ -623,6 +623,71 @@ static AstNode *ast_parse_comptime_expr(ParseContext *pc, size_t *token_index, b
623623 return node;
624624}
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
626691/*
627692PrimaryExpression = Number | String | CharLiteral | KeywordLiteral | GroupedExpression | GotoExpression | BlockExpression | Symbol | ("@" Symbol FnCallExpression) | ArrayType | (option("extern") FnProto) | AsmExpression | ("error" "." Symbol) | ContainerDecl
628693KeywordLiteral = "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
17751840}
17761841
17771842/*
1778BlockExpression = IfExpression | Block | WhileExpression | ForExpression | SwitchExpression | CompTimeExpression
1843BlockExpression = IfExpression | Block | WhileExpression | ForExpression | SwitchExpression | CompTimeExpression | TryExpression
17791844*/
17801845static AstNode *ast_parse_block_expr(ParseContext *pc, size_t *token_index, bool mandatory) {
17811846 Token *token = &pc->tokens->at(*token_index);
......@@ -1804,6 +1869,10 @@ static AstNode *ast_parse_block_expr(ParseContext *pc, size_t *token_index, bool
18041869 if (comptime_node)
18051870 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
18071876 if (mandatory)
18081877 ast_invalid_token_error(pc, token);
18091878
......@@ -2555,6 +2624,11 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont
25552624 visit_field(&node->data.if_var_expr.then_block, visit, context);
25562625 visit_field(&node->data.if_var_expr.else_node, visit, context);
25572626 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;
25582632 case NodeTypeWhileExpr:
25592633 visit_field(&node->data.while_expr.condition, visit, context);
25602634 visit_field(&node->data.while_expr.body, visit, context);
src/tokenizer.cpp+86-84
......@@ -134,6 +134,7 @@ static const struct ZigKeyword zig_keywords[] = {
134134 {"switch", TokenIdKeywordSwitch},
135135 {"this", TokenIdKeywordThis},
136136 {"true", TokenIdKeywordTrue},
137 {"try", TokenIdKeywordTry},
137138 {"type", TokenIdKeywordType},
138139 {"undefined", TokenIdKeywordUndefined},
139140 {"union", TokenIdKeywordUnion},
......@@ -1444,108 +1445,109 @@ void tokenize(Buf *buf, Tokenization *out) {
14441445
14451446const char * token_name(TokenId id) {
14461447 switch (id) {
1447 case TokenIdEof: return "EOF";
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 ":";
1448 case TokenIdAmpersand: return "&";
14991449 case TokenIdArrow: return "->";
1500 case TokenIdFatArrow: return "=>";
1501 case TokenIdDash: return "-";
1502 case TokenIdNumberSign: return "#";
1450 case TokenIdAtSign: return "@";
1451 case TokenIdBang: return "!";
15031452 case TokenIdBinOr: return "|";
1504 case TokenIdAmpersand: return "&";
15051453 case TokenIdBinXor: return "^";
1506 case TokenIdBoolOr: return "||";
1507 case TokenIdBoolAnd: return "&&";
1508 case TokenIdEq: return "=";
1509 case TokenIdTimesEq: return "*=";
1510 case TokenIdDivEq: return "/=";
1511 case TokenIdModEq: return "%=";
1512 case TokenIdPlusEq: return "+=";
1513 case TokenIdMinusEq: return "-=";
1454 case TokenIdBitAndEq: return "&=";
1455 case TokenIdBitOrEq: return "|=";
1456 case TokenIdBitShiftLeft: return "<<";
15141457 case TokenIdBitShiftLeftEq: return "<<=";
1458 case TokenIdBitShiftLeftPercent: return "<<%";
1459 case TokenIdBitShiftLeftPercentEq: return "<<%=";
1460 case TokenIdBitShiftRight: return ">>";
15151461 case TokenIdBitShiftRightEq: return ">>=";
1516 case TokenIdBitAndEq: return "&=";
15171462 case TokenIdBitXorEq: return "^=";
1518 case TokenIdBitOrEq: return "|=";
1463 case TokenIdBoolAnd: return "&&";
15191464 case TokenIdBoolAndEq: return "&&=";
1465 case TokenIdBoolOr: return "||";
15201466 case TokenIdBoolOrEq: return "||=";
1521 case TokenIdBang: return "!";
1522 case TokenIdTilde: return "~";
1467 case TokenIdCharLiteral: return "CharLiteral";
15231468 case TokenIdCmpEq: return "==";
1524 case TokenIdCmpNotEq: return "!=";
1525 case TokenIdCmpLessThan: return "<";
1469 case TokenIdCmpGreaterOrEq: return ">=";
15261470 case TokenIdCmpGreaterThan: return ">";
15271471 case TokenIdCmpLessOrEq: return "<=";
1528 case TokenIdCmpGreaterOrEq: return ">=";
1529 case TokenIdBitShiftLeft: return "<<";
1530 case TokenIdBitShiftRight: return ">>";
1531 case TokenIdSlash: return "/";
1532 case TokenIdPercent: return "%";
1533 case TokenIdPercentPercent: return "%%";
1472 case TokenIdCmpLessThan: return "<";
1473 case TokenIdCmpNotEq: return "!=";
1474 case TokenIdColon: return ":";
1475 case TokenIdComma: return ",";
1476 case TokenIdDash: return "-";
1477 case TokenIdDivEq: return "/=";
15341478 case TokenIdDot: return ".";
1479 case TokenIdDoubleQuestion: return "??";
15351480 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 "(";
15361522 case TokenIdMaybe: return "?";
1537 case TokenIdDoubleQuestion: return "??";
15381523 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 "%";
15401531 case TokenIdPercentDot: return "%.";
1541 case TokenIdTimesPercent: return "*%";
1542 case TokenIdTimesPercentEq: return "*%=";
1532 case TokenIdPercentPercent: return "%%";
1533 case TokenIdPlus: return "+";
1534 case TokenIdPlusEq: return "+=";
15431535 case TokenIdPlusPercent: return "+%";
15441536 case TokenIdPlusPercentEq: return "+%=";
1545 case TokenIdMinusPercent: return "-%";
1546 case TokenIdMinusPercentEq: return "-%=";
1547 case TokenIdBitShiftLeftPercent: return "<<%";
1548 case TokenIdBitShiftLeftPercentEq: return "<<%=";
1537 case TokenIdPlusPlus: return "++";
1538 case TokenIdRBrace: return "}";
1539 case TokenIdRBracket: 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 "*%=";
15491551 }
15501552 return "(invalid token)";
15511553}
src/tokenizer.hpp+1
......@@ -25,6 +25,7 @@ enum TokenId {
2525 TokenIdKeywordTrue,
2626 TokenIdKeywordFalse,
2727 TokenIdKeywordIf,
28 TokenIdKeywordTry,
2829 TokenIdKeywordElse,
2930 TokenIdKeywordGoto,
3031 TokenIdKeywordAsm,
std/debug.zig+2-2
......@@ -9,8 +9,8 @@ error MissingDebugInfo;
99error InvalidDebugInfo;
1010error UnsupportedDebugInfo;
1111
12pub fn assert(b: bool) {
13 if (!b) @unreachable()
12pub fn assert(ok: bool) {
13 if (!ok) @unreachable()
1414}
1515
1616pub 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");
2828const test_switch_prong_err_enum = @import("cases/switch_prong_err_enum.zig");
2929const test_switch_prong_implicit_cast = @import("cases/switch_prong_implicit_cast.zig");
3030const test_this = @import("cases/this.zig");
31const test_try = @import("cases/try.zig");
3132const test_undefined = @import("cases/undefined.zig");
3233const test_var_args = @import("cases/var_args.zig");
3334const test_while = @import("cases/while.zig");