···11-package.preload["fennel.repl"] = package.preload["fennel.repl"] or function(...)
22- local utils = require("fennel.utils")
33- local parser = require("fennel.parser")
44- local compiler = require("fennel.compiler")
55- local specials = require("fennel.specials")
66- local view = require("fennel.view")
77- local unpack = (table.unpack or _G.unpack)
88- local function default_read_chunk(parser_state)
99- local function _620_()
1010- if (0 < parser_state["stack-size"]) then
1111- return ".."
1212- else
1313- return ">> "
1414- end
1515- end
1616- io.write(_620_())
1717- io.flush()
1818- local input = io.read()
1919- return (input and (input .. "\n"))
2020- end
2121- local function default_on_values(xs)
2222- io.write(table.concat(xs, "\9"))
2323- return io.write("\n")
2424- end
2525- local function default_on_error(errtype, err, lua_source)
2626- local function _622_()
2727- local _621_ = errtype
2828- if (_621_ == "Lua Compile") then
2929- return ("Bad code generated - likely a bug with the compiler:\n" .. "--- Generated Lua Start ---\n" .. lua_source .. "--- Generated Lua End ---\n")
3030- elseif (_621_ == "Runtime") then
3131- return (compiler.traceback(tostring(err), 4) .. "\n")
3232- elseif true then
3333- local _ = _621_
3434- return ("%s error: %s\n"):format(errtype, tostring(err))
3535- else
3636- return nil
3737- end
3838- end
3939- return io.write(_622_())
4040- end
4141- local save_source = " ___replLocals___['%s'] = %s"
4242- local function splice_save_locals(env, lua_source, scope)
4343- local spliced_source = {}
4444- local bind = "local %s = ___replLocals___['%s']"
4545- for line in lua_source:gmatch("([^\n]+)\n?") do
4646- table.insert(spliced_source, line)
4747- end
4848- for name in pairs(env.___replLocals___) do
4949- table.insert(spliced_source, 1, bind:format(name, name))
5050- end
5151- if ((1 < #spliced_source) and (spliced_source[#spliced_source]):match("^ *return .*$")) then
5252- for _, name in pairs(scope.manglings) do
5353- table.insert(spliced_source, #spliced_source, save_source:format(name, name))
5454- end
5555- else
5656- end
5757- return table.concat(spliced_source, "\n")
5858- end
5959- local function completer(env, scope, text)
6060- local max_items = 2000
6161- local seen = {}
6262- local matches = {}
6363- local input_fragment = text:gsub(".*[%s)(]+", "")
6464- local stop_looking_3f = false
6565- local function add_partials(input, tbl, prefix)
6666- local scope_first_3f = ((tbl == env) or (tbl == env.___replLocals___))
6767- local tbl_14_auto = matches
6868- local i_15_auto = #tbl_14_auto
6969- local function _625_()
7070- if scope_first_3f then
7171- return scope.manglings
7272- else
7373- return tbl
7474- end
7575- end
7676- for k, is_mangled in utils.allpairs(_625_()) do
7777- if (max_items <= #matches) then break end
7878- local val_16_auto
7979- do
8080- local lookup_k
8181- if scope_first_3f then
8282- lookup_k = is_mangled
8383- else
8484- lookup_k = k
8585- end
8686- if ((type(k) == "string") and (input == k:sub(0, #input)) and not seen[k] and ((":" ~= prefix:sub(-1)) or ("function" == type(tbl[lookup_k])))) then
8787- seen[k] = true
8888- val_16_auto = (prefix .. k)
8989- else
9090- val_16_auto = nil
9191- end
9292- end
9393- if (nil ~= val_16_auto) then
9494- i_15_auto = (i_15_auto + 1)
9595- do end (tbl_14_auto)[i_15_auto] = val_16_auto
9696- else
9797- end
9898- end
9999- return tbl_14_auto
100100- end
101101- local function descend(input, tbl, prefix, add_matches, method_3f)
102102- local splitter
103103- if method_3f then
104104- splitter = "^([^:]+):(.*)"
105105- else
106106- splitter = "^([^.]+)%.(.*)"
107107- end
108108- local head, tail = input:match(splitter)
109109- local raw_head = (scope.manglings[head] or head)
110110- if (type(tbl[raw_head]) == "table") then
111111- stop_looking_3f = true
112112- if method_3f then
113113- return add_partials(tail, tbl[raw_head], (prefix .. head .. ":"))
114114- else
115115- return add_matches(tail, tbl[raw_head], (prefix .. head))
116116- end
117117- else
118118- return nil
119119- end
120120- end
121121- local function add_matches(input, tbl, prefix)
122122- local prefix0
123123- if prefix then
124124- prefix0 = (prefix .. ".")
125125- else
126126- prefix0 = ""
127127- end
128128- if (not input:find("%.") and input:find(":")) then
129129- return descend(input, tbl, prefix0, add_matches, true)
130130- elseif not input:find("%.") then
131131- return add_partials(input, tbl, prefix0)
132132- else
133133- return descend(input, tbl, prefix0, add_matches, false)
134134- end
135135- end
136136- for _, source in ipairs({scope.specials, scope.macros, (env.___replLocals___ or {}), env, env._G}) do
137137- if stop_looking_3f then break end
138138- add_matches(input_fragment, source)
139139- end
140140- return matches
141141- end
142142- local commands = {}
143143- local function command_3f(input)
144144- return input:match("^%s*,")
145145- end
146146- local function command_docs()
147147- local _634_
148148- do
149149- local tbl_14_auto = {}
150150- local i_15_auto = #tbl_14_auto
151151- for name, f in pairs(commands) do
152152- local val_16_auto = (" ,%s - %s"):format(name, ((compiler.metadata):get(f, "fnl/docstring") or "undocumented"))
153153- if (nil ~= val_16_auto) then
154154- i_15_auto = (i_15_auto + 1)
155155- do end (tbl_14_auto)[i_15_auto] = val_16_auto
156156- else
157157- end
158158- end
159159- _634_ = tbl_14_auto
160160- end
161161- return table.concat(_634_, "\n")
162162- end
163163- commands.help = function(_, _0, on_values)
164164- return on_values({("Welcome to Fennel.\nThis is the REPL where you can enter code to be evaluated.\nYou can also run these repl commands:\n\n" .. command_docs() .. "\n ,exit - Leave the repl.\n\nUse ,doc something to see descriptions for individual macros and special forms.\n\nFor more information about the language, see https://fennel-lang.org/reference")})
165165- end
166166- do end (compiler.metadata):set(commands.help, "fnl/docstring", "Show this message.")
167167- local function reload(module_name, env, on_values, on_error)
168168- local _636_, _637_ = pcall(specials["load-code"]("return require(...)", env), module_name)
169169- if ((_636_ == true) and (nil ~= _637_)) then
170170- local old = _637_
171171- local _
172172- package.loaded[module_name] = nil
173173- _ = nil
174174- local ok, new = pcall(require, module_name)
175175- local new0
176176- if not ok then
177177- on_values({new})
178178- new0 = old
179179- else
180180- new0 = new
181181- end
182182- specials["macro-loaded"][module_name] = nil
183183- if ((type(old) == "table") and (type(new0) == "table")) then
184184- for k, v in pairs(new0) do
185185- old[k] = v
186186- end
187187- for k in pairs(old) do
188188- if (nil == (new0)[k]) then
189189- old[k] = nil
190190- else
191191- end
192192- end
193193- package.loaded[module_name] = old
194194- else
195195- end
196196- return on_values({"ok"})
197197- elseif ((_636_ == false) and (nil ~= _637_)) then
198198- local msg = _637_
199199- if (specials["macro-loaded"])[module_name] then
200200- specials["macro-loaded"][module_name] = nil
201201- return nil
202202- else
203203- local function _642_()
204204- local _641_ = msg:gsub("\n.*", "")
205205- return _641_
206206- end
207207- return on_error("Runtime", _642_())
208208- end
209209- else
210210- return nil
211211- end
212212- end
213213- local function run_command(read, on_error, f)
214214- local _645_, _646_, _647_ = pcall(read)
215215- if ((_645_ == true) and (_646_ == true) and (nil ~= _647_)) then
216216- local val = _647_
217217- return f(val)
218218- elseif (_645_ == false) then
219219- return on_error("Parse", "Couldn't parse input.")
220220- else
221221- return nil
222222- end
223223- end
224224- commands.reload = function(env, read, on_values, on_error)
225225- local function _649_(_241)
226226- return reload(tostring(_241), env, on_values, on_error)
227227- end
228228- return run_command(read, on_error, _649_)
229229- end
230230- do end (compiler.metadata):set(commands.reload, "fnl/docstring", "Reload the specified module.")
231231- commands.reset = function(env, _, on_values)
232232- env.___replLocals___ = {}
233233- return on_values({"ok"})
234234- end
235235- do end (compiler.metadata):set(commands.reset, "fnl/docstring", "Erase all repl-local scope.")
236236- commands.complete = function(env, read, on_values, on_error, scope, chars)
237237- local function _650_()
238238- return on_values(completer(env, scope, string.char(unpack(chars)):gsub(",complete +", ""):sub(1, -2)))
239239- end
240240- return run_command(read, on_error, _650_)
241241- end
242242- do end (compiler.metadata):set(commands.complete, "fnl/docstring", "Print all possible completions for a given input symbol.")
243243- local function apropos_2a(pattern, tbl, prefix, seen, names)
244244- for name, subtbl in pairs(tbl) do
245245- if (("string" == type(name)) and (package ~= subtbl)) then
246246- local _651_ = type(subtbl)
247247- if (_651_ == "function") then
248248- if ((prefix .. name)):match(pattern) then
249249- table.insert(names, (prefix .. name))
250250- else
251251- end
252252- elseif (_651_ == "table") then
253253- if not seen[subtbl] then
254254- local _654_
255255- do
256256- local _653_ = seen
257257- _653_[subtbl] = true
258258- _654_ = _653_
259259- end
260260- apropos_2a(pattern, subtbl, (prefix .. name:gsub("%.", "/") .. "."), _654_, names)
261261- else
262262- end
263263- else
264264- end
265265- else
266266- end
267267- end
268268- return names
269269- end
270270- local function apropos(pattern)
271271- local names = apropos_2a(pattern, package.loaded, "", {}, {})
272272- local tbl_14_auto = {}
273273- local i_15_auto = #tbl_14_auto
274274- for _, name in ipairs(names) do
275275- local val_16_auto = name:gsub("^_G%.", "")
276276- if (nil ~= val_16_auto) then
277277- i_15_auto = (i_15_auto + 1)
278278- do end (tbl_14_auto)[i_15_auto] = val_16_auto
279279- else
280280- end
281281- end
282282- return tbl_14_auto
283283- end
284284- commands.apropos = function(_env, read, on_values, on_error, _scope)
285285- local function _659_(_241)
286286- return on_values(apropos(tostring(_241)))
287287- end
288288- return run_command(read, on_error, _659_)
289289- end
290290- do end (compiler.metadata):set(commands.apropos, "fnl/docstring", "Print all functions matching a pattern in all loaded modules.")
291291- local function apropos_follow_path(path)
292292- local paths
293293- do
294294- local tbl_14_auto = {}
295295- local i_15_auto = #tbl_14_auto
296296- for p in path:gmatch("[^%.]+") do
297297- local val_16_auto = p
298298- if (nil ~= val_16_auto) then
299299- i_15_auto = (i_15_auto + 1)
300300- do end (tbl_14_auto)[i_15_auto] = val_16_auto
301301- else
302302- end
303303- end
304304- paths = tbl_14_auto
305305- end
306306- local tgt = package.loaded
307307- for _, path0 in ipairs(paths) do
308308- if (nil == tgt) then break end
309309- local _662_
310310- do
311311- local _661_ = path0:gsub("%/", ".")
312312- _662_ = _661_
313313- end
314314- tgt = tgt[_662_]
315315- end
316316- return tgt
317317- end
318318- local function apropos_doc(pattern)
319319- local tbl_14_auto = {}
320320- local i_15_auto = #tbl_14_auto
321321- for _, path in ipairs(apropos(".*")) do
322322- local val_16_auto
323323- do
324324- local tgt = apropos_follow_path(path)
325325- if ("function" == type(tgt)) then
326326- local _663_ = (compiler.metadata):get(tgt, "fnl/docstring")
327327- if (nil ~= _663_) then
328328- local docstr = _663_
329329- val_16_auto = (docstr:match(pattern) and path)
330330- else
331331- val_16_auto = nil
332332- end
333333- else
334334- val_16_auto = nil
335335- end
336336- end
337337- if (nil ~= val_16_auto) then
338338- i_15_auto = (i_15_auto + 1)
339339- do end (tbl_14_auto)[i_15_auto] = val_16_auto
340340- else
341341- end
342342- end
343343- return tbl_14_auto
344344- end
345345- commands["apropos-doc"] = function(_env, read, on_values, on_error, _scope)
346346- local function _667_(_241)
347347- return on_values(apropos_doc(tostring(_241)))
348348- end
349349- return run_command(read, on_error, _667_)
350350- end
351351- do end (compiler.metadata):set(commands["apropos-doc"], "fnl/docstring", "Print all functions that match the pattern in their docs")
352352- local function apropos_show_docs(on_values, pattern)
353353- for _, path in ipairs(apropos(pattern)) do
354354- local tgt = apropos_follow_path(path)
355355- if (("function" == type(tgt)) and (compiler.metadata):get(tgt, "fnl/docstring")) then
356356- on_values(specials.doc(tgt, path))
357357- on_values()
358358- else
359359- end
360360- end
361361- return nil
362362- end
363363- commands["apropos-show-docs"] = function(_env, read, on_values, on_error)
364364- local function _669_(_241)
365365- return apropos_show_docs(on_values, tostring(_241))
366366- end
367367- return run_command(read, on_error, _669_)
368368- end
369369- do end (compiler.metadata):set(commands["apropos-show-docs"], "fnl/docstring", "Print all documentations matching a pattern in function name")
370370- local function resolve(identifier, _670_, scope)
371371- local _arg_671_ = _670_
372372- local ___replLocals___ = _arg_671_["___replLocals___"]
373373- local env = _arg_671_
374374- local e
375375- local function _672_(_241, _242)
376376- return (___replLocals___[_242] or env[_242])
377377- end
378378- e = setmetatable({}, {__index = _672_})
379379- local _673_, _674_ = pcall(compiler["compile-string"], tostring(identifier), {scope = scope})
380380- if ((_673_ == true) and (nil ~= _674_)) then
381381- local code = _674_
382382- return specials["load-code"](code, e)()
383383- else
384384- return nil
385385- end
386386- end
387387- commands.find = function(env, read, on_values, on_error, scope)
388388- local function _676_(_241)
389389- local _677_
390390- do
391391- local _678_ = utils["sym?"](_241)
392392- if (nil ~= _678_) then
393393- local _679_ = resolve(_678_, env, scope)
394394- if (nil ~= _679_) then
395395- _677_ = debug.getinfo(_679_)
396396- else
397397- _677_ = _679_
398398- end
399399- else
400400- _677_ = _678_
401401- end
402402- end
403403- if ((_G.type(_677_) == "table") and ((_677_).what == "Lua") and (nil ~= (_677_).source) and (nil ~= (_677_).linedefined) and (nil ~= (_677_).short_src)) then
404404- local source = (_677_).source
405405- local line = (_677_).linedefined
406406- local src = (_677_).short_src
407407- local fnlsrc
408408- do
409409- local t_682_ = compiler.sourcemap
410410- if (nil ~= t_682_) then
411411- t_682_ = (t_682_)[source]
412412- else
413413- end
414414- if (nil ~= t_682_) then
415415- t_682_ = (t_682_)[line]
416416- else
417417- end
418418- if (nil ~= t_682_) then
419419- t_682_ = (t_682_)[2]
420420- else
421421- end
422422- fnlsrc = t_682_
423423- end
424424- return on_values({string.format("%s:%s", src, (fnlsrc or line))})
425425- elseif (_677_ == nil) then
426426- return on_error("Repl", "Unknown value")
427427- elseif true then
428428- local _ = _677_
429429- return on_error("Repl", "No source info")
430430- else
431431- return nil
432432- end
433433- end
434434- return run_command(read, on_error, _676_)
435435- end
436436- do end (compiler.metadata):set(commands.find, "fnl/docstring", "Print the filename and line number for a given function")
437437- commands.doc = function(env, read, on_values, on_error, scope)
438438- local function _687_(_241)
439439- local name = tostring(_241)
440440- local path = (utils["multi-sym?"](name) or {name})
441441- local ok_3f, target = nil, nil
442442- local function _688_()
443443- return (utils["get-in"](scope.specials, path) or utils["get-in"](scope.macros, path) or resolve(name, env, scope))
444444- end
445445- ok_3f, target = pcall(_688_)
446446- if ok_3f then
447447- return on_values({specials.doc(target, name)})
448448- else
449449- return on_error("Repl", "Could not resolve value for docstring lookup")
450450- end
451451- end
452452- return run_command(read, on_error, _687_)
453453- end
454454- do end (compiler.metadata):set(commands.doc, "fnl/docstring", "Print the docstring and arglist for a function, macro, or special form.")
455455- commands.compile = function(env, read, on_values, on_error, scope)
456456- local function _690_(_241)
457457- local allowedGlobals = specials["current-global-names"](env)
458458- local ok_3f, result = pcall(compiler.compile, _241, {env = env, scope = scope, allowedGlobals = allowedGlobals})
459459- if ok_3f then
460460- return on_values({result})
461461- else
462462- return on_error("Repl", ("Error compiling expression: " .. result))
463463- end
464464- end
465465- return run_command(read, on_error, _690_)
466466- end
467467- do end (compiler.metadata):set(commands.compile, "fnl/docstring", "compiles the expression into lua and prints the result.")
468468- local function load_plugin_commands(plugins)
469469- for _, plugin in ipairs((plugins or {})) do
470470- for name, f in pairs(plugin) do
471471- local _692_ = name:match("^repl%-command%-(.*)")
472472- if (nil ~= _692_) then
473473- local cmd_name = _692_
474474- commands[cmd_name] = (commands[cmd_name] or f)
475475- else
476476- end
477477- end
478478- end
479479- return nil
480480- end
481481- local function run_command_loop(input, read, loop, env, on_values, on_error, scope, chars)
482482- local command_name = input:match(",([^%s/]+)")
483483- do
484484- local _694_ = commands[command_name]
485485- if (nil ~= _694_) then
486486- local command = _694_
487487- command(env, read, on_values, on_error, scope, chars)
488488- elseif true then
489489- local _ = _694_
490490- if ("exit" ~= command_name) then
491491- on_values({"Unknown command", command_name})
492492- else
493493- end
494494- else
495495- end
496496- end
497497- if ("exit" ~= command_name) then
498498- return loop()
499499- else
500500- return nil
501501- end
502502- end
503503- local function try_readline_21(opts, ok, readline)
504504- if ok then
505505- if readline.set_readline_name then
506506- readline.set_readline_name("fennel")
507507- else
508508- end
509509- do
510510- local rl_opts
511511- do
512512- local tbl_11_auto = {keeplines = 1000, histfile = ""}
513513- for k, v in pairs(readline.set_options({})) do
514514- local _699_, _700_ = k, v
515515- if ((nil ~= _699_) and (nil ~= _700_)) then
516516- local k_12_auto = _699_
517517- local v_13_auto = _700_
518518- tbl_11_auto[k_12_auto] = v_13_auto
519519- else
520520- end
521521- end
522522- rl_opts = tbl_11_auto
523523- end
524524- readline.set_options(rl_opts)
525525- end
526526- opts.readChunk = function(parser_state)
527527- local prompt
528528- if (0 < parser_state["stack-size"]) then
529529- prompt = ".. "
530530- else
531531- prompt = ">> "
532532- end
533533- local str = readline.readline(prompt)
534534- if str then
535535- return (str .. "\n")
536536- else
537537- return nil
538538- end
539539- end
540540- local completer0 = nil
541541- opts.registerCompleter = function(repl_completer)
542542- completer0 = repl_completer
543543- return nil
544544- end
545545- local function repl_completer(text, from, to)
546546- if completer0 then
547547- readline.set_completion_append_character("")
548548- return completer0(text:sub(from, to))
549549- else
550550- return {}
551551- end
552552- end
553553- readline.set_complete_function(repl_completer)
554554- return readline
555555- else
556556- return nil
557557- end
558558- end
559559- local function should_use_readline_3f(opts)
560560- return (("dumb" ~= os.getenv("TERM")) and not opts.readChunk and not opts.registerCompleter)
561561- end
562562- local function repl(_3foptions)
563563- local old_root_options = utils.root.options
564564- local opts = ((_3foptions and utils.copy(_3foptions)) or {})
565565- local readline = (should_use_readline_3f(opts) and try_readline_21(opts, pcall(require, "readline")))
566566- local env = specials["wrap-env"]((opts.env or rawget(_G, "_ENV") or _G))
567567- local save_locals_3f = (opts.saveLocals ~= false)
568568- local read_chunk = (opts.readChunk or default_read_chunk)
569569- local on_values = (opts.onValues or default_on_values)
570570- local on_error = (opts.onError or default_on_error)
571571- local pp = (opts.pp or view)
572572- local byte_stream, clear_stream = parser.granulate(read_chunk)
573573- local chars = {}
574574- local read, reset = nil, nil
575575- local function _706_(parser_state)
576576- local c = byte_stream(parser_state)
577577- table.insert(chars, c)
578578- return c
579579- end
580580- read, reset = parser.parser(_706_)
581581- opts.env, opts.scope = env, compiler["make-scope"]()
582582- opts.useMetadata = (opts.useMetadata ~= false)
583583- if (opts.allowedGlobals == nil) then
584584- opts.allowedGlobals = specials["current-global-names"](env)
585585- else
586586- end
587587- if opts.registerCompleter then
588588- local function _710_()
589589- local _708_ = env
590590- local _709_ = opts.scope
591591- local function _711_(...)
592592- return completer(_708_, _709_, ...)
593593- end
594594- return _711_
595595- end
596596- opts.registerCompleter(_710_())
597597- else
598598- end
599599- load_plugin_commands(opts.plugins)
600600- if save_locals_3f then
601601- local function newindex(t, k, v)
602602- if opts.scope.unmanglings[k] then
603603- return rawset(t, k, v)
604604- else
605605- return nil
606606- end
607607- end
608608- env.___replLocals___ = setmetatable({}, {__newindex = newindex})
609609- else
610610- end
611611- local function print_values(...)
612612- local vals = {...}
613613- local out = {}
614614- env._, env.__ = vals[1], vals
615615- for i = 1, select("#", ...) do
616616- table.insert(out, pp(vals[i]))
617617- end
618618- return on_values(out)
619619- end
620620- local function loop()
621621- for k in pairs(chars) do
622622- chars[k] = nil
623623- end
624624- reset()
625625- local ok, not_eof_3f, x = pcall(read)
626626- local src_string = string.char(unpack(chars))
627627- if not ok then
628628- on_error("Parse", not_eof_3f)
629629- clear_stream()
630630- return loop()
631631- elseif command_3f(src_string) then
632632- return run_command_loop(src_string, read, loop, env, on_values, on_error, opts.scope, chars)
633633- else
634634- if not_eof_3f then
635635- do
636636- local _715_, _716_ = nil, nil
637637- local function _718_()
638638- local _717_ = opts
639639- _717_["source"] = src_string
640640- return _717_
641641- end
642642- _715_, _716_ = pcall(compiler.compile, x, _718_())
643643- if ((_715_ == false) and (nil ~= _716_)) then
644644- local msg = _716_
645645- clear_stream()
646646- on_error("Compile", msg)
647647- elseif ((_715_ == true) and (nil ~= _716_)) then
648648- local src = _716_
649649- local src0
650650- if save_locals_3f then
651651- src0 = splice_save_locals(env, src, opts.scope)
652652- else
653653- src0 = src
654654- end
655655- local _720_, _721_ = pcall(specials["load-code"], src0, env)
656656- if ((_720_ == false) and (nil ~= _721_)) then
657657- local msg = _721_
658658- clear_stream()
659659- on_error("Lua Compile", msg, src0)
660660- elseif (true and (nil ~= _721_)) then
661661- local _ = _720_
662662- local chunk = _721_
663663- local function _722_()
664664- return print_values(chunk())
665665- end
666666- local function _723_()
667667- local function _724_(...)
668668- return on_error("Runtime", ...)
669669- end
670670- return _724_
671671- end
672672- xpcall(_722_, _723_())
673673- else
674674- end
675675- else
676676- end
677677- end
678678- utils.root.options = old_root_options
679679- return loop()
680680- else
681681- return nil
682682- end
683683- end
684684- end
685685- loop()
686686- if readline then
687687- return readline.save_history()
688688- else
689689- return nil
690690- end
691691- end
692692- return repl
693693-end
694694-package.preload["fennel.specials"] = package.preload["fennel.specials"] or function(...)
695695- local utils = require("fennel.utils")
696696- local view = require("fennel.view")
697697- local parser = require("fennel.parser")
698698- local compiler = require("fennel.compiler")
699699- local unpack = (table.unpack or _G.unpack)
700700- local SPECIALS = compiler.scopes.global.specials
701701- local function wrap_env(env)
702702- local function _415_(_, key)
703703- if utils["string?"](key) then
704704- return env[compiler["global-unmangling"](key)]
705705- else
706706- return env[key]
707707- end
708708- end
709709- local function _417_(_, key, value)
710710- if utils["string?"](key) then
711711- env[compiler["global-unmangling"](key)] = value
712712- return nil
713713- else
714714- env[key] = value
715715- return nil
716716- end
717717- end
718718- local function _419_()
719719- local function putenv(k, v)
720720- local _420_
721721- if utils["string?"](k) then
722722- _420_ = compiler["global-unmangling"](k)
723723- else
724724- _420_ = k
725725- end
726726- return _420_, v
727727- end
728728- return next, utils.kvmap(env, putenv), nil
729729- end
730730- return setmetatable({}, {__index = _415_, __newindex = _417_, __pairs = _419_})
731731- end
732732- local function current_global_names(_3fenv)
733733- local mt
734734- do
735735- local _422_ = getmetatable(_3fenv)
736736- if ((_G.type(_422_) == "table") and (nil ~= (_422_).__pairs)) then
737737- local mtpairs = (_422_).__pairs
738738- local tbl_11_auto = {}
739739- for k, v in mtpairs(_3fenv) do
740740- local _423_, _424_ = k, v
741741- if ((nil ~= _423_) and (nil ~= _424_)) then
742742- local k_12_auto = _423_
743743- local v_13_auto = _424_
744744- tbl_11_auto[k_12_auto] = v_13_auto
745745- else
746746- end
747747- end
748748- mt = tbl_11_auto
749749- elseif (_422_ == nil) then
750750- mt = (_3fenv or _G)
751751- else
752752- mt = nil
753753- end
754754- end
755755- return (mt and utils.kvmap(mt, compiler["global-unmangling"]))
756756- end
757757- local function load_code(code, _3fenv, _3ffilename)
758758- local env = (_3fenv or rawget(_G, "_ENV") or _G)
759759- local _427_, _428_ = rawget(_G, "setfenv"), rawget(_G, "loadstring")
760760- if ((nil ~= _427_) and (nil ~= _428_)) then
761761- local setfenv = _427_
762762- local loadstring = _428_
763763- local f = assert(loadstring(code, _3ffilename))
764764- local _429_ = f
765765- setfenv(_429_, env)
766766- return _429_
767767- elseif true then
768768- local _ = _427_
769769- return assert(load(code, _3ffilename, "t", env))
770770- else
771771- return nil
772772- end
773773- end
774774- local function doc_2a(tgt, name)
775775- if not tgt then
776776- return (name .. " not found")
777777- else
778778- local docstring = (((compiler.metadata):get(tgt, "fnl/docstring") or "#<undocumented>")):gsub("\n$", ""):gsub("\n", "\n ")
779779- local mt = getmetatable(tgt)
780780- if ((type(tgt) == "function") or ((type(mt) == "table") and (type(mt.__call) == "function"))) then
781781- local arglist = table.concat(((compiler.metadata):get(tgt, "fnl/arglist") or {"#<unknown-arguments>"}), " ")
782782- local _431_
783783- if (0 < #arglist) then
784784- _431_ = " "
785785- else
786786- _431_ = ""
787787- end
788788- return string.format("(%s%s%s)\n %s", name, _431_, arglist, docstring)
789789- else
790790- return string.format("%s\n %s", name, docstring)
791791- end
792792- end
793793- end
794794- local function doc_special(name, arglist, docstring, body_form_3f)
795795- compiler.metadata[SPECIALS[name]] = {["fnl/arglist"] = arglist, ["fnl/docstring"] = docstring, ["fnl/body-form?"] = body_form_3f}
796796- return nil
797797- end
798798- local function compile_do(ast, scope, parent, _3fstart)
799799- local start = (_3fstart or 2)
800800- local len = #ast
801801- local sub_scope = compiler["make-scope"](scope)
802802- for i = start, len do
803803- compiler.compile1(ast[i], sub_scope, parent, {nval = 0})
804804- end
805805- return nil
806806- end
807807- SPECIALS["do"] = function(ast, scope, parent, opts, _3fstart, _3fchunk, _3fsub_scope, _3fpre_syms)
808808- local start = (_3fstart or 2)
809809- local sub_scope = (_3fsub_scope or compiler["make-scope"](scope))
810810- local chunk = (_3fchunk or {})
811811- local len = #ast
812812- local retexprs = {returned = true}
813813- local function compile_body(outer_target, outer_tail, outer_retexprs)
814814- if (len < start) then
815815- compiler.compile1(nil, sub_scope, chunk, {tail = outer_tail, target = outer_target})
816816- else
817817- for i = start, len do
818818- local subopts = {nval = (((i ~= len) and 0) or opts.nval), tail = (((i == len) and outer_tail) or nil), target = (((i == len) and outer_target) or nil)}
819819- local _ = utils["propagate-options"](opts, subopts)
820820- local subexprs = compiler.compile1(ast[i], sub_scope, chunk, subopts)
821821- if (i ~= len) then
822822- compiler["keep-side-effects"](subexprs, parent, nil, ast[i])
823823- else
824824- end
825825- end
826826- end
827827- compiler.emit(parent, chunk, ast)
828828- compiler.emit(parent, "end", ast)
829829- utils.hook("do", ast, sub_scope)
830830- return (outer_retexprs or retexprs)
831831- end
832832- if (opts.target or (opts.nval == 0) or opts.tail) then
833833- compiler.emit(parent, "do", ast)
834834- return compile_body(opts.target, opts.tail)
835835- elseif opts.nval then
836836- local syms = {}
837837- for i = 1, opts.nval do
838838- local s = ((_3fpre_syms and (_3fpre_syms)[i]) or compiler.gensym(scope))
839839- do end (syms)[i] = s
840840- retexprs[i] = utils.expr(s, "sym")
841841- end
842842- local outer_target = table.concat(syms, ", ")
843843- compiler.emit(parent, string.format("local %s", outer_target), ast)
844844- compiler.emit(parent, "do", ast)
845845- return compile_body(outer_target, opts.tail)
846846- else
847847- local fname = compiler.gensym(scope)
848848- local fargs
849849- if scope.vararg then
850850- fargs = "..."
851851- else
852852- fargs = ""
853853- end
854854- compiler.emit(parent, string.format("local function %s(%s)", fname, fargs), ast)
855855- return compile_body(nil, true, utils.expr((fname .. "(" .. fargs .. ")"), "statement"))
856856- end
857857- end
858858- doc_special("do", {"..."}, "Evaluate multiple forms; return last value.", true)
859859- SPECIALS.values = function(ast, scope, parent)
860860- local len = #ast
861861- local exprs = {}
862862- for i = 2, len do
863863- local subexprs = compiler.compile1(ast[i], scope, parent, {nval = ((i ~= len) and 1)})
864864- table.insert(exprs, subexprs[1])
865865- if (i == len) then
866866- for j = 2, #subexprs do
867867- table.insert(exprs, subexprs[j])
868868- end
869869- else
870870- end
871871- end
872872- return exprs
873873- end
874874- doc_special("values", {"..."}, "Return multiple values from a function. Must be in tail position.")
875875- local function deep_tostring(x, key_3f)
876876- if utils["list?"](x) then
877877- local _440_
878878- do
879879- local tbl_14_auto = {}
880880- local i_15_auto = #tbl_14_auto
881881- for _, v in ipairs(x) do
882882- local val_16_auto = deep_tostring(v)
883883- if (nil ~= val_16_auto) then
884884- i_15_auto = (i_15_auto + 1)
885885- do end (tbl_14_auto)[i_15_auto] = val_16_auto
886886- else
887887- end
888888- end
889889- _440_ = tbl_14_auto
890890- end
891891- return ("(" .. table.concat(_440_, " ") .. ")")
892892- elseif utils["sequence?"](x) then
893893- local _442_
894894- do
895895- local tbl_14_auto = {}
896896- local i_15_auto = #tbl_14_auto
897897- for _, v in ipairs(x) do
898898- local val_16_auto = deep_tostring(v)
899899- if (nil ~= val_16_auto) then
900900- i_15_auto = (i_15_auto + 1)
901901- do end (tbl_14_auto)[i_15_auto] = val_16_auto
902902- else
903903- end
904904- end
905905- _442_ = tbl_14_auto
906906- end
907907- return ("[" .. table.concat(_442_, " ") .. "]")
908908- elseif utils["table?"](x) then
909909- local _444_
910910- do
911911- local tbl_14_auto = {}
912912- local i_15_auto = #tbl_14_auto
913913- for k, v in utils.stablepairs(x) do
914914- local val_16_auto = (deep_tostring(k, true) .. " " .. deep_tostring(v))
915915- if (nil ~= val_16_auto) then
916916- i_15_auto = (i_15_auto + 1)
917917- do end (tbl_14_auto)[i_15_auto] = val_16_auto
918918- else
919919- end
920920- end
921921- _444_ = tbl_14_auto
922922- end
923923- return ("{" .. table.concat(_444_, " ") .. "}")
924924- elseif (key_3f and utils["string?"](x) and x:find("^[-%w?\\^_!$%&*+./@:|<=>]+$")) then
925925- return (":" .. x)
926926- elseif utils["string?"](x) then
927927- return string.format("%q", x):gsub("\\\"", "\\\\\""):gsub("\"", "\\\"")
928928- else
929929- return tostring(x)
930930- end
931931- end
932932- local function set_fn_metadata(arg_list, docstring, parent, fn_name)
933933- if utils.root.options.useMetadata then
934934- local args
935935- local function _447_(_241)
936936- return ("\"%s\""):format(deep_tostring(_241))
937937- end
938938- args = utils.map(arg_list, _447_)
939939- local meta_fields = {"\"fnl/arglist\"", ("{" .. table.concat(args, ", ") .. "}")}
940940- if docstring then
941941- table.insert(meta_fields, "\"fnl/docstring\"")
942942- table.insert(meta_fields, ("\"" .. docstring:gsub("%s+$", ""):gsub("\\", "\\\\"):gsub("\n", "\\n"):gsub("\"", "\\\"") .. "\""))
943943- else
944944- end
945945- local meta_str = ("require(\"%s\").metadata"):format((utils.root.options.moduleName or "fennel"))
946946- return compiler.emit(parent, ("pcall(function() %s:setall(%s, %s) end)"):format(meta_str, fn_name, table.concat(meta_fields, ", ")))
947947- else
948948- return nil
949949- end
950950- end
951951- local function get_fn_name(ast, scope, fn_name, multi)
952952- if (fn_name and (fn_name[1] ~= "nil")) then
953953- local _450_
954954- if not multi then
955955- _450_ = compiler["declare-local"](fn_name, {}, scope, ast)
956956- else
957957- _450_ = (compiler["symbol-to-expression"](fn_name, scope))[1]
958958- end
959959- return _450_, not multi, 3
960960- else
961961- return nil, true, 2
962962- end
963963- end
964964- local function compile_named_fn(ast, f_scope, f_chunk, parent, index, fn_name, local_3f, arg_name_list, f_metadata)
965965- for i = (index + 1), #ast do
966966- compiler.compile1(ast[i], f_scope, f_chunk, {nval = (((i ~= #ast) and 0) or nil), tail = (i == #ast)})
967967- end
968968- local _453_
969969- if local_3f then
970970- _453_ = "local function %s(%s)"
971971- else
972972- _453_ = "%s = function(%s)"
973973- end
974974- compiler.emit(parent, string.format(_453_, fn_name, table.concat(arg_name_list, ", ")), ast)
975975- compiler.emit(parent, f_chunk, ast)
976976- compiler.emit(parent, "end", ast)
977977- set_fn_metadata(f_metadata["fnl/arglist"], f_metadata["fnl/docstring"], parent, fn_name)
978978- utils.hook("fn", ast, f_scope)
979979- return utils.expr(fn_name, "sym")
980980- end
981981- local function compile_anonymous_fn(ast, f_scope, f_chunk, parent, index, arg_name_list, f_metadata, scope)
982982- local fn_name = compiler.gensym(scope)
983983- return compile_named_fn(ast, f_scope, f_chunk, parent, index, fn_name, true, arg_name_list, f_metadata)
984984- end
985985- local function get_function_metadata(ast, arg_list, index)
986986- local f_metadata = {["fnl/arglist"] = arg_list}
987987- local index_2a = (index + 1)
988988- local expr = ast[index_2a]
989989- if (utils["string?"](expr) and (index_2a < #ast)) then
990990- local _456_
991991- do
992992- local _455_ = f_metadata
993993- _455_["fnl/docstring"] = expr
994994- _456_ = _455_
995995- end
996996- return _456_, index_2a
997997- elseif (utils["table?"](expr) and (index_2a < #ast)) then
998998- local _457_
999999- do
10001000- local tbl_11_auto = f_metadata
10011001- for k, v in pairs(expr) do
10021002- local _458_, _459_ = k, v
10031003- if ((nil ~= _458_) and (nil ~= _459_)) then
10041004- local k_12_auto = _458_
10051005- local v_13_auto = _459_
10061006- tbl_11_auto[k_12_auto] = v_13_auto
10071007- else
10081008- end
10091009- end
10101010- _457_ = tbl_11_auto
10111011- end
10121012- return _457_, index_2a
10131013- else
10141014- return f_metadata, index
10151015- end
10161016- end
10171017- SPECIALS.fn = function(ast, scope, parent)
10181018- local f_scope
10191019- do
10201020- local _462_ = compiler["make-scope"](scope)
10211021- do end (_462_)["vararg"] = false
10221022- f_scope = _462_
10231023- end
10241024- local f_chunk = {}
10251025- local fn_sym = utils["sym?"](ast[2])
10261026- local multi = (fn_sym and utils["multi-sym?"](fn_sym[1]))
10271027- local fn_name, local_3f, index = get_fn_name(ast, scope, fn_sym, multi)
10281028- local arg_list = compiler.assert(utils["table?"](ast[index]), "expected parameters table", ast)
10291029- compiler.assert((not multi or not multi["multi-sym-method-call"]), ("unexpected multi symbol " .. tostring(fn_name)), fn_sym)
10301030- local function get_arg_name(arg)
10311031- if utils["varg?"](arg) then
10321032- compiler.assert((arg == arg_list[#arg_list]), "expected vararg as last parameter", ast)
10331033- f_scope.vararg = true
10341034- return "..."
10351035- elseif (utils["sym?"](arg) and (tostring(arg) ~= "nil") and not utils["multi-sym?"](tostring(arg))) then
10361036- return compiler["declare-local"](arg, {}, f_scope, ast)
10371037- elseif utils["table?"](arg) then
10381038- local raw = utils.sym(compiler.gensym(scope))
10391039- local declared = compiler["declare-local"](raw, {}, f_scope, ast)
10401040- compiler.destructure(arg, raw, ast, f_scope, f_chunk, {declaration = true, nomulti = true, symtype = "arg"})
10411041- return declared
10421042- else
10431043- return compiler.assert(false, ("expected symbol for function parameter: %s"):format(tostring(arg)), ast[index])
10441044- end
10451045- end
10461046- local arg_name_list = utils.map(arg_list, get_arg_name)
10471047- local f_metadata, index0 = get_function_metadata(ast, arg_list, index)
10481048- if fn_name then
10491049- return compile_named_fn(ast, f_scope, f_chunk, parent, index0, fn_name, local_3f, arg_name_list, f_metadata)
10501050- else
10511051- return compile_anonymous_fn(ast, f_scope, f_chunk, parent, index0, arg_name_list, f_metadata, scope)
10521052- end
10531053- end
10541054- doc_special("fn", {"name?", "args", "docstring?", "..."}, "Function syntax. May optionally include a name and docstring or a metadata table.\nIf a name is provided, the function will be bound in the current scope.\nWhen called with the wrong number of args, excess args will be discarded\nand lacking args will be nil, use lambda for arity-checked functions.", true)
10551055- SPECIALS.lua = function(ast, _, parent)
10561056- compiler.assert(((#ast == 2) or (#ast == 3)), "expected 1 or 2 arguments", ast)
10571057- local _466_
10581058- do
10591059- local _465_ = utils["sym?"](ast[2])
10601060- if (nil ~= _465_) then
10611061- _466_ = tostring(_465_)
10621062- else
10631063- _466_ = _465_
10641064- end
10651065- end
10661066- if ("nil" ~= _466_) then
10671067- table.insert(parent, {ast = ast, leaf = tostring(ast[2])})
10681068- else
10691069- end
10701070- local _470_
10711071- do
10721072- local _469_ = utils["sym?"](ast[3])
10731073- if (nil ~= _469_) then
10741074- _470_ = tostring(_469_)
10751075- else
10761076- _470_ = _469_
10771077- end
10781078- end
10791079- if ("nil" ~= _470_) then
10801080- return tostring(ast[3])
10811081- else
10821082- return nil
10831083- end
10841084- end
10851085- local function dot(ast, scope, parent)
10861086- compiler.assert((1 < #ast), "expected table argument", ast)
10871087- local len = #ast
10881088- local _let_473_ = compiler.compile1(ast[2], scope, parent, {nval = 1})
10891089- local lhs = _let_473_[1]
10901090- if (len == 2) then
10911091- return tostring(lhs)
10921092- else
10931093- local indices = {}
10941094- for i = 3, len do
10951095- local index = ast[i]
10961096- if (utils["string?"](index) and utils["valid-lua-identifier?"](index)) then
10971097- table.insert(indices, ("." .. index))
10981098- else
10991099- local _let_474_ = compiler.compile1(index, scope, parent, {nval = 1})
11001100- local index0 = _let_474_[1]
11011101- table.insert(indices, ("[" .. tostring(index0) .. "]"))
11021102- end
11031103- end
11041104- if (tostring(lhs):find("[{\"0-9]") or ("nil" == tostring(lhs))) then
11051105- return ("(" .. tostring(lhs) .. ")" .. table.concat(indices))
11061106- else
11071107- return (tostring(lhs) .. table.concat(indices))
11081108- end
11091109- end
11101110- end
11111111- SPECIALS["."] = dot
11121112- doc_special(".", {"tbl", "key1", "..."}, "Look up key1 in tbl table. If more args are provided, do a nested lookup.")
11131113- SPECIALS.global = function(ast, scope, parent)
11141114- compiler.assert((#ast == 3), "expected name and value", ast)
11151115- compiler.destructure(ast[2], ast[3], ast, scope, parent, {forceglobal = true, nomulti = true, symtype = "global"})
11161116- return nil
11171117- end
11181118- doc_special("global", {"name", "val"}, "Set name as a global with val.")
11191119- SPECIALS.set = function(ast, scope, parent)
11201120- compiler.assert((#ast == 3), "expected name and value", ast)
11211121- compiler.destructure(ast[2], ast[3], ast, scope, parent, {noundef = true, symtype = "set"})
11221122- return nil
11231123- end
11241124- doc_special("set", {"name", "val"}, "Set a local variable to a new value. Only works on locals using var.")
11251125- local function set_forcibly_21_2a(ast, scope, parent)
11261126- compiler.assert((#ast == 3), "expected name and value", ast)
11271127- compiler.destructure(ast[2], ast[3], ast, scope, parent, {forceset = true, symtype = "set"})
11281128- return nil
11291129- end
11301130- SPECIALS["set-forcibly!"] = set_forcibly_21_2a
11311131- local function local_2a(ast, scope, parent)
11321132- compiler.assert((#ast == 3), "expected name and value", ast)
11331133- compiler.destructure(ast[2], ast[3], ast, scope, parent, {declaration = true, nomulti = true, symtype = "local"})
11341134- return nil
11351135- end
11361136- SPECIALS["local"] = local_2a
11371137- doc_special("local", {"name", "val"}, "Introduce new top-level immutable local.")
11381138- SPECIALS.var = function(ast, scope, parent)
11391139- compiler.assert((#ast == 3), "expected name and value", ast)
11401140- compiler.destructure(ast[2], ast[3], ast, scope, parent, {declaration = true, isvar = true, nomulti = true, symtype = "var"})
11411141- return nil
11421142- end
11431143- doc_special("var", {"name", "val"}, "Introduce new mutable local.")
11441144- local function kv_3f(t)
11451145- local _478_
11461146- do
11471147- local tbl_14_auto = {}
11481148- local i_15_auto = #tbl_14_auto
11491149- for k in pairs(t) do
11501150- local val_16_auto
11511151- if ("number" ~= type(k)) then
11521152- val_16_auto = k
11531153- else
11541154- val_16_auto = nil
11551155- end
11561156- if (nil ~= val_16_auto) then
11571157- i_15_auto = (i_15_auto + 1)
11581158- do end (tbl_14_auto)[i_15_auto] = val_16_auto
11591159- else
11601160- end
11611161- end
11621162- _478_ = tbl_14_auto
11631163- end
11641164- return (_478_)[1]
11651165- end
11661166- SPECIALS.let = function(ast, scope, parent, opts)
11671167- local bindings = ast[2]
11681168- local pre_syms = {}
11691169- compiler.assert((utils["table?"](bindings) and not kv_3f(bindings)), "expected binding sequence", bindings)
11701170- compiler.assert(((#bindings % 2) == 0), "expected even number of name/value bindings", ast[2])
11711171- compiler.assert((3 <= #ast), "expected body expression", ast[1])
11721172- for _ = 1, (opts.nval or 0) do
11731173- table.insert(pre_syms, compiler.gensym(scope))
11741174- end
11751175- local sub_scope = compiler["make-scope"](scope)
11761176- local sub_chunk = {}
11771177- for i = 1, #bindings, 2 do
11781178- compiler.destructure(bindings[i], bindings[(i + 1)], ast, sub_scope, sub_chunk, {declaration = true, nomulti = true, symtype = "let"})
11791179- end
11801180- return SPECIALS["do"](ast, scope, parent, opts, 3, sub_chunk, sub_scope, pre_syms)
11811181- end
11821182- doc_special("let", {"[name1 val1 ... nameN valN]", "..."}, "Introduces a new scope in which a given set of local bindings are used.", true)
11831183- local function get_prev_line(parent)
11841184- if ("table" == type(parent)) then
11851185- return get_prev_line((parent.leaf or parent[#parent]))
11861186- else
11871187- return (parent or "")
11881188- end
11891189- end
11901190- local function disambiguate_3f(rootstr, parent)
11911191- local function _483_()
11921192- local _482_ = get_prev_line(parent)
11931193- if (nil ~= _482_) then
11941194- local prev_line = _482_
11951195- return prev_line:match("%)$")
11961196- else
11971197- return nil
11981198- end
11991199- end
12001200- return (rootstr:match("^{") or _483_())
12011201- end
12021202- SPECIALS.tset = function(ast, scope, parent)
12031203- compiler.assert((3 < #ast), "expected table, key, and value arguments", ast)
12041204- local root = (compiler.compile1(ast[2], scope, parent, {nval = 1}))[1]
12051205- local keys = {}
12061206- for i = 3, (#ast - 1) do
12071207- local _let_485_ = compiler.compile1(ast[i], scope, parent, {nval = 1})
12081208- local key = _let_485_[1]
12091209- table.insert(keys, tostring(key))
12101210- end
12111211- local value = (compiler.compile1(ast[#ast], scope, parent, {nval = 1}))[1]
12121212- local rootstr = tostring(root)
12131213- local fmtstr
12141214- if disambiguate_3f(rootstr, parent) then
12151215- fmtstr = "do end (%s)[%s] = %s"
12161216- else
12171217- fmtstr = "%s[%s] = %s"
12181218- end
12191219- return compiler.emit(parent, fmtstr:format(rootstr, table.concat(keys, "]["), tostring(value)), ast)
12201220- end
12211221- doc_special("tset", {"tbl", "key1", "...", "keyN", "val"}, "Set the value of a table field. Can take additional keys to set\nnested values, but all parents must contain an existing table.")
12221222- local function calculate_target(scope, opts)
12231223- if not (opts.tail or opts.target or opts.nval) then
12241224- return "iife", true, nil
12251225- elseif (opts.nval and (opts.nval ~= 0) and not opts.target) then
12261226- local accum = {}
12271227- local target_exprs = {}
12281228- for i = 1, opts.nval do
12291229- local s = compiler.gensym(scope)
12301230- do end (accum)[i] = s
12311231- target_exprs[i] = utils.expr(s, "sym")
12321232- end
12331233- return "target", opts.tail, table.concat(accum, ", "), target_exprs
12341234- else
12351235- return "none", opts.tail, opts.target
12361236- end
12371237- end
12381238- local function if_2a(ast, scope, parent, opts)
12391239- compiler.assert((2 < #ast), "expected condition and body", ast)
12401240- local do_scope = compiler["make-scope"](scope)
12411241- local branches = {}
12421242- local wrapper, inner_tail, inner_target, target_exprs = calculate_target(scope, opts)
12431243- local body_opts = {nval = opts.nval, tail = inner_tail, target = inner_target}
12441244- local function compile_body(i)
12451245- local chunk = {}
12461246- local cscope = compiler["make-scope"](do_scope)
12471247- compiler["keep-side-effects"](compiler.compile1(ast[i], cscope, chunk, body_opts), chunk, nil, ast[i])
12481248- return {chunk = chunk, scope = cscope}
12491249- end
12501250- if (1 == (#ast % 2)) then
12511251- table.insert(ast, utils.sym("nil"))
12521252- else
12531253- end
12541254- for i = 2, (#ast - 1), 2 do
12551255- local condchunk = {}
12561256- local res = compiler.compile1(ast[i], do_scope, condchunk, {nval = 1})
12571257- local cond = res[1]
12581258- local branch = compile_body((i + 1))
12591259- branch.cond = cond
12601260- branch.condchunk = condchunk
12611261- branch.nested = ((i ~= 2) and (next(condchunk, nil) == nil))
12621262- table.insert(branches, branch)
12631263- end
12641264- local else_branch = compile_body(#ast)
12651265- local s = compiler.gensym(scope)
12661266- local buffer = {}
12671267- local last_buffer = buffer
12681268- for i = 1, #branches do
12691269- local branch = branches[i]
12701270- local fstr
12711271- if not branch.nested then
12721272- fstr = "if %s then"
12731273- else
12741274- fstr = "elseif %s then"
12751275- end
12761276- local cond = tostring(branch.cond)
12771277- local cond_line = fstr:format(cond)
12781278- if branch.nested then
12791279- compiler.emit(last_buffer, branch.condchunk, ast)
12801280- else
12811281- for _, v in ipairs(branch.condchunk) do
12821282- compiler.emit(last_buffer, v, ast)
12831283- end
12841284- end
12851285- compiler.emit(last_buffer, cond_line, ast)
12861286- compiler.emit(last_buffer, branch.chunk, ast)
12871287- if (i == #branches) then
12881288- compiler.emit(last_buffer, "else", ast)
12891289- compiler.emit(last_buffer, else_branch.chunk, ast)
12901290- compiler.emit(last_buffer, "end", ast)
12911291- elseif not (branches[(i + 1)]).nested then
12921292- local next_buffer = {}
12931293- compiler.emit(last_buffer, "else", ast)
12941294- compiler.emit(last_buffer, next_buffer, ast)
12951295- compiler.emit(last_buffer, "end", ast)
12961296- last_buffer = next_buffer
12971297- else
12981298- end
12991299- end
13001300- if (wrapper == "iife") then
13011301- local iifeargs = ((scope.vararg and "...") or "")
13021302- compiler.emit(parent, ("local function %s(%s)"):format(tostring(s), iifeargs), ast)
13031303- compiler.emit(parent, buffer, ast)
13041304- compiler.emit(parent, "end", ast)
13051305- return utils.expr(("%s(%s)"):format(tostring(s), iifeargs), "statement")
13061306- elseif (wrapper == "none") then
13071307- for i = 1, #buffer do
13081308- compiler.emit(parent, buffer[i], ast)
13091309- end
13101310- return {returned = true}
13111311- else
13121312- compiler.emit(parent, ("local %s"):format(inner_target), ast)
13131313- for i = 1, #buffer do
13141314- compiler.emit(parent, buffer[i], ast)
13151315- end
13161316- return target_exprs
13171317- end
13181318- end
13191319- SPECIALS["if"] = if_2a
13201320- doc_special("if", {"cond1", "body1", "...", "condN", "bodyN"}, "Conditional form.\nTakes any number of condition/body pairs and evaluates the first body where\nthe condition evaluates to truthy. Similar to cond in other lisps.")
13211321- local function remove_until_condition(bindings)
13221322- local last_item = bindings[(#bindings - 1)]
13231323- if ((utils["sym?"](last_item) and (tostring(last_item) == "&until")) or ("until" == last_item)) then
13241324- table.remove(bindings, (#bindings - 1))
13251325- return table.remove(bindings)
13261326- else
13271327- return nil
13281328- end
13291329- end
13301330- local function compile_until(condition, scope, chunk)
13311331- if condition then
13321332- local _let_494_ = compiler.compile1(condition, scope, chunk, {nval = 1})
13331333- local condition_lua = _let_494_[1]
13341334- return compiler.emit(chunk, ("if %s then break end"):format(tostring(condition_lua)), utils.expr(condition, "expression"))
13351335- else
13361336- return nil
13371337- end
13381338- end
13391339- SPECIALS.each = function(ast, scope, parent)
13401340- compiler.assert((3 <= #ast), "expected body expression", ast[1])
13411341- local binding = compiler.assert(utils["table?"](ast[2]), "expected binding table", ast)
13421342- local _ = compiler.assert((2 <= #binding), "expected binding and iterator", binding)
13431343- local until_condition = remove_until_condition(binding)
13441344- local iter = table.remove(binding, #binding)
13451345- local destructures = {}
13461346- local new_manglings = {}
13471347- local sub_scope = compiler["make-scope"](scope)
13481348- local function destructure_binding(v)
13491349- compiler.assert(not utils["string?"](v), ("unexpected iterator clause " .. tostring(v)), binding)
13501350- if utils["sym?"](v) then
13511351- return compiler["declare-local"](v, {}, sub_scope, ast, new_manglings)
13521352- else
13531353- local raw = utils.sym(compiler.gensym(sub_scope))
13541354- do end (destructures)[raw] = v
13551355- return compiler["declare-local"](raw, {}, sub_scope, ast)
13561356- end
13571357- end
13581358- local bind_vars = utils.map(binding, destructure_binding)
13591359- local vals = compiler.compile1(iter, scope, parent)
13601360- local val_names = utils.map(vals, tostring)
13611361- local chunk = {}
13621362- compiler.emit(parent, ("for %s in %s do"):format(table.concat(bind_vars, ", "), table.concat(val_names, ", ")), ast)
13631363- for raw, args in utils.stablepairs(destructures) do
13641364- compiler.destructure(args, raw, ast, sub_scope, chunk, {declaration = true, nomulti = true, symtype = "each"})
13651365- end
13661366- compiler["apply-manglings"](sub_scope, new_manglings, ast)
13671367- compile_until(until_condition, sub_scope, chunk)
13681368- compile_do(ast, sub_scope, chunk, 3)
13691369- compiler.emit(parent, chunk, ast)
13701370- return compiler.emit(parent, "end", ast)
13711371- end
13721372- doc_special("each", {"[key value (iterator)]", "..."}, "Runs the body once for each set of values provided by the given iterator.\nMost commonly used with ipairs for sequential tables or pairs for undefined\norder, but can be used with any iterator.", true)
13731373- local function while_2a(ast, scope, parent)
13741374- local len1 = #parent
13751375- local condition = (compiler.compile1(ast[2], scope, parent, {nval = 1}))[1]
13761376- local len2 = #parent
13771377- local sub_chunk = {}
13781378- if (len1 ~= len2) then
13791379- for i = (len1 + 1), len2 do
13801380- table.insert(sub_chunk, parent[i])
13811381- do end (parent)[i] = nil
13821382- end
13831383- compiler.emit(parent, "while true do", ast)
13841384- compiler.emit(sub_chunk, ("if not %s then break end"):format(condition[1]), ast)
13851385- else
13861386- compiler.emit(parent, ("while " .. tostring(condition) .. " do"), ast)
13871387- end
13881388- compile_do(ast, compiler["make-scope"](scope), sub_chunk, 3)
13891389- compiler.emit(parent, sub_chunk, ast)
13901390- return compiler.emit(parent, "end", ast)
13911391- end
13921392- SPECIALS["while"] = while_2a
13931393- doc_special("while", {"condition", "..."}, "The classic while loop. Evaluates body until a condition is non-truthy.", true)
13941394- local function for_2a(ast, scope, parent)
13951395- local ranges = compiler.assert(utils["table?"](ast[2]), "expected binding table", ast)
13961396- local until_condition = remove_until_condition(ast[2])
13971397- local binding_sym = table.remove(ast[2], 1)
13981398- local sub_scope = compiler["make-scope"](scope)
13991399- local range_args = {}
14001400- local chunk = {}
14011401- compiler.assert(utils["sym?"](binding_sym), ("unable to bind %s %s"):format(type(binding_sym), tostring(binding_sym)), ast[2])
14021402- compiler.assert((3 <= #ast), "expected body expression", ast[1])
14031403- compiler.assert((#ranges <= 3), "unexpected arguments", ranges[4])
14041404- for i = 1, math.min(#ranges, 3) do
14051405- range_args[i] = tostring((compiler.compile1(ranges[i], scope, parent, {nval = 1}))[1])
14061406- end
14071407- compiler.emit(parent, ("for %s = %s do"):format(compiler["declare-local"](binding_sym, {}, sub_scope, ast), table.concat(range_args, ", ")), ast)
14081408- compile_until(until_condition, sub_scope, chunk)
14091409- compile_do(ast, sub_scope, chunk, 3)
14101410- compiler.emit(parent, chunk, ast)
14111411- return compiler.emit(parent, "end", ast)
14121412- end
14131413- SPECIALS["for"] = for_2a
14141414- doc_special("for", {"[index start stop step?]", "..."}, "Numeric loop construct.\nEvaluates body once for each value between start and stop (inclusive).", true)
14151415- local function native_method_call(ast, _scope, _parent, target, args)
14161416- local _let_498_ = ast
14171417- local _ = _let_498_[1]
14181418- local _0 = _let_498_[2]
14191419- local method_string = _let_498_[3]
14201420- local call_string
14211421- if ((target.type == "literal") or (target.type == "varg") or (target.type == "expression")) then
14221422- call_string = "(%s):%s(%s)"
14231423- else
14241424- call_string = "%s:%s(%s)"
14251425- end
14261426- return utils.expr(string.format(call_string, tostring(target), method_string, table.concat(args, ", ")), "statement")
14271427- end
14281428- local function nonnative_method_call(ast, scope, parent, target, args)
14291429- local method_string = tostring((compiler.compile1(ast[3], scope, parent, {nval = 1}))[1])
14301430- local args0 = {tostring(target), unpack(args)}
14311431- return utils.expr(string.format("%s[%s](%s)", tostring(target), method_string, table.concat(args0, ", ")), "statement")
14321432- end
14331433- local function double_eval_protected_method_call(ast, scope, parent, target, args)
14341434- local method_string = tostring((compiler.compile1(ast[3], scope, parent, {nval = 1}))[1])
14351435- local call = "(function(tgt, m, ...) return tgt[m](tgt, ...) end)(%s, %s)"
14361436- table.insert(args, 1, method_string)
14371437- return utils.expr(string.format(call, tostring(target), table.concat(args, ", ")), "statement")
14381438- end
14391439- local function method_call(ast, scope, parent)
14401440- compiler.assert((2 < #ast), "expected at least 2 arguments", ast)
14411441- local _let_500_ = compiler.compile1(ast[2], scope, parent, {nval = 1})
14421442- local target = _let_500_[1]
14431443- local args = {}
14441444- for i = 4, #ast do
14451445- local subexprs
14461446- local _501_
14471447- if (i ~= #ast) then
14481448- _501_ = 1
14491449- else
14501450- _501_ = nil
14511451- end
14521452- subexprs = compiler.compile1(ast[i], scope, parent, {nval = _501_})
14531453- utils.map(subexprs, tostring, args)
14541454- end
14551455- if (utils["string?"](ast[3]) and utils["valid-lua-identifier?"](ast[3])) then
14561456- return native_method_call(ast, scope, parent, target, args)
14571457- elseif (target.type == "sym") then
14581458- return nonnative_method_call(ast, scope, parent, target, args)
14591459- else
14601460- return double_eval_protected_method_call(ast, scope, parent, target, args)
14611461- end
14621462- end
14631463- SPECIALS[":"] = method_call
14641464- doc_special(":", {"tbl", "method-name", "..."}, "Call the named method on tbl with the provided args.\nMethod name doesn't have to be known at compile-time; if it is, use\n(tbl:method-name ...) instead.")
14651465- SPECIALS.comment = function(ast, _, parent)
14661466- local els = {}
14671467- for i = 2, #ast do
14681468- table.insert(els, view(ast[i], {["one-line?"] = true}))
14691469- end
14701470- return compiler.emit(parent, ("--[[ " .. table.concat(els, " ") .. " ]]"), ast)
14711471- end
14721472- doc_special("comment", {"..."}, "Comment which will be emitted in Lua output.", true)
14731473- local function hashfn_max_used(f_scope, i, max)
14741474- local max0
14751475- if f_scope.symmeta[("$" .. i)].used then
14761476- max0 = i
14771477- else
14781478- max0 = max
14791479- end
14801480- if (i < 9) then
14811481- return hashfn_max_used(f_scope, (i + 1), max0)
14821482- else
14831483- return max0
14841484- end
14851485- end
14861486- SPECIALS.hashfn = function(ast, scope, parent)
14871487- compiler.assert((#ast == 2), "expected one argument", ast)
14881488- local f_scope
14891489- do
14901490- local _506_ = compiler["make-scope"](scope)
14911491- do end (_506_)["vararg"] = false
14921492- _506_["hashfn"] = true
14931493- f_scope = _506_
14941494- end
14951495- local f_chunk = {}
14961496- local name = compiler.gensym(scope)
14971497- local symbol = utils.sym(name)
14981498- local args = {}
14991499- compiler["declare-local"](symbol, {}, scope, ast)
15001500- for i = 1, 9 do
15011501- args[i] = compiler["declare-local"](utils.sym(("$" .. i)), {}, f_scope, ast)
15021502- end
15031503- local function walker(idx, node, parent_node)
15041504- if (utils["sym?"](node) and (tostring(node) == "$...")) then
15051505- parent_node[idx] = utils.varg()
15061506- f_scope.vararg = true
15071507- return nil
15081508- else
15091509- return (utils["list?"](node) or utils["table?"](node))
15101510- end
15111511- end
15121512- utils["walk-tree"](ast[2], walker)
15131513- compiler.compile1(ast[2], f_scope, f_chunk, {tail = true})
15141514- local max_used = hashfn_max_used(f_scope, 1, 0)
15151515- if f_scope.vararg then
15161516- compiler.assert((max_used == 0), "$ and $... in hashfn are mutually exclusive", ast)
15171517- else
15181518- end
15191519- local arg_str
15201520- if f_scope.vararg then
15211521- arg_str = tostring(utils.varg())
15221522- else
15231523- arg_str = table.concat(args, ", ", 1, max_used)
15241524- end
15251525- compiler.emit(parent, string.format("local function %s(%s)", name, arg_str), ast)
15261526- compiler.emit(parent, f_chunk, ast)
15271527- compiler.emit(parent, "end", ast)
15281528- return utils.expr(name, "sym")
15291529- end
15301530- doc_special("hashfn", {"..."}, "Function literal shorthand; args are either $... OR $1, $2, etc.")
15311531- local function maybe_short_circuit_protect(ast, i, name, _510_)
15321532- local _arg_511_ = _510_
15331533- local mac = _arg_511_["macros"]
15341534- local call = (utils["list?"](ast) and tostring(ast[1]))
15351535- if ((("or" == name) or ("and" == name)) and (1 < i) and (mac[call] or ("set" == call) or ("tset" == call) or ("global" == call))) then
15361536- return utils.list(utils.sym("do"), ast)
15371537- else
15381538- return ast
15391539- end
15401540- end
15411541- local function arithmetic_special(name, zero_arity, unary_prefix, ast, scope, parent)
15421542- local len = #ast
15431543- local operands = {}
15441544- local padded_op = (" " .. name .. " ")
15451545- for i = 2, len do
15461546- local subast = maybe_short_circuit_protect(ast[i], i, name, scope)
15471547- local subexprs = compiler.compile1(subast, scope, parent)
15481548- if (i == len) then
15491549- utils.map(subexprs, tostring, operands)
15501550- else
15511551- table.insert(operands, tostring(subexprs[1]))
15521552- end
15531553- end
15541554- local _514_ = #operands
15551555- if (_514_ == 0) then
15561556- local _516_
15571557- do
15581558- local _515_ = zero_arity
15591559- compiler.assert(_515_, "Expected more than 0 arguments", ast)
15601560- _516_ = _515_
15611561- end
15621562- return utils.expr(_516_, "literal")
15631563- elseif (_514_ == 1) then
15641564- if unary_prefix then
15651565- return ("(" .. unary_prefix .. padded_op .. operands[1] .. ")")
15661566- else
15671567- return operands[1]
15681568- end
15691569- elseif true then
15701570- local _ = _514_
15711571- return ("(" .. table.concat(operands, padded_op) .. ")")
15721572- else
15731573- return nil
15741574- end
15751575- end
15761576- local function define_arithmetic_special(name, zero_arity, unary_prefix, _3flua_name)
15771577- local _522_
15781578- do
15791579- local _519_ = (_3flua_name or name)
15801580- local _520_ = zero_arity
15811581- local _521_ = unary_prefix
15821582- local function _523_(...)
15831583- return arithmetic_special(_519_, _520_, _521_, ...)
15841584- end
15851585- _522_ = _523_
15861586- end
15871587- SPECIALS[name] = _522_
15881588- return doc_special(name, {"a", "b", "..."}, "Arithmetic operator; works the same as Lua but accepts more arguments.")
15891589- end
15901590- define_arithmetic_special("+", "0")
15911591- define_arithmetic_special("..", "''")
15921592- define_arithmetic_special("^")
15931593- define_arithmetic_special("-", nil, "")
15941594- define_arithmetic_special("*", "1")
15951595- define_arithmetic_special("%")
15961596- define_arithmetic_special("/", nil, "1")
15971597- define_arithmetic_special("//", nil, "1")
15981598- SPECIALS["or"] = function(ast, scope, parent)
15991599- return arithmetic_special("or", "false", nil, ast, scope, parent)
16001600- end
16011601- SPECIALS["and"] = function(ast, scope, parent)
16021602- return arithmetic_special("and", "true", nil, ast, scope, parent)
16031603- end
16041604- doc_special("and", {"a", "b", "..."}, "Boolean operator; works the same as Lua but accepts more arguments.")
16051605- doc_special("or", {"a", "b", "..."}, "Boolean operator; works the same as Lua but accepts more arguments.")
16061606- local function bitop_special(native_name, lib_name, zero_arity, unary_prefix, ast, scope, parent)
16071607- if (#ast == 1) then
16081608- return compiler.assert(zero_arity, "Expected more than 0 arguments.", ast)
16091609- else
16101610- local len = #ast
16111611- local operands = {}
16121612- local padded_native_name = (" " .. native_name .. " ")
16131613- local prefixed_lib_name = ("bit." .. lib_name)
16141614- for i = 2, len do
16151615- local subexprs
16161616- local _524_
16171617- if (i ~= len) then
16181618- _524_ = 1
16191619- else
16201620- _524_ = nil
16211621- end
16221622- subexprs = compiler.compile1(ast[i], scope, parent, {nval = _524_})
16231623- utils.map(subexprs, tostring, operands)
16241624- end
16251625- if (#operands == 1) then
16261626- if utils.root.options.useBitLib then
16271627- return (prefixed_lib_name .. "(" .. unary_prefix .. ", " .. operands[1] .. ")")
16281628- else
16291629- return ("(" .. unary_prefix .. padded_native_name .. operands[1] .. ")")
16301630- end
16311631- else
16321632- if utils.root.options.useBitLib then
16331633- return (prefixed_lib_name .. "(" .. table.concat(operands, ", ") .. ")")
16341634- else
16351635- return ("(" .. table.concat(operands, padded_native_name) .. ")")
16361636- end
16371637- end
16381638- end
16391639- end
16401640- local function define_bitop_special(name, zero_arity, unary_prefix, native)
16411641- local _534_
16421642- do
16431643- local _530_ = native
16441644- local _531_ = name
16451645- local _532_ = zero_arity
16461646- local _533_ = unary_prefix
16471647- local function _535_(...)
16481648- return bitop_special(_530_, _531_, _532_, _533_, ...)
16491649- end
16501650- _534_ = _535_
16511651- end
16521652- SPECIALS[name] = _534_
16531653- return nil
16541654- end
16551655- define_bitop_special("lshift", nil, "1", "<<")
16561656- define_bitop_special("rshift", nil, "1", ">>")
16571657- define_bitop_special("band", "0", "0", "&")
16581658- define_bitop_special("bor", "0", "0", "|")
16591659- define_bitop_special("bxor", "0", "0", "~")
16601660- doc_special("lshift", {"x", "n"}, "Bitwise logical left shift of x by n bits.\nOnly works in Lua 5.3+ or LuaJIT with the --use-bit-lib flag.")
16611661- doc_special("rshift", {"x", "n"}, "Bitwise logical right shift of x by n bits.\nOnly works in Lua 5.3+ or LuaJIT with the --use-bit-lib flag.")
16621662- doc_special("band", {"x1", "x2", "..."}, "Bitwise AND of any number of arguments.\nOnly works in Lua 5.3+ or LuaJIT with the --use-bit-lib flag.")
16631663- doc_special("bor", {"x1", "x2", "..."}, "Bitwise OR of any number of arguments.\nOnly works in Lua 5.3+ or LuaJIT with the --use-bit-lib flag.")
16641664- doc_special("bxor", {"x1", "x2", "..."}, "Bitwise XOR of any number of arguments.\nOnly works in Lua 5.3+ or LuaJIT with the --use-bit-lib flag.")
16651665- doc_special("..", {"a", "b", "..."}, "String concatenation operator; works the same as Lua but accepts more arguments.")
16661666- local function native_comparator(op, _536_, scope, parent)
16671667- local _arg_537_ = _536_
16681668- local _ = _arg_537_[1]
16691669- local lhs_ast = _arg_537_[2]
16701670- local rhs_ast = _arg_537_[3]
16711671- local _let_538_ = compiler.compile1(lhs_ast, scope, parent, {nval = 1})
16721672- local lhs = _let_538_[1]
16731673- local _let_539_ = compiler.compile1(rhs_ast, scope, parent, {nval = 1})
16741674- local rhs = _let_539_[1]
16751675- return string.format("(%s %s %s)", tostring(lhs), op, tostring(rhs))
16761676- end
16771677- local function double_eval_protected_comparator(op, chain_op, ast, scope, parent)
16781678- local arglist = {}
16791679- local comparisons = {}
16801680- local vals = {}
16811681- local chain = string.format(" %s ", (chain_op or "and"))
16821682- for i = 2, #ast do
16831683- table.insert(arglist, tostring(compiler.gensym(scope)))
16841684- table.insert(vals, tostring((compiler.compile1(ast[i], scope, parent, {nval = 1}))[1]))
16851685- end
16861686- for i = 1, (#arglist - 1) do
16871687- table.insert(comparisons, string.format("(%s %s %s)", arglist[i], op, arglist[(i + 1)]))
16881688- end
16891689- return string.format("(function(%s) return %s end)(%s)", table.concat(arglist, ","), table.concat(comparisons, chain), table.concat(vals, ","))
16901690- end
16911691- local function define_comparator_special(name, _3flua_op, _3fchain_op)
16921692- do
16931693- local op = (_3flua_op or name)
16941694- local function opfn(ast, scope, parent)
16951695- compiler.assert((2 < #ast), "expected at least two arguments", ast)
16961696- if (3 == #ast) then
16971697- return native_comparator(op, ast, scope, parent)
16981698- else
16991699- return double_eval_protected_comparator(op, _3fchain_op, ast, scope, parent)
17001700- end
17011701- end
17021702- SPECIALS[name] = opfn
17031703- end
17041704- return doc_special(name, {"a", "b", "..."}, "Comparison operator; works the same as Lua but accepts more arguments.")
17051705- end
17061706- define_comparator_special(">")
17071707- define_comparator_special("<")
17081708- define_comparator_special(">=")
17091709- define_comparator_special("<=")
17101710- define_comparator_special("=", "==")
17111711- define_comparator_special("not=", "~=", "or")
17121712- local function define_unary_special(op, _3frealop)
17131713- local function opfn(ast, scope, parent)
17141714- compiler.assert((#ast == 2), "expected one argument", ast)
17151715- local tail = compiler.compile1(ast[2], scope, parent, {nval = 1})
17161716- return ((_3frealop or op) .. tostring(tail[1]))
17171717- end
17181718- SPECIALS[op] = opfn
17191719- return nil
17201720- end
17211721- define_unary_special("not", "not ")
17221722- doc_special("not", {"x"}, "Logical operator; works the same as Lua.")
17231723- define_unary_special("bnot", "~")
17241724- doc_special("bnot", {"x"}, "Bitwise negation; only works in Lua 5.3+ or LuaJIT with the --use-bit-lib flag.")
17251725- define_unary_special("length", "#")
17261726- doc_special("length", {"x"}, "Returns the length of a table or string.")
17271727- do end (SPECIALS)["~="] = SPECIALS["not="]
17281728- SPECIALS["#"] = SPECIALS.length
17291729- SPECIALS.quote = function(ast, scope, parent)
17301730- compiler.assert((#ast == 2), "expected one argument", ast)
17311731- local runtime, this_scope = true, scope
17321732- while this_scope do
17331733- this_scope = this_scope.parent
17341734- if (this_scope == compiler.scopes.compiler) then
17351735- runtime = false
17361736- else
17371737- end
17381738- end
17391739- return compiler["do-quote"](ast[2], scope, parent, runtime)
17401740- end
17411741- doc_special("quote", {"x"}, "Quasiquote the following form. Only works in macro/compiler scope.")
17421742- local macro_loaded = {}
17431743- local function safe_getmetatable(tbl)
17441744- local mt = getmetatable(tbl)
17451745- assert((mt ~= getmetatable("")), "Illegal metatable access!")
17461746- return mt
17471747- end
17481748- local safe_require = nil
17491749- local function safe_compiler_env()
17501750- local _543_
17511751- do
17521752- local _542_ = rawget(_G, "utf8")
17531753- if (nil ~= _542_) then
17541754- _543_ = utils.copy(_542_)
17551755- else
17561756- _543_ = _542_
17571757- end
17581758- end
17591759- return {table = utils.copy(table), math = utils.copy(math), string = utils.copy(string), pairs = utils.stablepairs, ipairs = ipairs, select = select, tostring = tostring, tonumber = tonumber, bit = rawget(_G, "bit"), pcall = pcall, xpcall = xpcall, next = next, print = print, type = type, assert = assert, error = error, setmetatable = setmetatable, getmetatable = safe_getmetatable, require = safe_require, rawlen = rawget(_G, "rawlen"), rawget = rawget, rawset = rawset, rawequal = rawequal, _VERSION = _VERSION, utf8 = _543_}
17601760- end
17611761- local function combined_mt_pairs(env)
17621762- local combined = {}
17631763- local _let_545_ = getmetatable(env)
17641764- local __index = _let_545_["__index"]
17651765- if ("table" == type(__index)) then
17661766- for k, v in pairs(__index) do
17671767- combined[k] = v
17681768- end
17691769- else
17701770- end
17711771- for k, v in next, env, nil do
17721772- combined[k] = v
17731773- end
17741774- return next, combined, nil
17751775- end
17761776- local function make_compiler_env(ast, scope, parent, _3fopts)
17771777- local provided
17781778- do
17791779- local _547_ = (_3fopts or utils.root.options)
17801780- if ((_G.type(_547_) == "table") and ((_547_)["compiler-env"] == "strict")) then
17811781- provided = safe_compiler_env()
17821782- elseif ((_G.type(_547_) == "table") and (nil ~= (_547_).compilerEnv)) then
17831783- local compilerEnv = (_547_).compilerEnv
17841784- provided = compilerEnv
17851785- elseif ((_G.type(_547_) == "table") and (nil ~= (_547_)["compiler-env"])) then
17861786- local compiler_env = (_547_)["compiler-env"]
17871787- provided = compiler_env
17881788- elseif true then
17891789- local _ = _547_
17901790- provided = safe_compiler_env(false)
17911791- else
17921792- provided = nil
17931793- end
17941794- end
17951795- local env
17961796- local function _549_(base)
17971797- return utils.sym(compiler.gensym((compiler.scopes.macro or scope), base))
17981798- end
17991799- local function _550_()
18001800- return compiler.scopes.macro
18011801- end
18021802- local function _551_(symbol)
18031803- compiler.assert(compiler.scopes.macro, "must call from macro", ast)
18041804- return compiler.scopes.macro.manglings[tostring(symbol)]
18051805- end
18061806- local function _552_(form)
18071807- compiler.assert(compiler.scopes.macro, "must call from macro", ast)
18081808- return compiler.macroexpand(form, compiler.scopes.macro)
18091809- end
18101810- env = {_AST = ast, _CHUNK = parent, _IS_COMPILER = true, _SCOPE = scope, _SPECIALS = compiler.scopes.global.specials, _VARARG = utils.varg(), ["macro-loaded"] = macro_loaded, unpack = unpack, ["assert-compile"] = compiler.assert, view = view, version = utils.version, metadata = compiler.metadata, ["ast-source"] = utils["ast-source"], list = utils.list, ["list?"] = utils["list?"], ["table?"] = utils["table?"], sequence = utils.sequence, ["sequence?"] = utils["sequence?"], sym = utils.sym, ["sym?"] = utils["sym?"], ["multi-sym?"] = utils["multi-sym?"], comment = utils.comment, ["comment?"] = utils["comment?"], ["varg?"] = utils["varg?"], gensym = _549_, ["get-scope"] = _550_, ["in-scope?"] = _551_, macroexpand = _552_}
18111811- env._G = env
18121812- return setmetatable(env, {__index = provided, __newindex = provided, __pairs = combined_mt_pairs})
18131813- end
18141814- local function _554_(...)
18151815- local tbl_14_auto = {}
18161816- local i_15_auto = #tbl_14_auto
18171817- for c in string.gmatch((package.config or ""), "([^\n]+)") do
18181818- local val_16_auto = c
18191819- if (nil ~= val_16_auto) then
18201820- i_15_auto = (i_15_auto + 1)
18211821- do end (tbl_14_auto)[i_15_auto] = val_16_auto
18221822- else
18231823- end
18241824- end
18251825- return tbl_14_auto
18261826- end
18271827- local _local_553_ = _554_(...)
18281828- local dirsep = _local_553_[1]
18291829- local pathsep = _local_553_[2]
18301830- local pathmark = _local_553_[3]
18311831- local pkg_config = {dirsep = (dirsep or "/"), pathmark = (pathmark or ";"), pathsep = (pathsep or "?")}
18321832- local function escapepat(str)
18331833- return string.gsub(str, "[^%w]", "%%%1")
18341834- end
18351835- local function search_module(modulename, _3fpathstring)
18361836- local pathsepesc = escapepat(pkg_config.pathsep)
18371837- local pattern = ("([^%s]*)%s"):format(pathsepesc, pathsepesc)
18381838- local no_dot_module = modulename:gsub("%.", pkg_config.dirsep)
18391839- local fullpath = ((_3fpathstring or utils["fennel-module"].path) .. pkg_config.pathsep)
18401840- local function try_path(path)
18411841- local filename = path:gsub(escapepat(pkg_config.pathmark), no_dot_module)
18421842- local filename2 = path:gsub(escapepat(pkg_config.pathmark), modulename)
18431843- local _556_ = (io.open(filename) or io.open(filename2))
18441844- if (nil ~= _556_) then
18451845- local file = _556_
18461846- file:close()
18471847- return filename
18481848- elseif true then
18491849- local _ = _556_
18501850- return nil, ("no file '" .. filename .. "'")
18511851- else
18521852- return nil
18531853- end
18541854- end
18551855- local function find_in_path(start, _3ftried_paths)
18561856- local _558_ = fullpath:match(pattern, start)
18571857- if (nil ~= _558_) then
18581858- local path = _558_
18591859- local _559_, _560_ = try_path(path)
18601860- if (nil ~= _559_) then
18611861- local filename = _559_
18621862- return filename
18631863- elseif ((_559_ == nil) and (nil ~= _560_)) then
18641864- local error = _560_
18651865- local function _562_()
18661866- local _561_ = (_3ftried_paths or {})
18671867- table.insert(_561_, error)
18681868- return _561_
18691869- end
18701870- return find_in_path((start + #path + 1), _562_())
18711871- else
18721872- return nil
18731873- end
18741874- elseif true then
18751875- local _ = _558_
18761876- local function _564_()
18771877- local tried_paths = table.concat((_3ftried_paths or {}), "\n\9")
18781878- if (_VERSION < "Lua 5.4") then
18791879- return ("\n\9" .. tried_paths)
18801880- else
18811881- return tried_paths
18821882- end
18831883- end
18841884- return nil, _564_()
18851885- else
18861886- return nil
18871887- end
18881888- end
18891889- return find_in_path(1)
18901890- end
18911891- local function make_searcher(_3foptions)
18921892- local function _567_(module_name)
18931893- local opts = utils.copy(utils.root.options)
18941894- for k, v in pairs((_3foptions or {})) do
18951895- opts[k] = v
18961896- end
18971897- opts["module-name"] = module_name
18981898- local _568_, _569_ = search_module(module_name)
18991899- if (nil ~= _568_) then
19001900- local filename = _568_
19011901- local _572_
19021902- do
19031903- local _570_ = filename
19041904- local _571_ = opts
19051905- local function _573_(...)
19061906- return utils["fennel-module"].dofile(_570_, _571_, ...)
19071907- end
19081908- _572_ = _573_
19091909- end
19101910- return _572_, filename
19111911- elseif ((_568_ == nil) and (nil ~= _569_)) then
19121912- local error = _569_
19131913- return error
19141914- else
19151915- return nil
19161916- end
19171917- end
19181918- return _567_
19191919- end
19201920- local function dofile_with_searcher(fennel_macro_searcher, filename, opts, ...)
19211921- local searchers = (package.loaders or package.searchers or {})
19221922- local _ = table.insert(searchers, 1, fennel_macro_searcher)
19231923- local m = utils["fennel-module"].dofile(filename, opts, ...)
19241924- table.remove(searchers, 1)
19251925- return m
19261926- end
19271927- local function fennel_macro_searcher(module_name)
19281928- local opts
19291929- do
19301930- local _575_ = utils.copy(utils.root.options)
19311931- do end (_575_)["module-name"] = module_name
19321932- _575_["env"] = "_COMPILER"
19331933- _575_["requireAsInclude"] = false
19341934- _575_["allowedGlobals"] = nil
19351935- opts = _575_
19361936- end
19371937- local _576_ = search_module(module_name, utils["fennel-module"]["macro-path"])
19381938- if (nil ~= _576_) then
19391939- local filename = _576_
19401940- local _577_
19411941- if (opts["compiler-env"] == _G) then
19421942- local _578_ = fennel_macro_searcher
19431943- local _579_ = filename
19441944- local _580_ = opts
19451945- local function _582_(...)
19461946- return dofile_with_searcher(_578_, _579_, _580_, ...)
19471947- end
19481948- _577_ = _582_
19491949- else
19501950- local _583_ = filename
19511951- local _584_ = opts
19521952- local function _586_(...)
19531953- return utils["fennel-module"].dofile(_583_, _584_, ...)
19541954- end
19551955- _577_ = _586_
19561956- end
19571957- return _577_, filename
19581958- else
19591959- return nil
19601960- end
19611961- end
19621962- local function lua_macro_searcher(module_name)
19631963- local _589_ = search_module(module_name, package.path)
19641964- if (nil ~= _589_) then
19651965- local filename = _589_
19661966- local code
19671967- do
19681968- local f = io.open(filename)
19691969- local function close_handlers_8_auto(ok_9_auto, ...)
19701970- f:close()
19711971- if ok_9_auto then
19721972- return ...
19731973- else
19741974- return error(..., 0)
19751975- end
19761976- end
19771977- local function _591_()
19781978- return assert(f:read("*a"))
19791979- end
19801980- code = close_handlers_8_auto(_G.xpcall(_591_, (package.loaded.fennel or debug).traceback))
19811981- end
19821982- local chunk = load_code(code, make_compiler_env(), filename)
19831983- return chunk, filename
19841984- else
19851985- return nil
19861986- end
19871987- end
19881988- local macro_searchers = {fennel_macro_searcher, lua_macro_searcher}
19891989- local function search_macro_module(modname, n)
19901990- local _593_ = macro_searchers[n]
19911991- if (nil ~= _593_) then
19921992- local f = _593_
19931993- local _594_, _595_ = f(modname)
19941994- if ((nil ~= _594_) and true) then
19951995- local loader = _594_
19961996- local _3ffilename = _595_
19971997- return loader, _3ffilename
19981998- elseif true then
19991999- local _ = _594_
20002000- return search_macro_module(modname, (n + 1))
20012001- else
20022002- return nil
20032003- end
20042004- else
20052005- return nil
20062006- end
20072007- end
20082008- local function sandbox_fennel_module(modname)
20092009- if ((modname == "fennel.macros") or (package and package.loaded and ("table" == type(package.loaded[modname])) and (package.loaded[modname].metadata == compiler.metadata))) then
20102010- return {metadata = compiler.metadata, view = view}
20112011- else
20122012- return nil
20132013- end
20142014- end
20152015- local function _599_(modname)
20162016- local function _600_()
20172017- local loader, filename = search_macro_module(modname, 1)
20182018- compiler.assert(loader, (modname .. " module not found."))
20192019- do end (macro_loaded)[modname] = loader(modname, filename)
20202020- return macro_loaded[modname]
20212021- end
20222022- return (macro_loaded[modname] or sandbox_fennel_module(modname) or _600_())
20232023- end
20242024- safe_require = _599_
20252025- local function add_macros(macros_2a, ast, scope)
20262026- compiler.assert(utils["table?"](macros_2a), "expected macros to be table", ast)
20272027- for k, v in pairs(macros_2a) do
20282028- compiler.assert((type(v) == "function"), "expected each macro to be function", ast)
20292029- compiler["check-binding-valid"](utils.sym(k), scope, ast, {["macro?"] = true})
20302030- do end (scope.macros)[k] = v
20312031- end
20322032- return nil
20332033- end
20342034- local function resolve_module_name(_601_, _scope, _parent, opts)
20352035- local _arg_602_ = _601_
20362036- local filename = _arg_602_["filename"]
20372037- local second = _arg_602_[2]
20382038- local filename0 = (filename or (utils["table?"](second) and second.filename))
20392039- local module_name = utils.root.options["module-name"]
20402040- local modexpr = compiler.compile(second, opts)
20412041- local modname_chunk = load_code(modexpr)
20422042- return modname_chunk(module_name, filename0)
20432043- end
20442044- SPECIALS["require-macros"] = function(ast, scope, parent, _3freal_ast)
20452045- compiler.assert((#ast == 2), "Expected one module name argument", (_3freal_ast or ast))
20462046- local modname = resolve_module_name(ast, scope, parent, {})
20472047- compiler.assert(utils["string?"](modname), "module name must compile to string", (_3freal_ast or ast))
20482048- if not macro_loaded[modname] then
20492049- local loader, filename = search_macro_module(modname, 1)
20502050- compiler.assert(loader, (modname .. " module not found."), ast)
20512051- do end (macro_loaded)[modname] = compiler.assert(utils["table?"](loader(modname, filename)), "expected macros to be table", (_3freal_ast or ast))
20522052- else
20532053- end
20542054- if ("import-macros" == tostring(ast[1])) then
20552055- return macro_loaded[modname]
20562056- else
20572057- return add_macros(macro_loaded[modname], ast, scope, parent)
20582058- end
20592059- end
20602060- doc_special("require-macros", {"macro-module-name"}, "Load given module and use its contents as macro definitions in current scope.\nMacro module should return a table of macro functions with string keys.\nConsider using import-macros instead as it is more flexible.")
20612061- local function emit_included_fennel(src, path, opts, sub_chunk)
20622062- local subscope = compiler["make-scope"](utils.root.scope.parent)
20632063- local forms = {}
20642064- if utils.root.options.requireAsInclude then
20652065- subscope.specials.require = compiler["require-include"]
20662066- else
20672067- end
20682068- for _, val in parser.parser(parser["string-stream"](src), path) do
20692069- table.insert(forms, val)
20702070- end
20712071- for i = 1, #forms do
20722072- local subopts
20732073- if (i == #forms) then
20742074- subopts = {tail = true}
20752075- else
20762076- subopts = {nval = 0}
20772077- end
20782078- utils["propagate-options"](opts, subopts)
20792079- compiler.compile1(forms[i], subscope, sub_chunk, subopts)
20802080- end
20812081- return nil
20822082- end
20832083- local function include_path(ast, opts, path, mod, fennel_3f)
20842084- utils.root.scope.includes[mod] = "fnl/loading"
20852085- local src
20862086- do
20872087- local f = assert(io.open(path))
20882088- local function close_handlers_8_auto(ok_9_auto, ...)
20892089- f:close()
20902090- if ok_9_auto then
20912091- return ...
20922092- else
20932093- return error(..., 0)
20942094- end
20952095- end
20962096- local function _608_()
20972097- return assert(f:read("*all")):gsub("[\13\n]*$", "")
20982098- end
20992099- src = close_handlers_8_auto(_G.xpcall(_608_, (package.loaded.fennel or debug).traceback))
21002100- end
21012101- local ret = utils.expr(("require(\"" .. mod .. "\")"), "statement")
21022102- local target = ("package.preload[%q]"):format(mod)
21032103- local preload_str = (target .. " = " .. target .. " or function(...)")
21042104- local temp_chunk, sub_chunk = {}, {}
21052105- compiler.emit(temp_chunk, preload_str, ast)
21062106- compiler.emit(temp_chunk, sub_chunk)
21072107- compiler.emit(temp_chunk, "end", ast)
21082108- for _, v in ipairs(temp_chunk) do
21092109- table.insert(utils.root.chunk, v)
21102110- end
21112111- if fennel_3f then
21122112- emit_included_fennel(src, path, opts, sub_chunk)
21132113- else
21142114- compiler.emit(sub_chunk, src, ast)
21152115- end
21162116- utils.root.scope.includes[mod] = ret
21172117- return ret
21182118- end
21192119- local function include_circular_fallback(mod, modexpr, fallback, ast)
21202120- if (utils.root.scope.includes[mod] == "fnl/loading") then
21212121- compiler.assert(fallback, "circular include detected", ast)
21222122- return fallback(modexpr)
21232123- else
21242124- return nil
21252125- end
21262126- end
21272127- SPECIALS.include = function(ast, scope, parent, opts)
21282128- compiler.assert((#ast == 2), "expected one argument", ast)
21292129- local modexpr
21302130- do
21312131- local _611_, _612_ = pcall(resolve_module_name, ast, scope, parent, opts)
21322132- if ((_611_ == true) and (nil ~= _612_)) then
21332133- local modname = _612_
21342134- modexpr = utils.expr(string.format("%q", modname), "literal")
21352135- elseif true then
21362136- local _ = _611_
21372137- modexpr = (compiler.compile1(ast[2], scope, parent, {nval = 1}))[1]
21382138- else
21392139- modexpr = nil
21402140- end
21412141- end
21422142- if ((modexpr.type ~= "literal") or ((modexpr[1]):byte() ~= 34)) then
21432143- if opts.fallback then
21442144- return opts.fallback(modexpr)
21452145- else
21462146- return compiler.assert(false, "module name must be string literal", ast)
21472147- end
21482148- else
21492149- local mod = load_code(("return " .. modexpr[1]))()
21502150- local oldmod = utils.root.options["module-name"]
21512151- local _
21522152- utils.root.options["module-name"] = mod
21532153- _ = nil
21542154- local res
21552155- local function _616_()
21562156- local _615_ = search_module(mod)
21572157- if (nil ~= _615_) then
21582158- local fennel_path = _615_
21592159- return include_path(ast, opts, fennel_path, mod, true)
21602160- elseif true then
21612161- local _0 = _615_
21622162- local lua_path = search_module(mod, package.path)
21632163- if lua_path then
21642164- return include_path(ast, opts, lua_path, mod, false)
21652165- elseif opts.fallback then
21662166- return opts.fallback(modexpr)
21672167- else
21682168- return compiler.assert(false, ("module not found " .. mod), ast)
21692169- end
21702170- else
21712171- return nil
21722172- end
21732173- end
21742174- res = ((utils["member?"](mod, (utils.root.options.skipInclude or {})) and opts.fallback(modexpr, true)) or include_circular_fallback(mod, modexpr, opts.fallback, ast) or utils.root.scope.includes[mod] or _616_())
21752175- utils.root.options["module-name"] = oldmod
21762176- return res
21772177- end
21782178- end
21792179- doc_special("include", {"module-name-literal"}, "Like require but load the target module during compilation and embed it in the\nLua output. The module must be a string literal and resolvable at compile time.")
21802180- local function eval_compiler_2a(ast, scope, parent)
21812181- local env = make_compiler_env(ast, scope, parent)
21822182- local opts = utils.copy(utils.root.options)
21832183- opts.scope = compiler["make-scope"](compiler.scopes.compiler)
21842184- opts.allowedGlobals = current_global_names(env)
21852185- return load_code(compiler.compile(ast, opts), wrap_env(env))(opts["module-name"], ast.filename)
21862186- end
21872187- SPECIALS.macros = function(ast, scope, parent)
21882188- compiler.assert((#ast == 2), "Expected one table argument", ast)
21892189- return add_macros(eval_compiler_2a(ast[2], scope, parent), ast, scope, parent)
21902190- end
21912191- doc_special("macros", {"{:macro-name-1 (fn [...] ...) ... :macro-name-N macro-body-N}"}, "Define all functions in the given table as macros local to the current scope.")
21922192- SPECIALS["eval-compiler"] = function(ast, scope, parent)
21932193- local old_first = ast[1]
21942194- ast[1] = utils.sym("do")
21952195- local val = eval_compiler_2a(ast, scope, parent)
21962196- do end (ast)[1] = old_first
21972197- return val
21982198- end
21992199- doc_special("eval-compiler", {"..."}, "Evaluate the body at compile-time. Use the macro system instead if possible.", true)
22002200- return {doc = doc_2a, ["current-global-names"] = current_global_names, ["load-code"] = load_code, ["macro-loaded"] = macro_loaded, ["macro-searchers"] = macro_searchers, ["make-compiler-env"] = make_compiler_env, ["search-module"] = search_module, ["make-searcher"] = make_searcher, ["wrap-env"] = wrap_env}
22012201-end
22022202-package.preload["fennel.compiler"] = package.preload["fennel.compiler"] or function(...)
22032203- local utils = require("fennel.utils")
22042204- local parser = require("fennel.parser")
22052205- local friend = require("fennel.friend")
22062206- local unpack = (table.unpack or _G.unpack)
22072207- local scopes = {}
22082208- local function make_scope(_3fparent)
22092209- local parent = (_3fparent or scopes.global)
22102210- local _257_
22112211- if parent then
22122212- _257_ = ((parent.depth or 0) + 1)
22132213- else
22142214- _257_ = 0
22152215- end
22162216- return {includes = setmetatable({}, {__index = (parent and parent.includes)}), macros = setmetatable({}, {__index = (parent and parent.macros)}), manglings = setmetatable({}, {__index = (parent and parent.manglings)}), specials = setmetatable({}, {__index = (parent and parent.specials)}), symmeta = setmetatable({}, {__index = (parent and parent.symmeta)}), unmanglings = setmetatable({}, {__index = (parent and parent.unmanglings)}), gensyms = setmetatable({}, {__index = (parent and parent.gensyms)}), autogensyms = setmetatable({}, {__index = (parent and parent.autogensyms)}), vararg = (parent and parent.vararg), depth = _257_, hashfn = (parent and parent.hashfn), refedglobals = {}, parent = parent}
22172217- end
22182218- local function assert_msg(ast, msg)
22192219- local ast_tbl
22202220- if ("table" == type(ast)) then
22212221- ast_tbl = ast
22222222- else
22232223- ast_tbl = {}
22242224- end
22252225- local m = getmetatable(ast)
22262226- local filename = ((m and m.filename) or ast_tbl.filename or "unknown")
22272227- local line = ((m and m.line) or ast_tbl.line or "?")
22282228- local col = ((m and m.col) or ast_tbl.col or "?")
22292229- local target = tostring((utils["sym?"](ast_tbl[1]) or ast_tbl[1] or "()"))
22302230- return string.format("%s:%s:%s Compile error in '%s': %s", filename, line, col, target, msg)
22312231- end
22322232- local function assert_compile(condition, msg, ast)
22332233- if not condition then
22342234- local _let_260_ = (utils.root.options or {})
22352235- local source = _let_260_["source"]
22362236- local unfriendly = _let_260_["unfriendly"]
22372237- if (nil == utils.hook("assert-compile", condition, msg, ast, utils.root.reset)) then
22382238- utils.root.reset()
22392239- if (unfriendly or not friend or not _G.io or not _G.io.read) then
22402240- error(assert_msg(ast, msg), 0)
22412241- else
22422242- friend["assert-compile"](condition, msg, ast, source)
22432243- end
22442244- else
22452245- end
22462246- else
22472247- end
22482248- return condition
22492249- end
22502250- scopes.global = make_scope()
22512251- scopes.global.vararg = true
22522252- scopes.compiler = make_scope(scopes.global)
22532253- scopes.macro = scopes.global
22542254- local serialize_subst = {["\7"] = "\\a", ["\8"] = "\\b", ["\9"] = "\\t", ["\n"] = "n", ["\11"] = "\\v", ["\12"] = "\\f"}
22552255- local function serialize_string(str)
22562256- local function _264_(_241)
22572257- return ("\\" .. _241:byte())
22582258- end
22592259- return string.gsub(string.gsub(string.format("%q", str), ".", serialize_subst), "[\128-\255]", _264_)
22602260- end
22612261- local function global_mangling(str)
22622262- if utils["valid-lua-identifier?"](str) then
22632263- return str
22642264- else
22652265- local function _265_(_241)
22662266- return string.format("_%02x", _241:byte())
22672267- end
22682268- return ("__fnl_global__" .. str:gsub("[^%w]", _265_))
22692269- end
22702270- end
22712271- local function global_unmangling(identifier)
22722272- local _267_ = string.match(identifier, "^__fnl_global__(.*)$")
22732273- if (nil ~= _267_) then
22742274- local rest = _267_
22752275- local _268_
22762276- local function _269_(_241)
22772277- return string.char(tonumber(_241:sub(2), 16))
22782278- end
22792279- _268_ = string.gsub(rest, "_[%da-f][%da-f]", _269_)
22802280- return _268_
22812281- elseif true then
22822282- local _ = _267_
22832283- return identifier
22842284- else
22852285- return nil
22862286- end
22872287- end
22882288- local allowed_globals = nil
22892289- local function global_allowed_3f(name)
22902290- return (not allowed_globals or utils["member?"](name, allowed_globals))
22912291- end
22922292- local function unique_mangling(original, mangling, scope, append)
22932293- if (scope.unmanglings[mangling] and not scope.gensyms[mangling]) then
22942294- return unique_mangling(original, (original .. append), scope, (append + 1))
22952295- else
22962296- return mangling
22972297- end
22982298- end
22992299- local function local_mangling(str, scope, ast, _3ftemp_manglings)
23002300- assert_compile(not utils["multi-sym?"](str), ("unexpected multi symbol " .. str), ast)
23012301- local raw
23022302- if ((utils["lua-keywords"])[str] or str:match("^%d")) then
23032303- raw = ("_" .. str)
23042304- else
23052305- raw = str
23062306- end
23072307- local mangling
23082308- local function _273_(_241)
23092309- return string.format("_%02x", _241:byte())
23102310- end
23112311- mangling = string.gsub(string.gsub(raw, "-", "_"), "[^%w_]", _273_)
23122312- local unique = unique_mangling(mangling, mangling, scope, 0)
23132313- do end (scope.unmanglings)[unique] = str
23142314- do
23152315- local manglings = (_3ftemp_manglings or scope.manglings)
23162316- do end (manglings)[str] = unique
23172317- end
23182318- return unique
23192319- end
23202320- local function apply_manglings(scope, new_manglings, ast)
23212321- for raw, mangled in pairs(new_manglings) do
23222322- assert_compile(not scope.refedglobals[mangled], ("use of global " .. raw .. " is aliased by a local"), ast)
23232323- do end (scope.manglings)[raw] = mangled
23242324- end
23252325- return nil
23262326- end
23272327- local function combine_parts(parts, scope)
23282328- local ret = (scope.manglings[parts[1]] or global_mangling(parts[1]))
23292329- for i = 2, #parts do
23302330- if utils["valid-lua-identifier?"](parts[i]) then
23312331- if (parts["multi-sym-method-call"] and (i == #parts)) then
23322332- ret = (ret .. ":" .. parts[i])
23332333- else
23342334- ret = (ret .. "." .. parts[i])
23352335- end
23362336- else
23372337- ret = (ret .. "[" .. serialize_string(parts[i]) .. "]")
23382338- end
23392339- end
23402340- return ret
23412341- end
23422342- local function next_append()
23432343- utils.root.scope["gensym-append"] = ((utils.root.scope["gensym-append"] or 0) + 1)
23442344- return ("_" .. utils.root.scope["gensym-append"] .. "_")
23452345- end
23462346- local function gensym(scope, _3fbase, _3fsuffix)
23472347- local mangling = ((_3fbase or "") .. next_append() .. (_3fsuffix or ""))
23482348- while scope.unmanglings[mangling] do
23492349- mangling = ((_3fbase or "") .. next_append() .. (_3fsuffix or ""))
23502350- end
23512351- scope.unmanglings[mangling] = (_3fbase or true)
23522352- do end (scope.gensyms)[mangling] = true
23532353- return mangling
23542354- end
23552355- local function combine_auto_gensym(parts, first)
23562356- parts[1] = first
23572357- local last = table.remove(parts)
23582358- local last2 = table.remove(parts)
23592359- local last_joiner = ((parts["multi-sym-method-call"] and ":") or ".")
23602360- table.insert(parts, (last2 .. last_joiner .. last))
23612361- return table.concat(parts, ".")
23622362- end
23632363- local function autogensym(base, scope)
23642364- local _276_ = utils["multi-sym?"](base)
23652365- if (nil ~= _276_) then
23662366- local parts = _276_
23672367- return combine_auto_gensym(parts, autogensym(parts[1], scope))
23682368- elseif true then
23692369- local _ = _276_
23702370- local function _277_()
23712371- local mangling = gensym(scope, base:sub(1, ( - 2)), "auto")
23722372- do end (scope.autogensyms)[base] = mangling
23732373- return mangling
23742374- end
23752375- return (scope.autogensyms[base] or _277_())
23762376- else
23772377- return nil
23782378- end
23792379- end
23802380- local function check_binding_valid(symbol, scope, ast, _3fopts)
23812381- local name = tostring(symbol)
23822382- local macro_3f
23832383- do
23842384- local t_279_ = _3fopts
23852385- if (nil ~= t_279_) then
23862386- t_279_ = (t_279_)["macro?"]
23872387- else
23882388- end
23892389- macro_3f = t_279_
23902390- end
23912391- assert_compile(not name:find("&"), "invalid character: &")
23922392- assert_compile(not name:find("^%."), "invalid character: .")
23932393- assert_compile(not (scope.specials[name] or (not macro_3f and scope.macros[name])), ("local %s was overshadowed by a special form or macro"):format(name), ast)
23942394- return assert_compile(not utils["quoted?"](symbol), string.format("macro tried to bind %s without gensym", name), symbol)
23952395- end
23962396- local function declare_local(symbol, meta, scope, ast, _3ftemp_manglings)
23972397- check_binding_valid(symbol, scope, ast)
23982398- local name = tostring(symbol)
23992399- assert_compile(not utils["multi-sym?"](name), ("unexpected multi symbol " .. name), ast)
24002400- do end (scope.symmeta)[name] = meta
24012401- return local_mangling(name, scope, ast, _3ftemp_manglings)
24022402- end
24032403- local function hashfn_arg_name(name, multi_sym_parts, scope)
24042404- if not scope.hashfn then
24052405- return nil
24062406- elseif (name == "$") then
24072407- return "$1"
24082408- elseif multi_sym_parts then
24092409- if (multi_sym_parts and (multi_sym_parts[1] == "$")) then
24102410- multi_sym_parts[1] = "$1"
24112411- else
24122412- end
24132413- return table.concat(multi_sym_parts, ".")
24142414- else
24152415- return nil
24162416- end
24172417- end
24182418- local function symbol_to_expression(symbol, scope, _3freference_3f)
24192419- utils.hook("symbol-to-expression", symbol, scope, _3freference_3f)
24202420- local name = symbol[1]
24212421- local multi_sym_parts = utils["multi-sym?"](name)
24222422- local name0 = (hashfn_arg_name(name, multi_sym_parts, scope) or name)
24232423- local parts = (multi_sym_parts or {name0})
24242424- local etype = (((1 < #parts) and "expression") or "sym")
24252425- local local_3f = scope.manglings[parts[1]]
24262426- if (local_3f and scope.symmeta[parts[1]]) then
24272427- scope.symmeta[parts[1]]["used"] = true
24282428- else
24292429- end
24302430- assert_compile(not scope.macros[parts[1]], "tried to reference a macro at runtime", symbol)
24312431- assert_compile((not scope.specials[parts[1]] or ("require" == parts[1])), "tried to reference a special form at runtime", symbol)
24322432- assert_compile((not _3freference_3f or local_3f or ("_ENV" == parts[1]) or global_allowed_3f(parts[1])), ("unknown identifier in strict mode: " .. tostring(parts[1])), symbol)
24332433- if (allowed_globals and not local_3f and scope.parent) then
24342434- scope.parent.refedglobals[parts[1]] = true
24352435- else
24362436- end
24372437- return utils.expr(combine_parts(parts, scope), etype)
24382438- end
24392439- local function emit(chunk, out, _3fast)
24402440- if (type(out) == "table") then
24412441- return table.insert(chunk, out)
24422442- else
24432443- return table.insert(chunk, {ast = _3fast, leaf = out})
24442444- end
24452445- end
24462446- local function peephole(chunk)
24472447- if chunk.leaf then
24482448- return chunk
24492449- elseif ((3 <= #chunk) and (chunk[(#chunk - 2)].leaf == "do") and not chunk[(#chunk - 1)].leaf and (chunk[#chunk].leaf == "end")) then
24502450- local kid = peephole(chunk[(#chunk - 1)])
24512451- local new_chunk = {ast = chunk.ast}
24522452- for i = 1, (#chunk - 3) do
24532453- table.insert(new_chunk, peephole(chunk[i]))
24542454- end
24552455- for i = 1, #kid do
24562456- table.insert(new_chunk, kid[i])
24572457- end
24582458- return new_chunk
24592459- else
24602460- return utils.map(chunk, peephole)
24612461- end
24622462- end
24632463- local function flatten_chunk_correlated(main_chunk, options)
24642464- local function flatten(chunk, out, last_line, file)
24652465- local last_line0 = last_line
24662466- if chunk.leaf then
24672467- out[last_line0] = ((out[last_line0] or "") .. " " .. chunk.leaf)
24682468- else
24692469- for _, subchunk in ipairs(chunk) do
24702470- if (subchunk.leaf or (0 < #subchunk)) then
24712471- local source = utils["ast-source"](subchunk.ast)
24722472- if (file == source.filename) then
24732473- last_line0 = math.max(last_line0, (source.line or 0))
24742474- else
24752475- end
24762476- last_line0 = flatten(subchunk, out, last_line0, file)
24772477- else
24782478- end
24792479- end
24802480- end
24812481- return last_line0
24822482- end
24832483- local out = {}
24842484- local last = flatten(main_chunk, out, 1, options.filename)
24852485- for i = 1, last do
24862486- if (out[i] == nil) then
24872487- out[i] = ""
24882488- else
24892489- end
24902490- end
24912491- return table.concat(out, "\n")
24922492- end
24932493- local function flatten_chunk(file_sourcemap, chunk, tab, depth)
24942494- if chunk.leaf then
24952495- local _let_291_ = utils["ast-source"](chunk.ast)
24962496- local filename = _let_291_["filename"]
24972497- local line = _let_291_["line"]
24982498- table.insert(file_sourcemap, {filename, line})
24992499- return chunk.leaf
25002500- else
25012501- local tab0
25022502- do
25032503- local _292_ = tab
25042504- if (_292_ == true) then
25052505- tab0 = " "
25062506- elseif (_292_ == false) then
25072507- tab0 = ""
25082508- elseif (_292_ == tab) then
25092509- tab0 = tab
25102510- elseif (_292_ == nil) then
25112511- tab0 = ""
25122512- else
25132513- tab0 = nil
25142514- end
25152515- end
25162516- local function parter(c)
25172517- if (c.leaf or (0 < #c)) then
25182518- local sub = flatten_chunk(file_sourcemap, c, tab0, (depth + 1))
25192519- if (0 < depth) then
25202520- return (tab0 .. sub:gsub("\n", ("\n" .. tab0)))
25212521- else
25222522- return sub
25232523- end
25242524- else
25252525- return nil
25262526- end
25272527- end
25282528- return table.concat(utils.map(chunk, parter), "\n")
25292529- end
25302530- end
25312531- local sourcemap = {}
25322532- local function make_short_src(source)
25332533- local source0 = source:gsub("\n", " ")
25342534- if (#source0 <= 49) then
25352535- return ("[fennel \"" .. source0 .. "\"]")
25362536- else
25372537- return ("[fennel \"" .. source0:sub(1, 46) .. "...\"]")
25382538- end
25392539- end
25402540- local function flatten(chunk, options)
25412541- local chunk0 = peephole(chunk)
25422542- if options.correlate then
25432543- return flatten_chunk_correlated(chunk0, options), {}
25442544- else
25452545- local file_sourcemap = {}
25462546- local src = flatten_chunk(file_sourcemap, chunk0, options.indent, 0)
25472547- file_sourcemap.short_src = (options.filename or make_short_src((options.source or src)))
25482548- if options.filename then
25492549- file_sourcemap.key = ("@" .. options.filename)
25502550- else
25512551- file_sourcemap.key = src
25522552- end
25532553- sourcemap[file_sourcemap.key] = file_sourcemap
25542554- return src, file_sourcemap
25552555- end
25562556- end
25572557- local function make_metadata()
25582558- local function _300_(self, tgt, key)
25592559- if self[tgt] then
25602560- return self[tgt][key]
25612561- else
25622562- return nil
25632563- end
25642564- end
25652565- local function _302_(self, tgt, key, value)
25662566- self[tgt] = (self[tgt] or {})
25672567- do end (self[tgt])[key] = value
25682568- return tgt
25692569- end
25702570- local function _303_(self, tgt, ...)
25712571- local kv_len = select("#", ...)
25722572- local kvs = {...}
25732573- if ((kv_len % 2) ~= 0) then
25742574- error("metadata:setall() expected even number of k/v pairs")
25752575- else
25762576- end
25772577- self[tgt] = (self[tgt] or {})
25782578- for i = 1, kv_len, 2 do
25792579- self[tgt][kvs[i]] = kvs[(i + 1)]
25802580- end
25812581- return tgt
25822582- end
25832583- return setmetatable({}, {__index = {get = _300_, set = _302_, setall = _303_}, __mode = "k"})
25842584- end
25852585- local function exprs1(exprs)
25862586- return table.concat(utils.map(exprs, tostring), ", ")
25872587- end
25882588- local function keep_side_effects(exprs, chunk, start, ast)
25892589- local start0 = (start or 1)
25902590- for j = start0, #exprs do
25912591- local se = exprs[j]
25922592- if ((se.type == "expression") and (se[1] ~= "nil")) then
25932593- emit(chunk, string.format("do local _ = %s end", tostring(se)), ast)
25942594- elseif (se.type == "statement") then
25952595- local code = tostring(se)
25962596- local disambiguated
25972597- if (code:byte() == 40) then
25982598- disambiguated = ("do end " .. code)
25992599- else
26002600- disambiguated = code
26012601- end
26022602- emit(chunk, disambiguated, ast)
26032603- else
26042604- end
26052605- end
26062606- return nil
26072607- end
26082608- local function handle_compile_opts(exprs, parent, opts, ast)
26092609- if opts.nval then
26102610- local n = opts.nval
26112611- local len = #exprs
26122612- if (n ~= len) then
26132613- if (n < len) then
26142614- keep_side_effects(exprs, parent, (n + 1), ast)
26152615- for i = (n + 1), len do
26162616- exprs[i] = nil
26172617- end
26182618- else
26192619- for i = (#exprs + 1), n do
26202620- exprs[i] = utils.expr("nil", "literal")
26212621- end
26222622- end
26232623- else
26242624- end
26252625- else
26262626- end
26272627- if opts.tail then
26282628- emit(parent, string.format("return %s", exprs1(exprs)), ast)
26292629- else
26302630- end
26312631- if opts.target then
26322632- local result = exprs1(exprs)
26332633- local function _311_()
26342634- if (result == "") then
26352635- return "nil"
26362636- else
26372637- return result
26382638- end
26392639- end
26402640- emit(parent, string.format("%s = %s", opts.target, _311_()), ast)
26412641- else
26422642- end
26432643- if (opts.tail or opts.target) then
26442644- return {returned = true}
26452645- else
26462646- local _313_ = exprs
26472647- _313_["returned"] = true
26482648- return _313_
26492649- end
26502650- end
26512651- local function find_macro(ast, scope)
26522652- local macro_2a
26532653- do
26542654- local _315_ = utils["sym?"](ast[1])
26552655- if (_315_ ~= nil) then
26562656- local _316_ = tostring(_315_)
26572657- if (_316_ ~= nil) then
26582658- macro_2a = scope.macros[_316_]
26592659- else
26602660- macro_2a = _316_
26612661- end
26622662- else
26632663- macro_2a = _315_
26642664- end
26652665- end
26662666- local multi_sym_parts = utils["multi-sym?"](ast[1])
26672667- if (not macro_2a and multi_sym_parts) then
26682668- local nested_macro = utils["get-in"](scope.macros, multi_sym_parts)
26692669- assert_compile((not scope.macros[multi_sym_parts[1]] or (type(nested_macro) == "function")), "macro not found in imported macro module", ast)
26702670- return nested_macro
26712671- else
26722672- return macro_2a
26732673- end
26742674- end
26752675- local function propagate_trace_info(_320_, _index, node)
26762676- local _arg_321_ = _320_
26772677- local filename = _arg_321_["filename"]
26782678- local line = _arg_321_["line"]
26792679- local bytestart = _arg_321_["bytestart"]
26802680- local byteend = _arg_321_["byteend"]
26812681- do
26822682- local src = utils["ast-source"](node)
26832683- if (("table" == type(node)) and (filename ~= src.filename)) then
26842684- src.filename, src.line, src["from-macro?"] = filename, line, true
26852685- src.bytestart, src.byteend = bytestart, byteend
26862686- else
26872687- end
26882688- end
26892689- return ("table" == type(node))
26902690- end
26912691- local function max_n(t)
26922692- local n = 0
26932693- for k in pairs(t) do
26942694- if ("number" == type(k)) then
26952695- n = math.max(k, n)
26962696- else
26972697- end
26982698- end
26992699- return n
27002700- end
27012701- local function quote_literal_nils(index, node, parent)
27022702- if (parent and utils["list?"](parent)) then
27032703- for i = 1, max_n(parent) do
27042704- local _324_ = parent[i]
27052705- if (_324_ == nil) then
27062706- parent[i] = utils.sym("nil")
27072707- else
27082708- end
27092709- end
27102710- else
27112711- end
27122712- return index, node, parent
27132713- end
27142714- local function comp(f, g)
27152715- local function _327_(...)
27162716- return f(g(...))
27172717- end
27182718- return _327_
27192719- end
27202720- local function built_in_3f(m)
27212721- local found_3f = false
27222722- for _, f in pairs(scopes.global.macros) do
27232723- if found_3f then break end
27242724- found_3f = (f == m)
27252725- end
27262726- return found_3f
27272727- end
27282728- local function macroexpand_2a(ast, scope, _3fonce)
27292729- local _328_
27302730- if utils["list?"](ast) then
27312731- _328_ = find_macro(ast, scope)
27322732- else
27332733- _328_ = nil
27342734- end
27352735- if (_328_ == false) then
27362736- return ast
27372737- elseif (nil ~= _328_) then
27382738- local macro_2a = _328_
27392739- local old_scope = scopes.macro
27402740- local _
27412741- scopes.macro = scope
27422742- _ = nil
27432743- local ok, transformed = nil, nil
27442744- local function _330_()
27452745- return macro_2a(unpack(ast, 2))
27462746- end
27472747- local function _331_()
27482748- if built_in_3f(macro_2a) then
27492749- return tostring
27502750- else
27512751- return debug.traceback
27522752- end
27532753- end
27542754- ok, transformed = xpcall(_330_, _331_())
27552755- local _333_
27562756- do
27572757- local _332_ = ast
27582758- local function _334_(...)
27592759- return propagate_trace_info(_332_, ...)
27602760- end
27612761- _333_ = _334_
27622762- end
27632763- utils["walk-tree"](transformed, comp(_333_, quote_literal_nils))
27642764- scopes.macro = old_scope
27652765- assert_compile(ok, transformed, ast)
27662766- if (_3fonce or not transformed) then
27672767- return transformed
27682768- else
27692769- return macroexpand_2a(transformed, scope)
27702770- end
27712771- elseif true then
27722772- local _ = _328_
27732773- return ast
27742774- else
27752775- return nil
27762776- end
27772777- end
27782778- local function compile_special(ast, scope, parent, opts, special)
27792779- local exprs = (special(ast, scope, parent, opts) or utils.expr("nil", "literal"))
27802780- local exprs0
27812781- if ("table" ~= type(exprs)) then
27822782- exprs0 = utils.expr(exprs, "expression")
27832783- else
27842784- exprs0 = exprs
27852785- end
27862786- local exprs2
27872787- if utils["expr?"](exprs0) then
27882788- exprs2 = {exprs0}
27892789- else
27902790- exprs2 = exprs0
27912791- end
27922792- if not exprs2.returned then
27932793- return handle_compile_opts(exprs2, parent, opts, ast)
27942794- elseif (opts.tail or opts.target) then
27952795- return {returned = true}
27962796- else
27972797- return exprs2
27982798- end
27992799- end
28002800- local function compile_function_call(ast, scope, parent, opts, compile1, len)
28012801- local fargs = {}
28022802- local fcallee = (compile1(ast[1], scope, parent, {nval = 1}))[1]
28032803- assert_compile((utils["sym?"](ast[1]) or utils["list?"](ast[1]) or ("string" == type(ast[1]))), ("cannot call literal value " .. tostring(ast[1])), ast)
28042804- for i = 2, len do
28052805- local subexprs
28062806- local _340_
28072807- if (i ~= len) then
28082808- _340_ = 1
28092809- else
28102810- _340_ = nil
28112811- end
28122812- subexprs = compile1(ast[i], scope, parent, {nval = _340_})
28132813- table.insert(fargs, subexprs[1])
28142814- if (i == len) then
28152815- for j = 2, #subexprs do
28162816- table.insert(fargs, subexprs[j])
28172817- end
28182818- else
28192819- keep_side_effects(subexprs, parent, 2, ast[i])
28202820- end
28212821- end
28222822- local pat
28232823- if ("string" == type(ast[1])) then
28242824- pat = "(%s)(%s)"
28252825- else
28262826- pat = "%s(%s)"
28272827- end
28282828- local call = string.format(pat, tostring(fcallee), exprs1(fargs))
28292829- return handle_compile_opts({utils.expr(call, "statement")}, parent, opts, ast)
28302830- end
28312831- local function compile_call(ast, scope, parent, opts, compile1)
28322832- utils.hook("call", ast, scope)
28332833- local len = #ast
28342834- local first = ast[1]
28352835- local multi_sym_parts = utils["multi-sym?"](first)
28362836- local special = (utils["sym?"](first) and scope.specials[tostring(first)])
28372837- assert_compile((0 < len), "expected a function, macro, or special to call", ast)
28382838- if special then
28392839- return compile_special(ast, scope, parent, opts, special)
28402840- elseif (multi_sym_parts and multi_sym_parts["multi-sym-method-call"]) then
28412841- local table_with_method = table.concat({unpack(multi_sym_parts, 1, (#multi_sym_parts - 1))}, ".")
28422842- local method_to_call = multi_sym_parts[#multi_sym_parts]
28432843- local new_ast = utils.list(utils.sym(":", ast), utils.sym(table_with_method, ast), method_to_call, select(2, unpack(ast)))
28442844- return compile1(new_ast, scope, parent, opts)
28452845- else
28462846- return compile_function_call(ast, scope, parent, opts, compile1, len)
28472847- end
28482848- end
28492849- local function compile_varg(ast, scope, parent, opts)
28502850- local _345_
28512851- if scope.hashfn then
28522852- _345_ = "use $... in hashfn"
28532853- else
28542854- _345_ = "unexpected vararg"
28552855- end
28562856- assert_compile(scope.vararg, _345_, ast)
28572857- return handle_compile_opts({utils.expr("...", "varg")}, parent, opts, ast)
28582858- end
28592859- local function compile_sym(ast, scope, parent, opts)
28602860- local multi_sym_parts = utils["multi-sym?"](ast)
28612861- assert_compile(not (multi_sym_parts and multi_sym_parts["multi-sym-method-call"]), "multisym method calls may only be in call position", ast)
28622862- local e
28632863- if (ast[1] == "nil") then
28642864- e = utils.expr("nil", "literal")
28652865- else
28662866- e = symbol_to_expression(ast, scope, true)
28672867- end
28682868- return handle_compile_opts({e}, parent, opts, ast)
28692869- end
28702870- local function serialize_number(n)
28712871- local _348_ = string.gsub(tostring(n), ",", ".")
28722872- return _348_
28732873- end
28742874- local function compile_scalar(ast, _scope, parent, opts)
28752875- local serialize
28762876- do
28772877- local _349_ = type(ast)
28782878- if (_349_ == "nil") then
28792879- serialize = tostring
28802880- elseif (_349_ == "boolean") then
28812881- serialize = tostring
28822882- elseif (_349_ == "string") then
28832883- serialize = serialize_string
28842884- elseif (_349_ == "number") then
28852885- serialize = serialize_number
28862886- else
28872887- serialize = nil
28882888- end
28892889- end
28902890- return handle_compile_opts({utils.expr(serialize(ast), "literal")}, parent, opts)
28912891- end
28922892- local function compile_table(ast, scope, parent, opts, compile1)
28932893- local buffer = {}
28942894- local function write_other_values(k)
28952895- if ((type(k) ~= "number") or (math.floor(k) ~= k) or (k < 1) or (#ast < k)) then
28962896- if ((type(k) == "string") and utils["valid-lua-identifier?"](k)) then
28972897- return {k, k}
28982898- else
28992899- local _let_351_ = compile1(k, scope, parent, {nval = 1})
29002900- local compiled = _let_351_[1]
29012901- local kstr = ("[" .. tostring(compiled) .. "]")
29022902- return {kstr, k}
29032903- end
29042904- else
29052905- return nil
29062906- end
29072907- end
29082908- do
29092909- local keys
29102910- do
29112911- local tbl_14_auto = {}
29122912- local i_15_auto = #tbl_14_auto
29132913- for k, v in utils.stablepairs(ast) do
29142914- local val_16_auto = write_other_values(k, v)
29152915- if (nil ~= val_16_auto) then
29162916- i_15_auto = (i_15_auto + 1)
29172917- do end (tbl_14_auto)[i_15_auto] = val_16_auto
29182918- else
29192919- end
29202920- end
29212921- keys = tbl_14_auto
29222922- end
29232923- local function _357_(_355_)
29242924- local _arg_356_ = _355_
29252925- local k1 = _arg_356_[1]
29262926- local k2 = _arg_356_[2]
29272927- local _let_358_ = compile1(ast[k2], scope, parent, {nval = 1})
29282928- local v = _let_358_[1]
29292929- return string.format("%s = %s", k1, tostring(v))
29302930- end
29312931- utils.map(keys, _357_, buffer)
29322932- end
29332933- for i = 1, #ast do
29342934- local nval = ((i ~= #ast) and 1)
29352935- table.insert(buffer, exprs1(compile1(ast[i], scope, parent, {nval = nval})))
29362936- end
29372937- return handle_compile_opts({utils.expr(("{" .. table.concat(buffer, ", ") .. "}"), "expression")}, parent, opts, ast)
29382938- end
29392939- local function compile1(ast, scope, parent, _3fopts)
29402940- local opts = (_3fopts or {})
29412941- local ast0 = macroexpand_2a(ast, scope)
29422942- if utils["list?"](ast0) then
29432943- return compile_call(ast0, scope, parent, opts, compile1)
29442944- elseif utils["varg?"](ast0) then
29452945- return compile_varg(ast0, scope, parent, opts)
29462946- elseif utils["sym?"](ast0) then
29472947- return compile_sym(ast0, scope, parent, opts)
29482948- elseif (type(ast0) == "table") then
29492949- return compile_table(ast0, scope, parent, opts, compile1)
29502950- elseif ((type(ast0) == "nil") or (type(ast0) == "boolean") or (type(ast0) == "number") or (type(ast0) == "string")) then
29512951- return compile_scalar(ast0, scope, parent, opts)
29522952- else
29532953- return assert_compile(false, ("could not compile value of type " .. type(ast0)), ast0)
29542954- end
29552955- end
29562956- local function destructure(to, from, ast, scope, parent, opts)
29572957- local opts0 = (opts or {})
29582958- local _let_360_ = opts0
29592959- local isvar = _let_360_["isvar"]
29602960- local declaration = _let_360_["declaration"]
29612961- local forceglobal = _let_360_["forceglobal"]
29622962- local forceset = _let_360_["forceset"]
29632963- local symtype = _let_360_["symtype"]
29642964- local symtype0 = ("_" .. (symtype or "dst"))
29652965- local setter
29662966- if declaration then
29672967- setter = "local %s = %s"
29682968- else
29692969- setter = "%s = %s"
29702970- end
29712971- local new_manglings = {}
29722972- local function getname(symbol, up1)
29732973- local raw = symbol[1]
29742974- assert_compile(not (opts0.nomulti and utils["multi-sym?"](raw)), ("unexpected multi symbol " .. raw), up1)
29752975- if declaration then
29762976- return declare_local(symbol, nil, scope, symbol, new_manglings)
29772977- else
29782978- local parts = (utils["multi-sym?"](raw) or {raw})
29792979- local meta = scope.symmeta[parts[1]]
29802980- assert_compile(not raw:find(":"), "cannot set method sym", symbol)
29812981- if ((#parts == 1) and not forceset) then
29822982- assert_compile(not (forceglobal and meta), string.format("global %s conflicts with local", tostring(symbol)), symbol)
29832983- assert_compile(not (meta and not meta.var), ("expected var " .. raw), symbol)
29842984- assert_compile((meta or not opts0.noundef), ("expected local " .. parts[1]), symbol)
29852985- else
29862986- end
29872987- if forceglobal then
29882988- assert_compile(not scope.symmeta[scope.unmanglings[raw]], ("global " .. raw .. " conflicts with local"), symbol)
29892989- do end (scope.manglings)[raw] = global_mangling(raw)
29902990- do end (scope.unmanglings)[global_mangling(raw)] = raw
29912991- if allowed_globals then
29922992- table.insert(allowed_globals, raw)
29932993- else
29942994- end
29952995- else
29962996- end
29972997- return symbol_to_expression(symbol, scope)[1]
29982998- end
29992999- end
30003000- local function compile_top_target(lvalues)
30013001- local inits
30023002- local function _366_(_241)
30033003- if scope.manglings[_241] then
30043004- return _241
30053005- else
30063006- return "nil"
30073007- end
30083008- end
30093009- inits = utils.map(lvalues, _366_)
30103010- local init = table.concat(inits, ", ")
30113011- local lvalue = table.concat(lvalues, ", ")
30123012- local plast = parent[#parent]
30133013- local plen = #parent
30143014- local ret = compile1(from, scope, parent, {target = lvalue})
30153015- if declaration then
30163016- for pi = plen, #parent do
30173017- if (parent[pi] == plast) then
30183018- plen = pi
30193019- else
30203020- end
30213021- end
30223022- if ((#parent == (plen + 1)) and parent[#parent].leaf) then
30233023- parent[#parent]["leaf"] = ("local " .. parent[#parent].leaf)
30243024- elseif (init == "nil") then
30253025- table.insert(parent, (plen + 1), {ast = ast, leaf = ("local " .. lvalue)})
30263026- else
30273027- table.insert(parent, (plen + 1), {ast = ast, leaf = ("local " .. lvalue .. " = " .. init)})
30283028- end
30293029- else
30303030- end
30313031- return ret
30323032- end
30333033- local function destructure_sym(left, rightexprs, up1, top_3f)
30343034- local lname = getname(left, up1)
30353035- check_binding_valid(left, scope, left)
30363036- if top_3f then
30373037- compile_top_target({lname})
30383038- else
30393039- emit(parent, setter:format(lname, exprs1(rightexprs)), left)
30403040- end
30413041- if declaration then
30423042- scope.symmeta[tostring(left)] = {var = isvar}
30433043- return nil
30443044- else
30453045- return nil
30463046- end
30473047- end
30483048- local unpack_fn = "function (t, k, e)\n local mt = getmetatable(t)\n if 'table' == type(mt) and mt.__fennelrest then\n return mt.__fennelrest(t, k)\n elseif e then\n local rest = {}\n for k, v in pairs(t) do\n if not e[k] then rest[k] = v end\n end\n return rest\n else\n return {(table.unpack or unpack)(t, k)}\n end\n end"
30493049- local function destructure_kv_rest(s, v, left, excluded_keys, destructure1)
30503050- local exclude_str
30513051- local _373_
30523052- do
30533053- local tbl_14_auto = {}
30543054- local i_15_auto = #tbl_14_auto
30553055- for _, k in ipairs(excluded_keys) do
30563056- local val_16_auto = string.format("[%s] = true", serialize_string(k))
30573057- if (nil ~= val_16_auto) then
30583058- i_15_auto = (i_15_auto + 1)
30593059- do end (tbl_14_auto)[i_15_auto] = val_16_auto
30603060- else
30613061- end
30623062- end
30633063- _373_ = tbl_14_auto
30643064- end
30653065- exclude_str = table.concat(_373_, ", ")
30663066- local subexpr = utils.expr(string.format(string.gsub(("(" .. unpack_fn .. ")(%s, %s, {%s})"), "\n%s*", " "), s, tostring(v), exclude_str), "expression")
30673067- return destructure1(v, {subexpr}, left)
30683068- end
30693069- local function destructure_rest(s, k, left, destructure1)
30703070- local unpack_str = ("(" .. unpack_fn .. ")(%s, %s)")
30713071- local formatted = string.format(string.gsub(unpack_str, "\n%s*", " "), s, k)
30723072- local subexpr = utils.expr(formatted, "expression")
30733073- assert_compile((utils["sequence?"](left) and (nil == left[(k + 2)])), "expected rest argument before last parameter", left)
30743074- return destructure1(left[(k + 1)], {subexpr}, left)
30753075- end
30763076- local function destructure_table(left, rightexprs, top_3f, destructure1)
30773077- local s = gensym(scope, symtype0)
30783078- local right
30793079- do
30803080- local _375_
30813081- if top_3f then
30823082- _375_ = exprs1(compile1(from, scope, parent))
30833083- else
30843084- _375_ = exprs1(rightexprs)
30853085- end
30863086- if (_375_ == "") then
30873087- right = "nil"
30883088- elseif (nil ~= _375_) then
30893089- local right0 = _375_
30903090- right = right0
30913091- else
30923092- right = nil
30933093- end
30943094- end
30953095- local excluded_keys = {}
30963096- emit(parent, string.format("local %s = %s", s, right), left)
30973097- for k, v in utils.stablepairs(left) do
30983098- if not (("number" == type(k)) and tostring(left[(k - 1)]):find("^&")) then
30993099- if (utils["sym?"](k) and (tostring(k) == "&")) then
31003100- destructure_kv_rest(s, v, left, excluded_keys, destructure1)
31013101- elseif (utils["sym?"](v) and (tostring(v) == "&")) then
31023102- destructure_rest(s, k, left, destructure1)
31033103- elseif (utils["sym?"](k) and (tostring(k) == "&as")) then
31043104- destructure_sym(v, {utils.expr(tostring(s))}, left)
31053105- elseif (utils["sequence?"](left) and (tostring(v) == "&as")) then
31063106- local _, next_sym, trailing = select(k, unpack(left))
31073107- assert_compile((nil == trailing), "expected &as argument before last parameter", left)
31083108- destructure_sym(next_sym, {utils.expr(tostring(s))}, left)
31093109- else
31103110- local key
31113111- if (type(k) == "string") then
31123112- key = serialize_string(k)
31133113- else
31143114- key = k
31153115- end
31163116- local subexpr = utils.expr(string.format("%s[%s]", s, key), "expression")
31173117- if (type(k) == "string") then
31183118- table.insert(excluded_keys, k)
31193119- else
31203120- end
31213121- destructure1(v, {subexpr}, left)
31223122- end
31233123- else
31243124- end
31253125- end
31263126- return nil
31273127- end
31283128- local function destructure_values(left, up1, top_3f, destructure1)
31293129- local left_names, tables = {}, {}
31303130- for i, name in ipairs(left) do
31313131- if utils["sym?"](name) then
31323132- table.insert(left_names, getname(name, up1))
31333133- else
31343134- local symname = gensym(scope, symtype0)
31353135- table.insert(left_names, symname)
31363136- do end (tables)[i] = {name, utils.expr(symname, "sym")}
31373137- end
31383138- end
31393139- assert_compile(left[1], "must provide at least one value", left)
31403140- assert_compile(top_3f, "can't nest multi-value destructuring", left)
31413141- compile_top_target(left_names)
31423142- if declaration then
31433143- for _, sym in ipairs(left) do
31443144- if utils["sym?"](sym) then
31453145- scope.symmeta[tostring(sym)] = {var = isvar}
31463146- else
31473147- end
31483148- end
31493149- else
31503150- end
31513151- for _, pair in utils.stablepairs(tables) do
31523152- destructure1(pair[1], {pair[2]}, left)
31533153- end
31543154- return nil
31553155- end
31563156- local function destructure1(left, rightexprs, up1, top_3f)
31573157- if (utils["sym?"](left) and (left[1] ~= "nil")) then
31583158- destructure_sym(left, rightexprs, up1, top_3f)
31593159- elseif utils["table?"](left) then
31603160- destructure_table(left, rightexprs, top_3f, destructure1)
31613161- elseif utils["list?"](left) then
31623162- destructure_values(left, up1, top_3f, destructure1)
31633163- else
31643164- assert_compile(false, string.format("unable to bind %s %s", type(left), tostring(left)), (((type((up1)[2]) == "table") and (up1)[2]) or up1))
31653165- end
31663166- if top_3f then
31673167- return {returned = true}
31683168- else
31693169- return nil
31703170- end
31713171- end
31723172- local ret = destructure1(to, nil, ast, true)
31733173- utils.hook("destructure", from, to, scope, opts0)
31743174- apply_manglings(scope, new_manglings, ast)
31753175- return ret
31763176- end
31773177- local function require_include(ast, scope, parent, opts)
31783178- opts.fallback = function(e, no_warn)
31793179- if (not no_warn and ("literal" == e.type)) then
31803180- utils.warn(("include module not found, falling back to require: %s"):format(tostring(e)))
31813181- else
31823182- end
31833183- return utils.expr(string.format("require(%s)", tostring(e)), "statement")
31843184- end
31853185- return scopes.global.specials.include(ast, scope, parent, opts)
31863186- end
31873187- local function compile_stream(strm, options)
31883188- local opts = utils.copy(options)
31893189- local old_globals = allowed_globals
31903190- local scope = (opts.scope or make_scope(scopes.global))
31913191- local vals = {}
31923192- local chunk = {}
31933193- do end (function(tgt, m, ...) return tgt[m](tgt, ...) end)(utils.root, "set-reset")
31943194- allowed_globals = opts.allowedGlobals
31953195- if (opts.indent == nil) then
31963196- opts.indent = " "
31973197- else
31983198- end
31993199- if opts.requireAsInclude then
32003200- scope.specials.require = require_include
32013201- else
32023202- end
32033203- utils.root.chunk, utils.root.scope, utils.root.options = chunk, scope, opts
32043204- for _, val in parser.parser(strm, opts.filename, opts) do
32053205- table.insert(vals, val)
32063206- end
32073207- for i = 1, #vals do
32083208- local exprs = compile1(vals[i], scope, chunk, {nval = (((i < #vals) and 0) or nil), tail = (i == #vals)})
32093209- keep_side_effects(exprs, chunk, nil, vals[i])
32103210- if (i == #vals) then
32113211- utils.hook("chunk", vals[i], scope)
32123212- else
32133213- end
32143214- end
32153215- allowed_globals = old_globals
32163216- utils.root.reset()
32173217- return flatten(chunk, opts)
32183218- end
32193219- local function compile_string(str, opts)
32203220- return compile_stream(parser["string-stream"](str), (opts or {}))
32213221- end
32223222- local function compile(ast, opts)
32233223- local opts0 = utils.copy(opts)
32243224- local old_globals = allowed_globals
32253225- local chunk = {}
32263226- local scope = (opts0.scope or make_scope(scopes.global))
32273227- do end (function(tgt, m, ...) return tgt[m](tgt, ...) end)(utils.root, "set-reset")
32283228- allowed_globals = opts0.allowedGlobals
32293229- if (opts0.indent == nil) then
32303230- opts0.indent = " "
32313231- else
32323232- end
32333233- if opts0.requireAsInclude then
32343234- scope.specials.require = require_include
32353235- else
32363236- end
32373237- utils.root.chunk, utils.root.scope, utils.root.options = chunk, scope, opts0
32383238- local exprs = compile1(ast, scope, chunk, {tail = true})
32393239- keep_side_effects(exprs, chunk, nil, ast)
32403240- utils.hook("chunk", ast, scope)
32413241- allowed_globals = old_globals
32423242- utils.root.reset()
32433243- return flatten(chunk, opts0)
32443244- end
32453245- local function traceback_frame(info)
32463246- if ((info.what == "C") and info.name) then
32473247- return string.format(" [C]: in function '%s'", info.name)
32483248- elseif (info.what == "C") then
32493249- return " [C]: in ?"
32503250- else
32513251- local remap = sourcemap[info.source]
32523252- if (remap and remap[info.currentline]) then
32533253- if ((remap[info.currentline][1] or "unknown") ~= "unknown") then
32543254- info.short_src = sourcemap[("@" .. remap[info.currentline][1])].short_src
32553255- else
32563256- info.short_src = remap.short_src
32573257- end
32583258- info.currentline = (remap[info.currentline][2] or -1)
32593259- else
32603260- end
32613261- if (info.what == "Lua") then
32623262- local function _395_()
32633263- if info.name then
32643264- return ("'" .. info.name .. "'")
32653265- else
32663266- return "?"
32673267- end
32683268- end
32693269- return string.format(" %s:%d: in function %s", info.short_src, info.currentline, _395_())
32703270- elseif (info.short_src == "(tail call)") then
32713271- return " (tail call)"
32723272- else
32733273- return string.format(" %s:%d: in main chunk", info.short_src, info.currentline)
32743274- end
32753275- end
32763276- end
32773277- local function traceback(_3fmsg, _3fstart)
32783278- local msg = tostring((_3fmsg or ""))
32793279- if ((msg:find("^Compile error") or msg:find("^Parse error")) and not utils["debug-on?"]("trace")) then
32803280- return msg
32813281- else
32823282- local lines = {}
32833283- if (msg:find(":%d+: Compile error") or msg:find(":%d+: Parse error")) then
32843284- table.insert(lines, msg)
32853285- else
32863286- local newmsg = msg:gsub("^[^:]*:%d+:%s+", "runtime error: ")
32873287- table.insert(lines, newmsg)
32883288- end
32893289- table.insert(lines, "stack traceback:")
32903290- local done_3f, level = false, (_3fstart or 2)
32913291- while not done_3f do
32923292- do
32933293- local _399_ = debug.getinfo(level, "Sln")
32943294- if (_399_ == nil) then
32953295- done_3f = true
32963296- elseif (nil ~= _399_) then
32973297- local info = _399_
32983298- table.insert(lines, traceback_frame(info))
32993299- else
33003300- end
33013301- end
33023302- level = (level + 1)
33033303- end
33043304- return table.concat(lines, "\n")
33053305- end
33063306- end
33073307- local function entry_transform(fk, fv)
33083308- local function _402_(k, v)
33093309- if (type(k) == "number") then
33103310- return k, fv(v)
33113311- else
33123312- return fk(k), fv(v)
33133313- end
33143314- end
33153315- return _402_
33163316- end
33173317- local function mixed_concat(t, joiner)
33183318- local seen = {}
33193319- local ret, s = "", ""
33203320- for k, v in ipairs(t) do
33213321- table.insert(seen, k)
33223322- ret = (ret .. s .. v)
33233323- s = joiner
33243324- end
33253325- for k, v in utils.stablepairs(t) do
33263326- if not seen[k] then
33273327- ret = (ret .. s .. "[" .. k .. "]" .. "=" .. v)
33283328- s = joiner
33293329- else
33303330- end
33313331- end
33323332- return ret
33333333- end
33343334- local function do_quote(form, scope, parent, runtime_3f)
33353335- local function q(x)
33363336- return do_quote(x, scope, parent, runtime_3f)
33373337- end
33383338- if utils["varg?"](form) then
33393339- assert_compile(not runtime_3f, "quoted ... may only be used at compile time", form)
33403340- return "_VARARG"
33413341- elseif utils["sym?"](form) then
33423342- local filename
33433343- if form.filename then
33443344- filename = string.format("%q", form.filename)
33453345- else
33463346- filename = "nil"
33473347- end
33483348- local symstr = tostring(form)
33493349- assert_compile(not runtime_3f, "symbols may only be used at compile time", form)
33503350- if (symstr:find("#$") or symstr:find("#[:.]")) then
33513351- return string.format("sym('%s', {filename=%s, line=%s})", autogensym(symstr, scope), filename, (form.line or "nil"))
33523352- else
33533353- return string.format("sym('%s', {quoted=true, filename=%s, line=%s})", symstr, filename, (form.line or "nil"))
33543354- end
33553355- elseif (utils["list?"](form) and utils["sym?"](form[1]) and (tostring(form[1]) == "unquote")) then
33563356- local payload = form[2]
33573357- local res = unpack(compile1(payload, scope, parent))
33583358- return res[1]
33593359- elseif utils["list?"](form) then
33603360- local mapped
33613361- local function _407_()
33623362- return nil
33633363- end
33643364- mapped = utils.kvmap(form, entry_transform(_407_, q))
33653365- local filename
33663366- if form.filename then
33673367- filename = string.format("%q", form.filename)
33683368- else
33693369- filename = "nil"
33703370- end
33713371- assert_compile(not runtime_3f, "lists may only be used at compile time", form)
33723372- return string.format(("setmetatable({filename=%s, line=%s, bytestart=%s, %s}" .. ", getmetatable(list()))"), filename, (form.line or "nil"), (form.bytestart or "nil"), mixed_concat(mapped, ", "))
33733373- elseif utils["sequence?"](form) then
33743374- local mapped = utils.kvmap(form, entry_transform(q, q))
33753375- local source = getmetatable(form)
33763376- local filename
33773377- if source.filename then
33783378- filename = string.format("%q", source.filename)
33793379- else
33803380- filename = "nil"
33813381- end
33823382- local _410_
33833383- if source then
33843384- _410_ = source.line
33853385- else
33863386- _410_ = "nil"
33873387- end
33883388- return string.format("setmetatable({%s}, {filename=%s, line=%s, sequence=%s})", mixed_concat(mapped, ", "), filename, _410_, "(getmetatable(sequence()))['sequence']")
33893389- elseif (type(form) == "table") then
33903390- local mapped = utils.kvmap(form, entry_transform(q, q))
33913391- local source = getmetatable(form)
33923392- local filename
33933393- if source.filename then
33943394- filename = string.format("%q", source.filename)
33953395- else
33963396- filename = "nil"
33973397- end
33983398- local function _413_()
33993399- if source then
34003400- return source.line
34013401- else
34023402- return "nil"
34033403- end
34043404- end
34053405- return string.format("setmetatable({%s}, {filename=%s, line=%s})", mixed_concat(mapped, ", "), filename, _413_())
34063406- elseif (type(form) == "string") then
34073407- return serialize_string(form)
34083408- else
34093409- return tostring(form)
34103410- end
34113411- end
34123412- return {compile = compile, compile1 = compile1, ["compile-stream"] = compile_stream, ["compile-string"] = compile_string, ["check-binding-valid"] = check_binding_valid, emit = emit, destructure = destructure, ["require-include"] = require_include, autogensym = autogensym, gensym = gensym, ["do-quote"] = do_quote, ["global-mangling"] = global_mangling, ["global-unmangling"] = global_unmangling, ["apply-manglings"] = apply_manglings, macroexpand = macroexpand_2a, ["declare-local"] = declare_local, ["make-scope"] = make_scope, ["keep-side-effects"] = keep_side_effects, ["symbol-to-expression"] = symbol_to_expression, assert = assert_compile, scopes = scopes, traceback = traceback, metadata = make_metadata(), sourcemap = sourcemap}
34133413-end
34143414-package.preload["fennel.friend"] = package.preload["fennel.friend"] or function(...)
34153415- local utils = require("fennel.utils")
34163416- local utf8_ok_3f, utf8 = pcall(require, "utf8")
34173417- local suggestions = {["unexpected multi symbol (.*)"] = {"removing periods or colons from %s"}, ["use of global (.*) is aliased by a local"] = {"renaming local %s", "refer to the global using _G.%s instead of directly"}, ["local (.*) was overshadowed by a special form or macro"] = {"renaming local %s"}, ["global (.*) conflicts with local"] = {"renaming local %s"}, ["expected var (.*)"] = {"declaring %s using var instead of let/local", "introducing a new local instead of changing the value of %s"}, ["expected macros to be table"] = {"ensuring your macro definitions return a table"}, ["expected each macro to be function"] = {"ensuring that the value for each key in your macros table contains a function", "avoid defining nested macro tables"}, ["macro not found in macro module"] = {"checking the keys of the imported macro module's returned table"}, ["macro tried to bind (.*) without gensym"] = {"changing to %s# when introducing identifiers inside macros"}, ["unknown identifier in strict mode: (.*)"] = {"looking to see if there's a typo", "using the _G table instead, eg. _G.%s if you really want a global", "moving this code to somewhere that %s is in scope", "binding %s as a local in the scope of this code"}, ["expected a function.* to call"] = {"removing the empty parentheses", "using square brackets if you want an empty table"}, ["cannot call literal value"] = {"checking for typos", "checking for a missing function name"}, ["unexpected vararg"] = {"putting \"...\" at the end of the fn parameters if the vararg was intended"}, ["multisym method calls may only be in call position"] = {"using a period instead of a colon to reference a table's fields", "putting parens around this"}, ["unused local (.*)"] = {"renaming the local to _%s if it is meant to be unused", "fixing a typo so %s is used", "disabling the linter which checks for unused locals"}, ["expected parameters"] = {"adding function parameters as a list of identifiers in brackets"}, ["unable to bind (.*)"] = {"replacing the %s with an identifier"}, ["expected rest argument before last parameter"] = {"moving & to right before the final identifier when destructuring"}, ["expected vararg as last parameter"] = {"moving the \"...\" to the end of the parameter list"}, ["expected symbol for function parameter: (.*)"] = {"changing %s to an identifier instead of a literal value"}, ["could not compile value of type "] = {"debugging the macro you're calling to return a list or table"}, ["expected local"] = {"looking for a typo", "looking for a local which is used out of its scope"}, ["expected body expression"] = {"putting some code in the body of this form after the bindings"}, ["expected binding and iterator"] = {"making sure you haven't omitted a local name or iterator"}, ["expected binding sequence"] = {"placing a table here in square brackets containing identifiers to bind"}, ["expected even number of name/value bindings"] = {"finding where the identifier or value is missing"}, ["may only be used at compile time"] = {"moving this to inside a macro if you need to manipulate symbols/lists", "using square brackets instead of parens to construct a table"}, ["unexpected closing delimiter (.)"] = {"deleting %s", "adding matching opening delimiter earlier"}, ["mismatched closing delimiter (.), expected (.)"] = {"replacing %s with %s", "deleting %s", "adding matching opening delimiter earlier"}, ["expected even number of values in table literal"] = {"removing a key", "adding a value"}, ["expected whitespace before opening delimiter"] = {"adding whitespace"}, ["invalid character: (.)"] = {"deleting or replacing %s", "avoiding reserved characters like \", \\, ', ~, ;, @, `, and comma"}, ["could not read number (.*)"] = {"removing the non-digit character", "beginning the identifier with a non-digit if it is not meant to be a number"}, ["can't start multisym segment with a digit"] = {"removing the digit", "adding a non-digit before the digit"}, ["malformed multisym"] = {"ensuring each period or colon is not followed by another period or colon"}, ["method must be last component"] = {"using a period instead of a colon for field access", "removing segments after the colon", "making the method call, then looking up the field on the result"}, ["$ and $... in hashfn are mutually exclusive"] = {"modifying the hashfn so it only contains $... or $, $1, $2, $3, etc"}, ["tried to reference a macro at runtime"] = {"renaming the macro so as not to conflict with locals"}, ["tried to reference a special form at runtime"] = {"wrapping the special in a function if you need it to be first class"}, ["missing subject"] = {"adding an item to operate on"}, ["expected even number of pattern/body pairs"] = {"checking that every pattern has a body to go with it", "adding _ before the final body"}, ["expected at least one pattern/body pair"] = {"adding a pattern and a body to execute when the pattern matches"}, ["unexpected arguments"] = {"removing an argument", "checking for typos"}, ["unexpected iterator clause"] = {"removing an argument", "checking for typos"}}
34183418- local unpack = (table.unpack or _G.unpack)
34193419- local function suggest(msg)
34203420- local suggestion = nil
34213421- for pat, sug in pairs(suggestions) do
34223422- local matches = {msg:match(pat)}
34233423- if (0 < #matches) then
34243424- if ("table" == type(sug)) then
34253425- local out = {}
34263426- for _, s in ipairs(sug) do
34273427- table.insert(out, s:format(unpack(matches)))
34283428- end
34293429- suggestion = out
34303430- else
34313431- suggestion = sug(matches)
34323432- end
34333433- else
34343434- end
34353435- end
34363436- return suggestion
34373437- end
34383438- local function read_line(filename, line, _3fsource)
34393439- if _3fsource then
34403440- local matcher = string.gmatch((_3fsource .. "\n"), "(.-)(\13?\n)")
34413441- for _ = 2, line do
34423442- matcher()
34433443- end
34443444- return matcher()
34453445- else
34463446- local f = assert(io.open(filename))
34473447- local function close_handlers_8_auto(ok_9_auto, ...)
34483448- f:close()
34493449- if ok_9_auto then
34503450- return ...
34513451- else
34523452- return error(..., 0)
34533453- end
34543454- end
34553455- local function _178_()
34563456- for _ = 2, line do
34573457- f:read()
34583458- end
34593459- return f:read()
34603460- end
34613461- return close_handlers_8_auto(_G.xpcall(_178_, (package.loaded.fennel or debug).traceback))
34623462- end
34633463- end
34643464- local function sub(str, start, _end)
34653465- if (_end < start) then
34663466- return ""
34673467- elseif utf8_ok_3f then
34683468- return string.sub(str, utf8.offset(str, start), ((utf8.offset(str, (_end + 1)) or (utf8.len(str) + 1)) - 1))
34693469- else
34703470- return string.sub(str, start, math.min(_end, str:len()))
34713471- end
34723472- end
34733473- local function highlight_line(codeline, col, _3fendcol)
34743474- local endcol = (_3fendcol or col)
34753475- local eol
34763476- if utf8_ok_3f then
34773477- eol = utf8.len(codeline)
34783478- else
34793479- eol = string.len(codeline)
34803480- end
34813481- return (sub(codeline, 1, col) .. "\27[7m" .. sub(codeline, (col + 1), (endcol + 1)) .. "\27[0m" .. sub(codeline, (endcol + 2), eol))
34823482- end
34833483- local function friendly_msg(msg, _182_, source)
34843484- local _arg_183_ = _182_
34853485- local filename = _arg_183_["filename"]
34863486- local line = _arg_183_["line"]
34873487- local col = _arg_183_["col"]
34883488- local endcol = _arg_183_["endcol"]
34893489- local ok, codeline = pcall(read_line, filename, line, source)
34903490- local out = {msg, ""}
34913491- if (ok and codeline) then
34923492- if col then
34933493- table.insert(out, highlight_line(codeline, col, endcol))
34943494- else
34953495- table.insert(out, codeline)
34963496- end
34973497- else
34983498- end
34993499- for _, suggestion in ipairs((suggest(msg) or {})) do
35003500- table.insert(out, ("* Try %s."):format(suggestion))
35013501- end
35023502- return table.concat(out, "\n")
35033503- end
35043504- local function assert_compile(condition, msg, ast, source)
35053505- if not condition then
35063506- local _let_186_ = utils["ast-source"](ast)
35073507- local filename = _let_186_["filename"]
35083508- local line = _let_186_["line"]
35093509- local col = _let_186_["col"]
35103510- error(friendly_msg(("Compile error in %s:%s:%s\n %s"):format((filename or "unknown"), (line or "?"), (col or "?"), msg), utils["ast-source"](ast), source), 0)
35113511- else
35123512- end
35133513- return condition
35143514- end
35153515- local function parse_error(msg, filename, line, col, source)
35163516- return error(friendly_msg(("Parse error in %s:%s:%s\n %s"):format(filename, line, col, msg), {filename = filename, line = line, col = col}, source), 0)
35173517- end
35183518- return {["assert-compile"] = assert_compile, ["parse-error"] = parse_error}
35193519-end
35203520-package.preload["fennel.parser"] = package.preload["fennel.parser"] or function(...)
35213521- local utils = require("fennel.utils")
35223522- local friend = require("fennel.friend")
35233523- local unpack = (table.unpack or _G.unpack)
35243524- local function granulate(getchunk)
35253525- local c, index, done_3f = "", 1, false
35263526- local function _188_(parser_state)
35273527- if not done_3f then
35283528- if (index <= #c) then
35293529- local b = c:byte(index)
35303530- index = (index + 1)
35313531- return b
35323532- else
35333533- local _189_ = getchunk(parser_state)
35343534- local function _190_()
35353535- local char = _189_
35363536- return (char ~= "")
35373537- end
35383538- if ((nil ~= _189_) and _190_()) then
35393539- local char = _189_
35403540- c = char
35413541- index = 2
35423542- return c:byte()
35433543- elseif true then
35443544- local _ = _189_
35453545- done_3f = true
35463546- return nil
35473547- else
35483548- return nil
35493549- end
35503550- end
35513551- else
35523552- return nil
35533553- end
35543554- end
35553555- local function _194_()
35563556- c = ""
35573557- return nil
35583558- end
35593559- return _188_, _194_
35603560- end
35613561- local function string_stream(str)
35623562- local str0 = str:gsub("^#!", ";;")
35633563- local index = 1
35643564- local function _195_()
35653565- local r = str0:byte(index)
35663566- index = (index + 1)
35673567- return r
35683568- end
35693569- return _195_
35703570- end
35713571- local delims = {[40] = 41, [41] = true, [91] = 93, [93] = true, [123] = 125, [125] = true}
35723572- local function sym_char_3f(b)
35733573- local b0
35743574- if ("number" == type(b)) then
35753575- b0 = b
35763576- else
35773577- b0 = string.byte(b)
35783578- end
35793579- return ((32 < b0) and not delims[b0] and (b0 ~= 127) and (b0 ~= 34) and (b0 ~= 39) and (b0 ~= 126) and (b0 ~= 59) and (b0 ~= 44) and (b0 ~= 64) and (b0 ~= 96))
35803580- end
35813581- local prefixes = {[35] = "hashfn", [39] = "quote", [44] = "unquote", [96] = "quote"}
35823582- local function char_starter_3f(b)
35833583- return ((function(_197_,_198_,_199_) return (_197_ < _198_) and (_198_ < _199_) end)(1,b,127) or (function(_200_,_201_,_202_) return (_200_ < _201_) and (_201_ < _202_) end)(192,b,247))
35843584- end
35853585- local function parser_fn(getbyte, filename, _203_)
35863586- local _arg_204_ = _203_
35873587- local source = _arg_204_["source"]
35883588- local unfriendly = _arg_204_["unfriendly"]
35893589- local comments = _arg_204_["comments"]
35903590- local options = _arg_204_
35913591- local stack = {}
35923592- local line, byteindex, col, prev_col, lastb = 1, 0, 0, 0, nil
35933593- local function ungetb(ub)
35943594- if char_starter_3f(ub) then
35953595- col = (col - 1)
35963596- else
35973597- end
35983598- if (ub == 10) then
35993599- line, col = (line - 1), prev_col
36003600- else
36013601- end
36023602- byteindex = (byteindex - 1)
36033603- lastb = ub
36043604- return nil
36053605- end
36063606- local function getb()
36073607- local r = nil
36083608- if lastb then
36093609- r, lastb = lastb, nil
36103610- else
36113611- r = getbyte({["stack-size"] = #stack})
36123612- end
36133613- byteindex = (byteindex + 1)
36143614- if (r and char_starter_3f(r)) then
36153615- col = (col + 1)
36163616- else
36173617- end
36183618- if (r == 10) then
36193619- line, col, prev_col = (line + 1), 0, col
36203620- else
36213621- end
36223622- return r
36233623- end
36243624- local function whitespace_3f(b)
36253625- local function _214_()
36263626- local t_213_ = options.whitespace
36273627- if (nil ~= t_213_) then
36283628- t_213_ = (t_213_)[b]
36293629- else
36303630- end
36313631- return t_213_
36323632- end
36333633- return ((b == 32) or (function(_210_,_211_,_212_) return (_210_ <= _211_) and (_211_ <= _212_) end)(9,b,13) or _214_())
36343634- end
36353635- local function parse_error(msg, _3fcol_adjust)
36363636- local col0 = (col + (_3fcol_adjust or -1))
36373637- if (nil == utils["hook-opts"]("parse-error", options, msg, filename, (line or "?"), col0, source, utils.root.reset)) then
36383638- utils.root.reset()
36393639- if (unfriendly or not _G.io or not _G.io.read) then
36403640- return error(string.format("%s:%s:%s Parse error: %s", filename, (line or "?"), col0, msg), 0)
36413641- else
36423642- return friend["parse-error"](msg, filename, (line or "?"), col0, source)
36433643- end
36443644- else
36453645- return nil
36463646- end
36473647- end
36483648- local function parse_stream()
36493649- local whitespace_since_dispatch, done_3f, retval = true
36503650- local function set_source_fields(source0)
36513651- source0.byteend, source0.endcol = byteindex, (col - 1)
36523652- return nil
36533653- end
36543654- local function dispatch(v)
36553655- local _218_ = stack[#stack]
36563656- if (_218_ == nil) then
36573657- retval, done_3f, whitespace_since_dispatch = v, true, false
36583658- return nil
36593659- elseif ((_G.type(_218_) == "table") and (nil ~= (_218_).prefix)) then
36603660- local prefix = (_218_).prefix
36613661- local source0
36623662- do
36633663- local _219_ = table.remove(stack)
36643664- set_source_fields(_219_)
36653665- source0 = _219_
36663666- end
36673667- local list = utils.list(utils.sym(prefix, source0), v)
36683668- for k, v0 in pairs(source0) do
36693669- list[k] = v0
36703670- end
36713671- return dispatch(list)
36723672- elseif (nil ~= _218_) then
36733673- local top = _218_
36743674- whitespace_since_dispatch = false
36753675- return table.insert(top, v)
36763676- else
36773677- return nil
36783678- end
36793679- end
36803680- local function badend()
36813681- local accum = utils.map(stack, "closer")
36823682- local _221_
36833683- if (#stack == 1) then
36843684- _221_ = ""
36853685- else
36863686- _221_ = "s"
36873687- end
36883688- return parse_error(string.format("expected closing delimiter%s %s", _221_, string.char(unpack(accum))))
36893689- end
36903690- local function skip_whitespace(b)
36913691- if (b and whitespace_3f(b)) then
36923692- whitespace_since_dispatch = true
36933693- return skip_whitespace(getb())
36943694- elseif (not b and (0 < #stack)) then
36953695- return badend()
36963696- else
36973697- return b
36983698- end
36993699- end
37003700- local function parse_comment(b, contents)
37013701- if (b and (10 ~= b)) then
37023702- local function _225_()
37033703- local _224_ = contents
37043704- table.insert(_224_, string.char(b))
37053705- return _224_
37063706- end
37073707- return parse_comment(getb(), _225_())
37083708- elseif comments then
37093709- ungetb(10)
37103710- return dispatch(utils.comment(table.concat(contents), {line = (line - 1), filename = filename}))
37113711- else
37123712- return nil
37133713- end
37143714- end
37153715- local function open_table(b)
37163716- if not whitespace_since_dispatch then
37173717- parse_error(("expected whitespace before opening delimiter " .. string.char(b)))
37183718- else
37193719- end
37203720- return table.insert(stack, {bytestart = byteindex, closer = delims[b], filename = filename, line = line, col = (col - 1)})
37213721- end
37223722- local function close_list(list)
37233723- return dispatch(setmetatable(list, getmetatable(utils.list())))
37243724- end
37253725- local function close_sequence(tbl)
37263726- local val = utils.sequence(unpack(tbl))
37273727- for k, v in pairs(tbl) do
37283728- getmetatable(val)[k] = v
37293729- end
37303730- return dispatch(val)
37313731- end
37323732- local function add_comment_at(comments0, index, node)
37333733- local _228_ = (comments0)[index]
37343734- if (nil ~= _228_) then
37353735- local existing = _228_
37363736- return table.insert(existing, node)
37373737- elseif true then
37383738- local _ = _228_
37393739- comments0[index] = {node}
37403740- return nil
37413741- else
37423742- return nil
37433743- end
37443744- end
37453745- local function next_noncomment(tbl, i)
37463746- if utils["comment?"](tbl[i]) then
37473747- return next_noncomment(tbl, (i + 1))
37483748- else
37493749- return tbl[i]
37503750- end
37513751- end
37523752- local function extract_comments(tbl)
37533753- local comments0 = {keys = {}, values = {}, last = {}}
37543754- while utils["comment?"](tbl[#tbl]) do
37553755- table.insert(comments0.last, 1, table.remove(tbl))
37563756- end
37573757- local last_key_3f = false
37583758- for i, node in ipairs(tbl) do
37593759- if not utils["comment?"](node) then
37603760- last_key_3f = not last_key_3f
37613761- elseif last_key_3f then
37623762- add_comment_at(comments0.values, next_noncomment(tbl, i), node)
37633763- else
37643764- add_comment_at(comments0.keys, next_noncomment(tbl, i), node)
37653765- end
37663766- end
37673767- for i = #tbl, 1, -1 do
37683768- if utils["comment?"](tbl[i]) then
37693769- table.remove(tbl, i)
37703770- else
37713771- end
37723772- end
37733773- return comments0
37743774- end
37753775- local function close_curly_table(tbl)
37763776- local comments0 = extract_comments(tbl)
37773777- local keys = {}
37783778- local val = {}
37793779- if ((#tbl % 2) ~= 0) then
37803780- byteindex = (byteindex - 1)
37813781- parse_error("expected even number of values in table literal")
37823782- else
37833783- end
37843784- setmetatable(val, tbl)
37853785- for i = 1, #tbl, 2 do
37863786- if ((tostring(tbl[i]) == ":") and utils["sym?"](tbl[(i + 1)]) and utils["sym?"](tbl[i])) then
37873787- tbl[i] = tostring(tbl[(i + 1)])
37883788- else
37893789- end
37903790- val[tbl[i]] = tbl[(i + 1)]
37913791- table.insert(keys, tbl[i])
37923792- end
37933793- tbl.comments = comments0
37943794- tbl.keys = keys
37953795- return dispatch(val)
37963796- end
37973797- local function close_table(b)
37983798- local top = table.remove(stack)
37993799- if (top == nil) then
38003800- parse_error(("unexpected closing delimiter " .. string.char(b)))
38013801- else
38023802- end
38033803- if (top.closer and (top.closer ~= b)) then
38043804- parse_error(("mismatched closing delimiter " .. string.char(b) .. ", expected " .. string.char(top.closer)))
38053805- else
38063806- end
38073807- set_source_fields(top)
38083808- if (b == 41) then
38093809- return close_list(top)
38103810- elseif (b == 93) then
38113811- return close_sequence(top)
38123812- else
38133813- return close_curly_table(top)
38143814- end
38153815- end
38163816- local function parse_string_loop(chars, b, state)
38173817- table.insert(chars, b)
38183818- local state0
38193819- do
38203820- local _238_ = {state, b}
38213821- if ((_G.type(_238_) == "table") and ((_238_)[1] == "base") and ((_238_)[2] == 92)) then
38223822- state0 = "backslash"
38233823- elseif ((_G.type(_238_) == "table") and ((_238_)[1] == "base") and ((_238_)[2] == 34)) then
38243824- state0 = "done"
38253825- elseif ((_G.type(_238_) == "table") and ((_238_)[1] == "backslash") and ((_238_)[2] == 10)) then
38263826- table.remove(chars, (#chars - 1))
38273827- state0 = "base"
38283828- elseif true then
38293829- local _ = _238_
38303830- state0 = "base"
38313831- else
38323832- state0 = nil
38333833- end
38343834- end
38353835- if (b and (state0 ~= "done")) then
38363836- return parse_string_loop(chars, getb(), state0)
38373837- else
38383838- return b
38393839- end
38403840- end
38413841- local function escape_char(c)
38423842- return ({[7] = "\\a", [8] = "\\b", [9] = "\\t", [10] = "\\n", [11] = "\\v", [12] = "\\f", [13] = "\\r"})[c:byte()]
38433843- end
38443844- local function parse_string()
38453845- table.insert(stack, {closer = 34})
38463846- local chars = {34}
38473847- if not parse_string_loop(chars, getb(), "base") then
38483848- badend()
38493849- else
38503850- end
38513851- table.remove(stack)
38523852- local raw = string.char(unpack(chars))
38533853- local formatted = raw:gsub("[\7-\13]", escape_char)
38543854- local _242_ = (rawget(_G, "loadstring") or load)(("return " .. formatted))
38553855- if (nil ~= _242_) then
38563856- local load_fn = _242_
38573857- return dispatch(load_fn())
38583858- elseif (_242_ == nil) then
38593859- return parse_error(("Invalid string: " .. raw))
38603860- else
38613861- return nil
38623862- end
38633863- end
38643864- local function parse_prefix(b)
38653865- table.insert(stack, {prefix = prefixes[b], filename = filename, line = line, bytestart = byteindex, col = (col - 1)})
38663866- local nextb = getb()
38673867- if (whitespace_3f(nextb) or (true == delims[nextb])) then
38683868- if (b ~= 35) then
38693869- parse_error("invalid whitespace after quoting prefix")
38703870- else
38713871- end
38723872- table.remove(stack)
38733873- dispatch(utils.sym("#"))
38743874- else
38753875- end
38763876- return ungetb(nextb)
38773877- end
38783878- local function parse_sym_loop(chars, b)
38793879- if (b and sym_char_3f(b)) then
38803880- table.insert(chars, b)
38813881- return parse_sym_loop(chars, getb())
38823882- else
38833883- if b then
38843884- ungetb(b)
38853885- else
38863886- end
38873887- return chars
38883888- end
38893889- end
38903890- local function parse_number(rawstr)
38913891- local number_with_stripped_underscores = (not rawstr:find("^_") and rawstr:gsub("_", ""))
38923892- if rawstr:match("^%d") then
38933893- dispatch((tonumber(number_with_stripped_underscores) or parse_error(("could not read number \"" .. rawstr .. "\""))))
38943894- return true
38953895- else
38963896- local _248_ = tonumber(number_with_stripped_underscores)
38973897- if (nil ~= _248_) then
38983898- local x = _248_
38993899- dispatch(x)
39003900- return true
39013901- elseif true then
39023902- local _ = _248_
39033903- return false
39043904- else
39053905- return nil
39063906- end
39073907- end
39083908- end
39093909- local function check_malformed_sym(rawstr)
39103910- local function col_adjust(pat)
39113911- return (rawstr:find(pat) - utils.len(rawstr) - 1)
39123912- end
39133913- if (rawstr:match("^~") and (rawstr ~= "~=")) then
39143914- return parse_error("invalid character: ~")
39153915- elseif rawstr:match("%.[0-9]") then
39163916- return parse_error(("can't start multisym segment with a digit: " .. rawstr), col_adjust("%.[0-9]"))
39173917- elseif (rawstr:match("[%.:][%.:]") and (rawstr ~= "..") and (rawstr ~= "$...")) then
39183918- return parse_error(("malformed multisym: " .. rawstr), col_adjust("[%.:][%.:]"))
39193919- elseif ((rawstr ~= ":") and rawstr:match(":$")) then
39203920- return parse_error(("malformed multisym: " .. rawstr), col_adjust(":$"))
39213921- elseif rawstr:match(":.+[%.:]") then
39223922- return parse_error(("method must be last component of multisym: " .. rawstr), col_adjust(":.+[%.:]"))
39233923- else
39243924- return rawstr
39253925- end
39263926- end
39273927- local function parse_sym(b)
39283928- local source0 = {bytestart = byteindex, filename = filename, line = line, col = (col - 1)}
39293929- local rawstr = string.char(unpack(parse_sym_loop({b}, getb())))
39303930- set_source_fields(source0)
39313931- if (rawstr == "true") then
39323932- return dispatch(true)
39333933- elseif (rawstr == "false") then
39343934- return dispatch(false)
39353935- elseif (rawstr == "...") then
39363936- return dispatch(utils.varg(source0))
39373937- elseif rawstr:match("^:.+$") then
39383938- return dispatch(rawstr:sub(2))
39393939- elseif not parse_number(rawstr) then
39403940- return dispatch(utils.sym(check_malformed_sym(rawstr), source0))
39413941- else
39423942- return nil
39433943- end
39443944- end
39453945- local function parse_loop(b)
39463946- if not b then
39473947- elseif (b == 59) then
39483948- parse_comment(getb(), {";"})
39493949- elseif (type(delims[b]) == "number") then
39503950- open_table(b)
39513951- elseif delims[b] then
39523952- close_table(b)
39533953- elseif (b == 34) then
39543954- parse_string(b)
39553955- elseif prefixes[b] then
39563956- parse_prefix(b)
39573957- elseif (sym_char_3f(b) or (b == string.byte("~"))) then
39583958- parse_sym(b)
39593959- elseif not utils["hook-opts"]("illegal-char", options, b, getb, ungetb, dispatch) then
39603960- parse_error(("invalid character: " .. string.char(b)))
39613961- else
39623962- end
39633963- if not b then
39643964- return nil
39653965- elseif done_3f then
39663966- return true, retval
39673967- else
39683968- return parse_loop(skip_whitespace(getb()))
39693969- end
39703970- end
39713971- return parse_loop(skip_whitespace(getb()))
39723972- end
39733973- local function _255_()
39743974- stack, line, byteindex, col, lastb = {}, 1, 0, 0, nil
39753975- return nil
39763976- end
39773977- return parse_stream, _255_
39783978- end
39793979- local function parser(stream_or_string, _3ffilename, _3foptions)
39803980- local filename = (_3ffilename or "unknown")
39813981- local options = (_3foptions or utils.root.options or {})
39823982- assert(("string" == type(filename)), "expected filename as second argument to parser")
39833983- if ("string" == type(stream_or_string)) then
39843984- return parser_fn(string_stream(stream_or_string), filename, options)
39853985- else
39863986- return parser_fn(stream_or_string, filename, options)
39873987- end
39883988- end
39893989- return {granulate = granulate, parser = parser, ["string-stream"] = string_stream, ["sym-char?"] = sym_char_3f}
39903990-end
39913991-local utils
39923992-package.preload["fennel.view"] = package.preload["fennel.view"] or function(...)
39933993- local type_order = {number = 1, boolean = 2, string = 3, table = 4, ["function"] = 5, userdata = 6, thread = 7}
39943994- local lua_pairs = pairs
39953995- local lua_ipairs = ipairs
39963996- local function pairs(t)
39973997- local _1_ = getmetatable(t)
39983998- if ((_G.type(_1_) == "table") and (nil ~= (_1_).__pairs)) then
39993999- local p = (_1_).__pairs
40004000- return p(t)
40014001- elseif true then
40024002- local _ = _1_
40034003- return lua_pairs(t)
40044004- else
40054005- return nil
40064006- end
40074007- end
40084008- local function ipairs(t)
40094009- local _3_ = getmetatable(t)
40104010- if ((_G.type(_3_) == "table") and (nil ~= (_3_).__ipairs)) then
40114011- local i = (_3_).__ipairs
40124012- return i(t)
40134013- elseif true then
40144014- local _ = _3_
40154015- return lua_ipairs(t)
40164016- else
40174017- return nil
40184018- end
40194019- end
40204020- local function length_2a(t)
40214021- local _5_ = getmetatable(t)
40224022- if ((_G.type(_5_) == "table") and (nil ~= (_5_).__len)) then
40234023- local l = (_5_).__len
40244024- return l(t)
40254025- elseif true then
40264026- local _ = _5_
40274027- return #t
40284028- else
40294029- return nil
40304030- end
40314031- end
40324032- local function sort_keys(_7_, _9_)
40334033- local _arg_8_ = _7_
40344034- local a = _arg_8_[1]
40354035- local _arg_10_ = _9_
40364036- local b = _arg_10_[1]
40374037- local ta = type(a)
40384038- local tb = type(b)
40394039- if ((ta == tb) and ((ta == "string") or (ta == "number"))) then
40404040- return (a < b)
40414041- else
40424042- local dta = type_order[ta]
40434043- local dtb = type_order[tb]
40444044- if (dta and dtb) then
40454045- return (dta < dtb)
40464046- elseif dta then
40474047- return true
40484048- elseif dtb then
40494049- return false
40504050- else
40514051- return (ta < tb)
40524052- end
40534053- end
40544054- end
40554055- local function max_index_gap(kv)
40564056- local gap = 0
40574057- if (0 < length_2a(kv)) then
40584058- local i = 0
40594059- for _, _13_ in ipairs(kv) do
40604060- local _each_14_ = _13_
40614061- local k = _each_14_[1]
40624062- if (gap < (k - i)) then
40634063- gap = (k - i)
40644064- else
40654065- end
40664066- i = k
40674067- end
40684068- else
40694069- end
40704070- return gap
40714071- end
40724072- local function fill_gaps(kv)
40734073- local missing_indexes = {}
40744074- local i = 0
40754075- for _, _17_ in ipairs(kv) do
40764076- local _each_18_ = _17_
40774077- local j = _each_18_[1]
40784078- i = (i + 1)
40794079- while (i < j) do
40804080- table.insert(missing_indexes, i)
40814081- i = (i + 1)
40824082- end
40834083- end
40844084- for _, k in ipairs(missing_indexes) do
40854085- table.insert(kv, k, {k})
40864086- end
40874087- return nil
40884088- end
40894089- local function table_kv_pairs(t, options)
40904090- local assoc_3f = false
40914091- local kv = {}
40924092- local insert = table.insert
40934093- for k, v in pairs(t) do
40944094- if ((type(k) ~= "number") or (k < 1)) then
40954095- assoc_3f = true
40964096- else
40974097- end
40984098- insert(kv, {k, v})
40994099- end
41004100- table.sort(kv, sort_keys)
41014101- if not assoc_3f then
41024102- if (options["max-sparse-gap"] < max_index_gap(kv)) then
41034103- assoc_3f = true
41044104- else
41054105- fill_gaps(kv)
41064106- end
41074107- else
41084108- end
41094109- if (length_2a(kv) == 0) then
41104110- return kv, "empty"
41114111- else
41124112- local function _22_()
41134113- if assoc_3f then
41144114- return "table"
41154115- else
41164116- return "seq"
41174117- end
41184118- end
41194119- return kv, _22_()
41204120- end
41214121- end
41224122- local function count_table_appearances(t, appearances)
41234123- if (type(t) == "table") then
41244124- if not appearances[t] then
41254125- appearances[t] = 1
41264126- for k, v in pairs(t) do
41274127- count_table_appearances(k, appearances)
41284128- count_table_appearances(v, appearances)
41294129- end
41304130- else
41314131- appearances[t] = ((appearances[t] or 0) + 1)
41324132- end
41334133- else
41344134- end
41354135- return appearances
41364136- end
41374137- local function save_table(t, seen)
41384138- local seen0 = (seen or {len = 0})
41394139- local id = (seen0.len + 1)
41404140- if not (seen0)[t] then
41414141- seen0[t] = id
41424142- seen0.len = id
41434143- else
41444144- end
41454145- return seen0
41464146- end
41474147- local function detect_cycle(t, seen, _3fk)
41484148- if ("table" == type(t)) then
41494149- seen[t] = true
41504150- local _27_, _28_ = next(t, _3fk)
41514151- if ((nil ~= _27_) and (nil ~= _28_)) then
41524152- local k = _27_
41534153- local v = _28_
41544154- return (seen[k] or detect_cycle(k, seen) or seen[v] or detect_cycle(v, seen) or detect_cycle(t, seen, k))
41554155- else
41564156- return nil
41574157- end
41584158- else
41594159- return nil
41604160- end
41614161- end
41624162- local function visible_cycle_3f(t, options)
41634163- return (options["detect-cycles?"] and detect_cycle(t, {}) and save_table(t, options.seen) and (1 < (options.appearances[t] or 0)))
41644164- end
41654165- local function table_indent(indent, id)
41664166- local opener_length
41674167- if id then
41684168- opener_length = (length_2a(tostring(id)) + 2)
41694169- else
41704170- opener_length = 1
41714171- end
41724172- return (indent + opener_length)
41734173- end
41744174- local pp = nil
41754175- local function concat_table_lines(elements, options, multiline_3f, indent, table_type, prefix, last_comment_3f)
41764176- local indent_str = ("\n" .. string.rep(" ", indent))
41774177- local open
41784178- local function _32_()
41794179- if ("seq" == table_type) then
41804180- return "["
41814181- else
41824182- return "{"
41834183- end
41844184- end
41854185- open = ((prefix or "") .. _32_())
41864186- local close
41874187- if ("seq" == table_type) then
41884188- close = "]"
41894189- else
41904190- close = "}"
41914191- end
41924192- local oneline = (open .. table.concat(elements, " ") .. close)
41934193- if (not options["one-line?"] and (multiline_3f or (options["line-length"] < (indent + length_2a(oneline))) or last_comment_3f)) then
41944194- local function _34_()
41954195- if last_comment_3f then
41964196- return indent_str
41974197- else
41984198- return ""
41994199- end
42004200- end
42014201- return (open .. table.concat(elements, indent_str) .. _34_() .. close)
42024202- else
42034203- return oneline
42044204- end
42054205- end
42064206- local function utf8_len(x)
42074207- local n = 0
42084208- for _ in string.gmatch(x, "[%z\1-\127\192-\247]") do
42094209- n = (n + 1)
42104210- end
42114211- return n
42124212- end
42134213- local function comment_3f(x)
42144214- if ("table" == type(x)) then
42154215- local fst = x[1]
42164216- return (("string" == type(fst)) and (nil ~= fst:find("^;")))
42174217- else
42184218- return false
42194219- end
42204220- end
42214221- local function pp_associative(t, kv, options, indent)
42224222- local multiline_3f = false
42234223- local id = options.seen[t]
42244224- if (options.depth <= options.level) then
42254225- return "{...}"
42264226- elseif (id and options["detect-cycles?"]) then
42274227- return ("@" .. id .. "{...}")
42284228- else
42294229- local visible_cycle_3f0 = visible_cycle_3f(t, options)
42304230- local id0 = (visible_cycle_3f0 and options.seen[t])
42314231- local indent0 = table_indent(indent, id0)
42324232- local slength
42334233- if options["utf8?"] then
42344234- slength = utf8_len
42354235- else
42364236- local function _37_(_241)
42374237- return #_241
42384238- end
42394239- slength = _37_
42404240- end
42414241- local prefix
42424242- if visible_cycle_3f0 then
42434243- prefix = ("@" .. id0)
42444244- else
42454245- prefix = ""
42464246- end
42474247- local items
42484248- do
42494249- local tbl_14_auto = {}
42504250- local i_15_auto = #tbl_14_auto
42514251- for _, _40_ in ipairs(kv) do
42524252- local _each_41_ = _40_
42534253- local k = _each_41_[1]
42544254- local v = _each_41_[2]
42554255- local val_16_auto
42564256- do
42574257- local k0 = pp(k, options, (indent0 + 1), true)
42584258- local v0 = pp(v, options, (indent0 + slength(k0) + 1))
42594259- multiline_3f = (multiline_3f or k0:find("\n") or v0:find("\n"))
42604260- val_16_auto = (k0 .. " " .. v0)
42614261- end
42624262- if (nil ~= val_16_auto) then
42634263- i_15_auto = (i_15_auto + 1)
42644264- do end (tbl_14_auto)[i_15_auto] = val_16_auto
42654265- else
42664266- end
42674267- end
42684268- items = tbl_14_auto
42694269- end
42704270- return concat_table_lines(items, options, multiline_3f, indent0, "table", prefix, false)
42714271- end
42724272- end
42734273- local function pp_sequence(t, kv, options, indent)
42744274- local multiline_3f = false
42754275- local id = options.seen[t]
42764276- if (options.depth <= options.level) then
42774277- return "[...]"
42784278- elseif (id and options["detect-cycles?"]) then
42794279- return ("@" .. id .. "[...]")
42804280- else
42814281- local visible_cycle_3f0 = visible_cycle_3f(t, options)
42824282- local id0 = (visible_cycle_3f0 and options.seen[t])
42834283- local indent0 = table_indent(indent, id0)
42844284- local prefix
42854285- if visible_cycle_3f0 then
42864286- prefix = ("@" .. id0)
42874287- else
42884288- prefix = ""
42894289- end
42904290- local last_comment_3f = comment_3f(t[#t])
42914291- local items
42924292- do
42934293- local tbl_14_auto = {}
42944294- local i_15_auto = #tbl_14_auto
42954295- for _, _45_ in ipairs(kv) do
42964296- local _each_46_ = _45_
42974297- local _0 = _each_46_[1]
42984298- local v = _each_46_[2]
42994299- local val_16_auto
43004300- do
43014301- local v0 = pp(v, options, indent0)
43024302- multiline_3f = (multiline_3f or v0:find("\n") or v0:find("^;"))
43034303- val_16_auto = v0
43044304- end
43054305- if (nil ~= val_16_auto) then
43064306- i_15_auto = (i_15_auto + 1)
43074307- do end (tbl_14_auto)[i_15_auto] = val_16_auto
43084308- else
43094309- end
43104310- end
43114311- items = tbl_14_auto
43124312- end
43134313- return concat_table_lines(items, options, multiline_3f, indent0, "seq", prefix, last_comment_3f)
43144314- end
43154315- end
43164316- local function concat_lines(lines, options, indent, force_multi_line_3f)
43174317- if (length_2a(lines) == 0) then
43184318- if options["empty-as-sequence?"] then
43194319- return "[]"
43204320- else
43214321- return "{}"
43224322- end
43234323- else
43244324- local oneline
43254325- local _50_
43264326- do
43274327- local tbl_14_auto = {}
43284328- local i_15_auto = #tbl_14_auto
43294329- for _, line in ipairs(lines) do
43304330- local val_16_auto = line:gsub("^%s+", "")
43314331- if (nil ~= val_16_auto) then
43324332- i_15_auto = (i_15_auto + 1)
43334333- do end (tbl_14_auto)[i_15_auto] = val_16_auto
43344334- else
43354335- end
43364336- end
43374337- _50_ = tbl_14_auto
43384338- end
43394339- oneline = table.concat(_50_, " ")
43404340- if (not options["one-line?"] and (force_multi_line_3f or oneline:find("\n") or (options["line-length"] < (indent + length_2a(oneline))))) then
43414341- return table.concat(lines, ("\n" .. string.rep(" ", indent)))
43424342- else
43434343- return oneline
43444344- end
43454345- end
43464346- end
43474347- local function pp_metamethod(t, metamethod, options, indent)
43484348- if (options.depth <= options.level) then
43494349- if options["empty-as-sequence?"] then
43504350- return "[...]"
43514351- else
43524352- return "{...}"
43534353- end
43544354- else
43554355- local _
43564356- local function _55_(_241)
43574357- return visible_cycle_3f(_241, options)
43584358- end
43594359- options["visible-cycle?"] = _55_
43604360- _ = nil
43614361- local lines, force_multi_line_3f = metamethod(t, pp, options, indent)
43624362- options["visible-cycle?"] = nil
43634363- local _56_ = type(lines)
43644364- if (_56_ == "string") then
43654365- return lines
43664366- elseif (_56_ == "table") then
43674367- return concat_lines(lines, options, indent, force_multi_line_3f)
43684368- elseif true then
43694369- local _0 = _56_
43704370- return error("__fennelview metamethod must return a table of lines")
43714371- else
43724372- return nil
43734373- end
43744374- end
43754375- end
43764376- local function pp_table(x, options, indent)
43774377- options.level = (options.level + 1)
43784378- local x0
43794379- do
43804380- local _59_
43814381- if options["metamethod?"] then
43824382- local _60_ = x
43834383- if (nil ~= _60_) then
43844384- local _61_ = getmetatable(_60_)
43854385- if (nil ~= _61_) then
43864386- _59_ = (_61_).__fennelview
43874387- else
43884388- _59_ = _61_
43894389- end
43904390- else
43914391- _59_ = _60_
43924392- end
43934393- else
43944394- _59_ = nil
43954395- end
43964396- if (nil ~= _59_) then
43974397- local metamethod = _59_
43984398- x0 = pp_metamethod(x, metamethod, options, indent)
43994399- elseif true then
44004400- local _ = _59_
44014401- local _65_, _66_ = table_kv_pairs(x, options)
44024402- if (true and (_66_ == "empty")) then
44034403- local _0 = _65_
44044404- if options["empty-as-sequence?"] then
44054405- x0 = "[]"
44064406- else
44074407- x0 = "{}"
44084408- end
44094409- elseif ((nil ~= _65_) and (_66_ == "table")) then
44104410- local kv = _65_
44114411- x0 = pp_associative(x, kv, options, indent)
44124412- elseif ((nil ~= _65_) and (_66_ == "seq")) then
44134413- local kv = _65_
44144414- x0 = pp_sequence(x, kv, options, indent)
44154415- else
44164416- x0 = nil
44174417- end
44184418- else
44194419- x0 = nil
44204420- end
44214421- end
44224422- options.level = (options.level - 1)
44234423- return x0
44244424- end
44254425- local function number__3estring(n)
44264426- local _70_ = string.gsub(tostring(n), ",", ".")
44274427- return _70_
44284428- end
44294429- local function colon_string_3f(s)
44304430- return s:find("^[-%w?^_!$%&*+./@|<=>]+$")
44314431- end
44324432- local utf8_inits = {{["min-byte"] = 0, ["max-byte"] = 127, ["min-code"] = 0, ["max-code"] = 127, len = 1}, {["min-byte"] = 192, ["max-byte"] = 223, ["min-code"] = 128, ["max-code"] = 2047, len = 2}, {["min-byte"] = 224, ["max-byte"] = 239, ["min-code"] = 2048, ["max-code"] = 65535, len = 3}, {["min-byte"] = 240, ["max-byte"] = 247, ["min-code"] = 65536, ["max-code"] = 1114111, len = 4}}
44334433- local function utf8_escape(str)
44344434- local function validate_utf8(str0, index)
44354435- local inits = utf8_inits
44364436- local byte = string.byte(str0, index)
44374437- local init
44384438- do
44394439- local ret = nil
44404440- for _, init0 in ipairs(inits) do
44414441- if ret then break end
44424442- ret = (byte and (function(_71_,_72_,_73_) return (_71_ <= _72_) and (_72_ <= _73_) end)(init0["min-byte"],byte,init0["max-byte"]) and init0)
44434443- end
44444444- init = ret
44454445- end
44464446- local code
44474447- local function _74_()
44484448- local code0
44494449- if init then
44504450- code0 = (byte - init["min-byte"])
44514451- else
44524452- code0 = nil
44534453- end
44544454- for i = (index + 1), (index + init.len + -1) do
44554455- local byte0 = string.byte(str0, i)
44564456- code0 = (byte0 and code0 and (function(_76_,_77_,_78_) return (_76_ <= _77_) and (_77_ <= _78_) end)(128,byte0,191) and ((code0 * 64) + (byte0 - 128)))
44574457- end
44584458- return code0
44594459- end
44604460- code = (init and _74_())
44614461- if (code and (function(_79_,_80_,_81_) return (_79_ <= _80_) and (_80_ <= _81_) end)(init["min-code"],code,init["max-code"]) and not (function(_82_,_83_,_84_) return (_82_ <= _83_) and (_83_ <= _84_) end)(55296,code,57343)) then
44624462- return init.len
44634463- else
44644464- return nil
44654465- end
44664466- end
44674467- local index = 1
44684468- local output = {}
44694469- while (index <= #str) do
44704470- local nexti = (string.find(str, "[\128-\255]", index) or (#str + 1))
44714471- local len = validate_utf8(str, nexti)
44724472- table.insert(output, string.sub(str, index, (nexti + (len or 0) + -1)))
44734473- if (not len and (nexti <= #str)) then
44744474- table.insert(output, string.format("\\%03d", string.byte(str, nexti)))
44754475- else
44764476- end
44774477- if len then
44784478- index = (nexti + len)
44794479- else
44804480- index = (nexti + 1)
44814481- end
44824482- end
44834483- return table.concat(output)
44844484- end
44854485- local function pp_string(str, options, indent)
44864486- local escs
44874487- local _88_
44884488- if (options["escape-newlines?"] and (length_2a(str) < (options["line-length"] - indent))) then
44894489- _88_ = "\\n"
44904490- else
44914491- _88_ = "\n"
44924492- end
44934493- local function _90_(_241, _242)
44944494- return ("\\%03d"):format(_242:byte())
44954495- end
44964496- escs = setmetatable({["\7"] = "\\a", ["\8"] = "\\b", ["\12"] = "\\f", ["\11"] = "\\v", ["\13"] = "\\r", ["\9"] = "\\t", ["\\"] = "\\\\", ["\""] = "\\\"", ["\n"] = _88_}, {__index = _90_})
44974497- local str0 = ("\"" .. str:gsub("[%c\\\"]", escs) .. "\"")
44984498- if options["utf8?"] then
44994499- return utf8_escape(str0)
45004500- else
45014501- return str0
45024502- end
45034503- end
45044504- local function make_options(t, options)
45054505- local defaults = {["line-length"] = 80, ["one-line?"] = false, depth = 128, ["detect-cycles?"] = true, ["empty-as-sequence?"] = false, ["metamethod?"] = true, ["prefer-colon?"] = false, ["escape-newlines?"] = false, ["utf8?"] = true, ["max-sparse-gap"] = 10}
45064506- local overrides = {level = 0, appearances = count_table_appearances(t, {}), seen = {len = 0}}
45074507- for k, v in pairs((options or {})) do
45084508- defaults[k] = v
45094509- end
45104510- for k, v in pairs(overrides) do
45114511- defaults[k] = v
45124512- end
45134513- return defaults
45144514- end
45154515- local function _92_(x, options, indent, colon_3f)
45164516- local indent0 = (indent or 0)
45174517- local options0 = (options or make_options(x))
45184518- local x0
45194519- if options0.preprocess then
45204520- x0 = options0.preprocess(x, options0)
45214521- else
45224522- x0 = x
45234523- end
45244524- local tv = type(x0)
45254525- local function _95_()
45264526- local _94_ = getmetatable(x0)
45274527- if (nil ~= _94_) then
45284528- return (_94_).__fennelview
45294529- else
45304530- return _94_
45314531- end
45324532- end
45334533- if ((tv == "table") or ((tv == "userdata") and _95_())) then
45344534- return pp_table(x0, options0, indent0)
45354535- elseif (tv == "number") then
45364536- return number__3estring(x0)
45374537- else
45384538- local function _97_()
45394539- if (colon_3f ~= nil) then
45404540- return colon_3f
45414541- elseif ("function" == type(options0["prefer-colon?"])) then
45424542- return options0["prefer-colon?"](x0)
45434543- else
45444544- return options0["prefer-colon?"]
45454545- end
45464546- end
45474547- if ((tv == "string") and colon_string_3f(x0) and _97_()) then
45484548- return (":" .. x0)
45494549- elseif (tv == "string") then
45504550- return pp_string(x0, options0, indent0)
45514551- elseif ((tv == "boolean") or (tv == "nil")) then
45524552- return tostring(x0)
45534553- else
45544554- return ("#<" .. tostring(x0) .. ">")
45554555- end
45564556- end
45574557- end
45584558- pp = _92_
45594559- local function view(x, _3foptions)
45604560- return pp(x, make_options(x, _3foptions), 0)
45614561- end
45624562- return view
45634563-end
45644564-package.preload["fennel.utils"] = package.preload["fennel.utils"] or function(...)
45654565- local view = require("fennel.view")
45664566- local version = "1.2.1"
45674567- local function luajit_vm_3f()
45684568- return ((nil ~= _G.jit) and (type(_G.jit) == "table") and (nil ~= _G.jit.on) and (nil ~= _G.jit.off) and (type(_G.jit.version_num) == "number"))
45694569- end
45704570- local function luajit_vm_version()
45714571- local jit_os
45724572- if (_G.jit.os == "OSX") then
45734573- jit_os = "macOS"
45744574- else
45754575- jit_os = _G.jit.os
45764576- end
45774577- return (_G.jit.version .. " " .. jit_os .. "/" .. _G.jit.arch)
45784578- end
45794579- local function fengari_vm_3f()
45804580- return ((nil ~= _G.fengari) and (type(_G.fengari) == "table") and (nil ~= _G.fengari.VERSION) and (type(_G.fengari.VERSION_NUM) == "number"))
45814581- end
45824582- local function fengari_vm_version()
45834583- return (_G.fengari.RELEASE .. " (" .. _VERSION .. ")")
45844584- end
45854585- local function lua_vm_version()
45864586- if luajit_vm_3f() then
45874587- return luajit_vm_version()
45884588- elseif fengari_vm_3f() then
45894589- return fengari_vm_version()
45904590- else
45914591- return ("PUC " .. _VERSION)
45924592- end
45934593- end
45944594- local function runtime_version()
45954595- return ("Fennel " .. version .. " on " .. lua_vm_version())
45964596- end
45974597- local function warn(message)
45984598- if (_G.io and _G.io.stderr) then
45994599- return (_G.io.stderr):write(("--WARNING: %s\n"):format(tostring(message)))
46004600- else
46014601- return nil
46024602- end
46034603- end
46044604- local len
46054605- do
46064606- local _102_, _103_ = pcall(require, "utf8")
46074607- if ((_102_ == true) and (nil ~= _103_)) then
46084608- local utf8 = _103_
46094609- len = utf8.len
46104610- elseif true then
46114611- local _ = _102_
46124612- len = string.len
46134613- else
46144614- len = nil
46154615- end
46164616- end
46174617- local function mt_keys_in_order(t, out, used_keys)
46184618- for _, k in ipairs(getmetatable(t).keys) do
46194619- if (t[k] and not used_keys[k]) then
46204620- used_keys[k] = true
46214621- table.insert(out, k)
46224622- else
46234623- end
46244624- end
46254625- for k in pairs(t) do
46264626- if not used_keys[k] then
46274627- table.insert(out, k)
46284628- else
46294629- end
46304630- end
46314631- return out
46324632- end
46334633- local function stablepairs(t)
46344634- local keys
46354635- local _108_
46364636- do
46374637- local t_107_ = getmetatable(t)
46384638- if (nil ~= t_107_) then
46394639- t_107_ = (t_107_).keys
46404640- else
46414641- end
46424642- _108_ = t_107_
46434643- end
46444644- if _108_ then
46454645- keys = mt_keys_in_order(t, {}, {})
46464646- else
46474647- local _110_
46484648- do
46494649- local tbl_14_auto = {}
46504650- local i_15_auto = #tbl_14_auto
46514651- for k in pairs(t) do
46524652- local val_16_auto = k
46534653- if (nil ~= val_16_auto) then
46544654- i_15_auto = (i_15_auto + 1)
46554655- do end (tbl_14_auto)[i_15_auto] = val_16_auto
46564656- else
46574657- end
46584658- end
46594659- _110_ = tbl_14_auto
46604660- end
46614661- local function _112_(_241, _242)
46624662- return (tostring(_241) < tostring(_242))
46634663- end
46644664- table.sort(_110_, _112_)
46654665- keys = _110_
46664666- end
46674667- local succ
46684668- do
46694669- local tbl_11_auto = {}
46704670- for i, k in ipairs(keys) do
46714671- local _114_, _115_ = k, keys[(i + 1)]
46724672- if ((nil ~= _114_) and (nil ~= _115_)) then
46734673- local k_12_auto = _114_
46744674- local v_13_auto = _115_
46754675- tbl_11_auto[k_12_auto] = v_13_auto
46764676- else
46774677- end
46784678- end
46794679- succ = tbl_11_auto
46804680- end
46814681- local function stablenext(tbl, key)
46824682- local next_key
46834683- if (key == nil) then
46844684- next_key = keys[1]
46854685- else
46864686- next_key = succ[key]
46874687- end
46884688- return next_key, tbl[next_key]
46894689- end
46904690- return stablenext, t, nil
46914691- end
46924692- local function get_in(tbl, path, _3ffallback)
46934693- assert(("table" == type(tbl)), "get-in expects path to be a table")
46944694- if (0 == #path) then
46954695- return _3ffallback
46964696- else
46974697- local _118_
46984698- do
46994699- local t = tbl
47004700- for _, k in ipairs(path) do
47014701- if (nil == t) then break end
47024702- local _119_ = type(t)
47034703- if (_119_ == "table") then
47044704- t = t[k]
47054705- else
47064706- t = nil
47074707- end
47084708- end
47094709- _118_ = t
47104710- end
47114711- if (nil ~= _118_) then
47124712- local res = _118_
47134713- return res
47144714- elseif true then
47154715- local _ = _118_
47164716- return _3ffallback
47174717- else
47184718- return nil
47194719- end
47204720- end
47214721- end
47224722- local function map(t, f, _3fout)
47234723- local out = (_3fout or {})
47244724- local f0
47254725- if (type(f) == "function") then
47264726- f0 = f
47274727- else
47284728- local function _123_(_241)
47294729- return (_241)[f]
47304730- end
47314731- f0 = _123_
47324732- end
47334733- for _, x in ipairs(t) do
47344734- local _125_ = f0(x)
47354735- if (nil ~= _125_) then
47364736- local v = _125_
47374737- table.insert(out, v)
47384738- else
47394739- end
47404740- end
47414741- return out
47424742- end
47434743- local function kvmap(t, f, _3fout)
47444744- local out = (_3fout or {})
47454745- local f0
47464746- if (type(f) == "function") then
47474747- f0 = f
47484748- else
47494749- local function _127_(_241)
47504750- return (_241)[f]
47514751- end
47524752- f0 = _127_
47534753- end
47544754- for k, x in stablepairs(t) do
47554755- local _129_, _130_ = f0(k, x)
47564756- if ((nil ~= _129_) and (nil ~= _130_)) then
47574757- local key = _129_
47584758- local value = _130_
47594759- out[key] = value
47604760- elseif (nil ~= _129_) then
47614761- local value = _129_
47624762- table.insert(out, value)
47634763- else
47644764- end
47654765- end
47664766- return out
47674767- end
47684768- local function copy(from, _3fto)
47694769- local tbl_11_auto = (_3fto or {})
47704770- for k, v in pairs((from or {})) do
47714771- local _132_, _133_ = k, v
47724772- if ((nil ~= _132_) and (nil ~= _133_)) then
47734773- local k_12_auto = _132_
47744774- local v_13_auto = _133_
47754775- tbl_11_auto[k_12_auto] = v_13_auto
47764776- else
47774777- end
47784778- end
47794779- return tbl_11_auto
47804780- end
47814781- local function member_3f(x, tbl, _3fn)
47824782- local _135_ = tbl[(_3fn or 1)]
47834783- if (_135_ == x) then
47844784- return true
47854785- elseif (_135_ == nil) then
47864786- return nil
47874787- elseif true then
47884788- local _ = _135_
47894789- return member_3f(x, tbl, ((_3fn or 1) + 1))
47904790- else
47914791- return nil
47924792- end
47934793- end
47944794- local function allpairs(tbl)
47954795- assert((type(tbl) == "table"), "allpairs expects a table")
47964796- local t = tbl
47974797- local seen = {}
47984798- local function allpairs_next(_, state)
47994799- local next_state, value = next(t, state)
48004800- if seen[next_state] then
48014801- return allpairs_next(nil, next_state)
48024802- elseif next_state then
48034803- seen[next_state] = true
48044804- return next_state, value
48054805- else
48064806- local _137_ = getmetatable(t)
48074807- if ((_G.type(_137_) == "table") and true) then
48084808- local __index = (_137_).__index
48094809- if ("table" == type(__index)) then
48104810- t = __index
48114811- return allpairs_next(t)
48124812- else
48134813- return nil
48144814- end
48154815- else
48164816- return nil
48174817- end
48184818- end
48194819- end
48204820- return allpairs_next
48214821- end
48224822- local function deref(self)
48234823- return self[1]
48244824- end
48254825- local nil_sym = nil
48264826- local function list__3estring(self, _3ftostring2)
48274827- local safe = {}
48284828- local max = 0
48294829- for k in pairs(self) do
48304830- if ((type(k) == "number") and (max < k)) then
48314831- max = k
48324832- else
48334833- end
48344834- end
48354835- for i = 1, max do
48364836- safe[i] = (((self[i] == nil) and nil_sym) or self[i])
48374837- end
48384838- return ("(" .. table.concat(map(safe, (_3ftostring2 or view)), " ", 1, max) .. ")")
48394839- end
48404840- local function comment_view(c)
48414841- return c, true
48424842- end
48434843- local function sym_3d(a, b)
48444844- return ((deref(a) == deref(b)) and (getmetatable(a) == getmetatable(b)))
48454845- end
48464846- local function sym_3c(a, b)
48474847- return (a[1] < tostring(b))
48484848- end
48494849- local symbol_mt = {__fennelview = deref, __tostring = deref, __eq = sym_3d, __lt = sym_3c, "SYMBOL"}
48504850- local expr_mt
48514851- local function _142_(x)
48524852- return tostring(deref(x))
48534853- end
48544854- expr_mt = {__tostring = _142_, "EXPR"}
48554855- local list_mt = {__fennelview = list__3estring, __tostring = list__3estring, "LIST"}
48564856- local comment_mt = {__fennelview = comment_view, __tostring = deref, __eq = sym_3d, __lt = sym_3c, "COMMENT"}
48574857- local sequence_marker = {"SEQUENCE"}
48584858- local varg_mt = {__fennelview = deref, __tostring = deref, "VARARG"}
48594859- local getenv
48604860- local function _143_()
48614861- return nil
48624862- end
48634863- getenv = ((os and os.getenv) or _143_)
48644864- local function debug_on_3f(flag)
48654865- local level = (getenv("FENNEL_DEBUG") or "")
48664866- return ((level == "all") or level:find(flag))
48674867- end
48684868- local function list(...)
48694869- return setmetatable({...}, list_mt)
48704870- end
48714871- local function sym(str, _3fsource)
48724872- local _144_
48734873- do
48744874- local tbl_11_auto = {str}
48754875- for k, v in pairs((_3fsource or {})) do
48764876- local _145_, _146_ = nil, nil
48774877- if (type(k) == "string") then
48784878- _145_, _146_ = k, v
48794879- else
48804880- _145_, _146_ = nil
48814881- end
48824882- if ((nil ~= _145_) and (nil ~= _146_)) then
48834883- local k_12_auto = _145_
48844884- local v_13_auto = _146_
48854885- tbl_11_auto[k_12_auto] = v_13_auto
48864886- else
48874887- end
48884888- end
48894889- _144_ = tbl_11_auto
48904890- end
48914891- return setmetatable(_144_, symbol_mt)
48924892- end
48934893- nil_sym = sym("nil")
48944894- local function sequence(...)
48954895- return setmetatable({...}, {sequence = sequence_marker})
48964896- end
48974897- local function expr(strcode, etype)
48984898- return setmetatable({type = etype, strcode}, expr_mt)
48994899- end
49004900- local function comment_2a(contents, _3fsource)
49014901- local _let_149_ = (_3fsource or {})
49024902- local filename = _let_149_["filename"]
49034903- local line = _let_149_["line"]
49044904- return setmetatable({filename = filename, line = line, contents}, comment_mt)
49054905- end
49064906- local function varg(_3fsource)
49074907- local _150_
49084908- do
49094909- local tbl_11_auto = {"..."}
49104910- for k, v in pairs((_3fsource or {})) do
49114911- local _151_, _152_ = nil, nil
49124912- if (type(k) == "string") then
49134913- _151_, _152_ = k, v
49144914- else
49154915- _151_, _152_ = nil
49164916- end
49174917- if ((nil ~= _151_) and (nil ~= _152_)) then
49184918- local k_12_auto = _151_
49194919- local v_13_auto = _152_
49204920- tbl_11_auto[k_12_auto] = v_13_auto
49214921- else
49224922- end
49234923- end
49244924- _150_ = tbl_11_auto
49254925- end
49264926- return setmetatable(_150_, varg_mt)
49274927- end
49284928- local function expr_3f(x)
49294929- return ((type(x) == "table") and (getmetatable(x) == expr_mt) and x)
49304930- end
49314931- local function varg_3f(x)
49324932- return ((type(x) == "table") and (getmetatable(x) == varg_mt) and x)
49334933- end
49344934- local function list_3f(x)
49354935- return ((type(x) == "table") and (getmetatable(x) == list_mt) and x)
49364936- end
49374937- local function sym_3f(x)
49384938- return ((type(x) == "table") and (getmetatable(x) == symbol_mt) and x)
49394939- end
49404940- local function sequence_3f(x)
49414941- local mt = ((type(x) == "table") and getmetatable(x))
49424942- return (mt and (mt.sequence == sequence_marker) and x)
49434943- end
49444944- local function comment_3f(x)
49454945- return ((type(x) == "table") and (getmetatable(x) == comment_mt) and x)
49464946- end
49474947- local function table_3f(x)
49484948- return ((type(x) == "table") and not varg_3f(x) and (getmetatable(x) ~= list_mt) and (getmetatable(x) ~= symbol_mt) and not comment_3f(x) and x)
49494949- end
49504950- local function string_3f(x)
49514951- return (type(x) == "string")
49524952- end
49534953- local function multi_sym_3f(str)
49544954- if sym_3f(str) then
49554955- return multi_sym_3f(tostring(str))
49564956- elseif (type(str) ~= "string") then
49574957- return false
49584958- else
49594959- local parts = {}
49604960- for part in str:gmatch("[^%.%:]+[%.%:]?") do
49614961- local last_char = part:sub(( - 1))
49624962- if (last_char == ":") then
49634963- parts["multi-sym-method-call"] = true
49644964- else
49654965- end
49664966- if ((last_char == ":") or (last_char == ".")) then
49674967- parts[(#parts + 1)] = part:sub(1, ( - 2))
49684968- else
49694969- parts[(#parts + 1)] = part
49704970- end
49714971- end
49724972- return ((0 < #parts) and (str:match("%.") or str:match(":")) and not str:match("%.%.") and (str:byte() ~= string.byte(".")) and (str:byte(( - 1)) ~= string.byte(".")) and parts)
49734973- end
49744974- end
49754975- local function quoted_3f(symbol)
49764976- return symbol.quoted
49774977- end
49784978- local function ast_source(ast)
49794979- if (table_3f(ast) or sequence_3f(ast)) then
49804980- return (getmetatable(ast) or {})
49814981- elseif ("table" == type(ast)) then
49824982- return ast
49834983- else
49844984- return {}
49854985- end
49864986- end
49874987- local function walk_tree(root, f, _3fcustom_iterator)
49884988- local function walk(iterfn, parent, idx, node)
49894989- if f(idx, node, parent) then
49904990- for k, v in iterfn(node) do
49914991- walk(iterfn, node, k, v)
49924992- end
49934993- return nil
49944994- else
49954995- return nil
49964996- end
49974997- end
49984998- walk((_3fcustom_iterator or pairs), nil, nil, root)
49994999- return root
50005000- end
50015001- local lua_keywords = {"and", "break", "do", "else", "elseif", "end", "false", "for", "function", "if", "in", "local", "nil", "not", "or", "repeat", "return", "then", "true", "until", "while", "goto"}
50025002- for i, v in ipairs(lua_keywords) do
50035003- lua_keywords[v] = i
50045004- end
50055005- local function valid_lua_identifier_3f(str)
50065006- return (str:match("^[%a_][%w_]*$") and not lua_keywords[str])
50075007- end
50085008- local propagated_options = {"allowedGlobals", "indent", "correlate", "useMetadata", "env", "compiler-env", "compilerEnv"}
50095009- local function propagate_options(options, subopts)
50105010- for _, name in ipairs(propagated_options) do
50115011- subopts[name] = options[name]
50125012- end
50135013- return subopts
50145014- end
50155015- local root
50165016- local function _160_()
50175017- end
50185018- root = {chunk = nil, scope = nil, options = nil, reset = _160_}
50195019- root["set-reset"] = function(_161_)
50205020- local _arg_162_ = _161_
50215021- local chunk = _arg_162_["chunk"]
50225022- local scope = _arg_162_["scope"]
50235023- local options = _arg_162_["options"]
50245024- local reset = _arg_162_["reset"]
50255025- root.reset = function()
50265026- root.chunk, root.scope, root.options, root.reset = chunk, scope, options, reset
50275027- return nil
50285028- end
50295029- return root.reset
50305030- end
50315031- local warned = {}
50325032- local function check_plugin_version(_163_)
50335033- local _arg_164_ = _163_
50345034- local name = _arg_164_["name"]
50355035- local versions = _arg_164_["versions"]
50365036- local plugin = _arg_164_
50375037- if (not member_3f(version:gsub("-dev", ""), (versions or {})) and not warned[plugin]) then
50385038- warned[plugin] = true
50395039- return warn(string.format("plugin %s does not support Fennel version %s", (name or "unknown"), version))
50405040- else
50415041- return nil
50425042- end
50435043- end
50445044- local function hook_opts(event, _3foptions, ...)
50455045- local plugins
50465046- local function _167_(...)
50475047- local t_166_ = _3foptions
50485048- if (nil ~= t_166_) then
50495049- t_166_ = (t_166_).plugins
50505050- else
50515051- end
50525052- return t_166_
50535053- end
50545054- local function _170_(...)
50555055- local t_169_ = root.options
50565056- if (nil ~= t_169_) then
50575057- t_169_ = (t_169_).plugins
50585058- else
50595059- end
50605060- return t_169_
50615061- end
50625062- plugins = (_167_(...) or _170_(...))
50635063- if plugins then
50645064- local result = nil
50655065- for _, plugin in ipairs(plugins) do
50665066- if result then break end
50675067- check_plugin_version(plugin)
50685068- local _172_ = plugin[event]
50695069- if (nil ~= _172_) then
50705070- local f = _172_
50715071- result = f(...)
50725072- else
50735073- result = nil
50745074- end
50755075- end
50765076- return result
50775077- else
50785078- return nil
50795079- end
50805080- end
50815081- local function hook(event, ...)
50825082- return hook_opts(event, root.options, ...)
50835083- end
50845084- return {warn = warn, allpairs = allpairs, stablepairs = stablepairs, copy = copy, ["get-in"] = get_in, kvmap = kvmap, map = map, ["walk-tree"] = walk_tree, ["member?"] = member_3f, list = list, sequence = sequence, sym = sym, varg = varg, expr = expr, comment = comment_2a, ["comment?"] = comment_3f, ["expr?"] = expr_3f, ["list?"] = list_3f, ["multi-sym?"] = multi_sym_3f, ["sequence?"] = sequence_3f, ["sym?"] = sym_3f, ["table?"] = table_3f, ["varg?"] = varg_3f, ["quoted?"] = quoted_3f, ["string?"] = string_3f, ["valid-lua-identifier?"] = valid_lua_identifier_3f, ["lua-keywords"] = lua_keywords, hook = hook, ["hook-opts"] = hook_opts, ["propagate-options"] = propagate_options, root = root, ["debug-on?"] = debug_on_3f, ["ast-source"] = ast_source, version = version, ["runtime-version"] = runtime_version, len = len, path = table.concat({"./?.fnl", "./?/init.fnl", getenv("FENNEL_PATH")}, ";"), ["macro-path"] = table.concat({"./?.fnl", "./?/init-macros.fnl", "./?/init.fnl", getenv("FENNEL_MACRO_PATH")}, ";")}
50855085-end
50865086-utils = require("fennel.utils")
50875087-local parser = require("fennel.parser")
50885088-local compiler = require("fennel.compiler")
50895089-local specials = require("fennel.specials")
50905090-local repl = require("fennel.repl")
50915091-local view = require("fennel.view")
50925092-local function eval_env(env, opts)
50935093- if (env == "_COMPILER") then
50945094- local env0 = specials["make-compiler-env"](nil, compiler.scopes.compiler, {}, opts)
50955095- if (opts.allowedGlobals == nil) then
50965096- opts.allowedGlobals = specials["current-global-names"](env0)
50975097- else
50985098- end
50995099- return specials["wrap-env"](env0)
51005100- else
51015101- return (env and specials["wrap-env"](env))
51025102- end
51035103-end
51045104-local function eval_opts(options, str)
51055105- local opts = utils.copy(options)
51065106- if (opts.allowedGlobals == nil) then
51075107- opts.allowedGlobals = specials["current-global-names"](opts.env)
51085108- else
51095109- end
51105110- if (not opts.filename and not opts.source) then
51115111- opts.source = str
51125112- else
51135113- end
51145114- if (opts.env == "_COMPILER") then
51155115- opts.scope = compiler["make-scope"](compiler.scopes.compiler)
51165116- else
51175117- end
51185118- return opts
51195119-end
51205120-local function eval(str, options, ...)
51215121- local opts = eval_opts(options, str)
51225122- local env = eval_env(opts.env, opts)
51235123- local lua_source = compiler["compile-string"](str, opts)
51245124- local loader
51255125- local function _735_(...)
51265126- if opts.filename then
51275127- return ("@" .. opts.filename)
51285128- else
51295129- return str
51305130- end
51315131- end
51325132- loader = specials["load-code"](lua_source, env, _735_(...))
51335133- opts.filename = nil
51345134- return loader(...)
51355135-end
51365136-local function dofile_2a(filename, options, ...)
51375137- local opts = utils.copy(options)
51385138- local f = assert(io.open(filename, "rb"))
51395139- local source = assert(f:read("*all"), ("Could not read " .. filename))
51405140- f:close()
51415141- opts.filename = filename
51425142- return eval(source, opts, ...)
51435143-end
51445144-local function syntax()
51455145- local body_3f = {"when", "with-open", "collect", "icollect", "fcollect", "lambda", "\206\187", "macro", "match", "match-try", "accumulate", "doto"}
51465146- local binding_3f = {"collect", "icollect", "fcollect", "each", "for", "let", "with-open", "accumulate"}
51475147- local define_3f = {"fn", "lambda", "\206\187", "var", "local", "macro", "macros", "global"}
51485148- local out = {}
51495149- for k, v in pairs(compiler.scopes.global.specials) do
51505150- local metadata = (compiler.metadata[v] or {})
51515151- do end (out)[k] = {["special?"] = true, ["body-form?"] = metadata["fnl/body-form?"], ["binding-form?"] = utils["member?"](k, binding_3f), ["define?"] = utils["member?"](k, define_3f)}
51525152- end
51535153- for k, v in pairs(compiler.scopes.global.macros) do
51545154- out[k] = {["macro?"] = true, ["body-form?"] = utils["member?"](k, body_3f), ["binding-form?"] = utils["member?"](k, binding_3f), ["define?"] = utils["member?"](k, define_3f)}
51555155- end
51565156- for k, v in pairs(_G) do
51575157- local _736_ = type(v)
51585158- if (_736_ == "function") then
51595159- out[k] = {["global?"] = true, ["function?"] = true}
51605160- elseif (_736_ == "table") then
51615161- for k2, v2 in pairs(v) do
51625162- if (("function" == type(v2)) and (k ~= "_G")) then
51635163- out[(k .. "." .. k2)] = {["function?"] = true, ["global?"] = true}
51645164- else
51655165- end
51665166- end
51675167- out[k] = {["global?"] = true}
51685168- else
51695169- end
51705170- end
51715171- return out
51725172-end
51735173-local mod = {list = utils.list, ["list?"] = utils["list?"], sym = utils.sym, ["sym?"] = utils["sym?"], ["multi-sym?"] = utils["multi-sym?"], sequence = utils.sequence, ["sequence?"] = utils["sequence?"], ["table?"] = utils["table?"], comment = utils.comment, ["comment?"] = utils["comment?"], varg = utils.varg, ["varg?"] = utils["varg?"], ["sym-char?"] = parser["sym-char?"], parser = parser.parser, compile = compiler.compile, ["compile-string"] = compiler["compile-string"], ["compile-stream"] = compiler["compile-stream"], eval = eval, repl = repl, view = view, dofile = dofile_2a, ["load-code"] = specials["load-code"], doc = specials.doc, metadata = compiler.metadata, traceback = compiler.traceback, version = utils.version, ["runtime-version"] = utils["runtime-version"], ["ast-source"] = utils["ast-source"], path = utils.path, ["macro-path"] = utils["macro-path"], ["macro-loaded"] = specials["macro-loaded"], ["macro-searchers"] = specials["macro-searchers"], ["search-module"] = specials["search-module"], ["make-searcher"] = specials["make-searcher"], searcher = specials["make-searcher"](), syntax = syntax, gensym = compiler.gensym, scope = compiler["make-scope"], mangle = compiler["global-mangling"], unmangle = compiler["global-unmangling"], compile1 = compiler.compile1, ["string-stream"] = parser["string-stream"], granulate = parser.granulate, loadCode = specials["load-code"], make_searcher = specials["make-searcher"], makeSearcher = specials["make-searcher"], searchModule = specials["search-module"], macroPath = utils["macro-path"], macroSearchers = specials["macro-searchers"], macroLoaded = specials["macro-loaded"], compileStream = compiler["compile-stream"], compileString = compiler["compile-string"], stringStream = parser["string-stream"], runtimeVersion = utils["runtime-version"]}
51745174-mod.install = function(_3fopts)
51755175- table.insert((package.searchers or package.loaders), specials["make-searcher"](_3fopts))
51765176- return mod
51775177-end
51785178-utils["fennel-module"] = mod
51795179-do
51805180- local builtin_macros = [===[;; These macros are awkward because their definition cannot rely on the any
51815181- ;; built-in macros, only special forms. (no when, no icollect, etc)
51825182-51835183- (fn copy [t]
51845184- (let [out []]
51855185- (each [_ v (ipairs t)] (table.insert out v))
51865186- (setmetatable out (getmetatable t))))
51875187-51885188- (fn ->* [val ...]
51895189- "Thread-first macro.
51905190- Take the first value and splice it into the second form as its first argument.
51915191- The value of the second form is spliced into the first arg of the third, etc."
51925192- (var x val)
51935193- (each [_ e (ipairs [...])]
51945194- (let [elt (if (list? e) (copy e) (list e))]
51955195- (table.insert elt 2 x)
51965196- (set x elt)))
51975197- x)
51985198-51995199- (fn ->>* [val ...]
52005200- "Thread-last macro.
52015201- Same as ->, except splices the value into the last position of each form
52025202- rather than the first."
52035203- (var x val)
52045204- (each [_ e (ipairs [...])]
52055205- (let [elt (if (list? e) (copy e) (list e))]
52065206- (table.insert elt x)
52075207- (set x elt)))
52085208- x)
52095209-52105210- (fn -?>* [val ?e ...]
52115211- "Nil-safe thread-first macro.
52125212- Same as -> except will short-circuit with nil when it encounters a nil value."
52135213- (if (= nil ?e)
52145214- val
52155215- (let [el (if (list? ?e) (copy ?e) (list ?e))
52165216- tmp (gensym)]
52175217- (table.insert el 2 tmp)
52185218- `(let [,tmp ,val]
52195219- (if (not= nil ,tmp)
52205220- (-?> ,el ,...)
52215221- ,tmp)))))
52225222-52235223- (fn -?>>* [val ?e ...]
52245224- "Nil-safe thread-last macro.
52255225- Same as ->> except will short-circuit with nil when it encounters a nil value."
52265226- (if (= nil ?e)
52275227- val
52285228- (let [el (if (list? ?e) (copy ?e) (list ?e))
52295229- tmp (gensym)]
52305230- (table.insert el tmp)
52315231- `(let [,tmp ,val]
52325232- (if (not= ,tmp nil)
52335233- (-?>> ,el ,...)
52345234- ,tmp)))))
52355235-52365236- (fn ?dot [tbl ...]
52375237- "Nil-safe table look up.
52385238- Same as . (dot), except will short-circuit with nil when it encounters
52395239- a nil value in any of subsequent keys."
52405240- (let [head (gensym :t)
52415241- lookups `(do
52425242- (var ,head ,tbl)
52435243- ,head)]
52445244- (each [_ k (ipairs [...])]
52455245- ;; Kinda gnarly to reassign in place like this, but it emits the best lua.
52465246- ;; With this impl, it emits a flat, concise, and readable set of ifs
52475247- (table.insert lookups (# lookups) `(if (not= nil ,head)
52485248- (set ,head (. ,head ,k)))))
52495249- lookups))
52505250-52515251- (fn doto* [val ...]
52525252- "Evaluate val and splice it into the first argument of subsequent forms."
52535253- (assert (not= val nil) "missing subject")
52545254- (let [rebind? (or (not (sym? val))
52555255- (multi-sym? val))
52565256- name (if rebind? (gensym) val)
52575257- form (if rebind? `(let [,name ,val]) `(do))]
52585258- (each [_ elt (ipairs [...])]
52595259- (let [elt (if (list? elt) (copy elt) (list elt))]
52605260- (table.insert elt 2 name)
52615261- (table.insert form elt)))
52625262- (table.insert form name)
52635263- form))
52645264-52655265- (fn when* [condition body1 ...]
52665266- "Evaluate body for side-effects only when condition is truthy."
52675267- (assert body1 "expected body")
52685268- `(if ,condition
52695269- (do
52705270- ,body1
52715271- ,...)))
52725272-52735273- (fn with-open* [closable-bindings ...]
52745274- "Like `let`, but invokes (v:close) on each binding after evaluating the body.
52755275- The body is evaluated inside `xpcall` so that bound values will be closed upon
52765276- encountering an error before propagating it."
52775277- (let [bodyfn `(fn []
52785278- ,...)
52795279- closer `(fn close-handlers# [ok# ...]
52805280- (if ok# ... (error ... 0)))
52815281- traceback `(. (or package.loaded.fennel debug) :traceback)]
52825282- (for [i 1 (length closable-bindings) 2]
52835283- (assert (sym? (. closable-bindings i))
52845284- "with-open only allows symbols in bindings")
52855285- (table.insert closer 4 `(: ,(. closable-bindings i) :close)))
52865286- `(let ,closable-bindings
52875287- ,closer
52885288- (close-handlers# (_G.xpcall ,bodyfn ,traceback)))))
52895289-52905290- (fn extract-into [iter-tbl]
52915291- (var (into iter-out found?) (values [] (copy iter-tbl)))
52925292- (for [i (length iter-tbl) 2 -1]
52935293- (let [item (. iter-tbl i)]
52945294- (if (or (= `&into item)
52955295- (= :into item))
52965296- (do
52975297- (assert (not found?) "expected only one &into clause")
52985298- (set found? true)
52995299- (set into (. iter-tbl (+ i 1)))
53005300- (table.remove iter-out i)
53015301- (table.remove iter-out i)))))
53025302- (assert (or (not found?) (sym? into) (table? into) (list? into))
53035303- "expected table, function call, or symbol in &into clause")
53045304- (values into iter-out))
53055305-53065306- (fn collect* [iter-tbl key-expr value-expr ...]
53075307- "Return a table made by running an iterator and evaluating an expression that
53085308- returns key-value pairs to be inserted sequentially into the table. This can
53095309- be thought of as a table comprehension. The body should provide two expressions
53105310- (used as key and value) or nil, which causes it to be omitted.
53115311-53125312- For example,
53135313- (collect [k v (pairs {:apple \"red\" :orange \"orange\"})]
53145314- (values v k))
53155315- returns
53165316- {:red \"apple\" :orange \"orange\"}
53175317-53185318- Supports an &into clause after the iterator to put results in an existing table.
53195319- Supports early termination with an &until clause."
53205320- (assert (and (sequence? iter-tbl) (<= 2 (length iter-tbl)))
53215321- "expected iterator binding table")
53225322- (assert (not= nil key-expr) "expected key and value expression")
53235323- (assert (= nil ...)
53245324- "expected 1 or 2 body expressions; wrap multiple expressions with do")
53255325- (let [kv-expr (if (= nil value-expr) key-expr `(values ,key-expr ,value-expr))
53265326- (into iter) (extract-into iter-tbl)]
53275327- `(let [tbl# ,into]
53285328- (each ,iter
53295329- (match ,kv-expr
53305330- (k# v#) (tset tbl# k# v#)))
53315331- tbl#)))
53325332-53335333- (fn seq-collect [how iter-tbl value-expr ...]
53345334- "Common part between icollect and fcollect for producing sequential tables.
53355335-53365336- Iteration code only deffers in using the for or each keyword, the rest
53375337- of the generated code is identical."
53385338- (assert (not= nil value-expr) "expected table value expression")
53395339- (assert (= nil ...)
53405340- "expected exactly one body expression. Wrap multiple expressions in do")
53415341- (let [(into iter) (extract-into iter-tbl)]
53425342- `(let [tbl# ,into]
53435343- ;; believe it or not, using a var here has a pretty good performance
53445344- ;; boost: https://p.hagelb.org/icollect-performance.html
53455345- (var i# (length tbl#))
53465346- (,how ,iter
53475347- (let [val# ,value-expr]
53485348- (when (not= nil val#)
53495349- (set i# (+ i# 1))
53505350- (tset tbl# i# val#))))
53515351- tbl#)))
53525352-53535353- (fn icollect* [iter-tbl value-expr ...]
53545354- "Return a sequential table made by running an iterator and evaluating an
53555355- expression that returns values to be inserted sequentially into the table.
53565356- This can be thought of as a table comprehension. If the body evaluates to nil
53575357- that element is omitted.
53585358-53595359- For example,
53605360- (icollect [_ v (ipairs [1 2 3 4 5])]
53615361- (when (not= v 3)
53625362- (* v v)))
53635363- returns
53645364- [1 4 16 25]
53655365-53665366- Supports an &into clause after the iterator to put results in an existing table.
53675367- Supports early termination with an &until clause."
53685368- (assert (and (sequence? iter-tbl) (<= 2 (length iter-tbl)))
53695369- "expected iterator binding table")
53705370- (seq-collect 'each iter-tbl value-expr ...))
53715371-53725372- (fn fcollect* [iter-tbl value-expr ...]
53735373- "Return a sequential table made by advancing a range as specified by
53745374- for, and evaluating an expression that returns values to be inserted
53755375- sequentially into the table. This can be thought of as a range
53765376- comprehension. If the body evaluates to nil that element is omitted.
53775377-53785378- For example,
53795379- (fcollect [i 1 10 2]
53805380- (when (not= i 3)
53815381- (* i i)))
53825382- returns
53835383- [1 25 49 81]
53845384-53855385- Supports an &into clause after the range to put results in an existing table.
53865386- Supports early termination with an &until clause."
53875387- (assert (and (sequence? iter-tbl) (< 2 (length iter-tbl)))
53885388- "expected range binding table")
53895389- (seq-collect 'for iter-tbl value-expr ...))
53905390-53915391- (fn accumulate* [iter-tbl body ...]
53925392- "Accumulation macro.
53935393-53945394- It takes a binding table and an expression as its arguments. In the binding
53955395- table, the first form starts out bound to the second value, which is an initial
53965396- accumulator. The rest are an iterator binding table in the format `each` takes.
53975397-53985398- It runs through the iterator in each step of which the given expression is
53995399- evaluated, and the accumulator is set to the value of the expression. It
54005400- eventually returns the final value of the accumulator.
54015401-54025402- For example,
54035403- (accumulate [total 0
54045404- _ n (pairs {:apple 2 :orange 3})]
54055405- (+ total n))
54065406- returns 5"
54075407- (assert (and (sequence? iter-tbl) (<= 4 (length iter-tbl)))
54085408- "expected initial value and iterator binding table")
54095409- (assert (not= nil body) "expected body expression")
54105410- (assert (= nil ...)
54115411- "expected exactly one body expression. Wrap multiple expressions with do")
54125412- (let [accum-var (. iter-tbl 1)
54135413- accum-init (. iter-tbl 2)]
54145414- `(do
54155415- (var ,accum-var ,accum-init)
54165416- (each ,[(unpack iter-tbl 3)]
54175417- (set ,accum-var ,body))
54185418- ,(if (list? accum-var)
54195419- (list (sym :values) (unpack accum-var))
54205420- accum-var))))
54215421-54225422- (fn double-eval-safe? [x type]
54235423- (or (= :number type) (= :string type) (= :boolean type)
54245424- (and (sym? x) (not (multi-sym? x)))))
54255425-54265426- (fn partial* [f ...]
54275427- "Return a function with all arguments partially applied to f."
54285428- (assert f "expected a function to partially apply")
54295429- (let [bindings []
54305430- args []]
54315431- (each [_ arg (ipairs [...])]
54325432- (if (double-eval-safe? arg (type arg))
54335433- (table.insert args arg)
54345434- (let [name (gensym)]
54355435- (table.insert bindings name)
54365436- (table.insert bindings arg)
54375437- (table.insert args name))))
54385438- (let [body (list f (unpack args))]
54395439- (table.insert body _VARARG)
54405440- ;; only use the extra let if we need double-eval protection
54415441- (if (= 0 (length bindings))
54425442- `(fn [,_VARARG] ,body)
54435443- `(let ,bindings
54445444- (fn [,_VARARG] ,body))))))
54455445-54465446- (fn pick-args* [n f]
54475447- "Create a function of arity n that applies its arguments to f.
54485448-54495449- For example,
54505450- (pick-args 2 func)
54515451- expands to
54525452- (fn [_0_ _1_] (func _0_ _1_))"
54535453- (if (and _G.io _G.io.stderr)
54545454- (_G.io.stderr:write
54555455- "-- WARNING: pick-args is deprecated and will be removed in the future.\n"))
54565456- (assert (and (= (type n) :number) (= n (math.floor n)) (<= 0 n))
54575457- (.. "Expected n to be an integer literal >= 0, got " (tostring n)))
54585458- (let [bindings []]
54595459- (for [i 1 n]
54605460- (tset bindings i (gensym)))
54615461- `(fn ,bindings
54625462- (,f ,(unpack bindings)))))
54635463-54645464- (fn pick-values* [n ...]
54655465- "Evaluate to exactly n values.
54665466-54675467- For example,
54685468- (pick-values 2 ...)
54695469- expands to
54705470- (let [(_0_ _1_) ...]
54715471- (values _0_ _1_))"
54725472- (assert (and (= :number (type n)) (<= 0 n) (= n (math.floor n)))
54735473- (.. "Expected n to be an integer >= 0, got " (tostring n)))
54745474- (let [let-syms (list)
54755475- let-values (if (= 1 (select "#" ...)) ... `(values ,...))]
54765476- (for [i 1 n]
54775477- (table.insert let-syms (gensym)))
54785478- (if (= n 0) `(values)
54795479- `(let [,let-syms ,let-values]
54805480- (values ,(unpack let-syms))))))
54815481-54825482- (fn lambda* [...]
54835483- "Function literal with nil-checked arguments.
54845484- Like `fn`, but will throw an exception if a declared argument is passed in as
54855485- nil, unless that argument's name begins with a question mark."
54865486- (let [args [...]
54875487- has-internal-name? (sym? (. args 1))
54885488- arglist (if has-internal-name? (. args 2) (. args 1))
54895489- docstring-position (if has-internal-name? 3 2)
54905490- has-docstring? (and (< docstring-position (length args))
54915491- (= :string (type (. args docstring-position))))
54925492- arity-check-position (- 4 (if has-internal-name? 0 1)
54935493- (if has-docstring? 0 1))
54945494- empty-body? (< (length args) arity-check-position)]
54955495- (fn check! [a]
54965496- (if (table? a)
54975497- (each [_ a (pairs a)]
54985498- (check! a))
54995499- (let [as (tostring a)]
55005500- (and (not (as:match "^?")) (not= as "&") (not= as "_")
55015501- (not= as "...") (not= as "&as")))
55025502- (table.insert args arity-check-position
55035503- `(_G.assert (not= nil ,a)
55045504- ,(: "Missing argument %s on %s:%s" :format
55055505- (tostring a)
55065506- (or a.filename :unknown)
55075507- (or a.line "?"))))))
55085508-55095509- (assert (= :table (type arglist)) "expected arg list")
55105510- (each [_ a (ipairs arglist)]
55115511- (check! a))
55125512- (if empty-body?
55135513- (table.insert args (sym :nil)))
55145514- `(fn ,(unpack args))))
55155515-55165516- (fn macro* [name ...]
55175517- "Define a single macro."
55185518- (assert (sym? name) "expected symbol for macro name")
55195519- (local args [...])
55205520- `(macros {,(tostring name) (fn ,(unpack args))}))
55215521-55225522- (fn macrodebug* [form return?]
55235523- "Print the resulting form after performing macroexpansion.
55245524- With a second argument, returns expanded form as a string instead of printing."
55255525- (let [handle (if return? `do `print)]
55265526- `(,handle ,(view (macroexpand form _SCOPE)))))
55275527-55285528- (fn import-macros* [binding1 module-name1 ...]
55295529- "Bind a table of macros from each macro module according to a binding form.
55305530- Each binding form can be either a symbol or a k/v destructuring table.
55315531- Example:
55325532- (import-macros mymacros :my-macros ; bind to symbol
55335533- {:macro1 alias : macro2} :proj.macros) ; import by name"
55345534- (assert (and binding1 module-name1 (= 0 (% (select "#" ...) 2)))
55355535- "expected even number of binding/modulename pairs")
55365536- (for [i 1 (select "#" binding1 module-name1 ...) 2]
55375537- ;; delegate the actual loading of the macros to the require-macros
55385538- ;; special which already knows how to set up the compiler env and stuff.
55395539- ;; this is weird because require-macros is deprecated but it works.
55405540- (let [(binding modname) (select i binding1 module-name1 ...)
55415541- scope (get-scope)
55425542- ;; if the module-name is an expression (and not just a string) we
55435543- ;; patch our expression to have the correct source filename so
55445544- ;; require-macros can pass it down when resolving the module-name.
55455545- expr `(import-macros ,modname)
55465546- filename (if (list? modname) (. modname 1 :filename) :unknown)
55475547- _ (tset expr :filename filename)
55485548- macros* (_SPECIALS.require-macros expr scope {} binding)]
55495549- (if (sym? binding)
55505550- ;; bind whole table of macros to table bound to symbol
55515551- (tset scope.macros (. binding 1) macros*)
55525552- ;; 1-level table destructuring for importing individual macros
55535553- (table? binding)
55545554- (each [macro-name [import-key] (pairs binding)]
55555555- (assert (= :function (type (. macros* macro-name)))
55565556- (.. "macro " macro-name " not found in module "
55575557- (tostring modname)))
55585558- (tset scope.macros import-key (. macros* macro-name))))))
55595559- nil)
55605560-55615561- ;;; Pattern matching
55625562-55635563- (fn match-values [vals pattern unifications match-pattern]
55645564- (let [condition `(and)
55655565- bindings []]
55665566- (each [i pat (ipairs pattern)]
55675567- (let [(subcondition subbindings) (match-pattern [(. vals i)] pat
55685568- unifications)]
55695569- (table.insert condition subcondition)
55705570- (each [_ b (ipairs subbindings)]
55715571- (table.insert bindings b))))
55725572- (values condition bindings)))
55735573-55745574- (fn match-table [val pattern unifications match-pattern]
55755575- (let [condition `(and (= (_G.type ,val) :table))
55765576- bindings []]
55775577- (each [k pat (pairs pattern)]
55785578- (if (= pat `&)
55795579- (let [rest-pat (. pattern (+ k 1))
55805580- rest-val `(select ,k ((or table.unpack _G.unpack) ,val))
55815581- subcondition (match-table `(pick-values 1 ,rest-val)
55825582- rest-pat unifications match-pattern)]
55835583- (if (not (sym? rest-pat))
55845584- (table.insert condition subcondition))
55855585- (assert (= nil (. pattern (+ k 2)))
55865586- "expected & rest argument before last parameter")
55875587- (table.insert bindings rest-pat)
55885588- (table.insert bindings [rest-val]))
55895589- (= k `&as)
55905590- (do
55915591- (table.insert bindings pat)
55925592- (table.insert bindings val))
55935593- (and (= :number (type k)) (= `&as pat))
55945594- (do
55955595- (assert (= nil (. pattern (+ k 2)))
55965596- "expected &as argument before last parameter")
55975597- (table.insert bindings (. pattern (+ k 1)))
55985598- (table.insert bindings val))
55995599- ;; don't process the pattern right after &/&as; already got it
56005600- (or (not= :number (type k)) (and (not= `&as (. pattern (- k 1)))
56015601- (not= `& (. pattern (- k 1)))))
56025602- (let [subval `(. ,val ,k)
56035603- (subcondition subbindings) (match-pattern [subval] pat
56045604- unifications)]
56055605- (table.insert condition subcondition)
56065606- (each [_ b (ipairs subbindings)]
56075607- (table.insert bindings b)))))
56085608- (values condition bindings)))
56095609-56105610- (fn match-pattern [vals pattern unifications]
56115611- "Take the AST of values and a single pattern and returns a condition
56125612- to determine if it matches as well as a list of bindings to
56135613- introduce for the duration of the body if it does match."
56145614- ;; we have to assume we're matching against multiple values here until we
56155615- ;; know we're either in a multi-valued clause (in which case we know the #
56165616- ;; of vals) or we're not, in which case we only care about the first one.
56175617- (let [[val] vals]
56185618- (if (or (and (sym? pattern) ; unification with outer locals (or nil)
56195619- (not= "_" (tostring pattern)) ; never unify _
56205620- (or (in-scope? pattern) (= :nil (tostring pattern))))
56215621- (and (multi-sym? pattern) (in-scope? (. (multi-sym? pattern) 1))))
56225622- (values `(= ,val ,pattern) [])
56235623- ;; unify a local we've seen already
56245624- (and (sym? pattern) (. unifications (tostring pattern)))
56255625- (values `(= ,(. unifications (tostring pattern)) ,val) [])
56265626- ;; bind a fresh local
56275627- (sym? pattern)
56285628- (let [wildcard? (: (tostring pattern) :find "^_")]
56295629- (if (not wildcard?) (tset unifications (tostring pattern) val))
56305630- (values (if (or wildcard? (string.find (tostring pattern) "^?")) true
56315631- `(not= ,(sym :nil) ,val)) [pattern val]))
56325632- ;; guard clause
56335633- (and (list? pattern) (= (. pattern 2) `?))
56345634- (let [(pcondition bindings) (match-pattern vals (. pattern 1)
56355635- unifications)
56365636- condition `(and ,(unpack pattern 3))]
56375637- (values `(and ,pcondition
56385638- (let ,bindings
56395639- ,condition)) bindings))
56405640- ;; multi-valued patterns (represented as lists)
56415641- (list? pattern)
56425642- (match-values vals pattern unifications match-pattern)
56435643- ;; table patterns
56445644- (= (type pattern) :table)
56455645- (match-table val pattern unifications match-pattern)
56465646- ;; literal value
56475647- (values `(= ,val ,pattern) []))))
56485648-56495649- (fn match-condition [vals clauses]
56505650- "Construct the actual `if` AST for the given match values and clauses."
56515651- (if (not= 0 (% (length clauses) 2)) ; treat odd final clause as default
56525652- (table.insert clauses (length clauses) (sym "_")))
56535653- (let [out `(if)]
56545654- (for [i 1 (length clauses) 2]
56555655- (let [pattern (. clauses i)
56565656- body (. clauses (+ i 1))
56575657- (condition bindings) (match-pattern vals pattern {})]
56585658- (table.insert out condition)
56595659- (table.insert out `(let ,bindings
56605660- ,body))))
56615661- out))
56625662-56635663- (fn match-val-syms [clauses]
56645664- "How many multi-valued clauses are there? return a list of that many gensyms."
56655665- (let [syms (list (gensym))]
56665666- (for [i 1 (length clauses) 2]
56675667- (let [clause (if (and (list? (. clauses i)) (= `? (. clauses i 2)))
56685668- (. clauses i 1)
56695669- (. clauses i))]
56705670- (if (list? clause)
56715671- (each [valnum (ipairs clause)]
56725672- (if (not (. syms valnum))
56735673- (tset syms valnum (gensym)))))))
56745674- syms))
56755675-56765676- (fn match* [val ...]
56775677- ;; Old implementation of match macro, which doesn't directly support
56785678- ;; `where' and `or'. New syntax is implemented in `match-where',
56795679- ;; which simply generates old syntax and feeds it to `match*'.
56805680- (let [clauses [...]
56815681- vals (match-val-syms clauses)]
56825682- ;; protect against multiple evaluation of the value, bind against as
56835683- ;; many values as we ever match against in the clauses.
56845684- (list `let [vals val] (match-condition vals clauses))))
56855685-56865686- ;; Construction of old match syntax from new syntax
56875687-56885688- (fn partition-2 [seq]
56895689- ;; Partition `seq` by 2.
56905690- ;; If `seq` has odd amount of elements, the last one is dropped.
56915691- ;;
56925692- ;; Input: [1 2 3 4 5]
56935693- ;; Output: [[1 2] [3 4]]
56945694- (let [firsts []
56955695- seconds []
56965696- res []]
56975697- (for [i 1 (length seq) 2]
56985698- (let [first (. seq i)
56995699- second (. seq (+ i 1))]
57005700- (table.insert firsts (if (not= nil first) first `nil))
57015701- (table.insert seconds (if (not= nil second) second `nil))))
57025702- (each [i v1 (ipairs firsts)]
57035703- (let [v2 (. seconds i)]
57045704- (if (not= nil v2)
57055705- (table.insert res [v1 v2]))))
57065706- res))
57075707-57085708- (fn transform-or [[_ & pats] guards]
57095709- ;; Transforms `(or pat pats*)` lists into match `guard` patterns.
57105710- ;;
57115711- ;; (or pat1 pat2), guard => [(pat1 ? guard) (pat2 ? guard)]
57125712- (let [res []]
57135713- (each [_ pat (ipairs pats)]
57145714- (table.insert res (list pat `? (unpack guards))))
57155715- res))
57165716-57175717- (fn transform-cond [cond]
57185718- ;; Transforms `where` cond into sequence of `match` guards.
57195719- ;;
57205720- ;; pat => [pat]
57215721- ;; (where pat guard) => [(pat ? guard)]
57225722- ;; (where (or pat1 pat2) guard) => [(pat1 ? guard) (pat2 ? guard)]
57235723- (if (and (list? cond) (= (. cond 1) `where))
57245724- (let [second (. cond 2)]
57255725- (if (and (list? second) (= (. second 1) `or))
57265726- (transform-or second [(unpack cond 3)])
57275727- :else
57285728- [(list second `? (unpack cond 3))]))
57295729- :else
57305730- [cond]))
57315731-57325732- (fn match-where [val ...]
57335733- "Perform pattern matching on val. See reference for details.
57345734-57355735- Syntax:
57365736-57375737- (match data-expression
57385738- pattern body
57395739- (where pattern guard guards*) body
57405740- (where (or pattern patterns*) guard guards*) body)"
57415741- (assert (not= val nil) "missing subject")
57425742- (assert (= 0 (math.fmod (select :# ...) 2))
57435743- "expected even number of pattern/body pairs")
57445744- (assert (not= 0 (select :# ...))
57455745- "expected at least one pattern/body pair")
57465746- (let [conds-bodies (partition-2 [...])
57475747- match-body []]
57485748- (each [_ [cond body] (ipairs conds-bodies)]
57495749- (each [_ cond (ipairs (transform-cond cond))]
57505750- (table.insert match-body cond)
57515751- (table.insert match-body body)))
57525752- (match* val (unpack match-body))))
57535753-57545754- (fn match-try-step [expr else pattern body ...]
57555755- (if (= nil pattern body)
57565756- expr
57575757- ;; unlike regular match, we can't know how many values the value
57585758- ;; might evaluate to, so we have to capture them all in ... via IIFE
57595759- ;; to avoid double-evaluation.
57605760- `((fn [...]
57615761- (match ...
57625762- ,pattern ,(match-try-step body else ...)
57635763- ,(unpack else)))
57645764- ,expr)))
57655765-57665766- (fn match-try* [expr pattern body ...]
57675767- "Perform chained pattern matching for a sequence of steps which might fail.
57685768-57695769- The values from the initial expression are matched against the first pattern.
57705770- If they match, the first body is evaluated and its values are matched against
57715771- the second pattern, etc.
57725772-57735773- If there is a (catch pat1 body1 pat2 body2 ...) form at the end, any mismatch
57745774- from the steps will be tried against these patterns in sequence as a fallback
57755775- just like a normal match. If there is no catch, the mismatched values will be
57765776- returned as the value of the entire expression."
57775777- (let [clauses [pattern body ...]
57785778- last (. clauses (length clauses))
57795779- catch (if (= `catch (and (= :table (type last)) (. last 1)))
57805780- (let [[_ & e] (table.remove clauses)] e) ; remove `catch sym
57815781- [`_# `...])]
57825782- (assert (= 0 (math.fmod (length clauses) 2))
57835783- "expected every pattern to have a body")
57845784- (assert (= 0 (math.fmod (length catch) 2))
57855785- "expected every catch pattern to have a body")
57865786- (match-try-step expr catch (unpack clauses))))
57875787-57885788- {:-> ->*
57895789- :->> ->>*
57905790- :-?> -?>*
57915791- :-?>> -?>>*
57925792- :?. ?dot
57935793- :doto doto*
57945794- :when when*
57955795- :with-open with-open*
57965796- :collect collect*
57975797- :icollect icollect*
57985798- :fcollect fcollect*
57995799- :accumulate accumulate*
58005800- :partial partial*
58015801- :lambda lambda*
58025802- :pick-args pick-args*
58035803- :pick-values pick-values*
58045804- :macro macro*
58055805- :macrodebug macrodebug*
58065806- :import-macros import-macros*
58075807- :match match-where
58085808- :match-try match-try*}
58095809- ]===]
58105810- local module_name = "fennel.macros"
58115811- local _
58125812- local function _739_()
58135813- return mod
58145814- end
58155815- package.preload[module_name] = _739_
58165816- _ = nil
58175817- local env
58185818- do
58195819- local _740_ = specials["make-compiler-env"](nil, compiler.scopes.compiler, {})
58205820- do end (_740_)["utils"] = utils
58215821- _740_["fennel"] = mod
58225822- env = _740_
58235823- end
58245824- local built_ins = eval(builtin_macros, {env = env, scope = compiler.scopes.compiler, allowedGlobals = false, useMetadata = true, filename = "src/fennel/macros.fnl", moduleName = module_name})
58255825- for k, v in pairs(built_ins) do
58265826- compiler.scopes.global.macros[k] = v
58275827- end
58285828- compiler.scopes.global.macros["\206\187"] = compiler.scopes.global.macros.lambda
58295829- package.preload[module_name] = nil
58305830-end
58315831-return mod