From cb369b3b98dcadf0c95fea162c97f10a979e9b08 Mon Sep 17 00:00:00 2001
From: Houtan Bastani <houtan@dynare.org>
Date: Mon, 12 Jun 2017 14:56:44 +0200
Subject: [PATCH] preprocessor: support adl and diff

---
 CodeInterpreter.hh |   6 ++-
 DataTree.cc        |  16 ++++++-
 DataTree.hh        |   8 ++++
 DynamicModel.cc    |  23 ++++++++++
 DynamicModel.hh    |   3 ++
 DynareBison.yy     |   8 +++-
 DynareFlex.ll      |   2 +
 ExprNode.cc        | 111 +++++++++++++++++++++++++++++++++++++++++++++
 ExprNode.hh        |  14 ++++++
 ModFile.cc         |   2 +
 ParsingDriver.cc   |  16 +++++++
 ParsingDriver.hh   |   4 ++
 SymbolTable.cc     |  17 +++++++
 SymbolTable.hh     |   4 ++
 14 files changed, 230 insertions(+), 4 deletions(-)

diff --git a/CodeInterpreter.hh b/CodeInterpreter.hh
index 3c2f6e00..8dfd7e40 100644
--- a/CodeInterpreter.hh
+++ b/CodeInterpreter.hh
@@ -200,7 +200,8 @@ enum UnaryOpcode
     oSteadyStateParamDeriv, // for the derivative of the STEADY_STATE operator w.r.t. to a parameter
     oSteadyStateParam2ndDeriv, // for the 2nd derivative of the STEADY_STATE operator w.r.t. to a parameter
     oExpectation,
-    oErf
+    oErf,
+    oDiff
   };
 
 enum BinaryOpcode
@@ -219,7 +220,8 @@ enum BinaryOpcode
     oLessEqual,
     oGreaterEqual,
     oEqualEqual,
-    oDifferent
+    oDifferent,
+    oAdl
   };
 
 enum TrinaryOpcode
diff --git a/DataTree.cc b/DataTree.cc
index adaed600..2ce90dcc 100644
--- a/DataTree.cc
+++ b/DataTree.cc
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2003-2016 Dynare Team
+ * Copyright (C) 2003-2017 Dynare Team
  *
  * This file is part of Dynare.
  *
@@ -257,6 +257,20 @@ DataTree::AddPowerDeriv(expr_t iArg1, expr_t iArg2, int powerDerivOrder)
   return AddBinaryOp(iArg1, oPowerDeriv, iArg2, powerDerivOrder);
 }
 
+expr_t
+DataTree::AddDiff(expr_t iArg1)
+{
+  return AddUnaryOp(oDiff, iArg1);
+}
+
+expr_t
+DataTree::AddAdl(expr_t iArg1, string &name, expr_t iArg2)
+{
+  expr_t adlnode = AddBinaryOp(iArg1, oAdl, iArg2);
+  adl_map[adlnode] = new string(name);
+  return adlnode;
+}
+
 expr_t
 DataTree::AddExp(expr_t iArg1)
 {
diff --git a/DataTree.hh b/DataTree.hh
index 486b5744..18e73417 100644
--- a/DataTree.hh
+++ b/DataTree.hh
@@ -57,6 +57,10 @@ protected:
   //! A reference to the external functions table
   ExternalFunctionsTable &external_functions_table;
 
+  //! A reference to the adl table
+  typedef map<expr_t, string *> adl_map_t;
+  adl_map_t adl_map;
+
   typedef map<int, NumConstNode *> num_const_node_map_t;
   num_const_node_map_t num_const_node_map;
   //! Pair (symbol_id, lag) used as key
@@ -162,6 +166,10 @@ public:
   expr_t AddPowerDeriv(expr_t iArg1, expr_t iArg2, int powerDerivOrder);
   //! Adds "E(arg1)(arg2)" to model tree
   expr_t AddExpectation(int iArg1, expr_t iArg2);
+  //! Adds "diff(arg)" to model tree
+  expr_t AddDiff(expr_t iArg1);
+  //! Adds "adl(arg1, arg2)" to model tree
+  expr_t AddAdl(expr_t iArg1, string &name, expr_t iArg2);
   //! Adds "exp(arg)" to model tree
   expr_t AddExp(expr_t iArg1);
   //! Adds "log(arg)" to model tree
diff --git a/DynamicModel.cc b/DynamicModel.cc
index 42eaab23..36f7432f 100644
--- a/DynamicModel.cc
+++ b/DynamicModel.cc
@@ -4651,6 +4651,29 @@ DynamicModel::substituteLeadLagInternal(aux_var_t type, bool deterministic_model
     }
 }
 
