mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
250 lines
8.9 KiB
C++
250 lines
8.9 KiB
C++
//===--- AccessorKinds.def - Swift accessor metaprogramming -----*- C++ -*-===//
|
|
//
|
|
// This source file is part of the Swift.org open source project
|
|
//
|
|
// Copyright (c) 2014 - 2025 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
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This file defines macros used for macro-metaprogramming with accessor kinds.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#if defined(ACCESSOR) && defined(ACCESSOR_KEYWORD)
|
|
#error do not define both ACCESSOR and ACCESSOR_KEYWORD
|
|
#elif !defined(ACCESSOR) && !defined(ACCESSOR_KEYWORD)
|
|
#error must define either ACCESSOR or ACCESSOR_KEYWORD
|
|
#endif
|
|
|
|
/// ACCESSOR(ID, KEYWORD)
|
|
/// There is an accessor with the enumerator value AccessorKind::ID.
|
|
#if !defined(ACCESSOR) && defined(ACCESSOR_KEYWORD)
|
|
#define ACCESSOR(ID, KEYWORD)
|
|
#endif
|
|
|
|
/// SINGLETON_ACCESSOR(ID, KEYWORD)
|
|
/// The given accessor has only one matching accessor keyword.
|
|
///
|
|
/// Defaults to ACCESSOR(ID, KEYWORD) or ACCESSOR_KEYWORD(KEYWORD), depending
|
|
/// on which is defined.
|
|
#ifndef SINGLETON_ACCESSOR
|
|
#if defined(ACCESSOR_KEYWORD)
|
|
#define SINGLETON_ACCESSOR(ID, KEYWORD) ACCESSOR_KEYWORD(KEYWORD)
|
|
#else
|
|
#define SINGLETON_ACCESSOR(ID, KEYWORD) ACCESSOR(ID, KEYWORD)
|
|
#endif
|
|
#endif
|
|
|
|
/// OBSERVING_ACCESSOR(ID, KEYWORD)
|
|
/// The given accessor is an observing accessor.
|
|
///
|
|
/// Defaults to SINGLETON_ACCESSOR(ID, KEYWORD).
|
|
#ifndef OBSERVING_ACCESSOR
|
|
#define OBSERVING_ACCESSOR(ID, KEYWORD) SINGLETON_ACCESSOR(ID, KEYWORD)
|
|
#endif
|
|
|
|
/// OPAQUE_ACCESSOR(ID, KEYWORD)
|
|
/// The given accessor is used in the opaque access pattern and is created
|
|
/// for (mutable) storage whenever its implementation is unknown, such as
|
|
/// when it is resilient, overridable, or accessed through a protocol.
|
|
///
|
|
/// Defaults to SINGLETON_ACCESSOR(ID, KEYWORD).
|
|
#ifndef OPAQUE_ACCESSOR
|
|
#define OPAQUE_ACCESSOR(ID, KEYWORD) SINGLETON_ACCESSOR(ID, KEYWORD)
|
|
#endif
|
|
|
|
/// OBJC_ACCESSOR(ID, KEYWORD)
|
|
/// The given accessor is used in Objective-C, i.e. it is a getter or setter.
|
|
///
|
|
/// Defaults to OPAQUE_ACCESSOR(ID, KEYWORD).
|
|
#ifndef OBJC_ACCESSOR
|
|
#define OBJC_ACCESSOR(ID, KEYWORD) OPAQUE_ACCESSOR(ID, KEYWORD)
|
|
#endif
|
|
|
|
/// COROUTINE_ACCESSOR(ID, KEYWORD)
|
|
/// The given accessor is a coroutine accessor, i.e. a reader or modifier.
|
|
///
|
|
/// Defaults to OPAQUE_ACCESSOR(ID, KEYWORD).
|
|
#ifndef COROUTINE_ACCESSOR
|
|
#define COROUTINE_ACCESSOR(ID, KEYWORD) OPAQUE_ACCESSOR(ID, KEYWORD)
|
|
#endif
|
|
|
|
/// EXPERIMENTAL_COROUTINE_ACCESSOR(ID, KEYWORD, FEATURE)
|
|
/// The given coroutine accessor is experimental.
|
|
///
|
|
/// Defaults to COROUTINE_ACCESSOR(ID, KEYWORD)
|
|
#ifndef EXPERIMENTAL_COROUTINE_ACCESSOR
|
|
#define EXPERIMENTAL_COROUTINE_ACCESSOR(ID, KEYWORD, FEATURE) COROUTINE_ACCESSOR(ID, KEYWORD)
|
|
#endif
|
|
|
|
/// ANY_ADDRESSOR(ID, KEYWORD)
|
|
/// The given keyword corresponds to an addressor of the given kind.
|
|
///
|
|
/// Defaults to SINGLETON_ACCESSOR(ID, KEYWORD).
|
|
#ifndef ANY_ADDRESSOR
|
|
#define ANY_ADDRESSOR(ID, KEYWORD) \
|
|
SINGLETON_ACCESSOR(ID, KEYWORD)
|
|
#endif
|
|
|
|
/// IMMUTABLE_ADDRESSOR(ID, KEYWORD)
|
|
/// The given keyword corresponds to an immutable addressor of the given kind.
|
|
///
|
|
/// DEfaults to ANY_ADDRESSOR(ID, KEYWORD).
|
|
#ifndef IMMUTABLE_ADDRESSOR
|
|
#define IMMUTABLE_ADDRESSOR(ID, KEYWORD) \
|
|
ANY_ADDRESSOR(ID, KEYWORD)
|
|
#endif
|
|
|
|
/// MUTABLE_ADDRESSOR(ID, KEYWORD)
|
|
/// The given keyword corresponds to a mutable addressor of the given kind.
|
|
///
|
|
/// DEfaults to ANY_ADDRESSOR(ID, KEYWORD).
|
|
#ifndef MUTABLE_ADDRESSOR
|
|
#define MUTABLE_ADDRESSOR(ID, KEYWORD) \
|
|
ANY_ADDRESSOR(ID, KEYWORD)
|
|
#endif
|
|
|
|
/// INIT_ACCESSOR(ID, KEYWORD)
|
|
/// The given accessor is an init accessor.
|
|
///
|
|
/// Defaults to SINGLETON_ACCESSOR(ID, KEYWORD).
|
|
#ifndef INIT_ACCESSOR
|
|
#define INIT_ACCESSOR(ID, KEYWORD) SINGLETON_ACCESSOR(ID, KEYWORD)
|
|
#endif
|
|
|
|
#ifndef BORROW_ACCESSOR
|
|
#define BORROW_ACCESSOR(ID, KEYWORD) SINGLETON_ACCESSOR(ID, KEYWORD)
|
|
#endif
|
|
|
|
#ifndef MUTATE_ACCESSOR
|
|
#define MUTATE_ACCESSOR(ID, KEYWORD) SINGLETON_ACCESSOR(ID, KEYWORD)
|
|
#endif
|
|
|
|
/// This is a getter: a function that is called when a value is loaded
|
|
/// from the storage. It returns an owned value of the storage type.
|
|
///
|
|
/// If the storage is not implemented with a getter, a getter can
|
|
/// always be synthesized. However, this will not be true when
|
|
/// move-only types are introduced.
|
|
OBJC_ACCESSOR(Get, get)
|
|
|
|
/// This is a "distributed thunk" getter, that is used for a "distributed var"
|
|
/// 'get { ... }' accessor.
|
|
///
|
|
/// A distributed thunk is mangled as it's Storage's name.
|
|
/// This is never invoked directly by user code, but whenever making calls on
|
|
/// a distributed actor and the target is not known to be local, we invoke the
|
|
/// thunk. This is equivalent to a `distributed_thunk' FuncDecl of a
|
|
/// 'distributed func'.
|
|
///
|
|
/// For the most part, its behavior is exactly the same as a normal getter.
|
|
OBJC_ACCESSOR(DistributedGet, _distributed_get)
|
|
|
|
/// This is a setter: a function that is called when a value is assigned
|
|
/// to the storage. It takes a value of the storage type as its
|
|
/// primary parameter, in addition to any index values that may be
|
|
/// required for a subscript.
|
|
///
|
|
/// If the storage is not implemented with a setter, a setter can
|
|
/// always be synthesized if the storage is mutable at all.
|
|
OBJC_ACCESSOR(Set, set)
|
|
|
|
/// This is a read accessor: a yield-once coroutine which is called when a
|
|
/// value is loaded from the storage, like a getter, but which works
|
|
/// by yielding a borrowed value of the storage type.
|
|
///
|
|
/// If the storage is not implemented with a read accessor then
|
|
/// one can always be synthesized (even if the storage type is move-only).
|
|
COROUTINE_ACCESSOR(Read, _read)
|
|
|
|
/// This is a read accessor: a yield-once coroutine which is called when a
|
|
/// value is loaded from the storage, like a getter, but which works
|
|
/// by yielding a borrowed value of the storage type.
|
|
///
|
|
/// If the storage is not implemented with a read accessor then
|
|
/// one can always be synthesized (even if the storage type is move-only).
|
|
EXPERIMENTAL_COROUTINE_ACCESSOR(Read2, read, CoroutineAccessors)
|
|
|
|
/// This is a modify accessor: a yield-once coroutine which is called when a
|
|
/// the storage is modified which works by yielding an inout value
|
|
/// of the storage type.
|
|
///
|
|
/// If the storage is not implemented with a modify accessor then
|
|
/// one can be synthesized if the storage is mutable at all.
|
|
COROUTINE_ACCESSOR(Modify, _modify)
|
|
|
|
/// This is a modify accessor: a yield-once coroutine which is called when a
|
|
/// the storage is modified which works by yielding an inout value
|
|
/// of the storage type.
|
|
///
|
|
/// If the storage is not implemented with a modify accessor then
|
|
/// one can be synthesized if the storage is mutable at all.
|
|
EXPERIMENTAL_COROUTINE_ACCESSOR(Modify2, modify, CoroutineAccessors)
|
|
|
|
/// This is a willSet observer: a function which "decorates" an
|
|
/// underlying assignment operation by being called prior to the
|
|
/// operation when a value is assigned to the storage.
|
|
///
|
|
/// willSet is essentially sugar for implementing a certain common
|
|
/// setter idiom.
|
|
OBSERVING_ACCESSOR(WillSet, willSet)
|
|
|
|
/// This is a didSet observer: a function which "decorates" an
|
|
/// underlying assignment operation by being called after the
|
|
/// operation when a value is assigned to the storage.
|
|
///
|
|
/// didSet is essentially sugar for implementing a certain common
|
|
/// setter idiom.
|
|
OBSERVING_ACCESSOR(DidSet, didSet)
|
|
|
|
/// This is an address-family accessor: a function that is called when
|
|
/// a value is loaded from the storage, like a getter, but which works
|
|
/// by returning a pointer to an immutable value of the storage type.
|
|
/// This kind of accessor also has an addressor kind.
|
|
///
|
|
/// Addressors are a way of proving more efficient access to storage
|
|
/// when it is already stored in memory (but not as a stored member
|
|
/// of the type).
|
|
IMMUTABLE_ADDRESSOR(Address, unsafeAddress)
|
|
|
|
/// This is a mutableAddress-family accessor: a function that is
|
|
/// called when the storage is modified and which works by returning
|
|
/// a pointer to a mutable value of the storage type.
|
|
/// This kind of accessor also has an addressor kind.
|
|
///
|
|
/// Addressors are a way of proving more efficient access to storage
|
|
/// when it is already stored in memory (but not as a stored member
|
|
/// of the type).
|
|
MUTABLE_ADDRESSOR(MutableAddress, unsafeMutableAddress)
|
|
|
|
/// This is an init accessor: a function that is called when DI
|
|
/// re-writes assignment to initialization.
|
|
INIT_ACCESSOR(Init, init)
|
|
|
|
BORROW_ACCESSOR(Borrow, borrow)
|
|
|
|
MUTATE_ACCESSOR(Mutate, mutate)
|
|
|
|
#ifdef LAST_ACCESSOR
|
|
LAST_ACCESSOR(Mutate)
|
|
#undef LAST_ACCESSOR
|
|
#endif
|
|
|
|
#undef INIT_ACCESSOR
|
|
#undef IMMUTABLE_ADDRESSOR
|
|
#undef MUTABLE_ADDRESSOR
|
|
#undef ANY_ADDRESSOR
|
|
#undef OBJC_ACCESSOR
|
|
#undef OPAQUE_ACCESSOR
|
|
#undef COROUTINE_ACCESSOR
|
|
#undef EXPERIMENTAL_COROUTINE_ACCESSOR
|
|
#undef OBSERVING_ACCESSOR
|
|
#undef SINGLETON_ACCESSOR
|
|
#undef ACCESSOR
|
|
#undef ACCESSOR_KEYWORD
|
|
#undef SUPPRESS_ARTIFICIAL_ACCESSORS
|