From e1fbb2c5cd7b513e95f23318f5eb14c0d1ce4f96 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?S=C3=A9bastien=20Villemot?= <sebastien@dynare.org>
Date: Tue, 27 Aug 2013 10:38:54 +0200
Subject: [PATCH] Move check on variables types within 'shocks' block to the
 checking pass stage

Closes #448
---
 preprocessor/ParsingDriver.cc | 20 ---------
 preprocessor/Shocks.cc        | 77 ++++++++++++++++++++++++++++++-----
 2 files changed, 66 insertions(+), 31 deletions(-)

diff --git a/preprocessor/ParsingDriver.cc b/preprocessor/ParsingDriver.cc
index 39c2402381..ffc60a4bc2 100644
--- a/preprocessor/ParsingDriver.cc
+++ b/preprocessor/ParsingDriver.cc
@@ -644,10 +644,6 @@ ParsingDriver::add_stderr_shock(string *var, expr_t value)
   check_symbol_existence(*var);
   int symb_id = mod_file->symbol_table.getID(*var);
 
-  SymbolType type = mod_file->symbol_table.getType(symb_id);
-  if (type != eExogenous && !mod_file->symbol_table.isObservedVariable(symb_id))
-    error("shocks: standard error can only be specified for exogenous or observed endogenous variables");
-
   if (var_shocks.find(symb_id) != var_shocks.end()
       || std_shocks.find(symb_id) != std_shocks.end())
     error("shocks: variance or stderr of shock on " + *var + " declared twice");
@@ -663,10 +659,6 @@ ParsingDriver::add_var_shock(string *var, expr_t value)
   check_symbol_existence(*var);
   int symb_id = mod_file->symbol_table.getID(*var);
 
-  SymbolType type = mod_file->symbol_table.getType(symb_id);
-  if (type != eExogenous && !mod_file->symbol_table.isObservedVariable(symb_id))
-    error("shocks: variance can only be specified for exogenous or observed endogenous variables");
-
   if (var_shocks.find(symb_id) != var_shocks.end()
       || std_shocks.find(symb_id) != std_shocks.end())
     error("shocks: variance or stderr of shock on " + *var + " declared twice");
@@ -684,12 +676,6 @@ ParsingDriver::add_covar_shock(string *var1, string *var2, expr_t value)
   int symb_id1 = mod_file->symbol_table.getID(*var1);
   int symb_id2 = mod_file->symbol_table.getID(*var2);
 
