From 776ea0ab87ca6caf5239e3ba4c5c78bfda536307 Mon Sep 17 00:00:00 2001 From: Thakee Nathees Date: Wed, 20 Apr 2022 15:35:33 +0530 Subject: [PATCH] builtin types added. This commit adds the builtin types to the VM's builtin classes buffer (however no methods were added to those classes) and a super class parameter introduced while creating a new class. --- cli/modules/std_io.c | 2 +- src/include/pocketlang.h | 4 +++- src/pk_compiler.c | 39 +++++++++++++++++++++++++++++++++++---- src/pk_core.c | 22 +++++++++++++++++++--- src/pk_debug.c | 13 +++++++++++++ src/pk_opcodes.h | 4 ++++ src/pk_value.c | 5 +++-- src/pk_value.h | 7 +++++-- src/pk_vm.c | 9 +++++++++ 9 files changed, 92 insertions(+), 13 deletions(-) diff --git a/cli/modules/std_io.c b/cli/modules/std_io.c index aa944a9..fadaef0 100644 --- a/cli/modules/std_io.c +++ b/cli/modules/std_io.c @@ -171,7 +171,7 @@ static void _fileClose(PKVM* vm) { void registerModuleIO(PKVM* vm) { PkHandle* io = pkNewModule(vm, "io"); - PkHandle* cls_file = pkNewClass(vm, io, "File"); + PkHandle* cls_file = pkNewClass(vm, NULL, io, "File"); 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 58b9f46..fbcd18f 100644 --- a/src/include/pocketlang.h +++ b/src/include/pocketlang.h @@ -288,7 +288,9 @@ PK_PUBLIC PkHandle* pkNewModule(PKVM* vm, const char* name); PK_PUBLIC void pkRegisterModule(PKVM* vm, PkHandle* module); // Create a new class on the [module] with the [name] and return it. -PK_PUBLIC PkHandle* pkNewClass(PKVM* vm, PkHandle* module, const char* name); +// 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); // 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_compiler.c b/src/pk_compiler.c index d4c9835..139af8a 100644 --- a/src/pk_compiler.c +++ b/src/pk_compiler.c @@ -1257,6 +1257,19 @@ static int findBuiltinFunction(const PKVM* vm, return -1; } +// Find the builtin classes name and returns it's index in the VM's builtin +// classes array, if not found returns -1. +static int findBuiltinClass(const PKVM* vm, + const char* name, uint32_t length) { + for (int i = 0; i < PK_INSTANCE; i++) { + uint32_t bfn_length = vm->builtin_classes[i]->name->length; + if (IS_CSTR_EQ(vm->builtin_classes[i]->name, name, length)) { + return i; + } + } + return -1; +} + // Find the local with the [name] in the given function [func] and return // it's index, if not found returns -1. static int findLocal(Func* func, const char* name, uint32_t length) { @@ -1337,7 +1350,8 @@ typedef enum { NAME_LOCAL_VAR, //< Including parameter. NAME_UPVALUE, //< Local to an enclosing function. NAME_GLOBAL_VAR, - NAME_BUILTIN_FN, //< Native builtin function. + NAME_BUILTIN_FN, //< Native builtin function. + NAME_BUILTIN_TY, //< Builtin primitive type classes. } NameDefnType; // Identifier search result. @@ -1394,6 +1408,13 @@ static NameSearchResult compilerSearchName(Compiler* compiler, return result; } + index = findBuiltinClass(compiler->parser.vm, name, length); + if (index != -1) { + result.type = NAME_BUILTIN_TY; + result.index = index; + return result; + } + return result; } @@ -1573,6 +1594,11 @@ static void emitPushName(Compiler* compiler, NameDefnType type, int index) { emitOpcode(compiler, OP_PUSH_BUILTIN_FN); emitByte(compiler, index); return; + + case NAME_BUILTIN_TY: + emitOpcode(compiler, OP_PUSH_BUILTIN_TY); + emitByte(compiler, index); + return; } } @@ -1584,6 +1610,7 @@ static void emitStoreName(Compiler* compiler, NameDefnType type, int index) { switch (type) { case NAME_NOT_DEFINED: case NAME_BUILTIN_FN: + case NAME_BUILTIN_TY: UNREACHABLE(); case NAME_LOCAL_VAR: @@ -1701,7 +1728,9 @@ static void exprName(Compiler* compiler) { // like python does) and it's recommented to define all the globals // before entering a local scope. - if (result.type == NAME_NOT_DEFINED || result.type == NAME_BUILTIN_FN) { + if (result.type == NAME_NOT_DEFINED || + result.type == NAME_BUILTIN_FN || + result.type == NAME_BUILTIN_TY ) { name_type = (compiler->scope_depth == DEPTH_GLOBAL) ? NAME_GLOBAL_VAR : NAME_LOCAL_VAR; @@ -2283,8 +2312,10 @@ static void compileClass(Compiler* compiler) { // Create a new class. int cls_index; - Class* cls = newClass(compiler->parser.vm, name, name_len, - compiler->module, NULL, &cls_index); + PKVM* _vm = compiler->parser.vm; + Class* cls = newClass(_vm, name, name_len, + _vm->builtin_classes[PK_OBJECT], compiler->module, + NULL, &cls_index); // Check count exceeded. checkMaxConstantsReached(compiler, cls_index); diff --git a/src/pk_core.c b/src/pk_core.c index 5d9ee61..f4b3307 100644 --- a/src/pk_core.c +++ b/src/pk_core.c @@ -69,13 +69,21 @@ void pkRegisterModule(PKVM* vm, PkHandle* module) { vmRegisterModule(vm, module_, module_->name); } -PkHandle* pkNewClass(PKVM* vm, PkHandle* module, const char* name) { +PkHandle* pkNewClass(PKVM* vm, PkHandle* base_class, PkHandle* module, + const char* name) { CHECK_NULL(module); CHECK_NULL(name); CHECK_TYPE(module, OBJ_MODULE); + Class* super = vm->builtin_classes[PK_OBJECT]; + if (base_class != NULL) { + CHECK_TYPE(base_class, OBJ_CLASS); + super = (Class*)AS_OBJ(base_class->value); + } + Class* class_ = newClass(vm, name, (int)strlen(name), - (Module*)AS_OBJ(module->value), NULL, NULL); + super, (Module*)AS_OBJ(module->value), + NULL, NULL); return vmNewHandle(vm, VAR_OBJ(class_)); } @@ -1222,7 +1230,15 @@ static void initializeCoreModules(PKVM* vm) { /*****************************************************************************/ static void initializePrimitiveClasses(PKVM* vm) { - // TODO + for (int i = 0; i < PK_INSTANCE; i++) { + Class* super = NULL; + if (i != 0) super = vm->builtin_classes[PK_OBJECT]; + const char* name = getPkVarTypeName((PkVarType)i); + vm->builtin_classes[i] = newClass(vm, name, (int)strlen(name), + super, NULL, NULL, NULL); + } + + // TODO: Add methods to those classes. } /*****************************************************************************/ diff --git a/src/pk_debug.c b/src/pk_debug.c index a86aff6..1a0f593 100644 --- a/src/pk_debug.c +++ b/src/pk_debug.c @@ -227,6 +227,19 @@ void dumpFunctionCode(PKVM* vm, Function* func) { break; } + case OP_PUSH_BUILTIN_TY: + { + int index = READ_BYTE(); + ASSERT_INDEX(index, PK_INSTANCE); + const char* name = vm->builtin_classes[index]->name->data; + // Prints: %5d [Fn:%s]\n + PRINT_INT(index); + PRINT(" [Class:"); + PRINT(name); + PRINT("]\n"); + break; + } + case OP_PUSH_UPVALUE: case OP_STORE_UPVALUE: { diff --git a/src/pk_opcodes.h b/src/pk_opcodes.h index 1a7a561..f329f96 100644 --- a/src/pk_opcodes.h +++ b/src/pk_opcodes.h @@ -92,6 +92,10 @@ OPCODE(STORE_GLOBAL, 1, 0) // params: 1 bytes index. OPCODE(PUSH_BUILTIN_FN, 1, 1) +// Push a built in class. +// params: 1 bytes index. +OPCODE(PUSH_BUILTIN_TY, 1, 1) + // Push an upvalue of the current closure at the index which is the first one // byte argument. // params: 1 byte index. diff --git a/src/pk_value.c b/src/pk_value.c index 07bcfad..21829a8 100644 --- a/src/pk_value.c +++ b/src/pk_value.c @@ -492,8 +492,8 @@ Fiber* newFiber(PKVM* vm, Closure* closure) { } Class* newClass(PKVM* vm, const char* name, int length, - Module* module, const char* docstring, - int* cls_index) { + Class* super, Module* module, + const char* docstring, int* cls_index) { Class* cls = ALLOCATE(vm, Class); varInitObject(&cls->_super, vm, OBJ_CLASS); @@ -501,6 +501,7 @@ Class* newClass(PKVM* vm, const char* name, int length, vmPushTempRef(vm, &cls->_super); // class. cls->owner = NULL; + cls->super_class = super; cls->docstring = NULL; cls->ctor = NULL; diff --git a/src/pk_value.h b/src/pk_value.h index b8e80c2..520026e 100644 --- a/src/pk_value.h +++ b/src/pk_value.h @@ -480,6 +480,9 @@ struct Fiber { struct Class { Object _super; + // The base class of this class. + Class* super_class; + // The module that owns this class. Module* owner; @@ -566,8 +569,8 @@ Function* newFunction(PKVM* vm, const char* name, int length, // the module's constant pool. The class will be added to the modules global // as well. Class* newClass(PKVM* vm, const char* name, int length, - Module* module, const char* docstring, - int* cls_index); + Class* super, Module* module, + const char* docstring, int* cls_index); // Allocate new instance with of the base [type]. Instance* newInstance(PKVM* vm, Class* cls); diff --git a/src/pk_vm.c b/src/pk_vm.c index 4de2829..5c975f4 100644 --- a/src/pk_vm.c +++ b/src/pk_vm.c @@ -949,6 +949,15 @@ L_vm_main_loop: DISPATCH(); } + OPCODE(PUSH_BUILTIN_TY): + { + uint8_t index = READ_BYTE(); + ASSERT_INDEX(index, PK_INSTANCE); + Class* cls = vm->builtin_classes[index]; + PUSH(VAR_OBJ(cls)); + DISPATCH(); + } + OPCODE(PUSH_UPVALUE): { uint8_t index = READ_BYTE();