1 /// Copyright: Copyright (c) 2017-2019 Andrey Penechko. 2 /// License: $(WEB boost.org/LICENSE_1_0.txt, Boost License 1.0). 3 /// Authors: Andrey Penechko. 4 module vox.fe.ast.stmt.if_stmt; 5 6 import vox.all; 7 8 9 @(AstType.stmt_if) 10 struct IfStmtNode 11 { 12 mixin AstNodeData!(AstType.stmt_if, 0, AstNodeState.name_register_self_done); 13 AstIndex condition; 14 AstNodes thenStatements; // can be empty 15 AstNodes elseStatements; // can be empty 16 } 17 18 void print_if(IfStmtNode* node, ref AstPrintState state) 19 { 20 state.print("IF"); 21 print_ast(node.condition, state); 22 state.print("THEN"); 23 print_ast(node.thenStatements, state); 24 if (!node.elseStatements.empty) 25 { 26 state.print("ELSE"); 27 print_ast(node.elseStatements, state); 28 } 29 } 30 31 void post_clone_if(IfStmtNode* node, ref CloneState state) 32 { 33 state.fixAstIndex(node.condition); 34 state.fixAstNodes(node.thenStatements); 35 state.fixAstNodes(node.elseStatements); 36 } 37 38 void name_register_nested_if(IfStmtNode* node, ref NameRegisterState state) 39 { 40 node.state = AstNodeState.name_register_nested; 41 require_name_register(node.condition, state); 42 require_name_register(node.thenStatements, state); 43 require_name_register(node.elseStatements, state); 44 node.state = AstNodeState.name_register_nested_done; 45 } 46 47 void name_resolve_if(IfStmtNode* node, ref NameResolveState state) 48 { 49 node.state = AstNodeState.name_resolve; 50 require_name_resolve(node.condition, state); 51 require_name_resolve(node.thenStatements, state); 52 require_name_resolve(node.elseStatements, state); 53 node.state = AstNodeState.name_resolve_done; 54 } 55 56 void type_check_if(IfStmtNode* node, ref TypeCheckState state) 57 { 58 node.state = AstNodeState.type_check; 59 require_type_check(node.condition, state); 60 autoconvToBool(node.condition, state.context); 61 require_type_check(node.thenStatements, state); 62 require_type_check(node.elseStatements, state); 63 node.state = AstNodeState.type_check_done; 64 } 65 66 void ir_gen_if(ref IrGenState gen, IrIndex currentBlock, ref IrLabel nextStmt, IfStmtNode* i) 67 { 68 CompilationContext* c = gen.context; 69 if (!i.elseStatements.empty) // if then else 70 { 71 IrLabel trueLabel = IrLabel(currentBlock); 72 IrLabel falseLabel = IrLabel(currentBlock); 73 ir_gen_branch(gen, i.condition, currentBlock, trueLabel, falseLabel); 74 75 if (trueLabel.numPredecessors != 0) 76 { 77 IrIndex thenBlock = trueLabel.blockIndex; 78 gen.builder.sealBlock(thenBlock); 79 genBlock(gen, i.as!AstNode(c), i.thenStatements, thenBlock, nextStmt); 80 } 81 82 if (falseLabel.numPredecessors != 0) 83 { 84 IrIndex elseBlock = falseLabel.blockIndex; 85 gen.builder.sealBlock(elseBlock); 86 genBlock(gen, i.as!AstNode(c), i.elseStatements, elseBlock, nextStmt); 87 } 88 } 89 else // if then 90 { 91 IrLabel trueLabel = IrLabel(currentBlock); 92 ir_gen_branch(gen, i.condition, currentBlock, trueLabel, nextStmt); 93 94 if (trueLabel.numPredecessors != 0) 95 { 96 IrIndex thenBlock = trueLabel.blockIndex; 97 gen.builder.sealBlock(thenBlock); 98 genBlock(gen, i.as!AstNode(c), i.thenStatements, thenBlock, nextStmt); 99 } 100 } 101 }