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 }