authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-02-02 13:23:18-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-02-02 13:23:18-05:00
logb78c91951a1db34c615a011e0444608285f1a74c
tree2cae0609ec2670a4a1e1adb7905ae495abc9a238
parentcd08c1f3be278366ee69c3cf4ab1091eb884e264

remove ability to mark if and switch as inline

if and switch are implicitly inline if the condition/target expression is known at compile time. instead of: ``` inline if (condition) ... inline switch (target) ... ``` one can use: ``` if (comptime condition) ... switch (comptime target) ... ```

7 files changed, 29 insertions(+), 64 deletions(-)

doc/langref.md+3-3
...@@ -73,7 +73,7 @@ BlockExpression = IfExpression | Block | WhileExpression | ForExpression | Switc...@@ -73,7 +73,7 @@ BlockExpression = IfExpression | Block | WhileExpression | ForExpression | Switc
7373
74CompTimeExpression = option("comptime") Expression74CompTimeExpression = option("comptime") Expression
7575
76SwitchExpression = option("inline") "switch" "(" Expression ")" "{" many(SwitchProng) "}"76SwitchExpression = "switch" "(" Expression ")" "{" many(SwitchProng) "}"
7777
78SwitchProng = (list(SwitchItem, ",") | "else") "=>" option("|" option("*") Symbol "|") Expression ","78SwitchProng = (list(SwitchItem, ",") | "else") "=>" option("|" option("*") Symbol "|") Expression ","
7979
...@@ -91,9 +91,9 @@ Defer = option("%" | "?") "defer" Expression...@@ -91,9 +91,9 @@ Defer = option("%" | "?") "defer" Expression
9191
92IfExpression = IfVarExpression | IfBoolExpression92IfExpression = IfVarExpression | IfBoolExpression
9393
94IfBoolExpression = option("inline") "if" "(" Expression ")" Expression option(Else)94IfBoolExpression = "if" "(" Expression ")" Expression option(Else)
9595
96IfVarExpression = option("inline") "if" "(" ("const" | "var") option("*") Symbol option(":" TypeExpr) "?=" Expression ")" Expression Option(Else)96IfVarExpression = "if" "(" ("const" | "var") option("*") Symbol option(":" TypeExpr) "?=" Expression ")" Expression Option(Else)
9797
98Else = "else" Expression98Else = "else" Expression
9999
src/all_types.hpp-5
...@@ -509,7 +509,6 @@ struct AstNodeIfBoolExpr {...@@ -509,7 +509,6 @@ struct AstNodeIfBoolExpr {
509 AstNode *condition;509 AstNode *condition;
510 AstNode *then_block;510 AstNode *then_block;
511 AstNode *else_node; // null, block node, or other if expr node511 AstNode *else_node; // null, block node, or other if expr node
512 bool is_inline;
513};512};
514513
515struct AstNodeIfVarExpr {514struct AstNodeIfVarExpr {
...@@ -517,7 +516,6 @@ struct AstNodeIfVarExpr {...@@ -517,7 +516,6 @@ struct AstNodeIfVarExpr {
517 AstNode *then_block;516 AstNode *then_block;
518 AstNode *else_node; // null, block node, or other if expr node517 AstNode *else_node; // null, block node, or other if expr node
519 bool var_is_ptr;518 bool var_is_ptr;
520 bool is_inline;
521};519};
522520
523struct AstNodeWhileExpr {521struct AstNodeWhileExpr {
...@@ -539,7 +537,6 @@ struct AstNodeForExpr {...@@ -539,7 +537,6 @@ struct AstNodeForExpr {
539struct AstNodeSwitchExpr {537struct AstNodeSwitchExpr {
540 AstNode *expr;538 AstNode *expr;
541 ZigList<AstNode *> prongs;539 ZigList<AstNode *> prongs;
542 bool is_inline;
543};540};
544541
545struct AstNodeSwitchProng {542struct AstNodeSwitchProng {
...@@ -677,11 +674,9 @@ struct AstNodeBoolLiteral {...@@ -677,11 +674,9 @@ struct AstNodeBoolLiteral {
677};674};
678675
679struct AstNodeBreakExpr {676struct AstNodeBreakExpr {
680 bool is_inline; // TODO
681};677};
682678
683struct AstNodeContinueExpr {679struct AstNodeContinueExpr {
684 bool is_inline; // TODO
685};680};
686681
687struct AstNodeArrayType {682struct AstNodeArrayType {
src/ast_render.cpp+2-4
...@@ -844,14 +844,12 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {...@@ -844,14 +844,12 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {
844 }844 }
845 case NodeTypeBreak:845 case NodeTypeBreak:
846 {846 {
847 const char *inline_str = node->data.break_expr.is_inline ? "inline " : "";847 fprintf(ar->f, "break");
848 fprintf(ar->f, "%sbreak", inline_str);
849 break;848 break;
850 }849 }
851 case NodeTypeContinue:850 case NodeTypeContinue:
852 {851 {
853 const char *inline_str = node->data.continue_expr.is_inline ? "inline " : "";852 fprintf(ar->f, "continue");
854 fprintf(ar->f, "%scontinue", inline_str);
855 break;853 break;
856 }854 }
857 case NodeTypeSliceExpr:855 case NodeTypeSliceExpr:
src/ir.cpp+5-5
...@@ -4148,7 +4148,7 @@ static IrInstruction *ir_gen_if_bool_expr(IrBuilder *irb, Scope *scope, AstNode...@@ -4148,7 +4148,7 @@ static IrInstruction *ir_gen_if_bool_expr(IrBuilder *irb, Scope *scope, AstNode
4148 return condition;4148 return condition;
41494149
4150 IrInstruction *is_comptime;4150 IrInstruction *is_comptime;
4151 if (ir_should_inline(irb->exec, scope) || node->data.if_bool_expr.is_inline) {4151 if (ir_should_inline(irb->exec, scope)) {
4152 is_comptime = ir_build_const_bool(irb, scope, node, true);4152 is_comptime = ir_build_const_bool(irb, scope, node, true);
4153 } else {4153 } else {
4154 is_comptime = ir_build_test_comptime(irb, scope, node, condition);4154 is_comptime = ir_build_test_comptime(irb, scope, node, condition);
...@@ -4695,7 +4695,7 @@ static IrInstruction *ir_gen_if_var_expr(IrBuilder *irb, Scope *scope, AstNode *...@@ -4695,7 +4695,7 @@ static IrInstruction *ir_gen_if_var_expr(IrBuilder *irb, Scope *scope, AstNode *
4695 IrBasicBlock *endif_block = ir_build_basic_block(irb, scope, "MaybeEndIf");4695 IrBasicBlock *endif_block = ir_build_basic_block(irb, scope, "MaybeEndIf");
46964696
4697 IrInstruction *is_comptime;4697 IrInstruction *is_comptime;
4698 if (ir_should_inline(irb->exec, scope) || node->data.if_var_expr.is_inline) {4698 if (ir_should_inline(irb->exec, scope)) {
4699 is_comptime = ir_build_const_bool(irb, scope, node, true);4699 is_comptime = ir_build_const_bool(irb, scope, node, true);
4700 } else {4700 } else {
4701 is_comptime = ir_build_test_comptime(irb, scope, node, is_non_null);4701 is_comptime = ir_build_test_comptime(irb, scope, node, is_non_null);
...@@ -4807,7 +4807,7 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode *...@@ -4807,7 +4807,7 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode *
4807 ZigList<IrInstructionSwitchBrCase> cases = {0};4807 ZigList<IrInstructionSwitchBrCase> cases = {0};
48084808
4809 IrInstruction *is_comptime;4809 IrInstruction *is_comptime;
4810 if (ir_should_inline(irb->exec, scope) || node->data.switch_expr.is_inline) {4810 if (ir_should_inline(irb->exec, scope)) {
4811 is_comptime = ir_build_const_bool(irb, scope, node, true);4811 is_comptime = ir_build_const_bool(irb, scope, node, true);
4812 } else {4812 } else {
4813 is_comptime = ir_build_test_comptime(irb, scope, node, target_value);4813 is_comptime = ir_build_test_comptime(irb, scope, node, target_value);
...@@ -5002,7 +5002,7 @@ static IrInstruction *ir_gen_break(IrBuilder *irb, Scope *scope, AstNode *node)...@@ -5002,7 +5002,7 @@ static IrInstruction *ir_gen_break(IrBuilder *irb, Scope *scope, AstNode *node)
5002 LoopStackItem *loop_stack_item = &irb->loop_stack.last();5002 LoopStackItem *loop_stack_item = &irb->loop_stack.last();
50035003
5004 IrInstruction *is_comptime;5004 IrInstruction *is_comptime;
5005 if (ir_should_inline(irb->exec, scope) || node->data.break_expr.is_inline) {5005 if (ir_should_inline(irb->exec, scope)) {
5006 is_comptime = ir_build_const_bool(irb, scope, node, true);5006 is_comptime = ir_build_const_bool(irb, scope, node, true);
5007 } else {5007 } else {
5008 is_comptime = loop_stack_item->is_comptime;5008 is_comptime = loop_stack_item->is_comptime;
...@@ -5025,7 +5025,7 @@ static IrInstruction *ir_gen_continue(IrBuilder *irb, Scope *scope, AstNode *nod...@@ -5025,7 +5025,7 @@ static IrInstruction *ir_gen_continue(IrBuilder *irb, Scope *scope, AstNode *nod
5025 LoopStackItem *loop_stack_item = &irb->loop_stack.last();5025 LoopStackItem *loop_stack_item = &irb->loop_stack.last();
50265026
5027 IrInstruction *is_comptime;5027 IrInstruction *is_comptime;
5028 if (ir_should_inline(irb->exec, scope) || node->data.continue_expr.is_inline) {5028 if (ir_should_inline(irb->exec, scope)) {
5029 is_comptime = ir_build_const_bool(irb, scope, node, true);5029 is_comptime = ir_build_const_bool(irb, scope, node, true);
5030 } else {5030 } else {
5031 is_comptime = loop_stack_item->is_comptime;5031 is_comptime = loop_stack_item->is_comptime;
src/parser.cpp+12-43
...@@ -1313,30 +1313,17 @@ static AstNode *ast_parse_else(ParseContext *pc, size_t *token_index, bool manda...@@ -1313,30 +1313,17 @@ static AstNode *ast_parse_else(ParseContext *pc, size_t *token_index, bool manda
13131313
1314/*1314/*
1315IfExpression : IfVarExpression | IfBoolExpression1315IfExpression : IfVarExpression | IfBoolExpression
1316IfBoolExpression = option("inline") "if" "(" Expression ")" Expression option(Else)1316IfBoolExpression = "if" "(" Expression ")" Expression option(Else)
1317IfVarExpression = option("inline") "if" "(" ("const" | "var") option("*") Symbol option(":" TypeExpr) "?=" Expression ")" Expression Option(Else)1317IfVarExpression = "if" "(" ("const" | "var") option("*") Symbol option(":" TypeExpr) "?=" Expression ")" Expression Option(Else)
1318*/1318*/
1319static AstNode *ast_parse_if_expr(ParseContext *pc, size_t *token_index, bool mandatory) {1319static AstNode *ast_parse_if_expr(ParseContext *pc, size_t *token_index, bool mandatory) {
1320 Token *first_token = &pc->tokens->at(*token_index);1320 Token *if_token = &pc->tokens->at(*token_index);
1321 Token *if_tok;
13221321
1323 bool is_inline;1322 if (if_token->id == TokenIdKeywordIf) {
1324 if (first_token->id == TokenIdKeywordInline) {
1325 if_tok = &pc->tokens->at(*token_index + 1);
1326 if (if_tok->id == TokenIdKeywordIf) {
1327 is_inline = true;
1328 *token_index += 2;
1329 } else if (mandatory) {
1330 ast_expect_token(pc, if_tok, TokenIdKeywordIf);
1331 } else {
1332 return nullptr;
1333 }
1334 } else if (first_token->id == TokenIdKeywordIf) {
1335 if_tok = first_token;
1336 is_inline = false;
1337 *token_index += 1;1323 *token_index += 1;
1338 } else if (mandatory) {1324 } else if (mandatory) {
1339 ast_expect_token(pc, first_token, TokenIdKeywordIf);1325 ast_expect_token(pc, if_token, TokenIdKeywordIf);
1326 zig_unreachable();
1340 } else {1327 } else {
1341 return nullptr;1328 return nullptr;
1342 }1329 }
...@@ -1345,8 +1332,7 @@ static AstNode *ast_parse_if_expr(ParseContext *pc, size_t *token_index, bool ma...@@ -1345,8 +1332,7 @@ static AstNode *ast_parse_if_expr(ParseContext *pc, size_t *token_index, bool ma
13451332
1346 Token *token = &pc->tokens->at(*token_index);1333 Token *token = &pc->tokens->at(*token_index);
1347 if (token->id == TokenIdKeywordConst || token->id == TokenIdKeywordVar) {1334 if (token->id == TokenIdKeywordConst || token->id == TokenIdKeywordVar) {
1348 AstNode *node = ast_create_node(pc, NodeTypeIfVarExpr, if_tok);1335 AstNode *node = ast_create_node(pc, NodeTypeIfVarExpr, if_token);
1349 node->data.if_var_expr.is_inline = is_inline;
1350 node->data.if_var_expr.var_decl.is_const = (token->id == TokenIdKeywordConst);1336 node->data.if_var_expr.var_decl.is_const = (token->id == TokenIdKeywordConst);
1351 *token_index += 1;1337 *token_index += 1;
13521338
...@@ -1383,8 +1369,7 @@ static AstNode *ast_parse_if_expr(ParseContext *pc, size_t *token_index, bool ma...@@ -1383,8 +1369,7 @@ static AstNode *ast_parse_if_expr(ParseContext *pc, size_t *token_index, bool ma
13831369
1384 return node;1370 return node;
1385 } else {1371 } else {
1386 AstNode *node = ast_create_node(pc, NodeTypeIfBoolExpr, if_tok);1372 AstNode *node = ast_create_node(pc, NodeTypeIfBoolExpr, if_token);
1387 node->data.if_bool_expr.is_inline = is_inline;
1388 node->data.if_bool_expr.condition = ast_parse_expression(pc, token_index, true);1373 node->data.if_bool_expr.condition = ast_parse_expression(pc, token_index, true);
1389 ast_eat_token(pc, token_index, TokenIdRParen);1374 ast_eat_token(pc, token_index, TokenIdRParen);
1390 node->data.if_bool_expr.then_block = ast_parse_expression(pc, token_index, true);1375 node->data.if_bool_expr.then_block = ast_parse_expression(pc, token_index, true);
...@@ -1700,38 +1685,22 @@ static AstNode *ast_parse_for_expr(ParseContext *pc, size_t *token_index, bool m...@@ -1700,38 +1685,22 @@ static AstNode *ast_parse_for_expr(ParseContext *pc, size_t *token_index, bool m
1700}1685}
17011686
1702/*1687/*
1703SwitchExpression = option("inline") "switch" "(" Expression ")" "{" many(SwitchProng) "}"1688SwitchExpression = "switch" "(" Expression ")" "{" many(SwitchProng) "}"
1704SwitchProng = (list(SwitchItem, ",") | "else") "=>" option("|" option("*") Symbol "|") Expression ","1689SwitchProng = (list(SwitchItem, ",") | "else") "=>" option("|" option("*") Symbol "|") Expression ","
1705SwitchItem : Expression | (Expression "..." Expression)1690SwitchItem : Expression | (Expression "..." Expression)
1706*/1691*/
1707static AstNode *ast_parse_switch_expr(ParseContext *pc, size_t *token_index, bool mandatory) {1692static AstNode *ast_parse_switch_expr(ParseContext *pc, size_t *token_index, bool mandatory) {
1708 Token *first_token = &pc->tokens->at(*token_index);1693 Token *switch_token = &pc->tokens->at(*token_index);
1709 Token *switch_token;1694 if (switch_token->id == TokenIdKeywordSwitch) {
1710 bool is_inline;
1711 if (first_token->id == TokenIdKeywordInline) {
1712 is_inline = true;
1713 switch_token = &pc->tokens->at(*token_index + 1);
1714 if (switch_token->id == TokenIdKeywordSwitch) {
1715 *token_index += 2;
1716 } else if (mandatory) {
1717 ast_expect_token(pc, first_token, TokenIdKeywordSwitch);
1718 zig_unreachable();
1719 } else {
1720 return nullptr;
1721 }
1722 } else if (first_token->id == TokenIdKeywordSwitch) {
1723 is_inline = false;
1724 switch_token = first_token;
1725 *token_index += 1;1695 *token_index += 1;
1726 } else if (mandatory) {1696 } else if (mandatory) {
1727 ast_expect_token(pc, first_token, TokenIdKeywordSwitch);1697 ast_expect_token(pc, switch_token, TokenIdKeywordSwitch);
1728 zig_unreachable();1698 zig_unreachable();
1729 } else {1699 } else {
1730 return nullptr;1700 return nullptr;
1731 }1701 }
17321702
1733 AstNode *node = ast_create_node(pc, NodeTypeSwitchExpr, switch_token);1703 AstNode *node = ast_create_node(pc, NodeTypeSwitchExpr, switch_token);
1734 node->data.switch_expr.is_inline = is_inline;
17351704
1736 ast_eat_token(pc, token_index, TokenIdLParen);1705 ast_eat_token(pc, token_index, TokenIdLParen);
1737 node->data.switch_expr.expr = ast_parse_expression(pc, token_index, true);1706 node->data.switch_expr.expr = ast_parse_expression(pc, token_index, true);
std/io.zig+1-1
...@@ -150,7 +150,7 @@ pub const OutStream = struct {...@@ -150,7 +150,7 @@ pub const OutStream = struct {
150 @compileError("Incomplete format string: " ++ format);150 @compileError("Incomplete format string: " ++ format);
151 }151 }
152 }152 }
153 inline if (start_index < format.len) {153 if (start_index < format.len) {
154 %return self.write(format[start_index...format.len]);154 %return self.write(format[start_index...format.len]);
155 }155 }
156 %return self.flush();156 %return self.flush();
test/cases/switch.zig+6-3
...@@ -33,18 +33,21 @@ fn testSwitchWithAllRanges(x: u32, y: u32) -> u32 {...@@ -33,18 +33,21 @@ fn testSwitchWithAllRanges(x: u32, y: u32) -> u32 {
33 }33 }
34}34}
3535
36fn inlineSwitch() {36fn implicitComptimeSwitch() {
37 @setFnTest(this);37 @setFnTest(this);
3838
39 const x = 3 + 4;39 const x = 3 + 4;
40 const result = inline switch (x) {40 const result = switch (x) {
41 3 => 10,41 3 => 10,
42 4 => 11,42 4 => 11,
43 5, 6 => 12,43 5, 6 => 12,
44 7, 8 => 13,44 7, 8 => 13,
45 else => 14,45 else => 14,
46 };46 };
47 assert(result + 1 == 14);47
48 comptime {
49 assert(result + 1 == 14);
50 }
48}51}
4952
50fn switchOnEnum() {53fn switchOnEnum() {