aboutsummaryrefslogtreecommitdiff
path: root/nomsu.lua
diff options
context:
space:
mode:
authorBruce Hill <bitbucket@bruce-hill.com>2018-06-21 19:12:59 -0700
committerBruce Hill <bitbucket@bruce-hill.com>2018-06-21 19:13:47 -0700
commit86a3219e7fc3244331595819f742b365172f96ad (patch)
tree948a3f308bd9c45b85efa2e130af8432bb1a97e2 /nomsu.lua
parent7761f715f7497e8b325a4f1134869f332848fd16 (diff)
Cleanup of some metaprogramming stuff, as well as adding support for
"package.nomsupath" to search for files in different locations, and prioritizing use of "luafilesystem" over system calls.
Diffstat (limited to 'nomsu.lua')
-rw-r--r--nomsu.lua114
1 files changed, 107 insertions, 7 deletions
diff --git a/nomsu.lua b/nomsu.lua
index ca0f7ac..b561eb9 100644
--- a/nomsu.lua
+++ b/nomsu.lua
@@ -1,3 +1,4 @@
+local EXIT_SUCCESS, EXIT_FAILURE = 0, 1
local usage = [=[Nomsu Compiler
Usage: (lua nomsu.lua | moon nomsu.moon) [-i] [-O] [-v] [-c] [-f] [-s] [--help] [-p print_file] file1 file2... [-- nomsu args...]
@@ -13,8 +14,14 @@ OPTIONS
-p <file> Print to the specified file instead of stdout.
<input> Input file can be "-" to use stdin.
]=]
-local lpeg = require('lpeg')
-local re = require('re')
+local ok, _ = pcall(function()
+ lpeg = require('lpeg')
+ re = require('re')
+end)
+if not ok then
+ print("Error: unable to find the 'lpeg' Lua module. Please install LPEG either from http://www.inf.puc-rio.br/~roberto/lpeg/re.html or, if you use luarocks: `luarocks install lpeg`")
+ os.exit(EXIT_FAILURE)
+end
local Errhand = require("error_handling")
local NomsuCompiler = require("nomsu_compiler")
local NomsuCode, LuaCode, Source
@@ -46,10 +53,101 @@ local args = table.concat(arg, ";") .. ";"
args = parser:match(args)
if not args or args.help then
print(usage)
- os.exit()
+ os.exit(EXIT_FAILURE)
end
local nomsu = NomsuCompiler
nomsu.arg = args.nomsu_args
+FILE_CACHE = setmetatable({ }, {
+ __index = function(self, filename)
+ local file = io.open(filename)
+ if not (file) then
+ return nil
+ end
+ local contents = file:read("*a")
+ file:close()
+ self[filename] = contents
+ return contents
+ end
+})
+local match, sub, rep, gsub, format, byte, find
+do
+ local _obj_0 = string
+ match, sub, rep, gsub, format, byte, match, find = _obj_0.match, _obj_0.sub, _obj_0.rep, _obj_0.gsub, _obj_0.format, _obj_0.byte, _obj_0.match, _obj_0.find
+end
+local iterate_single
+iterate_single = function(item, prev)
+ if item == prev then
+ return nil
+ else
+ return item
+ end
+end
+local lfs
+ok, lfs = pcall(require, "lfs")
+if ok then
+ all_files = function(path)
+ local browse
+ browse = function(filename)
+ local file_type = lfs.attributes(filename, 'mode')
+ if file_type == 'file' then
+ if match(filename, "%.nom$") or match(filename, "%.lua$") then
+ coroutine.yield(filename)
+ return true
+ end
+ elseif file_type == 'directory' then
+ for subfile in lfs.dir(filename) do
+ if not (subfile == "." or subfile == "..") then
+ browse(filename .. "/" .. subfile)
+ end
+ end
+ return true
+ elseif file_type == 'char device' then
+ coroutine.yield(filename)
+ return true
+ end
+ return false
+ end
+ return coroutine.wrap(function()
+ if not browse(path) and package.nomsupath then
+ browse(package.nomsupath .. "/" .. path)
+ end
+ return nil
+ end)
+ end
+else
+ local ret = os.execute('find . -maxdepth 0')
+ if not (ret == true or ret == 0) then
+ error("Could not find 'luafilesystem' module and couldn't run system command `find` (this might happen on Windows). Please install `luafilesystem` (which can be found at: http://keplerproject.github.io/luafilesystem/ or `luarocks install luafilesystem`)", 0)
+ end
+ all_files = function(path)
+ if match(path, "%.nom$") or match(path, "%.lua$") or match(path, "^/dev/fd/[012]$") then
+ return iterate_single, path
+ end
+ path = gsub(path, "\\", "\\\\")
+ path = gsub(path, "`", "")
+ path = gsub(path, '"', '\\"')
+ path = gsub(path, "$", "")
+ return coroutine.wrap(function()
+ local f = io.popen('find -L "' .. path .. '" -not -path "*/\\.*" -type f -name "*.nom"')
+ local found = false
+ for line in f:lines() do
+ found = true
+ coroutine.yield(line)
+ end
+ if not found and package.nomsupath then
+ f:close()
+ f = io.popen('find -L "' .. package.nomsupath .. '/' .. path .. '" -not -path "*/\\.*" -type f -name "*.nom"')
+ for line in f:lines() do
+ coroutine.yield(line)
+ end
+ end
+ local success = f:close()
+ if not (success) then
+ return error("Invalid file path: " .. tostring(path))
+ end
+ end)
+ end
+end
local run
run = function()
for i, input in ipairs(args.inputs) do
@@ -120,7 +218,8 @@ run = function()
local filename = input_files[_index_0]
if args.syntax then
local file_contents = io.open(filename):read('*a')
- local ok, err = pcall(nomsu.parse, nomsu, file_contents, Source(filename, 1, #file_contents))
+ local err
+ ok, err = pcall(nomsu.parse, nomsu, file_contents, Source(filename, 1, #file_contents))
if not ok then
table.insert(parse_errs, err)
elseif print_file then
@@ -149,9 +248,9 @@ run = function()
if #parse_errs > 0 then
io.stderr:write(table.concat(parse_errs, "\n\n"))
io.stderr:flush()
- os.exit(false, true)
+ os.exit(EXIT_FAILURE)
elseif args.syntax then
- os.exit(true, true)
+ os.exit(EXIT_SUCCESS)
end
if args.interactive then
for repl_line = 1, math.huge do
@@ -179,7 +278,8 @@ run = function()
err_hand = function(error_message)
return Errhand.print_error(error_message)
end
- local ok, ret = xpcall(nomsu.run, err_hand, nomsu, buff, Source(pseudo_filename, 1, #buff))
+ local ret
+ ok, ret = xpcall(nomsu.run, err_hand, nomsu, buff, Source(pseudo_filename, 1, #buff))
if ok and ret ~= nil then
print("= " .. repr(ret))
elseif not ok then