/*
 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:   TestbenchElaboration.cpp
 * Author: alain
 *
 * Created on February 6, 2019, 9:01 PM
 */

#include <queue>

#include "SourceCompile/VObjectTypes.h"
#include "Design/VObject.h"
#include "Library/Library.h"
#include "Design/FileContent.h"
#include "SourceCompile/SymbolTable.h"
#include "ErrorReporting/Error.h"
#include "ErrorReporting/Location.h"
#include "ErrorReporting/Error.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 "CompileDesign.h"
#include "Testbench/Property.h"
#include "Design/Function.h"
#include "Testbench/ClassDefinition.h"
#include "TestbenchElaboration.h"

using namespace SURELOG;

TestbenchElaboration::~TestbenchElaboration() {}

bool TestbenchElaboration::bindTypedefs_() {
  Compiler* compiler = m_compileDesign->getCompiler();
  ErrorContainer* errors = compiler->getErrorContainer();
  SymbolTable* symbols = compiler->getSymbolTable();
  Design* design = compiler->getDesign();

  std::vector<std::pair<TypeDef*, DesignComponent*>> defs;

  for (auto file : design->getAllFileContents()) {
    FileContent* fC = file.second;
    for (auto typed : fC->getTypeDefMap()) {
      TypeDef* typd = typed.second;
      defs.push_back(std::make_pair(typd, fC));
    }
  }

  for (auto package : design->getPackageDefinitions()) {
    Package* pack = package.second;
    for (auto typed : pack->getTypeDefMap()) {
      TypeDef* typd = typed.second;
      defs.push_back(std::make_pair(typd, pack));
    }
  }

  for (auto program_def : design->getProgramDefinitions()) {
    Program* program = program_def.second;
    for (auto typed : program->getTypeDefMap()) {
      TypeDef* typd = typed.second;
      defs.push_back(std::make_pair(typd, program));
    }
  }

  for (auto class_def : design->getClassDefinitions()) {
    ClassDefinition* classp = class_def.second;
    for (auto typed : classp->getTypeDefMap()) {
      TypeDef* typd = typed.second;
      defs.push_back(std::make_pair(typd, classp));
    }
  }

  for (auto def : defs) {
    TypeDef* typd = def.first;
    DesignComponent* comp = def.second;
    if (typd->getDefinition() == NULL) {
      DataType* def =
          bindTypeDef_(typd, comp, ErrorDefinition::NO_ERROR_MESSAGE);
      if (def && (typd != def)) {
        typd->setDefinition(def);
      } else {
        FileContent* fC = typd->getFileContent();
        NodeId id = typd->getNodeId();
        std::string fileName = fC->getFileName(id);
        unsigned int line = fC->Line(id);
        std::string definition_string;
        NodeId defNode = typd->getDefinitionNode();
        VObjectType defType = fC->Type(defNode);
        if (defType == VObjectType::slStringConst) {
          definition_string = fC->SymName(defNode);
        }
        Location loc1(symbols->registerSymbol(fileName), line, 0,
                      symbols->registerSymbol(definition_string));
        Error err1(ErrorDefinition::COMP_UNDEFINED_TYPE, loc1);
        errors->addError(err1);
      }
    }
  }

  return true;
}

bool checkValidFunction(DataType* dtype, std::string function, Statement* stmt,
                        Design* design, std::string& datatypeName) {
  bool validFunction = true;
  VObjectType type = dtype->getType();
  DataType* def = dtype->getDefinition();
  if (type == VObjectType::slClass_declaration) {
    ClassDefinition* the_class = dynamic_cast<ClassDefinition*>(dtype);
    if (the_class) {
      Function* func = the_class->getFunction(function);
      if (func)
        stmt->setFunction(func);
      else
        validFunction = false;
    } else {
      the_class = dynamic_cast<ClassDefinition*>(def);
      if (the_class) {
        Function* func = the_class->getFunction(function);
        if (func)
          stmt->setFunction(func);
        else
          validFunction = false;
      }
    }
  } else if (dtype->isString_type(type)) {
    ClassDefinition* array = design->getClassDefinition("builtin::string");
    Function* func = array->getFunction(function);
    if (func)
      stmt->setFunction(func);
    else {
      datatypeName = "string";
      validFunction = false;
    }
  } else
    validFunction = false;
  return validFunction;
}

