mirror of
https://github.com/zekexiao/pocketlang.git
synced 2025-02-05 20:26:53 +08:00
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.
This commit is contained in:
parent
4d46930d1b
commit
776ea0ab87
@ -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);
|
||||
|
@ -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.
|
||||
|
@ -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);
|
||||
|
@ -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.
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
@ -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:
|
||||
{
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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();
|
||||
|
Loading…
Reference in New Issue
Block a user