13       devices(NUM_IO_DEVICE, nullptr),
 
   14       _pesudoVarIndex(), _lineOffset(), _elapsed(), _constants() {}
 
   25     throw RuntimeError(_lineOffset, 
"Invalid offset for index register: " + std::to_string(index));
 
   28 Computer::~Computer() {
 
   29     for (
size_t i = 0; i < 
devices.size(); ++i) {
 
   64     std::string symbolName = getPesudoSymbolname();
 
   74     int32_t lastOffset = _lineOffset;
 
   76         if (_lineOffset < 0 || 
NUM_MEMORY <= _lineOffset) {
 
   77             throw RuntimeError(_lineOffset, 
"Invalid code line: " + std::to_string(_lineOffset));
 
   80         if (lastOffset == _lineOffset) {
 
   83         lastOffset = _lineOffset;
 
   90         if (_lineOffset < 0 || 
NUM_MEMORY <= _lineOffset) {
 
   91             throw RuntimeError(_lineOffset, 
"Invalid code line: " + std::to_string(_lineOffset));
 
   93         if (
memory[_lineOffset].operation() == Instructions::HLT &&
 
   94             memory[_lineOffset].field() == 2) {
 
  107         throw RuntimeError(_lineOffset, 
"Literal constant cannot be used in single execution");
 
  109     if (instruction->
parsedType == ParsedType::INSTRUCTION) {
 
  111             if (!instruction->
evaluate(_constants)) {
 
  112                 throw RuntimeError(_lineOffset, 
"Unresolved symbol found when trying to execute");
 
  116     } 
else if (instruction->
parsedType == ParsedType::PSEUDO) {
 
  123     case Instructions::ADD:
 
  124         executeADD(instruction);
 
  126     case Instructions::SUB:
 
  127         executeSUB(instruction);
 
  129     case Instructions::MUL:
 
  130         executeMUL(instruction);
 
  132     case Instructions::DIV:
 
  133         executeDIV(instruction);
 
  135     case Instructions::HLT:
 
  136         switch (instruction.
field()) {
 
  137         case 0: executeNUM(); 
break;
 
  138         case 1: executeCHAR(); 
break;
 
  141     case Instructions::SLA:
 
  142         switch (instruction.
field()) {
 
  143         case 0: executeSLA(instruction); 
break;
 
  144         case 1: executeSRA(instruction); 
break;
 
  145         case 2: executeSLAX(instruction); 
break;
 
  146         case 3: executeSRAX(instruction); 
break;
 
  147         case 4: executeSLC(instruction); 
break;
 
  148         case 5: executeSRC(instruction); 
break;
 
  151     case Instructions::MOVE:
 
  152         executeMOVE(instruction);
 
  154     case Instructions::LDA:
 
  155         executeLD(instruction, &
rA);
 
  157     case Instructions::LD1:
 
  158     case Instructions::LD2:
 
  159     case Instructions::LD3:
 
  160     case Instructions::LD4:
 
  161     case Instructions::LD5:
 
  162     case Instructions::LD6:
 
  163         executeLDi(instruction);
 
  165     case Instructions::LDX:
 
  166         executeLD(instruction, &
rX);
 
  168     case Instructions::LDAN:
 
  169         executeLDN(instruction, &
rA);
 
  171     case Instructions::LD1N:
 
  172     case Instructions::LD2N:
 
  173     case Instructions::LD3N:
 
  174     case Instructions::LD4N:
 
  175     case Instructions::LD5N:
 
  176     case Instructions::LD6N:
 
  177         executeLDiN(instruction);
 
  179     case Instructions::LDXN:
 
  180         executeLDN(instruction, &
rX);
 
  182     case Instructions::STA:
 
  183         executeST(instruction, &
rA);
 
  185     case Instructions::ST1:
 
  186     case Instructions::ST2:
 
  187     case Instructions::ST3:
 
  188     case Instructions::ST4:
 
  189     case Instructions::ST5:
 
  190     case Instructions::ST6:
 
  191         executeSTi(instruction);
 
  193     case Instructions::STX:
 
  194         executeST(instruction, &
rX);
 
  196     case Instructions::STJ:
 
  197         executeSTJ(instruction);
 
  199     case Instructions::STZ:
 
  200         executeSTZ(instruction);
 
  202     case Instructions::JBUS:
 
  203         executeJBUS(instruction);
 
  205     case Instructions::IOC:
 
  206         executeIOC(instruction);
 
  208     case Instructions::IN:
 
  209         executeIN(instruction);
 
  211     case Instructions::OUT:
 
  212         executeOUT(instruction);
 
  214     case Instructions::JRED:
 
  215         executeJRED(instruction);
 
  217     case Instructions::JMP:
 
  218         switch (instruction.
field()) {
 
  219         case 0: executeJMP(instruction); 
break;
 
  220         case 1: executeJSJ(instruction); 
break;
 
  221         case 2: executeJOV(instruction); 
break;
 
  222         case 3: executeJNOV(instruction); 
break;
 
  223         case 4: executeJL(instruction); 
break;
 
  224         case 5: executeJE(instruction); 
break;
 
  225         case 6: executeJG(instruction); 
break;
 
  226         case 7: executeJGE(instruction); 
break;
 
  227         case 8: executeJNE(instruction); 
break;
 
  228         case 9: executeJLE(instruction); 
break;
 
  231     case Instructions::JAN:
 
  232         switch (instruction.
field()) {
 
  233         case 0: executeJN(instruction, &
rA); 
break;
 
  234         case 1: executeJZ(instruction, &
rA); 
break;
 
  235         case 2: executeJP(instruction, &
rA); 
break;
 
  236         case 3: executeJNN(instruction, &
rA); 
break;
 
  237         case 4: executeJNZ(instruction, &
rA); 
break;
 
  238         case 5: executeJNP(instruction, &
rA); 
break;
 
  241     case Instructions::J1N:
 
  242     case Instructions::J2N:
 
  243     case Instructions::J3N:
 
  244     case Instructions::J4N:
 
  245     case Instructions::J5N:
 
  246     case Instructions::J6N:
 
  247         switch (instruction.
field()) {
 
  248         case 0: executeJiN(instruction); 
break;
 
  249         case 1: executeJiZ(instruction); 
break;
 
  250         case 2: executeJiP(instruction); 
break;
 
  251         case 3: executeJiNN(instruction); 
break;
 
  252         case 4: executeJiNZ(instruction); 
break;
 
  253         case 5: executeJiNP(instruction); 
break;
 
  256     case Instructions::JXN:
 
  257         switch (instruction.
field()) {
 
  258         case 0: executeJN(instruction, &
rX); 
break;
 
  259         case 1: executeJZ(instruction, &
rX); 
break;
 
  260         case 2: executeJP(instruction, &
rX); 
break;
 
  261         case 3: executeJNN(instruction, &
rX); 
break;
 
  262         case 4: executeJNZ(instruction, &
rX); 
break;
 
  263         case 5: executeJNP(instruction, &
rX); 
break;
 
  266     case Instructions::INCA:
 
  267         switch (instruction.
field()) {
 
  268         case 0: executeINC(instruction, &
rA); 
break;
 
  269         case 1: executeDEC(instruction, &
rA); 
break;
 
  270         case 2: executeENT(instruction, &
rA); 
break;
 
  271         case 3: executeENN(instruction, &
rA); 
break;
 
  274     case Instructions::INC1:
 
  275     case Instructions::INC2:
 
  276     case Instructions::INC3:
 
  277     case Instructions::INC4:
 
  278     case Instructions::INC5:
 
  279     case Instructions::INC6:
 
  280         switch (instruction.
field()) {
 
  281         case 0: executeINCi(instruction); 
break;
 
  282         case 1: executeDECi(instruction); 
break;
 
  283         case 2: executeENTi(instruction); 
break;
 
  284         case 3: executeENNi(instruction); 
break;
 
  287     case Instructions::INCX:
 
  288         switch (instruction.
field()) {
 
  289         case 0: executeINC(instruction, &
rX); 
break;
 
  290         case 1: executeDEC(instruction, &
rX); 
break;
 
  291         case 2: executeENT(instruction, &
rX); 
break;
 
  292         case 3: executeENN(instruction, &
rX); 
break;
 
  295     case Instructions::CMPA:
 
  296         executeCMP(instruction, &
rA);
 
  298     case Instructions::CMP1:
 
  299     case Instructions::CMP2:
 
  300     case Instructions::CMP3:
 
  301     case Instructions::CMP4:
 
  302     case Instructions::CMP5:
 
  303     case Instructions::CMP6:
 
  304         executeCMPi(instruction);
 
  306     case Instructions::CMPX:
 
  307         executeCMP(instruction, &
rX);
 
  312                                       instruction.
field());
 
  316     switch (instruction->
word.
operation() + Instructions::PSEUDO) {
 
  317     case Instructions::EQU:
 
  318         executeEQU(instruction);
 
  320     case Instructions::ORIG:
 
  321         executeORIG(instruction);
 
  323     case Instructions::CON:
 
  324         executeCON(instruction);
 
  330     std::vector<std::string> lines;
 
  332     std::stringstream ss(codes);
 
  333     while (std::getline(ss, item, 
'\n')) {
 
  334         lines.emplace_back(item);
 
  341     std::vector<ParsedResult> results(codes.size());
 
  342     std::unordered_map<std::string, AtomicValue> evaluated;
 
  343     std::unordered_map<std::string, Expression*> expressions;
 
  344     std::vector<std::tuple<std::string, Expression, Expression>> constants;  
 
  345     std::string lineBase = getPesudoSymbolname();
 
  347     int32_t lineOffset = 0, endIndex = -1;
 
  348     for (
size_t codeIndex = 0; codeIndex < codes.size(); ++codeIndex) {
 
  349         auto code = codes[codeIndex];
 
  350         auto& result = results[codeIndex];
 
  351         auto lineSymbol = getPesudoSymbolname();
 
  353         if (result.parsedType == ParsedType::PSEUDO) {
 
  354             int32_t operation = result.word.operation() + Instructions::PSEUDO;
 
  356             case Instructions::EQU:
 
  357                 expressions[result.rawLocation] = &result.address;
 
  359             case Instructions::ORIG:
 
  360                 if (result.rawAddress.find(
'*') == std::string::npos) {
 
  361                     if (!result.rawLocation.empty()) {
 
  362                         expressions[result.rawLocation] = &result.address;
 
  368                     expressions[result.rawLocation] = &result.location;
 
  369                     expressions[lineSymbol] = &result.location;
 
  371                 lineBase = getPesudoSymbolname();
 
  372                 expressions[lineBase] = &result.address;
 
  375             case Instructions::CON:
 
  376             case Instructions::ALF:
 
  377                 if (!result.rawLocation.empty()) {
 
  378                     lineSymbol = result.rawLocation;
 
  380                 constants.push_back(std::make_tuple(
 
  385             case Instructions::END:
 
  386                 endIndex = codeIndex;
 
  389         } 
else if (result.parsedType == ParsedType::INSTRUCTION) {
 
  390             bool usedLineSymbol = !result.rawLocation.empty() ||
 
  391                                 (!result.rawAddress.empty() && result.address.depends().count(lineSymbol)) ||
 
  392                                 (!result.rawIndex.empty() && result.index.depends().count(lineSymbol)) ||
 
  393                                 (!result.rawField.empty() && result.field.depends().count(lineSymbol));
 
  395             if (!result.rawLocation.empty()) {
 
  397                     expressions[result.rawLocation] = &result.location;
 
  399             } 
else if (usedLineSymbol) {
 
  400                 result.rawLocation = lineSymbol;
 
  402             expressions[lineSymbol] = &result.location;
 
  407     std::unordered_map<std::string, std::string> localSymbolMapping;
 
  408     for (
auto& result : results) {
 
  409         if (!result.rawLocation.empty() && 
Atomic::isLocalSymbol(result.rawLocation) && result.rawLocation[1] == 
'H') {
 
  410             auto lineSymbol = getPesudoSymbolname();
 
  411             result.rawLocation[1] = 
'B';
 
  412             localSymbolMapping[result.rawLocation] = lineSymbol;
 
  413             result.rawLocation[1] = 
'H';
 
  414             expressions[lineSymbol] = &result.location;
 
  416         result.address.replaceSymbol(localSymbolMapping);
 
  418     for (
int i = 
static_cast<int>(results.size()) - 1; i >= 0; --i) {
 
  419         auto& result = results[i];
 
  420         if (!result.rawLocation.empty() && 
Atomic::isLocalSymbol(result.rawLocation) && result.rawLocation[1] == 
'H') {
 
  421             auto lineSymbol = getPesudoSymbolname();
 
  422             result.rawLocation[1] = 
'F';
 
  423             localSymbolMapping[result.rawLocation] = lineSymbol;
 
  424             result.rawLocation[1] = 
'H';
 
  425             expressions[lineSymbol] = &result.location;
 
  427         result.address.replaceSymbol(localSymbolMapping);
 
  431         auto lineSymbol = getPesudoSymbolname();
 
  433         constants.push_back(std::make_tuple(
 
  439     for (
auto& result : results) {
 
  440         if (!result.rawAddress.empty()) {
 
  441             if (result.address.literalConstant()) {
 
  442                 auto lineSymbol = getPesudoSymbolname();
 
  443                 constants.push_back(std::make_tuple(
 
  449             expressions[getPesudoSymbolname()] = &result.address;
 
  451         if (!result.rawIndex.empty()) {
 
  452             expressions[getPesudoSymbolname()] = &result.index;
 
  454         if (!result.rawField.empty()) {
 
  455             expressions[getPesudoSymbolname()] = &result.field;
 
  458     if (endIndex != -1) {
 
  459         auto lineSymbol = results[endIndex].rawLocation.empty() ? getPesudoSymbolname() : results[endIndex].rawLocation;
 
  460         constants.push_back(std::make_tuple(
 
  463             results[endIndex].address));
 
  466     for (
auto& it : constants) {
 
  467         expressions[std::get<0>(it)] = &std::get<1>(it);
 
  468         expressions[getPesudoSymbolname()] = &std::get<2>(it);
 
  471     std::unordered_map<std::string, int> dependNums;
 
  472     std::unordered_map<std::string, std::unordered_set<std::string>> solves;
 
  473     std::set<std::pair<int, std::string>> tasks;
 
  474     for (
auto& it : expressions) {
 
  475         dependNums[it.first] = 
static_cast<int>(it.second->depends().size());
 
  476         for (
auto& depend : it.second->depends()) {
 
  477             solves[depend].insert(it.first);
 
  478             if (evaluated.find(depend) != evaluated.end()) {
 
  479                 --dependNums[it.first];
 
  482         tasks.insert({dependNums[it.first], it.first});
 
  484     while (!tasks.empty()) {
 
  485         auto& symbol = tasks.begin()->second;
 
  486         auto& expression = expressions[symbol];
 
  487         if (tasks.begin()->first != 0 || !expression->evaluate(evaluated)) {
 
  488             std::ostringstream oss;
 
  489             oss << 
"Unresolved symbol found while trying to calcuate: ";
 
  490             oss << tasks.begin()->second << 
"=" << *expression;
 
  493         evaluated[symbol] = expression->result();
 
  494         tasks.erase({0, symbol});
 
  495         for (
auto& solve : solves[symbol]) {
 
  496             tasks.erase({dependNums[solve], solve});
 
  497             tasks.insert({--dependNums[solve], solve});
 
  501     for (
auto& it : constants) {
 
  502         int32_t location = std::get<1>(it).result().value;
 
  504             throw RuntimeError(location, 
"Location of the code is invalid: " + std::to_string(location));
 
  506         memory[location].
set(std::get<2>(it).result().value);
 
  510     for (
auto& result : results) {
 
  511         if (result.parsedType == ParsedType::INSTRUCTION) {
 
  512             result.evaluate(evaluated);
 
  513             int32_t location = result.location.result().value;
 
  515                 throw RuntimeError(location, 
"Location of the code is invalid: " + std::to_string(location));
 
  517             if (_lineOffset == -1) {
 
  518                 _lineOffset = location;
 
  520             memory[location].
set(result.word.negative,
 
  521                                  result.word.address(),
 
  524                                  result.word.operation());
 
  527     if (endIndex != -1) {
 
  528         results[endIndex].address.evaluate(evaluated);
 
  529         _lineOffset = results[endIndex].address.result().value;
 
  530     } 
else if (_lineOffset == -1) {
 
  535 std::string Computer::getPesudoSymbolname() {
 
  536     return "#" + std::to_string(_pesudoVarIndex++);
 
  539 int32_t Computer::getIndexedAddress(
const InstructionWord& instruction, 
bool checkRange) {
 
  541     if (instruction.index() != 0) {
 
  542         auto& rIi = 
rI(instruction.index());
 
  543         offset = 
static_cast<int32_t
>(rIi.value());
 
  545     int32_t address = 
static_cast<int32_t
>(instruction.addressValue()) + offset;
 
  546     if (checkRange && !(0 <= address && address < 
NUM_MEMORY)) {
 
  547         throw RuntimeError(_lineOffset, 
"Invalid address in instruction '" + instruction.getBytesString() +
 
  548                                         "': " + std::to_string(address));
 
  553 void Computer::copyToRegister5(
const InstructionWord& instruction, 
const ComputerWord& word, Register5* reg) {
 
  554     int32_t start = instruction.field() / 8;
 
  555     int32_t stop = instruction.field() % 8;
 
  557     if (start > stop || stop > 5) {
 
  558         throw RuntimeError(_lineOffset, 
"Invalid field value: (" 
  559                                         + std::to_string(start) + 
":" + std::to_string(stop) + 
")");
 
  562         reg->negative = word.negative;
 
  565     for (int32_t i = stop, j = 5; i >= start; --i, --j) {
 
  566         reg->set(j, word[i]);
 
  570 void Computer::copyFromRegister5(
const InstructionWord& instruction, 
const Register5& reg, ComputerWord* word) {
 
  571     int32_t start = instruction.field() / 8;
 
  572     int32_t stop = instruction.field() % 8;
 
  573     if (start > stop || stop > 5) {
 
  574         throw RuntimeError(_lineOffset, 
"Invalid field value: (" 
  575                                         + std::to_string(start) + 
":" + std::to_string(stop) + 
")");
 
  578         word->negative = reg.negative;
 
  581     for (int32_t i = stop, j = 5; i >= start; --i, --j) {
 
  582         word->set(i, reg[j]);
 
  586 void Computer::copyToRegister2(
const InstructionWord& instruction, 
const ComputerWord& word, Register2* reg) {
 
  587     int32_t start = instruction.field() / 8;
 
  588     int32_t stop = instruction.field() % 8;
 
  589     if (start > stop || stop > 5) {
 
  590         throw RuntimeError(_lineOffset, 
"Invalid field value: (" 
  591                                         + std::to_string(start) + 
":" + std::to_string(stop) + 
")");
 
  595         reg->negative = word.negative;
 
  598     for (int32_t i = stop, j = 2; i >= start && j > 0; --i, --j) {
 
  599         reg->set(j, word[i]);
 
  608 int32_t Computer::checkRange(int32_t value, 
int bytes) {
 
  609     int32_t range = 1 << (6 * bytes);
 
  610     if (std::abs(value) >= range) {
 
  619 uint8_t Computer::getAX(
int index)
 const {
 
  620     assert(1 <= index && index <= 10);
 
  621     return index <= 5 ? 
rA[index] : 
rX[index - 5];
 
  624 void Computer::setAX(
int index, uint8_t value) {
 
  625     assert(1 <= index && index <= 10);
 
  629         rX[index - 5] = value;