mirror of
https://github.com/ziglang/zig.git
synced 2024-12-14 07:10:16 +00:00
parent
d5346d7a80
commit
0cce115476
@ -69,7 +69,7 @@ AssignmentExpression = UnwrapExpression AssignmentOperator UnwrapExpression | Un
|
||||
|
||||
AssignmentOperator = "=" | "*=" | "/=" | "%=" | "+=" | "-=" | "<<=" | ">>=" | "&=" | "^=" | "|=" | "*%=" | "+%=" | "-%=" | "<<%="
|
||||
|
||||
BlockExpression(body) = Block | IfExpression(body) | TryExpression(body) | WhileExpression(body) | ForExpression(body) | SwitchExpression | CompTimeExpression(body)
|
||||
BlockExpression(body) = Block | IfExpression(body) | TryExpression(body) | TestExpression(body) | WhileExpression(body) | ForExpression(body) | SwitchExpression | CompTimeExpression(body)
|
||||
|
||||
CompTimeExpression(body) = "comptime" body
|
||||
|
||||
@ -89,13 +89,11 @@ ReturnExpression = option("%") "return" option(Expression)
|
||||
|
||||
Defer(body) = option("%") "defer" body
|
||||
|
||||
IfExpression(body) = IfVarExpression(body) | IfBoolExpression(body)
|
||||
IfExpression(body) = "if" "(" Expression ")" body option("else" BlockExpression(body))
|
||||
|
||||
IfBoolExpression(body) = "if" "(" Expression ")" body option("else" BlockExpression(body))
|
||||
TryExpression(body) = "try" "(" Expression ")" option("|" option("*") Symbol "|") body option("else" option("|" Symbol "|") BlockExpression(body))
|
||||
|
||||
TryExpression(body) = "try" "(" option(("const" | "var") option("*") Symbol "=") Expression ")" body option("else" option("|" Symbol "|") BlockExpression(body))
|
||||
|
||||
IfVarExpression(body) = "if" "(" ("const" | "var") option("*") Symbol option(":" TypeExpr) "?=" Expression ")" body Option("else" BlockExpression(body))
|
||||
TestExpression(body) = "test" "(" Expression ")" option("|" option("*") Symbol "|") body option("else" option("|" Symbol "|") BlockExpression(body))
|
||||
|
||||
BoolAndExpression = ComparisonExpression "and" BoolAndExpression | ComparisonExpression
|
||||
|
||||
|
@ -344,7 +344,6 @@ enum NodeType {
|
||||
NodeTypeThisLiteral,
|
||||
NodeTypeUnreachable,
|
||||
NodeTypeIfBoolExpr,
|
||||
NodeTypeIfVarExpr,
|
||||
NodeTypeWhileExpr,
|
||||
NodeTypeForExpr,
|
||||
NodeTypeSwitchExpr,
|
||||
@ -364,6 +363,7 @@ enum NodeType {
|
||||
NodeTypeErrorType,
|
||||
NodeTypeVarLiteral,
|
||||
NodeTypeTryExpr,
|
||||
NodeTypeTestExpr,
|
||||
NodeTypeInlineExpr,
|
||||
};
|
||||
|
||||
@ -577,7 +577,6 @@ struct AstNodeIfBoolExpr {
|
||||
};
|
||||
|
||||
struct AstNodeTryExpr {
|
||||
bool var_is_const;
|
||||
Buf *var_symbol;
|
||||
bool var_is_ptr;
|
||||
AstNode *target_node;
|
||||
@ -586,11 +585,12 @@ struct AstNodeTryExpr {
|
||||
Buf *err_symbol;
|
||||
};
|
||||
|
||||
struct AstNodeIfVarExpr {
|
||||
AstNodeVariableDeclaration var_decl;
|
||||
AstNode *then_block;
|
||||
AstNode *else_node; // null, block node, or other if expr node
|
||||
struct AstNodeTestExpr {
|
||||
Buf *var_symbol;
|
||||
bool var_is_ptr;
|
||||
AstNode *target_node;
|
||||
AstNode *then_node;
|
||||
AstNode *else_node; // null, block node, or other if expr node
|
||||
};
|
||||
|
||||
struct AstNodeWhileExpr {
|
||||
@ -807,8 +807,8 @@ struct AstNode {
|
||||
AstNodeSliceExpr slice_expr;
|
||||
AstNodeUse use;
|
||||
AstNodeIfBoolExpr if_bool_expr;
|
||||
AstNodeIfVarExpr if_var_expr;
|
||||
AstNodeTryExpr try_expr;
|
||||
AstNodeTestExpr test_expr;
|
||||
AstNodeWhileExpr while_expr;
|
||||
AstNodeForExpr for_expr;
|
||||
AstNodeSwitchExpr switch_expr;
|
||||
|
@ -2099,7 +2099,6 @@ void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node) {
|
||||
case NodeTypeSymbol:
|
||||
case NodeTypePrefixOpExpr:
|
||||
case NodeTypeIfBoolExpr:
|
||||
case NodeTypeIfVarExpr:
|
||||
case NodeTypeWhileExpr:
|
||||
case NodeTypeForExpr:
|
||||
case NodeTypeSwitchExpr:
|
||||
@ -2119,6 +2118,7 @@ void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node) {
|
||||
case NodeTypeErrorType:
|
||||
case NodeTypeVarLiteral:
|
||||
case NodeTypeTryExpr:
|
||||
case NodeTypeTestExpr:
|
||||
case NodeTypeInlineExpr:
|
||||
zig_unreachable();
|
||||
}
|
||||
|
@ -192,8 +192,6 @@ static const char *node_type_str(NodeType node_type) {
|
||||
return "ThisLiteral";
|
||||
case NodeTypeIfBoolExpr:
|
||||
return "IfBoolExpr";
|
||||
case NodeTypeIfVarExpr:
|
||||
return "IfVarExpr";
|
||||
case NodeTypeWhileExpr:
|
||||
return "WhileExpr";
|
||||
case NodeTypeForExpr:
|
||||
@ -236,6 +234,8 @@ static const char *node_type_str(NodeType node_type) {
|
||||
return "VarLiteral";
|
||||
case NodeTypeTryExpr:
|
||||
return "TryExpr";
|
||||
case NodeTypeTestExpr:
|
||||
return "TestExpr";
|
||||
case NodeTypeInlineExpr:
|
||||
return "InlineExpr";
|
||||
}
|
||||
@ -760,38 +760,16 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {
|
||||
fprintf(ar->f, "null");
|
||||
break;
|
||||
}
|
||||
case NodeTypeIfVarExpr:
|
||||
{
|
||||
AstNodeVariableDeclaration *var_decl = &node->data.if_var_expr.var_decl;
|
||||
const char *var_str = var_decl->is_const ? "const" : "var";
|
||||
const char *var_name = buf_ptr(var_decl->symbol);
|
||||
const char *ptr_str = node->data.if_var_expr.var_is_ptr ? "*" : "";
|
||||
fprintf(ar->f, "if (%s %s%s", var_str, ptr_str, var_name);
|
||||
if (var_decl->type) {
|
||||
fprintf(ar->f, ": ");
|
||||
render_node_ungrouped(ar, var_decl->type);
|
||||
}
|
||||
fprintf(ar->f, " ?= ");
|
||||
render_node_grouped(ar, var_decl->expr);
|
||||
fprintf(ar->f, ") ");
|
||||
render_node_grouped(ar, node->data.if_var_expr.then_block);
|
||||
if (node->data.if_var_expr.else_node) {
|
||||
fprintf(ar->f, " else ");
|
||||
render_node_grouped(ar, node->data.if_var_expr.else_node);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case NodeTypeTryExpr:
|
||||
{
|
||||
fprintf(ar->f, "try (");
|
||||
if (node->data.try_expr.var_symbol) {
|
||||
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, "%s %s%s = ", var_str, ptr_str, var_name);
|
||||
}
|
||||
render_node_grouped(ar, node->data.try_expr.target_node);
|
||||
fprintf(ar->f, ") ");
|
||||
if (node->data.try_expr.var_symbol) {
|
||||
const char *ptr_str = node->data.try_expr.var_is_ptr ? "*" : "";
|
||||
const char *var_name = buf_ptr(node->data.try_expr.var_symbol);
|
||||
fprintf(ar->f, "|%s%s| ", ptr_str, var_name);
|
||||
}
|
||||
render_node_grouped(ar, node->data.try_expr.then_node);
|
||||
if (node->data.try_expr.else_node) {
|
||||
fprintf(ar->f, " else ");
|
||||
@ -802,6 +780,23 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {
|
||||
}
|
||||
break;
|
||||
}
|
||||
case NodeTypeTestExpr:
|
||||
{
|
||||
fprintf(ar->f, "test (");
|
||||
render_node_grouped(ar, node->data.test_expr.target_node);
|
||||
fprintf(ar->f, ") ");
|
||||
if (node->data.test_expr.var_symbol) {
|
||||
const char *ptr_str = node->data.test_expr.var_is_ptr ? "*" : "";
|
||||
const char *var_name = buf_ptr(node->data.test_expr.var_symbol);
|
||||
fprintf(ar->f, "|%s%s| ", ptr_str, var_name);
|
||||
}
|
||||
render_node_grouped(ar, node->data.test_expr.then_node);
|
||||
if (node->data.test_expr.else_node) {
|
||||
fprintf(ar->f, " else ");
|
||||
render_node_grouped(ar, node->data.test_expr.else_node);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case NodeTypeSwitchExpr:
|
||||
{
|
||||
AstNodeSwitchExpr *switch_expr = &node->data.switch_expr;
|
||||
|
50
src/ir.cpp
50
src/ir.cpp
@ -4941,14 +4941,14 @@ static IrInstruction *ir_gen_asm_expr(IrBuilder *irb, Scope *scope, AstNode *nod
|
||||
return ir_build_asm(irb, scope, node, input_list, output_types, output_vars, return_count, is_volatile);
|
||||
}
|
||||
|
||||
static IrInstruction *ir_gen_if_var_expr(IrBuilder *irb, Scope *scope, AstNode *node) {
|
||||
assert(node->type == NodeTypeIfVarExpr);
|
||||
static IrInstruction *ir_gen_test_expr(IrBuilder *irb, Scope *scope, AstNode *node) {
|
||||
assert(node->type == NodeTypeTestExpr);
|
||||
|
||||
AstNodeVariableDeclaration *var_decl = &node->data.if_var_expr.var_decl;
|
||||
AstNode *expr_node = var_decl->expr;
|
||||
AstNode *then_node = node->data.if_var_expr.then_block;
|
||||
AstNode *else_node = node->data.if_var_expr.else_node;
|
||||
bool var_is_ptr = node->data.if_var_expr.var_is_ptr;
|
||||
Buf *var_symbol = node->data.test_expr.var_symbol;
|
||||
AstNode *expr_node = node->data.test_expr.target_node;
|
||||
AstNode *then_node = node->data.test_expr.then_node;
|
||||
AstNode *else_node = node->data.test_expr.else_node;
|
||||
bool var_is_ptr = node->data.test_expr.var_is_ptr;
|
||||
|
||||
IrInstruction *maybe_val_ptr = ir_gen_node_extra(irb, expr_node, scope, LVAL_PTR);
|
||||
if (maybe_val_ptr == irb->codegen->invalid_instruction)
|
||||
@ -4970,21 +4970,23 @@ static IrInstruction *ir_gen_if_var_expr(IrBuilder *irb, Scope *scope, AstNode *
|
||||
ir_build_cond_br(irb, scope, node, is_non_null, then_block, else_block, is_comptime);
|
||||
|
||||
ir_set_cursor_at_end(irb, then_block);
|
||||
IrInstruction *var_type = nullptr;
|
||||
if (var_decl->type) {
|
||||
var_type = ir_gen_node(irb, var_decl->type, scope);
|
||||
if (var_type == irb->codegen->invalid_instruction)
|
||||
return irb->codegen->invalid_instruction;
|
||||
}
|
||||
bool is_shadowable = false;
|
||||
bool is_const = var_decl->is_const;
|
||||
VariableTableEntry *var = ir_create_var(irb, node, scope,
|
||||
var_decl->symbol, is_const, is_const, is_shadowable, is_comptime);
|
||||
|
||||
IrInstruction *var_ptr_value = ir_build_unwrap_maybe(irb, scope, node, maybe_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);
|
||||
IrInstruction *then_expr_result = ir_gen_node(irb, then_node, var->child_scope);
|
||||
Scope *var_scope;
|
||||
if (var_symbol) {
|
||||
IrInstruction *var_type = nullptr;
|
||||
bool is_shadowable = false;
|
||||
bool is_const = true;
|
||||
VariableTableEntry *var = ir_create_var(irb, node, scope,
|
||||
var_symbol, is_const, is_const, is_shadowable, is_comptime);
|
||||
|
||||
IrInstruction *var_ptr_value = ir_build_unwrap_maybe(irb, scope, node, maybe_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;
|
||||
@ -5022,7 +5024,7 @@ static IrInstruction *ir_gen_try_expr(IrBuilder *irb, Scope *scope, AstNode *nod
|
||||
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;
|
||||
bool var_is_const = true;
|
||||
Buf *var_symbol = node->data.try_expr.var_symbol;
|
||||
Buf *err_symbol = node->data.try_expr.err_symbol;
|
||||
|
||||
@ -5659,10 +5661,10 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop
|
||||
return ir_lval_wrap(irb, scope, ir_gen_null_literal(irb, scope, node), lval);
|
||||
case NodeTypeVarLiteral:
|
||||
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 NodeTypeTestExpr:
|
||||
return ir_lval_wrap(irb, scope, ir_gen_test_expr(irb, scope, node), lval);
|
||||
case NodeTypeSwitchExpr:
|
||||
return ir_lval_wrap(irb, scope, ir_gen_switch_expr(irb, scope, node), lval);
|
||||
case NodeTypeGoto:
|
||||
|
172
src/parser.cpp
172
src/parser.cpp
@ -640,7 +640,7 @@ static AstNode *ast_parse_comptime_expr(ParseContext *pc, size_t *token_index, b
|
||||
}
|
||||
|
||||
/*
|
||||
TryExpression(body) = "try" "(" option(("const" | "var") option("*") Symbol "=") Expression ")" body option("else" option("|" Symbol "|") body)
|
||||
TryExpression(body) = "try" "(" Expression ")" option("|" option("*") Symbol "|") body option("else" option("|" Symbol "|") BlockExpression(body))
|
||||
*/
|
||||
static AstNode *ast_parse_try_expr(ParseContext *pc, size_t *token_index, bool mandatory) {
|
||||
Token *try_token = &pc->tokens->at(*token_index);
|
||||
@ -656,38 +656,25 @@ static AstNode *ast_parse_try_expr(ParseContext *pc, size_t *token_index, bool m
|
||||
AstNode *node = ast_create_node(pc, NodeTypeTryExpr, try_token);
|
||||
|
||||
ast_eat_token(pc, token_index, TokenIdLParen);
|
||||
node->data.try_expr.target_node = ast_parse_expression(pc, token_index, true);
|
||||
ast_eat_token(pc, token_index, TokenIdRParen);
|
||||
|
||||
Token *var_token = &pc->tokens->at(*token_index);
|
||||
bool have_vars;
|
||||
if (var_token->id == TokenIdKeywordVar) {
|
||||
node->data.try_expr.var_is_const = false;
|
||||
Token *open_bar_tok = &pc->tokens->at(*token_index);
|
||||
if (open_bar_tok->id == TokenIdBinOr) {
|
||||
*token_index += 1;
|
||||
have_vars = true;
|
||||
} else if (var_token->id == TokenIdKeywordConst) {
|
||||
node->data.try_expr.var_is_const = true;
|
||||
*token_index += 1;
|
||||
have_vars = true;
|
||||
} else {
|
||||
have_vars = false;
|
||||
}
|
||||
|
||||
if (have_vars) {
|
||||
Token *star_token = &pc->tokens->at(*token_index);
|
||||
if (star_token->id == TokenIdStar) {
|
||||
node->data.try_expr.var_is_ptr = true;
|
||||
Token *star_tok = &pc->tokens->at(*token_index);
|
||||
if (star_tok->id == TokenIdStar) {
|
||||
*token_index += 1;
|
||||
node->data.try_expr.var_is_ptr = true;
|
||||
}
|
||||
|
||||
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);
|
||||
ast_eat_token(pc, token_index, TokenIdBinOr);
|
||||
}
|
||||
|
||||
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_block_or_expression(pc, token_index, true);
|
||||
|
||||
Token *else_token = &pc->tokens->at(*token_index);
|
||||
@ -709,6 +696,53 @@ static AstNode *ast_parse_try_expr(ParseContext *pc, size_t *token_index, bool m
|
||||
return node;
|
||||
}
|
||||
|
||||
/*
|
||||
TestExpression(body) = "test" "(" Expression ")" option("|" option("*") Symbol "|") body option("else" BlockExpression(body))
|
||||
*/
|
||||
static AstNode *ast_parse_test_expr(ParseContext *pc, size_t *token_index, bool mandatory) {
|
||||
Token *test_token = &pc->tokens->at(*token_index);
|
||||
if (test_token->id == TokenIdKeywordTest) {
|
||||
*token_index += 1;
|
||||
} else if (mandatory) {
|
||||
ast_expect_token(pc, test_token, TokenIdKeywordTest);
|
||||
zig_unreachable();
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
AstNode *node = ast_create_node(pc, NodeTypeTestExpr, test_token);
|
||||
|
||||
ast_eat_token(pc, token_index, TokenIdLParen);
|
||||
node->data.test_expr.target_node = ast_parse_expression(pc, token_index, true);
|
||||
ast_eat_token(pc, token_index, TokenIdRParen);
|
||||
|
||||
Token *open_bar_tok = &pc->tokens->at(*token_index);
|
||||
if (open_bar_tok->id == TokenIdBinOr) {
|
||||
*token_index += 1;
|
||||
|
||||
Token *star_tok = &pc->tokens->at(*token_index);
|
||||
if (star_tok->id == TokenIdStar) {
|
||||
*token_index += 1;
|
||||
node->data.test_expr.var_is_ptr = true;
|
||||
}
|
||||
|
||||
Token *var_name_tok = ast_eat_token(pc, token_index, TokenIdSymbol);
|
||||
node->data.test_expr.var_symbol = token_buf(var_name_tok);
|
||||
|
||||
ast_eat_token(pc, token_index, TokenIdBinOr);
|
||||
}
|
||||
|
||||
node->data.test_expr.then_node = ast_parse_block_or_expression(pc, token_index, true);
|
||||
|
||||
Token *else_token = &pc->tokens->at(*token_index);
|
||||
if (else_token->id == TokenIdKeywordElse) {
|
||||
*token_index += 1;
|
||||
node->data.test_expr.else_node = ast_parse_block_expr_or_expression(pc, token_index, true);
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
/*
|
||||
PrimaryExpression = Number | String | CharLiteral | KeywordLiteral | GroupedExpression | GotoExpression | BlockExpression(BlockOrExpression) | Symbol | ("@" Symbol FnCallExpression) | ArrayType | (option("extern") FnProto) | AsmExpression | ("error" "." Symbol) | ContainerDecl
|
||||
KeywordLiteral = "true" | "false" | "null" | "break" | "continue" | "undefined" | "error" | "this" | "unreachable"
|
||||
@ -1405,9 +1439,7 @@ static AstNode *ast_parse_bool_and_expr(ParseContext *pc, size_t *token_index, b
|
||||
}
|
||||
|
||||
/*
|
||||
IfExpression(body) = IfVarExpression(body) | IfBoolExpression(body)
|
||||
IfBoolExpression(body) = "if" "(" Expression ")" body option("else" body)
|
||||
IfVarExpression(body) = "if" "(" ("const" | "var") option("*") Symbol option(":" TypeExpr) "?=" Expression ")" body Option("else" body)
|
||||
IfExpression(body) = "if" "(" Expression ")" body option("else" BlockExpression(body))
|
||||
*/
|
||||
static AstNode *ast_parse_if_expr(ParseContext *pc, size_t *token_index, bool mandatory) {
|
||||
Token *if_token = &pc->tokens->at(*token_index);
|
||||
@ -1423,63 +1455,18 @@ static AstNode *ast_parse_if_expr(ParseContext *pc, size_t *token_index, bool ma
|
||||
|
||||
ast_eat_token(pc, token_index, TokenIdLParen);
|
||||
|
||||
Token *token = &pc->tokens->at(*token_index);
|
||||
if (token->id == TokenIdKeywordConst || token->id == TokenIdKeywordVar) {
|
||||
AstNode *node = ast_create_node(pc, NodeTypeIfVarExpr, if_token);
|
||||
node->data.if_var_expr.var_decl.is_const = (token->id == TokenIdKeywordConst);
|
||||
AstNode *node = ast_create_node(pc, NodeTypeIfBoolExpr, if_token);
|
||||
node->data.if_bool_expr.condition = ast_parse_expression(pc, token_index, true);
|
||||
ast_eat_token(pc, token_index, TokenIdRParen);
|
||||
node->data.if_bool_expr.then_block = ast_parse_block_or_expression(pc, token_index, true);
|
||||
|
||||
Token *else_token = &pc->tokens->at(*token_index);
|
||||
if (else_token->id == TokenIdKeywordElse) {
|
||||
*token_index += 1;
|
||||
|
||||
Token *star_or_symbol = &pc->tokens->at(*token_index);
|
||||
if (star_or_symbol->id == TokenIdStar) {
|
||||
*token_index += 1;
|
||||
node->data.if_var_expr.var_is_ptr = true;
|
||||
Token *name_token = ast_eat_token(pc, token_index, TokenIdSymbol);
|
||||
node->data.if_var_expr.var_decl.symbol = token_buf(name_token);
|
||||
} else if (star_or_symbol->id == TokenIdSymbol) {
|
||||
*token_index += 1;
|
||||
node->data.if_var_expr.var_decl.symbol = token_buf(star_or_symbol);
|
||||
} else {
|
||||
ast_invalid_token_error(pc, star_or_symbol);
|
||||
}
|
||||
|
||||
|
||||
Token *eq_or_colon = &pc->tokens->at(*token_index);
|
||||
if (eq_or_colon->id == TokenIdMaybeAssign) {
|
||||
*token_index += 1;
|
||||
node->data.if_var_expr.var_decl.expr = ast_parse_expression(pc, token_index, true);
|
||||
} else if (eq_or_colon->id == TokenIdColon) {
|
||||
*token_index += 1;
|
||||
node->data.if_var_expr.var_decl.type = ast_parse_type_expr(pc, token_index, true);
|
||||
|
||||
ast_eat_token(pc, token_index, TokenIdMaybeAssign);
|
||||
node->data.if_var_expr.var_decl.expr = ast_parse_expression(pc, token_index, true);
|
||||
} else {
|
||||
ast_invalid_token_error(pc, eq_or_colon);
|
||||
}
|
||||
ast_eat_token(pc, token_index, TokenIdRParen);
|
||||
node->data.if_var_expr.then_block = ast_parse_block_or_expression(pc, token_index, true);
|
||||
|
||||
Token *else_token = &pc->tokens->at(*token_index);
|
||||
if (else_token->id == TokenIdKeywordElse) {
|
||||
*token_index += 1;
|
||||
node->data.if_var_expr.else_node = ast_parse_block_expr_or_expression(pc, token_index, true);
|
||||
}
|
||||
|
||||
return node;
|
||||
} else {
|
||||
AstNode *node = ast_create_node(pc, NodeTypeIfBoolExpr, if_token);
|
||||
node->data.if_bool_expr.condition = ast_parse_expression(pc, token_index, true);
|
||||
ast_eat_token(pc, token_index, TokenIdRParen);
|
||||
node->data.if_bool_expr.then_block = ast_parse_block_or_expression(pc, token_index, true);
|
||||
|
||||
Token *else_token = &pc->tokens->at(*token_index);
|
||||
if (else_token->id == TokenIdKeywordElse) {
|
||||
*token_index += 1;
|
||||
node->data.if_bool_expr.else_node = ast_parse_block_expr_or_expression(pc, token_index, true);
|
||||
}
|
||||
|
||||
return node;
|
||||
node->data.if_bool_expr.else_node = ast_parse_block_expr_or_expression(pc, token_index, true);
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1862,7 +1849,7 @@ static AstNode *ast_parse_switch_expr(ParseContext *pc, size_t *token_index, boo
|
||||
}
|
||||
|
||||
/*
|
||||
BlockExpression(body) = Block | IfExpression(body) | TryExpression(body) | WhileExpression(body) | ForExpression(body) | SwitchExpression | CompTimeExpression(body)
|
||||
BlockExpression(body) = Block | IfExpression(body) | TryExpression(body) | TestExpression(body) | WhileExpression(body) | ForExpression(body) | SwitchExpression | CompTimeExpression(body)
|
||||
*/
|
||||
static AstNode *ast_parse_block_expr(ParseContext *pc, size_t *token_index, bool mandatory) {
|
||||
Token *token = &pc->tokens->at(*token_index);
|
||||
@ -1895,6 +1882,10 @@ static AstNode *ast_parse_block_expr(ParseContext *pc, size_t *token_index, bool
|
||||
if (try_node)
|
||||
return try_node;
|
||||
|
||||
AstNode *test_node = ast_parse_test_expr(pc, token_index, false);
|
||||
if (test_node)
|
||||
return test_node;
|
||||
|
||||
if (mandatory)
|
||||
ast_invalid_token_error(pc, token);
|
||||
|
||||
@ -2079,14 +2070,14 @@ static bool statement_terminates_without_semicolon(AstNode *node) {
|
||||
if (node->data.if_bool_expr.else_node)
|
||||
return statement_terminates_without_semicolon(node->data.if_bool_expr.else_node);
|
||||
return node->data.if_bool_expr.then_block->type == NodeTypeBlock;
|
||||
case NodeTypeIfVarExpr:
|
||||
if (node->data.if_var_expr.else_node)
|
||||
return statement_terminates_without_semicolon(node->data.if_var_expr.else_node);
|
||||
return node->data.if_var_expr.then_block->type == NodeTypeBlock;
|
||||
case NodeTypeTryExpr:
|
||||
if (node->data.try_expr.else_node)
|
||||
return statement_terminates_without_semicolon(node->data.try_expr.else_node);
|
||||
return node->data.try_expr.then_node->type == NodeTypeBlock;
|
||||
case NodeTypeTestExpr:
|
||||
if (node->data.test_expr.else_node)
|
||||
return statement_terminates_without_semicolon(node->data.test_expr.else_node);
|
||||
return node->data.test_expr.then_node->type == NodeTypeBlock;
|
||||
case NodeTypeWhileExpr:
|
||||
return node->data.while_expr.body->type == NodeTypeBlock;
|
||||
case NodeTypeForExpr:
|
||||
@ -2667,17 +2658,16 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont
|
||||
visit_field(&node->data.if_bool_expr.then_block, visit, context);
|
||||
visit_field(&node->data.if_bool_expr.else_node, visit, context);
|
||||
break;
|
||||
case NodeTypeIfVarExpr:
|
||||
visit_field(&node->data.if_var_expr.var_decl.type, visit, context);
|
||||
visit_field(&node->data.if_var_expr.var_decl.expr, visit, context);
|
||||
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 NodeTypeTestExpr:
|
||||
visit_field(&node->data.test_expr.target_node, visit, context);
|
||||
visit_field(&node->data.test_expr.then_node, visit, context);
|
||||
visit_field(&node->data.test_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);
|
||||
|
@ -28,7 +28,7 @@ pub const BufMap = struct {
|
||||
}
|
||||
|
||||
pub fn set(self: &BufMap, key: []const u8, value: []const u8) -> %void {
|
||||
if (const entry ?= self.hash_map.get(key)) {
|
||||
test (self.hash_map.get(key)) |entry| {
|
||||
const value_copy = %return self.copy(value);
|
||||
%defer self.free(value_copy);
|
||||
%return self.hash_map.put(key, value_copy);
|
||||
|
@ -309,7 +309,7 @@ pub const Builder = struct {
|
||||
}
|
||||
|
||||
fn processNixOSEnvVars(self: &Builder) {
|
||||
if (const nix_cflags_compile ?= os.getEnv("NIX_CFLAGS_COMPILE")) {
|
||||
test (os.getEnv("NIX_CFLAGS_COMPILE")) |nix_cflags_compile| {
|
||||
var it = mem.split(nix_cflags_compile, ' ');
|
||||
while (true) {
|
||||
const word = it.next() ?? break;
|
||||
@ -325,7 +325,7 @@ pub const Builder = struct {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (const nix_ldflags ?= os.getEnv("NIX_LDFLAGS")) {
|
||||
test (os.getEnv("NIX_LDFLAGS")) |nix_ldflags| {
|
||||
var it = mem.split(nix_ldflags, ' ');
|
||||
while (true) {
|
||||
const word = it.next() ?? break;
|
||||
@ -353,7 +353,7 @@ pub const Builder = struct {
|
||||
.type_id = type_id,
|
||||
.description = description,
|
||||
};
|
||||
if (const _ ?= %%self.available_options_map.put(name, available_option)) {
|
||||
test (%%self.available_options_map.put(name, available_option)) {
|
||||
debug.panic("Option '{}' declared twice", name);
|
||||
}
|
||||
%%self.available_options_list.append(available_option);
|
||||
@ -410,11 +410,11 @@ pub const Builder = struct {
|
||||
}
|
||||
|
||||
pub fn addUserInputOption(self: &Builder, name: []const u8, value: []const u8) -> bool {
|
||||
if (var prev_value ?= %%self.user_input_options.put(name, UserInputOption {
|
||||
test (%%self.user_input_options.put(name, UserInputOption {
|
||||
.name = name,
|
||||
.value = UserValue.Scalar { value },
|
||||
.used = false,
|
||||
})) {
|
||||
})) |*prev_value| {
|
||||
switch (prev_value.value) {
|
||||
UserValue.Scalar => |s| {
|
||||
var list = List([]const u8).init(self.allocator);
|
||||
@ -444,11 +444,11 @@ pub const Builder = struct {
|
||||
}
|
||||
|
||||
pub fn addUserInputFlag(self: &Builder, name: []const u8) -> bool {
|
||||
if (const prev_value ?= %%self.user_input_options.put(name, UserInputOption {
|
||||
test (%%self.user_input_options.put(name, UserInputOption {
|
||||
.name = name,
|
||||
.value = UserValue.Flag,
|
||||
.used = false,
|
||||
})) {
|
||||
})) |*prev_value| {
|
||||
switch (prev_value.value) {
|
||||
UserValue.Scalar => |s| {
|
||||
%%io.stderr.printf("Flag '-D{}' conflicts with option '-D{}={}'.\n", name, name, s);
|
||||
@ -766,7 +766,7 @@ pub const LibOrExeStep = struct {
|
||||
%%zig_args.append("--release");
|
||||
}
|
||||
|
||||
if (const output_path ?= self.output_path) {
|
||||
test (self.output_path) |output_path| {
|
||||
%%zig_args.append("--output");
|
||||
%%zig_args.append(builder.pathFromRoot(output_path));
|
||||
}
|
||||
@ -912,7 +912,7 @@ pub const ObjectStep = struct {
|
||||
%%zig_args.append("--release");
|
||||
}
|
||||
|
||||
if (const output_path ?= self.output_path) {
|
||||
test (self.output_path) |output_path| {
|
||||
%%zig_args.append("--output");
|
||||
%%zig_args.append(builder.pathFromRoot(output_path));
|
||||
}
|
||||
@ -1017,7 +1017,7 @@ pub const AsmStep = struct {
|
||||
%%zig_args.append("--release");
|
||||
}
|
||||
|
||||
if (const output_path ?= self.output_path) {
|
||||
test (self.output_path) |output_path| {
|
||||
%%zig_args.append("--output");
|
||||
%%zig_args.append(builder.pathFromRoot(output_path));
|
||||
}
|
||||
@ -1194,7 +1194,7 @@ pub const LinkStep = struct {
|
||||
%%zig_args.append("--static");
|
||||
}
|
||||
|
||||
if (const output_path ?= self.output_path) {
|
||||
test (self.output_path) |output_path| {
|
||||
%%zig_args.append("--output");
|
||||
%%zig_args.append(builder.pathFromRoot(output_path));
|
||||
}
|
||||
@ -1316,7 +1316,7 @@ pub const TestStep = struct {
|
||||
%%zig_args.append("--release");
|
||||
}
|
||||
|
||||
if (const filter ?= self.filter) {
|
||||
test (self.filter) |filter| {
|
||||
%%zig_args.append("--test-filter");
|
||||
%%zig_args.append(filter);
|
||||
}
|
||||
|
@ -246,7 +246,7 @@ test "basicHashMapTest" {
|
||||
assert((??map.get(2)).value == 22);
|
||||
_ = map.remove(2);
|
||||
assert(map.remove(2) == null);
|
||||
assert(if (const entry ?= map.get(2)) false else true);
|
||||
assert(test (map.get(2)) false else true);
|
||||
}
|
||||
|
||||
fn hash_i32(x: i32) -> u32 {
|
||||
|
@ -56,9 +56,9 @@ pub const ChildProcess = struct {
|
||||
errno.EINVAL, errno.ECHILD => unreachable,
|
||||
errno.EINTR => continue,
|
||||
else => {
|
||||
if (const *stdin ?= self.stdin) { stdin.close(); }
|
||||
if (const *stdout ?= self.stdin) { stdout.close(); }
|
||||
if (const *stderr ?= self.stdin) { stderr.close(); }
|
||||
test (self.stdin) |*stdin| { stdin.close(); }
|
||||
test (self.stdout) |*stdout| { stdout.close(); }
|
||||
test (self.stderr) |*stderr| { stderr.close(); }
|
||||
return error.Unexpected;
|
||||
},
|
||||
}
|
||||
@ -66,9 +66,10 @@ pub const ChildProcess = struct {
|
||||
break;
|
||||
}
|
||||
|
||||
if (const *stdin ?= self.stdin) { stdin.close(); }
|
||||
if (const *stdout ?= self.stdin) { stdout.close(); }
|
||||
if (const *stderr ?= self.stdin) { stderr.close(); }
|
||||
// TODO oops!
|
||||
test (self.stdin) |*stdin| { stdin.close(); }
|
||||
test (self.stdin) |*stdout| { stdout.close(); }
|
||||
test (self.stdin) |*stderr| { stderr.close(); }
|
||||
|
||||
// Write @maxValue(ErrInt) to the write end of the err_pipe. This is after
|
||||
// waitpid, so this write is guaranteed to be after the child
|
||||
|
@ -162,7 +162,7 @@ pub fn posixOpen(file_path: []const u8, flags: usize, perm: usize, allocator: ?&
|
||||
|
||||
if (file_path.len < stack_buf.len) {
|
||||
path0 = stack_buf[0...file_path.len + 1];
|
||||
} else if (const a ?= allocator) {
|
||||
} else test (allocator) |a| {
|
||||
path0 = %return a.alloc(u8, file_path.len + 1);
|
||||
need_free = true;
|
||||
} else {
|
||||
@ -230,7 +230,7 @@ pub fn posixExecve(exe_path: []const u8, argv: []const []const u8, env_map: &con
|
||||
mem.set(?&u8, argv_buf, null);
|
||||
defer {
|
||||
for (argv_buf) |arg| {
|
||||
const arg_buf = if (const ptr ?= arg) cstr.toSlice(ptr) else break;
|
||||
const arg_buf = test (arg) |ptr| cstr.toSlice(ptr) else break;
|
||||
allocator.free(arg_buf);
|
||||
}
|
||||
allocator.free(argv_buf);
|
||||
@ -257,7 +257,7 @@ pub fn posixExecve(exe_path: []const u8, argv: []const []const u8, env_map: &con
|
||||
mem.set(?&u8, envp_buf, null);
|
||||
defer {
|
||||
for (envp_buf) |env| {
|
||||
const env_buf = if (const ptr ?= env) cstr.toSlice(ptr) else break;
|
||||
const env_buf = test (env) |ptr| cstr.toSlice(ptr) else break;
|
||||
allocator.free(env_buf);
|
||||
}
|
||||
allocator.free(envp_buf);
|
||||
|
@ -53,7 +53,7 @@ pub fn main() -> %void {
|
||||
%%io.stderr.printf("Expected option name after '-D'\n\n");
|
||||
return usage(&builder, false, &io.stderr);
|
||||
}
|
||||
if (const name_end ?= mem.indexOfScalar(u8, option_contents, '=')) {
|
||||
test (mem.indexOfScalar(u8, option_contents, '=')) |name_end| {
|
||||
const option_name = option_contents[0...name_end];
|
||||
const option_value = option_contents[name_end + 1...];
|
||||
if (builder.addUserInputOption(option_name, option_value))
|
||||
|
@ -34,7 +34,7 @@ export fn __udivmoddi4(a: du_int, b: du_int, maybe_rem: ?&du_int) -> du_int {
|
||||
// 0 X
|
||||
// ---
|
||||
// 0 X
|
||||
if (const rem ?= maybe_rem) {
|
||||
test (maybe_rem) |rem| {
|
||||
*rem = n[low] % d[low];
|
||||
}
|
||||
return n[low] / d[low];
|
||||
@ -42,7 +42,7 @@ export fn __udivmoddi4(a: du_int, b: du_int, maybe_rem: ?&du_int) -> du_int {
|
||||
// 0 X
|
||||
// ---
|
||||
// K X
|
||||
if (const rem ?= maybe_rem) {
|
||||
test (maybe_rem) |rem| {
|
||||
*rem = n[low];
|
||||
}
|
||||
return 0;
|
||||
@ -53,7 +53,7 @@ export fn __udivmoddi4(a: du_int, b: du_int, maybe_rem: ?&du_int) -> du_int {
|
||||
// K X
|
||||
// ---
|
||||
// 0 0
|
||||
if (var rem ?= maybe_rem) {
|
||||
test (maybe_rem) |rem| {
|
||||
*rem = n[high] % d[low];
|
||||
}
|
||||
return n[high] / d[low];
|
||||
@ -63,7 +63,7 @@ export fn __udivmoddi4(a: du_int, b: du_int, maybe_rem: ?&du_int) -> du_int {
|
||||
// K 0
|
||||
// ---
|
||||
// K 0
|
||||
if (var rem ?= maybe_rem) {
|
||||
test (maybe_rem) |rem| {
|
||||
r[high] = n[high] % d[high];
|
||||
r[low] = 0;
|
||||
*rem = *@ptrCast(&du_int, &r[0]);
|
||||
@ -75,7 +75,7 @@ export fn __udivmoddi4(a: du_int, b: du_int, maybe_rem: ?&du_int) -> du_int {
|
||||
// K 0
|
||||
// if d is a power of 2
|
||||
if ((d[high] & (d[high] - 1)) == 0) {
|
||||
if (var rem ?= maybe_rem) {
|
||||
test (maybe_rem) |rem| {
|
||||
r[low] = n[low];
|
||||
r[high] = n[high] & (d[high] - 1);
|
||||
*rem = *@ptrCast(&du_int, &r[0]);
|
||||
@ -88,7 +88,7 @@ export fn __udivmoddi4(a: du_int, b: du_int, maybe_rem: ?&du_int) -> du_int {
|
||||
sr = @clz(su_int(d[high])) - @clz(su_int(n[high]));
|
||||
// 0 <= sr <= n_uword_bits - 2 or sr large
|
||||
if (sr > n_uword_bits - 2) {
|
||||
if (var rem ?= maybe_rem) {
|
||||
test (maybe_rem) |rem| {
|
||||
*rem = *@ptrCast(&du_int, &n[0]);
|
||||
}
|
||||
return 0;
|
||||
@ -109,7 +109,7 @@ export fn __udivmoddi4(a: du_int, b: du_int, maybe_rem: ?&du_int) -> du_int {
|
||||
// 0 K
|
||||
// if d is a power of 2
|
||||
if ((d[low] & (d[low] - 1)) == 0) {
|
||||
if (var rem ?= maybe_rem) {
|
||||
test (maybe_rem) |rem| {
|
||||
*rem = n[low] & (d[low] - 1);
|
||||
}
|
||||
if (d[low] == 1) {
|
||||
@ -153,7 +153,7 @@ export fn __udivmoddi4(a: du_int, b: du_int, maybe_rem: ?&du_int) -> du_int {
|
||||
sr = @clz(su_int(d[high])) - @clz(su_int(n[high]));
|
||||
// 0 <= sr <= n_uword_bits - 1 or sr large
|
||||
if (sr > n_uword_bits - 1) {
|
||||
if (var rem ?= maybe_rem) {
|
||||
test (maybe_rem) |rem| {
|
||||
*rem = *@ptrCast(&du_int, &n[0]);
|
||||
}
|
||||
return 0;
|
||||
@ -198,7 +198,7 @@ export fn __udivmoddi4(a: du_int, b: du_int, maybe_rem: ?&du_int) -> du_int {
|
||||
sr -= 1;
|
||||
}
|
||||
*@ptrCast(&du_int, &q[0]) = (*@ptrCast(&du_int, &q[0]) << 1) | u64(carry);
|
||||
if (var rem ?= maybe_rem) {
|
||||
test (maybe_rem) |rem| {
|
||||
*rem = *@ptrCast(&du_int, &r[0]);
|
||||
}
|
||||
return *@ptrCast(&du_int, &q[0]);
|
||||
|
@ -128,16 +128,6 @@ fn testTruncate(x: u32) -> u8 {
|
||||
@truncate(u8, x)
|
||||
}
|
||||
|
||||
test "assignToIfVarPtr" {
|
||||
var maybe_bool: ?bool = true;
|
||||
|
||||
if (const *b ?= maybe_bool) {
|
||||
*b = false;
|
||||
}
|
||||
|
||||
assert(??maybe_bool == false);
|
||||
}
|
||||
|
||||
fn first4KeysOfHomeRow() -> []const u8 {
|
||||
"aoeu"
|
||||
}
|
||||
|
@ -3,7 +3,7 @@ const assert = @import("std").debug.assert;
|
||||
test "nullableType" {
|
||||
const x : ?bool = @generatedCode(true);
|
||||
|
||||
if (const y ?= x) {
|
||||
test (x) |y| {
|
||||
if (y) {
|
||||
// OK
|
||||
} else {
|
||||
@ -26,16 +26,17 @@ test "nullableType" {
|
||||
assert(num == 13);
|
||||
}
|
||||
|
||||
test "assignToIfVarPtr" {
|
||||
test "test maybe object and get a pointer to the inner value" {
|
||||
var maybe_bool: ?bool = true;
|
||||
|
||||
if (const *b ?= maybe_bool) {
|
||||
test (maybe_bool) |*b| {
|
||||
*b = false;
|
||||
}
|
||||
|
||||
assert(??maybe_bool == false);
|
||||
}
|
||||
|
||||
|
||||
test "rhsMaybeUnwrapReturn" {
|
||||
const x: ?bool = @generatedCode(true);
|
||||
const y = x ?? return;
|
||||
@ -49,7 +50,8 @@ test "maybe return" {
|
||||
|
||||
fn maybeReturnImpl() {
|
||||
assert(??foo(1235));
|
||||
assert(if (const _ ?= foo(null)) false else true);
|
||||
test (foo(null))
|
||||
unreachable;
|
||||
assert(!??foo(1234));
|
||||
}
|
||||
|
||||
@ -64,10 +66,10 @@ test "ifVarMaybePointer" {
|
||||
}
|
||||
fn shouldBeAPlus1(p: &const Particle) -> u64 {
|
||||
var maybe_particle: ?Particle = *p;
|
||||
if (const *particle ?= maybe_particle) {
|
||||
test (maybe_particle) |*particle| {
|
||||
particle.a += 1;
|
||||
}
|
||||
if (const particle ?= maybe_particle) {
|
||||
test (maybe_particle) |particle| {
|
||||
return particle.a;
|
||||
}
|
||||
return 0;
|
||||
@ -114,7 +116,7 @@ fn nullableVoidImpl() {
|
||||
}
|
||||
|
||||
fn bar(x: ?void) -> ?void {
|
||||
if (const _ ?= x) {
|
||||
test (x) {
|
||||
return {};
|
||||
} else {
|
||||
return null;
|
||||
|
@ -7,7 +7,7 @@ test "tryOnErrorUnion" {
|
||||
}
|
||||
|
||||
fn tryOnErrorUnionImpl() {
|
||||
const x = try (const val = returnsTen()) {
|
||||
const x = try (returnsTen()) |val| {
|
||||
val + 1
|
||||
} else |err| switch (err) {
|
||||
error.ItBroke, error.NoMem => 1,
|
||||
@ -51,7 +51,7 @@ fn failIfTrue(ok: bool) -> %void {
|
||||
//fn tryThenNotExecutedWithAssignment() {
|
||||
// @setFnTest(this);
|
||||
//
|
||||
// try (_ = failIfTrue(true)) {
|
||||
// try (failIfTrue(true)) {
|
||||
// unreachable;
|
||||
// } else |err| {
|
||||
// assert(err == error.ItBroke);
|
||||
|
@ -118,92 +118,38 @@ pub fn addCases(cases: &tests.CompileErrorContext) {
|
||||
\\}
|
||||
, ".tmp_source.zig:5:5: error: invalid token: 'var'");
|
||||
|
||||
cases.add("implicit semicolon - if(var) statement",
|
||||
\\export fn entry() {
|
||||
\\ if(_=foo()) {}
|
||||
\\ var good = {};
|
||||
\\ if(_=foo()) ({})
|
||||
\\ var bad = {};
|
||||
\\}
|
||||
, ".tmp_source.zig:5:5: error: invalid token: 'var'");
|
||||
|
||||
cases.add("implicit semicolon - if(var) expression",
|
||||
\\export fn entry() {
|
||||
\\ _ = if(_=foo()) {};
|
||||
\\ var good = {};
|
||||
\\ _ = if(_=foo()) {}
|
||||
\\ var bad = {};
|
||||
\\}
|
||||
, ".tmp_source.zig:5:5: error: invalid token: 'var'");
|
||||
|
||||
cases.add("implicit semicolon - if(var)-else statement",
|
||||
\\export fn entry() {
|
||||
\\ if(_=foo()) {} else {}
|
||||
\\ var good = {};
|
||||
\\ if(_=foo()) ({}) else ({})
|
||||
\\ var bad = {};
|
||||
\\}
|
||||
, ".tmp_source.zig:5:5: error: invalid token: 'var'");
|
||||
|
||||
cases.add("implicit semicolon - if(var)-else expression",
|
||||
\\export fn entry() {
|
||||
\\ _ = if(_=foo()) {} else {};
|
||||
\\ var good = {};
|
||||
\\ _ = if(_=foo()) {} else {}
|
||||
\\ var bad = {};
|
||||
\\}
|
||||
, ".tmp_source.zig:5:5: error: invalid token: 'var'");
|
||||
|
||||
cases.add("implicit semicolon - if(var)-else-if(var) statement",
|
||||
\\export fn entry() {
|
||||
\\ if(_=foo()) {} else if(_=foo()) {}
|
||||
\\ var good = {};
|
||||
\\ if(_=foo()) ({}) else if(_=foo()) ({})
|
||||
\\ var bad = {};
|
||||
\\}
|
||||
, ".tmp_source.zig:5:5: error: invalid token: 'var'");
|
||||
|
||||
cases.add("implicit semicolon - if(var)-else-if(var) expression",
|
||||
\\export fn entry() {
|
||||
\\ _ = if(_=foo()) {} else if(_=foo()) {};
|
||||
\\ var good = {};
|
||||
\\ _ = if(_=foo()) {} else if(_=foo()) {}
|
||||
\\ var bad = {};
|
||||
\\}
|
||||
, ".tmp_source.zig:5:5: error: invalid token: 'var'");
|
||||
|
||||
cases.add("implicit semicolon - if(var)-else-if(var)-else statement",
|
||||
\\export fn entry() {
|
||||
\\ if(_=foo()) {} else if(_=foo()) {} else {}
|
||||
\\ var good = {};
|
||||
\\ if(_=foo()) ({}) else if(_=foo()) ({}) else ({})
|
||||
\\ var bad = {};
|
||||
\\}
|
||||
, ".tmp_source.zig:5:5: error: invalid token: 'var'");
|
||||
|
||||
cases.add("implicit semicolon - if(var)-else-if(var)-else expression",
|
||||
\\export fn entry() {
|
||||
\\ _ = if(_=foo()) {} else if(_=foo()) {} else {};
|
||||
\\ var good = {};
|
||||
\\ _ = if(_=foo()) {} else if(_=foo()) {} else {}
|
||||
\\ var bad = {};
|
||||
\\}
|
||||
, ".tmp_source.zig:5:5: error: invalid token: 'var'");
|
||||
|
||||
cases.add("implicit semicolon - try statement",
|
||||
\\export fn entry() {
|
||||
\\ try (_ = foo()) {}
|
||||
\\ try (foo()) {}
|
||||
\\ var good = {};
|
||||
\\ try (_ = foo()) ({})
|
||||
\\ try (foo()) ({})
|
||||
\\ var bad = {};
|
||||
\\}
|
||||
, ".tmp_source.zig:5:5: error: invalid token: 'var'");
|
||||
|
||||
cases.add("implicit semicolon - try expression",
|
||||
\\export fn entry() {
|
||||
\\ _ = try (_ = foo()) {};
|
||||
\\ _ = try (foo()) {};
|
||||
\\ var good = {};
|
||||
\\ _ = try (_ = foo()) {}
|
||||
\\ _ = try (foo()) {}
|
||||
\\ var bad = {};
|
||||
\\}
|
||||
, ".tmp_source.zig:5:5: error: invalid token: 'var'");
|
||||
|
||||
cases.add("implicit semicolon - test statement",
|
||||
\\export fn entry() {
|
||||
\\ test (foo()) {}
|
||||
\\ var good = {};
|
||||
\\ test (foo()) ({})
|
||||
\\ var bad = {};
|
||||
\\}
|
||||
, ".tmp_source.zig:5:5: error: invalid token: 'var'");
|
||||
|
||||
cases.add("implicit semicolon - test expression",
|
||||
\\export fn entry() {
|
||||
\\ _ = test (foo()) {};
|
||||
\\ var good = {};
|
||||
\\ _ = test (foo()) {}
|
||||
\\ var bad = {};
|
||||
\\}
|
||||
, ".tmp_source.zig:5:5: error: invalid token: 'var'");
|
||||
@ -554,9 +500,9 @@ pub fn addCases(cases: &tests.CompileErrorContext) {
|
||||
|
||||
cases.add("invalid maybe type",
|
||||
\\export fn f() {
|
||||
\\ if (const x ?= true) { }
|
||||
\\ test (true) |x| { }
|
||||
\\}
|
||||
, ".tmp_source.zig:2:20: error: expected nullable type, found 'bool'");
|
||||
, ".tmp_source.zig:2:11: error: expected nullable type, found 'bool'");
|
||||
|
||||
cases.add("cast unreachable",
|
||||
\\fn f() -> i32 {
|
||||
|
@ -350,7 +350,7 @@ pub const CompareOutputContext = struct {
|
||||
Special.Asm => {
|
||||
const obj_path = %%os.path.join(b.allocator, "test_artifacts", "test.o");
|
||||
const annotated_case_name = %%fmt.allocPrint(self.b.allocator, "assemble-and-link {}", case.name);
|
||||
if (const filter ?= self.test_filter) {
|
||||
test (self.test_filter) |filter| {
|
||||
if (mem.indexOf(u8, annotated_case_name, filter) == null)
|
||||
return;
|
||||
}
|
||||
@ -379,7 +379,7 @@ pub const CompareOutputContext = struct {
|
||||
for ([]bool{false, true}) |release| {
|
||||
const annotated_case_name = %%fmt.allocPrint(self.b.allocator, "{} {} ({})",
|
||||
"compare-output", case.name, if (release) "release" else "debug");
|
||||
if (const filter ?= self.test_filter) {
|
||||
test (self.test_filter) |filter| {
|
||||
if (mem.indexOf(u8, annotated_case_name, filter) == null)
|
||||
continue;
|
||||
}
|
||||
@ -407,7 +407,7 @@ pub const CompareOutputContext = struct {
|
||||
Special.DebugSafety => {
|
||||
const obj_path = %%os.path.join(b.allocator, "test_artifacts", "test.o");
|
||||
const annotated_case_name = %%fmt.allocPrint(self.b.allocator, "debug-safety {}", case.name);
|
||||
if (const filter ?= self.test_filter) {
|
||||
test (self.test_filter) |filter| {
|
||||
if (mem.indexOf(u8, annotated_case_name, filter) == null)
|
||||
return;
|
||||
}
|
||||
@ -626,7 +626,7 @@ pub const CompileErrorContext = struct {
|
||||
for ([]bool{false, true}) |release| {
|
||||
const annotated_case_name = %%fmt.allocPrint(self.b.allocator, "compile-error {} ({})",
|
||||
case.name, if (release) "release" else "debug");
|
||||
if (const filter ?= self.test_filter) {
|
||||
test (self.test_filter) |filter| {
|
||||
if (mem.indexOf(u8, annotated_case_name, filter) == null)
|
||||
continue;
|
||||
}
|
||||
@ -661,7 +661,7 @@ pub const BuildExamplesContext = struct {
|
||||
const b = self.b;
|
||||
|
||||
const annotated_case_name = b.fmt("build {}", build_file);
|
||||
if (const filter ?= self.test_filter) {
|
||||
test (self.test_filter) |filter| {
|
||||
if (mem.indexOf(u8, annotated_case_name, filter) == null)
|
||||
return;
|
||||
}
|
||||
@ -692,7 +692,7 @@ pub const BuildExamplesContext = struct {
|
||||
for ([]bool{false, true}) |release| {
|
||||
const annotated_case_name = %%fmt.allocPrint(self.b.allocator, "build {} ({})",
|
||||
root_src, if (release) "release" else "debug");
|
||||
if (const filter ?= self.test_filter) {
|
||||
test (self.test_filter) |filter| {
|
||||
if (mem.indexOf(u8, annotated_case_name, filter) == null)
|
||||
continue;
|
||||
}
|
||||
@ -880,7 +880,7 @@ pub const ParseHContext = struct {
|
||||
const b = self.b;
|
||||
|
||||
const annotated_case_name = %%fmt.allocPrint(self.b.allocator, "parseh {}", case.name);
|
||||
if (const filter ?= self.test_filter) {
|
||||
test (self.test_filter) |filter| {
|
||||
if (mem.indexOf(u8, annotated_case_name, filter) == null)
|
||||
return;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user