+void
+DynamicModel::substituteAdlAndDiff()
+{
+  cout << endl << "BEFORE TRANSFORM" << endl;
+  for (int i = 0; i < (int) equations.size(); i++)
+    {
+      cout << i << ") ";
+      equations[i]->write();
+      cout << endl;
+    }
+
+  for (int i = 0; i < (int) equations.size(); i++)
+    equations[i] = dynamic_cast<BinaryOpNode *>(equations[i]->substituteAdlAndDiff());
+
+  cout << endl << endl << "AFTER TRANSFORM" << endl;
+  for (int i = 0; i < (int) equations.size(); i++)
+    {
+      cout << i << ") ";
+      equations[i]->write();
+      cout << endl;
+    }
+}
+
 void
 DynamicModel::substituteExpectation(bool partial_information_model)
 {
diff --git a/DynamicModel.hh b/DynamicModel.hh
index 62443cf4..7c742f41 100644
--- a/DynamicModel.hh
+++ b/DynamicModel.hh
@@ -330,6 +330,9 @@ public:
   //! Transforms the model by removing trends specified by the user
   void detrendEquations();
 
+  //! Substitutes adl and diff operators
+  void substituteAdlAndDiff();
+
   //! Fill var_expectation_functions_to_write
   void fillVarExpectationFunctionsToWrite();
 
diff --git a/DynareBison.yy b/DynareBison.yy
index 11e2506e..06b7db9d 100644
--- a/DynareBison.yy
+++ b/DynareBison.yy
@@ -139,7 +139,7 @@ class ParsingDriver;
 %left TIMES DIVIDE
 %left UMINUS UPLUS
 %nonassoc POWER
-%token EXP LOG LN LOG10 SIN COS TAN ASIN ACOS ATAN SINH COSH TANH ERF
+%token EXP LOG LN LOG10 SIN COS TAN ASIN ACOS ATAN SINH COSH TANH ERF DIFF ADL
 %token ASINH ACOSH ATANH SQRT NORMCDF NORMPDF STEADY_STATE EXPECTATION VAR_ESTIMATION
 /* GSA analysis */
 %token DYNARE_SENSITIVITY MORRIS STAB REDFORM PPRIOR PRIOR_RANGE PPOST ILPTAU MORRIS_NLIV
@@ -884,6 +884,12 @@ hand_side : '(' hand_side ')'
             { $$ = $2; }
           | EXP '(' hand_side ')'
             { $$ = driver.add_exp($3); }
+          | DIFF '(' hand_side ')'
+            { $$ = driver.add_diff($3); }
+          | ADL '(' hand_side COMMA QUOTED_STRING ')'
+            { $$ = driver.add_adl($3, $5, new string("1")); }
+          | ADL '(' hand_side COMMA QUOTED_STRING COMMA INT_NUMBER ')'
+            { $$ = driver.add_adl($3, $5, $7); }
           | LOG '(' hand_side ')'
             { $$ = driver.add_log($3); }
           | LN '(' hand_side ')'
diff --git a/DynareFlex.ll b/DynareFlex.ll
index b3834a3a..811b817c 100644
--- a/DynareFlex.ll
+++ b/DynareFlex.ll
@@ -373,6 +373,8 @@ DATE -?[0-9]+([YyAa]|[Mm]([1-9]|1[0-2])|[Qq][1-4]|[Ww]([1-9]{1}|[1-4][0-9]|5[0-2
 <DYNARE_STATEMENT>restrictions {return token::RESTRICTIONS;}
 <DYNARE_BLOCK>crossequations {return token::CROSSEQUATIONS;}
 <DYNARE_BLOCK>covariance {return token::COVARIANCE;}
+<DYNARE_BLOCK>adl {return token::ADL;}
+<DYNARE_BLOCK>diff {return token::DIFF;}
 <DYNARE_STATEMENT>cross_restrictions {return token::CROSS_RESTRICTIONS;}
 <DYNARE_STATEMENT>contemp_reduced_form {return token::CONTEMP_REDUCED_FORM;}
 <DYNARE_STATEMENT>real_pseudo_forecast {return token::REAL_PSEUDO_FORECAST;}
diff --git a/ExprNode.cc b/ExprNode.cc
index e738f7fd..7fcd58fc 100644
--- a/ExprNode.cc
+++ b/ExprNode.cc
@@ -456,6 +456,12 @@ NumConstNode::substituteExpectation(subst_table_t &subst_table, vector<BinaryOpN
   return const_cast<NumConstNode *>(this);
 }
 
+expr_t
+NumConstNode::substituteAdlAndDiff() const
+{
+  return const_cast<NumConstNode *>(this);
+}
+
 expr_t
 NumConstNode::differentiateForwardVars(const vector<string> &subset, subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const
 {
@@ -1194,6 +1200,12 @@ VariableNode::maxLead() const
     }
 }
 
+expr_t
+VariableNode::substituteAdlAndDiff() const
+{
+  return const_cast<VariableNode *>(this);
+}
+
 expr_t
 VariableNode::decreaseLeadsLags(int n) const
 {
@@ -1706,6 +1718,9 @@ UnaryOpNode::composeDerivatives(expr_t darg, int deriv_id)
       t14 = datatree.AddDivide(datatree.Two, t13);
       // (2/(sqrt(pi)*exp(x^2)))*dx;
       return datatree.AddTimes(t14, darg);
+    case oDiff:
+      cerr << "UnaryOpNode::composeDerivatives: not implemented on oDiff" << endl;
+      exit(EXIT_FAILURE);
     }
   // Suppress GCC warning
   exit(EXIT_FAILURE);
@@ -1787,6 +1802,9 @@ UnaryOpNode::cost(int cost, bool is_matlab) const
       case oSteadyStateParam2ndDeriv:
       case oExpectation:
         return cost;
+      case oDiff:
+        cerr << "UnaryOpNode::cost: not implemented on oDiff" << endl;
+        exit(EXIT_FAILURE);
       }
   else
     // Cost for C files
@@ -1829,6 +1847,9 @@ UnaryOpNode::cost(int cost, bool is_matlab) const
       case oSteadyStateParam2ndDeriv:
       case oExpectation:
         return cost;
+      case oDiff:
+        cerr << "UnaryOpNode::cost: not implemented on oDiff" << endl;
+        exit(EXIT_FAILURE);
       }
   exit(EXIT_FAILURE);
 }
@@ -2054,6 +2075,9 @@ UnaryOpNode::writeOutput(ostream &output, ExprNodeOutputType output_type,
     case oErf:
       output << "erf";
       break;
+    case oDiff:
+      output << "diff";
+      break;
     }
 
   bool close_parenthesis = false;
@@ -2151,6 +2175,9 @@ UnaryOpNode::eval_opcode(UnaryOpcode op_code, double v) throw (EvalException, Ev
     case oExpectation:
     case oErf:
       return (erf(v));
+    case oDiff:
+      cerr << "UnaryOpNode::eval_opcode: not implemented on oDiff" << endl;
+      exit(EXIT_FAILURE);
     }
   // Suppress GCC warning
   exit(EXIT_FAILURE);
@@ -2400,6 +2427,8 @@ UnaryOpNode::buildSimilarUnaryOpNode(expr_t alt_arg, DataTree &alt_datatree) con
       return alt_datatree.AddExpectation(expectation_information_set, alt_arg);
     case oErf:
       return alt_datatree.AddErf(alt_arg);
+    case oDiff:
+      return alt_datatree.AddDiff(alt_arg);
     }
   // Suppress GCC warning
   exit(EXIT_FAILURE);
