Skip to content

Commit cd193bf

Browse files
committed
Fold explicit casts
1 parent c357aa4 commit cd193bf

File tree

2 files changed

+58
-9
lines changed

2 files changed

+58
-9
lines changed

Sources/SwiftOperatorPrecedence/OperatorPrecedence+Folding.swift

Lines changed: 52 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,12 @@
1111
//===----------------------------------------------------------------------===//
1212
import SwiftSyntax
1313

14+
extension ExprSyntax {
15+
// Is this an unresolved explicit cast?
16+
fileprivate var isUnresolvedExplicitCast: Bool {
17+
self.is(UnresolvedIsExprSyntax.self) || self.is(UnresolvedAsExprSyntax.self)
18+
}
19+
}
1420
extension OperatorPrecedence {
1521
private struct PrecedenceBound {
1622
let groupName: PrecedenceGroupName?
@@ -69,6 +75,11 @@ extension OperatorPrecedence {
6975
return "AssignmentPrecedence"
7076
}
7177

78+
// Cast operators have fixed precedence.
79+
if expr.isUnresolvedExplicitCast {
80+
return "CastingPrecedence"
81+
}
82+
7283
// FIXME: Handle all of the language-defined precedence relationships.
7384
return nil
7485
}
@@ -116,6 +127,34 @@ extension OperatorPrecedence {
116127
)
117128
}
118129

130+
// An "is" type check.
131+
if let isExpr = op.as(UnresolvedIsExprSyntax.self) {
132+
// FIXME: Do we actually have a guarantee that the right-hand side is a
133+
// type expression here?
134+
return ExprSyntax(
135+
IsExprSyntax(
136+
expression: lhs,
137+
isExpr.unexpectedBeforeIsTok,
138+
isTok: isExpr.isTok,
139+
typeName: rhs.as(TypeExprSyntax.self)!.type)
140+
)
141+
}
142+
143+
// An "as" cast.
144+
if let asExpr = op.as(UnresolvedAsExprSyntax.self) {
145+
// FIXME: Do we actually have a guarantee that the right-hand side is a
146+
// type expression here?
147+
return ExprSyntax(
148+
AsExprSyntax(
149+
expression: lhs,
150+
asExpr.unexpectedBeforeAsTok,
151+
asTok: asExpr.asTok,
152+
asExpr.unexpectedBetweenAsTokAndQuestionOrExclamationMark,
153+
questionOrExclamationMark: asExpr.questionOrExclamationMark,
154+
typeName: rhs.as(TypeExprSyntax.self)!.type)
155+
)
156+
}
157+
119158
// FIXME: Fallback that we should never need
120159
fatalError("Unknown binary operator")
121160
}
@@ -203,18 +242,22 @@ extension OperatorPrecedence {
203242
rest = rest.dropFirst()
204243

205244
while !rest.isEmpty {
206-
#if compiler(>=10.0) && false
207245
// If the operator is a cast operator, the RHS can't extend past the type
208246
// that's part of the cast production.
209-
if (isa<ExplicitCastExpr>(op1.op)) {
210-
LHS = makeBinOp(Ctx, op1.op, LHS, RHS, op1.precedence, S.empty());
211-
op1 = getNextOperator();
212-
if (!op1) return LHS;
213-
RHS = S[1];
214-
S = S.slice(2);
215-
continue;
247+
if op1.isUnresolvedExplicitCast {
248+
lhs = Self.makeBinaryOperationExpr(lhs: lhs, op: op1, rhs: rhs)
249+
guard let (newOp1, newOp1Precedence) = try getNextOperator() else {
250+
return lhs
251+
}
252+
253+
op1 = newOp1
254+
op1Precedence = newOp1Precedence
255+
256+
rest = rest.dropFirst()
257+
rhs = rest.first!
258+
rest = rest.dropFirst()
259+
continue
216260
}
217-
#endif
218261

219262
// Pull out the next binary operator.
220263
let op2 = rest.first!

Tests/SwiftOperatorPrecedenceTest/OperatorPrecedence.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,12 @@ public class OperatorPrecedenceTests: XCTestCase {
124124
try opPrecedence.assertExpectedFold("a = b = c", "(a = (b = c))")
125125
}
126126

127+
func testCastExprs() throws {
128+
let opPrecedence = OperatorPrecedence.standardOperators
129+
try opPrecedence.assertExpectedFold("a is (b)", "(a is (b))")
130+
try opPrecedence.assertExpectedFold("a as c == nil", "((a as c) == nil)")
131+
}
132+
127133
func testParsedLogicalExprs() throws {
128134
let logicalOperatorSources =
129135
"""

0 commit comments

Comments
 (0)