authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-04-21 15:08:03-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-04-21 15:08:03-04:00
logd5346d7a8045549819abeb331d775aa2a10ca53b
tree524e11fa435e9f956f70ec9842d0572a02667ff0
parentbee1ae68ef1d36db8f4dfe255bef70b8ca6c4568

remove `?return` and `?defer`

closes #309

8 files changed, 19 insertions(+), 114 deletions(-)

doc/langref.md+2-2
......@@ -85,9 +85,9 @@ ForExpression(body) = "for" "(" Expression ")" option("|" option("*") Symbol opt
8585
8686BoolOrExpression = BoolAndExpression "or" BoolOrExpression | BoolAndExpression
8787
88ReturnExpression = option("%" | "?") "return" option(Expression)
88ReturnExpression = option("%") "return" option(Expression)
8989
90Defer(body) = option("%" | "?") "defer" body
90Defer(body) = option("%") "defer" body
9191
9292IfExpression(body) = IfVarExpression(body) | IfBoolExpression(body)
9393
example/README.md+2-4
......@@ -11,8 +11,6 @@
1111 libc.
1212 * **cat** - implementation of the `cat` UNIX utility in Zig, with no dependency
1313 on libc.
14
15## Work-In-Progress Examples
16
1714 * **shared_library** - demonstration of building a shared library and generating
18 a header file and documentation for interop with C code.
15 a header file for interop with C code.
16 * **mix_o_files** - how to mix .zig and .c files together as object files
src/all_types.hpp-1
......@@ -408,7 +408,6 @@ struct AstNodeBlock {
408408
409409enum ReturnKind {
410410 ReturnKindUnconditional,
411 ReturnKindMaybe,
412411 ReturnKindError,
413412};
414413
src/ast_render.cpp-2
......@@ -92,7 +92,6 @@ static const char *return_string(ReturnKind kind) {
9292 switch (kind) {
9393 case ReturnKindUnconditional: return "return";
9494 case ReturnKindError: return "%return";
95 case ReturnKindMaybe: return "?return";
9695 }
9796 zig_unreachable();
9897}
......@@ -101,7 +100,6 @@ static const char *defer_string(ReturnKind kind) {
101100 switch (kind) {
102101 case ReturnKindUnconditional: return "defer";
103102 case ReturnKindError: return "%defer";
104 case ReturnKindMaybe: return "?defer";
105103 }
106104 zig_unreachable();
107105}
src/ir.cpp+11-63
......@@ -3091,7 +3091,6 @@ static IrInstruction *ir_instruction_get_dep(IrInstruction *instruction, size_t
30913091static void ir_count_defers(IrBuilder *irb, Scope *inner_scope, Scope *outer_scope, size_t *results) {
30923092 results[ReturnKindUnconditional] = 0;
30933093 results[ReturnKindError] = 0;
3094 results[ReturnKindMaybe] = 0;
30953094
30963095 while (inner_scope != outer_scope) {
30973096 assert(inner_scope);
......@@ -3111,9 +3110,7 @@ static IrInstruction *ir_mark_gen(IrInstruction *instruction) {
31113110 return instruction;
31123111}
31133112
3114static bool ir_gen_defers_for_block(IrBuilder *irb, Scope *inner_scope, Scope *outer_scope,
3115 bool gen_error_defers, bool gen_maybe_defers)
3116{
3113static bool ir_gen_defers_for_block(IrBuilder *irb, Scope *inner_scope, Scope *outer_scope, bool gen_error_defers) {
31173114 Scope *scope = inner_scope;
31183115 while (scope != outer_scope) {
31193116 if (!scope)
......@@ -3124,8 +3121,7 @@ static bool ir_gen_defers_for_block(IrBuilder *irb, Scope *inner_scope, Scope *o
31243121 assert(defer_node->type == NodeTypeDefer);
31253122 ReturnKind defer_kind = defer_node->data.defer.kind;
31263123 if (defer_kind == ReturnKindUnconditional ||
3127 (gen_error_defers && defer_kind == ReturnKindError) ||
3128 (gen_maybe_defers && defer_kind == ReturnKindMaybe))
3124 (gen_error_defers && defer_kind == ReturnKindError))
31293125 {
31303126 AstNode *defer_expr_node = defer_node->data.defer.expr;
31313127 ir_gen_node(irb, defer_expr_node, defer_node->data.defer.expr_scope);
......@@ -3188,7 +3184,7 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node,
31883184 return_value = ir_build_const_void(irb, scope, node);
31893185 }
31903186
3191 size_t defer_counts[3];
3187 size_t defer_counts[2];
31923188 ir_count_defers(irb, scope, outer_scope, defer_counts);
31933189 if (defer_counts[ReturnKindError] > 0) {
31943190 IrBasicBlock *err_block = ir_build_basic_block(irb, scope, "ErrRetErr");
......@@ -3206,37 +3202,15 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node,
32063202 ir_mark_gen(ir_build_cond_br(irb, scope, node, is_err, err_block, ok_block, is_comptime));
32073203
32083204 ir_set_cursor_at_end(irb, err_block);
3209 ir_gen_defers_for_block(irb, scope, outer_scope, true, false);
3210 ir_build_return(irb, scope, node, return_value);
3211
3212 ir_set_cursor_at_end(irb, ok_block);
3213 ir_gen_defers_for_block(irb, scope, outer_scope, false, false);
3214 return ir_build_return(irb, scope, node, return_value);
3215 } else if (defer_counts[ReturnKindMaybe] > 0) {
3216 IrBasicBlock *null_block = ir_build_basic_block(irb, scope, "MaybeRetNull");
3217 IrBasicBlock *ok_block = ir_build_basic_block(irb, scope, "MaybeRetOk");
3218
3219 IrInstruction *is_non_null = ir_build_test_nonnull(irb, scope, node, return_value);
3220
3221 IrInstruction *is_comptime;
3222 if (ir_should_inline(irb->exec, scope)) {
3223 is_comptime = ir_build_const_bool(irb, scope, node, true);
3224 } else {
3225 is_comptime = ir_build_test_comptime(irb, scope, node, is_non_null);
3226 }
3227
3228 ir_mark_gen(ir_build_cond_br(irb, scope, node, is_non_null, ok_block, null_block, is_comptime));
3229
3230 ir_set_cursor_at_end(irb, null_block);
3231 ir_gen_defers_for_block(irb, scope, outer_scope, false, true);
3205 ir_gen_defers_for_block(irb, scope, outer_scope, true);
32323206 ir_build_return(irb, scope, node, return_value);
32333207
32343208 ir_set_cursor_at_end(irb, ok_block);
3235 ir_gen_defers_for_block(irb, scope, outer_scope, false, false);
3209 ir_gen_defers_for_block(irb, scope, outer_scope, false);
32363210 return ir_build_return(irb, scope, node, return_value);
32373211 } else {
32383212 // generate unconditional defers
3239 ir_gen_defers_for_block(irb, scope, outer_scope, false, false);
3213 ir_gen_defers_for_block(irb, scope, outer_scope, false);
32403214 return ir_build_return(irb, scope, node, return_value);
32413215 }
32423216 }
......@@ -3255,7 +3229,7 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node,
32553229 ir_mark_gen(ir_build_cond_br(irb, scope, node, is_err_val, return_block, continue_block, is_comptime));
32563230
32573231 ir_set_cursor_at_end(irb, return_block);
3258 ir_gen_defers_for_block(irb, scope, outer_scope, true, false);
3232 ir_gen_defers_for_block(irb, scope, outer_scope, true);
32593233 IrInstruction *err_val = ir_build_unwrap_err_code(irb, scope, node, err_union_ptr);
32603234 ir_build_return(irb, scope, node, err_val);
32613235
......@@ -3266,32 +3240,6 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node,
32663240 else
32673241 return ir_build_load_ptr(irb, scope, node, unwrapped_ptr);
32683242 }
3269 case ReturnKindMaybe:
3270 {
3271 assert(expr_node);
3272 IrInstruction *maybe_val_ptr = ir_gen_node_extra(irb, expr_node, scope, LVAL_PTR);
3273 if (maybe_val_ptr == irb->codegen->invalid_instruction)
3274 return irb->codegen->invalid_instruction;
3275 IrInstruction *maybe_val = ir_build_load_ptr(irb, scope, node, maybe_val_ptr);
3276 IrInstruction *is_non_null = ir_build_test_nonnull(irb, scope, node, maybe_val);
3277
3278 IrBasicBlock *return_block = ir_build_basic_block(irb, scope, "MaybeRetReturn");
3279 IrBasicBlock *continue_block = ir_build_basic_block(irb, scope, "MaybeRetContinue");
3280 IrInstruction *is_comptime = ir_build_const_bool(irb, scope, node, ir_should_inline(irb->exec, scope));
3281 ir_mark_gen(ir_build_cond_br(irb, scope, node, is_non_null, continue_block, return_block, is_comptime));
3282
3283 ir_set_cursor_at_end(irb, return_block);
3284 ir_gen_defers_for_block(irb, scope, outer_scope, false, true);
3285 IrInstruction *null = ir_build_const_null(irb, scope, node);
3286 ir_build_return(irb, scope, node, null);
3287
3288 ir_set_cursor_at_end(irb, continue_block);
3289 IrInstruction *unwrapped_ptr = ir_build_unwrap_maybe(irb, scope, node, maybe_val_ptr, false);
3290 if (lval.is_ptr)
3291 return unwrapped_ptr;
3292 else
3293 return ir_build_load_ptr(irb, scope, node, unwrapped_ptr);
3294 }
32953243 }
32963244 zig_unreachable();
32973245}
......@@ -3490,7 +3438,7 @@ static IrInstruction *ir_gen_block(IrBuilder *irb, Scope *parent_scope, AstNode
34903438 return_value = ir_mark_gen(ir_build_const_void(irb, child_scope, block_node));
34913439 }
34923440
3493 ir_gen_defers_for_block(irb, child_scope, outer_block_scope, false, false);
3441 ir_gen_defers_for_block(irb, child_scope, outer_block_scope, false);
34943442 }
34953443
34963444 assert(return_value != nullptr);
......@@ -5420,7 +5368,7 @@ static IrInstruction *ir_gen_break(IrBuilder *irb, Scope *scope, AstNode *node)
54205368 }
54215369
54225370 IrBasicBlock *dest_block = loop_stack_item->break_block;
5423 ir_gen_defers_for_block(irb, scope, dest_block->scope, false, false);
5371 ir_gen_defers_for_block(irb, scope, dest_block->scope, false);
54245372 return ir_build_br(irb, scope, node, dest_block, is_comptime);
54255373}
54265374
......@@ -5443,7 +5391,7 @@ static IrInstruction *ir_gen_continue(IrBuilder *irb, Scope *scope, AstNode *nod
54435391 }
54445392
54455393 IrBasicBlock *dest_block = loop_stack_item->continue_block;
5446 ir_gen_defers_for_block(irb, scope, dest_block->scope, false, false);
5394 ir_gen_defers_for_block(irb, scope, dest_block->scope, false);
54475395 return ir_build_br(irb, scope, node, dest_block, is_comptime);
54485396}
54495397
......@@ -5784,7 +5732,7 @@ static bool ir_goto_pass2(IrBuilder *irb) {
57845732
57855733 IrInstruction *is_comptime = ir_build_const_bool(irb, goto_item->scope, source_node,
57865734 ir_should_inline(irb->exec, goto_item->scope) || source_node->data.goto_expr.is_inline);
5787 if (!ir_gen_defers_for_block(irb, goto_item->scope, label->bb->scope, false, false)) {
5735 if (!ir_gen_defers_for_block(irb, goto_item->scope, label->bb->scope, false)) {
57885736 add_node_error(irb->codegen, source_node,
57895737 buf_sprintf("no label in scope named '%s'", buf_ptr(label_name)));
57905738 return false;
src/parser.cpp+2-20
......@@ -1483,7 +1483,7 @@ static AstNode *ast_parse_if_expr(ParseContext *pc, size_t *token_index, bool ma
14831483}
14841484
14851485/*
1486ReturnExpression : option("%" | "?") "return" option(Expression)
1486ReturnExpression : option("%") "return" option(Expression)
14871487*/
14881488static AstNode *ast_parse_return_expr(ParseContext *pc, size_t *token_index) {
14891489 Token *token = &pc->tokens->at(*token_index);
......@@ -1500,15 +1500,6 @@ static AstNode *ast_parse_return_expr(ParseContext *pc, size_t *token_index) {
15001500 } else {
15011501 return nullptr;
15021502 }
1503 } else if (token->id == TokenIdMaybe) {
1504 Token *next_token = &pc->tokens->at(*token_index + 1);
1505 if (next_token->id == TokenIdKeywordReturn) {
1506 kind = ReturnKindMaybe;
1507 node_type = NodeTypeReturnExpr;
1508 *token_index += 2;
1509 } else {
1510 return nullptr;
1511 }
15121503 } else if (token->id == TokenIdKeywordReturn) {
15131504 kind = ReturnKindUnconditional;
15141505 node_type = NodeTypeReturnExpr;
......@@ -1525,7 +1516,7 @@ static AstNode *ast_parse_return_expr(ParseContext *pc, size_t *token_index) {
15251516}
15261517
15271518/*
1528Defer(body) = option("%" | "?") "defer" body
1519Defer(body) = option("%") "defer" body
15291520*/
15301521static AstNode *ast_parse_defer_expr(ParseContext *pc, size_t *token_index) {
15311522 Token *token = &pc->tokens->at(*token_index);
......@@ -1542,15 +1533,6 @@ static AstNode *ast_parse_defer_expr(ParseContext *pc, size_t *token_index) {
15421533 } else {
15431534 return nullptr;
15441535 }
1545 } else if (token->id == TokenIdMaybe) {
1546 Token *next_token = &pc->tokens->at(*token_index + 1);
1547 if (next_token->id == TokenIdKeywordDefer) {
1548 kind = ReturnKindMaybe;
1549 node_type = NodeTypeDefer;
1550 *token_index += 2;
1551 } else {
1552 return nullptr;
1553 }
15541536 } else if (token->id == TokenIdKeywordDefer) {
15551537 kind = ReturnKindUnconditional;
15561538 node_type = NodeTypeDefer;
test/cases/defer.zig-20
......@@ -13,14 +13,6 @@ fn runSomeErrorDefers(x: bool) -> %bool {
1313 return if (x) x else error.FalseNotAllowed;
1414}
1515
16fn runSomeMaybeDefers(x: bool) -> ?bool {
17 index = 0;
18 defer {result[index] = 'a'; index += 1;};
19 ?defer {result[index] = 'b'; index += 1;};
20 defer {result[index] = 'c'; index += 1;};
21 return if (x) x else null;
22}
23
2416test "mixingNormalAndErrorDefers" {
2517 assert(%%runSomeErrorDefers(true));
2618 assert(result[0] == 'c');
......@@ -35,15 +27,3 @@ test "mixingNormalAndErrorDefers" {
3527 assert(result[1] == 'b');
3628 assert(result[2] == 'a');
3729}
38
39test "mixingNormalAndMaybeDefers" {
40 assert(??runSomeMaybeDefers(true));
41 assert(result[0] == 'c');
42 assert(result[1] == 'a');
43
44 const ok = runSomeMaybeDefers(false) ?? true;
45 assert(ok);
46 assert(result[0] == 'c');
47 assert(result[1] == 'b');
48 assert(result[2] == 'a');
49}
test/cases/null.zig+2-2
......@@ -42,7 +42,7 @@ test "rhsMaybeUnwrapReturn" {
4242}
4343
4444
45test "maybeReturn" {
45test "maybe return" {
4646 maybeReturnImpl();
4747 comptime maybeReturnImpl();
4848}
......@@ -54,7 +54,7 @@ fn maybeReturnImpl() {
5454}
5555
5656fn foo(x: ?i32) -> ?bool {
57 const value = ?return x;
57 const value = x ?? return null;
5858 return value > 1234;
5959}
6060