mirror of
https://github.com/leafo/moonscript.git
synced 2025-01-09 00:04:22 +00:00
fully moonspeak compiler
This commit is contained in:
parent
1bea9f1402
commit
f5c5e9fde3
2
moon
2
moon
@ -3,7 +3,7 @@
|
||||
module("moonscript", package.seeall)
|
||||
|
||||
require "moonscript.parse"
|
||||
require "moonscript.compile"
|
||||
require "moonscript.compile2"
|
||||
require "moonscript.util"
|
||||
|
||||
require "alt_getopt"
|
||||
|
2
moonc
2
moonc
@ -3,7 +3,7 @@
|
||||
module("moonscript", package.seeall)
|
||||
|
||||
require "moonscript.parse"
|
||||
require "moonscript.compile"
|
||||
require "moonscript.compile2"
|
||||
require "moonscript.util"
|
||||
|
||||
require "alt_getopt"
|
||||
|
@ -22,7 +22,7 @@ dependencies = {
|
||||
build = {
|
||||
type = "builtin",
|
||||
modules = {
|
||||
["moonscript.compile"] = "moonscript/compile.lua",
|
||||
["moonscript.compile2"] = "moonscript/compile2.lua",
|
||||
["moonscript.parse"] = "moonscript/parse.lua",
|
||||
["moonscript.dump"] = "moonscript/dump.lua",
|
||||
["moonscript.data"] = "moonscript/data.lua",
|
||||
|
606
moonscript/compile2.lua
Normal file
606
moonscript/compile2.lua
Normal file
@ -0,0 +1,606 @@
|
||||
module("moonscript.compile", package.seeall)
|
||||
local util = require("moonscript.util")
|
||||
local data = require("moonscript.data")
|
||||
local dump = require("moonscript.dump")
|
||||
local map, bind, itwos, every, reversed = util.map, util.bind, util.itwos, util.every, util.reversed
|
||||
local Stack, Set, ntype = data.Stack, data.Set, data.ntype
|
||||
local concat, insert = table.concat, table.insert
|
||||
local indent_char = " "
|
||||
local pretty
|
||||
pretty = function(lines, indent)
|
||||
indent = indent or ""
|
||||
local render
|
||||
render = function(line)
|
||||
if type(line) == "table" then
|
||||
return indent_char .. pretty(line, indent .. indent_char)
|
||||
else
|
||||
return line
|
||||
end
|
||||
end
|
||||
lines = (function()
|
||||
local _moon_0 = {}
|
||||
local _item_0 = lines
|
||||
for _index_0=1,#_item_0 do
|
||||
local line = _item_0[_index_0]
|
||||
table.insert(_moon_0, render(line))
|
||||
end
|
||||
return _moon_0
|
||||
end)()
|
||||
local fix
|
||||
fix = function(i, left, k, right)
|
||||
if left:sub(-1) == ")" and right:sub(1, 1) == "(" then
|
||||
lines[i] = lines[i] .. ";"
|
||||
end
|
||||
end
|
||||
for i, l, k, r in itwos(lines) do
|
||||
fix(i, l, k, r)
|
||||
end
|
||||
return concat(lines, "\n" .. indent)
|
||||
end
|
||||
local returner
|
||||
returner = function(exp)
|
||||
if ntype(exp) == "chain" and exp[2] == "return" then
|
||||
local items = { "explist" }
|
||||
local _item_0 = exp[3][2]
|
||||
for _index_0=1,#_item_0 do
|
||||
local v = _item_0[_index_0]
|
||||
insert(items, v)
|
||||
end
|
||||
return { "return", items }
|
||||
else
|
||||
return { "return", exp }
|
||||
end
|
||||
end
|
||||
local moonlib = { bind = function(tbl, name) return concat({
|
||||
"moon.bind(",
|
||||
tbl,
|
||||
".",
|
||||
name,
|
||||
", ",
|
||||
tbl,
|
||||
")"
|
||||
}) end }
|
||||
local cascading = Set({ "if" })
|
||||
local has_value
|
||||
has_value = function(node)
|
||||
if ntype(node) == "chain" then
|
||||
local ctype = ntype(node[#node])
|
||||
return ctype ~= "call" and ctype ~= "colon"
|
||||
else
|
||||
return true
|
||||
end
|
||||
end
|
||||
local line_compile = {
|
||||
assign = function(self, node)
|
||||
local _, names, values = unpack(node)
|
||||
local undeclared = (function()
|
||||
local _moon_0 = {}
|
||||
local _item_0 = names
|
||||
for _index_0=1,#_item_0 do
|
||||
local name = _item_0[_index_0]
|
||||
if type(name) == "string" and not self:has_name(name) then
|
||||
table.insert(_moon_0, name)
|
||||
end
|
||||
end
|
||||
return _moon_0
|
||||
end)()
|
||||
local _item_0 = undeclared
|
||||
for _index_0=1,#_item_0 do
|
||||
local name = _item_0[_index_0]
|
||||
self:put_name(name)
|
||||
end
|
||||
local declare = "local " .. (concat(undeclared, ", "))
|
||||
if self:is_stm(values) then
|
||||
if #undeclared > 0 then
|
||||
self:add_line(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))
|
||||
end
|
||||
else
|
||||
local has_fndef = false
|
||||
local i = 1
|
||||
while i <= #values do
|
||||
if ntype(values[i]) == "fndef" then
|
||||
has_fndef = true
|
||||
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))
|
||||
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()
|
||||
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)(), ", ") .. " = " .. values)
|
||||
end
|
||||
end
|
||||
end,
|
||||
["return"] = function(self, node) return self:add_line("return", self:value(node[2])) end,
|
||||
["import"] = function(self, node)
|
||||
local _, names, source = unpack(node)
|
||||
local to_bind = { }
|
||||
local get_name
|
||||
get_name = function(name)
|
||||
if ntype(name) == ":" then
|
||||
local tmp = self:name(name[2])
|
||||
to_bind[tmp] = true
|
||||
return tmp
|
||||
else
|
||||
return self:name(name)
|
||||
end
|
||||
end
|
||||
local final_names = (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, get_name(n))
|
||||
end
|
||||
return _moon_0
|
||||
end)()
|
||||
local _item_0 = final_names
|
||||
for _index_0=1,#_item_0 do
|
||||
local name = _item_0[_index_0]
|
||||
self:put_name(name)
|
||||
end
|
||||
local get_value
|
||||
get_value = function(name)
|
||||
if to_bind[name] then
|
||||
return moonlib.bind(source, name)
|
||||
else
|
||||
return source .. "." .. name
|
||||
end
|
||||
end
|
||||
if type(source) == "string" then
|
||||
local values = (function()
|
||||
local _moon_0 = {}
|
||||
local _item_0 = final_names
|
||||
for _index_0=1,#_item_0 do
|
||||
local name = _item_0[_index_0]
|
||||
table.insert(_moon_0, get_value(name))
|
||||
end
|
||||
return _moon_0
|
||||
end)()
|
||||
self:add_line("local", (concat(final_names, ", ")), "=", (concat(values, ", ")))
|
||||
return(nil)
|
||||
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))
|
||||
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 add_clause
|
||||
add_clause = function(clause)
|
||||
local type = clause[1]
|
||||
if type == "else" then
|
||||
self:add_line("else")
|
||||
block = clause[2]
|
||||
else
|
||||
self:add_line("elseif", (self:value(clause[2])), "then")
|
||||
block = clause[3]
|
||||
end
|
||||
local b = self:block()
|
||||
b:stms(block, ret)
|
||||
return self:add_line(b:render())
|
||||
end
|
||||
self:add_line("if", (self:value(cond)), "then")
|
||||
local b = self:block()
|
||||
b:stms(block, ret)
|
||||
self:add_line(b:render())
|
||||
for i, cond in ipairs(node) do
|
||||
if i > 3 then
|
||||
add_clause(cond)
|
||||
end
|
||||
end
|
||||
return self:add_line("end")
|
||||
end,
|
||||
["while"] = function(self, node)
|
||||
local _, cond, block = unpack(node)
|
||||
self:add_line("while", self:value(cond), "do")
|
||||
local inner = self:block()
|
||||
inner:stms(block)
|
||||
self:add_line(inner:render())
|
||||
return self:add_line("end")
|
||||
end,
|
||||
comprehension = function(self, node, action)
|
||||
local _, exp, clauses = unpack(node)
|
||||
if not action then
|
||||
action = self:block()
|
||||
action:stm(exp)
|
||||
end
|
||||
local depth = #clauses
|
||||
action:set_indent(self.indent + depth)
|
||||
local render_clause
|
||||
render_clause = function(self, clause)
|
||||
local t = clause[1]
|
||||
action = self:block()
|
||||
action:set_indent(-1 + self.indent)
|
||||
if "for" == t then
|
||||
local names, iter
|
||||
_, names, iter = unpack(clause)
|
||||
local name_list = concat((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:name(name))
|
||||
end
|
||||
return _moon_0
|
||||
end)(), ", ")
|
||||
if ntype(iter) == "unpack" then
|
||||
iter = iter[2]
|
||||
local items_tmp = self:free_name("item")
|
||||
local index_tmp = self:free_name("index")
|
||||
insert(self._lines, 1, ("local %s = %s[%s]"):format(name_list, items_tmp, index_tmp))
|
||||
return action:add_lines({
|
||||
("local %s = %s"):format(items_tmp, self:value(iter)),
|
||||
("for %s=1,#%s do"):format(index_tmp, items_tmp),
|
||||
self:render(true),
|
||||
"end"
|
||||
})
|
||||
else
|
||||
return action:add_lines({ ("for %s in %s do"):format(name_list, self:value(iter)), self:render(true), "end" })
|
||||
end
|
||||
elseif "when" == t then
|
||||
local cond
|
||||
_, cond = unpack(clause)
|
||||
return action:add_lines({ ("if %s then"):format(self:value(cond)), self:render(true), "end" })
|
||||
else
|
||||
return error("Unknown comprehension clause: " .. t)
|
||||
end
|
||||
end
|
||||
for i, clause in reversed(clauses) do
|
||||
render_clause(action, clause)
|
||||
end
|
||||
return self:add_lines(action._lines)
|
||||
end
|
||||
}
|
||||
local value_compile = {
|
||||
exp = function(self, node)
|
||||
local _comp
|
||||
_comp = function(i, value)
|
||||
if i % 2 == 1 and value == "!=" then
|
||||
value = "~="
|
||||
end
|
||||
return self:value(value)
|
||||
end
|
||||
return concat((function()
|
||||
local _moon_0 = {}
|
||||
for i, v in ipairs(node) do
|
||||
if i > 1 then
|
||||
table.insert(_moon_0, _comp(i, v))
|
||||
end
|
||||
end
|
||||
return _moon_0
|
||||
end)(), " ")
|
||||
end,
|
||||
explist = function(self, node) return concat((function()
|
||||
local _moon_0 = {}
|
||||
for i, v in ipairs(node) do
|
||||
if i > 1 then
|
||||
table.insert(_moon_0, self:value(v))
|
||||
end
|
||||
end
|
||||
return _moon_0
|
||||
end)(), ", ") end,
|
||||
parens = function(self, node) return "(" .. (self:value(node[2])) .. ")" end,
|
||||
string = function(self, node)
|
||||
local _, delim, inner, delim_end = unpack(node)
|
||||
return delim .. inner .. (delim_end or delim)
|
||||
end,
|
||||
["if"] = function(self, node)
|
||||
local func = self:block()
|
||||
func:stm(node, returner)
|
||||
return self:format("(function()", func:render(), "end)()")
|
||||
end,
|
||||
comprehension = function(self, node)
|
||||
local exp = node[2]
|
||||
local func = self:block()
|
||||
local tmp_name = func:free_name()
|
||||
func:add_line("local", tmp_name, "= {}")
|
||||
local action = func:block()
|
||||
action:add_line(("table.insert(%s, %s)"):format(tmp_name, func:value(exp)))
|
||||
func:stm(node, action)
|
||||
func:add_line("return", tmp_name)
|
||||
return self:format("(function()", func:render(), "end)()")
|
||||
end,
|
||||
chain = function(self, node)
|
||||
local callee = node[2]
|
||||
local chain_item
|
||||
chain_item = function(node)
|
||||
local t, arg = unpack(node)
|
||||
if t == "call" then
|
||||
return "(" .. (self:values(arg)) .. ")"
|
||||
elseif t == "index" then
|
||||
return "[" .. (self:value(arg)) .. "]"
|
||||
elseif t == "dot" then
|
||||
return "." .. arg
|
||||
elseif t == "colon" then
|
||||
return ":" .. arg .. (chain_item(node[3]))
|
||||
else
|
||||
return error("Unknown chain action: " .. t)
|
||||
end
|
||||
end
|
||||
local actions = (function()
|
||||
local _moon_0 = {}
|
||||
for i, act in ipairs(node) do
|
||||
if i > 2 then
|
||||
table.insert(_moon_0, chain_item(act))
|
||||
end
|
||||
end
|
||||
return _moon_0
|
||||
end)()
|
||||
if ntype(callee) == "self" and node[3] and ntype(node[3]) == "call" then
|
||||
callee[1] = "self_colon"
|
||||
end
|
||||
local callee_value = self:name(callee)
|
||||
if ntype(callee) == "exp" then
|
||||
callee_value = "(" .. callee_value .. ")"
|
||||
end
|
||||
return self:name(callee) .. concat(actions)
|
||||
end,
|
||||
fndef = function(self, node)
|
||||
local _, args, arrow, block = unpack(node)
|
||||
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")
|
||||
end
|
||||
end,
|
||||
table = function(self, node)
|
||||
local _, items = unpack(node)
|
||||
local inner = self:block()
|
||||
local _comp
|
||||
_comp = function(i, tuple)
|
||||
local out
|
||||
if #tuple == 2 then
|
||||
local key, value = unpack(tuple)
|
||||
if type(key) ~= "string" then
|
||||
key = ("[%s]"):format(self:value(key))
|
||||
else
|
||||
key = self:value(key)
|
||||
end
|
||||
out = ("%s = %s"):format(key, inner:value(value))
|
||||
else
|
||||
out = inner:value(tuple[1])
|
||||
end
|
||||
if i ~= #items then
|
||||
return out .. ","
|
||||
else
|
||||
return out
|
||||
end
|
||||
end
|
||||
local values = (function()
|
||||
local _moon_0 = {}
|
||||
for i, v in ipairs(items) do
|
||||
table.insert(_moon_0, _comp(i, v))
|
||||
end
|
||||
return _moon_0
|
||||
end)()
|
||||
if #values > 3 then
|
||||
return self:format("{", values, "}")
|
||||
else
|
||||
return "{ " .. (concat(values, " ")) .. " }"
|
||||
end
|
||||
end,
|
||||
minus = function(self, node) return "-" .. self:value(node[2]) end,
|
||||
length = function(self, node) return "#" .. self:value(node[2]) end,
|
||||
["not"] = function(self, node) return "not " .. self:value(node[2]) end,
|
||||
self = function(self, node) return "self." .. self:value(node[2]) end,
|
||||
self_colon = function(self, node) return "self:" .. self:value(node[2]) end
|
||||
}
|
||||
local block_t = { }
|
||||
local Block
|
||||
Block = function(parent)
|
||||
local indent = parent and parent.indent + 1 or 0
|
||||
local b = setmetatable({ _lines = { }, _names = { }, parent = parent }, block_t)
|
||||
b:set_indent(indent)
|
||||
return b
|
||||
end
|
||||
local B = {
|
||||
set_indent = function(self, depth)
|
||||
self.indent = depth
|
||||
self.lead = indent_char:rep(self.indent)
|
||||
end,
|
||||
put_name = function(self, name) self._names[name] = true end,
|
||||
has_name = function(self, name)
|
||||
if self._names[name] then
|
||||
return true
|
||||
elseif self.parent then
|
||||
return self.parent:has_name(name)
|
||||
else
|
||||
return false
|
||||
end
|
||||
end,
|
||||
free_name = function(self, prefix)
|
||||
prefix = prefix or "moon"
|
||||
local searching = true
|
||||
local name, i = nil, 0
|
||||
while searching do
|
||||
name = concat({ "", prefix, i }, "_")
|
||||
i = i + 1
|
||||
searching = self:has_name(name)
|
||||
end
|
||||
self:put_name(name)
|
||||
return name
|
||||
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
|
||||
end,
|
||||
add_line = function(self, ...)
|
||||
local args = { ... }
|
||||
local line
|
||||
if #args == 1 then
|
||||
line = args[1]
|
||||
else
|
||||
line = concat(args, " ")
|
||||
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
|
||||
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)
|
||||
return value_compile[t] ~= nil or t == "value"
|
||||
end,
|
||||
name = function(self, node) return self:value(node) end,
|
||||
value = function(self, node, ...)
|
||||
if type(node) ~= "table" then
|
||||
return(tostring(node))
|
||||
end
|
||||
local fn = value_compile[node[1]]
|
||||
if not fn then
|
||||
error("Failed to compile value: " .. dump.value(node))
|
||||
end
|
||||
return fn(self, node, ...)
|
||||
end,
|
||||
values = function(self, values, delim)
|
||||
delim = delim or ', '
|
||||
return 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))
|
||||
end
|
||||
return _moon_0
|
||||
end)(), delim)
|
||||
end,
|
||||
stm = function(self, node, ...)
|
||||
local fn = line_compile[ntype(node)]
|
||||
if not fn then
|
||||
if has_value(node) then
|
||||
return self:stm({ "assign", { "_" }, { node } })
|
||||
else
|
||||
return self:add_line(self:value(node))
|
||||
end
|
||||
else
|
||||
local out = fn(self, node, ...)
|
||||
if out then
|
||||
return self:add_line(out)
|
||||
end
|
||||
end
|
||||
end,
|
||||
ret_stms = function(self, stms, ret)
|
||||
if not ret then
|
||||
ret = returner
|
||||
end
|
||||
local i = 1
|
||||
while i < #stms do
|
||||
self:stm(stms[i])
|
||||
i = i + 1
|
||||
end
|
||||
local last_exp = stms[i]
|
||||
if last_exp then
|
||||
if cascading[ntype(last_exp)] then
|
||||
self:stm(last_exp, ret)
|
||||
elseif self:is_value(last_exp) then
|
||||
local line = ret(stms[i])
|
||||
if self:is_stm(line) then
|
||||
self:stm(line)
|
||||
else
|
||||
error("got a value from implicit return")
|
||||
end
|
||||
else
|
||||
self:stm(last_exp)
|
||||
end
|
||||
end
|
||||
return nil
|
||||
end,
|
||||
stms = function(self, stms, ret)
|
||||
if ret then
|
||||
self:ret_stms(stms, ret)
|
||||
else
|
||||
local _item_0 = stms
|
||||
for _index_0=1,#_item_0 do
|
||||
local stm = _item_0[_index_0]
|
||||
self:stm(stm)
|
||||
end
|
||||
end
|
||||
return nil
|
||||
end
|
||||
}
|
||||
block_t.__index = B
|
||||
local build_compiler
|
||||
build_compiler = function()
|
||||
Block(nil)
|
||||
return setmetatable({ }, { __index = compiler_index })
|
||||
end
|
||||
_M.tree = function(tree)
|
||||
local scope = Block()
|
||||
local _item_0 = tree
|
||||
for _index_0=1,#_item_0 do
|
||||
local line = _item_0[_index_0]
|
||||
scope:stm(line)
|
||||
end
|
||||
return scope:render()
|
||||
end
|
@ -18,7 +18,24 @@ pretty = (lines, indent) ->
|
||||
else
|
||||
line
|
||||
|
||||
concat [render line for line in *lines], "\n"..indent
|
||||
lines = [render line for line in *lines]
|
||||
|
||||
-- add semicolons for ambiguities
|
||||
fix = (i, left, k, right) ->
|
||||
if left:sub(-1) == ")" and right:sub(1,1) == "("
|
||||
lines[i] = lines[i]..";"
|
||||
fix(i,l, k,r) for i,l,k,r in itwos lines
|
||||
|
||||
concat lines, "\n"..indent
|
||||
|
||||
returner = (exp) ->
|
||||
if ntype(exp) == "chain" and exp[2] == "return"
|
||||
-- extract the return
|
||||
items = {"explist"}
|
||||
insert items, v for v in *exp[3][2]
|
||||
{"return", items}
|
||||
else
|
||||
{"return", exp}
|
||||
|
||||
moonlib =
|
||||
bind: (tbl, name) ->
|
||||
@ -29,7 +46,8 @@ cascading = Set{ "if" }
|
||||
-- does this always return a value
|
||||
has_value = (node) ->
|
||||
if ntype(node) == "chain"
|
||||
ntype(node[#node]) != "call"
|
||||
ctype = ntype(node[#node])
|
||||
ctype != "call" and ctype != "colon"
|
||||
else
|
||||
true
|
||||
|
||||
@ -53,8 +71,19 @@ line_compile =
|
||||
else
|
||||
@add_line concat([@value n for n in *names], ", ").." = "..@value values
|
||||
else
|
||||
has_fndef = false
|
||||
i = 1
|
||||
while i <= #values
|
||||
if ntype(values[i]) == "fndef"
|
||||
has_fndef = true
|
||||
i = i +1
|
||||
|
||||
-- need new compiler
|
||||
-- (if ntype(v) == "fndef" then has_fndef = true) for v in *values
|
||||
|
||||
values = concat [@value v for v in *values], ", "
|
||||
if #undeclared == #names
|
||||
|
||||
if #undeclared == #names and not has_fndef
|
||||
@add_line declare..' = '..values
|
||||
else
|
||||
@add_line declare if #undeclared > 0
|
||||
@ -80,7 +109,7 @@ line_compile =
|
||||
|
||||
get_value = (name) ->
|
||||
if to_bind[name]
|
||||
moonlib.bind name, source
|
||||
moonlib.bind source, name
|
||||
else
|
||||
source.."."..name
|
||||
|
||||
@ -133,7 +162,7 @@ line_compile =
|
||||
["while"]: (node) =>
|
||||
_, cond, block = unpack node
|
||||
|
||||
@add_line "while "..@value cond
|
||||
@add_line "while", @value(cond), "do"
|
||||
inner = @block()
|
||||
inner:stms block
|
||||
|
||||
@ -195,7 +224,7 @@ line_compile =
|
||||
value_compile =
|
||||
exp: (node) =>
|
||||
_comp = (i, value) ->
|
||||
if i % 1 == 1 and value == "!="
|
||||
if i % 2 == 1 and value == "!="
|
||||
value = "~="
|
||||
@value value
|
||||
|
||||
@ -214,7 +243,7 @@ value_compile =
|
||||
|
||||
["if"]: (node) =>
|
||||
func = @block()
|
||||
func:stm node, (exp) -> {"return", exp}
|
||||
func:stm node, returner
|
||||
@format "(function()", func:render(), "end)()"
|
||||
|
||||
comprehension: (node) =>
|
||||
@ -279,6 +308,7 @@ value_compile =
|
||||
table: (node) =>
|
||||
_, items = unpack node
|
||||
|
||||
inner = @block() -- handle indent
|
||||
_comp = (i, tuple) ->
|
||||
out = if #tuple == 2
|
||||
key, value = unpack tuple
|
||||
@ -286,9 +316,9 @@ value_compile =
|
||||
("[%s]"):format @value key
|
||||
else
|
||||
@value key
|
||||
("%s = %s"):format key, @value value
|
||||
("%s = %s"):format key, inner:value value
|
||||
else
|
||||
@value tuple[1]
|
||||
inner:value tuple[1]
|
||||
|
||||
out.."," if i != #items else out
|
||||
|
||||
@ -297,7 +327,7 @@ value_compile =
|
||||
if #values > 3
|
||||
@format "{", values, "}"
|
||||
else
|
||||
"{ "..(concat values, " ").."}"
|
||||
"{ "..(concat values, " ").." }"
|
||||
|
||||
minus: (node) =>
|
||||
"-"..@value node[2]
|
||||
@ -414,7 +444,7 @@ B =
|
||||
|
||||
ret_stms: (stms, ret) =>
|
||||
if not ret
|
||||
ret = (exp) -> {"return", exp}
|
||||
ret = returner
|
||||
|
||||
-- wow I really need a for loop
|
||||
i = 1
|
||||
|
14
test.lua
14
test.lua
@ -8,7 +8,11 @@ pcall(function()
|
||||
gettime = socket.gettime
|
||||
end)
|
||||
|
||||
local opts, ind = alt_getopt.get_opts(arg, "d:", { })
|
||||
require "moonscript.parse"
|
||||
require "moonscript.compile2"
|
||||
local parse, compile = moonscript.parse, moonscript.compile
|
||||
|
||||
local opts, ind = alt_getopt.get_opts(arg, "qd:", { })
|
||||
|
||||
local argv = {}
|
||||
for i = ind, #arg do table.insert(argv, arg[i]) end
|
||||
@ -16,6 +20,7 @@ for i = ind, #arg do table.insert(argv, arg[i]) end
|
||||
local action = table.remove(argv, 1) or "run"
|
||||
|
||||
local diff_tool = opts.d or "diff"
|
||||
local quiet = opts.q
|
||||
|
||||
local opts = {
|
||||
in_dir = "tests/inputs",
|
||||
@ -37,8 +42,6 @@ local function run_file(name, benchmark)
|
||||
name = input_name(name)
|
||||
file_str = io.open(name):read("*a")
|
||||
|
||||
local parse = require "moonscript.parse"
|
||||
local compile = require "moonscript.compile"
|
||||
|
||||
|
||||
local start_parse
|
||||
@ -112,7 +115,10 @@ local actions = {
|
||||
local tmp = io.open(tmp_name, "w")
|
||||
tmp:write(result)
|
||||
tmp:close()
|
||||
print(diff(correct_fname, tmp_name))
|
||||
|
||||
if not quiet then
|
||||
print(diff(correct_fname, tmp_name))
|
||||
end
|
||||
os.remove(tmp_name)
|
||||
-- break
|
||||
else
|
||||
|
@ -1,4 +1,5 @@
|
||||
local _ = function()
|
||||
local _
|
||||
_ = function()
|
||||
local joop = 2302
|
||||
return function(hi)
|
||||
local d = 100
|
||||
|
@ -1,14 +1,14 @@
|
||||
local hi = (function()
|
||||
local tmp = {}
|
||||
local _moon_0 = {}
|
||||
for _, x in ipairs({
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
4
|
||||
}) do
|
||||
table.insert(tmp, x * 2)
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
4
|
||||
}) do
|
||||
table.insert(_moon_0, x * 2)
|
||||
end
|
||||
return tmp
|
||||
return _moon_0
|
||||
end)()
|
||||
local items = {
|
||||
1,
|
||||
@ -19,11 +19,11 @@ local items = {
|
||||
6
|
||||
}
|
||||
local mm = (function()
|
||||
local tmp = {}
|
||||
local _moon_0 = {}
|
||||
for self.x in ipairs(items) do
|
||||
table.insert(tmp, self.x)
|
||||
table.insert(_moon_0, self.x)
|
||||
end
|
||||
return tmp
|
||||
return _moon_0
|
||||
end)()
|
||||
for z in ipairs(items) do
|
||||
if z > 4 then
|
||||
@ -31,25 +31,25 @@ for z in ipairs(items) do
|
||||
end
|
||||
end
|
||||
local rad = (function()
|
||||
local tmp = {}
|
||||
local _moon_0 = {}
|
||||
for a in ipairs({
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
4,
|
||||
5,
|
||||
6
|
||||
}) do
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
4,
|
||||
5,
|
||||
6
|
||||
}) do
|
||||
if good_number(a) then
|
||||
table.insert(tmp, { a })
|
||||
table.insert(_moon_0, { a })
|
||||
end
|
||||
end
|
||||
return tmp
|
||||
return _moon_0
|
||||
end)()
|
||||
for z in items do
|
||||
for j in list do
|
||||
if z > 4 then
|
||||
_ = z
|
||||
local _ = z
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -59,43 +59,43 @@ dump = function(x) return print(util.dump(x)) end
|
||||
local range
|
||||
range = function(count)
|
||||
local i = 0
|
||||
return(coroutine.wrap(function()
|
||||
return coroutine.wrap(function()
|
||||
while i < count do
|
||||
coroutine.yield(i)
|
||||
i = i + 1
|
||||
end
|
||||
end))
|
||||
end)
|
||||
end
|
||||
dump((function()
|
||||
local tmp = {}
|
||||
local _moon_0 = {}
|
||||
for x in range(10) do
|
||||
table.insert(tmp, x)
|
||||
table.insert(_moon_0, x)
|
||||
end
|
||||
return tmp
|
||||
return _moon_0
|
||||
end)())
|
||||
dump((function()
|
||||
local tmp = {}
|
||||
local _moon_0 = {}
|
||||
for x in range(5) do
|
||||
if x > 2 then
|
||||
for y in range(5) do
|
||||
table.insert(tmp, { x, y })
|
||||
table.insert(_moon_0, { x, y })
|
||||
end
|
||||
end
|
||||
end
|
||||
return tmp
|
||||
return _moon_0
|
||||
end)())
|
||||
local things = (function()
|
||||
local tmp = {}
|
||||
local _moon_0 = {}
|
||||
for x in range(10) do
|
||||
if x > 5 then
|
||||
for y in range(10) do
|
||||
if y > 7 then
|
||||
table.insert(tmp, x + y)
|
||||
table.insert(_moon_0, x + y)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
return tmp
|
||||
return _moon_0
|
||||
end)()
|
||||
for x in ipairs({ 1, 2, 4 }) do
|
||||
for y in ipairs({ 1, 2, 3 }) do
|
||||
@ -108,14 +108,14 @@ for x in items do
|
||||
print("hello", x)
|
||||
end
|
||||
for x in x do
|
||||
_ = x
|
||||
local _ = x
|
||||
end
|
||||
local x = (function()
|
||||
local tmp = {}
|
||||
local _moon_0 = {}
|
||||
for x in x do
|
||||
table.insert(tmp, x)
|
||||
table.insert(_moon_0, x)
|
||||
end
|
||||
return tmp
|
||||
return _moon_0
|
||||
end)()
|
||||
for x in ipairs({ 1, 2, 4 }) do
|
||||
for y in ipairs({ 1, 2, 3 }) do
|
||||
@ -125,45 +125,45 @@ for x in ipairs({ 1, 2, 4 }) do
|
||||
end
|
||||
end
|
||||
local double = (function()
|
||||
local tmp = {}
|
||||
local _items_0 = items
|
||||
for _index_0=1,#_items_0 do
|
||||
local x = _items_0[_index_0]
|
||||
table.insert(tmp, x * 2)
|
||||
local _moon_0 = {}
|
||||
local _item_0 = items
|
||||
for _index_0=1,#_item_0 do
|
||||
local x = _item_0[_index_0]
|
||||
table.insert(_moon_0, x * 2)
|
||||
end
|
||||
return tmp
|
||||
return _moon_0
|
||||
end)()
|
||||
local _items_0 = double
|
||||
for _index_0=1,#_items_0 do
|
||||
local x = _items_0[_index_0]
|
||||
local _item_0 = double
|
||||
for _index_0=1,#_item_0 do
|
||||
local x = _item_0[_index_0]
|
||||
print(x)
|
||||
end
|
||||
local cut = (function()
|
||||
local tmp = {}
|
||||
local _items_0 = items
|
||||
for _index_0=1,#_items_0 do
|
||||
local x = _items_0[_index_0]
|
||||
local _moon_0 = {}
|
||||
local _item_0 = items
|
||||
for _index_0=1,#_item_0 do
|
||||
local x = _item_0[_index_0]
|
||||
if x > 3 then
|
||||
table.insert(tmp, x)
|
||||
table.insert(_moon_0, x)
|
||||
end
|
||||
end
|
||||
return tmp
|
||||
return _moon_0
|
||||
end)()
|
||||
local hello = (function()
|
||||
local tmp = {}
|
||||
local _items_1 = items
|
||||
for _index_1=1,#_items_1 do
|
||||
local x = _items_1[_index_1]
|
||||
local _items_0 = items
|
||||
for _index_0=1,#_items_0 do
|
||||
local y = _items_0[_index_0]
|
||||
table.insert(tmp, x + y)
|
||||
local _moon_0 = {}
|
||||
local _item_1 = items
|
||||
for _index_1=1,#_item_1 do
|
||||
local x = _item_1[_index_1]
|
||||
local _item_0 = items
|
||||
for _index_0=1,#_item_0 do
|
||||
local y = _item_0[_index_0]
|
||||
table.insert(_moon_0, x + y)
|
||||
end
|
||||
end
|
||||
return tmp
|
||||
return _moon_0
|
||||
end)()
|
||||
local _items_0 = hello
|
||||
for _index_0=1,#_items_0 do
|
||||
local z = _items_0[_index_0]
|
||||
local _item_0 = hello
|
||||
for _index_0=1,#_item_0 do
|
||||
local z = _item_0[_index_0]
|
||||
print(z)
|
||||
end
|
@ -1,9 +1,8 @@
|
||||
local x
|
||||
x = function() return print(what) end
|
||||
local _ = function() end
|
||||
_ = function()
|
||||
return function() return function() end end
|
||||
end
|
||||
local _
|
||||
_ = function() end
|
||||
_ = function() return function() return function() end end end
|
||||
go(to(the(barn)))
|
||||
open(function() return the(function() return door end) end)
|
||||
open(function()
|
||||
@ -31,8 +30,8 @@ fun(a)(b)
|
||||
fun(a)(b, bad(hello))
|
||||
hello(world(what(are(you(doing(here))))))
|
||||
what(the)[3243](world, yeck(heck))
|
||||
hairy[hands][are](gross)(okay(okay[world]));
|
||||
(get[something] + 5)[years]
|
||||
hairy[hands][are](gross)(okay(okay[world]))
|
||||
_ = (get[something] + 5)[years]
|
||||
local i
|
||||
i, x = 200, 300
|
||||
local yeah = (1 + 5) * 3
|
||||
@ -49,16 +48,16 @@ end)
|
||||
something('else', "ya")
|
||||
something('else')
|
||||
something("else")
|
||||
here(we)("go")[12123]
|
||||
_ = here(we)("go")[12123]
|
||||
local something = { test = 12323, what = function() return print("hello world") end }
|
||||
print(something.test)
|
||||
local frick = { hello = "world" }
|
||||
local argon = { num = 100, world = function(self)
|
||||
print(self.num)
|
||||
return({ something = function() return print("hi from something") end })
|
||||
end, somethin = function(self,str)
|
||||
return { something = function() return print("hi from something") end }
|
||||
end, somethin = function(self, str)
|
||||
print("string is", str)
|
||||
return({ world = function(a,b) return print("sum", a + b) end })
|
||||
return { world = function(a, b) return print("sum", a + b) end }
|
||||
end }
|
||||
something.what()
|
||||
argon:world().something()
|
||||
@ -67,11 +66,11 @@ x = -434
|
||||
x = -hello(world(one(two)))
|
||||
local hi = -"herfef"
|
||||
x = -(function()
|
||||
local tmp = {}
|
||||
local _moon_0 = {}
|
||||
for x in x do
|
||||
table.insert(tmp, x)
|
||||
table.insert(_moon_0, x)
|
||||
end
|
||||
return tmp
|
||||
return _moon_0
|
||||
end)()
|
||||
if cool then
|
||||
print("hello")
|
||||
|
Loading…
Reference in New Issue
Block a user