<commit_before>#include <stdlib.h>
#include <gc.h>
#include "st.h"
#include "value.h"
#include "vm.h"
#include "string.h"
#include "class.h"
#include "method.h"

static sl_object_t*
allocate_class()
{
    sl_class_t* klass = GC_MALLOC(sizeof(sl_class_t));
    klass->base.primitive_type = SL_T_CLASS;
    return (sl_object_t*)klass;
}

static sl_class_t*
get_class(sl_vm_t* vm, SLVAL klass)
{
    if(!sl_is_a(vm, klass, vm->lib.Class)) {
        /* @TODO error */
        abort();
    }
    return (sl_class_t*)sl_get_ptr(klass);
}

void
sl_pre_init_class(sl_vm_t* vm)
{
    sl_class_t* obj = GC_MALLOC(sizeof(sl_class_t));
    vm->lib.Class = sl_make_ptr((sl_object_t*)obj);
    obj->name = vm->lib.nil;
    obj->super = vm->lib.Object;
    obj->class_variables = st_init_table(&sl_string_hash_type);
    obj->class_methods = st_init_table(&sl_string_hash_type);
    obj->instance_methods = st_init_table(&sl_string_hash_type);
    obj->allocator = allocate_class;
    obj->base.klass = vm->lib.Class;
    obj->base.primitive_type = SL_T_CLASS;
    obj->base.instance_variables = st_init_table(&sl_string_hash_type);
}

void
sl_init_class(sl_vm_t* vm)
{
    (void)vm;
}

SLVAL
sl_define_class(sl_vm_t* vm, char* name, SLVAL super)
{
    return sl_define_class2(vm, sl_make_cstring(vm, name), super);
}

SLVAL
sl_define_class2(sl_vm_t* vm, SLVAL name, SLVAL super)
{
    SLVAL vklass = sl_allocate(vm, vm->lib.Class);
    sl_class_t* klass = (sl_class_t*)sl_get_ptr(vklass);
    /* @TODO assert super is a class */
    klass->super = super;
    /* @TODO assert name is a string */
    klass->name = name;
    klass->class_variables = st_init_table(&sl_string_hash_type);
    klass->class_methods = st_init_table(&sl_string_hash_type);
    klass->instance_methods = st_init_table(&sl_string_hash_type);
    return vklass;
}

void
sl_class_set_allocator(sl_vm_t* vm, SLVAL klass, sl_object_t*(*allocator)(void))
{
    get_class(vm, klass)->allocator = allocator;
}

void
sl_define_method(sl_vm_t* vm, SLVAL klass, char* name, int arity, SLVAL(*func)())
{
    sl_define_method2(vm, klass, sl_make_cstring(vm, name), arity, func);
}

void
sl_define_method2(sl_vm_t* vm, SLVAL klass, SLVAL name, int arity, SLVAL(*func)())
{
    SLVAL method = sl_make_c_func(vm, name, arity, func);
    st_insert(get_class(vm, klass)->instance_methods, (st_data_t)sl_get_ptr(name), (st_data_t)sl_get_ptr(method));
}

void
sl_define_class_method(sl_vm_t* vm, SLVAL klass, char* name, int arity, SLVAL(*func)())<commit_msg>classes should inherit the allocator of their superclass<commit_after>#include <stdlib.h>
#include <gc.h>
#include "st.h"
#include "value.h"
#include "vm.h"
#include "string.h"
#include "class.h"
#include "method.h"

static sl_object_t*
allocate_class()
{
    sl_class_t* klass = GC_MALLOC(sizeof(sl_class_t));
    klass->base.primitive_type = SL_T_CLASS;
    return (sl_object_t*)klass;
}

static sl_class_t*
get_class(sl_vm_t* vm, SLVAL klass)
{
    if(!sl_is_a(vm, klass, vm->lib.Class)) {
        /* @TODO error */
        abort();
    }
    return (sl_class_t*)sl_get_ptr(klass);
}

void
sl_pre_init_class(sl_vm_t* vm)
{
    sl_class_t* obj = GC_MALLOC(sizeof(sl_class_t));
    vm->lib.Class = sl_make_ptr((sl_object_t*)obj);
    obj->name = vm->lib.nil;
    obj->super = vm->lib.Object;
    obj->class_variables = st_init_table(&sl_string_hash_type);
    obj->class_methods = st_init_table(&sl_string_hash_type);
    obj->instance_methods = st_init_table(&sl_string_hash_type);
    obj->allocator = allocate_class;
    obj->base.klass = vm->lib.Class;
    obj->base.primitive_type = SL_T_CLASS;
    obj->base.instance_variables = st_init_table(&sl_string_hash_type);
}

void
sl_init_class(sl_vm_t* vm)
{
    (void)vm;
}

SLVAL
sl_define_class(sl_vm_t* vm, char* name, SLVAL super)
{
    return sl_define_class2(vm, sl_make_cstring(vm, name), super);
}

SLVAL
sl_define_class2(sl_vm_t* vm, SLVAL name, SLVAL super)
{
    SLVAL vklass = sl_allocate(vm, vm->lib.Class);
    sl_class_t* klass = (sl_class_t*)sl_get_ptr(vklass);
    /* @TODO assert super is a class */
    klass->super = super;
    /* @TODO assert name is a string */
    klass->name = name;
    klass->class_variables = st_init_table(&sl_string_hash_type);
    klass->class_methods = st_init_table(&sl_string_hash_type);
    klass->instance_methods = st_init_table(&sl_string_hash_type);
    klass->allocator = get_class(vm, super)->allocator;
    return vklass;
}

void
sl_class_set_allocator(sl_vm_t* vm, SLVAL klass, sl_object_t*(*allocator)(void))
{
    get_class(vm, klass)->allocator = allocator;
}

void
sl_define_method(sl_vm_t* vm, SLVAL klass, char* name, int arity, SLVAL(*func)())
{
    sl_define_method2(vm, klass, sl_make_cstring(vm, name), arity, func);
}

void
sl_define_method2(sl_vm_t* vm, SLVAL klass, SLVAL name, int arity, SLVAL(*func)())
{
    SLVAL method = sl_make_c_func(vm, name, arity, func);
    st_insert(get_class(vm, klass)->instance_methods, (st_data_t)sl_get_ptr(name), (st_data_t)sl_get_ptr(method));
}

void
sl_define_class_method(sl_vm_t* vm, SLVAL klass, char* name, int arity, SLVAL(*func)())
{'fraction_non_alphanumeric': 0.14100804079231222, 'fraction_numerical': 0.0015689350853108452, 'mean_word_length': 4.848623853211009, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 55, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '593627', 'n_tokens_mistral': 2034, 'n_tokens_neox': 2074, 'n_words': 359}