mirror of
https://github.com/zekexiao/pocketlang.git
synced 2025-02-06 04:37:47 +08:00
literals renamed to constants
Since the functions and classes will be moved to the constants buffer rather than having their own (function buffer and class buffer) the rename is essential, and to make the refactoring process easier all the intermediate steps are done with its own pr.
This commit is contained in:
parent
a69718b020
commit
05a516d47d
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user