return It->second;
}
-namespace {
-// An arbitrary fragment of code within a stencil.
-struct RawTextData {
- explicit RawTextData(std::string T) : Text(std::move(T)) {}
- std::string Text;
-};
-
-// A debugging operation to dump the AST for a particular (bound) AST node.
-struct DebugPrintNodeData {
- explicit DebugPrintNodeData(std::string S) : Id(std::move(S)) {}
- std::string Id;
-};
-
-// Operators that take a single node Id as an argument.
-enum class UnaryNodeOperator {
- Parens,
- Deref,
- MaybeDeref,
- AddressOf,
- MaybeAddressOf,
- Describe,
-};
-
-// Generic container for stencil operations with a (single) node-id argument.
-struct UnaryOperationData {
- UnaryOperationData(UnaryNodeOperator Op, std::string Id)
- : Op(Op), Id(std::move(Id)) {}
- UnaryNodeOperator Op;
- std::string Id;
-};
-
-// The fragment of code corresponding to the selected range.
-struct SelectorData {
- explicit SelectorData(RangeSelector S) : Selector(std::move(S)) {}
- RangeSelector Selector;
-};
-
-// A stencil operation to build a member access `e.m` or `e->m`, as appropriate.
-struct AccessData {
- AccessData(StringRef BaseId, Stencil Member)
- : BaseId(std::string(BaseId)), Member(std::move(Member)) {}
- std::string BaseId;
- Stencil Member;
-};
-
-struct IfBoundData {
- IfBoundData(StringRef Id, Stencil TrueStencil, Stencil FalseStencil)
- : Id(std::string(Id)), TrueStencil(std::move(TrueStencil)),
- FalseStencil(std::move(FalseStencil)) {}
- std::string Id;
- Stencil TrueStencil;
- Stencil FalseStencil;
-};
-
-struct SequenceData {
- SequenceData(std::vector<Stencil> Stencils) : Stencils(std::move(Stencils)) {}
- std::vector<Stencil> Stencils;
-};
-
-std::string toStringData(const RawTextData &Data) {
- std::string Result;
- llvm::raw_string_ostream OS(Result);
- OS << "\"";
- OS.write_escaped(Data.Text);
- OS << "\"";
- OS.flush();
- return Result;
-}
-
-std::string toStringData(const DebugPrintNodeData &Data) {
- return (llvm::Twine("dPrint(\"") + Data.Id + "\")").str();
-}
-
-std::string toStringData(const UnaryOperationData &Data) {
- StringRef OpName;
- switch (Data.Op) {
- case UnaryNodeOperator::Parens:
- OpName = "expression";
- break;
- case UnaryNodeOperator::Deref:
- OpName = "deref";
- break;
- case UnaryNodeOperator::MaybeDeref:
- OpName = "maybeDeref";
- break;
- case UnaryNodeOperator::AddressOf:
- OpName = "addressOf";
- break;
- case UnaryNodeOperator::MaybeAddressOf:
- OpName = "maybeAddressOf";
- break;
- case UnaryNodeOperator::Describe:
- OpName = "describe";
- break;
- }
- return (OpName + "(\"" + Data.Id + "\")").str();
-}
-
-std::string toStringData(const SelectorData &) { return "selection(...)"; }
-
-std::string toStringData(const AccessData &Data) {
- return (llvm::Twine("access(\"") + Data.BaseId + "\", " +
- Data.Member->toString() + ")")
- .str();
-}
-
-std::string toStringData(const IfBoundData &Data) {
- return (llvm::Twine("ifBound(\"") + Data.Id + "\", " +
- Data.TrueStencil->toString() + ", " + Data.FalseStencil->toString() +
- ")")
- .str();
-}
-
-std::string toStringData(const MatchConsumer<std::string> &) {
- return "run(...)";
-}
-
-std::string toStringData(const SequenceData &Data) {
- llvm::SmallVector<std::string, 2> Parts;
- Parts.reserve(Data.Stencils.size());
- for (const auto &S : Data.Stencils)
- Parts.push_back(S->toString());
- return (llvm::Twine("seq(") + llvm::join(Parts, ", ") + ")").str();
-}
-
-// The `evalData()` overloads evaluate the given stencil data to a string, given
-// the match result, and append it to `Result`. We define an overload for each
-// type of stencil data.
-
-Error evalData(const RawTextData &Data, const MatchFinder::MatchResult &,
- std::string *Result) {
- Result->append(Data.Text);
- return Error::success();
-}
-
static Error printNode(StringRef Id, const MatchFinder::MatchResult &Match,
std::string *Result) {
std::string Output;
return Error::success();
}
-Error evalData(const DebugPrintNodeData &Data,
- const MatchFinder::MatchResult &Match, std::string *Result) {
- return printNode(Data.Id, Match, Result);
-}
-
// FIXME: Consider memoizing this function using the `ASTContext`.
static bool isSmartPointerType(QualType Ty, ASTContext &Context) {
using namespace ::clang::ast_matchers;
return match(SmartPointer, Ty, Context).size() > 0;
}
-Error evalData(const UnaryOperationData &Data,
- const MatchFinder::MatchResult &Match, std::string *Result) {
- // The `Describe` operation can be applied to any node, not just expressions,
- // so it is handled here, separately.
- if (Data.Op == UnaryNodeOperator::Describe)
- return printNode(Data.Id, Match, Result);
-
- const auto *E = Match.Nodes.getNodeAs<Expr>(Data.Id);
- if (E == nullptr)
- return llvm::make_error<StringError>(
- errc::invalid_argument, "Id not bound or not Expr: " + Data.Id);
- llvm::Optional<std::string> Source;
- switch (Data.Op) {
- case UnaryNodeOperator::Parens:
- Source = tooling::buildParens(*E, *Match.Context);
- break;
- case UnaryNodeOperator::Deref:
- Source = tooling::buildDereference(*E, *Match.Context);
- break;
- case UnaryNodeOperator::MaybeDeref:
- if (E->getType()->isAnyPointerType() ||
- isSmartPointerType(E->getType(), *Match.Context)) {
- // Strip off any operator->. This can only occur inside an actual arrow
- // member access, so we treat it as equivalent to an actual object
- // expression.
- if (const auto *OpCall = dyn_cast<clang::CXXOperatorCallExpr>(E)) {
- if (OpCall->getOperator() == clang::OO_Arrow &&
- OpCall->getNumArgs() == 1) {
- E = OpCall->getArg(0);
- }
- }
- Source = tooling::buildDereference(*E, *Match.Context);
+namespace {
+// An arbitrary fragment of code within a stencil.
+class RawTextStencil : public StencilInterface {
+ std::string Text;
+
+public:
+ explicit RawTextStencil(std::string T) : Text(std::move(T)) {}
+
+ std::string toString() const override {
+ std::string Result;
+ llvm::raw_string_ostream OS(Result);
+ OS << "\"";
+ OS.write_escaped(Text);
+ OS << "\"";
+ OS.flush();
+ return Result;
+ }
+
+ Error eval(const MatchFinder::MatchResult &Match,
+ std::string *Result) const override {
+ Result->append(Text);
+ return Error::success();
+ }
+};
+
+// A debugging operation to dump the AST for a particular (bound) AST node.
+class DebugPrintNodeStencil : public StencilInterface {
+ std::string Id;
+
+public:
+ explicit DebugPrintNodeStencil(std::string S) : Id(std::move(S)) {}
+
+ std::string toString() const override {
+ return (llvm::Twine("dPrint(\"") + Id + "\")").str();
+ }
+
+ Error eval(const MatchFinder::MatchResult &Match,
+ std::string *Result) const override {
+ return printNode(Id, Match, Result);
+ }
+};
+
+// Operators that take a single node Id as an argument.
+enum class UnaryNodeOperator {
+ Parens,
+ Deref,
+ MaybeDeref,
+ AddressOf,
+ MaybeAddressOf,
+ Describe,
+};
+
+// Generic container for stencil operations with a (single) node-id argument.
+class UnaryOperationStencil : public StencilInterface {
+ UnaryNodeOperator Op;
+ std::string Id;
+
+public:
+ UnaryOperationStencil(UnaryNodeOperator Op, std::string Id)
+ : Op(Op), Id(std::move(Id)) {}
+
+ std::string toString() const override {
+ StringRef OpName;
+ switch (Op) {
+ case UnaryNodeOperator::Parens:
+ OpName = "expression";
+ break;
+ case UnaryNodeOperator::Deref:
+ OpName = "deref";
+ break;
+ case UnaryNodeOperator::MaybeDeref:
+ OpName = "maybeDeref";
+ break;
+ case UnaryNodeOperator::AddressOf:
+ OpName = "addressOf";
+ break;
+ case UnaryNodeOperator::MaybeAddressOf:
+ OpName = "maybeAddressOf";
+ break;
+ case UnaryNodeOperator::Describe:
+ OpName = "describe";
break;
}
- *Result += tooling::getText(*E, *Match.Context);
- return Error::success();
- case UnaryNodeOperator::AddressOf:
- Source = tooling::buildAddressOf(*E, *Match.Context);
- break;
- case UnaryNodeOperator::MaybeAddressOf:
- if (E->getType()->isAnyPointerType() ||
- isSmartPointerType(E->getType(), *Match.Context)) {
- // Strip off any operator->. This can only occur inside an actual arrow
- // member access, so we treat it as equivalent to an actual object
- // expression.
- if (const auto *OpCall = dyn_cast<clang::CXXOperatorCallExpr>(E)) {
- if (OpCall->getOperator() == clang::OO_Arrow &&
- OpCall->getNumArgs() == 1) {
- E = OpCall->getArg(0);
+ return (OpName + "(\"" + Id + "\")").str();
+ }
+
+ Error eval(const MatchFinder::MatchResult &Match,
+ std::string *Result) const override {
+ // The `Describe` operation can be applied to any node, not just
+ // expressions, so it is handled here, separately.
+ if (Op == UnaryNodeOperator::Describe)
+ return printNode(Id, Match, Result);
+
+ const auto *E = Match.Nodes.getNodeAs<Expr>(Id);
+ if (E == nullptr)
+ return llvm::make_error<StringError>(errc::invalid_argument,
+ "Id not bound or not Expr: " + Id);
+ llvm::Optional<std::string> Source;
+ switch (Op) {
+ case UnaryNodeOperator::Parens:
+ Source = tooling::buildParens(*E, *Match.Context);
+ break;
+ case UnaryNodeOperator::Deref:
+ Source = tooling::buildDereference(*E, *Match.Context);
+ break;
+ case UnaryNodeOperator::MaybeDeref:
+ if (E->getType()->isAnyPointerType() ||
+ isSmartPointerType(E->getType(), *Match.Context)) {
+ // Strip off any operator->. This can only occur inside an actual arrow
+ // member access, so we treat it as equivalent to an actual object
+ // expression.
+ if (const auto *OpCall = dyn_cast<clang::CXXOperatorCallExpr>(E)) {
+ if (OpCall->getOperator() == clang::OO_Arrow &&
+ OpCall->getNumArgs() == 1) {
+ E = OpCall->getArg(0);
+ }
}
+ Source = tooling::buildDereference(*E, *Match.Context);
+ break;
}
*Result += tooling::getText(*E, *Match.Context);
return Error::success();
+ case UnaryNodeOperator::AddressOf:
+ Source = tooling::buildAddressOf(*E, *Match.Context);
+ break;
+ case UnaryNodeOperator::MaybeAddressOf:
+ if (E->getType()->isAnyPointerType() ||
+ isSmartPointerType(E->getType(), *Match.Context)) {
+ // Strip off any operator->. This can only occur inside an actual arrow
+ // member access, so we treat it as equivalent to an actual object
+ // expression.
+ if (const auto *OpCall = dyn_cast<clang::CXXOperatorCallExpr>(E)) {
+ if (OpCall->getOperator() == clang::OO_Arrow &&
+ OpCall->getNumArgs() == 1) {
+ E = OpCall->getArg(0);
+ }
+ }
+ *Result += tooling::getText(*E, *Match.Context);
+ return Error::success();
+ }
+ Source = tooling::buildAddressOf(*E, *Match.Context);
+ break;
+ case UnaryNodeOperator::Describe:
+ llvm_unreachable("This case is handled at the start of the function");
}
- Source = tooling::buildAddressOf(*E, *Match.Context);
- break;
- case UnaryNodeOperator::Describe:
- llvm_unreachable("This case is handled at the start of the function");
+ if (!Source)
+ return llvm::make_error<StringError>(
+ errc::invalid_argument,
+ "Could not construct expression source from ID: " + Id);
+ *Result += *Source;
+ return Error::success();
}
- if (!Source)
- return llvm::make_error<StringError>(
- errc::invalid_argument,
- "Could not construct expression source from ID: " + Data.Id);
- *Result += *Source;
- return Error::success();
-}
+};
-Error evalData(const SelectorData &Data, const MatchFinder::MatchResult &Match,
- std::string *Result) {
- auto RawRange = Data.Selector(Match);
- if (!RawRange)
- return RawRange.takeError();
- CharSourceRange Range = Lexer::makeFileCharRange(
- *RawRange, *Match.SourceManager, Match.Context->getLangOpts());
- if (Range.isInvalid()) {
- // Validate the original range to attempt to get a meaningful error message.
- // If it's valid, then something else is the cause and we just return the
- // generic failure message.
- if (auto Err = tooling::validateEditRange(*RawRange, *Match.SourceManager))
- return handleErrors(std::move(Err), [](std::unique_ptr<StringError> E) {
- assert(E->convertToErrorCode() ==
- llvm::make_error_code(errc::invalid_argument) &&
- "Validation errors must carry the invalid_argument code");
- return llvm::createStringError(
- errc::invalid_argument,
- "selected range could not be resolved to a valid source range; " +
- E->getMessage());
- });
- return llvm::createStringError(
- errc::invalid_argument,
- "selected range could not be resolved to a valid source range");
+// The fragment of code corresponding to the selected range.
+class SelectorStencil : public StencilInterface {
+ RangeSelector Selector;
+
+public:
+ explicit SelectorStencil(RangeSelector S) : Selector(std::move(S)) {}
+
+ std::string toString() const override { return "selection(...)"; }
+
+ Error eval(const MatchFinder::MatchResult &Match,
+ std::string *Result) const override {
+ auto RawRange = Selector(Match);
+ if (!RawRange)
+ return RawRange.takeError();
+ CharSourceRange Range = Lexer::makeFileCharRange(
+ *RawRange, *Match.SourceManager, Match.Context->getLangOpts());
+ if (Range.isInvalid()) {
+ // Validate the original range to attempt to get a meaningful error
+ // message. If it's valid, then something else is the cause and we just
+ // return the generic failure message.
+ if (auto Err =
+ tooling::validateEditRange(*RawRange, *Match.SourceManager))
+ return handleErrors(std::move(Err), [](std::unique_ptr<StringError> E) {
+ assert(E->convertToErrorCode() ==
+ llvm::make_error_code(errc::invalid_argument) &&
+ "Validation errors must carry the invalid_argument code");
+ return llvm::createStringError(
+ errc::invalid_argument,
+ "selected range could not be resolved to a valid source range; " +
+ E->getMessage());
+ });
+ return llvm::createStringError(
+ errc::invalid_argument,
+ "selected range could not be resolved to a valid source range");
+ }
+ // Validate `Range`, because `makeFileCharRange` accepts some ranges that
+ // `validateEditRange` rejects.
+ if (auto Err = tooling::validateEditRange(Range, *Match.SourceManager))
+ return joinErrors(
+ llvm::createStringError(errc::invalid_argument,
+ "selected range is not valid for editing"),
+ std::move(Err));
+ *Result += tooling::getText(Range, *Match.Context);
+ return Error::success();
}
- // Validate `Range`, because `makeFileCharRange` accepts some ranges that
- // `validateEditRange` rejects.
- if (auto Err = tooling::validateEditRange(Range, *Match.SourceManager))
- return joinErrors(
- llvm::createStringError(errc::invalid_argument,
- "selected range is not valid for editing"),
- std::move(Err));
- *Result += tooling::getText(Range, *Match.Context);
- return Error::success();
-}
+};
+
+// A stencil operation to build a member access `e.m` or `e->m`, as appropriate.
+class AccessStencil : public StencilInterface {
+ std::string BaseId;
+ Stencil Member;
-Error evalData(const AccessData &Data, const MatchFinder::MatchResult &Match,
- std::string *Result) {
- const auto *E = Match.Nodes.getNodeAs<Expr>(Data.BaseId);
- if (E == nullptr)
- return llvm::make_error<StringError>(errc::invalid_argument,
- "Id not bound: " + Data.BaseId);
- if (!E->isImplicitCXXThis()) {
- llvm::Optional<std::string> S;
- if (E->getType()->isAnyPointerType() ||
- isSmartPointerType(E->getType(), *Match.Context)) {
- // Strip off any operator->. This can only occur inside an actual arrow
- // member access, so we treat it as equivalent to an actual object
- // expression.
- if (const auto *OpCall = dyn_cast<clang::CXXOperatorCallExpr>(E)) {
- if (OpCall->getOperator() == clang::OO_Arrow &&
- OpCall->getNumArgs() == 1) {
- E = OpCall->getArg(0);
+public:
+ AccessStencil(StringRef BaseId, Stencil Member)
+ : BaseId(std::string(BaseId)), Member(std::move(Member)) {}
+
+ std::string toString() const override {
+ return (llvm::Twine("access(\"") + BaseId + "\", " + Member->toString() +
+ ")")
+ .str();
+ }
+
+ Error eval(const MatchFinder::MatchResult &Match,
+ std::string *Result) const override {
+ const auto *E = Match.Nodes.getNodeAs<Expr>(BaseId);
+ if (E == nullptr)
+ return llvm::make_error<StringError>(errc::invalid_argument,
+ "Id not bound: " + BaseId);
+ if (!E->isImplicitCXXThis()) {
+ llvm::Optional<std::string> S;
+ if (E->getType()->isAnyPointerType() ||
+ isSmartPointerType(E->getType(), *Match.Context)) {
+ // Strip off any operator->. This can only occur inside an actual arrow
+ // member access, so we treat it as equivalent to an actual object
+ // expression.
+ if (const auto *OpCall = dyn_cast<clang::CXXOperatorCallExpr>(E)) {
+ if (OpCall->getOperator() == clang::OO_Arrow &&
+ OpCall->getNumArgs() == 1) {
+ E = OpCall->getArg(0);
+ }
}
+ S = tooling::buildArrow(*E, *Match.Context);
+ } else {
+ S = tooling::buildDot(*E, *Match.Context);
}
- S = tooling::buildArrow(*E, *Match.Context);
- } else {
- S = tooling::buildDot(*E, *Match.Context);
+ if (S.hasValue())
+ *Result += *S;
+ else
+ return llvm::make_error<StringError>(
+ errc::invalid_argument,
+ "Could not construct object text from ID: " + BaseId);
}
- if (S.hasValue())
- *Result += *S;
- else
- return llvm::make_error<StringError>(
- errc::invalid_argument,
- "Could not construct object text from ID: " + Data.BaseId);
+ return Member->eval(Match, Result);
}
- return Data.Member->eval(Match, Result);
-}
+};
-Error evalData(const IfBoundData &Data, const MatchFinder::MatchResult &Match,
- std::string *Result) {
- auto &M = Match.Nodes.getMap();
- return (M.find(Data.Id) != M.end() ? Data.TrueStencil : Data.FalseStencil)
- ->eval(Match, Result);
-}
+class IfBoundStencil : public StencilInterface {
+ std::string Id;
+ Stencil TrueStencil;
+ Stencil FalseStencil;
-Error evalData(const MatchConsumer<std::string> &Fn,
- const MatchFinder::MatchResult &Match, std::string *Result) {
- Expected<std::string> Value = Fn(Match);
- if (!Value)
- return Value.takeError();
- *Result += *Value;
- return Error::success();
-}
+public:
+ IfBoundStencil(StringRef Id, Stencil TrueStencil, Stencil FalseStencil)
+ : Id(std::string(Id)), TrueStencil(std::move(TrueStencil)),
+ FalseStencil(std::move(FalseStencil)) {}
-Error evalData(const SequenceData &Data, const MatchFinder::MatchResult &Match,
- std::string *Result) {
- for (const auto &S : Data.Stencils)
- if (auto Err = S->eval(Match, Result))
- return Err;
- return Error::success();
-}
+ std::string toString() const override {
+ return (llvm::Twine("ifBound(\"") + Id + "\", " + TrueStencil->toString() +
+ ", " + FalseStencil->toString() + ")")
+ .str();
+ }
-template <typename T> class StencilImpl : public StencilInterface {
- T Data;
+ Error eval(const MatchFinder::MatchResult &Match,
+ std::string *Result) const override {
+ auto &M = Match.Nodes.getMap();
+ return (M.find(Id) != M.end() ? TrueStencil : FalseStencil)
+ ->eval(Match, Result);
+ }
+};
+
+class SequenceStencil : public StencilInterface {
+ std::vector<Stencil> Stencils;
public:
- template <typename... Ps>
- explicit StencilImpl(Ps &&... Args) : Data(std::forward<Ps>(Args)...) {}
+ SequenceStencil(std::vector<Stencil> Stencils)
+ : Stencils(std::move(Stencils)) {}
+
+ std::string toString() const override {
+ llvm::SmallVector<std::string, 2> Parts;
+ Parts.reserve(Stencils.size());
+ for (const auto &S : Stencils)
+ Parts.push_back(S->toString());
+ return (llvm::Twine("seq(") + llvm::join(Parts, ", ") + ")").str();
+ }
Error eval(const MatchFinder::MatchResult &Match,
std::string *Result) const override {
- return evalData(Data, Match, Result);
+ for (const auto &S : Stencils)
+ if (auto Err = S->eval(Match, Result))
+ return Err;
+ return Error::success();
}
+};
+
+class RunStencil : public StencilInterface {
+ MatchConsumer<std::string> Consumer;
+
+public:
+ explicit RunStencil(MatchConsumer<std::string> C) : Consumer(std::move(C)) {}
- std::string toString() const override { return toStringData(Data); }
+ std::string toString() const override { return "run(...)"; }
+
+ Error eval(const MatchFinder::MatchResult &Match,
+ std::string *Result) const override {
+
+ Expected<std::string> Value = Consumer(Match);
+ if (!Value)
+ return Value.takeError();
+ *Result += *Value;
+ return Error::success();
+ }
};
} // namespace
Stencil transformer::detail::makeStencil(StringRef Text) {
- return std::make_shared<StencilImpl<RawTextData>>(std::string(Text));
+ return std::make_shared<RawTextStencil>(std::string(Text));
}
Stencil transformer::detail::makeStencil(RangeSelector Selector) {
- return std::make_shared<StencilImpl<SelectorData>>(std::move(Selector));
+ return std::make_shared<SelectorStencil>(std::move(Selector));
}
Stencil transformer::dPrint(StringRef Id) {
- return std::make_shared<StencilImpl<DebugPrintNodeData>>(std::string(Id));
+ return std::make_shared<DebugPrintNodeStencil>(std::string(Id));
}
Stencil transformer::expression(llvm::StringRef Id) {
- return std::make_shared<StencilImpl<UnaryOperationData>>(
- UnaryNodeOperator::Parens, std::string(Id));
+ return std::make_shared<UnaryOperationStencil>(UnaryNodeOperator::Parens,
+ std::string(Id));
}
Stencil transformer::deref(llvm::StringRef ExprId) {
- return std::make_shared<StencilImpl<UnaryOperationData>>(
- UnaryNodeOperator::Deref, std::string(ExprId));
+ return std::make_shared<UnaryOperationStencil>(UnaryNodeOperator::Deref,
+ std::string(ExprId));
}
Stencil transformer::maybeDeref(llvm::StringRef ExprId) {
- return std::make_shared<StencilImpl<UnaryOperationData>>(
- UnaryNodeOperator::MaybeDeref, std::string(ExprId));
+ return std::make_shared<UnaryOperationStencil>(UnaryNodeOperator::MaybeDeref,
+ std::string(ExprId));
}
Stencil transformer::addressOf(llvm::StringRef ExprId) {
- return std::make_shared<StencilImpl<UnaryOperationData>>(
- UnaryNodeOperator::AddressOf, std::string(ExprId));
+ return std::make_shared<UnaryOperationStencil>(UnaryNodeOperator::AddressOf,
+ std::string(ExprId));
}
Stencil transformer::maybeAddressOf(llvm::StringRef ExprId) {
- return std::make_shared<StencilImpl<UnaryOperationData>>(
+ return std::make_shared<UnaryOperationStencil>(
UnaryNodeOperator::MaybeAddressOf, std::string(ExprId));
}
Stencil transformer::describe(StringRef Id) {
- return std::make_shared<StencilImpl<UnaryOperationData>>(
- UnaryNodeOperator::Describe, std::string(Id));
+ return std::make_shared<UnaryOperationStencil>(UnaryNodeOperator::Describe,
+ std::string(Id));
}
Stencil transformer::access(StringRef BaseId, Stencil Member) {
- return std::make_shared<StencilImpl<AccessData>>(BaseId, std::move(Member));
+ return std::make_shared<AccessStencil>(BaseId, std::move(Member));
}
Stencil transformer::ifBound(StringRef Id, Stencil TrueStencil,
Stencil FalseStencil) {
- return std::make_shared<StencilImpl<IfBoundData>>(Id, std::move(TrueStencil),
- std::move(FalseStencil));
+ return std::make_shared<IfBoundStencil>(Id, std::move(TrueStencil),
+ std::move(FalseStencil));
}
Stencil transformer::run(MatchConsumer<std::string> Fn) {
- return std::make_shared<StencilImpl<MatchConsumer<std::string>>>(
- std::move(Fn));
+ return std::make_shared<RunStencil>(std::move(Fn));
}
Stencil transformer::catVector(std::vector<Stencil> Parts) {
// Only one argument, so don't wrap in sequence.
if (Parts.size() == 1)
return std::move(Parts[0]);
- return std::make_shared<StencilImpl<SequenceData>>(std::move(Parts));
+ return std::make_shared<SequenceStencil>(std::move(Parts));
}