Skip to content

Commit aa42b64

Browse files
authored
[llvm][mustache] Introduce MustacheContext to simplify mustache APIs (#159191)
1 parent 3554c78 commit aa42b64

File tree

2 files changed

+76
-118
lines changed

2 files changed

+76
-118
lines changed

llvm/include/llvm/Support/Mustache.h

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,14 @@ using SectionLambda = std::function<llvm::json::Value(std::string)>;
8585

8686
class ASTNode;
8787
using AstPtr = std::unique_ptr<ASTNode>;
88+
using EscapeMap = DenseMap<char, std::string>;
89+
90+
struct MustacheContext {
91+
StringMap<AstPtr> Partials;
92+
StringMap<Lambda> Lambdas;
93+
StringMap<SectionLambda> SectionLambdas;
94+
EscapeMap Escapes;
95+
};
8896

8997
// A Template represents the container for the AST and the partials
9098
// and Lambdas that are registered with it.
@@ -118,10 +126,7 @@ class Template {
118126
LLVM_ABI void overrideEscapeCharacters(DenseMap<char, std::string> Escapes);
119127

120128
private:
121-
StringMap<AstPtr> Partials;
122-
StringMap<Lambda> Lambdas;
123-
StringMap<SectionLambda> SectionLambdas;
124-
DenseMap<char, std::string> Escapes;
129+
MustacheContext Ctx;
125130
AstPtr Tree;
126131
};
127132
} // namespace llvm::mustache

llvm/lib/Support/Mustache.cpp

Lines changed: 67 additions & 114 deletions
Original file line numberDiff line numberDiff line change
@@ -138,26 +138,17 @@ class ASTNode {
138138
InvertSection,
139139
};
140140

141-
ASTNode(llvm::StringMap<AstPtr> &Partials, llvm::StringMap<Lambda> &Lambdas,
142-
llvm::StringMap<SectionLambda> &SectionLambdas, EscapeMap &Escapes)
143-
: Partials(Partials), Lambdas(Lambdas), SectionLambdas(SectionLambdas),
144-
Escapes(Escapes), Ty(Type::Root), Parent(nullptr),
145-
ParentContext(nullptr) {}
141+
ASTNode(MustacheContext &Ctx)
142+
: Ctx(Ctx), Ty(Type::Root), Parent(nullptr), ParentContext(nullptr) {}
146143

147-
ASTNode(std::string Body, ASTNode *Parent, llvm::StringMap<AstPtr> &Partials,
148-
llvm::StringMap<Lambda> &Lambdas,
149-
llvm::StringMap<SectionLambda> &SectionLambdas, EscapeMap &Escapes)
150-
: Partials(Partials), Lambdas(Lambdas), SectionLambdas(SectionLambdas),
151-
Escapes(Escapes), Ty(Type::Text), Body(std::move(Body)), Parent(Parent),
144+
ASTNode(MustacheContext &Ctx, std::string Body, ASTNode *Parent)
145+
: Ctx(Ctx), Ty(Type::Text), Body(std::move(Body)), Parent(Parent),
152146
ParentContext(nullptr) {}
153147

154148
// Constructor for Section/InvertSection/Variable/UnescapeVariable Nodes
155-
ASTNode(Type Ty, Accessor Accessor, ASTNode *Parent,
156-
llvm::StringMap<AstPtr> &Partials, llvm::StringMap<Lambda> &Lambdas,
157-
llvm::StringMap<SectionLambda> &SectionLambdas, EscapeMap &Escapes)
158-
: Partials(Partials), Lambdas(Lambdas), SectionLambdas(SectionLambdas),
159-
Escapes(Escapes), Ty(Ty), Parent(Parent),
160-
AccessorValue(std::move(Accessor)), ParentContext(nullptr) {}
149+
ASTNode(MustacheContext &Ctx, Type Ty, Accessor Accessor, ASTNode *Parent)
150+
: Ctx(Ctx), Ty(Ty), Parent(Parent), AccessorValue(std::move(Accessor)),
151+
ParentContext(nullptr) {}
161152

162153
void addChild(AstPtr Child) { Children.emplace_back(std::move(Child)); };
163154

