/// 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); }