2026-04-11 16:06:34 +10:00
# include "list.h"
# include <groundext.h>
# include <groundvm.h>
# include <stdbool.h>
# include <stdint.h>
# include <stdio.h>
# include <stdlib.h>
# include <string.h>
const uint8_t STARTING_ELEMENTS = 2 ;
GroundValue appendToListStruct ( GroundScope * scope , List args ) {
GroundValue newValue = args . values [ 0 ] ;
// grab fields we need from struct
GroundVariable * sizeField = groundFindVariable ( scope , " size " ) ;
if ( sizeField = = NULL ) {
ERROR ( " A field called \" size \" was not found " , " FieldNotFound " ) ;
}
GroundVariable * memSizeField = groundFindVariable ( scope , " memSize " ) ;
if ( memSizeField = = NULL ) {
ERROR ( " A field called \" memSize \" was not found " , " FieldNotFound " ) ;
}
2026-04-11 19:47:12 +10:00
GroundVariable * ptrField = groundFindVariable ( scope , " private_ptr " ) ;
2026-04-11 16:06:34 +10:00
if ( ptrField = = NULL ) {
2026-04-11 19:47:12 +10:00
ERROR ( " A field called \" private_ptr \" was not found " , " FieldNotFound " ) ;
2026-04-11 16:06:34 +10:00
}
GroundValue * items = ( GroundValue * ) ptrField - > value . data . intVal ;
GroundVariable * capacityField = groundFindVariable ( scope , " capacity " ) ;
2026-04-11 17:04:54 +10:00
if ( capacityField = = NULL ) {
2026-04-11 16:06:34 +10:00
ERROR ( " A field called \" capacity \" was not found " , " FieldNotFound " ) ;
}
int64_t capacity = capacityField - > value . data . intVal ;
sizeField - > value . data . intVal + + ;
if ( capacity < = sizeField - > value . data . intVal ) {
capacity * = 2 ;
capacityField - > value . data . intVal = capacity ;
uint64_t newSize = sizeof ( GroundValue ) * capacity ;
memSizeField - > value . data . intVal = newSize ;
items = realloc ( items , newSize ) ;
if ( items = = NULL ) {
ERROR ( " Failed to allocate memory when increasing list size! " , " MemoryAllocationFailed " ) ;
}
2026-04-11 17:04:54 +10:00
ptrField - > value . data . intVal = ( int64_t ) items ;
2026-04-11 16:06:34 +10:00
}
items [ sizeField - > value . data . intVal - 1 ] = newValue ;
return groundCreateValue ( INT , 0 ) ;
}
GroundValue listStructAt ( GroundScope * scope , List args ) {
uint64_t index = args . values [ 0 ] . data . intVal ;
if ( index < 0 ) {
ERROR ( " Attempt to access list at negative index " , " OutOfBounds " ) ;
}
GroundVariable * sizeField = groundFindVariable ( scope , " size " ) ;
if ( sizeField = = NULL ) {
ERROR ( " A field called \" size \" was not found " , " FieldNotFound " ) ;
}
2026-04-11 17:04:54 +10:00
int64_t size = sizeField - > value . data . intVal ;
2026-04-11 16:06:34 +10:00
if ( index > = size ) {
char buffer [ 512 ] ;
sprintf ( buffer , " Attempt to access list at index %ld when list is of length %ld " , index , size ) ;
ERROR ( buffer , " OutOfBounds " ) ;
}
2026-04-11 19:47:12 +10:00
GroundVariable * ptrField = groundFindVariable ( scope , " private_ptr " ) ;
2026-04-11 16:06:34 +10:00
if ( ptrField = = NULL ) {
2026-04-11 19:47:12 +10:00
ERROR ( " A field called \" private_ptr \" was not found " , " FieldNotFound " ) ;
2026-04-11 16:06:34 +10:00
}
GroundValue * items = ( GroundValue * ) ptrField - > value . data . intVal ;
return items [ index ] ;
}
GroundValue listStructToString ( GroundScope * scope , List args ) {
return groundCreateValue ( STRING , " TODO " ) ;
}
GroundValue clearListStruct ( GroundScope * scope , List args ) {
// grab fields we need from struct
GroundVariable * sizeField = groundFindVariable ( scope , " size " ) ;
if ( sizeField = = NULL ) {
ERROR ( " A field called \" size \" was not found " , " FieldNotFound " ) ;
}
GroundVariable * memSizeField = groundFindVariable ( scope , " memSize " ) ;
if ( memSizeField = = NULL ) {
ERROR ( " A field called \" memSize \" was not found " , " FieldNotFound " ) ;
}
2026-04-11 19:47:12 +10:00
GroundVariable * ptrField = groundFindVariable ( scope , " private_ptr " ) ;
2026-04-11 16:06:34 +10:00
if ( ptrField = = NULL ) {
2026-04-11 19:47:12 +10:00
ERROR ( " A field called \" private_ptr \" was not found " , " FieldNotFound " ) ;
2026-04-11 16:06:34 +10:00
}
GroundVariable * capacityField = groundFindVariable ( scope , " capacity " ) ;
2026-04-11 17:04:54 +10:00
if ( capacityField = = NULL ) {
2026-04-11 16:06:34 +10:00
ERROR ( " A field called \" capacity \" was not found " , " FieldNotFound " ) ;
}
2026-04-11 19:47:12 +10:00
GroundValue * newBuffer = calloc ( STARTING_ELEMENTS , sizeof ( GroundValue ) ) ;
if ( newBuffer = = NULL ) {
ERROR ( " Failed to allocate memory when clearing list! " , " MemoryAllocationFailed " ) ;
}
2026-04-11 16:06:34 +10:00
sizeField - > value . data . intVal = 0 ;
2026-04-11 19:47:12 +10:00
ptrField - > value . data . intVal = ( int64_t ) newBuffer ;
2026-04-11 16:06:34 +10:00
capacityField - > value . data . intVal = STARTING_ELEMENTS ;
memSizeField - > value . data . intVal = sizeof ( GroundValue ) * STARTING_ELEMENTS ;
return groundCreateValue ( INT , 0 ) ;
}
GroundValue insertIntoListStruct ( GroundScope * scope , List args ) {
GroundValue value = args . values [ 0 ] ;
uint64_t index = args . values [ 1 ] . data . intVal ;
if ( index < 0 ) {
ERROR ( " Attempt to insert element into list at negative index " , " OutOfBounds " ) ;
}
// grab fields we need from struct
GroundVariable * sizeField = groundFindVariable ( scope , " size " ) ;
if ( sizeField = = NULL ) {
ERROR ( " A field called \" size \" was not found " , " FieldNotFound " ) ;
}
GroundVariable * memSizeField = groundFindVariable ( scope , " memSize " ) ;
if ( memSizeField = = NULL ) {
ERROR ( " A field called \" memSize \" was not found " , " FieldNotFound " ) ;
}
2026-04-11 19:47:12 +10:00
GroundVariable * ptrField = groundFindVariable ( scope , " private_ptr " ) ;
2026-04-11 16:06:34 +10:00
if ( ptrField = = NULL ) {
2026-04-11 19:47:12 +10:00
ERROR ( " A field called \" private_ptr \" was not found " , " FieldNotFound " ) ;
2026-04-11 16:06:34 +10:00
}
GroundValue * items = ( GroundValue * ) ptrField - > value . data . intVal ;
GroundVariable * capacityField = groundFindVariable ( scope , " capacity " ) ;
2026-04-11 17:04:54 +10:00
if ( capacityField = = NULL ) {
2026-04-11 16:06:34 +10:00
ERROR ( " A field called \" capacity \" was not found " , " FieldNotFound " ) ;
}
int64_t capacity = capacityField - > value . data . intVal ;
if ( sizeField - > value . data . intVal < = index ) {
sizeField - > value . data . intVal = index + 1 ;
} else {
sizeField - > value . data . intVal + + ;
}
// check if we have enough space to insert the element
if ( capacity < = sizeField - > value . data . intVal + 1 ) {
// not enough space, double size
capacity = sizeField - > value . data . intVal + 1 ;
capacityField - > value . data . intVal = capacity ;
}
// allocate new buffer
GroundValue * newBuffer = calloc ( capacity , sizeof ( GroundValue ) ) ;
if ( newBuffer = = NULL ) {
ERROR ( " Failed to allocate memory when increasing list size! " , " MemoryAllocationFailed " ) ;
}
2026-04-11 17:04:54 +10:00
ptrField - > value . data . intVal = ( int64_t ) newBuffer ;
memSizeField - > value . data . intVal = sizeof ( GroundValue ) * capacity ;
2026-04-11 16:06:34 +10:00
// copy elements from 0 to i-1 into new buffer
memcpy ( newBuffer , items , sizeof ( GroundValue ) * index ) ;
// insert element at i
newBuffer [ index ] = value ;
// copy elements 0 to i+1 into new buffer
memcpy ( newBuffer + ( index + 1 ) , items + index , sizeof ( GroundValue ) * ( sizeField - > value . data . intVal - index ) ) ;
// free older buffer
free ( items ) ;
// retur null
return groundCreateValue ( INT , 0 ) ;
}
GroundValue listStructDelete ( GroundScope * scope , List args ) {
uint64_t index = args . values [ 0 ] . data . intVal ;
if ( index < 0 ) {
ERROR ( " Attempt to remove element into list at negative index " , " OutOfBounds " ) ;
}
// grab fields we need from struct
GroundVariable * sizeField = groundFindVariable ( scope , " size " ) ;
if ( sizeField = = NULL ) {
ERROR ( " A field called \" size \" was not found " , " FieldNotFound " ) ;
}
GroundVariable * memSizeField = groundFindVariable ( scope , " memSize " ) ;
if ( memSizeField = = NULL ) {
ERROR ( " A field called \" memSize \" was not found " , " FieldNotFound " ) ;
}
2026-04-11 19:47:12 +10:00
GroundVariable * ptrField = groundFindVariable ( scope , " private_ptr " ) ;
2026-04-11 16:06:34 +10:00
if ( ptrField = = NULL ) {
2026-04-11 19:47:12 +10:00
ERROR ( " A field called \" private_ptr \" was not found " , " FieldNotFound " ) ;
2026-04-11 16:06:34 +10:00
}
GroundValue * items = ( GroundValue * ) ptrField - > value . data . intVal ;
GroundVariable * capacityField = groundFindVariable ( scope , " capacity " ) ;
2026-04-11 17:04:54 +10:00
if ( capacityField = = NULL ) {
2026-04-11 16:06:34 +10:00
ERROR ( " A field called \" capacity \" was not found " , " FieldNotFound " ) ;
}
int64_t capacity = capacityField - > value . data . intVal ;
printf ( " size = %ld, index = %ld \n " , sizeField - > value . data . intVal , index ) ;
if ( sizeField - > value . data . intVal < index ) {
char buffer [ 512 ] ;
sprintf ( buffer , " Attempt to delete element at index %ld when list is of size %ld " , index , sizeField - > value . data . intVal ) ;
ERROR ( buffer , " OutOfBounds " ) ;
} else {
sizeField - > value . data . intVal - - ;
}
int64_t size = sizeField - > value . data . intVal ;
// check if we have enough space to insert the element
if ( capacity > size + 1 ) {
// too much space, make list smaller
capacity = size + 1 ;
capacityField - > value . data . intVal = capacity ;
}
// allocate new buffer
GroundValue * newBuffer = calloc ( capacity , sizeof ( GroundValue ) ) ;
if ( newBuffer = = NULL ) {
ERROR ( " Failed to allocate memory when decreasing list size! " , " MemoryAllocationFailed " ) ;
}
2026-04-11 17:04:54 +10:00
ptrField - > value . data . intVal = ( int64_t ) newBuffer ;
memSizeField - > value . data . intVal = sizeof ( GroundValue ) * capacity ;
2026-04-11 16:06:34 +10:00
2026-04-11 17:04:54 +10:00
// copy elements from 0 to i-1 into new buffer
2026-04-11 16:06:34 +10:00
if ( index > 0 )
memcpy ( newBuffer , items , sizeof ( GroundValue ) * index ) ;
// copy elements 0 to i+1 into new buffer
if ( index < size )
memcpy ( newBuffer + index , items + index + 1 , sizeof ( GroundValue ) * ( size - index ) ) ;
// free older buffer
free ( items ) ;
// retur null
return groundCreateValue ( INT , 0 ) ;
}
GroundValue listStructSet ( GroundScope * scope , List args ) {
GroundValue value = args . values [ 0 ] ;
uint64_t index = args . values [ 1 ] . data . intVal ;
if ( index < 0 ) {
ERROR ( " Attempt to set element in list at negative index " , " OutOfBounds " ) ;
}
GroundVariable * sizeField = groundFindVariable ( scope , " size " ) ;
if ( sizeField = = NULL ) {
ERROR ( " A field called \" size \" was not found " , " FieldNotFound " ) ;
}
int64_t size = sizeField - > value . data . intVal ;
2026-04-11 19:47:12 +10:00
GroundVariable * ptrField = groundFindVariable ( scope , " private_ptr " ) ;
2026-04-11 16:06:34 +10:00
if ( ptrField = = NULL ) {
2026-04-11 19:47:12 +10:00
ERROR ( " A field called \" private_ptr \" was not found " , " FieldNotFound " ) ;
2026-04-11 16:06:34 +10:00
}
GroundValue * items = ( GroundValue * ) ptrField - > value . data . intVal ;
if ( index > = size ) {
insertIntoListStruct ( scope , args ) ;
} else {
items [ index ] = value ;
}
return groundCreateValue ( INT , 0 ) ;
}
GroundValue listStructIsEmpty ( GroundScope * scope , List args ) {
GroundVariable * sizeField = groundFindVariable ( scope , " size " ) ;
if ( sizeField = = NULL ) {
ERROR ( " A field called \" size \" was not found " , " FieldNotFound " ) ;
}
int64_t size = sizeField - > value . data . intVal ;
return groundCreateValue ( BOOL , size < = 0 ) ;
}
bool areGroundValuesEqual ( GroundValue a , GroundValue b ) {
if ( a . type ! = b . type ) {
if ( a . type = = INT & & b . type = = DOUBLE ) {
return a . data . intVal = = b . data . doubleVal ;
} else if ( a . type = = DOUBLE & & b . type = = INT ) {
return a . data . doubleVal = = b . data . intVal ;
}
} else {
switch ( a . type ) {
case INT :
return a . data . intVal = = b . data . intVal ;
case DOUBLE :
return a . data . doubleVal = = b . data . doubleVal ;
case BOOL :
return a . data . boolVal = = b . data . boolVal ;
case CHAR :
return a . data . charVal = = b . data . charVal ;
case STRING :
return strcmp ( a . data . stringVal , b . data . stringVal ) = = 0 ;
default :
return false ;
}
}
return false ;
}
GroundValue listStructContains ( GroundScope * scope , List args ) {
GroundValue targetValue = args . values [ 0 ] ;
GroundVariable * sizeField = groundFindVariable ( scope , " size " ) ;
if ( sizeField = = NULL ) {
ERROR ( " A field called \" size \" was not found " , " FieldNotFound " ) ;
}
int64_t size = sizeField - > value . data . intVal ;
2026-04-11 19:47:12 +10:00
GroundVariable * ptrField = groundFindVariable ( scope , " private_ptr " ) ;
2026-04-11 16:06:34 +10:00
if ( ptrField = = NULL ) {
2026-04-11 19:47:12 +10:00
ERROR ( " A field called \" private_ptr \" was not found " , " FieldNotFound " ) ;
2026-04-11 16:06:34 +10:00
}
GroundValue * items = ( GroundValue * ) ptrField - > value . data . intVal ;
for ( uint64_t i = 0 ; i < size ; i + + ) {
if ( areGroundValuesEqual ( items [ i ] , targetValue ) ) {
return groundCreateValue ( BOOL , true ) ;
}
}
return groundCreateValue ( BOOL , false ) ;
}
GroundValue reverseListStruct ( GroundScope * scope , List args ) {
2026-04-11 17:04:54 +10:00
GroundVariable * sizeField = groundFindVariable ( scope , " size " ) ;
if ( sizeField = = NULL ) {
ERROR ( " A field called \" size \" was not found " , " FieldNotFound " ) ;
}
int64_t size = sizeField - > value . data . intVal ;
GroundVariable * capacityField = groundFindVariable ( scope , " capacity " ) ;
if ( capacityField = = NULL ) {
ERROR ( " A field called \" capacity \" was not found " , " FieldNotFound " ) ;
}
int64_t capacity = capacityField - > value . data . intVal ;
2026-04-11 19:47:12 +10:00
GroundVariable * ptrField = groundFindVariable ( scope , " private_ptr " ) ;
2026-04-11 17:04:54 +10:00
if ( ptrField = = NULL ) {
2026-04-11 19:47:12 +10:00
ERROR ( " A field called \" private_ptr \" was not found " , " FieldNotFound " ) ;
2026-04-11 17:04:54 +10:00
}
GroundValue * items = ( GroundValue * ) ptrField - > value . data . intVal ;
GroundValue * newBuffer = calloc ( capacity , sizeof ( GroundValue ) ) ;
2026-04-12 07:50:03 +10:00
if ( newBuffer = = NULL ) {
ERROR ( " Failed to allocate memory when reversing list! " , " MemoryAllocationFailed " ) ;
}
2026-04-11 17:04:54 +10:00
int z = 0 ;
for ( int i = size - 1 ; i > = 0 ; i - - , z + + ) {
newBuffer [ z ] = items [ i ] ;
}
ptrField - > value . data . intVal = ( int64_t ) newBuffer ;
free ( items ) ;
2026-04-11 16:06:34 +10:00
return groundCreateValue ( INT , 0 ) ;
}
2026-04-11 17:04:54 +10:00
GroundValue findListStruct ( GroundScope * scope , List args ) {
GroundValue targetValue = args . values [ 0 ] ;
GroundVariable * sizeField = groundFindVariable ( scope , " size " ) ;
if ( sizeField = = NULL ) {
ERROR ( " A field called \" size \" was not found " , " FieldNotFound " ) ;
}
int64_t size = sizeField - > value . data . intVal ;
2026-04-11 19:47:12 +10:00
GroundVariable * ptrField = groundFindVariable ( scope , " private_ptr " ) ;
2026-04-11 17:04:54 +10:00
if ( ptrField = = NULL ) {
2026-04-11 19:47:12 +10:00
ERROR ( " A field called \" private_ptr \" was not found " , " FieldNotFound " ) ;
2026-04-11 17:04:54 +10:00
}
GroundValue * items = ( GroundValue * ) ptrField - > value . data . intVal ;
for ( uint64_t i = 0 ; i < size ; i + + ) {
if ( areGroundValuesEqual ( items [ i ] , targetValue ) ) {
return groundCreateValue ( INT , i ) ;
}
}
return groundCreateValue ( INT , ( int64_t ) - 1 ) ;
}
GroundValue reserveListStruct ( GroundScope * scope , List args ) {
int64_t amount = args . values [ 0 ] . data . intVal ;
GroundVariable * capacityField = groundFindVariable ( scope , " capacity " ) ;
if ( capacityField = = NULL ) {
ERROR ( " A field called \" capacity \" was not found " , " FieldNotFound " ) ;
}
int64_t capacity = capacityField - > value . data . intVal ;
2026-04-11 19:47:12 +10:00
GroundVariable * ptrField = groundFindVariable ( scope , " private_ptr " ) ;
2026-04-11 17:04:54 +10:00
if ( ptrField = = NULL ) {
2026-04-11 19:47:12 +10:00
ERROR ( " A field called \" private_ptr \" was not found " , " FieldNotFound " ) ;
2026-04-11 17:04:54 +10:00
}
GroundValue * items = ( GroundValue * ) ptrField - > value . data . intVal ;
GroundVariable * memSizeField = groundFindVariable ( scope , " memSize " ) ;
if ( memSizeField = = NULL ) {
ERROR ( " A field called \" memSize \" was not found " , " FieldNotFound " ) ;
}
if ( capacity > amount ) {
return groundCreateValue ( BOOL , false ) ;
}
capacityField - > value . data . intVal = amount ;
items = realloc ( items , sizeof ( GroundValue ) * amount ) ;
if ( items = = NULL ) {
ERROR ( " Failed to allocate memory when reserving list space! " , " MemoryAllocationFailed " ) ;
}
memSizeField - > value . data . intVal = sizeof ( GroundValue ) * amount ;
return groundCreateValue ( BOOL , true ) ;
}
2026-04-11 16:06:34 +10:00
GroundValue createListStruct ( ) {
GroundStruct listStruct = groundCreateStruct ( ) ;
GroundValue * items = calloc ( STARTING_ELEMENTS , sizeof ( GroundValue ) ) ;
groundAddFieldToStruct ( & listStruct , " size " , groundCreateValue ( INT , 0 ) ) ; // number of elements
groundAddFieldToStruct ( & listStruct , " memSize " , groundCreateValue ( INT , sizeof ( GroundValue ) * STARTING_ELEMENTS ) ) ; // number of bytes allocated
groundAddFieldToStruct ( & listStruct , " capacity " , groundCreateValue ( INT , STARTING_ELEMENTS ) ) ; // number of elements that can fit in the currently allocated space
2026-04-11 19:47:12 +10:00
groundAddFieldToStruct ( & listStruct , " private_ptr " , groundCreateValue ( INT , items ) ) ; // pointer to internal list struct
2026-04-11 16:06:34 +10:00
2026-04-11 19:47:12 +10:00
groundAddFunctionToStruct ( & listStruct , " append " , appendToListStruct , INT , 1 , ANY , " value " ) ; // append item to end of list
groundAddFunctionToStruct ( & listStruct , " insert " , insertIntoListStruct , INT , 2 , ANY , " value " , INT , " index " ) ; // insert value at index
groundAddFunctionToStruct ( & listStruct , " remove " , listStructDelete , INT , 1 , INT , " index " ) ; // delete value at index
2026-04-11 19:57:35 +10:00
groundAddFunctionToStruct ( & listStruct , " at " , listStructAt , ANY , 1 , INT , " index " ) ; // get value at index
2026-04-11 16:06:34 +10:00
groundAddFunctionToStruct ( & listStruct , " clear " , clearListStruct , INT , 0 ) ; // clear list
2026-04-11 19:47:12 +10:00
groundAddFunctionToStruct ( & listStruct , " set " , listStructSet , INT , 2 , ANY , " value " , INT , " index " ) ; // replace a value at an index
2026-04-11 16:06:34 +10:00
groundAddFunctionToStruct ( & listStruct , " isEmpty " , listStructIsEmpty , BOOL , 0 ) ; // returns true if list is empty, otherwise false
2026-04-11 19:47:12 +10:00
groundAddFunctionToStruct ( & listStruct , " contains " , listStructContains , BOOL , 1 , ANY , " value " ) ; // returns true if value is in list
2026-04-11 17:04:54 +10:00
groundAddFunctionToStruct ( & listStruct , " reverse " , reverseListStruct , INT , 0 ) ; // return list struct in reverse order
2026-04-11 19:47:12 +10:00
groundAddFunctionToStruct ( & listStruct , " find " , findListStruct , INT , 1 , ANY , " value " ) ; // return index of value in list, if not found, returns -1
groundAddFunctionToStruct ( & listStruct , " reserve " , reserveListStruct , BOOL , 1 , INT , " amount " ) ; // ensure list capacity >= amount. returns true if the list's capacity was expanded
2026-04-11 16:06:34 +10:00
return groundCreateValue ( STRUCTVAL , listStruct ) ;
}