2 ** $Id: lvm.c,v 1.30 1998/06/11 18:21:37 roberto Exp $
4 ** See Copyright Notice in lua.h
26 #define strcoll(a,b) strcmp(a,b)
30 #define skip_word(pc) (pc+=2)
31 #define get_word(pc) ((*(pc)<<8)+(*((pc)+1)))
32 #define next_word(pc) (pc+=2, get_word(pc-2))
35 /* Extra stack size to run a function: LUA_T_LINE(1), TM calls(2), ... */
40 static TaggedString
*strconc (TaggedString
*l
, TaggedString
*r
)
42 size_t nl
= l
->u
.s
.len
;
43 size_t nr
= r
->u
.s
.len
;
44 char *buffer
= luaL_openspace(nl
+nr
+1);
45 memcpy(buffer
, l
->str
, nl
);
46 memcpy(buffer
+nl
, r
->str
, nr
);
47 return luaS_newlstr(buffer
, nl
+nr
);
51 int luaV_tonumber (TObject
*obj
)
55 if (ttype(obj
) != LUA_T_STRING
)
57 else if (sscanf(svalue(obj
), "%lf %c",&t
, &c
) == 1) {
58 nvalue(obj
) = (real
)t
;
59 ttype(obj
) = LUA_T_NUMBER
;
67 int luaV_tostring (TObject
*obj
)
69 if (ttype(obj
) != LUA_T_NUMBER
)
75 if ((real
)(-MAX_INT
) <= f
&& f
<= (real
)MAX_INT
&& (real
)(i
=(int)f
) == f
)
78 sprintf (s
, NUMBER_FMT
, nvalue(obj
));
79 tsvalue(obj
) = luaS_new(s
);
80 ttype(obj
) = LUA_T_STRING
;
86 void luaV_closure (int nelems
)
89 struct Stack
*S
= &L
->stack
;
90 Closure
*c
= luaF_newclosure(nelems
);
91 c
->consts
[0] = *(S
->top
-1);
92 memcpy(&c
->consts
[1], S
->top
-(nelems
+1), nelems
*sizeof(TObject
));
94 ttype(S
->top
-1) = LUA_T_CLOSURE
;
95 (S
->top
-1)->value
.cl
= c
;
101 ** Function to index a table.
102 ** Receives the table at top-2 and the index at top-1.
104 void luaV_gettable (void)
106 struct Stack
*S
= &L
->stack
;
108 if (ttype(S
->top
-2) != LUA_T_ARRAY
) /* not a table, get "gettable" method */
109 im
= luaT_getimbyObj(S
->top
-2, IM_GETTABLE
);
110 else { /* object is a table... */
111 int tg
= (S
->top
-2)->value
.a
->htag
;
112 im
= luaT_getim(tg
, IM_GETTABLE
);
113 if (ttype(im
) == LUA_T_NIL
) { /* and does not have a "gettable" method */
114 TObject
*h
= luaH_get(avalue(S
->top
-2), S
->top
-1);
115 if (h
!= NULL
&& ttype(h
) != LUA_T_NIL
) {
119 else if (ttype(im
=luaT_getim(tg
, IM_INDEX
)) != LUA_T_NIL
)
120 luaD_callTM(im
, 2, 1);
123 ttype(S
->top
-1) = LUA_T_NIL
;
127 /* else it has a "gettable" method, go through to next command */
129 /* object is not a table, or it has a "gettable" method */
130 if (ttype(im
) != LUA_T_NIL
)
131 luaD_callTM(im
, 2, 1);
133 lua_error("indexed expression not a table");
138 ** Function to store indexed based on values at the stack.top
139 ** mode = 0: raw store (without tag methods)
140 ** mode = 1: normal store (with tag methods)
141 ** mode = 2: "deep L->stack.stack" store (with tag methods)
143 void luaV_settable (TObject
*t
, int mode
)
145 struct Stack
*S
= &L
->stack
;
146 TObject
*im
= (mode
== 0) ? NULL
: luaT_getimbyObj(t
, IM_SETTABLE
);
147 if (ttype(t
) == LUA_T_ARRAY
&& (im
== NULL
|| ttype(im
) == LUA_T_NIL
)) {
148 TObject
*h
= luaH_set(avalue(t
), t
+1);
150 S
->top
-= (mode
== 2) ? 1 : 3;
152 else { /* object is not a table, and/or has a specific "settable" method */
153 if (im
&& ttype(im
) != LUA_T_NIL
) {
155 *(S
->top
+1) = *(L
->stack
.top
-1);
158 S
->top
+= 2; /* WARNING: caller must assure stack space */
160 luaD_callTM(im
, 3, 0);
163 lua_error("indexed expression not a table");
168 void luaV_getglobal (TaggedString
*ts
)
170 /* WARNING: caller must assure stack space */
171 TObject
*value
= &ts
->u
.s
.globalval
;
172 TObject
*im
= luaT_getimbyObj(value
, IM_GETGLOBAL
);
173 if (ttype(im
) == LUA_T_NIL
) { /* default behavior */
174 *L
->stack
.top
++ = *value
;
177 struct Stack
*S
= &L
->stack
;
178 ttype(S
->top
) = LUA_T_STRING
;
179 tsvalue(S
->top
) = ts
;
182 luaD_callTM(im
, 2, 1);
187 void luaV_setglobal (TaggedString
*ts
)
189 TObject
*oldvalue
= &ts
->u
.s
.globalval
;
190 TObject
*im
= luaT_getimbyObj(oldvalue
, IM_SETGLOBAL
);
191 if (ttype(im
) == LUA_T_NIL
) /* default behavior */
192 luaS_rawsetglobal(ts
, --L
->stack
.top
);
194 /* WARNING: caller must assure stack space */
195 struct Stack
*S
= &L
->stack
;
196 TObject newvalue
= *(S
->top
-1);
197 ttype(S
->top
-1) = LUA_T_STRING
;
198 tsvalue(S
->top
-1) = ts
;
199 *S
->top
++ = *oldvalue
;
200 *S
->top
++ = newvalue
;
201 luaD_callTM(im
, 3, 0);
206 static void call_binTM (IMS event
, char *msg
)
208 TObject
*im
= luaT_getimbyObj(L
->stack
.top
-2, event
);/* try first operand */
209 if (ttype(im
) == LUA_T_NIL
) {
210 im
= luaT_getimbyObj(L
->stack
.top
-1, event
); /* try second operand */
211 if (ttype(im
) == LUA_T_NIL
) {
212 im
= luaT_getim(0, event
); /* try a 'global' i.m. */
213 if (ttype(im
) == LUA_T_NIL
)
217 lua_pushstring(luaT_eventname
[event
]);
218 luaD_callTM(im
, 3, 1);
222 static void call_arith (IMS event
)
224 call_binTM(event
, "unexpected type in arithmetic operation");
228 static int strcomp (char *l
, long ll
, char *r
, long lr
)
231 long temp
= strcoll(l
, r
);
232 if (temp
!= 0) return temp
;
233 /* strings are equal up to a '\0' */
234 temp
= strlen(l
); /* index of first '\0' in both strings */
235 if (temp
== ll
) /* l is finished? */
236 return (temp
== lr
) ? 0 : -1; /* l is equal or smaller than r */
237 else if (temp
== lr
) /* r is finished? */
238 return 1; /* l is greater than r (because l is not finished) */
239 /* both strings longer than temp; go on comparing (after the '\0') */
241 l
+= temp
; ll
-= temp
; r
+= temp
; lr
-= temp
;
245 static void comparison (lua_Type ttype_less
, lua_Type ttype_equal
,
246 lua_Type ttype_great
, IMS op
)
248 struct Stack
*S
= &L
->stack
;
249 TObject
*l
= S
->top
-2;
250 TObject
*r
= S
->top
-1;
252 if (ttype(l
) == LUA_T_NUMBER
&& ttype(r
) == LUA_T_NUMBER
)
253 result
= (nvalue(l
) < nvalue(r
)) ? -1 : (nvalue(l
) == nvalue(r
)) ? 0 : 1;
254 else if (ttype(l
) == LUA_T_STRING
&& ttype(r
) == LUA_T_STRING
)
255 result
= strcomp(svalue(l
), tsvalue(l
)->u
.s
.len
,
256 svalue(r
), tsvalue(r
)->u
.s
.len
);
258 call_binTM(op
, "unexpected type in comparison");
262 nvalue(S
->top
-1) = 1;
263 ttype(S
->top
-1) = (result
< 0) ? ttype_less
:
264 (result
== 0) ? ttype_equal
: ttype_great
;
268 void luaV_pack (StkId firstel
, int nvararg
, TObject
*tab
)
270 TObject
*firstelem
= L
->stack
.stack
+firstel
;
272 if (nvararg
< 0) nvararg
= 0;
273 avalue(tab
) = luaH_new(nvararg
+1); /* +1 for field 'n' */
274 ttype(tab
) = LUA_T_ARRAY
;
275 for (i
=0; i
<nvararg
; i
++) {
277 ttype(&index
) = LUA_T_NUMBER
;
278 nvalue(&index
) = i
+1;
279 *(luaH_set(avalue(tab
), &index
)) = *(firstelem
+i
);
281 /* store counter in field "n" */ {
282 TObject index
, extra
;
283 ttype(&index
) = LUA_T_STRING
;
284 tsvalue(&index
) = luaS_new("n");
285 ttype(&extra
) = LUA_T_NUMBER
;
286 nvalue(&extra
) = nvararg
;
287 *(luaH_set(avalue(tab
), &index
)) = extra
;
292 static void adjust_varargs (StkId first_extra_arg
)
295 luaV_pack(first_extra_arg
,
296 (L
->stack
.top
-L
->stack
.stack
)-first_extra_arg
, &arg
);
297 luaD_adjusttop(first_extra_arg
);
298 *L
->stack
.top
++ = arg
;
304 ** Execute the given opcode, until a RET. Parameters are between
305 ** [stack+base,top). Returns n such that the the results are between
308 StkId
luaV_execute (Closure
*cl
, TProtoFunc
*tf
, StkId base
)
310 struct Stack
*S
= &L
->stack
; /* to optimize */
312 TObject
*consts
= tf
->consts
;
314 luaD_callHook(base
, tf
, 0);
315 luaD_checkstack((*pc
++)+EXTRA_STACK
);
316 if (*pc
< ZEROVARARG
)
317 luaD_adjusttop(base
+*(pc
++));
320 adjust_varargs(base
+(*pc
++)-ZEROVARARG
);
324 switch ((OpCode
)(aux
= *pc
++)) {
327 ttype(S
->top
++) = LUA_T_NIL
;
333 ttype(S
->top
++) = LUA_T_NIL
;
338 aux
= *pc
++; goto pushnumber
;
341 aux
= next_word(pc
); goto pushnumber
;
343 case PUSHNUMBER0
: case PUSHNUMBER1
: case PUSHNUMBER2
:
346 ttype(S
->top
) = LUA_T_NUMBER
;
347 nvalue(S
->top
) = aux
;
352 aux
= *pc
++; goto pushlocal
;
354 case PUSHLOCAL0
: case PUSHLOCAL1
: case PUSHLOCAL2
: case PUSHLOCAL3
:
355 case PUSHLOCAL4
: case PUSHLOCAL5
: case PUSHLOCAL6
: case PUSHLOCAL7
:
358 *S
->top
++ = *((S
->stack
+base
) + aux
);
362 aux
= next_word(pc
); goto getglobal
;
365 aux
= *pc
++; goto getglobal
;
367 case GETGLOBAL0
: case GETGLOBAL1
: case GETGLOBAL2
: case GETGLOBAL3
:
368 case GETGLOBAL4
: case GETGLOBAL5
: case GETGLOBAL6
: case GETGLOBAL7
:
371 luaV_getglobal(tsvalue(&consts
[aux
]));
379 aux
= next_word(pc
); goto getdotted
;
382 aux
= *pc
++; goto getdotted
;
384 case GETDOTTED0
: case GETDOTTED1
: case GETDOTTED2
: case GETDOTTED3
:
385 case GETDOTTED4
: case GETDOTTED5
: case GETDOTTED6
: case GETDOTTED7
:
388 *S
->top
++ = consts
[aux
];
393 aux
= next_word(pc
); goto pushself
;
396 aux
= *pc
++; goto pushself
;
398 case PUSHSELF0
: case PUSHSELF1
: case PUSHSELF2
: case PUSHSELF3
:
399 case PUSHSELF4
: case PUSHSELF5
: case PUSHSELF6
: case PUSHSELF7
:
402 TObject receiver
= *(S
->top
-1);
403 *S
->top
++ = consts
[aux
];
405 *S
->top
++ = receiver
;
410 aux
= next_word(pc
); goto pushconstant
;
413 aux
= *pc
++; goto pushconstant
;
415 case PUSHCONSTANT0
: case PUSHCONSTANT1
: case PUSHCONSTANT2
:
416 case PUSHCONSTANT3
: case PUSHCONSTANT4
: case PUSHCONSTANT5
:
417 case PUSHCONSTANT6
: case PUSHCONSTANT7
:
418 aux
-= PUSHCONSTANT0
;
420 *S
->top
++ = consts
[aux
];
424 aux
= *pc
++; goto pushupvalue
;
426 case PUSHUPVALUE0
: case PUSHUPVALUE1
:
429 *S
->top
++ = cl
->consts
[aux
+1];
433 aux
= *pc
++; goto setlocal
;
435 case SETLOCAL0
: case SETLOCAL1
: case SETLOCAL2
: case SETLOCAL3
:
436 case SETLOCAL4
: case SETLOCAL5
: case SETLOCAL6
: case SETLOCAL7
:
439 *((S
->stack
+base
) + aux
) = *(--S
->top
);
443 aux
= next_word(pc
); goto setglobal
;
446 aux
= *pc
++; goto setglobal
;
448 case SETGLOBAL0
: case SETGLOBAL1
: case SETGLOBAL2
: case SETGLOBAL3
:
449 case SETGLOBAL4
: case SETGLOBAL5
: case SETGLOBAL6
: case SETGLOBAL7
:
452 luaV_setglobal(tsvalue(&consts
[aux
]));
456 luaV_settable(S
->top
-3, 1);
460 luaV_settable(S
->top
-3-(*pc
++), 2);
464 aux
= next_word(pc
); aux
*= LFIELDS_PER_FLUSH
; goto setlist
;
467 aux
= *(pc
++) * LFIELDS_PER_FLUSH
; goto setlist
;
473 TObject
*arr
= S
->top
-n
-1;
475 ttype(S
->top
) = LUA_T_NUMBER
;
476 nvalue(S
->top
) = n
+aux
;
477 *(luaH_set(avalue(arr
), S
->top
)) = *(S
->top
-1);
484 aux
= 0; goto setmap
;
489 TObject
*arr
= S
->top
-(2*aux
)-3;
491 *(luaH_set(avalue(arr
), S
->top
-2)) = *(S
->top
-1);
498 aux
= *pc
++; goto pop
;
500 case POP0
: case POP1
:
507 aux
= next_word(pc
); goto createarray
;
509 case CREATEARRAY0
: case CREATEARRAY1
:
510 aux
-= CREATEARRAY0
; goto createarray
;
516 avalue(S
->top
) = luaH_new(aux
);
517 ttype(S
->top
) = LUA_T_ARRAY
;
521 case EQOP
: case NEQOP
: {
522 int res
= luaO_equalObj(S
->top
-2, S
->top
-1);
524 if (aux
== NEQOP
) res
= !res
;
525 ttype(S
->top
-1) = res
? LUA_T_NUMBER
: LUA_T_NIL
;
526 nvalue(S
->top
-1) = 1;
531 comparison(LUA_T_NUMBER
, LUA_T_NIL
, LUA_T_NIL
, IM_LT
);
535 comparison(LUA_T_NUMBER
, LUA_T_NUMBER
, LUA_T_NIL
, IM_LE
);
539 comparison(LUA_T_NIL
, LUA_T_NIL
, LUA_T_NUMBER
, IM_GT
);
543 comparison(LUA_T_NIL
, LUA_T_NUMBER
, LUA_T_NUMBER
, IM_GE
);
547 TObject
*l
= S
->top
-2;
548 TObject
*r
= S
->top
-1;
549 if (tonumber(r
) || tonumber(l
))
552 nvalue(l
) += nvalue(r
);
559 TObject
*l
= S
->top
-2;
560 TObject
*r
= S
->top
-1;
561 if (tonumber(r
) || tonumber(l
))
564 nvalue(l
) -= nvalue(r
);
571 TObject
*l
= S
->top
-2;
572 TObject
*r
= S
->top
-1;
573 if (tonumber(r
) || tonumber(l
))
576 nvalue(l
) *= nvalue(r
);
583 TObject
*l
= S
->top
-2;
584 TObject
*r
= S
->top
-1;
585 if (tonumber(r
) || tonumber(l
))
588 nvalue(l
) /= nvalue(r
);
595 call_binTM(IM_POW
, "undefined operation");
599 TObject
*l
= S
->top
-2;
600 TObject
*r
= S
->top
-1;
601 if (tostring(l
) || tostring(r
))
602 call_binTM(IM_CONCAT
, "unexpected type for concatenation");
604 tsvalue(l
) = strconc(tsvalue(l
), tsvalue(r
));
612 if (tonumber(S
->top
-1)) {
613 ttype(S
->top
) = LUA_T_NIL
;
618 nvalue(S
->top
-1) = - nvalue(S
->top
-1);
623 (ttype(S
->top
-1) == LUA_T_NIL
) ? LUA_T_NUMBER
: LUA_T_NIL
;
624 nvalue(S
->top
-1) = 1;
628 aux
= next_word(pc
); goto ontjmp
;
633 if (ttype(S
->top
-1) != LUA_T_NIL
) pc
+= aux
;
638 aux
= next_word(pc
); goto onfjmp
;
643 if (ttype(S
->top
-1) == LUA_T_NIL
) pc
+= aux
;
648 aux
= next_word(pc
); goto jmp
;
657 aux
= next_word(pc
); goto iffjmp
;
662 if (ttype(--S
->top
) == LUA_T_NIL
) pc
+= aux
;
666 aux
= next_word(pc
); goto iftupjmp
;
671 if (ttype(--S
->top
) != LUA_T_NIL
) pc
-= aux
;
675 aux
= next_word(pc
); goto iffupjmp
;
680 if (ttype(--S
->top
) == LUA_T_NIL
) pc
-= aux
;
684 aux
= next_word(pc
); goto closure
;
689 *S
->top
++ = consts
[aux
];
695 aux
= *pc
++; goto callfunc
;
697 case CALLFUNC0
: case CALLFUNC1
:
700 StkId newBase
= (S
->top
-S
->stack
)-(*pc
++);
701 luaD_call(newBase
, aux
);
706 S
->top
= S
->stack
+ base
;
710 luaD_callHook(base
, NULL
, 1);
711 return (base
+ ((aux
==RETCODE
) ? *pc
: 0));
714 aux
= next_word(pc
); goto setline
;
719 if ((S
->stack
+base
-1)->ttype
!= LUA_T_LINE
) {
720 /* open space for LINE value */
721 luaD_openstack((S
->top
-S
->stack
)-base
);
723 (S
->stack
+base
-1)->ttype
= LUA_T_LINE
;
725 (S
->stack
+base
-1)->value
.i
= aux
;
732 LUA_INTERNALERROR("opcode doesn't match");