From 004d90962179102728c584039d726b2dc543e8bb Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?S=C3=A9bastien=20Villemot?= <sebastien@dynare.org>
Date: Wed, 5 Sep 2018 16:41:33 +0200
Subject: [PATCH] Use smart pointers for storage of ExprNode in DataTree class

- BTW, store them in a std::vector rather than std::list

- incidentally, fix issue in VariableNode::removeTrendLeadLag where expression
  sharing was possibly violated when creating a new VariableNode
---
 src/DataTree.cc | 55 +++++++++++++++++++++++++-----------
 src/DataTree.hh | 28 ++++++++++++------
 src/ExprNode.cc | 75 ++++++++++++++++---------------------------------
 src/ExprNode.hh | 28 +++++++++---------
 4 files changed, 96 insertions(+), 90 deletions(-)

diff --git a/src/DataTree.cc b/src/DataTree.cc
index a349c383..736e49e8 100644
--- a/src/DataTree.cc
+++ b/src/DataTree.cc
@@ -35,8 +35,7 @@ DataTree::DataTree(SymbolTable &symbol_table_arg,
   num_constants(num_constants_arg),
   external_functions_table(external_functions_table_arg),
   trend_component_model_table(trend_component_model_table_arg),
-  var_model_table(var_model_table_arg),
-  node_counter(0)
+  var_model_table(var_model_table_arg)
 {
   Zero = AddNonNegativeConstant("0");
   One = AddNonNegativeConstant("1");
@@ -51,11 +50,7 @@ DataTree::DataTree(SymbolTable &symbol_table_arg,
   Pi = AddNonNegativeConstant("3.141592653589793");
 }
 
-DataTree::~DataTree()
-{
-  for (auto & it : node_list)
-    delete it;
-}
+DataTree::~DataTree() = default;
 
 expr_t
 DataTree::AddNonNegativeConstant(const string &value)
@@ -65,8 +60,12 @@ DataTree::AddNonNegativeConstant(const string &value)
   auto it = num_const_node_map.find(id);
   if (it != num_const_node_map.end())
     return it->second;
-  else
-    return new NumConstNode(*this, id);
+
+  auto sp = make_unique<NumConstNode>(*this, node_list.size(), id);
+  auto p = sp.get();
+  node_list.push_back(move(sp));
+  num_const_node_map[id] = p;
+  return p;
 }
 
 VariableNode *
@@ -75,8 +74,12 @@ DataTree::AddVariableInternal(int symb_id, int lag)
   auto it = variable_node_map.find({ symb_id, lag });
   if (it != variable_node_map.end())
     return it->second;
-  else
-    return new VariableNode(*this, symb_id, lag);
+
+  auto sp = make_unique<VariableNode>(*this, node_list.size(), symb_id, lag);
+  auto p = sp.get();
+  node_list.push_back(move(sp));
+  variable_node_map[{ symb_id, lag }] = p;
+  return p;
 }
 
 bool
@@ -515,7 +518,11 @@ DataTree::AddVarExpectation(const string &model_name)
   if (it != var_expectation_node_map.end())
     return it->second;
 
-  return new VarExpectationNode(*this, model_name);
+  auto sp = make_unique<VarExpectationNode>(*this, node_list.size(), model_name);
+  auto p = sp.get();
+  node_list.push_back(move(sp));
+  var_expectation_node_map[model_name] = p;
+  return p;
 }
 
 expr_t
@@ -525,7 +532,11 @@ DataTree::AddPacExpectation(const string &model_name)
   if (it != pac_expectation_node_map.end())
     return it->second;
 
-  return new PacExpectationNode(*this, model_name);
+  auto sp = make_unique<PacExpectationNode>(*this, node_list.size(), model_name);
+  auto p = sp.get();
+  node_list.push_back(move(sp));
+  pac_expectation_node_map[model_name] = p;
+  return p;
 }
 
 expr_t
