Improvements to command line file handling.
This commit is contained in:
parent
df9a82a971
commit
3a049c15df
216
nomsu.lua
216
nomsu.lua
@ -34,6 +34,7 @@ do
|
||||
local _obj_0 = require("code_obj")
|
||||
Nomsu, Lua, Source = _obj_0.Nomsu, _obj_0.Lua, _obj_0.Source
|
||||
end
|
||||
local STDIN, STDOUT, STDERR = "/dev/fd/0", "/dev/fd/1", "/dev/fd/2"
|
||||
FILE_CACHE = setmetatable({ }, {
|
||||
__index = function(self, filename)
|
||||
local file = io.open(filename)
|
||||
@ -56,7 +57,7 @@ iterate_single = function(item, prev)
|
||||
end
|
||||
local all_files
|
||||
all_files = function(path)
|
||||
if path:match("%.nom$") or path:match("%.lua$") then
|
||||
if path:match("%.nom$") or path:match("%.lua$") or path:match("^/dev/fd/[012]$") then
|
||||
return iterate_single, path
|
||||
end
|
||||
path = path:gsub("\\", "\\\\"):gsub("`", ""):gsub('"', '\\"'):gsub("$", "")
|
||||
@ -388,7 +389,7 @@ do
|
||||
if filename:match("%.lua$") then
|
||||
local file = assert(FILE_CACHE[filename], "Could not find file: " .. tostring(filename))
|
||||
ret = self:run_lua(Lua(Source(filename), file))
|
||||
elseif filename:match("%.nom$") then
|
||||
elseif filename:match("%.nom$") or filename:match("^/dev/fd/[012]$") then
|
||||
if not self.skip_precompiled then
|
||||
local lua_filename = filename:gsub("%.nom$", ".lua")
|
||||
local file = FILE_CACHE[lua_filename]
|
||||
@ -1032,89 +1033,13 @@ OPTIONS
|
||||
end
|
||||
return info
|
||||
end
|
||||
local run
|
||||
run = function()
|
||||
if args.flags["-v"] then
|
||||
nomsu.debug = true
|
||||
local print_err_msg
|
||||
print_err_msg = function(error_message, stack_offset)
|
||||
if stack_offset == nil then
|
||||
stack_offset = 2
|
||||
end
|
||||
if args.input == "-" then
|
||||
args.input = "/dev/fd/0"
|
||||
end
|
||||
if args.output == nil then
|
||||
args.output = "/dev/null"
|
||||
elseif args.output == "-" then
|
||||
args.output = "/dev/fd/1"
|
||||
end
|
||||
nomsu.skip_precompiled = not args.flags["-O"]
|
||||
if args.input then
|
||||
local compile_fn = nil
|
||||
if args.output == "/dev/fd/1" and not args.print_file then
|
||||
args.print_file = "/dev/null"
|
||||
elseif not args.print_file or args.print_file == "-" then
|
||||
args.print_file = "/dev/fd/1"
|
||||
end
|
||||
local print_file = io.open(args.print_file, "w")
|
||||
nomsu.environment.print = function(...)
|
||||
local N = select("#", ...)
|
||||
if N > 0 then
|
||||
print_file:write(tostring(select(1, ...)))
|
||||
for i = 2, N do
|
||||
print_file:write('\t', tostring(select(1, ...)))
|
||||
end
|
||||
end
|
||||
print_file:write('\n')
|
||||
return print_file:flush()
|
||||
end
|
||||
local output_file = io.open(args.output, 'w')
|
||||
compile_fn = function(code)
|
||||
return output_file:write("local IMMEDIATE = true;\n" .. tostring(code))
|
||||
end
|
||||
if args.input:match("%.lua$") then
|
||||
dofile(args.input)(nomsu, { })
|
||||
else
|
||||
for input_file in all_files(args.input) do
|
||||
if args.flags["-s"] then
|
||||
nomsu:parse(io.open(input_file):read("*a"))
|
||||
elseif args.flags["-f"] then
|
||||
local tree = nomsu:parse(io.open(input_file):read("*a"))
|
||||
output_file:write(tostring(tree:as_nomsu()))
|
||||
else
|
||||
nomsu:run_file(input_file, compile_fn)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
if not args.input or args.flags["-i"] then
|
||||
nomsu:run('use "core"')
|
||||
while true do
|
||||
io.write(colored.bright(colored.yellow(">> ")))
|
||||
local buff = ""
|
||||
while true do
|
||||
local line = io.read("*L")
|
||||
if line == "\n" or not line then
|
||||
break
|
||||
end
|
||||
line = line:gsub("\t", " ")
|
||||
buff = buff .. line
|
||||
io.write(colored.dim(colored.yellow(".. ")))
|
||||
end
|
||||
if #buff == 0 then
|
||||
break
|
||||
end
|
||||
local ret
|
||||
ok, ret = pcall(nomsu.run, nomsu, buff)
|
||||
if ok and ret ~= nil then
|
||||
print("= " .. repr(ret))
|
||||
elseif not ok then
|
||||
print(colored.bright(colored.red(ret)))
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
local err_hand
|
||||
err_hand = function(error_message)
|
||||
print(tostring(colored.red("ERROR:")) .. " " .. tostring(colored.bright(colored.yellow(colored.onred((error_message or ""))))))
|
||||
print("stack traceback:")
|
||||
io.stderr:write(tostring(colored.red("ERROR:")) .. " " .. tostring(colored.bright(colored.red((error_message or "")))) .. "\n")
|
||||
io.stderr:write("stack traceback:\n")
|
||||
ok, to_lua = pcall(function()
|
||||
return require('moonscript.base').to_lua
|
||||
end)
|
||||
@ -1125,7 +1050,7 @@ OPTIONS
|
||||
end
|
||||
local nomsu_source = FILE_CACHE["nomsu.moon"]
|
||||
local _, line_table = to_lua(nomsu_source)
|
||||
local level = 2
|
||||
local level = stack_offset
|
||||
while true do
|
||||
local _continue_0 = false
|
||||
repeat
|
||||
@ -1182,15 +1107,132 @@ OPTIONS
|
||||
end
|
||||
end
|
||||
local _from = colored.dim(colored.white("|"))
|
||||
print(("%32s %s %s"):format(name, _from, line))
|
||||
io.stderr:write(("%32s %s %s\n"):format(name, _from, line))
|
||||
_continue_0 = true
|
||||
until true
|
||||
if not _continue_0 then
|
||||
break
|
||||
end
|
||||
end
|
||||
return io.stderr:flush()
|
||||
end
|
||||
local run
|
||||
run = function()
|
||||
if args.flags["-v"] then
|
||||
nomsu.debug = true
|
||||
end
|
||||
if args.input == "-" then
|
||||
args.input = STDIN
|
||||
end
|
||||
local output_file
|
||||
if args.output == "-" then
|
||||
output_file = io.stdout
|
||||
elseif args.output then
|
||||
output_file = io.open(args.output, 'w')
|
||||
end
|
||||
local print_file
|
||||
if args.print_file == "-" then
|
||||
print_file = io.stdout
|
||||
elseif args.print_file then
|
||||
print_file = io.open(args.print_file, 'w')
|
||||
elseif output_file == io.stdout then
|
||||
print_file = nil
|
||||
else
|
||||
print_file = io.stdout
|
||||
end
|
||||
nomsu.skip_precompiled = not args.flags["-O"]
|
||||
if args.input then
|
||||
local compile_fn = nil
|
||||
if print_file == nil then
|
||||
nomsu.environment.print = function() end
|
||||
elseif print_file ~= io.stdout then
|
||||
nomsu.environment.print = function(...)
|
||||
local N = select("#", ...)
|
||||
if N > 0 then
|
||||
print_file:write(tostring(select(1, ...)))
|
||||
for i = 2, N do
|
||||
print_file:write('\t', tostring(select(1, ...)))
|
||||
end
|
||||
end
|
||||
print_file:write('\n')
|
||||
return print_file:flush()
|
||||
end
|
||||
end
|
||||
if output_file then
|
||||
compile_fn = function(code)
|
||||
output_file:write("local IMMEDIATE = true;\n" .. tostring(code))
|
||||
return output_file:flush()
|
||||
end
|
||||
end
|
||||
if args.flags["-s"] then
|
||||
for input_file in all_files(args.input) do
|
||||
nomsu:parse(io.open(input_file):read("*a"))
|
||||
end
|
||||
if print_file then
|
||||
print_file:write("Success!\n")
|
||||
print_file:flush()
|
||||
end
|
||||
elseif args.flags["-f"] then
|
||||
for input_file in all_files(args.input) do
|
||||
local tree = nomsu:parse(io.open(input_file):read("*a"))
|
||||
local formatted = tostring(tree:as_nomsu())
|
||||
if output_file then
|
||||
output_file:write(formatted, "\n")
|
||||
output_file:flush()
|
||||
end
|
||||
if print_file then
|
||||
print_file:write(formatted, "\n")
|
||||
print_file:flush()
|
||||
end
|
||||
end
|
||||
elseif args.input == STDIN then
|
||||
nomsu:run(io.input():read("*a"), compile_fn)
|
||||
else
|
||||
nomsu:run_file(args.input, compile_fn)
|
||||
end
|
||||
end
|
||||
if not args.input or args.flags["-i"] then
|
||||
nomsu:run('use "core"')
|
||||
while true do
|
||||
io.write(colored.bright(colored.yellow(">> ")))
|
||||
local buff = ""
|
||||
while true do
|
||||
local line = io.read("*L")
|
||||
if line == "\n" or not line then
|
||||
if #buff > 0 then
|
||||
io.write("\027[1A\027[2K")
|
||||
end
|
||||
break
|
||||
end
|
||||
line = line:gsub("\t", " ")
|
||||
buff = buff .. line
|
||||
io.write(colored.dim(colored.yellow(".. ")))
|
||||
end
|
||||
if #buff == 0 then
|
||||
break
|
||||
end
|
||||
local ret
|
||||
ok, ret = pcall(nomsu.run, nomsu, buff)
|
||||
if ok and ret ~= nil then
|
||||
print("= " .. repr(ret))
|
||||
elseif not ok then
|
||||
print_err_msg(ret)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
local err_hand
|
||||
err_hand = function(error_message)
|
||||
print_err_msg(error_message)
|
||||
return os.exit(false, true)
|
||||
end
|
||||
require('ldt').guard(run)
|
||||
do
|
||||
local ldt = require('ldt')
|
||||
if ldt then
|
||||
ldt.guard(run)
|
||||
else
|
||||
xpcall(run, err_hand)
|
||||
end
|
||||
end
|
||||
end
|
||||
return NomsuCompiler
|
||||
|
170
nomsu.moon
170
nomsu.moon
@ -26,6 +26,7 @@ colored = setmetatable({}, {__index:(_,color)-> ((msg)-> colors[color]..tostring
|
||||
{:insert, :remove, :concat} = table
|
||||
debug_getinfo = debug.getinfo
|
||||
{:Nomsu, :Lua, :Source} = require "code_obj"
|
||||
STDIN, STDOUT, STDERR = "/dev/fd/0", "/dev/fd/1", "/dev/fd/2"
|
||||
|
||||
-- TODO:
|
||||
-- consider non-linear codegen, rather than doing thunks for things like comprehensions
|
||||
@ -52,7 +53,7 @@ FILE_CACHE = setmetatable {}, {
|
||||
iterate_single = (item, prev) -> if item == prev then nil else item
|
||||
all_files = (path)->
|
||||
-- Sanitize path
|
||||
if path\match("%.nom$") or path\match("%.lua$")
|
||||
if path\match("%.nom$") or path\match("%.lua$") or path\match("^/dev/fd/[012]$")
|
||||
return iterate_single, path
|
||||
-- TODO: improve sanitization
|
||||
path = path\gsub("\\","\\\\")\gsub("`","")\gsub('"','\\"')\gsub("$","")
|
||||
@ -336,7 +337,7 @@ class NomsuCompiler
|
||||
if filename\match("%.lua$")
|
||||
file = assert(FILE_CACHE[filename], "Could not find file: #{filename}")
|
||||
ret = @run_lua(Lua(Source(filename), file))
|
||||
elseif filename\match("%.nom$")
|
||||
elseif filename\match("%.nom$") or filename\match("^/dev/fd/[012]$")
|
||||
if not @skip_precompiled -- Look for precompiled version
|
||||
lua_filename = filename\gsub("%.nom$", ".lua")
|
||||
file = FILE_CACHE[lua_filename]
|
||||
@ -727,84 +728,17 @@ OPTIONS
|
||||
]=]
|
||||
return info
|
||||
|
||||
|
||||
run = ->
|
||||
if args.flags["-v"]
|
||||
nomsu.debug = true
|
||||
|
||||
if args.input == "-" then args.input = "/dev/fd/0" -- stdin
|
||||
if args.output == nil then args.output = "/dev/null"
|
||||
elseif args.output == "-" then args.output = "/dev/fd/1" -- stdout
|
||||
|
||||
nomsu.skip_precompiled = not args.flags["-O"]
|
||||
if args.input
|
||||
compile_fn = nil
|
||||
if args.output == "/dev/fd/1" and not args.print_file
|
||||
args.print_file = "/dev/null"
|
||||
elseif not args.print_file or args.print_file == "-"
|
||||
args.print_file = "/dev/fd/1" -- stdout
|
||||
|
||||
print_file = io.open(args.print_file, "w")
|
||||
nomsu.environment.print = (...)->
|
||||
N = select("#",...)
|
||||
if N > 0
|
||||
print_file\write(tostring(select(1,...)))
|
||||
for i=2,N
|
||||
print_file\write('\t',tostring(select(1,...)))
|
||||
print_file\write('\n')
|
||||
print_file\flush!
|
||||
|
||||
output_file = io.open(args.output, 'w')
|
||||
compile_fn = (code)->
|
||||
output_file\write("local IMMEDIATE = true;\n"..tostring(code))
|
||||
|
||||
if args.input\match("%.lua$")
|
||||
dofile(args.input)(nomsu, {})
|
||||
else
|
||||
for input_file in all_files(args.input)
|
||||
-- Check syntax:
|
||||
if args.flags["-s"]
|
||||
nomsu\parse(io.open(input_file)\read("*a"))
|
||||
elseif args.flags["-f"]
|
||||
tree = nomsu\parse(io.open(input_file)\read("*a"))
|
||||
output_file\write(tostring(tree\as_nomsu!))
|
||||
else
|
||||
nomsu\run_file(input_file, compile_fn)
|
||||
|
||||
if not args.input or args.flags["-i"]
|
||||
-- REPL
|
||||
nomsu\run('use "core"')
|
||||
while true
|
||||
io.write(colored.bright colored.yellow ">> ")
|
||||
buff = ""
|
||||
while true
|
||||
line = io.read("*L")
|
||||
if line == "\n" or not line
|
||||
break
|
||||
line = line\gsub("\t", " ")
|
||||
buff ..= line
|
||||
io.write(colored.dim colored.yellow ".. ")
|
||||
if #buff == 0
|
||||
break
|
||||
ok, ret = pcall(nomsu.run, nomsu, buff)
|
||||
if ok and ret != nil
|
||||
print "= "..repr(ret)
|
||||
elseif not ok
|
||||
print colored.bright colored.red ret
|
||||
|
||||
err_hand = (error_message)->
|
||||
-- TODO: write properly to stderr
|
||||
print("#{colored.red "ERROR:"} #{colored.bright colored.yellow colored.onred (error_message or "")}")
|
||||
print("stack traceback:")
|
||||
print_err_msg = (error_message, stack_offset=2)->
|
||||
io.stderr\write("#{colored.red "ERROR:"} #{colored.bright colored.red (error_message or "")}\n")
|
||||
io.stderr\write("stack traceback:\n")
|
||||
|
||||
-- TODO: properly print out the calling site of nomsu code, not just the *called* code
|
||||
|
||||
ok, to_lua = pcall -> require('moonscript.base').to_lua
|
||||
if not ok then to_lua = -> nil
|
||||
nomsu_source = FILE_CACHE["nomsu.moon"]
|
||||
_, line_table = to_lua(nomsu_source)
|
||||
|
||||
level = 2
|
||||
level = stack_offset
|
||||
while true
|
||||
-- TODO: reduce duplicate code
|
||||
calling_fn = debug_getinfo(level)
|
||||
@ -841,8 +775,91 @@ OPTIONS
|
||||
line = colored.blue("#{calling_fn.short_src}:#{calling_fn.currentline}")
|
||||
name = colored.bright(colored.blue(name or "???"))
|
||||
_from = colored.dim colored.white "|"
|
||||
print(("%32s %s %s")\format(name, _from, line))
|
||||
io.stderr\write(("%32s %s %s\n")\format(name, _from, line))
|
||||
io.stderr\flush!
|
||||
|
||||
run = ->
|
||||
if args.flags["-v"]
|
||||
nomsu.debug = true
|
||||
|
||||
if args.input == "-" then args.input = STDIN
|
||||
|
||||
output_file = if args.output == "-" then io.stdout
|
||||
elseif args.output then io.open(args.output, 'w')
|
||||
|
||||
print_file = if args.print_file == "-" then io.stdout
|
||||
elseif args.print_file then io.open(args.print_file, 'w')
|
||||
elseif output_file == io.stdout then nil
|
||||
else io.stdout
|
||||
|
||||
nomsu.skip_precompiled = not args.flags["-O"]
|
||||
if args.input
|
||||
compile_fn = nil
|
||||
if print_file == nil
|
||||
nomsu.environment.print = ->
|
||||
elseif print_file != io.stdout
|
||||
nomsu.environment.print = (...)->
|
||||
N = select("#",...)
|
||||
if N > 0
|
||||
print_file\write(tostring(select(1,...)))
|
||||
for i=2,N
|
||||
print_file\write('\t',tostring(select(1,...)))
|
||||
print_file\write('\n')
|
||||
print_file\flush!
|
||||
|
||||
if output_file
|
||||
compile_fn = (code)->
|
||||
output_file\write("local IMMEDIATE = true;\n"..tostring(code))
|
||||
output_file\flush!
|
||||
|
||||
if args.flags["-s"]
|
||||
-- Check syntax:
|
||||
for input_file in all_files(args.input)
|
||||
nomsu\parse(io.open(input_file)\read("*a"))
|
||||
if print_file
|
||||
print_file\write("Success!\n")
|
||||
print_file\flush!
|
||||
elseif args.flags["-f"]
|
||||
-- Auto-format
|
||||
for input_file in all_files(args.input)
|
||||
tree = nomsu\parse(io.open(input_file)\read("*a"))
|
||||
formatted = tostring(tree\as_nomsu!)
|
||||
if output_file
|
||||
output_file\write(formatted, "\n")
|
||||
output_file\flush!
|
||||
if print_file
|
||||
print_file\write(formatted, "\n")
|
||||
print_file\flush!
|
||||
elseif args.input == STDIN
|
||||
nomsu\run(io.input!\read("*a"), compile_fn)
|
||||
else
|
||||
nomsu\run_file(args.input, compile_fn)
|
||||
|
||||
if not args.input or args.flags["-i"]
|
||||
-- REPL
|
||||
nomsu\run('use "core"')
|
||||
while true
|
||||
io.write(colored.bright colored.yellow ">> ")
|
||||
buff = ""
|
||||
while true
|
||||
line = io.read("*L")
|
||||
if line == "\n" or not line
|
||||
if #buff > 0
|
||||
io.write("\027[1A\027[2K")
|
||||
break -- Run buffer
|
||||
line = line\gsub("\t", " ")
|
||||
buff ..= line
|
||||
io.write(colored.dim colored.yellow ".. ")
|
||||
if #buff == 0
|
||||
break -- Exit
|
||||
ok, ret = pcall(nomsu.run, nomsu, buff)
|
||||
if ok and ret != nil
|
||||
print "= "..repr(ret)
|
||||
elseif not ok
|
||||
print_err_msg ret
|
||||
|
||||
err_hand = (error_message)->
|
||||
print_err_msg error_message
|
||||
os.exit(false, true)
|
||||
|
||||
-- Note: xpcall has a slightly different API in Lua <=5.1 vs. >=5.2, but this works
|
||||
@ -851,8 +868,9 @@ OPTIONS
|
||||
|
||||
--ProFi = require 'ProFi'
|
||||
--ProFi\start()
|
||||
require('ldt').guard run
|
||||
--xpcall(run, err_hand)
|
||||
if ldt = require('ldt')
|
||||
ldt.guard run
|
||||
else xpcall(run, err_hand)
|
||||
--ProFi\stop()
|
||||
--ProFi\writeReport( 'MyProfilingReport.txt' )
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user