mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
583 lines
22 KiB
C++
583 lines
22 KiB
C++
//===--- ArgumentList.h - Function and subscript argument lists -*- C++ -*-===//
|
|
//
|
|
// This source file is part of the Swift.org open source project
|
|
//
|
|
// Copyright (c) 2021 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 the Argument and ArgumentList classes and support logic.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#ifndef SWIFT_AST_ARGUMENTLIST_H
|
|
#define SWIFT_AST_ARGUMENTLIST_H
|
|
|
|
#include "swift/AST/ASTAllocated.h"
|
|
#include "swift/AST/Types.h"
|
|
#include "swift/Basic/Debug.h"
|
|
#include "llvm/ADT/STLExtras.h"
|
|
#include "llvm/Support/TrailingObjects.h"
|
|
#include <optional>
|
|
|
|
namespace swift {
|
|
/// Forward declared trampoline for Expr::getType.
|
|
Type __Expr_getType(Expr *E);
|
|
|
|
/// Represents a single argument in an argument list, including its label
|
|
/// information and inout-ness.
|
|
///
|
|
/// \code
|
|
/// foo.bar(arg, label: arg2, other: &arg3)
|
|
/// ^^^ ^^^^^^^^^^^^
|
|
/// an unlabeled 'other' is the label, 'arg3' is the expr,
|
|
/// argument and isInout() is true.
|
|
/// \endcode
|
|
class Argument final {
|
|
SourceLoc LabelLoc;
|
|
Identifier Label;
|
|
Expr *ArgExpr;
|
|
// TODO: Store inout bit here.
|
|
|
|
public:
|
|
Argument(SourceLoc labelLoc, Identifier label, Expr *expr)
|
|
: LabelLoc(labelLoc), Label(label), ArgExpr(expr) {}
|
|
|
|
/// Make an unlabeled argument.
|
|
static Argument unlabeled(Expr *expr) {
|
|
return Argument(SourceLoc(), Identifier(), expr);
|
|
}
|
|
|
|
/// Make an implicit unlabeled 'inout' argument.
|
|
static Argument implicitInOut(ASTContext &ctx, Expr *expr);
|
|
|
|
SourceLoc getStartLoc() const { return getSourceRange().Start; }
|
|
SourceLoc getEndLoc() const { return getSourceRange().End; }
|
|
SourceRange getSourceRange() const;
|
|
|
|
/// If the argument has a label with location information, returns the
|
|
/// location.
|
|
///
|
|
/// Note this may be present even if the label is empty, e.g for multiple
|
|
/// trailing closures where labels are required such as '_: {}'.
|
|
SourceLoc getLabelLoc() const { return LabelLoc; }
|
|
|
|
/// The argument label written in the call.
|
|
Identifier getLabel() const { return Label; }
|
|
|
|
/// Whether the argument has a non-empty label. Note that this returns `false`
|
|
/// for an explicitly specified empty label e.g `_: {}` for a trailing
|
|
/// closure.
|
|
bool hasLabel() const { return !Label.empty(); }
|
|
|
|
/// Set a new argument label.
|
|
///
|
|
/// Note this is marked \c & to prevent its use on an rvalue Argument vended
|
|
/// from an ArgumentList.
|
|
void setLabel(Identifier newLabel) & { Label = newLabel; }
|
|
|
|
/// The argument expression.
|
|
Expr *getExpr() const { return ArgExpr; }
|
|
|
|
/// Set a new argument expression.
|
|
///
|
|
/// Note this is marked \c & to prevent its use on an rvalue Argument vended
|
|
/// from an ArgumentList.
|
|
void setExpr(Expr *newExpr) & { ArgExpr = newExpr; }
|
|
|
|
/// Whether the argument is \c inout, denoted with the '&' prefix.
|
|
bool isInOut() const;
|
|
|
|
/// Whether the argument is a compile-time constant value.
|
|
bool isCompileTimeLiteral() const;
|
|
|
|
bool operator==(const Argument &other) const {
|
|
return LabelLoc == other.LabelLoc && Label == other.Label &&
|
|
ArgExpr == other.ArgExpr;
|
|
}
|
|
bool operator!=(const Argument &other) const { return !(*this == other); }
|
|
};
|
|
|
|
/// Represents the argument list of a function call or subscript access.
|
|
/// \code
|
|
/// foo.bar(arg, label: arg2, other: &arg3)
|
|
/// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
/// \endcode
|
|
///
|
|
/// Note that arguments are split up and stored in separate buffers to optimize
|
|
/// ArgumentList's memory footprint for the unlabeled cases.
|
|
class alignas(Argument) ArgumentList final
|
|
: public ASTAllocated<ArgumentList>,
|
|
private llvm::TrailingObjects<ArgumentList, Expr *, Identifier,
|
|
SourceLoc, ArgumentList *> {
|
|
friend TrailingObjects;
|
|
|
|
SourceLoc LParenLoc;
|
|
SourceLoc RParenLoc;
|
|
|
|
/// The number of arguments in the list.
|
|
unsigned NumArgs : 16;
|
|
|
|
/// The index of the first trailing closure, or \c NumArgs if there are
|
|
/// either no trailing closures, or the trailing closure info is present in
|
|
/// the original args.
|
|
unsigned RawFirstTrailingClosureIndex : 16;
|
|
|
|
/// Whether an original set of arguments are available.
|
|
bool HasOriginalArgs : 1;
|
|
|
|
/// Whether the argument list was implicitly generated.
|
|
bool IsImplicit : 1;
|
|
|
|
/// Whether any of the arguments are labeled.
|
|
bool HasLabels : 1;
|
|
|
|
/// Whether any of the arguments have labels with location info.
|
|
bool HasLabelLocs : 1;
|
|
|
|
ArgumentList(SourceLoc lParenLoc, SourceLoc rParenLoc, unsigned numArgs,
|
|
std::optional<unsigned> firstTrailingClosureIndex,
|
|
ArgumentList *originalArgs, bool isImplicit, bool hasLabels,
|
|
bool hasLabelLocs)
|
|
: LParenLoc(lParenLoc), RParenLoc(rParenLoc), NumArgs(numArgs),
|
|
HasOriginalArgs(originalArgs), IsImplicit(isImplicit),
|
|
HasLabels(hasLabels), HasLabelLocs(hasLabelLocs) {
|
|
assert(LParenLoc.isValid() == RParenLoc.isValid());
|
|
assert(!(firstTrailingClosureIndex && originalArgs) &&
|
|
"Cannot have trailing closure info if original args present");
|
|
assert(!(originalArgs && originalArgs->getStoredOriginalArgs()) &&
|
|
"Cannot chain original argument lists");
|
|
assert(NumArgs == numArgs && "Num args truncated");
|
|
assert(!firstTrailingClosureIndex || *firstTrailingClosureIndex < numArgs &&
|
|
"Invalid trailing closure index");
|
|
RawFirstTrailingClosureIndex =
|
|
firstTrailingClosureIndex.value_or(numArgs);
|
|
}
|
|
|
|
ArgumentList(const ArgumentList &) = delete;
|
|
ArgumentList &operator=(const ArgumentList &) = delete;
|
|
|
|
size_t numTrailingObjects(OverloadToken<Expr *>) const {
|
|
return NumArgs;
|
|
}
|
|
size_t numTrailingObjects(OverloadToken<Identifier>) const {
|
|
return HasLabels ? NumArgs : 0;
|
|
}
|
|
size_t numTrailingObjects(OverloadToken<SourceLoc>) const {
|
|
return HasLabelLocs ? NumArgs : 0;
|
|
}
|
|
size_t numTrailingObjects(OverloadToken<ArgumentList *>) const {
|
|
return HasOriginalArgs ? 1 : 0;
|
|
}
|
|
|
|
ArrayRef<Expr *> getExprsBuffer() const {
|
|
return {getTrailingObjects<Expr *>(), NumArgs};
|
|
}
|
|
MutableArrayRef<Expr *> getExprsBuffer() {
|
|
return {getTrailingObjects<Expr *>(), NumArgs};
|
|
}
|
|
|
|
ArrayRef<Identifier> getLabelsBuffer() const {
|
|
assert(HasLabels);
|
|
return {getTrailingObjects<Identifier>(), NumArgs};
|
|
}
|
|
MutableArrayRef<Identifier> getLabelsBuffer() {
|
|
assert(HasLabels);
|
|
return {getTrailingObjects<Identifier>(), NumArgs};
|
|
}
|
|
|
|
ArrayRef<SourceLoc> getLabelLocsBuffer() const {
|
|
assert(HasLabelLocs);
|
|
return {getTrailingObjects<SourceLoc>(), NumArgs};
|
|
}
|
|
MutableArrayRef<SourceLoc> getLabelLocsBuffer() {
|
|
assert(HasLabelLocs);
|
|
return {getTrailingObjects<SourceLoc>(), NumArgs};
|
|
}
|
|
|
|
ArgumentList *getStoredOriginalArgs() const {
|
|
if (!HasOriginalArgs)
|
|
return nullptr;
|
|
return *getTrailingObjects<ArgumentList *>();
|
|
}
|
|
|
|
public:
|
|
/// Create a new ArgumentList.
|
|
///
|
|
/// \param lParenLoc The location of the opening '('. Note that for a
|
|
/// subscript argument list, this will be for the opening '['.
|
|
/// \param args The list of arguments in the call.
|
|
/// \param rParenLoc The location of the closing ')'. Note that for a
|
|
/// subscript argument list, this will be for the closing ']'.
|
|
/// \param firstTrailingClosureIndex The index of the first trailing closure.
|
|
/// \param isImplicit Whether this is an implicitly generated argument list.
|
|
/// \param originalArgs An original argument list prior to being rewritten by
|
|
/// the expression type-checker. Note \p firstTrailingClosureIndex must be
|
|
/// \c None if an original argument list is available.
|
|
/// \param arena The arena to allocate the ArgumentList in.
|
|
static ArgumentList *
|
|
create(ASTContext &ctx, SourceLoc lParenLoc, ArrayRef<Argument> args,
|
|
SourceLoc rParenLoc, std::optional<unsigned> firstTrailingClosureIndex,
|
|
bool isImplicit, ArgumentList *originalArgs = nullptr,
|
|
AllocationArena arena = AllocationArena::Permanent);
|
|
|
|
/// Create a new explicit parsed ArgumentList.
|
|
///
|
|
/// \param lParenLoc The location of the opening '('. Note that for a
|
|
/// subscript argument list, this will be for the opening '['.
|
|
/// \param args The list of arguments in the call.
|
|
/// \param rParenLoc The location of the closing ')'. Note that for a
|
|
/// subscript argument list, this will be for the closing ']'.
|
|
/// \param firstTrailingClosureIndex The index of the first trailing closure.
|
|
static ArgumentList *
|
|
createParsed(ASTContext &ctx, SourceLoc lParenLoc, ArrayRef<Argument> args,
|
|
SourceLoc rParenLoc,
|
|
std::optional<unsigned> firstTrailingClosureIndex);
|
|
|
|
/// Create a new type-checked ArgumentList from an original set of arguments.
|
|
///
|
|
/// \param originalArgs An original argument list prior to being rewritten by
|
|
/// the type-checker.
|
|
/// \param newArgs The new set of arguments for the call.
|
|
static ArgumentList *createTypeChecked(ASTContext &ctx,
|
|
ArgumentList *originalArgs,
|
|
ArrayRef<Argument> newArgs);
|
|
|
|
/// Create a new implicit ArgumentList.
|
|
///
|
|
/// \param lParenLoc The location of the opening '('. Note that for a
|
|
/// subscript argument list, this will be for the opening '['.
|
|
/// \param args The list of arguments in the call.
|
|
/// \param rParenLoc The location of the closing ')'. Note that for a
|
|
/// subscript argument list, this will be for the closing ']'.
|
|
/// \param arena The arena to allocate the ArgumentList in.
|
|
static ArgumentList *createImplicit(
|
|
ASTContext &ctx, SourceLoc lParenLoc, ArrayRef<Argument> args,
|
|
SourceLoc rParenLoc,
|
|
std::optional<unsigned> firstTrailingClosureIndex = std::nullopt,
|
|
AllocationArena arena = AllocationArena::Permanent);
|
|
|
|
/// Create a new implicit ArgumentList with a set of \p args.
|
|
static ArgumentList *createImplicit(
|
|
ASTContext &ctx, ArrayRef<Argument> args,
|
|
std::optional<unsigned> firstTrailingClosureIndex = std::nullopt,
|
|
AllocationArena arena = AllocationArena::Permanent);
|
|
|
|
/// Create a new implicit ArgumentList with a single labeled argument
|
|
/// expression.
|
|
static ArgumentList *forImplicitSingle(ASTContext &ctx, Identifier label,
|
|
Expr *arg);
|
|
|
|
/// Create a new implicit ArgumentList with a set of unlabeled arguments.
|
|
static ArgumentList *forImplicitUnlabeled(ASTContext &ctx,
|
|
ArrayRef<Expr *> argExprs);
|
|
|
|
/// Create a new implicit ArgumentList with a set of argument expressions,
|
|
/// and a DeclNameRef from which to infer the argument labels.
|
|
static ArgumentList *forImplicitCallTo(DeclNameRef fnNameRef,
|
|
ArrayRef<Expr *> argExprs,
|
|
ASTContext &ctx);
|
|
|
|
/// Create a new implicit ArgumentList with a set of argument expressions,
|
|
/// and a ParameterList from which to infer the argument labels.
|
|
static ArgumentList *forImplicitCallTo(ParameterList *params,
|
|
ArrayRef<Expr *> argExprs,
|
|
ASTContext &ctx);
|
|
|
|
/// The location of the opening '('. Note that for a subscript argument list,
|
|
/// this will be for the opening '['.
|
|
SourceLoc getLParenLoc() const { return LParenLoc; }
|
|
|
|
/// The location of the closing ')'. Note that for a subscript argument list,
|
|
/// this will be for the closing ']'.
|
|
SourceLoc getRParenLoc() const { return RParenLoc; }
|
|
|
|
/// Whether this is an implicitly generated argument list, not written in the
|
|
/// source.
|
|
bool isImplicit() const { return IsImplicit; }
|
|
|
|
/// Whether the argument list has any non-empty argument labels.
|
|
bool hasAnyArgumentLabels() const { return HasLabels; }
|
|
|
|
SourceLoc getLoc() const;
|
|
SourceLoc getStartLoc() const { return getSourceRange().Start; }
|
|
SourceLoc getEndLoc() const { return getSourceRange().End; }
|
|
SourceRange getSourceRange() const;
|
|
|
|
/// Retrieve the argument expression at a given index.
|
|
Expr *getExpr(unsigned idx) const { return getExprsBuffer()[idx]; }
|
|
void setExpr(unsigned idx, Expr *newExpr) { getExprsBuffer()[idx] = newExpr; }
|
|
|
|
/// Retrieve the argument label at a given index.
|
|
Identifier getLabel(unsigned idx) const {
|
|
if (!HasLabels)
|
|
return Identifier();
|
|
return getLabelsBuffer()[idx];
|
|
}
|
|
|
|
/// Retrieve the argument label location at a given index.
|
|
SourceLoc getLabelLoc(unsigned idx) const {
|
|
if (!HasLabelLocs)
|
|
return SourceLoc();
|
|
return getLabelLocsBuffer()[idx];
|
|
}
|
|
|
|
/// Retrieve the argument at a given index.
|
|
Argument get(unsigned idx) const {
|
|
return Argument(getLabelLoc(idx), getLabel(idx), getExpr(idx));
|
|
}
|
|
|
|
// MARK: Iterator Logic
|
|
|
|
unsigned size() const { return NumArgs; }
|
|
bool empty() const { return size() == 0; }
|
|
|
|
class iterator final
|
|
: public llvm::indexed_accessor_iterator<iterator, const ArgumentList *,
|
|
Argument, const Argument *,
|
|
Argument> {
|
|
public:
|
|
iterator(const ArgumentList *argList, unsigned idx)
|
|
: indexed_accessor_iterator(argList, idx) {}
|
|
|
|
Argument operator*() const {
|
|
assert(getBase());
|
|
return getBase()->get(getIndex());
|
|
}
|
|
Argument operator[](unsigned i) const {
|
|
assert(getBase());
|
|
return getBase()->get(getIndex() + i);
|
|
}
|
|
};
|
|
|
|
iterator begin() const { return {this, 0}; }
|
|
iterator end() const { return {this, size()}; }
|
|
|
|
Argument front() const { return get(0); }
|
|
Argument back() const { return get(size() - 1); }
|
|
|
|
Argument operator[](unsigned idx) const { return get(idx); }
|
|
|
|
// MARK: Trailing Closure Queries
|
|
//
|
|
// Trailing closure queries cannot be done on a type-checked argument list,
|
|
// instead they must be done on the original argument list prior to rewriting
|
|
// in CSApply. This can be obtained by querying the \c getOriginalArgs method.
|
|
//
|
|
// This restriction is due to the fact that trailing closures in type-checked
|
|
// argument lists can have an awkward representation. They may be:
|
|
// - Nested within variadic expansion exprs, and may not be the first element
|
|
// of that expansion.
|
|
// - In a position *before* default argument expressions, or even explicitly
|
|
// written non-trailing arguments in certain backward scanning argument
|
|
// matching cases.
|
|
|
|
/// Returns the index of the first trailing closure in the argument list, or
|
|
/// \c None if there are no trailing closures.
|
|
///
|
|
/// Note for a type-checked argument list, this must be queried on
|
|
/// \c getOriginalArgs instead.
|
|
std::optional<unsigned> getFirstTrailingClosureIndex() const {
|
|
assert(!HasOriginalArgs && "Query original args instead");
|
|
if (RawFirstTrailingClosureIndex == NumArgs)
|
|
return std::nullopt;
|
|
return RawFirstTrailingClosureIndex;
|
|
}
|
|
|
|
/// The number of trailing closures in the argument list.
|
|
///
|
|
/// Note for a type-checked argument list, this must be queried on
|
|
/// \c getOriginalArgs instead.
|
|
unsigned getNumTrailingClosures() const {
|
|
assert(!HasOriginalArgs && "Query original args instead");
|
|
if (!getFirstTrailingClosureIndex())
|
|
return 0;
|
|
return size() - *getFirstTrailingClosureIndex();
|
|
}
|
|
|
|
/// Whether any unlabeled or labeled trailing closures are present.
|
|
bool hasAnyTrailingClosures() const {
|
|
return getOriginalArgs()->getFirstTrailingClosureIndex().has_value();
|
|
}
|
|
|
|
/// Whether a given index is for an unlabeled trailing closure, which is the
|
|
/// first trailing closure in the argument list.
|
|
///
|
|
/// Note for a type-checked argument list, this must be queried on
|
|
/// \c getOriginalArgs instead.
|
|
bool isUnlabeledTrailingClosureIndex(unsigned i) const {
|
|
assert(!HasOriginalArgs && "Query original args instead");
|
|
return hasAnyTrailingClosures() && *getFirstTrailingClosureIndex() == i;
|
|
}
|
|
|
|
/// Whether a given index is for a labeled trailing closure in an argument
|
|
/// list with multiple trailing closures.
|
|
///
|
|
/// Note for a type-checked argument list, this must be queried on
|
|
/// \c getOriginalArgs instead.
|
|
bool isLabeledTrailingClosureIndex(unsigned i) const {
|
|
assert(!HasOriginalArgs && "Query original args instead");
|
|
if (!hasAnyTrailingClosures())
|
|
return false;
|
|
return i > *getFirstTrailingClosureIndex() && i < size();
|
|
}
|
|
|
|
/// Whether a given index is for a labeled or unlabeled trailing closure.
|
|
///
|
|
/// Note for a type-checked argument list, this must be queried on
|
|
/// \c getOriginalArgs instead.
|
|
bool isTrailingClosureIndex(unsigned i) const {
|
|
assert(!HasOriginalArgs && "Query original args instead");
|
|
if (!hasAnyTrailingClosures())
|
|
return false;
|
|
return i >= *getFirstTrailingClosureIndex() && i < size();
|
|
}
|
|
|
|
/// Returns the range of arguments excluding any trailing closures.
|
|
///
|
|
/// Note for a type-checked argument list, this must be queried on
|
|
/// \c getOriginalArgs instead.
|
|
iterator_range<iterator> getNonTrailingArgs() const {
|
|
assert(!HasOriginalArgs && "Query original args instead");
|
|
auto idx = getFirstTrailingClosureIndex();
|
|
if (!idx.has_value())
|
|
return *this;
|
|
|
|
return {begin(), iterator(this, *idx)};
|
|
}
|
|
|
|
/// Returns the range of trailing closure arguments.
|
|
///
|
|
/// Note for a type-checked argument list, this must be queried on
|
|
/// \c getOriginalArgs instead.
|
|
iterator_range<iterator> getTrailingClosures() const {
|
|
assert(!HasOriginalArgs && "Query original args instead");
|
|
auto idx = getFirstTrailingClosureIndex();
|
|
if (!idx.has_value())
|
|
return {end(), end()};
|
|
|
|
return {iterator(this, *idx), end()};
|
|
}
|
|
|
|
/// Retrieve the first trailing closure argument in the argument list, or
|
|
/// \c None if there are no trailing closures.
|
|
///
|
|
/// Note for a type-checked argument list, this must be queried on
|
|
/// \c getOriginalArgs instead.
|
|
std::optional<Argument> getFirstTrailingClosure() const {
|
|
assert(!HasOriginalArgs && "Query original args instead");
|
|
auto idx = getFirstTrailingClosureIndex();
|
|
if (!idx.has_value())
|
|
return std::nullopt;
|
|
return get(*idx);
|
|
}
|
|
|
|
/// Retrieve the source range of any trailing closure arguments, or an empty
|
|
/// range if there are no trailing closures.
|
|
///
|
|
/// Note for a type-checked argument list, this must be queried on
|
|
/// \c getOriginalArgs instead.
|
|
SourceRange getTrailingSourceRange() const {
|
|
assert(!HasOriginalArgs && "Query original args instead");
|
|
auto firstClosure = getFirstTrailingClosure();
|
|
if (!firstClosure)
|
|
return SourceRange();
|
|
|
|
return SourceRange(firstClosure->getStartLoc(), back().getEndLoc());
|
|
}
|
|
|
|
// MARK: Misc Queries
|
|
|
|
/// Whether any of the arguments in the argument are inout.
|
|
bool hasAnyInOutArgs() const {
|
|
return llvm::any_of(*this, [](auto arg) { return arg.isInOut(); });
|
|
}
|
|
|
|
/// Whether the argument list has a single argument, which may be labeled or
|
|
/// unlabeled.
|
|
bool isUnary() const { return size() == 1; }
|
|
|
|
/// Whether the argument list has a single unlabeled argument.
|
|
bool isUnlabeledUnary() const { return isUnary() && getLabel(0).empty(); }
|
|
|
|
/// If the argument list has a single argument, which may be labeled or
|
|
/// unlabeled, returns its expression, or \c nullptr if this isn't a unary
|
|
/// argument list.
|
|
Expr *getUnaryExpr() const { return isUnary() ? getExpr(0) : nullptr; }
|
|
|
|
/// If the argument list has a single unlabeled argument, returns its
|
|
/// expression, or \c nullptr if this isn't an unlabeled unary argument list.
|
|
Expr *getUnlabeledUnaryExpr() const {
|
|
return isUnlabeledUnary() ? getExpr(0) : nullptr;
|
|
}
|
|
|
|
/// Retrieve an array of the argument expressions used in the argument list.
|
|
ArrayRef<Expr *> getArgExprs() const { return getExprsBuffer(); }
|
|
|
|
/// Retrieve an array of the argument labels used in the argument list.
|
|
ArrayRef<Identifier>
|
|
getArgumentLabels(SmallVectorImpl<Identifier> &scratch) const;
|
|
|
|
/// If the provided expression appears as one of the argument list's
|
|
/// arguments, returns its index. Otherwise returns \c None. By default this
|
|
/// will match against semantic sub-expressions, but that may be disabled by
|
|
/// passing \c false for \c allowSemantic.
|
|
std::optional<unsigned> findArgumentExpr(Expr *expr,
|
|
bool allowSemantic = true) const;
|
|
|
|
/// Creates a TupleExpr or ParenExpr that holds the argument exprs. A
|
|
/// ParenExpr will be returned for a single argument, otherwise a TupleExpr.
|
|
/// Don't use this function unless you actually need an AST transform.
|
|
Expr *packIntoImplicitTupleOrParen(
|
|
ASTContext &ctx,
|
|
llvm::function_ref<Type(Expr *)> getType = __Expr_getType) const;
|
|
|
|
/// Whether the argument list matches a given parameter list. This will return
|
|
/// \c false if the arity doesn't match, or any of the canonical types or
|
|
/// labels don't match. Note that this expects types to be present for the
|
|
/// arguments and parameters.
|
|
bool matches(ArrayRef<AnyFunctionType::Param> params,
|
|
llvm::function_ref<Type(Expr *)> getType = __Expr_getType) const;
|
|
|
|
/// Returns the argument list prior to being rewritten by the expression
|
|
/// type-checker. If the argument list either hasn't been type-checked yet,
|
|
/// or was implicitly generated as type-checked, it returns itself.
|
|
///
|
|
/// Note that returned argument list will still have rewritten argument
|
|
/// expressions with types. However the order of the arguments will reflect
|
|
/// the call-site as written by the user, default arguments will be stripped,
|
|
/// and variadic arguments will be expanded.
|
|
ArgumentList *getOriginalArgs() {
|
|
if (auto *originalArgs = getStoredOriginalArgs())
|
|
return originalArgs;
|
|
return this;
|
|
}
|
|
|
|
/// Returns the argument list prior to being rewritten by the expression
|
|
/// type-checker. If the argument list either hasn't been type-checked yet,
|
|
/// or was implicitly generated as type-checked, it returns itself.
|
|
///
|
|
/// Note that returned argument list will still have rewritten argument
|
|
/// expressions with types. However the order of the arguments will reflect
|
|
/// the call-site as written by the user, default arguments will be stripped,
|
|
/// and variadic arguments will be expanded.
|
|
const ArgumentList *getOriginalArgs() const {
|
|
if (auto *originalArgs = getStoredOriginalArgs())
|
|
return originalArgs;
|
|
return this;
|
|
}
|
|
|
|
ArgumentList *walk(ASTWalker &walker);
|
|
|
|
SWIFT_DEBUG_DUMP;
|
|
void dump(raw_ostream &OS, unsigned Indent = 0) const;
|
|
};
|
|
|
|
} // end namespace swift
|
|
|
|
#endif
|