blob: ad7314adfc80cf445587e6c1c5a9b3fc1a7e30da [file] [log] [blame]
swissChili7a6f5eb2021-04-13 16:46:02 -07001#pragma once
2
swissChili6d02af42021-08-05 19:49:01 -07003#include "error.h"
swissChili923b5362021-05-09 20:31:43 -07004#include "istream.h"
swissChili7a6f5eb2021-04-13 16:46:02 -07005#include <stdbool.h>
swissChilibed80922021-04-13 21:58:05 -07006#include <stdio.h>
swissChili7e1393c2021-07-07 12:59:12 -07007#include <stdarg.h>
swissChili7a6f5eb2021-04-13 16:46:02 -07008
swissChili8cfb7c42021-04-18 21:17:58 -07009#define INT_MASK 0b11
10#define INT_TAG 0b00
11
12#define CHAR_MASK 0xff
13#define CHAR_TAG 0b00001111
14
15#define BOOL_MASK 0b1111111
16#define BOOL_TAG 0b0011111
17
18#define HEAP_MASK 0b111
19
20#define CONS_TAG 0b001
swissChili7e1393c2021-07-07 12:59:12 -070021#define CLASS_TAG 0b010
swissChili6eee4f92021-04-20 09:34:30 -070022#define STRING_TAG 0b011
swissChili8cfb7c42021-04-18 21:17:58 -070023#define SYMBOL_TAG 0b101
24#define CLOSURE_TAG 0b110
swissChili7a6f5eb2021-04-13 16:46:02 -070025
26struct cons;
27
swissChili2999dd12021-07-02 14:19:53 -070028/// Represents a Lisp value
swissChili8cfb7c42021-04-18 21:17:58 -070029typedef unsigned int value_t;
swissChili7a6f5eb2021-04-13 16:46:02 -070030
31struct cons
32{
swissChili8cfb7c42021-04-18 21:17:58 -070033 value_t car, cdr;
swissChili2999dd12021-07-02 14:19:53 -070034
35 /// Line of the input file from where this was parsed, 0 if it was created
36 /// in Lisp.
37 int line;
38
39 /// Description of where the cons was parsed from, or NULL if generated in
40 /// code.
41 char *name;
swissChili7a6f5eb2021-04-13 16:46:02 -070042};
43
swissChili15f1cae2021-07-05 19:08:47 -070044/**
45 * Represents how many arguments a function takes.
46 */
47struct args
48{
49 /// The minimum valid number of arguments
50 int num_required;
51
52 /// The number of optional values
53 int num_optional;
54
55 /// Does this function accept variadic arguments? If `true`, any arguments
56 /// after the required and optional arguments will be `cons`-ed to a list
57 /// and passed as a final argument.
58 bool variadic;
59
60 /// The default values for the optional arguments, as expressions. These
61 /// should be evaluated at the call site. They are known not to reference
62 /// anything that could clash with scope at the call site.
63 struct optional_argument
64 {
65 /// The default value of this argument
66 value_t value;
67
68 /// The name of this argument as a symbol
69 value_t name;
70 } optional_arguments[];
71};
72
swissChilif1ba8c12021-07-02 18:45:38 -070073struct closure
74{
swissChiliddc97542021-07-04 11:47:42 -070075 /// How many arguments does this closure take
swissChili15f1cae2021-07-05 19:08:47 -070076 struct args *args;
swissChiliddc97542021-07-04 11:47:42 -070077 /// How many free variables does it capture (i.e. length of `data`)
78 int num_captured;
79 /// The function pointer itself
swissChilif1ba8c12021-07-02 18:45:38 -070080 void *function;
81
82 /// This will be passed in edi.
83 value_t data[];
84};
85
swissChilib8fd4712021-06-23 15:32:04 -070086/// Default pool (no pool)
87#define NO_POOL 0
88
89/**
90 * The max used pool number, don't touch this.
91 */
92extern unsigned char max_pool;
93
94/**
95 * Current allocation pool, default 0 (no pool)
96 */
97extern unsigned char current_pool;
swissChilie9fec8b2021-06-22 13:59:33 -070098
99// It is integral that this be 16 bytes long so that whatever follows it is
100// still aligned to 4 bits.
swissChili9e57da42021-06-15 22:22:46 -0700101struct alloc
swissChili7a6f5eb2021-04-13 16:46:02 -0700102{
swissChilib8fd4712021-06-23 15:32:04 -0700103 /**
104 * One of the type tags, eg CONS_TAG, etc
105 */
swissChilie9fec8b2021-06-22 13:59:33 -0700106 unsigned int type_tag; // 4
107 struct alloc *prev, *next; // + 8
swissChilib8fd4712021-06-23 15:32:04 -0700108 /**
109 * Zero if this is not part of a release pool, pool number otherwise.
110 */
111 unsigned char pool; // + 1
112 /**
113 * Reserved for the GC.
114 */
swissChilia890aed2022-07-30 17:13:07 -0700115 unsigned int mark : 24; // + 3 = 16
swissChili9e57da42021-06-15 22:22:46 -0700116
117 // Whatever else
118};
119
swissChilie9fec8b2021-06-22 13:59:33 -0700120extern struct alloc *first_a, *last_a;
121
swissChili9e57da42021-06-15 22:22:46 -0700122struct cons_alloc
123{
124 struct alloc alloc;
125 struct cons cons;
swissChili7a6f5eb2021-04-13 16:46:02 -0700126};
127
swissChilif1ba8c12021-07-02 18:45:38 -0700128struct closure_alloc
129{
130 struct alloc alloc;
131 struct closure closure;
132};
133
swissChilib8fd4712021-06-23 15:32:04 -0700134/**
135 * Create a new allocation pool.
136 */
137unsigned char make_pool();
138
139/**
140 * Set the allocation pull
141 * @returns the old pool, you should reset this later with pop_pool.
142 */
143unsigned char push_pool(unsigned char pool);
144
145/**
146 * Set the allocation pool and throw away the old value.
147 */
148void pop_pool(unsigned char pool);
149
swissChili36f2c692021-08-08 14:31:44 -0700150void add_to_pool(value_t form);
151
swissChilic0acce42022-07-31 13:38:17 -0700152void del_alloc(struct alloc *alloc);
153
swissChilib8fd4712021-06-23 15:32:04 -0700154/**
155 * @returns true if pool is still alive (in scope).
156 */
157bool pool_alive(unsigned char pool);
158
swissChili53472e82021-05-08 16:06:32 -0700159bool startswith(struct istream *s, char *pattern);
swissChili7a6f5eb2021-04-13 16:46:02 -0700160
swissChili6d02af42021-08-05 19:49:01 -0700161struct error readsym(struct istream *is, value_t *val) WARN_UNUSED;
162struct error readstr(struct istream *is, value_t *val) WARN_UNUSED;
163struct error readlist(struct istream *is, value_t *val) WARN_UNUSED;
164struct error readint(struct istream *is, value_t *val) WARN_UNUSED;
swissChili7a6f5eb2021-04-13 16:46:02 -0700165
swissChilib6c858c2021-06-30 21:12:43 -0700166/**
167 * Read a quoted form, including `'` (quote) `\`` (backquote) and `,` (unquote)
swissChilib6c858c2021-06-30 21:12:43 -0700168 */
swissChili6d02af42021-08-05 19:49:01 -0700169struct error readquote(struct istream *is, value_t *val) WARN_UNUSED;
swissChilib6c858c2021-06-30 21:12:43 -0700170
swissChili53472e82021-05-08 16:06:32 -0700171value_t intval(int i);
172value_t strval(char *str);
swissChilib6c858c2021-06-30 21:12:43 -0700173value_t symval(char *str);
swissChili53472e82021-05-08 16:06:32 -0700174value_t cons(value_t car, value_t cdr);
swissChilia7568dc2021-08-08 16:52:52 -0700175value_t merge2(value_t front, value_t back);
swissChili6d02af42021-08-05 19:49:01 -0700176struct error read1(struct istream *is, value_t *val) WARN_UNUSED;
swissChili53472e82021-05-08 16:06:32 -0700177value_t read(struct istream *is);
178value_t readn(struct istream *is);
swissChilibed80922021-04-13 21:58:05 -0700179
swissChili53472e82021-05-08 16:06:32 -0700180value_t car(value_t v);
181value_t cdr(value_t v);
swissChilia7568dc2021-08-08 16:52:52 -0700182/// Return a pointer to the "nil" tail of the list, or NULL if you do
183/// something stupid.
184value_t *nilptr(value_t val);
swissChili53472e82021-05-08 16:06:32 -0700185value_t *carref(value_t v);
186value_t *cdrref(value_t v);
swissChili15f1cae2021-07-05 19:08:47 -0700187/// @returns the `index`-th `cdr`
188value_t cxdr(value_t v, int index);
189/// @returns a reference to the `index`-th `cdr`
190value_t *cxdrref(value_t *v, int index);
191
192value_t deep_copy(value_t val);
swissChili7a6f5eb2021-04-13 16:46:02 -0700193
swissChilif1ba8c12021-07-02 18:45:38 -0700194int cons_line(value_t val);
195char *cons_file(value_t val);
196
swissChili53472e82021-05-08 16:06:32 -0700197bool integerp(value_t v);
198bool symbolp(value_t v);
199bool stringp(value_t v);
200bool consp(value_t v);
201bool listp(value_t v);
202bool nilp(value_t v);
swissChili9e57da42021-06-15 22:22:46 -0700203bool heapp(value_t v);
swissChiliddc97542021-07-04 11:47:42 -0700204bool closurep(value_t v);
swissChili53472e82021-05-08 16:06:32 -0700205int length(value_t v);
206value_t elt(value_t v, int index);
swissChili8cfb7c42021-04-18 21:17:58 -0700207
swissChili53472e82021-05-08 16:06:32 -0700208void printval(value_t v, int depth);
swissChili7a6f5eb2021-04-13 16:46:02 -0700209
swissChili53472e82021-05-08 16:06:32 -0700210bool symstreq(value_t sym, char *str);
swissChilica107a02021-04-14 12:07:30 -0700211
swissChili15f1cae2021-07-05 19:08:47 -0700212value_t create_closure(void *code, struct args *args, int ncaptures);
swissChiliddc97542021-07-04 11:47:42 -0700213
214/**
215 * Set the `index`th capture variable of `closure`. This should really only be
216 * called when creating a new closure.
217 */
218void set_closure_capture_variable(int index, value_t value, value_t closure);
219
swissChili8fc5e2f2021-04-22 13:45:10 -0700220extern value_t nil;
swissChili923b5362021-05-09 20:31:43 -0700221extern value_t t;