/*
 Copyright 2019 Alain Dargelas

 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
 You may obtain a copy of the License at

 http://www.apache.org/licenses/LICENSE-2.0

 Unless required by applicable law or agreed to in writing, software
 distributed under the License is distributed on an "AS IS" BASIS,
 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 See the License for the specific language governing permissions and
 limitations under the License.
 */

/*
 * File:   CompileModule.cpp
 * Author: alain
 *
 * Created on March 22, 2018, 9:43 PM
 */

#include "SourceCompile/VObjectTypes.h"
#include "Design/VObject.h"
#include "Library/Library.h"
#include "Design/Signal.h"
#include "Design/FileContent.h"
#include "Design/ClockingBlock.h"
#include "SourceCompile/SymbolTable.h"
#include "ErrorReporting/Error.h"
#include "ErrorReporting/Location.h"
#include "ErrorReporting/Error.h"
#include "CommandLine/CommandLineParser.h"
#include "ErrorReporting/ErrorDefinition.h"
#include "ErrorReporting/ErrorContainer.h"
#include "SourceCompile/CompilationUnit.h"
#include "SourceCompile/PreprocessFile.h"
#include "SourceCompile/CompileSourceFile.h"
#include "SourceCompile/ParseFile.h"
#include "SourceCompile/Compiler.h"
#include "Testbench/ClassDefinition.h"
#include "DesignCompile/CompileHelper.h"
#include "DesignCompile/CompileDesign.h"
#include "DesignCompile/CompileModule.h"

using namespace SURELOG;

CompileModule::~CompileModule() {}

int FunctorCompileModule::operator()() const {
  CompileModule* instance = new CompileModule(m_compileDesign, m_module,
                                              m_design, m_symbols, m_errors);
  instance->compile();
  delete instance;
  return true;
}

bool CompileModule::compile() {
  FileContent* fC = m_module->m_fileContents[0];
  NodeId nodeId = m_module->m_nodeIds[0];
  Location loc(m_symbols->registerSymbol(fC->getFileName(nodeId)),
               fC->Line(nodeId), 0,
               m_symbols->registerSymbol(m_module->getName()));
  VObjectType moduleType = fC->Type(nodeId);
  ErrorDefinition::ErrorType errType = ErrorDefinition::COMP_COMPILE_MODULE;
  switch (moduleType) {
    case VObjectType::slInterface_declaration:
      errType = ErrorDefinition::COMP_COMPILE_INTERFACE;
      break;
    case VObjectType::slUdp_declaration:
      errType = ErrorDefinition::COMP_COMPILE_UDP;
      break;
    case VObjectType::slChecker_declaration:
      errType = ErrorDefinition::COMP_COMPILE_CHECKER;
      break;
    default:
      break;
  }

  Error err(errType, loc);
  ErrorContainer* errors = new ErrorContainer(m_symbols);
  errors->regiterCmdLine(
      m_compileDesign->getCompiler()->getCommandLineParser());
  errors->addError(err);
  errors->printMessage(
      err,
      m_compileDesign->getCompiler()->getCommandLineParser()->muteStdout());
  delete errors;

  switch (moduleType) {
    case VObjectType::slModule_declaration:
      if (!collectModuleObjects_()) return false;
      if (!checkModule_()) return false;
      break;
    case VObjectType::slInterface_declaration:
      if (!collectInterfaceObjects_()) return false;
      if (!checkInterface_()) return false;
      break;
    case VObjectType::slUdp_declaration:

      break;
    case VObjectType::slChecker_declaration:

      break;
    case VObjectType::slProgram_declaration:

      break;
    default:
      break;
  }

  return true;
}

VObjectType getSignalType(FileContent* fC, NodeId net_port_type) {
  VObjectType signal_type = VObjectType::slData_type_or_implicit;
  if (net_port_type) {
    NodeId data_type_or_implicit = fC->Child(net_port_type);
    if (fC->Type(data_type_or_implicit) == VObjectType::slNetType_Wire) {
      signal_type = VObjectType::slNetType_Wire;
    } else {
      NodeId data_type = fC->Child(data_type_or_implicit);
      if (data_type) {
        VObjectType the_type = fC->Type(data_type);
        if (the_type == VObjectType::slData_type) {
          NodeId integer_vector_type = fC->Child(data_type);
          the_type = fC->Type(integer_vector_type);
          if (the_type == VObjectType::slIntVec_TypeBit ||
              the_type == VObjectType::slIntVec_TypeLogic ||
              the_type == VObjectType::slIntVec_TypeReg) {
            signal_type = the_type;
          }
        }
      }
    }
  }
  return signal_type;
}

