blob: a8bea1c4c13e1048e2425cf91fb2b3787945fe03 [file] [log] [blame]
swissChili7a6f5eb2021-04-13 16:46:02 -07001#pragma once
2
swissChili923b5362021-05-09 20:31:43 -07003#include "istream.h"
swissChili7a6f5eb2021-04-13 16:46:02 -07004#include <stdbool.h>
swissChilibed80922021-04-13 21:58:05 -07005#include <stdio.h>
swissChili7a6f5eb2021-04-13 16:46:02 -07006
swissChili8cfb7c42021-04-18 21:17:58 -07007#define INT_MASK 0b11
8#define INT_TAG 0b00
9
10#define CHAR_MASK 0xff
11#define CHAR_TAG 0b00001111
12
13#define BOOL_MASK 0b1111111
14#define BOOL_TAG 0b0011111
15
16#define HEAP_MASK 0b111
17
18#define CONS_TAG 0b001
19#define VECTOR_TAG 0b010
swissChili6eee4f92021-04-20 09:34:30 -070020#define STRING_TAG 0b011
swissChili8cfb7c42021-04-18 21:17:58 -070021#define SYMBOL_TAG 0b101
22#define CLOSURE_TAG 0b110
swissChili7a6f5eb2021-04-13 16:46:02 -070023
24struct cons;
25
swissChili2999dd12021-07-02 14:19:53 -070026/// Represents a Lisp value
swissChili8cfb7c42021-04-18 21:17:58 -070027typedef unsigned int value_t;
swissChili7a6f5eb2021-04-13 16:46:02 -070028
29struct cons
30{
swissChili8cfb7c42021-04-18 21:17:58 -070031 value_t car, cdr;
swissChili2999dd12021-07-02 14:19:53 -070032
33 /// Line of the input file from where this was parsed, 0 if it was created
34 /// in Lisp.
35 int line;
36
37 /// Description of where the cons was parsed from, or NULL if generated in
38 /// code.
39 char *name;
swissChili7a6f5eb2021-04-13 16:46:02 -070040};
41
swissChili15f1cae2021-07-05 19:08:47 -070042/**
43 * Represents how many arguments a function takes.
44 */
45struct args
46{
47 /// The minimum valid number of arguments
48 int num_required;
49
50 /// The number of optional values
51 int num_optional;
52
53 /// Does this function accept variadic arguments? If `true`, any arguments
54 /// after the required and optional arguments will be `cons`-ed to a list
55 /// and passed as a final argument.
56 bool variadic;
57
58 /// The default values for the optional arguments, as expressions. These
59 /// should be evaluated at the call site. They are known not to reference
60 /// anything that could clash with scope at the call site.
61 struct optional_argument
62 {
63 /// The default value of this argument
64 value_t value;
65
66 /// The name of this argument as a symbol
67 value_t name;
68 } optional_arguments[];
69};
70
swissChilif1ba8c12021-07-02 18:45:38 -070071struct closure
72{
swissChiliddc97542021-07-04 11:47:42 -070073 /// How many arguments does this closure take
swissChili15f1cae2021-07-05 19:08:47 -070074 struct args *args;
swissChiliddc97542021-07-04 11:47:42 -070075 /// How many free variables does it capture (i.e. length of `data`)
76 int num_captured;
77 /// The function pointer itself
swissChilif1ba8c12021-07-02 18:45:38 -070078 void *function;
79
80 /// This will be passed in edi.
81 value_t data[];
82};
83
swissChilib8fd4712021-06-23 15:32:04 -070084/// Default pool (no pool)
85#define NO_POOL 0
86
87/**
88 * The max used pool number, don't touch this.
89 */
90extern unsigned char max_pool;
91
92/**
93 * Current allocation pool, default 0 (no pool)
94 */
95extern unsigned char current_pool;
swissChilie9fec8b2021-06-22 13:59:33 -070096
97// It is integral that this be 16 bytes long so that whatever follows it is
98// still aligned to 4 bits.
swissChili9e57da42021-06-15 22:22:46 -070099struct alloc
swissChili7a6f5eb2021-04-13 16:46:02 -0700100{
swissChilib8fd4712021-06-23 15:32:04 -0700101 /**
102 * One of the type tags, eg CONS_TAG, etc
103 */
swissChilie9fec8b2021-06-22 13:59:33 -0700104 unsigned int type_tag; // 4
105 struct alloc *prev, *next; // + 8
swissChilib8fd4712021-06-23 15:32:04 -0700106 /**
107 * Zero if this is not part of a release pool, pool number otherwise.
108 */
109 unsigned char pool; // + 1
110 /**
111 * Reserved for the GC.
112 */
113 unsigned int mark : 24; // + 2 = 16
swissChili9e57da42021-06-15 22:22:46 -0700114
115 // Whatever else
116};
117
swissChilie9fec8b2021-06-22 13:59:33 -0700118extern struct alloc *first_a, *last_a;
119
swissChili9e57da42021-06-15 22:22:46 -0700120struct cons_alloc
121{
122 struct alloc alloc;
123 struct cons cons;
swissChili7a6f5eb2021-04-13 16:46:02 -0700124};
125
swissChilif1ba8c12021-07-02 18:45:38 -0700126struct closure_alloc
127{
128 struct alloc alloc;
129 struct closure closure;
130};
131
swissChilib8fd4712021-06-23 15:32:04 -0700132/**
133 * Create a new allocation pool.
134 */
135unsigned char make_pool();
136
137/**
138 * Set the allocation pull
139 * @returns the old pool, you should reset this later with pop_pool.
140 */
141unsigned char push_pool(unsigned char pool);
142
143/**
144 * Set the allocation pool and throw away the old value.
145 */
146void pop_pool(unsigned char pool);
147
148/**
149 * @returns true if pool is still alive (in scope).
150 */
151bool pool_alive(unsigned char pool);
152
swissChili53472e82021-05-08 16:06:32 -0700153bool startswith(struct istream *s, char *pattern);
swissChili7a6f5eb2021-04-13 16:46:02 -0700154
swissChili53472e82021-05-08 16:06:32 -0700155bool readsym(struct istream *is, value_t *val);
156bool readstr(struct istream *is, value_t *val);
157bool readlist(struct istream *is, value_t *val);
158bool readint(struct istream *is, value_t *val);
swissChili7a6f5eb2021-04-13 16:46:02 -0700159
swissChilib6c858c2021-06-30 21:12:43 -0700160/**
161 * Read a quoted form, including `'` (quote) `\`` (backquote) and `,` (unquote)
162 * @returns true if read successfully, and sets `val`.
163 */
164bool readquote(struct istream *is, value_t *val);
165
swissChili53472e82021-05-08 16:06:32 -0700166value_t intval(int i);
167value_t strval(char *str);
swissChilib6c858c2021-06-30 21:12:43 -0700168value_t symval(char *str);
swissChili53472e82021-05-08 16:06:32 -0700169value_t cons(value_t car, value_t cdr);
170bool read1(struct istream *is, value_t *val);
171value_t read(struct istream *is);
172value_t readn(struct istream *is);
swissChilibed80922021-04-13 21:58:05 -0700173
swissChili53472e82021-05-08 16:06:32 -0700174value_t car(value_t v);
175value_t cdr(value_t v);
176value_t *carref(value_t v);
177value_t *cdrref(value_t v);
swissChili15f1cae2021-07-05 19:08:47 -0700178/// @returns the `index`-th `cdr`
179value_t cxdr(value_t v, int index);
180/// @returns a reference to the `index`-th `cdr`
181value_t *cxdrref(value_t *v, int index);
182
183value_t deep_copy(value_t val);
swissChili7a6f5eb2021-04-13 16:46:02 -0700184
swissChilif1ba8c12021-07-02 18:45:38 -0700185int cons_line(value_t val);
186char *cons_file(value_t val);
187
swissChili53472e82021-05-08 16:06:32 -0700188bool integerp(value_t v);
189bool symbolp(value_t v);
190bool stringp(value_t v);
191bool consp(value_t v);
192bool listp(value_t v);
193bool nilp(value_t v);
swissChili9e57da42021-06-15 22:22:46 -0700194bool heapp(value_t v);
swissChiliddc97542021-07-04 11:47:42 -0700195bool closurep(value_t v);
swissChili53472e82021-05-08 16:06:32 -0700196int length(value_t v);
197value_t elt(value_t v, int index);
swissChili8cfb7c42021-04-18 21:17:58 -0700198
swissChili53472e82021-05-08 16:06:32 -0700199void printval(value_t v, int depth);
swissChili7a6f5eb2021-04-13 16:46:02 -0700200
swissChili53472e82021-05-08 16:06:32 -0700201void err(const char *msg);
swissChilibed80922021-04-13 21:58:05 -0700202
swissChili53472e82021-05-08 16:06:32 -0700203bool symstreq(value_t sym, char *str);
swissChilica107a02021-04-14 12:07:30 -0700204
swissChili15f1cae2021-07-05 19:08:47 -0700205value_t create_closure(void *code, struct args *args, int ncaptures);
swissChiliddc97542021-07-04 11:47:42 -0700206
207/**
208 * Set the `index`th capture variable of `closure`. This should really only be
209 * called when creating a new closure.
210 */
211void set_closure_capture_variable(int index, value_t value, value_t closure);
212
swissChili8fc5e2f2021-04-22 13:45:10 -0700213extern value_t nil;
swissChili923b5362021-05-09 20:31:43 -0700214extern value_t t;