void AddNamespaceDataTypeTemplateVariableTypes(Context& context, const AST::Node<AST::NamespaceData>& astNamespaceDataNode) { const auto semNamespace = context.scopeStack().back().nameSpace(); for (auto astModuleScopeNode: astNamespaceDataNode->moduleScopes) { AddNamespaceDataTypeTemplateVariableTypes(context, astModuleScopeNode->data); } for (auto astNamespaceNode: astNamespaceDataNode->namespaces) { auto& semChildNamespace = semNamespace->items().at(astNamespaceNode->name).nameSpace(); PushScopeElement pushScopeElement(context.scopeStack(), ScopeElement::Namespace(&semChildNamespace)); AddNamespaceDataTypeTemplateVariableTypes(context, astNamespaceNode->data); } for (auto astAliasNode: astNamespaceDataNode->aliases) { auto& semChildAlias = semNamespace->items().at(astAliasNode->name).alias(); PushScopeElement pushScopeElement(context.scopeStack(), ScopeElement::Alias(&semChildAlias)); AddAliasTemplateVariableTypes(context, astAliasNode); } for (auto astTypeInstanceNode: astNamespaceDataNode->typeInstances) { auto& semChildTypeInstance = semNamespace->items().at(astTypeInstanceNode->name).typeInstance(); PushScopeElement pushScopeElement(context.scopeStack(), ScopeElement::TypeInstance(&semChildTypeInstance)); AddTypeInstanceTemplateVariableTypes(context, astTypeInstanceNode); } }
void AddNamespaceDataAliasValues(Context& context, const AST::Node<AST::NamespaceData>& astNamespaceDataNode) { const auto semNamespace = context.scopeStack().back().nameSpace(); for (const auto& astAliasNode: astNamespaceDataNode->aliases) { auto& semAlias = semNamespace->items().at(astAliasNode->name).alias(); PushScopeElement pushScopeElement(context.scopeStack(), ScopeElement::Alias(&semAlias)); semAlias.setValue(ConvertValue(context, astAliasNode->value)); } for (const auto& astChildNamespaceNode: astNamespaceDataNode->namespaces) { auto& semChildNamespace = semNamespace->items().at(astChildNamespaceNode->name).nameSpace(); PushScopeElement pushScopeElement(context.scopeStack(), ScopeElement::Namespace(&semChildNamespace)); AddNamespaceDataAliasValues(context, astChildNamespaceNode->data); } for (const auto& astModuleScopeNode: astNamespaceDataNode->moduleScopes) { AddNamespaceDataAliasValues(context, astModuleScopeNode->data); } }
void EvaluateNamespaceStaticAsserts(Context& context, const AST::Node<AST::NamespaceData>& astNamespaceDataNode) { for (const auto& astStaticAssertNode: astNamespaceDataNode->staticAsserts) { const auto& astPredicateNode = astStaticAssertNode->expression(); const auto astPredicate = ConvertPredicate(context, astPredicateNode); auto evaluateResult = evaluatePredicate(context, astPredicate, AST::TemplateVarMap()); if (evaluateResult.failed()) { context.issueDiag(StaticAssertPredicateIsFalseDiag(), astPredicateNode.location(), std::move(evaluateResult)); } } for (const auto& astNamespaceNode: astNamespaceDataNode->namespaces) { auto& astChildNamespace = astNamespaceNode->nameSpace(); PushScopeElement pushScopeElement(context.scopeStack(), ScopeElement::Namespace(astChildNamespace)); EvaluateNamespaceStaticAsserts(context, astNamespaceNode->data()); } }
void AddNamespaceData(Context& context, const AST::Node<AST::NamespaceData>& astNamespaceDataNode, const SEM::ModuleScope& moduleScope) { const auto semNamespace = context.scopeStack().back().nameSpace(); for (const auto& astChildNamespaceNode: astNamespaceDataNode->namespaces) { const auto& childNamespaceName = astChildNamespaceNode->name; SEM::Namespace* semChildNamespace = nullptr; const auto iterator = semNamespace->items().find(childNamespaceName); if (iterator == semNamespace->items().end()) { std::unique_ptr<SEM::Namespace> childNamespace(new SEM::Namespace(semNamespace->name() + childNamespaceName, *semNamespace)); semChildNamespace = childNamespace.get(); semNamespace->items().insert(std::make_pair(childNamespaceName, SEM::NamespaceItem::Namespace(std::move(childNamespace)))); } else { semChildNamespace = &(iterator->second.nameSpace()); } PushScopeElement pushScopeElement(context.scopeStack(), ScopeElement::Namespace(semChildNamespace)); AddNamespaceData(context, astChildNamespaceNode->data, moduleScope); } for (const auto& astModuleScopeNode: astNamespaceDataNode->moduleScopes) { if (!moduleScope.isInternal()) { throw ErrorException(makeString("Cannot nest module scopes, at position %s.", astModuleScopeNode.location().toString().c_str())); } AddNamespaceData(context, astModuleScopeNode->data, ConvertModuleScope(astModuleScopeNode)); } for (const auto& astAliasNode: astNamespaceDataNode->aliases) { const auto& aliasName = astAliasNode->name; const auto fullTypeName = semNamespace->name() + aliasName; const auto iterator = semNamespace->items().find(aliasName); if (iterator != semNamespace->items().end()) { throw ErrorException(makeString("Type alias name '%s' clashes with existing name, at position %s.", fullTypeName.toString().c_str(), astAliasNode.location().toString().c_str())); } std::unique_ptr<SEM::Alias> semAlias(new SEM::Alias(context.semContext(), *semNamespace, fullTypeName.copy())); // Add template variables. size_t templateVarIndex = 0; for (auto astTemplateVarNode: *(astAliasNode->templateVariables)) { const auto& templateVarName = astTemplateVarNode->name; // TODO! const bool isVirtual = false; const auto semTemplateVar = new SEM::TemplateVar(context.semContext(), fullTypeName + templateVarName, templateVarIndex++, isVirtual); const auto templateVarIterator = semAlias->namedTemplateVariables().find(templateVarName); if (templateVarIterator != semAlias->namedTemplateVariables().end()) { throw TemplateVariableClashException(fullTypeName.copy(), templateVarName); } semAlias->templateVariables().push_back(semTemplateVar); semAlias->namedTemplateVariables().insert(std::make_pair(templateVarName, semTemplateVar)); } PushScopeElement pushScopeElement(context.scopeStack(), ScopeElement::Alias(semAlias.get())); context.aliasTypeResolver().addAlias(*semAlias, astAliasNode->value, context.scopeStack().copy()); semNamespace->items().insert(std::make_pair(aliasName, SEM::NamespaceItem::Alias(std::move(semAlias)))); } for (const auto& astTypeInstanceNode: astNamespaceDataNode->typeInstances) { (void) AddTypeInstance(context, astTypeInstanceNode, moduleScope); } }
void ConvertTypeInstance(Context& context, AST::Node<AST::TypeInstance>& typeInstanceNode) { for (const auto& function: *(typeInstanceNode->functionDecls)) { PushScopeElement pushScopeElement(context.scopeStack(), ScopeElement::Function(*function)); ConvertFunctionDef(context, function); } if (typeInstanceNode->isEnum()) { size_t enumValue = 0; // Generate enum constructors. for (const auto& constructorName: *(typeInstanceNode->constructors)) { const auto canonicalMethodName = CanonicalizeMethodName(constructorName); CreateEnumConstructorMethod(context, typeInstanceNode, typeInstanceNode->getFunction(canonicalMethodName), enumValue++); } } // Generate default constructor for applicable types. if (typeInstanceNode->isException()) { CreateExceptionConstructor(context, typeInstanceNode, typeInstanceNode->getFunction(context.getCString("create"))); } else if (typeInstanceNode->isDatatype() || typeInstanceNode->isStruct() || typeInstanceNode->isUnion()) { (void) DefaultMethods(context).createDefaultMethod(typeInstanceNode.get(), typeInstanceNode->getFunction(context.getCString("create")), typeInstanceNode.location()); } // Generate default implicitCopy if relevant. if (typeInstanceNode->isEnum() || typeInstanceNode->isStruct() || typeInstanceNode->isDatatype() || typeInstanceNode->isVariant() || typeInstanceNode->isUnion()) { const auto existingFunction = typeInstanceNode->findFunction(context.getCString("implicitcopy")); if (existingFunction != nullptr) { CreateDefaultMethodOrRemove(context, *typeInstanceNode, *existingFunction, typeInstanceNode.location()); } } // Generate default compare if relevant. if (typeInstanceNode->isEnum() || typeInstanceNode->isStruct() || typeInstanceNode->isDatatype() || typeInstanceNode->isVariant()) { const auto existingFunction = typeInstanceNode->findFunction(context.getCString("compare")); if (existingFunction != nullptr) { CreateDefaultMethodOrRemove(context, *typeInstanceNode, *existingFunction, typeInstanceNode.location()); } } // Simplify all predicates to avoid confusing CodeGen. for (auto& function: typeInstanceNode->functions()) { PushScopeElement pushFunction(context.scopeStack(), ScopeElement::Function(*function)); function->setConstPredicate(reducePredicate(context, function->constPredicate().copy())); function->setRequiresPredicate(reducePredicate(context, function->requiresPredicate().copy())); // Simplify function type noexcept predicate. const auto oldFunctionType = function->type(); const bool isVarArg = oldFunctionType.attributes().isVarArg(); const bool isMethod = oldFunctionType.attributes().isMethod(); const bool isTemplated = oldFunctionType.attributes().isTemplated(); auto noExceptPredicate = reducePredicate(context, oldFunctionType.attributes().noExceptPredicate().copy()); const auto returnType = oldFunctionType.returnType(); const auto& argTypes = oldFunctionType.parameterTypes(); AST::FunctionAttributes attributes(isVarArg, isMethod, isTemplated, std::move(noExceptPredicate)); function->setType(AST::FunctionType(std::move(attributes), returnType, argTypes.copy())); } }