write AST in JSON

issue#70
Houtan Bastani 2018-09-18 14:50:31 +02:00
parent 8ec06dddc4
commit c9f5cef99b
4 changed files with 367 additions and 0 deletions

View File

@ -6057,6 +6057,46 @@ DynamicModel::writeJsonOutput(ostream &output) const
writeJsonModelEquations(output, false);
output << ", ";
writeJsonXrefs(output);
output << ", ";
writeJsonAST(output);
}
void
DynamicModel::writeJsonAST(ostream &output) const
{
vector<pair<string, string>> eqtags;
output << "\"Abstract Syntax Tree\":[" << endl;
for (int eq = 0; eq < (int) equations.size(); eq++)
{
if (eq != 0)
output << ", ";
output << "{ \"number\":" << eq
<< ", \"line\":" << equations_lineno[eq];
for (const auto & equation_tag : equation_tags)
if (equation_tag.first == eq)
eqtags.push_back(equation_tag.second);
if (!eqtags.empty())
{
output << ", \"tags\": {";
int i = 0;
for (vector<pair<string, string>>::const_iterator it = eqtags.begin(); it != eqtags.end(); it++, i++)
{
if (i != 0)
output << ", ";
output << "\"" << it->first << "\": \"" << it->second << "\"";
}
output << "}";
eqtags.clear();
}
output << ", \"AST\": ";
equations[eq]->writeJsonAST(output);
output << "}";
}
output << "]";
}
void
@ -6103,6 +6143,8 @@ void
DynamicModel::writeJsonOriginalModelOutput(ostream &output) const
{
writeJsonModelEquations(output, false);
output << ", ";
writeJsonAST(output);
}
void

View File

@ -284,6 +284,9 @@ public:
//! Writes model initialization and lead/lag incidence matrix to output
void writeOutput(ostream &output, const string &basename, bool block, bool byte_code, bool use_dll, int order, bool estimation_present, bool compute_xrefs, bool julia) const;
//! Write JSON AST
void writeJsonAST(ostream &output) const;
//! Write JSON Output
void writeJsonOutput(ostream &output) const;

View File

