/*
 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:   CompileClass.cpp
 * Author: alain
 *
 * Created on June 7, 2018, 10:26 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.hpp"
#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 "DesignCompile/CompileDesign.h"
#include "Testbench/ClassDefinition.h"
#include "DesignCompile/CompileClass.h"

using namespace SURELOG;

CompileClass::~CompileClass() {}

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

bool CompileClass::compile() {
  FileContent* fC = m_class->m_fileContents[0];
  NodeId nodeId = m_class->m_nodeIds[0];

  std::string fileName = fC->getFileName(nodeId);
  if (strstr(fileName.c_str(), "builtin.sv")) {
    fileName = "builtin.sv";
  }
  Location loc(m_symbols->registerSymbol(fileName),
               fC->Line(nodeId), 0,
               m_symbols->registerSymbol(m_class->getName()));

  Error err1(ErrorDefinition::COMP_COMPILE_CLASS, loc);
  ErrorContainer* errors = new ErrorContainer(m_symbols);
  errors->regiterCmdLine(
      m_compileDesign->getCompiler()->getCommandLineParser());
  errors->addError(err1);
  errors->printMessage(
      err1,
      m_compileDesign->getCompiler()->getCommandLineParser()->muteStdout());
  delete errors;
  if (fC->getSize() == 0) return true;

  // Package imports
  std::vector<FileCNodeId> pack_imports;
  // - Local file imports
  for (auto import : fC->getObjects(VObjectType::slPackage_import_item)) {
    pack_imports.push_back(import);
  }
  // - Parent container imports
  DesignComponent* container = m_class->getContainer();
  if (container) {
    // FileCNodeId itself(container->getFileContents ()[0],
    // container->getNodeIds ()[0]); pack_imports.push_back(itself);
    for (auto import :
         container->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_class, m_design, pack_fC, pack_id);
  }

  compile_class_parameters_(fC, nodeId);

  // This
  DataType* thisdt =
      new DataType(fC, nodeId, "this", VObjectType::slClass_declaration);
  thisdt->setDefinition(m_class);
  Property* prop = new Property(thisdt, fC, nodeId, 0, "this", false, false,
                                false, false, false);
  m_class->insertProperty(prop);

  VObject current = fC->Object(fC->getSize() - 2);
  NodeId id = nodeId;
  if (!id) return false;
  std::stack<NodeId> stack;
  stack.push(id);
  bool inFunction_body_declaration = false;
  bool inTask_body_declaration = false;
  while (stack.size()) {
    bool skipGuts = false;
    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_class, m_design, fC, id);
        break;
      }
      case VObjectType::slClass_constructor_declaration: {
        inFunction_body_declaration = true;
        break;
      }
      case VObjectType::slFunction_body_declaration: {
        inFunction_body_declaration = true;
        break;
      }
      case VObjectType::slEndfunction: {
        inFunction_body_declaration = false;
        break;
      }
      case VObjectType::slTask_body_declaration: {
        inTask_body_declaration = true;
        break;
      }
      case VObjectType::slEndtask: {
        inTask_body_declaration = false;
        break;
      }
      case VObjectType::slClass_property:
        if (inFunction_body_declaration || inTask_body_declaration) break;
        compile_class_property_(fC, id);
        break;
      case VObjectType::slClass_constraint:
        compile_class_constraint_(fC, id);
        break;
      case VObjectType::slClass_declaration:
        if (id != nodeId) {
          compile_class_declaration_(fC, id);
          if (current.m_sibling) stack.push(current.m_sibling);
          continue;
        }
        break;
      case VObjectType::slCovergroup_declaration:
        compile_covergroup_declaration_(fC, id);
        break;
      case VObjectType::slLocal_parameter_declaration:
        compile_local_parameter_declaration_(fC, id);
        break;
      case VObjectType::slParameter_declaration:
        compile_parameter_declaration_(fC, id);
        break;
      case VObjectType::slClass_method:
        compile_class_method_(fC, id);
        skipGuts = true;
        break;
      case VObjectType::slClass_type:
        compile_class_type_(fC, id);
      default:
        break;
    }

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

  // Default constructor
  DataType* returnType = new DataType();
  FunctionMethod* method =
      new FunctionMethod(m_class, fC, nodeId, "new", returnType, false, false,
                         false, false, false, false);
  method->compile(m_helper);
  Function* prevDef = m_class->getFunction("new");
  if (!prevDef) {
    m_class->insertFunction(method);
  }

  return true;
}

bool CompileClass::compile_class_property_(FileContent* fC, NodeId id) {
  NodeId data_declaration = fC->Child(id);
  NodeId var_decl = fC->Child(data_declaration);
  VObjectType type = fC->Type(data_declaration);
  bool is_local = false;
  bool is_static = false;
  bool is_protected = false;
  bool is_rand = false;
  bool is_randc = false;
  while ((type == VObjectType::slPropQualifier_ClassItem) ||
         (type == VObjectType::slPropQualifier_Rand) ||
         (type == VObjectType::slPropQualifier_Randc)) {
    NodeId qualifier = fC->Child(data_declaration);
    VObjectType qualType = fC->Type(qualifier);
    if (qualType == VObjectType::slClassItemQualifier_Protected)
      is_protected = true;
    if (qualType == VObjectType::slClassItemQualifier_Static) is_static = true;
    if (qualType == VObjectType::slClassItemQualifier_Local) is_local = true;
    if (type == VObjectType::slPropQualifier_Rand) is_rand = true;
    if (type == VObjectType::slPropQualifier_Randc) is_randc = true;
    data_declaration = fC->Sibling(data_declaration);
    type = fC->Type(data_declaration);
    var_decl = fC->Child(data_declaration);
  }

  if (type == VObjectType::slData_declaration) {
    /*
   n<A> u<3> t<StringConst> p<37> s<12> l<5>
   n<> u<4> t<IntegerAtomType_Int> p<5> l<6>
   n<> u<5> t<Data_type> p<9> c<4> s<8> l<6>
   n<size> u<6> t<StringConst> p<7> l<6>
   n<> u<7> t<Variable_decl_assignment> p<8> c<6> l<6>
   n<> u<8> t<List_of_variable_decl_assignments> p<9> c<7> l<6>
   n<> u<9> t<Variable_declaration> p<10> c<5> l<6>
   n<> u<10> t<Data_declaration> p<11> c<9> l<6>
   n<> u<11> t<Class_property> p<12> c<10> l<6>
   n<> u<12> t<Class_item> p<37> c<11> s<35> l<6>
     */
    VObjectType var_type = fC->Type(var_decl);
    if (var_type == VObjectType::slVariable_declaration) {
      NodeId data_type = fC->Child(var_decl);
      NodeId node_type = fC->Child(data_type);

      VObjectType the_type = fC->Type(node_type);
      std::string typeName;
      if (the_type == VObjectType::slStringConst) {
        typeName = fC->SymName(node_type);
      } else if (the_type == VObjectType::slClass_scope) {
        NodeId class_type = fC->Child(node_type);
        NodeId class_name = fC->Child(class_type);
        typeName = fC->SymName(class_name);
        typeName += "::";
        NodeId symb_id = fC->Sibling(node_type);
        typeName += fC->SymName(symb_id);
      } else {
        typeName = VObject::getTypeName(the_type);
      }
      DataType* datatype = m_class->getUsedDataType(typeName);
      if (!datatype) {
        DataType* type =
            new DataType(fC, node_type, typeName, fC->Type(node_type));
        m_class->insertUsedDataType(typeName, type);
        datatype = m_class->getUsedDataType(typeName);
      }

      NodeId list_of_variable_decl_assignments = fC->Sibling(data_type);
      NodeId variable_decl_assignment =
          fC->Child(list_of_variable_decl_assignments);
      while (variable_decl_assignment) {
        NodeId var = fC->Child(variable_decl_assignment);
        NodeId range = fC->Sibling(var);
        std::string varName = fC->SymName(var);

        Property* previous = m_class->getProperty(varName);
        if (previous) {
          Location loc1(m_symbols->registerSymbol(fC->getFileName(var)),
                        fC->Line(var), 0, m_symbols->registerSymbol(varName));
          FileContent* prevFile = previous->getFileContent();
          NodeId prevNode = previous->getNodeId();
          Location loc2(
              m_symbols->registerSymbol(prevFile->getFileName(prevNode)),
              prevFile->Line(prevNode), 0, m_symbols->registerSymbol(varName));
          Error err(ErrorDefinition::COMP_MULTIPLY_DEFINED_PROPERTY, loc1,
                    loc2);
          m_errors->addError(err);
        }

        Property* prop =
            new Property(datatype, fC, var, range, varName, is_local, is_static,
                         is_protected, is_rand, is_randc);
        m_class->insertProperty(prop);

        variable_decl_assignment = fC->Sibling(variable_decl_assignment);
      }
    } else if (var_type == VObjectType::slType_declaration) {
      compile_type_declaration_(fC, data_declaration);
    }
  }

  return true;
}

