Example #1
0
/// 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);
}
Example #2
0
/// 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);
}