From c9f5cef99b27c7b3a728f8d200b3dee1bc482356 Mon Sep 17 00:00:00 2001 From: Houtan Bastani Date: Tue, 18 Sep 2018 14:50:31 +0200 Subject: [PATCH] write AST in JSON --- src/DynamicModel.cc | 42 ++++++ src/DynamicModel.hh | 3 + src/ExprNode.cc | 307 ++++++++++++++++++++++++++++++++++++++++++++ src/ExprNode.hh | 15 +++ 4 files changed, 367 insertions(+) diff --git a/src/DynamicModel.cc b/src/DynamicModel.cc index 41892256..127ab721 100644 --- a/src/DynamicModel.cc +++ b/src/DynamicModel.cc @@ -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> 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>::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 diff --git a/src/DynamicModel.hh b/src/DynamicModel.hh index d6e4bc01..2ec940ab 100644 --- a/src/DynamicModel.hh +++ b/src/DynamicModel.hh @@ -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; diff --git a/src/ExprNode.cc b/src/ExprNode.cc index f9e8a10e..d26f2ff1 100644 --- a/src/ExprNode.cc +++ b/src/ExprNode.cc @@ -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 &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 &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 &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 &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, diff --git a/src/ExprNode.hh b/src/ExprNode.hh index 77106f23..1bd85c81 100644 --- a/src/ExprNode.hh +++ b/src/ExprNode.hh @@ -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 &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 &result) const override; @@ -804,6 +809,7 @@ public: map &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 &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 &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 &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 &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> &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> &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 &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 &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; };