You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

vm.c 23KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845
  1. #include "vm/vm.h"
  2. #include <string.h>
  3. #include <stdio.h>
  4. #include <stdarg.h>
  5. #include "vm/builtins.h"
  6. static int stdio_inited = 0;
  7. static struct l2_io_file_writer std_output;
  8. static struct l2_io_file_writer std_error;
  9. static l2_word alloc_val(struct l2_vm *vm) {
  10. size_t id = l2_bitset_set_next(&vm->valueset);
  11. if (id + 16 >= vm->valuessize) {
  12. if (id >= vm->valuessize) {
  13. if (vm->valuessize == 0) {
  14. vm->valuessize = 128;
  15. }
  16. while (id >= vm->valuessize) {
  17. vm->valuessize *= 2;
  18. }
  19. vm->values = realloc(vm->values, sizeof(*vm->values) * vm->valuessize);
  20. } else {
  21. vm->need_gc = 1;
  22. }
  23. }
  24. return (l2_word)id;
  25. }
  26. static void gc_mark_array(struct l2_vm *vm, struct l2_vm_value *val);
  27. static void gc_mark_namespace(struct l2_vm *vm, struct l2_vm_value *val);
  28. static void gc_mark(struct l2_vm *vm, l2_word id) {
  29. struct l2_vm_value *val = &vm->values[id];
  30. if (val->flags & L2_VAL_MARKED) {
  31. return;
  32. }
  33. val->flags |= L2_VAL_MARKED;
  34. int typ = l2_value_get_type(val);
  35. if (typ == L2_VAL_TYPE_ARRAY) {
  36. gc_mark_array(vm, val);
  37. } else if (typ == L2_VAL_TYPE_NAMESPACE) {
  38. gc_mark_namespace(vm, val);
  39. } else if (typ == L2_VAL_TYPE_FUNCTION) {
  40. gc_mark(vm, val->func.ns);
  41. } else if (typ == L2_VAL_TYPE_CONTINUATION) {
  42. gc_mark(vm, val->extra.cont_call);
  43. if (val->cont != NULL) {
  44. if (val->cont->marker != NULL) {
  45. val->cont->marker(vm, val->cont, gc_mark);
  46. }
  47. if (val->cont->args != 0) {
  48. gc_mark(vm, val->cont->args);
  49. }
  50. }
  51. }
  52. }
  53. static void gc_mark_array(struct l2_vm *vm, struct l2_vm_value *val) {
  54. l2_word *data;
  55. if (val->flags & L2_VAL_SBO) {
  56. data = val->shortarray;
  57. } else {
  58. data = val->array->data;
  59. }
  60. for (size_t i = 0; i < val->extra.arr_length; ++i) {
  61. gc_mark(vm, data[i]);
  62. }
  63. }
  64. static void gc_mark_namespace(struct l2_vm *vm, struct l2_vm_value *val) {
  65. if (val->extra.ns_parent != 0) {
  66. gc_mark(vm, val->extra.ns_parent);
  67. }
  68. if (val->ns == NULL) {
  69. return;
  70. }
  71. for (size_t i = 0; i < val->ns->size; ++i) {
  72. l2_word key = val->ns->data[i];
  73. if (key == 0 || key == ~(l2_word)0) {
  74. continue;
  75. }
  76. gc_mark(vm, val->ns->data[val->ns->size + i]);
  77. }
  78. }
  79. static void gc_free(struct l2_vm *vm, l2_word id) {
  80. struct l2_vm_value *val = &vm->values[id];
  81. l2_bitset_unset(&vm->valueset, id);
  82. // Don't need to do anything more; the next round of GC will free
  83. // whichever values were only referenced by the array
  84. int typ = l2_value_get_type(val);
  85. if (typ == L2_VAL_TYPE_ARRAY && !(val->flags & L2_VAL_SBO)) {
  86. free(val->array);
  87. } else if (typ == L2_VAL_TYPE_BUFFER) {
  88. free(val->buffer);
  89. } else if (typ == L2_VAL_TYPE_NAMESPACE) {
  90. free(val->ns);
  91. } else if (typ == L2_VAL_TYPE_ERROR) {
  92. free(val->error);
  93. } else if (typ == L2_VAL_TYPE_CONTINUATION && val->cont) {
  94. free(val->cont);
  95. }
  96. }
  97. static size_t gc_sweep(struct l2_vm *vm) {
  98. size_t freed = 0;
  99. for (size_t i = vm->gc_start; i < vm->valuessize; ++i) {
  100. if (!l2_bitset_get(&vm->valueset, i)) {
  101. continue;
  102. }
  103. struct l2_vm_value *val = &vm->values[i];
  104. if (!(val->flags & L2_VAL_MARKED)) {
  105. l2_bitset_unset(&vm->valueset, i);
  106. gc_free(vm, i);
  107. freed += 1;
  108. } else {
  109. val->flags &= ~L2_VAL_MARKED;
  110. }
  111. }
  112. // Normal variables are unmarked by the above loop,
  113. // but builtins don't go through that loop
  114. for (size_t i = 0; i < vm->gc_start; ++i) {
  115. vm->values[i].flags &= ~L2_VAL_MARKED;
  116. }
  117. return freed;
  118. }
  119. const char *l2_value_type_name(enum l2_value_type typ) {
  120. switch (typ) {
  121. case L2_VAL_TYPE_NONE: return "NONE";
  122. case L2_VAL_TYPE_ATOM: return "ATOM";
  123. case L2_VAL_TYPE_REAL: return "REAL";
  124. case L2_VAL_TYPE_BUFFER: return "BUFFER";
  125. case L2_VAL_TYPE_ARRAY: return "ARRAY";
  126. case L2_VAL_TYPE_NAMESPACE: return "NAMESPACE";
  127. case L2_VAL_TYPE_FUNCTION: return "FUNCTION";
  128. case L2_VAL_TYPE_CFUNCTION: return "CFUNCTION";
  129. case L2_VAL_TYPE_CONTINUATION: return "CONTINUATION";
  130. case L2_VAL_TYPE_RETURN: return "RETURN";
  131. case L2_VAL_TYPE_ERROR: return "ERROR";
  132. }
  133. return "(unknown)";
  134. }
  135. l2_word *l2_value_arr_data(struct l2_vm *vm, struct l2_vm_value *val) {
  136. if (val->flags & L2_VAL_SBO) {
  137. return val->shortarray;
  138. } else if (val->array) {
  139. return val->array->data;
  140. } else {
  141. return NULL;
  142. }
  143. }
  144. l2_word l2_value_arr_get(struct l2_vm *vm, struct l2_vm_value *val, l2_word k) {
  145. if (k >= val->extra.arr_length) {
  146. return vm->knone;
  147. }
  148. if (val->flags & L2_VAL_SBO) {
  149. return val->shortarray[k];
  150. }
  151. return val->array->data[k];
  152. }
  153. l2_word l2_value_arr_set(struct l2_vm *vm, struct l2_vm_value *val, l2_word k, l2_word v) {
  154. if (k >= val->extra.arr_length) {
  155. return l2_vm_error(vm, "Array index out of bounds");
  156. }
  157. if (val->flags & L2_VAL_SBO) {
  158. return val->shortarray[k] = v;
  159. }
  160. return val->array->data[k] = v;
  161. }
  162. void l2_vm_init(struct l2_vm *vm, unsigned char *ops, size_t opslen) {
  163. if (!stdio_inited) {
  164. std_output.w.write = l2_io_file_write;
  165. std_output.f = stdout;
  166. std_error.w.write = l2_io_file_write;
  167. std_error.f = stderr;
  168. stdio_inited = 1;
  169. }
  170. vm->std_output = &std_output.w;
  171. vm->std_error = &std_error.w;
  172. vm->halted = 0;
  173. vm->need_gc = 0;
  174. vm->need_check_retval = 0;
  175. vm->ops = ops;
  176. vm->opslen = opslen;
  177. vm->iptr = 0;
  178. vm->sptr = 0;
  179. vm->fsptr = 0;
  180. vm->values = NULL;
  181. vm->valuessize = 0;
  182. l2_bitset_init(&vm->valueset);
  183. // It's wasteful to allocate new 'none' variables all the time,
  184. // variable ID 0 should be the only 'none' variable in the system
  185. l2_word none_id = alloc_val(vm);
  186. vm->values[none_id].flags = L2_VAL_TYPE_NONE | L2_VAL_CONST;
  187. // Need to allocate a builtins namespace
  188. l2_word builtins = alloc_val(vm);
  189. vm->values[builtins].extra.ns_parent = 0;
  190. vm->values[builtins].ns = NULL; // Will be allocated on first insert
  191. vm->values[builtins].flags = L2_VAL_TYPE_NAMESPACE;
  192. vm->fstack[vm->fsptr].ns = builtins;
  193. vm->fstack[vm->fsptr].retptr = 0;
  194. vm->fstack[vm->fsptr].sptr = 0;
  195. vm->fsptr += 1;
  196. // Need to allocate a root namespace
  197. l2_word root = alloc_val(vm);
  198. vm->values[root].extra.ns_parent = builtins;
  199. vm->values[root].ns = NULL;
  200. vm->values[root].flags = L2_VAL_TYPE_NAMESPACE;
  201. vm->fstack[vm->fsptr].ns = root;
  202. vm->fstack[vm->fsptr].retptr = ~(l2_word)0;
  203. vm->fstack[vm->fsptr].sptr = 0;
  204. vm->fsptr += 1;
  205. // None is always at 0
  206. vm->knone = 0;
  207. vm->values[vm->knone].flags = L2_VAL_TYPE_NONE | L2_VAL_CONST;
  208. // Define a C function variable for every builtin
  209. l2_word id;
  210. l2_word key = 1;
  211. #define XNAME(name, k) \
  212. l2_vm_namespace_set(&vm->values[builtins], key, vm->k); \
  213. key += 1;
  214. #define XATOM(name, k) \
  215. id = alloc_val(vm); \
  216. vm->values[id].flags = L2_VAL_TYPE_ATOM | L2_VAL_CONST; \
  217. vm->values[id].atom = key; \
  218. vm->k = id; \
  219. key += 1;
  220. #define XFUNCTION(name, f) \
  221. id = alloc_val(vm); \
  222. vm->values[id].flags = L2_VAL_TYPE_CFUNCTION | L2_VAL_CONST; \
  223. vm->values[id].cfunc = f; \
  224. l2_vm_namespace_set(&vm->values[builtins], key, id); \
  225. key += 1;
  226. #include "builtins.x.h"
  227. #undef XNAME
  228. #undef XATOM
  229. #undef XFUNCTION
  230. vm->gc_start = id + 1;
  231. }
  232. l2_word l2_vm_alloc(struct l2_vm *vm, enum l2_value_type typ, enum l2_value_flags flags) {
  233. l2_word id = alloc_val(vm);
  234. memset(&vm->values[id], 0, sizeof(vm->values[id]));
  235. vm->values[id].flags = typ | flags;
  236. return id;
  237. }
  238. l2_word l2_vm_error(struct l2_vm *vm, const char *fmt, ...) {
  239. l2_word id = alloc_val(vm);
  240. struct l2_vm_value *val = &vm->values[id];
  241. val->flags = L2_VAL_CONST | L2_VAL_TYPE_ERROR;
  242. char buf[256];
  243. va_list va;
  244. va_start(va, fmt);
  245. int n = vsnprintf(buf, sizeof(buf), fmt, va);
  246. if (n < 0) {
  247. const char *message = "Failed to generate error message!";
  248. val->error = malloc(strlen(message) + 1);
  249. strcpy(val->error, message);
  250. va_end(va);
  251. return id;
  252. } else if ((size_t)n + 1 < sizeof(buf)) {
  253. val->error = malloc(n + 1);
  254. strcpy(val->error, buf);
  255. va_end(va);
  256. return id;
  257. }
  258. val->error = malloc(n + 1);
  259. vsnprintf(val->error, n + 1, fmt, va);
  260. va_end(va);
  261. return id;
  262. }
  263. l2_word l2_vm_type_error(struct l2_vm *vm, struct l2_vm_value *val) {
  264. enum l2_value_type typ = l2_value_get_type(val);
  265. if (typ == L2_VAL_TYPE_ERROR) {
  266. return val - vm->values;
  267. }
  268. return l2_vm_error(vm, "Unexpected type %s", l2_value_type_name(l2_value_get_type(val)));
  269. }
  270. void l2_vm_free(struct l2_vm *vm) {
  271. // Skip ID 0, because that's always NONE
  272. for (size_t i = 1; i < vm->valuessize; ++i) {
  273. if (!l2_bitset_get(&vm->valueset, i)) {
  274. continue;
  275. }
  276. gc_free(vm, i);
  277. }
  278. free(vm->values);
  279. l2_bitset_free(&vm->valueset);
  280. }
  281. size_t l2_vm_gc(struct l2_vm *vm) {
  282. for (l2_word sptr = 0; sptr < vm->sptr; ++sptr) {
  283. gc_mark(vm, vm->stack[sptr]);
  284. }
  285. // Don't need to mark the first stack frame, since that's where all the
  286. // builtins live, and they aren't sweeped anyways
  287. for (l2_word fsptr = 1; fsptr < vm->fsptr; ++fsptr) {
  288. gc_mark(vm, vm->fstack[fsptr].ns);
  289. }
  290. return gc_sweep(vm);
  291. }
  292. void l2_vm_run(struct l2_vm *vm) {
  293. while (!vm->halted) {
  294. l2_vm_step(vm);
  295. }
  296. }
  297. static void call_func_with_args(
  298. struct l2_vm *vm, l2_word func_id, l2_word args_id);
  299. static void call_func(
  300. struct l2_vm *vm, l2_word func_id,
  301. l2_word argc, l2_word *argv);
  302. static void after_cfunc_return(struct l2_vm *vm) {
  303. if (
  304. l2_value_get_type(&vm->values[vm->stack[vm->sptr - 1]]) ==
  305. L2_VAL_TYPE_RETURN ||
  306. l2_value_get_type(&vm->values[vm->stack[vm->sptr - 1]]) ==
  307. L2_VAL_TYPE_CONTINUATION ||
  308. (vm->sptr >= 2 &&
  309. l2_value_get_type(&vm->values[vm->stack[vm->sptr - 2]]) ==
  310. L2_VAL_TYPE_CONTINUATION)) {
  311. vm->need_check_retval = 1;
  312. }
  313. }
  314. static void after_func_return(struct l2_vm *vm) {
  315. struct l2_vm_value *ret = &vm->values[vm->stack[vm->sptr - 1]];
  316. if (l2_value_get_type(ret) == L2_VAL_TYPE_RETURN) {
  317. l2_word retval = ret->ret;
  318. l2_word retptr = vm->fstack[vm->fsptr - 1].retptr;
  319. l2_word sptr = vm->fstack[vm->fsptr - 1].sptr;
  320. if (retptr == ~(l2_word)0) {
  321. vm->halted = 1;
  322. return;
  323. }
  324. vm->fsptr -= 1;
  325. vm->sptr = sptr;
  326. vm->iptr = retptr;
  327. vm->stack[vm->sptr++] = retval;
  328. after_func_return(vm);
  329. return;
  330. }
  331. // If the function returns a continuation, we leave that continuation
  332. // on the stack to be handled later, then call the function
  333. if (l2_value_get_type(ret) == L2_VAL_TYPE_CONTINUATION) {
  334. if (ret->cont && ret->cont->args != vm->knone) {
  335. struct l2_vm_value *args = &vm->values[ret->cont->args];
  336. struct l2_vm_value *func = &vm->values[ret->extra.cont_call];
  337. // We can optimize calling a non-C function by re-using the
  338. // args array rather than allocating a new one
  339. if (l2_value_get_type(func) == L2_VAL_TYPE_FUNCTION) {
  340. call_func_with_args(vm, ret->extra.cont_call, ret->cont->args);
  341. } else {
  342. call_func(
  343. vm, ret->extra.cont_call, args->extra.arr_length,
  344. l2_value_arr_data(vm, args));
  345. }
  346. } else {
  347. call_func(vm, ret->extra.cont_call, 0, NULL);
  348. }
  349. return;
  350. }
  351. // If the value right below the returned value is a continuation,
  352. // it's a continuation left on the stack to be handled later - i.e now
  353. if (
  354. vm->sptr >= 2 &&
  355. l2_value_get_type(&vm->values[vm->stack[vm->sptr - 2]]) ==
  356. L2_VAL_TYPE_CONTINUATION) {
  357. struct l2_vm_value *cont = &vm->values[vm->stack[vm->sptr - 2]];
  358. // If it's just a basic continuation, don't need to do anything
  359. if (cont->cont == NULL || cont->cont->callback == NULL) {
  360. // Return the return value of the function, discard the continuation
  361. vm->stack[vm->sptr - 2] = vm->stack[vm->sptr - 1];
  362. vm->sptr -= 1;
  363. return;
  364. }
  365. // After this, the original return value and the continuation
  366. // are both replaced by whatever the callback returned
  367. l2_word contret = cont->cont->callback(
  368. vm, vm->stack[vm->sptr - 1], vm->stack[vm->sptr - 2]);
  369. vm->stack[vm->sptr - 2] = contret;
  370. vm->sptr -= 1;
  371. after_func_return(vm);
  372. return;
  373. }
  374. }
  375. static void call_func_with_args(struct l2_vm *vm, l2_word func_id, l2_word args_id) {
  376. l2_word stack_base = vm->sptr;
  377. vm->stack[vm->sptr++] = args_id;
  378. l2_word ns_id = alloc_val(vm);
  379. struct l2_vm_value *func = &vm->values[func_id]; // func might be stale after alloc_val
  380. vm->values[ns_id].extra.ns_parent = func->func.ns;
  381. vm->values[ns_id].ns = NULL;
  382. vm->values[ns_id].flags = L2_VAL_TYPE_NAMESPACE;
  383. vm->fstack[vm->fsptr].ns = ns_id;
  384. vm->fstack[vm->fsptr].retptr = vm->iptr;
  385. vm->fstack[vm->fsptr].sptr = stack_base;
  386. vm->fsptr += 1;
  387. vm->iptr = func->func.pos;
  388. }
  389. // The 'call_func' function assumes that all relevant values have been popped off
  390. // the stack, so that the return value can be pushed to the top of the stack
  391. // straight away
  392. static void call_func(
  393. struct l2_vm *vm, l2_word func_id,
  394. l2_word argc, l2_word *argv) {
  395. struct l2_vm_value *func = &vm->values[func_id];
  396. enum l2_value_type typ = l2_value_get_type(func);
  397. // C functions are called differently from language functions
  398. if (typ == L2_VAL_TYPE_CFUNCTION) {
  399. vm->stack[vm->sptr++] = func->cfunc(vm, argc, argv);
  400. after_cfunc_return(vm);
  401. return;
  402. }
  403. // Don't interpret a non-function as a function
  404. if (typ != L2_VAL_TYPE_FUNCTION) {
  405. vm->stack[vm->sptr++] = l2_vm_error(vm, "Attempt to call non-function");
  406. return;
  407. }
  408. l2_word args_id = alloc_val(vm);
  409. struct l2_vm_value *args = &vm->values[args_id];
  410. args->flags = L2_VAL_TYPE_ARRAY | L2_VAL_SBO;
  411. args->extra.arr_length = argc;
  412. if (argc > 0) {
  413. if (argc <= 2) {
  414. memcpy(args->shortarray, argv, argc * sizeof(l2_word));
  415. } else {
  416. args->flags = L2_VAL_TYPE_ARRAY;
  417. args->array = malloc(
  418. sizeof(struct l2_vm_array) + sizeof(l2_word) * argc);
  419. args->array->size = argc;
  420. memcpy(args->array->data, argv, argc * sizeof(l2_word));
  421. }
  422. }
  423. call_func_with_args(vm, func_id, args_id);
  424. }
  425. static l2_word read_u4le(struct l2_vm *vm) {
  426. unsigned char *data = &vm->ops[vm->iptr];
  427. l2_word ret =
  428. (l2_word)data[0] |
  429. (l2_word)data[1] << 8 |
  430. (l2_word)data[2] << 16 |
  431. (l2_word)data[3] << 24;
  432. vm->iptr += 4;
  433. return ret;
  434. }
  435. static l2_word read_u1le(struct l2_vm *vm) {
  436. return vm->ops[vm->iptr++];
  437. }
  438. static double read_d8le(struct l2_vm *vm) {
  439. unsigned char *data = &vm->ops[vm->iptr];
  440. uint64_t integer = 0 |
  441. (uint64_t)data[0] |
  442. (uint64_t)data[1] << 8 |
  443. (uint64_t)data[2] << 16 |
  444. (uint64_t)data[3] << 24 |
  445. (uint64_t)data[4] << 32 |
  446. (uint64_t)data[5] << 40 |
  447. (uint64_t)data[6] << 48 |
  448. (uint64_t)data[7] << 56;
  449. double num;
  450. memcpy(&num, &integer, 8);
  451. vm->iptr += 8;
  452. return num;
  453. }
  454. void l2_vm_step(struct l2_vm *vm) {
  455. if (vm->need_check_retval) {
  456. vm->need_check_retval = 0;
  457. after_func_return(vm);
  458. if (vm->need_gc) {
  459. vm->need_gc = 0;
  460. l2_vm_gc(vm);
  461. }
  462. return;
  463. }
  464. enum l2_opcode opcode = (enum l2_opcode)vm->ops[vm->iptr++];
  465. l2_word word;
  466. switch (opcode) {
  467. case L2_OP_NOP:
  468. break;
  469. case L2_OP_DISCARD:
  470. vm->sptr -= 1;
  471. if (l2_value_get_type(&vm->values[vm->stack[vm->sptr]]) == L2_VAL_TYPE_ERROR) {
  472. l2_io_printf(vm->std_error, "Error: %s\n", vm->values[vm->stack[vm->sptr]].error);
  473. vm->halted = 1;
  474. }
  475. break;
  476. case L2_OP_SWAP_DISCARD:
  477. vm->stack[vm->sptr - 2] = vm->stack[vm->sptr - 1];
  478. vm->sptr -= 1;
  479. if (l2_value_get_type(&vm->values[vm->stack[vm->sptr]]) == L2_VAL_TYPE_ERROR) {
  480. l2_io_printf(vm->std_error, "Error: %s\n", vm->values[vm->stack[vm->sptr]].error);
  481. vm->halted = 1;
  482. }
  483. break;
  484. case L2_OP_DUP:
  485. vm->stack[vm->sptr] = vm->ops[vm->sptr - 1];
  486. vm->sptr += 1;
  487. break;
  488. case L2_OP_ADD:
  489. vm->stack[vm->sptr - 2] += vm->stack[vm->sptr - 1];
  490. vm->sptr -= 1;
  491. break;
  492. #define X(read) \
  493. l2_word argc = read(vm); \
  494. vm->sptr -= argc; \
  495. l2_word *argv = vm->stack + vm->sptr; \
  496. l2_word func_id = vm->stack[--vm->sptr]; \
  497. call_func(vm, func_id, argc, argv)
  498. case L2_OP_FUNC_CALL_U4: { X(read_u4le); } break;
  499. case L2_OP_FUNC_CALL_U1: { X(read_u1le); } break;
  500. #undef X
  501. #define X(read) word = read(vm); vm->iptr += word;
  502. case L2_OP_RJMP_U4: { X(read_u4le); } break;
  503. case L2_OP_RJMP_U1: { X(read_u1le); } break;
  504. #undef X
  505. #define X(read) \
  506. l2_word key = read(vm); \
  507. struct l2_vm_value *ns = &vm->values[vm->fstack[vm->fsptr - 1].ns]; \
  508. vm->stack[vm->sptr++] = l2_vm_namespace_get(vm, ns, key);
  509. case L2_OP_STACK_FRAME_LOOKUP_U4: { X(read_u4le); } break;
  510. case L2_OP_STACK_FRAME_LOOKUP_U1: { X(read_u1le); } break;
  511. #undef X
  512. #define X(read) \
  513. l2_word key = read(vm); \
  514. l2_word val = vm->stack[vm->sptr - 1]; \
  515. struct l2_vm_value *ns = &vm->values[vm->fstack[vm->fsptr - 1].ns]; \
  516. l2_vm_namespace_set(ns, key, val);
  517. case L2_OP_STACK_FRAME_SET_U4: { X(read_u4le); } break;
  518. case L2_OP_STACK_FRAME_SET_U1: { X(read_u1le); } break;
  519. #undef X
  520. #define X(read) \
  521. l2_word key = read(vm); \
  522. l2_word val = vm->stack[vm->sptr - 1]; \
  523. struct l2_vm_value *ns = &vm->values[vm->fstack[vm->fsptr - 1].ns]; \
  524. if (l2_vm_namespace_replace(vm, ns, key, val) < 0) { \
  525. vm->stack[vm->sptr - 1] = l2_vm_error(vm, "Variable not found"); \
  526. }
  527. case L2_OP_STACK_FRAME_REPLACE_U4: { X(read_u4le); } break;
  528. case L2_OP_STACK_FRAME_REPLACE_U1: { X(read_u1le); } break;
  529. #undef X
  530. case L2_OP_RET:
  531. {
  532. l2_word retval = vm->stack[--vm->sptr];
  533. l2_word retptr = vm->fstack[vm->fsptr - 1].retptr;
  534. l2_word sptr = vm->fstack[vm->fsptr - 1].sptr;
  535. vm->fsptr -= 1;
  536. vm->sptr = sptr;
  537. vm->iptr = retptr;
  538. vm->stack[vm->sptr++] = retval;
  539. after_func_return(vm);
  540. }
  541. break;
  542. case L2_OP_ALLOC_NONE:
  543. vm->stack[vm->sptr++] = 0;
  544. break;
  545. #define X(read) \
  546. word = alloc_val(vm); \
  547. vm->values[word].flags = L2_VAL_TYPE_ATOM; \
  548. vm->values[word].atom = read(vm); \
  549. vm->stack[vm->sptr++] = word;
  550. case L2_OP_ALLOC_ATOM_U4: { X(read_u4le); } break;
  551. case L2_OP_ALLOC_ATOM_U1: { X(read_u1le); } break;
  552. #undef X
  553. case L2_OP_ALLOC_REAL_D8:
  554. {
  555. word = alloc_val(vm);
  556. vm->values[word].flags = L2_VAL_TYPE_REAL;
  557. vm->values[word].real = read_d8le(vm);
  558. vm->stack[vm->sptr++] = word;
  559. }
  560. break;
  561. #define X(read) \
  562. word = alloc_val(vm); \
  563. l2_word length = read(vm); \
  564. l2_word offset = read(vm); \
  565. vm->values[word].flags = L2_VAL_TYPE_BUFFER; \
  566. vm->values[word].buffer = length > 0 ? malloc(length) : NULL; \
  567. vm->values[word].extra.buf_length = length; \
  568. memcpy(vm->values[word].buffer, vm->ops + offset, length); \
  569. vm->stack[vm->sptr] = word; \
  570. vm->sptr += 1;
  571. case L2_OP_ALLOC_BUFFER_STATIC_U4: { X(read_u4le); } break;
  572. case L2_OP_ALLOC_BUFFER_STATIC_U1: { X(read_u1le); } break;
  573. #undef X
  574. #define X(read) \
  575. l2_word count = read(vm); \
  576. l2_word arr_id = alloc_val(vm); \
  577. struct l2_vm_value *arr = &vm->values[arr_id]; \
  578. arr->extra.arr_length = count; \
  579. l2_word *data; \
  580. if (count <= 2) { \
  581. arr->flags = L2_VAL_TYPE_ARRAY | L2_VAL_SBO; \
  582. data = arr->shortarray; \
  583. } else { \
  584. arr->flags = L2_VAL_TYPE_ARRAY; \
  585. arr->array = malloc(sizeof(struct l2_vm_array) + count * sizeof(l2_word)); \
  586. arr->array->size = count; \
  587. data = arr->array->data; \
  588. } \
  589. for (l2_word i = 0; i < count; ++i) { \
  590. data[count - 1 - i] = vm->stack[--vm->sptr]; \
  591. } \
  592. vm->stack[vm->sptr++] = arr_id;
  593. case L2_OP_ALLOC_ARRAY_U4: { X(read_u4le); } break;
  594. case L2_OP_ALLOC_ARRAY_U1: { X(read_u1le); } break;
  595. #undef X
  596. case L2_OP_ALLOC_NAMESPACE:
  597. word = alloc_val(vm);
  598. vm->values[word].flags = L2_VAL_TYPE_NAMESPACE;
  599. vm->values[word].extra.ns_parent = 0;
  600. vm->values[word].ns = NULL; // Will be allocated on first insert
  601. vm->stack[vm->sptr] = word;
  602. vm->sptr += 1;
  603. break;
  604. #define X(read) \
  605. word = alloc_val(vm); \
  606. vm->values[word].flags = L2_VAL_TYPE_FUNCTION; \
  607. vm->values[word].func.pos = read(vm); \
  608. vm->values[word].func.ns = vm->fstack[vm->fsptr - 1].ns; \
  609. vm->stack[vm->sptr] = word; \
  610. vm->sptr += 1;
  611. case L2_OP_ALLOC_FUNCTION_U4: { X(read_u4le); } break;
  612. case L2_OP_ALLOC_FUNCTION_U1: { X(read_u1le); } break;
  613. #undef X
  614. #define X(read) \
  615. l2_word key = read(vm); \
  616. l2_word val = vm->stack[vm->sptr - 1]; \
  617. l2_word ns = vm->stack[vm->sptr - 2]; \
  618. l2_vm_namespace_set(&vm->values[ns], key, val);
  619. case L2_OP_NAMESPACE_SET_U4: { X(read_u4le); } break;
  620. case L2_OP_NAMESPACE_SET_U1: { X(read_u1le); } break;
  621. #undef X
  622. #define X(read) \
  623. l2_word key = read(vm); \
  624. l2_word ns = vm->stack[--vm->sptr]; \
  625. vm->stack[vm->sptr++] = l2_vm_namespace_get(vm, &vm->values[ns], key);
  626. case L2_OP_NAMESPACE_LOOKUP_U4: { X(read_u4le); } break;
  627. case L2_OP_NAMESPACE_LOOKUP_U1: { X(read_u1le); } break;
  628. #undef X
  629. #define X(read) \
  630. l2_word key = read(vm); \
  631. l2_word arr_id = vm->stack[--vm->sptr]; \
  632. struct l2_vm_value *arr = &vm->values[arr_id]; \
  633. if (l2_value_get_type(arr) != L2_VAL_TYPE_ARRAY) { \
  634. vm->stack[vm->sptr++] = l2_vm_type_error(vm, arr); \
  635. } else { \
  636. vm->stack[vm->sptr++] = l2_value_arr_get(vm, arr, key); \
  637. }
  638. case L2_OP_ARRAY_LOOKUP_U4: { X(read_u4le); } break;
  639. case L2_OP_ARRAY_LOOKUP_U1: { X(read_u1le); } break;
  640. #undef X
  641. #define X(read) \
  642. l2_word key = read(vm); \
  643. l2_word val = vm->stack[vm->sptr - 1]; \
  644. l2_word arr_id = vm->stack[vm->sptr - 2]; \
  645. struct l2_vm_value *arr = &vm->values[arr_id]; \
  646. if (l2_value_get_type(arr) != L2_VAL_TYPE_ARRAY) { \
  647. vm->stack[vm->sptr - 1] = l2_vm_type_error(vm, arr); \
  648. } else { \
  649. vm->stack[vm->sptr - 1] = l2_value_arr_set(vm, arr, key, val); \
  650. }
  651. case L2_OP_ARRAY_SET_U4: { X(read_u4le); } break;
  652. case L2_OP_ARRAY_SET_U1: { X(read_u1le); } break;
  653. case L2_OP_DYNAMIC_LOOKUP:
  654. {
  655. l2_word key_id = vm->stack[--vm->sptr];
  656. l2_word container_id = vm->stack[--vm->sptr];
  657. struct l2_vm_value *key = &vm->values[key_id];
  658. struct l2_vm_value *container = &vm->values[container_id];
  659. if (l2_value_get_type(container) == L2_VAL_TYPE_ARRAY) {
  660. if (l2_value_get_type(key) != L2_VAL_TYPE_REAL) {
  661. vm->stack[vm->sptr++] = l2_vm_type_error(vm, key);
  662. } else if (key->real >= container->extra.arr_length) {
  663. vm->stack[vm->sptr++] = l2_vm_error(vm, "Index out of range");
  664. } else {
  665. vm->stack[vm->sptr++] = container->array->data[(l2_word)key->real];
  666. }
  667. } else if (l2_value_get_type(container) == L2_VAL_TYPE_NAMESPACE) {
  668. if (l2_value_get_type(key) != L2_VAL_TYPE_ATOM) {
  669. vm->stack[vm->sptr++] = l2_vm_type_error(vm, key);
  670. } else {
  671. vm->stack[vm->sptr++] = l2_vm_namespace_get(vm, container, key->atom);
  672. }
  673. } else {
  674. vm->stack[vm->sptr++] = l2_vm_type_error(vm, container);
  675. }
  676. }
  677. break;
  678. case L2_OP_DYNAMIC_SET:
  679. {
  680. l2_word val = vm->stack[--vm->sptr];
  681. l2_word key_id = vm->stack[--vm->sptr];
  682. l2_word container_id = vm->stack[--vm->sptr];
  683. vm->stack[vm->sptr++] = val;
  684. struct l2_vm_value *key = &vm->values[key_id];
  685. struct l2_vm_value *container = &vm->values[container_id];
  686. if (l2_value_get_type(container) == L2_VAL_TYPE_ARRAY) {
  687. if (l2_value_get_type(key) != L2_VAL_TYPE_REAL) {
  688. vm->stack[vm->sptr - 1] = l2_vm_type_error(vm, key);
  689. } else if (key->real >= container->extra.arr_length) {
  690. vm->stack[vm->sptr - 1] = l2_vm_error(vm, "Index out of range");
  691. } else {
  692. container->array->data[(size_t)key->real] = val;
  693. }
  694. } else if (l2_value_get_type(container) == L2_VAL_TYPE_NAMESPACE) {
  695. if (l2_value_get_type(key) != L2_VAL_TYPE_ATOM) {
  696. vm->stack[vm->sptr - 1] = l2_vm_type_error(vm, key);
  697. } else {
  698. l2_vm_namespace_set(container, key->atom, val);
  699. }
  700. } else {
  701. vm->stack[vm->sptr - 1] = l2_vm_type_error(vm, container);
  702. }
  703. }
  704. break;
  705. case L2_OP_FUNC_CALL_INFIX:
  706. {
  707. l2_word rhs = vm->stack[--vm->sptr];
  708. l2_word func_id = vm->stack[--vm->sptr];
  709. l2_word lhs = vm->stack[--vm->sptr];
  710. l2_word argv[] = {lhs, rhs};
  711. call_func(vm, func_id, 2, argv);
  712. }
  713. break;
  714. case L2_OP_HALT:
  715. vm->halted = 1;
  716. break;
  717. }
  718. if (vm->need_gc) {
  719. vm->need_gc = 0;
  720. l2_vm_gc(vm);
  721. }
  722. }
  723. int l2_vm_val_is_true(struct l2_vm *vm, struct l2_vm_value *val) {
  724. l2_word true_atom = vm->values[vm->ktrue].atom;
  725. return l2_value_get_type(val) == L2_VAL_TYPE_ATOM && val->atom == true_atom;
  726. }