diff --git a/moonscript/compile.lua b/moonscript/compile.lua index ff53509..98e0f44 100644 --- a/moonscript/compile.lua +++ b/moonscript/compile.lua @@ -18,6 +18,19 @@ do end local concat, insert = table.concat, table.insert local pos_to_line, get_closest_line, trim = util.pos_to_line, util.get_closest_line, util.trim +local mtype = util.moon.type +local insert_many +insert_many = function(tbl, ...) + local i = #tbl + 1 + local _list_0 = { + ... + } + for _index_0 = 1, #_list_0 do + local val = _list_0[_index_0] + tbl[i] = val + i = i + 1 + end +end local Line Line = (function() local _parent_0 = nil @@ -53,19 +66,41 @@ Line = (function() return nil end, render = function(self) - local buff = { } - for i = 1, #self do - local c = self[i] - insert(buff, (function() - if util.moon.type(c) == Block then - c:bubble() - return c:render() - else - return c - end - end)()) + local parts = { } + local current = { } + local add_current + add_current = function() + return insert(parts, table.concat(current)) end - return concat(buff) + local _list_0 = self + for _index_0 = 1, #_list_0 do + local chunk = _list_0[_index_0] + local _exp_0 = mtype(chunk) + if Block == _exp_0 then + local _list_1 = { + chunk:render() + } + for _index_1 = 1, #_list_1 do + local block_chunk = _list_1[_index_1] + if "string" == type(block_chunk) then + insert(current, block_chunk) + else + add_current() + insert(parts, block_chunk) + current = { } + end + end + else + insert(current, chunk) + end + end + if #current > 0 then + add_current() + end + return unpack(parts) + end, + __tostring = function(self) + return "Line<" .. tostring(self:render()) .. ">" end } _base_0.__index = _base_0 @@ -103,6 +138,7 @@ Line = (function() return _class_0 end)() Block = (function() + local flatten local _parent_0 = nil local _base_0 = { header = "do", @@ -251,8 +287,8 @@ Block = (function() end end end, - add_line_text = function(self, text) - return insert(self._lines, text) + add_raw = function(self, item) + return insert(self._lines, item) end, append_line_table = function(self, sub_table, offset) offset = offset + self.current_line @@ -281,62 +317,48 @@ Block = (function() end end, add = function(self, line) - local t = util.moon.type(line) - if t == "string" then - self:add_line_text(line) - elseif t == Block then - self:add(self:line(line)) - elseif t == Line then - self:add_line_tables(line) - self:add_line_text(line:render()) - self.current_line = self.current_line + 1 + local _exp_0 = util.moon.type(line) + if "string" == _exp_0 then + return insert(self._lines, line) + elseif Block == _exp_0 then + return insert_many(self._lines, line:render()) + elseif Line == _exp_0 then + return insert_many(self._lines, line:render()) else - error("Adding unknown item") - end - return nil - end, - _insert_breaks = function(self) - for i = 1, #self._lines - 1 do - local left, right = self._lines[i], self._lines[i + 1] - local lc = left:sub(-1) - if (lc == ")" or lc == "]") and right:sub(1, 1) == "(" then - self._lines[i] = self._lines[i] .. ";" - end + return error("Adding unknown item") end end, render = function(self) - local flatten - flatten = function(line) - if type(line) == "string" then - return line + local out = { + flatten(self.header) + } + local lines = (function() + local _accum_0 = { } + local _len_0 = 0 + local _list_0 = self._lines + for _index_0 = 1, #_list_0 do + local line = _list_0[_index_0] + local _value_0 = flatten(line) + if _value_0 ~= nil then + _len_0 = _len_0 + 1 + _accum_0[_len_0] = _value_0 + end + end + return _accum_0 + end)() + if self.next then + insert(out, lines) + insert_many(out, self.next:render()) + else + local footer = flatten(self.footer) + if #lines == 0 and #out == 1 then + out[1] = out[1] .. (" " .. footer) else - return line:render() + insert(out, lines) + insert(out, footer) end end - local header = flatten(self.header) - if #self._lines == 0 then - local footer = flatten(self.footer) - return concat({ - header, - footer - }, " ") - end - local indent = indent_char:rep(self.indent) - if not self.delim then - self:_insert_breaks() - end - local body = indent .. concat(self._lines, (self.delim or "") .. "\n" .. indent) - return concat({ - header, - body, - indent_char:rep(self.indent - 1) .. (function() - if self.next then - return self.next:render() - else - return flatten(self.footer) - end - end)() - }, "\n") + return unpack(out) end, block = function(self, header, footer) return Block(self, header, footer) @@ -492,11 +514,50 @@ Block = (function() end }) _base_0.__class = _class_0 + local self = _class_0 + flatten = function(line) + local _exp_0 = mtype(line) + if Line == _exp_0 then + return line:render() + else + return line + end + end if _parent_0 and _parent_0.__inherited then _parent_0.__inherited(_parent_0, _class_0) end return _class_0 end)() +local flatten_lines +flatten_lines = function(lines, indent, buffer) + if indent == nil then + indent = nil + end + if buffer == nil then + buffer = { } + end + for i = 1, #lines do + local l = lines[i] + local _exp_0 = type(l) + if "string" == _exp_0 then + if indent then + insert(buffer, indent) + end + insert(buffer, l) + if "string" == type(lines[i + 1]) then + local lc = l:sub(-1) + if (lc == ")" or lc == "]") and lines[i + 1]:sub(1, 1) == "(" then + insert(buffer, ";") + end + end + insert(buffer, "\n") + local last = l + elseif "table" == _exp_0 then + flatten_lines(l, indent and indent .. indent_char or indent_char, buffer) + end + end + return buffer +end RootBlock = (function() local _parent_0 = Block local _base_0 = { @@ -504,8 +565,11 @@ RootBlock = (function() return "RootBlock<>" end, render = function(self) - self:_insert_breaks() - return concat(self._lines, "\n") + local buffer = flatten_lines(self._lines) + if buffer[#buffer] == "\n" then + buffer[#buffer] = nil + end + return table.concat(buffer) end } _base_0.__index = _base_0 diff --git a/moonscript/compile.moon b/moonscript/compile.moon index 4b3b070..f5648f4 100644 --- a/moonscript/compile.moon +++ b/moonscript/compile.moon @@ -16,9 +16,17 @@ import ntype from require "moonscript.types" import concat, insert from table import pos_to_line, get_closest_line, trim from util +mtype = util.moon.type + export tree, value, format_error export Block, RootBlock +insert_many = (tbl, ...) -> + i = #tbl + 1 + for val in *{...} + tbl[i] = val + i += 1 + -- buffer for building up a line class Line _append_single: (item) => @@ -37,16 +45,34 @@ class Line @_append_single item for item in *{...} nil + -- todo: remove concats from here render: => - buff = {} - for i = 1,#self - c = self[i] - insert buff, if util.moon.type(c) == Block - c\bubble! - c\render! - else - c - concat buff + parts = {} + current = {} + + add_current = -> + insert parts, table.concat current + + for chunk in *@ + switch mtype chunk + when Block + for block_chunk in *{chunk\render!} + if "string" == type block_chunk + insert current, block_chunk + else + add_current! + insert parts, block_chunk + current = {} + else + insert current, chunk + + if #current > 0 + add_current! + + unpack parts + + + __tostring: => "Line<#{@render!}>" class Block header: "do" @@ -168,8 +194,8 @@ class Block @_posmap[@current_line] = @last_pos -- add raw text as new line - add_line_text: (text) => - insert @_lines, text + add_raw: (item) => + insert @_lines, item append_line_table: (sub_table, offset) => offset = offset + @current_line @@ -193,52 +219,43 @@ class Block -- add a line object add: (line) => - t = util.moon.type line - - if t == "string" - @add_line_text line - elseif t == Block - @add @line line - elseif t == Line - @add_line_tables line - @add_line_text line\render! - @current_line += 1 - else - error "Adding unknown item" - nil - - _insert_breaks: => - for i = 1, #@_lines - 1 - left, right = @_lines[i], @_lines[i+1] - lc = left\sub(-1) - if (lc == ")" or lc == "]") and right\sub(1,1) == "(" - @_lines[i] = @_lines[i]..";" - - render: => - flatten = (line) -> - if type(line) == "string" - line + -- print "adding", line + switch util.moon.type line + when "string" + insert @_lines, line + when Block + insert_many @_lines, line\render! + when Line + insert_many @_lines, line\render! else + error "Adding unknown item" + + flatten = (line) -> + switch mtype line + when Line line\render! + else + line - header = flatten @header + -- todo: pass in buffer as argument + render: => + out = { flatten @header } - if #@_lines == 0 + lines = for line in *@_lines + flatten line + + if @next + insert out, lines + insert_many out, @next\render! + else footer = flatten @footer - return concat {header, footer}, " " + if #lines == 0 and #out == 1 + out[1] ..= " " ..footer + else + insert out, lines + insert out, footer - indent = indent_char\rep @indent - - -- inject semicolons for ambiguous lines - if not @delim then @_insert_breaks! - - body = indent .. concat @_lines, (@delim or "") .. "\n" .. indent - - concat { - header, - body, - indent_char\rep(@indent - 1) .. if @next then @next\render! else flatten @footer - }, "\n" + unpack out block: (header, footer) => Block self, header, footer @@ -299,6 +316,28 @@ class Block @_lines = {} @stms fn lines + +flatten_lines = (lines, indent=nil, buffer={}) -> + for i = 1, #lines + l = lines[i] + switch type l + when "string" + insert buffer, indent if indent + insert buffer, l + + -- insert breaks between ambiguous statements + if "string" == type lines[i + 1] + lc = l\sub(-1) + if (lc == ")" or lc == "]") and lines[i + 1]\sub(1,1) == "(" + insert buffer, ";" + + insert buffer, "\n" + last = l + when "table" + flatten_lines l, indent and indent .. indent_char or indent_char, buffer + + buffer + class RootBlock extends Block new: (...) => @root = self @@ -307,8 +346,13 @@ class RootBlock extends Block __tostring: => "RootBlock<>" render: => - @_insert_breaks! - concat @_lines, "\n" + -- @_insert_breaks! + -- concat @_lines, "\n" + + -- print util.dump @_lines + buffer = flatten_lines @_lines + buffer[#buffer] = nil if buffer[#buffer] == "\n" + table.concat buffer format_error = (msg, pos, file_str) -> line = pos_to_line file_str, pos diff --git a/moonscript/compile/statement.lua b/moonscript/compile/statement.lua index e773203..8eb383c 100644 --- a/moonscript/compile/statement.lua +++ b/moonscript/compile/statement.lua @@ -19,7 +19,7 @@ line_compile = { local _list_0 = node[2] for _index_0 = 1, #_list_0 do local line = _list_0[_index_0] - self:add(line) + self:add_raw(line) end end, declare = function(self, node) diff --git a/moonscript/compile/statement.moon b/moonscript/compile/statement.moon index 00f9f38..9fcd9e3 100644 --- a/moonscript/compile/statement.moon +++ b/moonscript/compile/statement.moon @@ -18,7 +18,7 @@ line_compile = lines: (node) => for line in *node[2] - @add line + @add_raw line declare: (node) => names = node[2] diff --git a/moonscript/compile/value.lua b/moonscript/compile/value.lua index 4479b7a..d8fce5f 100644 --- a/moonscript/compile/value.lua +++ b/moonscript/compile/value.lua @@ -8,6 +8,7 @@ do ntype = _table_0.ntype end local concat, insert = table.concat, table.insert +local table_delim = "," value_compile = { exp = function(self, node) local _comp @@ -226,7 +227,6 @@ value_compile = { local _, items = unpack(node) do local _with_0 = self:block("{", "}") - _with_0.delim = "," local format_line format_line = function(tuple) if #tuple == 2 then @@ -253,10 +253,13 @@ value_compile = { end end if items then - local _list_0 = items - for _index_0 = 1, #_list_0 do - local line = _list_0[_index_0] - _with_0:add(format_line(line)) + local count = #items + for i, tuple in ipairs(items) do + local line = format_line(tuple) + if not (count == i) then + line:append(table_delim) + end + _with_0:add(line) end end return _with_0 diff --git a/moonscript/compile/value.moon b/moonscript/compile/value.moon index 0e6cdc9..c9d43c9 100644 --- a/moonscript/compile/value.moon +++ b/moonscript/compile/value.moon @@ -11,6 +11,8 @@ import concat, insert from table export value_compile +table_delim = "," + value_compile = -- list of values separated by binary operators exp: (node) => @@ -129,8 +131,6 @@ value_compile = table: (node) => _, items = unpack node with @block "{", "}" - .delim = "," - format_line = (tuple) -> if #tuple == 2 key, value = unpack tuple @@ -152,7 +152,11 @@ value_compile = @line \value tuple[1] if items - \add format_line line for line in *items + count = #items + for i, tuple in ipairs items + line = format_line tuple + line\append table_delim unless count == i + \add line minus: (node) => @line "-", @value node[2] diff --git a/moonscript/transform.moon b/moonscript/transform.moon index 7a839d4..b44330d 100644 --- a/moonscript/transform.moon +++ b/moonscript/transform.moon @@ -210,7 +210,7 @@ Statement = Transformer { transformed or node continue: (node) => - continue_name = @send"continue" + continue_name = @send "continue" error "continue must be inside of a loop" unless continue_name build.group { build.assign_one continue_name, "true"