diff --git a/CMakeLists.txt b/CMakeLists.txt index 4912807..de52805 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -14,7 +14,7 @@ set(CMAKE_C_COMPILER "gcc") project( Interpreter-AT2 - VERSION 1.0.0 + VERSION 1.1.0 LANGUAGES CXX C ) @@ -27,6 +27,8 @@ add_executable(tests src/debug.c src/error.c src/binExporter.c + src/vProc.c + src/vTerminal.c test/test.cc src/ast.c googletest/googletest/src/gtest-all.cc diff --git a/src/2at2.c b/src/2at2.c index 90f90d0..c485fd2 100644 --- a/src/2at2.c +++ b/src/2at2.c @@ -13,7 +13,7 @@ #include "error.h" #include "binExporter.h" -#define VERSION "1.0.0" +#define VERSION "1.1.0" #define BIN_NAME "bin.2at2" int main(int argc, char *argv[]) { @@ -99,7 +99,7 @@ int main(int argc, char *argv[]) { // ---------- Assemble ---------- // run exporter - exportToBin(instList, BIN_NAME, varList, errData); + exportToBin(instList, BIN_NAME, errData); // Stop if there are errors if(errData->errors > 0){ diff --git a/src/ast.c b/src/ast.c index 8d38b74..ce0ce7f 100644 --- a/src/ast.c +++ b/src/ast.c @@ -20,12 +20,6 @@ char *getIntCode(enum interruptKind kind, asm_error_t *errData){ return "1"; case INT_OB1: return "2"; - case INT_OR: - return "3"; - case INT_AND: - return "4"; - case INT_XOR: - return "5"; case INT_LT: return "6"; case INT_LTE: @@ -44,10 +38,6 @@ char *getIntCode(enum interruptKind kind, asm_error_t *errData){ return "13"; case INT_MOV_F_REG: return "14"; - case INT_ELSE: - return "15"; - case INT_END: - return "16"; default: errorIntCodeNotSupported(kind, errData); return NULL; diff --git a/src/ast.h b/src/ast.h index f6edb1e..3a4e31e 100644 --- a/src/ast.h +++ b/src/ast.h @@ -46,9 +46,6 @@ enum interruptKind{ INT_EXIT, INT_DRAW, INT_OB1, - INT_OR, - INT_AND, - INT_XOR, INT_LT, INT_LTE, INT_GT, @@ -58,8 +55,6 @@ enum interruptKind{ INT_PUSHA, INT_POPA, INT_MOV_F_REG, - INT_ELSE, - INT_END, }; // Register names diff --git a/src/binExporter.c b/src/binExporter.c index 0d7a8d6..601bf5e 100644 --- a/src/binExporter.c +++ b/src/binExporter.c @@ -11,7 +11,7 @@ #include "error.h" #include "debug.h" -void exportToBin(instList_t *nodeList, char *filename, varList_t *varList, asm_error_t *errData){ +void exportToBin(instList_t *nodeList, char *filename, asm_error_t *errData){ // Open the file FILE *file = fopen(filename, "wb"); @@ -158,12 +158,6 @@ char *interToBinCode(enum interruptKind inter){ return "00000001"; case INT_OB1: return "00000010"; - case INT_OR: - return "00000011"; - case INT_AND: - return "00000100"; - case INT_XOR: - return "00000101"; case INT_LT: return "00000110"; case INT_LTE: @@ -182,10 +176,6 @@ char *interToBinCode(enum interruptKind inter){ return "00001101"; case INT_MOV_F_REG: return "00001110"; - case INT_ELSE: - return "00001111"; - case INT_END: - return "00010000"; default: return NULL; } diff --git a/src/binExporter.h b/src/binExporter.h index d74b6e3..212b642 100644 --- a/src/binExporter.h +++ b/src/binExporter.h @@ -11,10 +11,9 @@ extern "C" { params: nodeList: pointer to the instruction list filename: name of the file - varList: pointer to the variable list errData: pointer to the error struct */ -void exportToBin(instList_t *nodeList, char *filename, varList_t *varList, asm_error_t *errData); +void exportToBin(instList_t *nodeList, char *filename, asm_error_t *errData); /* Convert an operation to its binary code diff --git a/src/builder.c b/src/builder.c index eb7913f..4a41533 100644 --- a/src/builder.c +++ b/src/builder.c @@ -37,7 +37,7 @@ void buildNode(instNode_t *node, varList_t *varList, labelList_t *labeList, asm_ buildCall(node, labeList, errData); break; case OP_INT: - node->isBuilt = true; + node->isBuilt = buildIntOpe(node, errData); break; case OP_B_XOR: case OP_DIV: case OP_ADD: case OP_SUB: case OP_MUL: case OP_R_SHIFT: case OP_L_SHIFT: case OP_B_AND: case OP_B_OR: case OP_B_NOT: case OP_MOD: buildOperation(node, varList, errData); @@ -474,4 +474,19 @@ int getVarDatasize(char *str){ else{ return (int)strlen(str); } +} + +bool buildIntOpe(instNode_t *node, asm_error_t *errData){ + switch (node->inter) + { + case INT_LT: case INT_GT: case INT_LTE: case INT_GTE: case INT_EQ: case INT_NEQ: + // check if next node is a goto + if(node->next == NULL || node->next->op != OP_GOTO){ + errorIfInt(node->lineNb, errData); + return false; + } + return true; + default: + return true; + } } \ No newline at end of file diff --git a/src/builder.h b/src/builder.h index 28f2d3a..0a790ac 100644 --- a/src/builder.h +++ b/src/builder.h @@ -99,6 +99,16 @@ enum regKind getRegKind(char *str, long lineNb, asm_error_t *errData); */ int getVarDatasize(char *str); +/* + build interrupt operation + params: + node: pointer to the instruction node + errData: pointer to the error struct + returns: + bool: true if the operation was built +*/ +bool buildIntOpe(instNode_t *node, asm_error_t *errData); + #ifdef __cplusplus } #endif \ No newline at end of file diff --git a/src/debug.c b/src/debug.c index 1deabaf..1a39912 100644 --- a/src/debug.c +++ b/src/debug.c @@ -113,12 +113,6 @@ char *getInterName(enum interruptKind kind){ return "DRAW"; case INT_OB1: return "OB1"; - case INT_OR: - return "OR"; - case INT_AND: - return "AND"; - case INT_XOR: - return "XOR"; case INT_LT: return "LT"; case INT_LTE: @@ -137,10 +131,6 @@ char *getInterName(enum interruptKind kind){ return "POPA"; case INT_MOV_F_REG: return "MOV_F_REG"; - case INT_ELSE: - return "ELSE"; - case INT_END: - return "END"; default: return "UNKNOWN"; } diff --git a/src/error.c b/src/error.c index d6f8b72..93f950b 100644 --- a/src/error.c +++ b/src/error.c @@ -475,4 +475,13 @@ void errorOverflow(asm_error_t *errData){ char *errType = "Overflow"; char *errDetails = "The value is too large"; displayError(errType, errDetails, NULL, errorFile, errData); +} + +void errorIfInt(long lineNb, asm_error_t *errData){ + char *errType = "Interrupt Error"; + char errDetails[64]; + char errLocation[64]; + sprintf(errDetails, "If interrupt must be followed by goto instruction"); + sprintf(errLocation, "File %s, line %ld", errData->inputFile, lineNb); + displayError(errType, errDetails, errLocation, errorFile, errData); } \ No newline at end of file diff --git a/src/error.h b/src/error.h index d832630..9f971e4 100644 --- a/src/error.h +++ b/src/error.h @@ -381,6 +381,14 @@ void errorReadOnly(asm_error_t *errData); */ void errorOverflow(asm_error_t *errData); +/* + Display error messages for invalid if statement + params: + lineNb: Line number + errData: Error history +*/ +void errorIfInt(long lineNb, asm_error_t *errData); + #ifdef __cplusplus } -#endif +#endif \ No newline at end of file diff --git a/src/parser.c b/src/parser.c index 564954c..1518500 100644 --- a/src/parser.c +++ b/src/parser.c @@ -282,21 +282,6 @@ bool isOp(char *inst, instNode_t *newNode, varList_t *varList, labelList_t *labe newNode->isInter = true; newNode->inter = INT_OB1; } - else if(strcmp(inst, "if_or") == 0){ - newNode->op = OP_INT; - newNode->isInter = true; - newNode->inter = INT_OR; - } - else if(strcmp(inst, "if_and") == 0){ - newNode->op = OP_INT; - newNode->isInter = true; - newNode->inter = INT_AND; - } - else if(strcmp(inst, "if_xor") == 0){ - newNode->op = OP_INT; - newNode->isInter = true; - newNode->inter = INT_XOR; - } else if(strcmp(inst, "if_lt") == 0){ newNode->op = OP_INT; newNode->isInter = true; @@ -337,16 +322,6 @@ bool isOp(char *inst, instNode_t *newNode, varList_t *varList, labelList_t *labe newNode->isInter = true; newNode->inter = INT_POPA; } - else if(strcmp(inst, "else") == 0){ - newNode->op = OP_INT; - newNode->isInter = true; - newNode->inter = INT_ELSE; - } - else if(strcmp(inst, "end") == 0){ - newNode->op = OP_INT; - newNode->isInter = true; - newNode->inter = INT_END; - } else{ errorInstruction(inst, newNode->lineNb, errData); return false; diff --git a/src/vProc.c b/src/vProc.c index 63445de..18fe3a6 100644 --- a/src/vProc.c +++ b/src/vProc.c @@ -21,6 +21,8 @@ int lastVarIdx = 0; fpos_t cursorPos[MAX_CALL_STACK]; int callStackSize = 0; +bool allowGoto = true; + // registers vRegister_t rg0 = {true, 0}; vRegister_t rg1 = {true, 0}; @@ -106,6 +108,10 @@ bool run(instruction_t inst, carry_t *carry, FILE *file, char *filename, asm_err reg->value = inst.arg; return true; case 1: //goto + if(!allowGoto){ + allowGoto = true; + return true; + } pos = searchLabel(inst.arg, filename, errData); // goto label fsetpos(file, &pos); @@ -283,23 +289,41 @@ bool runInt(instruction_t inst, carry_t *carry){ return true; case 2: // ob1 return true; - case 3: // cmp or - return true; - case 4: // cmp and - return true; - case 5: // cmp xor - return true; case 6: // cmp less than + if(!(rg0.value < rg1.value)) + { + allowGoto = false; + } return true; case 7: // cmp less than or equal + if(!(rg0.value <= rg1.value)) + { + allowGoto = false; + } return true; case 8: // cmp greater than + if(!(rg0.value > rg1.value)) + { + allowGoto = false; + } return true; case 9: // cmp greater than or equal + if(!(rg0.value >= rg1.value)) + { + allowGoto = false; + } return true; case 10: // cmp equal + if(!(rg0.value == rg1.value)) + { + allowGoto = false; + } return true; case 11: // cmp not equal + if(!(rg0.value != rg1.value)) + { + allowGoto = false; + } return true; case 12: // pusha return true; @@ -310,10 +334,6 @@ bool runInt(instruction_t inst, carry_t *carry){ carry->nextArg = getRegister(inst.reg)->value; carry->isUsed = true; return true; - case 15: // else - return true; - case 16: // end - return true; default: exit(EXIT_FAILURE); } diff --git a/src/vTerminal.c b/src/vTerminal.c index 6cdcf0b..3df4934 100644 --- a/src/vTerminal.c +++ b/src/vTerminal.c @@ -8,7 +8,7 @@ #include "vTerminal.h" -#define VERSION "1.0.0" +#define VERSION "1.1.0" void runVTerminal(asm_error_t *errData){ char *command = (char *)malloc(100 * sizeof(char)); diff --git a/test/test.cc b/test/test.cc index 4452a83..8637551 100644 --- a/test/test.cc +++ b/test/test.cc @@ -464,43 +464,6 @@ TEST(isOp, ob1) { ASSERT_TRUE(newNode->op == OP_INT); } -TEST(isOp, IntOR) { - asm_error_t *errData = initErrorFile(fileName); - char *inst = const_cast("if_or"); - - varList_t *varList = createEmptyVarList(); - instNode_t *newNode = createEmptyInstNode(errData); - labelList_t *labelList = createEmptyLabelList(); - bool isThatKind = isOp(inst, newNode, varList, labelList, errData); - - ASSERT_TRUE(isThatKind); - ASSERT_TRUE(newNode->op == OP_INT); -} - -TEST(isOp, IntIF_AND) { - asm_error_t *errData = initErrorFile(fileName); - char *inst = const_cast("if_and"); - - varList_t *varList = createEmptyVarList(); - instNode_t *newNode = createEmptyInstNode(errData); - labelList_t *labelList = createEmptyLabelList(); - bool isThatKind = isOp(inst, newNode, varList, labelList, errData); - - ASSERT_TRUE(isThatKind); - ASSERT_TRUE(newNode->op == OP_INT); -} -TEST(isOp, IntIF_XOR) { - asm_error_t *errData = initErrorFile(fileName); - char *inst = const_cast("if_xor"); - - varList_t *varList = createEmptyVarList(); - instNode_t *newNode = createEmptyInstNode(errData); - labelList_t *labelList = createEmptyLabelList(); - bool isThatKind = isOp(inst, newNode, varList, labelList, errData); - - ASSERT_TRUE(isThatKind); - ASSERT_TRUE(newNode->op == OP_INT); -} TEST(isOp, IntIF_LT) { asm_error_t *errData = initErrorFile(fileName); char *inst = const_cast("if_lt"); @@ -644,9 +607,9 @@ TEST(buildProgram, ParsingAndBuilding) { varList_t *varList = createEmptyVarList(); instList_t *nodeList = createEmptyInstList(); labelList_t *labelList = createEmptyLabelList(); - char *fileName = const_cast("../test/test.aop"); + char *fileName = const_cast("../test/aop/test.aop"); bool parsing = false; - parseFile(nodeList, fileName, varList, errData); + parseFile(nodeList, fileName, varList, labelList, errData); if (nodeList->head != NULL) { parsing = true; }