aboutsummaryrefslogtreecommitdiff
path: root/nomsu.moon
diff options
context:
space:
mode:
authorBruce Hill <bitbucket@bruce-hill.com>2018-04-28 17:08:28 -0700
committerBruce Hill <bitbucket@bruce-hill.com>2018-04-28 17:08:44 -0700
commitdf9a82a9711faf20c705d806fceab5c154b37f4c (patch)
tree7f873b6397772b65ef1c47a8e4db924ed17994af /nomsu.moon
parentd13a945b5f8924c1416ea2bd72212efdb3bebc20 (diff)
Overhaul of command-line API. It's a bit cleaner now.
Diffstat (limited to 'nomsu.moon')
-rwxr-xr-xnomsu.moon122
1 files changed, 84 insertions, 38 deletions
diff --git a/nomsu.moon b/nomsu.moon
index cf89666..c38417a 100755
--- a/nomsu.moon
+++ b/nomsu.moon
@@ -49,6 +49,15 @@ FILE_CACHE = setmetatable {}, {
return contents
}
+iterate_single = (item, prev) -> if item == prev then nil else item
+all_files = (path)->
+ -- Sanitize path
+ if path\match("%.nom$") or path\match("%.lua$")
+ return iterate_single, path
+ -- TODO: improve sanitization
+ path = path\gsub("\\","\\\\")\gsub("`","")\gsub('"','\\"')\gsub("$","")
+ return io.popen("find \""..path.."\" -type f -name \"*.nom\"")\lines!
+
line_counter = re.compile([[
lines <- {| line (%nl line)* |}
line <- {} (!%nl .)*
@@ -321,9 +330,9 @@ class NomsuCompiler
compile_fn(lua)
return @run_lua(lua)
- run_file: (path, compile_fn=nil)=>
+ run_file: (filename, compile_fn=nil)=>
ret = nil
- for filename in io.popen("find "..path.." -type f")\lines!
+ for filename in all_files(filename)
if filename\match("%.lua$")
file = assert(FILE_CACHE[filename], "Could not find file: #{filename}")
ret = @run_lua(Lua(Source(filename), file))
@@ -338,7 +347,6 @@ class NomsuCompiler
if not file
error("File does not exist: #{filename}", 0)
ret = @run(Nomsu(Source(filename), file), compile_fn)
- continue
else
error("Invalid filetype for #{filename}", 0)
return ret
@@ -346,13 +354,19 @@ class NomsuCompiler
use_file: (filename)=>
loaded = @environment.LOADED
if not loaded[filename]
- for i,f in ipairs @use_stack
- if f == filename
- loop = [@use_stack[j] for j=i,#@use_stack]
- insert loop, filename
- error("Circular import, this loops forever: #{concat loop, " -> "}")
- insert @use_stack, filename
- loaded[filename] = @run_file(filename) or true
+ ret = nil
+ for filename in all_files(filename)
+ if not loaded[filename]
+ for i,f in ipairs @use_stack
+ if f == filename
+ loop = [@use_stack[j] for j=i,#@use_stack]
+ insert loop, filename
+ error("Circular import, this loops forever: #{concat loop, " -> "}")
+ insert @use_stack, filename
+ loaded[filename] = @run_file(filename) or true
+ ret = loaded[filename]
+ remove @use_stack
+ loaded[filename] = ret
return loaded[filename]
run_lua: (lua)=>
@@ -638,26 +652,43 @@ class NomsuCompiler
@define_action "run file %filename", get_line_no!, (_filename)->
return nomsu\run_file(_filename)
- @define_compile_action "use %filename", get_line_no!, (_filename)=>
- filename = nomsu\tree_to_value(_filename)
- nomsu\use_file(filename)
- return Lua.Value(@source, "nomsu:use_file(#{repr filename})")
+ @define_compile_action "use %path", get_line_no!, (_path)=>
+ path = nomsu\tree_to_value(_path)
+ nomsu\use_file(path)
+ return Lua(@source, "nomsu:use_file(#{repr path});")
-- Only run this code if this file was run directly with command line arguments, and not require()'d:
if arg and debug_getinfo(2).func != require
export colors
colors = require 'consolecolors'
parser = re.compile([[
- args <- {| {:flags: flags? :} ({:input: input :} ";" ("-o;"{:output: output :} ";")?)? (";")? |} !.
+ args <- {| {:flags: flags? :} (input ";" (output / print_file)*)? (";")? |} !.
flags <- (({| ({flag} ";")* |}) -> set)
- flag <- "-c" / "-i" / "-p" / "-O" / "--help" / "-h" / "-v"
- input <- "-" / [^;]+
- output <- "-" / [^;]+
+ flag <- "-i" / "-O" / "-f" / "--help" / "-h" / "-s" / "-p"
+ input <- {:input: file :}
+ output <- "-o;" {:output: file :}
+ print_file <- "-p;" {:print_file: file :}
+ file <- "-" / [^;]+
]], {:set})
args = concat(arg, ";")..";"
args = parser\match(args) or {}
if not args or not args.flags or args.flags["--help"] or args.flags["-h"]
- print "Usage: lua nomsu.lua [-c] [-i] [-p] [-O] [--help] [input [-o output]]"
+ print [=[
+Nomsu Compiler
+
+Usage: (lua nomsu.lua | moon nomsu.moon) [-i] [-O] [-f] [-s] [--help] [input [-o output] [-p print_file]]
+
+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)
+ -f Auto-format the given Nomsu file and print the result.
+ -s Check the program for syntax errors.
+ -v Verbose
+ -h/--help Print this message.
+ <input> Input file can be "-" to use stdin.
+ -o <file> Output the compiled Lua file to the given file (use "-" to output to stdout; if outputting to stdout and -p is not specified, -p will default to /dev/null)
+ -p <file> Print to the specified file instead of stdout.
+]=]
os.exit!
nomsu = NomsuCompiler!
@@ -700,32 +731,47 @@ if arg and debug_getinfo(2).func != require
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
- -- Read a file or stdin and output either the printouts or the compiled lua
- if args.flags["-c"] and not args.output
- args.output = args.input\gsub("%.nom", ".lua")
compile_fn = nil
- if args.flags["-p"]
- nomsu.environment.print = ->
- compile_fn = (code)->
- io.output!\write("local IMMEDIATE = true;\n"..tostring(code))
- elseif args.output
- compile_fn = (code)->
- io.open(args.output, 'w')\write("local IMMEDIATE = true;\n"..tostring(code))
-
- if args.input\match(".*%.lua")
+ 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
- if args.input == "-"
- nomsu\run(io.read('a'), compile_fn)
- else nomsu\run_file(args.input, compile_fn)
-
- if args.flags["-p"]
- nomsu.environment.print = print
+ 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 args.flags["-i"]
+ if not args.input or args.flags["-i"]
-- REPL
nomsu\run('use "core"')
while true