** check whether, in an assignment to an upvalue/local variable, the ** upvalue/local variable is begin used in a previous assignment to a ** table. If so, save original upvalue/local value in a safe place and ** use this safe copy in the previous assignment. */
| 1443 | ** use this safe copy in the previous assignment. |
| 1444 | */ |
| 1445 | static void check_conflict (LexState *ls, struct LHS_assign *lh, expdesc *v) { |
| 1446 | FuncState *fs = ls->fs; |
| 1447 | lu_byte extra = fs->freereg; /* eventual position to save local variable */ |
| 1448 | int conflict = 0; |
| 1449 | for (; lh; lh = lh->prev) { /* check all previous assignments */ |
| 1450 | if (vkisindexed(lh->v.k)) { /* assignment to table field? */ |
| 1451 | if (lh->v.k == VINDEXUP) { /* is table an upvalue? */ |
| 1452 | if (v->k == VUPVAL && lh->v.u.ind.t == v->u.info) { |
| 1453 | conflict = 1; /* table is the upvalue being assigned now */ |
| 1454 | lh->v.k = VINDEXSTR; |
| 1455 | lh->v.u.ind.t = extra; /* assignment will use safe copy */ |
| 1456 | } |
| 1457 | } |
| 1458 | else { /* table is a register */ |
| 1459 | if (v->k == VLOCAL && lh->v.u.ind.t == v->u.var.ridx) { |
| 1460 | conflict = 1; /* table is the local being assigned now */ |
| 1461 | lh->v.u.ind.t = extra; /* assignment will use safe copy */ |
| 1462 | } |
| 1463 | /* is index the local being assigned? */ |
| 1464 | if (lh->v.k == VINDEXED && v->k == VLOCAL && |
| 1465 | lh->v.u.ind.idx == v->u.var.ridx) { |
| 1466 | conflict = 1; |
| 1467 | lh->v.u.ind.idx = extra; /* previous assignment will use safe copy */ |
| 1468 | } |
| 1469 | } |
| 1470 | } |
| 1471 | } |
| 1472 | if (conflict) { |
| 1473 | /* copy upvalue/local value to a temporary (in position 'extra') */ |
| 1474 | if (v->k == VLOCAL) |
| 1475 | luaK_codeABC(fs, OP_MOVE, extra, v->u.var.ridx, 0); |
| 1476 | else |
| 1477 | luaK_codeABC(fs, OP_GETUPVAL, extra, v->u.info, 0); |
| 1478 | luaK_reserveregs(fs, 1); |
| 1479 | } |
| 1480 | } |
| 1481 | |
| 1482 | |
| 1483 | /* Create code to store the "top" register in 'var' */ |
no test coverage detected