From b78c91951a1db34c615a011e0444608285f1a74c Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Thu, 2 Feb 2017 13:23:18 -0500 Subject: [PATCH] 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) ... ``` --- doc/langref.md | 6 ++--- src/all_types.hpp | 5 ---- src/ast_render.cpp | 6 ++--- src/ir.cpp | 10 ++++---- src/parser.cpp | 55 ++++++++++--------------------------------- std/io.zig | 2 +- test/cases/switch.zig | 9 ++++--- 7 files changed, 29 insertions(+), 64 deletions(-) diff --git a/doc/langref.md b/doc/langref.md index a24085c2bf..5851232504 100644 --- a/doc/langref.md +++ b/doc/langref.md @@ -73,7 +73,7 @@ BlockExpression = IfExpression | Block | WhileExpression | ForExpression | Switc CompTimeExpression = option("comptime") Expression -SwitchExpression = option("inline") "switch" "(" Expression ")" "{" many(SwitchProng) "}" +SwitchExpression = "switch" "(" Expression ")" "{" many(SwitchProng) "}" SwitchProng = (list(SwitchItem, ",") | "else") "=>" option("|" option("*") Symbol "|") Expression "," @@ -91,9 +91,9 @@ Defer = option("%" | "?") "defer" Expression IfExpression = IfVarExpression | IfBoolExpression -IfBoolExpression = option("inline") "if" "(" Expression ")" Expression option(Else) +IfBoolExpression = "if" "(" Expression ")" Expression option(Else) -IfVarExpression = option("inline") "if" "(" ("const" | "var") option("*") Symbol option(":" TypeExpr) "?=" Expression ")" Expression Option(Else) +IfVarExpression = "if" "(" ("const" | "var") option("*") Symbol option(":" TypeExpr) "?=" Expression ")" Expression Option(Else) Else = "else" Expression diff --git a/src/all_types.hpp b/src/all_types.hpp index 7fe4c9cf22..98a6d31dcf 100644 --- a/src/all_types.hpp +++ b/src/all_types.hpp @@ -509,7 +509,6 @@ struct AstNodeIfBoolExpr { AstNode *condition; AstNode *then_block; AstNode *else_node; // null, block node, or other if expr node - bool is_inline; }; struct AstNodeIfVarExpr { @@ -517,7 +516,6 @@ struct AstNodeIfVarExpr { AstNode *then_block; AstNode *else_node; // null, block node, or other if expr node bool var_is_ptr; - bool is_inline; }; struct AstNodeWhileExpr { @@ -539,7 +537,6 @@ struct AstNodeForExpr { struct AstNodeSwitchExpr { AstNode *expr; ZigList prongs; - bool is_inline; }; struct AstNodeSwitchProng { @@ -677,11 +674,9 @@ struct AstNodeBoolLiteral { }; struct AstNodeBreakExpr { - bool is_inline; // TODO }; struct AstNodeContinueExpr { - bool is_inline; // TODO }; struct AstNodeArrayType { diff --git a/src/ast_render.cpp b/src/ast_render.cpp index 3bba70486a..12642c71e2 100644 --- a/src/ast_render.cpp +++ b/src/ast_render.cpp @@ -844,14 +844,12 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) { } case NodeTypeBreak: { - const char *inline_str = node->data.break_expr.is_inline ? "inline " : ""; - fprintf(ar->f, "%sbreak", inline_str); + fprintf(ar->f, "break"); break; } case NodeTypeContinue: { - const char *inline_str = node->data.continue_expr.is_inline ? "inline " : ""; - fprintf(ar->f, "%scontinue", inline_str); + fprintf(ar->f, "continue"); break; } case NodeTypeSliceExpr: diff --git a/src/ir.cpp b/src/ir.cpp index ed4382d415..85afc93245 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -4148,7 +4148,7 @@ static IrInstruction *ir_gen_if_bool_expr(IrBuilder *irb, Scope *scope, AstNode return condition; IrInstruction *is_comptime; - if (ir_should_inline(irb->exec, scope) || node->data.if_bool_expr.is_inline) { + if (ir_should_inline(irb->exec, scope)) { is_comptime = ir_build_const_bool(irb, scope, node, true); } else { 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 * IrBasicBlock *endif_block = ir_build_basic_block(irb, scope, "MaybeEndIf"); IrInstruction *is_comptime; - if (ir_should_inline(irb->exec, scope) || node->data.if_var_expr.is_inline) { + if (ir_should_inline(irb->exec, scope)) { is_comptime = ir_build_const_bool(irb, scope, node, true); } else { 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 * ZigList cases = {0}; IrInstruction *is_comptime; - if (ir_should_inline(irb->exec, scope) || node->data.switch_expr.is_inline) { + if (ir_should_inline(irb->exec, scope)) { is_comptime = ir_build_const_bool(irb, scope, node, true); } else { 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) LoopStackItem *loop_stack_item = &irb->loop_stack.last(); IrInstruction *is_comptime; - if (ir_should_inline(irb->exec, scope) || node->data.break_expr.is_inline) { + if (ir_should_inline(irb->exec, scope)) { is_comptime = ir_build_const_bool(irb, scope, node, true); } else { is_comptime = loop_stack_item->is_comptime; @@ -5025,7 +5025,7 @@ static IrInstruction *ir_gen_continue(IrBuilder *irb, Scope *scope, AstNode *nod LoopStackItem *loop_stack_item = &irb->loop_stack.last(); IrInstruction *is_comptime; - if (ir_should_inline(irb->exec, scope) || node->data.continue_expr.is_inline) { + if (ir_should_inline(irb->exec, scope)) { is_comptime = ir_build_const_bool(irb, scope, node, true); } else { is_comptime = loop_stack_item->is_comptime; diff --git a/src/parser.cpp b/src/parser.cpp index 02926db46a..1b79da9b2b 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -1313,30 +1313,17 @@ static AstNode *ast_parse_else(ParseContext *pc, size_t *token_index, bool manda /* IfExpression : IfVarExpression | IfBoolExpression -IfBoolExpression = option("inline") "if" "(" Expression ")" Expression option(Else) -IfVarExpression = option("inline") "if" "(" ("const" | "var") option("*") Symbol option(":" TypeExpr) "?=" Expression ")" Expression Option(Else) +IfBoolExpression = "if" "(" Expression ")" Expression option(Else) +IfVarExpression = "if" "(" ("const" | "var") option("*") Symbol option(":" TypeExpr) "?=" Expression ")" Expression Option(Else) */ static AstNode *ast_parse_if_expr(ParseContext *pc, size_t *token_index, bool mandatory) { - Token *first_token = &pc->tokens->at(*token_index); - Token *if_tok; + Token *if_token = &pc->tokens->at(*token_index); - bool is_inline; - if (first_token->id == TokenIdKeywordInline) { - if_tok = &pc->tokens->at(*token_index + 1); - if (if_tok->id == TokenIdKeywordIf) { - is_inline = true; - *token_index += 2; - } else if (mandatory) { - ast_expect_token(pc, if_tok, TokenIdKeywordIf); - } else { - return nullptr; - } - } else if (first_token->id == TokenIdKeywordIf) { - if_tok = first_token; - is_inline = false; + if (if_token->id == TokenIdKeywordIf) { *token_index += 1; } else if (mandatory) { - ast_expect_token(pc, first_token, TokenIdKeywordIf); + ast_expect_token(pc, if_token, TokenIdKeywordIf); + zig_unreachable(); } else { return nullptr; } @@ -1345,8 +1332,7 @@ static AstNode *ast_parse_if_expr(ParseContext *pc, size_t *token_index, bool ma Token *token = &pc->tokens->at(*token_index); if (token->id == TokenIdKeywordConst || token->id == TokenIdKeywordVar) { - AstNode *node = ast_create_node(pc, NodeTypeIfVarExpr, if_tok); - node->data.if_var_expr.is_inline = is_inline; + AstNode *node = ast_create_node(pc, NodeTypeIfVarExpr, if_token); node->data.if_var_expr.var_decl.is_const = (token->id == TokenIdKeywordConst); *token_index += 1; @@ -1383,8 +1369,7 @@ static AstNode *ast_parse_if_expr(ParseContext *pc, size_t *token_index, bool ma return node; } else { - AstNode *node = ast_create_node(pc, NodeTypeIfBoolExpr, if_tok); - node->data.if_bool_expr.is_inline = is_inline; + AstNode *node = ast_create_node(pc, NodeTypeIfBoolExpr, if_token); node->data.if_bool_expr.condition = ast_parse_expression(pc, token_index, true); ast_eat_token(pc, token_index, TokenIdRParen); node->data.if_bool_expr.then_block = ast_parse_expression(pc, token_index, true); @@ -1700,38 +1685,22 @@ static AstNode *ast_parse_for_expr(ParseContext *pc, size_t *token_index, bool m } /* -SwitchExpression = option("inline") "switch" "(" Expression ")" "{" many(SwitchProng) "}" +SwitchExpression = "switch" "(" Expression ")" "{" many(SwitchProng) "}" SwitchProng = (list(SwitchItem, ",") | "else") "=>" option("|" option("*") Symbol "|") Expression "," SwitchItem : Expression | (Expression "..." Expression) */ static AstNode *ast_parse_switch_expr(ParseContext *pc, size_t *token_index, bool mandatory) { - Token *first_token = &pc->tokens->at(*token_index); - Token *switch_token; - bool is_inline; - if (first_token->id == TokenIdKeywordInline) { - is_inline = true; - switch_token = &pc->tokens->at(*token_index + 1); - if (switch_token->id == TokenIdKeywordSwitch) { - *token_index += 2; - } else if (mandatory) { - ast_expect_token(pc, first_token, TokenIdKeywordSwitch); - zig_unreachable(); - } else { - return nullptr; - } - } else if (first_token->id == TokenIdKeywordSwitch) { - is_inline = false; - switch_token = first_token; + Token *switch_token = &pc->tokens->at(*token_index); + if (switch_token->id == TokenIdKeywordSwitch) { *token_index += 1; } else if (mandatory) { - ast_expect_token(pc, first_token, TokenIdKeywordSwitch); + ast_expect_token(pc, switch_token, TokenIdKeywordSwitch); zig_unreachable(); } else { return nullptr; } AstNode *node = ast_create_node(pc, NodeTypeSwitchExpr, switch_token); - node->data.switch_expr.is_inline = is_inline; ast_eat_token(pc, token_index, TokenIdLParen); node->data.switch_expr.expr = ast_parse_expression(pc, token_index, true); diff --git a/std/io.zig b/std/io.zig index d4edc89981..d0c7f407bd 100644 --- a/std/io.zig +++ b/std/io.zig @@ -150,7 +150,7 @@ pub const OutStream = struct { @compileError("Incomplete format string: " ++ format); } } - inline if (start_index < format.len) { + if (start_index < format.len) { %return self.write(format[start_index...format.len]); } %return self.flush(); diff --git a/test/cases/switch.zig b/test/cases/switch.zig index edb42c871d..9d831bd356 100644 --- a/test/cases/switch.zig +++ b/test/cases/switch.zig @@ -33,18 +33,21 @@ fn testSwitchWithAllRanges(x: u32, y: u32) -> u32 { } } -fn inlineSwitch() { +fn implicitComptimeSwitch() { @setFnTest(this); const x = 3 + 4; - const result = inline switch (x) { + const result = switch (x) { 3 => 10, 4 => 11, 5, 6 => 12, 7, 8 => 13, else => 14, }; - assert(result + 1 == 14); + + comptime { + assert(result + 1 == 14); + } } fn switchOnEnum() {