@@ -557,7 +568,11 @@ DataTree::AddExternalFunction(int symb_id, const vector<expr_t> &arguments)
   if (it != external_function_node_map.end())
     return it->second;
 
-  return new ExternalFunctionNode(*this, symb_id, arguments);
+  auto sp = make_unique<ExternalFunctionNode>(*this, node_list.size(), symb_id, arguments);
+  auto p = sp.get();
+  node_list.push_back(move(sp));
+  external_function_node_map[{ arguments, symb_id }] = p;
+  return p;
 }
 
 expr_t
@@ -570,7 +585,11 @@ DataTree::AddFirstDerivExternalFunction(int top_level_symb_id, const vector<expr
   if (it != first_deriv_external_function_node_map.end())
     return it->second;
 
-  return new FirstDerivExternalFunctionNode(*this, top_level_symb_id, arguments, input_index);
+  auto sp = make_unique<FirstDerivExternalFunctionNode>(*this, node_list.size(), top_level_symb_id, arguments, input_index);
+  auto p = sp.get();
+  node_list.push_back(move(sp));
+  first_deriv_external_function_node_map[{ arguments, input_index, top_level_symb_id }] = p;
+  return p;
 }
 
 expr_t
@@ -584,7 +603,11 @@ DataTree::AddSecondDerivExternalFunction(int top_level_symb_id, const vector<exp
   if (it != second_deriv_external_function_node_map.end())
     return it->second;
 
-  return new SecondDerivExternalFunctionNode(*this, top_level_symb_id, arguments, input_index1, input_index2);
+  auto sp = make_unique<SecondDerivExternalFunctionNode>(*this, node_list.size(), top_level_symb_id, arguments, input_index1, input_index2);
+  auto p = sp.get();
+  node_list.push_back(move(sp));
+  second_deriv_external_function_node_map[{ arguments, input_index1, input_index2, top_level_symb_id }] = p;
+  return p;
 }
 
 bool
diff --git a/src/DataTree.hh b/src/DataTree.hh
index 55a7c810..d84ca9df 100644
--- a/src/DataTree.hh
+++ b/src/DataTree.hh
@@ -24,7 +24,7 @@ using namespace std;
 
 #include <string>
 #include <map>
-#include <list>
+#include <vector>
 #include <sstream>
 #include <iomanip>
 #include <cmath>
@@ -123,11 +123,8 @@ protected:
 private:
   const static int constants_precision{16};
 
-  using node_list_t = list<expr_t>;
   //! The list of nodes
-  node_list_t node_list;
-  //! A counter for filling ExprNode's idx field
-  int node_counter;
+  vector<unique_ptr<ExprNode>> node_list;
 
   inline expr_t AddPossiblyNegativeConstant(double val);
   inline expr_t AddUnaryOp(UnaryOpcode op_code, expr_t arg, int arg_exp_info_set = 0, int param1_symb_id = 0, int param2_symb_id = 0, const string &adl_param_name = "", const vector<int> &adl_lags = vector<int>());
@@ -371,7 +368,12 @@ DataTree::AddUnaryOp(UnaryOpcode op_code, expr_t arg, int arg_exp_info_set, int
         {
         }
     }
-  return new UnaryOpNode(*this, op_code, arg, arg_exp_info_set, param1_symb_id, param2_symb_id, adl_param_name, adl_lags);
+
+  auto sp = make_unique<UnaryOpNode>(*this, node_list.size(), op_code, arg, arg_exp_info_set, param1_symb_id, param2_symb_id, adl_param_name, adl_lags);
+  auto p = sp.get();
+  node_list.push_back(move(sp));
+  unary_op_node_map[{ arg, op_code, arg_exp_info_set, param1_symb_id, param2_symb_id, adl_param_name, adl_lags }] = p;
+  return p;
 }
 
 inline expr_t
