blob: 935df1ffc31d86603287739a27838f693bb80497 [file] [log] [blame]
swissChilib3ca4fb2021-04-20 10:33:00 -07001#include "std.h"
swissChilif68671f2021-07-05 14:14:44 -07002#include "../plat/plat.h"
swissChilif3e7f182021-04-20 13:57:22 -07003#include <stdlib.h>
swissChilif68671f2021-07-05 14:14:44 -07004#include <string.h>
swissChilib3ca4fb2021-04-20 10:33:00 -07005
swissChili53472e82021-05-08 16:06:32 -07006value_t l_plus(value_t a, value_t b)
swissChilib3ca4fb2021-04-20 10:33:00 -07007{
swissChili53472e82021-05-08 16:06:32 -07008 if (!integerp(a) || !integerp(b))
swissChilib3ca4fb2021-04-20 10:33:00 -07009 return nil;
10
11 return (((a >> 2) + (b >> 2)) << 2) | INT_TAG;
12}
13
swissChili53472e82021-05-08 16:06:32 -070014value_t l_minus(value_t a, value_t b)
swissChili6aff2bb2021-04-20 15:02:53 -070015{
swissChili53472e82021-05-08 16:06:32 -070016 if (!integerp(a) || !integerp(b))
swissChili6aff2bb2021-04-20 15:02:53 -070017 return nil;
18
19 return (((a >> 2) - (b >> 2)) << 2) | INT_TAG;
20}
21
swissChili53472e82021-05-08 16:06:32 -070022value_t l_times(value_t a, value_t b)
swissChili6aff2bb2021-04-20 15:02:53 -070023{
swissChili53472e82021-05-08 16:06:32 -070024 if (!integerp(a) || !integerp(b))
swissChili6aff2bb2021-04-20 15:02:53 -070025 return nil;
26
27 return (((a >> 2) * (b >> 2)) << 2) | INT_TAG;
28}
29
swissChili53472e82021-05-08 16:06:32 -070030value_t l_divide(value_t a, value_t b)
swissChili6aff2bb2021-04-20 15:02:53 -070031{
swissChili53472e82021-05-08 16:06:32 -070032 if (!integerp(a) || !integerp(b))
swissChili6aff2bb2021-04-20 15:02:53 -070033 return nil;
34
35 return (((a >> 2) / (b >> 2)) << 2) | INT_TAG;
36}
37
swissChili53472e82021-05-08 16:06:32 -070038value_t l_printval(value_t val)
swissChili8fc5e2f2021-04-22 13:45:10 -070039{
swissChili53472e82021-05-08 16:06:32 -070040 printval(val, 0);
swissChili8fc5e2f2021-04-22 13:45:10 -070041 return nil;
42}
43
swissChiliddc97542021-07-04 11:47:42 -070044value_t l_apply(value_t func, value_t args)
45{
46 if (!closurep(func))
47 return nil;
48
49 if (!listp(args))
50 return nil;
51
52 return call_list_closure((struct closure *)(func ^ CLOSURE_TAG), args);
53}
54
swissChili15f1cae2021-07-05 19:08:47 -070055value_t l_nilp(value_t val)
56{
57 return nilp(val) ? t : nil;
58}
59
60void add_function(struct environment *env, char *name, void *func, struct args *args, enum namespace ns)
swissChilib3ca4fb2021-04-20 10:33:00 -070061{
swissChili53472e82021-05-08 16:06:32 -070062 struct function *last, *new = malloc(sizeof(struct function));
swissChilib3ca4fb2021-04-20 10:33:00 -070063
64 last = env->first;
65 new->prev = last;
66 new->name = name;
swissChili15f1cae2021-07-05 19:08:47 -070067 new->args = args;
swissChilib3ca4fb2021-04-20 10:33:00 -070068 new->code_ptr = func;
swissChili2999dd12021-07-02 14:19:53 -070069 new->namespace = ns;
swissChilib3ca4fb2021-04-20 10:33:00 -070070
swissChilif3e7f182021-04-20 13:57:22 -070071 env->first = new;
swissChilib3ca4fb2021-04-20 10:33:00 -070072}
73
swissChili15f1cae2021-07-05 19:08:47 -070074void add_c_function(struct environment *env, char *name, void *func, int nargs)
75{
76 struct args *args = new_args();
77 args->num_required = nargs;
78
79 add_function(env, name, func, args, NS_FUNCTION);
80}
81
82value_t l_elt(value_t seq, value_t i)
83{
84 if (!listp(seq) || !integerp(i))
85 return nil;
86
87 return elt(seq, i >> 2);
88}
89
swissChili7e1393c2021-07-07 12:59:12 -070090value_t l_read_stdin()
91{
swissChili6d02af42021-08-05 19:49:01 -070092#ifndef NO_READLINE
swissChili7e1393c2021-07-07 12:59:12 -070093 char *string = read_input_line("lisp> ");
94 if (!string)
95 return nil;
96
97 struct istream *is = new_stristream_nt(string);
98
99 value_t val = nil;
swissChili36f2c692021-08-08 14:31:44 -0700100 struct error err = { 0 };
swissChili6d02af42021-08-05 19:49:01 -0700101
102 if (!IS_OKAY((err = read1(is, &val))))
103 {
104 ereport(err);
105
106 del_stristream(is);
107 free(string);
108 // tail recursion, yay!
109 return l_read_stdin();
110 }
swissChili7e1393c2021-07-07 12:59:12 -0700111
112 del_stristream(is);
113 free(string);
114
115 return val;
swissChili6d02af42021-08-05 19:49:01 -0700116#else
117 return nil;
118#endif
swissChili7e1393c2021-07-07 12:59:12 -0700119}
120
swissChili53e7cd12021-08-02 21:55:53 -0700121value_t l_num_eq(value_t a, value_t b)
122{
123 if (!integerp(a) || !integerp(b))
124 {
125 return nil;
126 }
127
128 return (a >> 3) == (b >> 3) ? t : nil;
129}
130
swissChilifc5c9412021-08-08 19:08:26 -0700131#define LISP_PREDICATE(name) value_t l_##name(value_t v) { return name(v) ? t : nil; }
132
133LISP_PREDICATE(listp)
134LISP_PREDICATE(integerp)
135LISP_PREDICATE(symbolp)
136LISP_PREDICATE(closurep)
137LISP_PREDICATE(consp)
138
139#undef LISP_PREDICATE
140
swissChili6d02af42021-08-05 19:49:01 -0700141struct error load_std(struct environment *env)
swissChilib3ca4fb2021-04-20 10:33:00 -0700142{
swissChili6d02af42021-08-05 19:49:01 -0700143 E_INIT();
144
swissChili15f1cae2021-07-05 19:08:47 -0700145 add_c_function(env, "+", l_plus, 2);
146 add_c_function(env, "-", l_minus, 2);
147 add_c_function(env, "*", l_times, 2);
148 add_c_function(env, "/", l_divide, 2);
swissChili53e7cd12021-08-02 21:55:53 -0700149 add_c_function(env, "=", l_num_eq, 2);
swissChili8fc5e2f2021-04-22 13:45:10 -0700150
swissChili15f1cae2021-07-05 19:08:47 -0700151 add_c_function(env, "car", car, 1);
152 add_c_function(env, "cdr", cdr, 1);
153 add_c_function(env, "cons", cons, 2);
swissChili8fc5e2f2021-04-22 13:45:10 -0700154
swissChili15f1cae2021-07-05 19:08:47 -0700155 add_c_function(env, "print", l_printval, 1);
swissChili7e1393c2021-07-07 12:59:12 -0700156 add_c_function(env, "read-stdin", l_read_stdin, 0);
swissChili15f1cae2021-07-05 19:08:47 -0700157 add_c_function(env, "apply", l_apply, 2);
swissChiliddc97542021-07-04 11:47:42 -0700158
swissChili15f1cae2021-07-05 19:08:47 -0700159 add_c_function(env, "nilp", l_nilp, 1);
swissChilifc5c9412021-08-08 19:08:26 -0700160 add_c_function(env, "listp", l_listp, 1);
161 add_c_function(env, "integerp", l_integerp, 1);
162 add_c_function(env, "symbolp", l_symbolp, 1);
163 add_c_function(env, "closurep", l_closurep, 1);
164 add_c_function(env, "functionp", l_closurep, 1);
165 add_c_function(env, "consp", l_consp, 1);
166
swissChili15f1cae2021-07-05 19:08:47 -0700167 add_c_function(env, "elt", l_elt, 2);
swissChilif68671f2021-07-05 14:14:44 -0700168
169 if (!load_library(env, "std"))
170 {
swissChili6d02af42021-08-05 19:49:01 -0700171 THROW(ENOTFOUND, "Could not load library `std`, make sure your $LISP_LIBRARY_PATH is correct.");
swissChilif68671f2021-07-05 14:14:44 -0700172 }
swissChili6d02af42021-08-05 19:49:01 -0700173
174 OKAY();
swissChilif68671f2021-07-05 14:14:44 -0700175}
176
177bool load_library(struct environment *env, char *name)
178{
179 char *lib_paths = getenv("LISP_LIBRARY_PATH");
180
181 if (!lib_paths)
182 lib_paths = "/lib/lisp";
183
184 for (char *p = strtok(lib_paths, ":"); p; p = strtok(NULL, ":"))
185 {
186 static char path[512];
187 snprintf(path, 512, "%s/%s.lisp", p, name);
188
189 if (file_exists(path))
190 {
swissChilifc5c9412021-08-08 19:08:26 -0700191 fprintf(stderr, "path: %s\n", path);
swissChilif68671f2021-07-05 14:14:44 -0700192 return load(env, path);
193 }
194
195 snprintf(path, 512, "%s/%s/%s.lisp", p, name, name);
196
197 if (file_exists(path))
198 {
swissChilifc5c9412021-08-08 19:08:26 -0700199 fprintf(stderr, "path: %s\n", path);
swissChilif68671f2021-07-05 14:14:44 -0700200 return load(env, path);
201 }
202 }
203
204 return false;
swissChilib3ca4fb2021-04-20 10:33:00 -0700205}