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