altos/scheme: Add ports. Split scheme code up.
[fw/altos] / src / scheme / ao_scheme.h
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 #ifndef _AO_SCHEME_H_
16 #define _AO_SCHEME_H_
17
18 #ifndef DBG_MEM
19 #define DBG_MEM         0
20 #endif
21 #ifndef DBG_EVAL
22 #define DBG_EVAL        0
23 #endif
24 #ifndef DBG_READ
25 #define DBG_READ        0
26 #endif
27 #ifndef DBG_FREE_CONS
28 #define DBG_FREE_CONS   0
29 #endif
30 #define NDEBUG          1
31
32 #include <stdint.h>
33 #include <string.h>
34 #include <stdbool.h>
35 #include <ao_scheme_os.h>
36 #define AO_SCHEME_BUILTIN_FEATURES
37 #include "ao_scheme_builtin.h"
38 #undef AO_SCHEME_BUILTIN_FEATURES
39 #ifndef __BYTE_ORDER
40 #include <endian.h>
41 #endif
42
43 typedef uint16_t        ao_poly;
44 typedef int16_t         ao_signed_poly;
45
46 #ifdef AO_SCHEME_MAKE_CONST
47 #define AO_SCHEME_POOL_CONST    32764
48 extern uint8_t ao_scheme_const[AO_SCHEME_POOL_CONST] __attribute__((aligned(4)));
49 #define ao_scheme_pool ao_scheme_const
50 #define AO_SCHEME_POOL AO_SCHEME_POOL_CONST
51
52 #define _atom(n) ao_scheme_atom_poly(ao_scheme_atom_intern((char *) n))
53 #define _bool(v) ao_scheme_bool_poly(ao_scheme_bool_get(v))
54
55 #define _ao_scheme_bool_true    _bool(1)
56 #define _ao_scheme_bool_false   _bool(0)
57
58 #define _ao_scheme_atom_eof     _atom("eof")
59 #define _ao_scheme_atom_else    _atom("else")
60
61 #define AO_SCHEME_BUILTIN_ATOMS
62 #include "ao_scheme_builtin.h"
63
64 #else
65
66 #include "ao_scheme_const.h"
67
68 #ifdef AO_SCHEME_FEATURE_SAVE
69
70 struct ao_scheme_os_save {
71         ao_poly         atoms;
72         ao_poly         globals;
73         uint16_t        const_checksum;
74         uint16_t        const_checksum_inv;
75 };
76
77 #ifndef AO_SCHEME_POOL_TOTAL
78 #error Must define AO_SCHEME_POOL_TOTAL for AO_SCHEME_FEATURE_SAVE
79 #endif
80
81 #define AO_SCHEME_POOL_EXTRA    (sizeof(struct ao_scheme_os_save))
82 #define AO_SCHEME_POOL  ((int) (AO_SCHEME_POOL_TOTAL - AO_SCHEME_POOL_EXTRA))
83
84 int
85 ao_scheme_os_save(void);
86
87 int
88 ao_scheme_os_restore_save(struct ao_scheme_os_save *save, int offset);
89
90 int
91 ao_scheme_os_restore(void);
92 #endif /* AO_SCHEME_FEATURE_SAVE */
93
94 #ifndef AO_SCHEME_POOL
95 #error Must define AO_SCHEME_POOL
96 #endif
97 #ifndef AO_SCHEME_POOL_EXTRA
98 #define AO_SCHEME_POOL_EXTRA 0
99 #endif
100 extern uint8_t          ao_scheme_pool[AO_SCHEME_POOL + AO_SCHEME_POOL_EXTRA] __attribute__((aligned(4)));
101 #endif
102
103 /* Primitive types */
104 #define AO_SCHEME_CONS          0
105 #define AO_SCHEME_INT           1
106 #define AO_SCHEME_BIGINT        2
107 #define AO_SCHEME_OTHER         3
108
109 #define AO_SCHEME_TYPE_MASK     0x0003
110 #define AO_SCHEME_TYPE_SHIFT    2
111 #define AO_SCHEME_REF_MASK      0x7ffc
112 #define AO_SCHEME_CONST         0x8000
113
114 /* These have a type value at the start of the struct */
115 #define AO_SCHEME_ATOM          4
116 #define AO_SCHEME_BUILTIN       5
117 #define AO_SCHEME_FRAME         6
118 #define AO_SCHEME_FRAME_VALS    7
119 #define AO_SCHEME_LAMBDA        8
120 #define AO_SCHEME_STACK         9
121 #define AO_SCHEME_BOOL          10
122 #define AO_SCHEME_STRING        11
123 #ifdef AO_SCHEME_FEATURE_FLOAT
124 #define AO_SCHEME_FLOAT         12
125 #define _AO_SCHEME_FLOAT        AO_SCHEME_FLOAT
126 #else
127 #define _AO_SCHEME_FLOAT        12
128 #endif
129 #ifdef AO_SCHEME_FEATURE_VECTOR
130 #define AO_SCHEME_VECTOR        13
131 #define _AO_SCHEME_VECTOR       AO_SCHEME_VECTOR
132 #else
133 #define _AO_SCHEME_VECTOR       _AO_SCHEME_FLOAT
134 #endif
135 #ifdef AO_SCHEME_FEATURE_PORT
136 #define AO_SCHEME_PORT          14
137 #define _AO_SCHEME_PORT         AO_SCHEME_PORT
138 #else
139 #define _AO_SCHEME_PORT         _AO_SCHEME_VECTOR
140 #endif
141 #define AO_SCHEME_NUM_TYPE      (_AO_SCHEME_PORT+1)
142
143 /* Leave two bits for types to use as they please */
144 #define AO_SCHEME_OTHER_TYPE_MASK       0x3f
145
146 #define AO_SCHEME_NIL   0
147
148 extern uint16_t         ao_scheme_top;
149
150 #define AO_SCHEME_OOM                   0x01
151 #define AO_SCHEME_DIVIDE_BY_ZERO        0x02
152 #define AO_SCHEME_INVALID               0x04
153 #define AO_SCHEME_UNDEFINED             0x08
154 #define AO_SCHEME_REDEFINED             0x10
155 #define AO_SCHEME_EOF                   0x20
156 #define AO_SCHEME_FILEERROR             0x40
157 #define AO_SCHEME_EXIT                  0x80
158
159 extern uint8_t          ao_scheme_exception;
160
161 static inline int
162 ao_scheme_is_const(ao_poly poly) {
163         return poly & AO_SCHEME_CONST;
164 }
165
166 static inline int
167 ao_scheme_is_const_addr(const void *addr) {
168         const uint8_t *a = addr;
169         return (ao_scheme_const <= a) && (a < ao_scheme_const + AO_SCHEME_POOL_CONST);
170 }
171
172 static inline int
173 ao_scheme_is_pool_addr(const void *addr) {
174         const uint8_t *a = addr;
175         return (ao_scheme_pool <= a) && (a < ao_scheme_pool + AO_SCHEME_POOL);
176 }
177
178 void *
179 ao_scheme_ref(ao_poly poly);
180
181 ao_poly
182 ao_scheme_poly(const void *addr, ao_poly type);
183
184 struct ao_scheme_type {
185         int     (*size)(void *addr);
186         void    (*mark)(void *addr);
187         void    (*move)(void *addr);
188         char    name[];
189 };
190
191 struct ao_scheme_cons {
192         ao_poly         car;
193         ao_poly         cdr;
194 };
195
196 struct ao_scheme_atom {
197         uint8_t         type;
198         uint8_t         pad[1];
199         ao_poly         next;
200         char            name[];
201 };
202
203 struct ao_scheme_string {
204         uint8_t         type;
205         char            val[];
206 };
207
208 struct ao_scheme_val {
209         ao_poly         atom;
210         ao_poly         val;
211 };
212
213 struct ao_scheme_frame_vals {
214         uint8_t                 type;
215         uint8_t                 size;
216         struct ao_scheme_val    vals[];
217 };
218
219 struct ao_scheme_frame {
220         uint8_t                 type;
221         uint8_t                 num;
222         ao_poly                 prev;
223         ao_poly                 vals;
224 };
225
226 struct ao_scheme_bool {
227         uint8_t                 type;
228         uint8_t                 value;
229         uint16_t                pad;
230 };
231
232
233 #ifdef AO_SCHEME_FEATURE_FLOAT
234 struct ao_scheme_float {
235         uint8_t                 type;
236         uint8_t                 pad1;
237         uint16_t                pad2;
238         float                   value;
239 };
240 #endif
241
242 #ifdef AO_SCHEME_FEATURE_VECTOR
243 struct ao_scheme_vector {
244         uint8_t                 type;
245         uint8_t                 pad1;
246         uint16_t                length;
247         ao_poly                 vals[];
248 };
249 #endif
250
251 #ifdef AO_SCHEME_FEATURE_PORT
252 struct ao_scheme_port {
253         uint8_t                 type;
254         uint8_t                 stayopen;
255         ao_poly                 next;
256         FILE                    *file;
257 };
258 #endif
259
260 #define AO_SCHEME_MIN_INT       (-(1 << (15 - AO_SCHEME_TYPE_SHIFT)))
261 #define AO_SCHEME_MAX_INT       ((1 << (15 - AO_SCHEME_TYPE_SHIFT)) - 1)
262
263 #ifdef AO_SCHEME_FEATURE_BIGINT
264
265 struct ao_scheme_bigint {
266         uint32_t                value;
267 };
268
269 #define AO_SCHEME_MIN_BIGINT    INT32_MIN
270 #define AO_SCHEME_MAX_BIGINT    INT32_MAX
271
272 #endif  /* AO_SCHEME_FEATURE_BIGINT */
273
274 /* Set on type when the frame escapes the lambda */
275 #define AO_SCHEME_FRAME_MARK    0x80
276
277 static inline int ao_scheme_frame_marked(struct ao_scheme_frame *f) {
278         return f->type & AO_SCHEME_FRAME_MARK;
279 }
280
281 static inline struct ao_scheme_frame *
282 ao_scheme_poly_frame(ao_poly poly) {
283         return ao_scheme_ref(poly);
284 }
285
286 static inline ao_poly
287 ao_scheme_frame_poly(struct ao_scheme_frame *frame) {
288         return ao_scheme_poly(frame, AO_SCHEME_OTHER);
289 }
290
291 static inline struct ao_scheme_frame_vals *
292 ao_scheme_poly_frame_vals(ao_poly poly) {
293         return ao_scheme_ref(poly);
294 }
295
296 static inline ao_poly
297 ao_scheme_frame_vals_poly(struct ao_scheme_frame_vals *vals) {
298         return ao_scheme_poly(vals, AO_SCHEME_OTHER);
299 }
300
301 enum eval_state {
302         eval_sexpr,             /* Evaluate an sexpr */
303         eval_val,               /* Value computed */
304         eval_formal,            /* Formal computed */
305         eval_exec,              /* Start a lambda evaluation */
306         eval_apply,             /* Execute apply */
307         eval_cond,              /* Start next cond clause */
308         eval_cond_test,         /* Check cond condition */
309         eval_begin,             /* Start next begin entry */
310         eval_while,             /* Start while condition */
311         eval_while_test,        /* Check while condition */
312         eval_macro,             /* Finished with macro generation */
313 };
314
315 struct ao_scheme_stack {
316         uint8_t                 type;           /* AO_SCHEME_STACK */
317         uint8_t                 state;          /* enum eval_state */
318         ao_poly                 prev;           /* previous stack frame */
319         ao_poly                 sexprs;         /* expressions to evaluate */
320         ao_poly                 values;         /* values computed */
321         ao_poly                 values_tail;    /* end of the values list for easy appending */
322         ao_poly                 frame;          /* current lookup frame */
323         ao_poly                 list;           /* most recent function call */
324 };
325
326 #define AO_SCHEME_STACK_MARK    0x80    /* set on type when a reference has been taken */
327
328 static inline int ao_scheme_stack_marked(struct ao_scheme_stack *s) {
329         return s->type & AO_SCHEME_STACK_MARK;
330 }
331
332 static inline void ao_scheme_stack_mark(struct ao_scheme_stack *s) {
333         s->type |= AO_SCHEME_STACK_MARK;
334 }
335
336 static inline struct ao_scheme_stack *
337 ao_scheme_poly_stack(ao_poly p)
338 {
339         return ao_scheme_ref(p);
340 }
341
342 static inline ao_poly
343 ao_scheme_stack_poly(struct ao_scheme_stack *stack)
344 {
345         return ao_scheme_poly(stack, AO_SCHEME_OTHER);
346 }
347
348 extern ao_poly                  ao_scheme_v;
349
350 #define AO_SCHEME_FUNC_LAMBDA           0
351 #define AO_SCHEME_FUNC_NLAMBDA          1
352 #define AO_SCHEME_FUNC_MACRO            2
353
354 #define AO_SCHEME_FUNC_FREE_ARGS        0x80
355 #define AO_SCHEME_FUNC_MASK             0x7f
356
357 #define AO_SCHEME_FUNC_F_LAMBDA         (AO_SCHEME_FUNC_FREE_ARGS | AO_SCHEME_FUNC_LAMBDA)
358 #define AO_SCHEME_FUNC_F_NLAMBDA        (AO_SCHEME_FUNC_FREE_ARGS | AO_SCHEME_FUNC_NLAMBDA)
359 #define AO_SCHEME_FUNC_F_MACRO          (AO_SCHEME_FUNC_FREE_ARGS | AO_SCHEME_FUNC_MACRO)
360
361 struct ao_scheme_builtin {
362         uint8_t         type;
363         uint8_t         args;
364         uint16_t        func;
365 };
366
367 #define AO_SCHEME_BUILTIN_ID
368 #include "ao_scheme_builtin.h"
369
370 typedef ao_poly (*ao_scheme_func_t)(struct ao_scheme_cons *cons);
371
372 extern const ao_scheme_func_t   ao_scheme_builtins[];
373
374 static inline ao_scheme_func_t
375 ao_scheme_func(struct ao_scheme_builtin *b)
376 {
377         return ao_scheme_builtins[b->func];
378 }
379
380 struct ao_scheme_lambda {
381         uint8_t         type;
382         uint8_t         args;
383         ao_poly         code;
384         ao_poly         frame;
385 };
386
387 static inline struct ao_scheme_lambda *
388 ao_scheme_poly_lambda(ao_poly poly)
389 {
390         return ao_scheme_ref(poly);
391 }
392
393 static inline ao_poly
394 ao_scheme_lambda_poly(struct ao_scheme_lambda *lambda)
395 {
396         return ao_scheme_poly(lambda, AO_SCHEME_OTHER);
397 }
398
399 static inline void *
400 ao_scheme_poly_other(ao_poly poly) {
401         return ao_scheme_ref(poly);
402 }
403
404 static inline uint8_t
405 ao_scheme_other_type(void *other) {
406 #if DBG_MEM
407         if ((*((uint8_t *) other) & AO_SCHEME_OTHER_TYPE_MASK) >= AO_SCHEME_NUM_TYPE)
408                 ao_scheme_abort();
409 #endif
410         return *((uint8_t *) other) & AO_SCHEME_OTHER_TYPE_MASK;
411 }
412
413 static inline ao_poly
414 ao_scheme_other_poly(const void *other)
415 {
416         return ao_scheme_poly(other, AO_SCHEME_OTHER);
417 }
418
419 static inline int
420 ao_scheme_size_round(int size)
421 {
422         return (size + 3) & ~3;
423 }
424
425 static inline int
426 ao_scheme_size(const struct ao_scheme_type *type, void *addr)
427 {
428         return ao_scheme_size_round(type->size(addr));
429 }
430
431 #define AO_SCHEME_OTHER_POLY(other) ((ao_poly)(other) + AO_SCHEME_OTHER)
432
433 static inline int ao_scheme_poly_base_type(ao_poly poly) {
434         return poly & AO_SCHEME_TYPE_MASK;
435 }
436
437 static inline int ao_scheme_poly_type(ao_poly poly) {
438         int     type = poly & AO_SCHEME_TYPE_MASK;
439         if (type == AO_SCHEME_OTHER)
440                 return ao_scheme_other_type(ao_scheme_poly_other(poly));
441         return type;
442 }
443
444 static inline int
445 ao_scheme_is_cons(ao_poly poly) {
446         return (ao_scheme_poly_base_type(poly) == AO_SCHEME_CONS);
447 }
448
449 static inline int
450 ao_scheme_is_pair(ao_poly poly) {
451         return poly != AO_SCHEME_NIL && (ao_scheme_poly_base_type(poly) == AO_SCHEME_CONS);
452 }
453
454 static inline struct ao_scheme_cons *
455 ao_scheme_poly_cons(ao_poly poly)
456 {
457         return ao_scheme_ref(poly);
458 }
459
460 static inline ao_poly
461 ao_scheme_cons_poly(struct ao_scheme_cons *cons)
462 {
463         return ao_scheme_poly(cons, AO_SCHEME_CONS);
464 }
465
466 static inline int32_t
467 ao_scheme_poly_int(ao_poly poly)
468 {
469         return (int32_t) ((ao_signed_poly) poly >> AO_SCHEME_TYPE_SHIFT);
470 }
471
472 static inline ao_poly
473 ao_scheme_int_poly(int32_t i)
474 {
475         return ((ao_poly) i << 2) | AO_SCHEME_INT;
476 }
477
478 #ifdef AO_SCHEME_FEATURE_BIGINT
479 static inline struct ao_scheme_bigint *
480 ao_scheme_poly_bigint(ao_poly poly)
481 {
482         return ao_scheme_ref(poly);
483 }
484
485 static inline ao_poly
486 ao_scheme_bigint_poly(struct ao_scheme_bigint *bi)
487 {
488         return ao_scheme_poly(bi, AO_SCHEME_BIGINT);
489 }
490 #endif /* AO_SCHEME_FEATURE_BIGINT */
491
492 static inline struct ao_scheme_string *
493 ao_scheme_poly_string(ao_poly poly)
494 {
495         return ao_scheme_ref(poly);
496 }
497
498 static inline ao_poly
499 ao_scheme_string_poly(struct ao_scheme_string *s)
500 {
501         return ao_scheme_poly(s, AO_SCHEME_OTHER);
502 }
503
504 static inline struct ao_scheme_atom *
505 ao_scheme_poly_atom(ao_poly poly)
506 {
507         return ao_scheme_ref(poly);
508 }
509
510 static inline ao_poly
511 ao_scheme_atom_poly(struct ao_scheme_atom *a)
512 {
513         return ao_scheme_poly(a, AO_SCHEME_OTHER);
514 }
515
516 static inline struct ao_scheme_builtin *
517 ao_scheme_poly_builtin(ao_poly poly)
518 {
519         return ao_scheme_ref(poly);
520 }
521
522 static inline ao_poly
523 ao_scheme_builtin_poly(struct ao_scheme_builtin *b)
524 {
525         return ao_scheme_poly(b, AO_SCHEME_OTHER);
526 }
527
528 static inline ao_poly
529 ao_scheme_bool_poly(struct ao_scheme_bool *b)
530 {
531         return ao_scheme_poly(b, AO_SCHEME_OTHER);
532 }
533
534 static inline struct ao_scheme_bool *
535 ao_scheme_poly_bool(ao_poly poly)
536 {
537         return ao_scheme_ref(poly);
538 }
539
540 #ifdef AO_SCHEME_FEATURE_FLOAT
541 static inline ao_poly
542 ao_scheme_float_poly(struct ao_scheme_float *f)
543 {
544         return ao_scheme_poly(f, AO_SCHEME_OTHER);
545 }
546
547 static inline struct ao_scheme_float *
548 ao_scheme_poly_float(ao_poly poly)
549 {
550         return ao_scheme_ref(poly);
551 }
552
553 float
554 ao_scheme_poly_number(ao_poly p);
555 #endif
556
557 #ifdef AO_SCHEME_FEATURE_VECTOR
558 static inline ao_poly
559 ao_scheme_vector_poly(struct ao_scheme_vector *v)
560 {
561         return ao_scheme_poly(v, AO_SCHEME_OTHER);
562 }
563
564 static inline struct ao_scheme_vector *
565 ao_scheme_poly_vector(ao_poly poly)
566 {
567         return ao_scheme_ref(poly);
568 }
569 #endif
570
571 #ifdef AO_SCHEME_FEATURE_PORT
572 static inline ao_poly
573 ao_scheme_port_poly(struct ao_scheme_port *v)
574 {
575         return ao_scheme_poly(v, AO_SCHEME_OTHER);
576 }
577
578 static inline struct ao_scheme_port *
579 ao_scheme_poly_port(ao_poly poly)
580 {
581         return ao_scheme_ref(poly);
582 }
583
584 extern ao_poly  ao_scheme_stdin, ao_scheme_stdout, ao_scheme_stderr;
585
586 #endif
587
588 /* memory functions */
589
590 extern uint64_t ao_scheme_collects[2];
591 extern uint64_t ao_scheme_freed[2];
592 extern uint64_t ao_scheme_loops[2];
593
594 /* returns 1 if the object was already marked */
595 int
596 ao_scheme_mark_memory(const struct ao_scheme_type *type, void *addr);
597
598 /* returns 1 if the object is marked */
599 int
600 ao_scheme_marked(void *addr);
601
602 /* returns 1 if the object was already moved */
603 int
604 ao_scheme_move_memory(const struct ao_scheme_type *type, void **ref);
605
606 void *
607 ao_scheme_alloc(int size);
608
609 /* Marks an object as being printed, returns 1 if it was already marked */
610 int
611 ao_scheme_print_mark_addr(void *addr);
612
613 void
614 ao_scheme_print_clear_addr(void *addr);
615
616 /* Notes that printing has started */
617 void
618 ao_scheme_print_start(void);
619
620 /* Notes that printing has ended, returns 1 if printing is still happening */
621 int
622 ao_scheme_print_stop(void);
623
624 #define AO_SCHEME_COLLECT_FULL          1
625 #define AO_SCHEME_COLLECT_INCREMENTAL   0
626
627 int
628 ao_scheme_collect(uint8_t style);
629
630 #if DBG_FREE_CONS
631 void
632 ao_scheme_cons_check(struct ao_scheme_cons *cons);
633 #endif
634
635 void
636 ao_scheme_poly_stash(ao_poly poly);
637
638 ao_poly
639 ao_scheme_poly_fetch(void);
640
641 static inline void
642 ao_scheme_cons_stash(struct ao_scheme_cons *cons) {
643         ao_scheme_poly_stash(ao_scheme_cons_poly(cons));
644 }
645
646 static inline struct ao_scheme_cons *
647 ao_scheme_cons_fetch(void) {
648         return ao_scheme_poly_cons(ao_scheme_poly_fetch());
649 }
650
651 static inline void
652 ao_scheme_atom_stash(struct ao_scheme_atom *atom) {
653         ao_scheme_poly_stash(ao_scheme_atom_poly(atom));
654 }
655
656 static inline struct ao_scheme_atom *
657 ao_scheme_atom_fetch(void) {
658         return ao_scheme_poly_atom(ao_scheme_poly_fetch());
659 }
660
661 static inline void
662 ao_scheme_string_stash(struct ao_scheme_string *string) {
663         ao_scheme_poly_stash(ao_scheme_string_poly(string));
664 }
665
666 static inline struct ao_scheme_string *
667 ao_scheme_string_fetch(void) {
668         return ao_scheme_poly_string(ao_scheme_poly_fetch());
669 }
670
671 #ifdef AO_SCHEME_FEATURE_VECTOR
672 static inline void
673 ao_scheme_vector_stash(struct ao_scheme_vector *vector) {
674         ao_scheme_poly_stash(ao_scheme_vector_poly(vector));
675 }
676
677 static inline struct ao_scheme_vector *
678 ao_scheme_vector_fetch(void) {
679         return ao_scheme_poly_vector(ao_scheme_poly_fetch());
680 }
681 #endif
682
683 #ifdef AO_SCHEME_FEATURE_PORT
684 static inline void
685 ao_scheme_port_stash(struct ao_scheme_port *port) {
686         ao_scheme_poly_stash(ao_scheme_port_poly(port));
687 }
688
689 static inline struct ao_scheme_port *
690 ao_scheme_port_fetch(void) {
691         return ao_scheme_poly_port(ao_scheme_poly_fetch());
692 }
693 #endif
694
695 static inline void
696 ao_scheme_stack_stash(struct ao_scheme_stack *stack) {
697         ao_scheme_poly_stash(ao_scheme_stack_poly(stack));
698 }
699
700 static inline struct ao_scheme_stack *
701 ao_scheme_stack_fetch(void) {
702         return ao_scheme_poly_stack(ao_scheme_poly_fetch());
703 }
704
705 static inline void
706 ao_scheme_frame_stash(struct ao_scheme_frame *frame) {
707         ao_scheme_poly_stash(ao_scheme_frame_poly(frame));
708 }
709
710 static inline struct ao_scheme_frame *
711 ao_scheme_frame_fetch(void) {
712         return ao_scheme_poly_frame(ao_scheme_poly_fetch());
713 }
714
715 /* bool */
716
717 extern const struct ao_scheme_type ao_scheme_bool_type;
718
719 void
720 ao_scheme_bool_write(FILE *out, ao_poly v, bool write);
721
722 #ifdef AO_SCHEME_MAKE_CONST
723 extern struct ao_scheme_bool    *ao_scheme_true, *ao_scheme_false;
724
725 struct ao_scheme_bool *
726 ao_scheme_bool_get(uint8_t value);
727 #endif
728
729 /* cons */
730 extern const struct ao_scheme_type ao_scheme_cons_type;
731
732 struct ao_scheme_cons *
733 ao_scheme_cons_cons(ao_poly car, ao_poly cdr);
734
735 /* Return a cons or NULL for a proper list, else error */
736 struct ao_scheme_cons *
737 ao_scheme_cons_cdr(struct ao_scheme_cons *cons);
738
739 ao_poly
740 ao_scheme_cons(ao_poly car, ao_poly cdr);
741
742 extern struct ao_scheme_cons *ao_scheme_cons_free_list;
743
744 void
745 ao_scheme_cons_free(struct ao_scheme_cons *cons);
746
747 void
748 ao_scheme_cons_write(FILE *out, ao_poly, bool write);
749
750 int
751 ao_scheme_cons_length(struct ao_scheme_cons *cons);
752
753 /* string */
754 extern const struct ao_scheme_type ao_scheme_string_type;
755
756 struct ao_scheme_string *
757 ao_scheme_string_new(char *a);
758
759 struct ao_scheme_string *
760 ao_scheme_atom_to_string(struct ao_scheme_atom *a);
761
762 struct ao_scheme_string *
763 ao_scheme_string_cat(struct ao_scheme_string *a, struct ao_scheme_string *b);
764
765 void
766 ao_scheme_string_write(FILE *out, ao_poly s, bool write);
767
768 /* atom */
769 extern const struct ao_scheme_type ao_scheme_atom_type;
770
771 extern struct ao_scheme_atom    *ao_scheme_atoms;
772 extern struct ao_scheme_frame   *ao_scheme_frame_global;
773 extern struct ao_scheme_frame   *ao_scheme_frame_current;
774
775 void
776 ao_scheme_atom_write(FILE *out, ao_poly a, bool write);
777
778 struct ao_scheme_atom *
779 ao_scheme_string_to_atom(struct ao_scheme_string *string);
780
781 struct ao_scheme_atom *
782 ao_scheme_atom_intern(char *name);
783
784 void
785 ao_scheme_atom_check_references(void);
786
787 void
788 ao_scheme_atom_move(void);
789
790 ao_poly *
791 ao_scheme_atom_ref(ao_poly atom, struct ao_scheme_frame **frame_ref);
792
793 ao_poly
794 ao_scheme_atom_get(ao_poly atom);
795
796 ao_poly
797 ao_scheme_atom_def(ao_poly atom, ao_poly val);
798
799 /* int */
800 void
801 ao_scheme_int_write(FILE *out, ao_poly i, bool write);
802
803 #ifdef AO_SCHEME_FEATURE_BIGINT
804 int32_t
805 ao_scheme_poly_integer(ao_poly p);
806
807 ao_poly
808 ao_scheme_integer_poly(int32_t i);
809
810 static inline int
811 ao_scheme_integer_typep(uint8_t t)
812 {
813         return (t == AO_SCHEME_INT) || (t == AO_SCHEME_BIGINT);
814 }
815
816 void
817 ao_scheme_bigint_write(FILE *out, ao_poly i, bool write);
818
819 extern const struct ao_scheme_type      ao_scheme_bigint_type;
820
821 #else
822
823 static inline int32_t ao_scheme_poly_integer(ao_poly poly) {
824         return ao_scheme_poly_int(poly);
825 }
826
827 static inline ao_poly ao_scheme_integer_poly(int32_t i) {
828         return ao_scheme_int_poly(i);
829 }
830
831 static inline int
832 ao_scheme_integer_typep(uint8_t t)
833 {
834         return (t == AO_SCHEME_INT);
835 }
836
837 #endif /* AO_SCHEME_FEATURE_BIGINT */
838
839 /* vector */
840
841 #ifdef AO_SCHEME_FEATURE_VECTOR
842
843 void
844 ao_scheme_vector_write(FILE *OUT, ao_poly v, bool write);
845
846 struct ao_scheme_vector *
847 ao_scheme_vector_alloc(uint16_t length, ao_poly fill);
848
849 struct ao_scheme_vector *
850 ao_scheme_list_to_vector(struct ao_scheme_cons *cons);
851
852 struct ao_scheme_cons *
853 ao_scheme_vector_to_list(struct ao_scheme_vector *vector, int start, int end);
854
855 extern const struct ao_scheme_type      ao_scheme_vector_type;
856
857 #endif /* AO_SCHEME_FEATURE_VECTOR */
858
859 /* port */
860
861 #ifdef AO_SCHEME_FEATURE_PORT
862
863 void
864 ao_scheme_port_write(FILE *out, ao_poly v, bool write);
865
866 struct ao_scheme_port *
867 ao_scheme_port_alloc(FILE *file, bool stayopen);
868
869 void
870 ao_scheme_port_close(struct ao_scheme_port *port);
871
872 void
873 ao_scheme_port_check_references(void);
874
875 extern ao_poly ao_scheme_open_ports;
876
877 static inline int
878 ao_scheme_port_getc(struct ao_scheme_port *port)
879 {
880         if (port->file)
881                 return getc(port->file);
882         return EOF;
883 }
884
885 static inline int
886 ao_scheme_port_putc(struct ao_scheme_port *port, char c)
887 {
888         if (port->file)
889                 return putc(c, port->file);
890         return EOF;
891 }
892
893 static inline int
894 ao_scheme_port_ungetc(struct ao_scheme_port *port, char c)
895 {
896         if (port->file)
897                 return ungetc(c, port->file);
898         return EOF;
899 }
900
901 extern const struct ao_scheme_type      ao_scheme_port_type;
902
903 #endif /* AO_SCHEME_FEATURE_PORT */
904
905 #ifdef AO_SCHEME_FEATURE_POSIX
906
907 void
908 ao_scheme_set_argv(char **argv);
909
910 #endif
911
912 /* prim */
913 void (*ao_scheme_poly_write_func(ao_poly p))(FILE *out, ao_poly p, bool write);
914
915 static inline void
916 ao_scheme_poly_write(FILE *out, ao_poly p, bool write) { (*ao_scheme_poly_write_func(p))(out, p, write); }
917
918 int
919 ao_scheme_poly_mark(ao_poly p, uint8_t note_cons);
920
921 /* returns 1 if the object has already been moved */
922 int
923 ao_scheme_poly_move(ao_poly *p, uint8_t note_cons);
924
925 /* eval */
926
927 #ifdef AO_SCHEME_FEATURE_SAVE
928 void
929 ao_scheme_eval_clear_globals(void);
930
931 int
932 ao_scheme_eval_restart(void);
933 #endif
934
935 ao_poly
936 ao_scheme_eval(ao_poly p);
937
938 ao_poly
939 ao_scheme_set_cond(struct ao_scheme_cons *cons);
940
941 /* float */
942 #ifdef AO_SCHEME_FEATURE_FLOAT
943 extern const struct ao_scheme_type ao_scheme_float_type;
944
945 void
946 ao_scheme_float_write(FILE *out, ao_poly p, bool write);
947
948 ao_poly
949 ao_scheme_float_get(float value);
950 #endif
951
952 #ifdef AO_SCHEME_FEATURE_FLOAT
953 static inline bool
954 ao_scheme_number_typep(uint8_t t)
955 {
956         return ao_scheme_integer_typep(t) || (t == AO_SCHEME_FLOAT);
957 }
958 #else
959 #define ao_scheme_number_typep ao_scheme_integer_typep
960 #endif
961
962 static inline bool
963 ao_scheme_is_integer(ao_poly poly) {
964         return ao_scheme_integer_typep(ao_scheme_poly_base_type(poly));
965 }
966
967 static inline bool
968 ao_scheme_is_number(ao_poly poly) {
969         return ao_scheme_number_typep(ao_scheme_poly_type(poly));
970 }
971
972 /* builtin */
973 void
974 ao_scheme_builtin_write(FILE *out, ao_poly b, bool write);
975
976 ao_poly
977 ao_scheme_do_typep(ao_poly proc, int type, struct ao_scheme_cons *cons);
978
979 extern const struct ao_scheme_type ao_scheme_builtin_type;
980
981 #define AO_SCHEME_ARG_OPTIONAL  0x100
982 #define AO_SCHEME_ARG_NIL_OK    0x200
983 #define AO_SCHEME_ARG_RET_POLY  0x400
984 #define AO_SCHEME_ARG_END       -1
985 #define AO_SCHEME_POLY          0xff
986 #define AO_SCHEME_ARG_MASK      0xff
987
988 int
989 ao_scheme_parse_args(ao_poly name, struct ao_scheme_cons *cons, ...);
990
991 /* Check argument count */
992 ao_poly
993 ao_scheme_check_argc(ao_poly name, struct ao_scheme_cons *cons, int min, int max);
994
995 /* Check argument type */
996 ao_poly
997 ao_scheme_check_argt(ao_poly name, struct ao_scheme_cons *cons, int argc, int type, int nil_ok);
998
999 /* Fetch an arg (nil if off the end) */
1000 ao_poly
1001 ao_scheme_arg(struct ao_scheme_cons *cons, int argc);
1002
1003 char *
1004 ao_scheme_args_name(uint8_t args);
1005
1006 /* read */
1007 extern int                      ao_scheme_read_list;
1008 extern struct ao_scheme_cons    *ao_scheme_read_cons;
1009 extern struct ao_scheme_cons    *ao_scheme_read_cons_tail;
1010 extern struct ao_scheme_cons    *ao_scheme_read_stack;
1011
1012 ao_poly
1013 ao_scheme_read(FILE *in);
1014
1015 /* rep */
1016 ao_poly
1017 ao_scheme_read_eval_print(FILE *read_file, FILE *write_file, bool interactive);
1018
1019 /* frame */
1020 extern const struct ao_scheme_type ao_scheme_frame_type;
1021 extern const struct ao_scheme_type ao_scheme_frame_vals_type;
1022
1023 #define AO_SCHEME_FRAME_FREE    6
1024
1025 extern struct ao_scheme_frame   *ao_scheme_frame_free_list[AO_SCHEME_FRAME_FREE];
1026
1027 ao_poly
1028 ao_scheme_frame_mark(struct ao_scheme_frame *frame);
1029
1030 ao_poly *
1031 ao_scheme_frame_ref(struct ao_scheme_frame *frame, ao_poly atom);
1032
1033 struct ao_scheme_frame *
1034 ao_scheme_frame_new(int num);
1035
1036 void
1037 ao_scheme_frame_free(struct ao_scheme_frame *frame);
1038
1039 void
1040 ao_scheme_frame_bind(struct ao_scheme_frame *frame, int num, ao_poly atom, ao_poly val);
1041
1042 ao_poly
1043 ao_scheme_frame_add(struct ao_scheme_frame *frame, ao_poly atom, ao_poly val);
1044
1045 #ifdef AO_SCHEME_FEATURE_UNDEF
1046 ao_poly
1047 ao_scheme_frame_del(struct ao_scheme_frame *frame, ao_poly atom);
1048 #endif
1049
1050 void
1051 ao_scheme_frame_write(FILE *out, ao_poly p, bool write);
1052
1053 void
1054 ao_scheme_frame_init(void);
1055
1056 /* lambda */
1057 extern const struct ao_scheme_type ao_scheme_lambda_type;
1058
1059 extern const char * const ao_scheme_state_names[];
1060
1061 struct ao_scheme_lambda *
1062 ao_scheme_lambda_new(ao_poly cons);
1063
1064 void
1065 ao_scheme_lambda_write(FILE *out, ao_poly lambda, bool write);
1066
1067 ao_poly
1068 ao_scheme_lambda_eval(void);
1069
1070 /* stack */
1071
1072 extern const struct ao_scheme_type ao_scheme_stack_type;
1073 extern struct ao_scheme_stack   *ao_scheme_stack;
1074 extern struct ao_scheme_stack   *ao_scheme_stack_free_list;
1075
1076 extern int                      ao_scheme_frame_print_indent;
1077
1078 void
1079 ao_scheme_stack_reset(struct ao_scheme_stack *stack);
1080
1081 int
1082 ao_scheme_stack_push(void);
1083
1084 void
1085 ao_scheme_stack_pop(void);
1086
1087 void
1088 ao_scheme_stack_write(FILE *out, ao_poly stack, bool write);
1089
1090 ao_poly
1091 ao_scheme_stack_eval(void);
1092
1093 /* error */
1094
1095 void
1096 ao_scheme_vfprintf(FILE *out, const char *format, va_list args);
1097
1098 void
1099 ao_scheme_fprintf(FILE *out, const char *format, ...);
1100
1101 ao_poly
1102 ao_scheme_error(int error, const char *format, ...);
1103
1104 /* builtins */
1105
1106 #define AO_SCHEME_BUILTIN_DECLS
1107 #include "ao_scheme_builtin.h"
1108
1109 /* debugging macros */
1110
1111 #if DBG_EVAL || DBG_READ
1112 int ao_scheme_stack_depth;
1113 #endif
1114
1115 #if DBG_EVAL
1116 #define DBG_DO(a)       a
1117 #define DBG_INDENT()    do { int _s; for(_s = 0; _s < ao_scheme_stack_depth; _s++) printf("  "); } while(0)
1118 #define DBG_IN()        (++ao_scheme_stack_depth)
1119 #define DBG_OUT()       (--ao_scheme_stack_depth)
1120 #define DBG_RESET()     (ao_scheme_stack_depth = 0)
1121 #define DBG(...)        ao_scheme_fprintf(stdout, __VA_ARGS__)
1122 #define DBGI(...)       do { printf("%4d: ", __LINE__); DBG_INDENT(); DBG(__VA_ARGS__); } while (0)
1123 #define DBG_CONS(a)     ao_scheme_cons_write(stdout, ao_scheme_cons_poly(a), true)
1124 #define DBG_POLY(a)     ao_scheme_poly_write(stdout, a, true)
1125 #define OFFSET(a)       ((a) ? (int) ((uint8_t *) a - ao_scheme_pool) : -1)
1126 #define DBG_STACK()     ao_scheme_stack_write(stdout, ao_scheme_stack_poly(ao_scheme_stack), true)
1127 static inline void
1128 ao_scheme_frames_dump(void)
1129 {
1130         struct ao_scheme_stack *s;
1131         DBGI(".. current frame: "); DBG_POLY(ao_scheme_frame_poly(ao_scheme_frame_current)); DBG("\n");
1132         for (s = ao_scheme_stack; s; s = ao_scheme_poly_stack(s->prev)) {
1133                 DBGI(".. stack frame: "); DBG_POLY(s->frame); DBG("\n");
1134         }
1135 }
1136 #define DBG_FRAMES()    ao_scheme_frames_dump()
1137 #else
1138 #define DBG_DO(a)
1139 #define DBG_INDENT()
1140 #define DBG_IN()
1141 #define DBG_OUT()
1142 #define DBG(...)
1143 #define DBGI(...)
1144 #define DBG_CONS(a)
1145 #define DBG_POLY(a)
1146 #define DBG_RESET()
1147 #define DBG_STACK()
1148 #define DBG_FRAMES()
1149 #endif
1150
1151 #if DBG_READ
1152 #define RDBGI(...)      do { printf("%4d: ", __LINE__); DBG_INDENT(); ao_scheme_printf(__VA_ARGS__); } while (0)
1153 #define RDBG_IN()       (++ao_scheme_stack_depth)
1154 #define RDBG_OUT()      (--ao_scheme_stack_depth)
1155 #else
1156 #define RDBGI(...)
1157 #define RDBG_IN()
1158 #define RDBG_OUT()
1159 #endif
1160
1161 static inline int
1162 ao_scheme_mdbg_offset(void *a)
1163 {
1164         uint8_t         *u = a;
1165
1166         if (u == 0)
1167                 return -1;
1168
1169         if (ao_scheme_pool <= u && u < ao_scheme_pool + AO_SCHEME_POOL)
1170                 return u - ao_scheme_pool;
1171
1172 #ifndef AO_SCHEME_MAKE_CONST
1173         if (ao_scheme_const <= u && u < ao_scheme_const + AO_SCHEME_POOL_CONST)
1174                 return - (int) (u - ao_scheme_const);
1175 #endif
1176         return -2;
1177 }
1178
1179 #define MDBG_OFFSET(a)  ao_scheme_mdbg_offset(a)
1180
1181 #if DBG_MEM
1182
1183 #define DBG_MEM_START   1
1184
1185 #include <assert.h>
1186 extern int dbg_move_depth;
1187 #define MDBG_DUMP 1
1188
1189 extern int dbg_mem;
1190
1191 #define MDBG_DO(a)      a
1192 #define MDBG_MOVE(...) do { if (dbg_mem) { int d; for (d = 0; d < dbg_move_depth; d++) printf ("  "); printf(__VA_ARGS__); } } while (0)
1193 #define MDBG_MORE(...) do { if (dbg_mem) printf(__VA_ARGS__); } while (0)
1194 #define MDBG_MOVE_IN()  (dbg_move_depth++)
1195 #define MDBG_MOVE_OUT() (--dbg_move_depth)
1196
1197 #else
1198
1199 #define MDBG_DO(a)
1200 #define MDBG_MOVE(...)
1201 #define MDBG_MORE(...)
1202 #define MDBG_MOVE_IN()
1203 #define MDBG_MOVE_OUT()
1204
1205 #endif
1206
1207 #endif /* _AO_SCHEME_H_ */