document isl_union_set_apply_union_pw_qpolynomial
[barvinok.git] / iscc.c
blob450b3989fe3d8395ae478d73fb91a79ae6b361d5
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_WRITE, 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_WRITE] = "write",
29 [ISCC_SOURCE] = "source",
30 [ISCC_VERTICES] = "vertices",
31 [ISCC_LAST] = "last",
32 [ISCC_ANY] = "any",
33 [ISCC_BEFORE] = "before",
34 [ISCC_UNDER] = "under",
35 [ISCC_TYPEOF] = "typeof"
37 static enum isl_token_type iscc_op[ISCC_N_OP];
39 struct isl_arg_choice iscc_format[] = {
40 {"isl", ISL_FORMAT_ISL},
41 {"omega", ISL_FORMAT_OMEGA},
42 {"polylib", ISL_FORMAT_POLYLIB},
43 {"ext-polylib", ISL_FORMAT_EXT_POLYLIB},
44 {"latex", ISL_FORMAT_LATEX},
45 {"C", ISL_FORMAT_C},
46 {0}
49 struct iscc_options {
50 struct barvinok_options *barvinok;
51 unsigned format;
52 int io;
55 struct isl_arg iscc_options_arg[] = {
56 ISL_ARG_CHILD(struct iscc_options, barvinok, "barvinok", barvinok_options_arg,
57 "barvinok options")
58 ISL_ARG_CHOICE(struct iscc_options, format, 0, "format", \
59 iscc_format, ISL_FORMAT_ISL, "output format")
60 ISL_ARG_BOOL(struct iscc_options, io, 0, "io", 1,
61 "allow read and write operations")
62 ISL_ARG_END
65 ISL_ARG_DEF(iscc_options, struct iscc_options, iscc_options_arg)
66 ISL_ARG_CTX_DEF(iscc_options, struct iscc_options, iscc_options_arg)
68 static void *isl_obj_bool_copy(void *v)
70 return v;
73 static void isl_obj_bool_free(void *v)
77 static __isl_give isl_printer *isl_obj_bool_print(__isl_take isl_printer *p,
78 void *v)
80 if (v == &isl_bool_true)
81 return isl_printer_print_str(p, "True");
82 else if (v == &isl_bool_false)
83 return isl_printer_print_str(p, "False");
84 else
85 return isl_printer_print_str(p, "Error");
88 static void *isl_obj_bool_add(void *v1, void *v2)
90 return v1;
93 struct isl_obj_vtable isl_obj_bool_vtable = {
94 isl_obj_bool_copy,
95 isl_obj_bool_add,
96 isl_obj_bool_print,
97 isl_obj_bool_free
99 #define isl_obj_bool (&isl_obj_bool_vtable)
101 int *isl_bool_from_int(int res)
103 return res < 0 ? &isl_bool_error : res ? &isl_bool_true : &isl_bool_false;
106 int *union_map_is_equal(__isl_take isl_union_map *map1,
107 __isl_take isl_union_map *map2)
109 int res = isl_union_map_is_equal(map1, map2);
110 isl_union_map_free(map1);
111 isl_union_map_free(map2);
112 return isl_bool_from_int(res);
114 int *union_set_is_equal(__isl_take isl_union_set *set1,
115 __isl_take isl_union_set *set2)
117 return union_map_is_equal((isl_union_map *)set1, (isl_union_map *)set2);
120 int *union_map_is_subset(__isl_take isl_union_map *map1,
121 __isl_take isl_union_map *map2)
123 int res = isl_union_map_is_subset(map1, map2);
124 isl_union_map_free(map1);
125 isl_union_map_free(map2);
126 return isl_bool_from_int(res);
128 int *union_set_is_subset(__isl_take isl_union_set *set1,
129 __isl_take isl_union_set *set2)
131 return union_map_is_subset((isl_union_map *)set1, (isl_union_map *)set2);
134 int *union_map_is_strict_subset(__isl_take isl_union_map *map1,
135 __isl_take isl_union_map *map2)
137 int res = isl_union_map_is_strict_subset(map1, map2);
138 isl_union_map_free(map1);
139 isl_union_map_free(map2);
140 return isl_bool_from_int(res);
142 int *union_set_is_strict_subset(__isl_take isl_union_set *set1,
143 __isl_take isl_union_set *set2)
145 return union_map_is_strict_subset((isl_union_map *)set1,
146 (isl_union_map *)set2);
149 int *union_map_is_superset(__isl_take isl_union_map *map1,
150 __isl_take isl_union_map *map2)
152 return union_map_is_subset(map2, map1);
154 int *union_set_is_superset(__isl_take isl_union_set *set1,
155 __isl_take isl_union_set *set2)
157 return union_set_is_subset(set2, set1);
160 int *union_map_is_strict_superset(__isl_take isl_union_map *map1,
161 __isl_take isl_union_map *map2)
163 return union_map_is_strict_subset(map2, map1);
165 int *union_set_is_strict_superset(__isl_take isl_union_set *set1,
166 __isl_take isl_union_set *set2)
168 return union_set_is_strict_subset(set2, set1);
171 extern struct isl_obj_vtable isl_obj_list_vtable;
172 #define isl_obj_list (&isl_obj_list_vtable)
174 typedef void *(*isc_bin_op_fn)(void *lhs, void *rhs);
175 struct isc_bin_op {
176 enum isl_token_type op;
177 isl_obj_type lhs;
178 isl_obj_type rhs;
179 isl_obj_type res;
180 isc_bin_op_fn fn;
182 struct isc_named_bin_op {
183 char *name;
184 struct isc_bin_op op;
187 struct iscc_at {
188 isl_union_pw_qpolynomial *upwqp;
189 isl_union_pw_qpolynomial *res;
192 static int eval_at(__isl_take isl_point *pnt, void *user)
194 struct iscc_at *at = (struct iscc_at *) user;
195 isl_qpolynomial *qp;
196 isl_set *set;
198 set = isl_set_from_point(isl_point_copy(pnt));
199 qp = isl_union_pw_qpolynomial_eval(
200 isl_union_pw_qpolynomial_copy(at->upwqp), pnt);
202 at->res = isl_union_pw_qpolynomial_add(at->res,
203 isl_union_pw_qpolynomial_from_pw_qpolynomial(
204 isl_pw_qpolynomial_alloc(set, qp)));
206 return 0;
209 __isl_give isl_union_pw_qpolynomial *isl_union_pw_qpolynomial_at(
210 __isl_take isl_union_pw_qpolynomial *upwqp,
211 __isl_take isl_union_set *uset)
213 struct iscc_at at;
215 at.upwqp = upwqp;
216 at.res = isl_union_pw_qpolynomial_zero(isl_union_set_get_dim(uset));
218 isl_union_set_foreach_point(uset, eval_at, &at);
220 isl_union_pw_qpolynomial_free(upwqp);
221 isl_union_set_free(uset);
223 return at.res;
226 struct iscc_fold_at {
227 isl_union_pw_qpolynomial_fold *upwf;
228 isl_union_pw_qpolynomial *res;
231 static int eval_fold_at(__isl_take isl_point *pnt, void *user)
233 struct iscc_fold_at *at = (struct iscc_fold_at *) user;
234 isl_qpolynomial *qp;
235 isl_set *set;
237 set = isl_set_from_point(isl_point_copy(pnt));
238 qp = isl_union_pw_qpolynomial_fold_eval(
239 isl_union_pw_qpolynomial_fold_copy(at->upwf), pnt);
241 at->res = isl_union_pw_qpolynomial_add(at->res,
242 isl_union_pw_qpolynomial_from_pw_qpolynomial(
243 isl_pw_qpolynomial_alloc(set, qp)));
245 return 0;
248 __isl_give isl_union_pw_qpolynomial *isl_union_pw_qpolynomial_fold_at(
249 __isl_take isl_union_pw_qpolynomial_fold *upwf,
250 __isl_take isl_union_set *uset)
252 struct iscc_fold_at at;
254 at.upwf = upwf;
255 at.res = isl_union_pw_qpolynomial_zero(isl_union_set_get_dim(uset));
257 isl_union_set_foreach_point(uset, eval_fold_at, &at);
259 isl_union_pw_qpolynomial_fold_free(upwf);
260 isl_union_set_free(uset);
262 return at.res;
265 static __isl_give isl_union_pw_qpolynomial_fold *union_pw_qpolynomial_add_union_pw_qpolynomial_fold(
266 __isl_take isl_union_pw_qpolynomial *upwqp,
267 __isl_take isl_union_pw_qpolynomial_fold *upwf)
269 return isl_union_pw_qpolynomial_fold_add_union_pw_qpolynomial(upwf,
270 upwqp);
273 static __isl_give struct isl_list *union_map_apply_union_pw_qpolynomial_fold(
274 __isl_take isl_union_map *umap,
275 __isl_take isl_union_pw_qpolynomial_fold *upwf)
277 isl_ctx *ctx;
278 struct isl_list *list;
279 int tight;
281 ctx = isl_union_map_get_ctx(umap);
282 list = isl_list_alloc(ctx, 2);
283 if (!list)
284 goto error2;
286 list->obj[0].type = isl_obj_union_pw_qpolynomial_fold;
287 list->obj[0].v = isl_union_map_apply_union_pw_qpolynomial_fold(umap,
288 upwf, &tight);
289 list->obj[1].type = isl_obj_bool;
290 list->obj[1].v = tight ? &isl_bool_true : &isl_bool_false;
291 if (tight < 0 || !list->obj[0].v)
292 goto error;
294 return list;
295 error2:
296 isl_union_map_free(umap);
297 isl_union_pw_qpolynomial_fold_free(upwf);
298 error:
299 isl_list_free(list);
300 return NULL;
303 struct isc_bin_op bin_ops[] = {
304 { '+', isl_obj_union_set, isl_obj_union_set,
305 isl_obj_union_set,
306 (isc_bin_op_fn) &isl_union_set_union },
307 { '+', isl_obj_union_map, isl_obj_union_map,
308 isl_obj_union_map,
309 (isc_bin_op_fn) &isl_union_map_union },
310 { '-', isl_obj_union_set, isl_obj_union_set,
311 isl_obj_union_set,
312 (isc_bin_op_fn) &isl_union_set_subtract },
313 { '-', isl_obj_union_map, isl_obj_union_map,
314 isl_obj_union_map,
315 (isc_bin_op_fn) &isl_union_map_subtract },
316 { '*', isl_obj_union_set, isl_obj_union_set,
317 isl_obj_union_set,
318 (isc_bin_op_fn) &isl_union_set_intersect },
319 { '*', isl_obj_union_map, isl_obj_union_map,
320 isl_obj_union_map,
321 (isc_bin_op_fn) &isl_union_map_intersect },
322 { '*', isl_obj_union_map, isl_obj_union_set,
323 isl_obj_union_map,
324 (isc_bin_op_fn) &isl_union_map_intersect_domain },
325 { '.', isl_obj_union_map, isl_obj_union_map,
326 isl_obj_union_map,
327 (isc_bin_op_fn) &isl_union_map_apply_range },
328 { '.', isl_obj_union_map, isl_obj_union_pw_qpolynomial,
329 isl_obj_union_pw_qpolynomial,
330 (isc_bin_op_fn) &isl_union_map_apply_union_pw_qpolynomial },
331 { '.', isl_obj_union_map, isl_obj_union_pw_qpolynomial_fold,
332 isl_obj_list,
333 (isc_bin_op_fn) &union_map_apply_union_pw_qpolynomial_fold },
334 { ISL_TOKEN_TO, isl_obj_union_set, isl_obj_union_set,
335 isl_obj_union_map,
336 (isc_bin_op_fn) &isl_union_map_from_domain_and_range },
337 { '=', isl_obj_union_set, isl_obj_union_set, isl_obj_bool,
338 (isc_bin_op_fn) &union_set_is_equal },
339 { '=', isl_obj_union_map, isl_obj_union_map, isl_obj_bool,
340 (isc_bin_op_fn) &union_map_is_equal },
341 { ISL_TOKEN_LE, isl_obj_union_set, isl_obj_union_set,
342 isl_obj_bool, (isc_bin_op_fn) &union_set_is_subset },
343 { ISL_TOKEN_LE, isl_obj_union_map, isl_obj_union_map,
344 isl_obj_bool, (isc_bin_op_fn) &union_map_is_subset },
345 { ISL_TOKEN_LT, isl_obj_union_set, isl_obj_union_set,
346 isl_obj_bool, (isc_bin_op_fn) &union_set_is_strict_subset },
347 { ISL_TOKEN_LT, isl_obj_union_map, isl_obj_union_map,
348 isl_obj_bool, (isc_bin_op_fn) &union_map_is_strict_subset },
349 { ISL_TOKEN_GE, isl_obj_union_set, isl_obj_union_set,
350 isl_obj_bool, (isc_bin_op_fn) &union_set_is_superset },
351 { ISL_TOKEN_GE, isl_obj_union_map, isl_obj_union_map,
352 isl_obj_bool, (isc_bin_op_fn) &union_map_is_superset },
353 { ISL_TOKEN_GT, isl_obj_union_set, isl_obj_union_set,
354 isl_obj_bool, (isc_bin_op_fn) &union_set_is_strict_superset },
355 { ISL_TOKEN_GT, isl_obj_union_map, isl_obj_union_map,
356 isl_obj_bool, (isc_bin_op_fn) &union_map_is_strict_superset },
357 { ISL_TOKEN_LEX_LE, isl_obj_union_set, isl_obj_union_set,
358 isl_obj_union_map,
359 (isc_bin_op_fn) &isl_union_set_lex_le_union_set },
360 { ISL_TOKEN_LEX_LT, isl_obj_union_set, isl_obj_union_set,
361 isl_obj_union_map,
362 (isc_bin_op_fn) &isl_union_set_lex_lt_union_set },
363 { ISL_TOKEN_LEX_GE, isl_obj_union_set, isl_obj_union_set,
364 isl_obj_union_map,
365 (isc_bin_op_fn) &isl_union_set_lex_ge_union_set },
366 { ISL_TOKEN_LEX_GT, isl_obj_union_set, isl_obj_union_set,
367 isl_obj_union_map,
368 (isc_bin_op_fn) &isl_union_set_lex_gt_union_set },
369 { ISL_TOKEN_LEX_LE, isl_obj_union_map, isl_obj_union_map,
370 isl_obj_union_map,
371 (isc_bin_op_fn) &isl_union_map_lex_le_union_map },
372 { ISL_TOKEN_LEX_LT, isl_obj_union_map, isl_obj_union_map,
373 isl_obj_union_map,
374 (isc_bin_op_fn) &isl_union_map_lex_lt_union_map },
375 { ISL_TOKEN_LEX_GE, isl_obj_union_map, isl_obj_union_map,
376 isl_obj_union_map,
377 (isc_bin_op_fn) &isl_union_map_lex_ge_union_map },
378 { ISL_TOKEN_LEX_GT, isl_obj_union_map, isl_obj_union_map,
379 isl_obj_union_map,
380 (isc_bin_op_fn) &isl_union_map_lex_gt_union_map },
381 { '.', isl_obj_union_pw_qpolynomial_fold,
382 isl_obj_union_pw_qpolynomial_fold,
383 isl_obj_union_pw_qpolynomial_fold,
384 (isc_bin_op_fn) &isl_union_pw_qpolynomial_fold_fold },
385 { '+', isl_obj_union_pw_qpolynomial, isl_obj_union_pw_qpolynomial,
386 isl_obj_union_pw_qpolynomial,
387 (isc_bin_op_fn) &isl_union_pw_qpolynomial_add },
388 { '+', isl_obj_union_pw_qpolynomial,
389 isl_obj_union_pw_qpolynomial_fold,
390 isl_obj_union_pw_qpolynomial_fold,
391 (isc_bin_op_fn) &union_pw_qpolynomial_add_union_pw_qpolynomial_fold },
392 { '+', isl_obj_union_pw_qpolynomial_fold,
393 isl_obj_union_pw_qpolynomial,
394 isl_obj_union_pw_qpolynomial_fold,
395 (isc_bin_op_fn) &isl_union_pw_qpolynomial_fold_add_union_pw_qpolynomial },
396 { '-', isl_obj_union_pw_qpolynomial, isl_obj_union_pw_qpolynomial,
397 isl_obj_union_pw_qpolynomial,
398 (isc_bin_op_fn) &isl_union_pw_qpolynomial_sub },
399 { '*', isl_obj_union_pw_qpolynomial, isl_obj_union_pw_qpolynomial,
400 isl_obj_union_pw_qpolynomial,
401 (isc_bin_op_fn) &isl_union_pw_qpolynomial_mul },
402 { '*', isl_obj_union_pw_qpolynomial, isl_obj_union_set,
403 isl_obj_union_pw_qpolynomial,
404 (isc_bin_op_fn) &isl_union_pw_qpolynomial_intersect_domain },
405 { '*', isl_obj_union_pw_qpolynomial_fold, isl_obj_union_set,
406 isl_obj_union_pw_qpolynomial_fold,
407 (isc_bin_op_fn) &isl_union_pw_qpolynomial_fold_intersect_domain },
408 { '@', isl_obj_union_pw_qpolynomial, isl_obj_union_set,
409 isl_obj_union_pw_qpolynomial,
410 (isc_bin_op_fn) &isl_union_pw_qpolynomial_at },
411 { '@', isl_obj_union_pw_qpolynomial_fold, isl_obj_union_set,
412 isl_obj_union_pw_qpolynomial,
413 (isc_bin_op_fn) &isl_union_pw_qpolynomial_fold_at },
414 { '%', isl_obj_union_set, isl_obj_union_set,
415 isl_obj_union_set,
416 (isc_bin_op_fn) &isl_union_set_gist },
417 { '%', isl_obj_union_map, isl_obj_union_map,
418 isl_obj_union_map,
419 (isc_bin_op_fn) &isl_union_map_gist },
420 { '%', isl_obj_union_pw_qpolynomial, isl_obj_union_set,
421 isl_obj_union_pw_qpolynomial,
422 (isc_bin_op_fn) &isl_union_pw_qpolynomial_gist },
423 { '%', isl_obj_union_pw_qpolynomial_fold, isl_obj_union_set,
424 isl_obj_union_pw_qpolynomial_fold,
425 (isc_bin_op_fn) &isl_union_pw_qpolynomial_fold_gist },
426 { '+', isl_obj_str, isl_obj_str, isl_obj_str,
427 (isc_bin_op_fn) &isl_str_concat },
431 static __isl_give isl_union_map *map_after_map(__isl_take isl_union_map *umap1,
432 __isl_take isl_union_map *umap2)
434 return isl_union_map_apply_range(umap2, umap1);
437 static __isl_give isl_union_pw_qpolynomial *qpolynomial_after_map(
438 __isl_take isl_union_pw_qpolynomial *upwqp,
439 __isl_take isl_union_map *umap)
441 return isl_union_map_apply_union_pw_qpolynomial(umap, upwqp);
444 static __isl_give struct isl_list *qpolynomial_fold_after_map(
445 __isl_take isl_union_pw_qpolynomial_fold *upwf,
446 __isl_take isl_union_map *umap)
448 return union_map_apply_union_pw_qpolynomial_fold(umap, upwf);
451 struct isc_named_bin_op named_bin_ops[] = {
452 { "after", { -1, isl_obj_union_map, isl_obj_union_map,
453 isl_obj_union_map,
454 (isc_bin_op_fn) &map_after_map } },
455 { "after", { -1, isl_obj_union_pw_qpolynomial,
456 isl_obj_union_map, isl_obj_union_pw_qpolynomial,
457 (isc_bin_op_fn) &qpolynomial_after_map } },
458 { "after", { -1, isl_obj_union_pw_qpolynomial_fold,
459 isl_obj_union_map, isl_obj_list,
460 (isc_bin_op_fn) &qpolynomial_fold_after_map } },
461 { "before", { -1, isl_obj_union_map, isl_obj_union_map,
462 isl_obj_union_map,
463 (isc_bin_op_fn) &isl_union_map_apply_range } },
464 { "before", { -1, isl_obj_union_map,
465 isl_obj_union_pw_qpolynomial, isl_obj_union_pw_qpolynomial,
466 (isc_bin_op_fn) &isl_union_map_apply_union_pw_qpolynomial } },
467 { "before", { -1, isl_obj_union_map,
468 isl_obj_union_pw_qpolynomial_fold, isl_obj_list,
469 (isc_bin_op_fn) &union_map_apply_union_pw_qpolynomial_fold } },
470 { "cross", { -1, isl_obj_union_set, isl_obj_union_set,
471 isl_obj_union_set,
472 (isc_bin_op_fn) &isl_union_set_product } },
473 { "cross", { -1, isl_obj_union_map, isl_obj_union_map,
474 isl_obj_union_map,
475 (isc_bin_op_fn) &isl_union_map_product } },
476 NULL
479 __isl_give isl_set *union_set_sample(__isl_take isl_union_set *uset)
481 return isl_set_from_basic_set(isl_union_set_sample(uset));
484 __isl_give isl_map *union_map_sample(__isl_take isl_union_map *umap)
486 return isl_map_from_basic_map(isl_union_map_sample(umap));
489 static __isl_give struct isl_list *union_pw_qpolynomial_upper_bound(
490 __isl_take isl_union_pw_qpolynomial *upwqp)
492 isl_ctx *ctx;
493 struct isl_list *list;
494 int tight;
496 ctx = isl_union_pw_qpolynomial_get_ctx(upwqp);
497 list = isl_list_alloc(ctx, 2);
498 if (!list)
499 goto error2;
501 list->obj[0].type = isl_obj_union_pw_qpolynomial_fold;
502 list->obj[0].v = isl_union_pw_qpolynomial_bound(upwqp,
503 isl_fold_max, &tight);
504 list->obj[1].type = isl_obj_bool;
505 list->obj[1].v = tight ? &isl_bool_true : &isl_bool_false;
506 if (tight < 0 || !list->obj[0].v)
507 goto error;
509 return list;
510 error2:
511 isl_union_pw_qpolynomial_free(upwqp);
512 error:
513 isl_list_free(list);
514 return NULL;
517 #ifdef HAVE_CLOOG
518 void *map_codegen(void *arg)
520 isl_dim *dim;
521 isl_union_map *umap = (isl_union_map *)arg;
522 isl_ctx *ctx = isl_union_map_get_ctx(umap);
523 CloogState *state;
524 CloogOptions *options;
525 CloogDomain *context;
526 CloogUnionDomain *ud;
527 CloogInput *input;
528 struct clast_stmt *stmt;
530 state = cloog_isl_state_malloc(ctx);
531 options = cloog_options_malloc(state);
532 options->language = LANGUAGE_C;
533 options->strides = 1;
535 ud = cloog_union_domain_from_isl_union_map(isl_union_map_copy(umap));
537 dim = isl_union_map_get_dim(umap);
538 context = cloog_domain_from_isl_set(isl_set_universe(dim));
540 input = cloog_input_alloc(context, ud);
542 stmt = cloog_clast_create_from_input(input, options);
543 clast_pprint(stdout, stmt, 0, options);
544 cloog_clast_free(stmt);
546 error:
547 cloog_options_free(options);
548 cloog_state_free(state);
549 isl_union_map_free(umap);
550 return NULL;
553 void *set_codegen(void *arg)
555 isl_dim *dim;
556 isl_union_set *uset = (isl_union_set *)arg;
557 isl_ctx *ctx = isl_union_set_get_ctx(uset);
558 CloogState *state;
559 CloogOptions *options;
560 CloogDomain *context;
561 CloogUnionDomain *ud;
562 CloogInput *input;
563 struct clast_stmt *stmt;
565 if (isl_union_set_n_set(uset) > 1)
566 isl_die(ctx, isl_error_invalid,
567 "code generation for more than one domain "
568 "requires a schedule", goto error);
570 state = cloog_isl_state_malloc(ctx);
571 options = cloog_options_malloc(state);
572 options->language = LANGUAGE_C;
573 options->strides = 1;
575 ud = cloog_union_domain_from_isl_union_set(isl_union_set_copy(uset));
577 dim = isl_union_set_get_dim(uset);
578 context = cloog_domain_from_isl_set(isl_set_universe(dim));
580 input = cloog_input_alloc(context, ud);
582 stmt = cloog_clast_create_from_input(input, options);
583 clast_pprint(stdout, stmt, 0, options);
584 cloog_clast_free(stmt);
586 cloog_options_free(options);
587 cloog_state_free(state);
588 error:
589 isl_union_set_free(uset);
590 return NULL;
592 #endif
594 static int add_point(__isl_take isl_point *pnt, void *user)
596 isl_union_set **scan = (isl_union_set **) user;
598 *scan = isl_union_set_add_set(*scan, isl_set_from_point(pnt));
600 return 0;
603 static __isl_give isl_union_set *union_set_scan(__isl_take isl_union_set *uset)
605 isl_union_set *scan;
607 scan = isl_union_set_empty(isl_union_set_get_dim(uset));
609 if (isl_union_set_foreach_point(uset, add_point, &scan) < 0) {
610 isl_union_set_free(scan);
611 return uset;
614 isl_union_set_free(uset);
615 return scan;
618 static __isl_give isl_union_map *union_map_scan(__isl_take isl_union_map *umap)
620 return isl_union_set_unwrap(union_set_scan(isl_union_map_wrap(umap)));
623 static __isl_give isl_union_pw_qpolynomial *union_pw_qpolynomial_poly(
624 __isl_take isl_union_pw_qpolynomial *upwqp)
626 return isl_union_pw_qpolynomial_to_polynomial(upwqp, 0);
629 static __isl_give isl_union_pw_qpolynomial *union_pw_qpolynomial_lpoly(
630 __isl_take isl_union_pw_qpolynomial *upwqp)
632 return isl_union_pw_qpolynomial_to_polynomial(upwqp, -1);
635 static __isl_give isl_union_pw_qpolynomial *union_pw_qpolynomial_upoly(
636 __isl_take isl_union_pw_qpolynomial *upwqp)
638 return isl_union_pw_qpolynomial_to_polynomial(upwqp, 1);
641 typedef void *(*isc_un_op_fn)(void *arg);
642 struct isc_un_op {
643 enum isl_token_type op;
644 isl_obj_type arg;
645 isl_obj_type res;
646 isc_un_op_fn fn;
648 struct isc_named_un_op {
649 char *name;
650 struct isc_un_op op;
652 struct isc_named_un_op named_un_ops[] = {
653 {"aff", { -1, isl_obj_union_map, isl_obj_union_map,
654 (isc_un_op_fn) &isl_union_map_affine_hull } },
655 {"aff", { -1, isl_obj_union_set, isl_obj_union_set,
656 (isc_un_op_fn) &isl_union_set_affine_hull } },
657 {"card", { -1, isl_obj_union_set,
658 isl_obj_union_pw_qpolynomial,
659 (isc_un_op_fn) &isl_union_set_card } },
660 {"card", { -1, isl_obj_union_map,
661 isl_obj_union_pw_qpolynomial,
662 (isc_un_op_fn) &isl_union_map_card } },
663 {"coalesce", { -1, isl_obj_union_set, isl_obj_union_set,
664 (isc_un_op_fn) &isl_union_set_coalesce } },
665 {"coalesce", { -1, isl_obj_union_map, isl_obj_union_map,
666 (isc_un_op_fn) &isl_union_map_coalesce } },
667 {"coalesce", { -1, isl_obj_union_pw_qpolynomial,
668 isl_obj_union_pw_qpolynomial,
669 (isc_un_op_fn) &isl_union_pw_qpolynomial_coalesce } },
670 {"coalesce", { -1, isl_obj_union_pw_qpolynomial_fold,
671 isl_obj_union_pw_qpolynomial_fold,
672 (isc_un_op_fn) &isl_union_pw_qpolynomial_fold_coalesce } },
673 #ifdef HAVE_CLOOG
674 {"codegen", { -1, isl_obj_union_set, isl_obj_none,
675 &set_codegen } },
676 {"codegen", { -1, isl_obj_union_map, isl_obj_none,
677 &map_codegen } },
678 #endif
679 {"deltas", { -1, isl_obj_union_map, isl_obj_union_set,
680 (isc_un_op_fn) &isl_union_map_deltas } },
681 {"dom", { -1, isl_obj_union_map, isl_obj_union_set,
682 (isc_un_op_fn) &isl_union_map_domain } },
683 {"dom", { -1, isl_obj_union_pw_qpolynomial, isl_obj_union_set,
684 (isc_un_op_fn) &isl_union_pw_qpolynomial_domain } },
685 {"dom", { -1, isl_obj_union_pw_qpolynomial_fold,
686 isl_obj_union_set,
687 (isc_un_op_fn) &isl_union_pw_qpolynomial_fold_domain } },
688 {"domain", { -1, isl_obj_union_map, isl_obj_union_set,
689 (isc_un_op_fn) &isl_union_map_domain } },
690 {"domain", { -1, isl_obj_union_pw_qpolynomial,
691 isl_obj_union_set,
692 (isc_un_op_fn) &isl_union_pw_qpolynomial_domain } },
693 {"domain", { -1, isl_obj_union_pw_qpolynomial_fold,
694 isl_obj_union_set,
695 (isc_un_op_fn) &isl_union_pw_qpolynomial_fold_domain } },
696 {"domain_map", { -1, isl_obj_union_map, isl_obj_union_map,
697 (isc_un_op_fn) &isl_union_map_domain_map } },
698 {"ran", { -1, isl_obj_union_map, isl_obj_union_set,
699 (isc_un_op_fn) &isl_union_map_range } },
700 {"range", { -1, isl_obj_union_map, isl_obj_union_set,
701 (isc_un_op_fn) &isl_union_map_range } },
702 {"range_map", { -1, isl_obj_union_map, isl_obj_union_map,
703 (isc_un_op_fn) &isl_union_map_range_map } },
704 {"identity", { -1, isl_obj_union_set, isl_obj_union_map,
705 (isc_un_op_fn) &isl_union_set_identity } },
706 {"lexmin", { -1, isl_obj_union_map, isl_obj_union_map,
707 (isc_un_op_fn) &isl_union_map_lexmin } },
708 {"lexmax", { -1, isl_obj_union_map, isl_obj_union_map,
709 (isc_un_op_fn) &isl_union_map_lexmax } },
710 {"lexmin", { -1, isl_obj_union_set, isl_obj_union_set,
711 (isc_un_op_fn) &isl_union_set_lexmin } },
712 {"lexmax", { -1, isl_obj_union_set, isl_obj_union_set,
713 (isc_un_op_fn) &isl_union_set_lexmax } },
714 {"poly", { -1, isl_obj_union_map, isl_obj_union_map,
715 (isc_un_op_fn) &isl_union_map_polyhedral_hull } },
716 {"poly", { -1, isl_obj_union_set, isl_obj_union_set,
717 (isc_un_op_fn) &isl_union_set_polyhedral_hull } },
718 {"poly", { -1, isl_obj_union_pw_qpolynomial,
719 isl_obj_union_pw_qpolynomial,
720 (isc_un_op_fn) &union_pw_qpolynomial_poly } },
721 {"lpoly", { -1, isl_obj_union_pw_qpolynomial,
722 isl_obj_union_pw_qpolynomial,
723 (isc_un_op_fn) &union_pw_qpolynomial_lpoly } },
724 {"upoly", { -1, isl_obj_union_pw_qpolynomial,
725 isl_obj_union_pw_qpolynomial,
726 (isc_un_op_fn) &union_pw_qpolynomial_upoly } },
727 {"sample", { -1, isl_obj_union_set, isl_obj_set,
728 (isc_un_op_fn) &union_set_sample } },
729 {"sample", { -1, isl_obj_union_map, isl_obj_map,
730 (isc_un_op_fn) &union_map_sample } },
731 {"scan", { -1, isl_obj_union_set, isl_obj_union_set,
732 (isc_un_op_fn) &union_set_scan } },
733 {"scan", { -1, isl_obj_union_map, isl_obj_union_map,
734 (isc_un_op_fn) &union_map_scan } },
735 {"sum", { -1, isl_obj_union_pw_qpolynomial,
736 isl_obj_union_pw_qpolynomial,
737 (isc_un_op_fn) &isl_union_pw_qpolynomial_sum } },
738 {"ub", { -1, isl_obj_union_pw_qpolynomial, isl_obj_list,
739 (isc_un_op_fn) &union_pw_qpolynomial_upper_bound } },
740 {"unwrap", { -1, isl_obj_union_set, isl_obj_union_map,
741 (isc_un_op_fn) &isl_union_set_unwrap } },
742 {"wrap", { -1, isl_obj_union_map, isl_obj_union_set,
743 (isc_un_op_fn) &isl_union_map_wrap } },
744 NULL
747 struct isl_named_obj {
748 char *name;
749 struct isl_obj obj;
752 static void free_obj(struct isl_obj obj)
754 obj.type->free(obj.v);
757 static int same_name(const void *entry, const void *val)
759 const struct isl_named_obj *named = (const struct isl_named_obj *)entry;
761 return !strcmp(named->name, val);
764 static int do_assign(struct isl_ctx *ctx, struct isl_hash_table *table,
765 char *name, struct isl_obj obj)
767 struct isl_hash_table_entry *entry;
768 uint32_t name_hash;
769 struct isl_named_obj *named;
771 name_hash = isl_hash_string(isl_hash_init(), name);
772 entry = isl_hash_table_find(ctx, table, name_hash, same_name, name, 1);
773 if (!entry)
774 goto error;
775 if (entry->data) {
776 named = entry->data;
777 free_obj(named->obj);
778 free(name);
779 } else {
780 named = isl_alloc_type(ctx, struct isl_named_obj);
781 if (!named)
782 goto error;
783 named->name = name;
784 entry->data = named;
786 named->obj = obj;
788 return 0;
789 error:
790 free_obj(obj);
791 free(name);
792 return -1;
795 static struct isl_obj stored_obj(struct isl_ctx *ctx,
796 struct isl_hash_table *table, char *name)
798 struct isl_obj obj = { isl_obj_none, NULL };
799 struct isl_hash_table_entry *entry;
800 uint32_t name_hash;
802 name_hash = isl_hash_string(isl_hash_init(), name);
803 entry = isl_hash_table_find(ctx, table, name_hash, same_name, name, 0);
804 if (entry) {
805 struct isl_named_obj *named;
806 named = entry->data;
807 obj = named->obj;
808 } else
809 fprintf(stderr, "unknown identifier '%s'\n", name);
811 free(name);
812 obj.v = obj.type->copy(obj.v);
813 return obj;
816 static int is_subtype(struct isl_obj obj, isl_obj_type super)
818 if (obj.type == super)
819 return 1;
820 if (obj.type == isl_obj_map && super == isl_obj_union_map)
821 return 1;
822 if (obj.type == isl_obj_set && super == isl_obj_union_set)
823 return 1;
824 if (obj.type == isl_obj_pw_qpolynomial &&
825 super == isl_obj_union_pw_qpolynomial)
826 return 1;
827 if (obj.type == isl_obj_pw_qpolynomial_fold &&
828 super == isl_obj_union_pw_qpolynomial_fold)
829 return 1;
830 if (obj.type == isl_obj_union_set && isl_union_set_is_empty(obj.v))
831 return 1;
832 if (obj.type == isl_obj_list) {
833 struct isl_list *list = obj.v;
834 if (list->n == 2 && list->obj[1].type == isl_obj_bool)
835 return is_subtype(list->obj[0], super);
837 if (super == isl_obj_str)
838 return 1;
839 return 0;
842 static struct isl_obj obj_at(struct isl_obj obj, int i)
844 struct isl_list *list = obj.v;
846 obj = list->obj[i];
847 obj.v = obj.type->copy(obj.v);
849 isl_list_free(list);
851 return obj;
854 static struct isl_obj convert(isl_ctx *ctx, struct isl_obj obj,
855 isl_obj_type type)
857 if (obj.type == type)
858 return obj;
859 if (obj.type == isl_obj_map && type == isl_obj_union_map) {
860 obj.type = isl_obj_union_map;
861 obj.v = isl_union_map_from_map(obj.v);
862 return obj;
864 if (obj.type == isl_obj_set && type == isl_obj_union_set) {
865 obj.type = isl_obj_union_set;
866 obj.v = isl_union_set_from_set(obj.v);
867 return obj;
869 if (obj.type == isl_obj_pw_qpolynomial &&
870 type == isl_obj_union_pw_qpolynomial) {
871 obj.type = isl_obj_union_pw_qpolynomial;
872 obj.v = isl_union_pw_qpolynomial_from_pw_qpolynomial(obj.v);
873 return obj;
875 if (obj.type == isl_obj_pw_qpolynomial_fold &&
876 type == isl_obj_union_pw_qpolynomial_fold) {
877 obj.type = isl_obj_union_pw_qpolynomial_fold;
878 obj.v = isl_union_pw_qpolynomial_fold_from_pw_qpolynomial_fold(obj.v);
879 return obj;
881 if (obj.type == isl_obj_union_set && isl_union_set_is_empty(obj.v)) {
882 if (type == isl_obj_union_map) {
883 obj.type = isl_obj_union_map;
884 return obj;
886 if (type == isl_obj_union_pw_qpolynomial) {
887 isl_dim *dim = isl_union_set_get_dim(obj.v);
888 isl_union_set_free(obj.v);
889 obj.v = isl_union_pw_qpolynomial_zero(dim);
890 obj.type = isl_obj_union_pw_qpolynomial;
891 return obj;
893 if (type == isl_obj_union_pw_qpolynomial_fold) {
894 isl_dim *dim = isl_union_set_get_dim(obj.v);
895 isl_union_set_free(obj.v);
896 obj.v = isl_union_pw_qpolynomial_fold_zero(dim,
897 isl_fold_list);
898 obj.type = isl_obj_union_pw_qpolynomial_fold;
899 return obj;
902 if (obj.type == isl_obj_list) {
903 struct isl_list *list = obj.v;
904 if (list->n == 2 && list->obj[1].type == isl_obj_bool)
905 return convert(ctx, obj_at(obj, 0), type);
907 if (type == isl_obj_str) {
908 isl_str *str;
909 isl_printer *p;
910 char *s;
912 p = isl_printer_to_str(ctx);
913 if (!p)
914 goto error;
915 p = obj.type->print(p, obj.v);
916 s = isl_printer_get_str(p);
917 isl_printer_free(p);
919 str = isl_str_from_string(ctx, s);
920 if (!str)
921 goto error;
922 free_obj(obj);
923 obj.v = str;
924 obj.type = isl_obj_str;
925 return obj;
928 error:
929 free_obj(obj);
930 obj.type = isl_obj_none;
931 obj.v = NULL;
932 return obj;
935 static struct isc_bin_op *read_bin_op_if_available(struct isl_stream *s,
936 struct isl_obj lhs)
938 int i;
939 struct isl_token *tok;
941 tok = isl_stream_next_token(s);
942 if (!tok)
943 return NULL;
945 for (i = 0; ; ++i) {
946 if (!bin_ops[i].op)
947 break;
948 if (bin_ops[i].op != tok->type)
949 continue;
950 if (!is_subtype(lhs, bin_ops[i].lhs))
951 continue;
953 isl_token_free(tok);
954 return &bin_ops[i];
957 for (i = 0; ; ++i) {
958 if (!named_bin_ops[i].name)
959 break;
960 if (named_bin_ops[i].op.op != tok->type)
961 continue;
962 if (!is_subtype(lhs, named_bin_ops[i].op.lhs))
963 continue;
965 isl_token_free(tok);
966 return &named_bin_ops[i].op;
969 isl_stream_push_token(s, tok);
971 return NULL;
974 static struct isc_un_op *read_prefix_un_op_if_available(struct isl_stream *s)
976 int i;
977 struct isl_token *tok;
979 tok = isl_stream_next_token(s);
980 if (!tok)
981 return NULL;
983 for (i = 0; ; ++i) {
984 if (!named_un_ops[i].name)
985 break;
986 if (named_un_ops[i].op.op != tok->type)
987 continue;
989 isl_token_free(tok);
990 return &named_un_ops[i].op;
993 isl_stream_push_token(s, tok);
995 return NULL;
998 static struct isc_un_op *find_matching_un_op(struct isc_un_op *like,
999 struct isl_obj arg)
1001 int i;
1003 for (i = 0; ; ++i) {
1004 if (!named_un_ops[i].name)
1005 break;
1006 if (named_un_ops[i].op.op != like->op)
1007 continue;
1008 if (!is_subtype(arg, named_un_ops[i].op.arg))
1009 continue;
1011 return &named_un_ops[i].op;
1014 return NULL;
1017 static int is_assign(struct isl_stream *s)
1019 struct isl_token *tok;
1020 struct isl_token *tok2;
1021 int assign;
1023 tok = isl_stream_next_token(s);
1024 if (!tok)
1025 return 0;
1026 if (tok->type != ISL_TOKEN_IDENT) {
1027 isl_stream_push_token(s, tok);
1028 return 0;
1031 tok2 = isl_stream_next_token(s);
1032 if (!tok2) {
1033 isl_stream_push_token(s, tok);
1034 return 0;
1036 assign = tok2->type == ISL_TOKEN_DEF;
1037 isl_stream_push_token(s, tok2);
1038 isl_stream_push_token(s, tok);
1040 return assign;
1043 static struct isl_obj read_obj(struct isl_stream *s,
1044 struct isl_hash_table *table);
1045 static struct isl_obj read_expr(struct isl_stream *s,
1046 struct isl_hash_table *table);
1048 static struct isl_obj read_un_op_expr(struct isl_stream *s,
1049 struct isl_hash_table *table, struct isc_un_op *op)
1051 struct isl_obj obj = { isl_obj_none, NULL };
1053 obj = read_obj(s, table);
1054 if (!obj.v)
1055 goto error;
1057 op = find_matching_un_op(op, obj);
1059 if (!op)
1060 isl_die(s->ctx, isl_error_invalid,
1061 "no such unary operator defined on given operand",
1062 goto error);
1064 obj = convert(s->ctx, obj, op->arg);
1065 obj.v = op->fn(obj.v);
1066 obj.type = op->res;
1068 return obj;
1069 error:
1070 free_obj(obj);
1071 obj.type = isl_obj_none;
1072 obj.v = NULL;
1073 return obj;
1076 static struct isl_obj transitive_closure(struct isl_ctx *ctx, struct isl_obj obj)
1078 struct isl_list *list;
1079 int exact;
1081 if (obj.type != isl_obj_union_map)
1082 obj = convert(ctx, obj, isl_obj_union_map);
1083 isl_assert(ctx, obj.type == isl_obj_union_map, goto error);
1084 list = isl_list_alloc(ctx, 2);
1085 if (!list)
1086 goto error;
1088 list->obj[0].type = isl_obj_union_map;
1089 list->obj[0].v = isl_union_map_transitive_closure(obj.v, &exact);
1090 list->obj[1].type = isl_obj_bool;
1091 list->obj[1].v = exact ? &isl_bool_true : &isl_bool_false;
1092 obj.v = list;
1093 obj.type = isl_obj_list;
1094 if (exact < 0 || !list->obj[0].v)
1095 goto error;
1097 return obj;
1098 error:
1099 free_obj(obj);
1100 obj.type = isl_obj_none;
1101 obj.v = NULL;
1102 return obj;
1105 static struct isl_obj obj_at_index(struct isl_stream *s, struct isl_obj obj)
1107 struct isl_list *list = obj.v;
1108 struct isl_token *tok;
1109 int i;
1111 tok = isl_stream_next_token(s);
1112 if (!tok || tok->type != ISL_TOKEN_VALUE) {
1113 isl_stream_error(s, tok, "expecting index");
1114 if (tok)
1115 isl_stream_push_token(s, tok);
1116 goto error;
1118 i = isl_int_get_si(tok->u.v);
1119 isl_token_free(tok);
1120 isl_assert(s->ctx, i < list->n, goto error);
1121 if (isl_stream_eat(s, ']'))
1122 goto error;
1124 return obj_at(obj, i);
1125 error:
1126 free_obj(obj);
1127 obj.type = isl_obj_none;
1128 obj.v = NULL;
1129 return obj;
1132 static struct isl_obj apply(struct isl_stream *s, __isl_take isl_union_map *umap,
1133 struct isl_hash_table *table)
1135 struct isl_obj obj;
1137 obj = read_expr(s, table);
1138 isl_assert(s->ctx, is_subtype(obj, isl_obj_union_set) ||
1139 is_subtype(obj, isl_obj_union_map), goto error);
1141 if (obj.type == isl_obj_list) {
1142 struct isl_list *list = obj.v;
1143 if (list->n == 2 && list->obj[1].type == isl_obj_bool)
1144 obj = obj_at(obj, 0);
1146 if (obj.type == isl_obj_set)
1147 obj = convert(s->ctx, obj, isl_obj_union_set);
1148 else if (obj.type == isl_obj_map)
1149 obj = convert(s->ctx, obj, isl_obj_union_map);
1150 if (obj.type == isl_obj_union_set) {
1151 obj.v = isl_union_set_apply(obj.v, umap);
1152 } else
1153 obj.v = isl_union_map_apply_range(obj.v, umap);
1154 if (!obj.v)
1155 goto error2;
1157 if (isl_stream_eat(s, ')'))
1158 goto error2;
1160 return obj;
1161 error:
1162 isl_union_map_free(umap);
1163 error2:
1164 free_obj(obj);
1165 obj.type = isl_obj_none;
1166 obj.v = NULL;
1167 return obj;
1170 static struct isl_obj apply_fun(struct isl_stream *s,
1171 struct isl_obj obj, struct isl_hash_table *table)
1173 struct isl_obj arg;
1175 arg = read_expr(s, table);
1176 if (!is_subtype(arg, isl_obj_union_map) &&
1177 !is_subtype(arg, isl_obj_union_set))
1178 isl_die(s->ctx, isl_error_invalid,
1179 "expecting set of map argument", goto error);
1181 if (arg.type == isl_obj_list) {
1182 struct isl_list *list = arg.v;
1183 if (list->n == 2 && list->obj[1].type == isl_obj_bool)
1184 arg = obj_at(arg, 0);
1186 if (arg.type == isl_obj_set)
1187 arg = convert(s->ctx, arg, isl_obj_union_set);
1188 else if (arg.type == isl_obj_map)
1189 arg = convert(s->ctx, arg, isl_obj_union_map);
1190 if (arg.type == isl_obj_union_set) {
1191 arg.v = isl_union_map_from_range(arg.v);
1192 arg.type = isl_obj_union_map;
1194 if (obj.type == isl_obj_union_pw_qpolynomial) {
1195 obj.v = isl_union_map_apply_union_pw_qpolynomial(arg.v, obj.v);
1196 } else {
1197 obj.type = isl_obj_list;
1198 obj.v = union_map_apply_union_pw_qpolynomial_fold(arg.v, obj.v);
1200 if (!obj.v)
1201 goto error2;
1203 if (isl_stream_eat(s, ')'))
1204 goto error2;
1206 return obj;
1207 error:
1208 free_obj(arg);
1209 error2:
1210 free_obj(obj);
1211 obj.type = isl_obj_none;
1212 obj.v = NULL;
1213 return obj;
1216 struct add_vertex_data {
1217 struct isl_list *list;
1218 int i;
1221 static int add_vertex(__isl_take isl_vertex *vertex, void *user)
1223 struct add_vertex_data *data = (struct add_vertex_data *)user;
1224 isl_basic_set *expr;
1226 expr = isl_vertex_get_expr(vertex);
1228 data->list->obj[data->i].type = isl_obj_set;
1229 data->list->obj[data->i].v = isl_set_from_basic_set(expr);
1230 data->i++;
1232 isl_vertex_free(vertex);
1234 return 0;
1237 static int set_vertices(__isl_take isl_set *set, void *user)
1239 isl_ctx *ctx;
1240 isl_basic_set *hull;
1241 isl_vertices *vertices = NULL;
1242 struct isl_list *list = NULL;
1243 int r;
1244 struct add_vertex_data *data = (struct add_vertex_data *)user;
1246 set = isl_set_remove_divs(set);
1247 hull = isl_set_convex_hull(set);
1248 vertices = isl_basic_set_compute_vertices(hull);
1249 isl_basic_set_free(hull);
1251 list = data->list;
1253 ctx = isl_vertices_get_ctx(vertices);
1254 data->list = isl_list_alloc(ctx, isl_vertices_get_n_vertices(vertices));
1255 if (!data->list)
1256 goto error;
1258 data->i = 0;
1259 r = isl_vertices_foreach_vertex(vertices, &add_vertex, user);
1261 data->list = isl_list_concat(list, data->list);
1263 isl_vertices_free(vertices);
1265 return r;
1266 error:
1267 data->list = list;
1268 isl_vertices_free(vertices);
1269 return -1;
1272 static struct isl_obj vertices(struct isl_stream *s,
1273 struct isl_hash_table *table)
1275 isl_ctx *ctx;
1276 struct isl_obj obj;
1277 struct isl_list *list = NULL;
1278 isl_union_set *uset;
1279 struct add_vertex_data data = { NULL };
1281 obj = read_expr(s, table);
1282 obj = convert(s->ctx, obj, isl_obj_union_set);
1283 isl_assert(s->ctx, obj.type == isl_obj_union_set, goto error);
1284 uset = obj.v;
1285 obj.v = NULL;
1287 ctx = isl_union_set_get_ctx(uset);
1288 list = isl_list_alloc(ctx, 0);
1289 if (!list)
1290 goto error;
1292 data.list = list;
1294 if (isl_union_set_foreach_set(uset, &set_vertices, &data) < 0)
1295 goto error;
1297 isl_union_set_free(uset);
1299 obj.type = isl_obj_list;
1300 obj.v = data.list;
1302 return obj;
1303 error:
1304 isl_union_set_free(uset);
1305 isl_list_free(data.list);
1306 free_obj(obj);
1307 obj.type = isl_obj_none;
1308 obj.v = NULL;
1309 return obj;
1312 static struct isl_obj type_of(struct isl_stream *s,
1313 struct isl_hash_table *table)
1315 isl_ctx *ctx;
1316 struct isl_obj obj;
1317 const char *type = "unknown";
1319 obj = read_expr(s, table);
1321 if (obj.type == isl_obj_map ||
1322 obj.type == isl_obj_union_map)
1323 type = "map";
1324 if (obj.type == isl_obj_set ||
1325 obj.type == isl_obj_union_set)
1326 type = "set";
1327 if (obj.type == isl_obj_pw_qpolynomial ||
1328 obj.type == isl_obj_union_pw_qpolynomial)
1329 type = "piecewise quasipolynomial";
1330 if (obj.type == isl_obj_pw_qpolynomial_fold ||
1331 obj.type == isl_obj_union_pw_qpolynomial_fold)
1332 type = "piecewise quasipolynomial fold";
1333 if (obj.type == isl_obj_list)
1334 type = "list";
1335 if (obj.type == isl_obj_bool)
1336 type = "boolean";
1337 if (obj.type == isl_obj_str)
1338 type = "string";
1340 free_obj(obj);
1341 obj.type = isl_obj_str;
1342 obj.v = isl_str_from_string(s->ctx, strdup(type));
1344 return obj;
1347 static __isl_give isl_union_map *read_map(struct isl_stream *s,
1348 struct isl_hash_table *table)
1350 struct isl_obj obj;
1352 obj = read_obj(s, table);
1353 obj = convert(s->ctx, obj, isl_obj_union_map);
1354 isl_assert(s->ctx, obj.type == isl_obj_union_map, goto error);
1355 return obj.v;
1356 error:
1357 free_obj(obj);
1358 return NULL;
1361 static struct isl_obj last_any(struct isl_stream *s,
1362 struct isl_hash_table *table, __isl_take isl_union_map *must_source,
1363 __isl_take isl_union_map *may_source)
1365 struct isl_obj obj = { isl_obj_none, NULL };
1366 isl_union_map *sink = NULL;
1367 isl_union_map *schedule = NULL;
1368 isl_union_map *may_dep;
1369 isl_union_map *must_dep;
1371 if (isl_stream_eat(s, iscc_op[ISCC_BEFORE]))
1372 goto error;
1374 sink = read_map(s, table);
1375 if (!sink)
1376 goto error;
1378 if (isl_stream_eat(s, iscc_op[ISCC_UNDER]))
1379 goto error;
1381 schedule = read_map(s, table);
1382 if (!schedule)
1383 goto error;
1385 if (isl_union_map_compute_flow(sink, must_source, may_source,
1386 schedule, &must_dep, &may_dep,
1387 NULL, NULL) < 0)
1388 return obj;
1390 obj.type = isl_obj_union_map;
1391 obj.v = isl_union_map_union(must_dep, may_dep);
1393 return obj;
1394 error:
1395 isl_union_map_free(may_source);
1396 isl_union_map_free(must_source);
1397 isl_union_map_free(sink);
1398 isl_union_map_free(schedule);
1399 free_obj(obj);
1400 obj.type = isl_obj_none;
1401 obj.v = NULL;
1402 return obj;
1405 static struct isl_obj any(struct isl_stream *s, struct isl_hash_table *table)
1407 struct isl_obj obj = { isl_obj_none, NULL };
1408 isl_union_map *must_source = NULL;
1409 isl_union_map *may_source = NULL;
1410 isl_union_map *sink = NULL;
1411 isl_union_map *schedule = NULL;
1412 isl_union_map *may_dep;
1414 may_source = read_map(s, table);
1415 if (!may_source)
1416 goto error;
1418 if (isl_stream_eat_if_available(s, iscc_op[ISCC_LAST])) {
1419 must_source = read_map(s, table);
1420 if (!must_source)
1421 goto error;
1422 return last_any(s, table, must_source, may_source);
1425 if (isl_stream_eat(s, iscc_op[ISCC_BEFORE]))
1426 goto error;
1428 sink = read_map(s, table);
1429 if (!sink)
1430 goto error;
1432 if (isl_stream_eat(s, iscc_op[ISCC_UNDER]))
1433 goto error;
1435 schedule = read_map(s, table);
1436 if (!schedule)
1437 goto error;
1439 must_source = isl_union_map_empty(isl_union_map_get_dim(sink));
1440 if (isl_union_map_compute_flow(sink, must_source, may_source,
1441 schedule, NULL, &may_dep,
1442 NULL, NULL) < 0)
1443 return obj;
1445 obj.type = isl_obj_union_map;
1446 obj.v = may_dep;
1448 return obj;
1449 error:
1450 isl_union_map_free(may_source);
1451 isl_union_map_free(must_source);
1452 isl_union_map_free(sink);
1453 isl_union_map_free(schedule);
1454 free_obj(obj);
1455 obj.type = isl_obj_none;
1456 obj.v = NULL;
1457 return obj;
1460 static struct isl_obj last(struct isl_stream *s, struct isl_hash_table *table)
1462 struct isl_obj obj = { isl_obj_none, NULL };
1463 struct isl_list *list = NULL;
1464 isl_union_map *must_source = NULL;
1465 isl_union_map *may_source = NULL;
1466 isl_union_map *sink = NULL;
1467 isl_union_map *schedule = NULL;
1468 isl_union_map *must_dep;
1469 isl_union_set *must_no_source;
1471 must_source = read_map(s, table);
1472 if (!must_source)
1473 goto error;
1475 if (isl_stream_eat_if_available(s, iscc_op[ISCC_ANY])) {
1476 may_source = read_map(s, table);
1477 if (!may_source)
1478 goto error;
1479 return last_any(s, table, must_source, may_source);
1482 list = isl_list_alloc(s->ctx, 2);
1483 if (!list)
1484 goto error;
1486 if (isl_stream_eat(s, iscc_op[ISCC_BEFORE]))
1487 goto error;
1489 sink = read_map(s, table);
1490 if (!sink)
1491 goto error;
1493 if (isl_stream_eat(s, iscc_op[ISCC_UNDER]))
1494 goto error;
1496 schedule = read_map(s, table);
1497 if (!schedule)
1498 goto error;
1500 may_source = isl_union_map_empty(isl_union_map_get_dim(sink));
1501 if (isl_union_map_compute_flow(sink, must_source, may_source,
1502 schedule, &must_dep, NULL,
1503 &must_no_source, NULL) < 0)
1504 return obj;
1506 list->obj[0].type = isl_obj_union_map;
1507 list->obj[0].v = must_dep;
1508 list->obj[1].type = isl_obj_union_set;
1509 list->obj[1].v = must_no_source;
1511 obj.v = list;
1512 obj.type = isl_obj_list;
1514 return obj;
1515 error:
1516 isl_list_free(list);
1517 isl_union_map_free(may_source);
1518 isl_union_map_free(must_source);
1519 isl_union_map_free(sink);
1520 isl_union_map_free(schedule);
1521 free_obj(obj);
1522 obj.type = isl_obj_none;
1523 obj.v = NULL;
1524 return obj;
1527 static struct isl_obj power(struct isl_stream *s, struct isl_obj obj)
1529 struct isl_token *tok;
1531 if (isl_stream_eat_if_available(s, '+'))
1532 return transitive_closure(s->ctx, obj);
1534 tok = isl_stream_next_token(s);
1535 if (!tok || tok->type != ISL_TOKEN_VALUE || isl_int_cmp_si(tok->u.v, -1)) {
1536 isl_stream_error(s, tok, "expecting -1");
1537 if (tok)
1538 isl_stream_push_token(s, tok);
1539 goto error;
1541 isl_token_free(tok);
1542 isl_assert(s->ctx, is_subtype(obj, isl_obj_union_map), goto error);
1543 if (obj.type != isl_obj_union_map)
1544 obj = convert(s->ctx, obj, isl_obj_union_map);
1546 obj.v = isl_union_map_reverse(obj.v);
1547 if (!obj.v)
1548 goto error;
1550 return obj;
1551 error:
1552 free_obj(obj);
1553 obj.type = isl_obj_none;
1554 obj.v = NULL;
1555 return obj;
1558 static struct isl_obj read_from_file(struct isl_stream *s)
1560 struct isl_obj obj;
1561 struct isl_token *tok;
1562 struct isl_stream *s_file;
1563 struct iscc_options *options;
1564 FILE *file;
1566 tok = isl_stream_next_token(s);
1567 if (!tok || tok->type != ISL_TOKEN_STRING) {
1568 isl_stream_error(s, tok, "expecting filename");
1569 isl_token_free(tok);
1570 goto error;
1573 options = isl_ctx_peek_iscc_options(s->ctx);
1574 if (!options || !options->io) {
1575 isl_token_free(tok);
1576 isl_die(s->ctx, isl_error_invalid,
1577 "read operation not allowed", goto error);
1580 file = fopen(tok->u.s, "r");
1581 isl_token_free(tok);
1582 isl_assert(s->ctx, file, goto error);
1584 s_file = isl_stream_new_file(s->ctx, file);
1585 if (!s_file) {
1586 fclose(file);
1587 goto error;
1590 obj = isl_stream_read_obj(s_file);
1592 isl_stream_free(s_file);
1593 fclose(file);
1595 return obj;
1596 error:
1597 obj.type = isl_obj_none;
1598 obj.v = NULL;
1599 return obj;
1602 static struct isl_obj write_to_file(struct isl_stream *s,
1603 struct isl_hash_table *table)
1605 struct isl_obj obj;
1606 struct isl_token *tok;
1607 struct isl_stream *s_file;
1608 struct iscc_options *options;
1609 FILE *file;
1610 isl_printer *p;
1612 tok = isl_stream_next_token(s);
1613 if (!tok || tok->type != ISL_TOKEN_STRING) {
1614 isl_stream_error(s, tok, "expecting filename");
1615 isl_token_free(tok);
1616 goto error;
1619 obj = read_expr(s, table);
1621 options = isl_ctx_peek_iscc_options(s->ctx);
1622 if (!options || !options->io) {
1623 isl_token_free(tok);
1624 isl_die(s->ctx, isl_error_invalid,
1625 "write operation not allowed", goto error);
1628 file = fopen(tok->u.s, "w");
1629 isl_token_free(tok);
1630 if (!file)
1631 isl_die(s->ctx, isl_error_unknown,
1632 "could not open file for writing", goto error);
1634 p = isl_printer_to_file(s->ctx, file);
1635 p = isl_printer_set_output_format(p, options->format);
1636 p = obj.type->print(p, obj.v);
1637 p = isl_printer_end_line(p);
1638 isl_printer_free(p);
1640 fclose(file);
1641 error:
1642 free_obj(obj);
1643 obj.type = isl_obj_none;
1644 obj.v = NULL;
1645 return obj;
1648 static struct isl_obj read_string_if_available(struct isl_stream *s)
1650 struct isl_token *tok;
1651 struct isl_obj obj = { isl_obj_none, NULL };
1653 tok = isl_stream_next_token(s);
1654 if (!tok)
1655 return obj;
1656 if (tok->type == ISL_TOKEN_STRING) {
1657 isl_str *str;
1658 str = isl_str_alloc(s->ctx);
1659 if (!str)
1660 goto error;
1661 str->s = strdup(tok->u.s);
1662 isl_token_free(tok);
1663 obj.v = str;
1664 obj.type = isl_obj_str;
1665 } else
1666 isl_stream_push_token(s, tok);
1667 return obj;
1668 error:
1669 isl_token_free(tok);
1670 return obj;
1673 static struct isl_obj read_obj(struct isl_stream *s,
1674 struct isl_hash_table *table)
1676 struct isl_obj obj = { isl_obj_none, NULL };
1677 char *name = NULL;
1678 struct isc_un_op *op = NULL;
1680 obj = read_string_if_available(s);
1681 if (obj.v)
1682 return obj;
1683 if (isl_stream_eat_if_available(s, '(')) {
1684 obj = read_expr(s, table);
1685 if (!obj.v || isl_stream_eat(s, ')'))
1686 goto error;
1687 } else {
1688 op = read_prefix_un_op_if_available(s);
1689 if (op)
1690 return read_un_op_expr(s, table, op);
1692 if (isl_stream_eat_if_available(s, iscc_op[ISCC_READ]))
1693 return read_from_file(s);
1694 if (isl_stream_eat_if_available(s, iscc_op[ISCC_WRITE]))
1695 return write_to_file(s, table);
1696 if (isl_stream_eat_if_available(s, iscc_op[ISCC_VERTICES]))
1697 return vertices(s, table);
1698 if (isl_stream_eat_if_available(s, iscc_op[ISCC_ANY]))
1699 return any(s, table);
1700 if (isl_stream_eat_if_available(s, iscc_op[ISCC_LAST]))
1701 return last(s, table);
1702 if (isl_stream_eat_if_available(s, iscc_op[ISCC_TYPEOF]))
1703 return type_of(s, table);
1705 name = isl_stream_read_ident_if_available(s);
1706 if (name)
1707 obj = stored_obj(s->ctx, table, name);
1708 else
1709 obj = isl_stream_read_obj(s);
1710 if (!obj.v)
1711 goto error;
1714 if (isl_stream_eat_if_available(s, '^'))
1715 obj = power(s, obj);
1716 else if (obj.type == isl_obj_list && isl_stream_eat_if_available(s, '['))
1717 obj = obj_at_index(s, obj);
1718 else if (is_subtype(obj, isl_obj_union_map) &&
1719 isl_stream_eat_if_available(s, '(')) {
1720 obj = convert(s->ctx, obj, isl_obj_union_map);
1721 obj = apply(s, obj.v, table);
1722 } else if (is_subtype(obj, isl_obj_union_pw_qpolynomial) &&
1723 isl_stream_eat_if_available(s, '(')) {
1724 obj = convert(s->ctx, obj, isl_obj_union_pw_qpolynomial);
1725 obj = apply_fun(s, obj, table);
1726 } else if (is_subtype(obj, isl_obj_union_pw_qpolynomial_fold) &&
1727 isl_stream_eat_if_available(s, '(')) {
1728 obj = convert(s->ctx, obj, isl_obj_union_pw_qpolynomial_fold);
1729 obj = apply_fun(s, obj, table);
1732 return obj;
1733 error:
1734 free_obj(obj);
1735 obj.type = isl_obj_none;
1736 obj.v = NULL;
1737 return obj;
1740 static struct isc_bin_op *find_matching_bin_op(struct isc_bin_op *like,
1741 struct isl_obj lhs, struct isl_obj rhs)
1743 int i;
1745 for (i = 0; ; ++i) {
1746 if (!bin_ops[i].op)
1747 break;
1748 if (bin_ops[i].op != like->op)
1749 continue;
1750 if (!is_subtype(lhs, bin_ops[i].lhs))
1751 continue;
1752 if (!is_subtype(rhs, bin_ops[i].rhs))
1753 continue;
1755 return &bin_ops[i];
1758 for (i = 0; ; ++i) {
1759 if (!named_bin_ops[i].name)
1760 break;
1761 if (named_bin_ops[i].op.op != like->op)
1762 continue;
1763 if (!is_subtype(lhs, named_bin_ops[i].op.lhs))
1764 continue;
1765 if (!is_subtype(rhs, named_bin_ops[i].op.rhs))
1766 continue;
1768 return &named_bin_ops[i].op;
1771 return NULL;
1774 static struct isl_obj read_expr(struct isl_stream *s,
1775 struct isl_hash_table *table)
1777 struct isl_obj obj = { isl_obj_none, NULL };
1778 struct isl_obj right_obj = { isl_obj_none, NULL };
1780 obj = read_obj(s, table);
1781 for (; obj.v;) {
1782 struct isc_bin_op *op = NULL;
1784 op = read_bin_op_if_available(s, obj);
1785 if (!op)
1786 break;
1788 right_obj = read_obj(s, table);
1790 op = find_matching_bin_op(op, obj, right_obj);
1792 if (!op)
1793 isl_die(s->ctx, isl_error_invalid,
1794 "no such binary operator defined on given operands",
1795 goto error);
1797 obj = convert(s->ctx, obj, op->lhs);
1798 right_obj = convert(s->ctx, right_obj, op->rhs);
1799 obj.v = op->fn(obj.v, right_obj.v);
1800 obj.type = op->res;
1803 return obj;
1804 error:
1805 free_obj(right_obj);
1806 free_obj(obj);
1807 obj.type = isl_obj_none;
1808 obj.v = NULL;
1809 return obj;
1812 static __isl_give isl_printer *source_file(struct isl_stream *s,
1813 struct isl_hash_table *table, __isl_take isl_printer *p);
1815 static __isl_give isl_printer *read_line(struct isl_stream *s,
1816 struct isl_hash_table *table, __isl_take isl_printer *p)
1818 struct isl_obj obj = { isl_obj_none, NULL };
1819 char *lhs = NULL;
1820 int assign = 0;
1821 struct isc_bin_op *op = NULL;
1823 if (!p)
1824 return NULL;
1825 if (isl_stream_is_empty(s))
1826 return p;
1828 if (isl_stream_eat_if_available(s, iscc_op[ISCC_SOURCE]))
1829 return source_file(s, table, p);
1831 assign = is_assign(s);
1832 if (assign) {
1833 lhs = isl_stream_read_ident_if_available(s);
1834 if (isl_stream_eat(s, ISL_TOKEN_DEF))
1835 goto error;
1838 obj = read_expr(s, table);
1839 if (obj.type == isl_obj_none || obj.v == NULL)
1840 goto error;
1841 if (isl_stream_eat(s, ';'))
1842 goto error;
1844 if (assign) {
1845 if (do_assign(s->ctx, table, lhs, obj))
1846 return;
1847 } else {
1848 p = obj.type->print(p, obj.v);
1849 p = isl_printer_end_line(p);
1850 free_obj(obj);
1853 return p;
1854 error:
1855 isl_stream_flush_tokens(s);
1856 isl_stream_skip_line(s);
1857 free(lhs);
1858 free_obj(obj);
1859 return p;
1862 int free_cb(void **entry, void *user)
1864 struct isl_named_obj *named = *entry;
1866 free_obj(named->obj);
1867 free(named->name);
1868 free(named);
1870 return 0;
1873 static void register_named_ops(struct isl_stream *s)
1875 int i;
1877 for (i = 0; i < ISCC_N_OP; ++i) {
1878 iscc_op[i] = isl_stream_register_keyword(s, op_name[i]);
1879 assert(iscc_op[i] != ISL_TOKEN_ERROR);
1882 for (i = 0; ; ++i) {
1883 if (!named_un_ops[i].name)
1884 break;
1885 named_un_ops[i].op.op = isl_stream_register_keyword(s,
1886 named_un_ops[i].name);
1887 assert(named_un_ops[i].op.op != ISL_TOKEN_ERROR);
1890 for (i = 0; ; ++i) {
1891 if (!named_bin_ops[i].name)
1892 break;
1893 named_bin_ops[i].op.op = isl_stream_register_keyword(s,
1894 named_bin_ops[i].name);
1895 assert(named_bin_ops[i].op.op != ISL_TOKEN_ERROR);
1899 static __isl_give isl_printer *source_file(struct isl_stream *s,
1900 struct isl_hash_table *table, __isl_take isl_printer *p)
1902 struct isl_token *tok;
1903 struct isl_stream *s_file;
1904 FILE *file;
1906 tok = isl_stream_next_token(s);
1907 if (!tok || tok->type != ISL_TOKEN_STRING) {
1908 isl_stream_error(s, tok, "expecting filename");
1909 isl_token_free(tok);
1910 return p;
1913 file = fopen(tok->u.s, "r");
1914 isl_token_free(tok);
1915 isl_assert(s->ctx, file, return p);
1917 s_file = isl_stream_new_file(s->ctx, file);
1918 if (!s_file) {
1919 fclose(file);
1920 return p;
1923 register_named_ops(s_file);
1925 while (!s_file->eof)
1926 p = read_line(s_file, table, p);
1928 isl_stream_free(s_file);
1929 fclose(file);
1931 isl_stream_eat(s, ';');
1933 return p;
1936 int main(int argc, char **argv)
1938 struct isl_ctx *ctx;
1939 struct isl_stream *s;
1940 struct isl_hash_table *table;
1941 struct iscc_options *options;
1942 isl_printer *p;
1944 options = iscc_options_new_with_defaults();
1945 assert(options);
1946 argc = iscc_options_parse(options, argc, argv, ISL_ARG_ALL);
1948 ctx = isl_ctx_alloc_with_options(iscc_options_arg, options);
1949 s = isl_stream_new_file(ctx, stdin);
1950 assert(s);
1951 table = isl_hash_table_alloc(ctx, 10);
1952 assert(table);
1953 p = isl_printer_to_file(ctx, stdout);
1954 p = isl_printer_set_output_format(p, options->format);
1955 assert(p);
1957 register_named_ops(s);
1959 while (p && !s->eof) {
1960 p = read_line(s, table, p);
1963 isl_printer_free(p);
1964 isl_hash_table_foreach(ctx, table, free_cb, NULL);
1965 isl_hash_table_free(ctx, table);
1966 isl_stream_free(s);
1967 isl_ctx_free(ctx);
1969 return 0;