mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
Initial implementation of the "print" part of the REPL.
Swift SVN r1484
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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(),
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user