forked from swiftlang/swift
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathParameter.cpp
188 lines (156 loc) · 6.84 KB
/
Parameter.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
//===--- Parameter.cpp - Functions & closures parameters ------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2017 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 Parameter class, the ParameterList class and support
// logic.
//
//===----------------------------------------------------------------------===//
#include "swift/AST/ParameterList.h"
#include "swift/AST/ASTContext.h"
#include "swift/AST/Expr.h"
#include "swift/AST/Types.h"
using namespace swift;
/// TODO: unique and reuse the () parameter list in ASTContext, it is common to
/// many methods. Other parameter lists cannot be uniqued because the decls
/// within them are always different anyway (they have different DeclContext's).
ParameterList *
ParameterList::create(const ASTContext &C, SourceLoc LParenLoc,
ArrayRef<ParamDecl*> params, SourceLoc RParenLoc) {
assert(LParenLoc.isValid() == RParenLoc.isValid() &&
"Either both paren locs are valid or neither are");
auto byteSize = totalSizeToAlloc<ParamDecl *>(params.size());
auto rawMem = C.Allocate(byteSize, alignof(ParameterList));
// Placement initialize the ParameterList and the Parameter's.
auto PL = ::new (rawMem) ParameterList(LParenLoc, params.size(), RParenLoc);
std::uninitialized_copy(params.begin(), params.end(), PL->getArray().begin());
return PL;
}
/// Create an implicit 'self' decl for a method in the specified decl context.
/// If 'static' is true, then this is self for a static method in the type.
///
/// Note that this decl is created, but it is returned with an incorrect
/// DeclContext that needs to be set correctly. This is automatically handled
/// when a function is created with this as part of its argument list.
/// For a generic context, this also gives the parameter an unbound generic
/// type with the expectation that type-checking will fill in the context
/// generic parameters.
ParameterList *ParameterList::createUnboundSelf(SourceLoc loc,
DeclContext *DC) {
auto *PD = ParamDecl::createUnboundSelf(loc, DC);
return create(DC->getASTContext(), PD);
}
/// Create an implicit 'self' decl for a method in the specified decl context.
/// If 'static' is true, then this is self for a static method in the type.
///
/// Note that this decl is created, but it is returned with an incorrect
/// DeclContext that needs to be set correctly. This is automatically handled
/// when a function is created with this as part of its argument list.
ParameterList *ParameterList::createSelf(SourceLoc loc,
DeclContext *DC,
bool isStaticMethod,
bool isInOut) {
auto *PD = ParamDecl::createSelf(loc, DC, isStaticMethod, isInOut);
return create(DC->getASTContext(), PD);
}
/// Change the DeclContext of any contained parameters to the specified
/// DeclContext.
void ParameterList::setDeclContextOfParamDecls(DeclContext *DC) {
for (auto P : *this)
P->setDeclContext(DC);
}
/// Make a duplicate copy of this parameter list. This allocates copies of
/// the ParamDecls, so they can be reparented into a new DeclContext.
ParameterList *ParameterList::clone(const ASTContext &C,
OptionSet<CloneFlags> options) const {
// If this list is empty, don't actually bother with a copy.
if (size() == 0)
return const_cast<ParameterList*>(this);
SmallVector<ParamDecl*, 8> params(begin(), end());
// Remap the ParamDecls inside of the ParameterList.
for (auto &decl : params) {
bool hadDefaultArgument =
decl->getDefaultArgumentKind() == DefaultArgumentKind::Normal;
decl = new (C) ParamDecl(decl);
if (options & Implicit)
decl->setImplicit();
// If the argument isn't named, and we're cloning for an inherited
// constructor, give the parameter a name so that silgen will produce a
// value for it.
if (decl->getName().empty() && (options & Inherited))
decl->setName(C.getIdentifier("argument"));
// If we're inheriting a default argument, mark it as such.
// FIXME: Figure out how to clone default arguments as well.
if (hadDefaultArgument) {
if (options & Inherited)
decl->setDefaultArgumentKind(DefaultArgumentKind::Inherited);
else
decl->setDefaultArgumentKind(DefaultArgumentKind::None);
}
}
return create(C, params);
}
/// Return a TupleType or ParenType for this parameter list, written in terms
/// of contextual archetypes.
Type ParameterList::getType(const ASTContext &C) const {
if (size() == 0)
return TupleType::getEmpty(C);
SmallVector<TupleTypeElt, 8> argumentInfo;
for (auto P : *this) {
argumentInfo.emplace_back(
P->getType(), P->getArgumentName(),
ParameterTypeFlags::fromParameterType(P->getType(), P->isVariadic()));
}
return TupleType::get(argumentInfo, C);
}
/// Return a TupleType or ParenType for this parameter list, written in terms
/// of interface types.
Type ParameterList::getInterfaceType(const ASTContext &C) const {
if (size() == 0)
return TupleType::getEmpty(C);
SmallVector<TupleTypeElt, 8> argumentInfo;
for (auto P : *this) {
auto type = P->getInterfaceType();
assert(!type->hasArchetype());
argumentInfo.emplace_back(
type, P->getArgumentName(),
ParameterTypeFlags::fromParameterType(type, P->isVariadic()));
}
return TupleType::get(argumentInfo, C);
}
/// Return the full function type for a set of curried parameter lists that
/// returns the specified result type. This returns a null type if one of the
/// ParamDecls does not have a type set for it yet.
///
Type ParameterList::getFullInterfaceType(Type resultType,
ArrayRef<ParameterList*> PLL,
const ASTContext &C) {
auto result = resultType;
for (auto PL : reversed(PLL)) {
auto paramType = PL->getInterfaceType(C);
result = FunctionType::get(paramType, result);
}
return result;
}
/// Return the full source range of this parameter list.
SourceRange ParameterList::getSourceRange() const {
// If we have locations for the parens, then they define our range.
if (LParenLoc.isValid())
return { LParenLoc, RParenLoc };
// Otherwise, try the first and last parameter.
if (size() != 0) {
auto Start = get(0)->getStartLoc();
auto End = getArray().back()->getEndLoc();
if (Start.isValid() && End.isValid())
return { Start, End };
}
return SourceRange();
}