bool checkValidBuiltinClass_(std::string classname, std::string function,
                             Statement* stmt, Design* design,
                             std::string& datatypeName) {
  bool validFunction = true;
  ClassDefinition* array = design->getClassDefinition("builtin::" + classname);
  Function* func = array->getFunction(function);
  if (func)
    stmt->setFunction(func);
  else {
    datatypeName = classname;
    validFunction = false;
  }
  return validFunction;
}

void computeVarChain(FileContent* fC, NodeId nodeId,
                     std::vector<std::string>& var_chain) {
  while (nodeId) {
    VObjectType type = fC->Type(nodeId);
    switch (type) {
      case VObjectType::slStringConst: {
        var_chain.push_back(fC->SymName(nodeId));
        break;
      }
      case VObjectType::slImplicit_class_handle: {
        NodeId child = fC->Child(nodeId);
        VObjectType childType = fC->Type(child);
        if (childType == VObjectType::slThis_keyword)
          var_chain.push_back("this");
        else if (childType == VObjectType::slSuper_keyword)
          var_chain.push_back("super");
        else
          var_chain.push_back("UNKNOWN_TYPE");
        break;
      }
      default:
        var_chain.push_back("UNKNOWN_NAME");
        break;
    }
    nodeId = fC->Sibling(nodeId);
  }
}

bool TestbenchElaboration::bindClasses_() {
  checkForMultipleDefinition_();
  bindBaseClasses_();
  bindDataTypes_();
  bindFunctions_();
  bindTasks_();
  return true;
}

bool TestbenchElaboration::checkForMultipleDefinition_() {
  Compiler* compiler = m_compileDesign->getCompiler();
  ErrorContainer* errors = compiler->getErrorContainer();
  SymbolTable* symbols = compiler->getSymbolTable();
  Design* design = compiler->getDesign();
  ClassNameClassDefinitionMultiMap classes = design->getClassDefinitions();

  // Check for multiple definition
  std::string prevClassName = "";
  ClassDefinition* prevClassDefinition = NULL;
  for (ClassNameClassDefinitionMultiMap::iterator itr = classes.begin();
       itr != classes.end(); itr++) {
    std::string className = (*itr).first;
    ClassDefinition* classDefinition = (*itr).second;
    bool done = false;
    if (className == prevClassName) {
      FileContent* fC1 = classDefinition->getFileContents()[0];
      NodeId nodeId1 = classDefinition->getNodeIds()[0];
      std::string fileName1 = fC1->getFileName(nodeId1);
      unsigned int line1 = fC1->Line(nodeId1);
      Location loc1(symbols->registerSymbol(fileName1), line1, 0,
                    symbols->registerSymbol(className));

      std::vector<Location> locations;

      while (1) {
        FileContent* fC2 = prevClassDefinition->getFileContents()[0];
        NodeId nodeId2 = prevClassDefinition->getNodeIds()[0];
        std::string fileName2 = fC2->getFileName(nodeId2);
        unsigned int line2 = fC2->Line(nodeId2);
        Location loc2(symbols->registerSymbol(fileName2), line2, 0,
                      symbols->registerSymbol(className));

        if ((fileName1 != fileName2) || (line1 != line2)) {
          std::string diff;
          if (fC1->diffTree(diff, nodeId1, fC2, nodeId2)) {
            locations.push_back(loc2);
          }
        }

        itr++;
        if (itr == classes.end()) {
          done = true;
          break;
        } else {
          std::string nextClassName = (*itr).first;
          ClassDefinition* nextClassDefinition = (*itr).second;
          prevClassName = nextClassName;
          prevClassDefinition = nextClassDefinition;
          if (prevClassName != className) {
            className = prevClassName;
            classDefinition = prevClassDefinition;
            break;
          }
        }
      }

      if (locations.size()) {
        Error err1(ErrorDefinition::COMP_MULTIPLY_DEFINED_CLASS, loc1,
                   &locations);
        errors->addError(err1);
      }
    }
    prevClassName = className;
    prevClassDefinition = classDefinition;
    if (done) break;
  }
  return true;
}

