/
StringTemplating.sv
204 lines (173 loc) · 6.4 KB
/
StringTemplating.sv
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
grammar silver:compiler:extension:templating;
imports silver:compiler:definition:core;
imports silver:compiler:definition:env;
imports silver:compiler:definition:type;
imports silver:compiler:definition:type:syntax;
imports silver:compiler:metatranslation;
imports silver:reflect;
imports silver:langutil:pp;
imports silver:langutil:lsp as lsp;
imports silver:compiler:translation:java:core;
exports silver:compiler:extension:templating:syntax;
import silver:util:treeset as ts;
terminal Template_kwd 's"""' lexer classes {LITERAL, lsp:String_};
terminal SLTemplate_kwd 's"' lexer classes {LITERAL, lsp:String_};
concrete production templateExpr
top::Expr ::= Template_kwd t::TemplateString
layout {}
{
forwards to foldr1(stringAppendCall(_, _), t.stringTemplate);
}
concrete production singleLineTemplateExpr
top::Expr ::= SLTemplate_kwd t::SingleLineTemplateString
layout {}
{
forwards to foldr1(stringAppendCall(_, _), t.stringTemplate);
}
production stringAppendCall
top::Expr ::= a::Expr b::Expr
{
top.unparse = s"${a.unparse} ++ ${b.unparse}";
-- TODO: We really need strictness analysis in Silver.
-- Otherwise the translation for a large string template block contains
-- new common.Thunk<Object>(new common.Thunk.Evaluable() { public final Object eval() { return ((common.StringCatter)silver.core.PstringAppend.invoke(${a.translation}, ${b.translation}); } })
-- a ridiculous number of times, when it can just be translated as:
top.translation = s"new common.StringCatter(${a.translation}, ${b.translation})";
top.lazyTranslation = wrapThunk(top.translation, top.frame.lazyApplication);
forwards to application(
baseExpr(
qName("silver:core:stringAppend")), '(',
snocAppExprs(
snocAppExprs(
emptyAppExprs(), ',',
presentAppExpr(@a)), ',',
presentAppExpr(@b)),
',',
emptyAnnoAppExprs(),
')');
}
terminal PPTemplate_kwd 'pp"""' lexer classes {LITERAL, lsp:String_};
terminal SLPPTemplate_kwd 'pp"' lexer classes {LITERAL, lsp:String_};
-- These are translated by building a Document value and meta-translating the whole thing into an Expr
concrete production pptemplateExpr
top::Expr ::= PPTemplate_kwd t::TemplateString
layout {}
{
forwards to translate(reflect(t.ppTemplate));
}
concrete production singleLinepptemplateExpr
top::Expr ::= SLPPTemplate_kwd t::SingleLineTemplateString
layout {}
{
forwards to translate(reflect(t.ppTemplate));
}
-- Antiquote production used in translating nonwater Exprs that should get directly embedded in the result.
-- See fig 9 of https://doi.org/10.1016/j.cola.2021.101033 (https://www-users.cse.umn.edu/~evw/pubs/kramer21cola/kramer21cola.pdf)
production antiquoteDoc
top::Document ::= e::Expr
{ forwards to error("No forward"); }
aspect production nonterminalAST
top::AST ::= _ _ _
{
directAntiquoteProductions <- ["silver:compiler:extension:templating:antiquoteDoc"];
}
synthesized attribute stringTemplate :: [Expr] occurs on TemplateString, SingleLineTemplateString,
TemplateStringBody, SingleLineTemplateStringBody,
TemplateStringBodyItem, SingleLineTemplateStringBodyItem, NonWater;
synthesized attribute ppTemplate :: Document occurs on TemplateString, SingleLineTemplateString,
TemplateStringBody, SingleLineTemplateStringBody,
TemplateStringBodyItem, SingleLineTemplateStringBodyItem, NonWater;
aspect production templateString
top::TemplateString ::= b::TemplateStringBody _
{
top.stringTemplate = b.stringTemplate;
top.ppTemplate = b.ppTemplate;
}
aspect production templateStringEmpty
top::TemplateString ::= _
{
top.stringTemplate = [Silver_Expr { "" }];
top.ppTemplate = notext();
}
aspect production singleLineTemplateString
top::SingleLineTemplateString ::= b::SingleLineTemplateStringBody _
{
top.stringTemplate = b.stringTemplate;
top.ppTemplate = b.ppTemplate;
}
aspect production singleLineTemplateStringEmpty
top::SingleLineTemplateString ::= _
{
top.stringTemplate = [Silver_Expr { "" }];
top.ppTemplate = notext();
}
aspect production bodyCons
top::TemplateStringBody ::= h::TemplateStringBodyItem t::TemplateStringBody
{
top.stringTemplate = h.stringTemplate ++ t.stringTemplate;
top.ppTemplate = cat(h.ppTemplate, t.ppTemplate);
}
aspect production bodyOne
top::TemplateStringBody ::= h::TemplateStringBodyItem
{
top.stringTemplate = h.stringTemplate;
top.ppTemplate = h.ppTemplate;
}
aspect production bodyOneWater
top::TemplateStringBody ::= w::Water
{
top.stringTemplate = [stringConst(terminal(String_t, "\"" ++ w.waterString ++ "\""))];
top.ppTemplate = w.waterDoc;
}
aspect production singleLineBodyCons
top::SingleLineTemplateStringBody ::= h::SingleLineTemplateStringBodyItem t::SingleLineTemplateStringBody
{
top.stringTemplate = h.stringTemplate ++ t.stringTemplate;
top.ppTemplate = cat(h.ppTemplate, t.ppTemplate);
}
aspect production singleLineBodyOne
top::SingleLineTemplateStringBody ::= h::SingleLineTemplateStringBodyItem
{
top.stringTemplate = h.stringTemplate;
top.ppTemplate = h.ppTemplate;
}
aspect production singleLineBodyOneWater
top::SingleLineTemplateStringBody ::= w::SingleLineWater
{
top.stringTemplate = [stringConst(terminal(String_t, "\"" ++ w.waterString ++ "\""))];
top.ppTemplate = w.waterDoc;
}
aspect production itemWaterEscape
top::TemplateStringBodyItem ::= w::Water nw::NonWater
{
top.stringTemplate = [
stringConst(terminal(String_t, "\"" ++ w.waterString ++ "\""))] ++
nw.stringTemplate;
top.ppTemplate = cat(w.waterDoc, nw.ppTemplate);
}
aspect production itemEscape
top::TemplateStringBodyItem ::= nw::NonWater
{
top.stringTemplate = nw.stringTemplate;
top.ppTemplate = nw.ppTemplate;
}
aspect production singleLineItemWaterEscape
top::SingleLineTemplateStringBodyItem ::= w::SingleLineWater nw::NonWater
{
top.stringTemplate = [
stringConst(terminal(String_t, "\"" ++ w.waterString ++ "\""))] ++
nw.stringTemplate;
top.ppTemplate = cat(w.waterDoc, nw.ppTemplate);
}
aspect production singleLineItemEscape
top::SingleLineTemplateStringBodyItem ::= nw::NonWater
{
top.stringTemplate = nw.stringTemplate;
top.ppTemplate = nw.ppTemplate;
}
aspect production nonwater
top::NonWater ::= '${' e::Expr '}'
{
top.stringTemplate = [e];
top.ppTemplate = antiquoteDoc(mkStrFunctionInvocation("silver:langutil:pp:pp", [e]));
}