lvm.c 16 KB

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