@@ -2455,6 +2484,20 @@ UnaryOpNode::maxLead() const
   return arg->maxLead();
 }
 
+expr_t
+UnaryOpNode::substituteAdlAndDiff() const
+{
+  if (op_code != oDiff)
+    {
+      expr_t argsubst = arg->substituteAdlAndDiff();
+      return buildSimilarUnaryOpNode(argsubst, datatree);
+    }
+
+  expr_t argsubst = arg->substituteAdlAndDiff();
+  return datatree.AddMinus(argsubst,
+                           argsubst->decreaseLeadsLags(1));
+}
+
 expr_t
 UnaryOpNode::decreaseLeadsLags(int n) const
 {
@@ -2803,6 +2846,9 @@ BinaryOpNode::composeDerivatives(expr_t darg1, expr_t darg2)
       return datatree.AddPlus(t14, t12);
     case oEqual:
       return datatree.AddMinus(darg1, darg2);
+    case oAdl:
+      cerr << "BinaryOpNode::composeDerivatives not implemented for oAdl";
+      exit(EXIT_FAILURE);
     }
   // Suppress GCC warning
   exit(EXIT_FAILURE);
@@ -2869,6 +2915,9 @@ BinaryOpNode::precedence(ExprNodeOutputType output_type, const temporary_terms_t
     case oMin:
     case oMax:
       return 100;
+    case oAdl:
+      cerr << "BinaryOpNode::precedence not implemented for oAdl";
+      exit(EXIT_FAILURE);
     }
   // Suppress GCC warning
   exit(EXIT_FAILURE);
