diff options
| -rw-r--r-- | lapi.c | 18 | ||||
| -rw-r--r-- | lcode.c | 1045 | ||||
| -rw-r--r-- | lcode.h | 49 | ||||
| -rw-r--r-- | ldebug.c | 360 | ||||
| -rw-r--r-- | ldebug.h | 27 | ||||
| -rw-r--r-- | lfunc.c | 11 | ||||
| -rw-r--r-- | lgc.c | 8 | ||||
| -rw-r--r-- | llimits.h | 89 | ||||
| -rw-r--r-- | lobject.h | 8 | ||||
| -rw-r--r-- | lopcodes.h | 219 | ||||
| -rw-r--r-- | lparser.c | 558 | ||||
| -rw-r--r-- | lparser.h | 32 | ||||
| -rw-r--r-- | ltests.c | 133 | ||||
| -rw-r--r-- | lvm.c | 476 | ||||
| -rw-r--r-- | lvm.h | 7 |
15 files changed, 1599 insertions, 1441 deletions
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lapi.c,v 1.140 2001/04/17 17:35:54 roberto Exp roberto $ | 2 | ** $Id: lapi.c,v 1.141 2001/04/23 16:35:45 roberto Exp roberto $ |
| 3 | ** Lua API | 3 | ** Lua API |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -184,9 +184,10 @@ LUA_API int lua_iscfunction (lua_State *L, int index) { | |||
| 184 | LUA_API int lua_isnumber (lua_State *L, int index) { | 184 | LUA_API int lua_isnumber (lua_State *L, int index) { |
| 185 | TObject *o; | 185 | TObject *o; |
| 186 | int i; | 186 | int i; |
| 187 | TObject n; | ||
| 187 | lua_lock(L); | 188 | lua_lock(L); |
| 188 | o = luaA_indexAcceptable(L, index); | 189 | o = luaA_indexAcceptable(L, index); |
| 189 | i = (o == NULL) ? 0 : (tonumber(o) == 0); | 190 | i = (o != NULL && (ttype(o) == LUA_TNUMBER || luaV_tonumber(o, &n))); |
| 190 | lua_unlock(L); | 191 | lua_unlock(L); |
| 191 | return i; | 192 | return i; |
| 192 | } | 193 | } |
| @@ -234,13 +235,18 @@ LUA_API int lua_lessthan (lua_State *L, int index1, int index2) { | |||
| 234 | 235 | ||
| 235 | 236 | ||
| 236 | LUA_API lua_Number lua_tonumber (lua_State *L, int index) { | 237 | LUA_API lua_Number lua_tonumber (lua_State *L, int index) { |
| 237 | StkId o; | 238 | const TObject *o; |
| 238 | lua_Number n; | 239 | TObject n; |
| 240 | lua_Number res; | ||
| 239 | lua_lock(L); | 241 | lua_lock(L); |
| 240 | o = luaA_indexAcceptable(L, index); | 242 | o = luaA_indexAcceptable(L, index); |
| 241 | n = (o == NULL || tonumber(o)) ? 0 : nvalue(o); | 243 | if (o != NULL && |
| 244 | (ttype(o) == LUA_TNUMBER || (o = luaV_tonumber(o, &n)) != NULL)) | ||
| 245 | res = nvalue(o); | ||
| 246 | else | ||
| 247 | res = 0; | ||
| 242 | lua_unlock(L); | 248 | lua_unlock(L); |
| 243 | return n; | 249 | return res; |
| 244 | } | 250 | } |
| 245 | 251 | ||
| 246 | LUA_API const l_char *lua_tostring (lua_State *L, int index) { | 252 | LUA_API const l_char *lua_tostring (lua_State *L, int index) { |
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lcode.c,v 1.67 2001/04/06 18:25:00 roberto Exp roberto $ | 2 | ** $Id: lcode.c,v 1.68 2001/04/23 16:35:45 roberto Exp roberto $ |
| 3 | ** Code generator for Lua | 3 | ** Code generator for Lua |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -11,6 +11,7 @@ | |||
| 11 | #include "lua.h" | 11 | #include "lua.h" |
| 12 | 12 | ||
| 13 | #include "lcode.h" | 13 | #include "lcode.h" |
| 14 | #include "ldebug.h" | ||
| 14 | #include "ldo.h" | 15 | #include "ldo.h" |
| 15 | #include "llex.h" | 16 | #include "llex.h" |
| 16 | #include "lmem.h" | 17 | #include "lmem.h" |
| @@ -19,6 +20,12 @@ | |||
| 19 | #include "lparser.h" | 20 | #include "lparser.h" |
| 20 | 21 | ||
| 21 | 22 | ||
| 23 | #define hasjumps(e) ((e)->t != (e)->f) | ||
| 24 | |||
| 25 | #define getcode(fs,e) ((fs)->f->code[(e)->u.i.info]) | ||
| 26 | |||
| 27 | |||
| 28 | |||
| 22 | void luaK_error (LexState *ls, const l_char *msg) { | 29 | void luaK_error (LexState *ls, const l_char *msg) { |
| 23 | luaX_error(ls, msg, ls->t.token); | 30 | luaX_error(ls, msg, ls->t.token); |
| 24 | } | 31 | } |
| @@ -33,12 +40,27 @@ static Instruction previous_instruction (FuncState *fs) { | |||
| 33 | if (fs->pc > fs->lasttarget) /* no jumps to current position? */ | 40 | if (fs->pc > fs->lasttarget) /* no jumps to current position? */ |
| 34 | return fs->f->code[fs->pc-1]; /* returns previous instruction */ | 41 | return fs->f->code[fs->pc-1]; /* returns previous instruction */ |
| 35 | else | 42 | else |
| 36 | return CREATE_0(-1); /* no optimizations after an invalid instruction */ | 43 | return (Instruction)(-1);/* no optimizations after an invalid instruction */ |
| 44 | } | ||
| 45 | |||
| 46 | |||
| 47 | void luaK_nil (FuncState *fs, int from, int n) { | ||
| 48 | Instruction previous = previous_instruction(fs); | ||
| 49 | if (GET_OPCODE(previous) == OP_LOADNIL) { | ||
| 50 | int pfrom = GETARG_A(previous); | ||
| 51 | int pto = GETARG_B(previous); | ||
| 52 | if (pfrom <= from && from <= pto+1) { /* can connect both? */ | ||
| 53 | if (from+n-1 > pto) | ||
| 54 | SETARG_B(fs->f->code[fs->pc-1], from+n-1); | ||
| 55 | return; | ||
| 56 | } | ||
| 57 | } | ||
| 58 | luaK_codeABC(fs, OP_LOADNIL, from, from+n-1, 0); /* else no optimization */ | ||
| 37 | } | 59 | } |
| 38 | 60 | ||
| 39 | 61 | ||
| 40 | int luaK_jump (FuncState *fs) { | 62 | int luaK_jump (FuncState *fs) { |
| 41 | int j = luaK_code1(fs, OP_JMP, NO_JUMP); | 63 | int j = luaK_codeAsBc(fs, OP_JMP, 0, NO_JUMP); |
| 42 | if (j == fs->lasttarget) { /* possible jumps to this jump? */ | 64 | if (j == fs->lasttarget) { /* possible jumps to this jump? */ |
| 43 | luaK_concat(fs, &j, fs->jlt); /* keep them on hold */ | 65 | luaK_concat(fs, &j, fs->jlt); /* keep them on hold */ |
| 44 | fs->jlt = NO_JUMP; | 66 | fs->jlt = NO_JUMP; |
| @@ -47,36 +69,33 @@ int luaK_jump (FuncState *fs) { | |||
| 47 | } | 69 | } |
| 48 | 70 | ||
| 49 | 71 | ||
| 72 | static int luaK_condjump (FuncState *fs, OpCode op, int B, int C) { | ||
| 73 | luaK_codeABC(fs, op, NO_REG, B, C); | ||
| 74 | return luaK_codeAsBc(fs, OP_CJMP, 0, NO_JUMP); | ||
| 75 | } | ||
| 76 | |||
| 77 | |||
| 50 | static void luaK_fixjump (FuncState *fs, int pc, int dest) { | 78 | static void luaK_fixjump (FuncState *fs, int pc, int dest) { |
| 51 | Instruction *jmp = &fs->f->code[pc]; | 79 | Instruction *jmp = &fs->f->code[pc]; |
| 52 | if (dest == NO_JUMP) | 80 | if (dest == NO_JUMP) |
| 53 | SETARG_S(*jmp, NO_JUMP); /* point to itself to represent end of list */ | 81 | SETARG_sBc(*jmp, NO_JUMP); /* point to itself to represent end of list */ |
| 54 | else { /* jump is relative to position following jump instruction */ | 82 | else { /* jump is relative to position following jump instruction */ |
| 55 | int offset = dest-(pc+1); | 83 | int offset = dest-(pc+1); |
| 56 | if (abs(offset) > MAXARG_S) | 84 | if (abs(offset) > MAXARG_sBc) |
| 57 | luaK_error(fs->ls, l_s("control structure too long")); | 85 | luaK_error(fs->ls, l_s("control structure too long")); |
| 58 | SETARG_S(*jmp, offset); | 86 | SETARG_sBc(*jmp, offset); |
| 59 | } | 87 | } |
| 60 | } | 88 | } |
| 61 | 89 | ||
| 62 | 90 | ||
| 63 | /* | 91 | /* |
| 64 | ** prep-for instructions (OP_FORPREP & OP_LFORPREP) have a negated jump, | 92 | ** prep-for instructions (OP_FORPREP & OP_TFORPREP) have a negated jump, |
| 65 | ** as they simulate the real jump... | 93 | ** as they simulate the real jump... |
| 66 | */ | 94 | */ |
| 67 | void luaK_fixfor (FuncState *fs, int pc, int dest) { | 95 | void luaK_fixfor (FuncState *fs, int pc, int dest) { |
| 68 | Instruction *jmp = &fs->f->code[pc]; | 96 | Instruction *jmp = &fs->f->code[pc]; |
| 69 | int offset = dest-(pc+1); | 97 | int offset = dest-(pc+1); |
| 70 | SETARG_S(*jmp, -offset); | 98 | SETARG_sBc(*jmp, -offset); |
| 71 | } | ||
| 72 | |||
| 73 | |||
| 74 | static int luaK_getjump (FuncState *fs, int pc) { | ||
| 75 | int offset = GETARG_S(fs->f->code[pc]); | ||
| 76 | if (offset == NO_JUMP) /* point to itself represents end of list */ | ||
| 77 | return NO_JUMP; /* end of list */ | ||
| 78 | else | ||
| 79 | return (pc+1)+offset; /* turn offset into absolute position */ | ||
| 80 | } | 99 | } |
| 81 | 100 | ||
| 82 | 101 | ||
| @@ -96,609 +115,677 @@ int luaK_getlabel (FuncState *fs) { | |||
| 96 | } | 115 | } |
| 97 | 116 | ||
| 98 | 117 | ||
| 99 | void luaK_deltastack (FuncState *fs, int delta) { | 118 | static int luaK_getjump (FuncState *fs, int pc) { |
| 100 | fs->stacklevel += delta; | 119 | int offset = GETARG_sBc(fs->f->code[pc]); |
| 101 | if (fs->stacklevel > fs->f->maxstacksize) { | 120 | if (offset == NO_JUMP) /* point to itself represents end of list */ |
| 102 | if (fs->stacklevel > MAXSTACK) | 121 | return NO_JUMP; /* end of list */ |
| 103 | luaK_error(fs->ls, l_s("function or expression too complex")); | 122 | else |
| 104 | fs->f->maxstacksize = (short)fs->stacklevel; | 123 | return (pc+1)+offset; /* turn offset into absolute position */ |
| 105 | } | ||
| 106 | } | 124 | } |
| 107 | 125 | ||
| 108 | 126 | ||
| 109 | void luaK_kstr (LexState *ls, int c) { | 127 | static Instruction *getjumpcontrol (FuncState *fs, int pc) { |
| 110 | luaK_code1(ls->fs, OP_PUSHSTRING, c); | 128 | Instruction *pi = &fs->f->code[pc]; |
| 129 | OpCode op = GET_OPCODE(*pi); | ||
| 130 | if (op == OP_CJMP) | ||
| 131 | return pi-1; | ||
| 132 | else { | ||
| 133 | lua_assert(op == OP_JMP || op == OP_FORLOOP || op == OP_TFORLOOP); | ||
| 134 | return pi; | ||
| 135 | } | ||
| 111 | } | 136 | } |
| 112 | 137 | ||
| 113 | 138 | ||
| 114 | static int number_constant (FuncState *fs, lua_Number r) { | 139 | static int need_value (FuncState *fs, int list, OpCode op) { |
| 115 | /* check whether `r' has appeared within the last LOOKBACKNUMS entries */ | 140 | /* check whether list has any jump different from `op' */ |
| 116 | Proto *f = fs->f; | 141 | for (; list != NO_JUMP; list = luaK_getjump(fs, list)) |
| 117 | int c = fs->nknum; | 142 | if (GET_OPCODE(*getjumpcontrol(fs, list)) != op) return 1; |
| 118 | int lim = c < LOOKBACKNUMS ? 0 : c-LOOKBACKNUMS; | 143 | return 0; /* not found */ |
| 119 | while (--c >= lim) | ||
| 120 | if (f->knum[c] == r) return c; | ||
| 121 | /* not found; create a new entry */ | ||
| 122 | luaM_growvector(fs->L, f->knum, fs->nknum, f->sizeknum, lua_Number, | ||
| 123 | MAXARG_U, l_s("constant table overflow")); | ||
| 124 | c = fs->nknum++; | ||
| 125 | f->knum[c] = r; | ||
| 126 | return c; | ||
| 127 | } | 144 | } |
| 128 | 145 | ||
| 129 | 146 | ||
| 130 | void luaK_number (FuncState *fs, lua_Number f) { | 147 | static void luaK_patchlistaux (FuncState *fs, int list, |
| 131 | if (f <= (lua_Number)MAXARG_S && (lua_Number)(int)f == f) | 148 | int ttarget, int treg, int ftarget, int freg, int dtarget) { |
| 132 | luaK_code1(fs, OP_PUSHINT, (int)f); /* f has a short integer value */ | 149 | while (list != NO_JUMP) { |
| 133 | else | 150 | int next = luaK_getjump(fs, list); |
| 134 | luaK_code1(fs, OP_PUSHNUM, number_constant(fs, f)); | 151 | Instruction *i = getjumpcontrol(fs, list); |
| 152 | switch (GET_OPCODE(*i)) { | ||
| 153 | case OP_TESTT: { | ||
| 154 | SETARG_A(*i, treg); | ||
| 155 | luaK_fixjump(fs, list, ttarget); | ||
| 156 | break; | ||
| 157 | } | ||
| 158 | case OP_TESTF: { | ||
| 159 | SETARG_A(*i, freg); | ||
| 160 | luaK_fixjump(fs, list, ftarget); | ||
| 161 | break; | ||
| 162 | } | ||
| 163 | default: { | ||
| 164 | luaK_fixjump(fs, list, dtarget); /* jump to default target */ | ||
| 165 | break; | ||
| 166 | } | ||
| 167 | } | ||
| 168 | list = next; | ||
| 169 | } | ||
| 135 | } | 170 | } |
| 136 | 171 | ||
| 137 | 172 | ||
| 138 | void luaK_adjuststack (FuncState *fs, int n) { | 173 | void luaK_patchlist (FuncState *fs, int list, int target) { |
| 139 | if (n > 0) | 174 | if (target == fs->lasttarget) /* same target that list `jlt'? */ |
| 140 | luaK_code1(fs, OP_POP, n); | 175 | luaK_concat(fs, &fs->jlt, list); /* delay fixing */ |
| 141 | else | 176 | else |
| 142 | luaK_code1(fs, OP_PUSHNIL, -n); | 177 | luaK_patchlistaux(fs, list, target, NO_REG, target, NO_REG, target); |
| 143 | } | 178 | } |
| 144 | 179 | ||
| 145 | 180 | ||
| 146 | int luaK_lastisopen (FuncState *fs) { | 181 | void luaK_concat (FuncState *fs, int *l1, int l2) { |
| 147 | /* check whether last instruction is an open function call */ | 182 | if (*l1 == NO_JUMP) |
| 148 | Instruction i = previous_instruction(fs); | 183 | *l1 = l2; |
| 149 | if (GET_OPCODE(i) == OP_CALL && GETARG_B(i) == MULT_RET) | 184 | else { |
| 150 | return 1; | 185 | int list = *l1; |
| 151 | else return 0; | 186 | int next; |
| 187 | while ((next = luaK_getjump(fs, list)) != NO_JUMP) /* find last element */ | ||
| 188 | list = next; | ||
| 189 | luaK_fixjump(fs, list, l2); | ||
| 190 | } | ||
| 152 | } | 191 | } |
| 153 | 192 | ||
| 154 | 193 | ||
| 155 | void luaK_setcallreturns (FuncState *fs, int nresults) { | 194 | void luaK_reserveregs (FuncState *fs, int n) { |
| 156 | if (luaK_lastisopen(fs)) { /* expression is an open function call? */ | 195 | fs->freereg += n; |
| 157 | SETARG_B(fs->f->code[fs->pc-1], nresults); /* set number of results */ | 196 | if (fs->freereg > fs->f->maxstacksize) { |
| 158 | luaK_deltastack(fs, nresults); /* push results */ | 197 | if (fs->freereg >= MAXSTACK) |
| 198 | luaK_error(fs->ls, l_s("function or expression too complex")); | ||
| 199 | fs->f->maxstacksize = (short)fs->freereg; | ||
| 159 | } | 200 | } |
| 160 | } | 201 | } |
| 161 | 202 | ||
| 162 | 203 | ||
| 163 | static int discharge (FuncState *fs, expdesc *var) { | 204 | static void freereg (FuncState *fs, int reg) { |
| 164 | switch (var->k) { | 205 | if (reg >= fs->nactloc && reg < MAXSTACK) { |
| 165 | case VLOCAL: | 206 | fs->freereg--; |
| 166 | luaK_code1(fs, OP_GETLOCAL, var->u.index); | 207 | lua_assert(reg == fs->freereg); |
| 167 | break; | ||
| 168 | case VGLOBAL: | ||
| 169 | luaK_code1(fs, OP_GETGLOBAL, var->u.index); | ||
| 170 | break; | ||
| 171 | case VINDEXED: | ||
| 172 | luaK_code0(fs, OP_GETTABLE); | ||
| 173 | break; | ||
| 174 | case VEXP: | ||
| 175 | return 0; /* nothing to do */ | ||
| 176 | } | 208 | } |
| 177 | var->k = VEXP; | ||
| 178 | var->u.l.t = var->u.l.f = NO_JUMP; | ||
| 179 | return 1; | ||
| 180 | } | 209 | } |
| 181 | 210 | ||
| 182 | 211 | ||
| 183 | static void discharge1 (FuncState *fs, expdesc *var) { | 212 | static void freeexp (FuncState *fs, expdesc *e) { |
| 184 | discharge(fs, var); | 213 | if (e->k == VNONRELOC) |
| 185 | /* if it has jumps then it is already discharged */ | 214 | freereg(fs, e->u.i.info); |
| 186 | if (var->u.l.t == NO_JUMP && var->u.l.f == NO_JUMP) | ||
| 187 | luaK_setcallreturns(fs, 1); /* call must return 1 value */ | ||
| 188 | } | 215 | } |
| 189 | 216 | ||
| 190 | 217 | ||
| 191 | void luaK_storevar (LexState *ls, const expdesc *var) { | 218 | static int addk (FuncState *fs, TObject *k) { |
| 192 | FuncState *fs = ls->fs; | 219 | Proto *f = fs->f; |
| 193 | switch (var->k) { | 220 | luaM_growvector(fs->L, f->k, fs->nk, f->sizek, TObject, |
| 194 | case VLOCAL: | 221 | MAXARG_Bc, l_s("constant table overflow")); |
| 195 | luaK_code1(fs, OP_SETLOCAL, var->u.index); | 222 | setobj(&f->k[fs->nk], k); |
| 196 | break; | 223 | return fs->nk++; |
| 197 | case VGLOBAL: | 224 | } |
| 198 | luaK_code1(fs, OP_SETGLOBAL, var->u.index); | 225 | |
| 199 | break; | 226 | |
| 200 | case VINDEXED: /* table is at top-3; pop 3 elements after operation */ | 227 | int luaK_stringk (FuncState *fs, TString *s) { |
| 201 | luaK_code2(fs, OP_SETTABLE, 3, 3); | 228 | Proto *f = fs->f; |
| 202 | break; | 229 | int c = s->u.s.constindex; |
| 203 | default: | 230 | if (c >= fs->nk || ttype(&f->k[c]) != LUA_TSTRING || tsvalue(&f->k[c]) != s) { |
| 204 | lua_assert(0); /* invalid var kind to store */ | 231 | TObject o; |
| 232 | setsvalue(&o, s); | ||
| 233 | c = addk(fs, &o); | ||
| 234 | s->u.s.constindex = c; /* hint for next time */ | ||
| 205 | } | 235 | } |
| 236 | return c; | ||
| 206 | } | 237 | } |
| 207 | 238 | ||
| 208 | 239 | ||
| 209 | static OpCode invertjump (OpCode op) { | 240 | static int number_constant (FuncState *fs, lua_Number r) { |
| 210 | switch (op) { | 241 | /* check whether `r' has appeared within the last LOOKBACKNUMS entries */ |
| 211 | case OP_JMPNE: return OP_JMPEQ; | 242 | TObject o; |
| 212 | case OP_JMPEQ: return OP_JMPNE; | 243 | Proto *f = fs->f; |
| 213 | case OP_JMPLT: return OP_JMPGE; | 244 | int c = fs->nk; |
| 214 | case OP_JMPLE: return OP_JMPGT; | 245 | int lim = c < LOOKBACKNUMS ? 0 : c-LOOKBACKNUMS; |
| 215 | case OP_JMPGT: return OP_JMPLE; | 246 | while (--c >= lim) { |
| 216 | case OP_JMPGE: return OP_JMPLT; | 247 | if (ttype(&f->k[c]) == LUA_TNUMBER && nvalue(&f->k[c]) == r) |
| 217 | case OP_JMPT: case OP_JMPONT: return OP_JMPF; | 248 | return c; |
| 218 | case OP_JMPF: case OP_JMPONF: return OP_JMPT; | ||
| 219 | default: | ||
| 220 | lua_assert(0); /* invalid jump instruction */ | ||
| 221 | return OP_JMP; /* to avoid warnings */ | ||
| 222 | } | 249 | } |
| 250 | /* not found; create a new entry */ | ||
| 251 | setnvalue(&o, r); | ||
| 252 | return addk(fs, &o); | ||
| 223 | } | 253 | } |
| 224 | 254 | ||
| 225 | 255 | ||
| 226 | static void luaK_patchlistaux (FuncState *fs, int list, int target, | 256 | void luaK_setcallreturns (FuncState *fs, expdesc *e, int nresults) { |
| 227 | OpCode special, int special_target) { | 257 | if (e->k == VCALL) { /* expression is an open function call? */ |
| 228 | Instruction *code = fs->f->code; | 258 | SETARG_C(getcode(fs, e), nresults); /* set number of results */ |
| 229 | while (list != NO_JUMP) { | 259 | if (nresults == 1) { /* `regular' expression? */ |
| 230 | int next = luaK_getjump(fs, list); | 260 | e->k = VNONRELOC; |
| 231 | Instruction *i = &code[list]; | 261 | e->u.i.info = GETARG_A(getcode(fs, e)); |
| 232 | OpCode op = GET_OPCODE(*i); | ||
| 233 | if (op == special) /* this `op' already has a value */ | ||
| 234 | luaK_fixjump(fs, list, special_target); | ||
| 235 | else { | ||
| 236 | luaK_fixjump(fs, list, target); /* do the patch */ | ||
| 237 | if (op == OP_JMPONT) /* remove eventual values */ | ||
| 238 | SET_OPCODE(*i, OP_JMPT); | ||
| 239 | else if (op == OP_JMPONF) | ||
| 240 | SET_OPCODE(*i, OP_JMPF); | ||
| 241 | } | 262 | } |
| 242 | list = next; | ||
| 243 | } | 263 | } |
| 244 | } | 264 | } |
| 245 | 265 | ||
| 246 | 266 | ||
| 247 | void luaK_patchlist (FuncState *fs, int list, int target) { | 267 | static void dischargevars (FuncState *fs, expdesc *e) { |
| 248 | if (target == fs->lasttarget) /* same target that list `jlt'? */ | 268 | switch (e->k) { |
| 249 | luaK_concat(fs, &fs->jlt, list); /* delay fixing */ | 269 | case VLOCAL: { |
| 250 | else | 270 | e->k = VNONRELOC; |
| 251 | luaK_patchlistaux(fs, list, target, OP_ADD, 0); | 271 | break; |
| 272 | } | ||
| 273 | case VGLOBAL: { | ||
| 274 | e->u.i.info = luaK_codeABc(fs, OP_GETGLOBAL, 0, e->u.i.info); | ||
| 275 | e->k = VRELOCABLE; | ||
| 276 | break; | ||
| 277 | } | ||
| 278 | case VINDEXED: { | ||
| 279 | freereg(fs, e->u.i.aux); | ||
| 280 | freereg(fs, e->u.i.info); | ||
| 281 | e->u.i.info = luaK_codeABC(fs, OP_GETTABLE, 0, e->u.i.info, e->u.i.aux); | ||
| 282 | e->k = VRELOCABLE; | ||
| 283 | break; | ||
| 284 | } | ||
| 285 | case VCALL: { | ||
| 286 | luaK_setcallreturns(fs, e, 1); | ||
| 287 | break; | ||
| 288 | } | ||
| 289 | default: break; /* there is one value available (somewhere) */ | ||
| 290 | } | ||
| 252 | } | 291 | } |
| 253 | 292 | ||
| 254 | 293 | ||
| 255 | static int need_value (FuncState *fs, int list, OpCode hasvalue) { | 294 | static int code_label (FuncState *fs, OpCode op, int A, int sBc) { |
| 256 | /* check whether list has a jump without a value */ | 295 | luaK_getlabel(fs); /* those instructions may be jump targets */ |
| 257 | for (; list != NO_JUMP; list = luaK_getjump(fs, list)) | 296 | return luaK_codeAsBc(fs, op, A, sBc); |
| 258 | if (GET_OPCODE(fs->f->code[list]) != hasvalue) return 1; | ||
| 259 | return 0; /* not found */ | ||
| 260 | } | 297 | } |
| 261 | 298 | ||
| 262 | 299 | ||
| 263 | void luaK_concat (FuncState *fs, int *l1, int l2) { | 300 | static void dischargejumps (FuncState *fs, expdesc *e, int reg) { |
| 264 | if (*l1 == NO_JUMP) | 301 | if (hasjumps(e)) { |
| 265 | *l1 = l2; | 302 | int final; /* position after whole expression */ |
| 266 | else { | 303 | int p_nil = NO_JUMP; /* position of an eventual PUSHNIL */ |
| 267 | int list = *l1; | 304 | int p_1 = NO_JUMP; /* position of an eventual PUSHINT */ |
| 268 | int next; | 305 | if (need_value(fs, e->f, OP_TESTF) || need_value(fs, e->t, OP_TESTT)) { |
| 269 | while ((next = luaK_getjump(fs, list)) != NO_JUMP) /* find last element */ | 306 | /* expression needs values */ |
| 270 | list = next; | 307 | if (e->k != VJMP) |
| 271 | luaK_fixjump(fs, list, l2); | 308 | code_label(fs, OP_JMP, 0, 2); /* to jump over both pushes */ |
| 309 | p_nil = code_label(fs, OP_NILJMP, reg, 0); | ||
| 310 | p_1 = code_label(fs, OP_LOADINT, reg, 1); | ||
| 311 | } | ||
| 312 | final = luaK_getlabel(fs); | ||
| 313 | luaK_patchlistaux(fs, e->f, p_nil, NO_REG, final, reg, p_nil); | ||
| 314 | luaK_patchlistaux(fs, e->t, final, reg, p_1, NO_REG, p_1); | ||
| 272 | } | 315 | } |
| 316 | e->f = e->t = NO_JUMP; | ||
| 273 | } | 317 | } |
| 274 | 318 | ||
| 275 | 319 | ||
| 276 | static void luaK_testgo (FuncState *fs, expdesc *v, int invert, OpCode jump) { | 320 | static void discharge2reg (FuncState *fs, expdesc *e, int reg) { |
| 277 | int prevpos; /* position of last instruction */ | 321 | dischargevars(fs, e); |
| 278 | Instruction *previous; | 322 | switch (e->k) { |
| 279 | int *golist, *exitlist; | 323 | case VNIL: { |
| 280 | if (!invert) { | 324 | luaK_nil(fs, reg, 1); |
| 281 | golist = &v->u.l.f; /* go if false */ | 325 | break; |
| 282 | exitlist = &v->u.l.t; /* exit if true */ | 326 | } |
| 283 | } | 327 | case VNUMBER: { |
| 284 | else { | 328 | lua_Number f = e->u.n; |
| 285 | golist = &v->u.l.t; /* go if true */ | 329 | int i = (int)f; |
| 286 | exitlist = &v->u.l.f; /* exit if false */ | 330 | if ((lua_Number)i == f && -MAXARG_sBc <= i && i <= MAXARG_sBc) |
| 331 | luaK_codeAsBc(fs, OP_LOADINT, reg, i); /* f has a small int value */ | ||
| 332 | else | ||
| 333 | luaK_codeABc(fs, OP_LOADK, reg, number_constant(fs, f)); | ||
| 334 | break; | ||
| 335 | } | ||
| 336 | case VK: { | ||
| 337 | luaK_codeABc(fs, OP_LOADK, reg, e->u.i.info); | ||
| 338 | break; | ||
| 339 | } | ||
| 340 | case VRELOCABLE: { | ||
| 341 | Instruction *pc = &getcode(fs, e); | ||
| 342 | SETARG_A(*pc, reg); | ||
| 343 | break; | ||
| 344 | } | ||
| 345 | default: return; | ||
| 287 | } | 346 | } |
| 288 | discharge1(fs, v); | 347 | e->u.i.info = reg; |
| 289 | prevpos = fs->pc-1; | 348 | e->k = VNONRELOC; |
| 290 | previous = &fs->f->code[prevpos]; | 349 | } |
| 291 | lua_assert(*previous==previous_instruction(fs)); /* no jump allowed here */ | 350 | |
| 292 | if (!ISJUMP(GET_OPCODE(*previous))) | 351 | |
| 293 | prevpos = luaK_code1(fs, jump, NO_JUMP); | 352 | static void discharge2anyreg (FuncState *fs, expdesc *e) { |
| 294 | else { /* last instruction is already a jump */ | 353 | if (e->k != VNONRELOC) { |
| 295 | if (invert) | 354 | luaK_reserveregs(fs, 1); |
| 296 | SET_OPCODE(*previous, invertjump(GET_OPCODE(*previous))); | 355 | discharge2reg(fs, e, fs->freereg-1); |
| 297 | } | 356 | } |
| 298 | luaK_concat(fs, exitlist, prevpos); /* insert last jump in `exitlist' */ | ||
| 299 | luaK_patchlist(fs, *golist, luaK_getlabel(fs)); | ||
| 300 | *golist = NO_JUMP; | ||
| 301 | } | 357 | } |
| 302 | 358 | ||
| 303 | 359 | ||
| 304 | void luaK_goiftrue (FuncState *fs, expdesc *v, int keepvalue) { | 360 | static void luaK_exp2reg (FuncState *fs, expdesc *e, int reg) { |
| 305 | luaK_testgo(fs, v, 1, keepvalue ? OP_JMPONF : OP_JMPF); | 361 | discharge2reg(fs, e, reg); |
| 362 | switch (e->k) { | ||
| 363 | case VVOID: { | ||
| 364 | return; /* nothing to do... */ | ||
| 365 | } | ||
| 366 | case VNONRELOC: { | ||
| 367 | if (reg != e->u.i.info) | ||
| 368 | luaK_codeABC(fs, OP_MOVE, reg, e->u.i.info, 0); | ||
| 369 | break; | ||
| 370 | } | ||
| 371 | case VJMP: { | ||
| 372 | luaK_concat(fs, &e->t, e->u.i.info); /* put this jump in `t' list */ | ||
| 373 | break; | ||
| 374 | } | ||
| 375 | default: { | ||
| 376 | lua_assert(0); /* cannot happen */ | ||
| 377 | break; | ||
| 378 | } | ||
| 379 | } | ||
| 380 | dischargejumps(fs, e, reg); | ||
| 381 | e->u.i.info = reg; | ||
| 382 | e->k = VNONRELOC; | ||
| 306 | } | 383 | } |
| 307 | 384 | ||
| 308 | 385 | ||
| 309 | static void luaK_goiffalse (FuncState *fs, expdesc *v) { | 386 | void luaK_exp2nextreg (FuncState *fs, expdesc *e) { |
| 310 | luaK_testgo(fs, v, 0, OP_JMPONT); | 387 | int reg; |
| 388 | dischargevars(fs, e); | ||
| 389 | freeexp(fs, e); | ||
| 390 | reg = fs->freereg; | ||
| 391 | luaK_reserveregs(fs, 1); | ||
| 392 | luaK_exp2reg(fs, e, reg); | ||
| 311 | } | 393 | } |
| 312 | 394 | ||
| 313 | 395 | ||
| 314 | static int code_label (FuncState *fs, OpCode op, int arg) { | 396 | int luaK_exp2anyreg (FuncState *fs, expdesc *e) { |
| 315 | luaK_getlabel(fs); /* those instructions may be jump targets */ | 397 | dischargevars(fs, e); |
| 316 | return luaK_code1(fs, op, arg); | 398 | if (e->k == VNONRELOC) { |
| 317 | } | 399 | if (!hasjumps(e)) return e->u.i.info; /* exp is already in a register */ |
| 318 | 400 | if (e->u.i.info >= fs->nactloc) { /* reg. is not a local? */ | |
| 319 | 401 | dischargejumps(fs, e, e->u.i.info); /* put value on it */ | |
| 320 | void luaK_tostack (LexState *ls, expdesc *v, int onlyone) { | 402 | return e->u.i.info; |
| 321 | FuncState *fs = ls->fs; | ||
| 322 | if (!discharge(fs, v)) { /* `v' is an expression? */ | ||
| 323 | OpCode previous = GET_OPCODE(fs->f->code[fs->pc-1]); | ||
| 324 | if (!ISJUMP(previous) && v->u.l.f == NO_JUMP && v->u.l.t == NO_JUMP) { | ||
| 325 | /* expression has no jumps */ | ||
| 326 | if (onlyone) | ||
| 327 | luaK_setcallreturns(fs, 1); /* call must return 1 value */ | ||
| 328 | } | ||
| 329 | else { /* expression has jumps */ | ||
| 330 | int final; /* position after whole expression */ | ||
| 331 | int j = NO_JUMP; /* eventual jump over values */ | ||
| 332 | int p_nil = NO_JUMP; /* position of an eventual PUSHNIL */ | ||
| 333 | int p_1 = NO_JUMP; /* position of an eventual PUSHINT */ | ||
| 334 | if (ISJUMP(previous) || need_value(fs, v->u.l.f, OP_JMPONF) | ||
| 335 | || need_value(fs, v->u.l.t, OP_JMPONT)) { | ||
| 336 | /* expression needs values */ | ||
| 337 | if (ISJUMP(previous)) | ||
| 338 | luaK_concat(fs, &v->u.l.t, fs->pc-1); /* put `previous' in t. list */ | ||
| 339 | else { | ||
| 340 | j = code_label(fs, OP_JMP, NO_JUMP); /* to jump over both pushes */ | ||
| 341 | /* correct stack for compiler and symbolic execution */ | ||
| 342 | luaK_adjuststack(fs, 1); | ||
| 343 | } | ||
| 344 | p_nil = code_label(fs, OP_PUSHNILJMP, 0); | ||
| 345 | p_1 = code_label(fs, OP_PUSHINT, 1); | ||
| 346 | luaK_patchlist(fs, j, luaK_getlabel(fs)); | ||
| 347 | } | ||
| 348 | final = luaK_getlabel(fs); | ||
| 349 | luaK_patchlistaux(fs, v->u.l.f, p_nil, OP_JMPONF, final); | ||
| 350 | luaK_patchlistaux(fs, v->u.l.t, p_1, OP_JMPONT, final); | ||
| 351 | v->u.l.f = v->u.l.t = NO_JUMP; | ||
| 352 | } | 403 | } |
| 353 | } | 404 | } |
| 405 | luaK_exp2nextreg(fs, e); /* default */ | ||
| 406 | return e->u.i.info; | ||
| 354 | } | 407 | } |
| 355 | 408 | ||
| 356 | 409 | ||
| 357 | void luaK_prefix (LexState *ls, UnOpr op, expdesc *v) { | 410 | void luaK_exp2val (FuncState *fs, expdesc *e) { |
| 358 | FuncState *fs = ls->fs; | 411 | if (hasjumps(e)) |
| 359 | if (op == OPR_MINUS) { | 412 | luaK_exp2anyreg(fs, e); |
| 360 | luaK_tostack(ls, v, 1); | 413 | else |
| 361 | luaK_code0(fs, OP_MINUS); | 414 | dischargevars(fs, e); |
| 362 | } | ||
| 363 | else { /* op == NOT */ | ||
| 364 | Instruction *previous; | ||
| 365 | discharge1(fs, v); | ||
| 366 | previous = &fs->f->code[fs->pc-1]; | ||
| 367 | if (ISJUMP(GET_OPCODE(*previous))) | ||
| 368 | SET_OPCODE(*previous, invertjump(GET_OPCODE(*previous))); | ||
| 369 | else | ||
| 370 | luaK_code0(fs, OP_NOT); | ||
| 371 | /* interchange true and false lists */ | ||
| 372 | { int temp = v->u.l.f; v->u.l.f = v->u.l.t; v->u.l.t = temp; } | ||
| 373 | } | ||
| 374 | } | 415 | } |
| 375 | 416 | ||
| 376 | 417 | ||
| 377 | void luaK_infix (LexState *ls, BinOpr op, expdesc *v) { | 418 | int luaK_exp2RK (FuncState *fs, expdesc *e) { |
| 378 | FuncState *fs = ls->fs; | 419 | luaK_exp2val(fs, e); |
| 379 | switch (op) { | 420 | if (e->k == VNUMBER && fs->nk + MAXSTACK <= MAXARG_C) { |
| 380 | case OPR_AND: | 421 | e->u.i.info = number_constant(fs, e->u.n); |
| 381 | luaK_goiftrue(fs, v, 1); | 422 | e->k = VK; |
| 382 | break; | ||
| 383 | case OPR_OR: | ||
| 384 | luaK_goiffalse(fs, v); | ||
| 385 | break; | ||
| 386 | default: | ||
| 387 | luaK_tostack(ls, v, 1); /* all other binary operators need a value */ | ||
| 388 | } | 423 | } |
| 424 | else if (!(e->k == VK && e->u.i.info + MAXSTACK <= MAXARG_C)) | ||
| 425 | luaK_exp2anyreg(fs, e); /* not a constant in the right range */ | ||
| 426 | return (e->k == VK) ? e->u.i.info+MAXSTACK : e->u.i.info; | ||
| 389 | } | 427 | } |
| 390 | 428 | ||
| 391 | 429 | ||
| 392 | 430 | void luaK_storevar (FuncState *fs, expdesc *var, expdesc *exp) { | |
| 393 | static const struct { | 431 | switch (var->k) { |
| 394 | OpCode opcode; /* opcode for each binary operator */ | 432 | case VLOCAL: { |
| 395 | int arg; /* default argument for the opcode */ | 433 | freeexp(fs, exp); |
| 396 | } codes[] = { /* ORDER OPR */ | 434 | luaK_exp2reg(fs, exp, var->u.i.info); |
| 397 | {OP_ADD, 0}, {OP_SUB, 0}, {OP_MULT, 0}, {OP_DIV, 0}, | ||
| 398 | {OP_POW, 0}, {OP_CONCAT, 2}, | ||
| 399 | {OP_JMPNE, NO_JUMP}, {OP_JMPEQ, NO_JUMP}, | ||
| 400 | {OP_JMPLT, NO_JUMP}, {OP_JMPLE, NO_JUMP}, | ||
| 401 | {OP_JMPGT, NO_JUMP}, {OP_JMPGE, NO_JUMP} | ||
| 402 | }; | ||
| 403 | |||
| 404 | |||
| 405 | void luaK_posfix (LexState *ls, BinOpr op, expdesc *v1, expdesc *v2) { | ||
| 406 | FuncState *fs = ls->fs; | ||
| 407 | switch (op) { | ||
| 408 | case OPR_AND: { | ||
| 409 | lua_assert(v1->u.l.t == NO_JUMP); /* list must be closed */ | ||
| 410 | discharge1(fs, v2); | ||
| 411 | v1->u.l.t = v2->u.l.t; | ||
| 412 | luaK_concat(fs, &v1->u.l.f, v2->u.l.f); | ||
| 413 | break; | 435 | break; |
| 414 | } | 436 | } |
| 415 | case OPR_OR: { | 437 | case VGLOBAL: { |
| 416 | lua_assert(v1->u.l.f == NO_JUMP); /* list must be closed */ | 438 | int e = luaK_exp2anyreg(fs, exp); |
| 417 | discharge1(fs, v2); | 439 | freereg(fs, e); |
| 418 | v1->u.l.f = v2->u.l.f; | 440 | luaK_codeABc(fs, OP_SETGLOBAL, e, var->u.i.info); |
| 419 | luaK_concat(fs, &v1->u.l.t, v2->u.l.t); | 441 | break; |
| 442 | } | ||
| 443 | case VINDEXED: { | ||
| 444 | int e = luaK_exp2anyreg(fs, exp); | ||
| 445 | freereg(fs, e); | ||
| 446 | luaK_codeABC(fs, OP_SETTABLE, e, var->u.i.info, var->u.i.aux); | ||
| 420 | break; | 447 | break; |
| 421 | } | 448 | } |
| 422 | default: { | 449 | default: { |
| 423 | luaK_tostack(ls, v2, 1); /* `v2' must be a value */ | 450 | lua_assert(0); /* invalid var kind to store */ |
| 424 | luaK_code1(fs, codes[op].opcode, codes[op].arg); | 451 | break; |
| 425 | } | 452 | } |
| 426 | } | 453 | } |
| 427 | } | 454 | } |
| 428 | 455 | ||
| 429 | 456 | ||
| 430 | static void codelineinfo (FuncState *fs) { | 457 | void luaK_self (FuncState *fs, expdesc *e, expdesc *key) { |
| 431 | Proto *f = fs->f; | 458 | luaK_exp2anyreg(fs, e); |
| 432 | LexState *ls = fs->ls; | 459 | freeexp(fs, e); |
| 433 | if (ls->lastline > fs->lastline) { | 460 | luaK_reserveregs(fs, 2); |
| 434 | if (ls->lastline > fs->lastline+1) { | 461 | luaK_codeABC(fs, OP_SELF, fs->freereg-2, e->u.i.info, luaK_exp2RK(fs, key)); |
| 435 | luaM_growvector(fs->L, f->lineinfo, fs->nlineinfo, f->sizelineinfo, int, | 462 | e->u.i.info = fs->freereg-2; |
| 436 | MAX_INT, l_s("line info overflow")); | 463 | e->k = VNONRELOC; |
| 437 | f->lineinfo[fs->nlineinfo++] = -(ls->lastline - (fs->lastline+1)); | 464 | } |
| 438 | } | 465 | |
| 439 | luaM_growvector(fs->L, f->lineinfo, fs->nlineinfo, f->sizelineinfo, int, | 466 | |
| 440 | MAX_INT, l_s("line info overflow")); | 467 | static OpCode invertoperator (OpCode op) { |
| 441 | f->lineinfo[fs->nlineinfo++] = fs->pc; | 468 | switch (op) { |
| 442 | fs->lastline = ls->lastline; | 469 | case OP_TESTNE: return OP_TESTEQ; |
| 470 | case OP_TESTEQ: return OP_TESTNE; | ||
| 471 | case OP_TESTLT: return OP_TESTGE; | ||
| 472 | case OP_TESTLE: return OP_TESTGT; | ||
| 473 | case OP_TESTGT: return OP_TESTLE; | ||
| 474 | case OP_TESTGE: return OP_TESTLT; | ||
| 475 | case OP_TESTT: return OP_TESTF; | ||
| 476 | case OP_TESTF: return OP_TESTT; | ||
| 477 | default: lua_assert(0); return op; /* invalid jump instruction */ | ||
| 443 | } | 478 | } |
| 444 | } | 479 | } |
| 445 | 480 | ||
| 446 | 481 | ||
| 447 | int luaK_code0 (FuncState *fs, OpCode o) { | 482 | static void invertjump (FuncState *fs, expdesc *e) { |
| 448 | return luaK_code2(fs, o, 0, 0); | 483 | Instruction *pc = getjumpcontrol(fs, e->u.i.info); |
| 484 | *pc = SET_OPCODE(*pc, invertoperator(GET_OPCODE(*pc))); | ||
| 449 | } | 485 | } |
| 450 | 486 | ||
| 451 | 487 | ||
| 452 | int luaK_code1 (FuncState *fs, OpCode o, int arg1) { | 488 | static int jumponcond (FuncState *fs, expdesc *e, OpCode op) { |
| 453 | return luaK_code2(fs, o, arg1, 0); | 489 | if (e->k == VRELOCABLE) { |
| 490 | Instruction ie = getcode(fs, e); | ||
| 491 | if (GET_OPCODE(ie) == OP_NOT) { | ||
| 492 | op = invertoperator(op); | ||
| 493 | fs->pc--; /* remove previous OP_NOT */ | ||
| 494 | return luaK_condjump(fs, op, GETARG_B(ie), 0); | ||
| 495 | } | ||
| 496 | /* else go through */ | ||
| 497 | } | ||
| 498 | discharge2anyreg(fs, e); | ||
| 499 | freeexp(fs, e); | ||
| 500 | return luaK_condjump(fs, op, e->u.i.info, 0); | ||
| 454 | } | 501 | } |
| 455 | 502 | ||
| 456 | 503 | ||
| 457 | int luaK_code2 (FuncState *fs, OpCode o, int arg1, int arg2) { | 504 | void luaK_goiftrue (FuncState *fs, expdesc *e) { |
| 458 | Proto *f; | 505 | int pc; /* pc of last jump */ |
| 459 | Instruction i = previous_instruction(fs); | 506 | dischargevars(fs, e); |
| 460 | int push = (int)luaK_opproperties[o].push; | 507 | switch (e->k) { |
| 461 | int pop = (int)luaK_opproperties[o].pop; | 508 | case VK: case VNUMBER: { |
| 462 | int optm = 0; /* 1 when there is an optimization */ | 509 | pc = NO_JUMP; /* always true; do nothing */ |
| 463 | switch (o) { | ||
| 464 | case OP_CLOSURE: { | ||
| 465 | pop = arg2; | ||
| 466 | break; | 510 | break; |
| 467 | } | 511 | } |
| 468 | case OP_SETTABLE: { | 512 | case VNIL: { |
| 469 | pop = arg2; | 513 | pc = luaK_codeAsBc(fs, OP_JMP, 0, NO_JUMP); /* always jump */ |
| 470 | break; | 514 | break; |
| 471 | } | 515 | } |
| 472 | case OP_SETLIST: { | 516 | case VJMP: { |
| 473 | pop = fs->stacklevel - 1 - arg2; | 517 | invertjump(fs, e); |
| 518 | pc = e->u.i.info; | ||
| 474 | break; | 519 | break; |
| 475 | } | 520 | } |
| 476 | case OP_SETMAP: { | 521 | case VRELOCABLE: |
| 477 | pop = fs->stacklevel - 1 - arg1; | 522 | case VNONRELOC: { |
| 523 | pc = jumponcond(fs, e, OP_TESTF); | ||
| 478 | break; | 524 | break; |
| 479 | } | 525 | } |
| 480 | case OP_PUSHNIL: { | 526 | default: { |
| 481 | if (arg1 == 0) return NO_JUMP; /* nothing to do */ | 527 | pc = 0; /* to avoid warnings */ |
| 482 | push = arg1; | 528 | lua_assert(0); /* cannot happen */ |
| 483 | switch(GET_OPCODE(i)) { | ||
| 484 | case OP_PUSHNIL: SETARG_U(i, GETARG_U(i)+arg1); optm = 1; break; | ||
| 485 | default: break; | ||
| 486 | } | ||
| 487 | break; | 529 | break; |
| 488 | } | 530 | } |
| 489 | case OP_POP: { | 531 | } |
| 490 | if (arg1 == 0) return NO_JUMP; /* nothing to do */ | 532 | luaK_concat(fs, &e->f, pc); /* insert last jump in `f' list */ |
| 491 | pop = arg1; | 533 | luaK_patchlist(fs, e->t, luaK_getlabel(fs)); |
| 492 | switch(GET_OPCODE(i)) { | 534 | e->t = NO_JUMP; |
| 493 | case OP_SETTABLE: SETARG_B(i, GETARG_B(i)+arg1); optm = 1; break; | 535 | } |
| 494 | default: break; | 536 | |
| 495 | } | 537 | |
| 538 | static void luaK_goiffalse (FuncState *fs, expdesc *e) { | ||
| 539 | int pc; /* pc of last jump */ | ||
| 540 | dischargevars(fs, e); | ||
| 541 | switch (e->k) { | ||
| 542 | case VNIL: { | ||
| 543 | pc = NO_JUMP; /* always false; do nothing */ | ||
| 496 | break; | 544 | break; |
| 497 | } | 545 | } |
| 498 | case OP_GETTABLE: { | 546 | case VJMP: { |
| 499 | switch(GET_OPCODE(i)) { | 547 | pc = e->u.i.info; |
| 500 | case OP_PUSHSTRING: /* `t.x' */ | ||
| 501 | SET_OPCODE(i, OP_GETDOTTED); | ||
| 502 | optm = 1; | ||
| 503 | break; | ||
| 504 | case OP_GETLOCAL: /* `t[i]' */ | ||
| 505 | SET_OPCODE(i, OP_GETINDEXED); | ||
| 506 | optm = 1; | ||
| 507 | break; | ||
| 508 | default: break; | ||
| 509 | } | ||
| 510 | break; | 548 | break; |
| 511 | } | 549 | } |
| 512 | case OP_ADD: { | 550 | case VK: case VNUMBER: /* cannot optimize it (`or' must keep value) */ |
| 513 | switch(GET_OPCODE(i)) { | 551 | case VRELOCABLE: |
| 514 | case OP_PUSHINT: SET_OPCODE(i, OP_ADDI); optm = 1; break; /* `a+k' */ | 552 | case VNONRELOC: { |
| 515 | default: break; | 553 | pc = jumponcond(fs, e, OP_TESTT); |
| 516 | } | ||
| 517 | break; | 554 | break; |
| 518 | } | 555 | } |
| 519 | case OP_SUB: { | 556 | default: { |
| 520 | switch(GET_OPCODE(i)) { | 557 | pc = 0; /* to avoid warnings */ |
| 521 | case OP_PUSHINT: /* `a-k' */ | 558 | lua_assert(0); /* cannot happen */ |
| 522 | i = CREATE_S(OP_ADDI, -GETARG_S(i)); | ||
| 523 | optm = 1; | ||
| 524 | break; | ||
| 525 | default: break; | ||
| 526 | } | ||
| 527 | break; | 559 | break; |
| 528 | } | 560 | } |
| 529 | case OP_CONCAT: { | 561 | } |
| 530 | pop = arg1; | 562 | luaK_concat(fs, &e->t, pc); /* insert last jump in `t' list */ |
| 531 | switch(GET_OPCODE(i)) { | 563 | luaK_patchlist(fs, e->f, luaK_getlabel(fs)); |
| 532 | case OP_CONCAT: /* `a..b..c' */ | 564 | e->f = NO_JUMP; |
| 533 | SETARG_U(i, GETARG_U(i)+1); | 565 | } |
| 534 | optm = 1; | 566 | |
| 535 | break; | 567 | |
| 536 | default: break; | 568 | static void codenot (FuncState *fs, expdesc *e) { |
| 537 | } | 569 | dischargevars(fs, e); |
| 570 | switch (e->k) { | ||
| 571 | case VNIL: { | ||
| 572 | e->u.n = 1; | ||
| 573 | e->k = VNUMBER; | ||
| 538 | break; | 574 | break; |
| 539 | } | 575 | } |
| 540 | case OP_MINUS: { | 576 | case VK: case VNUMBER: { |
| 541 | switch(GET_OPCODE(i)) { | 577 | e->k = VNIL; |
| 542 | case OP_PUSHINT: /* `-k' */ | ||
| 543 | SETARG_S(i, -GETARG_S(i)); | ||
| 544 | optm = 1; | ||
| 545 | break; | ||
| 546 | case OP_PUSHNUM: /* `-k' */ | ||
| 547 | SET_OPCODE(i, OP_PUSHNEGNUM); | ||
| 548 | optm = 1; | ||
| 549 | break; | ||
| 550 | default: break; | ||
| 551 | } | ||
| 552 | break; | 578 | break; |
| 553 | } | 579 | } |
| 554 | case OP_JMPNE: { | 580 | case VJMP: { |
| 555 | if (i == CREATE_U(OP_PUSHNIL, 1)) { /* `a~=nil' */ | 581 | invertjump(fs, e); |
| 556 | i = CREATE_S(OP_JMPT, NO_JUMP); | ||
| 557 | optm = 1; | ||
| 558 | } | ||
| 559 | break; | 582 | break; |
| 560 | } | 583 | } |
| 561 | case OP_JMPEQ: { | 584 | case VRELOCABLE: |
| 562 | if (i == CREATE_U(OP_PUSHNIL, 1)) { /* `a==nil' */ | 585 | case VNONRELOC: { |
| 563 | i = CREATE_0(OP_NOT); | 586 | discharge2anyreg(fs, e); |
| 564 | pop = 1; /* just undo effect of previous PUSHNIL */ | 587 | freeexp(fs, e); |
| 565 | optm = 1; | 588 | e->u.i.info = luaK_codeABC(fs, OP_NOT, 0, e->u.i.info, 0); |
| 566 | } | 589 | e->k = VRELOCABLE; |
| 567 | break; | 590 | break; |
| 568 | } | 591 | } |
| 569 | case OP_JMPT: | 592 | default: { |
| 570 | case OP_JMPONT: { | 593 | lua_assert(0); /* cannot happen */ |
| 571 | switch (GET_OPCODE(i)) { | ||
| 572 | case OP_NOT: { | ||
| 573 | i = CREATE_S(OP_JMPF, NO_JUMP); | ||
| 574 | optm = 1; | ||
| 575 | break; | ||
| 576 | } | ||
| 577 | case OP_PUSHINT: { | ||
| 578 | if (o == OP_JMPT) { /* JMPONT must keep original integer value */ | ||
| 579 | i = CREATE_S(OP_JMP, NO_JUMP); | ||
| 580 | optm = 1; | ||
| 581 | } | ||
| 582 | break; | ||
| 583 | } | ||
| 584 | case OP_PUSHNIL: { | ||
| 585 | if (GETARG_U(i) == 1) { | ||
| 586 | fs->pc--; /* erase previous instruction */ | ||
| 587 | luaK_deltastack(fs, -1); /* correct stack */ | ||
| 588 | return NO_JUMP; | ||
| 589 | } | ||
| 590 | break; | ||
| 591 | } | ||
| 592 | default: break; | ||
| 593 | } | ||
| 594 | break; | 594 | break; |
| 595 | } | 595 | } |
| 596 | case OP_JMPF: | 596 | } |
| 597 | case OP_JMPONF: { | 597 | /* interchange true and false lists */ |
| 598 | switch (GET_OPCODE(i)) { | 598 | { int temp = e->f; e->f = e->t; e->t = temp; } |
| 599 | case OP_NOT: { | 599 | } |
| 600 | i = CREATE_S(OP_JMPT, NO_JUMP); | 600 | |
| 601 | optm = 1; | 601 | |
| 602 | break; | 602 | void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k) { |
| 603 | } | 603 | t->u.i.aux = luaK_exp2RK(fs, k); |
| 604 | case OP_PUSHINT: { /* `while 1 do ...' */ | 604 | t->k = VINDEXED; |
| 605 | fs->pc--; /* erase previous instruction */ | 605 | } |
| 606 | luaK_deltastack(fs, -1); /* correct stack */ | 606 | |
| 607 | return NO_JUMP; | 607 | |
| 608 | } | 608 | void luaK_prefix (FuncState *fs, UnOpr op, expdesc *e) { |
| 609 | case OP_PUSHNIL: { /* `repeat ... until nil' */ | 609 | if (op == OPR_MINUS) { |
| 610 | if (GETARG_U(i) == 1) { | 610 | luaK_exp2val(fs, e); |
| 611 | i = CREATE_S(OP_JMP, NO_JUMP); | 611 | if (e->k == VNUMBER) |
| 612 | optm = 1; | 612 | e->u.n = -e->u.n; |
| 613 | } | 613 | else { |
| 614 | break; | 614 | luaK_exp2anyreg(fs, e); |
| 615 | } | 615 | freeexp(fs, e); |
| 616 | default: break; | 616 | e->u.i.info = luaK_codeABC(fs, OP_UNM, 0, e->u.i.info, 0); |
| 617 | } | 617 | e->k = VRELOCABLE; |
| 618 | } | ||
| 619 | } | ||
| 620 | else /* op == NOT */ | ||
| 621 | codenot(fs, e); | ||
| 622 | } | ||
| 623 | |||
| 624 | |||
| 625 | void luaK_infix (FuncState *fs, BinOpr op, expdesc *v) { | ||
| 626 | switch (op) { | ||
| 627 | case OPR_AND: { | ||
| 628 | luaK_goiftrue(fs, v); | ||
| 629 | break; | ||
| 630 | } | ||
| 631 | case OPR_OR: { | ||
| 632 | luaK_goiffalse(fs, v); | ||
| 633 | break; | ||
| 634 | } | ||
| 635 | case OPR_CONCAT: { | ||
| 636 | luaK_exp2nextreg(fs, v); /* operand must be on the `stack' */ | ||
| 618 | break; | 637 | break; |
| 619 | } | 638 | } |
| 620 | case OP_GETDOTTED: | 639 | case OPR_SUB: case OPR_DIV: case OPR_POW: { |
| 621 | case OP_GETINDEXED: | 640 | /* non-comutative operators */ |
| 622 | case OP_ADDI: { | 641 | luaK_exp2anyreg(fs, v); /* first operand must be a register */ |
| 623 | lua_assert(0); /* instruction used only for optimizations */ | ||
| 624 | break; | 642 | break; |
| 625 | } | 643 | } |
| 626 | default: { | 644 | default: { |
| 645 | luaK_exp2RK(fs, v); | ||
| 627 | break; | 646 | break; |
| 628 | } | 647 | } |
| 629 | } | 648 | } |
| 630 | f = fs->f; | 649 | } |
| 631 | lua_assert(push != VD); | 650 | |
| 632 | lua_assert(pop != VD); | 651 | |
| 633 | luaK_deltastack(fs, push); | 652 | |
| 634 | luaK_deltastack(fs, -pop); | 653 | /* opcode for each binary operator */ |
| 635 | if (optm) { /* optimize: put instruction in place of last one */ | 654 | static const OpCode codes[] = { /* ORDER OPR */ |
| 636 | f->code[fs->pc-1] = i; /* change previous instruction */ | 655 | OP_ADD, OP_SUB, OP_MUL, OP_DIV, |
| 637 | return fs->pc-1; /* do not generate new instruction */ | 656 | OP_POW, OP_CONCAT, |
| 657 | OP_TESTNE, OP_TESTEQ, | ||
| 658 | OP_TESTLT, OP_TESTLE, OP_TESTGT, OP_TESTGE | ||
| 659 | }; | ||
| 660 | |||
| 661 | |||
| 662 | /* `inverted' opcode for each binary operator */ | ||
| 663 | /* ( -1 means operator has no inverse) */ | ||
| 664 | static const OpCode invcodes[] = { /* ORDER OPR */ | ||
| 665 | OP_ADD, (OpCode)-1, OP_MUL, (OpCode)-1, | ||
| 666 | (OpCode)-1, (OpCode)-1, | ||
| 667 | OP_TESTNE, OP_TESTEQ, | ||
| 668 | OP_TESTGT, OP_TESTGE, OP_TESTLT, OP_TESTLE | ||
| 669 | }; | ||
| 670 | |||
| 671 | |||
| 672 | void luaK_posfix (FuncState *fs, BinOpr op, expdesc *e1, expdesc *e2) { | ||
| 673 | switch (op) { | ||
| 674 | case OPR_AND: { | ||
| 675 | lua_assert(e1->t == NO_JUMP); /* list must be closed */ | ||
| 676 | dischargevars(fs, e2); | ||
| 677 | luaK_concat(fs, &e1->f, e2->f); | ||
| 678 | e1->k = e2->k; e1->u = e2->u; e1->t = e2->t; | ||
| 679 | break; | ||
| 680 | } | ||
| 681 | case OPR_OR: { | ||
| 682 | lua_assert(e1->f == NO_JUMP); /* list must be closed */ | ||
| 683 | dischargevars(fs, e2); | ||
| 684 | luaK_concat(fs, &e1->t, e2->t); | ||
| 685 | e1->k = e2->k; e1->u = e2->u; e1->f = e2->f; | ||
| 686 | break; | ||
| 687 | } | ||
| 688 | case OPR_CONCAT: { | ||
| 689 | luaK_exp2val(fs, e2); | ||
| 690 | if (e2->k == VRELOCABLE && GET_OPCODE(getcode(fs, e2)) == OP_CONCAT) { | ||
| 691 | lua_assert(e1->u.i.info == GETARG_B(getcode(fs, e2))-1); | ||
| 692 | freeexp(fs, e1); | ||
| 693 | SETARG_B(getcode(fs, e2), e1->u.i.info); | ||
| 694 | e1->k = e2->k; e1->u.i.info = e2->u.i.info; | ||
| 695 | } | ||
| 696 | else { | ||
| 697 | luaK_exp2nextreg(fs, e2); | ||
| 698 | freeexp(fs, e2); | ||
| 699 | freeexp(fs, e1); | ||
| 700 | e1->u.i.info = luaK_codeABC(fs, codes[op], 0, e1->u.i.info, | ||
| 701 | e2->u.i.info); | ||
| 702 | e1->k = VRELOCABLE; | ||
| 703 | } | ||
| 704 | break; | ||
| 705 | } | ||
| 706 | case OPR_EQ: case OPR_NE: { | ||
| 707 | luaK_exp2val(fs, e2); | ||
| 708 | if (e2->k == VNIL) { /* exp x= nil ? */ | ||
| 709 | if (e1->k == VK) { /* constant x= nil ? */ | ||
| 710 | if (op == OPR_EQ) /* constant == nil ? */ | ||
| 711 | e1->k = VNIL; /* always false */ | ||
| 712 | /* else always true (leave the constant itself) */ | ||
| 713 | } | ||
| 714 | else { | ||
| 715 | OpCode opc = (op == OPR_EQ) ? OP_TESTF : OP_TESTT; | ||
| 716 | e1->u.i.info = jumponcond(fs, e1, opc); | ||
| 717 | e1->k = VJMP; | ||
| 718 | } | ||
| 719 | break; | ||
| 720 | } | ||
| 721 | /* else go through */ | ||
| 722 | } | ||
| 723 | default: { | ||
| 724 | int o1, o2; | ||
| 725 | OpCode opc; | ||
| 726 | if (e1->k != VK) { /* not a constant operator? */ | ||
| 727 | o1 = e1->u.i.info; | ||
| 728 | o2 = luaK_exp2RK(fs, e2); /* maybe other operator is constant... */ | ||
| 729 | opc = codes[op]; | ||
| 730 | } | ||
| 731 | else { /* invert operands */ | ||
| 732 | o2 = luaK_exp2RK(fs, e1); /* constant must be 2nd operand */ | ||
| 733 | o1 = luaK_exp2anyreg(fs, e2); /* other operator must be in register */ | ||
| 734 | opc = invcodes[op]; /* use inverted operator */ | ||
| 735 | } | ||
| 736 | freeexp(fs, e2); | ||
| 737 | freeexp(fs, e1); | ||
| 738 | if (op < OPR_NE) { /* ORDER OPR */ | ||
| 739 | e1->u.i.info = luaK_codeABC(fs, opc, 0, o1, o2); | ||
| 740 | e1->k = VRELOCABLE; | ||
| 741 | } | ||
| 742 | else { /* jump */ | ||
| 743 | e1->u.i.info = luaK_condjump(fs, opc, o1, o2); | ||
| 744 | e1->k = VJMP; | ||
| 745 | } | ||
| 746 | } | ||
| 638 | } | 747 | } |
| 639 | /* else build new instruction */ | 748 | } |
| 640 | switch ((enum Mode)luaK_opproperties[o].mode) { | 749 | |
| 641 | case iO: i = CREATE_0(o); break; | 750 | |
| 642 | case iU: i = CREATE_U(o, arg1); break; | 751 | static void codelineinfo (FuncState *fs) { |
| 643 | case iS: i = CREATE_S(o, arg1); break; | 752 | Proto *f = fs->f; |
| 644 | case iAB: i = CREATE_AB(o, arg1, arg2); break; | 753 | LexState *ls = fs->ls; |
| 754 | if (ls->lastline > fs->lastline) { | ||
| 755 | if (ls->lastline > fs->lastline+1) { | ||
| 756 | luaM_growvector(fs->L, f->lineinfo, fs->nlineinfo, f->sizelineinfo, int, | ||
| 757 | MAX_INT, l_s("line info overflow")); | ||
| 758 | f->lineinfo[fs->nlineinfo++] = -(ls->lastline - (fs->lastline+1)); | ||
| 759 | } | ||
| 760 | luaM_growvector(fs->L, f->lineinfo, fs->nlineinfo, f->sizelineinfo, int, | ||
| 761 | MAX_INT, l_s("line info overflow")); | ||
| 762 | f->lineinfo[fs->nlineinfo++] = fs->pc; | ||
| 763 | fs->lastline = ls->lastline; | ||
| 645 | } | 764 | } |
| 765 | } | ||
| 766 | |||
| 767 | |||
| 768 | static int luaK_code (FuncState *fs, Instruction i) { | ||
| 769 | Proto *f; | ||
| 646 | codelineinfo(fs); | 770 | codelineinfo(fs); |
| 771 | f = fs->f; | ||
| 647 | /* put new instruction in code array */ | 772 | /* put new instruction in code array */ |
| 648 | luaM_growvector(fs->L, f->code, fs->pc, f->sizecode, Instruction, | 773 | luaM_growvector(fs->L, f->code, fs->pc, f->sizecode, Instruction, |
| 649 | MAX_INT, l_s("code size overflow")); | 774 | MAX_INT, l_s("code size overflow")); |
| 650 | f->code[fs->pc] = i; | 775 | f->code[fs->pc] = i; |
| 776 | /*printf("free: %d ", fs->freereg); printopcode(f, fs->pc);*/ | ||
| 651 | return fs->pc++; | 777 | return fs->pc++; |
| 652 | } | 778 | } |
| 653 | 779 | ||
| 654 | 780 | ||
| 655 | const OpProperties luaK_opproperties[] = { | 781 | int luaK_codeABC (FuncState *fs, OpCode o, int a, int b, int c) { |
| 656 | {iU, 0, 0}, /* OP_RETURN */ | 782 | lua_assert(getOpMode(o) == iABC); |
| 657 | {iAB, 0, 0}, /* OP_CALL */ | 783 | return luaK_code(fs, CREATE_ABC(o, a, b, c)); |
| 658 | {iU, VD, 0}, /* OP_PUSHNIL */ | 784 | } |
| 659 | {iU, 0, VD}, /* OP_POP */ | 785 | |
| 660 | {iS, 1, 0}, /* OP_PUSHINT */ | 786 | |
| 661 | {iU, 1, 0}, /* OP_PUSHSTRING */ | 787 | int luaK_codeABc (FuncState *fs, OpCode o, int a, int bc) { |
| 662 | {iU, 1, 0}, /* OP_PUSHNUM */ | 788 | lua_assert(getOpMode(o) == iABc || getOpMode(o) == iAsBc); |
| 663 | {iU, 1, 0}, /* OP_PUSHNEGNUM */ | 789 | return luaK_code(fs, CREATE_ABc(o, a, bc)); |
| 664 | {iU, 1, 0}, /* OP_PUSHUPVALUE */ | 790 | } |
| 665 | {iU, 1, 0}, /* OP_GETLOCAL */ | ||
| 666 | {iU, 1, 0}, /* OP_GETGLOBAL */ | ||
| 667 | {iO, 1, 2}, /* OP_GETTABLE */ | ||
| 668 | {iU, 1, 1}, /* OP_GETDOTTED */ | ||
| 669 | {iU, 1, 1}, /* OP_GETINDEXED */ | ||
| 670 | {iU, 2, 1}, /* OP_PUSHSELF */ | ||
| 671 | {iU, 1, 0}, /* OP_CREATETABLE */ | ||
| 672 | {iU, 0, 1}, /* OP_SETLOCAL */ | ||
| 673 | {iU, 0, 1}, /* OP_SETGLOBAL */ | ||
| 674 | {iAB, 0, VD}, /* OP_SETTABLE */ | ||
| 675 | {iAB, 0, VD}, /* OP_SETLIST */ | ||
| 676 | {iU, 0, VD}, /* OP_SETMAP */ | ||
| 677 | {iO, 1, 2}, /* OP_ADD */ | ||
| 678 | {iS, 1, 1}, /* OP_ADDI */ | ||
| 679 | {iO, 1, 2}, /* OP_SUB */ | ||
| 680 | {iO, 1, 2}, /* OP_MULT */ | ||
| 681 | {iO, 1, 2}, /* OP_DIV */ | ||
| 682 | {iO, 1, 2}, /* OP_POW */ | ||
| 683 | {iU, 1, VD}, /* OP_CONCAT */ | ||
| 684 | {iO, 1, 1}, /* OP_MINUS */ | ||
| 685 | {iO, 1, 1}, /* OP_NOT */ | ||
| 686 | {iS, 0, 2}, /* OP_JMPNE */ | ||
| 687 | {iS, 0, 2}, /* OP_JMPEQ */ | ||
| 688 | {iS, 0, 2}, /* OP_JMPLT */ | ||
| 689 | {iS, 0, 2}, /* OP_JMPLE */ | ||
| 690 | {iS, 0, 2}, /* OP_JMPGT */ | ||
| 691 | {iS, 0, 2}, /* OP_JMPGE */ | ||
| 692 | {iS, 0, 1}, /* OP_JMPT */ | ||
| 693 | {iS, 0, 1}, /* OP_JMPF */ | ||
| 694 | {iS, 0, 1}, /* OP_JMPONT */ | ||
| 695 | {iS, 0, 1}, /* OP_JMPONF */ | ||
| 696 | {iS, 0, 0}, /* OP_JMP */ | ||
| 697 | {iO, 0, 0}, /* OP_PUSHNILJMP */ | ||
| 698 | {iS, 0, 0}, /* OP_FORPREP */ | ||
| 699 | {iS, 0, 3}, /* OP_FORLOOP */ | ||
| 700 | {iS, 3, 0}, /* OP_LFORPREP */ | ||
| 701 | {iS, 0, 4}, /* OP_LFORLOOP */ | ||
| 702 | {iAB, 1, VD} /* OP_CLOSURE */ | ||
| 703 | }; | ||
| 704 | 791 | ||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lcode.h,v 1.20 2001/02/20 18:15:33 roberto Exp roberto $ | 2 | ** $Id: lcode.h,v 1.21 2001/02/23 17:17:25 roberto Exp roberto $ |
| 3 | ** Code generator for Lua | 3 | ** Code generator for Lua |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -31,43 +31,36 @@ typedef enum BinOpr { | |||
| 31 | OPR_NOBINOPR | 31 | OPR_NOBINOPR |
| 32 | } BinOpr; | 32 | } BinOpr; |
| 33 | 33 | ||
| 34 | typedef enum UnOpr { OPR_MINUS, OPR_NOT, OPR_NOUNOPR } UnOpr; | 34 | #define binopistest(op) ((op) >= OPR_NE) |
| 35 | |||
| 36 | |||
| 37 | enum Mode {iO, iU, iS, iAB}; /* instruction format */ | ||
| 38 | 35 | ||
| 39 | #define VD 100 /* flag for variable delta */ | 36 | typedef enum UnOpr { OPR_MINUS, OPR_NOT, OPR_NOUNOPR } UnOpr; |
| 40 | |||
| 41 | typedef struct OpProperties { | ||
| 42 | lu_byte mode; | ||
| 43 | lu_byte push; | ||
| 44 | lu_byte pop; | ||
| 45 | } OpProperties; | ||
| 46 | 37 | ||
| 47 | extern const OpProperties luaK_opproperties[]; | ||
| 48 | 38 | ||
| 39 | #define luaK_codeAsBc(fs,o,A,sBc) luaK_codeABc(fs,o,A,(sBc)+MAXARG_sBc) | ||
| 49 | 40 | ||
| 50 | void luaK_error (LexState *ls, const l_char *msg); | 41 | void luaK_error (LexState *ls, const l_char *msg); |
| 51 | int luaK_code0 (FuncState *fs, OpCode o); | 42 | int luaK_codeABc (FuncState *fs, OpCode o, int A, int Bc); |
| 52 | int luaK_code1 (FuncState *fs, OpCode o, int arg1); | 43 | int luaK_codeABC (FuncState *fs, OpCode o, int A, int B, int C); |
| 53 | int luaK_code2 (FuncState *fs, OpCode o, int arg1, int arg2); | 44 | void luaK_nil (FuncState *fs, int from, int n); |
| 45 | void luaK_reserveregs (FuncState *fs, int n); | ||
| 46 | int luaK_stringk (FuncState *fs, TString *s); | ||
| 47 | int luaK_exp2anyreg (FuncState *fs, expdesc *e); | ||
| 48 | void luaK_exp2nextreg (FuncState *fs, expdesc *e); | ||
| 49 | void luaK_exp2val (FuncState *fs, expdesc *e); | ||
| 50 | int luaK_exp2RK (FuncState *fs, expdesc *e); | ||
| 51 | void luaK_self (FuncState *fs, expdesc *e, expdesc *key); | ||
| 52 | void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k); | ||
| 53 | void luaK_goiftrue (FuncState *fs, expdesc *e); | ||
| 54 | void luaK_storevar (FuncState *fs, expdesc *var, expdesc *e); | ||
| 55 | void luaK_setcallreturns (FuncState *fs, expdesc *var, int nresults); | ||
| 54 | int luaK_jump (FuncState *fs); | 56 | int luaK_jump (FuncState *fs); |
| 55 | void luaK_patchlist (FuncState *fs, int list, int target); | 57 | void luaK_patchlist (FuncState *fs, int list, int target); |
| 56 | void luaK_fixfor (FuncState *fs, int pc, int dest); | 58 | void luaK_fixfor (FuncState *fs, int pc, int dest); |
| 57 | void luaK_concat (FuncState *fs, int *l1, int l2); | 59 | void luaK_concat (FuncState *fs, int *l1, int l2); |
| 58 | void luaK_goiftrue (FuncState *fs, expdesc *v, int keepvalue); | ||
| 59 | int luaK_getlabel (FuncState *fs); | 60 | int luaK_getlabel (FuncState *fs); |
| 60 | void luaK_deltastack (FuncState *fs, int delta); | 61 | void luaK_prefix (FuncState *fs, UnOpr op, expdesc *v); |
| 61 | void luaK_kstr (LexState *ls, int c); | 62 | void luaK_infix (FuncState *fs, BinOpr op, expdesc *v); |
| 62 | void luaK_number (FuncState *fs, lua_Number f); | 63 | void luaK_posfix (FuncState *fs, BinOpr op, expdesc *v1, expdesc *v2); |
| 63 | void luaK_adjuststack (FuncState *fs, int n); | ||
| 64 | int luaK_lastisopen (FuncState *fs); | ||
| 65 | void luaK_setcallreturns (FuncState *fs, int nresults); | ||
| 66 | void luaK_tostack (LexState *ls, expdesc *v, int onlyone); | ||
| 67 | void luaK_storevar (LexState *ls, const expdesc *var); | ||
| 68 | void luaK_prefix (LexState *ls, UnOpr op, expdesc *v); | ||
| 69 | void luaK_infix (LexState *ls, BinOpr op, expdesc *v); | ||
| 70 | void luaK_posfix (LexState *ls, BinOpr op, expdesc *v1, expdesc *v2); | ||
| 71 | 64 | ||
| 72 | 65 | ||
| 73 | #endif | 66 | #endif |
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: ldebug.c,v 1.75 2001/03/26 14:31:49 roberto Exp roberto $ | 2 | ** $Id: ldebug.c,v 1.76 2001/04/06 18:25:00 roberto Exp roberto $ |
| 3 | ** Debug Interface | 3 | ** Debug Interface |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -22,6 +22,7 @@ | |||
| 22 | #include "ltable.h" | 22 | #include "ltable.h" |
| 23 | #include "ltm.h" | 23 | #include "ltm.h" |
| 24 | #include "luadebug.h" | 24 | #include "luadebug.h" |
| 25 | #include "lvm.h" | ||
| 25 | 26 | ||
| 26 | 27 | ||
| 27 | 28 | ||
| @@ -298,6 +299,10 @@ LUA_API int lua_getinfo (lua_State *L, const l_char *what, lua_Debug *ar) { | |||
| 298 | 299 | ||
| 299 | #define check(x) if (!(x)) return 0; | 300 | #define check(x) if (!(x)) return 0; |
| 300 | 301 | ||
| 302 | #define checkjump(pt,pc) check(0 <= pc && pc < pt->sizecode) | ||
| 303 | |||
| 304 | #define checkreg(pt,reg) check((reg) < (pt)->maxstacksize) | ||
| 305 | |||
| 301 | 306 | ||
| 302 | static int checklineinfo (const Proto *pt) { | 307 | static int checklineinfo (const Proto *pt) { |
| 303 | int *lineinfo = pt->lineinfo; | 308 | int *lineinfo = pt->lineinfo; |
| @@ -318,231 +323,199 @@ static int precheck (const Proto *pt) { | |||
| 318 | } | 323 | } |
| 319 | 324 | ||
| 320 | 325 | ||
| 321 | /* value for non-initialized entries in array stacklevel */ | 326 | static int checkopenop (Instruction i) { |
| 322 | #define SL_EMPTY 255 | 327 | OpCode op = GET_OPCODE(i); |
| 323 | 328 | switch (op) { | |
| 324 | #define checkjump(pt,sl,top,pc) if (!checkjump_aux(pt,sl,top,pc)) return 0; | 329 | case OP_CALL: |
| 325 | 330 | case OP_RETURN: { | |
| 326 | static int checkjump_aux (const Proto *pt, lu_byte *sl, int top, int pc) { | 331 | check(GETARG_B(i) == NO_REG); |
| 327 | check(0 <= pc && pc < pt->sizecode); | 332 | return 1; |
| 328 | if (sl == NULL) return 1; /* not full checking */ | 333 | } |
| 329 | if (sl[pc] == SL_EMPTY) | 334 | case OP_SETLISTO: return 1; |
| 330 | sl[pc] = (lu_byte)top; | 335 | default: return 0; /* invalid instruction after an open call */ |
| 331 | else | 336 | } |
| 332 | check(sl[pc] == top); | ||
| 333 | return 1; | ||
| 334 | } | 337 | } |
| 335 | 338 | ||
| 336 | 339 | ||
| 337 | static Instruction luaG_symbexec (lua_State *L, const Proto *pt, | 340 | static Instruction luaG_symbexec (const Proto *pt, int lastpc, int reg) { |
| 338 | int lastpc, int stackpos) { | ||
| 339 | int stack[MAXSTACK]; /* stores last instruction that changed a stack entry */ | ||
| 340 | lu_byte *sl = NULL; | ||
| 341 | int top; | ||
| 342 | int pc; | 341 | int pc; |
| 343 | if (stackpos < 0) { /* full check? */ | 342 | int last; /* stores position of last instruction that changed `reg' */ |
| 344 | int i; | 343 | last = pt->sizecode-1; /* points to final return (a `neutral' instruction) */ |
| 345 | sl = luaO_openspace(L, pt->sizecode, lu_byte); | 344 | if (reg == NO_REG) /* full check? */ |
| 346 | for (i=0; i<pt->sizecode; i++) /* initialize stack-level array */ | ||
| 347 | sl[i] = SL_EMPTY; | ||
| 348 | check(precheck(pt)); | 345 | check(precheck(pt)); |
| 349 | } | 346 | for (pc = 0; pc < lastpc; pc++) { |
| 350 | top = pt->numparams; | 347 | const Instruction i = pt->code[pc]; |
| 351 | pc = 0; | ||
| 352 | if (pt->is_vararg) /* varargs? */ | ||
| 353 | top++; /* `arg' */ | ||
| 354 | if (sl) sl[0] = (lu_byte)top; | ||
| 355 | while (pc < lastpc) { | ||
| 356 | const Instruction i = pt->code[pc++]; | ||
| 357 | OpCode op = GET_OPCODE(i); | 348 | OpCode op = GET_OPCODE(i); |
| 358 | int arg1 = 0; | 349 | int a = GETARG_A(i); |
| 359 | int arg2 = 0; | 350 | int b = 0; |
| 360 | int push, pop; | 351 | int c = 0; |
| 361 | check(op < NUM_OPCODES); | 352 | #undef check |
| 362 | push = (int)luaK_opproperties[op].push; | 353 | #define check(x) if (!(x)) { \ |
| 363 | pop = (int)luaK_opproperties[op].pop; | 354 | printf(">>>%d %d %d %d %d %d\n", op, a, b, c, pt->maxstacksize, pt->sizek); \ |
| 364 | switch ((enum Mode)luaK_opproperties[op].mode) { | 355 | return 0; } |
| 365 | case iO: break; | 356 | switch (getOpMode(op)) { |
| 366 | case iU: arg1 = GETARG_U(i); check(arg1 >= 0); break; | 357 | case iABC: { |
| 367 | case iS: arg1 = GETARG_S(i); break; | 358 | b = GETARG_B(i); |
| 368 | case iAB: | 359 | c = GETARG_C(i); |
| 369 | arg1 = GETARG_A(i); arg2 = GETARG_B(i); check(arg1 >= 0); break; | 360 | if (testOpMode(op, OpModeBreg)) { |
| 370 | } | 361 | checkreg(pt, b); |
| 371 | switch (op) { | 362 | check(c < pt->maxstacksize || |
| 372 | case OP_RETURN: { | 363 | (c >= MAXSTACK && c-MAXSTACK < pt->sizek)); |
| 373 | check(arg1 <= top); | 364 | } |
| 374 | pop = top-arg1; | ||
| 375 | break; | 365 | break; |
| 376 | } | 366 | } |
| 377 | case OP_CALL: { | 367 | case iABc: { |
| 378 | if (arg2 == MULT_RET) arg2 = 1; | 368 | b = GETARG_Bc(i); |
| 379 | check(arg1 < top); | 369 | if (testOpMode(op, OpModeK)) check(b < pt->sizek); |
| 380 | pop = top-arg1; | ||
| 381 | push = arg2; | ||
| 382 | break; | 370 | break; |
| 383 | } | 371 | } |
| 384 | case OP_PUSHNIL: { | 372 | case iAsBc: { |
| 385 | check(arg1 > 0); | 373 | b = GETARG_sBc(i); |
| 386 | push = arg1; | ||
| 387 | break; | 374 | break; |
| 388 | } | 375 | } |
| 389 | case OP_POP: { | 376 | } |
| 390 | pop = arg1; | 377 | if (testOpMode(op, OpModeAreg)) checkreg(pt, a); |
| 378 | if (testOpMode(op, OpModesetA)) { | ||
| 379 | if (a == reg) last = pc; /* change register `a' */ | ||
| 380 | } | ||
| 381 | if (testOpMode(op, OpModeT)) | ||
| 382 | check(GET_OPCODE(pt->code[pc+1]) == OP_CJMP); | ||
| 383 | switch (op) { | ||
| 384 | case OP_LOADNIL: { | ||
| 385 | if (a <= reg && reg <= b) | ||
| 386 | last = pc; /* set registers from `a' to `b' */ | ||
| 391 | break; | 387 | break; |
| 392 | } | 388 | } |
| 393 | case OP_PUSHSTRING: | 389 | case OP_LOADUPVAL: { |
| 394 | case OP_GETGLOBAL: | 390 | check(b < pt->nupvalues); |
| 395 | case OP_GETDOTTED: | ||
| 396 | case OP_PUSHSELF: | ||
| 397 | case OP_SETGLOBAL: { | ||
| 398 | check(arg1 < pt->sizekstr); | ||
| 399 | break; | 391 | break; |
| 400 | } | 392 | } |
| 401 | case OP_PUSHNUM: | 393 | case OP_GETGLOBAL: |
| 402 | case OP_PUSHNEGNUM: { | 394 | case OP_SETGLOBAL: { |
| 403 | check(arg1 < pt->sizeknum); | 395 | check(ttype(&pt->k[b]) == LUA_TSTRING); |
| 404 | break; | 396 | break; |
| 405 | } | 397 | } |
| 406 | case OP_PUSHUPVALUE: { | 398 | case OP_SELF: { |
| 407 | check(arg1 < pt->nupvalues); | 399 | checkreg(pt, a+1); |
| 400 | if (reg == a+1) last = pc; | ||
| 408 | break; | 401 | break; |
| 409 | } | 402 | } |
| 410 | case OP_GETLOCAL: | 403 | case OP_CONCAT: { |
| 411 | case OP_GETINDEXED: | 404 | check(b < c); /* at least two operands */ |
| 412 | case OP_SETLOCAL: { | ||
| 413 | check(arg1 < top); | ||
| 414 | break; | 405 | break; |
| 415 | } | 406 | } |
| 416 | case OP_SETTABLE: { | 407 | case OP_JMP: |
| 417 | check(3 <= arg1 && arg1 <= top); | 408 | case OP_CJMP: { |
| 418 | pop = arg2; | 409 | int dest = pc+1+b; |
| 410 | check(0 <= dest && dest < pt->sizecode); | ||
| 411 | /* not full check and jump is forward and do not skip `lastpc'? */ | ||
| 412 | if (reg != NO_REG && pc < dest && dest <= lastpc) | ||
| 413 | pc += b; /* do the jump */ | ||
| 419 | break; | 414 | break; |
| 420 | } | 415 | } |
| 421 | case OP_SETLIST: { | 416 | case OP_TESTT: |
| 422 | check(arg2 >= 0); | 417 | case OP_TESTF: { |
| 423 | pop = top-arg2-1; | 418 | if (a != NO_REG) |
| 419 | checkreg(pt, a); | ||
| 424 | break; | 420 | break; |
| 425 | } | 421 | } |
| 426 | case OP_SETMAP: { | 422 | case OP_NILJMP: { |
| 427 | check(arg1 >= 0); | 423 | check(pc+2 < pt->sizecode); /* check its jump */ |
| 428 | pop = top-arg1-1; | ||
| 429 | break; | 424 | break; |
| 430 | } | 425 | } |
| 431 | case OP_CONCAT: { | 426 | case OP_CALL: { |
| 432 | pop = arg1; | 427 | if (b == NO_REG) b = pt->maxstacksize; |
| 428 | if (c == NO_REG) { | ||
| 429 | check(checkopenop(pt->code[pc+1])); | ||
| 430 | c = 1; | ||
| 431 | } | ||
| 432 | check(b > a); | ||
| 433 | checkreg(pt, b-1); | ||
| 434 | checkreg(pt, a+c-1); | ||
| 435 | if (reg >= a) last = pc; /* affect all registers above base */ | ||
| 433 | break; | 436 | break; |
| 434 | } | 437 | } |
| 435 | case OP_CLOSURE: { | 438 | case OP_RETURN: { |
| 436 | check(arg1 < pt->sizekproto); | 439 | if (b == NO_REG) b = pt->maxstacksize; |
| 437 | check(arg2 == pt->kproto[arg1]->nupvalues); | 440 | checkreg(pt, b-1); |
| 438 | pop = arg2; | ||
| 439 | break; | 441 | break; |
| 440 | } | 442 | } |
| 441 | case OP_JMPNE: | 443 | case OP_FORPREP: |
| 442 | case OP_JMPEQ: | 444 | case OP_TFORPREP: { |
| 443 | case OP_JMPLT: | 445 | int dest = pc-b; /* jump is negated here */ |
| 444 | case OP_JMPLE: | 446 | check(0 <= dest && dest < pt->sizecode && |
| 445 | case OP_JMPGT: | 447 | GET_OPCODE(pt->code[dest]) == op+1); |
| 446 | case OP_JMPGE: | ||
| 447 | case OP_JMPT: | ||
| 448 | case OP_JMPF: | ||
| 449 | case OP_JMP: { | ||
| 450 | checkjump(pt, sl, top-pop, pc+arg1); | ||
| 451 | break; | 448 | break; |
| 452 | } | 449 | } |
| 453 | case OP_FORLOOP: | 450 | case OP_FORLOOP: |
| 454 | case OP_LFORLOOP: | 451 | case OP_TFORLOOP: { |
| 455 | case OP_JMPONT: | 452 | int dest = pc+b; |
| 456 | case OP_JMPONF: { | 453 | check(0 <= dest && dest < pt->sizecode && |
| 457 | int newpc = pc+arg1; | 454 | pt->code[dest] == SET_OPCODE(i, op-1)); |
| 458 | checkjump(pt, sl, top, newpc); | 455 | checkreg(pt, a + ((op == OP_FORLOOP) ? 2 : 3)); |
| 459 | /* jump is forward and do not skip `lastpc' and not full check? */ | ||
| 460 | if (pc < newpc && newpc <= lastpc && stackpos >= 0) { | ||
| 461 | stack[top-1] = pc-1; /* value comes from `and'/`or' */ | ||
| 462 | pc = newpc; /* do the jump */ | ||
| 463 | pop = 0; /* do not pop */ | ||
| 464 | } | ||
| 465 | break; | ||
| 466 | } | ||
| 467 | case OP_PUSHNILJMP: { | ||
| 468 | check(GET_OPCODE(pt->code[pc]) == OP_PUSHINT); /* only valid sequence */ | ||
| 469 | break; | 456 | break; |
| 470 | } | 457 | } |
| 471 | case OP_FORPREP: { | 458 | case OP_SETLIST: { |
| 472 | int endfor = pc-arg1-1; /* jump is `negative' here */ | 459 | checkreg(pt, a + (b&(LFIELDS_PER_FLUSH-1)) + 1); |
| 473 | check(top >= 3); | ||
| 474 | checkjump(pt, sl, top+push, endfor); | ||
| 475 | check(GET_OPCODE(pt->code[endfor]) == OP_FORLOOP); | ||
| 476 | check(GETARG_S(pt->code[endfor]) == arg1); | ||
| 477 | break; | ||
| 478 | } | ||
| 479 | case OP_LFORPREP: { | ||
| 480 | int endfor = pc-arg1-1; /* jump is `negative' here */ | ||
| 481 | check(top >= 1); | ||
| 482 | checkjump(pt, sl, top+push, endfor); | ||
| 483 | check(GET_OPCODE(pt->code[endfor]) == OP_LFORLOOP); | ||
| 484 | check(GETARG_S(pt->code[endfor]) == arg1); | ||
| 485 | break; | 460 | break; |
| 486 | } | 461 | } |
| 487 | case OP_PUSHINT: | 462 | case OP_CLOSURE: { |
| 488 | case OP_GETTABLE: | 463 | check(b < pt->sizekproto); |
| 489 | case OP_CREATETABLE: | 464 | checkreg(pt, a + pt->kproto[b]->nupvalues - 1); |
| 490 | case OP_ADD: | ||
| 491 | case OP_ADDI: | ||
| 492 | case OP_SUB: | ||
| 493 | case OP_MULT: | ||
| 494 | case OP_DIV: | ||
| 495 | case OP_POW: | ||
| 496 | case OP_MINUS: | ||
| 497 | case OP_NOT: { | ||
| 498 | break; | 465 | break; |
| 499 | } | 466 | } |
| 467 | default: break; | ||
| 500 | } | 468 | } |
| 501 | top -= pop; | ||
| 502 | check(0 <= top && top+push <= pt->maxstacksize); | ||
| 503 | while (push--) stack[top++] = pc-1; | ||
| 504 | checkjump(pt, sl, top, pc); | ||
| 505 | } | 469 | } |
| 506 | return (stackpos >= 0) ? pt->code[stack[stackpos]] : 1; | 470 | return pt->code[last]; |
| 507 | } | 471 | } |
| 508 | 472 | ||
| 509 | /* }====================================================== */ | 473 | /* }====================================================== */ |
| 510 | 474 | ||
| 511 | 475 | ||
| 512 | int luaG_checkcode (lua_State *L, const Proto *pt) { | 476 | int luaG_checkcode (const Proto *pt) { |
| 513 | return luaG_symbexec(L, pt, pt->sizecode-1, -1); | 477 | return luaG_symbexec(pt, pt->sizecode, NO_REG); |
| 514 | } | 478 | } |
| 515 | 479 | ||
| 516 | 480 | ||
| 517 | static const l_char *getobjname (lua_State *L, StkId obj, const l_char **name) { | 481 | static const l_char *getobjname (lua_State *L, StkId obj, const l_char **name) { |
| 518 | CallInfo *ci = ci_stack(L, obj); | 482 | CallInfo *ci = ci_stack(L, obj); |
| 519 | if (!isLmark(ci)) | 483 | if (isLmark(ci)) { /* an active Lua function? */ |
| 520 | return NULL; /* not an active Lua function */ | ||
| 521 | else { | ||
| 522 | Proto *p = ci_func(ci)->f.l; | 484 | Proto *p = ci_func(ci)->f.l; |
| 523 | int pc = currentpc(ci); | 485 | int pc = currentpc(ci); |
| 524 | int stackpos = obj - ci->base; | 486 | int stackpos = obj - ci->base; |
| 525 | Instruction i = luaG_symbexec(L, p, pc, stackpos); | 487 | Instruction i; |
| 488 | *name = luaF_getlocalname(p, stackpos+1, pc); | ||
| 489 | if (*name) /* is a local? */ | ||
| 490 | return l_s("local"); | ||
| 491 | i = luaG_symbexec(p, pc, stackpos); /* try symbolic execution */ | ||
| 526 | lua_assert(pc != -1); | 492 | lua_assert(pc != -1); |
| 527 | switch (GET_OPCODE(i)) { | 493 | switch (GET_OPCODE(i)) { |
| 528 | case OP_GETGLOBAL: { | 494 | case OP_GETGLOBAL: { |
| 529 | *name = getstr(p->kstr[GETARG_U(i)]); | 495 | lua_assert(ttype(&p->k[GETARG_Bc(i)]) == LUA_TSTRING); |
| 496 | *name = getstr(tsvalue(&p->k[GETARG_Bc(i)])); | ||
| 530 | return l_s("global"); | 497 | return l_s("global"); |
| 531 | } | 498 | } |
| 532 | case OP_GETLOCAL: { | 499 | case OP_MOVE: { |
| 533 | *name = luaF_getlocalname(p, GETARG_U(i)+1, pc); | 500 | int a = GETARG_A(i); |
| 534 | lua_assert(*name); | 501 | int b = GETARG_B(i); /* move from `b' to `a' */ |
| 535 | return l_s("local"); | 502 | if (b < a) |
| 503 | return getobjname(L, ci->base+b, name); /* get name for `b' */ | ||
| 504 | break; | ||
| 536 | } | 505 | } |
| 537 | case OP_PUSHSELF: | 506 | case OP_GETTABLE: |
| 538 | case OP_GETDOTTED: { | 507 | case OP_SELF: { |
| 539 | *name = getstr(p->kstr[GETARG_U(i)]); | 508 | int c = GETARG_C(i) - MAXSTACK; |
| 540 | return l_s("field"); | 509 | if (c >= 0 && ttype(&p->k[c]) == LUA_TSTRING) { |
| 510 | *name = getstr(tsvalue(&p->k[c])); | ||
| 511 | return l_s("field"); | ||
| 512 | } | ||
| 513 | break; | ||
| 541 | } | 514 | } |
| 542 | default: | 515 | default: break; |
| 543 | return NULL; /* no useful name found */ | ||
| 544 | } | 516 | } |
| 545 | } | 517 | } |
| 518 | return NULL; /* no useful name found */ | ||
| 546 | } | 519 | } |
| 547 | 520 | ||
| 548 | 521 | ||
| @@ -576,10 +549,18 @@ void luaG_typeerror (lua_State *L, StkId o, const l_char *op) { | |||
| 576 | } | 549 | } |
| 577 | 550 | ||
| 578 | 551 | ||
| 579 | void luaG_binerror (lua_State *L, StkId p1, int t, const l_char *op) { | 552 | void luaG_concaterror (lua_State *L, StkId p1, StkId p2) { |
| 580 | if (ttype(p1) == t) p1++; | 553 | if (ttype(p1) == LUA_TSTRING) p1 = p2; |
| 581 | lua_assert(ttype(p1) != t); | 554 | lua_assert(ttype(p1) != LUA_TSTRING); |
| 582 | luaG_typeerror(L, p1, op); | 555 | luaG_typeerror(L, p1, l_s("concat")); |
| 556 | } | ||
| 557 | |||
| 558 | |||
| 559 | void luaG_aritherror (lua_State *L, StkId p1, TObject *p2) { | ||
| 560 | TObject temp; | ||
| 561 | if (luaV_tonumber(p1, &temp) != NULL) | ||
| 562 | p1 = p2; /* first operand is OK; error is in the second */ | ||
| 563 | luaG_typeerror(L, p1, l_s("perform arithmetic on")); | ||
| 583 | } | 564 | } |
| 584 | 565 | ||
| 585 | 566 | ||
| @@ -592,3 +573,52 @@ void luaG_ordererror (lua_State *L, const TObject *p1, const TObject *p2) { | |||
| 592 | luaO_verror(L, l_s("attempt to compare %.10s with %.10s"), t1, t2); | 573 | luaO_verror(L, l_s("attempt to compare %.10s with %.10s"), t1, t2); |
| 593 | } | 574 | } |
| 594 | 575 | ||
| 576 | |||
| 577 | |||
| 578 | #define opmode(t,a,b,c,sa,k,m) (((t)<<OpModeT) | \ | ||
| 579 | ((a)<<OpModeAreg) | ((b)<<OpModeBreg) | ((c)<<OpModeCreg) | \ | ||
| 580 | ((sa)<<OpModesetA) | ((k)<<OpModeK) | (m)) | ||
| 581 | |||
| 582 | |||
| 583 | const unsigned char luaG_opmodes[] = { | ||
| 584 | /* T A B C sA K mode opcode */ | ||
| 585 | opmode(0,1,1,0, 1,0,iABC), /* OP_MOVE */ | ||
| 586 | opmode(0,1,0,0, 1,1,iABc), /* OP_LOADK */ | ||
| 587 | opmode(0,1,0,0, 1,0,iAsBc), /* OP_LOADINT */ | ||
| 588 | opmode(0,1,1,0, 1,0,iABC), /* OP_LOADNIL */ | ||
| 589 | opmode(0,1,0,0, 1,0,iABc), /* OP_LOADUPVAL */ | ||
| 590 | opmode(0,1,0,0, 1,1,iABc), /* OP_GETGLOBAL */ | ||
| 591 | opmode(0,1,1,1, 1,0,iABC), /* OP_GETTABLE */ | ||
| 592 | opmode(0,1,0,0, 0,1,iABc), /* OP_SETGLOBAL */ | ||
| 593 | opmode(0,1,1,1, 0,0,iABC), /* OP_SETTABLE */ | ||
| 594 | opmode(0,1,0,0, 1,0,iABc), /* OP_NEWTABLE */ | ||
| 595 | opmode(0,1,1,1, 1,0,iABC), /* OP_SELF */ | ||
| 596 | opmode(0,1,1,1, 1,0,iABC), /* OP_ADD */ | ||
| 597 | opmode(0,1,1,1, 1,0,iABC), /* OP_SUB */ | ||
| 598 | opmode(0,1,1,1, 1,0,iABC), /* OP_MUL */ | ||
| 599 | opmode(0,1,1,1, 1,0,iABC), /* OP_DIV */ | ||
| 600 | opmode(0,1,1,1, 1,0,iABC), /* OP_POW */ | ||
| 601 | opmode(0,1,1,0, 1,0,iABC), /* OP_UNM */ | ||
| 602 | opmode(0,1,1,0, 1,0,iABC), /* OP_NOT */ | ||
| 603 | opmode(0,1,1,1, 1,0,iABC), /* OP_CONCAT */ | ||
| 604 | opmode(0,0,0,0, 0,0,iAsBc), /* OP_JMP */ | ||
| 605 | opmode(0,0,0,0, 0,0,iAsBc), /* OP_CJMP */ | ||
| 606 | opmode(1,0,1,1, 0,0,iABC), /* OP_TESTEQ */ | ||
| 607 | opmode(1,0,1,1, 0,0,iABC), /* OP_TESTNE */ | ||
| 608 | opmode(1,0,1,1, 0,0,iABC), /* OP_TESTLT */ | ||
| 609 | opmode(1,0,1,1, 0,0,iABC), /* OP_TESTLE */ | ||
| 610 | opmode(1,0,1,1, 0,0,iABC), /* OP_TESTGT */ | ||
| 611 | opmode(1,0,1,1, 0,0,iABC), /* OP_TESTGE */ | ||
| 612 | opmode(1,0,1,0, 1,0,iABC), /* OP_TESTT */ | ||
| 613 | opmode(1,0,1,0, 1,0,iABC), /* OP_TESTF */ | ||
| 614 | opmode(0,1,0,0, 1,0,iAsBc), /* OP_NILJMP */ | ||
| 615 | opmode(0,1,0,0, 0,0,iABC), /* OP_CALL */ | ||
| 616 | opmode(0,1,0,0, 0,0,iABC), /* OP_RETURN */ | ||
| 617 | opmode(0,1,0,0, 0,0,iAsBc), /* OP_FORPREP */ | ||
| 618 | opmode(0,1,0,0, 0,0,iAsBc), /* OP_FORLOOP */ | ||
| 619 | opmode(0,1,0,0, 0,0,iAsBc), /* OP_TFORPREP */ | ||
| 620 | opmode(0,1,0,0, 0,0,iAsBc), /* OP_TFORLOOP */ | ||
| 621 | opmode(0,1,0,0, 0,0,iABc), /* OP_SETLIST */ | ||
| 622 | opmode(0,1,0,0, 0,0,iABc), /* OP_SETLIST0 */ | ||
| 623 | opmode(0,1,0,0, 0,0,iABc) /* OP_CLOSURE */ | ||
| 624 | }; | ||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: ldebug.h,v 1.10 2001/02/12 19:54:50 roberto Exp roberto $ | 2 | ** $Id: ldebug.h,v 1.11 2001/02/23 17:17:25 roberto Exp roberto $ |
| 3 | ** Auxiliary functions from Debug Interface module | 3 | ** Auxiliary functions from Debug Interface module |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -12,11 +12,32 @@ | |||
| 12 | #include "luadebug.h" | 12 | #include "luadebug.h" |
| 13 | 13 | ||
| 14 | 14 | ||
| 15 | enum OpMode {iABC, iABc, iAsBc}; /* basic instruction format */ | ||
| 16 | |||
| 17 | /* | ||
| 18 | ** masks for instruction properties | ||
| 19 | */ | ||
| 20 | enum OpModeMask { | ||
| 21 | OpModeAreg = 2, /* A is a register */ | ||
| 22 | OpModeBreg, /* B is a register */ | ||
| 23 | OpModeCreg, /* C is a register/constant */ | ||
| 24 | OpModesetA, /* instruction set register A */ | ||
| 25 | OpModeK, /* Bc is a constant */ | ||
| 26 | OpModeT /* operator is a test */ | ||
| 27 | }; | ||
| 28 | |||
| 29 | extern const unsigned char luaG_opmodes[]; | ||
| 30 | |||
| 31 | #define getOpMode(m) ((enum OpMode)(luaG_opmodes[m] & 3)) | ||
| 32 | #define testOpMode(m, b) (luaG_opmodes[m] & (1 << (b))) | ||
| 33 | |||
| 34 | |||
| 15 | void luaG_typeerror (lua_State *L, StkId o, const l_char *op); | 35 | void luaG_typeerror (lua_State *L, StkId o, const l_char *op); |
| 16 | void luaG_binerror (lua_State *L, StkId p1, int t, const l_char *op); | 36 | void luaG_concaterror (lua_State *L, StkId p1, StkId p2); |
| 37 | void luaG_aritherror (lua_State *L, StkId p1, TObject *p2); | ||
| 17 | int luaG_getline (int *lineinfo, int pc, int refline, int *refi); | 38 | int luaG_getline (int *lineinfo, int pc, int refline, int *refi); |
| 18 | void luaG_ordererror (lua_State *L, const TObject *p1, const TObject *p2); | 39 | void luaG_ordererror (lua_State *L, const TObject *p1, const TObject *p2); |
| 19 | int luaG_checkcode (lua_State *L, const Proto *pt); | 40 | int luaG_checkcode (const Proto *pt); |
| 20 | 41 | ||
| 21 | 42 | ||
| 22 | #endif | 43 | #endif |
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lfunc.c,v 1.42 2001/02/23 17:17:25 roberto Exp roberto $ | 2 | ** $Id: lfunc.c,v 1.43 2001/03/26 14:31:49 roberto Exp roberto $ |
| 3 | ** Auxiliary functions to manipulate prototypes and closures | 3 | ** Auxiliary functions to manipulate prototypes and closures |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -30,10 +30,8 @@ Closure *luaF_newclosure (lua_State *L, int nelems) { | |||
| 30 | 30 | ||
| 31 | Proto *luaF_newproto (lua_State *L) { | 31 | Proto *luaF_newproto (lua_State *L) { |
| 32 | Proto *f = luaM_new(L, Proto); | 32 | Proto *f = luaM_new(L, Proto); |
| 33 | f->knum = NULL; | 33 | f->k = NULL; |
| 34 | f->sizeknum = 0; | 34 | f->sizek = 0; |
| 35 | f->kstr = NULL; | ||
| 36 | f->sizekstr = 0; | ||
| 37 | f->kproto = NULL; | 35 | f->kproto = NULL; |
| 38 | f->sizekproto = 0; | 36 | f->sizekproto = 0; |
| 39 | f->code = NULL; | 37 | f->code = NULL; |
| @@ -58,8 +56,7 @@ Proto *luaF_newproto (lua_State *L) { | |||
| 58 | void luaF_freeproto (lua_State *L, Proto *f) { | 56 | void luaF_freeproto (lua_State *L, Proto *f) { |
| 59 | luaM_freearray(L, f->code, f->sizecode, Instruction); | 57 | luaM_freearray(L, f->code, f->sizecode, Instruction); |
| 60 | luaM_freearray(L, f->locvars, f->sizelocvars, struct LocVar); | 58 | luaM_freearray(L, f->locvars, f->sizelocvars, struct LocVar); |
| 61 | luaM_freearray(L, f->kstr, f->sizekstr, TString *); | 59 | luaM_freearray(L, f->k, f->sizek, TObject); |
| 62 | luaM_freearray(L, f->knum, f->sizeknum, lua_Number); | ||
| 63 | luaM_freearray(L, f->kproto, f->sizekproto, Proto *); | 60 | luaM_freearray(L, f->kproto, f->sizekproto, Proto *); |
| 64 | luaM_freearray(L, f->lineinfo, f->sizelineinfo, int); | 61 | luaM_freearray(L, f->lineinfo, f->sizelineinfo, int); |
| 65 | luaM_freelem(L, f, Proto); | 62 | luaM_freelem(L, f, Proto); |
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lgc.c,v 1.96 2001/04/11 14:42:41 roberto Exp roberto $ | 2 | ** $Id: lgc.c,v 1.97 2001/04/17 17:35:54 roberto Exp roberto $ |
| 3 | ** Garbage Collector | 3 | ** Garbage Collector |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -48,8 +48,10 @@ static void protomark (Proto *f) { | |||
| 48 | int i; | 48 | int i; |
| 49 | f->marked = 1; | 49 | f->marked = 1; |
| 50 | strmark(f->source); | 50 | strmark(f->source); |
| 51 | for (i=0; i<f->sizekstr; i++) | 51 | for (i=0; i<f->sizek; i++) { |
| 52 | strmark(f->kstr[i]); | 52 | if (ttype(f->k+i) == LUA_TSTRING) |
| 53 | strmark(tsvalue(f->k+i)); | ||
| 54 | } | ||
| 53 | for (i=0; i<f->sizekproto; i++) | 55 | for (i=0; i<f->sizekproto; i++) |
| 54 | protomark(f->kproto[i]); | 56 | protomark(f->kproto[i]); |
| 55 | for (i=0; i<f->sizelocvars; i++) /* mark local-variable names */ | 57 | for (i=0; i<f->sizelocvars; i++) /* mark local-variable names */ |
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: llimits.h,v 1.27 2001/02/23 20:28:56 roberto Exp roberto $ | 2 | ** $Id: llimits.h,v 1.28 2001/03/26 14:31:49 roberto Exp roberto $ |
| 3 | ** Limits, basic types, and some other `installation-dependent' definitions | 3 | ** Limits, basic types, and some other `installation-dependent' definitions |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -89,92 +89,23 @@ union L_Umaxalign { double d; void *s; long l; }; | |||
| 89 | /* | 89 | /* |
| 90 | ** type for virtual-machine instructions | 90 | ** type for virtual-machine instructions |
| 91 | ** must be an unsigned with (at least) 4 bytes (see details in lopcodes.h) | 91 | ** must be an unsigned with (at least) 4 bytes (see details in lopcodes.h) |
| 92 | ** For a very small machine, you may change that to 2 bytes (and adjust | ||
| 93 | ** the following limits accordingly) | ||
| 94 | */ | 92 | */ |
| 95 | typedef unsigned long Instruction; | 93 | typedef unsigned long Instruction; |
| 96 | 94 | ||
| 97 | 95 | ||
| 98 | /* | 96 | /* maximum stack for a Lua function */ |
| 99 | ** size and position of opcode arguments. | ||
| 100 | ** For an instruction with 2 bytes, size is 16, and size_b can be 5 | ||
| 101 | ** (accordingly, size_u will be 10, and size_a will be 5) | ||
| 102 | */ | ||
| 103 | #define SIZE_INSTRUCTION 32 | ||
| 104 | #define SIZE_B 8 | ||
| 105 | |||
| 106 | #define SIZE_OP 6 | ||
| 107 | #define SIZE_U (SIZE_INSTRUCTION-SIZE_OP) | ||
| 108 | #define POS_U SIZE_OP | ||
| 109 | #define POS_B SIZE_OP | ||
| 110 | #define SIZE_A (SIZE_INSTRUCTION-(SIZE_OP+SIZE_B)) | ||
| 111 | #define POS_A (SIZE_OP+SIZE_B) | ||
| 112 | |||
| 113 | |||
| 114 | /* | ||
| 115 | ** limits for opcode arguments. | ||
| 116 | ** we use (signed) int to manipulate most arguments, | ||
| 117 | ** so they must fit in BITS_INT-1 bits (-1 for sign) | ||
| 118 | */ | ||
| 119 | #if SIZE_U < BITS_INT-1 | ||
| 120 | #define MAXARG_U ((1<<SIZE_U)-1) | ||
| 121 | #define MAXARG_S (MAXARG_U>>1) /* `S' is signed */ | ||
| 122 | #else | ||
| 123 | #define MAXARG_U MAX_INT | ||
| 124 | #define MAXARG_S MAX_INT | ||
| 125 | #endif | ||
| 126 | |||
| 127 | #if SIZE_A < BITS_INT-1 | ||
| 128 | #define MAXARG_A ((1<<SIZE_A)-1) | ||
| 129 | #else | ||
| 130 | #define MAXARG_A MAX_INT | ||
| 131 | #endif | ||
| 132 | |||
| 133 | #if SIZE_B < BITS_INT-1 | ||
| 134 | #define MAXARG_B ((1<<SIZE_B)-1) | ||
| 135 | #else | ||
| 136 | #define MAXARG_B MAX_INT | ||
| 137 | #endif | ||
| 138 | |||
| 139 | |||
| 140 | /* maximum stack size in a function */ | ||
| 141 | #ifndef MAXSTACK | ||
| 142 | #define MAXSTACK 250 | 97 | #define MAXSTACK 250 |
| 143 | #endif | ||
| 144 | |||
| 145 | #if MAXSTACK > MAXARG_B | ||
| 146 | #undef MAXSTACK | ||
| 147 | #define MAXSTACK MAXARG_B | ||
| 148 | #endif | ||
| 149 | 98 | ||
| 150 | 99 | ||
| 151 | /* maximum number of local variables */ | 100 | /* maximum number of local variables */ |
| 152 | #ifndef MAXLOCALS | 101 | #ifndef MAXLOCALS |
| 153 | #define MAXLOCALS 200 /* arbitrary limit (<MAXSTACK) */ | 102 | #define MAXLOCALS 200 /* arbitrary limit (<MAXSTACK) */ |
| 154 | #endif | 103 | #endif |
| 155 | #if MAXLOCALS>=MAXSTACK | ||
| 156 | #undef MAXLOCALS | ||
| 157 | #define MAXLOCALS (MAXSTACK-1) | ||
| 158 | #endif | ||
| 159 | 104 | ||
| 160 | 105 | ||
| 161 | /* maximum number of upvalues */ | 106 | /* maximum number of upvalues */ |
| 162 | #ifndef MAXUPVALUES | 107 | #ifndef MAXUPVALUES |
| 163 | #define MAXUPVALUES 32 /* arbitrary limit (<=MAXARG_B) */ | 108 | #define MAXUPVALUES 32 /* arbitrary limit (<MAXSTACK) */ |
| 164 | #endif | ||
| 165 | #if MAXUPVALUES>MAXARG_B | ||
| 166 | #undef MAXUPVALUES | ||
| 167 | #define MAXUPVALUES MAXARG_B | ||
| 168 | #endif | ||
| 169 | |||
| 170 | |||
| 171 | /* maximum number of variables in the left side of an assignment */ | ||
| 172 | #ifndef MAXVARSLH | ||
| 173 | #define MAXVARSLH 100 /* arbitrary limit (<MULT_RET) */ | ||
| 174 | #endif | ||
| 175 | #if MAXVARSLH>=MULT_RET | ||
| 176 | #undef MAXVARSLH | ||
| 177 | #define MAXVARSLH (MULT_RET-1) | ||
| 178 | #endif | 109 | #endif |
| 179 | 110 | ||
| 180 | 111 | ||
| @@ -182,27 +113,17 @@ typedef unsigned long Instruction; | |||
| 182 | #ifndef MAXPARAMS | 113 | #ifndef MAXPARAMS |
| 183 | #define MAXPARAMS 100 /* arbitrary limit (<MAXLOCALS) */ | 114 | #define MAXPARAMS 100 /* arbitrary limit (<MAXLOCALS) */ |
| 184 | #endif | 115 | #endif |
| 185 | #if MAXPARAMS>=MAXLOCALS | ||
| 186 | #undef MAXPARAMS | ||
| 187 | #define MAXPARAMS (MAXLOCALS-1) | ||
| 188 | #endif | ||
| 189 | 116 | ||
| 190 | 117 | ||
| 191 | /* number of list items to accumulate before a SETLIST instruction */ | 118 | /* number of list items to accumulate before a SETLIST instruction */ |
| 119 | /* (must be a power of 2) */ | ||
| 192 | #define LFIELDS_PER_FLUSH 64 | 120 | #define LFIELDS_PER_FLUSH 64 |
| 193 | #if LFIELDS_PER_FLUSH>(MAXSTACK/4) | ||
| 194 | #undef LFIELDS_PER_FLUSH | ||
| 195 | #define LFIELDS_PER_FLUSH (MAXSTACK/4) | ||
| 196 | #endif | ||
| 197 | 121 | ||
| 198 | /* number of record items to accumulate before a SETMAP instruction */ | ||
| 199 | /* (each item counts 2 elements on the stack: an index and a value) */ | ||
| 200 | #define RFIELDS_PER_FLUSH (LFIELDS_PER_FLUSH/2) | ||
| 201 | 122 | ||
| 202 | 123 | ||
| 203 | /* maximum lookback to find a real constant (for code generation) */ | 124 | /* maximum lookback to find a real constant (for code generation) */ |
| 204 | #ifndef LOOKBACKNUMS | 125 | #ifndef LOOKBACKNUMS |
| 205 | #define LOOKBACKNUMS 20 /* arbitrary constant */ | 126 | #define LOOKBACKNUMS 40 /* arbitrary constant */ |
| 206 | #endif | 127 | #endif |
| 207 | 128 | ||
| 208 | 129 | ||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lobject.h,v 1.101 2001/03/07 18:09:25 roberto Exp roberto $ | 2 | ** $Id: lobject.h,v 1.102 2001/04/11 14:42:41 roberto Exp roberto $ |
| 3 | ** Type definitions for Lua objects | 3 | ** Type definitions for Lua objects |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -114,10 +114,8 @@ union L_UTString { | |||
| 114 | ** Function Prototypes | 114 | ** Function Prototypes |
| 115 | */ | 115 | */ |
| 116 | typedef struct Proto { | 116 | typedef struct Proto { |
| 117 | lua_Number *knum; /* numbers used by the function */ | 117 | TObject *k; /* constants used by the function */ |
| 118 | int sizeknum; /* size of `knum' */ | 118 | int sizek; /* size of `k' */ |
| 119 | struct TString **kstr; /* strings used by the function */ | ||
| 120 | int sizekstr; /* size of `kstr' */ | ||
| 121 | struct Proto **kproto; /* functions defined inside the function */ | 119 | struct Proto **kproto; /* functions defined inside the function */ |
| 122 | int sizekproto; /* size of `kproto' */ | 120 | int sizekproto; /* size of `kproto' */ |
| 123 | Instruction *code; | 121 | Instruction *code; |
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lopcodes.h,v 1.71 2001/03/07 13:22:55 roberto Exp roberto $ | 2 | ** $Id: lopcodes.h,v 1.72 2001/04/06 18:25:00 roberto Exp roberto $ |
| 3 | ** Opcodes for Lua virtual machine | 3 | ** Opcodes for Lua virtual machine |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -12,29 +12,55 @@ | |||
| 12 | 12 | ||
| 13 | /*=========================================================================== | 13 | /*=========================================================================== |
| 14 | We assume that instructions are unsigned numbers. | 14 | We assume that instructions are unsigned numbers. |
| 15 | All instructions have an opcode in the first 6 bits. Moreover, | 15 | All instructions have an opcode in the first 6 bits. |
| 16 | an instruction can have 0, 1, or 2 arguments. Instructions can | 16 | Instructions can have the following fields: |
| 17 | have the following types: | 17 | `A' : 8 bits (25-32) |
| 18 | type 0: no arguments | 18 | `B' : 8 bits (17-24) |
| 19 | type 1: 1 unsigned argument in the higher bits (called `U') | 19 | `C' : 10 bits (7-16) |
| 20 | type 2: 1 signed argument in the higher bits (`S') | 20 | `Bc' : 18 bits (`B' and `C' together) |
| 21 | type 3: 1st unsigned argument in the higher bits (`A') | 21 | `sBc' : signed Bc |
| 22 | 2nd unsigned argument in the middle bits (`B') | ||
| 23 | 22 | ||
| 24 | A signed argument is represented in excess K; that is, the number | 23 | A signed argument is represented in excess K; that is, the number |
| 25 | value is the unsigned value minus K. K is exactly the maximum value | 24 | value is the unsigned value minus K. K is exactly the maximum value |
| 26 | for that argument (so that -max is represented by 0, and +max is | 25 | for that argument (so that -max is represented by 0, and +max is |
| 27 | represented by 2*max), which is half the maximum for the corresponding | 26 | represented by 2*max), which is half the maximum for the corresponding |
| 28 | unsigned argument. | 27 | unsigned argument. |
| 29 | |||
| 30 | The size of each argument is defined in `llimits.h'. The usual is an | ||
| 31 | instruction with 32 bits, U arguments with 26 bits (32-6), B arguments | ||
| 32 | with 9 bits, and A arguments with 17 bits (32-6-9). For small | ||
| 33 | installations, the instruction size can be 16, so U has 10 bits, | ||
| 34 | and A and B have 5 bits each. | ||
| 35 | ===========================================================================*/ | 28 | ===========================================================================*/ |
| 36 | 29 | ||
| 37 | 30 | ||
| 31 | /* | ||
| 32 | ** size and position of opcode arguments. | ||
| 33 | */ | ||
| 34 | #define SIZE_C 10 | ||
| 35 | #define SIZE_B 8 | ||
| 36 | #define SIZE_Bc (SIZE_C + SIZE_B) | ||
| 37 | #define SIZE_A 8 | ||
| 38 | |||
| 39 | #define SIZE_OP 6 | ||
| 40 | |||
| 41 | #define POS_C SIZE_OP | ||
| 42 | #define POS_B (POS_C + SIZE_C) | ||
| 43 | #define POS_Bc POS_C | ||
| 44 | #define POS_A (POS_B + SIZE_B) | ||
| 45 | |||
| 46 | |||
| 47 | /* | ||
| 48 | ** limits for opcode arguments. | ||
| 49 | ** we use (signed) int to manipulate most arguments, | ||
| 50 | ** so they must fit in BITS_INT-1 bits (-1 for sign) | ||
| 51 | */ | ||
| 52 | #if SIZE_Bc < BITS_INT-1 | ||
| 53 | #define MAXARG_Bc ((1<<SIZE_Bc)-1) | ||
| 54 | #define MAXARG_sBc (MAXARG_Bc>>1) /* `sBc' is signed */ | ||
| 55 | #else | ||
| 56 | #define MAXARG_Bc MAX_INT | ||
| 57 | #define MAXARG_sBc MAX_INT | ||
| 58 | #endif | ||
| 59 | |||
| 60 | |||
| 61 | #define MAXARG_A ((1<<SIZE_A)-1) | ||
| 62 | #define MAXARG_B ((1<<SIZE_B)-1) | ||
| 63 | #define MAXARG_C ((1<<SIZE_C)-1) | ||
| 38 | 64 | ||
| 39 | 65 | ||
| 40 | /* creates a mask with `n' 1 bits at position `p' */ | 66 | /* creates a mask with `n' 1 bits at position `p' */ |
| @@ -47,120 +73,129 @@ | |||
| 47 | ** the following macros help to manipulate instructions | 73 | ** the following macros help to manipulate instructions |
| 48 | */ | 74 | */ |
| 49 | 75 | ||
| 50 | #define CREATE_0(o) ((Instruction)(o)) | ||
| 51 | #define GET_OPCODE(i) ((OpCode)((i)&MASK1(SIZE_OP,0))) | 76 | #define GET_OPCODE(i) ((OpCode)((i)&MASK1(SIZE_OP,0))) |
| 52 | #define SET_OPCODE(i,o) ((i) = (((i)&MASK0(SIZE_OP,0)) | (Instruction)(o))) | 77 | #define SET_OPCODE(i,o) (((i)&MASK0(SIZE_OP,0)) | (Instruction)(o)) |
| 53 | |||
| 54 | #define CREATE_U(o,u) ((Instruction)(o) | ((Instruction)(u)<<POS_U)) | ||
| 55 | #define GETARG_U(i) ((int)((i)>>POS_U)) | ||
| 56 | #define SETARG_U(i,u) ((i) = (((i)&MASK0(SIZE_U,POS_U)) | \ | ||
| 57 | ((Instruction)(u)<<POS_U))) | ||
| 58 | 78 | ||
| 59 | #define CREATE_S(o,s) CREATE_U((o),(s)+MAXARG_S) | ||
| 60 | #define GETARG_S(i) (GETARG_U(i)-MAXARG_S) | ||
| 61 | #define SETARG_S(i,s) SETARG_U((i),(s)+MAXARG_S) | ||
| 62 | |||
| 63 | |||
| 64 | #define CREATE_AB(o,a,b) ((Instruction)(o) | ((Instruction)(a)<<POS_A) \ | ||
| 65 | | ((Instruction)(b)<<POS_B)) | ||
| 66 | #define GETARG_A(i) ((int)((i)>>POS_A)) | 79 | #define GETARG_A(i) ((int)((i)>>POS_A)) |
| 67 | #define SETARG_A(i,a) ((i) = (((i)&MASK0(SIZE_A,POS_A)) | \ | 80 | #define SETARG_A(i,u) ((i) = (((i)&MASK0(SIZE_A,POS_A)) | \ |
| 68 | ((Instruction)(a)<<POS_A))) | 81 | ((Instruction)(u)<<POS_A))) |
| 82 | |||
| 69 | #define GETARG_B(i) ((int)(((i)>>POS_B) & MASK1(SIZE_B,0))) | 83 | #define GETARG_B(i) ((int)(((i)>>POS_B) & MASK1(SIZE_B,0))) |
| 70 | #define SETARG_B(i,b) ((i) = (((i)&MASK0(SIZE_B,POS_B)) | \ | 84 | #define SETARG_B(i,b) ((i) = (((i)&MASK0(SIZE_B,POS_B)) | \ |
| 71 | ((Instruction)(b)<<POS_B))) | 85 | ((Instruction)(b)<<POS_B))) |
| 72 | 86 | ||
| 87 | #define GETARG_C(i) ((int)(((i)>>POS_C) & MASK1(SIZE_C,0))) | ||
| 88 | #define SETARG_C(i,b) ((i) = (((i)&MASK0(SIZE_C,POS_C)) | \ | ||
| 89 | ((Instruction)(b)<<POS_C))) | ||
| 90 | |||
| 91 | #define GETARG_Bc(i) ((int)(((i)>>POS_Bc) & MASK1(SIZE_Bc,0))) | ||
| 92 | #define SETARG_Bc(i,b) ((i) = (((i)&MASK0(SIZE_Bc,POS_Bc)) | \ | ||
| 93 | ((Instruction)(b)<<POS_Bc))) | ||
| 94 | |||
| 95 | #define GETARG_sBc(i) (GETARG_Bc(i)-MAXARG_sBc) | ||
| 96 | #define SETARG_sBc(i,b) SETARG_Bc((i),(b)+MAXARG_sBc) | ||
| 97 | |||
| 98 | |||
| 99 | #define CREATE_ABC(o,a,b,c) ((Instruction)(o) \ | ||
| 100 | | ((Instruction)(a)<<POS_A) \ | ||
| 101 | | ((Instruction)(b)<<POS_B) \ | ||
| 102 | | ((Instruction)(c)<<POS_C)) | ||
| 103 | |||
| 104 | #define CREATE_ABc(o,a,bc) ((Instruction)(o) \ | ||
| 105 | | ((Instruction)(a)<<POS_A) \ | ||
| 106 | | ((Instruction)(bc)<<POS_Bc)) | ||
| 107 | |||
| 108 | |||
| 109 | |||
| 73 | 110 | ||
| 74 | /* | 111 | /* |
| 75 | ** K = U argument used as index to `kstr' | 112 | ** an invalid register that fits in 8 bits |
| 76 | ** J = S argument used as jump offset (relative to pc of next instruction) | 113 | */ |
| 77 | ** L = unsigned argument used as index of local variable | 114 | #define NO_REG MAXARG_A |
| 78 | ** N = U argument used as index to `knum' | 115 | |
| 116 | |||
| 117 | /* | ||
| 118 | ** R(x) - register | ||
| 119 | ** Kst(x) - constant (in constant table) | ||
| 120 | ** R/K(x) == if x < MAXSTACK then R(x) else Kst(x-MAXSTACK) | ||
| 79 | */ | 121 | */ |
| 80 | 122 | ||
| 81 | typedef enum { | 123 | typedef enum { |
| 82 | /*---------------------------------------------------------------------- | 124 | /*---------------------------------------------------------------------- |
| 83 | name args stack before stack after side effects | 125 | name args description |
| 84 | ------------------------------------------------------------------------*/ | 126 | ------------------------------------------------------------------------*/ |
| 85 | OP_RETURN,/* U v_n-v_x(at u) (return) returns v_x-v_n */ | 127 | OP_MOVE,/* A B R(A) := R(B) */ |
| 86 | 128 | OP_LOADK,/* A Bc R(A) := Kst(Bc) */ | |
| 87 | OP_CALL,/* A B v_n-v_1 f(at a) r_b-r_1 f(v1,...,v_n) */ | 129 | OP_LOADINT,/* A sBc R(A) := (Number)sBc */ |
| 88 | 130 | OP_LOADNIL,/* A B R(A) := ... := R(B) := nil */ | |
| 89 | OP_PUSHNIL,/* U - nil_1-nil_u */ | 131 | OP_LOADUPVAL,/* A Bc R(A) := UpValue[Bc] */ |
| 90 | OP_POP,/* U a_u-a_1 - */ | ||
| 91 | 132 | ||
| 92 | OP_PUSHINT,/* S - (lua_Number)s */ | 133 | OP_GETGLOBAL,/* A Bc R(A) := Gbl[Kst(Bc)] */ |
| 93 | OP_PUSHSTRING,/* K - KSTR[k] */ | 134 | OP_GETTABLE,/* A B C R(A) := R(B)[R/K(C)] */ |
| 94 | OP_PUSHNUM,/* N - KNUM[n] */ | ||
| 95 | OP_PUSHNEGNUM,/* N - -KNUM[n] */ | ||
| 96 | 135 | ||
| 97 | OP_PUSHUPVALUE,/* U - Closure[u] */ | 136 | OP_SETGLOBAL,/* A Bc Gbl[Kst(Bc)] := R(A) */ |
| 137 | OP_SETTABLE,/* A B C R(B)[R/K(C)] := R(A) */ | ||
| 98 | 138 | ||
| 99 | OP_GETLOCAL,/* L - LOC[l] */ | 139 | OP_NEWTABLE,/* A Bc R(A) := {} (size = Bc) */ |
| 100 | OP_GETGLOBAL,/* K - VAR[KSTR[k]] */ | ||
| 101 | 140 | ||
| 102 | OP_GETTABLE,/* - i t t[i] */ | 141 | OP_SELF,/* A B C R(A+1) := R(B); R(A) := R(B)[R/K(C)] */ |
| 103 | OP_GETDOTTED,/* K t t[KSTR[k]] */ | ||
| 104 | OP_GETINDEXED,/* L t t[LOC[l]] */ | ||
| 105 | OP_PUSHSELF,/* K t t t[KSTR[k]] */ | ||
| 106 | 142 | ||
| 107 | OP_CREATETABLE,/* U - newarray(size = u) */ | 143 | OP_ADD,/* A B C R(A) := R(B) + R/K(C) */ |
| 144 | OP_SUB,/* A B C R(A) := R(B) - R/K(C) */ | ||
| 145 | OP_MUL,/* A B C R(A) := R(B) * R/K(C) */ | ||
| 146 | OP_DIV,/* A B C R(A) := R(B) / R/K(C) */ | ||
| 147 | OP_POW,/* A B C R(A) := R(B) ^ R/K(C) */ | ||
| 148 | OP_UNM,/* A B R(A) := -R(B) */ | ||
| 149 | OP_NOT,/* A B R(A) := not R(B) */ | ||
| 108 | 150 | ||
| 109 | OP_SETLOCAL,/* L x - LOC[l]=x */ | 151 | OP_CONCAT,/* A B C R(A) := R(B).. ... ..R(C) */ |
| 110 | OP_SETGLOBAL,/* K x - VAR[KSTR[k]]=x */ | ||
| 111 | OP_SETTABLE,/* A B v a_a-a_1 i t (pops b values) t[i]=v */ | ||
| 112 | 152 | ||
| 113 | OP_SETLIST,/* A B v_n-v_1 v_b v_b v_b[i+a*FPF]=v_i */ | 153 | OP_JMP,/* sBc PC += sBc */ |
| 114 | OP_SETMAP,/* U v_n k_n - v_1 k_1 v_u v_u v_u[k_i]=v_i */ | 154 | OP_CJMP,/* sBc if test then PC += sBc (see (1)) */ |
| 115 | 155 | ||
| 116 | OP_ADD,/* - y x x+y */ | 156 | OP_TESTEQ,/* B C test := (R(B) == R/K(C)) */ |
| 117 | OP_ADDI,/* S x x+s */ | 157 | OP_TESTNE,/* B C test := (R(B) ~= R/K(C)) */ |
| 118 | OP_SUB,/* - y x x-y */ | 158 | OP_TESTLT,/* B C test := (R(B) < R/K(C)) */ |
| 119 | OP_MULT,/* - y x x*y */ | 159 | OP_TESTLE,/* B C test := (R(B) <= R/K(C)) */ |
| 120 | OP_DIV,/* - y x x/y */ | 160 | OP_TESTGT,/* B C test := (R(B) > R/K(C)) */ |
| 121 | OP_POW,/* - y x x^y */ | 161 | OP_TESTGE,/* B C test := (R(B) >= R/K(C)) */ |
| 122 | OP_CONCAT,/* U v_u-v_1 v1..-..v_u */ | ||
| 123 | OP_MINUS,/* - x -x */ | ||
| 124 | OP_NOT,/* - x (x==nil)? 1 : nil */ | ||
| 125 | 162 | ||
| 126 | OP_JMPNE,/* J y x - (x~=y)? PC+=s */ | 163 | OP_TESTT,/* A B test := R(B); if (test) R(A) := R(B) */ |
| 127 | OP_JMPEQ,/* J y x - (x==y)? PC+=s */ | 164 | OP_TESTF,/* A B test := not R(B); if (test) R(A) := nil */ |
| 128 | OP_JMPLT,/* J y x - (x<y)? PC+=s */ | ||
| 129 | OP_JMPLE,/* J y x - (x<y)? PC+=s */ | ||
| 130 | OP_JMPGT,/* J y x - (x>y)? PC+=s */ | ||
| 131 | OP_JMPGE,/* J y x - (x>=y)? PC+=s */ | ||
| 132 | 165 | ||
| 133 | OP_JMPT,/* J x - (x~=nil)? PC+=s */ | 166 | OP_NILJMP,/* A R(A) := nil; PC++; */ |
| 134 | OP_JMPF,/* J x - (x==nil)? PC+=s */ | ||
| 135 | OP_JMPONT,/* J x (x~=nil)? x : - (x~=nil)? PC+=s */ | ||
| 136 | OP_JMPONF,/* J x (x==nil)? x : - (x==nil)? PC+=s */ | ||
| 137 | OP_JMP,/* J - - PC+=s */ | ||
| 138 | 167 | ||
| 139 | OP_PUSHNILJMP,/* - - nil PC++; */ | 168 | OP_CALL,/* A B C R(A), ... ,R(A+C-1) := R(A)(R(A+1), ... ,R(B-1))*/ |
| 169 | OP_RETURN,/* A B return R(A), ... ,R(B-1) (see (3)) */ | ||
| 140 | 170 | ||
| 141 | OP_FORPREP,/* J */ | 171 | OP_FORPREP,/* A sBc */ |
| 142 | OP_FORLOOP,/* J */ | 172 | OP_FORLOOP,/* A sBc */ |
| 143 | 173 | ||
| 144 | OP_LFORPREP,/* J */ | 174 | OP_TFORPREP,/* A sBc */ |
| 145 | OP_LFORLOOP,/* J */ | 175 | OP_TFORLOOP,/* A sBc */ |
| 146 | 176 | ||
| 147 | OP_CLOSURE/* A B v_b-v_1 closure(KPROTO[a], v_1-v_b) */ | 177 | OP_SETLIST,/* A Bc R(A)[Bc-Bc%FPF+i] := R(A+i), 1 <= i <= Bc%FPF+1 */ |
| 178 | OP_SETLISTO,/* A Bc */ | ||
| 148 | 179 | ||
| 180 | OP_CLOSURE /* A Bc R(A) := closure(KPROTO[Bc], R(A), ... ,R(A+n)) */ | ||
| 149 | } OpCode; | 181 | } OpCode; |
| 150 | 182 | ||
| 183 | |||
| 151 | #define NUM_OPCODES ((int)OP_CLOSURE+1) | 184 | #define NUM_OPCODES ((int)OP_CLOSURE+1) |
| 152 | 185 | ||
| 153 | 186 | ||
| 154 | #define ISJUMP(o) (OP_JMPNE <= (o) && (o) <= OP_JMP) | ||
| 155 | 187 | ||
| 188 | /*=========================================================================== | ||
| 189 | Notes: | ||
| 190 | (1) In the current implementation there is no `test' variable; | ||
| 191 | instructions OP_TEST* and OP_CJMP must always occur together. | ||
| 156 | 192 | ||
| 193 | (2) In OP_CALL, if (B == NO_REG) then B = top. C is the number of returns, | ||
| 194 | and can be NO_REG. OP_CALL always set "top" to last_result+1, so | ||
| 195 | next open instruction (OP_CALL, OP_RETURN, OP_SETLIST) may use "top". | ||
| 157 | 196 | ||
| 158 | /* special code to fit a LUA_MULTRET inside an argB */ | 197 | (3) In OP_RETURN, if (B == NO_REG) then B = top. |
| 159 | #define MULT_RET 255 /* (<=MAXARG_B) */ | 198 | ===========================================================================*/ |
| 160 | #if MULT_RET>MAXARG_B | ||
| 161 | #undef MULT_RET | ||
| 162 | #define MULT_RET MAXARG_B | ||
| 163 | #endif | ||
| 164 | 199 | ||
| 165 | 200 | ||
| 166 | #endif | 201 | #endif |
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lparser.c,v 1.141 2001/04/05 16:49:14 roberto Exp roberto $ | 2 | ** $Id: lparser.c,v 1.142 2001/04/06 18:25:00 roberto Exp roberto $ |
| 3 | ** LL(1) Parser and code generator for Lua | 3 | ** LL(1) Parser and code generator for Lua |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -35,10 +35,12 @@ typedef struct Constdesc { | |||
| 35 | } Constdesc; | 35 | } Constdesc; |
| 36 | 36 | ||
| 37 | 37 | ||
| 38 | /* | ||
| 39 | ** nodes for break list (list of active breakable loops) | ||
| 40 | */ | ||
| 38 | typedef struct Breaklabel { | 41 | typedef struct Breaklabel { |
| 39 | struct Breaklabel *previous; /* chain */ | 42 | struct Breaklabel *previous; /* chain */ |
| 40 | int breaklist; | 43 | int breaklist; /* list of jumps out of this loop */ |
| 41 | int stacklevel; | ||
| 42 | } Breaklabel; | 44 | } Breaklabel; |
| 43 | 45 | ||
| 44 | 46 | ||
| @@ -47,11 +49,10 @@ typedef struct Breaklabel { | |||
| 47 | /* | 49 | /* |
| 48 | ** prototypes for recursive non-terminal functions | 50 | ** prototypes for recursive non-terminal functions |
| 49 | */ | 51 | */ |
| 50 | static void body (LexState *ls, int needself, int line); | 52 | static void body (LexState *ls, expdesc *v, int needself, int line); |
| 51 | static void chunk (LexState *ls); | 53 | static void chunk (LexState *ls); |
| 52 | static void constructor (LexState *ls); | 54 | static void constructor (LexState *ls, expdesc *v); |
| 53 | static void expr (LexState *ls, expdesc *v); | 55 | static void expr (LexState *ls, expdesc *v); |
| 54 | static void exp1 (LexState *ls); | ||
| 55 | 56 | ||
| 56 | 57 | ||
| 57 | 58 | ||
| @@ -119,25 +120,6 @@ static void check_match (LexState *ls, int what, int who, int where) { | |||
| 119 | } | 120 | } |
| 120 | 121 | ||
| 121 | 122 | ||
| 122 | static int string_constant (FuncState *fs, TString *s) { | ||
| 123 | Proto *f = fs->f; | ||
| 124 | int c = s->u.s.constindex; | ||
| 125 | if (c >= fs->nkstr || f->kstr[c] != s) { | ||
| 126 | luaM_growvector(fs->L, f->kstr, fs->nkstr, f->sizekstr, TString *, | ||
| 127 | MAXARG_U, l_s("constant table overflow")); | ||
| 128 | c = fs->nkstr++; | ||
| 129 | f->kstr[c] = s; | ||
| 130 | s->u.s.constindex = c; /* hint for next time */ | ||
| 131 | } | ||
| 132 | return c; | ||
| 133 | } | ||
| 134 | |||
| 135 | |||
| 136 | static void code_string (LexState *ls, TString *s) { | ||
| 137 | luaK_kstr(ls, string_constant(ls->fs, s)); | ||
| 138 | } | ||
| 139 | |||
| 140 | |||
| 141 | static TString *str_checkname (LexState *ls) { | 123 | static TString *str_checkname (LexState *ls) { |
| 142 | TString *ts; | 124 | TString *ts; |
| 143 | check_condition(ls, (ls->t.token == TK_NAME), l_s("<name> expected")); | 125 | check_condition(ls, (ls->t.token == TK_NAME), l_s("<name> expected")); |
| @@ -147,11 +129,21 @@ static TString *str_checkname (LexState *ls) { | |||
| 147 | } | 129 | } |
| 148 | 130 | ||
| 149 | 131 | ||
| 150 | static int checkname (LexState *ls) { | 132 | static void init_exp (expdesc *e, expkind k, int i) { |
| 151 | return string_constant(ls->fs, str_checkname(ls)); | 133 | e->f = e->t = NO_JUMP; |
| 134 | e->k = k; | ||
| 135 | e->u.i.info = i; | ||
| 136 | } | ||
| 137 | |||
| 138 | |||
| 139 | static void codestring (LexState *ls, expdesc *e, TString *s) { | ||
| 140 | init_exp(e, VK, luaK_stringk(ls->fs, s)); | ||
| 152 | } | 141 | } |
| 153 | 142 | ||
| 154 | 143 | ||
| 144 | #define checkname(ls,e) codestring(ls,e,str_checkname(ls)) | ||
| 145 | |||
| 146 | |||
| 155 | static int luaI_registerlocalvar (LexState *ls, TString *varname) { | 147 | static int luaI_registerlocalvar (LexState *ls, TString *varname) { |
| 156 | FuncState *fs = ls->fs; | 148 | FuncState *fs = ls->fs; |
| 157 | Proto *f = fs->f; | 149 | Proto *f = fs->f; |
| @@ -195,14 +187,13 @@ static int search_local (LexState *ls, TString *n, expdesc *var) { | |||
| 195 | int i; | 187 | int i; |
| 196 | for (i=fs->nactloc-1; i >= 0; i--) { | 188 | for (i=fs->nactloc-1; i >= 0; i--) { |
| 197 | if (n == fs->f->locvars[fs->actloc[i]].varname) { | 189 | if (n == fs->f->locvars[fs->actloc[i]].varname) { |
| 198 | var->k = VLOCAL; | 190 | init_exp(var, VLOCAL, i); |
| 199 | var->u.index = i; | ||
| 200 | return level; | 191 | return level; |
| 201 | } | 192 | } |
| 202 | } | 193 | } |
| 203 | level++; /* `var' not found; check outer level */ | 194 | level++; /* `var' not found; check outer level */ |
| 204 | } | 195 | } |
| 205 | var->k = VGLOBAL; /* not found in any level; must be global */ | 196 | init_exp(var, VGLOBAL, 0); /* not found in any level; must be global */ |
| 206 | return -1; | 197 | return -1; |
| 207 | } | 198 | } |
| 208 | 199 | ||
| @@ -213,7 +204,7 @@ static void singlevar (LexState *ls, TString *n, expdesc *var) { | |||
| 213 | luaX_syntaxerror(ls, l_s("cannot access a variable in outer function"), | 204 | luaX_syntaxerror(ls, l_s("cannot access a variable in outer function"), |
| 214 | getstr(n)); | 205 | getstr(n)); |
| 215 | else if (level == -1) /* global? */ | 206 | else if (level == -1) /* global? */ |
| 216 | var->u.index = string_constant(ls->fs, n); | 207 | var->u.i.info = luaK_stringk(ls->fs, n); |
| 217 | } | 208 | } |
| 218 | 209 | ||
| 219 | 210 | ||
| @@ -221,7 +212,7 @@ static int indexupvalue (LexState *ls, expdesc *v) { | |||
| 221 | FuncState *fs = ls->fs; | 212 | FuncState *fs = ls->fs; |
| 222 | int i; | 213 | int i; |
| 223 | for (i=0; i<fs->f->nupvalues; i++) { | 214 | for (i=0; i<fs->f->nupvalues; i++) { |
| 224 | if (fs->upvalues[i].k == v->k && fs->upvalues[i].u.index == v->u.index) | 215 | if (fs->upvalues[i].k == v->k && fs->upvalues[i].u.i.info == v->u.i.info) |
| 225 | return i; | 216 | return i; |
| 226 | } | 217 | } |
| 227 | /* new one */ | 218 | /* new one */ |
| @@ -231,37 +222,43 @@ static int indexupvalue (LexState *ls, expdesc *v) { | |||
| 231 | } | 222 | } |
| 232 | 223 | ||
| 233 | 224 | ||
| 234 | static void pushupvalue (LexState *ls, TString *n) { | 225 | static void codeupvalue (LexState *ls, expdesc *v, TString *n) { |
| 235 | FuncState *fs = ls->fs; | 226 | FuncState *fs = ls->fs; |
| 236 | expdesc v; | 227 | int level; |
| 237 | int level = search_local(ls, n, &v); | 228 | level = search_local(ls, n, v); |
| 238 | if (level == -1) { /* global? */ | 229 | if (level == -1) { /* global? */ |
| 239 | if (fs->prev == NULL) | 230 | if (fs->prev == NULL) |
| 240 | luaX_syntaxerror(ls, l_s("cannot access an upvalue at top level"), getstr(n)); | 231 | luaX_syntaxerror(ls, l_s("cannot access an upvalue at top level"), |
| 241 | v.u.index = string_constant(fs->prev, n); | 232 | getstr(n)); |
| 233 | v->u.i.info = luaK_stringk(fs->prev, n); | ||
| 242 | } | 234 | } |
| 243 | else if (level != 1) { | 235 | else if (level != 1) { |
| 244 | luaX_syntaxerror(ls, | 236 | luaX_syntaxerror(ls, |
| 245 | l_s("upvalue must be global or local to immediately outer function"), getstr(n)); | 237 | l_s("upvalue must be global or local to immediately outer function"), |
| 238 | getstr(n)); | ||
| 246 | } | 239 | } |
| 247 | luaK_code1(fs, OP_PUSHUPVALUE, indexupvalue(ls, &v)); | 240 | init_exp(v, VRELOCABLE, |
| 241 | luaK_codeABc(fs, OP_LOADUPVAL, 0, indexupvalue(ls, v))); | ||
| 248 | } | 242 | } |
| 249 | 243 | ||
| 250 | 244 | ||
| 251 | static void adjust_mult_assign (LexState *ls, int nvars, int nexps) { | 245 | static void adjust_assign (LexState *ls, int nvars, int nexps, expdesc *e) { |
| 252 | FuncState *fs = ls->fs; | 246 | FuncState *fs = ls->fs; |
| 253 | int diff = nexps - nvars; | 247 | int extra = nvars - nexps; |
| 254 | if (nexps > 0 && luaK_lastisopen(fs)) { /* list ends in a function call */ | 248 | if (e->k == VCALL) { |
| 255 | diff--; /* do not count function call itself */ | 249 | extra++; /* includes call itself */ |
| 256 | if (diff <= 0) { /* more variables than values? */ | 250 | if (extra <= 0) extra = 0; |
| 257 | luaK_setcallreturns(fs, -diff); /* function call provide extra values */ | 251 | else luaK_reserveregs(fs, extra-1); |
| 258 | diff = 0; /* no more difference */ | 252 | luaK_setcallreturns(fs, e, extra); /* call provides the difference */ |
| 253 | } | ||
| 254 | else { | ||
| 255 | if (e->k != VVOID) luaK_exp2nextreg(fs, e); /* close last expression */ | ||
| 256 | if (extra > 0) { | ||
| 257 | int reg = fs->freereg; | ||
| 258 | luaK_reserveregs(fs, extra); | ||
| 259 | luaK_nil(fs, reg, extra); | ||
| 259 | } | 260 | } |
| 260 | else /* more values than variables */ | ||
| 261 | luaK_setcallreturns(fs, 0); /* call should provide no value */ | ||
| 262 | } | 261 | } |
| 263 | /* push or pop eventual difference between list lengths */ | ||
| 264 | luaK_adjuststack(fs, diff); | ||
| 265 | } | 262 | } |
| 266 | 263 | ||
| 267 | 264 | ||
| @@ -275,12 +272,11 @@ static void code_params (LexState *ls, int nparams, short dots) { | |||
| 275 | new_localvarstr(ls, l_s("arg"), 0); | 272 | new_localvarstr(ls, l_s("arg"), 0); |
| 276 | adjustlocalvars(ls, 1); | 273 | adjustlocalvars(ls, 1); |
| 277 | } | 274 | } |
| 278 | luaK_deltastack(fs, fs->nactloc); /* count parameters in the stack */ | 275 | luaK_reserveregs(fs, fs->nactloc); /* reserve register for parameters */ |
| 279 | } | 276 | } |
| 280 | 277 | ||
| 281 | 278 | ||
| 282 | static void enterbreak (FuncState *fs, Breaklabel *bl) { | 279 | static void enterbreak (FuncState *fs, Breaklabel *bl) { |
| 283 | bl->stacklevel = fs->stacklevel; | ||
| 284 | bl->breaklist = NO_JUMP; | 280 | bl->breaklist = NO_JUMP; |
| 285 | bl->previous = fs->bl; | 281 | bl->previous = fs->bl; |
| 286 | fs->bl = bl; | 282 | fs->bl = bl; |
| @@ -289,21 +285,24 @@ static void enterbreak (FuncState *fs, Breaklabel *bl) { | |||
| 289 | 285 | ||
| 290 | static void leavebreak (FuncState *fs, Breaklabel *bl) { | 286 | static void leavebreak (FuncState *fs, Breaklabel *bl) { |
| 291 | fs->bl = bl->previous; | 287 | fs->bl = bl->previous; |
| 292 | lua_assert(bl->stacklevel == fs->stacklevel); | ||
| 293 | luaK_patchlist(fs, bl->breaklist, luaK_getlabel(fs)); | 288 | luaK_patchlist(fs, bl->breaklist, luaK_getlabel(fs)); |
| 294 | } | 289 | } |
| 295 | 290 | ||
| 296 | 291 | ||
| 297 | static void pushclosure (LexState *ls, FuncState *func) { | 292 | static void pushclosure (LexState *ls, FuncState *func, expdesc *v) { |
| 298 | FuncState *fs = ls->fs; | 293 | FuncState *fs = ls->fs; |
| 299 | Proto *f = fs->f; | 294 | Proto *f = fs->f; |
| 300 | int i; | 295 | int i; |
| 296 | int reg = fs->freereg; | ||
| 301 | for (i=0; i<func->f->nupvalues; i++) | 297 | for (i=0; i<func->f->nupvalues; i++) |
| 302 | luaK_tostack(ls, &func->upvalues[i], 1); | 298 | luaK_exp2nextreg(fs, &func->upvalues[i]); |
| 303 | luaM_growvector(ls->L, f->kproto, fs->nkproto, f->sizekproto, Proto *, | 299 | luaM_growvector(ls->L, f->kproto, fs->nkproto, f->sizekproto, Proto *, |
| 304 | MAXARG_A, l_s("constant table overflow")); | 300 | MAXARG_Bc, l_s("constant table overflow")); |
| 305 | f->kproto[fs->nkproto++] = func->f; | 301 | f->kproto[fs->nkproto++] = func->f; |
| 306 | luaK_code2(fs, OP_CLOSURE, fs->nkproto-1, func->f->nupvalues); | 302 | fs->freereg = reg; /* CLOSURE will consume those values */ |
| 303 | init_exp(v, VNONRELOC, reg); | ||
| 304 | luaK_reserveregs(fs, 1); | ||
| 305 | luaK_codeABc(fs, OP_CLOSURE, v->u.i.info, fs->nkproto-1); | ||
| 307 | } | 306 | } |
| 308 | 307 | ||
| 309 | 308 | ||
| @@ -317,10 +316,9 @@ static void open_func (LexState *ls, FuncState *fs) { | |||
| 317 | fs->pc = 0; | 316 | fs->pc = 0; |
| 318 | fs->lasttarget = 0; | 317 | fs->lasttarget = 0; |
| 319 | fs->jlt = NO_JUMP; | 318 | fs->jlt = NO_JUMP; |
| 320 | fs->stacklevel = 0; | 319 | fs->freereg = 0; |
| 321 | fs->nkstr = 0; | 320 | fs->nk = 0; |
| 322 | fs->nkproto = 0; | 321 | fs->nkproto = 0; |
| 323 | fs->nknum = 0; | ||
| 324 | fs->nlineinfo = 0; | 322 | fs->nlineinfo = 0; |
| 325 | fs->nlocvars = 0; | 323 | fs->nlocvars = 0; |
| 326 | fs->nactloc = 0; | 324 | fs->nactloc = 0; |
| @@ -328,7 +326,7 @@ static void open_func (LexState *ls, FuncState *fs) { | |||
| 328 | fs->bl = NULL; | 326 | fs->bl = NULL; |
| 329 | f->code = NULL; | 327 | f->code = NULL; |
| 330 | f->source = ls->source; | 328 | f->source = ls->source; |
| 331 | f->maxstacksize = 0; | 329 | f->maxstacksize = 1; /* register 0 is always valid */ |
| 332 | f->numparams = 0; /* default for main chunk */ | 330 | f->numparams = 0; /* default for main chunk */ |
| 333 | f->is_vararg = 0; /* default for main chunk */ | 331 | f->is_vararg = 0; /* default for main chunk */ |
| 334 | } | 332 | } |
| @@ -338,15 +336,13 @@ static void close_func (LexState *ls) { | |||
| 338 | lua_State *L = ls->L; | 336 | lua_State *L = ls->L; |
| 339 | FuncState *fs = ls->fs; | 337 | FuncState *fs = ls->fs; |
| 340 | Proto *f = fs->f; | 338 | Proto *f = fs->f; |
| 341 | luaK_code1(fs, OP_RETURN, ls->fs->nactloc); /* final return */ | 339 | luaK_codeABC(fs, OP_RETURN, 0, 0, 0); /* final return */ |
| 342 | luaK_getlabel(fs); /* close eventual list of pending jumps */ | 340 | luaK_getlabel(fs); /* close eventual list of pending jumps */ |
| 343 | removelocalvars(ls, fs->nactloc); | 341 | removelocalvars(ls, fs->nactloc); |
| 344 | luaM_reallocvector(L, f->code, f->sizecode, fs->pc, Instruction); | 342 | luaM_reallocvector(L, f->code, f->sizecode, fs->pc, Instruction); |
| 345 | f->sizecode = fs->pc; | 343 | f->sizecode = fs->pc; |
| 346 | luaM_reallocvector(L, f->kstr, f->sizekstr, fs->nkstr, TString *); | 344 | luaM_reallocvector(L, f->k, f->sizek, fs->nk, TObject); |
| 347 | f->sizekstr = fs->nkstr; | 345 | f->sizek = fs->nk; |
| 348 | luaM_reallocvector(L, f->knum, f->sizeknum, fs->nknum, lua_Number); | ||
| 349 | f->sizeknum = fs->nknum; | ||
| 350 | luaM_reallocvector(L, f->kproto, f->sizekproto, fs->nkproto, Proto *); | 346 | luaM_reallocvector(L, f->kproto, f->sizekproto, fs->nkproto, Proto *); |
| 351 | f->sizekproto = fs->nkproto; | 347 | f->sizekproto = fs->nkproto; |
| 352 | luaM_reallocvector(L, f->locvars, f->sizelocvars, fs->nlocvars, LocVar); | 348 | luaM_reallocvector(L, f->locvars, f->sizelocvars, fs->nlocvars, LocVar); |
| @@ -354,9 +350,9 @@ static void close_func (LexState *ls) { | |||
| 354 | luaM_reallocvector(L, f->lineinfo, f->sizelineinfo, fs->nlineinfo+1, int); | 350 | luaM_reallocvector(L, f->lineinfo, f->sizelineinfo, fs->nlineinfo+1, int); |
| 355 | f->lineinfo[fs->nlineinfo++] = MAX_INT; /* end flag */ | 351 | f->lineinfo[fs->nlineinfo++] = MAX_INT; /* end flag */ |
| 356 | f->sizelineinfo = fs->nlineinfo; | 352 | f->sizelineinfo = fs->nlineinfo; |
| 357 | lua_assert(luaG_checkcode(L, f)); | 353 | lua_assert(luaG_checkcode(f)); |
| 358 | ls->fs = fs->prev; | ||
| 359 | lua_assert(fs->bl == NULL); | 354 | lua_assert(fs->bl == NULL); |
| 355 | ls->fs = fs->prev; | ||
| 360 | } | 356 | } |
| 361 | 357 | ||
| 362 | 358 | ||
| @@ -367,7 +363,8 @@ Proto *luaY_parser (lua_State *L, ZIO *z) { | |||
| 367 | open_func(&lexstate, &funcstate); | 363 | open_func(&lexstate, &funcstate); |
| 368 | next(&lexstate); /* read first token */ | 364 | next(&lexstate); /* read first token */ |
| 369 | chunk(&lexstate); | 365 | chunk(&lexstate); |
| 370 | check_condition(&lexstate, (lexstate.t.token == TK_EOS), l_s("<eof> expected")); | 366 | check_condition(&lexstate, (lexstate.t.token == TK_EOS), |
| 367 | l_s("<eof> expected")); | ||
| 371 | close_func(&lexstate); | 368 | close_func(&lexstate); |
| 372 | lua_assert(funcstate.prev == NULL); | 369 | lua_assert(funcstate.prev == NULL); |
| 373 | lua_assert(funcstate.f->nupvalues == 0); | 370 | lua_assert(funcstate.f->nupvalues == 0); |
| @@ -381,48 +378,64 @@ Proto *luaY_parser (lua_State *L, ZIO *z) { | |||
| 381 | /*============================================================*/ | 378 | /*============================================================*/ |
| 382 | 379 | ||
| 383 | 380 | ||
| 384 | static int explist1 (LexState *ls) { | 381 | static void luaY_field (LexState *ls, expdesc *v) { |
| 382 | /* field -> ['.' | ':'] NAME */ | ||
| 383 | FuncState *fs = ls->fs; | ||
| 384 | expdesc key; | ||
| 385 | luaK_exp2anyreg(fs, v); | ||
| 386 | next(ls); /* skip the dot or colon */ | ||
| 387 | checkname(ls, &key); | ||
| 388 | luaK_indexed(fs, v, &key); | ||
| 389 | } | ||
| 390 | |||
| 391 | |||
| 392 | static void luaY_index (LexState *ls, expdesc *v) { | ||
| 393 | /* index -> '[' expr ']' */ | ||
| 394 | next(ls); /* skip the '[' */ | ||
| 395 | expr(ls, v); | ||
| 396 | luaK_exp2val(ls->fs, v); | ||
| 397 | check(ls, l_c(']')); | ||
| 398 | } | ||
| 399 | |||
| 400 | |||
| 401 | static int explist1 (LexState *ls, expdesc *v) { | ||
| 385 | /* explist1 -> expr { `,' expr } */ | 402 | /* explist1 -> expr { `,' expr } */ |
| 386 | int n = 1; /* at least one expression */ | 403 | int n = 1; /* at least one expression */ |
| 387 | expdesc v; | 404 | expr(ls, v); |
| 388 | expr(ls, &v); | ||
| 389 | while (ls->t.token == l_c(',')) { | 405 | while (ls->t.token == l_c(',')) { |
| 390 | next(ls); /* skip comma */ | 406 | next(ls); /* skip comma */ |
| 391 | luaK_tostack(ls, &v, 1); /* gets only 1 value from previous expression */ | 407 | luaK_exp2nextreg(ls->fs, v); |
| 392 | expr(ls, &v); | 408 | expr(ls, v); |
| 393 | n++; | 409 | n++; |
| 394 | } | 410 | } |
| 395 | luaK_tostack(ls, &v, 0); /* keep open number of values of last expression */ | ||
| 396 | return n; | 411 | return n; |
| 397 | } | 412 | } |
| 398 | 413 | ||
| 399 | 414 | ||
| 400 | static void funcargs (LexState *ls, int slf) { | 415 | static void funcargs (LexState *ls, expdesc *f) { |
| 401 | FuncState *fs = ls->fs; | 416 | FuncState *fs = ls->fs; |
| 402 | int slevel = fs->stacklevel - slf - 1; /* where is func in the stack */ | 417 | expdesc args; |
| 418 | int base, top; | ||
| 403 | switch (ls->t.token) { | 419 | switch (ls->t.token) { |
| 404 | case l_c('('): { /* funcargs -> `(' [ explist1 ] `)' */ | 420 | case l_c('('): { /* funcargs -> `(' [ explist1 ] `)' */ |
| 405 | int line = ls->linenumber; | 421 | int line = ls->linenumber; |
| 406 | int nargs = 0; | ||
| 407 | next(ls); | 422 | next(ls); |
| 408 | if (ls->t.token != l_c(')')) /* arg list not empty? */ | 423 | if (ls->t.token == l_c(')')) /* arg list is empty? */ |
| 409 | nargs = explist1(ls); | 424 | args.k = VVOID; |
| 425 | else { | ||
| 426 | explist1(ls, &args); | ||
| 427 | luaK_setcallreturns(fs, &args, NO_REG); | ||
| 428 | } | ||
| 410 | check_match(ls, l_c(')'), l_c('('), line); | 429 | check_match(ls, l_c(')'), l_c('('), line); |
| 411 | #ifdef LUA_COMPAT_ARGRET | ||
| 412 | if (nargs > 0) /* arg list is not empty? */ | ||
| 413 | luaK_setcallreturns(fs, 1); /* last call returns only 1 value */ | ||
| 414 | #else | ||
| 415 | UNUSED(nargs); /* to avoid warnings */ | ||
| 416 | #endif | ||
| 417 | break; | 430 | break; |
| 418 | } | 431 | } |
| 419 | case l_c('{'): { /* funcargs -> constructor */ | 432 | case l_c('{'): { /* funcargs -> constructor */ |
| 420 | constructor(ls); | 433 | constructor(ls, &args); |
| 421 | break; | 434 | break; |
| 422 | } | 435 | } |
| 423 | case TK_STRING: { /* funcargs -> STRING */ | 436 | case TK_STRING: { /* funcargs -> STRING */ |
| 424 | code_string(ls, ls->t.seminfo.ts); /* must use `seminfo' before `next' */ | 437 | codestring(ls, &args, ls->t.seminfo.ts); |
| 425 | next(ls); | 438 | next(ls); /* must use `seminfo' before `next' */ |
| 426 | break; | 439 | break; |
| 427 | } | 440 | } |
| 428 | default: { | 441 | default: { |
| @@ -430,11 +443,22 @@ static void funcargs (LexState *ls, int slf) { | |||
| 430 | break; | 443 | break; |
| 431 | } | 444 | } |
| 432 | } | 445 | } |
| 433 | fs->stacklevel = slevel; /* call will remove function and arguments */ | 446 | lua_assert(f->k == VNONRELOC); |
| 434 | luaK_code2(fs, OP_CALL, slevel, MULT_RET); | 447 | base = f->u.i.info; /* base register for call */ |
| 448 | if (args.k == VCALL) | ||
| 449 | top = NO_REG; /* open call */ | ||
| 450 | else { | ||
| 451 | if (args.k != VVOID) | ||
| 452 | luaK_exp2nextreg(fs, &args); /* close last argument */ | ||
| 453 | top = fs->freereg; | ||
| 454 | } | ||
| 455 | init_exp(f, VCALL, luaK_codeABC(fs, OP_CALL, base, top, 1)); | ||
| 456 | fs->freereg = base+1; /* call remove function and arguments and leaves | ||
| 457 | (unless changed) one result */ | ||
| 435 | } | 458 | } |
| 436 | 459 | ||
| 437 | 460 | ||
| 461 | |||
| 438 | /* | 462 | /* |
| 439 | ** {====================================================================== | 463 | ** {====================================================================== |
| 440 | ** Rules for Constructors | 464 | ** Rules for Constructors |
| @@ -442,69 +466,82 @@ static void funcargs (LexState *ls, int slf) { | |||
| 442 | */ | 466 | */ |
| 443 | 467 | ||
| 444 | 468 | ||
| 445 | static void recfield (LexState *ls) { | 469 | static void recfield (LexState *ls, expdesc *t) { |
| 446 | /* recfield -> (NAME | `['exp1`]') = exp1 */ | 470 | /* recfield -> (NAME | `['exp1`]') = exp1 */ |
| 471 | FuncState *fs = ls->fs; | ||
| 472 | int reg = ls->fs->freereg; | ||
| 473 | expdesc key, val; | ||
| 447 | switch (ls->t.token) { | 474 | switch (ls->t.token) { |
| 448 | case TK_NAME: { | 475 | case TK_NAME: { |
| 449 | luaK_kstr(ls, checkname(ls)); | 476 | checkname(ls, &key); |
| 450 | break; | 477 | break; |
| 451 | } | 478 | } |
| 452 | case l_c('['): { | 479 | case l_c('['): { |
| 453 | next(ls); | 480 | luaY_index(ls, &key); |
| 454 | exp1(ls); | ||
| 455 | check(ls, l_c(']')); | ||
| 456 | break; | 481 | break; |
| 457 | } | 482 | } |
| 458 | default: luaK_error(ls, l_s("<name> or `[' expected")); | 483 | default: luaK_error(ls, l_s("<name> or `[' expected")); |
| 459 | } | 484 | } |
| 460 | check(ls, l_c('=')); | 485 | check(ls, l_c('=')); |
| 461 | exp1(ls); | 486 | luaK_exp2RK(fs, &key); |
| 487 | expr(ls, &val); | ||
| 488 | luaK_exp2anyreg(fs, &val); | ||
| 489 | luaK_codeABC(fs, OP_SETTABLE, val.u.i.info, t->u.i.info, | ||
| 490 | luaK_exp2RK(fs, &key)); | ||
| 491 | fs->freereg = reg; /* free registers */ | ||
| 462 | } | 492 | } |
| 463 | 493 | ||
| 464 | 494 | ||
| 465 | static int recfields (LexState *ls) { | 495 | static int recfields (LexState *ls, expdesc *t) { |
| 466 | /* recfields -> recfield { `,' recfield } [`,'] */ | 496 | /* recfields -> recfield { `,' recfield } [`,'] */ |
| 467 | FuncState *fs = ls->fs; | ||
| 468 | int t = fs->stacklevel-1; /* level of table on the stack */ | ||
| 469 | int n = 1; /* at least one element */ | 497 | int n = 1; /* at least one element */ |
| 470 | recfield(ls); | 498 | luaK_exp2nextreg(ls->fs, t); |
| 471 | while (ls->t.token == l_c(',') && | 499 | recfield(ls, t); |
| 472 | (next(ls), (ls->t.token != l_c(';') && ls->t.token != l_c('}')))) { | 500 | while (ls->t.token == l_c(',')) { |
| 473 | if (n%RFIELDS_PER_FLUSH == 0) | 501 | next(ls); |
| 474 | luaK_code1(fs, OP_SETMAP, t); | 502 | if (ls->t.token == l_c(';') || ls->t.token == l_c('}')) break; |
| 475 | recfield(ls); | 503 | recfield(ls, t); |
| 476 | n++; | 504 | n++; |
| 477 | } | 505 | } |
| 478 | luaK_code1(fs, OP_SETMAP, t); | ||
| 479 | return n; | 506 | return n; |
| 480 | } | 507 | } |
| 481 | 508 | ||
| 482 | 509 | ||
| 483 | static int listfields (LexState *ls) { | 510 | static int listfields (LexState *ls, expdesc *t) { |
| 484 | /* listfields -> exp1 { `,' exp1 } [`,'] */ | 511 | /* listfields -> exp1 { `,' exp1 } [`,'] */ |
| 485 | expdesc v; | 512 | expdesc v; |
| 486 | FuncState *fs = ls->fs; | 513 | FuncState *fs = ls->fs; |
| 487 | int t = fs->stacklevel-1; /* level of table on the stack */ | ||
| 488 | int n = 1; /* at least one element */ | 514 | int n = 1; /* at least one element */ |
| 515 | int reg; | ||
| 516 | luaK_exp2nextreg(ls->fs, t); | ||
| 517 | reg = fs->freereg; | ||
| 489 | expr(ls, &v); | 518 | expr(ls, &v); |
| 490 | while (ls->t.token == l_c(',') && | 519 | while (ls->t.token == l_c(',') && |
| 491 | (next(ls), (ls->t.token != l_c(';') && ls->t.token != l_c('}')))) { | 520 | (next(ls), (ls->t.token != l_c(';') && ls->t.token != l_c('}')))) { |
| 492 | luaK_tostack(ls, &v, 1); /* only one value from intermediate expressions */ | 521 | luaK_exp2nextreg(fs, &v); |
| 493 | luaX_checklimit(ls, n/LFIELDS_PER_FLUSH, MAXARG_A, | 522 | luaX_checklimit(ls, n, MAXARG_Bc, |
| 494 | l_s("`item groups' in a list initializer")); | 523 | l_s("`item groups' in a list initializer")); |
| 495 | if (n%LFIELDS_PER_FLUSH == 0) | 524 | if (n%LFIELDS_PER_FLUSH == 0) { |
| 496 | luaK_code2(fs, OP_SETLIST, (n-1)/LFIELDS_PER_FLUSH, t); | 525 | luaK_codeABc(fs, OP_SETLIST, t->u.i.info, n-1); |
| 526 | fs->freereg = reg; /* free registers */ | ||
| 527 | } | ||
| 497 | expr(ls, &v); | 528 | expr(ls, &v); |
| 498 | n++; | 529 | n++; |
| 499 | } | 530 | } |
| 500 | luaK_tostack(ls, &v, 0); /* allow multiple values for last expression */ | 531 | if (v.k == VCALL) { |
| 501 | luaK_code2(fs, OP_SETLIST, (n-1)/LFIELDS_PER_FLUSH, t); | 532 | luaK_setcallreturns(fs, &v, NO_REG); |
| 533 | luaK_codeABc(fs, OP_SETLISTO, t->u.i.info, n-1); | ||
| 534 | } | ||
| 535 | else { | ||
| 536 | luaK_exp2nextreg(fs, &v); | ||
| 537 | luaK_codeABc(fs, OP_SETLIST, t->u.i.info, n-1); | ||
| 538 | } | ||
| 539 | fs->freereg = reg; /* free registers */ | ||
| 502 | return n; | 540 | return n; |
| 503 | } | 541 | } |
| 504 | 542 | ||
| 505 | 543 | ||
| 506 | 544 | static void constructor_part (LexState *ls, expdesc *t, Constdesc *cd) { | |
| 507 | static void constructor_part (LexState *ls, Constdesc *cd) { | ||
| 508 | switch (ls->t.token) { | 545 | switch (ls->t.token) { |
| 509 | case l_c(';'): case l_c('}'): { /* constructor_part -> empty */ | 546 | case l_c(';'): case l_c('}'): { /* constructor_part -> empty */ |
| 510 | cd->n = 0; | 547 | cd->n = 0; |
| @@ -518,13 +555,13 @@ static void constructor_part (LexState *ls, Constdesc *cd) { | |||
| 518 | /* else go through to recfields */ | 555 | /* else go through to recfields */ |
| 519 | } | 556 | } |
| 520 | case l_c('['): { /* constructor_part -> recfields */ | 557 | case l_c('['): { /* constructor_part -> recfields */ |
| 521 | cd->n = recfields(ls); | 558 | cd->n = recfields(ls, t); |
| 522 | cd->k = 1; /* record */ | 559 | cd->k = 1; /* record */ |
| 523 | break; | 560 | break; |
| 524 | } | 561 | } |
| 525 | default: { /* constructor_part -> listfields */ | 562 | default: { /* constructor_part -> listfields */ |
| 526 | case_default: | 563 | case_default: |
| 527 | cd->n = listfields(ls); | 564 | cd->n = listfields(ls, t); |
| 528 | cd->k = 0; /* list */ | 565 | cd->k = 0; /* list */ |
| 529 | break; | 566 | break; |
| 530 | } | 567 | } |
| @@ -532,25 +569,27 @@ static void constructor_part (LexState *ls, Constdesc *cd) { | |||
| 532 | } | 569 | } |
| 533 | 570 | ||
| 534 | 571 | ||
| 535 | static void constructor (LexState *ls) { | 572 | static void constructor (LexState *ls, expdesc *t) { |
| 536 | /* constructor -> `{' constructor_part [`;' constructor_part] `}' */ | 573 | /* constructor -> `{' constructor_part [`;' constructor_part] `}' */ |
| 537 | FuncState *fs = ls->fs; | 574 | FuncState *fs = ls->fs; |
| 538 | int line = ls->linenumber; | 575 | int line = ls->linenumber; |
| 539 | int pc = luaK_code1(fs, OP_CREATETABLE, 0); | 576 | int n; |
| 540 | int nelems; | 577 | int pc; |
| 541 | Constdesc cd; | 578 | Constdesc cd; |
| 579 | pc = luaK_codeABc(fs, OP_NEWTABLE, 0, 0); | ||
| 580 | init_exp(t, VRELOCABLE, pc); | ||
| 542 | check(ls, l_c('{')); | 581 | check(ls, l_c('{')); |
| 543 | constructor_part(ls, &cd); | 582 | constructor_part(ls, t, &cd); |
| 544 | nelems = cd.n; | 583 | n = cd.n; |
| 545 | if (optional(ls, l_c(';'))) { | 584 | if (optional(ls, l_c(';'))) { |
| 546 | Constdesc other_cd; | 585 | Constdesc other_cd; |
| 547 | constructor_part(ls, &other_cd); | 586 | constructor_part(ls, t, &other_cd); |
| 548 | check_condition(ls, (cd.k != other_cd.k), l_s("invalid constructor syntax")); | 587 | check_condition(ls, (cd.k != other_cd.k), l_s("invalid constructor syntax")); |
| 549 | nelems += other_cd.n; | 588 | n += other_cd.n; |
| 550 | } | 589 | } |
| 551 | check_match(ls, l_c('}'), l_c('{'), line); | 590 | check_match(ls, l_c('}'), l_c('{'), line); |
| 552 | luaX_checklimit(ls, nelems, MAXARG_U, l_s("elements in a table constructor")); | 591 | luaX_checklimit(ls, n, MAXARG_Bc, l_s("elements in a table constructor")); |
| 553 | SETARG_U(fs->f->code[pc], nelems); /* set initial table size */ | 592 | SETARG_Bc(fs->f->code[pc], n); /* set initial table size */ |
| 554 | } | 593 | } |
| 555 | 594 | ||
| 556 | /* }====================================================================== */ | 595 | /* }====================================================================== */ |
| @@ -565,31 +604,30 @@ static void constructor (LexState *ls) { | |||
| 565 | */ | 604 | */ |
| 566 | 605 | ||
| 567 | static void primaryexp (LexState *ls, expdesc *v) { | 606 | static void primaryexp (LexState *ls, expdesc *v) { |
| 568 | FuncState *fs = ls->fs; | ||
| 569 | switch (ls->t.token) { | 607 | switch (ls->t.token) { |
| 570 | case TK_NUMBER: { | 608 | case TK_NUMBER: { |
| 571 | lua_Number r = ls->t.seminfo.r; | 609 | init_exp(v, VNUMBER, 0); |
| 572 | next(ls); | 610 | v->u.n = ls->t.seminfo.r; |
| 573 | luaK_number(fs, r); | 611 | next(ls); /* must use `seminfo' before `next' */ |
| 574 | break; | 612 | break; |
| 575 | } | 613 | } |
| 576 | case TK_STRING: { | 614 | case TK_STRING: { |
| 577 | code_string(ls, ls->t.seminfo.ts); /* must use `seminfo' before `next' */ | 615 | codestring(ls, v, ls->t.seminfo.ts); |
| 578 | next(ls); | 616 | next(ls); /* must use `seminfo' before `next' */ |
| 579 | break; | 617 | break; |
| 580 | } | 618 | } |
| 581 | case TK_NIL: { | 619 | case TK_NIL: { |
| 582 | luaK_adjuststack(fs, -1); | 620 | init_exp(v, VNIL, 0); |
| 583 | next(ls); | 621 | next(ls); |
| 584 | break; | 622 | break; |
| 585 | } | 623 | } |
| 586 | case l_c('{'): { /* constructor */ | 624 | case l_c('{'): { /* constructor */ |
| 587 | constructor(ls); | 625 | constructor(ls, v); |
| 588 | break; | 626 | break; |
| 589 | } | 627 | } |
| 590 | case TK_FUNCTION: { | 628 | case TK_FUNCTION: { |
| 591 | next(ls); | 629 | next(ls); |
| 592 | body(ls, 0, ls->linenumber); | 630 | body(ls, v, 0, ls->linenumber); |
| 593 | break; | 631 | break; |
| 594 | } | 632 | } |
| 595 | case l_c('('): { | 633 | case l_c('('): { |
| @@ -604,7 +642,7 @@ static void primaryexp (LexState *ls, expdesc *v) { | |||
| 604 | } | 642 | } |
| 605 | case l_c('%'): { | 643 | case l_c('%'): { |
| 606 | next(ls); /* skip `%' */ | 644 | next(ls); /* skip `%' */ |
| 607 | pushupvalue(ls, str_checkname(ls)); | 645 | codeupvalue(ls, v, str_checkname(ls)); |
| 608 | break; | 646 | break; |
| 609 | } | 647 | } |
| 610 | default: { | 648 | default: { |
| @@ -612,46 +650,38 @@ static void primaryexp (LexState *ls, expdesc *v) { | |||
| 612 | return; | 650 | return; |
| 613 | } | 651 | } |
| 614 | } | 652 | } |
| 615 | v->k = VEXP; | ||
| 616 | v->u.l.t = v->u.l.f = NO_JUMP; | ||
| 617 | } | 653 | } |
| 618 | 654 | ||
| 619 | 655 | ||
| 620 | static void simpleexp (LexState *ls, expdesc *v) { | 656 | static void simpleexp (LexState *ls, expdesc *v) { |
| 621 | /* simpleexp -> | 657 | /* simpleexp -> |
| 622 | primaryexp { `.' NAME | `[' exp `]' | `:' NAME funcargs | funcargs } */ | 658 | primaryexp { `.' NAME | `[' exp `]' | `:' NAME funcargs | funcargs } */ |
| 659 | FuncState *fs = ls->fs; | ||
| 623 | primaryexp(ls, v); | 660 | primaryexp(ls, v); |
| 624 | for (;;) { | 661 | for (;;) { |
| 625 | switch (ls->t.token) { | 662 | switch (ls->t.token) { |
| 626 | case l_c('.'): { /* `.' NAME */ | 663 | case l_c('.'): { /* field */ |
| 627 | next(ls); | 664 | luaY_field(ls, v); |
| 628 | luaK_tostack(ls, v, 1); /* `v' must be on stack */ | ||
| 629 | luaK_kstr(ls, checkname(ls)); | ||
| 630 | v->k = VINDEXED; | ||
| 631 | break; | 665 | break; |
| 632 | } | 666 | } |
| 633 | case l_c('['): { /* `[' exp1 `]' */ | 667 | case l_c('['): { /* `[' exp1 `]' */ |
| 634 | next(ls); | 668 | expdesc key; |
| 635 | luaK_tostack(ls, v, 1); /* `v' must be on stack */ | 669 | luaK_exp2anyreg(fs, v); |
| 636 | v->k = VINDEXED; | 670 | luaY_index(ls, &key); |
| 637 | exp1(ls); | 671 | luaK_indexed(fs, v, &key); |
| 638 | check(ls, l_c(']')); | ||
| 639 | break; | 672 | break; |
| 640 | } | 673 | } |
| 641 | case l_c(':'): { /* `:' NAME funcargs */ | 674 | case l_c(':'): { /* `:' NAME funcargs */ |
| 675 | expdesc key; | ||
| 642 | next(ls); | 676 | next(ls); |
| 643 | luaK_tostack(ls, v, 1); /* `v' must be on stack */ | 677 | checkname(ls, &key); |
| 644 | luaK_code1(ls->fs, OP_PUSHSELF, checkname(ls)); | 678 | luaK_self(fs, v, &key); |
| 645 | funcargs(ls, 1); | 679 | funcargs(ls, v); |
| 646 | v->k = VEXP; | ||
| 647 | v->u.l.t = v->u.l.f = NO_JUMP; | ||
| 648 | break; | 680 | break; |
| 649 | } | 681 | } |
| 650 | case l_c('('): case TK_STRING: case l_c('{'): { /* funcargs */ | 682 | case l_c('('): case TK_STRING: case l_c('{'): { /* funcargs */ |
| 651 | luaK_tostack(ls, v, 1); /* `v' must be on stack */ | 683 | luaK_exp2nextreg(fs, v); |
| 652 | funcargs(ls, 0); | 684 | funcargs(ls, v); |
| 653 | v->k = VEXP; | ||
| 654 | v->u.l.t = v->u.l.f = NO_JUMP; | ||
| 655 | break; | 685 | break; |
| 656 | } | 686 | } |
| 657 | default: return; /* should be follow... */ | 687 | default: return; /* should be follow... */ |
| @@ -714,7 +744,7 @@ static BinOpr subexpr (LexState *ls, expdesc *v, int limit) { | |||
| 714 | if (uop != OPR_NOUNOPR) { | 744 | if (uop != OPR_NOUNOPR) { |
| 715 | next(ls); | 745 | next(ls); |
| 716 | subexpr(ls, v, UNARY_PRIORITY); | 746 | subexpr(ls, v, UNARY_PRIORITY); |
| 717 | luaK_prefix(ls, uop, v); | 747 | luaK_prefix(ls->fs, uop, v); |
| 718 | } | 748 | } |
| 719 | else simpleexp(ls, v); | 749 | else simpleexp(ls, v); |
| 720 | /* expand while operators have priorities higher than `limit' */ | 750 | /* expand while operators have priorities higher than `limit' */ |
| @@ -723,10 +753,10 @@ static BinOpr subexpr (LexState *ls, expdesc *v, int limit) { | |||
| 723 | expdesc v2; | 753 | expdesc v2; |
| 724 | BinOpr nextop; | 754 | BinOpr nextop; |
| 725 | next(ls); | 755 | next(ls); |
| 726 | luaK_infix(ls, op, v); | 756 | luaK_infix(ls->fs, op, v); |
| 727 | /* read sub-expression with higher priority */ | 757 | /* read sub-expression with higher priority */ |
| 728 | nextop = subexpr(ls, &v2, (int)priority[op].right); | 758 | nextop = subexpr(ls, &v2, (int)priority[op].right); |
| 729 | luaK_posfix(ls, op, v, &v2); | 759 | luaK_posfix(ls->fs, op, v, &v2); |
| 730 | op = nextop; | 760 | op = nextop; |
| 731 | } | 761 | } |
| 732 | return op; /* return first untreated operator */ | 762 | return op; /* return first untreated operator */ |
| @@ -737,13 +767,6 @@ static void expr (LexState *ls, expdesc *v) { | |||
| 737 | subexpr(ls, v, -1); | 767 | subexpr(ls, v, -1); |
| 738 | } | 768 | } |
| 739 | 769 | ||
| 740 | |||
| 741 | static void exp1 (LexState *ls) { | ||
| 742 | expdesc v; | ||
| 743 | expr(ls, &v); | ||
| 744 | luaK_tostack(ls, &v, 1); | ||
| 745 | } | ||
| 746 | |||
| 747 | /* }==================================================================== */ | 770 | /* }==================================================================== */ |
| 748 | 771 | ||
| 749 | 772 | ||
| @@ -769,41 +792,87 @@ static void block (LexState *ls) { | |||
| 769 | FuncState *fs = ls->fs; | 792 | FuncState *fs = ls->fs; |
| 770 | int nactloc = fs->nactloc; | 793 | int nactloc = fs->nactloc; |
| 771 | chunk(ls); | 794 | chunk(ls); |
| 772 | luaK_adjuststack(fs, fs->nactloc - nactloc); /* remove local variables */ | ||
| 773 | removelocalvars(ls, fs->nactloc - nactloc); | 795 | removelocalvars(ls, fs->nactloc - nactloc); |
| 796 | fs->freereg = nactloc; /* free registers used by locals */ | ||
| 774 | } | 797 | } |
| 775 | 798 | ||
| 776 | 799 | ||
| 777 | static int assignment (LexState *ls, expdesc *v, int nvars) { | 800 | /* |
| 778 | int left = 0; /* number of values left in the stack after assignment */ | 801 | ** structure to chain all variables in the left-hand side of an |
| 779 | luaX_checklimit(ls, nvars, MAXVARSLH, l_s("variables in a multiple assignment")); | 802 | ** assignment |
| 803 | */ | ||
| 804 | struct LHS_assign { | ||
| 805 | struct LHS_assign *prev; | ||
| 806 | expdesc v; /* variable (global, local, or indexed) */ | ||
| 807 | }; | ||
| 808 | |||
| 809 | |||
| 810 | /* | ||
| 811 | ** check whether, in an assignment to a local variable, the local variable | ||
| 812 | ** is needed in a previous assignment (to a table). If so, save original | ||
| 813 | ** local value in a safe place and use this safe copy in the previous | ||
| 814 | ** assignment. | ||
| 815 | */ | ||
| 816 | static void check_conflict (LexState *ls, struct LHS_assign *lh, expdesc *v) { | ||
| 817 | FuncState *fs = ls->fs; | ||
| 818 | int extra = fs->freereg; /* eventual position to save local variable */ | ||
| 819 | int conflict = 0; | ||
| 820 | for (; lh; lh = lh->prev) { | ||
| 821 | if (lh->v.k == VINDEXED) { | ||
| 822 | if (lh->v.u.i.info == v->u.i.info) { /* conflict? */ | ||
| 823 | conflict = 1; | ||
| 824 | lh->v.u.i.info = extra; /* previous assignment will use safe copy */ | ||
| 825 | } | ||
| 826 | if (lh->v.u.i.aux == v->u.i.info) { /* conflict? */ | ||
| 827 | conflict = 1; | ||
| 828 | lh->v.u.i.aux = extra; /* previous assignment will use safe copy */ | ||
| 829 | } | ||
| 830 | } | ||
| 831 | } | ||
| 832 | if (conflict) { | ||
| 833 | luaK_codeABC(fs, OP_MOVE, fs->freereg, v->u.i.info, 0); /* make copy */ | ||
| 834 | luaK_reserveregs(fs, 1); | ||
| 835 | } | ||
| 836 | } | ||
| 837 | |||
| 838 | |||
| 839 | static void assignment (LexState *ls, struct LHS_assign *lh, int nvars) { | ||
| 840 | expdesc e; | ||
| 841 | check_condition(ls, lh->v.k == VLOCAL || lh->v.k == VGLOBAL || | ||
| 842 | lh->v.k == VINDEXED, | ||
| 843 | l_s("syntax error")); | ||
| 780 | if (ls->t.token == l_c(',')) { /* assignment -> `,' simpleexp assignment */ | 844 | if (ls->t.token == l_c(',')) { /* assignment -> `,' simpleexp assignment */ |
| 781 | expdesc nv; | 845 | struct LHS_assign nv; |
| 846 | nv.prev = lh; | ||
| 782 | next(ls); | 847 | next(ls); |
| 783 | simpleexp(ls, &nv); | 848 | simpleexp(ls, &nv.v); |
| 784 | check_condition(ls, (nv.k != VEXP), l_s("syntax error")); | 849 | if (nv.v.k == VLOCAL) |
| 785 | left = assignment(ls, &nv, nvars+1); | 850 | check_conflict(ls, lh, &nv.v); |
| 851 | assignment(ls, &nv, nvars+1); | ||
| 786 | } | 852 | } |
| 787 | else { /* assignment -> `=' explist1 */ | 853 | else { /* assignment -> `=' explist1 */ |
| 788 | int nexps; | 854 | int nexps; |
| 789 | check(ls, l_c('=')); | 855 | check(ls, l_c('=')); |
| 790 | nexps = explist1(ls); | 856 | nexps = explist1(ls, &e); |
| 791 | adjust_mult_assign(ls, nvars, nexps); | 857 | if (nexps != nvars) { |
| 792 | } | 858 | adjust_assign(ls, nvars, nexps, &e); |
| 793 | if (v->k != VINDEXED) | 859 | if (nexps > nvars) |
| 794 | luaK_storevar(ls, v); | 860 | ls->fs->freereg -= nexps - nvars; /* remove extra values */ |
| 795 | else { /* there may be garbage between table-index and value */ | 861 | } |
| 796 | luaK_code2(ls->fs, OP_SETTABLE, left+nvars+2, 1); | 862 | else { |
| 797 | left += 2; | 863 | luaK_storevar(ls->fs, &lh->v, &e); |
| 864 | return; /* avoid default */ | ||
| 865 | } | ||
| 798 | } | 866 | } |
| 799 | return left; | 867 | init_exp(&e, VNONRELOC, ls->fs->freereg-1); /* default assignment */ |
| 868 | luaK_storevar(ls->fs, &lh->v, &e); | ||
| 800 | } | 869 | } |
| 801 | 870 | ||
| 802 | 871 | ||
| 803 | static void cond (LexState *ls, expdesc *v) { | 872 | static void cond (LexState *ls, expdesc *v) { |
| 804 | /* cond -> exp */ | 873 | /* cond -> exp */ |
| 805 | expr(ls, v); /* read condition */ | 874 | expr(ls, v); /* read condition */ |
| 806 | luaK_goiftrue(ls->fs, v, 0); | 875 | luaK_goiftrue(ls->fs, v); |
| 807 | } | 876 | } |
| 808 | 877 | ||
| 809 | 878 | ||
| @@ -819,7 +888,7 @@ static void whilestat (LexState *ls, int line) { | |||
| 819 | check(ls, TK_DO); | 888 | check(ls, TK_DO); |
| 820 | block(ls); | 889 | block(ls); |
| 821 | luaK_patchlist(fs, luaK_jump(fs), while_init); | 890 | luaK_patchlist(fs, luaK_jump(fs), while_init); |
| 822 | luaK_patchlist(fs, v.u.l.f, luaK_getlabel(fs)); | 891 | luaK_patchlist(fs, v.f, luaK_getlabel(fs)); |
| 823 | check_match(ls, TK_END, TK_WHILE, line); | 892 | check_match(ls, TK_END, TK_WHILE, line); |
| 824 | leavebreak(fs, &bl); | 893 | leavebreak(fs, &bl); |
| 825 | } | 894 | } |
| @@ -836,20 +905,28 @@ static void repeatstat (LexState *ls, int line) { | |||
| 836 | block(ls); | 905 | block(ls); |
| 837 | check_match(ls, TK_UNTIL, TK_REPEAT, line); | 906 | check_match(ls, TK_UNTIL, TK_REPEAT, line); |
| 838 | cond(ls, &v); | 907 | cond(ls, &v); |
| 839 | luaK_patchlist(fs, v.u.l.f, repeat_init); | 908 | luaK_patchlist(fs, v.f, repeat_init); |
| 840 | leavebreak(fs, &bl); | 909 | leavebreak(fs, &bl); |
| 841 | } | 910 | } |
| 842 | 911 | ||
| 843 | 912 | ||
| 913 | static void exp1 (LexState *ls) { | ||
| 914 | expdesc e; | ||
| 915 | expr(ls, &e); | ||
| 916 | luaK_exp2nextreg(ls->fs, &e); | ||
| 917 | } | ||
| 918 | |||
| 919 | |||
| 844 | static void forbody (LexState *ls, int nvar, OpCode prepfor, OpCode loopfor) { | 920 | static void forbody (LexState *ls, int nvar, OpCode prepfor, OpCode loopfor) { |
| 845 | /* forbody -> DO block END */ | 921 | /* forbody -> DO block END */ |
| 846 | FuncState *fs = ls->fs; | 922 | FuncState *fs = ls->fs; |
| 847 | int prep = luaK_code1(fs, prepfor, NO_JUMP); | 923 | int basereg = fs->freereg - nvar; |
| 924 | int prep = luaK_codeAsBc(fs, prepfor, basereg, NO_JUMP); | ||
| 848 | int blockinit = luaK_getlabel(fs); | 925 | int blockinit = luaK_getlabel(fs); |
| 849 | check(ls, TK_DO); | 926 | check(ls, TK_DO); |
| 850 | adjustlocalvars(ls, nvar); /* scope for control variables */ | 927 | adjustlocalvars(ls, nvar); /* scope for control variables */ |
| 851 | block(ls); | 928 | block(ls); |
| 852 | luaK_patchlist(fs, luaK_code1(fs, loopfor, NO_JUMP), blockinit); | 929 | luaK_patchlist(fs, luaK_codeAsBc(fs, loopfor, basereg, NO_JUMP), blockinit); |
| 853 | luaK_fixfor(fs, prep, luaK_getlabel(fs)); | 930 | luaK_fixfor(fs, prep, luaK_getlabel(fs)); |
| 854 | removelocalvars(ls, nvar); | 931 | removelocalvars(ls, nvar); |
| 855 | } | 932 | } |
| @@ -864,8 +941,10 @@ static void fornum (LexState *ls, TString *varname) { | |||
| 864 | exp1(ls); /* limit */ | 941 | exp1(ls); /* limit */ |
| 865 | if (optional(ls, l_c(','))) | 942 | if (optional(ls, l_c(','))) |
| 866 | exp1(ls); /* optional step */ | 943 | exp1(ls); /* optional step */ |
| 867 | else | 944 | else { |
| 868 | luaK_code1(fs, OP_PUSHINT, 1); /* default step */ | 945 | luaK_codeAsBc(fs, OP_LOADINT, fs->freereg, 1); /* default step */ |
| 946 | luaK_reserveregs(fs, 1); | ||
| 947 | } | ||
| 869 | new_localvar(ls, varname, 0); | 948 | new_localvar(ls, varname, 0); |
| 870 | new_localvarstr(ls, l_s("(limit)"), 1); | 949 | new_localvarstr(ls, l_s("(limit)"), 1); |
| 871 | new_localvarstr(ls, l_s("(step)"), 2); | 950 | new_localvarstr(ls, l_s("(step)"), 2); |
| @@ -889,7 +968,8 @@ static void forlist (LexState *ls, TString *indexname) { | |||
| 889 | new_localvarstr(ls, l_s("(index)"), 1); | 968 | new_localvarstr(ls, l_s("(index)"), 1); |
| 890 | new_localvar(ls, indexname, 2); | 969 | new_localvar(ls, indexname, 2); |
| 891 | new_localvar(ls, valname, 3); | 970 | new_localvar(ls, valname, 3); |
| 892 | forbody(ls, 4, OP_LFORPREP, OP_LFORLOOP); | 971 | luaK_reserveregs(ls->fs, 3); /* registers for control, index and val */ |
| 972 | forbody(ls, 4, OP_TFORPREP, OP_TFORLOOP); | ||
| 893 | } | 973 | } |
| 894 | 974 | ||
| 895 | 975 | ||
| @@ -928,17 +1008,17 @@ static void ifstat (LexState *ls, int line) { | |||
| 928 | test_then_block(ls, &v); /* IF cond THEN block */ | 1008 | test_then_block(ls, &v); /* IF cond THEN block */ |
| 929 | while (ls->t.token == TK_ELSEIF) { | 1009 | while (ls->t.token == TK_ELSEIF) { |
| 930 | luaK_concat(fs, &escapelist, luaK_jump(fs)); | 1010 | luaK_concat(fs, &escapelist, luaK_jump(fs)); |
| 931 | luaK_patchlist(fs, v.u.l.f, luaK_getlabel(fs)); | 1011 | luaK_patchlist(fs, v.f, luaK_getlabel(fs)); |
| 932 | test_then_block(ls, &v); /* ELSEIF cond THEN block */ | 1012 | test_then_block(ls, &v); /* ELSEIF cond THEN block */ |
| 933 | } | 1013 | } |
| 934 | if (ls->t.token == TK_ELSE) { | 1014 | if (ls->t.token == TK_ELSE) { |
| 935 | luaK_concat(fs, &escapelist, luaK_jump(fs)); | 1015 | luaK_concat(fs, &escapelist, luaK_jump(fs)); |
| 936 | luaK_patchlist(fs, v.u.l.f, luaK_getlabel(fs)); | 1016 | luaK_patchlist(fs, v.f, luaK_getlabel(fs)); |
| 937 | next(ls); /* skip ELSE */ | 1017 | next(ls); /* skip ELSE */ |
| 938 | block(ls); /* `else' part */ | 1018 | block(ls); /* `else' part */ |
| 939 | } | 1019 | } |
| 940 | else | 1020 | else |
| 941 | luaK_concat(fs, &escapelist, v.u.l.f); | 1021 | luaK_concat(fs, &escapelist, v.f); |
| 942 | luaK_patchlist(fs, escapelist, luaK_getlabel(fs)); | 1022 | luaK_patchlist(fs, escapelist, luaK_getlabel(fs)); |
| 943 | check_match(ls, TK_END, TK_IF, line); | 1023 | check_match(ls, TK_END, TK_IF, line); |
| 944 | } | 1024 | } |
| @@ -948,35 +1028,32 @@ static void localstat (LexState *ls) { | |||
| 948 | /* stat -> LOCAL NAME {`,' NAME} [`=' explist1] */ | 1028 | /* stat -> LOCAL NAME {`,' NAME} [`=' explist1] */ |
| 949 | int nvars = 0; | 1029 | int nvars = 0; |
| 950 | int nexps; | 1030 | int nexps; |
| 1031 | expdesc e; | ||
| 951 | do { | 1032 | do { |
| 952 | next(ls); /* skip LOCAL or `,' */ | 1033 | next(ls); /* skip LOCAL or `,' */ |
| 953 | new_localvar(ls, str_checkname(ls), nvars++); | 1034 | new_localvar(ls, str_checkname(ls), nvars++); |
| 954 | } while (ls->t.token == l_c(',')); | 1035 | } while (ls->t.token == l_c(',')); |
| 955 | if (optional(ls, l_c('='))) | 1036 | if (optional(ls, l_c('='))) |
| 956 | nexps = explist1(ls); | 1037 | nexps = explist1(ls, &e); |
| 957 | else | 1038 | else { |
| 1039 | e.k = VVOID; | ||
| 958 | nexps = 0; | 1040 | nexps = 0; |
| 959 | adjust_mult_assign(ls, nvars, nexps); | 1041 | } |
| 1042 | adjust_assign(ls, nvars, nexps, &e); | ||
| 960 | adjustlocalvars(ls, nvars); | 1043 | adjustlocalvars(ls, nvars); |
| 961 | } | 1044 | } |
| 962 | 1045 | ||
| 963 | 1046 | ||
| 964 | static int funcname (LexState *ls, expdesc *v) { | 1047 | static int funcname (LexState *ls, expdesc *v) { |
| 965 | /* funcname -> NAME {`.' NAME} [`:' NAME] */ | 1048 | /* funcname -> NAME {field} [`:' NAME] */ |
| 966 | int needself = 0; | 1049 | int needself = 0; |
| 967 | singlevar(ls, str_checkname(ls), v); | 1050 | singlevar(ls, str_checkname(ls), v); |
| 968 | while (ls->t.token == l_c('.')) { | 1051 | while (ls->t.token == l_c('.')) { |
| 969 | next(ls); | 1052 | luaY_field(ls, v); |
| 970 | luaK_tostack(ls, v, 1); | ||
| 971 | luaK_kstr(ls, checkname(ls)); | ||
| 972 | v->k = VINDEXED; | ||
| 973 | } | 1053 | } |
| 974 | if (ls->t.token == l_c(':')) { | 1054 | if (ls->t.token == l_c(':')) { |
| 975 | needself = 1; | 1055 | needself = 1; |
| 976 | next(ls); | 1056 | luaY_field(ls, v); |
| 977 | luaK_tostack(ls, v, 1); | ||
| 978 | luaK_kstr(ls, checkname(ls)); | ||
| 979 | v->k = VINDEXED; | ||
| 980 | } | 1057 | } |
| 981 | return needself; | 1058 | return needself; |
| 982 | } | 1059 | } |
| @@ -985,26 +1062,25 @@ static int funcname (LexState *ls, expdesc *v) { | |||
| 985 | static void funcstat (LexState *ls, int line) { | 1062 | static void funcstat (LexState *ls, int line) { |
| 986 | /* funcstat -> FUNCTION funcname body */ | 1063 | /* funcstat -> FUNCTION funcname body */ |
| 987 | int needself; | 1064 | int needself; |
| 988 | expdesc v; | 1065 | expdesc v, b; |
| 989 | next(ls); /* skip FUNCTION */ | 1066 | next(ls); /* skip FUNCTION */ |
| 990 | needself = funcname(ls, &v); | 1067 | needself = funcname(ls, &v); |
| 991 | body(ls, needself, line); | 1068 | body(ls, &b, needself, line); |
| 992 | luaK_storevar(ls, &v); | 1069 | luaK_storevar(ls->fs, &v, &b); |
| 993 | } | 1070 | } |
| 994 | 1071 | ||
| 995 | 1072 | ||
| 996 | static void exprstat (LexState *ls) { | 1073 | static void exprstat (LexState *ls) { |
| 997 | /* stat -> func | assignment */ | 1074 | /* stat -> func | assignment */ |
| 998 | FuncState *fs = ls->fs; | 1075 | FuncState *fs = ls->fs; |
| 999 | expdesc v; | 1076 | struct LHS_assign v; |
| 1000 | simpleexp(ls, &v); | 1077 | simpleexp(ls, &v.v); |
| 1001 | if (v.k == VEXP) { /* stat -> func */ | 1078 | if (v.v.k == VCALL) { /* stat -> func */ |
| 1002 | check_condition(ls, luaK_lastisopen(fs), l_s("syntax error")); /* an upvalue? */ | 1079 | luaK_setcallreturns(fs, &v.v, 0); /* call statement uses no results */ |
| 1003 | luaK_setcallreturns(fs, 0); /* call statement uses no results */ | ||
| 1004 | } | 1080 | } |
| 1005 | else { /* stat -> assignment */ | 1081 | else { /* stat -> assignment */ |
| 1006 | int left = assignment(ls, &v, 1); | 1082 | v.prev = NULL; |
| 1007 | luaK_adjuststack(fs, left); /* remove eventual garbage left on stack */ | 1083 | assignment(ls, &v, 1); |
| 1008 | } | 1084 | } |
| 1009 | } | 1085 | } |
| 1010 | 1086 | ||
| @@ -1012,26 +1088,45 @@ static void exprstat (LexState *ls) { | |||
| 1012 | static void retstat (LexState *ls) { | 1088 | static void retstat (LexState *ls) { |
| 1013 | /* stat -> RETURN explist */ | 1089 | /* stat -> RETURN explist */ |
| 1014 | FuncState *fs = ls->fs; | 1090 | FuncState *fs = ls->fs; |
| 1091 | expdesc e; | ||
| 1092 | int first, last1; /* registers with returned values */ | ||
| 1015 | next(ls); /* skip RETURN */ | 1093 | next(ls); /* skip RETURN */ |
| 1016 | if (!block_follow(ls->t.token) && ls->t.token != l_c(';')) | 1094 | if (block_follow(ls->t.token) || ls->t.token == l_c(';')) |
| 1017 | explist1(ls); /* optional return values */ | 1095 | first = last1 = 0; /* return no values */ |
| 1018 | luaK_code1(fs, OP_RETURN, ls->fs->nactloc); | 1096 | else { |
| 1019 | fs->stacklevel = fs->nactloc; /* removes all temp values */ | 1097 | int n = explist1(ls, &e); /* optional return values */ |
| 1098 | if (e.k == VCALL) { | ||
| 1099 | luaK_setcallreturns(fs, &e, NO_REG); | ||
| 1100 | first = fs->nactloc; | ||
| 1101 | last1 = NO_REG; /* return all values */ | ||
| 1102 | } | ||
| 1103 | else { | ||
| 1104 | if (n == 1) { /* only one value? */ | ||
| 1105 | luaK_exp2anyreg(fs, &e); | ||
| 1106 | first = e.u.i.info; | ||
| 1107 | last1 = first+1; /* return only this value */ | ||
| 1108 | } | ||
| 1109 | else { | ||
| 1110 | luaK_exp2nextreg(fs, &e); /* values must go to the `stack' */ | ||
| 1111 | first = fs->nactloc; | ||
| 1112 | last1 = fs->freereg; /* return all `active' values */ | ||
| 1113 | } | ||
| 1114 | } | ||
| 1115 | } | ||
| 1116 | luaK_codeABC(fs, OP_RETURN, first, last1, 0); | ||
| 1117 | fs->freereg = fs->nactloc; /* removes all temp values */ | ||
| 1020 | } | 1118 | } |
| 1021 | 1119 | ||
| 1022 | 1120 | ||
| 1023 | static void breakstat (LexState *ls) { | 1121 | static void breakstat (LexState *ls) { |
| 1024 | /* stat -> BREAK [NAME] */ | 1122 | /* stat -> BREAK [NAME] */ |
| 1025 | FuncState *fs = ls->fs; | 1123 | FuncState *fs = ls->fs; |
| 1026 | int currentlevel = fs->stacklevel; | ||
| 1027 | Breaklabel *bl = fs->bl; | 1124 | Breaklabel *bl = fs->bl; |
| 1028 | if (!bl) | 1125 | if (!bl) |
| 1029 | luaK_error(ls, l_s("no loop to break")); | 1126 | luaK_error(ls, l_s("no loop to break")); |
| 1030 | next(ls); /* skip BREAK */ | 1127 | next(ls); /* skip BREAK */ |
| 1031 | luaK_adjuststack(fs, currentlevel - bl->stacklevel); | ||
| 1032 | luaK_concat(fs, &bl->breaklist, luaK_jump(fs)); | 1128 | luaK_concat(fs, &bl->breaklist, luaK_jump(fs)); |
| 1033 | /* correct stack for compiler and symbolic execution */ | 1129 | /* correct stack for compiler and symbolic execution */ |
| 1034 | luaK_adjuststack(fs, bl->stacklevel - currentlevel); | ||
| 1035 | } | 1130 | } |
| 1036 | 1131 | ||
| 1037 | 1132 | ||
| @@ -1105,7 +1200,7 @@ static void parlist (LexState *ls) { | |||
| 1105 | } | 1200 | } |
| 1106 | 1201 | ||
| 1107 | 1202 | ||
| 1108 | static void body (LexState *ls, int needself, int line) { | 1203 | static void body (LexState *ls, expdesc *e, int needself, int line) { |
| 1109 | /* body -> `(' parlist `)' chunk END */ | 1204 | /* body -> `(' parlist `)' chunk END */ |
| 1110 | FuncState new_fs; | 1205 | FuncState new_fs; |
| 1111 | open_func(ls, &new_fs); | 1206 | open_func(ls, &new_fs); |
| @@ -1120,7 +1215,7 @@ static void body (LexState *ls, int needself, int line) { | |||
| 1120 | chunk(ls); | 1215 | chunk(ls); |
| 1121 | check_match(ls, TK_END, TK_FUNCTION, line); | 1216 | check_match(ls, TK_END, TK_FUNCTION, line); |
| 1122 | close_func(ls); | 1217 | close_func(ls); |
| 1123 | pushclosure(ls, &new_fs); | 1218 | pushclosure(ls, &new_fs, e); |
| 1124 | } | 1219 | } |
| 1125 | 1220 | ||
| 1126 | 1221 | ||
| @@ -1133,7 +1228,10 @@ static void chunk (LexState *ls) { | |||
| 1133 | while (!islast && !block_follow(ls->t.token)) { | 1228 | while (!islast && !block_follow(ls->t.token)) { |
| 1134 | islast = statement(ls); | 1229 | islast = statement(ls); |
| 1135 | optional(ls, l_c(';')); | 1230 | optional(ls, l_c(';')); |
| 1136 | lua_assert(ls->fs->stacklevel == ls->fs->nactloc); | 1231 | if (ls->fs->freereg < ls->fs->nactloc) |
| 1232 | printf(">>>>>>> %d %d\n", ls->fs->freereg, ls->fs->nactloc); | ||
| 1233 | lua_assert(ls->fs->freereg >= ls->fs->nactloc); | ||
| 1234 | ls->fs->freereg = ls->fs->nactloc; /* free registers */ | ||
| 1137 | } | 1235 | } |
| 1138 | } | 1236 | } |
| 1139 | 1237 | ||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lparser.h,v 1.29 2000/12/28 12:55:41 roberto Exp roberto $ | 2 | ** $Id: lparser.h,v 1.30 2001/02/20 18:28:11 roberto Exp roberto $ |
| 3 | ** LL(1) Parser and code generator for Lua | 3 | ** LL(1) Parser and code generator for Lua |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -16,25 +16,32 @@ | |||
| 16 | */ | 16 | */ |
| 17 | 17 | ||
| 18 | typedef enum { | 18 | typedef enum { |
| 19 | VGLOBAL, | 19 | VVOID, /* no value */ |
| 20 | VLOCAL, | 20 | VNIL, |
| 21 | VINDEXED, | 21 | VNUMBER, /* n = value */ |
| 22 | VEXP | 22 | VK, /* info = index of constant in `k' */ |
| 23 | VGLOBAL, /* info = index of global name in `k' */ | ||
| 24 | VLOCAL, /* info = local register */ | ||
| 25 | VINDEXED, /* info = table register; aux = index register (or `k') */ | ||
| 26 | VRELOCABLE, /* info = instruction pc */ | ||
| 27 | VNONRELOC, /* info = result register */ | ||
| 28 | VJMP, /* info = result register */ | ||
| 29 | VCALL /* info = result register */ | ||
| 23 | } expkind; | 30 | } expkind; |
| 24 | 31 | ||
| 25 | typedef struct expdesc { | 32 | typedef struct expdesc { |
| 26 | expkind k; | 33 | expkind k; |
| 27 | union { | 34 | union { |
| 28 | int index; /* VGLOBAL: `kstr' index of global name; VLOCAL: stack index */ | ||
| 29 | struct { | 35 | struct { |
| 30 | int t; /* patch list of `exit when true' */ | 36 | int info, aux; |
| 31 | int f; /* patch list of `exit when false' */ | 37 | } i; |
| 32 | } l; | 38 | lua_Number n; |
| 33 | } u; | 39 | } u; |
| 40 | int t; /* patch list of `exit when true' */ | ||
| 41 | int f; /* patch list of `exit when false' */ | ||
| 34 | } expdesc; | 42 | } expdesc; |
| 35 | 43 | ||
| 36 | 44 | ||
| 37 | |||
| 38 | /* state needed to generate code for a given function */ | 45 | /* state needed to generate code for a given function */ |
| 39 | typedef struct FuncState { | 46 | typedef struct FuncState { |
| 40 | Proto *f; /* current function header */ | 47 | Proto *f; /* current function header */ |
| @@ -44,10 +51,9 @@ typedef struct FuncState { | |||
| 44 | int pc; /* next position to code (equivalent to `ncode') */ | 51 | int pc; /* next position to code (equivalent to `ncode') */ |
| 45 | int lasttarget; /* `pc' of last `jump target' */ | 52 | int lasttarget; /* `pc' of last `jump target' */ |
| 46 | int jlt; /* list of jumps to `lasttarget' */ | 53 | int jlt; /* list of jumps to `lasttarget' */ |
| 47 | int stacklevel; /* number of values on activation register */ | 54 | int freereg; /* first free register */ |
| 48 | int nkstr; /* number of elements in `kstr' */ | 55 | int nk; /* number of elements in `k' */ |
| 49 | int nkproto; /* number of elements in `kproto' */ | 56 | int nkproto; /* number of elements in `kproto' */ |
| 50 | int nknum; /* number of elements in `knum' */ | ||
| 51 | int nlineinfo; /* number of elements in `lineinfo' */ | 57 | int nlineinfo; /* number of elements in `lineinfo' */ |
| 52 | int nlocvars; /* number of elements in `locvars' */ | 58 | int nlocvars; /* number of elements in `locvars' */ |
| 53 | int nactloc; /* number of active local variables */ | 59 | int nactloc; /* number of active local variables */ |
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: ltests.c,v 1.79 2001/04/17 17:35:54 roberto Exp roberto $ | 2 | ** $Id: ltests.c,v 1.80 2001/04/23 16:35:45 roberto Exp roberto $ |
| 3 | ** Internal Module for Debugging of the Lua Implementation | 3 | ** Internal Module for Debugging of the Lua Implementation |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -140,77 +140,65 @@ void *debug_realloc (void *block, size_t oldsize, size_t size) { | |||
| 140 | 140 | ||
| 141 | 141 | ||
| 142 | static const l_char *const instrname[NUM_OPCODES] = { | 142 | static const l_char *const instrname[NUM_OPCODES] = { |
| 143 | l_s("RETURN"), | 143 | l_s("OP_MOVE"), |
| 144 | l_s("CALL"), | 144 | l_s("OP_LOADK"), |
| 145 | l_s("PUSHNIL"), | 145 | l_s("OP_LOADINT"), |
| 146 | l_s("POP"), | 146 | l_s("OP_LOADNIL"), |
| 147 | l_s("PUSHINT"), | 147 | l_s("OP_LOADUPVAL"), |
| 148 | l_s("PUSHSTRING"), | 148 | l_s("OP_GETGLOBAL"), |
| 149 | l_s("PUSHNUM"), | 149 | l_s("OP_GETTABLE"), |
| 150 | l_s("PUSHNEGNUM"), | 150 | l_s("OP_SETGLOBAL"), |
| 151 | l_s("PUSHUPVALUE"), | 151 | l_s("OP_SETTABLE"), |
| 152 | l_s("GETLOCAL"), | 152 | l_s("OP_NEWTABLE"), |
| 153 | l_s("GETGLOBAL"), | 153 | l_s("OP_SELF"), |
| 154 | l_s("GETTABLE"), | 154 | l_s("OP_ADD"), |
| 155 | l_s("GETDOTTED"), | 155 | l_s("OP_SUB"), |
| 156 | l_s("GETINDEXED"), | 156 | l_s("OP_MUL"), |
| 157 | l_s("PUSHSELF"), | 157 | l_s("OP_DIV"), |
| 158 | l_s("CREATETABLE"), | 158 | l_s("OP_POW"), |
| 159 | l_s("SETLOCAL"), | 159 | l_s("OP_UNM"), |
| 160 | l_s("SETGLOBAL"), | 160 | l_s("OP_NOT"), |
| 161 | l_s("SETTABLE"), | 161 | l_s("OP_CONCAT"), |
| 162 | l_s("SETLIST"), | 162 | l_s("OP_JMP"), |
| 163 | l_s("SETMAP"), | 163 | l_s("OP_CJMP"), |
| 164 | l_s("ADD"), | 164 | l_s("OP_TESTEQ"), |
| 165 | l_s("ADDI"), | 165 | l_s("OP_TESTNE"), |
| 166 | l_s("SUB"), | 166 | l_s("OP_TESTLT"), |
| 167 | l_s("MULT"), | 167 | l_s("OP_TESTLE"), |
| 168 | l_s("DIV"), | 168 | l_s("OP_TESTGT"), |
| 169 | l_s("POW"), | 169 | l_s("OP_TESTGE"), |
| 170 | l_s("CONCAT"), | 170 | l_s("OP_TESTT"), |
| 171 | l_s("MINUS"), | 171 | l_s("OP_TESTF"), |
| 172 | l_s("NOT"), | 172 | l_s("OP_NILJMP"), |
| 173 | l_s("JMPNE"), | 173 | l_s("OP_CALL"), |
| 174 | l_s("JMPEQ"), | 174 | l_s("OP_RETURN"), |
| 175 | l_s("JMPLT"), | 175 | l_s("OP_FORPREP"), |
| 176 | l_s("JMPLE"), | 176 | l_s("OP_FORLOOP"), |
| 177 | l_s("JMPGT"), | 177 | l_s("OP_LFORPREP"), |
| 178 | l_s("JMPGE"), | 178 | l_s("OP_LFORLOOP"), |
| 179 | l_s("JMPT"), | 179 | l_s("OP_SETLIST"), |
| 180 | l_s("JMPF"), | 180 | l_s("OP_CLOSURE") |
| 181 | l_s("JMPONT"), | ||
| 182 | l_s("JMPONF"), | ||
| 183 | l_s("JMP"), | ||
| 184 | l_s("PUSHNILJMP"), | ||
| 185 | l_s("FORPREP"), | ||
| 186 | l_s("FORLOOP"), | ||
| 187 | l_s("LFORPREP"), | ||
| 188 | l_s("LFORLOOP"), | ||
| 189 | l_s("CLOSURE") | ||
| 190 | }; | 181 | }; |
| 191 | 182 | ||
| 192 | 183 | ||
| 193 | static void pushop (lua_State *L, Proto *p, int pc) { | 184 | static l_char *buildop (Proto *p, int pc, l_char *buff) { |
| 194 | l_char buff[100]; | ||
| 195 | Instruction i = p->code[pc]; | 185 | Instruction i = p->code[pc]; |
| 196 | OpCode o = GET_OPCODE(i); | 186 | OpCode o = GET_OPCODE(i); |
| 197 | const l_char *name = instrname[o]; | 187 | const l_char *name = instrname[o]; |
| 198 | sprintf(buff, l_s("%5d - "), luaG_getline(p->lineinfo, pc, 1, NULL)); | 188 | sprintf(buff, l_s("%4d - "), pc); |
| 199 | switch ((enum Mode)luaK_opproperties[o].mode) { | 189 | switch (getOpMode(o)) { |
| 200 | case iO: | 190 | case iABC: |
| 201 | sprintf(buff+8, l_s("%-12s"), name); | 191 | sprintf(buff+strlen(buff), l_s("%-12s%4d %4d %4d"), name, |
| 192 | GETARG_A(i), GETARG_B(i), GETARG_C(i)); | ||
| 202 | break; | 193 | break; |
| 203 | case iU: | 194 | case iABc: |
| 204 | sprintf(buff+8, l_s("%-12s%4u"), name, GETARG_U(i)); | 195 | sprintf(buff+strlen(buff), l_s("%-12s%4d %4d"), name, GETARG_A(i), GETARG_Bc(i)); |
| 205 | break; | 196 | break; |
| 206 | case iS: | 197 | case iAsBc: |
| 207 | sprintf(buff+8, l_s("%-12s%4d"), name, GETARG_S(i)); | 198 | sprintf(buff+strlen(buff), l_s("%-12s%4d %4d"), name, GETARG_A(i), GETARG_sBc(i)); |
| 208 | break; | ||
| 209 | case iAB: | ||
| 210 | sprintf(buff+8, l_s("%-12s%4d %4d"), name, GETARG_A(i), GETARG_B(i)); | ||
| 211 | break; | 199 | break; |
| 212 | } | 200 | } |
| 213 | lua_pushstring(L, buff); | 201 | return buff; |
| 214 | } | 202 | } |
| 215 | 203 | ||
| 216 | 204 | ||
| @@ -224,24 +212,25 @@ static int listcode (lua_State *L) { | |||
| 224 | setnameval(L, l_s("maxstack"), p->maxstacksize); | 212 | setnameval(L, l_s("maxstack"), p->maxstacksize); |
| 225 | setnameval(L, l_s("numparams"), p->numparams); | 213 | setnameval(L, l_s("numparams"), p->numparams); |
| 226 | for (pc=0; pc<p->sizecode; pc++) { | 214 | for (pc=0; pc<p->sizecode; pc++) { |
| 215 | l_char buff[100]; | ||
| 227 | lua_pushnumber(L, pc+1); | 216 | lua_pushnumber(L, pc+1); |
| 228 | pushop(L, p, pc); | 217 | lua_pushstring(L, buildop(p, pc, buff)); |
| 229 | lua_settable(L, -3); | 218 | lua_settable(L, -3); |
| 230 | } | 219 | } |
| 231 | return 1; | 220 | return 1; |
| 232 | } | 221 | } |
| 233 | 222 | ||
| 234 | 223 | ||
| 235 | static int liststrings (lua_State *L) { | 224 | static int listk (lua_State *L) { |
| 236 | Proto *p; | 225 | Proto *p; |
| 237 | int i; | 226 | int i; |
| 238 | luaL_arg_check(L, lua_isfunction(L, 1) && !lua_iscfunction(L, 1), | 227 | luaL_arg_check(L, lua_isfunction(L, 1) && !lua_iscfunction(L, 1), |
| 239 | 1, l_s("Lua function expected")); | 228 | 1, l_s("Lua function expected")); |
| 240 | p = clvalue(luaA_index(L, 1))->f.l; | 229 | p = clvalue(luaA_index(L, 1))->f.l; |
| 241 | lua_newtable(L); | 230 | lua_newtable(L); |
| 242 | for (i=0; i<p->sizekstr; i++) { | 231 | for (i=0; i<p->sizek; i++) { |
| 243 | lua_pushnumber(L, i+1); | 232 | lua_pushnumber(L, i+1); |
| 244 | lua_pushstring(L, getstr(p->kstr[i])); | 233 | luaA_pushobject(L, p->k+i); |
| 245 | lua_settable(L, -3); | 234 | lua_settable(L, -3); |
| 246 | } | 235 | } |
| 247 | return 1; | 236 | return 1; |
| @@ -276,20 +265,10 @@ static int get_limits (lua_State *L) { | |||
| 276 | lua_newtable(L); | 265 | lua_newtable(L); |
| 277 | setnameval(L, l_s("BITS_INT"), BITS_INT); | 266 | setnameval(L, l_s("BITS_INT"), BITS_INT); |
| 278 | setnameval(L, l_s("LFPF"), LFIELDS_PER_FLUSH); | 267 | setnameval(L, l_s("LFPF"), LFIELDS_PER_FLUSH); |
| 279 | setnameval(L, l_s("MAXARG_A"), MAXARG_A); | ||
| 280 | setnameval(L, l_s("MAXARG_B"), MAXARG_B); | ||
| 281 | setnameval(L, l_s("MAXARG_S"), MAXARG_S); | ||
| 282 | setnameval(L, l_s("MAXARG_U"), MAXARG_U); | ||
| 283 | setnameval(L, l_s("MAXLOCALS"), MAXLOCALS); | 268 | setnameval(L, l_s("MAXLOCALS"), MAXLOCALS); |
| 284 | setnameval(L, l_s("MAXPARAMS"), MAXPARAMS); | 269 | setnameval(L, l_s("MAXPARAMS"), MAXPARAMS); |
| 285 | setnameval(L, l_s("MAXSTACK"), MAXSTACK); | 270 | setnameval(L, l_s("MAXSTACK"), MAXSTACK); |
| 286 | setnameval(L, l_s("MAXUPVALUES"), MAXUPVALUES); | 271 | setnameval(L, l_s("MAXUPVALUES"), MAXUPVALUES); |
| 287 | setnameval(L, l_s("MAXVARSLH"), MAXVARSLH); | ||
| 288 | setnameval(L, l_s("RFPF"), RFIELDS_PER_FLUSH); | ||
| 289 | setnameval(L, l_s("SIZE_A"), SIZE_A); | ||
| 290 | setnameval(L, l_s("SIZE_B"), SIZE_B); | ||
| 291 | setnameval(L, l_s("SIZE_OP"), SIZE_OP); | ||
| 292 | setnameval(L, l_s("SIZE_U"), SIZE_U); | ||
| 293 | return 1; | 272 | return 1; |
| 294 | } | 273 | } |
| 295 | 274 | ||
| @@ -700,7 +679,7 @@ static const struct luaL_reg tests_funcs[] = { | |||
| 700 | {l_s("hash"), hash_query}, | 679 | {l_s("hash"), hash_query}, |
| 701 | {l_s("limits"), get_limits}, | 680 | {l_s("limits"), get_limits}, |
| 702 | {l_s("listcode"), listcode}, | 681 | {l_s("listcode"), listcode}, |
| 703 | {l_s("liststrings"), liststrings}, | 682 | {l_s("listk"), listk}, |
| 704 | {l_s("listlocals"), listlocals}, | 683 | {l_s("listlocals"), listlocals}, |
| 705 | {l_s("loadlib"), loadlib}, | 684 | {l_s("loadlib"), loadlib}, |
| 706 | {l_s("querystr"), string_query}, | 685 | {l_s("querystr"), string_query}, |
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lvm.c,v 1.177 2001/03/26 14:31:49 roberto Exp roberto $ | 2 | ** $Id: lvm.c,v 1.178 2001/04/06 18:25:00 roberto Exp roberto $ |
| 3 | ** Lua virtual machine | 3 | ** Lua virtual machine |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -28,15 +28,14 @@ | |||
| 28 | 28 | ||
| 29 | 29 | ||
| 30 | 30 | ||
| 31 | int luaV_tonumber (TObject *obj) { | 31 | const TObject *luaV_tonumber (const TObject *obj, TObject *n) { |
| 32 | if (ttype(obj) != LUA_TSTRING) | 32 | if (ttype(obj) == LUA_TNUMBER) return obj; |
| 33 | return 1; | 33 | if (ttype(obj) == LUA_TSTRING && luaO_str2d(svalue(obj), &nvalue(n))) { |
| 34 | else { | 34 | ttype(n) = LUA_TNUMBER; |
| 35 | if (!luaO_str2d(svalue(obj), &nvalue(obj))) | 35 | return n; |
| 36 | return 2; | ||
| 37 | ttype(obj) = LUA_TNUMBER; | ||
| 38 | return 0; | ||
| 39 | } | 36 | } |
| 37 | else | ||
| 38 | return NULL; | ||
| 40 | } | 39 | } |
| 41 | 40 | ||
| 42 | 41 | ||
| @@ -148,8 +147,7 @@ void luaV_gettable (lua_State *L, StkId t, TObject *key, StkId res) { | |||
| 148 | } | 147 | } |
| 149 | } | 148 | } |
| 150 | /* else will call the tag method */ | 149 | /* else will call the tag method */ |
| 151 | } | 150 | } else { /* not a table; try a `gettable' tag method */ |
| 152 | else { /* not a table; try a `gettable' tag method */ | ||
| 153 | tm = luaT_gettmbyObj(G(L), t, TM_GETTABLE); | 151 | tm = luaT_gettmbyObj(G(L), t, TM_GETTABLE); |
| 154 | if (tm == NULL) /* no tag method? */ | 152 | if (tm == NULL) /* no tag method? */ |
| 155 | luaG_typeerror(L, t, l_s("index")); | 153 | luaG_typeerror(L, t, l_s("index")); |
| @@ -162,7 +160,7 @@ void luaV_gettable (lua_State *L, StkId t, TObject *key, StkId res) { | |||
| 162 | /* | 160 | /* |
| 163 | ** Receives table at `t', key at `key' and value at `val'. | 161 | ** Receives table at `t', key at `key' and value at `val'. |
| 164 | */ | 162 | */ |
| 165 | void luaV_settable (lua_State *L, StkId t, StkId key, StkId val) { | 163 | void luaV_settable (lua_State *L, StkId t, TObject *key, StkId val) { |
| 166 | Closure *tm; | 164 | Closure *tm; |
| 167 | if (ttype(t) == LUA_TTABLE) { /* `t' is a table? */ | 165 | if (ttype(t) == LUA_TTABLE) { /* `t' is a table? */ |
| 168 | int tg = hvalue(t)->htag; | 166 | int tg = hvalue(t)->htag; |
| @@ -172,8 +170,7 @@ void luaV_settable (lua_State *L, StkId t, StkId key, StkId val) { | |||
| 172 | return; | 170 | return; |
| 173 | } | 171 | } |
| 174 | /* else will call the tag method */ | 172 | /* else will call the tag method */ |
| 175 | } | 173 | } else { /* not a table; try a `settable' tag method */ |
| 176 | else { /* not a table; try a `settable' tag method */ | ||
| 177 | tm = luaT_gettmbyObj(G(L), t, TM_SETTABLE); | 174 | tm = luaT_gettmbyObj(G(L), t, TM_SETTABLE); |
| 178 | if (tm == NULL) /* no tag method? */ | 175 | if (tm == NULL) /* no tag method? */ |
| 179 | luaG_typeerror(L, t, l_s("index")); | 176 | luaG_typeerror(L, t, l_s("index")); |
| @@ -188,8 +185,7 @@ void luaV_getglobal (lua_State *L, TString *name, StkId res) { | |||
| 188 | if (!HAS_TM_GETGLOBAL(L, ttype(value)) || /* is there a tag method? */ | 185 | if (!HAS_TM_GETGLOBAL(L, ttype(value)) || /* is there a tag method? */ |
| 189 | (tm = luaT_gettmbyObj(G(L), value, TM_GETGLOBAL)) == NULL) { | 186 | (tm = luaT_gettmbyObj(G(L), value, TM_GETGLOBAL)) == NULL) { |
| 190 | setobj(res, value); /* default behavior */ | 187 | setobj(res, value); /* default behavior */ |
| 191 | } | 188 | } else |
| 192 | else | ||
| 193 | callTM(L, l_s("csor"), tm, name, value, res); | 189 | callTM(L, l_s("csor"), tm, name, value, res); |
| 194 | } | 190 | } |
| 195 | 191 | ||
| @@ -200,8 +196,7 @@ void luaV_setglobal (lua_State *L, TString *name, StkId val) { | |||
| 200 | if (!HAS_TM_SETGLOBAL(L, ttype(oldvalue)) || /* no tag methods? */ | 196 | if (!HAS_TM_SETGLOBAL(L, ttype(oldvalue)) || /* no tag methods? */ |
| 201 | (tm = luaT_gettmbyObj(G(L), oldvalue, TM_SETGLOBAL)) == NULL) { | 197 | (tm = luaT_gettmbyObj(G(L), oldvalue, TM_SETGLOBAL)) == NULL) { |
| 202 | setobj(oldvalue, val); /* raw set */ | 198 | setobj(oldvalue, val); /* raw set */ |
| 203 | } | 199 | } else |
| 204 | else | ||
| 205 | callTM(L, l_s("csoo"), tm, name, oldvalue, val); | 200 | callTM(L, l_s("csoo"), tm, name, oldvalue, val); |
| 206 | } | 201 | } |
| 207 | 202 | ||
| @@ -224,9 +219,10 @@ static int call_binTM (lua_State *L, const TObject *p1, const TObject *p2, | |||
| 224 | } | 219 | } |
| 225 | 220 | ||
| 226 | 221 | ||
| 227 | static void call_arith (lua_State *L, StkId p1, TMS event) { | 222 | static void call_arith (lua_State *L, StkId p1, TObject *p2, |
| 228 | if (!call_binTM(L, p1, p1+1, p1, event)) | 223 | StkId res, TMS event) { |
| 229 | luaG_binerror(L, p1, LUA_TNUMBER, l_s("perform arithmetic on")); | 224 | if (!call_binTM(L, p1, p2, res, event)) |
| 225 | luaG_aritherror(L, p1, p2); | ||
| 230 | } | 226 | } |
| 231 | 227 | ||
| 232 | 228 | ||
| @@ -270,9 +266,8 @@ void luaV_strconc (lua_State *L, int total, StkId top) { | |||
| 270 | int n = 2; /* number of elements handled in this pass (at least 2) */ | 266 | int n = 2; /* number of elements handled in this pass (at least 2) */ |
| 271 | if (tostring(L, top-2) || tostring(L, top-1)) { | 267 | if (tostring(L, top-2) || tostring(L, top-1)) { |
| 272 | if (!call_binTM(L, top-2, top-1, top-2, TM_CONCAT)) | 268 | if (!call_binTM(L, top-2, top-1, top-2, TM_CONCAT)) |
| 273 | luaG_binerror(L, top-2, LUA_TSTRING, l_s("concat")); | 269 | luaG_concaterror(L, top-2, top-1); |
| 274 | } | 270 | } else if (tsvalue(top-1)->len > 0) { /* if len=0, do nothing */ |
| 275 | else if (tsvalue(top-1)->len > 0) { /* if len=0, do nothing */ | ||
| 276 | /* at least two string values; get as many as possible */ | 271 | /* at least two string values; get as many as possible */ |
| 277 | lu_mem tl = (lu_mem)tsvalue(top-1)->len + (lu_mem)tsvalue(top-2)->len; | 272 | lu_mem tl = (lu_mem)tsvalue(top-1)->len + (lu_mem)tsvalue(top-2)->len; |
| 278 | l_char *buffer; | 273 | l_char *buffer; |
| @@ -321,7 +316,32 @@ static void adjust_varargs (lua_State *L, StkId base, int nfixargs) { | |||
| 321 | 316 | ||
| 322 | 317 | ||
| 323 | 318 | ||
| 324 | #define dojump(pc, i) ((pc) += GETARG_S(i)) | 319 | /* |
| 320 | ** some macros for common tasks in `luaV_execute' | ||
| 321 | */ | ||
| 322 | |||
| 323 | #define runtime_check(L, c) { if (!(c)) return L->top; } | ||
| 324 | |||
| 325 | #define RA(i) (base+GETARG_A(i)) | ||
| 326 | #define RB(i) (base+GETARG_B(i)) | ||
| 327 | #define RC(i) (base+GETARG_C(i)) | ||
| 328 | #define RKC(i) ((GETARG_C(i) < MAXSTACK) ? \ | ||
| 329 | base+GETARG_C(i) : \ | ||
| 330 | tf->k+GETARG_C(i)-MAXSTACK) | ||
| 331 | #define KBc(i) (tf->k+GETARG_Bc(i)) | ||
| 332 | |||
| 333 | #define Arith(op, optm) { \ | ||
| 334 | const TObject *b = RB(i); const TObject *c = RKC(i); \ | ||
| 335 | TObject tempb, tempc; \ | ||
| 336 | if ((ttype(b) == LUA_TNUMBER || (b = luaV_tonumber(b, &tempb)) != NULL) && \ | ||
| 337 | (ttype(c) == LUA_TNUMBER || (c = luaV_tonumber(c, &tempc)) != NULL)) { \ | ||
| 338 | setnvalue(RA(i), nvalue(b) op nvalue(c)); \ | ||
| 339 | } else \ | ||
| 340 | call_arith(L, RB(i), RKC(i), RA(i), optm); \ | ||
| 341 | } | ||
| 342 | |||
| 343 | |||
| 344 | #define dojump(pc, i) ((pc) += GETARG_sBc(i)) | ||
| 325 | 345 | ||
| 326 | /* | 346 | /* |
| 327 | ** Executes the given Lua function. Parameters are between [base,top). | 347 | ** Executes the given Lua function. Parameters are between [base,top). |
| @@ -329,328 +349,294 @@ static void adjust_varargs (lua_State *L, StkId base, int nfixargs) { | |||
| 329 | */ | 349 | */ |
| 330 | StkId luaV_execute (lua_State *L, const Closure *cl, StkId base) { | 350 | StkId luaV_execute (lua_State *L, const Closure *cl, StkId base) { |
| 331 | const Proto *const tf = cl->f.l; | 351 | const Proto *const tf = cl->f.l; |
| 332 | StkId top; /* keep top local, for performance */ | 352 | const Instruction *pc; |
| 333 | const Instruction *pc = tf->code; | 353 | lua_Hook linehook; |
| 334 | const lua_Hook linehook = L->linehook; | ||
| 335 | L->ci->pc = &pc; | ||
| 336 | if (tf->is_vararg) /* varargs? */ | 354 | if (tf->is_vararg) /* varargs? */ |
| 337 | adjust_varargs(L, base, tf->numparams); | 355 | adjust_varargs(L, base, tf->numparams); |
| 338 | luaD_adjusttop(L, base, tf->maxstacksize); | 356 | luaD_adjusttop(L, base, tf->maxstacksize); |
| 339 | top = base+tf->numparams+tf->is_vararg; | 357 | pc = tf->code; |
| 358 | L->ci->pc = &pc; | ||
| 359 | linehook = L->linehook; | ||
| 340 | /* main loop of interpreter */ | 360 | /* main loop of interpreter */ |
| 341 | for (;;) { | 361 | for (;;) { |
| 342 | const Instruction i = *pc++; | 362 | const Instruction i = *pc++; |
| 343 | lua_assert(L->top == base+tf->maxstacksize); | ||
| 344 | if (linehook) | 363 | if (linehook) |
| 345 | traceexec(L, linehook); | 364 | traceexec(L, linehook); |
| 346 | switch (GET_OPCODE(i)) { | 365 | switch (GET_OPCODE(i)) { |
| 347 | case OP_RETURN: { | 366 | case OP_MOVE: { |
| 348 | L->top = top; | 367 | setobj(RA(i), RB(i)); |
| 349 | return base+GETARG_U(i); | ||
| 350 | } | ||
| 351 | case OP_CALL: { | ||
| 352 | int nres = GETARG_B(i); | ||
| 353 | if (nres == MULT_RET) nres = LUA_MULTRET; | ||
| 354 | L->top = top; | ||
| 355 | luaD_call(L, base+GETARG_A(i), nres); | ||
| 356 | top = L->top; | ||
| 357 | L->top = base+tf->maxstacksize; | ||
| 358 | break; | ||
| 359 | } | ||
| 360 | case OP_PUSHNIL: { | ||
| 361 | int n = GETARG_U(i); | ||
| 362 | lua_assert(n>0); | ||
| 363 | do { | ||
| 364 | setnilvalue(top++); | ||
| 365 | } while (--n > 0); | ||
| 366 | break; | ||
| 367 | } | ||
| 368 | case OP_POP: { | ||
| 369 | top -= GETARG_U(i); | ||
| 370 | break; | ||
| 371 | } | ||
| 372 | case OP_PUSHINT: { | ||
| 373 | setnvalue(top, (lua_Number)GETARG_S(i)); | ||
| 374 | top++; | ||
| 375 | break; | ||
| 376 | } | ||
| 377 | case OP_PUSHSTRING: { | ||
| 378 | setsvalue(top, tf->kstr[GETARG_U(i)]); | ||
| 379 | top++; | ||
| 380 | break; | 368 | break; |
| 381 | } | 369 | } |
| 382 | case OP_PUSHNUM: { | 370 | case OP_LOADK: { |
| 383 | setnvalue(top, tf->knum[GETARG_U(i)]); | 371 | setobj(RA(i), KBc(i)); |
| 384 | top++; | ||
| 385 | break; | 372 | break; |
| 386 | } | 373 | } |
| 387 | case OP_PUSHNEGNUM: { | 374 | case OP_LOADINT: { |
| 388 | setnvalue(top, -tf->knum[GETARG_U(i)]); | 375 | setnvalue(RA(i), (lua_Number)GETARG_sBc(i)); |
| 389 | top++; | ||
| 390 | break; | 376 | break; |
| 391 | } | 377 | } |
| 392 | case OP_PUSHUPVALUE: { | 378 | case OP_LOADUPVAL: { |
| 393 | setobj(top++, &cl->upvalue[GETARG_U(i)]); | 379 | setobj(RA(i), cl->upvalue+GETARG_Bc(i)); |
| 394 | break; | 380 | break; |
| 395 | } | 381 | } |
| 396 | case OP_GETLOCAL: { | 382 | case OP_LOADNIL: { |
| 397 | setobj(top++, base+GETARG_U(i)); | 383 | TObject *ra = RA(i); |
| 384 | TObject *rb = RB(i); | ||
| 385 | do { | ||
| 386 | setnilvalue(ra++); | ||
| 387 | } while (ra <= rb); | ||
| 398 | break; | 388 | break; |
| 399 | } | 389 | } |
| 400 | case OP_GETGLOBAL: { | 390 | case OP_GETGLOBAL: { |
| 401 | luaV_getglobal(L, tf->kstr[GETARG_U(i)], top); | 391 | lua_assert(ttype(KBc(i)) == LUA_TSTRING); |
| 402 | top++; | 392 | luaV_getglobal(L, tsvalue(KBc(i)), RA(i)); |
| 403 | break; | 393 | break; |
| 404 | } | 394 | } |
| 405 | case OP_GETTABLE: { | 395 | case OP_GETTABLE: { |
| 406 | top--; | 396 | luaV_gettable(L, RB(i), RKC(i), RA(i)); |
| 407 | luaV_gettable(L, top-1, top, top-1); | ||
| 408 | break; | ||
| 409 | } | ||
| 410 | case OP_GETDOTTED: { | ||
| 411 | setsvalue(top, tf->kstr[GETARG_U(i)]); | ||
| 412 | luaV_gettable(L, top-1, top, top-1); | ||
| 413 | break; | ||
| 414 | } | ||
| 415 | case OP_GETINDEXED: { | ||
| 416 | luaV_gettable(L, top-1, base+GETARG_U(i), top-1); | ||
| 417 | break; | ||
| 418 | } | ||
| 419 | case OP_PUSHSELF: { | ||
| 420 | setobj(top, top-1); | ||
| 421 | setsvalue(top+1, tf->kstr[GETARG_U(i)]); | ||
| 422 | luaV_gettable(L, top-1, top+1, top-1); | ||
| 423 | top++; | ||
| 424 | break; | ||
| 425 | } | ||
| 426 | case OP_CREATETABLE: { | ||
| 427 | luaC_checkGC(L); | ||
| 428 | sethvalue(top, luaH_new(L, GETARG_U(i))); | ||
| 429 | top++; | ||
| 430 | break; | ||
| 431 | } | ||
| 432 | case OP_SETLOCAL: { | ||
| 433 | setobj(base+GETARG_U(i), --top); | ||
| 434 | break; | 397 | break; |
| 435 | } | 398 | } |
| 436 | case OP_SETGLOBAL: { | 399 | case OP_SETGLOBAL: { |
| 437 | top--; | 400 | lua_assert(ttype(KBc(i)) == LUA_TSTRING); |
| 438 | luaV_setglobal(L, tf->kstr[GETARG_U(i)], top); | 401 | luaV_setglobal(L, tsvalue(KBc(i)), RA(i)); |
| 439 | break; | 402 | break; |
| 440 | } | 403 | } |
| 441 | case OP_SETTABLE: { | 404 | case OP_SETTABLE: { |
| 442 | StkId t = top-GETARG_A(i); | 405 | luaV_settable(L, RB(i), RKC(i), RA(i)); |
| 443 | luaV_settable(L, t, t+1, top-1); | ||
| 444 | top -= GETARG_B(i); /* pop values */ | ||
| 445 | break; | 406 | break; |
| 446 | } | 407 | } |
| 447 | case OP_SETLIST: { | 408 | case OP_NEWTABLE: { |
| 448 | int aux = GETARG_A(i) * LFIELDS_PER_FLUSH; | 409 | luaC_checkGC(L); |
| 449 | TObject *t = base+GETARG_B(i); | 410 | sethvalue(RA(i), luaH_new(L, GETARG_Bc(i))); |
| 450 | Hash *h = hvalue(t); | ||
| 451 | int n; | ||
| 452 | for (n = top-t-1; n; n--) | ||
| 453 | setobj(luaH_setnum(L, h, n+aux), --top); | ||
| 454 | break; | 411 | break; |
| 455 | } | 412 | } |
| 456 | case OP_SETMAP: { | 413 | case OP_SELF: { |
| 457 | TObject *t = base+GETARG_U(i); | 414 | StkId ra = RA(i); |
| 458 | Hash *h = hvalue(t); | 415 | StkId rb = RB(i); |
| 459 | while (top-1 > t) { | 416 | setobj(ra+1, rb); |
| 460 | top-=2; | 417 | luaV_gettable(L, rb, RKC(i), ra); |
| 461 | setobj(luaH_set(L, h, top), top+1); | ||
| 462 | } | ||
| 463 | break; | 418 | break; |
| 464 | } | 419 | } |
| 465 | case OP_ADD: { | 420 | case OP_ADD: { |
| 466 | if (tonumber(top-2) || tonumber(top-1)) | 421 | Arith( + , TM_ADD); |
| 467 | call_arith(L, top-2, TM_ADD); | ||
| 468 | else | ||
| 469 | nvalue(top-2) += nvalue(top-1); | ||
| 470 | top--; | ||
| 471 | break; | ||
| 472 | } | ||
| 473 | case OP_ADDI: { | ||
| 474 | if (tonumber(top-1)) { | ||
| 475 | setnvalue(top, (lua_Number)GETARG_S(i)); | ||
| 476 | call_arith(L, top-1, TM_ADD); | ||
| 477 | } | ||
| 478 | else | ||
| 479 | nvalue(top-1) += (lua_Number)GETARG_S(i); | ||
| 480 | break; | 422 | break; |
| 481 | } | 423 | } |
| 482 | case OP_SUB: { | 424 | case OP_SUB: { |
| 483 | if (tonumber(top-2) || tonumber(top-1)) | 425 | Arith( - , TM_SUB); |
| 484 | call_arith(L, top-2, TM_SUB); | ||
| 485 | else | ||
| 486 | nvalue(top-2) -= nvalue(top-1); | ||
| 487 | top--; | ||
| 488 | break; | 426 | break; |
| 489 | } | 427 | } |
| 490 | case OP_MULT: { | 428 | case OP_MUL: { |
| 491 | if (tonumber(top-2) || tonumber(top-1)) | 429 | Arith( * , TM_MUL); |
| 492 | call_arith(L, top-2, TM_MUL); | ||
| 493 | else | ||
| 494 | nvalue(top-2) *= nvalue(top-1); | ||
| 495 | top--; | ||
| 496 | break; | 430 | break; |
| 497 | } | 431 | } |
| 498 | case OP_DIV: { | 432 | case OP_DIV: { |
| 499 | if (tonumber(top-2) || tonumber(top-1)) | 433 | Arith( / , TM_DIV); |
| 500 | call_arith(L, top-2, TM_DIV); | ||
| 501 | else | ||
| 502 | nvalue(top-2) /= nvalue(top-1); | ||
| 503 | top--; | ||
| 504 | break; | 434 | break; |
| 505 | } | 435 | } |
| 506 | case OP_POW: { | 436 | case OP_POW: { |
| 507 | if (!call_binTM(L, top-2, top-1, top-2, TM_POW)) | 437 | call_arith(L, RB(i), RKC(i), RA(i), TM_POW); |
| 508 | luaD_error(L, l_s("undefined operation")); | ||
| 509 | top--; | ||
| 510 | break; | 438 | break; |
| 511 | } | 439 | } |
| 512 | case OP_CONCAT: { | 440 | case OP_UNM: { |
| 513 | int n = GETARG_U(i); | 441 | const TObject *rb = RB(i); |
| 514 | luaV_strconc(L, n, top); | 442 | StkId ra = RA(i); |
| 515 | top -= n-1; | 443 | if (ttype(rb) == LUA_TNUMBER || (rb=luaV_tonumber(rb, ra)) != NULL) { |
| 516 | luaC_checkGC(L); | 444 | setnvalue(ra, -nvalue(rb)); |
| 517 | break; | 445 | } |
| 518 | } | 446 | else { |
| 519 | case OP_MINUS: { | 447 | TObject temp; |
| 520 | if (tonumber(top-1)) { | 448 | setnilvalue(&temp); |
| 521 | setnilvalue(top); | 449 | call_arith(L, RB(i), &temp, ra, TM_UNM); |
| 522 | call_arith(L, top-1, TM_UNM); | ||
| 523 | } | 450 | } |
| 524 | else | ||
| 525 | nvalue(top-1) = -nvalue(top-1); | ||
| 526 | break; | 451 | break; |
| 527 | } | 452 | } |
| 528 | case OP_NOT: { | 453 | case OP_NOT: { |
| 529 | ttype(top-1) = | 454 | if (ttype(RB(i)) == LUA_TNIL) { |
| 530 | (ttype(top-1) == LUA_TNIL) ? LUA_TNUMBER : LUA_TNIL; | 455 | setnvalue(RA(i), 1); |
| 531 | nvalue(top-1) = 1; | 456 | } else { |
| 457 | setnilvalue(RA(i)); | ||
| 458 | } | ||
| 532 | break; | 459 | break; |
| 533 | } | 460 | } |
| 534 | case OP_JMPNE: { | 461 | case OP_CONCAT: { |
| 535 | top -= 2; | 462 | StkId top = RC(i)+1; |
| 536 | if (!luaO_equalObj(top, top+1)) dojump(pc, i); | 463 | StkId rb = RB(i); |
| 464 | luaV_strconc(L, top-rb, top); | ||
| 465 | setobj(RA(i), rb); | ||
| 466 | luaC_checkGC(L); | ||
| 537 | break; | 467 | break; |
| 538 | } | 468 | } |
| 539 | case OP_JMPEQ: { | 469 | case OP_CJMP: |
| 540 | top -= 2; | 470 | case OP_JMP: { |
| 541 | if (luaO_equalObj(top, top+1)) dojump(pc, i); | 471 | dojump(pc, i); |
| 542 | break; | 472 | break; |
| 543 | } | 473 | } |
| 544 | case OP_JMPLT: { | 474 | case OP_TESTEQ: { |
| 545 | top -= 2; | 475 | lua_assert(GET_OPCODE(*pc) == OP_CJMP); |
| 546 | if (luaV_lessthan(L, top, top+1)) dojump(pc, i); | 476 | if (luaO_equalObj(RB(i), RKC(i))) dojump(pc, *pc); |
| 477 | pc++; | ||
| 547 | break; | 478 | break; |
| 548 | } | 479 | } |
| 549 | case OP_JMPLE: { /* a <= b === !(b<a) */ | 480 | case OP_TESTNE: { |
| 550 | top -= 2; | 481 | lua_assert(GET_OPCODE(*pc) == OP_CJMP); |
| 551 | if (!luaV_lessthan(L, top+1, top)) dojump(pc, i); | 482 | if (!luaO_equalObj(RB(i), RKC(i))) dojump(pc, *pc); |
| 483 | pc++; | ||
| 552 | break; | 484 | break; |
| 553 | } | 485 | } |
| 554 | case OP_JMPGT: { /* a > b === (b<a) */ | 486 | case OP_TESTLT: { |
| 555 | top -= 2; | 487 | lua_assert(GET_OPCODE(*pc) == OP_CJMP); |
| 556 | if (luaV_lessthan(L, top+1, top)) dojump(pc, i); | 488 | if (luaV_lessthan(L, RB(i), RKC(i))) dojump(pc, *pc); |
| 489 | pc++; | ||
| 557 | break; | 490 | break; |
| 558 | } | 491 | } |
| 559 | case OP_JMPGE: { /* a >= b === !(a<b) */ | 492 | case OP_TESTLE: { /* b <= c === !(c<b) */ |
| 560 | top -= 2; | 493 | lua_assert(GET_OPCODE(*pc) == OP_CJMP); |
| 561 | if (!luaV_lessthan(L, top, top+1)) dojump(pc, i); | 494 | if (!luaV_lessthan(L, RKC(i), RB(i))) dojump(pc, *pc); |
| 495 | pc++; | ||
| 562 | break; | 496 | break; |
| 563 | } | 497 | } |
| 564 | case OP_JMPT: { | 498 | case OP_TESTGT: { /* b > c === (c<b) */ |
| 565 | if (ttype(--top) != LUA_TNIL) dojump(pc, i); | 499 | lua_assert(GET_OPCODE(*pc) == OP_CJMP); |
| 500 | if (luaV_lessthan(L, RKC(i), RB(i))) dojump(pc, *pc); | ||
| 501 | pc++; | ||
| 566 | break; | 502 | break; |
| 567 | } | 503 | } |
| 568 | case OP_JMPF: { | 504 | case OP_TESTGE: { /* b >= c === !(b<c) */ |
| 569 | if (ttype(--top) == LUA_TNIL) dojump(pc, i); | 505 | lua_assert(GET_OPCODE(*pc) == OP_CJMP); |
| 506 | if (!luaV_lessthan(L, RB(i), RKC(i))) dojump(pc, *pc); | ||
| 507 | pc++; | ||
| 570 | break; | 508 | break; |
| 571 | } | 509 | } |
| 572 | case OP_JMPONT: { | 510 | case OP_TESTT: { |
| 573 | if (ttype(top-1) == LUA_TNIL) top--; | 511 | StkId rb = RB(i); |
| 574 | else dojump(pc, i); | 512 | lua_assert(GET_OPCODE(*pc) == OP_CJMP); |
| 513 | if (ttype(rb) != LUA_TNIL) { | ||
| 514 | int a = GETARG_A(i); | ||
| 515 | if (a != NO_REG) setobj(base+a, rb); | ||
| 516 | dojump(pc, *pc); | ||
| 517 | } | ||
| 518 | pc++; | ||
| 575 | break; | 519 | break; |
| 576 | } | 520 | } |
| 577 | case OP_JMPONF: { | 521 | case OP_TESTF: { |
| 578 | if (ttype(top-1) != LUA_TNIL) top--; | 522 | lua_assert(GET_OPCODE(*pc) == OP_CJMP); |
| 579 | else dojump(pc, i); | 523 | if (ttype(RB(i)) == LUA_TNIL) { |
| 524 | int a = GETARG_A(i); | ||
| 525 | if (a != NO_REG) setnilvalue(base+a); | ||
| 526 | dojump(pc, *pc); | ||
| 527 | } | ||
| 528 | pc++; | ||
| 580 | break; | 529 | break; |
| 581 | } | 530 | } |
| 582 | case OP_JMP: { | 531 | case OP_NILJMP: { |
| 583 | dojump(pc, i); | 532 | setnilvalue(RA(i)); |
| 533 | pc++; | ||
| 584 | break; | 534 | break; |
| 585 | } | 535 | } |
| 586 | case OP_PUSHNILJMP: { | 536 | case OP_CALL: { |
| 587 | setnilvalue(top++); | 537 | int nres; |
| 588 | pc++; | 538 | int b = GETARG_B(i); |
| 539 | if (b != NO_REG) | ||
| 540 | L->top = base+b; | ||
| 541 | nres = GETARG_C(i); | ||
| 542 | if (nres == NO_REG) nres = LUA_MULTRET; | ||
| 543 | luaD_call(L, RA(i), nres); | ||
| 544 | if (nres != LUA_MULTRET) { | ||
| 545 | lua_assert(L->top == RA(i)+nres); | ||
| 546 | L->top = base+tf->maxstacksize; | ||
| 547 | } | ||
| 589 | break; | 548 | break; |
| 590 | } | 549 | } |
| 550 | case OP_RETURN: { | ||
| 551 | int b = GETARG_B(i); | ||
| 552 | if (b != NO_REG) | ||
| 553 | L->top = base+b; | ||
| 554 | return RA(i); | ||
| 555 | } | ||
| 591 | case OP_FORPREP: { | 556 | case OP_FORPREP: { |
| 592 | int jmp = GETARG_S(i); | 557 | int jmp = GETARG_sBc(i); |
| 593 | if (tonumber(top-1)) | 558 | StkId breg = RA(i); |
| 594 | luaD_error(L, l_s("`for' step must be a number")); | 559 | if (luaV_tonumber(breg, breg) == NULL) |
| 595 | if (tonumber(top-2)) | ||
| 596 | luaD_error(L, l_s("`for' limit must be a number")); | ||
| 597 | if (tonumber(top-3)) | ||
| 598 | luaD_error(L, l_s("`for' initial value must be a number")); | 560 | luaD_error(L, l_s("`for' initial value must be a number")); |
| 561 | if (luaV_tonumber(breg+1, breg+1) == NULL) | ||
| 562 | luaD_error(L, l_s("`for' limit must be a number")); | ||
| 563 | if (luaV_tonumber(breg+2, breg+2) == NULL) | ||
| 564 | luaD_error(L, l_s("`for' step must be a number")); | ||
| 599 | pc += -jmp; /* `jump' to loop end (delta is negated here) */ | 565 | pc += -jmp; /* `jump' to loop end (delta is negated here) */ |
| 600 | goto forloop; /* do not increment index */ | 566 | nvalue(breg) -= nvalue(breg+2);/* decrement index (to be incremented) */ |
| 567 | /* go through */ | ||
| 601 | } | 568 | } |
| 602 | case OP_FORLOOP: { | 569 | case OP_FORLOOP: { |
| 603 | lua_assert(ttype(top-1) == LUA_TNUMBER); | 570 | StkId breg = RA(i); |
| 604 | lua_assert(ttype(top-2) == LUA_TNUMBER); | 571 | if (ttype(breg) != LUA_TNUMBER) |
| 605 | if (ttype(top-3) != LUA_TNUMBER) | ||
| 606 | luaD_error(L, l_s("`for' index must be a number")); | 572 | luaD_error(L, l_s("`for' index must be a number")); |
| 607 | nvalue(top-3) += nvalue(top-1); /* increment index */ | 573 | runtime_check(L, ttype(breg+1) == LUA_TNUMBER && |
| 608 | forloop: | 574 | ttype(breg+2) == LUA_TNUMBER); |
| 609 | if (nvalue(top-1) > 0 ? | 575 | nvalue(breg) += nvalue(breg+2); /* increment index */ |
| 610 | nvalue(top-3) > nvalue(top-2) : | 576 | if (nvalue(breg+2) > 0 ? |
| 611 | nvalue(top-3) < nvalue(top-2)) | 577 | nvalue(breg) <= nvalue(breg+1) : |
| 612 | top -= 3; /* end loop: remove control variables */ | 578 | nvalue(breg) >= nvalue(breg+1)) |
| 613 | else | ||
| 614 | dojump(pc, i); /* repeat loop */ | 579 | dojump(pc, i); /* repeat loop */ |
| 615 | break; | 580 | break; |
| 616 | } | 581 | } |
| 617 | case OP_LFORPREP: { | 582 | case OP_TFORPREP: { |
| 618 | int jmp = GETARG_S(i); | 583 | int jmp = GETARG_sBc(i); |
| 619 | if (ttype(top-1) != LUA_TTABLE) | 584 | StkId breg = RA(i); |
| 585 | if (ttype(breg) != LUA_TTABLE) | ||
| 620 | luaD_error(L, l_s("`for' table must be a table")); | 586 | luaD_error(L, l_s("`for' table must be a table")); |
| 621 | top += 3; /* index,key,value */ | 587 | setnvalue(breg+1, -1); /* initial index */ |
| 622 | setnvalue(top-3, -1); /* initial index */ | 588 | setnilvalue(breg+2); |
| 623 | setnilvalue(top-2); | 589 | setnilvalue(breg+3); |
| 624 | setnilvalue(top-1); | ||
| 625 | pc += -jmp; /* `jump' to loop end (delta is negated here) */ | 590 | pc += -jmp; /* `jump' to loop end (delta is negated here) */ |
| 626 | /* go through */ | 591 | /* go through */ |
| 627 | } | 592 | } |
| 628 | case OP_LFORLOOP: { | 593 | case OP_TFORLOOP: { |
| 629 | Hash *t = hvalue(top-4); | 594 | StkId breg = RA(i); |
| 630 | int n = (int)nvalue(top-3); | 595 | Hash *t; |
| 631 | lua_assert(ttype(top-3) == LUA_TNUMBER); | 596 | int n; |
| 632 | lua_assert(ttype(top-4) == LUA_TTABLE); | 597 | runtime_check(L, ttype(breg) == LUA_TTABLE); |
| 598 | runtime_check(L, ttype(breg+1) == LUA_TNUMBER); | ||
| 599 | t = hvalue(breg); | ||
| 600 | n = (int)nvalue(breg+1); | ||
| 633 | n = luaH_nexti(t, n); | 601 | n = luaH_nexti(t, n); |
| 634 | if (n == -1) /* end loop? */ | 602 | if (n != -1) { /* repeat loop? */ |
| 635 | top -= 4; /* remove table, index, key, and value */ | ||
| 636 | else { | ||
| 637 | Node *node = node(t, n); | 603 | Node *node = node(t, n); |
| 638 | setnvalue(top-3, n); /* index */ | 604 | setnvalue(breg+1, n); /* index */ |
| 639 | setkey2obj(top-2, node); | 605 | setkey2obj(breg+2, node); |
| 640 | setobj(top-1, val(node)); | 606 | setobj(breg+3, val(node)); |
| 641 | dojump(pc, i); /* repeat loop */ | 607 | dojump(pc, i); /* repeat loop */ |
| 642 | } | 608 | } |
| 643 | break; | 609 | break; |
| 644 | } | 610 | } |
| 611 | case OP_SETLIST: | ||
| 612 | case OP_SETLISTO: { | ||
| 613 | int bc; | ||
| 614 | int n; | ||
| 615 | Hash *h; | ||
| 616 | StkId ra = RA(i); | ||
| 617 | runtime_check(L, ttype(ra) == LUA_TTABLE); | ||
| 618 | h = hvalue(ra); | ||
| 619 | bc = GETARG_Bc(i); | ||
| 620 | if (GET_OPCODE(i) == OP_SETLIST) | ||
| 621 | n = (bc&(LFIELDS_PER_FLUSH-1)) + 1; | ||
| 622 | else | ||
| 623 | n = L->top - ra - 1; | ||
| 624 | bc &= ~(LFIELDS_PER_FLUSH-1); /* bc = bc - bc%FPF */ | ||
| 625 | for (; n > 0; n--) | ||
| 626 | setobj(luaH_setnum(L, h, bc+n), ra+n); | ||
| 627 | break; | ||
| 628 | } | ||
| 645 | case OP_CLOSURE: { | 629 | case OP_CLOSURE: { |
| 646 | int nup = GETARG_B(i); | 630 | Proto *p = tf->kproto[GETARG_Bc(i)]; |
| 647 | luaC_checkGC(L); | 631 | int nup = p->nupvalues; |
| 648 | L->top = top; | 632 | StkId ra = RA(i); |
| 649 | luaV_Lclosure(L, tf->kproto[GETARG_A(i)], nup); | 633 | L->top = ra+nup; |
| 650 | top -= (nup-1); | 634 | luaV_Lclosure(L, p, nup); |
| 651 | L->top = base+tf->maxstacksize; | 635 | L->top = base+tf->maxstacksize; |
| 636 | luaC_checkGC(L); | ||
| 652 | break; | 637 | break; |
| 653 | } | 638 | } |
| 654 | } | 639 | } |
| 655 | } | 640 | } |
| 656 | } | 641 | } |
| 642 | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lvm.h,v 1.28 2001/02/01 16:03:38 roberto Exp roberto $ | 2 | ** $Id: lvm.h,v 1.29 2001/02/07 18:13:49 roberto Exp roberto $ |
| 3 | ** Lua virtual machine | 3 | ** Lua virtual machine |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -13,14 +13,13 @@ | |||
| 13 | #include "ltm.h" | 13 | #include "ltm.h" |
| 14 | 14 | ||
| 15 | 15 | ||
| 16 | #define tonumber(o) ((ttype(o) != LUA_TNUMBER) && (luaV_tonumber(o) != 0)) | ||
| 17 | #define tostring(L,o) ((ttype(o) != LUA_TSTRING) && (luaV_tostring(L, o) != 0)) | 16 | #define tostring(L,o) ((ttype(o) != LUA_TSTRING) && (luaV_tostring(L, o) != 0)) |
| 18 | 17 | ||
| 19 | 18 | ||
| 20 | int luaV_tonumber (TObject *obj); | 19 | const TObject *luaV_tonumber (const TObject *obj, TObject *n); |
| 21 | int luaV_tostring (lua_State *L, TObject *obj); | 20 | int luaV_tostring (lua_State *L, TObject *obj); |
| 22 | void luaV_gettable (lua_State *L, StkId t, TObject *key, StkId res); | 21 | void luaV_gettable (lua_State *L, StkId t, TObject *key, StkId res); |
| 23 | void luaV_settable (lua_State *L, StkId t, StkId key, StkId val); | 22 | void luaV_settable (lua_State *L, StkId t, TObject *key, StkId val); |
| 24 | void luaV_getglobal (lua_State *L, TString *s, StkId res); | 23 | void luaV_getglobal (lua_State *L, TString *s, StkId res); |
| 25 | void luaV_setglobal (lua_State *L, TString *s, StkId val); | 24 | void luaV_setglobal (lua_State *L, TString *s, StkId val); |
| 26 | StkId luaV_execute (lua_State *L, const Closure *cl, StkId base); | 25 | StkId luaV_execute (lua_State *L, const Closure *cl, StkId base); |
