bug fix: prevent vars with leads/lags from being used outside of the model block.

issue#70
Houtan Bastani 2010-03-15 10:47:44 +01:00
parent 673bf79a5e
commit 9d5e280b82
2 changed files with 21 additions and 15 deletions

View File

@ -416,7 +416,7 @@ expression : '(' expression ')'
| MIN '(' expression COMMA expression ')'
{ $$ = driver.add_min($3, $5); }
| symbol { driver.push_external_function_arg_vector_onto_stack(); } '(' comma_expression ')'
{ $$ = driver.add_model_var_or_external_function($1,false); }
{ $$ = driver.add_model_var_or_external_function($1, false); }
| NORMCDF '(' expression COMMA expression COMMA expression ')'
{ $$ = driver.add_normcdf($3, $5, $7); }
| NORMCDF '(' expression ')'
@ -572,7 +572,7 @@ hand_side : '(' hand_side ')'
| MIN '(' hand_side COMMA hand_side ')'
{ $$ = driver.add_min($3, $5); }
| symbol { driver.push_external_function_arg_vector_onto_stack(); } '(' comma_hand_side ')'
{ $$ = driver.add_model_var_or_external_function($1,true); }
{ $$ = driver.add_model_var_or_external_function($1, true); }
| NORMCDF '(' hand_side COMMA hand_side COMMA hand_side ')'
{ $$ = driver.add_normcdf($3, $5, $7); }
| NORMCDF '(' hand_side ')'

View File

@ -1723,9 +1723,19 @@ ParsingDriver::add_model_var_or_external_function(string *function_name, bool in
if (mod_file->symbol_table.exists(*function_name))
{
if (mod_file->symbol_table.getType(*function_name) != eExternalFunction)
{ // e.g. model_var(lag) => ADD MODEL VARIABLE WITH LEAD (NumConstNode)/LAG (UnaryOpNode)
if ((int)stack_external_function_args.top().size() == 1)
{
if (!in_model_block)
{
if ((int)stack_external_function_args.top().size() > 0)
error("A variable cannot take arguments.");
else
return add_expression_variable(function_name);
}
else
{ // e.g. model_var(lag) => ADD MODEL VARIABLE WITH LEAD (NumConstNode)/LAG (UnaryOpNode)
if ((int)stack_external_function_args.top().size() != 1)
error("A model variable is being treated as if it were a function (i.e., has received more than one argument).");
NumConstNode *numNode = dynamic_cast<NumConstNode *>(stack_external_function_args.top().front());
UnaryOpNode *unaryNode = dynamic_cast<UnaryOpNode *>(stack_external_function_args.top().front());
@ -1741,15 +1751,13 @@ ParsingDriver::add_model_var_or_external_function(string *function_name, bool in
model_var_arg_dbl = numNode->eval(ectmp);
}
else
{
if (unaryNode->get_op_code() != oUminus)
error("A model variable is being treated as if it were a function (i.e., takes an argument that is not an integer).");
else
{
model_var_arg = (int)unaryNode->eval(ectmp);
model_var_arg_dbl = unaryNode->eval(ectmp);
}
}
if (unaryNode->get_op_code() != oUminus)
error("A model variable is being treated as if it were a function (i.e., takes an argument that is not an integer).");
else
{
model_var_arg = (int)unaryNode->eval(ectmp);
model_var_arg_dbl = unaryNode->eval(ectmp);
}
if ((double) model_var_arg != model_var_arg_dbl) //make 100% sure int cast didn't lose info
error("A model variable is being treated as if it were a function (i.e., takes an argument that is not an integer).");
@ -1759,8 +1767,6 @@ ParsingDriver::add_model_var_or_external_function(string *function_name, bool in
delete function_name;
return nid;
}
else
error("A model variable is being treated as if it were a function (i.e., has received more than one argument).");
}
else
{ // e.g. this function has already been referenced (either ad hoc or through the external_function() statement