Newer
Older
Tardis / lang / main.c
// 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 struct {
	char name[SYMBOL_LEN];
} symbol;

symbol symbols[SYMBOLS_MAX] = {0};
mtx_t symbols_lock;

int find_symbol(char *name) {
	mtx_lock(&symbols_lock);
	for(int i = 0; i < SYMBOLS_MAX; ++i) {
		symbol *curr_sym = &symbols[i];
		char *curr_name = curr_sym->name;
		if(curr_name[0] == 0) {
			strncpy(curr_name, name, SYMBOL_LEN);
			mtx_unlock(&symbols_lock);
			return i;
		} else {
			int cmp = strncmp(curr_name, name, SYMBOL_LEN);
			if(cmp == 0) {
				mtx_unlock(&symbols_lock);
				return i;
			}
		}
	}
	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 {
	int 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;
}