blob: a0b7c78fd5409f64e3380c948ad3fa9dcdb1c499 [file] [log] [blame]
swissChilib3ca4fb2021-04-20 10:33:00 -07001#include "std.h"
swissChilia890aed2022-07-30 17:13:07 -07002#include "../gc.h"
swissChili04d94162022-07-30 21:46:49 -07003#include "../compiler.h"
swissChilif68671f2021-07-05 14:14:44 -07004#include "../plat/plat.h"
swissChilif3e7f182021-04-20 13:57:22 -07005#include <stdlib.h>
swissChilif68671f2021-07-05 14:14:44 -07006#include <string.h>
swissChilib3ca4fb2021-04-20 10:33:00 -07007
swissChili53472e82021-05-08 16:06:32 -07008value_t l_plus(value_t a, value_t b)
swissChilib3ca4fb2021-04-20 10:33:00 -07009{
swissChili53472e82021-05-08 16:06:32 -070010 if (!integerp(a) || !integerp(b))
swissChilib3ca4fb2021-04-20 10:33:00 -070011 return nil;
12
13 return (((a >> 2) + (b >> 2)) << 2) | INT_TAG;
14}
15
swissChili53472e82021-05-08 16:06:32 -070016value_t l_minus(value_t a, value_t b)
swissChili6aff2bb2021-04-20 15:02:53 -070017{
swissChili53472e82021-05-08 16:06:32 -070018 if (!integerp(a) || !integerp(b))
swissChili6aff2bb2021-04-20 15:02:53 -070019 return nil;
20
21 return (((a >> 2) - (b >> 2)) << 2) | INT_TAG;
22}
23
swissChili53472e82021-05-08 16:06:32 -070024value_t l_times(value_t a, value_t b)
swissChili6aff2bb2021-04-20 15:02:53 -070025{
swissChili53472e82021-05-08 16:06:32 -070026 if (!integerp(a) || !integerp(b))
swissChili6aff2bb2021-04-20 15:02:53 -070027 return nil;
28
29 return (((a >> 2) * (b >> 2)) << 2) | INT_TAG;
30}
31
swissChili53472e82021-05-08 16:06:32 -070032value_t l_divide(value_t a, value_t b)
swissChili6aff2bb2021-04-20 15:02:53 -070033{
swissChili53472e82021-05-08 16:06:32 -070034 if (!integerp(a) || !integerp(b))
swissChili6aff2bb2021-04-20 15:02:53 -070035 return nil;
36
37 return (((a >> 2) / (b >> 2)) << 2) | INT_TAG;
38}
39
swissChili53472e82021-05-08 16:06:32 -070040value_t l_printval(value_t val)
swissChili8fc5e2f2021-04-22 13:45:10 -070041{
swissChili53472e82021-05-08 16:06:32 -070042 printval(val, 0);
swissChili8fc5e2f2021-04-22 13:45:10 -070043 return nil;
44}
45
swissChiliddc97542021-07-04 11:47:42 -070046value_t l_apply(value_t func, value_t args)
47{
48 if (!closurep(func))
49 return nil;
50
51 if (!listp(args))
52 return nil;
53
54 return call_list_closure((struct closure *)(func ^ CLOSURE_TAG), args);
55}
56
swissChili15f1cae2021-07-05 19:08:47 -070057value_t l_nilp(value_t val)
58{
59 return nilp(val) ? t : nil;
60}
61
62void add_function(struct environment *env, char *name, void *func, struct args *args, enum namespace ns)
swissChilib3ca4fb2021-04-20 10:33:00 -070063{
swissChili53472e82021-05-08 16:06:32 -070064 struct function *last, *new = malloc(sizeof(struct function));
swissChilib3ca4fb2021-04-20 10:33:00 -070065
66 last = env->first;
67 new->prev = last;
68 new->name = name;
swissChili15f1cae2021-07-05 19:08:47 -070069 new->args = args;
swissChilib3ca4fb2021-04-20 10:33:00 -070070 new->code_ptr = func;
swissChili2999dd12021-07-02 14:19:53 -070071 new->namespace = ns;
swissChilib3ca4fb2021-04-20 10:33:00 -070072
swissChilif3e7f182021-04-20 13:57:22 -070073 env->first = new;
swissChilib3ca4fb2021-04-20 10:33:00 -070074}
75
swissChili1e8b7562021-12-22 21:22:57 -080076void add_c_varargs(struct environment *env, char *name, void *func, int nargs)
77{
78 struct args *args = new_args();
79 args->num_required = nargs;
80 args->variadic = true;
81
82 add_function(env, name, func, args, NS_FUNCTION);
83}
84
swissChili15f1cae2021-07-05 19:08:47 -070085void add_c_function(struct environment *env, char *name, void *func, int nargs)
86{
87 struct args *args = new_args();
88 args->num_required = nargs;
89
90 add_function(env, name, func, args, NS_FUNCTION);
91}
92
93value_t l_elt(value_t seq, value_t i)
94{
95 if (!listp(seq) || !integerp(i))
96 return nil;
97
98 return elt(seq, i >> 2);
99}
100
swissChili7e1393c2021-07-07 12:59:12 -0700101value_t l_read_stdin()
102{
103 char *string = read_input_line("lisp> ");
104 if (!string)
105 return nil;
106
107 struct istream *is = new_stristream_nt(string);
108
109 value_t val = nil;
swissChili36f2c692021-08-08 14:31:44 -0700110 struct error err = { 0 };
swissChili6d02af42021-08-05 19:49:01 -0700111
112 if (!IS_OKAY((err = read1(is, &val))))
113 {
114 ereport(err);
115
116 del_stristream(is);
117 free(string);
118 // tail recursion, yay!
119 return l_read_stdin();
120 }
swissChili7e1393c2021-07-07 12:59:12 -0700121
122 del_stristream(is);
123 free(string);
124
125 return val;
126}
127
swissChili53e7cd12021-08-02 21:55:53 -0700128value_t l_num_eq(value_t a, value_t b)
129{
130 if (!integerp(a) || !integerp(b))
131 {
132 return nil;
133 }
134
swissChili1e8b7562021-12-22 21:22:57 -0800135 return (a >> 2) == (b >> 2) ? t : nil;
136}
137
138value_t l_num_gt(value_t a, value_t b)
139{
140 if (!integerp(a) || !integerp(b))
141 return nil;
142
143 return (a >> 2) > (b >> 2) ? t : nil;
144}
145
146value_t l_num_lt(value_t a, value_t b)
147{
148 if (!integerp(a) || !integerp(b))
149 return nil;
150
151 return (a >> 2) < (b >> 2) ? t : nil;
152}
153
154value_t l_append(value_t l)
155{
156 if (nilp(l))
157 return l;
158
159 value_t first = nil;
160 value_t *last = NULL;
161
162 for (value_t item = l; !nilp(item); item = cdr(item))
163 {
164 value_t a = car(item);
165
166 if (!listp(a))
167 {
168 value_t new = cons(a, nil);
169 *last = new;
170 last = cdrref(new);
171 continue;
172 }
173
174 for (value_t i = a; !nilp(i); i = cdr(i))
175 {
176 value_t b = car(i);
177
178 if (!last)
179 {
180 first = cons(b, nil);
181 last = cdrref(first);
182 }
183 else
184 {
185 value_t new = cons(b, nil);
186 *last = new;
187 last = cdrref(new);
188 }
189 }
190 }
191
192 return first;
swissChili53e7cd12021-08-02 21:55:53 -0700193}
194
swissChilia890aed2022-07-30 17:13:07 -0700195value_t l_gc_stats()
196{
197 struct gc_stats stats = gc_get_stats();
198
199 return cons(intval(stats.total_allocs),
200 cons(intval(stats.gc_runs),
201 nil));
202}
203
swissChili04d94162022-07-30 21:46:49 -0700204value_t l_list_functions(value_t env)
205{
206 if (!integerp(env))
207 return nil;
208
209 struct environment *e = (void *)env;
210 value_t list = nil;
211
212 for (struct function *fun = e->first; fun; fun = fun->prev)
213 {
214 list = cons(symval(fun->name), list);
215 }
216
217 return list;
218}
219
swissChilifc5c9412021-08-08 19:08:26 -0700220#define LISP_PREDICATE(name) value_t l_##name(value_t v) { return name(v) ? t : nil; }
221
222LISP_PREDICATE(listp)
223LISP_PREDICATE(integerp)
224LISP_PREDICATE(symbolp)
225LISP_PREDICATE(closurep)
226LISP_PREDICATE(consp)
227
228#undef LISP_PREDICATE
229
swissChili6d02af42021-08-05 19:49:01 -0700230struct error load_std(struct environment *env)
swissChilib3ca4fb2021-04-20 10:33:00 -0700231{
swissChili6d02af42021-08-05 19:49:01 -0700232 E_INIT();
233
swissChili15f1cae2021-07-05 19:08:47 -0700234 add_c_function(env, "+", l_plus, 2);
235 add_c_function(env, "-", l_minus, 2);
236 add_c_function(env, "*", l_times, 2);
237 add_c_function(env, "/", l_divide, 2);
swissChili53e7cd12021-08-02 21:55:53 -0700238 add_c_function(env, "=", l_num_eq, 2);
swissChili1e8b7562021-12-22 21:22:57 -0800239 add_c_function(env, "<", l_num_lt, 2);
240 add_c_function(env, ">", l_num_gt, 2);
swissChili8fc5e2f2021-04-22 13:45:10 -0700241
swissChili15f1cae2021-07-05 19:08:47 -0700242 add_c_function(env, "car", car, 1);
243 add_c_function(env, "cdr", cdr, 1);
244 add_c_function(env, "cons", cons, 2);
swissChili8fc5e2f2021-04-22 13:45:10 -0700245
swissChili15f1cae2021-07-05 19:08:47 -0700246 add_c_function(env, "print", l_printval, 1);
swissChili7e1393c2021-07-07 12:59:12 -0700247 add_c_function(env, "read-stdin", l_read_stdin, 0);
swissChili15f1cae2021-07-05 19:08:47 -0700248 add_c_function(env, "apply", l_apply, 2);
swissChili1e8b7562021-12-22 21:22:57 -0800249 add_c_varargs(env, "append", l_append, 0);
swissChiliddc97542021-07-04 11:47:42 -0700250
swissChili15f1cae2021-07-05 19:08:47 -0700251 add_c_function(env, "nilp", l_nilp, 1);
swissChilifc5c9412021-08-08 19:08:26 -0700252 add_c_function(env, "listp", l_listp, 1);
253 add_c_function(env, "integerp", l_integerp, 1);
254 add_c_function(env, "symbolp", l_symbolp, 1);
255 add_c_function(env, "closurep", l_closurep, 1);
256 add_c_function(env, "functionp", l_closurep, 1);
257 add_c_function(env, "consp", l_consp, 1);
258
swissChili15f1cae2021-07-05 19:08:47 -0700259 add_c_function(env, "elt", l_elt, 2);
swissChilif68671f2021-07-05 14:14:44 -0700260
swissChilia890aed2022-07-30 17:13:07 -0700261 add_c_function(env, "gc-stats", l_gc_stats, 0);
262
swissChili04d94162022-07-30 21:46:49 -0700263 add_c_function(env, "env-functions", l_list_functions, 1);
264
swissChilif68671f2021-07-05 14:14:44 -0700265 if (!load_library(env, "std"))
266 {
swissChili1e8b7562021-12-22 21:22:57 -0800267 fprintf(stderr, "Not found std\n");
swissChili6d02af42021-08-05 19:49:01 -0700268 THROW(ENOTFOUND, "Could not load library `std`, make sure your $LISP_LIBRARY_PATH is correct.");
swissChilif68671f2021-07-05 14:14:44 -0700269 }
swissChili6d02af42021-08-05 19:49:01 -0700270
271 OKAY();
swissChilif68671f2021-07-05 14:14:44 -0700272}
273
274bool load_library(struct environment *env, char *name)
275{
276 char *lib_paths = getenv("LISP_LIBRARY_PATH");
277
278 if (!lib_paths)
279 lib_paths = "/lib/lisp";
280
281 for (char *p = strtok(lib_paths, ":"); p; p = strtok(NULL, ":"))
282 {
283 static char path[512];
284 snprintf(path, 512, "%s/%s.lisp", p, name);
285
286 if (file_exists(path))
287 {
swissChili1e8b7562021-12-22 21:22:57 -0800288 // fprintf(stderr, "loading path: %s\n", path);
swissChilif68671f2021-07-05 14:14:44 -0700289 return load(env, path);
290 }
291
292 snprintf(path, 512, "%s/%s/%s.lisp", p, name, name);
293
294 if (file_exists(path))
295 {
swissChili1e8b7562021-12-22 21:22:57 -0800296 // fprintf(stderr, "loading path: %s\n", path);
swissChilif68671f2021-07-05 14:14:44 -0700297 return load(env, path);
298 }
299 }
300
301 return false;
swissChilib3ca4fb2021-04-20 10:33:00 -0700302}