bool TestbenchElaboration::bindBaseClasses_() {
  Compiler* compiler = m_compileDesign->getCompiler();
  Design* design = compiler->getDesign();
  ClassNameClassDefinitionMultiMap classes = design->getClassDefinitions();

  // Bind base classes
  for (ClassNameClassDefinitionMultiMap::iterator itr = classes.begin();
       itr != classes.end(); itr++) {
    std::string className = (*itr).first;
    ClassDefinition* classDefinition = (*itr).second;
    for (auto& class_def : classDefinition->getBaseClassMap()) {
      DataType* the_def =
          bindDataType_(class_def.first, class_def.second->getFileContent(),
                        class_def.second->getNodeId(), classDefinition,
                        ErrorDefinition::COMP_UNDEFINED_BASE_CLASS);
      class_def.second = dynamic_cast<ClassDefinition*>(the_def);
      if (class_def.second) {
        // Super
        DataType* thisdt = new DataType(
            class_def.second->getFileContent(), class_def.second->getNodeId(),
            class_def.second->getName(), VObjectType::slClass_declaration);
        thisdt->setDefinition(class_def.second);
        Property* prop = new Property(thisdt, classDefinition->getFileContent(),
                                      classDefinition->getNodeId(), 0, "super",
                                      false, false, false, false, false);
        classDefinition->insertProperty(prop);
      } else {
        class_def.second = dynamic_cast<Parameter*>(the_def);
        if (class_def.second) {
          // Super
          DataType* thisdt = new DataType(
              class_def.second->getFileContent(), class_def.second->getNodeId(),
              class_def.second->getName(), VObjectType::slClass_declaration);
          thisdt->setDefinition(class_def.second);
          Property* prop =
              new Property(thisdt, classDefinition->getFileContent(),
                           classDefinition->getNodeId(), 0, "super", false,
                           false, false, false, false);
          classDefinition->insertProperty(prop);
        }
      }
    }
  }
  return true;
}

bool TestbenchElaboration::bindDataTypes_() {
  Compiler* compiler = m_compileDesign->getCompiler();
  Design* design = compiler->getDesign();
  ClassNameClassDefinitionMultiMap classes = design->getClassDefinitions();

  // Bind data types
  for (ClassNameClassDefinitionMultiMap::iterator itr = classes.begin();
       itr != classes.end(); itr++) {
    std::string className = (*itr).first;
    ClassDefinition* classDefinition = (*itr).second;

    for (auto& datatype : classDefinition->getUsedDataTypeMap()) {
      std::string dataTypeName = datatype.first;
      DataType* dtype = datatype.second;
      if (dtype->getDefinition()) continue;
      VObjectType type = dtype->getType();
      if (type == VObjectType::slStringConst ||
          type == VObjectType::slNull_rule ||
          type == VObjectType::slClass_scope) {
        DataType* the_def = bindDataType_(dataTypeName, dtype->getFileContent(),
                                          dtype->getNodeId(), classDefinition,
                                          ErrorDefinition::COMP_UNDEFINED_TYPE);
        if (the_def != dtype) dtype->setDefinition(the_def);
      }
    }
    for (auto& func : classDefinition->getFunctionMap()) {
      for (auto& datatype : func.second->getUsedDataTypeMap()) {
        std::string dataTypeName = datatype.first;
        DataType* dtype = datatype.second;
        if (dtype->getDefinition()) continue;
        VObjectType type = dtype->getType();
        if (type == VObjectType::slStringConst ||
            type == VObjectType::slNull_rule ||
            type == VObjectType::slClass_scope) {
          DataType* the_def = bindDataType_(
              dataTypeName, dtype->getFileContent(), dtype->getNodeId(),
              classDefinition, ErrorDefinition::COMP_UNDEFINED_TYPE);
          if (the_def != dtype) dtype->setDefinition(the_def);
        }
      }
    }
  }
  return true;
}

bool TestbenchElaboration::bindFunctions_() {
  bindFunctionReturnTypesAndParamaters_();
  bindFunctionBodies_();
  return true;
}

