1 local insert, remove, concat
4 insert, remove, concat = _obj_0.insert, _obj_0.remove, _obj_0.concat
7 Source = require("code_obj").Source
10 local _obj_0 = require('containers')
11 List, Dict = _obj_0.List, _obj_0.Dict
13 local Files = require('files')
14 local unpack = unpack or table.unpack
16 as_lua = function(self)
17 if type(self) == 'number' then
21 local mt = getmetatable(self)
24 local _as_lua = mt.as_lua
34 return error("Not supported: " .. tostring(self))
40 __tostring = function(self)
45 for _index_0 = 1, #self do
46 local b = self[_index_0]
47 _accum_0[_len_0] = type(b) == 'string' and b:as_lua() or tostring(b)
52 for k, v in pairs(self) do
53 if not (bits[k] or k == 'type' or k == 'source') then
54 table.insert(bits, tostring(k) .. "=" .. tostring(type(v) == 'string' and v:as_lua() or v))
57 return tostring(self.type) .. "{" .. tostring(table.concat(bits, ", ")) .. "}"
59 __eq = function(self, other)
60 if type(self) ~= type(other) or #self ~= #other or getmetatable(self) ~= getmetatable(other) then
63 if self.type ~= other.type then
67 if self[i] ~= other[i] then
73 as_lua = function(self)
78 for _index_0 = 1, #self do
79 local b = self[_index_0]
80 _accum_0[_len_0] = as_lua(b)
85 for k, v in pairs(self) do
87 table.insert(bits, "[ " .. tostring(as_lua(k)) .. "]=" .. tostring(as_lua(v)))
90 return "SyntaxTree{" .. tostring(table.concat(bits, ", ")) .. "}"
92 get_source_file = function(self)
93 return self.__class.source_code_for_tree[self]
95 get_source_code = function(self)
96 return self.__class.source_code_for_tree[self]:sub(self.source.start, self.source.stop - 1)
98 add = function(self, ...)
100 for i = 1, select('#', ...) do
101 self[n + i] = select(i, ...)
105 with = function(self, fn)
106 if type(fn) == 'table' then
107 local replacements = fn
109 if t.type == "Var" then
111 local r = replacements[t:as_var()]
119 local replacement = fn(self)
120 if replacement == false then
124 if SyntaxTree:is_instance(replacement) then
127 for k, v in pairs(replacement) do
132 replacement.source = self.source
133 if self.comments then
134 replacement.comments = {
135 unpack(self.comments)
138 replacement = SyntaxTree(replacement)
142 source = self.source,
143 comments = self.comments and {
144 unpack(self.comments)
147 local changes = false
148 for k, v in pairs(self) do
149 local _continue_0 = false
152 if SyntaxTree:is_instance(v) then
154 if r == v or r == nil then
163 if not _continue_0 then
167 if not (changes) then
170 replacement = SyntaxTree(replacement)
174 contains = function(self, subtree)
175 if subtree == self then
178 for k, v in pairs(self) do
179 if SyntaxTree:is_instance(v) then
180 if v:contains(subtree) then
187 get_args = function(self)
188 assert(self.type == "Action" or self.type == "MethodCall", "Only actions and method calls have arguments")
190 if self.type == "MethodCall" then
193 local _list_0 = self[i]
194 for _index_0 = 1, #_list_0 do
195 local tok = _list_0[_index_0]
196 if type(tok) ~= 'string' then
197 args[#args + 1] = tok
202 for _index_0 = 1, #self do
203 local tok = self[_index_0]
204 if type(tok) ~= 'string' then
205 args[#args + 1] = tok
211 get_stub = function(self)
212 local _exp_0 = self.type
213 if "Action" == _exp_0 then
214 local stub_bits = { }
216 for _index_0 = 1, #self do
217 local a = self[_index_0]
218 if type(a) == 'string' then
219 stub_bits[#stub_bits + 1] = a
221 stub_bits[#stub_bits + 1] = arg_i
225 while type(stub_bits[#stub_bits]) == 'number' do
226 stub_bits[#stub_bits] = nil
228 return concat(stub_bits, " ")
229 elseif "MethodCall" == _exp_0 then
230 return "0, " .. table.concat((function()
234 _accum_0[_len_0] = self[i]:get_stub()
240 return error(tostring(self.type) .. "s do not have stubs")
243 as_var = function(self)
244 assert(self.type == "Var")
245 if type(self[1]) == 'string' then
248 return self[1]:get_stub()
251 matching = function(self, patt)
252 if patt.type == "Var" then
254 [patt:as_var()] = self
257 if patt.type ~= self.type then
260 if patt.type == "Action" and patt:get_stub() ~= self:get_stub() then
263 if #self ~= #patt then
270 if type(v) ~= type(pv) then
273 if type(v) ~= 'table' then
274 if not (v == pv) then
278 local m = v:matching(pv)
282 for mk, mv in pairs(m) do
283 if match[mk] and match[mk] ~= mv then
292 _breadth_first = function(self)
293 coroutine.yield(self)
294 for _index_0 = 1, #self do
295 local child = self[_index_0]
296 if getmetatable(child) == SyntaxTree.__base then
297 child:_breadth_first()
301 breadth_first = function(self)
302 return coroutine.create(function()
303 return self:_breadth_first()
306 _depth_first = function(self)
307 coroutine.yield(self)
308 for _index_0 = 1, #self do
309 local child = self[_index_0]
310 if getmetatable(child) == SyntaxTree.__base then
315 depth_first = function(self)
316 return coroutine.create(function()
317 return self:_depth_first()
321 _base_0.__index = _base_0
322 _class_0 = setmetatable({
323 __init = function() end,
325 __name = "SyntaxTree"
328 __call = function(cls, ...)
329 local _self_0 = setmetatable({}, _base_0)
330 cls.__init(_self_0, ...)
334 _base_0.__class = _class_0
335 local self = _class_0
336 self.source_code_for_tree = setmetatable({ }, {
337 __index = function(self, t)
339 local f = Files.read(s.filename)
344 self.is_instance = function(self, t)
345 return type(t) == 'table' and getmetatable(t) == self.__base
347 SyntaxTree = _class_0
349 SyntaxTree.__base.__type = "a Syntax Tree"
350 getmetatable(SyntaxTree).__call = function(self, t, ...)
351 if type(t.source) == 'string' then
352 t.source = Source:from_string(t.source)
354 setmetatable(t, self.__base)
355 for i = 1, select("#", ...) do
356 t[i] = select(i, ...)
358 if t.type == 'Action' then
359 t.stub = t:get_stub()