Aegisub/automation/include/moonscript.lua

5467 lines
145 KiB
Lua
Raw Normal View History

2013-04-30 15:16:59 +02:00
package.preload['moonscript.base'] = function()
2014-03-07 04:19:12 +01:00
local compile = require("moonscript.compile")
local parse = require("moonscript.parse")
local concat, insert, remove
do
local _obj_0 = table
concat, insert, remove = _obj_0.concat, _obj_0.insert, _obj_0.remove
end
local split, dump, get_options, unpack
do
local _obj_0 = require("moonscript.util")
split, dump, get_options, unpack = _obj_0.split, _obj_0.dump, _obj_0.get_options, _obj_0.unpack
end
local lua = {
loadstring = loadstring,
load = load
}
2015-02-03 18:54:34 +01:00
local dirsep, line_tables, create_moonpath, to_lua, loadstring, loadfile, dofile
2014-03-07 04:19:12 +01:00
dirsep = "/"
line_tables = require("moonscript.line_tables")
create_moonpath = function(package_path)
local paths = split(package_path, ";")
for i, path in ipairs(paths) do
local p = path:match("^(.-)%.lua$")
if p then
paths[i] = p .. ".moon"
end
end
return concat(paths, ";")
end
to_lua = function(text, options)
if options == nil then
options = { }
end
if "string" ~= type(text) then
local t = type(text)
2015-02-03 18:54:34 +01:00
return nil, "expecting string (got " .. t .. ")"
2014-03-07 04:19:12 +01:00
end
local tree, err = parse.string(text)
if not tree then
return nil, err
end
local code, ltable, pos = compile.tree(tree, options)
if not code then
2015-02-03 18:54:34 +01:00
return nil, compile.format_error(ltable, pos, text)
2014-03-07 04:19:12 +01:00
end
return code, ltable
end
loadstring = function(...)
local options, str, chunk_name, mode, env = get_options(...)
chunk_name = chunk_name or "=(moonscript.loadstring)"
local code, ltable_or_err = to_lua(str, options)
if not (code) then
return nil, ltable_or_err
end
if chunk_name then
line_tables[chunk_name] = ltable_or_err
end
return (lua.loadstring or lua.load)(code, chunk_name, unpack({
mode,
env
}))
end
loadfile = function(fname, ...)
local file, err = io.open(fname)
if not (file) then
return nil, err
end
local text = assert(file:read("*a"))
file:close()
2015-02-03 18:54:34 +01:00
return loadstring(text, "@" .. tostring(fname), ...)
2014-03-07 04:19:12 +01:00
end
dofile = function(...)
local f = assert(loadfile(...))
return f()
end
return {
_NAME = "moonscript",
to_lua = to_lua,
dirsep = dirsep,
dofile = dofile,
loadfile = loadfile,
loadstring = loadstring
}
end
package.preload['moonscript.cmd.coverage'] = function()
local log
log = function(str)
if str == nil then
str = ""
end
return io.stderr:write(str .. "\n")
end
local create_counter
create_counter = function()
return setmetatable({ }, {
__index = function(self, name)
do
local tbl = setmetatable({ }, {
__index = function(self)
return 0
end
})
self[name] = tbl
return tbl
end
end
})
end
local position_to_lines
position_to_lines = function(file_content, positions)
local lines = { }
local current_pos = 0
local line_no = 1
for char in file_content:gmatch(".") do
do
local count = rawget(positions, current_pos)
if count then
lines[line_no] = count
end
end
if char == "\n" then
line_no = line_no + 1
end
current_pos = current_pos + 1
end
return lines
end
local format_file
format_file = function(fname, positions)
local file = assert(io.open(fname))
local content = file:read("*a")
file:close()
local lines = position_to_lines(content, positions)
log("------| @" .. tostring(fname))
local line_no = 1
for line in (content .. "\n"):gmatch("(.-)\n") do
local foramtted_no = ("% 5d"):format(line_no)
local sym = lines[line_no] and "*" or " "
log(tostring(sym) .. tostring(foramtted_no) .. "| " .. tostring(line))
line_no = line_no + 1
end
return log()
end
local CodeCoverage
do
local _base_0 = {
reset = function(self)
self.line_counts = create_counter()
end,
start = function(self)
return debug.sethook((function()
local _base_1 = self
local _fn_0 = _base_1.process_line
return function(...)
return _fn_0(_base_1, ...)
end
end)(), "l")
end,
stop = function(self)
return debug.sethook()
end,
print_results = function(self)
return self:format_results()
end,
process_line = function(self, _, line_no)
local debug_data = debug.getinfo(2, "S")
local source = debug_data.source
self.line_counts[source][line_no] = self.line_counts[source][line_no] + 1
end,
format_results = function(self)
local line_table = require("moonscript.line_tables")
local positions = create_counter()
for file, lines in pairs(self.line_counts) do
local _continue_0 = false
repeat
local file_table = line_table[file]
if not (file_table) then
_continue_0 = true
break
end
for line, count in pairs(lines) do
local _continue_1 = false
repeat
local position = file_table[line]
if not (position) then
_continue_1 = true
break
end
positions[file][position] = positions[file][position] + count
_continue_1 = true
until true
if not _continue_1 then
break
end
end
_continue_0 = true
until true
if not _continue_0 then
break
end
end
for file, ps in pairs(positions) do
format_file(file, ps)
end
end
}
_base_0.__index = _base_0
local _class_0 = setmetatable({
__init = function(self)
return self:reset()
end,
__base = _base_0,
__name = "CodeCoverage"
}, {
__index = _base_0,
__call = function(cls, ...)
local _self_0 = setmetatable({}, _base_0)
cls.__init(_self_0, ...)
return _self_0
end
})
_base_0.__class = _class_0
CodeCoverage = _class_0
end
return {
CodeCoverage = CodeCoverage
}
end
package.preload['moonscript.cmd.lint'] = function()
local insert
2015-02-03 18:54:34 +01:00
insert = table.insert
2014-03-07 04:19:12 +01:00
local Set
2015-02-03 18:54:34 +01:00
Set = require("moonscript.data").Set
2014-03-07 04:19:12 +01:00
local Block
2015-02-03 18:54:34 +01:00
Block = require("moonscript.compile").Block
local mtype
mtype = require("moonscript.util").moon.type
2014-03-07 04:19:12 +01:00
local default_whitelist = Set({
'_G',
'_VERSION',
'assert',
'bit32',
'collectgarbage',
'coroutine',
'debug',
'dofile',
'error',
'getfenv',
'getmetatable',
'io',
'ipairs',
'load',
'loadfile',
'loadstring',
'math',
'module',
'next',
'os',
'package',
'pairs',
'pcall',
'print',
'rawequal',
'rawget',
'rawlen',
'rawset',
'require',
'select',
'setfenv',
'setmetatable',
'string',
'table',
'tonumber',
'tostring',
'type',
'unpack',
'xpcall',
"nil",
"true",
"false"
})
local LinterBlock
do
local _parent_0 = Block
local _base_0 = {
2015-02-03 18:54:34 +01:00
lint_mark_used = function(self, name)
if self.lint_unused_names and self.lint_unused_names[name] then
self.lint_unused_names[name] = false
return
end
if self.parent then
return self.parent:lint_mark_used(name)
end
end,
lint_check_unused = function(self)
if not (self.lint_unused_names and next(self.lint_unused_names)) then
return
end
local names_by_position = { }
for name, pos in pairs(self.lint_unused_names) do
local _continue_0 = false
repeat
if not (pos) then
_continue_0 = true
break
end
names_by_position[pos] = names_by_position[pos] or { }
insert(names_by_position[pos], name)
_continue_0 = true
until true
if not _continue_0 then
break
end
end
local tuples
do
local _accum_0 = { }
local _len_0 = 1
for pos, names in pairs(names_by_position) do
_accum_0[_len_0] = {
pos,
names
}
_len_0 = _len_0 + 1
end
tuples = _accum_0
end
table.sort(tuples, function(a, b)
return a[1] < b[1]
end)
for _index_0 = 1, #tuples do
local _des_0 = tuples[_index_0]
local pos, names
pos, names = _des_0[1], _des_0[2]
insert(self:get_root_block().lint_errors, {
"assigned but unused " .. tostring(table.concat((function()
local _accum_0 = { }
local _len_0 = 1
for _index_1 = 1, #names do
local n = names[_index_1]
_accum_0[_len_0] = "`" .. tostring(n) .. "`"
_len_0 = _len_0 + 1
end
return _accum_0
end)(), ", ")),
pos
})
end
end,
render = function(self, ...)
self:lint_check_unused()
return _parent_0.render(self, ...)
end,
2014-03-07 04:19:12 +01:00
block = function(self, ...)
do
local _with_0 = _parent_0.block(self, ...)
_with_0.block = self.block
2015-02-03 18:54:34 +01:00
_with_0.render = self.render
_with_0.get_root_block = self.get_root_block
_with_0.lint_check_unused = self.lint_check_unused
_with_0.lint_mark_used = self.lint_mark_used
2014-03-07 04:19:12 +01:00
_with_0.value_compilers = self.value_compilers
2015-02-03 18:54:34 +01:00
_with_0.statement_compilers = self.statement_compilers
2014-03-07 04:19:12 +01:00
return _with_0
end
end
}
_base_0.__index = _base_0
setmetatable(_base_0, _parent_0.__base)
local _class_0 = setmetatable({
__init = function(self, whitelist_globals, ...)
if whitelist_globals == nil then
whitelist_globals = default_whitelist
end
_parent_0.__init(self, ...)
2015-02-03 18:54:34 +01:00
self.get_root_block = function()
return self
end
2014-03-07 04:19:12 +01:00
self.lint_errors = { }
local vc = self.value_compilers
self.value_compilers = setmetatable({
ref = function(block, val)
local name = val[2]
if not (block:has_name(name) or whitelist_globals[name] or name:match("%.")) then
insert(self.lint_errors, {
2015-02-03 18:54:34 +01:00
"accessing global `" .. tostring(name) .. "`",
2014-03-07 04:19:12 +01:00
val[-1]
})
end
2015-02-03 18:54:34 +01:00
block:lint_mark_used(name)
2014-03-07 04:19:12 +01:00
return vc.ref(block, val)
end
}, {
__index = vc
})
2015-02-03 18:54:34 +01:00
local sc = self.statement_compilers
self.statement_compilers = setmetatable({
assign = function(block, node)
local names = node[2]
for _index_0 = 1, #names do
local _continue_0 = false
repeat
local name = names[_index_0]
if type(name) == "table" and name[1] == "temp_name" then
_continue_0 = true
break
end
local real_name, is_local = block:extract_assign_name(name)
if not (is_local or real_name and not block:has_name(real_name, true)) then
_continue_0 = true
break
end
if real_name == "_" then
_continue_0 = true
break
end
block.lint_unused_names = block.lint_unused_names or { }
block.lint_unused_names[real_name] = node[-1] or 0
_continue_0 = true
until true
if not _continue_0 then
break
end
end
return sc.assign(block, node)
end
}, {
__index = sc
})
2014-03-07 04:19:12 +01:00
end,
__base = _base_0,
__name = "LinterBlock",
__parent = _parent_0
}, {
__index = function(cls, name)
local val = rawget(_base_0, name)
if val == nil then
return _parent_0[name]
else
return val
end
end,
__call = function(cls, ...)
local _self_0 = setmetatable({}, _base_0)
cls.__init(_self_0, ...)
return _self_0
end
})
_base_0.__class = _class_0
if _parent_0.__inherited then
_parent_0.__inherited(_parent_0, _class_0)
end
LinterBlock = _class_0
end
local format_lint
format_lint = function(errors, code, header)
if not (next(errors)) then
return
end
local pos_to_line, get_line
do
local _obj_0 = require("moonscript.util")
pos_to_line, get_line = _obj_0.pos_to_line, _obj_0.get_line
end
local formatted
do
local _accum_0 = { }
local _len_0 = 1
for _index_0 = 1, #errors do
local _des_0 = errors[_index_0]
local msg, pos
msg, pos = _des_0[1], _des_0[2]
if pos then
local line = pos_to_line(code, pos)
msg = "line " .. tostring(line) .. ": " .. tostring(msg)
local line_text = "> " .. get_line(code, line)
local sep_len = math.max(#msg, #line_text)
_accum_0[_len_0] = table.concat({
msg,
("="):rep(sep_len),
line_text
}, "\n")
else
_accum_0[_len_0] = msg
end
_len_0 = _len_0 + 1
end
formatted = _accum_0
end
if header then
table.insert(formatted, 1, header)
end
return table.concat(formatted, "\n\n")
end
local whitelist_for_file
do
local lint_config
whitelist_for_file = function(fname)
if not (lint_config) then
lint_config = { }
pcall(function()
lint_config = require("lint_config")
end)
end
if not (lint_config.whitelist_globals) then
return default_whitelist
end
local final_list = { }
for pattern, list in pairs(lint_config.whitelist_globals) do
if fname:match(pattern) then
for _index_0 = 1, #list do
local item = list[_index_0]
insert(final_list, item)
end
end
end
return setmetatable(Set(final_list), {
__index = default_whitelist
})
end
end
local lint_code
lint_code = function(code, name, whitelist_globals)
if name == nil then
name = "string input"
end
local parse = require("moonscript.parse")
local tree, err = parse.string(code)
if not (tree) then
return nil, err
end
local scope = LinterBlock(whitelist_globals)
scope:stms(tree)
2015-02-03 18:54:34 +01:00
scope:lint_check_unused()
2014-03-07 04:19:12 +01:00
return format_lint(scope.lint_errors, code, name)
end
local lint_file
lint_file = function(fname)
local f, err = io.open(fname)
if not (f) then
return nil, err
end
return lint_code(f:read("*a"), fname, whitelist_for_file(fname))
end
return {
lint_code = lint_code,
lint_file = lint_file
}
2013-04-30 15:16:59 +02:00
2015-02-03 18:54:34 +01:00
end
package.preload['moonscript.cmd.moonc'] = function()
local lfs = require("lfs")
local split
split = require("moonscript.util").split
local dirsep, dirsep_chars, mkdir, normalize_dir, parse_dir, parse_file, convert_path, format_time, gettime, compile_file_text, write_file, compile_and_write, is_abs_path, path_to_target
dirsep = package.config:sub(1, 1)
if dirsep == "\\" then
dirsep_chars = "\\/"
else
dirsep_chars = dirsep
end
mkdir = function(path)
local chunks = split(path, dirsep)
local accum
for _index_0 = 1, #chunks do
local dir = chunks[_index_0]
accum = accum and tostring(accum) .. tostring(dirsep) .. tostring(dir) or dir
lfs.mkdir(accum)
end
return lfs.attributes(path, "mode")
end
normalize_dir = function(path)
return path:match("^(.-)[" .. tostring(dirsep_chars) .. "]*$") .. dirsep
end
parse_dir = function(path)
return (path:match("^(.-)[^" .. tostring(dirsep_chars) .. "]*$"))
end
parse_file = function(path)
return (path:match("^.-([^" .. tostring(dirsep_chars) .. "]*)$"))
end
convert_path = function(path)
local new_path = path:gsub("%.moon$", ".lua")
if new_path == path then
new_path = path .. ".lua"
end
return new_path
end
format_time = function(time)
return ("%.3fms"):format(time * 1000)
end
do
local socket
gettime = function()
if socket == nil then
pcall(function()
socket = require("socket")
end)
if not (socket) then
socket = false
end
end
if socket then
return socket.gettime()
else
return nil, "LuaSocket needed for benchmark"
end
end
end
compile_file_text = function(text, opts)
if opts == nil then
opts = { }
end
local parse = require("moonscript.parse")
local compile = require("moonscript.compile")
local parse_time
if opts.benchmark then
parse_time = assert(gettime())
end
local tree, err = parse.string(text)
if not (tree) then
return nil, err
end
if parse_time then
parse_time = gettime() - parse_time
end
if opts.show_parse_tree then
local dump = require("moonscript.dump")
dump.tree(tree)
return true
end
local compile_time
if opts.benchmark then
compile_time = gettime()
end
local code, posmap_or_err, err_pos = compile.tree(tree)
if not (code) then
return nil, compile.format_error(posmap_or_err, err_pos, text)
end
if compile_time then
compile_time = gettime() - compile_time
end
if opts.show_posmap then
local debug_posmap
debug_posmap = require("moonscript.util").debug_posmap
print("Pos", "Lua", ">>", "Moon")
print(debug_posmap(posmap_or_err, text, code))
return true
end
if opts.benchmark then
print(table.concat({
opts.fname or "stdin",
"Parse time \t" .. format_time(parse_time),
"Compile time\t" .. format_time(compile_time),
""
}, "\n"))
return nil
end
return code
end
write_file = function(fname, code)
mkdir(parse_dir(fname))
local f, err = io.open(fname, "w")
if not (f) then
return nil, err
end
assert(f:write(code))
assert(f:write("\n"))
f:close()
return "build"
end
compile_and_write = function(src, dest, opts)
if opts == nil then
opts = { }
end
local f = io.open(src)
if not (f) then
return nil, "Can't find file"
end
local text = assert(f:read("*a"))
f:close()
local code, err = compile_file_text(text, opts)
if not code then
return nil, err
end
if code == true then
return true
end
if opts.print then
print(code)
return true
end
return write_file(dest, code)
end
is_abs_path = function(path)
local first = path:sub(1, 1)
if dirsep == "\\" then
return first == "/" or first == "\\" or path:sub(2, 1) == ":"
else
return first == dirsep
end
end
path_to_target = function(path, target_dir, base_dir)
if target_dir == nil then
target_dir = nil
end
if base_dir == nil then
base_dir = nil
end
local target = convert_path(path)
if target_dir then
target_dir = normalize_dir(target_dir)
end
if base_dir and target_dir then
local head = base_dir:match("^(.-)[^" .. tostring(dirsep_chars) .. "]*[" .. tostring(dirsep_chars) .. "]?$")
if head then
local start, stop = target:find(head, 1, true)
if start == 1 then
target = target:sub(stop + 1)
end
end
end
if target_dir then
if is_abs_path(target) then
target = parse_file(target)
end
target = target_dir .. target
end
return target
end
return {
dirsep = dirsep,
mkdir = mkdir,
normalize_dir = normalize_dir,
parse_dir = parse_dir,
parse_file = parse_file,
convert_path = convert_path,
gettime = gettime,
format_time = format_time,
path_to_target = path_to_target,
compile_file_text = compile_file_text,
compile_and_write = compile_and_write
}
2013-04-30 15:16:59 +02:00
end
package.preload['moonscript.compile.statement'] = function()
local util = require("moonscript.util")
2013-07-04 01:11:42 +02:00
local reversed, unpack
reversed, unpack = util.reversed, util.unpack
2013-04-30 15:16:59 +02:00
local ntype
2015-02-03 18:54:34 +01:00
ntype = require("moonscript.types").ntype
2013-07-04 01:11:42 +02:00
local concat, insert
do
local _obj_0 = table
concat, insert = _obj_0.concat, _obj_0.insert
2013-04-30 15:16:59 +02:00
end
2014-03-07 04:19:12 +01:00
return {
2013-04-30 15:16:59 +02:00
raw = function(self, node)
return self:add(node[2])
end,
lines = function(self, node)
local _list_0 = node[2]
for _index_0 = 1, #_list_0 do
local line = _list_0[_index_0]
self:add(line)
end
end,
declare = function(self, node)
local names = node[2]
local undeclared = self:declare(names)
if #undeclared > 0 then
do
local _with_0 = self:line("local ")
_with_0:append_list((function()
local _accum_0 = { }
local _len_0 = 1
2013-07-04 01:11:42 +02:00
for _index_0 = 1, #undeclared do
local name = undeclared[_index_0]
2013-04-30 15:16:59 +02:00
_accum_0[_len_0] = self:name(name)
_len_0 = _len_0 + 1
end
return _accum_0
end)(), ", ")
return _with_0
end
end
end,
declare_with_shadows = function(self, node)
local names = node[2]
self:declare(names)
do
local _with_0 = self:line("local ")
_with_0:append_list((function()
local _accum_0 = { }
local _len_0 = 1
2013-07-04 01:11:42 +02:00
for _index_0 = 1, #names do
local name = names[_index_0]
2013-04-30 15:16:59 +02:00
_accum_0[_len_0] = self:name(name)
_len_0 = _len_0 + 1
end
return _accum_0
end)(), ", ")
return _with_0
end
end,
assign = function(self, node)
local _, names, values = unpack(node)
local undeclared = self:declare(names)
local declare = "local " .. concat(undeclared, ", ")
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
do
local _with_0 = self:line()
if #undeclared == #names and not has_fndef then
_with_0:append(declare)
else
if #undeclared > 0 then
2015-02-03 18:54:34 +01:00
self:add(declare, node[-1])
2013-04-30 15:16:59 +02:00
end
_with_0:append_list((function()
local _accum_0 = { }
local _len_0 = 1
2013-07-04 01:11:42 +02:00
for _index_0 = 1, #names do
local name = names[_index_0]
2013-04-30 15:16:59 +02:00
_accum_0[_len_0] = self:value(name)
_len_0 = _len_0 + 1
end
return _accum_0
end)(), ", ")
end
_with_0:append(" = ")
_with_0:append_list((function()
local _accum_0 = { }
local _len_0 = 1
2013-07-04 01:11:42 +02:00
for _index_0 = 1, #values do
local v = values[_index_0]
2013-04-30 15:16:59 +02:00
_accum_0[_len_0] = self:value(v)
_len_0 = _len_0 + 1
end
return _accum_0
end)(), ", ")
return _with_0
end
end,
["return"] = function(self, node)
return self:line("return ", (function()
if node[2] ~= "" then
return self:value(node[2])
end
end)())
end,
["break"] = function(self, node)
return "break"
end,
["if"] = function(self, node)
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)
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
next = self:block("else")
else
i = i + 1
next = self:block(self:line("elseif ", self:value(clause[2]), " then"))
end
next:stms(clause[i])
current.next = next
current = next
end
2013-07-04 01:11:42 +02:00
for _index_0 = 4, #node do
cond = node[_index_0]
2013-04-30 15:16:59 +02:00
add_clause(cond)
end
return root
end,
["repeat"] = function(self, node)
local cond, block = unpack(node, 2)
do
local _with_0 = self:block("repeat", self:line("until ", self:value(cond)))
_with_0:stms(block)
return _with_0
end
end,
["while"] = function(self, node)
local _, cond, block = unpack(node)
do
local _with_0 = self:block(self:line("while ", self:value(cond), " do"))
_with_0:stms(block)
return _with_0
end
end,
["for"] = function(self, node)
local _, name, bounds, block = unpack(node)
local loop = self:line("for ", self:name(name), " = ", self:value({
"explist",
unpack(bounds)
}), " do")
do
local _with_0 = self:block(loop)
_with_0:declare({
name
})
_with_0:stms(block)
return _with_0
end
end,
foreach = function(self, node)
local _, names, exps, block = unpack(node)
local loop
do
local _with_0 = self:line()
_with_0:append("for ")
loop = _with_0
end
do
local _with_0 = self:block(loop)
loop:append_list((function()
local _accum_0 = { }
local _len_0 = 1
2013-07-04 01:11:42 +02:00
for _index_0 = 1, #names do
local name = names[_index_0]
2013-04-30 15:16:59 +02:00
_accum_0[_len_0] = _with_0:name(name, false)
_len_0 = _len_0 + 1
end
return _accum_0
end)(), ", ")
loop:append(" in ")
loop:append_list((function()
local _accum_0 = { }
local _len_0 = 1
2013-07-04 01:11:42 +02:00
for _index_0 = 1, #exps do
local exp = exps[_index_0]
2013-04-30 15:16:59 +02:00
_accum_0[_len_0] = self:value(exp)
_len_0 = _len_0 + 1
end
return _accum_0
end)(), ",")
loop:append(" do")
_with_0:declare(names)
_with_0:stms(block)
return _with_0
end
end,
export = function(self, node)
local _, names = unpack(node)
if type(names) == "string" then
if names == "*" then
self.export_all = true
elseif names == "^" then
self.export_proper = true
end
else
self:declare(names)
end
return nil
end,
run = function(self, code)
code:call(self)
return nil
end,
group = function(self, node)
return self:stms(node[2])
end,
["do"] = function(self, node)
do
local _with_0 = self:block()
_with_0:stms(node[2])
return _with_0
end
2013-07-04 01:11:42 +02:00
end,
noop = function(self) end
2013-04-30 15:16:59 +02:00
}
end
package.preload['moonscript.compile.value'] = function()
local util = require("moonscript.util")
local data = require("moonscript.data")
local ntype
2015-02-03 18:54:34 +01:00
ntype = require("moonscript.types").ntype
2013-04-30 15:16:59 +02:00
local user_error
2015-02-03 18:54:34 +01:00
user_error = require("moonscript.errors").user_error
2013-07-04 01:11:42 +02:00
local concat, insert
do
local _obj_0 = table
concat, insert = _obj_0.concat, _obj_0.insert
end
local unpack
unpack = util.unpack
2013-04-30 15:16:59 +02:00
local table_delim = ","
local string_chars = {
["\r"] = "\\r",
["\n"] = "\\n"
}
2014-03-07 04:19:12 +01:00
return {
2013-04-30 15:16:59 +02:00
exp = function(self, node)
local _comp
_comp = function(i, value)
if i % 2 == 1 and value == "!=" then
value = "~="
end
return self:value(value)
end
do
local _with_0 = self:line()
_with_0:append_list((function()
local _accum_0 = { }
local _len_0 = 1
for i, v in ipairs(node) do
if i > 1 then
_accum_0[_len_0] = _comp(i, v)
_len_0 = _len_0 + 1
end
end
return _accum_0
end)(), " ")
return _with_0
end
end,
explist = function(self, node)
do
local _with_0 = self:line()
_with_0:append_list((function()
local _accum_0 = { }
local _len_0 = 1
2013-07-04 01:11:42 +02:00
for _index_0 = 2, #node do
local v = node[_index_0]
2013-04-30 15:16:59 +02:00
_accum_0[_len_0] = self:value(v)
_len_0 = _len_0 + 1
end
return _accum_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 = unpack(node)
local end_delim = delim:gsub("%[", "]")
if delim == "'" or delim == '"' then
inner = inner:gsub("[\r\n]", string_chars)
end
return delim .. inner .. end_delim
end,
chain = function(self, node)
local callee = node[2]
2014-03-07 04:19:12 +01:00
local callee_type = ntype(callee)
2013-04-30 15:16:59 +02:00
if callee == -1 then
callee = self:get("scope_var")
if not callee then
user_error("Short-dot syntax must be called within a with block")
end
end
2014-03-07 04:19:12 +01:00
if callee_type == "ref" and callee[2] == "super" or callee == "super" then
do
local sup = self:get("super")
if sup then
return self:value(sup(self, node))
end
end
2013-04-30 15:16:59 +02:00
end
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 ".", tostring(arg)
elseif t == "colon" then
return ":", arg, chain_item(node[3])
elseif t == "colon_stub" then
return user_error("Uncalled colon stub")
else
2014-03-07 04:19:12 +01:00
return error("Unknown chain action: " .. tostring(t))
2013-04-30 15:16:59 +02:00
end
end
2014-03-07 04:19:12 +01:00
if (callee_type == "self" or callee_type == "self_class") and node[3] and ntype(node[3]) == "call" then
callee[1] = callee_type .. "_colon"
2013-04-30 15:16:59 +02:00
end
local callee_value = self:value(callee)
if ntype(callee) == "exp" then
callee_value = self:line("(", callee_value, ")")
end
local actions
do
local _with_0 = self:line()
2013-07-04 01:11:42 +02:00
for _index_0 = 3, #node do
local action = node[_index_0]
2013-04-30 15:16:59 +02:00
_with_0:append(chain_item(action))
end
actions = _with_0
end
return self:line(callee_value, actions)
end,
fndef = function(self, node)
local _, args, whitelist, arrow, block = unpack(node)
local default_args = { }
local self_args = { }
2013-07-04 01:11:42 +02:00
local arg_names
do
2013-04-30 15:16:59 +02:00
local _accum_0 = { }
local _len_0 = 1
2013-07-04 01:11:42 +02:00
for _index_0 = 1, #args do
local arg = args[_index_0]
2013-04-30 15:16:59 +02:00
local name, default_value = unpack(arg)
if type(name) == "string" then
name = name
else
if name[1] == "self" or name[1] == "self_class" then
insert(self_args, name)
end
name = name[2]
end
if default_value then
insert(default_args, arg)
end
local _value_0 = name
_accum_0[_len_0] = _value_0
_len_0 = _len_0 + 1
end
2013-07-04 01:11:42 +02:00
arg_names = _accum_0
end
2013-04-30 15:16:59 +02:00
if arrow == "fat" then
insert(arg_names, 1, "self")
end
do
local _with_0 = self:block()
if #whitelist > 0 then
_with_0:whitelist_names(whitelist)
end
2013-07-04 01:11:42 +02:00
for _index_0 = 1, #arg_names do
local name = arg_names[_index_0]
2013-04-30 15:16:59 +02:00
_with_0:put_name(name)
end
2013-07-04 01:11:42 +02:00
for _index_0 = 1, #default_args do
local default = default_args[_index_0]
2013-04-30 15:16:59 +02:00
local name, value = unpack(default)
if type(name) == "table" then
name = name[2]
end
_with_0:stm({
'if',
{
'exp',
2014-03-07 04:19:12 +01:00
{
"ref",
name
},
2013-04-30 15:16:59 +02:00
'==',
'nil'
},
{
{
'assign',
{
name
},
{
value
}
}
}
})
end
2013-07-04 01:11:42 +02:00
local self_arg_values
do
2013-04-30 15:16:59 +02:00
local _accum_0 = { }
local _len_0 = 1
2013-07-04 01:11:42 +02:00
for _index_0 = 1, #self_args do
local arg = self_args[_index_0]
2013-04-30 15:16:59 +02:00
_accum_0[_len_0] = arg[2]
_len_0 = _len_0 + 1
end
2013-07-04 01:11:42 +02:00
self_arg_values = _accum_0
end
2013-04-30 15:16:59 +02:00
if #self_args > 0 then
_with_0:stm({
"assign",
self_args,
self_arg_values
})
end
_with_0:stms(block)
if #args > #arg_names then
2013-07-04 01:11:42 +02:00
do
2013-04-30 15:16:59 +02:00
local _accum_0 = { }
local _len_0 = 1
2013-07-04 01:11:42 +02:00
for _index_0 = 1, #args do
local arg = args[_index_0]
2013-04-30 15:16:59 +02:00
_accum_0[_len_0] = arg[1]
_len_0 = _len_0 + 1
end
2013-07-04 01:11:42 +02:00
arg_names = _accum_0
end
2013-04-30 15:16:59 +02:00
end
_with_0.header = "function(" .. concat(arg_names, ", ") .. ")"
return _with_0
end
end,
table = function(self, node)
local _, items = unpack(node)
do
local _with_0 = self:block("{", "}")
local format_line
format_line = function(tuple)
if #tuple == 2 then
local key, value = unpack(tuple)
if ntype(key) == "key_literal" and data.lua_keywords[key[2]] then
key = {
"string",
'"',
key[2]
}
end
local assign
if ntype(key) == "key_literal" then
assign = key[2]
else
assign = self:line("[", _with_0:value(key), "]")
end
_with_0:set("current_block", key)
local out = self:line(assign, " = ", _with_0:value(value))
_with_0:set("current_block", nil)
return out
else
return self:line(_with_0:value(tuple[1]))
end
end
if items then
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
end
end,
minus = function(self, node)
return self:line("-", self:value(node[2]))
end,
temp_name = function(self, node, ...)
return node:get_name(self, ...)
end,
number = function(self, node)
return node[2]
end,
length = function(self, node)
return self:line("#", self:value(node[2]))
end,
["not"] = function(self, node)
return self:line("not ", self:value(node[2]))
end,
self = function(self, node)
2014-03-07 04:19:12 +01:00
return "self." .. self:name(node[2])
2013-04-30 15:16:59 +02:00
end,
self_class = function(self, node)
2014-03-07 04:19:12 +01:00
return "self.__class." .. self:name(node[2])
2013-04-30 15:16:59 +02:00
end,
self_colon = function(self, node)
2014-03-07 04:19:12 +01:00
return "self:" .. self:name(node[2])
2013-04-30 15:16:59 +02:00
end,
self_class_colon = function(self, node)
2014-03-07 04:19:12 +01:00
return "self.__class:" .. self:name(node[2])
2013-04-30 15:16:59 +02:00
end,
2014-03-07 04:19:12 +01:00
ref = function(self, value)
do
local sup = value[2] == "super" and self:get("super")
if sup then
return self:value(sup(self))
end
2013-04-30 15:16:59 +02:00
end
2014-03-07 04:19:12 +01:00
return tostring(value[2])
end,
raw_value = function(self, value)
2013-04-30 15:16:59 +02:00
if value == "..." then
self:send("varargs")
end
return tostring(value)
end
}
end
package.preload['moonscript.compile'] = function()
local util = require("moonscript.util")
local dump = require("moonscript.dump")
local transform = require("moonscript.transform")
local NameProxy, LocalName
do
2013-07-04 01:11:42 +02:00
local _obj_0 = require("moonscript.transform.names")
NameProxy, LocalName = _obj_0.NameProxy, _obj_0.LocalName
2013-04-30 15:16:59 +02:00
end
local Set
2015-02-03 18:54:34 +01:00
Set = require("moonscript.data").Set
2013-04-30 15:16:59 +02:00
local ntype, has_value
do
2013-07-04 01:11:42 +02:00
local _obj_0 = require("moonscript.types")
ntype, has_value = _obj_0.ntype, _obj_0.has_value
2013-04-30 15:16:59 +02:00
end
2014-03-07 04:19:12 +01:00
local statement_compilers = require("moonscript.compile.statement")
local value_compilers = require("moonscript.compile.value")
2013-07-04 01:11:42 +02:00
local concat, insert
do
local _obj_0 = table
concat, insert = _obj_0.concat, _obj_0.insert
end
local pos_to_line, get_closest_line, trim, unpack
pos_to_line, get_closest_line, trim, unpack = util.pos_to_line, util.get_closest_line, util.trim, util.unpack
2013-04-30 15:16:59 +02:00
local mtype = util.moon.type
local indent_char = " "
local Line, DelayedLine, Lines, Block, RootBlock
do
local _base_0 = {
mark_pos = function(self, pos, line)
if line == nil then
line = #self
end
if not (self.posmap[line]) then
self.posmap[line] = pos
end
end,
add = function(self, item)
local _exp_0 = mtype(item)
if Line == _exp_0 then
item:render(self)
elseif Block == _exp_0 then
item:render(self)
else
self[#self + 1] = item
end
return self
end,
flatten_posmap = function(self, line_no, out)
if line_no == nil then
line_no = 0
end
if out == nil then
out = { }
end
local posmap = self.posmap
for i, l in ipairs(self) do
local _exp_0 = mtype(l)
if "string" == _exp_0 or DelayedLine == _exp_0 then
line_no = line_no + 1
out[line_no] = posmap[i]
2014-03-07 04:19:12 +01:00
for _ in l:gmatch("\n") do
line_no = line_no + 1
end
out[line_no] = posmap[i]
2013-04-30 15:16:59 +02:00
elseif Lines == _exp_0 then
local _
_, line_no = l:flatten_posmap(line_no, out)
else
error("Unknown item in Lines: " .. tostring(l))
end
end
return out, line_no
end,
flatten = function(self, indent, buffer)
if indent == nil then
indent = nil
end
if buffer == nil then
buffer = { }
end
for i = 1, #self do
local l = self[i]
local t = mtype(l)
if t == DelayedLine then
l = l:render()
t = "string"
end
local _exp_0 = t
if "string" == _exp_0 then
if indent then
insert(buffer, indent)
end
insert(buffer, l)
if "string" == type(self[i + 1]) then
local lc = l:sub(-1)
if (lc == ")" or lc == "]") and self[i + 1]:sub(1, 1) == "(" then
insert(buffer, ";")
end
end
insert(buffer, "\n")
elseif Lines == _exp_0 then
l:flatten(indent and indent .. indent_char or indent_char, buffer)
else
error("Unknown item in Lines: " .. tostring(l))
end
end
return buffer
end,
__tostring = function(self)
local strip
strip = function(t)
if "table" == type(t) then
2013-07-04 01:11:42 +02:00
local _accum_0 = { }
local _len_0 = 1
for _index_0 = 1, #t do
local v = t[_index_0]
_accum_0[_len_0] = strip(v)
_len_0 = _len_0 + 1
end
return _accum_0
2013-04-30 15:16:59 +02:00
else
return t
end
end
return "Lines<" .. tostring(util.dump(strip(self)):sub(1, -2)) .. ">"
end
}
_base_0.__index = _base_0
local _class_0 = setmetatable({
__init = function(self)
self.posmap = { }
end,
__base = _base_0,
2013-07-04 01:11:42 +02:00
__name = "Lines"
2013-04-30 15:16:59 +02:00
}, {
2013-07-04 01:11:42 +02:00
__index = _base_0,
2013-04-30 15:16:59 +02:00
__call = function(cls, ...)
local _self_0 = setmetatable({}, _base_0)
cls.__init(_self_0, ...)
return _self_0
end
})
_base_0.__class = _class_0
Lines = _class_0
end
do
local _base_0 = {
pos = nil,
append_list = function(self, items, delim)
for i = 1, #items do
2014-03-07 04:19:12 +01:00
self:append(items[i])
2013-04-30 15:16:59 +02:00
if i < #items then
insert(self, delim)
end
end
return nil
end,
2014-03-07 04:19:12 +01:00
append = function(self, first, ...)
if Line == mtype(first) then
if not (self.pos) then
self.pos = first.pos
end
for _index_0 = 1, #first do
local value = first[_index_0]
self:append(value)
end
else
insert(self, first)
end
if ... then
return self:append(...)
2013-04-30 15:16:59 +02:00
end
end,
render = function(self, buffer)
local current = { }
local add_current
add_current = function()
buffer:add(concat(current))
return buffer:mark_pos(self.pos)
end
2013-07-04 01:11:42 +02:00
for _index_0 = 1, #self do
local chunk = self[_index_0]
2013-04-30 15:16:59 +02:00
local _exp_0 = mtype(chunk)
if Block == _exp_0 then
2013-07-04 01:11:42 +02:00
local _list_0 = chunk:render(Lines())
for _index_1 = 1, #_list_0 do
local block_chunk = _list_0[_index_1]
2013-04-30 15:16:59 +02:00
if "string" == type(block_chunk) then
insert(current, block_chunk)
else
add_current()
buffer:add(block_chunk)
current = { }
end
end
else
insert(current, chunk)
end
end
2014-03-07 04:19:12 +01:00
if current[1] then
2013-04-30 15:16:59 +02:00
add_current()
end
return buffer
end,
__tostring = function(self)
return "Line<" .. tostring(util.dump(self):sub(1, -2)) .. ">"
end
}
_base_0.__index = _base_0
local _class_0 = setmetatable({
2013-07-04 01:11:42 +02:00
__init = function() end,
2013-04-30 15:16:59 +02:00
__base = _base_0,
2013-07-04 01:11:42 +02:00
__name = "Line"
2013-04-30 15:16:59 +02:00
}, {
2013-07-04 01:11:42 +02:00
__index = _base_0,
2013-04-30 15:16:59 +02:00
__call = function(cls, ...)
local _self_0 = setmetatable({}, _base_0)
cls.__init(_self_0, ...)
return _self_0
end
})
_base_0.__class = _class_0
Line = _class_0
end
do
local _base_0 = {
prepare = function() end,
render = function(self)
self:prepare()
return concat(self)
end
}
_base_0.__index = _base_0
local _class_0 = setmetatable({
__init = function(self, fn)
self.prepare = fn
end,
__base = _base_0,
2013-07-04 01:11:42 +02:00
__name = "DelayedLine"
2013-04-30 15:16:59 +02:00
}, {
2013-07-04 01:11:42 +02:00
__index = _base_0,
2013-04-30 15:16:59 +02:00
__call = function(cls, ...)
local _self_0 = setmetatable({}, _base_0)
cls.__init(_self_0, ...)
return _self_0
end
})
_base_0.__class = _class_0
DelayedLine = _class_0
end
do
local _base_0 = {
header = "do",
footer = "end",
export_all = false,
export_proper = false,
2014-03-07 04:19:12 +01:00
value_compilers = value_compilers,
2015-02-03 18:54:34 +01:00
statement_compilers = statement_compilers,
2013-04-30 15:16:59 +02:00
__tostring = function(self)
local h
if "string" == type(self.header) then
h = self.header
else
h = unpack(self.header:render({ }))
end
return "Block<" .. tostring(h) .. "> <- " .. tostring(self.parent)
end,
set = function(self, name, value)
self._state[name] = value
end,
get = function(self, name)
return self._state[name]
end,
get_current = function(self, name)
return rawget(self._state, name)
end,
listen = function(self, name, fn)
self._listeners[name] = fn
end,
unlisten = function(self, name)
self._listeners[name] = nil
end,
send = function(self, name, ...)
do
local fn = self._listeners[name]
if fn then
return fn(self, ...)
end
end
end,
2015-02-03 18:54:34 +01:00
extract_assign_name = function(self, node)
local is_local = false
local real_name
local _exp_0 = mtype(node)
if LocalName == _exp_0 then
is_local = true
real_name = node:get_name(self)
elseif NameProxy == _exp_0 then
real_name = node:get_name(self)
elseif "table" == _exp_0 then
real_name = node[1] == "ref" and node[2]
elseif "string" == _exp_0 then
real_name = node
end
return real_name, is_local
end,
2013-04-30 15:16:59 +02:00
declare = function(self, names)
2013-07-04 01:11:42 +02:00
local undeclared
do
2013-04-30 15:16:59 +02:00
local _accum_0 = { }
local _len_0 = 1
2013-07-04 01:11:42 +02:00
for _index_0 = 1, #names do
2013-04-30 15:16:59 +02:00
local _continue_0 = false
repeat
2013-07-04 01:11:42 +02:00
local name = names[_index_0]
2015-02-03 18:54:34 +01:00
local real_name, is_local = self:extract_assign_name(name)
2013-04-30 15:16:59 +02:00
if not (is_local or real_name and not self:has_name(real_name, true)) then
_continue_0 = true
break
end
self:put_name(real_name)
if self:name_exported(real_name) then
_continue_0 = true
break
end
local _value_0 = real_name
_accum_0[_len_0] = _value_0
_len_0 = _len_0 + 1
_continue_0 = true
until true
if not _continue_0 then
break
end
end
2013-07-04 01:11:42 +02:00
undeclared = _accum_0
end
2013-04-30 15:16:59 +02:00
return undeclared
end,
whitelist_names = function(self, names)
self._name_whitelist = Set(names)
end,
name_exported = function(self, name)
if self.export_all then
return true
end
if self.export_proper and name:match("^%u") then
return true
end
end,
put_name = function(self, name, ...)
local value = ...
if select("#", ...) == 0 then
value = true
end
if NameProxy == mtype(name) then
name = name:get_name(self)
end
self._names[name] = value
end,
has_name = function(self, name, skip_exports)
if not skip_exports and self:name_exported(name) then
return true
end
local yes = self._names[name]
if yes == nil and self.parent then
if not self._name_whitelist or self._name_whitelist[name] then
return self.parent:has_name(name, true)
end
else
return yes
end
end,
2013-07-04 01:11:42 +02:00
is_local = function(self, node)
local t = mtype(node)
if t == "string" then
return self:has_name(node, false)
end
if t == NameProxy or t == LocalName then
return true
end
2014-03-07 04:19:12 +01:00
if t == "table" then
if node[1] == "ref" or (node[1] == "chain" and #node == 2) then
return self:is_local(node[2])
end
2013-07-04 01:11:42 +02:00
end
return false
end,
2013-04-30 15:16:59 +02:00
free_name = function(self, prefix, dont_put)
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, true)
end
if not dont_put then
self:put_name(name)
end
return name
end,
init_free_var = function(self, prefix, value)
local name = self:free_name(prefix, true)
self:stm({
"assign",
{
name
},
{
value
}
})
return name
end,
2015-02-03 18:54:34 +01:00
add = function(self, item, pos)
do
local _with_0 = self._lines
_with_0:add(item)
if pos then
_with_0:mark_pos(pos)
end
end
2013-04-30 15:16:59 +02:00
return item
end,
render = function(self, buffer)
buffer:add(self.header)
buffer:mark_pos(self.pos)
if self.next then
buffer:add(self._lines)
self.next:render(buffer)
else
if #self._lines == 0 and "string" == type(buffer[#buffer]) then
buffer[#buffer] = buffer[#buffer] .. (" " .. (unpack(Lines():add(self.footer))))
else
buffer:add(self._lines)
buffer:add(self.footer)
buffer:mark_pos(self.pos)
end
end
return buffer
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
end,
is_stm = function(self, node)
2015-02-03 18:54:34 +01:00
return self.statement_compilers[ntype(node)] ~= nil
2013-04-30 15:16:59 +02:00
end,
is_value = function(self, node)
local t = ntype(node)
2014-03-07 04:19:12 +01:00
return self.value_compilers[t] ~= nil or t == "value"
2013-04-30 15:16:59 +02:00
end,
name = function(self, node, ...)
2014-03-07 04:19:12 +01:00
if type(node) == "string" then
return node
else
return self:value(node, ...)
end
2013-04-30 15:16:59 +02:00
end,
value = function(self, node, ...)
node = self.transform.value(node)
local action
if type(node) ~= "table" then
action = "raw_value"
else
action = node[1]
end
2014-03-07 04:19:12 +01:00
local fn = self.value_compilers[action]
if not (fn) then
error({
"compile-error",
"Failed to find value compiler for: " .. dump.value(node),
node[-1]
})
2013-04-30 15:16:59 +02:00
end
local out = fn(self, node, ...)
if type(node) == "table" and node[-1] then
if type(out) == "string" then
do
local _with_0 = Line()
_with_0:append(out)
out = _with_0
end
end
out.pos = node[-1]
end
return out
end,
values = function(self, values, delim)
delim = delim or ', '
do
local _with_0 = Line()
_with_0:append_list((function()
local _accum_0 = { }
local _len_0 = 1
2013-07-04 01:11:42 +02:00
for _index_0 = 1, #values do
local v = values[_index_0]
2013-04-30 15:16:59 +02:00
_accum_0[_len_0] = self:value(v)
_len_0 = _len_0 + 1
end
return _accum_0
end)(), delim)
return _with_0
end
end,
stm = function(self, node, ...)
if not node then
return
end
node = self.transform.statement(node)
local result
do
2015-02-03 18:54:34 +01:00
local fn = self.statement_compilers[ntype(node)]
2013-04-30 15:16:59 +02:00
if fn then
result = fn(self, node, ...)
else
if has_value(node) then
result = self:stm({
"assign",
{
"_"
},
{
node
}
})
else
result = self:value(node)
end
end
end
if result then
if type(node) == "table" and type(result) == "table" and node[-1] then
result.pos = node[-1]
end
self:add(result)
end
return nil
end,
stms = function(self, stms, ret)
if ret then
error("deprecated stms call, use transformer")
end
local current_stms, current_stm_i
2013-07-04 01:11:42 +02:00
current_stms, current_stm_i = self.current_stms, self.current_stm_i
2013-04-30 15:16:59 +02:00
self.current_stms = stms
for i = 1, #stms do
self.current_stm_i = i
self:stm(stms[i])
end
self.current_stms = current_stms
self.current_stm_i = current_stm_i
return nil
end,
splice = function(self, fn)
local lines = {
"lines",
self._lines
}
self._lines = Lines()
return self:stms(fn(lines))
end
}
_base_0.__index = _base_0
local _class_0 = setmetatable({
__init = function(self, parent, header, footer)
self.parent, self.header, self.footer = parent, header, footer
self._lines = Lines()
self._names = { }
self._state = { }
self._listeners = { }
do
self.transform = {
2013-07-04 01:11:42 +02:00
value = transform.Value:bind(self),
statement = transform.Statement:bind(self)
2013-04-30 15:16:59 +02:00
}
end
if self.parent then
self.root = self.parent.root
self.indent = self.parent.indent + 1
setmetatable(self._state, {
__index = self.parent._state
})
return setmetatable(self._listeners, {
__index = self.parent._listeners
})
else
self.indent = 0
end
end,
__base = _base_0,
2013-07-04 01:11:42 +02:00
__name = "Block"
2013-04-30 15:16:59 +02:00
}, {
2013-07-04 01:11:42 +02:00
__index = _base_0,
2013-04-30 15:16:59 +02:00
__call = function(cls, ...)
local _self_0 = setmetatable({}, _base_0)
cls.__init(_self_0, ...)
return _self_0
end
})
_base_0.__class = _class_0
Block = _class_0
end
do
local _parent_0 = Block
local _base_0 = {
__tostring = function(self)
return "RootBlock<>"
end,
root_stms = function(self, stms)
if not (self.options.implicitly_return_root == false) then
stms = transform.Statement.transformers.root_stms(self, stms)
end
return self:stms(stms)
end,
render = function(self)
local buffer = self._lines:flatten()
if buffer[#buffer] == "\n" then
buffer[#buffer] = nil
end
return table.concat(buffer)
end
}
_base_0.__index = _base_0
2013-07-04 01:11:42 +02:00
setmetatable(_base_0, _parent_0.__base)
2013-04-30 15:16:59 +02:00
local _class_0 = setmetatable({
__init = function(self, options)
self.options = options
self.root = self
return _parent_0.__init(self)
end,
__base = _base_0,
__name = "RootBlock",
__parent = _parent_0
}, {
__index = function(cls, name)
local val = rawget(_base_0, name)
2013-07-04 01:11:42 +02:00
if val == nil then
2013-04-30 15:16:59 +02:00
return _parent_0[name]
else
return val
end
end,
__call = function(cls, ...)
local _self_0 = setmetatable({}, _base_0)
cls.__init(_self_0, ...)
return _self_0
end
})
_base_0.__class = _class_0
2013-07-04 01:11:42 +02:00
if _parent_0.__inherited then
2013-04-30 15:16:59 +02:00
_parent_0.__inherited(_parent_0, _class_0)
end
RootBlock = _class_0
end
local format_error
format_error = function(msg, pos, file_str)
2014-03-07 04:19:12 +01:00
local line_message
if pos then
local line = pos_to_line(file_str, pos)
local line_str
line_str, line = get_closest_line(file_str, line)
line_str = line_str or ""
line_message = (" [%d] >> %s"):format(line, trim(line_str))
end
2013-04-30 15:16:59 +02:00
return concat({
"Compile error: " .. msg,
2014-03-07 04:19:12 +01:00
line_message
2013-04-30 15:16:59 +02:00
}, "\n")
end
local value
value = function(value)
local out = nil
do
local _with_0 = RootBlock()
_with_0:add(_with_0:value(value))
out = _with_0:render()
end
return out
end
local tree
tree = function(tree, options)
if options == nil then
options = { }
end
assert(tree, "missing tree")
local scope = (options.scope or RootBlock)(options)
local runner = coroutine.create(function()
return scope:root_stms(tree)
end)
local success, err = coroutine.resume(runner)
2014-03-07 04:19:12 +01:00
if not (success) then
local error_msg, error_pos
2013-04-30 15:16:59 +02:00
if type(err) == "table" then
2014-03-07 04:19:12 +01:00
local _exp_0 = err[1]
if "user-error" == _exp_0 or "compile-error" == _exp_0 then
error_msg, error_pos = unpack(err, 2)
2013-04-30 15:16:59 +02:00
else
2014-03-07 04:19:12 +01:00
error_msg, error_pos = error("Unknown error thrown", util.dump(error_msg))
2013-04-30 15:16:59 +02:00
end
else
2014-03-07 04:19:12 +01:00
error_msg, error_pos = concat({
2013-04-30 15:16:59 +02:00
err,
debug.traceback(runner)
}, "\n")
end
2014-03-07 04:19:12 +01:00
return nil, error_msg, error_pos or scope.last_pos
2013-04-30 15:16:59 +02:00
end
2014-03-07 04:19:12 +01:00
local lua_code = scope:render()
local posmap = scope._lines:flatten_posmap()
return lua_code, posmap
2013-04-30 15:16:59 +02:00
end
do
2013-07-04 01:11:42 +02:00
local data = require("moonscript.data")
2013-04-30 15:16:59 +02:00
for name, cls in pairs({
Line = Line,
Lines = Lines,
DelayedLine = DelayedLine
}) do
data[name] = cls
end
end
return {
tree = tree,
value = value,
format_error = format_error,
Block = Block,
RootBlock = RootBlock
}
end
package.preload['moonscript.data'] = function()
2013-07-04 01:11:42 +02:00
local concat, remove, insert
do
local _obj_0 = table
concat, remove, insert = _obj_0.concat, _obj_0.remove, _obj_0.insert
end
2013-04-30 15:16:59 +02:00
local Set
Set = function(items)
2014-03-07 04:19:12 +01:00
local _tbl_0 = { }
2013-07-04 01:11:42 +02:00
for _index_0 = 1, #items do
2014-03-07 04:19:12 +01:00
local k = items[_index_0]
_tbl_0[k] = true
2013-04-30 15:16:59 +02:00
end
2014-03-07 04:19:12 +01:00
return _tbl_0
2013-04-30 15:16:59 +02:00
end
local Stack
do
local _base_0 = {
__tostring = function(self)
return "<Stack {" .. concat(self, ", ") .. "}>"
end,
pop = function(self)
return remove(self)
end,
2014-03-07 04:19:12 +01:00
push = function(self, value, ...)
2013-04-30 15:16:59 +02:00
insert(self, value)
2014-03-07 04:19:12 +01:00
if ... then
return self:push(...)
else
return value
end
2013-04-30 15:16:59 +02:00
end,
top = function(self)
return self[#self]
end
}
_base_0.__index = _base_0
local _class_0 = setmetatable({
__init = function(self, ...)
2014-03-07 04:19:12 +01:00
self:push(...)
2013-04-30 15:16:59 +02:00
return nil
end,
__base = _base_0,
2013-07-04 01:11:42 +02:00
__name = "Stack"
2013-04-30 15:16:59 +02:00
}, {
2013-07-04 01:11:42 +02:00
__index = _base_0,
2013-04-30 15:16:59 +02:00
__call = function(cls, ...)
local _self_0 = setmetatable({}, _base_0)
cls.__init(_self_0, ...)
return _self_0
end
})
_base_0.__class = _class_0
Stack = _class_0
end
local lua_keywords = Set({
'and',
'break',
'do',
'else',
'elseif',
'end',
'false',
'for',
'function',
'if',
'in',
'local',
'nil',
'not',
'or',
'repeat',
'return',
'then',
'true',
'until',
'while'
})
return {
Set = Set,
Stack = Stack,
lua_keywords = lua_keywords
}
end
package.preload['moonscript.dump'] = function()
local flat_value
flat_value = function(op, depth)
if depth == nil then
depth = 1
end
if type(op) == "string" then
return '"' .. op .. '"'
end
if type(op) ~= "table" then
return tostring(op)
end
2013-07-04 01:11:42 +02:00
local items
do
2013-04-30 15:16:59 +02:00
local _accum_0 = { }
local _len_0 = 1
2013-07-04 01:11:42 +02:00
for _index_0 = 1, #op do
local item = op[_index_0]
2013-04-30 15:16:59 +02:00
_accum_0[_len_0] = flat_value(item, depth + 1)
_len_0 = _len_0 + 1
end
2013-07-04 01:11:42 +02:00
items = _accum_0
end
2013-04-30 15:16:59 +02:00
local pos = op[-1]
return "{" .. (pos and "[" .. pos .. "] " or "") .. table.concat(items, ", ") .. "}"
end
local value
value = function(op)
return flat_value(op)
end
local tree
tree = function(block)
local _list_0 = block
for _index_0 = 1, #_list_0 do
value = _list_0[_index_0]
print(flat_value(value))
end
end
return {
value = value,
tree = tree
}
end
package.preload['moonscript.errors'] = function()
local util = require("moonscript.util")
local lpeg = require("lpeg")
2013-07-04 01:11:42 +02:00
local concat, insert
do
local _obj_0 = table
concat, insert = _obj_0.concat, _obj_0.insert
end
local split, pos_to_line
split, pos_to_line = util.split, util.pos_to_line
2013-04-30 15:16:59 +02:00
local user_error
user_error = function(...)
return error({
"user-error",
...
})
end
local lookup_line
lookup_line = function(fname, pos, cache)
if not cache[fname] then
do
2015-02-03 18:54:34 +01:00
local _with_0 = assert(io.open(fname))
2013-04-30 15:16:59 +02:00
cache[fname] = _with_0:read("*a")
_with_0:close()
end
end
return pos_to_line(cache[fname], pos)
end
local reverse_line_number
reverse_line_number = function(fname, line_table, line_num, cache)
for i = line_num, 0, -1 do
if line_table[i] then
return lookup_line(fname, line_table[i], cache)
end
end
return "unknown"
end
local truncate_traceback
truncate_traceback = function(traceback, chunk_func)
if chunk_func == nil then
chunk_func = "moonscript_chunk"
end
traceback = split(traceback, "\n")
local stop = #traceback
while stop > 1 do
if traceback[stop]:match(chunk_func) then
break
end
stop = stop - 1
end
2013-07-04 01:11:42 +02:00
do
2013-04-30 15:16:59 +02:00
local _accum_0 = { }
local _len_0 = 1
local _max_0 = stop
2013-07-04 01:11:42 +02:00
for _index_0 = 1, _max_0 < 0 and #traceback + _max_0 or _max_0 do
local t = traceback[_index_0]
2013-04-30 15:16:59 +02:00
_accum_0[_len_0] = t
_len_0 = _len_0 + 1
end
2013-07-04 01:11:42 +02:00
traceback = _accum_0
end
2013-04-30 15:16:59 +02:00
local rep = "function '" .. chunk_func .. "'"
traceback[#traceback] = traceback[#traceback]:gsub(rep, "main chunk")
return concat(traceback, "\n")
end
local rewrite_traceback
rewrite_traceback = function(text, err)
local line_tables = require("moonscript.line_tables")
2013-07-04 01:11:42 +02:00
local V, S, Ct, C
V, S, Ct, C = lpeg.V, lpeg.S, lpeg.Ct, lpeg.C
2013-04-30 15:16:59 +02:00
local header_text = "stack traceback:"
local Header, Line = V("Header"), V("Line")
local Break = lpeg.S("\n")
local g = lpeg.P({
Header,
Header = header_text * Break * Ct(Line ^ 1),
Line = "\t" * C((1 - Break) ^ 0) * (Break + -1)
})
local cache = { }
local rewrite_single
rewrite_single = function(trace)
2015-02-03 18:54:34 +01:00
local fname, line, msg = trace:match('^(.-):(%d+): (.*)$')
local tbl = line_tables["@" .. tostring(fname)]
2013-04-30 15:16:59 +02:00
if fname and tbl then
return concat({
fname,
":",
reverse_line_number(fname, tbl, line, cache),
": ",
"(",
line,
") ",
msg
})
else
return trace
end
end
err = rewrite_single(err)
local match = g:match(text)
if not (match) then
return nil
end
for i, trace in ipairs(match) do
match[i] = rewrite_single(trace)
end
return concat({
"moon: " .. err,
header_text,
"\t" .. concat(match, "\n\t")
}, "\n")
end
return {
rewrite_traceback = rewrite_traceback,
truncate_traceback = truncate_traceback,
2013-07-04 01:11:42 +02:00
user_error = user_error,
reverse_line_number = reverse_line_number
2013-04-30 15:16:59 +02:00
}
end
package.preload['moonscript'] = function()
2015-02-03 18:54:34 +01:00
do
local _with_0 = require("moonscript.base")
return _with_0
end
2013-04-30 15:16:59 +02:00
end
package.preload['moonscript.line_tables'] = function()
return { }
end
2015-02-03 18:54:34 +01:00
package.preload['moonscript.parse.env'] = function()
local getfenv, setfenv
do
local _obj_0 = require("moonscript.util")
getfenv, setfenv = _obj_0.getfenv, _obj_0.setfenv
2013-04-30 15:16:59 +02:00
end
2015-02-03 18:54:34 +01:00
local wrap_env
wrap_env = function(debug, fn)
local V, Cmt
do
local _obj_0 = require("lpeg")
V, Cmt = _obj_0.V, _obj_0.Cmt
end
local env = getfenv(fn)
local wrap_name = V
if debug then
local indent = 0
local indent_char = " "
local iprint
iprint = function(...)
local args = table.concat((function(...)
local _accum_0 = { }
local _len_0 = 1
local _list_0 = {
...
}
for _index_0 = 1, #_list_0 do
local a = _list_0[_index_0]
_accum_0[_len_0] = tostring(a)
_len_0 = _len_0 + 1
end
return _accum_0
end)(...), ", ")
return io.stderr:write(tostring(indent_char:rep(indent)) .. tostring(args) .. "\n")
end
wrap_name = function(name)
local v = V(name)
v = Cmt("", function()
iprint("* " .. name)
indent = indent + 1
return true
end) * Cmt(v, function(str, pos, ...)
iprint(name, true)
indent = indent - 1
return true, ...
end) + Cmt("", function()
iprint(name, false)
indent = indent - 1
return false
end)
return v
end
end
return setfenv(fn, setmetatable({ }, {
__index = function(self, name)
local value = env[name]
if value ~= nil then
return value
end
if name:match("^[A-Z][A-Za-z0-9]*$") then
local v = wrap_name(name)
return v
end
return error("unknown variable referenced: " .. tostring(name))
end
}))
end
return {
wrap_env = wrap_env
}
2013-04-30 15:16:59 +02:00
2015-02-03 18:54:34 +01:00
end
package.preload['moonscript.parse.literals'] = function()
local safe_module
safe_module = require("moonscript.util").safe_module
local S, P, R, C
do
local _obj_0 = require("lpeg")
S, P, R, C = _obj_0.S, _obj_0.P, _obj_0.R, _obj_0.C
end
local White = S(" \t\r\n") ^ 0
local plain_space = S(" \t") ^ 0
local Break = P("\r") ^ -1 * P("\n")
2013-04-30 15:16:59 +02:00
local Stop = Break + -1
2015-02-03 18:54:34 +01:00
local Comment = P("--") * (1 - S("\r\n")) ^ 0 * #Stop
local Space = plain_space * Comment ^ -1
local SomeSpace = S(" \t") ^ 1 * Comment ^ -1
2013-04-30 15:16:59 +02:00
local SpaceBreak = Space * Break
local EmptyLine = SpaceBreak
local AlphaNum = R("az", "AZ", "09", "__")
2015-02-03 18:54:34 +01:00
local Name = C(R("az", "AZ", "__") * AlphaNum ^ 0)
local Num = P("0x") * R("09", "af", "AF") ^ 1 * (S("uU") ^ -1 * S("lL") ^ 2) ^ -1 + R("09") ^ 1 * (S("uU") ^ -1 * S("lL") ^ 2) + (R("09") ^ 1 * (P(".") * R("09") ^ 1) ^ -1 + P(".") * R("09") ^ 1) * (S("eE") * P("-") ^ -1 * R("09") ^ 1) ^ -1
local Shebang = P("#!") * P(1 - Stop) ^ 0
return safe_module("moonscript.parse.literals", {
White = White,
Break = Break,
Stop = Stop,
Comment = Comment,
Space = Space,
SomeSpace = SomeSpace,
SpaceBreak = SpaceBreak,
EmptyLine = EmptyLine,
AlphaNum = AlphaNum,
Name = Name,
Num = Num,
Shebang = Shebang
})
2013-04-30 15:16:59 +02:00
2015-02-03 18:54:34 +01:00
end
package.preload['moonscript.parse.util'] = function()
local unpack
unpack = require("moonscript.util").unpack
local P, C, S, Cp, Cmt, V
do
local _obj_0 = require("lpeg")
P, C, S, Cp, Cmt, V = _obj_0.P, _obj_0.C, _obj_0.S, _obj_0.Cp, _obj_0.Cmt, _obj_0.V
2013-04-30 15:16:59 +02:00
end
2015-02-03 18:54:34 +01:00
local ntype
ntype = require("moonscript.types").ntype
local Space
Space = require("moonscript.parse.literals").Space
local Indent = C(S("\t ") ^ 0) / function(str)
do
local sum = 0
for v in str:gmatch("[\t ]") do
local _exp_0 = v
if " " == _exp_0 then
sum = sum + 1
elseif "\t" == _exp_0 then
sum = sum + 4
end
end
return sum
end
2013-04-30 15:16:59 +02:00
end
2015-02-03 18:54:34 +01:00
local Cut = P(function()
return false
end)
local ensure
ensure = function(patt, finally)
return patt * finally + finally * Cut
2013-04-30 15:16:59 +02:00
end
2015-02-03 18:54:34 +01:00
local extract_line
extract_line = function(str, start_pos)
str = str:sub(start_pos)
do
local m = str:match("^(.-)\n")
if m then
return m
end
end
return str:match("^.-$")
2013-04-30 15:16:59 +02:00
end
2015-02-03 18:54:34 +01:00
local mark
mark = function(name)
return function(...)
return {
name,
...
}
end
end
local pos
pos = function(patt)
return (Cp() * patt) / function(pos, value)
2013-04-30 15:16:59 +02:00
if type(value) == "table" then
2015-02-03 18:54:34 +01:00
value[-1] = pos
2013-04-30 15:16:59 +02:00
end
return value
2015-02-03 18:54:34 +01:00
end
2013-04-30 15:16:59 +02:00
end
2015-02-03 18:54:34 +01:00
local got
got = function(what)
return Cmt("", function(str, pos)
print("++ got " .. tostring(what), "[" .. tostring(extract_line(str, pos)) .. "]")
return true
end)
2013-04-30 15:16:59 +02:00
end
2015-02-03 18:54:34 +01:00
local flatten_or_mark
flatten_or_mark = function(name)
return function(tbl)
if #tbl == 1 then
return tbl[1]
end
table.insert(tbl, 1, name)
return tbl
end
2013-04-30 15:16:59 +02:00
end
2015-02-03 18:54:34 +01:00
local is_assignable
do
local chain_assignable = {
index = true,
dot = true,
slice = true
}
is_assignable = function(node)
if node == "..." then
return false
end
local _exp_0 = ntype(node)
if "ref" == _exp_0 or "self" == _exp_0 or "value" == _exp_0 or "self_class" == _exp_0 or "table" == _exp_0 then
return true
elseif "chain" == _exp_0 then
return chain_assignable[ntype(node[#node])]
else
return false
end
end
2013-04-30 15:16:59 +02:00
end
2015-02-03 18:54:34 +01:00
local check_assignable
check_assignable = function(str, pos, value)
if is_assignable(value) then
return true, value
else
return false
end
2013-04-30 15:16:59 +02:00
end
2015-02-03 18:54:34 +01:00
local format_assign
do
local flatten_explist = flatten_or_mark("explist")
format_assign = function(lhs_exps, assign)
if not (assign) then
return flatten_explist(lhs_exps)
end
for _index_0 = 1, #lhs_exps do
local assign_exp = lhs_exps[_index_0]
if not (is_assignable(assign_exp)) then
error({
assign_exp,
"left hand expression is not assignable"
})
end
end
local t = ntype(assign)
local _exp_0 = t
if "assign" == _exp_0 then
return {
"assign",
lhs_exps,
unpack(assign, 2)
}
elseif "update" == _exp_0 then
return {
"update",
lhs_exps[1],
unpack(assign, 2)
}
else
return error("unknown assign expression: " .. tostring(t))
end
end
2013-04-30 15:16:59 +02:00
end
2015-02-03 18:54:34 +01:00
local format_single_assign
format_single_assign = function(lhs, assign)
if assign then
return format_assign({
lhs
}, assign)
else
return lhs
end
2013-04-30 15:16:59 +02:00
end
2015-02-03 18:54:34 +01:00
local sym
sym = function(chars)
return Space * chars
2013-04-30 15:16:59 +02:00
end
2015-02-03 18:54:34 +01:00
local symx
symx = function(chars)
return chars
2013-04-30 15:16:59 +02:00
end
2015-02-03 18:54:34 +01:00
local simple_string
simple_string = function(delim, allow_interpolation)
local inner = P("\\" .. tostring(delim)) + "\\\\" + (1 - P(delim))
if allow_interpolation then
local interp = symx('#{') * V("Exp") * sym('}')
inner = (C((inner - interp) ^ 1) + interp / mark("interpolate")) ^ 0
else
inner = C(inner ^ 0)
end
return C(symx(delim)) * inner * sym(delim) / mark("string")
2013-04-30 15:16:59 +02:00
end
2015-02-03 18:54:34 +01:00
local wrap_func_arg
wrap_func_arg = function(value)
return {
"call",
{
value
}
}
2013-04-30 15:16:59 +02:00
end
2015-02-03 18:54:34 +01:00
local flatten_func
flatten_func = function(callee, args)
if #args == 0 then
return callee
end
args = {
"call",
args
}
if ntype(callee) == "chain" then
local stub = callee[#callee]
if ntype(stub) == "colon_stub" then
stub[1] = "colon"
table.insert(stub, args)
else
table.insert(callee, args)
end
return callee
end
return {
"chain",
callee,
args
}
2013-04-30 15:16:59 +02:00
end
2015-02-03 18:54:34 +01:00
local flatten_string_chain
flatten_string_chain = function(str, chain, args)
if not (chain) then
return str
end
return flatten_func({
"chain",
str,
unpack(chain)
}, args)
2013-04-30 15:16:59 +02:00
end
2015-02-03 18:54:34 +01:00
local wrap_decorator
wrap_decorator = function(stm, dec)
if not (dec) then
return stm
end
return {
"decorated",
stm,
dec
}
2013-04-30 15:16:59 +02:00
end
2015-02-03 18:54:34 +01:00
local check_lua_string
check_lua_string = function(str, pos, right, left)
return #left == #right
2013-04-30 15:16:59 +02:00
end
2015-02-03 18:54:34 +01:00
local self_assign
self_assign = function(name, pos)
return {
{
"key_literal",
name
},
{
"ref",
name,
[-1] = pos
}
}
2013-04-30 15:16:59 +02:00
end
2015-02-03 18:54:34 +01:00
return {
Indent = Indent,
Cut = Cut,
ensure = ensure,
extract_line = extract_line,
mark = mark,
pos = pos,
flatten_or_mark = flatten_or_mark,
is_assignable = is_assignable,
check_assignable = check_assignable,
format_assign = format_assign,
format_single_assign = format_single_assign,
sym = sym,
symx = symx,
simple_string = simple_string,
wrap_func_arg = wrap_func_arg,
flatten_func = flatten_func,
flatten_string_chain = flatten_string_chain,
wrap_decorator = wrap_decorator,
check_lua_string = check_lua_string,
self_assign = self_assign
}
2013-04-30 15:16:59 +02:00
2015-02-03 18:54:34 +01:00
end
package.preload['moonscript.parse'] = function()
local debug_grammar = false
local lpeg = require("lpeg")
lpeg.setmaxstack(10000)
local err_msg = "Failed to parse:%s\n [%d] >> %s"
local Stack
Stack = require("moonscript.data").Stack
local trim, pos_to_line, get_line
do
local _obj_0 = require("moonscript.util")
trim, pos_to_line, get_line = _obj_0.trim, _obj_0.pos_to_line, _obj_0.get_line
2013-04-30 15:16:59 +02:00
end
2015-02-03 18:54:34 +01:00
local unpack
unpack = require("moonscript.util").unpack
local wrap_env
wrap_env = require("moonscript.parse.env").wrap_env
local R, S, V, P, C, Ct, Cmt, Cg, Cb, Cc
R, S, V, P, C, Ct, Cmt, Cg, Cb, Cc = lpeg.R, lpeg.S, lpeg.V, lpeg.P, lpeg.C, lpeg.Ct, lpeg.Cmt, lpeg.Cg, lpeg.Cb, lpeg.Cc
local White, Break, Stop, Comment, Space, SomeSpace, SpaceBreak, EmptyLine, AlphaNum, Num, Shebang, _Name
do
local _obj_0 = require("moonscript.parse.literals")
White, Break, Stop, Comment, Space, SomeSpace, SpaceBreak, EmptyLine, AlphaNum, Num, Shebang, _Name = _obj_0.White, _obj_0.Break, _obj_0.Stop, _obj_0.Comment, _obj_0.Space, _obj_0.SomeSpace, _obj_0.SpaceBreak, _obj_0.EmptyLine, _obj_0.AlphaNum, _obj_0.Num, _obj_0.Shebang, _obj_0.Name
2013-04-30 15:16:59 +02:00
end
2015-02-03 18:54:34 +01:00
local SpaceName = Space * _Name
Num = Space * (Num / function(v)
return {
"number",
v
}
end)
local Indent, Cut, ensure, extract_line, mark, pos, flatten_or_mark, is_assignable, check_assignable, format_assign, format_single_assign, sym, symx, simple_string, wrap_func_arg, flatten_func, flatten_string_chain, wrap_decorator, check_lua_string, self_assign
do
local _obj_0 = require("moonscript.parse.util")
Indent, Cut, ensure, extract_line, mark, pos, flatten_or_mark, is_assignable, check_assignable, format_assign, format_single_assign, sym, symx, simple_string, wrap_func_arg, flatten_func, flatten_string_chain, wrap_decorator, check_lua_string, self_assign = _obj_0.Indent, _obj_0.Cut, _obj_0.ensure, _obj_0.extract_line, _obj_0.mark, _obj_0.pos, _obj_0.flatten_or_mark, _obj_0.is_assignable, _obj_0.check_assignable, _obj_0.format_assign, _obj_0.format_single_assign, _obj_0.sym, _obj_0.symx, _obj_0.simple_string, _obj_0.wrap_func_arg, _obj_0.flatten_func, _obj_0.flatten_string_chain, _obj_0.wrap_decorator, _obj_0.check_lua_string, _obj_0.self_assign
2013-04-30 15:16:59 +02:00
end
2015-02-03 18:54:34 +01:00
local build_grammar = wrap_env(debug_grammar, function()
local _indent = Stack(0)
local _do_stack = Stack(0)
local last_pos = 0
local check_indent
check_indent = function(str, pos, indent)
last_pos = pos
return _indent:top() == indent
end
local advance_indent
advance_indent = function(str, pos, indent)
local top = _indent:top()
if top ~= -1 and indent > top then
_indent:push(indent)
return true
end
end
local push_indent
push_indent = function(str, pos, indent)
_indent:push(indent)
return true
end
local pop_indent
pop_indent = function()
assert(_indent:pop(), "unexpected outdent")
return true
end
local check_do
check_do = function(str, pos, do_node)
local top = _do_stack:top()
if top == nil or top then
return true, do_node
end
return false
end
local disable_do
disable_do = function()
_do_stack:push(false)
return true
end
local pop_do
pop_do = function()
assert(_do_stack:pop() ~= nil, "unexpected do pop")
return true
end
local DisableDo = Cmt("", disable_do)
local PopDo = Cmt("", pop_do)
local keywords = { }
local key
key = function(chars)
keywords[chars] = true
return Space * chars * -AlphaNum
end
local op
op = function(chars)
local patt = Space * C(chars)
if chars:match("^%w*$") then
keywords[chars] = true
patt = patt * -AlphaNum
end
return patt
end
local Name = Cmt(SpaceName, function(str, pos, name)
if keywords[name] then
return false
end
return true
end) / trim
local SelfName = Space * "@" * ("@" * (_Name / mark("self_class") + Cc("self.__class")) + _Name / mark("self") + Cc("self"))
local KeyName = SelfName + Space * _Name / mark("key_literal")
local VarArg = Space * P("...") / trim
local g = P({
File,
File = Shebang ^ -1 * (Block + Ct("")),
Block = Ct(Line * (Break ^ 1 * Line) ^ 0),
CheckIndent = Cmt(Indent, check_indent),
Line = (CheckIndent * Statement + Space * #Stop),
Statement = pos(Import + While + With + For + ForEach + Switch + Return + Local + Export + BreakLoop + Ct(ExpList) * (Update + Assign) ^ -1 / format_assign) * Space * ((key("if") * Exp * (key("else") * Exp) ^ -1 * Space / mark("if") + key("unless") * Exp / mark("unless") + CompInner / mark("comprehension")) * Space) ^ -1 / wrap_decorator,
Body = Space ^ -1 * Break * EmptyLine ^ 0 * InBlock + Ct(Statement),
Advance = #Cmt(Indent, advance_indent),
PushIndent = Cmt(Indent, push_indent),
PreventIndent = Cmt(Cc(-1), push_indent),
PopIndent = Cmt("", pop_indent),
InBlock = Advance * Block * PopIndent,
Local = key("local") * ((op("*") + op("^")) / mark("declare_glob") + Ct(NameList) / mark("declare_with_shadows")),
Import = key("import") * Ct(ImportNameList) * SpaceBreak ^ 0 * key("from") * Exp / mark("import"),
ImportName = (sym("\\") * Ct(Cc("colon_stub") * Name) + Name),
ImportNameList = SpaceBreak ^ 0 * ImportName * ((SpaceBreak ^ 1 + sym(",") * SpaceBreak ^ 0) * ImportName) ^ 0,
BreakLoop = Ct(key("break") / trim) + Ct(key("continue") / trim),
Return = key("return") * (ExpListLow / mark("explist") + C("")) / mark("return"),
WithExp = Ct(ExpList) * Assign ^ -1 / format_assign,
With = key("with") * DisableDo * ensure(WithExp, PopDo) * key("do") ^ -1 * Body / mark("with"),
Switch = key("switch") * DisableDo * ensure(Exp, PopDo) * key("do") ^ -1 * Space ^ -1 * Break * SwitchBlock / mark("switch"),
SwitchBlock = EmptyLine ^ 0 * Advance * Ct(SwitchCase * (Break ^ 1 * SwitchCase) ^ 0 * (Break ^ 1 * SwitchElse) ^ -1) * PopIndent,
SwitchCase = key("when") * Ct(ExpList) * key("then") ^ -1 * Body / mark("case"),
SwitchElse = key("else") * Body / mark("else"),
IfCond = Exp * Assign ^ -1 / format_single_assign,
If = key("if") * IfCond * key("then") ^ -1 * Body * ((Break * CheckIndent) ^ -1 * EmptyLine ^ 0 * key("elseif") * pos(IfCond) * key("then") ^ -1 * Body / mark("elseif")) ^ 0 * ((Break * CheckIndent) ^ -1 * EmptyLine ^ 0 * key("else") * Body / mark("else")) ^ -1 / mark("if"),
Unless = key("unless") * IfCond * key("then") ^ -1 * Body * ((Break * CheckIndent) ^ -1 * EmptyLine ^ 0 * key("else") * Body / mark("else")) ^ -1 / mark("unless"),
While = key("while") * DisableDo * ensure(Exp, PopDo) * key("do") ^ -1 * Body / mark("while"),
For = key("for") * DisableDo * ensure(Name * sym("=") * Ct(Exp * sym(",") * Exp * (sym(",") * Exp) ^ -1), PopDo) * key("do") ^ -1 * Body / mark("for"),
ForEach = key("for") * Ct(AssignableNameList) * key("in") * DisableDo * ensure(Ct(sym("*") * Exp / mark("unpack") + ExpList), PopDo) * key("do") ^ -1 * Body / mark("foreach"),
Do = key("do") * Body / mark("do"),
Comprehension = sym("[") * Exp * CompInner * sym("]") / mark("comprehension"),
TblComprehension = sym("{") * Ct(Exp * (sym(",") * Exp) ^ -1) * CompInner * sym("}") / mark("tblcomprehension"),
CompInner = Ct((CompForEach + CompFor) * CompClause ^ 0),
CompForEach = key("for") * Ct(NameList) * key("in") * (sym("*") * Exp / mark("unpack") + Exp) / mark("foreach"),
CompFor = key("for" * Name * sym("=") * Ct(Exp * sym(",") * Exp * (sym(",") * Exp) ^ -1) / mark("for")),
CompClause = CompFor + CompForEach + key("when") * Exp / mark("when"),
Assign = sym("=") * (Ct(With + If + Switch) + Ct(TableBlock + ExpListLow)) / mark("assign"),
Update = ((sym("..=") + sym("+=") + sym("-=") + sym("*=") + sym("/=") + sym("%=") + sym("or=") + sym("and=")) / trim) * Exp / mark("update"),
CharOperators = Space * C(S("+-*/%^><")),
WordOperators = op("or") + op("and") + op("<=") + op(">=") + op("~=") + op("!=") + op("==") + op(".."),
BinaryOperator = (WordOperators + CharOperators) * SpaceBreak ^ 0,
Assignable = Cmt(DotChain + Chain, check_assignable) + Name + SelfName,
Exp = Ct(Value * (BinaryOperator * Value) ^ 0) / flatten_or_mark("exp"),
SimpleValue = If + Unless + Switch + With + ClassDecl + ForEach + For + While + Cmt(Do, check_do) + sym("-") * -SomeSpace * Exp / mark("minus") + sym("#") * Exp / mark("length") + key("not") * Exp / mark("not") + TblComprehension + TableLit + Comprehension + FunLit + Num,
ChainValue = StringChain + ((Chain + DotChain + Callable) * Ct(InvokeArgs ^ -1)) / flatten_func,
Value = pos(SimpleValue + Ct(KeyValueList) / mark("table") + ChainValue),
SliceValue = SimpleValue + ChainValue,
StringChain = String * (Ct((ColonCall + ColonSuffix) * ChainTail ^ -1) * Ct(InvokeArgs ^ -1)) ^ -1 / flatten_string_chain,
String = Space * DoubleString + Space * SingleString + LuaString,
SingleString = simple_string("'"),
DoubleString = simple_string('"', true),
LuaString = Cg(LuaStringOpen, "string_open") * Cb("string_open") * Break ^ -1 * C((1 - Cmt(C(LuaStringClose) * Cb("string_open"), check_lua_string)) ^ 0) * LuaStringClose / mark("string"),
LuaStringOpen = sym("[") * P("=") ^ 0 * "[" / trim,
LuaStringClose = "]" * P("=") ^ 0 * "]",
Callable = pos(Name / mark("ref")) + SelfName + VarArg + Parens / mark("parens"),
Parens = sym("(") * SpaceBreak ^ 0 * Exp * SpaceBreak ^ 0 * sym(")"),
FnArgs = symx("(") * SpaceBreak ^ 0 * Ct(ExpList ^ -1) * SpaceBreak ^ 0 * sym(")") + sym("!") * -P("=") * Ct(""),
ChainTail = ChainItem ^ 1 * ColonSuffix ^ -1 + ColonSuffix,
Chain = Callable * ChainTail / mark("chain"),
DotChain = (sym(".") * Cc(-1) * (_Name / mark("dot")) * ChainTail ^ -1) / mark("chain") + (sym("\\") * Cc(-1) * ((_Name * Invoke / mark("colon")) * ChainTail ^ -1 + (_Name / mark("colon_stub")))) / mark("chain"),
ChainItem = Invoke + Slice + symx("[") * Exp / mark("index") * sym("]") + symx(".") * _Name / mark("dot") + ColonCall,
Slice = symx("[") * (SliceValue + Cc(1)) * sym(",") * (SliceValue + Cc("")) * (sym(",") * SliceValue) ^ -1 * sym("]") / mark("slice"),
ColonCall = symx("\\") * (_Name * Invoke) / mark("colon"),
ColonSuffix = symx("\\") * _Name / mark("colon_stub"),
Invoke = FnArgs / mark("call") + SingleString / wrap_func_arg + DoubleString / wrap_func_arg,
TableValue = KeyValue + Ct(Exp),
TableLit = sym("{") * Ct(TableValueList ^ -1 * sym(",") ^ -1 * (SpaceBreak * TableLitLine * (sym(",") ^ -1 * SpaceBreak * TableLitLine) ^ 0 * sym(",") ^ -1) ^ -1) * White * sym("}") / mark("table"),
TableValueList = TableValue * (sym(",") * TableValue) ^ 0,
TableLitLine = PushIndent * ((TableValueList * PopIndent) + (PopIndent * Cut)) + Space,
TableBlockInner = Ct(KeyValueLine * (SpaceBreak ^ 1 * KeyValueLine) ^ 0),
TableBlock = SpaceBreak ^ 1 * Advance * ensure(TableBlockInner, PopIndent) / mark("table"),
ClassDecl = key("class") * -P(":") * (Assignable + Cc(nil)) * (key("extends") * PreventIndent * ensure(Exp, PopIndent) + C("")) ^ -1 * (ClassBlock + Ct("")) / mark("class"),
ClassBlock = SpaceBreak ^ 1 * Advance * Ct(ClassLine * (SpaceBreak ^ 1 * ClassLine) ^ 0) * PopIndent,
ClassLine = CheckIndent * ((KeyValueList / mark("props") + Statement / mark("stm") + Exp / mark("stm")) * sym(",") ^ -1),
Export = key("export") * (Cc("class") * ClassDecl + op("*") + op("^") + Ct(NameList) * (sym("=") * Ct(ExpListLow)) ^ -1) / mark("export"),
KeyValue = (sym(":") * -SomeSpace * Name * lpeg.Cp()) / self_assign + Ct((KeyName + sym("[") * Exp * sym("]") + DoubleString + SingleString) * symx(":") * (Exp + TableBlock + SpaceBreak ^ 1 * Exp)),
KeyValueList = KeyValue * (sym(",") * KeyValue) ^ 0,
KeyValueLine = CheckIndent * KeyValueList * sym(",") ^ -1,
FnArgsDef = sym("(") * Ct(FnArgDefList ^ -1) * (key("using") * Ct(NameList + Space * "nil") + Ct("")) * sym(")") + Ct("") * Ct(""),
FnArgDefList = FnArgDef * (sym(",") * FnArgDef) ^ 0 * (sym(",") * Ct(VarArg)) ^ 0 + Ct(VarArg),
FnArgDef = Ct((Name + SelfName) * (sym("=") * Exp) ^ -1),
FunLit = FnArgsDef * (sym("->") * Cc("slim") + sym("=>") * Cc("fat")) * (Body + Ct("")) / mark("fndef"),
NameList = Name * (sym(",") * Name) ^ 0,
NameOrDestructure = Name + TableLit,
AssignableNameList = NameOrDestructure * (sym(",") * NameOrDestructure) ^ 0,
ExpList = Exp * (sym(",") * Exp) ^ 0,
ExpListLow = Exp * ((sym(",") + sym(";")) * Exp) ^ 0,
InvokeArgs = -P("-") * (ExpList * (sym(",") * (TableBlock + SpaceBreak * Advance * ArgBlock * TableBlock ^ -1) + TableBlock) ^ -1 + TableBlock),
ArgBlock = ArgLine * (sym(",") * SpaceBreak * ArgLine) ^ 0 * PopIndent,
ArgLine = CheckIndent * ExpList
})
local file_grammar = White * g * White * -1
return {
match = function(self, str)
local tree
local _, err = xpcall((function()
tree = file_grammar:match(str)
end), function(err)
return debug.traceback(err, 2)
end)
if type(err) == "string" then
return nil, err
end
if not (tree) then
local msg
local err_pos = last_pos
if err then
local node
node, msg = unpack(err)
if msg then
msg = " " .. msg
end
err_pos = node[-1]
end
local line_no = pos_to_line(str, err_pos)
local line_str = get_line(str, line_no) or ""
return nil, err_msg:format(msg or "", line_no, trim(line_str))
end
return tree
end
}
2013-04-30 15:16:59 +02:00
end)
return {
2015-02-03 18:54:34 +01:00
extract_line = extract_line,
string = function(str)
return build_grammar():match(str)
end
2013-04-30 15:16:59 +02:00
}
end
package.preload['moonscript.transform.destructure'] = function()
local ntype, mtype, build
do
2013-07-04 01:11:42 +02:00
local _obj_0 = require("moonscript.types")
ntype, mtype, build = _obj_0.ntype, _obj_0.mtype, _obj_0.build
2013-04-30 15:16:59 +02:00
end
local NameProxy
2015-02-03 18:54:34 +01:00
NameProxy = require("moonscript.transform.names").NameProxy
2013-07-04 01:11:42 +02:00
local insert
2015-02-03 18:54:34 +01:00
insert = table.insert
2013-04-30 15:16:59 +02:00
local unpack
2015-02-03 18:54:34 +01:00
unpack = require("moonscript.util").unpack
2013-04-30 15:16:59 +02:00
local user_error
2015-02-03 18:54:34 +01:00
user_error = require("moonscript.errors").user_error
2013-04-30 15:16:59 +02:00
local join
join = function(...)
do
2013-07-04 01:11:42 +02:00
local out = { }
2013-04-30 15:16:59 +02:00
local i = 1
local _list_0 = {
...
}
for _index_0 = 1, #_list_0 do
local tbl = _list_0[_index_0]
2013-07-04 01:11:42 +02:00
for _index_1 = 1, #tbl do
local v = tbl[_index_1]
2013-04-30 15:16:59 +02:00
out[i] = v
i = i + 1
end
end
2013-07-04 01:11:42 +02:00
return out
2013-04-30 15:16:59 +02:00
end
end
local has_destructure
has_destructure = function(names)
2013-07-04 01:11:42 +02:00
for _index_0 = 1, #names do
local n = names[_index_0]
2013-04-30 15:16:59 +02:00
if ntype(n) == "table" then
return true
end
end
return false
end
local extract_assign_names
extract_assign_names = function(name, accum, prefix)
if accum == nil then
accum = { }
end
if prefix == nil then
prefix = { }
end
local i = 1
local _list_0 = name[2]
for _index_0 = 1, #_list_0 do
local tuple = _list_0[_index_0]
local value, suffix
if #tuple == 1 then
local s = {
"index",
{
"number",
i
}
}
i = i + 1
value, suffix = tuple[1], s
else
local key = tuple[1]
local s
if ntype(key) == "key_literal" then
2013-07-04 01:11:42 +02:00
local key_name = key[2]
if ntype(key_name) == "colon_stub" then
s = key_name
else
s = {
"dot",
key_name
}
end
2013-04-30 15:16:59 +02:00
else
s = {
"index",
key
}
end
value, suffix = tuple[2], s
end
suffix = join(prefix, {
suffix
})
2014-03-07 04:19:12 +01:00
local _exp_0 = ntype(value)
if "value" == _exp_0 or "ref" == _exp_0 or "chain" == _exp_0 or "self" == _exp_0 then
2013-04-30 15:16:59 +02:00
insert(accum, {
value,
suffix
})
2014-03-07 04:19:12 +01:00
elseif "table" == _exp_0 then
2013-04-30 15:16:59 +02:00
extract_assign_names(value, accum, suffix)
else
user_error("Can't destructure value of type: " .. tostring(ntype(value)))
end
end
return accum
end
local build_assign
2013-07-04 01:11:42 +02:00
build_assign = function(scope, destruct_literal, receiver)
2013-04-30 15:16:59 +02:00
local extracted_names = extract_assign_names(destruct_literal)
local names = { }
local values = { }
local inner = {
"assign",
names,
values
}
local obj
2015-02-03 18:54:34 +01:00
if scope:is_local(receiver) or #extracted_names == 1 then
2013-04-30 15:16:59 +02:00
obj = receiver
else
do
2013-07-04 01:11:42 +02:00
obj = NameProxy("obj")
2013-04-30 15:16:59 +02:00
inner = build["do"]({
build.assign_one(obj, receiver),
{
"assign",
names,
values
}
})
2013-07-04 01:11:42 +02:00
obj = obj
2013-04-30 15:16:59 +02:00
end
end
2013-07-04 01:11:42 +02:00
for _index_0 = 1, #extracted_names do
local tuple = extracted_names[_index_0]
2013-04-30 15:16:59 +02:00
insert(names, tuple[1])
2015-02-03 18:54:34 +01:00
local chain
if obj then
chain = NameProxy.chain(obj, unpack(tuple[2]))
else
chain = "nil"
end
insert(values, chain)
2013-04-30 15:16:59 +02:00
end
return build.group({
{
"declare",
names
},
inner
})
end
local split_assign
2013-07-04 01:11:42 +02:00
split_assign = function(scope, assign)
2013-04-30 15:16:59 +02:00
local names, values = unpack(assign, 2)
local g = { }
local total_names = #names
local total_values = #values
local start = 1
for i, n in ipairs(names) do
if ntype(n) == "table" then
if i > start then
local stop = i - 1
insert(g, {
"assign",
(function()
local _accum_0 = { }
local _len_0 = 1
for i = start, stop do
_accum_0[_len_0] = names[i]
_len_0 = _len_0 + 1
end
return _accum_0
end)(),
(function()
local _accum_0 = { }
local _len_0 = 1
for i = start, stop do
_accum_0[_len_0] = values[i]
_len_0 = _len_0 + 1
end
return _accum_0
end)()
})
end
2013-07-04 01:11:42 +02:00
insert(g, build_assign(scope, n, values[i]))
2013-04-30 15:16:59 +02:00
start = i + 1
end
end
if total_names >= start or total_values >= start then
local name_slice
if total_names < start then
name_slice = {
"_"
}
else
2013-07-04 01:11:42 +02:00
do
2013-04-30 15:16:59 +02:00
local _accum_0 = { }
local _len_0 = 1
for i = start, total_names do
_accum_0[_len_0] = names[i]
_len_0 = _len_0 + 1
end
2013-07-04 01:11:42 +02:00
name_slice = _accum_0
end
2013-04-30 15:16:59 +02:00
end
local value_slice
if total_values < start then
value_slice = {
"nil"
}
else
2013-07-04 01:11:42 +02:00
do
2013-04-30 15:16:59 +02:00
local _accum_0 = { }
local _len_0 = 1
for i = start, total_values do
_accum_0[_len_0] = values[i]
_len_0 = _len_0 + 1
end
2013-07-04 01:11:42 +02:00
value_slice = _accum_0
end
2013-04-30 15:16:59 +02:00
end
insert(g, {
"assign",
name_slice,
value_slice
})
end
return build.group(g)
end
return {
has_destructure = has_destructure,
split_assign = split_assign,
build_assign = build_assign
}
end
package.preload['moonscript.transform.names'] = function()
local build
2015-02-03 18:54:34 +01:00
build = require("moonscript.types").build
2013-04-30 15:16:59 +02:00
local unpack
2015-02-03 18:54:34 +01:00
unpack = require("moonscript.util").unpack
2013-04-30 15:16:59 +02:00
local LocalName
do
local _base_0 = {
get_name = function(self)
return self.name
end
}
_base_0.__index = _base_0
local _class_0 = setmetatable({
__init = function(self, name)
self.name = name
self[1] = "temp_name"
end,
__base = _base_0,
2013-07-04 01:11:42 +02:00
__name = "LocalName"
2013-04-30 15:16:59 +02:00
}, {
2013-07-04 01:11:42 +02:00
__index = _base_0,
2013-04-30 15:16:59 +02:00
__call = function(cls, ...)
local _self_0 = setmetatable({}, _base_0)
cls.__init(_self_0, ...)
return _self_0
end
})
_base_0.__class = _class_0
LocalName = _class_0
end
local NameProxy
do
local _base_0 = {
get_name = function(self, scope, dont_put)
if dont_put == nil then
dont_put = true
end
if not self.name then
self.name = scope:free_name(self.prefix, dont_put)
end
return self.name
end,
chain = function(self, ...)
2014-03-07 04:19:12 +01:00
local items = {
base = self,
...
}
for k, v in ipairs(items) do
if type(v) == "string" then
items[k] = {
"dot",
v
}
else
items[k] = v
2013-04-30 15:16:59 +02:00
end
2013-07-04 01:11:42 +02:00
end
2014-03-07 04:19:12 +01:00
return build.chain(items)
2013-04-30 15:16:59 +02:00
end,
index = function(self, key)
2014-03-07 04:19:12 +01:00
if type(key) == "string" then
key = {
"ref",
key
}
end
2013-04-30 15:16:59 +02:00
return build.chain({
base = self,
{
"index",
key
}
})
end,
__tostring = function(self)
if self.name then
return ("name<%s>"):format(self.name)
else
return ("name<prefix(%s)>"):format(self.prefix)
end
end
}
_base_0.__index = _base_0
local _class_0 = setmetatable({
__init = function(self, prefix)
self.prefix = prefix
self[1] = "temp_name"
end,
__base = _base_0,
2013-07-04 01:11:42 +02:00
__name = "NameProxy"
2013-04-30 15:16:59 +02:00
}, {
2013-07-04 01:11:42 +02:00
__index = _base_0,
2013-04-30 15:16:59 +02:00
__call = function(cls, ...)
local _self_0 = setmetatable({}, _base_0)
cls.__init(_self_0, ...)
return _self_0
end
})
_base_0.__class = _class_0
NameProxy = _class_0
end
return {
NameProxy = NameProxy,
LocalName = LocalName
}
end
package.preload['moonscript.transform'] = function()
local types = require("moonscript.types")
local util = require("moonscript.util")
local data = require("moonscript.data")
2013-07-04 01:11:42 +02:00
local reversed, unpack
reversed, unpack = util.reversed, util.unpack
local ntype, mtype, build, smart_node, is_slice, value_is_singular
ntype, mtype, build, smart_node, is_slice, value_is_singular = types.ntype, types.mtype, types.build, types.smart_node, types.is_slice, types.value_is_singular
local insert
2015-02-03 18:54:34 +01:00
insert = table.insert
2013-04-30 15:16:59 +02:00
local NameProxy, LocalName
do
2013-07-04 01:11:42 +02:00
local _obj_0 = require("moonscript.transform.names")
NameProxy, LocalName = _obj_0.NameProxy, _obj_0.LocalName
2013-04-30 15:16:59 +02:00
end
local destructure = require("moonscript.transform.destructure")
2013-07-04 01:11:42 +02:00
local NOOP = {
"noop"
}
local Run, apply_to_last, is_singular, extract_declarations, expand_elseif_assign, constructor_name, with_continue_listener, Transformer, construct_comprehension, Statement, Accumulator, default_accumulator, implicitly_return, Value
2013-04-30 15:16:59 +02:00
do
local _base_0 = {
call = function(self, state)
return self.fn(state)
end
}
_base_0.__index = _base_0
local _class_0 = setmetatable({
__init = function(self, fn)
self.fn = fn
self[1] = "run"
end,
__base = _base_0,
2013-07-04 01:11:42 +02:00
__name = "Run"
2013-04-30 15:16:59 +02:00
}, {
2013-07-04 01:11:42 +02:00
__index = _base_0,
2013-04-30 15:16:59 +02:00
__call = function(cls, ...)
local _self_0 = setmetatable({}, _base_0)
cls.__init(_self_0, ...)
return _self_0
end
})
_base_0.__class = _class_0
Run = _class_0
end
apply_to_last = function(stms, fn)
local last_exp_id = 0
for i = #stms, 1, -1 do
local stm = stms[i]
if stm and mtype(stm) ~= Run then
last_exp_id = i
break
end
end
return (function()
local _accum_0 = { }
local _len_0 = 1
for i, stm in ipairs(stms) do
if i == last_exp_id then
2013-07-04 01:11:42 +02:00
_accum_0[_len_0] = {
"transform",
stm,
fn
}
2013-04-30 15:16:59 +02:00
else
_accum_0[_len_0] = stm
end
_len_0 = _len_0 + 1
end
return _accum_0
end)()
end
is_singular = function(body)
if #body ~= 1 then
return false
end
if "group" == ntype(body) then
return is_singular(body[2])
else
return body[1]
end
end
extract_declarations = function(self, body, start, out)
if body == nil then
body = self.current_stms
end
if start == nil then
start = self.current_stm_i + 1
end
if out == nil then
out = { }
end
for i = start, #body do
local _continue_0 = false
repeat
local stm = body[i]
if stm == nil then
_continue_0 = true
break
end
stm = self.transform.statement(stm)
body[i] = stm
local _exp_0 = stm[1]
if "assign" == _exp_0 or "declare" == _exp_0 then
local _list_0 = stm[2]
for _index_0 = 1, #_list_0 do
local name = _list_0[_index_0]
2014-03-07 04:19:12 +01:00
if ntype(name) == "ref" then
insert(out, name)
elseif type(name) == "string" then
2013-04-30 15:16:59 +02:00
insert(out, name)
end
end
elseif "group" == _exp_0 then
extract_declarations(self, stm[2], 1, out)
end
_continue_0 = true
until true
if not _continue_0 then
break
end
end
return out
end
expand_elseif_assign = function(ifstm)
for i = 4, #ifstm do
local case = ifstm[i]
if ntype(case) == "elseif" and ntype(case[2]) == "assign" then
local split = {
unpack(ifstm, 1, i - 1)
}
insert(split, {
"else",
{
{
"if",
case[2],
case[3],
unpack(ifstm, i + 1)
}
}
})
return split
end
end
return ifstm
end
2013-07-04 01:11:42 +02:00
constructor_name = "new"
2013-04-30 15:16:59 +02:00
with_continue_listener = function(body)
local continue_name = nil
return {
Run(function(self)
return self:listen("continue", function()
if not (continue_name) then
continue_name = NameProxy("continue")
self:put_name(continue_name)
end
return continue_name
end)
end),
build.group(body),
Run(function(self)
if not (continue_name) then
return
end
self:put_name(continue_name, nil)
return self:splice(function(lines)
return {
{
"assign",
{
continue_name
},
{
"false"
}
},
{
"repeat",
"true",
{
lines,
{
"assign",
{
continue_name
},
{
"true"
}
}
}
},
{
"if",
{
"not",
continue_name
},
{
{
"break"
}
}
}
}
end)
end)
}
end
do
local _base_0 = {
2013-07-04 01:11:42 +02:00
transform_once = function(self, scope, node, ...)
if self.seen_nodes[node] then
return node
end
self.seen_nodes[node] = true
local transformer = self.transformers[ntype(node)]
if transformer then
return transformer(scope, node, ...) or node
else
return node
end
end,
2013-04-30 15:16:59 +02:00
transform = function(self, scope, node, ...)
if self.seen_nodes[node] then
return node
end
self.seen_nodes[node] = true
while true do
local transformer = self.transformers[ntype(node)]
local res
if transformer then
res = transformer(scope, node, ...) or node
else
res = node
end
if res == node then
return node
end
node = res
end
return node
end,
bind = function(self, scope)
return function(...)
return self:transform(scope, ...)
end
end,
__call = function(self, ...)
return self:transform(...)
end,
can_transform = function(self, node)
return self.transformers[ntype(node)] ~= nil
end
}
_base_0.__index = _base_0
local _class_0 = setmetatable({
__init = function(self, transformers)
self.transformers = transformers
self.seen_nodes = setmetatable({ }, {
__mode = "k"
})
end,
__base = _base_0,
2013-07-04 01:11:42 +02:00
__name = "Transformer"
2013-04-30 15:16:59 +02:00
}, {
2013-07-04 01:11:42 +02:00
__index = _base_0,
2013-04-30 15:16:59 +02:00
__call = function(cls, ...)
local _self_0 = setmetatable({}, _base_0)
cls.__init(_self_0, ...)
return _self_0
end
})
_base_0.__class = _class_0
Transformer = _class_0
end
construct_comprehension = function(inner, clauses)
local current_stms = inner
for _, clause in reversed(clauses) do
local t = clause[1]
local _exp_0 = t
if "for" == _exp_0 then
local name, bounds
2013-07-04 01:11:42 +02:00
_, name, bounds = clause[1], clause[2], clause[3]
2013-04-30 15:16:59 +02:00
current_stms = {
"for",
name,
bounds,
current_stms
}
elseif "foreach" == _exp_0 then
local names, iter
2013-07-04 01:11:42 +02:00
_, names, iter = clause[1], clause[2], clause[3]
2013-04-30 15:16:59 +02:00
current_stms = {
"foreach",
names,
{
iter
},
current_stms
}
elseif "when" == _exp_0 then
local cond
2013-07-04 01:11:42 +02:00
_, cond = clause[1], clause[2]
2013-04-30 15:16:59 +02:00
current_stms = {
"if",
cond,
current_stms
}
else
current_stms = error("Unknown comprehension clause: " .. t)
end
current_stms = {
current_stms
}
end
return current_stms[1]
end
2013-07-04 01:11:42 +02:00
Statement = Transformer({
transform = function(self, tuple)
local _, node, fn
_, node, fn = tuple[1], tuple[2], tuple[3]
return fn(node)
end,
2013-04-30 15:16:59 +02:00
root_stms = function(self, body)
return apply_to_last(body, implicitly_return(self))
end,
2013-07-04 01:11:42 +02:00
["return"] = function(self, node)
2014-03-07 04:19:12 +01:00
local ret_val = node[2]
local ret_val_type = ntype(ret_val)
if ret_val_type == "explist" and #ret_val == 2 then
ret_val = ret_val[2]
ret_val_type = ntype(ret_val)
end
if types.cascading[ret_val_type] then
return implicitly_return(self)(ret_val)
end
if ret_val_type == "chain" or ret_val_type == "comprehension" or ret_val_type == "tblcomprehension" then
ret_val = Value:transform_once(self, ret_val)
if ntype(ret_val) == "block_exp" then
return build.group(apply_to_last(ret_val[2], function(stm)
return {
"return",
stm
}
end))
end
2013-07-04 01:11:42 +02:00
end
2014-03-07 04:19:12 +01:00
node[2] = ret_val
2013-07-04 01:11:42 +02:00
return node
end,
2013-04-30 15:16:59 +02:00
declare_glob = function(self, node)
local names = extract_declarations(self)
if node[2] == "^" then
2013-07-04 01:11:42 +02:00
do
2013-04-30 15:16:59 +02:00
local _accum_0 = { }
local _len_0 = 1
2013-07-04 01:11:42 +02:00
for _index_0 = 1, #names do
2013-04-30 15:16:59 +02:00
local _continue_0 = false
repeat
2013-07-04 01:11:42 +02:00
local name = names[_index_0]
2014-03-07 04:19:12 +01:00
if not (name[2]:match("^%u")) then
2013-04-30 15:16:59 +02:00
_continue_0 = true
break
end
local _value_0 = name
_accum_0[_len_0] = _value_0
_len_0 = _len_0 + 1
_continue_0 = true
until true
if not _continue_0 then
break
end
end
2013-07-04 01:11:42 +02:00
names = _accum_0
end
2013-04-30 15:16:59 +02:00
end
return {
"declare",
names
}
end,
assign = function(self, node)
local names, values = unpack(node, 2)
2013-07-04 01:11:42 +02:00
local num_values = #values
local num_names = #values
if num_names == 1 and num_values == 1 then
local first_value = values[1]
local first_name = names[1]
2014-03-07 04:19:12 +01:00
local first_type = ntype(first_value)
if first_type == "chain" then
first_value = Value:transform_once(self, first_value)
first_type = ntype(first_value)
end
2013-07-04 01:11:42 +02:00
local _exp_0 = ntype(first_value)
if "block_exp" == _exp_0 then
local block_body = first_value[2]
local idx = #block_body
block_body[idx] = build.assign_one(first_name, block_body[idx])
return build.group({
{
"declare",
{
first_name
}
},
{
"do",
block_body
}
})
elseif "comprehension" == _exp_0 or "tblcomprehension" == _exp_0 or "foreach" == _exp_0 or "for" == _exp_0 or "while" == _exp_0 then
return build.assign_one(first_name, Value:transform_once(self, first_value))
2014-03-07 04:19:12 +01:00
else
values[1] = first_value
2013-07-04 01:11:42 +02:00
end
end
2013-04-30 15:16:59 +02:00
local transformed
2013-07-04 01:11:42 +02:00
if num_values == 1 then
2013-04-30 15:16:59 +02:00
local value = values[1]
local t = ntype(value)
if t == "decorated" then
value = self.transform.statement(value)
t = ntype(value)
end
if types.cascading[t] then
local ret
ret = function(stm)
if types.is_value(stm) then
return {
"assign",
names,
{
stm
}
}
else
return stm
end
end
transformed = build.group({
{
"declare",
names
},
self.transform.statement(value, ret, node)
})
end
end
node = transformed or node
if destructure.has_destructure(names) then
2013-07-04 01:11:42 +02:00
return destructure.split_assign(self, node)
2013-04-30 15:16:59 +02:00
end
return node
end,
continue = function(self, node)
local continue_name = self:send("continue")
if not (continue_name) then
error("continue must be inside of a loop")
end
return build.group({
build.assign_one(continue_name, "true"),
{
"break"
}
})
end,
export = function(self, node)
if #node > 2 then
if node[2] == "class" then
local cls = smart_node(node[3])
return build.group({
{
"export",
{
cls.name
}
},
cls
})
else
return build.group({
2013-07-04 01:11:42 +02:00
{
"export",
node[2]
},
2013-04-30 15:16:59 +02:00
build.assign({
names = node[2],
values = node[3]
})
})
end
else
return nil
end
end,
update = function(self, node)
local _, name, op, exp = unpack(node)
local op_final = op:match("^(.+)=$")
if not op_final then
error("Unknown op: " .. op)
end
if not (value_is_singular(exp)) then
exp = {
"parens",
exp
}
end
return build.assign_one(name, {
"exp",
name,
op_final,
exp
})
end,
import = function(self, node)
local _, names, source = unpack(node)
2013-07-04 01:11:42 +02:00
local table_values
do
2013-04-30 15:16:59 +02:00
local _accum_0 = { }
local _len_0 = 1
2013-07-04 01:11:42 +02:00
for _index_0 = 1, #names do
local name = names[_index_0]
local dest_val
if ntype(name) == "colon_stub" then
dest_val = name[2]
2013-04-30 15:16:59 +02:00
else
2013-07-04 01:11:42 +02:00
dest_val = name
2013-04-30 15:16:59 +02:00
end
2013-07-04 01:11:42 +02:00
local _value_0 = {
{
"key_literal",
name
},
dest_val
}
_accum_0[_len_0] = _value_0
2013-04-30 15:16:59 +02:00
_len_0 = _len_0 + 1
end
2013-07-04 01:11:42 +02:00
table_values = _accum_0
2013-04-30 15:16:59 +02:00
end
2013-07-04 01:11:42 +02:00
local dest = {
"table",
table_values
}
return {
"assign",
{
dest
},
{
source
},
[-1] = node[-1]
}
2013-04-30 15:16:59 +02:00
end,
comprehension = function(self, node, action)
local _, exp, clauses = unpack(node)
action = action or function(exp)
return {
exp
}
end
return construct_comprehension(action(exp), clauses)
end,
["do"] = function(self, node, ret)
if ret then
node[2] = apply_to_last(node[2], ret)
end
return node
end,
decorated = function(self, node)
local stm, dec = unpack(node, 2)
local wrapped
local _exp_0 = dec[1]
if "if" == _exp_0 then
local cond, fail = unpack(dec, 2)
if fail then
fail = {
"else",
{
fail
}
}
end
wrapped = {
"if",
cond,
{
stm
},
fail
}
elseif "unless" == _exp_0 then
wrapped = {
"unless",
dec[2],
{
stm
}
}
elseif "comprehension" == _exp_0 then
wrapped = {
"comprehension",
stm,
dec[2]
}
else
wrapped = error("Unknown decorator " .. dec[1])
end
if ntype(stm) == "assign" then
wrapped = build.group({
build.declare({
names = (function()
local _accum_0 = { }
local _len_0 = 1
local _list_0 = stm[2]
for _index_0 = 1, #_list_0 do
local name = _list_0[_index_0]
2014-03-07 04:19:12 +01:00
if ntype(name) == "ref" then
2013-04-30 15:16:59 +02:00
_accum_0[_len_0] = name
_len_0 = _len_0 + 1
end
end
return _accum_0
end)()
}),
wrapped
})
end
return wrapped
end,
unless = function(self, node)
return {
"if",
{
"not",
{
"parens",
node[2]
}
},
unpack(node, 3)
}
end,
["if"] = function(self, node, ret)
if ntype(node[2]) == "assign" then
local _, assign, body = unpack(node)
if destructure.has_destructure(assign[2]) then
local name = NameProxy("des")
body = {
2013-07-04 01:11:42 +02:00
destructure.build_assign(self, assign[2][1], name),
2013-04-30 15:16:59 +02:00
build.group(node[3])
}
return build["do"]({
build.assign_one(name, assign[3][1]),
{
"if",
name,
body,
unpack(node, 4)
}
})
else
local name = assign[2][1]
return build["do"]({
assign,
{
"if",
name,
unpack(node, 3)
}
})
end
end
node = expand_elseif_assign(node)
if ret then
smart_node(node)
node['then'] = apply_to_last(node['then'], ret)
for i = 4, #node do
local case = node[i]
local body_idx = #node[i]
case[body_idx] = apply_to_last(case[body_idx], ret)
end
end
return node
end,
with = function(self, node, ret)
2013-07-04 01:11:42 +02:00
local exp, block = unpack(node, 2)
local copy_scope = true
local scope_name, named_assign
2013-04-30 15:16:59 +02:00
if ntype(exp) == "assign" then
local names, values = unpack(exp, 2)
2013-07-04 01:11:42 +02:00
local first_name = names[1]
2014-03-07 04:19:12 +01:00
if ntype(first_name) == "ref" then
2013-07-04 01:11:42 +02:00
scope_name = first_name
named_assign = exp
exp = values[1]
copy_scope = false
else
scope_name = NameProxy("with")
exp = values[1]
values[1] = scope_name
named_assign = {
"assign",
names,
values
}
end
elseif self:is_local(exp) then
scope_name = exp
copy_scope = false
2013-04-30 15:16:59 +02:00
end
2013-07-04 01:11:42 +02:00
scope_name = scope_name or NameProxy("with")
2013-04-30 15:16:59 +02:00
return build["do"]({
Run(function(self)
return self:set("scope_var", scope_name)
end),
2013-07-04 01:11:42 +02:00
copy_scope and build.assign_one(scope_name, exp) or NOOP,
named_assign or NOOP,
2013-04-30 15:16:59 +02:00
build.group(block),
(function()
if ret then
return ret(scope_name)
end
end)()
})
end,
2013-07-04 01:11:42 +02:00
foreach = function(self, node, _)
2013-04-30 15:16:59 +02:00
smart_node(node)
local source = unpack(node.iter)
local destructures = { }
2013-07-04 01:11:42 +02:00
do
2013-04-30 15:16:59 +02:00
local _accum_0 = { }
local _len_0 = 1
for i, name in ipairs(node.names) do
if ntype(name) == "table" then
do
2013-07-04 01:11:42 +02:00
local proxy = NameProxy("des")
insert(destructures, destructure.build_assign(self, name, proxy))
_accum_0[_len_0] = proxy
2013-04-30 15:16:59 +02:00
end
else
_accum_0[_len_0] = name
end
_len_0 = _len_0 + 1
end
2013-07-04 01:11:42 +02:00
node.names = _accum_0
end
2013-04-30 15:16:59 +02:00
if next(destructures) then
insert(destructures, build.group(node.body))
node.body = destructures
end
if ntype(source) == "unpack" then
local list = source[2]
local index_name = NameProxy("index")
2013-07-04 01:11:42 +02:00
local list_name = self:is_local(list) and list or NameProxy("list")
2013-04-30 15:16:59 +02:00
local slice_var = nil
local bounds
if is_slice(list) then
local slice = list[#list]
table.remove(list)
table.remove(slice, 1)
2013-07-04 01:11:42 +02:00
if self:is_local(list) then
list_name = list
end
2013-04-30 15:16:59 +02:00
if slice[2] and slice[2] ~= "" then
local max_tmp_name = NameProxy("max")
slice_var = build.assign_one(max_tmp_name, slice[2])
slice[2] = {
"exp",
max_tmp_name,
"<",
0,
"and",
{
"length",
list_name
},
"+",
max_tmp_name,
"or",
max_tmp_name
}
else
slice[2] = {
"length",
list_name
}
end
bounds = slice
else
bounds = {
1,
{
"length",
list_name
}
}
end
return build.group({
2013-07-04 01:11:42 +02:00
list_name ~= list and build.assign_one(list_name, list) or NOOP,
slice_var or NOOP,
2013-04-30 15:16:59 +02:00
build["for"]({
name = index_name,
bounds = bounds,
body = {
{
"assign",
node.names,
{
2013-07-04 01:11:42 +02:00
NameProxy.index(list_name, index_name)
2013-04-30 15:16:59 +02:00
}
},
build.group(node.body)
}
})
})
end
node.body = with_continue_listener(node.body)
end,
["while"] = function(self, node)
smart_node(node)
node.body = with_continue_listener(node.body)
end,
["for"] = function(self, node)
smart_node(node)
node.body = with_continue_listener(node.body)
end,
switch = function(self, node, ret)
local _, exp, conds = unpack(node)
local exp_name = NameProxy("exp")
local convert_cond
convert_cond = function(cond)
local t, case_exps, body = unpack(cond)
local out = { }
insert(out, t == "case" and "elseif" or "else")
if t ~= "else" then
local cond_exp = { }
for i, case in ipairs(case_exps) do
if i == 1 then
insert(cond_exp, "exp")
else
insert(cond_exp, "or")
end
if not (value_is_singular(case)) then
case = {
"parens",
case
}
end
insert(cond_exp, {
"exp",
case,
"==",
exp_name
})
end
insert(out, cond_exp)
else
body = case_exps
end
if ret then
body = apply_to_last(body, ret)
end
insert(out, body)
return out
end
local first = true
local if_stm = {
"if"
}
2013-07-04 01:11:42 +02:00
for _index_0 = 1, #conds do
local cond = conds[_index_0]
2013-04-30 15:16:59 +02:00
local if_cond = convert_cond(cond)
if first then
first = false
insert(if_stm, if_cond[2])
insert(if_stm, if_cond[3])
else
insert(if_stm, if_cond)
end
end
return build.group({
build.assign_one(exp_name, exp),
if_stm
})
end,
class = function(self, node, ret, parent_assign)
local _, name, parent_val, body = unpack(node)
2013-07-04 01:11:42 +02:00
if parent_val == "" then
parent_val = nil
end
2013-04-30 15:16:59 +02:00
local statements = { }
local properties = { }
2013-07-04 01:11:42 +02:00
for _index_0 = 1, #body do
local item = body[_index_0]
2013-04-30 15:16:59 +02:00
local _exp_0 = item[1]
if "stm" == _exp_0 then
insert(statements, item[2])
elseif "props" == _exp_0 then
2013-07-04 01:11:42 +02:00
for _index_1 = 2, #item do
local tuple = item[_index_1]
2013-04-30 15:16:59 +02:00
if ntype(tuple[1]) == "self" then
insert(statements, build.assign_one(unpack(tuple)))
else
insert(properties, tuple)
end
end
end
end
local constructor
2013-07-04 01:11:42 +02:00
do
2013-04-30 15:16:59 +02:00
local _accum_0 = { }
local _len_0 = 1
2013-07-04 01:11:42 +02:00
for _index_0 = 1, #properties do
2013-04-30 15:16:59 +02:00
local _continue_0 = false
repeat
2013-07-04 01:11:42 +02:00
local tuple = properties[_index_0]
2013-04-30 15:16:59 +02:00
local key = tuple[1]
local _value_0
if key[1] == "key_literal" and key[2] == constructor_name then
constructor = tuple[2]
_continue_0 = true
break
else
_value_0 = tuple
end
_accum_0[_len_0] = _value_0
_len_0 = _len_0 + 1
_continue_0 = true
until true
if not _continue_0 then
break
end
end
2013-07-04 01:11:42 +02:00
properties = _accum_0
end
2013-04-30 15:16:59 +02:00
local parent_cls_name = NameProxy("parent")
local base_name = NameProxy("base")
local self_name = NameProxy("self")
local cls_name = NameProxy("class")
if not (constructor) then
2013-07-04 01:11:42 +02:00
if parent_val then
constructor = build.fndef({
args = {
{
"..."
}
},
arrow = "fat",
body = {
build.chain({
base = "super",
{
"call",
2013-04-30 15:16:59 +02:00
{
2013-07-04 01:11:42 +02:00
"..."
2013-04-30 15:16:59 +02:00
}
2013-07-04 01:11:42 +02:00
}
})
}
})
else
constructor = build.fndef()
end
2013-04-30 15:16:59 +02:00
end
local real_name = name or parent_assign and parent_assign[2][1]
local _exp_0 = ntype(real_name)
if "chain" == _exp_0 then
local last = real_name[#real_name]
local _exp_1 = ntype(last)
if "dot" == _exp_1 then
real_name = {
"string",
'"',
last[2]
}
elseif "index" == _exp_1 then
real_name = last[2]
else
real_name = "nil"
end
elseif "nil" == _exp_0 then
real_name = "nil"
else
2014-03-07 04:19:12 +01:00
local name_t = type(real_name)
local flattened_name
if name_t == "string" then
flattened_name = real_name
elseif name_t == "table" and real_name[1] == "ref" then
flattened_name = real_name[2]
else
flattened_name = error("don't know how to extract name from " .. tostring(name_t))
end
2013-04-30 15:16:59 +02:00
real_name = {
"string",
'"',
2014-03-07 04:19:12 +01:00
flattened_name
2013-04-30 15:16:59 +02:00
}
end
local cls = build.table({
{
"__init",
constructor
},
{
"__base",
base_name
},
{
"__name",
real_name
},
2013-07-04 01:11:42 +02:00
parent_val and {
2013-04-30 15:16:59 +02:00
"__parent",
parent_cls_name
2013-07-04 01:11:42 +02:00
} or nil
2013-04-30 15:16:59 +02:00
})
2013-07-04 01:11:42 +02:00
local class_index
if parent_val then
local class_lookup = build["if"]({
cond = {
"exp",
2014-03-07 04:19:12 +01:00
{
"ref",
"val"
},
2013-07-04 01:11:42 +02:00
"==",
"nil"
},
["then"] = {
parent_cls_name:index("name")
}
})
insert(class_lookup, {
"else",
{
"val"
}
})
class_index = build.fndef({
args = {
{
"cls"
2013-04-30 15:16:59 +02:00
},
2013-07-04 01:11:42 +02:00
{
"name"
}
},
body = {
build.assign_one(LocalName("val"), build.chain({
base = "rawget",
{
"call",
2013-04-30 15:16:59 +02:00
{
2013-07-04 01:11:42 +02:00
base_name,
2014-03-07 04:19:12 +01:00
{
"ref",
"name"
}
2013-04-30 15:16:59 +02:00
}
2013-07-04 01:11:42 +02:00
}
})),
class_lookup
}
})
else
class_index = base_name
end
local cls_mt = build.table({
{
"__index",
class_index
2013-04-30 15:16:59 +02:00
},
{
"__call",
build.fndef({
args = {
{
"cls"
},
{
"..."
}
},
body = {
build.assign_one(self_name, build.chain({
base = "setmetatable",
{
"call",
{
"{}",
base_name
}
}
})),
build.chain({
base = "cls.__init",
{
"call",
{
self_name,
"..."
}
}
}),
self_name
}
})
}
})
cls = build.chain({
base = "setmetatable",
{
"call",
{
cls,
cls_mt
}
}
})
local value = nil
do
local out_body = {
Run(function(self)
if name then
self:put_name(name)
end
return self:set("super", function(block, chain)
if chain then
2013-07-04 01:11:42 +02:00
local slice
do
2013-04-30 15:16:59 +02:00
local _accum_0 = { }
local _len_0 = 1
2013-07-04 01:11:42 +02:00
for _index_0 = 3, #chain do
local item = chain[_index_0]
2013-04-30 15:16:59 +02:00
_accum_0[_len_0] = item
_len_0 = _len_0 + 1
end
2013-07-04 01:11:42 +02:00
slice = _accum_0
end
2013-04-30 15:16:59 +02:00
local new_chain = {
"chain",
parent_cls_name
}
local head = slice[1]
if head == nil then
return parent_cls_name
end
local _exp_1 = head[1]
if "call" == _exp_1 then
local calling_name = block:get("current_block")
slice[1] = {
"call",
{
"self",
unpack(head[2])
}
}
if ntype(calling_name) == "key_literal" then
insert(new_chain, {
"dot",
calling_name[2]
})
else
insert(new_chain, {
"index",
calling_name
})
end
elseif "colon" == _exp_1 then
local call = head[3]
insert(new_chain, {
"dot",
head[2]
})
slice[1] = {
"call",
{
"self",
unpack(call[2])
}
}
end
2013-07-04 01:11:42 +02:00
for _index_0 = 1, #slice do
local item = slice[_index_0]
2013-04-30 15:16:59 +02:00
insert(new_chain, item)
end
return new_chain
else
return parent_cls_name
end
end)
end),
{
"declare_glob",
"*"
},
2013-07-04 01:11:42 +02:00
parent_val and build.assign_one(parent_cls_name, parent_val) or NOOP,
build.assign_one(base_name, {
2013-04-30 15:16:59 +02:00
"table",
properties
}),
2013-07-04 01:11:42 +02:00
build.assign_one(base_name:chain("__index"), base_name),
parent_val and build.chain({
base = "setmetatable",
{
"call",
{
base_name,
build.chain({
base = parent_cls_name,
2013-04-30 15:16:59 +02:00
{
2013-07-04 01:11:42 +02:00
"dot",
"__base"
2013-04-30 15:16:59 +02:00
}
2013-07-04 01:11:42 +02:00
})
}
2013-04-30 15:16:59 +02:00
}
2013-07-04 01:11:42 +02:00
}) or NOOP,
build.assign_one(cls_name, cls),
build.assign_one(base_name:chain("__class"), cls_name),
build.group((function()
2013-04-30 15:16:59 +02:00
if #statements > 0 then
return {
2013-07-04 01:11:42 +02:00
build.assign_one(LocalName("self"), cls_name),
build.group(statements)
2013-04-30 15:16:59 +02:00
}
end
end)()),
2013-07-04 01:11:42 +02:00
parent_val and build["if"]({
2013-04-30 15:16:59 +02:00
cond = {
"exp",
parent_cls_name:chain("__inherited")
},
["then"] = {
parent_cls_name:chain("__inherited", {
"call",
{
parent_cls_name,
cls_name
}
})
}
2013-07-04 01:11:42 +02:00
}) or NOOP,
build.group((function()
2013-04-30 15:16:59 +02:00
if name then
return {
2013-07-04 01:11:42 +02:00
build.assign_one(name, cls_name)
2013-04-30 15:16:59 +02:00
}
end
end)()),
(function()
if ret then
return ret(cls_name)
end
end)()
}
2013-07-04 01:11:42 +02:00
value = build.group({
build.group((function()
2013-04-30 15:16:59 +02:00
if ntype(name) == "value" then
return {
2013-07-04 01:11:42 +02:00
build.declare({
2013-04-30 15:16:59 +02:00
names = {
name
}
})
}
end
end)()),
2013-07-04 01:11:42 +02:00
build["do"](out_body)
2013-04-30 15:16:59 +02:00
})
end
return value
end
})
do
local _base_0 = {
body_idx = {
["for"] = 4,
["while"] = 3,
foreach = 4
},
convert = function(self, node)
local index = self.body_idx[ntype(node)]
node[index] = self:mutate_body(node[index])
return self:wrap(node)
end,
2013-07-04 01:11:42 +02:00
wrap = function(self, node, group_type)
if group_type == nil then
group_type = "block_exp"
end
return build[group_type]({
2013-04-30 15:16:59 +02:00
build.assign_one(self.accum_name, build.table()),
build.assign_one(self.len_name, 1),
node,
2013-07-04 01:11:42 +02:00
group_type == "block_exp" and self.accum_name or NOOP
2013-04-30 15:16:59 +02:00
})
end,
mutate_body = function(self, body)
local single_stm = is_singular(body)
local val
if single_stm and types.is_value(single_stm) then
body = { }
val = single_stm
else
body = apply_to_last(body, function(n)
if types.is_value(n) then
return build.assign_one(self.value_name, n)
else
return build.group({
{
"declare",
{
self.value_name
}
},
n
})
end
end)
val = self.value_name
end
local update = {
2013-07-04 01:11:42 +02:00
build.assign_one(NameProxy.index(self.accum_name, self.len_name), val),
2013-04-30 15:16:59 +02:00
{
"update",
self.len_name,
"+=",
1
}
}
insert(body, build.group(update))
return body
end
}
_base_0.__index = _base_0
local _class_0 = setmetatable({
2013-07-04 01:11:42 +02:00
__init = function(self, accum_name)
2013-04-30 15:16:59 +02:00
self.accum_name = NameProxy("accum")
self.value_name = NameProxy("value")
self.len_name = NameProxy("len")
end,
__base = _base_0,
2013-07-04 01:11:42 +02:00
__name = "Accumulator"
2013-04-30 15:16:59 +02:00
}, {
2013-07-04 01:11:42 +02:00
__index = _base_0,
2013-04-30 15:16:59 +02:00
__call = function(cls, ...)
local _self_0 = setmetatable({}, _base_0)
cls.__init(_self_0, ...)
return _self_0
end
})
_base_0.__class = _class_0
Accumulator = _class_0
end
default_accumulator = function(self, node)
return Accumulator():convert(node)
end
implicitly_return = function(scope)
local is_top = true
local fn
fn = function(stm)
local t = ntype(stm)
if t == "decorated" then
stm = scope.transform.statement(stm)
t = ntype(stm)
end
if types.cascading[t] then
is_top = false
return scope.transform.statement(stm, fn)
elseif types.manual_return[t] or not types.is_value(stm) then
if is_top and t == "return" and stm[2] == "" then
2013-07-04 01:11:42 +02:00
return NOOP
2013-04-30 15:16:59 +02:00
else
return stm
end
else
if t == "comprehension" and not types.comprehension_has_value(stm) then
return stm
else
return {
"return",
stm
}
end
end
end
return fn
end
2013-07-04 01:11:42 +02:00
Value = Transformer({
2013-04-30 15:16:59 +02:00
["for"] = default_accumulator,
["while"] = default_accumulator,
foreach = default_accumulator,
["do"] = function(self, node)
return build.block_exp(node[2])
end,
decorated = function(self, node)
return self.transform.statement(node)
end,
class = function(self, node)
return build.block_exp({
node
})
end,
string = function(self, node)
local delim = node[2]
local convert_part
convert_part = function(part)
if type(part) == "string" or part == nil then
return {
"string",
delim,
part or ""
}
else
return build.chain({
base = "tostring",
{
"call",
{
part[2]
}
}
})
end
end
if #node <= 3 then
2014-03-07 04:19:12 +01:00
if type(node[3]) == "string" then
return node
else
return convert_part(node[3])
end
2013-04-30 15:16:59 +02:00
end
local e = {
"exp",
convert_part(node[3])
}
for i = 4, #node do
insert(e, "..")
insert(e, convert_part(node[i]))
end
return e
end,
comprehension = function(self, node)
local a = Accumulator()
node = self.transform.statement(node, function(exp)
return a:mutate_body({
exp
})
end)
return a:wrap(node)
end,
tblcomprehension = function(self, node)
local _, explist, clauses = unpack(node)
local key_exp, value_exp = unpack(explist)
local accum = NameProxy("tbl")
local inner
if value_exp then
local dest = build.chain({
base = accum,
{
"index",
key_exp
}
})
inner = {
build.assign_one(dest, value_exp)
}
else
local key_name, val_name = NameProxy("key"), NameProxy("val")
local dest = build.chain({
base = accum,
{
"index",
key_name
}
})
inner = {
build.assign({
names = {
key_name,
val_name
},
values = {
key_exp
}
}),
build.assign_one(dest, val_name)
}
end
return build.block_exp({
build.assign_one(accum, build.table()),
construct_comprehension(inner, clauses),
accum
})
end,
fndef = function(self, node)
smart_node(node)
node.body = apply_to_last(node.body, implicitly_return(self))
node.body = {
Run(function(self)
return self:listen("varargs", function() end)
end),
unpack(node.body)
}
return node
end,
["if"] = function(self, node)
return build.block_exp({
node
})
end,
unless = function(self, node)
return build.block_exp({
node
})
end,
with = function(self, node)
return build.block_exp({
node
})
end,
switch = function(self, node)
return build.block_exp({
node
})
end,
chain = function(self, node)
local stub = node[#node]
for i = 3, #node do
local part = node[i]
if ntype(part) == "dot" and data.lua_keywords[part[2]] then
node[i] = {
"index",
{
"string",
'"',
part[2]
}
}
end
end
if ntype(node[2]) == "string" then
node[2] = {
"parens",
node[2]
}
elseif type(stub) == "table" and stub[1] == "colon_stub" then
table.remove(node, #node)
local base_name = NameProxy("base")
local fn_name = NameProxy("fn")
2014-03-07 04:19:12 +01:00
local is_super = ntype(node[2]) == "ref" and node[2][2] == "super"
return build.block_exp({
2013-04-30 15:16:59 +02:00
build.assign({
names = {
base_name
},
values = {
node
}
}),
build.assign({
names = {
fn_name
},
values = {
build.chain({
base = base_name,
{
"dot",
stub[2]
}
})
}
}),
build.fndef({
args = {
{
"..."
}
},
body = {
build.chain({
base = fn_name,
{
"call",
{
is_super and "self" or base_name,
"..."
}
}
})
}
})
2014-03-07 04:19:12 +01:00
})
2013-04-30 15:16:59 +02:00
end
end,
block_exp = function(self, node)
local _, body = unpack(node)
local fn = nil
local arg_list = { }
fn = smart_node(build.fndef({
body = {
Run(function(self)
return self:listen("varargs", function()
insert(arg_list, "...")
insert(fn.args, {
"..."
})
return self:unlisten("varargs")
end)
end),
unpack(body)
}
}))
return build.chain({
base = {
"parens",
fn
},
{
"call",
arg_list
}
})
end
})
return {
Statement = Statement,
Value = Value,
Run = Run
}
end
package.preload['moonscript.types'] = function()
local util = require("moonscript.util")
2013-07-04 01:11:42 +02:00
local Set
2015-02-03 18:54:34 +01:00
Set = require("moonscript.data").Set
2013-07-04 01:11:42 +02:00
local insert
2015-02-03 18:54:34 +01:00
insert = table.insert
2013-07-04 01:11:42 +02:00
local unpack
unpack = util.unpack
local manual_return = Set({
2013-04-30 15:16:59 +02:00
"foreach",
"for",
"while",
"return"
})
2013-07-04 01:11:42 +02:00
local cascading = Set({
2013-04-30 15:16:59 +02:00
"if",
"unless",
"with",
"switch",
"class",
"do"
})
local ntype
ntype = function(node)
local _exp_0 = type(node)
if "nil" == _exp_0 then
return "nil"
elseif "table" == _exp_0 then
return node[1]
else
return "value"
end
end
local mtype
do
local moon_type = util.moon.type
mtype = function(val)
local mt = getmetatable(val)
if mt and mt.smart_node then
return "table"
end
return moon_type(val)
end
end
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 is_value
is_value = function(stm)
local compile = require("moonscript.compile")
local transform = require("moonscript.transform")
return compile.Block:is_value(stm) or transform.Value:can_transform(stm)
end
local comprehension_has_value
comprehension_has_value = function(comp)
return is_value(comp[2])
end
local value_is_singular
value_is_singular = function(node)
return type(node) ~= "table" or node[1] ~= "exp" or #node == 2
end
local is_slice
is_slice = function(node)
return ntype(node) == "chain" and ntype(node[#node]) == "slice"
end
local t = { }
local node_types = {
class = {
{
"name",
"Tmp"
},
{
"body",
t
}
},
fndef = {
{
"args",
t
},
{
"whitelist",
t
},
{
"arrow",
"slim"
},
{
"body",
t
}
},
foreach = {
{
"names",
t
},
{
"iter"
},
{
"body",
t
}
},
["for"] = {
{
"name"
},
{
"bounds",
t
},
{
"body",
t
}
},
["while"] = {
{
"cond",
t
},
{
"body",
t
}
},
assign = {
{
"names",
t
},
{
"values",
t
}
},
declare = {
{
"names",
t
}
},
["if"] = {
{
"cond",
t
},
{
"then",
t
}
}
}
local build_table
build_table = function()
local key_table = { }
for node_name, args in pairs(node_types) do
local index = { }
for i, tuple in ipairs(args) do
local prop_name = tuple[1]
index[prop_name] = i + 1
end
key_table[node_name] = index
end
return key_table
end
local key_table = build_table()
local make_builder
make_builder = function(name)
local spec = node_types[name]
if not spec then
error("don't know how to build node: " .. name)
end
return function(props)
if props == nil then
props = { }
end
local node = {
name
}
for i, arg in ipairs(spec) do
local key, default_value = unpack(arg)
local val
if props[key] then
val = props[key]
else
val = default_value
end
if val == t then
val = { }
end
node[i + 1] = val
end
return node
end
end
local build = nil
build = setmetatable({
group = function(body)
if body == nil then
body = { }
end
return {
"group",
body
}
end,
["do"] = function(body)
return {
"do",
body
}
end,
assign_one = function(name, value)
return build.assign({
names = {
name
},
values = {
value
}
})
end,
table = function(tbl)
if tbl == nil then
tbl = { }
end
2013-07-04 01:11:42 +02:00
for _index_0 = 1, #tbl do
local tuple = tbl[_index_0]
2013-04-30 15:16:59 +02:00
if type(tuple[1]) == "string" then
tuple[1] = {
"key_literal",
tuple[1]
}
end
end
return {
"table",
tbl
}
end,
block_exp = function(body)
return {
"block_exp",
body
}
end,
chain = function(parts)
local base = parts.base or error("expecting base property for chain")
2014-03-07 04:19:12 +01:00
if type(base) == "string" then
base = {
"ref",
base
}
end
2013-04-30 15:16:59 +02:00
local node = {
"chain",
base
}
2013-07-04 01:11:42 +02:00
for _index_0 = 1, #parts do
local part = parts[_index_0]
2013-04-30 15:16:59 +02:00
insert(node, part)
end
return node
end
}, {
__index = function(self, name)
self[name] = make_builder(name)
return rawget(self, name)
end
})
local smart_node_mt = setmetatable({ }, {
__index = function(self, node_type)
local index = key_table[node_type]
local mt = {
smart_node = true,
__index = function(node, key)
if index[key] then
return rawget(node, index[key])
elseif type(key) == "string" then
return error("unknown key: `" .. key .. "` on node type: `" .. ntype(node) .. "`")
end
end,
__newindex = function(node, key, value)
if index[key] then
key = index[key]
end
return rawset(node, key, value)
end
}
self[node_type] = mt
return mt
end
})
local smart_node
smart_node = function(node)
return setmetatable(node, smart_node_mt[ntype(node)])
end
return {
ntype = ntype,
smart_node = smart_node,
build = build,
is_value = is_value,
is_slice = is_slice,
manual_return = manual_return,
cascading = cascading,
value_is_singular = value_is_singular,
comprehension_has_value = comprehension_has_value,
has_value = has_value,
mtype = mtype
}
end
package.preload['moonscript.util'] = function()
2013-07-04 01:11:42 +02:00
local concat
2015-02-03 18:54:34 +01:00
concat = table.concat
2013-04-30 15:16:59 +02:00
local unpack = unpack or table.unpack
local type = type
local moon = {
is_object = function(value)
return type(value) == "table" and value.__class
end,
is_a = function(thing, t)
if not (type(thing) == "table") then
return false
end
local cls = thing.__class
while cls do
if cls == t then
return true
end
cls = cls.__parent
end
return false
end,
type = function(value)
local base_type = type(value)
if base_type == "table" then
local cls = value.__class
if cls then
return cls
end
end
return base_type
end
}
local pos_to_line
pos_to_line = function(str, pos)
local line = 1
for _ in str:sub(1, pos):gmatch("\n") do
line = line + 1
end
return line
end
local trim
trim = function(str)
return str:match("^%s*(.-)%s*$")
end
local get_line
get_line = function(str, line_num)
for line in str:gmatch("([^\n]*)\n?") do
if line_num == 1 then
return line
end
line_num = line_num - 1
end
end
local get_closest_line
get_closest_line = function(str, line_num)
local line = get_line(str, line_num)
if (not line or trim(line) == "") and line_num > 1 then
return get_closest_line(str, line_num - 1)
else
return line, line_num
end
end
local reversed
reversed = function(seq)
return coroutine.wrap(function()
for i = #seq, 1, -1 do
coroutine.yield(i, seq[i])
end
end)
end
local split
split = function(str, delim)
if str == "" then
return { }
end
str = str .. delim
2013-07-04 01:11:42 +02:00
local _accum_0 = { }
local _len_0 = 1
for m in str:gmatch("(.-)" .. delim) do
_accum_0[_len_0] = m
_len_0 = _len_0 + 1
end
return _accum_0
2013-04-30 15:16:59 +02:00
end
local dump
dump = function(what)
local seen = { }
local _dump
_dump = function(what, depth)
if depth == nil then
depth = 0
end
local t = type(what)
if t == "string" then
return '"' .. what .. '"\n'
elseif t == "table" then
if seen[what] then
return "recursion(" .. tostring(what) .. ")...\n"
end
seen[what] = true
depth = depth + 1
2013-07-04 01:11:42 +02:00
local lines
do
2013-04-30 15:16:59 +02:00
local _accum_0 = { }
local _len_0 = 1
for k, v in pairs(what) do
_accum_0[_len_0] = (" "):rep(depth * 4) .. "[" .. tostring(k) .. "] = " .. _dump(v, depth)
_len_0 = _len_0 + 1
end
2013-07-04 01:11:42 +02:00
lines = _accum_0
end
2013-04-30 15:16:59 +02:00
seen[what] = false
return "{\n" .. concat(lines) .. (" "):rep((depth - 1) * 4) .. "}\n"
else
return tostring(what) .. "\n"
end
end
return _dump(what)
end
local debug_posmap
debug_posmap = function(posmap, moon_code, lua_code)
2013-07-04 01:11:42 +02:00
local tuples
do
2013-04-30 15:16:59 +02:00
local _accum_0 = { }
local _len_0 = 1
for k, v in pairs(posmap) do
_accum_0[_len_0] = {
k,
v
}
_len_0 = _len_0 + 1
end
2013-07-04 01:11:42 +02:00
tuples = _accum_0
end
2013-04-30 15:16:59 +02:00
table.sort(tuples, function(a, b)
return a[1] < b[1]
end)
2013-07-04 01:11:42 +02:00
local lines
do
2013-04-30 15:16:59 +02:00
local _accum_0 = { }
local _len_0 = 1
2013-07-04 01:11:42 +02:00
for _index_0 = 1, #tuples do
local pair = tuples[_index_0]
2013-04-30 15:16:59 +02:00
local lua_line, pos = unpack(pair)
local moon_line = pos_to_line(moon_code, pos)
local lua_text = get_line(lua_code, lua_line)
local moon_text = get_closest_line(moon_code, moon_line)
local _value_0 = tostring(pos) .. "\t " .. tostring(lua_line) .. ":[ " .. tostring(trim(lua_text)) .. " ] >> " .. tostring(moon_line) .. ":[ " .. tostring(trim(moon_text)) .. " ]"
_accum_0[_len_0] = _value_0
_len_0 = _len_0 + 1
end
2013-07-04 01:11:42 +02:00
lines = _accum_0
end
2013-04-30 15:16:59 +02:00
return concat(lines, "\n")
end
local setfenv = setfenv or function(fn, env)
local name
local i = 1
while true do
name = debug.getupvalue(fn, i)
if not name or name == "_ENV" then
break
end
i = i + 1
end
if name then
debug.upvaluejoin(fn, i, (function()
return env
end), 1)
end
return fn
end
local getfenv = getfenv or function(fn)
local i = 1
while true do
local name, val = debug.getupvalue(fn, i)
if not (name) then
break
end
if name == "_ENV" then
return val
end
i = i + 1
end
return nil
end
local get_options
get_options = function(...)
local count = select("#", ...)
local opts = select(count, ...)
if type(opts) == "table" then
return opts, unpack({
...
}, nil, count - 1)
else
return { }, ...
end
end
2015-02-03 18:54:34 +01:00
local safe_module
safe_module = function(name, tbl)
return setmetatable(tbl, {
__index = function(self, key)
return error("Attempted to import non-existent `" .. tostring(key) .. "` from " .. tostring(name))
end
})
end
2013-04-30 15:16:59 +02:00
return {
moon = moon,
pos_to_line = pos_to_line,
get_closest_line = get_closest_line,
get_line = get_line,
reversed = reversed,
trim = trim,
split = split,
dump = dump,
debug_posmap = debug_posmap,
getfenv = getfenv,
setfenv = setfenv,
get_options = get_options,
2015-02-03 18:54:34 +01:00
unpack = unpack,
safe_module = safe_module
2013-04-30 15:16:59 +02:00
}
end
package.preload['moonscript.version'] = function()
2015-02-03 18:54:34 +01:00
local version = "0.3.0"
return {
version = version,
print_version = function()
return print("MoonScript version " .. tostring(version))
end
}
2013-04-30 15:16:59 +02:00
end
return package.preload["moonscript"]()