chiark / gitweb /
src/method-impl.lisp: Initialize `suppliedp' flags properly.
[sod] / test / test.sod
1 /* -*-sod-*- */
2
3 code h: includes {
4 #include "sod.h"
5 }
6
7 code c: includes {
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <string.h>
11
12 #include "test.h"
13 }
14
15 code c: early_user {
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
47 code c: (tests head)
48   [user (tests head) tests (tests tail) main (user end)]
49 {
50 /*----- Test machinery ----------------------------------------------------*/
51
52 static void tests(void)
53 LBRACE
54 }
55 code c: (tests tail) {
56 RBRACE
57
58 }
59
60 code c: main {
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
73 code h: early_user {
74 struct item {
75   struct item *next;
76   const char *p;
77 };
78
79 }
80
81 code c: early_user {
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
138 [link = SodObject, nick = base]
139 class T1Base: SodObject {
140   [combination = progn] void aprogn();
141   [combination = sum] int asum();
142   [combination = and] int aand();
143   [combination = max] int amax();
144
145   [combination = custom,
146    empty = { sod_ret = 0; },
147    decls = { struct item **head = &sod_ret; },
148    each = { *head = sod_val; head = &sod_val->next; },
149    after = { *head = 0; }]
150   struct item *alist();
151
152   [combination = custom,
153    decls = { int *v; size_t i = 0; }, methty = <int>, count = n,
154    empty = { sod_ret.v = 0; sod_ret.n = 0; },
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();
159 }
160
161 [link = T1Base, nick = mid]
162 class T1Mid: T1Base {
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; }
169 }
170
171 [link = T1Mid, nick = sub]
172 class T1Sub: T1Mid {
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; }
179 }
180
181 code c: tests {
182   prepare("aggregate, base");
183   { SOD_DECL(T1Base, t1, NO_KWARGS);
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);
189     if (!t1->_vt->base.amax) STEP(4);
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);
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);
205     if (!check_list(l, "mid", (const char *)0)) STEP(5);
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");
213   { SOD_DECL(T1Sub, t1, NO_KWARGS);
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);
221     if (!check_list(l, "sub", "mid", (const char *)0)) STEP(5);
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
230 /*----- Slot and user initargs --------------------------------------------*/
231
232 [link = SodObject, nick = t2]
233 class T2: SodObject {
234   [initarg = x] int x = 0;
235
236   initarg int y = 1;
237   init { if (!y) STEP(0); }
238 }
239
240 code c: tests {
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
253 /*----- Keyword argument propagation --------------------------------------*/
254
255 [link = SodObject, nick = base]
256 class T3Base: SodObject {
257   void m0(?int x) { STEP(x); }
258   void m1(?) { }
259 }
260
261 [link = T3Base, nick = mid]
262 class T3Mid: T3Base {
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]
268 class T3Sub: T3Mid {
269   void base.m0(?int z) { STEP(z); CALL_NEXT_METHOD; }
270   void base.m1(?int z) { STEP(z); CALL_NEXT_METHOD; }
271 }
272
273 code c: tests {
274   prepare("kwargs");
275   { SOD_DECL(T3Sub, t, NO_KWARGS);
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);
279   }
280 }
281
282 /*----- That's all, folks -------------------------------------------------*/