@@ -392,7 +394,12 @@ DataTree::AddBinaryOp(expr_t arg1, BinaryOpcode op_code, expr_t arg2, int powerD
   catch (ExprNode::EvalException &e)
     {
     }
-  return new BinaryOpNode(*this, arg1, op_code, arg2, powerDerivOrder);
+
+  auto sp = make_unique<BinaryOpNode>(*this, node_list.size(), arg1, op_code, arg2, powerDerivOrder);
+  auto p = sp.get();
+  node_list.push_back(move(sp));
+  binary_op_node_map[{ arg1, arg2, op_code, powerDerivOrder }] = p;
+  return p;
 }
 
 inline expr_t
@@ -414,7 +421,12 @@ DataTree::AddTrinaryOp(expr_t arg1, TrinaryOpcode op_code, expr_t arg2, expr_t a
   catch (ExprNode::EvalException &e)
     {
     }
-  return new TrinaryOpNode(*this, arg1, op_code, arg2, arg3);
+
+  auto sp = make_unique<TrinaryOpNode>(*this, node_list.size(), arg1, op_code, arg2, arg3);
+  auto p = sp.get();
+  node_list.push_back(move(sp));
+  trinary_op_node_map[{ arg1, arg2, arg3, op_code }] = p;
+  return p;
 }
 
 #endif
diff --git a/src/ExprNode.cc b/src/ExprNode.cc
index 80ca2741..42611a1f 100644
--- a/src/ExprNode.cc
+++ b/src/ExprNode.cc
@@ -30,13 +30,8 @@
 #include "DataTree.hh"
 #include "ModFile.hh"
 
-ExprNode::ExprNode(DataTree &datatree_arg) : datatree(datatree_arg), preparedForDerivation(false)
+ExprNode::ExprNode(DataTree &datatree_arg, int idx_arg) : datatree{datatree_arg}, idx{idx_arg}, preparedForDerivation{false}
 {
-  // Add myself to datatree
-  datatree.node_list.push_back(this);
-
-  // Set my index and increment counter
-  idx = datatree.node_counter++;
 }
 
 ExprNode::~ExprNode()
@@ -321,12 +316,10 @@ ExprNode::getEndosAndMaxLags(map<string, int> &model_endos_and_lags) const
 {
 }
 
-NumConstNode::NumConstNode(DataTree &datatree_arg, int id_arg) :
-  ExprNode(datatree_arg),
+NumConstNode::NumConstNode(DataTree &datatree_arg, int idx_arg, int id_arg) :
+  ExprNode(datatree_arg, idx_arg),
   id(id_arg)
 {
-  // Add myself to the num const map
-  datatree.num_const_node_map[id] = this;
 }
 
 int
@@ -702,15 +695,12 @@ NumConstNode::substituteStaticAuxiliaryVariable() const
   return const_cast<NumConstNode *>(this);
 }
 
-VariableNode::VariableNode(DataTree &datatree_arg, int symb_id_arg, int lag_arg) :
-  ExprNode(datatree_arg),
+VariableNode::VariableNode(DataTree &datatree_arg, int idx_arg, int symb_id_arg, int lag_arg) :
+  ExprNode(datatree_arg, idx_arg),
   symb_id(symb_id_arg),
   type(datatree.symbol_table.getType(symb_id_arg)),
   lag(lag_arg)
 {
-  // Add myself to the variable map
-  datatree.variable_node_map[{ symb_id, lag }] = this;
-
   // It makes sense to allow a lead/lag on parameters: during steady state calibration, endogenous and parameters can be swapped
   assert(type != SymbolType::externalFunction
          && (lag == 0 || (type != SymbolType::modelLocalVariable && type != SymbolType::modFileLocalVariable)));
@@ -1831,7 +1821,7 @@ VariableNode::removeTrendLeadLag(map<int, expr_t> trend_symbols_map) const
     return const_cast<VariableNode *>(this);
 
   map<int, expr_t>::const_iterator it = trend_symbols_map.find(symb_id);
-  expr_t noTrendLeadLagNode = new VariableNode(datatree, it->first, 0);
+  expr_t noTrendLeadLagNode = datatree.AddVariable(it->first);
   bool log_trend = get_type() == SymbolType::logTrend;
   expr_t trend = it->second;
 
@@ -1938,8 +1928,8 @@ VariableNode::getEndosAndMaxLags(map<string, int> &model_endos_and_lags) const
       model_endos_and_lags[varname] = lag;
 }
 
