ATLAS Offline Software
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 
22 std::atomic<std::size_t> g_maxStackSize=0;
23 
24 namespace ExpressionParsing {
25  template <class T_func>
26  void bin_op( std::vector<StackElement> &stack, T_func a_func) {
27  assert( stack.size() >= 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 
58  VM_CASE_UNARY(abs);
59  VM_CASE_UNARY(sqrt);
60  VM_CASE_UNARY(cbrt);
64  VM_CASE_UNARY(asin);
65  VM_CASE_UNARY(acos);
67  VM_CASE_UNARY(sinh);
68  VM_CASE_UNARY(cosh);
69  VM_CASE_UNARY(tanh);
71  VM_CASE_UNARY(acosh);
72  VM_CASE_UNARY(atanh);
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);
171  VISITOR_UNARY(abs);
172  VISITOR_UNARY(sqrt);
173  VISITOR_UNARY(cbrt);
177  VISITOR_UNARY(asin);
178  VISITOR_UNARY(acos);
180  VISITOR_UNARY(sinh);
181  VISITOR_UNARY(cosh);
182  VISITOR_UNARY(tanh);
184  VISITOR_UNARY(acosh);
185  VISITOR_UNARY(atanh);
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 }
xAOD::iterator
JetConstituentVector::iterator iterator
Definition: JetConstituentVector.cxx:68
04Plot.stack
list stack
Definition: 04Plot.py:10
StackElement
void * StackElement
One element of a stack trace.
Definition: stackstash.h:74
drawFromPickle.cos
cos
Definition: drawFromPickle.py:36
g_maxStackSize
std::atomic< std::size_t > g_maxStackSize
Definition: ParsingInternals.cxx:22
drawFromPickle.exp
exp
Definition: drawFromPickle.py:36
x
#define x
XMLtoHeader.count
count
Definition: XMLtoHeader.py:85
VM_CASE_UNARY
#define VM_CASE_UNARY(OP)
Definition: ParsingInternals.cxx:14
drawFromPickle.atan
atan
Definition: drawFromPickle.py:36
LArG4FSStartPointFilterLegacy.execute
execute
Definition: LArG4FSStartPointFilterLegacy.py:20
HION12.expression
string expression
Definition: HION12.py:56
convertTimingResiduals.sum
sum
Definition: convertTimingResiduals.py:55
beamspotman.n
n
Definition: beamspotman.py:731
ExpressionParsing
Namespace holding all the expression evaluation code.
Definition: ExpressionParser.h:26
VISITOR_UNARY
#define VISITOR_UNARY(OP)
Definition: ParsingInternals.cxx:20
python.Dumpers.asinh
def asinh(x)
helper methods ---------------------------------------------------------—
Definition: Dumpers.py:89
drawFromPickle.tan
tan
Definition: drawFromPickle.py:36
pmontree.code
code
Definition: pmontree.py:443
plotBeamSpotMon.b
b
Definition: plotBeamSpotMon.py:77
perfmonmt-refit.units
string units
Definition: perfmonmt-refit.py:77
ExpressionParsing::bin_op
void bin_op(std::vector< StackElement > &stack, T_func a_func)
Definition: ParsingInternals.cxx:26
a
TList * a
Definition: liststreamerinfos.cxx:10
python.CaloCondTools.log
log
Definition: CaloCondTools.py:20
drawFromPickle.sin
sin
Definition: drawFromPickle.py:36
ParsingInternals.h
python.SystemOfUnits.pc
float pc
Definition: SystemOfUnits.py:99