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 [repeat while %condition %body] to code:
|
||||
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 = ".."
|
||||
while \(%condition as lua) do
|
||||
\(%body as lua statements)\
|
||||
|
419
nomsu.lua
419
nomsu.lua
@ -486,160 +486,331 @@ do
|
||||
end
|
||||
return lua_thunk()
|
||||
end,
|
||||
tree_to_nomsu = function(self, tree, force_inline)
|
||||
if force_inline == nil then
|
||||
force_inline = false
|
||||
tree_to_nomsu = function(self, tree, indentation, max_line, expr_type)
|
||||
if indentation == nil then
|
||||
indentation = ""
|
||||
end
|
||||
assert(tree, "No tree provided.")
|
||||
if not tree.type then
|
||||
error("Invalid tree: " .. tostring(repr(tree)))
|
||||
if max_line == nil then
|
||||
max_line = 80
|
||||
end
|
||||
local _exp_0 = tree.type
|
||||
if "File" == _exp_0 then
|
||||
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
|
||||
if expr_type == nil then
|
||||
expr_type = nil
|
||||
end
|
||||
return _accum_0
|
||||
end)(), "\n"), false
|
||||
elseif "Nomsu" == _exp_0 then
|
||||
local inside, inline = self:tree_to_nomsu(tree.value, force_inline)
|
||||
return "\\" .. tostring(inside), inline
|
||||
elseif "Comment" == _exp_0 then
|
||||
if tree.value:find("\n") then
|
||||
return "#.." .. tostring(self:indent(tree.value)), false
|
||||
else
|
||||
return "#" .. tostring(tree.value), false
|
||||
assert(tree, "No tree provided to tree_to_nomsu.")
|
||||
assert(tree.type, "Invalid tree: " .. tostring(repr(tree)))
|
||||
local join_lines
|
||||
join_lines = function(lines)
|
||||
for _index_0 = 1, #lines do
|
||||
local line = lines[_index_0]
|
||||
if #indentation + #line > max_line then
|
||||
return nil
|
||||
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
|
||||
return _accum_0
|
||||
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
|
||||
return concat(lines, "\n" .. indentation)
|
||||
end
|
||||
return _accum_0
|
||||
end)(), "\n")), false
|
||||
local is_operator
|
||||
is_operator = function(tok)
|
||||
return tok and tok.type == "Word" and OPERATOR_CHAR:match(tok.value)
|
||||
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
|
||||
local buff = ""
|
||||
local sep = ""
|
||||
local inline = true
|
||||
local line_len = 0
|
||||
local _list_0 = tree.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)
|
||||
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])) then
|
||||
buff = buff .. bit.value
|
||||
else
|
||||
line_len = 0
|
||||
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))
|
||||
buff = buff .. (" " .. bit.value)
|
||||
end
|
||||
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
|
||||
return buff, inline
|
||||
elseif "Text" == _exp_0 then
|
||||
local buff = "\""
|
||||
local longbuff = "\"..\"\n |"
|
||||
local inline = true
|
||||
local _list_0 = tree.value
|
||||
return buff
|
||||
elseif "List" == _exp_0 then
|
||||
local bits = { }
|
||||
local _list_0 = tok.value
|
||||
for _index_0 = 1, #_list_0 do
|
||||
local bit = _list_0[_index_0]
|
||||
if type(bit) == "string" then
|
||||
bit = bit:gsub("\\", "\\\\")
|
||||
buff = buff .. bit:gsub("\n", "\\n"):gsub("\"", "\\\"")
|
||||
longbuff = longbuff .. bit:gsub("\n", "\n |")
|
||||
local nomsu = inline_expression(bit)
|
||||
if not (nomsu) then
|
||||
return nil
|
||||
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
|
||||
local inside, bit_inline = self:tree_to_nomsu(bit, force_inline)
|
||||
inline = inline and bit_inline
|
||||
buff = buff .. "\\(" .. tostring(inside) .. ")"
|
||||
longbuff = longbuff .. "\\(" .. tostring(inside) .. ")"
|
||||
key_nomsu = inline_expression(bit.dict_key)
|
||||
end
|
||||
if not (key_nomsu) then
|
||||
return nil
|
||||
end
|
||||
buff = buff .. "\""
|
||||
if force_inline or (inline and #buff <= 90) then
|
||||
return buff, true
|
||||
if bit.dict_key.type == "FunctionCall" then
|
||||
key_nomsu = "(" .. key_nomsu .. ")"
|
||||
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
|
||||
return longbuff, false
|
||||
local 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
|
||||
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
|
||||
local buff = "["
|
||||
local longbuff = "[..]\n "
|
||||
local longsep = ""
|
||||
local longline = 0
|
||||
local inline = true
|
||||
for i, bit in ipairs(tree.value) do
|
||||
local nomsu, bit_inline = self:tree_to_nomsu(bit, force_inline)
|
||||
inline = inline and bit_inline
|
||||
if inline then
|
||||
if i > 1 then
|
||||
buff = buff .. ", "
|
||||
local buff = "[..]"
|
||||
local line = "\n "
|
||||
local _list_0 = tok.value
|
||||
for _index_0 = 1, #_list_0 do
|
||||
local bit = _list_0[_index_0]
|
||||
nomsu = inline_expression(bit)
|
||||
local sep = line == "\n " and "" or ", "
|
||||
if nomsu and #nomsu + #line < max_line then
|
||||
line = line .. (sep .. nomsu)
|
||||
if #line >= max_line then
|
||||
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
|
||||
buff = buff .. nomsu
|
||||
end
|
||||
longbuff = longbuff .. (longsep .. nomsu)
|
||||
longline = longline + #nomsu
|
||||
if bit_inline and longline <= 90 then
|
||||
longsep = ", "
|
||||
end
|
||||
return buff
|
||||
elseif "File" == _exp_0 then
|
||||
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
|
||||
longsep = "\n "
|
||||
return "#" .. tok.value
|
||||
end
|
||||
end
|
||||
buff = buff .. "]"
|
||||
if force_inline or (inline and #buff <= 90) then
|
||||
return buff, true
|
||||
else
|
||||
return longbuff, false
|
||||
return noeol_expression(tok)
|
||||
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
|
||||
return expression(tree)
|
||||
end,
|
||||
value_to_nomsu = function(self, 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}")
|
||||
return lua_thunk!
|
||||
|
||||
tree_to_nomsu: (tree, force_inline=false)=>
|
||||
-- Return <nomsu code>, <is safe for inline use>
|
||||
assert tree, "No tree provided."
|
||||
if not tree.type
|
||||
error "Invalid tree: #{repr(tree)}"
|
||||
switch tree.type
|
||||
when "File"
|
||||
return concat([@tree_to_nomsu(v, force_inline) for v in *tree.value], "\n"), false
|
||||
tree_to_nomsu: (tree, indentation="", max_line=80, expr_type=nil)=>
|
||||
-- Convert a tree into nomsu code that satisfies the max line requirement or nil
|
||||
-- if that's not possible
|
||||
-- expr_type is either:
|
||||
-- nil for code that goes at the top level and can contain anything
|
||||
-- "noeol" for code that can contain anything except an end-of-line component
|
||||
-- like a colon (i.e. it already occurs after a colon on the same line)
|
||||
-- "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"
|
||||
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
|
||||
is_operator = (tok)-> tok and tok.type == "Word" and OPERATOR_CHAR\match(tok.value)
|
||||
|
||||
local inline_expression, noeol_expression, expression
|
||||
inline_expression = (tok)->
|
||||
switch tok.type
|
||||
when "Block"
|
||||
if force_inline
|
||||
return "(:#{concat([@tree_to_nomsu(v, true) for v in *tree.value], "; ")})", true
|
||||
else
|
||||
return ":"..@indent("\n"..concat([@tree_to_nomsu v for v in *tree.value], "\n")), false
|
||||
|
||||
if #tok.value > 1 then return nil
|
||||
nomsu = inline_expression tok.value
|
||||
return nomsu and "(: #{nomsu})"
|
||||
when "FunctionCall"
|
||||
buff = ""
|
||||
sep = ""
|
||||
inline = true
|
||||
line_len = 0
|
||||
for arg in *tree.value
|
||||
nomsu, arg_inline = @tree_to_nomsu(arg, force_inline)
|
||||
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
|
||||
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]))
|
||||
buff ..= bit.value
|
||||
else buff ..= " "..bit.value
|
||||
else
|
||||
line_len = 0
|
||||
inline = false
|
||||
sep = "\n.."
|
||||
if arg.type == 'FunctionCall'
|
||||
if arg_inline
|
||||
buff ..= "(#{nomsu})"
|
||||
else
|
||||
buff ..= "(..)\n #{@indent nomsu}"
|
||||
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
|
||||
|
||||
nomsu = inline_expression bit
|
||||
return nil unless nomsu
|
||||
unless i == 1 or bit.type == "Block"
|
||||
buff ..= " "
|
||||
buff ..= if bit.type == "FunctionCall"
|
||||
"("..nomsu..")"
|
||||
else nomsu
|
||||
return buff
|
||||
when "List"
|
||||
buff = "["
|
||||
longbuff = "[..]\n "
|
||||
longsep = ""
|
||||
longline = 0
|
||||
inline = true
|
||||
for i,bit in ipairs tree.value
|
||||
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
|
||||
|
||||
bits = {}
|
||||
for bit in *tok.value
|
||||
nomsu = inline_expression bit
|
||||
return nil unless nomsu
|
||||
insert bits, nomsu
|
||||
return "["..concat(bits, ", ").."]"
|
||||
when "Dict"
|
||||
-- TODO: Implement
|
||||
error("Sorry, not yet implemented.")
|
||||
|
||||
when "Number"
|
||||
return repr(tree.value), true
|
||||
|
||||
when "Var"
|
||||
return "%#{tree.value}", true
|
||||
|
||||
when "Word"
|
||||
return tree.value, true
|
||||
|
||||
bits = {}
|
||||
for bit in *tok.value
|
||||
key_nomsu = if bit.dict_key.type == "Word"
|
||||
bit.dict_key.value
|
||||
else 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
|
||||
return nil unless value_nomsu
|
||||
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
|
||||
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)=>
|
||||
switch type(value)
|
||||
|
Loading…
Reference in New Issue
Block a user