Move the SequenceExpr transformation from the expression pre-check into the main expression type-checking visitor.

Swift SVN r2002
This commit is contained in:
Eli Friedman
2012-05-25 22:27:50 +00:00
parent 2289b10a28
commit 95838dca5d
4 changed files with 33 additions and 25 deletions

View File

@@ -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;}

View File

@@ -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,17 +844,25 @@ 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.
@@ -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;

View File

@@ -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;
} }
}; };

View File

@@ -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.
/// ///