struct Lisp_Object; struct String; struct Environment; define_array_list(Lisp_Object*, Lisp_Object); 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, Function, CFunction, }; enum struct Function_Type { Lambda, Special_Lambda, Macro }; enum struct Error_Type { Ill_Formed_Arguments, Ill_Formed_Lambda_List, Ill_Formed_List, Not_A_Function, Not_Yet_Implemented, Symbol_Not_Defined, Syntax_Error, Trailing_Garbage, Type_Missmatch, Unbalanced_Parenthesis, Unexpected_Eof, Unknown_Error, Unknown_Keyword_Argument, Wrong_Number_Of_Arguments, Out_Of_Memory, }; 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; }; struct Keyword { String* identifier; }; struct Number { double value; }; struct Pair { Lisp_Object* first; Lisp_Object* rest; }; struct Positional_Arguments { // TODO(Felix) use Lisp_Object_symbols here instead, so we don't have // to convert them to strings and back to symbols String** identifiers; // Array of Pointers to String int next_index; int length; }; struct Keyword_Arguments { String** identifiers; // Array of Pointers to String // 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; String* docstring; 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 prog Environment* parent_environment; // we are doing closures now!! }; struct cFunction { std::function function; }; struct Lisp_Object { Source_Code_Location* sourceCodeLocation; Lisp_Object_Type type; union { Symbol* symbol; Keyword* keyword; Number* 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* parent; int capacity; int next_index; // TODO(Felix): Use a hashmap here. char** keys; Lisp_Object** values; }; struct Error { Error_Type type; Source_Code_Location* location; };