diff options
| -rw-r--r-- | lcode.c | 290 | ||||
| -rw-r--r-- | lcode.h | 6 | ||||
| -rw-r--r-- | lopcodes.h | 60 | ||||
| -rw-r--r-- | lparser.c | 68 | ||||
| -rw-r--r-- | lparser.h | 14 | ||||
| -rw-r--r-- | lvm.c | 77 |
6 files changed, 371 insertions, 144 deletions
| @@ -5,6 +5,8 @@ | |||
| 5 | */ | 5 | */ |
| 6 | 6 | ||
| 7 | 7 | ||
| 8 | #define LUA_REENTRANT | ||
| 9 | |||
| 8 | #include "lcode.h" | 10 | #include "lcode.h" |
| 9 | #include "ldo.h" | 11 | #include "ldo.h" |
| 10 | #include "llex.h" | 12 | #include "llex.h" |
| @@ -47,9 +49,9 @@ int luaK_primitivecode (LexState *ls, Instruction i) { | |||
| 47 | static void luaK_minus (LexState *ls) { | 49 | static void luaK_minus (LexState *ls) { |
| 48 | Instruction *previous = previous_instruction(ls); | 50 | Instruction *previous = previous_instruction(ls); |
| 49 | switch(GET_OPCODE(*previous)) { | 51 | switch(GET_OPCODE(*previous)) { |
| 50 | case PUSHINT: *previous = SETARG_S(*previous, -GETARG_S(*previous)); return; | 52 | case PUSHINT: SETARG_S(*previous, -GETARG_S(*previous)); return; |
| 51 | case PUSHNUM: *previous = SET_OPCODE(*previous, PUSHNEGNUM); return; | 53 | case PUSHNUM: SET_OPCODE(*previous, PUSHNEGNUM); return; |
| 52 | case PUSHNEGNUM: *previous = SET_OPCODE(*previous, PUSHNUM); return; | 54 | case PUSHNEGNUM: SET_OPCODE(*previous, PUSHNUM); return; |
| 53 | default: luaK_primitivecode(ls, CREATE_0(MINUSOP)); | 55 | default: luaK_primitivecode(ls, CREATE_0(MINUSOP)); |
| 54 | } | 56 | } |
| 55 | } | 57 | } |
| @@ -59,7 +61,7 @@ static void luaK_gettable (LexState *ls) { | |||
| 59 | Instruction *previous = previous_instruction(ls); | 61 | Instruction *previous = previous_instruction(ls); |
| 60 | luaK_deltastack(ls, -1); | 62 | luaK_deltastack(ls, -1); |
| 61 | switch(GET_OPCODE(*previous)) { | 63 | switch(GET_OPCODE(*previous)) { |
| 62 | case PUSHSTRING: *previous = SET_OPCODE(*previous, GETDOTTED); break; | 64 | case PUSHSTRING: SET_OPCODE(*previous, GETDOTTED); break; |
| 63 | default: luaK_primitivecode(ls, CREATE_0(GETTABLE)); | 65 | default: luaK_primitivecode(ls, CREATE_0(GETTABLE)); |
| 64 | } | 66 | } |
| 65 | } | 67 | } |
| @@ -69,7 +71,7 @@ static void luaK_add (LexState *ls) { | |||
| 69 | Instruction *previous = previous_instruction(ls); | 71 | Instruction *previous = previous_instruction(ls); |
| 70 | luaK_deltastack(ls, -1); | 72 | luaK_deltastack(ls, -1); |
| 71 | switch(GET_OPCODE(*previous)) { | 73 | switch(GET_OPCODE(*previous)) { |
| 72 | case PUSHINT: *previous = SET_OPCODE(*previous, ADDI); break; | 74 | case PUSHINT: SET_OPCODE(*previous, ADDI); break; |
| 73 | default: luaK_primitivecode(ls, CREATE_0(ADDOP)); | 75 | default: luaK_primitivecode(ls, CREATE_0(ADDOP)); |
| 74 | } | 76 | } |
| 75 | } | 77 | } |
| @@ -80,8 +82,8 @@ static void luaK_sub (LexState *ls) { | |||
| 80 | luaK_deltastack(ls, -1); | 82 | luaK_deltastack(ls, -1); |
| 81 | switch(GET_OPCODE(*previous)) { | 83 | switch(GET_OPCODE(*previous)) { |
| 82 | case PUSHINT: | 84 | case PUSHINT: |
| 83 | *previous = SET_OPCODE(*previous, ADDI); | 85 | SET_OPCODE(*previous, ADDI); |
| 84 | *previous = SETARG_S(*previous, -GETARG_S(*previous)); | 86 | SETARG_S(*previous, -GETARG_S(*previous)); |
| 85 | break; | 87 | break; |
| 86 | default: luaK_primitivecode(ls, CREATE_0(SUBOP)); | 88 | default: luaK_primitivecode(ls, CREATE_0(SUBOP)); |
| 87 | } | 89 | } |
| @@ -92,7 +94,7 @@ static void luaK_conc (LexState *ls) { | |||
| 92 | Instruction *previous = previous_instruction(ls); | 94 | Instruction *previous = previous_instruction(ls); |
| 93 | luaK_deltastack(ls, -1); | 95 | luaK_deltastack(ls, -1); |
| 94 | switch(GET_OPCODE(*previous)) { | 96 | switch(GET_OPCODE(*previous)) { |
| 95 | case CONCOP: *previous = SETARG_U(*previous, GETARG_U(*previous)+1); break; | 97 | case CONCOP: SETARG_U(*previous, GETARG_U(*previous)+1); break; |
| 96 | default: luaK_primitivecode(ls, CREATE_U(CONCOP, 2)); | 98 | default: luaK_primitivecode(ls, CREATE_U(CONCOP, 2)); |
| 97 | } | 99 | } |
| 98 | } | 100 | } |
| @@ -102,8 +104,8 @@ void luaK_retcode (LexState *ls, int nlocals, int nexps) { | |||
| 102 | Instruction *previous = previous_instruction(ls); | 104 | Instruction *previous = previous_instruction(ls); |
| 103 | if (nexps > 0 && GET_OPCODE(*previous) == CALL) { | 105 | if (nexps > 0 && GET_OPCODE(*previous) == CALL) { |
| 104 | LUA_ASSERT(ls->L, GETARG_B(*previous) == MULT_RET, "call should be open"); | 106 | LUA_ASSERT(ls->L, GETARG_B(*previous) == MULT_RET, "call should be open"); |
| 105 | *previous = SET_OPCODE(*previous, TAILCALL); | 107 | SET_OPCODE(*previous, TAILCALL); |
| 106 | *previous = SETARG_B(*previous, nlocals); | 108 | SETARG_B(*previous, nlocals); |
| 107 | } | 109 | } |
| 108 | else | 110 | else |
| 109 | luaK_primitivecode(ls, CREATE_U(RETCODE, nlocals)); | 111 | luaK_primitivecode(ls, CREATE_U(RETCODE, nlocals)); |
| @@ -115,7 +117,7 @@ static void luaK_pushnil (LexState *ls, int n) { | |||
| 115 | luaK_deltastack(ls, n); | 117 | luaK_deltastack(ls, n); |
| 116 | switch(GET_OPCODE(*previous)) { | 118 | switch(GET_OPCODE(*previous)) { |
| 117 | case PUSHNIL: | 119 | case PUSHNIL: |
| 118 | *previous = SETARG_U(*previous, GETARG_U(*previous)+n); | 120 | SETARG_U(*previous, GETARG_U(*previous)+n); |
| 119 | break; | 121 | break; |
| 120 | default: luaK_primitivecode(ls, CREATE_U(PUSHNIL, n)); | 122 | default: luaK_primitivecode(ls, CREATE_U(PUSHNIL, n)); |
| 121 | } | 123 | } |
| @@ -132,7 +134,7 @@ void luaK_fixjump (LexState *ls, int pc, int dest) { | |||
| 132 | FuncState *fs = ls->fs; | 134 | FuncState *fs = ls->fs; |
| 133 | Instruction *jmp = &fs->f->code[pc]; | 135 | Instruction *jmp = &fs->f->code[pc]; |
| 134 | /* jump is relative to position following jump instruction */ | 136 | /* jump is relative to position following jump instruction */ |
| 135 | *jmp = SETARG_S(*jmp, dest-(pc+1)); | 137 | SETARG_S(*jmp, dest-(pc+1)); |
| 136 | } | 138 | } |
| 137 | 139 | ||
| 138 | 140 | ||
| @@ -213,7 +215,7 @@ void luaK_setcallreturns (LexState *ls, int nresults) { | |||
| 213 | Instruction *i = previous_instruction(ls); | 215 | Instruction *i = previous_instruction(ls); |
| 214 | if (GET_OPCODE(*i) == CALL) { /* expression is a function call? */ | 216 | if (GET_OPCODE(*i) == CALL) { /* expression is a function call? */ |
| 215 | LUA_ASSERT(ls->L, GETARG_B(*i) == MULT_RET, "call should be open"); | 217 | LUA_ASSERT(ls->L, GETARG_B(*i) == MULT_RET, "call should be open"); |
| 216 | *i = SETARG_B(*i, nresults); /* set nresults */ | 218 | SETARG_B(*i, nresults); /* set nresults */ |
| 217 | luaK_deltastack(ls, nresults); /* push results */ | 219 | luaK_deltastack(ls, nresults); /* push results */ |
| 218 | } | 220 | } |
| 219 | } | 221 | } |
| @@ -224,41 +226,43 @@ static void assertglobal (LexState *ls, int index) { | |||
| 224 | } | 226 | } |
| 225 | 227 | ||
| 226 | 228 | ||
| 227 | void luaK_tostack (LexState *ls, expdesc *var) { | 229 | static int discharge (LexState *ls, expdesc *var) { |
| 228 | switch (var->k) { | 230 | switch (var->k) { |
| 229 | case VLOCAL: | 231 | case VLOCAL: |
| 230 | luaK_U(ls, PUSHLOCAL, var->info, 1); | 232 | luaK_U(ls, PUSHLOCAL, var->u.index, 1); |
| 231 | break; | 233 | break; |
| 232 | case VGLOBAL: | 234 | case VGLOBAL: |
| 233 | luaK_U(ls, GETGLOBAL, var->info, 1); | 235 | luaK_U(ls, GETGLOBAL, var->u.index, 1); |
| 234 | assertglobal(ls, var->info); /* make sure that there is a global */ | 236 | assertglobal(ls, var->u.index); /* make sure that there is a global */ |
| 235 | break; | 237 | break; |
| 236 | case VINDEXED: | 238 | case VINDEXED: |
| 237 | luaK_gettable(ls); | 239 | luaK_gettable(ls); |
| 238 | break; | 240 | break; |
| 239 | case VEXP: | 241 | case VEXP: |
| 240 | return; /* exp result is already on stack */ | 242 | return 0; /* nothing to do */ |
| 241 | } | 243 | } |
| 242 | var->k = VEXP; | 244 | var->k = VEXP; |
| 245 | var->u.l.t = var->u.l.f = 0; | ||
| 246 | return 1; | ||
| 243 | } | 247 | } |
| 244 | 248 | ||
| 245 | 249 | ||
| 246 | void luaK_1tostack (LexState *ls, expdesc *var) { | 250 | static void discharge1 (LexState *ls, expdesc *var) { |
| 247 | if (var->k == VEXP) | 251 | discharge(ls, var); |
| 252 | /* if it has jumps it is already discharged */ | ||
| 253 | if (var->u.l.t == 0 && var->u.l.f == 0) | ||
| 248 | luaK_setcallreturns(ls, 1); /* call must return 1 value */ | 254 | luaK_setcallreturns(ls, 1); /* call must return 1 value */ |
| 249 | else | ||
| 250 | luaK_tostack(ls, var); | ||
| 251 | } | 255 | } |
| 252 | 256 | ||
| 253 | 257 | ||
| 254 | void luaK_storevar (LexState *ls, const expdesc *var) { | 258 | void luaK_storevar (LexState *ls, const expdesc *var) { |
| 255 | switch (var->k) { | 259 | switch (var->k) { |
| 256 | case VLOCAL: | 260 | case VLOCAL: |
| 257 | luaK_U(ls, SETLOCAL, var->info, -1); | 261 | luaK_U(ls, SETLOCAL, var->u.index, -1); |
| 258 | break; | 262 | break; |
| 259 | case VGLOBAL: | 263 | case VGLOBAL: |
| 260 | luaK_U(ls, SETGLOBAL, var->info, -1); | 264 | luaK_U(ls, SETGLOBAL, var->u.index, -1); |
| 261 | assertglobal(ls, var->info); /* make sure that there is a global */ | 265 | assertglobal(ls, var->u.index); /* make sure that there is a global */ |
| 262 | break; | 266 | break; |
| 263 | case VINDEXED: | 267 | case VINDEXED: |
| 264 | luaK_0(ls, SETTABLEPOP, -3); | 268 | luaK_0(ls, SETTABLEPOP, -3); |
| @@ -269,40 +273,228 @@ void luaK_storevar (LexState *ls, const expdesc *var) { | |||
| 269 | } | 273 | } |
| 270 | 274 | ||
| 271 | 275 | ||
| 276 | static OpCode invertjump (OpCode op) { | ||
| 277 | switch (op) { | ||
| 278 | case IFNEQJMP: return IFEQJMP; | ||
| 279 | case IFEQJMP: return IFNEQJMP; | ||
| 280 | case IFLTJMP: return IFGEJMP; | ||
| 281 | case IFLEJMP: return IFGTJMP; | ||
| 282 | case IFGTJMP: return IFLEJMP; | ||
| 283 | case IFGEJMP: return IFLTJMP; | ||
| 284 | default: | ||
| 285 | LUA_INTERNALERROR(NULL, "invalid jump instruction"); | ||
| 286 | return ENDCODE; /* to avoid warnings */ | ||
| 287 | } | ||
| 288 | } | ||
| 289 | |||
| 290 | |||
| 291 | static void insert_last (FuncState *fs, int *list) { | ||
| 292 | int temp = *list; | ||
| 293 | *list = fs->pc-1; | ||
| 294 | if (temp == 0) /* chain list */ | ||
| 295 | SETARG_S(fs->f->code[*list], 0); | ||
| 296 | else | ||
| 297 | SETARG_S(fs->f->code[*list], temp-fs->pc); | ||
| 298 | } | ||
| 299 | |||
| 300 | |||
| 301 | static void luaK_patchlistaux (LexState *ls, int list, int target, | ||
| 302 | OpCode special, int special_target) { | ||
| 303 | if (list != 0) { | ||
| 304 | Instruction *code = ls->fs->f->code; | ||
| 305 | for (;;) { | ||
| 306 | Instruction *i = &code[list]; | ||
| 307 | OpCode op = GET_OPCODE(*i); | ||
| 308 | int temp = GETARG_S(*i); | ||
| 309 | if (op == special) | ||
| 310 | SETARG_S(*i, special_target-(list+1)); | ||
| 311 | else { | ||
| 312 | SETARG_S(*i, target-(list+1)); | ||
| 313 | if (op == ONTJMP) | ||
| 314 | SET_OPCODE(*i, IFTJMP); | ||
| 315 | else if (op == ONFJMP) | ||
| 316 | SET_OPCODE(*i, IFFJMP); | ||
| 317 | } | ||
| 318 | if (temp == 0) return; | ||
| 319 | list += temp+1; | ||
| 320 | } | ||
| 321 | } | ||
| 322 | } | ||
| 323 | |||
| 324 | |||
| 325 | void luaK_patchlist (LexState *ls, int list, int target) { | ||
| 326 | luaK_patchlistaux(ls, list, target, ENDCODE, 0); | ||
| 327 | } | ||
| 328 | |||
| 329 | |||
| 330 | static int has_jumps (FuncState *fs, int list, OpCode ignore) { | ||
| 331 | if (list == 0) return 0; | ||
| 332 | else { | ||
| 333 | Instruction *code = fs->f->code; | ||
| 334 | for (;;) { | ||
| 335 | int temp = GETARG_S(code[list]); | ||
| 336 | if (GET_OPCODE(code[list]) != ignore) return 1; | ||
| 337 | else if (temp == 0) return 0; | ||
| 338 | list += temp+1; | ||
| 339 | } | ||
| 340 | } | ||
| 341 | } | ||
| 342 | |||
| 343 | |||
| 344 | static void concatlists (LexState *ls, int *l1, int l2) { | ||
| 345 | if (*l1 == 0) | ||
| 346 | *l1 = l2; | ||
| 347 | else if (l2 != 0) { | ||
| 348 | FuncState *fs = ls->fs; | ||
| 349 | int list = *l1; | ||
| 350 | for (;;) { /* traverse `l1' */ | ||
| 351 | int temp = GETARG_S(fs->f->code[list]); | ||
| 352 | if (temp == 0) { /* end of list? */ | ||
| 353 | SETARG_S(fs->f->code[list], l2-(list+1)); /* end points to `l2' */ | ||
| 354 | return; | ||
| 355 | } | ||
| 356 | list += temp+1; | ||
| 357 | } | ||
| 358 | } | ||
| 359 | } | ||
| 360 | |||
| 361 | |||
| 362 | void luaK_goiftrue (LexState *ls, expdesc *v, int keepvalue) { | ||
| 363 | FuncState *fs = ls->fs; | ||
| 364 | Instruction *previous; | ||
| 365 | discharge1(ls, 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 | OpCode jump = keepvalue ? ONFJMP : IFFJMP; | ||
| 371 | luaK_S(ls, jump, 0, -1); | ||
| 372 | } | ||
| 373 | insert_last(fs, &v->u.l.f); | ||
| 374 | luaK_patchlist(ls, v->u.l.t, luaK_getlabel(ls)); | ||
| 375 | v->u.l.t = 0; | ||
| 376 | } | ||
| 377 | |||
| 378 | |||
| 379 | void luaK_goiffalse (LexState *ls, expdesc *v, int keepvalue) { | ||
| 380 | FuncState *fs = ls->fs; | ||
| 381 | Instruction *previous; | ||
| 382 | discharge1(ls, v); | ||
| 383 | previous = &fs->f->code[fs->pc-1]; | ||
| 384 | if (!ISJUMP(GET_OPCODE(*previous))) { | ||
| 385 | OpCode jump = keepvalue ? ONTJMP : IFTJMP; | ||
| 386 | luaK_S(ls, jump, 0, -1); | ||
| 387 | } | ||
| 388 | insert_last(fs, &v->u.l.t); | ||
| 389 | luaK_patchlist(ls, v->u.l.f, luaK_getlabel(ls)); | ||
| 390 | v->u.l.f = 0; | ||
| 391 | } | ||
| 392 | |||
| 393 | |||
| 394 | void luaK_tostack (LexState *ls, expdesc *v, int onlyone) { | ||
| 395 | if (discharge(ls, v)) return; | ||
| 396 | else { /* is an expression */ | ||
| 397 | FuncState *fs = ls->fs; | ||
| 398 | Instruction *previous = &fs->f->code[fs->pc-1]; | ||
| 399 | if (!ISJUMP(GET_OPCODE(*previous)) && v->u.l.f == 0 && v->u.l.t == 0) { | ||
| 400 | /* it is an expression without jumps */ | ||
| 401 | if (onlyone && v->k == VEXP) | ||
| 402 | luaK_setcallreturns(ls, 1); /* call must return 1 value */ | ||
| 403 | return; | ||
| 404 | } | ||
| 405 | else { /* expression has jumps... */ | ||
| 406 | int p_nil = 0; /* position of an eventual PUSHNIL */ | ||
| 407 | int p_1 = 0; /* position of an eventual PUSHINT */ | ||
| 408 | int final; /* position after whole expression */ | ||
| 409 | if (ISJUMP(GET_OPCODE(*previous))) { | ||
| 410 | insert_last(fs, &v->u.l.t); | ||
| 411 | p_nil = luaK_0(ls, PUSHNILJMP, 0); | ||
| 412 | p_1 = luaK_S(ls, PUSHINT, 1, 1); | ||
| 413 | } | ||
| 414 | else { /* still may need a PUSHNIL or a PUSHINT */ | ||
| 415 | int need_nil = has_jumps(fs, v->u.l.f, ONFJMP); /* needs a PUSHNIL? */ | ||
| 416 | int need_1 = has_jumps(fs, v->u.l.t, ONTJMP); /* needs a PUSHINT? */ | ||
| 417 | if (need_nil && need_1) { | ||
| 418 | luaK_S(ls, JMP, 2, 0); | ||
| 419 | p_nil = luaK_0(ls, PUSHNILJMP, 0); | ||
| 420 | p_1 = luaK_S(ls, PUSHINT, 1, 1); | ||
| 421 | } | ||
| 422 | else if (need_nil || need_1) { | ||
| 423 | luaK_S(ls, JMP, 1, 0); | ||
| 424 | if (need_nil) | ||
| 425 | p_nil = luaK_0(ls, PUSHNIL, 1); | ||
| 426 | else /* need_1 */ | ||
| 427 | p_1 = luaK_S(ls, PUSHINT, 1, 1); | ||
| 428 | } | ||
| 429 | } | ||
| 430 | final = luaK_getlabel(ls); | ||
| 431 | luaK_patchlistaux(ls, v->u.l.f, p_nil, ONFJMP, final); | ||
| 432 | luaK_patchlistaux(ls, v->u.l.t, p_1, ONTJMP, final); | ||
| 433 | v->u.l.f = v->u.l.t = 0; | ||
| 434 | } | ||
| 435 | } | ||
| 436 | } | ||
| 437 | |||
| 438 | |||
| 272 | void luaK_prefix (LexState *ls, int op, expdesc *v) { | 439 | void luaK_prefix (LexState *ls, int op, expdesc *v) { |
| 273 | luaK_1tostack(ls, v); | 440 | if (op == '-') { |
| 274 | if (op == '-') luaK_minus(ls); | 441 | luaK_tostack(ls, v, 1); |
| 275 | else luaK_0(ls, NOTOP, 0); | 442 | luaK_minus(ls); |
| 443 | } | ||
| 444 | else { /* op == NOT */ | ||
| 445 | FuncState *fs = ls->fs; | ||
| 446 | Instruction *previous; | ||
| 447 | discharge1(ls, v); | ||
| 448 | previous = &fs->f->code[fs->pc-1]; | ||
| 449 | if (ISJUMP(GET_OPCODE(*previous))) | ||
| 450 | SET_OPCODE(*previous, invertjump(GET_OPCODE(*previous))); | ||
| 451 | else | ||
| 452 | luaK_0(ls, NOTOP, 0); | ||
| 453 | /* interchange true and false lists */ | ||
| 454 | { int temp = v->u.l.f; v->u.l.f = v->u.l.t; v->u.l.t = temp; } | ||
| 455 | } | ||
| 276 | } | 456 | } |
| 277 | 457 | ||
| 278 | 458 | ||
| 279 | void luaK_infix (LexState *ls, int op, expdesc *v) { | 459 | void luaK_infix (LexState *ls, int op, expdesc *v) { |
| 280 | luaK_1tostack(ls, v); | ||
| 281 | if (op == AND) | 460 | if (op == AND) |
| 282 | v->info = luaK_0(ls, ONFJMP, -1); | 461 | luaK_goiftrue(ls, v, 1); |
| 283 | else if (op == OR) | 462 | else if (op == OR) |
| 284 | v->info = luaK_0(ls, ONTJMP, -1); | 463 | luaK_goiffalse(ls, v, 1); |
| 464 | else | ||
| 465 | luaK_tostack(ls, v, 1); | ||
| 285 | } | 466 | } |
| 286 | 467 | ||
| 287 | 468 | ||
| 288 | void luaK_posfix (LexState *ls, int op, expdesc *v1, expdesc *v2) { | 469 | void luaK_posfix (LexState *ls, int op, expdesc *v1, expdesc *v2) { |
| 289 | luaK_1tostack(ls, v2); | 470 | if (op == AND) { |
| 290 | switch (op) { | 471 | LUA_ASSERT(ls->L, v1->u.l.t == 0, "list must be closed"); |
| 291 | case AND: case OR: | 472 | discharge1(ls, v2); |
| 292 | luaK_fixjump(ls, v1->info, luaK_getlabel(ls)); | 473 | v1->u.l.t = v2->u.l.t; |
| 293 | break; | 474 | concatlists(ls, &v1->u.l.f, v2->u.l.f); |
| 294 | case '+': luaK_add(ls); break; | 475 | } |
| 295 | case '-': luaK_sub(ls); break; | 476 | else if (op == OR) { |
| 296 | case '*': luaK_0(ls, MULTOP, -1); break; | 477 | LUA_ASSERT(ls->L, v1->u.l.f == 0, "list must be closed"); |
| 297 | case '/': luaK_0(ls, DIVOP, -1); break; | 478 | discharge1(ls, v2); |
| 298 | case '^': luaK_0(ls, POWOP, -1); break; | 479 | v1->u.l.f = v2->u.l.f; |
| 299 | case CONC: luaK_conc(ls); break; | 480 | concatlists(ls, &v1->u.l.t, v2->u.l.t); |
| 300 | case EQ: luaK_0(ls, EQOP, -1); break; | 481 | } |
| 301 | case NE: luaK_0(ls, NEQOP, -1); break; | 482 | else { |
| 302 | case '>': luaK_0(ls, GTOP, -1); break; | 483 | luaK_tostack(ls, v2, 1); /* `v2' must have a value */ |
| 303 | case '<': luaK_0(ls, LTOP, -1); break; | 484 | switch (op) { |
| 304 | case GE: luaK_0(ls, GEOP, -1); break; | 485 | case '+': luaK_add(ls); break; |
| 305 | case LE: luaK_0(ls, LEOP, -1); break; | 486 | case '-': luaK_sub(ls); break; |
| 487 | case '*': luaK_0(ls, MULTOP, -1); break; | ||
| 488 | case '/': luaK_0(ls, DIVOP, -1); break; | ||
| 489 | case '^': luaK_0(ls, POWOP, -1); break; | ||
| 490 | case CONC: luaK_conc(ls); break; | ||
| 491 | case EQ: luaK_S(ls, IFEQJMP, 0, -2); break; | ||
| 492 | case NE: luaK_S(ls, IFNEQJMP, 0, -2); break; | ||
| 493 | case '>': luaK_S(ls, IFGTJMP, 0, -2); break; | ||
| 494 | case '<': luaK_S(ls, IFLTJMP, 0, -2); break; | ||
| 495 | case GE: luaK_S(ls, IFGEJMP, 0, -2); break; | ||
| 496 | case LE: luaK_S(ls, IFLEJMP, 0, -2); break; | ||
| 497 | } | ||
| 306 | } | 498 | } |
| 307 | } | 499 | } |
| 308 | 500 | ||
| @@ -24,6 +24,9 @@ int luaK_primitivecode (LexState *ls, Instruction i); | |||
| 24 | int luaK_code (LexState *ls, Instruction i, int delta); | 24 | int luaK_code (LexState *ls, Instruction i, int delta); |
| 25 | void luaK_retcode (LexState *ls, int nlocals, int nexps); | 25 | void luaK_retcode (LexState *ls, int nlocals, int nexps); |
| 26 | void luaK_fixjump (LexState *ls, int pc, int dest); | 26 | void luaK_fixjump (LexState *ls, int pc, int dest); |
| 27 | void luaK_patchlist (LexState *ls, int list, int target); | ||
| 28 | void luaK_goiftrue (LexState *ls, expdesc *v, int keepvalue); | ||
| 29 | void luaK_goiffalse (LexState *ls, expdesc *v, int keepvalue); | ||
| 27 | int luaK_getlabel (LexState *ls); | 30 | int luaK_getlabel (LexState *ls); |
| 28 | void luaK_deltastack (LexState *ls, int delta); | 31 | void luaK_deltastack (LexState *ls, int delta); |
| 29 | void luaK_kstr (LexState *ls, int c); | 32 | void luaK_kstr (LexState *ls, int c); |
| @@ -31,8 +34,7 @@ void luaK_number (LexState *ls, real f); | |||
| 31 | void luaK_adjuststack (LexState *ls, int n); | 34 | void luaK_adjuststack (LexState *ls, int n); |
| 32 | int luaK_lastisopen (LexState *ls); | 35 | int luaK_lastisopen (LexState *ls); |
| 33 | void luaK_setcallreturns (LexState *ls, int nresults); | 36 | void luaK_setcallreturns (LexState *ls, int nresults); |
| 34 | void luaK_tostack (LexState *ls, expdesc *var); | 37 | void luaK_tostack (LexState *ls, expdesc *v, int onlyone); |
| 35 | void luaK_1tostack (LexState *ls, expdesc *var); | ||
| 36 | void luaK_storevar (LexState *ls, const expdesc *var); | 38 | void luaK_storevar (LexState *ls, const expdesc *var); |
| 37 | void luaK_prefix (LexState *ls, int op, expdesc *v); | 39 | void luaK_prefix (LexState *ls, int op, expdesc *v); |
| 38 | void luaK_infix (LexState *ls, int op, expdesc *v); | 40 | void luaK_infix (LexState *ls, int op, expdesc *v); |
| @@ -11,7 +11,7 @@ | |||
| 11 | 11 | ||
| 12 | /*=========================================================================== | 12 | /*=========================================================================== |
| 13 | We assume that instructions are unsigned numbers with 4 bytes. | 13 | We assume that instructions are unsigned numbers with 4 bytes. |
| 14 | All instructions have an opcode in the lower byte. Moreover, | 14 | All instructions have an opcode in the 8 bits. Moreover, |
| 15 | an instruction can have 0, 1, or 2 arguments. There are 4 types of | 15 | an instruction can have 0, 1, or 2 arguments. There are 4 types of |
| 16 | Instructions: | 16 | Instructions: |
| 17 | type 0: no arguments | 17 | type 0: no arguments |
| @@ -24,21 +24,23 @@ | |||
| 24 | is the usigned value minus 2^23. | 24 | is the usigned value minus 2^23. |
| 25 | ===========================================================================*/ | 25 | ===========================================================================*/ |
| 26 | 26 | ||
| 27 | #define SIZE_INSTRUCTION 32 | ||
| 28 | |||
| 27 | #define SIZE_OP 8 | 29 | #define SIZE_OP 8 |
| 28 | #define SIZE_U 24 | 30 | #define SIZE_U (SIZE_INSTRUCTION-SIZE_OP) |
| 29 | #define POS_U 8 | 31 | #define POS_U SIZE_OP |
| 30 | #define SIZE_S 24 | 32 | #define SIZE_S (SIZE_INSTRUCTION-SIZE_OP) |
| 31 | #define POS_S 8 | 33 | #define POS_S SIZE_OP |
| 32 | #define SIZE_A 16 | ||
| 33 | #define POS_A 16 | ||
| 34 | #define SIZE_B 8 | 34 | #define SIZE_B 8 |
| 35 | #define POS_B 8 | 35 | #define POS_B SIZE_OP |
| 36 | #define SIZE_A (SIZE_INSTRUCTION-(SIZE_OP+SIZE_B)) | ||
| 37 | #define POS_A (SIZE_OP+SIZE_B) | ||
| 36 | 38 | ||
| 37 | #define EXCESS_S (1<<(SIZE_S-1)) /* == 2^23 */ | 39 | #define EXCESS_S (1<<(SIZE_S-1)) /* == 2^23 */ |
| 38 | 40 | ||
| 39 | 41 | ||
| 40 | /* creates a mask with `n' 1 bits at position `p' */ | 42 | /* creates a mask with `n' 1 bits at position `p' */ |
| 41 | #define MASK1(n,p) ((~((~0ul)<<n))<<p) | 43 | #define MASK1(n,p) ((~((~(Instruction)0)<<n))<<p) |
| 42 | 44 | ||
| 43 | /* creates a mask with `n' 0 bits at position `p' */ | 45 | /* creates a mask with `n' 0 bits at position `p' */ |
| 44 | #define MASK0(n,p) (~MASK1(n,p)) | 46 | #define MASK0(n,p) (~MASK1(n,p)) |
| @@ -58,11 +60,15 @@ | |||
| 58 | #define GETARG_A(i) ((int)((i)>>POS_A)) | 60 | #define GETARG_A(i) ((int)((i)>>POS_A)) |
| 59 | #define GETARG_B(i) ((int)(((i)>>POS_B) & MASK1(SIZE_B,0))) | 61 | #define GETARG_B(i) ((int)(((i)>>POS_B) & MASK1(SIZE_B,0))) |
| 60 | 62 | ||
| 61 | #define SET_OPCODE(i,o) (((i)&MASK0(SIZE_OP,0)) | (Instruction)(o)) | 63 | #define SET_OPCODE(i,o) ((i) = (((i)&MASK0(SIZE_OP,0)) | (Instruction)(o))) |
| 62 | #define SETARG_U(i,u) (((i)&MASK0(SIZE_U,POS_U)) | ((Instruction)(u)<<POS_U)) | 64 | #define SETARG_U(i,u) ((i) = (((i)&MASK0(SIZE_U,POS_U)) | \ |
| 63 | #define SETARG_S(i,s) (((i)&MASK0(SIZE_S,POS_S)) | ((Instruction)((s)+EXCESS_S)<<POS_S)) | 65 | ((Instruction)(u)<<POS_U))) |
| 64 | #define SETARG_A(i,a) (((i)&MASK0(SIZE_A,POS_A)) | ((Instruction)(a)<<POS_A)) | 66 | #define SETARG_S(i,s) ((i) = (((i)&MASK0(SIZE_S,POS_S)) | \ |
| 65 | #define SETARG_B(i,b) (((i)&MASK0(SIZE_B,POS_B)) | ((Instruction)(b)<<POS_B)) | 67 | ((Instruction)((s)+EXCESS_S)<<POS_S))) |
| 68 | #define SETARG_A(i,a) ((i) = (((i)&MASK0(SIZE_A,POS_A)) | \ | ||
| 69 | ((Instruction)(a)<<POS_A))) | ||
| 70 | #define SETARG_B(i,b) ((i) = (((i)&MASK0(SIZE_B,POS_B)) | \ | ||
| 71 | ((Instruction)(b)<<POS_B))) | ||
| 66 | 72 | ||
| 67 | #define CREATE_0(o) ((Instruction)(o)) | 73 | #define CREATE_0(o) ((Instruction)(o)) |
| 68 | #define CREATE_U(o,u) ((Instruction)(o) | (Instruction)(u)<<POS_U) | 74 | #define CREATE_U(o,u) ((Instruction)(o) | (Instruction)(u)<<POS_U) |
| @@ -115,13 +121,6 @@ SETTABLE,/* U v a_u-a_1 i t a_u-a_1 i t t[i]=v */ | |||
| 115 | SETLIST,/* A B v_b-v_0 t t t[i+a*FPF]=v_i */ | 121 | SETLIST,/* A B v_b-v_0 t t t[i+a*FPF]=v_i */ |
| 116 | SETMAP,/* U v_u k_u - v_0 k_0 t t t[k_i]=v_i */ | 122 | SETMAP,/* U v_u k_u - v_0 k_0 t t t[k_i]=v_i */ |
| 117 | 123 | ||
| 118 | NEQOP,/* - y x (x~=y)? 1 : nil */ | ||
| 119 | EQOP,/* - y x (x==y)? 1 : nil */ | ||
| 120 | LTOP,/* - y x (x<y)? 1 : nil */ | ||
| 121 | LEOP,/* - y x (x<y)? 1 : nil */ | ||
| 122 | GTOP,/* - y x (x>y)? 1 : nil */ | ||
| 123 | GEOP,/* - y x (x>=y)? 1 : nil */ | ||
| 124 | |||
| 125 | ADDOP,/* - y x x+y */ | 124 | ADDOP,/* - y x x+y */ |
| 126 | ADDI,/* S x x+s */ | 125 | ADDI,/* S x x+s */ |
| 127 | SUBOP,/* - y x x-y */ | 126 | SUBOP,/* - y x x-y */ |
| @@ -132,19 +131,32 @@ CONCOP,/* U v_u-v_1 v1..-..v_u */ | |||
| 132 | MINUSOP,/* - x -x */ | 131 | MINUSOP,/* - x -x */ |
| 133 | NOTOP,/* - x (x==nil)? 1 : nil */ | 132 | NOTOP,/* - x (x==nil)? 1 : nil */ |
| 134 | 133 | ||
| 134 | IFNEQJMP,/* J y x - (x~=y)? PC+=s */ | ||
| 135 | IFEQJMP,/* J y x - (x==y)? PC+=s */ | ||
| 136 | IFLTJMP,/* J y x - (x<y)? PC+=s */ | ||
| 137 | IFLEJMP,/* J y x - (x<y)? PC+=s */ | ||
| 138 | IFGTJMP,/* J y x - (x>y)? PC+=s */ | ||
| 139 | IFGEJMP,/* J y x - (x>=y)? PC+=s */ | ||
| 140 | |||
| 141 | IFTJMP,/* J x - (x!=nil)? PC+=s */ | ||
| 142 | IFFJMP,/* J x - (x==nil)? PC+=s */ | ||
| 135 | ONTJMP,/* J x (x!=nil)? x : - (x!=nil)? PC+=s */ | 143 | ONTJMP,/* J x (x!=nil)? x : - (x!=nil)? PC+=s */ |
| 136 | ONFJMP,/* J x (x==nil)? x : - (x==nil)? PC+=s */ | 144 | ONFJMP,/* J x (x==nil)? x : - (x==nil)? PC+=s */ |
| 137 | JMP,/* J - - PC+=s */ | 145 | JMP,/* J - - PC+=s */ |
| 138 | IFTJMP,/* J x - (x!=nil)? PC+=s */ | ||
| 139 | IFFJMP,/* J x - (x==nil)? PC+=s */ | ||
| 140 | 146 | ||
| 141 | CLOSURE,/* A B v_b-v_1 closure(CNST[a], v_b-v_1) */ | 147 | PUSHNILJMP,/* - - nil PC++; */ |
| 148 | |||
| 149 | CLOSURE,/* A B v_b-v_1 closure(CNST[a], v_1-v_b) */ | ||
| 142 | 150 | ||
| 143 | SETLINE/* U - - LINE=u */ | 151 | SETLINE/* U - - LINE=u */ |
| 144 | 152 | ||
| 145 | } OpCode; | 153 | } OpCode; |
| 146 | 154 | ||
| 147 | 155 | ||
| 156 | |||
| 157 | #define ISJUMP(o) (IFNEQJMP <= (o) && (o) <= JMP) | ||
| 158 | |||
| 159 | |||
| 148 | #define RFIELDS_PER_FLUSH 32 /* records (SETMAP) */ | 160 | #define RFIELDS_PER_FLUSH 32 /* records (SETMAP) */ |
| 149 | #define LFIELDS_PER_FLUSH 64 /* FPF - lists (SETLIST) (<=MAXARG_B) */ | 161 | #define LFIELDS_PER_FLUSH 64 /* FPF - lists (SETLIST) (<=MAXARG_B) */ |
| 150 | 162 | ||
| @@ -218,7 +218,7 @@ static void singlevar (LexState *ls, TaggedString *n, expdesc *var, int prev) { | |||
| 218 | int i = aux_localname(fs, n); | 218 | int i = aux_localname(fs, n); |
| 219 | if (i >= 0) { /* local value? */ | 219 | if (i >= 0) { /* local value? */ |
| 220 | var->k = VLOCAL; | 220 | var->k = VLOCAL; |
| 221 | var->info = i; | 221 | var->u.index = i; |
| 222 | } | 222 | } |
| 223 | else { | 223 | else { |
| 224 | FuncState *level = fs; | 224 | FuncState *level = fs; |
| @@ -226,7 +226,7 @@ static void singlevar (LexState *ls, TaggedString *n, expdesc *var, int prev) { | |||
| 226 | if (aux_localname(level, n) >= 0) | 226 | if (aux_localname(level, n) >= 0) |
| 227 | luaX_syntaxerror(ls, "cannot access a variable in outer scope", n->str); | 227 | luaX_syntaxerror(ls, "cannot access a variable in outer scope", n->str); |
| 228 | var->k = VGLOBAL; | 228 | var->k = VGLOBAL; |
| 229 | var->info = string_constant(ls, fs, n); | 229 | var->u.index = string_constant(ls, fs, n); |
| 230 | } | 230 | } |
| 231 | } | 231 | } |
| 232 | 232 | ||
| @@ -237,7 +237,7 @@ static int indexupvalue (LexState *ls, TaggedString *n) { | |||
| 237 | int i; | 237 | int i; |
| 238 | singlevar(ls, n, &v, 1); | 238 | singlevar(ls, n, &v, 1); |
| 239 | for (i=0; i<fs->nupvalues; i++) { | 239 | for (i=0; i<fs->nupvalues; i++) { |
| 240 | if (fs->upvalues[i].k == v.k && fs->upvalues[i].info == v.info) | 240 | if (fs->upvalues[i].k == v.k && fs->upvalues[i].u.index == v.u.index) |
| 241 | return i; | 241 | return i; |
| 242 | } | 242 | } |
| 243 | /* new one */ | 243 | /* new one */ |
| @@ -296,9 +296,9 @@ static void code_args (LexState *ls, int nparams, int dots) { | |||
| 296 | static int getvarname (LexState *ls, expdesc *var) { | 296 | static int getvarname (LexState *ls, expdesc *var) { |
| 297 | switch (var->k) { | 297 | switch (var->k) { |
| 298 | case VGLOBAL: | 298 | case VGLOBAL: |
| 299 | return var->info; | 299 | return var->u.index; |
| 300 | case VLOCAL: | 300 | case VLOCAL: |
| 301 | return string_constant(ls, ls->fs, ls->fs->localvar[var->info]); | 301 | return string_constant(ls, ls->fs, ls->fs->localvar[var->u.index]); |
| 302 | break; | 302 | break; |
| 303 | default: | 303 | default: |
| 304 | error_unexpected(ls); /* there is no `var name' */ | 304 | error_unexpected(ls); /* there is no `var name' */ |
| @@ -311,7 +311,7 @@ static void func_onstack (LexState *ls, FuncState *func) { | |||
| 311 | TProtoFunc *f = ls->fs->f; | 311 | TProtoFunc *f = ls->fs->f; |
| 312 | int i; | 312 | int i; |
| 313 | for (i=0; i<func->nupvalues; i++) | 313 | for (i=0; i<func->nupvalues; i++) |
| 314 | luaK_1tostack(ls, &func->upvalues[i]); | 314 | luaK_tostack(ls, &func->upvalues[i], 1); |
| 315 | luaM_growvector(ls->L, f->kproto, f->nkproto, 1, TProtoFunc *, | 315 | luaM_growvector(ls->L, f->kproto, f->nkproto, 1, TProtoFunc *, |
| 316 | constantEM, MAXARG_A); | 316 | constantEM, MAXARG_A); |
| 317 | f->kproto[f->nkproto++] = func->f; | 317 | f->kproto[f->nkproto++] = func->f; |
| @@ -388,12 +388,12 @@ static int explist1 (LexState *ls) { | |||
| 388 | expdesc v; | 388 | expdesc v; |
| 389 | expr(ls, &v); | 389 | expr(ls, &v); |
| 390 | while (ls->token == ',') { | 390 | while (ls->token == ',') { |
| 391 | luaK_1tostack(ls, &v); /* gets only 1 value from previous expression */ | 391 | luaK_tostack(ls, &v, 1); /* gets only 1 value from previous expression */ |
| 392 | next(ls); /* skip comma */ | 392 | next(ls); /* skip comma */ |
| 393 | expr(ls, &v); | 393 | expr(ls, &v); |
| 394 | n++; | 394 | n++; |
| 395 | } | 395 | } |
| 396 | luaK_tostack(ls, &v); | 396 | luaK_tostack(ls, &v, 0); |
| 397 | return n; | 397 | return n; |
| 398 | } | 398 | } |
| 399 | 399 | ||
| @@ -451,14 +451,14 @@ static void var_or_func_tail (LexState *ls, expdesc *v) { | |||
| 451 | switch (ls->token) { | 451 | switch (ls->token) { |
| 452 | case '.': /* var_or_func_tail -> '.' NAME */ | 452 | case '.': /* var_or_func_tail -> '.' NAME */ |
| 453 | next(ls); | 453 | next(ls); |
| 454 | luaK_1tostack(ls, v); /* `v' must be on stack */ | 454 | luaK_tostack(ls, v, 1); /* `v' must be on stack */ |
| 455 | luaK_kstr(ls, checkname(ls)); | 455 | luaK_kstr(ls, checkname(ls)); |
| 456 | v->k = VINDEXED; | 456 | v->k = VINDEXED; |
| 457 | break; | 457 | break; |
| 458 | 458 | ||
| 459 | case '[': /* var_or_func_tail -> '[' exp1 ']' */ | 459 | case '[': /* var_or_func_tail -> '[' exp1 ']' */ |
| 460 | next(ls); | 460 | next(ls); |
| 461 | luaK_1tostack(ls, v); /* `v' must be on stack */ | 461 | luaK_tostack(ls, v, 1); /* `v' must be on stack */ |
| 462 | v->k = VINDEXED; | 462 | v->k = VINDEXED; |
| 463 | exp1(ls); | 463 | exp1(ls); |
| 464 | check(ls, ']'); | 464 | check(ls, ']'); |
| @@ -468,17 +468,19 @@ static void var_or_func_tail (LexState *ls, expdesc *v) { | |||
| 468 | int name; | 468 | int name; |
| 469 | next(ls); | 469 | next(ls); |
| 470 | name = checkname(ls); | 470 | name = checkname(ls); |
| 471 | luaK_1tostack(ls, v); /* `v' must be on stack */ | 471 | luaK_tostack(ls, v, 1); /* `v' must be on stack */ |
| 472 | luaK_U(ls, PUSHSELF, name, 1); | 472 | luaK_U(ls, PUSHSELF, name, 1); |
| 473 | funcargs(ls, 1); | 473 | funcargs(ls, 1); |
| 474 | v->k = VEXP; | 474 | v->k = VEXP; |
| 475 | v->u.l.t = v->u.l.f = 0; | ||
| 475 | break; | 476 | break; |
| 476 | } | 477 | } |
| 477 | 478 | ||
| 478 | case '(': case STRING: case '{': /* var_or_func_tail -> funcargs */ | 479 | case '(': case STRING: case '{': /* var_or_func_tail -> funcargs */ |
| 479 | luaK_1tostack(ls, v); /* `v' must be on stack */ | 480 | luaK_tostack(ls, v, 1); /* `v' must be on stack */ |
| 480 | funcargs(ls, 0); | 481 | funcargs(ls, 0); |
| 481 | v->k = VEXP; | 482 | v->k = VEXP; |
| 483 | v->u.l.t = v->u.l.f = 0; | ||
| 482 | break; | 484 | break; |
| 483 | 485 | ||
| 484 | default: return; /* should be follow... */ | 486 | default: return; /* should be follow... */ |
| @@ -492,6 +494,7 @@ static void var_or_func (LexState *ls, expdesc *v) { | |||
| 492 | if (optional(ls, '%')) { /* upvalue? */ | 494 | if (optional(ls, '%')) { /* upvalue? */ |
| 493 | pushupvalue(ls, str_checkname(ls)); | 495 | pushupvalue(ls, str_checkname(ls)); |
| 494 | v->k = VEXP; | 496 | v->k = VEXP; |
| 497 | v->u.l.t = v->u.l.f = 0; | ||
| 495 | } | 498 | } |
| 496 | else /* variable name */ | 499 | else /* variable name */ |
| 497 | singlevar(ls, str_checkname(ls), v, 0); | 500 | singlevar(ls, str_checkname(ls), v, 0); |
| @@ -591,7 +594,7 @@ static void constructor_part (LexState *ls, constdesc *cd) { | |||
| 591 | cd->k = 1; /* record */ | 594 | cd->k = 1; /* record */ |
| 592 | } | 595 | } |
| 593 | else { | 596 | else { |
| 594 | luaK_tostack(ls, &v); | 597 | luaK_tostack(ls, &v, 0); |
| 595 | cd->n = listfields(ls); | 598 | cd->n = listfields(ls); |
| 596 | cd->k = 0; /* list */ | 599 | cd->k = 0; /* list */ |
| 597 | } | 600 | } |
| @@ -632,7 +635,7 @@ static void constructor (LexState *ls) { | |||
| 632 | } | 635 | } |
| 633 | check_match(ls, '}', '{', line); | 636 | check_match(ls, '}', '{', line); |
| 634 | /* set initial table size */ | 637 | /* set initial table size */ |
| 635 | ls->fs->f->code[pc] = SETARG_U(ls->fs->f->code[pc], nelems); | 638 | SETARG_U(ls->fs->f->code[pc], nelems); |
| 636 | } | 639 | } |
| 637 | 640 | ||
| 638 | /* }====================================================================== */ | 641 | /* }====================================================================== */ |
| @@ -691,13 +694,14 @@ static void simpleexp (LexState *ls, expdesc *v) { | |||
| 691 | return; | 694 | return; |
| 692 | } | 695 | } |
| 693 | v->k = VEXP; | 696 | v->k = VEXP; |
| 697 | v->u.l.t = v->u.l.f = 0; | ||
| 694 | } | 698 | } |
| 695 | 699 | ||
| 696 | 700 | ||
| 697 | static void exp1 (LexState *ls) { | 701 | static void exp1 (LexState *ls) { |
| 698 | expdesc v; | 702 | expdesc v; |
| 699 | expr(ls, &v); | 703 | expr(ls, &v); |
| 700 | luaK_1tostack(ls, &v); | 704 | luaK_tostack(ls, &v, 1); |
| 701 | } | 705 | } |
| 702 | 706 | ||
| 703 | 707 | ||
| @@ -820,10 +824,13 @@ static void whilestat (LexState *ls, int line) { | |||
| 820 | FuncState *fs = ls->fs; | 824 | FuncState *fs = ls->fs; |
| 821 | int while_init = luaK_getlabel(ls); | 825 | int while_init = luaK_getlabel(ls); |
| 822 | int loopentry; /* point to jump to repeat the loop */ | 826 | int loopentry; /* point to jump to repeat the loop */ |
| 827 | int cond_init; /* init of condition, after the move */ | ||
| 823 | int cond_size; | 828 | int cond_size; |
| 829 | expdesc v; | ||
| 824 | int i; | 830 | int i; |
| 825 | next(ls); /* skip WHILE */ | 831 | next(ls); /* skip WHILE */ |
| 826 | exp1(ls); /* read condition */ | 832 | expr(ls, &v); /* read condition */ |
| 833 | luaK_goiffalse(ls, &v, 0); | ||
| 827 | cond_size = fs->pc - while_init; | 834 | cond_size = fs->pc - while_init; |
| 828 | /* save condition (to move it to after body) */ | 835 | /* save condition (to move it to after body) */ |
| 829 | if (cond_size > MAX_WHILE_EXP) | 836 | if (cond_size > MAX_WHILE_EXP) |
| @@ -831,28 +838,31 @@ static void whilestat (LexState *ls, int line) { | |||
| 831 | for (i=0; i<cond_size; i++) buffer[i] = fs->f->code[while_init+i]; | 838 | for (i=0; i<cond_size; i++) buffer[i] = fs->f->code[while_init+i]; |
| 832 | /* go back to state prior condition */ | 839 | /* go back to state prior condition */ |
| 833 | fs->pc = while_init; | 840 | fs->pc = while_init; |
| 834 | luaK_deltastack(ls, -1); | ||
| 835 | luaK_S(ls, JMP, 0, 0); /* initial jump to condition */ | 841 | luaK_S(ls, JMP, 0, 0); /* initial jump to condition */ |
| 836 | check(ls, DO); | 842 | check(ls, DO); |
| 837 | loopentry = luaK_getlabel(ls); | 843 | loopentry = luaK_getlabel(ls); |
| 838 | block(ls); | 844 | block(ls); |
| 839 | check_match(ls, END, WHILE, line); | 845 | check_match(ls, END, WHILE, line); |
| 840 | luaK_fixjump(ls, while_init, luaK_getlabel(ls)); | 846 | cond_init = luaK_getlabel(ls); |
| 841 | /* copy condition to new position, and correct stack */ | 847 | luaK_fixjump(ls, while_init, cond_init); |
| 848 | /* correct `v' and copy condition to new position */ | ||
| 849 | if (v.u.l.t != 0) v.u.l.t += cond_init-while_init; | ||
| 842 | for (i=0; i<cond_size; i++) luaK_primitivecode(ls, buffer[i]); | 850 | for (i=0; i<cond_size; i++) luaK_primitivecode(ls, buffer[i]); |
| 843 | luaK_deltastack(ls, 1); | 851 | luaK_patchlist(ls, v.u.l.t, loopentry); |
| 844 | luaK_fixjump(ls, luaK_S(ls, IFTJMP, 0, -1), loopentry); | 852 | luaK_getlabel(ls); /* mark possible jump to this point */ |
| 845 | } | 853 | } |
| 846 | 854 | ||
| 847 | 855 | ||
| 848 | static void repeatstat (LexState *ls, int line) { | 856 | static void repeatstat (LexState *ls, int line) { |
| 849 | /* repeatstat -> REPEAT block UNTIL exp1 */ | 857 | /* repeatstat -> REPEAT block UNTIL exp1 */ |
| 850 | int repeat_init = luaK_getlabel(ls); | 858 | int repeat_init = luaK_getlabel(ls); |
| 859 | expdesc v; | ||
| 851 | next(ls); | 860 | next(ls); |
| 852 | block(ls); | 861 | block(ls); |
| 853 | check_match(ls, UNTIL, REPEAT, line); | 862 | check_match(ls, UNTIL, REPEAT, line); |
| 854 | exp1(ls); | 863 | expr(ls, &v); |
| 855 | luaK_fixjump(ls, luaK_S(ls, IFFJMP, 0, -1), repeat_init); | 864 | luaK_goiftrue(ls, &v, 0); |
| 865 | luaK_patchlist(ls, v.u.l.f, repeat_init); | ||
| 856 | } | 866 | } |
| 857 | 867 | ||
| 858 | 868 | ||
| @@ -900,7 +910,7 @@ static int funcname (LexState *ls, expdesc *v) { | |||
| 900 | if (ls->token == ':' || ls->token == '.') { | 910 | if (ls->token == ':' || ls->token == '.') { |
| 901 | needself = (ls->token == ':'); | 911 | needself = (ls->token == ':'); |
| 902 | next(ls); | 912 | next(ls); |
| 903 | luaK_1tostack(ls, v); | 913 | luaK_tostack(ls, v, 1); |
| 904 | luaK_kstr(ls, checkname(ls)); | 914 | luaK_kstr(ls, checkname(ls)); |
| 905 | v->k = VINDEXED; | 915 | v->k = VINDEXED; |
| 906 | } | 916 | } |
| @@ -943,11 +953,11 @@ static void namestat (LexState *ls) { | |||
| 943 | static void ifpart (LexState *ls, int line) { | 953 | static void ifpart (LexState *ls, int line) { |
| 944 | /* ifpart -> cond THEN block (ELSEIF ifpart | [ELSE block] END) */ | 954 | /* ifpart -> cond THEN block (ELSEIF ifpart | [ELSE block] END) */ |
| 945 | FuncState *fs = ls->fs; | 955 | FuncState *fs = ls->fs; |
| 946 | int c; /* address of the conditional jump */ | 956 | expdesc v; |
| 947 | int elseinit; | 957 | int elseinit; |
| 948 | next(ls); /* skip IF or ELSEIF */ | 958 | next(ls); /* skip IF or ELSEIF */ |
| 949 | exp1(ls); /* cond */ | 959 | expr(ls, &v); /* cond */ |
| 950 | c = luaK_S(ls, IFFJMP, 0, -1); /* 1st jump: over `then' part */ | 960 | luaK_goiftrue(ls, &v, 0); |
| 951 | check(ls, THEN); | 961 | check(ls, THEN); |
| 952 | block(ls); /* `then' part */ | 962 | block(ls); /* `then' part */ |
| 953 | luaK_S(ls, JMP, 0, 0); /* 2nd jump: over `else' part */ | 963 | luaK_S(ls, JMP, 0, 0); /* 2nd jump: over `else' part */ |
| @@ -960,13 +970,13 @@ static void ifpart (LexState *ls, int line) { | |||
| 960 | check_match(ls, END, IF, line); | 970 | check_match(ls, END, IF, line); |
| 961 | } | 971 | } |
| 962 | if (fs->pc > elseinit) { /* is there an `else' part? */ | 972 | if (fs->pc > elseinit) { /* is there an `else' part? */ |
| 963 | luaK_fixjump(ls, c, elseinit); /* fix 1st jump to `else' part */ | ||
| 964 | luaK_fixjump(ls, elseinit-1, luaK_getlabel(ls)); /* fix 2nd jump */ | 973 | luaK_fixjump(ls, elseinit-1, luaK_getlabel(ls)); /* fix 2nd jump */ |
| 965 | } | 974 | } |
| 966 | else { /* no else part */ | 975 | else { /* no else part */ |
| 967 | fs->pc--; /* remove 2nd jump */ | 976 | fs->pc--; /* remove 2nd jump */ |
| 968 | luaK_fixjump(ls, c, luaK_getlabel(ls)); /* fix 1st jump to `if' end */ | 977 | elseinit = luaK_getlabel(ls); /* `elseinit' points to end */ |
| 969 | } | 978 | } |
| 979 | luaK_patchlist(ls, v.u.l.f, elseinit); /* fix 1st jump to `else' part */ | ||
| 970 | } | 980 | } |
| 971 | 981 | ||
| 972 | 982 | ||
| @@ -47,15 +47,21 @@ | |||
| 47 | */ | 47 | */ |
| 48 | 48 | ||
| 49 | typedef enum { | 49 | typedef enum { |
| 50 | VGLOBAL, /* info is constant index of global name */ | 50 | VGLOBAL, |
| 51 | VLOCAL, /* info is stack index */ | 51 | VLOCAL, |
| 52 | VINDEXED, | 52 | VINDEXED, |
| 53 | VEXP /* info is jump target if exp has internal jumps */ | 53 | VEXP |
| 54 | } expkind; | 54 | } expkind; |
| 55 | 55 | ||
| 56 | typedef struct expdesc { | 56 | typedef struct expdesc { |
| 57 | expkind k; | 57 | expkind k; |
| 58 | int info; | 58 | union { |
| 59 | int index; /* VGLOBAL: `kstr' index of global name; VLOCAL: stack index */ | ||
| 60 | struct { | ||
| 61 | int t; /* patch list of `exit when true' */ | ||
| 62 | int f; /* patch list of `exit when false' */ | ||
| 63 | } l; | ||
| 64 | } u; | ||
| 59 | } expdesc; | 65 | } expdesc; |
| 60 | 66 | ||
| 61 | 67 | ||
| @@ -478,36 +478,6 @@ StkId luaV_execute (lua_State *L, const Closure *cl, const TProtoFunc *tf, | |||
| 478 | break; | 478 | break; |
| 479 | } | 479 | } |
| 480 | 480 | ||
| 481 | case NEQOP: | ||
| 482 | top--; | ||
| 483 | setbool(top-1, !luaO_equalObj(top-1, top)); | ||
| 484 | break; | ||
| 485 | |||
| 486 | case EQOP: | ||
| 487 | top--; | ||
| 488 | setbool(top-1, luaO_equalObj(top-1, top)); | ||
| 489 | break; | ||
| 490 | |||
| 491 | case LTOP: | ||
| 492 | top--; | ||
| 493 | setbool(top-1, luaV_lessthan(L, top-1, top, top+1)); | ||
| 494 | break; | ||
| 495 | |||
| 496 | case LEOP: /* a <= b === !(b<a) */ | ||
| 497 | top--; | ||
| 498 | setbool(top-1, !luaV_lessthan(L, top, top-1, top+1)); | ||
| 499 | break; | ||
| 500 | |||
| 501 | case GTOP: /* a > b === (b<a) */ | ||
| 502 | top--; | ||
| 503 | setbool(top-1, luaV_lessthan(L, top, top-1, top+1)); | ||
| 504 | break; | ||
| 505 | |||
| 506 | case GEOP: /* a >= b === !(a<b) */ | ||
| 507 | top--; | ||
| 508 | setbool(top-1, !luaV_lessthan(L, top-1, top, top+1)); | ||
| 509 | break; | ||
| 510 | |||
| 511 | case ADDOP: | 481 | case ADDOP: |
| 512 | if (tonumber(top-1) || tonumber(top-2)) | 482 | if (tonumber(top-1) || tonumber(top-2)) |
| 513 | call_arith(L, top, IM_ADD); | 483 | call_arith(L, top, IM_ADD); |
| @@ -579,6 +549,44 @@ StkId luaV_execute (lua_State *L, const Closure *cl, const TProtoFunc *tf, | |||
| 579 | nvalue(top-1) = 1; | 549 | nvalue(top-1) = 1; |
| 580 | break; | 550 | break; |
| 581 | 551 | ||
| 552 | case IFNEQJMP: | ||
| 553 | top -= 2; | ||
| 554 | if (!luaO_equalObj(top, top+1)) pc += GETARG_S(i); | ||
| 555 | break; | ||
| 556 | |||
| 557 | case IFEQJMP: | ||
| 558 | top -= 2; | ||
| 559 | if (luaO_equalObj(top, top+1)) pc += GETARG_S(i); | ||
| 560 | break; | ||
| 561 | |||
| 562 | case IFLTJMP: | ||
| 563 | top -= 2; | ||
| 564 | if (luaV_lessthan(L, top, top+1, top+2)) pc += GETARG_S(i); | ||
| 565 | break; | ||
| 566 | |||
| 567 | case IFLEJMP: /* a <= b === !(b<a) */ | ||
| 568 | top -= 2; | ||
| 569 | if (!luaV_lessthan(L, top+1, top, top+2)) pc += GETARG_S(i); | ||
| 570 | break; | ||
| 571 | |||
| 572 | case IFGTJMP: /* a > b === (b<a) */ | ||
| 573 | top -= 2; | ||
| 574 | if (luaV_lessthan(L, top+1, top, top+2)) pc += GETARG_S(i); | ||
| 575 | break; | ||
| 576 | |||
| 577 | case IFGEJMP: /* a >= b === !(a<b) */ | ||
| 578 | top -= 2; | ||
| 579 | if (!luaV_lessthan(L, top, top+1, top+2)) pc += GETARG_S(i); | ||
| 580 | break; | ||
| 581 | |||
| 582 | case IFTJMP: | ||
| 583 | if (ttype(--top) != LUA_T_NIL) pc += GETARG_S(i); | ||
| 584 | break; | ||
| 585 | |||
| 586 | case IFFJMP: | ||
| 587 | if (ttype(--top) == LUA_T_NIL) pc += GETARG_S(i); | ||
| 588 | break; | ||
| 589 | |||
| 582 | case ONTJMP: | 590 | case ONTJMP: |
| 583 | if (ttype(top-1) != LUA_T_NIL) pc += GETARG_S(i); | 591 | if (ttype(top-1) != LUA_T_NIL) pc += GETARG_S(i); |
| 584 | else top--; | 592 | else top--; |
| @@ -593,12 +601,9 @@ StkId luaV_execute (lua_State *L, const Closure *cl, const TProtoFunc *tf, | |||
| 593 | pc += GETARG_S(i); | 601 | pc += GETARG_S(i); |
| 594 | break; | 602 | break; |
| 595 | 603 | ||
| 596 | case IFTJMP: | 604 | case PUSHNILJMP: |
| 597 | if (ttype(--top) != LUA_T_NIL) pc += GETARG_S(i); | 605 | ttype(top++) = LUA_T_NIL; |
| 598 | break; | 606 | pc++; |
| 599 | |||
| 600 | case IFFJMP: | ||
| 601 | if (ttype(--top) == LUA_T_NIL) pc += GETARG_S(i); | ||
| 602 | break; | 607 | break; |
| 603 | 608 | ||
| 604 | case CLOSURE: | 609 | case CLOSURE: |
