code / nomsu

Lines6.6K Lua5.1K PEG1.3K make117
2 others 83
Markdown60 Bourne Again Shell23
(542 lines)
1 local insert, remove, concat
2 do
3 local _obj_0 = table
4 insert, remove, concat = _obj_0.insert, _obj_0.remove, _obj_0.concat
5 end
6 local unpack = unpack or table.unpack
7 local LuaCode, NomsuCode, Source
8 do
9 local _class_0
10 local _base_0 = {
11 __tostring = function(self)
12 return "@" .. tostring(self.filename) .. "[" .. tostring(self.start) .. tostring(self.stop and ':' .. self.stop or '') .. "]"
13 end,
14 as_lua = function(self)
15 return "Source(" .. tostring(self.filename:as_lua()) .. ", " .. tostring(self.start) .. tostring(self.stop and ', ' .. self.stop or '') .. ")"
16 end,
17 __eq = function(self, other)
18 return getmetatable(self) == getmetatable(other) and self.filename == other.filename and self.start == other.start and self.stop == other.stop
19 end,
20 __lt = function(self, other)
21 assert(self.filename == other.filename, "Cannot compare sources from different files")
22 if self.start == other.start then
23 return (self.stop or self.start) < (other.stop or other.start)
24 else
25 return self.start < other.start
26 end
27 end,
28 __le = function(self, other)
29 assert(self.filename == other.filename, "Cannot compare sources from different files")
30 if self.start == other.start then
31 return (self.stop or self.start) <= (other.stop or other.start)
32 else
33 return self.start <= other.start
34 end
35 end,
36 __add = function(self, offset)
37 if type(self) == 'number' then
38 offset, self = self, offset
39 else
40 if type(offset) ~= 'number' then
41 error("Cannot add Source and " .. tostring(type(offset)))
42 end
43 end
44 return Source(self.filename, self.start + offset, self.stop)
45 end
47 _base_0.__index = _base_0
48 _class_0 = setmetatable({
49 __init = function(self, filename, start, stop)
50 self.filename, self.start, self.stop = filename, start, stop
51 end,
52 __base = _base_0,
53 __name = "Source"
54 }, {
55 __index = _base_0,
56 __call = function(cls, ...)
57 local _self_0 = setmetatable({}, _base_0)
58 cls.__init(_self_0, ...)
59 return _self_0
60 end
61 })
62 _base_0.__class = _class_0
63 local self = _class_0
64 self.from_string = function(self, str)
65 local filename, start, stop = str:match("^@(.-)%[(%d+):(%d+)%]$")
66 if not (filename) then
67 filename, start = str:match("^@(.-)%[(%d+)%]$")
68 end
69 return self(filename or str, tonumber(start or 1), tonumber(stop))
70 end
71 self.is_instance = function(self, x)
72 return type(x) == 'table' and x.__class == self
73 end
74 Source = _class_0
75 end
76 local Code
77 do
78 local _class_0
79 local _base_0 = {
80 text = function(self)
81 if self.__str == nil then
82 local buff, indent = { }, 0
83 local match, gsub, rep
84 do
85 local _obj_0 = string
86 match, gsub, rep = _obj_0.match, _obj_0.gsub, _obj_0.rep
87 end
88 for i, b in ipairs(self.bits) do
89 if type(b) == 'string' then
90 do
91 local spaces = match(b, "\n([ ]*)[^\n]*$")
92 if spaces then
93 indent = #spaces
94 end
95 end
96 else
97 b = b:text()
98 if indent > 0 then
99 b = gsub(b, "\n", "\n" .. rep(" ", indent))
100 end
101 end
102 buff[#buff + 1] = b
103 end
104 self.__str = concat(buff, "")
105 end
106 return self.__str
107 end,
108 last = function(self, n)
109 if self.__str then
110 return self.__str:sub(-n, -1)
111 end
112 local last = ""
113 for i = #self.bits, 1, -1 do
114 local b = self.bits[i]
115 last = (type(b) == 'string' and b:sub(-(n - #last)) or b:last(n - #last)) .. last
116 if #last == n then
117 break
118 end
119 end
120 return last
121 end,
122 first = function(self, n)
123 if self.__str then
124 return self.__str:sub(1, n)
125 end
126 local first = ""
127 local _list_0 = self.bits
128 for _index_0 = 1, #_list_0 do
129 local b = _list_0[_index_0]
130 first = first .. (type(b) == 'string' and b:sub(1, n - #first + 1) or b:first(n - #first + 1))
131 if #first == n then
132 break
133 end
134 end
135 return first
136 end,
137 __tostring = function(self)
138 return self:text()
139 end,
140 as_lua = function(self)
141 if self.source then
142 return tostring(self.__class.__name) .. ":from(" .. tostring(concat({
143 tostring(self.source):as_lua(),
144 unpack((function()
145 local _accum_0 = { }
146 local _len_0 = 1
147 local _list_0 = self.bits
148 for _index_0 = 1, #_list_0 do
149 local b = _list_0[_index_0]
150 _accum_0[_len_0] = b:as_lua()
151 _len_0 = _len_0 + 1
152 end
153 return _accum_0
154 end)())
155 }, ", ")) .. ")"
156 else
157 return tostring(self.__class.__name) .. "(" .. tostring(concat((function()
158 local _accum_0 = { }
159 local _len_0 = 1
160 local _list_0 = self.bits
161 for _index_0 = 1, #_list_0 do
162 local b = _list_0[_index_0]
163 _accum_0[_len_0] = b:as_lua()
164 _len_0 = _len_0 + 1
165 end
166 return _accum_0
167 end)(), ", ")) .. ")"
168 end
169 end,
170 __len = function(self)
171 if self.__str then
172 return #self.__str
173 end
174 local len = 0
175 local _list_0 = self.bits
176 for _index_0 = 1, #_list_0 do
177 local b = _list_0[_index_0]
178 len = len + #b
179 end
180 return len
181 end,
182 match = function(self, ...)
183 return self:text():match(...)
184 end,
185 gmatch = function(self, ...)
186 return self:text():gmatch(...)
187 end,
188 dirty = function(self)
189 self.__str = nil
190 self._trailing_line_len = nil
191 if self._is_multiline == false then
192 self._is_multiline = nil
193 end
194 end,
195 add = function(self, ...)
196 local n = select("#", ...)
197 local match = string.match
198 local bits = self.bits
199 for i = 1, n do
200 local _continue_0 = false
201 repeat
202 local b = select(i, ...)
203 assert(b, "code bit is nil")
204 assert(not Source:is_instance(b), "code bit is a Source")
205 if b == '' then
206 _continue_0 = true
207 break
208 end
209 bits[#bits + 1] = b
210 _continue_0 = true
211 until true
212 if not _continue_0 then
213 break
214 end
215 end
216 return self:dirty()
217 end,
218 trailing_line_len = function(self)
219 if self._trailing_line_len == nil then
220 self._trailing_line_len = #self:text():match("[^\n]*$")
221 end
222 return self._trailing_line_len
223 end,
224 is_multiline = function(self)
225 if self._is_multiline == nil then
226 local match = string.match
227 self._is_multiline = false
228 local _list_0 = self.bits
229 for _index_0 = 1, #_list_0 do
230 local b = _list_0[_index_0]
231 if type(b) == 'string' then
232 if match(b, '\n') then
233 self._is_multiline = true
234 break
235 end
236 elseif b:is_multiline() then
237 self._is_multiline = true
238 break
239 end
240 end
241 end
242 return self._is_multiline
243 end,
244 concat_add = function(self, values, joiner, wrapping_joiner)
245 wrapping_joiner = wrapping_joiner or joiner
246 local match = string.match
247 local bits = self.bits
248 local line_len = 0
249 for i = 1, #values do
250 local b = values[i]
251 if i > 1 then
252 if line_len > 80 then
253 bits[#bits + 1] = wrapping_joiner
254 line_len = 0
255 else
256 bits[#bits + 1] = joiner
257 end
258 end
259 bits[#bits + 1] = b
260 if type(b) ~= 'string' then
261 b.dirty = error
262 end
263 local line = b:match("\n([^\n]*)$")
264 if line then
265 line_len = #line
266 else
267 line_len = line_len + #b
268 end
269 end
270 return self:dirty()
271 end,
272 prepend = function(self, ...)
273 local n = select("#", ...)
274 local bits = self.bits
275 for i = #bits + n, n + 1, -1 do
276 bits[i] = bits[i - n]
277 end
278 for i = 1, n do
279 local b = select(i, ...)
280 if type(b) ~= 'string' then
281 b.dirty = error
282 end
283 bits[i] = b
284 end
285 return self:dirty()
286 end,
287 parenthesize = function(self)
288 self:prepend("(")
289 return self:add(")")
290 end
292 _base_0.__index = _base_0
293 _class_0 = setmetatable({
294 __init = function(self, ...)
295 self.bits = { }
296 return self:add(...)
297 end,
298 __base = _base_0,
299 __name = "Code"
300 }, {
301 __index = _base_0,
302 __call = function(cls, ...)
303 local _self_0 = setmetatable({}, _base_0)
304 cls.__init(_self_0, ...)
305 return _self_0
306 end
308 _base_0.__class = _class_0
309 local self = _class_0
310 self.from = function(self, source, ...)
311 local inst = self(...)
312 if type(source) == 'string' then
313 source = Source:from_string(source)
314 end
315 inst.source = source
316 return inst
317 end
318 self.is_instance = function(self, x)
319 return type(x) == 'table' and x.__class == self
320 end
321 Code = _class_0
322 end
324 local _class_0
325 local _parent_0 = Code
326 local _base_0 = {
327 __tostring = Code.__tostring,
328 as_lua = Code.as_lua,
329 __len = Code.__len,
330 add_free_vars = function(self, vars)
331 if not (#vars > 0) then
332 return
333 end
334 local seen
336 local _tbl_0 = { }
337 local _list_0 = self.free_vars
338 for _index_0 = 1, #_list_0 do
339 local v = _list_0[_index_0]
340 local _key_0, _val_0 = {
341 [v] = true
343 _tbl_0[_key_0] = _val_0
344 end
345 seen = _tbl_0
346 end
347 for _index_0 = 1, #vars do
348 local var = vars[_index_0]
349 assert(type(var) == 'string')
350 if not (seen[var]) then
351 self.free_vars[#self.free_vars + 1] = var
352 seen[var] = true
353 end
354 end
355 return self:dirty()
356 end,
357 remove_free_vars = function(self, vars)
358 if vars == nil then
359 vars = nil
360 end
361 vars = vars or self:get_free_vars()
362 if not (#vars > 0) then
363 return
364 end
365 local removals = { }
366 for _index_0 = 1, #vars do
367 local var = vars[_index_0]
368 assert(type(var) == 'string')
369 removals[var] = true
370 end
371 local stack = {
372 self
374 while #stack > 0 do
375 local lua
376 lua, stack[#stack] = stack[#stack], nil
377 for i = #lua.free_vars, 1, -1 do
378 local free_var = lua.free_vars[i]
379 if removals[free_var] then
380 remove(lua.free_vars, i)
381 end
382 end
383 local _list_0 = lua.bits
384 for _index_0 = 1, #_list_0 do
385 local b = _list_0[_index_0]
386 if type(b) ~= 'string' then
387 stack[#stack + 1] = b
388 end
389 end
390 end
391 return self:dirty()
392 end,
393 get_free_vars = function(self)
394 local vars, seen = { }, { }
395 local gather_from
396 gather_from = function(self)
397 local _list_0 = self.free_vars
398 for _index_0 = 1, #_list_0 do
399 local var = _list_0[_index_0]
400 if not (seen[var]) then
401 seen[var] = true
402 vars[#vars + 1] = var
403 end
404 end
405 local _list_1 = self.bits
406 for _index_0 = 1, #_list_1 do
407 local bit = _list_1[_index_0]
408 if not (type(bit) == 'string') then
409 gather_from(bit)
410 end
411 end
412 end
413 gather_from(self)
414 return vars
415 end,
416 declare_locals = function(self, to_declare)
417 if to_declare == nil then
418 to_declare = nil
419 end
420 to_declare = to_declare or self:get_free_vars()
421 if #to_declare > 0 then
422 self:remove_free_vars(to_declare)
423 self:prepend("local " .. tostring(concat(to_declare, ", ")) .. ";\n")
424 end
425 return to_declare
426 end,
427 make_offset_table = function(self)
428 assert(self.source, "This code doesn't have a source")
429 local lua_to_nomsu, nomsu_to_lua = { }, { }
430 local walk
431 walk = function(lua, pos)
432 local _list_0 = lua.bits
433 for _index_0 = 1, #_list_0 do
434 local b = _list_0[_index_0]
435 if type(b) == 'string' then
436 if lua.source then
437 lua_to_nomsu[pos] = lua.source.start
438 nomsu_to_lua[lua.source.start] = pos
439 end
440 else
441 walk(b, pos)
442 end
443 pos = pos + #b
444 end
445 end
446 walk(self, 1)
447 return {
448 nomsu_filename = self.source.filename,
449 lua_filename = tostring(self.source) .. ".lua",
450 lua_file = self:text(),
451 lua_to_nomsu = lua_to_nomsu,
452 nomsu_to_lua = nomsu_to_lua
454 end,
455 parenthesize = function(self)
456 self:prepend("(")
457 return self:add(")")
458 end
460 _base_0.__index = _base_0
461 setmetatable(_base_0, _parent_0.__base)
462 _class_0 = setmetatable({
463 __init = function(self, ...)
464 _class_0.__parent.__init(self, ...)
465 self.free_vars = { }
466 end,
467 __base = _base_0,
468 __name = "LuaCode",
469 __parent = _parent_0
470 }, {
471 __index = function(cls, name)
472 local val = rawget(_base_0, name)
473 if val == nil then
474 local parent = rawget(cls, "__parent")
475 if parent then
476 return parent[name]
477 end
478 else
479 return val
480 end
481 end,
482 __call = function(cls, ...)
483 local _self_0 = setmetatable({}, _base_0)
484 cls.__init(_self_0, ...)
485 return _self_0
486 end
488 _base_0.__class = _class_0
489 if _parent_0.__inherited then
490 _parent_0.__inherited(_parent_0, _class_0)
491 end
492 LuaCode = _class_0
493 end
495 local _class_0
496 local _parent_0 = Code
497 local _base_0 = {
498 __tostring = Code.__tostring,
499 as_lua = Code.as_lua,
500 __len = Code.__len
502 _base_0.__index = _base_0
503 setmetatable(_base_0, _parent_0.__base)
504 _class_0 = setmetatable({
505 __init = function(self, ...)
506 return _class_0.__parent.__init(self, ...)
507 end,
508 __base = _base_0,
509 __name = "NomsuCode",
510 __parent = _parent_0
511 }, {
512 __index = function(cls, name)
513 local val = rawget(_base_0, name)
514 if val == nil then
515 local parent = rawget(cls, "__parent")
516 if parent then
517 return parent[name]
518 end
519 else
520 return val
521 end
522 end,
523 __call = function(cls, ...)
524 local _self_0 = setmetatable({}, _base_0)
525 cls.__init(_self_0, ...)
526 return _self_0
527 end
529 _base_0.__class = _class_0
530 if _parent_0.__inherited then
531 _parent_0.__inherited(_parent_0, _class_0)
532 end
533 NomsuCode = _class_0
534 end
535 Code.__base.add_1_joined_with = assert(Code.__base.concat_add)
536 Code.__base.add = assert(Code.__base.add)
537 return {
538 Code = Code,
539 NomsuCode = NomsuCode,
540 LuaCode = LuaCode,
541 Source = Source