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...@@ -85,9 +85,9 @@ ForExpression(body) = "for" "(" Expression ")" option("|" option("*") Symbol opt
8585
86BoolOrExpression = BoolAndExpression "or" BoolOrExpression | BoolAndExpression86BoolOrExpression = BoolAndExpression "or" BoolOrExpression | BoolAndExpression
8787
88ReturnExpression = option("%" | "?") "return" option(Expression)88ReturnExpression = option("%") "return" option(Expression)
8989
90Defer(body) = option("%" | "?") "defer" body90Defer(body) = option("%") "defer" body
9191
92IfExpression(body) = IfVarExpression(body) | IfBoolExpression(body)92IfExpression(body) = IfVarExpression(body) | IfBoolExpression(body)
9393
example/README.md+2-4
...@@ -11,8 +11,6 @@...@@ -11,8 +11,6 @@
11 libc.11 libc.
12 * **cat** - implementation of the `cat` UNIX utility in Zig, with no dependency12 * **cat** - implementation of the `cat` UNIX utility in Zig, with no dependency
13 on libc.13 on libc.
14
15## Work-In-Progress Examples
16
17 * **shared_library** - demonstration of building a shared library and generating14 * **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 {...@@ -408,7 +408,6 @@ struct AstNodeBlock {
408408
409enum ReturnKind {409enum ReturnKind {
410 ReturnKindUnconditional,410 ReturnKindUnconditional,
411 ReturnKindMaybe,
412 ReturnKindError,411 ReturnKindError,
413};412};
414413
src/ast_render.cpp-2
...@@ -92,7 +92,6 @@ static const char *return_string(ReturnKind kind) {...@@ -92,7 +92,6 @@ static const char *return_string(ReturnKind kind) {
92 switch (kind) {92 switch (kind) {
93 case ReturnKindUnconditional: return "return";93 case ReturnKindUnconditional: return "return";
94 case ReturnKindError: return "%return";94 case ReturnKindError: return "%return";
95 case ReturnKindMaybe: return "?return";
96 }95 }
97 zig_unreachable();96 zig_unreachable();
98}97}
...@@ -101,7 +100,6 @@ static const char *defer_string(ReturnKind kind) {...@@ -101,7 +100,6 @@ static const char *defer_string(ReturnKind kind) {
101 switch (kind) {100 switch (kind) {
102 case ReturnKindUnconditional: return "defer";101 case ReturnKindUnconditional: return "defer";
103 case ReturnKindError: return "%defer";102 case ReturnKindError: return "%defer";
104 case ReturnKindMaybe: return "?defer";
105 }103 }
106 zig_unreachable();104 zig_unreachable();
107}105}
src/ir.cpp+11-63
...@@ -3091,7 +3091,6 @@ static IrInstruction *ir_instruction_get_dep(IrInstruction *instruction, size_t...@@ -3091,7 +3091,6 @@ static IrInstruction *ir_instruction_get_dep(IrInstruction *instruction, size_t
3091static void ir_count_defers(IrBuilder *irb, Scope *inner_scope, Scope *outer_scope, size_t *results) {3091static void ir_count_defers(IrBuilder *irb, Scope *inner_scope, Scope *outer_scope, size_t *results) {
3092 results[ReturnKindUnconditional] = 0;3092 results[ReturnKindUnconditional] = 0;
3093 results[ReturnKindError] = 0;3093 results[ReturnKindError] = 0;
3094 results[ReturnKindMaybe] = 0;
30953094
3096 while (inner_scope != outer_scope) {3095 while (inner_scope != outer_scope) {
3097 assert(inner_scope);3096 assert(inner_scope);
...@@ -3111,9 +3110,7 @@ static IrInstruction *ir_mark_gen(IrInstruction *instruction) {...@@ -3111,9 +3110,7 @@ static IrInstruction *ir_mark_gen(IrInstruction *instruction) {
3111 return instruction;3110 return instruction;
3112}3111}
31133112
3114static bool ir_gen_defers_for_block(IrBuilder *irb, Scope *inner_scope, Scope *outer_scope,3113static bool ir_gen_defers_for_block(IrBuilder *irb, Scope *inner_scope, Scope *outer_scope, bool gen_error_defers) {
3115 bool gen_error_defers, bool gen_maybe_defers)
3116{
3117 Scope *scope = inner_scope;3114 Scope *scope = inner_scope;
3118 while (scope != outer_scope) {3115 while (scope != outer_scope) {
3119 if (!scope)3116 if (!scope)
...@@ -3124,8 +3121,7 @@ static bool ir_gen_defers_for_block(IrBuilder *irb, Scope *inner_scope, Scope *o...@@ -3124,8 +3121,7 @@ static bool ir_gen_defers_for_block(IrBuilder *irb, Scope *inner_scope, Scope *o
3124 assert(defer_node->type == NodeTypeDefer);3121 assert(defer_node->type == NodeTypeDefer);
3125 ReturnKind defer_kind = defer_node->data.defer.kind;3122 ReturnKind defer_kind = defer_node->data.defer.kind;
3126 if (defer_kind == ReturnKindUnconditional ||3123 if (defer_kind == ReturnKindUnconditional ||
3127 (gen_error_defers && defer_kind == ReturnKindError) ||3124 (gen_error_defers && defer_kind == ReturnKindError))
3128 (gen_maybe_defers && defer_kind == ReturnKindMaybe))
3129 {3125 {
3130 AstNode *defer_expr_node = defer_node->data.defer.expr;3126 AstNode *defer_expr_node = defer_node->data.defer.expr;
3131 ir_gen_node(irb, defer_expr_node, defer_node->data.defer.expr_scope);3127 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,...@@ -3188,7 +3184,7 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node,
3188 return_value = ir_build_const_void(irb, scope, node);3184 return_value = ir_build_const_void(irb, scope, node);
3189 }3185 }
31903186
3191 size_t defer_counts[3];3187 size_t defer_counts[2];
3192 ir_count_defers(irb, scope, outer_scope, defer_counts);3188 ir_count_defers(irb, scope, outer_scope, defer_counts);
3193 if (defer_counts[ReturnKindError] > 0) {3189 if (defer_counts[ReturnKindError] > 0) {
3194 IrBasicBlock *err_block = ir_build_basic_block(irb, scope, "ErrRetErr");3190 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,...@@ -3206,37 +3202,15 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node,
3206 ir_mark_gen(ir_build_cond_br(irb, scope, node, is_err, err_block, ok_block, is_comptime));3202 ir_mark_gen(ir_build_cond_br(irb, scope, node, is_err, err_block, ok_block, is_comptime));
32073203
3208 ir_set_cursor_at_end(irb, err_block);3204 ir_set_cursor_at_end(irb, err_block);
3209 ir_gen_defers_for_block(irb, scope, outer_scope, true, false);3205 ir_gen_defers_for_block(irb, scope, outer_scope, true);
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);
3232 ir_build_return(irb, scope, node, return_value);3206 ir_build_return(irb, scope, node, return_value);
32333207
3234 ir_set_cursor_at_end(irb, ok_block);3208 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);
3236 return ir_build_return(irb, scope, node, return_value);3210 return ir_build_return(irb, scope, node, return_value);
3237 } else {3211 } else {
3238 // generate unconditional defers3212 // 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);
3240 return ir_build_return(irb, scope, node, return_value);3214 return ir_build_return(irb, scope, node, return_value);
3241 }3215 }
3242 }3216 }
...@@ -3255,7 +3229,7 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node,...@@ -3255,7 +3229,7 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node,
3255 ir_mark_gen(ir_build_cond_br(irb, scope, node, is_err_val, return_block, continue_block, is_comptime));3229 ir_mark_gen(ir_build_cond_br(irb, scope, node, is_err_val, return_block, continue_block, is_comptime));
32563230
3257 ir_set_cursor_at_end(irb, return_block);3231 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);
3259 IrInstruction *err_val = ir_build_unwrap_err_code(irb, scope, node, err_union_ptr);3233 IrInstruction *err_val = ir_build_unwrap_err_code(irb, scope, node, err_union_ptr);
3260 ir_build_return(irb, scope, node, err_val);3234 ir_build_return(irb, scope, node, err_val);
32613235
...@@ -3266,32 +3240,6 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node,...@@ -3266,32 +3240,6 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node,
3266 else3240 else
3267 return ir_build_load_ptr(irb, scope, node, unwrapped_ptr);3241 return ir_build_load_ptr(irb, scope, node, unwrapped_ptr);
3268 }3242 }
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 }
3295 }3243 }
3296 zig_unreachable();3244 zig_unreachable();
3297}3245}
...@@ -3490,7 +3438,7 @@ static IrInstruction *ir_gen_block(IrBuilder *irb, Scope *parent_scope, AstNode...@@ -3490,7 +3438,7 @@ static IrInstruction *ir_gen_block(IrBuilder *irb, Scope *parent_scope, AstNode
3490 return_value = ir_mark_gen(ir_build_const_void(irb, child_scope, block_node));3438 return_value = ir_mark_gen(ir_build_const_void(irb, child_scope, block_node));
3491 }3439 }
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);
3494 }3442 }
34953443
3496 assert(return_value != nullptr);3444 assert(return_value != nullptr);
...@@ -5420,7 +5368,7 @@ static IrInstruction *ir_gen_break(IrBuilder *irb, Scope *scope, AstNode *node)...@@ -5420,7 +5368,7 @@ static IrInstruction *ir_gen_break(IrBuilder *irb, Scope *scope, AstNode *node)
5420 }5368 }
54215369
5422 IrBasicBlock *dest_block = loop_stack_item->break_block;5370 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);
5424 return ir_build_br(irb, scope, node, dest_block, is_comptime);5372 return ir_build_br(irb, scope, node, dest_block, is_comptime);
5425}5373}
54265374
...@@ -5443,7 +5391,7 @@ static IrInstruction *ir_gen_continue(IrBuilder *irb, Scope *scope, AstNode *nod...@@ -5443,7 +5391,7 @@ static IrInstruction *ir_gen_continue(IrBuilder *irb, Scope *scope, AstNode *nod
5443 }5391 }
54445392
5445 IrBasicBlock *dest_block = loop_stack_item->continue_block;5393 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);
5447 return ir_build_br(irb, scope, node, dest_block, is_comptime);5395 return ir_build_br(irb, scope, node, dest_block, is_comptime);
5448}5396}
54495397
...@@ -5784,7 +5732,7 @@ static bool ir_goto_pass2(IrBuilder *irb) {...@@ -5784,7 +5732,7 @@ static bool ir_goto_pass2(IrBuilder *irb) {
57845732
5785 IrInstruction *is_comptime = ir_build_const_bool(irb, goto_item->scope, source_node,5733 IrInstruction *is_comptime = ir_build_const_bool(irb, goto_item->scope, source_node,
5786 ir_should_inline(irb->exec, goto_item->scope) || source_node->data.goto_expr.is_inline);5734 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)) {
5788 add_node_error(irb->codegen, source_node,5736 add_node_error(irb->codegen, source_node,
5789 buf_sprintf("no label in scope named '%s'", buf_ptr(label_name)));5737 buf_sprintf("no label in scope named '%s'", buf_ptr(label_name)));
5790 return false;5738 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...@@ -1483,7 +1483,7 @@ static AstNode *ast_parse_if_expr(ParseContext *pc, size_t *token_index, bool ma
1483}1483}
14841484
1485/*1485/*
1486ReturnExpression : option("%" | "?") "return" option(Expression)1486ReturnExpression : option("%") "return" option(Expression)
1487*/1487*/
1488static AstNode *ast_parse_return_expr(ParseContext *pc, size_t *token_index) {1488static AstNode *ast_parse_return_expr(ParseContext *pc, size_t *token_index) {
1489 Token *token = &pc->tokens->at(*token_index);1489 Token *token = &pc->tokens->at(*token_index);
...@@ -1500,15 +1500,6 @@ static AstNode *ast_parse_return_expr(ParseContext *pc, size_t *token_index) {...@@ -1500,15 +1500,6 @@ static AstNode *ast_parse_return_expr(ParseContext *pc, size_t *token_index) {
1500 } else {1500 } else {
1501 return nullptr;1501 return nullptr;
1502 }1502 }
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 }
1512 } else if (token->id == TokenIdKeywordReturn) {1503 } else if (token->id == TokenIdKeywordReturn) {
1513 kind = ReturnKindUnconditional;1504 kind = ReturnKindUnconditional;
1514 node_type = NodeTypeReturnExpr;1505 node_type = NodeTypeReturnExpr;
...@@ -1525,7 +1516,7 @@ static AstNode *ast_parse_return_expr(ParseContext *pc, size_t *token_index) {...@@ -1525,7 +1516,7 @@ static AstNode *ast_parse_return_expr(ParseContext *pc, size_t *token_index) {
1525}1516}
15261517
1527/*1518/*
1528Defer(body) = option("%" | "?") "defer" body1519Defer(body) = option("%") "defer" body
1529*/1520*/
1530static AstNode *ast_parse_defer_expr(ParseContext *pc, size_t *token_index) {1521static AstNode *ast_parse_defer_expr(ParseContext *pc, size_t *token_index) {
1531 Token *token = &pc->tokens->at(*token_index);1522 Token *token = &pc->tokens->at(*token_index);
...@@ -1542,15 +1533,6 @@ static AstNode *ast_parse_defer_expr(ParseContext *pc, size_t *token_index) {...@@ -1542,15 +1533,6 @@ static AstNode *ast_parse_defer_expr(ParseContext *pc, size_t *token_index) {
1542 } else {1533 } else {
1543 return nullptr;1534 return nullptr;
1544 }1535 }
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 }
1554 } else if (token->id == TokenIdKeywordDefer) {1536 } else if (token->id == TokenIdKeywordDefer) {
1555 kind = ReturnKindUnconditional;1537 kind = ReturnKindUnconditional;
1556 node_type = NodeTypeDefer;1538 node_type = NodeTypeDefer;
test/cases/defer.zig-20
...@@ -13,14 +13,6 @@ fn runSomeErrorDefers(x: bool) -> %bool {...@@ -13,14 +13,6 @@ fn runSomeErrorDefers(x: bool) -> %bool {
13 return if (x) x else error.FalseNotAllowed;13 return if (x) x else error.FalseNotAllowed;
14}14}
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
24test "mixingNormalAndErrorDefers" {16test "mixingNormalAndErrorDefers" {
25 assert(%%runSomeErrorDefers(true));17 assert(%%runSomeErrorDefers(true));
26 assert(result[0] == 'c');18 assert(result[0] == 'c');
...@@ -35,15 +27,3 @@ test "mixingNormalAndErrorDefers" {...@@ -35,15 +27,3 @@ test "mixingNormalAndErrorDefers" {
35 assert(result[1] == 'b');27 assert(result[1] == 'b');
36 assert(result[2] == 'a');28 assert(result[2] == 'a');
37}29}
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" {...@@ -42,7 +42,7 @@ test "rhsMaybeUnwrapReturn" {
42}42}
4343
4444
45test "maybeReturn" {45test "maybe return" {
46 maybeReturnImpl();46 maybeReturnImpl();
47 comptime maybeReturnImpl();47 comptime maybeReturnImpl();
48}48}
...@@ -54,7 +54,7 @@ fn maybeReturnImpl() {...@@ -54,7 +54,7 @@ fn maybeReturnImpl() {
54}54}
5555
56fn foo(x: ?i32) -> ?bool {56fn foo(x: ?i32) -> ?bool {
57 const value = ?return x;57 const value = x ?? return null;
58 return value > 1234;58 return value > 1234;
59}59}
6060