List stuff
This commit is contained in:
@@ -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);
|
||||
|
||||
54
src/types.c
54
src/types.c
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
32
src/types.h
32
src/types.h
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user