Add variables and add
This commit is contained in:
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user