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);
			}
		}
Пример #2
0
		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);
			}
		}
Пример #3
0
		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());
			}
		}
Пример #4
0
		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);
			}
		}
Пример #5
0
		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()));
			}
		}