Skip to content

Commit 7157510

Browse files
committed
[Macros] Parse macro declarations.
1 parent 8adee85 commit 7157510

File tree

5 files changed

+158
-1
lines changed

5 files changed

+158
-1
lines changed

include/swift/AST/DiagnosticsParse.def

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1999,8 +1999,22 @@ ERROR(foreign_diagnostic,none,
19991999
"%0", (StringRef))
20002000

20012001
//------------------------------------------------------------------------------
2002-
// MARK: macro expansion
2002+
// MARK: macros
20032003
//------------------------------------------------------------------------------
2004+
ERROR(expected_macro_value_type,PointsToFirstBadToken,
2005+
"expected macro value type following ':'", ())
2006+
ERROR(no_default_arg_macro,none,
2007+
"default arguments are not allowed in macros", ())
2008+
ERROR(expected_lparen_macro,PointsToFirstBadToken,
2009+
"expected '(' for macro parameters or ':' for a value-like macro''", ())
2010+
ERROR(macro_decl_expected_arrow,none,
2011+
"expected '->' after macro parameter list", ())
2012+
ERROR(expected_type_macro_result,PointsToFirstBadToken,
2013+
"expected macro result type", ())
2014+
ERROR(macro_decl_expected_equal,none,
2015+
"expected '=' to introduce external macro name", ())
2016+
ERROR(macro_decl_expected_period,none,
2017+
"expected '.' between external macro module and type name", ())
20042018

20052019
ERROR(macro_expansion_expr_expected_macro_identifier,none,
20062020
"expected a macro identifier for a pound literal expression", ())