@ -359,6 +359,12 @@ NumConstNode::writeOutput(ostream &output, ExprNodeOutputType output_type,
output << datatree.num_constants.get(id);
}
void
NumConstNode::writeJsonAST(ostream &output) const
{
output << "{\"node_type\" : \"NumConstNode\", \"value\" : " << datatree.num_constants.get(id) << "}";
}
void
NumConstNode::writeJsonOutput(ostream &output,
const temporary_terms_t &temporary_terms,
@ -810,6 +816,62 @@ VariableNode::containsExternalFunction() const
return false;
}
void
VariableNode::writeJsonAST(ostream &output) const
{
output << "{\"node_type\" : \"VariableNode\", "
<< "\"name\" : \"" << datatree.symbol_table.getName(symb_id) << "\", \"type\" : \"";
switch (type)
{
case SymbolType::endogenous:
output << "endogenous";
break;
case SymbolType::exogenous:
output << "exogenous";
break;
case SymbolType::exogenousDet:
output << "exogenousDet";
break;
case SymbolType::parameter:
output << "parameter";
break;
case SymbolType::modelLocalVariable:
output << "modelLocalVariable";
break;
case SymbolType::modFileLocalVariable:
output << "modFileLocalVariable";
break;
case SymbolType::externalFunction:
output << "externalFunction";
break;
case SymbolType::trend:
output << "trend";
break;
case SymbolType::statementDeclaredVariable:
output << "statementDeclaredVariable";
break;
case SymbolType::logTrend:
output << "logTrend:";
break;
case SymbolType::unusedEndogenous:
output << "unusedEndogenous";
break;
case SymbolType::endogenousVAR:
output << "endogenousVAR";
break;
case SymbolType::endogenousEpilogue:
output << "endogenousEpilogue";
break;
case SymbolType::exogenousEpilogue:
output << "exogenousEpilogue";
break;
case SymbolType::parameterEpilogue:
output << "parameterEpilogue";
break;
}
output << "\", \"lag\" : " << lag << "}";
}
void
VariableNode::writeJsonOutput(ostream &output,
const temporary_terms_t &temporary_terms,
@ -2311,6 +2373,111 @@ UnaryOpNode::containsExternalFunction() const
return arg->containsExternalFunction();
}
void
UnaryOpNode::writeJsonAST(ostream &output) const
{
output << "{\"node_type\" : \"UnaryOpNode\", \"op\" : \"";
switch (op_code)
{
case UnaryOpcode::uminus:
output << "uminus";
break;
case UnaryOpcode::exp:
output << "exp";
break;
case UnaryOpcode::log:
output << "log";
break;
case UnaryOpcode::log10:
output << "log10";
break;
case UnaryOpcode::cos:
output << "cos";
break;
case UnaryOpcode::sin:
output << "sin";
break;
case UnaryOpcode::tan:
output << "tan";
break;
case UnaryOpcode::acos:
output << "acos";
break;
case UnaryOpcode::asin:
output << "asin";
break;
case UnaryOpcode::atan:
output << "atan";
break;
case UnaryOpcode::cosh:
output << "cosh";
break;
case UnaryOpcode::sinh:
output << "sinh";
break;
case UnaryOpcode::tanh:
output << "tanh";
break;
case UnaryOpcode::acosh:
output << "acosh";
break;
case UnaryOpcode::asinh:
output << "asinh";
break;
case UnaryOpcode::atanh:
output << "atanh";
break;
case UnaryOpcode::sqrt:
output << "sqrt";
break;
case UnaryOpcode::abs:
output << "abs";
break;
case UnaryOpcode::sign:
output << "sign";
break;
case UnaryOpcode::diff:
output << "diff";
break;
case UnaryOpcode::adl:
output << "adl";
break;
case UnaryOpcode::steadyState:
output << "steady_state";
case UnaryOpcode::steadyStateParamDeriv:
output << "steady_state_param_deriv";
break;
case UnaryOpcode::steadyStateParam2ndDeriv:
output << "steady_state_param_second_deriv";
break;
case UnaryOpcode::expectation:
output << "expectation";
break;
case UnaryOpcode::erf:
output << "erf";
break;
}
output << "\", \"arg\" : ";
arg->writeJsonAST(output);
switch (op_code)
{
case UnaryOpcode::adl:
output << ", \"adl_param_name\" : \"" << adl_param_name << "\""
<< ", \"lags\" : [";
for (auto it = adl_lags.begin(); it != adl_lags.end(); it++)
{
if (it != adl_lags.begin())
output << ", ";
output << *it;
}
output << "]";
break;
default:
break;
}
output << "}";
}
void
UnaryOpNode::writeJsonOutput(ostream &output,
const temporary_terms_t &temporary_terms,
@ -4104,6 +4271,66 @@ BinaryOpNode::containsExternalFunction() const
|| arg2->containsExternalFunction();
}
void
BinaryOpNode::writeJsonAST(ostream &output) const
{
output << "{\"node_type\" : \"BinaryOpNode\","
<< " \"op\" : \"";
switch (op_code)
{
case BinaryOpcode::plus:
output << "+";
break;
case BinaryOpcode::minus:
output << "-";
break;
case BinaryOpcode::times:
output << "*";
break;
case BinaryOpcode::divide:
output << "/";
break;
case BinaryOpcode::power:
output << "^";
break;
case BinaryOpcode::less:
output << "<";
break;
case BinaryOpcode::greater:
output << ">";
break;
case BinaryOpcode::lessEqual:
output << "<=";
break;
case BinaryOpcode::greaterEqual:
output << ">=";
break;
case BinaryOpcode::equalEqual:
output << "==";
break;
case BinaryOpcode::different:
output << "!=";
break;
case BinaryOpcode::equal:
output << "=";
break;
case BinaryOpcode::max:
output << "max";
break;
case BinaryOpcode::min:
output << "min";
break;
case BinaryOpcode::powerDeriv:
output << "power_deriv";
break;
}
output << "\", \"arg1\" : ";
arg1->writeJsonAST(output);
output << ", \"arg2\" : ";
arg2->writeJsonAST(output);
output << "}";
}
void
BinaryOpNode::writeJsonOutput(ostream &output,
const temporary_terms_t &temporary_terms,
@ -5951,6 +6178,29 @@ TrinaryOpNode::containsExternalFunction() const
|| arg3->containsExternalFunction();
}
void
TrinaryOpNode::writeJsonAST(ostream &output) const
{
output << "{\"node_type\" : \"TrinaryOpNode\", "
<< "\"op\" : \"";
switch (op_code)
{
case TrinaryOpcode::normcdf:
output << "normcdf";
break;
case TrinaryOpcode::normpdf:
output << "normpdf";
break;
}
output << "\", \"arg1\" : ";
arg1->writeJsonAST(output);
output << ", \"arg2\" : ";
arg2->writeJsonAST(output);
output << ", \"arg2\" : ";
arg3->writeJsonAST(output);
output << "}";
}
void
TrinaryOpNode::writeJsonOutput(ostream &output,
const temporary_terms_t &temporary_terms,
@ -7109,6 +7359,22 @@ AbstractExternalFunctionNode::writeExternalFunctionArguments(ostream &output, Ex
}
}
void
AbstractExternalFunctionNode::writeJsonASTExternalFunctionArguments(ostream &output) const
{
int i = 0;
output << "{";
for (auto it = arguments.begin(); it != arguments.end(); it++, i++)
{
if (it != arguments.begin())
output << ",";
output << "\"arg" << i << "\" : ";
(*it)->writeJsonAST(output);
}
output << "}";
}
void
AbstractExternalFunctionNode::writeJsonExternalFunctionArguments(ostream &output,
const temporary_terms_t &temporary_terms,
@ -7292,6 +7558,15 @@ ExternalFunctionNode::compileExternalFunctionOutput(ostream &CompileCode, unsign
}
}
void
ExternalFunctionNode::writeJsonAST(ostream &output) const
{
output << "{\"node_type\" : \"ExternalFunctionNode\", "
<< "\"name\" : \"" << datatree.symbol_table.getName(symb_id) << "\", \"args\" : [";
writeJsonASTExternalFunctionArguments(output);
output << "]}";
}
void
ExternalFunctionNode::writeJsonOutput(ostream &output,
const temporary_terms_t &temporary_terms,
@ -7527,6 +7802,15 @@ FirstDerivExternalFunctionNode::composeDerivatives(const vector<expr_t> &dargs)
return theDeriv;
}
void
FirstDerivExternalFunctionNode::writeJsonAST(ostream &output) const
{
output << "{\"node_type\" : \"FirstDerivExternalFunctionNode\", "
<< "\"name\" : \"" << datatree.symbol_table.getName(symb_id) << "\", \"args\" : [";
writeJsonASTExternalFunctionArguments(output);
output << "]}";
}
void
FirstDerivExternalFunctionNode::writeJsonOutput(ostream &output,
const temporary_terms_t &temporary_terms,
@ -7907,6 +8191,15 @@ SecondDerivExternalFunctionNode::composeDerivatives(const vector<expr_t> &dargs)
exit(EXIT_FAILURE);
}
void
SecondDerivExternalFunctionNode::writeJsonAST(ostream &output) const
{
output << "{\"node_type\" : \"SecondDerivExternalFunctionNode\", "
<< "\"name\" : \"" << datatree.symbol_table.getName(symb_id) << "\", \"args\" : [";
writeJsonASTExternalFunctionArguments(output);
output << "]}";
}
void
SecondDerivExternalFunctionNode::writeJsonOutput(ostream &output,
const temporary_terms_t &temporary_terms,
@ -8657,6 +8950,13 @@ VarExpectationNode::fillErrorCorrectionRow(int eqn, const vector<int> &nontrend_
exit(EXIT_FAILURE);
}
void
VarExpectationNode::writeJsonAST(ostream &output) const
{
output << "{\"node_type\" : \"VarExpectationNode\", "
<< "\"name\" : \"" << model_name << "\"}";
}
void
VarExpectationNode::writeJsonOutput(ostream &output,
const temporary_terms_t &temporary_terms,
@ -9151,6 +9451,13 @@ PacExpectationNode::fillErrorCorrectionRow(int eqn, const vector<int> &nontrend_
exit(EXIT_FAILURE);
}
void
PacExpectationNode::writeJsonAST(ostream &output) const
{
output << "{\"node_type\" : \"PacExpectationNode\", "
<< "\"name\" : \"" << model_name << "\"}";
}
void
PacExpectationNode::writeJsonOutput(ostream &output,
const temporary_terms_t &temporary_terms,

View File

@ -262,6 +262,9 @@ class ExprNode
//! Writes output of node in JSON syntax
virtual void writeJsonOutput(ostream &output, const temporary_terms_t &temporary_terms, const deriv_node_temp_terms_t &tef_terms, const bool isdynamic = true) const = 0;
//! Writes the Abstract Syntax Tree in JSON
virtual void writeJsonAST(ostream &output) const = 0;
virtual int precedenceJson(const temporary_terms_t &temporary_terms) const;
//! Writes the output for an external function, ensuring that the external function is called as few times as possible using temporary terms
@ -612,6 +615,7 @@ public:
};
void prepareForDerivation() override;
void writeOutput(ostream &output, ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms, const temporary_terms_idxs_t &temporary_terms_idxs, const deriv_node_temp_terms_t &tef_terms) const override;
void writeJsonAST(ostream &output) const override;
void writeJsonOutput(ostream &output, const temporary_terms_t &temporary_terms, const deriv_node_temp_terms_t &tef_terms, const bool isdynamic) const override;
bool containsExternalFunction() const override;
void collectVARLHSVariable(set<expr_t> &result) const override;
@ -692,6 +696,7 @@ public:
VariableNode(DataTree &datatree_arg, int idx_arg, int symb_id_arg, int lag_arg);
void prepareForDerivation() override;
void writeOutput(ostream &output, ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms, const temporary_terms_idxs_t &temporary_terms_idxs, const deriv_node_temp_terms_t &tef_terms) const override;
void writeJsonAST(ostream &output) const override;
void writeJsonOutput(ostream &output, const temporary_terms_t &temporary_terms, const deriv_node_temp_terms_t &tef_terms, const bool isdynamic) const override;
bool containsExternalFunction() const override;
void collectVARLHSVariable(set<expr_t> &result) const override;
@ -804,6 +809,7 @@ public:
map<NodeTreeReference, temporary_terms_t> &temp_terms_map,
bool is_matlab, NodeTreeReference tr) const override;
void writeOutput(ostream &output, ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms, const temporary_terms_idxs_t &temporary_terms_idxs, const deriv_node_temp_terms_t &tef_terms) const override;
void writeJsonAST(ostream &output) const override;
void writeJsonOutput(ostream &output, const temporary_terms_t &temporary_terms, const deriv_node_temp_terms_t &tef_terms, const bool isdynamic) const override;
bool containsExternalFunction() const override;
void writeExternalFunctionOutput(ostream &output, ExprNodeOutputType output_type,
@ -928,6 +934,7 @@ public:
map<NodeTreeReference, temporary_terms_t> &temp_terms_map,
bool is_matlab, NodeTreeReference tr) const override;
void writeOutput(ostream &output, ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms, const temporary_terms_idxs_t &temporary_terms_idxs, const deriv_node_temp_terms_t &tef_terms) const override;
void writeJsonAST(ostream &output) const override;
void writeJsonOutput(ostream &output, const temporary_terms_t &temporary_terms, const deriv_node_temp_terms_t &tef_terms, const bool isdynamic) const override;
bool containsExternalFunction() const override;
void writeExternalFunctionOutput(ostream &output, ExprNodeOutputType output_type,
@ -1084,6 +1091,7 @@ public:
map<NodeTreeReference, temporary_terms_t> &temp_terms_map,
bool is_matlab, NodeTreeReference tr) const override;
void writeOutput(ostream &output, ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms, const temporary_terms_idxs_t &temporary_terms_idxs, const deriv_node_temp_terms_t &tef_terms) const override;
void writeJsonAST(ostream &output) const override;
void writeJsonOutput(ostream &output, const temporary_terms_t &temporary_terms, const deriv_node_temp_terms_t &tef_terms, const bool isdynamic) const override;
bool containsExternalFunction() const override;
void writeExternalFunctionOutput(ostream &output, ExprNodeOutputType output_type,
@ -1190,6 +1198,7 @@ protected:
int getIndxInTefTerms(int the_symb_id, const deriv_node_temp_terms_t &tef_terms) const noexcept(false);
//! Helper function to write output arguments of any given external function
void writeExternalFunctionArguments(ostream &output, ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms, const temporary_terms_idxs_t &temporary_terms_idxs, const deriv_node_temp_terms_t &tef_terms) const;
void writeJsonASTExternalFunctionArguments(ostream &output) const;
void writeJsonExternalFunctionArguments(ostream &output, const temporary_terms_t &temporary_terms, const deriv_node_temp_terms_t &tef_terms, const bool isdynamic) const;
/*! Returns a predicate that tests whether an other ExprNode is an external
function which is computed by the same external function call (i.e. it has
@ -1203,6 +1212,7 @@ public:
map<NodeTreeReference, temporary_terms_t> &temp_terms_map,
bool is_matlab, NodeTreeReference tr) const override;
void writeOutput(ostream &output, ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms, const temporary_terms_idxs_t &temporary_terms_idxs, const deriv_node_temp_terms_t &tef_terms) const override = 0;
void writeJsonAST(ostream &output) const override = 0;
void writeJsonOutput(ostream &output, const temporary_terms_t &temporary_terms, const deriv_node_temp_terms_t &tef_terms, const bool isdynamic = true) const override = 0;
bool containsExternalFunction() const override;
void writeExternalFunctionOutput(ostream &output, ExprNodeOutputType output_type,
@ -1306,6 +1316,7 @@ public:
ExternalFunctionNode(DataTree &datatree_arg, int idx_arg, int symb_id_arg,
const vector<expr_t> &arguments_arg);
void writeOutput(ostream &output, ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms, const temporary_terms_idxs_t &temporary_terms_idxs, const deriv_node_temp_terms_t &tef_terms) const override;
void writeJsonAST(ostream &output) const override;
void writeJsonOutput(ostream &output, const temporary_terms_t &temporary_terms, const deriv_node_temp_terms_t &tef_terms, const bool isdynamic) const override;
void writeExternalFunctionOutput(ostream &output, ExprNodeOutputType output_type,
const temporary_terms_t &temporary_terms,
@ -1351,6 +1362,7 @@ public:
vector< vector<temporary_terms_t>> &v_temporary_terms,
int equation) const override;
void writeOutput(ostream &output, ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms, const temporary_terms_idxs_t &temporary_terms_idxs, const deriv_node_temp_terms_t &tef_terms) const override;
void writeJsonAST(ostream &output) const override;
void writeJsonOutput(ostream &output, const temporary_terms_t &temporary_terms, const deriv_node_temp_terms_t &tef_terms, const bool isdynamic) const override;
void compile(ostream &CompileCode, unsigned int &instruction_number,
bool lhs_rhs, const temporary_terms_t &temporary_terms,
@ -1395,6 +1407,7 @@ public:
vector< vector<temporary_terms_t>> &v_temporary_terms,
int equation) const override;
void writeOutput(ostream &output, ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms, const temporary_terms_idxs_t &temporary_terms_idxs, const deriv_node_temp_terms_t &tef_terms) const override;
void writeJsonAST(ostream &output) const override;
void writeJsonOutput(ostream &output, const temporary_terms_t &temporary_terms, const deriv_node_temp_terms_t &tef_terms, const bool isdynamic) const override;
void compile(ostream &CompileCode, unsigned int &instruction_number,
bool lhs_rhs, const temporary_terms_t &temporary_terms,
@ -1501,6 +1514,7 @@ public:
bool isVarModelReferenced(const string &model_info_name) const override;
void getEndosAndMaxLags(map<string, int> &model_endos_and_lags) const override;
expr_t substituteStaticAuxiliaryVariable() const override;
void writeJsonAST(ostream &output) const override;
void writeJsonOutput(ostream &output, const temporary_terms_t &temporary_terms, const deriv_node_temp_terms_t &tef_terms, const bool isdynamic) const override;
};
@ -1599,6 +1613,7 @@ public:
bool isVarModelReferenced(const string &model_info_name) const override;
void getEndosAndMaxLags(map<string, int> &model_endos_and_lags) const override;
expr_t substituteStaticAuxiliaryVariable() const override;
void writeJsonAST(ostream &output) const override;
void writeJsonOutput(ostream &output, const temporary_terms_t &temporary_terms, const deriv_node_temp_terms_t &tef_terms, const bool isdynamic) const override;
};