altos/lisp: Lots more scheme bits
[fw/altos] / src / lisp / ao_lisp_builtin.c
1 /*
2  * Copyright © 2016 Keith Packard <keithp@keithp.com>
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * General Public License for more details.
13  */
14
15 #include "ao_lisp.h"
16
17 static int
18 builtin_size(void *addr)
19 {
20         (void) addr;
21         return sizeof (struct ao_lisp_builtin);
22 }
23
24 static void
25 builtin_mark(void *addr)
26 {
27         (void) addr;
28 }
29
30 static void
31 builtin_move(void *addr)
32 {
33         (void) addr;
34 }
35
36 const struct ao_lisp_type ao_lisp_builtin_type = {
37         .size = builtin_size,
38         .mark = builtin_mark,
39         .move = builtin_move
40 };
41
42 #ifdef AO_LISP_MAKE_CONST
43
44 #define AO_LISP_BUILTIN_CASENAME
45 #include "ao_lisp_builtin.h"
46
47 #define _atomn(n)       ao_lisp_poly_atom(_atom(n))
48
49 char *ao_lisp_args_name(uint8_t args) {
50         args &= AO_LISP_FUNC_MASK;
51         switch (args) {
52         case AO_LISP_FUNC_LAMBDA: return _atomn(lambda)->name;
53         case AO_LISP_FUNC_LEXPR: return _atomn(lexpr)->name;
54         case AO_LISP_FUNC_NLAMBDA: return _atomn(nlambda)->name;
55         case AO_LISP_FUNC_MACRO: return _atomn(macro)->name;
56         default: return "???";
57         }
58 }
59 #else
60
61 #define AO_LISP_BUILTIN_ARRAYNAME
62 #include "ao_lisp_builtin.h"
63
64 static char *
65 ao_lisp_builtin_name(enum ao_lisp_builtin_id b) {
66         if (b < _builtin_last)
67                 return ao_lisp_poly_atom(builtin_names[b])->name;
68         return "???";
69 }
70
71 static const ao_poly ao_lisp_args_atoms[] = {
72         [AO_LISP_FUNC_LAMBDA] = _ao_lisp_atom_lambda,
73         [AO_LISP_FUNC_LEXPR] = _ao_lisp_atom_lexpr,
74         [AO_LISP_FUNC_NLAMBDA] = _ao_lisp_atom_nlambda,
75         [AO_LISP_FUNC_MACRO] = _ao_lisp_atom_macro,
76 };
77
78 char *
79 ao_lisp_args_name(uint8_t args)
80 {
81         args &= AO_LISP_FUNC_MASK;
82         if (args < sizeof ao_lisp_args_atoms / sizeof ao_lisp_args_atoms[0])
83                 return ao_lisp_poly_atom(ao_lisp_args_atoms[args])->name;
84         return "(unknown)";
85 }
86 #endif
87
88 void
89 ao_lisp_builtin_print(ao_poly b)
90 {
91         struct ao_lisp_builtin *builtin = ao_lisp_poly_builtin(b);
92         printf("%s", ao_lisp_builtin_name(builtin->func));
93 }
94
95 ao_poly
96 ao_lisp_check_argc(ao_poly name, struct ao_lisp_cons *cons, int min, int max)
97 {
98         int     argc = 0;
99
100         while (cons && argc <= max) {
101                 argc++;
102                 cons = ao_lisp_poly_cons(cons->cdr);
103         }
104         if (argc < min || argc > max)
105                 return ao_lisp_error(AO_LISP_INVALID, "%s: invalid arg count", ao_lisp_poly_atom(name)->name);
106         return _ao_lisp_bool_true;
107 }
108
109 ao_poly
110 ao_lisp_arg(struct ao_lisp_cons *cons, int argc)
111 {
112         if (!cons)
113                 return AO_LISP_NIL;
114         while (argc--) {
115                 if (!cons)
116                         return AO_LISP_NIL;
117                 cons = ao_lisp_poly_cons(cons->cdr);
118         }
119         return cons->car;
120 }
121
122 ao_poly
123 ao_lisp_check_argt(ao_poly name, struct ao_lisp_cons *cons, int argc, int type, int nil_ok)
124 {
125         ao_poly car = ao_lisp_arg(cons, argc);
126
127         if ((!car && !nil_ok) || ao_lisp_poly_type(car) != type)
128                 return ao_lisp_error(AO_LISP_INVALID, "%s: invalid type for arg %d", ao_lisp_poly_atom(name)->name, argc);
129         return _ao_lisp_bool_true;
130 }
131
132 ao_poly
133 ao_lisp_do_car(struct ao_lisp_cons *cons)
134 {
135         if (!ao_lisp_check_argc(_ao_lisp_atom_car, cons, 1, 1))
136                 return AO_LISP_NIL;
137         if (!ao_lisp_check_argt(_ao_lisp_atom_car, cons, 0, AO_LISP_CONS, 0))
138                 return AO_LISP_NIL;
139         return ao_lisp_poly_cons(cons->car)->car;
140 }
141
142 ao_poly
143 ao_lisp_do_cdr(struct ao_lisp_cons *cons)
144 {
145         if (!ao_lisp_check_argc(_ao_lisp_atom_cdr, cons, 1, 1))
146                 return AO_LISP_NIL;
147         if (!ao_lisp_check_argt(_ao_lisp_atom_cdr, cons, 0, AO_LISP_CONS, 0))
148                 return AO_LISP_NIL;
149         return ao_lisp_poly_cons(cons->car)->cdr;
150 }
151
152 ao_poly
153 ao_lisp_do_cons(struct ao_lisp_cons *cons)
154 {
155         ao_poly car, cdr;
156         if(!ao_lisp_check_argc(_ao_lisp_atom_cons, cons, 2, 2))
157                 return AO_LISP_NIL;
158         car = ao_lisp_arg(cons, 0);
159         cdr = ao_lisp_arg(cons, 1);
160         return ao_lisp__cons(car, cdr);
161 }
162
163 ao_poly
164 ao_lisp_do_last(struct ao_lisp_cons *cons)
165 {
166         ao_poly l;
167         if (!ao_lisp_check_argc(_ao_lisp_atom_last, cons, 1, 1))
168                 return AO_LISP_NIL;
169         if (!ao_lisp_check_argt(_ao_lisp_atom_last, cons, 0, AO_LISP_CONS, 1))
170                 return AO_LISP_NIL;
171         l = ao_lisp_arg(cons, 0);
172         while (l) {
173                 struct ao_lisp_cons *list = ao_lisp_poly_cons(l);
174                 if (!list->cdr)
175                         return list->car;
176                 l = list->cdr;
177         }
178         return AO_LISP_NIL;
179 }
180
181 ao_poly
182 ao_lisp_do_length(struct ao_lisp_cons *cons)
183 {
184         if (!ao_lisp_check_argc(_ao_lisp_atom_length, cons, 1, 1))
185                 return AO_LISP_NIL;
186         if (!ao_lisp_check_argt(_ao_lisp_atom_length, cons, 0, AO_LISP_CONS, 1))
187                 return AO_LISP_NIL;
188         return ao_lisp_int_poly(ao_lisp_cons_length(ao_lisp_poly_cons(ao_lisp_arg(cons, 0))));
189 }
190
191 ao_poly
192 ao_lisp_do_quote(struct ao_lisp_cons *cons)
193 {
194         if (!ao_lisp_check_argc(_ao_lisp_atom_quote, cons, 1, 1))
195                 return AO_LISP_NIL;
196         return ao_lisp_arg(cons, 0);
197 }
198
199 ao_poly
200 ao_lisp_do_set(struct ao_lisp_cons *cons)
201 {
202         if (!ao_lisp_check_argc(_ao_lisp_atom_set, cons, 2, 2))
203                 return AO_LISP_NIL;
204         if (!ao_lisp_check_argt(_ao_lisp_atom_set, cons, 0, AO_LISP_ATOM, 0))
205                 return AO_LISP_NIL;
206
207         return ao_lisp_atom_set(ao_lisp_arg(cons, 0), ao_lisp_arg(cons, 1));
208 }
209
210 ao_poly
211 ao_lisp_do_setq(struct ao_lisp_cons *cons)
212 {
213         ao_poly name;
214         if (!ao_lisp_check_argc(_ao_lisp_atom_setq, cons, 2, 2))
215                 return AO_LISP_NIL;
216         name = cons->car;
217         if (ao_lisp_poly_type(name) != AO_LISP_ATOM)
218                 return ao_lisp_error(AO_LISP_INVALID, "set! of non-atom");
219         if (!ao_lisp_atom_ref(ao_lisp_frame_current, name))
220                 return ao_lisp_error(AO_LISP_INVALID, "atom not defined");
221         return ao_lisp__cons(_ao_lisp_atom_set,
222                              ao_lisp__cons(ao_lisp__cons(_ao_lisp_atom_quote,
223                                                          ao_lisp__cons(name, AO_LISP_NIL)),
224                                            cons->cdr));
225 }
226
227 ao_poly
228 ao_lisp_do_cond(struct ao_lisp_cons *cons)
229 {
230         ao_lisp_set_cond(cons);
231         return AO_LISP_NIL;
232 }
233
234 ao_poly
235 ao_lisp_do_progn(struct ao_lisp_cons *cons)
236 {
237         ao_lisp_stack->state = eval_progn;
238         ao_lisp_stack->sexprs = ao_lisp_cons_poly(cons);
239         return AO_LISP_NIL;
240 }
241
242 ao_poly
243 ao_lisp_do_while(struct ao_lisp_cons *cons)
244 {
245         ao_lisp_stack->state = eval_while;
246         ao_lisp_stack->sexprs = ao_lisp_cons_poly(cons);
247         return AO_LISP_NIL;
248 }
249
250 ao_poly
251 ao_lisp_do_print(struct ao_lisp_cons *cons)
252 {
253         ao_poly val = AO_LISP_NIL;
254         while (cons) {
255                 val = cons->car;
256                 ao_lisp_poly_print(val);
257                 cons = ao_lisp_poly_cons(cons->cdr);
258                 if (cons)
259                         printf(" ");
260         }
261         printf("\n");
262         return val;
263 }
264
265 ao_poly
266 ao_lisp_do_patom(struct ao_lisp_cons *cons)
267 {
268         ao_poly val = AO_LISP_NIL;
269         while (cons) {
270                 val = cons->car;
271                 ao_lisp_poly_patom(val);
272                 cons = ao_lisp_poly_cons(cons->cdr);
273         }
274         return val;
275 }
276
277 ao_poly
278 ao_lisp_math(struct ao_lisp_cons *cons, enum ao_lisp_builtin_id op)
279 {
280         struct ao_lisp_cons *orig_cons = cons;
281         ao_poly ret = AO_LISP_NIL;
282
283         while (cons) {
284                 ao_poly         car = cons->car;
285                 uint8_t         rt = ao_lisp_poly_type(ret);
286                 uint8_t         ct = ao_lisp_poly_type(car);
287
288                 if (cons == orig_cons) {
289                         ret = car;
290                         if (cons->cdr == AO_LISP_NIL && ct == AO_LISP_INT) {
291                                 switch (op) {
292                                 case builtin_minus:
293                                         ret = ao_lisp_int_poly(-ao_lisp_poly_int(ret));
294                                         break;
295                                 case builtin_divide:
296                                         switch (ao_lisp_poly_int(ret)) {
297                                         case 0:
298                                                 return ao_lisp_error(AO_LISP_DIVIDE_BY_ZERO, "divide by zero");
299                                         case 1:
300                                                 break;
301                                         default:
302                                                 ret = ao_lisp_int_poly(0);
303                                                 break;
304                                         }
305                                         break;
306                                 default:
307                                         break;
308                                 }
309                         }
310                 } else if (rt == AO_LISP_INT && ct == AO_LISP_INT) {
311                         int     r = ao_lisp_poly_int(ret);
312                         int     c = ao_lisp_poly_int(car);
313
314                         switch(op) {
315                         case builtin_plus:
316                                 r += c;
317                                 break;
318                         case builtin_minus:
319                                 r -= c;
320                                 break;
321                         case builtin_times:
322                                 r *= c;
323                                 break;
324                         case builtin_divide:
325                                 if (c == 0)
326                                         return ao_lisp_error(AO_LISP_DIVIDE_BY_ZERO, "divide by zero");
327                                 r /= c;
328                                 break;
329                         case builtin_quotient:
330                                 if (c == 0)
331                                         return ao_lisp_error(AO_LISP_DIVIDE_BY_ZERO, "quotient by zero");
332                                 if (r % c != 0 && (c < 0) != (r < 0))
333                                         r = r / c - 1;
334                                 else
335                                         r = r / c;
336                                 break;
337                         case builtin_remainder:
338                                 if (c == 0)
339                                         return ao_lisp_error(AO_LISP_DIVIDE_BY_ZERO, "remainder by zero");
340                                 r %= c;
341                                 break;
342                         case builtin_modulo:
343                                 if (c == 0)
344                                         return ao_lisp_error(AO_LISP_DIVIDE_BY_ZERO, "modulo by zero");
345                                 r %= c;
346                                 if ((r < 0) != (c < 0))
347                                         r += c;
348                                 break;
349                         default:
350                                 break;
351                         }
352                         ret = ao_lisp_int_poly(r);
353                 }
354
355                 else if (rt == AO_LISP_STRING && ct == AO_LISP_STRING && op == builtin_plus)
356                         ret = ao_lisp_string_poly(ao_lisp_string_cat(ao_lisp_poly_string(ret),
357                                                                      ao_lisp_poly_string(car)));
358                 else
359                         return ao_lisp_error(AO_LISP_INVALID, "invalid args");
360
361                 cons = ao_lisp_poly_cons(cons->cdr);
362         }
363         return ret;
364 }
365
366 ao_poly
367 ao_lisp_do_plus(struct ao_lisp_cons *cons)
368 {
369         return ao_lisp_math(cons, builtin_plus);
370 }
371
372 ao_poly
373 ao_lisp_do_minus(struct ao_lisp_cons *cons)
374 {
375         return ao_lisp_math(cons, builtin_minus);
376 }
377
378 ao_poly
379 ao_lisp_do_times(struct ao_lisp_cons *cons)
380 {
381         return ao_lisp_math(cons, builtin_times);
382 }
383
384 ao_poly
385 ao_lisp_do_divide(struct ao_lisp_cons *cons)
386 {
387         return ao_lisp_math(cons, builtin_divide);
388 }
389
390 ao_poly
391 ao_lisp_do_quotient(struct ao_lisp_cons *cons)
392 {
393         return ao_lisp_math(cons, builtin_quotient);
394 }
395
396 ao_poly
397 ao_lisp_do_modulo(struct ao_lisp_cons *cons)
398 {
399         return ao_lisp_math(cons, builtin_modulo);
400 }
401
402 ao_poly
403 ao_lisp_do_remainder(struct ao_lisp_cons *cons)
404 {
405         return ao_lisp_math(cons, builtin_remainder);
406 }
407
408 ao_poly
409 ao_lisp_compare(struct ao_lisp_cons *cons, enum ao_lisp_builtin_id op)
410 {
411         ao_poly left;
412
413         if (!cons)
414                 return _ao_lisp_bool_true;
415
416         left = cons->car;
417         cons = ao_lisp_poly_cons(cons->cdr);
418         while (cons) {
419                 ao_poly right = cons->car;
420
421                 if (op == builtin_equal) {
422                         if (left != right)
423                                 return _ao_lisp_bool_false;
424                 } else {
425                         uint8_t lt = ao_lisp_poly_type(left);
426                         uint8_t rt = ao_lisp_poly_type(right);
427                         if (lt == AO_LISP_INT && rt == AO_LISP_INT) {
428                                 int l = ao_lisp_poly_int(left);
429                                 int r = ao_lisp_poly_int(right);
430
431                                 switch (op) {
432                                 case builtin_less:
433                                         if (!(l < r))
434                                                 return _ao_lisp_bool_false;
435                                         break;
436                                 case builtin_greater:
437                                         if (!(l > r))
438                                                 return _ao_lisp_bool_false;
439                                         break;
440                                 case builtin_less_equal:
441                                         if (!(l <= r))
442                                                 return _ao_lisp_bool_false;
443                                         break;
444                                 case builtin_greater_equal:
445                                         if (!(l >= r))
446                                                 return _ao_lisp_bool_false;
447                                         break;
448                                 default:
449                                         break;
450                                 }
451                         } else if (lt == AO_LISP_STRING && rt == AO_LISP_STRING) {
452                                 int c = strcmp(ao_lisp_poly_string(left),
453                                                ao_lisp_poly_string(right));
454                                 switch (op) {
455                                 case builtin_less:
456                                         if (!(c < 0))
457                                                 return _ao_lisp_bool_false;
458                                         break;
459                                 case builtin_greater:
460                                         if (!(c > 0))
461                                                 return _ao_lisp_bool_false;
462                                         break;
463                                 case builtin_less_equal:
464                                         if (!(c <= 0))
465                                                 return _ao_lisp_bool_false;
466                                         break;
467                                 case builtin_greater_equal:
468                                         if (!(c >= 0))
469                                                 return _ao_lisp_bool_false;
470                                         break;
471                                 default:
472                                         break;
473                                 }
474                         }
475                 }
476                 left = right;
477                 cons = ao_lisp_poly_cons(cons->cdr);
478         }
479         return _ao_lisp_bool_true;
480 }
481
482 ao_poly
483 ao_lisp_do_equal(struct ao_lisp_cons *cons)
484 {
485         return ao_lisp_compare(cons, builtin_equal);
486 }
487
488 ao_poly
489 ao_lisp_do_less(struct ao_lisp_cons *cons)
490 {
491         return ao_lisp_compare(cons, builtin_less);
492 }
493
494 ao_poly
495 ao_lisp_do_greater(struct ao_lisp_cons *cons)
496 {
497         return ao_lisp_compare(cons, builtin_greater);
498 }
499
500 ao_poly
501 ao_lisp_do_less_equal(struct ao_lisp_cons *cons)
502 {
503         return ao_lisp_compare(cons, builtin_less_equal);
504 }
505
506 ao_poly
507 ao_lisp_do_greater_equal(struct ao_lisp_cons *cons)
508 {
509         return ao_lisp_compare(cons, builtin_greater_equal);
510 }
511
512 ao_poly
513 ao_lisp_do_pack(struct ao_lisp_cons *cons)
514 {
515         if (!ao_lisp_check_argc(_ao_lisp_atom_pack, cons, 1, 1))
516                 return AO_LISP_NIL;
517         if (!ao_lisp_check_argt(_ao_lisp_atom_pack, cons, 0, AO_LISP_CONS, 1))
518                 return AO_LISP_NIL;
519         return ao_lisp_string_pack(ao_lisp_poly_cons(ao_lisp_arg(cons, 0)));
520 }
521
522 ao_poly
523 ao_lisp_do_unpack(struct ao_lisp_cons *cons)
524 {
525         if (!ao_lisp_check_argc(_ao_lisp_atom_unpack, cons, 1, 1))
526                 return AO_LISP_NIL;
527         if (!ao_lisp_check_argt(_ao_lisp_atom_unpack, cons, 0, AO_LISP_STRING, 0))
528                 return AO_LISP_NIL;
529         return ao_lisp_string_unpack(ao_lisp_poly_string(ao_lisp_arg(cons, 0)));
530 }
531
532 ao_poly
533 ao_lisp_do_flush(struct ao_lisp_cons *cons)
534 {
535         if (!ao_lisp_check_argc(_ao_lisp_atom_flush, cons, 0, 0))
536                 return AO_LISP_NIL;
537         ao_lisp_os_flush();
538         return _ao_lisp_bool_true;
539 }
540
541 ao_poly
542 ao_lisp_do_led(struct ao_lisp_cons *cons)
543 {
544         ao_poly led;
545         if (!ao_lisp_check_argc(_ao_lisp_atom_led, cons, 1, 1))
546                 return AO_LISP_NIL;
547         if (!ao_lisp_check_argt(_ao_lisp_atom_led, cons, 0, AO_LISP_INT, 0))
548                 return AO_LISP_NIL;
549         led = ao_lisp_arg(cons, 0);
550         ao_lisp_os_led(ao_lisp_poly_int(led));
551         return led;
552 }
553
554 ao_poly
555 ao_lisp_do_delay(struct ao_lisp_cons *cons)
556 {
557         ao_poly delay;
558         if (!ao_lisp_check_argc(_ao_lisp_atom_led, cons, 1, 1))
559                 return AO_LISP_NIL;
560         if (!ao_lisp_check_argt(_ao_lisp_atom_led, cons, 0, AO_LISP_INT, 0))
561                 return AO_LISP_NIL;
562         delay = ao_lisp_arg(cons, 0);
563         ao_lisp_os_delay(ao_lisp_poly_int(delay));
564         return delay;
565 }
566
567 ao_poly
568 ao_lisp_do_eval(struct ao_lisp_cons *cons)
569 {
570         if (!ao_lisp_check_argc(_ao_lisp_atom_eval, cons, 1, 1))
571                 return AO_LISP_NIL;
572         ao_lisp_stack->state = eval_sexpr;
573         return cons->car;
574 }
575
576 ao_poly
577 ao_lisp_do_read(struct ao_lisp_cons *cons)
578 {
579         if (!ao_lisp_check_argc(_ao_lisp_atom_read, cons, 0, 0))
580                 return AO_LISP_NIL;
581         return ao_lisp_read();
582 }
583
584 ao_poly
585 ao_lisp_do_collect(struct ao_lisp_cons *cons)
586 {
587         int     free;
588         (void) cons;
589         free = ao_lisp_collect(AO_LISP_COLLECT_FULL);
590         return ao_lisp_int_poly(free);
591 }
592
593 ao_poly
594 ao_lisp_do_nullp(struct ao_lisp_cons *cons)
595 {
596         if (!ao_lisp_check_argc(_ao_lisp_atom_led, cons, 1, 1))
597                 return AO_LISP_NIL;
598         if (ao_lisp_arg(cons, 0) == AO_LISP_NIL)
599                 return _ao_lisp_bool_true;
600         else
601                 return _ao_lisp_bool_false;
602 }
603
604 ao_poly
605 ao_lisp_do_not(struct ao_lisp_cons *cons)
606 {
607         if (!ao_lisp_check_argc(_ao_lisp_atom_led, cons, 1, 1))
608                 return AO_LISP_NIL;
609         if (ao_lisp_arg(cons, 0) == _ao_lisp_bool_false)
610                 return _ao_lisp_bool_true;
611         else
612                 return _ao_lisp_bool_false;
613 }
614
615 ao_poly
616 ao_lisp_do_listp(struct ao_lisp_cons *cons)
617 {
618         ao_poly v;
619         if (!ao_lisp_check_argc(_ao_lisp_atom_led, cons, 1, 1))
620                 return AO_LISP_NIL;
621         v = ao_lisp_arg(cons, 0);
622         for (;;) {
623                 if (v == AO_LISP_NIL)
624                         return _ao_lisp_bool_true;
625                 if (ao_lisp_poly_type(v) != AO_LISP_CONS)
626                         return _ao_lisp_bool_false;
627                 v = ao_lisp_poly_cons(v)->cdr;
628         }
629 }
630
631 ao_poly
632 ao_lisp_do_pairp(struct ao_lisp_cons *cons)
633 {
634         ao_poly v;
635         if (!ao_lisp_check_argc(_ao_lisp_atom_led, cons, 1, 1))
636                 return AO_LISP_NIL;
637         v = ao_lisp_arg(cons, 0);
638         if (ao_lisp_poly_type(v) == AO_LISP_CONS)
639                 return _ao_lisp_bool_true;
640         return _ao_lisp_bool_false;
641 }
642
643 ao_poly
644 ao_lisp_do_numberp(struct ao_lisp_cons *cons)
645 {
646         if (!ao_lisp_check_argc(_ao_lisp_atom_led, cons, 1, 1))
647                 return AO_LISP_NIL;
648         if (AO_LISP_IS_INT(ao_lisp_arg(cons, 0)))
649                 return _ao_lisp_bool_true;
650         return _ao_lisp_bool_false;
651 }
652
653 ao_poly
654 ao_lisp_do_booleanp(struct ao_lisp_cons *cons)
655 {
656         if (!ao_lisp_check_argc(_ao_lisp_atom_led, cons, 1, 1))
657                 return AO_LISP_NIL;
658         if (ao_lisp_poly_type(ao_lisp_arg(cons, 0)) == AO_LISP_BOOL)
659                 return _ao_lisp_bool_true;
660         return _ao_lisp_bool_false;
661 }
662
663 ao_poly
664 ao_lisp_do_set_car(struct ao_lisp_cons *cons)
665 {
666         if (!ao_lisp_check_argc(_ao_lisp_atom_led, cons, 2, 2))
667                 return AO_LISP_NIL;
668         if (!ao_lisp_check_argt(_ao_lisp_atom_led, cons, 0, AO_LISP_CONS, 0))
669                 return AO_LISP_NIL;
670         return ao_lisp_poly_cons(ao_lisp_arg(cons, 0))->car = ao_lisp_arg(cons, 1);
671 }
672
673 ao_poly
674 ao_lisp_do_set_cdr(struct ao_lisp_cons *cons)
675 {
676         if (!ao_lisp_check_argc(_ao_lisp_atom_led, cons, 2, 2))
677                 return AO_LISP_NIL;
678         if (!ao_lisp_check_argt(_ao_lisp_atom_led, cons, 0, AO_LISP_CONS, 0))
679                 return AO_LISP_NIL;
680         return ao_lisp_poly_cons(ao_lisp_arg(cons, 0))->cdr = ao_lisp_arg(cons, 1);
681 }
682
683 #define AO_LISP_BUILTIN_FUNCS
684 #include "ao_lisp_builtin.h"