2025-11-23 13:37:08 +11:00
# include "types.h"
2025-11-23 18:34:30 +11:00
# include <inttypes.h>
2025-11-28 09:23:43 +11:00
# include <stdlib.h>
2025-11-23 13:37:08 +11:00
GroundValue createIntGroundValue ( int64_t in ) {
GroundValue gv ;
gv . data . intVal = in ;
gv . type = INT ;
return gv ;
}
GroundValue createDoubleGroundValue ( double in ) {
GroundValue gv ;
gv . data . doubleVal = in ;
gv . type = DOUBLE ;
return gv ;
}
GroundValue createStringGroundValue ( const char * in ) {
GroundValue gv ;
gv . data . stringVal = strdup ( in ) ;
gv . type = STRING ;
return gv ;
}
GroundValue createCharGroundValue ( char in ) {
GroundValue gv ;
gv . data . charVal = in ;
gv . type = CHAR ;
return gv ;
}
GroundValue createBoolGroundValue ( bool in ) {
GroundValue gv ;
gv . data . boolVal = in ;
gv . type = BOOL ;
return gv ;
}
2025-12-01 10:15:37 +11:00
GroundValue createListGroundValue ( List in ) {
GroundValue gv ;
gv . data . listVal = in ;
gv . type = LIST ;
return gv ;
}
2025-12-06 11:50:42 +11:00
GroundValue createFunctionGroundValue ( GroundFunction * in ) {
GroundValue gv ;
gv . data . fnVal = in ;
gv . type = FUNCTION ;
return gv ;
}
2025-12-01 10:36:09 +11:00
2025-12-06 14:35:13 +11:00
GroundValue createNoneGroundValue ( ) {
GroundValue gv ;
gv . type = NONE ;
return gv ;
}
2025-12-01 10:36:09 +11:00
GroundValue copyGroundValue ( const GroundValue * gv ) {
GroundValue newGv ;
newGv . type = gv - > type ;
switch ( gv - > type ) {
case INT : newGv . data . intVal = gv - > data . intVal ; break ;
case DOUBLE : newGv . data . doubleVal = gv - > data . doubleVal ; break ;
case CHAR : newGv . data . charVal = gv - > data . charVal ; break ;
case BOOL : newGv . data . boolVal = gv - > data . boolVal ; break ;
case STRING :
if ( gv - > data . stringVal ! = NULL ) {
newGv . data . stringVal = strdup ( gv - > data . stringVal ) ;
} else {
newGv . data . stringVal = NULL ;
}
break ;
case LIST : {
List newList = createList ( ) ;
for ( int i = 0 ; i < gv - > data . listVal . size ; i + + ) {
// Recursive call to handle nested lists and other types
appendToList ( & newList , copyGroundValue ( & gv - > data . listVal . values [ i ] ) ) ;
}
newGv . data . listVal = newList ;
break ;
}
2025-12-06 11:50:42 +11:00
case FUNCTION : newGv . data . fnVal = gv - > data . fnVal ; break ;
2025-12-01 10:36:09 +11:00
case CUSTOM :
newGv . data . customVal = gv - > data . customVal ; // Shallow copy for custom
break ;
}
return newGv ;
}
2025-11-23 18:34:30 +11:00
void printGroundValue ( GroundValue * gv ) {
switch ( gv - > type ) {
case INT : {
printf ( " % " PRId64 " " , gv - > data . intVal ) ;
break ;
}
case DOUBLE : {
printf ( " %f " , gv - > data . doubleVal ) ;
break ;
}
case STRING : {
printf ( " %s " , gv - > data . stringVal ) ;
break ;
}
case CHAR : {
printf ( " %c " , gv - > data . charVal ) ;
break ;
}
case BOOL : {
if ( gv - > data . boolVal ) {
printf ( " true " ) ;
} else {
printf ( " false " ) ;
}
break ;
}
2025-12-01 10:36:09 +11:00
case LIST : {
printf ( " [ " ) ;
for ( int i = 0 ; i < gv - > data . listVal . size ; i + + ) {
printGroundValue ( & gv - > data . listVal . values [ i ] ) ;
if ( i < gv - > data . listVal . size - 1 ) {
printf ( " , " ) ;
}
}
printf ( " ] " ) ;
break ;
}
2025-11-23 18:34:30 +11:00
default : {
printf ( " FIXME " ) ;
break ;
}
}
}
2025-11-23 13:37:08 +11:00
void freeGroundValue ( GroundValue * gv ) {
if ( gv - > type = = STRING & & gv - > data . stringVal ! = NULL ) {
free ( gv - > data . stringVal ) ;
2025-12-01 10:36:09 +11:00
gv - > data . stringVal = NULL ;
2025-11-23 13:37:08 +11:00
}
2025-12-01 10:15:37 +11:00
if ( gv - > type = = LIST & & gv - > data . listVal . values ! = NULL ) {
List * list = & gv - > data . listVal ;
for ( int i = 0 ; i < list - > size ; i + + ) {
freeGroundValue ( & list - > values [ i ] ) ;
}
free ( list - > values ) ;
2025-12-01 10:36:09 +11:00
list - > values = NULL ;
gv - > data . listVal = createList ( ) ;
2025-12-01 10:15:37 +11:00
}
2025-11-23 13:37:08 +11:00
}
GroundArg createValueGroundArg ( GroundValue value ) {
GroundArg ga ;
ga . value . value = value ;
ga . type = VALUE ;
return ga ;
}
GroundArg createRefGroundArg ( GroundArgType type , const char * refname ) {
GroundArg ga ;
ga . value . refName = strdup ( refname ) ;
ga . type = type ;
return ga ;
}
void freeGroundArg ( GroundArg * ga ) {
if ( ga - > type = = VALUE ) {
freeGroundValue ( & ga - > value . value ) ;
} else {
free ( ga - > value . refName ) ;
}
}
2025-11-23 18:34:30 +11:00
void printGroundArg ( GroundArg * ga ) {
switch ( ga - > type ) {
case VALUE : {
printGroundValue ( & ga - > value . value ) ;
break ;
}
case DIRREF : {
printf ( " &%s " , ga - > value . refName ) ;
break ;
}
case VALREF : {
printf ( " $%s " , ga - > value . refName ) ;
break ;
}
case LINEREF : {
printf ( " %%%s " , ga - > value . refName ) ;
break ;
}
case LABEL : {
printf ( " @%s " , ga - > value . refName ) ;
break ;
}
case FNREF : {
printf ( " !%s " , ga - > value . refName ) ;
break ;
}
case TYPEREF : {
printf ( " -%s " , ga - > value . refName ) ;
break ;
}
}
}
2025-11-23 13:37:08 +11:00
GroundInstruction createGroundInstruction ( GroundInstType type ) {
GroundInstruction gi ;
gi . type = type ;
gi . args . args = NULL ;
gi . args . length = 0 ;
return gi ;
}
void freeGroundInstruction ( GroundInstruction * gi ) {
for ( size_t i = 0 ; i < gi - > args . length ; i + + ) {
freeGroundArg ( & gi - > args . args [ i ] ) ;
}
2025-11-24 10:15:53 +11:00
free ( gi - > args . args ) ;
2025-11-23 13:37:08 +11:00
}
2025-11-24 10:15:53 +11:00
GroundInstruction copyGroundInstruction ( const GroundInstruction * inst ) {
GroundInstruction newInst ;
newInst . type = inst - > type ;
newInst . args . length = inst - > args . length ;
if ( inst - > args . length > 0 ) {
newInst . args . args = malloc ( inst - > args . length * sizeof ( GroundArg ) ) ;
for ( size_t i = 0 ; i < inst - > args . length ; i + + ) {
newInst . args . args [ i ] . type = inst - > args . args [ i ] . type ;
if ( inst - > args . args [ i ] . type = = VALUE ) {
2025-12-01 10:36:09 +11:00
newInst . args . args [ i ] . value . value = copyGroundValue ( & inst - > args . args [ i ] . value . value ) ;
2025-11-24 10:15:53 +11:00
} else {
newInst . args . args [ i ] . value . refName = strdup ( inst - > args . args [ i ] . value . refName ) ;
}
}
} else {
newInst . args . args = NULL ;
}
return newInst ;
}
2025-11-23 13:37:08 +11:00
void addArgToInstruction ( GroundInstruction * gi , GroundArg arg ) {
gi - > args . length + + ;
GroundArg * newArgs = realloc ( gi - > args . args , gi - > args . length * sizeof ( GroundArg ) ) ;
if ( newArgs = = NULL ) {
perror ( " Failed to allocate memory for instruction argument " ) ;
exit ( EXIT_FAILURE ) ;
}
gi - > args . args = newArgs ;
gi - > args . args [ gi - > args . length - 1 ] = arg ;
}
2025-11-23 18:34:30 +11:00
void printGroundInstruction ( GroundInstruction * gi ) {
switch ( gi - > type ) {
case IF :
printf ( " if " ) ;
break ;
case JUMP :
printf ( " jump " ) ;
break ;
case END :
printf ( " end " ) ;
break ;
case INPUT :
printf ( " input " ) ;
break ;
case PRINT :
printf ( " print " ) ;
break ;
case PRINTLN :
printf ( " println " ) ;
break ;
case SET :
printf ( " set " ) ;
break ;
case GETTYPE :
printf ( " gettype " ) ;
break ;
case EXISTS :
printf ( " exists " ) ;
break ;
case SETLIST :
printf ( " setlist " ) ;
break ;
case SETLISTAT :
printf ( " setlistat " ) ;
break ;
case GETLISTAT :
printf ( " getlistat " ) ;
break ;
case GETLISTSIZE :
printf ( " getlistsize " ) ;
break ;
case LISTAPPEND :
printf ( " listappend " ) ;
break ;
case GETSTRSIZE :
printf ( " getstrsize " ) ;
break ;
case GETSTRCHARAT :
printf ( " getstrcharat " ) ;
break ;
case ADD :
printf ( " add " ) ;
break ;
case SUBTRACT :
printf ( " subtract " ) ;
break ;
case MULTIPLY :
printf ( " multiply " ) ;
break ;
case DIVIDE :
printf ( " divide " ) ;
break ;
case EQUAL :
printf ( " equal " ) ;
break ;
case INEQUAL :
printf ( " inequal " ) ;
break ;
case NOT :
printf ( " not " ) ;
break ;
case GREATER :
printf ( " greater " ) ;
break ;
case LESSER :
printf ( " lesser " ) ;
break ;
case STOI :
printf ( " stoi " ) ;
break ;
case STOD :
printf ( " stod " ) ;
break ;
case TOSTRING :
printf ( " tostring " ) ;
break ;
case FUN :
printf ( " fun " ) ;
break ;
case RETURN :
printf ( " return " ) ;
break ;
case ENDFUN :
printf ( " endfun " ) ;
break ;
case PUSHARG :
printf ( " pusharg " ) ;
break ;
case CALL :
printf ( " call " ) ;
break ;
case STRUCT :
printf ( " struct " ) ;
break ;
case ENDSTRUCT :
printf ( " endstruct " ) ;
break ;
case INIT :
printf ( " init " ) ;
break ;
case USE :
printf ( " use " ) ;
break ;
case EXTERN :
printf ( " extern " ) ;
break ;
case CREATELABEL :
printf ( " createlabel " ) ;
break ;
default :
printf ( " FIXME " ) ;
break ;
}
printf ( " " ) ;
for ( int i = 0 ; i < gi - > args . length ; i + + ) {
printGroundArg ( & gi - > args . args [ i ] ) ;
printf ( " " ) ;
}
}
2025-11-28 09:23:43 +11:00
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. \n This is likely not an error with your Ground program. \n Please report this issue to https://chsp.au/ground/cground \n " ) ;
exit ( EXIT_FAILURE ) ;
}
2025-12-01 10:15:37 +11:00
GroundValue * ptr = realloc ( list - > values , ( list - > size + 1 ) * sizeof ( GroundValue ) ) ;
2025-11-28 09:23:43 +11:00
if ( ptr = = NULL ) {
printf ( " There was an error allocating memory for a list. \n This is likely not an error with your Ground program. \n Please 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. \n This is likely not an error with your Ground program. \n Please 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. \n This is likely not an error with your Ground program. \n Please 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 ;
}
}