void setDirectionAndType(ModuleDefinition* module, FileContent* fC,
                         NodeId signal, VObjectType type,
                         VObjectType signal_type) {
  while (signal) {
    for (auto& port : module->getPorts()) {
      if (port.getName() == fC->SymName(signal)) {
        VObjectType dir_type = slNoType;
        if (type == VObjectType::slInput_declaration)
          dir_type = slPortDir_Inp;
        else if (type == VObjectType::slOutput_declaration)
          dir_type = slPortDir_Out;
        else if (type == VObjectType::slInout_declaration)
          dir_type = slPortDir_Inout;

        port.setDirection(dir_type);
        if (signal_type != VObjectType::slData_type_or_implicit)
          port.setType(signal_type);
        break;
      }
    }
    signal = fC->Sibling(signal);
  }
}

bool CompileModule::collectModuleObjects_() {
  std::vector<VObjectType> stopPoints = {
      VObjectType::slConditional_generate_construct,
      VObjectType::slGenerate_module_conditional_statement,
      VObjectType::slLoop_generate_construct,
      VObjectType::slGenerate_module_loop_statement,
      VObjectType::slPar_block,
      VObjectType::slSeq_block,
      VObjectType::slModule_declaration,
      VObjectType::slClass_declaration};

  for (unsigned int i = 0; i < m_module->m_fileContents.size(); i++) {
    FileContent* fC = m_module->m_fileContents[i];
    std::string libName = fC->getLibrary()->getName();
    VObject current = fC->Object(m_module->m_nodeIds[i]);
    NodeId id = current.m_child;
    if (!id) id = current.m_sibling;
    if (!id) return false;

    // Package imports
    std::vector<FileCNodeId> pack_imports;
    // - Local file imports
    for (auto import : fC->getObjects(VObjectType::slPackage_import_item)) {
      pack_imports.push_back(import);
    }

    for (auto pack_import : pack_imports) {
      FileContent* pack_fC = pack_import.fC;
      NodeId pack_id = pack_import.nodeId;
      m_helper.importPackage(m_module, m_design, pack_fC, pack_id);
    }

    std::stack<NodeId> stack;
    stack.push(id);
    VObjectType port_direction = VObjectType::slNoType;
    while (stack.size()) {
      id = stack.top();
      stack.pop();
      current = fC->Object(id);
      VObjectType type = fC->Type(id);
      switch (type) {
        case VObjectType::slPackage_import_item: {
          m_helper.importPackage(m_module, m_design, fC, id);
          break;
        }
        case VObjectType::slAnsi_port_declaration: {
          NodeId net_port_header = fC->Child(id);
          NodeId identifier = fC->Sibling(net_port_header);
          NodeId net_port_type = fC->Child(net_port_header);
          VObjectType dir_type = fC->Type(net_port_type);
          if (dir_type == VObjectType::slPortDir_Out ||
              dir_type == VObjectType::slPortDir_Inp ||
              dir_type == VObjectType::slPortDir_Inout ||
              dir_type == VObjectType::slPortDir_Ref) {
            port_direction = dir_type;
            net_port_type = fC->Sibling(net_port_type);
            VObjectType signal_type = getSignalType(fC, net_port_type);
            Signal signal(fC, identifier, signal_type, port_direction);
            m_module->m_ports.push_back(signal);
          } else {
            NodeId data_type_or_implicit = fC->Child(net_port_type);
            NodeId data_type = fC->Child(data_type_or_implicit);
            if (data_type) {
              NodeId if_type_name_s = fC->Child(data_type);
              if (fC->Type(if_type_name_s) == VObjectType::slIntVec_TypeReg ||
                  fC->Type(if_type_name_s) == VObjectType::slIntVec_TypeLogic) {
                Signal signal(fC, identifier, fC->Type(if_type_name_s),
                              VObjectType::slNoType);
                m_module->m_ports.push_back(signal);
              } else {
                std::string interfaceName =
                    libName + "@" + fC->SymName(if_type_name_s);
                Signal signal(fC, if_type_name_s, identifier);
                ModuleDefinition* interface =
                    m_design->getModuleDefinition(interfaceName);
                if (interface) {
                  signal.setInterfaceDef(interface);
                } else {
                  Location loc(m_symbols->registerSymbol(
                                   fC->getFileName(if_type_name_s)),
                               fC->Line(if_type_name_s), 0,
                               m_symbols->registerSymbol(interfaceName));
                  Error err(ErrorDefinition::COMP_UNDEFINED_INTERFACE, loc);
                  m_errors->addError(err);
                }
              }
            } else {
              Signal signal(fC, identifier,
                            VObjectType::slData_type_or_implicit,
                            port_direction);
              m_module->m_ports.push_back(signal);
            }
          }
          break;
        }
        case VObjectType::slPort:
          /*
            n<mem_if> u<3> t<StringConst> p<6> s<5> l<1>
            n<> u<4> t<Constant_bit_select> p<5> l<1>
            n<> u<5> t<Constant_select> p<6> c<4> l<1>
            n<> u<6> t<Port_reference> p<11> c<3> s<10> l<1>
            n<mif> u<7> t<StringConst> p<10> s<9> l<1>
            n<> u<8> t<Constant_bit_select> p<9> l<1>
            n<> u<9> t<Constant_select> p<10> c<8> l<1>
            n<> u<10> t<Port_reference> p<11> c<7> l<1>
            n<> u<11> t<Port_expression> p<12> c<6> l<1>
            n<> u<12> t<Port> p<13> c<11> l<1>
          */
          {
            NodeId Port_expression = fC->Child(id);
            if (Port_expression &&
                (fC->Type(Port_expression) == VObjectType::slPort_expression)) {
              NodeId if_type = fC->Child(Port_expression);
              if (fC->Type(if_type) == VObjectType::slPort_reference) {
                NodeId if_type_name_s = fC->Child(if_type);
                NodeId if_name = fC->Sibling(if_type);
                if (if_name) {
                  NodeId if_name_s = fC->Child(if_name);
                  std::string interfaceName =
                      libName + "@" + fC->SymName(if_type_name_s);
                  Signal signal(fC, if_type_name_s, if_name_s);
                  ModuleDefinition* interface =
                      m_design->getModuleDefinition(interfaceName);
                  if (interface) {
                    signal.setInterfaceDef(interface);
                  } else {
                    Location loc(m_symbols->registerSymbol(
                                     fC->getFileName(if_type_name_s)),
                                 fC->Line(if_type_name_s), 0,
                                 m_symbols->registerSymbol(interfaceName));
                    Error err(ErrorDefinition::COMP_UNDEFINED_INTERFACE, loc);
                    m_errors->addError(err);
                  }
                  m_module->m_ports.push_back(signal);
                } else {
                  Signal signal(fC, if_type_name_s,
                                VObjectType::slData_type_or_implicit,
                                port_direction);
                  m_module->m_ports.push_back(signal);
                }
              }
            }
            break;
          }
        case VObjectType::slInput_declaration:
        case VObjectType::slOutput_declaration:
        case VObjectType::slInout_declaration: {
          /*
            n<> u<24> t<Data_type_or_implicit> p<25> l<7>
            n<> u<25> t<Net_port_type> p<28> c<24> s<27> l<7>
            n<c0> u<26> t<StringConst> p<27> l<7>
            n<> u<27> t<List_of_port_identifiers> p<28> c<26> l<7>
            n<> u<28> t<Output_declaration> p<29> c<25> l<7>
          */
          NodeId net_port_type = fC->Child(id);
          VObjectType signal_type = getSignalType(fC, net_port_type);
          NodeId list_of_port_identifiers = fC->Sibling(net_port_type);
          if (fC->Type(list_of_port_identifiers) ==
              VObjectType::slPacked_dimension) {
            list_of_port_identifiers = fC->Sibling(list_of_port_identifiers);
          }
          NodeId signal = fC->Child(list_of_port_identifiers);
          setDirectionAndType(m_module, fC, signal, type, signal_type);
          break;
        }
        case VObjectType::slClocking_declaration:
          compileClockingBlock_(fC, id);
          break;
        case VObjectType::slNet_declaration: {
          /*
           n<> u<17> t<NetType_Wire> p<18> l<27>
           n<> u<18> t<NetTypeOrTrireg_Net> p<22> c<17> s<21> l<27>
           n<a> u<19> t<StringConst> p<20> l<27>
           n<> u<20> t<Net_decl_assignment> p<21> c<19> l<27>
           n<> u<21> t<List_of_net_decl_assignments> p<22> c<20> l<27>
           n<> u<22> t<Net_declaration> p<23> c<18> l<27>
          */
          NodeId netTypeOrTrireg_Net = fC->Child(id);
          NodeId netType_Wire = fC->Child(netTypeOrTrireg_Net);
          NodeId list_of_net_decl_assignments =
              fC->Sibling(netTypeOrTrireg_Net);
          if (fC->Type(list_of_net_decl_assignments) ==
              VObjectType::slPacked_dimension) {
            list_of_net_decl_assignments =
                fC->Sibling(list_of_net_decl_assignments);
          }
          NodeId net_decl_assignment = fC->Child(list_of_net_decl_assignments);
          while (net_decl_assignment) {
            NodeId signal = fC->Child(net_decl_assignment);
            for (auto& port : m_module->m_ports) {
              if (port.getName() == fC->SymName(signal)) {
                port.setType(fC->Type(netType_Wire));
                break;
              }
            }
            net_decl_assignment = fC->Sibling(net_decl_assignment);
          }
          break;
        }
        case VObjectType::slData_declaration: {
          NodeId subNode = fC->Child(id);
          VObjectType subType = fC->Type(subNode);
          switch (subType) {
            case VObjectType::slType_declaration: {
              /*
                n<> u<15> t<Data_type> p<17> c<8> s<16> l<13>
                n<fsm_t> u<16> t<StringConst> p<17> l<13>
                n<> u<17> t<Type_declaration> p<18> c<15> l<13>
                n<> u<18> t<Data_declaration> p<19> c<17> l<13>
               */
              m_helper.compileTypeDef(m_module, fC, id);
              break;
            }
            case VObjectType::slVariable_declaration: {
              /*
                n<> u<29> t<IntVec_TypeReg> p<30> l<29>
                n<> u<30> t<Data_type> p<34> c<29> s<33> l<29>
                n<b> u<31> t<StringConst> p<32> l<29>
                n<> u<32> t<Variable_decl_assignment> p<33> c<31> l<29>
                n<> u<33> t<List_of_variable_decl_assignments> p<34> c<32> l<29>
                n<> u<34> t<Variable_declaration> p<35> c<30> l<29>
                n<> u<35> t<Data_declaration> p<36> c<34> l<29>
               */
              NodeId variable_declaration = fC->Child(id);
              NodeId data_type = fC->Child(variable_declaration);
              NodeId intVec_TypeReg = fC->Child(data_type);
              NodeId list_of_variable_decl_assignments = fC->Sibling(data_type);
              if (fC->Type(list_of_variable_decl_assignments) ==
                  VObjectType::slPacked_dimension) {
                list_of_variable_decl_assignments =
                    fC->Sibling(list_of_variable_decl_assignments);
              }
              NodeId variable_decl_assignment =
                  fC->Child(list_of_variable_decl_assignments);
              while (variable_decl_assignment) {
                NodeId signal = fC->Child(variable_decl_assignment);
                for (auto& port : m_module->m_ports) {
                  if (port.getName() == fC->SymName(signal)) {
                    port.setType(fC->Type(intVec_TypeReg));
                    break;
                  }
                }
                variable_decl_assignment =
                    fC->Sibling(variable_decl_assignment);
              }
              break;
            }
            default:
              break;
          }
          break;
        }
        case VObjectType::slPort_declaration: {
          /*
           n<Configuration> u<21> t<StringConst> p<22> l<7>
           n<> u<22> t<Interface_identifier> p<26> c<21> s<25> l<7>
           n<cfg> u<23> t<StringConst> p<24> l<7>
           n<> u<24> t<Interface_identifier> p<25> c<23> l<7>
           n<> u<25> t<List_of_interface_identifiers> p<26> c<24> l<7>
           n<> u<26> t<Interface_port_declaration> p<27> c<22> l<7>
           n<> u<27> t<Port_declaration> p<28> c<26> l<7>
           */
          NodeId subNode = fC->Child(id);
          VObjectType subType = fC->Type(subNode);
          switch (subType) {
            case VObjectType::slInterface_port_declaration: {
              NodeId interface_identifier = fC->Child(subNode);
              NodeId interfIdName = fC->Child(interface_identifier);
              std::string interfName = fC->SymName(interfIdName);

              DesignComponent* def = NULL;
              DataType* type = NULL;

              std::pair<FileCNodeId, DesignComponent*>* datatype =
                  m_module->getNamedObject(interfName);
              if (!datatype) {
                def = m_module->getClassDefinition(m_module->getName() +
                                                   "::" + interfName);
              }
              if (datatype) {
                def = datatype->second;
              }
              if (def == NULL) {
                def = m_design->getComponentDefinition(libName + "@" +
                                                       interfName);
              }
              if (def == NULL) {
                type = m_module->getDataType(interfName);
              }
              if (def == NULL && type == NULL && (interfName != "logic") &&
                  (interfName != "byte") && (interfName != "bit") &&
                  (interfName != "new") && (interfName != "expect") &&
                  (interfName != "var") && (interfName != "signed") &&
                  (interfName != "unsigned") && (interfName != "do") &&
                  (interfName != "final") && (interfName != "global") &&
                  (interfName != "soft")) {
                Location loc(m_symbols->registerSymbol(fC->getFileName(id)),
                             fC->Line(id), 0,
                             m_symbols->registerSymbol(interfName));
                Error err(ErrorDefinition::COMP_UNDEFINED_TYPE, loc);
                m_errors->addError(err);
              }

              NodeId list_of_interface_identifiers =
                  fC->Sibling(interface_identifier);
              NodeId identifier = fC->Child(list_of_interface_identifiers);
              while (identifier) {
                std::string name = fC->SymName(identifier);
                identifier = fC->Sibling(identifier);
                // TODO
              }

              break;
            }
            case VObjectType::slInput_declaration:
            case VObjectType::slOutput_declaration:
            case VObjectType::slInout_declaration: {
              /*
                n<> u<24> t<Data_type_or_implicit> p<25> l<7>
                n<> u<25> t<Net_port_type> p<28> c<24> s<27> l<7>
                n<c0> u<26> t<StringConst> p<27> l<7>
                n<> u<27> t<List_of_port_identifiers> p<28> c<26> l<7>
                n<> u<28> t<Output_declaration> p<29> c<25> l<7>
               */
              NodeId net_port_type = fC->Child(subNode);
              VObjectType signal_type = getSignalType(fC, net_port_type);
              NodeId list_of_port_identifiers = fC->Sibling(net_port_type);
              if (fC->Type(list_of_port_identifiers) ==
                  VObjectType::slPacked_dimension) {
                list_of_port_identifiers =
                    fC->Sibling(list_of_port_identifiers);
              }
              NodeId signal = fC->Child(list_of_port_identifiers);
              setDirectionAndType(m_module, fC, signal, subType, signal_type);
              break;
            }
            default:
              break;
          }
          break;
        }

        case VObjectType::slParam_assignment:
        case VObjectType::slHierarchical_instance:
        case VObjectType::slN_input_gate_instance:
        case VObjectType::slN_output_gate_instance:
        case VObjectType::slUdp_instance:
        case VObjectType::slUdp_instantiation:
        case VObjectType::slModule_instantiation:
        case VObjectType::slInterface_instantiation:
        case VObjectType::slGate_instantiation:
        case VObjectType::slConditional_generate_construct:
        case VObjectType::slGenerate_module_conditional_statement:
        case VObjectType::slLoop_generate_construct:
        case VObjectType::slGenerate_module_loop_statement:
        case VObjectType::slPar_block:
        case VObjectType::slSeq_block:
        case VObjectType::slDefparam_assignment: {
          FileCNodeId fnid(fC, id);
          m_module->addObject(type, fnid);
          break;
        }
        default:
          break;
      }

      if (current.m_sibling) stack.push(current.m_sibling);
      if (current.m_child) {
        if (stopPoints.size()) {
          bool stop = false;
          for (auto t : stopPoints) {
            if (t == current.m_type) {
              stop = true;
              break;
            }
          }
          if (!stop)
            if (current.m_child) stack.push(current.m_child);
        } else {
          if (current.m_child) stack.push(current.m_child);
        }
      }
    }
  }
  return true;
}

