Newer
Older
Tardis / lang / list.c
// SPDX-License-Identifier: MIT
// Copyright (c) 2024 John Watts and the LuminaSensum contributors

#include "list.h"
#include "object.h"
#include "vm.h"
#include <stddef.h>

static struct object_class object_list_class;

struct object_list {
	int length;
	Object elems[];
};

Object object_list_create(VmState state, int length) {
	size_t elem_size = sizeof(Object) * length;
	size_t size = sizeof(struct object_list) + elem_size;
	Object obj = object_create(state, &object_list_class, size);
	struct object_list *list = (struct object_list *)object_priv(
		state, obj, &object_list_class);
	list->length = length;
	for (int i = 0; i < length; ++i)
		list->elems[i] = object_none();
	return obj;
}

static void object_list_cleanup(VmState state, Object obj) {
	struct object_list *list = (struct object_list *)object_priv(
		state, obj, &object_list_class);
	for (int i = 0; i < list->length; ++i)
		object_drop(state, &(list->elems[i]));
}

int object_list_length(VmState state, Object obj) {
	struct object_list *list = (struct object_list *)object_priv(
		state, obj, &object_list_class);
	return list->length;
}

void object_list_set(VmState state, Object obj, int index, Object new) {
	struct object_list *list = (struct object_list *)object_priv(
		state, obj, &object_list_class);
	vm_abort_if(state, index < 0, "object_list_get: index too small");
	vm_abort_if(state, index >= list->length,
		"object_list_get: index too large");
	object_drop(state, &(list->elems[index]));
	list->elems[index] = new;
}

Object object_list_get(VmState state, Object obj, int index) {
	struct object_list *list = (struct object_list *)object_priv(
		state, obj, &object_list_class);
	vm_abort_if(state, index < 0, "object_list_get: index too small");
	vm_abort_if(state, index >= list->length,
		"object_list_get: index too large");
	Object new = list->elems[index];
	object_hold(state, new);
	return new;
}

Object object_list_copy(VmState state, Object obj) {
	int length = object_list_length(state, obj);
	Object new = object_list_create(state, length);
	for (int i = 0; i < length; ++i) {
		Object elem = object_list_get(state, obj, i);
		object_list_set(state, new, i, elem);
	}
	return new;
}

static struct object_call object_list_calls[] = {{.name = NULL, /* end */}};

static struct object_class object_list_class = {
	.cleanup = object_list_cleanup,
	.calls = &object_list_calls[0],
};