struct Lisp_Object; struct String; struct Environment; define_array_list(Lisp_Object*, Lisp_Object); define_array_list(Environment*, Environment); define_array_list(String*, String); define_array_list(int, Int); define_array_list(void*, Void_Ptr); enum struct Lisp_Object_Type { Nil, T, Symbol, Keyword, Number, String, Pair, // Pointer, // OwningPointer, Function, CFunction, }; typedef uint64_t u64; enum class Lisp_Object_Flags : u64 { // bits 1 to 5 (including) will be reserved for the type aliveness = 1 << 5, }; enum struct Function_Type { Lambda, Special_Lambda, Macro }; enum struct Log_Level { None, Critical, Warning, Info, Debug, }; struct String { int length; char data; }; struct Source_Code_Location { String* file; int line; int column; }; struct Symbol { String* identifier; u64 hash; }; struct Keyword { String* identifier; u64 hash; }; struct Pair { Lisp_Object* first; Lisp_Object* rest; }; struct Positional_Arguments { Lisp_Object** symbols; // Array of Pointers to Lisp_Object int next_index; int length; }; struct Keyword_Arguments { Lisp_Object** keywords; // Array of Pointers to Lisp_Object // NOTE(Felix): values[i] will be nullptr if no defalut value was // declared for key identifiers[i] Lisp_Object_Array_List* values; int next_index; int length; }; struct Function { Function_Type type; Positional_Arguments* positional_arguments; Keyword_Arguments* keyword_arguments; // rest_argument will be nullptr if no rest argument is declared String* rest_argument; Lisp_Object* body; // implicit begin Environment* parent_environment; // we are doing closures now!! }; struct cFunction { std::function function; }; struct Lisp_Object { Source_Code_Location* sourceCodeLocation; u64 flags; Lisp_Object* userType; String* docstring; union { Symbol symbol; // used for symbols and keywords double number; String* string; Pair pair; Function function; cFunction* cFunction; } value; }; struct Parsed_Arguments { Lisp_Object_Array_List* positional_arguments; // TODO(Felix): Really use hashmap (keyword[sting] -> // value[Lisp_Object*]) here Lisp_Object_Array_List* keyword_keys; Lisp_Object_Array_List* keyword_values; }; struct Environment { Environment_Array_List* parents; int capacity; int next_index; // TODO(Felix): Use a hashmap here. char** keys; Lisp_Object** values; }; struct Error { Lisp_Object* position; // type has to be a keyword Lisp_Object* type; String* message; };