#pragma once
#include "parser.h"

typedef enum {
  VALUE_INTEGER,
  VALUE_BOOLEAN,
  VALUE_NULL,
  VALUE_FUNCTION,
  VALUE_ARRAY,
  VALUE_OBJECT,
  VALUE_INVALID
} ValueType;

typedef struct Heap {
  u8 * begin;
  u8 * next;
  u8 * end;
} Heap;

typedef struct Value {
  ValueType kind;
} Value;

typedef struct SimpleEntry {
  Str name;
  Value * value;
} SimpleEntry;

typedef struct NullValue {
  Value kind;
} NullValue;

typedef struct IntValue {
  Value kind;
  i32 integer;
} IntValue;

typedef struct BoolValue {
  Value kind;
  bool boolean;
} BoolValue;

typedef struct FunctionValue {
  Value kind;
  AstFunction * function;
} FunctionValue;

typedef struct ConstantFunction {
  u32 len;
  const u8 * start;
  u16 locals;
  u8 parameters;
} ConstantFunction;

typedef struct CFunctionValue {
  Value kind;
  ConstantFunction function;
} CFunctionValue;

typedef struct ObjectValue {
  Value kind;
  Value * extends;
  size_t member_cnt;
  SimpleEntry members [];
} ObjectValue;

typedef struct ArrayValue {
  Value kind;
  i32 length;
  Value * elements [];
} ArrayValue;

void * heap_alloc_alligned ( Heap * heap, size_t len, size_t align );
void * heap_alloc ( Heap * heap, size_t len );
void heap_init ( Heap * heap, size_t heap_size );
void heap_destroy ( Heap * heap );

int compare_entry ( const void * a, const void * b );

bool value_to_bool ( Value * value );

Value * try_operator ( Heap * heap, Value * object, Value ** arguments, size_t argc, Str * name );
Value * get_base ( Value * object );
Value ** get_object_field ( Value * object, Str name );
Value * make_null ( Heap * heap );
Value * make_int ( Heap * heap, i32 val );
Value * make_bool ( Heap * heap, bool val );
Value * make_function ( Heap * heap, AstFunction * function );
Value * make_cfunction ( Heap * heap, ConstantFunction function );
Value * make_array ( Heap * heap, size_t len );
Value * make_object ( Heap * heap, size_t member_cnt );