Introduce a LangOptions class to capture various type-checker-tweaking flags. For now, introduce bits to enable the constraint solver and to enable debugging of the constraint solver, and use those to eliminate the "useConstraintSolver" bit that was threaded through too much of the type checker.

Swift SVN r2836
This commit is contained in:
Doug Gregor
2012-09-12 20:19:33 +00:00
parent 693318642d
commit 42b1ab6fbd
12 changed files with 96 additions and 40 deletions

View File

@@ -19,6 +19,7 @@
#include "llvm/Support/DataTypes.h"
#include "swift/AST/Type.h"
#include "swift/Basic/LangOptions.h"
#include "swift/Basic/Optional.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/StringMap.h"
@@ -82,9 +83,13 @@ public:
Implementation &Impl;
public:
ASTContext(llvm::SourceMgr &SourceMgr, DiagnosticEngine &Diags);
ASTContext(LangOptions &langOpts, llvm::SourceMgr &SourceMgr,
DiagnosticEngine &Diags);
~ASTContext();
/// \brief The language options used for translation.
LangOptions &LangOpts;
/// SourceMgr - The source manager object.
llvm::SourceMgr &SourceMgr;

View File

@@ -0,0 +1,47 @@
//===--- LangOptions.h - Language & configuration options -------*- C++ -*-===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
// This file defines the LangOptions class, which provides various
// language and configuration flags.
//
//===----------------------------------------------------------------------===//
//
// LangOptions.h
// Swift
//
// Created by Doug Gregor on 9/12/12.
//
//
#ifndef SWIFT_LANGOPTIONS_H
#define SWIFT_LANGOPTIONS_H
namespace swift {
/// \brief A collection of options that affect the language dialect and
/// provide compiler debugging facilities.
class LangOptions {
public:
/// \brief Whether to use the constraint solver for type checking.
///
/// FIXME: This option is temporary, and will be removed once the constraint
/// solver is the only type checker.
bool UseConstraintSolver = false;
/// \brief Whether we are debugging the constraint solver.
///
/// This option enables verbose debugging output from the constraint
/// solver.
bool DebugConstraintSolver = false;
};
}
#endif

View File

