From 8f31e443d65f76492dda8da14b62d5d4de56dcc7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?S=C3=A9bastien=20Villemot?= <sebastien@dynare.org>
Date: Wed, 23 Sep 2020 17:02:25 +0200
Subject: [PATCH] SymbolTable::getTypeSpecificID() now throws an exception
 instead of returning -1 when symbol does not have a type-specific ID

This can potentially avoid some undetected bugs.
---
 src/ExprNode.cc    | 16 +++++++++-------
 src/SymbolTable.cc |  7 +++----
 src/SymbolTable.hh | 20 +++++++++++++++++---
 3 files changed, 29 insertions(+), 14 deletions(-)

diff --git a/src/ExprNode.cc b/src/ExprNode.cc
index 10e9eaa3..a48de883 100644
--- a/src/ExprNode.cc
+++ b/src/ExprNode.cc
@@ -963,10 +963,11 @@ VariableNode::writeOutput(ostream &output, ExprNodeOutputType output_type,
     }
 
   int i;
-  switch (int tsid = datatree.symbol_table.getTypeSpecificID(symb_id); type)
+  switch (type)
     {
     case SymbolType::parameter:
-      if (output_type == ExprNodeOutputType::matlabOutsideModel)
+      if (int tsid = datatree.symbol_table.getTypeSpecificID(symb_id);
+          output_type == ExprNodeOutputType::matlabOutsideModel)
         output << "M_.params" << "(" << tsid + 1 << ")";
       else
         output << "params" << LEFT_ARRAY_SUBSCRIPT(output_type) << tsid + ARRAY_SUBSCRIPT_OFFSET(output_type) << RIGHT_ARRAY_SUBSCRIPT(output_type);
@@ -991,7 +992,8 @@ VariableNode::writeOutput(ostream &output, ExprNodeOutputType output_type,
       break;
 
     case SymbolType::endogenous:
-      switch (output_type)
+      switch (int tsid = datatree.symbol_table.getTypeSpecificID(symb_id);
+              output_type)
         {
         case ExprNodeOutputType::juliaDynamicModel:
         case ExprNodeOutputType::matlabDynamicModel:
@@ -1038,7 +1040,7 @@ VariableNode::writeOutput(ostream &output, ExprNodeOutputType output_type,
       break;
 
     case SymbolType::exogenous:
-      i = tsid + ARRAY_SUBSCRIPT_OFFSET(output_type);
+      i = datatree.symbol_table.getTypeSpecificID(symb_id) + ARRAY_SUBSCRIPT_OFFSET(output_type);
       switch (output_type)
         {
         case ExprNodeOutputType::juliaDynamicModel:
@@ -1096,7 +1098,7 @@ VariableNode::writeOutput(ostream &output, ExprNodeOutputType output_type,
       break;
 
     case SymbolType::exogenousDet:
-      i = tsid + datatree.symbol_table.exo_nbr() + ARRAY_SUBSCRIPT_OFFSET(output_type);
+      i = datatree.symbol_table.getTypeSpecificID(symb_id) + datatree.symbol_table.exo_nbr() + ARRAY_SUBSCRIPT_OFFSET(output_type);
       switch (output_type)
         {
         case ExprNodeOutputType::juliaDynamicModel:
@@ -1126,10 +1128,10 @@ VariableNode::writeOutput(ostream &output, ExprNodeOutputType output_type,
           break;
         case ExprNodeOutputType::matlabOutsideModel:
           assert(lag == 0);
-          output <<  "oo_.exo_det_steady_state(" << tsid + 1 << ")";
+          output <<  "oo_.exo_det_steady_state(" << datatree.symbol_table.getTypeSpecificID(symb_id) + 1 << ")";
           break;
         case ExprNodeOutputType::matlabDynamicSteadyStateOperator:
-          output <<  "oo_.exo_det_steady_state(" << tsid + 1 << ")";
+          output <<  "oo_.exo_det_steady_state(" << datatree.symbol_table.getTypeSpecificID(symb_id) + 1 << ")";
           break;
         case ExprNodeOutputType::juliaSteadyStateFile:
         case ExprNodeOutputType::steadyStateFile:
diff --git a/src/SymbolTable.cc b/src/SymbolTable.cc
index 895a2849..936a253a 100644
--- a/src/SymbolTable.cc
+++ b/src/SymbolTable.cc
@@ -1,5 +1,5 @@
 /*
- * Copyright © 2003-2019 Dynare Team
+ * Copyright © 2003-2020 Dynare Team
  *
  * This file is part of Dynare.
  *
@@ -130,10 +130,9 @@ SymbolTable::freeze() noexcept(false)
           param_ids.push_back(i);
           break;
         default:
-          tsi = -1;
-          break;
+          continue;
         }
-      type_specific_ids.push_back(tsi);
+      type_specific_ids[i] = tsi;
     }
 }
 
diff --git a/src/SymbolTable.hh b/src/SymbolTable.hh
index 8c3eef32..80171cfb 100644
--- a/src/SymbolTable.hh
+++ b/src/SymbolTable.hh
@@ -1,5 +1,5 @@
 /*
- * Copyright © 2003-2019 Dynare Team
+ * Copyright © 2003-2020 Dynare Team
  *
  * This file is part of Dynare.
  *
@@ -151,7 +151,7 @@ private:
   vector<SymbolType> type_table;
 
   //! Maps symbol IDs to type specific IDs
-  vector<int> type_specific_ids;
+  map<int, int> type_specific_ids;
 
   //! Maps type specific IDs of endogenous to symbol IDs
   vector<int> endo_ids;
@@ -204,6 +204,16 @@ public:
     {
     }
   };
+  /* Thrown when requesting the type specific ID of a symbol which doesn’t
+     have one */
+  class NoTypeSpecificIDException
+  {
+  public:
+    const int symb_id;
+    explicit NoTypeSpecificIDException(int symb_id_arg) : symb_id{symb_id_arg}
+    {
+    }
+  };
   //! Thrown when trying to declare a symbol twice
   class AlreadyDeclaredException
   {
@@ -496,7 +506,11 @@ SymbolTable::getTypeSpecificID(int id) const noexcept(false)
 
   validateSymbID(id);
 
-  return type_specific_ids[id];
+  if (auto it = type_specific_ids.find(id);
+      it != type_specific_ids.end())
+    return it->second;
+  else
+    throw NoTypeSpecificIDException(id);
 }
 
 inline int
-- 
GitLab