Newer
Older
Tardis / lang / vm.c
// 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;
}