List stuff

This commit is contained in:
2025-11-28 09:23:43 +11:00
parent 99e93bdfb8
commit 0b917a6702
3 changed files with 213 additions and 23 deletions

View File

@@ -136,6 +136,13 @@ void interpretGroundInstruction(GroundInstruction inst, GroundScope* scope) {
case CREATELABEL: {
break;
}
/*
* CONTROL FLOW
* These instructions are for controlling how the program is executed.
* Instructions:
* if, jump, end
*/
case IF: {
if (in->args.length < 2) {
runtimeError(TOO_FEW_ARGS, "Expecting 2 arguments", in, currentInstruction);
@@ -187,6 +194,13 @@ void interpretGroundInstruction(GroundInstruction inst, GroundScope* scope) {
}
break;
}
/*
* I/O
* These instructions take information from the user, and print it out.
* Instructions:
* print, println, input
*/
case PRINT: {
if (in->args.length < 1) {
runtimeError(TOO_FEW_ARGS, "Expecting 1 or more args", in, currentInstruction);
@@ -225,6 +239,14 @@ void interpretGroundInstruction(GroundInstruction inst, GroundScope* scope) {
break;
}
/*
* VARIABLES AND LISTS
* These instructions are for initializing variables and lists.
* Instructions:
* set, gettype, exists
* WIP Instructions:
* setlist, setlistat, getlistat, getlistsize, listappend
*/
case SET: {
if (in->args.length < 2) {
runtimeError(TOO_FEW_ARGS, "Expecting 2 args", in, currentInstruction);
@@ -242,7 +264,82 @@ void interpretGroundInstruction(GroundInstruction inst, GroundScope* scope) {
addVariable(scope->variables, in->args.args[0].value.refName, in->args.args[1].value.value);
break;
}
case GETTYPE: {
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) {
runtimeError(ARG_TYPE_MISMATCH, "Expecting a Value for arg 1", in, currentInstruction);
}
if (in->args.args[1].type != DIRREF) {
runtimeError(ARG_TYPE_MISMATCH, "Expecting a DirectRef for arg 2", in, currentInstruction);
}
switch (in->args.args[0].value.value.type) {
case INT: {
addVariable(scope->variables, in->args.args[1].value.refName, createStringGroundValue("int"));
break;
}
case DOUBLE: {
addVariable(scope->variables, in->args.args[1].value.refName, createStringGroundValue("double"));
break;
}
case STRING: {
addVariable(scope->variables, in->args.args[1].value.refName, createStringGroundValue("string"));
break;
}
case CHAR: {
addVariable(scope->variables, in->args.args[1].value.refName, createStringGroundValue("char"));
break;
}
case BOOL: {
addVariable(scope->variables, in->args.args[1].value.refName, createStringGroundValue("bool"));
break;
}
case LIST: {
addVariable(scope->variables, in->args.args[1].value.refName, createStringGroundValue("list"));
break;
}
case CUSTOM: {
addVariable(scope->variables, in->args.args[1].value.refName, createStringGroundValue("custom"));
break;
}
}
break;
}
case EXISTS: {
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[0].type != DIRREF) {
runtimeError(ARG_TYPE_MISMATCH, "Expecting a DirectRef for arg 2", in, currentInstruction);
}
if (findVariable(*scope->variables, in->args.args[0].value.refName)) {
addVariable(scope->variables, in->args.args[1].value.refName, createBoolGroundValue(true));
} else {
addVariable(scope->variables, in->args.args[1].value.refName, createBoolGroundValue(false));
}
break;
}
/*
* MATHS
* These instructions allow running mathematical operations on values.
* Instructions:
* add, subtract, multiply, divide
*/
case ADD: {
if (in->args.length < 3) {
runtimeError(TOO_FEW_ARGS, "Expecting 3 args", in, currentInstruction);
@@ -427,6 +524,10 @@ void interpretGroundInstruction(GroundInstruction inst, GroundScope* scope) {
if (right->type != INT && right->type != DOUBLE) {
runtimeError(ARG_TYPE_MISMATCH, "Expecting an Int or Double for arg 2", in, currentInstruction);
}
if (right->type == INT && right->data.intVal == 0) {
}
if (left->type == DOUBLE || right->type == DOUBLE) {
double result = 0;
@@ -453,6 +554,13 @@ void interpretGroundInstruction(GroundInstruction inst, GroundScope* scope) {
}
break;
}
/*
* COMPARISONS
* Allows comparing values.
* Instructions:
* equal, inequal, not, greater, lesser
*/
case EQUAL: {
if (in->args.length < 3) {
runtimeError(TOO_FEW_ARGS, "Expecting 3 args", in, currentInstruction);
@@ -583,6 +691,27 @@ void interpretGroundInstruction(GroundInstruction inst, GroundScope* scope) {
}
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);
}
case GREATER: {
if (in->args.length < 3) {
runtimeError(TOO_FEW_ARGS, "Expecting 3 args", in, currentInstruction);
@@ -695,27 +824,6 @@ void interpretGroundInstruction(GroundInstruction inst, GroundScope* scope) {
}
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);
}
}
freeGroundInstruction(in);

View File

@@ -1,5 +1,6 @@
#include "types.h"
#include <inttypes.h>
#include <stdlib.h>
GroundValue createIntGroundValue(int64_t in) {
GroundValue gv;
@@ -309,3 +310,56 @@ void printGroundInstruction(GroundInstruction* gi) {
printf(" ");
}
}
List createList() {
List list;
list.size = 0;
list.values = malloc(sizeof(GroundValue));
return list;
}
void appendToList(List* list, GroundValue value) {
if (list == NULL) {
printf("Expecting a List ptr, got a null pointer instead.\nThis is likely not an error with your Ground program.\nPlease report this issue to https://chsp.au/ground/cground\n");
exit(EXIT_FAILURE);
}
GroundValue* ptr = realloc(list, (list->size + 1) * sizeof(GroundValue));
if (ptr == NULL) {
printf("There was an error allocating memory for a list.\nThis is likely not an error with your Ground program.\nPlease report this issue to https://chsp.au/ground/cground\n");
exit(EXIT_FAILURE);
}
list->size++;
list->values = ptr;
list->values[list->size - 1] = value;
}
ListAccess getListAt(List* list, int idx) {
if (list == NULL) {
printf("Expecting a List ptr, got a null pointer instead.\nThis is likely not an error with your Ground program.\nPlease report this issue to https://chsp.au/ground/cground\n");
exit(EXIT_FAILURE);
}
if (idx < list->size) {
ListAccess retval;
retval.value = &list->values[idx];
retval.status = LIST_OKAY;
return retval;
} else {
ListAccess retval;
retval.value = NULL;
retval.status = LIST_OUT_OF_BOUNDS;
return retval;
}
}
ListAccessStatus setListAt(List* list, int idx, GroundValue value) {
if (list == NULL) {
printf("Expecting a List ptr, got a null pointer instead.\nThis is likely not an error with your Ground program.\nPlease report this issue to https://chsp.au/ground/cground\n");
exit(EXIT_FAILURE);
}
if (idx < list->size) {
list->values[idx] = value;
return LIST_OKAY;
} else {
return LIST_OUT_OF_BOUNDS;
}
}

View File

@@ -19,6 +19,10 @@ typedef enum GroundArgType {
VALUE, VALREF, DIRREF, LINEREF, LABEL, FNREF, TYPEREF
} GroundArgType;
typedef enum ListAccessStatus {
LIST_OKAY, LIST_OUT_OF_BOUNDS, LIST_FIXME
} ListAccessStatus;
struct GroundValue;
struct List;
@@ -43,14 +47,25 @@ typedef struct GroundValue {
} GroundValue;
/*
* Currently unused. Max, implement this sometime soon.
* Custom data type that stores Ground values.
* Associated functions:
* createList(), appendToList(), getListAt(), setListAt()
*/
typedef struct List {
size_t size;
size_t capacity;
GroundValue* values;
} List;
/*
* Indicates status when accessing a list.
* Associated functions:
* getListAt()
*/
typedef struct ListAccess {
ListAccessStatus status;
GroundValue* value;
} ListAccess;
/*
* Stores arguments for the GroundInstruction struct.
* Associated functions:
@@ -125,4 +140,17 @@ void addArgToInstruction(GroundInstruction* gi, GroundArg arg);
// Prints out a GroundInstruction.
void printGroundInstruction(GroundInstruction* gi);
// Creates a Ground list
List createList();
// Add item (value) to List (list)
void appendToList(List* list, GroundValue value);
// Gets item at index (idx) from list (list). If there is an error, it
// will be indicated in the status field.
ListAccess getListAt(List* list, int idx);
// Sets an item in list (list) at index (idx) to GroundValue (value).
ListAccessStatus setListAt(List* list, int idx, GroundValue value);
#endif