void ECodesAssembler :: readMessage(TokenInfo& token, int& verbId, IdentifierString& subject, int& paramCount) { verbId = mapVerb(token.value); if (verbId == 0) { if (token.check("dispatch")) { verbId = DISPATCH_MESSAGE_ID; } else verbId = EVAL_MESSAGE_ID; } token.read(); while (token.value[0] == '&') { subject.append(token.value); token.read(); subject.append(token.value); token.read(); if (token.value[0] == '$') { subject.append(token.value); token.read(); } } if (token.value[0] == '[') { paramCount = token.readInteger(constants); } else token.raiseErr("Invalid operand (%d)"); token.read("]", "Invalid operand (%d)"); }
void printReference(IdentifierString& command, _Module* module, size_t reference) { bool literalConstant = false; const wchar16_t* referenceName = NULL; int mask = reference & mskAnyRef; if (mask == mskInt32Ref) { referenceName = _integer; literalConstant = true; } //else if (mask == mskInt64Ref) { // referenceName = _long; // literalConstant = true; //} //else if (mask == mskLiteralRef) { // referenceName = _literal; // literalConstant = true; //} //else if (mask == mskRealRef) { // referenceName = _real; // literalConstant = true; //} else referenceName = module->resolveReference(reference & ~mskAnyRef); if (emptystr(referenceName)) { command.append(_T("unknown")); } else { command.append(referenceName); if (literalConstant) { command.append(_T("(")); command.append(module->resolveConstant(reference & ~mskAnyRef)); command.append(_T(")")); } } }
inline void appendHex32(IdentifierString& command, unsigned int hex) { unsigned int len = hex / 0x10 + 1; while (len < 8) { command.append(_T('0')); len++; } command.appendHex(hex); }
void printMessage(IdentifierString& command, _Module* module, size_t reference) { size_t signRef = 0; int verb = 0; int paramCount = 0; decodeMessage(reference, signRef, verb, paramCount); if (verb == SEND_MESSAGE_ID) { command.append(_T("resend")); } else if (verb == DISPATCH_MESSAGE_ID) { command.append(_T("dispatch")); } else if (verb == NEWOBJECT_MESSAGE_ID) { command.append(_T("new[0]")); } else { const wchar16_t* verbName = retrieveKey(_verbs.start(), verb, (const wchar16_t*)NULL); command.append(verbName); } if (signRef != 0) { const wchar16_t* subjectName = module->resolveSubject(signRef); command.append(_T('&')); command.append(subjectName); } if (paramCount > 0) { command.append('['); command.appendInt(paramCount); command.append(']'); } }
ref_t ECodesAssembler :: compileRMessageArg(TokenInfo& token, _Module* binary) { IdentifierString message; IdentifierString subject; int paramCount = 0; int verbId = 0; readMessage(token, verbId, subject, paramCount); // reserve place for param counter message.append('0'); // if it is not a verb - by default it is EVAL message if (verbId == 0) { message.append('#'); message.append(EVAL_MESSAGE_ID + 0x20); message.append('&'); message.append(verbId); } else { message.append('#'); message.append(verbId + 0x20); } message.append(subject); message[0] = message[0] + paramCount; return binary->mapReference(message) | mskMessage; }
void listClassMethods(_Module* module, ident_t className, int pageSize, bool fullInfo, bool withConstructors) { className = trim(className); // find class VMT _Memory* vmt = findClassVMT(module, className); if (vmt == NULL) { printLine("Class not found:", className); return; } // list methods MemoryReader vmtReader(vmt); // read tape record size size_t size = vmtReader.getDWord(); // read VMT info ClassHeader header; vmtReader.read((void*)&header, sizeof(ClassHeader)); int row = 0; if (fullInfo) { if (header.parentRef) { printLine("@parent ", module->resolveReference(header.parentRef)); row++; } listFlags(header.flags, row, pageSize); listFields(module, className, row, pageSize); } //if (header.classRef != 0 && withConstructors) { // listConstructorMethods(module, className, header.classRef); //} VMTEntry entry; size -= sizeof(ClassHeader); IdentifierString temp; while (size > 0) { vmtReader.read((void*)&entry, sizeof(VMTEntry)); // print the method name temp.copy(className); temp.append('.'); printMessage(temp, module, entry.message); printLine("@method ", temp); nextRow(row, pageSize); size -= sizeof(VMTEntry); } }
void printReference(IdentifierString& command, _Module* module, size_t reference) { bool literalConstant = false; bool charConstant = false; ident_t referenceName = NULL; int mask = reference & mskAnyRef; if (mask == mskInt32Ref) { referenceName = _integer; literalConstant = true; } else if (mask == mskInt64Ref) { referenceName = _long; literalConstant = true; } else if (mask == mskLiteralRef) { referenceName = _literal; literalConstant = true; } else if (mask == mskWideLiteralRef) { referenceName = _wide; literalConstant = true; } else if (mask == mskRealRef) { referenceName = _real; literalConstant = true; } else if (mask == mskCharRef) { referenceName = _char; charConstant = true; } else if (reference == 0) { referenceName = "nil"; } else if (reference == -1) { referenceName = "undefined"; } else referenceName = module->resolveReference(reference & ~mskAnyRef); if (emptystr(referenceName)) { command.append("unknown"); } else { command.append(referenceName); if (literalConstant) { command.append("("); command.append(module->resolveConstant(reference & ~mskAnyRef)); command.append(")"); } else if (charConstant) { const char* ch = module->resolveConstant(reference & ~mskAnyRef); IdentifierString num; num.appendInt(ch[0]); command.append("("); command.append(num); command.append(")"); } } }
void VMTapeParser :: writeSubject(TapeWriter& writer, ident_t message) { IdentifierString reference; reference.append('0'); reference.append('#'); reference.append(0x20); reference.append('&'); reference.append(message); writer.writeCommand(PUSHG_TAPE_MESSAGE_ID, reference); }
void runSession(_Module* module) { char buffer[MAX_LINE]; IdentifierString line; int pageSize = 30; while (true) { wprintf(_T("\n>")); // !! fgets is used instead of fgetws, because there is strange bug in fgetws implementation fgets(buffer, MAX_LINE, stdin); line.copy(buffer, strlen(buffer)); while (!emptystr(line) && line[getlength(line) - 1]=='\r' || line[getlength(line) - 1]=='\n') line[getlength(line) - 1] = 0; while (!emptystr(line) && line[getlength(line) - 1]==' ') line[getlength(line) - 1] = 0; // execute command if (line[0]=='-') { switch(line[1]) { case 'q': return; case 'h': printHelp(); break; case 'm': printMethod(module, line + 2, pageSize); break; //case 'c': // printConstructor(module, line + 2, pageSize); // break; case 's': printSymbol(module, line + 2, pageSize); break; case 'l': if (line[2]=='m') { listClassMethods(module, line + 3, pageSize); } //else if (line[2]=='r') { // listClassRoles(module, line + 3, pageSize); //} else listClasses(module, pageSize); break; case 'o': setOutputMode(line + 2); break; default: printHelp(); } } else printHelp(); } }
inline void findUninqueName(_Module* module, IdentifierString& name) { size_t pos = getlength(name); int index = 0; ref_t ref = 0; do { name[pos] = 0; name.appendHex(index++); ref = module->mapReference(name.c_str(), true); } while (ref != 0); }
ref_t ECodesAssembler::compileMessageArg(TokenInfo& token, _Module* binary) { IdentifierString subject; int paramCount = 0; int verbId = 0; readMessage(token, verbId, subject, paramCount); if (subject.Length() > 0) { return encodeMessage(binary->mapSubject(subject + 1, false), verbId, paramCount); } else return encodeMessage(0, verbId, paramCount); }
bool VMTapeParser :: writeExtension(TapeWriter& writer, ident_t message, int command) { IdentifierString reference; size_t dotPos = message.find('.'); if (parseMessage(message + dotPos + 1, reference)) { reference.insert(message, 0, dotPos + 1); writer.writeCommand(command, reference); return true; } else return false; }
bool VMTapeParser :: parseMessage(ident_t message, IdentifierString& reference) { int paramCounter = 0; size_t length = getlength(message); length = message.find('['); if (length != NOTFOUND_POS) { reference.copy(message + length + 1); if (reference[reference.Length() - 1] == ']') { reference.truncate(reference.Length() - 1); //if (emptystr(reference)) { // paramCounter = OPEN_ARG_COUNT; //} /*else */paramCounter = reference.ident().toInt(); } else return false; } else return false; reference.clear(); reference.append('0' + (char)paramCounter); reference.append(message, length); return true; }
void ECodesAssembler :: compileMessage(TokenInfo& token, IdentifierString& message) { IdentifierString subject; int paramCount = 0; int verbId = 0; readMessage(token, verbId, subject, paramCount); // reserve place for param counter message.append('0'); // if it is not a verb - by default it is EVAL message if (verbId == 0) { message.append('#'); message.append(EVAL_MESSAGE_ID + 0x20); message.append('&'); message.append(verbId); } else { message.append('#'); message.append(verbId + 0x20); } message.append(subject); message[0] = message[0] + paramCount; }
void listClassMethods(_Module* module, const wchar_t* className, int pageSize) { className = trim(className); // find class VMT ReferenceNs reference(module->Name(), className); _Memory* vmt = findClassVMT(module, reference); if (vmt == NULL) { wprintf(_T("Class %s not found\n"), (const wchar_t*)reference); return; } // list methods MemoryReader vmtReader(vmt); // read tape record size size_t size = vmtReader.getDWord(); // read VMT header ClassHeader header; vmtReader.read((void*)&header, sizeof(ClassHeader)); int vmtSize = vmtReader.getDWord(); VMTEntry entry; size -= sizeof(ClassHeader) + 4; IdentifierString temp; int row = 0; while (size > 0) { vmtReader.read((void*)&entry, sizeof(VMTEntry)); // print the method name temp.copy(className); temp.append('.'); printMessage(temp, module, entry.message); printLine(_T("@method "), temp); row++; if (row == pageSize) { wprintf(_T("Press any key to continue...")); fgetchar(); wprintf(_T("\n")); row = 0; } size -= sizeof(VMTEntry); } }
void printLabel(IdentifierString& command, int labelPosition, List<int>& labels) { int index = getLabelIndex(labelPosition, labels); if (index == -1) { index = labels.Count(); labels.add(labelPosition); } command.append("Lab"); if (index < 10) { command.append('0'); } command.appendInt(index); }
void ECodesAssembler :: compileMCommand(ByteCode code, TokenInfo& token, MemoryWriter& writer, _Module* binary) { ident_t word = token.read(); if (token.terminal.state == dfaInteger || constants.exist(word)) { int m = 0; if(token.getInteger(m, constants)) { writeCommand(ByteCommand(code, m), writer); } else token.raiseErr("Invalid number (%d)\n"); } else if (word.compare("subject")) { token.read(":", "Invalid operand (%d)"); token.read(); int paramCount = 0; // NOTE: paramCount might be not equal to stackCount (the actual stack size) in the case if variables are used for virtual methods int stackCount = 0; int verbId = mapVerb(token.value); if (verbId == 0) { verbId = EVAL_MESSAGE_ID; } IdentifierString subject; token.read(); bool first = true; while(token.value[0] == '&') { if (first) { first = false; } else subject.append(token.value); token.read(); subject.append(token.value); token.read(); } if (token.value[0] == '[') { paramCount = token.readInteger(constants); } else token.raiseErr("Invalid operand (%d)"); token.read("]", "Invalid operand (%d)"); ref_t subj = binary->mapSubject(subject, false); writeCommand(ByteCommand(code, encodeMessage(subj, verbId, paramCount)), writer); } else throw AssemblerException("Invalid operand (%d)\n", token.terminal.row); }
inline void appendHex32(IdentifierString& command, unsigned int hex) { unsigned int n = hex / 0x10; int len = 7; while (n > 0) { n = n / 0x10; len--; } while (len > 0) { command.append('0'); len--; } command.appendHex(hex); }
void ECodesAssembler :: compileProcedure(TokenInfo& token, _Module* binary, bool inlineMode, bool aligned) { LabelInfo info; token.read(); IdentifierString method; method.copy(token.value); token.read(); if (token.check(".")) { token.read(); IdentifierString message; compileMessage(token, message); method.append('.'); method.append(message); token.read(); } ReferenceNs refName(binary->Name(), method); ref_t reference = binary->mapReference(refName) | mskCodeRef; if (binary->mapSection(reference, true)!=NULL) { throw AssemblerException("Procedure already exists (%d)\n", token.terminal.row); } _Memory* code = binary->mapSection(reference, false); MemoryWriter writer(code); writer.writeDWord(0); while (!token.check("end")) { compileCommand(token, writer, info, binary); } (*code)[0] = writer.Position() - 4; }
ref_t ModuleScope :: generateTemplate(ref_t reference, List<SNode>& parameters, ident_t ns, bool declarationMode) { SyntaxTree templateTree; TemplateGenerator transformer(templateTree); SyntaxWriter writer(templateTree); writer.newNode(lxRoot); writer.newNode(lxNamespace, ns); ref_t generatedReference = 0; if (declarationMode) { generatedReference = transformer.declareTemplate(writer, *this, reference, parameters); } else { generatedReference = transformer.generateTemplate(writer, *this, reference, parameters, true, false); writer.closeNode(); writer.closeNode(); if (generatedReference) { IdentifierString path; path.copy("compiling "); path.append(resolveFullName(generatedReference)); path.append(" template..."); //writer.insertChild(0, lxSourcePath, path.c_str()); try { compile(templateTree, path.c_str()); } catch (_Exception&) { return 0; } } } return generatedReference; }
ref_t resolveMessageByIndex(_Module* module, ident_t className, int index) { // find class VMT _Memory* vmt = findClassVMT(module, className); if (vmt == NULL) { return 0; } // list methods MemoryReader vmtReader(vmt); // read tape record size size_t size = vmtReader.getDWord(); // read VMT header ClassHeader header; vmtReader.read((void*)&header, sizeof(ClassHeader)); VMTEntry entry; size -= sizeof(ClassHeader); IdentifierString temp; int row = 0; while (size > 0) { vmtReader.read((void*)&entry, sizeof(VMTEntry)); index--; if (index == 0) { IdentifierString temp; printMessage(temp, module, entry.message); return resolveMessage(module, temp.c_str()); } size -= sizeof(VMTEntry); } return 0; }
void parseMessageConstant(IdentifierString& message, ident_t reference) { // message constant: nverb&signature int verbId = 0; int signatureId = 0; // read the param counter int count = reference[0] - '0'; // skip the param counter reference+=1; int index = reference.find('&'); //HOTFIX: for generic GET message we have to ignore ampresand if (reference[index + 1] == 0) index = -1; if (index != -1) { //HOTFIX: for GET message we have &&, so the second ampersand should be used if (reference[index + 1] == 0 || reference[index + 1] == '&') index++; IdentifierString verb(reference, index); ident_t signature = reference + index + 1; // if it is a predefined verb if (verb[0] == '#') { verbId = verb[1] - 0x20; } message.append(signature); } else { message.append(reference); } }
ref_t resolveMessage(_Module* module, const wchar16_t* method) { int paramCount = 0; int subjIndex = StringHelper::find(method, '&', -1); int paramIndex = StringHelper::find(method, '[', -1); IdentifierString verbName; IdentifierString subjectName; if (subjIndex != -1) { verbName.copy(method, subjIndex); if (paramIndex != -1) { subjectName.copy(method + subjIndex + 1, paramIndex - subjIndex - 1); } else subjectName.copy(method + subjIndex + 1); } else if (paramIndex != -1) { verbName.copy(method, paramIndex); } else verbName.copy(method); if (paramIndex != -1) { IdentifierString countStr(method + paramIndex + 1, getlength(method) - paramIndex - 2); paramCount = StringHelper::strToInt(countStr); } ref_t verb = _verbs.get(verbName); if (verb == 0) { if (StringHelper::compare(verbName, _T("resend"))) { verb = SEND_MESSAGE_ID; } else if (StringHelper::compare(verbName, _T("dispatch"))) { verb = DISPATCH_MESSAGE_ID; } else { wprintf(_T("Unknown verb %s\n"), (const wchar16_t*)verbName); return 0; } } ref_t subject = emptystr(subjectName) ? 0 : module->mapSubject(subjectName, true); if (subject == 0 && !emptystr(subjectName)) { wprintf(_T("Unknown subject %s\n"), (const wchar16_t*)subjectName); return 0; } return encodeMessage(subject, verb, paramCount); }
void printMethod(_Module* module, ident_t methodReference, int pageSize) { methodReference = trim(methodReference); int separator = methodReference.find('.'); if (separator == -1) { printf("Invalid command"); return; } IdentifierString className(methodReference, separator); ident_t methodName = methodReference + separator + 1; ref_t message = 0; // resolve method if (methodName[0] >= '0' && methodName[0] <= '9') { message = resolveMessageByIndex(module, className.ident(), methodName.toInt()); } else message = resolveMessage(module, methodName); if (message == 0) return; // find class VMT _Memory* vmt = findClassVMT(module, className); _Memory* code = findClassCode(module, className); if (vmt == NULL || code == NULL) { printLine("Class not found: ", className); return; } // find method entry MemoryReader vmtReader(vmt); // read tape record size size_t size = vmtReader.getDWord(); // read VMT header ClassHeader header; vmtReader.read((void*)&header, sizeof(ClassHeader)); VMTEntry entry; // read VMT while the entry not found size -= sizeof(ClassHeader); bool found = false; while (size > 0) { vmtReader.read((void*)&entry, sizeof(VMTEntry)); if (entry.message == message) { found = true; IdentifierString temp; temp.copy(className); temp.append('.'); printMessage(temp, module, entry.message); printLine("@method ", temp); printByteCodes(module, code, entry.address, 4, pageSize); print("@end\n"); break; } size -= sizeof(VMTEntry); } if (!found) { printLine("Method not found:", methodName); } }
bool printCommand(_Module* module, MemoryReader& codeReader, int indent, List<int>& labels) { // read bytecode + arguments int position = codeReader.Position(); unsigned char code = codeReader.getByte(); // ignore a breakpoint if required if (code == bcBreakpoint && _ignoreBreakpoints) return false; char opcode[0x30]; ByteCodeCompiler::decode((ByteCode)code, opcode); IdentifierString command; while (indent > 0) { command.append(" "); indent--; } if (code < 0x10) command.append('0'); command.appendHex((int)code); command.append(' '); int argument = 0; int argument2 = 0; if (code > MAX_DOUBLE_ECODE) { argument = codeReader.getDWord(); argument2 = codeReader.getDWord(); appendHex32(command, argument); command.append(' '); appendHex32(command, argument2); command.append(' '); } else if (code > MAX_SINGLE_ECODE) { argument = codeReader.getDWord(); appendHex32(command, argument); command.append(' '); } size_t tabbing = code == bcNop ? 24 : 31; while (getlength(command) < tabbing) { command.append(' '); } switch(code) { case bcPushF: case bcSCopyF: case bcACopyF: case bcBCopyF: command.append(opcode); command.append(" fp:"); command.appendInt(argument); break; case bcACopyS: command.append(opcode); command.append(" sp:"); command.appendInt(argument); break; case bcJump: case bcHook: case bcIf: case bcIfB: case bcElse: case bcIfHeap: case bcNotLess: // case bcAddress: command.append(opcode); command.append(' '); printLabel(command, position + argument + 5, labels); break; case bcElseM: case bcIfM: command.append(opcode); command.append(' '); printMessage(command, module, argument); command.append(' '); printLabel(command, position + argument2 + 9, labels); break; case bcElseR: case bcIfR: command.append(opcode); command.append(' '); printReference(command, module, argument); command.append(' '); printLabel(command, position + argument2 + 9, labels); break; case bcIfN: case bcElseN: case bcLessN: case bcNotLessN: case bcGreaterN: case bcNotGreaterN: command.append(opcode); command.append(' '); command.appendHex(argument); command.append(' '); printLabel(command, position + argument2 + 9, labels); break; case bcNop: printLabel(command, position + argument, labels); command.append(':'); command.append(' '); command.append(opcode); break; case bcPushR: case bcALoadR: case bcCallExtR: case bcCallR: case bcASaveR: case bcACopyR: case bcBCopyR: command.append(opcode); command.append(' '); printReference(command, module, argument); break; case bcReserve: case bcRestore: case bcPushN: case bcPopI: case bcOpen: case bcQuitN: case bcDCopy: case bcECopy: case bcAndN: case bcOrN: case bcInit: case bcNLoadI: case bcNSaveI: case bcMulN: case bcAddN: command.append(opcode); command.append(' '); command.appendHex(argument); break; case bcPushSI: case bcALoadSI: case bcASaveSI: case bcBLoadSI: case bcBSaveSI: command.append(opcode); command.append(" sp["); command.appendInt(argument); command.append(']'); break; case bcBLoadFI: case bcPushFI: case bcALoadFI: case bcASaveFI: case bcDLoadFI: command.append(opcode); command.append(" fp["); command.appendInt(argument); command.append(']'); break; case bcAJumpVI: case bcACallVI: command.append(opcode); command.append(" acc::vmt["); command.appendInt(argument); command.append(']'); break; case bcPushAI: case bcALoadAI: command.append(opcode); command.append(" acc["); command.appendInt(argument); command.append(']'); break; case bcASaveBI: case bcAXSaveBI: case bcALoadBI: command.append(opcode); command.append(" base["); command.appendInt(argument); command.append(']'); break; case bcNew: command.append(opcode); command.append(' '); printReference(command, module, argument); command.append(", "); command.appendInt(argument2); break; case bcXCallRM: case bcXJumpRM: case bcXIndexRM: case bcXMTRedirect: command.append(opcode); command.append(' '); printReference(command, module, argument); command.append(", "); printMessage(command, module, argument2); break; case bcCopyM: command.append(opcode); command.append(' '); printMessage(command, module, argument); break; case bcSetVerb: command.append(opcode); command.append(' '); printMessage(command, module, encodeAction(argument)); break; case bcSelectR: case bcXSelectR: command.append(opcode); command.append(' '); printReference(command, module, argument); command.append(", "); printReference(command, module, argument2); break; case bcNewN: command.append(opcode); command.append(' '); printReference(command, module, argument); command.append(", "); command.appendInt(argument2); break; case bcSaveFI: case bcAddFI: case bcSubFI: command.append(opcode); command.append(" fp["); command.appendInt(argument); command.append("], "); command.appendInt(argument2); break; default: command.append(opcode); break; } print(command); return true; }
void printCommand(_Module* module, MemoryReader& codeReader, int indent, List<int>& labels) { // read bytecode + arguments int position = codeReader.Position(); unsigned char code = codeReader.getByte(); wchar16_t opcode[0x30]; ByteCodeCompiler::decode((ByteCode)code, opcode); IdentifierString command; while (indent > 0) { command.append(_T(" ")); indent--; } if (code < 0x10) command.append(_T('0')); command.appendHex((int)code); command.append(_T(' ')); int argument = 0; int argument2 = 0; if (code >= 0xE0) { argument = codeReader.getDWord(); argument2 = codeReader.getDWord(); appendHex32(command, argument); command.append(_T(' ')); appendHex32(command, argument2); command.append(_T(' ')); } else if (code >= 0x20) { argument = codeReader.getDWord(); appendHex32(command, argument); command.append(_T(' ')); } int tabbing = code == bcNop ? 24 : 31; while (getlength(command) < tabbing) { command.append(_T(' ')); } switch(code) { //case bcPushFPI: case bcXPushF: case bcSCopyF: case bcAXCopyF: //case bcAccCopyFPI: command.append(opcode); command.append(_T(" fp:")); command.appendHex(argument); break; case bcACopyS: command.append(opcode); command.append(_T(" sp:")); command.appendHex(argument); break; case bcAElse: case bcAThen: //case bcMccElseAcc: //case bcMccThenAcc: case bcJump: //case bcElseLocal: command.append(opcode); command.append(_T(' ')); printLabel(command, position + argument + 5, labels); break; case bcMElse: case bcMThen: command.append(opcode); command.append(_T(' ')); printMessage(command, module, argument); command.append(_T(' ')); printLabel(command, position + argument2 + 9, labels); break; //case bcElseR: //case bcThenR: // command.append(opcode); // command.append(_T(' ')); // printReference(command, module, argument); // command.append(_T(' ')); // printLabel(command, position + argument2 + 9, labels); // break; case bcTestFlag: case bcElseFlag: ////case bcElseN: ////case bcThenN: command.append(opcode); command.append(_T(' ')); command.appendHex(argument); command.append(_T(' ')); printLabel(command, position + argument2 + 9, labels); break; //case bcMccElseAccI: //case bcMccThenAccI: // command.append(opcode); // command.append(_T(' acc[')); // command.appendHex(argument); // command.append(_T('] ')); // printLabel(command, position + argument2 + 9, labels); // break; case bcAElseR: case bcAThenR: command.append(opcode); command.append(_T(' ')); printReference(command, module, argument); command.append(_T(' ')); printLabel(command, position + argument2 + 9, labels); break; break; case bcAElseSI: case bcAThenSI: ////case bcMccElseSI: ////case bcMccThenSI: ////case bcMccVerbElseSI: ////case bcMccVerbThenSI: command.append(opcode); command.append(_T(" sp[")); command.appendInt(argument); command.append(_T("] ")); printLabel(command, position + argument2 + 9, labels); break; case bcNop: printLabel(command, position + argument, labels); command.append(_T(':')); command.append(_T(' ')); command.append(opcode); break; case bcPushR: case bcALoadR: case bcCallExtR: case bcEvalR: //case bcCallR: ////case bcSendVMTR: case bcASaveR: case bcACopyR: case bcNBox: case bcBox: ////case bcAccTryR: ////case bcAccMergeR: ////case bcJumpR: command.append(opcode); command.append(_T(' ')); printReference(command, module, argument); break; case bcReserve: case bcRestore: //case bcPushN: case bcPopI: case bcOpen: case bcQuitN: case bcDCopy: //case bcAccCreate: ////case bcAccTestFlagN: ////case bcAccCopyN: //case bcAccAddN: //case bcGetLen: ////case bcAccTryN: ////case bcSelfShiftI: ////case bcAccShiftI: ////case bcTryLock: ////case bcFreeLock: ////case bcSPTryLock: ////case bcAccFreeLock: //case bcJumpAccN: command.append(opcode); command.append(_T(' ')); command.appendHex(argument); break; ////case bcAccInc: //case bcPushI: // command.append(opcode); // command.append(_T(' ')); // command.appendHex(argument); // break; case bcPushSI: case bcALoadSI: case bcASaveSI: //case bcSwapSI: //case bcPopSI: case bcMLoadSI: //case bcAccSwapSI: command.append(opcode); command.append(_T(" sp[")); command.appendInt(argument); command.append(_T(']')); break; //case bcAccGetSI: // command.append(opcode); // command.append(_T(" acc[sp[")); // command.appendInt(argument); // command.append(_T("]]")); // break; //case bcAccGetFI: // command.append(opcode); // command.append(_T(" acc[fp[")); // command.appendInt(argument); // command.append(_T("]]")); // break; case bcPushFI: case bcALoadFI: //case bcPopFI: //case bcIncFI: case bcASaveFI: case bcMLoadFI: case bcMSaveParams: //case bcXAccSaveFI: case bcDLoadFI: case bcDSaveFI: command.append(opcode); command.append(_T(" fp[")); command.appendInt(argument); command.append(_T(']')); break; case bcACallVI: command.append(opcode); command.append(_T(" acc::vmt[")); command.appendInt(argument); command.append(_T(']')); break; case bcPushAI: ////case bcPopAccI: case bcXPopAI: ////case bcPop2AccI: //case bcAccLoadAccI: case bcMLoadAI: //case bcMccAddAccI: case bcDSaveAI: command.append(opcode); command.append(_T(" acc[")); command.appendInt(argument); command.append(_T(']')); break; //case bcPushSelfI: //case bcPopSelfI: case bcASaveBI: ////case bcAccLoadSelfI: command.append(opcode); command.append(_T(" self[")); command.appendInt(argument); command.append(_T(']')); break; ////case bcIAccCopyN: //// command.append(opcode); //// command.append(_T(" acc[")); //// command.appendInt(argument); //// command.append(_T("], ")); //// command.appendHex(argument2); //// break; //case bcIAccCopyR: // command.append(opcode); // command.append(_T(" acc[")); // command.appendInt(argument); // command.append(_T("], ")); // printReference(command, module, argument2); // break; //case bcIAccFillR: // command.append(opcode); // command.append(_T(' ')); // command.appendInt(argument); // command.append(_T(", ")); // printReference(command, module, argument2); // break; //case bcCreate: //case bcCreateN: //case bcAccCreateN: //case bcAccBoxN: // command.append(opcode); // command.append(_T(' ')); // command.appendInt(argument); // command.append(_T(", ")); // printReference(command, module, argument2); // break; case bcXCallRM: command.append(opcode); command.append(_T(' ')); printReference(command, module, argument); command.append(_T(", ")); printMessage(command, module, argument2); break; //case bcRCallN: // command.append(opcode); // command.append(_T(' ')); // printReference(command, module, argument); // command.append(_T(", ")); // command.appendInt(argument2); // break; ////case bcAccCopyM: case bcMCopy: //case bcXMccCopyM: //case bcMccAddM: command.append(opcode); command.append(_T(' ')); printMessage(command, module, argument); break; case bcSCallVI: command.append(opcode); command.append(_T(" sp[")); command.appendInt(argument); command.append(_T("]::vmt[")); command.appendInt(argument2); command.append(_T("]")); break; case bcNFunc: case bcLFunc: case bcRFunc: case bcWSFunc: case bcFunc: command.append(opcode); ByteCodeCompiler::decodeFunction((FunctionCode)argument, opcode); command.append(opcode); break; default: command.append(opcode); break; } print(command); }
ref_t resolveMessage(_Module* module, ident_t method) { int paramCount = 0; ref_t actionRef = 0; ref_t flags = 0; if (method.startsWith("params#")) { flags |= VARIADIC_MESSAGE; method = method.c_str() + getlength("params#"); } if (method.startsWith("prop#")) { flags |= PROPERTY_MESSAGE; method = method.c_str() + getlength("prop#"); } if (method.startsWith("#invoke")) { flags |= SPECIAL_MESSAGE; } if (method.startsWith("#private&")) { flags |= STATIC_MESSAGE; method = method.c_str() + getlength("#private&"); } if (method.compare("#init")) { flags |= SPECIAL_MESSAGE; } IdentifierString actionName; int paramIndex = method.find('[', -1); if (paramIndex != -1) { actionName.copy(method, paramIndex); IdentifierString countStr(method + paramIndex + 1, getlength(method) - paramIndex - 2); paramCount = countStr.ident().toInt(); } else actionName.copy(method); //if (actionName.compare("dispatch")) { // actionRef = DISPATCH_MESSAGE_ID; //} //else if (actionName.compare("#new")) { // actionRef = NEWOBJECT_MESSAGE_ID; //} ///*else */if (actionName.compare("#init")) { // actionRef = INIT_MESSAGE_ID; //} //else { // if (method.find("set&") != NOTFOUND_POS) { // actionName.cut(0, 4); // flags = PROPSET_MESSAGE; // } // else if (method.startsWith("#cast<") && paramCount > 0) { // flags = SPECIAL_MESSAGE; // } //// else if (actionName.compare("set")) { //// flags = PROPSET_MESSAGE; //// } ref_t signature = 0; size_t index = actionName.ident().find('<'); if (index != NOTFOUND_POS) { ref_t references[ARG_COUNT]; size_t end = actionName.ident().find('>'); size_t len = 0; size_t i = index + 1; while (i < end) { size_t j = actionName.ident().find(i, ',', end); IdentifierString temp(actionName.c_str() + i, j-i); references[len++] = module->mapReference(temp, true); i = j + 1; } signature = module->mapSignature(references, len, true); actionName.truncate(index); } actionRef = module->mapAction(actionName, signature, true); if (actionRef == 0) { printLine("Unknown subject ", actionName); return 0; } //} return encodeMessage(actionRef, paramCount, flags); }
void runSession(_Module* module, int pageSize) { char buffer[MAX_LINE]; IdentifierString line; while (true) { printf("\n>"); // !! fgets is used instead of fgetws, because there is strange bug in fgetws implementation fgets(buffer, MAX_LINE, stdin); line.copy(buffer, strlen(buffer)); while (!emptystr(line) && line[getlength(line) - 1]=='\r' || line[getlength(line) - 1]=='\n') line[getlength(line) - 1] = 0; while (!emptystr(line) && line[getlength(line) - 1]==' ') line[getlength(line) - 1] = 0; // execute command if (line[0]=='?') { if (line[1]==0) { listClasses(module, pageSize); } else printHelp(); } else if (line[0]=='-') { switch(line[1]) { case 'q': return; case 'h': printHelp(); break; case 'l': printAPI(module, pageSize); break; case 'b': _ignoreBreakpoints = !_ignoreBreakpoints; break; //case 'c': // printConstructor(module, line + 2, pageSize); // break; case 'o': { Path path(line + 2); setOutputMode(path.c_str()); break; } default: printHelp(); } } else if (line[0] == '#') { printSymbol(module, line + 1, pageSize); } else { if (line.ident().find('.') != NOTFOUND_POS) { printMethod(module, line, pageSize); } else listClassMethods(module, line, pageSize, true, false); } } }
int main(int argc, char* argv[]) { printf("ELENA command line syntax generator %d.%d.%d (C)2005-2018 by Alexei Rakov\n", ENGINE_MAJOR_VERSION, ENGINE_MINOR_VERSION, BUILD_NUMBER); if (argc < 2 || argc > 3) { printLine("sg <syntax_file> [-cp<codepage>]"); return 0; } try { int encoding = DEFAULT_ENCODING; if (argc==3) { ident_t arg = argv[2]; if (arg.compare("-cp", 3)) { encoding = arg.toInt(3); } else { printLine("sg <syntax_file> [-cp<codepage>]"); return 0; } } Path path(argv[1]); TextFileReader sourceFile(path.c_str(), encoding, true); if (!sourceFile.isOpened()) { printLine("file not found %s", path); } TextSourceReader source(4, &sourceFile); ParserTable table; LineInfo info(0, 0, 0); IdentifierString token; int rule[20]; int rule_len = 0; bool arrayCheck = false; table.registerSymbol(ParserTable::nsEps, "eps"); while (true) { info = source.read(token, IDENTIFIER_LEN); if (info.state == dfaEOF) break; if (token.compare("__define")) { source.read(token, IDENTIFIER_LEN); char number[10]; source.read(number, 10); registerSymbol(table, token, ident_t(number).toInt()); } else if (token.compare("->") && !arrayCheck) { if (rule_len > 2) { table.registerRule(rule[0], rule + 1, rule_len - 2); rule[0] = rule[rule_len - 1]; rule_len = 1; } arrayCheck = true; } else if (token.compare("|") && rule_len != 1) { arrayCheck = false; table.registerRule(rule[0], rule + 1, rule_len - 1); rule_len = 1; } else { arrayCheck = false; rule[rule_len++] = registerSymbol(table, token, last_id + 1); if (token.compare("|")) source.read(token, IDENTIFIER_LEN); } } table.registerRule(rule[0], rule + 1, rule_len - 1); printLine("generating...\n"); int ambigous = table.generate(); if (ambigous) { printLine("error:ambigous rule %s\n", table.retrieveSymbol(ambigous)); return -1; } printLine("saving...\n"); path.changeExtension("dat"); FileWriter file(path.c_str(), feRaw, false); table.save(&file); } catch(_ELENA_::InvalidChar& e) { printLine("(%d:%d): Invalid char %c\n", e.row, e.column, (char)e.ch); } return 0; }