@@ -189,10 +180,7 @@ class ASTNode {
189180
void renderSection(const json::Value &CurrentCtx, raw_ostream &OS);
190181
void renderInvertSection(const json::Value &CurrentCtx, raw_ostream &OS);
191182

192-
StringMap<AstPtr> &Partials;
193-
StringMap<Lambda> &Lambdas;
194-
StringMap<SectionLambda> &SectionLambdas;
195-
EscapeMap &Escapes;
183+
MustacheContext &Ctx;
196184
Type Ty;
197185
size_t Indentation = 0;
198186
std::string RawBody;
@@ -205,29 +193,18 @@ class ASTNode {
205193
};
206194

207195
// A wrapper for arena allocator for ASTNodes
208-
static AstPtr createRootNode(llvm::StringMap<AstPtr> &Partials,
209-
llvm::StringMap<Lambda> &Lambdas,
210-
llvm::StringMap<SectionLambda> &SectionLambdas,
211-
EscapeMap &Escapes) {
212-
return std::make_unique<ASTNode>(Partials, Lambdas, SectionLambdas, Escapes);
196+
static AstPtr createRootNode(MustacheContext &Ctx) {
197+
return std::make_unique<ASTNode>(Ctx);
213198
}
214199

215-
static AstPtr createNode(ASTNode::Type T, Accessor A, ASTNode *Parent,
216-
llvm::StringMap<AstPtr> &Partials,
217-
llvm::StringMap<Lambda> &Lambdas,
218-
llvm::StringMap<SectionLambda> &SectionLambdas,
219-
EscapeMap &Escapes) {
220-
return std::make_unique<ASTNode>(T, std::move(A), Parent, Partials, Lambdas,
221-
SectionLambdas, Escapes);
200+
static AstPtr createNode(MustacheContext &Ctx, ASTNode::Type T, Accessor A,
201+
ASTNode *Parent) {
202+
return std::make_unique<ASTNode>(Ctx, T, std::move(A), Parent);
222203
}
223204

224-
static AstPtr createTextNode(std::string Body, ASTNode *Parent,
225-
llvm::StringMap<AstPtr> &Partials,
226-
llvm::StringMap<Lambda> &Lambdas,
227-
llvm::StringMap<SectionLambda> &SectionLambdas,
228-
EscapeMap &Escapes) {
229-
return std::make_unique<ASTNode>(std::move(Body), Parent, Partials, Lambdas,
230-
SectionLambdas, Escapes);
205+
static AstPtr createTextNode(MustacheContext &Ctx, std::string Body,
206+
ASTNode *Parent) {
207+
return std::make_unique<ASTNode>(Ctx, std::move(Body), Parent);
231208
}
232209

233210
// Function to check if there is meaningful text behind.
@@ -556,39 +533,26 @@ class AddIndentationStringStream : public raw_ostream {
556533

557534
class Parser {
558535
public:
559-
Parser(StringRef TemplateStr) : TemplateStr(TemplateStr) {}
536+
Parser(StringRef TemplateStr, MustacheContext &Ctx)
537+
: Ctx(Ctx), TemplateStr(TemplateStr) {}
560538

561-
AstPtr parse(llvm::StringMap<AstPtr> &Partials,
562-
llvm::StringMap<Lambda> &Lambdas,
563-
llvm::StringMap<SectionLambda> &SectionLambdas,
564-
EscapeMap &Escapes);
539+
AstPtr parse();
565540

566541
private:
567-
void parseMustache(ASTNode *Parent, llvm::StringMap<AstPtr> &Partials,
568-
llvm::StringMap<Lambda> &Lambdas,
569-
llvm::StringMap<SectionLambda> &SectionLambdas,
570-
EscapeMap &Escapes);
571-
572-
void parseSection(ASTNode *Parent, ASTNode::Type Ty, const Accessor &A,
573-
llvm::StringMap<AstPtr> &Partials,
574-
llvm::StringMap<Lambda> &Lambdas,
575-
llvm::StringMap<SectionLambda> &SectionLambdas,
576-
EscapeMap &Escapes);
542+
void parseMustache(ASTNode *Parent);
543+
void parseSection(ASTNode *Parent, ASTNode::Type Ty, const Accessor &A);
577544

545+
MustacheContext &Ctx;
578546
SmallVector<Token> Tokens;
579547
size_t CurrentPtr;
580548
StringRef TemplateStr;
581549
};
582550

583-
void Parser::parseSection(ASTNode *Parent, ASTNode::Type Ty, const Accessor &A,
584-
llvm::StringMap<AstPtr> &Partials,
585-
llvm::StringMap<Lambda> &Lambdas,
586-
llvm::StringMap<SectionLambda> &SectionLambdas,
587-
EscapeMap &Escapes) {
588-
AstPtr CurrentNode =
589-
createNode(Ty, A, Parent, Partials, Lambdas, SectionLambdas, Escapes);
551+
void Parser::parseSection(ASTNode *Parent, ASTNode::Type Ty,
552+
const Accessor &A) {
553+
AstPtr CurrentNode = createNode(Ctx, Ty, A, Parent);
590554
size_t Start = CurrentPtr;
591-
parseMustache(CurrentNode.get(), Partials, Lambdas, SectionLambdas, Escapes);
555+
parseMustache(CurrentNode.get());
592556
const size_t End = CurrentPtr - 1;
593557
std::string RawBody;
594558
for (std::size_t I = Start; I < End; I++)
@@ -597,21 +561,15 @@ void Parser::parseSection(ASTNode *Parent, ASTNode::Type Ty, const Accessor &A,
597561
Parent->addChild(std::move(CurrentNode));
598562
}
599563

600-
AstPtr Parser::parse(llvm::StringMap<AstPtr> &Partials,
601-
llvm::StringMap<Lambda> &Lambdas,
602-
llvm::StringMap<SectionLambda> &SectionLambdas,
603-
EscapeMap &Escapes) {
564+
AstPtr Parser::parse() {
604565
Tokens = tokenize(TemplateStr);
605566
CurrentPtr = 0;
606-
AstPtr RootNode = createRootNode(Partials, Lambdas, SectionLambdas, Escapes);
607-
parseMustache(RootNode.get(), Partials, Lambdas, SectionLambdas, Escapes);
567+
AstPtr RootNode = createRootNode(Ctx);
568+
parseMustache(RootNode.get());
608569
return RootNode;
609570
}
610571

611-
void Parser::parseMustache(ASTNode *Parent, llvm::StringMap<AstPtr> &Partials,
612-
llvm::StringMap<Lambda> &Lambdas,
613-
llvm::StringMap<SectionLambda> &SectionLambdas,
614-
EscapeMap &Escapes) {
572+
void Parser::parseMustache(ASTNode *Parent) {
615573

616574
while (CurrentPtr < Tokens.size()) {
617575
Token CurrentToken = Tokens[CurrentPtr];
@@ -621,38 +579,34 @@ void Parser::parseMustache(ASTNode *Parent, llvm::StringMap<AstPtr> &Partials,
621579

622580
switch (CurrentToken.getType()) {
623581
case Token::Type::Text: {
624-
CurrentNode = createTextNode(std::move(CurrentToken.TokenBody), Parent,
625-
Partials, Lambdas, SectionLambdas, Escapes);
582+
CurrentNode =
583+
createTextNode(Ctx, std::move(CurrentToken.TokenBody), Parent);
626584
Parent->addChild(std::move(CurrentNode));
627585
break;
628586
}
629587
case Token::Type::Variable: {
630-
CurrentNode = createNode(ASTNode::Variable, std::move(A), Parent,
631-
Partials, Lambdas, SectionLambdas, Escapes);
588+
CurrentNode = createNode(Ctx, ASTNode::Variable, std::move(A), Parent);
632589
Parent->addChild(std::move(CurrentNode));
633590
break;
634591
}
635592
case Token::Type::UnescapeVariable: {
636-
CurrentNode = createNode(ASTNode::UnescapeVariable, std::move(A), Parent,
637-
Partials, Lambdas, SectionLambdas, Escapes);
593+
CurrentNode =
594+
createNode(Ctx, ASTNode::UnescapeVariable, std::move(A), Parent);
638595
Parent->addChild(std::move(CurrentNode));
639596
break;
640597
}
641598
case Token::Type::Partial: {
642-
CurrentNode = createNode(ASTNode::Partial, std::move(A), Parent, Partials,
643-
Lambdas, SectionLambdas, Escapes);
599+
CurrentNode = createNode(Ctx, ASTNode::Partial, std::move(A), Parent);
644600
CurrentNode->setIndentation(CurrentToken.getIndentation());
645601
Parent->addChild(std::move(CurrentNode));
646602
break;
647603
}
648604
case Token::Type::SectionOpen: {
649-
parseSection(Parent, ASTNode::Section, A, Partials, Lambdas,
650-
SectionLambdas, Escapes);
605+
parseSection(Parent, ASTNode::Section, A);
651606
break;
652607
}
653608
case Token::Type::InvertSectionOpen: {
654-
parseSection(Parent, ASTNode::InvertSection, A, Partials, Lambdas,
655-
SectionLambdas, Escapes);
609+
parseSection(Parent, ASTNode::InvertSection, A);
656610
break;
657611
}
658612
case Token::Type::Comment:
@@ -702,34 +656,34 @@ void ASTNode::renderRoot(const json::Value &CurrentCtx, raw_ostream &OS) {
702656
void ASTNode::renderText(raw_ostream &OS) { OS << Body; }
703657

704658
void ASTNode::renderPartial(const json::Value &CurrentCtx, raw_ostream &OS) {
705-
auto Partial = Partials.find(AccessorValue[0]);
706-
if (Partial != Partials.end())
659+
auto Partial = Ctx.Partials.find(AccessorValue[0]);
660+
if (Partial != Ctx.Partials.end())
707661
renderPartial(CurrentCtx, OS, Partial->getValue().get());
708662
}
709663

710664
void ASTNode::renderVariable(const json::Value &CurrentCtx, raw_ostream &OS) {
711-
auto Lambda = Lambdas.find(AccessorValue[0]);
712-
if (Lambda != Lambdas.end()) {
665+
auto Lambda = Ctx.Lambdas.find(AccessorValue[0]);
666+
if (Lambda != Ctx.Lambdas.end()) {
713667
renderLambdas(CurrentCtx, OS, Lambda->getValue());
714668
} else if (const json::Value *ContextPtr = findContext()) {
715-
EscapeStringStream ES(OS, Escapes);
669+
EscapeStringStream ES(OS, Ctx.Escapes);
716670
toMustacheString(*ContextPtr, ES);
717671
}
718672
}
719673

720674
void ASTNode::renderUnescapeVariable(const json::Value &CurrentCtx,
721675
raw_ostream &OS) {
722-
auto Lambda = Lambdas.find(AccessorValue[0]);
723-
if (Lambda != Lambdas.end()) {
676+
auto Lambda = Ctx.Lambdas.find(AccessorValue[0]);
677+
if (Lambda != Ctx.Lambdas.end()) {
724678
renderLambdas(CurrentCtx, OS, Lambda->getValue());
725679
} else if (const json::Value *ContextPtr = findContext()) {
726680
toMustacheString(*ContextPtr, OS);
727681
}
728682
}
729683

730684
void ASTNode::renderSection(const json::Value &CurrentCtx, raw_ostream &OS) {
731-
auto SectionLambda = SectionLambdas.find(AccessorValue[0]);
732-
if (SectionLambda != SectionLambdas.end()) {
685+
auto SectionLambda = Ctx.SectionLambdas.find(AccessorValue[0]);
686+
if (SectionLambda != Ctx.SectionLambdas.end()) {
733687
renderSectionLambdas(CurrentCtx, OS, SectionLambda->getValue());
734688
return;
735689
}
@@ -748,7 +702,7 @@ void ASTNode::renderSection(const json::Value &CurrentCtx, raw_ostream &OS) {
748702

749703
void ASTNode::renderInvertSection(const json::Value &CurrentCtx,
750704
raw_ostream &OS) {
751-
bool IsLambda = SectionLambdas.contains(AccessorValue[0]);
705+
bool IsLambda = Ctx.SectionLambdas.contains(AccessorValue[0]);
752706
const json::Value *ContextPtr = findContext();
753707
if (isContextFalsey(ContextPtr) && !IsLambda) {
754708
renderChild(CurrentCtx, OS);
@@ -844,10 +798,10 @@ void ASTNode::renderLambdas(const json::Value &Contexts, llvm::raw_ostream &OS,
844798
std::string LambdaStr;
845799
raw_string_ostream Output(LambdaStr);
846800
toMustacheString(LambdaResult, Output);
847-
Parser P = Parser(LambdaStr);
848-
AstPtr LambdaNode = P.parse(Partials, Lambdas, SectionLambdas, Escapes);
801+
Parser P(LambdaStr, Ctx);
802+
AstPtr LambdaNode = P.parse();
849803

850-
EscapeStringStream ES(OS, Escapes);
804+
EscapeStringStream ES(OS, Ctx.Escapes);
851805
if (Ty == Variable) {
852806
LambdaNode->render(Contexts, ES);
853807
return;
@@ -863,8 +817,8 @@ void ASTNode::renderSectionLambdas(const json::Value &Contexts,
863817
std::string LambdaStr;
864818
raw_string_ostream Output(LambdaStr);
865819
toMustacheString(Return, Output);
866-
Parser P = Parser(LambdaStr);
867-
AstPtr LambdaNode = P.parse(Partials, Lambdas, SectionLambdas, Escapes);
820+
Parser P(LambdaStr, Ctx);
821+
AstPtr LambdaNode = P.parse();
868822
LambdaNode->render(Contexts, OS);
869823
}
870824

@@ -873,22 +827,26 @@ void Template::render(const json::Value &Data, llvm::raw_ostream &OS) {
873827
}
874828

875829
void Template::registerPartial(std::string Name, std::string Partial) {
876-
Parser P = Parser(Partial);
877-
AstPtr PartialTree = P.parse(Partials, Lambdas, SectionLambdas, Escapes);
878-
Partials.insert(std::make_pair(Name, std::move(PartialTree)));
830+
Parser P(Partial, Ctx);
831+
AstPtr PartialTree = P.parse();
832+
Ctx.Partials.insert(std::make_pair(Name, std::move(PartialTree)));
879833
}
880834

881-
void Template::registerLambda(std::string Name, Lambda L) { Lambdas[Name] = L; }
835+
void Template::registerLambda(std::string Name, Lambda L) {
836+
Ctx.Lambdas[Name] = L;
837+
}
882838

883839
void Template::registerLambda(std::string Name, SectionLambda L) {
884-
SectionLambdas[Name] = L;
840+
Ctx.SectionLambdas[Name] = L;
885841
}
886842

887-
void Template::overrideEscapeCharacters(EscapeMap E) { Escapes = std::move(E); }
843+
void Template::overrideEscapeCharacters(EscapeMap E) {
844+
Ctx.Escapes = std::move(E);
845+
}
888846

889847
Template::Template(StringRef TemplateStr) {
890-
Parser P = Parser(TemplateStr);
891-
Tree = P.parse(Partials, Lambdas, SectionLambdas, Escapes);
848+
Parser P(TemplateStr, Ctx);
849+
Tree = P.parse();
892850
// The default behavior is to escape html entities.
893851
const EscapeMap HtmlEntities = {{'&', "&amp;"},
894852
{'<', "&lt;"},
@@ -899,18 +857,13 @@ Template::Template(StringRef TemplateStr) {
899857
}
900858

901859
Template::Template(Template &&Other) noexcept
902-
: Partials(std::move(Other.Partials)), Lambdas(std::move(Other.Lambdas)),
903-
SectionLambdas(std::move(Other.SectionLambdas)),
904-
Escapes(std::move(Other.Escapes)), Tree(std::move(Other.Tree)) {}
860+
: Ctx(std::move(Other.Ctx)), Tree(std::move(Other.Tree)) {}
905861

906862
Template::~Template() = default;
907863

908864
Template &Template::operator=(Template &&Other) noexcept {
909865
if (this != &Other) {
910-
Partials = std::move(Other.Partials);
911-
Lambdas = std::move(Other.Lambdas);
912-
SectionLambdas = std::move(Other.SectionLambdas);
913-
Escapes = std::move(Other.Escapes);
866+
Ctx = std::move(Other.Ctx);
914867
Tree = std::move(Other.Tree);
915868
Other.Tree = nullptr;
916869
}

0 commit comments

Comments
 (0)