blob: 1afe9936286c159f7af8a2c9b50e3dab3abfe533 [file] [log] [blame]
swissChilib3ca4fb2021-04-20 10:33:00 -07001#include "std.h"
swissChilia890aed2022-07-30 17:13:07 -07002#include "../gc.h"
swissChilif68671f2021-07-05 14:14:44 -07003#include "../plat/plat.h"
swissChilif3e7f182021-04-20 13:57:22 -07004#include <stdlib.h>
swissChilif68671f2021-07-05 14:14:44 -07005#include <string.h>
swissChilib3ca4fb2021-04-20 10:33:00 -07006
swissChili53472e82021-05-08 16:06:32 -07007value_t l_plus(value_t a, value_t b)
swissChilib3ca4fb2021-04-20 10:33:00 -07008{
swissChili53472e82021-05-08 16:06:32 -07009 if (!integerp(a) || !integerp(b))
swissChilib3ca4fb2021-04-20 10:33:00 -070010 return nil;
11
12 return (((a >> 2) + (b >> 2)) << 2) | INT_TAG;
13}
14
swissChili53472e82021-05-08 16:06:32 -070015value_t l_minus(value_t a, value_t b)
swissChili6aff2bb2021-04-20 15:02:53 -070016{
swissChili53472e82021-05-08 16:06:32 -070017 if (!integerp(a) || !integerp(b))
swissChili6aff2bb2021-04-20 15:02:53 -070018 return nil;
19
20 return (((a >> 2) - (b >> 2)) << 2) | INT_TAG;
21}
22
swissChili53472e82021-05-08 16:06:32 -070023value_t l_times(value_t a, value_t b)
swissChili6aff2bb2021-04-20 15:02:53 -070024{
swissChili53472e82021-05-08 16:06:32 -070025 if (!integerp(a) || !integerp(b))
swissChili6aff2bb2021-04-20 15:02:53 -070026 return nil;
27
28 return (((a >> 2) * (b >> 2)) << 2) | INT_TAG;
29}
30
swissChili53472e82021-05-08 16:06:32 -070031value_t l_divide(value_t a, value_t b)
swissChili6aff2bb2021-04-20 15:02:53 -070032{
swissChili53472e82021-05-08 16:06:32 -070033 if (!integerp(a) || !integerp(b))
swissChili6aff2bb2021-04-20 15:02:53 -070034 return nil;
35
36 return (((a >> 2) / (b >> 2)) << 2) | INT_TAG;
37}
38
swissChili53472e82021-05-08 16:06:32 -070039value_t l_printval(value_t val)
swissChili8fc5e2f2021-04-22 13:45:10 -070040{
swissChili53472e82021-05-08 16:06:32 -070041 printval(val, 0);
swissChili8fc5e2f2021-04-22 13:45:10 -070042 return nil;
43}
44
swissChiliddc97542021-07-04 11:47:42 -070045value_t l_apply(value_t func, value_t args)
46{
47 if (!closurep(func))
48 return nil;
49
50 if (!listp(args))
51 return nil;
52
53 return call_list_closure((struct closure *)(func ^ CLOSURE_TAG), args);
54}
55
swissChili15f1cae2021-07-05 19:08:47 -070056value_t l_nilp(value_t val)
57{
58 return nilp(val) ? t : nil;
59}
60
61void add_function(struct environment *env, char *name, void *func, struct args *args, enum namespace ns)
swissChilib3ca4fb2021-04-20 10:33:00 -070062{
swissChili53472e82021-05-08 16:06:32 -070063 struct function *last, *new = malloc(sizeof(struct function));
swissChilib3ca4fb2021-04-20 10:33:00 -070064
65 last = env->first;
66 new->prev = last;
67 new->name = name;
swissChili15f1cae2021-07-05 19:08:47 -070068 new->args = args;
swissChilib3ca4fb2021-04-20 10:33:00 -070069 new->code_ptr = func;
swissChili2999dd12021-07-02 14:19:53 -070070 new->namespace = ns;
swissChilib3ca4fb2021-04-20 10:33:00 -070071
swissChilif3e7f182021-04-20 13:57:22 -070072 env->first = new;
swissChilib3ca4fb2021-04-20 10:33:00 -070073}
74
swissChili1e8b7562021-12-22 21:22:57 -080075void add_c_varargs(struct environment *env, char *name, void *func, int nargs)
76{
77 struct args *args = new_args();
78 args->num_required = nargs;
79 args->variadic = true;
80
81 add_function(env, name, func, args, NS_FUNCTION);
82}
83
swissChili15f1cae2021-07-05 19:08:47 -070084void add_c_function(struct environment *env, char *name, void *func, int nargs)
85{
86 struct args *args = new_args();
87 args->num_required = nargs;
88
89 add_function(env, name, func, args, NS_FUNCTION);
90}
91
92value_t l_elt(value_t seq, value_t i)
93{
94 if (!listp(seq) || !integerp(i))
95 return nil;
96
97 return elt(seq, i >> 2);
98}
99
swissChili7e1393c2021-07-07 12:59:12 -0700100value_t l_read_stdin()
101{
102 char *string = read_input_line("lisp> ");
103 if (!string)
104 return nil;
105
106 struct istream *is = new_stristream_nt(string);
107
108 value_t val = nil;
swissChili36f2c692021-08-08 14:31:44 -0700109 struct error err = { 0 };
swissChili6d02af42021-08-05 19:49:01 -0700110
111 if (!IS_OKAY((err = read1(is, &val))))
112 {
113 ereport(err);
114
115 del_stristream(is);
116 free(string);
117 // tail recursion, yay!
118 return l_read_stdin();
119 }
swissChili7e1393c2021-07-07 12:59:12 -0700120
121 del_stristream(is);
122 free(string);
123
124 return val;
125}
126
swissChili53e7cd12021-08-02 21:55:53 -0700127value_t l_num_eq(value_t a, value_t b)
128{
129 if (!integerp(a) || !integerp(b))
130 {
131 return nil;
132 }
133
swissChili1e8b7562021-12-22 21:22:57 -0800134 return (a >> 2) == (b >> 2) ? t : nil;
135}
136
137value_t l_num_gt(value_t a, value_t b)
138{
139 if (!integerp(a) || !integerp(b))
140 return nil;
141
142 return (a >> 2) > (b >> 2) ? t : nil;
143}
144
145value_t l_num_lt(value_t a, value_t b)
146{
147 if (!integerp(a) || !integerp(b))
148 return nil;
149
150 return (a >> 2) < (b >> 2) ? t : nil;
151}
152
153value_t l_append(value_t l)
154{
155 if (nilp(l))
156 return l;
157
158 value_t first = nil;
159 value_t *last = NULL;
160
161 for (value_t item = l; !nilp(item); item = cdr(item))
162 {
163 value_t a = car(item);
164
165 if (!listp(a))
166 {
167 value_t new = cons(a, nil);
168 *last = new;
169 last = cdrref(new);
170 continue;
171 }
172
173 for (value_t i = a; !nilp(i); i = cdr(i))
174 {
175 value_t b = car(i);
176
177 if (!last)
178 {
179 first = cons(b, nil);
180 last = cdrref(first);
181 }
182 else
183 {
184 value_t new = cons(b, nil);
185 *last = new;
186 last = cdrref(new);
187 }
188 }
189 }
190
191 return first;
swissChili53e7cd12021-08-02 21:55:53 -0700192}
193
swissChilia890aed2022-07-30 17:13:07 -0700194value_t l_gc_stats()
195{
196 struct gc_stats stats = gc_get_stats();
197
198 return cons(intval(stats.total_allocs),
199 cons(intval(stats.gc_runs),
200 nil));
201}
202
swissChilifc5c9412021-08-08 19:08:26 -0700203#define LISP_PREDICATE(name) value_t l_##name(value_t v) { return name(v) ? t : nil; }
204
205LISP_PREDICATE(listp)
206LISP_PREDICATE(integerp)
207LISP_PREDICATE(symbolp)
208LISP_PREDICATE(closurep)
209LISP_PREDICATE(consp)
210
211#undef LISP_PREDICATE
212
swissChili6d02af42021-08-05 19:49:01 -0700213struct error load_std(struct environment *env)
swissChilib3ca4fb2021-04-20 10:33:00 -0700214{
swissChili6d02af42021-08-05 19:49:01 -0700215 E_INIT();
216
swissChili15f1cae2021-07-05 19:08:47 -0700217 add_c_function(env, "+", l_plus, 2);
218 add_c_function(env, "-", l_minus, 2);
219 add_c_function(env, "*", l_times, 2);
220 add_c_function(env, "/", l_divide, 2);
swissChili53e7cd12021-08-02 21:55:53 -0700221 add_c_function(env, "=", l_num_eq, 2);
swissChili1e8b7562021-12-22 21:22:57 -0800222 add_c_function(env, "<", l_num_lt, 2);
223 add_c_function(env, ">", l_num_gt, 2);
swissChili8fc5e2f2021-04-22 13:45:10 -0700224
swissChili15f1cae2021-07-05 19:08:47 -0700225 add_c_function(env, "car", car, 1);
226 add_c_function(env, "cdr", cdr, 1);
227 add_c_function(env, "cons", cons, 2);
swissChili8fc5e2f2021-04-22 13:45:10 -0700228
swissChili15f1cae2021-07-05 19:08:47 -0700229 add_c_function(env, "print", l_printval, 1);
swissChili7e1393c2021-07-07 12:59:12 -0700230 add_c_function(env, "read-stdin", l_read_stdin, 0);
swissChili15f1cae2021-07-05 19:08:47 -0700231 add_c_function(env, "apply", l_apply, 2);
swissChili1e8b7562021-12-22 21:22:57 -0800232 add_c_varargs(env, "append", l_append, 0);
swissChiliddc97542021-07-04 11:47:42 -0700233
swissChili15f1cae2021-07-05 19:08:47 -0700234 add_c_function(env, "nilp", l_nilp, 1);
swissChilifc5c9412021-08-08 19:08:26 -0700235 add_c_function(env, "listp", l_listp, 1);
236 add_c_function(env, "integerp", l_integerp, 1);
237 add_c_function(env, "symbolp", l_symbolp, 1);
238 add_c_function(env, "closurep", l_closurep, 1);
239 add_c_function(env, "functionp", l_closurep, 1);
240 add_c_function(env, "consp", l_consp, 1);
241
swissChili15f1cae2021-07-05 19:08:47 -0700242 add_c_function(env, "elt", l_elt, 2);
swissChilif68671f2021-07-05 14:14:44 -0700243
swissChilia890aed2022-07-30 17:13:07 -0700244 add_c_function(env, "gc-stats", l_gc_stats, 0);
245
swissChilif68671f2021-07-05 14:14:44 -0700246 if (!load_library(env, "std"))
247 {
swissChili1e8b7562021-12-22 21:22:57 -0800248 fprintf(stderr, "Not found std\n");
swissChili6d02af42021-08-05 19:49:01 -0700249 THROW(ENOTFOUND, "Could not load library `std`, make sure your $LISP_LIBRARY_PATH is correct.");
swissChilif68671f2021-07-05 14:14:44 -0700250 }
swissChili6d02af42021-08-05 19:49:01 -0700251
252 OKAY();
swissChilif68671f2021-07-05 14:14:44 -0700253}
254
255bool load_library(struct environment *env, char *name)
256{
257 char *lib_paths = getenv("LISP_LIBRARY_PATH");
258
259 if (!lib_paths)
260 lib_paths = "/lib/lisp";
261
262 for (char *p = strtok(lib_paths, ":"); p; p = strtok(NULL, ":"))
263 {
264 static char path[512];
265 snprintf(path, 512, "%s/%s.lisp", p, name);
266
267 if (file_exists(path))
268 {
swissChili1e8b7562021-12-22 21:22:57 -0800269 // fprintf(stderr, "loading path: %s\n", path);
swissChilif68671f2021-07-05 14:14:44 -0700270 return load(env, path);
271 }
272
273 snprintf(path, 512, "%s/%s/%s.lisp", p, name, name);
274
275 if (file_exists(path))
276 {
swissChili1e8b7562021-12-22 21:22:57 -0800277 // fprintf(stderr, "loading path: %s\n", path);
swissChilif68671f2021-07-05 14:14:44 -0700278 return load(env, path);
279 }
280 }
281
282 return false;
swissChilib3ca4fb2021-04-20 10:33:00 -0700283}