mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
Move the SequenceExpr transformation from the expression pre-check into the main expression type-checking visitor.
Swift SVN r2002
This commit is contained in:
@@ -1457,7 +1457,11 @@ public:
|
|||||||
void setFn(Expr *e) { Fn = e; }
|
void setFn(Expr *e) { Fn = e; }
|
||||||
|
|
||||||
Expr *getArg() const { return Arg; }
|
Expr *getArg() const { return Arg; }
|
||||||
void setArg(Expr *e) { Arg = e; }
|
void setArg(Expr *e) {
|
||||||
|
assert((getKind() != ExprKind::Binary || isa<TupleExpr>(e)) &&
|
||||||
|
"BinaryExprs must have a TupleExpr as the argument");
|
||||||
|
Arg = e;
|
||||||
|
}
|
||||||
|
|
||||||
ValueDecl *getCalledValue() const;
|
ValueDecl *getCalledValue() const;
|
||||||
|
|
||||||
@@ -1518,6 +1522,8 @@ public:
|
|||||||
return getArg()->getSourceRange();
|
return getArg()->getSourceRange();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TupleExpr *getArg() const { return cast<TupleExpr>(ApplyExpr::getArg()); }
|
||||||
|
|
||||||
// Implement isa/cast/dyncast/etc.
|
// Implement isa/cast/dyncast/etc.
|
||||||
static bool classof(const BinaryExpr *) { return true; }
|
static bool classof(const BinaryExpr *) { return true; }
|
||||||
static bool classof(const Expr *E) { return E->getKind() == ExprKind::Binary;}
|
static bool classof(const Expr *E) { return E->getKind() == ExprKind::Binary;}
|
||||||
|
|||||||
@@ -642,6 +642,8 @@ public:
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Expr *makeBinOp(Expr *Op, Expr *LHS, Expr *RHS);
|
||||||
|
Expr *foldSequence(Expr *LHS, ArrayRef<Expr*> &S, unsigned MinPrecedence);
|
||||||
Expr *visitSequenceExpr(SequenceExpr *E);
|
Expr *visitSequenceExpr(SequenceExpr *E);
|
||||||
|
|
||||||
void PreProcessBraceStmt(BraceStmt *BS);
|
void PreProcessBraceStmt(BraceStmt *BS);
|
||||||
@@ -842,18 +844,26 @@ static InfixData getInfixData(TypeChecker &TC, Expr *E) {
|
|||||||
return InfixData(~0U, Associativity::Left);
|
return InfixData(~0U, Associativity::Left);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Expr *makeBinOp(TypeChecker &TC, Expr *Op, Expr *LHS, Expr *RHS) {
|
Expr *SemaExpressionTree::makeBinOp(Expr *Op, Expr *LHS, Expr *RHS) {
|
||||||
|
if (!LHS || !RHS)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
// Build the argument to the operation.
|
||||||
Expr *ArgElts[] = { LHS, RHS };
|
Expr *ArgElts[] = { LHS, RHS };
|
||||||
auto ArgElts2 = TC.Context.AllocateCopy(MutableArrayRef<Expr*>(ArgElts));
|
auto ArgElts2 = TC.Context.AllocateCopy(MutableArrayRef<Expr*>(ArgElts));
|
||||||
TupleExpr *Arg = new (TC.Context) TupleExpr(SourceLoc(),
|
TupleExpr *Arg = new (TC.Context) TupleExpr(SourceLoc(),
|
||||||
ArgElts2, 0, SourceLoc());
|
ArgElts2, 0, SourceLoc());
|
||||||
return new (TC.Context) BinaryExpr(Op, Arg);
|
if (TC.semaTupleExpr(Arg))
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
// Build the operation.
|
||||||
|
return visit(new (TC.Context) BinaryExpr(Op, Arg));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// foldSequence - Take a sequence of expressions and fold a prefix of
|
/// foldSequence - Take a sequence of expressions and fold a prefix of
|
||||||
/// it into a tree of BinaryExprs using precedence parsing.
|
/// it into a tree of BinaryExprs using precedence parsing.
|
||||||
static Expr *foldSequence(TypeChecker &TC, Expr *LHS, ArrayRef<Expr*> &S,
|
Expr *SemaExpressionTree::foldSequence(Expr *LHS, ArrayRef<Expr*> &S,
|
||||||
unsigned MinPrecedence) {
|
unsigned MinPrecedence) {
|
||||||
// Invariant: S is even-sized.
|
// Invariant: S is even-sized.
|
||||||
// Invariant: All elements at even indices are operator references.
|
// Invariant: All elements at even indices are operator references.
|
||||||
assert(!S.empty());
|
assert(!S.empty());
|
||||||
@@ -888,7 +898,7 @@ static Expr *foldSequence(TypeChecker &TC, Expr *LHS, ArrayRef<Expr*> &S,
|
|||||||
// both left-associative, fold LHS and RHS immediately.
|
// both left-associative, fold LHS and RHS immediately.
|
||||||
if (Op1Info.getPrecedence() > Op2Info.getPrecedence() ||
|
if (Op1Info.getPrecedence() > Op2Info.getPrecedence() ||
|
||||||
(Op1Info == Op2Info && Op1Info.isLeftAssociative())) {
|
(Op1Info == Op2Info && Op1Info.isLeftAssociative())) {
|
||||||
LHS = makeBinOp(TC, Op1, LHS, RHS);
|
LHS = makeBinOp(Op1, LHS, RHS);
|
||||||
RHS = S[1];
|
RHS = S[1];
|
||||||
Op1 = Op2;
|
Op1 = Op2;
|
||||||
Op1Info = Op2Info;
|
Op1Info = Op2Info;
|
||||||
@@ -901,7 +911,7 @@ static Expr *foldSequence(TypeChecker &TC, Expr *LHS, ArrayRef<Expr*> &S,
|
|||||||
// higher-precedence operators starting from this point, then
|
// higher-precedence operators starting from this point, then
|
||||||
// repeat.
|
// repeat.
|
||||||
if (Op1Info.getPrecedence() < Op2Info.getPrecedence()) {
|
if (Op1Info.getPrecedence() < Op2Info.getPrecedence()) {
|
||||||
RHS = foldSequence(TC, RHS, S, Op1Info.getPrecedence() + 1);
|
RHS = foldSequence(RHS, S, Op1Info.getPrecedence() + 1);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -910,14 +920,14 @@ static Expr *foldSequence(TypeChecker &TC, Expr *LHS, ArrayRef<Expr*> &S,
|
|||||||
// recursively fold operators starting from this point, then
|
// recursively fold operators starting from this point, then
|
||||||
// immediately fold LHS and RHS.
|
// immediately fold LHS and RHS.
|
||||||
if (Op1Info == Op2Info && Op1Info.isRightAssociative()) {
|
if (Op1Info == Op2Info && Op1Info.isRightAssociative()) {
|
||||||
RHS = foldSequence(TC, RHS, S, Op1Info.getPrecedence());
|
RHS = foldSequence(RHS, S, Op1Info.getPrecedence());
|
||||||
LHS = makeBinOp(TC, Op1, LHS, RHS);
|
LHS = makeBinOp(Op1, LHS, RHS);
|
||||||
|
|
||||||
// If we've drained the entire sequence, we're done.
|
// If we've drained the entire sequence, we're done.
|
||||||
if (S.empty()) return LHS;
|
if (S.empty()) return LHS;
|
||||||
|
|
||||||
// Otherwise, start all over with our new LHS.
|
// Otherwise, start all over with our new LHS.
|
||||||
return foldSequence(TC, LHS, S, MinPrecedence);
|
return foldSequence(LHS, S, MinPrecedence);
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we ended up here, it's because we have two operators
|
// If we ended up here, it's because we have two operators
|
||||||
@@ -936,17 +946,17 @@ static Expr *foldSequence(TypeChecker &TC, Expr *LHS, ArrayRef<Expr*> &S,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Recover by arbitrarily binding the first two.
|
// Recover by arbitrarily binding the first two.
|
||||||
LHS = makeBinOp(TC, Op1, LHS, RHS);
|
LHS = makeBinOp(Op1, LHS, RHS);
|
||||||
return foldSequence(TC, LHS, S, MinPrecedence);
|
return foldSequence(LHS, S, MinPrecedence);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fold LHS and RHS together and declare completion.
|
// Fold LHS and RHS together and declare completion.
|
||||||
return makeBinOp(TC, Op1, LHS, RHS);
|
return makeBinOp(Op1, LHS, RHS);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// foldSequence - Take a SequenceExpr and fold it into a tree of
|
/// foldSequence - Take a SequenceExpr and fold it into a tree of
|
||||||
/// BinaryExprs using precedence parsing.
|
/// BinaryExprs using precedence parsing.
|
||||||
Expr *TypeChecker::foldSequence(SequenceExpr *E) {
|
Expr *SemaExpressionTree::visitSequenceExpr(SequenceExpr *E) {
|
||||||
ArrayRef<Expr*> Elts = E->getElements();
|
ArrayRef<Expr*> Elts = E->getElements();
|
||||||
assert(Elts.size() > 1 && "inadequate number of elements in sequence");
|
assert(Elts.size() > 1 && "inadequate number of elements in sequence");
|
||||||
assert((Elts.size() & 1) == 1 && "even number of elements in sequence");
|
assert((Elts.size() & 1) == 1 && "even number of elements in sequence");
|
||||||
@@ -954,15 +964,11 @@ Expr *TypeChecker::foldSequence(SequenceExpr *E) {
|
|||||||
Expr *LHS = Elts[0];
|
Expr *LHS = Elts[0];
|
||||||
Elts = Elts.slice(1);
|
Elts = Elts.slice(1);
|
||||||
|
|
||||||
Expr *Result = ::foldSequence(*this, LHS, Elts, /*min precedence*/ 0);
|
Expr *Result = foldSequence(LHS, Elts, /*min precedence*/ 0);
|
||||||
assert(Elts.empty());
|
assert(Elts.empty());
|
||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
Expr *SemaExpressionTree::visitSequenceExpr(SequenceExpr *E) {
|
|
||||||
llvm_unreachable("visiting sequence expression during normal type-checking!");
|
|
||||||
}
|
|
||||||
|
|
||||||
Expr *TypeChecker::recheckTypes(Expr *E) {
|
Expr *TypeChecker::recheckTypes(Expr *E) {
|
||||||
if (!E)
|
if (!E)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|||||||
@@ -856,8 +856,6 @@ void swift::performTypeChecking(TranslationUnit *TU, unsigned StartElem) {
|
|||||||
return BindName(UDRE, CurFuncDecls.empty() ? 0 : CurFuncDecls.back(),
|
return BindName(UDRE, CurFuncDecls.empty() ? 0 : CurFuncDecls.back(),
|
||||||
TC);
|
TC);
|
||||||
}
|
}
|
||||||
if (SequenceExpr *SE = dyn_cast<SequenceExpr>(E))
|
|
||||||
return TC.foldSequence(SE);
|
|
||||||
return E;
|
return E;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -123,8 +123,6 @@ public:
|
|||||||
Expr *convertLValueToRValue(LValueType *SrcLT, Expr *E);
|
Expr *convertLValueToRValue(LValueType *SrcLT, Expr *E);
|
||||||
Expr *convertToMaterializable(Expr *E);
|
Expr *convertToMaterializable(Expr *E);
|
||||||
|
|
||||||
Expr *foldSequence(SequenceExpr *E);
|
|
||||||
|
|
||||||
/// conformsToProtocol - Determine whether the given type conforms to the
|
/// conformsToProtocol - Determine whether the given type conforms to the
|
||||||
/// given protocol.
|
/// given protocol.
|
||||||
///
|
///
|
||||||
|
|||||||
Reference in New Issue
Block a user