diff options
-rw-r--r-- | lcode.c | 40 | ||||
-rw-r--r-- | lcode.h | 4 | ||||
-rw-r--r-- | lopcodes.h | 23 | ||||
-rw-r--r-- | lparser.c | 29 | ||||
-rw-r--r-- | lvm.c | 28 | ||||
-rw-r--r-- | testes/nextvar.lua | 28 |
6 files changed, 80 insertions, 72 deletions
@@ -372,7 +372,7 @@ static void removelastinstruction (FuncState *fs) { | |||
372 | ** Emit instruction 'i', checking for array sizes and saving also its | 372 | ** Emit instruction 'i', checking for array sizes and saving also its |
373 | ** line information. Return 'i' position. | 373 | ** line information. Return 'i' position. |
374 | */ | 374 | */ |
375 | static int luaK_code (FuncState *fs, Instruction i) { | 375 | int luaK_code (FuncState *fs, Instruction i) { |
376 | Proto *f = fs->f; | 376 | Proto *f = fs->f; |
377 | /* put new instruction in code array */ | 377 | /* put new instruction in code array */ |
378 | luaM_growvector(fs->ls->L, f->code, fs->pc, f->sizecode, Instruction, | 378 | luaM_growvector(fs->ls->L, f->code, fs->pc, f->sizecode, Instruction, |
@@ -430,7 +430,7 @@ static int codesJ (FuncState *fs, OpCode o, int sj, int k) { | |||
430 | /* | 430 | /* |
431 | ** Emit an "extra argument" instruction (format 'iAx') | 431 | ** Emit an "extra argument" instruction (format 'iAx') |
432 | */ | 432 | */ |
433 | int luaK_codeextraarg (FuncState *fs, int a) { | 433 | static int codeextraarg (FuncState *fs, int a) { |
434 | lua_assert(a <= MAXARG_Ax); | 434 | lua_assert(a <= MAXARG_Ax); |
435 | return luaK_code(fs, CREATE_Ax(OP_EXTRAARG, a)); | 435 | return luaK_code(fs, CREATE_Ax(OP_EXTRAARG, a)); |
436 | } | 436 | } |
@@ -446,7 +446,7 @@ static int luaK_codek (FuncState *fs, int reg, int k) { | |||
446 | return luaK_codeABx(fs, OP_LOADK, reg, k); | 446 | return luaK_codeABx(fs, OP_LOADK, reg, k); |
447 | else { | 447 | else { |
448 | int p = luaK_codeABx(fs, OP_LOADKX, reg, 0); | 448 | int p = luaK_codeABx(fs, OP_LOADKX, reg, 0); |
449 | luaK_codeextraarg(fs, k); | 449 | codeextraarg(fs, k); |
450 | return p; | 450 | return p; |
451 | } | 451 | } |
452 | } | 452 | } |
@@ -1672,6 +1672,22 @@ void luaK_fixline (FuncState *fs, int line) { | |||
1672 | } | 1672 | } |
1673 | 1673 | ||
1674 | 1674 | ||
1675 | void luaK_settablesize (FuncState *fs, int pc, int ra, int rc, int rb) { | ||
1676 | Instruction *inst = &fs->f->code[pc]; | ||
1677 | int extra = 0; | ||
1678 | int k = 0; | ||
1679 | if (rb != 0) | ||
1680 | rb = luaO_ceillog2(rb) + 1; /* hash size */ | ||
1681 | if (rc > MAXARG_C) { /* does it need the extra argument? */ | ||
1682 | extra = rc / (MAXARG_C + 1); | ||
1683 | rc %= (MAXARG_C + 1); | ||
1684 | k = 1; | ||
1685 | } | ||
1686 | *inst = CREATE_ABCk(OP_NEWTABLE, ra, rb, rc, k); | ||
1687 | *(inst + 1) = CREATE_Ax(OP_EXTRAARG, extra); | ||
1688 | } | ||
1689 | |||
1690 | |||
1675 | /* | 1691 | /* |
1676 | ** Emit a SETLIST instruction. | 1692 | ** Emit a SETLIST instruction. |
1677 | ** 'base' is register that keeps table; | 1693 | ** 'base' is register that keeps table; |
@@ -1680,17 +1696,17 @@ void luaK_fixline (FuncState *fs, int line) { | |||
1680 | ** table (or LUA_MULTRET to add up to stack top). | 1696 | ** table (or LUA_MULTRET to add up to stack top). |
1681 | */ | 1697 | */ |
1682 | void luaK_setlist (FuncState *fs, int base, int nelems, int tostore) { | 1698 | void luaK_setlist (FuncState *fs, int base, int nelems, int tostore) { |
1683 | int c = (nelems - 1)/LFIELDS_PER_FLUSH + 1; | ||
1684 | int b = (tostore == LUA_MULTRET) ? 0 : tostore; | ||
1685 | lua_assert(tostore != 0 && tostore <= LFIELDS_PER_FLUSH); | 1699 | lua_assert(tostore != 0 && tostore <= LFIELDS_PER_FLUSH); |
1686 | if (c <= MAXARG_C) | 1700 | if (tostore == LUA_MULTRET) |
1687 | luaK_codeABC(fs, OP_SETLIST, base, b, c); | 1701 | tostore = 0; |
1688 | else if (c <= MAXARG_Ax) { | 1702 | if (nelems <= MAXARG_C) |
1689 | luaK_codeABC(fs, OP_SETLIST, base, b, 0); | 1703 | luaK_codeABC(fs, OP_SETLIST, base, tostore, nelems); |
1690 | luaK_codeextraarg(fs, c); | 1704 | else { |
1705 | int extra = nelems / (MAXARG_C + 1); | ||
1706 | nelems %= (MAXARG_C + 1); | ||
1707 | luaK_codeABCk(fs, OP_SETLIST, base, tostore, nelems, 1); | ||
1708 | codeextraarg(fs, extra); | ||
1691 | } | 1709 | } |
1692 | else | ||
1693 | luaX_syntaxerror(fs->ls, "constructor too long"); | ||
1694 | fs->freereg = base + 1; /* free registers with list values */ | 1710 | fs->freereg = base + 1; /* free registers with list values */ |
1695 | } | 1711 | } |
1696 | 1712 | ||
@@ -51,11 +51,11 @@ typedef enum UnOpr { OPR_MINUS, OPR_BNOT, OPR_NOT, OPR_LEN, OPR_NOUNOPR } UnOpr; | |||
51 | 51 | ||
52 | #define luaK_jumpto(fs,t) luaK_patchlist(fs, luaK_jump(fs), t) | 52 | #define luaK_jumpto(fs,t) luaK_patchlist(fs, luaK_jump(fs), t) |
53 | 53 | ||
54 | LUAI_FUNC int luaK_code (FuncState *fs, Instruction i); | ||
54 | LUAI_FUNC int luaK_codeABx (FuncState *fs, OpCode o, int A, unsigned int Bx); | 55 | LUAI_FUNC int luaK_codeABx (FuncState *fs, OpCode o, int A, unsigned int Bx); |
55 | LUAI_FUNC int luaK_codeAsBx (FuncState *fs, OpCode o, int A, int Bx); | 56 | LUAI_FUNC int luaK_codeAsBx (FuncState *fs, OpCode o, int A, int Bx); |
56 | LUAI_FUNC int luaK_codeABCk (FuncState *fs, OpCode o, int A, | 57 | LUAI_FUNC int luaK_codeABCk (FuncState *fs, OpCode o, int A, |
57 | int B, int C, int k); | 58 | int B, int C, int k); |
58 | LUAI_FUNC int luaK_codeextraarg (FuncState *fs, int a); | ||
59 | LUAI_FUNC int luaK_isKint (expdesc *e); | 59 | LUAI_FUNC int luaK_isKint (expdesc *e); |
60 | LUAI_FUNC int luaK_exp2const (FuncState *fs, const expdesc *e, TValue *v); | 60 | LUAI_FUNC int luaK_exp2const (FuncState *fs, const expdesc *e, TValue *v); |
61 | LUAI_FUNC void luaK_fixline (FuncState *fs, int line); | 61 | LUAI_FUNC void luaK_fixline (FuncState *fs, int line); |
@@ -87,6 +87,8 @@ LUAI_FUNC void luaK_prefix (FuncState *fs, UnOpr op, expdesc *v, int line); | |||
87 | LUAI_FUNC void luaK_infix (FuncState *fs, BinOpr op, expdesc *v); | 87 | LUAI_FUNC void luaK_infix (FuncState *fs, BinOpr op, expdesc *v); |
88 | LUAI_FUNC void luaK_posfix (FuncState *fs, BinOpr op, expdesc *v1, | 88 | LUAI_FUNC void luaK_posfix (FuncState *fs, BinOpr op, expdesc *v1, |
89 | expdesc *v2, int line); | 89 | expdesc *v2, int line); |
90 | LUAI_FUNC void luaK_settablesize (FuncState *fs, int pc, | ||
91 | int ra, int rb, int rc); | ||
90 | LUAI_FUNC void luaK_setlist (FuncState *fs, int base, int nelems, int tostore); | 92 | LUAI_FUNC void luaK_setlist (FuncState *fs, int base, int nelems, int tostore); |
91 | LUAI_FUNC void luaK_finish (FuncState *fs); | 93 | LUAI_FUNC void luaK_finish (FuncState *fs); |
92 | LUAI_FUNC l_noret luaK_semerror (LexState *ls, const char *msg); | 94 | LUAI_FUNC l_noret luaK_semerror (LexState *ls, const char *msg); |
@@ -214,7 +214,7 @@ OP_SETTABLE,/* A B C R(A)[R(B)] := RK(C) */ | |||
214 | OP_SETI,/* A B C R(A)[B] := RK(C) */ | 214 | OP_SETI,/* A B C R(A)[B] := RK(C) */ |
215 | OP_SETFIELD,/* A B C R(A)[K(B):string] := RK(C) */ | 215 | OP_SETFIELD,/* A B C R(A)[K(B):string] := RK(C) */ |
216 | 216 | ||
217 | OP_NEWTABLE,/* A B C R(A) := {} (size = B,C) */ | 217 | OP_NEWTABLE,/* A B C R(A) := {} */ |
218 | 218 | ||
219 | OP_SELF,/* A B C R(A+1) := R(B); R(A) := R(B)[RK(C):string] */ | 219 | OP_SELF,/* A B C R(A+1) := R(B); R(A) := R(B)[RK(C):string] */ |
220 | 220 | ||
@@ -321,12 +321,17 @@ OP_EXTRAARG/* Ax extra (larger) argument for previous opcode */ | |||
321 | 321 | ||
322 | (*) In OP_RETURN, if (B == 0) then return up to 'top'. | 322 | (*) In OP_RETURN, if (B == 0) then return up to 'top'. |
323 | 323 | ||
324 | (*) In OP_SETLIST, if (B == 0) then real B = 'top'; if (C == 0) then | 324 | (*) In OP_LOADKX and OP_NEWTABLE, the next instruction is always |
325 | next 'instruction' is EXTRAARG(real C). | ||
326 | |||
327 | (*) In OP_LOADKX and OP_NEWTABLE, the next 'instruction' is always | ||
328 | EXTRAARG. | 325 | EXTRAARG. |
329 | 326 | ||
327 | (*) In OP_SETLIST, if (B == 0) then real B = 'top'; if k, then | ||
328 | real C = EXTRAARG _ C (the bits of EXTRAARG concatenated with the | ||
329 | bits of C). | ||
330 | |||
331 | (*) In OP_NEWTABLE, B is log2 of the hash size (which is always a | ||
332 | power of 2) plus 1, or zero for size zero. If not k, the array size | ||
333 | is C. Otherwise, the array size is EXTRAARG _ C. | ||
334 | |||
330 | (*) For comparisons, k specifies what condition the test should accept | 335 | (*) For comparisons, k specifies what condition the test should accept |
331 | (true or false). | 336 | (true or false). |
332 | 337 | ||
@@ -375,12 +380,4 @@ LUAI_DDEC(const lu_byte luaP_opmodes[NUM_OPCODES];) | |||
375 | /* number of list items to accumulate before a SETLIST instruction */ | 380 | /* number of list items to accumulate before a SETLIST instruction */ |
376 | #define LFIELDS_PER_FLUSH 50 | 381 | #define LFIELDS_PER_FLUSH 50 |
377 | 382 | ||
378 | |||
379 | /* | ||
380 | ** In OP_NEWTABLE, array sizes smaller than LIMTABSZ are represented | ||
381 | ** directly in R(B). Otherwise, array size is given by | ||
382 | ** (R(B) - LIMTABSZ) + EXTRAARG * LFIELDS_PER_FLUSH | ||
383 | */ | ||
384 | #define LIMTABSZ (MAXARG_B - LFIELDS_PER_FLUSH) | ||
385 | |||
386 | #endif | 383 | #endif |
@@ -815,7 +815,7 @@ typedef struct ConsControl { | |||
815 | expdesc v; /* last list item read */ | 815 | expdesc v; /* last list item read */ |
816 | expdesc *t; /* table descriptor */ | 816 | expdesc *t; /* table descriptor */ |
817 | int nh; /* total number of 'record' elements */ | 817 | int nh; /* total number of 'record' elements */ |
818 | int na; /* total number of array elements */ | 818 | int na; /* number of array elements already stored */ |
819 | int tostore; /* number of array elements pending to be stored */ | 819 | int tostore; /* number of array elements pending to be stored */ |
820 | } ConsControl; | 820 | } ConsControl; |
821 | 821 | ||
@@ -847,6 +847,7 @@ static void closelistfield (FuncState *fs, ConsControl *cc) { | |||
847 | cc->v.k = VVOID; | 847 | cc->v.k = VVOID; |
848 | if (cc->tostore == LFIELDS_PER_FLUSH) { | 848 | if (cc->tostore == LFIELDS_PER_FLUSH) { |
849 | luaK_setlist(fs, cc->t->u.info, cc->na, cc->tostore); /* flush */ | 849 | luaK_setlist(fs, cc->t->u.info, cc->na, cc->tostore); /* flush */ |
850 | cc->na += cc->tostore; | ||
850 | cc->tostore = 0; /* no more items pending */ | 851 | cc->tostore = 0; /* no more items pending */ |
851 | } | 852 | } |
852 | } | 853 | } |
@@ -864,13 +865,13 @@ static void lastlistfield (FuncState *fs, ConsControl *cc) { | |||
864 | luaK_exp2nextreg(fs, &cc->v); | 865 | luaK_exp2nextreg(fs, &cc->v); |
865 | luaK_setlist(fs, cc->t->u.info, cc->na, cc->tostore); | 866 | luaK_setlist(fs, cc->t->u.info, cc->na, cc->tostore); |
866 | } | 867 | } |
868 | cc->na += cc->tostore; | ||
867 | } | 869 | } |
868 | 870 | ||
869 | 871 | ||
870 | static void listfield (LexState *ls, ConsControl *cc) { | 872 | static void listfield (LexState *ls, ConsControl *cc) { |
871 | /* listfield -> exp */ | 873 | /* listfield -> exp */ |
872 | expr(ls, &cc->v); | 874 | expr(ls, &cc->v); |
873 | cc->na++; | ||
874 | cc->tostore++; | 875 | cc->tostore++; |
875 | } | 876 | } |
876 | 877 | ||
@@ -897,22 +898,6 @@ static void field (LexState *ls, ConsControl *cc) { | |||
897 | } | 898 | } |
898 | 899 | ||
899 | 900 | ||
900 | static void settablesize (FuncState *fs, ConsControl *cc, int pc) { | ||
901 | Instruction *inst = &fs->f->code[pc]; | ||
902 | int rc = (cc->nh == 0) ? 0 : luaO_ceillog2(cc->nh) + 1; | ||
903 | int rb = cc->na; | ||
904 | int extra = 0; | ||
905 | if (rb >= LIMTABSZ) { | ||
906 | extra = rb / LFIELDS_PER_FLUSH; | ||
907 | rb = rb % LFIELDS_PER_FLUSH + LIMTABSZ; | ||
908 | checklimit(fs, extra, MAXARG_Ax, "items in a constructor"); | ||
909 | } | ||
910 | SETARG_C(*inst, rc); /* set initial table size */ | ||
911 | SETARG_B(*inst, rb); /* set initial array size */ | ||
912 | SETARG_Ax(*(inst + 1), extra); | ||
913 | } | ||
914 | |||
915 | |||
916 | static void constructor (LexState *ls, expdesc *t) { | 901 | static void constructor (LexState *ls, expdesc *t) { |
917 | /* constructor -> '{' [ field { sep field } [sep] ] '}' | 902 | /* constructor -> '{' [ field { sep field } [sep] ] '}' |
918 | sep -> ',' | ';' */ | 903 | sep -> ',' | ';' */ |
@@ -920,12 +905,12 @@ static void constructor (LexState *ls, expdesc *t) { | |||
920 | int line = ls->linenumber; | 905 | int line = ls->linenumber; |
921 | int pc = luaK_codeABC(fs, OP_NEWTABLE, 0, 0, 0); | 906 | int pc = luaK_codeABC(fs, OP_NEWTABLE, 0, 0, 0); |
922 | ConsControl cc; | 907 | ConsControl cc; |
923 | luaK_codeextraarg(fs, 0); | 908 | luaK_code(fs, 0); /* space for extra arg. */ |
924 | cc.na = cc.nh = cc.tostore = 0; | 909 | cc.na = cc.nh = cc.tostore = 0; |
925 | cc.t = t; | 910 | cc.t = t; |
926 | init_exp(t, VRELOC, pc); | 911 | init_exp(t, VNONRELOC, fs->freereg); /* table will be at stack top */ |
912 | luaK_reserveregs(fs, 1); | ||
927 | init_exp(&cc.v, VVOID, 0); /* no value (yet) */ | 913 | init_exp(&cc.v, VVOID, 0); /* no value (yet) */ |
928 | luaK_exp2nextreg(ls->fs, t); /* fix it at stack top */ | ||
929 | checknext(ls, '{'); | 914 | checknext(ls, '{'); |
930 | do { | 915 | do { |
931 | lua_assert(cc.v.k == VVOID || cc.tostore > 0); | 916 | lua_assert(cc.v.k == VVOID || cc.tostore > 0); |
@@ -935,7 +920,7 @@ static void constructor (LexState *ls, expdesc *t) { | |||
935 | } while (testnext(ls, ',') || testnext(ls, ';')); | 920 | } while (testnext(ls, ',') || testnext(ls, ';')); |
936 | check_match(ls, '}', '{', line); | 921 | check_match(ls, '}', '{', line); |
937 | lastlistfield(fs, &cc); | 922 | lastlistfield(fs, &cc); |
938 | settablesize(fs, &cc, pc); | 923 | luaK_settablesize(fs, pc, t->u.info, cc.na, cc.nh); |
939 | } | 924 | } |
940 | 925 | ||
941 | /* }====================================================================== */ | 926 | /* }====================================================================== */ |
@@ -1247,18 +1247,19 @@ void luaV_execute (lua_State *L, CallInfo *ci) { | |||
1247 | vmbreak; | 1247 | vmbreak; |
1248 | } | 1248 | } |
1249 | vmcase(OP_NEWTABLE) { | 1249 | vmcase(OP_NEWTABLE) { |
1250 | int b = GETARG_B(i); | 1250 | int b = GETARG_B(i); /* log2(hash size) + 1 */ |
1251 | int c = GETARG_C(i); | 1251 | int c = GETARG_C(i); /* array size */ |
1252 | Table *t; | 1252 | Table *t; |
1253 | c = (c == 0) ? 0 : 1 << (c - 1); /* size is 2^c */ | 1253 | if (b > 0) |
1254 | if (b >= LIMTABSZ) | 1254 | b = 1 << (b - 1); /* size is 2^(b - 1) */ |
1255 | b += LFIELDS_PER_FLUSH * GETARG_Ax(*pc) - LIMTABSZ; | 1255 | if (TESTARG_k(i)) |
1256 | c += GETARG_Ax(*pc) * (MAXARG_C + 1); | ||
1256 | pc++; /* skip extra argument */ | 1257 | pc++; /* skip extra argument */ |
1257 | L->top = ci->top; /* correct top in case of GC */ | 1258 | L->top = ci->top; /* correct top in case of GC */ |
1258 | t = luaH_new(L); /* memory allocation */ | 1259 | t = luaH_new(L); /* memory allocation */ |
1259 | sethvalue2s(L, ra, t); | 1260 | sethvalue2s(L, ra, t); |
1260 | if (b != 0 || c != 0) | 1261 | if (b != 0 || c != 0) |
1261 | luaH_resize(L, t, b, c); /* idem */ | 1262 | luaH_resize(L, t, c, b); /* idem */ |
1262 | checkGC(L, ra + 1); | 1263 | checkGC(L, ra + 1); |
1263 | vmbreak; | 1264 | vmbreak; |
1264 | } | 1265 | } |
@@ -1763,18 +1764,17 @@ void luaV_execute (lua_State *L, CallInfo *ci) { | |||
1763 | } | 1764 | } |
1764 | vmcase(OP_SETLIST) { | 1765 | vmcase(OP_SETLIST) { |
1765 | int n = GETARG_B(i); | 1766 | int n = GETARG_B(i); |
1766 | int c = GETARG_C(i); | 1767 | unsigned int last = GETARG_C(i); |
1767 | unsigned int last; | 1768 | Table *h = hvalue(s2v(ra)); |
1768 | Table *h; | ||
1769 | if (n == 0) | 1769 | if (n == 0) |
1770 | n = cast_int(L->top - ra) - 1; | 1770 | n = cast_int(L->top - ra) - 1; /* get up to the top */ |
1771 | else | 1771 | else |
1772 | L->top = ci->top; /* correct top in case of GC */ | 1772 | L->top = ci->top; /* correct top in case of GC */ |
1773 | if (c == 0) { | 1773 | last += n; |
1774 | c = GETARG_Ax(*pc); pc++; | 1774 | if (TESTARG_k(i)) { |
1775 | last += GETARG_Ax(*pc) * (MAXARG_C + 1); | ||
1776 | pc++; | ||
1775 | } | 1777 | } |
1776 | h = hvalue(s2v(ra)); | ||
1777 | last = ((c-1)*LFIELDS_PER_FLUSH) + n; | ||
1778 | if (last > luaH_realasize(h)) /* needs more space? */ | 1778 | if (last > luaH_realasize(h)) /* needs more space? */ |
1779 | luaH_resizearray(L, h, last); /* preallocate it at once */ | 1779 | luaH_resizearray(L, h, last); /* preallocate it at once */ |
1780 | for (; n > 0; n--) { | 1780 | for (; n > 0; n--) { |
diff --git a/testes/nextvar.lua b/testes/nextvar.lua index bdc9fc29..a7fe625e 100644 --- a/testes/nextvar.lua +++ b/testes/nextvar.lua | |||
@@ -80,15 +80,23 @@ local sizes = {0, 1, 2, 3, 4, 5, 7, 8, 9, 15, 16, 17, | |||
80 | 80 | ||
81 | for _, sa in ipairs(sizes) do -- 'sa' is size of the array part | 81 | for _, sa in ipairs(sizes) do -- 'sa' is size of the array part |
82 | local arr = {"return {"} | 82 | local arr = {"return {"} |
83 | -- array part | 83 | for i = 1, sa do arr[1 + i] = "1," end -- build array part |
84 | for i = 1, sa do arr[1 + i] = "1," end | ||
85 | for _, sh in ipairs(sizes) do -- 'sh' is size of the hash part | 84 | for _, sh in ipairs(sizes) do -- 'sh' is size of the hash part |
86 | for j = 1, sh do -- hash part | 85 | for j = 1, sh do -- build hash part |
87 | arr[1 + sa + j] = string.format('k%x=%d,', j, j) | 86 | arr[1 + sa + j] = string.format('k%x=%d,', j, j) |
88 | end | 87 | end |
89 | arr[1 + sa + sh + 1] = "}" | 88 | arr[1 + sa + sh + 1] = "}" |
90 | local prog = table.concat(arr) | 89 | local prog = table.concat(arr) |
91 | local t = assert(load(prog))() | 90 | local f = assert(load(prog)) |
91 | f() -- call once to ensure stack space | ||
92 | -- make sure table is not resized after being created | ||
93 | if sa == 0 or sh == 0 then | ||
94 | T.alloccount(2); -- header + array or hash part | ||
95 | else | ||
96 | T.alloccount(3); -- header + array part + hash part | ||
97 | end | ||
98 | local t = f() | ||
99 | T.alloccount(); | ||
92 | assert(#t == sa) | 100 | assert(#t == sa) |
93 | check(t, sa, mp2(sh)) | 101 | check(t, sa, mp2(sh)) |
94 | end | 102 | end |
@@ -99,12 +107,12 @@ end | |||
99 | local a = {} | 107 | local a = {} |
100 | for i=1,sizes[#sizes] do a[i] = i end -- build auxiliary table | 108 | for i=1,sizes[#sizes] do a[i] = i end -- build auxiliary table |
101 | for k in ipairs(sizes) do | 109 | for k in ipairs(sizes) do |
102 | local a = {table.unpack(a,1,k)} | 110 | local t = {table.unpack(a,1,k)} |
103 | assert(#a == k) | 111 | assert(#t == k) |
104 | check(a, k, 0) | 112 | check(t, k, 0) |
105 | a = {1,2,3,table.unpack(a,1,k)} | 113 | t = {1,2,3,table.unpack(a,1,k)} |
106 | check(a, k+3, 0) | 114 | check(t, k+3, 0) |
107 | assert(#a == k + 3) | 115 | assert(#t == k + 3) |
108 | end | 116 | end |
109 | 117 | ||
110 | 118 | ||