From b4c3d004ad6c8c19aa56a477677d1c6c89f8f23e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?S=C3=A9bastien=20Villemot?= <sebastien@dynare.org>
Date: Thu, 13 Mar 2014 11:22:00 +0100
Subject: [PATCH] Introduce a new abstract class for external function nodes.

This fixes the following bugs:

- 1st and 2nd ext fcn deriv nodes were incorrectly added to
  DataTree::external_function_node_map, because of the chaining of
  constructors.

- the following methods of FirstDerivExternalFunctionNode were not overloaded:
  toStatic(), buildSimilarExternalFunctionNode()

- the following methods of SecondDerivExternalFunctionNode were not overloaded:
  toStatic(), buildSimilarExternalFunctionNode(), compile(),
  compileExternalFunctionOutput()
---
 preprocessor/DataTree.hh     |   1 +
 preprocessor/DynamicModel.cc |   4 +-
 preprocessor/ExprNode.cc     | 154 ++++++++++++++++++++++++-----------
 preprocessor/ExprNode.hh     |  76 +++++++++++++----
 preprocessor/ModelTree.cc    |   4 +-
 preprocessor/StaticModel.cc  |   8 +-
 6 files changed, 175 insertions(+), 72 deletions(-)

diff --git a/preprocessor/DataTree.hh b/preprocessor/DataTree.hh
index 859556c5c4..19712e9bfd 100644
--- a/preprocessor/DataTree.hh
+++ b/preprocessor/DataTree.hh
@@ -44,6 +44,7 @@ class DataTree
   friend class UnaryOpNode;
   friend class BinaryOpNode;
   friend class TrinaryOpNode;
+  friend class AbstractExternalFunctionNode;
   friend class ExternalFunctionNode;
   friend class FirstDerivExternalFunctionNode;
   friend class SecondDerivExternalFunctionNode;
