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 ECodesAssembler :: compileProcedure(TokenInfo& token, _Module* binary, bool inlineMode, bool aligned) { LabelInfo info; token.read(); ReferenceNs refName(binary->Name(), token.value); 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); token.read(); while (!token.check("end")) { compileCommand(token, writer, info, binary); } (*code)[0] = writer.Position() - 4; }
void CFParser :: saveScript(TokenInfo& token, _ScriptReader& reader, Rule& rule) { token.read(reader); while (!token.compare("=>") || token.state == dfaQuote) { token.writeLog(); token.read(reader); } }
void ECodesAssembler::compileRMCommand(ByteCode code, TokenInfo& token, MemoryWriter& writer, _Module* binary) { size_t reference1 = compileRArg(token, binary); token.read("%", "Invalid operand (%d)"); token.read(); size_t reference2 = compileMessageArg(token, binary); writeCommand(ByteCommand(code, reference1 & ~mskAnyRef, reference2), writer); }
ref_t ECodesAssembler :: compileRArg(TokenInfo& token, _Module* binary) { ident_t word = token.read(); if (token.terminal.state == dfaFullIdentifier) { return binary->mapReference(token.value) | mskSymbolRelRef; } else if (word.compare("0")) { return 0; } else if (word.compare("const")) { token.read(":", "Invalid operand (%d)"); token.read(); if (word.compare("%")) { token.read(); return compileRMessageArg(token, binary); } else return binary->mapReference(token.value) | mskConstantRef; } else if (word.compare("class")) { token.read(":", "Invalid operand (%d)"); token.read(); return binary->mapReference(token.value) | mskVMTRef; } else if (word.compare("intern")) { token.read(":", "Invalid operand (%d)"); token.read(); return binary->mapReference(token.value) | mskInternalRef; } else throw AssemblerException("Invalid operand (%d)\n", token.terminal.row); }
ref_t ECodesAssembler :: compileRArg(TokenInfo& token, _Module* binary) { ident_t word = token.read(); if (token.terminal.state == dfaFullIdentifier) { return binary->mapReference(token.value) | mskSymbolRelRef; } else if (StringHelper::compare(word, "0")) { return 0; } else if (StringHelper::compare(word, "const")) { token.read(":", "Invalid operand"); token.read(); if (StringHelper::compare(word, "%")) { token.read(); return compileRMessageArg(token, binary); } else return binary->mapReference(token.value) | mskConstantRef; } else if (StringHelper::compare(word, "class")) { token.read(":", "Invalid operand"); token.read(); return binary->mapReference(token.value) | mskVMTRef; } else if (StringHelper::compare(word, "api")) { token.read(":", "Invalid operand"); token.read(); ReferenceNs functionName(NATIVE_MODULE, token.value); return binary->mapReference(functionName) | mskNativeCodeRef; } else if (StringHelper::compare(word, "intern")) { token.read(":", "Invalid operand"); token.read(); return binary->mapReference(token.value) | mskInternalRef; } else throw AssemblerException("Invalid operand (%d)\n", token.terminal.row); }
void ECodesAssembler :: compileExtCommand(ByteCode code, TokenInfo& token, MemoryWriter& writer, _Module* binary) { ident_t word = token.read(); if (StringHelper::compare(word, "extern")) { token.read(":", "Invalid operand"); token.read(); if (StringHelper::compare(token.value, "'dlls'", 6)) { ReferenceNs function(DLL_NAMESPACE, token.value + 6); token.read(".", "dot expected (%d)\n"); function.append("."); function.append(token.read()); size_t reference = binary->mapReference(function) | mskImportRef; writeCommand(ByteCommand(code, reference), writer); return; } } throw AssemblerException("Invalid operand (%d)\n", token.terminal.row); }
void ECodesAssembler :: compileRCommand(ByteCode code, TokenInfo& token, MemoryWriter& writer, _Module* binary) { const wchar16_t* word = token.read(); if (token.terminal.state == dfaFullIdentifier) { size_t reference = binary->mapReference(token.value) | mskSymbolRelRef; writeCommand(ByteCommand(code, reference), writer); } else if (ConstantIdentifier::compare(word, "const")) { token.read(_T(":"), _T("Invalid operand")); token.read(); size_t reference = binary->mapReference(token.value) | mskConstantRef; writeCommand(ByteCommand(code, reference), writer); } else if (ConstantIdentifier::compare(word, "class")) { token.read(_T(":"), _T("Invalid operand")); token.read(); size_t reference = binary->mapReference(token.value) | mskVMTRef; writeCommand(ByteCommand(code, reference), writer); } else throw AssemblerException(_T("Invalid operand (%d)\n"), token.terminal.row); }
void ECodesAssembler :: compileJump(ByteCode code, TokenInfo& token, MemoryWriter& writer, LabelInfo& info) { writer.writeByte(code); int label = 0; token.read(); if (info.labels.exist(token.value)) { label = info.labels.get(token.value) - writer.Position() - 4; } else { info.fwdJumps.add(token.value, writer.Position()); } writer.writeDWord(label); }
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); }
void ECodesAssembler :: compileExtCommand(ByteCode code, TokenInfo& token, MemoryWriter& writer, _Module* binary) { ident_t word = token.read(); if (word.compare("extern")) { token.read(":", "Invalid operand (%d)"); token.read(); if (token.check("'dlls'", 6)) { ReferenceNs function(DLL_NAMESPACE, token.value + 6); token.read(".", "dot expected (%d)\n"); function.append("."); function.append(token.read()); size_t reference = binary->mapReference(function) | mskImportRef; writeCommand(ByteCommand(code, reference), writer); return; } else { ReferenceNs function(DLL_NAMESPACE, RTDLL_FORWARD); function.append("."); function.append(token.value); size_t reference = binary->mapReference(function) | mskImportRef; writeCommand(ByteCommand(code, reference), writer); return; } } else if (word.compare("api")) { token.read(":", "Invalid operand (%d)"); token.read(); ReferenceNs functionName(NATIVE_MODULE, CORE_MODULE); functionName.combine(token.value); size_t reference = binary->mapReference(functionName) | mskNativeCodeRef; writeCommand(ByteCommand(code, reference), writer); return; } throw AssemblerException("Invalid operand (%d)\n", token.terminal.row); }
void ECodesAssembler :: compileRJump(ByteCode code, TokenInfo& token, MemoryWriter& writer, LabelInfo& info, _Module* binary) { writer.writeByte(code); int label = 0; token.read(); if (info.labels.exist(token.value)) { label = info.labels.get(token.value) - writer.Position() - 8; } else { info.fwdJumps.add(token.value, writer.Position() + 4); } size_t reference = compileRArg(token, binary); writer.writeDWord(reference); writer.writeDWord(label); }
void ECodesAssembler :: compileMccJump(ByteCode code, TokenInfo& token, MemoryWriter& writer, LabelInfo& info) { writer.writeByte(code); int label = 0; token.read(); if (info.labels.exist(token.value)) { label = info.labels.get(token.value) - writer.Position() - 8; } else { info.fwdJumps.add(token.value, 4 + writer.Position()); } int message = token.readInteger(constants); writer.writeDWord(message); writer.writeDWord(label); }
void ECodesAssembler :: compileCommand(TokenInfo& token, MemoryWriter& writer, LabelInfo& info, _Module* binary) { bool recognized = true; ByteCode opcode = ByteCodeCompiler::code(token.value); if (opcode != bcNone) { switch (opcode) { case bcCallR: case bcACopyR: case bcPushR: compileRCommand(opcode, token, writer, binary); break; case bcCallExtR: compileExtCommand(opcode, token, writer, binary); break; case bcACallVI: case bcAJumpVI: case bcALoadSI: case bcBLoadSI: case bcBLoadFI: case bcACopyS: case bcACopyF: case bcBCopyS: case bcBCopyF: case bcALoadAI: case bcALoadFI: case bcPushAI: case bcOpen: case bcAddN: case bcMulN: case bcDLoadFI: case bcDLoadSI: case bcDSaveFI: case bcDSaveSI: case bcRestore: case bcReserve: case bcALoadBI: case bcASaveSI: case bcASaveFI: case bcNSaveI: case bcNLoadI: case bcESwapSI: case bcBSwapSI: case bcAXSaveBI: case bcELoadFI: case bcELoadSI: case bcESaveSI: case bcESaveFI: case bcShiftN: case bcEAddN: case bcDSwapSI: case bcAJumpI: case bcACallI: case bcNReadI: case bcNWriteI: compileICommand(opcode, token, writer); break; case bcQuitN: case bcPopI: case bcDCopy: case bcECopy: case bcSetVerb: case bcSetSubj: case bcAndN: case bcOrN: case bcPushN: compileNCommand(opcode, token, writer); break; case bcCopyM: compileMCommand(opcode, token, writer, binary); break; case bcIfB: case bcElseB: case bcIf: case bcElse: case bcLess: case bcNotLess: case bcNext: case bcJump: case bcHook: case bcAddress: compileJump(opcode, token, writer, info); break; case bcIfM: case bcElseM: compileMccJump(opcode, token, writer, info); break; case bcIfN: case bcElseN: case bcLessN: compileNJump(opcode, token, writer, info); break; case bcIfR: case bcElseR: compileRJump(opcode, token, writer, info, binary); break; case bcNewN: compileCreateCommand(opcode, token, writer, binary); break; case bcSelectR: compileRRCommand(opcode, token, writer, binary); break; case bcXIndexRM: compileRMCommand(opcode, token, writer, binary); break; default: writeCommand(ByteCommand(opcode), writer); break; } } else recognized = false; if (!recognized) { info.labels.add(token.value, writer.Position()); fixJump(token.value, writer, info); writeCommand(ByteCommand(bcNop), writer); token.read(":", "':' expected (%d)\n"); } token.read(); }
void ECodesAssembler :: compileCommand(TokenInfo& token, MemoryWriter& writer, LabelInfo& info, _Module* binary) { bool recognized = true; ByteCode opcode = ByteCodeCompiler::code(token.value); switch (opcode) { case bcNop: case bcBreakpoint: case bcPushB: case bcPop: case bcPushM: case bcMCopyVerb: case bcThrow: case bcMCopySubj: case bcPushA: case bcPopA: case bcACopyB: case bcBCopyA: case bcPopM: case bcBSRedirect: case bcBSGRedirect: case bcClose: case bcPopB: case bcMQuit: case bcGet: case bcSet: case bcALoadD: case bcDDec: case bcGetLen: case bcDInc: writeCommand(ByteCommand(opcode), writer); break; case bcCallR: case bcACopyR: compileRCommand(opcode, token, writer, binary); break; case bcACopyF: case bcACallVI: case bcALoadSI: case bcASaveSI: case bcPushFI: case bcALoadAI: case bcMLoadAI: case bcMLoadSI: case bcMLoadFI: case bcMAddAI: case bcPushAI: case bcMSaveParams: case bcPushSI: case bcACopyS: case bcDAddAI: case bcDSubAI: case bcDAddSI: case bcDSubSI: case bcDLoadAI: case bcDSaveAI: case bcDLoadSI: case bcDSaveSI: case bcDLoadFI: case bcDSaveFI: case bcPopSI: compileICommand(opcode, token, writer); break; case bcOpen: case bcMAdd: case bcAJumpVI: case bcMCopy: case bcMReset: case bcQuitN: case bcPushN: case bcPopI: case bcDCopy: compileNCommand(opcode, token, writer); break; case bcJump: case bcDElse: case bcDThen: case bcWSTest: case bcBSTest: case bcTest: compileJump(opcode, token, writer, info); break; case bcMElse: case bcMThen: case bcMElseVerb: case bcMThenVerb: compileMccJump(opcode, token, writer, info); break; case bcTestFlag: case bcAElseSI: case bcAThenSI: case bcElseFlag: case bcMElseAI: case bcMThenAI: case bcDElseN: case bcDThenN: compileNJump(opcode, token, writer, info); break; case bcSCallVI: compileNNCommand(opcode, token, writer); break; default: recognized = false; break; } // check if it is function if (!recognized) { ByteCode code = bcNone; const wchar16_t* func = token.value; if (token.value[0]=='n') { code = bcNFunc; func++; } else if (token.value[0]=='l') { code = bcLFunc; func++; } else if (token.value[0]=='r') { code = bcRFunc; func++; } else if (token.value[0]=='w' && token.value[1]=='s') { code = bcWSFunc; func+=2; } else if (token.value[0]=='b' && token.value[1]=='s') { code = bcBSFunc; func+=2; } if (code != bcNone) { FunctionCode function = ByteCodeCompiler::codeFunction(func); if (function != fnUnknown) { writeCommand(ByteCommand(code, function), writer); recognized = true; } } } if (!recognized) { info.labels.add(token.value, writer.Position()); fixJump(token.value, writer, info); writeCommand(ByteCommand(bcNop), writer); token.read(_T(":"), _T("':' expected (%d)\n")); } token.read(); }
void CFParser :: defineGrammarRule(TokenInfo& token, _ScriptReader& reader, Rule& rule) { // read: terminal [nonterminal] ; // read: nonterminal [nonterminal2] ; RuleType type = rtNormal; while (token.value[0] != ';' || token.state == dfaQuote) { if (token.state == dfaQuote) { if (rule.terminal) { rule.nonterminal = defineGrammarRule(token, reader); break; } else rule.terminal = writeBodyText(token.value); } else if (token.compare("<=")) { saveScript(token, reader, rule); } else if (token.state == dfaPrivate) { if (rule.terminal) { rule.nonterminal = defineGrammarRule(token, reader); break; } else { rule.prefixPtr = defineDSARule(token, reader); if (StringHelper::compare(token.value, LITERAL_KEYWORD)) { type = rtLiteral; } else if (StringHelper::compare(token.value, NUMERIC_KEYWORD)) { type = rtNumeric; } else if (StringHelper::compare(token.value, EPS_KEYWORD)) { type = rtEps; } else if (StringHelper::compare(token.value, EOF_KEYWORD)) { type = rtEof; } else if (StringHelper::compare(token.value, REFERENCE_KEYWORD)) { type = rtReference; } else if (StringHelper::compare(token.value, SCOPE_KEYWORD)) { type = rtScope; } else if (StringHelper::compare(token.value, IDLE_MAPPING_KEYWORD)) { type = rtNewIdleVariable; } else if (StringHelper::compare(token.value, VAR_KEYWORD)) { type = rtVariable; } else if (StringHelper::compare(token.value, MAPPING_KEYWORD)) { type = rtNewVariable; } // else if (ConstantIdentifier::compare(token.value, ANY_KEYWORD)) { // type = rtAny; // } else if (StringHelper::compare(token.value, IDENTIFIER_KEYWORD)) { type = rtIdentifier; } } } else if (token.state == dfaIdentifier) { if (rule.nonterminal == 0) { rule.prefixPtr = defineDSARule(token, reader); rule.nonterminal = mapRuleId(token.value); } else if (rule.terminal == 0) { type = rtChomski; rule.terminal = mapRuleId(token.value); } else { if (type == rtChomski) { rule.terminal = defineGrammarRule(token, reader, rule.terminal); } else rule.nonterminal = defineGrammarRule(token, reader, rule.nonterminal); break; } } token.read(reader); } rule.postfixPtr = defineDSARule(token, reader); defineApplyRule(rule, type); }