/// processREPLTopLevel - This is called after we've parsed and typechecked some /// new decls at the top level. We inject code to print out expressions and /// pattern bindings the are evaluated. void TypeChecker::processREPLTopLevel(SourceFile &SF, TopLevelContext &TLC, unsigned FirstDecl) { // Move new declarations out. std::vector<Decl *> NewDecls(SF.Decls.begin()+FirstDecl, SF.Decls.end()); SF.Decls.resize(FirstDecl); REPLChecker RC(*this, SF, TLC); // Loop over each of the new decls, processing them, adding them back to // the Decls list. for (Decl *D : NewDecls) { SF.Decls.push_back(D); TopLevelCodeDecl *TLCD = dyn_cast<TopLevelCodeDecl>(D); if (!TLCD || TLCD->getBody()->getElements().empty()) continue; auto Entry = TLCD->getBody()->getElement(0); // Check to see if the TLCD has an expression that we have to transform. if (Expr *E = Entry.dyn_cast<Expr*>()) RC.processREPLTopLevelExpr(E); else if (Decl *D = Entry.dyn_cast<Decl*>()) if (PatternBindingDecl *PBD = dyn_cast<PatternBindingDecl>(D)) RC.processREPLTopLevelPatternBinding(PBD); } contextualizeTopLevelCode(TLC, llvm::makeArrayRef(SF.Decls).slice(FirstDecl)); }
/// Emit logic to print the specified expression value with the given /// description of the pattern involved. void REPLChecker::generatePrintOfExpression(StringRef NameStr, Expr *E) { // Always print rvalues, not lvalues. E = TC.coerceToMaterializable(E); SourceLoc Loc = E->getStartLoc(); SourceLoc EndLoc = E->getEndLoc(); // Require a non-trivial set of print functions. if (requirePrintDecls()) return; // Build function of type T->() which prints the operand. VarDecl *Arg = new (Context) ParamDecl(/*isLet=*/true, SourceLoc(), Identifier(), Loc, Context.getIdentifier("arg"), E->getType(), /*DC*/ nullptr); Pattern *ParamPat = new (Context) NamedPattern(Arg); ParamPat = new (Context) TypedPattern(ParamPat, TypeLoc::withoutLoc(Arg->getType())); TuplePatternElt elt{ParamPat}; ParamPat = TuplePattern::create(Context, SourceLoc(), elt, SourceLoc()); TC.typeCheckPattern(ParamPat, Arg->getDeclContext(), TR_ImmediateFunctionInput); TopLevelCodeDecl *newTopLevel = new (Context) TopLevelCodeDecl(&SF); unsigned discriminator = TLC.claimNextClosureDiscriminator(); ClosureExpr *CE = new (Context) ClosureExpr(ParamPat, SourceLoc(), SourceLoc(), SourceLoc(), TypeLoc(), discriminator, newTopLevel); Type ParamTy = ParamPat->getType(); ParamTy = ParamTy->getRelabeledType(TC.Context, { Identifier() }); Type FuncTy = FunctionType::get(ParamTy, TupleType::getEmpty(Context)); CE->setType(FuncTy); // Convert the pattern to a string we can print. llvm::SmallString<16> PrefixString; PrefixString += "// "; PrefixString += NameStr; PrefixString += " : "; PrefixString += E->getType()->getWithoutParens()->getString(); PrefixString += " = "; // Unique the type string into an identifier since PrintLiteralString is // building an AST around the string that must persist beyond the lifetime of // PrefixString. auto TmpStr = Context.getIdentifier(PrefixString).str(); StmtBuilder builder(*this, CE); builder.printLiteralString(TmpStr, Loc); builder.printReplExpr(Arg, Loc); // Typecheck the function. BraceStmt *Body = builder.createBodyStmt(Loc, EndLoc); CE->setBody(Body, false); TC.typeCheckClosureBody(CE); // If the caller didn't wrap the argument in parentheses or make it a tuple, // add the extra parentheses now. Expr *TheArg = E; Type Ty = ParenType::get(TC.Context, TheArg->getType()); TheArg = new (TC.Context) ParenExpr(SourceLoc(), TheArg, SourceLoc(), false, Ty); Expr *TheCall = new (Context) CallExpr(CE, TheArg, /*Implicit=*/true); if (TC.typeCheckExpressionShallow(TheCall, Arg->getDeclContext())) return ; // Inject the call into the top level stream by wrapping it with a TLCD. auto *BS = BraceStmt::create(Context, Loc, ASTNode(TheCall), EndLoc); newTopLevel->setBody(BS); TC.checkTopLevelErrorHandling(newTopLevel); SF.Decls.push_back(newTopLevel); }
/// Emit logic to print the specified expression value with the given /// description of the pattern involved. void REPLChecker::generatePrintOfExpression(StringRef NameStr, Expr *E) { // Always print rvalues, not lvalues. E = TC.coerceToRValue(E); SourceLoc Loc = E->getStartLoc(); SourceLoc EndLoc = E->getEndLoc(); // Require a non-trivial set of print functions. if (requirePrintDecls()) return; TopLevelCodeDecl *newTopLevel = new (Context) TopLevelCodeDecl(&SF); // Build function of type T->() which prints the operand. auto *Arg = new (Context) ParamDecl( VarDecl::Specifier::Default, SourceLoc(), SourceLoc(), Identifier(), Loc, Context.getIdentifier("arg"), E->getType(), /*DC*/ newTopLevel); Arg->setInterfaceType(E->getType()); auto params = ParameterList::createWithoutLoc(Arg); unsigned discriminator = TLC.claimNextClosureDiscriminator(); ClosureExpr *CE = new (Context) ClosureExpr(params, SourceLoc(), SourceLoc(), SourceLoc(), TypeLoc(), discriminator, newTopLevel); CE->setType(ParameterList::getFullInterfaceType( TupleType::getEmpty(Context), params, Context)); // Convert the pattern to a string we can print. llvm::SmallString<16> PrefixString; PrefixString += "// "; PrefixString += NameStr; PrefixString += " : "; PrefixString += E->getType()->getWithoutParens()->getString(); PrefixString += " = "; // Unique the type string into an identifier since PrintLiteralString is // building an AST around the string that must persist beyond the lifetime of // PrefixString. auto TmpStr = Context.getIdentifier(PrefixString).str(); StmtBuilder builder(*this, CE); builder.printLiteralString(TmpStr, Loc); builder.printReplExpr(Arg, Loc); // Typecheck the function. BraceStmt *Body = builder.createBodyStmt(Loc, EndLoc); CE->setBody(Body, false); TC.typeCheckClosureBody(CE); auto *TheCall = CallExpr::createImplicit(Context, CE, { E }, { }); TheCall->getArg()->setType(ParenType::get(Context, E->getType())); TheCall->setType(Context.TheEmptyTupleType); // Inject the call into the top level stream by wrapping it with a TLCD. auto *BS = BraceStmt::create(Context, Loc, ASTNode(TheCall), EndLoc); newTopLevel->setBody(BS); TC.checkTopLevelErrorHandling(newTopLevel); SF.Decls.push_back(newTopLevel); }