1do 2local _ENV = _ENV 3package.preload[ "erde" ] = function( ... ) local arg = _G.arg; 4local lib = require("erde.lib") 5local VERSION 6do 7 local __ERDE_TMP_4__ 8 __ERDE_TMP_4__ = require("erde.constants") 9 VERSION = __ERDE_TMP_4__["VERSION"] 10end 11return { 12 version = VERSION, 13 compile = require("erde.compile"), 14 rewrite = lib.rewrite, 15 traceback = lib.traceback, 16 run = lib.run, 17 load = lib.load, 18 unload = lib.unload, 19} 20-- Compiled with Erde 0.6.0-1 21-- __ERDE_COMPILED__ 22end 23end 24 25do 26local _ENV = _ENV 27package.preload[ "erde.compile" ] = function( ... ) local arg = _G.arg; 28local config = require("erde.config") 29local BINOP_ASSIGNMENT_TOKENS, BINOPS, BITOPS, BITLIB_METHODS, COMPILED_FOOTER_COMMENT, DIGIT, KEYWORDS, LEFT_ASSOCIATIVE, LUA_KEYWORDS, SURROUND_ENDS, TERMINALS, TOKEN_TYPES, UNOPS, VERSION 30do 31 local __ERDE_TMP_4__ 32 __ERDE_TMP_4__ = require("erde.constants") 33 BINOP_ASSIGNMENT_TOKENS = __ERDE_TMP_4__["BINOP_ASSIGNMENT_TOKENS"] 34 BINOPS = __ERDE_TMP_4__["BINOPS"] 35 BITOPS = __ERDE_TMP_4__["BITOPS"] 36 BITLIB_METHODS = __ERDE_TMP_4__["BITLIB_METHODS"] 37 COMPILED_FOOTER_COMMENT = __ERDE_TMP_4__["COMPILED_FOOTER_COMMENT"] 38 DIGIT = __ERDE_TMP_4__["DIGIT"] 39 KEYWORDS = __ERDE_TMP_4__["KEYWORDS"] 40 LEFT_ASSOCIATIVE = __ERDE_TMP_4__["LEFT_ASSOCIATIVE"] 41 LUA_KEYWORDS = __ERDE_TMP_4__["LUA_KEYWORDS"] 42 SURROUND_ENDS = __ERDE_TMP_4__["SURROUND_ENDS"] 43 TERMINALS = __ERDE_TMP_4__["TERMINALS"] 44 TOKEN_TYPES = __ERDE_TMP_4__["TOKEN_TYPES"] 45 UNOPS = __ERDE_TMP_4__["UNOPS"] 46 VERSION = __ERDE_TMP_4__["VERSION"] 47end 48local table 49do 50 local __ERDE_TMP_7__ 51 __ERDE_TMP_7__ = require("erde.stdlib") 52 table = __ERDE_TMP_7__["table"] 53end 54local tokenize = require("erde.tokenize") 55local get_source_alias 56do 57 local __ERDE_TMP_12__ 58 __ERDE_TMP_12__ = require("erde.utils") 59 get_source_alias = __ERDE_TMP_12__["get_source_alias"] 60end 61local unpack = table.unpack or unpack 62local arrow_function, block, expression, statement 63local tokens 64local current_token_index 65local current_token 66local block_depth 67local tmp_name_counter 68local break_name 69local has_continue 70local has_module_declarations 71local is_module_return_block, module_return_line 72local is_varargs_block 73local block_declarations, block_declaration_stack 74local goto_jumps, goto_labels 75local alias 76local lua_target 77local bitlib 78local function throw(message, line) 79 if line == nil then 80 line = current_token.line 81 end 82 error((tostring(alias) .. ":" .. tostring(line) .. ": " .. tostring(message)), 0) 83end 84local function add_block_declaration(var, scope, stack_depth) 85 if stack_depth == nil then 86 stack_depth = block_depth 87 end 88 if block_declaration_stack[stack_depth] == nil then 89 for i = stack_depth - 1, 1, -1 do 90 local parent_block_declarations = block_declaration_stack[i] 91 if parent_block_declarations ~= nil then 92 block_declaration_stack[stack_depth] = table.shallowcopy(parent_block_declarations) 93 break 94 end 95 end 96 end 97 local target_block_declarations = block_declaration_stack[stack_depth] 98 if type(var) == "string" then 99 target_block_declarations[var] = scope 100 else 101 for _, declaration_name in ipairs(var.declaration_names) do 102 target_block_declarations[declaration_name] = scope 103 end 104 end 105end 106local function consume() 107 local consumed_token_value = current_token.value 108 current_token_index = current_token_index + 1 109 current_token = tokens[current_token_index] 110 return consumed_token_value 111end 112local function branch(token) 113 if token == current_token.value then 114 consume() 115 return true 116 end 117end 118local function expect(token, should_consume) 119 if current_token.type == TOKEN_TYPES.EOF then 120 throw(("unexpected eof (expected " .. tostring(token) .. ")")) 121 end 122 if token ~= current_token.value then 123 throw(("expected '" .. tostring(token) .. "' got '" .. tostring(current_token.value) .. "'")) 124 end 125 if should_consume then 126 return consume() 127 end 128end 129local function look_past_surround(token_start_index) 130 if token_start_index == nil then 131 token_start_index = current_token_index 132 end 133 local surround_start_token = tokens[token_start_index] 134 local surround_end = SURROUND_ENDS[surround_start_token.value] 135 local surround_depth = 1 136 local look_ahead_token_index = token_start_index + 1 137 local look_ahead_token = tokens[look_ahead_token_index] 138 repeat 139 if look_ahead_token.type == TOKEN_TYPES.EOF then 140 throw(("unexpected eof, missing '" .. tostring(surround_end) .. "'"), surround_start_token.line) 141 end 142 if look_ahead_token.value == surround_start_token.value then 143 surround_depth = surround_depth + 1 144 elseif look_ahead_token.value == surround_end then 145 surround_depth = surround_depth - 1 146 end 147 look_ahead_token_index = look_ahead_token_index + 1 148 look_ahead_token = tokens[look_ahead_token_index] 149 until surround_depth == 0 150 return look_ahead_token, look_ahead_token_index 151end 152local function new_tmp_name() 153 tmp_name_counter = tmp_name_counter + 1 154 return ("__ERDE_TMP_" .. tostring(tmp_name_counter) .. "__") 155end 156local function get_compile_name(name, scope) 157 if scope == "module" then 158 if LUA_KEYWORDS[name] then 159 return ("_MODULE['" .. tostring(name) .. "']") 160 else 161 return "_MODULE." .. name 162 end 163 elseif scope == "global" then 164 if LUA_KEYWORDS[name] then 165 return ("_G['" .. tostring(name) .. "']") 166 else 167 return "_G." .. name 168 end 169 end 170 if LUA_KEYWORDS[name] then 171 return (tostring(name) .. "_") 172 else 173 return name 174 end 175end 176local function weave(t, separator) 177 if separator == nil then 178 separator = "," 179 end 180 local woven = {} 181 local len = #t 182 for i = 1, len - 1 do 183 table.insert(woven, t[i]) 184 if type(t[i]) ~= "number" then 185 table.insert(woven, separator) 186 end 187 end 188 table.insert(woven, t[len]) 189 return woven 190end 191local function compile_binop(op_token, op_line, lhs, rhs) 192 local needs_floor_division_polyfill = ( 193 op_token == "//" 194 and lua_target ~= "5.3" 195 and lua_target ~= "5.4" 196 and lua_target ~= "5.3+" 197 and lua_target ~= "5.4+" 198 ) 199 if needs_floor_division_polyfill then 200 return { 201 op_line, 202 "math.floor(", 203 lhs, 204 op_line, 205 "/", 206 rhs, 207 ")", 208 } 209 elseif bitlib and BITOPS[op_token] then 210 return { 211 op_line, 212 ("(require('" .. tostring(bitlib) .. "')." .. tostring(BITLIB_METHODS[op_token]) .. "("), 213 lhs, 214 ",", 215 rhs, 216 "))", 217 } 218 elseif op_token == "!=" then 219 return { 220 lhs, 221 "~=", 222 rhs, 223 } 224 elseif op_token == "==" then 225 return { 226 lhs, 227 op_token, 228 rhs, 229 } 230 elseif op_token == "||" then 231 return { 232 lhs, 233 "or", 234 rhs, 235 } 236 elseif op_token == "&&" then 237 return { 238 lhs, 239 "and", 240 rhs, 241 } 242 else 243 return { 244 lhs, 245 op_line, 246 op_token, 247 rhs, 248 } 249 end 250end 251local function list(callback, break_token) 252 local list = {} 253 repeat 254 table.insert(list, callback() or nil) 255 until not branch(",") or (break_token and current_token.value == break_token) 256 return list 257end 258local function surround(open_char, close_char, callback) 259 expect(open_char, true) 260 local result = callback() 261 expect(close_char, true) 262 return result 263end 264local function surround_list(open_char, close_char, allow_empty, callback) 265 return surround(open_char, close_char, function() 266 if current_token.value ~= close_char or not allow_empty then 267 return list(callback, close_char) 268 else 269 return {} 270 end 271 end) 272end 273local function name() 274 if current_token.type == TOKEN_TYPES.EOF then
275 throw("unexpected eof") 276 end 277 if current_token.type ~= TOKEN_TYPES.WORD then 278 throw(("unexpected token '" .. tostring(current_token.value) .. "'")) 279 end 280 if KEYWORDS[current_token.value] ~= nil then 281 throw(("unexpected keyword '" .. tostring(current_token.value) .. "'")) 282 end 283 if TERMINALS[current_token.value] ~= nil then 284 throw(("unexpected builtin '" .. tostring(current_token.value) .. "'")) 285 end 286 return consume() 287end 288local function array_destructure(scope) 289 local compile_lines = {} 290 local compile_name = new_tmp_name() 291 local declaration_names = {} 292 local array_index = 0 293 table.insert(compile_lines, current_token.line) 294 surround_list("[", "]", false, function() 295 array_index = array_index + 1 296 local declaration_name = name() 297 table.insert(declaration_names, declaration_name) 298 local assignment_name = get_compile_name(declaration_name, scope) 299 table.insert( 300 compile_lines, 301 (tostring(assignment_name) .. " = " .. tostring(compile_name) .. "[" .. tostring(array_index) .. "]") 302 ) 303 if branch("=") then 304 table.insert( 305 compile_lines, 306 ("if " .. tostring(assignment_name) .. " == nil then " .. tostring(assignment_name) .. " = ") 307 ) 308 table.insert(compile_lines, expression()) 309 table.insert(compile_lines, "end") 310 end 311 end) 312 return { 313 compile_lines = compile_lines, 314 compile_name = compile_name, 315 declaration_names = declaration_names, 316 } 317end 318local function map_destructure(scope) 319 local compile_lines = {} 320 local compile_name = new_tmp_name() 321 local declaration_names = {} 322 table.insert(compile_lines, current_token.line) 323 surround_list("{", "}", false, function() 324 local key = name() 325 local declaration_name = branch(":") and name() or key 326 table.insert(declaration_names, declaration_name) 327 local assignment_name = get_compile_name(declaration_name, scope) 328 if LUA_KEYWORDS[declaration_name] then 329 table.insert( 330 compile_lines, 331 (tostring(assignment_name) .. " = " .. tostring(compile_name) .. "['" .. tostring(key) .. "']") 332 ) 333 else 334 table.insert( 335 compile_lines, 336 (tostring(assignment_name) .. " = " .. tostring(compile_name) .. "." .. tostring(key)) 337 ) 338 end 339 if branch("=") then 340 table.insert( 341 compile_lines, 342 ("if " .. tostring(assignment_name) .. " == nil then " .. tostring(assignment_name) .. " = ") 343 ) 344 table.insert(compile_lines, expression()) 345 table.insert(compile_lines, "end") 346 end 347 end) 348 return { 349 compile_lines = compile_lines, 350 compile_name = compile_name, 351 declaration_names = declaration_names, 352 } 353end 354local function variable(scope) 355 if scope == nil then 356 scope = "local" 357 end 358 if current_token.value == "[" then 359 return array_destructure(scope) 360 elseif current_token.value == "{" then 361 return map_destructure(scope) 362 else 363 return name() 364 end 365end 366local function bracket_index(index_chain_state) 367 local compile_lines = { 368 current_token.line, 369 "[", 370 surround("[", "]", expression), 371 "]", 372 } 373 index_chain_state.final_base_compile_lines = table.shallowcopy(index_chain_state.compile_lines) 374 index_chain_state.final_index_compile_lines = compile_lines 375 table.insert(index_chain_state.compile_lines, compile_lines) 376end 377local function dot_index(index_chain_state) 378 local compile_lines = { 379 current_token.line, 380 } 381 consume() 382 local key = name() 383 if LUA_KEYWORDS[key] then 384 table.insert(compile_lines, ("['" .. tostring(key) .. "']")) 385 else 386 table.insert(compile_lines, "." .. key) 387 end 388 index_chain_state.final_base_compile_lines = table.shallowcopy(index_chain_state.compile_lines) 389 index_chain_state.final_index_compile_lines = compile_lines 390 table.insert(index_chain_state.compile_lines, compile_lines) 391end 392local function method_index(index_chain_state) 393 table.insert(index_chain_state.compile_lines, current_token.line) 394 consume() 395 local method_name = name() 396 local method_parameters = surround_list("(", ")", true, expression) 397 if not LUA_KEYWORDS[method_name] then 398 table.insert(index_chain_state.compile_lines, (":" .. tostring(method_name) .. "(")) 399 table.insert(index_chain_state.compile_lines, weave(method_parameters)) 400 table.insert(index_chain_state.compile_lines, ")") 401 elseif index_chain_state.has_trivial_base and index_chain_state.chain_len == 0 then 402 table.insert(index_chain_state.compile_lines, ("['" .. tostring(method_name) .. "'](")) 403 table.insert(method_parameters, 1, index_chain_state.base_compile_lines) 404 table.insert(index_chain_state.compile_lines, weave(method_parameters)) 405 table.insert(index_chain_state.compile_lines, ")") 406 else 407 index_chain_state.needs_block_compile = true 408 table.insert(index_chain_state.block_compile_lines, index_chain_state.block_compile_name .. "=") 409 table.insert(index_chain_state.block_compile_lines, index_chain_state.compile_lines) 410 table.insert(method_parameters, 1, index_chain_state.block_compile_name) 411 index_chain_state.compile_lines = { 412 (tostring(index_chain_state.block_compile_name) .. "['" .. tostring(method_name) .. "']("), 413 weave(method_parameters), 414 ")", 415 } 416 end 417end 418local function function_call_index(index_chain_state) 419 local preceding_compile_lines = index_chain_state.compile_lines 420 local preceding_compile_lines_len = #preceding_compile_lines 421 while type(preceding_compile_lines[preceding_compile_lines_len]) == "table" do 422 preceding_compile_lines = preceding_compile_lines[preceding_compile_lines_len] 423 preceding_compile_lines_len = #preceding_compile_lines 424 end 425 preceding_compile_lines[preceding_compile_lines_len] = preceding_compile_lines[preceding_compile_lines_len] .. "(" 426 table.insert(index_chain_state.compile_lines, weave(surround_list("(", ")", true, expression))) 427 table.insert(index_chain_state.compile_lines, ")") 428end 429local function index_chain(options) 430 local block_compile_name = new_tmp_name() 431 local index_chain_state = { 432 base_compile_lines = options.base_compile_lines, 433 compile_lines = { 434 options.base_compile_lines, 435 }, 436 has_trivial_base = options.has_trivial_base, 437 chain_len = 0, 438 is_function_call = false, 439 needs_block_compile = false, 440 block_compile_name = block_compile_name, 441 block_compile_lines = { 442 "local " .. block_compile_name, 443 }, 444 final_base_compile_lines = options.base_compile_lines, 445 final_index_compile_lines = {}, 446 } 447 if options.wrap_base_compile_lines then 448 table.insert(index_chain_state.compile_lines, 1, "(") 449 table.insert(index_chain_state.compile_lines, ")") 450 end 451 while true do 452 if current_token.value == "(" and current_token.line == tokens[current_token_index - 1].line then 453 index_chain_state.is_function_call = true 454 function_call_index(index_chain_state) 455 elseif current_token.value == "[" then 456 index_chain_state.is_function_call = false 457 bracket_index(index_chain_state) 458 elseif current_token.value == "." then 459 index_chain_state.is_function_call = false 460 dot_index(index_chain_state) 461 elseif current_token.value == ":" then 462 index_chain_state.is_function_call = true 463 method_index(index_chain_state) 464 else 465 break 466 end 467 index_chain_state.chain_len = index_chain_state.chain_len + 1 468 end 469 if options.require_chain and index_chain_state.chain_len == 0 then 470 if current_token.type == TOKEN_TYPES.EOF then
471 throw("unexpected eof") 472 else 473 throw(("unexpected token '" .. tostring(current_token.value) .. "'")) 474 end 475 end 476 if index_chain_state.chain_len == 0 then 477 index_chain_state.compile_lines = options.base_compile_lines 478 end 479 return index_chain_state 480end 481local function single_quote_string() 482 consume() 483 if current_token.type == TOKEN_TYPES.SINGLE_QUOTE_STRING then 484 return { 485 current_token.line, 486 "'" .. consume(), 487 } 488 else 489 return { 490 current_token.line, 491 "'" .. consume() .. consume(), 492 } 493 end 494end 495local function double_quote_string() 496 local double_quote_string_line = current_token.line 497 local has_interpolation = false 498 consume() 499 if current_token.type == TOKEN_TYPES.DOUBLE_QUOTE_STRING then 500 return { 501 double_quote_string_line, 502 '"' .. consume(), 503 }, has_interpolation 504 end 505 local compile_lines = {} 506 local content = "" 507 repeat 508 if current_token.type == TOKEN_TYPES.INTERPOLATION then 509 has_interpolation = true 510 if content ~= "" then 511 table.insert(compile_lines, '"' .. content .. '"') 512 end 513 table.insert(compile_lines, { 514 "tostring(", 515 surround("{", "}", expression), 516 ")", 517 }) 518 content = "" 519 else 520 content = content .. consume() 521 end 522 until current_token.type == TOKEN_TYPES.DOUBLE_QUOTE_STRING 523 if content ~= "" then 524 table.insert(compile_lines, '"' .. content .. '"') 525 end 526 consume() 527 return { 528 double_quote_string_line, 529 weave(compile_lines, ".."), 530 }, has_interpolation 531end 532local function block_string() 533 local block_string_line = current_token.line 534 local has_interpolation = false 535 local start_quote = "[" .. current_token.equals .. "[" 536 local end_quote = "]" .. current_token.equals .. "]" 537 consume() 538 if current_token.type == TOKEN_TYPES.BLOCK_STRING then 539 consume() 540 return { 541 block_string_line, 542 start_quote .. end_quote, 543 }, has_interpolation 544 end 545 local compile_lines = {} 546 local content = "" 547 repeat 548 if current_token.type == TOKEN_TYPES.INTERPOLATION then 549 has_interpolation = true 550 if content ~= "" then 551 table.insert(compile_lines, start_quote .. content .. end_quote) 552 end 553 table.insert(compile_lines, { 554 "tostring(", 555 surround("{", "}", expression), 556 ")", 557 }) 558 content = "" 559 if current_token.value:sub(1, 1) == "\n" then 560 content = content .. "\n" .. consume() 561 end 562 else 563 content = content .. consume() 564 end 565 until current_token.type == TOKEN_TYPES.BLOCK_STRING 566 if content ~= "" then 567 table.insert(compile_lines, start_quote .. content .. end_quote) 568 end 569 consume() 570 return { 571 block_string_line, 572 weave(compile_lines, ".."), 573 }, has_interpolation 574end 575local function table_constructor() 576 local table_constructor_line = current_token.line 577 local compile_lines = {} 578 surround_list("{", "}", true, function() 579 local next_token = tokens[current_token_index + 1] 580 if current_token.value == "[" then 581 table.insert(compile_lines, "[") 582 table.insert(compile_lines, surround("[", "]", expression)) 583 table.insert(compile_lines, "]") 584 table.insert(compile_lines, expect("=", true)) 585 elseif next_token.type == TOKEN_TYPES.SYMBOL and next_token.value == "=" then 586 local key = name() 587 if LUA_KEYWORDS[key] then 588 table.insert(compile_lines, ("['" .. tostring(key) .. "']") .. consume()) 589 else 590 table.insert(compile_lines, key .. consume()) 591 end 592 end 593 table.insert(compile_lines, expression()) 594 table.insert(compile_lines, ",") 595 end) 596 return { 597 table_constructor_line, 598 "{", 599 compile_lines, 600 "}", 601 } 602end 603local function return_list() 604 local look_ahead_limit_token, look_ahead_limit_token_index = look_past_surround() 605 if look_ahead_limit_token.value == "->" or look_ahead_limit_token.value == "=>" then 606 return arrow_function() 607 end 608 local look_ahead_token_index = current_token_index + 1 609 local look_ahead_token = tokens[look_ahead_token_index] 610 while look_ahead_token_index < look_ahead_limit_token_index do 611 if look_ahead_token.type == TOKEN_TYPES.SYMBOL and SURROUND_ENDS[look_ahead_token.value] then 612 look_ahead_token, look_ahead_token_index = look_past_surround(look_ahead_token_index) 613 elseif look_ahead_token.type == TOKEN_TYPES.SYMBOL and look_ahead_token.value == "," then 614 return weave(surround_list("(", ")", false, expression)) 615 else 616 look_ahead_token_index = look_ahead_token_index + 1 617 look_ahead_token = tokens[look_ahead_token_index] 618 end 619 end 620 return expression() 621end 622local function block_return() 623 if is_module_return_block then 624 module_return_line = current_token.line 625 end 626 local compile_lines = { 627 consume(), 628 } 629 if block_depth == 1 then 630 if current_token.type ~= TOKEN_TYPES.EOF then 631 if current_token.value == "(" then 632 table.insert(compile_lines, return_list()) 633 else 634 table.insert(compile_lines, weave(list(expression))) 635 end 636 end 637 if current_token.type ~= TOKEN_TYPES.EOF then 638 throw(("expected '<eof>', got '" .. tostring(current_token.value) .. "'")) 639 end 640 else 641 if current_token.value ~= "}" then 642 if current_token.value == "(" then 643 table.insert(compile_lines, return_list()) 644 else 645 table.insert(compile_lines, weave(list(expression))) 646 end 647 end 648 if current_token.value ~= "}" then 649 throw(("expected '}', got '" .. tostring(current_token.value) .. "'")) 650 end 651 end 652 return compile_lines 653end 654local function parameters() 655 local compile_lines = {} 656 local compile_names = {} 657 local has_varargs = false 658 surround_list("(", ")", true, function() 659 if branch("...") then 660 has_varargs = true 661 table.insert(compile_names, "...") 662 if current_token.type == TOKEN_TYPES.WORD then 663 local varargs_name = name() 664 table.insert(compile_lines, ("local " .. tostring(get_compile_name(varargs_name)) .. " = { ... }")) 665 add_block_declaration(varargs_name, "local", block_depth + 1) 666 end 667 branch(",") 668 expect(")") 669 else 670 local var = variable() 671 add_block_declaration(var, "local", block_depth + 1) 672 local compile_name = type(var) == "string" and get_compile_name(var) or var.compile_name 673 table.insert(compile_names, compile_name) 674 if branch("=") then 675 table.insert( 676 compile_lines, 677 ("if " .. tostring(compile_name) .. " == nil then " .. tostring(compile_name) .. " = ") 678 ) 679 table.insert(compile_lines, expression()) 680 table.insert(compile_lines, "end") 681 end 682 if type(var) == "table" then 683 table.insert( 684 compile_lines, 685 "local " .. table.concat(table.map(var.declaration_names, get_compile_name), ",") 686 ) 687 table.insert(compile_lines, var.compile_lines) 688 end 689 end 690 end) 691 return { 692 compile_lines = compile_lines, 693 compile_names = compile_names, 694 has_varargs = has_varargs, 695 } 696end 697local function function_block() 698 local old_is_module_return_block = is_module_return_block 699 local old_break_name = break_name 700 is_module_return_block = false 701 break_name = nil 702 local compile_lines = block() 703 is_module_return_block = old_is_module_return_block 704 break_name = old_break_name 705 return compile_lines 706end 707function arrow_function() 708 local old_is_varargs_block = is_varargs_block 709 local arrow_function_line = current_token.line 710 local param_compile_lines = {} 711 local param_compile_names = {} 712 if current_token.value == "(" then 713 local params = parameters() 714 table.insert(param_compile_lines, params.compile_lines) 715 is_varargs_block = params.has_varargs 716 param_compile_names = params.compile_names 717 else 718 is_varargs_block = false 719 local var = variable() 720 add_block_declaration(var, "local", block_depth + 1) 721 if type(var) == "string" then 722 table.insert(param_compile_names, get_compile_name(var)) 723 else 724 table.insert(param_compile_names, var.compile_name) 725 table.insert( 726 param_compile_lines, 727 "local " .. table.concat(table.map(var.declaration_names, get_compile_name), ",") 728 ) 729 table.insert(param_compile_lines, var.compile_lines) 730 end 731 end 732 if current_token.value == "->" then 733 consume() 734 elseif current_token.value == "=>" then 735 table.insert(param_compile_names, 1, "self") 736 consume() 737 elseif current_token.type == TOKEN_TYPES.EOF then
738 throw("unexpected eof (expected '->' or '=>')") 739 else 740 throw(("unexpected token '" .. tostring(current_token.value) .. "' (expected '->' or '=>')")) 741 end 742 local compile_lines = { 743 arrow_function_line, 744 ("function(" .. tostring(table.concat(param_compile_names, ",")) .. ")"), 745 param_compile_lines, 746 } 747 if current_token.value == "{" then 748 table.insert(compile_lines, surround("{", "}", function_block)) 749 else 750 table.insert(compile_lines, "return") 751 local old_block_declarations = block_declarations 752 block_depth = block_depth + 1 753 block_declaration_stack[block_depth] = block_declaration_stack[block_depth] or {} 754 block_declarations = block_declaration_stack[block_depth] 755 if current_token.value == "(" then 756 table.insert(compile_lines, return_list()) 757 else 758 table.insert(compile_lines, expression()) 759 end 760 block_declarations = old_block_declarations 761 block_declaration_stack[block_depth] = nil 762 block_depth = block_depth - 1 763 end 764 table.insert(compile_lines, "end") 765 is_varargs_block = old_is_varargs_block 766 return compile_lines 767end 768local function function_signature(scope) 769 local base_name = name() 770 if (current_token.value == "." or current_token.value == ":") and scope ~= nil then 771 throw("cannot use scopes for table values", current_token.line) 772 end 773 if scope == "module" or scope == "global" then 774 block_declarations[base_name] = scope 775 end 776 local signature = get_compile_name(base_name, scope or block_declarations[base_name]) 777 local needs_label_assignment = false 778 local needs_self_injection = false 779 while branch(".") do 780 local key = name() 781 if LUA_KEYWORDS[key] then 782 needs_label_assignment = true 783 signature = signature .. ("['" .. tostring(key) .. "']") 784 else 785 signature = signature .. "." .. key 786 end 787 end 788 if branch(":") then 789 local key = name() 790 if LUA_KEYWORDS[key] then 791 needs_label_assignment = true 792 needs_self_injection = true 793 signature = signature .. ("['" .. tostring(key) .. "']") 794 else 795 signature = signature .. ":" .. key 796 end 797 end 798 return { 799 signature = signature, 800 needs_label_assignment = needs_label_assignment, 801 needs_self_injection = needs_self_injection, 802 } 803end 804local function function_declaration(scope) 805 local compile_lines = { 806 current_token.line, 807 } 808 consume() 809 local signature, needs_label_assignment, needs_self_injection 810 do 811 local __ERDE_TMP_979__ 812 __ERDE_TMP_979__ = function_signature(scope) 813 signature = __ERDE_TMP_979__["signature"] 814 needs_label_assignment = __ERDE_TMP_979__["needs_label_assignment"] 815 needs_self_injection = __ERDE_TMP_979__["needs_self_injection"] 816 end 817 if scope == "local" then 818 table.insert(compile_lines, "local") 819 end 820 if needs_label_assignment then 821 table.insert(compile_lines, signature) 822 table.insert(compile_lines, "=") 823 table.insert(compile_lines, "function") 824 else 825 table.insert(compile_lines, "function") 826 table.insert(compile_lines, signature) 827 end 828 local params = parameters() 829 if needs_self_injection then 830 table.insert(params.compile_names, "self") 831 end 832 table.insert(compile_lines, "(" .. table.concat(params.compile_names, ",") .. ")") 833 table.insert(compile_lines, params.compile_lines) 834 local old_is_varargs_block = is_varargs_block 835 is_varargs_block = params.has_varargs 836 table.insert(compile_lines, surround("{", "}", function_block)) 837 is_varargs_block = old_is_varargs_block 838 table.insert(compile_lines, "end") 839 return compile_lines 840end 841local function index_chain_expression(options) 842 local index_chain = index_chain(options) 843 if index_chain.needs_block_compile then 844 return { 845 "(function()", 846 index_chain.block_compile_lines, 847 "return", 848 index_chain.compile_lines, 849 "end)()", 850 } 851 else 852 return index_chain.compile_lines 853 end 854end 855local function terminal_expression() 856 if current_token.type == TOKEN_TYPES.NUMBER then 857 return { 858 current_token.line, 859 consume(), 860 } 861 elseif current_token.type == TOKEN_TYPES.SINGLE_QUOTE_STRING then 862 return index_chain_expression({ 863 base_compile_lines = single_quote_string(), 864 has_trivial_base = true, 865 wrap_base_compile_lines = true, 866 }) 867 elseif current_token.type == TOKEN_TYPES.DOUBLE_QUOTE_STRING then 868 local compile_lines, has_interpolation = double_quote_string() 869 return index_chain_expression({ 870 base_compile_lines = compile_lines, 871 has_trivial_base = not has_interpolation, 872 wrap_base_compile_lines = true, 873 }) 874 elseif current_token.type == TOKEN_TYPES.BLOCK_STRING then 875 local compile_lines, has_interpolation = block_string() 876 return index_chain_expression({ 877 base_compile_lines = compile_lines, 878 has_trivial_base = not has_interpolation, 879 wrap_base_compile_lines = true, 880 }) 881 end 882 if TERMINALS[current_token.value] then 883 if current_token.value == "..." and not is_varargs_block then 884 throw("cannot use '...' outside a vararg function") 885 end 886 return { 887 current_token.line, 888 consume(), 889 } 890 end 891 local next_token = tokens[current_token_index + 1] 892 local is_arrow_function = ( 893 next_token.type == TOKEN_TYPES.SYMBOL and (next_token.value == "->" or next_token.value == "=>") 894 ) 895 if not is_arrow_function and SURROUND_ENDS[current_token.value] then 896 local past_surround_token = look_past_surround() 897 is_arrow_function = ( 898 past_surround_token.type == TOKEN_TYPES.SYMBOL 899 and (past_surround_token.value == "->" or past_surround_token.value == "=>") 900 ) 901 end 902 if is_arrow_function then 903 return arrow_function() 904 elseif current_token.value == "{" then 905 return table_constructor() 906 elseif current_token.value == "(" then 907 return index_chain_expression({ 908 base_compile_lines = { 909 current_token.line, 910 "(", 911 surround("(", ")", expression), 912 ")", 913 }, 914 }) 915 else 916 local base_name_line, base_name = current_token.line, name() 917 return index_chain_expression({ 918 base_compile_lines = { 919 base_name_line, 920 get_compile_name(base_name, block_declarations[base_name]), 921 }, 922 has_trivial_base = true, 923 }) 924 end 925end 926local function unop_expression() 927 local unop_line, unop = current_token.line, UNOPS[consume()] 928 local operand = expression(unop.prec + 1) 929 if unop.token == "!" then 930 return { 931 "not", 932 operand, 933 } 934 elseif unop.token ~= "~" then 935 return { 936 unop_line, 937 unop.token, 938 operand, 939 } 940 elseif bitlib then 941 return { 942 unop_line, 943 ("(require('" .. tostring(bitlib) .. "').bnot("), 944 operand, 945 "))", 946 } 947 elseif lua_target == "5.1+" or lua_target == "5.2+" then 948 throw("must specify bitlib for compiling bit operations when targeting 5.1+ or 5.2+", unop_line) 949 else 950 return { 951 unop_line, 952 unop.token, 953 operand, 954 } 955 end 956end 957function expression(min_prec) 958 if min_prec == nil then 959 min_prec = 1 960 end 961 if current_token.type == TOKEN_TYPES.EOF then
962 throw("unexpected eof (expected expression)") 963 end 964 local compile_lines = UNOPS[current_token.value] and unop_expression() or terminal_expression() 965 local binop_line, binop = current_token.line, BINOPS[current_token.value] 966 while binop and binop.prec >= min_prec do 967 if BITOPS[binop.token] and (lua_target == "5.1+" or lua_target == "5.2+") and not bitlib then 968 throw("must specify bitlib for compiling bit operations when targeting 5.1+ or 5.2+", binop_line) 969 end 970 consume() 971 if binop.token == "~" and current_token.value == "=" then 972 throw("unexpected token '~=', did you mean '!='?") 973 end 974 local operand = binop.assoc == LEFT_ASSOCIATIVE and expression(binop.prec + 1) or expression(binop.prec) 975 compile_lines = compile_binop(binop.token, binop_line, compile_lines, operand) 976 binop_line, binop = current_token.line, BINOPS[current_token.value] 977 end 978 return compile_lines 979end 980function block() 981 local old_block_declarations = block_declarations 982 block_depth = block_depth + 1 983 block_declaration_stack[block_depth] = block_declaration_stack[block_depth] 984 or table.shallowcopy(block_declaration_stack[block_depth - 1]) 985 block_declarations = block_declaration_stack[block_depth] 986 local compile_lines = {} 987 while current_token.value ~= "}" do 988 table.insert(compile_lines, statement()) 989 end 990 block_declarations = old_block_declarations 991 block_declaration_stack[block_depth] = nil 992 block_depth = block_depth - 1 993 return compile_lines 994end 995local function do_block() 996 return { 997 consume(), 998 surround("{", "}", block), 999 "end", 1000 } 1001end 1002local function loop_block() 1003 local old_break_name = break_name 1004 local old_has_continue = has_continue 1005 break_name = new_tmp_name() 1006 has_continue = false 1007 local compile_lines = block() 1008 if has_continue then 1009 if lua_target == "5.1" or lua_target == "5.1+" then 1010 table.insert(compile_lines, 1, ("local " .. tostring(break_name) .. " = true repeat")) 1011 table.insert( 1012 compile_lines, 1013 (tostring(break_name) .. " = false until true if " .. tostring(break_name) .. " then break end") 1014 ) 1015 else 1016 table.insert(compile_lines, ("::" .. tostring(break_name) .. "::")) 1017 end 1018 end 1019 break_name = old_break_name 1020 has_continue = old_has_continue 1021 return compile_lines 1022end 1023local function loop_break() 1024 consume() 1025 if break_name == nil then 1026 throw("cannot use 'break' outside of loop") 1027 end 1028 if lua_target == "5.1" or lua_target == "5.1+" or lua_target == "jit" then 1029 if current_token.value ~= "}" then 1030 throw(("expected '}', got '" .. tostring(current_token.value) .. "'")) 1031 end 1032 end 1033 return "break" 1034end 1035local function loop_continue() 1036 if break_name == nil then 1037 throw("cannot use 'continue' outside of loop") 1038 end 1039 has_continue = true 1040 consume() 1041 if lua_target == "5.1" or lua_target == "5.1+" then 1042 return (tostring(break_name) .. " = false do break end") 1043 else 1044 return ("goto " .. tostring(break_name)) 1045 end 1046end 1047local function for_loop() 1048 local compile_lines = {} 1049 local pre_body_compile_lines = {} 1050 table.insert(compile_lines, consume()) 1051 local next_token = tokens[current_token_index + 1] 1052 if next_token.type == TOKEN_TYPES.SYMBOL and next_token.value == "=" then 1053 local loop_name = name() 1054 add_block_declaration(loop_name, "local", block_depth + 1) 1055 table.insert(compile_lines, get_compile_name(loop_name) .. consume()) 1056 local expressions_line = current_token.line 1057 local expressions = list(expression) 1058 local num_expressions = #expressions 1059 if num_expressions ~= 2 and num_expressions ~= 3 then 1060 throw( 1061 ("invalid numeric for, expected 2-3 expressions, got " .. tostring(num_expressions)), 1062 expressions_line 1063 ) 1064 end 1065 table.insert(compile_lines, weave(expressions)) 1066 else 1067 local names = {} 1068 for _, var in ipairs(list(variable)) do 1069 add_block_declaration(var, "local", block_depth + 1) 1070 if type(var) == "string" then 1071 table.insert(names, get_compile_name(var)) 1072 else 1073 table.insert(names, var.compile_name) 1074 table.insert( 1075 pre_body_compile_lines, 1076 "local " .. table.concat(table.map(var.declaration_names, get_compile_name), ",") 1077 ) 1078 table.insert(pre_body_compile_lines, var.compile_lines) 1079 end 1080 end 1081 table.insert(compile_lines, weave(names)) 1082 table.insert(compile_lines, expect("in", true)) 1083 table.insert(compile_lines, weave(list(expression))) 1084 end 1085 table.insert(compile_lines, "do") 1086 table.insert(compile_lines, pre_body_compile_lines) 1087 table.insert(compile_lines, surround("{", "}", loop_block)) 1088 table.insert(compile_lines, "end") 1089 return compile_lines 1090end 1091local function repeat_until() 1092 return { 1093 consume(), 1094 surround("{", "}", loop_block), 1095 expect("until", true), 1096 expression(), 1097 } 1098end 1099local function while_loop() 1100 return { 1101 consume(), 1102 expression(), 1103 "do", 1104 surround("{", "}", loop_block), 1105 "end", 1106 } 1107end 1108local function goto_jump() 1109 if lua_target == "5.1" or lua_target == "5.1+" then 1110 throw("'goto' statements only compatibly with lua targets 5.2+, jit") 1111 end 1112 consume() 1113 local label_line, label = current_token.line, name() 1114 table.insert(goto_jumps, { 1115 label = label, 1116 line = label_line, 1117 }) 1118 return "goto " .. get_compile_name(label) 1119end 1120local function goto_label() 1121 if lua_target == "5.1" or lua_target == "5.1+" then 1122 throw("'goto' statements only compatibly with lua targets 5.2+, jit") 1123 end 1124 consume() 1125 local label = name() 1126 goto_labels[label] = true 1127 return "::" .. get_compile_name(label) .. expect("::", true)
1128end 1129local function if_else() 1130 local compile_lines = {} 1131 table.insert(compile_lines, consume()) 1132 table.insert(compile_lines, expression()) 1133 table.insert(compile_lines, "then") 1134 table.insert(compile_lines, surround("{", "}", block)) 1135 while current_token.value == "elseif" do 1136 table.insert(compile_lines, consume()) 1137 table.insert(compile_lines, expression()) 1138 table.insert(compile_lines, "then") 1139 table.insert(compile_lines, surround("{", "}", block)) 1140 end 1141 if current_token.value == "else" then 1142 table.insert(compile_lines, consume()) 1143 if current_token.value == "if" then 1144 throw("unexpected tokens 'else if', did you mean 'elseif'?") 1145 end 1146 table.insert(compile_lines, surround("{", "}", block)) 1147 end 1148 table.insert(compile_lines, "end") 1149 return compile_lines 1150end 1151local function assignment_index_chain() 1152 if current_token.value == "(" then 1153 return index_chain({ 1154 base_compile_lines = { 1155 current_token.line, 1156 "(", 1157 surround("(", ")", expression), 1158 ")", 1159 }, 1160 require_chain = true, 1161 }) 1162 else 1163 local base_name_line, base_name = current_token.line, name() 1164 return index_chain({ 1165 base_compile_lines = { 1166 base_name_line, 1167 get_compile_name(base_name, block_declarations[base_name]), 1168 }, 1169 has_trivial_base = true, 1170 }) 1171 end 1172end 1173local function non_operator_assignment(ids, expressions) 1174 local assignment_ids = {} 1175 local assignment_block_compile_names = {} 1176 local assignment_block_compile_lines = {} 1177 for _, id in ipairs(ids) do 1178 if not id.needs_block_compile then 1179 table.insert(assignment_ids, id.compile_lines) 1180 else 1181 local assignment_name = new_tmp_name() 1182 table.insert(assignment_ids, assignment_name) 1183 table.insert(assignment_block_compile_names, assignment_name) 1184 table.insert(assignment_block_compile_lines, id.block_compile_lines) 1185 table.insert(assignment_block_compile_lines, id.compile_lines) 1186 table.insert(assignment_block_compile_lines, "=" .. assignment_name) 1187 end 1188 end 1189 local compile_lines = {} 1190 if #assignment_block_compile_names > 0 then 1191 table.insert(compile_lines, "local") 1192 table.insert(compile_lines, weave(assignment_block_compile_names)) 1193 end 1194 table.insert(compile_lines, weave(assignment_ids)) 1195 table.insert(compile_lines, "=") 1196 table.insert(compile_lines, weave(expressions)) 1197 table.insert(compile_lines, assignment_block_compile_lines) 1198 return compile_lines 1199end 1200local function single_operator_assignment(id, expr, op_token, op_line) 1201 local compile_lines = {} 1202 local id_compile_lines = id.compile_lines 1203 if id.needs_block_compile then 1204 table.insert(compile_lines, id.block_compile_lines) 1205 end 1206 if not id.has_trivial_base or id.chain_len > 1 then 1207 local final_base_name = new_tmp_name() 1208 table.insert(compile_lines, ("local " .. tostring(final_base_name) .. " =")) 1209 table.insert(compile_lines, id.final_base_compile_lines) 1210 id_compile_lines = { 1211 final_base_name, 1212 id.final_index_compile_lines, 1213 } 1214 end 1215 table.insert(compile_lines, id_compile_lines) 1216 table.insert(compile_lines, "=") 1217 if type(expr) == "table" then 1218 expr = { 1219 "(", 1220 expr, 1221 ")", 1222 } 1223 end 1224 table.insert(compile_lines, compile_binop(op_token, op_line, id_compile_lines, expr)) 1225 return compile_lines 1226end 1227local function operator_assignment(ids, expressions, op_token, op_line) 1228 if #ids == 1 then 1229 return single_operator_assignment(ids[1], expressions[1], op_token, op_line) 1230 end 1231 local assignment_names = {} 1232 local assignment_compile_lines = {} 1233 for _, id in ipairs(ids) do 1234 local assignment_name = new_tmp_name() 1235 table.insert(assignment_names, assignment_name) 1236 table.insert(assignment_compile_lines, single_operator_assignment(id, assignment_name, op_token, op_line)) 1237 end 1238 return { 1239 ("local " .. tostring(table.concat(assignment_names, ",")) .. " ="), 1240 weave(expressions), 1241 assignment_compile_lines, 1242 } 1243end 1244local function variable_assignment(first_id) 1245 local ids = { 1246 first_id, 1247 } 1248 while branch(",") do 1249 local id_line, id = current_token.line, assignment_index_chain() 1250 if id.is_function_call then 1251 throw("cannot assign value to function call", id_line) 1252 end 1253 table.insert(ids, id) 1254 end 1255 local op_line, op_token = current_token.line, BINOP_ASSIGNMENT_TOKENS[current_token.value] and consume() 1256 if BITOPS[op_token] and (lua_target == "5.1+" or lua_target == "5.2+") and not bitlib then 1257 throw("must specify bitlib for compiling bit operations when targeting 5.1+ or 5.2+", op_line) 1258 end 1259 expect("=", true) 1260 local expressions = list(expression) 1261 if op_token then 1262 return operator_assignment(ids, expressions, op_token, op_line) 1263 else 1264 return non_operator_assignment(ids, expressions) 1265 end 1266end 1267local function variable_declaration(scope) 1268 local assignment_names = {} 1269 local has_destructure = false 1270 local destructure_declaration_names = {} 1271 local destructure_compile_lines = {} 1272 for _, var in 1273 ipairs(list(function() 1274 return variable(scope) 1275 end)) 1276 do 1277 add_block_declaration(var, scope) 1278 if type(var) == "string" then 1279 table.insert(assignment_names, get_compile_name(var, scope)) 1280 else 1281 has_destructure = true 1282 table.insert(assignment_names, var.compile_name) 1283 table.insert(destructure_compile_lines, var.compile_lines) 1284 if scope == "local" then 1285 table.merge(destructure_declaration_names, table.map(var.declaration_names, get_compile_name)) 1286 else 1287 table.insert(destructure_declaration_names, var.compile_name) 1288 end 1289 end 1290 end 1291 if has_destructure then 1292 expect("=", true) 1293 elseif scope == "local" and current_token.value ~= "=" then 1294 return "local " .. table.concat(assignment_names, ",") 1295 elseif not branch("=") then 1296 return "" 1297 end 1298 local compile_lines = {} 1299 if has_destructure then 1300 table.insert(compile_lines, "local " .. table.concat(destructure_declaration_names, ",")) 1301 end 1302 if scope == "local" then 1303 table.insert(compile_lines, "local") 1304 end 1305 table.insert(compile_lines, table.concat(assignment_names, ",") .. "=") 1306 table.insert(compile_lines, weave(list(expression))) 1307 table.insert(compile_lines, destructure_compile_lines) 1308 return compile_lines 1309end
1310function statement() 1311 local compile_lines = {} 1312 if current_token.value == "break" then 1313 table.insert(compile_lines, loop_break()) 1314 elseif current_token.value == "continue" then 1315 table.insert(compile_lines, loop_continue()) 1316 elseif current_token.value == "goto" then 1317 table.insert(compile_lines, goto_jump()) 1318 elseif current_token.value == "::" then 1319 table.insert(compile_lines, goto_label()) 1320 elseif current_token.value == "do" then 1321 table.insert(compile_lines, do_block()) 1322 elseif current_token.value == "if" then 1323 table.insert(compile_lines, if_else()) 1324 elseif current_token.value == "for" then 1325 table.insert(compile_lines, for_loop()) 1326 elseif current_token.value == "while" then 1327 table.insert(compile_lines, while_loop()) 1328 elseif current_token.value == "repeat" then 1329 table.insert(compile_lines, repeat_until()) 1330 elseif current_token.value == "return" then 1331 table.insert(compile_lines, block_return()) 1332 elseif current_token.value == "function" then 1333 table.insert(compile_lines, function_declaration()) 1334 elseif current_token.value == "local" or current_token.value == "global" or current_token.value == "module" then 1335 local scope_line, scope = current_token.line, consume() 1336 if scope == "module" then 1337 if block_depth > 1 then 1338 throw("module declarations must appear at the top level", scope_line) 1339 end 1340 has_module_declarations = true 1341 end 1342 if current_token.value == "function" then 1343 table.insert(compile_lines, function_declaration(scope)) 1344 else 1345 table.insert(compile_lines, variable_declaration(scope)) 1346 end 1347 else 1348 local chain = assignment_index_chain() 1349 if not chain.is_function_call then 1350 table.insert(compile_lines, variable_assignment(chain)) 1351 elseif chain.needs_block_compile then 1352 table.insert(compile_lines, "do") 1353 table.insert(compile_lines, chain.block_compile_lines) 1354 table.insert(compile_lines, chain.compile_lines) 1355 table.insert(compile_lines, "end") 1356 else 1357 table.insert(compile_lines, chain.compile_lines) 1358 end 1359 end 1360 if current_token.value == ";" then 1361 table.insert(compile_lines, consume()) 1362 elseif current_token.value == "(" then 1363 table.insert(compile_lines, ";") 1364 end 1365 return compile_lines 1366end 1367local function module_block() 1368 local compile_lines = {} 1369 block_declarations = {} 1370 block_declaration_stack[block_depth] = block_declarations 1371 if current_token.type == TOKEN_TYPES.SHEBANG then 1372 table.insert(compile_lines, consume()) 1373 end 1374 while current_token.type ~= TOKEN_TYPES.EOF do 1375 table.insert(compile_lines, statement()) 1376 end 1377 if has_module_declarations then 1378 if module_return_line ~= nil then 1379 throw("cannot use 'return' w/ 'module' declarations", module_return_line) 1380 end 1381 table.insert(compile_lines, 1, "local _MODULE = {}") 1382 table.insert(compile_lines, "return _MODULE") 1383 end 1384 return compile_lines 1385end 1386local function collect_compile_lines(lines, state) 1387 for _, line in ipairs(lines) do 1388 if type(line) == "number" then 1389 state.source_line = line 1390 elseif type(line) == "string" then 1391 table.insert(state.compile_lines, line) 1392 table.insert(state.source_map, state.source_line) 1393 else 1394 collect_compile_lines(line, state) 1395 end 1396 end 1397end 1398return function(source, options) 1399 if options == nil then 1400 options = {} 1401 end 1402 tokens = tokenize(source, options.alias) 1403 current_token_index = 1 1404 current_token = tokens[current_token_index] 1405 block_depth = 1 1406 tmp_name_counter = 1 1407 break_name = nil 1408 has_continue = false 1409 has_module_declarations = false 1410 is_module_return_block = true 1411 module_return_line = nil 1412 is_varargs_block = true 1413 block_declarations = {} 1414 block_declaration_stack = {} 1415 goto_jumps = {} 1416 goto_labels = {} 1417 alias = options.alias or get_source_alias(source) 1418 lua_target = options.lua_target or config.lua_target 1419 bitlib = options.bitlib 1420 or config.bitlib 1421 or (lua_target == "5.1" and "bit") 1422 or (lua_target == "jit" and "bit") 1423 or (lua_target == "5.2" and "bit32") 1424 local source_map = {} 1425 local compile_lines = {} 1426 collect_compile_lines(module_block(), { 1427 compile_lines = compile_lines, 1428 source_map = source_map, 1429 source_line = current_token.line, 1430 }) 1431 for _, __ERDE_TMP_1927__ in ipairs(goto_jumps) do 1432 local label, line 1433 label = __ERDE_TMP_1927__["label"] 1434 line = __ERDE_TMP_1927__["line"] 1435 if goto_labels[label] == nil then 1436 throw(("failed to find goto label '" .. tostring(label) .. "'"), line) 1437 end 1438 end 1439 table.insert( 1440 compile_lines, 1441 ("-- Compiled with Erde " .. tostring(VERSION) .. " w/ Lua target " .. tostring(lua_target)) 1442 ) 1443 table.insert(compile_lines, COMPILED_FOOTER_COMMENT) 1444 return table.concat(compile_lines, "\n"), source_map 1445end 1446-- Compiled with Erde 0.6.0-1 1447-- __ERDE_COMPILED__ 1448end 1449end 1450 1451do 1452local _ENV = _ENV 1453package.preload[ "erde.config" ] = function( ... ) local arg = _G.arg;
1454local _MODULE = {} 1455local lua_target = "5.1+" 1456_MODULE.lua_target = lua_target 1457local is_cli_runtime = false 1458_MODULE.is_cli_runtime = is_cli_runtime 1459local bitlib = nil 1460_MODULE.bitlib = bitlib 1461local disable_source_maps = false 1462_MODULE.disable_source_maps = disable_source_maps 1463return _MODULE 1464-- Compiled with Erde 0.6.0-1 1465-- __ERDE_COMPILED__ 1466end 1467end 1468 1469do 1470local _ENV = _ENV 1471package.preload[ "erde.constants" ] = function( ... ) local arg = _G.arg; 1472local _MODULE = {} 1473local VERSION = "1.0.0-1" 1474_MODULE.VERSION = VERSION 1475local PATH_SEPARATOR = package.config:sub(1, 1) 1476_MODULE.PATH_SEPARATOR = PATH_SEPARATOR 1477local COMPILED_FOOTER_COMMENT = "-- __ERDE_COMPILED__" 1478_MODULE.COMPILED_FOOTER_COMMENT = COMPILED_FOOTER_COMMENT 1479local TOKEN_TYPES = { 1480 EOF = 0, 1481 SHEBANG = 1, 1482 SYMBOL = 2, 1483 WORD = 3, 1484 NUMBER = 4, 1485 SINGLE_QUOTE_STRING = 5, 1486 DOUBLE_QUOTE_STRING = 6, 1487 STRING_CONTENT = 7, 1488 INTERPOLATION = 8, 1489} 1490_MODULE.TOKEN_TYPES = TOKEN_TYPES 1491local VALID_LUA_TARGETS = { 1492 "jit", 1493 "5.1", 1494 "5.1+", 1495 "5.2", 1496 "5.2+", 1497 "5.3", 1498 "5.3+", 1499 "5.4", 1500 "5.4+", 1501} 1502_MODULE.VALID_LUA_TARGETS = VALID_LUA_TARGETS 1503for i, target in ipairs(VALID_LUA_TARGETS) do 1504 VALID_LUA_TARGETS[target] = true 1505end 1506local KEYWORDS = { 1507 ["break"] = true, 1508 ["continue"] = true, 1509 ["do"] = true, 1510 ["else"] = true, 1511 ["elseif"] = true, 1512 ["for"] = true, 1513 ["function"] = true, 1514 ["global"] = true, 1515 ["if"] = true, 1516 ["in"] = true, 1517 ["local"] = true, 1518 ["module"] = true, 1519 ["repeat"] = true, 1520 ["return"] = true, 1521 ["until"] = true, 1522 ["while"] = true, 1523} 1524_MODULE.KEYWORDS = KEYWORDS 1525local LUA_KEYWORDS = { 1526 ["not"] = true, 1527 ["and"] = true, 1528 ["or"] = true, 1529 ["end"] = true, 1530 ["then"] = true, 1531} 1532_MODULE.LUA_KEYWORDS = LUA_KEYWORDS 1533local TERMINALS = { 1534 ["true"] = true, 1535 ["false"] = true, 1536 ["nil"] = true, 1537 ["..."] = true, 1538} 1539_MODULE.TERMINALS = TERMINALS 1540local LEFT_ASSOCIATIVE = -1 1541_MODULE.LEFT_ASSOCIATIVE = LEFT_ASSOCIATIVE 1542local RIGHT_ASSOCIATIVE = 1 1543_MODULE.RIGHT_ASSOCIATIVE = RIGHT_ASSOCIATIVE 1544local UNOPS = { 1545 ["-"] = { 1546 prec = 13, 1547 }, 1548 ["#"] = { 1549 prec = 13, 1550 }, 1551 ["!"] = { 1552 prec = 13, 1553 }, 1554 ["~"] = { 1555 prec = 13, 1556 }, 1557} 1558_MODULE.UNOPS = UNOPS 1559for token, op in pairs(UNOPS) do 1560 op.token = token 1561end 1562local BITOPS = { 1563 ["|"] = { 1564 prec = 6, 1565 assoc = LEFT_ASSOCIATIVE, 1566 }, 1567 ["~"] = { 1568 prec = 7, 1569 assoc = LEFT_ASSOCIATIVE, 1570 }, 1571 ["&"] = { 1572 prec = 8, 1573 assoc = LEFT_ASSOCIATIVE, 1574 }, 1575 ["<<"] = { 1576 prec = 9, 1577 assoc = LEFT_ASSOCIATIVE, 1578 }, 1579 [">>"] = { 1580 prec = 9, 1581 assoc = LEFT_ASSOCIATIVE, 1582 }, 1583} 1584_MODULE.BITOPS = BITOPS 1585local BITLIB_METHODS = { 1586 ["|"] = "bor", 1587 ["~"] = "bxor", 1588 ["&"] = "band", 1589 ["<<"] = "lshift", 1590 [">>"] = "rshift", 1591} 1592_MODULE.BITLIB_METHODS = BITLIB_METHODS 1593local BINOPS = { 1594 ["||"] = { 1595 prec = 3, 1596 assoc = LEFT_ASSOCIATIVE, 1597 }, 1598 ["&&"] = { 1599 prec = 4, 1600 assoc = LEFT_ASSOCIATIVE, 1601 }, 1602 ["=="] = { 1603 prec = 5, 1604 assoc = LEFT_ASSOCIATIVE, 1605 }, 1606 ["!="] = { 1607 prec = 5, 1608 assoc = LEFT_ASSOCIATIVE, 1609 }, 1610 ["<="] = { 1611 prec = 5, 1612 assoc = LEFT_ASSOCIATIVE, 1613 }, 1614 [">="] = { 1615 prec = 5, 1616 assoc = LEFT_ASSOCIATIVE, 1617 }, 1618 ["<"] = { 1619 prec = 5, 1620 assoc = LEFT_ASSOCIATIVE, 1621 }, 1622 [">"] = { 1623 prec = 5, 1624 assoc = LEFT_ASSOCIATIVE, 1625 }, 1626 [".."] = { 1627 prec = 10, 1628 assoc = LEFT_ASSOCIATIVE, 1629 }, 1630 ["+"] = { 1631 prec = 11, 1632 assoc = LEFT_ASSOCIATIVE, 1633 }, 1634 ["-"] = { 1635 prec = 11, 1636 assoc = LEFT_ASSOCIATIVE, 1637 }, 1638 ["*"] = { 1639 prec = 12, 1640 assoc = LEFT_ASSOCIATIVE, 1641 }, 1642 ["/"] = { 1643 prec = 12, 1644 assoc = LEFT_ASSOCIATIVE, 1645 }, 1646 ["//"] = { 1647 prec = 12, 1648 assoc = LEFT_ASSOCIATIVE, 1649 }, 1650 ["%"] = { 1651 prec = 12, 1652 assoc = LEFT_ASSOCIATIVE, 1653 }, 1654 ["^"] = { 1655 prec = 14, 1656 assoc = RIGHT_ASSOCIATIVE, 1657 }, 1658} 1659_MODULE.BINOPS = BINOPS 1660for token, op in pairs(BITOPS) do 1661 BINOPS[token] = op 1662end 1663for token, op in pairs(BINOPS) do 1664 op.token = token 1665end 1666local BINOP_ASSIGNMENT_TOKENS = { 1667 ["||"] = true, 1668 ["&&"] = true, 1669 [".."] = true, 1670 ["+"] = true, 1671 ["-"] = true, 1672 ["*"] = true, 1673 ["/"] = true, 1674 ["//"] = true, 1675 ["%"] = true, 1676 ["^"] = true, 1677 ["|"] = true, 1678 ["~"] = true, 1679 ["&"] = true, 1680 ["<<"] = true, 1681 [">>"] = true, 1682} 1683_MODULE.BINOP_ASSIGNMENT_TOKENS = BINOP_ASSIGNMENT_TOKENS 1684local SURROUND_ENDS = { 1685 ["("] = ")", 1686 ["["] = "]", 1687 ["{"] = "}", 1688} 1689_MODULE.SURROUND_ENDS = SURROUND_ENDS 1690local SYMBOLS = { 1691 ["->"] = true, 1692 ["=>"] = true, 1693 ["..."] = true, 1694 ["::"] = true, 1695} 1696_MODULE.SYMBOLS = SYMBOLS 1697for token, op in pairs(BINOPS) do 1698 if #token > 1 then 1699 SYMBOLS[token] = true 1700 end 1701end 1702local STANDARD_ESCAPE_CHARS = { 1703 a = true, 1704 b = true, 1705 f = true, 1706 n = true, 1707 r = true, 1708 t = true, 1709 v = true, 1710 ["\\"] = true, 1711 ['"'] = true, 1712 ["'"] = true, 1713 ["\n"] = true, 1714} 1715_MODULE.STANDARD_ESCAPE_CHARS = STANDARD_ESCAPE_CHARS 1716local DIGIT = {} 1717_MODULE.DIGIT = DIGIT 1718local HEX = {} 1719_MODULE.HEX = HEX 1720local WORD_HEAD = { 1721 ["_"] = true, 1722} 1723_MODULE.WORD_HEAD = WORD_HEAD 1724local WORD_BODY = { 1725 ["_"] = true, 1726} 1727_MODULE.WORD_BODY = WORD_BODY 1728for byte = string.byte("0"), string.byte("9") do 1729 local char = string.char(byte) 1730 DIGIT[char] = true 1731 HEX[char] = true 1732 WORD_BODY[char] = true 1733end 1734for byte = string.byte("A"), string.byte("F") do 1735 local char = string.char(byte) 1736 HEX[char] = true 1737 WORD_HEAD[char] = true 1738 WORD_BODY[char] = true 1739end 1740for byte = string.byte("G"), string.byte("Z") do 1741 local char = string.char(byte) 1742 WORD_HEAD[char] = true 1743 WORD_BODY[char] = true 1744end 1745for byte = string.byte("a"), string.byte("f") do 1746 local char = string.char(byte) 1747 HEX[char] = true 1748 WORD_HEAD[char] = true 1749 WORD_BODY[char] = true 1750end 1751for byte = string.byte("g"), string.byte("z") do 1752 local char = string.char(byte) 1753 WORD_HEAD[char] = true 1754 WORD_BODY[char] = true 1755end 1756return _MODULE 1757-- Compiled with Erde 0.6.0-1 1758-- __ERDE_COMPILED__ 1759end 1760end 1761 1762do 1763local _ENV = _ENV 1764package.preload[ "erde.lib" ] = function( ... ) local arg = _G.arg;
1765local _MODULE = {} 1766local compile = require("erde.compile") 1767local config = require("erde.config") 1768local PATH_SEPARATOR, VALID_LUA_TARGETS 1769do 1770 local __ERDE_TMP_6__ 1771 __ERDE_TMP_6__ = require("erde.constants") 1772 PATH_SEPARATOR = __ERDE_TMP_6__["PATH_SEPARATOR"] 1773 VALID_LUA_TARGETS = __ERDE_TMP_6__["VALID_LUA_TARGETS"] 1774end 1775local io, string 1776do 1777 local __ERDE_TMP_9__ 1778 __ERDE_TMP_9__ = require("erde.stdlib") 1779 io = __ERDE_TMP_9__["io"] 1780 string = __ERDE_TMP_9__["string"] 1781end 1782local echo, get_source_summary 1783do 1784 local __ERDE_TMP_12__ 1785 __ERDE_TMP_12__ = require("erde.utils") 1786 echo = __ERDE_TMP_12__["echo"] 1787 get_source_summary = __ERDE_TMP_12__["get_source_summary"] 1788end 1789local loadlua = loadstring or load 1790local unpack = table.unpack or unpack 1791local native_traceback = debug.traceback 1792local searchers = package.loaders or package.searchers 1793local erde_source_cache = {} 1794local erde_source_id_counter = 1 1795local function rewrite(message) 1796 if type(message) ~= "string" then 1797 return message 1798 end 1799 for erde_source_id, chunkname, compiled_line in message:gmatch('%[string "erde::(%d+)::([^\n]+)"]:(%d+)') do 1800 local cache = erde_source_cache[tonumber(erde_source_id)] or {} 1801 local source_map = cache.source_map or {} 1802 local source_line = source_map[tonumber(compiled_line)] or ("(compiled:" .. tostring(compiled_line) .. ")") 1803 local match = string.escape( 1804 ( 1805 '[string "erde::' 1806 .. tostring(erde_source_id) 1807 .. "::" 1808 .. tostring(chunkname) 1809 .. '"]:' 1810 .. tostring(compiled_line) 1811 ) 1812 ) 1813 message = cache.has_alias and message:gsub(match, chunkname .. ":" .. source_line) 1814 or message:gsub(match, ('[string "' .. tostring(chunkname) .. '"]:' .. tostring(source_line))) 1815 end 1816 message = message:gsub("__ERDE_SUBSTITUTE_([a-zA-Z]+)__", "%1") 1817 return message 1818end 1819_MODULE.rewrite = rewrite 1820local function traceback(arg1, arg2, arg3) 1821 local stacktrace, level 1822 if type(arg1) == "thread" then 1823 level = arg3 or 1 1824 stacktrace = native_traceback(arg1, arg2, level + 1) 1825 else 1826 level = arg2 or 1 1827 stacktrace = native_traceback(arg1, level + 1) 1828 end 1829 if type(stacktrace) ~= "string" then 1830 return stacktrace 1831 end 1832 if level > -1 and config.is_cli_runtime then 1833 local stack = string.split(stacktrace, "\n") 1834 local stacklen = #stack 1835 for i = 1, 4 do 1836 table.remove(stack, stacklen - i) 1837 end 1838 stacktrace = table.concat(stack, "\n") 1839 end 1840 stacktrace = stacktrace:gsub( 1841 table.concat({ 1842 "[^\n]*\n", 1843 "[^\n]*__erde_internal_load_source__[^\n]*\n", 1844 "[^\n]*\n", 1845 }), 1846 "" 1847 ) 1848 return rewrite(stacktrace) 1849end 1850_MODULE.traceback = traceback 1851local function __erde_internal_load_source__(source, options) 1852 if options == nil then 1853 options = {} 1854 end 1855 local chunkname = table.concat({ 1856 "erde", 1857 erde_source_id_counter, 1858 options.alias or get_source_summary(source), 1859 }, "::") 1860 local compiled, source_map = compile(source, { 1861 alias = options.alias, 1862 lua_target = options.lua_target, 1863 bitlib = options.bitlib, 1864 }) 1865 compiled = compiled:gsub("^#![^\n]+", "") 1866 local loader, load_error = loadlua(compiled, chunkname) 1867 if load_error ~= nil then 1868 error(table.concat({ 1869 "Failed to load compiled code:", 1870 tostring(load_error), 1871 "", 1872 "This is an internal error that should never happen.", 1873 "Please report this at: https://github.com/erde-lang/erde/issues", 1874 "", 1875 "erde", 1876 "----", 1877 source, 1878 "", 1879 "lua", 1880 "---", 1881 compiled, 1882 }, "\n")) 1883 end 1884 erde_source_cache[erde_source_id_counter] = { 1885 has_alias = options.alias ~= nil, 1886 } 1887 if not config.disable_source_maps and not options.disable_source_maps then 1888 erde_source_cache[erde_source_id_counter].source_map = source_map 1889 end 1890 erde_source_id_counter = erde_source_id_counter + 1 1891 return loader() 1892end 1893_MODULE.__erde_internal_load_source__ = __erde_internal_load_source__ 1894local function run(source, options) 1895 return echo(__erde_internal_load_source__(source, options)) 1896end 1897_MODULE.run = run 1898local function erde_searcher(module_name) 1899 local module_path = module_name:gsub("%.", PATH_SEPARATOR) 1900 for path in package.path:gmatch("[^;]+") do 1901 local fullpath = path:gsub("%.lua$", ".erde"):gsub("?", module_path) 1902 if io.exists(fullpath) then 1903 return function() 1904 local source = io.readfile(fullpath) 1905 local result = { 1906 __erde_internal_load_source__(source, { 1907 alias = fullpath, 1908 }), 1909 } 1910 return unpack(result) 1911 end 1912 end 1913 end 1914end 1915local function load(arg1, arg2) 1916 local new_lua_target, options = nil, {} 1917 if type(arg1) == "string" then 1918 new_lua_target = arg1 1919 end 1920 if type(arg1) == "table" then 1921 options = arg1 1922 elseif type(arg2) == "table" then 1923 options = arg2 1924 end 1925 config.bitlib = options.bitlib 1926 config.disable_source_maps = options.disable_source_maps 1927 debug.traceback = options.keep_traceback == true and native_traceback or traceback 1928 if new_lua_target ~= nil then 1929 if VALID_LUA_TARGETS[new_lua_target] then 1930 config.lua_target = new_lua_target 1931 else 1932 error(table.concat({ 1933 ("Invalid Lua target: " .. tostring(new_lua_target)), 1934 ("Must be one of: " .. tostring(table.concat(VALID_LUA_TARGETS, ", "))), 1935 }, "\n")) 1936 end 1937 elseif jit ~= nil then 1938 config.lua_target = "jit" 1939 else 1940 new_lua_target = _VERSION:match("Lua (%d%.%d)") 1941 if VALID_LUA_TARGETS[new_lua_target] then 1942 config.lua_target = new_lua_target 1943 else 1944 error(("Unsupported Lua version: " .. tostring(_VERSION))) 1945 end 1946 end 1947 for _, searcher in ipairs(searchers) do 1948 if searcher == erde_searcher then 1949 return 1950 end 1951 end 1952 table.insert(searchers, 2, erde_searcher) 1953end 1954_MODULE.load = load 1955local function unload() 1956 debug.traceback = native_traceback 1957 for i, searcher in ipairs(searchers) do 1958 if searcher == erde_searcher then 1959 table.remove(searchers, i) 1960 return 1961 end 1962 end 1963end 1964_MODULE.unload = unload 1965return _MODULE 1966-- Compiled with Erde 0.6.0-1 1967-- __ERDE_COMPILED__ 1968end 1969end 1970 1971do 1972local _ENV = _ENV 1973package.preload[ "erde.stdlib" ] = function( ... ) local arg = _G.arg;
1974local _MODULE = {} 1975local _native_coroutine = coroutine 1976local coroutine = {} 1977_MODULE.coroutine = coroutine 1978local _native_debug = debug 1979local debug = {} 1980_MODULE.debug = debug 1981local _native_io = io 1982local io = {} 1983_MODULE.io = io 1984local _native_math = math 1985local math = {} 1986_MODULE.math = math 1987local _native_os = os 1988local os = {} 1989_MODULE.os = os 1990local _native_package = package 1991local package = {} 1992_MODULE.package = package 1993local _native_string = string 1994local string = {} 1995_MODULE.string = string 1996local _native_table = table 1997local table = {} 1998_MODULE.table = table 1999local function load() 2000 for key, value in pairs(_MODULE) do 2001 local value_type = type(value) 2002 if value_type == "function" then 2003 if key ~= "load" and key ~= "unload" then 2004 _G[key] = value 2005 end 2006 elseif value_type == "table" then 2007 local library = _G[key] 2008 if type(library) == "table" then 2009 for subkey, subvalue in pairs(value) do 2010 library[subkey] = subvalue 2011 end 2012 end 2013 end 2014 end 2015end 2016_MODULE.load = load 2017local function unload() 2018 for key, value in pairs(_MODULE) do 2019 local value_type = type(value) 2020 if value_type == "function" then 2021 if _G[key] == value then 2022 _G[key] = nil 2023 end 2024 elseif value_type == "table" then 2025 local library = _G[key] 2026 if type(library) == "table" then 2027 for subkey, subvalue in pairs(value) do 2028 if library[subkey] == subvalue then 2029 library[subkey] = nil 2030 end 2031 end 2032 end 2033 end 2034 end 2035end 2036_MODULE.unload = unload 2037local function _kpairs_iter(a, i) 2038 local key, value = i, nil 2039 repeat 2040 key, value = next(a, key) 2041 until type(key) ~= "number" 2042 return key, value 2043end 2044local function kpairs(t) 2045 return _kpairs_iter, t, nil 2046end 2047_MODULE.kpairs = kpairs 2048function io.exists(path) 2049 local file = io.open(path, "r") 2050 if file == nil then 2051 return false 2052 end 2053 file:close() 2054 return true 2055end 2056function io.readfile(path) 2057 local file = assert(io.open(path, "r")) 2058 local content = assert(file:read("*a")) 2059 file:close() 2060 return content 2061end 2062function io.writefile(path, content) 2063 local file = assert(io.open(path, "w")) 2064 assert(file:write(content)) 2065 file:close() 2066end 2067function math.clamp(x, min, max) 2068 return math.min(math.max(x, min), max) 2069end 2070function math.round(x) 2071 if x < 0 then 2072 return math.ceil(x - 0.5) 2073 else 2074 return math.floor(x + 0.5) 2075 end 2076end 2077function math.sign(x) 2078 if x < 0 then 2079 return -1 2080 elseif x > 0 then 2081 return 1 2082 else 2083 return 0 2084 end 2085end 2086function os.capture(cmd) 2087 local file = assert(io.popen(cmd, "r")) 2088 local stdout = assert(file:read("*a")) 2089 file:close() 2090 return stdout 2091end 2092function package.cinsert(...) 2093 local templates = package.split(package.cpath) 2094 table.insert(templates, ...) 2095 package.cpath = package.concat(templates) 2096end 2097function package.concat(templates, i, j) 2098 local template_separator = string.split(package.config, "\n")[2] 2099 return table.concat(templates, template_separator, i, j) 2100end 2101function package.cremove(position) 2102 local templates = package.split(package.cpath) 2103 local removed = table.remove(templates, position) 2104 package.cpath = package.concat(templates) 2105 return removed 2106end 2107function package.insert(...) 2108 local templates = package.split(package.path) 2109 table.insert(templates, ...) 2110 package.path = package.concat(templates) 2111end 2112function package.remove(position) 2113 local templates = package.split(package.path) 2114 local removed = table.remove(templates, position) 2115 package.path = package.concat(templates) 2116 return removed 2117end 2118function package.split(path) 2119 local template_separator = string.split(package.config, "\n")[2] 2120 return string.split(path, template_separator) 2121end 2122local function _string_chars_iter(a, i) 2123 i = i + 1 2124 local char = a:sub(i, i) 2125 if char ~= "" then 2126 return i, char 2127 end 2128end 2129function string.chars(s) 2130 return _string_chars_iter, s, 0 2131end 2132function string.escape(s) 2133 local escaped = s:gsub("[().%%+%-*?[^$]", "%%%1") 2134 return escaped 2135end 2136function string.lpad(s, length, padding) 2137 if padding == nil then 2138 padding = " " 2139 end 2140 return padding:rep(math.ceil((length - #s) / #padding)) .. s 2141end 2142function string.ltrim(s, pattern) 2143 if pattern == nil then 2144 pattern = "%s+" 2145 end 2146 local trimmed = s:gsub(("^" .. tostring(pattern)), "") 2147 return trimmed 2148end 2149function string.pad(s, length, padding) 2150 if padding == nil then 2151 padding = " " 2152 end 2153 local num_pads = math.ceil(((length - #s) / #padding) / 2) 2154 return padding:rep(num_pads) .. s .. padding:rep(num_pads) 2155end 2156function string.rpad(s, length, padding) 2157 if padding == nil then 2158 padding = " " 2159 end 2160 return s .. padding:rep(math.ceil((length - #s) / #padding)) 2161end 2162function string.rtrim(s, pattern) 2163 if pattern == nil then 2164 pattern = "%s+" 2165 end 2166 local trimmed = s:gsub((tostring(pattern) .. "$"), "") 2167 return trimmed 2168end 2169function string.split(s, separator) 2170 if separator == nil then 2171 separator = "%s+" 2172 end 2173 local result = {} 2174 local i, j = s:find(separator) 2175 while i ~= nil do 2176 table.insert(result, s:sub(1, i - 1)) 2177 s = s:sub(j + 1) or "" 2178 i, j = s:find(separator) 2179 end 2180 table.insert(result, s) 2181 return result 2182end 2183function string.trim(s, pattern) 2184 if pattern == nil then 2185 pattern = "%s+" 2186 end 2187 return string.ltrim(string.rtrim(s, pattern), pattern) 2188end 2189if _VERSION == "Lua 5.1" then 2190 table.pack = function(...) 2191 return { 2192 n = select("#", ...), 2193 ..., 2194 } 2195 end 2196 table.unpack = unpack 2197end 2198function table.clear(t, callback) 2199 if type(callback) == "function" then 2200 for key, value in kpairs(t) do 2201 if callback(value, key) then 2202 t[key] = nil 2203 end 2204 end
2205 for i = #t, 1, -1 do 2206 if callback(t[i], i) then 2207 table.remove(t, i) 2208 end 2209 end 2210 else 2211 for key, value in kpairs(t) do 2212 if value == callback then 2213 t[key] = nil 2214 end 2215 end 2216 for i = #t, 1, -1 do 2217 if t[i] == callback then 2218 table.remove(t, i) 2219 end 2220 end 2221 end 2222end 2223function table.collect(...) 2224 local result = {} 2225 for key, value in ... do 2226 if value == nil then 2227 table.insert(result, key) 2228 else 2229 result[key] = value 2230 end 2231 end 2232 return result 2233end 2234function table.deepcopy(t) 2235 local result = {} 2236 for key, value in pairs(t) do 2237 if type(value) == "table" then 2238 result[key] = table.deepcopy(value) 2239 else 2240 result[key] = value 2241 end 2242 end 2243 return result 2244end 2245function table.empty(t) 2246 return next(t) == nil 2247end 2248function table.filter(t, callback) 2249 local result = {} 2250 for key, value in pairs(t) do 2251 if callback(value, key) then 2252 if type(key) == "number" then 2253 table.insert(result, value) 2254 else 2255 result[key] = value 2256 end 2257 end 2258 end 2259 return result 2260end 2261function table.find(t, callback) 2262 if type(callback) == "function" then 2263 for key, value in pairs(t) do 2264 if callback(value, key) then 2265 return value, key 2266 end 2267 end 2268 else 2269 for key, value in pairs(t) do 2270 if value == callback then 2271 return value, key 2272 end 2273 end 2274 end 2275end 2276function table.has(t, callback) 2277 local _, key = table.find(t, callback) 2278 return key ~= nil 2279end 2280function table.keys(t) 2281 local result = {} 2282 for key, value in pairs(t) do 2283 table.insert(result, key) 2284 end 2285 return result 2286end 2287function table.map(t, callback) 2288 local result = {} 2289 for key, value in pairs(t) do 2290 local newValue, newKey = callback(value, key) 2291 if newKey ~= nil then 2292 result[newKey] = newValue 2293 elseif type(key) == "number" then 2294 table.insert(result, newValue) 2295 else 2296 result[key] = newValue 2297 end 2298 end 2299 return result 2300end 2301function table.merge(t, ...) 2302 for _, _t in pairs({ 2303 ..., 2304 }) do 2305 for key, value in pairs(_t) do 2306 if type(key) == "number" then 2307 table.insert(t, value) 2308 else 2309 t[key] = value 2310 end 2311 end 2312 end 2313end 2314function table.reduce(t, initial, callback) 2315 local result = initial 2316 for key, value in pairs(t) do 2317 result = callback(result, value, key) 2318 end 2319 return result 2320end 2321function table.reverse(t) 2322 local len = #t 2323 for i = 1, math.floor(len / 2) do 2324 t[i], t[len - i + 1] = t[len - i + 1], t[i] 2325 end 2326end 2327function table.shallowcopy(t) 2328 local result = {} 2329 for key, value in pairs(t) do 2330 result[key] = value 2331 end 2332 return result 2333end 2334function table.slice(t, i, j) 2335 if i == nil then 2336 i = 1 2337 end 2338 if j == nil then 2339 j = #t 2340 end 2341 local result, len = {}, #t 2342 if i < 0 then 2343 i = i + len + 1 2344 end 2345 if j < 0 then 2346 j = j + len + 1 2347 end 2348 for i = math.max(i, 0), math.min(j, len) do 2349 table.insert(result, t[i]) 2350 end 2351 return result 2352end 2353function table.values(t) 2354 local result = {} 2355 for key, value in pairs(t) do 2356 table.insert(result, value) 2357 end 2358 return result 2359end 2360setmetatable(coroutine, { 2361 __index = _native_coroutine, 2362 __newindex = _native_coroutine, 2363}) 2364setmetatable(debug, { 2365 __index = _native_debug, 2366 __newindex = _native_debug, 2367}) 2368setmetatable(io, { 2369 __index = _native_io, 2370 __newindex = _native_io, 2371}) 2372setmetatable(math, { 2373 __index = _native_math, 2374 __newindex = _native_math, 2375}) 2376setmetatable(os, { 2377 __index = _native_os, 2378 __newindex = _native_os, 2379}) 2380setmetatable(package, { 2381 __index = _native_package, 2382 __newindex = _native_package, 2383}) 2384setmetatable(string, { 2385 __index = _native_string, 2386 __newindex = _native_string, 2387}) 2388setmetatable(table, { 2389 __index = _native_table, 2390 __newindex = _native_table, 2391}) 2392return _MODULE 2393-- Compiled with Erde 0.6.0-1 2394-- __ERDE_COMPILED__ 2395end 2396end 2397 2398do 2399local _ENV = _ENV 2400package.preload[ "erde.tokenize" ] = function( ... ) local arg = _G.arg; 2401local config = require("erde.config") 2402local DIGIT, HEX, STANDARD_ESCAPE_CHARS, SYMBOLS, TOKEN_TYPES, WORD_BODY, WORD_HEAD 2403do 2404 local __ERDE_TMP_4__ 2405 __ERDE_TMP_4__ = require("erde.constants") 2406 DIGIT = __ERDE_TMP_4__["DIGIT"] 2407 HEX = __ERDE_TMP_4__["HEX"] 2408 STANDARD_ESCAPE_CHARS = __ERDE_TMP_4__["STANDARD_ESCAPE_CHARS"] 2409 SYMBOLS = __ERDE_TMP_4__["SYMBOLS"] 2410 TOKEN_TYPES = __ERDE_TMP_4__["TOKEN_TYPES"] 2411 WORD_BODY = __ERDE_TMP_4__["WORD_BODY"] 2412 WORD_HEAD = __ERDE_TMP_4__["WORD_HEAD"] 2413end 2414local get_source_alias 2415do 2416 local __ERDE_TMP_7__ 2417 __ERDE_TMP_7__ = require("erde.utils") 2418 get_source_alias = __ERDE_TMP_7__["get_source_alias"] 2419end 2420local tokenize_token 2421local tokens = {} 2422local text = "" 2423local current_char = "" 2424local current_char_index = 1 2425local current_line = 1 2426local source_name = "" 2427local function peek(n) 2428 return text:sub(current_char_index, current_char_index + n - 1) 2429end 2430local function look_ahead(n) 2431 return text:sub(current_char_index + n, current_char_index + n)
2432end 2433local function throw(message, line) 2434 if line == nil then 2435 line = current_line 2436 end 2437 error((tostring(source_name) .. ":" .. tostring(line) .. ": " .. tostring(message)), 0) 2438end 2439local function consume(n) 2440 if n == nil then 2441 n = 1 2442 end 2443 local consumed = n == 1 and current_char or peek(n) 2444 current_char_index = current_char_index + n 2445 current_char = text:sub(current_char_index, current_char_index) 2446 return consumed 2447end 2448local function newline() 2449 current_line = current_line + 1 2450 return consume() 2451end 2452local function tokenize_binary() 2453 consume(2) 2454 if current_char ~= "0" and current_char ~= "1" then 2455 throw("malformed binary") 2456 end 2457 local value = 0 2458 repeat 2459 value = 2 * value + tonumber(consume()) 2460 until current_char ~= "0" and current_char ~= "1" 2461 table.insert(tokens, { 2462 type = TOKEN_TYPES.NUMBER, 2463 line = current_line, 2464 value = tostring(value), 2465 }) 2466end 2467local function tokenize_decimal() 2468 local value = "" 2469 while DIGIT[current_char] do 2470 value = value .. consume() 2471 end 2472 if current_char == "." and DIGIT[look_ahead(1)] then 2473 value = value .. consume(2) 2474 while DIGIT[current_char] do 2475 value = value .. consume() 2476 end 2477 end 2478 if current_char == "e" or current_char == "E" then 2479 value = value .. consume() 2480 if current_char == "+" or current_char == "-" then 2481 value = value .. consume() 2482 end 2483 if not DIGIT[current_char] then 2484 throw("missing exponent value") 2485 end 2486 while DIGIT[current_char] do 2487 value = value .. consume() 2488 end 2489 end 2490 table.insert(tokens, { 2491 type = TOKEN_TYPES.NUMBER, 2492 line = current_line, 2493 value = value, 2494 }) 2495end 2496local function tokenize_hex() 2497 consume(2) 2498 if not HEX[current_char] and not (current_char == "." and HEX[look_ahead(1)]) then 2499 throw("malformed hex") 2500 end 2501 local value = 0 2502 while HEX[current_char] do 2503 value = 16 * value + tonumber(consume(), 16) 2504 end 2505 if current_char == "." and HEX[look_ahead(1)] then 2506 consume() 2507 local counter = 1 2508 repeat 2509 value = value + tonumber(consume(), 16) / (16 ^ counter) 2510 counter = counter + 1 2511 until not HEX[current_char] 2512 end 2513 if current_char == "p" or current_char == "P" then 2514 consume() 2515 local exponent, sign = 0, 1 2516 if current_char == "+" or current_char == "-" then 2517 sign = sign * tonumber(consume() .. "1") 2518 end 2519 if not DIGIT[current_char] then 2520 throw("missing exponent value") 2521 end 2522 repeat 2523 exponent = 10 * exponent + tonumber(consume()) 2524 until not DIGIT[current_char] 2525 value = value * 2 ^ (sign * exponent) 2526 end 2527 table.insert(tokens, { 2528 type = TOKEN_TYPES.NUMBER, 2529 line = current_line, 2530 value = tostring(value), 2531 }) 2532end 2533local function escape_sequence() 2534 if STANDARD_ESCAPE_CHARS[current_char] then 2535 return consume() 2536 elseif DIGIT[current_char] then 2537 return consume() 2538 elseif current_char == "z" then 2539 if config.lua_target == "5.1" or config.lua_target == "5.1+" then 2540 throw("escape sequence \\z not compatible w/ lua targets 5.1, 5.1+") 2541 end 2542 return consume() 2543 elseif current_char == "x" then 2544 if config.lua_target == "5.1" or config.lua_target == "5.1+" then 2545 throw("escape sequence \\xXX not compatible w/ lua targets 5.1, 5.1+") 2546 end 2547 if not HEX[look_ahead(1)] or not HEX[look_ahead(2)] then 2548 throw("escape sequence \\xXX must use exactly 2 hex characters") 2549 end 2550 return consume(3) 2551 elseif current_char == "u" then 2552 if 2553 config.lua_target == "5.1" 2554 or config.lua_target == "5.1+" 2555 or config.lua_target == "5.2" 2556 or config.lua_target == "5.2+" 2557 then 2558 throw("escape sequence \\u{XXX} not compatible w/ lua targets 5.1, 5.1+, 5.2, 5.2+") 2559 end 2560 local sequence = consume() 2561 if current_char ~= "{" then 2562 throw("missing { in escape sequence \\u{XXX}") 2563 end 2564 sequence = sequence .. consume() 2565 if not HEX[current_char] then 2566 throw("missing hex in escape sequence \\u{XXX}") 2567 end 2568 while HEX[current_char] do 2569 sequence = sequence .. consume() 2570 end 2571 if current_char ~= "}" then 2572 throw("missing } in escape sequence \\u{XXX}") 2573 end 2574 return sequence .. consume() 2575 else 2576 throw(("invalid escape sequence \\" .. tostring(current_char))) 2577 end 2578end 2579local function tokenize_interpolation() 2580 table.insert(tokens, { 2581 type = TOKEN_TYPES.INTERPOLATION, 2582 line = current_line, 2583 value = consume(), 2584 }) 2585 local interpolation_line = current_line 2586 local brace_depth = 0 2587 while current_char ~= "}" or brace_depth > 0 do 2588 if current_char == "{" then 2589 brace_depth = brace_depth + 1 2590 table.insert(tokens, { 2591 type = TOKEN_TYPES.SYMBOL, 2592 line = current_line, 2593 value = consume(), 2594 }) 2595 elseif current_char == "}" then 2596 brace_depth = brace_depth - 1 2597 table.insert(tokens, { 2598 type = TOKEN_TYPES.SYMBOL, 2599 line = current_line, 2600 value = consume(), 2601 }) 2602 elseif current_char == "" then 2603 throw("unterminated interpolation", interpolation_line) 2604 else 2605 tokenize_token() 2606 end 2607 end 2608 table.insert(tokens, { 2609 type = TOKEN_TYPES.INTERPOLATION, 2610 line = current_line, 2611 value = consume(), 2612 }) 2613end 2614local function tokenize_single_quote_string() 2615 table.insert(tokens, {
2616 type = TOKEN_TYPES.SINGLE_QUOTE_STRING, 2617 line = current_line, 2618 value = consume(), 2619 }) 2620 local content = "" 2621 while current_char ~= "'" do 2622 if current_char == "" or current_char == "\n" then 2623 throw("unterminated string") 2624 elseif current_char == "\\" then 2625 content = content .. consume() .. escape_sequence() 2626 else 2627 content = content .. consume() 2628 end 2629 end 2630 if content ~= "" then 2631 table.insert(tokens, { 2632 type = TOKEN_TYPES.STRING_CONTENT, 2633 line = current_line, 2634 value = content, 2635 }) 2636 end 2637 table.insert(tokens, { 2638 type = TOKEN_TYPES.SINGLE_QUOTE_STRING, 2639 line = current_line, 2640 value = consume(), 2641 }) 2642end 2643local function tokenize_double_quote_string() 2644 table.insert(tokens, { 2645 type = TOKEN_TYPES.DOUBLE_QUOTE_STRING, 2646 line = current_line, 2647 value = consume(), 2648 }) 2649 local content, content_line = "", current_line 2650 while current_char ~= '"' do 2651 if current_char == "" or current_char == "\n" then 2652 throw("unterminated string") 2653 elseif current_char == "\\" then 2654 consume() 2655 if current_char == "{" or current_char == "}" then 2656 content = content .. consume() 2657 else 2658 content = content .. "\\" .. escape_sequence() 2659 end 2660 elseif current_char == "{" then 2661 if content ~= "" then 2662 table.insert(tokens, { 2663 type = TOKEN_TYPES.STRING_CONTENT, 2664 line = content_line, 2665 value = content, 2666 }) 2667 content, content_line = "", current_line 2668 end 2669 tokenize_interpolation() 2670 else 2671 content = content .. consume() 2672 end 2673 end 2674 if content ~= "" then 2675 table.insert(tokens, { 2676 type = TOKEN_TYPES.STRING_CONTENT, 2677 line = content_line, 2678 value = content, 2679 }) 2680 end 2681 table.insert(tokens, { 2682 type = TOKEN_TYPES.DOUBLE_QUOTE_STRING, 2683 line = current_line, 2684 value = consume(), 2685 }) 2686end 2687local function tokenize_block_string() 2688 consume() 2689 local equals = "" 2690 while current_char == "=" do 2691 equals = equals .. consume() 2692 end 2693 if current_char ~= "[" then 2694 throw("unterminated block string opening", current_line) 2695 end 2696 consume() 2697 table.insert(tokens, { 2698 type = TOKEN_TYPES.BLOCK_STRING, 2699 line = current_line, 2700 value = "[" .. equals .. "[", 2701 equals = equals, 2702 }) 2703 local close_quote = "]" .. equals .. "]" 2704 local close_quote_len = #close_quote 2705 local block_string_line = current_line 2706 local content, content_line = "", current_line 2707 while current_char ~= "]" or peek(close_quote_len) ~= close_quote do 2708 if current_char == "" then 2709 throw("unterminated block string", block_string_line) 2710 elseif current_char == "\n" then 2711 content = content .. newline() 2712 elseif current_char == "\\" then 2713 consume() 2714 if current_char == "{" or current_char == "}" then 2715 content = content .. consume() 2716 else 2717 content = content .. "\\" 2718 end 2719 elseif current_char == "{" then 2720 if content ~= "" then 2721 table.insert(tokens, { 2722 type = TOKEN_TYPES.STRING_CONTENT, 2723 line = content_line, 2724 value = content, 2725 }) 2726 content, content_line = "", current_line 2727 end 2728 tokenize_interpolation() 2729 else 2730 content = content .. consume() 2731 end 2732 end 2733 if content ~= "" then 2734 table.insert(tokens, { 2735 type = TOKEN_TYPES.STRING_CONTENT, 2736 line = content_line, 2737 value = content, 2738 }) 2739 end 2740 table.insert(tokens, { 2741 type = TOKEN_TYPES.BLOCK_STRING, 2742 line = current_line, 2743 value = consume(close_quote_len), 2744 }) 2745end 2746local function tokenize_word() 2747 local word = consume() 2748 while WORD_BODY[current_char] do 2749 word = word .. consume() 2750 end 2751 table.insert(tokens, { 2752 type = TOKEN_TYPES.WORD, 2753 line = current_line, 2754 value = word, 2755 }) 2756end 2757local function tokenize_comment() 2758 consume(2) 2759 local is_block_comment, equals = false, "" 2760 if current_char == "[" then 2761 consume() 2762 while current_char == "=" do 2763 equals = equals .. consume() 2764 end 2765 if current_char == "[" then 2766 consume() 2767 is_block_comment = true 2768 end 2769 end 2770 if not is_block_comment then 2771 while current_char ~= "" and current_char ~= "\n" do 2772 consume() 2773 end 2774 else 2775 local close_quote = "]" .. equals .. "]" 2776 local close_quote_len = #close_quote 2777 local comment_line = current_line 2778 while current_char ~= "]" or peek(close_quote_len) ~= close_quote do 2779 if current_char == "" then 2780 throw("unterminated comment", comment_line) 2781 elseif current_char == "\n" then 2782 newline() 2783 else 2784 consume() 2785 end 2786 end 2787 consume(close_quote_len) 2788 end 2789end 2790function tokenize_token() 2791 if current_char == "\n" then 2792 newline() 2793 elseif current_char == " " or current_char == "\t" then 2794 consume() 2795 elseif WORD_HEAD[current_char] then 2796 tokenize_word() 2797 elseif current_char == "'" then 2798 tokenize_single_quote_string() 2799 elseif current_char == '"' then 2800 tokenize_double_quote_string() 2801 else 2802 local peek_two = peek(2) 2803 if peek_two == "--" then 2804 tokenize_comment() 2805 elseif peek_two == "0x" or peek_two == "0X" then 2806 tokenize_hex() 2807 elseif peek_two == "0b" or peek_two == "0B" then 2808 tokenize_binary() 2809 elseif DIGIT[current_char] or (current_char == "." and DIGIT[look_ahead(1)]) then 2810 tokenize_decimal() 2811 elseif peek_two == "[[" or peek_two == "[=" then 2812 tokenize_block_string() 2813 elseif SYMBOLS[peek(3)] then 2814 table.insert(tokens, { 2815 type = TOKEN_TYPES.SYMBOL, 2816 line = current_line, 2817 value = consume(3), 2818 }) 2819 elseif SYMBOLS[peek_two] then 2820 table.insert(tokens, { 2821 type = TOKEN_TYPES.SYMBOL, 2822 line = current_line, 2823 value = consume(2), 2824 }) 2825 else 2826 table.insert(tokens, { 2827 type = TOKEN_TYPES.SYMBOL, 2828 line = current_line, 2829 value = consume(1), 2830 }) 2831 end 2832 end 2833end 2834return function(new_text, new_source_name) 2835 tokens = {} 2836 text = new_text 2837 current_char = text:sub(1, 1) 2838 current_char_index = 1 2839 current_line = 1 2840 source_name = new_source_name or get_source_alias(text) 2841 if peek(2) == "#!" then 2842 local shebang = consume(2) 2843 while current_char ~= "" and current_char ~= "\n" do 2844 shebang = shebang .. consume() 2845 end 2846 table.insert(tokens, { 2847 type = TOKEN_TYPES.SHEBANG, 2848 line = current_line, 2849 value = shebang, 2850 }) 2851 end 2852 while current_char ~= "" do 2853 tokenize_token() 2854 end 2855 table.insert(tokens, { 2856 type = TOKEN_TYPES.EOF, 2857 line = current_line, 2858 value = nil, 2859 }) 2860 return tokens 2861end 2862-- Compiled with Erde 0.6.0-1 2863-- __ERDE_COMPILED__ 2864end 2865end 2866 2867do 2868local _ENV = _ENV 2869package.preload[ "erde.utils" ] = function( ... ) local arg = _G.arg;
2870local _MODULE = {} 2871local PATH_SEPARATOR 2872do 2873 local __ERDE_TMP_2__ 2874 __ERDE_TMP_2__ = require("erde.constants") 2875 PATH_SEPARATOR = __ERDE_TMP_2__["PATH_SEPARATOR"] 2876end 2877local io, string 2878do 2879 local __ERDE_TMP_5__ 2880 __ERDE_TMP_5__ = require("erde.stdlib") 2881 io = __ERDE_TMP_5__["io"] 2882 string = __ERDE_TMP_5__["string"] 2883end 2884local function echo(...) 2885 return ... 2886end 2887_MODULE.echo = echo 2888local function join_paths(...) 2889 local joined = table.concat({ 2890 ..., 2891 }, PATH_SEPARATOR):gsub(PATH_SEPARATOR .. "+", PATH_SEPARATOR) 2892 return joined 2893end 2894_MODULE.join_paths = join_paths 2895local function get_source_summary(source) 2896 local summary = string.trim(source):sub(1, 5) 2897 if #source > 5 then 2898 summary = summary .. "..." 2899 end 2900 return summary 2901end 2902_MODULE.get_source_summary = get_source_summary 2903local function get_source_alias(source) 2904 return ('[string "' .. tostring(get_source_summary(source)) .. '"]') 2905end 2906_MODULE.get_source_alias = get_source_alias 2907return _MODULE 2908-- Compiled with Erde 0.6.0-1 2909-- __ERDE_COMPILED__ 2910end 2911end 2912
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.