23#include <ql/errors.hpp>
31class ASTToScriptConverter :
public AcyclicVisitor,
32 public Visitor<ASTNode>,
33 public Visitor<OperatorPlusNode>,
34 public Visitor<OperatorMinusNode>,
35 public Visitor<OperatorMultiplyNode>,
36 public Visitor<OperatorDivideNode>,
37 public Visitor<NegateNode>,
38 public Visitor<FunctionAbsNode>,
39 public Visitor<FunctionExpNode>,
40 public Visitor<FunctionLogNode>,
41 public Visitor<FunctionSqrtNode>,
42 public Visitor<FunctionNormalCdfNode>,
43 public Visitor<FunctionNormalPdfNode>,
44 public Visitor<FunctionMinNode>,
45 public Visitor<FunctionMaxNode>,
46 public Visitor<FunctionPowNode>,
47 public Visitor<FunctionBlackNode>,
48 public Visitor<FunctionDcfNode>,
49 public Visitor<FunctionDaysNode>,
50 public Visitor<FunctionPayNode>,
51 public Visitor<FunctionLogPayNode>,
52 public Visitor<FunctionNpvNode>,
53 public Visitor<FunctionNpvMemNode>,
54 public Visitor<HistFixingNode>,
55 public Visitor<FunctionDiscountNode>,
56 public Visitor<FunctionFwdCompNode>,
57 public Visitor<FunctionFwdAvgNode>,
58 public Visitor<FunctionAboveProbNode>,
59 public Visitor<FunctionBelowProbNode>,
60 public Visitor<FunctionDateIndexNode>,
61 public Visitor<SortNode>,
62 public Visitor<PermuteNode>,
63 public Visitor<ConstantNumberNode>,
64 public Visitor<VariableNode>,
65 public Visitor<SizeOpNode>,
66 public Visitor<VarEvaluationNode>,
67 public Visitor<AssignmentNode>,
68 public Visitor<RequireNode>,
69 public Visitor<DeclarationNumberNode>,
70 public Visitor<SequenceNode>,
71 public Visitor<ConditionEqNode>,
72 public Visitor<ConditionNeqNode>,
73 public Visitor<ConditionLtNode>,
74 public Visitor<ConditionLeqNode>,
75 public Visitor<ConditionGtNode>,
76 public Visitor<ConditionGeqNode>,
77 public Visitor<ConditionNotNode>,
78 public Visitor<ConditionAndNode>,
79 public Visitor<ConditionOrNode>,
80 public Visitor<IfThenElseNode>,
81 public Visitor<LoopNode> {
83 ASTToScriptConverter() :
indent(0) {}
85 void visit(ASTNode& n)
override { QL_FAIL(
"ASTToScriptConverter(): unknown node type"); }
87 void visit(OperatorPlusNode& n)
override {
88 n.args[0]->accept(*
this);
90 n.args[1]->accept(*
this);
92 script =
"(" + left +
" + " + right +
")";
95 void visit(OperatorMinusNode& n)
override {
96 n.args[0]->accept(*
this);
98 n.args[1]->accept(*
this);
100 script =
"(" + left +
" - (" + right +
"))";
103 void visit(OperatorMultiplyNode& n)
override {
104 n.args[0]->accept(*
this);
106 n.args[1]->accept(*
this);
108 script =
"(" + left +
" * " + right +
")";
111 void visit(OperatorDivideNode& n)
override {
112 n.args[0]->accept(*
this);
114 n.args[1]->accept(*
this);
116 script =
"(" + left +
" / (" + right +
"))";
119 void visit(NegateNode& n)
override {
120 n.args[0]->accept(*
this);
124 void visit(FunctionAbsNode& n)
override {
125 n.args[0]->accept(*
this);
129 void visit(FunctionExpNode& n)
override {
130 n.args[0]->accept(*
this);
134 void visit(FunctionLogNode& n)
override {
135 n.args[0]->accept(*
this);
139 void visit(FunctionSqrtNode& n)
override {
140 n.args[0]->accept(*
this);
144 void visit(FunctionNormalCdfNode& n)
override {
145 n.args[0]->accept(*
this);
149 void visit(FunctionNormalPdfNode& n)
override {
150 n.args[0]->accept(*
this);
154 void visit(FunctionMinNode& n)
override {
155 n.args[0]->accept(*
this);
157 n.args[1]->accept(*
this);
159 script =
"min(" + left +
", " + right +
")";
162 void visit(FunctionMaxNode& n)
override {
163 n.args[0]->accept(*
this);
165 n.args[1]->accept(*
this);
167 script =
"max(" + left +
", " + right +
")";
170 void visit(FunctionPowNode& n)
override {
171 n.args[0]->accept(*
this);
173 n.args[1]->accept(*
this);
175 script =
"pow(" + left +
", " + right +
")";
178 void visit(FunctionBlackNode& n)
override {
179 n.args[0]->accept(*
this);
181 n.args[1]->accept(*
this);
183 n.args[2]->accept(*
this);
185 n.args[3]->accept(*
this);
187 n.args[4]->accept(*
this);
189 n.args[5]->accept(*
this);
191 script =
"black(" + arg1 +
", " + arg2 +
", " + arg3 +
", " + arg4 +
", " + arg5 +
", " + arg6 +
")";
194 void visit(FunctionDcfNode& n)
override {
195 n.args[0]->accept(*
this);
197 n.args[1]->accept(*
this);
199 n.args[2]->accept(*
this);
201 script =
"dcf(" + arg1 +
", " + arg2 +
", " + arg3 +
")";
204 void visit(FunctionDaysNode& n)
override {
205 n.args[0]->accept(*
this);
207 n.args[1]->accept(*
this);
209 n.args[2]->accept(*
this);
211 script =
"days(" + arg1 +
", " + arg2 +
", " + arg3 +
")";
214 void visit(FunctionPayNode& n)
override {
215 n.args[0]->accept(*
this);
217 n.args[1]->accept(*
this);
219 n.args[2]->accept(*
this);
221 n.args[3]->accept(*
this);
223 script =
"PAY(" + arg1 +
", " + arg2 +
", " + arg3 +
", " + arg4 +
")";
226 void visit(FunctionLogPayNode& n)
override {
227 n.args[0]->accept(*
this);
229 n.args[1]->accept(*
this);
231 n.args[2]->accept(*
this);
233 n.args[3]->accept(*
this);
237 n.args[4]->accept(*
this);
242 n.args[5]->accept(*
this);
247 n.args[6]->accept(*
this);
250 script =
"LOGPAY(" + arg1 +
", " + arg2 +
", " + arg3 +
", " + arg4;
260 void visit(FunctionNpvNode& n)
override {
261 n.args[0]->accept(*
this);
263 n.args[1]->accept(*
this);
267 n.args[2]->accept(*
this);
272 n.args[3]->accept(*
this);
277 n.args[4]->accept(*
this);
280 script =
"NPV(" + arg1 +
", " + arg2;
290 void visit(FunctionNpvMemNode& n)
override {
291 n.args[0]->accept(*
this);
293 n.args[1]->accept(*
this);
295 n.args[2]->accept(*
this);
299 n.args[3]->accept(*
this);
304 n.args[4]->accept(*
this);
309 n.args[5]->accept(*
this);
312 script =
"NPVMEM(" + arg1 +
", " + arg2 +
", " + arg3;
322 void visit(HistFixingNode& n)
override {
323 n.args[0]->accept(*
this);
325 n.args[1]->accept(*
this);
327 script =
"HISTFIXING(" + arg1 +
", " + arg2 +
")";
330 void visit(FunctionDiscountNode& n)
override {
331 n.args[0]->accept(*
this);
333 n.args[1]->accept(*
this);
335 n.args[2]->accept(*
this);
337 script =
"DISCOUNT(" + arg1 +
", " + arg2 +
", " + arg3 +
")";
340 void visit(FunctionFwdCompNode& n)
override {
341 n.args[0]->accept(*
this);
343 n.args[1]->accept(*
this);
345 n.args[2]->accept(*
this);
347 n.args[3]->accept(*
this);
351 n.args[4]->accept(*
this);
356 n.args[5]->accept(*
this);
361 n.args[6]->accept(*
this);
366 n.args[7]->accept(*
this);
371 n.args[8]->accept(*
this);
376 n.args[9]->accept(*
this);
381 n.args[10]->accept(*
this);
386 n.args[11]->accept(*
this);
391 n.args[12]->accept(*
this);
396 n.args[13]->accept(*
this);
399 script =
"FWDCOMP(" + arg1 +
", " + arg2 +
", " + arg3 +
", " + arg4;
439 script +=
", " + arg14 +
")";
452 void visit(FunctionFwdAvgNode& n)
override {
453 n.args[0]->accept(*
this);
455 n.args[1]->accept(*
this);
457 n.args[2]->accept(*
this);
459 n.args[3]->accept(*
this);
463 n.args[4]->accept(*
this);
468 n.args[5]->accept(*
this);
473 n.args[6]->accept(*
this);
478 n.args[7]->accept(*
this);
483 n.args[8]->accept(*
this);
488 n.args[9]->accept(*
this);
493 n.args[10]->accept(*
this);
498 n.args[11]->accept(*
this);
503 n.args[12]->accept(*
this);
508 n.args[13]->accept(*
this);
511 script =
"FWDAVG(" + arg1 +
", " + arg2 +
", " + arg3 +
", " + arg4;
551 script +=
", " + arg14 +
")";
564 void visit(FunctionAboveProbNode& n)
override {
565 n.args[0]->accept(*
this);
567 n.args[1]->accept(*
this);
569 n.args[2]->accept(*
this);
571 n.args[3]->accept(*
this);
573 script =
"ABOVEPROB(" + arg1 +
", " + arg2 +
", " + arg3 +
", " + arg4 +
")";
576 void visit(FunctionBelowProbNode& n)
override {
577 n.args[0]->accept(*
this);
579 n.args[1]->accept(*
this);
581 n.args[2]->accept(*
this);
583 n.args[3]->accept(*
this);
585 script =
"BELOWPROB(" + arg1 +
", " + arg2 +
", " + arg3 +
", " + arg4 +
")";
588 void visit(FunctionDateIndexNode& n)
override {
589 n.args[0]->accept(*
this);
591 script =
"DATEINDEX(" + arg1 +
", " + n.name +
"," + n.op +
")";
594 void visit(SortNode& n)
override {
595 auto v1 = QuantLib::ext::dynamic_pointer_cast<VariableNode>(n.args[0]);
596 auto v2 = QuantLib::ext::dynamic_pointer_cast<VariableNode>(n.args[1]);
597 auto v3 = QuantLib::ext::dynamic_pointer_cast<VariableNode>(n.args[2]);
598 script =
"SORT ( " + (v1 ? v1->name :
"") + (v2 ?
"," + v2->name :
"") + (v3 ?
"," + v3->name :
"") +
" )";
601 void visit(PermuteNode& n)
override {
602 auto v1 = QuantLib::ext::dynamic_pointer_cast<VariableNode>(n.args[0]);
603 auto v2 = QuantLib::ext::dynamic_pointer_cast<VariableNode>(n.args[1]);
604 auto v3 = QuantLib::ext::dynamic_pointer_cast<VariableNode>(n.args[2]);
605 script =
"PERMUTE ( " + (v1 ? v1->name :
"") + (v2 ?
"," + v2->name :
"") + (v3 ?
"," + v3->name :
"") +
" )";
608 void visit(ConstantNumberNode& n)
override {
script = std::to_string(n.value); }
610 void visit(VariableNode& n)
override {
613 n.args[0]->accept(*
this);
616 script = n.name + (arg1.empty() ?
"" :
"[" + arg1 +
"]");
619 void visit(SizeOpNode& n)
override {
script =
"SIZE(" + n.name +
")"; }
621 void visit(VarEvaluationNode& n)
override {
622 n.args[0]->accept(*
this);
624 n.args[1]->accept(*
this);
628 n.args[2]->accept(*
this);
631 script = arg1 +
"(" + arg2 + (arg3.empty() ?
")" :
", " + arg3 +
")");
634 void visit(AssignmentNode& n)
override {
635 n.args[0]->accept(*
this);
637 n.args[1]->accept(*
this);
639 script = std::string(indent,
' ') + arg1 +
" = " + arg2;
642 void visit(RequireNode& n)
override {
643 n.args[0]->accept(*
this);
645 script = std::string(indent,
' ') +
"REQUIRE " + arg1;
648 void visit(DeclarationNumberNode& n)
override {
649 std::string tmp =
"NUMBER ";
650 for (Size i = 0; i < n.args.size(); ++i) {
651 n.args[i]->accept(*
this);
652 tmp +=
script + (i < n.args.size() - 1 ?
", " :
"");
654 script = std::string(indent,
' ') + tmp;
657 void visit(SequenceNode& n)
override {
659 for (Size i = 0; i < n.args.size(); ++i) {
660 n.args[i]->accept(*
this);
666 void visit(ConditionEqNode& n)
override {
667 n.args[0]->accept(*
this);
669 n.args[1]->accept(*
this);
671 script = arg1 +
" == " + arg2;
674 void visit(ConditionNeqNode& n)
override {
675 n.args[0]->accept(*
this);
677 n.args[1]->accept(*
this);
679 script = arg1 +
" != " + arg2;
682 void visit(ConditionLtNode& n)
override {
683 n.args[0]->accept(*
this);
685 n.args[1]->accept(*
this);
687 script = arg1 +
" < " + arg2;
690 void visit(ConditionLeqNode& n)
override {
691 n.args[0]->accept(*
this);
693 n.args[1]->accept(*
this);
695 script = arg1 +
" <= " + arg2;
698 void visit(ConditionGtNode& n)
override {
699 n.args[0]->accept(*
this);
701 n.args[1]->accept(*
this);
703 script = arg1 +
" > " + arg2;
706 void visit(ConditionGeqNode& n)
override {
707 n.args[0]->accept(*
this);
709 n.args[1]->accept(*
this);
711 script = arg1 +
" >= " + arg2;
714 void visit(ConditionNotNode& n)
override {
715 n.args[0]->accept(*
this);
717 script =
"NOT(" + arg1 +
")";
720 void visit(ConditionAndNode& n)
override {
721 n.args[0]->accept(*
this);
723 n.args[1]->accept(*
this);
725 script =
"{" + arg1 +
" AND " + arg2 +
"}";
728 void visit(ConditionOrNode& n)
override {
729 n.args[0]->accept(*
this);
731 n.args[1]->accept(*
this);
733 script =
"{" + arg1 +
" OR " + arg2 +
"}";
736 void visit(IfThenElseNode& n)
override {
737 n.args[0]->accept(*
this);
740 n.args[1]->accept(*
this);
744 n.args[2]->accept(*
this);
748 script = std::string(indent,
' ') +
"IF " + arg1 +
" THEN\n" + arg2 + std::string(indent,
' ') +
749 (arg3.empty() ?
"END" :
"ELSE\n" + arg3 + std::string(indent,
' ') +
"END");
752 void visit(LoopNode& n)
override {
753 n.args[0]->accept(*
this);
755 n.args[1]->accept(*
this);
758 n.args[2]->accept(*
this);
760 n.args[3]->accept(*
this);
763 script = std::string(indent,
' ') +
"FOR " + n.name +
" IN (" + arg1 +
", " + arg2 +
", " + arg3 +
") DO\n" +
764 arg4 + std::string(indent,
' ') +
"END";
769 static constexpr Size tabsize = 2;
774 ASTToScriptConverter p;
std::string to_script(const ASTNodePtr root)
QuantLib::ext::shared_ptr< ASTNode > ASTNodePtr
Serializable Credit Default Swap.
string conversion utilities