diff --git a/src/pk_compiler.c b/src/pk_compiler.c index c14975b..f772218 100644 --- a/src/pk_compiler.c +++ b/src/pk_compiler.c @@ -1958,22 +1958,22 @@ static void compilerAddForward(Compiler* compiler, int instruction, Fn* fn, // Add a literal constant to scripts literals and return it's index. static int compilerAddConstant(Compiler* compiler, Var value) { - pkVarBuffer* literals = &compiler->script->literals; + pkVarBuffer* constants = &compiler->script->constants; - for (uint32_t i = 0; i < literals->count; i++) { - if (isValuesSame(literals->data[i], value)) { + for (uint32_t i = 0; i < constants->count; i++) { + if (isValuesSame(constants->data[i], value)) { return i; } } // Add new constant to script. - if (literals->count < MAX_CONSTANTS) { - pkVarBufferWrite(literals, compiler->parser.vm, value); + if (constants->count < MAX_CONSTANTS) { + pkVarBufferWrite(constants, compiler->parser.vm, value); } else { parseError(compiler, "A script should contain at most %d " "unique constants.", MAX_CONSTANTS); } - return (int)literals->count - 1; + return (int)constants->count - 1; } // Enters inside a block. @@ -2665,12 +2665,12 @@ static void compileRegularImport(Compiler* compiler) { // If it has a module name use it as binding variable. // Core libs names are it's module name but for local libs it's optional // to define a module name for a script. - if (lib && lib->module != NULL) { + if (lib && lib->name != NULL) { // Get the variable to bind the imported symbol, if we already have a // variable with that name override it, otherwise use a new variable. - const char* name = lib->module->data; - uint32_t length = lib->module->length; + const char* name = lib->name->data; + uint32_t length = lib->name->length; int line = compiler->parser.previous.line; var_index = compilerImportName(compiler, line, name, length); @@ -3015,14 +3015,14 @@ PkResult compile(PKVM* vm, Script* script, const char* source, // If the script running a REPL or compiled multiple times by hosting // application module attribute might already set. In that case make it // Compile error. - if (script->module != NULL) { + if (script->name != NULL) { parseError(compiler, "Module name already defined."); } else { consume(compiler, TK_NAME, "Expected a name for the module."); const char* name = compiler->parser.previous.start; uint32_t len = compiler->parser.previous.length; - script->module = newStringLength(vm, name, len); + script->name = newStringLength(vm, name, len); consumeEndStatement(compiler); } } diff --git a/src/pk_core.c b/src/pk_core.c index cccd219..1541d9f 100644 --- a/src/pk_core.c +++ b/src/pk_core.c @@ -820,13 +820,13 @@ static inline void assertModuleNameDef(PKVM* vm, Script* script, // Check if function with the same name already exists. if (scriptGetFunc(script, name, (uint32_t)strlen(name)) != -1) { __ASSERT(false, stringFormat(vm, "A function named '$' already esists " - "on module '@'", name, script->module)->data); + "on module '@'", name, script->name)->data); } // Check if a global variable with the same name already exists. if (scriptGetGlobals(script, name, (uint32_t)strlen(name)) != -1) { __ASSERT(false, stringFormat(vm, "A global variable named '$' already " - "esists on module '@'", name, script->module)->data); + "esists on module '@'", name, script->name)->data); } } diff --git a/src/pk_debug.c b/src/pk_debug.c index 09f2081..7030fec 100644 --- a/src/pk_debug.c +++ b/src/pk_debug.c @@ -107,8 +107,8 @@ void dumpFunctionCode(PKVM* vm, Function* func) { case OP_PUSH_CONSTANT: { int index = READ_SHORT(); - ASSERT_INDEX((uint32_t)index, func->owner->literals.count); - Var value = func->owner->literals.data[index]; + ASSERT_INDEX((uint32_t)index, func->owner->constants.count); + Var value = func->owner->constants.data[index]; // Prints: %5d [val]\n PRINT_INT(index); diff --git a/src/pk_value.c b/src/pk_value.c index b457064..1493f97 100644 --- a/src/pk_value.c +++ b/src/pk_value.c @@ -209,7 +209,7 @@ static void popMarkedObjectsInternal(Object* obj, PKVM* vm) { vm->bytes_allocated += sizeof(Script); markObject(vm, &scr->path->_super); - markObject(vm, &scr->module->_super); + markObject(vm, &scr->name->_super); markVarBuffer(vm, &scr->globals); vm->bytes_allocated += sizeof(Var) * scr->globals.capacity; @@ -217,8 +217,8 @@ static void popMarkedObjectsInternal(Object* obj, PKVM* vm) { // Integer buffer has no gray call. vm->bytes_allocated += sizeof(uint32_t) * scr->global_names.capacity; - markVarBuffer(vm, &scr->literals); - vm->bytes_allocated += sizeof(Var) * scr->literals.capacity; + markVarBuffer(vm, &scr->constants); + vm->bytes_allocated += sizeof(Var) * scr->constants.capacity; markFunctionBuffer(vm, &scr->functions); vm->bytes_allocated += sizeof(Function*) * scr->functions.capacity; @@ -401,16 +401,16 @@ Script* newScript(PKVM* vm, String* name, bool is_core) { ASSERT(name != NULL && name->length > 0, OOPS); script->path = name; - script->module = NULL; + script->name = NULL; script->initialized = is_core; script->body = NULL; // Core modules has its name as the module name. - if (is_core) script->module = name; + if (is_core) script->name = name; pkVarBufferInit(&script->globals); pkUintBufferInit(&script->global_names); - pkVarBufferInit(&script->literals); + pkVarBufferInit(&script->constants); pkFunctionBufferInit(&script->functions); pkClassBufferInit(&script->classes); pkStringBufferInit(&script->names); @@ -454,7 +454,7 @@ Function* newFunction(PKVM* vm, const char* name, int length, Script* owner, func->name = owner->names.data[name_index]->data; func->owner = owner; - func->arity = -2; // -1 means variadic args. + func->arity = -2; // -2 means un-initialized (TODO: make it as a macro). } func->is_native = is_native; @@ -499,6 +499,7 @@ Upvalue* newUpvalue(PKVM* vm, Var* value) { upvalue->ptr = value; upvalue->closed = VAR_NULL; upvalue->next = NULL; + return upvalue; } Fiber* newFiber(PKVM* vm, Function* fn) { @@ -550,52 +551,51 @@ Fiber* newFiber(PKVM* vm, Function* fn) { } Class* newClass(PKVM* vm, Script* scr, const char* name, uint32_t length) { - Class* type = ALLOCATE(vm, Class); - varInitObject(&type->_super, vm, OBJ_CLASS); - vmPushTempRef(vm, &type->_super); // type. + Class* cls = ALLOCATE(vm, Class); + varInitObject(&cls->_super, vm, OBJ_CLASS); - pkClassBufferWrite(&scr->classes, vm, type); - type->owner = scr; - type->name = scriptAddName(scr, vm, name, length); - pkUintBufferInit(&type->field_names); + vmPushTempRef(vm, &cls->_super); // type. - // Can't use '$' in string format, since it has a special meaning. - // TODO: escape the character. - String* ty_name = scr->names.data[type->name]; - String* dollar = newStringLength(vm, "$", 1); - vmPushTempRef(vm, &dollar->_super); // dollar - String* ctor_name = stringFormat(vm, "@(Ctor:@)", dollar, ty_name); - vmPopTempRef(vm); // dollar + pkClassBufferWrite(&scr->classes, vm, cls); + pkUintBufferInit(&cls->field_names); + cls->owner = scr; + cls->name = scriptAddName(scr, vm, name, length); + + // FIXME: + // Make it possible to escape '@' and '$' character in formated string and + // replace below '%' with excaped '\@' (SPECIAL_NAME_CHAR) character. + String* ty_name = scr->names.data[cls->name]; + String* ctor_name = stringFormat(vm, "%(Ctor:@)", ty_name); // Constructor. vmPushTempRef(vm, &ctor_name->_super); // ctor_name - type->ctor = newFunction(vm, ctor_name->data, ctor_name->length, + cls->ctor = newFunction(vm, ctor_name->data, ctor_name->length, scr, false, NULL); vmPopTempRef(vm); // ctor_name vmPopTempRef(vm); // type. - return type; + return cls; } -Instance* newInstance(PKVM* vm, Class* ty, bool initialize) { +Instance* newInstance(PKVM* vm, Class* cls, bool initialize) { Instance* inst = ALLOCATE(vm, Instance); varInitObject(&inst->_super, vm, OBJ_INST); vmPushTempRef(vm, &inst->_super); // inst. - ASSERT(ty->name < ty->owner->names.count, OOPS); - inst->ty_name = ty->owner->names.data[ty->name]->data; + ASSERT(cls->name < cls->owner->names.count, OOPS); + inst->ty_name = cls->owner->names.data[cls->name]->data; inst->is_native = false; Inst* ins = ALLOCATE(vm, Inst); inst->ins = ins; - ins->type = ty; + ins->type = cls; pkVarBufferInit(&ins->fields); - if (initialize && ty->field_names.count != 0) { - pkVarBufferFill(&ins->fields, vm, VAR_NULL, ty->field_names.count); + if (initialize && cls->field_names.count != 0) { + pkVarBufferFill(&ins->fields, vm, VAR_NULL, cls->field_names.count); } vmPopTempRef(vm); // inst. @@ -1083,7 +1083,7 @@ void freeObject(PKVM* vm, Object* self) { Script* scr = (Script*)self; pkVarBufferClear(&scr->globals, vm); pkUintBufferClear(&scr->global_names, vm); - pkVarBufferClear(&scr->literals, vm); + pkVarBufferClear(&scr->constants, vm); pkFunctionBufferClear(&scr->functions, vm); pkClassBufferClear(&scr->classes, vm); pkStringBufferClear(&scr->names, vm); @@ -1109,8 +1109,8 @@ void freeObject(PKVM* vm, Object* self) { } break; case OBJ_CLASS: { - Class* type = (Class*)self; - pkUintBufferClear(&type->field_names, vm); + Class* cls = (Class*)self; + pkUintBufferClear(&cls->field_names, vm); } break; case OBJ_INST: @@ -1271,11 +1271,11 @@ bool instGetAttrib(PKVM* vm, Instance* inst, String* attrib, Var* value) { } else { // TODO: Optimize this with binary search. - Class* ty = inst->ins->type; - for (uint32_t i = 0; i < ty->field_names.count; i++) { - ASSERT_INDEX(i, ty->field_names.count); - ASSERT_INDEX(ty->field_names.data[i], ty->owner->names.count); - String* f_name = ty->owner->names.data[ty->field_names.data[i]]; + Class* cls = inst->ins->type; + for (uint32_t i = 0; i < cls->field_names.count; i++) { + ASSERT_INDEX(i, cls->field_names.count); + ASSERT_INDEX(cls->field_names.data[i], cls->owner->names.count); + String* f_name = cls->owner->names.data[cls->field_names.data[i]]; if (IS_STR_EQ(f_name, attrib)) { *value = inst->ins->fields.data[i]; return true; @@ -1637,9 +1637,9 @@ static void _toStringInternal(PKVM* vm, const Var v, pkByteBuffer* buff, case OBJ_SCRIPT: { const Script* scr = (const Script*)obj; pkByteBufferAddString(buff, vm, "[Module:", 8); - if (scr->module != NULL) { - pkByteBufferAddString(buff, vm, scr->module->data, - scr->module->length); + if (scr->name != NULL) { + pkByteBufferAddString(buff, vm, scr->name->data, + scr->name->length); } else { pkByteBufferWrite(buff, vm, '"'); pkByteBufferAddString(buff, vm, scr->path->data, scr->path->length); @@ -1682,9 +1682,9 @@ static void _toStringInternal(PKVM* vm, const Var v, pkByteBuffer* buff, } case OBJ_CLASS: { - const Class* ty = (const Class*)obj; + const Class* cls = (const Class*)obj; pkByteBufferAddString(buff, vm, "[Class:", 7); - String* ty_name = ty->owner->names.data[ty->name]; + String* ty_name = cls->owner->names.data[cls->name]; pkByteBufferAddString(buff, vm, ty_name->data, ty_name->length); pkByteBufferWrite(buff, vm, ']'); return; @@ -1699,15 +1699,15 @@ static void _toStringInternal(PKVM* vm, const Var v, pkByteBuffer* buff, pkByteBufferWrite(buff, vm, ':'); if (!inst->is_native) { - const Class* ty = inst->ins->type; + const Class* cls = inst->ins->type; const Inst* ins = inst->ins; - ASSERT(ins->fields.count == ty->field_names.count, OOPS); + ASSERT(ins->fields.count == cls->field_names.count, OOPS); - for (uint32_t i = 0; i < ty->field_names.count; i++) { + for (uint32_t i = 0; i < cls->field_names.count; i++) { if (i != 0) pkByteBufferWrite(buff, vm, ','); pkByteBufferWrite(buff, vm, ' '); - String* f_name = ty->owner->names.data[ty->field_names.data[i]]; + String* f_name = cls->owner->names.data[cls->field_names.data[i]]; pkByteBufferAddString(buff, vm, f_name->data, f_name->length); pkByteBufferWrite(buff, vm, '='); _toStringInternal(vm, ins->fields.data[i], buff, outer, repr); diff --git a/src/pk_value.h b/src/pk_value.h index 6107d22..5e02ee1 100644 --- a/src/pk_value.h +++ b/src/pk_value.h @@ -276,20 +276,36 @@ struct Range { struct Script { Object _super; - // For core libraries the module and the path are same and points to the + // For core libraries the name and the path are same and points to the // same String objects. - String* module; //< Module name of the script. + String* name; //< Module name of the script. String* path; //< Path of the script. - pkVarBuffer globals; //< Script level global variables. - pkUintBuffer global_names; //< Name map to index in globals. + // The constant pool of the module, which contains literal values like + // numbers, strings, and functions which are considered constants to + // a moduel as well as classes. + pkVarBuffer constants; + + // All the variable names, globals name, attribute name etc, are stored in + // the [names] buffer. They can be stored in the constants but to make it + // more clear different between string literal and names they're stored in + // a different location. + pkStringBuffer names; + + // TODO: + // Consider merging names and constants. Java's class file doesn't have + // a seperation between string literals and names in it's constant pool. + + // Globals is an array of global variables of the module. All the names + // (including global variables) are stored in the names buffer of the script + // (defined bellow). The (i)th global variables names is located at index (j) + // in the names buffer where j = global_names[i]. + pkVarBuffer globals; + pkUintBuffer global_names; pkFunctionBuffer functions; //< Functions of the script. pkClassBuffer classes; //< Classes of the script. - pkStringBuffer names; //< Name literals, attribute names, etc. - pkVarBuffer literals; //< Script literal constant values. - Function* body; //< Script body is an anonymous function. // When a script has globals, it's body need to be executed to initialize the @@ -310,7 +326,12 @@ struct Function { const char* name; //< Name in the script [owner] or C literal. Script* owner; //< Owner script of the function. - int arity; //< Number of argument the function expects. + + // Number of argument the function expects. If the arity is -1 that means + // the function has a variadic number of parameters. When a function is + // constructed the value for arity is set to -2 to indicate that it hasn't + // initialized. + int arity; // Number of upvalues it uses, we're defining it here (and not in object Fn) // is prevent checking is_native everytime (which might be a bit faster). @@ -539,7 +560,7 @@ Class* newClass(PKVM* vm, Script* scr, const char* name, uint32_t length); // Allocate new instance with of the base [type]. Note that if [initialize] is // false, the field value buffer of the instance would be un initialized (ie. // the buffer count = 0). Otherwise they'll be set to VAR_NULL. -Instance* newInstance(PKVM* vm, Class* ty, bool initialize); +Instance* newInstance(PKVM* vm, Class* cls, bool initialize); // Allocate new native instance and with [data] as the native type handle and // return Instance*. The [id] is the unique id of the instance, this would be diff --git a/src/pk_vm.c b/src/pk_vm.c index 87e2ba8..d4ef1e1 100644 --- a/src/pk_vm.c +++ b/src/pk_vm.c @@ -683,8 +683,8 @@ L_vm_main_loop: OPCODE(PUSH_CONSTANT): { uint16_t index = READ_SHORT(); - ASSERT_INDEX(index, script->literals.count); - PUSH(script->literals.data[index]); + ASSERT_INDEX(index, script->constants.count); + PUSH(script->constants.data[index]); DISPATCH(); }