Initial implementation of the "print" part of the REPL.

Swift SVN r1484
This commit is contained in:
Eli Friedman
2012-04-19 01:13:37 +00:00
parent ae316ce2a8
commit acc17d69aa
7 changed files with 96 additions and 13 deletions

View File

@@ -53,6 +53,7 @@ public:
ASTContext &Ctx;
Identifier Name;
bool IsMainModule;
bool IsReplModule;
//===--------------------------------------------------------------------===//
// AST Phase of Translation
@@ -74,10 +75,10 @@ public:
protected:
Module(DeclContextKind Kind, Identifier Name, Component *C, ASTContext &Ctx,
bool IsMainModule)
bool IsMainModule, bool IsReplModule)
: DeclContext(Kind, nullptr), LookupCachePimpl(0), ExtensionCachePimpl(0),
Comp(C), Ctx(Ctx), Name(Name), IsMainModule(IsMainModule),
ASTStage(Parsing) {
IsReplModule(IsReplModule), ASTStage(Parsing) {
assert(Comp != nullptr || Kind == DeclContextKind::BuiltinModule);
}
@@ -164,8 +165,9 @@ public:
BraceStmt *Body;
TranslationUnit(Identifier Name, Component *Comp, ASTContext &C,
bool IsMainModule)
: Module(DeclContextKind::TranslationUnit, Name, Comp, C, IsMainModule),
bool IsMainModule, bool IsReplModule)
: Module(DeclContextKind::TranslationUnit, Name, Comp, C, IsMainModule,
IsReplModule),
Body(nullptr) { }
/// getUnresolvedIdentifierTypes - This is a list of scope-qualified types
@@ -209,7 +211,7 @@ public:
class BuiltinModule : public Module {
public:
BuiltinModule(Identifier Name, ASTContext &Ctx)
: Module(DeclContextKind::BuiltinModule, Name, nullptr, Ctx, false) {
: Module(DeclContextKind::BuiltinModule, Name, nullptr, Ctx, false, false) {
// The Builtin module is always well formed.
ASTStage = TypeChecked;
}

View File

@@ -47,23 +47,27 @@ void swift::irgen::emitClosure(IRGenFunction &IGF, CapturingExpr *E,
explosion);
}
bool HasCaptures = !E->getCaptures().empty();
// Create the IR function.
llvm::FunctionType *fnType =
IGF.IGM.getFunctionType(E->getType(), ExplosionKind::Minimal, 0, true);
IGF.IGM.getFunctionType(E->getType(), ExplosionKind::Minimal, 0,
HasCaptures);
llvm::Function *fn =
llvm::Function::Create(fnType, llvm::GlobalValue::InternalLinkage,
"closure", &IGF.IGM.Module);
IRGenFunction innerIGF(IGF.IGM, E->getType(), Patterns,
ExplosionKind::Minimal, /*uncurry level*/ 0, fn,
Prologue::StandardWithContext);
HasCaptures ? Prologue::StandardWithContext :
Prologue::Standard);
ManagedValue contextPtr(IGF.IGM.RefCountedNull);
// There are two places we need to generate code for captures: in the
// current function, to store the captures to a capture block, and in the
// inner function, to load the captures from the capture block.
if (!E->getCaptures().empty()) {
if (HasCaptures) {
SmallVector<const TypeInfo *, 4> Fields;
for (ValueDecl *D : E->getCaptures()) {
Type RefTy = LValueType::get(D->getType(),

View File

@@ -149,7 +149,8 @@ Module *NameBinder::getModule(std::pair<Identifier, SourceLoc> ModuleID) {
// For now, treat all separate modules as unique components.
Component *Comp = new (Context.Allocate<Component>(1)) Component();
ImportedTU = new (Context) TranslationUnit(ModuleID.first, Comp, Context,
/*IsMainModule*/false);
/*IsMainModule*/false,
/*IsReplModule*/false);
parseIntoTranslationUnit(ImportedTU, BufferID);
LoadedModules[ModuleID.first.str()] = ImportedTU;

View File

@@ -21,6 +21,8 @@
#include "swift/AST/ASTWalker.h"
#include "llvm/ADT/PointerUnion.h"
#include "llvm/ADT/Twine.h"
#include "NameLookup.h"
using namespace swift;
namespace {
@@ -171,6 +173,74 @@ void TypeChecker::typeCheckIgnoredExpr(Expr *E) {
}
}
/// Check an expression at the top level in a REPL.
void TypeChecker::typeCheckTopLevelReplExpr(Expr *&E) {
CanType T = E->getType()->getCanonicalType();
SourceLoc Loc = E->getStartLoc();
SourceLoc EndLoc = E->getEndLoc();
// Build the function to call to print the expression.
Type FuncTy = T;
if (!isa<TupleType>(FuncTy)) {
TupleTypeElt Elt(T, Context.getIdentifier("arg"));
FuncTy = TupleType::get(Elt, Context);
}
FuncTy = FunctionType::get(FuncTy, TupleType::getEmpty(Context), Context);
VarDecl *Arg = new (Context) VarDecl(Loc, Context.getIdentifier("arg"), T,
&TU, /*IsModuleScope*/false);
Pattern* ParamPat = new (Context) NamedPattern(Arg);
FuncExpr *FE = FuncExpr::create(Context, Loc, ParamPat, FuncTy, 0, &TU);
// Print the expression.
// FIXME: Need to handle lvalues.
// FIXME: Need structural printing for tuples.
// FIXME: Need structural printing for oneofs.
SmallVector<BraceStmt::ExprStmtOrDecl, 4> BodyContent;
Identifier MemberName = Context.getIdentifier("replPrint");
MemberLookup Lookup(T, MemberName, TU);
if (Lookup.isSuccess()) {
Expr *ArgRef = new (Context) DeclRefExpr(Arg, Loc);
Expr *Res = recheckTypes(Lookup.createResultAST(ArgRef, Loc, EndLoc,
Context));
if (!Res)
return;
TupleExpr *CallArgs =
new (Context) TupleExpr(Loc, MutableArrayRef<Expr *>(), 0, EndLoc);
CallExpr *CE = new (Context) CallExpr(Res, CallArgs, Type());
Res = semaApplyExpr(CE);
if (!Res)
return;
BodyContent.push_back(Res);
} else {
Expr *PrintUnknown = new (Context) StringLiteralExpr("<unprintable value>",
Loc);
SmallVector<ValueDecl*, 4> Decls;
TU.lookupGlobalValue(Context.getIdentifier("print"),
NLKind::UnqualifiedLookup, Decls);
Expr *PrintStrFn = OverloadedDeclRefExpr::createWithCopy(Decls, Loc);
PrintUnknown = new (Context) CallExpr(PrintStrFn, PrintUnknown, Type());
BodyContent.push_back(PrintUnknown);
}
// Print a newline at the end.
Expr *PrintNewLine = new (Context) StringLiteralExpr("\n", E->getStartLoc());
SmallVector<ValueDecl*, 4> Decls;
TU.lookupGlobalValue(Context.getIdentifier("print"),
NLKind::UnqualifiedLookup, Decls);
Expr *PrintStrFn = OverloadedDeclRefExpr::createWithCopy(Decls, Loc);
PrintNewLine = new (Context) CallExpr(PrintStrFn, PrintNewLine, Type());
BodyContent.push_back(PrintNewLine);
// Typecheck the function.
BraceStmt *Body = BraceStmt::create(Context, Loc, BodyContent, EndLoc);
StmtChecker(*this, FE).typeCheckStmt(Body);
FE->setBody(Body);
// Typecheck the call.
CallExpr *CE = new (Context) CallExpr(FE, E);
E = semaApplyExpr(CE);
}
/// performTypeChecking - Once parsing and namebinding are complete, these
/// walks the AST to resolve types and diagnose problems therein.
///
@@ -215,7 +285,10 @@ void swift::performTypeChecking(TranslationUnit *TU, unsigned StartElem) {
auto Elem = TU->Body->getElement(i);
if (Expr *E = Elem.dyn_cast<Expr*>()) {
if (checker.typeCheckExpr(E)) continue;
TC.typeCheckIgnoredExpr(E);
if (TU->IsReplModule)
TC.typeCheckTopLevelReplExpr(E);
else
TC.typeCheckIgnoredExpr(E);
TU->Body->setElement(i, E);
} else if (Stmt *S = Elem.dyn_cast<Stmt*>()) {
if (checker.typeCheckStmt(S)) continue;

View File

@@ -41,7 +41,8 @@ public:
Expr *semaApplyExpr(ApplyExpr *E);
Expr *semaUnresolvedDotExpr(UnresolvedDotExpr *E);
void typeCheckIgnoredExpr(Expr *E);
void typeCheckTopLevelReplExpr(Expr *&E);
/// \brief Perform a shallow recheck of the given newly-built AST node.
///
/// Rechecking typically occurs when one has resolved name lookup and built a

View File

@@ -57,7 +57,8 @@ swift::buildSingleTranslationUnit(ASTContext &Context, unsigned BufferID,
const llvm::MemoryBuffer *Buffer = Context.SourceMgr.getMemoryBuffer(BufferID);
Identifier ID = getModuleIdentifier(Buffer, Context);
TranslationUnit *TU = new (Context) TranslationUnit(ID, Comp, Context,
IsMainModule);
IsMainModule,
/*IsReplModule=*/false);
unsigned BufferOffset = 0;
unsigned CurTUElem = 0;

View File

@@ -143,7 +143,8 @@ void swift::REPL(ASTContext &Context) {
Context.SourceMgr.AddNewSourceBuffer(Buffer, llvm::SMLoc());
Identifier ID = Context.getIdentifier("REPL");
TranslationUnit *TU = new (Context) TranslationUnit(ID, Comp, Context,
/*IsMainModule=*/true);
/*IsMainModule=*/true,
/*IsReplModule=*/true);
llvm::SmallPtrSet<TranslationUnit*, 8> ImportedModules;
llvm::LLVMContext LLVMContext;