Newer
Older
Tardis / lang / main.c
// 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;
}