@@ -53,11 +53,7 @@ namespace swift {
/// walks the AST to resolve types and diagnose problems therein. StartElem
/// indicates where to start for incremental type checking in the
/// main module.
///
/// \param dumpConstraints Dump the constraints of any expressions in
/// top-level code declarations.
void performTypeChecking(TranslationUnit *TU, unsigned StartElem = 0,
bool dumpConstraints = false);
void performTypeChecking(TranslationUnit *TU, unsigned StartElem = 0);
/// performCaptureAnalysis - Analyse the AST and mark local declarations
/// and expressions which can capture them so they can be emitted more

View File

@@ -58,8 +58,10 @@ ASTContext::Implementation::Implementation()
: IdentifierTable(Allocator) {}
ASTContext::Implementation::~Implementation() {}
ASTContext::ASTContext(llvm::SourceMgr &sourcemgr, DiagnosticEngine &Diags)
ASTContext::ASTContext(LangOptions &langOpts, llvm::SourceMgr &sourcemgr,
DiagnosticEngine &Diags)
: Impl(*new Implementation()),
LangOpts(langOpts),
SourceMgr(sourcemgr),
Diags(Diags),
TheBuiltinModule(new (*this) BuiltinModule(getIdentifier("Builtin"),*this)),

View File

@@ -25,6 +25,7 @@
#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/SaveAndRestore.h"
#include <iterator>
#include <memory>
#include <utility>
@@ -3303,11 +3304,11 @@ bool ConstraintSystem::solve(SmallVectorImpl<ConstraintSystem *> &viable) {
assert(&getTopConstraintSystem() == this &&"Can only solve at the top level");
// Simplify this constraint system.
if (TC.DebugConstraintSolver) {
if (TC.getLangOpts().DebugConstraintSolver) {
llvm::errs() << "---Simplified constraints---\n";
}
bool error = simplify();
if (TC.DebugConstraintSolver) {
if (TC.getLangOpts().DebugConstraintSolver) {
dump();
}
if (error)
@@ -3580,6 +3581,10 @@ Expr *ConstraintSystem::applySolution(Expr *expr) {
assert(freeVariables.empty() && "Solution has free variables");
#endif
// FIXME: Disable the constraint-based type checker here, because we depend
// heavily on the existing type checker.
llvm::SaveAndRestore<bool> savedUseCS(TC.getLangOpts().UseConstraintSolver,
false);
ExprRewriter rewriter(*this);
ExprWalker walker(rewriter);
return expr->walk(walker);
@@ -3618,6 +3623,9 @@ Expr *TypeChecker::typeCheckExpressionConstraints(Expr *expr, Type convertType){
// Type check the type in an array new expression.
if (auto newArray = dyn_cast<NewArrayExpr>(expr)) {
llvm::SaveAndRestore<bool> savedUseCS(
TC.getLangOpts().UseConstraintSolver,
false);
if (TC.validateType(newArray->getElementTypeLoc(),
/*isFirstPass=*/false))
return nullptr;
@@ -3677,7 +3685,7 @@ Expr *TypeChecker::typeCheckExpressionConstraints(Expr *expr, Type convertType){
cs.addConstraint(ConstraintKind::Conversion, expr->getType(), convertType);
}
if (DebugConstraintSolver) {
if (getLangOpts().DebugConstraintSolver) {
log << "---Initial constraints for the given expression---\n";
expr->dump();
log << "\n";
@@ -3687,7 +3695,7 @@ Expr *TypeChecker::typeCheckExpressionConstraints(Expr *expr, Type convertType){
// Attempt to solve the constraint system.
SmallVector<ConstraintSystem *, 4> viable;
if (cs.solve(viable)) {
if (DebugConstraintSolver) {
if (getLangOpts().DebugConstraintSolver) {
llvm::errs() << "---Solved constraints---\n";
cs.dump();
@@ -3721,7 +3729,7 @@ Expr *TypeChecker::typeCheckExpressionConstraints(Expr *expr, Type convertType){
}
auto solution = viable[0];
if (DebugConstraintSolver) {
if (getLangOpts().DebugConstraintSolver) {
log << "---Solution---\n";
solution->dump();
}
@@ -3741,7 +3749,7 @@ Expr *TypeChecker::typeCheckExpressionConstraints(Expr *expr, Type convertType){
return nullptr;
}
if (DebugConstraintSolver) {
if (getLangOpts().DebugConstraintSolver) {
log << "---Type-checked expression---\n";
result->dump();
}

View File

@@ -1664,12 +1664,16 @@ Expr *TypeChecker::typeCheckNewReferenceExpr(NewReferenceExpr *expr) {
return SemaExpressionTree(*this).visitNewReferenceExpr(expr);
}
bool TypeChecker::typeCheckExpression(Expr *&E, Type ConvertType,
bool useConstraintSolver) {
bool TypeChecker::typeCheckExpression(Expr *&E, Type ConvertType) {
// If we're using the constraint solver, we take a different path through
// the type checker. Handle it here.
if (useConstraintSolver) {
llvm::SaveAndRestore<bool> debug(DebugConstraintSolver, true);
if (getLangOpts().UseConstraintSolver) {
// If this expression has already been type-checked, we're done.
if (E->getType())
return E->getType()->is<ErrorType>();
llvm::SaveAndRestore<bool> debug(getLangOpts().DebugConstraintSolver,
true);
E = typeCheckExpressionConstraints(E, ConvertType);
return E == nullptr;
}

View File

@@ -519,11 +519,10 @@ void TypeChecker::typeCheckDestructorBody(DestructorDecl *DD) {
StmtChecker(*this, DD).typeCheckStmt(Body);
}
void TypeChecker::typeCheckTopLevelCodeDecl(TopLevelCodeDecl *TLCD,
bool useConstraintSolver) {
void TypeChecker::typeCheckTopLevelCodeDecl(TopLevelCodeDecl *TLCD) {
auto Elem = TLCD->getBody();
if (Expr *E = Elem.dyn_cast<Expr*>()) {
if (typeCheckExpression(E, Type(), useConstraintSolver))
if (typeCheckExpression(E, Type()))
return;
if (TU.Kind == TranslationUnit::Repl)
typeCheckTopLevelReplExpr(E, TLCD);

View File

@@ -401,8 +401,7 @@ static void checkClassOverrides(TypeChecker &TC, ClassDecl *CD) {
/// walks the AST to resolve types and diagnose problems therein.
///
/// FIXME: This should be moved out to somewhere else.
void swift::performTypeChecking(TranslationUnit *TU, unsigned StartElem,
bool useConstraintSolver) {
void swift::performTypeChecking(TranslationUnit *TU, unsigned StartElem) {
TypeChecker TC(*TU);
struct ExprPrePassWalker : private ASTWalker {
@@ -684,7 +683,7 @@ void swift::performTypeChecking(TranslationUnit *TU, unsigned StartElem,
if (TopLevelCodeDecl *TLCD = dyn_cast<TopLevelCodeDecl>(D)) {
// Immediately perform global name-binding etc.
prePass.doWalk(TLCD);
TC.typeCheckTopLevelCodeDecl(TLCD, useConstraintSolver);
TC.typeCheckTopLevelCodeDecl(TLCD);
} else {
prePass.doWalk(D);
TC.typeCheckDecl(D, /*isFirstPass*/false);

View File

@@ -278,9 +278,6 @@ public:
TranslationUnit &TU;
ASTContext &Context;
bool UseConstraintSolver = false;
bool DebugConstraintSolver = false;
private:
/// \brief The 'Enumerable' protocol, used by the for-each loop.
ProtocolDecl *EnumerableProto;
@@ -297,6 +294,8 @@ public:
TypeChecker(TranslationUnit &TU)
: TU(TU), Context(TU.Ctx), EnumerableProto(0), RangeProto(0) {}
LangOptions &getLangOpts() const { return Context.LangOpts; }
template<typename ...ArgTypes>
InFlightDiagnostic diagnose(ArgTypes... Args) {
return Context.Diags.diagnose(Args...);
@@ -368,8 +367,7 @@ public:
void typeCheckFunctionBody(FuncExpr *FE);
void typeCheckConstructorBody(ConstructorDecl *CD);
void typeCheckDestructorBody(DestructorDecl *DD);
void typeCheckTopLevelCodeDecl(TopLevelCodeDecl *TLCD,
bool useConstraintSolver);
void typeCheckTopLevelCodeDecl(TopLevelCodeDecl *TLCD);
void typeCheckTopLevelReplExpr(Expr *&E, TopLevelCodeDecl *TLCD);
void REPLCheckPatternBinding(PatternBindingDecl *D);
@@ -395,8 +393,7 @@ public:
/// solver's application.
Expr *typeCheckNewReferenceExpr(NewReferenceExpr *expr);
bool typeCheckExpression(Expr *&E, Type ConvertType = Type(),
bool useConstraintSolver = false);
bool typeCheckExpression(Expr *&E, Type ConvertType = Type());
Expr *typeCheckExpressionConstraints(Expr *expr, Type convertType = Type());
bool typeCheckPattern(Pattern *P, bool isFirstPass, bool allowUnknownTypes);

View File

@@ -77,15 +77,14 @@ swift::buildSingleTranslationUnit(ASTContext &Context, unsigned BufferID,
bool swift::appendToMainTranslationUnit(TranslationUnit *TU, unsigned BufferID,
unsigned CurTUElem,
unsigned &BufferOffset,
unsigned BufferEndOffset,
bool useConstraintSolver) {
unsigned BufferEndOffset) {
bool FoundAnySideEffects = false;
do {
FoundAnySideEffects |= parseIntoTranslationUnit(TU, BufferID,
&BufferOffset,
BufferEndOffset);
performNameBinding(TU, CurTUElem);
performTypeChecking(TU, CurTUElem, useConstraintSolver);
performTypeChecking(TU, CurTUElem);
CurTUElem = TU->Decls.size();
} while (BufferOffset != BufferEndOffset);
return FoundAnySideEffects;

View File

@@ -27,6 +27,5 @@ namespace swift {
bool appendToMainTranslationUnit(TranslationUnit *TU, unsigned BufferID,
unsigned CurTUElem,
unsigned &BufferOffset,
unsigned BufferEndOffset,
bool useConstraintSolver);
unsigned BufferEndOffset);
}

View File

@@ -34,6 +34,7 @@
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/Process.h"
#include "llvm/Support/SaveAndRestore.h"
#include "llvm/Support/Signals.h"
#include "llvm/Support/SourceMgr.h"
#include "llvm/Support/system_error.h"
@@ -305,8 +306,7 @@ void swift::REPL(ASTContext &Context) {
swift::appendToMainTranslationUnit(TU, BufferID, CurTUElem,
CurBufferOffset,
CurBufferEndOffset,
/*useConstraintSolver=*/false);
CurBufferEndOffset);
if (Context.hadError())
return;
@@ -418,11 +418,12 @@ void swift::REPL(ASTContext &Context) {
continue;
// Parse the current line(s).
llvm::SaveAndRestore<bool> setUseConstraintSolver(
TU->getASTContext().LangOpts.UseConstraintSolver, useConstraintSolver);
bool ShouldRun =
swift::appendToMainTranslationUnit(TU, BufferID, CurTUElem,
CurBufferOffset,
CurBufferEndOffset,
useConstraintSolver);
CurBufferEndOffset);
if (useConstraintSolver) {
useConstraintSolver = false;
ShouldRun = false;