New Lua functions
[jpcrr.git] / mnj / lua / FuncState.java
blob05f62a4386930bec4b5c1c89293116bee51855a1
1 /* $Header: //info.ravenbrook.com/project/jili/version/1.1/code/mnj/lua/FuncState.java#1 $
2 * Copyright (c) 2006 Nokia Corporation and/or its subsidiary(-ies).
3 * All rights reserved.
5 * Permission is hereby granted, free of charge, to any person obtaining
6 * a copy of this software and associated documentation files (the
7 * "Software"), to deal in the Software without restriction, including
8 * without limitation the rights to use, copy, modify, merge, publish,
9 * distribute, sublicense, and/or sell copies of the Software, and to
10 * permit persons to whom the Software is furnished to do so, subject
11 * to the following conditions:
13 * The above copyright notice and this permission notice shall be
14 * included in all copies or substantial portions of the Software.
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
20 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
21 * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 package mnj.lua;
27 import java.util.Hashtable;
29 /**
30 * Used to model a function during compilation. Code generation uses
31 * this structure extensively. Most of the PUC-Rio functions from
32 * lcode.c have moved into this class, alongwith a few functions from
33 * lparser.c
35 final class FuncState
37 /** See NO_JUMP in lcode.h. */
38 static final int NO_JUMP = -1;
40 /** Proto object for this function. */
41 Proto f;
43 /**
44 * Table to find (and reuse) elements in <var>f.k</var>. Maps from
45 * Object (a constant Lua value) to an index into <var>f.k</var>.
47 Hashtable<Object, Object> h = new Hashtable<Object, Object>();
49 /** Enclosing function. */
50 FuncState prev;
52 /** Lexical state. */
53 Syntax ls;
55 /** Lua state. */
56 Lua L;
58 /** chain of current blocks */
59 BlockCnt bl; // = null;
61 /** next position to code. */
62 int pc; // = 0;
64 /** pc of last jump target. */
65 int lasttarget = -1;
67 /** List of pending jumps to <var>pc</var>. */
68 int jpc = NO_JUMP;
70 /** First free register. */
71 int freereg; // = 0;
73 /** number of elements in <var>k</var>. */
74 int nk; // = 0;
76 /** number of elements in <var>p</var>. */
77 int np; // = 0;
79 /** number of elements in <var>locvars</var>. */
80 short nlocvars; // = 0;
82 /** number of active local variables. */
83 short nactvar; // = 0;
85 /** upvalues as 8-bit k and 8-bit info */
86 int [] upvalues = new int [Lua.MAXUPVALUES] ;
88 /** declared-variable stack. */
89 short[] actvar = new short[Lua.MAXVARS];
91 /**
92 * Constructor. Much of this is taken from <code>open_func</code> in
93 * <code>lparser.c</code>.
95 FuncState(Syntax ls)
97 f = new Proto(ls.source, 2); // default value for maxstacksize=2
98 L = ls.L ;
99 this.ls = ls;
100 // prev = ls.linkfs(this);
103 /** Equivalent to <code>close_func</code> from <code>lparser.c</code>. */
104 void close()
106 f.closeCode(pc);
107 f.closeLineinfo(pc);
108 f.closeK(nk);
109 f.closeP(np);
110 f.closeLocvars(nlocvars);
111 f.closeUpvalues();
112 L.gCheckcode(f);
113 //# assert checks
114 //# assert bl == null
117 /** Equivalent to getlocvar from lparser.c.
118 * Accesses <code>LocVar</code>s of the {@link Proto}.
120 LocVar getlocvar(int idx)
122 return f.locvars[actvar[idx]];
126 // Functions from lcode.c
128 /** Equivalent to luaK_checkstack. */
129 void kCheckstack(int n)
131 int newstack = freereg + n;
132 if (newstack > f.maxstacksize())
134 if (newstack >= Lua.MAXSTACK)
136 ls.xSyntaxerror("function or expression too complex");
138 f.setMaxstacksize(newstack);
142 /** Equivalent to luaK_code. */
143 int kCode(int i, int line)
145 dischargejpc();
146 // Put new instruction in code array.
147 f.codeAppend(L, pc, i, line);
148 return pc++;
151 /** Equivalent to luaK_codeABC. */
152 int kCodeABC(int o, int a, int b, int c)
154 // assert getOpMode(o) == iABC;
155 // assert getBMode(o) != OP_ARG_N || b == 0;
156 // assert getCMode(o) != OP_ARG_N || c == 0;
157 return kCode(Lua.CREATE_ABC(o, a, b, c), ls.lastline());
160 /** Equivalent to luaK_codeABx. */
161 int kCodeABx(int o, int a, int bc)
163 // assert getOpMode(o) == iABx || getOpMode(o) == iAsBx);
164 // assert getCMode(o) == OP_ARG_N);
165 return kCode(Lua.CREATE_ABx(o, a, bc), ls.lastline());
168 /** Equivalent to luaK_codeAsBx. */
169 int kCodeAsBx(int o, int a, int bc)
171 return kCodeABx(o, a, bc+Lua.MAXARG_sBx);
174 /** Equivalent to luaK_dischargevars. */
175 void kDischargevars(Expdesc e)
177 switch (e.kind())
179 case Expdesc.VLOCAL:
180 e.setKind(Expdesc.VNONRELOC);
181 break;
182 case Expdesc.VUPVAL:
183 e.reloc(kCodeABC(Lua.OP_GETUPVAL, 0, e.info, 0));
184 break;
185 case Expdesc.VGLOBAL:
186 e.reloc(kCodeABx(Lua.OP_GETGLOBAL, 0, e.info));
187 break;
188 case Expdesc.VINDEXED:
189 freereg(e.aux());
190 freereg(e.info());
191 e.reloc(kCodeABC(Lua.OP_GETTABLE, 0, e.info, e.aux));
192 break;
193 case Expdesc.VVARARG:
194 case Expdesc.VCALL:
195 kSetoneret(e);
196 break;
197 default:
198 break; // there is one value available (somewhere)
202 /** Equivalent to luaK_exp2anyreg. */
203 int kExp2anyreg(Expdesc e)
205 kDischargevars(e);
206 if (e.k == Expdesc.VNONRELOC)
208 if (!e.hasjumps())
210 return e.info;
212 if (e.info >= nactvar) // reg is not a local?
214 exp2reg(e, e.info); // put value on it
215 return e.info;
218 kExp2nextreg(e); // default
219 return e.info;
222 /** Equivalent to luaK_exp2nextreg. */
223 void kExp2nextreg(Expdesc e)
225 kDischargevars(e);
226 freeexp(e);
227 kReserveregs(1);
228 exp2reg(e, freereg - 1);
231 /** Equivalent to luaK_fixline. */
232 void kFixline(int line)
234 f.setLineinfo(pc-1, line);
237 /** Equivalent to luaK_infix. */
238 void kInfix(int op, Expdesc v)
240 switch (op)
242 case Syntax.OPR_AND:
243 kGoiftrue(v);
244 break;
245 case Syntax.OPR_OR:
246 kGoiffalse(v);
247 break;
248 case Syntax.OPR_CONCAT:
249 kExp2nextreg(v); /* operand must be on the `stack' */
250 break;
251 default:
252 if (!isnumeral(v))
253 kExp2RK(v);
254 break;
259 private boolean isnumeral(Expdesc e)
261 return e.k == Expdesc.VKNUM &&
262 e.t == NO_JUMP &&
263 e.f == NO_JUMP ;
266 /** Equivalent to luaK_nil. */
267 void kNil(int from, int n)
269 int previous;
270 if (pc > lasttarget) /* no jumps to current position? */
272 if (pc == 0) /* function start? */
273 return; /* positions are already clean */
274 previous = pc-1 ;
275 int instr = f.code[previous] ;
276 if (Lua.OPCODE(instr) == Lua.OP_LOADNIL)
278 int pfrom = Lua.ARGA(instr);
279 int pto = Lua.ARGB(instr);
280 if (pfrom <= from && from <= pto+1) /* can connect both? */
282 if (from+n-1 > pto)
283 f.code[previous] = Lua.SETARG_B(instr, from+n-1);
284 return;
288 kCodeABC(Lua.OP_LOADNIL, from, from+n-1, 0);
291 /** Equivalent to luaK_numberK. */
292 int kNumberK(double r)
294 return addk(Lua.valueOfNumber(r));
297 /** Equivalent to luaK_posfix. */
298 void kPosfix(int op, Expdesc e1, Expdesc e2)
300 switch (op)
302 case Syntax.OPR_AND:
303 /* list must be closed */
304 //# assert e1.t == NO_JUMP
305 kDischargevars(e2);
306 e2.f = kConcat(e2.f, e1.f);
307 e1.init(e2);
308 break;
310 case Syntax.OPR_OR:
311 /* list must be closed */
312 //# assert e1.f == NO_JUMP
313 kDischargevars(e2);
314 e2.t = kConcat(e2.t, e1.t);
315 e1.init(e2);
316 break;
318 case Syntax.OPR_CONCAT:
319 kExp2val(e2);
320 if (e2.k == Expdesc.VRELOCABLE && Lua.OPCODE(getcode(e2)) == Lua.OP_CONCAT)
322 //# assert e1.info == Lua.ARGB(getcode(e2))-1
323 freeexp(e1);
324 setcode(e2, Lua.SETARG_B(getcode(e2), e1.info));
325 e1.k = e2.k;
326 e1.info = e2.info;
328 else
330 kExp2nextreg(e2); /* operand must be on the 'stack' */
331 codearith(Lua.OP_CONCAT, e1, e2);
333 break;
335 case Syntax.OPR_ADD: codearith(Lua.OP_ADD, e1, e2); break;
336 case Syntax.OPR_SUB: codearith(Lua.OP_SUB, e1, e2); break;
337 case Syntax.OPR_MUL: codearith(Lua.OP_MUL, e1, e2); break;
338 case Syntax.OPR_DIV: codearith(Lua.OP_DIV, e1, e2); break;
339 case Syntax.OPR_MOD: codearith(Lua.OP_MOD, e1, e2); break;
340 case Syntax.OPR_POW: codearith(Lua.OP_POW, e1, e2); break;
341 case Syntax.OPR_EQ: codecomp(Lua.OP_EQ, true, e1, e2); break;
342 case Syntax.OPR_NE: codecomp(Lua.OP_EQ, false, e1, e2); break;
343 case Syntax.OPR_LT: codecomp(Lua.OP_LT, true, e1, e2); break;
344 case Syntax.OPR_LE: codecomp(Lua.OP_LE, true, e1, e2); break;
345 case Syntax.OPR_GT: codecomp(Lua.OP_LT, false, e1, e2); break;
346 case Syntax.OPR_GE: codecomp(Lua.OP_LE, false, e1, e2); break;
347 default:
348 //# assert false
352 /** Equivalent to luaK_prefix. */
353 void kPrefix(int op, Expdesc e)
355 Expdesc e2 = new Expdesc(Expdesc.VKNUM, 0);
356 switch (op)
358 case Syntax.OPR_MINUS:
359 if (e.kind() == Expdesc.VK)
361 kExp2anyreg(e);
363 codearith(Lua.OP_UNM, e, e2);
364 break;
365 case Syntax.OPR_NOT:
366 codenot(e);
367 break;
368 case Syntax.OPR_LEN:
369 kExp2anyreg(e);
370 codearith(Lua.OP_LEN, e, e2);
371 break;
372 default:
373 throw new IllegalArgumentException();
377 /** Equivalent to luaK_reserveregs. */
378 void kReserveregs(int n)
380 kCheckstack(n);
381 freereg += n;
384 /** Equivalent to luaK_ret. */
385 void kRet(int first, int nret)
387 kCodeABC(Lua.OP_RETURN, first, nret+1, 0);
390 /** Equivalent to luaK_setmultret (in lcode.h). */
391 void kSetmultret(Expdesc e)
393 kSetreturns(e, Lua.MULTRET);
396 /** Equivalent to luaK_setoneret. */
397 void kSetoneret(Expdesc e)
399 if (e.kind() == Expdesc.VCALL) // expression is an open function call?
401 e.nonreloc(Lua.ARGA(getcode(e)));
403 else if (e.kind() == Expdesc.VVARARG)
405 setargb(e, 2);
406 e.setKind(Expdesc.VRELOCABLE);
410 /** Equivalent to luaK_setreturns. */
411 void kSetreturns(Expdesc e, int nresults)
413 if (e.kind() == Expdesc.VCALL) // expression is an open function call?
415 setargc(e, nresults+1);
417 else if (e.kind() == Expdesc.VVARARG)
419 setargb(e, nresults+1);
420 setarga(e, freereg);
421 kReserveregs(1);
425 /** Equivalent to luaK_stringK. */
426 int kStringK(String s)
428 return addk(s.intern());
431 private int addk(Object o)
433 Object hash = o;
434 Object v = h.get(hash);
435 if (v != null)
437 // :todo: assert
438 return ((Integer)v).intValue();
440 // constant not found; create a new entry
441 f.constantAppend(nk, o);
442 h.put(hash, new Integer(nk));
443 return nk++;
446 private void codearith(int op, Expdesc e1, Expdesc e2)
448 if (constfolding(op, e1, e2))
449 return;
450 else
452 int o1 = kExp2RK(e1);
453 int o2 = (op != Lua.OP_UNM && op != Lua.OP_LEN) ? kExp2RK(e2) : 0;
454 freeexp(e2);
455 freeexp(e1);
456 e1.info = kCodeABC(op, 0, o1, o2);
457 e1.k = Expdesc.VRELOCABLE;
461 private boolean constfolding(int op, Expdesc e1, Expdesc e2)
463 double r;
464 if (!isnumeral(e1) || !isnumeral(e2))
465 return false;
466 double v1 = e1.nval;
467 double v2 = e2.nval;
468 switch (op)
470 case Lua.OP_ADD: r = v1 + v2; break;
471 case Lua.OP_SUB: r = v1 - v2; break;
472 case Lua.OP_MUL: r = v1 * v2; break;
473 case Lua.OP_DIV:
474 if (v2 == 0.0)
475 return false; /* do not attempt to divide by 0 */
476 r = v1 / v2;
477 break;
478 case Lua.OP_MOD:
479 if (v2 == 0.0)
480 return false; /* do not attempt to divide by 0 */
481 r = v1 % v2;
482 break;
483 case Lua.OP_POW: r = Lua.iNumpow(v1, v2); break;
484 case Lua.OP_UNM: r = -v1; break;
485 case Lua.OP_LEN: return false; /* no constant folding for 'len' */
486 default:
487 //# assert false
488 r = 0.0; break;
490 if (Double.isNaN(r))
491 return false; /* do not attempt to produce NaN */
492 e1.nval = r;
493 return true;
496 private void codenot(Expdesc e)
498 kDischargevars(e);
499 switch (e.k)
501 case Expdesc.VNIL:
502 case Expdesc.VFALSE:
503 e.k = Expdesc.VTRUE;
504 break;
506 case Expdesc.VK:
507 case Expdesc.VKNUM:
508 case Expdesc.VTRUE:
509 e.k = Expdesc.VFALSE;
510 break;
512 case Expdesc.VJMP:
513 invertjump(e);
514 break;
516 case Expdesc.VRELOCABLE:
517 case Expdesc.VNONRELOC:
518 discharge2anyreg(e);
519 freeexp(e);
520 e.info = kCodeABC(Lua.OP_NOT, 0, e.info, 0);
521 e.k = Expdesc.VRELOCABLE;
522 break;
524 default:
525 //# assert false
526 break;
528 /* interchange true and false lists */
529 { int temp = e.f; e.f = e.t; e.t = temp; }
530 removevalues(e.f);
531 removevalues(e.t);
534 private void removevalues(int list)
536 for (; list != NO_JUMP; list = getjump(list))
537 patchtestreg(list, Lua.NO_REG);
541 private void dischargejpc()
543 patchlistaux(jpc, pc, Lua.NO_REG, pc);
544 jpc = NO_JUMP;
547 private void discharge2reg(Expdesc e, int reg)
549 kDischargevars(e);
550 switch (e.k)
552 case Expdesc.VNIL:
553 kNil(reg, 1);
554 break;
556 case Expdesc.VFALSE:
557 case Expdesc.VTRUE:
558 kCodeABC(Lua.OP_LOADBOOL, reg, (e.k == Expdesc.VTRUE ? 1 : 0), 0);
559 break;
561 case Expdesc.VK:
562 kCodeABx(Lua.OP_LOADK, reg, e.info);
563 break;
565 case Expdesc.VKNUM:
566 kCodeABx(Lua.OP_LOADK, reg, kNumberK(e.nval));
567 break;
569 case Expdesc.VRELOCABLE:
570 setarga(e, reg);
571 break;
573 case Expdesc.VNONRELOC:
574 if (reg != e.info)
576 kCodeABC(Lua.OP_MOVE, reg, e.info, 0);
578 break;
580 case Expdesc.VVOID:
581 case Expdesc.VJMP:
582 return ;
584 default:
585 //# assert false
587 e.nonreloc(reg);
590 private void exp2reg(Expdesc e, int reg)
592 discharge2reg(e, reg);
593 if (e.k == Expdesc.VJMP)
595 e.t = kConcat(e.t, e.info); /* put this jump in `t' list */
597 if (e.hasjumps())
599 int p_f = NO_JUMP; /* position of an eventual LOAD false */
600 int p_t = NO_JUMP; /* position of an eventual LOAD true */
601 if (need_value(e.t) || need_value(e.f))
603 int fj = (e.k == Expdesc.VJMP) ? NO_JUMP : kJump();
604 p_f = code_label(reg, 0, 1);
605 p_t = code_label(reg, 1, 0);
606 kPatchtohere(fj);
608 int finalpos = kGetlabel(); /* position after whole expression */
609 patchlistaux(e.f, finalpos, reg, p_f);
610 patchlistaux(e.t, finalpos, reg, p_t);
612 e.init(Expdesc.VNONRELOC, reg);
615 private int code_label(int a, int b, int jump)
617 kGetlabel(); /* those instructions may be jump targets */
618 return kCodeABC(Lua.OP_LOADBOOL, a, b, jump);
622 * check whether list has any jump that do not produce a value
623 * (or produce an inverted value)
625 private boolean need_value(int list)
627 for (; list != NO_JUMP; list = getjump(list))
629 int i = getjumpcontrol(list);
630 int instr = f.code[i] ;
631 if (Lua.OPCODE(instr) != Lua.OP_TESTSET)
632 return true;
634 return false; /* not found */
637 private void freeexp(Expdesc e)
639 if (e.kind() == Expdesc.VNONRELOC)
641 freereg(e.info);
645 private void freereg(int reg)
647 if (!Lua.ISK(reg) && reg >= nactvar)
649 --freereg;
650 // assert reg == freereg;
654 int getcode(Expdesc e)
656 return f.code[e.info];
659 void setcode(Expdesc e, int code)
661 f.code[e.info] = code ;
665 /** Equivalent to searchvar from lparser.c */
666 int searchvar(String n)
668 // caution: descending loop (in emulation of PUC-Rio).
669 for (int i=nactvar-1; i >= 0; i--)
671 if (n.equals(getlocvar(i).varname))
672 return i;
674 return -1; // not found
677 void setarga(Expdesc e, int a)
679 int at = e.info;
680 int[] code = f.code;
681 code[at] = Lua.SETARG_A(code[at], a);
684 void setargb(Expdesc e, int b)
686 int at = e.info;
687 int[] code = f.code;
688 code[at] = Lua.SETARG_B(code[at], b);
691 void setargc(Expdesc e, int c)
693 int at = e.info;
694 int[] code = f.code;
695 code[at] = Lua.SETARG_C(code[at], c);
698 /** Equivalent to <code>luaK_getlabel</code>. */
699 int kGetlabel()
701 lasttarget = pc ;
702 return pc;
706 * Equivalent to <code>luaK_concat</code>.
707 * l1 was an int*, now passing back as result.
709 int kConcat(int l1, int l2)
711 if (l2 == NO_JUMP)
712 return l1;
713 else if (l1 == NO_JUMP)
714 return l2;
715 else
717 int list = l1;
718 int next;
719 while ((next = getjump(list)) != NO_JUMP) /* find last element */
720 list = next;
721 fixjump(list, l2);
722 return l1;
726 /** Equivalent to <code>luaK_patchlist</code>. */
727 void kPatchlist(int list, int target)
729 if (target == pc)
730 kPatchtohere(list);
731 else
733 //# assert target < pc
734 patchlistaux(list, target, Lua.NO_REG, target);
738 private void patchlistaux(int list, int vtarget, int reg,
739 int dtarget)
741 while (list != NO_JUMP)
743 int next = getjump(list);
744 if (patchtestreg(list, reg))
745 fixjump(list, vtarget);
746 else
747 fixjump(list, dtarget); /* jump to default target */
748 list = next;
752 private boolean patchtestreg(int node, int reg)
754 int i = getjumpcontrol(node);
755 int [] code = f.code ;
756 int instr = code[i] ;
757 if (Lua.OPCODE(instr) != Lua.OP_TESTSET)
758 return false; /* cannot patch other instructions */
759 if (reg != Lua.NO_REG && reg != Lua.ARGB(instr))
760 code[i] = Lua.SETARG_A(instr, reg);
761 else /* no register to put value or register already has the value */
762 code[i] = Lua.CREATE_ABC(Lua.OP_TEST, Lua.ARGB(instr), 0, Lua.ARGC(instr));
764 return true;
767 private int getjumpcontrol(int at)
769 int [] code = f.code ;
770 if (at >= 1 && testTMode(Lua.OPCODE(code[at-1])))
771 return at-1;
772 else
773 return at;
777 ** masks for instruction properties. The format is:
778 ** bits 0-1: op mode
779 ** bits 2-3: C arg mode
780 ** bits 4-5: B arg mode
781 ** bit 6: instruction set register A
782 ** bit 7: operator is a test
785 /** arg modes */
786 private static final int OP_ARG_N = 0 ;
787 private static final int OP_ARG_U = 1 ;
788 private static final int OP_ARG_R = 2 ;
789 private static final int OP_ARG_K = 3 ;
791 /** op modes */
792 private static final int iABC = 0 ;
793 private static final int iABx = 1 ;
794 private static final int iAsBx = 2 ;
796 static byte opmode(int t, int a, int b, int c, int m)
798 return (byte) ((t<<7) | (a<<6) | (b<<4) | (c<<2) | m) ;
801 private static final byte [] OPMODE = new byte []
803 /* T A B C mode opcode */
804 opmode(0, 1, OP_ARG_R, OP_ARG_N, iABC) /* OP_MOVE */
805 ,opmode(0, 1, OP_ARG_K, OP_ARG_N, iABx) /* OP_LOADK */
806 ,opmode(0, 1, OP_ARG_U, OP_ARG_U, iABC) /* OP_LOADBOOL */
807 ,opmode(0, 1, OP_ARG_R, OP_ARG_N, iABC) /* OP_LOADNIL */
808 ,opmode(0, 1, OP_ARG_U, OP_ARG_N, iABC) /* OP_GETUPVAL */
809 ,opmode(0, 1, OP_ARG_K, OP_ARG_N, iABx) /* OP_GETGLOBAL */
810 ,opmode(0, 1, OP_ARG_R, OP_ARG_K, iABC) /* OP_GETTABLE */
811 ,opmode(0, 0, OP_ARG_K, OP_ARG_N, iABx) /* OP_SETGLOBAL */
812 ,opmode(0, 0, OP_ARG_U, OP_ARG_N, iABC) /* OP_SETUPVAL */
813 ,opmode(0, 0, OP_ARG_K, OP_ARG_K, iABC) /* OP_SETTABLE */
814 ,opmode(0, 1, OP_ARG_U, OP_ARG_U, iABC) /* OP_NEWTABLE */
815 ,opmode(0, 1, OP_ARG_R, OP_ARG_K, iABC) /* OP_SELF */
816 ,opmode(0, 1, OP_ARG_K, OP_ARG_K, iABC) /* OP_ADD */
817 ,opmode(0, 1, OP_ARG_K, OP_ARG_K, iABC) /* OP_SUB */
818 ,opmode(0, 1, OP_ARG_K, OP_ARG_K, iABC) /* OP_MUL */
819 ,opmode(0, 1, OP_ARG_K, OP_ARG_K, iABC) /* OP_DIV */
820 ,opmode(0, 1, OP_ARG_K, OP_ARG_K, iABC) /* OP_MOD */
821 ,opmode(0, 1, OP_ARG_K, OP_ARG_K, iABC) /* OP_POW */
822 ,opmode(0, 1, OP_ARG_R, OP_ARG_N, iABC) /* OP_UNM */
823 ,opmode(0, 1, OP_ARG_R, OP_ARG_N, iABC) /* OP_NOT */
824 ,opmode(0, 1, OP_ARG_R, OP_ARG_N, iABC) /* OP_LEN */
825 ,opmode(0, 1, OP_ARG_R, OP_ARG_R, iABC) /* OP_CONCAT */
826 ,opmode(0, 0, OP_ARG_R, OP_ARG_N, iAsBx) /* OP_JMP */
827 ,opmode(1, 0, OP_ARG_K, OP_ARG_K, iABC) /* OP_EQ */
828 ,opmode(1, 0, OP_ARG_K, OP_ARG_K, iABC) /* OP_LT */
829 ,opmode(1, 0, OP_ARG_K, OP_ARG_K, iABC) /* OP_LE */
830 ,opmode(1, 1, OP_ARG_R, OP_ARG_U, iABC) /* OP_TEST */
831 ,opmode(1, 1, OP_ARG_R, OP_ARG_U, iABC) /* OP_TESTSET */
832 ,opmode(0, 1, OP_ARG_U, OP_ARG_U, iABC) /* OP_CALL */
833 ,opmode(0, 1, OP_ARG_U, OP_ARG_U, iABC) /* OP_TAILCALL */
834 ,opmode(0, 0, OP_ARG_U, OP_ARG_N, iABC) /* OP_RETURN */
835 ,opmode(0, 1, OP_ARG_R, OP_ARG_N, iAsBx) /* OP_FORLOOP */
836 ,opmode(0, 1, OP_ARG_R, OP_ARG_N, iAsBx) /* OP_FORPREP */
837 ,opmode(1, 0, OP_ARG_N, OP_ARG_U, iABC) /* OP_TFORLOOP */
838 ,opmode(0, 0, OP_ARG_U, OP_ARG_U, iABC) /* OP_SETLIST */
839 ,opmode(0, 0, OP_ARG_N, OP_ARG_N, iABC) /* OP_CLOSE */
840 ,opmode(0, 1, OP_ARG_U, OP_ARG_N, iABx) /* OP_CLOSURE */
841 ,opmode(0, 1, OP_ARG_U, OP_ARG_N, iABC) /* OP_VARARG */
844 private boolean testTMode(int m)
846 return (OPMODE[m] & (1<<7)) != 0 ;
849 /** Equivalent to <code>luaK_patchtohere</code>. */
850 void kPatchtohere(int list)
852 kGetlabel();
853 jpc = kConcat(jpc, list);
856 private void fixjump(int at, int dest)
858 int jmp = f.code[at];
859 int offset = dest-(at+1);
860 //# assert dest != NO_JUMP
861 if (Math.abs(offset) > Lua.MAXARG_sBx)
862 ls.xSyntaxerror("control structure too long");
863 f.code[at] = Lua.SETARG_sBx(jmp, offset);
866 private int getjump(int at)
868 int offset = Lua.ARGsBx(f.code[at]);
869 if (offset == NO_JUMP) /* point to itself represents end of list */
870 return NO_JUMP; /* end of list */
871 else
872 return (at+1)+offset; /* turn offset into absolute position */
875 /** Equivalent to <code>luaK_jump</code>. */
876 int kJump()
878 int old_jpc = jpc; /* save list of jumps to here */
879 jpc = NO_JUMP;
880 int j = kCodeAsBx(Lua.OP_JMP, 0, NO_JUMP);
881 j = kConcat(j, old_jpc); /* keep them on hold */
882 return j;
885 /** Equivalent to <code>luaK_storevar</code>. */
886 void kStorevar(Expdesc var, Expdesc ex)
888 switch (var.k)
890 case Expdesc.VLOCAL:
892 freeexp(ex);
893 exp2reg(ex, var.info);
894 return;
896 case Expdesc.VUPVAL:
898 int e = kExp2anyreg(ex);
899 kCodeABC(Lua.OP_SETUPVAL, e, var.info, 0);
900 break;
902 case Expdesc.VGLOBAL:
904 int e = kExp2anyreg(ex);
905 kCodeABx(Lua.OP_SETGLOBAL, e, var.info);
906 break;
908 case Expdesc.VINDEXED:
910 int e = kExp2RK(ex);
911 kCodeABC(Lua.OP_SETTABLE, var.info, var.aux, e);
912 break;
914 default:
916 /* invalid var kind to store */
917 //# assert false
918 break;
921 freeexp(ex);
924 /** Equivalent to <code>luaK_indexed</code>. */
925 void kIndexed(Expdesc t, Expdesc k)
927 t.aux = kExp2RK(k);
928 t.k = Expdesc.VINDEXED;
931 /** Equivalent to <code>luaK_exp2RK</code>. */
932 int kExp2RK(Expdesc e)
934 kExp2val(e);
935 switch (e.k)
937 case Expdesc.VKNUM:
938 case Expdesc.VTRUE:
939 case Expdesc.VFALSE:
940 case Expdesc.VNIL:
941 if (nk <= Lua.MAXINDEXRK) /* constant fit in RK operand? */
943 e.info = (e.k == Expdesc.VNIL) ? nilK() :
944 (e.k == Expdesc.VKNUM) ? kNumberK(e.nval) :
945 boolK(e.k == Expdesc.VTRUE);
946 e.k = Expdesc.VK;
947 return e.info | Lua.BITRK;
949 else break;
951 case Expdesc.VK:
952 if (e.info <= Lua.MAXINDEXRK) /* constant fit in argC? */
953 return e.info | Lua.BITRK;
954 else break;
956 default: break;
958 /* not a constant in the right range: put it in a register */
959 return kExp2anyreg(e);
962 /** Equivalent to <code>luaK_exp2val</code>. */
963 void kExp2val(Expdesc e)
965 if (e.hasjumps())
966 kExp2anyreg(e);
967 else
968 kDischargevars(e);
971 private int boolK(boolean b)
973 return addk(Lua.valueOfBoolean(b));
976 private int nilK()
978 return addk(Lua.NIL);
981 /** Equivalent to <code>luaK_goiffalse</code>. */
982 void kGoiffalse(Expdesc e)
984 int lj; /* pc of last jump */
985 kDischargevars(e);
986 switch (e.k)
988 case Expdesc.VNIL:
989 case Expdesc.VFALSE:
990 lj = NO_JUMP; /* always false; do nothing */
991 break;
993 case Expdesc.VTRUE:
994 lj = kJump(); /* always jump */
995 break;
997 case Expdesc.VJMP:
998 lj = e.info;
999 break;
1001 default:
1002 lj = jumponcond(e, true);
1003 break;
1005 e.t = kConcat(e.t, lj); /* insert last jump in `t' list */
1006 kPatchtohere(e.f);
1007 e.f = NO_JUMP;
1010 /** Equivalent to <code>luaK_goiftrue</code>. */
1011 void kGoiftrue(Expdesc e)
1013 int lj; /* pc of last jump */
1014 kDischargevars(e);
1015 switch (e.k)
1017 case Expdesc.VK:
1018 case Expdesc.VKNUM:
1019 case Expdesc.VTRUE:
1020 lj = NO_JUMP; /* always true; do nothing */
1021 break;
1023 case Expdesc.VFALSE:
1024 lj = kJump(); /* always jump */
1025 break;
1027 case Expdesc.VJMP:
1028 invertjump(e);
1029 lj = e.info;
1030 break;
1032 default:
1033 lj = jumponcond(e, false);
1034 break;
1036 e.f = kConcat(e.f, lj); /* insert last jump in `f' list */
1037 kPatchtohere(e.t);
1038 e.t = NO_JUMP;
1041 private void invertjump(Expdesc e)
1043 int at = getjumpcontrol(e.info);
1044 int [] code = f.code ;
1045 int instr = code[at] ;
1046 //# assert testTMode(Lua.OPCODE(instr)) && Lua.OPCODE(instr) != Lua.OP_TESTSET && Lua.OPCODE(instr) != Lua.OP_TEST
1047 code[at] = Lua.SETARG_A(instr, (Lua.ARGA(instr) == 0 ? 1 : 0));
1051 private int jumponcond(Expdesc e, boolean cond)
1053 if (e.k == Expdesc.VRELOCABLE)
1055 int ie = getcode(e);
1056 if (Lua.OPCODE(ie) == Lua.OP_NOT)
1058 pc--; /* remove previous OP_NOT */
1059 return condjump(Lua.OP_TEST, Lua.ARGB(ie), 0, cond ? 0 : 1);
1061 /* else go through */
1063 discharge2anyreg(e);
1064 freeexp(e);
1065 return condjump(Lua.OP_TESTSET, Lua.NO_REG, e.info, cond ? 1 : 0);
1068 private int condjump(int op, int a, int b, int c)
1070 kCodeABC(op, a, b, c);
1071 return kJump();
1074 private void discharge2anyreg(Expdesc e)
1076 if (e.k != Expdesc.VNONRELOC)
1078 kReserveregs(1);
1079 discharge2reg(e, freereg-1);
1084 void kSelf(Expdesc e, Expdesc key)
1086 kExp2anyreg(e);
1087 freeexp(e);
1088 int func = freereg;
1089 kReserveregs(2);
1090 kCodeABC(Lua.OP_SELF, func, e.info, kExp2RK(key));
1091 freeexp(key);
1092 e.info = func;
1093 e.k = Expdesc.VNONRELOC;
1096 void kSetlist(int base, int nelems, int tostore)
1098 int c = (nelems - 1) / Lua.LFIELDS_PER_FLUSH + 1;
1099 int b = (tostore == Lua.MULTRET) ? 0 : tostore;
1100 //# assert tostore != 0
1101 if (c <= Lua.MAXARG_C)
1102 kCodeABC(Lua.OP_SETLIST, base, b, c);
1103 else
1105 kCodeABC(Lua.OP_SETLIST, base, b, 0);
1106 kCode(c, ls.lastline);
1108 freereg = base + 1; /* free registers with list values */
1112 void codecomp(int op, boolean cond, Expdesc e1, Expdesc e2)
1114 int o1 = kExp2RK(e1);
1115 int o2 = kExp2RK(e2);
1116 freeexp(e2);
1117 freeexp(e1);
1118 if ((!cond) && op != Lua.OP_EQ)
1120 /* exchange args to replace by `<' or `<=' */
1121 int temp = o1; o1 = o2; o2 = temp; /* o1 <==> o2 */
1122 cond = true;
1124 e1.info = condjump(op, (cond ? 1 : 0), o1, o2);
1125 e1.k = Expdesc.VJMP;
1128 void markupval(int level)
1130 BlockCnt b = this.bl;
1131 while (b != null && b.nactvar > level)
1132 b = b.previous;
1133 if (b != null)
1134 b.upval = true;