1package.preload["fennel.repl"] = package.preload["fennel.repl"] or function(...) 2 local utils = require("fennel.utils") 3 local parser = require("fennel.parser") 4 local compiler = require("fennel.compiler") 5 local specials = require("fennel.specials") 6 local view = require("fennel.view") 7 local unpack = (table.unpack or _G.unpack) 8 local function default_read_chunk(parser_state) 9 local function _520_() 10 if (0 < parser_state["stack-size"]) then 11 return ".." 12 else 13 return ">> " 14 end 15 end 16 io.write(_520_()) 17 io.flush() 18 local input = io.read() 19 return (input and (input .. "\n")) 20 end 21 local function default_on_values(xs) 22 io.write(table.concat(xs, "\9")) 23 return io.write("\n") 24 end 25 local function default_on_error(errtype, err, lua_source) 26 local function _522_() 27 local _521_ = errtype 28 if (_521_ == "Lua Compile") then 29 return ("Bad code generated - likely a bug with the compiler:\n" .. "--- Generated Lua Start ---\n" .. lua_source .. "--- Generated Lua End ---\n") 30 elseif (_521_ == "Runtime") then 31 return (compiler.traceback(tostring(err), 4) .. "\n") 32 elseif true then 33 local _ = _521_ 34 return ("%s error: %s\n"):format(errtype, tostring(err)) 35 else 36 return nil 37 end 38 end 39 return io.write(_522_()) 40 end 41 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") 42 local function splice_save_locals(env, lua_source) 43 local spliced_source = {} 44 local bind = "local %s = ___replLocals___['%s']" 45 for line in lua_source:gmatch("([^\n]+)\n?") do 46 table.insert(spliced_source, line) 47 end 48 for name in pairs(env.___replLocals___) do 49 table.insert(spliced_source, 1, bind:format(name, name)) 50 end 51 if ((1 < #spliced_source) and (spliced_source[#spliced_source]):match("^ *return .*$")) then 52 table.insert(spliced_source, #spliced_source, save_source) 53 else 54 end 55 return table.concat(spliced_source, "\n") 56 end 57 local function completer(env, scope, text) 58 local matches = {} 59 local input_fragment = text:gsub(".*[%s)(]+", "") 60 local stop_looking_3f = false 61 local function add_partials(input, tbl, prefix, method_3f) 62 for k in utils.allpairs(tbl) do 63 local k0 64 if ((tbl == env) or (tbl == env.___replLocals___)) then 65 k0 = scope.unmanglings[k] 66 else 67 k0 = k 68 end 69 if ((#matches < 2000) and (type(k0) == "string") and (input == k0:sub(0, #input)) and (not method_3f or ("function" == type(tbl[k0])))) then 70 local function _526_() 71 if method_3f then 72 return (prefix .. ":" .. k0) 73 else 74 return (prefix .. k0) 75 end 76 end 77 table.insert(matches, _526_()) 78 else 79 end 80 end 81 return nil 82 end 83 local function descend(input, tbl, prefix, add_matches, method_3f) 84 local splitter 85 if method_3f then 86 splitter = "^([^:]+):(.*)" 87 else 88 splitter = "^([^.]+)%.(.*)" 89 end 90 local head, tail = input:match(splitter) 91 local raw_head = (scope.manglings[head] or head) 92 if (type(tbl[raw_head]) == "table") then 93 stop_looking_3f = true 94 if method_3f then 95 return add_partials(tail, tbl[raw_head], (prefix .. head), true) 96 else 97 return add_matches(tail, tbl[raw_head], (prefix .. head)) 98 end 99 else 100 return nil 101 end 102 end 103 local function add_matches(input, tbl, prefix) 104 local prefix0 105 if prefix then 106 prefix0 = (prefix .. ".") 107 else 108 prefix0 = "" 109 end 110 if (not input:find("%.") and input:find(":")) then 111 return descend(input, tbl, prefix0, add_matches, true) 112 elseif not input:find("%.") then 113 return add_partials(input, tbl, prefix0) 114 else 115 return descend(input, tbl, prefix0, add_matches, false) 116 end 117 end 118 for _, source in ipairs({scope.specials, scope.macros, (env.___replLocals___ or {}), env, env._G}) do 119 if stop_looking_3f then break end 120 add_matches(input_fragment, source) 121 end 122 return matches 123 end 124 local commands = {} 125 local function command_3f(input) 126 return input:match("^%s*,") 127 end 128 local function command_docs() 129 local _533_ 130 do 131 local tbl_14_auto = {} 132 local i_15_auto = #tbl_14_auto 133 for name, f in pairs(commands) do 134 local val_16_auto = (" ,%s - %s"):format(name, ((compiler.metadata):get(f, "fnl/docstring") or "undocumented")) 135 if (nil ~= val_16_auto) then 136 i_15_auto = (i_15_auto + 1) 137 do end (tbl_14_auto)[i_15_auto] = val_16_auto 138 else 139 end 140 end 141 _533_ = tbl_14_auto 142 end 143 return table.concat(_533_, "\n") 144 end 145 commands.help = function(_, _0, on_values) 146 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")}) 147 end 148 do end (compiler.metadata):set(commands.help, "fnl/docstring", "Show this message.") 149 local function reload(module_name, env, on_values, on_error) 150 local _535_, _536_ = pcall(specials["load-code"]("return require(...)", env), module_name) 151 if ((_535_ == true) and (nil ~= _536_)) then 152 local old = _536_ 153 local _ 154 package.loaded[module_name] = nil 155 _ = nil 156 local ok, new = pcall(require, module_name) 157 local new0 158 if not ok then 159 on_values({new}) 160 new0 = old 161 else 162 new0 = new 163 end 164 if ((type(old) == "table") and (type(new0) == "table")) then 165 for k, v in pairs(new0) do 166 old[k] = v 167 end 168 for k in pairs(old) do 169 if (nil == (new0)[k]) then 170 old[k] = nil 171 else 172 end 173 end 174 package.loaded[module_name] = old 175 else 176 end 177 return on_values({"ok"}) 178 elseif ((_535_ == false) and (nil ~= _536_)) then 179 local msg = _536_ 180 local function _541_() 181 local _540_ = msg:gsub("\n.*", "") 182 return _540_ 183 end 184 return on_error("Runtime", _541_()) 185 else 186 return nil 187 end 188 end 189 local function run_command(read, on_error, f) 190 local _543_, _544_, _545_ = pcall(read) 191 if ((_543_ == true) and (_544_ == true) and (nil ~= _545_)) then 192 local val = _545_ 193 return f(val) 194 elseif (_543_ == false) then 195 return on_error("Parse", "Couldn't parse input.") 196 else 197 return nil 198 end 199 end 200 commands.reload = function(env, read, on_values, on_error) 201 local function _547_(_241) 202 return reload(tostring(_241), env, on_values, on_error) 203 end 204 return run_command(read, on_error, _547_) 205 end 206 do end (compiler.metadata):set(commands.reload, "fnl/docstring", "Reload the specified module.") 207 commands.reset = function(env, _, on_values) 208 env.___replLocals___ = {} 209 return on_values({"ok"}) 210 end 211 do end (compiler.metadata):set(commands.reset, "fnl/docstring", "Erase all repl-local scope.") 212 commands.complete = function(env, read, on_values, on_error, scope, chars) 213 local function _548_() 214 return on_values(completer(env, scope, string.char(unpack(chars)):gsub(",complete +", ""):sub(1, -2))) 215 end 216 return run_command(read, on_error, _548_) 217 end 218 do end (compiler.metadata):set(commands.complete, "fnl/docstring", "Print all possible completions for a given input symbol.") 219 local function apropos_2a(pattern, tbl, prefix, seen, names) 220 for name, subtbl in pairs(tbl) do 221 if (("string" == type(name)) and (package ~= subtbl)) then 222 local _549_ = type(subtbl) 223 if (_549_ == "function") then 224 if ((prefix .. name)):match(pattern) then 225 table.insert(names, (prefix .. name)) 226 else 227 end 228 elseif (_549_ == "table") then 229 if not seen[subtbl] then 230 local _552_ 231 do 232 local _551_ = seen 233 _551_[subtbl] = true 234 _552_ = _551_ 235 end 236 apropos_2a(pattern, subtbl, (prefix .. name:gsub("%.", "/") .. "."), _552_, names) 237 else 238 end 239 else 240 end 241 else 242 end 243 end 244 return names 245 end 246 local function apropos(pattern) 247 local names = apropos_2a(pattern, package.loaded, "", {}, {}) 248 local tbl_14_auto = {} 249 local i_15_auto = #tbl_14_auto 250 for _, name in ipairs(names) do 251 local val_16_auto = name:gsub("^_G%.", "") 252 if (nil ~= val_16_auto) then 253 i_15_auto = (i_15_auto + 1) 254 do end (tbl_14_auto)[i_15_auto] = val_16_auto 255 else 256 end 257 end 258 return tbl_14_auto 259 end 260 commands.apropos = function(_env, read, on_values, on_error, _scope) 261 local function _557_(_241) 262 return on_values(apropos(tostring(_241))) 263 end 264 return run_command(read, on_error, _557_) 265 end 266 do end (compiler.metadata):set(commands.apropos, "fnl/docstring", "Print all functions matching a pattern in all loaded modules.") 267 local function apropos_follow_path(path) 268 local paths 269 do 270 local tbl_14_auto = {} 271 local i_15_auto = #tbl_14_auto 272 for p in path:gmatch("[^%.]+") do 273 local val_16_auto = p 274 if (nil ~= val_16_auto) then 275 i_15_auto = (i_15_auto + 1) 276 do end (tbl_14_auto)[i_15_auto] = val_16_auto 277 else 278 end 279 end 280 paths = tbl_14_auto 281 end 282 local tgt = package.loaded 283 for _, path0 in ipairs(paths) do 284 if (nil == tgt) then break end 285 local _560_ 286 do 287 local _559_ = path0:gsub("%/", ".") 288 _560_ = _559_ 289 end 290 tgt = tgt[_560_] 291 end 292 return tgt 293 end 294 local function apropos_doc(pattern) 295 local names = {} 296 for _, path in ipairs(apropos(".*")) do 297 local tgt = apropos_follow_path(path) 298 if ("function" == type(tgt)) then 299 local _561_ = (compiler.metadata):get(tgt, "fnl/docstring") 300 if (nil ~= _561_) then 301 local docstr = _561_ 302 if docstr:match(pattern) then 303 table.insert(names, path) 304 else 305 end 306 else 307 end 308 else 309 end 310 end 311 return names 312 end 313 commands["apropos-doc"] = function(_env, read, on_values, on_error, _scope) 314 local function _565_(_241) 315 return on_values(apropos_doc(tostring(_241))) 316 end 317 return run_command(read, on_error, _565_) 318 end 319 do end (compiler.metadata):set(commands["apropos-doc"], "fnl/docstring", "Print all functions that match the pattern in their docs") 320 local function apropos_show_docs(on_values, pattern) 321 for _, path in ipairs(apropos(pattern)) do 322 local tgt = apropos_follow_path(path) 323 if (("function" == type(tgt)) and (compiler.metadata):get(tgt, "fnl/docstring")) then 324 on_values(specials.doc(tgt, path)) 325 on_values() 326 else 327 end 328 end 329 return nil 330 end 331 commands["apropos-show-docs"] = function(_env, read, on_values, on_error) 332 local function _567_(_241) 333 return apropos_show_docs(on_values, tostring(_241)) 334 end 335 return run_command(read, on_error, _567_) 336 end 337 do end (compiler.metadata):set(commands["apropos-show-docs"], "fnl/docstring", "Print all documentations matching a pattern in function name") 338 local function resolve(identifier, _568_, scope) 339 local _arg_569_ = _568_ 340 local ___replLocals___ = _arg_569_["___replLocals___"] 341 local env = _arg_569_ 342 local e 343 local function _570_(_241, _242) 344 return (___replLocals___[_242] or env[_242]) 345 end 346 e = setmetatable({}, {__index = _570_}) 347 local code = compiler["compile-string"](tostring(identifier), {scope = scope}) 348 return specials["load-code"](code, e)() 349 end 350 commands.find = function(env, read, on_values, on_error, scope) 351 local function _571_(_241) 352 local _572_ 353 do 354 local _573_ = utils["sym?"](_241) 355 if (nil ~= _573_) then 356 local _574_ = resolve(_573_, env, scope) 357 if (nil ~= _574_) then 358 _572_ = debug.getinfo(_574_) 359 else 360 _572_ = _574_ 361 end 362 else 363 _572_ = _573_ 364 end 365 end 366 if ((_G.type(_572_) == "table") and (nil ~= (_572_).short_src) and (nil ~= (_572_).source) and (nil ~= (_572_).linedefined) and ((_572_).what == "Lua")) then 367 local src = (_572_).short_src 368 local source = (_572_).source 369 local line = (_572_).linedefined 370 local fnlsrc 371 do 372 local t_577_ = compiler.sourcemap 373 if (nil ~= t_577_) then 374 t_577_ = (t_577_)[source] 375 else 376 end 377 if (nil ~= t_577_) then 378 t_577_ = (t_577_)[line] 379 else 380 end 381 if (nil ~= t_577_) then 382 t_577_ = (t_577_)[2] 383 else 384 end 385 fnlsrc = t_577_ 386 end 387 return on_values({string.format("%s:%s", src, (fnlsrc or line))}) 388 elseif (_572_ == nil) then 389 return on_error("Repl", "Unknown value") 390 elseif true then 391 local _ = _572_ 392 return on_error("Repl", "No source info") 393 else 394 return nil 395 end 396 end 397 return run_command(read, on_error, _571_) 398 end 399 do end (compiler.metadata):set(commands.find, "fnl/docstring", "Print the filename and line number for a given function") 400 commands.doc = function(env, read, on_values, on_error, scope) 401 local function _582_(_241) 402 local name = tostring(_241) 403 local target = (scope.specials[name] or scope.macros[name] or resolve(name, env, scope)) 404 return on_values({specials.doc(target, name)}) 405 end 406 return run_command(read, on_error, _582_) 407 end 408 do end (compiler.metadata):set(commands.doc, "fnl/docstring", "Print the docstring and arglist for a function, macro, or special form.") 409 local function load_plugin_commands(plugins) 410 for _, plugin in ipairs((plugins or {})) do 411 for name, f in pairs(plugin) do 412 local _583_ = name:match("^repl%-command%-(.*)") 413 if (nil ~= _583_) then 414 local cmd_name = _583_ 415 commands[cmd_name] = (commands[cmd_name] or f) 416 else 417 end 418 end 419 end 420 return nil 421 end 422 local function run_command_loop(input, read, loop, env, on_values, on_error, scope, chars) 423 local command_name = input:match(",([^%s/]+)") 424 do 425 local _585_ = commands[command_name] 426 if (nil ~= _585_) then 427 local command = _585_ 428 command(env, read, on_values, on_error, scope, chars) 429 elseif true then 430 local _ = _585_ 431 if ("exit" ~= command_name) then 432 on_values({"Unknown command", command_name}) 433 else 434 end 435 else 436 end 437 end 438 if ("exit" ~= command_name) then 439 return loop() 440 else 441 return nil 442 end 443 end 444 local function repl(options) 445 local old_root_options = utils.root.options 446 local env 447 if options.env then 448 env = specials["wrap-env"](options.env) 449 else 450 env = setmetatable({}, {__index = (rawget(_G, "_ENV") or _G)}) 451 end 452 local save_locals_3f = ((options.saveLocals ~= false) and env.debug and env.debug.getlocal) 453 local opts = utils.copy(options) 454 local read_chunk = (opts.readChunk or default_read_chunk) 455 local on_values = (opts.onValues or default_on_values) 456 local on_error = (opts.onError or default_on_error) 457 local pp = (opts.pp or view) 458 local byte_stream, clear_stream = parser.granulate(read_chunk) 459 local chars = {} 460 local read, reset = nil, nil 461 local function _590_(parser_state) 462 local c = byte_stream(parser_state) 463 table.insert(chars, c) 464 return c 465 end 466 read, reset = parser.parser(_590_) 467 opts.env, opts.scope = env, compiler["make-scope"]() 468 opts.useMetadata = (options.useMetadata ~= false) 469 if (opts.allowedGlobals == nil) then 470 opts.allowedGlobals = specials["current-global-names"](opts.env) 471 else 472 end 473 if opts.registerCompleter then 474 local function _594_() 475 local _592_ = env 476 local _593_ = opts.scope 477 local function _595_(...) 478 return completer(_592_, _593_, ...) 479 end 480 return _595_ 481 end 482 opts.registerCompleter(_594_()) 483 else 484 end 485 load_plugin_commands(opts.plugins) 486 if save_locals_3f then 487 local function newindex(t, k, v) 488 if opts.scope.unmanglings[k] then 489 return rawset(t, k, v) 490 else 491 return nil 492 end 493 end 494 env.___replLocals___ = setmetatable({}, {__newindex = newindex}) 495 else 496 end 497 local function print_values(...) 498 local vals = {...} 499 local out = {} 500 env._, env.__ = vals[1], vals 501 for i = 1, select("#", ...) do 502 table.insert(out, pp(vals[i])) 503 end 504 return on_values(out) 505 end 506 local function loop() 507 for k in pairs(chars) do 508 chars[k] = nil 509 end 510 reset() 511 local ok, parse_ok_3f, x = pcall(read) 512 local src_string = string.char(unpack(chars)) 513 if not ok then 514 on_error("Parse", parse_ok_3f) 515 clear_stream() 516 return loop() 517 elseif command_3f(src_string) then 518 return run_command_loop(src_string, read, loop, env, on_values, on_error, opts.scope, chars) 519 else 520 if parse_ok_3f then 521 do 522 local _599_, _600_ = nil, nil 523 local function _602_() 524 local _601_ = opts 525 _601_["source"] = src_string 526 return _601_ 527 end 528 _599_, _600_ = pcall(compiler.compile, x, _602_()) 529 if ((_599_ == false) and (nil ~= _600_)) then 530 local msg = _600_ 531 clear_stream() 532 on_error("Compile", msg) 533 elseif ((_599_ == true) and (nil ~= _600_)) then 534 local src = _600_ 535 local src0 536 if save_locals_3f then 537 src0 = splice_save_locals(env, src, opts.scope) 538 else 539 src0 = src 540 end 541 local _604_, _605_ = pcall(specials["load-code"], src0, env) 542 if ((_604_ == false) and (nil ~= _605_)) then 543 local msg = _605_ 544 clear_stream() 545 on_error("Lua Compile", msg, src0) 546 elseif (true and (nil ~= _605_)) then 547 local _ = _604_ 548 local chunk = _605_ 549 local function _606_() 550 return print_values(chunk()) 551 end 552 local function _607_() 553 local function _608_(...) 554 return on_error("Runtime", ...) 555 end 556 return _608_ 557 end 558 xpcall(_606_, _607_()) 559 else 560 end 561 else 562 end 563 end 564 utils.root.options = old_root_options 565 return loop() 566 else 567 return nil 568 end 569 end 570 end 571 return loop() 572 end 573 return repl 574end 575package.preload["fennel.specials"] = package.preload["fennel.specials"] or function(...) 576 local utils = require("fennel.utils") 577 local view = require("fennel.view") 578 local parser = require("fennel.parser") 579 local compiler = require("fennel.compiler") 580 local unpack = (table.unpack or _G.unpack) 581 local SPECIALS = compiler.scopes.global.specials 582 local function wrap_env(env) 583 local function _345_(_, key) 584 if (type(key) == "string") then 585 return env[compiler["global-unmangling"](key)] 586 else 587 return env[key] 588 end 589 end 590 local function _347_(_, key, value) 591 if (type(key) == "string") then 592 env[compiler["global-unmangling"](key)] = value 593 return nil 594 else 595 env[key] = value 596 return nil 597 end 598 end 599 local function _349_() 600 local function putenv(k, v) 601 local _350_ 602 if (type(k) == "string") then 603 _350_ = compiler["global-unmangling"](k) 604 else 605 _350_ = k 606 end 607 return _350_, v 608 end 609 return next, utils.kvmap(env, putenv), nil 610 end 611 return setmetatable({}, {__index = _345_, __newindex = _347_, __pairs = _349_}) 612 end 613 local function current_global_names(_3fenv) 614 local mt 615 do 616 local _352_ = getmetatable(_3fenv) 617 local function _353_() 618 local __pairs = (_352_).__pairs 619 return __pairs 620 end 621 if (((_G.type(_352_) == "table") and true) and _353_()) then 622 local __pairs = (_352_).__pairs 623 local tbl_11_auto = {} 624 for k, v in __pairs(_3fenv) do 625 local _354_, _355_ = k, v 626 if ((nil ~= _354_) and (nil ~= _355_)) then 627 local k_12_auto = _354_ 628 local v_13_auto = _355_ 629 tbl_11_auto[k_12_auto] = v_13_auto 630 else 631 end 632 end 633 mt = tbl_11_auto 634 elseif (_352_ == nil) then 635 mt = (_3fenv or _G) 636 else 637 mt = nil 638 end 639 end 640 return (mt and utils.kvmap(mt, compiler["global-unmangling"])) 641 end 642 local function load_code(code, _3fenv, _3ffilename) 643 local env = (_3fenv or rawget(_G, "_ENV") or _G) 644 if (rawget(_G, "setfenv") and rawget(_G, "loadstring")) then 645 local f = assert(_G.loadstring(code, _3ffilename)) 646 local _358_ = f 647 setfenv(_358_, env) 648 return _358_ 649 else 650 return assert(load(code, _3ffilename, "t", env)) 651 end 652 end 653 local function doc_2a(tgt, name) 654 if not tgt then 655 return (name .. " not found") 656 else 657 local docstring = (((compiler.metadata):get(tgt, "fnl/docstring") or "#<undocumented>")):gsub("\n$", ""):gsub("\n", "\n ") 658 local mt = getmetatable(tgt) 659 if ((type(tgt) == "function") or ((type(mt) == "table") and (type(mt.__call) == "function"))) then 660 local arglist = table.concat(((compiler.metadata):get(tgt, "fnl/arglist") or {"#<unknown-arguments>"}), " ") 661 local _360_ 662 if (#arglist > 0) then 663 _360_ = " " 664 else 665 _360_ = "" 666 end 667 return string.format("(%s%s%s)\n %s", name, _360_, arglist, docstring) 668 else 669 return string.format("%s\n %s", name, docstring) 670 end 671 end 672 end 673 local function doc_special(name, arglist, docstring, body_form_3f) 674 compiler.metadata[SPECIALS[name]] = {["fnl/arglist"] = arglist, ["fnl/docstring"] = docstring, ["fnl/body-form?"] = body_form_3f} 675 return nil 676 end 677 local function compile_do(ast, scope, parent, _3fstart) 678 local start = (_3fstart or 2) 679 local len = #ast 680 local sub_scope = compiler["make-scope"](scope) 681 for i = start, len do 682 compiler.compile1(ast[i], sub_scope, parent, {nval = 0}) 683 end 684 return nil 685 end 686 SPECIALS["do"] = function(ast, scope, parent, opts, _3fstart, _3fchunk, _3fsub_scope, _3fpre_syms) 687 local start = (_3fstart or 2) 688 local sub_scope = (_3fsub_scope or compiler["make-scope"](scope)) 689 local chunk = (_3fchunk or {}) 690 local len = #ast 691 local retexprs = {returned = true} 692 local function compile_body(outer_target, outer_tail, outer_retexprs) 693 if (len < start) then 694 compiler.compile1(nil, sub_scope, chunk, {tail = outer_tail, target = outer_target}) 695 else 696 for i = start, len do 697 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)} 698 local _ = utils["propagate-options"](opts, subopts) 699 local subexprs = compiler.compile1(ast[i], sub_scope, chunk, subopts) 700 if (i ~= len) then 701 compiler["keep-side-effects"](subexprs, parent, nil, ast[i]) 702 else 703 end 704 end 705 end 706 compiler.emit(parent, chunk, ast) 707 compiler.emit(parent, "end", ast) 708 utils.hook("do", ast, sub_scope) 709 return (outer_retexprs or retexprs) 710 end 711 if (opts.target or (opts.nval == 0) or opts.tail) then 712 compiler.emit(parent, "do", ast) 713 return compile_body(opts.target, opts.tail) 714 elseif opts.nval then 715 local syms = {} 716 for i = 1, opts.nval do 717 local s = ((_3fpre_syms and (_3fpre_syms)[i]) or compiler.gensym(scope)) 718 do end (syms)[i] = s 719 retexprs[i] = utils.expr(s, "sym") 720 end 721 local outer_target = table.concat(syms, ", ") 722 compiler.emit(parent, string.format("local %s", outer_target), ast) 723 compiler.emit(parent, "do", ast) 724 return compile_body(outer_target, opts.tail) 725 else 726 local fname = compiler.gensym(scope) 727 local fargs 728 if scope.vararg then 729 fargs = "..." 730 else 731 fargs = "" 732 end 733 compiler.emit(parent, string.format("local function %s(%s)", fname, fargs), ast) 734 return compile_body(nil, true, utils.expr((fname .. "(" .. fargs .. ")"), "statement")) 735 end 736 end 737 doc_special("do", {"..."}, "Evaluate multiple forms; return last value.", true) 738 SPECIALS.values = function(ast, scope, parent) 739 local len = #ast 740 local exprs = {} 741 for i = 2, len do 742 local subexprs = compiler.compile1(ast[i], scope, parent, {nval = ((i ~= len) and 1)}) 743 table.insert(exprs, subexprs[1]) 744 if (i == len) then 745 for j = 2, #subexprs do 746 table.insert(exprs, subexprs[j]) 747 end 748 else 749 end 750 end 751 return exprs 752 end 753 doc_special("values", {"..."}, "Return multiple values from a function. Must be in tail position.") 754 local function deep_tostring(x, key_3f) 755 if utils["sequence?"](x) then 756 local _369_ 757 do 758 local tbl_14_auto = {} 759 local i_15_auto = #tbl_14_auto 760 for _, v in ipairs(x) do 761 local val_16_auto = deep_tostring(v) 762 if (nil ~= val_16_auto) then 763 i_15_auto = (i_15_auto + 1) 764 do end (tbl_14_auto)[i_15_auto] = val_16_auto 765 else 766 end 767 end 768 _369_ = tbl_14_auto 769 end 770 return ("[" .. table.concat(_369_, " ") .. "]") 771 elseif utils["table?"](x) then 772 local _371_ 773 do 774 local tbl_14_auto = {} 775 local i_15_auto = #tbl_14_auto 776 for k, v in pairs(x) do 777 local val_16_auto = (deep_tostring(k, true) .. " " .. deep_tostring(v)) 778 if (nil ~= val_16_auto) then 779 i_15_auto = (i_15_auto + 1) 780 do end (tbl_14_auto)[i_15_auto] = val_16_auto 781 else 782 end 783 end 784 _371_ = tbl_14_auto 785 end 786 return ("{" .. table.concat(_371_, " ") .. "}") 787 elseif (key_3f and (type(x) == "string") and x:find("^[-%w?\\^_!$%&*+./@:|<=>]+$")) then 788 return (":" .. x) 789 elseif (type(x) == "string") then 790 return string.format("%q", x):gsub("\\\"", "\\\\\""):gsub("\"", "\\\"") 791 else 792 return tostring(x) 793 end 794 end 795 local function set_fn_metadata(arg_list, docstring, parent, fn_name) 796 if utils.root.options.useMetadata then 797 local args 798 local function _374_(_241) 799 return ("\"%s\""):format(deep_tostring(_241)) 800 end 801 args = utils.map(arg_list, _374_) 802 local meta_fields = {"\"fnl/arglist\"", ("{" .. table.concat(args, ", ") .. "}")} 803 if docstring then 804 table.insert(meta_fields, "\"fnl/docstring\"") 805 table.insert(meta_fields, ("\"" .. docstring:gsub("%s+$", ""):gsub("\\", "\\\\"):gsub("\n", "\\n"):gsub("\"", "\\\"") .. "\"")) 806 else 807 end 808 local meta_str = ("require(\"%s\").metadata"):format((utils.root.options.moduleName or "fennel")) 809 return compiler.emit(parent, ("pcall(function() %s:setall(%s, %s) end)"):format(meta_str, fn_name, table.concat(meta_fields, ", "))) 810 else 811 return nil 812 end 813 end 814 local function get_fn_name(ast, scope, fn_name, multi) 815 if (fn_name and (fn_name[1] ~= "nil")) then 816 local _377_ 817 if not multi then 818 _377_ = compiler["declare-local"](fn_name, {}, scope, ast) 819 else 820 _377_ = (compiler["symbol-to-expression"](fn_name, scope))[1] 821 end 822 return _377_, not multi, 3 823 else 824 return nil, true, 2 825 end 826 end 827 local function compile_named_fn(ast, f_scope, f_chunk, parent, index, fn_name, local_3f, arg_name_list, arg_list, docstring) 828 for i = (index + 1), #ast do 829 compiler.compile1(ast[i], f_scope, f_chunk, {nval = (((i ~= #ast) and 0) or nil), tail = (i == #ast)}) 830 end 831 local _380_ 832 if local_3f then 833 _380_ = "local function %s(%s)" 834 else 835 _380_ = "%s = function(%s)" 836 end 837 compiler.emit(parent, string.format(_380_, fn_name, table.concat(arg_name_list, ", ")), ast) 838 compiler.emit(parent, f_chunk, ast) 839 compiler.emit(parent, "end", ast) 840 set_fn_metadata(arg_list, docstring, parent, fn_name) 841 utils.hook("fn", ast, f_scope) 842 return utils.expr(fn_name, "sym") 843 end 844 local function compile_anonymous_fn(ast, f_scope, f_chunk, parent, index, arg_name_list, arg_list, docstring, scope) 845 local fn_name = compiler.gensym(scope) 846 return compile_named_fn(ast, f_scope, f_chunk, parent, index, fn_name, true, arg_name_list, arg_list, docstring) 847 end 848 SPECIALS.fn = function(ast, scope, parent) 849 local f_scope 850 do 851 local _382_ = compiler["make-scope"](scope) 852 do end (_382_)["vararg"] = false 853 f_scope = _382_ 854 end 855 local f_chunk = {} 856 local fn_sym = utils["sym?"](ast[2]) 857 local multi = (fn_sym and utils["multi-sym?"](fn_sym[1])) 858 local fn_name, local_3f, index = get_fn_name(ast, scope, fn_sym, multi) 859 local arg_list = compiler.assert(utils["table?"](ast[index]), "expected parameters table", ast) 860 compiler.assert((not multi or not multi["multi-sym-method-call"]), ("unexpected multi symbol " .. tostring(fn_name)), fn_sym) 861 local function get_arg_name(arg) 862 if utils["varg?"](arg) then 863 compiler.assert((arg == arg_list[#arg_list]), "expected vararg as last parameter", ast) 864 f_scope.vararg = true 865 return "..." 866 elseif (utils["sym?"](arg) and (tostring(arg) ~= "nil") and not utils["multi-sym?"](tostring(arg))) then 867 return compiler["declare-local"](arg, {}, f_scope, ast) 868 elseif utils["table?"](arg) then 869 local raw = utils.sym(compiler.gensym(scope)) 870 local declared = compiler["declare-local"](raw, {}, f_scope, ast) 871 compiler.destructure(arg, raw, ast, f_scope, f_chunk, {declaration = true, nomulti = true, symtype = "arg"}) 872 return declared 873 else 874 return compiler.assert(false, ("expected symbol for function parameter: %s"):format(tostring(arg)), ast[index]) 875 end 876 end 877 local arg_name_list = utils.map(arg_list, get_arg_name) 878 local index0, docstring = nil, nil 879 if ((type(ast[(index + 1)]) == "string") and ((index + 1) < #ast)) then 880 index0, docstring = (index + 1), ast[(index + 1)] 881 else 882 index0, docstring = index, nil 883 end 884 if fn_name then 885 return compile_named_fn(ast, f_scope, f_chunk, parent, index0, fn_name, local_3f, arg_name_list, arg_list, docstring) 886 else 887 return compile_anonymous_fn(ast, f_scope, f_chunk, parent, index0, arg_name_list, arg_list, docstring, scope) 888 end 889 end 890 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.", true) 891 SPECIALS.lua = function(ast, _, parent) 892 compiler.assert(((#ast == 2) or (#ast == 3)), "expected 1 or 2 arguments", ast) 893 local _387_ 894 do 895 local _386_ = utils["sym?"](ast[2]) 896 if (nil ~= _386_) then 897 _387_ = tostring(_386_) 898 else 899 _387_ = _386_ 900 end 901 end 902 if ("nil" ~= _387_) then 903 table.insert(parent, {ast = ast, leaf = tostring(ast[2])}) 904 else 905 end 906 local _391_ 907 do 908 local _390_ = utils["sym?"](ast[3]) 909 if (nil ~= _390_) then 910 _391_ = tostring(_390_) 911 else 912 _391_ = _390_ 913 end 914 end 915 if ("nil" ~= _391_) then 916 return tostring(ast[3]) 917 else 918 return nil 919 end 920 end 921 local function dot(ast, scope, parent) 922 compiler.assert((1 < #ast), "expected table argument", ast) 923 local len = #ast 924 local _let_394_ = compiler.compile1(ast[2], scope, parent, {nval = 1}) 925 local lhs = _let_394_[1] 926 if (len == 2) then 927 return tostring(lhs) 928 else 929 local indices = {} 930 for i = 3, len do 931 local index = ast[i] 932 if ((type(index) == "string") and utils["valid-lua-identifier?"](index)) then 933 table.insert(indices, ("." .. index)) 934 else 935 local _let_395_ = compiler.compile1(index, scope, parent, {nval = 1}) 936 local index0 = _let_395_[1] 937 table.insert(indices, ("[" .. tostring(index0) .. "]")) 938 end 939 end 940 if (tostring(lhs):find("[{\"0-9]") or ("nil" == tostring(lhs))) then 941 return ("(" .. tostring(lhs) .. ")" .. table.concat(indices)) 942 else 943 return (tostring(lhs) .. table.concat(indices)) 944 end 945 end 946 end 947 SPECIALS["."] = dot 948 doc_special(".", {"tbl", "key1", "..."}, "Look up key1 in tbl table. If more args are provided, do a nested lookup.") 949 SPECIALS.global = function(ast, scope, parent) 950 compiler.assert((#ast == 3), "expected name and value", ast) 951 compiler.destructure(ast[2], ast[3], ast, scope, parent, {forceglobal = true, nomulti = true, symtype = "global"}) 952 return nil 953 end 954 doc_special("global", {"name", "val"}, "Set name as a global with val.") 955 SPECIALS.set = function(ast, scope, parent) 956 compiler.assert((#ast == 3), "expected name and value", ast) 957 compiler.destructure(ast[2], ast[3], ast, scope, parent, {noundef = true, symtype = "set"}) 958 return nil 959 end 960 doc_special("set", {"name", "val"}, "Set a local variable to a new value. Only works on locals using var.") 961 local function set_forcibly_21_2a(ast, scope, parent) 962 compiler.assert((#ast == 3), "expected name and value", ast) 963 compiler.destructure(ast[2], ast[3], ast, scope, parent, {forceset = true, symtype = "set"}) 964 return nil 965 end 966 SPECIALS["set-forcibly!"] = set_forcibly_21_2a 967 local function local_2a(ast, scope, parent) 968 compiler.assert((#ast == 3), "expected name and value", ast) 969 compiler.destructure(ast[2], ast[3], ast, scope, parent, {declaration = true, nomulti = true, symtype = "local"}) 970 return nil 971 end 972 SPECIALS["local"] = local_2a 973 doc_special("local", {"name", "val"}, "Introduce new top-level immutable local.") 974 SPECIALS.var = function(ast, scope, parent) 975 compiler.assert((#ast == 3), "expected name and value", ast) 976 compiler.destructure(ast[2], ast[3], ast, scope, parent, {declaration = true, isvar = true, nomulti = true, symtype = "var"}) 977 return nil 978 end 979 doc_special("var", {"name", "val"}, "Introduce new mutable local.") 980 local function kv_3f(t) 981 local _399_ 982 do 983 local tbl_14_auto = {} 984 local i_15_auto = #tbl_14_auto 985 for k in pairs(t) do 986 local val_16_auto 987 if not ("number" == type(k)) then 988 val_16_auto = k 989 else 990 val_16_auto = nil 991 end 992 if (nil ~= val_16_auto) then 993 i_15_auto = (i_15_auto + 1) 994 do end (tbl_14_auto)[i_15_auto] = val_16_auto 995 else 996 end 997 end 998 _399_ = tbl_14_auto 999 end 1000 return (_399_)[1] 1001 end 1002 SPECIALS.let = function(ast, scope, parent, opts) 1003 local bindings = ast[2] 1004 local pre_syms = {} 1005 compiler.assert((utils["table?"](bindings) and not kv_3f(bindings)), "expected binding sequence", bindings) 1006 compiler.assert(((#bindings % 2) == 0), "expected even number of name/value bindings", ast[2]) 1007 compiler.assert((#ast >= 3), "expected body expression", ast[1]) 1008 for _ = 1, (opts.nval or 0) do 1009 table.insert(pre_syms, compiler.gensym(scope)) 1010 end 1011 local sub_scope = compiler["make-scope"](scope) 1012 local sub_chunk = {} 1013 for i = 1, #bindings, 2 do 1014 compiler.destructure(bindings[i], bindings[(i + 1)], ast, sub_scope, sub_chunk, {declaration = true, nomulti = true, symtype = "let"}) 1015 end 1016 return SPECIALS["do"](ast, scope, parent, opts, 3, sub_chunk, sub_scope, pre_syms) 1017 end 1018 doc_special("let", {"[name1 val1 ... nameN valN]", "..."}, "Introduces a new scope in which a given set of local bindings are used.", true) 1019 local function get_prev_line(parent) 1020 if ("table" == type(parent)) then 1021 return get_prev_line((parent.leaf or parent[#parent])) 1022 else 1023 return (parent or "") 1024 end 1025 end 1026 local function disambiguate_3f(rootstr, parent) 1027 local function _404_() 1028 local _403_ = get_prev_line(parent) 1029 if (nil ~= _403_) then 1030 local prev_line = _403_ 1031 return prev_line:match("%)$") 1032 else 1033 return nil 1034 end 1035 end 1036 return (rootstr:match("^{") or _404_()) 1037 end 1038 SPECIALS.tset = function(ast, scope, parent) 1039 compiler.assert((#ast > 3), "expected table, key, and value arguments", ast) 1040 local root = (compiler.compile1(ast[2], scope, parent, {nval = 1}))[1] 1041 local keys = {} 1042 for i = 3, (#ast - 1) do 1043 local _let_406_ = compiler.compile1(ast[i], scope, parent, {nval = 1}) 1044 local key = _let_406_[1] 1045 table.insert(keys, tostring(key)) 1046 end 1047 local value = (compiler.compile1(ast[#ast], scope, parent, {nval = 1}))[1] 1048 local rootstr = tostring(root) 1049 local fmtstr 1050 if disambiguate_3f(rootstr, parent) then 1051 fmtstr = "do end (%s)[%s] = %s" 1052 else 1053 fmtstr = "%s[%s] = %s" 1054 end 1055 return compiler.emit(parent, fmtstr:format(rootstr, table.concat(keys, "]["), tostring(value)), ast) 1056 end 1057 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.") 1058 local function calculate_target(scope, opts) 1059 if not (opts.tail or opts.target or opts.nval) then 1060 return "iife", true, nil 1061 elseif (opts.nval and (opts.nval ~= 0) and not opts.target) then 1062 local accum = {} 1063 local target_exprs = {} 1064 for i = 1, opts.nval do 1065 local s = compiler.gensym(scope) 1066 do end (accum)[i] = s 1067 target_exprs[i] = utils.expr(s, "sym") 1068 end 1069 return "target", opts.tail, table.concat(accum, ", "), target_exprs 1070 else 1071 return "none", opts.tail, opts.target 1072 end 1073 end 1074 local function if_2a(ast, scope, parent, opts) 1075 compiler.assert((2 < #ast), "expected condition and body", ast) 1076 local do_scope = compiler["make-scope"](scope) 1077 local branches = {} 1078 local wrapper, inner_tail, inner_target, target_exprs = calculate_target(scope, opts) 1079 local body_opts = {nval = opts.nval, tail = inner_tail, target = inner_target} 1080 local function compile_body(i) 1081 local chunk = {} 1082 local cscope = compiler["make-scope"](do_scope) 1083 compiler["keep-side-effects"](compiler.compile1(ast[i], cscope, chunk, body_opts), chunk, nil, ast[i]) 1084 return {chunk = chunk, scope = cscope} 1085 end 1086 if (1 == (#ast % 2)) then 1087 table.insert(ast, utils.sym("nil")) 1088 else 1089 end 1090 for i = 2, (#ast - 1), 2 do 1091 local condchunk = {} 1092 local res = compiler.compile1(ast[i], do_scope, condchunk, {nval = 1}) 1093 local cond = res[1] 1094 local branch = compile_body((i + 1)) 1095 branch.cond = cond 1096 branch.condchunk = condchunk 1097 branch.nested = ((i ~= 2) and (next(condchunk, nil) == nil)) 1098 table.insert(branches, branch) 1099 end 1100 local else_branch = compile_body(#ast) 1101 local s = compiler.gensym(scope) 1102 local buffer = {} 1103 local last_buffer = buffer 1104 for i = 1, #branches do 1105 local branch = branches[i] 1106 local fstr 1107 if not branch.nested then 1108 fstr = "if %s then" 1109 else 1110 fstr = "elseif %s then" 1111 end 1112 local cond = tostring(branch.cond) 1113 local cond_line = fstr:format(cond) 1114 if branch.nested then 1115 compiler.emit(last_buffer, branch.condchunk, ast) 1116 else 1117 for _, v in ipairs(branch.condchunk) do 1118 compiler.emit(last_buffer, v, ast) 1119 end 1120 end 1121 compiler.emit(last_buffer, cond_line, ast) 1122 compiler.emit(last_buffer, branch.chunk, ast) 1123 if (i == #branches) then 1124 compiler.emit(last_buffer, "else", ast) 1125 compiler.emit(last_buffer, else_branch.chunk, ast) 1126 compiler.emit(last_buffer, "end", ast) 1127 elseif not (branches[(i + 1)]).nested then 1128 local next_buffer = {} 1129 compiler.emit(last_buffer, "else", ast) 1130 compiler.emit(last_buffer, next_buffer, ast) 1131 compiler.emit(last_buffer, "end", ast) 1132 last_buffer = next_buffer 1133 else 1134 end 1135 end 1136 if (wrapper == "iife") then 1137 local iifeargs = ((scope.vararg and "...") or "") 1138 compiler.emit(parent, ("local function %s(%s)"):format(tostring(s), iifeargs), ast) 1139 compiler.emit(parent, buffer, ast) 1140 compiler.emit(parent, "end", ast) 1141 return utils.expr(("%s(%s)"):format(tostring(s), iifeargs), "statement") 1142 elseif (wrapper == "none") then 1143 for i = 1, #buffer do 1144 compiler.emit(parent, buffer[i], ast) 1145 end 1146 return {returned = true} 1147 else 1148 compiler.emit(parent, ("local %s"):format(inner_target), ast) 1149 for i = 1, #buffer do 1150 compiler.emit(parent, buffer[i], ast) 1151 end 1152 return target_exprs 1153 end 1154 end 1155 SPECIALS["if"] = if_2a 1156 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.") 1157 local function remove_until_condition(bindings) 1158 if ("until" == bindings[(#bindings - 1)]) then 1159 table.remove(bindings, (#bindings - 1)) 1160 return table.remove(bindings) 1161 else 1162 return nil 1163 end 1164 end 1165 local function compile_until(condition, scope, chunk) 1166 if condition then 1167 local _let_415_ = compiler.compile1(condition, scope, chunk, {nval = 1}) 1168 local condition_lua = _let_415_[1] 1169 return compiler.emit(chunk, ("if %s then break end"):format(tostring(condition_lua)), utils.expr(condition, "expression")) 1170 else 1171 return nil 1172 end 1173 end 1174 SPECIALS.each = function(ast, scope, parent) 1175 compiler.assert((#ast >= 3), "expected body expression", ast[1]) 1176 local binding = compiler.assert(utils["table?"](ast[2]), "expected binding table", ast) 1177 local _ = compiler.assert((2 <= #binding), "expected binding and iterator", binding) 1178 local until_condition = remove_until_condition(binding) 1179 local iter = table.remove(binding, #binding) 1180 local destructures = {} 1181 local new_manglings = {} 1182 local sub_scope = compiler["make-scope"](scope) 1183 local function destructure_binding(v) 1184 compiler.assert(("string" ~= type(v)), ("unexpected iterator clause " .. tostring(v)), binding) 1185 if utils["sym?"](v) then 1186 return compiler["declare-local"](v, {}, sub_scope, ast, new_manglings) 1187 else 1188 local raw = utils.sym(compiler.gensym(sub_scope)) 1189 do end (destructures)[raw] = v 1190 return compiler["declare-local"](raw, {}, sub_scope, ast) 1191 end 1192 end 1193 local bind_vars = utils.map(binding, destructure_binding) 1194 local vals = compiler.compile1(iter, scope, parent) 1195 local val_names = utils.map(vals, tostring) 1196 local chunk = {} 1197 compiler.emit(parent, ("for %s in %s do"):format(table.concat(bind_vars, ", "), table.concat(val_names, ", ")), ast) 1198 for raw, args in utils.stablepairs(destructures) do 1199 compiler.destructure(args, raw, ast, sub_scope, chunk, {declaration = true, nomulti = true, symtype = "each"}) 1200 end 1201 compiler["apply-manglings"](sub_scope, new_manglings, ast) 1202 compile_until(until_condition, sub_scope, chunk) 1203 compile_do(ast, sub_scope, chunk, 3) 1204 compiler.emit(parent, chunk, ast) 1205 return compiler.emit(parent, "end", ast) 1206 end 1207 doc_special("each", {"[key value (iterator)]", "..."}, "Runs the body once for each set of values provided by the given iterator.\nMost commonly used with ipairs for sequential tables or pairs for undefined\norder, but can be used with any iterator.", true) 1208 local function while_2a(ast, scope, parent) 1209 local len1 = #parent 1210 local condition = (compiler.compile1(ast[2], scope, parent, {nval = 1}))[1] 1211 local len2 = #parent 1212 local sub_chunk = {} 1213 if (len1 ~= len2) then 1214 for i = (len1 + 1), len2 do 1215 table.insert(sub_chunk, parent[i]) 1216 do end (parent)[i] = nil 1217 end 1218 compiler.emit(parent, "while true do", ast) 1219 compiler.emit(sub_chunk, ("if not %s then break end"):format(condition[1]), ast) 1220 else 1221 compiler.emit(parent, ("while " .. tostring(condition) .. " do"), ast) 1222 end 1223 compile_do(ast, compiler["make-scope"](scope), sub_chunk, 3) 1224 compiler.emit(parent, sub_chunk, ast) 1225 return compiler.emit(parent, "end", ast) 1226 end 1227 SPECIALS["while"] = while_2a 1228 doc_special("while", {"condition", "..."}, "The classic while loop. Evaluates body until a condition is non-truthy.", true) 1229 local function for_2a(ast, scope, parent) 1230 local ranges = compiler.assert(utils["table?"](ast[2]), "expected binding table", ast) 1231 local until_condition = remove_until_condition(ast[2]) 1232 local binding_sym = table.remove(ast[2], 1) 1233 local sub_scope = compiler["make-scope"](scope) 1234 local range_args = {} 1235 local chunk = {} 1236 compiler.assert(utils["sym?"](binding_sym), ("unable to bind %s %s"):format(type(binding_sym), tostring(binding_sym)), ast[2]) 1237 compiler.assert((#ast >= 3), "expected body expression", ast[1]) 1238 compiler.assert((#ranges <= 3), "unexpected arguments", ranges[4]) 1239 for i = 1, math.min(#ranges, 3) do 1240 range_args[i] = tostring((compiler.compile1(ranges[i], scope, parent, {nval = 1}))[1]) 1241 end 1242 compiler.emit(parent, ("for %s = %s do"):format(compiler["declare-local"](binding_sym, {}, sub_scope, ast), table.concat(range_args, ", ")), ast) 1243 compile_until(until_condition, sub_scope, chunk) 1244 compile_do(ast, sub_scope, chunk, 3) 1245 compiler.emit(parent, chunk, ast) 1246 return compiler.emit(parent, "end", ast) 1247 end 1248 SPECIALS["for"] = for_2a 1249 doc_special("for", {"[index start stop step?]", "..."}, "Numeric loop construct.\nEvaluates body once for each value between start and stop (inclusive).", true) 1250 local function native_method_call(ast, _scope, _parent, target, args) 1251 local _let_419_ = ast 1252 local _ = _let_419_[1] 1253 local _0 = _let_419_[2] 1254 local method_string = _let_419_[3] 1255 local call_string 1256 if ((target.type == "literal") or (target.type == "varg") or (target.type == "expression")) then 1257 call_string = "(%s):%s(%s)" 1258 else 1259 call_string = "%s:%s(%s)" 1260 end 1261 return utils.expr(string.format(call_string, tostring(target), method_string, table.concat(args, ", ")), "statement") 1262 end 1263 local function nonnative_method_call(ast, scope, parent, target, args) 1264 local method_string = tostring((compiler.compile1(ast[3], scope, parent, {nval = 1}))[1]) 1265 local args0 = {tostring(target), unpack(args)} 1266 return utils.expr(string.format("%s[%s](%s)", tostring(target), method_string, table.concat(args0, ", ")), "statement") 1267 end 1268 local function double_eval_protected_method_call(ast, scope, parent, target, args) 1269 local method_string = tostring((compiler.compile1(ast[3], scope, parent, {nval = 1}))[1]) 1270 local call = "(function(tgt, m, ...) return tgt[m](tgt, ...) end)(%s, %s)" 1271 table.insert(args, 1, method_string) 1272 return utils.expr(string.format(call, tostring(target), table.concat(args, ", ")), "statement") 1273 end 1274 local function method_call(ast, scope, parent) 1275 compiler.assert((2 < #ast), "expected at least 2 arguments", ast) 1276 local _let_421_ = compiler.compile1(ast[2], scope, parent, {nval = 1}) 1277 local target = _let_421_[1] 1278 local args = {} 1279 for i = 4, #ast do 1280 local subexprs 1281 local _422_ 1282 if (i ~= #ast) then 1283 _422_ = 1 1284 else 1285 _422_ = nil 1286 end 1287 subexprs = compiler.compile1(ast[i], scope, parent, {nval = _422_}) 1288 utils.map(subexprs, tostring, args) 1289 end 1290 if ((type(ast[3]) == "string") and utils["valid-lua-identifier?"](ast[3])) then 1291 return native_method_call(ast, scope, parent, target, args) 1292 elseif (target.type == "sym") then 1293 return nonnative_method_call(ast, scope, parent, target, args) 1294 else 1295 return double_eval_protected_method_call(ast, scope, parent, target, args) 1296 end 1297 end 1298 SPECIALS[":"] = method_call 1299 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.") 1300 SPECIALS.comment = function(ast, _, parent) 1301 local els = {} 1302 for i = 2, #ast do 1303 table.insert(els, view(ast[i], {["one-line?"] = true})) 1304 end 1305 return compiler.emit(parent, ("--[[ " .. table.concat(els, " ") .. " ]]--"), ast) 1306 end 1307 doc_special("comment", {"..."}, "Comment which will be emitted in Lua output.", true) 1308 local function hashfn_max_used(f_scope, i, max) 1309 local max0 1310 if f_scope.symmeta[("$" .. i)].used then 1311 max0 = i 1312 else 1313 max0 = max 1314 end 1315 if (i < 9) then 1316 return hashfn_max_used(f_scope, (i + 1), max0) 1317 else 1318 return max0 1319 end 1320 end 1321 SPECIALS.hashfn = function(ast, scope, parent) 1322 compiler.assert((#ast == 2), "expected one argument", ast) 1323 local f_scope 1324 do 1325 local _427_ = compiler["make-scope"](scope) 1326 do end (_427_)["vararg"] = false 1327 _427_["hashfn"] = true 1328 f_scope = _427_ 1329 end 1330 local f_chunk = {} 1331 local name = compiler.gensym(scope) 1332 local symbol = utils.sym(name) 1333 local args = {} 1334 compiler["declare-local"](symbol, {}, scope, ast) 1335 for i = 1, 9 do 1336 args[i] = compiler["declare-local"](utils.sym(("$" .. i)), {}, f_scope, ast) 1337 end 1338 local function walker(idx, node, parent_node) 1339 if (utils["sym?"](node) and (tostring(node) == "$...")) then 1340 parent_node[idx] = utils.varg() 1341 f_scope.vararg = true 1342 return nil 1343 else 1344 return (utils["list?"](node) or utils["table?"](node)) 1345 end 1346 end 1347 utils["walk-tree"](ast[2], walker) 1348 compiler.compile1(ast[2], f_scope, f_chunk, {tail = true}) 1349 local max_used = hashfn_max_used(f_scope, 1, 0) 1350 if f_scope.vararg then 1351 compiler.assert((max_used == 0), "$ and $... in hashfn are mutually exclusive", ast) 1352 else 1353 end 1354 local arg_str 1355 if f_scope.vararg then 1356 arg_str = tostring(utils.varg()) 1357 else 1358 arg_str = table.concat(args, ", ", 1, max_used) 1359 end 1360 compiler.emit(parent, string.format("local function %s(%s)", name, arg_str), ast) 1361 compiler.emit(parent, f_chunk, ast) 1362 compiler.emit(parent, "end", ast) 1363 return utils.expr(name, "sym") 1364 end 1365 doc_special("hashfn", {"..."}, "Function literal shorthand; args are either $... OR $1, $2, etc.") 1366 local function arithmetic_special(name, zero_arity, unary_prefix, ast, scope, parent) 1367 local len = #ast 1368 local operands = {} 1369 local padded_op = (" " .. name .. " ") 1370 for i = 2, len do 1371 local subexprs = compiler.compile1(ast[i], scope, parent) 1372 if (i == len) then 1373 utils.map(subexprs, tostring, operands) 1374 else 1375 table.insert(operands, tostring(subexprs[1])) 1376 end 1377 end 1378 local _432_ = #operands 1379 if (_432_ == 0) then 1380 local _434_ 1381 do 1382 local _433_ = zero_arity 1383 compiler.assert(_433_, "Expected more than 0 arguments", ast) 1384 _434_ = _433_ 1385 end 1386 return utils.expr(_434_, "literal") 1387 elseif (_432_ == 1) then 1388 if unary_prefix then 1389 return ("(" .. unary_prefix .. padded_op .. operands[1] .. ")") 1390 else 1391 return operands[1] 1392 end 1393 elseif true then 1394 local _ = _432_ 1395 return ("(" .. table.concat(operands, padded_op) .. ")") 1396 else 1397 return nil 1398 end 1399 end 1400 local function define_arithmetic_special(name, zero_arity, unary_prefix, _3flua_name) 1401 local _440_ 1402 do 1403 local _437_ = (_3flua_name or name) 1404 local _438_ = zero_arity 1405 local _439_ = unary_prefix 1406 local function _441_(...) 1407 return arithmetic_special(_437_, _438_, _439_, ...) 1408 end 1409 _440_ = _441_ 1410 end 1411 SPECIALS[name] = _440_ 1412 return doc_special(name, {"a", "b", "..."}, "Arithmetic operator; works the same as Lua but accepts more arguments.") 1413 end 1414 define_arithmetic_special("+", "0") 1415 define_arithmetic_special("..", "''") 1416 define_arithmetic_special("^") 1417 define_arithmetic_special("-", nil, "") 1418 define_arithmetic_special("*", "1") 1419 define_arithmetic_special("%") 1420 define_arithmetic_special("/", nil, "1") 1421 define_arithmetic_special("//", nil, "1") 1422 SPECIALS["or"] = function(ast, scope, parent) 1423 return arithmetic_special("or", "false", nil, ast, scope, parent) 1424 end 1425 SPECIALS["and"] = function(ast, scope, parent) 1426 return arithmetic_special("and", "true", nil, ast, scope, parent) 1427 end 1428 doc_special("and", {"a", "b", "..."}, "Boolean operator; works the same as Lua but accepts more arguments.") 1429 doc_special("or", {"a", "b", "..."}, "Boolean operator; works the same as Lua but accepts more arguments.") 1430 local function bitop_special(native_name, lib_name, zero_arity, unary_prefix, ast, scope, parent) 1431 if (#ast == 1) then 1432 return compiler.assert(zero_arity, "Expected more than 0 arguments.", ast) 1433 else 1434 local len = #ast 1435 local operands = {} 1436 local padded_native_name = (" " .. native_name .. " ") 1437 local prefixed_lib_name = ("bit." .. lib_name) 1438 for i = 2, len do 1439 local subexprs 1440 local _442_ 1441 if (i ~= len) then 1442 _442_ = 1 1443 else 1444 _442_ = nil 1445 end 1446 subexprs = compiler.compile1(ast[i], scope, parent, {nval = _442_}) 1447 utils.map(subexprs, tostring, operands) 1448 end 1449 if (#operands == 1) then 1450 if utils.root.options.useBitLib then 1451 return (prefixed_lib_name .. "(" .. unary_prefix .. ", " .. operands[1] .. ")") 1452 else 1453 return ("(" .. unary_prefix .. padded_native_name .. operands[1] .. ")") 1454 end 1455 else 1456 if utils.root.options.useBitLib then 1457 return (prefixed_lib_name .. "(" .. table.concat(operands, ", ") .. ")") 1458 else 1459 return ("(" .. table.concat(operands, padded_native_name) .. ")") 1460 end 1461 end 1462 end 1463 end 1464 local function define_bitop_special(name, zero_arity, unary_prefix, native) 1465 local _452_ 1466 do 1467 local _448_ = native 1468 local _449_ = name 1469 local _450_ = zero_arity 1470 local _451_ = unary_prefix 1471 local function _453_(...) 1472 return bitop_special(_448_, _449_, _450_, _451_, ...) 1473 end 1474 _452_ = _453_ 1475 end 1476 SPECIALS[name] = _452_ 1477 return nil 1478 end 1479 define_bitop_special("lshift", nil, "1", "<<") 1480 define_bitop_special("rshift", nil, "1", ">>") 1481 define_bitop_special("band", "0", "0", "&") 1482 define_bitop_special("bor", "0", "0", "|") 1483 define_bitop_special("bxor", "0", "0", "~") 1484 doc_special("lshift", {"x", "n"}, "Bitwise logical left shift of x by n bits.\nOnly works in Lua 5.3+ or LuaJIT with the --use-bit-lib flag.") 1485 doc_special("rshift", {"x", "n"}, "Bitwise logical right shift of x by n bits.\nOnly works in Lua 5.3+ or LuaJIT with the --use-bit-lib flag.") 1486 doc_special("band", {"x1", "x2", "..."}, "Bitwise AND of any number of arguments.\nOnly works in Lua 5.3+ or LuaJIT with the --use-bit-lib flag.") 1487 doc_special("bor", {"x1", "x2", "..."}, "Bitwise OR of any number of arguments.\nOnly works in Lua 5.3+ or LuaJIT with the --use-bit-lib flag.") 1488 doc_special("bxor", {"x1", "x2", "..."}, "Bitwise XOR of any number of arguments.\nOnly works in Lua 5.3+ or LuaJIT with the --use-bit-lib flag.") 1489 doc_special("..", {"a", "b", "..."}, "String concatenation operator; works the same as Lua but accepts more arguments.") 1490 local function native_comparator(op, _454_, scope, parent) 1491 local _arg_455_ = _454_ 1492 local _ = _arg_455_[1] 1493 local lhs_ast = _arg_455_[2] 1494 local rhs_ast = _arg_455_[3] 1495 local _let_456_ = compiler.compile1(lhs_ast, scope, parent, {nval = 1}) 1496 local lhs = _let_456_[1] 1497 local _let_457_ = compiler.compile1(rhs_ast, scope, parent, {nval = 1}) 1498 local rhs = _let_457_[1] 1499 return string.format("(%s %s %s)", tostring(lhs), op, tostring(rhs)) 1500 end 1501 local function double_eval_protected_comparator(op, chain_op, ast, scope, parent) 1502 local arglist = {} 1503 local comparisons = {} 1504 local vals = {} 1505 local chain = string.format(" %s ", (chain_op or "and")) 1506 for i = 2, #ast do 1507 table.insert(arglist, tostring(compiler.gensym(scope))) 1508 table.insert(vals, tostring((compiler.compile1(ast[i], scope, parent, {nval = 1}))[1])) 1509 end 1510 for i = 1, (#arglist - 1) do 1511 table.insert(comparisons, string.format("(%s %s %s)", arglist[i], op, arglist[(i + 1)])) 1512 end 1513 return string.format("(function(%s) return %s end)(%s)", table.concat(arglist, ","), table.concat(comparisons, chain), table.concat(vals, ",")) 1514 end 1515 local function define_comparator_special(name, _3flua_op, _3fchain_op) 1516 do 1517 local op = (_3flua_op or name) 1518 local function opfn(ast, scope, parent) 1519 compiler.assert((2 < #ast), "expected at least two arguments", ast) 1520 if (3 == #ast) then 1521 return native_comparator(op, ast, scope, parent) 1522 else 1523 return double_eval_protected_comparator(op, _3fchain_op, ast, scope, parent) 1524 end 1525 end 1526 SPECIALS[name] = opfn 1527 end 1528 return doc_special(name, {"a", "b", "..."}, "Comparison operator; works the same as Lua but accepts more arguments.") 1529 end 1530 define_comparator_special(">") 1531 define_comparator_special("<") 1532 define_comparator_special(">=") 1533 define_comparator_special("<=") 1534 define_comparator_special("=", "==") 1535 define_comparator_special("not=", "~=", "or") 1536 local function define_unary_special(op, _3frealop) 1537 local function opfn(ast, scope, parent) 1538 compiler.assert((#ast == 2), "expected one argument", ast) 1539 local tail = compiler.compile1(ast[2], scope, parent, {nval = 1}) 1540 return ((_3frealop or op) .. tostring(tail[1])) 1541 end 1542 SPECIALS[op] = opfn 1543 return nil 1544 end 1545 define_unary_special("not", "not ") 1546 doc_special("not", {"x"}, "Logical operator; works the same as Lua.") 1547 define_unary_special("bnot", "~") 1548 doc_special("bnot", {"x"}, "Bitwise negation; only works in Lua 5.3+ or LuaJIT with the --use-bit-lib flag.") 1549 define_unary_special("length", "#") 1550 doc_special("length", {"x"}, "Returns the length of a table or string.") 1551 do end (SPECIALS)["~="] = SPECIALS["not="] 1552 SPECIALS["#"] = SPECIALS.length 1553 SPECIALS.quote = function(ast, scope, parent) 1554 compiler.assert((#ast == 2), "expected one argument", ast) 1555 local runtime, this_scope = true, scope 1556 while this_scope do 1557 this_scope = this_scope.parent 1558 if (this_scope == compiler.scopes.compiler) then 1559 runtime = false 1560 else 1561 end 1562 end 1563 return compiler["do-quote"](ast[2], scope, parent, runtime) 1564 end 1565 doc_special("quote", {"x"}, "Quasiquote the following form. Only works in macro/compiler scope.") 1566 local macro_loaded = {} 1567 local function safe_getmetatable(tbl) 1568 local mt = getmetatable(tbl) 1569 assert((mt ~= getmetatable("")), "Illegal metatable access!") 1570 return mt 1571 end 1572 local safe_require = nil 1573 local function safe_compiler_env() 1574 return {table = utils.copy(table), math = utils.copy(math), string = utils.copy(string), pairs = pairs, ipairs = ipairs, select = select, tostring = tostring, tonumber = tonumber, bit = rawget(_G, "bit"), pcall = pcall, xpcall = xpcall, next = next, print = print, type = type, assert = assert, error = error, setmetatable = setmetatable, getmetatable = safe_getmetatable, require = safe_require, rawlen = rawget(_G, "rawlen"), rawget = rawget, rawset = rawset, rawequal = rawequal, _VERSION = _VERSION} 1575 end 1576 local function combined_mt_pairs(env) 1577 local combined = {} 1578 local _let_460_ = getmetatable(env) 1579 local __index = _let_460_["__index"] 1580 if ("table" == type(__index)) then 1581 for k, v in pairs(__index) do 1582 combined[k] = v 1583 end 1584 else 1585 end 1586 for k, v in next, env, nil do 1587 combined[k] = v 1588 end 1589 return next, combined, nil 1590 end 1591 local function make_compiler_env(ast, scope, parent, _3fopts) 1592 local provided 1593 do 1594 local _462_ = (_3fopts or utils.root.options) 1595 if ((_G.type(_462_) == "table") and ((_462_)["compiler-env"] == "strict")) then 1596 provided = safe_compiler_env() 1597 elseif ((_G.type(_462_) == "table") and (nil ~= (_462_).compilerEnv)) then 1598 local compilerEnv = (_462_).compilerEnv 1599 provided = compilerEnv 1600 elseif ((_G.type(_462_) == "table") and (nil ~= (_462_)["compiler-env"])) then 1601 local compiler_env = (_462_)["compiler-env"] 1602 provided = compiler_env 1603 elseif true then 1604 local _ = _462_ 1605 provided = safe_compiler_env(false) 1606 else 1607 provided = nil 1608 end 1609 end 1610 local env 1611 local function _464_(base) 1612 return utils.sym(compiler.gensym((compiler.scopes.macro or scope), base)) 1613 end 1614 local function _465_() 1615 return compiler.scopes.macro 1616 end 1617 local function _466_(symbol) 1618 compiler.assert(compiler.scopes.macro, "must call from macro", ast) 1619 return compiler.scopes.macro.manglings[tostring(symbol)] 1620 end 1621 local function _467_(form) 1622 compiler.assert(compiler.scopes.macro, "must call from macro", ast) 1623 return compiler.macroexpand(form, compiler.scopes.macro) 1624 end 1625 env = {_AST = ast, _CHUNK = parent, _IS_COMPILER = true, _SCOPE = scope, _SPECIALS = compiler.scopes.global.specials, _VARARG = utils.varg(), ["macro-loaded"] = macro_loaded, unpack = unpack, ["assert-compile"] = compiler.assert, view = view, version = utils.version, metadata = compiler.metadata, list = utils.list, ["list?"] = utils["list?"], ["table?"] = utils["table?"], sequence = utils.sequence, ["sequence?"] = utils["sequence?"], sym = utils.sym, ["sym?"] = utils["sym?"], ["multi-sym?"] = utils["multi-sym?"], comment = utils.comment, ["comment?"] = utils["comment?"], ["varg?"] = utils["varg?"], gensym = _464_, ["get-scope"] = _465_, ["in-scope?"] = _466_, macroexpand = _467_} 1626 env._G = env 1627 return setmetatable(env, {__index = provided, __newindex = provided, __pairs = combined_mt_pairs}) 1628 end 1629 local function _469_(...) 1630 local tbl_14_auto = {} 1631 local i_15_auto = #tbl_14_auto 1632 for c in string.gmatch((package.config or ""), "([^\n]+)") do 1633 local val_16_auto = c 1634 if (nil ~= val_16_auto) then 1635 i_15_auto = (i_15_auto + 1) 1636 do end (tbl_14_auto)[i_15_auto] = val_16_auto 1637 else 1638 end 1639 end 1640 return tbl_14_auto 1641 end 1642 local _local_468_ = _469_(...) 1643 local dirsep = _local_468_[1] 1644 local pathsep = _local_468_[2] 1645 local pathmark = _local_468_[3] 1646 local pkg_config = {dirsep = (dirsep or "/"), pathmark = (pathmark or ";"), pathsep = (pathsep or "?")} 1647 local function escapepat(str) 1648 return string.gsub(str, "[^%w]", "%%%1") 1649 end 1650 local function search_module(modulename, _3fpathstring) 1651 local pathsepesc = escapepat(pkg_config.pathsep) 1652 local pattern = ("([^%s]*)%s"):format(pathsepesc, pathsepesc) 1653 local no_dot_module = modulename:gsub("%.", pkg_config.dirsep) 1654 local fullpath = ((_3fpathstring or utils["fennel-module"].path) .. pkg_config.pathsep) 1655 local function try_path(path) 1656 local filename = path:gsub(escapepat(pkg_config.pathmark), no_dot_module) 1657 local filename2 = path:gsub(escapepat(pkg_config.pathmark), modulename) 1658 local _471_ = (io.open(filename) or io.open(filename2)) 1659 if (nil ~= _471_) then 1660 local file = _471_ 1661 file:close() 1662 return filename 1663 else 1664 return nil 1665 end 1666 end 1667 local function find_in_path(start) 1668 local _473_ = fullpath:match(pattern, start) 1669 if (nil ~= _473_) then 1670 local path = _473_ 1671 return (try_path(path) or find_in_path((start + #path + 1))) 1672 else 1673 return nil 1674 end 1675 end 1676 return find_in_path(1) 1677 end 1678 local function make_searcher(_3foptions) 1679 local function _475_(module_name) 1680 local opts = utils.copy(utils.root.options) 1681 for k, v in pairs((_3foptions or {})) do 1682 opts[k] = v 1683 end 1684 opts["module-name"] = module_name 1685 local _476_ = search_module(module_name) 1686 if (nil ~= _476_) then 1687 local filename = _476_ 1688 local _479_ 1689 do 1690 local _477_ = filename 1691 local _478_ = opts 1692 local function _480_(...) 1693 return utils["fennel-module"].dofile(_477_, _478_, ...) 1694 end 1695 _479_ = _480_ 1696 end 1697 return _479_, filename 1698 else 1699 return nil 1700 end 1701 end 1702 return _475_ 1703 end 1704 local function fennel_macro_searcher(module_name) 1705 local opts 1706 do 1707 local _482_ = utils.copy(utils.root.options) 1708 do end (_482_)["env"] = "_COMPILER" 1709 _482_["requireAsInclude"] = false 1710 _482_["allowedGlobals"] = nil 1711 opts = _482_ 1712 end 1713 local _483_ = search_module(module_name, utils["fennel-module"]["macro-path"]) 1714 if (nil ~= _483_) then 1715 local filename = _483_ 1716 local _486_ 1717 do 1718 local _484_ = filename 1719 local _485_ = opts 1720 local function _487_(...) 1721 return utils["fennel-module"].dofile(_484_, _485_, ...) 1722 end 1723 _486_ = _487_ 1724 end 1725 return _486_, filename 1726 else 1727 return nil 1728 end 1729 end 1730 local function lua_macro_searcher(module_name) 1731 local _489_ = search_module(module_name, package.path) 1732 if (nil ~= _489_) then 1733 local filename = _489_ 1734 local code 1735 do 1736 local f = io.open(filename) 1737 local function close_handlers_8_auto(ok_9_auto, ...) 1738 f:close() 1739 if ok_9_auto then 1740 return ... 1741 else 1742 return error(..., 0) 1743 end 1744 end 1745 local function _491_() 1746 return assert(f:read("*a")) 1747 end 1748 code = close_handlers_8_auto(_G.xpcall(_491_, (package.loaded.fennel or debug).traceback)) 1749 end 1750 local chunk = load_code(code, make_compiler_env(), filename) 1751 return chunk, filename 1752 else 1753 return nil 1754 end 1755 end 1756 local macro_searchers = {fennel_macro_searcher, lua_macro_searcher} 1757 local function search_macro_module(modname, n) 1758 local _493_ = macro_searchers[n] 1759 if (nil ~= _493_) then 1760 local f = _493_ 1761 local _494_, _495_ = f(modname) 1762 if ((nil ~= _494_) and true) then 1763 local loader = _494_ 1764 local _3ffilename = _495_ 1765 return loader, _3ffilename 1766 elseif true then 1767 local _ = _494_ 1768 return search_macro_module(modname, (n + 1)) 1769 else 1770 return nil 1771 end 1772 else 1773 return nil 1774 end 1775 end 1776 local function metadata_only_fennel(modname) 1777 if ((modname == "fennel.macros") or (package and package.loaded and ("table" == type(package.loaded[modname])) and (package.loaded[modname].metadata == compiler.metadata))) then 1778 return {metadata = compiler.metadata} 1779 else 1780 return nil 1781 end 1782 end 1783 local function _499_(modname) 1784 local function _500_() 1785 local loader, filename = search_macro_module(modname, 1) 1786 compiler.assert(loader, (modname .. " module not found.")) 1787 do end (macro_loaded)[modname] = loader(modname, filename) 1788 return macro_loaded[modname] 1789 end 1790 return (macro_loaded[modname] or metadata_only_fennel(modname) or _500_()) 1791 end 1792 safe_require = _499_ 1793 local function add_macros(macros_2a, ast, scope) 1794 compiler.assert(utils["table?"](macros_2a), "expected macros to be table", ast) 1795 for k, v in pairs(macros_2a) do 1796 compiler.assert((type(v) == "function"), "expected each macro to be function", ast) 1797 do end (scope.macros)[k] = v 1798 end 1799 return nil 1800 end 1801 local function resolve_module_name(_501_, _scope, _parent, opts) 1802 local _arg_502_ = _501_ 1803 local filename = _arg_502_["filename"] 1804 local second = _arg_502_[2] 1805 local filename0 = (filename or (utils["table?"](second) and second.filename)) 1806 local module_name = utils.root.options["module-name"] 1807 local modexpr = compiler.compile(second, opts) 1808 local modname_chunk = load_code(modexpr) 1809 return modname_chunk(module_name, filename0) 1810 end 1811 SPECIALS["require-macros"] = function(ast, scope, parent, _3freal_ast) 1812 compiler.assert((#ast == 2), "Expected one module name argument", (_3freal_ast or ast)) 1813 local modname = resolve_module_name(ast, scope, parent, {}) 1814 compiler.assert(("string" == type(modname)), "module name must compile to string", (_3freal_ast or ast)) 1815 if not macro_loaded[modname] then 1816 local loader, filename = search_macro_module(modname, 1) 1817 compiler.assert(loader, (modname .. " module not found."), ast) 1818 do end (macro_loaded)[modname] = loader(modname, filename) 1819 else 1820 end 1821 if ("import-macros" == tostring(ast[1])) then 1822 return macro_loaded[modname] 1823 else 1824 return add_macros(macro_loaded[modname], ast, scope, parent) 1825 end 1826 end 1827 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.") 1828 local function emit_included_fennel(src, path, opts, sub_chunk) 1829 local subscope = compiler["make-scope"](utils.root.scope.parent) 1830 local forms = {} 1831 if utils.root.options.requireAsInclude then 1832 subscope.specials.require = compiler["require-include"] 1833 else 1834 end 1835 for _, val in parser.parser(parser["string-stream"](src), path) do 1836 table.insert(forms, val) 1837 end 1838 for i = 1, #forms do 1839 local subopts 1840 if (i == #forms) then 1841 subopts = {tail = true} 1842 else 1843 subopts = {nval = 0} 1844 end 1845 utils["propagate-options"](opts, subopts) 1846 compiler.compile1(forms[i], subscope, sub_chunk, subopts) 1847 end 1848 return nil 1849 end 1850 local function include_path(ast, opts, path, mod, fennel_3f) 1851 utils.root.scope.includes[mod] = "fnl/loading" 1852 local src 1853 do 1854 local f = assert(io.open(path)) 1855 local function close_handlers_8_auto(ok_9_auto, ...) 1856 f:close() 1857 if ok_9_auto then 1858 return ... 1859 else 1860 return error(..., 0) 1861 end 1862 end 1863 local function _508_() 1864 return f:read("*all"):gsub("[\13\n]*$", "") 1865 end 1866 src = close_handlers_8_auto(_G.xpcall(_508_, (package.loaded.fennel or debug).traceback)) 1867 end 1868 local ret = utils.expr(("require(\"" .. mod .. "\")"), "statement") 1869 local target = ("package.preload[%q]"):format(mod) 1870 local preload_str = (target .. " = " .. target .. " or function(...)") 1871 local temp_chunk, sub_chunk = {}, {} 1872 compiler.emit(temp_chunk, preload_str, ast) 1873 compiler.emit(temp_chunk, sub_chunk) 1874 compiler.emit(temp_chunk, "end", ast) 1875 for i, v in ipairs(temp_chunk) do 1876 table.insert(utils.root.chunk, i, v) 1877 end 1878 if fennel_3f then 1879 emit_included_fennel(src, path, opts, sub_chunk) 1880 else 1881 compiler.emit(sub_chunk, src, ast) 1882 end 1883 utils.root.scope.includes[mod] = ret 1884 return ret 1885 end 1886 local function include_circular_fallback(mod, modexpr, fallback, ast) 1887 if (utils.root.scope.includes[mod] == "fnl/loading") then 1888 compiler.assert(fallback, "circular include detected", ast) 1889 return fallback(modexpr) 1890 else 1891 return nil 1892 end 1893 end 1894 SPECIALS.include = function(ast, scope, parent, opts) 1895 compiler.assert((#ast == 2), "expected one argument", ast) 1896 local modexpr 1897 do 1898 local _511_, _512_ = pcall(resolve_module_name, ast, scope, parent, opts) 1899 if ((_511_ == true) and (nil ~= _512_)) then 1900 local modname = _512_ 1901 modexpr = utils.expr(string.format("%q", modname), "literal") 1902 elseif true then 1903 local _ = _511_ 1904 modexpr = (compiler.compile1(ast[2], scope, parent, {nval = 1}))[1] 1905 else 1906 modexpr = nil 1907 end 1908 end 1909 if ((modexpr.type ~= "literal") or ((modexpr[1]):byte() ~= 34)) then 1910 if opts.fallback then 1911 return opts.fallback(modexpr) 1912 else 1913 return compiler.assert(false, "module name must be string literal", ast) 1914 end 1915 else 1916 local mod = load_code(("return " .. modexpr[1]))() 1917 local oldmod = utils.root.options["module-name"] 1918 local _ 1919 utils.root.options["module-name"] = mod 1920 _ = nil 1921 local res 1922 local function _516_() 1923 local _515_ = search_module(mod) 1924 if (nil ~= _515_) then 1925 local fennel_path = _515_ 1926 return include_path(ast, opts, fennel_path, mod, true) 1927 elseif true then 1928 local _0 = _515_ 1929 local lua_path = search_module(mod, package.path) 1930 if lua_path then 1931 return include_path(ast, opts, lua_path, mod, false) 1932 elseif opts.fallback then 1933 return opts.fallback(modexpr) 1934 else 1935 return compiler.assert(false, ("module not found " .. mod), ast) 1936 end 1937 else 1938 return nil 1939 end 1940 end 1941 res = ((utils["member?"](mod, (utils.root.options.skipInclude or {})) and utils.expr("nil --[[SKIPPED INCLUDE]]--", "literal")) or include_circular_fallback(mod, modexpr, opts.fallback, ast) or utils.root.scope.includes[mod] or _516_()) 1942 utils.root.options["module-name"] = oldmod 1943 return res 1944 end 1945 end 1946 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.") 1947 local function eval_compiler_2a(ast, scope, parent) 1948 local env = make_compiler_env(ast, scope, parent) 1949 local opts = utils.copy(utils.root.options) 1950 opts.scope = compiler["make-scope"](compiler.scopes.compiler) 1951 opts.allowedGlobals = current_global_names(env) 1952 return load_code(compiler.compile(ast, opts), wrap_env(env))(opts["module-name"], ast.filename) 1953 end 1954 SPECIALS.macros = function(ast, scope, parent) 1955 compiler.assert((#ast == 2), "Expected one table argument", ast) 1956 return add_macros(eval_compiler_2a(ast[2], scope, parent), ast, scope, parent) 1957 end 1958 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.") 1959 SPECIALS["eval-compiler"] = function(ast, scope, parent) 1960 local old_first = ast[1] 1961 ast[1] = utils.sym("do") 1962 local val = eval_compiler_2a(ast, scope, parent) 1963 do end (ast)[1] = old_first 1964 return val 1965 end 1966 doc_special("eval-compiler", {"..."}, "Evaluate the body at compile-time. Use the macro system instead if possible.", true) 1967 return {doc = doc_2a, ["current-global-names"] = current_global_names, ["load-code"] = load_code, ["macro-loaded"] = macro_loaded, ["macro-searchers"] = macro_searchers, ["make-compiler-env"] = make_compiler_env, ["search-module"] = search_module, ["make-searcher"] = make_searcher, ["wrap-env"] = wrap_env} 1968end 1969package.preload["fennel.compiler"] = package.preload["fennel.compiler"] or function(...) 1970 local utils = require("fennel.utils") 1971 local parser = require("fennel.parser") 1972 local friend = require("fennel.friend") 1973 local unpack = (table.unpack or _G.unpack) 1974 local scopes = {} 1975 local function make_scope(_3fparent) 1976 local parent = (_3fparent or scopes.global) 1977 local _203_ 1978 if parent then 1979 _203_ = ((parent.depth or 0) + 1) 1980 else 1981 _203_ = 0 1982 end 1983 return {includes = setmetatable({}, {__index = (parent and parent.includes)}), macros = setmetatable({}, {__index = (parent and parent.macros)}), manglings = setmetatable({}, {__index = (parent and parent.manglings)}), specials = setmetatable({}, {__index = (parent and parent.specials)}), symmeta = setmetatable({}, {__index = (parent and parent.symmeta)}), unmanglings = setmetatable({}, {__index = (parent and parent.unmanglings)}), gensyms = setmetatable({}, {__index = (parent and parent.gensyms)}), autogensyms = setmetatable({}, {__index = (parent and parent.autogensyms)}), vararg = (parent and parent.vararg), depth = _203_, hashfn = (parent and parent.hashfn), refedglobals = {}, parent = parent} 1984 end 1985 local function assert_msg(ast, msg) 1986 local ast_tbl 1987 if ("table" == type(ast)) then 1988 ast_tbl = ast 1989 else 1990 ast_tbl = {} 1991 end 1992 local m = getmetatable(ast) 1993 local filename = ((m and m.filename) or ast_tbl.filename or "unknown") 1994 local line = ((m and m.line) or ast_tbl.line or "?") 1995 local target = tostring((utils["sym?"](ast_tbl[1]) or ast_tbl[1] or "()")) 1996 return string.format("%s:%s: Compile error in '%s': %s", filename, line, target, msg) 1997 end 1998 local function assert_compile(condition, msg, ast) 1999 if not condition then 2000 local _let_206_ = (utils.root.options or {}) 2001 local source = _let_206_["source"] 2002 local unfriendly = _let_206_["unfriendly"] 2003 if (nil == utils.hook("assert-compile", condition, msg, ast, utils.root.reset)) then 2004 utils.root.reset() 2005 if (unfriendly or not friend or not _G.io or not _G.io.read) then 2006 error(assert_msg(ast, msg), 0) 2007 else 2008 friend["assert-compile"](condition, msg, ast, source) 2009 end 2010 else 2011 end 2012 else 2013 end 2014 return condition 2015 end 2016 scopes.global = make_scope() 2017 scopes.global.vararg = true 2018 scopes.compiler = make_scope(scopes.global) 2019 scopes.macro = scopes.global 2020 local serialize_subst = {["\7"] = "\\a", ["\8"] = "\\b", ["\9"] = "\\t", ["\n"] = "n", ["\11"] = "\\v", ["\12"] = "\\f"} 2021 local function serialize_string(str) 2022 local function _210_(_241) 2023 return ("\\" .. _241:byte()) 2024 end 2025 return string.gsub(string.gsub(string.format("%q", str), ".", serialize_subst), "[\128-\255]", _210_) 2026 end 2027 local function global_mangling(str) 2028 if utils["valid-lua-identifier?"](str) then 2029 return str 2030 else 2031 local function _211_(_241) 2032 return string.format("_%02x", _241:byte()) 2033 end 2034 return ("__fnl_global__" .. str:gsub("[^%w]", _211_)) 2035 end 2036 end 2037 local function global_unmangling(identifier) 2038 local _213_ = string.match(identifier, "^__fnl_global__(.*)$") 2039 if (nil ~= _213_) then 2040 local rest = _213_ 2041 local _214_ 2042 local function _215_(_241) 2043 return string.char(tonumber(_241:sub(2), 16)) 2044 end 2045 _214_ = string.gsub(rest, "_[%da-f][%da-f]", _215_) 2046 return _214_ 2047 elseif true then 2048 local _ = _213_ 2049 return identifier 2050 else 2051 return nil 2052 end 2053 end 2054 local allowed_globals = nil 2055 local function global_allowed_3f(name) 2056 return (not allowed_globals or utils["member?"](name, allowed_globals)) 2057 end 2058 local function unique_mangling(original, mangling, scope, append) 2059 if (scope.unmanglings[mangling] and not scope.gensyms[mangling]) then 2060 return unique_mangling(original, (original .. append), scope, (append + 1)) 2061 else 2062 return mangling 2063 end 2064 end 2065 local function local_mangling(str, scope, ast, _3ftemp_manglings) 2066 assert_compile(not utils["multi-sym?"](str), ("unexpected multi symbol " .. str), ast) 2067 local raw 2068 if ((utils["lua-keywords"])[str] or str:match("^%d")) then 2069 raw = ("_" .. str) 2070 else 2071 raw = str 2072 end 2073 local mangling 2074 local function _219_(_241) 2075 return string.format("_%02x", _241:byte()) 2076 end 2077 mangling = string.gsub(string.gsub(raw, "-", "_"), "[^%w_]", _219_) 2078 local unique = unique_mangling(mangling, mangling, scope, 0) 2079 do end (scope.unmanglings)[unique] = str 2080 do 2081 local manglings = (_3ftemp_manglings or scope.manglings) 2082 do end (manglings)[str] = unique 2083 end 2084 return unique 2085 end 2086 local function apply_manglings(scope, new_manglings, ast) 2087 for raw, mangled in pairs(new_manglings) do 2088 assert_compile(not scope.refedglobals[mangled], ("use of global " .. raw .. " is aliased by a local"), ast) 2089 do end (scope.manglings)[raw] = mangled 2090 end 2091 return nil 2092 end 2093 local function combine_parts(parts, scope) 2094 local ret = (scope.manglings[parts[1]] or global_mangling(parts[1])) 2095 for i = 2, #parts do 2096 if utils["valid-lua-identifier?"](parts[i]) then 2097 if (parts["multi-sym-method-call"] and (i == #parts)) then 2098 ret = (ret .. ":" .. parts[i]) 2099 else 2100 ret = (ret .. "." .. parts[i]) 2101 end 2102 else 2103 ret = (ret .. "[" .. serialize_string(parts[i]) .. "]") 2104 end 2105 end 2106 return ret 2107 end 2108 local function next_append() 2109 utils.root.scope["gensym-append"] = ((utils.root.scope["gensym-append"] or 0) + 1) 2110 return ("_" .. utils.root.scope["gensym-append"] .. "_") 2111 end 2112 local function gensym(scope, _3fbase, _3fsuffix) 2113 local mangling = ((_3fbase or "") .. next_append() .. (_3fsuffix or "")) 2114 while scope.unmanglings[mangling] do 2115 mangling = ((_3fbase or "") .. next_append() .. (_3fsuffix or "")) 2116 end 2117 scope.unmanglings[mangling] = (_3fbase or true) 2118 do end (scope.gensyms)[mangling] = true 2119 return mangling 2120 end 2121 local function autogensym(base, scope) 2122 local _222_ = utils["multi-sym?"](base) 2123 if (nil ~= _222_) then 2124 local parts = _222_ 2125 parts[1] = autogensym(parts[1], scope) 2126 return table.concat(parts, ((parts["multi-sym-method-call"] and ":") or ".")) 2127 elseif true then 2128 local _ = _222_ 2129 local function _223_() 2130 local mangling = gensym(scope, base:sub(1, ( - 2)), "auto") 2131 do end (scope.autogensyms)[base] = mangling 2132 return mangling 2133 end 2134 return (scope.autogensyms[base] or _223_()) 2135 else 2136 return nil 2137 end 2138 end 2139 local function check_binding_valid(symbol, scope, ast) 2140 local name = tostring(symbol) 2141 assert_compile(not name:find("&"), "illegal character &") 2142 assert_compile(not (scope.specials[name] or scope.macros[name]), ("local %s was overshadowed by a special form or macro"):format(name), ast) 2143 return assert_compile(not utils["quoted?"](symbol), string.format("macro tried to bind %s without gensym", name), symbol) 2144 end 2145 local function declare_local(symbol, meta, scope, ast, _3ftemp_manglings) 2146 check_binding_valid(symbol, scope, ast) 2147 local name = tostring(symbol) 2148 assert_compile(not utils["multi-sym?"](name), ("unexpected multi symbol " .. name), ast) 2149 do end (scope.symmeta)[name] = meta 2150 return local_mangling(name, scope, ast, _3ftemp_manglings) 2151 end 2152 local function hashfn_arg_name(name, multi_sym_parts, scope) 2153 if not scope.hashfn then 2154 return nil 2155 elseif (name == "$") then 2156 return "$1" 2157 elseif multi_sym_parts then 2158 if (multi_sym_parts and (multi_sym_parts[1] == "$")) then 2159 multi_sym_parts[1] = "$1" 2160 else 2161 end 2162 return table.concat(multi_sym_parts, ".") 2163 else 2164 return nil 2165 end 2166 end 2167 local function symbol_to_expression(symbol, scope, _3freference_3f) 2168 utils.hook("symbol-to-expression", symbol, scope, _3freference_3f) 2169 local name = symbol[1] 2170 local multi_sym_parts = utils["multi-sym?"](name) 2171 local name0 = (hashfn_arg_name(name, multi_sym_parts, scope) or name) 2172 local parts = (multi_sym_parts or {name0}) 2173 local etype = (((#parts > 1) and "expression") or "sym") 2174 local local_3f = scope.manglings[parts[1]] 2175 if (local_3f and scope.symmeta[parts[1]]) then 2176 scope.symmeta[parts[1]]["used"] = true 2177 else 2178 end 2179 assert_compile(not scope.macros[parts[1]], "tried to reference a macro at runtime", symbol) 2180 assert_compile((not _3freference_3f or local_3f or ("_ENV" == parts[1]) or global_allowed_3f(parts[1])), ("unknown identifier in strict mode: " .. tostring(parts[1])), symbol) 2181 if (allowed_globals and not local_3f and scope.parent) then 2182 scope.parent.refedglobals[parts[1]] = true 2183 else 2184 end 2185 return utils.expr(combine_parts(parts, scope), etype) 2186 end 2187 local function emit(chunk, out, _3fast) 2188 if (type(out) == "table") then 2189 return table.insert(chunk, out) 2190 else 2191 return table.insert(chunk, {ast = _3fast, leaf = out}) 2192 end 2193 end 2194 local function peephole(chunk) 2195 if chunk.leaf then 2196 return chunk 2197 elseif ((#chunk >= 3) and ((chunk[(#chunk - 2)]).leaf == "do") and not (chunk[(#chunk - 1)]).leaf and (chunk[#chunk].leaf == "end")) then 2198 local kid = peephole(chunk[(#chunk - 1)]) 2199 local new_chunk = {ast = chunk.ast} 2200 for i = 1, (#chunk - 3) do 2201 table.insert(new_chunk, peephole(chunk[i])) 2202 end 2203 for i = 1, #kid do 2204 table.insert(new_chunk, kid[i]) 2205 end 2206 return new_chunk 2207 else 2208 return utils.map(chunk, peephole) 2209 end 2210 end 2211 local function flatten_chunk_correlated(main_chunk, options) 2212 local function flatten(chunk, out, last_line, file) 2213 local last_line0 = last_line 2214 if chunk.leaf then 2215 out[last_line0] = ((out[last_line0] or "") .. " " .. chunk.leaf) 2216 else 2217 for _, subchunk in ipairs(chunk) do 2218 if (subchunk.leaf or (#subchunk > 0)) then 2219 local source = utils["ast-source"](subchunk.ast) 2220 if (file == source.filename) then 2221 last_line0 = math.max(last_line0, (source.line or 0)) 2222 else 2223 end 2224 last_line0 = flatten(subchunk, out, last_line0, file) 2225 else 2226 end 2227 end 2228 end 2229 return last_line0 2230 end 2231 local out = {} 2232 local last = flatten(main_chunk, out, 1, options.filename) 2233 for i = 1, last do 2234 if (out[i] == nil) then 2235 out[i] = "" 2236 else 2237 end 2238 end 2239 return table.concat(out, "\n") 2240 end 2241 local function flatten_chunk(sm, chunk, tab, depth) 2242 if chunk.leaf then 2243 local code = chunk.leaf 2244 local info = chunk.ast 2245 if sm then 2246 table.insert(sm, {(info and info.filename), (info and info.line)}) 2247 else 2248 end 2249 return code 2250 else 2251 local tab0 2252 do 2253 local _236_ = tab 2254 if (_236_ == true) then 2255 tab0 = " " 2256 elseif (_236_ == false) then 2257 tab0 = "" 2258 elseif (_236_ == tab) then 2259 tab0 = tab 2260 elseif (_236_ == nil) then 2261 tab0 = "" 2262 else 2263 tab0 = nil 2264 end 2265 end 2266 local function parter(c) 2267 if (c.leaf or (#c > 0)) then 2268 local sub = flatten_chunk(sm, c, tab0, (depth + 1)) 2269 if (depth > 0) then 2270 return (tab0 .. sub:gsub("\n", ("\n" .. tab0))) 2271 else 2272 return sub 2273 end 2274 else 2275 return nil 2276 end 2277 end 2278 return table.concat(utils.map(chunk, parter), "\n") 2279 end 2280 end 2281 local sourcemap = {} 2282 local function make_short_src(source) 2283 local source0 = source:gsub("\n", " ") 2284 if (#source0 <= 49) then 2285 return ("[fennel \"" .. source0 .. "\"]") 2286 else 2287 return ("[fennel \"" .. source0:sub(1, 46) .. "...\"]") 2288 end 2289 end 2290 local function flatten(chunk, options) 2291 local chunk0 = peephole(chunk) 2292 if options.correlate then 2293 return flatten_chunk_correlated(chunk0, options), {} 2294 else 2295 local sm = {} 2296 local ret = flatten_chunk(sm, chunk0, options.indent, 0) 2297 if sm then 2298 sm.short_src = (options.filename or make_short_src((options.source or ret))) 2299 if options.filename then 2300 sm.key = ("@" .. options.filename) 2301 else 2302 sm.key = ret 2303 end 2304 sourcemap[sm.key] = sm 2305 else 2306 end 2307 return ret, sm 2308 end 2309 end 2310 local function make_metadata() 2311 local function _245_(self, tgt, key) 2312 if self[tgt] then 2313 return self[tgt][key] 2314 else 2315 return nil 2316 end 2317 end 2318 local function _247_(self, tgt, key, value) 2319 self[tgt] = (self[tgt] or {}) 2320 do end (self[tgt])[key] = value 2321 return tgt 2322 end 2323 local function _248_(self, tgt, ...) 2324 local kv_len = select("#", ...) 2325 local kvs = {...} 2326 if ((kv_len % 2) ~= 0) then 2327 error("metadata:setall() expected even number of k/v pairs") 2328 else 2329 end 2330 self[tgt] = (self[tgt] or {}) 2331 for i = 1, kv_len, 2 do 2332 self[tgt][kvs[i]] = kvs[(i + 1)] 2333 end 2334 return tgt 2335 end 2336 return setmetatable({}, {__index = {get = _245_, set = _247_, setall = _248_}, __mode = "k"}) 2337 end 2338 local function exprs1(exprs) 2339 return table.concat(utils.map(exprs, tostring), ", ") 2340 end 2341 local function keep_side_effects(exprs, chunk, start, ast) 2342 local start0 = (start or 1) 2343 for j = start0, #exprs do 2344 local se = exprs[j] 2345 if ((se.type == "expression") and (se[1] ~= "nil")) then 2346 emit(chunk, string.format("do local _ = %s end", tostring(se)), ast) 2347 elseif (se.type == "statement") then 2348 local code = tostring(se) 2349 local disambiguated 2350 if (code:byte() == 40) then 2351 disambiguated = ("do end " .. code) 2352 else 2353 disambiguated = code 2354 end 2355 emit(chunk, disambiguated, ast) 2356 else 2357 end 2358 end 2359 return nil 2360 end 2361 local function handle_compile_opts(exprs, parent, opts, ast) 2362 if opts.nval then 2363 local n = opts.nval 2364 local len = #exprs 2365 if (n ~= len) then 2366 if (len > n) then 2367 keep_side_effects(exprs, parent, (n + 1), ast) 2368 for i = (n + 1), len do 2369 exprs[i] = nil 2370 end 2371 else 2372 for i = (#exprs + 1), n do 2373 exprs[i] = utils.expr("nil", "literal") 2374 end 2375 end 2376 else 2377 end 2378 else 2379 end 2380 if opts.tail then 2381 emit(parent, string.format("return %s", exprs1(exprs)), ast) 2382 else 2383 end 2384 if opts.target then 2385 local result = exprs1(exprs) 2386 local function _256_() 2387 if (result == "") then 2388 return "nil" 2389 else 2390 return result 2391 end 2392 end 2393 emit(parent, string.format("%s = %s", opts.target, _256_()), ast) 2394 else 2395 end 2396 if (opts.tail or opts.target) then 2397 return {returned = true} 2398 else 2399 local _258_ = exprs 2400 _258_["returned"] = true 2401 return _258_ 2402 end 2403 end 2404 local function find_macro(ast, scope, multi_sym_parts) 2405 local function find_in_table(t, i) 2406 if (i <= #multi_sym_parts) then 2407 return find_in_table((utils["table?"](t) and t[multi_sym_parts[i]]), (i + 1)) 2408 else 2409 return t 2410 end 2411 end 2412 local macro_2a = (utils["sym?"](ast[1]) and scope.macros[tostring(ast[1])]) 2413 if (not macro_2a and multi_sym_parts) then 2414 local nested_macro = find_in_table(scope.macros, 1) 2415 assert_compile((not scope.macros[multi_sym_parts[1]] or (type(nested_macro) == "function")), "macro not found in imported macro module", ast) 2416 return nested_macro 2417 else 2418 return macro_2a 2419 end 2420 end 2421 local function propagate_trace_info(_262_, _index, node) 2422 local _arg_263_ = _262_ 2423 local filename = _arg_263_["filename"] 2424 local line = _arg_263_["line"] 2425 local bytestart = _arg_263_["bytestart"] 2426 local byteend = _arg_263_["byteend"] 2427 if (("table" == type(node)) and (filename ~= node.filename)) then 2428 local src = utils["ast-source"](node) 2429 src.filename, src.line = filename, line 2430 src.bytestart, src.byteend = bytestart, byteend 2431 else 2432 end 2433 return ("table" == type(node)) 2434 end 2435 local function macroexpand_2a(ast, scope, _3fonce) 2436 local _265_ 2437 if utils["list?"](ast) then 2438 _265_ = find_macro(ast, scope, utils["multi-sym?"](ast[1])) 2439 else 2440 _265_ = nil 2441 end 2442 if (_265_ == false) then 2443 return ast 2444 elseif (nil ~= _265_) then 2445 local macro_2a = _265_ 2446 local old_scope = scopes.macro 2447 local _ 2448 scopes.macro = scope 2449 _ = nil 2450 local ok, transformed = nil, nil 2451 local function _267_() 2452 return macro_2a(unpack(ast, 2)) 2453 end 2454 ok, transformed = xpcall(_267_, debug.traceback) 2455 local function _269_() 2456 local _268_ = ast 2457 local function _270_(...) 2458 return propagate_trace_info(_268_, ...) 2459 end 2460 return _270_ 2461 end 2462 utils["walk-tree"](transformed, _269_()) 2463 scopes.macro = old_scope 2464 assert_compile(ok, transformed, ast) 2465 if (_3fonce or not transformed) then 2466 return transformed 2467 else 2468 return macroexpand_2a(transformed, scope) 2469 end 2470 elseif true then 2471 local _ = _265_ 2472 return ast 2473 else 2474 return nil 2475 end 2476 end 2477 local function compile_special(ast, scope, parent, opts, special) 2478 local exprs = (special(ast, scope, parent, opts) or utils.expr("nil", "literal")) 2479 local exprs0 2480 if ("table" ~= type(exprs)) then 2481 exprs0 = utils.expr(exprs, "expression") 2482 else 2483 exprs0 = exprs 2484 end 2485 local exprs2 2486 if utils["expr?"](exprs0) then 2487 exprs2 = {exprs0} 2488 else 2489 exprs2 = exprs0 2490 end 2491 if not exprs2.returned then 2492 return handle_compile_opts(exprs2, parent, opts, ast) 2493 elseif (opts.tail or opts.target) then 2494 return {returned = true} 2495 else 2496 return exprs2 2497 end 2498 end 2499 local function compile_function_call(ast, scope, parent, opts, compile1, len) 2500 local fargs = {} 2501 local fcallee = (compile1(ast[1], scope, parent, {nval = 1}))[1] 2502 assert_compile((("string" == type(ast[1])) or (fcallee.type ~= "literal")), ("cannot call literal value " .. tostring(ast[1])), ast) 2503 for i = 2, len do 2504 local subexprs 2505 local _276_ 2506 if (i ~= len) then 2507 _276_ = 1 2508 else 2509 _276_ = nil 2510 end 2511 subexprs = compile1(ast[i], scope, parent, {nval = _276_}) 2512 table.insert(fargs, (subexprs[1] or utils.expr("nil", "literal"))) 2513 if (i == len) then 2514 for j = 2, #subexprs do 2515 table.insert(fargs, subexprs[j]) 2516 end 2517 else 2518 keep_side_effects(subexprs, parent, 2, ast[i]) 2519 end 2520 end 2521 local pat 2522 if ("string" == type(ast[1])) then 2523 pat = "(%s)(%s)" 2524 else 2525 pat = "%s(%s)" 2526 end 2527 local call = string.format(pat, tostring(fcallee), exprs1(fargs)) 2528 return handle_compile_opts({utils.expr(call, "statement")}, parent, opts, ast) 2529 end 2530 local function compile_call(ast, scope, parent, opts, compile1) 2531 utils.hook("call", ast, scope) 2532 local len = #ast 2533 local first = ast[1] 2534 local multi_sym_parts = utils["multi-sym?"](first) 2535 local special = (utils["sym?"](first) and scope.specials[tostring(first)]) 2536 assert_compile((len > 0), "expected a function, macro, or special to call", ast) 2537 if special then 2538 return compile_special(ast, scope, parent, opts, special) 2539 elseif (multi_sym_parts and multi_sym_parts["multi-sym-method-call"]) then 2540 local table_with_method = table.concat({unpack(multi_sym_parts, 1, (#multi_sym_parts - 1))}, ".") 2541 local method_to_call = multi_sym_parts[#multi_sym_parts] 2542 local new_ast = utils.list(utils.sym(":", nil, scope), utils.sym(table_with_method, nil, scope), method_to_call, select(2, unpack(ast))) 2543 return compile1(new_ast, scope, parent, opts) 2544 else 2545 return compile_function_call(ast, scope, parent, opts, compile1, len) 2546 end 2547 end 2548 local function compile_varg(ast, scope, parent, opts) 2549 assert_compile(scope.vararg, "unexpected vararg", ast) 2550 return handle_compile_opts({utils.expr("...", "varg")}, parent, opts, ast) 2551 end 2552 local function compile_sym(ast, scope, parent, opts) 2553 local multi_sym_parts = utils["multi-sym?"](ast) 2554 assert_compile(not (multi_sym_parts and multi_sym_parts["multi-sym-method-call"]), "multisym method calls may only be in call position", ast) 2555 local e 2556 if (ast[1] == "nil") then 2557 e = utils.expr("nil", "literal") 2558 else 2559 e = symbol_to_expression(ast, scope, true) 2560 end 2561 return handle_compile_opts({e}, parent, opts, ast) 2562 end 2563 local function serialize_number(n) 2564 local _282_ = string.gsub(tostring(n), ",", ".") 2565 return _282_ 2566 end 2567 local function compile_scalar(ast, _scope, parent, opts) 2568 local serialize 2569 do 2570 local _283_ = type(ast) 2571 if (_283_ == "nil") then 2572 serialize = tostring 2573 elseif (_283_ == "boolean") then 2574 serialize = tostring 2575 elseif (_283_ == "string") then 2576 serialize = serialize_string 2577 elseif (_283_ == "number") then 2578 serialize = serialize_number 2579 else 2580 serialize = nil 2581 end 2582 end 2583 return handle_compile_opts({utils.expr(serialize(ast), "literal")}, parent, opts) 2584 end 2585 local function compile_table(ast, scope, parent, opts, compile1) 2586 local buffer = {} 2587 local function write_other_values(k) 2588 if ((type(k) ~= "number") or (math.floor(k) ~= k) or (k < 1) or (k > #ast)) then 2589 if ((type(k) == "string") and utils["valid-lua-identifier?"](k)) then 2590 return {k, k} 2591 else 2592 local _let_285_ = compile1(k, scope, parent, {nval = 1}) 2593 local compiled = _let_285_[1] 2594 local kstr = ("[" .. tostring(compiled) .. "]") 2595 return {kstr, k} 2596 end 2597 else 2598 return nil 2599 end 2600 end 2601 do 2602 local keys 2603 do 2604 local tbl_14_auto = {} 2605 local i_15_auto = #tbl_14_auto 2606 for k, v in utils.stablepairs(ast) do 2607 local val_16_auto = write_other_values(k, v) 2608 if (nil ~= val_16_auto) then 2609 i_15_auto = (i_15_auto + 1) 2610 do end (tbl_14_auto)[i_15_auto] = val_16_auto 2611 else 2612 end 2613 end 2614 keys = tbl_14_auto 2615 end 2616 local function _291_(_289_) 2617 local _arg_290_ = _289_ 2618 local k1 = _arg_290_[1] 2619 local k2 = _arg_290_[2] 2620 local _let_292_ = compile1(ast[k2], scope, parent, {nval = 1}) 2621 local v = _let_292_[1] 2622 return string.format("%s = %s", k1, tostring(v)) 2623 end 2624 utils.map(keys, _291_, buffer) 2625 end 2626 for i = 1, #ast do 2627 local nval = ((i ~= #ast) and 1) 2628 table.insert(buffer, exprs1(compile1(ast[i], scope, parent, {nval = nval}))) 2629 end 2630 return handle_compile_opts({utils.expr(("{" .. table.concat(buffer, ", ") .. "}"), "expression")}, parent, opts, ast) 2631 end 2632 local function compile1(ast, scope, parent, _3fopts) 2633 local opts = (_3fopts or {}) 2634 local ast0 = macroexpand_2a(ast, scope) 2635 if utils["list?"](ast0) then 2636 return compile_call(ast0, scope, parent, opts, compile1) 2637 elseif utils["varg?"](ast0) then 2638 return compile_varg(ast0, scope, parent, opts) 2639 elseif utils["sym?"](ast0) then 2640 return compile_sym(ast0, scope, parent, opts) 2641 elseif (type(ast0) == "table") then 2642 return compile_table(ast0, scope, parent, opts, compile1) 2643 elseif ((type(ast0) == "nil") or (type(ast0) == "boolean") or (type(ast0) == "number") or (type(ast0) == "string")) then 2644 return compile_scalar(ast0, scope, parent, opts) 2645 else 2646 return assert_compile(false, ("could not compile value of type " .. type(ast0)), ast0) 2647 end 2648 end 2649 local function destructure(to, from, ast, scope, parent, opts) 2650 local opts0 = (opts or {}) 2651 local _let_294_ = opts0 2652 local isvar = _let_294_["isvar"] 2653 local declaration = _let_294_["declaration"] 2654 local forceglobal = _let_294_["forceglobal"] 2655 local forceset = _let_294_["forceset"] 2656 local symtype = _let_294_["symtype"] 2657 local symtype0 = ("_" .. (symtype or "dst")) 2658 local setter 2659 if declaration then 2660 setter = "local %s = %s" 2661 else 2662 setter = "%s = %s" 2663 end 2664 local new_manglings = {} 2665 local function getname(symbol, up1) 2666 local raw = symbol[1] 2667 assert_compile(not (opts0.nomulti and utils["multi-sym?"](raw)), ("unexpected multi symbol " .. raw), up1) 2668 if declaration then 2669 return declare_local(symbol, nil, scope, symbol, new_manglings) 2670 else 2671 local parts = (utils["multi-sym?"](raw) or {raw}) 2672 local meta = scope.symmeta[parts[1]] 2673 assert_compile(not raw:find(":"), "cannot set method sym", symbol) 2674 if ((#parts == 1) and not forceset) then 2675 assert_compile(not (forceglobal and meta), string.format("global %s conflicts with local", tostring(symbol)), symbol) 2676 assert_compile(not (meta and not meta.var), ("expected var " .. raw), symbol) 2677 assert_compile((meta or not opts0.noundef), ("expected local " .. parts[1]), symbol) 2678 else 2679 end 2680 if forceglobal then 2681 assert_compile(not scope.symmeta[scope.unmanglings[raw]], ("global " .. raw .. " conflicts with local"), symbol) 2682 do end (scope.manglings)[raw] = global_mangling(raw) 2683 do end (scope.unmanglings)[global_mangling(raw)] = raw 2684 if allowed_globals then 2685 table.insert(allowed_globals, raw) 2686 else 2687 end 2688 else 2689 end 2690 return symbol_to_expression(symbol, scope)[1] 2691 end 2692 end 2693 local function compile_top_target(lvalues) 2694 local inits 2695 local function _300_(_241) 2696 if scope.manglings[_241] then 2697 return _241 2698 else 2699 return "nil" 2700 end 2701 end 2702 inits = utils.map(lvalues, _300_) 2703 local init = table.concat(inits, ", ") 2704 local lvalue = table.concat(lvalues, ", ") 2705 local plen, plast = #parent, parent[#parent] 2706 local ret = compile1(from, scope, parent, {target = lvalue}) 2707 if declaration then 2708 for pi = plen, #parent do 2709 if (parent[pi] == plast) then 2710 plen = pi 2711 else 2712 end 2713 end 2714 if ((#parent == (plen + 1)) and parent[#parent].leaf) then 2715 parent[#parent]["leaf"] = ("local " .. parent[#parent].leaf) 2716 elseif (init == "nil") then 2717 table.insert(parent, (plen + 1), {ast = ast, leaf = ("local " .. lvalue)}) 2718 else 2719 table.insert(parent, (plen + 1), {ast = ast, leaf = ("local " .. lvalue .. " = " .. init)}) 2720 end 2721 else 2722 end 2723 return ret 2724 end 2725 local function destructure_sym(left, rightexprs, up1, top_3f) 2726 local lname = getname(left, up1) 2727 check_binding_valid(left, scope, left) 2728 if top_3f then 2729 compile_top_target({lname}) 2730 else 2731 emit(parent, setter:format(lname, exprs1(rightexprs)), left) 2732 end 2733 if declaration then 2734 scope.symmeta[tostring(left)] = {var = isvar} 2735 return nil 2736 else 2737 return nil 2738 end 2739 end 2740 local function destructure_table(left, rightexprs, top_3f, destructure1) 2741 local s = gensym(scope, symtype0) 2742 local right 2743 do 2744 local _307_ 2745 if top_3f then 2746 _307_ = exprs1(compile1(from, scope, parent)) 2747 else 2748 _307_ = exprs1(rightexprs) 2749 end 2750 if (_307_ == "") then 2751 right = "nil" 2752 elseif (nil ~= _307_) then 2753 local right0 = _307_ 2754 right = right0 2755 else 2756 right = nil 2757 end 2758 end 2759 emit(parent, string.format("local %s = %s", s, right), left) 2760 for k, v in utils.stablepairs(left) do 2761 if not (("number" == type(k)) and tostring(left[(k - 1)]):find("^&")) then 2762 if (utils["sym?"](v) and (tostring(v) == "&")) then 2763 local unpack_str = "(function (t, k)\n local mt = getmetatable(t)\n if \"table\" == type(mt) and mt.__fennelrest then\n return mt.__fennelrest(t, k)\n else\n return {(table.unpack or unpack)(t, k)}\n end\n end)(%s, %s)" 2764 local formatted = string.format(string.gsub(unpack_str, "\n%s*", " "), s, k) 2765 local subexpr = utils.expr(formatted, "expression") 2766 assert_compile((utils["sequence?"](left) and (nil == left[(k + 2)])), "expected rest argument before last parameter", left) 2767 destructure1(left[(k + 1)], {subexpr}, left) 2768 elseif (utils["sym?"](k) and (tostring(k) == "&as")) then 2769 destructure_sym(v, {utils.expr(tostring(s))}, left) 2770 elseif (utils["sequence?"](left) and (tostring(v) == "&as")) then 2771 local _, next_sym, trailing = select(k, unpack(left)) 2772 assert_compile((nil == trailing), "expected &as argument before last parameter", left) 2773 destructure_sym(next_sym, {utils.expr(tostring(s))}, left) 2774 else 2775 local key 2776 if (type(k) == "string") then 2777 key = serialize_string(k) 2778 else 2779 key = k 2780 end 2781 local subexpr = utils.expr(string.format("%s[%s]", s, key), "expression") 2782 destructure1(v, {subexpr}, left) 2783 end 2784 else 2785 end 2786 end 2787 return nil 2788 end 2789 local function destructure_values(left, up1, top_3f, destructure1) 2790 local left_names, tables = {}, {} 2791 for i, name in ipairs(left) do 2792 if utils["sym?"](name) then 2793 table.insert(left_names, getname(name, up1)) 2794 else 2795 local symname = gensym(scope, symtype0) 2796 table.insert(left_names, symname) 2797 do end (tables)[i] = {name, utils.expr(symname, "sym")} 2798 end 2799 end 2800 assert_compile(top_3f, "can't nest multi-value destructuring", left) 2801 compile_top_target(left_names) 2802 if declaration then 2803 for _, sym in ipairs(left) do 2804 if utils["sym?"](sym) then 2805 scope.symmeta[tostring(sym)] = {var = isvar} 2806 else 2807 end 2808 end 2809 else 2810 end 2811 for _, pair in utils.stablepairs(tables) do 2812 destructure1(pair[1], {pair[2]}, left) 2813 end 2814 return nil 2815 end 2816 local function destructure1(left, rightexprs, up1, top_3f) 2817 if (utils["sym?"](left) and (left[1] ~= "nil")) then 2818 destructure_sym(left, rightexprs, up1, top_3f) 2819 elseif utils["table?"](left) then 2820 destructure_table(left, rightexprs, top_3f, destructure1) 2821 elseif utils["list?"](left) then 2822 destructure_values(left, up1, top_3f, destructure1) 2823 else 2824 assert_compile(false, string.format("unable to bind %s %s", type(left), tostring(left)), (((type((up1)[2]) == "table") and (up1)[2]) or up1)) 2825 end 2826 if top_3f then 2827 return {returned = true} 2828 else 2829 return nil 2830 end 2831 end 2832 local ret = destructure1(to, nil, ast, true) 2833 utils.hook("destructure", from, to, scope) 2834 apply_manglings(scope, new_manglings, ast) 2835 return ret 2836 end 2837 local function require_include(ast, scope, parent, opts) 2838 opts.fallback = function(e) 2839 utils.warn(("include module not found, falling back to require: %s"):format(tostring(e))) 2840 return utils.expr(string.format("require(%s)", tostring(e)), "statement") 2841 end 2842 return scopes.global.specials.include(ast, scope, parent, opts) 2843 end 2844 local function compile_stream(strm, options) 2845 local opts = utils.copy(options) 2846 local old_globals = allowed_globals 2847 local scope = (opts.scope or make_scope(scopes.global)) 2848 local vals = {} 2849 local chunk = {} 2850 do end (function(tgt, m, ...) return tgt[m](tgt, ...) end)(utils.root, "set-reset") 2851 allowed_globals = opts.allowedGlobals 2852 if (opts.indent == nil) then 2853 opts.indent = " " 2854 else 2855 end 2856 if opts.requireAsInclude then 2857 scope.specials.require = require_include 2858 else 2859 end 2860 utils.root.chunk, utils.root.scope, utils.root.options = chunk, scope, opts 2861 for _, val in parser.parser(strm, opts.filename, opts) do 2862 table.insert(vals, val) 2863 end 2864 for i = 1, #vals do 2865 local exprs = compile1(vals[i], scope, chunk, {nval = (((i < #vals) and 0) or nil), tail = (i == #vals)}) 2866 keep_side_effects(exprs, chunk, nil, vals[i]) 2867 if (i == #vals) then 2868 utils.hook("chunk", vals[i], scope) 2869 else 2870 end 2871 end 2872 allowed_globals = old_globals 2873 utils.root.reset() 2874 return flatten(chunk, opts) 2875 end 2876 local function compile_string(str, opts) 2877 return compile_stream(parser["string-stream"](str), (opts or {})) 2878 end 2879 local function compile(ast, opts) 2880 local opts0 = utils.copy(opts) 2881 local old_globals = allowed_globals 2882 local chunk = {} 2883 local scope = (opts0.scope or make_scope(scopes.global)) 2884 do end (function(tgt, m, ...) return tgt[m](tgt, ...) end)(utils.root, "set-reset") 2885 allowed_globals = opts0.allowedGlobals 2886 if (opts0.indent == nil) then 2887 opts0.indent = " " 2888 else 2889 end 2890 if opts0.requireAsInclude then 2891 scope.specials.require = require_include 2892 else 2893 end 2894 utils.root.chunk, utils.root.scope, utils.root.options = chunk, scope, opts0 2895 local exprs = compile1(ast, scope, chunk, {tail = true}) 2896 keep_side_effects(exprs, chunk, nil, ast) 2897 utils.hook("chunk", ast, scope) 2898 allowed_globals = old_globals 2899 utils.root.reset() 2900 return flatten(chunk, opts0) 2901 end 2902 local function traceback_frame(info) 2903 if ((info.what == "C") and info.name) then 2904 return string.format(" [C]: in function '%s'", info.name) 2905 elseif (info.what == "C") then 2906 return " [C]: in ?" 2907 else 2908 local remap = sourcemap[info.source] 2909 if (remap and remap[info.currentline]) then 2910 if remap[info.currentline][1] then 2911 info.short_src = sourcemap[("@" .. remap[info.currentline][1])].short_src 2912 else 2913 info.short_src = remap.short_src 2914 end 2915 info.currentline = (remap[info.currentline][2] or -1) 2916 else 2917 end 2918 if (info.what == "Lua") then 2919 local function _325_() 2920 if info.name then 2921 return ("'" .. info.name .. "'") 2922 else 2923 return "?" 2924 end 2925 end 2926 return string.format(" %s:%d: in function %s", info.short_src, info.currentline, _325_()) 2927 elseif (info.short_src == "(tail call)") then 2928 return " (tail call)" 2929 else 2930 return string.format(" %s:%d: in main chunk", info.short_src, info.currentline) 2931 end 2932 end 2933 end 2934 local function traceback(msg, start) 2935 local msg0 = tostring((msg or "")) 2936 if ((msg0:find("^Compile error") or msg0:find("^Parse error")) and not utils["debug-on?"]("trace")) then 2937 return msg0 2938 else 2939 local lines = {} 2940 if (msg0:find(":%d+: Compile error") or msg0:find(":%d+: Parse error")) then 2941 table.insert(lines, msg0) 2942 else 2943 local newmsg = msg0:gsub("^[^:]*:%d+:%s+", "runtime error: ") 2944 table.insert(lines, newmsg) 2945 end 2946 table.insert(lines, "stack traceback:") 2947 local done_3f, level = false, (start or 2) 2948 while not done_3f do 2949 do 2950 local _329_ = debug.getinfo(level, "Sln") 2951 if (_329_ == nil) then 2952 done_3f = true 2953 elseif (nil ~= _329_) then 2954 local info = _329_ 2955 table.insert(lines, traceback_frame(info)) 2956 else 2957 end 2958 end 2959 level = (level + 1) 2960 end 2961 return table.concat(lines, "\n") 2962 end 2963 end 2964 local function entry_transform(fk, fv) 2965 local function _332_(k, v) 2966 if (type(k) == "number") then 2967 return k, fv(v) 2968 else 2969 return fk(k), fv(v) 2970 end 2971 end 2972 return _332_ 2973 end 2974 local function mixed_concat(t, joiner) 2975 local seen = {} 2976 local ret, s = "", "" 2977 for k, v in ipairs(t) do 2978 table.insert(seen, k) 2979 ret = (ret .. s .. v) 2980 s = joiner 2981 end 2982 for k, v in utils.stablepairs(t) do 2983 if not seen[k] then 2984 ret = (ret .. s .. "[" .. k .. "]" .. "=" .. v) 2985 s = joiner 2986 else 2987 end 2988 end 2989 return ret 2990 end 2991 local function do_quote(form, scope, parent, runtime_3f) 2992 local function q(x) 2993 return do_quote(x, scope, parent, runtime_3f) 2994 end 2995 if utils["varg?"](form) then 2996 assert_compile(not runtime_3f, "quoted ... may only be used at compile time", form) 2997 return "_VARARG" 2998 elseif utils["sym?"](form) then 2999 local filename 3000 if form.filename then 3001 filename = string.format("%q", form.filename) 3002 else 3003 filename = "nil" 3004 end 3005 local symstr = tostring(form) 3006 assert_compile(not runtime_3f, "symbols may only be used at compile time", form) 3007 if (symstr:find("#$") or symstr:find("#[:.]")) then 3008 return string.format("sym('%s', {filename=%s, line=%s})", autogensym(symstr, scope), filename, (form.line or "nil")) 3009 else 3010 return string.format("sym('%s', {quoted=true, filename=%s, line=%s})", symstr, filename, (form.line or "nil")) 3011 end 3012 elseif (utils["list?"](form) and utils["sym?"](form[1]) and (tostring(form[1]) == "unquote")) then 3013 local payload = form[2] 3014 local res = unpack(compile1(payload, scope, parent)) 3015 return res[1] 3016 elseif utils["list?"](form) then 3017 local mapped 3018 local function _337_() 3019 return nil 3020 end 3021 mapped = utils.kvmap(form, entry_transform(_337_, q)) 3022 local filename 3023 if form.filename then 3024 filename = string.format("%q", form.filename) 3025 else 3026 filename = "nil" 3027 end 3028 assert_compile(not runtime_3f, "lists may only be used at compile time", form) 3029 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, ", ")) 3030 elseif utils["sequence?"](form) then 3031 local mapped = utils.kvmap(form, entry_transform(q, q)) 3032 local source = getmetatable(form) 3033 local filename 3034 if source.filename then 3035 filename = string.format("%q", source.filename) 3036 else 3037 filename = "nil" 3038 end 3039 local _340_ 3040 if source then 3041 _340_ = source.line 3042 else 3043 _340_ = "nil" 3044 end 3045 return string.format("setmetatable({%s}, {filename=%s, line=%s, sequence=%s})", mixed_concat(mapped, ", "), filename, _340_, "(getmetatable(sequence()))['sequence']") 3046 elseif (type(form) == "table") then 3047 local mapped = utils.kvmap(form, entry_transform(q, q)) 3048 local source = getmetatable(form) 3049 local filename 3050 if source.filename then 3051 filename = string.format("%q", source.filename) 3052 else 3053 filename = "nil" 3054 end 3055 local function _343_() 3056 if source then 3057 return source.line 3058 else 3059 return "nil" 3060 end 3061 end 3062 return string.format("setmetatable({%s}, {filename=%s, line=%s})", mixed_concat(mapped, ", "), filename, _343_()) 3063 elseif (type(form) == "string") then 3064 return serialize_string(form) 3065 else 3066 return tostring(form) 3067 end 3068 end 3069 return {compile = compile, compile1 = compile1, ["compile-stream"] = compile_stream, ["compile-string"] = compile_string, emit = emit, destructure = destructure, ["require-include"] = require_include, autogensym = autogensym, gensym = gensym, ["do-quote"] = do_quote, ["global-mangling"] = global_mangling, ["global-unmangling"] = global_unmangling, ["apply-manglings"] = apply_manglings, macroexpand = macroexpand_2a, ["declare-local"] = declare_local, ["make-scope"] = make_scope, ["keep-side-effects"] = keep_side_effects, ["symbol-to-expression"] = symbol_to_expression, assert = assert_compile, scopes = scopes, traceback = traceback, metadata = make_metadata(), sourcemap = sourcemap} 3070end 3071package.preload["fennel.friend"] = package.preload["fennel.friend"] or function(...) 3072 local utils = require("fennel.utils") 3073 local suggestions = {["unexpected multi symbol (.*)"] = {"removing periods or colons from %s"}, ["use of global (.*) is aliased by a local"] = {"renaming local %s", "refer to the global using _G.%s instead of directly"}, ["local (.*) was overshadowed by a special form or macro"] = {"renaming local %s"}, ["global (.*) conflicts with local"] = {"renaming local %s"}, ["expected var (.*)"] = {"declaring %s using var instead of let/local", "introducing a new local instead of changing the value of %s"}, ["expected macros to be table"] = {"ensuring your macro definitions return a table"}, ["expected each macro to be function"] = {"ensuring that the value for each key in your macros table contains a function", "avoid defining nested macro tables"}, ["macro not found in macro module"] = {"checking the keys of the imported macro module's returned table"}, ["macro tried to bind (.*) without gensym"] = {"changing to %s# when introducing identifiers inside macros"}, ["unknown identifier in strict mode: (.*)"] = {"looking to see if there's a typo", "using the _G table instead, eg. _G.%s if you really want a global", "moving this code to somewhere that %s is in scope", "binding %s as a local in the scope of this code"}, ["expected a function.* to call"] = {"removing the empty parentheses", "using square brackets if you want an empty table"}, ["cannot call literal value"] = {"checking for typos", "checking for a missing function name"}, ["unexpected vararg"] = {"putting \"...\" at the end of the fn parameters if the vararg was intended"}, ["multisym method calls may only be in call position"] = {"using a period instead of a colon to reference a table's fields", "putting parens around this"}, ["unused local (.*)"] = {"renaming the local to _%s if it is meant to be unused", "fixing a typo so %s is used", "disabling the linter which checks for unused locals"}, ["expected parameters"] = {"adding function parameters as a list of identifiers in brackets"}, ["unable to bind (.*)"] = {"replacing the %s with an identifier"}, ["expected rest argument before last parameter"] = {"moving & to right before the final identifier when destructuring"}, ["expected vararg as last parameter"] = {"moving the \"...\" to the end of the parameter list"}, ["expected symbol for function parameter: (.*)"] = {"changing %s to an identifier instead of a literal value"}, ["could not compile value of type "] = {"debugging the macro you're calling to return a list or table"}, ["expected local"] = {"looking for a typo", "looking for a local which is used out of its scope"}, ["expected body expression"] = {"putting some code in the body of this form after the bindings"}, ["expected binding and iterator"] = {"making sure you haven't omitted a local name or iterator"}, ["expected binding sequence"] = {"placing a table here in square brackets containing identifiers to bind"}, ["expected even number of name/value bindings"] = {"finding where the identifier or value is missing"}, ["may only be used at compile time"] = {"moving this to inside a macro if you need to manipulate symbols/lists", "using square brackets instead of parens to construct a table"}, ["unexpected closing delimiter (.)"] = {"deleting %s", "adding matching opening delimiter earlier"}, ["mismatched closing delimiter (.), expected (.)"] = {"replacing %s with %s", "deleting %s", "adding matching opening delimiter earlier"}, ["expected even number of values in table literal"] = {"removing a key", "adding a value"}, ["expected whitespace before opening delimiter"] = {"adding whitespace"}, ["illegal character: (.)"] = {"deleting or replacing %s", "avoiding reserved characters like \", \\, ', ~, ;, @, `, and comma"}, ["could not read number (.*)"] = {"removing the non-digit character", "beginning the identifier with a non-digit if it is not meant to be a number"}, ["can't start multisym segment with a digit"] = {"removing the digit", "adding a non-digit before the digit"}, ["malformed multisym"] = {"ensuring each period or colon is not followed by another period or colon"}, ["method must be last component"] = {"using a period instead of a colon for field access", "removing segments after the colon", "making the method call, then looking up the field on the result"}, ["$ and $... in hashfn are mutually exclusive"] = {"modifying the hashfn so it only contains $... or $, $1, $2, $3, etc"}, ["tried to reference a macro at runtime"] = {"renaming the macro so as not to conflict with locals"}, ["expected even number of pattern/body pairs"] = {"checking that every pattern has a body to go with it", "adding _ before the final body"}, ["unexpected arguments"] = {"removing an argument", "checking for typos"}, ["unexpected iterator clause"] = {"removing an argument", "checking for typos"}} 3074 local unpack = (table.unpack or _G.unpack) 3075 local function suggest(msg) 3076 local suggestion = nil 3077 for pat, sug in pairs(suggestions) do 3078 local matches = {msg:match(pat)} 3079 if (0 < #matches) then 3080 if ("table" == type(sug)) then 3081 local out = {} 3082 for _, s in ipairs(sug) do 3083 table.insert(out, s:format(unpack(matches))) 3084 end 3085 suggestion = out 3086 else 3087 suggestion = sug(matches) 3088 end 3089 else 3090 end 3091 end 3092 return suggestion 3093 end 3094 local function read_line_from_file(filename, line) 3095 local bytes = 0 3096 local f = assert(io.open(filename)) 3097 local _ 3098 for _0 = 1, (line - 1) do 3099 bytes = (bytes + 1 + #f:read()) 3100 end 3101 _ = nil 3102 local codeline = f:read() 3103 f:close() 3104 return codeline, bytes 3105 end 3106 local function read_line_from_string(matcher, target_line, _3fcurrent_line, _3fbytes) 3107 local this_line, newline = matcher() 3108 local current_line = (_3fcurrent_line or 1) 3109 local bytes = ((_3fbytes or 0) + #this_line + #newline) 3110 if (target_line == current_line) then 3111 return this_line, (bytes - #this_line - 1) 3112 elseif this_line then 3113 return read_line_from_string(matcher, target_line, (current_line + 1), bytes) 3114 else 3115 return nil 3116 end 3117 end 3118 local function read_line(filename, line, source) 3119 if source then 3120 return read_line_from_string(string.gmatch((source .. "\n"), "(.-)(\13?\n)"), line) 3121 else 3122 return read_line_from_file(filename, line) 3123 end 3124 end 3125 local function friendly_msg(msg, _142_, source) 3126 local _arg_143_ = _142_ 3127 local filename = _arg_143_["filename"] 3128 local line = _arg_143_["line"] 3129 local bytestart = _arg_143_["bytestart"] 3130 local byteend = _arg_143_["byteend"] 3131 local ok, codeline, bol = pcall(read_line, filename, line, source) 3132 local suggestions0 = suggest(msg) 3133 local out = {msg, ""} 3134 if (ok and codeline) then 3135 table.insert(out, codeline) 3136 else 3137 end 3138 if (ok and codeline and bytestart and byteend) then 3139 table.insert(out, (string.rep(" ", (bytestart - bol - 1)) .. "^" .. string.rep("^", math.min((byteend - bytestart), ((bol + #codeline) - bytestart))))) 3140 else 3141 end 3142 if (ok and codeline and bytestart and not byteend) then 3143 table.insert(out, (string.rep("-", (bytestart - bol - 1)) .. "^")) 3144 table.insert(out, "") 3145 else 3146 end 3147 if suggestions0 then 3148 for _, suggestion in ipairs(suggestions0) do 3149 table.insert(out, ("* Try %s."):format(suggestion)) 3150 end 3151 else 3152 end 3153 return table.concat(out, "\n") 3154 end 3155 local function assert_compile(condition, msg, ast, source) 3156 if not condition then 3157 local _let_148_ = utils["ast-source"](ast) 3158 local filename = _let_148_["filename"] 3159 local line = _let_148_["line"] 3160 error(friendly_msg(("Compile error in %s:%s\n %s"):format((filename or "unknown"), (line or "?"), msg), utils["ast-source"](ast), source), 0) 3161 else 3162 end 3163 return condition 3164 end 3165 local function parse_error(msg, filename, line, bytestart, source) 3166 return error(friendly_msg(("Parse error in %s:%s\n %s"):format(filename, line, msg), {filename = filename, line = line, bytestart = bytestart}, source), 0) 3167 end 3168 return {["assert-compile"] = assert_compile, ["parse-error"] = parse_error} 3169end 3170package.preload["fennel.parser"] = package.preload["fennel.parser"] or function(...) 3171 local utils = require("fennel.utils") 3172 local friend = require("fennel.friend") 3173 local unpack = (table.unpack or _G.unpack) 3174 local function granulate(getchunk) 3175 local c, index, done_3f = "", 1, false 3176 local function _150_(parser_state) 3177 if not done_3f then 3178 if (index <= #c) then 3179 local b = c:byte(index) 3180 index = (index + 1) 3181 return b 3182 else 3183 local _151_ = getchunk(parser_state) 3184 local function _152_() 3185 local char = _151_ 3186 return (char ~= "") 3187 end 3188 if ((nil ~= _151_) and _152_()) then 3189 local char = _151_ 3190 c = char 3191 index = 2 3192 return c:byte() 3193 elseif true then 3194 local _ = _151_ 3195 done_3f = true 3196 return nil 3197 else 3198 return nil 3199 end 3200 end 3201 else 3202 return nil 3203 end 3204 end 3205 local function _156_() 3206 c = "" 3207 return nil 3208 end 3209 return _150_, _156_ 3210 end 3211 local function string_stream(str) 3212 local str0 = str:gsub("^#!", ";;") 3213 local index = 1 3214 local function _157_() 3215 local r = str0:byte(index) 3216 index = (index + 1) 3217 return r 3218 end 3219 return _157_ 3220 end 3221 local delims = {[40] = 41, [41] = true, [91] = 93, [93] = true, [123] = 125, [125] = true} 3222 local function whitespace_3f(b) 3223 return ((b == 32) or ((b >= 9) and (b <= 13))) 3224 end 3225 local function sym_char_3f(b) 3226 local b0 3227 if ("number" == type(b)) then 3228 b0 = b 3229 else 3230 b0 = string.byte(b) 3231 end 3232 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)) 3233 end 3234 local prefixes = {[35] = "hashfn", [39] = "quote", [44] = "unquote", [96] = "quote"} 3235 local function parser(getbyte, _3ffilename, _3foptions) 3236 local stack = {} 3237 local line = 1 3238 local byteindex = 0 3239 local lastb = nil 3240 local function ungetb(ub) 3241 if (ub == 10) then 3242 line = (line - 1) 3243 else 3244 end 3245 byteindex = (byteindex - 1) 3246 lastb = ub 3247 return nil 3248 end 3249 local function getb() 3250 local r = nil 3251 if lastb then 3252 r, lastb = lastb, nil 3253 else 3254 r = getbyte({["stack-size"] = #stack}) 3255 end 3256 byteindex = (byteindex + 1) 3257 if (r == 10) then 3258 line = (line + 1) 3259 else 3260 end 3261 return r 3262 end 3263 assert(((nil == _3ffilename) or ("string" == type(_3ffilename))), "expected filename as second argument to parser") 3264 local function parse_error(msg, byteindex_override) 3265 local _let_162_ = (_3foptions or utils.root.options or {}) 3266 local source = _let_162_["source"] 3267 local unfriendly = _let_162_["unfriendly"] 3268 if (nil == utils.hook("parse-error", msg, (_3ffilename or "unknown"), (line or "?"), (byteindex_override or byteindex), source, utils.root.reset)) then 3269 utils.root.reset() 3270 if (unfriendly or not friend or not _G.io or not _G.io.read) then 3271 return error(string.format("%s:%s: Parse error: %s", (_3ffilename or "unknown"), (line or "?"), msg), 0) 3272 else 3273 return friend["parse-error"](msg, (_3ffilename or "unknown"), (line or "?"), (byteindex_override or byteindex), source) 3274 end 3275 else 3276 return nil 3277 end 3278 end 3279 local function parse_stream() 3280 local whitespace_since_dispatch, done_3f, retval = true 3281 local function dispatch(v) 3282 local _165_ = stack[#stack] 3283 if (_165_ == nil) then 3284 retval, done_3f, whitespace_since_dispatch = v, true, false 3285 return nil 3286 elseif ((_G.type(_165_) == "table") and (nil ~= (_165_).prefix)) then 3287 local prefix = (_165_).prefix 3288 local source 3289 do 3290 local _166_ = table.remove(stack) 3291 do end (_166_)["byteend"] = byteindex 3292 source = _166_ 3293 end 3294 local list = utils.list(utils.sym(prefix, source), v) 3295 for k, v0 in pairs(source) do 3296 list[k] = v0 3297 end 3298 return dispatch(list) 3299 elseif (nil ~= _165_) then 3300 local top = _165_ 3301 whitespace_since_dispatch = false 3302 return table.insert(top, v) 3303 else 3304 return nil 3305 end 3306 end 3307 local function badend() 3308 local accum = utils.map(stack, "closer") 3309 local _168_ 3310 if (#stack == 1) then 3311 _168_ = "" 3312 else 3313 _168_ = "s" 3314 end 3315 return parse_error(string.format("expected closing delimiter%s %s", _168_, string.char(unpack(accum)))) 3316 end 3317 local function skip_whitespace(b) 3318 if (b and whitespace_3f(b)) then 3319 whitespace_since_dispatch = true 3320 return skip_whitespace(getb()) 3321 elseif (not b and (#stack > 0)) then 3322 return badend() 3323 else 3324 return b 3325 end 3326 end 3327 local function parse_comment(b, contents) 3328 if (b and (10 ~= b)) then 3329 local function _172_() 3330 local _171_ = contents 3331 table.insert(_171_, string.char(b)) 3332 return _171_ 3333 end 3334 return parse_comment(getb(), _172_()) 3335 elseif (_3foptions and _3foptions.comments) then 3336 return dispatch(utils.comment(table.concat(contents), {line = (line - 1), filename = _3ffilename})) 3337 else 3338 return b 3339 end 3340 end 3341 local function open_table(b) 3342 if not whitespace_since_dispatch then 3343 parse_error(("expected whitespace before opening delimiter " .. string.char(b))) 3344 else 3345 end 3346 return table.insert(stack, {bytestart = byteindex, closer = delims[b], filename = _3ffilename, line = line}) 3347 end 3348 local function close_list(list) 3349 return dispatch(setmetatable(list, getmetatable(utils.list()))) 3350 end 3351 local function close_sequence(tbl) 3352 local val = utils.sequence(unpack(tbl)) 3353 for k, v in pairs(tbl) do 3354 getmetatable(val)[k] = v 3355 end 3356 return dispatch(val) 3357 end 3358 local function add_comment_at(comments, index, node) 3359 local _175_ = comments[index] 3360 if (nil ~= _175_) then 3361 local existing = _175_ 3362 return table.insert(existing, node) 3363 elseif true then 3364 local _ = _175_ 3365 comments[index] = {node} 3366 return nil 3367 else 3368 return nil 3369 end 3370 end 3371 local function next_noncomment(tbl, i) 3372 if utils["comment?"](tbl[i]) then 3373 return next_noncomment(tbl, (i + 1)) 3374 else 3375 return tbl[i] 3376 end 3377 end 3378 local function extract_comments(tbl) 3379 local comments = {keys = {}, values = {}, last = {}} 3380 while utils["comment?"](tbl[#tbl]) do 3381 table.insert(comments.last, 1, table.remove(tbl)) 3382 end 3383 local last_key_3f = false 3384 for i, node in ipairs(tbl) do 3385 if not utils["comment?"](node) then 3386 last_key_3f = not last_key_3f 3387 elseif last_key_3f then 3388 add_comment_at(comments.values, next_noncomment(tbl, i), node) 3389 else 3390 add_comment_at(comments.keys, next_noncomment(tbl, i), node) 3391 end 3392 end 3393 for i = #tbl, 1, -1 do 3394 if utils["comment?"](tbl[i]) then 3395 table.remove(tbl, i) 3396 else 3397 end 3398 end 3399 return comments 3400 end 3401 local function close_curly_table(tbl) 3402 local comments = extract_comments(tbl) 3403 local keys = {} 3404 local val = {} 3405 if ((#tbl % 2) ~= 0) then 3406 byteindex = (byteindex - 1) 3407 parse_error("expected even number of values in table literal") 3408 else 3409 end 3410 setmetatable(val, tbl) 3411 for i = 1, #tbl, 2 do 3412 if ((tostring(tbl[i]) == ":") and utils["sym?"](tbl[(i + 1)]) and utils["sym?"](tbl[i])) then 3413 tbl[i] = tostring(tbl[(i + 1)]) 3414 else 3415 end 3416 val[tbl[i]] = tbl[(i + 1)] 3417 table.insert(keys, tbl[i]) 3418 end 3419 tbl.comments = comments 3420 tbl.keys = keys 3421 return dispatch(val) 3422 end 3423 local function close_table(b) 3424 local top = table.remove(stack) 3425 if (top == nil) then 3426 parse_error(("unexpected closing delimiter " .. string.char(b))) 3427 else 3428 end 3429 if (top.closer and (top.closer ~= b)) then 3430 parse_error(("mismatched closing delimiter " .. string.char(b) .. ", expected " .. string.char(top.closer))) 3431 else 3432 end 3433 top.byteend = byteindex 3434 if (b == 41) then 3435 return close_list(top) 3436 elseif (b == 93) then 3437 return close_sequence(top) 3438 else 3439 return close_curly_table(top) 3440 end 3441 end 3442 local function parse_string_loop(chars, b, state) 3443 table.insert(chars, b) 3444 local state0 3445 do 3446 local _185_ = {state, b} 3447 if ((_G.type(_185_) == "table") and ((_185_)[1] == "base") and ((_185_)[2] == 92)) then 3448 state0 = "backslash" 3449 elseif ((_G.type(_185_) == "table") and ((_185_)[1] == "base") and ((_185_)[2] == 34)) then 3450 state0 = "done" 3451 elseif ((_G.type(_185_) == "table") and ((_185_)[1] == "backslash") and ((_185_)[2] == 10)) then 3452 table.remove(chars, (#chars - 1)) 3453 state0 = "base" 3454 elseif true then 3455 local _ = _185_ 3456 state0 = "base" 3457 else 3458 state0 = nil 3459 end 3460 end 3461 if (b and (state0 ~= "done")) then 3462 return parse_string_loop(chars, getb(), state0) 3463 else 3464 return b 3465 end 3466 end 3467 local function escape_char(c) 3468 return ({[7] = "\\a", [8] = "\\b", [9] = "\\t", [10] = "\\n", [11] = "\\v", [12] = "\\f", [13] = "\\r"})[c:byte()] 3469 end 3470 local function parse_string() 3471 table.insert(stack, {closer = 34}) 3472 local chars = {34} 3473 if not parse_string_loop(chars, getb(), "base") then 3474 badend() 3475 else 3476 end 3477 table.remove(stack) 3478 local raw = string.char(unpack(chars)) 3479 local formatted = raw:gsub("[\7-\13]", escape_char) 3480 local _189_ = (rawget(_G, "loadstring") or load)(("return " .. formatted)) 3481 if (nil ~= _189_) then 3482 local load_fn = _189_ 3483 return dispatch(load_fn()) 3484 elseif (_189_ == nil) then 3485 return parse_error(("Invalid string: " .. raw)) 3486 else 3487 return nil 3488 end 3489 end 3490 local function parse_prefix(b) 3491 table.insert(stack, {prefix = prefixes[b], filename = _3ffilename, line = line, bytestart = byteindex}) 3492 local nextb = getb() 3493 if (whitespace_3f(nextb) or (true == delims[nextb])) then 3494 if (b ~= 35) then 3495 parse_error("invalid whitespace after quoting prefix") 3496 else 3497 end 3498 table.remove(stack) 3499 dispatch(utils.sym("#")) 3500 else 3501 end 3502 return ungetb(nextb) 3503 end 3504 local function parse_sym_loop(chars, b) 3505 if (b and sym_char_3f(b)) then 3506 table.insert(chars, b) 3507 return parse_sym_loop(chars, getb()) 3508 else 3509 if b then 3510 ungetb(b) 3511 else 3512 end 3513 return chars 3514 end 3515 end 3516 local function parse_number(rawstr) 3517 local number_with_stripped_underscores = (not rawstr:find("^_") and rawstr:gsub("_", "")) 3518 if rawstr:match("^%d") then 3519 dispatch((tonumber(number_with_stripped_underscores) or parse_error(("could not read number \"" .. rawstr .. "\"")))) 3520 return true 3521 else 3522 local _195_ = tonumber(number_with_stripped_underscores) 3523 if (nil ~= _195_) then 3524 local x = _195_ 3525 dispatch(x) 3526 return true 3527 elseif true then 3528 local _ = _195_ 3529 return false 3530 else 3531 return nil 3532 end 3533 end 3534 end 3535 local function check_malformed_sym(rawstr) 3536 if (rawstr:match("^~") and (rawstr ~= "~=")) then 3537 return parse_error("illegal character: ~") 3538 elseif rawstr:match("%.[0-9]") then 3539 return parse_error(("can't start multisym segment with a digit: " .. rawstr), (((byteindex - #rawstr) + rawstr:find("%.[0-9]")) + 1)) 3540 elseif (rawstr:match("[%.:][%.:]") and (rawstr ~= "..") and (rawstr ~= "$...")) then 3541 return parse_error(("malformed multisym: " .. rawstr), ((byteindex - #rawstr) + 1 + rawstr:find("[%.:][%.:]"))) 3542 elseif ((rawstr ~= ":") and rawstr:match(":$")) then 3543 return parse_error(("malformed multisym: " .. rawstr), ((byteindex - #rawstr) + 1 + rawstr:find(":$"))) 3544 elseif rawstr:match(":.+[%.:]") then 3545 return parse_error(("method must be last component of multisym: " .. rawstr), ((byteindex - #rawstr) + rawstr:find(":.+[%.:]"))) 3546 else 3547 return rawstr 3548 end 3549 end 3550 local function parse_sym(b) 3551 local bytestart = byteindex 3552 local rawstr = string.char(unpack(parse_sym_loop({b}, getb()))) 3553 if (rawstr == "true") then 3554 return dispatch(true) 3555 elseif (rawstr == "false") then 3556 return dispatch(false) 3557 elseif (rawstr == "...") then 3558 return dispatch(utils.varg()) 3559 elseif rawstr:match("^:.+$") then 3560 return dispatch(rawstr:sub(2)) 3561 elseif not parse_number(rawstr) then 3562 return dispatch(utils.sym(check_malformed_sym(rawstr), {byteend = byteindex, bytestart = bytestart, filename = _3ffilename, line = line})) 3563 else 3564 return nil 3565 end 3566 end 3567 local function parse_loop(b) 3568 if not b then 3569 elseif (b == 59) then 3570 parse_comment(getb(), {";"}) 3571 elseif (type(delims[b]) == "number") then 3572 open_table(b) 3573 elseif delims[b] then 3574 close_table(b) 3575 elseif (b == 34) then 3576 parse_string(b) 3577 elseif prefixes[b] then 3578 parse_prefix(b) 3579 elseif (sym_char_3f(b) or (b == string.byte("~"))) then 3580 parse_sym(b) 3581 elseif not utils.hook("illegal-char", b, getb, ungetb, dispatch) then 3582 parse_error(("illegal character: " .. string.char(b))) 3583 else 3584 end 3585 if not b then 3586 return nil 3587 elseif done_3f then 3588 return true, retval 3589 else 3590 return parse_loop(skip_whitespace(getb())) 3591 end 3592 end 3593 return parse_loop(skip_whitespace(getb())) 3594 end 3595 local function _202_() 3596 stack, line, byteindex, lastb = {}, 1, 0, nil 3597 return nil 3598 end 3599 return parse_stream, _202_ 3600 end 3601 return {granulate = granulate, parser = parser, ["string-stream"] = string_stream, ["sym-char?"] = sym_char_3f} 3602end 3603local utils 3604package.preload["fennel.view"] = package.preload["fennel.view"] or function(...) 3605 local type_order = {number = 1, boolean = 2, string = 3, table = 4, ["function"] = 5, userdata = 6, thread = 7} 3606 local lua_pairs = pairs 3607 local lua_ipairs = ipairs 3608 local function pairs(t) 3609 local _1_ = getmetatable(t) 3610 if ((_G.type(_1_) == "table") and (nil ~= (_1_).__pairs)) then 3611 local p = (_1_).__pairs 3612 return p(t) 3613 elseif true then 3614 local _ = _1_ 3615 return lua_pairs(t) 3616 else 3617 return nil 3618 end 3619 end 3620 local function ipairs(t) 3621 local _3_ = getmetatable(t) 3622 if ((_G.type(_3_) == "table") and (nil ~= (_3_).__ipairs)) then 3623 local i = (_3_).__ipairs 3624 return i(t) 3625 elseif true then 3626 local _ = _3_ 3627 return lua_ipairs(t) 3628 else 3629 return nil 3630 end 3631 end 3632 local function length_2a(t) 3633 local _5_ = getmetatable(t) 3634 if ((_G.type(_5_) == "table") and (nil ~= (_5_).__len)) then 3635 local l = (_5_).__len 3636 return l(t) 3637 elseif true then 3638 local _ = _5_ 3639 return #t 3640 else 3641 return nil 3642 end 3643 end 3644 local function sort_keys(_7_, _9_) 3645 local _arg_8_ = _7_ 3646 local a = _arg_8_[1] 3647 local _arg_10_ = _9_ 3648 local b = _arg_10_[1] 3649 local ta = type(a) 3650 local tb = type(b) 3651 if ((ta == tb) and ((ta == "string") or (ta == "number"))) then 3652 return (a < b) 3653 else 3654 local dta = type_order[ta] 3655 local dtb = type_order[tb] 3656 if (dta and dtb) then 3657 return (dta < dtb) 3658 elseif dta then 3659 return true 3660 elseif dtb then 3661 return false 3662 else 3663 return (ta < tb) 3664 end 3665 end 3666 end 3667 local function max_index_gap(kv) 3668 local gap = 0 3669 if (length_2a(kv) > 0) then 3670 local i = 0 3671 for _, _13_ in ipairs(kv) do 3672 local _each_14_ = _13_ 3673 local k = _each_14_[1] 3674 if ((k - i) > gap) then 3675 gap = (k - i) 3676 else 3677 end 3678 i = k 3679 end 3680 else 3681 end 3682 return gap 3683 end 3684 local function fill_gaps(kv) 3685 local missing_indexes = {} 3686 local i = 0 3687 for _, _17_ in ipairs(kv) do 3688 local _each_18_ = _17_ 3689 local j = _each_18_[1] 3690 i = (i + 1) 3691 while (i < j) do 3692 table.insert(missing_indexes, i) 3693 i = (i + 1) 3694 end 3695 end 3696 for _, k in ipairs(missing_indexes) do 3697 table.insert(kv, k, {k}) 3698 end 3699 return nil 3700 end 3701 local function table_kv_pairs(t, options) 3702 local assoc_3f = false 3703 local kv = {} 3704 local insert = table.insert 3705 for k, v in pairs(t) do 3706 if ((type(k) ~= "number") or (k < 1)) then 3707 assoc_3f = true 3708 else 3709 end 3710 insert(kv, {k, v}) 3711 end 3712 table.sort(kv, sort_keys) 3713 if not assoc_3f then 3714 if (max_index_gap(kv) > options["max-sparse-gap"]) then 3715 assoc_3f = true 3716 else 3717 fill_gaps(kv) 3718 end 3719 else 3720 end 3721 if (length_2a(kv) == 0) then 3722 return kv, "empty" 3723 else 3724 local function _22_() 3725 if assoc_3f then 3726 return "table" 3727 else 3728 return "seq" 3729 end 3730 end 3731 return kv, _22_() 3732 end 3733 end 3734 local function count_table_appearances(t, appearances) 3735 if (type(t) == "table") then 3736 if not appearances[t] then 3737 appearances[t] = 1 3738 for k, v in pairs(t) do 3739 count_table_appearances(k, appearances) 3740 count_table_appearances(v, appearances) 3741 end 3742 else 3743 appearances[t] = ((appearances[t] or 0) + 1) 3744 end 3745 else 3746 end 3747 return appearances 3748 end 3749 local function save_table(t, seen) 3750 local seen0 = (seen or {len = 0}) 3751 local id = (seen0.len + 1) 3752 if not (seen0)[t] then 3753 seen0[t] = id 3754 seen0.len = id 3755 else 3756 end 3757 return seen0 3758 end 3759 local function detect_cycle(t, seen, _3fk) 3760 if ("table" == type(t)) then 3761 seen[t] = true 3762 local _27_, _28_ = next(t, _3fk) 3763 if ((nil ~= _27_) and (nil ~= _28_)) then 3764 local k = _27_ 3765 local v = _28_ 3766 return (seen[k] or detect_cycle(k, seen) or seen[v] or detect_cycle(v, seen) or detect_cycle(t, seen, k)) 3767 else 3768 return nil 3769 end 3770 else 3771 return nil 3772 end 3773 end 3774 local function visible_cycle_3f(t, options) 3775 return (options["detect-cycles?"] and detect_cycle(t, {}) and save_table(t, options.seen) and (1 < (options.appearances[t] or 0))) 3776 end 3777 local function table_indent(indent, id) 3778 local opener_length 3779 if id then 3780 opener_length = (length_2a(tostring(id)) + 2) 3781 else 3782 opener_length = 1 3783 end 3784 return (indent + opener_length) 3785 end 3786 local pp = nil 3787 local function concat_table_lines(elements, options, multiline_3f, indent, table_type, prefix) 3788 local indent_str = ("\n" .. string.rep(" ", indent)) 3789 local open 3790 local function _32_() 3791 if ("seq" == table_type) then 3792 return "[" 3793 else 3794 return "{" 3795 end 3796 end 3797 open = ((prefix or "") .. _32_()) 3798 local close 3799 if ("seq" == table_type) then 3800 close = "]" 3801 else 3802 close = "}" 3803 end 3804 local oneline = (open .. table.concat(elements, " ") .. close) 3805 if (not options["one-line?"] and (multiline_3f or ((indent + length_2a(oneline)) > options["line-length"]))) then 3806 return (open .. table.concat(elements, indent_str) .. close) 3807 else 3808 return oneline 3809 end 3810 end 3811 local function utf8_len(x) 3812 local n = 0 3813 for _ in string.gmatch(x, "[%z\1-\127\192-\247]") do 3814 n = (n + 1) 3815 end 3816 return n 3817 end 3818 local function pp_associative(t, kv, options, indent) 3819 local multiline_3f = false 3820 local id = options.seen[t] 3821 if (options.level >= options.depth) then 3822 return "{...}" 3823 elseif (id and options["detect-cycles?"]) then 3824 return ("@" .. id .. "{...}") 3825 else 3826 local visible_cycle_3f0 = visible_cycle_3f(t, options) 3827 local id0 = (visible_cycle_3f0 and options.seen[t]) 3828 local indent0 = table_indent(indent, id0) 3829 local slength 3830 if options["utf8?"] then 3831 slength = utf8_len 3832 else 3833 local function _35_(_241) 3834 return #_241 3835 end 3836 slength = _35_ 3837 end 3838 local prefix 3839 if visible_cycle_3f0 then 3840 prefix = ("@" .. id0) 3841 else 3842 prefix = "" 3843 end 3844 local items 3845 do 3846 local tbl_14_auto = {} 3847 local i_15_auto = #tbl_14_auto 3848 for _, _38_ in pairs(kv) do 3849 local _each_39_ = _38_ 3850 local k = _each_39_[1] 3851 local v = _each_39_[2] 3852 local val_16_auto 3853 do 3854 local k0 = pp(k, options, (indent0 + 1), true) 3855 local v0 = pp(v, options, (indent0 + slength(k0) + 1)) 3856 multiline_3f = (multiline_3f or k0:find("\n") or v0:find("\n")) 3857 val_16_auto = (k0 .. " " .. v0) 3858 end 3859 if (nil ~= val_16_auto) then 3860 i_15_auto = (i_15_auto + 1) 3861 do end (tbl_14_auto)[i_15_auto] = val_16_auto 3862 else 3863 end 3864 end 3865 items = tbl_14_auto 3866 end 3867 return concat_table_lines(items, options, multiline_3f, indent0, "table", prefix) 3868 end 3869 end 3870 local function pp_sequence(t, kv, options, indent) 3871 local multiline_3f = false 3872 local id = options.seen[t] 3873 if (options.level >= options.depth) then 3874 return "[...]" 3875 elseif (id and options["detect-cycles?"]) then 3876 return ("@" .. id .. "[...]") 3877 else 3878 local visible_cycle_3f0 = visible_cycle_3f(t, options) 3879 local id0 = (visible_cycle_3f0 and options.seen[t]) 3880 local indent0 = table_indent(indent, id0) 3881 local prefix 3882 if visible_cycle_3f0 then 3883 prefix = ("@" .. id0) 3884 else 3885 prefix = "" 3886 end 3887 local items 3888 do 3889 local tbl_14_auto = {} 3890 local i_15_auto = #tbl_14_auto 3891 for _, _43_ in pairs(kv) do 3892 local _each_44_ = _43_ 3893 local _0 = _each_44_[1] 3894 local v = _each_44_[2] 3895 local val_16_auto 3896 do 3897 local v0 = pp(v, options, indent0) 3898 multiline_3f = (multiline_3f or v0:find("\n")) 3899 val_16_auto = v0 3900 end 3901 if (nil ~= val_16_auto) then 3902 i_15_auto = (i_15_auto + 1) 3903 do end (tbl_14_auto)[i_15_auto] = val_16_auto 3904 else 3905 end 3906 end 3907 items = tbl_14_auto 3908 end 3909 return concat_table_lines(items, options, multiline_3f, indent0, "seq", prefix) 3910 end 3911 end 3912 local function concat_lines(lines, options, indent, force_multi_line_3f) 3913 if (length_2a(lines) == 0) then 3914 if options["empty-as-sequence?"] then 3915 return "[]" 3916 else 3917 return "{}" 3918 end 3919 else 3920 local oneline 3921 local _48_ 3922 do 3923 local tbl_14_auto = {} 3924 local i_15_auto = #tbl_14_auto 3925 for _, line in ipairs(lines) do 3926 local val_16_auto = line:gsub("^%s+", "") 3927 if (nil ~= val_16_auto) then 3928 i_15_auto = (i_15_auto + 1) 3929 do end (tbl_14_auto)[i_15_auto] = val_16_auto 3930 else 3931 end 3932 end 3933 _48_ = tbl_14_auto 3934 end 3935 oneline = table.concat(_48_, " ") 3936 if (not options["one-line?"] and (force_multi_line_3f or oneline:find("\n") or ((indent + length_2a(oneline)) > options["line-length"]))) then 3937 return table.concat(lines, ("\n" .. string.rep(" ", indent))) 3938 else 3939 return oneline 3940 end 3941 end 3942 end 3943 local function pp_metamethod(t, metamethod, options, indent) 3944 if (options.level >= options.depth) then 3945 if options["empty-as-sequence?"] then 3946 return "[...]" 3947 else 3948 return "{...}" 3949 end 3950 else 3951 local _ 3952 local function _53_(_241) 3953 return visible_cycle_3f(_241, options) 3954 end 3955 options["visible-cycle?"] = _53_ 3956 _ = nil 3957 local lines, force_multi_line_3f = metamethod(t, pp, options, indent) 3958 options["visible-cycle?"] = nil 3959 local _54_ = type(lines) 3960 if (_54_ == "string") then 3961 return lines 3962 elseif (_54_ == "table") then 3963 return concat_lines(lines, options, indent, force_multi_line_3f) 3964 elseif true then 3965 local _0 = _54_ 3966 return error("__fennelview metamethod must return a table of lines") 3967 else 3968 return nil 3969 end 3970 end 3971 end 3972 local function pp_table(x, options, indent) 3973 options.level = (options.level + 1) 3974 local x0 3975 do 3976 local _57_ 3977 if options["metamethod?"] then 3978 local _58_ = x 3979 if (nil ~= _58_) then 3980 local _59_ = getmetatable(_58_) 3981 if (nil ~= _59_) then 3982 _57_ = (_59_).__fennelview 3983 else 3984 _57_ = _59_ 3985 end 3986 else 3987 _57_ = _58_ 3988 end 3989 else 3990 _57_ = nil 3991 end 3992 if (nil ~= _57_) then 3993 local metamethod = _57_ 3994 x0 = pp_metamethod(x, metamethod, options, indent) 3995 elseif true then 3996 local _ = _57_ 3997 local _63_, _64_ = table_kv_pairs(x, options) 3998 if (true and (_64_ == "empty")) then 3999 local _0 = _63_ 4000 if options["empty-as-sequence?"] then 4001 x0 = "[]" 4002 else 4003 x0 = "{}" 4004 end 4005 elseif ((nil ~= _63_) and (_64_ == "table")) then 4006 local kv = _63_ 4007 x0 = pp_associative(x, kv, options, indent) 4008 elseif ((nil ~= _63_) and (_64_ == "seq")) then 4009 local kv = _63_ 4010 x0 = pp_sequence(x, kv, options, indent) 4011 else 4012 x0 = nil 4013 end 4014 else 4015 x0 = nil 4016 end 4017 end 4018 options.level = (options.level - 1) 4019 return x0 4020 end 4021 local function number__3estring(n) 4022 local _68_ = string.gsub(tostring(n), ",", ".") 4023 return _68_ 4024 end 4025 local function colon_string_3f(s) 4026 return s:find("^[-%w?^_!$%&*+./@|<=>]+$") 4027 end 4028 local utf8_inits = {{["min-byte"] = 0, ["max-byte"] = 127, ["min-code"] = 0, ["max-code"] = 127, len = 1}, {["min-byte"] = 192, ["max-byte"] = 223, ["min-code"] = 128, ["max-code"] = 2047, len = 2}, {["min-byte"] = 224, ["max-byte"] = 239, ["min-code"] = 2048, ["max-code"] = 65535, len = 3}, {["min-byte"] = 240, ["max-byte"] = 247, ["min-code"] = 65536, ["max-code"] = 1114111, len = 4}} 4029 local function utf8_escape(str) 4030 local function validate_utf8(str0, index) 4031 local inits = utf8_inits 4032 local byte = string.byte(str0, index) 4033 local init 4034 do 4035 local ret = nil 4036 for _, init0 in ipairs(inits) do 4037 if ret then break end 4038 ret = (byte and (function(_69_,_70_,_71_) return (_69_ >= _70_) and (_70_ >= _71_) end)(init0["max-byte"],byte,init0["min-byte"]) and init0) 4039 end 4040 init = ret 4041 end 4042 local code 4043 local function _72_() 4044 local code0 4045 if init then 4046 code0 = (byte - init["min-byte"]) 4047 else 4048 code0 = nil 4049 end 4050 for i = (index + 1), (index + init.len + -1) do 4051 local byte0 = string.byte(str0, i) 4052 code0 = (byte0 and code0 and (function(_74_,_75_,_76_) return (_74_ >= _75_) and (_75_ >= _76_) end)(191,byte0,128) and ((code0 * 64) + (byte0 - 128))) 4053 end 4054 return code0 4055 end 4056 code = (init and _72_()) 4057 if (code and (function(_77_,_78_,_79_) return (_77_ >= _78_) and (_78_ >= _79_) end)(init["max-code"],code,init["min-code"]) and not (function(_80_,_81_,_82_) return (_80_ >= _81_) and (_81_ >= _82_) end)(57343,code,55296)) then 4058 return init.len 4059 else 4060 return nil 4061 end 4062 end 4063 local index = 1 4064 local output = {} 4065 while (index <= #str) do 4066 local nexti = (string.find(str, "[\128-\255]", index) or (#str + 1)) 4067 local len = validate_utf8(str, nexti) 4068 table.insert(output, string.sub(str, index, (nexti + (len or 0) + -1))) 4069 if (not len and (nexti <= #str)) then 4070 table.insert(output, string.format("\\%03d", string.byte(str, nexti))) 4071 else 4072 end 4073 if len then 4074 index = (nexti + len) 4075 else 4076 index = (nexti + 1) 4077 end 4078 end 4079 return table.concat(output) 4080 end 4081 local function pp_string(str, options, indent) 4082 local escs 4083 local _86_ 4084 if (options["escape-newlines?"] and (length_2a(str) < (options["line-length"] - indent))) then 4085 _86_ = "\\n" 4086 else 4087 _86_ = "\n" 4088 end 4089 local function _88_(_241, _242) 4090 return ("\\%03d"):format(_242:byte()) 4091 end 4092 escs = setmetatable({["\7"] = "\\a", ["\8"] = "\\b", ["\12"] = "\\f", ["\11"] = "\\v", ["\13"] = "\\r", ["\9"] = "\\t", ["\\"] = "\\\\", ["\""] = "\\\"", ["\n"] = _86_}, {__index = _88_}) 4093 local str0 = ("\"" .. str:gsub("[%c\\\"]", escs) .. "\"") 4094 if options["utf8?"] then 4095 return utf8_escape(str0) 4096 else 4097 return str0 4098 end 4099 end 4100 local function make_options(t, options) 4101 local defaults = {["line-length"] = 80, ["one-line?"] = false, depth = 128, ["detect-cycles?"] = true, ["empty-as-sequence?"] = false, ["metamethod?"] = true, ["prefer-colon?"] = false, ["escape-newlines?"] = false, ["utf8?"] = true, ["max-sparse-gap"] = 10} 4102 local overrides = {level = 0, appearances = count_table_appearances(t, {}), seen = {len = 0}} 4103 for k, v in pairs((options or {})) do 4104 defaults[k] = v 4105 end 4106 for k, v in pairs(overrides) do 4107 defaults[k] = v 4108 end 4109 return defaults 4110 end 4111 local function _90_(x, options, indent, colon_3f) 4112 local indent0 = (indent or 0) 4113 local options0 = (options or make_options(x)) 4114 local x0 4115 if options0.preprocess then 4116 x0 = options0.preprocess(x, options0) 4117 else 4118 x0 = x 4119 end 4120 local tv = type(x0) 4121 local function _93_() 4122 local _92_ = getmetatable(x0) 4123 if (nil ~= _92_) then 4124 return (_92_).__fennelview 4125 else 4126 return _92_ 4127 end 4128 end 4129 if ((tv == "table") or ((tv == "userdata") and _93_())) then 4130 return pp_table(x0, options0, indent0) 4131 elseif (tv == "number") then 4132 return number__3estring(x0) 4133 else 4134 local function _95_() 4135 if (colon_3f ~= nil) then 4136 return colon_3f 4137 elseif ("function" == type(options0["prefer-colon?"])) then 4138 return options0["prefer-colon?"](x0) 4139 else 4140 return options0["prefer-colon?"] 4141 end 4142 end 4143 if ((tv == "string") and colon_string_3f(x0) and _95_()) then 4144 return (":" .. x0) 4145 elseif (tv == "string") then 4146 return pp_string(x0, options0, indent0) 4147 elseif ((tv == "boolean") or (tv == "nil")) then 4148 return tostring(x0) 4149 else 4150 return ("#<" .. tostring(x0) .. ">") 4151 end 4152 end 4153 end 4154 pp = _90_ 4155 local function view(x, _3foptions) 4156 return pp(x, make_options(x, _3foptions), 0) 4157 end 4158 return view 4159end 4160package.preload["fennel.utils"] = package.preload["fennel.utils"] or function(...) 4161 local view = require("fennel.view") 4162 local version = "1.0.0-dev" 4163 local function warn(message) 4164 if (_G.io and _G.io.stderr) then 4165 return (_G.io.stderr):write(("--WARNING: %s\n"):format(tostring(message))) 4166 else 4167 return nil 4168 end 4169 end 4170 local function stablepairs(t) 4171 local keys = {} 4172 local used_keys = {} 4173 local succ = {} 4174 if (getmetatable(t) and getmetatable(t).keys) then 4175 for _, k in ipairs(getmetatable(t).keys) do 4176 if used_keys[k] then 4177 for i = #keys, 1, -1 do 4178 if (keys[i] == k) then 4179 table.remove(keys, i) 4180 else 4181 end 4182 end 4183 else 4184 end 4185 used_keys[k] = true 4186 table.insert(keys, k) 4187 end 4188 else 4189 for k in pairs(t) do 4190 table.insert(keys, k) 4191 end 4192 local function _100_(_241, _242) 4193 return (tostring(_241) < tostring(_242)) 4194 end 4195 table.sort(keys, _100_) 4196 end 4197 for i, k in ipairs(keys) do 4198 succ[k] = keys[(i + 1)] 4199 end 4200 local function stablenext(tbl, idx) 4201 local key 4202 if (idx == nil) then 4203 key = keys[1] 4204 else 4205 key = succ[idx] 4206 end 4207 local value 4208 if (key == nil) then 4209 value = nil 4210 else 4211 value = tbl[key] 4212 end 4213 return key, value 4214 end 4215 return stablenext, t, nil 4216 end 4217 local function map(t, f, _3fout) 4218 local out = (_3fout or {}) 4219 local f0 4220 if (type(f) == "function") then 4221 f0 = f 4222 else 4223 local function _104_(_241) 4224 return (_241)[f] 4225 end 4226 f0 = _104_ 4227 end 4228 for _, x in ipairs(t) do 4229 local _106_ = f0(x) 4230 if (nil ~= _106_) then 4231 local v = _106_ 4232 table.insert(out, v) 4233 else 4234 end 4235 end 4236 return out 4237 end 4238 local function kvmap(t, f, _3fout) 4239 local out = (_3fout or {}) 4240 local f0 4241 if (type(f) == "function") then 4242 f0 = f 4243 else 4244 local function _108_(_241) 4245 return (_241)[f] 4246 end 4247 f0 = _108_ 4248 end 4249 for k, x in stablepairs(t) do 4250 local _110_, _111_ = f0(k, x) 4251 if ((nil ~= _110_) and (nil ~= _111_)) then 4252 local key = _110_ 4253 local value = _111_ 4254 out[key] = value 4255 elseif (nil ~= _110_) then 4256 local value = _110_ 4257 table.insert(out, value) 4258 else 4259 end 4260 end 4261 return out 4262 end 4263 local function copy(from, _3fto) 4264 local to = (_3fto or {}) 4265 for k, v in pairs((from or {})) do 4266 to[k] = v 4267 end 4268 return to 4269 end 4270 local function member_3f(x, tbl, _3fn) 4271 local _113_ = tbl[(_3fn or 1)] 4272 if (_113_ == x) then 4273 return true 4274 elseif (_113_ == nil) then 4275 return nil 4276 elseif true then 4277 local _ = _113_ 4278 return member_3f(x, tbl, ((_3fn or 1) + 1)) 4279 else 4280 return nil 4281 end 4282 end 4283 local function allpairs(tbl) 4284 assert((type(tbl) == "table"), "allpairs expects a table") 4285 local t = tbl 4286 local seen = {} 4287 local function allpairs_next(_, state) 4288 local next_state, value = next(t, state) 4289 if seen[next_state] then 4290 return allpairs_next(nil, next_state) 4291 elseif next_state then 4292 seen[next_state] = true 4293 return next_state, value 4294 else 4295 local _115_ = getmetatable(t) 4296 if ((_G.type(_115_) == "table") and true) then 4297 local __index = (_115_).__index 4298 if ("table" == type(__index)) then 4299 t = __index 4300 return allpairs_next(t) 4301 else 4302 return nil 4303 end 4304 else 4305 return nil 4306 end 4307 end 4308 end 4309 return allpairs_next 4310 end 4311 local function deref(self) 4312 return self[1] 4313 end 4314 local nil_sym = nil 4315 local function list__3estring(self, _3ftostring2) 4316 local safe, max = {}, 0 4317 for k in pairs(self) do 4318 if ((type(k) == "number") and (k > max)) then 4319 max = k 4320 else 4321 end 4322 end 4323 for i = 1, max do 4324 safe[i] = (((self[i] == nil) and nil_sym) or self[i]) 4325 end 4326 return ("(" .. table.concat(map(safe, (_3ftostring2 or view)), " ", 1, max) .. ")") 4327 end 4328 local function comment_view(c) 4329 return c, true 4330 end 4331 local function sym_3d(a, b) 4332 return ((deref(a) == deref(b)) and (getmetatable(a) == getmetatable(b))) 4333 end 4334 local function sym_3c(a, b) 4335 return (a[1] < tostring(b)) 4336 end 4337 local symbol_mt = {__fennelview = deref, __tostring = deref, __eq = sym_3d, __lt = sym_3c, "SYMBOL"} 4338 local expr_mt 4339 local function _120_(x) 4340 return tostring(deref(x)) 4341 end 4342 expr_mt = {__tostring = _120_, "EXPR"} 4343 local list_mt = {__fennelview = list__3estring, __tostring = list__3estring, "LIST"} 4344 local comment_mt = {__fennelview = comment_view, __tostring = deref, __eq = sym_3d, __lt = sym_3c, "COMMENT"} 4345 local sequence_marker = {"SEQUENCE"} 4346 local vararg = setmetatable({"..."}, {__fennelview = deref, __tostring = deref, "VARARG"}) 4347 local getenv 4348 local function _121_() 4349 return nil 4350 end 4351 getenv = ((os and os.getenv) or _121_) 4352 local function debug_on_3f(flag) 4353 local level = (getenv("FENNEL_DEBUG") or "") 4354 return ((level == "all") or level:find(flag)) 4355 end 4356 local function list(...) 4357 return setmetatable({...}, list_mt) 4358 end 4359 local function sym(str, _3fsource, _3fscope) 4360 local s = {["?scope"] = _3fscope, str} 4361 for k, v in pairs((_3fsource or {})) do 4362 if (type(k) == "string") then 4363 s[k] = v 4364 else 4365 end 4366 end 4367 return setmetatable(s, symbol_mt) 4368 end 4369 nil_sym = sym("nil") 4370 local function sequence(...) 4371 return setmetatable({...}, {sequence = sequence_marker}) 4372 end 4373 local function expr(strcode, etype) 4374 return setmetatable({type = etype, strcode}, expr_mt) 4375 end 4376 local function comment_2a(contents, _3fsource) 4377 local _let_123_ = (_3fsource or {}) 4378 local filename = _let_123_["filename"] 4379 local line = _let_123_["line"] 4380 return setmetatable({filename = filename, line = line, contents}, comment_mt) 4381 end 4382 local function varg() 4383 return vararg 4384 end 4385 local function expr_3f(x) 4386 return ((type(x) == "table") and (getmetatable(x) == expr_mt) and x) 4387 end 4388 local function varg_3f(x) 4389 return ((x == vararg) and x) 4390 end 4391 local function list_3f(x) 4392 return ((type(x) == "table") and (getmetatable(x) == list_mt) and x) 4393 end 4394 local function sym_3f(x) 4395 return ((type(x) == "table") and (getmetatable(x) == symbol_mt) and x) 4396 end 4397 local function sequence_3f(x) 4398 local mt = ((type(x) == "table") and getmetatable(x)) 4399 return (mt and (mt.sequence == sequence_marker) and x) 4400 end 4401 local function comment_3f(x) 4402 return ((type(x) == "table") and (getmetatable(x) == comment_mt) and x) 4403 end 4404 local function table_3f(x) 4405 return ((type(x) == "table") and (x ~= vararg) and (getmetatable(x) ~= list_mt) and (getmetatable(x) ~= symbol_mt) and not comment_3f(x) and x) 4406 end 4407 local function multi_sym_3f(str) 4408 if sym_3f(str) then 4409 return multi_sym_3f(tostring(str)) 4410 elseif (type(str) ~= "string") then 4411 return false 4412 else 4413 local parts = {} 4414 for part in str:gmatch("[^%.%:]+[%.%:]?") do 4415 local last_char = part:sub(( - 1)) 4416 if (last_char == ":") then 4417 parts["multi-sym-method-call"] = true 4418 else 4419 end 4420 if ((last_char == ":") or (last_char == ".")) then 4421 parts[(#parts + 1)] = part:sub(1, ( - 2)) 4422 else 4423 parts[(#parts + 1)] = part 4424 end 4425 end 4426 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) 4427 end 4428 end 4429 local function quoted_3f(symbol) 4430 return symbol.quoted 4431 end 4432 local function ast_source(ast) 4433 if table_3f(ast) then 4434 return (getmetatable(ast) or {}) 4435 elseif ("table" == type(ast)) then 4436 return ast 4437 else 4438 return {} 4439 end 4440 end 4441 local function walk_tree(root, f, _3fcustom_iterator) 4442 local function walk(iterfn, parent, idx, node) 4443 if f(idx, node, parent) then 4444 for k, v in iterfn(node) do 4445 walk(iterfn, node, k, v) 4446 end 4447 return nil 4448 else 4449 return nil 4450 end 4451 end 4452 walk((_3fcustom_iterator or pairs), nil, nil, root) 4453 return root 4454 end 4455 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"} 4456 for i, v in ipairs(lua_keywords) do 4457 lua_keywords[v] = i 4458 end 4459 local function valid_lua_identifier_3f(str) 4460 return (str:match("^[%a_][%w_]*$") and not lua_keywords[str]) 4461 end 4462 local propagated_options = {"allowedGlobals", "indent", "correlate", "useMetadata", "env", "compiler-env", "compilerEnv"} 4463 local function propagate_options(options, subopts) 4464 for _, name in ipairs(propagated_options) do 4465 subopts[name] = options[name] 4466 end 4467 return subopts 4468 end 4469 local root 4470 local function _129_() 4471 end 4472 root = {chunk = nil, scope = nil, options = nil, reset = _129_} 4473 root["set-reset"] = function(_130_) 4474 local _arg_131_ = _130_ 4475 local chunk = _arg_131_["chunk"] 4476 local scope = _arg_131_["scope"] 4477 local options = _arg_131_["options"] 4478 local reset = _arg_131_["reset"] 4479 root.reset = function() 4480 root.chunk, root.scope, root.options, root.reset = chunk, scope, options, reset 4481 return nil 4482 end 4483 return root.reset 4484 end 4485 local warned = {} 4486 local function check_plugin_version(_132_) 4487 local _arg_133_ = _132_ 4488 local name = _arg_133_["name"] 4489 local versions = _arg_133_["versions"] 4490 local plugin = _arg_133_ 4491 if (not member_3f(version:gsub("-dev", ""), (versions or {})) and not warned[plugin]) then 4492 warned[plugin] = true 4493 return warn(string.format("plugin %s does not support Fennel version %s", (name or "unknown"), version)) 4494 else 4495 return nil 4496 end 4497 end 4498 local function hook(event, ...) 4499 local result = nil 4500 if (root.options and root.options.plugins) then 4501 for _, plugin in ipairs(root.options.plugins) do 4502 if result then break end 4503 check_plugin_version(plugin) 4504 local _135_ = plugin[event] 4505 if (nil ~= _135_) then 4506 local f = _135_ 4507 result = f(...) 4508 else 4509 end 4510 end 4511 else 4512 end 4513 return result 4514 end 4515 return {warn = warn, allpairs = allpairs, stablepairs = stablepairs, copy = copy, kvmap = kvmap, map = map, ["walk-tree"] = walk_tree, ["member?"] = member_3f, list = list, sequence = sequence, sym = sym, varg = varg, expr = expr, comment = comment_2a, ["comment?"] = comment_3f, ["expr?"] = expr_3f, ["list?"] = list_3f, ["multi-sym?"] = multi_sym_3f, ["sequence?"] = sequence_3f, ["sym?"] = sym_3f, ["table?"] = table_3f, ["varg?"] = varg_3f, ["quoted?"] = quoted_3f, ["valid-lua-identifier?"] = valid_lua_identifier_3f, ["lua-keywords"] = lua_keywords, hook = hook, ["propagate-options"] = propagate_options, root = root, ["debug-on?"] = debug_on_3f, ["ast-source"] = ast_source, version = version, path = table.concat({"./?.fnl", "./?/init.fnl", getenv("FENNEL_PATH")}, ";"), ["macro-path"] = table.concat({"./?.fnl", "./?/init-macros.fnl", "./?/init.fnl", getenv("FENNEL_MACRO_PATH")}, ";")} 4516end 4517utils = require("fennel.utils") 4518local parser = require("fennel.parser") 4519local compiler = require("fennel.compiler") 4520local specials = require("fennel.specials") 4521local repl = require("fennel.repl") 4522local view = require("fennel.view") 4523local function eval_env(env, opts) 4524 if (env == "_COMPILER") then 4525 local env0 = specials["make-compiler-env"](nil, compiler.scopes.compiler, {}, opts) 4526 if (opts.allowedGlobals == nil) then 4527 opts.allowedGlobals = specials["current-global-names"](env0) 4528 else 4529 end 4530 return specials["wrap-env"](env0) 4531 else 4532 return (env and specials["wrap-env"](env)) 4533 end 4534end 4535local function eval_opts(options, str) 4536 local opts = utils.copy(options) 4537 if (opts.allowedGlobals == nil) then 4538 opts.allowedGlobals = specials["current-global-names"](opts.env) 4539 else 4540 end 4541 if (not opts.filename and not opts.source) then 4542 opts.source = str 4543 else 4544 end 4545 if (opts.env == "_COMPILER") then 4546 opts.scope = compiler["make-scope"](compiler.scopes.compiler) 4547 else 4548 end 4549 return opts 4550end 4551local function eval(str, options, ...) 4552 local opts = eval_opts(options, str) 4553 local env = eval_env(opts.env, opts) 4554 local lua_source = compiler["compile-string"](str, opts) 4555 local loader 4556 local function _618_(...) 4557 if opts.filename then 4558 return ("@" .. opts.filename) 4559 else 4560 return str 4561 end 4562 end 4563 loader = specials["load-code"](lua_source, env, _618_(...)) 4564 opts.filename = nil 4565 return loader(...) 4566end 4567local function dofile_2a(filename, options, ...) 4568 local opts = utils.copy(options) 4569 local f = assert(io.open(filename, "rb")) 4570 local source = assert(f:read("*all"), ("Could not read " .. filename)) 4571 f:close() 4572 opts.filename = filename 4573 return eval(source, opts, ...) 4574end 4575local function syntax() 4576 local body_3f = {"when", "with-open", "collect", "icollect", "lambda", "\206\187", "macro", "match", "accumulate"} 4577 local binding_3f = {"collect", "icollect", "each", "for", "let", "with-open", "accumulate"} 4578 local define_3f = {"fn", "lambda", "\206\187", "var", "local", "macro", "macros", "global"} 4579 local out = {} 4580 for k, v in pairs(compiler.scopes.global.specials) do 4581 local metadata = (compiler.metadata[v] or {}) 4582 do end (out)[k] = {["special?"] = true, ["body-form?"] = metadata["fnl/body-form?"], ["binding-form?"] = utils["member?"](k, binding_3f), ["define?"] = utils["member?"](k, define_3f)} 4583 end 4584 for k, v in pairs(compiler.scopes.global.macros) do 4585 out[k] = {["macro?"] = true, ["body-form?"] = utils["member?"](k, body_3f), ["binding-form?"] = utils["member?"](k, binding_3f), ["define?"] = utils["member?"](k, define_3f)} 4586 end 4587 for k, v in pairs(_G) do 4588 local _619_ = type(v) 4589 if (_619_ == "function") then 4590 out[k] = {["global?"] = true, ["function?"] = true} 4591 elseif (_619_ == "table") then 4592 for k2, v2 in pairs(v) do 4593 if (("function" == type(v2)) and (k ~= "_G")) then 4594 out[(k .. "." .. k2)] = {["function?"] = true, ["global?"] = true} 4595 else 4596 end 4597 end 4598 out[k] = {["global?"] = true} 4599 else 4600 end 4601 end 4602 return out 4603end 4604local mod = {list = utils.list, ["list?"] = utils["list?"], sym = utils.sym, ["sym?"] = utils["sym?"], sequence = utils.sequence, ["sequence?"] = utils["sequence?"], comment = utils.comment, ["comment?"] = utils["comment?"], varg = utils.varg, path = utils.path, ["macro-path"] = utils["macro-path"], ["sym-char?"] = parser["sym-char?"], parser = parser.parser, granulate = parser.granulate, ["string-stream"] = parser["string-stream"], compile = compiler.compile, ["compile-string"] = compiler["compile-string"], ["compile-stream"] = compiler["compile-stream"], compile1 = compiler.compile1, traceback = compiler.traceback, mangle = compiler["global-mangling"], unmangle = compiler["global-unmangling"], metadata = compiler.metadata, scope = compiler["make-scope"], gensym = compiler.gensym, ["load-code"] = specials["load-code"], ["macro-loaded"] = specials["macro-loaded"], ["macro-searchers"] = specials["macro-searchers"], ["search-module"] = specials["search-module"], ["make-searcher"] = specials["make-searcher"], makeSearcher = specials["make-searcher"], searcher = specials["make-searcher"](), doc = specials.doc, view = view, eval = eval, dofile = dofile_2a, version = utils.version, repl = repl, syntax = syntax, loadCode = specials["load-code"], make_searcher = specials["make-searcher"], searchModule = specials["search-module"], macroLoaded = specials["macro-loaded"], compileStream = compiler["compile-stream"], compileString = compiler["compile-string"], stringStream = parser["string-stream"]} 4605utils["fennel-module"] = mod 4606do 4607 local builtin_macros = [===[;; This module contains all the built-in Fennel macros. Unlike all the other 4608 ;; modules that are loaded by the old bootstrap compiler, this runs in the 4609 ;; compiler scope of the version of the compiler being defined. 4610 4611 ;; The code for these macros is somewhat idiosyncratic because it cannot use any 4612 ;; macros which have not yet been defined. 4613 4614 ;; TODO: some of these macros modify their arguments; we should stop doing that, 4615 ;; but in a way that preserves file/line metadata. 4616 4617 (fn ->* [val ...] 4618 "Thread-first macro. 4619 Take the first value and splice it into the second form as its first argument. 4620 The value of the second form is spliced into the first arg of the third, etc." 4621 (var x val) 4622 (each [_ e (ipairs [...])] 4623 (let [elt (if (list? e) e (list e))] 4624 (table.insert elt 2 x) 4625 (set x elt))) 4626 x) 4627 4628 (fn ->>* [val ...] 4629 "Thread-last macro. 4630 Same as ->, except splices the value into the last position of each form 4631 rather than the first." 4632 (var x val) 4633 (each [_ e (ipairs [...])] 4634 (let [elt (if (list? e) e (list e))] 4635 (table.insert elt x) 4636 (set x elt))) 4637 x) 4638 4639 (fn -?>* [val ...] 4640 "Nil-safe thread-first macro. 4641 Same as -> except will short-circuit with nil when it encounters a nil value." 4642 (if (= 0 (select "#" ...)) 4643 val 4644 (let [els [...] 4645 e (table.remove els 1) 4646 el (if (list? e) e (list e)) 4647 tmp (gensym)] 4648 (table.insert el 2 tmp) 4649 `(let [,tmp ,val] 4650 (if (not= nil ,tmp) 4651 (-?> ,el ,(unpack els)) 4652 ,tmp))))) 4653 4654 (fn -?>>* [val ...] 4655 "Nil-safe thread-last macro. 4656 Same as ->> except will short-circuit with nil when it encounters a nil value." 4657 (if (= 0 (select "#" ...)) 4658 val 4659 (let [els [...] 4660 e (table.remove els 1) 4661 el (if (list? e) e (list e)) 4662 tmp (gensym)] 4663 (table.insert el tmp) 4664 `(let [,tmp ,val] 4665 (if (not= ,tmp nil) 4666 (-?>> ,el ,(unpack els)) 4667 ,tmp))))) 4668 4669 (fn ?dot [tbl ...] 4670 "Nil-safe table look up. 4671 Same as . (dot), except will short-circuit with nil when it encounters 4672 a nil value in any of subsequent keys." 4673 (let [head (gensym :t) 4674 lookups `(do (var ,head ,tbl) ,head)] 4675 (each [_ k (ipairs [...])] 4676 ;; Kinda gnarly to reassign in place like this, but it emits the best lua. 4677 ;; With this impl, it emits a flat, concise, and readable set of if blocks. 4678 (table.insert lookups (# lookups) `(if (not= nil ,head) 4679 (set ,head (. ,head ,k))))) 4680 lookups)) 4681 4682 (fn doto* [val ...] 4683 "Evaluates val and splices it into the first argument of subsequent forms." 4684 (let [name (gensym) 4685 form `(let [,name ,val])] 4686 (each [_ elt (ipairs [...])] 4687 (let [elt (if (list? elt) elt (list elt))] 4688 (table.insert elt 2 name) 4689 (table.insert form elt))) 4690 (table.insert form name) 4691 form)) 4692 4693 (fn when* [condition body1 ...] 4694 "Evaluate body for side-effects only when condition is truthy." 4695 (assert body1 "expected body") 4696 `(if ,condition 4697 (do 4698 ,body1 4699 ,...))) 4700 4701 (fn with-open* [closable-bindings ...] 4702 "Like `let`, but invokes (v:close) on each binding after evaluating the body. 4703 The body is evaluated inside `xpcall` so that bound values will be closed upon 4704 encountering an error before propagating it." 4705 (let [bodyfn `(fn [] 4706 ,...) 4707 closer `(fn close-handlers# [ok# ...] 4708 (if ok# ... (error ... 0))) 4709 traceback `(. (or package.loaded.fennel debug) :traceback)] 4710 (for [i 1 (length closable-bindings) 2] 4711 (assert (sym? (. closable-bindings i)) 4712 "with-open only allows symbols in bindings") 4713 (table.insert closer 4 `(: ,(. closable-bindings i) :close))) 4714 `(let ,closable-bindings 4715 ,closer 4716 (close-handlers# (_G.xpcall ,bodyfn ,traceback))))) 4717 4718 (fn into-val [iter-tbl] 4719 (var into nil) 4720 (for [i (length iter-tbl) 2 -1] 4721 (if (= :into (. iter-tbl i)) 4722 (do (assert (not into) "expected only one :into clause") 4723 (set into (table.remove iter-tbl (+ i 1))) 4724 (table.remove iter-tbl i)))) 4725 (assert (or (not into) 4726 (sym? into) 4727 (table? into) 4728 (list? into)) 4729 "expected table, function call, or symbol in :into clause") 4730 (or into [])) 4731 4732 (fn collect* [iter-tbl key-value-expr ...] 4733 "Returns a table made by running an iterator and evaluating an expression 4734 that returns key-value pairs to be inserted sequentially into the table. 4735 This can be thought of as a \"table comprehension\". The provided key-value 4736 expression must return either 2 values, or nil. 4737 4738 For example, 4739 (collect [k v (pairs {:apple \"red\" :orange \"orange\"})] 4740 (values v k)) 4741 returns 4742 {:red \"apple\" :orange \"orange\"} 4743 4744 Supports an :into clause after the iterator to put results in an existing table. 4745 Supports early termination with an :until clause." 4746 (assert (and (sequence? iter-tbl) (>= (length iter-tbl) 2)) 4747 "expected iterator binding table") 4748 (assert (not= nil key-value-expr) "expected key-value expression") 4749 (assert (= nil ...) 4750 "expected exactly one body expression. Wrap multiple expressions with do") 4751 `(let [tbl# ,(into-val iter-tbl)] 4752 (each ,iter-tbl 4753 (match ,key-value-expr 4754 (k# v#) (tset tbl# k# v#))) 4755 tbl#)) 4756 4757 (fn icollect* [iter-tbl value-expr ...] 4758 "Returns a sequential table made by running an iterator and evaluating an 4759 expression that returns values to be inserted sequentially into the table. 4760 This can be thought of as a \"list comprehension\". 4761 4762 For example, 4763 (icollect [_ v (ipairs [1 2 3 4 5])] (when (> v 2) (* v v))) 4764 returns 4765 [9 16 25] 4766 4767 Supports an :into clause after the iterator to put results in an existing table. 4768 Supports early termination with an :until clause." 4769 (assert (and (sequence? iter-tbl) (>= (length iter-tbl) 2)) 4770 "expected iterator binding table") 4771 (assert (not= nil value-expr) "expected table value expression") 4772 (assert (= nil ...) 4773 "expected exactly one body expression. Wrap multiple expressions with do") 4774 `(let [tbl# ,(into-val iter-tbl)] 4775 ;; believe it or not, using a var here has a pretty good performance boost: 4776 ;; https://p.hagelb.org/icollect-performance.html 4777 (var i# (length tbl#)) 4778 (each ,iter-tbl 4779 (let [val# ,value-expr] 4780 (when (not= nil val#) 4781 (set i# (+ i# 1)) 4782 (tset tbl# i# val#)))) 4783 tbl#)) 4784 4785 (fn accumulate* [iter-tbl accum-expr ...] 4786 "Accumulation macro. 4787 It takes a binding table and an expression as its arguments. 4788 In the binding table, the first symbol is bound to the second value, being an 4789 initial accumulator variable. The rest are an iterator binding table in the 4790 format `each` takes. 4791 It runs through the iterator in each step of which the given expression is 4792 evaluated, and its returned value updates the accumulator variable. 4793 It eventually returns the final value of the accumulator variable. 4794 4795 For example, 4796 (accumulate [total 0 4797 _ n (pairs {:apple 2 :orange 3})] 4798 (+ total n)) 4799 returns 4800 5" 4801 (assert (and (sequence? iter-tbl) (>= (length iter-tbl) 4)) 4802 "expected initial value and iterator binding table") 4803 (assert (not= nil accum-expr) "expected accumulating expression") 4804 (assert (= nil ...) 4805 "expected exactly one body expression. Wrap multiple expressions with do") 4806 (let [accum-var (table.remove iter-tbl 1) 4807 accum-init (table.remove iter-tbl 1)] 4808 `(do (var ,accum-var ,accum-init) 4809 (each ,iter-tbl 4810 (set ,accum-var ,accum-expr)) 4811 ,accum-var))) 4812 4813 (fn partial* [f ...] 4814 "Returns a function with all arguments partially applied to f." 4815 (assert f "expected a function to partially apply") 4816 (let [bindings [] 4817 args []] 4818 (each [_ arg (ipairs [...])] 4819 (if (or (= :number (type arg)) 4820 (= :string (type arg)) 4821 (= :boolean (type arg)) 4822 (= `nil arg)) 4823 (table.insert args arg) 4824 (let [name (gensym)] 4825 (table.insert bindings name) 4826 (table.insert bindings arg) 4827 (table.insert args name)))) 4828 (let [body (list f (unpack args))] 4829 (table.insert body _VARARG) 4830 `(let ,bindings 4831 (fn [,_VARARG] 4832 ,body))))) 4833 4834 (fn pick-args* [n f] 4835 "Creates a function of arity n that applies its arguments to f. 4836 4837 For example, 4838 (pick-args 2 func) 4839 expands to 4840 (fn [_0_ _1_] (func _0_ _1_))" 4841 (if (and _G.io _G.io.stderr) 4842 (_G.io.stderr:write 4843 "-- WARNING: pick-args is deprecated and will be removed in the future.\n")) 4844 (assert (and (= (type n) :number) (= n (math.floor n)) (>= n 0)) 4845 (.. "Expected n to be an integer literal >= 0, got " (tostring n))) 4846 (let [bindings []] 4847 (for [i 1 n] 4848 (tset bindings i (gensym))) 4849 `(fn ,bindings 4850 (,f ,(unpack bindings))))) 4851 4852 (fn pick-values* [n ...] 4853 "Like the `values` special, but emits exactly n values. 4854 4855 For example, 4856 (pick-values 2 ...) 4857 expands to 4858 (let [(_0_ _1_) ...] 4859 (values _0_ _1_))" 4860 (assert (and (= :number (type n)) (>= n 0) (= n (math.floor n))) 4861 (.. "Expected n to be an integer >= 0, got " (tostring n))) 4862 (let [let-syms (list) 4863 let-values (if (= 1 (select "#" ...)) ... `(values ,...))] 4864 (for [i 1 n] 4865 (table.insert let-syms (gensym))) 4866 (if (= n 0) `(values) 4867 `(let [,let-syms ,let-values] 4868 (values ,(unpack let-syms)))))) 4869 4870 (fn lambda* [...] 4871 "Function literal with nil-checked arguments. 4872 Like `fn`, but will throw an exception if a declared argument is passed in as 4873 nil, unless that argument's name begins with a question mark." 4874 (let [args [...] 4875 has-internal-name? (sym? (. args 1)) 4876 arglist (if has-internal-name? (. args 2) (. args 1)) 4877 docstring-position (if has-internal-name? 3 2) 4878 has-docstring? (and (> (length args) docstring-position) 4879 (= :string (type (. args docstring-position)))) 4880 arity-check-position (- 4 (if has-internal-name? 0 1) 4881 (if has-docstring? 0 1)) 4882 empty-body? (< (length args) arity-check-position)] 4883 (fn check! [a] 4884 (if (table? a) 4885 (each [_ a (pairs a)] 4886 (check! a)) 4887 (let [as (tostring a)] 4888 (and (not (as:match "^?")) (not= as "&") (not= as "_") 4889 (not= as "...") (not= as "&as"))) 4890 (table.insert args arity-check-position 4891 `(_G.assert (not= nil ,a) 4892 ,(: "Missing argument %s on %s:%s" :format 4893 (tostring a) 4894 (or a.filename :unknown) 4895 (or a.line "?")))))) 4896 4897 (assert (= :table (type arglist)) "expected arg list") 4898 (each [_ a (ipairs arglist)] 4899 (check! a)) 4900 (if empty-body? 4901 (table.insert args (sym :nil))) 4902 `(fn ,(unpack args)))) 4903 4904 (fn macro* [name ...] 4905 "Define a single macro." 4906 (assert (sym? name) "expected symbol for macro name") 4907 (local args [...]) 4908 `(macros {,(tostring name) (fn ,(unpack args))})) 4909 4910 (fn macrodebug* [form return?] 4911 "Print the resulting form after performing macroexpansion. 4912 With a second argument, returns expanded form as a string instead of printing." 4913 (let [handle (if return? `do `print)] 4914 `(,handle ,(view (macroexpand form _SCOPE))))) 4915 4916 (fn import-macros* [binding1 module-name1 ...] 4917 "Binds a table of macros from each macro module according to a binding form. 4918 Each binding form can be either a symbol or a k/v destructuring table. 4919 Example: 4920 (import-macros mymacros :my-macros ; bind to symbol 4921 {:macro1 alias : macro2} :proj.macros) ; import by name" 4922 (assert (and binding1 module-name1 (= 0 (% (select "#" ...) 2))) 4923 "expected even number of binding/modulename pairs") 4924 (for [i 1 (select "#" binding1 module-name1 ...) 2] 4925 (let [(binding modname) (select i binding1 module-name1 ...) 4926 ;; generate a subscope of current scope, use require-macros 4927 ;; to bring in macro module. after that, we just copy the 4928 ;; macros from subscope to scope. 4929 scope (get-scope) 4930 macros* (_SPECIALS.require-macros `(import-macros ,modname) 4931 (fennel.scope scope) {} ast)] 4932 (if (sym? binding) 4933 ;; bind whole table of macros to table bound to symbol 4934 (tset scope.macros (. binding 1) macros*) 4935 ;; 1-level table destructuring for importing individual macros 4936 (table? binding) 4937 (each [macro-name [import-key] (pairs binding)] 4938 (assert (= :function (type (. macros* macro-name))) 4939 (.. "macro " macro-name " not found in module " 4940 (tostring modname))) 4941 (tset scope.macros import-key (. macros* macro-name)))))) 4942 nil) 4943 4944 ;;; Pattern matching 4945 4946 (fn match-values [vals pattern unifications match-pattern] 4947 (let [condition `(and) 4948 bindings []] 4949 (each [i pat (ipairs pattern)] 4950 (let [(subcondition subbindings) (match-pattern [(. vals i)] pat 4951 unifications)] 4952 (table.insert condition subcondition) 4953 (each [_ b (ipairs subbindings)] 4954 (table.insert bindings b)))) 4955 (values condition bindings))) 4956 4957 (fn match-table [val pattern unifications match-pattern] 4958 (let [condition `(and (= (_G.type ,val) :table)) 4959 bindings []] 4960 (each [k pat (pairs pattern)] 4961 (if (= pat `&) 4962 (do 4963 (assert (= nil (. pattern (+ k 2))) 4964 "expected & rest argument before last parameter") 4965 (table.insert bindings (. pattern (+ k 1))) 4966 (table.insert bindings 4967 [`(select ,k ((or table.unpack _G.unpack) ,val))])) 4968 (= k `&as) 4969 (do 4970 (table.insert bindings pat) 4971 (table.insert bindings val)) 4972 (and (= :number (type k)) (= `&as pat)) 4973 (do 4974 (assert (= nil (. pattern (+ k 2))) 4975 "expected &as argument before last parameter") 4976 (table.insert bindings (. pattern (+ k 1))) 4977 (table.insert bindings val)) 4978 ;; don't process the pattern right after &/&as; already got it 4979 (or (not= :number (type k)) (and (not= `&as (. pattern (- k 1))) 4980 (not= `& (. pattern (- k 1))))) 4981 (let [subval `(. ,val ,k) 4982 (subcondition subbindings) (match-pattern [subval] pat 4983 unifications)] 4984 (table.insert condition subcondition) 4985 (each [_ b (ipairs subbindings)] 4986 (table.insert bindings b))))) 4987 (values condition bindings))) 4988 4989 (fn match-pattern [vals pattern unifications] 4990 "Takes the AST of values and a single pattern and returns a condition 4991 to determine if it matches as well as a list of bindings to 4992 introduce for the duration of the body if it does match." 4993 ;; we have to assume we're matching against multiple values here until we 4994 ;; know we're either in a multi-valued clause (in which case we know the # 4995 ;; of vals) or we're not, in which case we only care about the first one. 4996 (let [[val] vals] 4997 (if (or (and (sym? pattern) ; unification with outer locals (or nil) 4998 (not= "_" (tostring pattern)) ; never unify _ 4999 (or (in-scope? pattern) (= :nil (tostring pattern)))) 5000 (and (multi-sym? pattern) (in-scope? (. (multi-sym? pattern) 1)))) 5001 (values `(= ,val ,pattern) []) 5002 ;; unify a local we've seen already 5003 (and (sym? pattern) (. unifications (tostring pattern))) 5004 (values `(= ,(. unifications (tostring pattern)) ,val) []) 5005 ;; bind a fresh local 5006 (sym? pattern) 5007 (let [wildcard? (: (tostring pattern) :find "^_")] 5008 (if (not wildcard?) (tset unifications (tostring pattern) val)) 5009 (values (if (or wildcard? (string.find (tostring pattern) "^?")) true 5010 `(not= ,(sym :nil) ,val)) [pattern val])) 5011 ;; guard clause 5012 (and (list? pattern) (= (. pattern 2) `?)) 5013 (let [(pcondition bindings) (match-pattern vals (. pattern 1) 5014 unifications) 5015 condition `(and ,(unpack pattern 3))] 5016 (values `(and ,pcondition 5017 (let ,bindings 5018 ,condition)) bindings)) 5019 ;; multi-valued patterns (represented as lists) 5020 (list? pattern) 5021 (match-values vals pattern unifications match-pattern) 5022 ;; table patterns 5023 (= (type pattern) :table) 5024 (match-table val pattern unifications match-pattern) 5025 ;; literal value 5026 (values `(= ,val ,pattern) [])))) 5027 5028 (fn match-condition [vals clauses] 5029 "Construct the actual `if` AST for the given match values and clauses." 5030 (if (not= 0 (% (length clauses) 2)) ; treat odd final clause as default 5031 (table.insert clauses (length clauses) (sym "_"))) 5032 (let [out `(if)] 5033 (for [i 1 (length clauses) 2] 5034 (let [pattern (. clauses i) 5035 body (. clauses (+ i 1)) 5036 (condition bindings) (match-pattern vals pattern {})] 5037 (table.insert out condition) 5038 (table.insert out `(let ,bindings 5039 ,body)))) 5040 out)) 5041 5042 (fn match-val-syms [clauses] 5043 "How many multi-valued clauses are there? return a list of that many gensyms." 5044 (let [syms (list (gensym))] 5045 (for [i 1 (length clauses) 2] 5046 (let [clause (if (and (list? (. clauses i)) (= `? (. clauses i 2))) 5047 (. clauses i 1) 5048 (. clauses i))] 5049 (if (list? clause) 5050 (each [valnum (ipairs clause)] 5051 (if (not (. syms valnum)) 5052 (tset syms valnum (gensym))))))) 5053 syms)) 5054 5055 (fn match* [val ...] 5056 ;; Old implementation of match macro, which doesn't directly support 5057 ;; `where' and `or'. New syntax is implemented in `match-where', 5058 ;; which simply generates old syntax and feeds it to `match*'. 5059 (let [clauses [...] 5060 vals (match-val-syms clauses)] 5061 (assert (= 0 (math.fmod (length clauses) 2)) 5062 "expected even number of pattern/body pairs") 5063 ;; protect against multiple evaluation of the value, bind against as 5064 ;; many values as we ever match against in the clauses. 5065 (list `let [vals val] (match-condition vals clauses)))) 5066 5067 ;; Construction of old match syntax from new syntax 5068 5069 (fn partition-2 [seq] 5070 ;; Partition `seq` by 2. 5071 ;; If `seq` has odd amount of elements, the last one is dropped. 5072 ;; 5073 ;; Input: [1 2 3 4 5] 5074 ;; Output: [[1 2] [3 4]] 5075 (let [firsts [] 5076 seconds [] 5077 res []] 5078 (for [i 1 (length seq) 2] 5079 (let [first (. seq i) 5080 second (. seq (+ i 1))] 5081 (table.insert firsts (if (not= nil first) first `nil)) 5082 (table.insert seconds (if (not= nil second) second `nil)))) 5083 (each [i v1 (ipairs firsts)] 5084 (let [v2 (. seconds i)] 5085 (if (not= nil v2) 5086 (table.insert res [v1 v2])))) 5087 res)) 5088 5089 (fn transform-or [[_ & pats] guards] 5090 ;; Transforms `(or pat pats*)` lists into match `guard` patterns. 5091 ;; 5092 ;; (or pat1 pat2), guard => [(pat1 ? guard) (pat2 ? guard)] 5093 (let [res []] 5094 (each [_ pat (ipairs pats)] 5095 (table.insert res (list pat `? (unpack guards)))) 5096 res)) 5097 5098 (fn transform-cond [cond] 5099 ;; Transforms `where` cond into sequence of `match` guards. 5100 ;; 5101 ;; pat => [pat] 5102 ;; (where pat guard) => [(pat ? guard)] 5103 ;; (where (or pat1 pat2) guard) => [(pat1 ? guard) (pat2 ? guard)] 5104 (if (and (list? cond) (= (. cond 1) `where)) 5105 (let [second (. cond 2)] 5106 (if (and (list? second) (= (. second 1) `or)) 5107 (transform-or second [(unpack cond 3)]) 5108 :else 5109 [(list second `? (unpack cond 3))])) 5110 :else 5111 [cond])) 5112 5113 (fn match-where [val ...] 5114 "Perform pattern matching on val. See reference for details. 5115 5116 Syntax: 5117 5118 (match data-expression 5119 pattern body 5120 (where pattern guard guards*) body 5121 (where (or pattern patterns*) guard guards*) body)" 5122 (let [conds-bodies (partition-2 [...]) 5123 else-branch (if (not= 0 (% (select "#" ...) 2)) 5124 (select (select "#" ...) ...)) 5125 match-body []] 5126 (each [_ [cond body] (ipairs conds-bodies)] 5127 (each [_ cond (ipairs (transform-cond cond))] 5128 (table.insert match-body cond) 5129 (table.insert match-body body))) 5130 (if else-branch 5131 (table.insert match-body else-branch)) 5132 (match* val (unpack match-body)))) 5133 5134 {:-> ->* 5135 :->> ->>* 5136 :-?> -?>* 5137 :-?>> -?>>* 5138 :?. ?dot 5139 :doto doto* 5140 :when when* 5141 :with-open with-open* 5142 :collect collect* 5143 :icollect icollect* 5144 :accumulate accumulate* 5145 :partial partial* 5146 :lambda lambda* 5147 :pick-args pick-args* 5148 :pick-values pick-values* 5149 :macro macro* 5150 :macrodebug macrodebug* 5151 :import-macros import-macros* 5152 :match match-where} 5153 ]===] 5154 local module_name = "fennel.macros" 5155 local _ 5156 local function _622_() 5157 return mod 5158 end 5159 package.preload[module_name] = _622_ 5160 _ = nil 5161 local env 5162 do 5163 local _623_ = specials["make-compiler-env"](nil, compiler.scopes.compiler, {}) 5164 do end (_623_)["utils"] = utils 5165 _623_["fennel"] = mod 5166 env = _623_ 5167 end 5168 local built_ins = eval(builtin_macros, {env = env, scope = compiler.scopes.compiler, allowedGlobals = false, useMetadata = true, filename = "src/fennel/macros.fnl", moduleName = module_name}) 5169 for k, v in pairs(built_ins) do 5170 compiler.scopes.global.macros[k] = v 5171 end 5172 compiler.scopes.global.macros["\206\187"] = compiler.scopes.global.macros.lambda 5173 package.preload[module_name] = nil 5174end 5175return mod 5176