add try expression

See #83
This commit is contained in:
Andrew Kelley 2017-02-02 17:09:27 -05:00
parent 8b1c6d8b76
commit c0b37e8514
12 changed files with 344 additions and 103 deletions

View File

@ -69,7 +69,7 @@ AssignmentExpression = UnwrapExpression AssignmentOperator UnwrapExpression | Un
AssignmentOperator = "=" | "*=" | "/=" | "%=" | "+=" | "-=" | "<<=" | ">>=" | "&=" | "^=" | "|=" | "&&=" | "||=" | "*%=" | "+%=" | "-%=" | "<<%="
BlockExpression = IfExpression | Block | WhileExpression | ForExpression | SwitchExpression | CompTimeExpression
BlockExpression = IfExpression | Block | WhileExpression | ForExpression | SwitchExpression | CompTimeExpression | TryExpression
CompTimeExpression = option("comptime") Expression
@ -93,6 +93,8 @@ IfExpression = IfVarExpression | IfBoolExpression
IfBoolExpression = "if" "(" Expression ")" Expression option(Else)
TryExpression = "try" "(" ("const" | "var") option("*") Symbol "=" Expression ")" Expression option("else" option("|" Symbol "|") Expression)
IfVarExpression = "if" "(" ("const" | "var") option("*") Symbol option(":" TypeExpr) "?=" Expression ")" Expression Option(Else)
Else = "else" Expression

View File

@ -11,7 +11,7 @@ let b:current_syntax = "zig"
syn keyword zigStorage const var extern export pub noalias inline comptime nakedcc coldcc
syn keyword zigStructure struct enum union
syn keyword zigStatement goto break return continue asm defer
syn keyword zigConditional if else switch
syn keyword zigConditional if else switch try
syn keyword zigRepeat while for
syn keyword zigConstant null undefined zeroes this

View File

