Commit | Line | Data |
---|---|---|
4a83289a MW |
1 | /* -*-sod-*- */ |
2 | ||
fd040f06 | 3 | code h: includes { |
4a83289a MW |
4 | #include "sod.h" |
5 | } | |
6 | ||
fd040f06 | 7 | code c: includes { |
4a83289a MW |
8 | #include <stdio.h> |
9 | #include <stdlib.h> | |
10 | #include <string.h> | |
11 | ||
12 | #include "test.h" | |
13 | } | |
14 | ||
fd040f06 | 15 | code c: early_user { |
4a83289a MW |
16 | /*----- Preliminary definitions -------------------------------------------*/ |
17 | ||
18 | /* Confuse the fragment scanner... */ | |
19 | #define LBRACE { | |
20 | #define RBRACE } | |
21 | ||
22 | static const char *test_name; | |
23 | static int test_seq; | |
24 | ||
25 | static void prepare(const char *name) { test_name = name; test_seq = 0; } | |
26 | ||
27 | static void step(int q, const char *where) | |
28 | { | |
29 | if (test_seq != q) { | |
30 | fprintf(stderr, "test %s (%s): step %d instead of %d\n", | |
31 | test_name, where, q, test_seq); | |
32 | abort(); | |
33 | } | |
34 | test_seq++; | |
35 | } | |
36 | ||
37 | static void done(int q, const char *where) { step(q, where); } | |
38 | ||
39 | #define STRINGIFY_(x) #x | |
40 | #define STRINGIFY(x) STRINGIFY_(x) | |
41 | #define WHERE __FILE__ ":" STRINGIFY(__LINE__) | |
42 | #define STEP(q) step((q), WHERE) | |
43 | #define DONE(q) done((q), WHERE) | |
44 | ||
45 | } | |
46 | ||
fd040f06 | 47 | code c: (tests head) |
4a83289a MW |
48 | [user (tests head) tests (tests tail) main (user end)] |
49 | { | |
50 | /*----- Test machinery ----------------------------------------------------*/ | |
51 | ||
52 | static void tests(void) | |
53 | LBRACE | |
54 | } | |
fd040f06 | 55 | code c: (tests tail) { |
4a83289a MW |
56 | RBRACE |
57 | ||
58 | } | |
59 | ||
fd040f06 | 60 | code c: main { |
4a83289a MW |
61 | /*----- Main program ------------------------------------------------------*/ |
62 | ||
63 | int main(void) | |
64 | { | |
65 | tests(); | |
66 | return (0); | |
67 | } | |
68 | ||
69 | } | |
70 | ||
71 | /*----- Various kinds of method combinations ------------------------------*/ | |
72 | ||
fd040f06 | 73 | code h: early_user { |
4a83289a MW |
74 | struct item { |
75 | struct item *next; | |
76 | const char *p; | |
77 | }; | |
78 | ||
79 | } | |
80 | ||
fd040f06 | 81 | code c: early_user { |
4a83289a MW |
82 | static void *xmalloc(size_t n) |
83 | { | |
84 | void *p = malloc(n); | |
85 | if (!p) { perror("malloc"); exit(EXIT_FAILURE); } | |
86 | return (p); | |
87 | } | |
88 | ||
89 | static struct item *make_item(const char *p) | |
90 | { struct item *q = xmalloc(sizeof(*q)); q->p = p; return (q); } | |
91 | ||
92 | static void free_list(struct item *i) | |
93 | { struct item *ii; while (i) { ii = i->next; free(i); i = ii; } } | |
94 | ||
95 | static int check_list(struct item *i, ...) | |
96 | { | |
97 | va_list ap; | |
98 | const char *p; | |
99 | int rc = -1; | |
100 | ||
101 | va_start(ap, i); | |
102 | for (;;) { | |
103 | p = va_arg(ap, const char *); | |
104 | if (!p) break; | |
105 | if (!i || strcmp(i->p, p) != 0) break; | |
106 | i = i->next; | |
107 | } | |
108 | if (!i) rc = 0; | |
109 | va_end(ap); | |
110 | return (rc); | |
111 | } | |
112 | ||
113 | struct vec { int *v; size_t n; }; | |
114 | ||
115 | static void free_vec(struct vec *v) { free(v->v); } | |
116 | ||
117 | static int check_vec(struct vec *v, ...) | |
118 | { | |
119 | va_list ap; | |
120 | int j; | |
121 | size_t i = 0; | |
122 | int rc = -1; | |
123 | ||
124 | va_start(ap, v); | |
125 | for (;;) { | |
126 | j = va_arg(ap, int); | |
127 | if (j < 0) break; | |
128 | if (i == v->n || j != v->v[i]) break; | |
129 | i++; | |
130 | } | |
131 | if (i == v->n) rc = 0; | |
132 | va_end(ap); | |
133 | return (rc); | |
134 | } | |
135 | ||
136 | } | |
137 | ||
1e99dff0 | 138 | [link = SodObject, nick = base] |
fd040f06 | 139 | class T1Base: SodObject { |
b07535d8 MW |
140 | [combination = progn] void aprogn(); |
141 | [combination = sum] int asum(); | |
142 | [combination = and] int aand(); | |
143 | [combination = max] int amax(); | |
4a83289a MW |
144 | |
145 | [combination = custom, | |
b07535d8 | 146 | empty = { sod_ret = 0; }, |
4a83289a MW |
147 | decls = { struct item **head = &sod_ret; }, |
148 | each = { *head = sod_val; head = &sod_val->next; }, | |
149 | after = { *head = 0; }] | |
b07535d8 | 150 | struct item *alist(); |
4a83289a MW |
151 | |
152 | [combination = custom, | |
153 | decls = { int *v; size_t i = 0; }, methty = <int>, count = n, | |
b07535d8 | 154 | empty = { sod_ret.v = 0; sod_ret.n = 0; }, |
4a83289a MW |
155 | before = { v = xmalloc(n*sizeof(int)); }, |
156 | each = { v[i++] = sod_val; }, | |
157 | after = { sod_ret.v = v; sod_ret.n = n; }] | |
158 | struct vec avec(); | |
b07535d8 MW |
159 | } |
160 | ||
1e99dff0 | 161 | [link = T1Base, nick = mid] |
b07535d8 | 162 | class T1Mid: T1Base { |
1e99dff0 MW |
163 | void base.aprogn() { STEP(1); } |
164 | int base.asum() { return 1; } | |
165 | int base.aand() { return 8; } | |
166 | int base.amax() { return 12; } | |
167 | struct item *base.alist() { return make_item("mid"); } | |
168 | int base.avec() { return 19; } | |
4a83289a MW |
169 | } |
170 | ||
1e99dff0 | 171 | [link = T1Mid, nick = sub] |
b07535d8 | 172 | class T1Sub: T1Mid { |
1e99dff0 MW |
173 | void base.aprogn() { STEP(0); } |
174 | int base.asum() { return 2; } | |
175 | int base.aand() { return 6; } | |
176 | int base.amax() { return 17; } | |
177 | struct item *base.alist() { return make_item("sub"); } | |
178 | int base.avec() { return 4; } | |
4a83289a MW |
179 | } |
180 | ||
fd040f06 | 181 | code c: tests { |
4a83289a | 182 | prepare("aggregate, base"); |
a142609c | 183 | { SOD_DECL(T1Base, t1, NO_KWARGS); |
b07535d8 MW |
184 | struct item *l; |
185 | struct vec v; | |
186 | STEP(0); T1Base_aprogn(t1); STEP(1); | |
187 | if (T1Base_asum(t1) == 0) STEP(2); | |
188 | if (T1Base_aand(t1) == 1) STEP(3); | |
1e99dff0 | 189 | if (!t1->_vt->base.amax) STEP(4); |
b07535d8 MW |
190 | l = T1Base_alist(t1); |
191 | if (!l) STEP(5); | |
192 | v = T1Base_avec(t1); | |
193 | if (!v.n) STEP(6); | |
194 | DONE(7); | |
195 | } | |
196 | prepare("aggregate, mid"); | |
197 | { SOD_DECL(T1Mid, t1, NO_KWARGS); | |
4a83289a MW |
198 | struct item *l; |
199 | struct vec v; | |
200 | STEP(0); T1Base_aprogn(t1); /* 1 */ | |
201 | if (T1Base_asum(t1) == 1) STEP(2); | |
202 | if (T1Base_aand(t1) == 8) STEP(3); | |
203 | if (T1Base_amax(t1) == 12) STEP(4); | |
204 | l = T1Base_alist(t1); | |
b07535d8 | 205 | if (!check_list(l, "mid", (const char *)0)) STEP(5); |
4a83289a MW |
206 | free_list(l); |
207 | v = T1Base_avec(t1); | |
208 | if (!check_vec(&v, 19, -1)) STEP(6); | |
209 | free_vec(&v); | |
210 | DONE(7); | |
211 | } | |
212 | prepare("aggregate, sub"); | |
a142609c | 213 | { SOD_DECL(T1Sub, t1, NO_KWARGS); |
4a83289a MW |
214 | struct item *l; |
215 | struct vec v; | |
216 | T1Base_aprogn(t1); /* 0, 1 */ | |
217 | if (T1Base_asum(t1) == 3) STEP(2); | |
218 | if (T1Base_aand(t1) == 8) STEP(3); | |
219 | if (T1Base_amax(t1) == 17) STEP(4); | |
220 | l = T1Base_alist(t1); | |
b07535d8 | 221 | if (!check_list(l, "sub", "mid", (const char *)0)) STEP(5); |
4a83289a MW |
222 | free_list(l); |
223 | v = T1Base_avec(t1); | |
224 | if (!check_vec(&v, 4, 19, -1)) STEP(6); | |
225 | free_vec(&v); | |
226 | DONE(7); | |
227 | } | |
228 | } | |
229 | ||
b2983f35 MW |
230 | /*----- Slot and user initargs --------------------------------------------*/ |
231 | ||
232 | [link = SodObject, nick = t2] | |
fd040f06 | 233 | class T2: SodObject { |
b2983f35 MW |
234 | [initarg = x] int x = 0; |
235 | ||
236 | initarg int y = 1; | |
237 | init { if (!y) STEP(0); } | |
238 | } | |
239 | ||
fd040f06 | 240 | code c: tests { |
b2983f35 MW |
241 | prepare("initargs, defaults"); |
242 | { SOD_DECL(T2, t, NO_KWARGS); | |
243 | if (t->t2.x == 0) STEP(0); | |
244 | DONE(1); | |
245 | } | |
246 | prepare("initargs, explicit"); | |
247 | { SOD_DECL(T2, t, KWARGS(K(x, 42) K(y, 0))); | |
248 | if (t->t2.x == 42) STEP(1); | |
249 | DONE(2); | |
250 | } | |
251 | } | |
252 | ||
bce58d37 MW |
253 | /*----- Keyword argument propagation --------------------------------------*/ |
254 | ||
255 | [link = SodObject, nick = base] | |
fd040f06 | 256 | class T3Base: SodObject { |
bce58d37 MW |
257 | void m0(?int x) { STEP(x); } |
258 | void m1(?) { } | |
259 | } | |
260 | ||
12386a26 | 261 | [link = T3Base, nick = mid] |
fd040f06 | 262 | class T3Mid: T3Base { |
12386a26 MW |
263 | void base.m0(?int y) { STEP(y); CALL_NEXT_METHOD; } |
264 | void base.m1(?) { STEP(4); CALL_NEXT_METHOD; } | |
265 | } | |
266 | ||
267 | [link = T3Mid, nick = sub] | |
fd040f06 | 268 | class T3Sub: T3Mid { |
bce58d37 MW |
269 | void base.m0(?int z) { STEP(z); CALL_NEXT_METHOD; } |
270 | void base.m1(?int z) { STEP(z); CALL_NEXT_METHOD; } | |
271 | } | |
272 | ||
fd040f06 | 273 | code c: tests { |
bce58d37 MW |
274 | prepare("kwargs"); |
275 | { SOD_DECL(T3Sub, t, NO_KWARGS); | |
12386a26 MW |
276 | T3Base_m0(t, KWARGS(K(z, 0) K(y, 1) K(x, 2))); |
277 | T3Base_m1(t, KWARGS(K(z, 3))); | |
278 | DONE(5); | |
bce58d37 MW |
279 | } |
280 | } | |
281 | ||
4a83289a | 282 | /*----- That's all, folks -------------------------------------------------*/ |