iscc.c: use isl_stream_get_ctx instead of reading ctx field of isl_stream
[barvinok/uuh.git] / iscc.c
blob88a8dd1962af10a750b956836d307bb4da63df78
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 struct isc_bin_op bin_ops[] = {
385 { '+', isl_obj_val, isl_obj_val, isl_obj_val,
386 (isc_bin_op_fn) &isl_val_add },
387 { '-', isl_obj_val, isl_obj_val, isl_obj_val,
388 (isc_bin_op_fn) &isl_val_sub },
389 { '*', isl_obj_val, isl_obj_val, isl_obj_val,
390 (isc_bin_op_fn) &isl_val_mul },
391 { '+', isl_obj_pw_multi_aff, isl_obj_pw_multi_aff,
392 isl_obj_pw_multi_aff,
393 (isc_bin_op_fn) &isl_pw_multi_aff_add },
394 { '+', isl_obj_union_set, isl_obj_union_set,
395 isl_obj_union_set,
396 (isc_bin_op_fn) &isl_union_set_union },
397 { '+', isl_obj_union_map, isl_obj_union_map,
398 isl_obj_union_map,
399 (isc_bin_op_fn) &isl_union_map_union },
400 { '-', isl_obj_union_set, isl_obj_union_set,
401 isl_obj_union_set,
402 (isc_bin_op_fn) &isl_union_set_subtract },
403 { '-', isl_obj_union_map, isl_obj_union_map,
404 isl_obj_union_map,
405 (isc_bin_op_fn) &isl_union_map_subtract },
406 { '*', isl_obj_union_set, isl_obj_union_set,
407 isl_obj_union_set,
408 (isc_bin_op_fn) &isl_union_set_intersect },
409 { '*', isl_obj_union_map, isl_obj_union_map,
410 isl_obj_union_map,
411 (isc_bin_op_fn) &isl_union_map_intersect },
412 { '*', isl_obj_union_map, isl_obj_union_set,
413 isl_obj_union_map,
414 (isc_bin_op_fn) &isl_union_map_intersect_domain },
415 { '.', isl_obj_union_map, isl_obj_union_map,
416 isl_obj_union_map,
417 (isc_bin_op_fn) &isl_union_map_apply_range },
418 { '.', isl_obj_union_map, isl_obj_union_pw_qpolynomial,
419 isl_obj_union_pw_qpolynomial,
420 (isc_bin_op_fn) &isl_union_map_apply_union_pw_qpolynomial },
421 { '.', isl_obj_union_map, isl_obj_union_pw_qpolynomial_fold,
422 isl_obj_list,
423 (isc_bin_op_fn) &union_map_apply_union_pw_qpolynomial_fold },
424 { ISL_TOKEN_TO, isl_obj_union_set, isl_obj_union_set,
425 isl_obj_union_map,
426 (isc_bin_op_fn) &isl_union_map_from_domain_and_range },
427 { '=', isl_obj_union_set, isl_obj_union_set, isl_obj_bool,
428 { .test = (isc_bin_test_fn) &isl_union_set_is_equal } },
429 { '=', isl_obj_union_map, isl_obj_union_map, isl_obj_bool,
430 { .test = (isc_bin_test_fn) &isl_union_map_is_equal } },
431 { ISL_TOKEN_LE, isl_obj_union_set, isl_obj_union_set,
432 isl_obj_bool,
433 { .test = (isc_bin_test_fn) &isl_union_set_is_subset } },
434 { ISL_TOKEN_LE, isl_obj_union_map, isl_obj_union_map,
435 isl_obj_bool,
436 { .test = (isc_bin_test_fn) &isl_union_map_is_subset } },
437 { ISL_TOKEN_LT, isl_obj_union_set, isl_obj_union_set,
438 isl_obj_bool,
439 { .test = (isc_bin_test_fn) &isl_union_set_is_strict_subset } },
440 { ISL_TOKEN_LT, isl_obj_union_map, isl_obj_union_map,
441 isl_obj_bool,
442 { .test = (isc_bin_test_fn) &isl_union_map_is_strict_subset } },
443 { ISL_TOKEN_GE, isl_obj_union_set, isl_obj_union_set,
444 isl_obj_bool,
445 { .test = (isc_bin_test_fn) &isl_union_set_is_superset } },
446 { ISL_TOKEN_GE, isl_obj_union_map, isl_obj_union_map,
447 isl_obj_bool,
448 { .test = (isc_bin_test_fn) &isl_union_map_is_superset } },
449 { ISL_TOKEN_GT, isl_obj_union_set, isl_obj_union_set,
450 isl_obj_bool,
451 { .test =
452 (isc_bin_test_fn) &isl_union_set_is_strict_superset } },
453 { ISL_TOKEN_GT, isl_obj_union_map, isl_obj_union_map,
454 isl_obj_bool,
455 { .test =
456 (isc_bin_test_fn) &isl_union_map_is_strict_superset } },
457 { ISL_TOKEN_LEX_LE, isl_obj_union_set, isl_obj_union_set,
458 isl_obj_union_map,
459 (isc_bin_op_fn) &isl_union_set_lex_le_union_set },
460 { ISL_TOKEN_LEX_LT, isl_obj_union_set, isl_obj_union_set,
461 isl_obj_union_map,
462 (isc_bin_op_fn) &isl_union_set_lex_lt_union_set },
463 { ISL_TOKEN_LEX_GE, isl_obj_union_set, isl_obj_union_set,
464 isl_obj_union_map,
465 (isc_bin_op_fn) &isl_union_set_lex_ge_union_set },
466 { ISL_TOKEN_LEX_GT, isl_obj_union_set, isl_obj_union_set,
467 isl_obj_union_map,
468 (isc_bin_op_fn) &isl_union_set_lex_gt_union_set },
469 { ISL_TOKEN_LEX_LE, isl_obj_union_map, isl_obj_union_map,
470 isl_obj_union_map,
471 (isc_bin_op_fn) &isl_union_map_lex_le_union_map },
472 { ISL_TOKEN_LEX_LT, isl_obj_union_map, isl_obj_union_map,
473 isl_obj_union_map,
474 (isc_bin_op_fn) &isl_union_map_lex_lt_union_map },
475 { ISL_TOKEN_LEX_GE, isl_obj_union_map, isl_obj_union_map,
476 isl_obj_union_map,
477 (isc_bin_op_fn) &isl_union_map_lex_ge_union_map },
478 { ISL_TOKEN_LEX_GT, isl_obj_union_map, isl_obj_union_map,
479 isl_obj_union_map,
480 (isc_bin_op_fn) &isl_union_map_lex_gt_union_map },
481 { '.', isl_obj_union_pw_qpolynomial_fold,
482 isl_obj_union_pw_qpolynomial_fold,
483 isl_obj_union_pw_qpolynomial_fold,
484 (isc_bin_op_fn) &isl_union_pw_qpolynomial_fold_fold },
485 { '+', isl_obj_union_pw_qpolynomial, isl_obj_union_pw_qpolynomial,
486 isl_obj_union_pw_qpolynomial,
487 (isc_bin_op_fn) &isl_union_pw_qpolynomial_add },
488 { '+', isl_obj_union_pw_qpolynomial,
489 isl_obj_union_pw_qpolynomial_fold,
490 isl_obj_union_pw_qpolynomial_fold,
491 (isc_bin_op_fn) &union_pw_qpolynomial_add_union_pw_qpolynomial_fold },
492 { '+', isl_obj_union_pw_qpolynomial_fold,
493 isl_obj_union_pw_qpolynomial,
494 isl_obj_union_pw_qpolynomial_fold,
495 (isc_bin_op_fn) &isl_union_pw_qpolynomial_fold_add_union_pw_qpolynomial },
496 { '-', isl_obj_union_pw_qpolynomial, isl_obj_union_pw_qpolynomial,
497 isl_obj_union_pw_qpolynomial,
498 (isc_bin_op_fn) &isl_union_pw_qpolynomial_sub },
499 { '*', isl_obj_val, isl_obj_union_pw_qpolynomial,
500 isl_obj_union_pw_qpolynomial,
501 (isc_bin_op_fn) &isl_val_mul_union_pw_qpolynomial },
502 { '*', isl_obj_union_pw_qpolynomial, isl_obj_val,
503 isl_obj_union_pw_qpolynomial,
504 (isc_bin_op_fn) &isl_union_pw_qpolynomial_scale_val },
505 { '*', isl_obj_val, isl_obj_union_pw_qpolynomial_fold,
506 isl_obj_union_pw_qpolynomial_fold,
507 (isc_bin_op_fn) &int_val_mul_union_pw_qpolynomial_fold },
508 { '*', isl_obj_union_pw_qpolynomial_fold, isl_obj_val,
509 isl_obj_union_pw_qpolynomial_fold,
510 (isc_bin_op_fn) &isl_union_pw_qpolynomial_fold_scale_val },
511 { '*', isl_obj_union_pw_qpolynomial, isl_obj_union_pw_qpolynomial,
512 isl_obj_union_pw_qpolynomial,
513 (isc_bin_op_fn) &isl_union_pw_qpolynomial_mul },
514 { '*', isl_obj_union_pw_qpolynomial, isl_obj_union_set,
515 isl_obj_union_pw_qpolynomial,
516 (isc_bin_op_fn) &isl_union_pw_qpolynomial_intersect_domain },
517 { '*', isl_obj_union_pw_qpolynomial_fold, isl_obj_union_set,
518 isl_obj_union_pw_qpolynomial_fold,
519 (isc_bin_op_fn) &isl_union_pw_qpolynomial_fold_intersect_domain },
520 { '@', isl_obj_union_pw_qpolynomial, isl_obj_union_set,
521 isl_obj_union_pw_qpolynomial,
522 (isc_bin_op_fn) &isl_union_pw_qpolynomial_at },
523 { '@', isl_obj_union_pw_qpolynomial_fold, isl_obj_union_set,
524 isl_obj_union_pw_qpolynomial,
525 (isc_bin_op_fn) &isl_union_pw_qpolynomial_fold_at },
526 { '%', isl_obj_union_set, isl_obj_union_set,
527 isl_obj_union_set,
528 (isc_bin_op_fn) &isl_union_set_gist },
529 { '%', isl_obj_union_map, isl_obj_union_map,
530 isl_obj_union_map,
531 (isc_bin_op_fn) &isl_union_map_gist },
532 { '%', isl_obj_union_map, isl_obj_union_set,
533 isl_obj_union_map,
534 (isc_bin_op_fn) &isl_union_map_gist_domain },
535 { '%', isl_obj_union_pw_qpolynomial, isl_obj_union_set,
536 isl_obj_union_pw_qpolynomial,
537 (isc_bin_op_fn) &isl_union_pw_qpolynomial_gist },
538 { '%', isl_obj_union_pw_qpolynomial_fold, isl_obj_union_set,
539 isl_obj_union_pw_qpolynomial_fold,
540 (isc_bin_op_fn) &isl_union_pw_qpolynomial_fold_gist },
541 { ISL_TOKEN_EQ_EQ, isl_obj_union_pw_qpolynomial,
542 isl_obj_union_pw_qpolynomial, isl_obj_bool,
543 { .test = (isc_bin_test_fn)
544 &isl_union_pw_qpolynomial_plain_is_equal } },
545 { ISL_TOKEN_EQ_EQ, isl_obj_union_pw_qpolynomial_fold,
546 isl_obj_union_pw_qpolynomial_fold, isl_obj_bool,
547 { .test = (isc_bin_test_fn)
548 &isl_union_pw_qpolynomial_fold_plain_is_equal } },
549 { '+', isl_obj_str, isl_obj_str, isl_obj_str,
550 (isc_bin_op_fn) &isl_str_concat },
554 static __isl_give isl_union_map *map_after_map(__isl_take isl_union_map *umap1,
555 __isl_take isl_union_map *umap2)
557 return isl_union_map_apply_range(umap2, umap1);
560 static __isl_give isl_union_pw_qpolynomial *qpolynomial_after_map(
561 __isl_take isl_union_pw_qpolynomial *upwqp,
562 __isl_take isl_union_map *umap)
564 return isl_union_map_apply_union_pw_qpolynomial(umap, upwqp);
567 static __isl_give struct isl_list *qpolynomial_fold_after_map(
568 __isl_take isl_union_pw_qpolynomial_fold *upwf,
569 __isl_take isl_union_map *umap)
571 return union_map_apply_union_pw_qpolynomial_fold(umap, upwf);
574 struct isc_named_bin_op named_bin_ops[] = {
575 { "after", { -1, isl_obj_union_map, isl_obj_union_map,
576 isl_obj_union_map,
577 (isc_bin_op_fn) &map_after_map } },
578 { "after", { -1, isl_obj_union_pw_qpolynomial,
579 isl_obj_union_map, isl_obj_union_pw_qpolynomial,
580 (isc_bin_op_fn) &qpolynomial_after_map } },
581 { "after", { -1, isl_obj_union_pw_qpolynomial_fold,
582 isl_obj_union_map, isl_obj_list,
583 (isc_bin_op_fn) &qpolynomial_fold_after_map } },
584 { "before", { -1, isl_obj_union_map, isl_obj_union_map,
585 isl_obj_union_map,
586 (isc_bin_op_fn) &isl_union_map_apply_range } },
587 { "before", { -1, isl_obj_union_map,
588 isl_obj_union_pw_qpolynomial, isl_obj_union_pw_qpolynomial,
589 (isc_bin_op_fn) &isl_union_map_apply_union_pw_qpolynomial } },
590 { "before", { -1, isl_obj_union_map,
591 isl_obj_union_pw_qpolynomial_fold, isl_obj_list,
592 (isc_bin_op_fn) &union_map_apply_union_pw_qpolynomial_fold } },
593 { "cross", { -1, isl_obj_union_set, isl_obj_union_set,
594 isl_obj_union_set,
595 (isc_bin_op_fn) &isl_union_set_product } },
596 { "cross", { -1, isl_obj_union_map, isl_obj_union_map,
597 isl_obj_union_map,
598 (isc_bin_op_fn) &isl_union_map_product } },
599 NULL
602 __isl_give isl_set *union_set_sample(__isl_take isl_union_set *uset)
604 return isl_set_from_basic_set(isl_union_set_sample(uset));
607 __isl_give isl_map *union_map_sample(__isl_take isl_union_map *umap)
609 return isl_map_from_basic_map(isl_union_map_sample(umap));
612 static __isl_give struct isl_list *union_map_power(
613 __isl_take isl_union_map *umap)
615 isl_ctx *ctx;
616 struct isl_list *list;
617 int exact;
619 ctx = isl_union_map_get_ctx(umap);
620 list = isl_list_alloc(ctx, 2);
621 if (!list)
622 goto error2;
624 list->obj[0].type = isl_obj_union_map;
625 list->obj[0].v = isl_union_map_power(umap, &exact);
626 list->obj[1].type = isl_obj_bool;
627 list->obj[1].v = exact ? &isl_bool_true : &isl_bool_false;
628 if (exact < 0 || !list->obj[0].v)
629 goto error;
631 return list;
632 error2:
633 isl_union_map_free(umap);
634 error:
635 isl_list_free(list);
636 return NULL;
639 static __isl_give struct isl_list *union_pw_qpolynomial_upper_bound(
640 __isl_take isl_union_pw_qpolynomial *upwqp)
642 isl_ctx *ctx;
643 struct isl_list *list;
644 int tight;
646 ctx = isl_union_pw_qpolynomial_get_ctx(upwqp);
647 list = isl_list_alloc(ctx, 2);
648 if (!list)
649 goto error2;
651 list->obj[0].type = isl_obj_union_pw_qpolynomial_fold;
652 list->obj[0].v = isl_union_pw_qpolynomial_bound(upwqp,
653 isl_fold_max, &tight);
654 list->obj[1].type = isl_obj_bool;
655 list->obj[1].v = tight ? &isl_bool_true : &isl_bool_false;
656 if (tight < 0 || !list->obj[0].v)
657 goto error;
659 return list;
660 error2:
661 isl_union_pw_qpolynomial_free(upwqp);
662 error:
663 isl_list_free(list);
664 return NULL;
667 #ifdef HAVE_PET
668 static __isl_give isl_list *parse(__isl_take isl_str *str)
670 isl_ctx *ctx;
671 struct isl_list *list;
672 struct pet_scop *scop;
673 isl_union_map *sched, *may_reads, *must_writes, *may_writes;
674 isl_union_set *domain;
675 struct iscc_options *options;
677 if (!str)
678 return NULL;
679 ctx = str->ctx;
681 options = isl_ctx_peek_iscc_options(ctx);
682 if (!options || !options->io) {
683 isl_str_free(str);
684 isl_die(ctx, isl_error_invalid,
685 "parse_file operation not allowed", return NULL);
688 list = isl_list_alloc(ctx, 5);
689 if (!list)
690 goto error;
692 scop = pet_scop_extract_from_C_source(ctx, str->s, NULL);
693 domain = pet_scop_collect_domains(scop);
694 sched = pet_scop_collect_schedule(scop);
695 may_reads = pet_scop_collect_may_reads(scop);
696 may_writes = pet_scop_collect_may_writes(scop);
697 must_writes = pet_scop_collect_must_writes(scop);
698 pet_scop_free(scop);
700 list->obj[0].type = isl_obj_union_set;
701 list->obj[0].v = domain;
702 list->obj[1].type = isl_obj_union_map;
703 list->obj[1].v = must_writes;
704 list->obj[2].type = isl_obj_union_map;
705 list->obj[2].v = may_writes;
706 list->obj[3].type = isl_obj_union_map;
707 list->obj[3].v = may_reads;
708 list->obj[4].type = isl_obj_union_map;
709 list->obj[4].v = sched;
711 if (!list->obj[0].v || !list->obj[1].v ||
712 !list->obj[2].v || !list->obj[3].v || !list->obj[4].v)
713 goto error;
715 isl_str_free(str);
716 return list;
717 error:
718 isl_list_free(list);
719 isl_str_free(str);
720 return NULL;
722 #endif
724 static int add_point(__isl_take isl_point *pnt, void *user)
726 isl_union_set **scan = (isl_union_set **) user;
728 *scan = isl_union_set_add_set(*scan, isl_set_from_point(pnt));
730 return 0;
733 static __isl_give isl_union_set *union_set_scan(__isl_take isl_union_set *uset)
735 isl_union_set *scan;
737 scan = isl_union_set_empty(isl_union_set_get_space(uset));
739 if (isl_union_set_foreach_point(uset, add_point, &scan) < 0) {
740 isl_union_set_free(scan);
741 return uset;
744 isl_union_set_free(uset);
745 return scan;
748 static __isl_give isl_union_map *union_map_scan(__isl_take isl_union_map *umap)
750 return isl_union_set_unwrap(union_set_scan(isl_union_map_wrap(umap)));
753 static __isl_give isl_union_pw_qpolynomial *union_pw_qpolynomial_poly(
754 __isl_take isl_union_pw_qpolynomial *upwqp)
756 return isl_union_pw_qpolynomial_to_polynomial(upwqp, 0);
759 static __isl_give isl_union_pw_qpolynomial *union_pw_qpolynomial_lpoly(
760 __isl_take isl_union_pw_qpolynomial *upwqp)
762 return isl_union_pw_qpolynomial_to_polynomial(upwqp, -1);
765 static __isl_give isl_union_pw_qpolynomial *union_pw_qpolynomial_upoly(
766 __isl_take isl_union_pw_qpolynomial *upwqp)
768 return isl_union_pw_qpolynomial_to_polynomial(upwqp, 1);
771 typedef void *(*isc_un_op_fn)(void *arg);
772 struct isc_un_op {
773 enum isl_token_type op;
774 isl_obj_type arg;
775 isl_obj_type res;
776 isc_un_op_fn fn;
778 struct isc_named_un_op {
779 char *name;
780 struct isc_un_op op;
782 struct isc_named_un_op named_un_ops[] = {
783 {"aff", { -1, isl_obj_union_map, isl_obj_union_map,
784 (isc_un_op_fn) &isl_union_map_affine_hull } },
785 {"aff", { -1, isl_obj_union_set, isl_obj_union_set,
786 (isc_un_op_fn) &isl_union_set_affine_hull } },
787 {"card", { -1, isl_obj_union_set,
788 isl_obj_union_pw_qpolynomial,
789 (isc_un_op_fn) &isl_union_set_card } },
790 {"card", { -1, isl_obj_union_map,
791 isl_obj_union_pw_qpolynomial,
792 (isc_un_op_fn) &isl_union_map_card } },
793 {"coalesce", { -1, isl_obj_union_set, isl_obj_union_set,
794 (isc_un_op_fn) &isl_union_set_coalesce } },
795 {"coalesce", { -1, isl_obj_union_map, isl_obj_union_map,
796 (isc_un_op_fn) &isl_union_map_coalesce } },
797 {"coalesce", { -1, isl_obj_union_pw_qpolynomial,
798 isl_obj_union_pw_qpolynomial,
799 (isc_un_op_fn) &isl_union_pw_qpolynomial_coalesce } },
800 {"coalesce", { -1, isl_obj_union_pw_qpolynomial_fold,
801 isl_obj_union_pw_qpolynomial_fold,
802 (isc_un_op_fn) &isl_union_pw_qpolynomial_fold_coalesce } },
803 {"coefficients", { -1, isl_obj_union_set,
804 isl_obj_union_set,
805 (isc_un_op_fn) &isl_union_set_coefficients } },
806 {"solutions", { -1, isl_obj_union_set, isl_obj_union_set,
807 (isc_un_op_fn) &isl_union_set_solutions } },
808 {"deltas", { -1, isl_obj_union_map, isl_obj_union_set,
809 (isc_un_op_fn) &isl_union_map_deltas } },
810 {"deltas_map", { -1, isl_obj_union_map, isl_obj_union_map,
811 (isc_un_op_fn) &isl_union_map_deltas_map } },
812 {"dom", { -1, isl_obj_union_map, isl_obj_union_set,
813 (isc_un_op_fn) &isl_union_map_domain } },
814 {"dom", { -1, isl_obj_union_pw_qpolynomial, isl_obj_union_set,
815 (isc_un_op_fn) &isl_union_pw_qpolynomial_domain } },
816 {"dom", { -1, isl_obj_union_pw_qpolynomial_fold,
817 isl_obj_union_set,
818 (isc_un_op_fn) &isl_union_pw_qpolynomial_fold_domain } },
819 {"domain", { -1, isl_obj_union_map, isl_obj_union_set,
820 (isc_un_op_fn) &isl_union_map_domain } },
821 {"domain", { -1, isl_obj_union_pw_qpolynomial,
822 isl_obj_union_set,
823 (isc_un_op_fn) &isl_union_pw_qpolynomial_domain } },
824 {"domain", { -1, isl_obj_union_pw_qpolynomial_fold,
825 isl_obj_union_set,
826 (isc_un_op_fn) &isl_union_pw_qpolynomial_fold_domain } },
827 {"domain_map", { -1, isl_obj_union_map, isl_obj_union_map,
828 (isc_un_op_fn) &isl_union_map_domain_map } },
829 {"ran", { -1, isl_obj_union_map, isl_obj_union_set,
830 (isc_un_op_fn) &isl_union_map_range } },
831 {"range", { -1, isl_obj_union_map, isl_obj_union_set,
832 (isc_un_op_fn) &isl_union_map_range } },
833 {"range_map", { -1, isl_obj_union_map, isl_obj_union_map,
834 (isc_un_op_fn) &isl_union_map_range_map } },
835 {"identity", { -1, isl_obj_union_set, isl_obj_union_map,
836 (isc_un_op_fn) &isl_union_set_identity } },
837 {"lattice_width", { -1, isl_obj_union_set,
838 isl_obj_union_pw_qpolynomial,
839 (isc_un_op_fn) &isl_union_set_lattice_width } },
840 {"lexmin", { -1, isl_obj_union_map, isl_obj_union_map,
841 (isc_un_op_fn) &isl_union_map_lexmin } },
842 {"lexmax", { -1, isl_obj_union_map, isl_obj_union_map,
843 (isc_un_op_fn) &isl_union_map_lexmax } },
844 {"lexmin", { -1, isl_obj_union_set, isl_obj_union_set,
845 (isc_un_op_fn) &isl_union_set_lexmin } },
846 {"lexmax", { -1, isl_obj_union_set, isl_obj_union_set,
847 (isc_un_op_fn) &isl_union_set_lexmax } },
848 {"lift", { -1, isl_obj_union_set, isl_obj_union_set,
849 (isc_un_op_fn) &isl_union_set_lift } },
850 {"params", { -1, isl_obj_union_map, isl_obj_set,
851 (isc_un_op_fn) &isl_union_map_params } },
852 {"params", { -1, isl_obj_union_set, isl_obj_set,
853 (isc_un_op_fn) &isl_union_set_params } },
854 {"poly", { -1, isl_obj_union_map, isl_obj_union_map,
855 (isc_un_op_fn) &isl_union_map_polyhedral_hull } },
856 {"poly", { -1, isl_obj_union_set, isl_obj_union_set,
857 (isc_un_op_fn) &isl_union_set_polyhedral_hull } },
858 {"poly", { -1, isl_obj_union_pw_qpolynomial,
859 isl_obj_union_pw_qpolynomial,
860 (isc_un_op_fn) &union_pw_qpolynomial_poly } },
861 {"lpoly", { -1, isl_obj_union_pw_qpolynomial,
862 isl_obj_union_pw_qpolynomial,
863 (isc_un_op_fn) &union_pw_qpolynomial_lpoly } },
864 {"upoly", { -1, isl_obj_union_pw_qpolynomial,
865 isl_obj_union_pw_qpolynomial,
866 (isc_un_op_fn) &union_pw_qpolynomial_upoly } },
867 #ifdef HAVE_PET
868 {"parse_file", { -1, isl_obj_str, isl_obj_list,
869 (isc_un_op_fn) &parse } },
870 #endif
871 {"pow", { -1, isl_obj_union_map, isl_obj_list,
872 (isc_un_op_fn) &union_map_power } },
873 {"sample", { -1, isl_obj_union_set, isl_obj_set,
874 (isc_un_op_fn) &union_set_sample } },
875 {"sample", { -1, isl_obj_union_map, isl_obj_map,
876 (isc_un_op_fn) &union_map_sample } },
877 {"scan", { -1, isl_obj_union_set, isl_obj_union_set,
878 (isc_un_op_fn) &union_set_scan } },
879 {"scan", { -1, isl_obj_union_map, isl_obj_union_map,
880 (isc_un_op_fn) &union_map_scan } },
881 {"sum", { -1, isl_obj_union_pw_qpolynomial,
882 isl_obj_union_pw_qpolynomial,
883 (isc_un_op_fn) &isl_union_pw_qpolynomial_sum } },
884 {"ub", { -1, isl_obj_union_pw_qpolynomial, isl_obj_list,
885 (isc_un_op_fn) &union_pw_qpolynomial_upper_bound } },
886 {"unwrap", { -1, isl_obj_union_set, isl_obj_union_map,
887 (isc_un_op_fn) &isl_union_set_unwrap } },
888 {"wrap", { -1, isl_obj_union_map, isl_obj_union_set,
889 (isc_un_op_fn) &isl_union_map_wrap } },
890 {"zip", { -1, isl_obj_union_map, isl_obj_union_map,
891 (isc_un_op_fn) &isl_union_map_zip } },
892 NULL
895 struct isl_named_obj {
896 char *name;
897 struct isl_obj obj;
900 static void free_obj(struct isl_obj obj)
902 obj.type->free(obj.v);
905 static int same_name(const void *entry, const void *val)
907 const struct isl_named_obj *named = (const struct isl_named_obj *)entry;
909 return !strcmp(named->name, val);
912 static int do_assign(struct isl_ctx *ctx, struct isl_hash_table *table,
913 char *name, struct isl_obj obj)
915 struct isl_hash_table_entry *entry;
916 uint32_t name_hash;
917 struct isl_named_obj *named;
919 name_hash = isl_hash_string(isl_hash_init(), name);
920 entry = isl_hash_table_find(ctx, table, name_hash, same_name, name, 1);
921 if (!entry)
922 goto error;
923 if (entry->data) {
924 named = entry->data;
925 free_obj(named->obj);
926 free(name);
927 } else {
928 named = isl_alloc_type(ctx, struct isl_named_obj);
929 if (!named)
930 goto error;
931 named->name = name;
932 entry->data = named;
934 named->obj = obj;
936 return 0;
937 error:
938 free_obj(obj);
939 free(name);
940 return -1;
943 static struct isl_obj stored_obj(struct isl_ctx *ctx,
944 struct isl_hash_table *table, char *name)
946 struct isl_obj obj = { isl_obj_none, NULL };
947 struct isl_hash_table_entry *entry;
948 uint32_t name_hash;
950 name_hash = isl_hash_string(isl_hash_init(), name);
951 entry = isl_hash_table_find(ctx, table, name_hash, same_name, name, 0);
952 if (entry) {
953 struct isl_named_obj *named;
954 named = entry->data;
955 obj = named->obj;
956 } else if (isdigit(name[0]))
957 fprintf(stderr, "unknown identifier '$%s'\n", name);
958 else
959 fprintf(stderr, "unknown identifier '%s'\n", name);
961 free(name);
962 obj.v = obj.type->copy(obj.v);
963 return obj;
966 static int is_subtype(struct isl_obj obj, isl_obj_type super)
968 if (obj.type == super)
969 return 1;
970 if (obj.type == isl_obj_map && super == isl_obj_union_map)
971 return 1;
972 if (obj.type == isl_obj_set && super == isl_obj_union_set)
973 return 1;
974 if (obj.type == isl_obj_pw_multi_aff && super == isl_obj_union_set) {
975 isl_space *space = isl_pw_multi_aff_get_space(obj.v);
976 int is_set = isl_space_is_set(space);
977 isl_space_free(space);
978 return is_set;
980 if (obj.type == isl_obj_pw_qpolynomial &&
981 super == isl_obj_union_pw_qpolynomial)
982 return 1;
983 if (obj.type == isl_obj_pw_qpolynomial_fold &&
984 super == isl_obj_union_pw_qpolynomial_fold)
985 return 1;
986 if (obj.type == isl_obj_union_set && isl_union_set_is_empty(obj.v))
987 return 1;
988 if (obj.type == isl_obj_list) {
989 struct isl_list *list = obj.v;
990 if (list->n == 2 && list->obj[1].type == isl_obj_bool)
991 return is_subtype(list->obj[0], super);
993 if (super == isl_obj_str)
994 return 1;
995 return 0;
998 static struct isl_obj obj_at(struct isl_obj obj, int i)
1000 struct isl_list *list = obj.v;
1002 obj = list->obj[i];
1003 obj.v = obj.type->copy(obj.v);
1005 isl_list_free(list);
1007 return obj;
1010 static struct isl_obj convert(isl_ctx *ctx, struct isl_obj obj,
1011 isl_obj_type type)
1013 if (obj.type == type)
1014 return obj;
1015 if (obj.type == isl_obj_pw_multi_aff && type == isl_obj_union_set) {
1016 isl_set *set = isl_set_from_pw_multi_aff(obj.v);
1017 obj.type = isl_obj_union_set;
1018 obj.v = isl_union_set_from_set(set);
1019 return obj;
1021 if (obj.type == isl_obj_map && type == isl_obj_union_map) {
1022 obj.type = isl_obj_union_map;
1023 obj.v = isl_union_map_from_map(obj.v);
1024 return obj;
1026 if (obj.type == isl_obj_set && type == isl_obj_union_set) {
1027 obj.type = isl_obj_union_set;
1028 obj.v = isl_union_set_from_set(obj.v);
1029 return obj;
1031 if (obj.type == isl_obj_pw_qpolynomial &&
1032 type == isl_obj_union_pw_qpolynomial) {
1033 obj.type = isl_obj_union_pw_qpolynomial;
1034 obj.v = isl_union_pw_qpolynomial_from_pw_qpolynomial(obj.v);
1035 return obj;
1037 if (obj.type == isl_obj_pw_qpolynomial_fold &&
1038 type == isl_obj_union_pw_qpolynomial_fold) {
1039 obj.type = isl_obj_union_pw_qpolynomial_fold;
1040 obj.v = isl_union_pw_qpolynomial_fold_from_pw_qpolynomial_fold(obj.v);
1041 return obj;
1043 if (obj.type == isl_obj_union_set && isl_union_set_is_empty(obj.v)) {
1044 if (type == isl_obj_union_map) {
1045 obj.type = isl_obj_union_map;
1046 return obj;
1048 if (type == isl_obj_union_pw_qpolynomial) {
1049 isl_space *dim = isl_union_set_get_space(obj.v);
1050 isl_union_set_free(obj.v);
1051 obj.v = isl_union_pw_qpolynomial_zero(dim);
1052 obj.type = isl_obj_union_pw_qpolynomial;
1053 return obj;
1055 if (type == isl_obj_union_pw_qpolynomial_fold) {
1056 isl_space *dim = isl_union_set_get_space(obj.v);
1057 isl_union_set_free(obj.v);
1058 obj.v = isl_union_pw_qpolynomial_fold_zero(dim,
1059 isl_fold_list);
1060 obj.type = isl_obj_union_pw_qpolynomial_fold;
1061 return obj;
1064 if (obj.type == isl_obj_list) {
1065 struct isl_list *list = obj.v;
1066 if (list->n == 2 && list->obj[1].type == isl_obj_bool)
1067 return convert(ctx, obj_at(obj, 0), type);
1069 if (type == isl_obj_str) {
1070 isl_str *str;
1071 isl_printer *p;
1072 char *s;
1074 p = isl_printer_to_str(ctx);
1075 if (!p)
1076 goto error;
1077 p = obj.type->print(p, obj.v);
1078 s = isl_printer_get_str(p);
1079 isl_printer_free(p);
1081 str = isl_str_from_string(ctx, s);
1082 if (!str)
1083 goto error;
1084 free_obj(obj);
1085 obj.v = str;
1086 obj.type = isl_obj_str;
1087 return obj;
1090 error:
1091 free_obj(obj);
1092 obj.type = isl_obj_none;
1093 obj.v = NULL;
1094 return obj;
1097 static struct isc_bin_op *read_bin_op_if_available(struct isl_stream *s,
1098 struct isl_obj lhs)
1100 int i;
1101 struct isl_token *tok;
1103 tok = isl_stream_next_token(s);
1104 if (!tok)
1105 return NULL;
1107 for (i = 0; ; ++i) {
1108 if (!bin_ops[i].op)
1109 break;
1110 if (bin_ops[i].op != isl_token_get_type(tok))
1111 continue;
1112 if (!is_subtype(lhs, bin_ops[i].lhs))
1113 continue;
1115 isl_token_free(tok);
1116 return &bin_ops[i];
1119 for (i = 0; ; ++i) {
1120 if (!named_bin_ops[i].name)
1121 break;
1122 if (named_bin_ops[i].op.op != isl_token_get_type(tok))
1123 continue;
1124 if (!is_subtype(lhs, named_bin_ops[i].op.lhs))
1125 continue;
1127 isl_token_free(tok);
1128 return &named_bin_ops[i].op;
1131 isl_stream_push_token(s, tok);
1133 return NULL;
1136 static struct isc_un_op *read_prefix_un_op_if_available(struct isl_stream *s)
1138 int i;
1139 struct isl_token *tok;
1141 tok = isl_stream_next_token(s);
1142 if (!tok)
1143 return NULL;
1145 for (i = 0; ; ++i) {
1146 if (!named_un_ops[i].name)
1147 break;
1148 if (named_un_ops[i].op.op != isl_token_get_type(tok))
1149 continue;
1151 isl_token_free(tok);
1152 return &named_un_ops[i].op;
1155 isl_stream_push_token(s, tok);
1157 return NULL;
1160 static struct isc_un_op *find_matching_un_op(struct isc_un_op *like,
1161 struct isl_obj arg)
1163 int i;
1165 for (i = 0; ; ++i) {
1166 if (!named_un_ops[i].name)
1167 break;
1168 if (named_un_ops[i].op.op != like->op)
1169 continue;
1170 if (!is_subtype(arg, named_un_ops[i].op.arg))
1171 continue;
1173 return &named_un_ops[i].op;
1176 return NULL;
1179 static int is_assign(struct isl_stream *s)
1181 struct isl_token *tok;
1182 struct isl_token *tok2;
1183 int assign;
1185 tok = isl_stream_next_token(s);
1186 if (!tok)
1187 return 0;
1188 if (isl_token_get_type(tok) != ISL_TOKEN_IDENT) {
1189 isl_stream_push_token(s, tok);
1190 return 0;
1193 tok2 = isl_stream_next_token(s);
1194 if (!tok2) {
1195 isl_stream_push_token(s, tok);
1196 return 0;
1198 assign = isl_token_get_type(tok2) == ISL_TOKEN_DEF;
1199 isl_stream_push_token(s, tok2);
1200 isl_stream_push_token(s, tok);
1202 return assign;
1205 static struct isl_obj read_obj(struct isl_stream *s,
1206 struct isl_hash_table *table);
1207 static struct isl_obj read_expr(struct isl_stream *s,
1208 struct isl_hash_table *table);
1210 static struct isl_obj read_un_op_expr(struct isl_stream *s,
1211 struct isl_hash_table *table, struct isc_un_op *op)
1213 isl_ctx *ctx;
1214 struct isl_obj obj = { isl_obj_none, NULL };
1216 obj = read_obj(s, table);
1217 if (!obj.v)
1218 goto error;
1220 op = find_matching_un_op(op, obj);
1222 ctx = isl_stream_get_ctx(s);
1223 if (!op)
1224 isl_die(ctx, isl_error_invalid,
1225 "no such unary operator defined on given operand",
1226 goto error);
1228 obj = convert(ctx, obj, op->arg);
1229 obj.v = op->fn(obj.v);
1230 obj.type = op->res;
1232 return obj;
1233 error:
1234 free_obj(obj);
1235 obj.type = isl_obj_none;
1236 obj.v = NULL;
1237 return obj;
1240 static struct isl_obj transitive_closure(struct isl_ctx *ctx, struct isl_obj obj)
1242 struct isl_list *list;
1243 int exact;
1245 if (obj.type != isl_obj_union_map)
1246 obj = convert(ctx, obj, isl_obj_union_map);
1247 isl_assert(ctx, obj.type == isl_obj_union_map, goto error);
1248 list = isl_list_alloc(ctx, 2);
1249 if (!list)
1250 goto error;
1252 list->obj[0].type = isl_obj_union_map;
1253 list->obj[0].v = isl_union_map_transitive_closure(obj.v, &exact);
1254 list->obj[1].type = isl_obj_bool;
1255 list->obj[1].v = exact ? &isl_bool_true : &isl_bool_false;
1256 obj.v = list;
1257 obj.type = isl_obj_list;
1258 if (exact < 0 || !list->obj[0].v)
1259 goto error;
1261 return obj;
1262 error:
1263 free_obj(obj);
1264 obj.type = isl_obj_none;
1265 obj.v = NULL;
1266 return obj;
1269 static struct isl_obj obj_at_index(struct isl_stream *s, struct isl_obj obj)
1271 struct isl_list *list = obj.v;
1272 struct isl_token *tok;
1273 isl_ctx *ctx;
1274 isl_val *v;
1275 int i;
1277 tok = isl_stream_next_token(s);
1278 if (!tok || isl_token_get_type(tok) != ISL_TOKEN_VALUE) {
1279 isl_stream_error(s, tok, "expecting index");
1280 if (tok)
1281 isl_stream_push_token(s, tok);
1282 goto error;
1284 ctx = isl_stream_get_ctx(s);
1285 v = isl_token_get_val(ctx, tok);
1286 i = isl_val_get_num_si(v);
1287 isl_val_free(v);
1288 isl_token_free(tok);
1289 isl_assert(ctx, i < list->n, goto error);
1290 if (isl_stream_eat(s, ']'))
1291 goto error;
1293 return obj_at(obj, i);
1294 error:
1295 free_obj(obj);
1296 obj.type = isl_obj_none;
1297 obj.v = NULL;
1298 return obj;
1301 static struct isl_obj apply(struct isl_stream *s, __isl_take isl_union_map *umap,
1302 struct isl_hash_table *table)
1304 isl_ctx *ctx;
1305 struct isl_obj obj;
1307 obj = read_expr(s, table);
1308 ctx = isl_stream_get_ctx(s);
1309 isl_assert(ctx, is_subtype(obj, isl_obj_union_set) ||
1310 is_subtype(obj, isl_obj_union_map), goto error);
1312 if (obj.type == isl_obj_list) {
1313 struct isl_list *list = obj.v;
1314 if (list->n == 2 && list->obj[1].type == isl_obj_bool)
1315 obj = obj_at(obj, 0);
1317 if (obj.type == isl_obj_set)
1318 obj = convert(ctx, obj, isl_obj_union_set);
1319 else if (obj.type == isl_obj_map)
1320 obj = convert(ctx, obj, isl_obj_union_map);
1321 if (obj.type == isl_obj_union_set) {
1322 obj.v = isl_union_set_apply(obj.v, umap);
1323 } else
1324 obj.v = isl_union_map_apply_range(obj.v, umap);
1325 if (!obj.v)
1326 goto error2;
1328 if (isl_stream_eat(s, ')'))
1329 goto error2;
1331 return obj;
1332 error:
1333 isl_union_map_free(umap);
1334 error2:
1335 free_obj(obj);
1336 obj.type = isl_obj_none;
1337 obj.v = NULL;
1338 return obj;
1341 static struct isl_obj apply_fun_set(struct isl_obj obj,
1342 __isl_take isl_union_set *uset)
1344 if (obj.type == isl_obj_union_pw_qpolynomial) {
1345 obj.v = isl_union_set_apply_union_pw_qpolynomial(uset, obj.v);
1346 } else {
1347 obj.type = isl_obj_list;
1348 obj.v = union_set_apply_union_pw_qpolynomial_fold(uset, obj.v);
1350 return obj;
1353 static struct isl_obj apply_fun_map(struct isl_obj obj,
1354 __isl_take isl_union_map *umap)
1356 if (obj.type == isl_obj_union_pw_qpolynomial) {
1357 obj.v = isl_union_map_apply_union_pw_qpolynomial(umap, obj.v);
1358 } else {
1359 obj.type = isl_obj_list;
1360 obj.v = union_map_apply_union_pw_qpolynomial_fold(umap, obj.v);
1362 return obj;
1365 static struct isl_obj apply_fun(struct isl_stream *s,
1366 struct isl_obj obj, struct isl_hash_table *table)
1368 struct isl_obj arg;
1369 isl_ctx *ctx;
1371 arg = read_expr(s, table);
1372 ctx = isl_stream_get_ctx(s);
1373 if (!is_subtype(arg, isl_obj_union_map) &&
1374 !is_subtype(arg, isl_obj_union_set))
1375 isl_die(ctx, isl_error_invalid,
1376 "expecting set of map argument", goto error);
1378 if (arg.type == isl_obj_list) {
1379 struct isl_list *list = arg.v;
1380 if (list->n == 2 && list->obj[1].type == isl_obj_bool)
1381 arg = obj_at(arg, 0);
1383 if (arg.type == isl_obj_set)
1384 arg = convert(ctx, arg, isl_obj_union_set);
1385 else if (arg.type == isl_obj_map)
1386 arg = convert(ctx, arg, isl_obj_union_map);
1387 if (arg.type == isl_obj_union_set)
1388 obj = apply_fun_set(obj, arg.v);
1389 else
1390 obj = apply_fun_map(obj, arg.v);
1391 if (!obj.v)
1392 goto error2;
1394 if (isl_stream_eat(s, ')'))
1395 goto error2;
1397 return obj;
1398 error:
1399 free_obj(arg);
1400 error2:
1401 free_obj(obj);
1402 obj.type = isl_obj_none;
1403 obj.v = NULL;
1404 return obj;
1407 struct add_vertex_data {
1408 struct isl_list *list;
1409 int i;
1412 static int add_vertex(__isl_take isl_vertex *vertex, void *user)
1414 struct add_vertex_data *data = (struct add_vertex_data *)user;
1415 isl_multi_aff *ma;
1416 isl_set *dom;
1418 ma = isl_vertex_get_expr(vertex);
1419 dom = isl_set_from_basic_set(isl_vertex_get_domain(vertex));
1421 data->list->obj[data->i].type = isl_obj_pw_multi_aff;
1422 data->list->obj[data->i].v = isl_pw_multi_aff_alloc(dom, ma);
1423 data->i++;
1425 isl_vertex_free(vertex);
1427 return 0;
1430 static int set_vertices(__isl_take isl_set *set, void *user)
1432 isl_ctx *ctx;
1433 isl_basic_set *hull;
1434 isl_vertices *vertices = NULL;
1435 struct isl_list *list = NULL;
1436 int r;
1437 struct add_vertex_data *data = (struct add_vertex_data *)user;
1439 set = isl_set_remove_divs(set);
1440 hull = isl_set_convex_hull(set);
1441 vertices = isl_basic_set_compute_vertices(hull);
1442 isl_basic_set_free(hull);
1444 list = data->list;
1446 ctx = isl_vertices_get_ctx(vertices);
1447 data->list = isl_list_alloc(ctx, isl_vertices_get_n_vertices(vertices));
1448 if (!data->list)
1449 goto error;
1451 data->i = 0;
1452 r = isl_vertices_foreach_vertex(vertices, &add_vertex, user);
1454 data->list = isl_list_concat(list, data->list);
1456 isl_vertices_free(vertices);
1458 return r;
1459 error:
1460 data->list = list;
1461 isl_vertices_free(vertices);
1462 return -1;
1465 static struct isl_obj vertices(struct isl_stream *s,
1466 struct isl_hash_table *table)
1468 isl_ctx *ctx;
1469 struct isl_obj obj;
1470 struct isl_list *list = NULL;
1471 isl_union_set *uset;
1472 struct add_vertex_data data = { NULL };
1474 obj = read_expr(s, table);
1475 ctx = isl_stream_get_ctx(s);
1476 obj = convert(ctx, obj, isl_obj_union_set);
1477 isl_assert(ctx, obj.type == isl_obj_union_set, goto error);
1478 uset = obj.v;
1479 obj.v = NULL;
1481 list = isl_list_alloc(ctx, 0);
1482 if (!list)
1483 goto error;
1485 data.list = list;
1487 if (isl_union_set_foreach_set(uset, &set_vertices, &data) < 0)
1488 goto error;
1490 isl_union_set_free(uset);
1492 obj.type = isl_obj_list;
1493 obj.v = data.list;
1495 return obj;
1496 error:
1497 isl_union_set_free(uset);
1498 isl_list_free(data.list);
1499 free_obj(obj);
1500 obj.type = isl_obj_none;
1501 obj.v = NULL;
1502 return obj;
1505 static struct isl_obj type_of(struct isl_stream *s,
1506 struct isl_hash_table *table)
1508 isl_ctx *ctx;
1509 struct isl_obj obj;
1510 const char *type = "unknown";
1512 obj = read_expr(s, table);
1514 if (obj.type == isl_obj_map ||
1515 obj.type == isl_obj_union_map)
1516 type = "map";
1517 if (obj.type == isl_obj_set ||
1518 obj.type == isl_obj_union_set)
1519 type = "set";
1520 if (obj.type == isl_obj_pw_multi_aff)
1521 type = "piecewise multi-quasiaffine expression";
1522 if (obj.type == isl_obj_pw_qpolynomial ||
1523 obj.type == isl_obj_union_pw_qpolynomial)
1524 type = "piecewise quasipolynomial";
1525 if (obj.type == isl_obj_pw_qpolynomial_fold ||
1526 obj.type == isl_obj_union_pw_qpolynomial_fold)
1527 type = "piecewise quasipolynomial fold";
1528 if (obj.type == isl_obj_list)
1529 type = "list";
1530 if (obj.type == isl_obj_bool)
1531 type = "boolean";
1532 if (obj.type == isl_obj_str)
1533 type = "string";
1534 if (obj.type == isl_obj_val)
1535 type = "value";
1537 free_obj(obj);
1538 obj.type = isl_obj_str;
1539 obj.v = isl_str_from_string(isl_stream_get_ctx(s), strdup(type));
1541 return obj;
1544 static __isl_give isl_union_set *read_set(struct isl_stream *s,
1545 struct isl_hash_table *table)
1547 struct isl_obj obj;
1548 isl_ctx *ctx;
1550 obj = read_obj(s, table);
1551 ctx = isl_stream_get_ctx(s);
1552 obj = convert(ctx, obj, isl_obj_union_set);
1553 isl_assert(ctx, obj.type == isl_obj_union_set, goto error);
1554 return obj.v;
1555 error:
1556 free_obj(obj);
1557 return NULL;
1560 static __isl_give isl_union_map *read_map(struct isl_stream *s,
1561 struct isl_hash_table *table)
1563 struct isl_obj obj;
1564 isl_ctx *ctx;
1566 obj = read_obj(s, table);
1567 ctx = isl_stream_get_ctx(s);
1568 obj = convert(ctx, obj, isl_obj_union_map);
1569 isl_assert(ctx, obj.type == isl_obj_union_map, goto error);
1570 return obj.v;
1571 error:
1572 free_obj(obj);
1573 return NULL;
1576 static struct isl_obj last_any(struct isl_stream *s,
1577 struct isl_hash_table *table, __isl_take isl_union_map *must_source,
1578 __isl_take isl_union_map *may_source)
1580 struct isl_obj obj = { isl_obj_none, NULL };
1581 isl_union_map *sink = NULL;
1582 isl_union_map *schedule = NULL;
1583 isl_union_map *may_dep;
1584 isl_union_map *must_dep;
1586 if (isl_stream_eat(s, iscc_op[ISCC_BEFORE]))
1587 goto error;
1589 sink = read_map(s, table);
1590 if (!sink)
1591 goto error;
1593 if (isl_stream_eat(s, iscc_op[ISCC_UNDER]))
1594 goto error;
1596 schedule = read_map(s, table);
1597 if (!schedule)
1598 goto error;
1600 if (isl_union_map_compute_flow(sink, must_source, may_source,
1601 schedule, &must_dep, &may_dep,
1602 NULL, NULL) < 0)
1603 return obj;
1605 obj.type = isl_obj_union_map;
1606 obj.v = isl_union_map_union(must_dep, may_dep);
1608 return obj;
1609 error:
1610 isl_union_map_free(may_source);
1611 isl_union_map_free(must_source);
1612 isl_union_map_free(sink);
1613 isl_union_map_free(schedule);
1614 free_obj(obj);
1615 obj.type = isl_obj_none;
1616 obj.v = NULL;
1617 return obj;
1620 static struct isl_obj any(struct isl_stream *s, struct isl_hash_table *table)
1622 struct isl_obj obj = { isl_obj_none, NULL };
1623 isl_union_map *must_source = NULL;
1624 isl_union_map *may_source = NULL;
1625 isl_union_map *sink = NULL;
1626 isl_union_map *schedule = NULL;
1627 isl_union_map *may_dep;
1629 may_source = read_map(s, table);
1630 if (!may_source)
1631 goto error;
1633 if (isl_stream_eat_if_available(s, iscc_op[ISCC_LAST])) {
1634 must_source = read_map(s, table);
1635 if (!must_source)
1636 goto error;
1637 return last_any(s, table, must_source, may_source);
1640 if (isl_stream_eat(s, iscc_op[ISCC_BEFORE]))
1641 goto error;
1643 sink = read_map(s, table);
1644 if (!sink)
1645 goto error;
1647 if (isl_stream_eat(s, iscc_op[ISCC_UNDER]))
1648 goto error;
1650 schedule = read_map(s, table);
1651 if (!schedule)
1652 goto error;
1654 must_source = isl_union_map_empty(isl_union_map_get_space(sink));
1655 if (isl_union_map_compute_flow(sink, must_source, may_source,
1656 schedule, NULL, &may_dep,
1657 NULL, NULL) < 0)
1658 return obj;
1660 obj.type = isl_obj_union_map;
1661 obj.v = may_dep;
1663 return obj;
1664 error:
1665 isl_union_map_free(may_source);
1666 isl_union_map_free(must_source);
1667 isl_union_map_free(sink);
1668 isl_union_map_free(schedule);
1669 free_obj(obj);
1670 obj.type = isl_obj_none;
1671 obj.v = NULL;
1672 return obj;
1675 static struct isl_obj last(struct isl_stream *s, struct isl_hash_table *table)
1677 struct isl_obj obj = { isl_obj_none, NULL };
1678 struct isl_list *list = NULL;
1679 isl_union_map *must_source = NULL;
1680 isl_union_map *may_source = NULL;
1681 isl_union_map *sink = NULL;
1682 isl_union_map *schedule = NULL;
1683 isl_union_map *must_dep;
1684 isl_union_map *must_no_source;
1686 must_source = read_map(s, table);
1687 if (!must_source)
1688 goto error;
1690 if (isl_stream_eat_if_available(s, iscc_op[ISCC_ANY])) {
1691 may_source = read_map(s, table);
1692 if (!may_source)
1693 goto error;
1694 return last_any(s, table, must_source, may_source);
1697 list = isl_list_alloc(isl_stream_get_ctx(s), 2);
1698 if (!list)
1699 goto error;
1701 if (isl_stream_eat(s, iscc_op[ISCC_BEFORE]))
1702 goto error;
1704 sink = read_map(s, table);
1705 if (!sink)
1706 goto error;
1708 if (isl_stream_eat(s, iscc_op[ISCC_UNDER]))
1709 goto error;
1711 schedule = read_map(s, table);
1712 if (!schedule)
1713 goto error;
1715 may_source = isl_union_map_empty(isl_union_map_get_space(sink));
1716 if (isl_union_map_compute_flow(sink, must_source, may_source,
1717 schedule, &must_dep, NULL,
1718 &must_no_source, NULL) < 0) {
1719 isl_list_free(list);
1720 return obj;
1723 list->obj[0].type = isl_obj_union_map;
1724 list->obj[0].v = must_dep;
1725 list->obj[1].type = isl_obj_union_map;
1726 list->obj[1].v = must_no_source;
1728 obj.v = list;
1729 obj.type = isl_obj_list;
1731 return obj;
1732 error:
1733 isl_list_free(list);
1734 isl_union_map_free(may_source);
1735 isl_union_map_free(must_source);
1736 isl_union_map_free(sink);
1737 isl_union_map_free(schedule);
1738 free_obj(obj);
1739 obj.type = isl_obj_none;
1740 obj.v = NULL;
1741 return obj;
1744 static __isl_give isl_schedule *get_schedule(struct isl_stream *s,
1745 struct isl_hash_table *table)
1747 isl_union_set *domain;
1748 isl_union_map *validity;
1749 isl_union_map *proximity;
1751 domain = read_set(s, table);
1752 if (!domain)
1753 return NULL;
1755 validity = isl_union_map_empty(isl_union_set_get_space(domain));
1756 proximity = isl_union_map_empty(isl_union_set_get_space(domain));
1758 for (;;) {
1759 isl_union_map *umap;
1760 if (isl_stream_eat_if_available(s, iscc_op[ISCC_RESPECTING])) {
1761 umap = read_map(s, table);
1762 validity = isl_union_map_union(validity, umap);
1763 } else if (isl_stream_eat_if_available(s, iscc_op[ISCC_MINIMIZING])) {
1764 umap = read_map(s, table);
1765 proximity = isl_union_map_union(proximity, umap);
1766 } else
1767 break;
1770 return isl_union_set_compute_schedule(domain, validity, proximity);
1773 static struct isl_obj schedule(struct isl_stream *s,
1774 struct isl_hash_table *table)
1776 struct isl_obj obj = { isl_obj_none, NULL };
1777 isl_schedule *schedule;
1779 schedule = get_schedule(s, table);
1781 obj.v = isl_schedule_get_map(schedule);
1782 obj.type = isl_obj_union_map;
1784 isl_schedule_free(schedule);
1786 return obj;
1789 /* Read a schedule for code generation.
1790 * If the input is a set rather than a map, then we construct
1791 * an identity schedule on the given set.
1793 static __isl_give isl_union_map *get_codegen_schedule(struct isl_stream *s,
1794 struct isl_hash_table *table)
1796 struct isl_obj obj;
1797 isl_ctx *ctx;
1799 obj = read_obj(s, table);
1800 ctx = isl_stream_get_ctx(s);
1802 if (is_subtype(obj, isl_obj_union_map)) {
1803 obj = convert(ctx, obj, isl_obj_union_map);
1804 return obj.v;
1807 if (is_subtype(obj, isl_obj_union_set)) {
1808 obj = convert(ctx, obj, isl_obj_union_set);
1809 return isl_union_set_identity(obj.v);
1812 free_obj(obj);
1813 isl_die(ctx, isl_error_invalid, "expecting set or map", return NULL);
1816 /* Generate an AST for the given schedule and options and print
1817 * the AST on the printer.
1819 static __isl_give isl_printer *print_code(__isl_take isl_printer *p,
1820 __isl_take isl_union_map *schedule,
1821 __isl_take isl_union_map *options)
1823 isl_space *space;
1824 isl_set *context;
1825 isl_ast_build *build;
1826 isl_ast_node *tree;
1827 int format;
1829 space = isl_union_map_get_space(schedule);
1830 context = isl_set_universe(isl_space_params(space));
1832 build = isl_ast_build_from_context(context);
1833 build = isl_ast_build_set_options(build, options);
1834 tree = isl_ast_build_ast_from_schedule(build, schedule);
1835 isl_ast_build_free(build);
1837 if (!tree)
1838 return p;
1840 format = isl_printer_get_output_format(p);
1841 p = isl_printer_set_output_format(p, ISL_FORMAT_C);
1842 p = isl_printer_print_ast_node(p, tree);
1843 p = isl_printer_set_output_format(p, format);
1845 isl_ast_node_free(tree);
1847 return p;
1850 /* Perform the codegen operation.
1851 * In particular, read a schedule, check if the user has specified any options
1852 * and then generate an AST from the schedule (and options) and print it.
1854 static __isl_give isl_printer *codegen(struct isl_stream *s,
1855 struct isl_hash_table *table, __isl_take isl_printer *p)
1857 isl_union_map *schedule;
1858 isl_union_map *options;
1860 schedule = get_codegen_schedule(s, table);
1861 if (!schedule)
1862 return p;
1864 if (isl_stream_eat_if_available(s, iscc_op[ISCC_USING]))
1865 options = read_map(s, table);
1866 else
1867 options = isl_union_map_empty(
1868 isl_union_map_get_space(schedule));
1870 p = print_code(p, schedule, options);
1872 isl_stream_eat(s, ';');
1874 return p;
1877 static struct isl_obj band_list_to_obj_list(__isl_take isl_band_list *bands);
1879 static struct isl_obj band_to_obj_list(__isl_take isl_band *band)
1881 struct isl_obj obj = { isl_obj_none, NULL };
1882 isl_ctx *ctx = isl_band_get_ctx(band);
1883 struct isl_list *list;
1885 list = isl_list_alloc(ctx, 2);
1886 if (!list)
1887 goto error;
1889 obj.v = list;
1890 obj.type = isl_obj_list;
1892 list->obj[0].type = isl_obj_union_map;
1893 list->obj[0].v = isl_band_get_partial_schedule(band);
1895 if (isl_band_has_children(band)) {
1896 isl_band_list *children;
1898 children = isl_band_get_children(band);
1899 list->obj[1] = band_list_to_obj_list(children);
1900 } else {
1901 list->obj[1].type = isl_obj_list;
1902 list->obj[1].v = isl_list_alloc(ctx, 0);
1905 if (!list->obj[0].v || !list->obj[1].v)
1906 goto error;
1908 isl_band_free(band);
1910 return obj;
1911 error:
1912 isl_band_free(band);
1913 free_obj(obj);
1914 obj.type = isl_obj_none;
1915 obj.v = NULL;
1916 return obj;
1919 static struct isl_obj band_list_to_obj_list(__isl_take isl_band_list *bands)
1921 struct isl_obj obj = { isl_obj_none, NULL };
1922 isl_ctx *ctx = isl_band_list_get_ctx(bands);
1923 struct isl_list *list;
1924 int i, n;
1926 n = isl_band_list_n_band(bands);
1927 list = isl_list_alloc(ctx, n);
1928 if (!list)
1929 goto error;
1931 obj.v = list;
1932 obj.type = isl_obj_list;
1934 for (i = 0; i < n; ++i) {
1935 isl_band *band;
1937 band = isl_band_list_get_band(bands, i);
1938 list->obj[i] = band_to_obj_list(band);
1939 if (!list->obj[i].v)
1940 goto error;
1943 isl_band_list_free(bands);
1945 return obj;
1946 error:
1947 isl_band_list_free(bands);
1948 free_obj(obj);
1949 obj.type = isl_obj_none;
1950 obj.v = NULL;
1951 return obj;
1954 static struct isl_obj schedule_forest(struct isl_stream *s,
1955 struct isl_hash_table *table)
1957 struct isl_obj obj = { isl_obj_none, NULL };
1958 isl_schedule *schedule;
1959 isl_band_list *roots;
1961 schedule = get_schedule(s, table);
1962 if (!schedule)
1963 return obj;
1965 roots = isl_schedule_get_band_forest(schedule);
1966 isl_schedule_free(schedule);
1968 return band_list_to_obj_list(roots);
1971 static struct isl_obj power(struct isl_stream *s, struct isl_obj obj)
1973 struct isl_token *tok;
1974 isl_ctx *ctx;
1975 isl_val *v;
1977 ctx = isl_stream_get_ctx(s);
1978 if (isl_stream_eat_if_available(s, '+'))
1979 return transitive_closure(ctx, obj);
1981 isl_assert(ctx, is_subtype(obj, isl_obj_union_map), goto error);
1982 if (obj.type != isl_obj_union_map)
1983 obj = convert(ctx, obj, isl_obj_union_map);
1985 tok = isl_stream_next_token(s);
1986 if (!tok || isl_token_get_type(tok) != ISL_TOKEN_VALUE) {
1987 isl_stream_error(s, tok, "expecting integer exponent");
1988 if (tok)
1989 isl_stream_push_token(s, tok);
1990 goto error;
1993 v = isl_token_get_val(ctx, tok);
1994 if (isl_val_is_zero(v)) {
1995 isl_stream_error(s, tok, "expecting non-zero exponent");
1996 isl_val_free(v);
1997 if (tok)
1998 isl_stream_push_token(s, tok);
1999 goto error;
2002 obj.v = isl_union_map_fixed_power_val(obj.v, v);
2003 isl_token_free(tok);
2004 if (!obj.v)
2005 goto error;
2007 return obj;
2008 error:
2009 free_obj(obj);
2010 obj.type = isl_obj_none;
2011 obj.v = NULL;
2012 return obj;
2015 static struct isl_obj check_assert(struct isl_stream *s,
2016 struct isl_hash_table *table)
2018 struct isl_obj obj;
2019 isl_ctx *ctx;
2021 obj = read_expr(s, table);
2022 ctx = isl_stream_get_ctx(s);
2023 if (obj.type != isl_obj_bool)
2024 isl_die(ctx, isl_error_invalid,
2025 "expecting boolean expression", goto error);
2026 if (obj.v != &isl_bool_true)
2027 isl_die(ctx, isl_error_unknown,
2028 "assertion failed", abort());
2029 error:
2030 free_obj(obj);
2031 obj.type = isl_obj_none;
2032 obj.v = NULL;
2033 return obj;
2036 static struct isl_obj read_from_file(struct isl_stream *s)
2038 isl_ctx *ctx;
2039 struct isl_obj obj;
2040 struct isl_token *tok;
2041 struct isl_stream *s_file;
2042 struct iscc_options *options;
2043 char *name;
2044 FILE *file;
2046 tok = isl_stream_next_token(s);
2047 if (!tok || isl_token_get_type(tok) != ISL_TOKEN_STRING) {
2048 isl_stream_error(s, tok, "expecting filename");
2049 isl_token_free(tok);
2050 goto error;
2053 ctx = isl_stream_get_ctx(s);
2054 options = isl_ctx_peek_iscc_options(ctx);
2055 if (!options || !options->io) {
2056 isl_token_free(tok);
2057 isl_die(ctx, isl_error_invalid,
2058 "read operation not allowed", goto error);
2061 name = isl_token_get_str(ctx, tok);
2062 isl_token_free(tok);
2063 file = fopen(name, "r");
2064 free(name);
2065 isl_assert(ctx, file, goto error);
2067 s_file = isl_stream_new_file(ctx, file);
2068 if (!s_file) {
2069 fclose(file);
2070 goto error;
2073 obj = isl_stream_read_obj(s_file);
2075 isl_stream_free(s_file);
2076 fclose(file);
2078 return obj;
2079 error:
2080 obj.type = isl_obj_none;
2081 obj.v = NULL;
2082 return obj;
2085 static struct isl_obj write_to_file(struct isl_stream *s,
2086 struct isl_hash_table *table)
2088 struct isl_obj obj;
2089 struct isl_token *tok;
2090 struct isl_stream *s_file;
2091 struct iscc_options *options;
2092 char *name;
2093 FILE *file;
2094 isl_ctx *ctx;
2095 isl_printer *p;
2097 tok = isl_stream_next_token(s);
2098 if (!tok || isl_token_get_type(tok) != ISL_TOKEN_STRING) {
2099 isl_stream_error(s, tok, "expecting filename");
2100 isl_token_free(tok);
2101 goto error;
2104 obj = read_expr(s, table);
2106 ctx = isl_stream_get_ctx(s);
2107 options = isl_ctx_peek_iscc_options(ctx);
2108 if (!options || !options->io) {
2109 isl_token_free(tok);
2110 isl_die(ctx, isl_error_invalid,
2111 "write operation not allowed", goto error);
2114 name = isl_token_get_str(ctx, tok);
2115 isl_token_free(tok);
2116 file = fopen(name, "w");
2117 free(name);
2118 if (!file)
2119 isl_die(ctx, isl_error_unknown,
2120 "could not open file for writing", goto error);
2122 p = isl_printer_to_file(ctx, file);
2123 p = isl_printer_set_output_format(p, options->format);
2124 p = obj.type->print(p, obj.v);
2125 p = isl_printer_end_line(p);
2126 isl_printer_free(p);
2128 fclose(file);
2129 error:
2130 free_obj(obj);
2131 obj.type = isl_obj_none;
2132 obj.v = NULL;
2133 return obj;
2136 static struct isl_obj read_string_if_available(struct isl_stream *s)
2138 struct isl_token *tok;
2139 struct isl_obj obj = { isl_obj_none, NULL };
2141 tok = isl_stream_next_token(s);
2142 if (!tok)
2143 return obj;
2144 if (isl_token_get_type(tok) == ISL_TOKEN_STRING) {
2145 isl_str *str;
2146 str = isl_str_alloc(isl_stream_get_ctx(s));
2147 if (!str)
2148 goto error;
2149 str->s = isl_token_get_str(isl_stream_get_ctx(s), tok);
2150 isl_token_free(tok);
2151 obj.v = str;
2152 obj.type = isl_obj_str;
2153 } else
2154 isl_stream_push_token(s, tok);
2155 return obj;
2156 error:
2157 isl_token_free(tok);
2158 return obj;
2161 static struct isl_obj read_bool_if_available(struct isl_stream *s)
2163 struct isl_token *tok;
2164 struct isl_obj obj = { isl_obj_none, NULL };
2165 int type;
2167 tok = isl_stream_next_token(s);
2168 if (!tok)
2169 return obj;
2170 type = isl_token_get_type(tok);
2171 if (type == ISL_TOKEN_FALSE || type == ISL_TOKEN_TRUE) {
2172 int is_true = type == ISL_TOKEN_TRUE;
2173 isl_token_free(tok);
2174 obj.v = is_true ? &isl_bool_true : &isl_bool_false;
2175 obj.type = isl_obj_bool;
2176 } else
2177 isl_stream_push_token(s, tok);
2178 return obj;
2181 static __isl_give char *read_ident(struct isl_stream *s)
2183 char *name;
2184 isl_val *v;
2185 struct isl_token *tok, *tok2;
2187 name = isl_stream_read_ident_if_available(s);
2188 if (name)
2189 return name;
2191 tok = isl_stream_next_token(s);
2192 if (!tok)
2193 return NULL;
2194 if (isl_token_get_type(tok) != '$') {
2195 isl_stream_push_token(s, tok);
2196 return NULL;
2198 tok2 = isl_stream_next_token(s);
2199 if (!tok2 || isl_token_get_type(tok2) != ISL_TOKEN_VALUE) {
2200 if (tok2)
2201 isl_stream_push_token(s, tok2);
2202 isl_stream_push_token(s, tok);
2203 return NULL;
2206 v = isl_token_get_val(isl_stream_get_ctx(s), tok2);
2207 name = isl_val_to_str(v);
2208 isl_val_free(v);
2209 isl_token_free(tok);
2210 isl_token_free(tok2);
2212 return name;
2215 static struct isl_obj read_list(struct isl_stream *s,
2216 struct isl_hash_table *table, struct isl_obj obj)
2218 struct isl_list *list;
2220 list = isl_list_alloc(isl_stream_get_ctx(s), 2);
2221 if (!list)
2222 goto error;
2223 list->obj[0] = obj;
2224 list->obj[1] = read_obj(s, table);
2225 obj.v = list;
2226 obj.type = isl_obj_list;
2228 if (!list->obj[1].v)
2229 goto error;
2231 while (isl_stream_eat_if_available(s, ',')) {
2232 obj.v = list = isl_list_add_obj(list, read_obj(s, table));
2233 if (!obj.v)
2234 goto error;
2237 return obj;
2238 error:
2239 free_obj(obj);
2240 obj.type = isl_obj_none;
2241 obj.v = NULL;
2242 return obj;
2245 static struct isl_obj read_obj(struct isl_stream *s,
2246 struct isl_hash_table *table)
2248 isl_ctx *ctx;
2249 struct isl_obj obj = { isl_obj_none, NULL };
2250 char *name = NULL;
2251 struct isc_un_op *op = NULL;
2253 obj = read_string_if_available(s);
2254 if (obj.v)
2255 return obj;
2256 obj = read_bool_if_available(s);
2257 if (obj.v)
2258 return obj;
2259 ctx = isl_stream_get_ctx(s);
2260 if (isl_stream_eat_if_available(s, '(')) {
2261 if (isl_stream_next_token_is(s, ')')) {
2262 obj.type = isl_obj_list;
2263 obj.v = isl_list_alloc(ctx, 0);
2264 } else {
2265 obj = read_expr(s, table);
2266 if (obj.v && isl_stream_eat_if_available(s, ','))
2267 obj = read_list(s, table, obj);
2269 if (!obj.v || isl_stream_eat(s, ')'))
2270 goto error;
2271 } else {
2272 op = read_prefix_un_op_if_available(s);
2273 if (op)
2274 return read_un_op_expr(s, table, op);
2276 if (isl_stream_eat_if_available(s, iscc_op[ISCC_ASSERT]))
2277 return check_assert(s, table);
2278 if (isl_stream_eat_if_available(s, iscc_op[ISCC_READ]))
2279 return read_from_file(s);
2280 if (isl_stream_eat_if_available(s, iscc_op[ISCC_WRITE]))
2281 return write_to_file(s, table);
2282 if (isl_stream_eat_if_available(s, iscc_op[ISCC_VERTICES]))
2283 return vertices(s, table);
2284 if (isl_stream_eat_if_available(s, iscc_op[ISCC_ANY]))
2285 return any(s, table);
2286 if (isl_stream_eat_if_available(s, iscc_op[ISCC_LAST]))
2287 return last(s, table);
2288 if (isl_stream_eat_if_available(s, iscc_op[ISCC_SCHEDULE]))
2289 return schedule(s, table);
2290 if (isl_stream_eat_if_available(s, iscc_op[ISCC_SCHEDULE_FOREST]))
2291 return schedule_forest(s, table);
2292 if (isl_stream_eat_if_available(s, iscc_op[ISCC_TYPEOF]))
2293 return type_of(s, table);
2295 name = read_ident(s);
2296 if (name)
2297 obj = stored_obj(ctx, table, name);
2298 else
2299 obj = isl_stream_read_obj(s);
2300 if (!obj.v)
2301 goto error;
2304 if (isl_stream_eat_if_available(s, '^'))
2305 obj = power(s, obj);
2306 else if (obj.type == isl_obj_list && isl_stream_eat_if_available(s, '['))
2307 obj = obj_at_index(s, obj);
2308 else if (is_subtype(obj, isl_obj_union_map) &&
2309 isl_stream_eat_if_available(s, '(')) {
2310 obj = convert(ctx, obj, isl_obj_union_map);
2311 obj = apply(s, obj.v, table);
2312 } else if (is_subtype(obj, isl_obj_union_pw_qpolynomial) &&
2313 isl_stream_eat_if_available(s, '(')) {
2314 obj = convert(ctx, obj, isl_obj_union_pw_qpolynomial);
2315 obj = apply_fun(s, obj, table);
2316 } else if (is_subtype(obj, isl_obj_union_pw_qpolynomial_fold) &&
2317 isl_stream_eat_if_available(s, '(')) {
2318 obj = convert(ctx, obj, isl_obj_union_pw_qpolynomial_fold);
2319 obj = apply_fun(s, obj, table);
2322 return obj;
2323 error:
2324 free_obj(obj);
2325 obj.type = isl_obj_none;
2326 obj.v = NULL;
2327 return obj;
2330 static struct isc_bin_op *find_matching_bin_op(struct isc_bin_op *like,
2331 struct isl_obj lhs, struct isl_obj rhs)
2333 int i;
2335 for (i = 0; ; ++i) {
2336 if (!bin_ops[i].op)
2337 break;
2338 if (bin_ops[i].op != like->op)
2339 continue;
2340 if (!is_subtype(lhs, bin_ops[i].lhs))
2341 continue;
2342 if (!is_subtype(rhs, bin_ops[i].rhs))
2343 continue;
2345 return &bin_ops[i];
2348 for (i = 0; ; ++i) {
2349 if (!named_bin_ops[i].name)
2350 break;
2351 if (named_bin_ops[i].op.op != like->op)
2352 continue;
2353 if (!is_subtype(lhs, named_bin_ops[i].op.lhs))
2354 continue;
2355 if (!is_subtype(rhs, named_bin_ops[i].op.rhs))
2356 continue;
2358 return &named_bin_ops[i].op;
2361 return NULL;
2364 static int next_is_neg_int(struct isl_stream *s)
2366 struct isl_token *tok;
2367 int ret;
2369 tok = isl_stream_next_token(s);
2370 if (tok && isl_token_get_type(tok) == ISL_TOKEN_VALUE) {
2371 isl_val *v;
2372 v = isl_token_get_val(isl_stream_get_ctx(s), tok);
2373 ret = isl_val_is_neg(v);
2374 isl_val_free(v);
2375 } else
2376 ret = 0;
2377 isl_stream_push_token(s, tok);
2379 return ret;
2382 static struct isl_obj call_bin_op(isl_ctx *ctx, struct isc_bin_op *op,
2383 struct isl_obj lhs, struct isl_obj rhs)
2385 struct isl_obj obj;
2387 lhs = convert(ctx, lhs, op->lhs);
2388 rhs = convert(ctx, rhs, op->rhs);
2389 if (op->res != isl_obj_bool)
2390 obj.v = op->o.fn(lhs.v, rhs.v);
2391 else {
2392 int res = op->o.test(lhs.v, rhs.v);
2393 free_obj(lhs);
2394 free_obj(rhs);
2395 obj.v = isl_bool_from_int(res);
2397 obj.type = op->res;
2399 return obj;
2402 static struct isl_obj read_expr(struct isl_stream *s,
2403 struct isl_hash_table *table)
2405 isl_ctx *ctx;
2406 struct isl_obj obj = { isl_obj_none, NULL };
2407 struct isl_obj right_obj = { isl_obj_none, NULL };
2409 obj = read_obj(s, table);
2410 ctx = isl_stream_get_ctx(s);
2411 for (; obj.v;) {
2412 struct isc_bin_op *op = NULL;
2414 op = read_bin_op_if_available(s, obj);
2415 if (!op)
2416 break;
2418 right_obj = read_obj(s, table);
2420 op = find_matching_bin_op(op, obj, right_obj);
2422 if (!op)
2423 isl_die(ctx, isl_error_invalid,
2424 "no such binary operator defined on given operands",
2425 goto error);
2427 obj = call_bin_op(ctx, op, obj, right_obj);
2430 if (obj.type == isl_obj_val && next_is_neg_int(s)) {
2431 right_obj = read_obj(s, table);
2432 obj.v = isl_val_add(obj.v, right_obj.v);
2435 return obj;
2436 error:
2437 free_obj(right_obj);
2438 free_obj(obj);
2439 obj.type = isl_obj_none;
2440 obj.v = NULL;
2441 return obj;
2444 static __isl_give isl_printer *source_file(struct isl_stream *s,
2445 struct isl_hash_table *table, __isl_take isl_printer *p);
2447 static __isl_give isl_printer *read_line(struct isl_stream *s,
2448 struct isl_hash_table *table, __isl_take isl_printer *p, int tty)
2450 isl_ctx *ctx;
2451 struct isl_obj obj = { isl_obj_none, NULL };
2452 char *lhs = NULL;
2453 int assign = 0;
2454 int only_print = 0;
2455 struct isc_bin_op *op = NULL;
2456 char buf[30];
2458 if (!p)
2459 return NULL;
2460 if (isl_stream_is_empty(s))
2461 return p;
2463 if (isl_stream_eat_if_available(s, iscc_op[ISCC_SOURCE]))
2464 return source_file(s, table, p);
2465 if (isl_stream_eat_if_available(s, iscc_op[ISCC_CODEGEN]))
2466 return codegen(s, table, p);
2468 assign = is_assign(s);
2469 if (assign) {
2470 lhs = isl_stream_read_ident_if_available(s);
2471 if (isl_stream_eat(s, ISL_TOKEN_DEF))
2472 goto error;
2473 } else if (isl_stream_eat_if_available(s, iscc_op[ISCC_PRINT]))
2474 only_print = 1;
2475 else if (!tty)
2476 only_print = 1;
2478 obj = read_expr(s, table);
2479 ctx = isl_stream_get_ctx(s);
2480 if (isl_ctx_last_error(ctx) == isl_error_abort) {
2481 fprintf(stderr, "Interrupted\n");
2482 isl_ctx_reset_error(ctx);
2484 if (isl_stream_eat(s, ';'))
2485 goto error;
2487 if (only_print) {
2488 if (obj.type != isl_obj_none && obj.v != NULL) {
2489 p = obj.type->print(p, obj.v);
2490 p = isl_printer_end_line(p);
2492 free_obj(obj);
2493 return p;
2495 if (!assign && obj.type != isl_obj_none && obj.v != NULL) {
2496 static int count = 0;
2497 snprintf(buf, sizeof(buf), "$%d", count++);
2498 lhs = strdup(buf + 1);
2500 p = isl_printer_print_str(p, buf);
2501 p = isl_printer_print_str(p, " := ");
2502 p = obj.type->print(p, obj.v);
2503 p = isl_printer_end_line(p);
2505 if (lhs && do_assign(ctx, table, lhs, obj))
2506 return p;
2508 return p;
2509 error:
2510 isl_stream_flush_tokens(s);
2511 isl_stream_skip_line(s);
2512 free(lhs);
2513 free_obj(obj);
2514 return p;
2517 int free_cb(void **entry, void *user)
2519 struct isl_named_obj *named = *entry;
2521 free_obj(named->obj);
2522 free(named->name);
2523 free(named);
2525 return 0;
2528 static void register_named_ops(struct isl_stream *s)
2530 int i;
2532 for (i = 0; i < ISCC_N_OP; ++i) {
2533 iscc_op[i] = isl_stream_register_keyword(s, op_name[i]);
2534 assert(iscc_op[i] != ISL_TOKEN_ERROR);
2537 for (i = 0; ; ++i) {
2538 if (!named_un_ops[i].name)
2539 break;
2540 named_un_ops[i].op.op = isl_stream_register_keyword(s,
2541 named_un_ops[i].name);
2542 assert(named_un_ops[i].op.op != ISL_TOKEN_ERROR);
2545 for (i = 0; ; ++i) {
2546 if (!named_bin_ops[i].name)
2547 break;
2548 named_bin_ops[i].op.op = isl_stream_register_keyword(s,
2549 named_bin_ops[i].name);
2550 assert(named_bin_ops[i].op.op != ISL_TOKEN_ERROR);
2554 static __isl_give isl_printer *source_file(struct isl_stream *s,
2555 struct isl_hash_table *table, __isl_take isl_printer *p)
2557 isl_ctx *ctx;
2558 struct isl_token *tok;
2559 struct isl_stream *s_file;
2560 struct iscc_options *options;
2561 char *name;
2562 FILE *file;
2564 tok = isl_stream_next_token(s);
2565 if (!tok || isl_token_get_type(tok) != ISL_TOKEN_STRING) {
2566 isl_stream_error(s, tok, "expecting filename");
2567 isl_token_free(tok);
2568 return p;
2571 isl_stream_eat(s, ';');
2573 ctx = isl_stream_get_ctx(s);
2574 options = isl_ctx_peek_iscc_options(ctx);
2575 if (!options || !options->io) {
2576 isl_token_free(tok);
2577 isl_die(ctx, isl_error_invalid,
2578 "source operation not allowed", return p);
2581 name = isl_token_get_str(ctx, tok);
2582 isl_token_free(tok);
2583 file = fopen(name, "r");
2584 free(name);
2585 isl_assert(ctx, file, return p);
2587 s_file = isl_stream_new_file(ctx, file);
2588 if (!s_file) {
2589 fclose(file);
2590 return p;
2593 register_named_ops(s_file);
2595 while (!isl_stream_is_empty(s_file))
2596 p = read_line(s_file, table, p, 0);
2598 isl_stream_free(s_file);
2599 fclose(file);
2601 return p;
2604 int main(int argc, char **argv)
2606 struct isl_ctx *ctx;
2607 struct isl_stream *s;
2608 struct isl_hash_table *table;
2609 struct iscc_options *options;
2610 isl_printer *p;
2611 int tty = isatty(0);
2613 options = iscc_options_new_with_defaults();
2614 assert(options);
2616 ctx = isl_ctx_alloc_with_options(&iscc_options_args, options);
2617 pet_options_set_autodetect(ctx, 1);
2618 argc = isl_ctx_parse_options(ctx, argc, argv, ISL_ARG_ALL);
2619 s = isl_stream_new_file(ctx, stdin);
2620 assert(s);
2621 table = isl_hash_table_alloc(ctx, 10);
2622 assert(table);
2623 p = isl_printer_to_file(ctx, stdout);
2624 p = isl_printer_set_output_format(p, options->format);
2625 assert(p);
2627 register_named_ops(s);
2629 install_signal_handler(ctx);
2631 while (p && !isl_stream_is_empty(s)) {
2632 isl_ctx_resume(ctx);
2633 p = read_line(s, table, p, tty);
2636 remove_signal_handler(ctx);
2638 isl_printer_free(p);
2639 isl_hash_table_foreach(ctx, table, free_cb, NULL);
2640 isl_hash_table_free(ctx, table);
2641 isl_stream_free(s);
2642 isl_ctx_free(ctx);
2644 return 0;