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