#include <stdio.h> #include "heap.h" void * heap_alloc_alligned ( Heap * heap, size_t len, size_t align ) { size_t pos = (size_t) heap -> next; size_t rem = pos % align; if ( rem ) heap -> next = heap -> next + align - rem; if ( heap -> next + len >= heap -> end ) return NULL; void * ret = heap -> next; heap -> next += len; return ret; } void * heap_alloc ( Heap * heap, size_t len ) { size_t pos = (size_t) heap -> next; size_t rem = pos % 8; if ( rem ) heap -> next = heap -> next + 8 - rem; if ( heap -> next + len >= heap -> end ) return NULL; void * ret = heap -> next; heap -> next += len; return ret; } void heap_init ( Heap * heap, size_t heap_size ) { heap -> begin = (u8*) malloc ( heap_size ); heap -> next = heap -> begin; heap -> end = heap -> begin + heap_size; } void heap_destroy ( Heap * heap ) { free ( heap -> begin ); } int compare_entry ( const void * a, const void * b ) { return str_cmp ( ((SimpleEntry*) a) -> name, ((SimpleEntry*) b) -> name ); } bool value_to_bool ( Value * value ) { if ( value -> kind == VALUE_NULL ) return false; if ( value -> kind == VALUE_BOOLEAN ) return ((BoolValue*) value ) -> boolean; return true; } Value * try_operator ( Heap * heap, Value * object, Value ** arguments, size_t argc, Str * name ) { switch ( object -> kind ) { case VALUE_INTEGER: { if ( argc != 1 ) { fprintf ( stderr, "Invalid argument count for integer operation %.*s.\n", (int) name -> len, name -> str ); exit ( 10 ); } IntValue * this = (IntValue*) object; bool is_int = arguments [ 0 ] -> kind == VALUE_INTEGER; if ( is_int ) { IntValue * other = (IntValue*) arguments [ 0 ]; if ( str_eq ( *name, STR ("+") ) ) return make_int ( heap, this -> integer + other -> integer ); if ( str_eq ( *name, STR ("-") ) ) return make_int ( heap, this -> integer - other -> integer ); if ( str_eq ( *name, STR ("*") ) ) return make_int ( heap, this -> integer * other -> integer ); if ( str_eq ( *name, STR ("/") ) ) return make_int ( heap, this -> integer / other -> integer ); if ( str_eq ( *name, STR ("%") ) ) return make_int ( heap, this -> integer % other -> integer ); if ( str_eq ( *name, STR ("<=") ) ) return make_bool ( heap, this -> integer <= other -> integer ); if ( str_eq ( *name, STR (">=") ) ) return make_bool ( heap, this -> integer >= other -> integer ); if ( str_eq ( *name, STR ("<") ) ) return make_bool ( heap, this -> integer < other -> integer ); if ( str_eq ( *name, STR (">") ) ) return make_bool ( heap, this -> integer > other -> integer ); if ( str_eq ( *name, STR ("==") ) ) return make_bool ( heap, this -> integer == other -> integer ); if ( str_eq ( *name, STR ("!=") ) ) return make_bool ( heap, this -> integer != other -> integer ); break; } if ( str_eq ( *name, STR ("==") ) ) return make_bool ( heap, false ); if ( str_eq ( *name, STR ("!=") ) ) return make_bool ( heap, true ); break; } case VALUE_BOOLEAN: { if ( argc != 1 ) { fprintf ( stderr, "Invalid argument count for bool operation %.*s.\n", (int) name -> len, name -> str ); exit ( 10 ); } BoolValue * this = (BoolValue*) object; bool is_bool = arguments [ 0 ] -> kind == VALUE_BOOLEAN; if ( is_bool ) { BoolValue * other = (BoolValue*) arguments [ 0 ]; if ( str_eq ( *name, STR ("&") ) ) return make_bool ( heap, this -> boolean & other -> boolean ); if ( str_eq ( *name, STR ("|") ) ) return make_bool ( heap, this -> boolean | other -> boolean ); if ( str_eq ( *name, STR ("==") ) ) return make_bool ( heap, this -> boolean == other -> boolean ); if ( str_eq ( *name, STR ("!=") ) ) return make_bool ( heap, this -> boolean != other -> boolean ); break; } if ( str_eq ( *name, STR ("==") ) ) return make_bool ( heap, false ); if ( str_eq ( *name, STR ("!=") ) ) return make_bool ( heap, true ); break; } case VALUE_NULL: { if ( argc != 1 ) { fprintf ( stderr, "Invalid amount of arguments for null operation %.*s.\n", (int) name -> len, name -> str ); exit ( 10 ); } if ( str_eq ( *name, STR ("==") ) ) return make_bool ( heap, arguments [ 0 ] -> kind == VALUE_NULL ? true : false ); if ( str_eq ( *name, STR ("!=") ) ) return make_bool ( heap, arguments [ 0 ] -> kind != VALUE_NULL ? true : false ); break; } case VALUE_ARRAY: if ( str_eq ( *name, STR ("get") ) ) { if ( argc != 1 || arguments [ 0 ] -> kind != VALUE_INTEGER ) { fprintf ( stderr, "Invalid argument for array get.\n" ); exit ( 11 ); } ArrayValue * array = (ArrayValue*) object; i32 index = ((IntValue*) arguments [ 0 ]) -> integer; if ( index < 0 || index >= array -> length ) { fprintf ( stderr, "Index is out of bounds.\n" ); exit ( 11 ); } return array -> elements [ index ]; } if ( str_eq ( *name, STR ("set") ) ) { if ( argc != 2 || arguments [ 0 ] -> kind != VALUE_INTEGER ) { fprintf ( stderr, "Invalid arguments for array set.\n" ); exit ( 12 ); } ArrayValue * array = (ArrayValue*) object; i32 index = ((IntValue*) arguments [ 0 ]) -> integer; if ( index < 0 || index >= array -> length ) { fprintf ( stderr, "Index is out of bounds.\n" ); exit ( 12 ); } array -> elements [ index ] = arguments [ 1 ]; return arguments [ 1 ]; } break; default: break; } return NULL; } Value * get_base ( Value * object ) { Value * curr = object; while ( curr -> kind == VALUE_OBJECT ) curr = ((ObjectValue *) curr) -> extends; return curr; } Value ** get_object_field ( Value * object, Str name ) { Value * next = object; ObjectValue * curr; do { curr = (ObjectValue*) next; for ( size_t i = 0; i < curr -> member_cnt; ++i ) if ( str_eq ( curr -> members [ i ] . name, name ) ) return & curr -> members [ i ] . value; next = curr -> extends; } while ( next -> kind == VALUE_OBJECT ); return NULL; } Value * find_current_object_field ( Value * object, Str name ) { ObjectValue * curr = (ObjectValue*) object; for ( size_t i = 0; i < curr -> member_cnt; ++i ) if ( str_eq ( curr -> members [ i ] . name, name ) ) return curr -> members [ i ] . value; return NULL; } Value * make_int ( Heap * heap, i32 val ) { IntValue * value = heap_alloc ( heap, sizeof (IntValue) ); *value = (IntValue) { .kind = (Value) { .kind = VALUE_INTEGER }, .integer = val }; return (Value*) value; } Value * make_bool ( Heap * heap, bool val ) { BoolValue * value = heap_alloc ( heap, sizeof (BoolValue) ); *value = (BoolValue) { .kind = (Value) { .kind = VALUE_BOOLEAN }, .boolean = val }; return (Value*) value; } Value * make_function ( Heap * heap, AstFunction * function ) { FunctionValue * value = heap_alloc ( heap, sizeof (FunctionValue) ); *value = (FunctionValue) { .kind = (Value) { .kind = VALUE_FUNCTION }, .function = function }; return (Value*) value; } Value * make_cfunction ( Heap * heap, ConstantFunction function ) { CFunctionValue * value = heap_alloc ( heap, sizeof (CFunctionValue) ); *value = (CFunctionValue) { .kind = (Value) { .kind = VALUE_FUNCTION }, .function = function }; return (Value*) value; } Value * make_array ( Heap * heap, size_t len ) { ArrayValue * value = heap_alloc ( heap, sizeof (ArrayValue) + len * sizeof (Value*) ); *value = (ArrayValue) { .kind = (Value) { .kind = VALUE_ARRAY }, .length = len }; return (Value*) value; } Value * make_object ( Heap * heap, size_t member_cnt ) { ObjectValue * value = heap_alloc ( heap, sizeof (ObjectValue) + member_cnt * sizeof (SimpleEntry) ); *value = (ObjectValue) { .kind = (Value) { .kind = VALUE_OBJECT }, .member_cnt = member_cnt }; return (Value*) value; } Value * make_null ( Heap * heap ) { NullValue * value = heap_alloc ( heap, sizeof (NullValue) ); *value = (NullValue) { .kind = (Value) { .kind = VALUE_NULL } }; return (Value*) value; }