bool CompileModule::collectInterfaceObjects_() {
  for (unsigned int i = 0; i < m_module->m_fileContents.size(); i++) {
    FileContent* fC = m_module->m_fileContents[i];
    VObject current = fC->Object(m_module->m_nodeIds[i]);
    NodeId id = current.m_child;
    if (!id) id = current.m_sibling;
    if (!id) return false;

    // Package imports
    std::vector<FileCNodeId> pack_imports;
    // - Local file imports
    for (auto import : fC->getObjects(VObjectType::slPackage_import_item)) {
      pack_imports.push_back(import);
    }

    for (auto pack_import : pack_imports) {
      FileContent* pack_fC = pack_import.fC;
      NodeId pack_id = pack_import.nodeId;
      m_helper.importPackage(m_module, m_design, pack_fC, pack_id);
    }

    std::stack<NodeId> stack;
    stack.push(id);
    while (stack.size()) {
      id = stack.top();
      stack.pop();
      current = fC->Object(id);
      VObjectType type = fC->Type(id);
      switch (type) {
        case VObjectType::slPackage_import_item: {
          m_helper.importPackage(m_module, m_design, fC, id);
          break;
        }
        case VObjectType::slAnsi_port_declaration: {
          NodeId Net_port_header = fC->Child(id);
          NodeId net = fC->Sibling(Net_port_header);
          NodeId Direction = fC->Child(Net_port_header);
          VObjectType direction = fC->Type(Direction);
          NodeId Net_port_type = fC->Sibling(Direction);
          NodeId NetType = fC->Child(Net_port_type);
          VObjectType nettype = fC->Type(NetType);
          Signal signal(fC, net, nettype, direction);
          m_module->m_ports.push_back(signal);
          break;
        }
        case VObjectType::slNet_declaration: {
          NodeId NetTypeOrTrireg_Net = fC->Child(id);
          NodeId NetType = fC->Child(NetTypeOrTrireg_Net);
          VObjectType nettype = fC->Type(NetType);
          NodeId net = fC->Sibling(NetTypeOrTrireg_Net);
          NodeId List_of_net_decl_assignments;
          if (fC->Type(net) == slPacked_dimension) {
            List_of_net_decl_assignments = fC->Sibling(net);
          } else {
            List_of_net_decl_assignments = net;
          }
          NodeId Net_decl_assignment = fC->Child(List_of_net_decl_assignments);
          net = fC->Child(Net_decl_assignment);
          bool existing = false;
          for (auto& port : m_module->m_ports) {
            if (port.getName() == fC->SymName(net)) {
              existing = true;
              port.setType(nettype);
              break;
            }
          }
          if (!existing) {
            Signal signal(fC, net, nettype, VObjectType::slNoType);
            m_module->m_ports.push_back(signal);
          }
          break;
        }
        case VObjectType::slData_declaration: {
          /*
           n<> u<29> t<IntVec_TypeReg> p<30> l<29>
           n<> u<30> t<Data_type> p<34> c<29> s<33> l<29>
           n<b> u<31> t<StringConst> p<32> l<29>
           n<> u<32> t<Variable_decl_assignment> p<33> c<31> l<29>
           n<> u<33> t<List_of_variable_decl_assignments> p<34> c<32> l<29>
           n<> u<34> t<Variable_declaration> p<35> c<30> l<29>
           n<> u<35> t<Data_declaration> p<36> c<34> l<29>
          */
          NodeId variable_declaration = fC->Child(id);
          NodeId data_type = fC->Child(variable_declaration);
          NodeId intVec_TypeReg = fC->Child(data_type);
          NodeId list_of_variable_decl_assignments = fC->Sibling(data_type);
          if (fC->Type(list_of_variable_decl_assignments) ==
              VObjectType::slPacked_dimension) {
            list_of_variable_decl_assignments =
                fC->Sibling(list_of_variable_decl_assignments);
          }
          NodeId variable_decl_assignment =
              fC->Child(list_of_variable_decl_assignments);
          while (variable_decl_assignment) {
            NodeId signal = fC->Child(variable_decl_assignment);
            bool port_exist = false;
            for (auto& port : m_module->m_ports) {
              if (port.getName() == fC->SymName(signal)) {
                port_exist = true;
                port.setType(fC->Type(intVec_TypeReg));
                break;
              }
            }
            if (!port_exist) {
              Signal sig(fC, signal, fC->Type(intVec_TypeReg),
                         VObjectType::slNoType);
              m_module->m_ports.push_back(sig);
            }
            variable_decl_assignment = fC->Sibling(variable_decl_assignment);
          }
          break;
        }
        case VObjectType::slClocking_declaration:
          compileClockingBlock_(fC, id);
          break;
        case VObjectType::slGenerate_interface_item: {
          // TODO: rewrite this rough implementation
          std::vector<VObjectType> types = {VObjectType::slModport_item};
          std::vector<NodeId> items = fC->sl_collect_all(id, types);
          for (auto nodeId : items) {
            Location loc(m_symbols->registerSymbol(fC->getFileName(nodeId)),
                         fC->Line(nodeId), 0, 0);
            Error err(ErrorDefinition::COMP_NO_MODPORT_IN_GENERATE, loc);
            m_errors->addError(err);
          }
          break;
        }
        case VObjectType::slModport_item:
          /*
           n<tb> u<45> t<StringConst> p<56> s<50> l<43>
           n<> u<46> t<PortDir_Inp> p<49> s<48> l<43>
           n<clk> u<47> t<StringConst> p<48> l<43>
           n<> u<48> t<Modport_simple_port> p<49> c<47> l<43>
           n<> u<49> t<Modport_simple_ports_declaration> p<50> c<46> l<43>
           n<> u<50> t<Modport_ports_declaration> p<56> c<49> s<55> l<43>
           n<> u<51> t<PortDir_Out> p<54> s<53> l<43>
           n<reset> u<52> t<StringConst> p<53> l<43>
           n<> u<53> t<Modport_simple_port> p<54> c<52> l<43>
           n<> u<54> t<Modport_simple_ports_declaration> p<55> c<51> l<43>
           n<> u<55> t<Modport_ports_declaration> p<56> c<54> l<43>
           n<> u<56> t<Modport_item> p<57> c<45> l<43>
          */
          {
            NodeId modportname = fC->Child(id);
            SymbolId modportsymb = fC->Name(modportname);
            NodeId modport_ports_declaration = fC->Sibling(modportname);
            VObjectType port_direction_type = VObjectType::slNoType;
            while (modport_ports_declaration) {
              NodeId port_declaration = fC->Child(modport_ports_declaration);
              VObjectType port_declaration_type = fC->Type(port_declaration);
              if (port_declaration_type ==
                  VObjectType::slModport_simple_ports_declaration) {
                NodeId port_direction = fC->Child(port_declaration);
                port_direction_type = fC->Type(port_direction);
                NodeId modport_simple_port = fC->Sibling(port_direction);
                while (modport_simple_port) {
                  NodeId simple_port_name = fC->Child(modport_simple_port);
                  SymbolId port_symbol = fC->Name(simple_port_name);
                  bool port_exists = false;
                  for (auto& port : m_module->m_ports) {
                    if (fC->Name(port.getNodeId()) == port_symbol) {
                      port_exists = true;
                      break;
                    }
                  }
                  if (!port_exists) {
                    Location loc(m_symbols->registerSymbol(
                                     fC->getFileName(simple_port_name)),
                                 fC->Line(simple_port_name), 0,
                                 m_symbols->registerSymbol(
                                     fC->SymName(simple_port_name)));
                    Error err(ErrorDefinition::COMP_MODPORT_UNDEFINED_PORT,
                              loc);
                    m_errors->addError(err);
                  }
                  Signal signal(fC, simple_port_name,
                                VObjectType::slData_type_or_implicit,
                                port_direction_type);
                  m_module->insertModPort(modportsymb, signal);
                  modport_simple_port = fC->Sibling(modport_simple_port);
                }
              } else if (port_declaration_type ==
                         VObjectType::
                             slModport_hierarchical_ports_declaration) {
              } else if (port_declaration_type ==
                         VObjectType::slModport_tf_ports_declaration) {
              } else {
                // CLOCKING
                NodeId clocking_block_name = port_declaration;
                SymbolId clocking_block_symbol =
                    m_symbols->registerSymbol(fC->SymName(clocking_block_name));
                ClockingBlock* cb =
                    m_module->getClockingBlock(clocking_block_symbol);
                if (cb == NULL) {
                  Location loc(m_symbols->registerSymbol(
                                   fC->getFileName(clocking_block_name)),
                               fC->Line(clocking_block_name), 0,
                               clocking_block_symbol);
                  Error err(
                      ErrorDefinition::COMP_MODPORT_UNDEFINED_CLOCKING_BLOCK,
                      loc);
                  m_errors->addError(err);
                } else {
                  m_module->insertModPort(modportsymb, *cb);
                }
              }
              modport_ports_declaration =
                  fC->Sibling(modport_ports_declaration);
            }
          }
        default:
          break;
      }

      if (current.m_sibling) stack.push(current.m_sibling);
      if (current.m_child) stack.push(current.m_child);
    }
  }

  return true;
}

