Beispiel #1
0
		void CreateEnumConstructorMethod(Context& context,
		                                 const AST::Node<AST::TypeInstance>& typeInstanceNode,
		                                 AST::Function& function, const size_t value) {
			assert(typeInstanceNode->isEnum());
			
			if (function.hasScope()) {
				// Function already has a scope; this can happen when
				// the user has given duplicate enum constructors, in
				// which case we will have issued an error but continued
				// onwards to find more errors.
				return;
			}
			
			auto functionScope = AST::Scope::Create(typeInstanceNode.location());
			
			HeapArray<AST::Value> constructValues;
			
			const auto intConstant = Constant::Integer(APInt(value));
			const auto intType = getBuiltInType(context, context.getCString("int_t"), {});
			constructValues.push_back(AST::Value::Constant(intConstant, intType));
			
			auto internalConstructedValue = AST::Value::InternalConstruct(typeInstanceNode->selfType(), std::move(constructValues));
			functionScope->statements().push_back(AST::Statement::Return(std::move(internalConstructedValue)));
			
			function.setScope(std::move(functionScope));
		}
		Debug::TemplateVarInfo makeTemplateVarInfo(const AST::Node<AST::TemplateTypeVar>& astTemplateVarNode) {
			Debug::TemplateVarInfo templateVarInfo;
			templateVarInfo.declLocation = astTemplateVarNode.location();
			
			// TODO
			templateVarInfo.scopeLocation = Debug::SourceLocation::Null();
			return templateVarInfo;
		}
Beispiel #3
0
		Debug::VarInfo makeVarInfo(const Debug::VarInfo::Kind kind, const AST::Node<AST::TypeVar>& astTypeVarNode) {
			assert(astTypeVarNode->isNamed());
			
			Debug::VarInfo varInfo;
			varInfo.kind = kind;
			varInfo.name = astTypeVarNode->name();
			varInfo.declLocation = astTypeVarNode.location();
			
			// TODO
			varInfo.scopeLocation = Debug::SourceLocation::Null();
			return varInfo;
		}
Beispiel #4
0
		// Attach the variable to the SemanticAnalysis node tree.
		void attachVar(Context& context, const String& name, const AST::Node<AST::TypeVar>& astTypeVarNode, SEM::Var* const var, const Debug::VarInfo::Kind varKind) {
			assert(var->isBasic());
			
			const auto insertResult = insertVar(context.scopeStack().back(), name, var);
			if (!insertResult.second) {
				const auto existingVar = insertResult.first->second;
				throw ErrorException(makeString("Variable name '%s' at position %s duplicates existing variable of the same name at position %s.",
					name.c_str(), astTypeVarNode.location().toString().c_str(),
					existingVar->debugInfo()->declLocation.toString().c_str()));
			}
			
			var->setDebugInfo(makeVarInfo(varKind, astTypeVarNode));
		}
Beispiel #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()));
			}
		}