/// When we see an expression in a TopLevelCodeDecl in the REPL, process it, /// adding the proper decls back to the top level of the file. void REPLChecker::processREPLTopLevelExpr(Expr *E) { CanType T = E->getType()->getCanonicalType(); // Don't try to print invalid expressions, module exprs, or void expressions. if (T->hasError() || isa<ModuleType>(T) || T->isVoid()) return; // Okay, we need to print this expression. We generally do this by creating a // REPL metavariable (e.g. r4) to hold the result, so it can be referred to // in the future. However, if this is a direct reference to a decl (e.g. "x") // then don't create a repl metavariable. if (VarDecl *d = getObviousDeclFromExpr(E)) { generatePrintOfExpression(d->getName().str(), E); return; } // Remove the expression from being in the list of decls to execute, we're // going to reparent it. auto TLCD = cast<TopLevelCodeDecl>(SF.Decls.back()); E = TC.coerceToRValue(E); // Create the meta-variable, let the typechecker name it. Identifier name = TC.getNextResponseVariableName(SF.getParentModule()); VarDecl *vd = new (Context) VarDecl(/*IsStatic*/false, VarDecl::Specifier::Let, /*IsCaptureList*/false, E->getStartLoc(), name, E->getType(), &SF); vd->setInterfaceType(E->getType()); SF.Decls.push_back(vd); // Create a PatternBindingDecl to bind the expression into the decl. Pattern *metavarPat = new (Context) NamedPattern(vd); metavarPat->setType(E->getType()); PatternBindingDecl *metavarBinding = PatternBindingDecl::create( Context, /*StaticLoc*/ SourceLoc(), StaticSpellingKind::None, /*VarLoc*/ E->getStartLoc(), metavarPat, /*EqualLoc*/ SourceLoc(), E, TLCD); // Overwrite the body of the existing TopLevelCodeDecl. TLCD->setBody(BraceStmt::create(Context, metavarBinding->getStartLoc(), ASTNode(metavarBinding), metavarBinding->getEndLoc(), /*implicit*/true)); // Finally, print the variable's value. E = TC.buildCheckedRefExpr(vd, &SF, DeclNameLoc(E->getStartLoc()), /*Implicit=*/true); generatePrintOfExpression(vd->getName().str(), E); }
static bool isVoidLike(CanType type) { return (type->isVoid() || (isa<TupleType>(type) && cast<TupleType>(type)->getNumElements() == 1 && cast<TupleType>(type).getElementType(0)->isVoid())); }