Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/ceguilua/src/lua/lcode.c @ 2236

Last change on this file since 2236 was 1806, checked in by rgrieder, 16 years ago

added single 5.1.3 directory for lua since CEGUILua 0.5 can also build against lua 5.1

  • Property svn:eol-style set to native
File size: 20.8 KB
RevLine 
[1806]1/*
2** $Id: lcode.c,v 2.25.1.3 2007/12/28 15:32:23 roberto Exp $
3** Code generator for Lua
4** See Copyright Notice in lua.h
5*/
6
7
8#include <stdlib.h>
9
10#define lcode_c
11#define LUA_CORE
12
13#include "lua.h"
14
15#include "lcode.h"
16#include "ldebug.h"
17#include "ldo.h"
18#include "lgc.h"
19#include "llex.h"
20#include "lmem.h"
21#include "lobject.h"
22#include "lopcodes.h"
23#include "lparser.h"
24#include "ltable.h"
25
26
27#define hasjumps(e)     ((e)->t != (e)->f)
28
29
30static int isnumeral(expdesc *e) {
31  return (e->k == VKNUM && e->t == NO_JUMP && e->f == NO_JUMP);
32}
33
34
35void luaK_nil (FuncState *fs, int from, int n) {
36  Instruction *previous;
37  if (fs->pc > fs->lasttarget) {  /* no jumps to current position? */
38    if (fs->pc == 0) {  /* function start? */
39      if (from >= fs->nactvar)
40        return;  /* positions are already clean */
41    }
42    else {
43      previous = &fs->f->code[fs->pc-1];
44      if (GET_OPCODE(*previous) == OP_LOADNIL) {
45        int pfrom = GETARG_A(*previous);
46        int pto = GETARG_B(*previous);
47        if (pfrom <= from && from <= pto+1) {  /* can connect both? */
48          if (from+n-1 > pto)
49            SETARG_B(*previous, from+n-1);
50          return;
51        }
52      }
53    }
54  }
55  luaK_codeABC(fs, OP_LOADNIL, from, from+n-1, 0);  /* else no optimization */
56}
57
58
59int luaK_jump (FuncState *fs) {
60  int jpc = fs->jpc;  /* save list of jumps to here */
61  int j;
62  fs->jpc = NO_JUMP;
63  j = luaK_codeAsBx(fs, OP_JMP, 0, NO_JUMP);
64  luaK_concat(fs, &j, jpc);  /* keep them on hold */
65  return j;
66}
67
68
69void luaK_ret (FuncState *fs, int first, int nret) {
70  luaK_codeABC(fs, OP_RETURN, first, nret+1, 0);
71}
72
73
74static int condjump (FuncState *fs, OpCode op, int A, int B, int C) {
75  luaK_codeABC(fs, op, A, B, C);
76  return luaK_jump(fs);
77}
78
79
80static void fixjump (FuncState *fs, int pc, int dest) {
81  Instruction *jmp = &fs->f->code[pc];
82  int offset = dest-(pc+1);
83  lua_assert(dest != NO_JUMP);
84  if (abs(offset) > MAXARG_sBx)
85    luaX_syntaxerror(fs->ls, "control structure too long");
86  SETARG_sBx(*jmp, offset);
87}
88
89
90/*
91** returns current `pc' and marks it as a jump target (to avoid wrong
92** optimizations with consecutive instructions not in the same basic block).
93*/
94int luaK_getlabel (FuncState *fs) {
95  fs->lasttarget = fs->pc;
96  return fs->pc;
97}
98
99
100static int getjump (FuncState *fs, int pc) {
101  int offset = GETARG_sBx(fs->f->code[pc]);
102  if (offset == NO_JUMP)  /* point to itself represents end of list */
103    return NO_JUMP;  /* end of list */
104  else
105    return (pc+1)+offset;  /* turn offset into absolute position */
106}
107
108
109static Instruction *getjumpcontrol (FuncState *fs, int pc) {
110  Instruction *pi = &fs->f->code[pc];
111  if (pc >= 1 && testTMode(GET_OPCODE(*(pi-1))))
112    return pi-1;
113  else
114    return pi;
115}
116
117
118/*
119** check whether list has any jump that do not produce a value
120** (or produce an inverted value)
121*/
122static int need_value (FuncState *fs, int list) {
123  for (; list != NO_JUMP; list = getjump(fs, list)) {
124    Instruction i = *getjumpcontrol(fs, list);
125    if (GET_OPCODE(i) != OP_TESTSET) return 1;
126  }
127  return 0;  /* not found */
128}
129
130
131static int patchtestreg (FuncState *fs, int node, int reg) {
132  Instruction *i = getjumpcontrol(fs, node);
133  if (GET_OPCODE(*i) != OP_TESTSET)
134    return 0;  /* cannot patch other instructions */
135  if (reg != NO_REG && reg != GETARG_B(*i))
136    SETARG_A(*i, reg);
137  else  /* no register to put value or register already has the value */
138    *i = CREATE_ABC(OP_TEST, GETARG_B(*i), 0, GETARG_C(*i));
139
140  return 1;
141}
142
143
144static void removevalues (FuncState *fs, int list) {
145  for (; list != NO_JUMP; list = getjump(fs, list))
146      patchtestreg(fs, list, NO_REG);
147}
148
149
150static void patchlistaux (FuncState *fs, int list, int vtarget, int reg,
151                          int dtarget) {
152  while (list != NO_JUMP) {
153    int next = getjump(fs, list);
154    if (patchtestreg(fs, list, reg))
155      fixjump(fs, list, vtarget);
156    else
157      fixjump(fs, list, dtarget);  /* jump to default target */
158    list = next;
159  }
160}
161
162
163static void dischargejpc (FuncState *fs) {
164  patchlistaux(fs, fs->jpc, fs->pc, NO_REG, fs->pc);
165  fs->jpc = NO_JUMP;
166}
167
168
169void luaK_patchlist (FuncState *fs, int list, int target) {
170  if (target == fs->pc)
171    luaK_patchtohere(fs, list);
172  else {
173    lua_assert(target < fs->pc);
174    patchlistaux(fs, list, target, NO_REG, target);
175  }
176}
177
178
179void luaK_patchtohere (FuncState *fs, int list) {
180  luaK_getlabel(fs);
181  luaK_concat(fs, &fs->jpc, list);
182}
183
184
185void luaK_concat (FuncState *fs, int *l1, int l2) {
186  if (l2 == NO_JUMP) return;
187  else if (*l1 == NO_JUMP)
188    *l1 = l2;
189  else {
190    int list = *l1;
191    int next;
192    while ((next = getjump(fs, list)) != NO_JUMP)  /* find last element */
193      list = next;
194    fixjump(fs, list, l2);
195  }
196}
197
198
199void luaK_checkstack (FuncState *fs, int n) {
200  int newstack = fs->freereg + n;
201  if (newstack > fs->f->maxstacksize) {
202    if (newstack >= MAXSTACK)
203      luaX_syntaxerror(fs->ls, "function or expression too complex");
204    fs->f->maxstacksize = cast_byte(newstack);
205  }
206}
207
208
209void luaK_reserveregs (FuncState *fs, int n) {
210  luaK_checkstack(fs, n);
211  fs->freereg += n;
212}
213
214
215static void freereg (FuncState *fs, int reg) {
216  if (!ISK(reg) && reg >= fs->nactvar) {
217    fs->freereg--;
218    lua_assert(reg == fs->freereg);
219  }
220}
221
222
223static void freeexp (FuncState *fs, expdesc *e) {
224  if (e->k == VNONRELOC)
225    freereg(fs, e->u.s.info);
226}
227
228
229static int addk (FuncState *fs, TValue *k, TValue *v) {
230  lua_State *L = fs->L;
231  TValue *idx = luaH_set(L, fs->h, k);
232  Proto *f = fs->f;
233  int oldsize = f->sizek;
234  if (ttisnumber(idx)) {
235    lua_assert(luaO_rawequalObj(&fs->f->k[cast_int(nvalue(idx))], v));
236    return cast_int(nvalue(idx));
237  }
238  else {  /* constant not found; create a new entry */
239    setnvalue(idx, cast_num(fs->nk));
240    luaM_growvector(L, f->k, fs->nk, f->sizek, TValue,
241                    MAXARG_Bx, "constant table overflow");
242    while (oldsize < f->sizek) setnilvalue(&f->k[oldsize++]);
243    setobj(L, &f->k[fs->nk], v);
244    luaC_barrier(L, f, v);
245    return fs->nk++;
246  }
247}
248
249
250int luaK_stringK (FuncState *fs, TString *s) {
251  TValue o;
252  setsvalue(fs->L, &o, s);
253  return addk(fs, &o, &o);
254}
255
256
257int luaK_numberK (FuncState *fs, lua_Number r) {
258  TValue o;
259  setnvalue(&o, r);
260  return addk(fs, &o, &o);
261}
262
263
264static int boolK (FuncState *fs, int b) {
265  TValue o;
266  setbvalue(&o, b);
267  return addk(fs, &o, &o);
268}
269
270
271static int nilK (FuncState *fs) {
272  TValue k, v;
273  setnilvalue(&v);
274  /* cannot use nil as key; instead use table itself to represent nil */
275  sethvalue(fs->L, &k, fs->h);
276  return addk(fs, &k, &v);
277}
278
279
280void luaK_setreturns (FuncState *fs, expdesc *e, int nresults) {
281  if (e->k == VCALL) {  /* expression is an open function call? */
282    SETARG_C(getcode(fs, e), nresults+1);
283  }
284  else if (e->k == VVARARG) {
285    SETARG_B(getcode(fs, e), nresults+1);
286    SETARG_A(getcode(fs, e), fs->freereg);
287    luaK_reserveregs(fs, 1);
288  }
289}
290
291
292void luaK_setoneret (FuncState *fs, expdesc *e) {
293  if (e->k == VCALL) {  /* expression is an open function call? */
294    e->k = VNONRELOC;
295    e->u.s.info = GETARG_A(getcode(fs, e));
296  }
297  else if (e->k == VVARARG) {
298    SETARG_B(getcode(fs, e), 2);
299    e->k = VRELOCABLE;  /* can relocate its simple result */
300  }
301}
302
303
304void luaK_dischargevars (FuncState *fs, expdesc *e) {
305  switch (e->k) {
306    case VLOCAL: {
307      e->k = VNONRELOC;
308      break;
309    }
310    case VUPVAL: {
311      e->u.s.info = luaK_codeABC(fs, OP_GETUPVAL, 0, e->u.s.info, 0);
312      e->k = VRELOCABLE;
313      break;
314    }
315    case VGLOBAL: {
316      e->u.s.info = luaK_codeABx(fs, OP_GETGLOBAL, 0, e->u.s.info);
317      e->k = VRELOCABLE;
318      break;
319    }
320    case VINDEXED: {
321      freereg(fs, e->u.s.aux);
322      freereg(fs, e->u.s.info);
323      e->u.s.info = luaK_codeABC(fs, OP_GETTABLE, 0, e->u.s.info, e->u.s.aux);
324      e->k = VRELOCABLE;
325      break;
326    }
327    case VVARARG:
328    case VCALL: {
329      luaK_setoneret(fs, e);
330      break;
331    }
332    default: break;  /* there is one value available (somewhere) */
333  }
334}
335
336
337static int code_label (FuncState *fs, int A, int b, int jump) {
338  luaK_getlabel(fs);  /* those instructions may be jump targets */
339  return luaK_codeABC(fs, OP_LOADBOOL, A, b, jump);
340}
341
342
343static void discharge2reg (FuncState *fs, expdesc *e, int reg) {
344  luaK_dischargevars(fs, e);
345  switch (e->k) {
346    case VNIL: {
347      luaK_nil(fs, reg, 1);
348      break;
349    }
350    case VFALSE:  case VTRUE: {
351      luaK_codeABC(fs, OP_LOADBOOL, reg, e->k == VTRUE, 0);
352      break;
353    }
354    case VK: {
355      luaK_codeABx(fs, OP_LOADK, reg, e->u.s.info);
356      break;
357    }
358    case VKNUM: {
359      luaK_codeABx(fs, OP_LOADK, reg, luaK_numberK(fs, e->u.nval));
360      break;
361    }
362    case VRELOCABLE: {
363      Instruction *pc = &getcode(fs, e);
364      SETARG_A(*pc, reg);
365      break;
366    }
367    case VNONRELOC: {
368      if (reg != e->u.s.info)
369        luaK_codeABC(fs, OP_MOVE, reg, e->u.s.info, 0);
370      break;
371    }
372    default: {
373      lua_assert(e->k == VVOID || e->k == VJMP);
374      return;  /* nothing to do... */
375    }
376  }
377  e->u.s.info = reg;
378  e->k = VNONRELOC;
379}
380
381
382static void discharge2anyreg (FuncState *fs, expdesc *e) {
383  if (e->k != VNONRELOC) {
384    luaK_reserveregs(fs, 1);
385    discharge2reg(fs, e, fs->freereg-1);
386  }
387}
388
389
390static void exp2reg (FuncState *fs, expdesc *e, int reg) {
391  discharge2reg(fs, e, reg);
392  if (e->k == VJMP)
393    luaK_concat(fs, &e->t, e->u.s.info);  /* put this jump in `t' list */
394  if (hasjumps(e)) {
395    int final;  /* position after whole expression */
396    int p_f = NO_JUMP;  /* position of an eventual LOAD false */
397    int p_t = NO_JUMP;  /* position of an eventual LOAD true */
398    if (need_value(fs, e->t) || need_value(fs, e->f)) {
399      int fj = (e->k == VJMP) ? NO_JUMP : luaK_jump(fs);
400      p_f = code_label(fs, reg, 0, 1);
401      p_t = code_label(fs, reg, 1, 0);
402      luaK_patchtohere(fs, fj);
403    }
404    final = luaK_getlabel(fs);
405    patchlistaux(fs, e->f, final, reg, p_f);
406    patchlistaux(fs, e->t, final, reg, p_t);
407  }
408  e->f = e->t = NO_JUMP;
409  e->u.s.info = reg;
410  e->k = VNONRELOC;
411}
412
413
414void luaK_exp2nextreg (FuncState *fs, expdesc *e) {
415  luaK_dischargevars(fs, e);
416  freeexp(fs, e);
417  luaK_reserveregs(fs, 1);
418  exp2reg(fs, e, fs->freereg - 1);
419}
420
421
422int luaK_exp2anyreg (FuncState *fs, expdesc *e) {
423  luaK_dischargevars(fs, e);
424  if (e->k == VNONRELOC) {
425    if (!hasjumps(e)) return e->u.s.info;  /* exp is already in a register */
426    if (e->u.s.info >= fs->nactvar) {  /* reg. is not a local? */
427      exp2reg(fs, e, e->u.s.info);  /* put value on it */
428      return e->u.s.info;
429    }
430  }
431  luaK_exp2nextreg(fs, e);  /* default */
432  return e->u.s.info;
433}
434
435
436void luaK_exp2val (FuncState *fs, expdesc *e) {
437  if (hasjumps(e))
438    luaK_exp2anyreg(fs, e);
439  else
440    luaK_dischargevars(fs, e);
441}
442
443
444int luaK_exp2RK (FuncState *fs, expdesc *e) {
445  luaK_exp2val(fs, e);
446  switch (e->k) {
447    case VKNUM:
448    case VTRUE:
449    case VFALSE:
450    case VNIL: {
451      if (fs->nk <= MAXINDEXRK) {  /* constant fit in RK operand? */
452        e->u.s.info = (e->k == VNIL)  ? nilK(fs) :
453                      (e->k == VKNUM) ? luaK_numberK(fs, e->u.nval) :
454                                        boolK(fs, (e->k == VTRUE));
455        e->k = VK;
456        return RKASK(e->u.s.info);
457      }
458      else break;
459    }
460    case VK: {
461      if (e->u.s.info <= MAXINDEXRK)  /* constant fit in argC? */
462        return RKASK(e->u.s.info);
463      else break;
464    }
465    default: break;
466  }
467  /* not a constant in the right range: put it in a register */
468  return luaK_exp2anyreg(fs, e);
469}
470
471
472void luaK_storevar (FuncState *fs, expdesc *var, expdesc *ex) {
473  switch (var->k) {
474    case VLOCAL: {
475      freeexp(fs, ex);
476      exp2reg(fs, ex, var->u.s.info);
477      return;
478    }
479    case VUPVAL: {
480      int e = luaK_exp2anyreg(fs, ex);
481      luaK_codeABC(fs, OP_SETUPVAL, e, var->u.s.info, 0);
482      break;
483    }
484    case VGLOBAL: {
485      int e = luaK_exp2anyreg(fs, ex);
486      luaK_codeABx(fs, OP_SETGLOBAL, e, var->u.s.info);
487      break;
488    }
489    case VINDEXED: {
490      int e = luaK_exp2RK(fs, ex);
491      luaK_codeABC(fs, OP_SETTABLE, var->u.s.info, var->u.s.aux, e);
492      break;
493    }
494    default: {
495      lua_assert(0);  /* invalid var kind to store */
496      break;
497    }
498  }
499  freeexp(fs, ex);
500}
501
502
503void luaK_self (FuncState *fs, expdesc *e, expdesc *key) {
504  int func;
505  luaK_exp2anyreg(fs, e);
506  freeexp(fs, e);
507  func = fs->freereg;
508  luaK_reserveregs(fs, 2);
509  luaK_codeABC(fs, OP_SELF, func, e->u.s.info, luaK_exp2RK(fs, key));
510  freeexp(fs, key);
511  e->u.s.info = func;
512  e->k = VNONRELOC;
513}
514
515
516static void invertjump (FuncState *fs, expdesc *e) {
517  Instruction *pc = getjumpcontrol(fs, e->u.s.info);
518  lua_assert(testTMode(GET_OPCODE(*pc)) && GET_OPCODE(*pc) != OP_TESTSET &&
519                                           GET_OPCODE(*pc) != OP_TEST);
520  SETARG_A(*pc, !(GETARG_A(*pc)));
521}
522
523
524static int jumponcond (FuncState *fs, expdesc *e, int cond) {
525  if (e->k == VRELOCABLE) {
526    Instruction ie = getcode(fs, e);
527    if (GET_OPCODE(ie) == OP_NOT) {
528      fs->pc--;  /* remove previous OP_NOT */
529      return condjump(fs, OP_TEST, GETARG_B(ie), 0, !cond);
530    }
531    /* else go through */
532  }
533  discharge2anyreg(fs, e);
534  freeexp(fs, e);
535  return condjump(fs, OP_TESTSET, NO_REG, e->u.s.info, cond);
536}
537
538
539void luaK_goiftrue (FuncState *fs, expdesc *e) {
540  int pc;  /* pc of last jump */
541  luaK_dischargevars(fs, e);
542  switch (e->k) {
543    case VK: case VKNUM: case VTRUE: {
544      pc = NO_JUMP;  /* always true; do nothing */
545      break;
546    }
547    case VFALSE: {
548      pc = luaK_jump(fs);  /* always jump */
549      break;
550    }
551    case VJMP: {
552      invertjump(fs, e);
553      pc = e->u.s.info;
554      break;
555    }
556    default: {
557      pc = jumponcond(fs, e, 0);
558      break;
559    }
560  }
561  luaK_concat(fs, &e->f, pc);  /* insert last jump in `f' list */
562  luaK_patchtohere(fs, e->t);
563  e->t = NO_JUMP;
564}
565
566
567static void luaK_goiffalse (FuncState *fs, expdesc *e) {
568  int pc;  /* pc of last jump */
569  luaK_dischargevars(fs, e);
570  switch (e->k) {
571    case VNIL: case VFALSE: {
572      pc = NO_JUMP;  /* always false; do nothing */
573      break;
574    }
575    case VTRUE: {
576      pc = luaK_jump(fs);  /* always jump */
577      break;
578    }
579    case VJMP: {
580      pc = e->u.s.info;
581      break;
582    }
583    default: {
584      pc = jumponcond(fs, e, 1);
585      break;
586    }
587  }
588  luaK_concat(fs, &e->t, pc);  /* insert last jump in `t' list */
589  luaK_patchtohere(fs, e->f);
590  e->f = NO_JUMP;
591}
592
593
594static void codenot (FuncState *fs, expdesc *e) {
595  luaK_dischargevars(fs, e);
596  switch (e->k) {
597    case VNIL: case VFALSE: {
598      e->k = VTRUE;
599      break;
600    }
601    case VK: case VKNUM: case VTRUE: {
602      e->k = VFALSE;
603      break;
604    }
605    case VJMP: {
606      invertjump(fs, e);
607      break;
608    }
609    case VRELOCABLE:
610    case VNONRELOC: {
611      discharge2anyreg(fs, e);
612      freeexp(fs, e);
613      e->u.s.info = luaK_codeABC(fs, OP_NOT, 0, e->u.s.info, 0);
614      e->k = VRELOCABLE;
615      break;
616    }
617    default: {
618      lua_assert(0);  /* cannot happen */
619      break;
620    }
621  }
622  /* interchange true and false lists */
623  { int temp = e->f; e->f = e->t; e->t = temp; }
624  removevalues(fs, e->f);
625  removevalues(fs, e->t);
626}
627
628
629void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k) {
630  t->u.s.aux = luaK_exp2RK(fs, k);
631  t->k = VINDEXED;
632}
633
634
635static int constfolding (OpCode op, expdesc *e1, expdesc *e2) {
636  lua_Number v1, v2, r;
637  if (!isnumeral(e1) || !isnumeral(e2)) return 0;
638  v1 = e1->u.nval;
639  v2 = e2->u.nval;
640  switch (op) {
641    case OP_ADD: r = luai_numadd(v1, v2); break;
642    case OP_SUB: r = luai_numsub(v1, v2); break;
643    case OP_MUL: r = luai_nummul(v1, v2); break;
644    case OP_DIV:
645      if (v2 == 0) return 0;  /* do not attempt to divide by 0 */
646      r = luai_numdiv(v1, v2); break;
647    case OP_MOD:
648      if (v2 == 0) return 0;  /* do not attempt to divide by 0 */
649      r = luai_nummod(v1, v2); break;
650    case OP_POW: r = luai_numpow(v1, v2); break;
651    case OP_UNM: r = luai_numunm(v1); break;
652    case OP_LEN: return 0;  /* no constant folding for 'len' */
653    default: lua_assert(0); r = 0; break;
654  }
655  if (luai_numisnan(r)) return 0;  /* do not attempt to produce NaN */
656  e1->u.nval = r;
657  return 1;
658}
659
660
661static void codearith (FuncState *fs, OpCode op, expdesc *e1, expdesc *e2) {
662  if (constfolding(op, e1, e2))
663    return;
664  else {
665    int o2 = (op != OP_UNM && op != OP_LEN) ? luaK_exp2RK(fs, e2) : 0;
666    int o1 = luaK_exp2RK(fs, e1);
667    if (o1 > o2) {
668      freeexp(fs, e1);
669      freeexp(fs, e2);
670    }
671    else {
672      freeexp(fs, e2);
673      freeexp(fs, e1);
674    }
675    e1->u.s.info = luaK_codeABC(fs, op, 0, o1, o2);
676    e1->k = VRELOCABLE;
677  }
678}
679
680
681static void codecomp (FuncState *fs, OpCode op, int cond, expdesc *e1,
682                                                          expdesc *e2) {
683  int o1 = luaK_exp2RK(fs, e1);
684  int o2 = luaK_exp2RK(fs, e2);
685  freeexp(fs, e2);
686  freeexp(fs, e1);
687  if (cond == 0 && op != OP_EQ) {
688    int temp;  /* exchange args to replace by `<' or `<=' */
689    temp = o1; o1 = o2; o2 = temp;  /* o1 <==> o2 */
690    cond = 1;
691  }
692  e1->u.s.info = condjump(fs, op, cond, o1, o2);
693  e1->k = VJMP;
694}
695
696
697void luaK_prefix (FuncState *fs, UnOpr op, expdesc *e) {
698  expdesc e2;
699  e2.t = e2.f = NO_JUMP; e2.k = VKNUM; e2.u.nval = 0;
700  switch (op) {
701    case OPR_MINUS: {
702      if (!isnumeral(e))
703        luaK_exp2anyreg(fs, e);  /* cannot operate on non-numeric constants */
704      codearith(fs, OP_UNM, e, &e2);
705      break;
706    }
707    case OPR_NOT: codenot(fs, e); break;
708    case OPR_LEN: {
709      luaK_exp2anyreg(fs, e);  /* cannot operate on constants */
710      codearith(fs, OP_LEN, e, &e2);
711      break;
712    }
713    default: lua_assert(0);
714  }
715}
716
717
718void luaK_infix (FuncState *fs, BinOpr op, expdesc *v) {
719  switch (op) {
720    case OPR_AND: {
721      luaK_goiftrue(fs, v);
722      break;
723    }
724    case OPR_OR: {
725      luaK_goiffalse(fs, v);
726      break;
727    }
728    case OPR_CONCAT: {
729      luaK_exp2nextreg(fs, v);  /* operand must be on the `stack' */
730      break;
731    }
732    case OPR_ADD: case OPR_SUB: case OPR_MUL: case OPR_DIV:
733    case OPR_MOD: case OPR_POW: {
734      if (!isnumeral(v)) luaK_exp2RK(fs, v);
735      break;
736    }
737    default: {
738      luaK_exp2RK(fs, v);
739      break;
740    }
741  }
742}
743
744
745void luaK_posfix (FuncState *fs, BinOpr op, expdesc *e1, expdesc *e2) {
746  switch (op) {
747    case OPR_AND: {
748      lua_assert(e1->t == NO_JUMP);  /* list must be closed */
749      luaK_dischargevars(fs, e2);
750      luaK_concat(fs, &e2->f, e1->f);
751      *e1 = *e2;
752      break;
753    }
754    case OPR_OR: {
755      lua_assert(e1->f == NO_JUMP);  /* list must be closed */
756      luaK_dischargevars(fs, e2);
757      luaK_concat(fs, &e2->t, e1->t);
758      *e1 = *e2;
759      break;
760    }
761    case OPR_CONCAT: {
762      luaK_exp2val(fs, e2);
763      if (e2->k == VRELOCABLE && GET_OPCODE(getcode(fs, e2)) == OP_CONCAT) {
764        lua_assert(e1->u.s.info == GETARG_B(getcode(fs, e2))-1);
765        freeexp(fs, e1);
766        SETARG_B(getcode(fs, e2), e1->u.s.info);
767        e1->k = VRELOCABLE; e1->u.s.info = e2->u.s.info;
768      }
769      else {
770        luaK_exp2nextreg(fs, e2);  /* operand must be on the 'stack' */
771        codearith(fs, OP_CONCAT, e1, e2);
772      }
773      break;
774    }
775    case OPR_ADD: codearith(fs, OP_ADD, e1, e2); break;
776    case OPR_SUB: codearith(fs, OP_SUB, e1, e2); break;
777    case OPR_MUL: codearith(fs, OP_MUL, e1, e2); break;
778    case OPR_DIV: codearith(fs, OP_DIV, e1, e2); break;
779    case OPR_MOD: codearith(fs, OP_MOD, e1, e2); break;
780    case OPR_POW: codearith(fs, OP_POW, e1, e2); break;
781    case OPR_EQ: codecomp(fs, OP_EQ, 1, e1, e2); break;
782    case OPR_NE: codecomp(fs, OP_EQ, 0, e1, e2); break;
783    case OPR_LT: codecomp(fs, OP_LT, 1, e1, e2); break;
784    case OPR_LE: codecomp(fs, OP_LE, 1, e1, e2); break;
785    case OPR_GT: codecomp(fs, OP_LT, 0, e1, e2); break;
786    case OPR_GE: codecomp(fs, OP_LE, 0, e1, e2); break;
787    default: lua_assert(0);
788  }
789}
790
791
792void luaK_fixline (FuncState *fs, int line) {
793  fs->f->lineinfo[fs->pc - 1] = line;
794}
795
796
797static int luaK_code (FuncState *fs, Instruction i, int line) {
798  Proto *f = fs->f;
799  dischargejpc(fs);  /* `pc' will change */
800  /* put new instruction in code array */
801  luaM_growvector(fs->L, f->code, fs->pc, f->sizecode, Instruction,
802                  MAX_INT, "code size overflow");
803  f->code[fs->pc] = i;
804  /* save corresponding line information */
805  luaM_growvector(fs->L, f->lineinfo, fs->pc, f->sizelineinfo, int,
806                  MAX_INT, "code size overflow");
807  f->lineinfo[fs->pc] = line;
808  return fs->pc++;
809}
810
811
812int luaK_codeABC (FuncState *fs, OpCode o, int a, int b, int c) {
813  lua_assert(getOpMode(o) == iABC);
814  lua_assert(getBMode(o) != OpArgN || b == 0);
815  lua_assert(getCMode(o) != OpArgN || c == 0);
816  return luaK_code(fs, CREATE_ABC(o, a, b, c), fs->ls->lastline);
817}
818
819
820int luaK_codeABx (FuncState *fs, OpCode o, int a, unsigned int bc) {
821  lua_assert(getOpMode(o) == iABx || getOpMode(o) == iAsBx);
822  lua_assert(getCMode(o) == OpArgN);
823  return luaK_code(fs, CREATE_ABx(o, a, bc), fs->ls->lastline);
824}
825
826
827void luaK_setlist (FuncState *fs, int base, int nelems, int tostore) {
828  int c =  (nelems - 1)/LFIELDS_PER_FLUSH + 1;
829  int b = (tostore == LUA_MULTRET) ? 0 : tostore;
830  lua_assert(tostore != 0);
831  if (c <= MAXARG_C)
832    luaK_codeABC(fs, OP_SETLIST, base, b, c);
833  else {
834    luaK_codeABC(fs, OP_SETLIST, base, b, 0);
835    luaK_code(fs, cast(Instruction, c), fs->ls->lastline);
836  }
837  fs->freereg = base + 1;  /* free registers with list values */
838}
839
Note: See TracBrowser for help on using the repository browser.