bool CompileClass::compile_class_method_(FileContent* fC, NodeId id) {
  /*
    n<> u<8> t<MethodQualifier_Virtual> p<21> s<20> l<12>
    n<> u<9> t<Function_data_type> p<10> l<12>
    n<> u<10> t<Function_data_type_or_implicit> p<19> c<9> s<11> l<12>
    n<print_tree1> u<11> t<StringConst> p<19> s<17> l<12>
    n<> u<12> t<IntegerAtomType_Int> p<13> l<12>
    n<> u<13> t<Data_type> p<14> c<12> l<12>
    n<> u<14> t<Data_type_or_implicit> p<16> c<13> s<15> l<12>
    n<a> u<15> t<StringConst> p<16> l<12>
    n<> u<16> t<Tf_port_item> p<17> c<14> l<12>
    n<> u<17> t<Tf_port_list> p<19> c<16> s<18> l<12>
    n<> u<18> t<Endfunction> p<19> l<14>
    n<> u<19> t<Function_body_declaration> p<20> c<10> l<12>
    n<> u<20> t<Function_declaration> p<21> c<19> l<12>
    n<> u<21> t<Class_method> p<22> c<8> l<12>
   */
  NodeId func_decl = fC->Child(id);
  VObjectType func_type = fC->Type(func_decl);
  std::string funcName;
  std::string taskName;
  bool is_virtual = false;
  bool is_extern = false;
  bool is_static = false;
  bool is_local = false;
  bool is_protected = false;
  bool is_pure = false;
  DataType* returnType = new DataType();
  while ((func_type == VObjectType::slMethodQualifier_Virtual) ||
         (func_type == VObjectType::slMethodQualifier_ClassItem) ||
         (func_type == VObjectType::slPure_virtual_qualifier) ||
         (func_type == VObjectType::slExtern_qualifier) ||
         (func_type == VObjectType::slClassItemQualifier_Protected)) {
    if (func_type == VObjectType::slMethodQualifier_Virtual) {
      is_virtual = true;
      func_decl = fC->Sibling(func_decl);
      func_type = fC->Type(func_decl);
    }
    if (func_type == VObjectType::slClassItemQualifier_Protected) {
      is_protected = true;
      func_decl = fC->Sibling(func_decl);
      func_type = fC->Type(func_decl);
    }
    if (func_type == VObjectType::slPure_virtual_qualifier) {
      is_virtual = true;
      is_pure = true;
      func_decl = fC->Sibling(func_decl);
      func_type = fC->Type(func_decl);
    }
    if (func_type == VObjectType::slExtern_qualifier) {
      is_extern = true;
      func_decl = fC->Sibling(func_decl);
      func_type = fC->Type(func_decl);
    }
    if (func_type == VObjectType::slMethodQualifier_ClassItem) {
      NodeId qualifier = fC->Child(func_decl);
      VObjectType type = fC->Type(qualifier);
      if (type == VObjectType::slClassItemQualifier_Static) is_static = true;
      if (type == VObjectType::slClassItemQualifier_Local) is_local = true;
      if (type == VObjectType::slClassItemQualifier_Protected)
        is_protected = true;
      func_decl = fC->Sibling(func_decl);
      func_type = fC->Type(func_decl);
    }
  }
  if (func_type == VObjectType::slFunction_declaration) {
    NodeId func_body_decl = fC->Child(func_decl);
    NodeId function_data_type_or_implicit = fC->Child(func_body_decl);
    NodeId function_data_type = fC->Child(function_data_type_or_implicit);
    NodeId data_type = fC->Child(function_data_type);
    NodeId type = fC->Child(data_type);
    VObjectType the_type = fC->Type(type);
    std::string typeName;
    if (the_type == VObjectType::slStringConst) {
      typeName = fC->SymName(type);
    } else {
      typeName = VObject::getTypeName(the_type);
    }
    returnType->init(fC, type, typeName, fC->Type(type));
    NodeId function_name = fC->Sibling(function_data_type_or_implicit);
    funcName = fC->SymName(function_name);

  } else if (func_type == VObjectType::slTask_declaration) {
    /*
     n<cfg_dut> u<143> t<StringConst> p<146> s<144> l<37>
     n<> u<144> t<Endtask> p<146> s<145> l<39>
     n<cfg_dut> u<145> t<StringConst> p<146> l<39>
     n<> u<146> t<Task_body_declaration> p<147> c<143> l<37>
     n<> u<147> t<Task_declaration> p<148> c<146> l<37>
     n<> u<148> t<Class_method> p<149> c<147> l<37>
     */
    NodeId task_body_decl = fC->Child(func_decl);
    NodeId task_name = fC->Child(task_body_decl);
    taskName = fC->SymName(task_name);
  } else if (func_type == VObjectType::slMethod_prototype) {
    /*
     n<> u<65> t<IntVec_TypeBit> p<66> l<37>
     n<> u<66> t<Data_type> p<67> c<65> l<37>
     n<> u<67> t<Function_data_type> p<69> c<66> s<68> l<37>
     n<is_active> u<68> t<StringConst> p<69> l<37>
     n<> u<69> t<Function_prototype> p<70> c<67> l<37>
     n<> u<70> t<Method_prototype> p<71> c<69> l<37>
     n<> u<71> t<Class_method> p<72> c<70> l<37>
     */
    NodeId func_prototype = fC->Child(func_decl);
    if (fC->Type(func_prototype) == VObjectType::slTask_prototype) {
      NodeId task_name = fC->Child(func_prototype);
      taskName = fC->SymName(task_name);
    } else {
      NodeId function_data_type = fC->Child(func_prototype);
      NodeId data_type = fC->Child(function_data_type);
      NodeId type = fC->Child(data_type);
      VObjectType the_type = fC->Type(type);
      std::string typeName;
      if (the_type == VObjectType::slStringConst) {
        typeName = fC->SymName(type);
      } else {
        typeName = VObject::getTypeName(the_type);
      }
      returnType->init(fC, type, typeName, fC->Type(type));
      NodeId function_name = fC->Sibling(function_data_type);
      funcName = fC->SymName(function_name);
    }
    is_extern = true;
  } else if (func_type == VObjectType::slClass_constructor_declaration) {
    funcName = "new";
    returnType->init(fC, 0, "void", VObjectType::slNoType);
  } else if (func_type == VObjectType::slClass_constructor_prototype) {
    funcName = "new";
  } else {
    funcName = "UNRECOGNIZED_METHOD_TYPE";
  }
  if (taskName != "") {
    TaskMethod* method = new TaskMethod(m_class, fC, id, taskName, is_extern);
    method->compile(m_helper);
    TaskMethod* prevDef = m_class->getTask(taskName);
    if (prevDef) {
      Location loc1(m_symbols->registerSymbol(fC->getFileName(id)),
                    fC->Line(id), 0, m_symbols->registerSymbol(taskName));
      FileContent* prevFile = prevDef->getFileContent();
      NodeId prevNode = prevDef->getNodeId();
      Location loc2(m_symbols->registerSymbol(prevFile->getFileName(prevNode)),
                    prevFile->Line(prevNode), 0,
                    m_symbols->registerSymbol(taskName));
      Error err(ErrorDefinition::COMP_MULTIPLY_DEFINED_TASK, loc1, loc2);
      m_errors->addError(err);
    }
    m_class->insertTask(method);
  } else {
    FunctionMethod* method = new FunctionMethod(
        m_class, fC, id, funcName, returnType, is_virtual, is_extern, is_static,
        is_local, is_protected, is_pure);
    Variable* variable = new Variable(returnType, fC, id, 0, funcName);
    method->addVariable(variable);
    method->compile(m_helper);
    Function* prevDef = m_class->getFunction(funcName);
    if (prevDef) {
      Location loc1(m_symbols->registerSymbol(fC->getFileName(id)),
                    fC->Line(id), 0, m_symbols->registerSymbol(funcName));
      FileContent* prevFile = prevDef->getFileContent();
      NodeId prevNode = prevDef->getNodeId();
      Location loc2(m_symbols->registerSymbol(prevFile->getFileName(prevNode)),
                    prevFile->Line(prevNode), 0,
                    m_symbols->registerSymbol(funcName));
      Error err(ErrorDefinition::COMP_MULTIPLY_DEFINED_FUNCTION, loc1, loc2);
      m_errors->addError(err);
    }
    m_class->insertFunction(method);
  }
  return true;
}

