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)
213 if (!ao_lisp_check_argc(_ao_lisp_atom_setq, cons, 2, 2))
215 return ao_lisp__cons(_ao_lisp_atom_set,
216 ao_lisp__cons(ao_lisp__cons(_ao_lisp_atom_quote,
217 ao_lisp__cons(cons->car, AO_LISP_NIL)),
222 ao_lisp_do_cond(struct ao_lisp_cons *cons)
224 ao_lisp_set_cond(cons);
229 ao_lisp_do_progn(struct ao_lisp_cons *cons)
231 ao_lisp_stack->state = eval_progn;
232 ao_lisp_stack->sexprs = ao_lisp_cons_poly(cons);
237 ao_lisp_do_while(struct ao_lisp_cons *cons)
239 ao_lisp_stack->state = eval_while;
240 ao_lisp_stack->sexprs = ao_lisp_cons_poly(cons);
245 ao_lisp_do_print(struct ao_lisp_cons *cons)
247 ao_poly val = AO_LISP_NIL;
250 ao_lisp_poly_print(val);
251 cons = ao_lisp_poly_cons(cons->cdr);
260 ao_lisp_do_patom(struct ao_lisp_cons *cons)
262 ao_poly val = AO_LISP_NIL;
265 ao_lisp_poly_patom(val);
266 cons = ao_lisp_poly_cons(cons->cdr);
272 ao_lisp_math(struct ao_lisp_cons *cons, enum ao_lisp_builtin_id op)
274 ao_poly ret = AO_LISP_NIL;
277 ao_poly car = cons->car;
278 uint8_t rt = ao_lisp_poly_type(ret);
279 uint8_t ct = ao_lisp_poly_type(car);
281 cons = ao_lisp_poly_cons(cons->cdr);
283 if (rt == AO_LISP_NIL)
286 else if (rt == AO_LISP_INT && ct == AO_LISP_INT) {
287 int r = ao_lisp_poly_int(ret);
288 int c = ao_lisp_poly_int(car);
302 return ao_lisp_error(AO_LISP_DIVIDE_BY_ZERO, "divide by zero");
307 return ao_lisp_error(AO_LISP_DIVIDE_BY_ZERO, "mod by zero");
313 ret = ao_lisp_int_poly(r);
316 else if (rt == AO_LISP_STRING && ct == AO_LISP_STRING && op == builtin_plus)
317 ret = ao_lisp_string_poly(ao_lisp_string_cat(ao_lisp_poly_string(ret),
318 ao_lisp_poly_string(car)));
320 return ao_lisp_error(AO_LISP_INVALID, "invalid args");
326 ao_lisp_do_plus(struct ao_lisp_cons *cons)
328 return ao_lisp_math(cons, builtin_plus);
332 ao_lisp_do_minus(struct ao_lisp_cons *cons)
334 return ao_lisp_math(cons, builtin_minus);
338 ao_lisp_do_times(struct ao_lisp_cons *cons)
340 return ao_lisp_math(cons, builtin_times);
344 ao_lisp_do_divide(struct ao_lisp_cons *cons)
346 return ao_lisp_math(cons, builtin_divide);
350 ao_lisp_do_mod(struct ao_lisp_cons *cons)
352 return ao_lisp_math(cons, builtin_mod);
356 ao_lisp_compare(struct ao_lisp_cons *cons, enum ao_lisp_builtin_id op)
361 return _ao_lisp_bool_true;
364 cons = ao_lisp_poly_cons(cons->cdr);
366 ao_poly right = cons->car;
368 if (op == builtin_equal) {
370 return _ao_lisp_bool_false;
372 uint8_t lt = ao_lisp_poly_type(left);
373 uint8_t rt = ao_lisp_poly_type(right);
374 if (lt == AO_LISP_INT && rt == AO_LISP_INT) {
375 int l = ao_lisp_poly_int(left);
376 int r = ao_lisp_poly_int(right);
381 return _ao_lisp_bool_false;
383 case builtin_greater:
385 return _ao_lisp_bool_false;
387 case builtin_less_equal:
389 return _ao_lisp_bool_false;
391 case builtin_greater_equal:
393 return _ao_lisp_bool_false;
398 } else if (lt == AO_LISP_STRING && rt == AO_LISP_STRING) {
399 int c = strcmp(ao_lisp_poly_string(left),
400 ao_lisp_poly_string(right));
404 return _ao_lisp_bool_false;
406 case builtin_greater:
408 return _ao_lisp_bool_false;
410 case builtin_less_equal:
412 return _ao_lisp_bool_false;
414 case builtin_greater_equal:
416 return _ao_lisp_bool_false;
424 cons = ao_lisp_poly_cons(cons->cdr);
426 return _ao_lisp_bool_true;
430 ao_lisp_do_equal(struct ao_lisp_cons *cons)
432 return ao_lisp_compare(cons, builtin_equal);
436 ao_lisp_do_less(struct ao_lisp_cons *cons)
438 return ao_lisp_compare(cons, builtin_less);
442 ao_lisp_do_greater(struct ao_lisp_cons *cons)
444 return ao_lisp_compare(cons, builtin_greater);
448 ao_lisp_do_less_equal(struct ao_lisp_cons *cons)
450 return ao_lisp_compare(cons, builtin_less_equal);
454 ao_lisp_do_greater_equal(struct ao_lisp_cons *cons)
456 return ao_lisp_compare(cons, builtin_greater_equal);
460 ao_lisp_do_pack(struct ao_lisp_cons *cons)
462 if (!ao_lisp_check_argc(_ao_lisp_atom_pack, cons, 1, 1))
464 if (!ao_lisp_check_argt(_ao_lisp_atom_pack, cons, 0, AO_LISP_CONS, 1))
466 return ao_lisp_string_pack(ao_lisp_poly_cons(ao_lisp_arg(cons, 0)));
470 ao_lisp_do_unpack(struct ao_lisp_cons *cons)
472 if (!ao_lisp_check_argc(_ao_lisp_atom_unpack, cons, 1, 1))
474 if (!ao_lisp_check_argt(_ao_lisp_atom_unpack, cons, 0, AO_LISP_STRING, 0))
476 return ao_lisp_string_unpack(ao_lisp_poly_string(ao_lisp_arg(cons, 0)));
480 ao_lisp_do_flush(struct ao_lisp_cons *cons)
482 if (!ao_lisp_check_argc(_ao_lisp_atom_flush, cons, 0, 0))
485 return _ao_lisp_bool_true;
489 ao_lisp_do_led(struct ao_lisp_cons *cons)
492 if (!ao_lisp_check_argc(_ao_lisp_atom_led, cons, 1, 1))
494 if (!ao_lisp_check_argt(_ao_lisp_atom_led, cons, 0, AO_LISP_INT, 0))
496 led = ao_lisp_arg(cons, 0);
497 ao_lisp_os_led(ao_lisp_poly_int(led));
502 ao_lisp_do_delay(struct ao_lisp_cons *cons)
505 if (!ao_lisp_check_argc(_ao_lisp_atom_led, cons, 1, 1))
507 if (!ao_lisp_check_argt(_ao_lisp_atom_led, cons, 0, AO_LISP_INT, 0))
509 delay = ao_lisp_arg(cons, 0);
510 ao_lisp_os_delay(ao_lisp_poly_int(delay));
515 ao_lisp_do_eval(struct ao_lisp_cons *cons)
517 if (!ao_lisp_check_argc(_ao_lisp_atom_eval, cons, 1, 1))
519 ao_lisp_stack->state = eval_sexpr;
524 ao_lisp_do_read(struct ao_lisp_cons *cons)
526 if (!ao_lisp_check_argc(_ao_lisp_atom_read, cons, 0, 0))
528 return ao_lisp_read();
532 ao_lisp_do_collect(struct ao_lisp_cons *cons)
536 free = ao_lisp_collect(AO_LISP_COLLECT_FULL);
537 return ao_lisp_int_poly(free);
541 ao_lisp_do_nullp(struct ao_lisp_cons *cons)
543 if (!ao_lisp_check_argc(_ao_lisp_atom_led, cons, 1, 1))
545 if (ao_lisp_arg(cons, 0) == AO_LISP_NIL)
546 return _ao_lisp_bool_true;
548 return _ao_lisp_bool_false;
552 ao_lisp_do_not(struct ao_lisp_cons *cons)
554 if (!ao_lisp_check_argc(_ao_lisp_atom_led, cons, 1, 1))
556 if (ao_lisp_arg(cons, 0) == _ao_lisp_bool_false)
557 return _ao_lisp_bool_true;
559 return _ao_lisp_bool_false;
562 #define AO_LISP_BUILTIN_FUNCS
563 #include "ao_lisp_builtin.h"