// SPDX-License-Identifier: MIT // Copyright (c) 2023 John Watts and the LuminaSensum contributors #include "error.h" #include "object.h" #include <stdlib.h> static struct object_class num_class; struct number { struct object obj; int value; }; Object number_create(int value) { struct number *num = malloc(sizeof(struct number)); abort_if(!num, "unable to allocate number"); num->obj.class_data = &num_class; num->obj.ref_count = 1; num->value = value; return (Object)num; } static void number_cleanup(Object obj) { abort_if(obj->class_data != &num_class, "number_cleanup obj is not a number"); struct number *num = (struct number *)obj; free(num); } int number_value(Object obj) { abort_if(obj->class_data != &num_class, "number_value obj is not a number"); struct number *num = (struct number *)obj; return num->value; } static void number_add(VmState state, Object obj) { int arg_count = vm_stack_depth(state); abort_if(arg_count != 2, "number_add called without 2 arguments"); Object arg1 = vm_stack_get(state, 1); abort_if(!arg1, "number_add arg is NULL"); abort_if(arg1->class_data != &num_class, "number_add arg is not a number"); struct number *numA = (struct number *)obj; struct number *numB = (struct number *)arg1; int added = numA->value + numB->value; vm_stack_set(state, 0, number_create(added)); vm_stack_drop(state, 1); object_drop(&arg1); numB = NULL; } static void number_minus(VmState state, Object obj) { int arg_count = vm_stack_depth(state); abort_if(arg_count != 2, "number_minus called without 2 arguments"); Object arg1 = vm_stack_get(state, 1); abort_if(!arg1, "number_minus arg is NULL"); abort_if(arg1->class_data != &num_class, "number_minus arg is not a number"); struct number *numA = (struct number *)obj; struct number *numB = (struct number *)arg1; int subbed = numA->value - numB->value; vm_stack_set(state, 0, number_create(subbed)); vm_stack_drop(state, 1); object_drop(&arg1); numB = NULL; } static struct object_call calls[] = {{.name = "Add", .handler = number_add}, {.name = "Minus", .handler = number_minus}, {.name = NULL, /* end */}}; static struct object_class num_class = { .cleanup = number_cleanup, .calls = &calls[0], };