-UnaryOpNode::UnaryOpNode(DataTree &datatree_arg, UnaryOpcode op_code_arg, const expr_t arg_arg, int expectation_information_set_arg, int param1_symb_id_arg, int param2_symb_id_arg, string adl_param_name_arg, vector<int> adl_lags_arg) :
-  ExprNode(datatree_arg),
+UnaryOpNode::UnaryOpNode(DataTree &datatree_arg, int idx_arg, UnaryOpcode op_code_arg, const expr_t arg_arg, int expectation_information_set_arg, int param1_symb_id_arg, int param2_symb_id_arg, string adl_param_name_arg, vector<int> adl_lags_arg) :
+  ExprNode(datatree_arg, idx_arg),
   arg(arg_arg),
   expectation_information_set(expectation_information_set_arg),
   param1_symb_id(param1_symb_id_arg),
@@ -1948,8 +1938,6 @@ UnaryOpNode::UnaryOpNode(DataTree &datatree_arg, UnaryOpcode op_code_arg, const
   adl_param_name(move(adl_param_name_arg)),
   adl_lags(move(adl_lags_arg))
 {
-  // Add myself to the unary op map
-  datatree.unary_op_node_map[{ arg, op_code, expectation_information_set, param1_symb_id, param2_symb_id, adl_param_name, adl_lags }] = this;
 }
 
 void
@@ -3573,27 +3561,15 @@ UnaryOpNode::substituteStaticAuxiliaryVariable() const
     return buildSimilarUnaryOpNode(argsubst, datatree);
 }
 
-BinaryOpNode::BinaryOpNode(DataTree &datatree_arg, const expr_t arg1_arg,
-                           BinaryOpcode op_code_arg, const expr_t arg2_arg) :
-  ExprNode(datatree_arg),
-  arg1(arg1_arg),
-  arg2(arg2_arg),
-  op_code(op_code_arg),
-  powerDerivOrder(0)
-{
-  datatree.binary_op_node_map[{ arg1, arg2, op_code, powerDerivOrder }] = this;
-}
-
-BinaryOpNode::BinaryOpNode(DataTree &datatree_arg, const expr_t arg1_arg,
+BinaryOpNode::BinaryOpNode(DataTree &datatree_arg, int idx_arg, const expr_t arg1_arg,
                            BinaryOpcode op_code_arg, const expr_t arg2_arg, int powerDerivOrder_arg) :
-  ExprNode(datatree_arg),
+  ExprNode(datatree_arg, idx_arg),
   arg1(arg1_arg),
   arg2(arg2_arg),
   op_code(op_code_arg),
   powerDerivOrder(powerDerivOrder_arg)
 {
   assert(powerDerivOrder >= 0);
-  datatree.binary_op_node_map[{ arg1, arg2, op_code, powerDerivOrder }] = this;
 }
 
 void
@@ -5494,15 +5470,14 @@ BinaryOpNode::substituteStaticAuxiliaryDefinition() const
   return buildSimilarBinaryOpNode(arg1, arg2subst, datatree);
 }
 
-TrinaryOpNode::TrinaryOpNode(DataTree &datatree_arg, const expr_t arg1_arg,
+TrinaryOpNode::TrinaryOpNode(DataTree &datatree_arg, int idx_arg, const expr_t arg1_arg,
                              TrinaryOpcode op_code_arg, const expr_t arg2_arg, const expr_t arg3_arg) :
-  ExprNode(datatree_arg),
+  ExprNode(datatree_arg, idx_arg),
   arg1(arg1_arg),
   arg2(arg2_arg),
   arg3(arg3_arg),
   op_code(op_code_arg)
 {
-  datatree.trinary_op_node_map[{ arg1, arg2, arg3, op_code }] = this;
 }
 
 void
@@ -6395,9 +6370,10 @@ TrinaryOpNode::substituteStaticAuxiliaryVariable() const
 }
 
 AbstractExternalFunctionNode::AbstractExternalFunctionNode(DataTree &datatree_arg,
+                                                           int idx_arg,
                                                            int symb_id_arg,
                                                            vector<expr_t> arguments_arg) :
