From 99e93bdfb8fbe095ea19d0fb2bd9925644c46f82 Mon Sep 17 00:00:00 2001 From: Maxwell Jeffress Date: Mon, 24 Nov 2025 13:19:37 +1100 Subject: [PATCH] Add more features --- README.md | 10 +-- src/interpreter.c | 205 +++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 209 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 8abd17d..6b40625 100644 --- a/README.md +++ b/README.md @@ -23,17 +23,17 @@ Progress marker: - [x] References - [ ] Interpreter - [x] Labels - - [ ] Console I/O + - [x] Console I/O - [x] Control flow - [ ] Data - - [ ] Variable creation - - [ ] Variable access + - [x] Variable creation + - [x] Variable access - [ ] Lists - [ ] Creation - [ ] Access - [ ] String operations - - [ ] Maths - - [ ] Comparisions + - [x] Maths + - [x] Comparisions - [ ] Type conversions - [ ] Functions - [ ] Custom data structures diff --git a/src/interpreter.c b/src/interpreter.c index 74a09d5..056f5f0 100644 --- a/src/interpreter.c +++ b/src/interpreter.c @@ -474,7 +474,15 @@ void interpretGroundInstruction(GroundInstruction inst, GroundScope* scope) { GroundValue* right = &in->args.args[1].value.value; if (left->type != right->type) { - addVariable(scope->variables, in->args.args[2].value.refName, createBoolGroundValue(false)); + if (left->type == INT && right->type == DOUBLE) { + bool cond = (left->data.intVal == right->data.doubleVal); + addVariable(scope->variables, in->args.args[2].value.refName, createBoolGroundValue(cond)); + } else if (left->type == DOUBLE && right->type == INT) { + bool cond = (left->data.doubleVal == right->data.intVal); + addVariable(scope->variables, in->args.args[2].value.refName, createBoolGroundValue(cond)); + } else { + addVariable(scope->variables, in->args.args[2].value.refName, createBoolGroundValue(false)); + } } else { switch (left->type) { case INT: { @@ -510,6 +518,201 @@ void interpretGroundInstruction(GroundInstruction inst, GroundScope* scope) { } break; } + case INEQUAL: { + if (in->args.length < 3) { + runtimeError(TOO_FEW_ARGS, "Expecting 3 args", in, currentInstruction); + } + if (in->args.length > 3) { + runtimeError(TOO_MANY_ARGS, "Expecting 3 args", in, currentInstruction); + } + if (in->args.args[0].type != VALUE) { + runtimeError(ARG_TYPE_MISMATCH, "Expecting a Value for arg 1", in, currentInstruction); + } + if (in->args.args[1].type != VALUE) { + runtimeError(ARG_TYPE_MISMATCH, "Expecting a Value for arg 2", in, currentInstruction); + } + if (in->args.args[2].type != DIRREF) { + runtimeError(ARG_TYPE_MISMATCH, "Expecting a DirectRef for arg 3", in, currentInstruction); + } + + GroundValue* left = &in->args.args[0].value.value; + GroundValue* right = &in->args.args[1].value.value; + + if (left->type != right->type) { + if (left->type == INT && right->type == DOUBLE) { + bool cond = (left->data.intVal != right->data.doubleVal); + addVariable(scope->variables, in->args.args[2].value.refName, createBoolGroundValue(cond)); + } else if (left->type == DOUBLE && right->type == INT) { + bool cond = (left->data.doubleVal != right->data.intVal); + addVariable(scope->variables, in->args.args[2].value.refName, createBoolGroundValue(cond)); + } else { + addVariable(scope->variables, in->args.args[2].value.refName, createBoolGroundValue(false)); + } + } else { + switch (left->type) { + case INT: { + bool cond = (left->data.intVal != right->data.intVal); + addVariable(scope->variables, in->args.args[2].value.refName, createBoolGroundValue(cond)); + break; + } + case DOUBLE: { + bool cond = (left->data.doubleVal != right->data.doubleVal); + addVariable(scope->variables, in->args.args[2].value.refName, createBoolGroundValue(cond)); + break; + } + case STRING: { + bool cond = (strcmp(left->data.stringVal, right->data.stringVal) != 0); + addVariable(scope->variables, in->args.args[2].value.refName, createBoolGroundValue(cond)); + break; + } + case CHAR: { + bool cond = (left->data.charVal != right->data.charVal); + addVariable(scope->variables, in->args.args[2].value.refName, createBoolGroundValue(cond)); + break; + } + case BOOL: { + bool cond = (left->data.boolVal != right->data.boolVal); + addVariable(scope->variables, in->args.args[2].value.refName, createBoolGroundValue(cond)); + break; + } + default: { + addVariable(scope->variables, in->args.args[2].value.refName, createBoolGroundValue(true)); + break; + } + } + } + break; + } + case GREATER: { + if (in->args.length < 3) { + runtimeError(TOO_FEW_ARGS, "Expecting 3 args", in, currentInstruction); + } + if (in->args.length > 3) { + runtimeError(TOO_MANY_ARGS, "Expecting 3 args", in, currentInstruction); + } + if (in->args.args[0].type != VALUE) { + runtimeError(ARG_TYPE_MISMATCH, "Expecting a Value for arg 1", in, currentInstruction); + } + if (in->args.args[1].type != VALUE) { + runtimeError(ARG_TYPE_MISMATCH, "Expecting a Value for arg 2", in, currentInstruction); + } + if (in->args.args[2].type != DIRREF) { + runtimeError(ARG_TYPE_MISMATCH, "Expecting a DirectRef for arg 3", in, currentInstruction); + } + + GroundValue* left = &in->args.args[0].value.value; + GroundValue* right = &in->args.args[1].value.value; + + if (left->type != INT && left->type != DOUBLE) { + runtimeError(ARG_TYPE_MISMATCH, "Expecting an Int or Double for arg 1", in, currentInstruction); + } else if (right->type != INT && right->type != DOUBLE) { + runtimeError(ARG_TYPE_MISMATCH, "Expecting an Int or Double for arg 2", in, currentInstruction); + } + + if (left->type != right->type) { + if (left->type == INT && right->type == DOUBLE) { + bool cond = (left->data.intVal > right->data.doubleVal); + addVariable(scope->variables, in->args.args[2].value.refName, createBoolGroundValue(cond)); + } else if (left->type == DOUBLE && right->type == INT) { + bool cond = (left->data.doubleVal > right->data.intVal); + addVariable(scope->variables, in->args.args[2].value.refName, createBoolGroundValue(cond)); + } else { + runtimeError(FIXME, "Uncaught invalid type", in, currentInstruction); + } + } else { + switch (left->type) { + case INT: { + bool cond = (left->data.intVal > right->data.intVal); + addVariable(scope->variables, in->args.args[2].value.refName, createBoolGroundValue(cond)); + break; + } + case DOUBLE: { + bool cond = (left->data.doubleVal > right->data.doubleVal); + addVariable(scope->variables, in->args.args[2].value.refName, createBoolGroundValue(cond)); + break; + } + default: { + runtimeError(FIXME, "Uncaught invalid type", in, currentInstruction); + break; + } + } + } + break; + } + case LESSER: { + if (in->args.length < 3) { + runtimeError(TOO_FEW_ARGS, "Expecting 3 args", in, currentInstruction); + } + if (in->args.length > 3) { + runtimeError(TOO_MANY_ARGS, "Expecting 3 args", in, currentInstruction); + } + if (in->args.args[0].type != VALUE) { + runtimeError(ARG_TYPE_MISMATCH, "Expecting a Value for arg 1", in, currentInstruction); + } + if (in->args.args[1].type != VALUE) { + runtimeError(ARG_TYPE_MISMATCH, "Expecting a Value for arg 2", in, currentInstruction); + } + if (in->args.args[2].type != DIRREF) { + runtimeError(ARG_TYPE_MISMATCH, "Expecting a DirectRef for arg 3", in, currentInstruction); + } + + GroundValue* left = &in->args.args[0].value.value; + GroundValue* right = &in->args.args[1].value.value; + + if (left->type != INT && left->type != DOUBLE) { + runtimeError(ARG_TYPE_MISMATCH, "Expecting an Int or Double for arg 1", in, currentInstruction); + } else if (right->type != INT && right->type != DOUBLE) { + runtimeError(ARG_TYPE_MISMATCH, "Expecting an Int or Double for arg 2", in, currentInstruction); + } + + if (left->type != right->type) { + if (left->type == INT && right->type == DOUBLE) { + bool cond = (left->data.intVal < right->data.doubleVal); + addVariable(scope->variables, in->args.args[2].value.refName, createBoolGroundValue(cond)); + } else if (left->type == DOUBLE && right->type == INT) { + bool cond = (left->data.doubleVal < right->data.intVal); + addVariable(scope->variables, in->args.args[2].value.refName, createBoolGroundValue(cond)); + } else { + runtimeError(FIXME, "Uncaught invalid type", in, currentInstruction); + } + } else { + switch (left->type) { + case INT: { + bool cond = (left->data.intVal < right->data.intVal); + addVariable(scope->variables, in->args.args[2].value.refName, createBoolGroundValue(cond)); + break; + } + case DOUBLE: { + bool cond = (left->data.doubleVal < right->data.doubleVal); + addVariable(scope->variables, in->args.args[2].value.refName, createBoolGroundValue(cond)); + break; + } + default: { + runtimeError(FIXME, "Uncaught invalid type", in, currentInstruction); + break; + } + } + } + break; + } + case NOT: { + if (in->args.length < 2) { + runtimeError(TOO_FEW_ARGS, "Expecting 2 args", in, currentInstruction); + } + if (in->args.length > 2) { + runtimeError(TOO_MANY_ARGS, "Expecting 2 args", in, currentInstruction); + } + if (in->args.args[0].type != VALUE && in->args.args[0].value.value.type != BOOL) { + runtimeError(ARG_TYPE_MISMATCH, "Expecting a Bool for arg 1", in, currentInstruction); + } + if (in->args.args[1].type != DIRREF) { + runtimeError(ARG_TYPE_MISMATCH, "Expecting a DirectRef for arg 2", in, currentInstruction); + } + + bool condition = !in->args.args[1].value.value.data.boolVal; + + addVariable(scope->variables, in->args.args[1].value.refName, createBoolGroundValue(condition)); + } default: { runtimeError(FIXME, "Currently unimplemented instruction", in, currentInstruction); }