diff --git a/Makefile b/Makefile index 921f40e..cf25fca 100644 --- a/Makefile +++ b/Makefile @@ -6,11 +6,7 @@ LUA= lua LUA_BIN= $(shell which $(LUA)) -PREFIX=/usr/local -NOMSU_BIN_DIR= $(PREFIX)/bin -NOMSU_LIB_DIR= $(PREFIX)/lib/nomsu -NOMSU_SHARE_DIR= $(PREFIX)/share/nomsu - +PREFIX= # ========= You shouldn't need to mess with any of these variables below ================ MOON_FILES= code_obj.moon error_handling.moon files.moon nomsu.moon nomsu_compiler.moon nomsu_tree.moon parser.moon @@ -36,25 +32,11 @@ test: build optimize %.lua: %.nom @./nomsu_latest -c $< -.PHONY: check_header -check_header: $(PEG_FILE) nomsu.lua $(CORE_NOM_FILES) $(LIB_NOM_FILES) - @if [ -f nomsu_latest ]; then \ - NOMSU_HEADER="#!$(LUA_BIN)\\nlocal NOMSU_VERSION, NOMSU_LIB, NOMSU_SHARE = [[`$(GET_VERSION)`]], [[$(NOMSU_LIB_DIR)]], [[$(NOMSU_SHARE_DIR)]]"; \ - if [ "`head -n 3 nomsu_latest 2>/dev/null`" != "`echo $$NOMSU_HEADER`" ]; then \ - rm -f nomsu_latest; \ - fi; \ - fi; +.DELETE_ON_ERROR: version +version: $(LUA_FILES) $(CORE_NOM_FILES) $(LIB_NOM_FILES) $(PEG_FILE) + @$(LUA_BIN) nomsu.lua --version > version || exit -nomsu_latest: nomsu.lua - @rm -f nomsu_latest - @NOMSU_HEADER="#!$(LUA_BIN)\\nlocal NOMSU_VERSION, NOMSU_LIB, NOMSU_SHARE = [[`$(GET_VERSION)`]], [[$(NOMSU_LIB_DIR)]], [[$(NOMSU_SHARE_DIR)]]"; \ - echo $$NOMSU_HEADER | cat - nomsu.lua > nomsu_latest - @chmod +x nomsu_latest - @mv -f nomsu_latest nomsu`$(GET_VERSION)` - @ln -s nomsu`$(GET_VERSION)` nomsu_latest - @echo "\033[1mBuilt nomsu binary\033[0m" - -build: $(LUA_FILES) check_header nomsu_latest +build: $(LUA_FILES) .PHONY: optimize optimize: build $(CORE_LUA_FILES) $(LIB_LUA_FILES) @@ -62,44 +44,71 @@ optimize: build $(CORE_LUA_FILES) $(LIB_LUA_FILES) .PHONY: clean clean: @echo "\033[1mDeleting...\033[0m" - @rm -rvf nomsu`$(GET_VERSION)` nomsu_latest core/*.lua lib/*.lua + @rm -rvf version core/*.lua lib/*.lua .PHONY: install -install: all - @echo "\033[1mNomsu will be installed to:\033[0m" - @echo " $(NOMSU_BIN_DIR)" - @echo " $(NOMSU_LIB_DIR)" - @echo " $(NOMSU_SHARE_DIR)" - @read -p $$'\033[1mis this okay? [Y/n]\033[0m ' ans; \ - if [[ ! $$ans =~ ^[Nn] ]]; then \ - mkdir -pv $(NOMSU_BIN_DIR) $(NOMSU_LIB_DIR)/`$(GET_VERSION)` $(NOMSU_SHARE_DIR)/`$(GET_VERSION)` \ - && cp -v nomsu nomsu`$(GET_VERSION)` $(NOMSU_BIN_DIR) \ - && cp -rv $(LUA_FILES) $(PEG_FILE) core lib tests $(NOMSU_SHARE_DIR)/`$(GET_VERSION)`; \ - fi +install: build version optimize + @prefix="$(PREFIX)"; \ + if [[ ! $$prefix ]]; then \ + read -p $$'\033[1mWhere do you want to install Nomsu? (default: /usr/local) \033[0m' prefix; \ + fi; \ + if [[ $$prefix != "`realpath $$prefix`" ]]; then \ + echo $$'\033[1;31mWarning: '$$prefix$$' is not an absolute path. This may cause problems.\033[0m'; \ + read -p $$'\033[1mWould you rather use '`realpath $$prefix`$$' instead? (recommended)[Y/n]\033[0m ' use_real; \ + if [[ ! $$use_real =~ ^[Nn] ]]; then \ + prefix="`realpath $$prefix`"; \ + fi; \ + fi; \ + version="`cat version`"; \ + echo "#!$(LUA_BIN)\\nlocal NOMSU_VERSION, NOMSU_PREFIX = [[$$version]], [[$$prefix]]" | cat - nomsu.lua > nomsu$$version; \ + mkdir -pv $$prefix/bin $$prefix/lib/nomsu/$$version $$prefix/share/nomsu/$$version \ + && cp -v nomsu nomsu$$version $$prefix/bin \ + && cp -rv $(LUA_FILES) $(PEG_FILE) core lib tests $$prefix/share/nomsu/$$version; .PHONY: uninstall -uninstall: all - @echo "\033[1mNomsu will be uninstalled from:\033[0m" - @echo " $(NOMSU_BIN_DIR)" - @echo " $(NOMSU_LIB_DIR)" - @echo " $(NOMSU_SHARE_DIR)" - @read -p $$'\033[1mis this okay? [Y/n]\033[0m ' ans; \ - if [[ ! $$ans =~ ^[Nn] ]]; then \ - echo "\033[1mDeleting...\033[0m"; \ - rm -rvf $(NOMSU_LIB_DIR)/`$(GET_VERSION)` $(NOMSU_SHARE_DIR)/`$(GET_VERSION)` $(NOMSU_BIN_DIR)/nomsu`$(GET_VERSION)`; \ - if [ "`ls $(NOMSU_BIN_DIR)/nomsu* 2> /dev/null`" == "nomsu" ]; then \ - rm -vf $(NOMSU_BIN_DIR)/nomsu; \ - else \ - if [ "`ls $(NOMSU_BIN_DIR)/nomsu* 2> /dev/null`" != "" ]; then \ - read -p $$'\033[1mIt looks like there are other versions of Nomsu installed. Is it okay to leave the "nomsu" cross-version launcher in place? (recommended) [Y/n]\033[0m ' ans; \ - if [[ $$ans =~ ^[Nn] ]]; then \ - echo "\033[1mDeleting...\033[0m"; \ - rm -vf $(NOMSU_BIN_DIR)/nomsu; \ - fi; \ +uninstall: version + @prefix="$(PREFIX)"; \ + if [[ ! $$prefix ]]; then \ + read -p $$'\033[1mWhere do you want to uninstall Nomsu from? (default: /usr/local) \033[0m' prefix; \ + fi; \ + echo "\033[1mNomsu will be uninstalled from:\033[0m"; \ + echo " $$prefix/bin"; \ + echo " $$prefix/lib"; \ + echo " $$prefix/share"; \ + read -p $$'\033[1mis this okay? [Y/n]\033[0m ' ans; \ + if [[ $$ans =~ ^[Nn] ]]; then exit; fi; \ + echo "\033[1mDeleting...\033[0m"; \ + version="`cat version`"; \ + rm -rvf $$prefix/lib/nomsu/$$version $$prefix/share/nomsu/$$version $$prefix/bin/nomsu$$version; \ + if [[ "`find -E $$prefix/bin -type f -regex '.*/nomsu[0-9.]+\$$'`" == "" ]]; then \ + rm -vf $$prefix/bin/nomsu; \ + else \ + if [ -f $$prefix/bin/nomsu ]; then \ + read -p $$'\033[1mIt looks like there are other versions of Nomsu installed. Is it okay to leave the "nomsu" cross-version launcher in place? (recommended) [Y/n]\033[0m ' ans; \ + if [[ $$ans =~ ^[Nn] ]]; then \ + echo "\033[1mDeleting...\033[0m"; \ + rm -vf $$prefix/bin/nomsu; \ fi; \ fi; \ - if [ "`ls $(NOMSU_LIB_DIR) 2>/dev/null`" == "" ]; then rm -rvf $(NOMSU_LIB_DIR); fi;\ - if [ "`ls $(NOMSU_SHARE_DIR) 2>/dev/null`" == "" ]; then rm -rvf $(NOMSU_SHARE_DIR); fi;\ - fi + fi; \ + if [ "`ls $$prefix/lib/nomsu 2>/dev/null`" == "" ]; then rm -rvf $$prefix/lib/nomsu; fi;\ + if [ "`ls $$prefix/share/nomsu 2>/dev/null`" == "" ]; then rm -rvf $$prefix/share/nomsu; fi;\ + echo $$'\033[1mDone.\033[0m'; + +.PHONY: uninstall-all +uninstall-all: + @prefix="$(PREFIX)"; \ + if [[ ! $$prefix ]]; then \ + read -p $$'\033[1mWhere do you want to uninstall Nomsu from? (default: /usr/local) \033[0m' prefix; \ + fi; \ + echo "\033[1mEvery version of Nomsu will be uninstalled from:\033[0m"; \ + echo " $$prefix/bin"; \ + echo " $$prefix/lib"; \ + echo " $$prefix/share"; \ + read -p $$'\033[1mis this okay? [Y/n]\033[0m ' ans; \ + if [[ ! $$ans =~ ^[Nn] ]]; then exit; fi; \ + echo "\033[1mDeleting...\033[0m"; \ + rm -rvf $$prefix/lib/nomsu $$prefix/share/nomsu $$prefix/bin/nomsu*;\ + echo $$'\033[1mDone.\033[0m'; # eof diff --git a/core/metaprogramming.nom b/core/metaprogramming.nom index f9cb4e9..d22a457 100644 --- a/core/metaprogramming.nom +++ b/core/metaprogramming.nom @@ -206,7 +206,7 @@ compile [%lua <-write %code, to %lua write %code] to: Lua "\(%lua as lua expr):a compile [quote %s] to Lua value ".." - ('"'..\(%s as lua expr):gsub("\\\\", "\\\\\\\\"):gsub("\n","\\\\n"):gsub('"', '\\\\"')..'"') + repr(\(%s as lua expr)) compile [type of %obj] to: Lua value "type(\(%obj as lua expr))" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/files.lua b/files.lua index 9265056..130a880 100644 --- a/files.lua +++ b/files.lua @@ -60,7 +60,7 @@ if ok then end elseif file_type == 'directory' then for subfile in lfs.dir(filename) do - if not (subfile == "." or subfile == "..") then + if not (subfile == "." or subfile == ".." or not subfile:match("%.nom$")) then browse(filename .. "/" .. subfile) end end diff --git a/files.moon b/files.moon index 629bc9c..e873c1d 100644 --- a/files.moon +++ b/files.moon @@ -39,7 +39,8 @@ if ok return true elseif file_type == 'directory' for subfile in lfs.dir(filename) - unless subfile == "." or subfile == ".." + -- 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' diff --git a/lib/consolecolor.nom b/lib/consolecolor.nom index 3a53849..8184b59 100644 --- a/lib/consolecolor.nom +++ b/lib/consolecolor.nom @@ -10,10 +10,8 @@ use "core" for %name = %colornum in %colors with {%escapecode: "\27[\(%colornum)m"} - lua> ".." - nomsu.COMPILE_ACTIONS[\%name] = function(nomsu, tree) - return LuaCode.Value(tree.source, repr(\%escapecode)) - end - nomsu.COMPILE_ACTIONS[\%name.." %"] = function(nomsu, tree, text) - return LuaCode.Value(tree.source, repr(\%escapecode), "..", nomsu:compile(text), "..'\\\\27[0m'") - end + run ".." + compile [\%name] to: Lua value (quote \(quote %escapecode)) + compile [\%name %text] to + Lua value ".." + (\\(quote \(quote %escapecode))..\\(%text as lua expr)..\(quote "\27[0m")) diff --git a/nomsu.lua b/nomsu.lua index de1885f..6a0ea6d 100644 --- a/nomsu.lua +++ b/nomsu.lua @@ -117,7 +117,8 @@ local files = require("files") local nomsu = NomsuCompiler nomsu.arg = args.nomsu_args if args.version then - nomsu:run('use "core"\nsay (Nomsu version)') + nomsu:run([[use "core" +say (Nomsu version)]]) os.exit(EXIT_SUCCESS) end FILE_CACHE = setmetatable({ }, { @@ -192,54 +193,94 @@ run = function() end return true end - if args.compile or args.verbose then - nomsu.on_compile = function(code, from_file) - if not (to_run[from_file]) then - return - end - if args.verbose then - io.write(tostring(code), "\n") - end - if args.compile and from_file:match("%.nom$") then - local output_filename = from_file:gsub("%.nom$", ".lua") - local output_file = io.open(output_filename, 'w') - output_file:write(tostring(code)) - output_file:flush() - print(("Compiled %-25s -> %s"):format(from_file, output_filename)) - return output_file:close() - end - end - end local parse_errs = { } - for _index_0 = 1, #input_files do - local filename = input_files[_index_0] - if args.syntax then - local file_contents = io.open(filename):read('*a') - 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 - print_file:write("Parse succeeded: " .. tostring(filename) .. "\n") - print_file:flush() + 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 + local _continue_0 = false + repeat + local file, source + if filename == STDIN then + file = io.input():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 + _continue_0 = true + break + 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 + 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 + if args.verbose then + print(tostring(lua)) + end + nomsu:run_lua(lua) + end + end + if args.compile then + print(("Compiled %-25s -> %s"):format(filename, filename:gsub("%.nom$", ".lua"))) + output:close() + end + _continue_0 = true + until true + if not _continue_0 then + break end - elseif args.format then - local file = files.read(filename) - if not file then - error("File does not exist: " .. tostring(filename), 0) - end - local tree = nomsu:parse(file, Source(filename, 1, #file)) - local formatted = tostring(nomsu:tree_to_nomsu(tree)) - if print_file then - print_file:write(formatted, "\n") - print_file:flush() - end - elseif filename == STDIN then - local file = io.input():read("*a") - files.spoof('stdin', file) - nomsu:run(file, Source('stdin', 1, #file)) - else - nomsu:run_file(filename) end end if #parse_errs > 0 then diff --git a/nomsu.moon b/nomsu.moon index d66825d..b3f806f 100755 --- a/nomsu.moon +++ b/nomsu.moon @@ -70,7 +70,9 @@ nomsu = NomsuCompiler nomsu.arg = args.nomsu_args if args.version - nomsu\run 'use "core"\nsay (Nomsu version)' + nomsu\run [[ +use "core" +say (Nomsu version)]] os.exit(EXIT_SUCCESS) export FILE_CACHE @@ -125,46 +127,70 @@ run = -> return false if to_run[f] return true - if args.compile or args.verbose - nomsu.on_compile = (code, from_file)-> - return unless to_run[from_file] - if args.verbose - io.write(tostring(code), "\n") - if args.compile and from_file\match("%.nom$") - output_filename = from_file\gsub("%.nom$", ".lua") - output_file = io.open(output_filename, 'w') - output_file\write(tostring(code)) - output_file\flush! - print ("Compiled %-25s -> %s")\format(from_file, output_filename) - output_file\close! - parse_errs = {} - for filename in *input_files - if args.syntax - -- Check syntax: - file_contents = io.open(filename)\read('*a') - ok,err = pcall nomsu.parse, nomsu, file_contents, Source(filename, 1, #file_contents) - if not ok - table.insert parse_errs, err - elseif print_file - print_file\write("Parse succeeded: #{filename}\n") - print_file\flush! - elseif args.format - -- Auto-format - file = files.read(filename) - if not file - error("File does not exist: #{filename}", 0) - tree = nomsu\parse(file, Source(filename,1,#file)) - formatted = tostring(nomsu\tree_to_nomsu(tree)) - if print_file - print_file\write(formatted, "\n") - print_file\flush! - elseif filename == STDIN - file = io.input!\read("*a") - files.spoof('stdin', file) - nomsu\run(file, Source('stdin',1,#file)) - else - nomsu\run_file(filename) + for arg in *args.inputs + for filename in files.walk(arg) + local file, source + if filename == STDIN + file = io.input!\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) + if args.compile + 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") diff --git a/nomsu_compiler.lua b/nomsu_compiler.lua index 42cdb17..200f0f7 100644 --- a/nomsu_compiler.lua +++ b/nomsu_compiler.lua @@ -365,12 +365,13 @@ do return add_lua_bits(self, LuaCode.Value(tree.source), _code) end, ["use %"] = function(self, tree, _path) - if not (_path.type == 'Text' and #_path == 1 and type(_path[1]) == 'string') then - return LuaCode(tree.source, "nomsu:run_file(" .. tostring(self:compile(_path)) .. ");") + if _path.type == 'Text' and #_path == 1 and type(_path[1]) == 'string' then + local path = _path[1] + for f in files.walk(path) do + self:run_file(f) + end end - local path = _path[1] - self:run_file(path) - return LuaCode(tree.source, "nomsu:run_file(" .. tostring(repr(path)) .. ");") + return LuaCode(tree.source, "for f in files.walk(", self:compile(_path), ") do nomsu:run_file(f) end") end }, { __index = function(self, stub) @@ -407,17 +408,11 @@ do insert(all_lua, tostring(lua)) ret = self:run_lua(lua) end - if self.on_compile then - self.on_compile(concat(all_lua, "\n"), source.filename) - end return ret else - local lua = self:compile(tree, compile_actions):as_statements("return ") + local lua = self:compile(tree):as_statements("return ") lua:declare_locals() lua:prepend("-- File: " .. tostring(source.filename:gsub("\n.*", "...")) .. "\n") - if self.on_compile then - self.on_compile(lua, source.filename) - end return self:run_lua(lua) end end @@ -426,67 +421,51 @@ do if self.LOADED[filename] then return self.LOADED[filename] end - local ret = nil - for filename in files.walk(filename) do - local _continue_0 = false - repeat + for i, running in ipairs(_running_files) do + if running == filename then + local loop do - ret = self.LOADED[filename] - if ret then - _continue_0 = true - break + local _accum_0 = { } + local _len_0 = 1 + for j = i, #_running_files do + _accum_0[_len_0] = _running_files[j] + _len_0 = _len_0 + 1 end + loop = _accum_0 end - for i, running in ipairs(_running_files) do - if running == filename then - local loop - do - local _accum_0 = { } - local _len_0 = 1 - for j = i, #_running_files do - _accum_0[_len_0] = _running_files[j] - _len_0 = _len_0 + 1 - end - loop = _accum_0 - end - insert(loop, filename) - error("Circular import, this loops forever: " .. tostring(concat(loop, " -> ")) .. "...") - end - end - insert(_running_files, filename) - if match(filename, "%.lua$") then - local file = assert(files.read(filename), "Could not find file: " .. tostring(filename)) - ret = self:run_lua(file, Source(filename, 1, #file)) - elseif match(filename, "%.nom$") or match(filename, "^/dev/fd/[012]$") then - local ran_lua - if self.can_optimize(filename) then - local lua_filename = gsub(filename, "%.nom$", ".lua") - do - local file = files.read(lua_filename) - if file then - ret = self:run_lua(file, Source(lua_filename, 1, #file)) - ran_lua = true - end - end - end - if not (ran_lua) then - local file = file or files.read(filename) - if not file then - error("File does not exist: " .. tostring(filename), 0) - end - ret = self:run(file, Source(filename, 1, #file)) - end - else - error("Invalid filetype for " .. tostring(filename), 0) - end - self.LOADED[filename] = ret or true - remove(_running_files) - _continue_0 = true - until true - if not _continue_0 then - break + insert(loop, filename) + error("Circular import, this loops forever: " .. tostring(concat(loop, " -> ")) .. "...") end end + insert(_running_files, filename) + local ret = nil + if match(filename, "%.lua$") then + local file = assert(files.read(filename), "Could not find file: " .. tostring(filename)) + ret = self:run_lua(file, Source(filename, 1, #file)) + elseif match(filename, "%.nom$") or match(filename, "^/dev/fd/[012]$") then + local ran_lua + if self.can_optimize(filename) then + local lua_filename = gsub(filename, "%.nom$", ".lua") + do + local file = files.read(lua_filename) + if file then + ret = self:run_lua(file, Source(lua_filename, 1, #file)) + ran_lua = true + end + end + end + if not (ran_lua) then + local file = files.read(filename) + if not file then + error("File does not exist: " .. tostring(filename), 0) + end + ret = self:run(file, Source(filename, 1, #file)) + end + else + error("Invalid filetype for " .. tostring(filename), 0) + end + self.LOADED[filename] = ret or true + remove(_running_files) self.LOADED[filename] = ret or true return ret end diff --git a/nomsu_compiler.moon b/nomsu_compiler.moon index e16af76..99cfce7 100644 --- a/nomsu_compiler.moon +++ b/nomsu_compiler.moon @@ -246,11 +246,11 @@ with NomsuCompiler return add_lua_bits(@, LuaCode.Value(tree.source), _code) ["use %"]: (tree, _path)=> - unless _path.type == 'Text' and #_path == 1 and type(_path[1]) == 'string' - return LuaCode(tree.source, "nomsu:run_file(#{@compile(_path)});") - path = _path[1] - @run_file(path) - return LuaCode(tree.source, "nomsu:run_file(#{repr path});") + if _path.type == 'Text' and #_path == 1 and type(_path[1]) == 'string' + path = _path[1] + for f in files.walk(path) + @run_file(f) + return LuaCode(tree.source, "for f in files.walk(", @compile(_path), ") do nomsu:run_file(f) end") }, { __index: (stub)=> if math_expression\match(stub) @@ -275,52 +275,45 @@ with NomsuCompiler lua\prepend "-- File: #{source.filename\gsub("\n.*", "...")}\n" insert all_lua, tostring(lua) ret = @run_lua(lua) - if @on_compile - self.on_compile(concat(all_lua, "\n"), source.filename) return ret else - lua = @compile(tree, compile_actions)\as_statements("return ") + lua = @compile(tree)\as_statements("return ") lua\declare_locals! lua\prepend "-- File: #{source.filename\gsub("\n.*", "...")}\n" - if @on_compile - self.on_compile(lua, source.filename) return @run_lua(lua) _running_files = {} -- For detecting circular imports .run_file = (filename)=> if @LOADED[filename] return @LOADED[filename] + -- Check for circular import + -- TODO: optimize? + for i,running in ipairs _running_files + if running == filename + loop = [_running_files[j] for j=i,#_running_files] + insert loop, filename + error("Circular import, this loops forever: #{concat loop, " -> "}...") + + insert _running_files, filename ret = nil - for filename in files.walk(filename) - if ret = @LOADED[filename] - continue - - -- Check for circular import - for i,running in ipairs _running_files - if running == filename - loop = [_running_files[j] for j=i,#_running_files] - insert loop, filename - error("Circular import, this loops forever: #{concat loop, " -> "}...") - - insert _running_files, filename - if match(filename, "%.lua$") - file = assert(files.read(filename), "Could not find file: #{filename}") - ret = @run_lua file, Source(filename, 1, #file) - elseif match(filename, "%.nom$") or match(filename, "^/dev/fd/[012]$") - ran_lua = if @.can_optimize(filename) -- Look for precompiled version - lua_filename = gsub(filename, "%.nom$", ".lua") - if file = files.read(lua_filename) - ret = @run_lua file, Source(lua_filename, 1, #file) - true - unless ran_lua - file = file or files.read(filename) - if not file - error("File does not exist: #{filename}", 0) - ret = @run file, Source(filename,1,#file) - else - error("Invalid filetype for #{filename}", 0) - @LOADED[filename] = ret or true - remove _running_files + if match(filename, "%.lua$") + file = assert(files.read(filename), "Could not find file: #{filename}") + ret = @run_lua file, Source(filename, 1, #file) + elseif match(filename, "%.nom$") or match(filename, "^/dev/fd/[012]$") + ran_lua = if @.can_optimize(filename) -- Look for precompiled version + lua_filename = gsub(filename, "%.nom$", ".lua") + if file = files.read(lua_filename) + ret = @run_lua file, Source(lua_filename, 1, #file) + true + unless ran_lua + file = files.read(filename) + if not file + error("File does not exist: #{filename}", 0) + ret = @run file, Source(filename,1,#file) + else + error("Invalid filetype for #{filename}", 0) + @LOADED[filename] = ret or true + remove _running_files @LOADED[filename] = ret or true return ret