diff options
| author | Bruce Hill <bitbucket@bruce-hill.com> | 2018-06-21 19:12:59 -0700 |
|---|---|---|
| committer | Bruce Hill <bitbucket@bruce-hill.com> | 2018-06-21 19:13:47 -0700 |
| commit | 86a3219e7fc3244331595819f742b365172f96ad (patch) | |
| tree | 948a3f308bd9c45b85efa2e130af8432bb1a97e2 /nomsu.lua | |
| parent | 7761f715f7497e8b325a4f1134869f332848fd16 (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.lua | 114 |
1 files changed, 107 insertions, 7 deletions
@@ -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 |
