Skip to content

Commit 3bddc92

Browse files
authored
Merge pull request #8 from alerque/type-operators
2 parents 6a860ca + 31f6590 commit 3bddc92

File tree

3 files changed

+97
-44
lines changed

3 files changed

+97
-44
lines changed

.editorconfig

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
root = true
2+
3+
[*]
4+
end_of_line = lf
5+
insert_final_newline = true
6+
7+
[{*.lua,*.rockspec}]
8+
indent_style = space
9+
indent_size = 2
10+
11+
[*.ftl]
12+
indent_style = space
13+
indent_size = 4
14+
15+
[*.json]
16+
indent_style = space
17+
indent_size = 2

fluent/init.lua

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,9 @@ local FluentBundle = class({
1616

1717
add_messages = function (self, input)
1818
if type(input) == "string" then input = { input } end
19-
-- TODO: add way to add two resources together, then reduce instead of unpacking this
20-
local resource = tablex.imap(function (v) return self.syntax:parsestring(v) end, input)
21-
self.locales[self.locale] = resource[1]
19+
local resources = tablex.imap(function (v) return self.syntax:parsestring(v) end, input)
20+
local resource = tablex.reduce('+', resources)
21+
self.locales[self.locale] = resource
2222
end,
2323

2424
format = function (self, identifier, parameters)

fluent/resource.lua

Lines changed: 77 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,12 @@ local class = require("pl.class")
33
local tablex = require("pl.tablex")
44

55
local node_types = {}
6-
local node_to_class
6+
local node_to_type
77
local dedent
88

99
local FluentNode = class({
1010
discardable = false,
11-
mergable = false,
11+
appendable = false,
1212

1313
_init = function (self, node)
1414
for key, value in pairs(node) do
@@ -24,7 +24,7 @@ local FluentNode = class({
2424
end
2525
if (node[1] and #node > 0) then
2626
self.elements = {}
27-
tablex.insertvalues(self.elements, tablex.imap(node_to_class, node))
27+
tablex.insertvalues(self.elements, tablex.imap(node_to_type, node))
2828
end
2929
end,
3030

@@ -33,6 +33,28 @@ local FluentNode = class({
3333
for k, v in pairs(self) do ast[k] = v end
3434
ast.identifier = nil
3535
return ast
36+
end,
37+
38+
append = function (self, node)
39+
if type(self.__add) == "function"
40+
and self.appendable
41+
and node.appendable
42+
and self:is_a(node:is_a())
43+
then
44+
return self + node
45+
else
46+
return false
47+
end
48+
end,
49+
50+
attach = function (self, node)
51+
if node and
52+
type(node.__mul) == "function"
53+
then
54+
return node * self
55+
else
56+
return false
57+
end
3658
end
3759

3860
})
@@ -47,9 +69,8 @@ node_types.blank_block = class({
4769
end
4870
})
4971

50-
-- TODO: can their ever be more than 1 entry?
5172
node_types.Entry = function(node)
52-
return node_to_class(node[1])
73+
return node_to_type(node[1])
5374
end
5475

5576
node_types.Junk = class({
@@ -121,7 +142,7 @@ node_types.Pattern = class({
121142
-- end
122143

123144
node_types.TextElement = class({
124-
mergable = true,
145+
appendable = true,
125146
_base = FluentNode,
126147
_init = function (self, node)
127148
self:super(node)
@@ -134,27 +155,42 @@ node_types.PatternElement = function (node)
134155
end
135156

136157
node_types.Comment = class({
137-
mergable = true,
158+
appendable = true,
138159
_base = FluentNode,
139160
_init = function (self, node)
140161
self:super(node)
162+
end,
163+
__add = function (self, node)
164+
self.content = (self.content or "") .. "\n" .. (node.content or "")
165+
return self
166+
end,
167+
__mul = function (self, node)
168+
if self:is_a(node_types.Message) then
169+
self.comment = node
170+
return self
171+
elseif node:is_a(node_types.Message) then
172+
node.comment = self
173+
return node
174+
end
141175
end
142176
})
143177

144178
node_types.GroupComment = class({
145-
mergable = true,
179+
appendable = true,
146180
_base = FluentNode,
147181
_init = function (self, node)
148182
self:super(node)
149-
end
183+
end,
184+
__add = node_types.Comment.__add
150185
})
151186

152187
node_types.ResourceComment = class({
153-
mergable = true,
188+
appendable = true,
154189
_base = FluentNode,
155190
_init = function (self, node)
156191
self:super(node)
157-
end
192+
end,
193+
__add = node_types.Comment.__add
158194
})
159195

160196
node_types.Attribute = class({
@@ -171,7 +207,7 @@ node_types.CommentLine = function(node)
171207
return node_types[node.id](node)
172208
end
173209

174-
node_to_class = function (node)
210+
node_to_type = function (node)
175211
if type(node.id) ~= "string" then return nil end
176212
return node_types[node.id](node)
177213
end
@@ -197,65 +233,65 @@ end
197233

198234
local FluentResource = class({
199235
type = "Resource",
200-
idmap = {},
236+
index = {},
201237

202238
_init = function (self, ast)
203239
self.body = {}
204240
local _stash = nil
205241
local flush = function ()
206-
if _stash then table.insert(self.body, _stash) end
207-
_stash = nil
242+
if _stash then
243+
self:insert(_stash)
244+
_stash = nil
245+
end
246+
return #self.body
208247
end
209248
local stash = function (node)
210249
if not _stash then
211250
_stash = node
212-
elseif _stash:is_a(node:is_a()) then
213-
-- TODO: move to _add meta method
214-
_stash.content = (_stash.content or "") .. "\n" .. (node.content or "")
215-
else
251+
elseif not _stash:append(node) then
216252
flush()
217253
_stash = node
218254
end
219255
end
220-
-- TODO: eliminate double iteration by looking ahead?
221-
local elements = tablex.imap(node_to_class, ast)
222-
for _, node in ipairs(elements) do
223-
if node.mergable then
224-
stash(node)
225-
elseif node:is_a(node_types.blank_block) then
256+
for _, leaf in ipairs(ast) do
257+
local node = node_to_type(leaf)
258+
if node:is_a(node_types.blank_block) then
226259
if not node.discardable then
227260
flush()
228261
end
229-
elseif node:is_a(node_types.Message) or node:is_a(node_types.Term) then
230-
if _stash then
231-
if _stash.type ~= "Comment" then
232-
flush()
233-
else
234-
node.comment = _stash
235-
_stash = nil
236-
end
237-
end
238-
table.insert(self.body, node)
239-
if node:is_a(node_types.Message) then
240-
self.idmap[node.identifier] = #self.body
241-
end
262+
elseif node:attach(_stash) then
263+
_stash = nil
264+
stash(node)
242265
else
243-
flush()
244-
table.insert(self.body, node)
266+
stash(node)
245267
end
246268
end
247269
flush()
248270
-- self:catch(function (self, identifier) return self:get_message(identifier) end)
249271
end,
250272

273+
insert = function (self, node)
274+
table.insert(self.body, node)
275+
if node:is_a(node_types.Message) then
276+
self.index[node.identifier] = #self.body
277+
end
278+
end,
279+
251280
get_message = function (self, identifier)
252-
return self.idmap[identifier] and self.body[self.idmap[identifier]]
281+
return self.index[identifier] and self.body[self.index[identifier]]
253282
end,
254283

255284
dump_ast = function (self)
256285
local ast = { type = "Resource", body = {} }
257286
for _, v in ipairs(self.body) do table.insert(ast.body, v:dump_ast()) end
258287
return ast
288+
end,
289+
290+
__add = function (self, resource)
291+
for _, node in ipairs(resource.body) do
292+
self:insert(node)
293+
end
294+
return self
259295
end
260296

261297
})

0 commit comments

Comments
 (0)