From fa44e3ee601c48c38b52b887f5ceed5afb3a0855 Mon Sep 17 00:00:00 2001 From: Maxwell Jeffress Date: Mon, 24 Nov 2025 11:37:16 +1100 Subject: [PATCH] Add input instruction --- src/interpreter.c | 170 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 168 insertions(+), 2 deletions(-) diff --git a/src/interpreter.c b/src/interpreter.c index 599fa16..74a09d5 100644 --- a/src/interpreter.c +++ b/src/interpreter.c @@ -192,8 +192,8 @@ void interpretGroundInstruction(GroundInstruction inst, GroundScope* scope) { runtimeError(TOO_FEW_ARGS, "Expecting 1 or more args", in, currentInstruction); } for (int i = 0; i < in->args.length; i++) { + if (i != 0) printf(" "); printGroundArg(&in->args.args[i]); - printf(" "); } break; } @@ -202,12 +202,28 @@ void interpretGroundInstruction(GroundInstruction inst, GroundScope* scope) { runtimeError(TOO_FEW_ARGS, "Expecting 1 or more args", in, currentInstruction); } for (int i = 0; i < in->args.length; i++) { + if (i != 0) printf(" "); printGroundArg(&in->args.args[i]); - printf(" "); } printf("\n"); break; } + case INPUT: { + if (in->args.length < 1) { + runtimeError(TOO_FEW_ARGS, "Expecting 1 arg", in, currentInstruction); + } + if (in->args.args[0].type != DIRREF) { + runtimeError(ARG_TYPE_MISMATCH, "Expecting a DirectRef for arg 1", in, currentInstruction); + } + char buffer[256]; + if (fgets(buffer, sizeof(buffer), stdin) != NULL) { + buffer[strcspn(buffer, "\n")] = '\0'; + addVariable(scope->variables, in->args.args[0].value.refName, createStringGroundValue(buffer)); + } else { + runtimeError(FIXME, "Failed to read input from console with fgets", in, currentInstruction); + } + break; + } case SET: { if (in->args.length < 2) { @@ -287,6 +303,156 @@ void interpretGroundInstruction(GroundInstruction inst, GroundScope* scope) { } break; } + case SUBTRACT: { + 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) { + if (right->type != INT && right->type != DOUBLE) { + runtimeError(ARG_TYPE_MISMATCH, "Expecting an Int or Double for arg 2", in, currentInstruction); + } + + if (left->type == DOUBLE || right->type == DOUBLE) { + double result = 0; + + if (left->type == INT) { + result -= left->data.intVal; + } else if (left->type == DOUBLE) { + result -= left->data.doubleVal; + } + + if (right->type == INT) { + result += right->data.intVal; + } else if (right->type == DOUBLE) { + result += right->data.doubleVal; + } + + addVariable(scope->variables, in->args.args[2].value.refName, createDoubleGroundValue(result)); + } else { + int64_t result = left->data.intVal - right->data.intVal; + addVariable(scope->variables, in->args.args[2].value.refName, createIntGroundValue(result)); + } + } else { + runtimeError(ARG_TYPE_MISMATCH, "Expecting an Int or Double for arg 1", in, currentInstruction); + } + break; + } + case MULTIPLY: { + 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) { + if (right->type != INT && right->type != DOUBLE) { + runtimeError(ARG_TYPE_MISMATCH, "Expecting an Int or Double for arg 2", in, currentInstruction); + } + + if (left->type == DOUBLE || right->type == DOUBLE) { + double result = 0; + + if (left->type == INT) { + result *= left->data.intVal; + } else if (left->type == DOUBLE) { + result += left->data.doubleVal; + } + + if (right->type == INT) { + result *= right->data.intVal; + } else if (right->type == DOUBLE) { + result += right->data.doubleVal; + } + + addVariable(scope->variables, in->args.args[2].value.refName, createDoubleGroundValue(result)); + } else { + int64_t result = left->data.intVal * right->data.intVal; + addVariable(scope->variables, in->args.args[2].value.refName, createIntGroundValue(result)); + } + } else { + runtimeError(ARG_TYPE_MISMATCH, "Expecting an Int or Double for arg 1", in, currentInstruction); + } + break; + } + case DIVIDE: { + 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) { + if (right->type != INT && right->type != DOUBLE) { + runtimeError(ARG_TYPE_MISMATCH, "Expecting an Int or Double for arg 2", in, currentInstruction); + } + + if (left->type == DOUBLE || right->type == DOUBLE) { + double result = 0; + + if (left->type == INT) { + result /= left->data.intVal; + } else if (left->type == DOUBLE) { + result /= left->data.doubleVal; + } + + if (right->type == INT) { + result /= right->data.intVal; + } else if (right->type == DOUBLE) { + result /= right->data.doubleVal; + } + + addVariable(scope->variables, in->args.args[2].value.refName, createDoubleGroundValue(result)); + } else { + int64_t result = left->data.intVal / right->data.intVal; + addVariable(scope->variables, in->args.args[2].value.refName, createIntGroundValue(result)); + } + } else { + runtimeError(ARG_TYPE_MISMATCH, "Expecting an Int or Double for arg 1", in, currentInstruction); + } + break; + } case EQUAL: { if (in->args.length < 3) { runtimeError(TOO_FEW_ARGS, "Expecting 3 args", in, currentInstruction);