@@ -2928,6 +2977,9 @@ BinaryOpNode::cost(int cost, bool is_matlab) const
         return cost + (MIN_COST_MATLAB/2+1);
       case oEqual:
         return cost;
+      case oAdl:
+        cerr << "BinaryOpNode::cost not implemented for oAdl";
+        exit(EXIT_FAILURE);
       }
   else
     // Cost for C files
@@ -2955,6 +3007,9 @@ BinaryOpNode::cost(int cost, bool is_matlab) const
         return cost + (MIN_COST_C/2+1);;
       case oEqual:
         return cost;
+      case oAdl:
+        cerr << "BinaryOpNode::cost not implemented for oAdl";
+        exit(EXIT_FAILURE);
       }
   // Suppress GCC warning
   exit(EXIT_FAILURE);
@@ -3067,6 +3122,9 @@ BinaryOpNode::eval_opcode(double v1, BinaryOpcode op_code, double v2, int derivO
       return (v1 != v2);
     case oEqual:
       throw EvalException();
+    case oAdl:
+        cerr << "BinaryOpNode::eval_opcode not implemented for oAdl";
+        exit(EXIT_FAILURE);
     }
   // Suppress GCC warning
   exit(EXIT_FAILURE);
@@ -3685,6 +3743,10 @@ BinaryOpNode::buildSimilarBinaryOpNode(expr_t alt_arg1, expr_t alt_arg2, DataTre
       return alt_datatree.AddDifferent(alt_arg1, alt_arg2);
     case oPowerDeriv:
       return alt_datatree.AddPowerDeriv(alt_arg1, alt_arg2, powerDerivOrder);
+    case oAdl:
+      DataTree::adl_map_t::const_iterator it = datatree.adl_map.find(const_cast<BinaryOpNode *>(this));
+      assert (it != datatree.adl_map.end());
+      return alt_datatree.AddAdl(alt_arg1, *(it->second), alt_arg2);
     }
   // Suppress GCC warning
   exit(EXIT_FAILURE);
@@ -3871,6 +3933,31 @@ BinaryOpNode::substituteExpectation(subst_table_t &subst_table, vector<BinaryOpN
   return buildSimilarBinaryOpNode(arg1subst, arg2subst, datatree);
 }
 