bool TestbenchElaboration::bindFunctionReturnTypesAndParamaters_() {
  Compiler* compiler = m_compileDesign->getCompiler();
  ErrorContainer* errors = compiler->getErrorContainer();
  SymbolTable* symbols = compiler->getSymbolTable();
  Design* design = compiler->getDesign();
  ClassNameClassDefinitionMultiMap classes = design->getClassDefinitions();

  // Bind Function return values, parameters and body
  for (ClassNameClassDefinitionMultiMap::iterator itr = classes.begin();
       itr != classes.end(); itr++) {
    std::string className = (*itr).first;
    ClassDefinition* classDefinition = (*itr).second;
    for (auto& func : classDefinition->getFunctionMap()) {
      DataType* dtype = func.second->getReturnType();
      std::string dataTypeName = dtype->getName();
      if (dtype->getDefinition()) continue;
      if (dtype->getFileContent() == NULL) continue;
      if (dtype->getType() == VObjectType::slStringConst) {
        DataType* the_def = bindDataType_(
            dataTypeName, dtype->getFileContent(), func.second->getNodeId(),
            classDefinition, ErrorDefinition::COMP_UNDEFINED_TYPE);
        if (the_def != dtype) dtype->setDefinition(the_def);
      }
      for (auto& param : func.second->getParams()) {
        DataType* dtype = param->getDataType();
        std::string dataTypeName = dtype->getName();
        if (dtype->getDefinition()) continue;
        if (dtype->getFileContent() == NULL) continue;
        if (dtype->getType() == VObjectType::slStringConst) {
          DataType* the_def = bindDataType_(
              dataTypeName, dtype->getFileContent(), param->getNodeId(),
              classDefinition, ErrorDefinition::COMP_UNDEFINED_TYPE);
          if (the_def != dtype) dtype->setDefinition(the_def);
          if (the_def && the_def->isParameter()) continue;
          Value* value = param->getDefault();
          if (value) {
            if (!dtype->isCompatible(value)) {
              std::string name = param->getName();
              std::string typeName = dtype->getName();
              NodeId p = param->getNodeId();
              FileContent* fC = dtype->getFileContent();
              std::string fileName = fC->getFileName(p);
              unsigned int line = fC->Line(p);
              Location loc1(
                  symbols->registerSymbol(fileName), line, 0,
                  symbols->registerSymbol(name + " of type " + typeName));
              std::string exp;
              if (value->getType() == Value::String)
                exp = value->getValueS();
              else if (value->getType() == Value::Double)
                exp = std::to_string(value->getValueD(0));
              else
                exp = std::to_string(value->getValueL(0));
              Location loc2(0, 0, 0, symbols->registerSymbol(exp));
              Error err1(ErrorDefinition::COMP_INCOMPATIBLE_TYPES, loc1, loc2);
              errors->addError(err1);
            }
          }
        }
      }
    }
  }
  return true;
}

