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.
This commit is contained in:
Thakee Nathees 2022-04-20 16:41:57 +05:30
parent 776ea0ab87
commit 67ab2057c0
6 changed files with 85 additions and 26 deletions

View File

@ -188,8 +188,7 @@ int main(int argc, const char** argv) {
user_data.repl_mode = false; user_data.repl_mode = false;
pkSetUserData(vm, &user_data); pkSetUserData(vm, &user_data);
registerModulePath(vm); REGISTER_ALL_MODULES(vm);
//REGISTER_ALL_MODULES(vm);
PkCompileOptions options = pkNewCompilerOptions(); PkCompileOptions options = pkNewCompilerOptions();
options.debug = debug; options.debug = debug;

View File

@ -6,6 +6,10 @@
#include "modules.h" #include "modules.h"
/*****************************************************************************/
/* FILE CLASS */
/*****************************************************************************/
// Str | If already exists | If does not exist | // Str | If already exists | If does not exist |
// -----+-------------------+-------------------| // -----+-------------------+-------------------|
// 'r' | read from start | failure to open | // 'r' | read from start | failure to open |
@ -31,26 +35,21 @@ typedef struct {
bool closed; // True if the file isn't closed yet. bool closed; // True if the file isn't closed yet.
} File; } File;
/*****************************************************************************/ void* _newFile() {
/* FILE OBJECT OPERATORS */ File* file = NEW_OBJ(File);
/*****************************************************************************/ file->closed = true;
file->mode = FMODE_NONE;
void fileGetAttrib(PKVM* vm, File* file, const char* attrib) { file->fp = NULL;
if (strcmp(attrib, "closed") == 0) { return file;
pkReturnBool(vm, file->closed);
return;
}
} }
bool fileSetAttrib(PKVM* vm, File* file, const char* attrib) { void _deleteFile(void* ptr) {
return false; File* file = (File*)ptr;
}
void fileClean(PKVM* vm, File* file) {
if (!file->closed) { if (!file->closed) {
if (fclose(file->fp) != 0) { /* TODO: error! */ } if (fclose(file->fp) != 0) { /* TODO: error! */ }
file->closed = true; file->closed = true;
} }
FREE_OBJ(file);
} }
/*****************************************************************************/ /*****************************************************************************/
@ -171,7 +170,7 @@ static void _fileClose(PKVM* vm) {
void registerModuleIO(PKVM* vm) { void registerModuleIO(PKVM* vm) {
PkHandle* io = pkNewModule(vm, "io"); 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, "open", _fileOpen, -1);
pkClassAddMethod(vm, cls_file, "read", _fileRead, 0); pkClassAddMethod(vm, cls_file, "read", _fileRead, 0);
pkClassAddMethod(vm, cls_file, "write", _fileWrite, 1); pkClassAddMethod(vm, cls_file, "write", _fileWrite, 1);

View File

@ -127,6 +127,15 @@ typedef PkStringPtr (*pkResolvePathFn) (PKVM* vm, const char* from,
// to indicate if it's failed to load the script. // to indicate if it's failed to load the script.
typedef PkStringPtr (*pkLoadScriptFn) (PKVM* vm, const char* path); 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 */ /* 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. // 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. // If the [base_class] is NULL by default it'll set to "Object" class.
PK_PUBLIC PkHandle* pkNewClass(PKVM* vm, PkHandle* base_class, PK_PUBLIC PkHandle* pkNewClass(PKVM* vm, const char* name,
PkHandle* module, 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 // 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. // the method has variadic parameters and use pkGetArgc() to get the argc.

View File

@ -69,8 +69,10 @@ void pkRegisterModule(PKVM* vm, PkHandle* module) {
vmRegisterModule(vm, module_, module_->name); vmRegisterModule(vm, module_, module_->name);
} }
PkHandle* pkNewClass(PKVM* vm, PkHandle* base_class, PkHandle* module, PkHandle* pkNewClass(PKVM* vm, const char* name,
const char* name) { PkHandle* base_class, PkHandle* module,
pkNewInstanceFn new_fn,
pkDeleteInstanceFn delete_fn) {
CHECK_NULL(module); CHECK_NULL(module);
CHECK_NULL(name); CHECK_NULL(name);
CHECK_TYPE(module, OBJ_MODULE); 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), Class* class_ = newClass(vm, name, (int)strlen(name),
super, (Module*)AS_OBJ(module->value), super, (Module*)AS_OBJ(module->value),
NULL, NULL); NULL, NULL);
class_->new_fn = new_fn;
class_->delete_fn = delete_fn;
return vmNewHandle(vm, VAR_OBJ(class_)); return vmNewHandle(vm, VAR_OBJ(class_));
} }
@ -92,9 +97,21 @@ void pkClassAddMethod(PKVM* vm, PkHandle* cls,
pkNativeFn fptr, int arity) { pkNativeFn fptr, int arity) {
CHECK_NULL(cls); CHECK_NULL(cls);
CHECK_NULL(fptr); 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) { void* pkGetSelf(const PKVM* vm) {

View File

@ -94,6 +94,7 @@ DEFINE_BUFFER(Uint, uint32_t)
DEFINE_BUFFER(Byte, uint8_t) DEFINE_BUFFER(Byte, uint8_t)
DEFINE_BUFFER(Var, Var) DEFINE_BUFFER(Var, Var)
DEFINE_BUFFER(String, String*) DEFINE_BUFFER(String, String*)
DEFINE_BUFFER(Closure, Closure*)
void pkByteBufferAddString(pkByteBuffer* self, PKVM* vm, const char* str, void pkByteBufferAddString(pkByteBuffer* self, PKVM* vm, const char* str,
uint32_t length) { 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) { static void popMarkedObjectsInternal(Object* obj, PKVM* vm) {
// TODO: trace here. // TODO: trace here.
@ -271,6 +279,10 @@ static void popMarkedObjectsInternal(Object* obj, PKVM* vm) {
markObject(vm, &cls->owner->_super); markObject(vm, &cls->owner->_super);
markObject(vm, &cls->ctor->_super); markObject(vm, &cls->ctor->_super);
markObject(vm, &cls->name->_super); markObject(vm, &cls->name->_super);
markClosureBuffer(vm, &cls->methods);
vm->bytes_allocated += sizeof(Closure) * cls->methods.capacity;
} break; } break;
case OBJ_INST: case OBJ_INST:
@ -500,10 +512,14 @@ Class* newClass(PKVM* vm, const char* name, int length,
vmPushTempRef(vm, &cls->_super); // class. vmPushTempRef(vm, &cls->_super); // class.
pkClosureBufferInit(&cls->methods);
cls->owner = NULL; cls->owner = NULL;
cls->super_class = super; cls->super_class = super;
cls->docstring = NULL; cls->docstring = NULL;
cls->ctor = NULL; cls->ctor = NULL;
cls->new_fn = NULL;
cls->delete_fn = NULL;
// Builtin types doesn't belongs to a module. // Builtin types doesn't belongs to a module.
if (module != NULL) { if (module != NULL) {
@ -523,7 +539,13 @@ Instance* newInstance(PKVM* vm, Class* cls) {
Instance* inst = ALLOCATE(vm, Instance); Instance* inst = ALLOCATE(vm, Instance);
varInitObject(&inst->_super, vm, OBJ_INST); varInitObject(&inst->_super, vm, OBJ_INST);
inst->cls = cls; 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; return inst;
} }
@ -1016,12 +1038,13 @@ void freeObject(PKVM* vm, Object* self) {
case OBJ_CLASS: { case OBJ_CLASS: {
Class* cls = (Class*)self; Class* cls = (Class*)self;
pkClosureBufferClear(&cls->methods, vm);
} break; } break;
case OBJ_INST: { case OBJ_INST: {
Instance* inst = (Instance*)self; Instance* inst = (Instance*)self;
if (inst->native) { if (inst->cls->delete_fn != NULL) {
TODO; // Call native clean function. inst->cls->delete_fn(inst->native);
} }
} break; } break;
} }

View File

@ -200,6 +200,7 @@ DECLARE_BUFFER(Uint, uint32_t)
DECLARE_BUFFER(Byte, uint8_t) DECLARE_BUFFER(Byte, uint8_t)
DECLARE_BUFFER(Var, Var) DECLARE_BUFFER(Var, Var)
DECLARE_BUFFER(String, String*) DECLARE_BUFFER(String, String*)
DECLARE_BUFFER(Closure, Closure*)
// Add all the characters to the buffer, byte buffer can also be used as a // 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 // buffer to write string (like a string stream). Note that this will not
@ -494,6 +495,15 @@ struct Class {
const char* docstring; const char* docstring;
Closure* ctor; //< The constructor function. 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 { typedef struct {