/source/Parser.ooc
Unknown | 2234 lines | 1936 code | 298 blank | 0 comment | 0 complexity | a8a9aa5862e8ac43d17a84cb129ccde3 MD5 | raw file
1 2import math 3import structs/ArrayList 4 5import Lexer 6import Types 7import Opcodes 8 9ExpKind: enum { 10 VVOID, /* no value */ 11 VNIL, 12 VTRUE, 13 VFALSE, 14 VK, /* info = index of constant in `k' */ 15 VKNUM, /* nval = numerical value */ 16 VNONRELOC, /* info = result register */ 17 VLOCAL, /* info = local register */ 18 VUPVAL, /* info = index of upvalue in 'upvalues' */ 19 VINDEXED, /* t = table register/upvalue; idx = index R/K */ 20 VJMP, /* info = instruction pc */ 21 VRELOCABLE, /* info = instruction pc */ 22 VCALL, /* info = instruction pc */ 23 VVARARG /* info = instruction pc */ 24 25 vkisvar: inline func -> Bool { 26 return (ExpKind VLOCAL <= this) && (this <= ExpKind VINDEXED) 27 } 28 29 vkisinreg: inline func -> Bool { 30 return (this == ExpKind VNONRELOC) || (this == ExpKind VLOCAL) 31 } 32 33 hasmultret: inline func -> Bool { 34 return (this == ExpKind VCALL) || (this == ExpKind VVARARG) 35 } 36} 37 38ExpDesc: cover { 39 k: ExpKind 40 ind_idx: Int16 /* index (R/K) */ 41 ind_t: UInt8 /* table (register or upvalue) */ 42 ind_vt: ExpKind /* whether 't' is register (VLOCAL) or upvalue (VUPVAL) */ 43 info: Int /* for generic use */ 44 nval: Double /* for VKNUM lua_Number */ 45 t: Int /* patch list of `exit when true' */ 46 f: Int /* patch list of `exit when false' */ 47 48 isnumeral: inline func -> Bool { 49 return k == ExpKind VKNUM && t == NO_JUMP && f == NO_JUMP 50 } 51 52 hasjumps: inline func -> Bool { 53 return t != f 54 } 55} 56 57init_exp: inline func(e: ExpDesc@, k: ExpKind, info: Int) { 58 e k = k 59 e info = info 60 e ind_idx = 0 61 e ind_t = 0 62 e ind_vt = ExpKind VVOID 63 e f = NO_JUMP 64 e t = NO_JUMP 65} 66 67 68 69/* state needed to generate code for a given function */ 70FuncState: final class { 71 f: LuaProto /* current function header */ 72 h: Table /* table to find (and reuse) elements in `k' */ 73 prev: FuncState /* enclosing function */ 74 ls: Parser /* lexical state */ 75 bl: BlockCnt* /* chain of current blocks */ 76 lasttarget: Int /* `pc' of last `jump target' */ 77 jpc: Int /* list of pending jumps to `pc' */ 78 freereg: Int /* first free register */ 79 firstlocal: Int /* index of first local var of this function */ 80 nactvar: Short /* number of active local variables */ 81 82 init: func(=ls, =prev) { 83 f = LuaProto new() 84 f source = ls source 85 f maxstacksize = 2 /* registers 0/1 are always valid */ 86 h = Table new(0, 0) 87 bl = null 88 lasttarget = 0 89 jpc = NO_JUMP 90 freereg = 0 91 firstlocal = ls actvar getSize() 92 nactvar = 0 93 } 94 95 96 finalize: func -> FuncState { 97 luaK_ret(0, 0) /* final return */ 98 removevars(0) 99 version(debug) { 100 assert(! bl) 101 } 102 return prev 103 } 104 105 106 getlocvar: func(i: Int) -> LocVar* { 107 idx := ls actvar get(firstlocal + i) 108 version(debug) { 109 assert(idx < f locvars getSize()) 110 } 111 return f locvars data as LocVar* + idx 112 } 113 114 enterblock: func(_bl: BlockCnt@, _isbreakable: Bool) { 115 _bl breaklist = NO_JUMP 116 _bl isbreakable = _isbreakable 117 _bl nactvar = nactvar 118 _bl upval = false 119 _bl previous = bl 120 bl = _bl& 121 version(debug) { 122 assert(freereg == nactvar) 123 } 124 } 125 126 leaveblock: func { 127 _bl := bl 128 bl = _bl@ previous 129 removevars(_bl@ nactvar) 130 if (_bl@ upval) 131 luaK_codeABC(OpCode OP_CLOSE, _bl@ nactvar, 0, 0) 132 version(debug) { 133 /* a block either controls scope or breaks (never both) */ 134 assert(!_bl@ isbreakable || !_bl@ upval) 135 assert(_bl@ nactvar == nactvar) 136 } 137 freereg = nactvar /* free registers */ 138 luaK_patchtohere(_bl@ breaklist) 139 } 140 141 removevars: func(tolevel: Int) { 142 pc := f code getSize() 143 actvar := ls actvar 144 while (nactvar > tolevel) { 145 nactvar -= 1 146 pvar := getlocvar(nactvar) 147 pvar@ endpc = pc 148 actvar removeAt(actvar lastIndex()) 149 } 150 } 151 152 153 searchupvalue: func(name: String) -> Int { 154 up := f upvalues 155 for (i in 0 .. up getSize()) 156 if (up get(i) name equals?(name)) 157 return i 158 return -1 /* not found */ 159 } 160 161 162 newupvalue: func(name: String, v: ExpDesc@) -> Int { 163 up := f upvalues 164 idx := up getSize() 165 up add(UpvalDesc new(name, v k == ExpKind VLOCAL, v info)) 166 return idx 167 } 168 169 searchvar: func(n: String) -> Int { 170 i := nactvar - 1 171 while (i >= 0) { 172 pvar := getlocvar(i) 173 if (pvar@ varname equals?(n)) 174 return i 175 i -= 1 176 } 177 return -1; /* not found */ 178 } 179 180/* 181 Mark block where variable at given level was defined 182 (to emit OP_CLOSE later). 183*/ 184 markupval: func(level: Int) { 185 _bl := bl 186 while (_bl) { 187 if (!(_bl@ nactvar > level)) 188 break 189 _bl = _bl@ previous 190 } 191 if (_bl) 192 _bl@ upval = true 193 } 194 195 196/* 197 Find variable with given name 'n'. If it is an upvalue, add this 198 upvalue into all intermediate functions. 199*/ 200 singlevaraux: func(n: String, var: ExpDesc@, base: Int) -> ExpKind { 201 v := searchvar(n) /* look up locals at current level */ 202 if (v >= 0) { /* found? */ 203 init_exp(var&, ExpKind VLOCAL, v) /* variable is local */ 204 if (!base) 205 markupval(v) /* local will be used as an upval */ 206 return ExpKind VLOCAL 207 } 208 else { /* not found as local at current level; try upvalues */ 209 idx := searchupvalue(n) /* try existing upvalues */ 210 if (idx < 0) { /* not found? */ 211 if (! prev || /* no more levels */ 212 prev singlevaraux(n, var&, 0) == ExpKind VVOID) /* try upper levels */ 213 return ExpKind VVOID; /* not found; is a global */ 214 /* else was LOCAL or UPVAL */ 215 idx = newupvalue(n, var&) /* will be a new upvalue */ 216 } 217 init_exp(var&, ExpKind VUPVAL, idx) 218 return ExpKind VUPVAL 219 } 220 } 221 222 223 luaK_nil: func(_from, n: Int) { 224 pc := f code getSize() 225 if (pc > lasttarget) { /* no jumps to current position? */ 226 previous := f code data as Instruction* + pc - 1 227 if (previous@ getOpcode() == OpCode OP_LOADNIL) { 228 pfrom := previous@ getarg_A() 229 pto := previous@ getarg_B() 230 if (pfrom <= _from && _from <= pto + 1) { /* can connect both? */ 231 if (_from + n - 1 > pto) 232 previous@ = previous@ setarg_B(_from + n - 1) 233 return 234 } 235 } 236 } 237 luaK_codeABC(OpCode OP_LOADNIL, _from, _from + n - 1, 0) /* else no optimization */ 238 } 239 240 241 luaK_jump: func -> Int { 242 save := jpc /* save list of jumps to here */ 243 jpc = NO_JUMP 244 j := luaK_codeABx(OpCode OP_JMP, 0, NO_JUMP + MAXARG_sBx) 245 luaK_concat(j&, save) /* keep them on hold */ 246 return j 247 } 248 249 250 luaK_ret: func(first, nret: Int) { 251 luaK_codeABC(OpCode OP_RETURN, first, nret+1, 0) 252 } 253 254 255 _condjump: func(op: OpCode, A, B, C: Int) -> Int { 256 luaK_codeABC(op, A, B, C) 257 return luaK_jump() 258 } 259 260 261 _fixjump: func(pc, dest: Int) { 262 jmp := f code data as Instruction* + pc 263 offset := dest - (pc + 1) 264 version(debug) { 265 assert(dest != NO_JUMP) 266 } 267 if (offset abs() > MAXARG_sBx) 268 ls syntaxError("control structure too long") 269 jmp@ = jmp@ setarg_sBx(offset) 270 } 271 272 273/* 274** returns current `pc' and marks it as a jump target (to avoid wrong 275** optimizations with consecutive instructions not in the same basic block). 276*/ 277 luaK_getlabel: func -> Int { 278 lasttarget = f code getSize() 279 return lasttarget 280 } 281 282 283 _getjump: func(pc: Int) -> Int { 284 offset := f code get(pc) getarg_sBx() 285 if (offset == NO_JUMP) /* point to itself represents end of list */ 286 return NO_JUMP /* end of list */ 287 else 288 return pc + 1 + offset /* turn offset into absolute position */ 289 } 290 291 292 _getjumpcontrol: func(pc: Int) -> Instruction* { 293 pi := f code data as Instruction* + pc 294 if (pc >= 1 && (pi-1)@ getOpcode() testTMode()) 295 return pi - 1 296 else 297 return pi 298 } 299 300 301/* 302** check whether list has any jump that do not produce a value 303** (or produce an inverted value) 304*/ 305 _need_value: func(list: Int) -> Bool { 306 while (list != NO_JUMP) { 307 i := _getjumpcontrol(list)@ 308 if (i getOpcode() != OpCode OP_TESTSET) 309 return true 310 list = _getjump(list) 311 } 312 return false /* not found */ 313 } 314 315 316 _patchtestreg: func(node, reg: Int) -> Int { 317 i := _getjumpcontrol(node) 318 if (i@ getOpcode() != OpCode OP_TESTSET) 319 return 0; /* cannot patch other instructions */ 320 if (reg != NO_REG && reg != i@ getarg_B()) 321 i@ = i@ setarg_A(reg) 322 else /* no register to put value or register already has the value */ 323 i@ = Instruction createABC(OpCode OP_TEST, i@ getarg_B(), 0, i@ getarg_C()) 324 325 return 1 326 } 327 328 329 _removevalues: func(list: Int) { 330 while (list != NO_JUMP) { 331 _patchtestreg(list, NO_REG) 332 list = _getjump(list) 333 } 334 } 335 336 337 _patchlistaux: func(list, vtarget, reg, dtarget: Int) { 338 while (list != NO_JUMP) { 339 next := _getjump(list) 340 if (_patchtestreg(list, reg)) 341 _fixjump(list, vtarget) 342 else 343 _fixjump(list, dtarget) /* jump to default target */ 344 list = next 345 } 346 } 347 348 349 _dischargejpc: func { 350 pc := f code getSize() 351 _patchlistaux(jpc, pc, NO_REG, pc) 352 jpc = NO_JUMP 353 } 354 355 356 luaK_patchlist: func(list, target: Int) { 357 pc := f code getSize() 358 if (target == pc) 359 luaK_patchtohere(list) 360 else { 361 version(debug) { 362 assert(target < pc) 363 } 364 _patchlistaux(list, target, NO_REG, target) 365 } 366 } 367 368 369 luaK_patchtohere: func(list: Int) { 370 luaK_getlabel() 371 luaK_concat(jpc&, list) 372 } 373 374 375 luaK_concat: func(l1: Int*, l2: Int) { 376 if (l2 == NO_JUMP) 377 return 378 else if (l1@ == NO_JUMP) 379 l1@ = l2 380 else { 381 list := l1@ 382 next := _getjump(list) 383 while (next != NO_JUMP) { /* find last element */ 384 list = next 385 next = _getjump(next) 386 } 387 _fixjump(list, l2) 388 } 389 } 390 391 392 luaK_code: func(i: Instruction) -> Int{ 393 _dischargejpc() /* `pc' will change */ 394 pc := f code getSize() 395 /* put new instruction in code array */ 396 f code add(i) 397 /* save corresponding line information */ 398 f lineinfo add(ls lastline) 399 return pc 400 } 401 402 403 luaK_codeABC: func(o: OpCode, a, b, c: Int) -> Int { 404 version(debug) { 405 assert(o getOpMode() == OpMode iABC) 406 assert(o getBMode() != OpArgMask OpArgN || b == 0) 407 assert(o getCMode() != OpArgMask OpArgN || c == 0) 408 assert(a <= MAXARG_A) 409 assert(b <= MAXARG_B) 410 assert(c <= MAXARG_C) 411 } 412 return luaK_code(Instruction createABC(o, a, b, c)) 413 } 414 415 416 luaK_codeABx: func(o: OpCode, a: Int, bc: UInt) -> Int { 417 version(debug) { 418 assert(o getOpMode() == OpMode iABx || o getOpMode() == OpMode iAsBx) 419 assert(o getCMode() == OpArgMask OpArgN) 420 assert(a <= MAXARG_A) 421 assert(bc <= MAXARG_Bx) 422 } 423 return luaK_code(Instruction createABx(o, a, bc)) 424 } 425 426 427 luaK_codeABxX: func(o: OpCode, reg, k: Int) -> Int { 428 if (k < MAXARG_Bx) 429 return luaK_codeABx(o, reg, k + 1) 430 else { 431 p := luaK_codeABx(o, reg, 0) 432 version(debug) { 433 assert(k <= MAXARG_Ax) 434 } 435 luaK_code(Instruction createAx(OpCode OP_EXTRAARG, k)) 436 return p 437 } 438 } 439 440 441 luaK_checkstack: func(n: Int) { 442 newstack := freereg + n 443 if (newstack > f maxstacksize) { 444 if (newstack >= MAXSTACK) 445 ls syntaxError("function or expression too complex") 446 f maxstacksize = newstack 447 } 448 } 449 450 451 luaK_reserveregs: func(n: Int) { 452 luaK_checkstack(n) 453 freereg += n 454 } 455 456 457 _freereg: func(reg: Int) { 458 if (!(reg & BITRK) && reg >= nactvar) { 459 freereg -= 1 460 version(debug) { 461 assert(reg == freereg) 462 } 463 } 464 } 465 466 467 _freeexp: func(e: ExpDesc@) { 468 if (e k == ExpKind VNONRELOC) 469 _freereg(e info) 470 } 471 472 473 _addk: func(key, v: LuaAny) -> Int { 474 n := h get(key) 475 if (n) { 476 k := n as LuaNumber v as Int 477 if (f k get(k) eq(v)) 478 return k 479 /* else may be a collision (e.g., between 0.0 and "\0\0\0\0\0\0\0\0"); 480 go through and create a new entry for this value */ 481 } 482 /* constant not found; create a new entry */ 483 nk := f k getSize() 484 h set(key, LuaNumber new(nk)) 485 f k add(v) 486 return nk 487 } 488 489 490 luaK_stringK: func(s: String) -> Int { 491 o := LuaString new(s) 492 return _addk(o, o) 493 } 494 495 496 luaK_numberK: func(r: Double) -> Int { 497 o := LuaNumber new(r) 498 if (r == 0 || !(r == r)) { /* handle -0 and NaN */ 499 /* use raw representation as key to avoid numeric problems */ 500 k := LuaString new(r toString()) 501 return _addk(k, o) 502 } 503 else 504 return _addk(o, o) /* regular case */ 505 } 506 507 508 _boolK: func(b: Bool) -> Int { 509 o := LuaBoolean new(b) 510 return _addk(o, o) 511 } 512 513 514 _nilK: func -> Int { 515 o := LuaNil new() 516 return _addk(o, o) 517 } 518 519 520 luaK_setreturns: func(e: ExpDesc@, nresults: Int) { 521 pi := f code data as Instruction* + e info 522 if (e k == ExpKind VCALL) { /* expression is an open function call? */ 523 pi@ = pi@ setarg_C(nresults + 1) 524 } 525 else if (e k == ExpKind VVARARG) { 526 pi@ = pi@ setarg_B(nresults + 1) 527 pi@ = pi@ setarg_A(freereg) 528 luaK_reserveregs(1) 529 } 530 } 531 532 533 luaK_setoneret: func(e: ExpDesc@) { 534 pi := f code data as Instruction* + e info 535 if (e k == ExpKind VCALL) { /* expression is an open function call? */ 536 e k = ExpKind VNONRELOC 537 e info = pi@ getarg_A() 538 } 539 else if (e k == ExpKind VVARARG) { 540 pi@ = pi@ setarg_B(2) 541 e k = ExpKind VRELOCABLE /* can relocate its simple result */ 542 } 543 } 544 545 546 luaK_dischargevars: func(e: ExpDesc@) { 547 k := e k 548 match { 549 case k == ExpKind VLOCAL => 550 e k = ExpKind VNONRELOC 551 case k == ExpKind VUPVAL => 552 e info = luaK_codeABC(OpCode OP_GETUPVAL, 0, e info, 0) 553 e k = ExpKind VRELOCABLE 554 case k == ExpKind VINDEXED => 555 op := OpCode OP_GETTABUP /* assume 't' is in an upvalue */ 556 _freereg(e ind_idx) 557 if (e ind_vt == ExpKind VLOCAL) { /* 't' is in a register? */ 558 _freereg(e ind_t) 559 op = OpCode OP_GETTABLE 560 } 561 e info = luaK_codeABC(op, 0, e ind_t, e ind_idx) 562 e k = ExpKind VRELOCABLE 563 case k == ExpKind VVARARG || 564 k == ExpKind VCALL => 565 luaK_setoneret(e&) 566 } 567 } 568 569 570 _code_label: func(A, b, jump: Int) -> Int { 571 luaK_getlabel() /* those instructions may be jump targets */ 572 return luaK_codeABC(OpCode OP_LOADBOOL, A, b, jump) 573 } 574 575 576 _discharge2reg: func(e: ExpDesc@, reg: Int) { 577 luaK_dischargevars(e&) 578 match (e k) { 579 case ExpKind VNIL => 580 luaK_nil(reg, 1) 581 case ExpKind VFALSE => 582 luaK_codeABC(OpCode OP_LOADBOOL, reg, 0, 0) 583 case ExpKind VTRUE => 584 luaK_codeABC(OpCode OP_LOADBOOL, reg, 1, 0) 585 case ExpKind VK => 586 luaK_codeABxX(OpCode OP_LOADK, reg, e info) 587 case ExpKind VKNUM => 588 luaK_codeABxX(OpCode OP_LOADK, reg, luaK_numberK(e nval)) 589 case ExpKind VRELOCABLE => 590 pc := f code data as Instruction* + e info 591 pc@ = pc@ setarg_A(reg) 592 case ExpKind VNONRELOC => 593 if (reg != e info) 594 luaK_codeABC(OpCode OP_MOVE, reg, e info, 0) 595 case => 596 version(debug) { 597 assert(e k == ExpKind VVOID || e k == ExpKind VJMP) 598 } 599 return /* nothing to do... */ 600 } 601 e info = reg 602 e k = ExpKind VNONRELOC 603 } 604 605 606 _discharge2anyreg: func(e: ExpDesc@) { 607 if (e k != ExpKind VNONRELOC) { 608 luaK_reserveregs(1) 609 _discharge2reg(e&, freereg-1) 610 } 611 } 612 613 614 _exp2reg: func(e: ExpDesc@, reg: Int) { 615 _discharge2reg(e&, reg) 616 if (e k == ExpKind VJMP) 617 luaK_concat(e t&, e info) /* put this jump in `t' list */ 618 if (e hasjumps()) { 619 p_f := NO_JUMP /* position of an eventual LOAD false */ 620 p_t := NO_JUMP /* position of an eventual LOAD true */ 621 if (_need_value(e t) || _need_value(e f)) { 622 fj := (e k == ExpKind VJMP) ? NO_JUMP : luaK_jump() 623 p_f = _code_label(reg, 0, 1) 624 p_t = _code_label(reg, 1, 0) 625 luaK_patchtohere(fj) 626 } 627 _final := luaK_getlabel() /* position after whole expression */ 628 _patchlistaux(e f, _final, reg, p_f) 629 _patchlistaux(e t, _final, reg, p_t) 630 } 631 e f = NO_JUMP 632 e t = NO_JUMP 633 e info = reg 634 e k = ExpKind VNONRELOC 635 } 636 637 638 luaK_exp2nextreg: func(e: ExpDesc@) { 639 luaK_dischargevars(e&) 640 _freeexp(e&) 641 luaK_reserveregs(1) 642 _exp2reg(e&, freereg - 1) 643 } 644 645 646 luaK_exp2anyreg: func(e: ExpDesc@) -> Int { 647 luaK_dischargevars(e&) 648 if (e k == ExpKind VNONRELOC) { 649 if (! e hasjumps()) 650 return e info /* exp is already in a register */ 651 if (e info >= nactvar) { /* reg. is not a local? */ 652 _exp2reg(e&, e info) /* put value on it */ 653 return e info 654 } 655 } 656 luaK_exp2nextreg(e&) /* default */ 657 return e info 658 } 659 660 661 luaK_exp2anyregup: func(e: ExpDesc@) { 662 if (e k != ExpKind VUPVAL || e hasjumps()) 663 luaK_exp2anyreg(e&) 664 } 665 666 667 luaK_exp2val: func(e: ExpDesc@) { 668 if (e hasjumps()) 669 luaK_exp2anyreg(e&) 670 else 671 luaK_dischargevars(e&) 672 } 673 674 675 luaK_exp2RK: func(e: ExpDesc@) -> Int { 676 luaK_exp2val(e&) 677 k := e k 678 nk := f k getSize() 679 match { 680 case k == ExpKind VTRUE || 681 k == ExpKind VFALSE || 682 k == ExpKind VNIL => 683 if (nk <= MAXINDEXRK) { /* constant fits in RK operand? */ 684 e info = (e k == ExpKind VNIL) ? _nilK() : _boolK(e k == ExpKind VTRUE) 685 e k = ExpKind VK 686 return e info | BITRK 687 } 688 case k == ExpKind VKNUM => 689 e info = luaK_numberK(e nval) 690 e k = ExpKind VK 691 if (e info <= MAXINDEXRK) /* constant fits in argC? */ 692 return e info | BITRK 693 case k == ExpKind VK => 694 if (e info <= MAXINDEXRK) /* constant fits in argC? */ 695 return e info | BITRK 696 } 697 /* not a constant in the right range: put it in a register */ 698 return luaK_exp2anyreg(e&) 699 } 700 701 702 luaK_storevar: func(var, ex: ExpDesc@) { 703 match (var k) { 704 case ExpKind VLOCAL => 705 _freeexp(ex&) 706 _exp2reg(ex&, var info) 707 case ExpKind VUPVAL => 708 e := luaK_exp2anyreg(ex&) 709 luaK_codeABC(OpCode OP_SETUPVAL, e, var info, 0) 710 case ExpKind VINDEXED => 711 op := (var ind_vt == ExpKind VLOCAL) ? OpCode OP_SETTABLE : OpCode OP_SETTABUP 712 e := luaK_exp2RK(ex&) 713 luaK_codeABC(op, var ind_t, var ind_idx, e) 714 case => 715 version(debug) { 716 assert(false) /* invalid var kind to store */ 717 } 718 } 719 _freeexp(ex&) 720 } 721 722 723 luaK_self: func(e, key: ExpDesc@) { 724 luaK_exp2anyreg(e&) 725 _freeexp(e&) 726 _func := freereg 727 luaK_codeABC(OpCode OP_SELF, _func, e info, luaK_exp2RK(key&)) 728 _freeexp(key&) 729 luaK_reserveregs(2) 730 e info = _func 731 e k = ExpKind VNONRELOC 732 } 733 734 735 _invertjump: func(e: ExpDesc@) { 736 pc := _getjumpcontrol(e info) 737 version(debug) { 738 op := pc@ getOpcode() 739 assert(op testTMode()) 740 assert(op != OpCode OP_TESTSET) 741 assert(op != OpCode OP_TEST) 742 } 743 pc@ = pc@ setarg_A(pc@ getarg_A() == 0 ? 1 : 0) 744 } 745 746 747 _jumponcond: func(e: ExpDesc@, cond: Int) -> Int { 748 if (e k == ExpKind VRELOCABLE) { 749 ie := f code get(e info) 750 if (ie getOpcode() == OpCode OP_NOT) { 751 f code removeAt(f code lastIndex()) /* remove previous OP_NOT */ 752 return _condjump(OpCode OP_TEST, ie getarg_B(), 0, cond == 0 ? 1 : 0) 753 } 754 /* else go through */ 755 } 756 _discharge2anyreg(e&) 757 _freeexp(e&) 758 return _condjump(OpCode OP_TESTSET, NO_REG, e info, cond) 759 } 760 761 762 luaK_goiftrue: func(e: ExpDesc@) { 763 pc: Int /* pc of last jump */ 764 luaK_dischargevars(e&) 765 k := e k 766 match { 767 case k == ExpKind VK || 768 k == ExpKind VKNUM || 769 k == ExpKind VTRUE => 770 pc = NO_JUMP /* always true; do nothing */ 771 case k == ExpKind VJMP => 772 _invertjump(e&) 773 pc = e info 774 case k == ExpKind VFALSE => 775 if (! e hasjumps()) 776 pc = luaK_jump() /* always jump */ 777 else 778 pc = _jumponcond(e&, 0) 779 case => 780 pc = _jumponcond(e&, 0) 781 } 782 luaK_concat(e f&, pc) /* insert last jump in `f' list */ 783 luaK_patchtohere(e t) 784 e t = NO_JUMP 785 } 786 787 788 luaK_goiffalse: func(e: ExpDesc@) { 789 pc: Int /* pc of last jump */ 790 luaK_dischargevars(e&) 791 k := e k 792 match { 793 case k == ExpKind VNIL || 794 k == ExpKind VFALSE => 795 pc = NO_JUMP /* always false; do nothing */ 796 case k == ExpKind VJMP => 797 pc = e info 798 case k == ExpKind VTRUE => 799 if (! e hasjumps()) 800 pc = luaK_jump() /* always jump */ 801 else 802 pc = _jumponcond(e&, 1) 803 case => 804 pc = _jumponcond(e&, 1) 805 } 806 luaK_concat(e t&, pc) /* insert last jump in `t' list */ 807 luaK_patchtohere(e f) 808 e f = NO_JUMP 809 } 810 811 812 _codenot: func(e: ExpDesc@) { 813 luaK_dischargevars(e&) 814 k := e k 815 match { 816 case k == ExpKind VNIL || 817 k == ExpKind VFALSE => 818 e k = ExpKind VTRUE 819 case k == ExpKind VK || 820 k == ExpKind VKNUM || 821 k == ExpKind VTRUE => 822 e k = ExpKind VFALSE 823 case k == ExpKind VJMP => 824 _invertjump(e&) 825 case k == ExpKind VRELOCABLE || 826 k == ExpKind VNONRELOC => 827 _discharge2anyreg(e&) 828 _freeexp(e&) 829 e info = luaK_codeABC(OpCode OP_NOT, 0, e info, 0) 830 e k = ExpKind VRELOCABLE 831 case => 832 version(debug) { 833 assert(false) /* cannot happen */ 834 } 835 } 836 /* interchange true and false lists */ 837 temp := e f; e f = e t; e t = temp 838 _removevalues(e f) 839 _removevalues(e t) 840 } 841 842 843 luaK_indexed: func(t, k: ExpDesc@) { 844 version(debug) { 845 assert(! t hasjumps()) 846 } 847 t ind_t = t info 848 t ind_idx = luaK_exp2RK(k&) 849 version(debug) { 850 if (t k != ExpKind VUPVAL) 851 assert(t k vkisinreg()) 852 } 853 t ind_vt = (t k == ExpKind VUPVAL) ? ExpKind VUPVAL : ExpKind VLOCAL 854 t k = ExpKind VINDEXED 855 } 856 857 858 _constfolding: func(op: OpCode, e1, e2: ExpDesc@) -> Bool { 859 if (! e1 isnumeral() || ! e2 isnumeral()) 860 return false 861 if ((op == OpCode OP_DIV || op == OpCode OP_MOD) && e2 nval == 0) 862 return false /* do not attempt to divide by 0 */ 863 match (op) { 864 case OpCode OP_ADD => 865 e1 nval = e1 nval + e2 nval 866 case OpCode OP_SUB => 867 e1 nval = e1 nval - e2 nval 868 case OpCode OP_MUL => 869 e1 nval = e1 nval * e2 nval 870 case OpCode OP_DIV => 871 e1 nval = e1 nval / e2 nval 872 case OpCode OP_MOD => 873 e1 nval = e1 nval - (e1 nval / e2 nval) floor() * e2 nval 874 case OpCode OP_POW => 875 e1 nval = e1 nval pow(e2 nval) 876 case => 877 assert(false) 878 } 879 return true 880 } 881 882 883 _codearith: func(op: OpCode, e1, e2: ExpDesc@, line: Int) { 884 if (_constfolding(op, e1&, e2&)) 885 return 886 else { 887 o2 := (op != OpCode OP_UNM && op != OpCode OP_LEN) ? luaK_exp2RK(e2&) : 0 888 o1 := luaK_exp2RK(e1&) 889 if (o1 > o2) { 890 _freeexp(e1&) 891 _freeexp(e2&) 892 } 893 else { 894 _freeexp(e2&) 895 _freeexp(e1&) 896 } 897 e1 info = luaK_codeABC(op, 0, o1, o2) 898 e1 k = ExpKind VRELOCABLE 899 luaK_fixline(line) 900 } 901 } 902 903 904 _codecomp: func(op: OpCode, cond: Int, e1, e2: ExpDesc@) { 905 o1 := luaK_exp2RK(e1&) 906 o2 := luaK_exp2RK(e2&) 907 _freeexp(e2&) 908 _freeexp(e1&) 909 if (! cond && op != OpCode OP_EQ) { 910 /* exchange args to replace by `<' or `<=' */ 911 temp := o1; o1 = o2; o2 = temp; /* o1 <==> o2 */ 912 cond = 1 913 } 914 e1 info = _condjump(op, cond, o1, o2) 915 e1 k = ExpKind VJMP 916 } 917 918 919 luaK_prefix: func(op: UnOpr, e: ExpDesc@, line: Int) { 920 e2: ExpDesc 921 e2 t = NO_JUMP 922 e2 f = NO_JUMP 923 e2 k = ExpKind VKNUM 924 e2 nval = 0 925 match (op) { 926 case UnOpr OPR_MINUS => 927 if (e isnumeral()) /* minus constant? */ 928 e nval = - e nval /* fold it */ 929 else { 930 luaK_exp2anyreg(e&) 931 _codearith(OpCode OP_UNM, e&, e2&, line) 932 } 933 case UnOpr OPR_NOT => 934 _codenot(e&) 935 case UnOpr OPR_LEN => 936 luaK_exp2anyreg(e&) /* cannot operate on constants */ 937 _codearith(OpCode OP_LEN, e&, e2&, line) 938 case => 939 version(debug) { 940 assert(false) 941 } 942 } 943 } 944 945 946 luaK_infix: func(op: BinOpr, v: ExpDesc@) { 947 match { 948 case op == BinOpr OPR_AND => 949 luaK_goiftrue(v&) 950 case op == BinOpr OPR_OR => 951 luaK_goiffalse(v&) 952 case op == BinOpr OPR_CONCAT => 953 luaK_exp2nextreg(v&) /* operand must be on the `stack' */ 954 case op == BinOpr OPR_ADD || 955 op == BinOpr OPR_SUB || 956 op == BinOpr OPR_MUL || 957 op == BinOpr OPR_DIV || 958 op == BinOpr OPR_MOD || 959 op == BinOpr OPR_POW => 960 if (! v isnumeral()) 961 luaK_exp2RK(v&) 962 case => 963 luaK_exp2RK(v&) 964 } 965 } 966 967 968 luaK_posfix: func(op: BinOpr, e1, e2: ExpDesc@, line: Int) { 969 match { 970 case op == BinOpr OPR_AND => 971 version(debug) { 972 assert(e1 t == NO_JUMP) /* list must be closed */ 973 } 974 luaK_dischargevars(e2&) 975 luaK_concat(e2 f&, e1 f) 976 e1 = e2 977 case op == BinOpr OPR_OR => 978 version(debug) { 979 assert(e1 f == NO_JUMP) /* list must be closed */ 980 } 981 luaK_dischargevars(e2&) 982 luaK_concat(e2 t&, e1 t) 983 e1 = e2 984 case op == BinOpr OPR_CONCAT => 985 luaK_exp2val(e2&) 986 pi := f code data as Instruction* + e2 info 987 if (e2 k == ExpKind VRELOCABLE && pi@ getOpcode() == OpCode OP_CONCAT) { 988 version(debug) { 989 assert(e1 info == pi@ getarg_B() - 1) 990 } 991 _freeexp(e1&) 992 pi@ = pi@ setarg_B(e1 info) 993 e1 k = ExpKind VRELOCABLE 994 e1 info = e2 info 995 } 996 else { 997 luaK_exp2nextreg(e2&) /* operand must be on the 'stack' */ 998 _codearith(OpCode OP_CONCAT, e1&, e2&, line) 999 } 1000 case op == BinOpr OPR_ADD => 1001 _codearith(OpCode OP_ADD, e1&, e2&, line) 1002 case op == BinOpr OPR_SUB => 1003 _codearith(OpCode OP_SUB, e1&, e2&, line) 1004 case op == BinOpr OPR_MUL => 1005 _codearith(OpCode OP_MUL, e1&, e2&, line) 1006 case op == BinOpr OPR_DIV => 1007 _codearith(OpCode OP_DIV, e1&, e2&, line) 1008 case op == BinOpr OPR_MOD => 1009 _codearith(OpCode OP_MOD, e1&, e2&, line) 1010 case op == BinOpr OPR_POW => 1011 _codearith(OpCode OP_POW, e1&, e2&, line) 1012 case op == BinOpr OPR_EQ => 1013 _codecomp(OpCode OP_EQ, 1, e1&, e2&) 1014 case op == BinOpr OPR_LT => 1015 _codecomp(OpCode OP_LT, 1, e1&, e2&) 1016 case op == BinOpr OPR_LE => 1017 _codecomp(OpCode OP_LE, 1, e1&, e2&) 1018 case op == BinOpr OPR_NE => 1019 _codecomp(OpCode OP_EQ, 0, e1&, e2&) 1020 case op == BinOpr OPR_GT => 1021 _codecomp(OpCode OP_LT, 0, e1&, e2&) 1022 case op == BinOpr OPR_GE => 1023 _codecomp(OpCode OP_LE, 0, e1&, e2&) 1024 case => 1025 version(debug) { 1026 assert(false) 1027 } 1028 } 1029 } 1030 1031 1032 luaK_fixline: func(line: Int) { 1033 f lineinfo set(f code getSize() - 1, line) 1034 } 1035 1036 1037 luaK_setlist: func(base, nelems, tostore: Int) { 1038 c := (nelems - 1)/LFIELDS_PER_FLUSH + 1 1039 b := (tostore == LUA_MULTRET) ? 0 : tostore 1040 version(debug) { 1041 assert(tostore != 0) 1042 } 1043 if (c <= MAXARG_C) 1044 luaK_codeABC(OpCode OP_SETLIST, base, b, c) 1045 else if (c <= MAXARG_Ax) { 1046 luaK_codeABC(OpCode OP_SETLIST, base, b, 0) 1047 version(debug) { 1048 assert(c <= MAXARG_Ax) 1049 } 1050 luaK_code(Instruction createAx(OpCode OP_EXTRAARG, c)) 1051 } 1052 else 1053 ls syntaxError("constructor too long") 1054 freereg = base + 1 /* free registers with list values */ 1055 } 1056 1057 checklimit: func(v, l: Int, what: String) { 1058 if (v > l) { 1059 line := f linedefined 1060 where := (line == 0) ? "main function" : "function at line %d" format(line) 1061 msg := "too many %s (limit is %d) in %s" format(what, l, where) 1062 ls syntaxError(msg) 1063 } 1064 } 1065 1066} 1067 1068 1069/* 1070** nodes for block list (list of active blocks) 1071*/ 1072BlockCnt: cover { 1073 previous: BlockCnt* /* chain */ 1074 breaklist: Int /* list of jumps out of this loop */ 1075 nactvar: UInt8 /* # active locals outside the breakable structure */ 1076 upval: Bool /* true if some variable in the block is an upvalue */ 1077 isbreakable: Bool /* true if `block' is a loop */ 1078} 1079 1080/* 1081** structure to chain all variables in the left-hand side of an 1082** assignment 1083*/ 1084LHS_assign: cover { 1085 prev: LHS_assign* 1086 v: ExpDesc /* variable (global, local, upvalue, or indexed) */ 1087} 1088 1089 1090ConsControl: cover { 1091 v: ExpDesc /* last list item read */ 1092 t: ExpDesc* /* table descriptor */ 1093 nh: Int /* total number of `record' elements */ 1094 na: Int /* total number of array elements */ 1095 tostore: Int /* number of array elements pending to be stored */ 1096} 1097 1098 1099 1100Parser: final class extends Lexer { 1101 fs: FuncState /* `FuncState' is private to the parser */ 1102 actvar: ArrayList<UInt16> /* list of all active local variables */ 1103 1104 init: func {} 1105 1106 1107 parse: func(=actvar) -> LuaProto { 1108 _mainfunc() 1109 next() /* read first token */ 1110 chunk() /* read main chunk */ 1111 _check(TK_EOS) 1112 fs finalize() 1113 version(debug) { 1114 assert(! fs prev) 1115 assert(fs f upvalues getSize() == 1) 1116 } 1117 return fs f 1118 } 1119 1120/*============================================================*/ 1121/* GRAMMAR RULES */ 1122/*============================================================*/ 1123 1124 1125 fieldsel: func(v: ExpDesc@) { 1126 /* fieldsel -> ['.' | ':'] NAME */ 1127 key: ExpDesc 1128 fs luaK_exp2anyregup(v&) 1129 next() /* skip the dot or colon */ 1130 _checkname(key&) 1131 fs luaK_indexed(v&, key&) 1132 } 1133 1134 1135 yindex: func(v: ExpDesc@) { 1136 /* index -> '[' expr ']' */ 1137 next() /* skip the '[' */ 1138 expr(v&) 1139 fs luaK_exp2val(v&) 1140 _checknext(']' as Int) 1141 } 1142 1143 1144/* 1145** {====================================================================== 1146** Rules for Constructors 1147** ======================================================================= 1148*/ 1149 1150 1151 recfield: func(cc: ConsControl@) { 1152 /* recfield -> (NAME | `['exp1`]') = exp1 */ 1153 reg := fs freereg 1154 key: ExpDesc 1155 if (t token == TK_NAME) { 1156 fs checklimit(cc nh, MAX_INT, "items in a constructor") 1157 _checkname(key&) 1158 } 1159 else /* ls->t.token == '[' */ 1160 yindex(key&) 1161 cc nh += 1 1162 _checknext('=' as Int) 1163 rkkey := fs luaK_exp2RK(key&) 1164 val: ExpDesc 1165 expr(val&) 1166 fs luaK_codeABC(OpCode OP_SETTABLE, cc t@ info, rkkey, fs luaK_exp2RK(val&)) 1167 fs freereg = reg /* free registers */ 1168 } 1169 1170 1171 closelistfield: func(cc: ConsControl@) { 1172 if (cc v k == ExpKind VVOID) 1173 return; /* there is no list item */ 1174 fs luaK_exp2nextreg(cc v&) 1175 cc v k = ExpKind VVOID 1176 if (cc tostore == LFIELDS_PER_FLUSH) { 1177 fs luaK_setlist(cc t@ info, cc na, cc tostore) /* flush */ 1178 cc tostore = 0 /* no more items pending */ 1179 } 1180 } 1181 1182 1183 lastlistfield: func(cc: ConsControl@) { 1184 if (cc tostore == 0) 1185 return 1186 if (cc v k hasmultret()) { 1187 fs luaK_setreturns(cc v&, LUA_MULTRET) 1188 fs luaK_setlist(cc t@ info, cc na, LUA_MULTRET) 1189 cc na -= 1 /* do not count last expression (unknown number of elements) */ 1190 } 1191 else { 1192 if (cc v k != ExpKind VVOID) 1193 fs luaK_exp2nextreg(cc v&) 1194 fs luaK_setlist(cc t@ info, cc na, cc tostore) 1195 } 1196 } 1197 1198 1199 listfield: func(cc: ConsControl@) { 1200 /* listfield -> exp */ 1201 expr(cc v&) 1202 fs checklimit(cc na, MAX_INT, "items in a constructor") 1203 cc na += 1 1204 cc tostore += 1 1205 } 1206 1207 1208 field: func(cc: ConsControl@) { 1209 /* field -> listfield | recfield */ 1210 match (t token) { 1211 case TK_NAME => /* may be 'listfield' or 'recfield' */ 1212 if (lookahead() != '=') /* expression? */ 1213 listfield(cc&) 1214 else 1215 recfield(cc&) 1216 case '[' => 1217 recfield(cc&) 1218 case => 1219 listfield(cc&) 1220 } 1221 } 1222 1223 1224 constructor: func(_t: ExpDesc@) { 1225 /* constructor -> '{' [ field { sep field } [sep] ] '}' 1226 sep -> ',' | ';' */ 1227 line := linenumber 1228 pc := fs luaK_codeABC(OpCode OP_NEWTABLE, 0, 0, 0) 1229 cc: ConsControl 1230 cc na = 0 1231 cc nh = 0 1232 cc tostore = 0 1233 cc t = _t& 1234 init_exp(_t&, ExpKind VRELOCABLE, pc) 1235 init_exp(cc v&, ExpKind VVOID, 0) /* no value (yet) */ 1236 fs luaK_exp2nextreg(_t&) /* fix it at stack top (for gc) */ 1237 _checknext('{' as Int) 1238 while (true) { 1239 version(debug) { 1240 assert(cc v k == ExpKind VVOID || cc tostore > 0) 1241 } 1242 if (t token == '}') 1243 break 1244 closelistfield(cc&) 1245 field(cc&) 1246 if (! _testnext(',' as Int) && ! _testnext(';' as Int)) 1247 break 1248 } 1249 _check_match('}' as Int, '{' as Int, line) 1250 lastlistfield(cc&) 1251 pi := fs f code data as Instruction* + pc 1252 pi@ = pi@ setarg_B(int2fb(cc na)) /* set initial array size */ 1253 pi@ = pi@ setarg_C(int2fb(cc nh)) /* set initial table size */ 1254 } 1255 1256/* }====================================================================== */ 1257 1258 1259 1260 parlist: func { 1261 /* parlist -> [ param { `,' param } ] */ 1262 f := fs f 1263 nparams := 0 1264 f is_vararg = false 1265 if (t token != ')') { /* is `parlist' not empty? */ 1266 while (! f is_vararg) { 1267 match (t token) { 1268 case TK_NAME => /* param -> NAME */ 1269 _new_localvar(_str_checkname()) 1270 nparams += 1 1271 case TK_DOTS => /* param -> `...' */ 1272 next() 1273 f is_vararg = true 1274 case => 1275 syntaxError("<name> or '...' expected") 1276 } 1277 if (! _testnext(',' as Int)) 1278 break 1279 } 1280 } 1281 _adjustlocalvars(nparams) 1282 f numparams = fs nactvar 1283 fs luaK_reserveregs(fs nactvar) /* reserve register for parameters */ 1284 } 1285 1286 1287 body: func(e: ExpDesc@, needself: Bool, line: Int) { 1288 /* body -> `(' parlist `)' chunk END */ 1289 fs = FuncState new(this, fs) 1290 f := fs f 1291 f linedefined = line 1292 _checknext('(' as Int) 1293 if (needself) { 1294 _new_localvarliteral("self") 1295 _adjustlocalvars(1) 1296 } 1297 parlist() 1298 _checknext(')' as Int) 1299 chunk() 1300 f lastlinedefined = linenumber 1301 _check_match(TK_END, TK_FUNCTION, line) 1302 _codeclosure(f, e&) 1303 fs = fs finalize() 1304 } 1305 1306 1307 explist1: func(v: ExpDesc@) -> Int { 1308 /* explist1 -> expr { `,' expr } */ 1309 n := 1 /* at least one expression */ 1310 expr(v&) 1311 while (_testnext(',' as Int)) { 1312 fs luaK_exp2nextreg(v&) 1313 expr(v&) 1314 n += 1 1315 } 1316 return n 1317 } 1318 1319 1320 funcargs: func(f: ExpDesc@, line: Int) { 1321 args: ExpDesc 1322 match (t token) { 1323 case '(' => /* funcargs -> `(' [ explist1 ] `)' */ 1324 next() 1325 if (t token == ')') /* arg list is empty? */ 1326 args k = ExpKind VVOID 1327 else { 1328 explist1(args&) 1329 fs luaK_setreturns(args&, LUA_MULTRET) 1330 } 1331 _check_match(')' as Int, '(' as Int, line) 1332 case '{' => /* funcargs -> constructor */ 1333 constructor(args&) 1334 case TK_STRING => /* funcargs -> STRING */ 1335 _codestring(args&, t str); 1336 next() /* must use `seminfo' before `next' */ 1337 case => 1338 syntaxError("function arguments expected") 1339 } 1340 version(debug) { 1341 assert(f k == ExpKind VNONRELOC) 1342 } 1343 nparams: Int 1344 base := f info /* base register for call */ 1345 if (args k hasmultret()) 1346 nparams = LUA_MULTRET /* open call */ 1347 else { 1348 if (args k != ExpKind VVOID) 1349 fs luaK_exp2nextreg(args&) /* close last argument */ 1350 nparams = fs freereg - (base+1) 1351 } 1352 init_exp(f&, ExpKind VCALL, fs luaK_codeABC(OpCode OP_CALL, base, nparams+1, 2)) 1353 fs luaK_fixline(line) 1354 fs freereg = base+1 /* call remove function and arguments and leaves 1355 (unless changed) one result */ 1356 } 1357 1358 1359 1360 1361/* 1362** {====================================================================== 1363** Expression parsing 1364** ======================================================================= 1365*/ 1366 1367 1368 prefixexp: func(v: ExpDesc@) { 1369 /* prefixexp -> NAME | '(' expr ')' */ 1370 match (t token) { 1371 case '(' => 1372 line := linenumber 1373 next() 1374 expr(v&) 1375 _check_match(')' as Int, '(' as Int, line) 1376 fs luaK_dischargevars(v&) 1377 case TK_NAME => 1378 _singlevar(v&) 1379 case => 1380 syntaxError("unexpected symbol") 1381 } 1382 } 1383 1384 1385 primaryexp: func(v: ExpDesc@) { 1386 /* primaryexp -> 1387 prefixexp { `.' NAME | `[' exp `]' | `:' NAME funcargs | funcargs } */ 1388 line := linenumber 1389 prefixexp(v&) 1390 while (true) { 1391 match { 1392 case t token == '.' => /* fieldsel */ 1393 fieldsel(v&) 1394 case t token == '[' => /* `[' exp1 `]' */ 1395 key: ExpDesc 1396 fs luaK_exp2anyregup(v&) 1397 yindex(key&) 1398 fs luaK_indexed(v&, key&) 1399 case t token == ':' => /* `:' NAME funcargs */ 1400 key: ExpDesc 1401 next() 1402 _checkname(key&) 1403 fs luaK_self(v&, key&) 1404 funcargs(v&, line) 1405 case t token == '(' || 1406 t token == TK_STRING || 1407 t token == '{' => /* funcargs */ 1408 fs luaK_exp2nextreg(v&) 1409 funcargs(v&, line) 1410 case => 1411 return 1412 } 1413 } 1414 } 1415 1416 1417 simpleexp: func(v: ExpDesc@) { 1418 /* simpleexp -> NUMBER | STRING | NIL | TRUE | FALSE | ... | 1419 constructor | FUNCTION body | primaryexp */ 1420 match (t token) { 1421 case TK_NUMBER => 1422 init_exp(v&, ExpKind VKNUM, 0) 1423 v nval = t num 1424 case TK_STRING => 1425 _codestring(v&, t str); 1426 case TK_NIL => 1427 init_exp(v&, ExpKind VNIL, 0) 1428 case TK_TRUE => 1429 init_exp(v&, ExpKind VTRUE, 0) 1430 case TK_FALSE => 1431 init_exp(v&, ExpKind VFALSE, 0) 1432 case TK_DOTS => /* vararg */ 1433 _check_condition(fs f is_vararg, 1434 "cannot use '...' outside a vararg function") 1435 init_exp(v&, ExpKind VVARARG, fs luaK_codeABC(OpCode OP_VARARG, 0, 1, 0)) 1436 case '{' => /* constructor */ 1437 constructor(v&) 1438 return 1439 case TK_FUNCTION => 1440 next() 1441 body(v&, false, linenumber) 1442 return 1443 case => 1444 primaryexp(v&) 1445 return 1446 } 1447 next() 1448 } 1449 1450 1451 getunopr: func(op: Int) -> UnOpr { 1452 match (op) { 1453 case TK_NOT => 1454 return UnOpr OPR_NOT 1455 case '-' => 1456 return UnOpr OPR_MINUS 1457 case '#' => 1458 return UnOpr OPR_LEN 1459 case => 1460 return UnOpr OPR_NOUNOPR 1461 } 1462 return UnOpr OPR_NOUNOPR // avoir error 1463 } 1464 1465 1466 getbinopr: func(op: Int) -> BinOpr { 1467 match (op) { 1468 case '+' => 1469 return BinOpr OPR_ADD 1470 case '-' => 1471 return BinOpr OPR_SUB 1472 case '*' => 1473 return BinOpr OPR_MUL 1474 case '/' => 1475 return BinOpr OPR_DIV 1476 case '%' => 1477 return BinOpr OPR_MOD 1478 case '^' => 1479 return BinOpr OPR_POW 1480 case TK_CONCAT => 1481 return BinOpr OPR_CONCAT 1482 case TK_NE => 1483 return BinOpr OPR_NE 1484 case TK_EQ => 1485 return BinOpr OPR_EQ 1486 case '<' => 1487 return BinOpr OPR_LT 1488 case TK_LE => 1489 return BinOpr OPR_LE 1490 case '>' => 1491 return BinOpr OPR_GT 1492 case TK_GE => 1493 return BinOpr OPR_GE 1494 case TK_AND => 1495 return BinOpr OPR_AND 1496 case TK_OR => 1497 return BinOpr OPR_OR 1498 case => 1499 return BinOpr OPR_NOBINOPR 1500 } 1501 return BinOpr OPR_NOBINOPR // avoid error 1502 } 1503 1504 1505/* 1506** subexpr -> (simpleexp | unop subexpr) { binop subexpr } 1507** where `binop' is any binary operator with a priority higher than `limit' 1508*/ 1509 subexpr: func(v: ExpDesc@, limit: Int) -> BinOpr { 1510 _enterlevel() 1511 uop := getunopr(t token) 1512 if (uop != UnOpr OPR_NOUNOPR) { 1513 line := linenumber 1514 next() 1515 subexpr(v&, UNARY_PRIORITY) 1516 fs luaK_prefix(uop, v&, line) 1517 } 1518 else 1519 simpleexp(v&) 1520 /* expand while operators have priorities higher than `limit' */ 1521 op := getbinopr(t token) 1522 while (op != BinOpr OPR_NOBINOPR && PRIORITY_LEFT[op] > limit) { 1523 v2: ExpDesc 1524 line := linenumber 1525 next() 1526 fs luaK_infix(op, v&) 1527 /* read sub-expression with higher priority */ 1528 nextop := subexpr(v2&, PRIORITY_RIGHT[op]) 1529 fs luaK_posfix(op, v&, v2&, line) 1530 op = nextop 1531 } 1532 _leavelevel() 1533 return op; /* return first untreated operator */ 1534 } 1535 1536 1537 expr: func(v: ExpDesc@) { 1538 subexpr(v&, 0) 1539 } 1540 1541/* }==================================================================== */ 1542 1543 1544 1545/* 1546** {====================================================================== 1547** Rules for Statements 1548** ======================================================================= 1549*/ 1550 1551 block_follow: func(token: Int) -> Bool { 1552 return (token == TK_ELSE || 1553 token == TK_ELSEIF || 1554 token == TK_END || 1555 token == TK_UNTIL || 1556 token == TK_EOS) 1557 } 1558 1559 1560 block: func { 1561 /* block -> chunk */ 1562 bl: BlockCnt 1563 fs enterblock(bl&, false) 1564 chunk() 1565 version(debug) { 1566 assert(bl breaklist == NO_JUMP) 1567 } 1568 fs leaveblock() 1569 } 1570 1571 1572/* 1573** check whether, in an assignment to a local variable, the local variable 1574** is needed in a previous assignment (to a table). If so, save original 1575** local value in a safe place and use this safe copy in the previous 1576** assignment. 1577*/ 1578 _check_conflict: func(lh: LHS_assign*, v: ExpDesc@) { 1579 extra := fs freereg /* eventual position to save local variable */ 1580 conflict := false 1581 while (lh) { 1582 /* conflict in table 't'? */ 1583 if (lh@ v ind_vt == v k && lh@ v ind_t == v info) { 1584 conflict = true 1585 lh@ v ind_vt = ExpKind VLOCAL 1586 lh@ v ind_t = extra /* previous assignment will use safe copy */ 1587 } 1588 /* conflict in index 'idx'? */ 1589 if (v k == ExpKind VLOCAL && lh@ v ind_idx == v info) { 1590 conflict = true 1591 lh@ v ind_idx = extra /* previous assignment will use safe copy */ 1592 } 1593 lh = lh@ prev 1594 } 1595 if (conflict) { 1596 op := (v k == ExpKind VLOCAL) ? OpCode OP_MOVE : OpCode OP_GETUPVAL 1597 fs luaK_codeABC(op, fs freereg, v info, 0) /* make copy */ 1598 fs luaK_reserveregs(1) 1599 } 1600 } 1601 1602 1603 assignment: func(lh: LHS_assign@, nvars: Int) { 1604 e: ExpDesc 1605 _check_condition(lh v k vkisvar(), "syntax error") 1606 if (_testnext(',' as Int)) { /* assignment -> `,' primaryexp assignment */ 1607 nv: LHS_assign 1608 nv prev = lh& 1609 primaryexp(nv v&) 1610 if (nv v k != ExpKind VINDEXED) 1611 _check_conflict(lh&, nv v&) 1612 assignment(nv&, nvars+1) 1613 } 1614 else { /* assignment -> `=' explist1 */ 1615 _checknext('=' as Int) 1616 nexps := explist1(e&) 1617 if (nexps != nvars) { 1618 _adjust_assign(nvars, nexps, e&) 1619 if (nexps > nvars) 1620 fs freereg -= nexps - nvars /* remove extra values */ 1621 } 1622 else { 1623 fs luaK_setoneret(e&) /* close last expression */ 1624 fs luaK_storevar(lh v&, e&) 1625 return /* avoid default */ 1626 } 1627 } 1628 init_exp(e&, ExpKind VNONRELOC, fs freereg - 1) /* default assignment */ 1629 fs luaK_storevar(lh v&, e&) 1630 } 1631 1632 1633 cond: func -> Int { 1634 /* cond -> exp */ 1635 v: ExpDesc 1636 expr(v&) /* read condition */ 1637 if (v k == ExpKind VNIL) 1638 v k = ExpKind VFALSE /* `falses' are all equal here */ 1639 fs luaK_goiftrue(v&) 1640 return v f 1641 } 1642 1643 1644 breakstat: func { 1645 bl := fs bl 1646 upval := false 1647 while (bl) { 1648 if (bl@ isbreakable) 1649 break 1650 upval |= bl@ upval 1651 bl = bl@ previous 1652 } 1653 if (! bl) 1654 syntaxError("no loop to break") 1655 if (upval) 1656 fs luaK_codeABC(OpCode OP_CLOSE, bl@ nactvar, 0, 0) 1657 fs luaK_concat(bl@ breaklist&, fs luaK_jump()) 1658 } 1659 1660 1661 whilestat: func(line: Int) { 1662 /* whilestat -> WHILE cond DO block END */ 1663 bl: BlockCnt 1664 next() /* skip WHILE */ 1665 whileinit := fs luaK_getlabel() 1666 condexit := cond() 1667 fs enterblock(bl&, true) 1668 _checknext(TK_DO) 1669 block() 1670 fs luaK_patchlist(fs luaK_jump(), whileinit) 1671 _check_match(TK_END, TK_WHILE, line) 1672 fs leaveblock() 1673 fs luaK_patchtohere(condexit) /* false conditions finish the loop */ 1674 } 1675 1676 1677 repeatstat: func(line: Int) { 1678 /* repeatstat -> REPEAT block UNTIL cond */ 1679 repeat_init := fs luaK_getlabel() 1680 bl1, bl2: BlockCnt 1681 fs enterblock(bl1&, true); /* loop block */ 1682 fs enterblock(bl2&, false); /* scope block */ 1683 next() /* skip REPEAT */ 1684 chunk() 1685 _check_match(TK_UNTIL, TK_REPEAT, line) 1686 condexit := cond() /* read condition (inside scope block) */ 1687 if (!bl2 upval) { /* no upvalues? */ 1688 fs leaveblock() /* finish scope */ 1689 fs luaK_patchlist(condexit, repeat_init) /* close the loop */ 1690 } 1691 else { /* complete semantics when there are upvalues */ 1692 breakstat() /* if condition then break */ 1693 fs luaK_patchtohere(condexit) /* else... */ 1694 fs leaveblock() /* finish scope... */ 1695 fs luaK_patchlist(fs luaK_jump(), repeat_init) /* and repeat */ 1696 } 1697 fs leaveblock() /* finish loop */ 1698 } 1699 1700 1701 exp1: func { 1702 e: ExpDesc 1703 expr(e&) 1704 fs luaK_exp2nextreg(e&) 1705 version(debug) { 1706 assert(e k == ExpKind VNONRELOC) 1707 } 1708 return e info 1709 } 1710 1711 1712 forbody: func(base, line, nvars: Int, isnum: Bool) { 1713 /* forbody -> DO block */ 1714 bl: BlockCnt 1715 _adjustlocalvars(3) /* control variables */ 1716 _checknext(TK_DO) 1717 prep := isnum ? fs luaK_codeABx(OpCode OP_FORPREP, base, NO_JUMP + MAXARG_sBx) : fs luaK_jump() 1718 fs enterblock(bl&, false) /* scope for declared variables */ 1719 _adjustlocalvars(nvars) 1720 fs luaK_reserveregs(nvars) 1721 block() 1722 fs leaveblock() /* end of scope for declared variables */ 1723 fs luaK_patchtohere(prep) 1724 endfor: Int 1725 if (isnum) /* numeric for? */ 1726 endfor = fs luaK_codeABx(OpCode OP_FORLOOP, base, NO_JUMP + MAXARG_sBx); 1727 else { /* generic for */ 1728 fs luaK_codeABC(OpCode OP_TFORCALL, base, 0, nvars) 1729 fs luaK_fixline(line) 1730 endfor = fs luaK_codeABx(OpCode OP_TFORLOOP, base + 2, NO_JUMP + MAXARG_sBx); 1731 } 1732 fs luaK_patchlist(endfor, prep + 1) 1733 fs luaK_fixline(line) 1734 } 1735 1736 1737 fornum: func(varname: String, line: Int) { 1738 /* fornum -> NAME = exp1,exp1[,exp1] forbody */ 1739 base := fs freereg 1740 _new_localvarliteral("(for index)") 1741 _new_localvarliteral("(for limit)") 1742 _new_localvarliteral("(for step)") 1743 _new_localvar(varname) 1744 _checknext('=' as Int) 1745 exp1() /* initial value */ 1746 _checknext(',' as Int) 1747 exp1() /* limit */ 1748 if (_testnext(',' as Int)) 1749 exp1() /* optional step */ 1750 else { /* default step = 1 */ 1751 fs luaK_codeABxX(OpCode OP_LOADK, fs freereg, fs luaK_numberK(1)) 1752 fs luaK_reserveregs(1) 1753 } 1754 forbody(base, line, 1, true) 1755 } 1756 1757 1758 forlist: func(indexname: String) { 1759 /* forlist -> NAME {,NAME} IN explist1 forbody */ 1760 nvars := 4 /* gen, state, control, plus at least one declared var */ 1761 base := fs freereg 1762 /* create control variables */ 1763 _new_localvarliteral("(for generator)") 1764 _new_localvarliteral("(for state)") 1765 _new_localvarliteral("(for control)") 1766 /* create declared variables */ 1767 _new_localvar(indexname) 1768 while (_testnext(',' as Int)) { 1769 _new_localvar(_str_checkname()) 1770 nvars += 1 1771 } 1772 _checknext(TK_IN) 1773 line := linenumber 1774 e: ExpDesc 1775 _adjust_assign(3, explist1(e&), e&) 1776 fs luaK_checkstack(3) /* extra space to call generator */ 1777 forbody(base, line, nvars - 3, false) 1778 } 1779 1780 1781 forstat: func(line: Int) { 1782 /* forstat -> FOR (fornum | forlist) END */ 1783 bl: BlockCnt 1784 fs enterblock(bl&, true) /* scope for loop and control variables */ 1785 next() /* skip `for' */ 1786 varname := _str_checkname() /* first variable name */ 1787 match (t token) { 1788 case '=' => 1789 fornum(varname, line) 1790 case ',' => 1791 forlist(varname) 1792 case TK_IN => 1793 forlist(varname) 1794 case => 1795 syntaxError("'=' or 'in' expected") 1796 } 1797 _check_match(TK_END, TK_FOR, line) 1798 fs leaveblock() /* loop scope (`break' jumps to this point) */ 1799 } 1800 1801 1802 test_then_block: func -> Int { 1803 /* test_then_block -> [IF | ELSEIF] cond THEN block */ 1804 next() /* skip IF or ELSEIF */ 1805 condexit := cond() 1806 _checknext(TK_THEN) 1807 block() /* `then' part */ 1808 return condexit 1809 } 1810 1811 1812 ifstat: func(line: Int) { 1813 /* ifstat -> IF cond THEN block {ELSEIF cond THEN block} [ELSE block] END */ 1814 escapelist := NO_JUMP 1815 flist := test_then_block() /* IF cond THEN block */ 1816 while (t token == TK_ELSEIF) { 1817 fs luaK_concat(escapelist&, fs luaK_jump()) 1818 fs luaK_patchtohere(flist) 1819 flist = test_then_block() /* ELSEIF cond THEN block */ 1820 } 1821 if (t token == TK_ELSE) { 1822 fs luaK_concat(escapelist&, fs luaK_jump()) 1823 fs luaK_patchtohere(flist) 1824 next() /* skip ELSE (after patch, for correct line info) */ 1825 block() /* `else' part */ 1826 } 1827 else 1828 fs luaK_concat(escapelist&, flist) 1829 fs luaK_patchtohere(escapelist) 1830 _check_match(TK_END, TK_IF, line) 1831 } 1832 1833 1834 localfunc: func { 1835 v, b: ExpDesc 1836 _new_localvar(_str_checkname()) 1837 init_exp(v&, ExpKind VLOCAL, fs freereg) 1838 fs luaK_reserveregs(1) 1839 _adjustlocalvars(1) 1840 body(b&, false, linenumber) 1841 fs luaK_storevar(v&, b&) 1842 } 1843 1844 1845 localstat: func { 1846 /* stat -> LOCAL NAME {`,' NAME} [`=' explist1] */ 1847 nvars := 0 1848 nexps: Int 1849 e: ExpDesc 1850 while (true) { 1851 _new_localvar(_str_checkname()) 1852 nvars += 1 1853 if (! _testnext(',' as Int)) 1854 break 1855 } 1856 if (_testnext('=' as Int)) 1857 nexps = explist1(e&) 1858 else { 1859 e k = ExpKind VVOID 1860 nexps = 0 1861 } 1862 _adjust_assign(nvars, nexps, e&) 1863 _adjustlocalvars(nvars) 1864 } 1865 1866 1867 funcname: func(v: ExpDesc@) -> Bool { 1868 /* funcname -> NAME {fieldsel} [`:' NAME] */ 1869 needself := false 1870 _singlevar(v&) 1871 while (t token == '.') 1872 fieldsel(v&) 1873 if (t token == ':') { 1874 needself = true 1875 fieldsel(v&) 1876 } 1877 return needself 1878 } 1879 1880 funcstat: func(line: Int) { 1881 /* funcstat -> FUNCTION funcname body */ 1882 v, b: ExpDesc 1883 next() /* skip FUNCTION */ 1884 needself := funcname(v&) 1885 body(b&, needself, line) 1886 fs luaK_storevar(v&, b&) 1887 fs luaK_fixline(line) /* definition `happens' in the first line */ 1888 } 1889 1890 1891 exprstat: func { 1892 /* stat -> func | assignment */ 1893 v: LHS_assign 1894 primaryexp(v v&) 1895 if (v v k == ExpKind VCALL) { /* stat -> func */ 1896 pi := fs f code data as Instruction* + v v info 1897 pi@ = pi@ setarg_C(1) /* call statement uses no results */ 1898 } 1899 else { /* stat -> assignment */ 1900 v prev = null 1901 assignment(v&, 1) 1902 } 1903 } 1904 1905 1906 retstat: func { 1907 /* stat -> RETURN explist */ 1908 e: ExpDesc 1909 first, nret: Int /* registers with returned values */ 1910 if (block_follow(t token) || t token == ';') { 1911 first = 0 1912 nret = 0 /* return no values */ 1913 } 1914 else { 1915 nret = explist1(e&) /* optional return values */ 1916 if (e k hasmultret()) { 1917 fs luaK_setreturns(e&, LUA_MULTRET) 1918 if (e k == ExpKind VCALL && nret == 1) { /* tail call? */ 1919 pi := fs f code data as Instruction* + e info 1920 pi@ = pi@ setOpcode(OpCode OP_TAILCALL) 1921 version(debug) { 1922 assert(pi@ getarg_A() == fs nactvar) 1923 } 1924 } 1925 first = fs nactvar 1926 nret = LUA_MULTRET /* return all values */ 1927 } 1928 else { 1929 if (nret == 1) /* only one single value? */ 1930 first = fs luaK_exp2anyreg(e&) 1931 else { 1932 fs luaK_exp2nextreg(e&) /* values must go to the `stack' */ 1933 first = fs nactvar /* return all `active' values */ 1934 version(debug) { 1935 assert(nret == fs freereg - first) 1936 } 1937 } 1938 } 1939 } 1940 fs luaK_ret(first, nret) 1941 } 1942 1943 1944 statement: func -> Bool { 1945 line := linenumber /* may be needed for error messages */ 1946 match (t token) { 1947 case ';' => /* stat -> ';' (empty statement) */ 1948 next() /* skip ';' */ 1949 return false 1950 case TK_IF => /* stat -> ifstat */ 1951 ifstat(line) 1952 return false 1953 case TK_WHILE => /* stat -> whilestat */ 1954 whilestat(line) 1955 return false 1956 case TK_DO => /* stat -> DO block END */ 1957 next() /* skip DO */ 1958 block() 1959 _check_match(TK_END, TK_DO, line) 1960 return false 1961 case TK_FOR => /* stat -> forstat */ 1962 forstat(line) 1963 return false 1964 case TK_REPEAT => /* stat -> repeatstat */ 1965 repeatstat(line) 1966 return false 1967 case TK_FUNCTION => /* stat -> funcstat */ 1968 funcstat(line) 1969 return false 1970 case TK_LOCAL => /* stat -> localstat */ 1971 next() /* skip LOCAL */ 1972 if (_testnext(TK_FUNCTION)) /* local function? */ 1973 localfunc() 1974 else 1975 localstat() 1976 return false 1977 case TK_RETURN => /* stat -> retstat */ 1978 next() /* skip RETURN */ 1979 retstat() 1980 return true /* must be last statement */ 1981 case TK_BREAK => /* stat -> breakstat */ 1982 next() /* skip BREAK */ 1983 breakstat() 1984 return true /* must be last statement */ 1985 case => /* stat -> func | assignment */ 1986 exprstat() 1987 return false 1988 } 1989 return false 1990 } 1991 1992 1993 chunk: func { 1994 /* chunk -> { stat [`;'] } */ 1995 last := false 1996 _enterlevel() 1997 while (!last && !block_follow(t token)) { 1998 last = statement() 1999 if (last) 2000 _testnext(';' as Int) 2001 version(debug) { 2002 assert(fs f maxstacksize >= fs freereg) 2003 assert(fs freereg >= fs nactvar) 2004 } 2005 fs freereg = fs nactvar 2006 } 2007 _leavelevel() 2008 } 2009 2010 2011 _testnext: func(c: Int) -> Bool { 2012 if (t token == c) { 2013 next() 2014 return true 2015 } 2016 else 2017 return false 2018 } 2019 2020 _check: func(c: Int) { 2021 if (t token != c) 2022 _error_expected(c) 2023 } 2024 2025 _checknext: func(c: Int) { 2026 _check(c) 2027 next() 2028 } 2029 2030 _check_condition: func(c: Bool, msg: String) { 2031 if (! c) 2032 syntaxError(msg) 2033 } 2034 2035 _check_match: func(what, who, where: Int) { 2036 if (! _testnext(what)) { 2037 if (where == linenumber) 2038 _error_expected(what) 2039 else 2040 syntaxError("%s expected (to close %s at line %d)" format( 2041 token2str(what), 2042 token2str(who), 2043 where 2044 )) 2045 } 2046 } 2047 2048 _str_checkname: func -> String { 2049 _check(TK_NAME) 2050 ts := t str 2051 next() 2052 return ts 2053 } 2054 2055 _codestring: func(e: ExpDesc@, s: String) { 2056 init_exp(e&, ExpKind VK, fs luaK_stringK(s)) 2057 } 2058 2059 _checkname: func(e: ExpDesc@) { 2060 _codestring(e&, _str_checkname()) 2061 } 2062 2063 _registerlocalvar: func(varname: String) -> Int { 2064 locvars := fs f locvars 2065 idx := locvars getSize() 2066 locvars add(LocVar new(varname)) 2067 return idx 2068 } 2069 2070 2071 _new_localvar: func(name: String) { 2072 reg := _registerlocalvar(name) 2073 fs checklimit(actvar getSize() + 1 - fs firstlocal, MAXVARS, "local variables") 2074 actvar add(reg) 2075 } 2076 2077 2078 _new_localvarliteral: func(name: String) { 2079 _new_localvar(name) 2080 } 2081 2082 2083 _adjustlocalvars: func(nvars: Int) { 2084 fs nactvar += nvars 2085 while (nvars) { 2086 pvar := fs getlocvar(fs nactvar - nvars) 2087 pvar@ startpc = fs f code getSize() 2088 nvars -= 1 2089 } 2090 } 2091 2092 2093 _singlevar: func(var: ExpDesc@) { 2094 varname := _str_checkname() 2095 if (fs singlevaraux(varname, var&, 1) == ExpKind VVOID) { /* global name? */ 2096 key: ExpDesc 2097 fs singlevaraux(envn, var&, 1) /* get environment variable */ 2098 version(debug) { 2099 assert(var k == ExpKind VLOCAL || var k == ExpKind VUPVAL) 2100 } 2101 _codestring(key&, varname) /* key is variable name */ 2102 fs luaK_indexed(var&, key&) /* env[varname] */ 2103 } 2104 } 2105 2106 2107 _adjust_assign: func(nvars, nexps: Int, e: ExpDesc@) { 2108 extra := nvars - nexps 2109 if (e k hasmultret()) { 2110 extra += 1 /* includes call itself */ 2111 if (extra < 0) 2112 extra = 0 2113 fs luaK_setreturns(e&, extra) /* last exp. provides the difference */ 2114 if (extra > 1) 2115 fs luaK_reserveregs(extra-1) 2116 } 2117 else { 2118 if (e k != ExpKind VVOID) 2119 fs luaK_exp2nextreg(e&) /* close last expression */ 2120 if (extra > 0) { 2121 reg := fs freereg 2122 fs luaK_reserveregs(extra) 2123 fs luaK_nil(reg, extra) 2124 } 2125 } 2126 } 2127 2128 2129 _enterlevel: func { 2130 } 2131 2132 2133 _leavelevel: func { 2134 } 2135 2136 2137/* 2138** adds prototype being created into its parent list of prototypes 2139** and codes instruction to create new closure 2140*/ 2141 _codeclosure: func(clp: LuaProto, v: ExpDesc@) { 2142 f := fs prev f /* prototype of function creating new closure */ 2143 np := f p getSize() 2144 f p add(clp) 2145 init_exp(v&, ExpKind VRELOCABLE, fs prev luaK_codeABx(OpCode OP_CLOSURE, 0, np)) 2146 } 2147 2148 2149/* 2150** opens the main function, which is a regular vararg function with an 2151** upvalue named LUA_ENV 2152*/ 2153 _mainfunc: func { 2154 fs = FuncState new(this, null as FuncState) 2155 fs f is_vararg = true /* main function is always vararg */ 2156 v: ExpDesc 2157 init_exp(v&, ExpKind VLOCAL, 0) 2158 fs newupvalue(envn, v&) /* create environment upvalue */ 2159 } 2160 2161 2162 _error_expected: func(c: Int) { 2163 syntaxError("%s expected" format(token2str(c))) 2164 } 2165 2166} 2167 2168PRIORITY_LEFT := const [ 2169 6, 6, 7, 7, 7, /* `+' `-' `*' `/' `%' */ 2170 10, 5, /* ^, .. (right associative) */ 2171 3, 3, 3, /* ==, <, <= */ 2172 3, 3, 3, /* ~=, >, >= */ 2173 2, 1 /* and, or */ 2174] 2175 2176PRIORITY_RIGHT := const [ 2177 6, 6, 7, 7, 7, /* `+' `-' `*' `/' `%' */ 2178 9, 4, /* ^, .. (right associative) */ 2179 3, 3, 3, /* ==, <, <= */ 2180 3, 3, 3, /* ~=, >, >= */ 2181 2, 1 /* and, or */ 2182] 2183 2184UNARY_PRIORITY := const 8 /* priority for unary operators */ 2185 2186 2187/* 2188** Marks the end of a patch list. It is an invalid value both as an absolute 2189** address, and as a list link (would link an element to itself). 2190*/ 2191NO_JUMP := const -1 2192 2193 2194/* 2195** grep "ORDER OPR" if you change these enums (ORDER OP) 2196*/ 2197BinOpr: enum { 2198 OPR_ADD, OPR_SUB, OPR_MUL, OPR_DIV, OPR_MOD, OPR_POW, 2199 OPR_CONCAT, 2200 OPR_EQ, OPR_LT, OPR_LE, 2201 OPR_NE, OPR_GT, OPR_GE, 2202 OPR_AND, OPR_OR, 2203 OPR_NOBINOPR 2204} 2205 2206 2207UnOpr: enum { 2208 OPR_MINUS, 2209 OPR_NOT, 2210 OPR_LEN, 2211 OPR_NOUNOPR 2212} 2213 2214/* maximum number of local variables per function (must be smaller 2215 than 250, due to the bytecode format) */ 2216MAXVARS := const 200 2217 2218 2219/* maximum stack for a Lua function */ 2220MAXSTACK := const 250 2221 2222MAX_INT := const INT_MAX-2 /* maximum value of an int (-2 for safety) */ 2223 2224/* 2225** maximum depth for nested C calls and syntactical nested non-terminals 2226** in a program. (Value must fit in an unsigned short int.) 2227*/ 2228LUAI_MAXCCALLS := const 200 2229 2230/* 2231** maximum number of upvalues in a closure (both C and Lua). (Value 2232** must fit in an unsigned char.) 2233*/ 2234MAXUPVAL := const 255 // UCHAR_MAX