diff --git a/lang/bytecode.c b/lang/bytecode.c index 748c53c..19bb6f5 100644 --- a/lang/bytecode.c +++ b/lang/bytecode.c @@ -6,6 +6,7 @@ #include "bytecode.h" #include "boolean.h" #include "debug.h" +#include "list.h" #include "object.h" #include "rational.h" #include "string.h" diff --git a/lang/list.c b/lang/list.c new file mode 100644 index 0000000..a3a3d53 --- /dev/null +++ b/lang/list.c @@ -0,0 +1,67 @@ +// SPDX-License-Identifier: MIT +// Copyright (c) 2023 John Watts and the LuminaSensum contributors + +#include "list.h" +#include "object.h" +#include "vm.h" +#include + +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; +} + +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], +}; diff --git a/lang/list.h b/lang/list.h new file mode 100644 index 0000000..9054c83 --- /dev/null +++ b/lang/list.h @@ -0,0 +1,24 @@ +// SPDX-License-Identifier: MIT +// Copyright (c) 2023 John Watts and the LuminaSensum contributors + +#ifndef LIST_H +#define LIST_H + +#include "types.h" + +// Creates a list of objects with a specific length +// All objects are initialized to object_none +Object object_list_create(VmState state, int length); + +// Gets the length of an object list +int object_list_length(VmState state, Object list); + +// Sets an element in the object list +// The object's reference is taken from the caller +void object_list_set(VmState state, Object list, int index, Object obj); + +// Gets an element from the object list +// A new reference is created for the caller +Object object_list_get(VmState state, Object list, int index); + +#endif diff --git a/lang/module.c b/lang/module.c index c1c5db7..2ed171e 100644 --- a/lang/module.c +++ b/lang/module.c @@ -4,6 +4,7 @@ #define MODULE_INTERNAL_API #include "module.h" #include "error.h" +#include "list.h" #include "object.h" #include "string.h" #include "vm.h" diff --git a/lang/object.c b/lang/object.c index 9508bbf..2237a9b 100644 --- a/lang/object.c +++ b/lang/object.c @@ -73,63 +73,3 @@ } vm_abort_msg(state, "dispatch_call: no call found to dispatch"); } - -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; -} - -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; -} - -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])); -} - -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], -}; diff --git a/lang/object.h b/lang/object.h index 0aee1a4..1939426 100644 --- a/lang/object.h +++ b/lang/object.h @@ -39,19 +39,4 @@ // Calls a method on an object void dispatch_call(VmState state, Object obj, const char *name); -// Creates a list of objects with a specific length -// All objects are initialized to object_none -Object object_list_create(VmState state, int length); - -// Gets the length of an object list -int object_list_length(VmState state, Object list); - -// Sets an element in the object list -// The object's reference is taken from the caller -void object_list_set(VmState state, Object list, int index, Object obj); - -// Gets an element from the object list -// A new reference is created for the caller -Object object_list_get(VmState state, Object list, int index); - #endif diff --git a/lang/vm.c b/lang/vm.c index 45156ce..b015c21 100644 --- a/lang/vm.c +++ b/lang/vm.c @@ -6,6 +6,7 @@ #include "vm.h" #include "debug.h" #include "error.h" +#include "list.h" #include "object.h" #include #include