2 * Copyright © 2016 Keith Packard <keithp@keithp.com>
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.
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.
18 builtin_size(void *addr)
21 return sizeof (struct ao_lisp_builtin);
25 builtin_mark(void *addr)
31 builtin_move(void *addr)
36 const struct ao_lisp_type ao_lisp_builtin_type = {
42 #ifdef AO_LISP_MAKE_CONST
44 #define AO_LISP_BUILTIN_CASENAME
45 #include "ao_lisp_builtin.h"
47 #define _atomn(n) ao_lisp_poly_atom(_atom(n))
49 char *ao_lisp_args_name(uint8_t args) {
50 args &= AO_LISP_FUNC_MASK;
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 "???";
61 #define AO_LISP_BUILTIN_ARRAYNAME
62 #include "ao_lisp_builtin.h"
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;
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,
79 ao_lisp_args_name(uint8_t args)
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;
89 ao_lisp_builtin_print(ao_poly b)
91 struct ao_lisp_builtin *builtin = ao_lisp_poly_builtin(b);
92 printf("%s", ao_lisp_builtin_name(builtin->func));
96 ao_lisp_check_argc(ao_poly name, struct ao_lisp_cons *cons, int min, int max)
100 while (cons && argc <= max) {
102 cons = ao_lisp_poly_cons(cons->cdr);
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;
110 ao_lisp_arg(struct ao_lisp_cons *cons, int argc)
117 cons = ao_lisp_poly_cons(cons->cdr);
123 ao_lisp_check_argt(ao_poly name, struct ao_lisp_cons *cons, int argc, int type, int nil_ok)
125 ao_poly car = ao_lisp_arg(cons, argc);
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;
133 ao_lisp_do_car(struct ao_lisp_cons *cons)
135 if (!ao_lisp_check_argc(_ao_lisp_atom_car, cons, 1, 1))
137 if (!ao_lisp_check_argt(_ao_lisp_atom_car, cons, 0, AO_LISP_CONS, 0))
139 return ao_lisp_poly_cons(cons->car)->car;
143 ao_lisp_do_cdr(struct ao_lisp_cons *cons)
145 if (!ao_lisp_check_argc(_ao_lisp_atom_cdr, cons, 1, 1))
147 if (!ao_lisp_check_argt(_ao_lisp_atom_cdr, cons, 0, AO_LISP_CONS, 0))
149 return ao_lisp_poly_cons(cons->car)->cdr;
153 ao_lisp_do_cons(struct ao_lisp_cons *cons)
156 if(!ao_lisp_check_argc(_ao_lisp_atom_cons, cons, 2, 2))
158 car = ao_lisp_arg(cons, 0);
159 cdr = ao_lisp_arg(cons, 1);
160 return ao_lisp__cons(car, cdr);
164 ao_lisp_do_last(struct ao_lisp_cons *cons)
167 if (!ao_lisp_check_argc(_ao_lisp_atom_last, cons, 1, 1))
169 if (!ao_lisp_check_argt(_ao_lisp_atom_last, cons, 0, AO_LISP_CONS, 1))
171 l = ao_lisp_arg(cons, 0);
173 struct ao_lisp_cons *list = ao_lisp_poly_cons(l);
182 ao_lisp_do_length(struct ao_lisp_cons *cons)
184 if (!ao_lisp_check_argc(_ao_lisp_atom_length, cons, 1, 1))
186 if (!ao_lisp_check_argt(_ao_lisp_atom_length, cons, 0, AO_LISP_CONS, 1))
188 return ao_lisp_int_poly(ao_lisp_cons_length(ao_lisp_poly_cons(ao_lisp_arg(cons, 0))));
192 ao_lisp_do_quote(struct ao_lisp_cons *cons)
194 if (!ao_lisp_check_argc(_ao_lisp_atom_quote, cons, 1, 1))
196 return ao_lisp_arg(cons, 0);
200 ao_lisp_do_set(struct ao_lisp_cons *cons)
202 if (!ao_lisp_check_argc(_ao_lisp_atom_set, cons, 2, 2))
204 if (!ao_lisp_check_argt(_ao_lisp_atom_set, cons, 0, AO_LISP_ATOM, 0))
207 return ao_lisp_atom_set(ao_lisp_arg(cons, 0), ao_lisp_arg(cons, 1));
211 ao_lisp_do_setq(struct ao_lisp_cons *cons)
214 if (!ao_lisp_check_argc(_ao_lisp_atom_setq, cons, 2, 2))
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)),
228 ao_lisp_do_cond(struct ao_lisp_cons *cons)
230 ao_lisp_set_cond(cons);
235 ao_lisp_do_progn(struct ao_lisp_cons *cons)
237 ao_lisp_stack->state = eval_progn;
238 ao_lisp_stack->sexprs = ao_lisp_cons_poly(cons);
243 ao_lisp_do_while(struct ao_lisp_cons *cons)
245 ao_lisp_stack->state = eval_while;
246 ao_lisp_stack->sexprs = ao_lisp_cons_poly(cons);
251 ao_lisp_do_print(struct ao_lisp_cons *cons)
253 ao_poly val = AO_LISP_NIL;
256 ao_lisp_poly_print(val);
257 cons = ao_lisp_poly_cons(cons->cdr);
266 ao_lisp_do_patom(struct ao_lisp_cons *cons)
268 ao_poly val = AO_LISP_NIL;
271 ao_lisp_poly_patom(val);
272 cons = ao_lisp_poly_cons(cons->cdr);
278 ao_lisp_math(struct ao_lisp_cons *cons, enum ao_lisp_builtin_id op)
280 ao_poly ret = AO_LISP_NIL;
283 ao_poly car = cons->car;
284 uint8_t rt = ao_lisp_poly_type(ret);
285 uint8_t ct = ao_lisp_poly_type(car);
287 cons = ao_lisp_poly_cons(cons->cdr);
289 if (rt == AO_LISP_NIL)
292 else if (rt == AO_LISP_INT && ct == AO_LISP_INT) {
293 int r = ao_lisp_poly_int(ret);
294 int c = ao_lisp_poly_int(car);
308 return ao_lisp_error(AO_LISP_DIVIDE_BY_ZERO, "divide by zero");
313 return ao_lisp_error(AO_LISP_DIVIDE_BY_ZERO, "mod by zero");
319 ret = ao_lisp_int_poly(r);
322 else if (rt == AO_LISP_STRING && ct == AO_LISP_STRING && op == builtin_plus)
323 ret = ao_lisp_string_poly(ao_lisp_string_cat(ao_lisp_poly_string(ret),
324 ao_lisp_poly_string(car)));
326 return ao_lisp_error(AO_LISP_INVALID, "invalid args");
332 ao_lisp_do_plus(struct ao_lisp_cons *cons)
334 return ao_lisp_math(cons, builtin_plus);
338 ao_lisp_do_minus(struct ao_lisp_cons *cons)
340 return ao_lisp_math(cons, builtin_minus);
344 ao_lisp_do_times(struct ao_lisp_cons *cons)
346 return ao_lisp_math(cons, builtin_times);
350 ao_lisp_do_divide(struct ao_lisp_cons *cons)
352 return ao_lisp_math(cons, builtin_divide);
356 ao_lisp_do_mod(struct ao_lisp_cons *cons)
358 return ao_lisp_math(cons, builtin_mod);
362 ao_lisp_compare(struct ao_lisp_cons *cons, enum ao_lisp_builtin_id op)
367 return _ao_lisp_bool_true;
370 cons = ao_lisp_poly_cons(cons->cdr);
372 ao_poly right = cons->car;
374 if (op == builtin_equal) {
376 return _ao_lisp_bool_false;
378 uint8_t lt = ao_lisp_poly_type(left);
379 uint8_t rt = ao_lisp_poly_type(right);
380 if (lt == AO_LISP_INT && rt == AO_LISP_INT) {
381 int l = ao_lisp_poly_int(left);
382 int r = ao_lisp_poly_int(right);
387 return _ao_lisp_bool_false;
389 case builtin_greater:
391 return _ao_lisp_bool_false;
393 case builtin_less_equal:
395 return _ao_lisp_bool_false;
397 case builtin_greater_equal:
399 return _ao_lisp_bool_false;
404 } else if (lt == AO_LISP_STRING && rt == AO_LISP_STRING) {
405 int c = strcmp(ao_lisp_poly_string(left),
406 ao_lisp_poly_string(right));
410 return _ao_lisp_bool_false;
412 case builtin_greater:
414 return _ao_lisp_bool_false;
416 case builtin_less_equal:
418 return _ao_lisp_bool_false;
420 case builtin_greater_equal:
422 return _ao_lisp_bool_false;
430 cons = ao_lisp_poly_cons(cons->cdr);
432 return _ao_lisp_bool_true;
436 ao_lisp_do_equal(struct ao_lisp_cons *cons)
438 return ao_lisp_compare(cons, builtin_equal);
442 ao_lisp_do_less(struct ao_lisp_cons *cons)
444 return ao_lisp_compare(cons, builtin_less);
448 ao_lisp_do_greater(struct ao_lisp_cons *cons)
450 return ao_lisp_compare(cons, builtin_greater);
454 ao_lisp_do_less_equal(struct ao_lisp_cons *cons)
456 return ao_lisp_compare(cons, builtin_less_equal);
460 ao_lisp_do_greater_equal(struct ao_lisp_cons *cons)
462 return ao_lisp_compare(cons, builtin_greater_equal);
466 ao_lisp_do_pack(struct ao_lisp_cons *cons)
468 if (!ao_lisp_check_argc(_ao_lisp_atom_pack, cons, 1, 1))
470 if (!ao_lisp_check_argt(_ao_lisp_atom_pack, cons, 0, AO_LISP_CONS, 1))
472 return ao_lisp_string_pack(ao_lisp_poly_cons(ao_lisp_arg(cons, 0)));
476 ao_lisp_do_unpack(struct ao_lisp_cons *cons)
478 if (!ao_lisp_check_argc(_ao_lisp_atom_unpack, cons, 1, 1))
480 if (!ao_lisp_check_argt(_ao_lisp_atom_unpack, cons, 0, AO_LISP_STRING, 0))
482 return ao_lisp_string_unpack(ao_lisp_poly_string(ao_lisp_arg(cons, 0)));
486 ao_lisp_do_flush(struct ao_lisp_cons *cons)
488 if (!ao_lisp_check_argc(_ao_lisp_atom_flush, cons, 0, 0))
491 return _ao_lisp_bool_true;
495 ao_lisp_do_led(struct ao_lisp_cons *cons)
498 if (!ao_lisp_check_argc(_ao_lisp_atom_led, cons, 1, 1))
500 if (!ao_lisp_check_argt(_ao_lisp_atom_led, cons, 0, AO_LISP_INT, 0))
502 led = ao_lisp_arg(cons, 0);
503 ao_lisp_os_led(ao_lisp_poly_int(led));
508 ao_lisp_do_delay(struct ao_lisp_cons *cons)
511 if (!ao_lisp_check_argc(_ao_lisp_atom_led, cons, 1, 1))
513 if (!ao_lisp_check_argt(_ao_lisp_atom_led, cons, 0, AO_LISP_INT, 0))
515 delay = ao_lisp_arg(cons, 0);
516 ao_lisp_os_delay(ao_lisp_poly_int(delay));
521 ao_lisp_do_eval(struct ao_lisp_cons *cons)
523 if (!ao_lisp_check_argc(_ao_lisp_atom_eval, cons, 1, 1))
525 ao_lisp_stack->state = eval_sexpr;
530 ao_lisp_do_read(struct ao_lisp_cons *cons)
532 if (!ao_lisp_check_argc(_ao_lisp_atom_read, cons, 0, 0))
534 return ao_lisp_read();
538 ao_lisp_do_collect(struct ao_lisp_cons *cons)
542 free = ao_lisp_collect(AO_LISP_COLLECT_FULL);
543 return ao_lisp_int_poly(free);
547 ao_lisp_do_nullp(struct ao_lisp_cons *cons)
549 if (!ao_lisp_check_argc(_ao_lisp_atom_led, cons, 1, 1))
551 if (ao_lisp_arg(cons, 0) == AO_LISP_NIL)
552 return _ao_lisp_bool_true;
554 return _ao_lisp_bool_false;
558 ao_lisp_do_not(struct ao_lisp_cons *cons)
560 if (!ao_lisp_check_argc(_ao_lisp_atom_led, cons, 1, 1))
562 if (ao_lisp_arg(cons, 0) == _ao_lisp_bool_false)
563 return _ao_lisp_bool_true;
565 return _ao_lisp_bool_false;
569 ao_lisp_do_listp(struct ao_lisp_cons *cons)
572 if (!ao_lisp_check_argc(_ao_lisp_atom_led, cons, 1, 1))
574 v = ao_lisp_arg(cons, 0);
576 if (v == AO_LISP_NIL)
577 return _ao_lisp_bool_true;
578 if (ao_lisp_poly_type(v) != AO_LISP_CONS)
579 return _ao_lisp_bool_false;
580 v = ao_lisp_poly_cons(v)->cdr;
585 ao_lisp_do_pairp(struct ao_lisp_cons *cons)
588 if (!ao_lisp_check_argc(_ao_lisp_atom_led, cons, 1, 1))
590 v = ao_lisp_arg(cons, 0);
591 if (ao_lisp_poly_type(v) == AO_LISP_CONS)
592 return _ao_lisp_bool_true;
593 return _ao_lisp_bool_false;
596 #define AO_LISP_BUILTIN_FUNCS
597 #include "ao_lisp_builtin.h"