132 lines
3.3 KiB
C
132 lines
3.3 KiB
C
#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
|