]> git.lizzy.rs Git - nothing.git/blob - src/ebisp/expr.h
Add TODO(#928)
[nothing.git] / src / ebisp / expr.h
1 #ifndef EXPR_H_
2 #define EXPR_H_
3
4 #include <stdbool.h>
5 #include <stdio.h>
6 #include <stdlib.h>
7
8 typedef struct Gc Gc;
9 typedef struct Scope Scope;
10
11 struct Cons;
12 struct Atom;
13
14 #define NUMBER(G, X) atom_as_expr(create_number_atom(G, X))
15 #define STRING(G, S) atom_as_expr(create_string_atom(G, S, NULL))
16 #define SYMBOL(G, S) atom_as_expr(create_symbol_atom(G, S, NULL))
17 #define NATIVE(G, F, P) atom_as_expr(create_native_atom(G, F, P))
18 #define CONS(G, CAR, CDR) cons_as_expr(create_cons(G, CAR, CDR))
19 #define NIL(G) SYMBOL(G, "nil")
20 #define T(G) SYMBOL(G, "t")
21
22 #define CAR(O) ((O).cons->car)
23 #define CDR(O) ((O).cons->cdr)
24
25 enum ExprType
26 {
27     EXPR_ATOM = 0,
28     EXPR_CONS,
29     EXPR_VOID
30 };
31
32 struct Expr
33 {
34     enum ExprType type;
35     union {
36         struct Cons *cons;
37         struct Atom *atom;
38     };
39 };
40
41 // Prototype to prevent https://gcc.gnu.org/bugzilla/show_bug.cgi?id=54113
42 const char *expr_type_as_string(enum ExprType expr_type);
43
44 struct Expr atom_as_expr(struct Atom *atom);
45 struct Expr cons_as_expr(struct Cons *cons);
46 struct Expr void_expr(void);
47
48 void destroy_expr(struct Expr expr);
49 void print_expr_as_sexpr(FILE *stream, struct Expr expr);
50 void print_expr_as_c(FILE *stream, struct Expr expr);
51 int expr_as_sexpr(struct Expr expr, char *output, size_t n);
52
53 // TODO(#337): EvalResult does not belong to expr unit
54 struct EvalResult
55 {
56     bool is_error;
57     struct Expr expr;
58 };
59
60
61 typedef struct EvalResult (*NativeFunction)(void *param, Gc *gc, struct Scope *scope, struct Expr args);
62
63 struct Native
64 {
65     NativeFunction fun;
66     void *param;
67 };
68
69 struct Lambda
70 {
71     struct Expr args_list;
72     struct Expr body;
73     struct Expr envir;
74 };
75
76 enum AtomType
77 {
78     ATOM_SYMBOL = 0,
79     ATOM_NUMBER,
80     ATOM_STRING,
81     ATOM_LAMBDA,
82     ATOM_NATIVE
83 };
84
85 const char *atom_type_as_string(enum AtomType atom_type);
86
87 struct Atom
88 {
89     enum AtomType type;
90     union
91     {
92         // TODO(#330): Atom doesn't support floats
93         long int num;           // ATOM_NUMBER
94         char *sym;              // ATOM_SYMBOL
95         char *str;              // ATOM_STRING
96         struct Lambda lambda;   // ATOM_LAMBDA
97         struct Native native;   // ATOM_NATIVE
98     };
99 };
100
101 struct Atom *create_number_atom(Gc *gc, long int num);
102 struct Atom *create_string_atom(Gc *gc, const char *str, const char *str_end);
103 struct Atom *create_symbol_atom(Gc *gc, const char *sym, const char *sym_end);
104 struct Atom *create_lambda_atom(Gc *gc, struct Expr args_list, struct Expr body, struct Expr envir);
105 struct Atom *create_native_atom(Gc *gc, NativeFunction fun, void *param);
106 void destroy_atom(struct Atom *atom);
107 void print_atom_as_sexpr(FILE *stream, struct Atom *atom);
108
109 struct Cons
110 {
111     struct Expr car;
112     struct Expr cdr;
113 };
114
115 struct Cons *create_cons(Gc *gc, struct Expr car, struct Expr cdr);
116 void destroy_cons(struct Cons *cons);
117 void print_cons_as_sexpr(FILE *stream, struct Cons *cons);
118
119 #endif  // EXPR_H_