// SPDX-License-Identifier: MIT // Copyright (c) 2023 John Watts and the LuminaSensum contributors #include <stdatomic.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include "error.h" #include "symbol.h" struct object; #define ARGS_MAX 8 typedef struct { struct object *args[ARGS_MAX]; } argstack; typedef struct object *(object_call)(struct object *, int, argstack *); typedef struct { symbol symbol; object_call *call; } call_mapping; #define CALLS_MAX 32 typedef struct object { int value; atomic_int refcount; call_mapping calls[CALLS_MAX]; int calls_count; } object; object *create_object(int value); object *add_objects(object *objA, int args, argstack *stack) { abort_if(args != 1, "wrong arg count"); object *objB = stack->args[0]; abort_if(objB == NULL, "objB is null"); int new_value = objA->value + objB->value; return create_object(new_value); } object *create_object(int value) { object *obj = malloc(sizeof(object)); abort_if(!obj, "obj malloc failed"); obj->value = value; obj->refcount = 1; call_mapping *add_call = &obj->calls[0]; add_call->symbol = find_symbol("Add"); add_call->call = add_objects; obj->calls_count = 1; return obj; } void drop_object(object **objptr) { if (*objptr) { object *obj = *objptr; atomic_int count = atomic_fetch_sub_explicit( &obj->refcount, 1, memory_order_relaxed); if (count == 1) { printf("freeing %p\n", (void *)obj); free(obj); } } *objptr = NULL; } object *dispatch_call(object *obj, int sym, int args, argstack *stack) { for (int i = 0; i < obj->calls_count; ++i) { call_mapping *curr_call = &obj->calls[i]; int symbol = curr_call->symbol; if (symbol == sym) { return curr_call->call(obj, args, stack); } } abort_msg("no call found to dispatch"); } int lang_main(void) { printf("Hello world!\n"); printf("symb %i\n", find_symbol("a")); printf("symb %i\n", find_symbol("b")); object *numA = create_object(5); object *numB = create_object(3); argstack stack; stack.args[0] = numB; object *numC = dispatch_call(numA, find_symbol("Add"), 1, &stack); printf("numC value is %i\n", numC->value); printf("numA is %p\n", (void *)numA); printf("numB is %p\n", (void *)numB); printf("numC is %p\n", (void *)numC); drop_object(&numA); drop_object(&numB); drop_object(&numC); printf("numA is %p\n", (void *)numA); printf("numB is %p\n", (void *)numB); printf("numC is %p\n", (void *)numC); return 0; }