authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-04-21 16:46:33-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-04-21 16:46:33-04:00
log0cce115476628ad1bb266309225efa5714d56321
tree47b49a58d1ff23ed74ea599961b5f9bc92e6fadc
parentd5346d7a8045549819abeb331d775aa2a10ca53b

update syntax for try and nullable unwrapping

closes #285

18 files changed, 208 insertions(+), 284 deletions(-)

doc/langref.md+4-6
...@@ -69,7 +69,7 @@ AssignmentExpression = UnwrapExpression AssignmentOperator UnwrapExpression | Un...@@ -69,7 +69,7 @@ AssignmentExpression = UnwrapExpression AssignmentOperator UnwrapExpression | Un
6969
70AssignmentOperator = "=" | "*=" | "/=" | "%=" | "+=" | "-=" | "<<=" | ">>=" | "&=" | "^=" | "|=" | "*%=" | "+%=" | "-%=" | "<<%="70AssignmentOperator = "=" | "*=" | "/=" | "%=" | "+=" | "-=" | "<<=" | ">>=" | "&=" | "^=" | "|=" | "*%=" | "+%=" | "-%=" | "<<%="
7171
72BlockExpression(body) = Block | IfExpression(body) | TryExpression(body) | WhileExpression(body) | ForExpression(body) | SwitchExpression | CompTimeExpression(body)72BlockExpression(body) = Block | IfExpression(body) | TryExpression(body) | TestExpression(body) | WhileExpression(body) | ForExpression(body) | SwitchExpression | CompTimeExpression(body)
7373
74CompTimeExpression(body) = "comptime" body74CompTimeExpression(body) = "comptime" body
7575
...@@ -89,13 +89,11 @@ ReturnExpression = option("%") "return" option(Expression)...@@ -89,13 +89,11 @@ ReturnExpression = option("%") "return" option(Expression)
8989
90Defer(body) = option("%") "defer" body90Defer(body) = option("%") "defer" body
9191
92IfExpression(body) = IfVarExpression(body) | IfBoolExpression(body)92IfExpression(body) = "if" "(" Expression ")" body option("else" BlockExpression(body))
9393
94IfBoolExpression(body) = "if" "(" Expression ")" body option("else" BlockExpression(body))94TryExpression(body) = "try" "(" Expression ")" option("|" option("*") Symbol "|") body option("else" option("|" Symbol "|") BlockExpression(body))
9595
96TryExpression(body) = "try" "(" option(("const" | "var") option("*") Symbol "=") Expression ")" body option("else" option("|" Symbol "|") BlockExpression(body))96TestExpression(body) = "test" "(" Expression ")" option("|" option("*") Symbol "|") body option("else" option("|" Symbol "|") BlockExpression(body))
97
98IfVarExpression(body) = "if" "(" ("const" | "var") option("*") Symbol option(":" TypeExpr) "?=" Expression ")" body Option("else" BlockExpression(body))
9997
100BoolAndExpression = ComparisonExpression "and" BoolAndExpression | ComparisonExpression98BoolAndExpression = ComparisonExpression "and" BoolAndExpression | ComparisonExpression
10199
src/all_types.hpp+7-7
...@@ -344,7 +344,6 @@ enum NodeType {...@@ -344,7 +344,6 @@ enum NodeType {
344 NodeTypeThisLiteral,344 NodeTypeThisLiteral,
345 NodeTypeUnreachable,345 NodeTypeUnreachable,
346 NodeTypeIfBoolExpr,346 NodeTypeIfBoolExpr,
347 NodeTypeIfVarExpr,
348 NodeTypeWhileExpr,347 NodeTypeWhileExpr,
349 NodeTypeForExpr,348 NodeTypeForExpr,
350 NodeTypeSwitchExpr,349 NodeTypeSwitchExpr,
...@@ -364,6 +363,7 @@ enum NodeType {...@@ -364,6 +363,7 @@ enum NodeType {
364 NodeTypeErrorType,363 NodeTypeErrorType,
365 NodeTypeVarLiteral,364 NodeTypeVarLiteral,
366 NodeTypeTryExpr,365 NodeTypeTryExpr,
366 NodeTypeTestExpr,
367 NodeTypeInlineExpr,367 NodeTypeInlineExpr,
368};368};
369369
...@@ -577,7 +577,6 @@ struct AstNodeIfBoolExpr {...@@ -577,7 +577,6 @@ struct AstNodeIfBoolExpr {
577};577};
578578
579struct AstNodeTryExpr {579struct AstNodeTryExpr {
580 bool var_is_const;
581 Buf *var_symbol;580 Buf *var_symbol;
582 bool var_is_ptr;581 bool var_is_ptr;
583 AstNode *target_node;582 AstNode *target_node;
...@@ -586,11 +585,12 @@ struct AstNodeTryExpr {...@@ -586,11 +585,12 @@ struct AstNodeTryExpr {
586 Buf *err_symbol;585 Buf *err_symbol;
587};586};
588587
589struct AstNodeIfVarExpr {588struct AstNodeTestExpr {
590 AstNodeVariableDeclaration var_decl;589 Buf *var_symbol;
591 AstNode *then_block;
592 AstNode *else_node; // null, block node, or other if expr node
593 bool var_is_ptr;590 bool var_is_ptr;
591 AstNode *target_node;
592 AstNode *then_node;
593 AstNode *else_node; // null, block node, or other if expr node
594};594};
595595
596struct AstNodeWhileExpr {596struct AstNodeWhileExpr {
...@@ -807,8 +807,8 @@ struct AstNode {...@@ -807,8 +807,8 @@ struct AstNode {
807 AstNodeSliceExpr slice_expr;807 AstNodeSliceExpr slice_expr;
808 AstNodeUse use;808 AstNodeUse use;
809 AstNodeIfBoolExpr if_bool_expr;809 AstNodeIfBoolExpr if_bool_expr;
810 AstNodeIfVarExpr if_var_expr;
811 AstNodeTryExpr try_expr;810 AstNodeTryExpr try_expr;
811 AstNodeTestExpr test_expr;
812 AstNodeWhileExpr while_expr;812 AstNodeWhileExpr while_expr;
813 AstNodeForExpr for_expr;813 AstNodeForExpr for_expr;
814 AstNodeSwitchExpr switch_expr;814 AstNodeSwitchExpr switch_expr;
src/analyze.cpp+1-1
...@@ -2099,7 +2099,6 @@ void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node) {...@@ -2099,7 +2099,6 @@ void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node) {
2099 case NodeTypeSymbol:2099 case NodeTypeSymbol:
2100 case NodeTypePrefixOpExpr:2100 case NodeTypePrefixOpExpr:
2101 case NodeTypeIfBoolExpr:2101 case NodeTypeIfBoolExpr:
2102 case NodeTypeIfVarExpr:
2103 case NodeTypeWhileExpr:2102 case NodeTypeWhileExpr:
2104 case NodeTypeForExpr:2103 case NodeTypeForExpr:
2105 case NodeTypeSwitchExpr:2104 case NodeTypeSwitchExpr:
...@@ -2119,6 +2118,7 @@ void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node) {...@@ -2119,6 +2118,7 @@ void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node) {
2119 case NodeTypeErrorType:2118 case NodeTypeErrorType:
2120 case NodeTypeVarLiteral:2119 case NodeTypeVarLiteral:
2121 case NodeTypeTryExpr:2120 case NodeTypeTryExpr:
2121 case NodeTypeTestExpr:
2122 case NodeTypeInlineExpr:2122 case NodeTypeInlineExpr:
2123 zig_unreachable();2123 zig_unreachable();
2124 }2124 }
src/ast_render.cpp+23-28
...@@ -192,8 +192,6 @@ static const char *node_type_str(NodeType node_type) {...@@ -192,8 +192,6 @@ static const char *node_type_str(NodeType node_type) {
192 return "ThisLiteral";192 return "ThisLiteral";
193 case NodeTypeIfBoolExpr:193 case NodeTypeIfBoolExpr:
194 return "IfBoolExpr";194 return "IfBoolExpr";
195 case NodeTypeIfVarExpr:
196 return "IfVarExpr";
197 case NodeTypeWhileExpr:195 case NodeTypeWhileExpr:
198 return "WhileExpr";196 return "WhileExpr";
199 case NodeTypeForExpr:197 case NodeTypeForExpr:
...@@ -236,6 +234,8 @@ static const char *node_type_str(NodeType node_type) {...@@ -236,6 +234,8 @@ static const char *node_type_str(NodeType node_type) {
236 return "VarLiteral";234 return "VarLiteral";
237 case NodeTypeTryExpr:235 case NodeTypeTryExpr:
238 return "TryExpr";236 return "TryExpr";
237 case NodeTypeTestExpr:
238 return "TestExpr";
239 case NodeTypeInlineExpr:239 case NodeTypeInlineExpr:
240 return "InlineExpr";240 return "InlineExpr";
241 }241 }
...@@ -760,38 +760,16 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {...@@ -760,38 +760,16 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {
760 fprintf(ar->f, "null");760 fprintf(ar->f, "null");
761 break;761 break;
762 }762 }
763 case NodeTypeIfVarExpr:
764 {
765 AstNodeVariableDeclaration *var_decl = &node->data.if_var_expr.var_decl;
766 const char *var_str = var_decl->is_const ? "const" : "var";
767 const char *var_name = buf_ptr(var_decl->symbol);
768 const char *ptr_str = node->data.if_var_expr.var_is_ptr ? "*" : "";
769 fprintf(ar->f, "if (%s %s%s", var_str, ptr_str, var_name);
770 if (var_decl->type) {
771 fprintf(ar->f, ": ");
772 render_node_ungrouped(ar, var_decl->type);
773 }
774 fprintf(ar->f, " ?= ");
775 render_node_grouped(ar, var_decl->expr);
776 fprintf(ar->f, ") ");
777 render_node_grouped(ar, node->data.if_var_expr.then_block);
778 if (node->data.if_var_expr.else_node) {
779 fprintf(ar->f, " else ");
780 render_node_grouped(ar, node->data.if_var_expr.else_node);
781 }
782 break;
783 }
784 case NodeTypeTryExpr:763 case NodeTypeTryExpr:
785 {764 {
786 fprintf(ar->f, "try (");765 fprintf(ar->f, "try (");
766 render_node_grouped(ar, node->data.try_expr.target_node);
767 fprintf(ar->f, ") ");
787 if (node->data.try_expr.var_symbol) {768 if (node->data.try_expr.var_symbol) {
788 const char *var_str = node->data.try_expr.var_is_const ? "const" : "var";
789 const char *var_name = buf_ptr(node->data.try_expr.var_symbol);
790 const char *ptr_str = node->data.try_expr.var_is_ptr ? "*" : "";769 const char *ptr_str = node->data.try_expr.var_is_ptr ? "*" : "";
791 fprintf(ar->f, "%s %s%s = ", var_str, ptr_str, var_name);770 const char *var_name = buf_ptr(node->data.try_expr.var_symbol);
771 fprintf(ar->f, "|%s%s| ", ptr_str, var_name);
792 }772 }
793 render_node_grouped(ar, node->data.try_expr.target_node);
794 fprintf(ar->f, ") ");
795 render_node_grouped(ar, node->data.try_expr.then_node);773 render_node_grouped(ar, node->data.try_expr.then_node);
796 if (node->data.try_expr.else_node) {774 if (node->data.try_expr.else_node) {
797 fprintf(ar->f, " else ");775 fprintf(ar->f, " else ");
...@@ -802,6 +780,23 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {...@@ -802,6 +780,23 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {
802 }780 }
803 break;781 break;
804 }782 }
783 case NodeTypeTestExpr:
784 {
785 fprintf(ar->f, "test (");
786 render_node_grouped(ar, node->data.test_expr.target_node);
787 fprintf(ar->f, ") ");
788 if (node->data.test_expr.var_symbol) {
789 const char *ptr_str = node->data.test_expr.var_is_ptr ? "*" : "";
790 const char *var_name = buf_ptr(node->data.test_expr.var_symbol);
791 fprintf(ar->f, "|%s%s| ", ptr_str, var_name);
792 }
793 render_node_grouped(ar, node->data.test_expr.then_node);
794 if (node->data.test_expr.else_node) {
795 fprintf(ar->f, " else ");
796 render_node_grouped(ar, node->data.test_expr.else_node);
797 }
798 break;
799 }
805 case NodeTypeSwitchExpr:800 case NodeTypeSwitchExpr:
806 {801 {
807 AstNodeSwitchExpr *switch_expr = &node->data.switch_expr;802 AstNodeSwitchExpr *switch_expr = &node->data.switch_expr;
src/ir.cpp+26-24
...@@ -4941,14 +4941,14 @@ static IrInstruction *ir_gen_asm_expr(IrBuilder *irb, Scope *scope, AstNode *nod...@@ -4941,14 +4941,14 @@ static IrInstruction *ir_gen_asm_expr(IrBuilder *irb, Scope *scope, AstNode *nod
4941 return ir_build_asm(irb, scope, node, input_list, output_types, output_vars, return_count, is_volatile);4941 return ir_build_asm(irb, scope, node, input_list, output_types, output_vars, return_count, is_volatile);
4942}4942}
49434943
4944static IrInstruction *ir_gen_if_var_expr(IrBuilder *irb, Scope *scope, AstNode *node) {4944static IrInstruction *ir_gen_test_expr(IrBuilder *irb, Scope *scope, AstNode *node) {
4945 assert(node->type == NodeTypeIfVarExpr);4945 assert(node->type == NodeTypeTestExpr);
49464946
4947 AstNodeVariableDeclaration *var_decl = &node->data.if_var_expr.var_decl;4947 Buf *var_symbol = node->data.test_expr.var_symbol;
4948 AstNode *expr_node = var_decl->expr;4948 AstNode *expr_node = node->data.test_expr.target_node;
4949 AstNode *then_node = node->data.if_var_expr.then_block;4949 AstNode *then_node = node->data.test_expr.then_node;
4950 AstNode *else_node = node->data.if_var_expr.else_node;4950 AstNode *else_node = node->data.test_expr.else_node;
4951 bool var_is_ptr = node->data.if_var_expr.var_is_ptr;4951 bool var_is_ptr = node->data.test_expr.var_is_ptr;
49524952
4953 IrInstruction *maybe_val_ptr = ir_gen_node_extra(irb, expr_node, scope, LVAL_PTR);4953 IrInstruction *maybe_val_ptr = ir_gen_node_extra(irb, expr_node, scope, LVAL_PTR);
4954 if (maybe_val_ptr == irb->codegen->invalid_instruction)4954 if (maybe_val_ptr == irb->codegen->invalid_instruction)
...@@ -4970,21 +4970,23 @@ static IrInstruction *ir_gen_if_var_expr(IrBuilder *irb, Scope *scope, AstNode *...@@ -4970,21 +4970,23 @@ static IrInstruction *ir_gen_if_var_expr(IrBuilder *irb, Scope *scope, AstNode *
4970 ir_build_cond_br(irb, scope, node, is_non_null, then_block, else_block, is_comptime);4970 ir_build_cond_br(irb, scope, node, is_non_null, then_block, else_block, is_comptime);
49714971
4972 ir_set_cursor_at_end(irb, then_block);4972 ir_set_cursor_at_end(irb, then_block);
4973 IrInstruction *var_type = nullptr;4973
4974 if (var_decl->type) {4974 Scope *var_scope;
4975 var_type = ir_gen_node(irb, var_decl->type, scope);4975 if (var_symbol) {
4976 if (var_type == irb->codegen->invalid_instruction)4976 IrInstruction *var_type = nullptr;
4977 return irb->codegen->invalid_instruction;4977 bool is_shadowable = false;
4978 bool is_const = true;
4979 VariableTableEntry *var = ir_create_var(irb, node, scope,
4980 var_symbol, is_const, is_const, is_shadowable, is_comptime);
4981
4982 IrInstruction *var_ptr_value = ir_build_unwrap_maybe(irb, scope, node, maybe_val_ptr, false);
4983 IrInstruction *var_value = var_is_ptr ? var_ptr_value : ir_build_load_ptr(irb, scope, node, var_ptr_value);
4984 ir_build_var_decl(irb, scope, node, var, var_type, var_value);
4985 var_scope = var->child_scope;
4986 } else {
4987 var_scope = scope;
4978 }4988 }
4979 bool is_shadowable = false;4989 IrInstruction *then_expr_result = ir_gen_node(irb, then_node, var_scope);
4980 bool is_const = var_decl->is_const;
4981 VariableTableEntry *var = ir_create_var(irb, node, scope,
4982 var_decl->symbol, is_const, is_const, is_shadowable, is_comptime);
4983
4984 IrInstruction *var_ptr_value = ir_build_unwrap_maybe(irb, scope, node, maybe_val_ptr, false);
4985 IrInstruction *var_value = var_is_ptr ? var_ptr_value : ir_build_load_ptr(irb, scope, node, var_ptr_value);
4986 ir_build_var_decl(irb, scope, node, var, var_type, var_value);
4987 IrInstruction *then_expr_result = ir_gen_node(irb, then_node, var->child_scope);
4988 if (then_expr_result == irb->codegen->invalid_instruction)4990 if (then_expr_result == irb->codegen->invalid_instruction)
4989 return then_expr_result;4991 return then_expr_result;
4990 IrBasicBlock *after_then_block = irb->current_basic_block;4992 IrBasicBlock *after_then_block = irb->current_basic_block;
...@@ -5022,7 +5024,7 @@ static IrInstruction *ir_gen_try_expr(IrBuilder *irb, Scope *scope, AstNode *nod...@@ -5022,7 +5024,7 @@ static IrInstruction *ir_gen_try_expr(IrBuilder *irb, Scope *scope, AstNode *nod
5022 AstNode *then_node = node->data.try_expr.then_node;5024 AstNode *then_node = node->data.try_expr.then_node;
5023 AstNode *else_node = node->data.try_expr.else_node;5025 AstNode *else_node = node->data.try_expr.else_node;
5024 bool var_is_ptr = node->data.try_expr.var_is_ptr;5026 bool var_is_ptr = node->data.try_expr.var_is_ptr;
5025 bool var_is_const = node->data.try_expr.var_is_const;5027 bool var_is_const = true;
5026 Buf *var_symbol = node->data.try_expr.var_symbol;5028 Buf *var_symbol = node->data.try_expr.var_symbol;
5027 Buf *err_symbol = node->data.try_expr.err_symbol;5029 Buf *err_symbol = node->data.try_expr.err_symbol;
50285030
...@@ -5659,10 +5661,10 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop...@@ -5659,10 +5661,10 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop
5659 return ir_lval_wrap(irb, scope, ir_gen_null_literal(irb, scope, node), lval);5661 return ir_lval_wrap(irb, scope, ir_gen_null_literal(irb, scope, node), lval);
5660 case NodeTypeVarLiteral:5662 case NodeTypeVarLiteral:
5661 return ir_lval_wrap(irb, scope, ir_gen_var_literal(irb, scope, node), lval);5663 return ir_lval_wrap(irb, scope, ir_gen_var_literal(irb, scope, node), lval);
5662 case NodeTypeIfVarExpr:
5663 return ir_lval_wrap(irb, scope, ir_gen_if_var_expr(irb, scope, node), lval);
5664 case NodeTypeTryExpr:5664 case NodeTypeTryExpr:
5665 return ir_lval_wrap(irb, scope, ir_gen_try_expr(irb, scope, node), lval);5665 return ir_lval_wrap(irb, scope, ir_gen_try_expr(irb, scope, node), lval);
5666 case NodeTypeTestExpr:
5667 return ir_lval_wrap(irb, scope, ir_gen_test_expr(irb, scope, node), lval);
5666 case NodeTypeSwitchExpr:5668 case NodeTypeSwitchExpr:
5667 return ir_lval_wrap(irb, scope, ir_gen_switch_expr(irb, scope, node), lval);5669 return ir_lval_wrap(irb, scope, ir_gen_switch_expr(irb, scope, node), lval);
5668 case NodeTypeGoto:5670 case NodeTypeGoto:
src/parser.cpp+81-91
...@@ -640,7 +640,7 @@ static AstNode *ast_parse_comptime_expr(ParseContext *pc, size_t *token_index, b...@@ -640,7 +640,7 @@ static AstNode *ast_parse_comptime_expr(ParseContext *pc, size_t *token_index, b
640}640}
641641
642/*642/*
643TryExpression(body) = "try" "(" option(("const" | "var") option("*") Symbol "=") Expression ")" body option("else" option("|" Symbol "|") body)643TryExpression(body) = "try" "(" Expression ")" option("|" option("*") Symbol "|") body option("else" option("|" Symbol "|") BlockExpression(body))
644*/644*/
645static AstNode *ast_parse_try_expr(ParseContext *pc, size_t *token_index, bool mandatory) {645static AstNode *ast_parse_try_expr(ParseContext *pc, size_t *token_index, bool mandatory) {
646 Token *try_token = &pc->tokens->at(*token_index);646 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...@@ -656,38 +656,25 @@ static AstNode *ast_parse_try_expr(ParseContext *pc, size_t *token_index, bool m
656 AstNode *node = ast_create_node(pc, NodeTypeTryExpr, try_token);656 AstNode *node = ast_create_node(pc, NodeTypeTryExpr, try_token);
657657
658 ast_eat_token(pc, token_index, TokenIdLParen);658 ast_eat_token(pc, token_index, TokenIdLParen);
659 node->data.try_expr.target_node = ast_parse_expression(pc, token_index, true);
660 ast_eat_token(pc, token_index, TokenIdRParen);
659661
660 Token *var_token = &pc->tokens->at(*token_index);662 Token *open_bar_tok = &pc->tokens->at(*token_index);
661 bool have_vars;663 if (open_bar_tok->id == TokenIdBinOr) {
662 if (var_token->id == TokenIdKeywordVar) {
663 node->data.try_expr.var_is_const = false;
664 *token_index += 1;
665 have_vars = true;
666 } else if (var_token->id == TokenIdKeywordConst) {
667 node->data.try_expr.var_is_const = true;
668 *token_index += 1;664 *token_index += 1;
669 have_vars = true;
670 } else {
671 have_vars = false;
672 }
673665
674 if (have_vars) {666 Token *star_tok = &pc->tokens->at(*token_index);
675 Token *star_token = &pc->tokens->at(*token_index);667 if (star_tok->id == TokenIdStar) {
676 if (star_token->id == TokenIdStar) {
677 node->data.try_expr.var_is_ptr = true;
678 *token_index += 1;668 *token_index += 1;
669 node->data.try_expr.var_is_ptr = true;
679 }670 }
680671
681 Token *var_name_tok = ast_eat_token(pc, token_index, TokenIdSymbol);672 Token *var_name_tok = ast_eat_token(pc, token_index, TokenIdSymbol);
682 node->data.try_expr.var_symbol = token_buf(var_name_tok);673 node->data.try_expr.var_symbol = token_buf(var_name_tok);
683674
684 ast_eat_token(pc, token_index, TokenIdEq);675 ast_eat_token(pc, token_index, TokenIdBinOr);
685 }676 }
686677
687 node->data.try_expr.target_node = ast_parse_expression(pc, token_index, true);
688
689 ast_eat_token(pc, token_index, TokenIdRParen);
690
691 node->data.try_expr.then_node = ast_parse_block_or_expression(pc, token_index, true);678 node->data.try_expr.then_node = ast_parse_block_or_expression(pc, token_index, true);
692679
693 Token *else_token = &pc->tokens->at(*token_index);680 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...@@ -709,6 +696,53 @@ static AstNode *ast_parse_try_expr(ParseContext *pc, size_t *token_index, bool m
709 return node;696 return node;
710}697}
711698
699/*
700TestExpression(body) = "test" "(" Expression ")" option("|" option("*") Symbol "|") body option("else" BlockExpression(body))
701*/
702static AstNode *ast_parse_test_expr(ParseContext *pc, size_t *token_index, bool mandatory) {
703 Token *test_token = &pc->tokens->at(*token_index);
704 if (test_token->id == TokenIdKeywordTest) {
705 *token_index += 1;
706 } else if (mandatory) {
707 ast_expect_token(pc, test_token, TokenIdKeywordTest);
708 zig_unreachable();
709 } else {
710 return nullptr;
711 }
712
713 AstNode *node = ast_create_node(pc, NodeTypeTestExpr, test_token);
714
715 ast_eat_token(pc, token_index, TokenIdLParen);
716 node->data.test_expr.target_node = ast_parse_expression(pc, token_index, true);
717 ast_eat_token(pc, token_index, TokenIdRParen);
718
719 Token *open_bar_tok = &pc->tokens->at(*token_index);
720 if (open_bar_tok->id == TokenIdBinOr) {
721 *token_index += 1;
722
723 Token *star_tok = &pc->tokens->at(*token_index);
724 if (star_tok->id == TokenIdStar) {
725 *token_index += 1;
726 node->data.test_expr.var_is_ptr = true;
727 }
728
729 Token *var_name_tok = ast_eat_token(pc, token_index, TokenIdSymbol);
730 node->data.test_expr.var_symbol = token_buf(var_name_tok);
731
732 ast_eat_token(pc, token_index, TokenIdBinOr);
733 }
734
735 node->data.test_expr.then_node = ast_parse_block_or_expression(pc, token_index, true);
736
737 Token *else_token = &pc->tokens->at(*token_index);
738 if (else_token->id == TokenIdKeywordElse) {
739 *token_index += 1;
740 node->data.test_expr.else_node = ast_parse_block_expr_or_expression(pc, token_index, true);
741 }
742
743 return node;
744}
745
712/*746/*
713PrimaryExpression = Number | String | CharLiteral | KeywordLiteral | GroupedExpression | GotoExpression | BlockExpression(BlockOrExpression) | Symbol | ("@" Symbol FnCallExpression) | ArrayType | (option("extern") FnProto) | AsmExpression | ("error" "." Symbol) | ContainerDecl747PrimaryExpression = Number | String | CharLiteral | KeywordLiteral | GroupedExpression | GotoExpression | BlockExpression(BlockOrExpression) | Symbol | ("@" Symbol FnCallExpression) | ArrayType | (option("extern") FnProto) | AsmExpression | ("error" "." Symbol) | ContainerDecl
714KeywordLiteral = "true" | "false" | "null" | "break" | "continue" | "undefined" | "error" | "this" | "unreachable"748KeywordLiteral = "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...@@ -1405,9 +1439,7 @@ static AstNode *ast_parse_bool_and_expr(ParseContext *pc, size_t *token_index, b
1405}1439}
14061440
1407/*1441/*
1408IfExpression(body) = IfVarExpression(body) | IfBoolExpression(body)1442IfExpression(body) = "if" "(" Expression ")" body option("else" BlockExpression(body))
1409IfBoolExpression(body) = "if" "(" Expression ")" body option("else" body)
1410IfVarExpression(body) = "if" "(" ("const" | "var") option("*") Symbol option(":" TypeExpr) "?=" Expression ")" body Option("else" body)
1411*/1443*/
1412static AstNode *ast_parse_if_expr(ParseContext *pc, size_t *token_index, bool mandatory) {1444static AstNode *ast_parse_if_expr(ParseContext *pc, size_t *token_index, bool mandatory) {
1413 Token *if_token = &pc->tokens->at(*token_index);1445 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...@@ -1423,63 +1455,18 @@ static AstNode *ast_parse_if_expr(ParseContext *pc, size_t *token_index, bool ma
14231455
1424 ast_eat_token(pc, token_index, TokenIdLParen);1456 ast_eat_token(pc, token_index, TokenIdLParen);
14251457
1426 Token *token = &pc->tokens->at(*token_index);1458 AstNode *node = ast_create_node(pc, NodeTypeIfBoolExpr, if_token);
1427 if (token->id == TokenIdKeywordConst || token->id == TokenIdKeywordVar) {1459 node->data.if_bool_expr.condition = ast_parse_expression(pc, token_index, true);
1428 AstNode *node = ast_create_node(pc, NodeTypeIfVarExpr, if_token);1460 ast_eat_token(pc, token_index, TokenIdRParen);
1429 node->data.if_var_expr.var_decl.is_const = (token->id == TokenIdKeywordConst);1461 node->data.if_bool_expr.then_block = ast_parse_block_or_expression(pc, token_index, true);
1430 *token_index += 1;
1431
1432 Token *star_or_symbol = &pc->tokens->at(*token_index);
1433 if (star_or_symbol->id == TokenIdStar) {
1434 *token_index += 1;
1435 node->data.if_var_expr.var_is_ptr = true;
1436 Token *name_token = ast_eat_token(pc, token_index, TokenIdSymbol);
1437 node->data.if_var_expr.var_decl.symbol = token_buf(name_token);
1438 } else if (star_or_symbol->id == TokenIdSymbol) {
1439 *token_index += 1;
1440 node->data.if_var_expr.var_decl.symbol = token_buf(star_or_symbol);
1441 } else {
1442 ast_invalid_token_error(pc, star_or_symbol);
1443 }
1444
1445
1446 Token *eq_or_colon = &pc->tokens->at(*token_index);
1447 if (eq_or_colon->id == TokenIdMaybeAssign) {
1448 *token_index += 1;
1449 node->data.if_var_expr.var_decl.expr = ast_parse_expression(pc, token_index, true);
1450 } else if (eq_or_colon->id == TokenIdColon) {
1451 *token_index += 1;
1452 node->data.if_var_expr.var_decl.type = ast_parse_type_expr(pc, token_index, true);
1453
1454 ast_eat_token(pc, token_index, TokenIdMaybeAssign);
1455 node->data.if_var_expr.var_decl.expr = ast_parse_expression(pc, token_index, true);
1456 } else {
1457 ast_invalid_token_error(pc, eq_or_colon);
1458 }
1459 ast_eat_token(pc, token_index, TokenIdRParen);
1460 node->data.if_var_expr.then_block = ast_parse_block_or_expression(pc, token_index, true);
1461
1462 Token *else_token = &pc->tokens->at(*token_index);
1463 if (else_token->id == TokenIdKeywordElse) {
1464 *token_index += 1;
1465 node->data.if_var_expr.else_node = ast_parse_block_expr_or_expression(pc, token_index, true);
1466 }
1467
1468 return node;
1469 } else {
1470 AstNode *node = ast_create_node(pc, NodeTypeIfBoolExpr, if_token);
1471 node->data.if_bool_expr.condition = ast_parse_expression(pc, token_index, true);
1472 ast_eat_token(pc, token_index, TokenIdRParen);
1473 node->data.if_bool_expr.then_block = ast_parse_block_or_expression(pc, token_index, true);
1474
1475 Token *else_token = &pc->tokens->at(*token_index);
1476 if (else_token->id == TokenIdKeywordElse) {
1477 *token_index += 1;
1478 node->data.if_bool_expr.else_node = ast_parse_block_expr_or_expression(pc, token_index, true);
1479 }
14801462
1481 return node;1463 Token *else_token = &pc->tokens->at(*token_index);
1464 if (else_token->id == TokenIdKeywordElse) {
1465 *token_index += 1;
1466 node->data.if_bool_expr.else_node = ast_parse_block_expr_or_expression(pc, token_index, true);
1482 }1467 }
1468
1469 return node;
1483}1470}
14841471
1485/*1472/*
...@@ -1862,7 +1849,7 @@ static AstNode *ast_parse_switch_expr(ParseContext *pc, size_t *token_index, boo...@@ -1862,7 +1849,7 @@ static AstNode *ast_parse_switch_expr(ParseContext *pc, size_t *token_index, boo
1862}1849}
18631850
1864/*1851/*
1865BlockExpression(body) = Block | IfExpression(body) | TryExpression(body) | WhileExpression(body) | ForExpression(body) | SwitchExpression | CompTimeExpression(body)1852BlockExpression(body) = Block | IfExpression(body) | TryExpression(body) | TestExpression(body) | WhileExpression(body) | ForExpression(body) | SwitchExpression | CompTimeExpression(body)
1866*/1853*/
1867static AstNode *ast_parse_block_expr(ParseContext *pc, size_t *token_index, bool mandatory) {1854static AstNode *ast_parse_block_expr(ParseContext *pc, size_t *token_index, bool mandatory) {
1868 Token *token = &pc->tokens->at(*token_index);1855 Token *token = &pc->tokens->at(*token_index);
...@@ -1895,6 +1882,10 @@ static AstNode *ast_parse_block_expr(ParseContext *pc, size_t *token_index, bool...@@ -1895,6 +1882,10 @@ static AstNode *ast_parse_block_expr(ParseContext *pc, size_t *token_index, bool
1895 if (try_node)1882 if (try_node)
1896 return try_node;1883 return try_node;
18971884
1885 AstNode *test_node = ast_parse_test_expr(pc, token_index, false);
1886 if (test_node)
1887 return test_node;
1888
1898 if (mandatory)1889 if (mandatory)
1899 ast_invalid_token_error(pc, token);1890 ast_invalid_token_error(pc, token);
19001891
...@@ -2079,14 +2070,14 @@ static bool statement_terminates_without_semicolon(AstNode *node) {...@@ -2079,14 +2070,14 @@ static bool statement_terminates_without_semicolon(AstNode *node) {
2079 if (node->data.if_bool_expr.else_node)2070 if (node->data.if_bool_expr.else_node)
2080 return statement_terminates_without_semicolon(node->data.if_bool_expr.else_node);2071 return statement_terminates_without_semicolon(node->data.if_bool_expr.else_node);
2081 return node->data.if_bool_expr.then_block->type == NodeTypeBlock;2072 return node->data.if_bool_expr.then_block->type == NodeTypeBlock;
2082 case NodeTypeIfVarExpr:
2083 if (node->data.if_var_expr.else_node)
2084 return statement_terminates_without_semicolon(node->data.if_var_expr.else_node);
2085 return node->data.if_var_expr.then_block->type == NodeTypeBlock;
2086 case NodeTypeTryExpr:2073 case NodeTypeTryExpr:
2087 if (node->data.try_expr.else_node)2074 if (node->data.try_expr.else_node)
2088 return statement_terminates_without_semicolon(node->data.try_expr.else_node);2075 return statement_terminates_without_semicolon(node->data.try_expr.else_node);
2089 return node->data.try_expr.then_node->type == NodeTypeBlock;2076 return node->data.try_expr.then_node->type == NodeTypeBlock;
2077 case NodeTypeTestExpr:
2078 if (node->data.test_expr.else_node)
2079 return statement_terminates_without_semicolon(node->data.test_expr.else_node);
2080 return node->data.test_expr.then_node->type == NodeTypeBlock;
2090 case NodeTypeWhileExpr:2081 case NodeTypeWhileExpr:
2091 return node->data.while_expr.body->type == NodeTypeBlock;2082 return node->data.while_expr.body->type == NodeTypeBlock;
2092 case NodeTypeForExpr:2083 case NodeTypeForExpr:
...@@ -2667,17 +2658,16 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont...@@ -2667,17 +2658,16 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont
2667 visit_field(&node->data.if_bool_expr.then_block, visit, context);2658 visit_field(&node->data.if_bool_expr.then_block, visit, context);
2668 visit_field(&node->data.if_bool_expr.else_node, visit, context);2659 visit_field(&node->data.if_bool_expr.else_node, visit, context);
2669 break;2660 break;
2670 case NodeTypeIfVarExpr:
2671 visit_field(&node->data.if_var_expr.var_decl.type, visit, context);
2672 visit_field(&node->data.if_var_expr.var_decl.expr, visit, context);
2673 visit_field(&node->data.if_var_expr.then_block, visit, context);
2674 visit_field(&node->data.if_var_expr.else_node, visit, context);
2675 break;
2676 case NodeTypeTryExpr:2661 case NodeTypeTryExpr:
2677 visit_field(&node->data.try_expr.target_node, visit, context);2662 visit_field(&node->data.try_expr.target_node, visit, context);
2678 visit_field(&node->data.try_expr.then_node, visit, context);2663 visit_field(&node->data.try_expr.then_node, visit, context);
2679 visit_field(&node->data.try_expr.else_node, visit, context);2664 visit_field(&node->data.try_expr.else_node, visit, context);
2680 break;2665 break;
2666 case NodeTypeTestExpr:
2667 visit_field(&node->data.test_expr.target_node, visit, context);
2668 visit_field(&node->data.test_expr.then_node, visit, context);
2669 visit_field(&node->data.test_expr.else_node, visit, context);
2670 break;
2681 case NodeTypeWhileExpr:2671 case NodeTypeWhileExpr:
2682 visit_field(&node->data.while_expr.condition, visit, context);2672 visit_field(&node->data.while_expr.condition, visit, context);
2683 visit_field(&node->data.while_expr.body, visit, context);2673 visit_field(&node->data.while_expr.body, visit, context);
std/buf_map.zig+1-1
...@@ -28,7 +28,7 @@ pub const BufMap = struct {...@@ -28,7 +28,7 @@ pub const BufMap = struct {
28 }28 }
2929
30 pub fn set(self: &BufMap, key: []const u8, value: []const u8) -> %void {30 pub fn set(self: &BufMap, key: []const u8, value: []const u8) -> %void {
31 if (const entry ?= self.hash_map.get(key)) {31 test (self.hash_map.get(key)) |entry| {
32 const value_copy = %return self.copy(value);32 const value_copy = %return self.copy(value);
33 %defer self.free(value_copy);33 %defer self.free(value_copy);
34 %return self.hash_map.put(key, value_copy);34 %return self.hash_map.put(key, value_copy);
std/build.zig+12-12
...@@ -309,7 +309,7 @@ pub const Builder = struct {...@@ -309,7 +309,7 @@ pub const Builder = struct {
309 }309 }
310310
311 fn processNixOSEnvVars(self: &Builder) {311 fn processNixOSEnvVars(self: &Builder) {
312 if (const nix_cflags_compile ?= os.getEnv("NIX_CFLAGS_COMPILE")) {312 test (os.getEnv("NIX_CFLAGS_COMPILE")) |nix_cflags_compile| {
313 var it = mem.split(nix_cflags_compile, ' ');313 var it = mem.split(nix_cflags_compile, ' ');
314 while (true) {314 while (true) {
315 const word = it.next() ?? break;315 const word = it.next() ?? break;
...@@ -325,7 +325,7 @@ pub const Builder = struct {...@@ -325,7 +325,7 @@ pub const Builder = struct {
325 }325 }
326 }326 }
327 }327 }
328 if (const nix_ldflags ?= os.getEnv("NIX_LDFLAGS")) {328 test (os.getEnv("NIX_LDFLAGS")) |nix_ldflags| {
329 var it = mem.split(nix_ldflags, ' ');329 var it = mem.split(nix_ldflags, ' ');
330 while (true) {330 while (true) {
331 const word = it.next() ?? break;331 const word = it.next() ?? break;
...@@ -353,7 +353,7 @@ pub const Builder = struct {...@@ -353,7 +353,7 @@ pub const Builder = struct {
353 .type_id = type_id,353 .type_id = type_id,
354 .description = description,354 .description = description,
355 };355 };
356 if (const _ ?= %%self.available_options_map.put(name, available_option)) {356 test (%%self.available_options_map.put(name, available_option)) {
357 debug.panic("Option '{}' declared twice", name);357 debug.panic("Option '{}' declared twice", name);
358 }358 }
359 %%self.available_options_list.append(available_option);359 %%self.available_options_list.append(available_option);
...@@ -410,11 +410,11 @@ pub const Builder = struct {...@@ -410,11 +410,11 @@ pub const Builder = struct {
410 }410 }
411411
412 pub fn addUserInputOption(self: &Builder, name: []const u8, value: []const u8) -> bool {412 pub fn addUserInputOption(self: &Builder, name: []const u8, value: []const u8) -> bool {
413 if (var prev_value ?= %%self.user_input_options.put(name, UserInputOption {413 test (%%self.user_input_options.put(name, UserInputOption {
414 .name = name,414 .name = name,
415 .value = UserValue.Scalar { value },415 .value = UserValue.Scalar { value },
416 .used = false,416 .used = false,
417 })) {417 })) |*prev_value| {
418 switch (prev_value.value) {418 switch (prev_value.value) {
419 UserValue.Scalar => |s| {419 UserValue.Scalar => |s| {
420 var list = List([]const u8).init(self.allocator);420 var list = List([]const u8).init(self.allocator);
...@@ -444,11 +444,11 @@ pub const Builder = struct {...@@ -444,11 +444,11 @@ pub const Builder = struct {
444 }444 }
445445
446 pub fn addUserInputFlag(self: &Builder, name: []const u8) -> bool {446 pub fn addUserInputFlag(self: &Builder, name: []const u8) -> bool {
447 if (const prev_value ?= %%self.user_input_options.put(name, UserInputOption {447 test (%%self.user_input_options.put(name, UserInputOption {
448 .name = name,448 .name = name,
449 .value = UserValue.Flag,449 .value = UserValue.Flag,
450 .used = false,450 .used = false,
451 })) {451 })) |*prev_value| {
452 switch (prev_value.value) {452 switch (prev_value.value) {
453 UserValue.Scalar => |s| {453 UserValue.Scalar => |s| {
454 %%io.stderr.printf("Flag '-D{}' conflicts with option '-D{}={}'.\n", name, name, s);454 %%io.stderr.printf("Flag '-D{}' conflicts with option '-D{}={}'.\n", name, name, s);
...@@ -766,7 +766,7 @@ pub const LibOrExeStep = struct {...@@ -766,7 +766,7 @@ pub const LibOrExeStep = struct {
766 %%zig_args.append("--release");766 %%zig_args.append("--release");
767 }767 }
768768
769 if (const output_path ?= self.output_path) {769 test (self.output_path) |output_path| {
770 %%zig_args.append("--output");770 %%zig_args.append("--output");
771 %%zig_args.append(builder.pathFromRoot(output_path));771 %%zig_args.append(builder.pathFromRoot(output_path));
772 }772 }
...@@ -912,7 +912,7 @@ pub const ObjectStep = struct {...@@ -912,7 +912,7 @@ pub const ObjectStep = struct {
912 %%zig_args.append("--release");912 %%zig_args.append("--release");
913 }913 }
914914
915 if (const output_path ?= self.output_path) {915 test (self.output_path) |output_path| {
916 %%zig_args.append("--output");916 %%zig_args.append("--output");
917 %%zig_args.append(builder.pathFromRoot(output_path));917 %%zig_args.append(builder.pathFromRoot(output_path));
918 }918 }
...@@ -1017,7 +1017,7 @@ pub const AsmStep = struct {...@@ -1017,7 +1017,7 @@ pub const AsmStep = struct {
1017 %%zig_args.append("--release");1017 %%zig_args.append("--release");
1018 }1018 }
10191019
1020 if (const output_path ?= self.output_path) {1020 test (self.output_path) |output_path| {
1021 %%zig_args.append("--output");1021 %%zig_args.append("--output");
1022 %%zig_args.append(builder.pathFromRoot(output_path));1022 %%zig_args.append(builder.pathFromRoot(output_path));
1023 }1023 }
...@@ -1194,7 +1194,7 @@ pub const LinkStep = struct {...@@ -1194,7 +1194,7 @@ pub const LinkStep = struct {
1194 %%zig_args.append("--static");1194 %%zig_args.append("--static");
1195 }1195 }
11961196
1197 if (const output_path ?= self.output_path) {1197 test (self.output_path) |output_path| {
1198 %%zig_args.append("--output");1198 %%zig_args.append("--output");
1199 %%zig_args.append(builder.pathFromRoot(output_path));1199 %%zig_args.append(builder.pathFromRoot(output_path));
1200 }1200 }
...@@ -1316,7 +1316,7 @@ pub const TestStep = struct {...@@ -1316,7 +1316,7 @@ pub const TestStep = struct {
1316 %%zig_args.append("--release");1316 %%zig_args.append("--release");
1317 }1317 }
13181318
1319 if (const filter ?= self.filter) {1319 test (self.filter) |filter| {
1320 %%zig_args.append("--test-filter");1320 %%zig_args.append("--test-filter");
1321 %%zig_args.append(filter);1321 %%zig_args.append(filter);
1322 }1322 }
std/hash_map.zig+1-1
...@@ -246,7 +246,7 @@ test "basicHashMapTest" {...@@ -246,7 +246,7 @@ test "basicHashMapTest" {
246 assert((??map.get(2)).value == 22);246 assert((??map.get(2)).value == 22);
247 _ = map.remove(2);247 _ = map.remove(2);
248 assert(map.remove(2) == null);248 assert(map.remove(2) == null);
249 assert(if (const entry ?= map.get(2)) false else true);249 assert(test (map.get(2)) false else true);
250}250}
251251
252fn hash_i32(x: i32) -> u32 {252fn hash_i32(x: i32) -> u32 {
std/os/child_process.zig+7-6
...@@ -56,9 +56,9 @@ pub const ChildProcess = struct {...@@ -56,9 +56,9 @@ pub const ChildProcess = struct {
56 errno.EINVAL, errno.ECHILD => unreachable,56 errno.EINVAL, errno.ECHILD => unreachable,
57 errno.EINTR => continue,57 errno.EINTR => continue,
58 else => {58 else => {
59 if (const *stdin ?= self.stdin) { stdin.close(); }59 test (self.stdin) |*stdin| { stdin.close(); }
60 if (const *stdout ?= self.stdin) { stdout.close(); }60 test (self.stdout) |*stdout| { stdout.close(); }
61 if (const *stderr ?= self.stdin) { stderr.close(); }61 test (self.stderr) |*stderr| { stderr.close(); }
62 return error.Unexpected;62 return error.Unexpected;
63 },63 },
64 }64 }
...@@ -66,9 +66,10 @@ pub const ChildProcess = struct {...@@ -66,9 +66,10 @@ pub const ChildProcess = struct {
66 break;66 break;
67 }67 }
6868
69 if (const *stdin ?= self.stdin) { stdin.close(); }69 // TODO oops!
70 if (const *stdout ?= self.stdin) { stdout.close(); }70 test (self.stdin) |*stdin| { stdin.close(); }
71 if (const *stderr ?= self.stdin) { stderr.close(); }71 test (self.stdin) |*stdout| { stdout.close(); }
72 test (self.stdin) |*stderr| { stderr.close(); }
7273
73 // Write @maxValue(ErrInt) to the write end of the err_pipe. This is after74 // Write @maxValue(ErrInt) to the write end of the err_pipe. This is after
74 // waitpid, so this write is guaranteed to be after the child75 // waitpid, so this write is guaranteed to be after the child
std/os/index.zig+3-3
...@@ -162,7 +162,7 @@ pub fn posixOpen(file_path: []const u8, flags: usize, perm: usize, allocator: ?&...@@ -162,7 +162,7 @@ pub fn posixOpen(file_path: []const u8, flags: usize, perm: usize, allocator: ?&
162162
163 if (file_path.len < stack_buf.len) {163 if (file_path.len < stack_buf.len) {
164 path0 = stack_buf[0...file_path.len + 1];164 path0 = stack_buf[0...file_path.len + 1];
165 } else if (const a ?= allocator) {165 } else test (allocator) |a| {
166 path0 = %return a.alloc(u8, file_path.len + 1);166 path0 = %return a.alloc(u8, file_path.len + 1);
167 need_free = true;167 need_free = true;
168 } else {168 } else {
...@@ -230,7 +230,7 @@ pub fn posixExecve(exe_path: []const u8, argv: []const []const u8, env_map: &con...@@ -230,7 +230,7 @@ pub fn posixExecve(exe_path: []const u8, argv: []const []const u8, env_map: &con
230 mem.set(?&u8, argv_buf, null);230 mem.set(?&u8, argv_buf, null);
231 defer {231 defer {
232 for (argv_buf) |arg| {232 for (argv_buf) |arg| {
233 const arg_buf = if (const ptr ?= arg) cstr.toSlice(ptr) else break;233 const arg_buf = test (arg) |ptr| cstr.toSlice(ptr) else break;
234 allocator.free(arg_buf);234 allocator.free(arg_buf);
235 }235 }
236 allocator.free(argv_buf);236 allocator.free(argv_buf);
...@@ -257,7 +257,7 @@ pub fn posixExecve(exe_path: []const u8, argv: []const []const u8, env_map: &con...@@ -257,7 +257,7 @@ pub fn posixExecve(exe_path: []const u8, argv: []const []const u8, env_map: &con
257 mem.set(?&u8, envp_buf, null);257 mem.set(?&u8, envp_buf, null);
258 defer {258 defer {
259 for (envp_buf) |env| {259 for (envp_buf) |env| {
260 const env_buf = if (const ptr ?= env) cstr.toSlice(ptr) else break;260 const env_buf = test (env) |ptr| cstr.toSlice(ptr) else break;
261 allocator.free(env_buf);261 allocator.free(env_buf);
262 }262 }
263 allocator.free(envp_buf);263 allocator.free(envp_buf);
std/special/build_runner.zig+1-1
...@@ -53,7 +53,7 @@ pub fn main() -> %void {...@@ -53,7 +53,7 @@ pub fn main() -> %void {
53 %%io.stderr.printf("Expected option name after '-D'\n\n");53 %%io.stderr.printf("Expected option name after '-D'\n\n");
54 return usage(&builder, false, &io.stderr);54 return usage(&builder, false, &io.stderr);
55 }55 }
56 if (const name_end ?= mem.indexOfScalar(u8, option_contents, '=')) {56 test (mem.indexOfScalar(u8, option_contents, '=')) |name_end| {
57 const option_name = option_contents[0...name_end];57 const option_name = option_contents[0...name_end];
58 const option_value = option_contents[name_end + 1...];58 const option_value = option_contents[name_end + 1...];
59 if (builder.addUserInputOption(option_name, option_value))59 if (builder.addUserInputOption(option_name, option_value))
std/special/compiler_rt.zig+9-9
...@@ -34,7 +34,7 @@ export fn __udivmoddi4(a: du_int, b: du_int, maybe_rem: ?&du_int) -> du_int {...@@ -34,7 +34,7 @@ export fn __udivmoddi4(a: du_int, b: du_int, maybe_rem: ?&du_int) -> du_int {
34 // 0 X34 // 0 X
35 // ---35 // ---
36 // 0 X36 // 0 X
37 if (const rem ?= maybe_rem) {37 test (maybe_rem) |rem| {
38 *rem = n[low] % d[low];38 *rem = n[low] % d[low];
39 }39 }
40 return n[low] / d[low];40 return n[low] / d[low];
...@@ -42,7 +42,7 @@ export fn __udivmoddi4(a: du_int, b: du_int, maybe_rem: ?&du_int) -> du_int {...@@ -42,7 +42,7 @@ export fn __udivmoddi4(a: du_int, b: du_int, maybe_rem: ?&du_int) -> du_int {
42 // 0 X42 // 0 X
43 // ---43 // ---
44 // K X44 // K X
45 if (const rem ?= maybe_rem) {45 test (maybe_rem) |rem| {
46 *rem = n[low];46 *rem = n[low];
47 }47 }
48 return 0;48 return 0;
...@@ -53,7 +53,7 @@ export fn __udivmoddi4(a: du_int, b: du_int, maybe_rem: ?&du_int) -> du_int {...@@ -53,7 +53,7 @@ export fn __udivmoddi4(a: du_int, b: du_int, maybe_rem: ?&du_int) -> du_int {
53 // K X53 // K X
54 // ---54 // ---
55 // 0 055 // 0 0
56 if (var rem ?= maybe_rem) {56 test (maybe_rem) |rem| {
57 *rem = n[high] % d[low];57 *rem = n[high] % d[low];
58 }58 }
59 return n[high] / d[low];59 return n[high] / d[low];
...@@ -63,7 +63,7 @@ export fn __udivmoddi4(a: du_int, b: du_int, maybe_rem: ?&du_int) -> du_int {...@@ -63,7 +63,7 @@ export fn __udivmoddi4(a: du_int, b: du_int, maybe_rem: ?&du_int) -> du_int {
63 // K 063 // K 0
64 // ---64 // ---
65 // K 065 // K 0
66 if (var rem ?= maybe_rem) {66 test (maybe_rem) |rem| {
67 r[high] = n[high] % d[high];67 r[high] = n[high] % d[high];
68 r[low] = 0;68 r[low] = 0;
69 *rem = *@ptrCast(&du_int, &r[0]);69 *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 {...@@ -75,7 +75,7 @@ export fn __udivmoddi4(a: du_int, b: du_int, maybe_rem: ?&du_int) -> du_int {
75 // K 075 // K 0
76 // if d is a power of 276 // if d is a power of 2
77 if ((d[high] & (d[high] - 1)) == 0) {77 if ((d[high] & (d[high] - 1)) == 0) {
78 if (var rem ?= maybe_rem) {78 test (maybe_rem) |rem| {
79 r[low] = n[low];79 r[low] = n[low];
80 r[high] = n[high] & (d[high] - 1);80 r[high] = n[high] & (d[high] - 1);
81 *rem = *@ptrCast(&du_int, &r[0]);81 *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 {...@@ -88,7 +88,7 @@ export fn __udivmoddi4(a: du_int, b: du_int, maybe_rem: ?&du_int) -> du_int {
88 sr = @clz(su_int(d[high])) - @clz(su_int(n[high]));88 sr = @clz(su_int(d[high])) - @clz(su_int(n[high]));
89 // 0 <= sr <= n_uword_bits - 2 or sr large89 // 0 <= sr <= n_uword_bits - 2 or sr large
90 if (sr > n_uword_bits - 2) {90 if (sr > n_uword_bits - 2) {
91 if (var rem ?= maybe_rem) {91 test (maybe_rem) |rem| {
92 *rem = *@ptrCast(&du_int, &n[0]);92 *rem = *@ptrCast(&du_int, &n[0]);
93 }93 }
94 return 0;94 return 0;
...@@ -109,7 +109,7 @@ export fn __udivmoddi4(a: du_int, b: du_int, maybe_rem: ?&du_int) -> du_int {...@@ -109,7 +109,7 @@ export fn __udivmoddi4(a: du_int, b: du_int, maybe_rem: ?&du_int) -> du_int {
109 // 0 K109 // 0 K
110 // if d is a power of 2110 // if d is a power of 2
111 if ((d[low] & (d[low] - 1)) == 0) {111 if ((d[low] & (d[low] - 1)) == 0) {
112 if (var rem ?= maybe_rem) {112 test (maybe_rem) |rem| {
113 *rem = n[low] & (d[low] - 1);113 *rem = n[low] & (d[low] - 1);
114 }114 }
115 if (d[low] == 1) {115 if (d[low] == 1) {
...@@ -153,7 +153,7 @@ export fn __udivmoddi4(a: du_int, b: du_int, maybe_rem: ?&du_int) -> du_int {...@@ -153,7 +153,7 @@ export fn __udivmoddi4(a: du_int, b: du_int, maybe_rem: ?&du_int) -> du_int {
153 sr = @clz(su_int(d[high])) - @clz(su_int(n[high]));153 sr = @clz(su_int(d[high])) - @clz(su_int(n[high]));
154 // 0 <= sr <= n_uword_bits - 1 or sr large154 // 0 <= sr <= n_uword_bits - 1 or sr large
155 if (sr > n_uword_bits - 1) {155 if (sr > n_uword_bits - 1) {
156 if (var rem ?= maybe_rem) {156 test (maybe_rem) |rem| {
157 *rem = *@ptrCast(&du_int, &n[0]);157 *rem = *@ptrCast(&du_int, &n[0]);
158 }158 }
159 return 0;159 return 0;
...@@ -198,7 +198,7 @@ export fn __udivmoddi4(a: du_int, b: du_int, maybe_rem: ?&du_int) -> du_int {...@@ -198,7 +198,7 @@ export fn __udivmoddi4(a: du_int, b: du_int, maybe_rem: ?&du_int) -> du_int {
198 sr -= 1;198 sr -= 1;
199 }199 }
200 *@ptrCast(&du_int, &q[0]) = (*@ptrCast(&du_int, &q[0]) << 1) | u64(carry);200 *@ptrCast(&du_int, &q[0]) = (*@ptrCast(&du_int, &q[0]) << 1) | u64(carry);
201 if (var rem ?= maybe_rem) {201 test (maybe_rem) |rem| {
202 *rem = *@ptrCast(&du_int, &r[0]);202 *rem = *@ptrCast(&du_int, &r[0]);
203 }203 }
204 return *@ptrCast(&du_int, &q[0]);204 return *@ptrCast(&du_int, &q[0]);
test/cases/misc.zig-10
...@@ -128,16 +128,6 @@ fn testTruncate(x: u32) -> u8 {...@@ -128,16 +128,6 @@ fn testTruncate(x: u32) -> u8 {
128 @truncate(u8, x)128 @truncate(u8, x)
129}129}
130130
131test "assignToIfVarPtr" {
132 var maybe_bool: ?bool = true;
133
134 if (const *b ?= maybe_bool) {
135 *b = false;
136 }
137
138 assert(??maybe_bool == false);
139}
140
141fn first4KeysOfHomeRow() -> []const u8 {131fn first4KeysOfHomeRow() -> []const u8 {
142 "aoeu"132 "aoeu"
143}133}
test/cases/null.zig+9-7
...@@ -3,7 +3,7 @@ const assert = @import("std").debug.assert;...@@ -3,7 +3,7 @@ const assert = @import("std").debug.assert;
3test "nullableType" {3test "nullableType" {
4 const x : ?bool = @generatedCode(true);4 const x : ?bool = @generatedCode(true);
55
6 if (const y ?= x) {6 test (x) |y| {
7 if (y) {7 if (y) {
8 // OK8 // OK
9 } else {9 } else {
...@@ -26,16 +26,17 @@ test "nullableType" {...@@ -26,16 +26,17 @@ test "nullableType" {
26 assert(num == 13);26 assert(num == 13);
27}27}
2828
29test "assignToIfVarPtr" {29test "test maybe object and get a pointer to the inner value" {
30 var maybe_bool: ?bool = true;30 var maybe_bool: ?bool = true;
3131
32 if (const *b ?= maybe_bool) {32 test (maybe_bool) |*b| {
33 *b = false;33 *b = false;
34 }34 }
3535
36 assert(??maybe_bool == false);36 assert(??maybe_bool == false);
37}37}
3838
39
39test "rhsMaybeUnwrapReturn" {40test "rhsMaybeUnwrapReturn" {
40 const x: ?bool = @generatedCode(true);41 const x: ?bool = @generatedCode(true);
41 const y = x ?? return;42 const y = x ?? return;
...@@ -49,7 +50,8 @@ test "maybe return" {...@@ -49,7 +50,8 @@ test "maybe return" {
4950
50fn maybeReturnImpl() {51fn maybeReturnImpl() {
51 assert(??foo(1235));52 assert(??foo(1235));
52 assert(if (const _ ?= foo(null)) false else true);53 test (foo(null))
54 unreachable;
53 assert(!??foo(1234));55 assert(!??foo(1234));
54}56}
5557
...@@ -64,10 +66,10 @@ test "ifVarMaybePointer" {...@@ -64,10 +66,10 @@ test "ifVarMaybePointer" {
64}66}
65fn shouldBeAPlus1(p: &const Particle) -> u64 {67fn shouldBeAPlus1(p: &const Particle) -> u64 {
66 var maybe_particle: ?Particle = *p;68 var maybe_particle: ?Particle = *p;
67 if (const *particle ?= maybe_particle) {69 test (maybe_particle) |*particle| {
68 particle.a += 1;70 particle.a += 1;
69 }71 }
70 if (const particle ?= maybe_particle) {72 test (maybe_particle) |particle| {
71 return particle.a;73 return particle.a;
72 }74 }
73 return 0;75 return 0;
...@@ -114,7 +116,7 @@ fn nullableVoidImpl() {...@@ -114,7 +116,7 @@ fn nullableVoidImpl() {
114}116}
115117
116fn bar(x: ?void) -> ?void {118fn bar(x: ?void) -> ?void {
117 if (const _ ?= x) {119 test (x) {
118 return {};120 return {};
119 } else {121 } else {
120 return null;122 return null;
test/cases/try.zig+2-2
...@@ -7,7 +7,7 @@ test "tryOnErrorUnion" {...@@ -7,7 +7,7 @@ test "tryOnErrorUnion" {
7}7}
88
9fn tryOnErrorUnionImpl() {9fn tryOnErrorUnionImpl() {
10 const x = try (const val = returnsTen()) {10 const x = try (returnsTen()) |val| {
11 val + 111 val + 1
12 } else |err| switch (err) {12 } else |err| switch (err) {
13 error.ItBroke, error.NoMem => 1,13 error.ItBroke, error.NoMem => 1,
...@@ -51,7 +51,7 @@ fn failIfTrue(ok: bool) -> %void {...@@ -51,7 +51,7 @@ fn failIfTrue(ok: bool) -> %void {
51//fn tryThenNotExecutedWithAssignment() {51//fn tryThenNotExecutedWithAssignment() {
52// @setFnTest(this);52// @setFnTest(this);
53//53//
54// try (_ = failIfTrue(true)) {54// try (failIfTrue(true)) {
55// unreachable;55// unreachable;
56// } else |err| {56// } else |err| {
57// assert(err == error.ItBroke);57// assert(err == error.ItBroke);
test/compile_errors.zig+14-68
...@@ -118,92 +118,38 @@ pub fn addCases(cases: &tests.CompileErrorContext) {...@@ -118,92 +118,38 @@ pub fn addCases(cases: &tests.CompileErrorContext) {
118 \\}118 \\}
119 , ".tmp_source.zig:5:5: error: invalid token: 'var'");119 , ".tmp_source.zig:5:5: error: invalid token: 'var'");
120120
121 cases.add("implicit semicolon - if(var) statement",121 cases.add("implicit semicolon - try statement",
122 \\export fn entry() {
123 \\ if(_=foo()) {}
124 \\ var good = {};
125 \\ if(_=foo()) ({})
126 \\ var bad = {};
127 \\}
128 , ".tmp_source.zig:5:5: error: invalid token: 'var'");
129
130 cases.add("implicit semicolon - if(var) expression",
131 \\export fn entry() {
132 \\ _ = if(_=foo()) {};
133 \\ var good = {};
134 \\ _ = if(_=foo()) {}
135 \\ var bad = {};
136 \\}
137 , ".tmp_source.zig:5:5: error: invalid token: 'var'");
138
139 cases.add("implicit semicolon - if(var)-else statement",
140 \\export fn entry() {
141 \\ if(_=foo()) {} else {}
142 \\ var good = {};
143 \\ if(_=foo()) ({}) else ({})
144 \\ var bad = {};
145 \\}
146 , ".tmp_source.zig:5:5: error: invalid token: 'var'");
147
148 cases.add("implicit semicolon - if(var)-else expression",
149 \\export fn entry() {
150 \\ _ = if(_=foo()) {} else {};
151 \\ var good = {};
152 \\ _ = if(_=foo()) {} else {}
153 \\ var bad = {};
154 \\}
155 , ".tmp_source.zig:5:5: error: invalid token: 'var'");
156
157 cases.add("implicit semicolon - if(var)-else-if(var) statement",
158 \\export fn entry() {
159 \\ if(_=foo()) {} else if(_=foo()) {}
160 \\ var good = {};
161 \\ if(_=foo()) ({}) else if(_=foo()) ({})
162 \\ var bad = {};
163 \\}
164 , ".tmp_source.zig:5:5: error: invalid token: 'var'");
165
166 cases.add("implicit semicolon - if(var)-else-if(var) expression",
167 \\export fn entry() {
168 \\ _ = if(_=foo()) {} else if(_=foo()) {};
169 \\ var good = {};
170 \\ _ = if(_=foo()) {} else if(_=foo()) {}
171 \\ var bad = {};
172 \\}
173 , ".tmp_source.zig:5:5: error: invalid token: 'var'");
174
175 cases.add("implicit semicolon - if(var)-else-if(var)-else statement",
176 \\export fn entry() {122 \\export fn entry() {
177 \\ if(_=foo()) {} else if(_=foo()) {} else {}123 \\ try (foo()) {}
178 \\ var good = {};124 \\ var good = {};
179 \\ if(_=foo()) ({}) else if(_=foo()) ({}) else ({})125 \\ try (foo()) ({})
180 \\ var bad = {};126 \\ var bad = {};
181 \\}127 \\}
182 , ".tmp_source.zig:5:5: error: invalid token: 'var'");128 , ".tmp_source.zig:5:5: error: invalid token: 'var'");
183129
184 cases.add("implicit semicolon - if(var)-else-if(var)-else expression",130 cases.add("implicit semicolon - try expression",
185 \\export fn entry() {131 \\export fn entry() {
186 \\ _ = if(_=foo()) {} else if(_=foo()) {} else {};132 \\ _ = try (foo()) {};
187 \\ var good = {};133 \\ var good = {};
188 \\ _ = if(_=foo()) {} else if(_=foo()) {} else {}134 \\ _ = try (foo()) {}
189 \\ var bad = {};135 \\ var bad = {};
190 \\}136 \\}
191 , ".tmp_source.zig:5:5: error: invalid token: 'var'");137 , ".tmp_source.zig:5:5: error: invalid token: 'var'");
192138
193 cases.add("implicit semicolon - try statement",139 cases.add("implicit semicolon - test statement",
194 \\export fn entry() {140 \\export fn entry() {
195 \\ try (_ = foo()) {}141 \\ test (foo()) {}
196 \\ var good = {};142 \\ var good = {};
197 \\ try (_ = foo()) ({})143 \\ test (foo()) ({})
198 \\ var bad = {};144 \\ var bad = {};
199 \\}145 \\}
200 , ".tmp_source.zig:5:5: error: invalid token: 'var'");146 , ".tmp_source.zig:5:5: error: invalid token: 'var'");
201147
202 cases.add("implicit semicolon - try expression",148 cases.add("implicit semicolon - test expression",
203 \\export fn entry() {149 \\export fn entry() {
204 \\ _ = try (_ = foo()) {};150 \\ _ = test (foo()) {};
205 \\ var good = {};151 \\ var good = {};
206 \\ _ = try (_ = foo()) {}152 \\ _ = test (foo()) {}
207 \\ var bad = {};153 \\ var bad = {};
208 \\}154 \\}
209 , ".tmp_source.zig:5:5: error: invalid token: 'var'");155 , ".tmp_source.zig:5:5: error: invalid token: 'var'");
...@@ -554,9 +500,9 @@ pub fn addCases(cases: &tests.CompileErrorContext) {...@@ -554,9 +500,9 @@ pub fn addCases(cases: &tests.CompileErrorContext) {
554500
555 cases.add("invalid maybe type",501 cases.add("invalid maybe type",
556 \\export fn f() {502 \\export fn f() {
557 \\ if (const x ?= true) { }503 \\ test (true) |x| { }
558 \\}504 \\}
559 , ".tmp_source.zig:2:20: error: expected nullable type, found 'bool'");505 , ".tmp_source.zig:2:11: error: expected nullable type, found 'bool'");
560506
561 cases.add("cast unreachable",507 cases.add("cast unreachable",
562 \\fn f() -> i32 {508 \\fn f() -> i32 {
test/tests.zig+7-7
...@@ -350,7 +350,7 @@ pub const CompareOutputContext = struct {...@@ -350,7 +350,7 @@ pub const CompareOutputContext = struct {
350 Special.Asm => {350 Special.Asm => {
351 const obj_path = %%os.path.join(b.allocator, "test_artifacts", "test.o");351 const obj_path = %%os.path.join(b.allocator, "test_artifacts", "test.o");
352 const annotated_case_name = %%fmt.allocPrint(self.b.allocator, "assemble-and-link {}", case.name);352 const annotated_case_name = %%fmt.allocPrint(self.b.allocator, "assemble-and-link {}", case.name);
353 if (const filter ?= self.test_filter) {353 test (self.test_filter) |filter| {
354 if (mem.indexOf(u8, annotated_case_name, filter) == null)354 if (mem.indexOf(u8, annotated_case_name, filter) == null)
355 return;355 return;
356 }356 }
...@@ -379,7 +379,7 @@ pub const CompareOutputContext = struct {...@@ -379,7 +379,7 @@ pub const CompareOutputContext = struct {
379 for ([]bool{false, true}) |release| {379 for ([]bool{false, true}) |release| {
380 const annotated_case_name = %%fmt.allocPrint(self.b.allocator, "{} {} ({})",380 const annotated_case_name = %%fmt.allocPrint(self.b.allocator, "{} {} ({})",
381 "compare-output", case.name, if (release) "release" else "debug");381 "compare-output", case.name, if (release) "release" else "debug");
382 if (const filter ?= self.test_filter) {382 test (self.test_filter) |filter| {
383 if (mem.indexOf(u8, annotated_case_name, filter) == null)383 if (mem.indexOf(u8, annotated_case_name, filter) == null)
384 continue;384 continue;
385 }385 }
...@@ -407,7 +407,7 @@ pub const CompareOutputContext = struct {...@@ -407,7 +407,7 @@ pub const CompareOutputContext = struct {
407 Special.DebugSafety => {407 Special.DebugSafety => {
408 const obj_path = %%os.path.join(b.allocator, "test_artifacts", "test.o");408 const obj_path = %%os.path.join(b.allocator, "test_artifacts", "test.o");
409 const annotated_case_name = %%fmt.allocPrint(self.b.allocator, "debug-safety {}", case.name);409 const annotated_case_name = %%fmt.allocPrint(self.b.allocator, "debug-safety {}", case.name);
410 if (const filter ?= self.test_filter) {410 test (self.test_filter) |filter| {
411 if (mem.indexOf(u8, annotated_case_name, filter) == null)411 if (mem.indexOf(u8, annotated_case_name, filter) == null)
412 return;412 return;
413 }413 }
...@@ -626,7 +626,7 @@ pub const CompileErrorContext = struct {...@@ -626,7 +626,7 @@ pub const CompileErrorContext = struct {
626 for ([]bool{false, true}) |release| {626 for ([]bool{false, true}) |release| {
627 const annotated_case_name = %%fmt.allocPrint(self.b.allocator, "compile-error {} ({})",627 const annotated_case_name = %%fmt.allocPrint(self.b.allocator, "compile-error {} ({})",
628 case.name, if (release) "release" else "debug");628 case.name, if (release) "release" else "debug");
629 if (const filter ?= self.test_filter) {629 test (self.test_filter) |filter| {
630 if (mem.indexOf(u8, annotated_case_name, filter) == null)630 if (mem.indexOf(u8, annotated_case_name, filter) == null)
631 continue;631 continue;
632 }632 }
...@@ -661,7 +661,7 @@ pub const BuildExamplesContext = struct {...@@ -661,7 +661,7 @@ pub const BuildExamplesContext = struct {
661 const b = self.b;661 const b = self.b;
662662
663 const annotated_case_name = b.fmt("build {}", build_file);663 const annotated_case_name = b.fmt("build {}", build_file);
664 if (const filter ?= self.test_filter) {664 test (self.test_filter) |filter| {
665 if (mem.indexOf(u8, annotated_case_name, filter) == null)665 if (mem.indexOf(u8, annotated_case_name, filter) == null)
666 return;666 return;
667 }667 }
...@@ -692,7 +692,7 @@ pub const BuildExamplesContext = struct {...@@ -692,7 +692,7 @@ pub const BuildExamplesContext = struct {
692 for ([]bool{false, true}) |release| {692 for ([]bool{false, true}) |release| {
693 const annotated_case_name = %%fmt.allocPrint(self.b.allocator, "build {} ({})",693 const annotated_case_name = %%fmt.allocPrint(self.b.allocator, "build {} ({})",
694 root_src, if (release) "release" else "debug");694 root_src, if (release) "release" else "debug");
695 if (const filter ?= self.test_filter) {695 test (self.test_filter) |filter| {
696 if (mem.indexOf(u8, annotated_case_name, filter) == null)696 if (mem.indexOf(u8, annotated_case_name, filter) == null)
697 continue;697 continue;
698 }698 }
...@@ -880,7 +880,7 @@ pub const ParseHContext = struct {...@@ -880,7 +880,7 @@ pub const ParseHContext = struct {
880 const b = self.b;880 const b = self.b;
881881
882 const annotated_case_name = %%fmt.allocPrint(self.b.allocator, "parseh {}", case.name);882 const annotated_case_name = %%fmt.allocPrint(self.b.allocator, "parseh {}", case.name);
883 if (const filter ?= self.test_filter) {883 test (self.test_filter) |filter| {
884 if (mem.indexOf(u8, annotated_case_name, filter) == null)884 if (mem.indexOf(u8, annotated_case_name, filter) == null)
885 return;885 return;
886 }886 }