From 67ab2057c0f991d41f7f4cd14cd49d445c26a54c Mon Sep 17 00:00:00 2001 From: Thakee Nathees Date: Wed, 20 Apr 2022 16:41:57 +0530 Subject: [PATCH] method buffer added to classes and also allocation/de-allocation callbacks were added to newClass function and yet registering attribute getters and setters is to do. --- cli/main.c | 3 +-- cli/modules/std_io.c | 29 ++++++++++++++--------------- src/include/pocketlang.h | 15 +++++++++++++-- src/pk_core.c | 25 +++++++++++++++++++++---- src/pk_value.c | 29 ++++++++++++++++++++++++++--- src/pk_value.h | 10 ++++++++++ 6 files changed, 85 insertions(+), 26 deletions(-) diff --git a/cli/main.c b/cli/main.c index 3c317eb..09ff9e4 100644 --- a/cli/main.c +++ b/cli/main.c @@ -188,8 +188,7 @@ int main(int argc, const char** argv) { user_data.repl_mode = false; pkSetUserData(vm, &user_data); - registerModulePath(vm); - //REGISTER_ALL_MODULES(vm); + REGISTER_ALL_MODULES(vm); PkCompileOptions options = pkNewCompilerOptions(); options.debug = debug; diff --git a/cli/modules/std_io.c b/cli/modules/std_io.c index fadaef0..e2c6402 100644 --- a/cli/modules/std_io.c +++ b/cli/modules/std_io.c @@ -6,6 +6,10 @@ #include "modules.h" +/*****************************************************************************/ +/* FILE CLASS */ +/*****************************************************************************/ + // Str | If already exists | If does not exist | // -----+-------------------+-------------------| // 'r' | read from start | failure to open | @@ -31,26 +35,21 @@ typedef struct { bool closed; // True if the file isn't closed yet. } File; -/*****************************************************************************/ -/* FILE OBJECT OPERATORS */ -/*****************************************************************************/ - -void fileGetAttrib(PKVM* vm, File* file, const char* attrib) { - if (strcmp(attrib, "closed") == 0) { - pkReturnBool(vm, file->closed); - return; - } +void* _newFile() { + File* file = NEW_OBJ(File); + file->closed = true; + file->mode = FMODE_NONE; + file->fp = NULL; + return file; } -bool fileSetAttrib(PKVM* vm, File* file, const char* attrib) { - return false; -} - -void fileClean(PKVM* vm, File* file) { +void _deleteFile(void* ptr) { + File* file = (File*)ptr; if (!file->closed) { if (fclose(file->fp) != 0) { /* TODO: error! */ } file->closed = true; } + FREE_OBJ(file); } /*****************************************************************************/ @@ -171,7 +170,7 @@ static void _fileClose(PKVM* vm) { void registerModuleIO(PKVM* vm) { PkHandle* io = pkNewModule(vm, "io"); - PkHandle* cls_file = pkNewClass(vm, NULL, io, "File"); + PkHandle* cls_file = pkNewClass(vm, "File", NULL, io, _newFile, _deleteFile); pkClassAddMethod(vm, cls_file, "open", _fileOpen, -1); pkClassAddMethod(vm, cls_file, "read", _fileRead, 0); pkClassAddMethod(vm, cls_file, "write", _fileWrite, 1); diff --git a/src/include/pocketlang.h b/src/include/pocketlang.h index fbcd18f..10690df 100644 --- a/src/include/pocketlang.h +++ b/src/include/pocketlang.h @@ -127,6 +127,15 @@ typedef PkStringPtr (*pkResolvePathFn) (PKVM* vm, const char* from, // to indicate if it's failed to load the script. typedef PkStringPtr (*pkLoadScriptFn) (PKVM* vm, const char* path); +// A function callback to allocate and return a new instance of the registered +// class. Which will be called when the instance is constructed. The returned/ +// data is expected to be alive till the delete callback occurs. +typedef void* (*pkNewInstanceFn) (); + +// A function callback to de-allocate the aloocated native instance of the +// registered class. +typedef void (*pkDeleteInstanceFn) (void*); + /*****************************************************************************/ /* POCKETLANG TYPES */ /*****************************************************************************/ @@ -289,8 +298,10 @@ PK_PUBLIC void pkRegisterModule(PKVM* vm, PkHandle* module); // Create a new class on the [module] with the [name] and return it. // If the [base_class] is NULL by default it'll set to "Object" class. -PK_PUBLIC PkHandle* pkNewClass(PKVM* vm, PkHandle* base_class, - PkHandle* module, const char* name); +PK_PUBLIC PkHandle* pkNewClass(PKVM* vm, const char* name, + PkHandle* base_class, PkHandle* module, + pkNewInstanceFn new_fn, + pkDeleteInstanceFn delete_fn); // Add a native method to the given class. If the [arity] is -1 that means // the method has variadic parameters and use pkGetArgc() to get the argc. diff --git a/src/pk_core.c b/src/pk_core.c index f4b3307..c13fc47 100644 --- a/src/pk_core.c +++ b/src/pk_core.c @@ -69,8 +69,10 @@ void pkRegisterModule(PKVM* vm, PkHandle* module) { vmRegisterModule(vm, module_, module_->name); } -PkHandle* pkNewClass(PKVM* vm, PkHandle* base_class, PkHandle* module, - const char* name) { +PkHandle* pkNewClass(PKVM* vm, const char* name, + PkHandle* base_class, PkHandle* module, + pkNewInstanceFn new_fn, + pkDeleteInstanceFn delete_fn) { CHECK_NULL(module); CHECK_NULL(name); CHECK_TYPE(module, OBJ_MODULE); @@ -84,6 +86,9 @@ PkHandle* pkNewClass(PKVM* vm, PkHandle* base_class, PkHandle* module, Class* class_ = newClass(vm, name, (int)strlen(name), super, (Module*)AS_OBJ(module->value), NULL, NULL); + class_->new_fn = new_fn; + class_->delete_fn = delete_fn; + return vmNewHandle(vm, VAR_OBJ(class_)); } @@ -92,9 +97,21 @@ void pkClassAddMethod(PKVM* vm, PkHandle* cls, pkNativeFn fptr, int arity) { CHECK_NULL(cls); CHECK_NULL(fptr); - CHECK_TYPE(cls, OBJ_MODULE); + CHECK_TYPE(cls, OBJ_CLASS); - TODO; + Class* class_ = (Class*)AS_OBJ(cls->value); + + Function* fn = newFunction(vm, name, (int)strlen(name), + class_->owner, true, NULL, NULL); + + // No need to push the function to temp references of the VM + // since it's written to the constant pool of the module and the module + // won't be garbage collected (class handle has reference to the module). + + Closure* method = newClosure(vm, fn); + vmPushTempRef(vm, &method->_super); // method. + pkClosureBufferWrite(&class_->methods, vm, method); + vmPopTempRef(vm); // method. } void* pkGetSelf(const PKVM* vm) { diff --git a/src/pk_value.c b/src/pk_value.c index 21829a8..4e31f85 100644 --- a/src/pk_value.c +++ b/src/pk_value.c @@ -94,6 +94,7 @@ DEFINE_BUFFER(Uint, uint32_t) DEFINE_BUFFER(Byte, uint8_t) DEFINE_BUFFER(Var, Var) DEFINE_BUFFER(String, String*) +DEFINE_BUFFER(Closure, Closure*) void pkByteBufferAddString(pkByteBuffer* self, PKVM* vm, const char* str, uint32_t length) { @@ -146,6 +147,13 @@ void markStringBuffer(PKVM* vm, pkStringBuffer* self) { } } +void markClosureBuffer(PKVM* vm, pkClosureBuffer* self) { + if (self == NULL) return; + for (uint32_t i = 0; i < self->count; i++) { + markObject(vm, &self->data[i]->_super); + } +} + static void popMarkedObjectsInternal(Object* obj, PKVM* vm) { // TODO: trace here. @@ -271,6 +279,10 @@ static void popMarkedObjectsInternal(Object* obj, PKVM* vm) { markObject(vm, &cls->owner->_super); markObject(vm, &cls->ctor->_super); markObject(vm, &cls->name->_super); + + markClosureBuffer(vm, &cls->methods); + vm->bytes_allocated += sizeof(Closure) * cls->methods.capacity; + } break; case OBJ_INST: @@ -500,10 +512,14 @@ Class* newClass(PKVM* vm, const char* name, int length, vmPushTempRef(vm, &cls->_super); // class. + pkClosureBufferInit(&cls->methods); + cls->owner = NULL; cls->super_class = super; cls->docstring = NULL; cls->ctor = NULL; + cls->new_fn = NULL; + cls->delete_fn = NULL; // Builtin types doesn't belongs to a module. if (module != NULL) { @@ -523,7 +539,13 @@ Instance* newInstance(PKVM* vm, Class* cls) { Instance* inst = ALLOCATE(vm, Instance); varInitObject(&inst->_super, vm, OBJ_INST); inst->cls = cls; - inst->native = NULL; + if (cls->new_fn != NULL) { + vmPushTempRef(vm, &inst->_super); // inst. + inst->native = cls->new_fn(); + vmPopTempRef(vm); // inst. + } else { + inst->native = NULL; + } return inst; } @@ -1016,12 +1038,13 @@ void freeObject(PKVM* vm, Object* self) { case OBJ_CLASS: { Class* cls = (Class*)self; + pkClosureBufferClear(&cls->methods, vm); } break; case OBJ_INST: { Instance* inst = (Instance*)self; - if (inst->native) { - TODO; // Call native clean function. + if (inst->cls->delete_fn != NULL) { + inst->cls->delete_fn(inst->native); } } break; } diff --git a/src/pk_value.h b/src/pk_value.h index 520026e..8858b48 100644 --- a/src/pk_value.h +++ b/src/pk_value.h @@ -200,6 +200,7 @@ DECLARE_BUFFER(Uint, uint32_t) DECLARE_BUFFER(Byte, uint8_t) DECLARE_BUFFER(Var, Var) DECLARE_BUFFER(String, String*) +DECLARE_BUFFER(Closure, Closure*) // Add all the characters to the buffer, byte buffer can also be used as a // buffer to write string (like a string stream). Note that this will not @@ -494,6 +495,15 @@ struct Class { const char* docstring; Closure* ctor; //< The constructor function. + + // A buffer of methods of the class. + pkClosureBuffer methods; + + // Allocater and de-allocator functions for native types. + // For script/ builtin types it'll be NULL. + pkNewInstanceFn new_fn; + pkDeleteInstanceFn delete_fn; + }; typedef struct {