if(pv.major != major) return PACKAGE_INAPPROPRIATE_MAJOR; if(pv.minor < minor) return PACKAGE_INAPPROPRIATE_MINOR; return PACKAGE_LOADED; } char* packageError(){ return dlerror(); } void readQualifiedTypeName(EmojicodeChar *name, EmojicodeChar *namespace, FILE *in){ *name = readEmojicodeChar(in); *namespace = readEmojicodeChar(in); } uint32_t readBlock(EmojicodeCoin **destination, uint8_t *variableCount, FILE *in){ *variableCount = fgetc(in); uint32_t coinCount = readEmojicodeChar(in); *destination = malloc(sizeof(EmojicodeCoin) * coinCount); for (uint32_t i = 0; i < coinCount; i++) { (*destination)[i] = readCoin(in); } return coinCount; }
Function* readBytecode(FILE *in) { uint8_t version = fgetc(in); if (version != kByteCodeVersion) { error("The bytecode file (bcsv %d) is not compatible with this interpreter (bcsv %d).\n", version, kByteCodeVersion); } DEBUG_LOG("Bytecode version %d", version); const int classCount = readUInt16(in); classTable = new Class*[classCount]; DEBUG_LOG("%d class(es) on the whole", classCount); const int functionCount = readUInt16(in); functionTable = new Function*[functionCount]; DEBUG_LOG("%d function(s) on the whole", functionCount); for (int i = 0, l = fgetc(in); i < l; i++) { DEBUG_LOG("📦 Reading package %d of %d", i + 1, l); readPackage(in); } CL_STRING = classTable[0]; CL_LIST = classTable[1]; CL_DATA = classTable[2]; CL_DICTIONARY = classTable[3]; CL_CLOSURE = classTable[4]; DEBUG_LOG("✅ Read all packages"); uint16_t tableSize = readUInt16(in); protocolDispatchTableTable = new ProtocolDispatchTable[tableSize]; protocolDTTOffset = readUInt16(in); for (uint16_t count = readUInt16(in); count > 0; count--) { DEBUG_LOG("➡️ Still %d value type protocol tables to load", count); auto index = readUInt16(in); readProtocolTable(protocolDispatchTableTable[index - protocolDTTOffset], functionTable, in); } size_t n = readInstruction(in); boxObjectVariableRecordTable = new BoxObjectVariableRecords[n]; for (size_t i = 0; i < n; i++) { boxObjectVariableRecordTable[i].count = readUInt16(in); boxObjectVariableRecordTable[i].records = new ObjectVariableRecord[boxObjectVariableRecordTable[i].count]; for (size_t j = 0; j < boxObjectVariableRecordTable[i].count; j++) { boxObjectVariableRecordTable[i].records[j].variableIndex = readUInt16(in); boxObjectVariableRecordTable[i].records[j].condition = readUInt16(in); boxObjectVariableRecordTable[i].records[j].type = static_cast<ObjectVariableType>(readUInt16(in)); } } stringPoolCount = readUInt16(in); DEBUG_LOG("Reading string pool with %d strings", stringPoolCount); stringPool = new Object*[stringPoolCount]; for (int i = 0; i < stringPoolCount; i++) { Object *o = newObject(CL_STRING); auto *string = o->val<String>(); string->length = readUInt16(in); string->charactersObject = newArray(string->length * sizeof(EmojicodeChar)); for (int j = 0; j < string->length; j++) { string->characters()[j] = readEmojicodeChar(in); } stringPool[i] = o; } DEBUG_LOG("✅ Program ready for execution"); return functionTable[0]; }
void readFunction(Function **table, FILE *in, FunctionFunctionPointer *linkingTable) { uint16_t vti = readUInt16(in); auto *function = static_cast<Function *>(malloc(sizeof(Function))); function->argumentCount = fgetc(in); DEBUG_LOG("*️⃣ Reading function with vti %d and takes %d argument(s)", vti, function->argumentCount); function->objectVariableRecordsCount = readUInt16(in); function->objectVariableRecords = new FunctionObjectVariableRecord[function->objectVariableRecordsCount]; for (unsigned int i = 0; i < function->objectVariableRecordsCount; i++) { function->objectVariableRecords[i].variableIndex = readUInt16(in); function->objectVariableRecords[i].condition = readUInt16(in); function->objectVariableRecords[i].type = static_cast<ObjectVariableType>(readUInt16(in)); function->objectVariableRecords[i].from = readInstruction(in); function->objectVariableRecords[i].to = readInstruction(in); } function->context = static_cast<ContextType>(fgetc(in)); DEBUG_LOG("Read %d object variable records", function->objectVariableRecordsCount); function->frameSize = readUInt16(in); uint16_t native = readUInt16(in); if (native != 0) { DEBUG_LOG("Function has native function"); function->handler = linkingTable[native]; } function->block.instructionCount = readEmojicodeChar(in); function->block.instructions = new EmojicodeInstruction[function->block.instructionCount]; #ifdef DEBUG int numberPrint = 0; #endif for (unsigned int i = 0; i < function->block.instructionCount; i++) { function->block.instructions[i] = readInstruction(in); #ifdef DEBUG if (numberPrint == 0) { printf("%4d: ", i); auto ins = static_cast<Instructions>(function->block.instructions[i]); pinsname(ins); printf(" "); numberPrint = inscount(ins); if (numberPrint == 0) { puts(""); } } else { printf("%d ", function->block.instructions[i]); if (--numberPrint == 0) { puts(""); } } #endif } DEBUG_LOG("Read block with %d coins and %d local variable(s)", function->block.instructionCount, function->frameSize); table[vti] = function; }
void readPackage(FILE *in) { static uint16_t classNextIndex = 0; FunctionFunctionPointer *linkingTable; PrepareClassFunction prepareClass; uint_fast8_t packageNameLength = fgetc(in); if (packageNameLength == 0) { DEBUG_LOG("Package does not have native binary"); linkingTable = sLinkingTable; prepareClass = sPrepareClass; } else { DEBUG_LOG("Package has native binary"); auto name = new char[packageNameLength]; fread(name, sizeof(char), packageNameLength, in); uint16_t major = readUInt16(in); uint16_t minor = readUInt16(in); DEBUG_LOG("Package is named %s and has version %d.%d.x", name, major, minor); PackageLoadingState s = packageLoad(name, major, minor, &linkingTable, &prepareClass); if (s == PACKAGE_INAPPROPRIATE_MAJOR) { error("Installed version of package \"%s\" is incompatible with required version %d.%d. (How did you made Emojicode load this version of the package?!)", name, major, minor); } else if (s == PACKAGE_INAPPROPRIATE_MINOR) { error("Installed version of package \"%s\" is incompatible with required version %d.%d. Please update to the latest minor version.", name, major, minor); } else if (s == PACKAGE_LOADING_FAILED) { error("Could not load package \"%s\" %s.", name, packageError()); } delete [] name; } for (int classCount = readUInt16(in); classCount > 0; classCount--) { DEBUG_LOG("➡️ Still %d class(es) to load", classCount); EmojicodeChar name = readEmojicodeChar(in); auto *klass = new Class; classTable[classNextIndex++] = klass; DEBUG_LOG("Loading class %X into %p", name, klass); klass->superclass = classTable[readUInt16(in)]; int instanceVariableCount = readUInt16(in); int methodCount = readUInt16(in); klass->methodsVtable = new Function*[methodCount]; bool inheritsInitializers = fgetc(in); int initializerCount = readUInt16(in); klass->initializersVtable = new Function*[initializerCount]; DEBUG_LOG("Inherting intializers: %s", inheritsInitializers ? "true" : "false"); DEBUG_LOG("%d instance variable(s); %d methods; %d initializer(s)", instanceVariableCount, initializerCount, methodCount); uint_fast16_t localMethodCount = readUInt16(in); uint_fast16_t localInitializerCount = readUInt16(in); DEBUG_LOG("Reading %d method(s) and %d initializer(s) that are not inherited or overriden", localMethodCount, localInitializerCount); if (klass != klass->superclass) { memcpy(klass->methodsVtable, klass->superclass->methodsVtable, methodCount * sizeof(Function*)); if (inheritsInitializers) { memcpy(klass->initializersVtable, klass->superclass->initializersVtable, initializerCount * sizeof(Function*)); } } else { klass->superclass = nullptr; } for (uint_fast16_t i = 0; i < localMethodCount; i++) { DEBUG_LOG("Reading method %d", i); readFunction(klass->methodsVtable, in, linkingTable); } for (uint_fast16_t i = 0; i < localInitializerCount; i++) { DEBUG_LOG("Reading initializer %d", i); readFunction(klass->initializersVtable, in, linkingTable); } readProtocolTable(klass->protocolTable, klass->methodsVtable, in); // Allow inheritance from class with value, e.g. list klass->valueSize = klass->superclass && klass->superclass->valueSize ? klass->superclass->valueSize : 0; prepareClass(klass, name); klass->size = alignSize(sizeof(Object) + klass->valueSize + instanceVariableCount * sizeof(Value)); klass->instanceVariableRecordsCount = readUInt16(in); klass->instanceVariableRecords = new FunctionObjectVariableRecord[klass->instanceVariableRecordsCount]; for (size_t i = 0; i < klass->instanceVariableRecordsCount; i++) { klass->instanceVariableRecords[i].variableIndex = readUInt16(in); klass->instanceVariableRecords[i].condition = readUInt16(in); klass->instanceVariableRecords[i].type = static_cast<ObjectVariableType>(readUInt16(in)); } DEBUG_LOG("Read %d object variable records", klass->instanceVariableRecordsCount); } for (int functionCount = readUInt16(in); functionCount > 0; functionCount--) { DEBUG_LOG("➡️ Still %d functions to come", functionCount); readFunction(functionTable, in, linkingTable); } }