Completely fixed/reworked tree_to_nomsu, and it's okay right now.
This commit is contained in:
parent
64865aa596
commit
8bbebb8735
@ -89,7 +89,8 @@ immediately:
|
|||||||
compile [stop repeat-loop] to code: "goto stop_repeat;"
|
compile [stop repeat-loop] to code: "goto stop_repeat;"
|
||||||
compile [repeat while %condition %body] to code:
|
compile [repeat while %condition %body] to code:
|
||||||
set %continue_labels = (..)
|
set %continue_labels = (..)
|
||||||
"\n::continue_repeat::;" if (tree %body has function call \(do next repeat-loop)) else ""
|
"\n::continue_repeat::;"
|
||||||
|
..if (tree %body has function call \(do next repeat-loop)) else ""
|
||||||
set %code = ".."
|
set %code = ".."
|
||||||
while \(%condition as lua) do
|
while \(%condition as lua) do
|
||||||
\(%body as lua statements)\
|
\(%body as lua statements)\
|
||||||
|
419
nomsu.lua
419
nomsu.lua
@ -486,160 +486,331 @@ do
|
|||||||
end
|
end
|
||||||
return lua_thunk()
|
return lua_thunk()
|
||||||
end,
|
end,
|
||||||
tree_to_nomsu = function(self, tree, force_inline)
|
tree_to_nomsu = function(self, tree, indentation, max_line, expr_type)
|
||||||
if force_inline == nil then
|
if indentation == nil then
|
||||||
force_inline = false
|
indentation = ""
|
||||||
end
|
end
|
||||||
assert(tree, "No tree provided.")
|
if max_line == nil then
|
||||||
if not tree.type then
|
max_line = 80
|
||||||
error("Invalid tree: " .. tostring(repr(tree)))
|
|
||||||
end
|
end
|
||||||
local _exp_0 = tree.type
|
if expr_type == nil then
|
||||||
if "File" == _exp_0 then
|
expr_type = nil
|
||||||
return concat((function()
|
|
||||||
local _accum_0 = { }
|
|
||||||
local _len_0 = 1
|
|
||||||
local _list_0 = tree.value
|
|
||||||
for _index_0 = 1, #_list_0 do
|
|
||||||
local v = _list_0[_index_0]
|
|
||||||
_accum_0[_len_0] = self:tree_to_nomsu(v, force_inline)
|
|
||||||
_len_0 = _len_0 + 1
|
|
||||||
end
|
end
|
||||||
return _accum_0
|
assert(tree, "No tree provided to tree_to_nomsu.")
|
||||||
end)(), "\n"), false
|
assert(tree.type, "Invalid tree: " .. tostring(repr(tree)))
|
||||||
elseif "Nomsu" == _exp_0 then
|
local join_lines
|
||||||
local inside, inline = self:tree_to_nomsu(tree.value, force_inline)
|
join_lines = function(lines)
|
||||||
return "\\" .. tostring(inside), inline
|
for _index_0 = 1, #lines do
|
||||||
elseif "Comment" == _exp_0 then
|
local line = lines[_index_0]
|
||||||
if tree.value:find("\n") then
|
if #indentation + #line > max_line then
|
||||||
return "#.." .. tostring(self:indent(tree.value)), false
|
return nil
|
||||||
else
|
|
||||||
return "#" .. tostring(tree.value), false
|
|
||||||
end
|
end
|
||||||
elseif "Block" == _exp_0 then
|
|
||||||
if force_inline then
|
|
||||||
return "(:" .. tostring(concat((function()
|
|
||||||
local _accum_0 = { }
|
|
||||||
local _len_0 = 1
|
|
||||||
local _list_0 = tree.value
|
|
||||||
for _index_0 = 1, #_list_0 do
|
|
||||||
local v = _list_0[_index_0]
|
|
||||||
_accum_0[_len_0] = self:tree_to_nomsu(v, true)
|
|
||||||
_len_0 = _len_0 + 1
|
|
||||||
end
|
end
|
||||||
return _accum_0
|
return concat(lines, "\n" .. indentation)
|
||||||
end)(), "; ")) .. ")", true
|
|
||||||
else
|
|
||||||
return ":" .. self:indent("\n" .. concat((function()
|
|
||||||
local _accum_0 = { }
|
|
||||||
local _len_0 = 1
|
|
||||||
local _list_0 = tree.value
|
|
||||||
for _index_0 = 1, #_list_0 do
|
|
||||||
local v = _list_0[_index_0]
|
|
||||||
_accum_0[_len_0] = self:tree_to_nomsu(v)
|
|
||||||
_len_0 = _len_0 + 1
|
|
||||||
end
|
end
|
||||||
return _accum_0
|
local is_operator
|
||||||
end)(), "\n")), false
|
is_operator = function(tok)
|
||||||
|
return tok and tok.type == "Word" and OPERATOR_CHAR:match(tok.value)
|
||||||
end
|
end
|
||||||
|
local inline_expression, noeol_expression, expression
|
||||||
|
inline_expression = function(tok)
|
||||||
|
local _exp_0 = tok.type
|
||||||
|
if "Block" == _exp_0 then
|
||||||
|
if #tok.value > 1 then
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
local nomsu = inline_expression(tok.value)
|
||||||
|
return nomsu and "(: " .. tostring(nomsu) .. ")"
|
||||||
elseif "FunctionCall" == _exp_0 then
|
elseif "FunctionCall" == _exp_0 then
|
||||||
local buff = ""
|
local buff = ""
|
||||||
local sep = ""
|
for i, bit in ipairs(tok.value) do
|
||||||
local inline = true
|
if bit.type == "Word" then
|
||||||
local line_len = 0
|
if i == 1 or (is_operator(bit) and is_operator(tok.value[i - 1])) then
|
||||||
local _list_0 = tree.value
|
buff = buff .. bit.value
|
||||||
for _index_0 = 1, #_list_0 do
|
|
||||||
local arg = _list_0[_index_0]
|
|
||||||
local nomsu, arg_inline = self:tree_to_nomsu(arg, force_inline)
|
|
||||||
if sep == " " and line_len + #nomsu > 80 then
|
|
||||||
sep = "\n.."
|
|
||||||
end
|
|
||||||
if not (sep == " " and not arg_inline and nomsu:sub(1, 1) == ":") then
|
|
||||||
buff = buff .. sep
|
|
||||||
end
|
|
||||||
if arg_inline then
|
|
||||||
sep = " "
|
|
||||||
line_len = line_len + (1 + #nomsu)
|
|
||||||
else
|
else
|
||||||
line_len = 0
|
buff = buff .. (" " .. bit.value)
|
||||||
inline = false
|
|
||||||
sep = "\n.."
|
|
||||||
end
|
|
||||||
if arg.type == 'FunctionCall' then
|
|
||||||
if arg_inline then
|
|
||||||
buff = buff .. "(" .. tostring(nomsu) .. ")"
|
|
||||||
else
|
|
||||||
buff = buff .. "(..)\n " .. tostring(self:indent(nomsu))
|
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
buff = buff .. nomsu
|
local nomsu = inline_expression(bit)
|
||||||
|
if not (nomsu) then
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
if not (i == 1 or bit.type == "Block") then
|
||||||
|
buff = buff .. " "
|
||||||
|
end
|
||||||
|
buff = buff .. (function()
|
||||||
|
if bit.type == "FunctionCall" then
|
||||||
|
return "(" .. nomsu .. ")"
|
||||||
|
else
|
||||||
|
return nomsu
|
||||||
|
end
|
||||||
|
end)()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
return buff, inline
|
return buff
|
||||||
elseif "Text" == _exp_0 then
|
elseif "List" == _exp_0 then
|
||||||
local buff = "\""
|
local bits = { }
|
||||||
local longbuff = "\"..\"\n |"
|
local _list_0 = tok.value
|
||||||
local inline = true
|
|
||||||
local _list_0 = tree.value
|
|
||||||
for _index_0 = 1, #_list_0 do
|
for _index_0 = 1, #_list_0 do
|
||||||
local bit = _list_0[_index_0]
|
local bit = _list_0[_index_0]
|
||||||
if type(bit) == "string" then
|
local nomsu = inline_expression(bit)
|
||||||
bit = bit:gsub("\\", "\\\\")
|
if not (nomsu) then
|
||||||
buff = buff .. bit:gsub("\n", "\\n"):gsub("\"", "\\\"")
|
return nil
|
||||||
longbuff = longbuff .. bit:gsub("\n", "\n |")
|
end
|
||||||
|
insert(bits, nomsu)
|
||||||
|
end
|
||||||
|
return "[" .. concat(bits, ", ") .. "]"
|
||||||
|
elseif "Dict" == _exp_0 then
|
||||||
|
local bits = { }
|
||||||
|
local _list_0 = tok.value
|
||||||
|
for _index_0 = 1, #_list_0 do
|
||||||
|
local bit = _list_0[_index_0]
|
||||||
|
local key_nomsu
|
||||||
|
if bit.dict_key.type == "Word" then
|
||||||
|
key_nomsu = bit.dict_key.value
|
||||||
else
|
else
|
||||||
local inside, bit_inline = self:tree_to_nomsu(bit, force_inline)
|
key_nomsu = inline_expression(bit.dict_key)
|
||||||
inline = inline and bit_inline
|
|
||||||
buff = buff .. "\\(" .. tostring(inside) .. ")"
|
|
||||||
longbuff = longbuff .. "\\(" .. tostring(inside) .. ")"
|
|
||||||
end
|
end
|
||||||
|
if not (key_nomsu) then
|
||||||
|
return nil
|
||||||
end
|
end
|
||||||
buff = buff .. "\""
|
if bit.dict_key.type == "FunctionCall" then
|
||||||
if force_inline or (inline and #buff <= 90) then
|
key_nomsu = "(" .. key_nomsu .. ")"
|
||||||
return buff, true
|
end
|
||||||
|
local value_nomsu = inline_expression(bit.dict_value)
|
||||||
|
if not (value_nomsu) then
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
insert(bits, key_nomsu .. "=" .. value_nomsu)
|
||||||
|
end
|
||||||
|
return "{" .. concat(bits, ", ") .. "}"
|
||||||
|
elseif "Text" == _exp_0 then
|
||||||
|
local buff = '"'
|
||||||
|
local _list_0 = tok.value
|
||||||
|
for _index_0 = 1, #_list_0 do
|
||||||
|
local bit = _list_0[_index_0]
|
||||||
|
if type(bit) == 'string' then
|
||||||
|
if bit:find("\n") then
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
buff = buff .. bit:gsub("\\", "\\\\"):gsub("\n", "\\n")
|
||||||
else
|
else
|
||||||
return longbuff, false
|
local nomsu = inline_expression(bit)
|
||||||
|
if not (nomsu) then
|
||||||
|
return nil
|
||||||
end
|
end
|
||||||
|
buff = buff .. (function()
|
||||||
|
if nomsu.type == "Var" or nomsu.type == "List" or nomsu.type == "Dict" then
|
||||||
|
return "\\" .. nomsu
|
||||||
|
else
|
||||||
|
return "\\(" .. nomsu .. ")"
|
||||||
|
end
|
||||||
|
end)()
|
||||||
|
end
|
||||||
|
if #buff > max_line then
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return buff .. '"'
|
||||||
|
elseif "Nomsu" == _exp_0 then
|
||||||
|
local nomsu = inline_expression(tok.value)
|
||||||
|
if not nomsu then
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
return "\\(" .. nomsu .. ")"
|
||||||
|
elseif "Number" == _exp_0 then
|
||||||
|
return tostring(tok.value)
|
||||||
|
elseif "Var" == _exp_0 then
|
||||||
|
return "%" .. tok.value
|
||||||
|
else
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
noeol_expression = function(tok)
|
||||||
|
local nomsu = inline_expression(tok)
|
||||||
|
if nomsu and #nomsu < max_line then
|
||||||
|
return nomsu
|
||||||
|
end
|
||||||
|
local _exp_0 = tok.type
|
||||||
|
if "Block" == _exp_0 then
|
||||||
|
local buff = ":"
|
||||||
|
local _list_0 = tok.value
|
||||||
|
for _index_0 = 1, #_list_0 do
|
||||||
|
local line = _list_0[_index_0]
|
||||||
|
nomsu = expression(line)
|
||||||
|
if not (nomsu) then
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
buff = buff .. ("\n " .. self:indent(nomsu))
|
||||||
|
end
|
||||||
|
return buff
|
||||||
|
elseif "FunctionCall" == _exp_0 then
|
||||||
|
nomsu = expression(tok)
|
||||||
|
if not (nomsu) then
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
return "(..)\n " .. self:indent(nomsu)
|
||||||
elseif "List" == _exp_0 then
|
elseif "List" == _exp_0 then
|
||||||
local buff = "["
|
local buff = "[..]"
|
||||||
local longbuff = "[..]\n "
|
local line = "\n "
|
||||||
local longsep = ""
|
local _list_0 = tok.value
|
||||||
local longline = 0
|
for _index_0 = 1, #_list_0 do
|
||||||
local inline = true
|
local bit = _list_0[_index_0]
|
||||||
for i, bit in ipairs(tree.value) do
|
nomsu = inline_expression(bit)
|
||||||
local nomsu, bit_inline = self:tree_to_nomsu(bit, force_inline)
|
local sep = line == "\n " and "" or ", "
|
||||||
inline = inline and bit_inline
|
if nomsu and #nomsu + #line < max_line then
|
||||||
if inline then
|
line = line .. (sep .. nomsu)
|
||||||
if i > 1 then
|
if #line >= max_line then
|
||||||
buff = buff .. ", "
|
buff = buff .. line
|
||||||
|
line = "\n "
|
||||||
|
end
|
||||||
|
else
|
||||||
|
line = line .. (sep .. expression(bit))
|
||||||
|
buff = buff .. line
|
||||||
|
line = "\n "
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if line ~= "\n " then
|
||||||
|
buff = buff .. line
|
||||||
|
end
|
||||||
|
return buff
|
||||||
|
elseif "Dict" == _exp_0 then
|
||||||
|
local buff = "{..}"
|
||||||
|
local line = "\n "
|
||||||
|
local _list_0 = tok.value
|
||||||
|
for _index_0 = 1, #_list_0 do
|
||||||
|
local bit = _list_0[_index_0]
|
||||||
|
local key_nomsu = inline_expression(bit.dict_key)
|
||||||
|
if not (key_nomsu) then
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
if bit.dict_key.type == "FunctionCall" then
|
||||||
|
key_nomsu = "(" .. key_nomsu .. ")"
|
||||||
|
end
|
||||||
|
local value_nomsu = inline_expression(bit.dict_value)
|
||||||
|
if value_nomsu and #key_nomsu + #value_nomsu < max_line then
|
||||||
|
line = line .. (key_nomsu .. "=" .. value_nomsu .. ",")
|
||||||
|
if #line >= max_line then
|
||||||
|
buff = buff .. line
|
||||||
|
line = "\n "
|
||||||
|
end
|
||||||
|
else
|
||||||
|
line = line .. (key_nomsu .. "=" .. expression(bit.dict_value))
|
||||||
|
buff = buff .. line
|
||||||
|
line = "\n "
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if line ~= "\n " then
|
||||||
|
buff = buff .. line
|
||||||
|
end
|
||||||
|
return buff
|
||||||
|
elseif "Text" == _exp_0 then
|
||||||
|
local buff = '".."\n '
|
||||||
|
local _list_0 = tok.value
|
||||||
|
for _index_0 = 1, #_list_0 do
|
||||||
|
local bit = _list_0[_index_0]
|
||||||
|
if type(bit) == 'string' then
|
||||||
|
buff = buff .. bit:gsub("\\", "\\\\"):gsub("\n", "\n ")
|
||||||
|
else
|
||||||
|
nomsu = inline_expression(bit)
|
||||||
|
if not (nomsu) then
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
buff = buff .. (function()
|
||||||
|
if nomsu.type == "Var" or nomsu.type == "List" or nomsu.type == "Dict" then
|
||||||
|
return "\\" .. nomsu
|
||||||
|
else
|
||||||
|
return "\\(" .. nomsu .. ")"
|
||||||
|
end
|
||||||
|
end)()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return buff
|
||||||
|
elseif "Nomsu" == _exp_0 then
|
||||||
|
nomsu = expression(tok.value)
|
||||||
|
if not nomsu then
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
return "\\(..)\n " .. self:indent(nomsu)
|
||||||
|
elseif "Comment" == _exp_0 then
|
||||||
|
if tok.value:find("\n") then
|
||||||
|
return "#.." .. tok.value:gsub("\n", "\n ")
|
||||||
|
else
|
||||||
|
return "#" .. tok.value
|
||||||
|
end
|
||||||
|
else
|
||||||
|
return inline_expression(tok)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
expression = function(tok)
|
||||||
|
local nomsu = inline_expression(tok)
|
||||||
|
if nomsu and #nomsu < max_line then
|
||||||
|
return nomsu
|
||||||
|
end
|
||||||
|
local _exp_0 = tok.type
|
||||||
|
if "Block" == _exp_0 then
|
||||||
|
if #tok.value == 1 then
|
||||||
|
nomsu = noeol_expression(tok.value[1])
|
||||||
|
if nomsu and #(nomsu:match("[^\n]*")) < max_line then
|
||||||
|
return ": " .. nomsu
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return noeol_expression(tok)
|
||||||
|
elseif "FunctionCall" == _exp_0 then
|
||||||
|
local buff = ""
|
||||||
|
for i, bit in ipairs(tok.value) do
|
||||||
|
if bit.type == "Word" then
|
||||||
|
if i == 1 or (is_operator(bit) and is_operator(tok.value[i - 1])) or buff:sub(-2, -1) == ".." then
|
||||||
|
buff = buff .. bit.value
|
||||||
|
else
|
||||||
|
buff = buff .. (" " .. bit.value)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
nomsu = inline_expression(bit)
|
||||||
|
if nomsu and #nomsu < max_line then
|
||||||
|
if bit.type == "FunctionCall" then
|
||||||
|
nomsu = "(" .. nomsu .. ")"
|
||||||
|
end
|
||||||
|
else
|
||||||
|
nomsu = expression(bit)
|
||||||
|
if not (nomsu) then
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
if bit.type == "FunctionCall" then
|
||||||
|
nomsu = "(..)\n " .. self:indent(nomsu)
|
||||||
|
end
|
||||||
|
if i < #tok.value then
|
||||||
|
nomsu = nomsu .. "\n.."
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if not (i == 1 or bit.type == "Block") then
|
||||||
|
buff = buff .. " "
|
||||||
end
|
end
|
||||||
buff = buff .. nomsu
|
buff = buff .. nomsu
|
||||||
end
|
end
|
||||||
longbuff = longbuff .. (longsep .. nomsu)
|
end
|
||||||
longline = longline + #nomsu
|
return buff
|
||||||
if bit_inline and longline <= 90 then
|
elseif "File" == _exp_0 then
|
||||||
longsep = ", "
|
local lines = { }
|
||||||
|
local _list_0 = tree.value
|
||||||
|
for _index_0 = 1, #_list_0 do
|
||||||
|
local line = _list_0[_index_0]
|
||||||
|
nomsu = expression(line)
|
||||||
|
assert(nomsu, "Failed to produce output for:\n" .. tostring(colored.yellow(line.src)))
|
||||||
|
insert(lines, nomsu)
|
||||||
|
end
|
||||||
|
return concat(lines, "\n")
|
||||||
|
elseif "Comment" == _exp_0 then
|
||||||
|
if tok.value:find("\n") then
|
||||||
|
return "#.." .. tok.value:gsub("\n", "\n ")
|
||||||
else
|
else
|
||||||
longsep = "\n "
|
return "#" .. tok.value
|
||||||
end
|
end
|
||||||
end
|
|
||||||
buff = buff .. "]"
|
|
||||||
if force_inline or (inline and #buff <= 90) then
|
|
||||||
return buff, true
|
|
||||||
else
|
else
|
||||||
return longbuff, false
|
return noeol_expression(tok)
|
||||||
end
|
end
|
||||||
elseif "Dict" == _exp_0 then
|
|
||||||
return error("Sorry, not yet implemented.")
|
|
||||||
elseif "Number" == _exp_0 then
|
|
||||||
return repr(tree.value), true
|
|
||||||
elseif "Var" == _exp_0 then
|
|
||||||
return "%" .. tostring(tree.value), true
|
|
||||||
elseif "Word" == _exp_0 then
|
|
||||||
return tree.value, true
|
|
||||||
else
|
|
||||||
return error("Unknown/unimplemented thingy: " .. tostring(tree.type))
|
|
||||||
end
|
end
|
||||||
|
return expression(tree)
|
||||||
end,
|
end,
|
||||||
value_to_nomsu = function(self, value)
|
value_to_nomsu = function(self, value)
|
||||||
local _exp_0 = type(value)
|
local _exp_0 = type(value)
|
||||||
|
309
nomsu.moon
309
nomsu.moon
@ -355,117 +355,222 @@ class NomsuCompiler
|
|||||||
error("Failed to compile generated code:\n#{colored.bright colored.blue colored.onblack code}\n\n#{colored.red err}")
|
error("Failed to compile generated code:\n#{colored.bright colored.blue colored.onblack code}\n\n#{colored.red err}")
|
||||||
return lua_thunk!
|
return lua_thunk!
|
||||||
|
|
||||||
tree_to_nomsu: (tree, force_inline=false)=>
|
tree_to_nomsu: (tree, indentation="", max_line=80, expr_type=nil)=>
|
||||||
-- Return <nomsu code>, <is safe for inline use>
|
-- Convert a tree into nomsu code that satisfies the max line requirement or nil
|
||||||
assert tree, "No tree provided."
|
-- if that's not possible
|
||||||
if not tree.type
|
-- expr_type is either:
|
||||||
error "Invalid tree: #{repr(tree)}"
|
-- nil for code that goes at the top level and can contain anything
|
||||||
switch tree.type
|
-- "noeol" for code that can contain anything except an end-of-line component
|
||||||
when "File"
|
-- like a colon (i.e. it already occurs after a colon on the same line)
|
||||||
return concat([@tree_to_nomsu(v, force_inline) for v in *tree.value], "\n"), false
|
-- "inline" for code that cannot contain indented code or an end-of-line component
|
||||||
|
-- e.g. code that is meant to go inside parentheses
|
||||||
|
assert tree, "No tree provided to tree_to_nomsu."
|
||||||
|
assert tree.type, "Invalid tree: #{repr(tree)}"
|
||||||
|
join_lines = (lines)->
|
||||||
|
for line in *lines
|
||||||
|
if #indentation + #line > max_line
|
||||||
|
return nil
|
||||||
|
return concat(lines, "\n"..indentation)
|
||||||
|
|
||||||
when "Nomsu"
|
is_operator = (tok)-> tok and tok.type == "Word" and OPERATOR_CHAR\match(tok.value)
|
||||||
inside, inline = @tree_to_nomsu(tree.value, force_inline)
|
|
||||||
return "\\#{inside}", inline
|
|
||||||
|
|
||||||
when "Comment"
|
|
||||||
if tree.value\find("\n")
|
|
||||||
return "#..#{@indent tree.value}", false
|
|
||||||
else
|
|
||||||
return "##{tree.value}", false
|
|
||||||
|
|
||||||
|
local inline_expression, noeol_expression, expression
|
||||||
|
inline_expression = (tok)->
|
||||||
|
switch tok.type
|
||||||
when "Block"
|
when "Block"
|
||||||
if force_inline
|
if #tok.value > 1 then return nil
|
||||||
return "(:#{concat([@tree_to_nomsu(v, true) for v in *tree.value], "; ")})", true
|
nomsu = inline_expression tok.value
|
||||||
else
|
return nomsu and "(: #{nomsu})"
|
||||||
return ":"..@indent("\n"..concat([@tree_to_nomsu v for v in *tree.value], "\n")), false
|
|
||||||
|
|
||||||
when "FunctionCall"
|
when "FunctionCall"
|
||||||
buff = ""
|
buff = ""
|
||||||
sep = ""
|
for i,bit in ipairs tok.value
|
||||||
inline = true
|
if bit.type == "Word"
|
||||||
line_len = 0
|
if i == 1 or (is_operator(bit) and is_operator(tok.value[i-1]))
|
||||||
for arg in *tree.value
|
buff ..= bit.value
|
||||||
nomsu, arg_inline = @tree_to_nomsu(arg, force_inline)
|
else buff ..= " "..bit.value
|
||||||
if sep == " " and line_len + #nomsu > 80
|
|
||||||
sep = "\n.."
|
|
||||||
unless sep == " " and not arg_inline and nomsu\sub(1,1) == ":"
|
|
||||||
buff ..= sep
|
|
||||||
if arg_inline
|
|
||||||
sep = " "
|
|
||||||
line_len += 1 + #nomsu
|
|
||||||
else
|
else
|
||||||
line_len = 0
|
nomsu = inline_expression bit
|
||||||
inline = false
|
return nil unless nomsu
|
||||||
sep = "\n.."
|
unless i == 1 or bit.type == "Block"
|
||||||
if arg.type == 'FunctionCall'
|
buff ..= " "
|
||||||
if arg_inline
|
buff ..= if bit.type == "FunctionCall"
|
||||||
buff ..= "(#{nomsu})"
|
"("..nomsu..")"
|
||||||
else
|
else nomsu
|
||||||
buff ..= "(..)\n #{@indent nomsu}"
|
return buff
|
||||||
else
|
|
||||||
buff ..= nomsu
|
|
||||||
return buff, inline
|
|
||||||
|
|
||||||
when "Text"
|
|
||||||
buff = "\""
|
|
||||||
longbuff = "\"..\"\n |"
|
|
||||||
inline = true
|
|
||||||
for bit in *tree.value
|
|
||||||
if type(bit) == "string"
|
|
||||||
bit = bit\gsub("\\","\\\\")
|
|
||||||
buff ..= bit\gsub("\n","\\n")\gsub("\"","\\\"")
|
|
||||||
longbuff ..= bit\gsub("\n","\n |")
|
|
||||||
else
|
|
||||||
inside, bit_inline = @tree_to_nomsu(bit, force_inline)
|
|
||||||
inline and= bit_inline
|
|
||||||
buff ..= "\\(#{inside})"
|
|
||||||
longbuff ..= "\\(#{inside})"
|
|
||||||
buff ..= "\""
|
|
||||||
if force_inline or (inline and #buff <= 90)
|
|
||||||
return buff, true
|
|
||||||
else
|
|
||||||
return longbuff, false
|
|
||||||
|
|
||||||
when "List"
|
when "List"
|
||||||
buff = "["
|
bits = {}
|
||||||
longbuff = "[..]\n "
|
for bit in *tok.value
|
||||||
longsep = ""
|
nomsu = inline_expression bit
|
||||||
longline = 0
|
return nil unless nomsu
|
||||||
inline = true
|
insert bits, nomsu
|
||||||
for i,bit in ipairs tree.value
|
return "["..concat(bits, ", ").."]"
|
||||||
nomsu, bit_inline = @tree_to_nomsu(bit, force_inline)
|
|
||||||
inline and= bit_inline
|
|
||||||
if inline
|
|
||||||
if i > 1
|
|
||||||
buff ..= ", "
|
|
||||||
buff ..= nomsu
|
|
||||||
longbuff ..= longsep .. nomsu
|
|
||||||
longline += #nomsu
|
|
||||||
longsep = if bit_inline and longline <= 90
|
|
||||||
", "
|
|
||||||
else "\n "
|
|
||||||
buff ..= "]"
|
|
||||||
if force_inline or (inline and #buff <= 90)
|
|
||||||
return buff, true
|
|
||||||
else
|
|
||||||
return longbuff, false
|
|
||||||
|
|
||||||
when "Dict"
|
when "Dict"
|
||||||
-- TODO: Implement
|
bits = {}
|
||||||
error("Sorry, not yet implemented.")
|
for bit in *tok.value
|
||||||
|
key_nomsu = if bit.dict_key.type == "Word"
|
||||||
when "Number"
|
bit.dict_key.value
|
||||||
return repr(tree.value), true
|
else inline_expression bit.dict_key
|
||||||
|
return nil unless key_nomsu
|
||||||
when "Var"
|
if bit.dict_key.type == "FunctionCall"
|
||||||
return "%#{tree.value}", true
|
key_nomsu = "("..key_nomsu..")"
|
||||||
|
value_nomsu = inline_expression bit.dict_value
|
||||||
when "Word"
|
return nil unless value_nomsu
|
||||||
return tree.value, true
|
insert bits, key_nomsu.."="..value_nomsu
|
||||||
|
return "{"..concat(bits, ", ").."}"
|
||||||
|
when "Text"
|
||||||
|
buff = '"'
|
||||||
|
for bit in *tok.value
|
||||||
|
if type(bit) == 'string'
|
||||||
|
-- Force indented text
|
||||||
|
return nil if bit\find("\n")
|
||||||
|
buff ..= bit\gsub("\\","\\\\")\gsub("\n","\\n")
|
||||||
else
|
else
|
||||||
error("Unknown/unimplemented thingy: #{tree.type}")
|
nomsu = inline_expression(bit)
|
||||||
|
return nil unless nomsu
|
||||||
|
buff ..= if nomsu.type == "Var" or nomsu.type == "List" or nomsu.type == "Dict"
|
||||||
|
"\\"..nomsu
|
||||||
|
else "\\("..nomsu..")"
|
||||||
|
if #buff > max_line then return nil
|
||||||
|
return buff..'"'
|
||||||
|
when "Nomsu"
|
||||||
|
nomsu = inline_expression(tok.value)
|
||||||
|
return nil if not nomsu
|
||||||
|
return "\\("..nomsu..")"
|
||||||
|
when "Number" then tostring(tok.value)
|
||||||
|
when "Var" then "%"..tok.value
|
||||||
|
else return nil
|
||||||
|
|
||||||
|
noeol_expression = (tok)->
|
||||||
|
nomsu = inline_expression(tok)
|
||||||
|
if nomsu and #nomsu < max_line
|
||||||
|
return nomsu
|
||||||
|
switch tok.type
|
||||||
|
when "Block"
|
||||||
|
buff = ":"
|
||||||
|
for line in *tok.value
|
||||||
|
nomsu = expression(line)
|
||||||
|
return nil unless nomsu
|
||||||
|
buff ..= "\n "..@indent(nomsu)
|
||||||
|
return buff
|
||||||
|
when "FunctionCall"
|
||||||
|
nomsu = expression(tok)
|
||||||
|
return nil unless nomsu
|
||||||
|
return "(..)\n "..@indent(nomsu)
|
||||||
|
when "List"
|
||||||
|
buff = "[..]"
|
||||||
|
line = "\n "
|
||||||
|
for bit in *tok.value
|
||||||
|
nomsu = inline_expression bit
|
||||||
|
sep = line == "\n " and "" or ", "
|
||||||
|
if nomsu and #nomsu + #line < max_line
|
||||||
|
line ..= sep..nomsu
|
||||||
|
if #line >= max_line
|
||||||
|
buff ..= line
|
||||||
|
line = "\n "
|
||||||
|
else
|
||||||
|
line ..= sep..expression(bit)
|
||||||
|
buff ..= line
|
||||||
|
line = "\n "
|
||||||
|
if line ~= "\n "
|
||||||
|
buff ..= line
|
||||||
|
return buff
|
||||||
|
when "Dict"
|
||||||
|
buff = "{..}"
|
||||||
|
line = "\n "
|
||||||
|
for bit in *tok.value
|
||||||
|
key_nomsu = inline_expression bit.dict_key
|
||||||
|
return nil unless key_nomsu
|
||||||
|
if bit.dict_key.type == "FunctionCall"
|
||||||
|
key_nomsu = "("..key_nomsu..")"
|
||||||
|
value_nomsu = inline_expression bit.dict_value
|
||||||
|
if value_nomsu and #key_nomsu + #value_nomsu < max_line
|
||||||
|
line ..= key_nomsu.."="..value_nomsu..","
|
||||||
|
if #line >= max_line
|
||||||
|
buff ..= line
|
||||||
|
line = "\n "
|
||||||
|
else
|
||||||
|
line ..= key_nomsu.."="..expression(bit.dict_value)
|
||||||
|
buff ..= line
|
||||||
|
line = "\n "
|
||||||
|
if line ~= "\n "
|
||||||
|
buff ..= line
|
||||||
|
return buff
|
||||||
|
when "Text"
|
||||||
|
buff = '".."\n '
|
||||||
|
for bit in *tok.value
|
||||||
|
if type(bit) == 'string'
|
||||||
|
buff ..= bit\gsub("\\","\\\\")\gsub("\n","\n ")
|
||||||
|
else
|
||||||
|
nomsu = inline_expression(bit)
|
||||||
|
return nil unless nomsu
|
||||||
|
buff ..= if nomsu.type == "Var" or nomsu.type == "List" or nomsu.type == "Dict"
|
||||||
|
"\\"..nomsu
|
||||||
|
else "\\("..nomsu..")"
|
||||||
|
return buff
|
||||||
|
when "Nomsu"
|
||||||
|
nomsu = expression(tok.value)
|
||||||
|
return nil if not nomsu
|
||||||
|
return "\\(..)\n "..@indent(nomsu)
|
||||||
|
when "Comment"
|
||||||
|
if tok.value\find("\n")
|
||||||
|
return "#.."..tok.value\gsub("\n","\n ")
|
||||||
|
else
|
||||||
|
return "#"..tok.value
|
||||||
|
else return inline_expression(tok)
|
||||||
|
|
||||||
|
expression = (tok)->
|
||||||
|
nomsu = inline_expression(tok)
|
||||||
|
if nomsu and #nomsu < max_line
|
||||||
|
return nomsu
|
||||||
|
switch tok.type
|
||||||
|
when "Block"
|
||||||
|
if #tok.value == 1
|
||||||
|
nomsu = noeol_expression(tok.value[1])
|
||||||
|
if nomsu and #(nomsu\match("[^\n]*")) < max_line
|
||||||
|
return ": "..nomsu
|
||||||
|
return noeol_expression(tok)
|
||||||
|
when "FunctionCall"
|
||||||
|
-- The hard task
|
||||||
|
buff = ""
|
||||||
|
for i,bit in ipairs tok.value
|
||||||
|
if bit.type == "Word"
|
||||||
|
if i == 1 or (is_operator(bit) and is_operator(tok.value[i-1])) or buff\sub(-2,-1) == ".."
|
||||||
|
buff ..= bit.value
|
||||||
|
else
|
||||||
|
buff ..= " "..bit.value
|
||||||
|
else
|
||||||
|
nomsu = inline_expression(bit)
|
||||||
|
if nomsu and #nomsu < max_line
|
||||||
|
if bit.type == "FunctionCall"
|
||||||
|
nomsu = "("..nomsu..")"
|
||||||
|
else
|
||||||
|
nomsu = expression(bit)
|
||||||
|
return nil unless nomsu
|
||||||
|
if bit.type == "FunctionCall"
|
||||||
|
nomsu = "(..)\n "..@indent(nomsu)
|
||||||
|
if i < #tok.value
|
||||||
|
nomsu ..= "\n.."
|
||||||
|
unless i == 1 or bit.type == "Block"
|
||||||
|
buff ..= " "
|
||||||
|
buff ..= nomsu
|
||||||
|
return buff
|
||||||
|
when "File"
|
||||||
|
lines = {}
|
||||||
|
for line in *tree.value
|
||||||
|
nomsu = expression(line)
|
||||||
|
assert nomsu, "Failed to produce output for:\n#{colored.yellow line.src}"
|
||||||
|
|
||||||
|
insert lines, nomsu
|
||||||
|
return concat lines, "\n"
|
||||||
|
when "Comment"
|
||||||
|
if tok.value\find("\n")
|
||||||
|
return "#.."..tok.value\gsub("\n","\n ")
|
||||||
|
else
|
||||||
|
return "#"..tok.value
|
||||||
|
else return noeol_expression(tok)
|
||||||
|
|
||||||
|
return expression(tree)
|
||||||
|
|
||||||
|
|
||||||
value_to_nomsu: (value)=>
|
value_to_nomsu: (value)=>
|
||||||
switch type(value)
|
switch type(value)
|
||||||
|
Loading…
Reference in New Issue
Block a user