// See the file "COPYING" in the main distribution directory for copyright. #include "pac_analyzer.h" #include "pac_action.h" #include "pac_context.h" #include "pac_embedded.h" #include "pac_exception.h" #include "pac_expr.h" #include "pac_flow.h" #include "pac_func.h" #include "pac_output.h" #include "pac_param.h" #include "pac_paramtype.h" #include "pac_state.h" #include "pac_type.h" AnalyzerDecl::AnalyzerDecl(ID* id, DeclType decl_type, ParamList* params) : TypeDecl(id, params, new DummyType()) { decl_type_ = decl_type; statevars_ = new StateVarList(); actions_ = new AnalyzerActionList(); helpers_ = new AnalyzerHelperList(); functions_ = new FunctionList(); constructor_helpers_ = new AnalyzerHelperList(); destructor_helpers_ = new AnalyzerHelperList(); eof_helpers_ = new AnalyzerHelperList(); SetAnalyzerContext(); env_ = nullptr; } AnalyzerDecl::~AnalyzerDecl() { delete_list(statevars_); delete_list(actions_); delete_list(helpers_); delete_list(functions_); delete_list(params_); delete_list(constructor_helpers_); delete_list(destructor_helpers_); delete_list(eof_helpers_); } void AnalyzerDecl::AddElements(AnalyzerElementList* elemlist) { ASSERT(! env_); foreach (i, AnalyzerElementList, elemlist) { AnalyzerElement* elem = *i; switch ( elem->type() ) { case AnalyzerElement::STATE: { ASSERT(0); AnalyzerState* state_elem = (AnalyzerState*)elem; statevars_->insert(statevars_->end(), state_elem->statevars()->begin(), state_elem->statevars()->end()); } break; case AnalyzerElement::ACTION: { ASSERT(0); AnalyzerAction* action_elem = (AnalyzerAction*)elem; actions_->push_back(action_elem); } break; case AnalyzerElement::HELPER: { AnalyzerHelper* helper_elem = (AnalyzerHelper*)elem; switch ( helper_elem->helper_type() ) { case AnalyzerHelper::INIT_CODE: constructor_helpers_->push_back(helper_elem); break; case AnalyzerHelper::CLEANUP_CODE: destructor_helpers_->push_back(helper_elem); break; case AnalyzerHelper::EOF_CODE: eof_helpers_->push_back(helper_elem); break; default: helpers_->push_back(helper_elem); } } break; case AnalyzerElement::FUNCTION: { AnalyzerFunction* func_elem = (AnalyzerFunction*)elem; Function* func = func_elem->function(); func->set_analyzer_decl(this); functions_->push_back(func); } break; case AnalyzerElement::FLOW: { AnalyzerFlow* flow_elem = (AnalyzerFlow*)elem; ProcessFlowElement(flow_elem); } break; case AnalyzerElement::DATAUNIT: { AnalyzerDataUnit* dataunit_elem = (AnalyzerDataUnit*)elem; ProcessDataUnitElement(dataunit_elem); } break; } } } string AnalyzerDecl::class_name() const { return id_->Name(); } void AnalyzerDecl::Prepare() { TypeDecl::Prepare(); ASSERT(statevars_->empty()); ASSERT(actions_->empty()); foreach (i, FunctionList, functions_) { Function* function = *i; function->Prepare(env_); } foreach (i, StateVarList, statevars_) { StateVar* statevar = *i; env_->AddID(statevar->id(), STATE_VAR, statevar->type()); } foreach (i, AnalyzerActionList, actions_) { AnalyzerAction* action = *i; action->InstallHook(this); } } void AnalyzerDecl::GenForwardDeclaration(Output* out_h) { out_h->println("class %s;", class_name().c_str()); foreach (i, FunctionList, functions_) { Function* function = *i; function->GenForwardDeclaration(out_h); } } void AnalyzerDecl::GenActions(Output* out_h, Output* out_cc) { foreach (i, AnalyzerActionList, actions_) { (*i)->GenCode(out_h, out_cc, this); } } void AnalyzerDecl::GenHelpers(Output* out_h, Output* out_cc) { foreach (i, AnalyzerHelperList, helpers_) { (*i)->GenCode(out_h, out_cc, this); } } void AnalyzerDecl::GenPubDecls(Output* out_h, Output* out_cc) { TypeDecl::GenPubDecls(out_h, out_cc); GenProcessFunc(out_h, out_cc); GenGapFunc(out_h, out_cc); GenEOFFunc(out_h, out_cc); out_h->println(""); if ( ! functions_->empty() ) { out_h->println("// Functions"); GenFunctions(out_h, out_cc); out_h->println(""); } // TODO: export public state variables } void AnalyzerDecl::GenPrivDecls(Output* out_h, Output* out_cc) { TypeDecl::GenPrivDecls(out_h, out_cc); if ( ! helpers_->empty() ) { out_h->println(""); out_h->println("// Additional members"); GenHelpers(out_h, out_cc); } // TODO: declare state variables } void AnalyzerDecl::GenInitCode(Output* out_cc) { TypeDecl::GenInitCode(out_cc); foreach (i, AnalyzerHelperList, constructor_helpers_) { (*i)->GenCode(nullptr, out_cc, this); } } void AnalyzerDecl::GenCleanUpCode(Output* out_cc) { TypeDecl::GenCleanUpCode(out_cc); foreach (i, AnalyzerHelperList, destructor_helpers_) { (*i)->GenCode(nullptr, out_cc, this); } } void AnalyzerDecl::GenStateVarDecls(Output* out_h) { foreach (i, StateVarList, statevars_) { StateVar* var = *i; var->GenDecl(out_h, env_); } } void AnalyzerDecl::GenStateVarSetFunctions(Output* out_h) { foreach (i, StateVarList, statevars_) { StateVar* var = *i; var->GenSetFunction(out_h, env_); } } void AnalyzerDecl::GenStateVarInitCode(Output* out_cc) { foreach (i, StateVarList, statevars_) { StateVar* var = *i; var->GenInitCode(out_cc, env_); } } void AnalyzerDecl::GenStateVarCleanUpCode(Output* out_cc) { foreach (i, StateVarList, statevars_) { StateVar* var = *i; var->GenCleanUpCode(out_cc, env_); } } void AnalyzerDecl::GenFunctions(Output* out_h, Output* out_cc) { foreach (i, FunctionList, functions_) { Function* function = *i; function->GenCode(out_h, out_cc); } } AnalyzerState::~AnalyzerState() { // Note: do not delete elements of statevars_, because they // are referenced by the AnalyzerDecl. delete statevars_; } AnalyzerHelper::~AnalyzerHelper() { delete code_; } void AnalyzerHelper::GenCode(Output* out_h, Output* out_cc, AnalyzerDecl* decl) { Output* out = nullptr; switch ( helper_type_ ) { case MEMBER_DECLS: out = out_h; break; case INIT_CODE: case CLEANUP_CODE: case EOF_CODE: out = out_cc; break; } ASSERT(out); code()->GenCode(out, decl->env()); } FlowField::FlowField(ID* flow_id, ParameterizedType* flow_type) : Field(FLOW_FIELD, TYPE_NOT_TO_BE_PARSED | CLASS_MEMBER | PUBLIC_READABLE, flow_id, flow_type) {} void FlowField::GenInitCode(Output* out_cc, Env* env) { type_->GenPreParsing(out_cc, env); } AnalyzerFlow::AnalyzerFlow(Direction dir, ID* type_id, ExprList* params) : AnalyzerElement(FLOW), dir_(dir), type_id_(type_id) { if ( ! params ) params = new ExprList(); // Add "this" to the list of params params->insert(params->begin(), new Expr(this_id->clone())); ID* flow_id = ((dir == UP) ? upflow_id : downflow_id)->clone(); ParameterizedType* flow_type = new ParameterizedType(type_id_, params); flow_field_ = new FlowField(flow_id, flow_type); flow_decl_ = nullptr; } AnalyzerFlow::~AnalyzerFlow() { delete flow_field_; } FlowDecl* AnalyzerFlow::flow_decl() { DEBUG_MSG("Getting flow_decl for %s\n", type_id_->Name()); if ( ! flow_decl_ ) { Decl* decl = Decl::LookUpDecl(type_id_); if ( decl && decl->decl_type() == Decl::FLOW ) flow_decl_ = static_cast(decl); if ( ! flow_decl_ ) { throw Exception(this, "cannot find the flow declaration"); } } return flow_decl_; }