-  ExprNode(datatree_arg),
+  ExprNode(datatree_arg, idx_arg),
   symb_id(symb_id_arg),
   arguments(move(arguments_arg))
 {
@@ -7000,12 +6976,11 @@ AbstractExternalFunctionNode::substituteStaticAuxiliaryVariable() const
 }
 
 ExternalFunctionNode::ExternalFunctionNode(DataTree &datatree_arg,
+                                           int idx_arg,
                                            int symb_id_arg,
                                            const vector<expr_t> &arguments_arg) :
-  AbstractExternalFunctionNode(datatree_arg, symb_id_arg, arguments_arg)
+  AbstractExternalFunctionNode(datatree_arg, idx_arg, symb_id_arg, arguments_arg)
 {
-  // Add myself to the external function map
-  datatree.external_function_node_map[{ arguments, symb_id }] = this;
 }
 
 expr_t
@@ -7321,14 +7296,13 @@ ExternalFunctionNode::sameTefTermPredicate() const
 }
 
 FirstDerivExternalFunctionNode::FirstDerivExternalFunctionNode(DataTree &datatree_arg,
+                                                               int idx_arg,
                                                                int top_level_symb_id_arg,
                                                                const vector<expr_t> &arguments_arg,
                                                                int inputIndex_arg) :
-  AbstractExternalFunctionNode(datatree_arg, top_level_symb_id_arg, arguments_arg),
+  AbstractExternalFunctionNode(datatree_arg, idx_arg, top_level_symb_id_arg, arguments_arg),
   inputIndex(inputIndex_arg)
 {
-  // Add myself to the first derivative external function map
-  datatree.first_deriv_external_function_node_map[{ arguments, inputIndex, symb_id }] = this;
 }
 
 void
@@ -7705,16 +7679,15 @@ FirstDerivExternalFunctionNode::sameTefTermPredicate() const
 }
 
 SecondDerivExternalFunctionNode::SecondDerivExternalFunctionNode(DataTree &datatree_arg,
+                                                                 int idx_arg,
                                                                  int top_level_symb_id_arg,
                                                                  const vector<expr_t> &arguments_arg,
                                                                  int inputIndex1_arg,
                                                                  int inputIndex2_arg) :
-  AbstractExternalFunctionNode(datatree_arg, top_level_symb_id_arg, arguments_arg),
+  AbstractExternalFunctionNode(datatree_arg, idx_arg, top_level_symb_id_arg, arguments_arg),
   inputIndex1(inputIndex1_arg),
   inputIndex2(inputIndex2_arg)
 {
-  // Add myself to the second derivative external function map
-  datatree.second_deriv_external_function_node_map[{ arguments, inputIndex1, inputIndex2, symb_id }] = this;
 }
 
 void
@@ -8040,11 +8013,11 @@ SecondDerivExternalFunctionNode::sameTefTermPredicate() const
 }
 
 VarExpectationNode::VarExpectationNode(DataTree &datatree_arg,
+                                       int idx_arg,
                                        string model_name_arg) :
-  ExprNode(datatree_arg),
+  ExprNode(datatree_arg, idx_arg),
   model_name{move(model_name_arg)}
 {
-  datatree.var_expectation_node_map[model_name] = this;
 }
 
 void
@@ -8485,11 +8458,11 @@ VarExpectationNode::writeJsonOutput(ostream &output,
 }
 
 PacExpectationNode::PacExpectationNode(DataTree &datatree_arg,
+                                       int idx_arg,
                                        string model_name_arg) :
