2ea221ec996e4404f726396fd096b7c4f0d8b507
[fw/altos] / src / scheme / ao_scheme_poly.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_scheme.h"
16
17 struct ao_scheme_funcs {
18         void (*write)(ao_poly);
19         void (*display)(ao_poly);
20 };
21
22 static const struct ao_scheme_funcs ao_scheme_funcs[AO_SCHEME_NUM_TYPE] = {
23         [AO_SCHEME_CONS] = {
24                 .write = ao_scheme_cons_write,
25                 .display = ao_scheme_cons_display,
26         },
27 #ifdef AO_SCHEME_FEATURE_BIGINT
28         [AO_SCHEME_BIGINT] = {
29                 .write = ao_scheme_bigint_write,
30                 .display = ao_scheme_bigint_write,
31         },
32 #endif
33         [AO_SCHEME_INT] = {
34                 .write = ao_scheme_int_write,
35                 .display = ao_scheme_int_write,
36         },
37         [AO_SCHEME_ATOM] = {
38                 .write = ao_scheme_atom_write,
39                 .display = ao_scheme_atom_write,
40         },
41         [AO_SCHEME_BUILTIN] = {
42                 .write = ao_scheme_builtin_write,
43                 .display = ao_scheme_builtin_write,
44         },
45         [AO_SCHEME_FRAME] = {
46                 .write = ao_scheme_frame_write,
47                 .display = ao_scheme_frame_write,
48         },
49         [AO_SCHEME_FRAME_VALS] = {
50                 .write = NULL,
51                 .display = NULL,
52         },
53         [AO_SCHEME_LAMBDA] = {
54                 .write = ao_scheme_lambda_write,
55                 .display = ao_scheme_lambda_write,
56         },
57         [AO_SCHEME_STACK] = {
58                 .write = ao_scheme_stack_write,
59                 .display = ao_scheme_stack_write,
60         },
61         [AO_SCHEME_BOOL] = {
62                 .write = ao_scheme_bool_write,
63                 .display = ao_scheme_bool_write,
64         },
65         [AO_SCHEME_STRING] = {
66                 .write = ao_scheme_string_write,
67                 .display = ao_scheme_string_display,
68         },
69 #ifdef AO_SCHEME_FEATURE_FLOAT
70         [AO_SCHEME_FLOAT] = {
71                 .write = ao_scheme_float_write,
72                 .display = ao_scheme_float_write,
73         },
74 #endif
75 #ifdef AO_SCHEME_FEATURE_VECTOR
76         [AO_SCHEME_VECTOR] = {
77                 .write = ao_scheme_vector_write,
78                 .display = ao_scheme_vector_display
79         },
80 #endif
81 };
82
83 static void ao_scheme_invalid_write(ao_poly p) {
84         printf("??? 0x%04x ???", p);
85 }
86
87 static const struct ao_scheme_funcs ao_scheme_invalid_funcs = {
88         .write = ao_scheme_invalid_write,
89         .display = ao_scheme_invalid_write,
90 };
91
92 static const struct ao_scheme_funcs *
93 funcs(ao_poly p)
94 {
95         uint8_t type = ao_scheme_poly_type(p);
96
97         if (type < AO_SCHEME_NUM_TYPE)
98                 return &ao_scheme_funcs[type];
99         return &ao_scheme_invalid_funcs;
100 }
101
102 void (*ao_scheme_poly_write_func(ao_poly p))(ao_poly p)
103 {
104         return funcs(p)->write;
105 }
106
107 void (*ao_scheme_poly_display_func(ao_poly p))(ao_poly p)
108 {
109         return funcs(p)->display;
110 }
111
112 void *
113 ao_scheme_ref(ao_poly poly) {
114         if (poly == AO_SCHEME_NIL)
115                 return NULL;
116         if (poly & AO_SCHEME_CONST)
117                 return (void *) (ao_scheme_const + (poly & AO_SCHEME_REF_MASK) - 4);
118         return (void *) (ao_scheme_pool + (poly & AO_SCHEME_REF_MASK) - 4);
119 }
120
121 ao_poly
122 ao_scheme_poly(const void *addr, ao_poly type) {
123         const uint8_t   *a = addr;
124         if (a == NULL)
125                 return AO_SCHEME_NIL;
126         if (AO_SCHEME_IS_CONST(a))
127                 return AO_SCHEME_CONST | (a - ao_scheme_const + 4) | type;
128         return (a - ao_scheme_pool + 4) | type;
129 }