iscc: add equality operation on strings
[barvinok.git] / iscc.c
blobfff567fbdec99f77c8cd0a13c1fc4cc8de59ae47
1 #include <assert.h>
2 #include <ctype.h>
3 #include <stdio.h>
4 #include <string.h>
5 #include <unistd.h>
6 #include <isl/aff.h>
7 #include <isl/obj.h>
8 #include <isl/stream.h>
9 #include <isl/set.h>
10 #include <isl/map.h>
11 #include <isl/vertices.h>
12 #include <isl/flow.h>
13 #include <isl/band.h>
14 #include <isl/schedule.h>
15 #include <isl/ast_build.h>
16 #include <isl_obj_list.h>
17 #include <isl_obj_str.h>
18 #include <barvinok/isl.h>
19 #include <barvinok/options.h>
20 #include "lattice_width.h"
22 #include "config.h"
24 #ifdef HAVE_SIGACTION
25 #include <signal.h>
27 static isl_ctx *main_ctx;
29 static void handler(int signum)
31 if (isl_ctx_aborted(main_ctx))
32 exit(EXIT_FAILURE);
33 isl_ctx_abort(main_ctx);
36 static struct sigaction sa_old;
38 static void install_signal_handler(isl_ctx *ctx)
40 struct sigaction sa;
42 main_ctx = ctx;
44 memset(&sa, 0, sizeof(struct sigaction));
45 sa.sa_handler = &handler;
46 sa.sa_flags = SA_RESTART;
47 sigaction(SIGINT, &sa, &sa_old);
50 static void remove_signal_handler(isl_ctx *ctx)
52 sigaction(SIGINT, &sa_old, NULL);
55 #else
57 static void install_signal_handler(isl_ctx *ctx)
61 static void remove_signal_handler(isl_ctx *ctx)
65 #endif
67 #ifdef HAVE_PET
68 #include <pet.h>
69 #else
70 struct pet_options;
71 int pet_options_set_autodetect(isl_ctx *ctx, int val)
73 return -1;
75 #endif
77 static int isl_bool_false = 0;
78 static int isl_bool_true = 1;
79 static int isl_bool_error = -1;
81 enum iscc_op { ISCC_READ, ISCC_WRITE, ISCC_SOURCE, ISCC_VERTICES,
82 ISCC_LAST, ISCC_ANY, ISCC_BEFORE, ISCC_UNDER,
83 ISCC_SCHEDULE, ISCC_SCHEDULE_FOREST,
84 ISCC_MINIMIZING, ISCC_RESPECTING,
85 ISCC_CODEGEN, ISCC_USING,
86 ISCC_TYPEOF, ISCC_PRINT, ISCC_ASSERT,
87 ISCC_N_OP };
88 static const char *op_name[ISCC_N_OP] = {
89 [ISCC_ASSERT] = "assert",
90 [ISCC_READ] = "read",
91 [ISCC_WRITE] = "write",
92 [ISCC_PRINT] = "print",
93 [ISCC_SOURCE] = "source",
94 [ISCC_VERTICES] = "vertices",
95 [ISCC_LAST] = "last",
96 [ISCC_ANY] = "any",
97 [ISCC_BEFORE] = "before",
98 [ISCC_UNDER] = "under",
99 [ISCC_SCHEDULE] = "schedule",
100 [ISCC_SCHEDULE_FOREST] = "schedule_forest",
101 [ISCC_MINIMIZING] = "minimizing",
102 [ISCC_RESPECTING] = "respecting",
103 [ISCC_CODEGEN] = "codegen",
104 [ISCC_USING] = "using",
105 [ISCC_TYPEOF] = "typeof"
107 static enum isl_token_type iscc_op[ISCC_N_OP];
109 struct isl_arg_choice iscc_format[] = {
110 {"isl", ISL_FORMAT_ISL},
111 {"omega", ISL_FORMAT_OMEGA},
112 {"polylib", ISL_FORMAT_POLYLIB},
113 {"ext-polylib", ISL_FORMAT_EXT_POLYLIB},
114 {"latex", ISL_FORMAT_LATEX},
115 {"C", ISL_FORMAT_C},
119 struct iscc_options {
120 struct barvinok_options *barvinok;
121 struct pet_options *pet;
122 unsigned format;
123 int io;
126 ISL_ARGS_START(struct iscc_options, iscc_options_args)
127 ISL_ARG_CHILD(struct iscc_options, barvinok, "barvinok", &barvinok_options_args,
128 "barvinok options")
129 #ifdef HAVE_PET
130 ISL_ARG_CHILD(struct iscc_options, pet, "pet", &pet_options_args, "pet options")
131 #endif
132 ISL_ARG_CHOICE(struct iscc_options, format, 0, "format", \
133 iscc_format, ISL_FORMAT_ISL, "output format")
134 ISL_ARG_BOOL(struct iscc_options, io, 0, "io", 1,
135 "allow read and write operations")
136 ISL_ARGS_END
138 ISL_ARG_DEF(iscc_options, struct iscc_options, iscc_options_args)
139 ISL_ARG_CTX_DEF(iscc_options, struct iscc_options, iscc_options_args)
141 static void *isl_obj_bool_copy(void *v)
143 return v;
146 static void isl_obj_bool_free(void *v)
150 static __isl_give isl_printer *isl_obj_bool_print(__isl_take isl_printer *p,
151 void *v)
153 if (v == &isl_bool_true)
154 return isl_printer_print_str(p, "True");
155 else if (v == &isl_bool_false)
156 return isl_printer_print_str(p, "False");
157 else
158 return isl_printer_print_str(p, "Error");
161 static void *isl_obj_bool_add(void *v1, void *v2)
163 return v1;
166 struct isl_obj_vtable isl_obj_bool_vtable = {
167 isl_obj_bool_copy,
168 isl_obj_bool_add,
169 isl_obj_bool_print,
170 isl_obj_bool_free
172 #define isl_obj_bool (&isl_obj_bool_vtable)
174 int *isl_bool_from_int(int res)
176 return res < 0 ? &isl_bool_error : res ? &isl_bool_true : &isl_bool_false;
179 static int isl_union_map_is_superset(__isl_take isl_union_map *map1,
180 __isl_take isl_union_map *map2)
182 return isl_union_map_is_subset(map2, map1);
184 static int isl_union_set_is_superset(__isl_take isl_union_set *set1,
185 __isl_take isl_union_set *set2)
187 return isl_union_set_is_subset(set2, set1);
190 static int isl_union_map_is_strict_superset(__isl_take isl_union_map *map1,
191 __isl_take isl_union_map *map2)
193 return isl_union_map_is_strict_subset(map2, map1);
195 static int isl_union_set_is_strict_superset(__isl_take isl_union_set *set1,
196 __isl_take isl_union_set *set2)
198 return isl_union_set_is_strict_subset(set2, set1);
201 extern struct isl_obj_vtable isl_obj_list_vtable;
202 #define isl_obj_list (&isl_obj_list_vtable)
204 typedef void *(*isc_bin_op_fn)(void *lhs, void *rhs);
205 typedef int (*isc_bin_test_fn)(void *lhs, void *rhs);
206 struct isc_bin_op {
207 enum isl_token_type op;
208 isl_obj_type lhs;
209 isl_obj_type rhs;
210 isl_obj_type res;
211 union {
212 isc_bin_op_fn fn;
213 isc_bin_test_fn test;
214 } o;
216 struct isc_named_bin_op {
217 char *name;
218 struct isc_bin_op op;
221 struct iscc_at {
222 isl_union_pw_qpolynomial *upwqp;
223 isl_union_pw_qpolynomial *res;
226 static int eval_at(__isl_take isl_point *pnt, void *user)
228 struct iscc_at *at = (struct iscc_at *) user;
229 isl_val *v;
230 isl_qpolynomial *qp;
231 isl_set *set;
233 set = isl_set_from_point(isl_point_copy(pnt));
234 v = isl_union_pw_qpolynomial_eval(
235 isl_union_pw_qpolynomial_copy(at->upwqp), pnt);
236 qp = isl_qpolynomial_val_on_domain(isl_set_get_space(set), v);
238 at->res = isl_union_pw_qpolynomial_add(at->res,
239 isl_union_pw_qpolynomial_from_pw_qpolynomial(
240 isl_pw_qpolynomial_alloc(set, qp)));
242 return 0;
245 __isl_give isl_union_pw_qpolynomial *isl_union_pw_qpolynomial_at(
246 __isl_take isl_union_pw_qpolynomial *upwqp,
247 __isl_take isl_union_set *uset)
249 struct iscc_at at;
251 at.upwqp = upwqp;
252 at.res = isl_union_pw_qpolynomial_zero(isl_union_set_get_space(uset));
254 isl_union_set_foreach_point(uset, eval_at, &at);
256 isl_union_pw_qpolynomial_free(upwqp);
257 isl_union_set_free(uset);
259 return at.res;
262 struct iscc_fold_at {
263 isl_union_pw_qpolynomial_fold *upwf;
264 isl_union_pw_qpolynomial *res;
267 static int eval_fold_at(__isl_take isl_point *pnt, void *user)
269 struct iscc_fold_at *at = (struct iscc_fold_at *) user;
270 isl_val *v;
271 isl_qpolynomial *qp;
272 isl_set *set;
274 set = isl_set_from_point(isl_point_copy(pnt));
275 v = isl_union_pw_qpolynomial_fold_eval(
276 isl_union_pw_qpolynomial_fold_copy(at->upwf), pnt);
277 qp = isl_qpolynomial_val_on_domain(isl_set_get_space(set), v);
279 at->res = isl_union_pw_qpolynomial_add(at->res,
280 isl_union_pw_qpolynomial_from_pw_qpolynomial(
281 isl_pw_qpolynomial_alloc(set, qp)));
283 return 0;
286 __isl_give isl_union_pw_qpolynomial *isl_union_pw_qpolynomial_fold_at(
287 __isl_take isl_union_pw_qpolynomial_fold *upwf,
288 __isl_take isl_union_set *uset)
290 struct iscc_fold_at at;
292 at.upwf = upwf;
293 at.res = isl_union_pw_qpolynomial_zero(isl_union_set_get_space(uset));
295 isl_union_set_foreach_point(uset, eval_fold_at, &at);
297 isl_union_pw_qpolynomial_fold_free(upwf);
298 isl_union_set_free(uset);
300 return at.res;
303 static __isl_give isl_union_pw_qpolynomial_fold *union_pw_qpolynomial_add_union_pw_qpolynomial_fold(
304 __isl_take isl_union_pw_qpolynomial *upwqp,
305 __isl_take isl_union_pw_qpolynomial_fold *upwf)
307 return isl_union_pw_qpolynomial_fold_add_union_pw_qpolynomial(upwf,
308 upwqp);
311 static __isl_give struct isl_list *union_map_apply_union_pw_qpolynomial_fold(
312 __isl_take isl_union_map *umap,
313 __isl_take isl_union_pw_qpolynomial_fold *upwf)
315 isl_ctx *ctx;
316 struct isl_list *list;
317 int tight;
319 ctx = isl_union_map_get_ctx(umap);
320 list = isl_list_alloc(ctx, 2);
321 if (!list)
322 goto error2;
324 list->obj[0].type = isl_obj_union_pw_qpolynomial_fold;
325 list->obj[0].v = isl_union_map_apply_union_pw_qpolynomial_fold(umap,
326 upwf, &tight);
327 list->obj[1].type = isl_obj_bool;
328 list->obj[1].v = tight ? &isl_bool_true : &isl_bool_false;
329 if (tight < 0 || !list->obj[0].v)
330 goto error;
332 return list;
333 error2:
334 isl_union_map_free(umap);
335 isl_union_pw_qpolynomial_fold_free(upwf);
336 error:
337 isl_list_free(list);
338 return NULL;
341 static __isl_give struct isl_list *union_set_apply_union_pw_qpolynomial_fold(
342 __isl_take isl_union_set *uset,
343 __isl_take isl_union_pw_qpolynomial_fold *upwf)
345 isl_ctx *ctx;
346 struct isl_list *list;
347 int tight;
349 ctx = isl_union_set_get_ctx(uset);
350 list = isl_list_alloc(ctx, 2);
351 if (!list)
352 goto error2;
354 list->obj[0].type = isl_obj_union_pw_qpolynomial_fold;
355 list->obj[0].v = isl_union_set_apply_union_pw_qpolynomial_fold(uset,
356 upwf, &tight);
357 list->obj[1].type = isl_obj_bool;
358 list->obj[1].v = tight ? &isl_bool_true : &isl_bool_false;
359 if (tight < 0 || !list->obj[0].v)
360 goto error;
362 return list;
363 error2:
364 isl_union_set_free(uset);
365 isl_union_pw_qpolynomial_fold_free(upwf);
366 error:
367 isl_list_free(list);
368 return NULL;
371 static __isl_give isl_union_pw_qpolynomial *isl_val_mul_union_pw_qpolynomial(
372 __isl_take isl_val *v, __isl_take isl_union_pw_qpolynomial *upwqp)
374 return isl_union_pw_qpolynomial_scale_val(upwqp, v);
377 static __isl_give isl_union_pw_qpolynomial_fold *
378 int_val_mul_union_pw_qpolynomial_fold(__isl_take isl_val *v,
379 __isl_take isl_union_pw_qpolynomial_fold *upwf)
381 return isl_union_pw_qpolynomial_fold_scale_val(upwf, v);
384 /* Are the two strings "str1" and "str2" equal to each other?
386 static int str_eq(__isl_keep isl_str *str1, __isl_keep isl_str *str2)
388 if (!str1 || !str2)
389 return -1;
391 return !strcmp(str1->s, str2->s);
394 struct isc_bin_op bin_ops[] = {
395 { '+', isl_obj_val, isl_obj_val, isl_obj_val,
396 (isc_bin_op_fn) &isl_val_add },
397 { '-', isl_obj_val, isl_obj_val, isl_obj_val,
398 (isc_bin_op_fn) &isl_val_sub },
399 { '*', isl_obj_val, isl_obj_val, isl_obj_val,
400 (isc_bin_op_fn) &isl_val_mul },
401 { '+', isl_obj_pw_multi_aff, isl_obj_pw_multi_aff,
402 isl_obj_pw_multi_aff,
403 (isc_bin_op_fn) &isl_pw_multi_aff_add },
404 { '+', isl_obj_union_set, isl_obj_union_set,
405 isl_obj_union_set,
406 (isc_bin_op_fn) &isl_union_set_union },
407 { '+', isl_obj_union_map, isl_obj_union_map,
408 isl_obj_union_map,
409 (isc_bin_op_fn) &isl_union_map_union },
410 { '-', isl_obj_union_set, isl_obj_union_set,
411 isl_obj_union_set,
412 (isc_bin_op_fn) &isl_union_set_subtract },
413 { '-', isl_obj_union_map, isl_obj_union_map,
414 isl_obj_union_map,
415 (isc_bin_op_fn) &isl_union_map_subtract },
416 { '*', isl_obj_union_set, isl_obj_union_set,
417 isl_obj_union_set,
418 (isc_bin_op_fn) &isl_union_set_intersect },
419 { '*', isl_obj_union_map, isl_obj_union_map,
420 isl_obj_union_map,
421 (isc_bin_op_fn) &isl_union_map_intersect },
422 { '*', isl_obj_union_map, isl_obj_union_set,
423 isl_obj_union_map,
424 (isc_bin_op_fn) &isl_union_map_intersect_domain },
425 { '.', isl_obj_union_map, isl_obj_union_map,
426 isl_obj_union_map,
427 (isc_bin_op_fn) &isl_union_map_apply_range },
428 { '.', isl_obj_union_map, isl_obj_union_pw_qpolynomial,
429 isl_obj_union_pw_qpolynomial,
430 (isc_bin_op_fn) &isl_union_map_apply_union_pw_qpolynomial },
431 { '.', isl_obj_union_map, isl_obj_union_pw_qpolynomial_fold,
432 isl_obj_list,
433 (isc_bin_op_fn) &union_map_apply_union_pw_qpolynomial_fold },
434 { ISL_TOKEN_TO, isl_obj_union_set, isl_obj_union_set,
435 isl_obj_union_map,
436 (isc_bin_op_fn) &isl_union_map_from_domain_and_range },
437 { '=', isl_obj_union_set, isl_obj_union_set, isl_obj_bool,
438 { .test = (isc_bin_test_fn) &isl_union_set_is_equal } },
439 { '=', isl_obj_union_map, isl_obj_union_map, isl_obj_bool,
440 { .test = (isc_bin_test_fn) &isl_union_map_is_equal } },
441 { ISL_TOKEN_LE, isl_obj_union_set, isl_obj_union_set,
442 isl_obj_bool,
443 { .test = (isc_bin_test_fn) &isl_union_set_is_subset } },
444 { ISL_TOKEN_LE, isl_obj_union_map, isl_obj_union_map,
445 isl_obj_bool,
446 { .test = (isc_bin_test_fn) &isl_union_map_is_subset } },
447 { ISL_TOKEN_LT, isl_obj_union_set, isl_obj_union_set,
448 isl_obj_bool,
449 { .test = (isc_bin_test_fn) &isl_union_set_is_strict_subset } },
450 { ISL_TOKEN_LT, isl_obj_union_map, isl_obj_union_map,
451 isl_obj_bool,
452 { .test = (isc_bin_test_fn) &isl_union_map_is_strict_subset } },
453 { ISL_TOKEN_GE, isl_obj_union_set, isl_obj_union_set,
454 isl_obj_bool,
455 { .test = (isc_bin_test_fn) &isl_union_set_is_superset } },
456 { ISL_TOKEN_GE, isl_obj_union_map, isl_obj_union_map,
457 isl_obj_bool,
458 { .test = (isc_bin_test_fn) &isl_union_map_is_superset } },
459 { ISL_TOKEN_GT, isl_obj_union_set, isl_obj_union_set,
460 isl_obj_bool,
461 { .test =
462 (isc_bin_test_fn) &isl_union_set_is_strict_superset } },
463 { ISL_TOKEN_GT, isl_obj_union_map, isl_obj_union_map,
464 isl_obj_bool,
465 { .test =
466 (isc_bin_test_fn) &isl_union_map_is_strict_superset } },
467 { ISL_TOKEN_LEX_LE, isl_obj_union_set, isl_obj_union_set,
468 isl_obj_union_map,
469 (isc_bin_op_fn) &isl_union_set_lex_le_union_set },
470 { ISL_TOKEN_LEX_LT, isl_obj_union_set, isl_obj_union_set,
471 isl_obj_union_map,
472 (isc_bin_op_fn) &isl_union_set_lex_lt_union_set },
473 { ISL_TOKEN_LEX_GE, isl_obj_union_set, isl_obj_union_set,
474 isl_obj_union_map,
475 (isc_bin_op_fn) &isl_union_set_lex_ge_union_set },
476 { ISL_TOKEN_LEX_GT, isl_obj_union_set, isl_obj_union_set,
477 isl_obj_union_map,
478 (isc_bin_op_fn) &isl_union_set_lex_gt_union_set },
479 { ISL_TOKEN_LEX_LE, isl_obj_union_map, isl_obj_union_map,
480 isl_obj_union_map,
481 (isc_bin_op_fn) &isl_union_map_lex_le_union_map },
482 { ISL_TOKEN_LEX_LT, isl_obj_union_map, isl_obj_union_map,
483 isl_obj_union_map,
484 (isc_bin_op_fn) &isl_union_map_lex_lt_union_map },
485 { ISL_TOKEN_LEX_GE, isl_obj_union_map, isl_obj_union_map,
486 isl_obj_union_map,
487 (isc_bin_op_fn) &isl_union_map_lex_ge_union_map },
488 { ISL_TOKEN_LEX_GT, isl_obj_union_map, isl_obj_union_map,
489 isl_obj_union_map,
490 (isc_bin_op_fn) &isl_union_map_lex_gt_union_map },
491 { '.', isl_obj_union_pw_qpolynomial_fold,
492 isl_obj_union_pw_qpolynomial_fold,
493 isl_obj_union_pw_qpolynomial_fold,
494 (isc_bin_op_fn) &isl_union_pw_qpolynomial_fold_fold },
495 { '+', isl_obj_union_pw_qpolynomial, isl_obj_union_pw_qpolynomial,
496 isl_obj_union_pw_qpolynomial,
497 (isc_bin_op_fn) &isl_union_pw_qpolynomial_add },
498 { '+', isl_obj_union_pw_qpolynomial,
499 isl_obj_union_pw_qpolynomial_fold,
500 isl_obj_union_pw_qpolynomial_fold,
501 (isc_bin_op_fn) &union_pw_qpolynomial_add_union_pw_qpolynomial_fold },
502 { '+', isl_obj_union_pw_qpolynomial_fold,
503 isl_obj_union_pw_qpolynomial,
504 isl_obj_union_pw_qpolynomial_fold,
505 (isc_bin_op_fn) &isl_union_pw_qpolynomial_fold_add_union_pw_qpolynomial },
506 { '-', isl_obj_union_pw_qpolynomial, isl_obj_union_pw_qpolynomial,
507 isl_obj_union_pw_qpolynomial,
508 (isc_bin_op_fn) &isl_union_pw_qpolynomial_sub },
509 { '*', isl_obj_val, isl_obj_union_pw_qpolynomial,
510 isl_obj_union_pw_qpolynomial,
511 (isc_bin_op_fn) &isl_val_mul_union_pw_qpolynomial },
512 { '*', isl_obj_union_pw_qpolynomial, isl_obj_val,
513 isl_obj_union_pw_qpolynomial,
514 (isc_bin_op_fn) &isl_union_pw_qpolynomial_scale_val },
515 { '*', isl_obj_val, isl_obj_union_pw_qpolynomial_fold,
516 isl_obj_union_pw_qpolynomial_fold,
517 (isc_bin_op_fn) &int_val_mul_union_pw_qpolynomial_fold },
518 { '*', isl_obj_union_pw_qpolynomial_fold, isl_obj_val,
519 isl_obj_union_pw_qpolynomial_fold,
520 (isc_bin_op_fn) &isl_union_pw_qpolynomial_fold_scale_val },
521 { '*', isl_obj_union_pw_qpolynomial, isl_obj_union_pw_qpolynomial,
522 isl_obj_union_pw_qpolynomial,
523 (isc_bin_op_fn) &isl_union_pw_qpolynomial_mul },
524 { '*', isl_obj_union_pw_qpolynomial, isl_obj_union_set,
525 isl_obj_union_pw_qpolynomial,
526 (isc_bin_op_fn) &isl_union_pw_qpolynomial_intersect_domain },
527 { '*', isl_obj_union_pw_qpolynomial_fold, isl_obj_union_set,
528 isl_obj_union_pw_qpolynomial_fold,
529 (isc_bin_op_fn) &isl_union_pw_qpolynomial_fold_intersect_domain },
530 { '@', isl_obj_union_pw_qpolynomial, isl_obj_union_set,
531 isl_obj_union_pw_qpolynomial,
532 (isc_bin_op_fn) &isl_union_pw_qpolynomial_at },
533 { '@', isl_obj_union_pw_qpolynomial_fold, isl_obj_union_set,
534 isl_obj_union_pw_qpolynomial,
535 (isc_bin_op_fn) &isl_union_pw_qpolynomial_fold_at },
536 { '%', isl_obj_union_set, isl_obj_union_set,
537 isl_obj_union_set,
538 (isc_bin_op_fn) &isl_union_set_gist },
539 { '%', isl_obj_union_map, isl_obj_union_map,
540 isl_obj_union_map,
541 (isc_bin_op_fn) &isl_union_map_gist },
542 { '%', isl_obj_union_map, isl_obj_union_set,
543 isl_obj_union_map,
544 (isc_bin_op_fn) &isl_union_map_gist_domain },
545 { '%', isl_obj_union_pw_qpolynomial, isl_obj_union_set,
546 isl_obj_union_pw_qpolynomial,
547 (isc_bin_op_fn) &isl_union_pw_qpolynomial_gist },
548 { '%', isl_obj_union_pw_qpolynomial_fold, isl_obj_union_set,
549 isl_obj_union_pw_qpolynomial_fold,
550 (isc_bin_op_fn) &isl_union_pw_qpolynomial_fold_gist },
551 { ISL_TOKEN_EQ_EQ, isl_obj_union_pw_qpolynomial,
552 isl_obj_union_pw_qpolynomial, isl_obj_bool,
553 { .test = (isc_bin_test_fn)
554 &isl_union_pw_qpolynomial_plain_is_equal } },
555 { ISL_TOKEN_EQ_EQ, isl_obj_union_pw_qpolynomial_fold,
556 isl_obj_union_pw_qpolynomial_fold, isl_obj_bool,
557 { .test = (isc_bin_test_fn)
558 &isl_union_pw_qpolynomial_fold_plain_is_equal } },
559 { '+', isl_obj_str, isl_obj_str, isl_obj_str,
560 (isc_bin_op_fn) &isl_str_concat },
561 { '=', isl_obj_str, isl_obj_str, isl_obj_bool,
562 { .test = (isc_bin_test_fn) &str_eq } },
566 static __isl_give isl_union_map *map_after_map(__isl_take isl_union_map *umap1,
567 __isl_take isl_union_map *umap2)
569 return isl_union_map_apply_range(umap2, umap1);
572 static __isl_give isl_union_pw_qpolynomial *qpolynomial_after_map(
573 __isl_take isl_union_pw_qpolynomial *upwqp,
574 __isl_take isl_union_map *umap)
576 return isl_union_map_apply_union_pw_qpolynomial(umap, upwqp);
579 static __isl_give struct isl_list *qpolynomial_fold_after_map(
580 __isl_take isl_union_pw_qpolynomial_fold *upwf,
581 __isl_take isl_union_map *umap)
583 return union_map_apply_union_pw_qpolynomial_fold(umap, upwf);
586 struct isc_named_bin_op named_bin_ops[] = {
587 { "after", { -1, isl_obj_union_map, isl_obj_union_map,
588 isl_obj_union_map,
589 (isc_bin_op_fn) &map_after_map } },
590 { "after", { -1, isl_obj_union_pw_qpolynomial,
591 isl_obj_union_map, isl_obj_union_pw_qpolynomial,
592 (isc_bin_op_fn) &qpolynomial_after_map } },
593 { "after", { -1, isl_obj_union_pw_qpolynomial_fold,
594 isl_obj_union_map, isl_obj_list,
595 (isc_bin_op_fn) &qpolynomial_fold_after_map } },
596 { "before", { -1, isl_obj_union_map, isl_obj_union_map,
597 isl_obj_union_map,
598 (isc_bin_op_fn) &isl_union_map_apply_range } },
599 { "before", { -1, isl_obj_union_map,
600 isl_obj_union_pw_qpolynomial, isl_obj_union_pw_qpolynomial,
601 (isc_bin_op_fn) &isl_union_map_apply_union_pw_qpolynomial } },
602 { "before", { -1, isl_obj_union_map,
603 isl_obj_union_pw_qpolynomial_fold, isl_obj_list,
604 (isc_bin_op_fn) &union_map_apply_union_pw_qpolynomial_fold } },
605 { "cross", { -1, isl_obj_union_set, isl_obj_union_set,
606 isl_obj_union_set,
607 (isc_bin_op_fn) &isl_union_set_product } },
608 { "cross", { -1, isl_obj_union_map, isl_obj_union_map,
609 isl_obj_union_map,
610 (isc_bin_op_fn) &isl_union_map_product } },
611 NULL
614 __isl_give isl_set *union_set_sample(__isl_take isl_union_set *uset)
616 return isl_set_from_basic_set(isl_union_set_sample(uset));
619 __isl_give isl_map *union_map_sample(__isl_take isl_union_map *umap)
621 return isl_map_from_basic_map(isl_union_map_sample(umap));
624 static __isl_give struct isl_list *union_map_power(
625 __isl_take isl_union_map *umap)
627 isl_ctx *ctx;
628 struct isl_list *list;
629 int exact;
631 ctx = isl_union_map_get_ctx(umap);
632 list = isl_list_alloc(ctx, 2);
633 if (!list)
634 goto error2;
636 list->obj[0].type = isl_obj_union_map;
637 list->obj[0].v = isl_union_map_power(umap, &exact);
638 list->obj[1].type = isl_obj_bool;
639 list->obj[1].v = exact ? &isl_bool_true : &isl_bool_false;
640 if (exact < 0 || !list->obj[0].v)
641 goto error;
643 return list;
644 error2:
645 isl_union_map_free(umap);
646 error:
647 isl_list_free(list);
648 return NULL;
651 static __isl_give struct isl_list *union_pw_qpolynomial_upper_bound(
652 __isl_take isl_union_pw_qpolynomial *upwqp)
654 isl_ctx *ctx;
655 struct isl_list *list;
656 int tight;
658 ctx = isl_union_pw_qpolynomial_get_ctx(upwqp);
659 list = isl_list_alloc(ctx, 2);
660 if (!list)
661 goto error2;
663 list->obj[0].type = isl_obj_union_pw_qpolynomial_fold;
664 list->obj[0].v = isl_union_pw_qpolynomial_bound(upwqp,
665 isl_fold_max, &tight);
666 list->obj[1].type = isl_obj_bool;
667 list->obj[1].v = tight ? &isl_bool_true : &isl_bool_false;
668 if (tight < 0 || !list->obj[0].v)
669 goto error;
671 return list;
672 error2:
673 isl_union_pw_qpolynomial_free(upwqp);
674 error:
675 isl_list_free(list);
676 return NULL;
679 #ifdef HAVE_PET
680 static __isl_give isl_list *parse(__isl_take isl_str *str)
682 isl_ctx *ctx;
683 struct isl_list *list;
684 struct pet_scop *scop;
685 isl_union_map *sched, *may_reads, *must_writes, *may_writes;
686 isl_union_set *domain;
687 struct iscc_options *options;
689 if (!str)
690 return NULL;
691 ctx = str->ctx;
693 options = isl_ctx_peek_iscc_options(ctx);
694 if (!options || !options->io) {
695 isl_str_free(str);
696 isl_die(ctx, isl_error_invalid,
697 "parse_file operation not allowed", return NULL);
700 list = isl_list_alloc(ctx, 5);
701 if (!list)
702 goto error;
704 scop = pet_scop_extract_from_C_source(ctx, str->s, NULL);
705 domain = pet_scop_collect_domains(scop);
706 sched = scop ? isl_schedule_get_map(scop->schedule) : NULL;
707 may_reads = pet_scop_collect_may_reads(scop);
708 may_writes = pet_scop_collect_may_writes(scop);
709 must_writes = pet_scop_collect_must_writes(scop);
710 pet_scop_free(scop);
712 list->obj[0].type = isl_obj_union_set;
713 list->obj[0].v = domain;
714 list->obj[1].type = isl_obj_union_map;
715 list->obj[1].v = must_writes;
716 list->obj[2].type = isl_obj_union_map;
717 list->obj[2].v = may_writes;
718 list->obj[3].type = isl_obj_union_map;
719 list->obj[3].v = may_reads;
720 list->obj[4].type = isl_obj_union_map;
721 list->obj[4].v = sched;
723 if (!list->obj[0].v || !list->obj[1].v ||
724 !list->obj[2].v || !list->obj[3].v || !list->obj[4].v)
725 goto error;
727 isl_str_free(str);
728 return list;
729 error:
730 isl_list_free(list);
731 isl_str_free(str);
732 return NULL;
734 #endif
736 static int add_point(__isl_take isl_point *pnt, void *user)
738 isl_union_set **scan = (isl_union_set **) user;
740 *scan = isl_union_set_add_set(*scan, isl_set_from_point(pnt));
742 return 0;
745 static __isl_give isl_union_set *union_set_scan(__isl_take isl_union_set *uset)
747 isl_union_set *scan;
749 scan = isl_union_set_empty(isl_union_set_get_space(uset));
751 if (isl_union_set_foreach_point(uset, add_point, &scan) < 0) {
752 isl_union_set_free(scan);
753 return uset;
756 isl_union_set_free(uset);
757 return scan;
760 static __isl_give isl_union_map *union_map_scan(__isl_take isl_union_map *umap)
762 return isl_union_set_unwrap(union_set_scan(isl_union_map_wrap(umap)));
765 static __isl_give isl_union_pw_qpolynomial *union_pw_qpolynomial_poly(
766 __isl_take isl_union_pw_qpolynomial *upwqp)
768 return isl_union_pw_qpolynomial_to_polynomial(upwqp, 0);
771 static __isl_give isl_union_pw_qpolynomial *union_pw_qpolynomial_lpoly(
772 __isl_take isl_union_pw_qpolynomial *upwqp)
774 return isl_union_pw_qpolynomial_to_polynomial(upwqp, -1);
777 static __isl_give isl_union_pw_qpolynomial *union_pw_qpolynomial_upoly(
778 __isl_take isl_union_pw_qpolynomial *upwqp)
780 return isl_union_pw_qpolynomial_to_polynomial(upwqp, 1);
783 typedef void *(*isc_un_op_fn)(void *arg);
784 struct isc_un_op {
785 enum isl_token_type op;
786 isl_obj_type arg;
787 isl_obj_type res;
788 isc_un_op_fn fn;
790 struct isc_named_un_op {
791 char *name;
792 struct isc_un_op op;
794 struct isc_named_un_op named_un_ops[] = {
795 {"aff", { -1, isl_obj_union_map, isl_obj_union_map,
796 (isc_un_op_fn) &isl_union_map_affine_hull } },
797 {"aff", { -1, isl_obj_union_set, isl_obj_union_set,
798 (isc_un_op_fn) &isl_union_set_affine_hull } },
799 {"card", { -1, isl_obj_union_set,
800 isl_obj_union_pw_qpolynomial,
801 (isc_un_op_fn) &isl_union_set_card } },
802 {"card", { -1, isl_obj_union_map,
803 isl_obj_union_pw_qpolynomial,
804 (isc_un_op_fn) &isl_union_map_card } },
805 {"coalesce", { -1, isl_obj_union_set, isl_obj_union_set,
806 (isc_un_op_fn) &isl_union_set_coalesce } },
807 {"coalesce", { -1, isl_obj_union_map, isl_obj_union_map,
808 (isc_un_op_fn) &isl_union_map_coalesce } },
809 {"coalesce", { -1, isl_obj_union_pw_qpolynomial,
810 isl_obj_union_pw_qpolynomial,
811 (isc_un_op_fn) &isl_union_pw_qpolynomial_coalesce } },
812 {"coalesce", { -1, isl_obj_union_pw_qpolynomial_fold,
813 isl_obj_union_pw_qpolynomial_fold,
814 (isc_un_op_fn) &isl_union_pw_qpolynomial_fold_coalesce } },
815 {"coefficients", { -1, isl_obj_union_set,
816 isl_obj_union_set,
817 (isc_un_op_fn) &isl_union_set_coefficients } },
818 {"solutions", { -1, isl_obj_union_set, isl_obj_union_set,
819 (isc_un_op_fn) &isl_union_set_solutions } },
820 {"deltas", { -1, isl_obj_union_map, isl_obj_union_set,
821 (isc_un_op_fn) &isl_union_map_deltas } },
822 {"deltas_map", { -1, isl_obj_union_map, isl_obj_union_map,
823 (isc_un_op_fn) &isl_union_map_deltas_map } },
824 {"dom", { -1, isl_obj_union_map, isl_obj_union_set,
825 (isc_un_op_fn) &isl_union_map_domain } },
826 {"dom", { -1, isl_obj_union_pw_qpolynomial, isl_obj_union_set,
827 (isc_un_op_fn) &isl_union_pw_qpolynomial_domain } },
828 {"dom", { -1, isl_obj_union_pw_qpolynomial_fold,
829 isl_obj_union_set,
830 (isc_un_op_fn) &isl_union_pw_qpolynomial_fold_domain } },
831 {"domain", { -1, isl_obj_union_map, isl_obj_union_set,
832 (isc_un_op_fn) &isl_union_map_domain } },
833 {"domain", { -1, isl_obj_union_pw_qpolynomial,
834 isl_obj_union_set,
835 (isc_un_op_fn) &isl_union_pw_qpolynomial_domain } },
836 {"domain", { -1, isl_obj_union_pw_qpolynomial_fold,
837 isl_obj_union_set,
838 (isc_un_op_fn) &isl_union_pw_qpolynomial_fold_domain } },
839 {"domain_map", { -1, isl_obj_union_map, isl_obj_union_map,
840 (isc_un_op_fn) &isl_union_map_domain_map } },
841 {"ran", { -1, isl_obj_union_map, isl_obj_union_set,
842 (isc_un_op_fn) &isl_union_map_range } },
843 {"range", { -1, isl_obj_union_map, isl_obj_union_set,
844 (isc_un_op_fn) &isl_union_map_range } },
845 {"range_map", { -1, isl_obj_union_map, isl_obj_union_map,
846 (isc_un_op_fn) &isl_union_map_range_map } },
847 {"identity", { -1, isl_obj_union_set, isl_obj_union_map,
848 (isc_un_op_fn) &isl_union_set_identity } },
849 {"lattice_width", { -1, isl_obj_union_set,
850 isl_obj_union_pw_qpolynomial,
851 (isc_un_op_fn) &isl_union_set_lattice_width } },
852 {"lexmin", { -1, isl_obj_union_map, isl_obj_union_map,
853 (isc_un_op_fn) &isl_union_map_lexmin } },
854 {"lexmax", { -1, isl_obj_union_map, isl_obj_union_map,
855 (isc_un_op_fn) &isl_union_map_lexmax } },
856 {"lexmin", { -1, isl_obj_union_set, isl_obj_union_set,
857 (isc_un_op_fn) &isl_union_set_lexmin } },
858 {"lexmax", { -1, isl_obj_union_set, isl_obj_union_set,
859 (isc_un_op_fn) &isl_union_set_lexmax } },
860 {"lift", { -1, isl_obj_union_set, isl_obj_union_set,
861 (isc_un_op_fn) &isl_union_set_lift } },
862 {"params", { -1, isl_obj_union_map, isl_obj_set,
863 (isc_un_op_fn) &isl_union_map_params } },
864 {"params", { -1, isl_obj_union_set, isl_obj_set,
865 (isc_un_op_fn) &isl_union_set_params } },
866 {"poly", { -1, isl_obj_union_map, isl_obj_union_map,
867 (isc_un_op_fn) &isl_union_map_polyhedral_hull } },
868 {"poly", { -1, isl_obj_union_set, isl_obj_union_set,
869 (isc_un_op_fn) &isl_union_set_polyhedral_hull } },
870 {"poly", { -1, isl_obj_union_pw_qpolynomial,
871 isl_obj_union_pw_qpolynomial,
872 (isc_un_op_fn) &union_pw_qpolynomial_poly } },
873 {"lpoly", { -1, isl_obj_union_pw_qpolynomial,
874 isl_obj_union_pw_qpolynomial,
875 (isc_un_op_fn) &union_pw_qpolynomial_lpoly } },
876 {"upoly", { -1, isl_obj_union_pw_qpolynomial,
877 isl_obj_union_pw_qpolynomial,
878 (isc_un_op_fn) &union_pw_qpolynomial_upoly } },
879 #ifdef HAVE_PET
880 {"parse_file", { -1, isl_obj_str, isl_obj_list,
881 (isc_un_op_fn) &parse } },
882 #endif
883 {"pow", { -1, isl_obj_union_map, isl_obj_list,
884 (isc_un_op_fn) &union_map_power } },
885 {"sample", { -1, isl_obj_union_set, isl_obj_set,
886 (isc_un_op_fn) &union_set_sample } },
887 {"sample", { -1, isl_obj_union_map, isl_obj_map,
888 (isc_un_op_fn) &union_map_sample } },
889 {"scan", { -1, isl_obj_union_set, isl_obj_union_set,
890 (isc_un_op_fn) &union_set_scan } },
891 {"scan", { -1, isl_obj_union_map, isl_obj_union_map,
892 (isc_un_op_fn) &union_map_scan } },
893 {"sum", { -1, isl_obj_union_pw_qpolynomial,
894 isl_obj_union_pw_qpolynomial,
895 (isc_un_op_fn) &isl_union_pw_qpolynomial_sum } },
896 {"ub", { -1, isl_obj_union_pw_qpolynomial, isl_obj_list,
897 (isc_un_op_fn) &union_pw_qpolynomial_upper_bound } },
898 {"unwrap", { -1, isl_obj_union_set, isl_obj_union_map,
899 (isc_un_op_fn) &isl_union_set_unwrap } },
900 {"wrap", { -1, isl_obj_union_map, isl_obj_union_set,
901 (isc_un_op_fn) &isl_union_map_wrap } },
902 {"zip", { -1, isl_obj_union_map, isl_obj_union_map,
903 (isc_un_op_fn) &isl_union_map_zip } },
904 NULL
907 struct isl_named_obj {
908 char *name;
909 struct isl_obj obj;
912 static void free_obj(struct isl_obj obj)
914 obj.type->free(obj.v);
917 static int same_name(const void *entry, const void *val)
919 const struct isl_named_obj *named = (const struct isl_named_obj *)entry;
921 return !strcmp(named->name, val);
924 static int do_assign(struct isl_ctx *ctx, struct isl_hash_table *table,
925 char *name, struct isl_obj obj)
927 struct isl_hash_table_entry *entry;
928 uint32_t name_hash;
929 struct isl_named_obj *named;
931 name_hash = isl_hash_string(isl_hash_init(), name);
932 entry = isl_hash_table_find(ctx, table, name_hash, same_name, name, 1);
933 if (!entry)
934 goto error;
935 if (entry->data) {
936 named = entry->data;
937 free_obj(named->obj);
938 free(name);
939 } else {
940 named = isl_alloc_type(ctx, struct isl_named_obj);
941 if (!named)
942 goto error;
943 named->name = name;
944 entry->data = named;
946 named->obj = obj;
948 return 0;
949 error:
950 free_obj(obj);
951 free(name);
952 return -1;
955 static struct isl_obj stored_obj(struct isl_ctx *ctx,
956 struct isl_hash_table *table, char *name)
958 struct isl_obj obj = { isl_obj_none, NULL };
959 struct isl_hash_table_entry *entry;
960 uint32_t name_hash;
962 name_hash = isl_hash_string(isl_hash_init(), name);
963 entry = isl_hash_table_find(ctx, table, name_hash, same_name, name, 0);
964 if (entry) {
965 struct isl_named_obj *named;
966 named = entry->data;
967 obj = named->obj;
968 } else if (isdigit(name[0]))
969 fprintf(stderr, "unknown identifier '$%s'\n", name);
970 else
971 fprintf(stderr, "unknown identifier '%s'\n", name);
973 free(name);
974 obj.v = obj.type->copy(obj.v);
975 return obj;
978 static int is_subtype(struct isl_obj obj, isl_obj_type super)
980 if (obj.type == super)
981 return 1;
982 if (obj.type == isl_obj_map && super == isl_obj_union_map)
983 return 1;
984 if (obj.type == isl_obj_set && super == isl_obj_union_set)
985 return 1;
986 if (obj.type == isl_obj_pw_multi_aff && super == isl_obj_union_set) {
987 isl_space *space = isl_pw_multi_aff_get_space(obj.v);
988 int is_set = isl_space_is_set(space);
989 isl_space_free(space);
990 return is_set;
992 if (obj.type == isl_obj_pw_qpolynomial &&
993 super == isl_obj_union_pw_qpolynomial)
994 return 1;
995 if (obj.type == isl_obj_pw_qpolynomial_fold &&
996 super == isl_obj_union_pw_qpolynomial_fold)
997 return 1;
998 if (obj.type == isl_obj_union_set && isl_union_set_is_empty(obj.v))
999 return 1;
1000 if (obj.type == isl_obj_list) {
1001 struct isl_list *list = obj.v;
1002 if (list->n == 2 && list->obj[1].type == isl_obj_bool)
1003 return is_subtype(list->obj[0], super);
1005 if (super == isl_obj_str)
1006 return 1;
1007 return 0;
1010 static struct isl_obj obj_at(struct isl_obj obj, int i)
1012 struct isl_list *list = obj.v;
1014 obj = list->obj[i];
1015 obj.v = obj.type->copy(obj.v);
1017 isl_list_free(list);
1019 return obj;
1022 static struct isl_obj convert(isl_ctx *ctx, struct isl_obj obj,
1023 isl_obj_type type)
1025 if (obj.type == type)
1026 return obj;
1027 if (obj.type == isl_obj_pw_multi_aff && type == isl_obj_union_set) {
1028 isl_set *set = isl_set_from_pw_multi_aff(obj.v);
1029 obj.type = isl_obj_union_set;
1030 obj.v = isl_union_set_from_set(set);
1031 return obj;
1033 if (obj.type == isl_obj_map && type == isl_obj_union_map) {
1034 obj.type = isl_obj_union_map;
1035 obj.v = isl_union_map_from_map(obj.v);
1036 return obj;
1038 if (obj.type == isl_obj_set && type == isl_obj_union_set) {
1039 obj.type = isl_obj_union_set;
1040 obj.v = isl_union_set_from_set(obj.v);
1041 return obj;
1043 if (obj.type == isl_obj_pw_qpolynomial &&
1044 type == isl_obj_union_pw_qpolynomial) {
1045 obj.type = isl_obj_union_pw_qpolynomial;
1046 obj.v = isl_union_pw_qpolynomial_from_pw_qpolynomial(obj.v);
1047 return obj;
1049 if (obj.type == isl_obj_pw_qpolynomial_fold &&
1050 type == isl_obj_union_pw_qpolynomial_fold) {
1051 obj.type = isl_obj_union_pw_qpolynomial_fold;
1052 obj.v = isl_union_pw_qpolynomial_fold_from_pw_qpolynomial_fold(obj.v);
1053 return obj;
1055 if (obj.type == isl_obj_union_set && isl_union_set_is_empty(obj.v)) {
1056 if (type == isl_obj_union_map) {
1057 obj.type = isl_obj_union_map;
1058 return obj;
1060 if (type == isl_obj_union_pw_qpolynomial) {
1061 isl_space *dim = isl_union_set_get_space(obj.v);
1062 isl_union_set_free(obj.v);
1063 obj.v = isl_union_pw_qpolynomial_zero(dim);
1064 obj.type = isl_obj_union_pw_qpolynomial;
1065 return obj;
1067 if (type == isl_obj_union_pw_qpolynomial_fold) {
1068 isl_space *dim = isl_union_set_get_space(obj.v);
1069 isl_union_set_free(obj.v);
1070 obj.v = isl_union_pw_qpolynomial_fold_zero(dim,
1071 isl_fold_list);
1072 obj.type = isl_obj_union_pw_qpolynomial_fold;
1073 return obj;
1076 if (obj.type == isl_obj_list) {
1077 struct isl_list *list = obj.v;
1078 if (list->n == 2 && list->obj[1].type == isl_obj_bool)
1079 return convert(ctx, obj_at(obj, 0), type);
1081 if (type == isl_obj_str) {
1082 isl_str *str;
1083 isl_printer *p;
1084 char *s;
1086 p = isl_printer_to_str(ctx);
1087 if (!p)
1088 goto error;
1089 p = obj.type->print(p, obj.v);
1090 s = isl_printer_get_str(p);
1091 isl_printer_free(p);
1093 str = isl_str_from_string(ctx, s);
1094 if (!str)
1095 goto error;
1096 free_obj(obj);
1097 obj.v = str;
1098 obj.type = isl_obj_str;
1099 return obj;
1102 error:
1103 free_obj(obj);
1104 obj.type = isl_obj_none;
1105 obj.v = NULL;
1106 return obj;
1109 static struct isc_bin_op *read_bin_op_if_available(struct isl_stream *s,
1110 struct isl_obj lhs)
1112 int i;
1113 struct isl_token *tok;
1115 tok = isl_stream_next_token(s);
1116 if (!tok)
1117 return NULL;
1119 for (i = 0; ; ++i) {
1120 if (!bin_ops[i].op)
1121 break;
1122 if (bin_ops[i].op != isl_token_get_type(tok))
1123 continue;
1124 if (!is_subtype(lhs, bin_ops[i].lhs))
1125 continue;
1127 isl_token_free(tok);
1128 return &bin_ops[i];
1131 for (i = 0; ; ++i) {
1132 if (!named_bin_ops[i].name)
1133 break;
1134 if (named_bin_ops[i].op.op != isl_token_get_type(tok))
1135 continue;
1136 if (!is_subtype(lhs, named_bin_ops[i].op.lhs))
1137 continue;
1139 isl_token_free(tok);
1140 return &named_bin_ops[i].op;
1143 isl_stream_push_token(s, tok);
1145 return NULL;
1148 static struct isc_un_op *read_prefix_un_op_if_available(struct isl_stream *s)
1150 int i;
1151 struct isl_token *tok;
1153 tok = isl_stream_next_token(s);
1154 if (!tok)
1155 return NULL;
1157 for (i = 0; ; ++i) {
1158 if (!named_un_ops[i].name)
1159 break;
1160 if (named_un_ops[i].op.op != isl_token_get_type(tok))
1161 continue;
1163 isl_token_free(tok);
1164 return &named_un_ops[i].op;
1167 isl_stream_push_token(s, tok);
1169 return NULL;
1172 static struct isc_un_op *find_matching_un_op(struct isc_un_op *like,
1173 struct isl_obj arg)
1175 int i;
1177 for (i = 0; ; ++i) {
1178 if (!named_un_ops[i].name)
1179 break;
1180 if (named_un_ops[i].op.op != like->op)
1181 continue;
1182 if (!is_subtype(arg, named_un_ops[i].op.arg))
1183 continue;
1185 return &named_un_ops[i].op;
1188 return NULL;
1191 static int is_assign(struct isl_stream *s)
1193 struct isl_token *tok;
1194 struct isl_token *tok2;
1195 int assign;
1197 tok = isl_stream_next_token(s);
1198 if (!tok)
1199 return 0;
1200 if (isl_token_get_type(tok) != ISL_TOKEN_IDENT) {
1201 isl_stream_push_token(s, tok);
1202 return 0;
1205 tok2 = isl_stream_next_token(s);
1206 if (!tok2) {
1207 isl_stream_push_token(s, tok);
1208 return 0;
1210 assign = isl_token_get_type(tok2) == ISL_TOKEN_DEF;
1211 isl_stream_push_token(s, tok2);
1212 isl_stream_push_token(s, tok);
1214 return assign;
1217 static struct isl_obj read_obj(struct isl_stream *s,
1218 struct isl_hash_table *table);
1219 static struct isl_obj read_expr(struct isl_stream *s,
1220 struct isl_hash_table *table);
1222 static struct isl_obj read_un_op_expr(struct isl_stream *s,
1223 struct isl_hash_table *table, struct isc_un_op *op)
1225 isl_ctx *ctx;
1226 struct isl_obj obj = { isl_obj_none, NULL };
1228 obj = read_obj(s, table);
1229 if (!obj.v)
1230 goto error;
1232 op = find_matching_un_op(op, obj);
1234 ctx = isl_stream_get_ctx(s);
1235 if (!op)
1236 isl_die(ctx, isl_error_invalid,
1237 "no such unary operator defined on given operand",
1238 goto error);
1240 obj = convert(ctx, obj, op->arg);
1241 obj.v = op->fn(obj.v);
1242 obj.type = op->res;
1244 return obj;
1245 error:
1246 free_obj(obj);
1247 obj.type = isl_obj_none;
1248 obj.v = NULL;
1249 return obj;
1252 static struct isl_obj transitive_closure(struct isl_ctx *ctx, struct isl_obj obj)
1254 struct isl_list *list;
1255 int exact;
1257 if (obj.type != isl_obj_union_map)
1258 obj = convert(ctx, obj, isl_obj_union_map);
1259 isl_assert(ctx, obj.type == isl_obj_union_map, goto error);
1260 list = isl_list_alloc(ctx, 2);
1261 if (!list)
1262 goto error;
1264 list->obj[0].type = isl_obj_union_map;
1265 list->obj[0].v = isl_union_map_transitive_closure(obj.v, &exact);
1266 list->obj[1].type = isl_obj_bool;
1267 list->obj[1].v = exact ? &isl_bool_true : &isl_bool_false;
1268 obj.v = list;
1269 obj.type = isl_obj_list;
1270 if (exact < 0 || !list->obj[0].v)
1271 goto error;
1273 return obj;
1274 error:
1275 free_obj(obj);
1276 obj.type = isl_obj_none;
1277 obj.v = NULL;
1278 return obj;
1281 static struct isl_obj obj_at_index(struct isl_stream *s, struct isl_obj obj)
1283 struct isl_list *list = obj.v;
1284 struct isl_token *tok;
1285 isl_ctx *ctx;
1286 isl_val *v;
1287 int i;
1289 tok = isl_stream_next_token(s);
1290 if (!tok || isl_token_get_type(tok) != ISL_TOKEN_VALUE) {
1291 isl_stream_error(s, tok, "expecting index");
1292 if (tok)
1293 isl_stream_push_token(s, tok);
1294 goto error;
1296 ctx = isl_stream_get_ctx(s);
1297 v = isl_token_get_val(ctx, tok);
1298 i = isl_val_get_num_si(v);
1299 isl_val_free(v);
1300 isl_token_free(tok);
1301 isl_assert(ctx, i < list->n, goto error);
1302 if (isl_stream_eat(s, ']'))
1303 goto error;
1305 return obj_at(obj, i);
1306 error:
1307 free_obj(obj);
1308 obj.type = isl_obj_none;
1309 obj.v = NULL;
1310 return obj;
1313 static struct isl_obj apply(struct isl_stream *s, __isl_take isl_union_map *umap,
1314 struct isl_hash_table *table)
1316 isl_ctx *ctx;
1317 struct isl_obj obj;
1319 obj = read_expr(s, table);
1320 ctx = isl_stream_get_ctx(s);
1321 isl_assert(ctx, is_subtype(obj, isl_obj_union_set) ||
1322 is_subtype(obj, isl_obj_union_map), goto error);
1324 if (obj.type == isl_obj_list) {
1325 struct isl_list *list = obj.v;
1326 if (list->n == 2 && list->obj[1].type == isl_obj_bool)
1327 obj = obj_at(obj, 0);
1329 if (obj.type == isl_obj_set)
1330 obj = convert(ctx, obj, isl_obj_union_set);
1331 else if (obj.type == isl_obj_map)
1332 obj = convert(ctx, obj, isl_obj_union_map);
1333 if (obj.type == isl_obj_union_set) {
1334 obj.v = isl_union_set_apply(obj.v, umap);
1335 } else
1336 obj.v = isl_union_map_apply_range(obj.v, umap);
1337 if (!obj.v)
1338 goto error2;
1340 if (isl_stream_eat(s, ')'))
1341 goto error2;
1343 return obj;
1344 error:
1345 isl_union_map_free(umap);
1346 error2:
1347 free_obj(obj);
1348 obj.type = isl_obj_none;
1349 obj.v = NULL;
1350 return obj;
1353 static struct isl_obj apply_fun_set(struct isl_obj obj,
1354 __isl_take isl_union_set *uset)
1356 if (obj.type == isl_obj_union_pw_qpolynomial) {
1357 obj.v = isl_union_set_apply_union_pw_qpolynomial(uset, obj.v);
1358 } else {
1359 obj.type = isl_obj_list;
1360 obj.v = union_set_apply_union_pw_qpolynomial_fold(uset, obj.v);
1362 return obj;
1365 static struct isl_obj apply_fun_map(struct isl_obj obj,
1366 __isl_take isl_union_map *umap)
1368 if (obj.type == isl_obj_union_pw_qpolynomial) {
1369 obj.v = isl_union_map_apply_union_pw_qpolynomial(umap, obj.v);
1370 } else {
1371 obj.type = isl_obj_list;
1372 obj.v = union_map_apply_union_pw_qpolynomial_fold(umap, obj.v);
1374 return obj;
1377 static struct isl_obj apply_fun(struct isl_stream *s,
1378 struct isl_obj obj, struct isl_hash_table *table)
1380 struct isl_obj arg;
1381 isl_ctx *ctx;
1383 arg = read_expr(s, table);
1384 ctx = isl_stream_get_ctx(s);
1385 if (!is_subtype(arg, isl_obj_union_map) &&
1386 !is_subtype(arg, isl_obj_union_set))
1387 isl_die(ctx, isl_error_invalid,
1388 "expecting set of map argument", goto error);
1390 if (arg.type == isl_obj_list) {
1391 struct isl_list *list = arg.v;
1392 if (list->n == 2 && list->obj[1].type == isl_obj_bool)
1393 arg = obj_at(arg, 0);
1395 if (arg.type == isl_obj_set)
1396 arg = convert(ctx, arg, isl_obj_union_set);
1397 else if (arg.type == isl_obj_map)
1398 arg = convert(ctx, arg, isl_obj_union_map);
1399 if (arg.type == isl_obj_union_set)
1400 obj = apply_fun_set(obj, arg.v);
1401 else
1402 obj = apply_fun_map(obj, arg.v);
1403 if (!obj.v)
1404 goto error2;
1406 if (isl_stream_eat(s, ')'))
1407 goto error2;
1409 return obj;
1410 error:
1411 free_obj(arg);
1412 error2:
1413 free_obj(obj);
1414 obj.type = isl_obj_none;
1415 obj.v = NULL;
1416 return obj;
1419 struct add_vertex_data {
1420 struct isl_list *list;
1421 int i;
1424 static int add_vertex(__isl_take isl_vertex *vertex, void *user)
1426 struct add_vertex_data *data = (struct add_vertex_data *)user;
1427 isl_multi_aff *ma;
1428 isl_set *dom;
1430 ma = isl_vertex_get_expr(vertex);
1431 dom = isl_set_from_basic_set(isl_vertex_get_domain(vertex));
1433 data->list->obj[data->i].type = isl_obj_pw_multi_aff;
1434 data->list->obj[data->i].v = isl_pw_multi_aff_alloc(dom, ma);
1435 data->i++;
1437 isl_vertex_free(vertex);
1439 return 0;
1442 static int set_vertices(__isl_take isl_set *set, void *user)
1444 isl_ctx *ctx;
1445 isl_basic_set *hull;
1446 isl_vertices *vertices = NULL;
1447 struct isl_list *list = NULL;
1448 int r;
1449 struct add_vertex_data *data = (struct add_vertex_data *)user;
1451 set = isl_set_remove_divs(set);
1452 hull = isl_set_convex_hull(set);
1453 vertices = isl_basic_set_compute_vertices(hull);
1454 isl_basic_set_free(hull);
1456 list = data->list;
1458 ctx = isl_vertices_get_ctx(vertices);
1459 data->list = isl_list_alloc(ctx, isl_vertices_get_n_vertices(vertices));
1460 if (!data->list)
1461 goto error;
1463 data->i = 0;
1464 r = isl_vertices_foreach_vertex(vertices, &add_vertex, user);
1466 data->list = isl_list_concat(list, data->list);
1468 isl_vertices_free(vertices);
1470 return r;
1471 error:
1472 data->list = list;
1473 isl_vertices_free(vertices);
1474 return -1;
1477 static struct isl_obj vertices(struct isl_stream *s,
1478 struct isl_hash_table *table)
1480 isl_ctx *ctx;
1481 struct isl_obj obj;
1482 struct isl_list *list = NULL;
1483 isl_union_set *uset = NULL;
1484 struct add_vertex_data data = { NULL };
1486 obj = read_expr(s, table);
1487 ctx = isl_stream_get_ctx(s);
1488 obj = convert(ctx, obj, isl_obj_union_set);
1489 isl_assert(ctx, obj.type == isl_obj_union_set, goto error);
1490 uset = obj.v;
1491 obj.v = NULL;
1493 list = isl_list_alloc(ctx, 0);
1494 if (!list)
1495 goto error;
1497 data.list = list;
1499 if (isl_union_set_foreach_set(uset, &set_vertices, &data) < 0)
1500 goto error;
1502 isl_union_set_free(uset);
1504 obj.type = isl_obj_list;
1505 obj.v = data.list;
1507 return obj;
1508 error:
1509 isl_union_set_free(uset);
1510 isl_list_free(data.list);
1511 free_obj(obj);
1512 obj.type = isl_obj_none;
1513 obj.v = NULL;
1514 return obj;
1517 static struct isl_obj type_of(struct isl_stream *s,
1518 struct isl_hash_table *table)
1520 isl_ctx *ctx;
1521 struct isl_obj obj;
1522 const char *type = "unknown";
1524 obj = read_expr(s, table);
1526 if (obj.type == isl_obj_map ||
1527 obj.type == isl_obj_union_map)
1528 type = "map";
1529 if (obj.type == isl_obj_set ||
1530 obj.type == isl_obj_union_set)
1531 type = "set";
1532 if (obj.type == isl_obj_pw_multi_aff)
1533 type = "piecewise multi-quasiaffine expression";
1534 if (obj.type == isl_obj_pw_qpolynomial ||
1535 obj.type == isl_obj_union_pw_qpolynomial)
1536 type = "piecewise quasipolynomial";
1537 if (obj.type == isl_obj_pw_qpolynomial_fold ||
1538 obj.type == isl_obj_union_pw_qpolynomial_fold)
1539 type = "piecewise quasipolynomial fold";
1540 if (obj.type == isl_obj_list)
1541 type = "list";
1542 if (obj.type == isl_obj_bool)
1543 type = "boolean";
1544 if (obj.type == isl_obj_str)
1545 type = "string";
1546 if (obj.type == isl_obj_val)
1547 type = "value";
1549 free_obj(obj);
1550 obj.type = isl_obj_str;
1551 obj.v = isl_str_from_string(isl_stream_get_ctx(s), strdup(type));
1553 return obj;
1556 static __isl_give isl_union_set *read_set(struct isl_stream *s,
1557 struct isl_hash_table *table)
1559 struct isl_obj obj;
1560 isl_ctx *ctx;
1562 obj = read_obj(s, table);
1563 ctx = isl_stream_get_ctx(s);
1564 obj = convert(ctx, obj, isl_obj_union_set);
1565 isl_assert(ctx, obj.type == isl_obj_union_set, goto error);
1566 return obj.v;
1567 error:
1568 free_obj(obj);
1569 return NULL;
1572 static __isl_give isl_union_map *read_map(struct isl_stream *s,
1573 struct isl_hash_table *table)
1575 struct isl_obj obj;
1576 isl_ctx *ctx;
1578 obj = read_obj(s, table);
1579 ctx = isl_stream_get_ctx(s);
1580 obj = convert(ctx, obj, isl_obj_union_map);
1581 isl_assert(ctx, obj.type == isl_obj_union_map, goto error);
1582 return obj.v;
1583 error:
1584 free_obj(obj);
1585 return NULL;
1588 static struct isl_obj last_any(struct isl_stream *s,
1589 struct isl_hash_table *table, __isl_take isl_union_map *must_source,
1590 __isl_take isl_union_map *may_source)
1592 struct isl_obj obj = { isl_obj_none, NULL };
1593 isl_union_map *sink = NULL;
1594 isl_union_map *schedule = NULL;
1595 isl_union_map *may_dep;
1596 isl_union_map *must_dep;
1598 if (isl_stream_eat(s, iscc_op[ISCC_BEFORE]))
1599 goto error;
1601 sink = read_map(s, table);
1602 if (!sink)
1603 goto error;
1605 if (isl_stream_eat(s, iscc_op[ISCC_UNDER]))
1606 goto error;
1608 schedule = read_map(s, table);
1609 if (!schedule)
1610 goto error;
1612 if (isl_union_map_compute_flow(sink, must_source, may_source,
1613 schedule, &must_dep, &may_dep,
1614 NULL, NULL) < 0)
1615 return obj;
1617 obj.type = isl_obj_union_map;
1618 obj.v = isl_union_map_union(must_dep, may_dep);
1620 return obj;
1621 error:
1622 isl_union_map_free(may_source);
1623 isl_union_map_free(must_source);
1624 isl_union_map_free(sink);
1625 isl_union_map_free(schedule);
1626 free_obj(obj);
1627 obj.type = isl_obj_none;
1628 obj.v = NULL;
1629 return obj;
1632 static struct isl_obj any(struct isl_stream *s, struct isl_hash_table *table)
1634 struct isl_obj obj = { isl_obj_none, NULL };
1635 isl_union_map *must_source = NULL;
1636 isl_union_map *may_source = NULL;
1637 isl_union_map *sink = NULL;
1638 isl_union_map *schedule = NULL;
1639 isl_union_map *may_dep;
1641 may_source = read_map(s, table);
1642 if (!may_source)
1643 goto error;
1645 if (isl_stream_eat_if_available(s, iscc_op[ISCC_LAST])) {
1646 must_source = read_map(s, table);
1647 if (!must_source)
1648 goto error;
1649 return last_any(s, table, must_source, may_source);
1652 if (isl_stream_eat(s, iscc_op[ISCC_BEFORE]))
1653 goto error;
1655 sink = read_map(s, table);
1656 if (!sink)
1657 goto error;
1659 if (isl_stream_eat(s, iscc_op[ISCC_UNDER]))
1660 goto error;
1662 schedule = read_map(s, table);
1663 if (!schedule)
1664 goto error;
1666 must_source = isl_union_map_empty(isl_union_map_get_space(sink));
1667 if (isl_union_map_compute_flow(sink, must_source, may_source,
1668 schedule, NULL, &may_dep,
1669 NULL, NULL) < 0)
1670 return obj;
1672 obj.type = isl_obj_union_map;
1673 obj.v = may_dep;
1675 return obj;
1676 error:
1677 isl_union_map_free(may_source);
1678 isl_union_map_free(must_source);
1679 isl_union_map_free(sink);
1680 isl_union_map_free(schedule);
1681 free_obj(obj);
1682 obj.type = isl_obj_none;
1683 obj.v = NULL;
1684 return obj;
1687 static struct isl_obj last(struct isl_stream *s, struct isl_hash_table *table)
1689 struct isl_obj obj = { isl_obj_none, NULL };
1690 struct isl_list *list = NULL;
1691 isl_union_map *must_source = NULL;
1692 isl_union_map *may_source = NULL;
1693 isl_union_map *sink = NULL;
1694 isl_union_map *schedule = NULL;
1695 isl_union_map *must_dep;
1696 isl_union_map *must_no_source;
1698 must_source = read_map(s, table);
1699 if (!must_source)
1700 goto error;
1702 if (isl_stream_eat_if_available(s, iscc_op[ISCC_ANY])) {
1703 may_source = read_map(s, table);
1704 if (!may_source)
1705 goto error;
1706 return last_any(s, table, must_source, may_source);
1709 list = isl_list_alloc(isl_stream_get_ctx(s), 2);
1710 if (!list)
1711 goto error;
1713 if (isl_stream_eat(s, iscc_op[ISCC_BEFORE]))
1714 goto error;
1716 sink = read_map(s, table);
1717 if (!sink)
1718 goto error;
1720 if (isl_stream_eat(s, iscc_op[ISCC_UNDER]))
1721 goto error;
1723 schedule = read_map(s, table);
1724 if (!schedule)
1725 goto error;
1727 may_source = isl_union_map_empty(isl_union_map_get_space(sink));
1728 if (isl_union_map_compute_flow(sink, must_source, may_source,
1729 schedule, &must_dep, NULL,
1730 &must_no_source, NULL) < 0) {
1731 isl_list_free(list);
1732 return obj;
1735 list->obj[0].type = isl_obj_union_map;
1736 list->obj[0].v = must_dep;
1737 list->obj[1].type = isl_obj_union_map;
1738 list->obj[1].v = must_no_source;
1740 obj.v = list;
1741 obj.type = isl_obj_list;
1743 return obj;
1744 error:
1745 isl_list_free(list);
1746 isl_union_map_free(may_source);
1747 isl_union_map_free(must_source);
1748 isl_union_map_free(sink);
1749 isl_union_map_free(schedule);
1750 free_obj(obj);
1751 obj.type = isl_obj_none;
1752 obj.v = NULL;
1753 return obj;
1756 static __isl_give isl_schedule *get_schedule(struct isl_stream *s,
1757 struct isl_hash_table *table)
1759 isl_union_set *domain;
1760 isl_union_map *validity;
1761 isl_union_map *proximity;
1763 domain = read_set(s, table);
1764 if (!domain)
1765 return NULL;
1767 validity = isl_union_map_empty(isl_union_set_get_space(domain));
1768 proximity = isl_union_map_empty(isl_union_set_get_space(domain));
1770 for (;;) {
1771 isl_union_map *umap;
1772 if (isl_stream_eat_if_available(s, iscc_op[ISCC_RESPECTING])) {
1773 umap = read_map(s, table);
1774 validity = isl_union_map_union(validity, umap);
1775 } else if (isl_stream_eat_if_available(s, iscc_op[ISCC_MINIMIZING])) {
1776 umap = read_map(s, table);
1777 proximity = isl_union_map_union(proximity, umap);
1778 } else
1779 break;
1782 return isl_union_set_compute_schedule(domain, validity, proximity);
1785 static struct isl_obj schedule(struct isl_stream *s,
1786 struct isl_hash_table *table)
1788 struct isl_obj obj = { isl_obj_none, NULL };
1789 isl_schedule *schedule;
1791 schedule = get_schedule(s, table);
1793 obj.v = isl_schedule_get_map(schedule);
1794 obj.type = isl_obj_union_map;
1796 isl_schedule_free(schedule);
1798 return obj;
1801 /* Read a schedule for code generation.
1802 * If the input is a set rather than a map, then we construct
1803 * an identity schedule on the given set.
1805 static __isl_give isl_union_map *get_codegen_schedule(struct isl_stream *s,
1806 struct isl_hash_table *table)
1808 struct isl_obj obj;
1809 isl_ctx *ctx;
1811 obj = read_obj(s, table);
1812 ctx = isl_stream_get_ctx(s);
1814 if (is_subtype(obj, isl_obj_union_map)) {
1815 obj = convert(ctx, obj, isl_obj_union_map);
1816 return obj.v;
1819 if (is_subtype(obj, isl_obj_union_set)) {
1820 obj = convert(ctx, obj, isl_obj_union_set);
1821 return isl_union_set_identity(obj.v);
1824 free_obj(obj);
1825 isl_die(ctx, isl_error_invalid, "expecting set or map", return NULL);
1828 /* Generate an AST for the given schedule and options and print
1829 * the AST on the printer.
1831 static __isl_give isl_printer *print_code(__isl_take isl_printer *p,
1832 __isl_take isl_union_map *schedule,
1833 __isl_take isl_union_map *options)
1835 isl_space *space;
1836 isl_set *context;
1837 isl_ast_build *build;
1838 isl_ast_node *tree;
1839 int format;
1841 space = isl_union_map_get_space(schedule);
1842 context = isl_set_universe(isl_space_params(space));
1844 build = isl_ast_build_from_context(context);
1845 build = isl_ast_build_set_options(build, options);
1846 tree = isl_ast_build_ast_from_schedule(build, schedule);
1847 isl_ast_build_free(build);
1849 if (!tree)
1850 return p;
1852 format = isl_printer_get_output_format(p);
1853 p = isl_printer_set_output_format(p, ISL_FORMAT_C);
1854 p = isl_printer_print_ast_node(p, tree);
1855 p = isl_printer_set_output_format(p, format);
1857 isl_ast_node_free(tree);
1859 return p;
1862 /* Perform the codegen operation.
1863 * In particular, read a schedule, check if the user has specified any options
1864 * and then generate an AST from the schedule (and options) and print it.
1866 static __isl_give isl_printer *codegen(struct isl_stream *s,
1867 struct isl_hash_table *table, __isl_take isl_printer *p)
1869 isl_union_map *schedule;
1870 isl_union_map *options;
1872 schedule = get_codegen_schedule(s, table);
1873 if (!schedule)
1874 return p;
1876 if (isl_stream_eat_if_available(s, iscc_op[ISCC_USING]))
1877 options = read_map(s, table);
1878 else
1879 options = isl_union_map_empty(
1880 isl_union_map_get_space(schedule));
1882 p = print_code(p, schedule, options);
1884 isl_stream_eat(s, ';');
1886 return p;
1889 static struct isl_obj band_list_to_obj_list(__isl_take isl_band_list *bands);
1891 static struct isl_obj band_to_obj_list(__isl_take isl_band *band)
1893 struct isl_obj obj = { isl_obj_none, NULL };
1894 isl_ctx *ctx = isl_band_get_ctx(band);
1895 struct isl_list *list;
1897 list = isl_list_alloc(ctx, 2);
1898 if (!list)
1899 goto error;
1901 obj.v = list;
1902 obj.type = isl_obj_list;
1904 list->obj[0].type = isl_obj_union_map;
1905 list->obj[0].v = isl_band_get_partial_schedule(band);
1907 if (isl_band_has_children(band)) {
1908 isl_band_list *children;
1910 children = isl_band_get_children(band);
1911 list->obj[1] = band_list_to_obj_list(children);
1912 } else {
1913 list->obj[1].type = isl_obj_list;
1914 list->obj[1].v = isl_list_alloc(ctx, 0);
1917 if (!list->obj[0].v || !list->obj[1].v)
1918 goto error;
1920 isl_band_free(band);
1922 return obj;
1923 error:
1924 isl_band_free(band);
1925 free_obj(obj);
1926 obj.type = isl_obj_none;
1927 obj.v = NULL;
1928 return obj;
1931 static struct isl_obj band_list_to_obj_list(__isl_take isl_band_list *bands)
1933 struct isl_obj obj = { isl_obj_none, NULL };
1934 isl_ctx *ctx = isl_band_list_get_ctx(bands);
1935 struct isl_list *list;
1936 int i, n;
1938 n = isl_band_list_n_band(bands);
1939 list = isl_list_alloc(ctx, n);
1940 if (!list)
1941 goto error;
1943 obj.v = list;
1944 obj.type = isl_obj_list;
1946 for (i = 0; i < n; ++i) {
1947 isl_band *band;
1949 band = isl_band_list_get_band(bands, i);
1950 list->obj[i] = band_to_obj_list(band);
1951 if (!list->obj[i].v)
1952 goto error;
1955 isl_band_list_free(bands);
1957 return obj;
1958 error:
1959 isl_band_list_free(bands);
1960 free_obj(obj);
1961 obj.type = isl_obj_none;
1962 obj.v = NULL;
1963 return obj;
1966 static struct isl_obj schedule_forest(struct isl_stream *s,
1967 struct isl_hash_table *table)
1969 struct isl_obj obj = { isl_obj_none, NULL };
1970 isl_schedule *schedule;
1971 isl_band_list *roots;
1973 schedule = get_schedule(s, table);
1974 if (!schedule)
1975 return obj;
1977 roots = isl_schedule_get_band_forest(schedule);
1978 isl_schedule_free(schedule);
1980 return band_list_to_obj_list(roots);
1983 static struct isl_obj power(struct isl_stream *s, struct isl_obj obj)
1985 struct isl_token *tok;
1986 isl_ctx *ctx;
1987 isl_val *v;
1989 ctx = isl_stream_get_ctx(s);
1990 if (isl_stream_eat_if_available(s, '+'))
1991 return transitive_closure(ctx, obj);
1993 isl_assert(ctx, is_subtype(obj, isl_obj_union_map), goto error);
1994 if (obj.type != isl_obj_union_map)
1995 obj = convert(ctx, obj, isl_obj_union_map);
1997 tok = isl_stream_next_token(s);
1998 if (!tok || isl_token_get_type(tok) != ISL_TOKEN_VALUE) {
1999 isl_stream_error(s, tok, "expecting integer exponent");
2000 if (tok)
2001 isl_stream_push_token(s, tok);
2002 goto error;
2005 v = isl_token_get_val(ctx, tok);
2006 if (isl_val_is_zero(v)) {
2007 isl_stream_error(s, tok, "expecting non-zero exponent");
2008 isl_val_free(v);
2009 if (tok)
2010 isl_stream_push_token(s, tok);
2011 goto error;
2014 obj.v = isl_union_map_fixed_power_val(obj.v, v);
2015 isl_token_free(tok);
2016 if (!obj.v)
2017 goto error;
2019 return obj;
2020 error:
2021 free_obj(obj);
2022 obj.type = isl_obj_none;
2023 obj.v = NULL;
2024 return obj;
2027 static struct isl_obj check_assert(struct isl_stream *s,
2028 struct isl_hash_table *table)
2030 struct isl_obj obj;
2031 isl_ctx *ctx;
2033 obj = read_expr(s, table);
2034 ctx = isl_stream_get_ctx(s);
2035 if (obj.type != isl_obj_bool)
2036 isl_die(ctx, isl_error_invalid,
2037 "expecting boolean expression", goto error);
2038 if (obj.v != &isl_bool_true)
2039 isl_die(ctx, isl_error_unknown,
2040 "assertion failed", abort());
2041 error:
2042 free_obj(obj);
2043 obj.type = isl_obj_none;
2044 obj.v = NULL;
2045 return obj;
2048 static struct isl_obj read_from_file(struct isl_stream *s)
2050 isl_ctx *ctx;
2051 struct isl_obj obj;
2052 struct isl_token *tok;
2053 struct isl_stream *s_file;
2054 struct iscc_options *options;
2055 char *name;
2056 FILE *file;
2058 tok = isl_stream_next_token(s);
2059 if (!tok || isl_token_get_type(tok) != ISL_TOKEN_STRING) {
2060 isl_stream_error(s, tok, "expecting filename");
2061 isl_token_free(tok);
2062 goto error;
2065 ctx = isl_stream_get_ctx(s);
2066 options = isl_ctx_peek_iscc_options(ctx);
2067 if (!options || !options->io) {
2068 isl_token_free(tok);
2069 isl_die(ctx, isl_error_invalid,
2070 "read operation not allowed", goto error);
2073 name = isl_token_get_str(ctx, tok);
2074 isl_token_free(tok);
2075 file = fopen(name, "r");
2076 free(name);
2077 isl_assert(ctx, file, goto error);
2079 s_file = isl_stream_new_file(ctx, file);
2080 if (!s_file) {
2081 fclose(file);
2082 goto error;
2085 obj = isl_stream_read_obj(s_file);
2087 isl_stream_free(s_file);
2088 fclose(file);
2090 return obj;
2091 error:
2092 obj.type = isl_obj_none;
2093 obj.v = NULL;
2094 return obj;
2097 static struct isl_obj write_to_file(struct isl_stream *s,
2098 struct isl_hash_table *table)
2100 struct isl_obj obj;
2101 struct isl_token *tok;
2102 struct isl_stream *s_file;
2103 struct iscc_options *options;
2104 char *name;
2105 FILE *file;
2106 isl_ctx *ctx;
2107 isl_printer *p;
2109 tok = isl_stream_next_token(s);
2110 if (!tok || isl_token_get_type(tok) != ISL_TOKEN_STRING) {
2111 isl_stream_error(s, tok, "expecting filename");
2112 isl_token_free(tok);
2113 goto error;
2116 obj = read_expr(s, table);
2118 ctx = isl_stream_get_ctx(s);
2119 options = isl_ctx_peek_iscc_options(ctx);
2120 if (!options || !options->io) {
2121 isl_token_free(tok);
2122 isl_die(ctx, isl_error_invalid,
2123 "write operation not allowed", goto error);
2126 name = isl_token_get_str(ctx, tok);
2127 isl_token_free(tok);
2128 file = fopen(name, "w");
2129 free(name);
2130 if (!file)
2131 isl_die(ctx, isl_error_unknown,
2132 "could not open file for writing", goto error);
2134 p = isl_printer_to_file(ctx, file);
2135 p = isl_printer_set_output_format(p, options->format);
2136 p = obj.type->print(p, obj.v);
2137 p = isl_printer_end_line(p);
2138 isl_printer_free(p);
2140 fclose(file);
2141 error:
2142 free_obj(obj);
2143 obj.type = isl_obj_none;
2144 obj.v = NULL;
2145 return obj;
2148 static struct isl_obj read_string_if_available(struct isl_stream *s)
2150 struct isl_token *tok;
2151 struct isl_obj obj = { isl_obj_none, NULL };
2153 tok = isl_stream_next_token(s);
2154 if (!tok)
2155 return obj;
2156 if (isl_token_get_type(tok) == ISL_TOKEN_STRING) {
2157 isl_str *str;
2158 str = isl_str_alloc(isl_stream_get_ctx(s));
2159 if (!str)
2160 goto error;
2161 str->s = isl_token_get_str(isl_stream_get_ctx(s), tok);
2162 isl_token_free(tok);
2163 obj.v = str;
2164 obj.type = isl_obj_str;
2165 } else
2166 isl_stream_push_token(s, tok);
2167 return obj;
2168 error:
2169 isl_token_free(tok);
2170 return obj;
2173 static struct isl_obj read_bool_if_available(struct isl_stream *s)
2175 struct isl_token *tok;
2176 struct isl_obj obj = { isl_obj_none, NULL };
2177 int type;
2179 tok = isl_stream_next_token(s);
2180 if (!tok)
2181 return obj;
2182 type = isl_token_get_type(tok);
2183 if (type == ISL_TOKEN_FALSE || type == ISL_TOKEN_TRUE) {
2184 int is_true = type == ISL_TOKEN_TRUE;
2185 isl_token_free(tok);
2186 obj.v = is_true ? &isl_bool_true : &isl_bool_false;
2187 obj.type = isl_obj_bool;
2188 } else
2189 isl_stream_push_token(s, tok);
2190 return obj;
2193 static __isl_give char *read_ident(struct isl_stream *s)
2195 char *name;
2196 isl_val *v;
2197 struct isl_token *tok, *tok2;
2199 name = isl_stream_read_ident_if_available(s);
2200 if (name)
2201 return name;
2203 tok = isl_stream_next_token(s);
2204 if (!tok)
2205 return NULL;
2206 if (isl_token_get_type(tok) != '$') {
2207 isl_stream_push_token(s, tok);
2208 return NULL;
2210 tok2 = isl_stream_next_token(s);
2211 if (!tok2 || isl_token_get_type(tok2) != ISL_TOKEN_VALUE) {
2212 if (tok2)
2213 isl_stream_push_token(s, tok2);
2214 isl_stream_push_token(s, tok);
2215 return NULL;
2218 v = isl_token_get_val(isl_stream_get_ctx(s), tok2);
2219 name = isl_val_to_str(v);
2220 isl_val_free(v);
2221 isl_token_free(tok);
2222 isl_token_free(tok2);
2224 return name;
2227 static struct isl_obj read_list(struct isl_stream *s,
2228 struct isl_hash_table *table, struct isl_obj obj)
2230 struct isl_list *list;
2232 list = isl_list_alloc(isl_stream_get_ctx(s), 2);
2233 if (!list)
2234 goto error;
2235 list->obj[0] = obj;
2236 list->obj[1] = read_obj(s, table);
2237 obj.v = list;
2238 obj.type = isl_obj_list;
2240 if (!list->obj[1].v)
2241 goto error;
2243 while (isl_stream_eat_if_available(s, ',')) {
2244 obj.v = list = isl_list_add_obj(list, read_obj(s, table));
2245 if (!obj.v)
2246 goto error;
2249 return obj;
2250 error:
2251 free_obj(obj);
2252 obj.type = isl_obj_none;
2253 obj.v = NULL;
2254 return obj;
2257 static struct isl_obj read_obj(struct isl_stream *s,
2258 struct isl_hash_table *table)
2260 isl_ctx *ctx;
2261 struct isl_obj obj = { isl_obj_none, NULL };
2262 char *name = NULL;
2263 struct isc_un_op *op = NULL;
2265 obj = read_string_if_available(s);
2266 if (obj.v)
2267 return obj;
2268 obj = read_bool_if_available(s);
2269 if (obj.v)
2270 return obj;
2271 ctx = isl_stream_get_ctx(s);
2272 if (isl_stream_eat_if_available(s, '(')) {
2273 if (isl_stream_next_token_is(s, ')')) {
2274 obj.type = isl_obj_list;
2275 obj.v = isl_list_alloc(ctx, 0);
2276 } else {
2277 obj = read_expr(s, table);
2278 if (obj.v && isl_stream_eat_if_available(s, ','))
2279 obj = read_list(s, table, obj);
2281 if (!obj.v || isl_stream_eat(s, ')'))
2282 goto error;
2283 } else {
2284 op = read_prefix_un_op_if_available(s);
2285 if (op)
2286 return read_un_op_expr(s, table, op);
2288 if (isl_stream_eat_if_available(s, iscc_op[ISCC_ASSERT]))
2289 return check_assert(s, table);
2290 if (isl_stream_eat_if_available(s, iscc_op[ISCC_READ]))
2291 return read_from_file(s);
2292 if (isl_stream_eat_if_available(s, iscc_op[ISCC_WRITE]))
2293 return write_to_file(s, table);
2294 if (isl_stream_eat_if_available(s, iscc_op[ISCC_VERTICES]))
2295 return vertices(s, table);
2296 if (isl_stream_eat_if_available(s, iscc_op[ISCC_ANY]))
2297 return any(s, table);
2298 if (isl_stream_eat_if_available(s, iscc_op[ISCC_LAST]))
2299 return last(s, table);
2300 if (isl_stream_eat_if_available(s, iscc_op[ISCC_SCHEDULE]))
2301 return schedule(s, table);
2302 if (isl_stream_eat_if_available(s, iscc_op[ISCC_SCHEDULE_FOREST]))
2303 return schedule_forest(s, table);
2304 if (isl_stream_eat_if_available(s, iscc_op[ISCC_TYPEOF]))
2305 return type_of(s, table);
2307 name = read_ident(s);
2308 if (name)
2309 obj = stored_obj(ctx, table, name);
2310 else
2311 obj = isl_stream_read_obj(s);
2312 if (!obj.v)
2313 goto error;
2316 if (isl_stream_eat_if_available(s, '^'))
2317 obj = power(s, obj);
2318 else if (obj.type == isl_obj_list && isl_stream_eat_if_available(s, '['))
2319 obj = obj_at_index(s, obj);
2320 else if (is_subtype(obj, isl_obj_union_map) &&
2321 isl_stream_eat_if_available(s, '(')) {
2322 obj = convert(ctx, obj, isl_obj_union_map);
2323 obj = apply(s, obj.v, table);
2324 } else if (is_subtype(obj, isl_obj_union_pw_qpolynomial) &&
2325 isl_stream_eat_if_available(s, '(')) {
2326 obj = convert(ctx, obj, isl_obj_union_pw_qpolynomial);
2327 obj = apply_fun(s, obj, table);
2328 } else if (is_subtype(obj, isl_obj_union_pw_qpolynomial_fold) &&
2329 isl_stream_eat_if_available(s, '(')) {
2330 obj = convert(ctx, obj, isl_obj_union_pw_qpolynomial_fold);
2331 obj = apply_fun(s, obj, table);
2334 return obj;
2335 error:
2336 free_obj(obj);
2337 obj.type = isl_obj_none;
2338 obj.v = NULL;
2339 return obj;
2342 static struct isc_bin_op *find_matching_bin_op(struct isc_bin_op *like,
2343 struct isl_obj lhs, struct isl_obj rhs)
2345 int i;
2347 for (i = 0; ; ++i) {
2348 if (!bin_ops[i].op)
2349 break;
2350 if (bin_ops[i].op != like->op)
2351 continue;
2352 if (!is_subtype(lhs, bin_ops[i].lhs))
2353 continue;
2354 if (!is_subtype(rhs, bin_ops[i].rhs))
2355 continue;
2357 return &bin_ops[i];
2360 for (i = 0; ; ++i) {
2361 if (!named_bin_ops[i].name)
2362 break;
2363 if (named_bin_ops[i].op.op != like->op)
2364 continue;
2365 if (!is_subtype(lhs, named_bin_ops[i].op.lhs))
2366 continue;
2367 if (!is_subtype(rhs, named_bin_ops[i].op.rhs))
2368 continue;
2370 return &named_bin_ops[i].op;
2373 return NULL;
2376 static int next_is_neg_int(struct isl_stream *s)
2378 struct isl_token *tok;
2379 int ret;
2381 tok = isl_stream_next_token(s);
2382 if (tok && isl_token_get_type(tok) == ISL_TOKEN_VALUE) {
2383 isl_val *v;
2384 v = isl_token_get_val(isl_stream_get_ctx(s), tok);
2385 ret = isl_val_is_neg(v);
2386 isl_val_free(v);
2387 } else
2388 ret = 0;
2389 isl_stream_push_token(s, tok);
2391 return ret;
2394 static struct isl_obj call_bin_op(isl_ctx *ctx, struct isc_bin_op *op,
2395 struct isl_obj lhs, struct isl_obj rhs)
2397 struct isl_obj obj;
2399 lhs = convert(ctx, lhs, op->lhs);
2400 rhs = convert(ctx, rhs, op->rhs);
2401 if (op->res != isl_obj_bool)
2402 obj.v = op->o.fn(lhs.v, rhs.v);
2403 else {
2404 int res = op->o.test(lhs.v, rhs.v);
2405 free_obj(lhs);
2406 free_obj(rhs);
2407 obj.v = isl_bool_from_int(res);
2409 obj.type = op->res;
2411 return obj;
2414 static struct isl_obj read_expr(struct isl_stream *s,
2415 struct isl_hash_table *table)
2417 isl_ctx *ctx;
2418 struct isl_obj obj = { isl_obj_none, NULL };
2419 struct isl_obj right_obj = { isl_obj_none, NULL };
2421 obj = read_obj(s, table);
2422 ctx = isl_stream_get_ctx(s);
2423 for (; obj.v;) {
2424 struct isc_bin_op *op = NULL;
2426 op = read_bin_op_if_available(s, obj);
2427 if (!op)
2428 break;
2430 right_obj = read_obj(s, table);
2432 op = find_matching_bin_op(op, obj, right_obj);
2434 if (!op)
2435 isl_die(ctx, isl_error_invalid,
2436 "no such binary operator defined on given operands",
2437 goto error);
2439 obj = call_bin_op(ctx, op, obj, right_obj);
2442 if (obj.type == isl_obj_val && next_is_neg_int(s)) {
2443 right_obj = read_obj(s, table);
2444 obj.v = isl_val_add(obj.v, right_obj.v);
2447 return obj;
2448 error:
2449 free_obj(right_obj);
2450 free_obj(obj);
2451 obj.type = isl_obj_none;
2452 obj.v = NULL;
2453 return obj;
2456 static __isl_give isl_printer *source_file(struct isl_stream *s,
2457 struct isl_hash_table *table, __isl_take isl_printer *p);
2459 static __isl_give isl_printer *read_line(struct isl_stream *s,
2460 struct isl_hash_table *table, __isl_take isl_printer *p, int tty)
2462 isl_ctx *ctx;
2463 struct isl_obj obj = { isl_obj_none, NULL };
2464 char *lhs = NULL;
2465 int assign = 0;
2466 int only_print = 0;
2467 struct isc_bin_op *op = NULL;
2468 char buf[30];
2470 if (!p)
2471 return NULL;
2472 if (isl_stream_is_empty(s))
2473 return p;
2475 if (isl_stream_eat_if_available(s, iscc_op[ISCC_SOURCE]))
2476 return source_file(s, table, p);
2477 if (isl_stream_eat_if_available(s, iscc_op[ISCC_CODEGEN]))
2478 return codegen(s, table, p);
2480 assign = is_assign(s);
2481 if (assign) {
2482 lhs = isl_stream_read_ident_if_available(s);
2483 if (isl_stream_eat(s, ISL_TOKEN_DEF))
2484 goto error;
2485 } else if (isl_stream_eat_if_available(s, iscc_op[ISCC_PRINT]))
2486 only_print = 1;
2487 else if (!tty)
2488 only_print = 1;
2490 obj = read_expr(s, table);
2491 ctx = isl_stream_get_ctx(s);
2492 if (isl_ctx_last_error(ctx) == isl_error_abort) {
2493 fprintf(stderr, "Interrupted\n");
2494 isl_ctx_reset_error(ctx);
2496 if (isl_stream_eat(s, ';'))
2497 goto error;
2499 if (only_print) {
2500 if (obj.type != isl_obj_none && obj.v != NULL) {
2501 p = obj.type->print(p, obj.v);
2502 p = isl_printer_end_line(p);
2504 free_obj(obj);
2505 return p;
2507 if (!assign && obj.type != isl_obj_none && obj.v != NULL) {
2508 static int count = 0;
2509 snprintf(buf, sizeof(buf), "$%d", count++);
2510 lhs = strdup(buf + 1);
2512 p = isl_printer_print_str(p, buf);
2513 p = isl_printer_print_str(p, " := ");
2514 p = obj.type->print(p, obj.v);
2515 p = isl_printer_end_line(p);
2517 if (lhs && do_assign(ctx, table, lhs, obj))
2518 return p;
2520 return p;
2521 error:
2522 isl_stream_flush_tokens(s);
2523 isl_stream_skip_line(s);
2524 free(lhs);
2525 free_obj(obj);
2526 return p;
2529 int free_cb(void **entry, void *user)
2531 struct isl_named_obj *named = *entry;
2533 free_obj(named->obj);
2534 free(named->name);
2535 free(named);
2537 return 0;
2540 static void register_named_ops(struct isl_stream *s)
2542 int i;
2544 for (i = 0; i < ISCC_N_OP; ++i) {
2545 iscc_op[i] = isl_stream_register_keyword(s, op_name[i]);
2546 assert(iscc_op[i] != ISL_TOKEN_ERROR);
2549 for (i = 0; ; ++i) {
2550 if (!named_un_ops[i].name)
2551 break;
2552 named_un_ops[i].op.op = isl_stream_register_keyword(s,
2553 named_un_ops[i].name);
2554 assert(named_un_ops[i].op.op != ISL_TOKEN_ERROR);
2557 for (i = 0; ; ++i) {
2558 if (!named_bin_ops[i].name)
2559 break;
2560 named_bin_ops[i].op.op = isl_stream_register_keyword(s,
2561 named_bin_ops[i].name);
2562 assert(named_bin_ops[i].op.op != ISL_TOKEN_ERROR);
2566 static __isl_give isl_printer *source_file(struct isl_stream *s,
2567 struct isl_hash_table *table, __isl_take isl_printer *p)
2569 isl_ctx *ctx;
2570 struct isl_token *tok;
2571 struct isl_stream *s_file;
2572 struct iscc_options *options;
2573 char *name;
2574 FILE *file;
2576 tok = isl_stream_next_token(s);
2577 if (!tok || isl_token_get_type(tok) != ISL_TOKEN_STRING) {
2578 isl_stream_error(s, tok, "expecting filename");
2579 isl_token_free(tok);
2580 return p;
2583 isl_stream_eat(s, ';');
2585 ctx = isl_stream_get_ctx(s);
2586 options = isl_ctx_peek_iscc_options(ctx);
2587 if (!options || !options->io) {
2588 isl_token_free(tok);
2589 isl_die(ctx, isl_error_invalid,
2590 "source operation not allowed", return p);
2593 name = isl_token_get_str(ctx, tok);
2594 isl_token_free(tok);
2595 file = fopen(name, "r");
2596 free(name);
2597 isl_assert(ctx, file, return p);
2599 s_file = isl_stream_new_file(ctx, file);
2600 if (!s_file) {
2601 fclose(file);
2602 return p;
2605 register_named_ops(s_file);
2607 while (!isl_stream_is_empty(s_file))
2608 p = read_line(s_file, table, p, 0);
2610 isl_stream_free(s_file);
2611 fclose(file);
2613 return p;
2616 int main(int argc, char **argv)
2618 struct isl_ctx *ctx;
2619 struct isl_stream *s;
2620 struct isl_hash_table *table;
2621 struct iscc_options *options;
2622 isl_printer *p;
2623 int tty = isatty(0);
2625 options = iscc_options_new_with_defaults();
2626 assert(options);
2628 ctx = isl_ctx_alloc_with_options(&iscc_options_args, options);
2629 pet_options_set_autodetect(ctx, 1);
2630 argc = isl_ctx_parse_options(ctx, argc, argv, ISL_ARG_ALL);
2631 s = isl_stream_new_file(ctx, stdin);
2632 assert(s);
2633 table = isl_hash_table_alloc(ctx, 10);
2634 assert(table);
2635 p = isl_printer_to_file(ctx, stdout);
2636 p = isl_printer_set_output_format(p, options->format);
2637 assert(p);
2639 register_named_ops(s);
2641 install_signal_handler(ctx);
2643 while (p && !isl_stream_is_empty(s)) {
2644 isl_ctx_resume(ctx);
2645 p = read_line(s, table, p, tty);
2648 remove_signal_handler(ctx);
2650 isl_printer_free(p);
2651 isl_hash_table_foreach(ctx, table, free_cb, NULL);
2652 isl_hash_table_free(ctx, table);
2653 isl_stream_free(s);
2654 isl_ctx_free(ctx);
2656 return 0;