-  ExprNode(datatree_arg),
+  ExprNode(datatree_arg, idx_arg),
   model_name(move(model_name_arg))
 {
-  datatree.pac_expectation_node_map[model_name] = this;
 }
 
 void
diff --git a/src/ExprNode.hh b/src/ExprNode.hh
index a519d88a..62370cb4 100644
--- a/src/ExprNode.hh
+++ b/src/ExprNode.hh
@@ -153,7 +153,7 @@ class ExprNode
       DataTree &datatree;
 
       //! Index number
-      int idx;
+      const int idx;
 
       //! Is the data member non_null_derivatives initialized ?
       bool preparedForDerivation;
@@ -190,7 +190,7 @@ class ExprNode
                                          const temporary_terms_t &temporary_terms,
                                          const temporary_terms_idxs_t &temporary_terms_idxs) const;
     public:
-      ExprNode(DataTree &datatree_arg);
+      ExprNode(DataTree &datatree_arg, int idx_arg);
       virtual
       ~ExprNode();
 
@@ -581,7 +581,7 @@ private:
   const int id;
   expr_t computeDerivative(int deriv_id) override;
 public:
-  NumConstNode(DataTree &datatree_arg, int id_arg);
+  NumConstNode(DataTree &datatree_arg, int idx_arg, int id_arg);
   int
   get_id() const
   {
@@ -664,7 +664,7 @@ private:
   const int lag;
   expr_t computeDerivative(int deriv_id) override;
 public:
-  VariableNode(DataTree &datatree_arg, int symb_id_arg, int lag_arg);
+  VariableNode(DataTree &datatree_arg, int idx_arg, int symb_id_arg, int lag_arg);
   void prepareForDerivation() override;
   void writeOutput(ostream &output, ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms, const temporary_terms_idxs_t &temporary_terms_idxs, const deriv_node_temp_terms_t &tef_terms) const override;
   void writeJsonOutput(ostream &output, const temporary_terms_t &temporary_terms, const deriv_node_temp_terms_t &tef_terms, const bool isdynamic) const override;
@@ -771,7 +771,7 @@ private:
   //! Returns the derivative of this node if darg is the derivative of the argument
   expr_t composeDerivatives(expr_t darg, int deriv_id);
 public:
-  UnaryOpNode(DataTree &datatree_arg, UnaryOpcode op_code_arg, const expr_t arg_arg, int expectation_information_set_arg, int param1_symb_id_arg, int param2_symb_id_arg, string adl_param_name_arg, vector<int> adl_lags_arg);
+  UnaryOpNode(DataTree &datatree_arg, int idx_arg, UnaryOpcode op_code_arg, const expr_t arg_arg, int expectation_information_set_arg, int param1_symb_id_arg, int param2_symb_id_arg, string adl_param_name_arg, vector<int> adl_lags_arg);
   void prepareForDerivation() override;
   void computeTemporaryTerms(map<expr_t, pair<int, NodeTreeReference>> &reference_count,
                                      map<NodeTreeReference, temporary_terms_t> &temp_terms_map,
@@ -890,9 +890,7 @@ private:
   const int powerDerivOrder;
   const string adlparam;
 public:
-  BinaryOpNode(DataTree &datatree_arg, const expr_t arg1_arg,
-               BinaryOpcode op_code_arg, const expr_t arg2_arg);
-  BinaryOpNode(DataTree &datatree_arg, const expr_t arg1_arg,
+  BinaryOpNode(DataTree &datatree_arg, int idx_arg, const expr_t arg1_arg,
                BinaryOpcode op_code_arg, const expr_t arg2_arg, int powerDerivOrder);
   void prepareForDerivation() override;
   int precedenceJson(const temporary_terms_t &temporary_terms) const override;
@@ -1042,7 +1040,7 @@ private:
   //! Returns the derivative of this node if darg1, darg2 and darg3 are the derivatives of the arguments
   expr_t composeDerivatives(expr_t darg1, expr_t darg2, expr_t darg3);
 public:
-  TrinaryOpNode(DataTree &datatree_arg, const expr_t arg1_arg,
+  TrinaryOpNode(DataTree &datatree_arg, int idx_arg, const expr_t arg1_arg,
                 TrinaryOpcode op_code_arg, const expr_t arg2_arg, const expr_t arg3_arg);
   void prepareForDerivation() override;
   int precedence(ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms) const override;
@@ -1160,7 +1158,7 @@ protected:
     the same so-called "Tef" index) */
   virtual function<bool (expr_t)> sameTefTermPredicate() const = 0;
 public:
-  AbstractExternalFunctionNode(DataTree &datatree_arg, int symb_id_arg,
+  AbstractExternalFunctionNode(DataTree &datatree_arg, int idx_arg, int symb_id_arg,
                                vector<expr_t> arguments_arg);
   void prepareForDerivation() override;
   void computeTemporaryTerms(map<expr_t, pair<int, NodeTreeReference>> &reference_count,
@@ -1265,7 +1263,7 @@ private:
 protected:
   function<bool (expr_t)> sameTefTermPredicate() const override;
 public:
-  ExternalFunctionNode(DataTree &datatree_arg, int symb_id_arg,
+  ExternalFunctionNode(DataTree &datatree_arg, int idx_arg, int symb_id_arg,
                        const vector<expr_t> &arguments_arg);
   void writeOutput(ostream &output, ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms, const temporary_terms_idxs_t &temporary_terms_idxs, const deriv_node_temp_terms_t &tef_terms) const override;
   void writeJsonOutput(ostream &output, const temporary_terms_t &temporary_terms, const deriv_node_temp_terms_t &tef_terms, const bool isdynamic) const override;
@@ -1302,7 +1300,7 @@ private:
 protected:
   function<bool (expr_t)> sameTefTermPredicate() const override;
 public:
-  FirstDerivExternalFunctionNode(DataTree &datatree_arg,
+  FirstDerivExternalFunctionNode(DataTree &datatree_arg, int idx_arg,
                                  int top_level_symb_id_arg,
                                  const vector<expr_t> &arguments_arg,
                                  int inputIndex_arg);
@@ -1345,7 +1343,7 @@ private:
 protected:
   function<bool (expr_t)> sameTefTermPredicate() const override;
 public:
-  SecondDerivExternalFunctionNode(DataTree &datatree_arg,
+  SecondDerivExternalFunctionNode(DataTree &datatree_arg, int idx_arg,
                                   int top_level_symb_id_arg,
                                   const vector<expr_t> &arguments_arg,
                                   int inputIndex1_arg,
@@ -1385,7 +1383,7 @@ class VarExpectationNode : public ExprNode
 private:
   const string model_name;
 public:
-  VarExpectationNode(DataTree &datatree_arg, string model_name_arg);
+  VarExpectationNode(DataTree &datatree_arg, int idx_arg, string model_name_arg);
   void computeTemporaryTerms(map<expr_t, pair<int, NodeTreeReference>> &reference_count,
                                      map<NodeTreeReference, temporary_terms_t> &temp_terms_map,
                                      bool is_matlab, NodeTreeReference tr) const override;
@@ -1481,7 +1479,7 @@ private:
   set<pair<int, pair<int, int>>> ar_params_and_vars;
   set<pair<int, pair<pair<int, int>, double>>> params_vars_and_scaling_factor;
 public:
-  PacExpectationNode(DataTree &datatree_arg, string model_name);
+  PacExpectationNode(DataTree &datatree_arg, int idx_arg, string model_name);
   void computeTemporaryTerms(map<expr_t, pair<int, NodeTreeReference>> &reference_count,
                                      map<NodeTreeReference, temporary_terms_t> &temp_terms_map,
                                      bool is_matlab, NodeTreeReference tr) const override;
-- 
GitLab