bool TestbenchElaboration::bindSubRoutineCall_(ClassDefinition* classDefinition,
                                               Statement* stmt, Design* design,
                                               SymbolTable* symbols,
                                               ErrorContainer* errors) {
  std::string datatypeName;
  SubRoutineCallStmt* st = dynamic_cast<SubRoutineCallStmt*>(stmt);
  std::vector<std::string> var_chain = st->getVarChainNames();
  std::string function = st->getFunc();
  bool validFunction = true;
  DataType* dtype = NULL;
  Variable* the_obj = NULL;
  if (st->isStatic())
    the_obj = locateStaticVariable_(
        var_chain, st->getFileContent(), st->getNodeId(), stmt->getScope(),
        classDefinition, ErrorDefinition::ELAB_UNDEF_VARIABLE);
  else
    the_obj = locateVariable_(var_chain, st->getFileContent(), st->getNodeId(),
                              stmt->getScope(), classDefinition,
                              ErrorDefinition::ELAB_UNDEF_VARIABLE);

  if (the_obj) {
    dtype = the_obj->getDataType();
    if (dtype == NULL) return true;
    VObjectType type = dtype->getType();
    DataType* def = dtype->getDefinition();

    if (type == VObjectType::slClass_declaration) {
      validFunction =
          checkValidFunction(dtype, function, stmt, design, datatypeName);
    } else if (dtype->isNumber(type) || dtype->isInteger_type(type) ||
               dtype->isNon_integer_type(type) || dtype->isString_type(type)) {
      if (def) {
        type = def->getType();
        dtype = def;
      }

      NodeId range = the_obj->getRange();
      if (range) {
        VObjectType rangeType = the_obj->getFileContent()->Type(range);

        if (rangeType == VObjectType::slUnsized_dimension) {
          // Vector
          validFunction = checkValidBuiltinClass_("array", function, stmt,
                                                  design, datatypeName);
        } else if (rangeType == VObjectType::slVariable_dimension) {
          FileContent* sfC = the_obj->getFileContent();
          NodeId subRange = sfC->Child(range);
          VObjectType the_type = sfC->Type(subRange);
          if (the_type == VObjectType::slQueue_dimension) {
            // Queue

            // foreach (darray[id]) darray[id].func()
            NodeId tmp = stmt->getNodeId();
            tmp = sfC->Child(tmp);
            tmp = sfC->Sibling(tmp);
            VObjectType t = sfC->Type(tmp);
            if ((t == VObjectType::slConstant_bit_select) && sfC->Child(tmp)) {
              // there is an actual array index
              if (type == VObjectType::slClass_declaration) {
                validFunction = checkValidFunction(dtype, function, stmt,
                                                   design, datatypeName);
              }
            } else {
              validFunction = checkValidBuiltinClass_("queue", function, stmt,
                                                      design, datatypeName);
            }
          } else if (the_type == VObjectType::slUnpacked_dimension) {
            // foreach (darray[id]) darray[id].func()
            NodeId subroutine_call = stmt->getNodeId();
            NodeId var_id = sfC->Child(subroutine_call);
            NodeId constant_bit_select = sfC->Sibling(var_id);
            VObjectType t = sfC->Type(constant_bit_select);
            NodeId select_id = sfC->Child(constant_bit_select);
            if ((t == VObjectType::slConstant_bit_select) && select_id) {
              validFunction = checkValidFunction(dtype, function, stmt, design,
                                                 datatypeName);
            } else {
              validFunction = checkValidBuiltinClass_("queue", function, stmt,
                                                      design, datatypeName);
            }
          }
        }
      } else {
        validFunction =
            checkValidFunction(dtype, function, stmt, design, datatypeName);
      }
    }
  }
  if (var_chain.size() == 0) {
    if (st->isSystemCall()) {
      validFunction = checkValidBuiltinClass_("system", function, stmt, design,
                                              datatypeName);
      if (!validFunction) {
        FileContent* fC = st->getFileContent();
        NodeId p = st->getNodeId();
        std::string fileName = fC->getFileName(p);
        unsigned int line = fC->Line(p);
        Location loc1(symbols->registerSymbol(fileName), line, 0,
                      symbols->registerSymbol(function));
        Error err1(ErrorDefinition::COMP_UNDEFINED_SYSTEM_FUNCTION, loc1);
        errors->addError(err1);
        return true;
      }
    } else {
      Function* func = classDefinition->getFunction(function);
      if (func)
        stmt->setFunction(func);
      else {
        validFunction = false;
        dtype = classDefinition;
      }
    }
  }

  if (validFunction == false) {
    if (dtype->isParameter()) {
      return true;
    }
    std::string name;
    for (auto v : var_chain) name += v + ".";
    if (name.size()) name = name.substr(0, name.size() - 1);
    while (dtype && dtype->getDefinition()) {
      dtype = dtype->getDefinition();
    }
    if (name == "") {
      name = "this";
    }
    std::string typeName = dtype->getName();
    if (datatypeName != "") typeName = datatypeName;
    NodeId p = st->getNodeId();
    FileContent* fC = st->getFileContent();
    std::string fileName = fC->getFileName(p);
    unsigned int line = fC->Line(p);
    Location loc1(
        symbols->registerSymbol(fileName), line, 0,
        symbols->registerSymbol("\"" + name + "\"" + " of type " + typeName));
    FileContent* fC2 = dtype->getFileContent();
    std::string fileName2 = fC2->getFileName(dtype->getNodeId());
    unsigned int line2 = fC2->Line(dtype->getNodeId());
    Location loc2(symbols->registerSymbol(fileName2), line2, 0,
                  symbols->registerSymbol(function));
    Error err1(ErrorDefinition::COMP_NO_METHOD_FOR_TYPE, loc1, loc2);
    errors->addError(err1);
  }
  return true;
}

bool TestbenchElaboration::bindForLoop_(ClassDefinition* classDefinition,
                                        Statement* stmt, ForLoopStmt* st) {
  FileContent* sfC = st->getFileContent();
  NodeId fid = st->getNodeId();
  VObjectType itr_type = st->getIteratorType();
  DataType* itrDataType = new DataType(sfC, fid, "integer", itr_type);
  for (auto itrId : st->getIteratorIds()) {
    Variable* var = new Variable(itrDataType, sfC, itrId.first, 0,
                                 sfC->SymName(itrId.first));
    st->getParentScope()->addVariable(var);
  }
  return true;
}