bool CompileModule::checkModule_() {
  int countMissingType = 0;
  int countMissingDirection = 0;
  Location* missingTypeLoc = NULL;
  Location* missingDirectionLoc = NULL;
  for (auto& port : m_module->m_ports) {
    if (port.isInterface()) continue;
    if (port.getType() == VObjectType::slData_type_or_implicit) {
      if (port.getDirection() == VObjectType::slPortDir_Out ||
          port.getDirection() == VObjectType::slPortDir_Inout) {
        if (countMissingType == 0)
          missingTypeLoc = new Location(
              m_symbols->registerSymbol(
                  port.getFileContent()->getFileName(port.getNodeId())),
              port.getFileContent()->Line(port.getNodeId()), 0,
              m_symbols->registerSymbol(port.getName()));
        countMissingType++;
      }
    }
    if (port.getDirection() == VObjectType::slNoType) {
      if (countMissingDirection == 0)
        missingDirectionLoc = new Location(
            m_symbols->registerSymbol(
                port.getFileContent()->getFileName(port.getNodeId())),
            port.getFileContent()->Line(port.getNodeId()), 0,
            m_symbols->registerSymbol(port.getName()));
      countMissingDirection++;
    }
  }
  if (countMissingType) {
    Location countLoc(
        0, 0, 0,
        m_symbols->registerSymbol(std::to_string(countMissingType - 1)));
    if (countMissingType - 1 > 0) {
      Error err(ErrorDefinition::COMP_PORT_MISSING_TYPE, *missingTypeLoc,
                countLoc);
      m_errors->addError(err);
    } else {
      Error err(ErrorDefinition::COMP_PORT_MISSING_TYPE, *missingTypeLoc);
      m_errors->addError(err);
    }
    delete missingTypeLoc;
  }
  if (countMissingDirection) {
    Location countLoc(
        0, 0, 0,
        m_symbols->registerSymbol(std::to_string(countMissingDirection - 1)));
    if (countMissingDirection - 1 > 0) {
      Error err(ErrorDefinition::COMP_PORT_MISSING_DIRECTION,
                *missingDirectionLoc, countLoc);
      m_errors->addError(err);
    } else {
      Error err(ErrorDefinition::COMP_PORT_MISSING_DIRECTION,
                *missingDirectionLoc);
      m_errors->addError(err);
    }
    delete missingDirectionLoc;
  }

  return true;
}

