diff --git a/src/compiler.c b/src/compiler.c index b2c2dcb..a8bb1bf 100644 --- a/src/compiler.c +++ b/src/compiler.c @@ -13,7 +13,7 @@ VariableTable createVariableTable() { return vt; } -void addVtVariable(VariableTable* vt, const char* name) { +void addVtVariable(VariableTable* vt, const char* name, GroundValueType type) { // check if it already exists for (size_t i = 0; i < vt->count; i++) { if (strcmp(vt->vars[i].name, name) == 0) { @@ -29,10 +29,20 @@ void addVtVariable(VariableTable* vt, const char* name) { // add the variable strcpy(vt->vars[vt->count].name, name); + vt->vars[vt->count].type = type; vt->vars[vt->count].offset = vt->count * 8; vt->count++; } +VariableInfo* getVariable(VariableTable* vt, const char* name) { + for (size_t i = 0; i < vt->count; i++) { + if (strcmp(vt->vars[i].name, name) == 0) { + return &vt->vars[i]; + } + } + return NULL; +} + int getVariablePos(VariableTable* vt, const char* name) { for (size_t i = 0; i < vt->count; i++) { if (strcmp(vt->vars[i].name, name) == 0) { @@ -42,6 +52,232 @@ int getVariablePos(VariableTable* vt, const char* name) { return -1; } +GroundValueType getInstructionReturnType(GroundInstruction* gi, VariableTable* table) { + switch (gi->type) { + case JUMP: + case PRINT: + case PRINTLN: + case END: + case IF: + case RETURN: + case ENDFUN: + case PUSHARG: + case CALL: // FIXME do this when functions are added + case USE: + case EXTERN: + case CREATELABEL: + case PAUSE: + case DROP: + case ERRORCMD: + case ENDSTRUCT: + case INIT: // FIXME do this when objects are added + case GETFIELD: // FIXME do this when objects are added + case SETFIELD: // FIXME do this when objects are added + case DIVIDE: // FIXME do this when division is added + case SETLISTAT: + case GETLISTAT: // FIXME do this when lists are getting implemented + case LISTAPPEND: { + return NONE; + } + case TOSTRING: + case GETTYPE: + case INPUT: { + return STRING; + } + case STOI: + case GETLISTSIZE: + case GETSTRSIZE: { + return INT; + } + case STOD: { + return DOUBLE; + } + case EQUAL: + case INEQUAL: + case GREATER: + case LESSER: + case NOT: + case EXISTS: { + return BOOL; + } + case GETSTRCHARAT: { + return CHAR; + } + case SETLIST: { + return LIST; + } + case FUN: { + return FUNCTION; + } + case STRUCT: { + return STRUCTVAL; + } + case SET: { + if (gi->args.length == 2) { + if (gi->args.args[0].type == VALUE) { + return gi->args.args[0].value.value.type; + } else if (gi->args.args[0].type == VALREF) { + VariableInfo* var = getVariable(table, gi->args.args[0].value.refName); + if (var == NULL) { + return NONE; + } + return var->type; + } else { + return NONE; + } + } else { + return NONE; + } + } + case ADD: { + if (gi->args.length == 3) { + GroundValueType leftType; + GroundValueType rightType; + if (gi->args.args[0].type == VALUE) { + leftType = gi->args.args[0].value.value.type; + } else if (gi->args.args[0].type == VALREF) { + VariableInfo* var = getVariable(table, gi->args.args[0].value.refName); + if (var == NULL) { + return NONE; + } + leftType = var->type; + } else { + return NONE; + } + if (gi->args.args[1].type == VALUE) { + rightType = gi->args.args[1].value.value.type; + } else if (gi->args.args[1].type == VALREF) { + VariableInfo* var = getVariable(table, gi->args.args[1].value.refName); + if (var == NULL) { + return NONE; + } + rightType = var->type; + } else { + return NONE; + } + + if (leftType == STRING) { + if (rightType == STRING) { + return STRING; + } else { + return NONE; + } + } + if (leftType == DOUBLE) { + if (rightType == DOUBLE || rightType == INT) { + return DOUBLE; + } else { + return NONE; + } + } + if (rightType == DOUBLE) { + if (leftType == DOUBLE || leftType == INT) { + return DOUBLE; + } else { + return NONE; + } + } + return NONE; + } else { + return NONE; + } + } + case SUBTRACT: { + if (gi->args.length == 3) { + GroundValueType leftType; + GroundValueType rightType; + if (gi->args.args[0].type == VALUE) { + leftType = gi->args.args[0].value.value.type; + } else if (gi->args.args[0].type == VALREF) { + VariableInfo* var = getVariable(table, gi->args.args[0].value.refName); + if (var == NULL) { + return NONE; + } + leftType = var->type; + } else { + return NONE; + } + if (gi->args.args[1].type == VALUE) { + rightType = gi->args.args[1].value.value.type; + } else if (gi->args.args[1].type == VALREF) { + VariableInfo* var = getVariable(table, gi->args.args[1].value.refName); + if (var == NULL) { + return NONE; + } + rightType = var->type; + } else { + return NONE; + } + + if (leftType == DOUBLE) { + if (rightType == DOUBLE || rightType == INT) { + return DOUBLE; + } else { + return NONE; + } + } + if (rightType == DOUBLE) { + if (leftType == DOUBLE || leftType == INT) { + return DOUBLE; + } else { + return NONE; + } + } + return NONE; + } else { + return NONE; + } + } + case MULTIPLY: { + if (gi->args.length == 3) { + GroundValueType leftType; + GroundValueType rightType; + if (gi->args.args[0].type == VALUE) { + leftType = gi->args.args[0].value.value.type; + } else if (gi->args.args[0].type == VALREF) { + VariableInfo* var = getVariable(table, gi->args.args[0].value.refName); + if (var == NULL) { + return NONE; + } + leftType = var->type; + } else { + return NONE; + } + if (gi->args.args[1].type == VALUE) { + rightType = gi->args.args[1].value.value.type; + } else if (gi->args.args[1].type == VALREF) { + VariableInfo* var = getVariable(table, gi->args.args[1].value.refName); + if (var == NULL) { + return NONE; + } + rightType = var->type; + } else { + return NONE; + } + + if (leftType == DOUBLE) { + if (rightType == DOUBLE || rightType == INT) { + return DOUBLE; + } else { + return NONE; + } + } + if (rightType == DOUBLE) { + if (leftType == DOUBLE || leftType == INT) { + return DOUBLE; + } else { + return NONE; + } + } + return NONE; + } else { + return NONE; + } + } + } + return INT; +} + char* processValueString(GroundArg arg) { if (arg.type == VALREF) { char* buf = malloc(sizeof(char) * 260); @@ -124,7 +360,7 @@ char* compileGroundProgram(GroundProgram* program) { GroundInstruction gi = program->instructions[i]; for (size_t j = 0; j < gi.args.length; j++) { if (gi.args.args[j].type == DIRREF) { - addVtVariable(&varTable, gi.args.args[j].value.refName); + addVtVariable(&varTable, gi.args.args[j].value.refName, getInstructionReturnType(&gi, &varTable)); } } } diff --git a/src/compiler.h b/src/compiler.h index 4e5e37f..ddcb7bf 100644 --- a/src/compiler.h +++ b/src/compiler.h @@ -7,6 +7,7 @@ char* compileGroundProgram(GroundProgram* program); typedef struct VariableInfo { char name[256]; int offset; + GroundValueType type; } VariableInfo; typedef struct VariableTable {