bool CompileClass::compile_class_constraint_(FileContent* fC,
                                             NodeId class_constraint) {
  NodeId constraint_prototype = fC->Child(class_constraint);
  NodeId constraint_name = fC->Child(constraint_prototype);
  std::string constName = fC->SymName(constraint_name);
  Constraint* prevDef = m_class->getConstraint(constName);
  if (prevDef) {
    Location loc1(m_symbols->registerSymbol(fC->getFileName(class_constraint)),
                  fC->Line(class_constraint), 0,
                  m_symbols->registerSymbol(constName));
    FileContent* prevFile = prevDef->getFileContent();
    NodeId prevNode = prevDef->getNodeId();
    Location loc2(m_symbols->registerSymbol(prevFile->getFileName(prevNode)),
                  prevFile->Line(prevNode), 0,
                  m_symbols->registerSymbol(constName));
    Error err(ErrorDefinition::COMP_MULTIPLY_DEFINED_CONSTRAINT, loc1, loc2);
    m_errors->addError(err);
  }
  Constraint* constraint = new Constraint(fC, class_constraint, constName);
  m_class->insertConstraint(constraint);

  return true;
}

bool CompileClass::compile_type_declaration_(FileContent* fC, NodeId id) {
  /*
    n<> u<8> t<IntegerAtomType_Int> p<9> l<3>
    n<> u<9> t<Data_type> p<11> c<8> s<10> l<3>
    n<my_int> u<10> t<StringConst> p<11> l<3>
    n<> u<11> t<Type_declaration> p<12> c<9> l<3>
    n<> u<12> t<Data_declaration> p<13> c<11> l<3>
    n<> u<13> t<Class_property> p<14> c<12> l<3>
  */
  m_helper.compileTypeDef(m_class, fC, id);

  return true;
}

