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).
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.
27 import java
.util
.Hashtable
;
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
37 /** See NO_JUMP in lcode.h. */
38 static final int NO_JUMP
= -1;
40 /** Proto object for this function. */
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. */
58 /** chain of current blocks */
59 BlockCnt bl
; // = null;
61 /** next position to code. */
64 /** pc of last jump target. */
67 /** List of pending jumps to <var>pc</var>. */
70 /** First free register. */
73 /** number of elements in <var>k</var>. */
76 /** number of elements in <var>p</var>. */
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
];
92 * Constructor. Much of this is taken from <code>open_func</code> in
93 * <code>lparser.c</code>.
97 f
= new Proto(ls
.source
, 2); // default value for maxstacksize=2
100 // prev = ls.linkfs(this);
103 /** Equivalent to <code>close_func</code> from <code>lparser.c</code>. */
110 f
.closeLocvars(nlocvars
);
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
)
146 // Put new instruction in code array.
147 f
.codeAppend(L
, pc
, i
, line
);
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
)
180 e
.setKind(Expdesc
.VNONRELOC
);
183 e
.reloc(kCodeABC(Lua
.OP_GETUPVAL
, 0, e
.info
, 0));
185 case Expdesc
.VGLOBAL
:
186 e
.reloc(kCodeABx(Lua
.OP_GETGLOBAL
, 0, e
.info
));
188 case Expdesc
.VINDEXED
:
191 e
.reloc(kCodeABC(Lua
.OP_GETTABLE
, 0, e
.info
, e
.aux
));
193 case Expdesc
.VVARARG
:
198 break; // there is one value available (somewhere)
202 /** Equivalent to luaK_exp2anyreg. */
203 int kExp2anyreg(Expdesc e
)
206 if (e
.k
== Expdesc
.VNONRELOC
)
212 if (e
.info
>= nactvar
) // reg is not a local?
214 exp2reg(e
, e
.info
); // put value on it
218 kExp2nextreg(e
); // default
222 /** Equivalent to luaK_exp2nextreg. */
223 void kExp2nextreg(Expdesc e
)
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
)
248 case Syntax
.OPR_CONCAT
:
249 kExp2nextreg(v
); /* operand must be on the `stack' */
259 private boolean isnumeral(Expdesc e
)
261 return e
.k
== Expdesc
.VKNUM
&&
266 /** Equivalent to luaK_nil. */
267 void kNil(int from
, int n
)
270 if (pc
> lasttarget
) /* no jumps to current position? */
272 if (pc
== 0) /* function start? */
273 return; /* positions are already clean */
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? */
283 f
.code
[previous
] = Lua
.SETARG_B(instr
, from
+n
-1);
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
)
303 /* list must be closed */
304 //# assert e1.t == NO_JUMP
306 e2
.f
= kConcat(e2
.f
, e1
.f
);
311 /* list must be closed */
312 //# assert e1.f == NO_JUMP
314 e2
.t
= kConcat(e2
.t
, e1
.t
);
318 case Syntax
.OPR_CONCAT
:
320 if (e2
.k
== Expdesc
.VRELOCABLE
&& Lua
.OPCODE(getcode(e2
)) == Lua
.OP_CONCAT
)
322 //# assert e1.info == Lua.ARGB(getcode(e2))-1
324 setcode(e2
, Lua
.SETARG_B(getcode(e2
), e1
.info
));
330 kExp2nextreg(e2
); /* operand must be on the 'stack' */
331 codearith(Lua
.OP_CONCAT
, e1
, e2
);
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;
352 /** Equivalent to luaK_prefix. */
353 void kPrefix(int op
, Expdesc e
)
355 Expdesc e2
= new Expdesc(Expdesc
.VKNUM
, 0);
358 case Syntax
.OPR_MINUS
:
359 if (e
.kind() == Expdesc
.VK
)
363 codearith(Lua
.OP_UNM
, e
, e2
);
370 codearith(Lua
.OP_LEN
, e
, e2
);
373 throw new IllegalArgumentException();
377 /** Equivalent to luaK_reserveregs. */
378 void kReserveregs(int 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
)
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);
425 /** Equivalent to luaK_stringK. */
426 int kStringK(String s
)
428 return addk(s
.intern());
431 private int addk(Object o
)
434 Object v
= h
.get(hash
);
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
));
446 private void codearith(int op
, Expdesc e1
, Expdesc e2
)
448 if (constfolding(op
, e1
, e2
))
452 int o1
= kExp2RK(e1
);
453 int o2
= (op
!= Lua
.OP_UNM
&& op
!= Lua
.OP_LEN
) ?
kExp2RK(e2
) : 0;
456 e1
.info
= kCodeABC(op
, 0, o1
, o2
);
457 e1
.k
= Expdesc
.VRELOCABLE
;
461 private boolean constfolding(int op
, Expdesc e1
, Expdesc e2
)
464 if (!isnumeral(e1
) || !isnumeral(e2
))
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;
475 return false; /* do not attempt to divide by 0 */
480 return false; /* do not attempt to divide by 0 */
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' */
491 return false; /* do not attempt to produce NaN */
496 private void codenot(Expdesc e
)
509 e
.k
= Expdesc
.VFALSE
;
516 case Expdesc
.VRELOCABLE
:
517 case Expdesc
.VNONRELOC
:
520 e
.info
= kCodeABC(Lua
.OP_NOT
, 0, e
.info
, 0);
521 e
.k
= Expdesc
.VRELOCABLE
;
528 /* interchange true and false lists */
529 { int temp
= e
.f
; e
.f
= e
.t
; e
.t
= temp
; }
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
);
547 private void discharge2reg(Expdesc e
, int reg
)
558 kCodeABC(Lua
.OP_LOADBOOL
, reg
, (e
.k
== Expdesc
.VTRUE ?
1 : 0), 0);
562 kCodeABx(Lua
.OP_LOADK
, reg
, e
.info
);
566 kCodeABx(Lua
.OP_LOADK
, reg
, kNumberK(e
.nval
));
569 case Expdesc
.VRELOCABLE
:
573 case Expdesc
.VNONRELOC
:
576 kCodeABC(Lua
.OP_MOVE
, reg
, e
.info
, 0);
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 */
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);
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
)
634 return false; /* not found */
637 private void freeexp(Expdesc e
)
639 if (e
.kind() == Expdesc
.VNONRELOC
)
645 private void freereg(int reg
)
647 if (!Lua
.ISK(reg
) && reg
>= nactvar
)
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
))
674 return -1; // not found
677 void setarga(Expdesc e
, int a
)
681 code
[at
] = Lua
.SETARG_A(code
[at
], a
);
684 void setargb(Expdesc e
, int b
)
688 code
[at
] = Lua
.SETARG_B(code
[at
], b
);
691 void setargc(Expdesc e
, int c
)
695 code
[at
] = Lua
.SETARG_C(code
[at
], c
);
698 /** Equivalent to <code>luaK_getlabel</code>. */
706 * Equivalent to <code>luaK_concat</code>.
707 * l1 was an int*, now passing back as result.
709 int kConcat(int l1
, int l2
)
713 else if (l1
== NO_JUMP
)
719 while ((next
= getjump(list
)) != NO_JUMP
) /* find last element */
726 /** Equivalent to <code>luaK_patchlist</code>. */
727 void kPatchlist(int list
, int target
)
733 //# assert target < pc
734 patchlistaux(list
, target
, Lua
.NO_REG
, target
);
738 private void patchlistaux(int list
, int vtarget
, int reg
,
741 while (list
!= NO_JUMP
)
743 int next
= getjump(list
);
744 if (patchtestreg(list
, reg
))
745 fixjump(list
, vtarget
);
747 fixjump(list
, dtarget
); /* jump to default target */
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
));
767 private int getjumpcontrol(int at
)
769 int [] code
= f
.code
;
770 if (at
>= 1 && testTMode(Lua
.OPCODE(code
[at
-1])))
777 ** masks for instruction properties. The format is:
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
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 ;
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
)
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 */
872 return (at
+1)+offset
; /* turn offset into absolute position */
875 /** Equivalent to <code>luaK_jump</code>. */
878 int old_jpc
= jpc
; /* save list of jumps to here */
880 int j
= kCodeAsBx(Lua
.OP_JMP
, 0, NO_JUMP
);
881 j
= kConcat(j
, old_jpc
); /* keep them on hold */
885 /** Equivalent to <code>luaK_storevar</code>. */
886 void kStorevar(Expdesc var
, Expdesc ex
)
893 exp2reg(ex
, var
.info
);
898 int e
= kExp2anyreg(ex
);
899 kCodeABC(Lua
.OP_SETUPVAL
, e
, var
.info
, 0);
902 case Expdesc
.VGLOBAL
:
904 int e
= kExp2anyreg(ex
);
905 kCodeABx(Lua
.OP_SETGLOBAL
, e
, var
.info
);
908 case Expdesc
.VINDEXED
:
911 kCodeABC(Lua
.OP_SETTABLE
, var
.info
, var
.aux
, e
);
916 /* invalid var kind to store */
924 /** Equivalent to <code>luaK_indexed</code>. */
925 void kIndexed(Expdesc t
, Expdesc k
)
928 t
.k
= Expdesc
.VINDEXED
;
931 /** Equivalent to <code>luaK_exp2RK</code>. */
932 int kExp2RK(Expdesc e
)
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
);
947 return e
.info
| Lua
.BITRK
;
952 if (e
.info
<= Lua
.MAXINDEXRK
) /* constant fit in argC? */
953 return e
.info
| Lua
.BITRK
;
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
)
971 private int boolK(boolean b
)
973 return addk(Lua
.valueOfBoolean(b
));
978 return addk(Lua
.NIL
);
981 /** Equivalent to <code>luaK_goiffalse</code>. */
982 void kGoiffalse(Expdesc e
)
984 int lj
; /* pc of last jump */
990 lj
= NO_JUMP
; /* always false; do nothing */
994 lj
= kJump(); /* always jump */
1002 lj
= jumponcond(e
, true);
1005 e
.t
= kConcat(e
.t
, lj
); /* insert last jump in `t' list */
1010 /** Equivalent to <code>luaK_goiftrue</code>. */
1011 void kGoiftrue(Expdesc e
)
1013 int lj
; /* pc of last jump */
1020 lj
= NO_JUMP
; /* always true; do nothing */
1023 case Expdesc
.VFALSE
:
1024 lj
= kJump(); /* always jump */
1033 lj
= jumponcond(e
, false);
1036 e
.f
= kConcat(e
.f
, lj
); /* insert last jump in `f' list */
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
);
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
);
1074 private void discharge2anyreg(Expdesc e
)
1076 if (e
.k
!= Expdesc
.VNONRELOC
)
1079 discharge2reg(e
, freereg
-1);
1084 void kSelf(Expdesc e
, Expdesc key
)
1090 kCodeABC(Lua
.OP_SELF
, func
, e
.info
, kExp2RK(key
));
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
);
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
);
1118 if ((!cond
) && op
!= Lua
.OP_EQ
)
1120 /* exchange args to replace by `<' or `<=' */
1121 int temp
= o1
; o1
= o2
; o2
= temp
; /* o1 <==> o2 */
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
)