blob: 6035dfd652868718ff96fc359e26df524b8b64c0 [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
swissChili9d428a82022-08-01 20:47:40 -070086struct class
87{
88 // A symbol representing the name of the class this is an instance
89 // of.
90 value_t type;
91
92 int num_members;
93 // C data
94 void *cdata;
95 value_t members[];
96};
97
swissChilib8fd4712021-06-23 15:32:04 -070098/// Default pool (no pool)
99#define NO_POOL 0
100
101/**
102 * The max used pool number, don't touch this.
103 */
104extern unsigned char max_pool;
105
106/**
107 * Current allocation pool, default 0 (no pool)
108 */
109extern unsigned char current_pool;
swissChilie9fec8b2021-06-22 13:59:33 -0700110
111// It is integral that this be 16 bytes long so that whatever follows it is
112// still aligned to 4 bits.
swissChili9e57da42021-06-15 22:22:46 -0700113struct alloc
swissChili7a6f5eb2021-04-13 16:46:02 -0700114{
swissChilib8fd4712021-06-23 15:32:04 -0700115 /**
116 * One of the type tags, eg CONS_TAG, etc
117 */
swissChilie9fec8b2021-06-22 13:59:33 -0700118 unsigned int type_tag; // 4
119 struct alloc *prev, *next; // + 8
swissChilib8fd4712021-06-23 15:32:04 -0700120 /**
121 * Zero if this is not part of a release pool, pool number otherwise.
122 */
123 unsigned char pool; // + 1
124 /**
125 * Reserved for the GC.
126 */
swissChilia890aed2022-07-30 17:13:07 -0700127 unsigned int mark : 24; // + 3 = 16
swissChili9e57da42021-06-15 22:22:46 -0700128
129 // Whatever else
130};
131
swissChilie9fec8b2021-06-22 13:59:33 -0700132extern struct alloc *first_a, *last_a;
133
swissChili9e57da42021-06-15 22:22:46 -0700134struct cons_alloc
135{
136 struct alloc alloc;
137 struct cons cons;
swissChili7a6f5eb2021-04-13 16:46:02 -0700138};
139
swissChilif1ba8c12021-07-02 18:45:38 -0700140struct closure_alloc
141{
142 struct alloc alloc;
143 struct closure closure;
144};
145
swissChili9d428a82022-08-01 20:47:40 -0700146struct class_alloc
147{
148 struct alloc alloc;
149 struct class class;
150};
151
swissChilib8fd4712021-06-23 15:32:04 -0700152/**
153 * Create a new allocation pool.
154 */
155unsigned char make_pool();
156
157/**
158 * Set the allocation pull
159 * @returns the old pool, you should reset this later with pop_pool.
160 */
161unsigned char push_pool(unsigned char pool);
162
163/**
164 * Set the allocation pool and throw away the old value.
165 */
166void pop_pool(unsigned char pool);
167
swissChili36f2c692021-08-08 14:31:44 -0700168void add_to_pool(value_t form);
169
swissChilic0acce42022-07-31 13:38:17 -0700170void del_alloc(struct alloc *alloc);
swissChili8b5ec7a2022-08-05 22:26:17 -0700171void add_this_alloc(struct alloc *a, int tag);
swissChilic0acce42022-07-31 13:38:17 -0700172
swissChilib8fd4712021-06-23 15:32:04 -0700173/**
174 * @returns true if pool is still alive (in scope).
175 */
176bool pool_alive(unsigned char pool);
177
swissChili53472e82021-05-08 16:06:32 -0700178bool startswith(struct istream *s, char *pattern);
swissChili7a6f5eb2021-04-13 16:46:02 -0700179
swissChili6d02af42021-08-05 19:49:01 -0700180struct error readsym(struct istream *is, value_t *val) WARN_UNUSED;
181struct error readstr(struct istream *is, value_t *val) WARN_UNUSED;
182struct error readlist(struct istream *is, value_t *val) WARN_UNUSED;
183struct error readint(struct istream *is, value_t *val) WARN_UNUSED;
swissChili7a6f5eb2021-04-13 16:46:02 -0700184
swissChilib6c858c2021-06-30 21:12:43 -0700185/**
186 * Read a quoted form, including `'` (quote) `\`` (backquote) and `,` (unquote)
swissChilib6c858c2021-06-30 21:12:43 -0700187 */
swissChili6d02af42021-08-05 19:49:01 -0700188struct error readquote(struct istream *is, value_t *val) WARN_UNUSED;
swissChilib6c858c2021-06-30 21:12:43 -0700189
swissChili8b5ec7a2022-08-05 22:26:17 -0700190int valint(value_t i);
191
swissChili53472e82021-05-08 16:06:32 -0700192value_t intval(int i);
193value_t strval(char *str);
swissChilib6c858c2021-06-30 21:12:43 -0700194value_t symval(char *str);
swissChili53472e82021-05-08 16:06:32 -0700195value_t cons(value_t car, value_t cdr);
swissChilia7568dc2021-08-08 16:52:52 -0700196value_t merge2(value_t front, value_t back);
swissChili6d02af42021-08-05 19:49:01 -0700197struct error read1(struct istream *is, value_t *val) WARN_UNUSED;
swissChili53472e82021-05-08 16:06:32 -0700198value_t read(struct istream *is);
199value_t readn(struct istream *is);
swissChilibed80922021-04-13 21:58:05 -0700200
swissChili53472e82021-05-08 16:06:32 -0700201value_t car(value_t v);
202value_t cdr(value_t v);
swissChilia7568dc2021-08-08 16:52:52 -0700203/// Return a pointer to the "nil" tail of the list, or NULL if you do
204/// something stupid.
swissChili9d428a82022-08-01 20:47:40 -0700205value_t *nilptr(value_t *val);
swissChili53472e82021-05-08 16:06:32 -0700206value_t *carref(value_t v);
207value_t *cdrref(value_t v);
swissChili15f1cae2021-07-05 19:08:47 -0700208/// @returns the `index`-th `cdr`
209value_t cxdr(value_t v, int index);
210/// @returns a reference to the `index`-th `cdr`
211value_t *cxdrref(value_t *v, int index);
212
213value_t deep_copy(value_t val);
swissChili7a6f5eb2021-04-13 16:46:02 -0700214
swissChilif1ba8c12021-07-02 18:45:38 -0700215int cons_line(value_t val);
216char *cons_file(value_t val);
217
swissChili53472e82021-05-08 16:06:32 -0700218bool integerp(value_t v);
219bool symbolp(value_t v);
220bool stringp(value_t v);
221bool consp(value_t v);
swissChili8b5ec7a2022-08-05 22:26:17 -0700222bool classp(value_t v);
swissChili53472e82021-05-08 16:06:32 -0700223bool listp(value_t v);
224bool nilp(value_t v);
swissChili9e57da42021-06-15 22:22:46 -0700225bool heapp(value_t v);
swissChiliddc97542021-07-04 11:47:42 -0700226bool closurep(value_t v);
swissChili53472e82021-05-08 16:06:32 -0700227int length(value_t v);
228value_t elt(value_t v, int index);
swissChili8cfb7c42021-04-18 21:17:58 -0700229
swissChili53472e82021-05-08 16:06:32 -0700230void printval(value_t v, int depth);
swissChili7a6f5eb2021-04-13 16:46:02 -0700231
swissChili53472e82021-05-08 16:06:32 -0700232bool symstreq(value_t sym, char *str);
swissChilica107a02021-04-14 12:07:30 -0700233
swissChili15f1cae2021-07-05 19:08:47 -0700234value_t create_closure(void *code, struct args *args, int ncaptures);
swissChiliddc97542021-07-04 11:47:42 -0700235
236/**
237 * Set the `index`th capture variable of `closure`. This should really only be
238 * called when creating a new closure.
239 */
240void set_closure_capture_variable(int index, value_t value, value_t closure);
241
swissChili8fc5e2f2021-04-22 13:45:10 -0700242extern value_t nil;
swissChili923b5362021-05-09 20:31:43 -0700243extern value_t t;