Skip to content

Commit 61ee914

Browse files
committed
Introduce callables.
Introduce callables: values that can be "called" like functions. Add a new `call` declaration kind to represent callable methods.
1 parent de65d30 commit 61ee914

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

55 files changed

+1217
-250
lines changed

include/swift/AST/Decl.h

Lines changed: 80 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ namespace swift {
5454
struct ASTNode;
5555
class ASTPrinter;
5656
class ASTWalker;
57+
class CallDecl;
5758
class ConstructorDecl;
5859
class DestructorDecl;
5960
class DiagnosticEngine;
@@ -137,6 +138,7 @@ enum class DescriptiveDeclKind : uint8_t {
137138
GenericStruct,
138139
GenericClass,
139140
GenericType,
141+
Call,
140142
Subscript,
141143
Constructor,
142144
Destructor,
@@ -3296,6 +3298,21 @@ class NominalTypeDecl : public GenericTypeDecl, public IterableDeclContext {
32963298
ToStoredPropertyOrMissingMemberPlaceholder());
32973299
}
32983300

3301+
private:
3302+
/// Predicate used to filter CallDeclRange.
3303+
struct ToCallDecl {
3304+
ToCallDecl() {}
3305+
Optional<CallDecl *> operator()(Decl *decl) const;
3306+
};
3307+
3308+
public:
3309+
/// A range for iterating the call declarations of a nominal type.
3310+
using CallDeclRange = OptionalTransformRange<DeclRange,
3311+
ToCallDecl>;
3312+
3313+
/// Return a collection of the call declarations of this nominal type.
3314+
CallDeclRange getCallDeclarations() const;
3315+
32993316
// Implement isa/cast/dyncast/etc.
33003317
static bool classof(const Decl *D) {
33013318
return D->getKind() >= DeclKind::First_NominalTypeDecl &&
@@ -5732,7 +5749,8 @@ class FuncDecl : public AbstractFunctionDecl {
57325749

57335750
static bool classof(const Decl *D) {
57345751
return D->getKind() == DeclKind::Func ||
5735-
D->getKind() == DeclKind::Accessor;
5752+
D->getKind() == DeclKind::Accessor ||
5753+
D->getKind() == DeclKind::Call;
57365754
}
57375755
static bool classof(const AbstractFunctionDecl *D) {
57385756
return classof(static_cast<const Decl*>(D));
@@ -5885,7 +5903,53 @@ AbstractStorageDecl::AccessorRecord::getAccessor(AccessorKind kind) const {
58855903
}
58865904
return nullptr;
58875905
}
5888-
5906+
5907+
/// CallDecl - Declares a callable method for a type. For example:
5908+
///
5909+
/// \code
5910+
/// struct Adder {
5911+
/// var base: Int
5912+
/// call(_ x: Int) -> Int {
5913+
/// return base + x
5914+
/// }
5915+
/// }
5916+
/// \endcode
5917+
class CallDecl final : public FuncDecl {
5918+
CallDecl(DeclName fullName, SourceLoc declLoc, bool throws,
5919+
SourceLoc throwsLoc, unsigned numParameterLists,
5920+
GenericParamList *genericParams, DeclContext *parent)
5921+
: FuncDecl(DeclKind::Call,
5922+
/*staticLoc*/ SourceLoc(), StaticSpellingKind::None,
5923+
/*func loc*/ declLoc, /*name*/ fullName, /*name loc*/ declLoc,
5924+
throws, throwsLoc, numParameterLists, genericParams, parent) {}
5925+
5926+
static CallDecl *createImpl(ASTContext &ctx, DeclName fullName,
5927+
SourceLoc declLoc, bool throws,
5928+
SourceLoc throwsLoc,
5929+
GenericParamList *genericParams,
5930+
DeclContext *parent, ClangNode clangNode);
5931+
5932+
public:
5933+
static CallDecl *create(ASTContext &ctx, DeclName fullName, SourceLoc declLoc,
5934+
bool throws, SourceLoc throwsLoc,
5935+
GenericParamList *genericParams,
5936+
ParameterList *parameterList,
5937+
TypeLoc fnRetType, DeclContext *parent,
5938+
ClangNode clangNode = ClangNode());
5939+
5940+
static bool classof(const Decl *D) {
5941+
return D->getKind() == DeclKind::Call;
5942+
}
5943+
static bool classof(const AbstractFunctionDecl *D) {
5944+
return classof(static_cast<const Decl*>(D));
5945+
}
5946+
static bool classof(const DeclContext *DC) {
5947+
if (auto D = DC->getAsDecl())
5948+
return classof(D);
5949+
return false;
5950+
}
5951+
};
5952+
58895953
/// This represents a 'case' declaration in an 'enum', which may declare
58905954
/// one or more individual comma-separated EnumElementDecls.
58915955
class EnumCaseDecl final : public Decl,
@@ -6775,6 +6839,13 @@ ::operator()(Decl *decl) const {
67756839
return None;
67766840
}
67776841

6842+
inline Optional<CallDecl *>
6843+
NominalTypeDecl::ToCallDecl::operator()(Decl *decl) const {
6844+
if (auto callDecl = dyn_cast<CallDecl>(decl))
6845+
return callDecl;
6846+
return None;
6847+
}
6848+
67786849
inline void
67796850
AbstractStorageDecl::overwriteSetterAccess(AccessLevel accessLevel) {
67806851
Accessors.setInt(accessLevel);
@@ -6808,6 +6879,7 @@ inline ParamDecl **AbstractFunctionDecl::getImplicitSelfDeclStorage() {
68086879
return cast<DestructorDecl>(this)->getImplicitSelfDeclStorage();
68096880
case DeclKind::Func:
68106881
case DeclKind::Accessor:
6882+
case DeclKind::Call:
68116883
return cast<FuncDecl>(this)->getImplicitSelfDeclStorage();
68126884
}
68136885
}
@@ -6816,11 +6888,12 @@ inline ParamDecl **FuncDecl::getImplicitSelfDeclStorage() {
68166888
if (!hasImplicitSelfDecl())
68176889
return nullptr;
68186890

6819-
if (!isa<AccessorDecl>(this)) {
6820-
assert(getKind() == DeclKind::Func && "no new kinds of functions");
6821-
return reinterpret_cast<ParamDecl **>(this+1);
6822-
}
6823-
return reinterpret_cast<ParamDecl **>(static_cast<AccessorDecl*>(this)+1);
6891+
if (isa<AccessorDecl>(this))
6892+
return reinterpret_cast<ParamDecl **>(static_cast<AccessorDecl *>(this)+1);
6893+
else if (isa<CallDecl>(this))
6894+
return reinterpret_cast<ParamDecl **>(static_cast<CallDecl *>(this)+1);
6895+
assert(getKind() == DeclKind::Func && "no new kinds of functions");
6896+
return reinterpret_cast<ParamDecl **>(this+1);
68246897
}
68256898

68266899
inline DeclIterator &DeclIterator::operator++() {

include/swift/AST/DeclNodes.def

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,8 @@ ABSTRACT_DECL(Value, Decl)
170170
ABSTRACT_FUNCTION_DECL(Destructor, AbstractFunctionDecl)
171171
ABSTRACT_FUNCTION_DECL(Func, AbstractFunctionDecl)
172172
ABSTRACT_FUNCTION_DECL(Accessor, FuncDecl)
173-
DECL_RANGE(AbstractFunction, Constructor, Accessor)
173+
ABSTRACT_FUNCTION_DECL(Call, FuncDecl)
174+
DECL_RANGE(AbstractFunction, Constructor, Call)
174175
CONTEXT_VALUE_DECL(EnumElement, ValueDecl)
175176
DECL_RANGE(Value, Enum, EnumElement)
176177

include/swift/AST/DiagnosticsParse.def

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -395,6 +395,16 @@ ERROR(subscript_without_get,none,
395395
ERROR(subscript_static,none,
396396
"subscript cannot be marked %0", (StaticSpellingKind))
397397

398+
// `call` member
399+
ERROR(call_decl_static,none,
400+
"'call' member cannot be marked %0", (StaticSpellingKind))
401+
ERROR(call_decl_wrong_scope,none,
402+
"'call' members may only be declared within a type", ())
403+
ERROR(expected_lparen_call,PointsToFirstBadToken,
404+
"expected '(' for 'call' member parameters", ())
405+
ERROR(call_decl_cannot_have_name,PointsToFirstBadToken,
406+
"'call' member cannot have a name", ())
407+
398408
// initializer
399409
ERROR(invalid_nested_init,none,
400410
"missing '%select{super.|self.}0' at initializer invocation", (bool))

include/swift/AST/DiagnosticsSema.def

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1051,6 +1051,9 @@ NOTE(archetype_declared_in_type,none,
10511051
NOTE(unbound_generic_parameter_explicit_fix,none,
10521052
"explicitly specify the generic arguments to fix this issue", ())
10531053

1054+
ERROR(missing_call_decl,none,
1055+
"%0 does not define 'call' declaration of type", (Type))
1056+
10541057
ERROR(invalid_dynamic_callable_type,none,
10551058
"@dynamicCallable attribute requires %0 to have either a valid "
10561059
"'dynamicallyCall(withArguments:)' method or "
@@ -1765,8 +1768,8 @@ NOTE(inherited_protocol_does_not_conform,none,
17651768
"type %0 does not conform to inherited protocol %1", (Type, Type))
17661769
NOTE(no_witnesses,none,
17671770
"protocol requires "
1768-
"%select{initializer %1|function %1|property %1|subscript}0 with type %2"
1769-
"%select{|; do you want to add a stub?}3",
1771+
"%select{initializer %1|function %1|property %1|subscript|'call' member}0 "
1772+
"with type %2%select{|; do you want to add a stub?}3",
17701773
(RequirementKind, DeclName, Type, bool))
17711774
NOTE(missing_witnesses_general,none, "do you want to add protocol stubs?",
17721775
())

include/swift/AST/DiagnosticsSema.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,8 @@ namespace swift {
2929
Constructor,
3030
Func,
3131
Var,
32-
Subscript
32+
Subscript,
33+
Call
3334
};
3435

3536
// Declare common diagnostics objects with their appropriate types.

include/swift/AST/Identifier.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -221,8 +221,8 @@ class DeclBaseName {
221221
};
222222

223223
private:
224-
/// In a special DeclName represenenting a subscript, this opaque pointer
225-
/// is used as the data of the base name identifier.
224+
/// In a special DeclName representing a subscript, this opaque pointer is
225+
/// used as the data of the base name identifier.
226226
/// This is an implementation detail that should never leak outside of
227227
/// DeclName.
228228
static void *SubscriptIdentifierData;

include/swift/Demangling/DemangleNodes.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ NODE(BoundGenericOtherNominalType)
4343
NODE(BoundGenericTypeAlias)
4444
NODE(BoundGenericFunction)
4545
NODE(BuiltinTypeName)
46+
CONTEXT_NODE(CallDeclaration)
4647
NODE(CFunctionPointer)
4748
CONTEXT_NODE(Class)
4849
NODE(ClassMetadataBaseOffset)

include/swift/IDE/CodeCompletion.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -398,6 +398,7 @@ enum class CodeCompletionDeclKind {
398398
Constructor,
399399
Destructor,
400400
Subscript,
401+
Call,
401402
StaticMethod,
402403
InstanceMethod,
403404
PrefixOperatorFunction,

include/swift/IDE/SyntaxModel.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ enum class SyntaxStructureKind : uint8_t {
9797
EnumElement,
9898
TypeAlias,
9999
Subscript,
100+
Call,
100101
AssociatedType,
101102
GenericTypeParam,
102103

include/swift/Parse/Parser.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -520,7 +520,8 @@ class Parser {
520520
}
521521

522522
SourceLoc consumeIdentifier(Identifier *Result = nullptr) {
523-
assert(Tok.isAny(tok::identifier, tok::kw_self, tok::kw_Self));
523+
assert(Tok.isAny(tok::identifier, tok::kw_self, tok::kw_Self,
524+
tok::kw_call));
524525
if (Result)
525526
*Result = Context.getIdentifier(Tok.getText());
526527
return consumeToken();
@@ -1005,6 +1006,8 @@ class Parser {
10051006
ParserResult<ProtocolDecl> parseDeclProtocol(ParseDeclOptions Flags,
10061007
DeclAttributes &Attributes);
10071008

1009+
ParserResult<CallDecl>
1010+
parseDeclCall(ParseDeclOptions Flags, DeclAttributes &Attributes);
10081011
ParserResult<SubscriptDecl>
10091012
parseDeclSubscript(ParseDeclOptions Flags, DeclAttributes &Attributes,
10101013
SmallVectorImpl<Decl *> &Decls);
@@ -1160,6 +1163,8 @@ class Parser {
11601163
Closure,
11611164
/// A subscript.
11621165
Subscript,
1166+
/// A call declaration.
1167+
Call,
11631168
/// A curried argument clause.
11641169
Curried,
11651170
/// An enum element.
@@ -1198,6 +1203,7 @@ class Parser {
11981203
DefaultArgumentInfo &defaultArgs);
11991204
ParserStatus parseFunctionSignature(Identifier functionName,
12001205
DeclName &fullName,
1206+
ParameterContextKind paramContext,
12011207
ParameterList *&bodyParams,
12021208
DefaultArgumentInfo &defaultArgs,
12031209
SourceLoc &throws,

0 commit comments

Comments
 (0)