Cleanup of replaced vars, now uses tree_map()

This commit is contained in:
Bruce Hill 2018-02-12 14:47:56 -08:00
parent 02af19153e
commit da65c91cb6
2 changed files with 86 additions and 61 deletions

View File

@ -864,9 +864,6 @@ do
if not tree.type then if not tree.type then
error("Invalid tree: " .. tostring(repr(tree)), 0) error("Invalid tree: " .. tostring(repr(tree)), 0)
end end
if not (self.tree_metadata[tree]) then
error("??? tree: " .. tostring(repr(tree)), 0)
end
local _exp_0 = tree.type local _exp_0 = tree.type
if "File" == _exp_0 then if "File" == _exp_0 then
if #tree.value == 1 then if #tree.value == 1 then
@ -1240,19 +1237,27 @@ do
end end
return concat(bits, "\n") return concat(bits, "\n")
end, end,
tree_with_replaced_vars = function(self, tree, replacements) tree_map = function(self, tree, fn)
if type(tree) ~= 'table' then if type(tree) ~= 'table' then
return tree return tree
end end
local replacement = fn(tree)
if replacement ~= nil then
return replacement
end
local _exp_0 = tree.type local _exp_0 = tree.type
if "Var" == _exp_0 then if "File" == _exp_0 or "Nomsu" == _exp_0 or "Block" == _exp_0 or "List" == _exp_0 or "FunctionCall" == _exp_0 or "Text" == _exp_0 then
local id = self:var_to_lua_identifier(tree.value) local new_values, is_changed = { }, false
if replacements[id] ~= nil then for i, old_value in ipairs(tree.value) do
tree = replacements[id] local new_value = type(old_value) ~= "string" and self:tree_map(old_value, fn) or nil
if new_value ~= nil and new_value ~= old_value then
is_changed = true
new_values[i] = new_value
else
new_values[i] = old_value
end
end end
elseif "File" == _exp_0 or "Nomsu" == _exp_0 or "Block" == _exp_0 or "List" == _exp_0 or "FunctionCall" == _exp_0 or "Text" == _exp_0 then if is_changed then
local new_value = self:tree_with_replaced_vars(tree.value, replacements)
if new_value ~= tree.value then
local new_tree local new_tree
do do
local _tbl_0 = { } local _tbl_0 = { }
@ -1262,22 +1267,25 @@ do
new_tree = _tbl_0 new_tree = _tbl_0
end end
self.tree_metadata[new_tree] = self.tree_metadata[tree] self.tree_metadata[new_tree] = self.tree_metadata[tree]
tree = new_tree new_tree.value = new_values
tree.value = new_value return new_tree
end end
elseif "Dict" == _exp_0 then elseif "Dict" == _exp_0 then
local dirty = false local new_values, is_changed = { }, false
replacements = { }
for i, e in ipairs(tree.value) do for i, e in ipairs(tree.value) do
local new_key = self:tree_with_replaced_vars(e.dict_key, replacements) local new_key = self:tree_map(e.dict_key, fn)
local new_value = self:tree_with_replaced_vars(e.dict_value, replacements) local new_value = self:tree_map(e.dict_value, fn)
dirty = dirty or (new_key ~= e.dict_key or new_value ~= e.dict_value) if (new_key ~= nil and new_key ~= e.dict_key) or (new_value ~= nil and new_value ~= e.dict_value) then
replacements[i] = { is_changed = true
dict_key = new_key, new_values[i] = {
dict_value = new_value dict_key = new_key,
} dict_value = new_value
}
else
new_values[i] = e
end
end end
if dirty then if is_changed then
local new_tree local new_tree
do do
local _tbl_0 = { } local _tbl_0 = { }
@ -1287,22 +1295,24 @@ do
new_tree = _tbl_0 new_tree = _tbl_0
end end
self.tree_metadata[new_tree] = self.tree_metadata[tree] self.tree_metadata[new_tree] = self.tree_metadata[tree]
tree = new_tree new_tree.value = new_values
tree.value = replacements return new_tree
end end
elseif nil == _exp_0 then elseif nil == _exp_0 then
local new_values = { } error("Invalid tree: " .. tostring(repr(tree)))
local any_different = false
for k, v in pairs(tree) do
new_values[k] = self:tree_with_replaced_vars(v, replacements)
any_different = any_different or (new_values[k] ~= tree[k])
end
if any_different then
tree = new_values
end
end end
return tree return tree
end, end,
tree_with_replaced_vars = function(self, tree, replacements)
return self:tree_map(tree, function(t)
if t.type == "Var" then
local id = self:var_to_lua_identifier(t.value)
if replacements[id] ~= nil then
return replacements[id]
end
end
end)
end,
tree_to_stub = cached(function(self, tree) tree_to_stub = cached(function(self, tree)
if tree.type ~= "FunctionCall" then if tree.type ~= "FunctionCall" then
error("Tried to get stub from non-functioncall tree: " .. tostring(tree.type), 0) error("Tried to get stub from non-functioncall tree: " .. tostring(tree.type), 0)
@ -1663,6 +1673,8 @@ if arg and debug.getinfo(2).func ~= require then
end) end)
if ok and ret ~= nil then if ok and ret ~= nil then
print("= " .. repr(ret)) print("= " .. repr(ret))
elseif not ok then
print(colored.bright(colored.red(ret)))
end end
end end
end end

