diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 1997-09-16 16:25:59 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 1997-09-16 16:25:59 -0300 |
commit | 6990da0057008adf934d88125ae9cf5162964117 (patch) | |
tree | 551873be0e3921c9c93b7c32d75a72a688bd26b1 | |
parent | d985dc0629c2a10371b345d1ce3e4404bb011ad9 (diff) | |
download | lua-6990da0057008adf934d88125ae9cf5162964117.tar.gz lua-6990da0057008adf934d88125ae9cf5162964117.tar.bz2 lua-6990da0057008adf934d88125ae9cf5162964117.zip |
Lua virtual machine
-rw-r--r-- | lvm.c | 655 | ||||
-rw-r--r-- | lvm.h | 29 |
2 files changed, 684 insertions, 0 deletions
@@ -0,0 +1,655 @@ | |||
1 | /* | ||
2 | ** $Id: $ | ||
3 | ** Lua virtual machine | ||
4 | ** See Copyright Notice in lua.h | ||
5 | */ | ||
6 | |||
7 | |||
8 | #include <stdio.h> | ||
9 | #include <string.h> | ||
10 | |||
11 | #include "lauxlib.h" | ||
12 | #include "ldo.h" | ||
13 | #include "lfunc.h" | ||
14 | #include "lgc.h" | ||
15 | #include "lglobal.h" | ||
16 | #include "lmem.h" | ||
17 | #include "lopcodes.h" | ||
18 | #include "lstring.h" | ||
19 | #include "ltable.h" | ||
20 | #include "ltm.h" | ||
21 | #include "luadebug.h" | ||
22 | #include "lvm.h" | ||
23 | |||
24 | |||
25 | #define get_word(w,pc) {w=*pc+(*(pc+1)<<8); pc+=2;} | ||
26 | |||
27 | |||
28 | /* Extra stack to run a function: LUA_T_LINE(1), TM calls(2), ... */ | ||
29 | #define EXTRA_STACK 4 | ||
30 | |||
31 | |||
32 | |||
33 | static TaggedString *strconc (char *l, char *r) | ||
34 | { | ||
35 | size_t nl = strlen(l); | ||
36 | char *buffer = luaM_buffer(nl+strlen(r)+1); | ||
37 | strcpy(buffer, l); | ||
38 | strcpy(buffer+nl, r); | ||
39 | return luaS_new(buffer); | ||
40 | } | ||
41 | |||
42 | |||
43 | int luaV_tonumber (TObject *obj) | ||
44 | { | ||
45 | double t; | ||
46 | char c; | ||
47 | if (ttype(obj) != LUA_T_STRING) | ||
48 | return 1; | ||
49 | else if (sscanf(svalue(obj), "%lf %c",&t, &c) == 1) { | ||
50 | nvalue(obj) = (real)t; | ||
51 | ttype(obj) = LUA_T_NUMBER; | ||
52 | return 0; | ||
53 | } | ||
54 | else | ||
55 | return 2; | ||
56 | } | ||
57 | |||
58 | |||
59 | int luaV_tostring (TObject *obj) | ||
60 | { | ||
61 | if (ttype(obj) != LUA_T_NUMBER) | ||
62 | return 1; | ||
63 | else { | ||
64 | char s[60]; | ||
65 | real f = nvalue(obj); | ||
66 | int i; | ||
67 | if ((real)(-MAX_INT) <= f && f <= (real)MAX_INT && (real)(i=(int)f) == f) | ||
68 | sprintf (s, "%d", i); | ||
69 | else | ||
70 | sprintf (s, "%g", (double)nvalue(obj)); | ||
71 | tsvalue(obj) = luaS_new(s); | ||
72 | ttype(obj) = LUA_T_STRING; | ||
73 | return 0; | ||
74 | } | ||
75 | } | ||
76 | |||
77 | |||
78 | void luaV_closure (void) | ||
79 | { | ||
80 | int nelems = (luaD_stack.top-1)->value.tf->nupvalues; | ||
81 | Closure *c = luaF_newclosure(nelems); | ||
82 | c->consts[0] = *(luaD_stack.top-1); | ||
83 | memcpy(&c->consts[1], luaD_stack.top-(nelems+1), nelems*sizeof(TObject)); | ||
84 | luaD_stack.top -= nelems; | ||
85 | ttype(luaD_stack.top-1) = LUA_T_FUNCTION; | ||
86 | (luaD_stack.top-1)->value.cl = c; | ||
87 | } | ||
88 | |||
89 | |||
90 | /* | ||
91 | ** Function to index a table. | ||
92 | ** Receives the table at top-2 and the index at top-1. | ||
93 | */ | ||
94 | void luaV_gettable (void) | ||
95 | { | ||
96 | TObject *im; | ||
97 | if (ttype(luaD_stack.top-2) != LUA_T_ARRAY) /* not a table, get "gettable" method */ | ||
98 | im = luaT_getimbyObj(luaD_stack.top-2, IM_GETTABLE); | ||
99 | else { /* object is a table... */ | ||
100 | int tg = (luaD_stack.top-2)->value.a->htag; | ||
101 | im = luaT_getim(tg, IM_GETTABLE); | ||
102 | if (ttype(im) == LUA_T_NIL) { /* and does not have a "gettable" method */ | ||
103 | TObject *h = luaH_get(avalue(luaD_stack.top-2), luaD_stack.top-1); | ||
104 | if (h != NULL && ttype(h) != LUA_T_NIL) { | ||
105 | --luaD_stack.top; | ||
106 | *(luaD_stack.top-1) = *h; | ||
107 | } | ||
108 | else if (ttype(im=luaT_getim(tg, IM_INDEX)) != LUA_T_NIL) | ||
109 | luaD_callTM(im, 2, 1); | ||
110 | else { | ||
111 | --luaD_stack.top; | ||
112 | ttype(luaD_stack.top-1) = LUA_T_NIL; | ||
113 | } | ||
114 | return; | ||
115 | } | ||
116 | /* else it has a "gettable" method, go through to next command */ | ||
117 | } | ||
118 | /* object is not a table, or it has a "gettable" method */ | ||
119 | if (ttype(im) != LUA_T_NIL) | ||
120 | luaD_callTM(im, 2, 1); | ||
121 | else | ||
122 | lua_error("indexed expression not a table"); | ||
123 | } | ||
124 | |||
125 | |||
126 | /* | ||
127 | ** Function to store indexed based on values at the luaD_stack.top | ||
128 | ** mode = 0: raw store (without internal methods) | ||
129 | ** mode = 1: normal store (with internal methods) | ||
130 | ** mode = 2: "deep luaD_stack.stack" store (with internal methods) | ||
131 | */ | ||
132 | void luaV_settable (TObject *t, int mode) | ||
133 | { | ||
134 | TObject *im = (mode == 0) ? NULL : luaT_getimbyObj(t, IM_SETTABLE); | ||
135 | if (ttype(t) == LUA_T_ARRAY && (im == NULL || ttype(im) == LUA_T_NIL)) { | ||
136 | TObject *h = luaH_set(avalue(t), t+1); | ||
137 | *h = *(luaD_stack.top-1); | ||
138 | luaD_stack.top -= (mode == 2) ? 1 : 3; | ||
139 | } | ||
140 | else { /* object is not a table, and/or has a specific "settable" method */ | ||
141 | if (im && ttype(im) != LUA_T_NIL) { | ||
142 | if (mode == 2) { | ||
143 | *(luaD_stack.top+1) = *(luaD_stack.top-1); | ||
144 | *(luaD_stack.top) = *(t+1); | ||
145 | *(luaD_stack.top-1) = *t; | ||
146 | luaD_stack.top += 2; /* WARNING: caller must assure stack space */ | ||
147 | } | ||
148 | luaD_callTM(im, 3, 0); | ||
149 | } | ||
150 | else | ||
151 | lua_error("indexed expression not a table"); | ||
152 | } | ||
153 | } | ||
154 | |||
155 | |||
156 | void luaV_getglobal (Word n) | ||
157 | { | ||
158 | /* WARNING: caller must assure stack space */ | ||
159 | TObject *value = &luaG_global[n].object; | ||
160 | TObject *im = luaT_getimbyObj(value, IM_GETGLOBAL); | ||
161 | if (ttype(im) == LUA_T_NIL) { /* default behavior */ | ||
162 | *luaD_stack.top = *value; | ||
163 | luaD_stack.top++; | ||
164 | } | ||
165 | else { | ||
166 | ttype(luaD_stack.top) = LUA_T_STRING; | ||
167 | tsvalue(luaD_stack.top) = luaG_global[n].varname; | ||
168 | luaD_stack.top++; | ||
169 | *luaD_stack.top = *value; | ||
170 | luaD_stack.top++; | ||
171 | luaD_callTM(im, 2, 1); | ||
172 | } | ||
173 | } | ||
174 | |||
175 | |||
176 | void luaV_setglobal (Word n) | ||
177 | { | ||
178 | TObject *oldvalue = &luaG_global[n].object; | ||
179 | TObject *im = luaT_getimbyObj(oldvalue, IM_SETGLOBAL); | ||
180 | if (ttype(im) == LUA_T_NIL) /* default behavior */ | ||
181 | s_object(n) = *(--luaD_stack.top); | ||
182 | else { | ||
183 | /* WARNING: caller must assure stack space */ | ||
184 | TObject newvalue = *(luaD_stack.top-1); | ||
185 | ttype(luaD_stack.top-1) = LUA_T_STRING; | ||
186 | tsvalue(luaD_stack.top-1) = luaG_global[n].varname; | ||
187 | *luaD_stack.top = *oldvalue; | ||
188 | luaD_stack.top++; | ||
189 | *luaD_stack.top = newvalue; | ||
190 | luaD_stack.top++; | ||
191 | luaD_callTM(im, 3, 0); | ||
192 | } | ||
193 | } | ||
194 | |||
195 | |||
196 | static void call_binTM (IMS event, char *msg) | ||
197 | { | ||
198 | TObject *im = luaT_getimbyObj(luaD_stack.top-2, event);/* try first operand */ | ||
199 | if (ttype(im) == LUA_T_NIL) { | ||
200 | im = luaT_getimbyObj(luaD_stack.top-1, event); /* try second operand */ | ||
201 | if (ttype(im) == LUA_T_NIL) { | ||
202 | im = luaT_getim(0, event); /* try a 'global' i.m. */ | ||
203 | if (ttype(im) == LUA_T_NIL) | ||
204 | lua_error(msg); | ||
205 | } | ||
206 | } | ||
207 | lua_pushstring(luaT_eventname[event]); | ||
208 | luaD_callTM(im, 3, 1); | ||
209 | } | ||
210 | |||
211 | |||
212 | static void call_arith (IMS event) | ||
213 | { | ||
214 | call_binTM(event, "unexpected type at arithmetic operation"); | ||
215 | } | ||
216 | |||
217 | |||
218 | static void comparison (lua_Type ttype_less, lua_Type ttype_equal, | ||
219 | lua_Type ttype_great, IMS op) | ||
220 | { | ||
221 | TObject *l = luaD_stack.top-2; | ||
222 | TObject *r = luaD_stack.top-1; | ||
223 | int result; | ||
224 | if (ttype(l) == LUA_T_NUMBER && ttype(r) == LUA_T_NUMBER) | ||
225 | result = (nvalue(l) < nvalue(r)) ? -1 : (nvalue(l) == nvalue(r)) ? 0 : 1; | ||
226 | else if (ttype(l) == LUA_T_STRING && ttype(r) == LUA_T_STRING) | ||
227 | result = strcoll(svalue(l), svalue(r)); | ||
228 | else { | ||
229 | call_binTM(op, "unexpected type at comparison"); | ||
230 | return; | ||
231 | } | ||
232 | luaD_stack.top--; | ||
233 | nvalue(luaD_stack.top-1) = 1; | ||
234 | ttype(luaD_stack.top-1) = (result < 0) ? ttype_less : | ||
235 | (result == 0) ? ttype_equal : ttype_great; | ||
236 | } | ||
237 | |||
238 | |||
239 | void luaV_pack (StkId firstel, int nvararg, TObject *tab) | ||
240 | { | ||
241 | TObject *firstelem = luaD_stack.stack+firstel; | ||
242 | int i; | ||
243 | if (nvararg < 0) nvararg = 0; | ||
244 | avalue(tab) = luaH_new(nvararg+1); /* +1 for field 'n' */ | ||
245 | ttype(tab) = LUA_T_ARRAY; | ||
246 | for (i=0; i<nvararg; i++) { | ||
247 | TObject index; | ||
248 | ttype(&index) = LUA_T_NUMBER; | ||
249 | nvalue(&index) = i+1; | ||
250 | *(luaH_set(avalue(tab), &index)) = *(firstelem+i); | ||
251 | } | ||
252 | /* store counter in field "n" */ { | ||
253 | TObject index, extra; | ||
254 | ttype(&index) = LUA_T_STRING; | ||
255 | tsvalue(&index) = luaS_new("n"); | ||
256 | ttype(&extra) = LUA_T_NUMBER; | ||
257 | nvalue(&extra) = nvararg; | ||
258 | *(luaH_set(avalue(tab), &index)) = extra; | ||
259 | } | ||
260 | } | ||
261 | |||
262 | |||
263 | static void adjust_varargs (StkId first_extra_arg) | ||
264 | { | ||
265 | TObject arg; | ||
266 | luaV_pack(first_extra_arg, | ||
267 | (luaD_stack.top-luaD_stack.stack)-first_extra_arg, &arg); | ||
268 | luaD_adjusttop(first_extra_arg); | ||
269 | *luaD_stack.top = arg; | ||
270 | luaD_stack.top++; | ||
271 | } | ||
272 | |||
273 | |||
274 | |||
275 | /* | ||
276 | ** Execute the given opcode, until a RET. Parameters are between | ||
277 | ** [luaD_stack.stack+base,luaD_stack.top). Returns n such that the the results are between | ||
278 | ** [luaD_stack.stack+n,luaD_stack.top). | ||
279 | */ | ||
280 | StkId luaV_execute (Closure *cl, StkId base) | ||
281 | { | ||
282 | TProtoFunc *func = cl->consts[0].value.tf; | ||
283 | Byte *pc = func->code; | ||
284 | if (lua_callhook) | ||
285 | luaD_callHook(base, LUA_T_MARK, 0); | ||
286 | luaD_checkstack((*pc++)+EXTRA_STACK); | ||
287 | while (1) { | ||
288 | OpCode opcode; | ||
289 | switch (opcode = (OpCode)*pc++) { | ||
290 | |||
291 | case PUSHNIL: | ||
292 | ttype(luaD_stack.top) = LUA_T_NIL; | ||
293 | luaD_stack.top++; | ||
294 | break; | ||
295 | |||
296 | case PUSHNILS: { | ||
297 | int n = *pc++; | ||
298 | while (n--) | ||
299 | ttype(luaD_stack.top++) = LUA_T_NIL; | ||
300 | break; | ||
301 | } | ||
302 | |||
303 | case PUSH0: case PUSH1: case PUSH2: | ||
304 | ttype(luaD_stack.top) = LUA_T_NUMBER; | ||
305 | nvalue(luaD_stack.top) = opcode-PUSH0; | ||
306 | luaD_stack.top++; | ||
307 | break; | ||
308 | |||
309 | case PUSHBYTE: | ||
310 | ttype(luaD_stack.top) = LUA_T_NUMBER; | ||
311 | nvalue(luaD_stack.top) = *pc++; | ||
312 | luaD_stack.top++; | ||
313 | break; | ||
314 | |||
315 | case PUSHWORD: { | ||
316 | Word w; | ||
317 | get_word(w,pc); | ||
318 | ttype(luaD_stack.top) = LUA_T_NUMBER; | ||
319 | nvalue(luaD_stack.top) = w; | ||
320 | luaD_stack.top++; | ||
321 | break; | ||
322 | } | ||
323 | |||
324 | case PUSHLOCAL0: case PUSHLOCAL1: case PUSHLOCAL2: | ||
325 | case PUSHLOCAL3: case PUSHLOCAL4: case PUSHLOCAL5: | ||
326 | case PUSHLOCAL6: case PUSHLOCAL7: case PUSHLOCAL8: | ||
327 | case PUSHLOCAL9: | ||
328 | *luaD_stack.top = *((luaD_stack.stack+base) + (int)(opcode-PUSHLOCAL0)); | ||
329 | luaD_stack.top++; | ||
330 | break; | ||
331 | |||
332 | case PUSHLOCAL: | ||
333 | *luaD_stack.top = *((luaD_stack.stack+base) + (*pc++)); | ||
334 | luaD_stack.top++; | ||
335 | break; | ||
336 | |||
337 | case PUSHGLOBAL: { | ||
338 | Word w; | ||
339 | get_word(w,pc); | ||
340 | luaV_getglobal(w); | ||
341 | break; | ||
342 | } | ||
343 | |||
344 | case PUSHTABLE: | ||
345 | luaV_gettable(); | ||
346 | break; | ||
347 | |||
348 | case PUSHSELF: { | ||
349 | TObject receiver = *(luaD_stack.top-1); | ||
350 | Word w; | ||
351 | get_word(w,pc); | ||
352 | *luaD_stack.top = func->consts[w]; | ||
353 | luaD_stack.top++; | ||
354 | luaV_gettable(); | ||
355 | *luaD_stack.top = receiver; | ||
356 | luaD_stack.top++; | ||
357 | break; | ||
358 | } | ||
359 | |||
360 | case PUSHCONSTANTB: { | ||
361 | *luaD_stack.top = func->consts[*pc++]; | ||
362 | luaD_stack.top++; | ||
363 | break; | ||
364 | } | ||
365 | |||
366 | case PUSHCONSTANT: { | ||
367 | Word w; | ||
368 | get_word(w,pc); | ||
369 | *luaD_stack.top = func->consts[w]; | ||
370 | luaD_stack.top++; | ||
371 | break; | ||
372 | } | ||
373 | |||
374 | case PUSHUPVALUE0: | ||
375 | case PUSHUPVALUE: { | ||
376 | int i = (opcode == PUSHUPVALUE0) ? 0 : *pc++; | ||
377 | *luaD_stack.top = cl->consts[i+1]; | ||
378 | luaD_stack.top++; | ||
379 | break; | ||
380 | } | ||
381 | |||
382 | case SETLOCAL0: case SETLOCAL1: case SETLOCAL2: | ||
383 | case SETLOCAL3: case SETLOCAL4: case SETLOCAL5: | ||
384 | case SETLOCAL6: case SETLOCAL7: case SETLOCAL8: | ||
385 | case SETLOCAL9: | ||
386 | *((luaD_stack.stack+base) + (int)(opcode-SETLOCAL0)) = | ||
387 | *(--luaD_stack.top); | ||
388 | break; | ||
389 | |||
390 | case SETLOCAL: | ||
391 | *((luaD_stack.stack+base) + (*pc++)) = *(--luaD_stack.top); break; | ||
392 | |||
393 | case SETGLOBAL: { | ||
394 | Word w; | ||
395 | get_word(w,pc); | ||
396 | luaV_setglobal(w); | ||
397 | break; | ||
398 | } | ||
399 | |||
400 | case SETTABLE0: | ||
401 | luaV_settable(luaD_stack.top-3, 1); | ||
402 | break; | ||
403 | |||
404 | case SETTABLE: { | ||
405 | int n = *pc++; | ||
406 | luaV_settable(luaD_stack.top-3-n, 2); | ||
407 | break; | ||
408 | } | ||
409 | |||
410 | case SETLIST0: | ||
411 | case SETLIST: { | ||
412 | int m, n; | ||
413 | TObject *arr; | ||
414 | if (opcode == SETLIST0) m = 0; | ||
415 | else m = *(pc++) * LFIELDS_PER_FLUSH; | ||
416 | n = *(pc++); | ||
417 | arr = luaD_stack.top-n-1; | ||
418 | while (n) { | ||
419 | ttype(luaD_stack.top) = LUA_T_NUMBER; nvalue(luaD_stack.top) = n+m; | ||
420 | *(luaH_set (avalue(arr), luaD_stack.top)) = *(luaD_stack.top-1); | ||
421 | luaD_stack.top--; | ||
422 | n--; | ||
423 | } | ||
424 | break; | ||
425 | } | ||
426 | |||
427 | case SETMAP: { | ||
428 | int n = *(pc++); | ||
429 | TObject *arr = luaD_stack.top-(2*n)-1; | ||
430 | while (n--) { | ||
431 | *(luaH_set (avalue(arr), luaD_stack.top-2)) = *(luaD_stack.top-1); | ||
432 | luaD_stack.top-=2; | ||
433 | } | ||
434 | break; | ||
435 | } | ||
436 | |||
437 | case POPS: | ||
438 | luaD_stack.top -= *(pc++); | ||
439 | break; | ||
440 | |||
441 | case ARGS: | ||
442 | luaD_adjusttop(base + *(pc++)); | ||
443 | break; | ||
444 | |||
445 | case VARARGS: | ||
446 | luaC_checkGC(); | ||
447 | adjust_varargs(base + *(pc++)); | ||
448 | break; | ||
449 | |||
450 | case CREATEARRAY: { | ||
451 | Word size; | ||
452 | luaC_checkGC(); | ||
453 | get_word(size,pc); | ||
454 | avalue(luaD_stack.top) = luaH_new(size); | ||
455 | ttype(luaD_stack.top) = LUA_T_ARRAY; | ||
456 | luaD_stack.top++; | ||
457 | break; | ||
458 | } | ||
459 | |||
460 | case EQOP: case NEQOP: { | ||
461 | int res = luaO_equalObj(luaD_stack.top-2, luaD_stack.top-1); | ||
462 | --luaD_stack.top; | ||
463 | if (opcode == NEQOP) res = !res; | ||
464 | ttype(luaD_stack.top-1) = res ? LUA_T_NUMBER : LUA_T_NIL; | ||
465 | nvalue(luaD_stack.top-1) = 1; | ||
466 | break; | ||
467 | } | ||
468 | |||
469 | case LTOP: | ||
470 | comparison(LUA_T_NUMBER, LUA_T_NIL, LUA_T_NIL, IM_LT); | ||
471 | break; | ||
472 | |||
473 | case LEOP: | ||
474 | comparison(LUA_T_NUMBER, LUA_T_NUMBER, LUA_T_NIL, IM_LE); | ||
475 | break; | ||
476 | |||
477 | case GTOP: | ||
478 | comparison(LUA_T_NIL, LUA_T_NIL, LUA_T_NUMBER, IM_GT); | ||
479 | break; | ||
480 | |||
481 | case GEOP: | ||
482 | comparison(LUA_T_NIL, LUA_T_NUMBER, LUA_T_NUMBER, IM_GE); | ||
483 | break; | ||
484 | |||
485 | case ADDOP: { | ||
486 | TObject *l = luaD_stack.top-2; | ||
487 | TObject *r = luaD_stack.top-1; | ||
488 | if (tonumber(r) || tonumber(l)) | ||
489 | call_arith(IM_ADD); | ||
490 | else { | ||
491 | nvalue(l) += nvalue(r); | ||
492 | --luaD_stack.top; | ||
493 | } | ||
494 | break; | ||
495 | } | ||
496 | |||
497 | case SUBOP: { | ||
498 | TObject *l = luaD_stack.top-2; | ||
499 | TObject *r = luaD_stack.top-1; | ||
500 | if (tonumber(r) || tonumber(l)) | ||
501 | call_arith(IM_SUB); | ||
502 | else { | ||
503 | nvalue(l) -= nvalue(r); | ||
504 | --luaD_stack.top; | ||
505 | } | ||
506 | break; | ||
507 | } | ||
508 | |||
509 | case MULTOP: { | ||
510 | TObject *l = luaD_stack.top-2; | ||
511 | TObject *r = luaD_stack.top-1; | ||
512 | if (tonumber(r) || tonumber(l)) | ||
513 | call_arith(IM_MUL); | ||
514 | else { | ||
515 | nvalue(l) *= nvalue(r); | ||
516 | --luaD_stack.top; | ||
517 | } | ||
518 | break; | ||
519 | } | ||
520 | |||
521 | case DIVOP: { | ||
522 | TObject *l = luaD_stack.top-2; | ||
523 | TObject *r = luaD_stack.top-1; | ||
524 | if (tonumber(r) || tonumber(l)) | ||
525 | call_arith(IM_DIV); | ||
526 | else { | ||
527 | nvalue(l) /= nvalue(r); | ||
528 | --luaD_stack.top; | ||
529 | } | ||
530 | break; | ||
531 | } | ||
532 | |||
533 | case POWOP: | ||
534 | call_arith(IM_POW); | ||
535 | break; | ||
536 | |||
537 | case CONCOP: { | ||
538 | TObject *l = luaD_stack.top-2; | ||
539 | TObject *r = luaD_stack.top-1; | ||
540 | if (tostring(l) || tostring(r)) | ||
541 | call_binTM(IM_CONCAT, "unexpected type for concatenation"); | ||
542 | else { | ||
543 | tsvalue(l) = strconc(svalue(l), svalue(r)); | ||
544 | --luaD_stack.top; | ||
545 | } | ||
546 | luaC_checkGC(); | ||
547 | break; | ||
548 | } | ||
549 | |||
550 | case MINUSOP: | ||
551 | if (tonumber(luaD_stack.top-1)) { | ||
552 | ttype(luaD_stack.top) = LUA_T_NIL; | ||
553 | luaD_stack.top++; | ||
554 | call_arith(IM_UNM); | ||
555 | } | ||
556 | else | ||
557 | nvalue(luaD_stack.top-1) = - nvalue(luaD_stack.top-1); | ||
558 | break; | ||
559 | |||
560 | case NOTOP: | ||
561 | ttype(luaD_stack.top-1) = | ||
562 | (ttype(luaD_stack.top-1) == LUA_T_NIL) ? LUA_T_NUMBER : LUA_T_NIL; | ||
563 | nvalue(luaD_stack.top-1) = 1; | ||
564 | break; | ||
565 | |||
566 | case ONTJMP: { | ||
567 | Word w; | ||
568 | get_word(w,pc); | ||
569 | if (ttype(luaD_stack.top-1) != LUA_T_NIL) pc += w; | ||
570 | else luaD_stack.top--; | ||
571 | } | ||
572 | break; | ||
573 | |||
574 | case ONFJMP: { | ||
575 | Word w; | ||
576 | get_word(w,pc); | ||
577 | if (ttype(luaD_stack.top-1) == LUA_T_NIL) pc += w; | ||
578 | else luaD_stack.top--; | ||
579 | break; | ||
580 | } | ||
581 | |||
582 | case JMP: { | ||
583 | Word w; | ||
584 | get_word(w,pc); | ||
585 | pc += w; | ||
586 | break; | ||
587 | } | ||
588 | |||
589 | case UPJMP: { | ||
590 | Word w; | ||
591 | get_word(w,pc); | ||
592 | pc -= w; | ||
593 | break; | ||
594 | } | ||
595 | |||
596 | case IFFJMP: { | ||
597 | Word w; | ||
598 | get_word(w,pc); | ||
599 | luaD_stack.top--; | ||
600 | if (ttype(luaD_stack.top) == LUA_T_NIL) pc += w; | ||
601 | break; | ||
602 | } | ||
603 | |||
604 | case IFFUPJMP: { | ||
605 | Word w; | ||
606 | get_word(w,pc); | ||
607 | luaD_stack.top--; | ||
608 | if (ttype(luaD_stack.top) == LUA_T_NIL) pc -= w; | ||
609 | break; | ||
610 | } | ||
611 | |||
612 | case CLOSURE: | ||
613 | luaV_closure(); | ||
614 | luaC_checkGC(); | ||
615 | break; | ||
616 | |||
617 | case CALLFUNC: { | ||
618 | int nParams = *pc++; | ||
619 | int nResults = *pc++; | ||
620 | StkId newBase = (luaD_stack.top-luaD_stack.stack)-nParams; | ||
621 | luaD_call(newBase, nResults); | ||
622 | break; | ||
623 | } | ||
624 | |||
625 | case ENDCODE: | ||
626 | luaD_stack.top = luaD_stack.stack + base; | ||
627 | /* goes through */ | ||
628 | case RETCODE: | ||
629 | if (lua_callhook) | ||
630 | luaD_callHook(base, LUA_T_MARK, 1); | ||
631 | return (base + ((opcode==RETCODE) ? *pc : 0)); | ||
632 | |||
633 | case SETLINE: { | ||
634 | Word line; | ||
635 | get_word(line,pc); | ||
636 | if ((luaD_stack.stack+base-1)->ttype != LUA_T_LINE) { | ||
637 | /* open space for LINE value */ | ||
638 | luaD_openstack((luaD_stack.top-luaD_stack.stack)-base); | ||
639 | base++; | ||
640 | (luaD_stack.stack+base-1)->ttype = LUA_T_LINE; | ||
641 | } | ||
642 | (luaD_stack.stack+base-1)->value.i = line; | ||
643 | if (lua_linehook) | ||
644 | luaD_lineHook(line); | ||
645 | break; | ||
646 | } | ||
647 | |||
648 | #ifdef DEBUG | ||
649 | default: | ||
650 | lua_error("internal error - opcode doesn't match"); | ||
651 | #endif | ||
652 | } | ||
653 | } | ||
654 | } | ||
655 | |||
@@ -0,0 +1,29 @@ | |||
1 | /* | ||
2 | ** $Id: $ | ||
3 | ** Lua virtual machine | ||
4 | ** See Copyright Notice in lua.h | ||
5 | */ | ||
6 | |||
7 | #ifndef lvm_h | ||
8 | #define lvm_h | ||
9 | |||
10 | |||
11 | #include "ldo.h" | ||
12 | #include "lobject.h" | ||
13 | |||
14 | |||
15 | #define tonumber(o) ((ttype(o) != LUA_T_NUMBER) && (luaV_tonumber(o) != 0)) | ||
16 | #define tostring(o) ((ttype(o) != LUA_T_STRING) && (luaV_tostring(o) != 0)) | ||
17 | |||
18 | |||
19 | void luaV_pack (StkId firstel, int nvararg, TObject *tab); | ||
20 | int luaV_tonumber (TObject *obj); | ||
21 | int luaV_tostring (TObject *obj); | ||
22 | void luaV_gettable (void); | ||
23 | void luaV_settable (TObject *t, int mode); | ||
24 | void luaV_getglobal (Word n); | ||
25 | void luaV_setglobal (Word n); | ||
26 | StkId luaV_execute (Closure *func, StkId base); | ||
27 | void luaV_closure (void); | ||
28 | |||
29 | #endif | ||