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