include/swift/Parse/Parser.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1216,6 +1216,8 @@ class Parser {
12161216
BodyAndFingerprint
12171217
parseAbstractFunctionBodyDelayed(AbstractFunctionDecl *AFD);
12181218

1219+
ParserResult<MacroDecl> parseDeclMacro(DeclAttributes &Attributes);
1220+
12191221
ParserStatus parsePrimaryAssociatedTypes(
12201222
SmallVectorImpl<PrimaryAssociatedTypeName> &AssocTypeNames);
12211223
ParserStatus parsePrimaryAssociatedTypeList(
@@ -1427,6 +1429,8 @@ class Parser {
14271429
Curried,
14281430
/// An enum element.
14291431
EnumElement,
1432+
/// A macro.
1433+
Macro,
14301434
};
14311435

14321436
/// Whether we are at the start of a parameter name when parsing a parameter.

include/swift/Parse/Token.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,7 @@ class Token {
157157
#define CONTEXTUAL_SIMPLE_DECL_ATTR(KW, ...) CONTEXTUAL_CASE(KW)
158158
#include "swift/AST/Attr.def"
159159
#undef CONTEXTUAL_CASE
160+
.Case("macro", true)
160161
.Default(false);
161162
}
162163

lib/Parse/ParseDecl.cpp

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4494,6 +4494,10 @@ bool Parser::isStartOfSwiftDecl(bool allowPoundIfAttributes) {
44944494
return Tok.is(tok::identifier);
44954495
}
44964496

4497+
// 'macro' name
4498+
if (Tok.isContextualKeyword("macro") && Tok2.is(tok::identifier))
4499+
return true;
4500+
44974501
// If the next token is obviously not the start of a decl, bail early.
44984502
if (!isKeywordPossibleDeclStart(Tok2))
44994503
return false;
@@ -4824,6 +4828,12 @@ Parser::parseDecl(ParseDeclOptions Flags,
48244828
break;
48254829
}
48264830

4831+
if (Tok.isContextualKeyword("macro") && peekToken().is(tok::identifier)) {
4832+
Tok.setKind(tok::contextual_keyword);
4833+
DeclResult = parseDeclMacro(Attributes);
4834+
break;
4835+
}
4836+
48274837
if (Flags.contains(PD_HasContainerType) &&
48284838
IsAtStartOfLineOrPreviousHadSemi) {
48294839

@@ -8976,6 +8986,127 @@ Parser::parseDeclPrecedenceGroup(ParseDeclOptions flags,
89768986
return makeParserResult(result);
89778987
}
89788988

8989+
ParserResult<MacroDecl> Parser::parseDeclMacro(DeclAttributes &Attributes) {
8990+
assert(Tok.isContextualKeyword("macro"));
8991+
SourceLoc macroLoc = consumeToken(); // 'macro'
8992+
8993+
Identifier macroName;
8994+
SourceLoc macroNameLoc;
8995+
ParserStatus status;
8996+
8997+
status |= parseIdentifierDeclName(
8998+
*this, macroName, macroNameLoc, "macro",
8999+
[&](const Token &next) {
9000+
return next.isAny(tok::colon, tok::l_paren) || startsWithLess(next);
9001+
});
9002+
if (status.isErrorOrHasCompletion())
9003+
return status;
9004+
9005+
DebuggerContextChange dcc (*this, macroName, DeclKind::Macro);
9006+
9007+
// Parse the generic-params, if present.
9008+
GenericParamList *genericParams = nullptr;
9009+
{
9010+
auto result = maybeParseGenericParams();
9011+
genericParams = result.getPtrOrNull();
9012+
if (result.hasCodeCompletion())
9013+
return makeParserCodeCompletionStatus();
9014+
}
9015+
9016+
// Parse the macro signature.
9017+
TypeRepr *resultType = nullptr;
9018+
ParameterList *parameterList = nullptr;
9019+
DeclName macroFullName;
9020+
if (consumeIf(tok::colon)) {
9021+
// Value-like macros.
9022+
auto type = parseType(diag::expected_macro_value_type);
9023+
status |= type;
9024+
if (status.isErrorOrHasCompletion())
9025+
return status;
9026+
9027+
resultType = type.getPtrOrNull();
9028+
macroFullName = macroName;
9029+
} else {
9030+
// Parameter list.
9031+
SmallVector<Identifier, 2> namePieces;
9032+
DefaultArgumentInfo defaultArgs;
9033+
auto parameterResult = parseSingleParameterClause(
9034+
ParameterContextKind::Macro, &namePieces, &defaultArgs);
9035+
status |= parameterResult;
9036+
parameterList = parameterResult.getPtrOrNull();
9037+
9038+
// ->
9039+
SourceLoc arrowLoc;
9040+
if (!consumeIf(tok::arrow, arrowLoc)) {
9041+
diagnose(Tok, diag::macro_decl_expected_arrow);
9042+
}
9043+
9044+
// Result type.
9045+
auto parsedResultType =
9046+
parseDeclResultType(diag::expected_type_macro_result);
9047+
resultType = parsedResultType.getPtrOrNull();
9048+
status |= parsedResultType;
9049+
if (status.isErrorOrHasCompletion())
9050+
return status;
9051+
9052+
macroFullName = DeclName(Context, macroName, namePieces);
9053+
}
9054+
9055+
// Parse '=' ModuleName . MacroTypeName
9056+
if (!consumeIf(tok::equal)) {
9057+
diagnose(Tok, diag::macro_decl_expected_equal);
9058+
}
9059+
9060+
// ModuleName
9061+
Identifier externalMacroModule;
9062+
SourceLoc externalMacroModuleLoc;
9063+
status |= parseIdentifierDeclName(
9064+
*this, externalMacroModule, externalMacroModuleLoc,
9065+
"external macro module",
9066+
[&](const Token &next) {
9067+
return next.is(tok::period);
9068+
});
9069+
if (status.isErrorOrHasCompletion())
9070+
return status;
9071+
9072+
// '.'
9073+
if (!consumeIf(tok::period)) {
9074+
diagnose(Tok, diag::macro_decl_expected_period);
9075+
}
9076+
9077+
// MacroTypeName
9078+
Identifier externalMacroTypeName;
9079+
SourceLoc externalMacroTypeNameLoc;
9080+
status |= parseIdentifierDeclName(
9081+
*this, externalMacroTypeName, externalMacroTypeNameLoc,
9082+
"external macro type name",
9083+
[&](const Token &next) {
9084+
return true;
9085+
});
9086+
if (status.isErrorOrHasCompletion())
9087+
return status;
9088+
9089+
// Create the macro declaration.
9090+
auto *macro = new (Context) MacroDecl(
9091+
MacroDecl::Kind::Expression, MacroDecl::ImplementationKind::Builtin,
9092+
macroName, CurDeclContext->getParentModule(), { }, nullptr);
9093+
9094+
// FIXME: Egregious hack.
9095+
macro->setImplicit();
9096+
9097+
// Parse a 'where' clause if present.
9098+
if (Tok.is(tok::kw_where)) {
9099+
auto whereStatus = parseFreestandingGenericWhereClause(macro);
9100+
if (whereStatus.hasCodeCompletion() && !CodeCompletion) {
9101+
// Trigger delayed parsing, no need to continue.
9102+
return whereStatus;
9103+
}
9104+
status |= whereStatus;
9105+
}
9106+
9107+
return dcc.fixupParserResult(status, macro);
9108+
}
9109+
89799110
ParserResult<MacroExpansionDecl>
89809111
Parser::parseDeclMacroExpansion(ParseDeclOptions flags,
89819112
DeclAttributes &attributes) {

lib/Parse/ParsePattern.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,9 @@ static ParserStatus parseDefaultArgument(
116116
case Parser::ParameterContextKind::Curried:
117117
diagID = diag::no_default_arg_curried;
118118
break;
119+
case Parser::ParameterContextKind::Macro:
120+
diagID = diag::no_default_arg_macro;
121+
break;
119122
}
120123

121124
assert((diagID.ID != DiagID()) == !defaultArgs &&
@@ -662,6 +665,7 @@ mapParsedParameters(Parser &parser,
662665
case Parser::ParameterContextKind::Curried:
663666
case Parser::ParameterContextKind::Initializer:
664667
case Parser::ParameterContextKind::Function:
668+
case Parser::ParameterContextKind::Macro:
665669
isKeywordArgumentByDefault = true;
666670
break;
667671
}
@@ -741,6 +745,9 @@ Parser::parseSingleParameterClause(ParameterContextKind paramContext,
741745
case ParameterContextKind::Initializer:
742746
diagID = diag::expected_lparen_initializer;
743747
break;
748+
case ParameterContextKind::Macro:
749+
diagID = diag::expected_lparen_macro;
750+
break;
744751
case ParameterContextKind::EnumElement:
745752
case ParameterContextKind::Closure:
746753
case ParameterContextKind::Curried:

0 commit comments

Comments
 (0)