@ -299,6 +299,7 @@ enum NodeType {
NodeTypeErrorType,
NodeTypeTypeLiteral,
NodeTypeVarLiteral,
NodeTypeTryExpr,
};
struct AstNodeRoot {
@ -511,6 +512,16 @@ struct AstNodeIfBoolExpr {
AstNode *else_node; // null, block node, or other if expr node
};
struct AstNodeTryExpr {
bool var_is_const;
Buf *var_symbol;
bool var_is_ptr;
AstNode *target_node;
AstNode *then_node;
AstNode *else_node;
Buf *err_symbol;
};
struct AstNodeIfVarExpr {
AstNodeVariableDeclaration var_decl;
AstNode *then_block;
@ -721,6 +732,7 @@ struct AstNode {
AstNodeUse use;
AstNodeIfBoolExpr if_bool_expr;
AstNodeIfVarExpr if_var_expr;
AstNodeTryExpr try_expr;
AstNodeWhileExpr while_expr;
AstNodeForExpr for_expr;
AstNodeSwitchExpr switch_expr;

View File

@ -1769,6 +1769,7 @@ void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node) {
case NodeTypeErrorType:
case NodeTypeTypeLiteral:
case NodeTypeVarLiteral:
case NodeTypeTryExpr:
zig_unreachable();
}
}

View File

@ -223,6 +223,8 @@ static const char *node_type_str(NodeType node_type) {
return "TypeLiteral";
case NodeTypeVarLiteral:
return "VarLiteral";
case NodeTypeTryExpr:
return "TryExpr";
}
zig_unreachable();
}
@ -769,6 +771,25 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {
}
break;
}
case NodeTypeTryExpr:
{
const char *var_str = node->data.try_expr.var_is_const ? "const" : "var";
const char *var_name = buf_ptr(node->data.try_expr.var_symbol);
const char *ptr_str = node->data.try_expr.var_is_ptr ? "*" : "";
fprintf(ar->f, "try (%s %s%s", var_str, ptr_str, var_name);
fprintf(ar->f, " = ");
render_node_grouped(ar, node->data.try_expr.target_node);
fprintf(ar->f, ") ");
render_node_grouped(ar, node->data.try_expr.then_node);
if (node->data.try_expr.else_node) {
fprintf(ar->f, " else ");
if (node->data.try_expr.err_symbol) {
fprintf(ar->f, "|%s| ", buf_ptr(node->data.try_expr.err_symbol));
}
render_node_grouped(ar, node->data.try_expr.else_node);
}
break;
}
case NodeTypeSwitchExpr:
{
AstNodeSwitchExpr *switch_expr = &node->data.switch_expr;

View File

@ -4748,6 +4748,98 @@ static IrInstruction *ir_gen_if_var_expr(IrBuilder *irb, Scope *scope, AstNode *
return ir_build_phi(irb, scope, node, 2, incoming_blocks, incoming_values);
}
static IrInstruction *ir_gen_try_expr(IrBuilder *irb, Scope *scope, AstNode *node) {
assert(node->type == NodeTypeTryExpr);
AstNode *target_node = node->data.try_expr.target_node;
AstNode *then_node = node->data.try_expr.then_node;
AstNode *else_node = node->data.try_expr.else_node;
bool var_is_ptr = node->data.try_expr.var_is_ptr;
bool var_is_const = node->data.try_expr.var_is_const;
Buf *var_symbol = node->data.try_expr.var_symbol;
Buf *err_symbol = node->data.try_expr.err_symbol;
IrInstruction *err_val_ptr = ir_gen_node_extra(irb, target_node, scope, LValPurposeAddressOf);
if (err_val_ptr == irb->codegen->invalid_instruction)
return err_val_ptr;
IrInstruction *err_val = ir_build_load_ptr(irb, scope, node, err_val_ptr);
IrInstruction *is_err = ir_build_test_err(irb, scope, node, err_val);
IrBasicBlock *ok_block = ir_build_basic_block(irb, scope, "TryOk");
IrBasicBlock *else_block = ir_build_basic_block(irb, scope, "TryElse");
IrBasicBlock *endif_block = ir_build_basic_block(irb, scope, "TryEnd");
IrInstruction *is_comptime;
if (ir_should_inline(irb->exec, scope)) {
is_comptime = ir_build_const_bool(irb, scope, node, true);
} else {
is_comptime = ir_build_test_comptime(irb, scope, node, is_err);
}
ir_build_cond_br(irb, scope, node, is_err, else_block, ok_block, is_comptime);
ir_set_cursor_at_end(irb, ok_block);
Scope *var_scope;
if (var_symbol) {
IrInstruction *var_type = nullptr;
bool is_shadowable = false;
VariableTableEntry *var = ir_create_var(irb, node, scope,
var_symbol, var_is_const, var_is_const, is_shadowable, is_comptime);
IrInstruction *var_ptr_value = ir_build_unwrap_err_payload(irb, scope, node, err_val_ptr, false);
IrInstruction *var_value = var_is_ptr ? var_ptr_value : ir_build_load_ptr(irb, scope, node, var_ptr_value);
ir_build_var_decl(irb, scope, node, var, var_type, var_value);
var_scope = var->child_scope;
} else {
var_scope = scope;
}
IrInstruction *then_expr_result = ir_gen_node(irb, then_node, var_scope);
if (then_expr_result == irb->codegen->invalid_instruction)
return then_expr_result;
IrBasicBlock *after_then_block = irb->current_basic_block;
if (!instr_is_unreachable(then_expr_result))
ir_mark_gen(ir_build_br(irb, scope, node, endif_block, is_comptime));
ir_set_cursor_at_end(irb, else_block);
IrInstruction *else_expr_result;
if (else_node) {
Scope *err_var_scope;
if (err_symbol) {
IrInstruction *var_type = nullptr;
bool is_shadowable = false;
bool is_const = true;
VariableTableEntry *var = ir_create_var(irb, node, scope,
err_symbol, is_const, is_const, is_shadowable, is_comptime);
IrInstruction *var_value = ir_build_unwrap_err_code(irb, scope, node, err_val_ptr);
ir_build_var_decl(irb, scope, node, var, var_type, var_value);
err_var_scope = var->child_scope;
} else {
err_var_scope = scope;
}
else_expr_result = ir_gen_node(irb, else_node, err_var_scope);
if (else_expr_result == irb->codegen->invalid_instruction)
return else_expr_result;
} else {
else_expr_result = ir_build_const_void(irb, scope, node);
}
IrBasicBlock *after_else_block = irb->current_basic_block;
if (!instr_is_unreachable(else_expr_result))
ir_mark_gen(ir_build_br(irb, scope, node, endif_block, is_comptime));
ir_set_cursor_at_end(irb, endif_block);
IrInstruction **incoming_values = allocate<IrInstruction *>(2);
incoming_values[0] = then_expr_result;
incoming_values[1] = else_expr_result;
IrBasicBlock **incoming_blocks = allocate<IrBasicBlock *>(2);
incoming_blocks[0] = after_then_block;
incoming_blocks[1] = after_else_block;
return ir_build_phi(irb, scope, node, 2, incoming_blocks, incoming_values);
}
static bool ir_gen_switch_prong_expr(IrBuilder *irb, Scope *scope, AstNode *switch_node, AstNode *prong_node,
IrBasicBlock *end_block, IrInstruction *is_comptime, IrInstruction *target_value_ptr, IrInstruction *prong_value,
ZigList<IrBasicBlock *> *incoming_blocks, ZigList<IrInstruction *> *incoming_values)
@ -5291,6 +5383,8 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop
return ir_lval_wrap(irb, scope, ir_gen_var_literal(irb, scope, node), lval);
case NodeTypeIfVarExpr:
return ir_lval_wrap(irb, scope, ir_gen_if_var_expr(irb, scope, node), lval);
case NodeTypeTryExpr:
return ir_lval_wrap(irb, scope, ir_gen_try_expr(irb, scope, node), lval);
case NodeTypeSwitchExpr:
return ir_lval_wrap(irb, scope, ir_gen_switch_expr(irb, scope, node), lval);
case NodeTypeGoto:

View File

@ -623,6 +623,71 @@ static AstNode *ast_parse_comptime_expr(ParseContext *pc, size_t *token_index, b
return node;
}
/*
TryExpression = "try" "(" ("const" | "var") option("*") Symbol "=" Expression ")" Expression option("else" option("|" Symbol "|") Expression)
*/
static AstNode *ast_parse_try_expr(ParseContext *pc, size_t *token_index, bool mandatory) {
Token *try_token = &pc->tokens->at(*token_index);
if (try_token->id == TokenIdKeywordTry) {
*token_index += 1;
} else if (mandatory) {
ast_expect_token(pc, try_token, TokenIdKeywordTry);
zig_unreachable();
} else {
return nullptr;
}
AstNode *node = ast_create_node(pc, NodeTypeTryExpr, try_token);
ast_eat_token(pc, token_index, TokenIdLParen);
Token *var_token = &pc->tokens->at(*token_index);
if (var_token->id == TokenIdKeywordVar) {
node->data.try_expr.var_is_const = false;
*token_index += 1;
} else if (var_token->id == TokenIdKeywordConst) {
node->data.try_expr.var_is_const = true;
*token_index += 1;
} else {
ast_invalid_token_error(pc, var_token);
}
Token *star_token = &pc->tokens->at(*token_index);
if (star_token->id == TokenIdStar) {
node->data.try_expr.var_is_ptr = true;
*token_index += 1;
}
Token *var_name_tok = ast_eat_token(pc, token_index, TokenIdSymbol);
node->data.try_expr.var_symbol = token_buf(var_name_tok);
ast_eat_token(pc, token_index, TokenIdEq);
node->data.try_expr.target_node = ast_parse_expression(pc, token_index, true);
ast_eat_token(pc, token_index, TokenIdRParen);
node->data.try_expr.then_node = ast_parse_expression(pc, token_index, true);
Token *else_token = &pc->tokens->at(*token_index);
if (else_token->id != TokenIdKeywordElse)
return node;
*token_index += 1;
Token *open_bar_tok = &pc->tokens->at(*token_index);
if (open_bar_tok->id == TokenIdBinOr) {
*token_index += 1;
Token *err_name_tok = ast_eat_token(pc, token_index, TokenIdSymbol);
node->data.try_expr.err_symbol = token_buf(err_name_tok);
ast_eat_token(pc, token_index, TokenIdBinOr);
}
node->data.try_expr.else_node = ast_parse_expression(pc, token_index, true);
return node;
}
/*
PrimaryExpression = Number | String | CharLiteral | KeywordLiteral | GroupedExpression | GotoExpression | BlockExpression | Symbol | ("@" Symbol FnCallExpression) | ArrayType | (option("extern") FnProto) | AsmExpression | ("error" "." Symbol) | ContainerDecl
KeywordLiteral = "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
}
/*
BlockExpression = IfExpression | Block | WhileExpression | ForExpression | SwitchExpression | CompTimeExpression
BlockExpression = IfExpression | Block | WhileExpression | ForExpression | SwitchExpression | CompTimeExpression | TryExpression
*/
static AstNode *ast_parse_block_expr(ParseContext *pc, size_t *token_index, bool mandatory) {
Token *token = &pc->tokens->at(*token_index);
@ -1804,6 +1869,10 @@ static AstNode *ast_parse_block_expr(ParseContext *pc, size_t *token_index, bool
if (comptime_node)
return comptime_node;
AstNode *try_node = ast_parse_try_expr(pc, token_index, false);
if (try_node)
return try_node;
if (mandatory)
ast_invalid_token_error(pc, token);
@ -2555,6 +2624,11 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont
visit_field(&node->data.if_var_expr.then_block, visit, context);
visit_field(&node->data.if_var_expr.else_node, visit, context);
break;
case NodeTypeTryExpr:
visit_field(&node->data.try_expr.target_node, visit, context);
visit_field(&node->data.try_expr.then_node, visit, context);
visit_field(&node->data.try_expr.else_node, visit, context);
break;
case NodeTypeWhileExpr:
visit_field(&node->data.while_expr.condition, visit, context);
visit_field(&node->data.while_expr.body, visit, context);

View File

@ -134,6 +134,7 @@ static const struct ZigKeyword zig_keywords[] = {
{"switch", TokenIdKeywordSwitch},
{"this", TokenIdKeywordThis},
{"true", TokenIdKeywordTrue},
{"try", TokenIdKeywordTry},
{"type", TokenIdKeywordType},
{"undefined", TokenIdKeywordUndefined},
{"union", TokenIdKeywordUnion},
@ -1444,108 +1445,109 @@ void tokenize(Buf *buf, Tokenization *out) {
const char * token_name(TokenId id) {
switch (id) {
case TokenIdEof: return "EOF";
case TokenIdSymbol: return "Symbol";
case TokenIdKeywordFn: return "fn";
case TokenIdKeywordConst: return "const";
case TokenIdKeywordVar: return "var";
case TokenIdKeywordReturn: return "return";
case TokenIdKeywordExtern: return "extern";
case TokenIdKeywordPub: return "pub";
case TokenIdKeywordExport: return "export";
case TokenIdKeywordUse: return "use";
case TokenIdKeywordTrue: return "true";
case TokenIdKeywordFalse: return "false";
case TokenIdKeywordIf: return "if";
case TokenIdKeywordElse: return "else";
case TokenIdKeywordGoto: return "goto";
case TokenIdKeywordVolatile: return "volatile";
case TokenIdKeywordAsm: return "asm";
case TokenIdKeywordStruct: return "struct";
case TokenIdKeywordEnum: return "enum";
case TokenIdKeywordUnion: return "union";
case TokenIdKeywordWhile: return "while";
case TokenIdKeywordFor: return "for";
case TokenIdKeywordContinue: return "continue";
case TokenIdKeywordBreak: return "break";
case TokenIdKeywordNull: return "null";
case TokenIdKeywordNoAlias: return "noalias";
case TokenIdKeywordSwitch: return "switch";
case TokenIdKeywordUndefined: return "undefined";
case TokenIdKeywordThis: return "this";
case TokenIdKeywordError: return "error";
case TokenIdKeywordType: return "type";
case TokenIdKeywordInline: return "inline";
case TokenIdKeywordCompTime: return "comptime";
case TokenIdKeywordDefer: return "defer";
case TokenIdKeywordColdCC: return "coldcc";
case TokenIdKeywordNakedCC: return "nakedcc";
case TokenIdLParen: return "(";
case TokenIdRParen: return ")";
case TokenIdComma: return ",";
case TokenIdStar: return "*";
case TokenIdStarStar: return "**";
case TokenIdLBrace: return "{";
case TokenIdRBrace: return "}";
case TokenIdLBracket: return "[";
case TokenIdRBracket: return "]";
case TokenIdStringLiteral: return "StringLiteral";
case TokenIdCharLiteral: return "CharLiteral";
case TokenIdSemicolon: return ";";
case TokenIdNumberLiteral: return "NumberLiteral";
case TokenIdPlus: return "+";
case TokenIdPlusPlus: return "++";
case TokenIdColon: return ":";
case TokenIdArrow: return "->";
case TokenIdFatArrow: return "=>";
case TokenIdDash: return "-";
case TokenIdNumberSign: return "#";
case TokenIdBinOr: return "|";
case TokenIdAmpersand: return "&";
case TokenIdBinXor: return "^";
case TokenIdBoolOr: return "||";
case TokenIdBoolAnd: return "&&";
case TokenIdEq: return "=";
case TokenIdTimesEq: return "*=";
case TokenIdDivEq: return "/=";
case TokenIdModEq: return "%=";
case TokenIdPlusEq: return "+=";
case TokenIdMinusEq: return "-=";
case TokenIdBitShiftLeftEq: return "<<=";
case TokenIdBitShiftRightEq: return ">>=";
case TokenIdBitAndEq: return "&=";
case TokenIdBitXorEq: return "^=";
case TokenIdBitOrEq: return "|=";
case TokenIdBoolAndEq: return "&&=";
case TokenIdBoolOrEq: return "||=";
case TokenIdBang: return "!";
case TokenIdTilde: return "~";
case TokenIdCmpEq: return "==";
case TokenIdCmpNotEq: return "!=";
case TokenIdCmpLessThan: return "<";
case TokenIdCmpGreaterThan: return ">";
case TokenIdCmpLessOrEq: return "<=";
case TokenIdCmpGreaterOrEq: return ">=";
case TokenIdBitShiftLeft: return "<<";
case TokenIdBitShiftRight: return ">>";
case TokenIdSlash: return "/";
case TokenIdPercent: return "%";
case TokenIdPercentPercent: return "%%";
case TokenIdDot: return ".";
case TokenIdEllipsis: return "...";
case TokenIdMaybe: return "?";
case TokenIdDoubleQuestion: return "??";
case TokenIdMaybeAssign: return "?=";
case TokenIdArrow: return "->";
case TokenIdAtSign: return "@";
case TokenIdPercentDot: return "%.";
case TokenIdTimesPercent: return "*%";
case TokenIdTimesPercentEq: return "*%=";
case TokenIdPlusPercent: return "+%";
case TokenIdPlusPercentEq: return "+%=";
case TokenIdMinusPercent: return "-%";
case TokenIdMinusPercentEq: return "-%=";
case TokenIdBang: return "!";
case TokenIdBinOr: return "|";
case TokenIdBinXor: return "^";
case TokenIdBitAndEq: return "&=";
case TokenIdBitOrEq: return "|=";
case TokenIdBitShiftLeft: return "<<";
case TokenIdBitShiftLeftEq: return "<<=";
case TokenIdBitShiftLeftPercent: return "<<%";
case TokenIdBitShiftLeftPercentEq: return "<<%=";
case TokenIdBitShiftRight: return ">>";
case TokenIdBitShiftRightEq: return ">>=";
case TokenIdBitXorEq: return "^=";
case TokenIdBoolAnd: return "&&";
case TokenIdBoolAndEq: return "&&=";
case TokenIdBoolOr: return "||";
case TokenIdBoolOrEq: return "||=";
case TokenIdCharLiteral: return "CharLiteral";
case TokenIdCmpEq: return "==";
case TokenIdCmpGreaterOrEq: return ">=";
case TokenIdCmpGreaterThan: return ">";
case TokenIdCmpLessOrEq: return "<=";
case TokenIdCmpLessThan: return "<";
case TokenIdCmpNotEq: return "!=";
case TokenIdColon: return ":";
case TokenIdComma: return ",";
case TokenIdDash: return "-";
case TokenIdDivEq: return "/=";
case TokenIdDot: return ".";
case TokenIdDoubleQuestion: return "??";
case TokenIdEllipsis: return "...";
case TokenIdEof: return "EOF";
case TokenIdEq: return "=";
case TokenIdFatArrow: return "=>";
case TokenIdKeywordAsm: return "asm";
case TokenIdKeywordBreak: return "break";
case TokenIdKeywordColdCC: return "coldcc";
case TokenIdKeywordCompTime: return "comptime";
case TokenIdKeywordConst: return "const";
case TokenIdKeywordContinue: return "continue";
case TokenIdKeywordDefer: return "defer";
case TokenIdKeywordElse: return "else";
case TokenIdKeywordEnum: return "enum";
case TokenIdKeywordError: return "error";
case TokenIdKeywordExport: return "export";
case TokenIdKeywordExtern: return "extern";
case TokenIdKeywordFalse: return "false";
case TokenIdKeywordFn: return "fn";
case TokenIdKeywordFor: return "for";
case TokenIdKeywordGoto: return "goto";
case TokenIdKeywordIf: return "if";
case TokenIdKeywordInline: return "inline";
case TokenIdKeywordNakedCC: return "nakedcc";
case TokenIdKeywordNoAlias: return "noalias";
case TokenIdKeywordNull: return "null";
case TokenIdKeywordPub: return "pub";
case TokenIdKeywordReturn: return "return";
case TokenIdKeywordStruct: return "struct";
case TokenIdKeywordSwitch: return "switch";
case TokenIdKeywordThis: return "this";
case TokenIdKeywordTrue: return "true";
case TokenIdKeywordTry: return "try";
case TokenIdKeywordType: return "type";
case TokenIdKeywordUndefined: return "undefined";
case TokenIdKeywordUnion: return "union";
case TokenIdKeywordUse: return "use";
case TokenIdKeywordVar: return "var";
case TokenIdKeywordVolatile: return "volatile";
case TokenIdKeywordWhile: return "while";
case TokenIdLBrace: return "{";
case TokenIdLBracket: return "[";
case TokenIdLParen: return "(";
case TokenIdMaybe: return "?";
case TokenIdMaybeAssign: return "?=";
case TokenIdMinusEq: return "-=";
case TokenIdMinusPercent: return "-%";
case TokenIdMinusPercentEq: return "-%=";
case TokenIdModEq: return "%=";
case TokenIdNumberLiteral: return "NumberLiteral";
case TokenIdNumberSign: return "#";
case TokenIdPercent: return "%";
case TokenIdPercentDot: return "%.";
case TokenIdPercentPercent: return "%%";
case TokenIdPlus: return "+";
case TokenIdPlusEq: return "+=";
case TokenIdPlusPercent: return "+%";
case TokenIdPlusPercentEq: return "+%=";
case TokenIdPlusPlus: return "++";
case TokenIdRBrace: return "}";
case TokenIdRBracket: return "]";
case TokenIdRParen: return ")";
case TokenIdSemicolon: return ";";
case TokenIdSlash: return "/";
case TokenIdStar: return "*";
case TokenIdStarStar: return "**";
case TokenIdStringLiteral: return "StringLiteral";
case TokenIdSymbol: return "Symbol";
case TokenIdTilde: return "~";
case TokenIdTimesEq: return "*=";
case TokenIdTimesPercent: return "*%";
case TokenIdTimesPercentEq: return "*%=";
}
return "(invalid token)";
}

View File

@ -25,6 +25,7 @@ enum TokenId {
TokenIdKeywordTrue,
TokenIdKeywordFalse,
TokenIdKeywordIf,
TokenIdKeywordTry,
TokenIdKeywordElse,
TokenIdKeywordGoto,
TokenIdKeywordAsm,

View File

@ -9,8 +9,8 @@ error MissingDebugInfo;
error InvalidDebugInfo;
error UnsupportedDebugInfo;
pub fn assert(b: bool) {
if (!b) @unreachable()
pub fn assert(ok: bool) {
if (!ok) @unreachable()
}
pub fn printStackTrace() -> %void {

33
test/cases/try.zig Normal file
View File

@ -0,0 +1,33 @@
const assert = @import("std").debug.assert;
fn tryOnErrorUnion() {
@setFnTest(this);
const x = try (const val = returnsTen()) {
val + 1
} else |err| switch (err) {
error.ItBroke, error.NoMem => 1,
error.CrappedOut => i32(2),
};
assert(x == 11);
}
fn tryOnErrorUnionComptime() {
@setFnTest(this);
comptime {
const x = try (const val = returnsTen()) {
val + 1
} else |err| switch (err) {
error.ItBroke, error.NoMem => 1,
error.CrappedOut => i32(2),
};
assert(x == 11);
}
}
error ItBroke;
error NoMem;
error CrappedOut;
fn returnsTen() -> %i32 {
10
}

View File

@ -28,6 +28,7 @@ const test_switch = @import("cases/switch.zig");
const test_switch_prong_err_enum = @import("cases/switch_prong_err_enum.zig");
const test_switch_prong_implicit_cast = @import("cases/switch_prong_implicit_cast.zig");
const test_this = @import("cases/this.zig");
const test_try = @import("cases/try.zig");
const test_undefined = @import("cases/undefined.zig");
const test_var_args = @import("cases/var_args.zig");
const test_while = @import("cases/while.zig");