aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBruce Hill <bitbucket@bruce-hill.com>2018-01-17 16:37:05 -0800
committerBruce Hill <bitbucket@bruce-hill.com>2018-01-17 16:37:27 -0800
commit8bbebb87351c2ad0684d785cd4fb02ef579707fc (patch)
treea463bac942c65f95e1b1443fd999de5a8b928e9d
parent64865aa5961bba2bafa8ce5a9e775cc795c40dc7 (diff)
Completely fixed/reworked tree_to_nomsu, and it's okay right now.
-rw-r--r--lib/control_flow.nom3
-rw-r--r--nomsu.lua433
-rwxr-xr-xnomsu.moon317
3 files changed, 515 insertions, 238 deletions
diff --git a/lib/control_flow.nom b/lib/control_flow.nom
index 288fb4d..7455ee9 100644
--- a/lib/control_flow.nom
+++ b/lib/control_flow.nom
@@ -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)\
diff --git a/nomsu.lua b/nomsu.lua
index 0df32fb..76bc342 100644
--- a/nomsu.lua
+++ b/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
- end
- assert(tree, "No tree provided.")
- if not tree.type then
- error("Invalid tree: " .. tostring(repr(tree)))
- 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
+ tree_to_nomsu = function(self, tree, indentation, max_line, expr_type)
+ if indentation == nil then
+ indentation = ""
+ end
+ if max_line == nil then
+ max_line = 80
+ end
+ if expr_type == nil then
+ expr_type = nil
+ end
+ 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
+ end
+ return concat(lines, "\n" .. indentation)
+ end
+ 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 = ""
+ 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
+ buff = buff .. (" " .. bit.value)
+ end
+ else
+ 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
+ elseif "List" == _exp_0 then
+ local bits = { }
+ local _list_0 = tok.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
+ local bit = _list_0[_index_0]
+ local nomsu = inline_expression(bit)
+ if not (nomsu) then
+ return nil
+ end
+ insert(bits, nomsu)
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
+ 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
+ key_nomsu = inline_expression(bit.dict_key)
+ end
+ 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 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
+ 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 "#" .. tostring(tree.value), false
+ 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
+ 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
- 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
+ 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 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
- return _accum_0
- end)(), "\n")), false
- end
- 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
+ if line ~= "\n " then
+ buff = buff .. line
end
- if arg_inline then
- sep = " "
- line_len = line_len + (1 + #nomsu)
- else
- line_len = 0
- inline = false
- sep = "\n.."
+ 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
- if arg.type == 'FunctionCall' then
- if arg_inline then
- buff = buff .. "(" .. tostring(nomsu) .. ")"
+ 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
- buff = buff .. "(..)\n " .. tostring(self:indent(nomsu))
+ 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
- else
- buff = buff .. nomsu
end
- end
- return buff, inline
- elseif "Text" == _exp_0 then
- local buff = "\""
- local longbuff = "\"..\"\n |"
- local inline = true
- local _list_0 = tree.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 |")
+ 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
- local inside, bit_inline = self:tree_to_nomsu(bit, force_inline)
- inline = inline and bit_inline
- buff = buff .. "\\(" .. tostring(inside) .. ")"
- longbuff = longbuff .. "\\(" .. tostring(inside) .. ")"
+ return "#" .. tok.value
end
- end
- buff = buff .. "\""
- if force_inline or (inline and #buff <= 90) then
- return buff, true
else
- return longbuff, false
+ return inline_expression(tok)
end
- 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 .. ", "
+ 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
- buff = buff .. nomsu
end
- longbuff = longbuff .. (longsep .. nomsu)
- longline = longline + #nomsu
- if bit_inline and longline <= 90 then
- longsep = ", "
+ 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)
diff --git a/nomsu.moon b/nomsu.moon
index bc7aa22..3594246 100755
--- a/nomsu.moon
+++ b/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
-
- 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
-
- 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
-
- 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
- else
- line_len = 0
- inline = false
- sep = "\n.."
- if arg.type == 'FunctionCall'
- if arg_inline
- buff ..= "(#{nomsu})"
+ 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)
+
+ 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 #tok.value > 1 then return nil
+ nomsu = inline_expression tok.value
+ return nomsu and "(: #{nomsu})"
+ when "FunctionCall"
+ 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]))
+ buff ..= bit.value
+ else buff ..= " "..bit.value
+ else
+ 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"
+ bits = {}
+ for bit in *tok.value
+ nomsu = inline_expression bit
+ return nil unless nomsu
+ insert bits, nomsu
+ return "["..concat(bits, ", ").."]"
+ when "Dict"
+ 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
- buff ..= "(..)\n #{@indent nomsu}"
+ 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
- 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 |")
+ 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
- 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"
- 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
-
- when "Dict"
- -- TODO: Implement
- error("Sorry, not yet implemented.")
-
- when "Number"
- return repr(tree.value), true
-
- when "Var"
- return "%#{tree.value}", true
+ return "#"..tok.value
+ else return noeol_expression(tok)
- when "Word"
- return tree.value, true
+ return expression(tree)
- else
- error("Unknown/unimplemented thingy: #{tree.type}")
value_to_nomsu: (value)=>
switch type(value)