bool CompileClass::compile_class_declaration_(FileContent* fC, NodeId id) {
  NodeId class_name_id = fC->Child(id);
  std::string class_name =
      m_class->getName() + "::" + fC->SymName(class_name_id);
  ClassDefinition* prevDef = m_class->getClass(class_name);
  if (prevDef) {
    Location loc1(m_symbols->registerSymbol(fC->getFileName(class_name_id)),
                  fC->Line(class_name_id), 0,
                  m_symbols->registerSymbol(class_name));
    FileContent* prevFile = prevDef->getFileContent();
    NodeId prevNode = prevDef->getNodeId();
    Location loc2(m_symbols->registerSymbol(prevFile->getFileName(prevNode)),
                  prevFile->Line(prevNode), 0,
                  m_symbols->registerSymbol(class_name));
    Error err(ErrorDefinition::COMP_MULTIPLY_DEFINED_INNER_CLASS, loc1, loc2);
    m_errors->addError(err);
  }

  ClassDefinition* the_class =
      new ClassDefinition(class_name, m_class->getLibrary(),
                          m_class->getContainer(), fC, class_name_id, m_class);
  m_class->insertClass(the_class);

  CompileClass* instance = new CompileClass(m_compileDesign, the_class,
                                            m_design, m_symbols, m_errors);
  instance->compile();
  delete instance;

  return true;
}

