blob: 7c0e57180eebc35a47f60389d3c659ac892c3cfc [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
swissChilif1ba8c12021-07-02 18:45:38 -070042struct closure
43{
swissChiliddc97542021-07-04 11:47:42 -070044 /// How many arguments does this closure take
swissChilif1ba8c12021-07-02 18:45:38 -070045 int num_args;
swissChiliddc97542021-07-04 11:47:42 -070046 /// How many free variables does it capture (i.e. length of `data`)
47 int num_captured;
48 /// The function pointer itself
swissChilif1ba8c12021-07-02 18:45:38 -070049 void *function;
50
51 /// This will be passed in edi.
52 value_t data[];
53};
54
swissChilib8fd4712021-06-23 15:32:04 -070055/// Default pool (no pool)
56#define NO_POOL 0
57
58/**
59 * The max used pool number, don't touch this.
60 */
61extern unsigned char max_pool;
62
63/**
64 * Current allocation pool, default 0 (no pool)
65 */
66extern unsigned char current_pool;
swissChilie9fec8b2021-06-22 13:59:33 -070067
68// It is integral that this be 16 bytes long so that whatever follows it is
69// still aligned to 4 bits.
swissChili9e57da42021-06-15 22:22:46 -070070struct alloc
swissChili7a6f5eb2021-04-13 16:46:02 -070071{
swissChilib8fd4712021-06-23 15:32:04 -070072 /**
73 * One of the type tags, eg CONS_TAG, etc
74 */
swissChilie9fec8b2021-06-22 13:59:33 -070075 unsigned int type_tag; // 4
76 struct alloc *prev, *next; // + 8
swissChilib8fd4712021-06-23 15:32:04 -070077 /**
78 * Zero if this is not part of a release pool, pool number otherwise.
79 */
80 unsigned char pool; // + 1
81 /**
82 * Reserved for the GC.
83 */
84 unsigned int mark : 24; // + 2 = 16
swissChili9e57da42021-06-15 22:22:46 -070085
86 // Whatever else
87};
88
swissChilie9fec8b2021-06-22 13:59:33 -070089extern struct alloc *first_a, *last_a;
90
swissChili9e57da42021-06-15 22:22:46 -070091struct cons_alloc
92{
93 struct alloc alloc;
94 struct cons cons;
swissChili7a6f5eb2021-04-13 16:46:02 -070095};
96
swissChilif1ba8c12021-07-02 18:45:38 -070097struct closure_alloc
98{
99 struct alloc alloc;
100 struct closure closure;
101};
102
swissChilib8fd4712021-06-23 15:32:04 -0700103/**
104 * Create a new allocation pool.
105 */
106unsigned char make_pool();
107
108/**
109 * Set the allocation pull
110 * @returns the old pool, you should reset this later with pop_pool.
111 */
112unsigned char push_pool(unsigned char pool);
113
114/**
115 * Set the allocation pool and throw away the old value.
116 */
117void pop_pool(unsigned char pool);
118
119/**
120 * @returns true if pool is still alive (in scope).
121 */
122bool pool_alive(unsigned char pool);
123
swissChili53472e82021-05-08 16:06:32 -0700124bool startswith(struct istream *s, char *pattern);
swissChili7a6f5eb2021-04-13 16:46:02 -0700125
swissChili53472e82021-05-08 16:06:32 -0700126bool readsym(struct istream *is, value_t *val);
127bool readstr(struct istream *is, value_t *val);
128bool readlist(struct istream *is, value_t *val);
129bool readint(struct istream *is, value_t *val);
swissChili7a6f5eb2021-04-13 16:46:02 -0700130
swissChilib6c858c2021-06-30 21:12:43 -0700131/**
132 * Read a quoted form, including `'` (quote) `\`` (backquote) and `,` (unquote)
133 * @returns true if read successfully, and sets `val`.
134 */
135bool readquote(struct istream *is, value_t *val);
136
swissChili53472e82021-05-08 16:06:32 -0700137value_t intval(int i);
138value_t strval(char *str);
swissChilib6c858c2021-06-30 21:12:43 -0700139value_t symval(char *str);
swissChili53472e82021-05-08 16:06:32 -0700140value_t cons(value_t car, value_t cdr);
141bool read1(struct istream *is, value_t *val);
142value_t read(struct istream *is);
143value_t readn(struct istream *is);
swissChilibed80922021-04-13 21:58:05 -0700144
swissChili53472e82021-05-08 16:06:32 -0700145value_t car(value_t v);
146value_t cdr(value_t v);
147value_t *carref(value_t v);
148value_t *cdrref(value_t v);
swissChili7a6f5eb2021-04-13 16:46:02 -0700149
swissChilif1ba8c12021-07-02 18:45:38 -0700150int cons_line(value_t val);
151char *cons_file(value_t val);
152
swissChili53472e82021-05-08 16:06:32 -0700153bool integerp(value_t v);
154bool symbolp(value_t v);
155bool stringp(value_t v);
156bool consp(value_t v);
157bool listp(value_t v);
158bool nilp(value_t v);
swissChili9e57da42021-06-15 22:22:46 -0700159bool heapp(value_t v);
swissChiliddc97542021-07-04 11:47:42 -0700160bool closurep(value_t v);
swissChili53472e82021-05-08 16:06:32 -0700161int length(value_t v);
162value_t elt(value_t v, int index);
swissChili8cfb7c42021-04-18 21:17:58 -0700163
swissChili53472e82021-05-08 16:06:32 -0700164void printval(value_t v, int depth);
swissChili7a6f5eb2021-04-13 16:46:02 -0700165
swissChili53472e82021-05-08 16:06:32 -0700166void err(const char *msg);
swissChilibed80922021-04-13 21:58:05 -0700167
swissChili53472e82021-05-08 16:06:32 -0700168bool symstreq(value_t sym, char *str);
swissChilica107a02021-04-14 12:07:30 -0700169
swissChiliddc97542021-07-04 11:47:42 -0700170value_t create_closure(void *code, int nargs, int ncaptures);
171
172/**
173 * Set the `index`th capture variable of `closure`. This should really only be
174 * called when creating a new closure.
175 */
176void set_closure_capture_variable(int index, value_t value, value_t closure);
177
swissChili8fc5e2f2021-04-22 13:45:10 -0700178extern value_t nil;
swissChili923b5362021-05-09 20:31:43 -0700179extern value_t t;