-
Notifications
You must be signed in to change notification settings - Fork 13
/
Copy pathscriptingConstCondProc.h
145 lines (118 loc) · 3.69 KB
/
scriptingConstCondProc.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
/*
Written by Antoine Savine in 2018
This code is the strict IP of Antoine Savine
License to use and alter this code for personal and commercial applications
is freely granted to any person or company who purchased a copy of the book
Modern Computational Finance: Scripting for Derivatives and XVA
Jesper Andreasen & Antoine Savine
Wiley, 2018
As long as this comment is preserved at the top of the file
*/
#pragma once
#include "scriptingNodes.h"
// ConstCond processor
// Processes all constant (always true/false) conditions and conditional statements
// Remove all the if and condition nodes that are always true or always false
// The domain proc must have been run first, so always true/false flags are properly set inside the nodes
// The always true/false if nodes are replaced by collections of statements to be evaluated
// The always true/false conditions are replaced by true/false nodes
class ConstCondProcessor : public Visitor<ConstCondProcessor>
{
// The (unique) pointer on the node currently being visited
ExprTree* myCurrent;
// Visit arguments plus set myCurrent pointer
void visitArgsSetCurrent(Node& node)
{
for( auto& arg : node.arguments)
{
myCurrent = &arg;
arg->accept(*this);
}
}
public:
// Overload catch-all-nodes visitor to visit arguments plus set myCurrent
template <class NODE>
enable_if_t<is_same<NODE, remove_const_t<NODE>>::value && !hasConstVisit<ConstCondProcessor>::forNodeType<NODE>()> visit(NODE& node)
{
visitArgsSetCurrent(node);
}
// This patricular visitor modifies the structure of the tree, hence it must be called only
// with this method from the top of every tree, passing a ref on the unique_ptr holding
// the top node of the tree
void processFromTop( unique_ptr<Node>& top)
{
myCurrent = ⊤
top->accept(*this);
}
// Conditions
// One visitor for all booleans
void visitBool(boolNode& node)
{
// Always true ==> replace the tree by a True node
if(node.alwaysTrue) myCurrent->reset( new NodeTrue);
// Always false ==> replace the tree by a False node
else if(node.alwaysFalse) myCurrent->reset( new NodeFalse);
// Nothing to do here ==> visit the arguments
else visitArgsSetCurrent(node);
}
// Visitors
void visit(NodeEqual& node)
{
visitBool( node);
}
void visit(NodeSup& node)
{
visitBool(node);
}
void visit(NodeSupEqual& node)
{
visitBool(node);
}
void visit( NodeNot& node)
{
visitBool( node);
}
void visit( NodeAnd& node)
{
visitBool( node);
}
void visit( NodeOr& node)
{
visitBool( node);
}
// If
void visit(NodeIf& node)
{
// Always true ==> replace the tree by the collection of "if true" statements
if(node.alwaysTrue)
{
size_t lastTrueStat = node.firstElse == -1? node.arguments.size()-1: node.firstElse-1;
// Move arguments, destroy node
vector<ExprTree> args = move( node.arguments);
myCurrent->reset( new NodeCollect);
for(size_t i=1; i<=lastTrueStat; ++i)
{
(*myCurrent)->arguments.push_back( move( args[i]));
}
visitArgsSetCurrent( **myCurrent);
}
// Always false ==> replace the tree by the collection of "else" statements
else if( node.alwaysFalse)
{
int firstElseStatement = node.firstElse;
// Move arguments, destroy node
vector<ExprTree> args = move( node.arguments);
myCurrent->reset( new NodeCollect);
if( firstElseStatement != -1)
{
for(size_t i=firstElseStatement; i<args.size(); ++i)
{
(*myCurrent)->arguments.push_back( move( args[i]));
}
}
visitArgsSetCurrent( **myCurrent);
}
// Nothing to do here ==> visit the arguments
else visitArgsSetCurrent(node);
}
};