bool CompileClass::compile_covergroup_declaration_(FileContent* fC, NodeId id) {
  NodeId covergroup_name = fC->Child(id);
  std::string covergroupName = fC->SymName(covergroup_name);
  CoverGroupDefinition* prevDef = m_class->getCoverGroup(covergroupName);
  if (prevDef) {
    Location loc1(m_symbols->registerSymbol(fC->getFileName(covergroup_name)),
                  fC->Line(covergroup_name), 0,
                  m_symbols->registerSymbol(covergroupName));
    FileContent* prevFile = prevDef->getFileContent();
    NodeId prevNode = prevDef->getNodeId();
    Location loc2(m_symbols->registerSymbol(prevFile->getFileName(prevNode)),
                  prevFile->Line(prevNode), 0,
                  m_symbols->registerSymbol(covergroupName));
    Error err(ErrorDefinition::COMP_MULTIPLY_DEFINED_COVERGROUP, loc1, loc2);
    m_errors->addError(err);
  }
  CoverGroupDefinition* covergroup =
      new CoverGroupDefinition(fC, id, covergroupName);
  m_class->insertCoverGroup(covergroup);

  return true;
}

bool CompileClass::compile_local_parameter_declaration_(FileContent* fC,
                                                        NodeId id) {
  /*
   n<> u<8> t<IntegerAtomType_Int> p<9> l<3>
   n<> u<9> t<Data_type> p<10> c<8> l<3>
   n<> u<10> t<Data_type_or_implicit> p<20> c<9> s<19> l<3>
   n<FOO> u<11> t<StringConst> p<18> s<17> l<3>
   n<3> u<12> t<IntConst> p<13> l<3>
   n<> u<13> t<Primary_literal> p<14> c<12> l<3>
   n<> u<14> t<Constant_primary> p<15> c<13> l<3>
   n<> u<15> t<Constant_expression> p<16> c<14> l<3>
   n<> u<16> t<Constant_mintypmax_expression> p<17> c<15> l<3>
   n<> u<17> t<Constant_param_expression> p<18> c<16> l<3>
   n<> u<18> t<Param_assignment> p<19> c<11> l<3>
   n<> u<19> t<List_of_param_assignments> p<20> c<18> l<3>
   n<> u<20> t<Local_parameter_declaration> p<21> c<10> l<3>
  */

  NodeId data_type_or_implicit = fC->Child(id);
  NodeId list_of_param_assignments = fC->Sibling(data_type_or_implicit);
  NodeId param_assignment = fC->Child(list_of_param_assignments);
  while (param_assignment) {
    NodeId var = fC->Child(param_assignment);
    std::string name = fC->SymName(var);
    std::pair<FileCNodeId, DesignComponent*>* prevDef =
        m_class->getNamedObject(name);
    if (prevDef) {
      Location loc1(m_symbols->registerSymbol(fC->getFileName(var)),
                    fC->Line(var), 0, m_symbols->registerSymbol(name));
      FileContent* prevFile = prevDef->first.fC;
      NodeId prevNode = prevDef->first.nodeId;
      Location loc2(m_symbols->registerSymbol(prevFile->getFileName(prevNode)),
                    prevFile->Line(prevNode), 0,
                    m_symbols->registerSymbol(name));
      Error err(ErrorDefinition::COMP_MULTIPLY_DEFINED_PARAMETER, loc1, loc2);
      m_errors->addError(err);
    }

    FileCNodeId fnid(fC, id);
    m_class->addObject(VObjectType::slLocal_parameter_declaration, fnid);
    m_class->addNamedObject(name, fnid, NULL);

    param_assignment = fC->Sibling(param_assignment);
  }
  return true;
}

