mirror of
https://github.com/leafo/moonscript.git
synced 2024-11-22 02:44:23 +00:00
conversion of line output
This commit is contained in:
parent
a80f8f875e
commit
d66b7f3af5
@ -7,16 +7,71 @@ require("moonscript.compile.line")
|
||||
require("moonscript.compile.value")
|
||||
local ntype = data.ntype
|
||||
local concat, insert = table.concat, table.insert
|
||||
local Block
|
||||
Block = (function(_parent_0)
|
||||
local Line
|
||||
Line = (function(_parent_0)
|
||||
local _base_0 = {
|
||||
_append_single = function(self, item)
|
||||
if util.moon.type(item) == Line then
|
||||
local _item_0 = item
|
||||
for _index_0=1,#_item_0 do
|
||||
local value = _item_0[_index_0]
|
||||
self:_append_single(value)
|
||||
end
|
||||
else
|
||||
insert(self, item)
|
||||
end
|
||||
return nil
|
||||
end,
|
||||
append_list = function(self, items, delim)
|
||||
for i = 1, #items do
|
||||
self:_append_single(items[i])
|
||||
if i < #items then
|
||||
insert(self, delim)
|
||||
end
|
||||
end
|
||||
end,
|
||||
append = function(self, ...)
|
||||
local _item_0 = { ... }
|
||||
for _index_0=1,#_item_0 do
|
||||
local item = _item_0[_index_0]
|
||||
self:_append_single(item)
|
||||
end
|
||||
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
|
||||
return c:render()
|
||||
else
|
||||
return c
|
||||
end
|
||||
end)())
|
||||
end
|
||||
return concat(buff)
|
||||
end
|
||||
}
|
||||
_base_0.__index = _base_0
|
||||
local _class_0 = setmetatable({ __init = function(self, ...)
|
||||
if _parent_0 then
|
||||
return _parent_0.__init(self, ...)
|
||||
end
|
||||
end }, { __index = _base_0, __call = function(mt, ...)
|
||||
local self = setmetatable({}, _base_0)
|
||||
mt.__init(self, ...)
|
||||
return self
|
||||
end })
|
||||
_base_0.__class = _class_0
|
||||
return _class_0
|
||||
end)()
|
||||
local Block_
|
||||
Block_ = (function(_parent_0)
|
||||
local _base_0 = {
|
||||
line_table = function(self) return self._posmap end,
|
||||
set = function(self, name, value) self._state[name] = value end,
|
||||
get = function(self, name) return self._state[name] end,
|
||||
set_indent = function(self, depth)
|
||||
self.indent = depth
|
||||
self.lead = indent_char:rep(self.indent)
|
||||
end,
|
||||
declare = function(self, names)
|
||||
local undeclared = (function()
|
||||
local _moon_0 = {}
|
||||
@ -52,36 +107,61 @@ Block = (function(_parent_0)
|
||||
end
|
||||
return name
|
||||
end,
|
||||
mark_pos = function(self, node) self._posmap[#self._lines + 1] = node[-1] end,
|
||||
add_lines = function(self, lines)
|
||||
local _item_0 = lines
|
||||
for _index_0=1,#_item_0 do
|
||||
local line = _item_0[_index_0]
|
||||
insert(self._lines, line)
|
||||
end
|
||||
return nil
|
||||
init_free_var = function(self, prefix, value)
|
||||
local name = self:free_name(prefix, true)
|
||||
self:stm({ "assign", { name }, { value } })
|
||||
return name
|
||||
end,
|
||||
add_line = function(self, ...)
|
||||
local args = { ... }
|
||||
local line
|
||||
if #args == 1 then
|
||||
line = args[1]
|
||||
mark_pos = function(self, node) self._posmap[#self._lines + 1] = node[-1] end,
|
||||
add_line_text = function(self, text)
|
||||
self.line_offset = self.line_offset + 1
|
||||
return insert(self._lines, text)
|
||||
end,
|
||||
add = function(self, line)
|
||||
local t = util.moon.type(line)
|
||||
if t == "string" then
|
||||
return self:add_line_text(line)
|
||||
elseif t == Block then
|
||||
return self:add(self:line(line))
|
||||
elseif t == Line then
|
||||
return self:add_line_text(line:render())
|
||||
else
|
||||
line = concat(args, " ")
|
||||
return error("Adding unknown item")
|
||||
end
|
||||
return insert(self._lines, line)
|
||||
end,
|
||||
push = function(self) self._names = setmetatable({ }, { __index = self._names }) end,
|
||||
pop = function(self) self._names = getmetatable(self._names).__index end,
|
||||
format = function(self, ...) return pretty({ ... }, self.lead) end,
|
||||
render = function(self)
|
||||
local out = pretty(self._lines, self.lead)
|
||||
if self.indent > 0 then
|
||||
out = indent_char .. out
|
||||
local flatten
|
||||
flatten = function(line)
|
||||
if type(line) == "string" then
|
||||
return line
|
||||
else
|
||||
return line:render()
|
||||
end
|
||||
end
|
||||
local header = flatten(self.header)
|
||||
if #self._lines == 0 then
|
||||
local footer = flatten(self.footer)
|
||||
return(concat({ header, footer }, " "))
|
||||
end
|
||||
local body = pretty(self._lines, indent_char:rep(self.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")
|
||||
end,
|
||||
block = function(self, header, footer) return Block(self, header, footer) end,
|
||||
line = function(self, ...)
|
||||
do
|
||||
local _with_0 = Line()
|
||||
_with_0:append(...)
|
||||
return _with_0
|
||||
end
|
||||
return out
|
||||
end,
|
||||
block = function(self, node) return Block(self) end,
|
||||
is_stm = function(self, node) return line_compile[ntype(node)] ~= nil end,
|
||||
is_value = function(self, node)
|
||||
local t = ntype(node)
|
||||
@ -117,12 +197,12 @@ Block = (function(_parent_0)
|
||||
if has_value(node) then
|
||||
return self:stm({ "assign", { "_" }, { node } })
|
||||
else
|
||||
return self:add_line(self:value(node))
|
||||
return self:add(self:value(node))
|
||||
end
|
||||
else
|
||||
local out = fn(self, node, ...)
|
||||
if out then
|
||||
return self:add_line(out)
|
||||
return self:add(out)
|
||||
end
|
||||
end
|
||||
end,
|
||||
@ -166,16 +246,25 @@ Block = (function(_parent_0)
|
||||
end
|
||||
}
|
||||
_base_0.__index = _base_0
|
||||
local _class_0 = setmetatable({ __init = function(self, parent)
|
||||
self.parent = parent
|
||||
self:set_indent(self.parent and self.parent.indent + 1 or 0)
|
||||
local _class_0 = setmetatable({ __init = function(self, parent, header, footer)
|
||||
self.parent, self.header, self.footer = parent, header, footer
|
||||
if not self.header then
|
||||
self.header = "do"
|
||||
end
|
||||
if not self.footer then
|
||||
self.footer = "end"
|
||||
end
|
||||
self.line_offset = 1
|
||||
self._lines = { }
|
||||
self._posmap = { }
|
||||
self._names = { }
|
||||
self._state = { }
|
||||
if self.parent then
|
||||
self.indent = self.parent.indent + 1
|
||||
setmetatable(self._state, { __index = self.parent._state })
|
||||
return setmetatable(self._names, { __index = self.parent._names })
|
||||
else
|
||||
self.indent = 0
|
||||
end
|
||||
end }, { __index = _base_0, __call = function(mt, ...)
|
||||
local self = setmetatable({}, _base_0)
|
||||
@ -185,8 +274,28 @@ Block = (function(_parent_0)
|
||||
_base_0.__class = _class_0
|
||||
return _class_0
|
||||
end)()
|
||||
local RootBlock
|
||||
RootBlock = (function(_parent_0)
|
||||
local _base_0 = { render = function(self) return concat(self._lines, "\n") end }
|
||||
_base_0.__index = _base_0
|
||||
if _parent_0 then
|
||||
setmetatable(_base_0, getmetatable(_parent_0).__index)
|
||||
end
|
||||
local _class_0 = setmetatable({ __init = function(self, ...)
|
||||
if _parent_0 then
|
||||
return _parent_0.__init(self, ...)
|
||||
end
|
||||
end }, { __index = _base_0, __call = function(mt, ...)
|
||||
local self = setmetatable({}, _base_0)
|
||||
mt.__init(self, ...)
|
||||
return self
|
||||
end })
|
||||
_base_0.__class = _class_0
|
||||
return _class_0
|
||||
end)(Block_)
|
||||
Block = Block_
|
||||
tree = function(tree)
|
||||
local scope = Block()
|
||||
local scope = RootBlock()
|
||||
local _item_0 = tree
|
||||
for _index_0=1,#_item_0 do
|
||||
local line = _item_0[_index_0]
|
||||
|
@ -12,18 +12,54 @@ import ntype from data
|
||||
import concat, insert from table
|
||||
|
||||
export tree
|
||||
export Block
|
||||
|
||||
-- buffer for building up a line
|
||||
class Line
|
||||
_append_single: (item) =>
|
||||
if util.moon.type(item) == Line
|
||||
@_append_single value for value in *item
|
||||
else
|
||||
insert self, item
|
||||
nil
|
||||
|
||||
append_list: (items, delim) =>
|
||||
for i = 1,#items
|
||||
@_append_single items[i]
|
||||
if i < #items then insert self, delim
|
||||
|
||||
append: (...) =>
|
||||
@_append_single item for item in *{...}
|
||||
nil
|
||||
|
||||
render: =>
|
||||
buff = {}
|
||||
for i = 1,#self
|
||||
c = self[i]
|
||||
insert buff, if util.moon.type(c) == Block
|
||||
c\render!
|
||||
else
|
||||
c
|
||||
concat buff
|
||||
|
||||
class Block_
|
||||
new: (@parent, @header, @footer) =>
|
||||
@header = "do" if not @header
|
||||
@footer = "end" if not @footer
|
||||
|
||||
@line_offset = 1
|
||||
|
||||
class Block
|
||||
new: (@parent) =>
|
||||
@set_indent @parent and @parent.indent + 1 or 0
|
||||
@_lines = {}
|
||||
@_posmap = {}
|
||||
@_names = {}
|
||||
@_state = {}
|
||||
|
||||
if @parent
|
||||
@indent = @parent.indent + 1
|
||||
setmetatable @_state, { __index: @parent._state }
|
||||
setmetatable @_names, { __index: @parent._names }
|
||||
else
|
||||
@indent = 0
|
||||
|
||||
line_table: =>
|
||||
@_posmap
|
||||
@ -34,10 +70,6 @@ class Block
|
||||
get: (name) =>
|
||||
@_state[name]
|
||||
|
||||
set_indent: (depth) =>
|
||||
@indent = depth
|
||||
@lead = indent_char\rep @indent
|
||||
|
||||
declare: (names) =>
|
||||
undeclared = [name for name in *names when type(name) == "string" and not @has_name name]
|
||||
@put_name name for name in *undeclared
|
||||
@ -61,18 +93,31 @@ class Block
|
||||
@put_name name if not dont_put
|
||||
name
|
||||
|
||||
init_free_var: (prefix, value) =>
|
||||
name = @free_name prefix, true
|
||||
@stm {"assign", {name}, {value}}
|
||||
name
|
||||
|
||||
mark_pos: (node) =>
|
||||
@_posmap[#@_lines + 1] = node[-1]
|
||||
|
||||
add_lines: (lines) =>
|
||||
insert @_lines, line for line in *lines
|
||||
nil
|
||||
-- add raw text as new line
|
||||
add_line_text: (text) =>
|
||||
@line_offset += 1
|
||||
insert @_lines, text
|
||||
|
||||
add_line: (...) =>
|
||||
args = {...}
|
||||
line = if #args == 1 then args[1] else concat args, " "
|
||||
-- add a line object
|
||||
add: (line) =>
|
||||
t = util.moon.type line
|
||||
|
||||
insert @_lines, line
|
||||
if t == "string"
|
||||
@add_line_text line
|
||||
elseif t == Block
|
||||
@add @line line
|
||||
elseif t == Line
|
||||
@add_line_text line\render!
|
||||
else
|
||||
error "Adding unknown item"
|
||||
|
||||
push: =>
|
||||
@_names = setmetatable {}, { __index: @_names }
|
||||
@ -80,17 +125,33 @@ class Block
|
||||
pop: =>
|
||||
@_names = getmetatable(@_names).__index
|
||||
|
||||
format: (...) =>
|
||||
pretty {...}, @lead
|
||||
|
||||
render: =>
|
||||
out = pretty @_lines, @lead
|
||||
if @indent > 0
|
||||
out = indent_char..out
|
||||
out
|
||||
flatten = (line) ->
|
||||
if type(line) == "string"
|
||||
line
|
||||
else
|
||||
line\render!
|
||||
|
||||
block: (node) =>
|
||||
Block(self)
|
||||
header = flatten @header
|
||||
|
||||
if #@_lines == 0
|
||||
footer = flatten @footer
|
||||
return concat {header, footer}, " "
|
||||
|
||||
body = pretty @_lines, indent_char\rep @indent
|
||||
|
||||
concat {
|
||||
header,
|
||||
body,
|
||||
indent_char\rep(@indent - 1) .. if @next then @next\render! else flatten @footer
|
||||
}, "\n"
|
||||
|
||||
block: (header, footer) =>
|
||||
Block self, header, footer
|
||||
|
||||
line: (...) =>
|
||||
with Line!
|
||||
\append ...
|
||||
|
||||
is_stm: (node) =>
|
||||
line_compile[ntype node] != nil
|
||||
@ -119,10 +180,10 @@ class Block
|
||||
if has_value node
|
||||
@stm {"assign", {"_"}, {node}}
|
||||
else
|
||||
@add_line @value node
|
||||
@add @value node
|
||||
else
|
||||
out = fn self, node, ...
|
||||
@add_line out if out
|
||||
@add out if out
|
||||
|
||||
ret_stms: (stms, ret) =>
|
||||
if not ret
|
||||
@ -158,8 +219,13 @@ class Block
|
||||
@stm stm for stm in *stms
|
||||
nil
|
||||
|
||||
class RootBlock extends Block_
|
||||
render: => concat @_lines, "\n"
|
||||
|
||||
Block = Block_
|
||||
|
||||
tree = (tree) ->
|
||||
scope = Block!
|
||||
scope = RootBlock!
|
||||
scope\stm line for line in *tree
|
||||
|
||||
scope\render!, scope\line_table!
|
||||
|
@ -33,7 +33,7 @@ pretty = function(lines, indent)
|
||||
for i, l, k, r in itwos(lines) do
|
||||
fix(i, l, k, r)
|
||||
end
|
||||
return concat(lines, "\n" .. indent)
|
||||
return indent .. concat(lines, "\n" .. indent)
|
||||
end
|
||||
returner = function(exp)
|
||||
if ntype(exp) == "chain" and exp[2] == "return" then
|
||||
|
@ -27,7 +27,7 @@ pretty = (lines, indent) ->
|
||||
lines[i] = lines[i]..";"
|
||||
fix(i,l, k,r) for i,l,k,r in itwos lines
|
||||
|
||||
concat lines, "\n"..indent
|
||||
indent .. concat lines, "\n"..indent
|
||||
|
||||
returner = (exp) ->
|
||||
if ntype(exp) == "chain" and exp[2] == "return"
|
||||
|
@ -12,7 +12,7 @@ is_slice = function(node) return ntype(node) == "chain" and ntype(node[#node]) =
|
||||
line_compile = {
|
||||
raw = function(self, node)
|
||||
local _, text = unpack(node)
|
||||
return self:add_line(text)
|
||||
return self:add(text)
|
||||
end,
|
||||
assign = function(self, node)
|
||||
local _, names, values = unpack(node)
|
||||
@ -20,22 +20,14 @@ line_compile = {
|
||||
local declare = "local " .. (concat(undeclared, ", "))
|
||||
if self:is_stm(values) then
|
||||
if #undeclared > 0 then
|
||||
self:add_line(declare)
|
||||
self:add(declare)
|
||||
end
|
||||
if cascading[ntype(values)] then
|
||||
local decorate
|
||||
decorate = function(value) return { "assign", names, { value } } end
|
||||
return self:stm(values, decorate)
|
||||
else
|
||||
return self:add_line(concat((function()
|
||||
local _moon_0 = {}
|
||||
local _item_0 = names
|
||||
for _index_0=1,#_item_0 do
|
||||
local n = _item_0[_index_0]
|
||||
table.insert(_moon_0, self:value(n))
|
||||
end
|
||||
return _moon_0
|
||||
end)(), ", ") .. " = " .. self:value(values))
|
||||
return error("Assigning unsupported statement")
|
||||
end
|
||||
else
|
||||
local has_fndef = false
|
||||
@ -46,30 +38,35 @@ line_compile = {
|
||||
end
|
||||
i = i + 1
|
||||
end
|
||||
values = concat((function()
|
||||
local _moon_0 = {}
|
||||
local _item_0 = values
|
||||
for _index_0=1,#_item_0 do
|
||||
local v = _item_0[_index_0]
|
||||
table.insert(_moon_0, self:value(v))
|
||||
do
|
||||
local _with_0 = self:line()
|
||||
if #undeclared == #names and not has_fndef then
|
||||
_with_0:append(declare)
|
||||
else
|
||||
if #undeclared > 0 then
|
||||
self:add(declare)
|
||||
end
|
||||
_with_0:append_list((function()
|
||||
local _moon_0 = {}
|
||||
local _item_0 = names
|
||||
for _index_0=1,#_item_0 do
|
||||
local name = _item_0[_index_0]
|
||||
table.insert(_moon_0, self:value(name))
|
||||
end
|
||||
return _moon_0
|
||||
end)(), ", ")
|
||||
end
|
||||
return _moon_0
|
||||
end)(), ", ")
|
||||
if #undeclared == #names and not has_fndef then
|
||||
return self:add_line(declare .. ' = ' .. values)
|
||||
else
|
||||
if #undeclared > 0 then
|
||||
self:add_line(declare)
|
||||
end
|
||||
return self:add_line(concat((function()
|
||||
_with_0:append(" = ")
|
||||
_with_0:append_list((function()
|
||||
local _moon_0 = {}
|
||||
local _item_0 = names
|
||||
local _item_0 = values
|
||||
for _index_0=1,#_item_0 do
|
||||
local n = _item_0[_index_0]
|
||||
table.insert(_moon_0, self:value(n))
|
||||
local v = _item_0[_index_0]
|
||||
table.insert(_moon_0, self:value(v))
|
||||
end
|
||||
return _moon_0
|
||||
end)(), ", ") .. " = " .. values)
|
||||
end)(), ", ")
|
||||
return _with_0
|
||||
end
|
||||
end
|
||||
end,
|
||||
@ -86,8 +83,8 @@ line_compile = {
|
||||
exp
|
||||
} } })
|
||||
end,
|
||||
["return"] = function(self, node) return self:add_line("return", self:value(node[2])) end,
|
||||
["break"] = function(self, node) return self:add_line("break") end,
|
||||
["return"] = function(self, node) return self:line("return ", self:value(node[2])) end,
|
||||
["break"] = function(self, node) return "break" end,
|
||||
import = function(self, node)
|
||||
local _, names, source = unpack(node)
|
||||
local to_bind = { }
|
||||
@ -133,71 +130,80 @@ line_compile = {
|
||||
end
|
||||
return _moon_0
|
||||
end)()
|
||||
self:add_line("local", (concat(final_names, ", ")), "=", (concat(values, ", ")))
|
||||
return(nil)
|
||||
local line
|
||||
do
|
||||
local _with_0 = self:line("local ", concat(final_names, ", "), " = ")
|
||||
_with_0:append_list(values, ", ")
|
||||
line = _with_0
|
||||
end
|
||||
return(line)
|
||||
end
|
||||
self:add_line("local", concat(final_names, ", "))
|
||||
self:add_line("do")
|
||||
local inner = self:block()
|
||||
local tmp_name = inner:free_name("table")
|
||||
inner:add_line("local", tmp_name, "=", self:value(source))
|
||||
source = tmp_name
|
||||
local _item_0 = final_names
|
||||
for _index_0=1,#_item_0 do
|
||||
local name = _item_0[_index_0]
|
||||
inner:add_line(name .. " = " .. get_value(name))
|
||||
self:add(self:line("local ", concat(final_names, ", ")))
|
||||
do
|
||||
local _with_0 = self:block("do")
|
||||
source = _with_0:init_free_var("table", source)
|
||||
local _item_0 = final_names
|
||||
for _index_0=1,#_item_0 do
|
||||
local name = _item_0[_index_0]
|
||||
_with_0:stm({ "assign", { name }, { get_value(name) } })
|
||||
end
|
||||
return _with_0
|
||||
end
|
||||
self:add_line(inner:render())
|
||||
return self:add_line("end")
|
||||
end,
|
||||
["if"] = function(self, node, ret)
|
||||
local cond, block = node[2], node[3]
|
||||
local root
|
||||
do
|
||||
local _with_0 = self:block(self:line("if ", self:value(cond), " then"))
|
||||
_with_0:stms(block, ret)
|
||||
root = _with_0
|
||||
end
|
||||
local current = root
|
||||
local add_clause
|
||||
add_clause = function(clause)
|
||||
local type = clause[1]
|
||||
local i = 2
|
||||
local next
|
||||
if type == "else" then
|
||||
self:add_line("else")
|
||||
block = clause[2]
|
||||
next = self:block("else")
|
||||
else
|
||||
self:add_line("elseif", (self:value(clause[2])), "then")
|
||||
block = clause[3]
|
||||
i = i + 1
|
||||
next = self:block(self:line("elseif ", self:value(clause[2]), " then"))
|
||||
end
|
||||
local b = self:block()
|
||||
b:stms(block, ret)
|
||||
return self:add_line(b:render())
|
||||
next:stms(clause[i], ret)
|
||||
current.next = next
|
||||
current = next
|
||||
end
|
||||
self:add_line("if", (self:value(cond)), "then")
|
||||
local b = self:block()
|
||||
b:stms(block, ret)
|
||||
self:add_line(b:render())
|
||||
local _item_0 = node
|
||||
for _index_0=4,#_item_0 do
|
||||
local cond = _item_0[_index_0]
|
||||
add_clause(cond)
|
||||
end
|
||||
return self:add_line("end")
|
||||
return root
|
||||
end,
|
||||
["while"] = function(self, node)
|
||||
local _, cond, block = unpack(node)
|
||||
local inner = self:block()
|
||||
local out
|
||||
if is_non_atomic(cond) then
|
||||
self:add_line("while", "true", "do")
|
||||
inner:stm({ "if", { "not", cond }, { { "break" } } })
|
||||
do
|
||||
local _with_0 = self:block("while true do")
|
||||
_with_0:stm({ "if", { "not", cond }, { { "break" } } })
|
||||
out = _with_0
|
||||
end
|
||||
else
|
||||
self:add_line("while", self:value(cond), "do")
|
||||
out = self:block(self:line("while ", self:value(cond), " do"))
|
||||
end
|
||||
inner:stms(block)
|
||||
self:add_line(inner:render())
|
||||
return self:add_line("end")
|
||||
out:stms(block)
|
||||
return out
|
||||
end,
|
||||
["for"] = function(self, node)
|
||||
local _, name, bounds, block = unpack(node)
|
||||
bounds = self:value({ "explist", unpack(bounds) })
|
||||
self:add_line("for", self:name(name), "=", bounds, "do")
|
||||
local inner = self:block()
|
||||
inner:stms(block)
|
||||
self:add_line(inner:render())
|
||||
return self:add_line("end")
|
||||
local loop = self:line("for ", self:name(name), " = ", self:value({ "explist", unpack(bounds) }))
|
||||
do
|
||||
local _with_0 = self:block(loop)
|
||||
_with_0:stms(block)
|
||||
return _with_0
|
||||
end
|
||||
end,
|
||||
export = function(self, node)
|
||||
local _, names = unpack(node)
|
||||
@ -402,16 +408,15 @@ line_compile = {
|
||||
end,
|
||||
with = function(self, node, ret)
|
||||
local _, exp, block = unpack(node)
|
||||
local inner = self:block()
|
||||
local tmp_name = inner:free_name("with", true)
|
||||
self:set("scope_var", tmp_name)
|
||||
inner:stm({ "assign", { tmp_name }, { exp } })
|
||||
inner:stms(block)
|
||||
if ret then
|
||||
inner:stm(ret(tmp_name))
|
||||
do
|
||||
local _with_0 = self:block()
|
||||
local var = _with_0:init_free_var("with", exp)
|
||||
self:set("scope_var", var)
|
||||
_with_0:stms(block)
|
||||
if ret then
|
||||
_with_0:stm(ret(var))
|
||||
end
|
||||
return _with_0
|
||||
end
|
||||
self:add_line("do")
|
||||
self:add_line(inner:render())
|
||||
return self:add_line("end")
|
||||
end
|
||||
}
|
||||
|
@ -20,7 +20,8 @@ is_slice = (node) ->
|
||||
line_compile =
|
||||
raw: (node) =>
|
||||
_, text = unpack node
|
||||
@add_line text
|
||||
@add text
|
||||
|
||||
assign: (node) =>
|
||||
_, names, values = unpack node
|
||||
|
||||
@ -28,14 +29,14 @@ line_compile =
|
||||
declare = "local "..(concat undeclared, ", ")
|
||||
|
||||
if @is_stm values
|
||||
@add_line declare if #undeclared > 0
|
||||
@add declare if #undeclared > 0
|
||||
if cascading[ntype(values)]
|
||||
decorate = (value) ->
|
||||
{"assign", names, {value}}
|
||||
|
||||
@stm values, decorate
|
||||
else
|
||||
@add_line concat([@value n for n in *names], ", ").." = "..@value values
|
||||
error "Assigning unsupported statement"
|
||||
else
|
||||
has_fndef = false
|
||||
i = 1
|
||||
@ -44,16 +45,15 @@ line_compile =
|
||||
has_fndef = true
|
||||
i = i +1
|
||||
|
||||
-- need new compiler
|
||||
-- (if ntype(v) == "fndef" then has_fndef = true) for v in *values
|
||||
with @line!
|
||||
if #undeclared == #names and not has_fndef
|
||||
\append declare
|
||||
else
|
||||
@add declare if #undeclared > 0
|
||||
\append_list [@value name for name in *names], ", "
|
||||
|
||||
values = concat [@value v for v in *values], ", "
|
||||
|
||||
if #undeclared == #names and not has_fndef
|
||||
@add_line declare..' = '..values
|
||||
else
|
||||
@add_line declare if #undeclared > 0
|
||||
@add_line concat([@value n for n in *names], ", ").." = "..values
|
||||
\append " = "
|
||||
\append_list [@value v for v in *values], ", "
|
||||
|
||||
update: (node) =>
|
||||
_, name, op, exp = unpack node
|
||||
@ -62,10 +62,10 @@ line_compile =
|
||||
@stm {"assign", {name}, {{"exp", name, op_final, exp}}}
|
||||
|
||||
return: (node) =>
|
||||
@add_line "return", @value node[2]
|
||||
@line "return ", @value node[2]
|
||||
|
||||
break: (node) =>
|
||||
@add_line "break"
|
||||
"break"
|
||||
|
||||
import: (node) =>
|
||||
_, names, source = unpack node
|
||||
@ -91,84 +91,69 @@ line_compile =
|
||||
-- from constant expression, put it on one line
|
||||
if type(source) == "string"
|
||||
values = [get_value name for name in *final_names]
|
||||
@add_line "local", (concat final_names, ", "), "=", (concat values, ", ")
|
||||
return nil
|
||||
line = with @line "local ", concat(final_names, ", "), " = "
|
||||
\append_list values, ", "
|
||||
return line
|
||||
|
||||
@add_line "local", concat(final_names, ", ")
|
||||
@add_line "do"
|
||||
|
||||
inner = @block()
|
||||
tmp_name = inner\free_name "table"
|
||||
inner\add_line "local", tmp_name , "=", @value source
|
||||
|
||||
source = tmp_name
|
||||
inner\add_line name.." = "..get_value name for name in *final_names
|
||||
|
||||
@add_line inner\render!
|
||||
|
||||
@add_line "end"
|
||||
@add @line "local ", concat(final_names, ", ")
|
||||
with @block "do"
|
||||
source = \init_free_var "table", source
|
||||
\stm {"assign", {name}, {get_value name}} for name in *final_names
|
||||
|
||||
if: (node, ret) =>
|
||||
cond, block = node[2], node[3]
|
||||
root = with @block @line "if ", @value(cond), " then"
|
||||
\stms block, ret
|
||||
|
||||
add_clause = (clause) ->
|
||||
current = root
|
||||
add_clause = (clause)->
|
||||
type = clause[1]
|
||||
block = if type == "else"
|
||||
@add_line "else"
|
||||
clause[2]
|
||||
i = 2
|
||||
next = if type == "else"
|
||||
@block "else"
|
||||
else
|
||||
@add_line "elseif", (@value clause[2]), "then"
|
||||
clause[3]
|
||||
i += 1
|
||||
@block @line "elseif ", @value(clause[2]), " then"
|
||||
|
||||
b = @block!
|
||||
b\stms block, ret
|
||||
@add_line b\render!
|
||||
next\stms clause[i], ret
|
||||
|
||||
@add_line "if", (@value cond), "then"
|
||||
|
||||
b = @block!
|
||||
b\stms block, ret
|
||||
@add_line b\render!
|
||||
current.next = next
|
||||
current = next
|
||||
|
||||
add_clause cond for cond in *node[4:]
|
||||
|
||||
@add_line "end"
|
||||
root
|
||||
|
||||
while: (node) =>
|
||||
_, cond, block = unpack node
|
||||
|
||||
inner = @block!
|
||||
if is_non_atomic cond
|
||||
@add_line "while", "true", "do"
|
||||
inner\stm {"if", {"not", cond}, {{"break"}}}
|
||||
out = if is_non_atomic cond
|
||||
with @block "while true do"
|
||||
\stm {"if", {"not", cond}, {{"break"}}}
|
||||
else
|
||||
@add_line "while", @value(cond), "do"
|
||||
@block @line "while ", @value(cond), " do"
|
||||
|
||||
inner\stms block
|
||||
|
||||
@add_line inner\render!
|
||||
@add_line "end"
|
||||
out\stms block
|
||||
out
|
||||
|
||||
for: (node) =>
|
||||
_, name, bounds, block = unpack node
|
||||
bounds = @value {"explist", unpack bounds}
|
||||
@add_line "for", @name(name), "=", bounds, "do"
|
||||
inner = @block!
|
||||
inner\stms block
|
||||
@add_line inner\render!
|
||||
@add_line "end"
|
||||
loop = @line "for ", @name(name), " = ", @value {"explist", unpack bounds}
|
||||
with @block loop
|
||||
\stms block
|
||||
|
||||
export: (node) =>
|
||||
_, names = unpack node
|
||||
@put_name name for name in *names when type(name) == "string"
|
||||
nil
|
||||
|
||||
-- TODO convert this
|
||||
class: (node) =>
|
||||
_, name, parent_val, tbl = unpack node
|
||||
|
||||
constructor = nil
|
||||
final_properties = {}
|
||||
|
||||
-- organize constructor and everything else
|
||||
find_special = (name, value) ->
|
||||
if name == constructor_name
|
||||
constructor = value
|
||||
@ -325,15 +310,10 @@ line_compile =
|
||||
|
||||
with: (node, ret) =>
|
||||
_, exp, block = unpack node
|
||||
inner = @block!
|
||||
tmp_name = inner\free_name "with", true
|
||||
|
||||
@set "scope_var", tmp_name
|
||||
inner\stm {"assign", {tmp_name}, {exp}}
|
||||
inner\stms block
|
||||
inner\stm ret tmp_name if ret
|
||||
|
||||
@add_line "do"
|
||||
@add_line inner\render!
|
||||
@add_line "end"
|
||||
with @block!
|
||||
var = \init_free_var "with", exp
|
||||
@set "scope_var", var
|
||||
\stms block
|
||||
\stm ret var if ret
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
module("moonscript.compile", package.seeall)
|
||||
local util = require("moonscript.util")
|
||||
local data = require("moonscript.data")
|
||||
local dump = require("moonscript.dump")
|
||||
require("moonscript.compile.format")
|
||||
local ntype = data.ntype
|
||||
local concat, insert = table.concat, table.insert
|
||||
@ -28,16 +29,22 @@ value_compile = {
|
||||
self:stm(node)
|
||||
return self:name(name)
|
||||
end,
|
||||
explist = function(self, node) return concat((function()
|
||||
local _moon_0 = {}
|
||||
local _item_0 = node
|
||||
for _index_0=2,#_item_0 do
|
||||
local v = _item_0[_index_0]
|
||||
table.insert(_moon_0, self:value(v))
|
||||
end
|
||||
return _moon_0
|
||||
end)(), ", ") end,
|
||||
parens = function(self, node) return "(" .. (self:value(node[2])) .. ")" end,
|
||||
explist = function(self, node)
|
||||
do
|
||||
local _with_0 = self:line()
|
||||
_with_0:append_list((function()
|
||||
local _moon_0 = {}
|
||||
local _item_0 = node
|
||||
for _index_0=2,#_item_0 do
|
||||
local v = _item_0[_index_0]
|
||||
table.insert(_moon_0, self:value(v))
|
||||
end
|
||||
return _moon_0
|
||||
end)(), ", ")
|
||||
return _with_0
|
||||
end
|
||||
end,
|
||||
parens = function(self, node) return self:line("(", self:value(node[2]), ")") end,
|
||||
string = function(self, node)
|
||||
local _, delim, inner, delim_end = unpack(node)
|
||||
return delim .. inner .. (delim_end or delim)
|
||||
@ -108,20 +115,15 @@ value_compile = {
|
||||
if arrow == "fat" then
|
||||
insert(args, 1, "self")
|
||||
end
|
||||
local b = self:block()
|
||||
local _item_0 = args
|
||||
for _index_0=1,#_item_0 do
|
||||
local name = _item_0[_index_0]
|
||||
b:put_name(name)
|
||||
end
|
||||
b:ret_stms(block)
|
||||
local decl = "function(" .. (concat(args, ", ")) .. ")"
|
||||
if #b._lines == 0 then
|
||||
return decl .. " end"
|
||||
elseif #b._lines == 1 then
|
||||
return concat({ decl, b._lines[1], "end" }, " ")
|
||||
else
|
||||
return self:format(decl, b._lines, "end")
|
||||
do
|
||||
local _with_0 = self:block("function(" .. concat(args, ", ") .. ")")
|
||||
local _item_0 = args
|
||||
for _index_0=1,#_item_0 do
|
||||
local name = _item_0[_index_0]
|
||||
_with_0:put_name(name)
|
||||
end
|
||||
_with_0:ret_stms(block)
|
||||
return _with_0
|
||||
end
|
||||
end,
|
||||
table = function(self, node)
|
||||
|
@ -3,6 +3,7 @@ module "moonscript.compile", package.seeall
|
||||
|
||||
util = require "moonscript.util"
|
||||
data = require "moonscript.data"
|
||||
dump = require "moonscript.dump"
|
||||
|
||||
require "moonscript.compile.format"
|
||||
|
||||
@ -27,10 +28,11 @@ value_compile =
|
||||
@name name
|
||||
|
||||
explist: (node) =>
|
||||
concat [@value v for v in *node[2:]], ", "
|
||||
with @line!
|
||||
\append_list [@value v for v in *node[2:]], ", "
|
||||
|
||||
parens: (node) =>
|
||||
"("..(@value node[2])..")"
|
||||
@line "(", @value(node[2]), ")"
|
||||
|
||||
string: (node) =>
|
||||
_, delim, inner, delim_end = unpack node
|
||||
@ -96,17 +98,9 @@ value_compile =
|
||||
if arrow == "fat"
|
||||
insert args, 1, "self"
|
||||
|
||||
b = @block!
|
||||
b\put_name name for name in *args
|
||||
b\ret_stms block
|
||||
|
||||
decl = "function("..(concat args, ", ")..")"
|
||||
if #b._lines == 0
|
||||
decl.." end"
|
||||
elseif #b._lines == 1
|
||||
concat {decl, b._lines[1], "end"}, " "
|
||||
else
|
||||
@format decl, b._lines, "end"
|
||||
with @block "function("..concat(args, ", ")..")"
|
||||
\put_name name for name in *args
|
||||
\ret_stms block
|
||||
|
||||
table: (node) =>
|
||||
_, items = unpack node
|
||||
|
@ -1,6 +1,20 @@
|
||||
|
||||
module("moonscript.util", package.seeall)
|
||||
|
||||
moon = {
|
||||
is_object = function(value)
|
||||
return type(value) == "table" and value.__class
|
||||
end,
|
||||
type = function(value)
|
||||
base_type = type(value)
|
||||
if base_type == "table" then
|
||||
cls = value.__class
|
||||
if cls then return cls end
|
||||
end
|
||||
return base_type
|
||||
end
|
||||
}
|
||||
|
||||
-- shallow copy
|
||||
function clone(tbl)
|
||||
local out = {}
|
||||
|
14
todo
14
todo
@ -1,5 +1,17 @@
|
||||
# TODO
|
||||
|
||||
|
||||
posmap = {
|
||||
[out_line] = file char
|
||||
}
|
||||
|
||||
differentiate root block and normal block
|
||||
|
||||
- use `with` as an arugment to function (normal expression)
|
||||
- varargs that get put in a nested generated function aren't valid anymor:
|
||||
- variable declartion for classes is messed up (always local)
|
||||
|
||||
|
||||
- add all lines through Block
|
||||
- add_line should only add one line at a time
|
||||
- add_block?
|
||||
@ -47,3 +59,5 @@ x =
|
||||
* allow return anywhere in block
|
||||
* upercase constants and capital letter variables should automatically be exported (in the global scope?)
|
||||
|
||||
|
||||
* any/every keywords for comprehensions
|
||||
|
Loading…
Reference in New Issue
Block a user