-  SymbolType type1 = mod_file->symbol_table.getType(symb_id1);
-  SymbolType type2 = mod_file->symbol_table.getType(symb_id2);
-  if (!((type1 == eExogenous && type2 == eExogenous)
-        || (mod_file->symbol_table.isObservedVariable(symb_id1) && mod_file->symbol_table.isObservedVariable(symb_id2))))
-    error("shocks: covariance can only be specified for exogenous or observed endogenous variables of same type");
-
   pair<int, int> key(symb_id1, symb_id2), key_inv(symb_id2, symb_id1);
 
   if (covar_shocks.find(key) != covar_shocks.end()
@@ -713,12 +699,6 @@ ParsingDriver::add_correl_shock(string *var1, string *var2, expr_t value)
   int symb_id1 = mod_file->symbol_table.getID(*var1);
   int symb_id2 = mod_file->symbol_table.getID(*var2);
 
-  SymbolType type1 = mod_file->symbol_table.getType(symb_id1);
-  SymbolType type2 = mod_file->symbol_table.getType(symb_id2);
-  if (!((type1 == eExogenous && type2 == eExogenous)
-        || (mod_file->symbol_table.isObservedVariable(symb_id1) && mod_file->symbol_table.isObservedVariable(symb_id2))))
-    error("shocks: correlation can only be specified for exogenous or observed endogenous variables of same type");
-
   pair<int, int> key(symb_id1, symb_id2), key_inv(symb_id2, symb_id1);
 
   if (covar_shocks.find(key) != covar_shocks.end()
diff --git a/preprocessor/Shocks.cc b/preprocessor/Shocks.cc
index 31fcdd173c..ab5b36df46 100644
--- a/preprocessor/Shocks.cc
+++ b/preprocessor/Shocks.cc
@@ -198,28 +198,83 @@ ShocksStatement::checkPass(ModFileStructure &mod_file_struct, WarningConsolidati
   // Workaround for trac ticket #35
   mod_file_struct.shocks_present_but_simul_not_yet = true;
 
-  // Determine if there is a calibrated measurement error
+  /* Error out if variables are not of the right type. This must be done here
+     and not at parsing time (see #448).
+     Also Determine if there is a calibrated measurement error */
   for (var_and_std_shocks_t::const_iterator it = var_shocks.begin();
        it != var_shocks.end(); it++)
-    if (symbol_table.isObservedVariable(it->first))
-      mod_file_struct.calibrated_measurement_errors = true;
+    {
+      if (symbol_table.getType(it->first) != eExogenous
+          && !symbol_table.isObservedVariable(it->first))
+        {
+          cerr << "shocks: setting a variance on '"
+               << symbol_table.getName(it->first) << "' is not allowed, because it is neither an exogenous variable nor an observed endogenous variable" << endl;
+          exit(EXIT_FAILURE);
+        }
+    
+      if (symbol_table.isObservedVariable(it->first))
+        mod_file_struct.calibrated_measurement_errors = true;
+    }
+  
 
   for (var_and_std_shocks_t::const_iterator it = std_shocks.begin();
        it != std_shocks.end(); it++)
-    if (symbol_table.isObservedVariable(it->first))
-      mod_file_struct.calibrated_measurement_errors = true;
+    {
+      if (symbol_table.getType(it->first) != eExogenous
+          && !symbol_table.isObservedVariable(it->first))
+        {
+          cerr << "shocks: setting a standard error on '"
+               << symbol_table.getName(it->first) << "' is not allowed, because it is neither an exogenous variable nor an observed endogenous variable" << endl;
+          exit(EXIT_FAILURE);
+        }
+
+      if (symbol_table.isObservedVariable(it->first))
+        mod_file_struct.calibrated_measurement_errors = true;
+    }
 
   for (covar_and_corr_shocks_t::const_iterator it = covar_shocks.begin();
        it != covar_shocks.end(); it++)
-    if (symbol_table.isObservedVariable(it->first.first)
-        || symbol_table.isObservedVariable(it->first.second))
-      mod_file_struct.calibrated_measurement_errors = true;
+    {
+      int symb_id1 = it->first.first;
+      int symb_id2 = it->first.second;
+      
+      if (!((symbol_table.getType(symb_id1) == eExogenous
+             && symbol_table.getType(symb_id2) == eExogenous)
+            || (symbol_table.isObservedVariable(symb_id1)
+                && symbol_table.isObservedVariable(symb_id2))))
+        {
+          cerr << "shocks: setting a covariance between '"
+               << symbol_table.getName(symb_id1) << "' and '"
+               << symbol_table.getName(symb_id2) << "'is not allowed; covariances can only be specified for exogenous or observed endogenous variables of same type" << endl;
+          exit(EXIT_FAILURE);
+        }
+      
+      if (symbol_table.isObservedVariable(symb_id1)
+          || symbol_table.isObservedVariable(symb_id2))
+        mod_file_struct.calibrated_measurement_errors = true;
+    }
 
   for (covar_and_corr_shocks_t::const_iterator it = corr_shocks.begin();
        it != corr_shocks.end(); it++)
-    if (symbol_table.isObservedVariable(it->first.first)
-        || symbol_table.isObservedVariable(it->first.second))
-      mod_file_struct.calibrated_measurement_errors = true;
+    {
+      int symb_id1 = it->first.first;
+      int symb_id2 = it->first.second;
+      
+      if (!((symbol_table.getType(symb_id1) == eExogenous
+             && symbol_table.getType(symb_id2) == eExogenous)
+            || (symbol_table.isObservedVariable(symb_id1)
+                && symbol_table.isObservedVariable(symb_id2))))
+        {
+          cerr << "shocks: setting a correlation between '"
+               << symbol_table.getName(symb_id1) << "' and '"
+               << symbol_table.getName(symb_id2) << "'is not allowed; correlations can only be specified for exogenous or observed endogenous variables of same type" << endl;
+          exit(EXIT_FAILURE);
+        }
+      
+      if (symbol_table.isObservedVariable(it->first.first)
+          || symbol_table.isObservedVariable(it->first.second))
+        mod_file_struct.calibrated_measurement_errors = true;
+    }
 }
 
 MShocksStatement::MShocksStatement(const det_shocks_t &det_shocks_arg,
-- 
GitLab