code / nomsu

Lines6.6K Lua5.1K PEG1.3K make117
2 others 83
Markdown60 Bourne Again Shell23
(300 lines)
1 NOMSU_VERSION = {
2 7,
3 0,
4 1
5 }
6 local clibtype = package.cpath:match("?%.(so)") or package.cpath:match("?%.(dll)")
7 if NOMSU_PREFIX then
8 package.path = tostring(NOMSU_PREFIX) .. "/share/nomsu/" .. tostring(table.concat(NOMSU_VERSION, ".")) .. "/?.lua;" .. package.path
9 package.cpath = tostring(NOMSU_PREFIX) .. "/lib/nomsu/" .. tostring(table.concat(NOMSU_VERSION, ".")) .. "/?." .. tostring(clibtype) .. ";" .. package.cpath
10 end
11 COLOR_ENABLED = true
12 if clibtype == "dll" then
13 local ok, enable_colors = pcall(require, 'wincolors')
14 COLOR_ENABLED = false
15 if ok then
16 local _
17 ok, _ = pcall(enable_colors)
18 if ok then
19 COLOR_ENABLED = false
20 end
21 end
22 pcall(os.execute, "chcp 65001>nul")
23 end
24 local List, Dict
25 do
26 local _obj_0 = require('containers')
27 List, Dict = _obj_0.List, _obj_0.Dict
28 end
29 NOMSU_VERSION = List(NOMSU_VERSION)
30 local Text = require('text')
31 require('builtin_metatables')
32 local EXIT_FAILURE = 1
33 local EXIT_SUCCESS = 0
34 local usage = [=[Nomsu Usage: nomsu [-V version] [--help | -h] [--version] [-O optimization level] [-v] [-c] [-s] [-d debugger] [--no-core] [(file | -t tool | -e "nomsu code..." | files... -- ) [nomsu args...]]
36 OPTIONS
37 -t <tool> Run a tool.
38 -e Execute the specified string.
39 -O <level> Run the compiler with the given optimization level (>0: use precompiled .lua versions of Nomsu files, when available).
40 -v Verbose: print compiled lua code.
41 -c Compile the input files into a .lua files.
42 -s Check the input files for syntax errors.
43 -d <debugger> Attempt to use the specified debugger to wrap the main body of execution.
44 -h/--help Print this message.
45 --version Print the version number and exit.
46 --no-core Skip loading the Nomsu core by default.
47 -V specify which Nomsu version is desired.
48 <file> The Nomsu file to run (can be "-" to use stdin).
49 ]=]
50 local ok, _ = pcall(function()
51 lpeg = require('lpeg')
52 re = require('re')
53 end)
54 if not ok then
55 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`")
56 os.exit(EXIT_FAILURE)
57 end
58 local Files = require("files")
59 local NomsuCode, LuaCode, Source
60 do
61 local _obj_0 = require("code_obj")
62 NomsuCode, LuaCode, Source = _obj_0.NomsuCode, _obj_0.LuaCode, _obj_0.Source
63 end
64 local sep = "\3"
65 local parser = re.compile([[ args <- {| (flag %sep)*
66 {:files: {|
67 ( ("-m" %sep)? (file %sep)+ "--" %sep
68 / file %sep
69 / {~ '' %sep? -> 'nomsu://tools/repl.nom' ~}) |} :}
70 {:nomsu_args: {| (nomsu_flag %sep)* {:extras: {| ({[^%sep]+} %sep)* |} :} |} :}
71 |} ({.+}?)
73 file <-
74 ( "-e" %sep ({[^%sep]+} -> spoof)
75 / "-t" %sep {~ {[^%sep]+} -> "nomsu://tools/%1.nom" ~}
76 / !"--" {[^%sep]+})
78 flag <- longflag / shortflag / "-" shortboolflag+
79 longflag <-
80 {:help: "--help" %true :}
81 / {:version: "--version" %true :}
82 / {:no_core: "--no-core" %true :}
83 shortflag <-
84 {:optimization: "-O" %sep? %number :}
85 / {:debugger: ("-d" %sep? {[^%sep]+}) :}
86 / {:requested_version: "-V" %sep? {([0-9.])+} :}
87 shortboolflag <-
88 {:check_syntax: "s" %true:}
89 / {:compile: "c" %true:}
90 / {:verbose: "v" %true :}
91 / {:help: "h" %true :}
93 nomsu_flag <- nomsu_longflag / "-" nomsu_shortboolflag+
94 nomsu_shortboolflag <- {| {:key: [a-zA-Z] :} {:value: %true :} |}
95 nomsu_longflag <- '--' {| {:key: [^%sep=]+ :} {:value: ('=' {[^%sep]+}) / %true :} |}
96 ]], {
97 ["true"] = lpeg.Cc(true),
98 number = lpeg.R("09") ^ 1 / tonumber,
99 sep = lpeg.P(sep),
100 spoof = Files.spoof
102 local arg_string = table.concat(arg, sep) .. sep
103 local args, err = parser:match(arg_string)
104 if not args or err then
105 if err then
106 print("Didn't understand: " .. tostring(err))
107 end
108 print(usage)
109 os.exit(EXIT_FAILURE)
110 end
111 if args.help then
112 print("Nomsu - A dynamically typed programming language with natural syntax and strong metaprogramming abilities.")
113 print("https://nomsu.org\n")
114 print(usage)
115 os.exit(EXIT_SUCCESS)
116 end
117 if args.version then
118 print(NOMSU_VERSION:joined_with("."))
119 os.exit(EXIT_SUCCESS)
120 end
121 local nomsu_args = Dict({ })
122 local _list_0 = args.nomsu_args
123 for _index_0 = 1, #_list_0 do
124 local argpair = _list_0[_index_0]
125 nomsu_args[argpair.key] = argpair.value
126 end
127 nomsu_args.extras = List(args.nomsu_args.extras or { })
128 local optimization = tonumber(args.optimization or 1)
129 local nomsupath = { }
130 local suffixes
131 if optimization > 0 then
132 suffixes = {
133 "?.lua",
134 "?/init.lua",
135 "?.nom",
136 "?/init.nom"
138 else
139 suffixes = {
140 "?.nom",
141 "?/init.nom"
143 end
144 local add_path
145 add_path = function(p)
146 for _index_0 = 1, #suffixes do
147 local s = suffixes[_index_0]
148 table.insert(nomsupath, p .. "/" .. s)
149 end
150 end
151 if NOMSU_PREFIX then
152 add_path(tostring(NOMSU_PREFIX) .. "/share/nomsu/" .. tostring(NOMSU_VERSION:joined_with(".")) .. "/lib")
153 else
154 add_path("./lib")
155 end
156 local NOMSU_PACKAGEPATH = NOMSU_PACKAGEPATH or "/opt/nomsu"
157 add_path(NOMSU_PACKAGEPATH)
158 add_path(".")
159 package.nomsupath = table.concat(nomsupath, ";")
160 package.nomsuloaded = Dict({ })
161 local nomsu_environment = require('nomsu_environment')
162 nomsu_environment.NOMSU_VERSION = NOMSU_VERSION
163 nomsu_environment.COMMAND_LINE_ARGS = nomsu_args
164 nomsu_environment.OPTIMIZATION = optimization
165 nomsu_environment.NOMSU_PACKAGEPATH = NOMSU_PACKAGEPATH
166 nomsu_environment.NOMSU_PREFIX = NOMSU_PREFIX
167 nomsu_environment.COLOR_ENABLED = COLOR_ENABLED
168 local run
169 run = function()
170 if not (args.no_core) then
171 nomsu_environment:export("core")
172 end
173 local input_files = { }
174 if args.files and #args.files > 0 then
175 local _list_1 = args.files
176 for _index_0 = 1, #_list_1 do
177 local f = _list_1[_index_0]
179 local nomsu_name = f:match("^nomsu://(.*)%.nom")
180 if nomsu_name then
181 local path
182 path, err = package.searchpath(nomsu_name, package.nomsupath, "/")
183 if not path then
184 error(err)
185 end
186 table.insert(input_files, path)
187 else
188 table.insert(input_files, f)
189 end
190 end
191 end
192 end
193 for _index_0 = 1, #input_files do
194 local filename = input_files[_index_0]
195 if args.check_syntax then
196 local code = Files.read(filename)
197 local source = Source(filename, 1, #code)
198 nomsu_environment._1_parsed(NomsuCode:from(source, code))
199 print("Parse succeeded: " .. tostring(filename))
200 elseif args.compile then
201 local code = Files.read(filename)
202 if not code then
203 error("Could not find file '" .. tostring(filename) .. "'")
204 end
205 if filename:match("%.lua$") then
206 error("Cannot compile a lua file (expected a nomsu file as input)")
207 end
208 local output
209 if filename == 'stdin' then
210 output = io.output()
211 else
212 output = io.open(filename:gsub("%.nom$", ".lua"), "w")
213 end
214 local source = Source(filename, 1, #code)
215 code = NomsuCode:from(source, code)
216 local env = nomsu_environment.new_environment()
217 env.MODULE_NAME = filename
218 local tree = env._1_parsed(code)
219 if tree.shebang then
220 output:write(tree.shebang)
221 end
222 if not (tree.type == 'FileChunks') then
223 tree = {
224 tree
226 end
227 for chunk_no, chunk in ipairs(tree) do
228 local lua = env:compile(chunk)
229 lua:declare_locals()
230 lua:prepend((chunk_no > 1) and '\n' or '', "-- File " .. tostring(filename) .. " chunk #" .. tostring(chunk_no) .. "\n")
231 if args.verbose then
232 print(lua:text())
233 end
234 env:run(chunk)
235 output:write(lua:text(), "\n")
236 end
237 print(("Compiled %-25s -> %s"):format(filename, filename:gsub("%.nom$", ".lua")))
238 output:close()
239 elseif args.verbose then
240 local env = nomsu_environment.new_environment()
241 env.MODULE_NAME = filename
242 env.WAS_RUN_DIRECTLY = true
243 local code = Files.read(filename)
244 local source = Source(filename, 1, #code)
245 if filename:match("%.lua$") then
246 code = LuaCode:from(Source(filename, 1, #code), code)
247 print(code:text())
248 env:run(code)
249 else
250 code = NomsuCode:from(source, code)
251 local tree = env._1_parsed(code)
252 if not (tree.type == 'FileChunks') then
253 tree = {
254 tree
256 end
257 for chunk_no, chunk in ipairs(tree) do
258 local lua = env:compile(chunk)
259 lua:declare_locals()
260 lua:prepend((chunk_no > 1) and '\n' or '', "-- File " .. tostring(filename) .. " chunk #" .. tostring(chunk_no) .. "\n")
261 print(lua:text())
262 env:run(lua)
263 end
264 end
265 else
266 local f = Files.read(filename)
267 if not f then
268 if filename:match("^-") then
269 print("Not a valid flag: " .. filename .. "\n")
270 print(usage)
271 else
272 print("File not found: " .. filename)
273 end
274 os.exit(EXIT_FAILURE)
275 end
276 if filename:match("%.lua$") then
277 f = LuaCode:from(Source(filename, 1, #f), f)
278 end
279 local env = nomsu_environment.new_environment()
280 env.MODULE_NAME = filename
281 env.WAS_RUN_DIRECTLY = true
282 env:run(f)
283 end
284 end
285 end
286 local debugger
287 if args.debugger == "nil" then
288 debugger = { }
289 else
290 debugger = require(args.debugger or 'error_handling')
291 end
292 local guard
293 if type(debugger) == 'function' then
294 guard = debugger
295 else
296 guard = debugger.guard or debugger.call or debugger.wrap or debugger.run or (function(fn)
297 return fn()
298 end)
299 end
300 return guard(run)