View File

@ -640,8 +640,6 @@ class NomsuCompiler
assert tree, "No tree provided." assert tree, "No tree provided."
if not tree.type if not tree.type
error("Invalid tree: #{repr(tree)}", 0) error("Invalid tree: #{repr(tree)}", 0)
unless @tree_metadata[tree]
error "??? tree: #{repr tree}", 0
switch tree.type switch tree.type
when "File" when "File"
if #tree.value == 1 if #tree.value == 1
@ -859,45 +857,58 @@ class NomsuCompiler
insert bits, close insert bits, close
return concat(bits) return concat(bits)
tree_with_replaced_vars: (tree, replacements)=> tree_map: (tree, fn)=>
-- Return a new tree with fn mapped to each node. If fn provides a replacement,
-- use that and stop recursing, otherwise recurse.
if type(tree) != 'table' then return tree if type(tree) != 'table' then return tree
replacement = fn(tree)
if replacement != nil
return replacement
switch tree.type switch tree.type
when "Var"
id = @var_to_lua_identifier tree.value
if replacements[id] ~= nil
tree = replacements[id]
when "File", "Nomsu", "Block", "List", "FunctionCall", "Text" when "File", "Nomsu", "Block", "List", "FunctionCall", "Text"
new_value = @tree_with_replaced_vars tree.value, replacements new_values, is_changed = {}, false
if new_value != tree.value for i,old_value in ipairs(tree.value)
new_value = type(old_value) != "string" and @tree_map(old_value, fn) or nil
if new_value != nil and new_value != old_value
is_changed = true
new_values[i] = new_value
else
new_values[i] = old_value
if is_changed
new_tree = {k,v for k,v in pairs(tree)} new_tree = {k,v for k,v in pairs(tree)}
-- TODO: Maybe generate new metadata? -- TODO: Maybe generate new metadata?
@tree_metadata[new_tree] = @tree_metadata[tree] @tree_metadata[new_tree] = @tree_metadata[tree]
tree = new_tree new_tree.value = new_values
tree.value = new_value return new_tree
when "Dict" when "Dict"
dirty = false new_values, is_changed = {}, false
replacements = {}
for i,e in ipairs tree.value for i,e in ipairs tree.value
new_key = @tree_with_replaced_vars e.dict_key, replacements new_key = @tree_map(e.dict_key, fn)
new_value = @tree_with_replaced_vars e.dict_value, replacements new_value = @tree_map(e.dict_value, fn)
dirty or= new_key != e.dict_key or new_value != e.dict_value if (new_key != nil and new_key != e.dict_key) or (new_value != nil and new_value != e.dict_value)
replacements[i] = {dict_key:new_key, dict_value:new_value} is_changed = true
if dirty new_values[i] = {dict_key:new_key, dict_value:new_value}
else
new_values[i] = e
if is_changed
new_tree = {k,v for k,v in pairs(tree)} new_tree = {k,v for k,v in pairs(tree)}
-- TODO: Maybe generate new metadata? -- TODO: Maybe generate new metadata?
@tree_metadata[new_tree] = @tree_metadata[tree] @tree_metadata[new_tree] = @tree_metadata[tree]
tree = new_tree new_tree.value = new_values
tree.value = replacements return new_tree
when nil -- Raw table, probably from one of the .value of a multi-value tree (e.g. List) when nil -- Raw table, probably from one of the .value of a multi-value tree (e.g. List)
new_values = {} error("Invalid tree: #{repr tree}")
any_different = false
for k,v in pairs tree
new_values[k] = @tree_with_replaced_vars v, replacements
any_different or= (new_values[k] != tree[k])
if any_different
tree = new_values
return tree return tree
tree_with_replaced_vars: (tree, replacements)=>
return @tree_map tree, (t)->
if t.type == "Var"
id = @var_to_lua_identifier t.value
if replacements[id] != nil
return replacements[id]
tree_to_stub: cached (tree)=> tree_to_stub: cached (tree)=>
if tree.type != "FunctionCall" then error "Tried to get stub from non-functioncall tree: #{tree.type}", 0 if tree.type != "FunctionCall" then error "Tried to get stub from non-functioncall tree: #{tree.type}", 0
return concat([(t.type == "Word" and t.value or "%") for t in *tree.value], " ") return concat([(t.type == "Word" and t.value or "%") for t in *tree.value], " ")
@ -1065,6 +1076,8 @@ if arg and debug.getinfo(2).func != require
ok, ret = pcall(-> nomsu\run(buff, "stdin")) ok, ret = pcall(-> nomsu\run(buff, "stdin"))
if ok and ret != nil if ok and ret != nil
print "= "..repr(ret) print "= "..repr(ret)
elseif not ok
print colored.bright colored.red ret
err_hand = (error_message)-> err_hand = (error_message)->
-- TODO: write properly to stderr -- TODO: write properly to stderr