// 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; }; struct 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 (struct object *)num; } static void number_cleanup(struct 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(struct 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( struct object *obj, int arg_count, struct vm_state *state) { abort_if(arg_count != 2, "number_add called without 2 arguments"); struct 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)); object_drop(&arg1); numB = NULL; } static void number_minus( struct object *obj, int arg_count, struct vm_state *state) { abort_if(arg_count != 2, "number_minus called without 2 arguments"); struct 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)); 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], };