+expr_t
+BinaryOpNode::substituteAdlAndDiff() const
+{
+  if (op_code != oAdl)
+    {
+      expr_t arg1subst = arg1->substituteAdlAndDiff();
+      expr_t arg2subst = arg2->substituteAdlAndDiff();
+      return buildSimilarBinaryOpNode(arg1subst, arg2subst, datatree);
+    }
+
+  expr_t arg1subst = arg1->substituteAdlAndDiff();
+  DataTree::adl_map_t::const_iterator it = datatree.adl_map.find(const_cast<BinaryOpNode *>(this));
+  assert (it != datatree.adl_map.end());
+
+  int i = 1;
+  expr_t retval = datatree.AddTimes(datatree.AddVariable(datatree.symbol_table.addAdlParameter(*(it->second), i), 0),
+                                    arg1subst->decreaseLeadsLags(i));
+  i++;
+  for (; i <= (int) arg2->eval(eval_context_t()); i++)
+    retval = datatree.AddPlus(retval,
+                              datatree.AddTimes(datatree.AddVariable(datatree.symbol_table.addAdlParameter(*(it->second), i), 0),
+                                                arg1subst->decreaseLeadsLags(i)));
+  return retval;
+}
+
 expr_t
 BinaryOpNode::differentiateForwardVars(const vector<string> &subset, subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const
 {
@@ -4567,6 +4654,15 @@ TrinaryOpNode::substituteExpectation(subst_table_t &subst_table, vector<BinaryOp
   return buildSimilarTrinaryOpNode(arg1subst, arg2subst, arg3subst, datatree);
 }
 
+expr_t
+TrinaryOpNode::substituteAdlAndDiff() const
+{
+  expr_t arg1subst = arg1->substituteAdlAndDiff();
+  expr_t arg2subst = arg2->substituteAdlAndDiff();
+  expr_t arg3subst = arg3->substituteAdlAndDiff();
+  return buildSimilarTrinaryOpNode(arg1subst, arg2subst, arg3subst, datatree);
+}
+
 expr_t
 TrinaryOpNode::differentiateForwardVars(const vector<string> &subset, subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const
 {
@@ -4870,6 +4966,15 @@ AbstractExternalFunctionNode::substituteExpectation(subst_table_t &subst_table,
   return buildSimilarExternalFunctionNode(arguments_subst, datatree);
 }
 
+expr_t
+AbstractExternalFunctionNode::substituteAdlAndDiff() const
+{
+  vector<expr_t> arguments_subst;
+  for (vector<expr_t>::const_iterator it = arguments.begin(); it != arguments.end(); it++)
+    arguments_subst.push_back((*it)->substituteAdlAndDiff());
+  return buildSimilarExternalFunctionNode(arguments_subst, datatree);
+}
+
 expr_t
 AbstractExternalFunctionNode::differentiateForwardVars(const vector<string> &subset, subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const
 {
@@ -6118,6 +6223,12 @@ VarExpectationNode::substituteExpectation(subst_table_t &subst_table, vector<Bin
   return const_cast<VarExpectationNode *>(this);
 }
 
+expr_t
+VarExpectationNode::substituteAdlAndDiff() const
+{
+  return const_cast<VarExpectationNode *>(this);
+}
+
 expr_t
 VarExpectationNode::differentiateForwardVars(const vector<string> &subset, subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const
 {
diff --git a/ExprNode.hh b/ExprNode.hh
index ca6cbeb7..b4d0ce15 100644
--- a/ExprNode.hh
+++ b/ExprNode.hh
@@ -336,6 +336,10 @@ enum ExprNodeOutputType
       //! Type for the substitution map used in the process of creating auxiliary vars for leads >= 2
       typedef map<const ExprNode *, const VariableNode *> subst_table_t;
 
+      //! Type for the substitution map used in the process of substituting adl/diff expressions
+      //      typedef map<const ExprNode *, const UnaryOpNode *> subst_table_diff_t;
+      typedef map<const ExprNode *, const expr_t> subst_table_adl_t;
+
       //! Creates auxiliary endo lead variables corresponding to this expression
       /*!
         If maximum endogenous lead >= 3, this method will also create intermediary auxiliary var, and will add the equations of the form aux1 = aux2(+1) to the substitution table.
@@ -441,6 +445,9 @@ enum ExprNodeOutputType
       */
       virtual expr_t detrend(int symb_id, bool log_trend, expr_t trend) const = 0;
 
+      //! Substitute adl and diff operators
+      virtual expr_t substituteAdlAndDiff() const = 0;
+
       //! Add ExprNodes to the provided datatree
       virtual expr_t cloneDynamic(DataTree &dynamic_datatree) const = 0;
 
@@ -510,6 +517,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 substituteAdlAndDiff() const;
   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;
@@ -583,6 +591,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 substituteAdlAndDiff() const;
   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;
@@ -672,6 +681,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 substituteAdlAndDiff() const;
   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;
@@ -774,6 +784,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 substituteAdlAndDiff() const;
   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;
@@ -858,6 +869,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 substituteAdlAndDiff() const;
   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;
@@ -941,6 +953,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 substituteAdlAndDiff() 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;
@@ -1106,6 +1119,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 substituteAdlAndDiff() const;
   virtual pair<int, expr_t> normalizeEquation(int symb_id_endo, vector<pair<int, pair<expr_t, expr_t> > >  &List_of_Op_RHS) const;
   virtual void compile(ostream &CompileCode, unsigned int &instruction_number,
                        bool lhs_rhs, const temporary_terms_t &temporary_terms,
diff --git a/ModFile.cc b/ModFile.cc
index 2aa4a392..88ef7f92 100644
--- a/ModFile.cc
+++ b/ModFile.cc
@@ -349,6 +349,8 @@ ModFile::transformPass(bool nostrict, bool compute_xrefs)
     }
 
   // Var Model
+  dynamic_model.substituteAdlAndDiff();
+
   map<string, pair<SymbolList, int> > var_model_info;
   for (vector<Statement *>::const_iterator it = statements.begin();
        it != statements.end(); it++)
diff --git a/ParsingDriver.cc b/ParsingDriver.cc
index d3c05fb8..e71b6321 100644
--- a/ParsingDriver.cc
+++ b/ParsingDriver.cc
@@ -2585,6 +2585,22 @@ ParsingDriver::add_exp(expr_t arg1)
   return data_tree->AddExp(arg1);
 }
 
+expr_t
+ParsingDriver::add_diff(expr_t arg1)
+{
+  return data_tree->AddDiff(arg1);
+}
+
+expr_t
+ParsingDriver::add_adl(expr_t arg1, string *name, string *lag)
+{
+  expr_t id = data_tree->AddAdl(arg1, *name,
+                                data_tree->AddNonNegativeConstant(*lag));
+  delete name;
+  delete lag;
+  return id;
+}
+
 expr_t
 ParsingDriver::add_log(expr_t arg1)
 {
diff --git a/ParsingDriver.hh b/ParsingDriver.hh
index 9d3eb46a..be533089 100644
--- a/ParsingDriver.hh
+++ b/ParsingDriver.hh
@@ -668,6 +668,10 @@ public:
   expr_t add_expectation(string *arg1,  expr_t arg2);
   //! Writes token "VAR_EXPECTATION(arg1, arg2, arg3)" to model tree
   expr_t add_var_expectation(string *arg1,  string *arg2, string *arg3);
+  //! Writes token "diff(arg1)" to model tree
+  expr_t add_diff(expr_t arg1);
+  //! Writes token "adl(arg1, lag)" to model tree
+  expr_t add_adl(expr_t arg1, string *name, string *lag);
   //! Writes token "exp(arg1)" to model tree
   expr_t add_exp(expr_t arg1);
   //! Writes token "log(arg1)" to model tree
diff --git a/SymbolTable.cc b/SymbolTable.cc
index fe96c908..0657fe2a 100644
--- a/SymbolTable.cc
+++ b/SymbolTable.cc
@@ -637,6 +637,23 @@ SymbolTable::addLagAuxiliaryVarInternal(bool endo, int orig_symb_id, int orig_le
   return symb_id;
 }
 
+int
+SymbolTable::addAdlParameter(string &basename, int lag) throw (FrozenException)
+{
+  ostringstream varname;
+  varname << basename << "_lag_" << lag;
+
+  try
+    {
+      return addSymbol(varname.str(), eParameter);
+    }
+  catch (AlreadyDeclaredException &e)
+    {
+      cerr << "ERROR: you should rename your variable called " << varname.str() << ", this name is internally used by Dynare" << endl;
+      exit(EXIT_FAILURE);
+    }
+}
+
 int
 SymbolTable::addEndoLeadAuxiliaryVar(int index, expr_t expr_arg) throw (FrozenException)
 {
diff --git a/SymbolTable.hh b/SymbolTable.hh
index 8a67d6bd..9dd260ee 100644
--- a/SymbolTable.hh
+++ b/SymbolTable.hh
@@ -283,6 +283,10 @@ public:
   //! Adds an auxiliary variable when var_model is used with an order that is greater in absolute value
   //! than the largest lag present in the model.
   int addVarModelEndoLagAuxiliaryVar(int orig_symb_id, int orig_lead_lag, expr_t expr_arg) throw (AlreadyDeclaredException, FrozenException);
+  /*
+  // Adds a parameter for the transformation of the adl operator
+  */
+  int addAdlParameter(string &basename, int lag) throw (FrozenException);
   //! Returns the number of auxiliary variables
   int
   AuxVarsSize() const
-- 
GitLab