bool CompileModule::checkInterface_() {
  int countMissingType = 0;
  Location* missingTypeLoc = NULL;
  for (auto& port : m_module->m_ports) {
    if (port.getType() == VObjectType::slData_type_or_implicit) {
      if (port.getDirection() == VObjectType::slPortDir_Out ||
          port.getDirection() == VObjectType::slPortDir_Inout) {
        if (countMissingType == 0)
          missingTypeLoc = new Location(
              m_symbols->registerSymbol(
                  port.getFileContent()->getFileName(port.getNodeId())),
              port.getFileContent()->Line(port.getNodeId()), 0,
              m_symbols->registerSymbol(port.getName()));
        countMissingType++;
      }
    }
  }
  if (countMissingType) {
    Location countLoc(
        0, 0, 0,
        m_symbols->registerSymbol(std::to_string(countMissingType - 1)));
    if (countMissingType - 1 > 0) {
      Error err(ErrorDefinition::COMP_PORT_MISSING_TYPE, *missingTypeLoc,
                countLoc);
      m_errors->addError(err);
    } else {
      Error err(ErrorDefinition::COMP_PORT_MISSING_TYPE, *missingTypeLoc);
      m_errors->addError(err);
    }
    delete missingTypeLoc;
  }
  return true;
}

void CompileModule::compileClockingBlock_(FileContent* fC, NodeId id) {
  /*
    n<cb> u<12> t<StringConst> p<21> s<20> l<39>
    n<> u<13> t<Edge_Posedge> p<19> s<18> l<39>
    n<clk> u<14> t<StringConst> p<17> s<16> l<39>
    n<> u<15> t<Bit_select> p<16> l<39>
    n<> u<16> t<Select> p<17> c<15> l<39>
    n<> u<17> t<Primary> p<18> c<14> l<39>
    n<> u<18> t<Expression> p<19> c<17> l<39>
    n<> u<19> t<Event_expression> p<20> c<13> l<39>
    n<> u<20> t<Clocking_event> p<21> c<19> l<39>
    n<> u<21> t<Clocking_declaration> p<22> c<12> l<39>
   */

  NodeId clocking_block_name = fC->Child(id);
  SymbolId clocking_block_symbol =
      m_symbols->registerSymbol(fC->SymName(clocking_block_name));
  NodeId clocking_event = fC->Sibling(clocking_block_name);
  ClockingBlock cb(fC, clocking_block_name, clocking_event);
  m_module->addClockingBlock(clocking_block_symbol, cb);
}
