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

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856
  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->fstack[vm->fsptr].args = 0;
  196. vm->fsptr += 1;
  197. // Need to allocate a root namespace
  198. l2_word root = alloc_val(vm);
  199. vm->values[root].extra.ns_parent = builtins;
  200. vm->values[root].ns = NULL;
  201. vm->values[root].flags = L2_VAL_TYPE_NAMESPACE;
  202. vm->fstack[vm->fsptr].ns = root;
  203. vm->fstack[vm->fsptr].retptr = ~(l2_word)0;
  204. vm->fstack[vm->fsptr].sptr = 0;
  205. vm->fstack[vm->fsptr].args = 0;
  206. vm->fsptr += 1;
  207. // None is always at 0
  208. vm->knone = 0;
  209. vm->values[vm->knone].flags = L2_VAL_TYPE_NONE | L2_VAL_CONST;
  210. // Define a C function variable for every builtin
  211. l2_word id;
  212. l2_word key = 1;
  213. #define XNAME(name, k) \
  214. l2_vm_namespace_set(&vm->values[builtins], key, vm->k); \
  215. key += 1;
  216. #define XATOM(name, k) \
  217. id = alloc_val(vm); \
  218. vm->values[id].flags = L2_VAL_TYPE_ATOM | L2_VAL_CONST; \
  219. vm->values[id].atom = key; \
  220. vm->k = id; \
  221. key += 1;
  222. #define XFUNCTION(name, f) \
  223. id = alloc_val(vm); \
  224. vm->values[id].flags = L2_VAL_TYPE_CFUNCTION | L2_VAL_CONST; \
  225. vm->values[id].cfunc = f; \
  226. l2_vm_namespace_set(&vm->values[builtins], key, id); \
  227. key += 1;
  228. #include "builtins.x.h"
  229. #undef XNAME
  230. #undef XATOM
  231. #undef XFUNCTION
  232. vm->gc_start = id + 1;
  233. }
  234. l2_word l2_vm_alloc(struct l2_vm *vm, enum l2_value_type typ, enum l2_value_flags flags) {
  235. l2_word id = alloc_val(vm);
  236. memset(&vm->values[id], 0, sizeof(vm->values[id]));
  237. vm->values[id].flags = typ | flags;
  238. return id;
  239. }
  240. l2_word l2_vm_error(struct l2_vm *vm, const char *fmt, ...) {
  241. l2_word id = alloc_val(vm);
  242. struct l2_vm_value *val = &vm->values[id];
  243. val->flags = L2_VAL_CONST | L2_VAL_TYPE_ERROR;
  244. char buf[256];
  245. va_list va;
  246. va_start(va, fmt);
  247. int n = vsnprintf(buf, sizeof(buf), fmt, va);
  248. if (n < 0) {
  249. const char *message = "Failed to generate error message!";
  250. val->error = malloc(strlen(message) + 1);
  251. strcpy(val->error, message);
  252. va_end(va);
  253. return id;
  254. } else if ((size_t)n + 1 < sizeof(buf)) {
  255. val->error = malloc(n + 1);
  256. strcpy(val->error, buf);
  257. va_end(va);
  258. return id;
  259. }
  260. val->error = malloc(n + 1);
  261. vsnprintf(val->error, n + 1, fmt, va);
  262. va_end(va);
  263. return id;
  264. }
  265. l2_word l2_vm_type_error(struct l2_vm *vm, struct l2_vm_value *val) {
  266. enum l2_value_type typ = l2_value_get_type(val);
  267. if (typ == L2_VAL_TYPE_ERROR) {
  268. return val - vm->values;
  269. }
  270. return l2_vm_error(vm, "Unexpected type %s", l2_value_type_name(l2_value_get_type(val)));
  271. }
  272. void l2_vm_free(struct l2_vm *vm) {
  273. // Skip ID 0, because that's always NONE
  274. for (size_t i = 1; i < vm->valuessize; ++i) {
  275. if (!l2_bitset_get(&vm->valueset, i)) {
  276. continue;
  277. }
  278. gc_free(vm, i);
  279. }
  280. free(vm->values);
  281. l2_bitset_free(&vm->valueset);
  282. }
  283. size_t l2_vm_gc(struct l2_vm *vm) {
  284. for (l2_word sptr = 0; sptr < vm->sptr; ++sptr) {
  285. gc_mark(vm, vm->stack[sptr]);
  286. }
  287. // Don't need to mark the first stack frame, since that's where all the
  288. // builtins live, and they aren't sweeped anyways
  289. for (l2_word fsptr = 1; fsptr < vm->fsptr; ++fsptr) {
  290. gc_mark(vm, vm->fstack[fsptr].ns);
  291. gc_mark(vm, vm->fstack[fsptr].args);
  292. }
  293. return gc_sweep(vm);
  294. }
  295. void l2_vm_run(struct l2_vm *vm) {
  296. while (!vm->halted) {
  297. l2_vm_step(vm);
  298. }
  299. }
  300. static void call_func_with_args(
  301. struct l2_vm *vm, l2_word func_id, l2_word args_id);
  302. static void call_func(
  303. struct l2_vm *vm, l2_word func_id,
  304. l2_word argc, l2_word *argv);
  305. static void after_cfunc_return(struct l2_vm *vm) {
  306. if (
  307. l2_value_get_type(&vm->values[vm->stack[vm->sptr - 1]]) ==
  308. L2_VAL_TYPE_RETURN ||
  309. l2_value_get_type(&vm->values[vm->stack[vm->sptr - 1]]) ==
  310. L2_VAL_TYPE_CONTINUATION ||
  311. (vm->sptr >= 2 &&
  312. l2_value_get_type(&vm->values[vm->stack[vm->sptr - 2]]) ==
  313. L2_VAL_TYPE_CONTINUATION)) {
  314. vm->need_check_retval = 1;
  315. }
  316. }
  317. static void after_func_return(struct l2_vm *vm) {
  318. struct l2_vm_value *ret = &vm->values[vm->stack[vm->sptr - 1]];
  319. if (l2_value_get_type(ret) == L2_VAL_TYPE_RETURN) {
  320. l2_word retval = ret->ret;
  321. l2_word retptr = vm->fstack[vm->fsptr - 1].retptr;
  322. l2_word sptr = vm->fstack[vm->fsptr - 1].sptr;
  323. if (retptr == ~(l2_word)0) {
  324. vm->halted = 1;
  325. return;
  326. }
  327. vm->fsptr -= 1;
  328. vm->sptr = sptr;
  329. vm->iptr = retptr;
  330. vm->stack[vm->sptr++] = retval;
  331. after_func_return(vm);
  332. return;
  333. }
  334. // If the function returns a continuation, we leave that continuation
  335. // on the stack to be handled later, then call the function
  336. if (l2_value_get_type(ret) == L2_VAL_TYPE_CONTINUATION) {
  337. if (ret->cont && ret->cont->args != vm->knone) {
  338. struct l2_vm_value *args = &vm->values[ret->cont->args];
  339. struct l2_vm_value *func = &vm->values[ret->extra.cont_call];
  340. // We can optimize calling a non-C function by re-using the
  341. // args array rather than allocating a new one
  342. if (l2_value_get_type(func) == L2_VAL_TYPE_FUNCTION) {
  343. call_func_with_args(vm, ret->extra.cont_call, ret->cont->args);
  344. } else {
  345. call_func(
  346. vm, ret->extra.cont_call, args->extra.arr_length,
  347. l2_value_arr_data(vm, args));
  348. }
  349. } else {
  350. call_func(vm, ret->extra.cont_call, 0, NULL);
  351. }
  352. return;
  353. }
  354. // If the value right below the returned value is a continuation,
  355. // it's a continuation left on the stack to be handled later - i.e now
  356. if (
  357. vm->sptr >= 2 &&
  358. l2_value_get_type(&vm->values[vm->stack[vm->sptr - 2]]) ==
  359. L2_VAL_TYPE_CONTINUATION) {
  360. struct l2_vm_value *cont = &vm->values[vm->stack[vm->sptr - 2]];
  361. // If it's just a basic continuation, don't need to do anything
  362. if (cont->cont == NULL || cont->cont->callback == NULL) {
  363. // Return the return value of the function, discard the continuation
  364. vm->stack[vm->sptr - 2] = vm->stack[vm->sptr - 1];
  365. vm->sptr -= 1;
  366. return;
  367. }
  368. // After this, the original return value and the continuation
  369. // are both replaced by whatever the callback returned
  370. l2_word contret = cont->cont->callback(
  371. vm, vm->stack[vm->sptr - 1], vm->stack[vm->sptr - 2]);
  372. vm->stack[vm->sptr - 2] = contret;
  373. vm->sptr -= 1;
  374. after_func_return(vm);
  375. return;
  376. }
  377. }
  378. static void call_func_with_args(struct l2_vm *vm, l2_word func_id, l2_word args_id) {
  379. l2_word ns_id = alloc_val(vm);
  380. struct l2_vm_value *func = &vm->values[func_id]; // func might be stale after alloc_val
  381. vm->values[ns_id].extra.ns_parent = func->func.ns;
  382. vm->values[ns_id].ns = NULL;
  383. vm->values[ns_id].flags = L2_VAL_TYPE_NAMESPACE;
  384. vm->fstack[vm->fsptr].ns = ns_id;
  385. vm->fstack[vm->fsptr].retptr = vm->iptr;
  386. vm->fstack[vm->fsptr].sptr = vm->sptr;
  387. vm->fstack[vm->fsptr].args = args_id;
  388. vm->fsptr += 1;
  389. vm->iptr = func->func.pos;
  390. // We need one value as a buffer between the previous stack frame and the new.
  391. // This is mostly due to the way continuations are handled.
  392. // This wouldn't be necessary if continuations were stored in the stack
  393. // frame struct rather than as a value on the stack.
  394. vm->stack[vm->sptr++] = vm->knone;
  395. }
  396. // The 'call_func' function assumes that all relevant values have been popped off
  397. // the stack, so that the return value can be pushed to the top of the stack
  398. // straight away
  399. static void call_func(
  400. struct l2_vm *vm, l2_word func_id,
  401. l2_word argc, l2_word *argv) {
  402. struct l2_vm_value *func = &vm->values[func_id];
  403. enum l2_value_type typ = l2_value_get_type(func);
  404. // C functions are called differently from language functions
  405. if (typ == L2_VAL_TYPE_CFUNCTION) {
  406. vm->stack[vm->sptr++] = func->cfunc(vm, argc, argv);
  407. after_cfunc_return(vm);
  408. return;
  409. }
  410. // Don't interpret a non-function as a function
  411. if (typ != L2_VAL_TYPE_FUNCTION) {
  412. vm->stack[vm->sptr++] = l2_vm_error(vm, "Attempt to call non-function");
  413. return;
  414. }
  415. l2_word args_id = alloc_val(vm);
  416. struct l2_vm_value *args = &vm->values[args_id];
  417. args->flags = L2_VAL_TYPE_ARRAY | L2_VAL_SBO;
  418. args->extra.arr_length = argc;
  419. if (argc > 0) {
  420. if (argc <= 2) {
  421. memcpy(args->shortarray, argv, argc * sizeof(l2_word));
  422. } else {
  423. args->flags = L2_VAL_TYPE_ARRAY;
  424. args->array = malloc(
  425. sizeof(struct l2_vm_array) + sizeof(l2_word) * argc);
  426. args->array->size = argc;
  427. memcpy(args->array->data, argv, argc * sizeof(l2_word));
  428. }
  429. }
  430. call_func_with_args(vm, func_id, args_id);
  431. }
  432. static l2_word read_u4le(struct l2_vm *vm) {
  433. unsigned char *data = &vm->ops[vm->iptr];
  434. l2_word ret =
  435. (l2_word)data[0] |
  436. (l2_word)data[1] << 8 |
  437. (l2_word)data[2] << 16 |
  438. (l2_word)data[3] << 24;
  439. vm->iptr += 4;
  440. return ret;
  441. }
  442. static l2_word read_u1le(struct l2_vm *vm) {
  443. return vm->ops[vm->iptr++];
  444. }
  445. static double read_d8le(struct l2_vm *vm) {
  446. unsigned char *data = &vm->ops[vm->iptr];
  447. uint64_t integer = 0 |
  448. (uint64_t)data[0] |
  449. (uint64_t)data[1] << 8 |
  450. (uint64_t)data[2] << 16 |
  451. (uint64_t)data[3] << 24 |
  452. (uint64_t)data[4] << 32 |
  453. (uint64_t)data[5] << 40 |
  454. (uint64_t)data[6] << 48 |
  455. (uint64_t)data[7] << 56;
  456. double num;
  457. memcpy(&num, &integer, 8);
  458. vm->iptr += 8;
  459. return num;
  460. }
  461. void l2_vm_step(struct l2_vm *vm) {
  462. if (vm->need_check_retval) {
  463. vm->need_check_retval = 0;
  464. after_func_return(vm);
  465. if (vm->need_gc) {
  466. vm->need_gc = 0;
  467. l2_vm_gc(vm);
  468. }
  469. return;
  470. }
  471. enum l2_opcode opcode = (enum l2_opcode)vm->ops[vm->iptr++];
  472. l2_word word;
  473. switch (opcode) {
  474. case L2_OP_NOP:
  475. break;
  476. case L2_OP_DISCARD:
  477. vm->sptr -= 1;
  478. if (l2_value_get_type(&vm->values[vm->stack[vm->sptr]]) == L2_VAL_TYPE_ERROR) {
  479. l2_io_printf(vm->std_error, "Error: %s\n", vm->values[vm->stack[vm->sptr]].error);
  480. vm->halted = 1;
  481. }
  482. break;
  483. case L2_OP_SWAP_DISCARD:
  484. vm->stack[vm->sptr - 2] = vm->stack[vm->sptr - 1];
  485. vm->sptr -= 1;
  486. if (l2_value_get_type(&vm->values[vm->stack[vm->sptr]]) == L2_VAL_TYPE_ERROR) {
  487. l2_io_printf(vm->std_error, "Error: %s\n", vm->values[vm->stack[vm->sptr]].error);
  488. vm->halted = 1;
  489. }
  490. break;
  491. case L2_OP_DUP:
  492. vm->stack[vm->sptr] = vm->ops[vm->sptr - 1];
  493. vm->sptr += 1;
  494. break;
  495. case L2_OP_ADD:
  496. vm->stack[vm->sptr - 2] += vm->stack[vm->sptr - 1];
  497. vm->sptr -= 1;
  498. break;
  499. #define X(read) \
  500. l2_word argc = read(vm); \
  501. vm->sptr -= argc; \
  502. l2_word *argv = vm->stack + vm->sptr; \
  503. l2_word func_id = vm->stack[--vm->sptr]; \
  504. call_func(vm, func_id, argc, argv)
  505. case L2_OP_FUNC_CALL_U4: { X(read_u4le); } break;
  506. case L2_OP_FUNC_CALL_U1: { X(read_u1le); } break;
  507. #undef X
  508. #define X(read) word = read(vm); vm->iptr += word;
  509. case L2_OP_RJMP_U4: { X(read_u4le); } break;
  510. case L2_OP_RJMP_U1: { X(read_u1le); } break;
  511. #undef X
  512. case L2_OP_STACK_FRAME_GET_ARGS:
  513. vm->stack[vm->sptr++] = vm->fstack[vm->fsptr - 1].args;
  514. break;
  515. #define X(read) \
  516. l2_word key = read(vm); \
  517. struct l2_vm_value *ns = &vm->values[vm->fstack[vm->fsptr - 1].ns]; \
  518. vm->stack[vm->sptr++] = l2_vm_namespace_get(vm, ns, key);
  519. case L2_OP_STACK_FRAME_LOOKUP_U4: { X(read_u4le); } break;
  520. case L2_OP_STACK_FRAME_LOOKUP_U1: { X(read_u1le); } break;
  521. #undef X
  522. #define X(read) \
  523. l2_word key = read(vm); \
  524. l2_word val = vm->stack[vm->sptr - 1]; \
  525. struct l2_vm_value *ns = &vm->values[vm->fstack[vm->fsptr - 1].ns]; \
  526. l2_vm_namespace_set(ns, key, val);
  527. case L2_OP_STACK_FRAME_SET_U4: { X(read_u4le); } break;
  528. case L2_OP_STACK_FRAME_SET_U1: { X(read_u1le); } break;
  529. #undef X
  530. #define X(read) \
  531. l2_word key = read(vm); \
  532. l2_word val = vm->stack[vm->sptr - 1]; \
  533. struct l2_vm_value *ns = &vm->values[vm->fstack[vm->fsptr - 1].ns]; \
  534. if (l2_vm_namespace_replace(vm, ns, key, val) < 0) { \
  535. vm->stack[vm->sptr - 1] = l2_vm_error(vm, "Variable not found"); \
  536. }
  537. case L2_OP_STACK_FRAME_REPLACE_U4: { X(read_u4le); } break;
  538. case L2_OP_STACK_FRAME_REPLACE_U1: { X(read_u1le); } break;
  539. #undef X
  540. case L2_OP_RET:
  541. {
  542. l2_word retval = vm->stack[--vm->sptr];
  543. l2_word retptr = vm->fstack[vm->fsptr - 1].retptr;
  544. l2_word sptr = vm->fstack[vm->fsptr - 1].sptr;
  545. vm->fsptr -= 1;
  546. vm->sptr = sptr;
  547. vm->iptr = retptr;
  548. vm->stack[vm->sptr++] = retval;
  549. after_func_return(vm);
  550. }
  551. break;
  552. case L2_OP_ALLOC_NONE:
  553. vm->stack[vm->sptr++] = 0;
  554. break;
  555. #define X(read) \
  556. word = alloc_val(vm); \
  557. vm->values[word].flags = L2_VAL_TYPE_ATOM; \
  558. vm->values[word].atom = read(vm); \
  559. vm->stack[vm->sptr++] = word;
  560. case L2_OP_ALLOC_ATOM_U4: { X(read_u4le); } break;
  561. case L2_OP_ALLOC_ATOM_U1: { X(read_u1le); } break;
  562. #undef X
  563. case L2_OP_ALLOC_REAL_D8:
  564. {
  565. word = alloc_val(vm);
  566. vm->values[word].flags = L2_VAL_TYPE_REAL;
  567. vm->values[word].real = read_d8le(vm);
  568. vm->stack[vm->sptr++] = word;
  569. }
  570. break;
  571. #define X(read) \
  572. word = alloc_val(vm); \
  573. l2_word length = read(vm); \
  574. l2_word offset = read(vm); \
  575. vm->values[word].flags = L2_VAL_TYPE_BUFFER; \
  576. vm->values[word].buffer = length > 0 ? malloc(length) : NULL; \
  577. vm->values[word].extra.buf_length = length; \
  578. memcpy(vm->values[word].buffer, vm->ops + offset, length); \
  579. vm->stack[vm->sptr] = word; \
  580. vm->sptr += 1;
  581. case L2_OP_ALLOC_BUFFER_STATIC_U4: { X(read_u4le); } break;
  582. case L2_OP_ALLOC_BUFFER_STATIC_U1: { X(read_u1le); } break;
  583. #undef X
  584. #define X(read) \
  585. l2_word count = read(vm); \
  586. l2_word arr_id = alloc_val(vm); \
  587. struct l2_vm_value *arr = &vm->values[arr_id]; \
  588. arr->extra.arr_length = count; \
  589. l2_word *data; \
  590. if (count <= 2) { \
  591. arr->flags = L2_VAL_TYPE_ARRAY | L2_VAL_SBO; \
  592. data = arr->shortarray; \
  593. } else { \
  594. arr->flags = L2_VAL_TYPE_ARRAY; \
  595. arr->array = malloc(sizeof(struct l2_vm_array) + count * sizeof(l2_word)); \
  596. arr->array->size = count; \
  597. data = arr->array->data; \
  598. } \
  599. for (l2_word i = 0; i < count; ++i) { \
  600. data[count - 1 - i] = vm->stack[--vm->sptr]; \
  601. } \
  602. vm->stack[vm->sptr++] = arr_id;
  603. case L2_OP_ALLOC_ARRAY_U4: { X(read_u4le); } break;
  604. case L2_OP_ALLOC_ARRAY_U1: { X(read_u1le); } break;
  605. #undef X
  606. case L2_OP_ALLOC_NAMESPACE:
  607. word = alloc_val(vm);
  608. vm->values[word].flags = L2_VAL_TYPE_NAMESPACE;
  609. vm->values[word].extra.ns_parent = 0;
  610. vm->values[word].ns = NULL; // Will be allocated on first insert
  611. vm->stack[vm->sptr] = word;
  612. vm->sptr += 1;
  613. break;
  614. #define X(read) \
  615. word = alloc_val(vm); \
  616. vm->values[word].flags = L2_VAL_TYPE_FUNCTION; \
  617. vm->values[word].func.pos = read(vm); \
  618. vm->values[word].func.ns = vm->fstack[vm->fsptr - 1].ns; \
  619. vm->stack[vm->sptr] = word; \
  620. vm->sptr += 1;
  621. case L2_OP_ALLOC_FUNCTION_U4: { X(read_u4le); } break;
  622. case L2_OP_ALLOC_FUNCTION_U1: { X(read_u1le); } break;
  623. #undef X
  624. #define X(read) \
  625. l2_word key = read(vm); \
  626. l2_word val = vm->stack[vm->sptr - 1]; \
  627. l2_word ns = vm->stack[vm->sptr - 2]; \
  628. l2_vm_namespace_set(&vm->values[ns], key, val);
  629. case L2_OP_NAMESPACE_SET_U4: { X(read_u4le); } break;
  630. case L2_OP_NAMESPACE_SET_U1: { X(read_u1le); } break;
  631. #undef X
  632. #define X(read) \
  633. l2_word key = read(vm); \
  634. l2_word ns = vm->stack[--vm->sptr]; \
  635. vm->stack[vm->sptr++] = l2_vm_namespace_get(vm, &vm->values[ns], key);
  636. case L2_OP_NAMESPACE_LOOKUP_U4: { X(read_u4le); } break;
  637. case L2_OP_NAMESPACE_LOOKUP_U1: { X(read_u1le); } break;
  638. #undef X
  639. #define X(read) \
  640. l2_word key = read(vm); \
  641. l2_word arr_id = vm->stack[--vm->sptr]; \
  642. struct l2_vm_value *arr = &vm->values[arr_id]; \
  643. if (l2_value_get_type(arr) != L2_VAL_TYPE_ARRAY) { \
  644. vm->stack[vm->sptr++] = l2_vm_type_error(vm, arr); \
  645. } else { \
  646. vm->stack[vm->sptr++] = l2_value_arr_get(vm, arr, key); \
  647. }
  648. case L2_OP_ARRAY_LOOKUP_U4: { X(read_u4le); } break;
  649. case L2_OP_ARRAY_LOOKUP_U1: { X(read_u1le); } break;
  650. #undef X
  651. #define X(read) \
  652. l2_word key = read(vm); \
  653. l2_word val = vm->stack[vm->sptr - 1]; \
  654. l2_word arr_id = vm->stack[vm->sptr - 2]; \
  655. struct l2_vm_value *arr = &vm->values[arr_id]; \
  656. if (l2_value_get_type(arr) != L2_VAL_TYPE_ARRAY) { \
  657. vm->stack[vm->sptr - 1] = l2_vm_type_error(vm, arr); \
  658. } else { \
  659. vm->stack[vm->sptr - 1] = l2_value_arr_set(vm, arr, key, val); \
  660. }
  661. case L2_OP_ARRAY_SET_U4: { X(read_u4le); } break;
  662. case L2_OP_ARRAY_SET_U1: { X(read_u1le); } break;
  663. case L2_OP_DYNAMIC_LOOKUP:
  664. {
  665. l2_word key_id = vm->stack[--vm->sptr];
  666. l2_word container_id = vm->stack[--vm->sptr];
  667. struct l2_vm_value *key = &vm->values[key_id];
  668. struct l2_vm_value *container = &vm->values[container_id];
  669. if (l2_value_get_type(container) == L2_VAL_TYPE_ARRAY) {
  670. if (l2_value_get_type(key) != L2_VAL_TYPE_REAL) {
  671. vm->stack[vm->sptr++] = l2_vm_type_error(vm, key);
  672. } else if (key->real >= container->extra.arr_length) {
  673. vm->stack[vm->sptr++] = l2_vm_error(vm, "Index out of range");
  674. } else {
  675. vm->stack[vm->sptr++] = container->array->data[(l2_word)key->real];
  676. }
  677. } else if (l2_value_get_type(container) == L2_VAL_TYPE_NAMESPACE) {
  678. if (l2_value_get_type(key) != L2_VAL_TYPE_ATOM) {
  679. vm->stack[vm->sptr++] = l2_vm_type_error(vm, key);
  680. } else {
  681. vm->stack[vm->sptr++] = l2_vm_namespace_get(vm, container, key->atom);
  682. }
  683. } else {
  684. vm->stack[vm->sptr++] = l2_vm_type_error(vm, container);
  685. }
  686. }
  687. break;
  688. case L2_OP_DYNAMIC_SET:
  689. {
  690. l2_word val = vm->stack[--vm->sptr];
  691. l2_word key_id = vm->stack[--vm->sptr];
  692. l2_word container_id = vm->stack[--vm->sptr];
  693. vm->stack[vm->sptr++] = val;
  694. struct l2_vm_value *key = &vm->values[key_id];
  695. struct l2_vm_value *container = &vm->values[container_id];
  696. if (l2_value_get_type(container) == L2_VAL_TYPE_ARRAY) {
  697. if (l2_value_get_type(key) != L2_VAL_TYPE_REAL) {
  698. vm->stack[vm->sptr - 1] = l2_vm_type_error(vm, key);
  699. } else if (key->real >= container->extra.arr_length) {
  700. vm->stack[vm->sptr - 1] = l2_vm_error(vm, "Index out of range");
  701. } else {
  702. container->array->data[(size_t)key->real] = val;
  703. }
  704. } else if (l2_value_get_type(container) == L2_VAL_TYPE_NAMESPACE) {
  705. if (l2_value_get_type(key) != L2_VAL_TYPE_ATOM) {
  706. vm->stack[vm->sptr - 1] = l2_vm_type_error(vm, key);
  707. } else {
  708. l2_vm_namespace_set(container, key->atom, val);
  709. }
  710. } else {
  711. vm->stack[vm->sptr - 1] = l2_vm_type_error(vm, container);
  712. }
  713. }
  714. break;
  715. case L2_OP_FUNC_CALL_INFIX:
  716. {
  717. l2_word rhs = vm->stack[--vm->sptr];
  718. l2_word func_id = vm->stack[--vm->sptr];
  719. l2_word lhs = vm->stack[--vm->sptr];
  720. l2_word argv[] = {lhs, rhs};
  721. call_func(vm, func_id, 2, argv);
  722. }
  723. break;
  724. case L2_OP_HALT:
  725. vm->halted = 1;
  726. break;
  727. }
  728. if (vm->need_gc) {
  729. vm->need_gc = 0;
  730. l2_vm_gc(vm);
  731. }
  732. }
  733. int l2_vm_val_is_true(struct l2_vm *vm, struct l2_vm_value *val) {
  734. l2_word true_atom = vm->values[vm->ktrue].atom;
  735. return l2_value_get_type(val) == L2_VAL_TYPE_ATOM && val->atom == true_atom;
  736. }