#ifndef LISP_H #define LISP_H #include "nob.h" typedef enum e_TokenKind { TOKEN_KIND_PAR_LEFT, TOKEN_KIND_PAR_RIGHT, TOKEN_KIND_NUMBER, TOKEN_KIND_SYMBOL, } TokenKind; typedef struct s_Token { TokenKind kind; Nob_String_View data; } Token; typedef struct s_Tokens { Token *items; size_t count; size_t capacity; } Tokens; typedef enum e_NodeKind { NODE_KIND_SYMBOL, NODE_KIND_LIST, NODE_KIND_NUMBER, NODE_KIND_FUNCTION, NODE_KIND_LAMBDA, } NodeKind; typedef struct s_Node Node; typedef struct s_Nodes Nodes; typedef struct s_Scopes Scopes; // args is specifically not a pointer, // functions shouldn't be able to mess with their arguments typedef int (*LispFunctionPtr)(Nodes args, Scopes *scopes, Node *result); typedef struct s_LispFunction { Nob_String_View name; LispFunctionPtr apply; } LispFunction; struct s_Node { NodeKind kind; union { Nob_String_View as_symbol; Nodes *as_list; double as_number; LispFunction as_function; struct { Nodes *params; Node *body; } as_lambda; }; }; struct s_Nodes { Node *items; size_t count; size_t capacity; }; typedef struct s_ScopeObject { Nob_String_View name; Node node; } ScopeObject; // TODO: use hashtable typedef struct s_Scope { ScopeObject *items; size_t count; size_t capacity; } Scope; struct s_Scopes { Scope **items; size_t count; size_t capacity; }; const char *token_kind_name(TokenKind kind); void node_print(Node node); void build_scopes(Scopes *scopes); int tokenize(Nob_String_View content, Tokens *tokens); int parse_one(Tokens *tokens, Node *node); int parse(Tokens *tokens, Nodes *nodes); int eval_one(Node input, Scopes *scopes, Node *result); int eval(Nodes inputs, Scopes *scopes, Nodes *results); /* special forms and builtins follow the function signature defined by LispFunctionPtr The arguments for builtins will be evaluated before calling them, that is not the case for special forms. */ // special forms int special_form_if(Nodes args, Scopes *scopes, Node *result); int special_form_define(Nodes args, Scopes *scopes, Node *result); int special_form_let(Nodes args, Scopes *scopes, Node *result); int special_form_lambda(Nodes args, Scopes *scopes, Node *result); // builtins int builtin_add(Nodes args, Scopes *scopes, Node *result); int builtin_sub(Nodes args, Scopes *scope, Node *result); int builtin_div(Nodes args, Scopes *scope, Node *result); int builtin_mul(Nodes args, Scopes *scope, Node *result); int builtin_eq(Nodes args, Scopes *scope, Node *result); int builtin_lt(Nodes args, Scopes *scope, Node *result); int builtin_gt(Nodes args, Scopes *scope, Node *result); int builtin_lt_eq(Nodes args, Scopes *scope, Node *result); int builtin_gt_eq(Nodes args, Scopes *scope, Node *result); int builtin_println(Nodes args, Scopes *scopes, Node *result); int builtin_list(Nodes args, Scopes *scopes, Node *result); int builtin_append(Nodes args, Scopes *scope, Node *result); int builtin_length(Nodes args, Scopes *scope, Node *result); int builtin_isnull(Nodes args, Scopes *scope, Node *result); int builtin_builtins(Nodes args, Scopes *scopes, Node *result); int builtin_floor(Nodes args, Scopes *scopes, Node *result); int builtin_ceil(Nodes args, Scopes *scopes, Node *result); #endif // LISP_H