2017-04-18 02:40:39 +00:00
|
|
|
/*
|
2018-05-18 03:41:20 +00:00
|
|
|
* Copyright (c) 2018 Calvin Rose
|
2017-07-02 01:51:16 +00:00
|
|
|
*
|
2017-04-18 02:40:39 +00:00
|
|
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
|
|
* of this software and associated documentation files (the "Software"), to
|
|
|
|
* deal in the Software without restriction, including without limitation the
|
|
|
|
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
|
|
|
* sell copies of the Software, and to permit persons to whom the Software is
|
|
|
|
* furnished to do so, subject to the following conditions:
|
2017-07-02 01:51:16 +00:00
|
|
|
*
|
2017-04-18 02:40:39 +00:00
|
|
|
* The above copyright notice and this permission notice shall be included in
|
|
|
|
* all copies or substantial portions of the Software.
|
2017-07-02 01:51:16 +00:00
|
|
|
*
|
2017-04-18 02:40:39 +00:00
|
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
|
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
|
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
|
|
|
* IN THE SOFTWARE.
|
|
|
|
*/
|
|
|
|
|
2018-09-06 02:18:42 +00:00
|
|
|
#include <janet/janet.h>
|
2018-03-31 20:40:36 +00:00
|
|
|
#include "state.h"
|
2018-03-11 19:35:23 +00:00
|
|
|
#include "fiber.h"
|
2017-12-21 04:03:34 +00:00
|
|
|
#include "gc.h"
|
2018-03-11 19:35:23 +00:00
|
|
|
#include "symcache.h"
|
2018-07-04 03:07:35 +00:00
|
|
|
#include "util.h"
|
2017-02-09 20:02:59 +00:00
|
|
|
|
2018-03-11 19:35:23 +00:00
|
|
|
/* VM state */
|
2018-09-06 02:18:42 +00:00
|
|
|
JANET_THREAD_LOCAL JanetTable *janet_vm_registry;
|
|
|
|
JANET_THREAD_LOCAL int janet_vm_stackn = 0;
|
|
|
|
JANET_THREAD_LOCAL JanetFiber *janet_vm_fiber = NULL;
|
2017-02-09 20:02:59 +00:00
|
|
|
|
2018-03-31 20:40:36 +00:00
|
|
|
/* Maybe collect garbage */
|
2018-09-06 02:18:42 +00:00
|
|
|
#define janet_maybe_collect() do {\
|
|
|
|
if (janet_vm_next_collection >= janet_vm_gc_interval) janet_collect(); } while (0)
|
2018-03-31 20:40:36 +00:00
|
|
|
|
2017-04-19 13:02:12 +00:00
|
|
|
/* Start running the VM from where it left off. */
|
2018-09-06 02:18:42 +00:00
|
|
|
JanetSignal janet_continue(JanetFiber *fiber, Janet in, Janet *out) {
|
2017-11-06 03:05:47 +00:00
|
|
|
|
2018-05-11 00:25:49 +00:00
|
|
|
/* Save old fiber to reset */
|
2018-09-06 02:18:42 +00:00
|
|
|
JanetFiber *old_vm_fiber = janet_vm_fiber;
|
2018-05-11 00:25:49 +00:00
|
|
|
|
2018-05-16 13:24:34 +00:00
|
|
|
/* interpreter state */
|
2018-09-06 02:18:42 +00:00
|
|
|
register Janet *stack;
|
2018-01-16 01:14:21 +00:00
|
|
|
register uint32_t *pc;
|
2018-09-06 02:18:42 +00:00
|
|
|
register JanetFunction *func;
|
2018-01-16 01:14:21 +00:00
|
|
|
|
|
|
|
/* Keep in mind the garbage collector cannot see this value.
|
|
|
|
* Values stored here should be used immediately */
|
2018-09-06 02:18:42 +00:00
|
|
|
Janet retreg;
|
2017-11-06 03:05:47 +00:00
|
|
|
|
2018-07-04 03:07:35 +00:00
|
|
|
/* Expected types on type error */
|
|
|
|
uint16_t expected_types;
|
|
|
|
|
2018-05-17 02:09:36 +00:00
|
|
|
/* Signal to return when done */
|
2018-09-06 02:18:42 +00:00
|
|
|
JanetSignal signal = JANET_SIGNAL_OK;
|
2018-05-17 02:09:36 +00:00
|
|
|
|
|
|
|
/* Ensure fiber is not alive, dead, or error */
|
2018-09-06 02:18:42 +00:00
|
|
|
JanetFiberStatus startstatus = janet_fiber_status(fiber);
|
|
|
|
if (startstatus == JANET_STATUS_ALIVE ||
|
|
|
|
startstatus == JANET_STATUS_DEAD ||
|
|
|
|
startstatus == JANET_STATUS_ERROR) {
|
|
|
|
*out = janet_cstringv("cannot resume alive, dead, or errored fiber");
|
|
|
|
return JANET_SIGNAL_ERROR;
|
2018-05-17 02:09:36 +00:00
|
|
|
}
|
|
|
|
|
2018-03-04 23:56:13 +00:00
|
|
|
/* Increment the stackn */
|
2018-09-06 02:18:42 +00:00
|
|
|
if (janet_vm_stackn >= JANET_RECURSION_GUARD) {
|
|
|
|
janet_fiber_set_status(fiber, JANET_STATUS_ERROR);
|
|
|
|
*out = janet_cstringv("C stack recursed too deeply");
|
|
|
|
return JANET_SIGNAL_ERROR;
|
2018-03-04 23:56:13 +00:00
|
|
|
}
|
2018-09-06 02:18:42 +00:00
|
|
|
janet_vm_stackn++;
|
2018-03-04 23:56:13 +00:00
|
|
|
|
2018-05-11 00:25:49 +00:00
|
|
|
/* Setup fiber state */
|
2018-09-06 02:18:42 +00:00
|
|
|
janet_vm_fiber = fiber;
|
|
|
|
janet_gcroot(janet_wrap_fiber(fiber));
|
|
|
|
janet_gcroot(in);
|
|
|
|
if (startstatus == JANET_STATUS_NEW) {
|
|
|
|
janet_fiber_push(fiber, in);
|
|
|
|
if (janet_fiber_funcframe(fiber, fiber->root)) {
|
|
|
|
janet_gcunroot(janet_wrap_fiber(fiber));
|
|
|
|
janet_gcunroot(in);
|
|
|
|
*out = janet_wrap_string(janet_formatc(
|
2018-09-03 16:51:57 +00:00
|
|
|
"Could not start fiber with function of arity %d",
|
|
|
|
fiber->root->def->arity));
|
2018-09-06 02:18:42 +00:00
|
|
|
return JANET_SIGNAL_ERROR;
|
2018-09-03 16:51:57 +00:00
|
|
|
}
|
2018-03-11 19:35:23 +00:00
|
|
|
}
|
2018-09-06 02:18:42 +00:00
|
|
|
janet_fiber_set_status(fiber, JANET_STATUS_ALIVE);
|
2018-03-11 19:35:23 +00:00
|
|
|
stack = fiber->data + fiber->frame;
|
2018-09-06 02:18:42 +00:00
|
|
|
pc = janet_stack_frame(stack)->pc;
|
|
|
|
func = janet_stack_frame(stack)->func;
|
2018-03-11 19:35:23 +00:00
|
|
|
|
2018-05-17 02:09:36 +00:00
|
|
|
/* Used to extract bits from the opcode that correspond to arguments.
|
|
|
|
* Pulls out unsigned integers */
|
|
|
|
#define oparg(shift, mask) (((*pc) >> ((shift) << 3)) & (mask))
|
|
|
|
|
|
|
|
/* Check for child fiber. If there is a child, run child before self.
|
|
|
|
* This should only be hit when the current fiber is pending on a RESUME
|
|
|
|
* instruction. */
|
|
|
|
if (fiber->child) {
|
|
|
|
retreg = in;
|
|
|
|
goto vm_resume_child;
|
2018-09-06 02:18:42 +00:00
|
|
|
} else if (fiber->flags & JANET_FIBER_FLAG_SIGNAL_WAITING) {
|
2018-05-17 02:09:36 +00:00
|
|
|
/* If waiting for response to signal, use input and increment pc */
|
|
|
|
stack[oparg(1, 0xFF)] = in;
|
|
|
|
pc++;
|
2018-09-06 02:18:42 +00:00
|
|
|
fiber->flags &= ~JANET_FIBER_FLAG_SIGNAL_WAITING;
|
2018-05-17 02:09:36 +00:00
|
|
|
}
|
|
|
|
|
2018-02-01 02:47:18 +00:00
|
|
|
/* Use computed gotos for GCC and clang, otherwise use switch */
|
|
|
|
#ifdef __GNUC__
|
2018-02-01 02:40:19 +00:00
|
|
|
#define VM_START() {vm_next();
|
|
|
|
#define VM_END() }
|
|
|
|
#define VM_OP(op) label_##op :
|
|
|
|
#define VM_DEFAULT() label_unknown_op:
|
|
|
|
#define vm_next() goto *op_lookup[*pc & 0xFF];
|
|
|
|
static void *op_lookup[255] = {
|
2018-09-06 02:18:42 +00:00
|
|
|
&&label_JOP_NOOP,
|
|
|
|
&&label_JOP_ERROR,
|
|
|
|
&&label_JOP_TYPECHECK,
|
|
|
|
&&label_JOP_RETURN,
|
|
|
|
&&label_JOP_RETURN_NIL,
|
|
|
|
&&label_JOP_ADD_INTEGER,
|
|
|
|
&&label_JOP_ADD_IMMEDIATE,
|
|
|
|
&&label_JOP_ADD_REAL,
|
|
|
|
&&label_JOP_ADD,
|
|
|
|
&&label_JOP_SUBTRACT_INTEGER,
|
|
|
|
&&label_JOP_SUBTRACT_REAL,
|
|
|
|
&&label_JOP_SUBTRACT,
|
|
|
|
&&label_JOP_MULTIPLY_INTEGER,
|
|
|
|
&&label_JOP_MULTIPLY_IMMEDIATE,
|
|
|
|
&&label_JOP_MULTIPLY_REAL,
|
|
|
|
&&label_JOP_MULTIPLY,
|
|
|
|
&&label_JOP_DIVIDE_INTEGER,
|
|
|
|
&&label_JOP_DIVIDE_IMMEDIATE,
|
|
|
|
&&label_JOP_DIVIDE_REAL,
|
|
|
|
&&label_JOP_DIVIDE,
|
|
|
|
&&label_JOP_BAND,
|
|
|
|
&&label_JOP_BOR,
|
|
|
|
&&label_JOP_BXOR,
|
|
|
|
&&label_JOP_BNOT,
|
|
|
|
&&label_JOP_SHIFT_LEFT,
|
|
|
|
&&label_JOP_SHIFT_LEFT_IMMEDIATE,
|
|
|
|
&&label_JOP_SHIFT_RIGHT,
|
|
|
|
&&label_JOP_SHIFT_RIGHT_IMMEDIATE,
|
|
|
|
&&label_JOP_SHIFT_RIGHT_UNSIGNED,
|
|
|
|
&&label_JOP_SHIFT_RIGHT_UNSIGNED_IMMEDIATE,
|
|
|
|
&&label_JOP_MOVE_FAR,
|
|
|
|
&&label_JOP_MOVE_NEAR,
|
|
|
|
&&label_JOP_JUMP,
|
|
|
|
&&label_JOP_JUMP_IF,
|
|
|
|
&&label_JOP_JUMP_IF_NOT,
|
|
|
|
&&label_JOP_GREATER_THAN,
|
|
|
|
&&label_JOP_GREATER_THAN_INTEGER,
|
|
|
|
&&label_JOP_GREATER_THAN_IMMEDIATE,
|
|
|
|
&&label_JOP_GREATER_THAN_REAL,
|
|
|
|
&&label_JOP_GREATER_THAN_EQUAL_REAL,
|
|
|
|
&&label_JOP_LESS_THAN,
|
|
|
|
&&label_JOP_LESS_THAN_INTEGER,
|
|
|
|
&&label_JOP_LESS_THAN_IMMEDIATE,
|
|
|
|
&&label_JOP_LESS_THAN_REAL,
|
|
|
|
&&label_JOP_LESS_THAN_EQUAL_REAL,
|
|
|
|
&&label_JOP_EQUALS,
|
|
|
|
&&label_JOP_EQUALS_INTEGER,
|
|
|
|
&&label_JOP_EQUALS_IMMEDIATE,
|
|
|
|
&&label_JOP_EQUALS_REAL,
|
|
|
|
&&label_JOP_COMPARE,
|
|
|
|
&&label_JOP_LOAD_NIL,
|
|
|
|
&&label_JOP_LOAD_TRUE,
|
|
|
|
&&label_JOP_LOAD_FALSE,
|
|
|
|
&&label_JOP_LOAD_INTEGER,
|
|
|
|
&&label_JOP_LOAD_CONSTANT,
|
|
|
|
&&label_JOP_LOAD_UPVALUE,
|
|
|
|
&&label_JOP_LOAD_SELF,
|
|
|
|
&&label_JOP_SET_UPVALUE,
|
|
|
|
&&label_JOP_CLOSURE,
|
|
|
|
&&label_JOP_PUSH,
|
|
|
|
&&label_JOP_PUSH_2,
|
|
|
|
&&label_JOP_PUSH_3,
|
|
|
|
&&label_JOP_PUSH_ARRAY,
|
|
|
|
&&label_JOP_CALL,
|
|
|
|
&&label_JOP_TAILCALL,
|
|
|
|
&&label_JOP_RESUME,
|
|
|
|
&&label_JOP_SIGNAL,
|
|
|
|
&&label_JOP_GET,
|
|
|
|
&&label_JOP_PUT,
|
|
|
|
&&label_JOP_GET_INDEX,
|
|
|
|
&&label_JOP_PUT_INDEX,
|
|
|
|
&&label_JOP_LENGTH,
|
|
|
|
&&label_JOP_MAKE_ARRAY,
|
|
|
|
&&label_JOP_MAKE_BUFFER,
|
|
|
|
&&label_JOP_MAKE_STRING,
|
|
|
|
&&label_JOP_MAKE_STRUCT,
|
|
|
|
&&label_JOP_MAKE_TABLE,
|
|
|
|
&&label_JOP_MAKE_TUPLE,
|
|
|
|
&&label_JOP_NUMERIC_LESS_THAN,
|
|
|
|
&&label_JOP_NUMERIC_LESS_THAN_EQUAL,
|
|
|
|
&&label_JOP_NUMERIC_GREATER_THAN,
|
|
|
|
&&label_JOP_NUMERIC_GREATER_THAN_EQUAL,
|
|
|
|
&&label_JOP_NUMERIC_EQUAL,
|
2018-02-01 02:40:19 +00:00
|
|
|
&&label_unknown_op
|
|
|
|
};
|
|
|
|
#else
|
|
|
|
#define VM_START() for(;;){switch(*pc & 0xFF){
|
|
|
|
#define VM_END() }}
|
|
|
|
#define VM_OP(op) case op :
|
|
|
|
#define VM_DEFAULT() default:
|
2017-12-08 20:57:02 +00:00
|
|
|
#define vm_next() continue
|
2018-02-01 02:40:19 +00:00
|
|
|
#endif
|
|
|
|
|
2018-09-06 02:18:42 +00:00
|
|
|
#define vm_checkgc_next() janet_maybe_collect(); vm_next()
|
2017-12-08 20:57:02 +00:00
|
|
|
|
2018-09-06 02:18:42 +00:00
|
|
|
#define vm_throw(e) do { retreg = janet_cstringv(e); goto vm_error; } while (0)
|
2017-11-06 03:05:47 +00:00
|
|
|
#define vm_assert(cond, e) do {if (!(cond)) vm_throw((e)); } while (0)
|
2018-07-04 03:07:35 +00:00
|
|
|
#define vm_assert_type(X, T) do { \
|
2018-09-06 02:18:42 +00:00
|
|
|
if (!(janet_checktype((X), (T)))) { \
|
2018-07-04 03:07:35 +00:00
|
|
|
expected_types = 1 << (T); \
|
|
|
|
retreg = (X); \
|
|
|
|
goto vm_type_error; \
|
|
|
|
} \
|
|
|
|
} while (0)
|
|
|
|
#define vm_assert_types(X, TS) do { \
|
2018-09-06 02:18:42 +00:00
|
|
|
if (!((1 << janet_type(X)) & (TS))) { \
|
2018-07-04 03:07:35 +00:00
|
|
|
expected_types = (TS); \
|
|
|
|
retreg = (X); \
|
|
|
|
goto vm_type_error; \
|
|
|
|
} \
|
|
|
|
} while (0)
|
2017-11-06 03:05:47 +00:00
|
|
|
|
|
|
|
#define vm_binop_integer(op) \
|
2018-09-06 02:18:42 +00:00
|
|
|
stack[oparg(1, 0xFF)] = janet_wrap_integer(\
|
|
|
|
janet_unwrap_integer(stack[oparg(2, 0xFF)]) op janet_unwrap_integer(stack[oparg(3, 0xFF)])\
|
2017-11-06 03:05:47 +00:00
|
|
|
);\
|
|
|
|
pc++;\
|
2017-11-27 00:31:40 +00:00
|
|
|
vm_next();
|
2017-11-06 03:05:47 +00:00
|
|
|
|
|
|
|
#define vm_binop_real(op)\
|
2018-09-06 02:18:42 +00:00
|
|
|
stack[oparg(1, 0xFF)] = janet_wrap_real(\
|
|
|
|
janet_unwrap_real(stack[oparg(2, 0xFF)]) op janet_unwrap_real(stack[oparg(3, 0xFF)])\
|
2017-11-06 03:05:47 +00:00
|
|
|
);\
|
|
|
|
pc++;\
|
2017-11-27 00:31:40 +00:00
|
|
|
vm_next();
|
2017-11-06 03:05:47 +00:00
|
|
|
|
|
|
|
#define vm_binop_immediate(op)\
|
2018-09-06 02:18:42 +00:00
|
|
|
stack[oparg(1, 0xFF)] = janet_wrap_integer(\
|
|
|
|
janet_unwrap_integer(stack[oparg(2, 0xFF)]) op (*((int32_t *)pc) >> 24)\
|
2017-11-06 03:05:47 +00:00
|
|
|
);\
|
|
|
|
pc++;\
|
2017-11-27 00:31:40 +00:00
|
|
|
vm_next();
|
2017-11-06 03:05:47 +00:00
|
|
|
|
|
|
|
#define vm_binop(op)\
|
|
|
|
{\
|
2018-09-06 02:18:42 +00:00
|
|
|
Janet op1 = stack[oparg(2, 0xFF)];\
|
|
|
|
Janet op2 = stack[oparg(3, 0xFF)];\
|
|
|
|
vm_assert_types(op1, JANET_TFLAG_NUMBER);\
|
|
|
|
vm_assert_types(op2, JANET_TFLAG_NUMBER);\
|
|
|
|
stack[oparg(1, 0xFF)] = janet_checktype(op1, JANET_INTEGER)\
|
|
|
|
? (janet_checktype(op2, JANET_INTEGER)\
|
|
|
|
? janet_wrap_integer(janet_unwrap_integer(op1) op janet_unwrap_integer(op2))\
|
|
|
|
: janet_wrap_real((double)janet_unwrap_integer(op1) op janet_unwrap_real(op2)))\
|
|
|
|
: (janet_checktype(op2, JANET_INTEGER)\
|
|
|
|
? janet_wrap_real(janet_unwrap_real(op1) op (double)janet_unwrap_integer(op2))\
|
|
|
|
: janet_wrap_real(janet_unwrap_real(op1) op janet_unwrap_real(op2)));\
|
2017-11-06 03:05:47 +00:00
|
|
|
pc++;\
|
2017-11-27 00:31:40 +00:00
|
|
|
vm_next();\
|
2017-11-06 03:05:47 +00:00
|
|
|
}
|
2017-05-09 23:21:30 +00:00
|
|
|
|
2018-07-10 01:24:22 +00:00
|
|
|
#define vm_numcomp(op)\
|
|
|
|
{\
|
2018-09-06 02:18:42 +00:00
|
|
|
Janet op1 = stack[oparg(2, 0xFF)];\
|
|
|
|
Janet op2 = stack[oparg(3, 0xFF)];\
|
|
|
|
vm_assert_types(op1, JANET_TFLAG_NUMBER);\
|
|
|
|
vm_assert_types(op2, JANET_TFLAG_NUMBER);\
|
|
|
|
stack[oparg(1, 0xFF)] = janet_wrap_boolean(janet_checktype(op1, JANET_INTEGER)\
|
|
|
|
? (janet_checktype(op2, JANET_INTEGER)\
|
|
|
|
? janet_unwrap_integer(op1) op janet_unwrap_integer(op2)\
|
|
|
|
: (double)janet_unwrap_integer(op1) op janet_unwrap_real(op2))\
|
|
|
|
: (janet_checktype(op2, JANET_INTEGER)\
|
|
|
|
? janet_unwrap_real(op1) op (double)janet_unwrap_integer(op2)\
|
|
|
|
: janet_unwrap_real(op1) op janet_unwrap_real(op2)));\
|
2018-07-10 01:24:22 +00:00
|
|
|
pc++;\
|
|
|
|
vm_next();\
|
|
|
|
}
|
|
|
|
|
2018-05-11 00:25:49 +00:00
|
|
|
/* Main interpreter loop. Semantically is a switch on
|
2018-03-09 22:14:26 +00:00
|
|
|
* (*pc & 0xFF) inside of an infinte loop. */
|
2018-02-01 02:40:19 +00:00
|
|
|
VM_START();
|
2017-02-09 20:02:59 +00:00
|
|
|
|
2018-02-01 02:40:19 +00:00
|
|
|
VM_DEFAULT();
|
2018-09-06 02:18:42 +00:00
|
|
|
retreg = janet_wrap_nil();
|
2018-05-17 02:09:36 +00:00
|
|
|
goto vm_exit;
|
2017-11-06 03:05:47 +00:00
|
|
|
|
2018-09-06 02:18:42 +00:00
|
|
|
VM_OP(JOP_NOOP)
|
2018-02-01 02:40:19 +00:00
|
|
|
pc++;
|
|
|
|
vm_next();
|
2017-11-06 03:05:47 +00:00
|
|
|
|
2018-09-06 02:18:42 +00:00
|
|
|
VM_OP(JOP_ERROR)
|
2018-02-01 02:40:19 +00:00
|
|
|
retreg = stack[oparg(1, 0xFF)];
|
|
|
|
goto vm_error;
|
2017-11-06 03:05:47 +00:00
|
|
|
|
2018-09-06 02:18:42 +00:00
|
|
|
VM_OP(JOP_TYPECHECK)
|
|
|
|
if (!((1 << janet_type(stack[oparg(1, 0xFF)])) & oparg(2, 0xFFFF))) {
|
|
|
|
JanetArgs tempargs;
|
2018-05-13 00:31:28 +00:00
|
|
|
tempargs.n = oparg(1, 0xFF) + 1;
|
|
|
|
tempargs.v = stack;
|
2018-09-06 02:18:42 +00:00
|
|
|
janet_typemany_err(tempargs, oparg(1, 0xFF), oparg(2, 0xFFFF));
|
2018-05-13 00:31:28 +00:00
|
|
|
goto vm_error;
|
|
|
|
}
|
2018-02-01 02:40:19 +00:00
|
|
|
pc++;
|
|
|
|
vm_next();
|
2017-11-06 03:05:47 +00:00
|
|
|
|
2018-09-06 02:18:42 +00:00
|
|
|
VM_OP(JOP_RETURN)
|
2018-02-01 02:40:19 +00:00
|
|
|
retreg = stack[oparg(1, 0xFFFFFF)];
|
|
|
|
goto vm_return;
|
2017-11-06 03:05:47 +00:00
|
|
|
|
2018-09-06 02:18:42 +00:00
|
|
|
VM_OP(JOP_RETURN_NIL)
|
|
|
|
retreg = janet_wrap_nil();
|
2018-02-01 02:40:19 +00:00
|
|
|
goto vm_return;
|
2017-11-06 03:05:47 +00:00
|
|
|
|
2018-09-06 02:18:42 +00:00
|
|
|
VM_OP(JOP_ADD_INTEGER)
|
2018-02-01 02:40:19 +00:00
|
|
|
vm_binop_integer(+);
|
2017-11-06 03:05:47 +00:00
|
|
|
|
2018-09-06 02:18:42 +00:00
|
|
|
VM_OP(JOP_ADD_IMMEDIATE)
|
2018-02-01 02:40:19 +00:00
|
|
|
vm_binop_immediate(+);
|
2017-11-06 03:05:47 +00:00
|
|
|
|
2018-09-06 02:18:42 +00:00
|
|
|
VM_OP(JOP_ADD_REAL)
|
2018-02-01 02:40:19 +00:00
|
|
|
vm_binop_real(+);
|
2017-11-06 03:05:47 +00:00
|
|
|
|
2018-09-06 02:18:42 +00:00
|
|
|
VM_OP(JOP_ADD)
|
2018-02-01 02:40:19 +00:00
|
|
|
vm_binop(+);
|
2017-11-06 03:05:47 +00:00
|
|
|
|
2018-09-06 02:18:42 +00:00
|
|
|
VM_OP(JOP_SUBTRACT_INTEGER)
|
2018-02-01 02:40:19 +00:00
|
|
|
vm_binop_integer(-);
|
2017-11-06 03:05:47 +00:00
|
|
|
|
2018-09-06 02:18:42 +00:00
|
|
|
VM_OP(JOP_SUBTRACT_REAL)
|
2018-02-01 02:40:19 +00:00
|
|
|
vm_binop_real(-);
|
2017-11-06 03:05:47 +00:00
|
|
|
|
2018-09-06 02:18:42 +00:00
|
|
|
VM_OP(JOP_SUBTRACT)
|
2018-02-01 02:40:19 +00:00
|
|
|
vm_binop(-);
|
2018-05-20 01:16:00 +00:00
|
|
|
|
2018-09-06 02:18:42 +00:00
|
|
|
VM_OP(JOP_MULTIPLY_INTEGER)
|
2018-02-01 02:40:19 +00:00
|
|
|
vm_binop_integer(*);
|
2017-11-06 03:05:47 +00:00
|
|
|
|
2018-09-06 02:18:42 +00:00
|
|
|
VM_OP(JOP_MULTIPLY_IMMEDIATE)
|
2018-02-01 02:40:19 +00:00
|
|
|
vm_binop_immediate(*);
|
2017-11-06 03:05:47 +00:00
|
|
|
|
2018-09-06 02:18:42 +00:00
|
|
|
VM_OP(JOP_MULTIPLY_REAL)
|
2018-02-01 02:40:19 +00:00
|
|
|
vm_binop_real(*);
|
2017-11-06 03:05:47 +00:00
|
|
|
|
2018-09-06 02:18:42 +00:00
|
|
|
VM_OP(JOP_MULTIPLY)
|
2018-02-01 02:40:19 +00:00
|
|
|
vm_binop(*);
|
2017-11-06 03:05:47 +00:00
|
|
|
|
2018-09-06 02:18:42 +00:00
|
|
|
VM_OP(JOP_NUMERIC_LESS_THAN)
|
2018-07-10 01:24:22 +00:00
|
|
|
vm_numcomp(<);
|
|
|
|
|
2018-09-06 02:18:42 +00:00
|
|
|
VM_OP(JOP_NUMERIC_LESS_THAN_EQUAL)
|
2018-07-10 01:24:22 +00:00
|
|
|
vm_numcomp(<=);
|
|
|
|
|
2018-09-06 02:18:42 +00:00
|
|
|
VM_OP(JOP_NUMERIC_GREATER_THAN)
|
2018-07-10 01:24:22 +00:00
|
|
|
vm_numcomp(>);
|
|
|
|
|
2018-09-06 02:18:42 +00:00
|
|
|
VM_OP(JOP_NUMERIC_GREATER_THAN_EQUAL)
|
2018-07-10 01:24:22 +00:00
|
|
|
vm_numcomp(>=);
|
|
|
|
|
2018-09-06 02:18:42 +00:00
|
|
|
VM_OP(JOP_NUMERIC_EQUAL)
|
2018-07-10 01:24:22 +00:00
|
|
|
vm_numcomp(==);
|
|
|
|
|
2018-09-06 02:18:42 +00:00
|
|
|
VM_OP(JOP_DIVIDE_INTEGER)
|
|
|
|
vm_assert(janet_unwrap_integer(stack[oparg(3, 0xFF)]) != 0, "integer divide error");
|
|
|
|
vm_assert(!(janet_unwrap_integer(stack[oparg(3, 0xFF)]) == -1 &&
|
|
|
|
janet_unwrap_integer(stack[oparg(2, 0xFF)]) == INT32_MIN),
|
2018-02-01 02:40:19 +00:00
|
|
|
"integer divide error");
|
|
|
|
vm_binop_integer(/);
|
2018-05-20 01:16:00 +00:00
|
|
|
|
2018-09-06 02:18:42 +00:00
|
|
|
VM_OP(JOP_DIVIDE_IMMEDIATE)
|
2018-02-01 02:40:19 +00:00
|
|
|
{
|
2018-09-06 02:18:42 +00:00
|
|
|
int32_t op1 = janet_unwrap_integer(stack[oparg(2, 0xFF)]);
|
2018-02-01 02:40:19 +00:00
|
|
|
int32_t op2 = *((int32_t *)pc) >> 24;
|
|
|
|
/* Check for degenerate integer division (divide by zero, and dividing
|
2018-05-20 01:16:00 +00:00
|
|
|
* min value by -1). These checks could be omitted if the arg is not
|
2018-02-01 02:40:19 +00:00
|
|
|
* 0 or -1. */
|
|
|
|
if (op2 == 0)
|
|
|
|
vm_throw("integer divide error");
|
|
|
|
if (op2 == -1 && op1 == INT32_MIN)
|
|
|
|
vm_throw("integer divide error");
|
|
|
|
else
|
2018-09-06 02:18:42 +00:00
|
|
|
stack[oparg(1, 0xFF)] = janet_wrap_integer(op1 / op2);
|
2017-11-27 00:31:40 +00:00
|
|
|
pc++;
|
|
|
|
vm_next();
|
2018-02-01 02:40:19 +00:00
|
|
|
}
|
2017-11-06 03:05:47 +00:00
|
|
|
|
2018-09-06 02:18:42 +00:00
|
|
|
VM_OP(JOP_DIVIDE_REAL)
|
2018-02-01 02:40:19 +00:00
|
|
|
vm_binop_real(/);
|
|
|
|
|
2018-09-06 02:18:42 +00:00
|
|
|
VM_OP(JOP_DIVIDE)
|
2018-02-01 02:40:19 +00:00
|
|
|
{
|
2018-09-06 02:18:42 +00:00
|
|
|
Janet op1 = stack[oparg(2, 0xFF)];
|
|
|
|
Janet op2 = stack[oparg(3, 0xFF)];
|
|
|
|
vm_assert_types(op1, JANET_TFLAG_NUMBER);
|
|
|
|
vm_assert_types(op2, JANET_TFLAG_NUMBER);
|
|
|
|
if (janet_checktype(op2, JANET_INTEGER) && janet_unwrap_integer(op2) == 0)
|
2018-07-02 04:12:36 +00:00
|
|
|
vm_throw("integer divide by zero");
|
2018-09-06 02:18:42 +00:00
|
|
|
if (janet_checktype(op2, JANET_INTEGER) && janet_unwrap_integer(op2) == -1 &&
|
|
|
|
janet_checktype(op1, JANET_INTEGER) && janet_unwrap_integer(op1) == INT32_MIN)
|
2018-07-02 04:12:36 +00:00
|
|
|
vm_throw("integer divide out of range");
|
2018-09-06 02:18:42 +00:00
|
|
|
stack[oparg(1, 0xFF)] = janet_checktype(op1, JANET_INTEGER)
|
|
|
|
? (janet_checktype(op2, JANET_INTEGER)
|
|
|
|
? janet_wrap_integer(janet_unwrap_integer(op1) / janet_unwrap_integer(op2))
|
|
|
|
: janet_wrap_real((double)janet_unwrap_integer(op1) / janet_unwrap_real(op2)))
|
|
|
|
: (janet_checktype(op2, JANET_INTEGER)
|
|
|
|
? janet_wrap_real(janet_unwrap_real(op1) / (double)janet_unwrap_integer(op2))
|
|
|
|
: janet_wrap_real(janet_unwrap_real(op1) / janet_unwrap_real(op2)));
|
2017-11-27 00:31:40 +00:00
|
|
|
pc++;
|
|
|
|
vm_next();
|
2018-02-01 02:40:19 +00:00
|
|
|
}
|
2017-11-06 03:05:47 +00:00
|
|
|
|
2018-09-06 02:18:42 +00:00
|
|
|
VM_OP(JOP_BAND)
|
2018-02-01 02:40:19 +00:00
|
|
|
vm_binop_integer(&);
|
2017-11-06 03:05:47 +00:00
|
|
|
|
2018-09-06 02:18:42 +00:00
|
|
|
VM_OP(JOP_BOR)
|
2018-02-01 02:40:19 +00:00
|
|
|
vm_binop_integer(|);
|
2017-11-06 03:05:47 +00:00
|
|
|
|
2018-09-06 02:18:42 +00:00
|
|
|
VM_OP(JOP_BXOR)
|
2018-02-01 02:40:19 +00:00
|
|
|
vm_binop_integer(^);
|
2017-02-13 05:11:30 +00:00
|
|
|
|
2018-09-06 02:18:42 +00:00
|
|
|
VM_OP(JOP_BNOT)
|
|
|
|
stack[oparg(1, 0xFF)] = janet_wrap_integer(~janet_unwrap_integer(stack[oparg(2, 0xFFFF)]));
|
2018-07-09 03:10:02 +00:00
|
|
|
++pc;
|
2018-02-01 02:40:19 +00:00
|
|
|
vm_next();
|
2018-05-20 01:16:00 +00:00
|
|
|
|
2018-09-06 02:18:42 +00:00
|
|
|
VM_OP(JOP_SHIFT_RIGHT_UNSIGNED)
|
|
|
|
stack[oparg(1, 0xFF)] = janet_wrap_integer(
|
|
|
|
(int32_t)(((uint32_t)janet_unwrap_integer(stack[oparg(2, 0xFF)]))
|
2018-02-01 02:40:19 +00:00
|
|
|
>>
|
2018-09-06 02:18:42 +00:00
|
|
|
janet_unwrap_integer(stack[oparg(3, 0xFF)]))
|
2018-02-01 02:40:19 +00:00
|
|
|
);
|
|
|
|
pc++;
|
|
|
|
vm_next();
|
2017-11-25 04:17:04 +00:00
|
|
|
|
2018-09-06 02:18:42 +00:00
|
|
|
VM_OP(JOP_SHIFT_RIGHT_UNSIGNED_IMMEDIATE)
|
|
|
|
stack[oparg(1, 0xFF)] = janet_wrap_integer(
|
|
|
|
(int32_t) (((uint32_t)janet_unwrap_integer(stack[oparg(2, 0xFF)])) >> oparg(3, 0xFF))
|
2018-02-01 02:40:19 +00:00
|
|
|
);
|
|
|
|
pc++;
|
|
|
|
vm_next();
|
2017-11-06 03:05:47 +00:00
|
|
|
|
2018-09-06 02:18:42 +00:00
|
|
|
VM_OP(JOP_SHIFT_RIGHT)
|
2018-02-01 02:40:19 +00:00
|
|
|
vm_binop_integer(>>);
|
2017-12-16 06:17:53 +00:00
|
|
|
|
2018-09-06 02:18:42 +00:00
|
|
|
VM_OP(JOP_SHIFT_RIGHT_IMMEDIATE)
|
|
|
|
stack[oparg(1, 0xFF)] = janet_wrap_integer(
|
|
|
|
(int32_t)(janet_unwrap_integer(stack[oparg(2, 0xFF)]) >> oparg(3, 0xFF))
|
2018-02-01 02:40:19 +00:00
|
|
|
);
|
|
|
|
pc++;
|
|
|
|
vm_next();
|
2017-11-06 03:05:47 +00:00
|
|
|
|
2018-09-06 02:18:42 +00:00
|
|
|
VM_OP(JOP_SHIFT_LEFT)
|
2018-02-01 02:40:19 +00:00
|
|
|
vm_binop_integer(<<);
|
2017-02-09 20:02:59 +00:00
|
|
|
|
2018-09-06 02:18:42 +00:00
|
|
|
VM_OP(JOP_SHIFT_LEFT_IMMEDIATE)
|
|
|
|
stack[oparg(1, 0xFF)] = janet_wrap_integer(
|
|
|
|
janet_unwrap_integer(stack[oparg(2, 0xFF)]) << oparg(3, 0xFF)
|
2018-02-01 02:40:19 +00:00
|
|
|
);
|
|
|
|
pc++;
|
|
|
|
vm_next();
|
2017-11-25 04:17:04 +00:00
|
|
|
|
2018-09-06 02:18:42 +00:00
|
|
|
VM_OP(JOP_MOVE_NEAR)
|
2018-02-01 02:40:19 +00:00
|
|
|
stack[oparg(1, 0xFF)] = stack[oparg(2, 0xFFFF)];
|
|
|
|
pc++;
|
|
|
|
vm_next();
|
|
|
|
|
2018-09-06 02:18:42 +00:00
|
|
|
VM_OP(JOP_MOVE_FAR)
|
2018-02-01 02:40:19 +00:00
|
|
|
stack[oparg(2, 0xFFFF)] = stack[oparg(1, 0xFF)];
|
|
|
|
pc++;
|
|
|
|
vm_next();
|
|
|
|
|
2018-09-06 02:18:42 +00:00
|
|
|
VM_OP(JOP_JUMP)
|
2018-02-01 02:40:19 +00:00
|
|
|
pc += (*(int32_t *)pc) >> 8;
|
|
|
|
vm_next();
|
2017-11-25 04:17:04 +00:00
|
|
|
|
2018-09-06 02:18:42 +00:00
|
|
|
VM_OP(JOP_JUMP_IF)
|
|
|
|
if (janet_truthy(stack[oparg(1, 0xFF)])) {
|
2018-02-01 02:40:19 +00:00
|
|
|
pc += (*(int32_t *)pc) >> 16;
|
|
|
|
} else {
|
2017-11-27 00:31:40 +00:00
|
|
|
pc++;
|
2018-02-01 02:40:19 +00:00
|
|
|
}
|
|
|
|
vm_next();
|
2017-11-06 03:05:47 +00:00
|
|
|
|
2018-09-06 02:18:42 +00:00
|
|
|
VM_OP(JOP_JUMP_IF_NOT)
|
|
|
|
if (janet_truthy(stack[oparg(1, 0xFF)])) {
|
2017-11-27 00:31:40 +00:00
|
|
|
pc++;
|
2018-02-01 02:40:19 +00:00
|
|
|
} else {
|
|
|
|
pc += (*(int32_t *)pc) >> 16;
|
|
|
|
}
|
|
|
|
vm_next();
|
|
|
|
|
2018-09-06 02:18:42 +00:00
|
|
|
VM_OP(JOP_LESS_THAN)
|
|
|
|
stack[oparg(1, 0xFF)] = janet_wrap_boolean(janet_compare(
|
2018-02-01 02:40:19 +00:00
|
|
|
stack[oparg(2, 0xFF)],
|
|
|
|
stack[oparg(3, 0xFF)]
|
|
|
|
) < 0);
|
|
|
|
pc++;
|
|
|
|
vm_next();
|
|
|
|
|
2018-05-07 16:34:04 +00:00
|
|
|
/* Candidate */
|
2018-09-06 02:18:42 +00:00
|
|
|
VM_OP(JOP_LESS_THAN_INTEGER)
|
|
|
|
stack[oparg(1, 0xFF)] = janet_wrap_boolean(
|
|
|
|
janet_unwrap_integer(stack[oparg(2, 0xFF)]) <
|
|
|
|
janet_unwrap_integer(stack[oparg(3, 0xFF)]));
|
2018-05-07 16:34:04 +00:00
|
|
|
pc++;
|
|
|
|
vm_next();
|
|
|
|
|
|
|
|
/* Candidate */
|
2018-09-06 02:18:42 +00:00
|
|
|
VM_OP(JOP_LESS_THAN_IMMEDIATE)
|
|
|
|
stack[oparg(1, 0xFF)] = janet_wrap_boolean(
|
|
|
|
janet_unwrap_integer(stack[oparg(2, 0xFF)]) < ((*(int32_t *)pc) >> 24)
|
2018-05-07 16:34:04 +00:00
|
|
|
);
|
|
|
|
pc++;
|
|
|
|
vm_next();
|
|
|
|
|
|
|
|
/* Candidate */
|
2018-09-06 02:18:42 +00:00
|
|
|
VM_OP(JOP_LESS_THAN_REAL)
|
|
|
|
stack[oparg(1, 0xFF)] = janet_wrap_boolean(
|
|
|
|
janet_unwrap_real(stack[oparg(2, 0xFF)]) <
|
|
|
|
janet_unwrap_real(stack[oparg(3, 0xFF)]));
|
2018-05-07 16:34:04 +00:00
|
|
|
pc++;
|
|
|
|
vm_next();
|
|
|
|
|
|
|
|
/* Candidate */
|
2018-09-06 02:18:42 +00:00
|
|
|
VM_OP(JOP_LESS_THAN_EQUAL_REAL)
|
|
|
|
stack[oparg(1, 0xFF)] = janet_wrap_boolean(
|
|
|
|
janet_unwrap_real(stack[oparg(2, 0xFF)]) <=
|
|
|
|
janet_unwrap_real(stack[oparg(3, 0xFF)]));
|
2018-05-07 16:34:04 +00:00
|
|
|
pc++;
|
|
|
|
vm_next();
|
|
|
|
|
|
|
|
|
2018-09-06 02:18:42 +00:00
|
|
|
VM_OP(JOP_GREATER_THAN)
|
|
|
|
stack[oparg(1, 0xFF)] = janet_wrap_boolean(janet_compare(
|
2018-02-01 02:40:19 +00:00
|
|
|
stack[oparg(2, 0xFF)],
|
|
|
|
stack[oparg(3, 0xFF)]
|
|
|
|
) > 0);
|
|
|
|
pc++;
|
|
|
|
vm_next();
|
2017-02-09 20:02:59 +00:00
|
|
|
|
2018-05-07 16:34:04 +00:00
|
|
|
/* Candidate */
|
2018-09-06 02:18:42 +00:00
|
|
|
VM_OP(JOP_GREATER_THAN_INTEGER)
|
|
|
|
stack[oparg(1, 0xFF)] = janet_wrap_boolean(
|
|
|
|
janet_unwrap_integer(stack[oparg(2, 0xFF)]) >
|
|
|
|
janet_unwrap_integer(stack[oparg(3, 0xFF)]));
|
2018-05-07 16:34:04 +00:00
|
|
|
pc++;
|
|
|
|
vm_next();
|
|
|
|
|
|
|
|
/* Candidate */
|
2018-09-06 02:18:42 +00:00
|
|
|
VM_OP(JOP_GREATER_THAN_IMMEDIATE)
|
|
|
|
stack[oparg(1, 0xFF)] = janet_wrap_boolean(
|
|
|
|
janet_unwrap_integer(stack[oparg(2, 0xFF)]) > ((*(int32_t *)pc) >> 24)
|
2018-05-07 16:34:04 +00:00
|
|
|
);
|
|
|
|
pc++;
|
|
|
|
vm_next();
|
|
|
|
|
|
|
|
/* Candidate */
|
2018-09-06 02:18:42 +00:00
|
|
|
VM_OP(JOP_GREATER_THAN_REAL)
|
|
|
|
stack[oparg(1, 0xFF)] = janet_wrap_boolean(
|
|
|
|
janet_unwrap_real(stack[oparg(2, 0xFF)]) >
|
|
|
|
janet_unwrap_real(stack[oparg(3, 0xFF)]));
|
2018-05-07 16:34:04 +00:00
|
|
|
pc++;
|
|
|
|
vm_next();
|
|
|
|
|
|
|
|
/* Candidate */
|
2018-09-06 02:18:42 +00:00
|
|
|
VM_OP(JOP_GREATER_THAN_EQUAL_REAL)
|
|
|
|
stack[oparg(1, 0xFF)] = janet_wrap_boolean(
|
|
|
|
janet_unwrap_real(stack[oparg(2, 0xFF)]) >=
|
|
|
|
janet_unwrap_real(stack[oparg(3, 0xFF)]));
|
2018-05-07 16:34:04 +00:00
|
|
|
pc++;
|
|
|
|
vm_next();
|
|
|
|
|
2018-09-06 02:18:42 +00:00
|
|
|
VM_OP(JOP_EQUALS)
|
|
|
|
stack[oparg(1, 0xFF)] = janet_wrap_boolean(janet_equals(
|
2017-11-28 23:27:55 +00:00
|
|
|
stack[oparg(2, 0xFF)],
|
|
|
|
stack[oparg(3, 0xFF)]
|
|
|
|
));
|
2018-02-01 02:40:19 +00:00
|
|
|
pc++;
|
|
|
|
vm_next();
|
2017-02-09 20:02:59 +00:00
|
|
|
|
2018-05-07 16:34:04 +00:00
|
|
|
/* Candidate */
|
2018-09-06 02:18:42 +00:00
|
|
|
VM_OP(JOP_EQUALS_INTEGER)
|
|
|
|
stack[oparg(1, 0xFF)] = janet_wrap_boolean(
|
|
|
|
janet_unwrap_integer(stack[oparg(2, 0xFF)]) ==
|
|
|
|
janet_unwrap_integer(stack[oparg(3, 0xFF)])
|
2018-05-07 16:34:04 +00:00
|
|
|
);
|
|
|
|
pc++;
|
|
|
|
vm_next();
|
|
|
|
|
|
|
|
/* Candidate */
|
2018-09-06 02:18:42 +00:00
|
|
|
VM_OP(JOP_EQUALS_REAL)
|
|
|
|
stack[oparg(1, 0xFF)] = janet_wrap_boolean(
|
|
|
|
janet_unwrap_real(stack[oparg(2, 0xFF)]) ==
|
|
|
|
janet_unwrap_real(stack[oparg(3, 0xFF)])
|
2018-05-07 16:34:04 +00:00
|
|
|
);
|
|
|
|
pc++;
|
|
|
|
vm_next();
|
|
|
|
|
|
|
|
/* Candidate */
|
2018-09-06 02:18:42 +00:00
|
|
|
VM_OP(JOP_EQUALS_IMMEDIATE)
|
|
|
|
stack[oparg(1, 0xFF)] = janet_wrap_boolean(
|
|
|
|
janet_unwrap_integer(stack[oparg(2, 0xFF)]) == ((*(int32_t *)pc) >> 24)
|
2018-05-07 16:34:04 +00:00
|
|
|
);
|
|
|
|
pc++;
|
|
|
|
vm_next();
|
|
|
|
|
2018-09-06 02:18:42 +00:00
|
|
|
VM_OP(JOP_COMPARE)
|
|
|
|
stack[oparg(1, 0xFF)] = janet_wrap_integer(janet_compare(
|
2018-02-01 02:40:19 +00:00
|
|
|
stack[oparg(2, 0xFF)],
|
|
|
|
stack[oparg(3, 0xFF)]
|
|
|
|
));
|
|
|
|
pc++;
|
|
|
|
vm_next();
|
2017-02-09 20:02:59 +00:00
|
|
|
|
2018-09-06 02:18:42 +00:00
|
|
|
VM_OP(JOP_LOAD_NIL)
|
|
|
|
stack[oparg(1, 0xFFFFFF)] = janet_wrap_nil();
|
2018-02-01 02:40:19 +00:00
|
|
|
pc++;
|
|
|
|
vm_next();
|
2017-12-16 06:17:53 +00:00
|
|
|
|
2018-09-06 02:18:42 +00:00
|
|
|
VM_OP(JOP_LOAD_TRUE)
|
|
|
|
stack[oparg(1, 0xFFFFFF)] = janet_wrap_boolean(1);
|
2018-02-01 02:40:19 +00:00
|
|
|
pc++;
|
|
|
|
vm_next();
|
2017-04-24 20:02:54 +00:00
|
|
|
|
2018-09-06 02:18:42 +00:00
|
|
|
VM_OP(JOP_LOAD_FALSE)
|
|
|
|
stack[oparg(1, 0xFFFFFF)] = janet_wrap_boolean(0);
|
2018-02-01 02:40:19 +00:00
|
|
|
pc++;
|
|
|
|
vm_next();
|
2017-02-13 05:11:30 +00:00
|
|
|
|
2018-09-06 02:18:42 +00:00
|
|
|
VM_OP(JOP_LOAD_INTEGER)
|
|
|
|
stack[oparg(1, 0xFF)] = janet_wrap_integer(*((int32_t *)pc) >> 16);
|
2018-02-01 02:40:19 +00:00
|
|
|
pc++;
|
|
|
|
vm_next();
|
2017-02-13 05:11:30 +00:00
|
|
|
|
2018-09-06 02:18:42 +00:00
|
|
|
VM_OP(JOP_LOAD_CONSTANT)
|
2018-02-01 02:40:19 +00:00
|
|
|
{
|
|
|
|
int32_t index = oparg(2, 0xFFFF);
|
|
|
|
vm_assert(index < func->def->constants_length, "invalid constant");
|
|
|
|
stack[oparg(1, 0xFF)] = func->def->constants[index];
|
2017-12-16 06:17:53 +00:00
|
|
|
pc++;
|
|
|
|
vm_next();
|
2018-02-01 02:40:19 +00:00
|
|
|
}
|
2017-12-16 06:17:53 +00:00
|
|
|
|
2018-09-06 02:18:42 +00:00
|
|
|
VM_OP(JOP_LOAD_SELF)
|
|
|
|
stack[oparg(1, 0xFFFFFF)] = janet_wrap_function(func);
|
2018-02-01 02:40:19 +00:00
|
|
|
pc++;
|
|
|
|
vm_next();
|
2017-04-19 13:02:12 +00:00
|
|
|
|
2018-09-06 02:18:42 +00:00
|
|
|
VM_OP(JOP_LOAD_UPVALUE)
|
2018-02-01 02:40:19 +00:00
|
|
|
{
|
|
|
|
int32_t eindex = oparg(2, 0xFF);
|
|
|
|
int32_t vindex = oparg(3, 0xFF);
|
2018-09-06 02:18:42 +00:00
|
|
|
JanetFuncEnv *env;
|
2018-05-17 02:09:36 +00:00
|
|
|
vm_assert(func->def->environments_length > eindex, "invalid upvalue environment");
|
2018-02-01 02:40:19 +00:00
|
|
|
env = func->envs[eindex];
|
2018-05-17 02:09:36 +00:00
|
|
|
vm_assert(env->length > vindex, "invalid upvalue index");
|
2018-02-01 02:40:19 +00:00
|
|
|
if (env->offset) {
|
|
|
|
/* On stack */
|
|
|
|
stack[oparg(1, 0xFF)] = env->as.fiber->data[env->offset + vindex];
|
|
|
|
} else {
|
|
|
|
/* Off stack */
|
|
|
|
stack[oparg(1, 0xFF)] = env->as.values[vindex];
|
2017-11-27 00:31:40 +00:00
|
|
|
}
|
|
|
|
pc++;
|
2018-02-01 02:40:19 +00:00
|
|
|
vm_next();
|
|
|
|
}
|
2017-04-19 13:02:12 +00:00
|
|
|
|
2018-09-06 02:18:42 +00:00
|
|
|
VM_OP(JOP_SET_UPVALUE)
|
2018-02-01 02:40:19 +00:00
|
|
|
{
|
|
|
|
int32_t eindex = oparg(2, 0xFF);
|
|
|
|
int32_t vindex = oparg(3, 0xFF);
|
2018-09-06 02:18:42 +00:00
|
|
|
JanetFuncEnv *env;
|
2018-05-17 02:09:36 +00:00
|
|
|
vm_assert(func->def->environments_length > eindex, "invalid upvalue environment");
|
2018-02-01 02:40:19 +00:00
|
|
|
env = func->envs[eindex];
|
2018-05-17 02:09:36 +00:00
|
|
|
vm_assert(env->length > vindex, "invalid upvalue index");
|
2018-02-01 02:40:19 +00:00
|
|
|
if (env->offset) {
|
|
|
|
env->as.fiber->data[env->offset + vindex] = stack[oparg(1, 0xFF)];
|
|
|
|
} else {
|
|
|
|
env->as.values[vindex] = stack[oparg(1, 0xFF)];
|
|
|
|
}
|
2017-11-27 00:31:40 +00:00
|
|
|
pc++;
|
2018-02-01 02:40:19 +00:00
|
|
|
vm_next();
|
|
|
|
}
|
2017-11-06 03:05:47 +00:00
|
|
|
|
2018-09-06 02:18:42 +00:00
|
|
|
VM_OP(JOP_CLOSURE)
|
2018-02-01 02:40:19 +00:00
|
|
|
{
|
2018-09-06 02:18:42 +00:00
|
|
|
JanetFuncDef *fd;
|
|
|
|
JanetFunction *fn;
|
2018-02-13 21:14:55 +00:00
|
|
|
int32_t elen;
|
2018-02-01 02:40:19 +00:00
|
|
|
vm_assert((int32_t)oparg(2, 0xFFFF) < func->def->defs_length, "invalid funcdef");
|
|
|
|
fd = func->def->defs[(int32_t)oparg(2, 0xFFFF)];
|
2018-02-13 21:14:55 +00:00
|
|
|
elen = fd->environments_length;
|
2018-09-06 02:18:42 +00:00
|
|
|
fn = janet_gcalloc(JANET_MEMORY_FUNCTION, sizeof(JanetFunction) + (elen * sizeof(JanetFuncEnv *)));
|
2018-02-13 21:14:55 +00:00
|
|
|
fn->def = fd;
|
2018-02-12 21:43:59 +00:00
|
|
|
{
|
2018-02-13 21:14:55 +00:00
|
|
|
int32_t i;
|
|
|
|
for (i = 0; i < elen; ++i) {
|
|
|
|
int32_t inherit = fd->environments[i];
|
|
|
|
if (inherit == -1) {
|
2018-09-06 02:18:42 +00:00
|
|
|
JanetStackFrame *frame = janet_stack_frame(stack);
|
2018-02-13 21:14:55 +00:00
|
|
|
if (!frame->env) {
|
|
|
|
/* Lazy capture of current stack frame */
|
2018-09-06 02:18:42 +00:00
|
|
|
JanetFuncEnv *env = janet_gcalloc(JANET_MEMORY_FUNCENV, sizeof(JanetFuncEnv));
|
2018-03-11 19:35:23 +00:00
|
|
|
env->offset = fiber->frame;
|
|
|
|
env->as.fiber = fiber;
|
2018-02-13 21:14:55 +00:00
|
|
|
env->length = func->def->slotcount;
|
|
|
|
frame->env = env;
|
2018-02-12 21:43:59 +00:00
|
|
|
}
|
2018-02-13 21:14:55 +00:00
|
|
|
fn->envs[i] = frame->env;
|
|
|
|
} else {
|
|
|
|
fn->envs[i] = func->envs[inherit];
|
2018-02-12 21:43:59 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2018-09-06 02:18:42 +00:00
|
|
|
stack[oparg(1, 0xFF)] = janet_wrap_function(fn);
|
2017-11-27 00:31:40 +00:00
|
|
|
pc++;
|
|
|
|
vm_checkgc_next();
|
2018-05-20 01:16:00 +00:00
|
|
|
}
|
2017-04-19 13:02:12 +00:00
|
|
|
|
2018-09-06 02:18:42 +00:00
|
|
|
VM_OP(JOP_PUSH)
|
|
|
|
janet_fiber_push(fiber, stack[oparg(1, 0xFFFFFF)]);
|
2018-02-12 21:43:59 +00:00
|
|
|
pc++;
|
2018-03-11 19:35:23 +00:00
|
|
|
stack = fiber->data + fiber->frame;
|
2018-02-12 21:43:59 +00:00
|
|
|
vm_checkgc_next();
|
2018-02-01 02:40:19 +00:00
|
|
|
|
2018-09-06 02:18:42 +00:00
|
|
|
VM_OP(JOP_PUSH_2)
|
|
|
|
janet_fiber_push2(fiber,
|
2018-02-12 21:43:59 +00:00
|
|
|
stack[oparg(1, 0xFF)],
|
|
|
|
stack[oparg(2, 0xFFFF)]);
|
2018-02-01 02:40:19 +00:00
|
|
|
pc++;
|
2018-03-11 19:35:23 +00:00
|
|
|
stack = fiber->data + fiber->frame;
|
2018-02-01 02:40:19 +00:00
|
|
|
vm_checkgc_next();
|
|
|
|
|
2018-09-06 02:18:42 +00:00
|
|
|
VM_OP(JOP_PUSH_3)
|
|
|
|
janet_fiber_push3(fiber,
|
2018-02-12 21:43:59 +00:00
|
|
|
stack[oparg(1, 0xFF)],
|
|
|
|
stack[oparg(2, 0xFF)],
|
|
|
|
stack[oparg(3, 0xFF)]);
|
2018-02-01 02:40:19 +00:00
|
|
|
pc++;
|
2018-03-11 19:35:23 +00:00
|
|
|
stack = fiber->data + fiber->frame;
|
2018-02-01 02:40:19 +00:00
|
|
|
vm_checkgc_next();
|
|
|
|
|
2018-09-06 02:18:42 +00:00
|
|
|
VM_OP(JOP_PUSH_ARRAY)
|
2018-02-01 02:40:19 +00:00
|
|
|
{
|
2018-09-06 02:18:42 +00:00
|
|
|
const Janet *vals;
|
2018-02-01 02:40:19 +00:00
|
|
|
int32_t len;
|
2018-09-06 02:18:42 +00:00
|
|
|
if (janet_indexed_view(stack[oparg(1, 0xFFFFFF)], &vals, &len)) {
|
|
|
|
janet_fiber_pushn(fiber, vals, len);
|
2018-02-01 02:40:19 +00:00
|
|
|
} else {
|
2018-07-04 03:07:35 +00:00
|
|
|
retreg = stack[oparg(1, 0xFFFFFF)];
|
2018-09-06 02:18:42 +00:00
|
|
|
expected_types = JANET_TFLAG_INDEXED;
|
2018-07-04 03:07:35 +00:00
|
|
|
goto vm_type_error;
|
2018-01-12 18:54:37 +00:00
|
|
|
}
|
2018-02-01 02:40:19 +00:00
|
|
|
}
|
|
|
|
pc++;
|
2018-03-11 19:35:23 +00:00
|
|
|
stack = fiber->data + fiber->frame;
|
2018-02-01 02:40:19 +00:00
|
|
|
vm_checkgc_next();
|
|
|
|
|
2018-09-06 02:18:42 +00:00
|
|
|
VM_OP(JOP_CALL)
|
2018-02-01 02:40:19 +00:00
|
|
|
{
|
2018-09-06 02:18:42 +00:00
|
|
|
Janet callee = stack[oparg(2, 0xFFFF)];
|
2018-03-11 19:35:23 +00:00
|
|
|
if (fiber->maxstack &&
|
|
|
|
fiber->stacktop > fiber->maxstack) {
|
2018-02-12 16:49:10 +00:00
|
|
|
vm_throw("stack overflow");
|
|
|
|
}
|
2018-09-06 02:18:42 +00:00
|
|
|
if (janet_checktype(callee, JANET_FUNCTION)) {
|
|
|
|
func = janet_unwrap_function(callee);
|
|
|
|
janet_stack_frame(stack)->pc = pc;
|
|
|
|
if (janet_fiber_funcframe(fiber, func))
|
2018-08-03 17:41:44 +00:00
|
|
|
goto vm_arity_error;
|
2018-03-11 19:35:23 +00:00
|
|
|
stack = fiber->data + fiber->frame;
|
2018-02-01 02:40:19 +00:00
|
|
|
pc = func->def->bytecode;
|
|
|
|
vm_checkgc_next();
|
2018-09-06 02:18:42 +00:00
|
|
|
} else if (janet_checktype(callee, JANET_CFUNCTION)) {
|
|
|
|
JanetArgs args;
|
2018-03-11 19:35:23 +00:00
|
|
|
args.n = fiber->stacktop - fiber->stackstart;
|
2018-09-06 02:18:42 +00:00
|
|
|
janet_fiber_cframe(fiber, janet_unwrap_cfunction(callee));
|
|
|
|
retreg = janet_wrap_nil();
|
2018-03-11 19:35:23 +00:00
|
|
|
args.v = fiber->data + fiber->frame;
|
2018-02-01 02:40:19 +00:00
|
|
|
args.ret = &retreg;
|
2018-09-06 02:18:42 +00:00
|
|
|
if ((signal = janet_unwrap_cfunction(callee)(args))) {
|
2018-05-17 17:34:11 +00:00
|
|
|
goto vm_exit;
|
2017-04-12 14:31:50 +00:00
|
|
|
}
|
2018-02-01 02:40:19 +00:00
|
|
|
goto vm_return_cfunc;
|
2017-11-06 03:05:47 +00:00
|
|
|
}
|
2018-09-06 02:18:42 +00:00
|
|
|
expected_types = JANET_TFLAG_CALLABLE;
|
2018-07-04 03:07:35 +00:00
|
|
|
retreg = callee;
|
|
|
|
goto vm_type_error;
|
2018-02-01 02:40:19 +00:00
|
|
|
}
|
2017-11-06 03:05:47 +00:00
|
|
|
|
2018-09-06 02:18:42 +00:00
|
|
|
VM_OP(JOP_TAILCALL)
|
2018-02-01 02:40:19 +00:00
|
|
|
{
|
2018-09-06 02:18:42 +00:00
|
|
|
Janet callee = stack[oparg(1, 0xFFFFFF)];
|
|
|
|
if (janet_checktype(callee, JANET_FUNCTION)) {
|
|
|
|
func = janet_unwrap_function(callee);
|
|
|
|
if (janet_fiber_funcframe_tail(fiber, func))
|
2018-08-03 17:41:44 +00:00
|
|
|
goto vm_arity_error;
|
2018-03-11 19:35:23 +00:00
|
|
|
stack = fiber->data + fiber->frame;
|
2018-02-01 02:40:19 +00:00
|
|
|
pc = func->def->bytecode;
|
|
|
|
vm_checkgc_next();
|
2018-09-06 02:18:42 +00:00
|
|
|
} else if (janet_checktype(callee, JANET_CFUNCTION)) {
|
|
|
|
JanetArgs args;
|
2018-03-11 19:35:23 +00:00
|
|
|
args.n = fiber->stacktop - fiber->stackstart;
|
2018-09-06 02:18:42 +00:00
|
|
|
janet_fiber_cframe(fiber, janet_unwrap_cfunction(callee));
|
|
|
|
retreg = janet_wrap_nil();
|
2018-03-11 19:35:23 +00:00
|
|
|
args.v = fiber->data + fiber->frame;
|
2018-02-01 02:40:19 +00:00
|
|
|
args.ret = &retreg;
|
2018-09-06 02:18:42 +00:00
|
|
|
if ((signal = janet_unwrap_cfunction(callee)(args))) {
|
2018-05-17 17:34:11 +00:00
|
|
|
goto vm_exit;
|
2017-04-12 14:31:50 +00:00
|
|
|
}
|
2018-02-01 02:40:19 +00:00
|
|
|
goto vm_return_cfunc_tail;
|
2017-11-06 03:05:47 +00:00
|
|
|
}
|
2018-09-06 02:18:42 +00:00
|
|
|
expected_types = JANET_TFLAG_CALLABLE;
|
2018-07-04 03:07:35 +00:00
|
|
|
retreg = callee;
|
|
|
|
goto vm_type_error;
|
2018-02-01 02:40:19 +00:00
|
|
|
}
|
2017-04-12 14:31:50 +00:00
|
|
|
|
2018-09-06 02:18:42 +00:00
|
|
|
VM_OP(JOP_RESUME)
|
2018-02-01 02:40:19 +00:00
|
|
|
{
|
2018-09-06 02:18:42 +00:00
|
|
|
Janet fiberval = stack[oparg(2, 0xFF)];
|
|
|
|
vm_assert_type(fiberval, JANET_FIBER);
|
2018-05-17 02:09:36 +00:00
|
|
|
retreg = stack[oparg(3, 0xFF)];
|
2018-09-06 02:18:42 +00:00
|
|
|
fiber->child = janet_unwrap_fiber(fiberval);
|
2018-05-17 02:09:36 +00:00
|
|
|
goto vm_resume_child;
|
2018-02-01 02:40:19 +00:00
|
|
|
}
|
2017-11-25 04:17:04 +00:00
|
|
|
|
2018-09-06 02:18:42 +00:00
|
|
|
VM_OP(JOP_SIGNAL)
|
2018-03-11 19:35:23 +00:00
|
|
|
{
|
2018-05-17 02:09:36 +00:00
|
|
|
int32_t s = oparg(3, 0xFF);
|
2018-09-06 02:18:42 +00:00
|
|
|
if (s > JANET_SIGNAL_USER9) s = JANET_SIGNAL_USER9;
|
2018-05-17 02:09:36 +00:00
|
|
|
if (s < 0) s = 0;
|
|
|
|
signal = s;
|
|
|
|
retreg = stack[oparg(2, 0xFF)];
|
2018-09-06 02:18:42 +00:00
|
|
|
fiber->flags |= JANET_FIBER_FLAG_SIGNAL_WAITING;
|
2018-03-11 19:35:23 +00:00
|
|
|
goto vm_exit;
|
|
|
|
}
|
|
|
|
|
2018-09-06 02:18:42 +00:00
|
|
|
VM_OP(JOP_PUT)
|
2018-06-17 17:55:02 +00:00
|
|
|
{
|
2018-09-06 02:18:42 +00:00
|
|
|
Janet ds = stack[oparg(1, 0xFF)];
|
|
|
|
Janet key = stack[oparg(2, 0xFF)];
|
|
|
|
Janet value = stack[oparg(3, 0xFF)];
|
|
|
|
switch (janet_type(ds)) {
|
2018-06-17 17:55:02 +00:00
|
|
|
default:
|
2018-09-06 02:18:42 +00:00
|
|
|
expected_types = JANET_TFLAG_ARRAY | JANET_TFLAG_BUFFER | JANET_TFLAG_TABLE;
|
2018-07-04 03:07:35 +00:00
|
|
|
retreg = ds;
|
|
|
|
goto vm_type_error;
|
2018-09-06 02:18:42 +00:00
|
|
|
case JANET_ARRAY:
|
2018-06-17 17:55:02 +00:00
|
|
|
{
|
|
|
|
int32_t index;
|
2018-09-06 02:18:42 +00:00
|
|
|
JanetArray *array = janet_unwrap_array(ds);
|
|
|
|
vm_assert_type(key, JANET_INTEGER);
|
|
|
|
if (janet_unwrap_integer(key) < 0)
|
2018-06-17 17:55:02 +00:00
|
|
|
vm_throw("expected non-negative integer key");
|
2018-09-06 02:18:42 +00:00
|
|
|
index = janet_unwrap_integer(key);
|
2018-06-17 17:55:02 +00:00
|
|
|
if (index == INT32_MAX)
|
|
|
|
vm_throw("key too large");
|
|
|
|
if (index >= array->count) {
|
2018-09-06 02:18:42 +00:00
|
|
|
janet_array_setcount(array, index + 1);
|
2018-06-17 17:55:02 +00:00
|
|
|
}
|
|
|
|
array->data[index] = value;
|
|
|
|
break;
|
|
|
|
}
|
2018-09-06 02:18:42 +00:00
|
|
|
case JANET_BUFFER:
|
2018-06-17 17:55:02 +00:00
|
|
|
{
|
|
|
|
int32_t index;
|
2018-09-06 02:18:42 +00:00
|
|
|
JanetBuffer *buffer = janet_unwrap_buffer(ds);
|
|
|
|
vm_assert_type(key, JANET_INTEGER);
|
|
|
|
if (janet_unwrap_integer(key) < 0)
|
2018-06-17 17:55:02 +00:00
|
|
|
vm_throw("expected non-negative integer key");
|
2018-09-06 02:18:42 +00:00
|
|
|
index = janet_unwrap_integer(key);
|
2018-06-17 17:55:02 +00:00
|
|
|
if (index == INT32_MAX)
|
|
|
|
vm_throw("key too large");
|
2018-09-06 02:18:42 +00:00
|
|
|
vm_assert_type(value, JANET_INTEGER);
|
2018-06-17 17:55:02 +00:00
|
|
|
if (index >= buffer->count) {
|
2018-09-06 02:18:42 +00:00
|
|
|
janet_buffer_setcount(buffer, index + 1);
|
2018-06-17 17:55:02 +00:00
|
|
|
}
|
2018-09-06 02:18:42 +00:00
|
|
|
buffer->data[index] = (uint8_t) (janet_unwrap_integer(value) & 0xFF);
|
2018-06-17 17:55:02 +00:00
|
|
|
break;
|
|
|
|
}
|
2018-09-06 02:18:42 +00:00
|
|
|
case JANET_TABLE:
|
|
|
|
janet_table_put(janet_unwrap_table(ds), key, value);
|
2018-06-17 17:55:02 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
++pc;
|
|
|
|
vm_checkgc_next();
|
|
|
|
}
|
2017-11-25 04:17:04 +00:00
|
|
|
|
2018-09-06 02:18:42 +00:00
|
|
|
VM_OP(JOP_PUT_INDEX)
|
2018-06-17 17:55:02 +00:00
|
|
|
{
|
2018-09-06 02:18:42 +00:00
|
|
|
Janet ds = stack[oparg(1, 0xFF)];
|
|
|
|
Janet value = stack[oparg(2, 0xFF)];
|
2018-06-17 17:55:02 +00:00
|
|
|
int32_t index = oparg(3, 0xFF);
|
2018-09-06 02:18:42 +00:00
|
|
|
switch (janet_type(ds)) {
|
2018-06-17 17:55:02 +00:00
|
|
|
default:
|
2018-09-06 02:18:42 +00:00
|
|
|
expected_types = JANET_TFLAG_ARRAY | JANET_TFLAG_BUFFER;
|
2018-07-04 03:07:35 +00:00
|
|
|
retreg = ds;
|
|
|
|
goto vm_type_error;
|
2018-09-06 02:18:42 +00:00
|
|
|
case JANET_ARRAY:
|
|
|
|
if (index >= janet_unwrap_array(ds)->count) {
|
|
|
|
janet_array_ensure(janet_unwrap_array(ds), 2 * index);
|
|
|
|
janet_unwrap_array(ds)->count = index + 1;
|
2018-06-17 17:55:02 +00:00
|
|
|
}
|
2018-09-06 02:18:42 +00:00
|
|
|
janet_unwrap_array(ds)->data[index] = value;
|
2018-06-17 17:55:02 +00:00
|
|
|
break;
|
2018-09-06 02:18:42 +00:00
|
|
|
case JANET_BUFFER:
|
|
|
|
vm_assert_type(value, JANET_INTEGER);
|
|
|
|
if (index >= janet_unwrap_buffer(ds)->count) {
|
|
|
|
janet_buffer_ensure(janet_unwrap_buffer(ds), 2 * index);
|
|
|
|
janet_unwrap_buffer(ds)->count = index + 1;
|
2018-06-17 17:55:02 +00:00
|
|
|
}
|
2018-09-06 02:18:42 +00:00
|
|
|
janet_unwrap_buffer(ds)->data[index] = janet_unwrap_integer(value);
|
2018-06-17 17:55:02 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
++pc;
|
|
|
|
vm_checkgc_next();
|
|
|
|
}
|
2017-11-25 04:17:04 +00:00
|
|
|
|
2018-09-06 02:18:42 +00:00
|
|
|
VM_OP(JOP_GET)
|
2018-06-17 17:55:02 +00:00
|
|
|
{
|
2018-09-06 02:18:42 +00:00
|
|
|
Janet ds = stack[oparg(2, 0xFF)];
|
|
|
|
Janet key = stack[oparg(3, 0xFF)];
|
|
|
|
Janet value;
|
|
|
|
switch (janet_type(ds)) {
|
2018-06-17 17:55:02 +00:00
|
|
|
default:
|
2018-09-06 02:18:42 +00:00
|
|
|
expected_types = JANET_TFLAG_LENGTHABLE;
|
2018-07-04 03:07:35 +00:00
|
|
|
retreg = ds;
|
|
|
|
goto vm_type_error;
|
2018-09-06 02:18:42 +00:00
|
|
|
case JANET_STRUCT:
|
|
|
|
value = janet_struct_get(janet_unwrap_struct(ds), key);
|
2018-06-17 17:55:02 +00:00
|
|
|
break;
|
2018-09-06 02:18:42 +00:00
|
|
|
case JANET_TABLE:
|
|
|
|
value = janet_table_get(janet_unwrap_table(ds), key);
|
2018-06-17 17:55:02 +00:00
|
|
|
break;
|
2018-09-06 02:18:42 +00:00
|
|
|
case JANET_ARRAY:
|
2018-06-17 17:55:02 +00:00
|
|
|
{
|
2018-09-06 02:18:42 +00:00
|
|
|
JanetArray *array = janet_unwrap_array(ds);
|
2018-06-17 17:55:02 +00:00
|
|
|
int32_t index;
|
2018-09-06 02:18:42 +00:00
|
|
|
vm_assert_type(key, JANET_INTEGER);
|
|
|
|
index = janet_unwrap_integer(key);
|
2018-06-17 17:55:02 +00:00
|
|
|
if (index < 0 || index >= array->count) {
|
|
|
|
/*vm_throw("index out of bounds");*/
|
2018-09-06 02:18:42 +00:00
|
|
|
value = janet_wrap_nil();
|
2018-06-17 17:55:02 +00:00
|
|
|
} else {
|
|
|
|
value = array->data[index];
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2018-09-06 02:18:42 +00:00
|
|
|
case JANET_TUPLE:
|
2018-06-17 17:55:02 +00:00
|
|
|
{
|
2018-09-06 02:18:42 +00:00
|
|
|
const Janet *tuple = janet_unwrap_tuple(ds);
|
2018-06-17 17:55:02 +00:00
|
|
|
int32_t index;
|
2018-09-06 02:18:42 +00:00
|
|
|
vm_assert_type(key, JANET_INTEGER);
|
|
|
|
index = janet_unwrap_integer(key);
|
|
|
|
if (index < 0 || index >= janet_tuple_length(tuple)) {
|
2018-06-17 17:55:02 +00:00
|
|
|
/*vm_throw("index out of bounds");*/
|
2018-09-06 02:18:42 +00:00
|
|
|
value = janet_wrap_nil();
|
2018-06-17 17:55:02 +00:00
|
|
|
} else {
|
|
|
|
value = tuple[index];
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2018-09-06 02:18:42 +00:00
|
|
|
case JANET_BUFFER:
|
2018-06-17 17:55:02 +00:00
|
|
|
{
|
2018-09-06 02:18:42 +00:00
|
|
|
JanetBuffer *buffer = janet_unwrap_buffer(ds);
|
2018-06-17 17:55:02 +00:00
|
|
|
int32_t index;
|
2018-09-06 02:18:42 +00:00
|
|
|
vm_assert_type(key, JANET_INTEGER);
|
|
|
|
index = janet_unwrap_integer(key);
|
2018-06-17 17:55:02 +00:00
|
|
|
if (index < 0 || index >= buffer->count) {
|
|
|
|
/*vm_throw("index out of bounds");*/
|
2018-09-06 02:18:42 +00:00
|
|
|
value = janet_wrap_nil();
|
2018-06-17 17:55:02 +00:00
|
|
|
} else {
|
2018-09-06 02:18:42 +00:00
|
|
|
value = janet_wrap_integer(buffer->data[index]);
|
2018-06-17 17:55:02 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2018-09-06 02:18:42 +00:00
|
|
|
case JANET_STRING:
|
|
|
|
case JANET_SYMBOL:
|
2018-06-17 17:55:02 +00:00
|
|
|
{
|
2018-09-06 02:18:42 +00:00
|
|
|
const uint8_t *str = janet_unwrap_string(ds);
|
2018-06-17 17:55:02 +00:00
|
|
|
int32_t index;
|
2018-09-06 02:18:42 +00:00
|
|
|
vm_assert_type(key, JANET_INTEGER);
|
|
|
|
index = janet_unwrap_integer(key);
|
|
|
|
if (index < 0 || index >= janet_string_length(str)) {
|
2018-06-17 17:55:02 +00:00
|
|
|
/*vm_throw("index out of bounds");*/
|
2018-09-06 02:18:42 +00:00
|
|
|
value = janet_wrap_nil();
|
2018-06-17 17:55:02 +00:00
|
|
|
} else {
|
2018-09-06 02:18:42 +00:00
|
|
|
value = janet_wrap_integer(str[index]);
|
2018-06-17 17:55:02 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
stack[oparg(1, 0xFF)] = value;
|
|
|
|
++pc;
|
|
|
|
vm_next();
|
|
|
|
}
|
2017-11-25 04:17:04 +00:00
|
|
|
|
2018-09-06 02:18:42 +00:00
|
|
|
VM_OP(JOP_GET_INDEX)
|
2018-06-17 17:55:02 +00:00
|
|
|
{
|
2018-09-06 02:18:42 +00:00
|
|
|
Janet ds = stack[oparg(2, 0xFF)];
|
2018-06-17 17:55:02 +00:00
|
|
|
int32_t index = oparg(3, 0xFF);
|
2018-09-06 02:18:42 +00:00
|
|
|
Janet value;
|
|
|
|
switch (janet_type(ds)) {
|
2018-06-17 17:55:02 +00:00
|
|
|
default:
|
2018-09-06 02:18:42 +00:00
|
|
|
expected_types = JANET_TFLAG_LENGTHABLE;
|
2018-07-04 03:07:35 +00:00
|
|
|
retreg = ds;
|
|
|
|
goto vm_type_error;
|
2018-09-06 02:18:42 +00:00
|
|
|
case JANET_STRING:
|
|
|
|
case JANET_SYMBOL:
|
|
|
|
if (index >= janet_string_length(janet_unwrap_string(ds))) {
|
2018-06-17 17:55:02 +00:00
|
|
|
/*vm_throw("index out of bounds");*/
|
2018-09-06 02:18:42 +00:00
|
|
|
value = janet_wrap_nil();
|
2018-06-17 17:55:02 +00:00
|
|
|
} else {
|
2018-09-06 02:18:42 +00:00
|
|
|
value = janet_wrap_integer(janet_unwrap_string(ds)[index]);
|
2018-06-17 17:55:02 +00:00
|
|
|
}
|
|
|
|
break;
|
2018-09-06 02:18:42 +00:00
|
|
|
case JANET_ARRAY:
|
|
|
|
if (index >= janet_unwrap_array(ds)->count) {
|
2018-06-17 17:55:02 +00:00
|
|
|
/*vm_throw("index out of bounds");*/
|
2018-09-06 02:18:42 +00:00
|
|
|
value = janet_wrap_nil();
|
2018-06-17 17:55:02 +00:00
|
|
|
} else {
|
2018-09-06 02:18:42 +00:00
|
|
|
value = janet_unwrap_array(ds)->data[index];
|
2018-06-17 17:55:02 +00:00
|
|
|
}
|
|
|
|
break;
|
2018-09-06 02:18:42 +00:00
|
|
|
case JANET_BUFFER:
|
|
|
|
if (index >= janet_unwrap_buffer(ds)->count) {
|
2018-06-17 17:55:02 +00:00
|
|
|
/*vm_throw("index out of bounds");*/
|
2018-09-06 02:18:42 +00:00
|
|
|
value = janet_wrap_nil();
|
2018-06-17 17:55:02 +00:00
|
|
|
} else {
|
2018-09-06 02:18:42 +00:00
|
|
|
value = janet_wrap_integer(janet_unwrap_buffer(ds)->data[index]);
|
2018-06-17 17:55:02 +00:00
|
|
|
}
|
|
|
|
break;
|
2018-09-06 02:18:42 +00:00
|
|
|
case JANET_TUPLE:
|
|
|
|
if (index >= janet_tuple_length(janet_unwrap_tuple(ds))) {
|
2018-06-17 17:55:02 +00:00
|
|
|
/*vm_throw("index out of bounds");*/
|
2018-09-06 02:18:42 +00:00
|
|
|
value = janet_wrap_nil();
|
2018-06-17 17:55:02 +00:00
|
|
|
} else {
|
2018-09-06 02:18:42 +00:00
|
|
|
value = janet_unwrap_tuple(ds)[index];
|
2018-06-17 17:55:02 +00:00
|
|
|
}
|
|
|
|
break;
|
2018-09-06 02:18:42 +00:00
|
|
|
case JANET_TABLE:
|
|
|
|
value = janet_table_get(janet_unwrap_table(ds), janet_wrap_integer(index));
|
2018-07-04 03:07:35 +00:00
|
|
|
break;
|
2018-09-06 02:18:42 +00:00
|
|
|
case JANET_STRUCT:
|
|
|
|
value = janet_struct_get(janet_unwrap_struct(ds), janet_wrap_integer(index));
|
2018-07-04 03:07:35 +00:00
|
|
|
break;
|
2018-06-17 17:55:02 +00:00
|
|
|
}
|
|
|
|
stack[oparg(1, 0xFF)] = value;
|
|
|
|
++pc;
|
|
|
|
vm_next();
|
|
|
|
}
|
2018-02-01 02:40:19 +00:00
|
|
|
|
2018-09-06 02:18:42 +00:00
|
|
|
VM_OP(JOP_LENGTH)
|
2018-06-17 17:55:02 +00:00
|
|
|
{
|
2018-09-06 02:18:42 +00:00
|
|
|
Janet x = stack[oparg(2, 0xFFFF)];
|
2018-06-17 17:55:02 +00:00
|
|
|
int32_t len;
|
2018-09-06 02:18:42 +00:00
|
|
|
switch (janet_type(x)) {
|
2018-06-17 17:55:02 +00:00
|
|
|
default:
|
2018-09-06 02:18:42 +00:00
|
|
|
expected_types = JANET_TFLAG_LENGTHABLE;
|
2018-07-04 03:07:35 +00:00
|
|
|
retreg = x;
|
|
|
|
goto vm_type_error;
|
2018-09-06 02:18:42 +00:00
|
|
|
case JANET_STRING:
|
|
|
|
case JANET_SYMBOL:
|
|
|
|
len = janet_string_length(janet_unwrap_string(x));
|
2018-06-17 17:55:02 +00:00
|
|
|
break;
|
2018-09-06 02:18:42 +00:00
|
|
|
case JANET_ARRAY:
|
|
|
|
len = janet_unwrap_array(x)->count;
|
2018-06-17 17:55:02 +00:00
|
|
|
break;
|
2018-09-06 02:18:42 +00:00
|
|
|
case JANET_BUFFER:
|
|
|
|
len = janet_unwrap_buffer(x)->count;
|
2018-06-17 17:55:02 +00:00
|
|
|
break;
|
2018-09-06 02:18:42 +00:00
|
|
|
case JANET_TUPLE:
|
|
|
|
len = janet_tuple_length(janet_unwrap_tuple(x));
|
2018-06-17 17:55:02 +00:00
|
|
|
break;
|
2018-09-06 02:18:42 +00:00
|
|
|
case JANET_STRUCT:
|
|
|
|
len = janet_struct_length(janet_unwrap_struct(x));
|
2018-06-17 17:55:02 +00:00
|
|
|
break;
|
2018-09-06 02:18:42 +00:00
|
|
|
case JANET_TABLE:
|
|
|
|
len = janet_unwrap_table(x)->count;
|
2018-06-17 17:55:02 +00:00
|
|
|
break;
|
|
|
|
}
|
2018-09-06 02:18:42 +00:00
|
|
|
stack[oparg(1, 0xFF)] = janet_wrap_integer(len);
|
2018-06-17 17:55:02 +00:00
|
|
|
++pc;
|
|
|
|
vm_next();
|
|
|
|
}
|
2018-02-01 02:40:19 +00:00
|
|
|
|
2018-09-06 02:18:42 +00:00
|
|
|
VM_OP(JOP_MAKE_ARRAY)
|
2018-07-04 03:07:35 +00:00
|
|
|
{
|
|
|
|
int32_t count = fiber->stacktop - fiber->stackstart;
|
2018-09-06 02:18:42 +00:00
|
|
|
Janet *mem = fiber->data + fiber->stackstart;
|
|
|
|
stack[oparg(1, 0xFFFFFF)] = janet_wrap_array(janet_array_n(mem, count));
|
2018-07-04 03:07:35 +00:00
|
|
|
fiber->stacktop = fiber->stackstart;
|
|
|
|
++pc;
|
|
|
|
vm_checkgc_next();
|
|
|
|
}
|
|
|
|
|
2018-09-06 02:18:42 +00:00
|
|
|
VM_OP(JOP_MAKE_TUPLE)
|
2018-07-04 03:07:35 +00:00
|
|
|
{
|
|
|
|
int32_t count = fiber->stacktop - fiber->stackstart;
|
2018-09-06 02:18:42 +00:00
|
|
|
Janet *mem = fiber->data + fiber->stackstart;
|
|
|
|
stack[oparg(1, 0xFFFFFF)] = janet_wrap_tuple(janet_tuple_n(mem, count));
|
2018-07-04 03:07:35 +00:00
|
|
|
fiber->stacktop = fiber->stackstart;
|
|
|
|
++pc;
|
|
|
|
vm_checkgc_next();
|
|
|
|
}
|
|
|
|
|
2018-09-06 02:18:42 +00:00
|
|
|
VM_OP(JOP_MAKE_TABLE)
|
2018-07-04 03:07:35 +00:00
|
|
|
{
|
|
|
|
int32_t count = fiber->stacktop - fiber->stackstart;
|
2018-09-06 02:18:42 +00:00
|
|
|
Janet *mem = fiber->data + fiber->stackstart;
|
2018-07-04 03:07:35 +00:00
|
|
|
if (count & 1)
|
|
|
|
vm_throw("expected even number of arguments to table constructor");
|
2018-09-06 02:18:42 +00:00
|
|
|
JanetTable *table = janet_table(count / 2);
|
2018-07-04 03:07:35 +00:00
|
|
|
for (int32_t i = 0; i < count; i += 2)
|
2018-09-06 02:18:42 +00:00
|
|
|
janet_table_put(table, mem[i], mem[i + 1]);
|
|
|
|
stack[oparg(1, 0xFFFFFF)] = janet_wrap_table(table);
|
2018-07-04 03:07:35 +00:00
|
|
|
fiber->stacktop = fiber->stackstart;
|
|
|
|
++pc;
|
|
|
|
vm_checkgc_next();
|
|
|
|
}
|
|
|
|
|
2018-09-06 02:18:42 +00:00
|
|
|
VM_OP(JOP_MAKE_STRUCT)
|
2018-07-04 03:07:35 +00:00
|
|
|
{
|
|
|
|
int32_t count = fiber->stacktop - fiber->stackstart;
|
2018-09-06 02:18:42 +00:00
|
|
|
Janet *mem = fiber->data + fiber->stackstart;
|
2018-07-04 03:07:35 +00:00
|
|
|
if (count & 1)
|
|
|
|
vm_throw("expected even number of arguments to struct constructor");
|
2018-09-06 02:18:42 +00:00
|
|
|
JanetKV *st = janet_struct_begin(count / 2);
|
2018-07-04 03:07:35 +00:00
|
|
|
for (int32_t i = 0; i < count; i += 2)
|
2018-09-06 02:18:42 +00:00
|
|
|
janet_struct_put(st, mem[i], mem[i + 1]);
|
|
|
|
stack[oparg(1, 0xFFFFFF)] = janet_wrap_struct(janet_struct_end(st));
|
2018-07-04 03:07:35 +00:00
|
|
|
fiber->stacktop = fiber->stackstart;
|
|
|
|
++pc;
|
|
|
|
vm_checkgc_next();
|
|
|
|
}
|
|
|
|
|
2018-09-06 02:18:42 +00:00
|
|
|
VM_OP(JOP_MAKE_STRING)
|
2018-07-04 03:07:35 +00:00
|
|
|
{
|
|
|
|
int32_t count = fiber->stacktop - fiber->stackstart;
|
2018-09-06 02:18:42 +00:00
|
|
|
Janet *mem = fiber->data + fiber->stackstart;
|
|
|
|
JanetBuffer buffer;
|
|
|
|
janet_buffer_init(&buffer, 10 * count);
|
2018-07-04 03:07:35 +00:00
|
|
|
for (int32_t i = 0; i < count; i++)
|
2018-09-06 02:18:42 +00:00
|
|
|
janet_to_string_b(&buffer, mem[i]);
|
|
|
|
stack[oparg(1, 0xFFFFFF)] = janet_stringv(buffer.data, buffer.count);
|
|
|
|
janet_buffer_deinit(&buffer);
|
2018-07-04 03:07:35 +00:00
|
|
|
fiber->stacktop = fiber->stackstart;
|
|
|
|
++pc;
|
|
|
|
vm_checkgc_next();
|
|
|
|
}
|
|
|
|
|
2018-09-06 02:18:42 +00:00
|
|
|
VM_OP(JOP_MAKE_BUFFER)
|
2018-07-04 03:07:35 +00:00
|
|
|
{
|
|
|
|
int32_t count = fiber->stacktop - fiber->stackstart;
|
2018-09-06 02:18:42 +00:00
|
|
|
Janet *mem = fiber->data + fiber->stackstart;
|
|
|
|
JanetBuffer *buffer = janet_buffer(10 * count);
|
2018-07-04 03:07:35 +00:00
|
|
|
for (int32_t i = 0; i < count; i++)
|
2018-09-06 02:18:42 +00:00
|
|
|
janet_to_string_b(buffer, mem[i]);
|
|
|
|
stack[oparg(1, 0xFFFFFF)] = janet_wrap_buffer(buffer);
|
2018-07-04 03:07:35 +00:00
|
|
|
fiber->stacktop = fiber->stackstart;
|
|
|
|
++pc;
|
|
|
|
vm_checkgc_next();
|
|
|
|
}
|
|
|
|
|
2018-09-06 02:18:42 +00:00
|
|
|
/* Return from c function. Simpler than returning from janet function */
|
2018-02-01 02:40:19 +00:00
|
|
|
vm_return_cfunc:
|
|
|
|
{
|
2018-09-06 02:18:42 +00:00
|
|
|
janet_fiber_popframe(fiber);
|
2018-05-17 02:09:36 +00:00
|
|
|
if (fiber->frame == 0) goto vm_exit;
|
2018-03-11 19:35:23 +00:00
|
|
|
stack = fiber->data + fiber->frame;
|
2018-02-01 02:40:19 +00:00
|
|
|
stack[oparg(1, 0xFF)] = retreg;
|
2018-06-17 17:55:02 +00:00
|
|
|
++pc;
|
2018-02-01 02:40:19 +00:00
|
|
|
vm_checkgc_next();
|
|
|
|
}
|
2017-11-25 04:17:04 +00:00
|
|
|
|
2018-03-09 22:14:26 +00:00
|
|
|
/* Return from a cfunction that is in tail position (pop 2 stack frames) */
|
2018-02-01 02:40:19 +00:00
|
|
|
vm_return_cfunc_tail:
|
|
|
|
{
|
2018-09-06 02:18:42 +00:00
|
|
|
janet_fiber_popframe(fiber);
|
|
|
|
janet_fiber_popframe(fiber);
|
2018-05-17 02:09:36 +00:00
|
|
|
if (fiber->frame == 0) goto vm_exit;
|
2018-03-11 19:35:23 +00:00
|
|
|
goto vm_reset;
|
2018-02-01 02:40:19 +00:00
|
|
|
}
|
2018-01-04 02:36:10 +00:00
|
|
|
|
2018-02-01 02:40:19 +00:00
|
|
|
/* Handle returning from stack frame. Expect return value in retreg */
|
|
|
|
vm_return:
|
|
|
|
{
|
2018-09-06 02:18:42 +00:00
|
|
|
janet_fiber_popframe(fiber);
|
2018-05-17 02:09:36 +00:00
|
|
|
if (fiber->frame == 0) goto vm_exit;
|
2018-03-09 22:14:26 +00:00
|
|
|
goto vm_reset;
|
2018-02-01 02:40:19 +00:00
|
|
|
}
|
2017-03-10 05:09:42 +00:00
|
|
|
|
2018-08-03 17:41:44 +00:00
|
|
|
/* Handle function calls with bad arity */
|
|
|
|
vm_arity_error:
|
|
|
|
{
|
2018-08-03 23:46:15 +00:00
|
|
|
int32_t nargs = fiber->stacktop - fiber->stackstart;
|
2018-09-06 02:18:42 +00:00
|
|
|
retreg = janet_wrap_string(janet_formatc("%V called with %d argument%s, expected %d",
|
|
|
|
janet_wrap_function(func),
|
2018-08-03 23:46:15 +00:00
|
|
|
nargs,
|
|
|
|
nargs == 1 ? "" : "s",
|
2018-08-03 17:41:44 +00:00
|
|
|
func->def->arity));
|
2018-09-06 02:18:42 +00:00
|
|
|
signal = JANET_SIGNAL_ERROR;
|
2018-08-03 17:41:44 +00:00
|
|
|
goto vm_exit;
|
|
|
|
}
|
|
|
|
|
2018-05-17 02:09:36 +00:00
|
|
|
/* Resume a child fiber */
|
|
|
|
vm_resume_child:
|
2018-03-11 19:35:23 +00:00
|
|
|
{
|
2018-09-06 02:18:42 +00:00
|
|
|
JanetFiber *child = fiber->child;
|
|
|
|
JanetFiberStatus status = janet_fiber_status(child);
|
|
|
|
if (status == JANET_STATUS_ALIVE ||
|
|
|
|
status == JANET_STATUS_DEAD ||
|
|
|
|
status == JANET_STATUS_ERROR) {
|
2018-05-17 02:09:36 +00:00
|
|
|
vm_throw("cannot resume alive, dead, or errored fiber");
|
|
|
|
}
|
2018-09-06 02:18:42 +00:00
|
|
|
signal = janet_continue(child, retreg, &retreg);
|
|
|
|
if (signal != JANET_SIGNAL_OK) {
|
2018-05-17 02:09:36 +00:00
|
|
|
if (child->flags & (1 << signal)) {
|
|
|
|
/* Intercept signal */
|
2018-09-06 02:18:42 +00:00
|
|
|
signal = JANET_SIGNAL_OK;
|
2018-05-17 02:09:36 +00:00
|
|
|
fiber->child = NULL;
|
|
|
|
} else {
|
|
|
|
/* Propogate signal */
|
|
|
|
goto vm_exit;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
stack[oparg(1, 0xFF)] = retreg;
|
|
|
|
pc++;
|
|
|
|
vm_checkgc_next();
|
2018-03-11 19:35:23 +00:00
|
|
|
}
|
|
|
|
|
2018-07-04 03:07:35 +00:00
|
|
|
/* Handle type errors. The found type is the type of retreg,
|
|
|
|
* the expected types are in the expected_types field. */
|
|
|
|
vm_type_error:
|
|
|
|
{
|
2018-09-06 02:18:42 +00:00
|
|
|
JanetBuffer errbuf;
|
|
|
|
janet_buffer_init(&errbuf, 10);
|
|
|
|
janet_buffer_push_cstring(&errbuf, "expected ");
|
|
|
|
janet_buffer_push_types(&errbuf, expected_types);
|
|
|
|
janet_buffer_push_cstring(&errbuf, ", got ");
|
|
|
|
janet_buffer_push_cstring(&errbuf, janet_type_names[janet_type(retreg)] + 1);
|
|
|
|
retreg = janet_stringv(errbuf.data, errbuf.count);
|
|
|
|
janet_buffer_deinit(&errbuf);
|
|
|
|
signal = JANET_SIGNAL_ERROR;
|
2018-07-04 03:07:35 +00:00
|
|
|
goto vm_exit;
|
|
|
|
}
|
|
|
|
|
2018-02-01 02:40:19 +00:00
|
|
|
/* Handle errors from c functions and vm opcodes */
|
|
|
|
vm_error:
|
|
|
|
{
|
2018-09-06 02:18:42 +00:00
|
|
|
signal = JANET_SIGNAL_ERROR;
|
2018-03-11 19:35:23 +00:00
|
|
|
goto vm_exit;
|
2018-03-09 22:14:26 +00:00
|
|
|
}
|
|
|
|
|
2018-05-17 02:09:36 +00:00
|
|
|
/* Exit from vm loop. If signal is not set explicitely, does
|
2018-09-06 02:18:42 +00:00
|
|
|
* a successful return (JANET_SIGNAL_OK). */
|
2018-03-11 19:35:23 +00:00
|
|
|
vm_exit:
|
|
|
|
{
|
2018-09-06 02:18:42 +00:00
|
|
|
janet_stack_frame(stack)->pc = pc;
|
|
|
|
janet_vm_stackn--;
|
|
|
|
janet_gcunroot(in);
|
|
|
|
janet_gcunroot(janet_wrap_fiber(fiber));
|
|
|
|
janet_vm_fiber = old_vm_fiber;
|
2018-05-17 02:09:36 +00:00
|
|
|
*out = retreg;
|
2018-05-20 01:16:00 +00:00
|
|
|
/* All statuses correspond to signals except new and alive,
|
2018-05-17 02:09:36 +00:00
|
|
|
* which cannot be entered when exiting the vm loop.
|
2018-09-06 02:18:42 +00:00
|
|
|
* JANET_SIGNAL_OK -> JANET_STATUS_DEAD
|
|
|
|
* JANET_SIGNAL_YIELD -> JANET_STATUS_PENDING */
|
|
|
|
janet_fiber_set_status(fiber, signal);
|
2018-05-17 02:09:36 +00:00
|
|
|
return signal;
|
2018-03-09 22:14:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Reset state of machine */
|
|
|
|
vm_reset:
|
|
|
|
{
|
2018-03-11 19:35:23 +00:00
|
|
|
stack = fiber->data + fiber->frame;
|
2018-09-06 02:18:42 +00:00
|
|
|
func = janet_stack_frame(stack)->func;
|
|
|
|
pc = janet_stack_frame(stack)->pc;
|
2018-02-01 02:40:19 +00:00
|
|
|
stack[oparg(1, 0xFF)] = retreg;
|
|
|
|
pc++;
|
|
|
|
vm_checkgc_next();
|
2018-05-20 01:16:00 +00:00
|
|
|
}
|
2018-03-09 22:14:26 +00:00
|
|
|
|
2018-02-01 02:40:19 +00:00
|
|
|
VM_END()
|
2017-03-10 05:09:42 +00:00
|
|
|
|
2017-11-06 03:05:47 +00:00
|
|
|
#undef oparg
|
|
|
|
|
|
|
|
#undef vm_error
|
|
|
|
#undef vm_assert
|
|
|
|
#undef vm_binop
|
|
|
|
#undef vm_binop_real
|
|
|
|
#undef vm_binop_integer
|
|
|
|
#undef vm_binop_immediate
|
2017-03-10 05:09:42 +00:00
|
|
|
|
|
|
|
}
|
2018-05-17 02:09:36 +00:00
|
|
|
|
2018-09-06 02:18:42 +00:00
|
|
|
JanetSignal janet_call(
|
|
|
|
JanetFunction *fun,
|
2018-07-04 03:07:35 +00:00
|
|
|
int32_t argn,
|
2018-09-06 02:18:42 +00:00
|
|
|
const Janet *argv,
|
|
|
|
Janet *out,
|
|
|
|
JanetFiber **f) {
|
2018-05-17 02:09:36 +00:00
|
|
|
int32_t i;
|
2018-09-06 02:18:42 +00:00
|
|
|
JanetFiber *fiber = janet_fiber(fun, 64);
|
2018-07-04 03:07:35 +00:00
|
|
|
if (f)
|
|
|
|
*f = fiber;
|
|
|
|
for (i = 0; i < argn; i++)
|
2018-09-06 02:18:42 +00:00
|
|
|
janet_fiber_push(fiber, argv[i]);
|
|
|
|
if (janet_fiber_funcframe(fiber, fiber->root)) {
|
|
|
|
*out = janet_cstringv("arity mismatch");
|
|
|
|
return JANET_SIGNAL_ERROR;
|
2018-08-03 17:41:44 +00:00
|
|
|
}
|
2018-05-17 02:09:36 +00:00
|
|
|
/* Prevent push an extra value on the stack */
|
2018-09-06 02:18:42 +00:00
|
|
|
janet_fiber_set_status(fiber, JANET_STATUS_PENDING);
|
|
|
|
return janet_continue(fiber, janet_wrap_nil(), out);
|
2018-03-04 23:56:13 +00:00
|
|
|
}
|
|
|
|
|
2018-05-13 00:31:28 +00:00
|
|
|
/* Setup VM */
|
2018-09-06 02:18:42 +00:00
|
|
|
int janet_init(void) {
|
2017-02-12 20:16:55 +00:00
|
|
|
/* Garbage collection */
|
2018-09-06 02:18:42 +00:00
|
|
|
janet_vm_blocks = NULL;
|
|
|
|
janet_vm_next_collection = 0;
|
2017-04-18 20:55:03 +00:00
|
|
|
/* Setting memoryInterval to zero forces
|
2017-02-13 05:11:30 +00:00
|
|
|
* a collection pretty much every cycle, which is
|
2018-06-09 17:08:30 +00:00
|
|
|
* incredibly horrible for performance, but can help ensure
|
|
|
|
* there are no memory bugs during development */
|
2018-09-23 01:46:50 +00:00
|
|
|
janet_vm_gc_interval = 0x4000000;
|
2018-09-06 02:18:42 +00:00
|
|
|
janet_symcache_init();
|
2018-09-22 18:59:50 +00:00
|
|
|
/* Initialize gc list */
|
|
|
|
janet_vm_gc_marklist = NULL;
|
|
|
|
janet_vm_gc_marklist_count = 0;
|
|
|
|
janet_vm_gc_marklist_capacity = 0;
|
|
|
|
janet_vm_gc_marklist_rootcount = 0;
|
2018-06-12 18:24:45 +00:00
|
|
|
/* Initialize registry */
|
2018-09-06 02:18:42 +00:00
|
|
|
janet_vm_registry = janet_table(0);
|
|
|
|
janet_gcroot(janet_wrap_table(janet_vm_registry));
|
2017-11-06 03:05:47 +00:00
|
|
|
return 0;
|
2017-02-09 20:02:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Clear all memory associated with the VM */
|
2018-09-06 02:18:42 +00:00
|
|
|
void janet_deinit(void) {
|
|
|
|
janet_clear_memory();
|
|
|
|
janet_symcache_deinit();
|
2018-09-22 18:59:50 +00:00
|
|
|
free(janet_vm_gc_marklist);
|
|
|
|
janet_vm_gc_marklist = NULL;
|
2018-09-06 02:18:42 +00:00
|
|
|
janet_vm_registry = NULL;
|
2017-02-09 20:02:59 +00:00
|
|
|
}
|