| /* | |
| 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: ElaborationStep.cpp | |
| * Author: alain | |
| * | |
| * Created on July 12, 2017, 8:55 PM | |
| */ | |
| #include "../SourceCompile/VObjectTypes.h" | |
| #include "../Design/VObject.h" | |
| #include "../Library/Library.h" | |
| #include "../Utils/StringUtils.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/ClassDefinition.h" | |
| #include "ElaborationStep.h" | |
| using namespace SURELOG; | |
| ElaborationStep::~ElaborationStep() {} | |
| DataType* ElaborationStep::bindTypeDef_(TypeDef* typd, DesignComponent* parent, | |
| ErrorDefinition::ErrorType errtype) { | |
| Compiler* compiler = m_compileDesign->getCompiler(); | |
| SymbolTable* symbols = compiler->getSymbolTable(); | |
| NodeId defNode = typd->getDefinitionNode(); | |
| FileContent* fC = typd->getFileContent(); | |
| VObjectType defType = fC->Type(defNode); | |
| std::string objName; | |
| if (defType == VObjectType::slStringConst) { | |
| objName = fC->SymName(defNode); | |
| } else { | |
| objName = "NOT_A_VALID_TYPE_NAME"; | |
| symbols->registerSymbol(objName); | |
| } | |
| DataType* result = bindDataType_(objName, fC, defNode, parent, errtype); | |
| if (result != typd) | |
| return result; | |
| else | |
| return NULL; | |
| } | |
| DataType* ElaborationStep::bindDataType_(std::string type_name, FileContent* fC, | |
| NodeId id, DesignComponent* parent, | |
| ErrorDefinition::ErrorType errtype) { | |
| DataType* result = NULL; | |
| Compiler* compiler = m_compileDesign->getCompiler(); | |
| ErrorContainer* errors = compiler->getErrorContainer(); | |
| SymbolTable* symbols = compiler->getSymbolTable(); | |
| Design* design = compiler->getDesign(); | |
| std::string libName = "work"; | |
| if (parent->getFileContents().size()) | |
| libName = parent->getFileContents()[0]->getLibrary()->getName(); | |
| ClassNameClassDefinitionMultiMap classes = design->getClassDefinitions(); | |
| bool found = false; | |
| bool classFound = false; | |
| std::string class_in_lib = libName + "@" + type_name; | |
| ClassNameClassDefinitionMultiMap::iterator itr1 = classes.end(); | |
| if (type_name == "signed") { | |
| result = new DataType(fC, id, type_name, VObjectType::slSigning_Signed); | |
| return result; | |
| } else if (type_name == "unsigned") { | |
| result = new DataType(fC, id, type_name, VObjectType::slSigning_Unsigned); | |
| return result; | |
| } else if (type_name == "logic") { | |
| result = new DataType(fC, id, type_name, VObjectType::slIntVec_TypeLogic); | |
| return result; | |
| } else if (type_name == "bit") { | |
| result = new DataType(fC, id, type_name, VObjectType::slIntVec_TypeBit); | |
| return result; | |
| } else if (type_name == "byte") { | |
| result = | |
| new DataType(fC, id, type_name, VObjectType::slIntegerAtomType_Byte); | |
| return result; | |
| } | |
| if ((result = parent->getDataType(type_name))) { | |
| found = true; | |
| } | |
| if (found == false) { | |
| itr1 = classes.find(class_in_lib); | |
| if (itr1 != classes.end()) { | |
| found = true; | |
| classFound = true; | |
| } | |
| } | |
| if (found == false) { | |
| std::string class_in_class = parent->getName() + "::" + type_name; | |
| itr1 = classes.find(class_in_class); | |
| if (itr1 != classes.end()) { | |
| found = true; | |
| classFound = true; | |
| } | |
| } | |
| if (found == false) { | |
| if (parent->getParentScope()) { | |
| std::string class_in_own_package = | |
| ((DesignComponent*)parent->getParentScope())->getName() + | |
| "::" + type_name; | |
| itr1 = classes.find(class_in_own_package); | |
| if (itr1 != classes.end()) { | |
| found = true; | |
| classFound = true; | |
| } | |
| } | |
| } | |
| if (found == false) { | |
| for (auto package : parent->getAccessPackages()) { | |
| std::string class_in_package = package->getName() + "::" + type_name; | |
| itr1 = classes.find(class_in_package); | |
| if (itr1 != classes.end()) { | |
| found = true; | |
| classFound = true; | |
| break; | |
| } | |
| DataType* dtype = package->getDataType(type_name); | |
| if (dtype) { | |
| found = true; | |
| result = dtype; | |
| break; | |
| } | |
| } | |
| } | |
| if (found == false) { | |
| ClassDefinition* classDefinition = dynamic_cast<ClassDefinition*>(parent); | |
| if (classDefinition) { | |
| if (classDefinition->getName() == type_name) { | |
| result = classDefinition; | |
| found = true; | |
| } | |
| if (found == false) { | |
| Parameter* param = classDefinition->getParameter(type_name); | |
| if (param) { | |
| found = true; | |
| result = param; | |
| } | |
| } | |
| if (found == false) { | |
| if ((result = classDefinition->getBaseDataType(type_name))) { | |
| found = true; | |
| } | |
| } | |
| if (found == false) { | |
| if (classDefinition->getContainer()) { | |
| DataType* dtype = | |
| classDefinition->getContainer()->getDataType(type_name); | |
| if (dtype) { | |
| found = true; | |
| result = dtype; | |
| } | |
| } | |
| } | |
| } | |
| } | |
| if (found == false) { | |
| TypeDef* def = parent->getTypeDef(type_name); | |
| if (def) { | |
| found = true; | |
| result = def; | |
| } | |
| } | |
| if (found == false) { | |
| auto res = parent->getNamedObject(type_name); | |
| if (res) { | |
| DesignComponent* comp = res->second; | |
| result = dynamic_cast<ClassDefinition*>(comp); | |
| if (result) found = true; | |
| } | |
| } | |
| if (found == false) { | |
| auto res = parent->getNamedObject(libName + "@" + type_name); | |
| if (res) { | |
| DesignComponent* comp = res->second; | |
| result = dynamic_cast<ClassDefinition*>(comp); | |
| if (result) found = true; | |
| } | |
| } | |
| if (found == false) { | |
| const char* sname = type_name.c_str(); | |
| if (strstr(sname, "::")) { | |
| std::vector<std::string> args; | |
| StringUtils::tokenizeMulti(type_name, "::", args); | |
| std::string classOrPackageName = args[0]; | |
| std::string the_type_name = args[1]; | |
| itr1 = classes.find(libName + "@" + classOrPackageName); | |
| if (itr1 == classes.end()) { | |
| if (parent->getParentScope()) { | |
| std::string class_in_own_package = | |
| ((DesignComponent*)parent->getParentScope())->getName() + | |
| "::" + classOrPackageName; | |
| itr1 = classes.find(class_in_own_package); | |
| } | |
| } | |
| if (itr1 != classes.end()) { | |
| DataType* dtype = (*itr1).second->getDataType(the_type_name); | |
| if (dtype) { | |
| result = dtype; | |
| found = true; | |
| } | |
| } | |
| if (found == false) { | |
| Package* pack = design->getPackage(classOrPackageName); | |
| if (pack) { | |
| DataType* dtype = pack->getDataType(the_type_name); | |
| if (dtype) { | |
| result = dtype; | |
| found = true; | |
| } | |
| if (found == false) { | |
| dtype = pack->getDataType(type_name); | |
| if (dtype) { | |
| result = dtype; | |
| found = true; | |
| } | |
| } | |
| if (found == false) { | |
| dtype = pack->getClassDefinition(type_name); | |
| if (dtype) { | |
| result = dtype; | |
| found = true; | |
| } | |
| } | |
| } | |
| } | |
| } | |
| } | |
| if ((found == false) && (errtype != ErrorDefinition::NO_ERROR_MESSAGE)) { | |
| std::string fileName = fC->getFileName(id); | |
| unsigned int line = fC->Line(id); | |
| Location loc1(symbols->registerSymbol(fileName), line, 0, | |
| symbols->registerSymbol(type_name)); | |
| Location loc2(0, 0, 0, symbols->registerSymbol(parent->getName())); | |
| Error err1(errtype, loc1, loc2); | |
| errors->addError(err1); | |
| } else { | |
| if (classFound == true) { | |
| // Binding | |
| ClassDefinition* def = (*itr1).second; | |
| result = def; | |
| } | |
| } | |
| while (result && result->getDefinition()) { | |
| result = result->getDefinition(); | |
| } | |
| return result; | |
| } | |
| Variable* ElaborationStep::bindVariable_(std::string var_name, Scope* scope, | |
| FileContent* fC, NodeId id, | |
| DesignComponent* parent, | |
| ErrorDefinition::ErrorType errtype, | |
| bool returnClassParam) { | |
| Compiler* compiler = m_compileDesign->getCompiler(); | |
| ErrorContainer* errors = compiler->getErrorContainer(); | |
| SymbolTable* symbols = compiler->getSymbolTable(); | |
| Variable* result = NULL; | |
| ClassDefinition* classDefinition = dynamic_cast<ClassDefinition*>(parent); | |
| if (classDefinition) result = classDefinition->getProperty(var_name); | |
| if (result == NULL) { | |
| if (scope) { | |
| result = scope->getVariable(var_name); | |
| } | |
| } | |
| if ((result == NULL) && scope) { | |
| Scope* itr_scope = scope; | |
| while (itr_scope) { | |
| Procedure* proc = dynamic_cast<Procedure*>(itr_scope); | |
| if (proc) { | |
| for (auto param : proc->getParams()) { | |
| if (param->getName() == var_name) { | |
| result = param; | |
| break; | |
| } | |
| } | |
| } | |
| if (result) break; | |
| itr_scope = itr_scope->getParentScope(); | |
| } | |
| } | |
| if (result == NULL && parent) { | |
| for (auto package : parent->getAccessPackages()) { | |
| Value* val = package->getValue(var_name); | |
| if (val) { | |
| break; | |
| } | |
| } | |
| } | |
| if ((result == NULL) && (errtype != ErrorDefinition::NO_ERROR_MESSAGE)) { | |
| std::string fileName = fC->getFileName(id); | |
| unsigned int line = fC->Line(id); | |
| Location loc1(symbols->registerSymbol(fileName), line, 0, | |
| symbols->registerSymbol(var_name)); | |
| Location loc2(0, 0, 0, symbols->registerSymbol(parent->getName())); | |
| Error err1(errtype, loc1, loc2); | |
| errors->addError(err1); | |
| } | |
| if (!returnClassParam) { | |
| // Class parameters datatype have no definition and are strings | |
| if (result) { | |
| DataType* dtype = result->getDataType(); | |
| if (dtype && !dtype->getDefinition()) { | |
| if (dtype->getType() == VObjectType::slStringConst) { | |
| result = NULL; | |
| } | |
| } | |
| } | |
| } | |
| return result; | |
| } | |
| Variable* ElaborationStep::locateVariable_(std::vector<std::string>& var_chain, | |
| FileContent* fC, NodeId id, | |
| Scope* scope, | |
| DesignComponent* parentComponent, | |
| ErrorDefinition::ErrorType errtype) { | |
| Variable* the_obj = NULL; | |
| DesignComponent* currentComponent = parentComponent; | |
| for (auto var : var_chain) { | |
| if (var == "this") { | |
| } else if (var == "super") { | |
| ClassDefinition* classDefinition = | |
| dynamic_cast<ClassDefinition*>(currentComponent); | |
| if (classDefinition) { | |
| currentComponent = NULL; | |
| for (auto cc : classDefinition->getBaseClassMap()) { | |
| currentComponent = dynamic_cast<ClassDefinition*>(cc.second); | |
| var = "this"; | |
| break; | |
| } | |
| if (currentComponent == NULL) { | |
| var = "super"; | |
| currentComponent = parentComponent; | |
| } | |
| } | |
| } | |
| the_obj = | |
| bindVariable_(var, scope, fC, id, currentComponent, errtype, false); | |
| if (the_obj) { | |
| DataType* dtype = the_obj->getDataType(); | |
| while (dtype && dtype->getDefinition()) { | |
| dtype = dtype->getDefinition(); | |
| } | |
| ClassDefinition* tmpClass = dynamic_cast<ClassDefinition*>(dtype); | |
| if (tmpClass) { | |
| currentComponent = tmpClass; | |
| } | |
| } | |
| } | |
| return the_obj; | |
| } | |
| Variable* ElaborationStep::locateStaticVariable_( | |
| std::vector<std::string>& var_chain, FileContent* fC, NodeId id, | |
| Scope* scope, DesignComponent* parentComponent, | |
| ErrorDefinition::ErrorType errtype) { | |
| std::string name; | |
| for (unsigned int i = 0; i < var_chain.size(); i++) { | |
| name += var_chain[i]; | |
| if (i < var_chain.size() - 1) name += "::"; | |
| } | |
| std::map<std::string, Variable*>::iterator itr = m_staticVariables.find(name); | |
| if (itr != m_staticVariables.end()) return (*itr).second; | |
| Variable* result = NULL; | |
| Design* design = m_compileDesign->getCompiler()->getDesign(); | |
| if (var_chain.size() > 0) { | |
| Package* package = design->getPackage(var_chain[0]); | |
| if (package) { | |
| if (var_chain.size() > 1) { | |
| ClassDefinition* classDefinition = | |
| package->getClassDefinition(var_chain[1]); | |
| if (classDefinition) { | |
| if (var_chain.size() == 2) { | |
| result = new Variable( | |
| classDefinition, classDefinition->getFileContent(), | |
| classDefinition->getNodeId(), 0, classDefinition->getName()); | |
| } | |
| if (var_chain.size() == 3) { | |
| std::vector<std::string> tmp; | |
| tmp.push_back(var_chain[2]); | |
| result = | |
| locateVariable_(tmp, fC, id, scope, classDefinition, errtype); | |
| } | |
| } | |
| } | |
| } | |
| if (result == NULL) { | |
| ClassDefinition* classDefinition = | |
| design->getClassDefinition(var_chain[0]); | |
| if (classDefinition == NULL) { | |
| std::string name; | |
| if (parentComponent && parentComponent->getParentScope()) { | |
| name = | |
| ((DesignComponent*)parentComponent->getParentScope())->getName(); | |
| name += "::" + var_chain[0]; | |
| classDefinition = design->getClassDefinition(name); | |
| } | |
| } | |
| if (classDefinition) { | |
| if (var_chain.size() == 1) | |
| result = new Variable( | |
| classDefinition, classDefinition->getFileContent(), | |
| classDefinition->getNodeId(), 0, classDefinition->getName()); | |
| if (var_chain.size() == 2) { | |
| std::vector<std::string> tmp; | |
| tmp.push_back(var_chain[1]); | |
| DataType* dtype = bindDataType_(var_chain[1], fC, id, classDefinition, | |
| ErrorDefinition::NO_ERROR_MESSAGE); | |
| if (dtype) { | |
| result = new Variable(dtype, dtype->getFileContent(), | |
| dtype->getNodeId(), 0, dtype->getName()); | |
| } else | |
| result = | |
| locateVariable_(tmp, fC, id, scope, classDefinition, errtype); | |
| } | |
| } | |
| } | |
| } | |
| if (result == NULL) { | |
| if (var_chain.size()) { | |
| DataType* dtype = | |
| bindDataType_(var_chain[0], fC, id, parentComponent, errtype); | |
| if (dtype) { | |
| result = new Variable(dtype, dtype->getFileContent(), | |
| dtype->getNodeId(), 0, dtype->getName()); | |
| } | |
| } | |
| } | |
| m_staticVariables.insert(std::make_pair(name, result)); | |
| return result; | |
| } |