// MIT license or something // Copyright 2023 Jookia #include <stdio.h> #include <string.h> #include <stdlib.h> #include <threads.h> #include <stdatomic.h> #define SYMBOL_LEN 32 #define SYMBOLS_MAX 32 typedef int symbol; typedef struct { char name[SYMBOL_LEN]; symbol sym; } symbol_mapping; symbol_mapping symbols[SYMBOLS_MAX] = {0}; mtx_t symbols_lock; symbol find_symbol(char *name) { mtx_lock(&symbols_lock); for(int i = 0; i < SYMBOLS_MAX; ++i) { symbol_mapping *curr_sym = &symbols[i]; char *curr_name = curr_sym->name; if(curr_name[0] == 0) { strncpy(curr_name, name, SYMBOL_LEN); curr_sym->sym = i; mtx_unlock(&symbols_lock); return curr_sym->sym; } else { int cmp = strncmp(curr_name, name, SYMBOL_LEN); if(cmp == 0) { mtx_unlock(&symbols_lock); return curr_sym->sym; } } } mtx_unlock(&symbols_lock); printf("ERROR: ran out of symbols\n"); abort(); } 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) { if(args != 1) { printf("ERROR: wrong arg countnull\n"); abort(); } object *objB = stack->args[0]; if(objB == NULL) { printf("ERROR: objA is null\n"); abort(); } int new_value = objA->value + objB->value; return create_object(new_value); } object *create_object(int value) { object *obj = malloc(sizeof(object)); if(!obj) { printf("ERROR: ran out of malloc memory\n"); abort(); } 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); } } printf("ERROR: no call found to dispatch\n"); abort(); } int main(void) { mtx_init(&symbols_lock, mtx_plain); 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; }