// SPDX-License-Identifier: MIT // Copyright (c) 2023 John Watts and the LuminaSensum contributors #include "vm.h" #include "object.h" #include <stddef.h> #include <stdlib.h> struct vm_state { struct object **stack; struct object **stack_base; struct object **stack_next; }; struct vm_state *vm_create(void) { struct vm_state *state = malloc(sizeof(struct vm_state)); struct object **stack = malloc(sizeof(struct object *) * 16); state->stack = stack; state->stack_base = stack; state->stack_next = stack; return state; } void vm_destroy(struct vm_state **state) { free((*state)->stack); free(*state); *state = NULL; } void vm_stack_set(struct vm_state *state, int index, struct object *obj) { struct object **stack_pos = &state->stack_base[index]; struct object *old = *stack_pos; if (old != NULL) { object_drop(stack_pos); } *stack_pos = obj; } struct object *vm_stack_get(struct vm_state *state, int index) { struct object *obj = state->stack_base[index]; if (obj != NULL) { object_hold(obj); } return obj; } void vm_stack_push(struct vm_state *state, struct object *obj) { *state->stack_next++ = obj; } struct object *vm_stack_pop(struct vm_state *state) { struct object *obj = *--state->stack_next; *state->stack_next = NULL; return obj; } void vm_stack_drop(struct vm_state *state, int count) { while (count--) { struct object *obj = vm_stack_pop(state); if (obj != NULL) { object_drop(&obj); } } } void vm_call(struct object *obj, const char *name, int arg_count, struct vm_state *state) { struct object **old_base = state->stack_base; state->stack_base = state->stack_next - arg_count; dispatch_call(obj, name, arg_count, state); state->stack_base = old_base; }