Skip to content

Commit a31a1ef

Browse files
committed
[llvm][mustache] Introduce MustacheContext to simplify mustache APIs
1 parent 0b15e73 commit a31a1ef

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
@@ -139,26 +139,17 @@ class ASTNode {
139139
InvertSection,
140140
};
141141

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

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

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

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

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

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

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

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

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

234211
// Function to check if there is meaningful text behind.
@@ -545,39 +522,26 @@ class AddIndentationStringStream : public raw_ostream {
545522

546523
class Parser {
547524
public:
548-
Parser(StringRef TemplateStr) : TemplateStr(TemplateStr) {}
525+
Parser(StringRef TemplateStr, MustacheContext &Ctx)
526+
: Ctx(Ctx), TemplateStr(TemplateStr) {}
549527

550-
AstPtr parse(llvm::StringMap<AstPtr> &Partials,
551-
llvm::StringMap<Lambda> &Lambdas,
552-
llvm::StringMap<SectionLambda> &SectionLambdas,
553-
EscapeMap &Escapes);
528+
AstPtr parse();
554529

555530
private:
556-
void parseMustache(ASTNode *Parent, llvm::StringMap<AstPtr> &Partials,
557-
llvm::StringMap<Lambda> &Lambdas,
558-
llvm::StringMap<SectionLambda> &SectionLambdas,
559-
EscapeMap &Escapes);
560-
561-
void parseSection(ASTNode *Parent, ASTNode::Type Ty, const Accessor &A,
562-
llvm::StringMap<AstPtr> &Partials,
563-
llvm::StringMap<Lambda> &Lambdas,
564-
llvm::StringMap<SectionLambda> &SectionLambdas,
565-
EscapeMap &Escapes);
531+
void parseMustache(ASTNode *Parent);
532+
void parseSection(ASTNode *Parent, ASTNode::Type Ty, const Accessor &A);
566533

534+
MustacheContext &Ctx;
567535
SmallVector<Token> Tokens;
568536
size_t CurrentPtr;
569537
StringRef TemplateStr;
570538
};
571539

572-
void Parser::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) {
577-
AstPtr CurrentNode =
578-
createNode(Ty, A, Parent, Partials, Lambdas, SectionLambdas, Escapes);
540+
void Parser::parseSection(ASTNode *Parent, ASTNode::Type Ty,
541+
const Accessor &A) {
542+
AstPtr CurrentNode = createNode(Ctx, Ty, A, Parent);
579543
size_t Start = CurrentPtr;
580-
parseMustache(CurrentNode.get(), Partials, Lambdas, SectionLambdas, Escapes);
544+
parseMustache(CurrentNode.get());
581545
const size_t End = CurrentPtr - 1;
582546
std::string RawBody;
583547
for (std::size_t I = Start; I < End; I++)
@@ -586,21 +550,15 @@ void Parser::parseSection(ASTNode *Parent, ASTNode::Type Ty, const Accessor &A,
586550
Parent->addChild(std::move(CurrentNode));
587551
}
588552

589-
AstPtr Parser::parse(llvm::StringMap<AstPtr> &Partials,
590-
llvm::StringMap<Lambda> &Lambdas,
591-
llvm::StringMap<SectionLambda> &SectionLambdas,
592-
EscapeMap &Escapes) {
553+
AstPtr Parser::parse() {
593554
Tokens = tokenize(TemplateStr);
594555
CurrentPtr = 0;
595-
AstPtr RootNode = createRootNode(Partials, Lambdas, SectionLambdas, Escapes);
596-
parseMustache(RootNode.get(), Partials, Lambdas, SectionLambdas, Escapes);
556+
AstPtr RootNode = createRootNode(Ctx);
557+
parseMustache(RootNode.get());
597558
return RootNode;
598559
}
599560

600-
void Parser::parseMustache(ASTNode *Parent, llvm::StringMap<AstPtr> &Partials,
601-
llvm::StringMap<Lambda> &Lambdas,
602-
llvm::StringMap<SectionLambda> &SectionLambdas,
603-
EscapeMap &Escapes) {
561+
void Parser::parseMustache(ASTNode *Parent) {
604562

605563
while (CurrentPtr < Tokens.size()) {
606564
Token CurrentToken = Tokens[CurrentPtr];
@@ -610,38 +568,34 @@ void Parser::parseMustache(ASTNode *Parent, llvm::StringMap<AstPtr> &Partials,
610568

611569
switch (CurrentToken.getType()) {
612570
case Token::Type::Text: {
613-
CurrentNode = createTextNode(std::move(CurrentToken.TokenBody), Parent,
614-
Partials, Lambdas, SectionLambdas, Escapes);
571+
CurrentNode =
572+
createTextNode(Ctx, std::move(CurrentToken.TokenBody), Parent);
615573
Parent->addChild(std::move(CurrentNode));
616574
break;
617575
}
618576
case Token::Type::Variable: {
619-
CurrentNode = createNode(ASTNode::Variable, std::move(A), Parent,
620-
Partials, Lambdas, SectionLambdas, Escapes);
577+
CurrentNode = createNode(Ctx, ASTNode::Variable, std::move(A), Parent);
621578
Parent->addChild(std::move(CurrentNode));
622579
break;
623580
}
624581
case Token::Type::UnescapeVariable: {
625-
CurrentNode = createNode(ASTNode::UnescapeVariable, std::move(A), Parent,
626-
Partials, Lambdas, SectionLambdas, Escapes);
582+
CurrentNode =
583+
createNode(Ctx, ASTNode::UnescapeVariable, std::move(A), Parent);
627584
Parent->addChild(std::move(CurrentNode));
628585
break;
629586
}
630587
case Token::Type::Partial: {
631-
CurrentNode = createNode(ASTNode::Partial, std::move(A), Parent, Partials,
632-
Lambdas, SectionLambdas, Escapes);
588+
CurrentNode = createNode(Ctx, ASTNode::Partial, std::move(A), Parent);
633589
CurrentNode->setIndentation(CurrentToken.getIndentation());
634590
Parent->addChild(std::move(CurrentNode));
635591
break;
636592
}
637593
case Token::Type::SectionOpen: {
638-
parseSection(Parent, ASTNode::Section, A, Partials, Lambdas,
639-
SectionLambdas, Escapes);
594+
parseSection(Parent, ASTNode::Section, A);
640595
break;
641596
}
642597
case Token::Type::InvertSectionOpen: {
643-
parseSection(Parent, ASTNode::InvertSection, A, Partials, Lambdas,
644-
SectionLambdas, Escapes);
598+
parseSection(Parent, ASTNode::InvertSection, A);
645599
break;
646600
}
647601
case Token::Type::Comment:
@@ -691,34 +645,34 @@ void ASTNode::renderRoot(const json::Value &CurrentCtx, raw_ostream &OS) {
691645
void ASTNode::renderText(raw_ostream &OS) { OS << Body; }
692646

693647
void ASTNode::renderPartial(const json::Value &CurrentCtx, raw_ostream &OS) {
694-
auto Partial = Partials.find(AccessorValue[0]);
695-
if (Partial != Partials.end())
648+
auto Partial = Ctx.Partials.find(AccessorValue[0]);
649+
if (Partial != Ctx.Partials.end())
696650
renderPartial(CurrentCtx, OS, Partial->getValue().get());
697651
}
698652

699653
void ASTNode::renderVariable(const json::Value &CurrentCtx, raw_ostream &OS) {
700-
auto Lambda = Lambdas.find(AccessorValue[0]);
701-
if (Lambda != Lambdas.end()) {
654+
auto Lambda = Ctx.Lambdas.find(AccessorValue[0]);
655+
if (Lambda != Ctx.Lambdas.end()) {
702656
renderLambdas(CurrentCtx, OS, Lambda->getValue());
703657
} else if (const json::Value *ContextPtr = findContext()) {
704-
EscapeStringStream ES(OS, Escapes);
658+
EscapeStringStream ES(OS, Ctx.Escapes);
705659
toMustacheString(*ContextPtr, ES);
706660
}
707661
}
708662

709663
void ASTNode::renderUnescapeVariable(const json::Value &CurrentCtx,
710664
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()) {
715669
toMustacheString(*ContextPtr, OS);
716670
}
717671
}
718672

719673
void ASTNode::renderSection(const json::Value &CurrentCtx, raw_ostream &OS) {
720-
auto SectionLambda = SectionLambdas.find(AccessorValue[0]);
721-
if (SectionLambda != SectionLambdas.end()) {
674+
auto SectionLambda = Ctx.SectionLambdas.find(AccessorValue[0]);
675+
if (SectionLambda != Ctx.SectionLambdas.end()) {
722676
renderSectionLambdas(CurrentCtx, OS, SectionLambda->getValue());
723677
return;
724678
}
@@ -737,7 +691,7 @@ void ASTNode::renderSection(const json::Value &CurrentCtx, raw_ostream &OS) {
737691

738692
void ASTNode::renderInvertSection(const json::Value &CurrentCtx,
739693
raw_ostream &OS) {
740-
bool IsLambda = SectionLambdas.contains(AccessorValue[0]);
694+
bool IsLambda = Ctx.SectionLambdas.contains(AccessorValue[0]);
741695
const json::Value *ContextPtr = findContext();
742696
if (isContextFalsey(ContextPtr) && !IsLambda) {
743697
renderChild(CurrentCtx, OS);
@@ -833,10 +787,10 @@ void ASTNode::renderLambdas(const json::Value &Contexts, llvm::raw_ostream &OS,
833787
std::string LambdaStr;
834788
raw_string_ostream Output(LambdaStr);
835789
toMustacheString(LambdaResult, Output);
836-
Parser P = Parser(LambdaStr);
837-
AstPtr LambdaNode = P.parse(Partials, Lambdas, SectionLambdas, Escapes);
790+
Parser P(LambdaStr, Ctx);
791+
AstPtr LambdaNode = P.parse();
838792

839-
EscapeStringStream ES(OS, Escapes);
793+
EscapeStringStream ES(OS, Ctx.Escapes);
840794
if (Ty == Variable) {
841795
LambdaNode->render(Contexts, ES);
842796
return;
@@ -852,8 +806,8 @@ void ASTNode::renderSectionLambdas(const json::Value &Contexts,
852806
std::string LambdaStr;
853807
raw_string_ostream Output(LambdaStr);
854808
toMustacheString(Return, Output);
855-
Parser P = Parser(LambdaStr);
856-
AstPtr LambdaNode = P.parse(Partials, Lambdas, SectionLambdas, Escapes);
809+
Parser P(LambdaStr, Ctx);
810+
AstPtr LambdaNode = P.parse();
857811
LambdaNode->render(Contexts, OS);
858812
}
859813

@@ -862,22 +816,26 @@ void Template::render(const json::Value &Data, llvm::raw_ostream &OS) {
862816
}
863817

864818
void Template::registerPartial(std::string Name, std::string Partial) {
865-
Parser P = Parser(Partial);
866-
AstPtr PartialTree = P.parse(Partials, Lambdas, SectionLambdas, Escapes);
867-
Partials.insert(std::make_pair(Name, std::move(PartialTree)));
819+
Parser P(Partial, Ctx);
820+
AstPtr PartialTree = P.parse();
821+
Ctx.Partials.insert(std::make_pair(Name, std::move(PartialTree)));
868822
}
869823

870-
void Template::registerLambda(std::string Name, Lambda L) { Lambdas[Name] = L; }
824+
void Template::registerLambda(std::string Name, Lambda L) {
825+
Ctx.Lambdas[Name] = L;
826+
}
871827

872828
void Template::registerLambda(std::string Name, SectionLambda L) {
873-
SectionLambdas[Name] = L;
829+
Ctx.SectionLambdas[Name] = L;
874830
}
875831

876-
void Template::overrideEscapeCharacters(EscapeMap E) { Escapes = std::move(E); }
832+
void Template::overrideEscapeCharacters(EscapeMap E) {
833+
Ctx.Escapes = std::move(E);
834+
}
877835

878836
Template::Template(StringRef TemplateStr) {
879-
Parser P = Parser(TemplateStr);
880-
Tree = P.parse(Partials, Lambdas, SectionLambdas, Escapes);
837+
Parser P(TemplateStr, Ctx);
838+
Tree = P.parse();
881839
// The default behavior is to escape html entities.
882840
const EscapeMap HtmlEntities = {{'&', "&amp;"},
883841
{'<', "&lt;"},
@@ -888,18 +846,13 @@ Template::Template(StringRef TemplateStr) {
888846
}
889847

890848
Template::Template(Template &&Other) noexcept
891-
: Partials(std::move(Other.Partials)), Lambdas(std::move(Other.Lambdas)),
892-
SectionLambdas(std::move(Other.SectionLambdas)),
893-
Escapes(std::move(Other.Escapes)), Tree(std::move(Other.Tree)) {}
849+
: Ctx(std::move(Other.Ctx)), Tree(std::move(Other.Tree)) {}
894850

895851
Template::~Template() = default;
896852

897853
Template &Template::operator=(Template &&Other) noexcept {
898854
if (this != &Other) {
899-
Partials = std::move(Other.Partials);
900-
Lambdas = std::move(Other.Lambdas);
901-
SectionLambdas = std::move(Other.SectionLambdas);
902-
Escapes = std::move(Other.Escapes);
855+
Ctx = std::move(Other.Ctx);
903856
Tree = std::move(Other.Tree);
904857
Other.Tree = nullptr;
905858
}

0 commit comments

Comments
 (0)