bool CompileClass::compile_parameter_declaration_(FileContent* fC, NodeId id) {
  NodeId data_type_or_implicit = fC->Child(id);
  NodeId list_of_param_assignments = fC->Sibling(data_type_or_implicit);
  NodeId param_assignment = fC->Child(list_of_param_assignments);
  while (param_assignment) {
    NodeId var = fC->Child(param_assignment);
    std::string name = fC->SymName(var);
    std::pair<FileCNodeId, DesignComponent*>* prevDef =
        m_class->getNamedObject(name);
    if (prevDef) {
      Location loc1(m_symbols->registerSymbol(fC->getFileName(var)),
                    fC->Line(var), 0, m_symbols->registerSymbol(name));
      FileContent* prevFile = prevDef->first.fC;
      NodeId prevNode = prevDef->first.nodeId;
      Location loc2(m_symbols->registerSymbol(prevFile->getFileName(prevNode)),
                    prevFile->Line(prevNode), 0,
                    m_symbols->registerSymbol(name));
      Error err(ErrorDefinition::COMP_MULTIPLY_DEFINED_PARAMETER, loc1, loc2);
      m_errors->addError(err);
    }

    FileCNodeId fnid(fC, id);
    m_class->addObject(VObjectType::slLocal_parameter_declaration, fnid);
    m_class->addNamedObject(name, fnid, NULL);

    param_assignment = fC->Sibling(param_assignment);
  }
  return true;
}

