mirror of
https://github.com/leafo/moonscript.git
synced 2025-01-09 00:04:22 +00:00
start moving moonc code to moonscript
This commit is contained in:
parent
a4585f8b1c
commit
c60d83c546
128
bin/moonc
128
bin/moonc
@ -55,62 +55,19 @@ function print_help(err)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function mkdir(path)
|
|
||||||
local chunks = util.split(path, dirsep)
|
|
||||||
local accum
|
|
||||||
|
|
||||||
for _, dir in ipairs(chunks) do
|
|
||||||
accum = accum and accum.. dirsep ..dir or dir
|
|
||||||
lfs.mkdir(accum)
|
|
||||||
end
|
|
||||||
|
|
||||||
return lfs.attributes(path, "mode")
|
|
||||||
end
|
|
||||||
|
|
||||||
function normalize(path)
|
|
||||||
return path:match("^(.-)" .. dirsep .. "*$")..dirsep
|
|
||||||
end
|
|
||||||
|
|
||||||
function parse_dir(fname)
|
|
||||||
return fname:match("^(.-)[^" .. dirsep .. "]*$")
|
|
||||||
end
|
|
||||||
|
|
||||||
function parse_file(fname)
|
|
||||||
return fname:match("^.-([^" .. dirsep .. "]*)$")
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
-- convert .moon to .lua
|
|
||||||
function convert_path(path)
|
|
||||||
local new_path = path:gsub("%.moon$", ".lua")
|
|
||||||
if new_path == path then
|
|
||||||
new_path = path .. ".lua"
|
|
||||||
end
|
|
||||||
return new_path
|
|
||||||
end
|
|
||||||
|
|
||||||
function log_msg(...)
|
function log_msg(...)
|
||||||
if not opts.p then
|
if not opts.p then
|
||||||
io.stderr:write(table.concat({...}, " ") .. "\n")
|
io.stderr:write(table.concat({...}, " ") .. "\n")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local gettime = nil
|
local moonc = require("moonscript.cmd.moonc")
|
||||||
if opts.b then
|
local mkdir = moonc.mkdir
|
||||||
pcall(function()
|
local normalize_dir = moonc.normalize_dir
|
||||||
require "socket"
|
local parse_dir = moonc.parse_dir
|
||||||
gettime = socket.gettime
|
local parse_file = moonc.parse_file
|
||||||
end)
|
local convert_path = moonc.convert_path
|
||||||
|
local compile_file_text = moonc.compile_file_text
|
||||||
function format_time(time)
|
|
||||||
return ("%.3fms"):format(time*1000)
|
|
||||||
end
|
|
||||||
if not gettime then
|
|
||||||
print_help"LuaSocket needed for benchmark"
|
|
||||||
end
|
|
||||||
else
|
|
||||||
gettime = function() return 0 end
|
|
||||||
end
|
|
||||||
|
|
||||||
function write_file(fname, code)
|
function write_file(fname, code)
|
||||||
if opts.p then
|
if opts.p then
|
||||||
@ -125,50 +82,8 @@ function write_file(fname, code)
|
|||||||
out_f:write(code.."\n")
|
out_f:write(code.."\n")
|
||||||
out_f:close()
|
out_f:close()
|
||||||
end
|
end
|
||||||
return true
|
|
||||||
end
|
|
||||||
|
|
||||||
function compile_file(text, fname)
|
return "built"
|
||||||
local parse_time = gettime()
|
|
||||||
local tree, err = parse.string(text)
|
|
||||||
parse_time = gettime() - parse_time
|
|
||||||
|
|
||||||
if not tree then
|
|
||||||
return nil, err
|
|
||||||
end
|
|
||||||
|
|
||||||
if opts.T then
|
|
||||||
opts.p = true
|
|
||||||
dump_tree(tree)
|
|
||||||
return ""
|
|
||||||
else
|
|
||||||
local compile_time = gettime()
|
|
||||||
local code, posmap_or_err, err_pos = compile.tree(tree)
|
|
||||||
compile_time = gettime() - compile_time
|
|
||||||
|
|
||||||
if not code then
|
|
||||||
return nil, compile.format_error(posmap_or_err, err_pos, text)
|
|
||||||
end
|
|
||||||
|
|
||||||
if opts.X then
|
|
||||||
opts.p = true
|
|
||||||
print("Pos", "Lua", ">>", "Moon")
|
|
||||||
print(util.debug_posmap(posmap_or_err, text, code))
|
|
||||||
return ""
|
|
||||||
end
|
|
||||||
|
|
||||||
if opts.b then
|
|
||||||
opts.p = true
|
|
||||||
return table.concat({
|
|
||||||
fname,
|
|
||||||
"Parse time \t" .. format_time(parse_time),
|
|
||||||
"Compile time\t" .. format_time(compile_time),
|
|
||||||
""
|
|
||||||
}, "\n")
|
|
||||||
end
|
|
||||||
|
|
||||||
return code
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function compile_and_write(from, to)
|
function compile_and_write(from, to)
|
||||||
@ -178,16 +93,25 @@ function compile_and_write(from, to)
|
|||||||
end
|
end
|
||||||
local text = f:read("*a")
|
local text = f:read("*a")
|
||||||
|
|
||||||
local code, err = compile_file(text, from)
|
local code, err = compile_file_text(text, from, {
|
||||||
if not code then
|
benchmark = opts.b,
|
||||||
|
show_posmap = opts.X,
|
||||||
|
show_parse_tree = opts.T,
|
||||||
|
})
|
||||||
|
|
||||||
|
if not code and err then
|
||||||
return nil, err
|
return nil, err
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if not code then
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
return write_file(to, code)
|
return write_file(to, code)
|
||||||
end
|
end
|
||||||
|
|
||||||
function scan_directory(root, collected)
|
function scan_directory(root, collected)
|
||||||
root = normalize(root)
|
root = normalize_dir(root)
|
||||||
collected = collected or {}
|
collected = collected or {}
|
||||||
|
|
||||||
for fname in lfs.dir(root) do
|
for fname in lfs.dir(root) do
|
||||||
@ -247,7 +171,7 @@ function get_files(fname, files)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
target_fname = normalize(opts.t) .. target_fname
|
target_fname = normalize_dir(opts.t) .. target_fname
|
||||||
end
|
end
|
||||||
|
|
||||||
table.insert(files, {sub_fname, target_fname})
|
table.insert(files, {sub_fname, target_fname})
|
||||||
@ -255,7 +179,7 @@ function get_files(fname, files)
|
|||||||
else
|
else
|
||||||
local target_fname = convert_path(fname)
|
local target_fname = convert_path(fname)
|
||||||
if opts.t then
|
if opts.t then
|
||||||
local prefix = normalize(opts.t)
|
local prefix = normalize_dir(opts.t)
|
||||||
|
|
||||||
if is_abs_path(target_fname) then
|
if is_abs_path(target_fname) then
|
||||||
target_fname = parse_file(target_fname)
|
target_fname = parse_file(target_fname)
|
||||||
@ -426,8 +350,8 @@ if opts.w then
|
|||||||
err,
|
err,
|
||||||
"\n",
|
"\n",
|
||||||
}, "\n"))
|
}, "\n"))
|
||||||
else
|
elseif success == "build" then
|
||||||
log_msg("Built:", fname, "->", target)
|
log_msg("Built", fname, "->", target)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -450,8 +374,8 @@ else
|
|||||||
if not success then
|
if not success then
|
||||||
io.stderr:write(fname .. "\t" .. err .. "\n")
|
io.stderr:write(fname .. "\t" .. err .. "\n")
|
||||||
os.exit(1)
|
os.exit(1)
|
||||||
else
|
elseif success == "build" then
|
||||||
log_msg("Built", fname, "->", target)
|
log_msg("Built", fname)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -28,6 +28,7 @@ build = {
|
|||||||
["moonscript.base"] = "moonscript/base.lua",
|
["moonscript.base"] = "moonscript/base.lua",
|
||||||
["moonscript.cmd.coverage"] = "moonscript/cmd/coverage.lua",
|
["moonscript.cmd.coverage"] = "moonscript/cmd/coverage.lua",
|
||||||
["moonscript.cmd.lint"] = "moonscript/cmd/lint.lua",
|
["moonscript.cmd.lint"] = "moonscript/cmd/lint.lua",
|
||||||
|
["moonscript.cmd.moonc"] = "moonscript/cmd/moonc.lua",
|
||||||
["moonscript.compile"] = "moonscript/compile.lua",
|
["moonscript.compile"] = "moonscript/compile.lua",
|
||||||
["moonscript.compile.statement"] = "moonscript/compile/statement.lua",
|
["moonscript.compile.statement"] = "moonscript/compile/statement.lua",
|
||||||
["moonscript.compile.value"] = "moonscript/compile/value.lua",
|
["moonscript.compile.value"] = "moonscript/compile/value.lua",
|
||||||
|
134
moonscript/cmd/moonc.lua
Normal file
134
moonscript/cmd/moonc.lua
Normal file
@ -0,0 +1,134 @@
|
|||||||
|
local lfs = require("lfs")
|
||||||
|
local split
|
||||||
|
do
|
||||||
|
local _obj_0 = require("moonscript.util")
|
||||||
|
split = _obj_0.split
|
||||||
|
end
|
||||||
|
local dirsep = package.config:sub(1, 1)
|
||||||
|
local dirsep_chars
|
||||||
|
if dirsep == "\\" then
|
||||||
|
dirsep_chars = "\\/"
|
||||||
|
else
|
||||||
|
dirsep_chars = dirsep
|
||||||
|
end
|
||||||
|
local mkdir
|
||||||
|
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
|
||||||
|
local normalize_dir
|
||||||
|
normalize_dir = function(path)
|
||||||
|
return path:match("^(.-)[" .. tostring(dirsep_chars) .. "]*$") .. dirsep
|
||||||
|
end
|
||||||
|
local parse_dir
|
||||||
|
parse_dir = function(path)
|
||||||
|
return (path:match("^(.-)[^" .. tostring(dirsep_chars) .. "]*$"))
|
||||||
|
end
|
||||||
|
local parse_file
|
||||||
|
parse_file = function(path)
|
||||||
|
return (path:match("^.-([^" .. tostring(dirsep_chars) .. "]*)$"))
|
||||||
|
end
|
||||||
|
local convert_path
|
||||||
|
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
|
||||||
|
local format_time
|
||||||
|
format_time = function(time)
|
||||||
|
return ("%.3fms"):format(time * 1000)
|
||||||
|
end
|
||||||
|
local gettime
|
||||||
|
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
|
||||||
|
local compile_file_text
|
||||||
|
compile_file_text = function(text, fname, 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 nil
|
||||||
|
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
|
||||||
|
do
|
||||||
|
local _obj_0 = require("moonscript.util")
|
||||||
|
debug_posmap = _obj_0.debug_posmap
|
||||||
|
end
|
||||||
|
print("Pos", "Lua", ">>", "Moon")
|
||||||
|
print(debug_posmap(posmap_or_err, text, code))
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
if opts.benchmark then
|
||||||
|
print(table.concat({
|
||||||
|
fname,
|
||||||
|
"Parse time \t" .. format_time(parse_time),
|
||||||
|
"Compile time\t" .. format_time(compile_time),
|
||||||
|
""
|
||||||
|
}, "\n"))
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
return code
|
||||||
|
end
|
||||||
|
return {
|
||||||
|
dirsep = dirsep,
|
||||||
|
mkdir = mkdir,
|
||||||
|
normalize_dir = normalize_dir,
|
||||||
|
parse_dir = parse_dir,
|
||||||
|
parse_file = parse_file,
|
||||||
|
new_path = new_path,
|
||||||
|
convert_path = convert_path,
|
||||||
|
gettime = gettime,
|
||||||
|
format_time = format_time,
|
||||||
|
compile_file_text = compile_file_text
|
||||||
|
}
|
122
moonscript/cmd/moonc.moon
Normal file
122
moonscript/cmd/moonc.moon
Normal file
@ -0,0 +1,122 @@
|
|||||||
|
-- assorted utilities for moonc command line tool
|
||||||
|
|
||||||
|
lfs = require "lfs"
|
||||||
|
|
||||||
|
import split from require "moonscript.util"
|
||||||
|
|
||||||
|
dirsep = package.config\sub 1,1
|
||||||
|
dirsep_chars = if dirsep == "\\"
|
||||||
|
"\\/" -- windows
|
||||||
|
else
|
||||||
|
dirsep
|
||||||
|
|
||||||
|
|
||||||
|
-- similar to mkdir -p
|
||||||
|
mkdir = (path) ->
|
||||||
|
chunks = split path, dirsep
|
||||||
|
|
||||||
|
local accum
|
||||||
|
for dir in *chunks
|
||||||
|
accum = accum and "#{accum}#{dirsep}#{dir}" or dir
|
||||||
|
lfs.mkdir accum
|
||||||
|
|
||||||
|
lfs.attributes path, "mode"
|
||||||
|
|
||||||
|
-- strips excess / and ensures path ends with /
|
||||||
|
normalize_dir = (path) ->
|
||||||
|
path\match("^(.-)[#{dirsep_chars}]*$") .. dirsep
|
||||||
|
|
||||||
|
-- parse the directory out of a path
|
||||||
|
parse_dir = (path) ->
|
||||||
|
(path\match "^(.-)[^#{dirsep_chars}]*$")
|
||||||
|
|
||||||
|
-- parse the filename out of a path
|
||||||
|
parse_file = (path) ->
|
||||||
|
(path\match "^.-([^#{dirsep_chars}]*)$")
|
||||||
|
|
||||||
|
-- converts .moon to a .lua path for calcuating compile target
|
||||||
|
convert_path = (path) ->
|
||||||
|
new_path = path\gsub "%.moon$", ".lua"
|
||||||
|
if new_path == path
|
||||||
|
new_path = path .. ".lua"
|
||||||
|
new_path
|
||||||
|
|
||||||
|
format_time = (time) ->
|
||||||
|
"%.3fms"\format time*1000
|
||||||
|
|
||||||
|
gettime = do
|
||||||
|
local socket
|
||||||
|
->
|
||||||
|
if socket == nil
|
||||||
|
pcall ->
|
||||||
|
socket = require "socket"
|
||||||
|
|
||||||
|
unless socket
|
||||||
|
socket = false
|
||||||
|
|
||||||
|
if socket
|
||||||
|
socket.gettime()
|
||||||
|
else
|
||||||
|
nil, "LuaSocket needed for benchmark"
|
||||||
|
|
||||||
|
-- compiles file to lua
|
||||||
|
-- returns nil, error on error
|
||||||
|
-- returns just nil if some option handled the output instead
|
||||||
|
compile_file_text = (text, fname, opts={}) ->
|
||||||
|
parse = require "moonscript.parse"
|
||||||
|
compile = require "moonscript.compile"
|
||||||
|
|
||||||
|
parse_time = if opts.benchmark
|
||||||
|
assert gettime!
|
||||||
|
|
||||||
|
tree, err = parse.string text
|
||||||
|
return nil, err unless tree
|
||||||
|
|
||||||
|
if parse_time
|
||||||
|
parse_time = gettime! - parse_time
|
||||||
|
|
||||||
|
if opts.show_parse_tree
|
||||||
|
dump = require "moonscript.dump"
|
||||||
|
dump.tree tree
|
||||||
|
return nil
|
||||||
|
|
||||||
|
compile_time = if opts.benchmark
|
||||||
|
gettime!
|
||||||
|
|
||||||
|
code, posmap_or_err, err_pos = compile.tree tree
|
||||||
|
|
||||||
|
unless code
|
||||||
|
return nil, compile.format_error posmap_or_err, err_pos, text
|
||||||
|
|
||||||
|
if compile_time
|
||||||
|
compile_time = gettime() - compile_time
|
||||||
|
|
||||||
|
if opts.show_posmap
|
||||||
|
import debug_posmap from require "moonscript.util"
|
||||||
|
print "Pos", "Lua", ">>", "Moon"
|
||||||
|
print debug_posmap posmap_or_err, text, code
|
||||||
|
return nil
|
||||||
|
|
||||||
|
if opts.benchmark
|
||||||
|
print table.concat {
|
||||||
|
fname,
|
||||||
|
"Parse time \t" .. format_time(parse_time),
|
||||||
|
"Compile time\t" .. format_time(compile_time),
|
||||||
|
""
|
||||||
|
}, "\n"
|
||||||
|
return nil
|
||||||
|
|
||||||
|
code
|
||||||
|
|
||||||
|
{
|
||||||
|
:dirsep
|
||||||
|
:mkdir
|
||||||
|
:normalize_dir
|
||||||
|
:parse_dir
|
||||||
|
:parse_file
|
||||||
|
:new_path
|
||||||
|
:convert_path
|
||||||
|
:gettime
|
||||||
|
:format_time
|
||||||
|
:compile_file_text
|
||||||
|
}
|
68
spec/cmd_spec.moon
Normal file
68
spec/cmd_spec.moon
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
|
||||||
|
moonc = require "moonscript.cmd.moonc"
|
||||||
|
|
||||||
|
-- TODO: add specs for windows equivalents
|
||||||
|
|
||||||
|
describe "moonc", ->
|
||||||
|
same = (fn, a, b)->
|
||||||
|
assert.same b, fn a
|
||||||
|
|
||||||
|
it "should normalize dir", ->
|
||||||
|
same moonc.normalize_dir, "hello/world/", "hello/world/"
|
||||||
|
same moonc.normalize_dir, "hello/world//", "hello/world/"
|
||||||
|
same moonc.normalize_dir, "", "/" -- wrong
|
||||||
|
same moonc.normalize_dir, "hello", "hello/"
|
||||||
|
|
||||||
|
|
||||||
|
it "should parse dir", ->
|
||||||
|
same moonc.parse_dir, "/hello/world/file", "/hello/world/"
|
||||||
|
same moonc.parse_dir, "/hello/world/", "/hello/world/"
|
||||||
|
same moonc.parse_dir, "world", ""
|
||||||
|
same moonc.parse_dir, "", ""
|
||||||
|
|
||||||
|
it "should parse file", ->
|
||||||
|
same moonc.parse_file, "/hello/world/file", "file"
|
||||||
|
same moonc.parse_file, "/hello/world/", ""
|
||||||
|
same moonc.parse_file, "world", "world"
|
||||||
|
same moonc.parse_file, "", ""
|
||||||
|
|
||||||
|
it "convert path", ->
|
||||||
|
same moonc.convert_path, "test.moon", "test.lua"
|
||||||
|
same moonc.convert_path, "/hello/file.moon", "/hello/file.lua"
|
||||||
|
same moonc.convert_path, "/hello/world/file", "/hello/world/file.lua"
|
||||||
|
|
||||||
|
it "chould compile file text", ->
|
||||||
|
assert.same {
|
||||||
|
[[return print('hello')]]
|
||||||
|
}, {
|
||||||
|
moonc.compile_file_text "print'hello'", "test.moon"
|
||||||
|
}
|
||||||
|
|
||||||
|
describe "stubbed lfs", ->
|
||||||
|
local dirs
|
||||||
|
|
||||||
|
before_each ->
|
||||||
|
dirs = {}
|
||||||
|
package.loaded.lfs = nil
|
||||||
|
package.loaded["moonscript.cmd.moonc"] = nil
|
||||||
|
|
||||||
|
package.loaded.lfs = {
|
||||||
|
mkdir: (dir) -> table.insert dirs, dir
|
||||||
|
attributes: -> "directory"
|
||||||
|
}
|
||||||
|
|
||||||
|
moonc = require "moonscript.cmd.moonc"
|
||||||
|
|
||||||
|
after_each ->
|
||||||
|
package.loaded.lfs = nil
|
||||||
|
package.loaded["moonscript.cmd.moonc"] = nil
|
||||||
|
moonc = require "moonscript.cmd.moonc"
|
||||||
|
|
||||||
|
it "should make directory", ->
|
||||||
|
moonc.mkdir "hello/world/directory"
|
||||||
|
assert.same {
|
||||||
|
"hello"
|
||||||
|
"hello/world"
|
||||||
|
"hello/world/directory"
|
||||||
|
}, dirs
|
||||||
|
|
Loading…
Reference in New Issue
Block a user