Skip to content
Snippets Groups Projects
heap.c 8.3 KiB
Newer Older
#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;
}