diff --git a/preprocessor/DynamicModel.cc b/preprocessor/DynamicModel.cc
index 1a5de8b9b0..bd2adaede7 100644
--- a/preprocessor/DynamicModel.cc
+++ b/preprocessor/DynamicModel.cc
@@ -460,7 +460,7 @@ DynamicModel::writeModelEquationsOrdered_M(const string &dynamic_basename) const
               for (temporary_terms_t::const_iterator it = v_temporary_terms[block][i].begin();
                    it != v_temporary_terms[block][i].end(); it++)
                 {
-                  if (dynamic_cast<ExternalFunctionNode *>(*it) != NULL)
+                  if (dynamic_cast<AbstractExternalFunctionNode *>(*it) != NULL)
                     (*it)->writeExternalFunctionOutput(output, local_output_type, tt2, tef_terms);
 
                   output << "  " <<  sps;
@@ -1181,7 +1181,7 @@ DynamicModel::writeModelEquationsCode_Block(string &file_name, const string &bin
               for (temporary_terms_t::const_iterator it = v_temporary_terms[block][i].begin();
                    it != v_temporary_terms[block][i].end(); it++)
                 {
-                  if (dynamic_cast<ExternalFunctionNode *>(*it) != NULL)
+                  if (dynamic_cast<AbstractExternalFunctionNode *>(*it) != NULL)
                     (*it)->compileExternalFunctionOutput(code_file, instruction_number, false, tt2, map_idx, true, false, tef_terms);
 
                   FNUMEXPR_ fnumexpr(TemporaryTerm, (int) (map_idx.find((*it)->idx)->second));
diff --git a/preprocessor/ExprNode.cc b/preprocessor/ExprNode.cc
index d6df84960d..f435107a3e 100644
--- a/preprocessor/ExprNode.cc
+++ b/preprocessor/ExprNode.cc
@@ -4274,19 +4274,26 @@ TrinaryOpNode::isInStaticForm() const
   return arg1->isInStaticForm() && arg2->isInStaticForm() && arg3->isInStaticForm();
 }
 
-ExternalFunctionNode::ExternalFunctionNode(DataTree &datatree_arg,
-                                           int symb_id_arg,
-                                           const vector<expr_t> &arguments_arg) :
+AbstractExternalFunctionNode::AbstractExternalFunctionNode(DataTree &datatree_arg,
+                                                           int symb_id_arg,
+                                                           const vector<expr_t> &arguments_arg) :
   ExprNode(datatree_arg),
   symb_id(symb_id_arg),
   arguments(arguments_arg)
+{
+}
+
+ExternalFunctionNode::ExternalFunctionNode(DataTree &datatree_arg,
+                                           int symb_id_arg,
+                                           const vector<expr_t> &arguments_arg) :
+  AbstractExternalFunctionNode(datatree_arg, symb_id_arg, arguments_arg)
 {
   // Add myself to the external function map
   datatree.external_function_node_map[make_pair(arguments, symb_id)] = this;
 }
 
 void
-ExternalFunctionNode::prepareForDerivation()
+AbstractExternalFunctionNode::prepareForDerivation()
 {
   if (preparedForDerivation)
     return;
@@ -4306,7 +4313,7 @@ ExternalFunctionNode::prepareForDerivation()
 }
 
 expr_t
-ExternalFunctionNode::computeDerivative(int deriv_id)
+AbstractExternalFunctionNode::computeDerivative(int deriv_id)
 {
   assert(datatree.external_functions_table.getNargs(symb_id) > 0);
   vector<expr_t> dargs;
@@ -4330,7 +4337,7 @@ ExternalFunctionNode::composeDerivatives(const vector<expr_t> &dargs)
 }
 
 expr_t
-ExternalFunctionNode::getChainRuleDerivative(int deriv_id, const map<int, expr_t> &recursive_variables)
+AbstractExternalFunctionNode::getChainRuleDerivative(int deriv_id, const map<int, expr_t> &recursive_variables)
 {
   assert(datatree.external_functions_table.getNargs(symb_id) > 0);
   vector<expr_t> dargs;
@@ -4349,9 +4356,9 @@ ExternalFunctionNode::computeTemporaryTerms(map<expr_t, int> &reference_count,
 }
 
 void
-ExternalFunctionNode::writeExternalFunctionArguments(ostream &output, ExprNodeOutputType output_type,
-                                                     const temporary_terms_t &temporary_terms,
-                                                     deriv_node_temp_terms_t &tef_terms) const
+AbstractExternalFunctionNode::writeExternalFunctionArguments(ostream &output, ExprNodeOutputType output_type,
+                                                             const temporary_terms_t &temporary_terms,
+                                                             deriv_node_temp_terms_t &tef_terms) const
 {
   for (vector<expr_t>::const_iterator it = arguments.begin();
        it != arguments.end(); it++)
@@ -4364,9 +4371,9 @@ ExternalFunctionNode::writeExternalFunctionArguments(ostream &output, ExprNodeOu
 }
 
 void
-ExternalFunctionNode::writePrhs(ostream &output, ExprNodeOutputType output_type,
-                                const temporary_terms_t &temporary_terms,
-                                deriv_node_temp_terms_t &tef_terms, const string &ending) const
+AbstractExternalFunctionNode::writePrhs(ostream &output, ExprNodeOutputType output_type,
+                                        const temporary_terms_t &temporary_terms,
+                                        deriv_node_temp_terms_t &tef_terms, const string &ending) const
 {
   output << "mxArray *prhs"<< ending << "[nrhs"<< ending << "];" << endl;
   int i = 0;
@@ -4411,10 +4418,10 @@ ExternalFunctionNode::writeOutput(ostream &output, ExprNodeOutputType output_typ
 }
 
 unsigned int
-ExternalFunctionNode::compileExternalFunctionArguments(ostream &CompileCode, unsigned int &instruction_number,
-                                                       bool lhs_rhs, const temporary_terms_t &temporary_terms,
-                                                       const map_idx_t &map_idx, bool dynamic, bool steady_dynamic,
-                                                       deriv_node_temp_terms_t &tef_terms) const
+AbstractExternalFunctionNode::compileExternalFunctionArguments(ostream &CompileCode, unsigned int &instruction_number,
+                                                               bool lhs_rhs, const temporary_terms_t &temporary_terms,
+                                                               const map_idx_t &map_idx, bool dynamic, bool steady_dynamic,
+                                                               deriv_node_temp_terms_t &tef_terms) const
 {
   for (vector<expr_t>::const_iterator it = arguments.begin();
        it != arguments.end(); it++)
@@ -4602,7 +4609,7 @@ ExternalFunctionNode::computeTemporaryTerms(map<expr_t, int> &reference_count,
 }
 
 void
-ExternalFunctionNode::collectDynamicVariables(SymbolType type_arg, set<pair<int, int> > &result) const
+AbstractExternalFunctionNode::collectDynamicVariables(SymbolType type_arg, set<pair<int, int> > &result) const
 {
   for (vector<expr_t>::const_iterator it = arguments.begin();
        it != arguments.end(); it++)
@@ -4610,9 +4617,9 @@ ExternalFunctionNode::collectDynamicVariables(SymbolType type_arg, set<pair<int,
 }
 
 void
-ExternalFunctionNode::collectTemporary_terms(const temporary_terms_t &temporary_terms, temporary_terms_inuse_t &temporary_terms_inuse, int Curr_Block) const
+AbstractExternalFunctionNode::collectTemporary_terms(const temporary_terms_t &temporary_terms, temporary_terms_inuse_t &temporary_terms_inuse, int Curr_Block) const
 {
-  temporary_terms_t::const_iterator it = temporary_terms.find(const_cast<ExternalFunctionNode *>(this));
+  temporary_terms_t::const_iterator it = temporary_terms.find(const_cast<AbstractExternalFunctionNode *>(this));
   if (it != temporary_terms.end())
     temporary_terms_inuse.insert(idx);
   else
@@ -4624,13 +4631,13 @@ ExternalFunctionNode::collectTemporary_terms(const temporary_terms_t &temporary_
 }
 
 double
-ExternalFunctionNode::eval(const eval_context_t &eval_context) const throw (EvalException, EvalExternalFunctionException)
+AbstractExternalFunctionNode::eval(const eval_context_t &eval_context) const throw (EvalException, EvalExternalFunctionException)
 {
   throw EvalExternalFunctionException();
 }
 
 pair<int, expr_t>
-ExternalFunctionNode::normalizeEquation(int var_endo, vector<pair<int, pair<expr_t, expr_t> > >  &List_of_Op_RHS) const
+AbstractExternalFunctionNode::normalizeEquation(int var_endo, vector<pair<int, pair<expr_t, expr_t> > >  &List_of_Op_RHS) const
 {
   vector<pair<bool, expr_t> > V_arguments;
   vector<expr_t> V_expr_t;
@@ -4669,7 +4676,7 @@ ExternalFunctionNode::cloneDynamic(DataTree &dynamic_datatree) const
 }
 
 int
-ExternalFunctionNode::maxEndoLead() const
+AbstractExternalFunctionNode::maxEndoLead() const
 {
   int val = 0;
   for (vector<expr_t>::const_iterator it = arguments.begin();
@@ -4679,7 +4686,7 @@ ExternalFunctionNode::maxEndoLead() const
 }
 
 int
-ExternalFunctionNode::maxExoLead() const
+AbstractExternalFunctionNode::maxExoLead() const
 {
   int val = 0;
   for (vector<expr_t>::const_iterator it = arguments.begin();
@@ -4689,7 +4696,7 @@ ExternalFunctionNode::maxExoLead() const
 }
 
 int
-ExternalFunctionNode::maxEndoLag() const
+AbstractExternalFunctionNode::maxEndoLag() const
 {
   int val = 0;
   for (vector<expr_t>::const_iterator it = arguments.begin();
@@ -4699,7 +4706,7 @@ ExternalFunctionNode::maxEndoLag() const
 }
 
 int
-ExternalFunctionNode::maxExoLag() const
+AbstractExternalFunctionNode::maxExoLag() const
 {
   int val = 0;
   for (vector<expr_t>::const_iterator it = arguments.begin();
@@ -4709,7 +4716,7 @@ ExternalFunctionNode::maxExoLag() const
 }
 
 int
-ExternalFunctionNode::maxLead() const
+AbstractExternalFunctionNode::maxLead() const
 {
   int val = 0;
   for (vector<expr_t>::const_iterator it = arguments.begin();
@@ -4719,7 +4726,7 @@ ExternalFunctionNode::maxLead() const
 }
 
 expr_t
-ExternalFunctionNode::decreaseLeadsLags(int n) const
+AbstractExternalFunctionNode::decreaseLeadsLags(int n) const
 {
   vector<expr_t> arguments_subst;
   for (vector<expr_t>::const_iterator it = arguments.begin(); it != arguments.end(); it++)
@@ -4728,7 +4735,7 @@ ExternalFunctionNode::decreaseLeadsLags(int n) const
 }
 
 expr_t
-ExternalFunctionNode::decreaseLeadsLagsPredeterminedVariables() const
+AbstractExternalFunctionNode::decreaseLeadsLagsPredeterminedVariables() const
 {
   vector<expr_t> arguments_subst;
   for (vector<expr_t>::const_iterator it = arguments.begin(); it != arguments.end(); it++)
@@ -4737,7 +4744,7 @@ ExternalFunctionNode::decreaseLeadsLagsPredeterminedVariables() const
 }
 
 expr_t
-ExternalFunctionNode::substituteEndoLeadGreaterThanTwo(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs, bool deterministic_model) const
+AbstractExternalFunctionNode::substituteEndoLeadGreaterThanTwo(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs, bool deterministic_model) const
 {
   vector<expr_t> arguments_subst;
   for (vector<expr_t>::const_iterator it = arguments.begin(); it != arguments.end(); it++)
@@ -4746,7 +4753,7 @@ ExternalFunctionNode::substituteEndoLeadGreaterThanTwo(subst_table_t &subst_tabl
 }
 
 expr_t
-ExternalFunctionNode::substituteEndoLagGreaterThanTwo(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const
+AbstractExternalFunctionNode::substituteEndoLagGreaterThanTwo(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const
 {
   vector<expr_t> arguments_subst;
   for (vector<expr_t>::const_iterator it = arguments.begin(); it != arguments.end(); it++)
@@ -4755,7 +4762,7 @@ ExternalFunctionNode::substituteEndoLagGreaterThanTwo(subst_table_t &subst_table
 }
 
 expr_t
-ExternalFunctionNode::substituteExoLead(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs, bool deterministic_model) const
+AbstractExternalFunctionNode::substituteExoLead(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs, bool deterministic_model) const
 {
   vector<expr_t> arguments_subst;
   for (vector<expr_t>::const_iterator it = arguments.begin(); it != arguments.end(); it++)
@@ -4764,7 +4771,7 @@ ExternalFunctionNode::substituteExoLead(subst_table_t &subst_table, vector<Binar
 }
 
 expr_t
-ExternalFunctionNode::substituteExoLag(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const
+AbstractExternalFunctionNode::substituteExoLag(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const
 {
   vector<expr_t> arguments_subst;
   for (vector<expr_t>::const_iterator it = arguments.begin(); it != arguments.end(); it++)
@@ -4773,7 +4780,7 @@ ExternalFunctionNode::substituteExoLag(subst_table_t &subst_table, vector<Binary
 }
 
 expr_t
-ExternalFunctionNode::substituteExpectation(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs, bool partial_information_model) const
+AbstractExternalFunctionNode::substituteExpectation(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs, bool partial_information_model) const
 {
   vector<expr_t> arguments_subst;
   for (vector<expr_t>::const_iterator it = arguments.begin(); it != arguments.end(); it++)
@@ -4782,7 +4789,7 @@ ExternalFunctionNode::substituteExpectation(subst_table_t &subst_table, vector<B
 }
 
 expr_t
-ExternalFunctionNode::differentiateForwardVars(const vector<string> &subset, subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const
+AbstractExternalFunctionNode::differentiateForwardVars(const vector<string> &subset, subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const
 {
   vector<expr_t> arguments_subst;
   for (vector<expr_t>::const_iterator it = arguments.begin(); it != arguments.end(); it++)
@@ -4797,7 +4804,7 @@ ExternalFunctionNode::buildSimilarExternalFunctionNode(vector<expr_t> &alt_args,
 }
 
 bool
-ExternalFunctionNode::alreadyWrittenAsTefTerm(int the_symb_id, deriv_node_temp_terms_t &tef_terms) const
+AbstractExternalFunctionNode::alreadyWrittenAsTefTerm(int the_symb_id, deriv_node_temp_terms_t &tef_terms) const
 {
   deriv_node_temp_terms_t::const_iterator it = tef_terms.find(make_pair(the_symb_id, arguments));
   if (it != tef_terms.end())
@@ -4806,7 +4813,7 @@ ExternalFunctionNode::alreadyWrittenAsTefTerm(int the_symb_id, deriv_node_temp_t
 }
 
 int
-ExternalFunctionNode::getIndxInTefTerms(int the_symb_id, deriv_node_temp_terms_t &tef_terms) const throw (UnknownFunctionNameAndArgs)
+AbstractExternalFunctionNode::getIndxInTefTerms(int the_symb_id, deriv_node_temp_terms_t &tef_terms) const throw (UnknownFunctionNameAndArgs)
 {
   deriv_node_temp_terms_t::const_iterator it = tef_terms.find(make_pair(the_symb_id, arguments));
   if (it != tef_terms.end())
@@ -4815,19 +4822,19 @@ ExternalFunctionNode::getIndxInTefTerms(int the_symb_id, deriv_node_temp_terms_t
 }
 
 bool
-ExternalFunctionNode::isNumConstNodeEqualTo(double value) const
+AbstractExternalFunctionNode::isNumConstNodeEqualTo(double value) const
 {
   return false;
 }
 
 bool
-ExternalFunctionNode::isVariableNodeEqualTo(SymbolType type_arg, int variable_id, int lag_arg) const
+AbstractExternalFunctionNode::isVariableNodeEqualTo(SymbolType type_arg, int variable_id, int lag_arg) const
 {
   return false;
 }
 
 bool
-ExternalFunctionNode::containsEndogenous(void) const
+AbstractExternalFunctionNode::containsEndogenous(void) const
 {
   bool result = false;
   for (vector<expr_t>::const_iterator it = arguments.begin(); it != arguments.end(); it++)
@@ -4836,7 +4843,7 @@ ExternalFunctionNode::containsEndogenous(void) const
 }
 
 expr_t
-ExternalFunctionNode::replaceTrendVar() const
+AbstractExternalFunctionNode::replaceTrendVar() const
 {
   vector<expr_t> arguments_subst;
   for (vector<expr_t>::const_iterator it = arguments.begin(); it != arguments.end(); it++)
@@ -4845,7 +4852,7 @@ ExternalFunctionNode::replaceTrendVar() const
 }
 
 expr_t
-ExternalFunctionNode::detrend(int symb_id, bool log_trend, expr_t trend) const
+AbstractExternalFunctionNode::detrend(int symb_id, bool log_trend, expr_t trend) const
 {
   vector<expr_t> arguments_subst;
   for (vector<expr_t>::const_iterator it = arguments.begin(); it != arguments.end(); it++)
@@ -4854,7 +4861,7 @@ ExternalFunctionNode::detrend(int symb_id, bool log_trend, expr_t trend) const
 }
 
 expr_t
-ExternalFunctionNode::removeTrendLeadLag(map<int, expr_t> trend_symbols_map) const
+AbstractExternalFunctionNode::removeTrendLeadLag(map<int, expr_t> trend_symbols_map) const
 {
   vector<expr_t> arguments_subst;
   for (vector<expr_t>::const_iterator it = arguments.begin(); it != arguments.end(); it++)
@@ -4863,7 +4870,7 @@ ExternalFunctionNode::removeTrendLeadLag(map<int, expr_t> trend_symbols_map) con
 }
 
 bool
-ExternalFunctionNode::isInStaticForm() const
+AbstractExternalFunctionNode::isInStaticForm() const
 {
   for (vector<expr_t>::const_iterator it = arguments.begin(); it != arguments.end(); ++it)
     if (!(*it)->isInStaticForm())
@@ -4876,7 +4883,7 @@ FirstDerivExternalFunctionNode::FirstDerivExternalFunctionNode(DataTree &datatre
                                                                int top_level_symb_id_arg,
                                                                const vector<expr_t> &arguments_arg,
                                                                int inputIndex_arg) :
-  ExternalFunctionNode(datatree_arg, top_level_symb_id_arg, arguments_arg),
+  AbstractExternalFunctionNode(datatree_arg, top_level_symb_id_arg, arguments_arg),
   inputIndex(inputIndex_arg)
 {
   // Add myself to the first derivative external function map
@@ -5151,12 +5158,29 @@ FirstDerivExternalFunctionNode::cloneDynamic(DataTree &dynamic_datatree) const
                                                         inputIndex);
 }
 
+expr_t
+FirstDerivExternalFunctionNode::buildSimilarExternalFunctionNode(vector<expr_t> &alt_args, DataTree &alt_datatree) const
+{
+  return alt_datatree.AddFirstDerivExternalFunction(symb_id, alt_args, inputIndex);
+}
+
+expr_t
+FirstDerivExternalFunctionNode::toStatic(DataTree &static_datatree) const
+{
+  vector<expr_t> static_arguments;
+  for (vector<expr_t>::const_iterator it = arguments.begin();
+       it != arguments.end(); it++)
+    static_arguments.push_back((*it)->toStatic(static_datatree));
+  return static_datatree.AddFirstDerivExternalFunction(symb_id, static_arguments,
+                                                       inputIndex);
+}
+
 SecondDerivExternalFunctionNode::SecondDerivExternalFunctionNode(DataTree &datatree_arg,
                                                                  int top_level_symb_id_arg,
                                                                  const vector<expr_t> &arguments_arg,
                                                                  int inputIndex1_arg,
                                                                  int inputIndex2_arg) :
-  ExternalFunctionNode(datatree_arg, top_level_symb_id_arg, arguments_arg),
+  AbstractExternalFunctionNode(datatree_arg, top_level_symb_id_arg, arguments_arg),
   inputIndex1(inputIndex1_arg),
   inputIndex2(inputIndex2_arg)
 {
@@ -5187,7 +5211,8 @@ SecondDerivExternalFunctionNode::computeTemporaryTerms(map<expr_t, int> &referen
 }
 
 expr_t
-SecondDerivExternalFunctionNode::computeDerivative(int deriv_id)
+SecondDerivExternalFunctionNode::composeDerivatives(const vector<expr_t> &dargs)
+
 {
   cerr << "ERROR: third order derivatives of external functions are not implemented" << endl;
   exit(EXIT_FAILURE);
@@ -5358,3 +5383,40 @@ SecondDerivExternalFunctionNode::cloneDynamic(DataTree &dynamic_datatree) const
   return dynamic_datatree.AddSecondDerivExternalFunction(symb_id, dynamic_arguments,
                                                          inputIndex1, inputIndex2);
 }
+
+expr_t
+SecondDerivExternalFunctionNode::buildSimilarExternalFunctionNode(vector<expr_t> &alt_args, DataTree &alt_datatree) const
+{
+  return alt_datatree.AddSecondDerivExternalFunction(symb_id, alt_args, inputIndex1, inputIndex2);
+}
+
+expr_t
+SecondDerivExternalFunctionNode::toStatic(DataTree &static_datatree) const
+{
+  vector<expr_t> static_arguments;
+  for (vector<expr_t>::const_iterator it = arguments.begin();
+       it != arguments.end(); it++)
+    static_arguments.push_back((*it)->toStatic(static_datatree));
+  return static_datatree.AddSecondDerivExternalFunction(symb_id, static_arguments,
+                                                        inputIndex1, inputIndex2);
+}
+
+void
+SecondDerivExternalFunctionNode::compile(ostream &CompileCode, unsigned int &instruction_number,
+                                         bool lhs_rhs, const temporary_terms_t &temporary_terms,
+                                         const map_idx_t &map_idx, bool dynamic, bool steady_dynamic,
+                                         deriv_node_temp_terms_t &tef_terms) const
+{
+  cerr << "SecondDerivExternalFunctionNode::compile: not implemented." << endl;
+  exit(EXIT_FAILURE);
+}
+
+void
+SecondDerivExternalFunctionNode::compileExternalFunctionOutput(ostream &CompileCode, unsigned int &instruction_number,
+                                                               bool lhs_rhs, const temporary_terms_t &temporary_terms,
+                                                               const map_idx_t &map_idx, bool dynamic, bool steady_dynamic,
+                                                               deriv_node_temp_terms_t &tef_terms) const
+{
+  cerr << "SecondDerivExternalFunctionNode::compileExternalFunctionOutput: not implemented." << endl;
+  exit(EXIT_FAILURE);
+}
diff --git a/preprocessor/ExprNode.hh b/preprocessor/ExprNode.hh
index c0de01b82e..b008333cdf 100644
--- a/preprocessor/ExprNode.hh
+++ b/preprocessor/ExprNode.hh
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007-2013 Dynare Team
+ * Copyright (C) 2007-2014 Dynare Team
  *
  * This file is part of Dynare.
  *
@@ -125,7 +125,7 @@ class ExprNode
   friend class UnaryOpNode;
   friend class BinaryOpNode;
   friend class TrinaryOpNode;
-  friend class ExternalFunctionNode;
+  friend class AbstractExternalFunctionNode;
 private:
   //! Computes derivative w.r. to a derivation ID (but doesn't store it in derivatives map)
   /*! You shoud use getDerivative() to get the benefit of symbolic a priori and of caching */
@@ -771,11 +771,11 @@ public:
 };
 
 //! External function node
-class ExternalFunctionNode : public ExprNode
+class AbstractExternalFunctionNode : public ExprNode
 {
 private:
   virtual expr_t computeDerivative(int deriv_id);
-  virtual expr_t composeDerivatives(const vector<expr_t> &dargs);
+  virtual expr_t composeDerivatives(const vector<expr_t> &dargs) = 0;
 protected:
   //! Thrown when trying to access an unknown entry in external_function_node_map
   class UnknownFunctionNameAndArgs
@@ -790,24 +790,24 @@ protected:
   //! Helper function to write output arguments of any given external function
   void writeExternalFunctionArguments(ostream &output, ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms, deriv_node_temp_terms_t &tef_terms) const;
 public:
-  ExternalFunctionNode(DataTree &datatree_arg, int symb_id_arg,
-                       const vector<expr_t> &arguments_arg);
+  AbstractExternalFunctionNode(DataTree &datatree_arg, int symb_id_arg,
+                               const vector<expr_t> &arguments_arg);
   virtual void prepareForDerivation();
-  virtual void computeTemporaryTerms(map<expr_t, int> &reference_count, temporary_terms_t &temporary_terms, bool is_matlab) const;
-  virtual void writeOutput(ostream &output, ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms, deriv_node_temp_terms_t &tef_terms) const;
+  virtual void computeTemporaryTerms(map<expr_t, int> &reference_count, temporary_terms_t &temporary_terms, bool is_matlab) const = 0;
+  virtual void writeOutput(ostream &output, ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms, deriv_node_temp_terms_t &tef_terms) const = 0;
   virtual void writeExternalFunctionOutput(ostream &output, ExprNodeOutputType output_type,
                                            const temporary_terms_t &temporary_terms,
-                                           deriv_node_temp_terms_t &tef_terms) const;
+                                           deriv_node_temp_terms_t &tef_terms) const = 0;
   virtual void compileExternalFunctionOutput(ostream &CompileCode, unsigned int &instruction_number,
                                              bool lhs_rhs, const temporary_terms_t &temporary_terms,
                                              const map_idx_t &map_idx, bool dynamic, bool steady_dynamic,
-                                             deriv_node_temp_terms_t &tef_terms) const;
+                                             deriv_node_temp_terms_t &tef_terms) const = 0;
   virtual void computeTemporaryTerms(map<expr_t, int> &reference_count,
                                      temporary_terms_t &temporary_terms,
                                      map<expr_t, pair<int, int> > &first_occurence,
                                      int Curr_block,
                                      vector< vector<temporary_terms_t> > &v_temporary_terms,
-                                     int equation) const;
+                                     int equation) const = 0;
   virtual void collectDynamicVariables(SymbolType type_arg, set<pair<int, int> > &result) const;
   virtual void collectTemporary_terms(const temporary_terms_t &temporary_terms, temporary_terms_inuse_t &temporary_terms_inuse, int Curr_Block) const;
   virtual double eval(const eval_context_t &eval_context) const throw (EvalException, EvalExternalFunctionException);
@@ -816,8 +816,8 @@ public:
                                                 const map_idx_t &map_idx, bool dynamic, bool steady_dynamic,
                                                 deriv_node_temp_terms_t &tef_terms) const;
 
-  virtual void compile(ostream &CompileCode, unsigned int &instruction_number, bool lhs_rhs, const temporary_terms_t &temporary_terms, const map_idx_t &map_idx, bool dynamic, bool steady_dynamic, deriv_node_temp_terms_t &tef_terms) const;
-  virtual expr_t toStatic(DataTree &static_datatree) const;
+  virtual void compile(ostream &CompileCode, unsigned int &instruction_number, bool lhs_rhs, const temporary_terms_t &temporary_terms, const map_idx_t &map_idx, bool dynamic, bool steady_dynamic, deriv_node_temp_terms_t &tef_terms) const = 0;
+  virtual expr_t toStatic(DataTree &static_datatree) const = 0;
   virtual pair<int, expr_t> normalizeEquation(int symb_id_endo, vector<pair<int, pair<expr_t, expr_t> > >  &List_of_Op_RHS) const;
   virtual expr_t getChainRuleDerivative(int deriv_id, const map<int, expr_t> &recursive_variables);
   virtual int maxEndoLead() const;
@@ -831,7 +831,7 @@ public:
   virtual expr_t substituteExoLead(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs, bool deterministic_model) const;
   virtual expr_t substituteExoLag(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const;
   virtual expr_t substituteExpectation(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs, bool partial_information_model) const;
-  virtual expr_t buildSimilarExternalFunctionNode(vector<expr_t> &alt_args, DataTree &alt_datatree) const;
+  virtual expr_t buildSimilarExternalFunctionNode(vector<expr_t> &alt_args, DataTree &alt_datatree) const = 0;
   virtual expr_t decreaseLeadsLagsPredeterminedVariables() const;
   virtual expr_t differentiateForwardVars(const vector<string> &subset, subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const;
   virtual bool isNumConstNodeEqualTo(double value) const;
@@ -840,12 +840,40 @@ public:
   virtual void writePrhs(ostream &output, ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms, deriv_node_temp_terms_t &tef_terms, const string &ending) const;
   virtual expr_t replaceTrendVar() const;
   virtual expr_t detrend(int symb_id, bool log_trend, expr_t trend) const;
-  virtual expr_t cloneDynamic(DataTree &dynamic_datatree) const;
+  virtual expr_t cloneDynamic(DataTree &dynamic_datatree) const = 0;
   virtual expr_t removeTrendLeadLag(map<int, expr_t> trend_symbols_map) const;
   virtual bool isInStaticForm() const;
 };
 
-class FirstDerivExternalFunctionNode : public ExternalFunctionNode
+class ExternalFunctionNode : public AbstractExternalFunctionNode
+{
+private:
+  virtual expr_t composeDerivatives(const vector<expr_t> &dargs);
+public:
+  ExternalFunctionNode(DataTree &datatree_arg, int symb_id_arg,
+                       const vector<expr_t> &arguments_arg);
+  virtual void computeTemporaryTerms(map<expr_t, int> &reference_count, temporary_terms_t &temporary_terms, bool is_matlab) const;
+  virtual void writeOutput(ostream &output, ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms, deriv_node_temp_terms_t &tef_terms) const;
+  virtual void writeExternalFunctionOutput(ostream &output, ExprNodeOutputType output_type,
+                                           const temporary_terms_t &temporary_terms,
+                                           deriv_node_temp_terms_t &tef_terms) const;
+  virtual void compileExternalFunctionOutput(ostream &CompileCode, unsigned int &instruction_number,
+                                             bool lhs_rhs, const temporary_terms_t &temporary_terms,
+                                             const map_idx_t &map_idx, bool dynamic, bool steady_dynamic,
+                                             deriv_node_temp_terms_t &tef_terms) const;
+  virtual void computeTemporaryTerms(map<expr_t, int> &reference_count,
+                                     temporary_terms_t &temporary_terms,
+                                     map<expr_t, pair<int, int> > &first_occurence,
+                                     int Curr_block,
+                                     vector< vector<temporary_terms_t> > &v_temporary_terms,
+                                     int equation) const;
+  virtual void compile(ostream &CompileCode, unsigned int &instruction_number, bool lhs_rhs, const temporary_terms_t &temporary_terms, const map_idx_t &map_idx, bool dynamic, bool steady_dynamic, deriv_node_temp_terms_t &tef_terms) const;
+  virtual expr_t toStatic(DataTree &static_datatree) const;
+  virtual expr_t buildSimilarExternalFunctionNode(vector<expr_t> &alt_args, DataTree &alt_datatree) const;
+  virtual expr_t cloneDynamic(DataTree &dynamic_datatree) const;
+};
+
+class FirstDerivExternalFunctionNode : public AbstractExternalFunctionNode
 {
 private:
   const int inputIndex;
@@ -874,15 +902,17 @@ public:
                                              bool lhs_rhs, const temporary_terms_t &temporary_terms,
                                              const map_idx_t &map_idx, bool dynamic, bool steady_dynamic,
                                              deriv_node_temp_terms_t &tef_terms) const;
+  virtual expr_t toStatic(DataTree &static_datatree) const;
+  virtual expr_t buildSimilarExternalFunctionNode(vector<expr_t> &alt_args, DataTree &alt_datatree) const;
   virtual expr_t cloneDynamic(DataTree &dynamic_datatree) const;
 };
 
-class SecondDerivExternalFunctionNode : public ExternalFunctionNode
+class SecondDerivExternalFunctionNode : public AbstractExternalFunctionNode
 {
 private:
   const int inputIndex1;
   const int inputIndex2;
-  virtual expr_t computeDerivative(int deriv_id);
+  virtual expr_t composeDerivatives(const vector<expr_t> &dargs);
 public:
   SecondDerivExternalFunctionNode(DataTree &datatree_arg,
                                   int top_level_symb_id_arg,
@@ -897,9 +927,19 @@ public:
                                      vector< vector<temporary_terms_t> > &v_temporary_terms,
                                      int equation) const;
   virtual void writeOutput(ostream &output, ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms, deriv_node_temp_terms_t &tef_terms) const;
+  virtual void compile(ostream &CompileCode, unsigned int &instruction_number,
+                       bool lhs_rhs, const temporary_terms_t &temporary_terms,
+                       const map_idx_t &map_idx, bool dynamic, bool steady_dynamic,
+                       deriv_node_temp_terms_t &tef_terms) const;
   virtual void writeExternalFunctionOutput(ostream &output, ExprNodeOutputType output_type,
                                            const temporary_terms_t &temporary_terms,
                                            deriv_node_temp_terms_t &tef_terms) const;
+  virtual void compileExternalFunctionOutput(ostream &CompileCode, unsigned int &instruction_number,
+                                             bool lhs_rhs, const temporary_terms_t &temporary_terms,
+                                             const map_idx_t &map_idx, bool dynamic, bool steady_dynamic,
+                                             deriv_node_temp_terms_t &tef_terms) const;
+  virtual expr_t toStatic(DataTree &static_datatree) const;
+  virtual expr_t buildSimilarExternalFunctionNode(vector<expr_t> &alt_args, DataTree &alt_datatree) const;
   virtual expr_t cloneDynamic(DataTree &dynamic_datatree) const;
 };
 
diff --git a/preprocessor/ModelTree.cc b/preprocessor/ModelTree.cc
index 5daf09df08..a83ea06f90 100644
--- a/preprocessor/ModelTree.cc
+++ b/preprocessor/ModelTree.cc
@@ -1113,7 +1113,7 @@ ModelTree::writeTemporaryTerms(const temporary_terms_t &tt, ostream &output,
   for (temporary_terms_t::const_iterator it = tt.begin();
        it != tt.end(); it++)
     {
-      if (dynamic_cast<ExternalFunctionNode *>(*it) != NULL)
+      if (dynamic_cast<AbstractExternalFunctionNode *>(*it) != NULL)
         (*it)->writeExternalFunctionOutput(output, output_type, tt2, tef_terms);
 
       if (IS_C(output_type))
@@ -1144,7 +1144,7 @@ ModelTree::compileTemporaryTerms(ostream &code_file, unsigned int &instruction_n
   for (temporary_terms_t::const_iterator it = tt.begin();
        it != tt.end(); it++)
     {
-      if (dynamic_cast<ExternalFunctionNode *>(*it) != NULL)
+      if (dynamic_cast<AbstractExternalFunctionNode *>(*it) != NULL)
         {
           (*it)->compileExternalFunctionOutput(code_file, instruction_number, false, tt2, map_idx, dynamic, steady_dynamic, tef_terms);
         }
diff --git a/preprocessor/StaticModel.cc b/preprocessor/StaticModel.cc
index d82efaeda7..ab11ca9aae 100644
--- a/preprocessor/StaticModel.cc
+++ b/preprocessor/StaticModel.cc
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2003-2012 Dynare Team
+ * Copyright (C) 2003-2014 Dynare Team
  *
  * This file is part of Dynare.
  *
@@ -286,7 +286,7 @@ StaticModel::writeModelEquationsOrdered_M(const string &static_basename) const
               for (temporary_terms_t::const_iterator it = v_temporary_terms[block][i].begin();
                    it != v_temporary_terms[block][i].end(); it++)
                 {
-                  if (dynamic_cast<ExternalFunctionNode *>(*it) != NULL)
+                  if (dynamic_cast<AbstractExternalFunctionNode *>(*it) != NULL)
                     (*it)->writeExternalFunctionOutput(output, local_output_type, tt2, tef_terms);
 
                   output << "  " <<  sps;
@@ -658,7 +658,7 @@ StaticModel::writeModelEquationsCode_Block(const string file_name, const string
               for (temporary_terms_t::const_iterator it = v_temporary_terms[block][i].begin();
                    it != v_temporary_terms[block][i].end(); it++)
                 {
-                  if (dynamic_cast<ExternalFunctionNode *>(*it) != NULL)
+                  if (dynamic_cast<AbstractExternalFunctionNode *>(*it) != NULL)
                     (*it)->compileExternalFunctionOutput(code_file, instruction_number, false, tt2, map_idx, false, false, tef_terms);
 
                   FNUMEXPR_ fnumexpr(TemporaryTerm, (int) (map_idx.find((*it)->idx)->second));
@@ -851,7 +851,7 @@ StaticModel::writeModelEquationsCode_Block(const string file_name, const string
               for (temporary_terms_t::const_iterator it = v_temporary_terms_local[block][i].begin();
                    it != v_temporary_terms_local[block][i].end(); it++)
                 {
-                  if (dynamic_cast<ExternalFunctionNode *>(*it) != NULL)
+                  if (dynamic_cast<AbstractExternalFunctionNode *>(*it) != NULL)
                     (*it)->compileExternalFunctionOutput(code_file, instruction_number, false, tt3, map_idx2[block], false, false, tef_terms2);
 
                   FNUMEXPR_ fnumexpr(TemporaryTerm, (int) (map_idx2[block].find((*it)->idx)->second));
-- 
GitLab