ATLAS Offline Software
Loading...
Searching...
No Matches
ParsingInternals.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration
3*/
4
6// ParsingInternals.cxx, (c) ATLAS Detector software
8// Author: Thomas Gillam (thomas.gillam@cern.ch)
9// ExpressionParsing library
11
12#include "ParsingInternals.h"
13
14#define VM_CASE_UNARY(OP) case op_ ## OP: \
15 stack.back() = stack.back()._ ## OP(); \
16 break
17
18
19
20#define VISITOR_UNARY(OP) else if (x.operator_ == #OP) code.push_back(op_ ## OP)
21
22std::atomic<std::size_t> g_maxStackSize=0;
23
24namespace ExpressionParsing {
25 template <class T_func>
26 void bin_op( std::vector<StackElement> &stack, T_func a_func) {
27 assert( stack.size() >= 2);
28 std::vector<ExpressionParsing::StackElement>::iterator last_elm = stack.end()-1;
29 std::vector<ExpressionParsing::StackElement>::iterator second_last_elm = stack.end()-2;
30 a_func(*second_last_elm, *last_elm);
31 stack.pop_back();
32 }
33
34 StackElement VirtualMachine::execute(std::vector<StackElement> const& code) const
35 {
36 std::vector<StackElement> stack;
37 stack.reserve(m_stackSize);
38 std::size_t max_stack_size=g_maxStackSize;
39
40 std::vector<StackElement>::const_iterator pc = code.begin();
41
42 while (pc != code.end())
43 {
44 if (stack.size() > max_stack_size) max_stack_size = stack.size();
45 ++pc;
46 switch (pc[-1].asInt())
47 {
48 case op_neg: {
49 stack.back() = -std::move(stack.back());
50 break;
51 }
52 case op_not:
53 stack.back() = !std::move(stack.back());
54 break;
55
56 VM_CASE_UNARY(sum);
58 VM_CASE_UNARY(abs);
59 VM_CASE_UNARY(sqrt);
60 VM_CASE_UNARY(cbrt);
61 VM_CASE_UNARY(sin);
62 VM_CASE_UNARY(cos);
63 VM_CASE_UNARY(tan);
64 VM_CASE_UNARY(asin);
65 VM_CASE_UNARY(acos);
66 VM_CASE_UNARY(atan);
67 VM_CASE_UNARY(sinh);
68 VM_CASE_UNARY(cosh);
69 VM_CASE_UNARY(tanh);
70 VM_CASE_UNARY(asinh);
71 VM_CASE_UNARY(acosh);
72 VM_CASE_UNARY(atanh);
73 VM_CASE_UNARY(log);
74 VM_CASE_UNARY(exp);
75
76 case op_and: bin_op(stack,[](StackElement &a, StackElement &b) { a=a._and(b); }); break;
77 case op_or: bin_op(stack,[](StackElement &a, StackElement &b) { a=a._or(b); }); break;
78 case op_eq: bin_op(stack,[](StackElement &a, StackElement &b) { a=a._eq(b); }); break;
79 case op_neq: bin_op(stack,[](StackElement &a, StackElement &b) { a=a._neq(b); }); break;
80 case op_gt: bin_op(stack,[](StackElement &a, StackElement &b) { a=a._gt(b); }); break;
81 case op_gte: bin_op(stack,[](StackElement &a, StackElement &b) { a=a._gte(b); }); break;
82 case op_lt: bin_op(stack,[](StackElement &a, StackElement &b) { a=a._lt(b); }); break;
83 case op_lte: bin_op(stack,[](StackElement &a, StackElement &b) { a=a._lte(b); }); break;
84
85 case op_add: bin_op(stack,[](StackElement &a, StackElement &b) { a += b; }); break;
86 case op_sub: bin_op(stack,[](StackElement &a, StackElement &b) { a -= b; }); break;
87
88 case op_pow: bin_op(stack,[](StackElement &a, StackElement &b) { a = a._pow(b); }); break;
89
90 case op_mul: bin_op(stack,[](StackElement &a, StackElement &b) { a *= b; }); break;
91 case op_div: bin_op(stack,[](StackElement &a, StackElement &b) { a /= b; }); break;
92
93 case op_val:
94 if (pc->isProxy()) {
95 stack.emplace_back(pc->valueFromProxy());
96 }
97 else {
98 stack.emplace_back(*pc);
99 }
100 ++pc;
101 break;
102 }
103 }
104
105 if (stack.size()!=1){
106 throw std::runtime_error("ExpressionEvaluation: Virtual machine finished in undefined state. Is expression valid?");
107 }
108 if (max_stack_size>g_maxStackSize) {
109 g_maxStackSize=max_stack_size;
110 }
111 return stack.back();
112 }
113
114
115
116 void Compiler::operator()(unsigned int n)
117 {
118 code.push_back(op_val);
119 code.push_back(n);
120 }
121 void Compiler::operator()(bool n)
122 {
123 code.push_back(op_val);
124 code.push_back((int)n);
125 }
126 void Compiler::operator()(double n)
127 {
128 code.push_back(op_val);
129 code.push_back(n);
130 }
131 void Compiler::operator()(const std::string &n)
132 {
133 const IUnitInterpreter *units = m_unitInterpreter;
134
135 code.push_back(op_val);
136 // Intercept special values
137 if (n == "pi") code.push_back(3.14159265359);
138 else if (n == "e") code.push_back(2.71828182846);
139 else if (n == "kBigNumber") code.push_back(1234567890);
140 else if (n == "kLeinGrossNummer") code.push_back(123456789);
141 else if (units->isKnownUnit(n)) code.push_back(units->unitValue(n));
142 else code.push_back(StackElement(n, m_proxyLoader));
143 }
144
145 void Compiler::operator()(ast::operation const& x)
146 {
147 boost::apply_visitor(*this, x.operand_);
148 if (x.operator_ == "&&") code.push_back(op_and);
149 else if (x.operator_ == "||") code.push_back(op_or);
150 else if (x.operator_ == "==") code.push_back(op_eq);
151 else if (x.operator_ == "!=") code.push_back(op_neq);
152 else if (x.operator_ == ">") code.push_back(op_gt);
153 else if (x.operator_ == ">=") code.push_back(op_gte);
154 else if (x.operator_ == "<") code.push_back(op_lt);
155 else if (x.operator_ == "<=") code.push_back(op_lte);
156 else if (x.operator_ == "+") code.push_back(op_add);
157 else if (x.operator_ == "-") code.push_back(op_sub);
158 else if (x.operator_ == "**") code.push_back(op_pow);
159 else if (x.operator_ == "*") code.push_back(op_mul);
160 else if (x.operator_ == "/") code.push_back(op_div);
161 else BOOST_ASSERT(0);
162 }
163
164 void Compiler::operator()(ast::unaryexpr_ const& x)
165 {
166 boost::apply_visitor(*this, x.operand_);
167 if (x.operator_ == "-") code.push_back(op_neg);
168 else if (x.operator_ == "!") code.push_back(op_not);
169 VISITOR_UNARY(sum);
171 VISITOR_UNARY(abs);
172 VISITOR_UNARY(sqrt);
173 VISITOR_UNARY(cbrt);
174 VISITOR_UNARY(sin);
175 VISITOR_UNARY(cos);
176 VISITOR_UNARY(tan);
177 VISITOR_UNARY(asin);
178 VISITOR_UNARY(acos);
179 VISITOR_UNARY(atan);
180 VISITOR_UNARY(sinh);
181 VISITOR_UNARY(cosh);
182 VISITOR_UNARY(tanh);
183 VISITOR_UNARY(asinh);
184 VISITOR_UNARY(acosh);
185 VISITOR_UNARY(atanh);
186 VISITOR_UNARY(log);
187 VISITOR_UNARY(exp);
188 else if (x.operator_ == "+") ;
189 else BOOST_ASSERT(0);
190 }
191
192 void Compiler::operator()(ast::expression const& x)
193 {
194 boost::apply_visitor(*this, x.first);
195 for(ast::operation const& oper : x.rest)
196 {
197 (*this)(oper);
198 }
199 }
200
201}
#define VM_CASE_UNARY(OP)
#define VISITOR_UNARY(OP)
std::atomic< std::size_t > g_maxStackSize
#define x
Class describing a single element in a text expression.
int count(std::string s, const std::string &regx)
count how many occurances of a regx are in a string
Definition hcg.cxx:146
TList * a
Namespace holding all the expression evaluation code.
void bin_op(std::vector< StackElement > &stack, T_func a_func)
void * StackElement
One element of a stack trace.
Definition stackstash.h:74