Add variables and add

This commit is contained in:
2025-11-23 21:23:04 +11:00
parent 1c03f20af8
commit 251dd719b0
3 changed files with 122 additions and 6 deletions

View File

@@ -3,6 +3,7 @@
#include "types.h"
#include "include/uthash.h"
#include <stdlib.h>
#include <string.h>
int currentInstruction = 0;
@@ -21,6 +22,14 @@ void runtimeError(GroundRuntimeError error, char* what, GroundInstruction* where
printf("TooManyArgs");
break;
}
case UNKNOWN_LABEL: {
printf("UnknownLabel");
break;
}
case UNKNOWN_VARIABLE: {
printf("UnknownVariable");
break;
}
default:
case FIXME: {
printf("FIXME (please report issue to https://chsp.au/ground/cground)");
@@ -98,6 +107,18 @@ void interpretGroundProgram(GroundProgram* in) {
}
void interpretGroundInstruction(GroundInstruction* in, GroundScope* scope) {
// Insert variables prefixed with $
for (int i = 0; i < in->args.length; i++) {
if (in->args.args[i].type == VALREF) {
GroundVariable* variable = findVariable(*scope->variables, in->args.args[0].value.refName);
if (variable) {
in->args.args[i].value.value = variable->value;
in->args.args[i].type = VALUE;
} else {
runtimeError(UNKNOWN_VARIABLE, NULL, in, currentInstruction);
}
}
}
switch (in->type) {
// We can safely ignore any CREATELABEL instructions, these have been preprocessed
case CREATELABEL: {
@@ -156,7 +177,7 @@ void interpretGroundInstruction(GroundInstruction* in, GroundScope* scope) {
}
case PRINT: {
if (in->args.length < 1) {
runtimeError(TOO_FEW_ARGS, NULL, in, currentInstruction);
runtimeError(TOO_FEW_ARGS, "Expecting 1 or more args", in, currentInstruction);
}
for (int i = 0; i < in->args.length; i++) {
printGroundArg(&in->args.args[i]);
@@ -166,7 +187,7 @@ void interpretGroundInstruction(GroundInstruction* in, GroundScope* scope) {
}
case PRINTLN: {
if (in->args.length < 1) {
runtimeError(TOO_FEW_ARGS, NULL, in, currentInstruction);
runtimeError(TOO_FEW_ARGS, "Expecting 1 or more args", in, currentInstruction);
}
for (int i = 0; i < in->args.length; i++) {
printGroundArg(&in->args.args[i]);
@@ -175,6 +196,85 @@ void interpretGroundInstruction(GroundInstruction* in, GroundScope* scope) {
printf("\n");
break;
}
case SET: {
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 != DIRREF) {
runtimeError(ARG_TYPE_MISMATCH, "Expecting a DirectRef for arg 1", in, currentInstruction);
}
if (in->args.args[1].type != VALUE) {
runtimeError(ARG_TYPE_MISMATCH, "Expecting a Value for arg 2", in, currentInstruction);
}
addVariable(scope->variables, in->args.args[0].value.refName, in->args.args[1].value.value);
break;
}
case ADD: {
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 == STRING) {
if (right->type != STRING) {
runtimeError(ARG_TYPE_MISMATCH, "Expecting a String for arg 2", in, currentInstruction);
}
char* newString = malloc(sizeof(char));
strcpy(newString, left->data.stringVal);
strcat(newString, right->data.stringVal);
addVariable(scope->variables, in->args.args[2].value.refName, createStringGroundValue(newString));
}
else 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 (left->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, Double, or String for arg 1", in, currentInstruction);
}
break;
}
default: {
runtimeError(FIXME, "Currently unimplemented instruction", in, currentInstruction);
}

View File

@@ -7,7 +7,7 @@
#include "include/uthash.h"
typedef enum GroundRuntimeError {
ARG_TYPE_MISMATCH, TOO_FEW_ARGS, TOO_MANY_ARGS, UNKNOWN_LABEL, FIXME
ARG_TYPE_MISMATCH, TOO_FEW_ARGS, TOO_MANY_ARGS, UNKNOWN_LABEL, UNKNOWN_VARIABLE, FIXME
} GroundRuntimeError;
typedef struct GroundLabel {