| //===--- ASTGen.cpp -------------------------------------------------------===// |
| // |
| // This source file is part of the Swift.org open source project |
| // |
| // Copyright (c) 2014 - 2019 Apple Inc. and the Swift project authors |
| // Licensed under Apache License v2.0 with Runtime Library Exception |
| // |
| // See https://swift.org/LICENSE.txt for license information |
| // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #include "swift/Parse/ASTGen.h" |
| #include "swift/AST/TypeRepr.h" |
| #include "swift/Basic/SourceManager.h" |
| |
| #include "DebuggerContextChange.h" |
| #include "swift/Basic/SourceManager.h" |
| #include "swift/Parse/CodeCompletionCallbacks.h" |
| #include "swift/Parse/Parser.h" |
| #include "swift/Parse/Scope.h" |
| |
| using namespace swift; |
| using namespace swift::syntax; |
| |
| SourceLoc ASTGen::generate(const TokenSyntax &Tok, const SourceLoc Loc) { |
| return advanceLocBegin(Loc, Tok); |
| } |
| |
| SourceLoc ASTGen::generateIdentifierDeclName(const syntax::TokenSyntax &Tok, |
| const SourceLoc Loc, |
| Identifier &Id) { |
| StringRef text; |
| if (Tok.getText() == "Any") |
| // Special handle 'Any' because we don't want to accidantaly declare 'Any' |
| // type in any way. |
| text = "#Any"; |
| else |
| text = Tok.getIdentifierText(); |
| |
| Id = Context.getIdentifier(text); |
| return advanceLocBegin(Loc, Tok); |
| } |
| |
| Decl *ASTGen::generate(const DeclSyntax &D, const SourceLoc Loc) { |
| Decl *DeclAST = nullptr; |
| |
| if (auto associatedTypeDecl = D.getAs<AssociatedtypeDeclSyntax>()) { |
| DeclAST = generate(*associatedTypeDecl, Loc); |
| } else if (auto typealiasDecl = D.getAs<TypealiasDeclSyntax>()) { |
| DeclAST = generate(*typealiasDecl, Loc); |
| } else { |
| llvm_unreachable("unsupported decl kind"); |
| } |
| |
| return DeclAST; |
| } |
| |
| DeclAttributes |
| ASTGen::generateDeclAttributes(const Syntax &D, SourceLoc Loc, |
| bool includeComments) { |
| // Find the AST attribute-list from the lookup table. |
| if (auto firstTok = D.getFirstToken()) { |
| auto declLoc = advanceLocBegin(Loc, *firstTok); |
| if (hasDeclAttributes(declLoc)) |
| return getDeclAttributes(declLoc); |
| } |
| return DeclAttributes(); |
| } |
| |
| MutableArrayRef<TypeLoc> |
| ASTGen::generate(const TypeInheritanceClauseSyntax &clause, SourceLoc Loc, |
| bool allowClassRequirement) { |
| SmallVector<TypeLoc, 2> inherited; |
| |
| bool hasClass = false; |
| for (const auto elem : clause.getInheritedTypeCollection()) { |
| const auto &tySyntax = elem.getTypeName(); |
| if (tySyntax.is<ClassRestrictionTypeSyntax>()) { |
| // Accept 'class' only if it's allowed and it's the first one. |
| if (!allowClassRequirement || hasClass) |
| continue; |
| hasClass = true; |
| } |
| if (auto ty = generate(tySyntax, Loc)) |
| inherited.emplace_back(ty); |
| } |
| |
| return Context.AllocateCopy(inherited); |
| } |
| |
| TypeDecl *ASTGen::generate(const AssociatedtypeDeclSyntax &D, |
| const SourceLoc Loc) { |
| if (!isa<ProtocolDecl>(P.CurDeclContext)) { |
| // This is already diagnosed in Parser. |
| return nullptr; |
| } |
| |
| auto idToken = D.getIdentifier(); |
| if (idToken.isMissing()) |
| return nullptr; |
| |
| auto keywordLoc = advanceLocBegin(Loc, D.getAssociatedtypeKeyword()); |
| Identifier name; |
| SourceLoc nameLoc = generateIdentifierDeclName(idToken, Loc, name); |
| |
| DeclAttributes attrs = generateDeclAttributes(D, Loc, true); |
| |
| DebuggerContextChange DCC(P, name, DeclKind::AssociatedType); |
| |
| ArrayRef<TypeLoc> inherited; |
| if (const auto inheritanceClause = D.getInheritanceClause()) |
| inherited = |
| generate(*inheritanceClause, Loc, /*allowClassRequirement=*/true); |
| |
| TypeRepr *defaultTy = nullptr; |
| if (const auto init = D.getInitializer()) |
| defaultTy = generate(init->getValue(), Loc); |
| |
| TrailingWhereClause *trailingWhere = nullptr; |
| if (auto whereClause = D.getGenericWhereClause()) |
| trailingWhere = generate(*whereClause, Loc); |
| |
| auto assocType = new (Context) |
| AssociatedTypeDecl(P.CurDeclContext, keywordLoc, name, nameLoc, defaultTy, |
| trailingWhere); |
| assocType->getAttrs() = attrs; |
| if (!inherited.empty()) |
| assocType->setInherited(Context.AllocateCopy(inherited)); |
| addToScope(assocType); |
| return assocType; |
| } |
| |
| TypeDecl *ASTGen::generate(const TypealiasDeclSyntax &D, const SourceLoc Loc) { |
| auto idToken = D.getIdentifier(); |
| if (idToken.isMissing()) |
| return nullptr; |
| |
| auto keywordLoc = advanceLocBegin(Loc, D.getTypealiasKeyword()); |
| Identifier name; |
| SourceLoc nameLoc = generateIdentifierDeclName(idToken, Loc, name); |
| auto attrs = generateDeclAttributes(D, Loc, true); |
| SourceLoc equalLoc; |
| |
| DebuggerContextChange DCC(P, name, DeclKind::TypeAlias); |
| |
| Optional<Scope> GenericScope; |
| GenericParamList *genericParams = nullptr; |
| GenericScope.emplace(&P, ScopeKind::Generics); |
| if (auto clause = D.getGenericParameterClause()) |
| genericParams = generate(*clause, Loc); |
| |
| auto *TAD = new (Context) TypeAliasDecl(keywordLoc, equalLoc, name, nameLoc, |
| genericParams, P.CurDeclContext); |
| P.setLocalDiscriminator(TAD); |
| TAD->getAttrs() = attrs; |
| |
| TypeRepr *underlyingType = nullptr; |
| SourceLoc typeEndLoc; |
| if (auto init = D.getInitializer()) { |
| Parser::ContextChange CC(P, TAD); |
| equalLoc = generate(init->getEqual(), Loc); |
| underlyingType = generate(init->getValue(), Loc); |
| if (auto lastToken = init->getLastToken()) |
| typeEndLoc = generate(*lastToken, Loc); |
| } |
| TAD->setUnderlyingTypeRepr(underlyingType); |
| |
| SourceLoc whereLoc; |
| if (auto clause = D.getGenericWhereClause()) { |
| whereLoc = advanceLocBegin(Loc, clause->getWhereKeyword()); |
| Parser::ContextChange CC(P, TAD); |
| generateFreeStandingGenericWhereClause(*clause, Loc, genericParams); |
| } |
| P.diagnoseWhereClauseInGenericParamList(genericParams, whereLoc); |
| |
| if (equalLoc.isInvalid()) |
| return nullptr; |
| |
| GenericScope.reset(); |
| |
| addToScope(TAD); |
| return DCC.fixupParserResult(TAD).getPtrOrNull(); |
| } |
| |
| void ASTGen::generateFreeStandingGenericWhereClause( |
| const syntax::GenericWhereClauseSyntax &syntax, const SourceLoc Loc, |
| GenericParamList *genericParams) { |
| |
| SourceLoc whereLoc = generate(syntax.getWhereKeyword(), Loc); |
| |
| if (!genericParams) { |
| P.diagnose(whereLoc, diag::where_without_generic_params, |
| unsigned(Parser::WhereClauseKind::Declaration)); |
| return; |
| } |
| |
| // Push the generic parameters back into a local scope so that references |
| // will find them. |
| Scope S(&P, ScopeKind::Generics); |
| for (auto pd : genericParams->getParams()) |
| addToScope(pd); |
| |
| SmallVector<RequirementRepr, 4> requirements; |
| requirements.reserve(syntax.getRequirementList().size()); |
| for (auto elem : syntax.getRequirementList()) { |
| if (auto req = generate(elem, Loc)) |
| requirements.push_back(*req); |
| } |
| if (requirements.empty()) |
| return; |
| |
| genericParams->addTrailingWhereClause(Context, whereLoc, requirements); |
| } |
| |
| TrailingWhereClause *ASTGen::generate(const GenericWhereClauseSyntax &syntax, |
| const SourceLoc Loc) { |
| SourceLoc whereLoc = advanceLocBegin(Loc, syntax.getWhereKeyword()); |
| |
| SmallVector<RequirementRepr, 4> requirements; |
| requirements.reserve(syntax.getRequirementList().size()); |
| for (auto elem : syntax.getRequirementList()) { |
| if (auto req = generate(elem, Loc)) |
| requirements.push_back(*req); |
| } |
| |
| if (requirements.empty()) |
| return nullptr; |
| return TrailingWhereClause::create(Context, whereLoc, requirements); |
| } |
| |
| Expr *ASTGen::generate(const ExprSyntax &E, const SourceLoc Loc) { |
| Expr *result = nullptr; |
| |
| if (auto identifierExpr = E.getAs<IdentifierExprSyntax>()) |
| result = generate(*identifierExpr, Loc); |
| else if (auto specializeExpr = E.getAs<SpecializeExprSyntax>()) |
| result = generate(*specializeExpr, Loc); |
| else if (auto editorPlaceHolderExpr = E.getAs<EditorPlaceholderExprSyntax>()) |
| result = generate(*editorPlaceHolderExpr, Loc); |
| else if (auto integerLiteralExpr = E.getAs<IntegerLiteralExprSyntax>()) |
| result = generate(*integerLiteralExpr, Loc); |
| else if (auto floatLiteralExpr = E.getAs<FloatLiteralExprSyntax>()) |
| result = generate(*floatLiteralExpr, Loc); |
| else if (auto nilLiteral = E.getAs<NilLiteralExprSyntax>()) |
| result = generate(*nilLiteral, Loc); |
| else if (auto boolLiteral = E.getAs<BooleanLiteralExprSyntax>()) |
| result = generate(*boolLiteral, Loc); |
| else if (auto poundFileExpr = E.getAs<PoundFileExprSyntax>()) |
| result = generate(*poundFileExpr, Loc); |
| else if (auto poundLineExpr = E.getAs<PoundLineExprSyntax>()) |
| result = generate(*poundLineExpr, Loc); |
| else if (auto poundColumnExpr = E.getAs<PoundColumnExprSyntax>()) |
| result = generate(*poundColumnExpr, Loc); |
| else if (auto poundFunctionExpr = E.getAs<PoundFunctionExprSyntax>()) |
| result = generate(*poundFunctionExpr, Loc); |
| else if (auto poundDsohandleExpr = E.getAs<PoundDsohandleExprSyntax>()) |
| result = generate(*poundDsohandleExpr, Loc); |
| else |
| llvm_unreachable("unsupported expression"); |
| |
| return result; |
| } |
| |
| std::pair<DeclName, DeclNameLoc> ASTGen::generateUnqualifiedDeclName( |
| const TokenSyntax &idTok, const Optional<DeclNameArgumentsSyntax> &args, |
| const SourceLoc Loc) { |
| SourceLoc baseNameLoc = advanceLocBegin(Loc, idTok); |
| |
| DeclBaseName baseName; |
| if (idTok.getTokenKind() == tok::kw_init) |
| baseName = DeclBaseName::createConstructor(); |
| else if (idTok.getTokenKind() == tok::kw_deinit) |
| baseName = DeclBaseName::createDestructor(); |
| else if (idTok.getTokenKind() == tok::kw_subscript) |
| baseName = DeclBaseName::createSubscript(); |
| else |
| baseName = Context.getIdentifier(idTok.getIdentifierText()); |
| |
| if (!args) |
| return {DeclName(baseName), DeclNameLoc(baseNameLoc)}; |
| |
| // FIXME: Remove this block and use 'Loc'. |
| // This is needed for the case 'idTok' and 'args' are not in the same tree. |
| // i.e. Call from parseUnqualifiedDeclName(). |
| SourceLoc argsLeadingLoc = Loc; |
| if (!args->getParent()) { |
| argsLeadingLoc = Loc.getAdvancedLoc(idTok.getTextLength()); |
| } else { |
| assert(idTok.getData().getParent() == args->getData().getParent() && |
| idTok.getIndexInParent() + 1 == args->getIndexInParent() && |
| "'idTok' must be immediately followed by 'args'"); |
| } |
| |
| SmallVector<Identifier, 2> argumentLabels; |
| SmallVector<SourceLoc, 2> argumentLabelLocs; |
| for (auto arg : args->getArguments()) { |
| Identifier label; |
| if (!arg.getName().isMissing() && |
| arg.getName().getTokenKind() != tok::kw__) { |
| label = Context.getIdentifier(arg.getName().getIdentifierText()); |
| } |
| argumentLabels.push_back(label); |
| argumentLabelLocs.push_back(advanceLocBegin(argsLeadingLoc, |
| *arg.getFirstToken())); |
| } |
| SourceLoc lParenLoc = advanceLocBegin(argsLeadingLoc, args->getLeftParen()); |
| SourceLoc rParenLoc = advanceLocBegin(argsLeadingLoc, args->getRightParen()); |
| |
| DeclName name(Context, baseName, argumentLabels); |
| DeclNameLoc nameLoc; |
| if (argumentLabelLocs.empty()) |
| nameLoc = DeclNameLoc(baseNameLoc); |
| else |
| nameLoc = DeclNameLoc(Context, baseNameLoc, lParenLoc, argumentLabelLocs, |
| rParenLoc); |
| return {name, nameLoc}; |
| } |
| |
| Expr *ASTGen::generate(const IdentifierExprSyntax &E, const SourceLoc Loc) { |
| auto idTok = E.getIdentifier(); |
| DeclName name; |
| DeclNameLoc nameLoc; |
| std::tie(name, nameLoc) = generateUnqualifiedDeclName( |
| E.getIdentifier(), E.getDeclNameArguments(), Loc); |
| |
| ValueDecl *D = nullptr; |
| if (!P.InPoundIfEnvironment) { |
| D = lookupInScope(name); |
| // FIXME: We want this to work: "var x = { x() }", but for now it's better |
| // to disallow it than to crash. |
| if (D) { |
| for (auto activeVar : P.DisabledVars) { |
| if (activeVar != D) |
| continue; |
| P.diagnose(nameLoc.getBaseNameLoc(), P.DisabledVarReason); |
| return new (Context) ErrorExpr(nameLoc.getSourceRange()); |
| } |
| } else { |
| for (auto activeVar : P.DisabledVars) { |
| if (activeVar->getFullName() != name) |
| continue; |
| P.diagnose(nameLoc.getBaseNameLoc(), P.DisabledVarReason); |
| return new (Context) ErrorExpr(nameLoc.getSourceRange()); |
| } |
| } |
| } |
| |
| if (!D) { |
| return new (Context) |
| UnresolvedDeclRefExpr(name, DeclRefKind::Ordinary, nameLoc); |
| } |
| |
| if (auto TD = dyn_cast<TypeDecl>(D)) { |
| // When parsing default argument expressions for generic functions, |
| // we haven't built a FuncDecl or re-parented the GenericTypeParamDecls |
| // to the FuncDecl yet. Other than that, we should only ever find |
| // global or local declarations here. |
| assert(!TD->getDeclContext()->isTypeContext() || |
| isa<GenericTypeParamDecl>(TD)); |
| return TypeExpr::createForDecl(nameLoc.getBaseNameLoc(), TD, |
| /*DeclContext=*/nullptr, |
| /*inplicit=*/false); |
| } |
| |
| return new (Context) DeclRefExpr(D, nameLoc, /*implicit=*/false); |
| } |
| |
| Expr *ASTGen::generate(const EditorPlaceholderExprSyntax &E, const SourceLoc Loc) { |
| assert(!E.getIdentifier().isMissing()); |
| |
| auto text = E.getIdentifier().getText(); |
| auto tokLoc = advanceLocBegin(Loc, E.getIdentifier()); |
| return P.parseExprEditorPlaceholder(tokLoc, text); |
| } |
| |
| Expr *ASTGen::generate(const SpecializeExprSyntax &E, const SourceLoc Loc) { |
| auto base = generate(E.getExpression(), Loc); |
| |
| SourceLoc lAngleLoc, rAngleLoc; |
| SmallVector<TypeRepr *, 4> argTyRs; |
| generate(E.getGenericArgumentClause(), Loc, lAngleLoc, rAngleLoc, argTyRs); |
| if (argTyRs.empty()) |
| return base; |
| |
| SmallVector<TypeLoc, 4> args; |
| args.assign(argTyRs.begin(), argTyRs.end()); |
| return UnresolvedSpecializeExpr::create(Context, base, lAngleLoc, args, |
| rAngleLoc); |
| } |
| |
| Expr *ASTGen::generate(const IntegerLiteralExprSyntax &Expr, |
| const SourceLoc Loc) { |
| auto Digits = Expr.getDigits(); |
| auto Text = copyAndStripUnderscores(Digits.getText()); |
| auto DigitsLoc = advanceLocBegin(Loc, Digits); |
| return new (Context) IntegerLiteralExpr(Text, DigitsLoc); |
| } |
| |
| Expr *ASTGen::generate(const FloatLiteralExprSyntax &Expr, |
| const SourceLoc Loc) { |
| auto Digits = Expr.getFloatingDigits(); |
| auto Text = copyAndStripUnderscores(Digits.getText()); |
| auto DigitsLoc = advanceLocBegin(Loc, Digits); |
| return new (Context) FloatLiteralExpr(Text, DigitsLoc); |
| } |
| |
| Expr *ASTGen::generate(const NilLiteralExprSyntax &Expr, const SourceLoc Loc) { |
| auto Nil = Expr.getNilKeyword(); |
| auto NilLoc = advanceLocBegin(Loc, Nil); |
| return new (Context) NilLiteralExpr(NilLoc); |
| } |
| |
| Expr *ASTGen::generate(const BooleanLiteralExprSyntax &Expr, |
| const SourceLoc Loc) { |
| auto Boolean = Expr.getBooleanLiteral(); |
| auto Value = Boolean.getTokenKind() == tok::kw_true; |
| auto BooleanLoc = advanceLocBegin(Loc, Boolean); |
| return new (Context) BooleanLiteralExpr(Value, BooleanLoc); |
| } |
| |
| Expr *ASTGen::generate(const PoundFileExprSyntax &Expr, const SourceLoc Loc) { |
| return generateMagicIdentifierLiteralExpression(Expr.getPoundFile(), Loc); |
| } |
| |
| Expr *ASTGen::generate(const PoundLineExprSyntax &Expr, const SourceLoc Loc) { |
| return generateMagicIdentifierLiteralExpression(Expr.getPoundLine(), Loc); |
| } |
| |
| Expr *ASTGen::generate(const PoundColumnExprSyntax &Expr, const SourceLoc Loc) { |
| return generateMagicIdentifierLiteralExpression(Expr.getPoundColumn(), Loc); |
| } |
| |
| Expr *ASTGen::generate(const PoundFunctionExprSyntax &Expr, |
| const SourceLoc Loc) { |
| return generateMagicIdentifierLiteralExpression(Expr.getPoundFunction(), Loc); |
| } |
| |
| Expr *ASTGen::generate(const PoundDsohandleExprSyntax &Expr, |
| const SourceLoc Loc) { |
| return generateMagicIdentifierLiteralExpression(Expr.getPoundDsohandle(), |
| Loc); |
| } |
| |
| Expr *ASTGen::generate(const UnknownExprSyntax &Expr, const SourceLoc Loc) { |
| if (Expr.getNumChildren() == 1 && Expr.getChild(0)->isToken()) { |
| Syntax Token = *Expr.getChild(0); |
| tok Kind = Token.getRaw()->getTokenKind(); |
| switch (Kind) { |
| case tok::kw___FILE__: |
| case tok::kw___LINE__: |
| case tok::kw___COLUMN__: |
| case tok::kw___FUNCTION__: |
| case tok::kw___DSO_HANDLE__: { |
| auto MagicKind = getMagicIdentifierLiteralKind(Kind); |
| auto KindLoc = advanceLocBegin(Loc, Token); |
| return new (Context) MagicIdentifierLiteralExpr(MagicKind, KindLoc); |
| } |
| default: |
| return nullptr; |
| } |
| } |
| return nullptr; |
| } |
| |
| TypeRepr *ASTGen::generate(const TypeSyntax &Type, const SourceLoc Loc, |
| bool IsSILFuncDecl) { |
| TypeRepr *TypeAST = nullptr; |
| |
| if (auto SimpleIdentifier = Type.getAs<SimpleTypeIdentifierSyntax>()) |
| TypeAST = generate(*SimpleIdentifier, Loc); |
| else if (auto MemberIdentifier = Type.getAs<MemberTypeIdentifierSyntax>()) |
| TypeAST = generate(*MemberIdentifier, Loc); |
| else if (auto Composition = Type.getAs<CompositionTypeSyntax>()) |
| TypeAST = generate(*Composition, Loc); |
| else if (auto Function = Type.getAs<FunctionTypeSyntax>()) |
| TypeAST = generate(*Function, Loc); |
| else if (auto Metatype = Type.getAs<MetatypeTypeSyntax>()) |
| TypeAST = generate(*Metatype, Loc); |
| else if (auto Array = Type.getAs<ArrayTypeSyntax>()) |
| TypeAST = generate(*Array, Loc); |
| else if (auto Dictionary = Type.getAs<DictionaryTypeSyntax>()) |
| TypeAST = generate(*Dictionary, Loc); |
| else if (auto Tuple = Type.getAs<TupleTypeSyntax>()) |
| TypeAST = generate(*Tuple, Loc); |
| else if (auto Some = Type.getAs<SomeTypeSyntax>()) |
| TypeAST = generate(*Some, Loc); |
| else if (auto Optional = Type.getAs<OptionalTypeSyntax>()) |
| TypeAST = generate(*Optional, Loc); |
| else if (auto Unwrapped = Type.getAs<ImplicitlyUnwrappedOptionalTypeSyntax>()) |
| TypeAST = generate(*Unwrapped, Loc); |
| else if (auto Attributed = Type.getAs<AttributedTypeSyntax>()) |
| TypeAST = generate(*Attributed, Loc); |
| else if (auto ClassRestriction = Type.getAs<ClassRestrictionTypeSyntax>()) |
| TypeAST = generate(*ClassRestriction, Loc); |
| else if (auto SILBoxType = Type.getAs<SILBoxTypeSyntax>()) |
| TypeAST = generate(*SILBoxType, Loc, IsSILFuncDecl); |
| else if (auto SILFunctionType = Type.getAs<SILFunctionTypeSyntax>()) |
| TypeAST = generate(*SILFunctionType, Loc, IsSILFuncDecl); |
| else if (auto CompletionTy = Type.getAs<CodeCompletionTypeSyntax>()) |
| TypeAST = generate(*CompletionTy, Loc); |
| else if (auto Unknown = Type.getAs<UnknownTypeSyntax>()) |
| TypeAST = generate(*Unknown, Loc); |
| |
| return cacheType(Type, TypeAST); |
| } |
| |
| TypeRepr *ASTGen::generate(const FunctionTypeSyntax &Type, |
| const SourceLoc Loc) { |
| TupleTypeRepr *ArgumentTypes = nullptr; |
| |
| SourceLoc VoidLoc; |
| if (Type.getLeftParen().isMissing() && Type.getArguments().size() == 1) { |
| if (auto ident = Type.getArguments()[0] |
| .getType() |
| .getAs<SimpleTypeIdentifierSyntax>()) { |
| if (!ident->getGenericArgumentClause().hasValue() && |
| ident->getName().getText() == "Void") |
| VoidLoc = advanceLocBegin(Loc, ident->getName()); |
| } |
| } |
| |
| if (VoidLoc.isValid()) |
| ArgumentTypes = TupleTypeRepr::createEmpty(Context, VoidLoc); |
| else { |
| ArgumentTypes = generateTuple(Type.getLeftParen(), Type.getArguments(), |
| Type.getRightParen(), Loc, |
| /*IsFunction=*/true); |
| } |
| if (!ArgumentTypes) |
| return nullptr; |
| |
| auto ThrowsLoc = Type.getThrowsOrRethrowsKeyword() |
| ? generate(*Type.getThrowsOrRethrowsKeyword(), Loc) |
| : SourceLoc(); |
| |
| auto ArrowLoc = generate(Type.getArrow(), Loc); |
| auto ReturnType = generate(Type.getReturnType(), Loc); |
| if (!ReturnType) |
| return nullptr; |
| |
| return new (Context) |
| FunctionTypeRepr(nullptr, ArgumentTypes, ThrowsLoc, ArrowLoc, ReturnType); |
| } |
| |
| TupleTypeRepr *ASTGen::generateTuple(const TokenSyntax &LParen, |
| const TupleTypeElementListSyntax &Elements, |
| const TokenSyntax &RParen, |
| const SourceLoc Loc, bool IsFunction) { |
| auto LPLoc = generate(LParen, Loc); |
| auto RPLoc = generate(RParen, Loc); |
| |
| SmallVector<TupleTypeReprElement, 4> TupleElements; |
| |
| SourceLoc EllipsisLoc; |
| unsigned EllipsisIdx = Elements.size(); |
| |
| for (unsigned i = 0; i < Elements.getNumChildren(); i++) { |
| auto Element = Elements.getChild(i)->castTo<TupleTypeElementSyntax>(); |
| TupleTypeReprElement ElementAST; |
| if (auto Name = Element.getName()) { |
| ElementAST.NameLoc = generate(*Name, Loc); |
| ElementAST.Name = Name->getText() == "_" |
| ? Identifier() |
| : Context.getIdentifier(Name->getIdentifierText()); |
| } |
| if (auto Colon = Element.getColon()) |
| ElementAST.ColonLoc = generate(*Colon, Loc); |
| if (auto SecondName = Element.getSecondName()) { |
| ElementAST.SecondNameLoc = generate(*SecondName, Loc); |
| ElementAST.SecondName = |
| SecondName->getText() == "_" |
| ? Identifier() |
| : Context.getIdentifier(SecondName->getIdentifierText()); |
| if (IsFunction) { |
| // Form the named parameter type representation. |
| ElementAST.UnderscoreLoc = ElementAST.NameLoc; |
| ElementAST.Name = ElementAST.SecondName; |
| ElementAST.NameLoc = ElementAST.SecondNameLoc; |
| } |
| } |
| ElementAST.Type = generate(Element.getType(), Loc); |
| if (auto InOut = Element.getInOut()) { |
| // don't apply multiple inout specifiers to a type: that's invalid and was |
| // already reported in the parser, handle gracefully |
| if (!isa<InOutTypeRepr>(ElementAST.Type)) { |
| auto InOutLoc = generate(*InOut, Loc); |
| ElementAST.Type = |
| new (Context) InOutTypeRepr(ElementAST.Type, InOutLoc); |
| } |
| } |
| if (auto Comma = Element.getTrailingComma()) |
| ElementAST.TrailingCommaLoc = generate(*Comma, Loc); |
| if (auto Ellipsis = Element.getEllipsis()) { |
| EllipsisLoc = generate(*Ellipsis, Loc); |
| if (EllipsisIdx == Elements.size()) |
| EllipsisIdx = i; |
| } |
| TupleElements.push_back(ElementAST); |
| } |
| |
| return TupleTypeRepr::create(Context, TupleElements, {LPLoc, RPLoc}, |
| EllipsisLoc, EllipsisIdx); |
| } |
| |
| TypeAttributes ASTGen::generateTypeAttributes(const AttributeListSyntax &syntax, |
| const SourceLoc Loc) { |
| TypeAttributes attrs; |
| |
| for (auto elem : syntax) { |
| auto attrSyntax = elem.castTo<AttributeSyntax>(); |
| if (attrSyntax.getAttributeName().isMissing()) |
| continue; |
| |
| auto attrName = attrSyntax.getAttributeName().getText(); |
| |
| auto atLoc = advanceLocBegin(Loc, attrSyntax.getAtSignToken()); |
| if (attrs.AtLoc.isInvalid()) |
| attrs.AtLoc = atLoc; |
| |
| auto attr = TypeAttributes::getAttrKindFromString(attrName); |
| if (attr == TAK_Count) |
| continue; |
| |
| if (attrs.has(attr)) { |
| P.diagnose(atLoc, diag::duplicate_attribute, /*isModifier=*/false); |
| continue; |
| } |
| |
| auto arg = attrSyntax.getArgument(); |
| |
| if (attr == TAK_sil_weak || attr == TAK_sil_unowned) { |
| if (attrs.hasOwnership()) { |
| P.diagnose(atLoc, diag::duplicate_attribute, /*isModifier*/false); |
| } |
| } else if (attr == TAK_convention) { |
| // @convention(block) |
| // @convention(witness_method: ProtocolName) |
| if (!arg) |
| continue; |
| |
| if (auto conventionNameTok = arg->getAs<TokenSyntax>()) { |
| assert(conventionNameTok->getTokenKind() == tok::identifier); |
| auto convention = |
| Context.getIdentifier(conventionNameTok->getIdentifierText()); |
| attrs.convention = convention.str(); |
| } else if (auto witness = |
| arg->getAs<NamedAttributeStringArgumentSyntax>()) { |
| assert(witness->getNameTok().getIdentifierText() == "witness_method"); |
| if (witness->getStringOrDeclname().isMissing()) |
| continue; |
| auto protocolName = |
| witness->getStringOrDeclname().castTo<DeclNameSyntax>(); |
| auto protocol = Context.getIdentifier( |
| protocolName.getDeclBaseName().getIdentifierText()); |
| attrs.convention = "witness_method"; |
| attrs.conventionWitnessMethodProtocol = protocol.str(); |
| } else { |
| continue; |
| } |
| } else if (attr == TAK_opened) { |
| // @opened("01234567-89ab-cdef-0123-111111111111") |
| if (!arg) |
| continue; |
| |
| assert(arg->castTo<TokenSyntax>().getTokenKind() == |
| tok::string_literal); |
| auto tokText = arg->castTo<TokenSyntax>().getText(); |
| auto literalText = tokText.slice(1, tokText.size() - 1); |
| attrs.OpenedID = UUID::fromString(literalText.str().c_str()); |
| } else if (attr == TAK__opaqueReturnTypeOf) { |
| // @_opaqueReturnTypeOf("$sMangledName", 0) |
| if (!arg) |
| continue; |
| |
| auto opaqueArg = |
| arg->castTo<OpaqueReturnTypeOfAttributeArgumentsSyntax>(); |
| |
| auto manglingTok = opaqueArg.getMangledName(); |
| auto indexTok = opaqueArg.getIndex(); |
| if (manglingTok.isMissing() || indexTok.isMissing()) |
| continue; |
| |
| auto tokText = manglingTok.getText(); |
| auto mangling = |
| Context.getIdentifier(tokText.slice(1, tokText.size() - 1)); |
| unsigned index; |
| if (indexTok.getText().getAsInteger(10, index)) |
| continue; |
| attrs.setOpaqueReturnTypeOf(mangling.str(), index); |
| // SWIFT_ENABLE_TENSORFLOW |
| } else if (attr == TAK_differentiable) { |
| if (arg) { |
| auto argSyntax = arg->getAs<TokenSyntax>(); |
| attrs.linear = argSyntax->getTokenKind() == tok::identifier && |
| argSyntax->getIdentifierText() == "linear"; |
| } else { |
| attrs.linear = false; |
| } |
| } |
| |
| attrs.setAttr(attr, atLoc); |
| } |
| |
| return attrs; |
| } |
| |
| TypeRepr *ASTGen::generate(const AttributedTypeSyntax &Type, |
| const SourceLoc Loc) { |
| auto TypeAST = generate(Type.getBaseType(), Loc); |
| if (!TypeAST) |
| return nullptr; |
| |
| if (auto Attributes = Type.getAttributes()) { |
| TypeAttributes attrs = generateTypeAttributes(*Attributes, Loc); |
| if (!attrs.empty()) |
| TypeAST = new (Context) AttributedTypeRepr(attrs, TypeAST); |
| } |
| |
| if (auto Specifier = Type.getSpecifier()) { |
| auto SpecifierLoc = generate(*Specifier, Loc); |
| auto SpecifierText = Specifier->getText(); |
| |
| // don't apply multiple specifiers to a type: that's invalid and was already |
| // reported in the parser, handle gracefully |
| if (!isa<SpecifierTypeRepr>(TypeAST)) { |
| if (SpecifierText == "inout") |
| TypeAST = new (Context) InOutTypeRepr(TypeAST, SpecifierLoc); |
| else if (SpecifierText == "__owned") |
| TypeAST = new (Context) OwnedTypeRepr(TypeAST, SpecifierLoc); |
| else if (SpecifierText == "__shared") |
| TypeAST = new (Context) SharedTypeRepr(TypeAST, SpecifierLoc); |
| } |
| } |
| |
| return TypeAST; |
| } |
| |
| TypeRepr *ASTGen::generate(const TupleTypeSyntax &Type, const SourceLoc Loc) { |
| return generateTuple(Type.getLeftParen(), Type.getElements(), |
| Type.getRightParen(), Loc); |
| } |
| |
| TypeRepr *ASTGen::generate(const SomeTypeSyntax &Type, const SourceLoc Loc) { |
| auto Some = Type.getSomeSpecifier(); |
| auto SomeLoc = generate(Some, Loc); |
| auto BaseType = generate(Type.getBaseType(), Loc); |
| return new (Context) OpaqueReturnTypeRepr(SomeLoc, BaseType); |
| } |
| |
| TypeRepr *ASTGen::generate(const CompositionTypeSyntax &Type, |
| const SourceLoc Loc) { |
| auto Elements = Type.getElements(); |
| auto FirstElem = Elements[0]; |
| auto LastElem = Elements[Elements.size() - 1]; |
| |
| SmallVector<TypeRepr *, 4> ElemTypes; |
| for (unsigned i = 0; i < Elements.size(); i++) { |
| auto ElemType = Elements[i].getType(); |
| |
| TypeRepr *ElemTypeR = nullptr; |
| if (auto Some = ElemType.getAs<SomeTypeSyntax>()) { |
| // the invalid `some` after an ampersand was already diagnosed by the |
| // parser, handle it gracefully |
| ElemTypeR = generate(Some->getBaseType(), Loc); |
| } else { |
| ElemTypeR = generate(ElemType, Loc); |
| } |
| |
| if (ElemTypeR) { |
| if (auto Comp = dyn_cast<CompositionTypeRepr>(ElemTypeR)) { |
| // Accept protocol<P1, P2> & P3; explode it. |
| auto TyRs = Comp->getTypes(); |
| ElemTypes.append(TyRs.begin(), TyRs.end()); |
| } else { |
| ElemTypes.push_back(ElemTypeR); |
| } |
| } |
| } |
| |
| auto FirstTypeLoc = advanceLocBegin(Loc, FirstElem); |
| auto FirstAmpersandLoc = advanceLocBegin(Loc, *FirstElem.getAmpersand()); |
| auto LastTypeLoc = advanceLocBegin(Loc, *LastElem.getLastToken()); |
| return CompositionTypeRepr::create(Context, ElemTypes, FirstTypeLoc, |
| {FirstAmpersandLoc, LastTypeLoc}); |
| } |
| |
| void ASTGen::gatherTypeIdentifierComponents( |
| const TypeSyntax &Component, const SourceLoc Loc, |
| SmallVectorImpl<ComponentIdentTypeRepr *> &Components) { |
| if (auto SimpleIdentifier = Component.getAs<SimpleTypeIdentifierSyntax>()) { |
| auto ComponentType = generateIdentifier(*SimpleIdentifier, Loc); |
| Components.push_back(ComponentType); |
| return; |
| } |
| |
| if (auto MemberIdentifier = Component.getAs<MemberTypeIdentifierSyntax>()) { |
| auto ComponentType = generateIdentifier(*MemberIdentifier, Loc); |
| Components.push_back(ComponentType); |
| gatherTypeIdentifierComponents(MemberIdentifier->getBaseType(), Loc, |
| Components); |
| return; |
| } |
| |
| llvm_unreachable("unexpected type identifier component"); |
| } |
| |
| template <typename T> |
| TypeRepr *ASTGen::generateSimpleOrMemberIdentifier(const T &Type, |
| const SourceLoc Loc) { |
| SmallVector<ComponentIdentTypeRepr *, 4> Components; |
| gatherTypeIdentifierComponents(Type, Loc, Components); |
| std::reverse(Components.begin(), Components.end()); |
| |
| auto IdentType = IdentTypeRepr::create(Context, Components); |
| auto FirstComponent = IdentType->getComponentRange().front(); |
| // Lookup element #0 through our current scope chains in case it is some |
| // thing local (this returns null if nothing is found). |
| if (auto Entry = lookupInScope(FirstComponent->getIdentifier())) { |
| if (auto *TD = dyn_cast<TypeDecl>(Entry)) |
| FirstComponent->setValue(TD, nullptr); |
| } |
| |
| return IdentType; |
| } |
| |
| template <typename T> |
| ComponentIdentTypeRepr *ASTGen::generateIdentifier(const T &Type, |
| const SourceLoc Loc) { |
| auto IdentifierLoc = advanceLocBegin(Loc, Type.getName()); |
| auto Identifier = Context.getIdentifier(Type.getName().getIdentifierText()); |
| if (auto Clause = Type.getGenericArgumentClause()) { |
| SourceLoc lAngleLoc, rAngleLoc; |
| SmallVector<TypeRepr *, 4> args; |
| generate(*Clause, Loc, lAngleLoc, rAngleLoc, args); |
| if (!args.empty()) |
| return GenericIdentTypeRepr::create(Context, IdentifierLoc, Identifier, |
| args, {lAngleLoc, rAngleLoc}); |
| } |
| return new (Context) SimpleIdentTypeRepr(IdentifierLoc, Identifier); |
| } |
| |
| TypeRepr *ASTGen::generate(const SimpleTypeIdentifierSyntax &Type, |
| const SourceLoc Loc) { |
| if (Type.getName().getTokenKind() == tok::kw_Any) { |
| auto AnyLoc = advanceLocBegin(Loc, Type.getName()); |
| return CompositionTypeRepr::createEmptyComposition(Context, AnyLoc); |
| } |
| |
| return generateSimpleOrMemberIdentifier(Type, Loc); |
| } |
| |
| TypeRepr *ASTGen::generate(const MemberTypeIdentifierSyntax &Type, |
| SourceLoc Loc) { |
| return generateSimpleOrMemberIdentifier(Type, Loc); |
| } |
| |
| TypeRepr *ASTGen::generate(const DictionaryTypeSyntax &Type, |
| const SourceLoc Loc) { |
| TypeRepr *ValueType = generate(Type.getValueType(), Loc); |
| TypeRepr *KeyType = generate(Type.getKeyType(), Loc); |
| if (!ValueType || !KeyType) |
| return nullptr; |
| auto ColonLoc = advanceLocBegin(Loc, Type.getColon()); |
| |
| SourceLoc LBracketLoc, RBracketLoc; |
| if (Type.getLeftSquareBracket().isPresent()) |
| LBracketLoc = advanceLocBegin(Loc, Type.getLeftSquareBracket()); |
| else |
| LBracketLoc = advanceLocBegin(Loc, *Type.getFirstToken()); |
| if (Type.getRightSquareBracket().isPresent()) |
| RBracketLoc = advanceLocBegin(Loc, Type.getRightSquareBracket()); |
| else |
| RBracketLoc = advanceLocBegin(Loc, *Type.getLastToken()); |
| SourceRange Range{LBracketLoc, RBracketLoc}; |
| return new (Context) DictionaryTypeRepr(KeyType, ValueType, ColonLoc, Range); |
| } |
| |
| TypeRepr *ASTGen::generate(const ArrayTypeSyntax &Type, SourceLoc Loc) { |
| TypeRepr *ElementType = generate(Type.getElementType(), Loc); |
| if (!ElementType) |
| return nullptr; |
| SourceLoc LBracketLoc, RBracketLoc; |
| if (Type.getLeftSquareBracket().isPresent()) |
| LBracketLoc = advanceLocBegin(Loc, Type.getLeftSquareBracket()); |
| else |
| LBracketLoc = advanceLocBegin(Loc, *Type.getFirstToken()); |
| if (Type.getRightSquareBracket().isPresent()) |
| RBracketLoc = advanceLocBegin(Loc, Type.getRightSquareBracket()); |
| else |
| RBracketLoc = advanceLocBegin(Loc, *Type.getLastToken()); |
| return new (Context) ArrayTypeRepr(ElementType, {LBracketLoc, RBracketLoc}); |
| } |
| |
| TypeRepr *ASTGen::generate(const MetatypeTypeSyntax &Type, |
| const SourceLoc Loc) { |
| TypeRepr *BaseType = generate(Type.getBaseType(), Loc); |
| auto TypeOrProtocol = Type.getTypeOrProtocol(); |
| auto TypeOrProtocolLoc = advanceLocBegin(Loc, TypeOrProtocol); |
| if (TypeOrProtocol.getText() == "Type") |
| return new (Context) MetatypeTypeRepr(BaseType, TypeOrProtocolLoc); |
| return new (Context) ProtocolTypeRepr(BaseType, TypeOrProtocolLoc); |
| } |
| |
| TypeRepr *ASTGen::generate(const OptionalTypeSyntax &Type, |
| const SourceLoc Loc) { |
| TypeRepr *WrappedType = generate(Type.getWrappedType(), Loc); |
| auto QuestionLoc = advanceLocBegin(Loc, Type.getQuestionMark()); |
| return new (Context) OptionalTypeRepr(WrappedType, QuestionLoc); |
| } |
| |
| TypeRepr *ASTGen::generate(const ImplicitlyUnwrappedOptionalTypeSyntax &Type, |
| const SourceLoc Loc) { |
| TypeRepr *WrappedType = generate(Type.getWrappedType(), Loc); |
| auto ExclamationLoc = advanceLocBegin(Loc, Type.getExclamationMark()); |
| return new (Context) |
| ImplicitlyUnwrappedOptionalTypeRepr(WrappedType, ExclamationLoc); |
| } |
| |
| TypeRepr * |
| ASTGen::generate(const ClassRestrictionTypeSyntax &Type, const SourceLoc Loc) { |
| auto classLoc = advanceLocBegin(Loc, Type); |
| return new (Context) |
| SimpleIdentTypeRepr(classLoc, Context.getIdentifier("AnyObject")); |
| } |
| |
| TypeRepr *ASTGen::generate(const SILBoxTypeSyntax &Type, const SourceLoc Loc, |
| bool IsSILFuncDecl) { |
| if (Type.getRightBrace().isMissing()) |
| return nullptr; |
| |
| // If this is part of a sil function decl, generic parameters are visible in |
| // the function body; otherwise, they are visible when parsing the type. |
| Optional<Scope> GenericsScope; |
| if (!IsSILFuncDecl) |
| GenericsScope.emplace(&P, ScopeKind::Generics); |
| |
| GenericParamList *generics = nullptr; |
| if (auto genericParamsSyntax = Type.getGenericParameterClauses()) |
| generics = generate(*genericParamsSyntax, Loc); |
| |
| SmallVector<SILBoxTypeRepr::Field, 4> Fields; |
| for (auto field : Type.getFields()) { |
| auto specifier = field.getSpecifier(); |
| if (specifier.isMissing()) |
| return nullptr; |
| bool Mutable; |
| if (specifier.getTokenKind() == tok::kw_let) |
| Mutable = false; |
| else if (specifier.getTokenKind() == tok::kw_var) |
| Mutable = true; |
| else |
| return nullptr; |
| SourceLoc VarOrLetLoc = advanceLocBegin(Loc, specifier);; |
| auto fieldTy = generate(field.getType(), Loc); |
| if (!fieldTy) |
| return nullptr; |
| |
| Fields.emplace_back(VarOrLetLoc, Mutable, fieldTy); |
| } |
| GenericsScope.reset(); |
| |
| auto LBraceLoc = advanceLocBegin(Loc, Type.getLeftBrace()); |
| auto RBraceLoc = advanceLocBegin(Loc, Type.getRightBrace()); |
| |
| SourceLoc LAngleLoc, RAngleLoc; |
| SmallVector<TypeRepr *, 4> Args; |
| if (auto genericArgs = Type.getGenericArgumentClause()) { |
| if (genericArgs->getRightAngleBracket().isMissing()) |
| return nullptr; |
| generate(*genericArgs, Loc, LAngleLoc, RAngleLoc, Args); |
| } |
| |
| auto SILType = SILBoxTypeRepr::create(Context, generics, LBraceLoc, Fields, |
| RBraceLoc, LAngleLoc, Args, RAngleLoc); |
| return SILType; |
| } |
| |
| TypeRepr *ASTGen::generate(const SILFunctionTypeSyntax &Type, |
| const SourceLoc Loc, bool IsSILFuncDecl) { |
| // If this is part of a sil function decl, generic parameters are visible in |
| // the function body; otherwise, they are visible when parsing the type. |
| Optional<Scope> GenericsScope; |
| if (!IsSILFuncDecl) |
| GenericsScope.emplace(&P, ScopeKind::Generics); |
| |
| GenericParamList *generics = nullptr; |
| if (auto genericParamsSyntax = Type.getGenericParameterClauses()) |
| generics = generate(*genericParamsSyntax, Loc); |
| |
| auto tyR = cast<FunctionTypeRepr>(generate(Type.getFunction(), Loc)); |
| return new (Context) |
| FunctionTypeRepr(generics, tyR->getArgsTypeRepr(), tyR->getThrowsLoc(), |
| tyR->getArrowLoc(), tyR->getResultTypeRepr()); |
| } |
| |
| TypeRepr *ASTGen::generate(const CodeCompletionTypeSyntax &Type, |
| const SourceLoc Loc) { |
| auto base = Type.getBase(); |
| if (!base) { |
| if (P.CodeCompletion) |
| P.CodeCompletion->completeTypeSimpleBeginning(); |
| return nullptr; |
| } |
| |
| if (P.CodeCompletion) { |
| if (auto *parsedTyR = generate(*base, Loc)) { |
| P.CodeCompletion->setParsedTypeLoc(parsedTyR); |
| if (Type.getPeriod()) |
| P.CodeCompletion->completeTypeIdentifierWithDot(); |
| else |
| P.CodeCompletion->completeTypeIdentifierWithoutDot(); |
| } |
| } |
| |
| // Return nullptr to typecheck this TypeRepr independently in code completion. |
| return nullptr; |
| } |
| |
| TypeRepr *ASTGen::generate(const UnknownTypeSyntax &Type, const SourceLoc Loc) { |
| auto ChildrenCount = Type.getNumChildren(); |
| |
| // Recover from old-style protocol composition: |
| // `protocol` `<` protocols `>` |
| if (ChildrenCount >= 2) { |
| auto keyword = Type.getChild(0)->getAs<TokenSyntax>(); |
| |
| if (keyword && keyword->getText() == "protocol") { |
| auto keywordLoc = advanceLocBegin(Loc, *keyword); |
| auto LAngle = Type.getChild(1); |
| auto RAngle = Type.getChild(ChildrenCount - 1); |
| |
| auto LAngleLoc = advanceLocBegin(Loc, *LAngle); |
| auto RAngleLoc = advanceLocBegin(Loc, *RAngle); |
| |
| SmallVector<TypeRepr *, 4> protocols; |
| for (unsigned i = 2; i < Type.getNumChildren(); i++) { |
| if (auto elem = Type.getChild(i)->getAs<TypeSyntax>()) |
| if (auto proto = generate(*elem, Loc)) |
| protocols.push_back(proto); |
| } |
| |
| return CompositionTypeRepr::create(Context, protocols, keywordLoc, |
| {LAngleLoc, RAngleLoc}); |
| } |
| } |
| |
| // Create ErrorTypeRepr for keywords. |
| if (ChildrenCount == 1) { |
| auto Keyword = Type.getChild(0)->getAs<TokenSyntax>(); |
| if (Keyword && isTokenKeyword(Keyword->getTokenKind())) { |
| auto ErrorLoc = generate(*Keyword, Loc); |
| return new (Context) ErrorTypeRepr(ErrorLoc); |
| } |
| } |
| |
| // Create empty TupleTypeRepr for types starting with `(`. |
| if (ChildrenCount >= 1) { |
| auto LParen = Type.getChild(0)->getAs<TokenSyntax>(); |
| if (LParen && LParen->getTokenKind() == tok::l_paren) { |
| // generate child 'TypeSyntax' anyway to trigger the side effects e.g. |
| // code-completion. |
| for (size_t i = 1; i != ChildrenCount; ++i) { |
| auto elem = *Type.getChild(i); |
| if (auto ty = elem.getAs<TypeSyntax>()) |
| (void)generate(*ty, Loc); |
| } |
| auto LParenLoc = advanceLocBegin(Loc, *LParen); |
| auto EndLoc = |
| advanceLocBegin(Loc, *Type.getChild(Type.getNumChildren() - 1)); |
| return TupleTypeRepr::createEmpty(Context, {LParenLoc, EndLoc}); |
| } |
| } |
| |
| // generate child 'TypeSyntax' anyway to trigger the side effects e.g. |
| // code-completion. |
| for (size_t i = 0; i != ChildrenCount; ++i) { |
| auto elem = *Type.getChild(i); |
| if (auto ty = elem.getAs<TypeSyntax>()) |
| (void)generate(*ty, Loc); |
| } |
| |
| // let's hope the main `generate` method can find this node in the type map |
| return nullptr; |
| } |
| |
| void |
| ASTGen::generate(const GenericArgumentClauseSyntax &clause, const SourceLoc Loc, |
| SourceLoc &lAngleLoc, SourceLoc &rAngleLoc, |
| SmallVectorImpl<TypeRepr *> &args) { |
| lAngleLoc = advanceLocBegin(Loc, clause.getLeftAngleBracket()); |
| rAngleLoc = advanceLocBegin(Loc, clause.getRightAngleBracket()); |
| |
| assert(args.empty()); |
| for (auto Arg : clause.getArguments()) { |
| auto tyR = generate(Arg.getArgumentType(), Loc); |
| if (!tyR) |
| tyR = new (Context) ErrorTypeRepr(advanceLocBegin(Loc, Arg)); |
| args.push_back(tyR); |
| } |
| } |
| |
| StringRef ASTGen::copyAndStripUnderscores(StringRef Orig, ASTContext &Context) { |
| char *start = static_cast<char *>(Context.Allocate(Orig.size(), 1)); |
| char *p = start; |
| |
| if (p) { |
| for (char c : Orig) { |
| if (c != '_') { |
| *p++ = c; |
| } |
| } |
| } |
| |
| return StringRef(start, p - start); |
| } |
| |
| GenericParamList * |
| ASTGen::generate(const GenericParameterClauseListSyntax &clauses, |
| const SourceLoc Loc) { |
| GenericParamList *curr = nullptr; |
| |
| // The first one is the outmost generic parameter list. |
| for (const auto &clause : clauses) { |
| auto params = generate(clause, Loc); |
| if (!params) |
| continue; |
| params->setOuterParameters(curr); |
| curr = params; |
| } |
| |
| return curr; |
| } |
| |
| GenericParamList *ASTGen::generate(const GenericParameterClauseSyntax &clause, |
| const SourceLoc Loc) { |
| SmallVector<GenericTypeParamDecl *, 4> params; |
| params.reserve(clause.getGenericParameterList().getNumChildren()); |
| |
| for (auto elem : clause.getGenericParameterList()) { |
| auto nameTok = elem.getName(); |
| if (nameTok.isMissing()) |
| break; |
| |
| DeclAttributes attrs = generateDeclAttributes(elem, Loc, false); |
| Identifier name = Context.getIdentifier(elem.getName().getIdentifierText()); |
| SourceLoc nameLoc = advanceLocBegin(Loc, elem.getName()); |
| |
| // We always create generic type parameters with an invalid depth. |
| // Semantic analysis fills in the depth when it processes the generic |
| // parameter list. |
| auto param = new (Context) |
| GenericTypeParamDecl(P.CurDeclContext, name, nameLoc, |
| GenericTypeParamDecl::InvalidDepth, params.size()); |
| |
| if (auto inherited = elem.getInheritedType()) { |
| if (auto ty = generate(*inherited, Loc)) { |
| SmallVector<TypeLoc, 1> constraints = {ty}; |
| param->setInherited(Context.AllocateCopy(constraints)); |
| } |
| } |
| |
| // Attach attributes. |
| param->getAttrs() = attrs; |
| |
| // Add this parameter to the scope. |
| addToScope(param); |
| |
| params.push_back(param); |
| } |
| if (params.empty()) |
| return nullptr; |
| |
| SourceLoc whereLoc; |
| SmallVector<RequirementRepr, 4> requirements; |
| if (auto whereClause = clause.getObsoletedWhereClause()) { |
| requirements.reserve(whereClause->getRequirementList().size()); |
| for (auto elem : whereClause->getRequirementList()) { |
| if (auto req = generate(elem, Loc)) |
| requirements.push_back(*req); |
| } |
| // There's an invariant that valid 'where' loc means that there's at |
| // at least one valid requirement. |
| if (!requirements.empty()) |
| whereLoc = advanceLocBegin(Loc, whereClause->getWhereKeyword()); |
| } |
| |
| auto lAngleLoc = advanceLocBegin(Loc, clause.getLeftAngleBracket()); |
| auto rAngleLoc = advanceLocBegin(Loc, clause.getRightAngleBracket()); |
| return GenericParamList::create(Context, lAngleLoc, params, whereLoc, |
| requirements, rAngleLoc); |
| } |
| |
| Optional<RequirementRepr> |
| ASTGen::generate(const syntax::GenericRequirementSyntax &req, |
| const SourceLoc Loc) { |
| if (auto sameTypeReq = req.getBody().getAs<SameTypeRequirementSyntax>()) { |
| auto firstType = generate(sameTypeReq->getLeftTypeIdentifier(), Loc); |
| auto secondType = generate(sameTypeReq->getRightTypeIdentifier(), Loc); |
| if (!firstType || !secondType) |
| return None; |
| return RequirementRepr::getSameType( |
| firstType, advanceLocBegin(Loc, sameTypeReq->getEqualityToken()), |
| secondType); |
| } else if (auto conformanceReq = |
| req.getBody().getAs<ConformanceRequirementSyntax>()) { |
| auto firstType = generate(conformanceReq->getLeftTypeIdentifier(), Loc); |
| auto secondType = generate(conformanceReq->getRightTypeIdentifier(), Loc); |
| if (!firstType || !secondType) |
| return None; |
| return RequirementRepr::getTypeConstraint( |
| firstType, advanceLocBegin(Loc, conformanceReq->getColon()), |
| secondType); |
| } else if (auto layoutReq = req.getBody().getAs<LayoutRequirementSyntax>()) { |
| auto firstType = generate(layoutReq->getLeftTypeIdentifier(), Loc); |
| auto layout = generate(layoutReq->getLayoutConstraint(), Loc); |
| if (!firstType || layout.isNull()) |
| return None; |
| auto colonLoc = advanceLocBegin(Loc, layoutReq->getColon()); |
| auto layoutLoc = advanceLocBegin(Loc, layoutReq->getLayoutConstraint()); |
| return RequirementRepr::getLayoutConstraint( |
| firstType, colonLoc, LayoutConstraintLoc(layout, layoutLoc)); |
| } else { |
| llvm_unreachable("invalid syntax kind for requirement body"); |
| } |
| } |
| |
| static LayoutConstraintKind getLayoutConstraintKind(Identifier &id, |
| ASTContext &Ctx) { |
| if (id == Ctx.Id_TrivialLayout) |
| return LayoutConstraintKind::TrivialOfExactSize; |
| if (id == Ctx.Id_TrivialAtMostLayout) |
| return LayoutConstraintKind::TrivialOfAtMostSize; |
| if (id == Ctx.Id_RefCountedObjectLayout) |
| return LayoutConstraintKind::RefCountedObject; |
| if (id == Ctx.Id_NativeRefCountedObjectLayout) |
| return LayoutConstraintKind::NativeRefCountedObject; |
| if (id == Ctx.Id_ClassLayout) |
| return LayoutConstraintKind::Class; |
| if (id == Ctx.Id_NativeClassLayout) |
| return LayoutConstraintKind::NativeClass; |
| return LayoutConstraintKind::UnknownLayout; |
| } |
| |
| LayoutConstraint ASTGen::generate(const LayoutConstraintSyntax &constraint, |
| const SourceLoc Loc) { |
| auto name = Context.getIdentifier(constraint.getName().getIdentifierText()); |
| auto constraintKind = getLayoutConstraintKind(name, Context); |
| assert(constraintKind != LayoutConstraintKind::UnknownLayout); |
| |
| // Non-trivial constraint kinds don't have size/alignment. |
| // TODO: Diagnose if it's supplied? |
| if (!LayoutConstraintInfo::isTrivial(constraintKind)) |
| return LayoutConstraint::getLayoutConstraint(constraintKind, Context); |
| |
| // '_Trivial' without explicit size/alignment. |
| if (!constraint.getSize()) |
| return LayoutConstraint::getLayoutConstraint(LayoutConstraintKind::Trivial, |
| Context); |
| |
| int size = 0; |
| if (auto sizeSyntax = constraint.getSize()) |
| sizeSyntax->getText().getAsInteger(10, size); |
| assert(size >= 0); |
| |
| int alignment = 0; |
| if (auto alignmentSyntax = constraint.getAlignment()) |
| alignmentSyntax->getText().getAsInteger(10, alignment); |
| assert(alignment >= 0); |
| |
| return LayoutConstraint::getLayoutConstraint(constraintKind, size, alignment, |
| Context); |
| } |
| |
| SourceLoc ASTGen::advanceLocBegin(const SourceLoc &Loc, const Syntax &Node) { |
| return Loc.getAdvancedLoc(Node.getAbsolutePosition().getOffset()); |
| } |
| |
| StringRef ASTGen::copyAndStripUnderscores(StringRef Orig) { |
| return copyAndStripUnderscores(Orig, Context); |
| } |
| |
| Expr * |
| ASTGen::generateMagicIdentifierLiteralExpression(const TokenSyntax &PoundToken, |
| const SourceLoc Loc) { |
| auto Kind = getMagicIdentifierLiteralKind(PoundToken.getTokenKind()); |
| auto KindLoc = advanceLocBegin(Loc, PoundToken); |
| return new (Context) MagicIdentifierLiteralExpr(Kind, KindLoc); |
| } |
| |
| MagicIdentifierLiteralExpr::Kind |
| ASTGen::getMagicIdentifierLiteralKind(tok Kind) { |
| switch (Kind) { |
| case tok::kw___COLUMN__: |
| case tok::pound_column: |
| return MagicIdentifierLiteralExpr::Kind::Column; |
| case tok::kw___FILE__: |
| case tok::pound_file: |
| return MagicIdentifierLiteralExpr::Kind::File; |
| case tok::kw___FUNCTION__: |
| case tok::pound_function: |
| return MagicIdentifierLiteralExpr::Kind::Function; |
| case tok::kw___LINE__: |
| case tok::pound_line: |
| return MagicIdentifierLiteralExpr::Kind::Line; |
| case tok::kw___DSO_HANDLE__: |
| case tok::pound_dsohandle: |
| return MagicIdentifierLiteralExpr::Kind::DSOHandle; |
| default: |
| llvm_unreachable("not a magic literal"); |
| } |
| } |
| |
| ValueDecl *ASTGen::lookupInScope(DeclName Name) { |
| return P.lookupInScope(Name); |
| } |
| |
| void ASTGen::addToScope(ValueDecl *D, bool diagnoseRedefinitions) { |
| P.addToScope(D, diagnoseRedefinitions); |
| } |
| |
| TypeRepr *ASTGen::cacheType(TypeSyntax Type, TypeRepr *TypeAST) { |
| TypeCache[Type.getId()] = TypeAST; |
| return TypeAST; |
| } |
| |
| TypeRepr *ASTGen::lookupType(TypeSyntax Type) { |
| auto Found = TypeCache.find(Type.getId()); |
| return Found != TypeCache.end() ? Found->second : nullptr; |
| } |
| |
| void ASTGen::addDeclAttributes(DeclAttributes attrs, SourceLoc Loc) { |
| ParsedDeclAttrs.insert({Loc, attrs}); |
| } |
| |
| bool ASTGen::hasDeclAttributes(SourceLoc Loc) const { |
| return ParsedDeclAttrs.find(Loc) != ParsedDeclAttrs.end(); |
| } |
| |
| DeclAttributes ASTGen::getDeclAttributes(SourceLoc Loc) const { |
| return ParsedDeclAttrs.find(Loc)->second; |
| } |