bool TestbenchElaboration::bindForeachLoop_(ClassDefinition* classDefinition,
                                            Statement* stmt,
                                            ForeachLoopStmt* st) {
  NodeId arrayId = st->getArrayId();
  FileContent* sfC = st->getFileContent();
  std::vector<std::string> var_chain;
  computeVarChain(sfC, arrayId, var_chain);
  Variable* arrayVar =
      locateVariable_(var_chain, sfC, arrayId, stmt->getScope(),
                      classDefinition, ErrorDefinition::ELAB_UNDEF_VARIABLE);
  if (arrayVar) {
    NodeId range = arrayVar->getRange();
    NodeId rangeTypeId = range;
    DataType* itrDataType = NULL;
    while (range) {
      rangeTypeId = range;
      range = sfC->Child(rangeTypeId);
    }
    VObjectType rangeType = sfC->Type(rangeTypeId);
    if (rangeType == VObjectType::slStringConst) {
      std::string dataTypeName = sfC->SymName(rangeTypeId);
      itrDataType =
          bindDataType_(dataTypeName, sfC, rangeTypeId, classDefinition,
                        ErrorDefinition::COMP_UNDEFINED_TYPE);
    } else if (rangeType == VObjectType::slAssociative_dimension ||
               rangeType == VObjectType::slQueue_dimension) {
      // Integer Type
      itrDataType = new DataType(sfC, arrayId, "integer",
                                 VObjectType::slIntegerAtomType_Int);
    }

    for (auto itrId : st->getIteratorIds()) {
      Variable* var =
          new Variable(itrDataType, sfC, itrId, 0, sfC->SymName(itrId));
      st->getParentScope()->addVariable(var);
    }
  }
  return true;
}

bool TestbenchElaboration::bindFunctionBodies_() {
  Compiler* compiler = m_compileDesign->getCompiler();
  ErrorContainer* errors = compiler->getErrorContainer();
  SymbolTable* symbols = compiler->getSymbolTable();
  Design* design = compiler->getDesign();
  ClassNameClassDefinitionMultiMap classes = design->getClassDefinitions();

  // Bind Function return values, parameters and body
  for (ClassNameClassDefinitionMultiMap::iterator itr = classes.begin();
       itr != classes.end(); itr++) {
    std::string className = (*itr).first;
    ClassDefinition* classDefinition = (*itr).second;
    for (auto& func : classDefinition->getFunctionMap()) {
      // Skip binding of parameterized classes
      if (!classDefinition->hasCompleteBaseSpecification()) continue;

      std::queue<Statement*> stmts;
      for (Statement* stmt : func.second->getStmts()) stmts.push(stmt);

      while (stmts.size()) {
        Statement* stmt = stmts.front();
        stmts.pop();
        for (Statement* stmt1 : stmt->getStatements()) stmts.push(stmt1);
        VObjectType stmt_type = stmt->getType();
        switch (stmt_type) {
          case VObjectType::slPs_or_hierarchical_array_identifier: {
            // Foreach loop
            ForeachLoopStmt* st = dynamic_cast<ForeachLoopStmt*>(stmt);
            if (st) {
              bindForeachLoop_(classDefinition, stmt, st);
            }
            break;
          }
          case VObjectType::slFor_initialization: {
            // For loop
            ForLoopStmt* st = dynamic_cast<ForLoopStmt*>(stmt);
            if (st) {
              bindForLoop_(classDefinition, stmt, st);
            }
            break;
          }
          case VObjectType::slSubroutine_call_statement:
            bindSubRoutineCall_(classDefinition, stmt, design, symbols, errors);
            break;
          default:
            break;
        }
      }
    }
  }
  return true;
}

bool TestbenchElaboration::bindTasks_() {
  Compiler* compiler = m_compileDesign->getCompiler();
  // ErrorContainer* errors = compiler->getErrorContainer ();
  // SymbolTable* symbols = compiler->getSymbolTable ();
  Design* design = compiler->getDesign();
  ClassNameClassDefinitionMultiMap classes = design->getClassDefinitions();

  // Bind Tasks parameters and body
  for (ClassNameClassDefinitionMultiMap::iterator itr = classes.begin();
       itr != classes.end(); itr++) {
    std::string className = (*itr).first;
    ClassDefinition* classDefinition = (*itr).second;

    // Bind Tasks parameters
    for (auto& func : classDefinition->getTaskMap()) {
      for (auto param : func.second->getParams()) {
        DataType* dtype = param->getDataType();
        std::string dataTypeName = dtype->getName();
        if (dtype->getDefinition()) continue;
        if (dtype->getFileContent() == NULL) continue;
        if (dtype->getType() == VObjectType::slStringConst) {
          DataType* the_def = bindDataType_(
              dataTypeName, dtype->getFileContent(), param->getNodeId(),
              classDefinition, ErrorDefinition::COMP_UNDEFINED_TYPE);
          if (the_def != dtype) dtype->setDefinition(the_def);
        }
      }
    }
  }
  return true;
}
