···11-alias git=hub
21source (direnv hook fish | psub)
3244-if test "$EDITOR" = nano
55- set -x EDITOR nvim
66-end
77-88-set -x LESS '-SRFXi'
99-set -x ERL_AFLAGS '-kernel shell_history enabled'
1010-113if not functions -q fundle
124 eval (curl -sfL https://git.io/fundle-install)
135end
146fundle plugin 'hauleth/agnoster'
77+fundle plugin 'oh-my-fish/plugin-foreign-env'
158fundle init
1691710ulimit -n 10480
18111919-set fish_user_paths ~/bin ~/.nix-profile/bin /run/current-system/sw/bin
1212+# if type nix-locate 2>/dev/null >/dev/null
1313+# function nix_locate_bin --on-event fish_command_not_found
1414+# if not test -t 1
1515+# __fish_default_command_not_found_handler $argv[1]
1616+# end
20172121-if type nix-locate 2>/dev/null >/dev/null
2222- function nix_locate_bin --on-event fish_command_not_found
2323- if not test -t 1
2424- __fish_default_command_not_found_handler $argv[1]
2525- end
1818+# set -l cmd $argv[1]
1919+# set -l attrs (nix-locate --minimal --no-group --type x --type s --top-level --whole-name --at-root "/bin/$cmd")
26202727- set -l cmd $argv[1]
2828- set -l attrs (nix-locate --minimal --no-group --type x --type s --top-level --whole-name --at-root "/bin/$cmd")
2929-3030- switch (count $attrs)
3131- case 0
3232- echo "$cmd: command not found" >&2
3333- case 1
3434- echo "Found one package with $cmd, trying to run in 1s" >&2
3535- sleep 1
3636- if nix-build --no-out-link -A $attrs "<nixpkgs>"
3737- nix-shell -p $attrs --run (printf "'%s' " $argv)
3838- return
3939- else
4040- echo "Failed to install nixpkgs.$attrs"
4141- echo "$cmd: command not found"
4242- end
4343- case '*'
4444- echo "$cmd is not installed. You can find it in:" >&2
4545- printf "\tnix-env -iA nixpkgs.%s\n" $attrs >&2
4646- end
4747- end
4848-end
4949-5050-if status --is-interactive
5151- # env SHELL=fish keychain --eval --quiet -Q | source
5252-5353- kitty + complete setup fish | source
5454-end
2121+# switch (count $attrs)
2222+# case 0
2323+# echo "$cmd: command not found" >&2
2424+# case 1
2525+# echo "Found one package with $cmd, trying to run in 1s" >&2
2626+# sleep 1
2727+# if nix-build --no-out-link -A $attrs "<nixpkgs>"
2828+# nix-shell -p $attrs --run (printf "'%s' " $argv)
2929+# return
3030+# else
3131+# echo "Failed to install nixpkgs.$attrs"
3232+# echo "$cmd: command not found"
3333+# end
3434+# case '*'
3535+# echo "$cmd is not installed. You can find it in:" >&2
3636+# printf "\tnix-env -iA nixpkgs.%s\n" $attrs >&2
3737+# end
3838+# end
3939+# end
···11+-- Fennel loader, default one do not work well with NeoVim so there is custom
22+-- one
33+local fennel = require('fennel')
44+local function fennel_loader(name)
55+ local basename = name:gsub('%.', '/')
66+ local paths = {"fnl/"..basename..".fnl", "fnl/"..basename.."/init.fnl"}
77+88+ for _, path in ipairs(paths) do
99+ local found = vim.api.nvim_get_runtime_file(path, false)
1010+ if #found > 0 then
1111+ return function() return fennel.dofile(found[1]) end
1212+ end
1313+ end
1414+1515+ return nil
1616+end
1717+table.insert(package.loaders, 1, fennel_loader)
1818+1919+local u = require('utils')
2020+2121+require('startup')
2222+2323+-- Load legacy configuration file
2424+vim.api.nvim_command('runtime! legacy.vim')
···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 function default_read_chunk(parser_state)
77+ local function _0_()
88+ if (0 < parser_state["stack-size"]) then
99+ return ".."
1010+ else
1111+ return ">> "
1212+ end
1313+ end
1414+ io.write(_0_())
1515+ io.flush()
1616+ local input = io.read()
1717+ return (input and (input .. "\n"))
1818+ end
1919+ local function default_on_values(xs)
2020+ io.write(table.concat(xs, "\9"))
2121+ return io.write("\n")
2222+ end
2323+ local function default_on_error(errtype, err, lua_source)
2424+ local function _1_()
2525+ local _0_0 = errtype
2626+ if (_0_0 == "Lua Compile") then
2727+ return ("Bad code generated - likely a bug with the compiler:\n" .. "--- Generated Lua Start ---\n" .. lua_source .. "--- Generated Lua End ---\n")
2828+ elseif (_0_0 == "Runtime") then
2929+ return (compiler.traceback(tostring(err), 4) .. "\n")
3030+ else
3131+ local _ = _0_0
3232+ return ("%s error: %s\n"):format(errtype, tostring(err))
3333+ end
3434+ end
3535+ return io.write(_1_())
3636+ end
3737+ local save_source = table.concat({"local ___i___ = 1", "while true do", " local name, value = debug.getlocal(1, ___i___)", " if(name and name ~= \"___i___\") then", " ___replLocals___[name] = value", " ___i___ = ___i___ + 1", " else break end end"}, "\n")
3838+ local function splice_save_locals(env, lua_source)
3939+ env.___replLocals___ = (env.___replLocals___ or {})
4040+ local spliced_source = {}
4141+ local bind = "local %s = ___replLocals___['%s']"
4242+ for line in lua_source:gmatch("([^\n]+)\n?") do
4343+ table.insert(spliced_source, line)
4444+ end
4545+ for name in pairs(env.___replLocals___) do
4646+ table.insert(spliced_source, 1, bind:format(name, name))
4747+ end
4848+ if ((1 < #spliced_source) and (spliced_source[#spliced_source]):match("^ *return .*$")) then
4949+ table.insert(spliced_source, #spliced_source, save_source)
5050+ end
5151+ return table.concat(spliced_source, "\n")
5252+ end
5353+ local commands = {}
5454+ local function command_3f(input)
5555+ return input:match("^%s*,")
5656+ end
5757+ local function command_docs()
5858+ local _0_
5959+ do
6060+ local tbl_0_ = {}
6161+ for name, f in pairs(commands) do
6262+ tbl_0_[(#tbl_0_ + 1)] = (" ,%s - %s"):format(name, ((compiler.metadata):get(f, "fnl/docstring") or "undocumented"))
6363+ end
6464+ _0_ = tbl_0_
6565+ end
6666+ return table.concat(_0_, "\n")
6767+ end
6868+ commands.help = function(_, _0, on_values)
6969+ 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")})
7070+ end
7171+ do end (compiler.metadata):set(commands.help, "fnl/docstring", "Show this message.")
7272+ local function reload(module_name, env, on_values, on_error)
7373+ local _0_0, _1_0 = pcall(specials["load-code"]("return require(...)", env), module_name)
7474+ if ((_0_0 == true) and (nil ~= _1_0)) then
7575+ local old = _1_0
7676+ local _ = nil
7777+ package.loaded[module_name] = nil
7878+ _ = nil
7979+ local ok, new = pcall(require, module_name)
8080+ local new0 = nil
8181+ if not ok then
8282+ on_values({new})
8383+ new0 = old
8484+ else
8585+ new0 = new
8686+ end
8787+ if ((type(old) == "table") and (type(new0) == "table")) then
8888+ for k, v in pairs(new0) do
8989+ old[k] = v
9090+ end
9191+ for k in pairs(old) do
9292+ if (nil == new0[k]) then
9393+ old[k] = nil
9494+ end
9595+ end
9696+ package.loaded[module_name] = old
9797+ end
9898+ return on_values({"ok"})
9999+ elseif ((_0_0 == false) and (nil ~= _1_0)) then
100100+ local msg = _1_0
101101+ local function _3_()
102102+ local _2_0 = msg:gsub("\n.*", "")
103103+ return _2_0
104104+ end
105105+ return on_error("Runtime", _3_())
106106+ end
107107+ end
108108+ commands.reload = function(env, read, on_values, on_error)
109109+ local _0_0, _1_0, _2_0 = pcall(read)
110110+ if ((_0_0 == true) and (_1_0 == true) and (nil ~= _2_0)) then
111111+ local module_sym = _2_0
112112+ return reload(tostring(module_sym), env, on_values, on_error)
113113+ elseif ((_0_0 == false) and true and true) then
114114+ local _3fparse_ok = _1_0
115115+ local _3fmsg = _2_0
116116+ return on_error("Parse", (_3fmsg or _3fparse_ok))
117117+ end
118118+ end
119119+ do end (compiler.metadata):set(commands.reload, "fnl/docstring", "Reload the specified module.")
120120+ commands.reset = function(env, _, on_values)
121121+ env.___replLocals___ = {}
122122+ return on_values({"ok"})
123123+ end
124124+ do end (compiler.metadata):set(commands.reset, "fnl/docstring", "Erase all repl-local scope.")
125125+ local function load_plugin_commands()
126126+ if (utils.root and utils.root.options and utils.root.options.plugins) then
127127+ for _, plugin in ipairs(utils.root.options.plugins) do
128128+ for name, f in pairs(plugin) do
129129+ local _0_0 = name:match("^repl%-command%-(.*)")
130130+ if (nil ~= _0_0) then
131131+ local cmd_name = _0_0
132132+ commands[cmd_name] = (commands[cmd_name] or f)
133133+ end
134134+ end
135135+ end
136136+ return nil
137137+ end
138138+ end
139139+ local function run_command(input, read, loop, env, on_values, on_error)
140140+ load_plugin_commands()
141141+ local command_name = input:match(",([^%s/]+)")
142142+ do
143143+ local _0_0 = commands[command_name]
144144+ if (nil ~= _0_0) then
145145+ local command = _0_0
146146+ command(env, read, on_values, on_error)
147147+ else
148148+ local _ = _0_0
149149+ if ("exit" ~= command_name) then
150150+ on_values({"Unknown command", command_name})
151151+ end
152152+ end
153153+ end
154154+ if ("exit" ~= command_name) then
155155+ return loop()
156156+ end
157157+ end
158158+ local function completer(env, scope, text)
159159+ local matches = {}
160160+ local input_fragment = text:gsub(".*[%s)(]+", "")
161161+ local function add_partials(input, tbl, prefix)
162162+ for k in utils.allpairs(tbl) do
163163+ local k0 = nil
164164+ if ((tbl == env) or (tbl == env.___replLocals___)) then
165165+ k0 = scope.unmanglings[k]
166166+ else
167167+ k0 = k
168168+ end
169169+ if ((#matches < 2000) and (type(k0) == "string") and (input == k0:sub(0, #input))) then
170170+ table.insert(matches, (prefix .. k0))
171171+ end
172172+ end
173173+ return nil
174174+ end
175175+ local function add_matches(input, tbl, prefix)
176176+ local prefix0 = nil
177177+ if prefix then
178178+ prefix0 = (prefix .. ".")
179179+ else
180180+ prefix0 = ""
181181+ end
182182+ if not input:find("%.") then
183183+ return add_partials(input, tbl, prefix0)
184184+ else
185185+ local head, tail = input:match("^([^.]+)%.(.*)")
186186+ local raw_head = nil
187187+ if ((tbl == env) or (tbl == env.___replLocals___)) then
188188+ raw_head = scope.manglings[head]
189189+ else
190190+ raw_head = head
191191+ end
192192+ if (type(tbl[raw_head]) == "table") then
193193+ return add_matches(tail, tbl[raw_head], (prefix0 .. head))
194194+ end
195195+ end
196196+ end
197197+ add_matches(input_fragment, (scope.specials or {}))
198198+ add_matches(input_fragment, (scope.macros or {}))
199199+ add_matches(input_fragment, (env.___replLocals___ or {}))
200200+ add_matches(input_fragment, env)
201201+ add_matches(input_fragment, (env._ENV or env._G or {}))
202202+ return matches
203203+ end
204204+ local function repl(options)
205205+ local old_root_options = utils.root.options
206206+ local env = nil
207207+ if options.env then
208208+ env = specials["wrap-env"](options.env)
209209+ else
210210+ env = setmetatable({}, {__index = (rawget(_G, "_ENV") or _G)})
211211+ end
212212+ local save_locals_3f = ((options.saveLocals ~= false) and env.debug and env.debug.getlocal)
213213+ local opts = {}
214214+ local _ = nil
215215+ for k, v in pairs(options) do
216216+ opts[k] = v
217217+ end
218218+ _ = nil
219219+ local read_chunk = (opts.readChunk or default_read_chunk)
220220+ local on_values = (opts.onValues or default_on_values)
221221+ local on_error = (opts.onError or default_on_error)
222222+ local pp = (opts.pp or tostring)
223223+ local byte_stream, clear_stream = parser.granulate(read_chunk)
224224+ local chars = {}
225225+ local read, reset = nil, nil
226226+ local function _1_(parser_state)
227227+ local c = byte_stream(parser_state)
228228+ table.insert(chars, c)
229229+ return c
230230+ end
231231+ read, reset = parser.parser(_1_)
232232+ local scope = compiler["make-scope"]()
233233+ opts.useMetadata = (options.useMetadata ~= false)
234234+ if (opts.allowedGlobals == nil) then
235235+ opts.allowedGlobals = specials["current-global-names"](opts.env)
236236+ end
237237+ if opts.registerCompleter then
238238+ local function _3_(...)
239239+ return completer(env, scope, ...)
240240+ end
241241+ opts.registerCompleter(_3_)
242242+ end
243243+ local function print_values(...)
244244+ local vals = {...}
245245+ local out = {}
246246+ env._, env.__ = vals[1], vals
247247+ for i = 1, select("#", ...) do
248248+ table.insert(out, pp(vals[i]))
249249+ end
250250+ return on_values(out)
251251+ end
252252+ local function loop()
253253+ for k in pairs(chars) do
254254+ chars[k] = nil
255255+ end
256256+ local ok, parse_ok_3f, x = pcall(read)
257257+ local src_string = string.char((table.unpack or _G.unpack)(chars))
258258+ utils.root.options = opts
259259+ if not ok then
260260+ on_error("Parse", parse_ok_3f)
261261+ clear_stream()
262262+ reset()
263263+ return loop()
264264+ elseif command_3f(src_string) then
265265+ return run_command(src_string, read, loop, env, on_values, on_error)
266266+ else
267267+ if parse_ok_3f then
268268+ do
269269+ local _4_0, _5_0 = pcall(compiler.compile, x, {["assert-compile"] = opts["assert-compile"], ["parse-error"] = opts["parse-error"], correlate = opts.correlate, moduleName = opts.moduleName, scope = scope, source = src_string, useMetadata = opts.useMetadata})
270270+ if ((_4_0 == false) and (nil ~= _5_0)) then
271271+ local msg = _5_0
272272+ clear_stream()
273273+ on_error("Compile", msg)
274274+ elseif ((_4_0 == true) and (nil ~= _5_0)) then
275275+ local src = _5_0
276276+ local src0 = nil
277277+ if save_locals_3f then
278278+ src0 = splice_save_locals(env, src)
279279+ else
280280+ src0 = src
281281+ end
282282+ local _7_0, _8_0 = pcall(specials["load-code"], src0, env)
283283+ if ((_7_0 == false) and (nil ~= _8_0)) then
284284+ local msg = _8_0
285285+ clear_stream()
286286+ on_error("Lua Compile", msg, src0)
287287+ elseif (true and (nil ~= _8_0)) then
288288+ local _0 = _7_0
289289+ local chunk = _8_0
290290+ local function _9_()
291291+ return print_values(chunk())
292292+ end
293293+ local function _10_(...)
294294+ return on_error("Runtime", ...)
295295+ end
296296+ xpcall(_9_, _10_)
297297+ end
298298+ end
299299+ end
300300+ utils.root.options = old_root_options
301301+ return loop()
302302+ end
303303+ end
304304+ end
305305+ return loop()
306306+ end
307307+ return repl
308308+end
309309+package.preload["fennel.view"] = package.preload["fennel.view"] or function(...)
310310+ local type_order = {["function"] = 5, boolean = 2, number = 1, string = 3, table = 4, thread = 7, userdata = 6}
311311+ local function sort_keys(_0_0, _1_0)
312312+ local _1_ = _0_0
313313+ local a = _1_[1]
314314+ local _2_ = _1_0
315315+ local b = _2_[1]
316316+ local ta = type(a)
317317+ local tb = type(b)
318318+ if ((ta == tb) and ((ta == "string") or (ta == "number"))) then
319319+ return (a < b)
320320+ else
321321+ local dta = type_order[ta]
322322+ local dtb = type_order[tb]
323323+ if (dta and dtb) then
324324+ return (dta < dtb)
325325+ elseif dta then
326326+ return true
327327+ elseif dtb then
328328+ return false
329329+ else
330330+ return (ta < tb)
331331+ end
332332+ end
333333+ end
334334+ local function table_kv_pairs(t)
335335+ local assoc_3f = false
336336+ local kv = {}
337337+ local insert = table.insert
338338+ for k, v in pairs(t) do
339339+ if (type(k) ~= "number") then
340340+ assoc_3f = true
341341+ end
342342+ insert(kv, {k, v})
343343+ end
344344+ table.sort(kv, sort_keys)
345345+ if (#kv == 0) then
346346+ return kv, "empty"
347347+ else
348348+ local function _2_()
349349+ if assoc_3f then
350350+ return "table"
351351+ else
352352+ return "seq"
353353+ end
354354+ end
355355+ return kv, _2_()
356356+ end
357357+ end
358358+ local function count_table_appearances(t, appearances)
359359+ if (type(t) == "table") then
360360+ if not appearances[t] then
361361+ appearances[t] = 1
362362+ for k, v in pairs(t) do
363363+ count_table_appearances(k, appearances)
364364+ count_table_appearances(v, appearances)
365365+ end
366366+ else
367367+ appearances[t] = ((appearances[t] or 0) + 1)
368368+ end
369369+ end
370370+ return appearances
371371+ end
372372+ local function save_table(t, seen)
373373+ local seen0 = (seen or {len = 0})
374374+ local id = (seen0.len + 1)
375375+ if not seen0[t] then
376376+ seen0[t] = id
377377+ seen0.len = id
378378+ end
379379+ return seen0
380380+ end
381381+ local function detect_cycle(t, seen)
382382+ local seen0 = (seen or {})
383383+ seen0[t] = true
384384+ for k, v in pairs(t) do
385385+ if ((type(k) == "table") and (seen0[k] or detect_cycle(k, seen0))) then
386386+ return true
387387+ end
388388+ if ((type(v) == "table") and (seen0[v] or detect_cycle(v, seen0))) then
389389+ return true
390390+ end
391391+ end
392392+ return nil
393393+ end
394394+ local function visible_cycle_3f(t, options)
395395+ return (options["detect-cycles?"] and detect_cycle(t) and save_table(t, options.seen) and (1 < (options.appearances[t] or 0)))
396396+ end
397397+ local function table_indent(t, indent, id)
398398+ local opener_length = nil
399399+ if id then
400400+ opener_length = (#tostring(id) + 2)
401401+ else
402402+ opener_length = 1
403403+ end
404404+ return (indent + opener_length)
405405+ end
406406+ local pp = {}
407407+ local function concat_table_lines(elements, options, multiline_3f, indent, table_type, prefix)
408408+ local indent_str = ("\n" .. string.rep(" ", indent))
409409+ local open = nil
410410+ local function _2_()
411411+ if ("seq" == table_type) then
412412+ return "["
413413+ else
414414+ return "{"
415415+ end
416416+ end
417417+ open = ((prefix or "") .. _2_())
418418+ local close = nil
419419+ if ("seq" == table_type) then
420420+ close = "]"
421421+ else
422422+ close = "}"
423423+ end
424424+ local oneline = (open .. table.concat(elements, " ") .. close)
425425+ local _4_
426426+ if (table_type == "seq") then
427427+ _4_ = options["sequential-length"]
428428+ else
429429+ _4_ = options["associative-length"]
430430+ end
431431+ if (not options["one-line?"] and (multiline_3f or (#elements > _4_) or ((indent + #oneline) > options["line-length"]))) then
432432+ return (open .. table.concat(elements, indent_str) .. close)
433433+ else
434434+ return oneline
435435+ end
436436+ end
437437+ local function pp_associative(t, kv, options, indent, key_3f)
438438+ local multiline_3f = false
439439+ local id = options.seen[t]
440440+ if (options.level >= options.depth) then
441441+ return "{...}"
442442+ elseif (id and options["detect-cycles?"]) then
443443+ return ("@" .. id .. "{...}")
444444+ else
445445+ local visible_cycle_3f0 = visible_cycle_3f(t, options)
446446+ local id0 = (visible_cycle_3f0 and options.seen[t])
447447+ local indent0 = table_indent(t, indent, id0)
448448+ local slength = nil
449449+ local function _3_()
450450+ local _2_0 = rawget(_G, "utf8")
451451+ if _2_0 then
452452+ return _2_0.len
453453+ else
454454+ return _2_0
455455+ end
456456+ end
457457+ local function _4_(_241)
458458+ return #_241
459459+ end
460460+ slength = ((options["utf8?"] and _3_()) or _4_)
461461+ local prefix = nil
462462+ if visible_cycle_3f0 then
463463+ prefix = ("@" .. id0)
464464+ else
465465+ prefix = ""
466466+ end
467467+ local elements = nil
468468+ do
469469+ local tbl_0_ = {}
470470+ for _, _6_0 in pairs(kv) do
471471+ local _7_ = _6_0
472472+ local k = _7_[1]
473473+ local v = _7_[2]
474474+ local _8_
475475+ do
476476+ local k0 = pp.pp(k, options, (indent0 + 1), true)
477477+ local v0 = pp.pp(v, options, (indent0 + slength(k0) + 1))
478478+ multiline_3f = (multiline_3f or k0:find("\n") or v0:find("\n"))
479479+ _8_ = (k0 .. " " .. v0)
480480+ end
481481+ tbl_0_[(#tbl_0_ + 1)] = _8_
482482+ end
483483+ elements = tbl_0_
484484+ end
485485+ return concat_table_lines(elements, options, multiline_3f, indent0, "table", prefix)
486486+ end
487487+ end
488488+ local function pp_sequence(t, kv, options, indent)
489489+ local multiline_3f = false
490490+ local id = options.seen[t]
491491+ if (options.level >= options.depth) then
492492+ return "[...]"
493493+ elseif (id and options["detect-cycles?"]) then
494494+ return ("@" .. id .. "[...]")
495495+ else
496496+ local visible_cycle_3f0 = visible_cycle_3f(t, options)
497497+ local id0 = (visible_cycle_3f0 and options.seen[t])
498498+ local indent0 = table_indent(t, indent, id0)
499499+ local prefix = nil
500500+ if visible_cycle_3f0 then
501501+ prefix = ("@" .. id0)
502502+ else
503503+ prefix = ""
504504+ end
505505+ local elements = nil
506506+ do
507507+ local tbl_0_ = {}
508508+ for _, _3_0 in pairs(kv) do
509509+ local _4_ = _3_0
510510+ local _0 = _4_[1]
511511+ local v = _4_[2]
512512+ local _5_
513513+ do
514514+ local v0 = pp.pp(v, options, indent0)
515515+ multiline_3f = (multiline_3f or v0:find("\n"))
516516+ _5_ = v0
517517+ end
518518+ tbl_0_[(#tbl_0_ + 1)] = _5_
519519+ end
520520+ elements = tbl_0_
521521+ end
522522+ return concat_table_lines(elements, options, multiline_3f, indent0, "seq", prefix)
523523+ end
524524+ end
525525+ local function concat_lines(lines, options, indent, force_multi_line_3f)
526526+ if (#lines == 0) then
527527+ if options["empty-as-sequence?"] then
528528+ return "[]"
529529+ else
530530+ return "{}"
531531+ end
532532+ else
533533+ local oneline = nil
534534+ local _2_
535535+ do
536536+ local tbl_0_ = {}
537537+ for _, line in ipairs(lines) do
538538+ tbl_0_[(#tbl_0_ + 1)] = line:gsub("^%s+", "")
539539+ end
540540+ _2_ = tbl_0_
541541+ end
542542+ oneline = table.concat(_2_, " ")
543543+ if (not options["one-line?"] and (force_multi_line_3f or oneline:find("\n") or ((indent + #oneline) > options["line-length"]))) then
544544+ return table.concat(lines, ("\n" .. string.rep(" ", indent)))
545545+ else
546546+ return oneline
547547+ end
548548+ end
549549+ end
550550+ local function pp_metamethod(t, metamethod, options, indent)
551551+ if (options.level >= options.depth) then
552552+ if options["empty-as-sequence?"] then
553553+ return "[...]"
554554+ else
555555+ return "{...}"
556556+ end
557557+ else
558558+ local _ = nil
559559+ local function _2_(_241)
560560+ return visible_cycle_3f(_241, options)
561561+ end
562562+ options["visible-cycle?"] = _2_
563563+ _ = nil
564564+ local lines, force_multi_line_3f = metamethod(t, pp.pp, options, indent)
565565+ options["visible-cycle?"] = nil
566566+ local _3_0 = type(lines)
567567+ if (_3_0 == "string") then
568568+ return lines
569569+ elseif (_3_0 == "table") then
570570+ return concat_lines(lines, options, indent, force_multi_line_3f)
571571+ else
572572+ local _0 = _3_0
573573+ return error("Error: __fennelview metamethod must return a table of lines")
574574+ end
575575+ end
576576+ end
577577+ local function pp_table(x, options, indent)
578578+ options.level = (options.level + 1)
579579+ local x0 = nil
580580+ do
581581+ local _2_0 = nil
582582+ if options["metamethod?"] then
583583+ local _3_0 = x
584584+ if _3_0 then
585585+ local _4_0 = getmetatable(_3_0)
586586+ if _4_0 then
587587+ _2_0 = _4_0.__fennelview
588588+ else
589589+ _2_0 = _4_0
590590+ end
591591+ else
592592+ _2_0 = _3_0
593593+ end
594594+ else
595595+ _2_0 = nil
596596+ end
597597+ if (nil ~= _2_0) then
598598+ local metamethod = _2_0
599599+ x0 = pp_metamethod(x, metamethod, options, indent)
600600+ else
601601+ local _ = _2_0
602602+ local _4_0, _5_0 = table_kv_pairs(x)
603603+ if (true and (_5_0 == "empty")) then
604604+ local _0 = _4_0
605605+ if options["empty-as-sequence?"] then
606606+ x0 = "[]"
607607+ else
608608+ x0 = "{}"
609609+ end
610610+ elseif ((nil ~= _4_0) and (_5_0 == "table")) then
611611+ local kv = _4_0
612612+ x0 = pp_associative(x, kv, options, indent)
613613+ elseif ((nil ~= _4_0) and (_5_0 == "seq")) then
614614+ local kv = _4_0
615615+ x0 = pp_sequence(x, kv, options, indent)
616616+ else
617617+ x0 = nil
618618+ end
619619+ end
620620+ end
621621+ options.level = (options.level - 1)
622622+ return x0
623623+ end
624624+ local function number__3estring(n)
625625+ local _2_0, _3_0, _4_0 = math.modf(n)
626626+ if ((nil ~= _2_0) and (_3_0 == 0)) then
627627+ local int = _2_0
628628+ return tostring(int)
629629+ else
630630+ local _5_
631631+ do
632632+ local frac = _3_0
633633+ _5_ = (((_2_0 == 0) and (nil ~= _3_0)) and (frac < 0))
634634+ end
635635+ if _5_ then
636636+ local frac = _3_0
637637+ return ("-0." .. tostring(frac):gsub("^-?0.", ""))
638638+ elseif ((nil ~= _2_0) and (nil ~= _3_0)) then
639639+ local int = _2_0
640640+ local frac = _3_0
641641+ return (int .. "." .. tostring(frac):gsub("^-?0.", ""))
642642+ end
643643+ end
644644+ end
645645+ local function colon_string_3f(s)
646646+ return s:find("^[-%w?\\^_!$%&*+./@:|<=>]+$")
647647+ end
648648+ local function make_options(t, options)
649649+ local defaults = {["associative-length"] = 4, ["detect-cycles?"] = true, ["empty-as-sequence?"] = false, ["line-length"] = 80, ["metamethod?"] = true, ["one-line?"] = false, ["sequential-length"] = 10, ["utf8?"] = true, depth = 128}
650650+ local overrides = {appearances = count_table_appearances(t, {}), level = 0, seen = {len = 0}}
651651+ for k, v in pairs((options or {})) do
652652+ defaults[k] = v
653653+ end
654654+ for k, v in pairs(overrides) do
655655+ defaults[k] = v
656656+ end
657657+ return defaults
658658+ end
659659+ pp.pp = function(x, options, indent, key_3f)
660660+ local indent0 = (indent or 0)
661661+ local options0 = (options or make_options(x))
662662+ local tv = type(x)
663663+ local function _3_()
664664+ local _2_0 = getmetatable(x)
665665+ if _2_0 then
666666+ return _2_0.__fennelview
667667+ else
668668+ return _2_0
669669+ end
670670+ end
671671+ if ((tv == "table") or ((tv == "userdata") and _3_())) then
672672+ return pp_table(x, options0, indent0)
673673+ elseif (tv == "number") then
674674+ return number__3estring(x)
675675+ elseif ((tv == "string") and key_3f and colon_string_3f(x)) then
676676+ return (":" .. x)
677677+ elseif (tv == "string") then
678678+ return string.format("%q", x)
679679+ elseif ((tv == "boolean") or (tv == "nil")) then
680680+ return tostring(x)
681681+ else
682682+ return ("#<" .. tostring(x) .. ">")
683683+ end
684684+ end
685685+ local function view(x, options)
686686+ return pp.pp(x, make_options(x, options), 0)
687687+ end
688688+ return view
689689+end
690690+package.preload["fennel.specials"] = package.preload["fennel.specials"] or function(...)
691691+ local utils = require("fennel.utils")
692692+ local view = require("fennel.view")
693693+ local parser = require("fennel.parser")
694694+ local compiler = require("fennel.compiler")
695695+ local unpack = (table.unpack or _G.unpack)
696696+ local SPECIALS = compiler.scopes.global.specials
697697+ local function wrap_env(env)
698698+ local function _0_(_, key)
699699+ if (type(key) == "string") then
700700+ return env[compiler["global-unmangling"](key)]
701701+ else
702702+ return env[key]
703703+ end
704704+ end
705705+ local function _1_(_, key, value)
706706+ if (type(key) == "string") then
707707+ env[compiler["global-unmangling"](key)] = value
708708+ return nil
709709+ else
710710+ env[key] = value
711711+ return nil
712712+ end
713713+ end
714714+ local function _2_()
715715+ local function putenv(k, v)
716716+ local _3_
717717+ if (type(k) == "string") then
718718+ _3_ = compiler["global-unmangling"](k)
719719+ else
720720+ _3_ = k
721721+ end
722722+ return _3_, v
723723+ end
724724+ return next, utils.kvmap(env, putenv), nil
725725+ end
726726+ return setmetatable({}, {__index = _0_, __newindex = _1_, __pairs = _2_})
727727+ end
728728+ local function current_global_names(env)
729729+ return utils.kvmap((env or _G), compiler["global-unmangling"])
730730+ end
731731+ local function load_code(code, environment, filename)
732732+ local environment0 = (environment or rawget(_G, "_ENV") or _G)
733733+ if (rawget(_G, "setfenv") and rawget(_G, "loadstring")) then
734734+ local f = assert(_G.loadstring(code, filename))
735735+ _G.setfenv(f, environment0)
736736+ return f
737737+ else
738738+ return assert(load(code, filename, "t", environment0))
739739+ end
740740+ end
741741+ local function doc_2a(tgt, name)
742742+ if not tgt then
743743+ return (name .. " not found")
744744+ else
745745+ local docstring = (((compiler.metadata):get(tgt, "fnl/docstring") or "#<undocumented>")):gsub("\n$", ""):gsub("\n", "\n ")
746746+ local mt = getmetatable(tgt)
747747+ if ((type(tgt) == "function") or ((type(mt) == "table") and (type(mt.__call) == "function"))) then
748748+ local arglist = table.concat(((compiler.metadata):get(tgt, "fnl/arglist") or {"#<unknown-arguments>"}), " ")
749749+ local _0_
750750+ if (#arglist > 0) then
751751+ _0_ = " "
752752+ else
753753+ _0_ = ""
754754+ end
755755+ return string.format("(%s%s%s)\n %s", name, _0_, arglist, docstring)
756756+ else
757757+ return string.format("%s\n %s", name, docstring)
758758+ end
759759+ end
760760+ end
761761+ local function doc_special(name, arglist, docstring)
762762+ compiler.metadata[SPECIALS[name]] = {["fnl/arglist"] = arglist, ["fnl/docstring"] = docstring}
763763+ return nil
764764+ end
765765+ local function compile_do(ast, scope, parent, start)
766766+ local start0 = (start or 2)
767767+ local len = #ast
768768+ local sub_scope = compiler["make-scope"](scope)
769769+ for i = start0, len do
770770+ compiler.compile1(ast[i], sub_scope, parent, {nval = 0})
771771+ end
772772+ return nil
773773+ end
774774+ SPECIALS["do"] = function(ast, scope, parent, opts, start, chunk, sub_scope, pre_syms)
775775+ local start0 = (start or 2)
776776+ local sub_scope0 = (sub_scope or compiler["make-scope"](scope))
777777+ local chunk0 = (chunk or {})
778778+ local len = #ast
779779+ local retexprs = {returned = true}
780780+ local function compile_body(outer_target, outer_tail, outer_retexprs)
781781+ if (len < start0) then
782782+ compiler.compile1(nil, sub_scope0, chunk0, {tail = outer_tail, target = outer_target})
783783+ else
784784+ for i = start0, len do
785785+ 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)}
786786+ local _ = utils["propagate-options"](opts, subopts)
787787+ local subexprs = compiler.compile1(ast[i], sub_scope0, chunk0, subopts)
788788+ if (i ~= len) then
789789+ compiler["keep-side-effects"](subexprs, parent, nil, ast[i])
790790+ end
791791+ end
792792+ end
793793+ compiler.emit(parent, chunk0, ast)
794794+ compiler.emit(parent, "end", ast)
795795+ return (outer_retexprs or retexprs)
796796+ end
797797+ if (opts.target or (opts.nval == 0) or opts.tail) then
798798+ compiler.emit(parent, "do", ast)
799799+ return compile_body(opts.target, opts.tail)
800800+ elseif opts.nval then
801801+ local syms = {}
802802+ for i = 1, opts.nval do
803803+ local s = ((pre_syms and pre_syms[i]) or compiler.gensym(scope))
804804+ syms[i] = s
805805+ retexprs[i] = utils.expr(s, "sym")
806806+ end
807807+ local outer_target = table.concat(syms, ", ")
808808+ compiler.emit(parent, string.format("local %s", outer_target), ast)
809809+ compiler.emit(parent, "do", ast)
810810+ return compile_body(outer_target, opts.tail)
811811+ else
812812+ local fname = compiler.gensym(scope)
813813+ local fargs = nil
814814+ if scope.vararg then
815815+ fargs = "..."
816816+ else
817817+ fargs = ""
818818+ end
819819+ compiler.emit(parent, string.format("local function %s(%s)", fname, fargs), ast)
820820+ utils.hook("do", ast, sub_scope0)
821821+ return compile_body(nil, true, utils.expr((fname .. "(" .. fargs .. ")"), "statement"))
822822+ end
823823+ end
824824+ doc_special("do", {"..."}, "Evaluate multiple forms; return last value.")
825825+ SPECIALS.values = function(ast, scope, parent)
826826+ local len = #ast
827827+ local exprs = {}
828828+ for i = 2, len do
829829+ local subexprs = compiler.compile1(ast[i], scope, parent, {nval = ((i ~= len) and 1)})
830830+ table.insert(exprs, subexprs[1])
831831+ if (i == len) then
832832+ for j = 2, #subexprs do
833833+ table.insert(exprs, subexprs[j])
834834+ end
835835+ end
836836+ end
837837+ return exprs
838838+ end
839839+ doc_special("values", {"..."}, "Return multiple values from a function. Must be in tail position.")
840840+ local function deep_tostring(x, key_3f)
841841+ local elems = {}
842842+ if utils["sequence?"](x) then
843843+ local _0_
844844+ do
845845+ local tbl_0_ = {}
846846+ for _, v in ipairs(x) do
847847+ tbl_0_[(#tbl_0_ + 1)] = deep_tostring(v)
848848+ end
849849+ _0_ = tbl_0_
850850+ end
851851+ return ("[" .. table.concat(_0_, " ") .. "]")
852852+ elseif utils["table?"](x) then
853853+ local _0_
854854+ do
855855+ local tbl_0_ = {}
856856+ for k, v in pairs(x) do
857857+ tbl_0_[(#tbl_0_ + 1)] = (deep_tostring(k, true) .. " " .. deep_tostring(v))
858858+ end
859859+ _0_ = tbl_0_
860860+ end
861861+ return ("{" .. table.concat(_0_, " ") .. "}")
862862+ elseif (key_3f and (type(x) == "string") and x:find("^[-%w?\\^_!$%&*+./@:|<=>]+$")) then
863863+ return (":" .. x)
864864+ elseif (type(x) == "string") then
865865+ return string.format("%q", x):gsub("\\\"", "\\\\\""):gsub("\"", "\\\"")
866866+ else
867867+ return tostring(x)
868868+ end
869869+ end
870870+ local function set_fn_metadata(arg_list, docstring, parent, fn_name)
871871+ if utils.root.options.useMetadata then
872872+ local args = nil
873873+ local function _0_(v)
874874+ return ("\"%s\""):format(deep_tostring(v))
875875+ end
876876+ args = utils.map(arg_list, _0_)
877877+ local meta_fields = {"\"fnl/arglist\"", ("{" .. table.concat(args, ", ") .. "}")}
878878+ if docstring then
879879+ table.insert(meta_fields, "\"fnl/docstring\"")
880880+ table.insert(meta_fields, ("\"" .. docstring:gsub("%s+$", ""):gsub("\\", "\\\\"):gsub("\n", "\\n"):gsub("\"", "\\\"") .. "\""))
881881+ end
882882+ local meta_str = ("require(\"%s\").metadata"):format((utils.root.options.moduleName or "fennel"))
883883+ return compiler.emit(parent, ("pcall(function() %s:setall(%s, %s) end)"):format(meta_str, fn_name, table.concat(meta_fields, ", ")))
884884+ end
885885+ end
886886+ local function get_fn_name(ast, scope, fn_name, multi)
887887+ if (fn_name and (fn_name[1] ~= "nil")) then
888888+ local _0_
889889+ if not multi then
890890+ _0_ = compiler["declare-local"](fn_name, {}, scope, ast)
891891+ else
892892+ _0_ = compiler["symbol-to-expression"](fn_name, scope)[1]
893893+ end
894894+ return _0_, not multi, 3
895895+ else
896896+ return compiler.gensym(scope), true, 2
897897+ end
898898+ end
899899+ SPECIALS.fn = function(ast, scope, parent)
900900+ local f_scope = nil
901901+ do
902902+ local _0_0 = compiler["make-scope"](scope)
903903+ _0_0["vararg"] = false
904904+ f_scope = _0_0
905905+ end
906906+ local f_chunk = {}
907907+ local fn_sym = utils["sym?"](ast[2])
908908+ local multi = (fn_sym and utils["multi-sym?"](fn_sym[1]))
909909+ local fn_name, local_fn_3f, index = get_fn_name(ast, scope, fn_sym, multi)
910910+ local arg_list = compiler.assert(utils["table?"](ast[index]), "expected parameters table", ast)
911911+ compiler.assert((not multi or not multi["multi-sym-method-call"]), ("unexpected multi symbol " .. tostring(fn_name)), fn_sym)
912912+ local function get_arg_name(arg)
913913+ if utils["varg?"](arg) then
914914+ compiler.assert((arg == arg_list[#arg_list]), "expected vararg as last parameter", ast)
915915+ f_scope.vararg = true
916916+ return "..."
917917+ elseif (utils["sym?"](arg) and (utils.deref(arg) ~= "nil") and not utils["multi-sym?"](utils.deref(arg))) then
918918+ return compiler["declare-local"](arg, {}, f_scope, ast)
919919+ elseif utils["table?"](arg) then
920920+ local raw = utils.sym(compiler.gensym(scope))
921921+ local declared = compiler["declare-local"](raw, {}, f_scope, ast)
922922+ compiler.destructure(arg, raw, ast, f_scope, f_chunk, {declaration = true, nomulti = true, symtype = "arg"})
923923+ return declared
924924+ else
925925+ return compiler.assert(false, ("expected symbol for function parameter: %s"):format(tostring(arg)), ast[2])
926926+ end
927927+ end
928928+ do
929929+ local arg_name_list = utils.map(arg_list, get_arg_name)
930930+ local index0, docstring = nil, nil
931931+ if ((type(ast[(index + 1)]) == "string") and ((index + 1) < #ast)) then
932932+ index0, docstring = (index + 1), ast[(index + 1)]
933933+ else
934934+ index0, docstring = index, nil
935935+ end
936936+ for i = (index0 + 1), #ast do
937937+ compiler.compile1(ast[i], f_scope, f_chunk, {nval = (((i ~= #ast) and 0) or nil), tail = (i == #ast)})
938938+ end
939939+ local _2_
940940+ if local_fn_3f then
941941+ _2_ = "local function %s(%s)"
942942+ else
943943+ _2_ = "%s = function(%s)"
944944+ end
945945+ compiler.emit(parent, string.format(_2_, fn_name, table.concat(arg_name_list, ", ")), ast)
946946+ compiler.emit(parent, f_chunk, ast)
947947+ compiler.emit(parent, "end", ast)
948948+ set_fn_metadata(arg_list, docstring, parent, fn_name)
949949+ end
950950+ utils.hook("fn", ast, f_scope)
951951+ return utils.expr(fn_name, "sym")
952952+ end
953953+ doc_special("fn", {"name?", "args", "docstring?", "..."}, "Function syntax. May optionally include a name and docstring.\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.")
954954+ SPECIALS.lua = function(ast, _, parent)
955955+ compiler.assert(((#ast == 2) or (#ast == 3)), "expected 1 or 2 arguments", ast)
956956+ if (ast[2] ~= nil) then
957957+ table.insert(parent, {ast = ast, leaf = tostring(ast[2])})
958958+ end
959959+ if (ast[3] ~= nil) then
960960+ return tostring(ast[3])
961961+ end
962962+ end
963963+ SPECIALS.doc = function(ast, scope, parent)
964964+ assert(utils.root.options.useMetadata, "can't look up doc with metadata disabled.")
965965+ compiler.assert((#ast == 2), "expected one argument", ast)
966966+ local target = utils.deref(ast[2])
967967+ local special_or_macro = (scope.specials[target] or scope.macros[target])
968968+ if special_or_macro then
969969+ return ("print(%q)"):format(doc_2a(special_or_macro, target))
970970+ else
971971+ local value = tostring(compiler.compile1(ast[2], scope, parent, {nval = 1})[1])
972972+ return ("print(require('%s').doc(%s, '%s'))"):format((utils.root.options.moduleName or "fennel"), value, tostring(ast[2]))
973973+ end
974974+ end
975975+ doc_special("doc", {"x"}, "Print the docstring and arglist for a function, macro, or special form.")
976976+ local function dot(ast, scope, parent)
977977+ compiler.assert((1 < #ast), "expected table argument", ast)
978978+ local len = #ast
979979+ local _0_ = compiler.compile1(ast[2], scope, parent, {nval = 1})
980980+ local lhs = _0_[1]
981981+ if (len == 2) then
982982+ return tostring(lhs)
983983+ else
984984+ local indices = {}
985985+ for i = 3, len do
986986+ local index = ast[i]
987987+ if ((type(index) == "string") and utils["valid-lua-identifier?"](index)) then
988988+ table.insert(indices, ("." .. index))
989989+ else
990990+ local _1_ = compiler.compile1(index, scope, parent, {nval = 1})
991991+ local index0 = _1_[1]
992992+ table.insert(indices, ("[" .. tostring(index0) .. "]"))
993993+ end
994994+ end
995995+ if (tostring(lhs):find("[{\"0-9]") or ("nil" == tostring(lhs))) then
996996+ return ("(" .. tostring(lhs) .. ")" .. table.concat(indices))
997997+ else
998998+ return (tostring(lhs) .. table.concat(indices))
999999+ end
10001000+ end
10011001+ end
10021002+ SPECIALS["."] = dot
10031003+ doc_special(".", {"tbl", "key1", "..."}, "Look up key1 in tbl table. If more args are provided, do a nested lookup.")
10041004+ SPECIALS.global = function(ast, scope, parent)
10051005+ compiler.assert((#ast == 3), "expected name and value", ast)
10061006+ compiler.destructure(ast[2], ast[3], ast, scope, parent, {forceglobal = true, nomulti = true, symtype = "global"})
10071007+ return nil
10081008+ end
10091009+ doc_special("global", {"name", "val"}, "Set name as a global with val.")
10101010+ SPECIALS.set = function(ast, scope, parent)
10111011+ compiler.assert((#ast == 3), "expected name and value", ast)
10121012+ compiler.destructure(ast[2], ast[3], ast, scope, parent, {noundef = true, symtype = "set"})
10131013+ return nil
10141014+ end
10151015+ doc_special("set", {"name", "val"}, "Set a local variable to a new value. Only works on locals using var.")
10161016+ local function set_forcibly_21_2a(ast, scope, parent)
10171017+ compiler.assert((#ast == 3), "expected name and value", ast)
10181018+ compiler.destructure(ast[2], ast[3], ast, scope, parent, {forceset = true, symtype = "set"})
10191019+ return nil
10201020+ end
10211021+ SPECIALS["set-forcibly!"] = set_forcibly_21_2a
10221022+ local function local_2a(ast, scope, parent)
10231023+ compiler.assert((#ast == 3), "expected name and value", ast)
10241024+ compiler.destructure(ast[2], ast[3], ast, scope, parent, {declaration = true, nomulti = true, symtype = "local"})
10251025+ return nil
10261026+ end
10271027+ SPECIALS["local"] = local_2a
10281028+ doc_special("local", {"name", "val"}, "Introduce new top-level immutable local.")
10291029+ SPECIALS.var = function(ast, scope, parent)
10301030+ compiler.assert((#ast == 3), "expected name and value", ast)
10311031+ compiler.destructure(ast[2], ast[3], ast, scope, parent, {declaration = true, isvar = true, nomulti = true, symtype = "var"})
10321032+ return nil
10331033+ end
10341034+ doc_special("var", {"name", "val"}, "Introduce new mutable local.")
10351035+ SPECIALS.let = function(ast, scope, parent, opts)
10361036+ local bindings = ast[2]
10371037+ local pre_syms = {}
10381038+ compiler.assert((utils["list?"](bindings) or utils["table?"](bindings)), "expected binding table", ast)
10391039+ compiler.assert(((#bindings % 2) == 0), "expected even number of name/value bindings", ast[2])
10401040+ compiler.assert((#ast >= 3), "expected body expression", ast[1])
10411041+ for _ = 1, (opts.nval or 0) do
10421042+ table.insert(pre_syms, compiler.gensym(scope))
10431043+ end
10441044+ local sub_scope = compiler["make-scope"](scope)
10451045+ local sub_chunk = {}
10461046+ for i = 1, #bindings, 2 do
10471047+ compiler.destructure(bindings[i], bindings[(i + 1)], ast, sub_scope, sub_chunk, {declaration = true, nomulti = true, symtype = "let"})
10481048+ end
10491049+ return SPECIALS["do"](ast, scope, parent, opts, 3, sub_chunk, sub_scope, pre_syms)
10501050+ end
10511051+ doc_special("let", {"[name1 val1 ... nameN valN]", "..."}, "Introduces a new scope in which a given set of local bindings are used.")
10521052+ SPECIALS.tset = function(ast, scope, parent)
10531053+ compiler.assert((#ast > 3), "expected table, key, and value arguments", ast)
10541054+ local root = compiler.compile1(ast[2], scope, parent, {nval = 1})[1]
10551055+ local keys = {}
10561056+ for i = 3, (#ast - 1) do
10571057+ local _0_ = compiler.compile1(ast[i], scope, parent, {nval = 1})
10581058+ local key = _0_[1]
10591059+ table.insert(keys, tostring(key))
10601060+ end
10611061+ local value = compiler.compile1(ast[#ast], scope, parent, {nval = 1})[1]
10621062+ local rootstr = tostring(root)
10631063+ local fmtstr = nil
10641064+ if rootstr:match("^{") then
10651065+ fmtstr = "do end (%s)[%s] = %s"
10661066+ else
10671067+ fmtstr = "%s[%s] = %s"
10681068+ end
10691069+ return compiler.emit(parent, fmtstr:format(tostring(root), table.concat(keys, "]["), tostring(value)), ast)
10701070+ end
10711071+ 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.")
10721072+ local function calculate_target(scope, opts)
10731073+ if not (opts.tail or opts.target or opts.nval) then
10741074+ return "iife", true, nil
10751075+ elseif (opts.nval and (opts.nval ~= 0) and not opts.target) then
10761076+ local accum = {}
10771077+ local target_exprs = {}
10781078+ for i = 1, opts.nval do
10791079+ local s = compiler.gensym(scope)
10801080+ accum[i] = s
10811081+ target_exprs[i] = utils.expr(s, "sym")
10821082+ end
10831083+ return "target", opts.tail, table.concat(accum, ", "), target_exprs
10841084+ else
10851085+ return "none", opts.tail, opts.target
10861086+ end
10871087+ end
10881088+ local function if_2a(ast, scope, parent, opts)
10891089+ local do_scope = compiler["make-scope"](scope)
10901090+ local branches = {}
10911091+ local wrapper, inner_tail, inner_target, target_exprs = calculate_target(scope, opts)
10921092+ local body_opts = {nval = opts.nval, tail = inner_tail, target = inner_target}
10931093+ local function compile_body(i)
10941094+ local chunk = {}
10951095+ local cscope = compiler["make-scope"](do_scope)
10961096+ compiler["keep-side-effects"](compiler.compile1(ast[i], cscope, chunk, body_opts), chunk, nil, ast[i])
10971097+ return {chunk = chunk, scope = cscope}
10981098+ end
10991099+ for i = 2, (#ast - 1), 2 do
11001100+ local condchunk = {}
11011101+ local res = compiler.compile1(ast[i], do_scope, condchunk, {nval = 1})
11021102+ local cond = res[1]
11031103+ local branch = compile_body((i + 1))
11041104+ branch.cond = cond
11051105+ branch.condchunk = condchunk
11061106+ branch.nested = ((i ~= 2) and (next(condchunk, nil) == nil))
11071107+ table.insert(branches, branch)
11081108+ end
11091109+ local has_else_3f = ((#ast > 3) and ((#ast % 2) == 0))
11101110+ local else_branch = (has_else_3f and compile_body(#ast))
11111111+ local s = compiler.gensym(scope)
11121112+ local buffer = {}
11131113+ local last_buffer = buffer
11141114+ for i = 1, #branches do
11151115+ local branch = branches[i]
11161116+ local fstr = nil
11171117+ if not branch.nested then
11181118+ fstr = "if %s then"
11191119+ else
11201120+ fstr = "elseif %s then"
11211121+ end
11221122+ local cond = tostring(branch.cond)
11231123+ local cond_line = nil
11241124+ if ((cond == "true") and branch.nested and (i == #branches)) then
11251125+ cond_line = "else"
11261126+ else
11271127+ cond_line = fstr:format(cond)
11281128+ end
11291129+ if branch.nested then
11301130+ compiler.emit(last_buffer, branch.condchunk, ast)
11311131+ else
11321132+ for _, v in ipairs(branch.condchunk) do
11331133+ compiler.emit(last_buffer, v, ast)
11341134+ end
11351135+ end
11361136+ compiler.emit(last_buffer, cond_line, ast)
11371137+ compiler.emit(last_buffer, branch.chunk, ast)
11381138+ if (i == #branches) then
11391139+ if has_else_3f then
11401140+ compiler.emit(last_buffer, "else", ast)
11411141+ compiler.emit(last_buffer, else_branch.chunk, ast)
11421142+ elseif (inner_target and (cond_line ~= "else")) then
11431143+ compiler.emit(last_buffer, "else", ast)
11441144+ compiler.emit(last_buffer, ("%s = nil"):format(inner_target), ast)
11451145+ end
11461146+ compiler.emit(last_buffer, "end", ast)
11471147+ elseif not branches[(i + 1)].nested then
11481148+ local next_buffer = {}
11491149+ compiler.emit(last_buffer, "else", ast)
11501150+ compiler.emit(last_buffer, next_buffer, ast)
11511151+ compiler.emit(last_buffer, "end", ast)
11521152+ last_buffer = next_buffer
11531153+ end
11541154+ end
11551155+ if (wrapper == "iife") then
11561156+ local iifeargs = ((scope.vararg and "...") or "")
11571157+ compiler.emit(parent, ("local function %s(%s)"):format(tostring(s), iifeargs), ast)
11581158+ compiler.emit(parent, buffer, ast)
11591159+ compiler.emit(parent, "end", ast)
11601160+ return utils.expr(("%s(%s)"):format(tostring(s), iifeargs), "statement")
11611161+ elseif (wrapper == "none") then
11621162+ for i = 1, #buffer do
11631163+ compiler.emit(parent, buffer[i], ast)
11641164+ end
11651165+ return {returned = true}
11661166+ else
11671167+ compiler.emit(parent, ("local %s"):format(inner_target), ast)
11681168+ for i = 1, #buffer do
11691169+ compiler.emit(parent, buffer[i], ast)
11701170+ end
11711171+ return target_exprs
11721172+ end
11731173+ end
11741174+ SPECIALS["if"] = if_2a
11751175+ 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.")
11761176+ SPECIALS.each = function(ast, scope, parent)
11771177+ compiler.assert((#ast >= 3), "expected body expression", ast[1])
11781178+ local binding = compiler.assert(utils["table?"](ast[2]), "expected binding table", ast)
11791179+ local iter = table.remove(binding, #binding)
11801180+ local destructures = {}
11811181+ local new_manglings = {}
11821182+ local sub_scope = compiler["make-scope"](scope)
11831183+ local function destructure_binding(v)
11841184+ if utils["sym?"](v) then
11851185+ return compiler["declare-local"](v, {}, sub_scope, ast, new_manglings)
11861186+ else
11871187+ local raw = utils.sym(compiler.gensym(sub_scope))
11881188+ destructures[raw] = v
11891189+ return compiler["declare-local"](raw, {}, sub_scope, ast)
11901190+ end
11911191+ end
11921192+ local bind_vars = utils.map(binding, destructure_binding)
11931193+ local vals = compiler.compile1(iter, sub_scope, parent)
11941194+ local val_names = utils.map(vals, tostring)
11951195+ local chunk = {}
11961196+ compiler.emit(parent, ("for %s in %s do"):format(table.concat(bind_vars, ", "), table.concat(val_names, ", ")), ast)
11971197+ for raw, args in utils.stablepairs(destructures) do
11981198+ compiler.destructure(args, raw, ast, sub_scope, chunk, {declaration = true, nomulti = true, symtype = "each"})
11991199+ end
12001200+ compiler["apply-manglings"](sub_scope, new_manglings, ast)
12011201+ compile_do(ast, sub_scope, chunk, 3)
12021202+ compiler.emit(parent, chunk, ast)
12031203+ return compiler.emit(parent, "end", ast)
12041204+ end
12051205+ 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.")
12061206+ local function while_2a(ast, scope, parent)
12071207+ local len1 = #parent
12081208+ local condition = compiler.compile1(ast[2], scope, parent, {nval = 1})[1]
12091209+ local len2 = #parent
12101210+ local sub_chunk = {}
12111211+ if (len1 ~= len2) then
12121212+ for i = (len1 + 1), len2 do
12131213+ table.insert(sub_chunk, parent[i])
12141214+ parent[i] = nil
12151215+ end
12161216+ compiler.emit(parent, "while true do", ast)
12171217+ compiler.emit(sub_chunk, ("if not %s then break end"):format(condition[1]), ast)
12181218+ else
12191219+ compiler.emit(parent, ("while " .. tostring(condition) .. " do"), ast)
12201220+ end
12211221+ compile_do(ast, compiler["make-scope"](scope), sub_chunk, 3)
12221222+ compiler.emit(parent, sub_chunk, ast)
12231223+ return compiler.emit(parent, "end", ast)
12241224+ end
12251225+ SPECIALS["while"] = while_2a
12261226+ doc_special("while", {"condition", "..."}, "The classic while loop. Evaluates body until a condition is non-truthy.")
12271227+ local function for_2a(ast, scope, parent)
12281228+ local ranges = compiler.assert(utils["table?"](ast[2]), "expected binding table", ast)
12291229+ local binding_sym = table.remove(ast[2], 1)
12301230+ local sub_scope = compiler["make-scope"](scope)
12311231+ local range_args = {}
12321232+ local chunk = {}
12331233+ compiler.assert(utils["sym?"](binding_sym), ("unable to bind %s %s"):format(type(binding_sym), tostring(binding_sym)), ast[2])
12341234+ compiler.assert((#ast >= 3), "expected body expression", ast[1])
12351235+ for i = 1, math.min(#ranges, 3) do
12361236+ range_args[i] = tostring(compiler.compile1(ranges[i], sub_scope, parent, {nval = 1})[1])
12371237+ end
12381238+ compiler.emit(parent, ("for %s = %s do"):format(compiler["declare-local"](binding_sym, {}, sub_scope, ast), table.concat(range_args, ", ")), ast)
12391239+ compile_do(ast, sub_scope, chunk, 3)
12401240+ compiler.emit(parent, chunk, ast)
12411241+ return compiler.emit(parent, "end", ast)
12421242+ end
12431243+ SPECIALS["for"] = for_2a
12441244+ doc_special("for", {"[index start stop step?]", "..."}, "Numeric loop construct.\nEvaluates body once for each value between start and stop (inclusive).")
12451245+ local function native_method_call(ast, _scope, _parent, target, args)
12461246+ local _0_ = ast
12471247+ local _ = _0_[1]
12481248+ local _0 = _0_[2]
12491249+ local method_string = _0_[3]
12501250+ local call_string = nil
12511251+ if ((target.type == "literal") or (target.type == "expression")) then
12521252+ call_string = "(%s):%s(%s)"
12531253+ else
12541254+ call_string = "%s:%s(%s)"
12551255+ end
12561256+ return utils.expr(string.format(call_string, tostring(target), method_string, table.concat(args, ", ")), "statement")
12571257+ end
12581258+ local function nonnative_method_call(ast, scope, parent, target, args)
12591259+ local method_string = tostring(compiler.compile1(ast[3], scope, parent, {nval = 1})[1])
12601260+ local args0 = {tostring(target), unpack(args)}
12611261+ return utils.expr(string.format("%s[%s](%s)", tostring(target), method_string, table.concat(args0, ", ")), "statement")
12621262+ end
12631263+ local function double_eval_protected_method_call(ast, scope, parent, target, args)
12641264+ local method_string = tostring(compiler.compile1(ast[3], scope, parent, {nval = 1})[1])
12651265+ local call = "(function(tgt, m, ...) return tgt[m](tgt, ...) end)(%s, %s)"
12661266+ table.insert(args, 1, method_string)
12671267+ return utils.expr(string.format(call, tostring(target), table.concat(args, ", ")), "statement")
12681268+ end
12691269+ local function method_call(ast, scope, parent)
12701270+ compiler.assert((2 < #ast), "expected at least 2 arguments", ast)
12711271+ local _0_ = compiler.compile1(ast[2], scope, parent, {nval = 1})
12721272+ local target = _0_[1]
12731273+ local args = {}
12741274+ for i = 4, #ast do
12751275+ local subexprs = nil
12761276+ local _1_
12771277+ if (i ~= #ast) then
12781278+ _1_ = 1
12791279+ else
12801280+ _1_ = nil
12811281+ end
12821282+ subexprs = compiler.compile1(ast[i], scope, parent, {nval = _1_})
12831283+ utils.map(subexprs, tostring, args)
12841284+ end
12851285+ if ((type(ast[3]) == "string") and utils["valid-lua-identifier?"](ast[3])) then
12861286+ return native_method_call(ast, scope, parent, target, args)
12871287+ elseif (target.type == "sym") then
12881288+ return nonnative_method_call(ast, scope, parent, target, args)
12891289+ else
12901290+ return double_eval_protected_method_call(ast, scope, parent, target, args)
12911291+ end
12921292+ end
12931293+ SPECIALS[":"] = method_call
12941294+ 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.")
12951295+ SPECIALS.comment = function(ast, _, parent)
12961296+ local els = {}
12971297+ for i = 2, #ast do
12981298+ local function _1_()
12991299+ local _0_0 = tostring(ast[i]):gsub("\n", " ")
13001300+ return _0_0
13011301+ end
13021302+ table.insert(els, _1_())
13031303+ end
13041304+ return compiler.emit(parent, ("-- " .. table.concat(els, " ")), ast)
13051305+ end
13061306+ doc_special("comment", {"..."}, "Comment which will be emitted in Lua output.")
13071307+ local function hashfn_max_used(f_scope, i, max)
13081308+ local max0 = nil
13091309+ if f_scope.symmeta[("$" .. i)].used then
13101310+ max0 = i
13111311+ else
13121312+ max0 = max
13131313+ end
13141314+ if (i < 9) then
13151315+ return hashfn_max_used(f_scope, (i + 1), max0)
13161316+ else
13171317+ return max0
13181318+ end
13191319+ end
13201320+ SPECIALS.hashfn = function(ast, scope, parent)
13211321+ compiler.assert((#ast == 2), "expected one argument", ast)
13221322+ local f_scope = nil
13231323+ do
13241324+ local _0_0 = compiler["make-scope"](scope)
13251325+ _0_0["vararg"] = false
13261326+ _0_0["hashfn"] = true
13271327+ f_scope = _0_0
13281328+ end
13291329+ local f_chunk = {}
13301330+ local name = compiler.gensym(scope)
13311331+ local symbol = utils.sym(name)
13321332+ local args = {}
13331333+ compiler["declare-local"](symbol, {}, scope, ast)
13341334+ for i = 1, 9 do
13351335+ args[i] = compiler["declare-local"](utils.sym(("$" .. i)), {}, f_scope, ast)
13361336+ end
13371337+ local function walker(idx, node, parent_node)
13381338+ if (utils["sym?"](node) and (utils.deref(node) == "$...")) then
13391339+ parent_node[idx] = utils.varg()
13401340+ f_scope.vararg = true
13411341+ return nil
13421342+ else
13431343+ return (utils["list?"](node) or utils["table?"](node))
13441344+ end
13451345+ end
13461346+ utils["walk-tree"](ast[2], walker)
13471347+ compiler.compile1(ast[2], f_scope, f_chunk, {tail = true})
13481348+ local max_used = hashfn_max_used(f_scope, 1, 0)
13491349+ if f_scope.vararg then
13501350+ compiler.assert((max_used == 0), "$ and $... in hashfn are mutually exclusive", ast)
13511351+ end
13521352+ local arg_str = nil
13531353+ if f_scope.vararg then
13541354+ arg_str = utils.deref(utils.varg())
13551355+ else
13561356+ arg_str = table.concat(args, ", ", 1, max_used)
13571357+ end
13581358+ compiler.emit(parent, string.format("local function %s(%s)", name, arg_str), ast)
13591359+ compiler.emit(parent, f_chunk, ast)
13601360+ compiler.emit(parent, "end", ast)
13611361+ return utils.expr(name, "sym")
13621362+ end
13631363+ doc_special("hashfn", {"..."}, "Function literal shorthand; args are either $... OR $1, $2, etc.")
13641364+ local function define_arithmetic_special(name, zero_arity, unary_prefix, lua_name)
13651365+ do
13661366+ local padded_op = (" " .. (lua_name or name) .. " ")
13671367+ local function _0_(ast, scope, parent)
13681368+ local len = #ast
13691369+ if (len == 1) then
13701370+ compiler.assert((zero_arity ~= nil), "Expected more than 0 arguments", ast)
13711371+ return utils.expr(zero_arity, "literal")
13721372+ else
13731373+ local operands = {}
13741374+ for i = 2, len do
13751375+ local subexprs = nil
13761376+ local _1_
13771377+ if (i ~= len) then
13781378+ _1_ = 1
13791379+ else
13801380+ _1_ = nil
13811381+ end
13821382+ subexprs = compiler.compile1(ast[i], scope, parent, {nval = _1_})
13831383+ utils.map(subexprs, tostring, operands)
13841384+ end
13851385+ if (#operands == 1) then
13861386+ if unary_prefix then
13871387+ return ("(" .. unary_prefix .. padded_op .. operands[1] .. ")")
13881388+ else
13891389+ return operands[1]
13901390+ end
13911391+ else
13921392+ return ("(" .. table.concat(operands, padded_op) .. ")")
13931393+ end
13941394+ end
13951395+ end
13961396+ SPECIALS[name] = _0_
13971397+ end
13981398+ return doc_special(name, {"a", "b", "..."}, "Arithmetic operator; works the same as Lua but accepts more arguments.")
13991399+ end
14001400+ define_arithmetic_special("+", "0")
14011401+ define_arithmetic_special("..", "''")
14021402+ define_arithmetic_special("^")
14031403+ define_arithmetic_special("-", nil, "")
14041404+ define_arithmetic_special("*", "1")
14051405+ define_arithmetic_special("%")
14061406+ define_arithmetic_special("/", nil, "1")
14071407+ define_arithmetic_special("//", nil, "1")
14081408+ define_arithmetic_special("lshift", nil, "1", "<<")
14091409+ define_arithmetic_special("rshift", nil, "1", ">>")
14101410+ define_arithmetic_special("band", "0", "0", "&")
14111411+ define_arithmetic_special("bor", "0", "0", "|")
14121412+ define_arithmetic_special("bxor", "0", "0", "~")
14131413+ doc_special("lshift", {"x", "n"}, "Bitwise logical left shift of x by n bits; only works in Lua 5.3+.")
14141414+ doc_special("rshift", {"x", "n"}, "Bitwise logical right shift of x by n bits; only works in Lua 5.3+.")
14151415+ doc_special("band", {"x1", "x2"}, "Bitwise AND of arguments; only works in Lua 5.3+.")
14161416+ doc_special("bor", {"x1", "x2"}, "Bitwise OR of arguments; only works in Lua 5.3+.")
14171417+ doc_special("bxor", {"x1", "x2"}, "Bitwise XOR of arguments; only works in Lua 5.3+.")
14181418+ define_arithmetic_special("or", "false")
14191419+ define_arithmetic_special("and", "true")
14201420+ doc_special("and", {"a", "b", "..."}, "Boolean operator; works the same as Lua but accepts more arguments.")
14211421+ doc_special("or", {"a", "b", "..."}, "Boolean operator; works the same as Lua but accepts more arguments.")
14221422+ doc_special("..", {"a", "b", "..."}, "String concatenation operator; works the same as Lua but accepts more arguments.")
14231423+ local function native_comparator(op, _0_0, scope, parent)
14241424+ local _1_ = _0_0
14251425+ local _ = _1_[1]
14261426+ local lhs_ast = _1_[2]
14271427+ local rhs_ast = _1_[3]
14281428+ local _2_ = compiler.compile1(lhs_ast, scope, parent, {nval = 1})
14291429+ local lhs = _2_[1]
14301430+ local _3_ = compiler.compile1(rhs_ast, scope, parent, {nval = 1})
14311431+ local rhs = _3_[1]
14321432+ return string.format("(%s %s %s)", tostring(lhs), op, tostring(rhs))
14331433+ end
14341434+ local function double_eval_protected_comparator(op, chain_op, ast, scope, parent)
14351435+ local arglist = {}
14361436+ local comparisons = {}
14371437+ local vals = {}
14381438+ local chain = string.format(" %s ", (chain_op or "and"))
14391439+ for i = 2, #ast do
14401440+ table.insert(arglist, tostring(compiler.gensym(scope)))
14411441+ table.insert(vals, tostring(compiler.compile1(ast[i], scope, parent, {nval = 1})[1]))
14421442+ end
14431443+ for i = 1, (#arglist - 1) do
14441444+ table.insert(comparisons, string.format("(%s %s %s)", arglist[i], op, arglist[(i + 1)]))
14451445+ end
14461446+ return string.format("(function(%s) return %s end)(%s)", table.concat(arglist, ","), table.concat(comparisons, chain), table.concat(vals, ","))
14471447+ end
14481448+ local function define_comparator_special(name, lua_op, chain_op)
14491449+ do
14501450+ local op = (lua_op or name)
14511451+ local function opfn(ast, scope, parent)
14521452+ compiler.assert((2 < #ast), "expected at least two arguments", ast)
14531453+ if (3 == #ast) then
14541454+ return native_comparator(op, ast, scope, parent)
14551455+ else
14561456+ return double_eval_protected_comparator(op, chain_op, ast, scope, parent)
14571457+ end
14581458+ end
14591459+ SPECIALS[name] = opfn
14601460+ end
14611461+ return doc_special(name, {"a", "b", "..."}, "Comparison operator; works the same as Lua but accepts more arguments.")
14621462+ end
14631463+ define_comparator_special(">")
14641464+ define_comparator_special("<")
14651465+ define_comparator_special(">=")
14661466+ define_comparator_special("<=")
14671467+ define_comparator_special("=", "==")
14681468+ define_comparator_special("not=", "~=", "or")
14691469+ SPECIALS["~="] = SPECIALS["not="]
14701470+ local function define_unary_special(op, realop)
14711471+ local function opfn(ast, scope, parent)
14721472+ compiler.assert((#ast == 2), "expected one argument", ast)
14731473+ local tail = compiler.compile1(ast[2], scope, parent, {nval = 1})
14741474+ return ((realop or op) .. tostring(tail[1]))
14751475+ end
14761476+ SPECIALS[op] = opfn
14771477+ return nil
14781478+ end
14791479+ define_unary_special("not", "not ")
14801480+ doc_special("not", {"x"}, "Logical operator; works the same as Lua.")
14811481+ define_unary_special("bnot", "~")
14821482+ doc_special("bnot", {"x"}, "Bitwise negation; only works in Lua 5.3+.")
14831483+ define_unary_special("length", "#")
14841484+ doc_special("length", {"x"}, "Returns the length of a table or string.")
14851485+ SPECIALS["#"] = SPECIALS.length
14861486+ SPECIALS.quote = function(ast, scope, parent)
14871487+ compiler.assert((#ast == 2), "expected one argument")
14881488+ local runtime, this_scope = true, scope
14891489+ while this_scope do
14901490+ this_scope = this_scope.parent
14911491+ if (this_scope == compiler.scopes.compiler) then
14921492+ runtime = false
14931493+ end
14941494+ end
14951495+ return compiler["do-quote"](ast[2], scope, parent, runtime)
14961496+ end
14971497+ doc_special("quote", {"x"}, "Quasiquote the following form. Only works in macro/compiler scope.")
14981498+ local already_warned_3f = {}
14991499+ local compile_env_warning = ("WARNING: Attempting to %s %s in compile" .. " scope.\nIn future versions of Fennel this will not" .. " be allowed without the\n--no-compiler-sandbox flag" .. " or passing a :compilerEnv globals table in options.\n")
15001500+ local function compiler_env_warn(_, key)
15011501+ local v = _G[key]
15021502+ if (v and io and io.stderr and not already_warned_3f[key]) then
15031503+ already_warned_3f[key] = true
15041504+ do end (io.stderr):write(compile_env_warning:format("use global", key))
15051505+ end
15061506+ return v
15071507+ end
15081508+ local safe_compiler_env = setmetatable({assert = assert, bit = rawget(_G, "bit"), error = error, getmetatable = getmetatable, ipairs = ipairs, math = math, next = next, pairs = pairs, pcall = pcall, print = print, rawequal = rawequal, rawget = rawget, rawlen = rawget(_G, "rawlen"), rawset = rawset, select = select, setmetatable = setmetatable, string = string, table = table, tonumber = tonumber, tostring = tostring, type = type, xpcall = xpcall}, {__index = compiler_env_warn})
15091509+ local function make_compiler_env(ast, scope, parent)
15101510+ local function _1_()
15111511+ return compiler.scopes.macro
15121512+ end
15131513+ local function _2_(symbol)
15141514+ compiler.assert(compiler.scopes.macro, "must call from macro", ast)
15151515+ return compiler.scopes.macro.manglings[tostring(symbol)]
15161516+ end
15171517+ local function _3_(base)
15181518+ return utils.sym(compiler.gensym((compiler.scopes.macro or scope), base))
15191519+ end
15201520+ local function _4_(form)
15211521+ compiler.assert(compiler.scopes.macro, "must call from macro", ast)
15221522+ return compiler.macroexpand(form, compiler.scopes.macro)
15231523+ end
15241524+ local _6_
15251525+ do
15261526+ local _5_0 = utils.root.options
15271527+ if ((type(_5_0) == "table") and (nil ~= _5_0.compilerEnv)) then
15281528+ local compilerEnv = _5_0.compilerEnv
15291529+ _6_ = compilerEnv
15301530+ elseif ((type(_5_0) == "table") and (nil ~= _5_0["compiler-env"])) then
15311531+ local compiler_env = _5_0["compiler-env"]
15321532+ _6_ = compiler_env
15331533+ else
15341534+ local _ = _5_0
15351535+ _6_ = safe_compiler_env
15361536+ end
15371537+ end
15381538+ return setmetatable({["assert-compile"] = compiler.assert, ["get-scope"] = _1_, ["in-scope?"] = _2_, ["list?"] = utils["list?"], ["multi-sym?"] = utils["multi-sym?"], ["sequence?"] = utils["sequence?"], ["sym?"] = utils["sym?"], ["table?"] = utils["table?"], ["varg?"] = utils["varg?"], _AST = ast, _CHUNK = parent, _IS_COMPILER = true, _SCOPE = scope, _SPECIALS = compiler.scopes.global.specials, _VARARG = utils.varg(), gensym = _3_, list = utils.list, macroexpand = _4_, sequence = utils.sequence, sym = utils.sym, unpack = unpack, view = view}, {__index = _6_})
15391539+ end
15401540+ local cfg = string.gmatch(package.config, "([^\n]+)")
15411541+ local dirsep, pathsep, pathmark = (cfg() or "/"), (cfg() or ";"), (cfg() or "?")
15421542+ local pkg_config = {dirsep = dirsep, pathmark = pathmark, pathsep = pathsep}
15431543+ local function escapepat(str)
15441544+ return string.gsub(str, "[^%w]", "%%%1")
15451545+ end
15461546+ local function search_module(modulename, pathstring)
15471547+ local pathsepesc = escapepat(pkg_config.pathsep)
15481548+ local pattern = ("([^%s]*)%s"):format(pathsepesc, pathsepesc)
15491549+ local no_dot_module = modulename:gsub("%.", pkg_config.dirsep)
15501550+ local fullpath = ((pathstring or utils["fennel-module"].path) .. pkg_config.pathsep)
15511551+ local function try_path(path)
15521552+ local filename = path:gsub(escapepat(pkg_config.pathmark), no_dot_module)
15531553+ local filename2 = path:gsub(escapepat(pkg_config.pathmark), modulename)
15541554+ local _1_0 = (io.open(filename) or io.open(filename2))
15551555+ if (nil ~= _1_0) then
15561556+ local file = _1_0
15571557+ file:close()
15581558+ return filename
15591559+ end
15601560+ end
15611561+ local function find_in_path(start)
15621562+ local _1_0 = fullpath:match(pattern, start)
15631563+ if (nil ~= _1_0) then
15641564+ local path = _1_0
15651565+ return (try_path(path) or find_in_path((start + #path + 1)))
15661566+ end
15671567+ end
15681568+ return find_in_path(1)
15691569+ end
15701570+ local function make_searcher(options)
15711571+ local function _1_(module_name)
15721572+ local opts = utils.copy(utils.root.options)
15731573+ for k, v in pairs((options or {})) do
15741574+ opts[k] = v
15751575+ end
15761576+ opts["module-name"] = module_name
15771577+ local _2_0 = search_module(module_name)
15781578+ if (nil ~= _2_0) then
15791579+ local filename = _2_0
15801580+ local function _3_(...)
15811581+ return utils["fennel-module"].dofile(filename, opts, ...)
15821582+ end
15831583+ return _3_, filename
15841584+ end
15851585+ end
15861586+ return _1_
15871587+ end
15881588+ local function macro_globals(env, globals)
15891589+ local allowed = current_global_names(env)
15901590+ for _, k in pairs((globals or {})) do
15911591+ table.insert(allowed, k)
15921592+ end
15931593+ return allowed
15941594+ end
15951595+ local function compiler_env_domodule(modname, env, _3fast)
15961596+ local filename = compiler.assert(search_module(modname), (modname .. " module not found."), _3fast)
15971597+ local globals = macro_globals(env, current_global_names())
15981598+ return utils["fennel-module"].dofile(filename, {allowedGlobals = globals, env = env, scope = compiler.scopes.compiler, useMetadata = utils.root.options.useMetadata}, modname, filename)
15991599+ end
16001600+ local macro_loaded = {}
16011601+ local function metadata_only_fennel(modname)
16021602+ if ((modname == "fennel.macros") or (package and package.loaded and ("table" == type(package.loaded[modname])) and (package.loaded[modname].metadata == compiler.metadata))) then
16031603+ return {metadata = compiler.metadata}
16041604+ end
16051605+ end
16061606+ safe_compiler_env.require = function(modname)
16071607+ local function _1_()
16081608+ local mod = compiler_env_domodule(modname, safe_compiler_env)
16091609+ macro_loaded[modname] = mod
16101610+ return mod
16111611+ end
16121612+ return (macro_loaded[modname] or metadata_only_fennel(modname) or _1_())
16131613+ end
16141614+ local function add_macros(macros_2a, ast, scope)
16151615+ compiler.assert(utils["table?"](macros_2a), "expected macros to be table", ast)
16161616+ for k, v in pairs(macros_2a) do
16171617+ compiler.assert((type(v) == "function"), "expected each macro to be function", ast)
16181618+ scope.macros[k] = v
16191619+ end
16201620+ return nil
16211621+ end
16221622+ SPECIALS["require-macros"] = function(ast, scope, parent, real_ast)
16231623+ compiler.assert((#ast == 2), "Expected one module name argument", (real_ast or ast))
16241624+ local filename = (ast[2].filename or ast.filename)
16251625+ local modname_code = compiler.compile(ast[2])
16261626+ local modname = load_code(modname_code, nil, filename)(utils.root.options["module-name"], filename)
16271627+ compiler.assert((type(modname) == "string"), "module name must compile to string", (real_ast or ast))
16281628+ if not macro_loaded[modname] then
16291629+ local env = make_compiler_env(ast, scope, parent)
16301630+ macro_loaded[modname] = compiler_env_domodule(modname, env, ast)
16311631+ end
16321632+ return add_macros(macro_loaded[modname], ast, scope, parent)
16331633+ end
16341634+ 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.")
16351635+ local function emit_included_fennel(src, path, opts, sub_chunk)
16361636+ local subscope = compiler["make-scope"](utils.root.scope.parent)
16371637+ local forms = {}
16381638+ if utils.root.options.requireAsInclude then
16391639+ subscope.specials.require = compiler["require-include"]
16401640+ end
16411641+ for _, val in parser.parser(parser["string-stream"](src), path) do
16421642+ table.insert(forms, val)
16431643+ end
16441644+ for i = 1, #forms do
16451645+ local subopts = nil
16461646+ if (i == #forms) then
16471647+ subopts = {tail = true}
16481648+ else
16491649+ subopts = {nval = 0}
16501650+ end
16511651+ utils["propagate-options"](opts, subopts)
16521652+ compiler.compile1(forms[i], subscope, sub_chunk, subopts)
16531653+ end
16541654+ return nil
16551655+ end
16561656+ local function include_path(ast, opts, path, mod, fennel_3f)
16571657+ utils.root.scope.includes[mod] = "fnl/loading"
16581658+ local src = nil
16591659+ do
16601660+ local f = assert(io.open(path))
16611661+ local function close_handlers_0_(ok_0_, ...)
16621662+ f:close()
16631663+ if ok_0_ then
16641664+ return ...
16651665+ else
16661666+ return error(..., 0)
16671667+ end
16681668+ end
16691669+ local function _1_()
16701670+ return f:read("*all"):gsub("[\13\n]*$", "")
16711671+ end
16721672+ src = close_handlers_0_(xpcall(_1_, (package.loaded.fennel or debug).traceback))
16731673+ end
16741674+ local ret = utils.expr(("require(\"" .. mod .. "\")"), "statement")
16751675+ local target = ("package.preload[%q]"):format(mod)
16761676+ local preload_str = (target .. " = " .. target .. " or function(...)")
16771677+ local temp_chunk, sub_chunk = {}, {}
16781678+ compiler.emit(temp_chunk, preload_str, ast)
16791679+ compiler.emit(temp_chunk, sub_chunk)
16801680+ compiler.emit(temp_chunk, "end", ast)
16811681+ for i, v in ipairs(temp_chunk) do
16821682+ table.insert(utils.root.chunk, i, v)
16831683+ end
16841684+ if fennel_3f then
16851685+ emit_included_fennel(src, path, opts, sub_chunk)
16861686+ else
16871687+ compiler.emit(sub_chunk, src, ast)
16881688+ end
16891689+ utils.root.scope.includes[mod] = ret
16901690+ return ret
16911691+ end
16921692+ local function include_circular_fallback(mod, modexpr, fallback, ast)
16931693+ if (utils.root.scope.includes[mod] == "fnl/loading") then
16941694+ compiler.assert(fallback, "circular include detected", ast)
16951695+ return fallback(modexpr)
16961696+ end
16971697+ end
16981698+ SPECIALS.include = function(ast, scope, parent, opts)
16991699+ compiler.assert((#ast == 2), "expected one argument", ast)
17001700+ local modexpr = compiler.compile1(ast[2], scope, parent, {nval = 1})[1]
17011701+ if ((modexpr.type ~= "literal") or ((modexpr[1]):byte() ~= 34)) then
17021702+ if opts.fallback then
17031703+ return opts.fallback(modexpr)
17041704+ else
17051705+ return compiler.assert(false, "module name must be string literal", ast)
17061706+ end
17071707+ else
17081708+ local mod = load_code(("return " .. modexpr[1]))()
17091709+ local function _2_()
17101710+ local _1_0 = search_module(mod)
17111711+ if (nil ~= _1_0) then
17121712+ local fennel_path = _1_0
17131713+ return include_path(ast, opts, fennel_path, mod, true)
17141714+ else
17151715+ local _ = _1_0
17161716+ local lua_path = search_module(mod, package.path)
17171717+ if lua_path then
17181718+ return include_path(ast, opts, lua_path, mod, false)
17191719+ elseif opts.fallback then
17201720+ return opts.fallback(modexpr)
17211721+ else
17221722+ return compiler.assert(false, ("module not found " .. mod), ast)
17231723+ end
17241724+ end
17251725+ end
17261726+ return (include_circular_fallback(mod, modexpr, opts.fallback, ast) or utils.root.scope.includes[mod] or _2_())
17271727+ end
17281728+ end
17291729+ 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.")
17301730+ local function eval_compiler_2a(ast, scope, parent)
17311731+ local env = make_compiler_env(ast, scope, parent)
17321732+ local opts = utils.copy(utils.root.options)
17331733+ opts.scope = compiler["make-scope"](compiler.scopes.compiler)
17341734+ opts.allowedGlobals = macro_globals(env, current_global_names())
17351735+ return load_code(compiler.compile(ast, opts), wrap_env(env))(opts["module-name"], ast.filename)
17361736+ end
17371737+ SPECIALS.macros = function(ast, scope, parent)
17381738+ compiler.assert((#ast == 2), "Expected one table argument", ast)
17391739+ return add_macros(eval_compiler_2a(ast[2], scope, parent), ast, scope, parent)
17401740+ end
17411741+ 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.")
17421742+ SPECIALS["eval-compiler"] = function(ast, scope, parent)
17431743+ local old_first = ast[1]
17441744+ ast[1] = utils.sym("do")
17451745+ local val = eval_compiler_2a(ast, scope, parent)
17461746+ ast[1] = old_first
17471747+ return val
17481748+ end
17491749+ doc_special("eval-compiler", {"..."}, "Evaluate the body at compile-time. Use the macro system instead if possible.")
17501750+ return {["current-global-names"] = current_global_names, ["load-code"] = load_code, ["macro-loaded"] = macro_loaded, ["make-compiler-env"] = make_compiler_env, ["make-searcher"] = make_searcher, ["search-module"] = search_module, ["wrap-env"] = wrap_env, doc = doc_2a}
17511751+end
17521752+package.preload["fennel.compiler"] = package.preload["fennel.compiler"] or function(...)
17531753+ local utils = require("fennel.utils")
17541754+ local parser = require("fennel.parser")
17551755+ local friend = require("fennel.friend")
17561756+ local unpack = (table.unpack or _G.unpack)
17571757+ local scopes = {}
17581758+ local function make_scope(parent)
17591759+ local parent0 = (parent or scopes.global)
17601760+ local _0_
17611761+ if parent0 then
17621762+ _0_ = ((parent0.depth or 0) + 1)
17631763+ else
17641764+ _0_ = 0
17651765+ end
17661766+ return {autogensyms = {}, depth = _0_, hashfn = (parent0 and parent0.hashfn), includes = setmetatable({}, {__index = (parent0 and parent0.includes)}), macros = setmetatable({}, {__index = (parent0 and parent0.macros)}), manglings = setmetatable({}, {__index = (parent0 and parent0.manglings)}), parent = parent0, refedglobals = setmetatable({}, {__index = (parent0 and parent0.refedglobals)}), specials = setmetatable({}, {__index = (parent0 and parent0.specials)}), symmeta = setmetatable({}, {__index = (parent0 and parent0.symmeta)}), unmanglings = setmetatable({}, {__index = (parent0 and parent0.unmanglings)}), vararg = (parent0 and parent0.vararg)}
17671767+ end
17681768+ local function assert_msg(ast, msg)
17691769+ local ast_tbl = nil
17701770+ if ("table" == type(ast)) then
17711771+ ast_tbl = ast
17721772+ else
17731773+ ast_tbl = {}
17741774+ end
17751775+ local m = getmetatable(ast)
17761776+ local filename = ((m and m.filename) or ast_tbl.filename or "unknown")
17771777+ local line = ((m and m.line) or ast_tbl.line or "?")
17781778+ local target = nil
17791779+ local function _1_()
17801780+ if utils["sym?"](ast_tbl[1]) then
17811781+ return utils.deref(ast_tbl[1])
17821782+ else
17831783+ return (ast_tbl[1] or "()")
17841784+ end
17851785+ end
17861786+ target = tostring(_1_())
17871787+ return string.format("Compile error in '%s' %s:%s: %s", target, filename, line, msg)
17881788+ end
17891789+ local function assert_compile(condition, msg, ast)
17901790+ if not condition then
17911791+ local _0_ = (utils.root.options or {})
17921792+ local source = _0_["source"]
17931793+ local unfriendly = _0_["unfriendly"]
17941794+ utils.root.reset()
17951795+ if unfriendly then
17961796+ error(assert_msg(ast, msg), 0)
17971797+ else
17981798+ friend["assert-compile"](condition, msg, ast, source)
17991799+ end
18001800+ end
18011801+ return condition
18021802+ end
18031803+ scopes.global = make_scope()
18041804+ scopes.global.vararg = true
18051805+ scopes.compiler = make_scope(scopes.global)
18061806+ scopes.macro = scopes.global
18071807+ local serialize_subst = {["\11"] = "\\v", ["\12"] = "\\f", ["\7"] = "\\a", ["\8"] = "\\b", ["\9"] = "\\t", ["\n"] = "n"}
18081808+ local function serialize_string(str)
18091809+ local function _0_(_241)
18101810+ return ("\\" .. _241:byte())
18111811+ end
18121812+ return string.gsub(string.gsub(string.format("%q", str), ".", serialize_subst), "[\128-\255]", _0_)
18131813+ end
18141814+ local function global_mangling(str)
18151815+ if utils["valid-lua-identifier?"](str) then
18161816+ return str
18171817+ else
18181818+ local function _0_(_241)
18191819+ return string.format("_%02x", _241:byte())
18201820+ end
18211821+ return ("__fnl_global__" .. str:gsub("[^%w]", _0_))
18221822+ end
18231823+ end
18241824+ local function global_unmangling(identifier)
18251825+ local _0_0 = string.match(identifier, "^__fnl_global__(.*)$")
18261826+ if (nil ~= _0_0) then
18271827+ local rest = _0_0
18281828+ local _1_0 = nil
18291829+ local function _2_(_241)
18301830+ return string.char(tonumber(_241:sub(2), 16))
18311831+ end
18321832+ _1_0 = string.gsub(rest, "_[%da-f][%da-f]", _2_)
18331833+ return _1_0
18341834+ else
18351835+ local _ = _0_0
18361836+ return identifier
18371837+ end
18381838+ end
18391839+ local allowed_globals = nil
18401840+ local function global_allowed(name)
18411841+ return (not allowed_globals or utils["member?"](name, allowed_globals))
18421842+ end
18431843+ local function unique_mangling(original, mangling, scope, append)
18441844+ if scope.unmanglings[mangling] then
18451845+ return unique_mangling(original, (original .. append), scope, (append + 1))
18461846+ else
18471847+ return mangling
18481848+ end
18491849+ end
18501850+ local function local_mangling(str, scope, ast, temp_manglings)
18511851+ assert_compile(not utils["multi-sym?"](str), ("unexpected multi symbol " .. str), ast)
18521852+ local raw = nil
18531853+ if (utils["lua-keywords"][str] or str:match("^%d")) then
18541854+ raw = ("_" .. str)
18551855+ else
18561856+ raw = str
18571857+ end
18581858+ local mangling = nil
18591859+ local function _1_(_241)
18601860+ return string.format("_%02x", _241:byte())
18611861+ end
18621862+ mangling = string.gsub(string.gsub(raw, "-", "_"), "[^%w_]", _1_)
18631863+ local unique = unique_mangling(mangling, mangling, scope, 0)
18641864+ scope.unmanglings[unique] = str
18651865+ do
18661866+ local manglings = (temp_manglings or scope.manglings)
18671867+ manglings[str] = unique
18681868+ end
18691869+ return unique
18701870+ end
18711871+ local function apply_manglings(scope, new_manglings, ast)
18721872+ for raw, mangled in pairs(new_manglings) do
18731873+ assert_compile(not scope.refedglobals[mangled], ("use of global " .. raw .. " is aliased by a local"), ast)
18741874+ scope.manglings[raw] = mangled
18751875+ end
18761876+ return nil
18771877+ end
18781878+ local function combine_parts(parts, scope)
18791879+ local ret = (scope.manglings[parts[1]] or global_mangling(parts[1]))
18801880+ for i = 2, #parts do
18811881+ if utils["valid-lua-identifier?"](parts[i]) then
18821882+ if (parts["multi-sym-method-call"] and (i == #parts)) then
18831883+ ret = (ret .. ":" .. parts[i])
18841884+ else
18851885+ ret = (ret .. "." .. parts[i])
18861886+ end
18871887+ else
18881888+ ret = (ret .. "[" .. serialize_string(parts[i]) .. "]")
18891889+ end
18901890+ end
18911891+ return ret
18921892+ end
18931893+ local function gensym(scope, base)
18941894+ local append, mangling = 0, ((base or "") .. "_0_")
18951895+ while scope.unmanglings[mangling] do
18961896+ mangling = ((base or "") .. "_" .. append .. "_")
18971897+ append = (append + 1)
18981898+ end
18991899+ scope.unmanglings[mangling] = (base or true)
19001900+ return mangling
19011901+ end
19021902+ local function autogensym(base, scope)
19031903+ local _0_0 = utils["multi-sym?"](base)
19041904+ if (nil ~= _0_0) then
19051905+ local parts = _0_0
19061906+ parts[1] = autogensym(parts[1], scope)
19071907+ return table.concat(parts, ((parts["multi-sym-method-call"] and ":") or "."))
19081908+ else
19091909+ local _ = _0_0
19101910+ local function _1_()
19111911+ local mangling = gensym(scope, base:sub(1, ( - 2)))
19121912+ scope.autogensyms[base] = mangling
19131913+ return mangling
19141914+ end
19151915+ return (scope.autogensyms[base] or _1_())
19161916+ end
19171917+ end
19181918+ local already_warned = {}
19191919+ local function check_binding_valid(symbol, scope, ast)
19201920+ local name = utils.deref(symbol)
19211921+ if (io and io.stderr and name:find("&") and not already_warned[symbol]) then
19221922+ already_warned[symbol] = true
19231923+ do end (io.stderr):write(("-- Warning: & will not be allowed in identifier names in " .. "future versions: " .. symbol.filename .. ":" .. symbol.line .. "\n"))
19241924+ end
19251925+ assert_compile(not (scope.specials[name] or scope.macros[name]), ("local %s was overshadowed by a special form or macro"):format(name), ast)
19261926+ return assert_compile(not utils["quoted?"](symbol), string.format("macro tried to bind %s without gensym", name), symbol)
19271927+ end
19281928+ local function declare_local(symbol, meta, scope, ast, temp_manglings)
19291929+ check_binding_valid(symbol, scope, ast)
19301930+ local name = utils.deref(symbol)
19311931+ assert_compile(not utils["multi-sym?"](name), ("unexpected multi symbol " .. name), ast)
19321932+ scope.symmeta[name] = meta
19331933+ return local_mangling(name, scope, ast, temp_manglings)
19341934+ end
19351935+ local function hashfn_arg_name(name, multi_sym_parts, scope)
19361936+ if not scope.hashfn then
19371937+ return nil
19381938+ elseif (name == "$") then
19391939+ return "$1"
19401940+ elseif multi_sym_parts then
19411941+ if (multi_sym_parts and (multi_sym_parts[1] == "$")) then
19421942+ multi_sym_parts[1] = "$1"
19431943+ end
19441944+ return table.concat(multi_sym_parts, ".")
19451945+ end
19461946+ end
19471947+ local function symbol_to_expression(symbol, scope, reference_3f)
19481948+ utils.hook("symbol-to-expression", symbol, scope, reference_3f)
19491949+ local name = symbol[1]
19501950+ local multi_sym_parts = utils["multi-sym?"](name)
19511951+ local name0 = (hashfn_arg_name(name, multi_sym_parts, scope) or name)
19521952+ local parts = (multi_sym_parts or {name0})
19531953+ local etype = (((#parts > 1) and "expression") or "sym")
19541954+ local local_3f = scope.manglings[parts[1]]
19551955+ if (local_3f and scope.symmeta[parts[1]]) then
19561956+ scope.symmeta[parts[1]]["used"] = true
19571957+ end
19581958+ assert_compile((not reference_3f or local_3f or global_allowed(parts[1])), ("unknown global in strict mode: " .. parts[1]), symbol)
19591959+ if (allowed_globals and not local_3f) then
19601960+ utils.root.scope.refedglobals[parts[1]] = true
19611961+ end
19621962+ return utils.expr(combine_parts(parts, scope), etype)
19631963+ end
19641964+ local function emit(chunk, out, ast)
19651965+ if (type(out) == "table") then
19661966+ return table.insert(chunk, out)
19671967+ else
19681968+ return table.insert(chunk, {ast = ast, leaf = out})
19691969+ end
19701970+ end
19711971+ local function peephole(chunk)
19721972+ if chunk.leaf then
19731973+ return chunk
19741974+ elseif ((#chunk >= 3) and (chunk[(#chunk - 2)].leaf == "do") and not chunk[(#chunk - 1)].leaf and (chunk[#chunk].leaf == "end")) then
19751975+ local kid = peephole(chunk[(#chunk - 1)])
19761976+ local new_chunk = {ast = chunk.ast}
19771977+ for i = 1, (#chunk - 3) do
19781978+ table.insert(new_chunk, peephole(chunk[i]))
19791979+ end
19801980+ for i = 1, #kid do
19811981+ table.insert(new_chunk, kid[i])
19821982+ end
19831983+ return new_chunk
19841984+ else
19851985+ return utils.map(chunk, peephole)
19861986+ end
19871987+ end
19881988+ local function flatten_chunk_correlated(main_chunk)
19891989+ local function flatten(chunk, out, last_line, file)
19901990+ local last_line0 = last_line
19911991+ if chunk.leaf then
19921992+ out[last_line0] = ((out[last_line0] or "") .. " " .. chunk.leaf)
19931993+ else
19941994+ for _, subchunk in ipairs(chunk) do
19951995+ if (subchunk.leaf or (#subchunk > 0)) then
19961996+ if (subchunk.ast and (file == subchunk.ast.file)) then
19971997+ last_line0 = math.max(last_line0, (subchunk.ast.line or 0))
19981998+ end
19991999+ last_line0 = flatten(subchunk, out, last_line0, file)
20002000+ end
20012001+ end
20022002+ end
20032003+ return last_line0
20042004+ end
20052005+ local out = {}
20062006+ local last = flatten(main_chunk, out, 1, main_chunk.file)
20072007+ for i = 1, last do
20082008+ if (out[i] == nil) then
20092009+ out[i] = ""
20102010+ end
20112011+ end
20122012+ return table.concat(out, "\n")
20132013+ end
20142014+ local function flatten_chunk(sm, chunk, tab, depth)
20152015+ if chunk.leaf then
20162016+ local code = chunk.leaf
20172017+ local info = chunk.ast
20182018+ if sm then
20192019+ table.insert(sm, ((info and info.line) or ( - 1)))
20202020+ end
20212021+ return code
20222022+ else
20232023+ local tab0 = nil
20242024+ do
20252025+ local _0_0 = tab
20262026+ if (_0_0 == true) then
20272027+ tab0 = " "
20282028+ elseif (_0_0 == false) then
20292029+ tab0 = ""
20302030+ elseif (_0_0 == tab) then
20312031+ tab0 = tab
20322032+ elseif (_0_0 == nil) then
20332033+ tab0 = ""
20342034+ else
20352035+ tab0 = nil
20362036+ end
20372037+ end
20382038+ local function parter(c)
20392039+ if (c.leaf or (#c > 0)) then
20402040+ local sub = flatten_chunk(sm, c, tab0, (depth + 1))
20412041+ if (depth > 0) then
20422042+ return (tab0 .. sub:gsub("\n", ("\n" .. tab0)))
20432043+ else
20442044+ return sub
20452045+ end
20462046+ end
20472047+ end
20482048+ return table.concat(utils.map(chunk, parter), "\n")
20492049+ end
20502050+ end
20512051+ local fennel_sourcemap = {}
20522052+ local function make_short_src(source)
20532053+ local source0 = source:gsub("\n", " ")
20542054+ if (#source0 <= 49) then
20552055+ return ("[fennel \"" .. source0 .. "\"]")
20562056+ else
20572057+ return ("[fennel \"" .. source0:sub(1, 46) .. "...\"]")
20582058+ end
20592059+ end
20602060+ local function flatten(chunk, options)
20612061+ local chunk0 = peephole(chunk)
20622062+ if options.correlate then
20632063+ return flatten_chunk_correlated(chunk0), {}
20642064+ else
20652065+ local sm = {}
20662066+ local ret = flatten_chunk(sm, chunk0, options.indent, 0)
20672067+ if sm then
20682068+ sm.short_src = make_short_src((options.filename or options.source or ret))
20692069+ if options.filename then
20702070+ sm.key = ("@" .. options.filename)
20712071+ else
20722072+ sm.key = ret
20732073+ end
20742074+ fennel_sourcemap[sm.key] = sm
20752075+ end
20762076+ return ret, sm
20772077+ end
20782078+ end
20792079+ local function make_metadata()
20802080+ local function _0_(self, tgt, key)
20812081+ if self[tgt] then
20822082+ return self[tgt][key]
20832083+ end
20842084+ end
20852085+ local function _1_(self, tgt, key, value)
20862086+ self[tgt] = (self[tgt] or {})
20872087+ self[tgt][key] = value
20882088+ return tgt
20892089+ end
20902090+ local function _2_(self, tgt, ...)
20912091+ local kv_len = select("#", ...)
20922092+ local kvs = {...}
20932093+ if ((kv_len % 2) ~= 0) then
20942094+ error("metadata:setall() expected even number of k/v pairs")
20952095+ end
20962096+ self[tgt] = (self[tgt] or {})
20972097+ for i = 1, kv_len, 2 do
20982098+ self[tgt][kvs[i]] = kvs[(i + 1)]
20992099+ end
21002100+ return tgt
21012101+ end
21022102+ return setmetatable({}, {__index = {get = _0_, set = _1_, setall = _2_}, __mode = "k"})
21032103+ end
21042104+ local function exprs1(exprs)
21052105+ return table.concat(utils.map(exprs, 1), ", ")
21062106+ end
21072107+ local function keep_side_effects(exprs, chunk, start, ast)
21082108+ local start0 = (start or 1)
21092109+ for j = start0, #exprs do
21102110+ local se = exprs[j]
21112111+ if ((se.type == "expression") and (se[1] ~= "nil")) then
21122112+ emit(chunk, string.format("do local _ = %s end", tostring(se)), ast)
21132113+ elseif (se.type == "statement") then
21142114+ local code = tostring(se)
21152115+ emit(chunk, (((code:byte() == 40) and ("do end " .. code)) or code), ast)
21162116+ end
21172117+ end
21182118+ return nil
21192119+ end
21202120+ local function handle_compile_opts(exprs, parent, opts, ast)
21212121+ if opts.nval then
21222122+ local n = opts.nval
21232123+ local len = #exprs
21242124+ if (n ~= len) then
21252125+ if (len > n) then
21262126+ keep_side_effects(exprs, parent, (n + 1), ast)
21272127+ for i = (n + 1), len do
21282128+ exprs[i] = nil
21292129+ end
21302130+ else
21312131+ for i = (#exprs + 1), n do
21322132+ exprs[i] = utils.expr("nil", "literal")
21332133+ end
21342134+ end
21352135+ end
21362136+ end
21372137+ if opts.tail then
21382138+ emit(parent, string.format("return %s", exprs1(exprs)), ast)
21392139+ end
21402140+ if opts.target then
21412141+ local result = exprs1(exprs)
21422142+ local function _2_()
21432143+ if (result == "") then
21442144+ return "nil"
21452145+ else
21462146+ return result
21472147+ end
21482148+ end
21492149+ emit(parent, string.format("%s = %s", opts.target, _2_()), ast)
21502150+ end
21512151+ if (opts.tail or opts.target) then
21522152+ return {returned = true}
21532153+ else
21542154+ local _3_0 = exprs
21552155+ _3_0["returned"] = true
21562156+ return _3_0
21572157+ end
21582158+ end
21592159+ local function find_macro(ast, scope, multi_sym_parts)
21602160+ local function find_in_table(t, i)
21612161+ if (i <= #multi_sym_parts) then
21622162+ return find_in_table((utils["table?"](t) and t[multi_sym_parts[i]]), (i + 1))
21632163+ else
21642164+ return t
21652165+ end
21662166+ end
21672167+ local macro_2a = (utils["sym?"](ast[1]) and scope.macros[utils.deref(ast[1])])
21682168+ if (not macro_2a and multi_sym_parts) then
21692169+ local nested_macro = find_in_table(scope.macros, 1)
21702170+ assert_compile((not scope.macros[multi_sym_parts[1]] or (type(nested_macro) == "function")), "macro not found in imported macro module", ast)
21712171+ return nested_macro
21722172+ else
21732173+ return macro_2a
21742174+ end
21752175+ end
21762176+ local function macroexpand_2a(ast, scope, once)
21772177+ if not utils["list?"](ast) then
21782178+ return ast
21792179+ else
21802180+ local macro_2a = find_macro(ast, scope, utils["multi-sym?"](ast[1]))
21812181+ if not macro_2a then
21822182+ return ast
21832183+ else
21842184+ local old_scope = scopes.macro
21852185+ local _ = nil
21862186+ scopes.macro = scope
21872187+ _ = nil
21882188+ local ok, transformed = pcall(macro_2a, unpack(ast, 2))
21892189+ scopes.macro = old_scope
21902190+ assert_compile(ok, transformed, ast)
21912191+ if (once or not transformed) then
21922192+ return transformed
21932193+ else
21942194+ return macroexpand_2a(transformed, scope)
21952195+ end
21962196+ end
21972197+ end
21982198+ end
21992199+ local function compile_special(ast, scope, parent, opts, special)
22002200+ local exprs = (special(ast, scope, parent, opts) or utils.expr("nil", "literal"))
22012201+ local exprs0 = nil
22022202+ if (type(exprs) == "string") then
22032203+ exprs0 = utils.expr(exprs, "expression")
22042204+ else
22052205+ exprs0 = exprs
22062206+ end
22072207+ local exprs2 = nil
22082208+ if utils["expr?"](exprs0) then
22092209+ exprs2 = {exprs0}
22102210+ else
22112211+ exprs2 = exprs0
22122212+ end
22132213+ if not exprs2.returned then
22142214+ return handle_compile_opts(exprs2, parent, opts, ast)
22152215+ elseif (opts.tail or opts.target) then
22162216+ return {returned = true}
22172217+ else
22182218+ return exprs2
22192219+ end
22202220+ end
22212221+ local function compile_function_call(ast, scope, parent, opts, compile1, len)
22222222+ local fargs = {}
22232223+ local fcallee = compile1(ast[1], scope, parent, {nval = 1})[1]
22242224+ assert_compile((fcallee.type ~= "literal"), ("cannot call literal value " .. tostring(ast[1])), ast)
22252225+ for i = 2, len do
22262226+ local subexprs = nil
22272227+ local _0_
22282228+ if (i ~= len) then
22292229+ _0_ = 1
22302230+ else
22312231+ _0_ = nil
22322232+ end
22332233+ subexprs = compile1(ast[i], scope, parent, {nval = _0_})
22342234+ table.insert(fargs, (subexprs[1] or utils.expr("nil", "literal")))
22352235+ if (i == len) then
22362236+ for j = 2, #subexprs do
22372237+ table.insert(fargs, subexprs[j])
22382238+ end
22392239+ else
22402240+ keep_side_effects(subexprs, parent, 2, ast[i])
22412241+ end
22422242+ end
22432243+ local call = string.format("%s(%s)", tostring(fcallee), exprs1(fargs))
22442244+ return handle_compile_opts({utils.expr(call, "statement")}, parent, opts, ast)
22452245+ end
22462246+ local function compile_call(ast, scope, parent, opts, compile1)
22472247+ utils.hook("call", ast, scope)
22482248+ local len = #ast
22492249+ local first = ast[1]
22502250+ local multi_sym_parts = utils["multi-sym?"](first)
22512251+ local special = (utils["sym?"](first) and scope.specials[utils.deref(first)])
22522252+ assert_compile((len > 0), "expected a function, macro, or special to call", ast)
22532253+ if special then
22542254+ return compile_special(ast, scope, parent, opts, special)
22552255+ elseif (multi_sym_parts and multi_sym_parts["multi-sym-method-call"]) then
22562256+ local table_with_method = table.concat({unpack(multi_sym_parts, 1, (#multi_sym_parts - 1))}, ".")
22572257+ local method_to_call = multi_sym_parts[#multi_sym_parts]
22582258+ local new_ast = utils.list(utils.sym(":", scope), utils.sym(table_with_method, scope), method_to_call, select(2, unpack(ast)))
22592259+ return compile1(new_ast, scope, parent, opts)
22602260+ else
22612261+ return compile_function_call(ast, scope, parent, opts, compile1, len)
22622262+ end
22632263+ end
22642264+ local function compile_varg(ast, scope, parent, opts)
22652265+ assert_compile(scope.vararg, "unexpected vararg", ast)
22662266+ return handle_compile_opts({utils.expr("...", "varg")}, parent, opts, ast)
22672267+ end
22682268+ local function compile_sym(ast, scope, parent, opts)
22692269+ local multi_sym_parts = utils["multi-sym?"](ast)
22702270+ assert_compile(not (multi_sym_parts and multi_sym_parts["multi-sym-method-call"]), "multisym method calls may only be in call position", ast)
22712271+ local e = nil
22722272+ if (ast[1] == "nil") then
22732273+ e = utils.expr("nil", "literal")
22742274+ else
22752275+ e = symbol_to_expression(ast, scope, true)
22762276+ end
22772277+ return handle_compile_opts({e}, parent, opts, ast)
22782278+ end
22792279+ local function serialize_number(n)
22802280+ local _0_0, _1_0, _2_0 = math.modf(n)
22812281+ if ((nil ~= _0_0) and (_1_0 == 0)) then
22822282+ local int = _0_0
22832283+ return tostring(int)
22842284+ else
22852285+ local _3_
22862286+ do
22872287+ local frac = _1_0
22882288+ _3_ = (((_0_0 == 0) and (nil ~= _1_0)) and (frac < 0))
22892289+ end
22902290+ if _3_ then
22912291+ local frac = _1_0
22922292+ return ("-0." .. tostring(frac):gsub("^-?0.", ""))
22932293+ elseif ((nil ~= _0_0) and (nil ~= _1_0)) then
22942294+ local int = _0_0
22952295+ local frac = _1_0
22962296+ return (int .. "." .. tostring(frac):gsub("^-?0.", ""))
22972297+ end
22982298+ end
22992299+ end
23002300+ local function compile_scalar(ast, _scope, parent, opts)
23012301+ local serialize = nil
23022302+ do
23032303+ local _0_0 = type(ast)
23042304+ if (_0_0 == "nil") then
23052305+ serialize = tostring
23062306+ elseif (_0_0 == "boolean") then
23072307+ serialize = tostring
23082308+ elseif (_0_0 == "string") then
23092309+ serialize = serialize_string
23102310+ elseif (_0_0 == "number") then
23112311+ serialize = serialize_number
23122312+ else
23132313+ serialize = nil
23142314+ end
23152315+ end
23162316+ return handle_compile_opts({utils.expr(serialize(ast), "literal")}, parent, opts)
23172317+ end
23182318+ local function compile_table(ast, scope, parent, opts, compile1)
23192319+ local buffer = {}
23202320+ for i = 1, #ast do
23212321+ local nval = ((i ~= #ast) and 1)
23222322+ table.insert(buffer, exprs1(compile1(ast[i], scope, parent, {nval = nval})))
23232323+ end
23242324+ local function write_other_values(k)
23252325+ if ((type(k) ~= "number") or (math.floor(k) ~= k) or (k < 1) or (k > #ast)) then
23262326+ if ((type(k) == "string") and utils["valid-lua-identifier?"](k)) then
23272327+ return {k, k}
23282328+ else
23292329+ local _0_ = compile1(k, scope, parent, {nval = 1})
23302330+ local compiled = _0_[1]
23312331+ local kstr = ("[" .. tostring(compiled) .. "]")
23322332+ return {kstr, k}
23332333+ end
23342334+ end
23352335+ end
23362336+ do
23372337+ local keys = nil
23382338+ do
23392339+ local _0_0 = utils.kvmap(ast, write_other_values)
23402340+ local function _1_(a, b)
23412341+ return (a[1] < b[1])
23422342+ end
23432343+ table.sort(_0_0, _1_)
23442344+ keys = _0_0
23452345+ end
23462346+ local function _1_(k)
23472347+ local v = tostring(compile1(ast[k[2]], scope, parent, {nval = 1})[1])
23482348+ return string.format("%s = %s", k[1], v)
23492349+ end
23502350+ utils.map(keys, _1_, buffer)
23512351+ end
23522352+ return handle_compile_opts({utils.expr(("{" .. table.concat(buffer, ", ") .. "}"), "expression")}, parent, opts, ast)
23532353+ end
23542354+ local function compile1(ast, scope, parent, opts)
23552355+ local opts0 = (opts or {})
23562356+ local ast0 = macroexpand_2a(ast, scope)
23572357+ if utils["list?"](ast0) then
23582358+ return compile_call(ast0, scope, parent, opts0, compile1)
23592359+ elseif utils["varg?"](ast0) then
23602360+ return compile_varg(ast0, scope, parent, opts0)
23612361+ elseif utils["sym?"](ast0) then
23622362+ return compile_sym(ast0, scope, parent, opts0)
23632363+ elseif (type(ast0) == "table") then
23642364+ return compile_table(ast0, scope, parent, opts0, compile1)
23652365+ elseif ((type(ast0) == "nil") or (type(ast0) == "boolean") or (type(ast0) == "number") or (type(ast0) == "string")) then
23662366+ return compile_scalar(ast0, scope, parent, opts0)
23672367+ else
23682368+ return assert_compile(false, ("could not compile value of type " .. type(ast0)), ast0)
23692369+ end
23702370+ end
23712371+ local function destructure(to, from, ast, scope, parent, opts)
23722372+ local opts0 = (opts or {})
23732373+ local _0_ = opts0
23742374+ local declaration = _0_["declaration"]
23752375+ local forceglobal = _0_["forceglobal"]
23762376+ local forceset = _0_["forceset"]
23772377+ local isvar = _0_["isvar"]
23782378+ local nomulti = _0_["nomulti"]
23792379+ local noundef = _0_["noundef"]
23802380+ local symtype = _0_["symtype"]
23812381+ local symtype0 = ("_" .. (symtype or "dst"))
23822382+ local setter = nil
23832383+ if declaration then
23842384+ setter = "local %s = %s"
23852385+ else
23862386+ setter = "%s = %s"
23872387+ end
23882388+ local new_manglings = {}
23892389+ local function getname(symbol, up1)
23902390+ local raw = symbol[1]
23912391+ assert_compile(not (nomulti and utils["multi-sym?"](raw)), ("unexpected multi symbol " .. raw), up1)
23922392+ if declaration then
23932393+ return declare_local(symbol, nil, scope, symbol, new_manglings)
23942394+ else
23952395+ local parts = (utils["multi-sym?"](raw) or {raw})
23962396+ local meta = scope.symmeta[parts[1]]
23972397+ if ((#parts == 1) and not forceset) then
23982398+ assert_compile(not (forceglobal and meta), string.format("global %s conflicts with local", tostring(symbol)), symbol)
23992399+ assert_compile(not (meta and not meta.var), ("expected var " .. raw), symbol)
24002400+ assert_compile((meta or not noundef), ("expected local " .. parts[1]), symbol)
24012401+ end
24022402+ if forceglobal then
24032403+ assert_compile(not scope.symmeta[scope.unmanglings[raw]], ("global " .. raw .. " conflicts with local"), symbol)
24042404+ scope.manglings[raw] = global_mangling(raw)
24052405+ scope.unmanglings[global_mangling(raw)] = raw
24062406+ if allowed_globals then
24072407+ table.insert(allowed_globals, raw)
24082408+ end
24092409+ end
24102410+ return symbol_to_expression(symbol, scope)[1]
24112411+ end
24122412+ end
24132413+ local function compile_top_target(lvalues)
24142414+ local inits = nil
24152415+ local function _2_(_241)
24162416+ if scope.manglings[_241] then
24172417+ return _241
24182418+ else
24192419+ return "nil"
24202420+ end
24212421+ end
24222422+ inits = utils.map(lvalues, _2_)
24232423+ local init = table.concat(inits, ", ")
24242424+ local lvalue = table.concat(lvalues, ", ")
24252425+ local plen, plast = #parent, parent[#parent]
24262426+ local ret = compile1(from, scope, parent, {target = lvalue})
24272427+ if declaration then
24282428+ for pi = plen, #parent do
24292429+ if (parent[pi] == plast) then
24302430+ plen = pi
24312431+ end
24322432+ end
24332433+ if ((#parent == (plen + 1)) and parent[#parent].leaf) then
24342434+ parent[#parent]["leaf"] = ("local " .. parent[#parent].leaf)
24352435+ else
24362436+ table.insert(parent, (plen + 1), {ast = ast, leaf = ("local " .. lvalue .. " = " .. init)})
24372437+ end
24382438+ end
24392439+ return ret
24402440+ end
24412441+ local function destructure_sym(left, rightexprs, up1, top_3f)
24422442+ local lname = getname(left, up1)
24432443+ check_binding_valid(left, scope, left)
24442444+ if top_3f then
24452445+ compile_top_target({lname})
24462446+ else
24472447+ emit(parent, setter:format(lname, exprs1(rightexprs)), left)
24482448+ end
24492449+ if declaration then
24502450+ scope.symmeta[utils.deref(left)] = {var = isvar}
24512451+ return nil
24522452+ end
24532453+ end
24542454+ local function destructure_table(left, rightexprs, top_3f, destructure1)
24552455+ local s = gensym(scope, symtype0)
24562456+ local right = nil
24572457+ do
24582458+ local _2_0 = nil
24592459+ if top_3f then
24602460+ _2_0 = exprs1(compile1(from, scope, parent))
24612461+ else
24622462+ _2_0 = exprs1(rightexprs)
24632463+ end
24642464+ if (_2_0 == "") then
24652465+ right = "nil"
24662466+ elseif (nil ~= _2_0) then
24672467+ local right0 = _2_0
24682468+ right = right0
24692469+ else
24702470+ right = nil
24712471+ end
24722472+ end
24732473+ emit(parent, string.format("local %s = %s", s, right), left)
24742474+ for k, v in utils.stablepairs(left) do
24752475+ if not (("number" == type(k)) and tostring(left[(k - 1)]):find("^&")) then
24762476+ if (utils["sym?"](v) and (utils.deref(v) == "&")) then
24772477+ local unpack_str = "{(table.unpack or unpack)(%s, %s)}"
24782478+ local formatted = string.format(unpack_str, s, k)
24792479+ local subexpr = utils.expr(formatted, "expression")
24802480+ assert_compile((utils["sequence?"](left) and (nil == left[(k + 2)])), "expected rest argument before last parameter", left)
24812481+ destructure1(left[(k + 1)], {subexpr}, left)
24822482+ elseif (utils["sym?"](k) and (utils.deref(k) == "&as")) then
24832483+ destructure_sym(v, {utils.expr(tostring(s))}, left)
24842484+ elseif (utils["sequence?"](left) and (utils.deref(v) == "&as")) then
24852485+ local _, next_sym, trailing = select(k, unpack(left))
24862486+ assert_compile((nil == trailing), "expected &as argument before last parameter", left)
24872487+ destructure_sym(next_sym, {utils.expr(tostring(s))}, left)
24882488+ else
24892489+ local key = nil
24902490+ if (type(k) == "string") then
24912491+ key = serialize_string(k)
24922492+ else
24932493+ key = k
24942494+ end
24952495+ local subexpr = utils.expr(string.format("%s[%s]", s, key), "expression")
24962496+ destructure1(v, {subexpr}, left)
24972497+ end
24982498+ end
24992499+ end
25002500+ return nil
25012501+ end
25022502+ local function destructure_values(left, up1, top_3f, destructure1)
25032503+ local left_names, tables = {}, {}
25042504+ for i, name in ipairs(left) do
25052505+ if utils["sym?"](name) then
25062506+ table.insert(left_names, getname(name, up1))
25072507+ else
25082508+ local symname = gensym(scope, symtype0)
25092509+ table.insert(left_names, symname)
25102510+ tables[i] = {name, utils.expr(symname, "sym")}
25112511+ end
25122512+ end
25132513+ assert_compile(top_3f, "can't nest multi-value destructuring", left)
25142514+ compile_top_target(left_names)
25152515+ if declaration then
25162516+ for _, sym in ipairs(left) do
25172517+ scope.symmeta[utils.deref(sym)] = {var = isvar}
25182518+ end
25192519+ end
25202520+ for _, pair in utils.stablepairs(tables) do
25212521+ destructure1(pair[1], {pair[2]}, left)
25222522+ end
25232523+ return nil
25242524+ end
25252525+ local function destructure1(left, rightexprs, up1, top_3f)
25262526+ if (utils["sym?"](left) and (left[1] ~= "nil")) then
25272527+ destructure_sym(left, rightexprs, up1, top_3f)
25282528+ elseif utils["table?"](left) then
25292529+ destructure_table(left, rightexprs, top_3f, destructure1)
25302530+ elseif utils["list?"](left) then
25312531+ destructure_values(left, up1, top_3f, destructure1)
25322532+ else
25332533+ assert_compile(false, string.format("unable to bind %s %s", type(left), tostring(left)), (((type(up1[2]) == "table") and up1[2]) or up1))
25342534+ end
25352535+ if top_3f then
25362536+ return {returned = true}
25372537+ end
25382538+ end
25392539+ local ret = destructure1(to, nil, ast, true)
25402540+ utils.hook("destructure", from, to, scope)
25412541+ apply_manglings(scope, new_manglings, ast)
25422542+ return ret
25432543+ end
25442544+ local function require_include(ast, scope, parent, opts)
25452545+ opts.fallback = function(e)
25462546+ return utils.expr(string.format("require(%s)", tostring(e)), "statement")
25472547+ end
25482548+ return scopes.global.specials.include(ast, scope, parent, opts)
25492549+ end
25502550+ local function compile_stream(strm, options)
25512551+ local opts = utils.copy(options)
25522552+ local old_globals = allowed_globals
25532553+ local scope = (opts.scope or make_scope(scopes.global))
25542554+ local vals = {}
25552555+ local chunk = {}
25562556+ local _0_ = utils.root
25572557+ _0_["set-reset"](_0_)
25582558+ allowed_globals = opts.allowedGlobals
25592559+ if (opts.indent == nil) then
25602560+ opts.indent = " "
25612561+ end
25622562+ if opts.requireAsInclude then
25632563+ scope.specials.require = require_include
25642564+ end
25652565+ utils.root.chunk, utils.root.scope, utils.root.options = chunk, scope, opts
25662566+ for _, val in parser.parser(strm, opts.filename, opts) do
25672567+ table.insert(vals, val)
25682568+ end
25692569+ for i = 1, #vals do
25702570+ local exprs = compile1(vals[i], scope, chunk, {nval = (((i < #vals) and 0) or nil), tail = (i == #vals)})
25712571+ keep_side_effects(exprs, chunk, nil, vals[i])
25722572+ end
25732573+ allowed_globals = old_globals
25742574+ utils.root.reset()
25752575+ return flatten(chunk, opts)
25762576+ end
25772577+ local function compile_string(str, opts)
25782578+ return compile_stream(parser["string-stream"](str), (opts or {}))
25792579+ end
25802580+ local function compile(ast, opts)
25812581+ local opts0 = utils.copy(opts)
25822582+ local old_globals = allowed_globals
25832583+ local chunk = {}
25842584+ local scope = (opts0.scope or make_scope(scopes.global))
25852585+ local _0_ = utils.root
25862586+ _0_["set-reset"](_0_)
25872587+ allowed_globals = opts0.allowedGlobals
25882588+ if (opts0.indent == nil) then
25892589+ opts0.indent = " "
25902590+ end
25912591+ if opts0.requireAsInclude then
25922592+ scope.specials.require = require_include
25932593+ end
25942594+ utils.root.chunk, utils.root.scope, utils.root.options = chunk, scope, opts0
25952595+ local exprs = compile1(ast, scope, chunk, {tail = true})
25962596+ keep_side_effects(exprs, chunk, nil, ast)
25972597+ allowed_globals = old_globals
25982598+ utils.root.reset()
25992599+ return flatten(chunk, opts0)
26002600+ end
26012601+ local function traceback_frame(info)
26022602+ if ((info.what == "C") and info.name) then
26032603+ return string.format(" [C]: in function '%s'", info.name)
26042604+ elseif (info.what == "C") then
26052605+ return " [C]: in ?"
26062606+ else
26072607+ local remap = fennel_sourcemap[info.source]
26082608+ if (remap and remap[info.currentline]) then
26092609+ info["short-src"] = remap["short-src"]
26102610+ info.currentline = remap[info.currentline]
26112611+ end
26122612+ if (info.what == "Lua") then
26132613+ local function _1_()
26142614+ if info.name then
26152615+ return ("'" .. info.name .. "'")
26162616+ else
26172617+ return "?"
26182618+ end
26192619+ end
26202620+ return string.format(" %s:%d: in function %s", info.short_src, info.currentline, _1_())
26212621+ elseif (info["short-src"] == "(tail call)") then
26222622+ return " (tail call)"
26232623+ else
26242624+ return string.format(" %s:%d: in main chunk", info.short_src, info.currentline)
26252625+ end
26262626+ end
26272627+ end
26282628+ local function traceback(msg, start)
26292629+ local msg0 = (msg or "")
26302630+ if ((msg0:find("^Compile error") or msg0:find("^Parse error")) and not utils["debug-on?"]("trace")) then
26312631+ return msg0
26322632+ else
26332633+ local lines = {}
26342634+ if (msg0:find("^Compile error") or msg0:find("^Parse error")) then
26352635+ table.insert(lines, msg0)
26362636+ else
26372637+ local newmsg = msg0:gsub("^[^:]*:%d+:%s+", "runtime error: ")
26382638+ table.insert(lines, newmsg)
26392639+ end
26402640+ table.insert(lines, "stack traceback:")
26412641+ local done_3f, level = false, (start or 2)
26422642+ while not done_3f do
26432643+ do
26442644+ local _1_0 = debug.getinfo(level, "Sln")
26452645+ if (_1_0 == nil) then
26462646+ done_3f = true
26472647+ elseif (nil ~= _1_0) then
26482648+ local info = _1_0
26492649+ table.insert(lines, traceback_frame(info))
26502650+ end
26512651+ end
26522652+ level = (level + 1)
26532653+ end
26542654+ return table.concat(lines, "\n")
26552655+ end
26562656+ end
26572657+ local function entry_transform(fk, fv)
26582658+ local function _0_(k, v)
26592659+ if (type(k) == "number") then
26602660+ return k, fv(v)
26612661+ else
26622662+ return fk(k), fv(v)
26632663+ end
26642664+ end
26652665+ return _0_
26662666+ end
26672667+ local function no()
26682668+ return nil
26692669+ end
26702670+ local function mixed_concat(t, joiner)
26712671+ local seen = {}
26722672+ local ret, s = "", ""
26732673+ for k, v in ipairs(t) do
26742674+ table.insert(seen, k)
26752675+ ret = (ret .. s .. v)
26762676+ s = joiner
26772677+ end
26782678+ for k, v in utils.stablepairs(t) do
26792679+ if not seen[k] then
26802680+ ret = (ret .. s .. "[" .. k .. "]" .. "=" .. v)
26812681+ s = joiner
26822682+ end
26832683+ end
26842684+ return ret
26852685+ end
26862686+ local function do_quote(form, scope, parent, runtime_3f)
26872687+ local function q(x)
26882688+ return do_quote(x, scope, parent, runtime_3f)
26892689+ end
26902690+ if utils["varg?"](form) then
26912691+ assert_compile(not runtime_3f, "quoted ... may only be used at compile time", form)
26922692+ return "_VARARG"
26932693+ elseif utils["sym?"](form) then
26942694+ local filename = nil
26952695+ if form.filename then
26962696+ filename = string.format("%q", form.filename)
26972697+ else
26982698+ filename = "nil"
26992699+ end
27002700+ local symstr = utils.deref(form)
27012701+ assert_compile(not runtime_3f, "symbols may only be used at compile time", form)
27022702+ if (symstr:find("#$") or symstr:find("#[:.]")) then
27032703+ return string.format("sym('%s', nil, {filename=%s, line=%s})", autogensym(symstr, scope), filename, (form.line or "nil"))
27042704+ else
27052705+ return string.format("sym('%s', nil, {quoted=true, filename=%s, line=%s})", symstr, filename, (form.line or "nil"))
27062706+ end
27072707+ elseif (utils["list?"](form) and utils["sym?"](form[1]) and (utils.deref(form[1]) == "unquote")) then
27082708+ local payload = form[2]
27092709+ local res = unpack(compile1(payload, scope, parent))
27102710+ return res[1]
27112711+ elseif utils["list?"](form) then
27122712+ local mapped = utils.kvmap(form, entry_transform(no, q))
27132713+ local filename = nil
27142714+ if form.filename then
27152715+ filename = string.format("%q", form.filename)
27162716+ else
27172717+ filename = "nil"
27182718+ end
27192719+ assert_compile(not runtime_3f, "lists may only be used at compile time", form)
27202720+ 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, ", "))
27212721+ elseif (type(form) == "table") then
27222722+ local mapped = utils.kvmap(form, entry_transform(q, q))
27232723+ local source = getmetatable(form)
27242724+ local filename = nil
27252725+ if source.filename then
27262726+ filename = string.format("%q", source.filename)
27272727+ else
27282728+ filename = "nil"
27292729+ end
27302730+ local function _1_()
27312731+ if source then
27322732+ return source.line
27332733+ else
27342734+ return "nil"
27352735+ end
27362736+ end
27372737+ return string.format("setmetatable({%s}, {filename=%s, line=%s})", mixed_concat(mapped, ", "), filename, _1_())
27382738+ elseif (type(form) == "string") then
27392739+ return serialize_string(form)
27402740+ else
27412741+ return tostring(form)
27422742+ end
27432743+ end
27442744+ return {["apply-manglings"] = apply_manglings, ["compile-stream"] = compile_stream, ["compile-string"] = compile_string, ["declare-local"] = declare_local, ["do-quote"] = do_quote, ["global-mangling"] = global_mangling, ["global-unmangling"] = global_unmangling, ["keep-side-effects"] = keep_side_effects, ["make-scope"] = make_scope, ["require-include"] = require_include, ["symbol-to-expression"] = symbol_to_expression, assert = assert_compile, autogensym = autogensym, compile = compile, compile1 = compile1, destructure = destructure, emit = emit, gensym = gensym, macroexpand = macroexpand_2a, metadata = make_metadata(), scopes = scopes, traceback = traceback}
27452745+end
27462746+package.preload["fennel.friend"] = package.preload["fennel.friend"] or function(...)
27472747+ local function ast_source(ast)
27482748+ local m = getmetatable(ast)
27492749+ return ((m and m.line and m) or (("table" == type(ast)) and ast) or {})
27502750+ end
27512751+ local suggestions = {["$ and $... in hashfn are mutually exclusive"] = {"modifying the hashfn so it only contains $... or $, $1, $2, $3, etc"}, ["can't start multisym segment with a digit"] = {"removing the digit", "adding a non-digit before the digit"}, ["cannot call literal value"] = {"checking for typos", "checking for a missing function name"}, ["could not compile value of type "] = {"debugging the macro you're calling not to return a coroutine or userdata"}, ["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"}, ["expected a function.* to call"] = {"removing the empty parentheses", "using square brackets if you want an empty table"}, ["expected binding table"] = {"placing a table here in square brackets containing identifiers to bind"}, ["expected body expression"] = {"putting some code in the body of this form after the bindings"}, ["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"}, ["expected even number of name/value bindings"] = {"finding where the identifier or value is missing"}, ["expected even number of values in table literal"] = {"removing a key", "adding a value"}, ["expected local"] = {"looking for a typo", "looking for a local which is used out of its scope"}, ["expected macros to be table"] = {"ensuring your macro definitions return a table"}, ["expected parameters"] = {"adding function parameters as a list of identifiers in brackets"}, ["expected rest argument before last parameter"] = {"moving & to right before the final identifier when destructuring"}, ["expected symbol for function parameter: (.*)"] = {"changing %s to an identifier instead of a literal value"}, ["expected var (.*)"] = {"declaring %s using var instead of let/local", "introducing a new local instead of changing the value of %s"}, ["expected vararg as last parameter"] = {"moving the \"...\" to the end of the parameter list"}, ["expected whitespace before opening delimiter"] = {"adding whitespace"}, ["global (.*) conflicts with local"] = {"renaming local %s"}, ["illegal character: (.)"] = {"deleting or replacing %s", "avoiding reserved characters like \", \\, ', ~, ;, @, `, and comma"}, ["local (.*) was overshadowed by a special form or macro"] = {"renaming local %s"}, ["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"}, ["malformed multisym"] = {"ensuring each period or colon is not followed by another period or colon"}, ["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"}, ["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"}, ["mismatched closing delimiter (.), expected (.)"] = {"replacing %s with %s", "deleting %s", "adding matching opening delimiter earlier"}, ["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"}, ["unable to bind (.*)"] = {"replacing the %s with an identifier"}, ["unexpected closing delimiter (.)"] = {"deleting %s", "adding matching opening delimiter earlier"}, ["unexpected multi symbol (.*)"] = {"removing periods or colons from %s"}, ["unexpected vararg"] = {"putting \"...\" at the end of the fn parameters if the vararg was intended"}, ["unknown global 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"}, ["unused local (.*)"] = {"fixing a typo so %s is used", "renaming the local to _%s"}, ["use of global (.*) is aliased by a local"] = {"renaming local %s", "refer to the global using _G.%s instead of directly"}}
27522752+ local unpack = (table.unpack or _G.unpack)
27532753+ local function suggest(msg)
27542754+ local suggestion = nil
27552755+ for pat, sug in pairs(suggestions) do
27562756+ local matches = {msg:match(pat)}
27572757+ if (0 < #matches) then
27582758+ if ("table" == type(sug)) then
27592759+ local out = {}
27602760+ for _, s in ipairs(sug) do
27612761+ table.insert(out, s:format(unpack(matches)))
27622762+ end
27632763+ suggestion = out
27642764+ else
27652765+ suggestion = sug(matches)
27662766+ end
27672767+ end
27682768+ end
27692769+ return suggestion
27702770+ end
27712771+ local function read_line_from_file(filename, line)
27722772+ local bytes = 0
27732773+ local f = assert(io.open(filename))
27742774+ local _ = nil
27752775+ for _0 = 1, (line - 1) do
27762776+ bytes = (bytes + 1 + #f:read())
27772777+ end
27782778+ _ = nil
27792779+ local codeline = f:read()
27802780+ f:close()
27812781+ return codeline, bytes
27822782+ end
27832783+ local function read_line_from_source(source, line)
27842784+ local lines, bytes, codeline = 0, 0
27852785+ for this_line, newline in string.gmatch((source .. "\n"), "(.-)(\13?\n)") do
27862786+ lines = (lines + 1)
27872787+ if (lines == line) then
27882788+ codeline = this_line
27892789+ break
27902790+ end
27912791+ bytes = (bytes + #newline + #this_line)
27922792+ end
27932793+ return codeline, bytes
27942794+ end
27952795+ local function read_line(filename, line, source)
27962796+ if source then
27972797+ return read_line_from_source(source, line)
27982798+ else
27992799+ return read_line_from_file(filename, line)
28002800+ end
28012801+ end
28022802+ local function friendly_msg(msg, _0_0, source)
28032803+ local _1_ = _0_0
28042804+ local byteend = _1_["byteend"]
28052805+ local bytestart = _1_["bytestart"]
28062806+ local filename = _1_["filename"]
28072807+ local line = _1_["line"]
28082808+ local ok, codeline, bol = pcall(read_line, filename, line, source)
28092809+ local suggestions0 = suggest(msg)
28102810+ local out = {msg, ""}
28112811+ if (ok and codeline) then
28122812+ table.insert(out, codeline)
28132813+ end
28142814+ if (ok and codeline and bytestart and byteend) then
28152815+ table.insert(out, (string.rep(" ", (bytestart - bol - 1)) .. "^" .. string.rep("^", math.min((byteend - bytestart), ((bol + #codeline) - bytestart)))))
28162816+ end
28172817+ if (ok and codeline and bytestart and not byteend) then
28182818+ table.insert(out, (string.rep("-", (bytestart - bol - 1)) .. "^"))
28192819+ table.insert(out, "")
28202820+ end
28212821+ if suggestions0 then
28222822+ for _, suggestion in ipairs(suggestions0) do
28232823+ table.insert(out, ("* Try %s."):format(suggestion))
28242824+ end
28252825+ end
28262826+ return table.concat(out, "\n")
28272827+ end
28282828+ local function assert_compile(condition, msg, ast, source)
28292829+ if not condition then
28302830+ local _1_ = ast_source(ast)
28312831+ local filename = _1_["filename"]
28322832+ local line = _1_["line"]
28332833+ error(friendly_msg(("Compile error in %s:%s\n %s"):format((filename or "unknown"), (line or "?"), msg), ast_source(ast), source), 0)
28342834+ end
28352835+ return condition
28362836+ end
28372837+ local function parse_error(msg, filename, line, bytestart, source)
28382838+ return error(friendly_msg(("Parse error in %s:%s\n %s"):format(filename, line, msg), {bytestart = bytestart, filename = filename, line = line}, source), 0)
28392839+ end
28402840+ return {["assert-compile"] = assert_compile, ["parse-error"] = parse_error}
28412841+end
28422842+package.preload["fennel.parser"] = package.preload["fennel.parser"] or function(...)
28432843+ local utils = require("fennel.utils")
28442844+ local friend = require("fennel.friend")
28452845+ local unpack = (table.unpack or _G.unpack)
28462846+ local function granulate(getchunk)
28472847+ local c, index, done_3f = "", 1, false
28482848+ local function _0_(parser_state)
28492849+ if not done_3f then
28502850+ if (index <= #c) then
28512851+ local b = c:byte(index)
28522852+ index = (index + 1)
28532853+ return b
28542854+ else
28552855+ local _1_0, _2_0, _3_0 = getchunk(parser_state)
28562856+ local _4_
28572857+ do
28582858+ local char = _1_0
28592859+ _4_ = ((nil ~= _1_0) and (char ~= ""))
28602860+ end
28612861+ if _4_ then
28622862+ local char = _1_0
28632863+ c = char
28642864+ index = 2
28652865+ return c:byte()
28662866+ else
28672867+ local _ = _1_0
28682868+ done_3f = true
28692869+ return nil
28702870+ end
28712871+ end
28722872+ end
28732873+ end
28742874+ local function _1_()
28752875+ c = ""
28762876+ return nil
28772877+ end
28782878+ return _0_, _1_
28792879+ end
28802880+ local function string_stream(str)
28812881+ local str0 = str:gsub("^#!", ";;")
28822882+ local index = 1
28832883+ local function _0_()
28842884+ local r = str0:byte(index)
28852885+ index = (index + 1)
28862886+ return r
28872887+ end
28882888+ return _0_
28892889+ end
28902890+ local delims = {[123] = 125, [125] = true, [40] = 41, [41] = true, [91] = 93, [93] = true}
28912891+ local function whitespace_3f(b)
28922892+ return ((b == 32) or ((b >= 9) and (b <= 13)))
28932893+ end
28942894+ local function sym_char_3f(b)
28952895+ local b0 = nil
28962896+ if ("number" == type(b)) then
28972897+ b0 = b
28982898+ else
28992899+ b0 = string.byte(b)
29002900+ end
29012901+ return ((b0 > 32) 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))
29022902+ end
29032903+ local prefixes = {[35] = "hashfn", [39] = "quote", [44] = "unquote", [96] = "quote"}
29042904+ local function parser(getbyte, filename, options)
29052905+ local stack = {}
29062906+ local line = 1
29072907+ local byteindex = 0
29082908+ local lastb = nil
29092909+ local function ungetb(ub)
29102910+ if (ub == 10) then
29112911+ line = (line - 1)
29122912+ end
29132913+ byteindex = (byteindex - 1)
29142914+ lastb = ub
29152915+ return nil
29162916+ end
29172917+ local function getb()
29182918+ local r = nil
29192919+ if lastb then
29202920+ r, lastb = lastb, nil
29212921+ else
29222922+ r = getbyte({["stack-size"] = #stack})
29232923+ end
29242924+ byteindex = (byteindex + 1)
29252925+ if (r == 10) then
29262926+ line = (line + 1)
29272927+ end
29282928+ return r
29292929+ end
29302930+ local function parse_error(msg, byteindex_override)
29312931+ local _0_ = (options or utils.root.options or {})
29322932+ local source = _0_["source"]
29332933+ local unfriendly = _0_["unfriendly"]
29342934+ utils.root.reset()
29352935+ if unfriendly then
29362936+ return error(string.format("Parse error in %s:%s: %s", (filename or "unknown"), (line or "?"), msg), 0)
29372937+ else
29382938+ return friend["parse-error"](msg, (filename or "unknown"), (line or "?"), (byteindex_override or byteindex), source)
29392939+ end
29402940+ end
29412941+ local function parse_stream()
29422942+ local whitespace_since_dispatch, done_3f, retval = true
29432943+ local function dispatch(v)
29442944+ local _0_0 = stack[#stack]
29452945+ if (_0_0 == nil) then
29462946+ retval, done_3f, whitespace_since_dispatch = v, true, false
29472947+ return nil
29482948+ elseif ((type(_0_0) == "table") and (nil ~= _0_0.prefix)) then
29492949+ local prefix = _0_0.prefix
29502950+ table.remove(stack)
29512951+ return dispatch(utils.list(utils.sym(prefix), v))
29522952+ elseif (nil ~= _0_0) then
29532953+ local top = _0_0
29542954+ whitespace_since_dispatch = false
29552955+ return table.insert(top, v)
29562956+ end
29572957+ end
29582958+ local function badend()
29592959+ local accum = utils.map(stack, "closer")
29602960+ local _0_
29612961+ if (#stack == 1) then
29622962+ _0_ = ""
29632963+ else
29642964+ _0_ = "s"
29652965+ end
29662966+ return parse_error(string.format("expected closing delimiter%s %s", _0_, string.char(unpack(accum))))
29672967+ end
29682968+ local function skip_whitespace(b)
29692969+ if (b and whitespace_3f(b)) then
29702970+ whitespace_since_dispatch = true
29712971+ return skip_whitespace(getb())
29722972+ elseif (not b and (#stack > 0)) then
29732973+ return badend()
29742974+ else
29752975+ return b
29762976+ end
29772977+ end
29782978+ local function parse_comment(b, contents)
29792979+ if (b and (10 ~= b)) then
29802980+ local function _1_()
29812981+ local _0_0 = contents
29822982+ table.insert(_0_0, string.char(b))
29832983+ return _0_0
29842984+ end
29852985+ return parse_comment(getb(), _1_())
29862986+ elseif (options and options.comments) then
29872987+ return dispatch(utils.comment(table.concat(contents)))
29882988+ else
29892989+ return b
29902990+ end
29912991+ end
29922992+ local function open_table(b)
29932993+ if not whitespace_since_dispatch then
29942994+ parse_error(("expected whitespace before opening delimiter " .. string.char(b)))
29952995+ end
29962996+ return table.insert(stack, {bytestart = byteindex, closer = delims[b], filename = filename, line = line})
29972997+ end
29982998+ local function close_list(list)
29992999+ return dispatch(setmetatable(list, getmetatable(utils.list())))
30003000+ end
30013001+ local function close_sequence(tbl)
30023002+ local val = utils.sequence(unpack(tbl))
30033003+ for k, v in pairs(tbl) do
30043004+ getmetatable(val)[k] = v
30053005+ end
30063006+ return dispatch(val)
30073007+ end
30083008+ local function close_curly_table(tbl)
30093009+ local val = {}
30103010+ if ((#tbl % 2) ~= 0) then
30113011+ byteindex = (byteindex - 1)
30123012+ parse_error("expected even number of values in table literal")
30133013+ end
30143014+ setmetatable(val, tbl)
30153015+ for i = 1, #tbl, 2 do
30163016+ if ((tostring(tbl[i]) == ":") and utils["sym?"](tbl[(i + 1)]) and utils["sym?"](tbl[i])) then
30173017+ tbl[i] = tostring(tbl[(i + 1)])
30183018+ end
30193019+ val[tbl[i]] = tbl[(i + 1)]
30203020+ end
30213021+ return dispatch(val)
30223022+ end
30233023+ local function close_table(b)
30243024+ local top = table.remove(stack)
30253025+ if (top == nil) then
30263026+ parse_error(("unexpected closing delimiter " .. string.char(b)))
30273027+ end
30283028+ if (top.closer ~= b) then
30293029+ parse_error(("mismatched closing delimiter " .. string.char(b) .. ", expected " .. string.char(top.closer)))
30303030+ end
30313031+ top.byteend = byteindex
30323032+ if (b == 41) then
30333033+ return close_list(top)
30343034+ elseif (b == 93) then
30353035+ return close_sequence(top)
30363036+ else
30373037+ return close_curly_table(top)
30383038+ end
30393039+ end
30403040+ local function parse_string_loop(chars, b, state)
30413041+ table.insert(chars, b)
30423042+ local state0 = nil
30433043+ do
30443044+ local _0_0 = {state, b}
30453045+ if ((type(_0_0) == "table") and (_0_0[1] == "base") and (_0_0[2] == 92)) then
30463046+ state0 = "backslash"
30473047+ elseif ((type(_0_0) == "table") and (_0_0[1] == "base") and (_0_0[2] == 34)) then
30483048+ state0 = "done"
30493049+ else
30503050+ local _ = _0_0
30513051+ state0 = "base"
30523052+ end
30533053+ end
30543054+ if (b and (state0 ~= "done")) then
30553055+ return parse_string_loop(chars, getb(), state0)
30563056+ else
30573057+ return b
30583058+ end
30593059+ end
30603060+ local function escape_char(c)
30613061+ return ({[10] = "\\n", [11] = "\\v", [12] = "\\f", [13] = "\\r", [7] = "\\a", [8] = "\\b", [9] = "\\t"})[c:byte()]
30623062+ end
30633063+ local function parse_string()
30643064+ table.insert(stack, {closer = 34})
30653065+ local chars = {34}
30663066+ if not parse_string_loop(chars, getb(), "base") then
30673067+ badend()
30683068+ end
30693069+ table.remove(stack)
30703070+ local raw = string.char(unpack(chars))
30713071+ local formatted = raw:gsub("[\7-\13]", escape_char)
30723072+ local load_fn = (rawget(_G, "loadstring") or load)(("return " .. formatted))
30733073+ return dispatch(load_fn())
30743074+ end
30753075+ local function parse_prefix(b)
30763076+ table.insert(stack, {prefix = prefixes[b]})
30773077+ local nextb = getb()
30783078+ if whitespace_3f(nextb) then
30793079+ if (b ~= 35) then
30803080+ parse_error("invalid whitespace after quoting prefix")
30813081+ end
30823082+ table.remove(stack)
30833083+ dispatch(utils.sym("#"))
30843084+ end
30853085+ return ungetb(nextb)
30863086+ end
30873087+ local function parse_sym_loop(chars, b)
30883088+ if (b and sym_char_3f(b)) then
30893089+ table.insert(chars, b)
30903090+ return parse_sym_loop(chars, getb())
30913091+ else
30923092+ if b then
30933093+ ungetb(b)
30943094+ end
30953095+ return chars
30963096+ end
30973097+ end
30983098+ local function parse_number(rawstr)
30993099+ local number_with_stripped_underscores = (not rawstr:find("^_") and rawstr:gsub("_", ""))
31003100+ if rawstr:match("^%d") then
31013101+ dispatch((tonumber(number_with_stripped_underscores) or parse_error(("could not read number \"" .. rawstr .. "\""))))
31023102+ return true
31033103+ else
31043104+ local _0_0 = tonumber(number_with_stripped_underscores)
31053105+ if (nil ~= _0_0) then
31063106+ local x = _0_0
31073107+ dispatch(x)
31083108+ return true
31093109+ else
31103110+ local _ = _0_0
31113111+ return false
31123112+ end
31133113+ end
31143114+ end
31153115+ local function check_malformed_sym(rawstr)
31163116+ if (rawstr:match("^~") and (rawstr ~= "~=")) then
31173117+ return parse_error("illegal character: ~")
31183118+ elseif rawstr:match("%.[0-9]") then
31193119+ return parse_error(("can't start multisym segment " .. "with a digit: " .. rawstr), (((byteindex - #rawstr) + rawstr:find("%.[0-9]")) + 1))
31203120+ elseif (rawstr:match("[%.:][%.:]") and (rawstr ~= "..") and (rawstr ~= "$...")) then
31213121+ return parse_error(("malformed multisym: " .. rawstr), ((byteindex - #rawstr) + 1 + rawstr:find("[%.:][%.:]")))
31223122+ elseif rawstr:match(":.+[%.:]") then
31233123+ return parse_error(("method must be last component " .. "of multisym: " .. rawstr), ((byteindex - #rawstr) + rawstr:find(":.+[%.:]")))
31243124+ end
31253125+ end
31263126+ local function parse_sym(b)
31273127+ local bytestart = byteindex
31283128+ local rawstr = string.char(unpack(parse_sym_loop({b}, getb())))
31293129+ if (rawstr == "true") then
31303130+ return dispatch(true)
31313131+ elseif (rawstr == "false") then
31323132+ return dispatch(false)
31333133+ elseif (rawstr == "...") then
31343134+ return dispatch(utils.varg())
31353135+ elseif rawstr:match("^:.+$") then
31363136+ return dispatch(rawstr:sub(2))
31373137+ elseif parse_number(rawstr) then
31383138+ return nil
31393139+ elseif check_malformed_sym(rawstr) then
31403140+ return nil
31413141+ else
31423142+ return dispatch(utils.sym(rawstr, nil, {byteend = byteindex, bytestart = bytestart, filename = filename, line = line}))
31433143+ end
31443144+ end
31453145+ local function parse_loop(b)
31463146+ if not b then
31473147+ elseif (b == 59) then
31483148+ parse_comment(getb(), {";"})
31493149+ elseif (type(delims[b]) == "number") then
31503150+ open_table(b)
31513151+ elseif delims[b] then
31523152+ close_table(b)
31533153+ elseif (b == 34) then
31543154+ parse_string(b)
31553155+ elseif prefixes[b] then
31563156+ parse_prefix(b)
31573157+ elseif (sym_char_3f(b) or (b == string.byte("~"))) then
31583158+ parse_sym(b)
31593159+ else
31603160+ parse_error(("illegal character: " .. string.char(b)))
31613161+ end
31623162+ if not b then
31633163+ return nil
31643164+ elseif done_3f then
31653165+ return true, retval
31663166+ else
31673167+ return parse_loop(skip_whitespace(getb()))
31683168+ end
31693169+ end
31703170+ return parse_loop(skip_whitespace(getb()))
31713171+ end
31723172+ local function _0_()
31733173+ stack = {}
31743174+ return nil
31753175+ end
31763176+ return parse_stream, _0_
31773177+ end
31783178+ return {["string-stream"] = string_stream, ["sym-char?"] = sym_char_3f, granulate = granulate, parser = parser}
31793179+end
31803180+local utils = nil
31813181+package.preload["fennel.utils"] = package.preload["fennel.utils"] or function(...)
31823182+ local function stablepairs(t)
31833183+ local keys = {}
31843184+ local succ = {}
31853185+ for k in pairs(t) do
31863186+ table.insert(keys, k)
31873187+ end
31883188+ local function _0_(a, b)
31893189+ return (tostring(a) < tostring(b))
31903190+ end
31913191+ table.sort(keys, _0_)
31923192+ for i, k in ipairs(keys) do
31933193+ succ[k] = keys[(i + 1)]
31943194+ end
31953195+ local function stablenext(tbl, idx)
31963196+ if (idx == nil) then
31973197+ return keys[1], tbl[keys[1]]
31983198+ else
31993199+ return succ[idx], tbl[succ[idx]]
32003200+ end
32013201+ end
32023202+ return stablenext, t, nil
32033203+ end
32043204+ local function map(t, f, out)
32053205+ local out0 = (out or {})
32063206+ local f0 = nil
32073207+ if (type(f) == "function") then
32083208+ f0 = f
32093209+ else
32103210+ local s = f
32113211+ local function _0_(x)
32123212+ return x[s]
32133213+ end
32143214+ f0 = _0_
32153215+ end
32163216+ for _, x in ipairs(t) do
32173217+ local _1_0 = f0(x)
32183218+ if (nil ~= _1_0) then
32193219+ local v = _1_0
32203220+ table.insert(out0, v)
32213221+ end
32223222+ end
32233223+ return out0
32243224+ end
32253225+ local function kvmap(t, f, out)
32263226+ local out0 = (out or {})
32273227+ local f0 = nil
32283228+ if (type(f) == "function") then
32293229+ f0 = f
32303230+ else
32313231+ local s = f
32323232+ local function _0_(x)
32333233+ return x[s]
32343234+ end
32353235+ f0 = _0_
32363236+ end
32373237+ for k, x in stablepairs(t) do
32383238+ local _1_0, _2_0 = f0(k, x)
32393239+ if ((nil ~= _1_0) and (nil ~= _2_0)) then
32403240+ local key = _1_0
32413241+ local value = _2_0
32423242+ out0[key] = value
32433243+ elseif (nil ~= _1_0) then
32443244+ local value = _1_0
32453245+ table.insert(out0, value)
32463246+ end
32473247+ end
32483248+ return out0
32493249+ end
32503250+ local function copy(from, to)
32513251+ local to0 = (to or {})
32523252+ for k, v in pairs((from or {})) do
32533253+ to0[k] = v
32543254+ end
32553255+ return to0
32563256+ end
32573257+ local function member_3f(x, tbl, n)
32583258+ local _0_0 = tbl[(n or 1)]
32593259+ if (_0_0 == x) then
32603260+ return true
32613261+ elseif (_0_0 == nil) then
32623262+ return false
32633263+ else
32643264+ local _ = _0_0
32653265+ return member_3f(x, tbl, ((n or 1) + 1))
32663266+ end
32673267+ end
32683268+ local function allpairs(tbl)
32693269+ assert((type(tbl) == "table"), "allpairs expects a table")
32703270+ local t = tbl
32713271+ local seen = {}
32723272+ local function allpairs_next(_, state)
32733273+ local next_state, value = next(t, state)
32743274+ if seen[next_state] then
32753275+ return allpairs_next(nil, next_state)
32763276+ elseif next_state then
32773277+ seen[next_state] = true
32783278+ return next_state, value
32793279+ else
32803280+ local meta = getmetatable(t)
32813281+ if (meta and meta.__index) then
32823282+ t = meta.__index
32833283+ return allpairs_next(t)
32843284+ end
32853285+ end
32863286+ end
32873287+ return allpairs_next
32883288+ end
32893289+ local function deref(self)
32903290+ return self[1]
32913291+ end
32923292+ local nil_sym = nil
32933293+ local function list__3estring(self, tostring2)
32943294+ local safe, max = {}, 0
32953295+ for k in pairs(self) do
32963296+ if ((type(k) == "number") and (k > max)) then
32973297+ max = k
32983298+ end
32993299+ end
33003300+ for i = 1, max do
33013301+ safe[i] = (((self[i] == nil) and nil_sym) or self[i])
33023302+ end
33033303+ return ("(" .. table.concat(map(safe, (tostring2 or tostring)), " ", 1, max) .. ")")
33043304+ end
33053305+ local symbol_mt = {"SYMBOL", __fennelview = deref, __tostring = deref}
33063306+ local expr_mt = {"EXPR", __tostring = deref}
33073307+ local list_mt = {"LIST", __fennelview = list__3estring, __tostring = list__3estring}
33083308+ local comment_mt = {"COMMENT", __fennelview = deref, __tostring = deref}
33093309+ local sequence_marker = {"SEQUENCE"}
33103310+ local vararg = setmetatable({"..."}, {"VARARG", __fennelview = deref, __tostring = deref})
33113311+ local getenv = nil
33123312+ local function _0_()
33133313+ return nil
33143314+ end
33153315+ getenv = ((os and os.getenv) or _0_)
33163316+ local function debug_on_3f(flag)
33173317+ local level = (getenv("FENNEL_DEBUG") or "")
33183318+ return ((level == "all") or level:find(flag))
33193319+ end
33203320+ local function list(...)
33213321+ return setmetatable({...}, list_mt)
33223322+ end
33233323+ local function sym(str, scope, source)
33243324+ local s = {str, scope = scope}
33253325+ for k, v in pairs((source or {})) do
33263326+ if (type(k) == "string") then
33273327+ s[k] = v
33283328+ end
33293329+ end
33303330+ return setmetatable(s, symbol_mt)
33313331+ end
33323332+ nil_sym = sym("nil")
33333333+ local function sequence(...)
33343334+ return setmetatable({...}, {sequence = sequence_marker})
33353335+ end
33363336+ local function expr(strcode, etype)
33373337+ return setmetatable({strcode, type = etype}, expr_mt)
33383338+ end
33393339+ local function comment_2a(contents)
33403340+ return setmetatable({contents}, comment_mt)
33413341+ end
33423342+ local function varg()
33433343+ return vararg
33443344+ end
33453345+ local function expr_3f(x)
33463346+ return ((type(x) == "table") and (getmetatable(x) == expr_mt) and x)
33473347+ end
33483348+ local function varg_3f(x)
33493349+ return ((x == vararg) and x)
33503350+ end
33513351+ local function list_3f(x)
33523352+ return ((type(x) == "table") and (getmetatable(x) == list_mt) and x)
33533353+ end
33543354+ local function sym_3f(x)
33553355+ return ((type(x) == "table") and (getmetatable(x) == symbol_mt) and x)
33563356+ end
33573357+ local function table_3f(x)
33583358+ return ((type(x) == "table") and (x ~= vararg) and (getmetatable(x) ~= list_mt) and (getmetatable(x) ~= symbol_mt) and x)
33593359+ end
33603360+ local function sequence_3f(x)
33613361+ local mt = ((type(x) == "table") and getmetatable(x))
33623362+ return (mt and (mt.sequence == sequence_marker) and x)
33633363+ end
33643364+ local function comment_3f(x)
33653365+ return ((type(x) == "table") and (getmetatable(x) == comment_mt) and x)
33663366+ end
33673367+ local function multi_sym_3f(str)
33683368+ if sym_3f(str) then
33693369+ return multi_sym_3f(tostring(str))
33703370+ elseif (type(str) ~= "string") then
33713371+ return false
33723372+ else
33733373+ local parts = {}
33743374+ for part in str:gmatch("[^%.%:]+[%.%:]?") do
33753375+ local last_char = part:sub(( - 1))
33763376+ if (last_char == ":") then
33773377+ parts["multi-sym-method-call"] = true
33783378+ end
33793379+ if ((last_char == ":") or (last_char == ".")) then
33803380+ parts[(#parts + 1)] = part:sub(1, ( - 2))
33813381+ else
33823382+ parts[(#parts + 1)] = part
33833383+ end
33843384+ end
33853385+ return ((#parts > 0) and (str:match("%.") or str:match(":")) and not str:match("%.%.") and (str:byte() ~= string.byte(".")) and (str:byte(( - 1)) ~= string.byte(".")) and parts)
33863386+ end
33873387+ end
33883388+ local function quoted_3f(symbol)
33893389+ return symbol.quoted
33903390+ end
33913391+ local function walk_tree(root, f, custom_iterator)
33923392+ local function walk(iterfn, parent, idx, node)
33933393+ if f(idx, node, parent) then
33943394+ for k, v in iterfn(node) do
33953395+ walk(iterfn, node, k, v)
33963396+ end
33973397+ return nil
33983398+ end
33993399+ end
34003400+ walk((custom_iterator or pairs), nil, nil, root)
34013401+ return root
34023402+ end
34033403+ 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"}
34043404+ for i, v in ipairs(lua_keywords) do
34053405+ lua_keywords[v] = i
34063406+ end
34073407+ local function valid_lua_identifier_3f(str)
34083408+ return (str:match("^[%a_][%w_]*$") and not lua_keywords[str])
34093409+ end
34103410+ local propagated_options = {"allowedGlobals", "indent", "correlate", "useMetadata", "env", "compiler-env", "compilerEnv"}
34113411+ local function propagate_options(options, subopts)
34123412+ for _, name in ipairs(propagated_options) do
34133413+ subopts[name] = options[name]
34143414+ end
34153415+ return subopts
34163416+ end
34173417+ local root = nil
34183418+ local function _1_()
34193419+ end
34203420+ root = {chunk = nil, options = nil, reset = _1_, scope = nil}
34213421+ root["set-reset"] = function(_2_0)
34223422+ local _3_ = _2_0
34233423+ local chunk = _3_["chunk"]
34243424+ local options = _3_["options"]
34253425+ local reset = _3_["reset"]
34263426+ local scope = _3_["scope"]
34273427+ root.reset = function()
34283428+ root.chunk, root.scope, root.options, root.reset = chunk, scope, options, reset
34293429+ return nil
34303430+ end
34313431+ return root.reset
34323432+ end
34333433+ local function hook(event, ...)
34343434+ if (root.options and root.options.plugins) then
34353435+ for _, plugin in ipairs(root.options.plugins) do
34363436+ local _3_0 = plugin[event]
34373437+ if (nil ~= _3_0) then
34383438+ local f = _3_0
34393439+ f(...)
34403440+ end
34413441+ end
34423442+ return nil
34433443+ end
34443444+ end
34453445+ return {["comment?"] = comment_3f, ["debug-on?"] = debug_on_3f, ["expr?"] = expr_3f, ["list?"] = list_3f, ["lua-keywords"] = lua_keywords, ["member?"] = member_3f, ["multi-sym?"] = multi_sym_3f, ["propagate-options"] = propagate_options, ["quoted?"] = quoted_3f, ["sequence?"] = sequence_3f, ["sym?"] = sym_3f, ["table?"] = table_3f, ["valid-lua-identifier?"] = valid_lua_identifier_3f, ["varg?"] = varg_3f, ["walk-tree"] = walk_tree, allpairs = allpairs, comment = comment_2a, copy = copy, deref = deref, expr = expr, hook = hook, kvmap = kvmap, list = list, map = map, path = table.concat({"./?.fnl", "./?/init.fnl", getenv("FENNEL_PATH")}, ";"), root = root, sequence = sequence, stablepairs = stablepairs, sym = sym, varg = varg}
34463446+end
34473447+utils = require("fennel.utils")
34483448+local parser = require("fennel.parser")
34493449+local compiler = require("fennel.compiler")
34503450+local specials = require("fennel.specials")
34513451+local repl = require("fennel.repl")
34523452+local view = require("fennel.view")
34533453+local function get_env(env)
34543454+ if (env == "_COMPILER") then
34553455+ local env0 = specials["make-compiler-env"](nil, compiler.scopes.compiler, {})
34563456+ local mt = getmetatable(env0)
34573457+ mt.__index = _G
34583458+ return specials["wrap-env"](env0)
34593459+ else
34603460+ return (env and specials["wrap-env"](env))
34613461+ end
34623462+end
34633463+local function eval(str, options, ...)
34643464+ local opts = utils.copy(options)
34653465+ local _ = nil
34663466+ if ((opts.allowedGlobals == nil) and not getmetatable(opts.env)) then
34673467+ opts.allowedGlobals = specials["current-global-names"](opts.env)
34683468+ _ = nil
34693469+ else
34703470+ _ = nil
34713471+ end
34723472+ local env = get_env(opts.env)
34733473+ local lua_source = compiler["compile-string"](str, opts)
34743474+ local loader = nil
34753475+ local function _1_(...)
34763476+ if opts.filename then
34773477+ return ("@" .. opts.filename)
34783478+ else
34793479+ return str
34803480+ end
34813481+ end
34823482+ loader = specials["load-code"](lua_source, env, _1_(...))
34833483+ opts.filename = nil
34843484+ return loader(...)
34853485+end
34863486+local function dofile_2a(filename, options, ...)
34873487+ local opts = utils.copy(options)
34883488+ local f = assert(io.open(filename, "rb"))
34893489+ local source = assert(f:read("*all"), ("Could not read " .. filename))
34903490+ f:close()
34913491+ opts.filename = filename
34923492+ return eval(source, opts, ...)
34933493+end
34943494+local mod = {["compile-stream"] = compiler["compile-stream"], ["compile-string"] = compiler["compile-string"], ["list?"] = utils["list?"], ["load-code"] = specials["load-code"], ["macro-loaded"] = specials["macro-loaded"], ["make-searcher"] = specials["make-searcher"], ["search-module"] = specials["search-module"], ["sequence?"] = utils["sequence?"], ["string-stream"] = parser["string-stream"], ["sym-char?"] = parser["sym-char?"], ["sym?"] = utils["sym?"], compile = compiler.compile, compile1 = compiler.compile1, compileStream = compiler["compile-stream"], compileString = compiler["compile-string"], doc = specials.doc, dofile = dofile_2a, eval = eval, gensym = compiler.gensym, granulate = parser.granulate, list = utils.list, loadCode = specials["load-code"], macroLoaded = specials["macro-loaded"], makeSearcher = specials["make-searcher"], make_searcher = specials["make-searcher"], mangle = compiler["global-mangling"], metadata = compiler.metadata, parser = parser.parser, path = utils.path, repl = repl, scope = compiler["make-scope"], searchModule = specials["search-module"], searcher = specials["make-searcher"](), sequence = utils.sequence, stringStream = parser["string-stream"], sym = utils.sym, traceback = compiler.traceback, unmangle = compiler["global-unmangling"], varg = utils.varg, version = "0.8.0", view = view}
34953495+utils["fennel-module"] = mod
34963496+do
34973497+ local builtin_macros = [===[;; This module contains all the built-in Fennel macros. Unlike all the other
34983498+ ;; modules that are loaded by the old bootstrap compiler, this runs in the
34993499+ ;; compiler scope of the version of the compiler being defined.
35003500+35013501+ ;; The code for these macros is somewhat idiosyncratic because it cannot use any
35023502+ ;; macros which have not yet been defined.
35033503+35043504+ ;; TODO: some of these macros modify their arguments; we should stop doing that,
35053505+ ;; but in a way that preserves file/line metadata.
35063506+35073507+ (fn -> [val ...]
35083508+ "Thread-first macro.
35093509+ Take the first value and splice it into the second form as its first argument.
35103510+ The value of the second form is spliced into the first arg of the third, etc."
35113511+ (var x val)
35123512+ (each [_ e (ipairs [...])]
35133513+ (let [elt (if (list? e) e (list e))]
35143514+ (table.insert elt 2 x)
35153515+ (set x elt)))
35163516+ x)
35173517+35183518+ (fn ->> [val ...]
35193519+ "Thread-last macro.
35203520+ Same as ->, except splices the value into the last position of each form
35213521+ rather than the first."
35223522+ (var x val)
35233523+ (each [_ e (pairs [...])]
35243524+ (let [elt (if (list? e) e (list e))]
35253525+ (table.insert elt x)
35263526+ (set x elt)))
35273527+ x)
35283528+35293529+ (fn -?> [val ...]
35303530+ "Nil-safe thread-first macro.
35313531+ Same as -> except will short-circuit with nil when it encounters a nil value."
35323532+ (if (= 0 (select "#" ...))
35333533+ val
35343534+ (let [els [...]
35353535+ e (table.remove els 1)
35363536+ el (if (list? e) e (list e))
35373537+ tmp (gensym)]
35383538+ (table.insert el 2 tmp)
35393539+ `(let [,tmp ,val]
35403540+ (if ,tmp
35413541+ (-?> ,el ,(unpack els))
35423542+ ,tmp)))))
35433543+35443544+ (fn -?>> [val ...]
35453545+ "Nil-safe thread-last macro.
35463546+ Same as ->> except will short-circuit with nil when it encounters a nil value."
35473547+ (if (= 0 (select "#" ...))
35483548+ val
35493549+ (let [els [...]
35503550+ e (table.remove els 1)
35513551+ el (if (list? e) e (list e))
35523552+ tmp (gensym)]
35533553+ (table.insert el tmp)
35543554+ `(let [,tmp ,val]
35553555+ (if ,tmp
35563556+ (-?>> ,el ,(unpack els))
35573557+ ,tmp)))))
35583558+35593559+ (fn doto [val ...]
35603560+ "Evaluates val and splices it into the first argument of subsequent forms."
35613561+ (let [name (gensym)
35623562+ form `(let [,name ,val])]
35633563+ (each [_ elt (pairs [...])]
35643564+ (table.insert elt 2 name)
35653565+ (table.insert form elt))
35663566+ (table.insert form name)
35673567+ form))
35683568+35693569+ (fn when [condition body1 ...]
35703570+ "Evaluate body for side-effects only when condition is truthy."
35713571+ (assert body1 "expected body")
35723572+ `(if ,condition
35733573+ (do ,body1 ,...)))
35743574+35753575+ (fn with-open [closable-bindings ...]
35763576+ "Like `let`, but invokes (v:close) on each binding after evaluating the body.
35773577+ The body is evaluated inside `xpcall` so that bound values will be closed upon
35783578+ encountering an error before propagating it."
35793579+ (let [bodyfn `(fn [] ,...)
35803580+ closer `(fn close-handlers# [ok# ...] (if ok# ...
35813581+ (error ... 0)))
35823582+ traceback `(. (or package.loaded.fennel debug) :traceback)]
35833583+ (for [i 1 (# closable-bindings) 2]
35843584+ (assert (sym? (. closable-bindings i))
35853585+ "with-open only allows symbols in bindings")
35863586+ (table.insert closer 4 `(: ,(. closable-bindings i) :close)))
35873587+ `(let ,closable-bindings ,closer
35883588+ (close-handlers# (xpcall ,bodyfn ,traceback)))))
35893589+35903590+ (fn collect [iter-tbl key-value-expr ...]
35913591+ "Returns a table made by running an iterator and evaluating an expression
35923592+ that returns key-value pairs to be inserted sequentially into the table.
35933593+ This can be thought of as a \"table comprehension\". The provided key-value
35943594+ expression must return either 2 values, or nil.
35953595+35963596+ For example,
35973597+ (collect [k v (pairs {:apple \"red\" :orange \"orange\"})]
35983598+ (values v k))
35993599+ returns
36003600+ {:red \"apple\" :orange \"orange\"}"
36013601+ (assert (and (sequence? iter-tbl) (>= (length iter-tbl) 2))
36023602+ "expected iterator binding table")
36033603+ (assert (not= nil key-value-expr)
36043604+ "expected key-value expression")
36053605+ (assert (= nil ...)
36063606+ "expected exactly one body expression. Wrap multiple expressions with do")
36073607+ `(let [tbl# {}]
36083608+ (each ,iter-tbl
36093609+ (match ,key-value-expr
36103610+ (k# v#) (tset tbl# k# v#)))
36113611+ tbl#))
36123612+36133613+ (fn icollect [iter-tbl value-expr ...]
36143614+ "Returns a sequential table made by running an iterator and evaluating an
36153615+ expression that returns values to be inserted sequentially into the table.
36163616+ This can be thought of as a \"list comprehension\".
36173617+36183618+ For example,
36193619+ (icollect [_ v (ipairs [1 2 3 4 5])] (when (> v 2) (* v v)))
36203620+ returns
36213621+ [9 16 25]"
36223622+ (assert (and (sequence? iter-tbl) (>= (length iter-tbl) 2))
36233623+ "expected iterator binding table")
36243624+ (assert (not= nil value-expr)
36253625+ "expected table value expression")
36263626+ (assert (= nil ...)
36273627+ "expected exactly one body expression. Wrap multiple expressions with do")
36283628+ `(let [tbl# []]
36293629+ (each ,iter-tbl
36303630+ (tset tbl# (+ (length tbl#) 1) ,value-expr))
36313631+ tbl#))
36323632+36333633+ (fn partial [f ...]
36343634+ "Returns a function with all arguments partially applied to f."
36353635+ (let [body (list f ...)]
36363636+ (table.insert body _VARARG)
36373637+ `(fn [,_VARARG] ,body)))
36383638+36393639+ (fn pick-args [n f]
36403640+ "Creates a function of arity n that applies its arguments to f.
36413641+36423642+ For example,
36433643+ (pick-args 2 func)
36443644+ expands to
36453645+ (fn [_0_ _1_] (func _0_ _1_))"
36463646+ (assert (and (= (type n) :number) (= n (math.floor n)) (>= n 0))
36473647+ "Expected n to be an integer literal >= 0.")
36483648+ (let [bindings []]
36493649+ (for [i 1 n] (tset bindings i (gensym)))
36503650+ `(fn ,bindings (,f ,(unpack bindings)))))
36513651+36523652+ (fn pick-values [n ...]
36533653+ "Like the `values` special, but emits exactly n values.
36543654+36553655+ For example,
36563656+ (pick-values 2 ...)
36573657+ expands to
36583658+ (let [(_0_ _1_) ...]
36593659+ (values _0_ _1_))"
36603660+ (assert (and (= :number (type n)) (>= n 0) (= n (math.floor n)))
36613661+ "Expected n to be an integer >= 0")
36623662+ (let [let-syms (list)
36633663+ let-values (if (= 1 (select :# ...)) ... `(values ,...))]
36643664+ (for [i 1 n] (table.insert let-syms (gensym)))
36653665+ (if (= n 0) `(values)
36663666+ `(let [,let-syms ,let-values] (values ,(unpack let-syms))))))
36673667+36683668+ (fn lambda [...]
36693669+ "Function literal with arity checking.
36703670+ Will throw an exception if a declared argument is passed in as nil, unless
36713671+ that argument name begins with ?."
36723672+ (let [args [...]
36733673+ has-internal-name? (sym? (. args 1))
36743674+ arglist (if has-internal-name? (. args 2) (. args 1))
36753675+ docstring-position (if has-internal-name? 3 2)
36763676+ has-docstring? (and (> (# args) docstring-position)
36773677+ (= :string (type (. args docstring-position))))
36783678+ arity-check-position (- 4 (if has-internal-name? 0 1)
36793679+ (if has-docstring? 0 1))
36803680+ empty-body? (< (# args) arity-check-position)]
36813681+ (fn check! [a]
36823682+ (if (table? a)
36833683+ (each [_ a (pairs a)]
36843684+ (check! a))
36853685+ (let [as (tostring a)]
36863686+ (and (not (as:match "^?")) (not= as "&") (not= as "_") (not= as "...")))
36873687+ (table.insert args arity-check-position
36883688+ `(assert (not= nil ,a)
36893689+ (string.format "Missing argument %s on %s:%s"
36903690+ ,(tostring a)
36913691+ ,(or a.filename "unknown")
36923692+ ,(or a.line "?"))))))
36933693+ (assert (= :table (type arglist)) "expected arg list")
36943694+ (each [_ a (ipairs arglist)]
36953695+ (check! a))
36963696+ (if empty-body?
36973697+ (table.insert args (sym :nil)))
36983698+ `(fn ,(unpack args))))
36993699+37003700+ (fn macro [name ...]
37013701+ "Define a single macro."
37023702+ (assert (sym? name) "expected symbol for macro name")
37033703+ (local args [...])
37043704+ `(macros { ,(tostring name) (fn ,(unpack args))}))
37053705+37063706+ (fn macrodebug [form return?]
37073707+ "Print the resulting form after performing macroexpansion.
37083708+ With a second argument, returns expanded form as a string instead of printing."
37093709+ (let [handle (if return? `do `print)]
37103710+ `(,handle ,(view (macroexpand form _SCOPE)))))
37113711+37123712+ (fn import-macros [binding1 module-name1 ...]
37133713+ "Binds a table of macros from each macro module according to a binding form.
37143714+ Each binding form can be either a symbol or a k/v destructuring table.
37153715+ Example:
37163716+ (import-macros mymacros :my-macros ; bind to symbol
37173717+ {:macro1 alias : macro2} :proj.macros) ; import by name"
37183718+ (assert (and binding1 module-name1 (= 0 (% (select :# ...) 2)))
37193719+ "expected even number of binding/modulename pairs")
37203720+ (for [i 1 (select :# binding1 module-name1 ...) 2]
37213721+ (let [(binding modname) (select i binding1 module-name1 ...)
37223722+ ;; generate a subscope of current scope, use require-macros
37233723+ ;; to bring in macro module. after that, we just copy the
37243724+ ;; macros from subscope to scope.
37253725+ scope (get-scope)
37263726+ subscope (fennel.scope scope)]
37273727+ (_SPECIALS.require-macros `(require-macros ,modname) subscope {} ast)
37283728+ (if (sym? binding)
37293729+ ;; bind whole table of macros to table bound to symbol
37303730+ (do (tset scope.macros (. binding 1) {})
37313731+ (each [k v (pairs subscope.macros)]
37323732+ (tset (. scope.macros (. binding 1)) k v)))
37333733+37343734+ ;; 1-level table destructuring for importing individual macros
37353735+ (table? binding)
37363736+ (each [macro-name [import-key] (pairs binding)]
37373737+ (assert (= :function (type (. subscope.macros macro-name)))
37383738+ (.. "macro " macro-name " not found in module "
37393739+ (tostring modname)))
37403740+ (tset scope.macros import-key (. subscope.macros macro-name))))))
37413741+ nil)
37423742+37433743+ ;;; Pattern matching
37443744+37453745+ (fn match-values [vals pattern unifications match-pattern]
37463746+ (let [condition `(and)
37473747+ bindings []]
37483748+ (each [i pat (ipairs pattern)]
37493749+ (let [(subcondition subbindings) (match-pattern [(. vals i)] pat
37503750+ unifications)]
37513751+ (table.insert condition subcondition)
37523752+ (each [_ b (ipairs subbindings)]
37533753+ (table.insert bindings b))))
37543754+ (values condition bindings)))
37553755+37563756+ (fn match-table [val pattern unifications match-pattern]
37573757+ (let [condition `(and (= (type ,val) :table))
37583758+ bindings []]
37593759+ (each [k pat (pairs pattern)]
37603760+ (if (and (sym? pat) (= "&" (tostring pat)))
37613761+ (do (assert (not (. pattern (+ k 2)))
37623762+ "expected rest argument before last parameter")
37633763+ (table.insert bindings (. pattern (+ k 1)))
37643764+ (table.insert bindings [`(select ,k ((or table.unpack
37653765+ _G.unpack)
37663766+ ,val))]))
37673767+ (and (= :number (type k))
37683768+ (= "&" (tostring (. pattern (- k 1)))))
37693769+ nil ; don't process the pattern right after &; already got it
37703770+ (let [subval `(. ,val ,k)
37713771+ (subcondition subbindings) (match-pattern [subval] pat
37723772+ unifications)]
37733773+ (table.insert condition subcondition)
37743774+ (each [_ b (ipairs subbindings)]
37753775+ (table.insert bindings b)))))
37763776+ (values condition bindings)))
37773777+37783778+ (fn match-pattern [vals pattern unifications]
37793779+ "Takes the AST of values and a single pattern and returns a condition
37803780+ to determine if it matches as well as a list of bindings to
37813781+ introduce for the duration of the body if it does match."
37823782+ ;; we have to assume we're matching against multiple values here until we
37833783+ ;; know we're either in a multi-valued clause (in which case we know the #
37843784+ ;; of vals) or we're not, in which case we only care about the first one.
37853785+ (let [[val] vals]
37863786+ (if (or (and (sym? pattern) ; unification with outer locals (or nil)
37873787+ (not= :_ (tostring pattern)) ; never unify _
37883788+ (or (in-scope? pattern)
37893789+ (= :nil (tostring pattern))))
37903790+ (and (multi-sym? pattern)
37913791+ (in-scope? (. (multi-sym? pattern) 1))))
37923792+ (values `(= ,val ,pattern) [])
37933793+ ;; unify a local we've seen already
37943794+ (and (sym? pattern) (. unifications (tostring pattern)))
37953795+ (values `(= ,(. unifications (tostring pattern)) ,val) [])
37963796+ ;; bind a fresh local
37973797+ (sym? pattern)
37983798+ (let [wildcard? (: (tostring pattern) :find "^_")]
37993799+ (if (not wildcard?) (tset unifications (tostring pattern) val))
38003800+ (values (if (or wildcard? (string.find (tostring pattern) "^?"))
38013801+ true `(not= ,(sym :nil) ,val))
38023802+ [pattern val]))
38033803+ ;; guard clause
38043804+ (and (list? pattern) (sym? (. pattern 2)) (= :? (tostring (. pattern 2))))
38053805+ (let [(pcondition bindings) (match-pattern vals (. pattern 1)
38063806+ unifications)
38073807+ condition `(and ,pcondition)]
38083808+ (for [i 3 (# pattern)] ; splice in guard clauses
38093809+ (table.insert condition (. pattern i)))
38103810+ (values `(let ,bindings ,condition) bindings))
38113811+38123812+ ;; multi-valued patterns (represented as lists)
38133813+ (list? pattern)
38143814+ (match-values vals pattern unifications match-pattern)
38153815+ ;; table patterns
38163816+ (= (type pattern) :table)
38173817+ (match-table val pattern unifications match-pattern)
38183818+ ;; literal value
38193819+ (values `(= ,val ,pattern) []))))
38203820+38213821+ (fn match-condition [vals clauses]
38223822+ "Construct the actual `if` AST for the given match values and clauses."
38233823+ (if (not= 0 (% (length clauses) 2)) ; treat odd final clause as default
38243824+ (table.insert clauses (length clauses) (sym :_)))
38253825+ (let [out `(if)]
38263826+ (for [i 1 (length clauses) 2]
38273827+ (let [pattern (. clauses i)
38283828+ body (. clauses (+ i 1))
38293829+ (condition bindings) (match-pattern vals pattern {})]
38303830+ (table.insert out condition)
38313831+ (table.insert out `(let ,bindings ,body))))
38323832+ out))
38333833+38343834+ (fn match-val-syms [clauses]
38353835+ "How many multi-valued clauses are there? return a list of that many gensyms."
38363836+ (let [syms (list (gensym))]
38373837+ (for [i 1 (length clauses) 2]
38383838+ (if (list? (. clauses i))
38393839+ (each [valnum (ipairs (. clauses i))]
38403840+ (if (not (. syms valnum))
38413841+ (tset syms valnum (gensym))))))
38423842+ syms))
38433843+38443844+ (fn match [val ...]
38453845+ "Perform pattern matching on val. See reference for details."
38463846+ (let [clauses [...]
38473847+ vals (match-val-syms clauses)]
38483848+ ;; protect against multiple evaluation of the value, bind against as
38493849+ ;; many values as we ever match against in the clauses.
38503850+ (list `let [vals val]
38513851+ (match-condition vals clauses))))
38523852+38533853+ {: -> : ->> : -?> : -?>>
38543854+ : doto : when : with-open
38553855+ : collect : icollect
38563856+ : partial : lambda
38573857+ : pick-args : pick-values
38583858+ : macro : macrodebug : import-macros
38593859+ : match}
38603860+ ]===]
38613861+ local module_name = "fennel.macros"
38623862+ local _ = nil
38633863+ local function _0_()
38643864+ return mod
38653865+ end
38663866+ package.preload[module_name] = _0_
38673867+ _ = nil
38683868+ local env = nil
38693869+ do
38703870+ local _1_0 = specials["make-compiler-env"](nil, compiler.scopes.compiler, {})
38713871+ _1_0["utils"] = utils
38723872+ _1_0["fennel"] = mod
38733873+ env = _1_0
38743874+ end
38753875+ local built_ins = eval(builtin_macros, {allowedGlobals = false, env = env, filename = "src/fennel/macros.fnl", moduleName = module_name, scope = compiler.scopes.compiler, useMetadata = true})
38763876+ for k, v in pairs(built_ins) do
38773877+ compiler.scopes.global.macros[k] = v
38783878+ end
38793879+ compiler.scopes.global.macros["\206\187"] = compiler.scopes.global.macros.lambda
38803880+ package.preload[module_name] = nil
38813881+end
38823882+return mod
+52
vim/.config/nvim/lua/utils.lua
···11+local function tbl_filter(func, t)
22+ vim.validate{func={func,'c'},t={t,'t'}}
33+44+ local rettab = {}
55+ for key, entry in pairs(t) do
66+ if func(key, entry) then
77+ rettab[key] = entry
88+ end
99+ end
1010+ return rettab
1111+end
1212+1313+local function normalise_map(rhs, opts)
1414+ -- If it is command line map, then automaticall add <C-u> for cleaning
1515+ -- selection and <CR> at the end, to fire it up
1616+ if vim.startswith(rhs, ':') and rhs ~= ':' then
1717+ if not vim.startswith(rhs, ':<C-u>') and options["selection"] then
1818+ rhs = '<cmd>' .. rhs:sub(2)
1919+ end
2020+ if not vim.endswith(rhs, '<CR>') and options["cr"] then
2121+ rhs = rhs .. '<CR>'
2222+ end
2323+ end
2424+2525+ return rhs
2626+end
2727+2828+local function do_map(cb)
2929+ return function(modes, lhs, rhs, opts)
3030+ -- Defaults to non recursive mappings
3131+ options = vim.tbl_extend('force', {noremap = true, selection = true, cr = true}, opts or {})
3232+3333+ if modes == '' then
3434+ error('Modes must not be empty')
3535+ end
3636+3737+ local f = function(k, _)
3838+ return not (k == "selection" or k == "cr")
3939+ end
4040+ local map_opts = tbl_filter(f, options)
4141+ local normalised = normalise_map(rhs, options)
4242+4343+ for mode in modes:gmatch('.') do
4444+ cb(mode, lhs, normalised, map_opts)
4545+ end
4646+ end
4747+end
4848+4949+return {
5050+ map = do_map(vim.api.nvim_set_keymap),
5151+ buf_map = do_map(function(...) vim.api.nvim_buf_set_keymap(0, ...) end)
5252+}