aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/nomsu.143
-rw-r--r--files.lua84
-rw-r--r--files.moon65
-rw-r--r--nomsu.lua253
-rwxr-xr-xnomsu.moon201
-rw-r--r--nomsu_compiler.lua2
-rw-r--r--nomsu_compiler.moon2
7 files changed, 300 insertions, 350 deletions
diff --git a/doc/nomsu.1 b/doc/nomsu.1
index 2524aba..a76a377 100644
--- a/doc/nomsu.1
+++ b/doc/nomsu.1
@@ -1,6 +1,6 @@
.\" Manpage for nomsu.
.\" Contact bruce@bruce-hill.com to correct errors or typos.
-.TH man 8 "24 June 2018" "1.0" "nomsu man page"
+.TH man 8 "9 July 2018" "1.1" "nomsu man page"
.SH NAME
nomsu \- run a Nomsu program
.SH SYNOPSIS
@@ -9,27 +9,26 @@ nomsu \- run a Nomsu program
.I options
]
[
-.I scripts
-[ --
+.I nomsu_file
+[
.I args
]
]
.SH DESCRIPTION
-.B
-nomsu
-is the compiler/interpreter for the Nomsu programming language.
+\fBnomsu\fR is the compiler/interpreter for the Nomsu programming language.
+.SH INPUT
+.TP
+If an input file is provided, \fBnomsu\fR will run that file.
+.TP
+If an input directory is provided, \fBnomsu\fR will run every .nom file in the directory and its subdirectories.
+.TP
+If "-" is used, \fBnomsu\fR will read from standard input
+.TP
+If no input files are provided, \fBnomsu\fR will run in interactive mode.
.SH OPTIONS
.TP
.BI \-V " version"
-Specify the desired Nomsu version (defaults to the latest installed version). E.g.
-.B
-nomsu -V 1.2
-or
-.B
-nomsu -V 1.2.5.9
-.TP
-.B \-i
-Enter interactive mode after the input files are executed.
+Specify the desired Nomsu version (defaults to the latest installed version). E.g. \fBnomsu -V 1.2\fR or \fBnomsu -V 1.2.5.9\fR
.TP
.B \-O
Run the compiler in optimized mode (use precompiled .lua versions of .nom files, when available)
@@ -38,13 +37,13 @@ Run the compiler in optimized mode (use precompiled .lua versions of .nom files,
Verbose: print compiled lua code as it's generated for the input files.
.TP
.B \-c
-Compile input files into .lua files
+Compile the input files into .lua files.
.TP
-.B \-f
-Auto-format the given Nomsu file and print the result.
+.B \-s " file"
+Check the input files for syntax errors without running them.
.TP
-.B \-s
-Check the program for syntax errors.
+.B \-I " file"
+Include the specified file (or all .nom files in a directory and its subdirectories) in the input files.
.TP
.B \--version
Print the version number and exit.
@@ -69,8 +68,8 @@ Compiles the Nomsu file 'my_file.nom' into a Lua file called 'my_file.lua'
.TP
.B
-nomsu my_directory
-Runs every '.nom' file in 'my_directory' or its subdirectories.
+nomsu -I one.nom -I two.nom three.nom
+Runs 'one.nom', then 'two.nom', then 'three.nom'.
.TP
.B
diff --git a/files.lua b/files.lua
index 686ec8c..d9686d9 100644
--- a/files.lua
+++ b/files.lua
@@ -56,30 +56,52 @@ iterate_single = function(item, prev)
end
local ok, lfs = pcall(require, "lfs")
if ok then
- files.walk = function(path)
- if match(path, "%.nom$") or match(path, "%.lua$") or path == 'stdin' then
- return iterate_single, path
+ local raw_file_exists
+ raw_file_exists = function(filename)
+ local mode = lfs.attributes(filename, 'mode')
+ if mode == 'file' or mode == 'directory' then
+ return true
+ else
+ return false
end
- 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)
+ end
+ files.exists = function(path)
+ if path == 'stdin' or raw_file_exists(path) then
+ return true
+ end
+ if package.nomsupath then
+ for nomsupath in package.nomsupath:gmatch("[^;]+") do
+ if raw_file_exists(nomsupath .. "/" .. path) then
return true
end
- elseif file_type == 'directory' then
- for subfile in lfs.dir(filename) do
- if not (subfile == "." or subfile == ".." or not subfile:match("%.nom$")) then
- browse(filename .. "/" .. subfile)
- end
- end
- return true
- elseif file_type == 'char device' then
+ end
+ end
+ return false
+ end
+ 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
- return false
+ elseif file_type == 'directory' then
+ for subfile in lfs.dir(filename) do
+ if not (subfile == "." or subfile == ".." or not subfile:match("%.nom$")) then
+ browse(filename .. "/" .. subfile)
+ end
+ end
+ return true
+ elseif file_type == 'char device' then
+ coroutine.yield(filename)
+ return true
+ end
+ return false
+ end
+ files.walk = function(path)
+ if match(path, "%.nom$") or match(path, "%.lua$") or path == 'stdin' then
+ return iterate_single, path
end
return coroutine.wrap(function()
if not browse(path) and package.nomsupath then
@@ -96,14 +118,32 @@ else
if io.popen('find . -maxdepth 0'):close() 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
- files.walk = function(path)
- if match(path, "%.nom$") or match(path, "%.lua$") or path == 'stdin' then
- return iterate_single, path
- end
+ local sanitize
+ sanitize = function(path)
path = gsub(path, "\\", "\\\\")
path = gsub(path, "`", "")
path = gsub(path, '"', '\\"')
path = gsub(path, "$", "")
+ return path
+ end
+ files.exists = function(path)
+ if not (io.popen("ls " .. tostring(sanitize(path))):close()) then
+ return true
+ end
+ if package.nomsupath then
+ for nomsupath in package.nomsupath:gmatch("[^;]+") do
+ if not (io.popen("ls " .. tostring(nomsupath) .. "/" .. tostring(sanitize(path))):close()) then
+ return true
+ end
+ end
+ end
+ return false
+ end
+ files.walk = function(path)
+ if match(path, "%.nom$") or match(path, "%.lua$") or path == 'stdin' then
+ return iterate_single, path
+ end
+ path = sanitize(path)
return coroutine.wrap(function()
local f = io.popen('find -L "' .. path .. '" -not -path "*/\\.*" -type f -name "*.nom"')
local found = false
diff --git a/files.moon b/files.moon
index c53af55..708bba1 100644
--- a/files.moon
+++ b/files.moon
@@ -35,26 +35,35 @@ iterate_single = (item, prev) -> if item == prev then nil else item
iterate_single = (item, prev) -> if item == prev then nil else item
ok, lfs = pcall(require, "lfs")
if ok
+ raw_file_exists = (filename)->
+ mode = lfs.attributes(filename, 'mode')
+ return if mode == 'file' or mode == 'directory' then true else false
+ files.exists = (path)->
+ return true if path == 'stdin' or raw_file_exists(path)
+ if package.nomsupath
+ for nomsupath in package.nomsupath\gmatch("[^;]+")
+ return true if raw_file_exists(nomsupath.."/"..path)
+ return false
+ -- Return 'true' if any files or directories are found, otherwise 'false', and yield every filename
+ browse = (filename)->
+ file_type = lfs.attributes(filename, 'mode')
+ if file_type == 'file'
+ if match(filename, "%.nom$") or match(filename, "%.lua$")
+ coroutine.yield filename
+ return true
+ elseif file_type == 'directory'
+ for subfile in lfs.dir(filename)
+ -- Only include .nom files unless directly specified
+ unless subfile == "." or subfile == ".." or not subfile\match("%.nom$")
+ browse(filename.."/"..subfile)
+ return true
+ elseif file_type == 'char device'
+ coroutine.yield(filename)
+ return true
+ return false
files.walk = (path)->
if match(path, "%.nom$") or match(path, "%.lua$") or path == 'stdin'
return iterate_single, path
- -- Return 'true' if any files or directories are found, otherwise 'false'
- browse = (filename)->
- file_type = lfs.attributes(filename, 'mode')
- if file_type == 'file'
- if match(filename, "%.nom$") or match(filename, "%.lua$")
- coroutine.yield filename
- return true
- elseif file_type == 'directory'
- for subfile in lfs.dir(filename)
- -- Only include .nom files unless directly specified
- unless subfile == "." or subfile == ".." or not subfile\match("%.nom$")
- browse(filename.."/"..subfile)
- return true
- elseif file_type == 'char device'
- coroutine.yield(filename)
- return true
- return false
return coroutine.wrap ->
if not browse(path) and package.nomsupath
for nomsupath in package.nomsupath\gmatch("[^;]+")
@@ -63,16 +72,26 @@ if ok
else
if io.popen('find . -maxdepth 0')\close!
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
-
- files.walk = (path)->
- if match(path, "%.nom$") or match(path, "%.lua$") or path == 'stdin'
- return iterate_single, path
- -- Sanitize path
- -- TODO: improve sanitization
+
+ -- TODO: improve sanitization
+ sanitize = (path)->
path = gsub(path,"\\","\\\\")
path = gsub(path,"`","")
path = gsub(path,'"','\\"')
path = gsub(path,"$","")
+ return path
+
+ files.exists = (path)->
+ return true unless io.popen("ls #{sanitize(path)}")\close!
+ if package.nomsupath
+ for nomsupath in package.nomsupath\gmatch("[^;]+")
+ return true unless io.popen("ls #{nomsupath}/#{sanitize(path)}")\close!
+ return false
+
+ files.walk = (path)->
+ if match(path, "%.nom$") or match(path, "%.lua$") or path == 'stdin'
+ return iterate_single, path
+ path = sanitize(path)
return coroutine.wrap ->
f = io.popen('find -L "'..path..'" -not -path "*/\\.*" -type f -name "*.nom"')
found = false
diff --git a/nomsu.lua b/nomsu.lua
index c131c17..d02150d 100644
--- a/nomsu.lua
+++ b/nomsu.lua
@@ -53,20 +53,18 @@ end
local EXIT_SUCCESS, EXIT_FAILURE = 0, 1
local usage = [=[Nomsu Compiler
-Usage: (lua nomsu.lua | moon nomsu.moon) [-V version] [-i] [-O] [-v] [-c] [-f] [-s] [--help] [--version] [-p print_file] file1 file2... [-- nomsu args...]
+Usage: (nomsu | lua nomsu.lua | moon nomsu.moon) [-V version] [-O] [-v] [-c] [-s] [-I file] [--help | -h] [--version] [file [nomsu args...]]
OPTIONS
- -i Run the compiler in interactive mode (REPL)
- -O Run the compiler in optimized mode (use precompiled .lua versions of Nomsu files, when available)
- -v Verbose: print compiled lua code
- -c Compile .nom files into .lua files
- -f Auto-format the given Nomsu file and print the result.
- -s Check the program for syntax errors.
+ -O Run the compiler in optimized mode (use precompiled .lua versions of Nomsu files, when available).
+ -v Verbose: print compiled lua code.
+ -c Compile the input files into a .lua files.
+ -s Check the input files for syntax errors.
+ -I <file> Add an additional input file or directory.
-h/--help Print this message.
--version Print the version number and exit.
- -V specify which Nomsu version is desired
- -p <file> Print to the specified file instead of stdout.
- <input> Input file can be "-" to use stdin.
+ -V specify which Nomsu version is desired.
+ <file> The Nomsu file to run (can be "-" to use stdin).
]=]
local ok, _ = pcall(function()
lpeg = require('lpeg')
@@ -88,22 +86,24 @@ repr = require("utils").repr
if not arg or debug.getinfo(2).func == require then
return NomsuCompiler
end
-local parser = re.compile([[ args <- {| (flag ";")* {:inputs: {| ({file} ";")* |} :} {:nomsu_args: {| ("--;" ({[^;]*} ";")*)? |} :} ";"? |} !.
+local file_queue = { }
+local parser = re.compile([[ args <- {| (flag ";")* (({~ file ~} -> add_file) ";")? {:nomsu_args: {| ({[^;]*} ";")* |} :} ";"? |} !.
flag <-
- {:interactive: ("-i" -> true) :}
- / {:optimized: ("-O" -> true) :}
- / {:format: ("-f" -> true) :}
- / {:syntax: ("-s" -> true) :}
- / {:print_file: "-p" ";" {file} :}
- / {:compile: ("-c" -> true) :}
+ {:optimized: ("-O" -> true) :}
+ / ("-I" (";")? ({~ file ~} -> add_file))
+ / ({:check_syntax: ("-s" -> true):})
+ / ({:compile: ("-c" -> true):})
/ {:verbose: ("-v" -> true) :}
/ {:help: (("-h" / "--help") -> true) :}
/ {:version: ("--version" -> true) :}
/ {:requested_version: "-V" ((";")? {([0-9.])+})? :}
- file <- "-" / [^;]+
+ file <- ("-" -> "stdin") / {[^;]+}
]], {
["true"] = function()
return true
+ end,
+ add_file = function(f)
+ return table.insert(file_queue, f)
end
})
local arg_string = table.concat(arg, ";") .. ";"
@@ -134,160 +134,106 @@ FILE_CACHE = setmetatable({ }, {
})
local run
run = function()
- for i, input in ipairs(args.inputs) do
- if input == "-" then
- args.inputs[i] = 'stdin'
- end
- end
- if #args.inputs == 0 and not args.interactive then
- args.inputs = {
- "core"
- }
- args.interactive = true
- 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')
- else
- print_file = io.stdout
- end
- if print_file == nil then
- nomsu.print = function() end
- elseif print_file ~= io.stdout then
- nomsu.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
local input_files = { }
- local to_run = { }
- local _list_0 = args.inputs
- for _index_0 = 1, #_list_0 do
- local _continue_0 = false
- repeat
- local input = _list_0[_index_0]
- if input == 'stdin' then
- input_files[#input_files + 1] = 'stdin'
- to_run['stdin'] = true
- _continue_0 = true
- break
- end
- local found = false
- for f in files.walk(input) do
- input_files[#input_files + 1] = f
- to_run[f] = true
- found = true
- end
- if not found then
- error("Could not find: " .. tostring(input))
- end
- _continue_0 = true
- until true
- if not _continue_0 then
- break
+ for _index_0 = 1, #file_queue do
+ local f = file_queue[_index_0]
+ if not (files.exists(f)) then
+ error("Could not find: " .. tostring(f))
+ end
+ for filename in files.walk(f) do
+ input_files[filename] = true
end
end
nomsu.can_optimize = function(f)
if not (args.optimized) then
return false
end
- if to_run[f] then
+ if args.compile and input_files[f] then
return false
end
return true
end
+ local get_file_and_source
+ get_file_and_source = function(filename)
+ local file, source
+ if filename == 'stdin' then
+ file = io.read("*a")
+ files.spoof('stdin', file)
+ source = Source('stdin', 1, #file)
+ elseif filename:match("%.nom$") then
+ file = files.read(filename)
+ if not file then
+ error("File does not exist: " .. tostring(filename), 0)
+ end
+ source = Source(filename, 1, #file)
+ else
+ return nil
+ end
+ source = Source(filename, 1, #file)
+ return file, source
+ end
+ local run_file
+ run_file = function(filename, lua_handler)
+ if lua_handler == nil then
+ lua_handler = nil
+ end
+ local file, source = get_file_and_source(filename)
+ if not (file) then
+ return nil
+ end
+ local tree = nomsu:parse(file, source)
+ if tree then
+ if tree.type ~= "FileChunks" then
+ tree = {
+ tree
+ }
+ end
+ for _index_0 = 1, #tree do
+ local chunk = tree[_index_0]
+ local lua = nomsu:compile(chunk):as_statements("return ")
+ lua:declare_locals()
+ lua:prepend("-- File: " .. tostring(source.filename:gsub("\n.*", "...")) .. "\n")
+ if lua_handler then
+ lua_handler(tostring(lua))
+ end
+ nomsu:run_lua(lua)
+ end
+ end
+ end
local parse_errs = { }
- local _list_1 = args.inputs
- for _index_0 = 1, #_list_1 do
- local arg = _list_1[_index_0]
- for filename in files.walk(arg) do
+ for _index_0 = 1, #file_queue do
+ local f = file_queue[_index_0]
+ for filename in files.walk(f) do
local _continue_0 = false
repeat
- local file, source
- if filename == 'stdin' then
- file = io.read("*a")
- files.spoof('stdin', file)
- source = Source('stdin', 1, #file)
- elseif filename:match("%.nom$") then
- file = files.read(filename)
- if not file then
- error("File does not exist: " .. tostring(filename), 0)
+ if args.check_syntax then
+ local file, source = get_file_and_source(filename)
+ if not (file) then
+ _continue_0 = true
+ break
end
- source = Source(filename, 1, #file)
- else
- _continue_0 = true
- break
+ nomsu:parse(file, source)
+ print("Parse succeeded: " .. tostring(filename))
end
- source = Source(filename, 1, #file)
- local output
if args.compile then
- output = io.open(filename:gsub("%.nom$", ".lua"), "w")
- else
- output = nil
- end
- if args.syntax then
- local err
- ok, err = pcall(nomsu.parse, nomsu, file, source)
- if not ok then
- table.insert(parse_errs, err)
- elseif print_file then
- print_file:write("Parse succeeded: " .. tostring(filename) .. "\n")
- print_file:flush()
- end
- _continue_0 = true
- break
- end
- local tree = nomsu:parse(file, source)
- if args.format then
- local formatted = tree and tostring(nomsu:tree_to_nomsu(tree)) or ""
- if print_file then
- print_file:write(formatted, "\n")
- print_file:flush()
- end
- _continue_0 = true
- break
- end
- if tree then
- if tree.type == "FileChunks" then
- for _index_1 = 1, #tree do
- local chunk = tree[_index_1]
- local lua = nomsu:compile(chunk):as_statements("return ")
- lua:declare_locals()
- lua:prepend("-- File: " .. tostring(source.filename:gsub("\n.*", "...")) .. "\n")
- if args.compile then
- output:write(tostring(lua), "\n")
- end
- if args.verbose then
- print(tostring(lua))
- end
- nomsu:run_lua(lua)
- end
+ local output
+ if filename == 'stdin' then
+ output = io.output()
else
- local lua = nomsu:compile(tree):as_statements("return ")
- lua:declare_locals()
- lua:prepend("-- File: " .. tostring(source.filename:gsub("\n.*", "...")) .. "\n")
- if args.compile then
- output:write(tostring(lua), "\n")
- end
+ output = io.open(filename:gsub("%.nom$", ".lua"), "w")
+ end
+ run_file(filename, function(lua)
+ output:write(tostring(lua), "\n")
if args.verbose then
- print(tostring(lua))
+ return print(tostring(lua))
end
- nomsu:run_lua(lua)
- end
- end
- if args.compile then
+ end)
print(("Compiled %-25s -> %s"):format(filename, filename:gsub("%.nom$", ".lua")))
output:close()
end
+ if not args.check_syntax and not args.compile then
+ run_file(filename, (args.verbose and print or nil))
+ end
_continue_0 = true
until true
if not _continue_0 then
@@ -295,14 +241,7 @@ run = function()
end
end
end
- if #parse_errs > 0 then
- io.stderr:write(table.concat(parse_errs, "\n\n"))
- io.stderr:flush()
- os.exit(EXIT_FAILURE)
- elseif args.syntax then
- os.exit(EXIT_SUCCESS)
- end
- if args.interactive then
+ if #file_queue == 0 then
nomsu:run([[use "core"
use "lib/consolecolor.nom"
action [quit, exit]: lua> "os.exit(0)"
diff --git a/nomsu.moon b/nomsu.moon
index 1b32982..6897a1f 100755
--- a/nomsu.moon
+++ b/nomsu.moon
@@ -11,20 +11,18 @@ EXIT_SUCCESS, EXIT_FAILURE = 0, 1
usage = [=[
Nomsu Compiler
-Usage: (lua nomsu.lua | moon nomsu.moon) [-V version] [-i] [-O] [-v] [-c] [-f] [-s] [--help] [--version] [-p print_file] file1 file2... [-- nomsu args...]
+Usage: (nomsu | lua nomsu.lua | moon nomsu.moon) [-V version] [-O] [-v] [-c] [-s] [-I file] [--help | -h] [--version] [file [nomsu args...]]
OPTIONS
- -i Run the compiler in interactive mode (REPL)
- -O Run the compiler in optimized mode (use precompiled .lua versions of Nomsu files, when available)
- -v Verbose: print compiled lua code
- -c Compile .nom files into .lua files
- -f Auto-format the given Nomsu file and print the result.
- -s Check the program for syntax errors.
+ -O Run the compiler in optimized mode (use precompiled .lua versions of Nomsu files, when available).
+ -v Verbose: print compiled lua code.
+ -c Compile the input files into a .lua files.
+ -s Check the input files for syntax errors.
+ -I <file> Add an additional input file or directory.
-h/--help Print this message.
--version Print the version number and exit.
- -V specify which Nomsu version is desired
- -p <file> Print to the specified file instead of stdout.
- <input> Input file can be "-" to use stdin.
+ -V specify which Nomsu version is desired.
+ <file> The Nomsu file to run (can be "-" to use stdin).
]=]
ok, _ = pcall ->
@@ -43,21 +41,23 @@ NomsuCompiler = require "nomsu_compiler"
if not arg or debug.getinfo(2).func == require
return NomsuCompiler
+file_queue = {}
parser = re.compile([[
- args <- {| (flag ";")* {:inputs: {| ({file} ";")* |} :} {:nomsu_args: {| ("--;" ({[^;]*} ";")*)? |} :} ";"? |} !.
+ args <- {| (flag ";")* (({~ file ~} -> add_file) ";")? {:nomsu_args: {| ({[^;]*} ";")* |} :} ";"? |} !.
flag <-
- {:interactive: ("-i" -> true) :}
- / {:optimized: ("-O" -> true) :}
- / {:format: ("-f" -> true) :}
- / {:syntax: ("-s" -> true) :}
- / {:print_file: "-p" ";" {file} :}
- / {:compile: ("-c" -> true) :}
+ {:optimized: ("-O" -> true) :}
+ / ("-I" (";")? ({~ file ~} -> add_file))
+ / ({:check_syntax: ("-s" -> true):})
+ / ({:compile: ("-c" -> true):})
/ {:verbose: ("-v" -> true) :}
/ {:help: (("-h" / "--help") -> true) :}
/ {:version: ("--version" -> true) :}
/ {:requested_version: "-V" ((";")? {([0-9.])+})? :}
- file <- "-" / [^;]+
-]], {true: -> true})
+ file <- ("-" -> "stdin") / {[^;]+}
+]], {
+ true: -> true
+ add_file: (f)-> table.insert(file_queue, f)
+})
arg_string = table.concat(arg, ";")..";"
args = parser\match(arg_string)
if not args or args.help
@@ -87,123 +87,76 @@ FILE_CACHE = setmetatable {}, {
}
run = ->
- for i,input in ipairs args.inputs
- if input == "-" then args.inputs[i] = 'stdin'
-
- if #args.inputs == 0 and not args.interactive
- args.inputs = {"core"}
- args.interactive = true
-
- print_file = if args.print_file == "-" then io.stdout
- elseif args.print_file then io.open(args.print_file, 'w')
- else io.stdout
-
- if print_file == nil
- nomsu.print = ->
- elseif print_file != io.stdout
- nomsu.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!
-
input_files = {}
- to_run = {}
- for input in *args.inputs
- if input == 'stdin'
- input_files[#input_files+1] = 'stdin'
- to_run['stdin'] = true
- continue
- found = false
- for f in files.walk(input)
- input_files[#input_files+1] = f
- to_run[f] = true
- found = true
- if not found
- error("Could not find: #{input}")
+ for f in *file_queue
+ unless files.exists(f)
+ error("Could not find: #{f}")
+ for filename in files.walk(f)
+ input_files[filename] = true
nomsu.can_optimize = (f)->
return false unless args.optimized
- return false if to_run[f]
+ return false if args.compile and input_files[f]
return true
+ get_file_and_source = (filename)->
+ local file, source
+ if filename == 'stdin'
+ file = io.read("*a")
+ files.spoof('stdin', file)
+ source = Source('stdin', 1, #file)
+ elseif filename\match("%.nom$")
+ file = files.read(filename)
+ if not file
+ error("File does not exist: #{filename}", 0)
+ source = Source(filename, 1, #file)
+ else return nil
+ source = Source(filename,1,#file)
+ return file, source
+
+ run_file = (filename, lua_handler=nil)->
+ file, source = get_file_and_source(filename)
+ return nil unless file
+ tree = nomsu\parse(file, source)
+ if tree
+ if tree.type != "FileChunks"
+ tree = {tree}
+ -- Each chunk's compilation is affected by the code in the previous chunks
+ -- (typically), so each chunk needs to compile and run before the next one
+ -- compiles.
+ for chunk in *tree
+ lua = nomsu\compile(chunk)\as_statements("return ")
+ lua\declare_locals!
+ lua\prepend "-- File: #{source.filename\gsub("\n.*", "...")}\n"
+ if lua_handler then lua_handler(tostring(lua))
+ nomsu\run_lua(lua)
+
parse_errs = {}
- for arg in *args.inputs
- for filename in files.walk(arg)
- local file, source
- if filename == 'stdin'
- file = io.read("*a")
- files.spoof('stdin', file)
- source = Source('stdin', 1, #file)
- elseif filename\match("%.nom$")
- file = files.read(filename)
- if not file
- error("File does not exist: #{filename}", 0)
- source = Source(filename, 1, #file)
- else continue
- source = Source(filename,1,#file)
-
- output = if args.compile then io.open(filename\gsub("%.nom$", ".lua"), "w") else nil
-
- if args.syntax
- -- Check syntax:
- ok,err = pcall nomsu.parse, nomsu, file, source
- if not ok
- table.insert parse_errs, err
- elseif print_file
- print_file\write("Parse succeeded: #{filename}\n")
- print_file\flush!
- continue
-
- tree = nomsu\parse(file, source)
-
- if args.format
- -- Auto-format
- formatted = tree and tostring(nomsu\tree_to_nomsu(tree)) or ""
- if print_file
- print_file\write(formatted, "\n")
- print_file\flush!
- continue
-
- if tree
- if tree.type == "FileChunks"
- -- Each chunk's compilation is affected by the code in the previous chunks
- -- (typically), so each chunk needs to compile and run before the next one
- -- compiles.
- for chunk in *tree
- lua = nomsu\compile(chunk)\as_statements("return ")
- lua\declare_locals!
- lua\prepend "-- File: #{source.filename\gsub("\n.*", "...")}\n"
- if args.compile
- output\write(tostring(lua), "\n")
- if args.verbose
- print(tostring(lua))
- nomsu\run_lua(lua)
- else
- lua = nomsu\compile(tree)\as_statements("return ")
- lua\declare_locals!
- lua\prepend "-- File: #{source.filename\gsub("\n.*", "...")}\n"
- if args.compile
- output\write(tostring(lua), "\n")
- if args.verbose
- print(tostring(lua))
- nomsu\run_lua(lua)
+ for f in *file_queue
+ for filename in files.walk(f)
+ if args.check_syntax
+ -- Check syntax
+ file, source = get_file_and_source(filename)
+ continue unless file
+ nomsu\parse(file, source)
+ print("Parse succeeded: #{filename}")
+
if args.compile
+ -- Compile .nom files into .lua
+ output = if filename == 'stdin' then io.output()
+ else io.open(filename\gsub("%.nom$", ".lua"), "w")
+ run_file filename, (lua)->
+ output\write(tostring(lua), "\n")
+ if args.verbose then print(tostring(lua))
print ("Compiled %-25s -> %s")\format(filename, filename\gsub("%.nom$", ".lua"))
output\close!
- if #parse_errs > 0
- io.stderr\write table.concat(parse_errs, "\n\n")
- io.stderr\flush!
- os.exit(EXIT_FAILURE)
- elseif args.syntax
- os.exit(EXIT_SUCCESS)
+ if not args.check_syntax and not args.compile
+ -- Just run the file
+ run_file filename, (args.verbose and print or nil)
- if args.interactive
- -- REPL
+ if #file_queue == 0
+ -- Run in interactive mode (REPL)
nomsu\run [[
use "core"
use "lib/consolecolor.nom"
diff --git a/nomsu_compiler.lua b/nomsu_compiler.lua
index 4f650da..98f3791 100644
--- a/nomsu_compiler.lua
+++ b/nomsu_compiler.lua
@@ -150,7 +150,7 @@ local NomsuCompiler = setmetatable({ }, {
end
})
do
- NomsuCompiler.NOMSU_COMPILER_VERSION = 2
+ NomsuCompiler.NOMSU_COMPILER_VERSION = 3
NomsuCompiler.NOMSU_SYNTAX_VERSION = Parser.version
NomsuCompiler._ENV = NomsuCompiler
NomsuCompiler.nomsu = NomsuCompiler
diff --git a/nomsu_compiler.moon b/nomsu_compiler.moon
index bb31829..8e4dee7 100644
--- a/nomsu_compiler.moon
+++ b/nomsu_compiler.moon
@@ -92,7 +92,7 @@ dict = (t)-> setmetatable(t, _dict_mt)
MAX_LINE = 80 -- For beautification purposes, try not to make lines much longer than this value
NomsuCompiler = setmetatable({}, {__index: (k)=> if _self = rawget(@, "self") then _self[k] else nil})
with NomsuCompiler
- .NOMSU_COMPILER_VERSION = 2
+ .NOMSU_COMPILER_VERSION = 3
.NOMSU_SYNTAX_VERSION = Parser.version
._ENV = NomsuCompiler
.nomsu = NomsuCompiler