Skip to content

Commit 1586da6

Browse files
committed
Adding libsyntax integration and fixing up an error message.
1 parent 8da86cc commit 1586da6

File tree

6 files changed

+111
-8
lines changed

6 files changed

+111
-8
lines changed

lib/Parse/ParseDecl.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1098,6 +1098,7 @@ static bool parseBaseTypeForQualifiedDeclName(Parser &P, TypeRepr *&baseType) {
10981098
static bool parseQualifiedDeclName(Parser &P, Diag<> nameParseError,
10991099
TypeRepr *&baseType,
11001100
DeclNameRefWithLoc &original) {
1101+
{
11011102
SyntaxParsingContext DeclNameContext(P.SyntaxContext,
11021103
SyntaxKind::QualifiedDeclName);
11031104
// Parse base type.
@@ -1113,7 +1114,8 @@ static bool parseQualifiedDeclName(Parser &P, Diag<> nameParseError,
11131114
// not. If name could not be parsed, return true for error.
11141115
if (!original.Name)
11151116
return true;
1116-
1117+
}
1118+
11171119
// Parse to see if this is an accessor and set it's type. This is an optional field.
11181120
if (P.Tok.is(tok::period)) {
11191121
const Token &nextToken = P.peekToken();

lib/Sema/TypeCheckAttr.cpp

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3661,11 +3661,13 @@ static AbstractFunctionDecl *findAbstractFunctionDecl(
36613661
if (auto *asd = dyn_cast<AbstractStorageDecl>(decl)) {
36623662
// If accessor kind is specified, use corresponding accessor from the
36633663
// candidate. Otherwise, use the getter by default.
3664-
candidate =
3665-
asd->getOpaqueAccessor(accessorKind.getValueOr(AccessorKind::Get));
3666-
// Error if candidate is missing the requested accessor.
3667-
if (!candidate)
3668-
missingAccessor = true;
3664+
if (accessorKind != None) {
3665+
candidate = asd->getAccessor(accessorKind.getValue());
3666+
// Error if candidate is missing the requested accessor.
3667+
if (!candidate)
3668+
missingAccessor = true;
3669+
} else
3670+
candidate = asd->getAccessor(AccessorKind::Get);
36693671
}
36703672
if (!candidate) {
36713673
notFunction = true;

test/AutoDiff/Sema/derivative_attr_type_checking.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -605,7 +605,7 @@ func jvpDuplicate2(_ x: Float) -> (value: Float, differential: (Float) -> Float)
605605
// Test invalid original declaration kind.
606606

607607
var globalVariable: Float
608-
// expected-error @+1 {{'globalVariable' does not have a 'get' accessor}}
608+
// expected-error @+1 {{'globalVariable' is not a 'func', 'init', 'subscript', or 'var' computed property declaration}}
609609
@derivative(of: globalVariable)
610610
func invalidOriginalDeclaration(x: Float) -> (
611611
value: Float, differential: (Float) -> (Float)

test/AutoDiff/Syntax/Outputs/round_trip_parse_gen.swift.withkinds

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,18 @@ func bazDerivative<FunctionSignature><ParameterClause>(<FunctionParameter>_ x: <
3838
return <TupleExpr>(<TupleExprElement><IdentifierExpr>x</IdentifierExpr>, </TupleExprElement><TupleExprElement><ClosureExpr>{ <ClosureSignature><ClosureParam>v </ClosureParam>in </ClosureSignature><IdentifierExpr>v </IdentifierExpr>}</ClosureExpr></TupleExprElement>)</TupleExpr></ReturnStmt>
3939
}</CodeBlock></FunctionDecl><FunctionDecl><Attribute>
4040

41+
@derivative(<DerivativeRegistrationAttributeArguments>of: <QualifiedDeclName>baz<DeclNameArguments>(<DeclNameArgument>label:</DeclNameArgument><DeclNameArgument>_:</DeclNameArgument>)</DeclNameArguments></QualifiedDeclName>.set, <DifferentiabilityParamsClause>wrt: <DifferentiabilityParams>(<DifferentiabilityParam>x</DifferentiabilityParam>)</DifferentiabilityParams></DifferentiabilityParamsClause></DerivativeRegistrationAttributeArguments>)</Attribute>
42+
func bazSetDerivative<FunctionSignature><ParameterClause>(<FunctionParameter>_ x: <SimpleTypeIdentifier>Float</SimpleTypeIdentifier>, </FunctionParameter><FunctionParameter>y: <SimpleTypeIdentifier>Float</SimpleTypeIdentifier></FunctionParameter>)</ParameterClause><ReturnClause>
43+
-> <TupleType>(<TupleTypeElement>value: <SimpleTypeIdentifier>Float</SimpleTypeIdentifier>, </TupleTypeElement><TupleTypeElement>pullback: <FunctionType>(<TupleTypeElement><SimpleTypeIdentifier>Float</SimpleTypeIdentifier></TupleTypeElement>) -> <SimpleTypeIdentifier>Float</SimpleTypeIdentifier></FunctionType></TupleTypeElement>) </TupleType></ReturnClause></FunctionSignature><CodeBlock>{<ReturnStmt>
44+
return <TupleExpr>(<TupleExprElement><IdentifierExpr>x</IdentifierExpr>, </TupleExprElement><TupleExprElement><ClosureExpr>{ <ClosureSignature><ClosureParam>v </ClosureParam>in </ClosureSignature><IdentifierExpr>v </IdentifierExpr>}</ClosureExpr></TupleExprElement>)</TupleExpr></ReturnStmt>
45+
}</CodeBlock></FunctionDecl><FunctionDecl><Attribute>
46+
47+
@derivative(<DerivativeRegistrationAttributeArguments>of: <QualifiedDeclName>baz<DeclNameArguments>(<DeclNameArgument>label:</DeclNameArgument><DeclNameArgument>_:</DeclNameArgument>)</DeclNameArguments></QualifiedDeclName>.get, <DifferentiabilityParamsClause>wrt: <DifferentiabilityParams>(<DifferentiabilityParam>x</DifferentiabilityParam>)</DifferentiabilityParams></DifferentiabilityParamsClause></DerivativeRegistrationAttributeArguments>)</Attribute>
48+
func bazGetDerivative<FunctionSignature><ParameterClause>(<FunctionParameter>_ x: <SimpleTypeIdentifier>Float</SimpleTypeIdentifier>, </FunctionParameter><FunctionParameter>y: <SimpleTypeIdentifier>Float</SimpleTypeIdentifier></FunctionParameter>)</ParameterClause><ReturnClause>
49+
-> <TupleType>(<TupleTypeElement>value: <SimpleTypeIdentifier>Float</SimpleTypeIdentifier>, </TupleTypeElement><TupleTypeElement>pullback: <FunctionType>(<TupleTypeElement><SimpleTypeIdentifier>Float</SimpleTypeIdentifier></TupleTypeElement>) -> <SimpleTypeIdentifier>Float</SimpleTypeIdentifier></FunctionType></TupleTypeElement>) </TupleType></ReturnClause></FunctionSignature><CodeBlock>{<ReturnStmt>
50+
return <TupleExpr>(<TupleExprElement><IdentifierExpr>x</IdentifierExpr>, </TupleExprElement><TupleExprElement><ClosureExpr>{ <ClosureSignature><ClosureParam>v </ClosureParam>in </ClosureSignature><IdentifierExpr>v </IdentifierExpr>}</ClosureExpr></TupleExprElement>)</TupleExpr></ReturnStmt>
51+
}</CodeBlock></FunctionDecl><FunctionDecl><Attribute>
52+
4153
@transpose(<DerivativeRegistrationAttributeArguments>of: <QualifiedDeclName>-</QualifiedDeclName></DerivativeRegistrationAttributeArguments>)</Attribute>
4254
func negateDerivative<FunctionSignature><ParameterClause>(<FunctionParameter>_ x: <SimpleTypeIdentifier>Float</SimpleTypeIdentifier></FunctionParameter>)</ParameterClause><ReturnClause>
4355
-> <TupleType>(<TupleTypeElement>value: <SimpleTypeIdentifier>Float</SimpleTypeIdentifier>, </TupleTypeElement><TupleTypeElement>pullback: <FunctionType>(<TupleTypeElement><SimpleTypeIdentifier>Float</SimpleTypeIdentifier></TupleTypeElement>) -> <SimpleTypeIdentifier>Float</SimpleTypeIdentifier></FunctionType></TupleTypeElement>) </TupleType></ReturnClause></FunctionSignature><CodeBlock>{<ReturnStmt>
@@ -56,6 +68,18 @@ func qualifiedDerivative<FunctionSignature><ParameterClause>(<FunctionParameter>
5668
return <TupleExpr>(<TupleExprElement><IdentifierExpr>x</IdentifierExpr>, </TupleExprElement><TupleExprElement><ClosureExpr>{ <ClosureSignature><ClosureParam>v </ClosureParam>in </ClosureSignature><IdentifierExpr>v </IdentifierExpr>}</ClosureExpr></TupleExprElement>)</TupleExpr></ReturnStmt>
5769
}</CodeBlock></FunctionDecl><FunctionDecl><Attribute>
5870

71+
@derivative(<DerivativeRegistrationAttributeArguments>of: <QualifiedDeclName><MemberTypeIdentifier><MemberTypeIdentifier><SimpleTypeIdentifier>A<GenericArgumentClause><<GenericArgument><SimpleTypeIdentifier>T</SimpleTypeIdentifier></GenericArgument>></GenericArgumentClause></SimpleTypeIdentifier>.B<GenericArgumentClause><<GenericArgument><SimpleTypeIdentifier>U</SimpleTypeIdentifier>, </GenericArgument><GenericArgument><SimpleTypeIdentifier>V</SimpleTypeIdentifier></GenericArgument>></GenericArgumentClause></MemberTypeIdentifier>.C</MemberTypeIdentifier>.foo<DeclNameArguments>(<DeclNameArgument>label:</DeclNameArgument><DeclNameArgument>_:</DeclNameArgument>)</DeclNameArguments></QualifiedDeclName>.get, <DifferentiabilityParamsClause>wrt: <DifferentiabilityParam>x</DifferentiabilityParam></DifferentiabilityParamsClause></DerivativeRegistrationAttributeArguments>)</Attribute>
72+
func qualifiedGetDerivative<FunctionSignature><ParameterClause>(<FunctionParameter>_ x: <SimpleTypeIdentifier>Float</SimpleTypeIdentifier>, </FunctionParameter><FunctionParameter>y: <SimpleTypeIdentifier>Float</SimpleTypeIdentifier></FunctionParameter>)</ParameterClause><ReturnClause>
73+
-> <TupleType>(<TupleTypeElement>value: <SimpleTypeIdentifier>Float</SimpleTypeIdentifier>, </TupleTypeElement><TupleTypeElement>pullback: <FunctionType>(<TupleTypeElement><SimpleTypeIdentifier>Float</SimpleTypeIdentifier></TupleTypeElement>) -> <SimpleTypeIdentifier>Float</SimpleTypeIdentifier></FunctionType></TupleTypeElement>) </TupleType></ReturnClause></FunctionSignature><CodeBlock>{<ReturnStmt>
74+
return <TupleExpr>(<TupleExprElement><IdentifierExpr>x</IdentifierExpr>, </TupleExprElement><TupleExprElement><ClosureExpr>{ <ClosureSignature><ClosureParam>v </ClosureParam>in </ClosureSignature><IdentifierExpr>v </IdentifierExpr>}</ClosureExpr></TupleExprElement>)</TupleExpr></ReturnStmt>
75+
}</CodeBlock></FunctionDecl><FunctionDecl><Attribute>
76+
77+
@derivative(<DerivativeRegistrationAttributeArguments>of: <QualifiedDeclName><MemberTypeIdentifier><MemberTypeIdentifier><SimpleTypeIdentifier>A<GenericArgumentClause><<GenericArgument><SimpleTypeIdentifier>T</SimpleTypeIdentifier></GenericArgument>></GenericArgumentClause></SimpleTypeIdentifier>.B<GenericArgumentClause><<GenericArgument><SimpleTypeIdentifier>U</SimpleTypeIdentifier>, </GenericArgument><GenericArgument><SimpleTypeIdentifier>V</SimpleTypeIdentifier></GenericArgument>></GenericArgumentClause></MemberTypeIdentifier>.C</MemberTypeIdentifier>.foo<DeclNameArguments>(<DeclNameArgument>label:</DeclNameArgument><DeclNameArgument>_:</DeclNameArgument>)</DeclNameArguments></QualifiedDeclName>.set, <DifferentiabilityParamsClause>wrt: <DifferentiabilityParam>x</DifferentiabilityParam></DifferentiabilityParamsClause></DerivativeRegistrationAttributeArguments>)</Attribute>
78+
func qualifiedSetDerivative<FunctionSignature><ParameterClause>(<FunctionParameter>_ x: <SimpleTypeIdentifier>Float</SimpleTypeIdentifier>, </FunctionParameter><FunctionParameter>y: <SimpleTypeIdentifier>Float</SimpleTypeIdentifier></FunctionParameter>)</ParameterClause><ReturnClause>
79+
-> <TupleType>(<TupleTypeElement>value: <SimpleTypeIdentifier>Float</SimpleTypeIdentifier>, </TupleTypeElement><TupleTypeElement>pullback: <FunctionType>(<TupleTypeElement><SimpleTypeIdentifier>Float</SimpleTypeIdentifier></TupleTypeElement>) -> <SimpleTypeIdentifier>Float</SimpleTypeIdentifier></FunctionType></TupleTypeElement>) </TupleType></ReturnClause></FunctionSignature><CodeBlock>{<ReturnStmt>
80+
return <TupleExpr>(<TupleExprElement><IdentifierExpr>x</IdentifierExpr>, </TupleExprElement><TupleExprElement><ClosureExpr>{ <ClosureSignature><ClosureParam>v </ClosureParam>in </ClosureSignature><IdentifierExpr>v </IdentifierExpr>}</ClosureExpr></TupleExprElement>)</TupleExpr></ReturnStmt>
81+
}</CodeBlock></FunctionDecl><FunctionDecl><Attribute>
82+
5983
@transpose(<DerivativeRegistrationAttributeArguments>of: <QualifiedDeclName>+</QualifiedDeclName></DerivativeRegistrationAttributeArguments>)</Attribute>
6084
func addTranspose<FunctionSignature><ParameterClause>(<FunctionParameter>_ v: <SimpleTypeIdentifier>Float</SimpleTypeIdentifier></FunctionParameter>) </ParameterClause><ReturnClause>-> <TupleType>(<TupleTypeElement><SimpleTypeIdentifier>Float</SimpleTypeIdentifier>, </TupleTypeElement><TupleTypeElement><SimpleTypeIdentifier>Float</SimpleTypeIdentifier></TupleTypeElement>) </TupleType></ReturnClause></FunctionSignature><CodeBlock>{<ReturnStmt>
6185
return <TupleExpr>(<TupleExprElement><IdentifierExpr>v</IdentifierExpr>, </TupleExprElement><TupleExprElement><IdentifierExpr>v</IdentifierExpr></TupleExprElement>)</TupleExpr></ReturnStmt>
@@ -71,7 +95,28 @@ func subtractTranspose<FunctionSignature><ParameterClause>(<FunctionParameter>_
7195
return <TupleExpr>(<TupleExprElement><IdentifierExpr>v</IdentifierExpr>, </TupleExprElement><TupleExprElement><PrefixOperatorExpr>-<IdentifierExpr>v</IdentifierExpr></PrefixOperatorExpr></TupleExprElement>)</TupleExpr></ReturnStmt>
7296
}</CodeBlock></FunctionDecl><FunctionDecl><Attribute>
7397

98+
@transpose(<DerivativeRegistrationAttributeArguments>of: <QualifiedDeclName><SimpleTypeIdentifier>Float</SimpleTypeIdentifier>.-</QualifiedDeclName>.get, <DifferentiabilityParamsClause>wrt: <DifferentiabilityParams>(<DifferentiabilityParam>0, </DifferentiabilityParam><DifferentiabilityParam>1</DifferentiabilityParam>)</DifferentiabilityParams></DifferentiabilityParamsClause></DerivativeRegistrationAttributeArguments>)</Attribute>
99+
func subtractGetTranspose<FunctionSignature><ParameterClause>(<FunctionParameter>_ v: <SimpleTypeIdentifier>Float</SimpleTypeIdentifier></FunctionParameter>) </ParameterClause><ReturnClause>-> <TupleType>(<TupleTypeElement><SimpleTypeIdentifier>Float</SimpleTypeIdentifier>, </TupleTypeElement><TupleTypeElement><SimpleTypeIdentifier>Float</SimpleTypeIdentifier></TupleTypeElement>) </TupleType></ReturnClause></FunctionSignature><CodeBlock>{<ReturnStmt>
100+
return <TupleExpr>(<TupleExprElement><IdentifierExpr>v</IdentifierExpr>, </TupleExprElement><TupleExprElement><PrefixOperatorExpr>-<IdentifierExpr>v</IdentifierExpr></PrefixOperatorExpr></TupleExprElement>)</TupleExpr></ReturnStmt>
101+
}</CodeBlock></FunctionDecl><FunctionDecl><Attribute>
102+
103+
@transpose(<DerivativeRegistrationAttributeArguments>of: <QualifiedDeclName><SimpleTypeIdentifier>Float</SimpleTypeIdentifier>.-</QualifiedDeclName>.set, <DifferentiabilityParamsClause>wrt: <DifferentiabilityParams>(<DifferentiabilityParam>0, </DifferentiabilityParam><DifferentiabilityParam>1</DifferentiabilityParam>)</DifferentiabilityParams></DifferentiabilityParamsClause></DerivativeRegistrationAttributeArguments>)</Attribute>
104+
func subtractSetTranspose<FunctionSignature><ParameterClause>(<FunctionParameter>_ v: <SimpleTypeIdentifier>Float</SimpleTypeIdentifier></FunctionParameter>) </ParameterClause><ReturnClause>-> <TupleType>(<TupleTypeElement><SimpleTypeIdentifier>Float</SimpleTypeIdentifier>, </TupleTypeElement><TupleTypeElement><SimpleTypeIdentifier>Float</SimpleTypeIdentifier></TupleTypeElement>) </TupleType></ReturnClause></FunctionSignature><CodeBlock>{<ReturnStmt>
105+
return <TupleExpr>(<TupleExprElement><IdentifierExpr>v</IdentifierExpr>, </TupleExprElement><TupleExprElement><PrefixOperatorExpr>-<IdentifierExpr>v</IdentifierExpr></PrefixOperatorExpr></TupleExprElement>)</TupleExpr></ReturnStmt>
106+
}</CodeBlock></FunctionDecl><FunctionDecl><Attribute>
107+
74108
@derivative(<DerivativeRegistrationAttributeArguments>of: <QualifiedDeclName><MemberTypeIdentifier><MemberTypeIdentifier><SimpleTypeIdentifier>A<GenericArgumentClause><<GenericArgument><SimpleTypeIdentifier>T</SimpleTypeIdentifier></GenericArgument>></GenericArgumentClause></SimpleTypeIdentifier>.B<GenericArgumentClause><<GenericArgument><SimpleTypeIdentifier>U</SimpleTypeIdentifier>, </GenericArgument><GenericArgument><SimpleTypeIdentifier>V</SimpleTypeIdentifier></GenericArgument>></GenericArgumentClause></MemberTypeIdentifier>.C</MemberTypeIdentifier>.foo<DeclNameArguments>(<DeclNameArgument>label:</DeclNameArgument><DeclNameArgument>_:</DeclNameArgument>)</DeclNameArguments></QualifiedDeclName>, <DifferentiabilityParamsClause>wrt: <DifferentiabilityParam>0</DifferentiabilityParam></DifferentiabilityParamsClause></DerivativeRegistrationAttributeArguments>)</Attribute>
75109
func qualifiedTranspose<FunctionSignature><ParameterClause>(<FunctionParameter>_ v: <SimpleTypeIdentifier>Float</SimpleTypeIdentifier></FunctionParameter>) </ParameterClause><ReturnClause>-> <TupleType>(<TupleTypeElement><SimpleTypeIdentifier>Float</SimpleTypeIdentifier>, </TupleTypeElement><TupleTypeElement><SimpleTypeIdentifier>Float</SimpleTypeIdentifier></TupleTypeElement>) </TupleType></ReturnClause></FunctionSignature><CodeBlock>{<ReturnStmt>
76110
return <TupleExpr>(<TupleExprElement><IdentifierExpr>v</IdentifierExpr>, </TupleExprElement><TupleExprElement><PrefixOperatorExpr>-<IdentifierExpr>v</IdentifierExpr></PrefixOperatorExpr></TupleExprElement>)</TupleExpr></ReturnStmt>
77-
}</CodeBlock></FunctionDecl>
111+
}</CodeBlock></FunctionDecl><FunctionDecl><Attribute>
112+
113+
@transpose(<DerivativeRegistrationAttributeArguments>of: <QualifiedDeclName><MemberTypeIdentifier><MemberTypeIdentifier><SimpleTypeIdentifier>A<GenericArgumentClause><<GenericArgument><SimpleTypeIdentifier>T</SimpleTypeIdentifier></GenericArgument>></GenericArgumentClause></SimpleTypeIdentifier>.B<GenericArgumentClause><<GenericArgument><SimpleTypeIdentifier>U</SimpleTypeIdentifier>, </GenericArgument><GenericArgument><SimpleTypeIdentifier>V</SimpleTypeIdentifier></GenericArgument>></GenericArgumentClause></MemberTypeIdentifier>.C</MemberTypeIdentifier>.foo<DeclNameArguments>(<DeclNameArgument>label:</DeclNameArgument><DeclNameArgument>_:</DeclNameArgument>)</DeclNameArguments></QualifiedDeclName>.get, <DifferentiabilityParamsClause>wrt: <DifferentiabilityParam>0</DifferentiabilityParam></DifferentiabilityParamsClause></DerivativeRegistrationAttributeArguments>)</Attribute>
114+
func qualifiedGetTranspose<FunctionSignature><ParameterClause>(<FunctionParameter>_ v: <SimpleTypeIdentifier>Float</SimpleTypeIdentifier></FunctionParameter>) </ParameterClause><ReturnClause>-> <TupleType>(<TupleTypeElement><SimpleTypeIdentifier>Float</SimpleTypeIdentifier>, </TupleTypeElement><TupleTypeElement><SimpleTypeIdentifier>Float</SimpleTypeIdentifier></TupleTypeElement>) </TupleType></ReturnClause></FunctionSignature><CodeBlock>{<ReturnStmt>
115+
return <TupleExpr>(<TupleExprElement><IdentifierExpr>v</IdentifierExpr>, </TupleExprElement><TupleExprElement><PrefixOperatorExpr>-<IdentifierExpr>v</IdentifierExpr></PrefixOperatorExpr></TupleExprElement>)</TupleExpr></ReturnStmt>
116+
}</CodeBlock></FunctionDecl><FunctionDecl><Attribute>
117+
118+
@derivative(<DerivativeRegistrationAttributeArguments>of: <QualifiedDeclName>subscript<DeclNameArguments>(<DeclNameArgument>_:</DeclNameArgument>)</DeclNameArguments></QualifiedDeclName>.set, <DifferentiabilityParamsClause>wrt: <DifferentiabilityParams>(<DifferentiabilityParam>self, </DifferentiabilityParam><DifferentiabilityParam>newValue</DifferentiabilityParam>)</DifferentiabilityParams></DifferentiabilityParamsClause></DerivativeRegistrationAttributeArguments>)</Attribute>
119+
func subscriptSetterDerivative<FunctionSignature><ParameterClause>() </ParameterClause></FunctionSignature><CodeBlock>{}</CodeBlock></FunctionDecl><FunctionDecl><Attribute>
120+
121+
@transpose(<DerivativeRegistrationAttributeArguments>of: <QualifiedDeclName>subscript<DeclNameArguments>(<DeclNameArgument>_:</DeclNameArgument>)</DeclNameArguments></QualifiedDeclName>.set, <DifferentiabilityParamsClause>wrt: <DifferentiabilityParams>(<DifferentiabilityParam>self, </DifferentiabilityParam><DifferentiabilityParam>0</DifferentiabilityParam>)</DifferentiabilityParams></DifferentiabilityParamsClause></DerivativeRegistrationAttributeArguments></Attribute>
122+
func subscriptSetterTranspose<FunctionSignature><ParameterClause>() </ParameterClause></FunctionSignature><CodeBlock>{}</CodeBlock></FunctionDecl>

0 commit comments

Comments
 (0)