| /* |
| 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) && (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; |
| } |
| |