altos/lisp: have 'while' return the last body value
[fw/altos] / src / lisp / ao_lisp_error.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 #include <stdarg.h>
17
18 static void
19 ao_lisp_error_poly(char *name, ao_poly poly)
20 {
21         int first = 1;
22         printf("\t\t%s(", name);
23         if (ao_lisp_poly_type(poly) == AO_LISP_CONS) {
24                 struct ao_lisp_cons *cons = ao_lisp_poly_cons(poly);
25
26                 if (cons) {
27                         while (cons) {
28                                 if (!first)
29                                         printf("\t\t         ");
30                                 else
31                                         first = 0;
32                                 ao_lisp_poly_print(cons->car);
33                                 printf("\n");
34                                 cons = ao_lisp_poly_cons(cons->cdr);
35                         }
36                         printf("\t\t         )\n");
37                 } else
38                         printf(")\n");
39         } else {
40                 ao_lisp_poly_print(poly);
41                 printf("\n");
42         }
43 }
44
45 static void tabs(int indent)
46 {
47         while (indent--)
48                 printf("\t");
49 }
50
51 static void
52 ao_lisp_error_frame(int indent, char *name, struct ao_lisp_frame *frame)
53 {
54         int                     f;
55
56         tabs(indent);
57         printf ("%s{", name);
58         if (frame) {
59                 for (f = 0; f < ao_lisp_frame_num(frame); f++) {
60                         if (f != 0) {
61                                 tabs(indent);
62                                 printf("         ");
63                         }
64                         ao_lisp_poly_print(frame->vals[f].atom);
65                         printf(" = ");
66                         ao_lisp_poly_print(frame->vals[f].val);
67                         printf("\n");
68                 }
69                 if (frame->prev)
70                         ao_lisp_error_frame(indent + 1, "prev:   ", ao_lisp_poly_frame(frame->prev));
71         }
72         tabs(indent);
73         printf("        }\n");
74 }
75
76 static const char *state_names[] = {
77         "sexpr",
78         "val",
79         "formal",
80         "exec",
81         "cond",
82         "cond_test",
83         "progn",
84 };
85
86 void
87 ao_lisp_stack_print(void)
88 {
89         struct ao_lisp_stack *s;
90         printf("Value:  "); ao_lisp_poly_print(ao_lisp_v); printf("\n");
91         printf("Stack:\n");
92         for (s = ao_lisp_stack; s; s = ao_lisp_poly_stack(s->prev)) {
93                 printf("\t[\n");
94                 printf("\t\texpr:   "); ao_lisp_poly_print(s->list); printf("\n");
95                 printf("\t\tstate:  %s\n", state_names[s->state]);
96 //              printf("\t\tmacro:  %s\n", s->macro ? "true" : "false");
97                 ao_lisp_error_poly ("sexprs: ", s->sexprs);
98                 ao_lisp_error_poly ("values: ", s->values);
99                 ao_lisp_error_frame(2, "frame:  ", ao_lisp_poly_frame(s->frame));
100 //              ao_lisp_error_frame(2, "mframe: ", ao_lisp_poly_frame(s->macro_frame));
101                 printf("\t]\n");
102         }
103 }
104
105 ao_poly
106 ao_lisp_error(int error, char *format, ...)
107 {
108         va_list args;
109
110         ao_lisp_exception |= error;
111         va_start(args, format);
112         vprintf(format, args);
113         va_end(args);
114         printf("\n");
115         ao_lisp_stack_print();
116         printf("Globals:\n\t");
117         ao_lisp_frame_print(ao_lisp_frame_poly(ao_lisp_frame_global));
118         printf("\n");
119         return AO_LISP_NIL;
120 }