mirror of
https://github.com/ziglang/zig.git
synced 2025-12-29 17:43:17 +00:00
parent
8b1c6d8b76
commit
c0b37e8514
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -1769,6 +1769,7 @@ void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node) {
|
||||
case NodeTypeErrorType:
|
||||
case NodeTypeTypeLiteral:
|
||||
case NodeTypeVarLiteral:
|
||||
case NodeTypeTryExpr:
|
||||
zig_unreachable();
|
||||
}
|
||||
}
|
||||
|
||||
@ -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;
|
||||
|
||||
94
src/ir.cpp
94
src/ir.cpp
@ -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:
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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)";
|
||||
}
|
||||
|
||||
@ -25,6 +25,7 @@ enum TokenId {
|
||||
TokenIdKeywordTrue,
|
||||
TokenIdKeywordFalse,
|
||||
TokenIdKeywordIf,
|
||||
TokenIdKeywordTry,
|
||||
TokenIdKeywordElse,
|
||||
TokenIdKeywordGoto,
|
||||
TokenIdKeywordAsm,
|
||||
|
||||
@ -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
33
test/cases/try.zig
Normal 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
|
||||
}
|
||||
@ -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");
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user