iscc: add typeof operator
[barvinok.git] / iscc.c
blob606754ffee73c3ccab337ac063c04f36d387dfc9
1 #include <assert.h>
2 #include <stdio.h>
3 #include <string.h>
4 #include <isl/obj.h>
5 #include <isl/stream.h>
6 #include <isl/vertices.h>
7 #include <isl_obj_list.h>
8 #include <isl_obj_str.h>
9 #include <barvinok/isl.h>
10 #include <barvinok/options.h>
12 #include "config.h"
14 #ifdef HAVE_CLOOG
15 #include <cloog/isl/cloog.h>
16 #endif
18 static int isl_bool_false = 0;
19 static int isl_bool_true = 1;
20 static int isl_bool_error = -1;
22 enum iscc_op { ISCC_READ, ISCC_SOURCE, ISCC_VERTICES,
23 ISCC_LAST, ISCC_ANY, ISCC_BEFORE, ISCC_UNDER,
24 ISCC_TYPEOF,
25 ISCC_N_OP };
26 static const char *op_name[ISCC_N_OP] = {
27 [ISCC_READ] = "read",
28 [ISCC_SOURCE] = "source",
29 [ISCC_VERTICES] = "vertices",
30 [ISCC_LAST] = "last",
31 [ISCC_ANY] = "any",
32 [ISCC_BEFORE] = "before",
33 [ISCC_UNDER] = "under",
34 [ISCC_TYPEOF] = "typeof"
36 static enum isl_token_type iscc_op[ISCC_N_OP];
38 struct isl_arg_choice iscc_format[] = {
39 {"isl", ISL_FORMAT_ISL},
40 {"omega", ISL_FORMAT_OMEGA},
41 {"polylib", ISL_FORMAT_POLYLIB},
42 {"ext-polylib", ISL_FORMAT_EXT_POLYLIB},
43 {"latex", ISL_FORMAT_LATEX},
44 {"C", ISL_FORMAT_C},
45 {0}
48 struct iscc_options {
49 struct barvinok_options *barvinok;
50 unsigned format;
53 struct isl_arg iscc_options_arg[] = {
54 ISL_ARG_CHILD(struct iscc_options, barvinok, "barvinok", barvinok_options_arg,
55 "barvinok options")
56 ISL_ARG_CHOICE(struct iscc_options, format, 0, "format", \
57 iscc_format, ISL_FORMAT_ISL, "output format")
58 ISL_ARG_END
61 ISL_ARG_DEF(iscc_options, struct iscc_options, iscc_options_arg)
63 static void *isl_obj_bool_copy(void *v)
65 return v;
68 static void isl_obj_bool_free(void *v)
72 static __isl_give isl_printer *isl_obj_bool_print(__isl_take isl_printer *p,
73 void *v)
75 if (v == &isl_bool_true)
76 return isl_printer_print_str(p, "True");
77 else if (v == &isl_bool_false)
78 return isl_printer_print_str(p, "False");
79 else
80 return isl_printer_print_str(p, "Error");
83 static void *isl_obj_bool_add(void *v1, void *v2)
85 return v1;
88 struct isl_obj_vtable isl_obj_bool_vtable = {
89 isl_obj_bool_copy,
90 isl_obj_bool_add,
91 isl_obj_bool_print,
92 isl_obj_bool_free
94 #define isl_obj_bool (&isl_obj_bool_vtable)
96 int *isl_bool_from_int(int res)
98 return res < 0 ? &isl_bool_error : res ? &isl_bool_true : &isl_bool_false;
101 int *union_map_is_equal(__isl_take isl_union_map *map1,
102 __isl_take isl_union_map *map2)
104 int res = isl_union_map_is_equal(map1, map2);
105 isl_union_map_free(map1);
106 isl_union_map_free(map2);
107 return isl_bool_from_int(res);
109 int *union_set_is_equal(__isl_take isl_union_set *set1,
110 __isl_take isl_union_set *set2)
112 return union_map_is_equal((isl_union_map *)set1, (isl_union_map *)set2);
115 int *union_map_is_subset(__isl_take isl_union_map *map1,
116 __isl_take isl_union_map *map2)
118 int res = isl_union_map_is_subset(map1, map2);
119 isl_union_map_free(map1);
120 isl_union_map_free(map2);
121 return isl_bool_from_int(res);
123 int *union_set_is_subset(__isl_take isl_union_set *set1,
124 __isl_take isl_union_set *set2)
126 return union_map_is_subset((isl_union_map *)set1, (isl_union_map *)set2);
129 int *union_map_is_strict_subset(__isl_take isl_union_map *map1,
130 __isl_take isl_union_map *map2)
132 int res = isl_union_map_is_strict_subset(map1, map2);
133 isl_union_map_free(map1);
134 isl_union_map_free(map2);
135 return isl_bool_from_int(res);
137 int *union_set_is_strict_subset(__isl_take isl_union_set *set1,
138 __isl_take isl_union_set *set2)
140 return union_map_is_strict_subset((isl_union_map *)set1,
141 (isl_union_map *)set2);
144 int *union_map_is_superset(__isl_take isl_union_map *map1,
145 __isl_take isl_union_map *map2)
147 return union_map_is_subset(map2, map1);
149 int *union_set_is_superset(__isl_take isl_union_set *set1,
150 __isl_take isl_union_set *set2)
152 return union_set_is_subset(set2, set1);
155 int *union_map_is_strict_superset(__isl_take isl_union_map *map1,
156 __isl_take isl_union_map *map2)
158 return union_map_is_strict_subset(map2, map1);
160 int *union_set_is_strict_superset(__isl_take isl_union_set *set1,
161 __isl_take isl_union_set *set2)
163 return union_set_is_strict_subset(set2, set1);
166 extern struct isl_obj_vtable isl_obj_list_vtable;
167 #define isl_obj_list (&isl_obj_list_vtable)
169 typedef void *(*isc_bin_op_fn)(void *lhs, void *rhs);
170 struct isc_bin_op {
171 enum isl_token_type op;
172 isl_obj_type lhs;
173 isl_obj_type rhs;
174 isl_obj_type res;
175 isc_bin_op_fn fn;
177 struct isc_named_bin_op {
178 char *name;
179 struct isc_bin_op op;
182 struct iscc_at {
183 isl_union_pw_qpolynomial *upwqp;
184 isl_union_pw_qpolynomial *res;
187 static int eval_at(__isl_take isl_point *pnt, void *user)
189 struct iscc_at *at = (struct iscc_at *) user;
190 isl_qpolynomial *qp;
191 isl_set *set;
193 set = isl_set_from_point(isl_point_copy(pnt));
194 qp = isl_union_pw_qpolynomial_eval(
195 isl_union_pw_qpolynomial_copy(at->upwqp), pnt);
197 at->res = isl_union_pw_qpolynomial_add(at->res,
198 isl_union_pw_qpolynomial_from_pw_qpolynomial(
199 isl_pw_qpolynomial_alloc(set, qp)));
201 return 0;
204 __isl_give isl_union_pw_qpolynomial *isl_union_pw_qpolynomial_at(
205 __isl_take isl_union_pw_qpolynomial *upwqp,
206 __isl_take isl_union_set *uset)
208 struct iscc_at at;
210 at.upwqp = upwqp;
211 at.res = isl_union_pw_qpolynomial_zero(isl_union_set_get_dim(uset));
213 isl_union_set_foreach_point(uset, eval_at, &at);
215 isl_union_pw_qpolynomial_free(upwqp);
216 isl_union_set_free(uset);
218 return at.res;
221 struct iscc_fold_at {
222 isl_union_pw_qpolynomial_fold *upwf;
223 isl_union_pw_qpolynomial *res;
226 static int eval_fold_at(__isl_take isl_point *pnt, void *user)
228 struct iscc_fold_at *at = (struct iscc_fold_at *) user;
229 isl_qpolynomial *qp;
230 isl_set *set;
232 set = isl_set_from_point(isl_point_copy(pnt));
233 qp = isl_union_pw_qpolynomial_fold_eval(
234 isl_union_pw_qpolynomial_fold_copy(at->upwf), pnt);
236 at->res = isl_union_pw_qpolynomial_add(at->res,
237 isl_union_pw_qpolynomial_from_pw_qpolynomial(
238 isl_pw_qpolynomial_alloc(set, qp)));
240 return 0;
243 __isl_give isl_union_pw_qpolynomial *isl_union_pw_qpolynomial_fold_at(
244 __isl_take isl_union_pw_qpolynomial_fold *upwf,
245 __isl_take isl_union_set *uset)
247 struct iscc_fold_at at;
249 at.upwf = upwf;
250 at.res = isl_union_pw_qpolynomial_zero(isl_union_set_get_dim(uset));
252 isl_union_set_foreach_point(uset, eval_fold_at, &at);
254 isl_union_pw_qpolynomial_fold_free(upwf);
255 isl_union_set_free(uset);
257 return at.res;
260 static __isl_give isl_union_pw_qpolynomial_fold *union_pw_qpolynomial_add_union_pw_qpolynomial_fold(
261 __isl_take isl_union_pw_qpolynomial *upwqp,
262 __isl_take isl_union_pw_qpolynomial_fold *upwf)
264 return isl_union_pw_qpolynomial_fold_add_union_pw_qpolynomial(upwf,
265 upwqp);
268 static __isl_give struct isl_list *union_map_apply_union_pw_qpolynomial_fold(
269 __isl_take isl_union_map *umap,
270 __isl_take isl_union_pw_qpolynomial_fold *upwf)
272 isl_ctx *ctx;
273 struct isl_list *list;
274 int tight;
276 ctx = isl_union_map_get_ctx(umap);
277 list = isl_list_alloc(ctx, 2);
278 if (!list)
279 goto error2;
281 list->obj[0].type = isl_obj_union_pw_qpolynomial_fold;
282 list->obj[0].v = isl_union_map_apply_union_pw_qpolynomial_fold(umap,
283 upwf, &tight);
284 list->obj[1].type = isl_obj_bool;
285 list->obj[1].v = tight ? &isl_bool_true : &isl_bool_false;
286 if (tight < 0 || !list->obj[0].v)
287 goto error;
289 return list;
290 error2:
291 isl_union_map_free(umap);
292 isl_union_pw_qpolynomial_fold_free(upwf);
293 error:
294 isl_list_free(list);
295 return NULL;
298 struct isc_bin_op bin_ops[] = {
299 { '+', isl_obj_union_set, isl_obj_union_set,
300 isl_obj_union_set,
301 (isc_bin_op_fn) &isl_union_set_union },
302 { '+', isl_obj_union_map, isl_obj_union_map,
303 isl_obj_union_map,
304 (isc_bin_op_fn) &isl_union_map_union },
305 { '-', isl_obj_union_set, isl_obj_union_set,
306 isl_obj_union_set,
307 (isc_bin_op_fn) &isl_union_set_subtract },
308 { '-', isl_obj_union_map, isl_obj_union_map,
309 isl_obj_union_map,
310 (isc_bin_op_fn) &isl_union_map_subtract },
311 { '*', isl_obj_union_set, isl_obj_union_set,
312 isl_obj_union_set,
313 (isc_bin_op_fn) &isl_union_set_intersect },
314 { '*', isl_obj_union_map, isl_obj_union_map,
315 isl_obj_union_map,
316 (isc_bin_op_fn) &isl_union_map_intersect },
317 { '*', isl_obj_union_map, isl_obj_union_set,
318 isl_obj_union_map,
319 (isc_bin_op_fn) &isl_union_map_intersect_domain },
320 { '.', isl_obj_union_map, isl_obj_union_map,
321 isl_obj_union_map,
322 (isc_bin_op_fn) &isl_union_map_apply_range },
323 { '.', isl_obj_union_map, isl_obj_union_pw_qpolynomial,
324 isl_obj_union_pw_qpolynomial,
325 (isc_bin_op_fn) &isl_union_map_apply_union_pw_qpolynomial },
326 { '.', isl_obj_union_map, isl_obj_union_pw_qpolynomial_fold,
327 isl_obj_list,
328 (isc_bin_op_fn) &union_map_apply_union_pw_qpolynomial_fold },
329 { ISL_TOKEN_TO, isl_obj_union_set, isl_obj_union_set,
330 isl_obj_union_map,
331 (isc_bin_op_fn) &isl_union_map_from_domain_and_range },
332 { '=', isl_obj_union_set, isl_obj_union_set, isl_obj_bool,
333 (isc_bin_op_fn) &union_set_is_equal },
334 { '=', isl_obj_union_map, isl_obj_union_map, isl_obj_bool,
335 (isc_bin_op_fn) &union_map_is_equal },
336 { ISL_TOKEN_LE, isl_obj_union_set, isl_obj_union_set,
337 isl_obj_bool, (isc_bin_op_fn) &union_set_is_subset },
338 { ISL_TOKEN_LE, isl_obj_union_map, isl_obj_union_map,
339 isl_obj_bool, (isc_bin_op_fn) &union_map_is_subset },
340 { ISL_TOKEN_LT, isl_obj_union_set, isl_obj_union_set,
341 isl_obj_bool, (isc_bin_op_fn) &union_set_is_strict_subset },
342 { ISL_TOKEN_LT, isl_obj_union_map, isl_obj_union_map,
343 isl_obj_bool, (isc_bin_op_fn) &union_map_is_strict_subset },
344 { ISL_TOKEN_GE, isl_obj_union_set, isl_obj_union_set,
345 isl_obj_bool, (isc_bin_op_fn) &union_set_is_superset },
346 { ISL_TOKEN_GE, isl_obj_union_map, isl_obj_union_map,
347 isl_obj_bool, (isc_bin_op_fn) &union_map_is_superset },
348 { ISL_TOKEN_GT, isl_obj_union_set, isl_obj_union_set,
349 isl_obj_bool, (isc_bin_op_fn) &union_set_is_strict_superset },
350 { ISL_TOKEN_GT, isl_obj_union_map, isl_obj_union_map,
351 isl_obj_bool, (isc_bin_op_fn) &union_map_is_strict_superset },
352 { ISL_TOKEN_LEX_LE, isl_obj_union_set, isl_obj_union_set,
353 isl_obj_union_map,
354 (isc_bin_op_fn) &isl_union_set_lex_le_union_set },
355 { ISL_TOKEN_LEX_LT, isl_obj_union_set, isl_obj_union_set,
356 isl_obj_union_map,
357 (isc_bin_op_fn) &isl_union_set_lex_lt_union_set },
358 { ISL_TOKEN_LEX_GE, isl_obj_union_set, isl_obj_union_set,
359 isl_obj_union_map,
360 (isc_bin_op_fn) &isl_union_set_lex_ge_union_set },
361 { ISL_TOKEN_LEX_GT, isl_obj_union_set, isl_obj_union_set,
362 isl_obj_union_map,
363 (isc_bin_op_fn) &isl_union_set_lex_gt_union_set },
364 { ISL_TOKEN_LEX_LE, isl_obj_union_map, isl_obj_union_map,
365 isl_obj_union_map,
366 (isc_bin_op_fn) &isl_union_map_lex_le_union_map },
367 { ISL_TOKEN_LEX_LT, isl_obj_union_map, isl_obj_union_map,
368 isl_obj_union_map,
369 (isc_bin_op_fn) &isl_union_map_lex_lt_union_map },
370 { ISL_TOKEN_LEX_GE, isl_obj_union_map, isl_obj_union_map,
371 isl_obj_union_map,
372 (isc_bin_op_fn) &isl_union_map_lex_ge_union_map },
373 { ISL_TOKEN_LEX_GT, isl_obj_union_map, isl_obj_union_map,
374 isl_obj_union_map,
375 (isc_bin_op_fn) &isl_union_map_lex_gt_union_map },
376 { '.', isl_obj_union_pw_qpolynomial_fold,
377 isl_obj_union_pw_qpolynomial_fold,
378 isl_obj_union_pw_qpolynomial_fold,
379 (isc_bin_op_fn) &isl_union_pw_qpolynomial_fold_fold },
380 { '+', isl_obj_union_pw_qpolynomial, isl_obj_union_pw_qpolynomial,
381 isl_obj_union_pw_qpolynomial,
382 (isc_bin_op_fn) &isl_union_pw_qpolynomial_add },
383 { '+', isl_obj_union_pw_qpolynomial,
384 isl_obj_union_pw_qpolynomial_fold,
385 isl_obj_union_pw_qpolynomial_fold,
386 (isc_bin_op_fn) &union_pw_qpolynomial_add_union_pw_qpolynomial_fold },
387 { '+', isl_obj_union_pw_qpolynomial_fold,
388 isl_obj_union_pw_qpolynomial,
389 isl_obj_union_pw_qpolynomial_fold,
390 (isc_bin_op_fn) &isl_union_pw_qpolynomial_fold_add_union_pw_qpolynomial },
391 { '-', isl_obj_union_pw_qpolynomial, isl_obj_union_pw_qpolynomial,
392 isl_obj_union_pw_qpolynomial,
393 (isc_bin_op_fn) &isl_union_pw_qpolynomial_sub },
394 { '*', isl_obj_union_pw_qpolynomial, isl_obj_union_pw_qpolynomial,
395 isl_obj_union_pw_qpolynomial,
396 (isc_bin_op_fn) &isl_union_pw_qpolynomial_mul },
397 { '*', isl_obj_union_pw_qpolynomial, isl_obj_union_set,
398 isl_obj_union_pw_qpolynomial,
399 (isc_bin_op_fn) &isl_union_pw_qpolynomial_intersect_domain },
400 { '*', isl_obj_union_pw_qpolynomial_fold, isl_obj_union_set,
401 isl_obj_union_pw_qpolynomial_fold,
402 (isc_bin_op_fn) &isl_union_pw_qpolynomial_fold_intersect_domain },
403 { '@', isl_obj_union_pw_qpolynomial, isl_obj_union_set,
404 isl_obj_union_pw_qpolynomial,
405 (isc_bin_op_fn) &isl_union_pw_qpolynomial_at },
406 { '@', isl_obj_union_pw_qpolynomial_fold, isl_obj_union_set,
407 isl_obj_union_pw_qpolynomial,
408 (isc_bin_op_fn) &isl_union_pw_qpolynomial_fold_at },
409 { '%', isl_obj_union_set, isl_obj_union_set,
410 isl_obj_union_set,
411 (isc_bin_op_fn) &isl_union_set_gist },
412 { '%', isl_obj_union_map, isl_obj_union_map,
413 isl_obj_union_map,
414 (isc_bin_op_fn) &isl_union_map_gist },
415 { '%', isl_obj_union_pw_qpolynomial, isl_obj_union_set,
416 isl_obj_union_pw_qpolynomial,
417 (isc_bin_op_fn) &isl_union_pw_qpolynomial_gist },
418 { '%', isl_obj_union_pw_qpolynomial_fold, isl_obj_union_set,
419 isl_obj_union_pw_qpolynomial_fold,
420 (isc_bin_op_fn) &isl_union_pw_qpolynomial_fold_gist },
421 { '+', isl_obj_str, isl_obj_str, isl_obj_str,
422 (isc_bin_op_fn) &isl_str_concat },
426 static __isl_give isl_union_map *map_after_map(__isl_take isl_union_map *umap1,
427 __isl_take isl_union_map *umap2)
429 return isl_union_map_apply_range(umap2, umap1);
432 static __isl_give isl_union_pw_qpolynomial *qpolynomial_after_map(
433 __isl_take isl_union_pw_qpolynomial *upwqp,
434 __isl_take isl_union_map *umap)
436 return isl_union_map_apply_union_pw_qpolynomial(umap, upwqp);
439 static __isl_give struct isl_list *qpolynomial_fold_after_map(
440 __isl_take isl_union_pw_qpolynomial_fold *upwf,
441 __isl_take isl_union_map *umap)
443 return union_map_apply_union_pw_qpolynomial_fold(umap, upwf);
446 struct isc_named_bin_op named_bin_ops[] = {
447 { "after", { -1, isl_obj_union_map, isl_obj_union_map,
448 isl_obj_union_map,
449 (isc_bin_op_fn) &map_after_map } },
450 { "after", { -1, isl_obj_union_pw_qpolynomial,
451 isl_obj_union_map, isl_obj_union_pw_qpolynomial,
452 (isc_bin_op_fn) &qpolynomial_after_map } },
453 { "after", { -1, isl_obj_union_pw_qpolynomial_fold,
454 isl_obj_union_map, isl_obj_list,
455 (isc_bin_op_fn) &qpolynomial_fold_after_map } },
456 { "before", { -1, isl_obj_union_map, isl_obj_union_map,
457 isl_obj_union_map,
458 (isc_bin_op_fn) &isl_union_map_apply_range } },
459 { "before", { -1, isl_obj_union_map,
460 isl_obj_union_pw_qpolynomial, isl_obj_union_pw_qpolynomial,
461 (isc_bin_op_fn) &isl_union_map_apply_union_pw_qpolynomial } },
462 { "before", { -1, isl_obj_union_map,
463 isl_obj_union_pw_qpolynomial_fold, isl_obj_list,
464 (isc_bin_op_fn) &union_map_apply_union_pw_qpolynomial_fold } },
465 { "cross", { -1, isl_obj_union_set, isl_obj_union_set,
466 isl_obj_union_set,
467 (isc_bin_op_fn) &isl_union_set_product } },
468 { "cross", { -1, isl_obj_union_map, isl_obj_union_map,
469 isl_obj_union_map,
470 (isc_bin_op_fn) &isl_union_map_product } },
471 NULL
474 __isl_give isl_set *union_set_sample(__isl_take isl_union_set *uset)
476 return isl_set_from_basic_set(isl_union_set_sample(uset));
479 __isl_give isl_map *union_map_sample(__isl_take isl_union_map *umap)
481 return isl_map_from_basic_map(isl_union_map_sample(umap));
484 static __isl_give struct isl_list *union_pw_qpolynomial_upper_bound(
485 __isl_take isl_union_pw_qpolynomial *upwqp)
487 isl_ctx *ctx;
488 struct isl_list *list;
489 int tight;
491 ctx = isl_union_pw_qpolynomial_get_ctx(upwqp);
492 list = isl_list_alloc(ctx, 2);
493 if (!list)
494 goto error2;
496 list->obj[0].type = isl_obj_union_pw_qpolynomial_fold;
497 list->obj[0].v = isl_union_pw_qpolynomial_bound(upwqp,
498 isl_fold_max, &tight);
499 list->obj[1].type = isl_obj_bool;
500 list->obj[1].v = tight ? &isl_bool_true : &isl_bool_false;
501 if (tight < 0 || !list->obj[0].v)
502 goto error;
504 return list;
505 error2:
506 isl_union_pw_qpolynomial_free(upwqp);
507 error:
508 isl_list_free(list);
509 return NULL;
512 #ifdef HAVE_CLOOG
513 void *map_codegen(void *arg)
515 isl_dim *dim;
516 isl_union_map *umap = (isl_union_map *)arg;
517 isl_ctx *ctx = isl_union_map_get_ctx(umap);
518 CloogState *state;
519 CloogOptions *options;
520 CloogDomain *context;
521 CloogUnionDomain *ud;
522 CloogInput *input;
523 struct clast_stmt *stmt;
525 state = cloog_isl_state_malloc(ctx);
526 options = cloog_options_malloc(state);
527 options->language = LANGUAGE_C;
528 options->strides = 1;
530 ud = cloog_union_domain_from_isl_union_map(isl_union_map_copy(umap));
532 dim = isl_union_map_get_dim(umap);
533 context = cloog_domain_from_isl_set(isl_set_universe(dim));
535 input = cloog_input_alloc(context, ud);
537 stmt = cloog_clast_create_from_input(input, options);
538 clast_pprint(stdout, stmt, 0, options);
539 cloog_clast_free(stmt);
541 error:
542 cloog_options_free(options);
543 cloog_state_free(state);
544 isl_union_map_free(umap);
545 return NULL;
548 void *set_codegen(void *arg)
550 isl_dim *dim;
551 isl_union_set *uset = (isl_union_set *)arg;
552 isl_ctx *ctx = isl_union_set_get_ctx(uset);
553 CloogState *state;
554 CloogOptions *options;
555 CloogDomain *context;
556 CloogUnionDomain *ud;
557 CloogInput *input;
558 struct clast_stmt *stmt;
560 if (isl_union_set_n_set(uset) > 1)
561 isl_die(ctx, isl_error_invalid,
562 "code generation for more than one domain "
563 "requires a schedule", goto error);
565 state = cloog_isl_state_malloc(ctx);
566 options = cloog_options_malloc(state);
567 options->language = LANGUAGE_C;
568 options->strides = 1;
570 ud = cloog_union_domain_from_isl_union_set(isl_union_set_copy(uset));
572 dim = isl_union_set_get_dim(uset);
573 context = cloog_domain_from_isl_set(isl_set_universe(dim));
575 input = cloog_input_alloc(context, ud);
577 stmt = cloog_clast_create_from_input(input, options);
578 clast_pprint(stdout, stmt, 0, options);
579 cloog_clast_free(stmt);
581 cloog_options_free(options);
582 cloog_state_free(state);
583 error:
584 isl_union_set_free(uset);
585 return NULL;
587 #endif
589 static int add_point(__isl_take isl_point *pnt, void *user)
591 isl_union_set **scan = (isl_union_set **) user;
593 *scan = isl_union_set_add_set(*scan, isl_set_from_point(pnt));
595 return 0;
598 static __isl_give isl_union_set *union_set_scan(__isl_take isl_union_set *uset)
600 isl_union_set *scan;
602 scan = isl_union_set_empty(isl_union_set_get_dim(uset));
604 if (isl_union_set_foreach_point(uset, add_point, &scan) < 0) {
605 isl_union_set_free(scan);
606 return uset;
609 isl_union_set_free(uset);
610 return scan;
613 static __isl_give isl_union_map *union_map_scan(__isl_take isl_union_map *umap)
615 return isl_union_set_unwrap(union_set_scan(isl_union_map_wrap(umap)));
618 static __isl_give isl_union_pw_qpolynomial *union_pw_qpolynomial_poly(
619 __isl_take isl_union_pw_qpolynomial *upwqp)
621 return isl_union_pw_qpolynomial_to_polynomial(upwqp, 0);
624 static __isl_give isl_union_pw_qpolynomial *union_pw_qpolynomial_lpoly(
625 __isl_take isl_union_pw_qpolynomial *upwqp)
627 return isl_union_pw_qpolynomial_to_polynomial(upwqp, -1);
630 static __isl_give isl_union_pw_qpolynomial *union_pw_qpolynomial_upoly(
631 __isl_take isl_union_pw_qpolynomial *upwqp)
633 return isl_union_pw_qpolynomial_to_polynomial(upwqp, 1);
636 typedef void *(*isc_un_op_fn)(void *arg);
637 struct isc_un_op {
638 enum isl_token_type op;
639 isl_obj_type arg;
640 isl_obj_type res;
641 isc_un_op_fn fn;
643 struct isc_named_un_op {
644 char *name;
645 struct isc_un_op op;
647 struct isc_named_un_op named_un_ops[] = {
648 {"aff", { -1, isl_obj_union_map, isl_obj_union_map,
649 (isc_un_op_fn) &isl_union_map_affine_hull } },
650 {"aff", { -1, isl_obj_union_set, isl_obj_union_set,
651 (isc_un_op_fn) &isl_union_set_affine_hull } },
652 {"card", { -1, isl_obj_union_set,
653 isl_obj_union_pw_qpolynomial,
654 (isc_un_op_fn) &isl_union_set_card } },
655 {"card", { -1, isl_obj_union_map,
656 isl_obj_union_pw_qpolynomial,
657 (isc_un_op_fn) &isl_union_map_card } },
658 {"coalesce", { -1, isl_obj_union_set, isl_obj_union_set,
659 (isc_un_op_fn) &isl_union_set_coalesce } },
660 {"coalesce", { -1, isl_obj_union_map, isl_obj_union_map,
661 (isc_un_op_fn) &isl_union_map_coalesce } },
662 {"coalesce", { -1, isl_obj_union_pw_qpolynomial,
663 isl_obj_union_pw_qpolynomial,
664 (isc_un_op_fn) &isl_union_pw_qpolynomial_coalesce } },
665 {"coalesce", { -1, isl_obj_union_pw_qpolynomial_fold,
666 isl_obj_union_pw_qpolynomial_fold,
667 (isc_un_op_fn) &isl_union_pw_qpolynomial_fold_coalesce } },
668 #ifdef HAVE_CLOOG
669 {"codegen", { -1, isl_obj_union_set, isl_obj_none,
670 &set_codegen } },
671 {"codegen", { -1, isl_obj_union_map, isl_obj_none,
672 &map_codegen } },
673 #endif
674 {"deltas", { -1, isl_obj_union_map, isl_obj_union_set,
675 (isc_un_op_fn) &isl_union_map_deltas } },
676 {"dom", { -1, isl_obj_union_map, isl_obj_union_set,
677 (isc_un_op_fn) &isl_union_map_domain } },
678 {"dom", { -1, isl_obj_union_pw_qpolynomial, isl_obj_union_set,
679 (isc_un_op_fn) &isl_union_pw_qpolynomial_domain } },
680 {"dom", { -1, isl_obj_union_pw_qpolynomial_fold,
681 isl_obj_union_set,
682 (isc_un_op_fn) &isl_union_pw_qpolynomial_fold_domain } },
683 {"domain", { -1, isl_obj_union_map, isl_obj_union_set,
684 (isc_un_op_fn) &isl_union_map_domain } },
685 {"domain", { -1, isl_obj_union_pw_qpolynomial,
686 isl_obj_union_set,
687 (isc_un_op_fn) &isl_union_pw_qpolynomial_domain } },
688 {"domain", { -1, isl_obj_union_pw_qpolynomial_fold,
689 isl_obj_union_set,
690 (isc_un_op_fn) &isl_union_pw_qpolynomial_fold_domain } },
691 {"domain_map", { -1, isl_obj_union_map, isl_obj_union_map,
692 (isc_un_op_fn) &isl_union_map_domain_map } },
693 {"ran", { -1, isl_obj_union_map, isl_obj_union_set,
694 (isc_un_op_fn) &isl_union_map_range } },
695 {"range", { -1, isl_obj_union_map, isl_obj_union_set,
696 (isc_un_op_fn) &isl_union_map_range } },
697 {"range_map", { -1, isl_obj_union_map, isl_obj_union_map,
698 (isc_un_op_fn) &isl_union_map_range_map } },
699 {"identity", { -1, isl_obj_union_set, isl_obj_union_map,
700 (isc_un_op_fn) &isl_union_set_identity } },
701 {"lexmin", { -1, isl_obj_union_map, isl_obj_union_map,
702 (isc_un_op_fn) &isl_union_map_lexmin } },
703 {"lexmax", { -1, isl_obj_union_map, isl_obj_union_map,
704 (isc_un_op_fn) &isl_union_map_lexmax } },
705 {"lexmin", { -1, isl_obj_union_set, isl_obj_union_set,
706 (isc_un_op_fn) &isl_union_set_lexmin } },
707 {"lexmax", { -1, isl_obj_union_set, isl_obj_union_set,
708 (isc_un_op_fn) &isl_union_set_lexmax } },
709 {"poly", { -1, isl_obj_union_map, isl_obj_union_map,
710 (isc_un_op_fn) &isl_union_map_polyhedral_hull } },
711 {"poly", { -1, isl_obj_union_set, isl_obj_union_set,
712 (isc_un_op_fn) &isl_union_set_polyhedral_hull } },
713 {"poly", { -1, isl_obj_union_pw_qpolynomial,
714 isl_obj_union_pw_qpolynomial,
715 (isc_un_op_fn) &union_pw_qpolynomial_poly } },
716 {"lpoly", { -1, isl_obj_union_pw_qpolynomial,
717 isl_obj_union_pw_qpolynomial,
718 (isc_un_op_fn) &union_pw_qpolynomial_lpoly } },
719 {"upoly", { -1, isl_obj_union_pw_qpolynomial,
720 isl_obj_union_pw_qpolynomial,
721 (isc_un_op_fn) &union_pw_qpolynomial_upoly } },
722 {"sample", { -1, isl_obj_union_set, isl_obj_set,
723 (isc_un_op_fn) &union_set_sample } },
724 {"sample", { -1, isl_obj_union_map, isl_obj_map,
725 (isc_un_op_fn) &union_map_sample } },
726 {"scan", { -1, isl_obj_union_set, isl_obj_union_set,
727 (isc_un_op_fn) &union_set_scan } },
728 {"scan", { -1, isl_obj_union_map, isl_obj_union_map,
729 (isc_un_op_fn) &union_map_scan } },
730 {"sum", { -1, isl_obj_union_pw_qpolynomial,
731 isl_obj_union_pw_qpolynomial,
732 (isc_un_op_fn) &isl_union_pw_qpolynomial_sum } },
733 {"ub", { -1, isl_obj_union_pw_qpolynomial, isl_obj_list,
734 (isc_un_op_fn) &union_pw_qpolynomial_upper_bound } },
735 {"unwrap", { -1, isl_obj_union_set, isl_obj_union_map,
736 (isc_un_op_fn) &isl_union_set_unwrap } },
737 {"wrap", { -1, isl_obj_union_map, isl_obj_union_set,
738 (isc_un_op_fn) &isl_union_map_wrap } },
739 NULL
742 struct isl_named_obj {
743 char *name;
744 struct isl_obj obj;
747 static void free_obj(struct isl_obj obj)
749 obj.type->free(obj.v);
752 static int same_name(const void *entry, const void *val)
754 const struct isl_named_obj *named = (const struct isl_named_obj *)entry;
756 return !strcmp(named->name, val);
759 static int do_assign(struct isl_ctx *ctx, struct isl_hash_table *table,
760 char *name, struct isl_obj obj)
762 struct isl_hash_table_entry *entry;
763 uint32_t name_hash;
764 struct isl_named_obj *named;
766 name_hash = isl_hash_string(isl_hash_init(), name);
767 entry = isl_hash_table_find(ctx, table, name_hash, same_name, name, 1);
768 if (!entry)
769 goto error;
770 if (entry->data) {
771 named = entry->data;
772 free_obj(named->obj);
773 free(name);
774 } else {
775 named = isl_alloc_type(ctx, struct isl_named_obj);
776 if (!named)
777 goto error;
778 named->name = name;
779 entry->data = named;
781 named->obj = obj;
783 return 0;
784 error:
785 free_obj(obj);
786 free(name);
787 return -1;
790 static struct isl_obj stored_obj(struct isl_ctx *ctx,
791 struct isl_hash_table *table, char *name)
793 struct isl_obj obj = { isl_obj_none, NULL };
794 struct isl_hash_table_entry *entry;
795 uint32_t name_hash;
797 name_hash = isl_hash_string(isl_hash_init(), name);
798 entry = isl_hash_table_find(ctx, table, name_hash, same_name, name, 0);
799 if (entry) {
800 struct isl_named_obj *named;
801 named = entry->data;
802 obj = named->obj;
803 } else
804 fprintf(stderr, "unknown identifier '%s'\n", name);
806 free(name);
807 obj.v = obj.type->copy(obj.v);
808 return obj;
811 static int is_subtype(struct isl_obj obj, isl_obj_type super)
813 if (obj.type == super)
814 return 1;
815 if (obj.type == isl_obj_map && super == isl_obj_union_map)
816 return 1;
817 if (obj.type == isl_obj_set && super == isl_obj_union_set)
818 return 1;
819 if (obj.type == isl_obj_pw_qpolynomial &&
820 super == isl_obj_union_pw_qpolynomial)
821 return 1;
822 if (obj.type == isl_obj_pw_qpolynomial_fold &&
823 super == isl_obj_union_pw_qpolynomial_fold)
824 return 1;
825 if (obj.type == isl_obj_union_set && isl_union_set_is_empty(obj.v))
826 return 1;
827 if (obj.type == isl_obj_list) {
828 struct isl_list *list = obj.v;
829 if (list->n == 2 && list->obj[1].type == isl_obj_bool)
830 return is_subtype(list->obj[0], super);
832 if (super == isl_obj_str)
833 return 1;
834 return 0;
837 static struct isl_obj obj_at(struct isl_obj obj, int i)
839 struct isl_list *list = obj.v;
841 obj = list->obj[i];
842 obj.v = obj.type->copy(obj.v);
844 isl_list_free(list);
846 return obj;
849 static struct isl_obj convert(isl_ctx *ctx, struct isl_obj obj,
850 isl_obj_type type)
852 if (obj.type == type)
853 return obj;
854 if (obj.type == isl_obj_map && type == isl_obj_union_map) {
855 obj.type = isl_obj_union_map;
856 obj.v = isl_union_map_from_map(obj.v);
857 return obj;
859 if (obj.type == isl_obj_set && type == isl_obj_union_set) {
860 obj.type = isl_obj_union_set;
861 obj.v = isl_union_set_from_set(obj.v);
862 return obj;
864 if (obj.type == isl_obj_pw_qpolynomial &&
865 type == isl_obj_union_pw_qpolynomial) {
866 obj.type = isl_obj_union_pw_qpolynomial;
867 obj.v = isl_union_pw_qpolynomial_from_pw_qpolynomial(obj.v);
868 return obj;
870 if (obj.type == isl_obj_pw_qpolynomial_fold &&
871 type == isl_obj_union_pw_qpolynomial_fold) {
872 obj.type = isl_obj_union_pw_qpolynomial_fold;
873 obj.v = isl_union_pw_qpolynomial_fold_from_pw_qpolynomial_fold(obj.v);
874 return obj;
876 if (obj.type == isl_obj_union_set && isl_union_set_is_empty(obj.v)) {
877 if (type == isl_obj_union_map) {
878 obj.type = isl_obj_union_map;
879 return obj;
881 if (type == isl_obj_union_pw_qpolynomial) {
882 isl_dim *dim = isl_union_set_get_dim(obj.v);
883 isl_union_set_free(obj.v);
884 obj.v = isl_union_pw_qpolynomial_zero(dim);
885 obj.type = isl_obj_union_pw_qpolynomial;
886 return obj;
888 if (type == isl_obj_union_pw_qpolynomial_fold) {
889 isl_dim *dim = isl_union_set_get_dim(obj.v);
890 isl_union_set_free(obj.v);
891 obj.v = isl_union_pw_qpolynomial_fold_zero(dim,
892 isl_fold_list);
893 obj.type = isl_obj_union_pw_qpolynomial_fold;
894 return obj;
897 if (obj.type == isl_obj_list) {
898 struct isl_list *list = obj.v;
899 if (list->n == 2 && list->obj[1].type == isl_obj_bool)
900 return convert(ctx, obj_at(obj, 0), type);
902 if (type == isl_obj_str) {
903 isl_str *str;
904 isl_printer *p;
905 char *s;
907 p = isl_printer_to_str(ctx);
908 if (!p)
909 goto error;
910 p = obj.type->print(p, obj.v);
911 s = isl_printer_get_str(p);
912 isl_printer_free(p);
914 str = isl_str_from_string(ctx, s);
915 if (!str)
916 goto error;
917 free_obj(obj);
918 obj.v = str;
919 obj.type = isl_obj_str;
920 return obj;
923 error:
924 free_obj(obj);
925 obj.type = isl_obj_none;
926 obj.v = NULL;
927 return obj;
930 static struct isc_bin_op *read_bin_op_if_available(struct isl_stream *s,
931 struct isl_obj lhs)
933 int i;
934 struct isl_token *tok;
936 tok = isl_stream_next_token(s);
937 if (!tok)
938 return NULL;
940 for (i = 0; ; ++i) {
941 if (!bin_ops[i].op)
942 break;
943 if (bin_ops[i].op != tok->type)
944 continue;
945 if (!is_subtype(lhs, bin_ops[i].lhs))
946 continue;
948 isl_token_free(tok);
949 return &bin_ops[i];
952 for (i = 0; ; ++i) {
953 if (!named_bin_ops[i].name)
954 break;
955 if (named_bin_ops[i].op.op != tok->type)
956 continue;
957 if (!is_subtype(lhs, named_bin_ops[i].op.lhs))
958 continue;
960 isl_token_free(tok);
961 return &named_bin_ops[i].op;
964 isl_stream_push_token(s, tok);
966 return NULL;
969 static struct isc_un_op *read_prefix_un_op_if_available(struct isl_stream *s)
971 int i;
972 struct isl_token *tok;
974 tok = isl_stream_next_token(s);
975 if (!tok)
976 return NULL;
978 for (i = 0; ; ++i) {
979 if (!named_un_ops[i].name)
980 break;
981 if (named_un_ops[i].op.op != tok->type)
982 continue;
984 isl_token_free(tok);
985 return &named_un_ops[i].op;
988 isl_stream_push_token(s, tok);
990 return NULL;
993 static struct isc_un_op *find_matching_un_op(struct isc_un_op *like,
994 struct isl_obj arg)
996 int i;
998 for (i = 0; ; ++i) {
999 if (!named_un_ops[i].name)
1000 break;
1001 if (named_un_ops[i].op.op != like->op)
1002 continue;
1003 if (!is_subtype(arg, named_un_ops[i].op.arg))
1004 continue;
1006 return &named_un_ops[i].op;
1009 return NULL;
1012 static int is_assign(struct isl_stream *s)
1014 struct isl_token *tok;
1015 struct isl_token *tok2;
1016 int assign;
1018 tok = isl_stream_next_token(s);
1019 if (!tok)
1020 return 0;
1021 if (tok->type != ISL_TOKEN_IDENT) {
1022 isl_stream_push_token(s, tok);
1023 return 0;
1026 tok2 = isl_stream_next_token(s);
1027 if (!tok2) {
1028 isl_stream_push_token(s, tok);
1029 return 0;
1031 assign = tok2->type == ISL_TOKEN_DEF;
1032 isl_stream_push_token(s, tok2);
1033 isl_stream_push_token(s, tok);
1035 return assign;
1038 static struct isl_obj read_obj(struct isl_stream *s,
1039 struct isl_hash_table *table);
1040 static struct isl_obj read_expr(struct isl_stream *s,
1041 struct isl_hash_table *table);
1043 static struct isl_obj read_un_op_expr(struct isl_stream *s,
1044 struct isl_hash_table *table, struct isc_un_op *op)
1046 struct isl_obj obj = { isl_obj_none, NULL };
1048 obj = read_obj(s, table);
1049 if (!obj.v)
1050 goto error;
1052 op = find_matching_un_op(op, obj);
1054 if (!op)
1055 isl_die(s->ctx, isl_error_invalid,
1056 "no such unary operator defined on given operand",
1057 goto error);
1059 obj = convert(s->ctx, obj, op->arg);
1060 obj.v = op->fn(obj.v);
1061 obj.type = op->res;
1063 return obj;
1064 error:
1065 free_obj(obj);
1066 obj.type = isl_obj_none;
1067 obj.v = NULL;
1068 return obj;
1071 static struct isl_obj transitive_closure(struct isl_ctx *ctx, struct isl_obj obj)
1073 struct isl_list *list;
1074 int exact;
1076 if (obj.type != isl_obj_union_map)
1077 obj = convert(ctx, obj, isl_obj_union_map);
1078 isl_assert(ctx, obj.type == isl_obj_union_map, goto error);
1079 list = isl_list_alloc(ctx, 2);
1080 if (!list)
1081 goto error;
1083 list->obj[0].type = isl_obj_union_map;
1084 list->obj[0].v = isl_union_map_transitive_closure(obj.v, &exact);
1085 list->obj[1].type = isl_obj_bool;
1086 list->obj[1].v = exact ? &isl_bool_true : &isl_bool_false;
1087 obj.v = list;
1088 obj.type = isl_obj_list;
1089 if (exact < 0 || !list->obj[0].v)
1090 goto error;
1092 return obj;
1093 error:
1094 free_obj(obj);
1095 obj.type = isl_obj_none;
1096 obj.v = NULL;
1097 return obj;
1100 static struct isl_obj obj_at_index(struct isl_stream *s, struct isl_obj obj)
1102 struct isl_list *list = obj.v;
1103 struct isl_token *tok;
1104 int i;
1106 tok = isl_stream_next_token(s);
1107 if (!tok || tok->type != ISL_TOKEN_VALUE) {
1108 isl_stream_error(s, tok, "expecting index");
1109 if (tok)
1110 isl_stream_push_token(s, tok);
1111 goto error;
1113 i = isl_int_get_si(tok->u.v);
1114 isl_token_free(tok);
1115 isl_assert(s->ctx, i < list->n, goto error);
1116 if (isl_stream_eat(s, ']'))
1117 goto error;
1119 return obj_at(obj, i);
1120 error:
1121 free_obj(obj);
1122 obj.type = isl_obj_none;
1123 obj.v = NULL;
1124 return obj;
1127 static struct isl_obj apply(struct isl_stream *s, __isl_take isl_union_map *umap,
1128 struct isl_hash_table *table)
1130 struct isl_obj obj;
1132 obj = read_expr(s, table);
1133 isl_assert(s->ctx, is_subtype(obj, isl_obj_union_set) ||
1134 is_subtype(obj, isl_obj_union_map), goto error);
1136 if (obj.type == isl_obj_list) {
1137 struct isl_list *list = obj.v;
1138 if (list->n == 2 && list->obj[1].type == isl_obj_bool)
1139 obj = obj_at(obj, 0);
1141 if (obj.type == isl_obj_set)
1142 obj = convert(s->ctx, obj, isl_obj_union_set);
1143 else if (obj.type == isl_obj_map)
1144 obj = convert(s->ctx, obj, isl_obj_union_map);
1145 if (obj.type == isl_obj_union_set) {
1146 obj.v = isl_union_set_apply(obj.v, umap);
1147 } else
1148 obj.v = isl_union_map_apply_range(obj.v, umap);
1149 if (!obj.v)
1150 goto error2;
1152 if (isl_stream_eat(s, ')'))
1153 goto error2;
1155 return obj;
1156 error:
1157 isl_union_map_free(umap);
1158 error2:
1159 free_obj(obj);
1160 obj.type = isl_obj_none;
1161 obj.v = NULL;
1162 return obj;
1165 static struct isl_obj apply_fun(struct isl_stream *s,
1166 struct isl_obj obj, struct isl_hash_table *table)
1168 struct isl_obj arg;
1170 arg = read_expr(s, table);
1171 isl_assert(s->ctx, is_subtype(arg, isl_obj_union_map), goto error);
1173 if (arg.type == isl_obj_list) {
1174 struct isl_list *list = arg.v;
1175 if (list->n == 2 && list->obj[1].type == isl_obj_bool)
1176 arg = obj_at(arg, 0);
1178 if (arg.type == isl_obj_map)
1179 arg = convert(s->ctx, arg, isl_obj_union_map);
1180 if (obj.type == isl_obj_union_pw_qpolynomial) {
1181 obj.v = isl_union_map_apply_union_pw_qpolynomial(arg.v, obj.v);
1182 } else {
1183 obj.type = isl_obj_list;
1184 obj.v = union_map_apply_union_pw_qpolynomial_fold(arg.v, obj.v);
1186 if (!obj.v)
1187 goto error2;
1189 if (isl_stream_eat(s, ')'))
1190 goto error2;
1192 return obj;
1193 error:
1194 free_obj(arg);
1195 error2:
1196 free_obj(obj);
1197 obj.type = isl_obj_none;
1198 obj.v = NULL;
1199 return obj;
1202 struct add_vertex_data {
1203 struct isl_list *list;
1204 int i;
1207 static int add_vertex(__isl_take isl_vertex *vertex, void *user)
1209 struct add_vertex_data *data = (struct add_vertex_data *)user;
1210 isl_basic_set *expr;
1212 expr = isl_vertex_get_expr(vertex);
1214 data->list->obj[data->i].type = isl_obj_set;
1215 data->list->obj[data->i].v = isl_set_from_basic_set(expr);
1216 data->i++;
1218 isl_vertex_free(vertex);
1220 return 0;
1223 static int set_vertices(__isl_take isl_set *set, void *user)
1225 isl_ctx *ctx;
1226 isl_basic_set *hull;
1227 isl_vertices *vertices = NULL;
1228 struct isl_list *list = NULL;
1229 int r;
1230 struct add_vertex_data *data = (struct add_vertex_data *)user;
1232 set = isl_set_remove_divs(set);
1233 hull = isl_set_convex_hull(set);
1234 vertices = isl_basic_set_compute_vertices(hull);
1235 isl_basic_set_free(hull);
1237 list = data->list;
1239 ctx = isl_vertices_get_ctx(vertices);
1240 data->list = isl_list_alloc(ctx, isl_vertices_get_n_vertices(vertices));
1241 if (!data->list)
1242 goto error;
1244 data->i = 0;
1245 r = isl_vertices_foreach_vertex(vertices, &add_vertex, user);
1247 data->list = isl_list_concat(list, data->list);
1249 isl_vertices_free(vertices);
1251 return r;
1252 error:
1253 data->list = list;
1254 isl_vertices_free(vertices);
1255 return -1;
1258 static struct isl_obj vertices(struct isl_stream *s,
1259 struct isl_hash_table *table)
1261 isl_ctx *ctx;
1262 struct isl_obj obj;
1263 struct isl_list *list = NULL;
1264 isl_union_set *uset;
1265 struct add_vertex_data data = { NULL };
1267 obj = read_expr(s, table);
1268 obj = convert(s->ctx, obj, isl_obj_union_set);
1269 isl_assert(s->ctx, obj.type == isl_obj_union_set, goto error);
1270 uset = obj.v;
1271 obj.v = NULL;
1273 ctx = isl_union_set_get_ctx(uset);
1274 list = isl_list_alloc(ctx, 0);
1275 if (!list)
1276 goto error;
1278 data.list = list;
1280 if (isl_union_set_foreach_set(uset, &set_vertices, &data) < 0)
1281 goto error;
1283 isl_union_set_free(uset);
1285 obj.type = isl_obj_list;
1286 obj.v = data.list;
1288 return obj;
1289 error:
1290 isl_union_set_free(uset);
1291 isl_list_free(data.list);
1292 free_obj(obj);
1293 obj.type = isl_obj_none;
1294 obj.v = NULL;
1295 return obj;
1298 static struct isl_obj type_of(struct isl_stream *s,
1299 struct isl_hash_table *table)
1301 isl_ctx *ctx;
1302 struct isl_obj obj;
1303 const char *type = "unknown";
1305 obj = read_expr(s, table);
1307 if (obj.type == isl_obj_map ||
1308 obj.type == isl_obj_union_map)
1309 type = "map";
1310 if (obj.type == isl_obj_set ||
1311 obj.type == isl_obj_union_set)
1312 type = "set";
1313 if (obj.type == isl_obj_pw_qpolynomial ||
1314 obj.type == isl_obj_union_pw_qpolynomial)
1315 type = "piecewise quasipolynomial";
1316 if (obj.type == isl_obj_pw_qpolynomial_fold ||
1317 obj.type == isl_obj_union_pw_qpolynomial_fold)
1318 type = "piecewise quasipolynomial fold";
1319 if (obj.type == isl_obj_list)
1320 type = "list";
1321 if (obj.type == isl_obj_bool)
1322 type = "boolean";
1323 if (obj.type == isl_obj_str)
1324 type = "string";
1326 free_obj(obj);
1327 obj.type = isl_obj_str;
1328 obj.v = isl_str_from_string(s->ctx, strdup(type));
1330 return obj;
1333 static __isl_give isl_union_map *read_map(struct isl_stream *s,
1334 struct isl_hash_table *table)
1336 struct isl_obj obj;
1338 obj = read_obj(s, table);
1339 obj = convert(s->ctx, obj, isl_obj_union_map);
1340 isl_assert(s->ctx, obj.type == isl_obj_union_map, goto error);
1341 return obj.v;
1342 error:
1343 free_obj(obj);
1344 return NULL;
1347 static struct isl_obj last_any(struct isl_stream *s,
1348 struct isl_hash_table *table, __isl_take isl_union_map *must_source,
1349 __isl_take isl_union_map *may_source)
1351 struct isl_obj obj = { isl_obj_none, NULL };
1352 isl_union_map *sink = NULL;
1353 isl_union_map *schedule = NULL;
1354 isl_union_map *may_dep;
1355 isl_union_map *must_dep;
1357 if (isl_stream_eat(s, iscc_op[ISCC_BEFORE]))
1358 goto error;
1360 sink = read_map(s, table);
1361 if (!sink)
1362 goto error;
1364 if (isl_stream_eat(s, iscc_op[ISCC_UNDER]))
1365 goto error;
1367 schedule = read_map(s, table);
1368 if (!schedule)
1369 goto error;
1371 if (isl_union_map_compute_flow(sink, must_source, may_source,
1372 schedule, &must_dep, &may_dep,
1373 NULL, NULL) < 0)
1374 return obj;
1376 obj.type = isl_obj_union_map;
1377 obj.v = isl_union_map_union(must_dep, may_dep);
1379 return obj;
1380 error:
1381 isl_union_map_free(may_source);
1382 isl_union_map_free(must_source);
1383 isl_union_map_free(sink);
1384 isl_union_map_free(schedule);
1385 free_obj(obj);
1386 obj.type = isl_obj_none;
1387 obj.v = NULL;
1388 return obj;
1391 static struct isl_obj any(struct isl_stream *s, struct isl_hash_table *table)
1393 struct isl_obj obj = { isl_obj_none, NULL };
1394 isl_union_map *must_source = NULL;
1395 isl_union_map *may_source = NULL;
1396 isl_union_map *sink = NULL;
1397 isl_union_map *schedule = NULL;
1398 isl_union_map *may_dep;
1400 may_source = read_map(s, table);
1401 if (!may_source)
1402 goto error;
1404 if (isl_stream_eat_if_available(s, iscc_op[ISCC_LAST])) {
1405 must_source = read_map(s, table);
1406 if (!must_source)
1407 goto error;
1408 return last_any(s, table, must_source, may_source);
1411 if (isl_stream_eat(s, iscc_op[ISCC_BEFORE]))
1412 goto error;
1414 sink = read_map(s, table);
1415 if (!sink)
1416 goto error;
1418 if (isl_stream_eat(s, iscc_op[ISCC_UNDER]))
1419 goto error;
1421 schedule = read_map(s, table);
1422 if (!schedule)
1423 goto error;
1425 must_source = isl_union_map_empty(isl_union_map_get_dim(sink));
1426 if (isl_union_map_compute_flow(sink, must_source, may_source,
1427 schedule, NULL, &may_dep,
1428 NULL, NULL) < 0)
1429 return obj;
1431 obj.type = isl_obj_union_map;
1432 obj.v = may_dep;
1434 return obj;
1435 error:
1436 isl_union_map_free(may_source);
1437 isl_union_map_free(must_source);
1438 isl_union_map_free(sink);
1439 isl_union_map_free(schedule);
1440 free_obj(obj);
1441 obj.type = isl_obj_none;
1442 obj.v = NULL;
1443 return obj;
1446 static struct isl_obj last(struct isl_stream *s, struct isl_hash_table *table)
1448 struct isl_obj obj = { isl_obj_none, NULL };
1449 struct isl_list *list = NULL;
1450 isl_union_map *must_source = NULL;
1451 isl_union_map *may_source = NULL;
1452 isl_union_map *sink = NULL;
1453 isl_union_map *schedule = NULL;
1454 isl_union_map *must_dep;
1455 isl_union_set *must_no_source;
1457 must_source = read_map(s, table);
1458 if (!must_source)
1459 goto error;
1461 if (isl_stream_eat_if_available(s, iscc_op[ISCC_ANY])) {
1462 may_source = read_map(s, table);
1463 if (!may_source)
1464 goto error;
1465 return last_any(s, table, must_source, may_source);
1468 list = isl_list_alloc(s->ctx, 2);
1469 if (!list)
1470 goto error;
1472 if (isl_stream_eat(s, iscc_op[ISCC_BEFORE]))
1473 goto error;
1475 sink = read_map(s, table);
1476 if (!sink)
1477 goto error;
1479 if (isl_stream_eat(s, iscc_op[ISCC_UNDER]))
1480 goto error;
1482 schedule = read_map(s, table);
1483 if (!schedule)
1484 goto error;
1486 may_source = isl_union_map_empty(isl_union_map_get_dim(sink));
1487 if (isl_union_map_compute_flow(sink, must_source, may_source,
1488 schedule, &must_dep, NULL,
1489 &must_no_source, NULL) < 0)
1490 return obj;
1492 list->obj[0].type = isl_obj_union_map;
1493 list->obj[0].v = must_dep;
1494 list->obj[1].type = isl_obj_union_set;
1495 list->obj[1].v = must_no_source;
1497 obj.v = list;
1498 obj.type = isl_obj_list;
1500 return obj;
1501 error:
1502 isl_list_free(list);
1503 isl_union_map_free(may_source);
1504 isl_union_map_free(must_source);
1505 isl_union_map_free(sink);
1506 isl_union_map_free(schedule);
1507 free_obj(obj);
1508 obj.type = isl_obj_none;
1509 obj.v = NULL;
1510 return obj;
1513 static struct isl_obj power(struct isl_stream *s, struct isl_obj obj)
1515 struct isl_token *tok;
1517 if (isl_stream_eat_if_available(s, '+'))
1518 return transitive_closure(s->ctx, obj);
1520 tok = isl_stream_next_token(s);
1521 if (!tok || tok->type != ISL_TOKEN_VALUE || isl_int_cmp_si(tok->u.v, -1)) {
1522 isl_stream_error(s, tok, "expecting -1");
1523 if (tok)
1524 isl_stream_push_token(s, tok);
1525 goto error;
1527 isl_token_free(tok);
1528 isl_assert(s->ctx, is_subtype(obj, isl_obj_union_map), goto error);
1529 if (obj.type != isl_obj_union_map)
1530 obj = convert(s->ctx, obj, isl_obj_union_map);
1532 obj.v = isl_union_map_reverse(obj.v);
1533 if (!obj.v)
1534 goto error;
1536 return obj;
1537 error:
1538 free_obj(obj);
1539 obj.type = isl_obj_none;
1540 obj.v = NULL;
1541 return obj;
1544 static struct isl_obj read_from_file(struct isl_stream *s)
1546 struct isl_obj obj;
1547 struct isl_token *tok;
1548 struct isl_stream *s_file;
1549 FILE *file;
1551 tok = isl_stream_next_token(s);
1552 if (!tok || tok->type != ISL_TOKEN_STRING) {
1553 isl_stream_error(s, tok, "expecting filename");
1554 isl_token_free(tok);
1555 goto error;
1558 file = fopen(tok->u.s, "r");
1559 isl_token_free(tok);
1560 isl_assert(s->ctx, file, goto error);
1562 s_file = isl_stream_new_file(s->ctx, file);
1563 if (!s_file) {
1564 fclose(file);
1565 goto error;
1568 obj = isl_stream_read_obj(s_file);
1570 isl_stream_free(s_file);
1571 fclose(file);
1573 return obj;
1574 error:
1575 obj.type = isl_obj_none;
1576 obj.v = NULL;
1577 return obj;
1580 static struct isl_obj read_string_if_available(struct isl_stream *s)
1582 struct isl_token *tok;
1583 struct isl_obj obj = { isl_obj_none, NULL };
1585 tok = isl_stream_next_token(s);
1586 if (!tok)
1587 return obj;
1588 if (tok->type == ISL_TOKEN_STRING) {
1589 isl_str *str;
1590 str = isl_str_alloc(s->ctx);
1591 if (!str)
1592 goto error;
1593 str->s = strdup(tok->u.s);
1594 isl_token_free(tok);
1595 obj.v = str;
1596 obj.type = isl_obj_str;
1597 } else
1598 isl_stream_push_token(s, tok);
1599 return obj;
1600 error:
1601 isl_token_free(tok);
1602 return obj;
1605 static struct isl_obj read_obj(struct isl_stream *s,
1606 struct isl_hash_table *table)
1608 struct isl_obj obj = { isl_obj_none, NULL };
1609 char *name = NULL;
1610 struct isc_un_op *op = NULL;
1612 obj = read_string_if_available(s);
1613 if (obj.v)
1614 return obj;
1615 if (isl_stream_eat_if_available(s, '(')) {
1616 obj = read_expr(s, table);
1617 if (!obj.v || isl_stream_eat(s, ')'))
1618 goto error;
1619 } else {
1620 op = read_prefix_un_op_if_available(s);
1621 if (op)
1622 return read_un_op_expr(s, table, op);
1624 if (isl_stream_eat_if_available(s, iscc_op[ISCC_READ]))
1625 return read_from_file(s);
1626 if (isl_stream_eat_if_available(s, iscc_op[ISCC_VERTICES]))
1627 return vertices(s, table);
1628 if (isl_stream_eat_if_available(s, iscc_op[ISCC_ANY]))
1629 return any(s, table);
1630 if (isl_stream_eat_if_available(s, iscc_op[ISCC_LAST]))
1631 return last(s, table);
1632 if (isl_stream_eat_if_available(s, iscc_op[ISCC_TYPEOF]))
1633 return type_of(s, table);
1635 name = isl_stream_read_ident_if_available(s);
1636 if (name)
1637 obj = stored_obj(s->ctx, table, name);
1638 else
1639 obj = isl_stream_read_obj(s);
1640 if (!obj.v)
1641 goto error;
1644 if (isl_stream_eat_if_available(s, '^'))
1645 obj = power(s, obj);
1646 else if (obj.type == isl_obj_list && isl_stream_eat_if_available(s, '['))
1647 obj = obj_at_index(s, obj);
1648 else if (is_subtype(obj, isl_obj_union_map) &&
1649 isl_stream_eat_if_available(s, '(')) {
1650 obj = convert(s->ctx, obj, isl_obj_union_map);
1651 obj = apply(s, obj.v, table);
1652 } else if (is_subtype(obj, isl_obj_union_pw_qpolynomial) &&
1653 isl_stream_eat_if_available(s, '(')) {
1654 obj = convert(s->ctx, obj, isl_obj_union_pw_qpolynomial);
1655 obj = apply_fun(s, obj, table);
1656 } else if (is_subtype(obj, isl_obj_union_pw_qpolynomial_fold) &&
1657 isl_stream_eat_if_available(s, '(')) {
1658 obj = convert(s->ctx, obj, isl_obj_union_pw_qpolynomial_fold);
1659 obj = apply_fun(s, obj, table);
1662 return obj;
1663 error:
1664 free_obj(obj);
1665 obj.type = isl_obj_none;
1666 obj.v = NULL;
1667 return obj;
1670 static struct isc_bin_op *find_matching_bin_op(struct isc_bin_op *like,
1671 struct isl_obj lhs, struct isl_obj rhs)
1673 int i;
1675 for (i = 0; ; ++i) {
1676 if (!bin_ops[i].op)
1677 break;
1678 if (bin_ops[i].op != like->op)
1679 continue;
1680 if (!is_subtype(lhs, bin_ops[i].lhs))
1681 continue;
1682 if (!is_subtype(rhs, bin_ops[i].rhs))
1683 continue;
1685 return &bin_ops[i];
1688 for (i = 0; ; ++i) {
1689 if (!named_bin_ops[i].name)
1690 break;
1691 if (named_bin_ops[i].op.op != like->op)
1692 continue;
1693 if (!is_subtype(lhs, named_bin_ops[i].op.lhs))
1694 continue;
1695 if (!is_subtype(rhs, named_bin_ops[i].op.rhs))
1696 continue;
1698 return &named_bin_ops[i].op;
1701 return NULL;
1704 static struct isl_obj read_expr(struct isl_stream *s,
1705 struct isl_hash_table *table)
1707 struct isl_obj obj = { isl_obj_none, NULL };
1708 struct isl_obj right_obj = { isl_obj_none, NULL };
1710 obj = read_obj(s, table);
1711 for (; obj.v;) {
1712 struct isc_bin_op *op = NULL;
1714 op = read_bin_op_if_available(s, obj);
1715 if (!op)
1716 break;
1718 right_obj = read_obj(s, table);
1720 op = find_matching_bin_op(op, obj, right_obj);
1722 if (!op)
1723 isl_die(s->ctx, isl_error_invalid,
1724 "no such binary operator defined on given operands",
1725 goto error);
1727 obj = convert(s->ctx, obj, op->lhs);
1728 right_obj = convert(s->ctx, right_obj, op->rhs);
1729 obj.v = op->fn(obj.v, right_obj.v);
1730 obj.type = op->res;
1733 return obj;
1734 error:
1735 free_obj(right_obj);
1736 free_obj(obj);
1737 obj.type = isl_obj_none;
1738 obj.v = NULL;
1739 return obj;
1742 static __isl_give isl_printer *source_file(struct isl_stream *s,
1743 struct isl_hash_table *table, __isl_take isl_printer *p);
1745 static __isl_give isl_printer *read_line(struct isl_stream *s,
1746 struct isl_hash_table *table, __isl_take isl_printer *p)
1748 struct isl_obj obj = { isl_obj_none, NULL };
1749 char *lhs = NULL;
1750 int assign = 0;
1751 struct isc_bin_op *op = NULL;
1753 if (!p)
1754 return NULL;
1755 if (isl_stream_is_empty(s))
1756 return p;
1758 if (isl_stream_eat_if_available(s, iscc_op[ISCC_SOURCE]))
1759 return source_file(s, table, p);
1761 assign = is_assign(s);
1762 if (assign) {
1763 lhs = isl_stream_read_ident_if_available(s);
1764 if (isl_stream_eat(s, ISL_TOKEN_DEF))
1765 goto error;
1768 obj = read_expr(s, table);
1769 if (obj.type == isl_obj_none || obj.v == NULL)
1770 goto error;
1771 if (isl_stream_eat(s, ';'))
1772 goto error;
1774 if (assign) {
1775 if (do_assign(s->ctx, table, lhs, obj))
1776 return;
1777 } else {
1778 p = obj.type->print(p, obj.v);
1779 p = isl_printer_end_line(p);
1780 free_obj(obj);
1783 return p;
1784 error:
1785 isl_stream_flush_tokens(s);
1786 isl_stream_skip_line(s);
1787 free(lhs);
1788 free_obj(obj);
1789 return p;
1792 int free_cb(void **entry, void *user)
1794 struct isl_named_obj *named = *entry;
1796 free_obj(named->obj);
1797 free(named->name);
1798 free(named);
1800 return 0;
1803 static void register_named_ops(struct isl_stream *s)
1805 int i;
1807 for (i = 0; i < ISCC_N_OP; ++i) {
1808 iscc_op[i] = isl_stream_register_keyword(s, op_name[i]);
1809 assert(iscc_op[i] != ISL_TOKEN_ERROR);
1812 for (i = 0; ; ++i) {
1813 if (!named_un_ops[i].name)
1814 break;
1815 named_un_ops[i].op.op = isl_stream_register_keyword(s,
1816 named_un_ops[i].name);
1817 assert(named_un_ops[i].op.op != ISL_TOKEN_ERROR);
1820 for (i = 0; ; ++i) {
1821 if (!named_bin_ops[i].name)
1822 break;
1823 named_bin_ops[i].op.op = isl_stream_register_keyword(s,
1824 named_bin_ops[i].name);
1825 assert(named_bin_ops[i].op.op != ISL_TOKEN_ERROR);
1829 static __isl_give isl_printer *source_file(struct isl_stream *s,
1830 struct isl_hash_table *table, __isl_take isl_printer *p)
1832 struct isl_token *tok;
1833 struct isl_stream *s_file;
1834 FILE *file;
1836 tok = isl_stream_next_token(s);
1837 if (!tok || tok->type != ISL_TOKEN_STRING) {
1838 isl_stream_error(s, tok, "expecting filename");
1839 isl_token_free(tok);
1840 return p;
1843 file = fopen(tok->u.s, "r");
1844 isl_token_free(tok);
1845 isl_assert(s->ctx, file, return p);
1847 s_file = isl_stream_new_file(s->ctx, file);
1848 if (!s_file) {
1849 fclose(file);
1850 return p;
1853 register_named_ops(s_file);
1855 while (!s_file->eof)
1856 p = read_line(s_file, table, p);
1858 isl_stream_free(s_file);
1859 fclose(file);
1861 isl_stream_eat(s, ';');
1863 return p;
1866 int main(int argc, char **argv)
1868 struct isl_ctx *ctx;
1869 struct isl_stream *s;
1870 struct isl_hash_table *table;
1871 struct iscc_options *options;
1872 isl_printer *p;
1874 options = iscc_options_new_with_defaults();
1875 assert(options);
1876 argc = iscc_options_parse(options, argc, argv, ISL_ARG_ALL);
1878 ctx = isl_ctx_alloc_with_options(iscc_options_arg, options);
1879 s = isl_stream_new_file(ctx, stdin);
1880 assert(s);
1881 table = isl_hash_table_alloc(ctx, 10);
1882 assert(table);
1883 p = isl_printer_to_file(ctx, stdout);
1884 p = isl_printer_set_output_format(p, options->format);
1885 assert(p);
1887 register_named_ops(s);
1889 while (p && !s->eof) {
1890 p = read_line(s, table, p);
1893 isl_printer_free(p);
1894 isl_hash_table_foreach(ctx, table, free_cb, NULL);
1895 isl_hash_table_free(ctx, table);
1896 isl_stream_free(s);
1897 isl_ctx_free(ctx);
1899 return 0;