blob: c572c807bcdb9c6a4672f29953743464bb0f9244 [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>
swissChili7e1393c2021-07-07 12:59:12 -07006#include <stdarg.h>
swissChili7a6f5eb2021-04-13 16:46:02 -07007
swissChili8cfb7c42021-04-18 21:17:58 -07008#define INT_MASK 0b11
9#define INT_TAG 0b00
10
11#define CHAR_MASK 0xff
12#define CHAR_TAG 0b00001111
13
14#define BOOL_MASK 0b1111111
15#define BOOL_TAG 0b0011111
16
17#define HEAP_MASK 0b111
18
19#define CONS_TAG 0b001
swissChili7e1393c2021-07-07 12:59:12 -070020#define CLASS_TAG 0b010
swissChili6eee4f92021-04-20 09:34:30 -070021#define STRING_TAG 0b011
swissChili8cfb7c42021-04-18 21:17:58 -070022#define SYMBOL_TAG 0b101
23#define CLOSURE_TAG 0b110
swissChili7a6f5eb2021-04-13 16:46:02 -070024
25struct cons;
26
swissChili2999dd12021-07-02 14:19:53 -070027/// Represents a Lisp value
swissChili8cfb7c42021-04-18 21:17:58 -070028typedef unsigned int value_t;
swissChili7a6f5eb2021-04-13 16:46:02 -070029
30struct cons
31{
swissChili8cfb7c42021-04-18 21:17:58 -070032 value_t car, cdr;
swissChili2999dd12021-07-02 14:19:53 -070033
34 /// Line of the input file from where this was parsed, 0 if it was created
35 /// in Lisp.
36 int line;
37
38 /// Description of where the cons was parsed from, or NULL if generated in
39 /// code.
40 char *name;
swissChili7a6f5eb2021-04-13 16:46:02 -070041};
42
swissChili15f1cae2021-07-05 19:08:47 -070043/**
44 * Represents how many arguments a function takes.
45 */
46struct args
47{
48 /// The minimum valid number of arguments
49 int num_required;
50
51 /// The number of optional values
52 int num_optional;
53
54 /// Does this function accept variadic arguments? If `true`, any arguments
55 /// after the required and optional arguments will be `cons`-ed to a list
56 /// and passed as a final argument.
57 bool variadic;
58
59 /// The default values for the optional arguments, as expressions. These
60 /// should be evaluated at the call site. They are known not to reference
61 /// anything that could clash with scope at the call site.
62 struct optional_argument
63 {
64 /// The default value of this argument
65 value_t value;
66
67 /// The name of this argument as a symbol
68 value_t name;
69 } optional_arguments[];
70};
71
swissChilif1ba8c12021-07-02 18:45:38 -070072struct closure
73{
swissChiliddc97542021-07-04 11:47:42 -070074 /// How many arguments does this closure take
swissChili15f1cae2021-07-05 19:08:47 -070075 struct args *args;
swissChiliddc97542021-07-04 11:47:42 -070076 /// How many free variables does it capture (i.e. length of `data`)
77 int num_captured;
78 /// The function pointer itself
swissChilif1ba8c12021-07-02 18:45:38 -070079 void *function;
80
81 /// This will be passed in edi.
82 value_t data[];
83};
84
swissChilib8fd4712021-06-23 15:32:04 -070085/// Default pool (no pool)
86#define NO_POOL 0
87
88/**
89 * The max used pool number, don't touch this.
90 */
91extern unsigned char max_pool;
92
93/**
94 * Current allocation pool, default 0 (no pool)
95 */
96extern unsigned char current_pool;
swissChilie9fec8b2021-06-22 13:59:33 -070097
98// It is integral that this be 16 bytes long so that whatever follows it is
99// still aligned to 4 bits.
swissChili9e57da42021-06-15 22:22:46 -0700100struct alloc
swissChili7a6f5eb2021-04-13 16:46:02 -0700101{
swissChilib8fd4712021-06-23 15:32:04 -0700102 /**
103 * One of the type tags, eg CONS_TAG, etc
104 */
swissChilie9fec8b2021-06-22 13:59:33 -0700105 unsigned int type_tag; // 4
106 struct alloc *prev, *next; // + 8
swissChilib8fd4712021-06-23 15:32:04 -0700107 /**
108 * Zero if this is not part of a release pool, pool number otherwise.
109 */
110 unsigned char pool; // + 1
111 /**
112 * Reserved for the GC.
113 */
114 unsigned int mark : 24; // + 2 = 16
swissChili9e57da42021-06-15 22:22:46 -0700115
116 // Whatever else
117};
118
swissChilie9fec8b2021-06-22 13:59:33 -0700119extern struct alloc *first_a, *last_a;
120
swissChili9e57da42021-06-15 22:22:46 -0700121struct cons_alloc
122{
123 struct alloc alloc;
124 struct cons cons;
swissChili7a6f5eb2021-04-13 16:46:02 -0700125};
126
swissChilif1ba8c12021-07-02 18:45:38 -0700127struct closure_alloc
128{
129 struct alloc alloc;
130 struct closure closure;
131};
132
swissChilib8fd4712021-06-23 15:32:04 -0700133/**
134 * Create a new allocation pool.
135 */
136unsigned char make_pool();
137
138/**
139 * Set the allocation pull
140 * @returns the old pool, you should reset this later with pop_pool.
141 */
142unsigned char push_pool(unsigned char pool);
143
144/**
145 * Set the allocation pool and throw away the old value.
146 */
147void pop_pool(unsigned char pool);
148
149/**
150 * @returns true if pool is still alive (in scope).
151 */
152bool pool_alive(unsigned char pool);
153
swissChili53472e82021-05-08 16:06:32 -0700154bool startswith(struct istream *s, char *pattern);
swissChili7a6f5eb2021-04-13 16:46:02 -0700155
swissChili53472e82021-05-08 16:06:32 -0700156bool readsym(struct istream *is, value_t *val);
157bool readstr(struct istream *is, value_t *val);
158bool readlist(struct istream *is, value_t *val);
159bool readint(struct istream *is, value_t *val);
swissChili7a6f5eb2021-04-13 16:46:02 -0700160
swissChilib6c858c2021-06-30 21:12:43 -0700161/**
162 * Read a quoted form, including `'` (quote) `\`` (backquote) and `,` (unquote)
163 * @returns true if read successfully, and sets `val`.
164 */
165bool readquote(struct istream *is, value_t *val);
166
swissChili53472e82021-05-08 16:06:32 -0700167value_t intval(int i);
168value_t strval(char *str);
swissChilib6c858c2021-06-30 21:12:43 -0700169value_t symval(char *str);
swissChili53472e82021-05-08 16:06:32 -0700170value_t cons(value_t car, value_t cdr);
171bool read1(struct istream *is, value_t *val);
172value_t read(struct istream *is);
173value_t readn(struct istream *is);
swissChilibed80922021-04-13 21:58:05 -0700174
swissChili53472e82021-05-08 16:06:32 -0700175value_t car(value_t v);
176value_t cdr(value_t v);
177value_t *carref(value_t v);
178value_t *cdrref(value_t v);
swissChili15f1cae2021-07-05 19:08:47 -0700179/// @returns the `index`-th `cdr`
180value_t cxdr(value_t v, int index);
181/// @returns a reference to the `index`-th `cdr`
182value_t *cxdrref(value_t *v, int index);
183
184value_t deep_copy(value_t val);
swissChili7a6f5eb2021-04-13 16:46:02 -0700185
swissChilif1ba8c12021-07-02 18:45:38 -0700186int cons_line(value_t val);
187char *cons_file(value_t val);
188
swissChili53472e82021-05-08 16:06:32 -0700189bool integerp(value_t v);
190bool symbolp(value_t v);
191bool stringp(value_t v);
192bool consp(value_t v);
193bool listp(value_t v);
194bool nilp(value_t v);
swissChili9e57da42021-06-15 22:22:46 -0700195bool heapp(value_t v);
swissChiliddc97542021-07-04 11:47:42 -0700196bool closurep(value_t v);
swissChili53472e82021-05-08 16:06:32 -0700197int length(value_t v);
198value_t elt(value_t v, int index);
swissChili8cfb7c42021-04-18 21:17:58 -0700199
swissChili53472e82021-05-08 16:06:32 -0700200void printval(value_t v, int depth);
swissChili7a6f5eb2021-04-13 16:46:02 -0700201
swissChili53472e82021-05-08 16:06:32 -0700202void err(const char *msg);
swissChili7e1393c2021-07-07 12:59:12 -0700203void err_at(value_t form, const char *msg, ...);
swissChilibed80922021-04-13 21:58:05 -0700204
swissChili53472e82021-05-08 16:06:32 -0700205bool symstreq(value_t sym, char *str);
swissChilica107a02021-04-14 12:07:30 -0700206
swissChili15f1cae2021-07-05 19:08:47 -0700207value_t create_closure(void *code, struct args *args, int ncaptures);
swissChiliddc97542021-07-04 11:47:42 -0700208
209/**
210 * Set the `index`th capture variable of `closure`. This should really only be
211 * called when creating a new closure.
212 */
213void set_closure_capture_variable(int index, value_t value, value_t closure);
214
swissChili8fc5e2f2021-04-22 13:45:10 -0700215extern value_t nil;
swissChili923b5362021-05-09 20:31:43 -0700216extern value_t t;