bool CompileClass::compile_class_type_(FileContent* fC, NodeId id) {
  NodeId parent = fC->Parent(id);
  VObjectType ptype = fC->Type(parent);
  if (ptype != VObjectType::slClass_declaration) return true;
  NodeId base_class_id = fC->Child(id);
  std::string base_class_name = fC->SymName(base_class_id);
  while (fC->Sibling(base_class_id) &&
         (fC->Type(fC->Sibling(base_class_id)) == VObjectType::slStringConst)) {
    base_class_id = fC->Sibling(base_class_id);
    base_class_name += "::" + fC->SymName(base_class_id);
  }
  // Insert base class placeholder
  // Will be bound in UVMElaboration step
  ClassDefinition* base_class =
      new ClassDefinition(base_class_name, m_class->getLibrary(),
                          m_class->getContainer(), fC, base_class_id, NULL);
  m_class->insertBaseClass(base_class);

  return true;
}

bool CompileClass::compile_class_parameters_(FileContent* fC, NodeId id) {
  /*
  n<all_c> u<1> t<StringConst> p<16> s<14> l<3>
  n<uvm_port_base> u<2> t<StringConst> p<12> s<8> l<7>
  n<IF> u<3> t<StringConst> p<6> s<5> l<7>
  n<uvm_void> u<4> t<StringConst> p<5> l<7>
  n<> u<5> t<Data_type> p<6> c<4> l<7>
  n<> u<6> t<List_of_type_assignments> p<7> c<3> l<7>
  n<> u<7> t<Parameter_port_declaration> p<8> c<6> l<7>
  n<> u<8> t<Parameter_port_list> p<12> c<7> s<10> l<7>
  n<IF> u<9> t<StringConst> p<10> l<7>
  n<> u<10> t<Class_type> p<12> c<9> s<11> l<7>
  n<> u<11> t<Endclass> p<12> l<8>
  n<> u<12> t<Class_declaration> p<13> c<2> l<7>

  or

  n<T1> u<3> t<StringConst> p<9> s<5> l<18>
  n<> u<4> t<IntegerAtomType_Int> p<5> l<18>
  n<> u<5> t<Data_type> p<9> c<4> s<6> l<18>
  n<T2> u<6> t<StringConst> p<9> s<8> l<18>
  n<T1> u<7> t<StringConst> p<8> l<18>
  n<> u<8> t<Data_type> p<9> c<7> l<18>
  n<> u<9> t<List_of_type_assignments> p<10> c<3> l<18>
  n<> u<10> t<Parameter_port_declaration> p<11> c<9> l<18>
  n<> u<11> t<Parameter_port_list> p<31> c<10> s<20> l<18>

  */

  NodeId className = fC->Child(id);
  NodeId paramList = fC->Sibling(className);
  if (fC->Type(paramList) == VObjectType::slParameter_port_list) {
    NodeId parameter_port_declaration = fC->Child(paramList);
    while (parameter_port_declaration) {
      NodeId list_of_type_assignments = fC->Child(parameter_port_declaration);
      NodeId typeNameId = fC->Child(list_of_type_assignments);
      while (typeNameId) {
        NodeId ntype = fC->Sibling(typeNameId);
        bool skip = false;
        if (ntype && fC->Type(ntype) == VObjectType::slData_type) {
          ntype = fC->Child(ntype);
          skip = true;
        } else {
          ntype = 0;
        }
        Parameter* param =
            new Parameter(fC, typeNameId, fC->SymName(typeNameId), ntype);
        m_class->insertParameter(param);
        typeNameId = fC->Sibling(typeNameId);
        if (skip) typeNameId = fC->Sibling(typeNameId);
      }
      parameter_port_declaration = fC->Sibling(parameter_port_declaration);
    }
  }
  return true;
}
