diff options
Diffstat (limited to 'nomsu_environment.lua')
| -rw-r--r-- | nomsu_environment.lua | 325 |
1 files changed, 325 insertions, 0 deletions
diff --git a/nomsu_environment.lua b/nomsu_environment.lua new file mode 100644 index 0000000..3bb54b1 --- /dev/null +++ b/nomsu_environment.lua @@ -0,0 +1,325 @@ +local NomsuCode, LuaCode, Source +do + local _obj_0 = require("code_obj") + NomsuCode, LuaCode, Source = _obj_0.NomsuCode, _obj_0.LuaCode, _obj_0.Source +end +local Importer, import_to_1_from, _1_forked +do + local _obj_0 = require('importer') + Importer, import_to_1_from, _1_forked = _obj_0.Importer, _obj_0.import_to_1_from, _obj_0._1_forked +end +local List, Dict, Text +do + local _obj_0 = require('containers') + List, Dict, Text = _obj_0.List, _obj_0.Dict, _obj_0.Text +end +local SyntaxTree = require("syntax_tree") +local Files = require("files") +local make_parser = require("parser") +local pretty_error = require("pretty_errors") +local make_tree +make_tree = function(tree, userdata) + tree.source = Source(userdata.filename, tree.start, tree.stop) + tree.start, tree.stop = nil, nil + tree = SyntaxTree(tree) + return tree +end +local Parsers = { } +local max_parser_version = 0 +for version = 1, 999 do + local peg_file + if package.nomsupath then + for path in package.nomsupath:gmatch("[^;]+") do + peg_file = io.open(path .. "/nomsu." .. tostring(version) .. ".peg") + if peg_file then + break + end + end + else + peg_file = io.open("nomsu." .. tostring(version) .. ".peg") + end + if not (peg_file) then + break + end + max_parser_version = version + local peg_contents = peg_file:read('*a') + peg_file:close() + Parsers[version] = make_parser(peg_contents, make_tree) +end +local tree_to_nomsu, tree_to_inline_nomsu +do + local _obj_0 = require("nomsu_decompiler") + tree_to_nomsu, tree_to_inline_nomsu = _obj_0.tree_to_nomsu, _obj_0.tree_to_inline_nomsu +end +local nomsu_environment = Importer({ + NOMSU_COMPILER_VERSION = 12, + NOMSU_SYNTAX_VERSION = max_parser_version, + next = next, + unpack = unpack or table.unpack, + setmetatable = setmetatable, + coroutine = coroutine, + rawequal = rawequal, + getmetatable = getmetatable, + pcall = pcall, + error = error, + package = package, + os = os, + require = require, + tonumber = tonumber, + tostring = tostring, + string = string, + xpcall = xpcall, + module = module, + print = print, + loadfile = loadfile, + rawset = rawset, + _VERSION = _VERSION, + collectgarbage = collectgarbage, + rawget = rawget, + rawlen = rawlen, + table = table, + assert = assert, + dofile = dofile, + loadstring = loadstring, + lua_type_of = type, + select = select, + math = math, + io = io, + load = load, + pairs = pairs, + ipairs = ipairs, + jit = jit, + _VERSION = _VERSION, + bit = (jit or _VERSION == "Lua 5.2") and require('bitops') or nil, + List = List, + Dict = Dict, + lpeg = lpeg, + re = re, + Files = Files, + SyntaxTree = SyntaxTree, + TESTS = Dict({ }), + globals = Dict({ }), + LuaCode = LuaCode, + NomsuCode = NomsuCode, + Source = Source, + SOURCE_MAP = Importer({ }), + _1_as_nomsu = tree_to_nomsu, + _1_as_inline_nomsu = tree_to_inline_nomsu, + compile = require('nomsu_compiler'), + _1_forked = _1_forked, + import_to_1_from = import_to_1_from, + _1_parsed = function(nomsu_code) + if type(nomsu_code) == 'string' then + local filename = Files.spoof(nomsu_code) + nomsu_code = NomsuCode(Source(filename, 1, #nomsu_code), nomsu_code) + end + local source = nomsu_code.source + nomsu_code = tostring(nomsu_code) + local version = nomsu_code:match("^#![^\n]*nomsu[ ]+-V[ ]*([0-9.]+)") + local syntax_version = version and tonumber(version:match("^[0-9]+")) or max_parser_version + local parse = Parsers[syntax_version] or Parsers[max_parser_version] + local tree = parse(nomsu_code, source.filename) + local find_errors + find_errors = function(t) + if t.type == "Error" then + return coroutine.yield(t) + else + for k, v in pairs(t) do + local _continue_0 = false + repeat + if not (SyntaxTree:is_instance(v)) then + _continue_0 = true + break + end + find_errors(v) + _continue_0 = true + until true + if not _continue_0 then + break + end + end + end + end + local errs + do + local _accum_0 = { } + local _len_0 = 1 + for err in coroutine.wrap(function() + return find_errors(tree) + end) do + _accum_0[_len_0] = err + _len_0 = _len_0 + 1 + end + errs = _accum_0 + end + local num_errs = #errs + if num_errs > 0 then + local err_strings + do + local _accum_0 = { } + local _len_0 = 1 + for i, e in ipairs(errs) do + if i <= 3 then + _accum_0[_len_0] = pretty_error({ + title = "Parse error", + error = e.error, + hint = e.hint, + source = e:get_source_code(), + start = e.source.start, + stop = e.source.stop, + filename = e.source.filename + }) + _len_0 = _len_0 + 1 + end + end + err_strings = _accum_0 + end + if num_errs > #err_strings then + table.insert(err_strings, "\027[31;1m +" .. tostring(num_errs - #err_strings) .. " additional errors...\027[0m\n") + end + error(table.concat(err_strings, '\n\n'), 0) + end + return tree + end, + run_1_in = function(to_run, environment) + if type(to_run) == 'string' then + local filename = Files.spoof(to_run) + to_run = NomsuCode(Source(filename, 1, #to_run), to_run) + local ret = environment.run_1_in(to_run, environment) + return ret + elseif NomsuCode:is_instance(to_run) then + local tree = environment._1_parsed(to_run) + if tree == nil then + return nil + end + local ret = environment.run_1_in(tree, environment) + return ret + elseif SyntaxTree:is_instance(to_run) then + local filename = to_run.source.filename:gsub("\n.*", "...") + if to_run.type ~= "FileChunks" then + to_run = { + to_run + } + end + local ret = nil + for _index_0 = 1, #to_run do + local chunk = to_run[_index_0] + local lua = environment.compile(chunk) + lua:declare_locals() + lua:prepend("-- File: " .. tostring(filename) .. "\n") + ret = environment.run_1_in(lua, environment) + end + return ret + elseif LuaCode:is_instance(to_run) then + local source = to_run.source + local lua_string = to_run:text() + local run_lua_fn, err = load(lua_string, tostring(source), "t", environment) + if not run_lua_fn then + local lines + do + local _accum_0 = { } + local _len_0 = 1 + for i, line in ipairs(Files.get_lines(lua_string)) do + _accum_0[_len_0] = ("%3d|%s"):format(i, line) + _len_0 = _len_0 + 1 + end + lines = _accum_0 + end + local line_numbered_lua = table.concat(lines, "\n") + error("Failed to compile generated code:\n\027[1;34m" .. tostring(line_numbered_lua) .. "\027[0m\n\n" .. tostring(err), 0) + end + local source_key = tostring(source) + if not (environment.SOURCE_MAP[source_key]) then + local map = { } + local file = Files.read(source.filename) + if not file then + error("Failed to find file: " .. tostring(source.filename)) + end + local nomsu_str = file:sub(source.start, source.stop) + local lua_line = 1 + local nomsu_line = Files.get_line_number(file, source.start) + local map_sources + map_sources = function(s) + if type(s) == 'string' then + for nl in s:gmatch("\n") do + map[lua_line] = map[lua_line] or nomsu_line + lua_line = lua_line + 1 + end + else + if s.source and s.source.filename == source.filename then + nomsu_line = Files.get_line_number(file, s.source.start) + end + local _list_0 = s.bits + for _index_0 = 1, #_list_0 do + local b = _list_0[_index_0] + map_sources(b) + end + end + end + map_sources(to_run) + map[lua_line] = map[lua_line] or nomsu_line + map[0] = 0 + environment.SOURCE_MAP[source_key] = map + end + return run_lua_fn() + else + return error("Attempt to run unknown thing: " .. tostring(to_run)) + end + end, + FILE_CACHE = { }, + run_file_1_in = function(path, environment, optimization) + if optimization == nil then + optimization = 1 + end + if environment.FILE_CACHE[path] then + import_to_1_from(environment, environment.FILE_CACHE[path]) + return + end + local mod = _1_forked(environment) + assert(mod._1_parsed) + mod._ENV = mod + for _, filename in Files.walk(path) do + local _continue_0 = false + repeat + if not (filename == "stdin" or filename:match("%.nom$")) then + _continue_0 = true + break + end + local lua_filename = filename:gsub("%.nom$", ".lua") + local code + if optimization ~= 0 and Files.read(lua_filename) then + local file = Files.read(lua_filename) + code = LuaCode(Source(filename, 1, #file), file) + else + local file = Files.read(filename) + code = NomsuCode(Source(filename, 1, #file), file) + end + environment.run_1_in(code, mod) + _continue_0 = true + until true + if not _continue_0 then + break + end + end + import_to_1_from(environment, mod) + environment.FILE_CACHE[path] = mod + end, + compile_error_at = function(tree, err_msg, hint) + if hint == nil then + hint = nil + end + local err_str = pretty_error({ + title = "Compile error", + error = err_msg, + hint = hint, + source = tree:get_source_code(), + start = tree.source.start, + stop = tree.source.stop, + filename = tree.source.filename + }) + return error(err_str, 0) + end +}) +nomsu_environment._ENV = nomsu_environment +SOURCE_MAP = nomsu_environment.SOURCE_MAP +return nomsu_environment |
