update cloog for not using undocumented isl_set_extend
[barvinok.git] / iscc.c
blob05109b4390e5dc35765c99cb6951afe83839bdb2
1 #include <assert.h>
2 #include <ctype.h>
3 #include <stdio.h>
4 #include <string.h>
5 #include <unistd.h>
6 #include <isl/obj.h>
7 #include <isl/stream.h>
8 #include <isl/vertices.h>
9 #include <isl/flow.h>
10 #include <isl/band.h>
11 #include <isl/schedule.h>
12 #include <isl_obj_list.h>
13 #include <isl_obj_str.h>
14 #include <barvinok/isl.h>
15 #include <barvinok/options.h>
16 #include "lattice_width.h"
18 #include "config.h"
20 #ifdef HAVE_SIGACTION
21 #include <signal.h>
23 static isl_ctx *main_ctx;
25 static void handler(int signum)
27 if (isl_ctx_aborted(main_ctx))
28 exit(EXIT_FAILURE);
29 isl_ctx_abort(main_ctx);
32 static struct sigaction sa_old;
34 static void install_signal_handler(isl_ctx *ctx)
36 struct sigaction sa;
38 main_ctx = ctx;
40 memset(&sa, 0, sizeof(struct sigaction));
41 sa.sa_handler = &handler;
42 sa.sa_flags = SA_RESTART;
43 sigaction(SIGINT, &sa, &sa_old);
46 static void remove_signal_handler(isl_ctx *ctx)
48 sigaction(SIGINT, &sa_old, NULL);
51 #else
53 static void install_signal_handler(isl_ctx *ctx)
57 static void remove_signal_handler(isl_ctx *ctx)
61 #endif
63 #ifdef HAVE_CLOOG
64 #include <cloog/isl/cloog.h>
65 #endif
67 #ifdef HAVE_PET
68 #include <pet.h>
69 #endif
71 static int isl_bool_false = 0;
72 static int isl_bool_true = 1;
73 static int isl_bool_error = -1;
75 enum iscc_op { ISCC_READ, ISCC_WRITE, ISCC_SOURCE, ISCC_VERTICES,
76 ISCC_LAST, ISCC_ANY, ISCC_BEFORE, ISCC_UNDER,
77 ISCC_SCHEDULE, ISCC_SCHEDULE_FOREST,
78 ISCC_MINIMIZING, ISCC_RESPECTING,
79 ISCC_TYPEOF, ISCC_PRINT,
80 ISCC_N_OP };
81 static const char *op_name[ISCC_N_OP] = {
82 [ISCC_READ] = "read",
83 [ISCC_WRITE] = "write",
84 [ISCC_PRINT] = "print",
85 [ISCC_SOURCE] = "source",
86 [ISCC_VERTICES] = "vertices",
87 [ISCC_LAST] = "last",
88 [ISCC_ANY] = "any",
89 [ISCC_BEFORE] = "before",
90 [ISCC_UNDER] = "under",
91 [ISCC_SCHEDULE] = "schedule",
92 [ISCC_SCHEDULE_FOREST] = "schedule_forest",
93 [ISCC_MINIMIZING] = "minimizing",
94 [ISCC_RESPECTING] = "respecting",
95 [ISCC_TYPEOF] = "typeof"
97 static enum isl_token_type iscc_op[ISCC_N_OP];
99 struct isl_arg_choice iscc_format[] = {
100 {"isl", ISL_FORMAT_ISL},
101 {"omega", ISL_FORMAT_OMEGA},
102 {"polylib", ISL_FORMAT_POLYLIB},
103 {"ext-polylib", ISL_FORMAT_EXT_POLYLIB},
104 {"latex", ISL_FORMAT_LATEX},
105 {"C", ISL_FORMAT_C},
109 struct iscc_options {
110 struct barvinok_options *barvinok;
111 unsigned format;
112 int io;
115 struct isl_arg iscc_options_arg[] = {
116 ISL_ARG_CHILD(struct iscc_options, barvinok, "barvinok", barvinok_options_arg,
117 "barvinok options")
118 ISL_ARG_CHOICE(struct iscc_options, format, 0, "format", \
119 iscc_format, ISL_FORMAT_ISL, "output format")
120 ISL_ARG_BOOL(struct iscc_options, io, 0, "io", 1,
121 "allow read and write operations")
122 ISL_ARG_END
125 ISL_ARG_DEF(iscc_options, struct iscc_options, iscc_options_arg)
126 ISL_ARG_CTX_DEF(iscc_options, struct iscc_options, iscc_options_arg)
128 static void *isl_obj_bool_copy(void *v)
130 return v;
133 static void isl_obj_bool_free(void *v)
137 static __isl_give isl_printer *isl_obj_bool_print(__isl_take isl_printer *p,
138 void *v)
140 if (v == &isl_bool_true)
141 return isl_printer_print_str(p, "True");
142 else if (v == &isl_bool_false)
143 return isl_printer_print_str(p, "False");
144 else
145 return isl_printer_print_str(p, "Error");
148 static void *isl_obj_bool_add(void *v1, void *v2)
150 return v1;
153 struct isl_obj_vtable isl_obj_bool_vtable = {
154 isl_obj_bool_copy,
155 isl_obj_bool_add,
156 isl_obj_bool_print,
157 isl_obj_bool_free
159 #define isl_obj_bool (&isl_obj_bool_vtable)
161 int *isl_bool_from_int(int res)
163 return res < 0 ? &isl_bool_error : res ? &isl_bool_true : &isl_bool_false;
166 int *union_map_is_equal(__isl_take isl_union_map *map1,
167 __isl_take isl_union_map *map2)
169 int res = isl_union_map_is_equal(map1, map2);
170 isl_union_map_free(map1);
171 isl_union_map_free(map2);
172 return isl_bool_from_int(res);
174 int *union_set_is_equal(__isl_take isl_union_set *set1,
175 __isl_take isl_union_set *set2)
177 return union_map_is_equal((isl_union_map *)set1, (isl_union_map *)set2);
180 int *union_map_is_subset(__isl_take isl_union_map *map1,
181 __isl_take isl_union_map *map2)
183 int res = isl_union_map_is_subset(map1, map2);
184 isl_union_map_free(map1);
185 isl_union_map_free(map2);
186 return isl_bool_from_int(res);
188 int *union_set_is_subset(__isl_take isl_union_set *set1,
189 __isl_take isl_union_set *set2)
191 return union_map_is_subset((isl_union_map *)set1, (isl_union_map *)set2);
194 int *union_map_is_strict_subset(__isl_take isl_union_map *map1,
195 __isl_take isl_union_map *map2)
197 int res = isl_union_map_is_strict_subset(map1, map2);
198 isl_union_map_free(map1);
199 isl_union_map_free(map2);
200 return isl_bool_from_int(res);
202 int *union_set_is_strict_subset(__isl_take isl_union_set *set1,
203 __isl_take isl_union_set *set2)
205 return union_map_is_strict_subset((isl_union_map *)set1,
206 (isl_union_map *)set2);
209 int *union_map_is_superset(__isl_take isl_union_map *map1,
210 __isl_take isl_union_map *map2)
212 return union_map_is_subset(map2, map1);
214 int *union_set_is_superset(__isl_take isl_union_set *set1,
215 __isl_take isl_union_set *set2)
217 return union_set_is_subset(set2, set1);
220 int *union_map_is_strict_superset(__isl_take isl_union_map *map1,
221 __isl_take isl_union_map *map2)
223 return union_map_is_strict_subset(map2, map1);
225 int *union_set_is_strict_superset(__isl_take isl_union_set *set1,
226 __isl_take isl_union_set *set2)
228 return union_set_is_strict_subset(set2, set1);
231 extern struct isl_obj_vtable isl_obj_list_vtable;
232 #define isl_obj_list (&isl_obj_list_vtable)
234 typedef void *(*isc_bin_op_fn)(void *lhs, void *rhs);
235 struct isc_bin_op {
236 enum isl_token_type op;
237 isl_obj_type lhs;
238 isl_obj_type rhs;
239 isl_obj_type res;
240 isc_bin_op_fn fn;
242 struct isc_named_bin_op {
243 char *name;
244 struct isc_bin_op op;
247 struct iscc_at {
248 isl_union_pw_qpolynomial *upwqp;
249 isl_union_pw_qpolynomial *res;
252 static int eval_at(__isl_take isl_point *pnt, void *user)
254 struct iscc_at *at = (struct iscc_at *) user;
255 isl_qpolynomial *qp;
256 isl_set *set;
258 set = isl_set_from_point(isl_point_copy(pnt));
259 qp = isl_union_pw_qpolynomial_eval(
260 isl_union_pw_qpolynomial_copy(at->upwqp), pnt);
262 at->res = isl_union_pw_qpolynomial_add(at->res,
263 isl_union_pw_qpolynomial_from_pw_qpolynomial(
264 isl_pw_qpolynomial_alloc(set, qp)));
266 return 0;
269 __isl_give isl_union_pw_qpolynomial *isl_union_pw_qpolynomial_at(
270 __isl_take isl_union_pw_qpolynomial *upwqp,
271 __isl_take isl_union_set *uset)
273 struct iscc_at at;
275 at.upwqp = upwqp;
276 at.res = isl_union_pw_qpolynomial_zero(isl_union_set_get_space(uset));
278 isl_union_set_foreach_point(uset, eval_at, &at);
280 isl_union_pw_qpolynomial_free(upwqp);
281 isl_union_set_free(uset);
283 return at.res;
286 struct iscc_fold_at {
287 isl_union_pw_qpolynomial_fold *upwf;
288 isl_union_pw_qpolynomial *res;
291 static int eval_fold_at(__isl_take isl_point *pnt, void *user)
293 struct iscc_fold_at *at = (struct iscc_fold_at *) user;
294 isl_qpolynomial *qp;
295 isl_set *set;
297 set = isl_set_from_point(isl_point_copy(pnt));
298 qp = isl_union_pw_qpolynomial_fold_eval(
299 isl_union_pw_qpolynomial_fold_copy(at->upwf), pnt);
301 at->res = isl_union_pw_qpolynomial_add(at->res,
302 isl_union_pw_qpolynomial_from_pw_qpolynomial(
303 isl_pw_qpolynomial_alloc(set, qp)));
305 return 0;
308 __isl_give isl_union_pw_qpolynomial *isl_union_pw_qpolynomial_fold_at(
309 __isl_take isl_union_pw_qpolynomial_fold *upwf,
310 __isl_take isl_union_set *uset)
312 struct iscc_fold_at at;
314 at.upwf = upwf;
315 at.res = isl_union_pw_qpolynomial_zero(isl_union_set_get_space(uset));
317 isl_union_set_foreach_point(uset, eval_fold_at, &at);
319 isl_union_pw_qpolynomial_fold_free(upwf);
320 isl_union_set_free(uset);
322 return at.res;
325 static __isl_give isl_union_pw_qpolynomial_fold *union_pw_qpolynomial_add_union_pw_qpolynomial_fold(
326 __isl_take isl_union_pw_qpolynomial *upwqp,
327 __isl_take isl_union_pw_qpolynomial_fold *upwf)
329 return isl_union_pw_qpolynomial_fold_add_union_pw_qpolynomial(upwf,
330 upwqp);
333 static __isl_give struct isl_list *union_map_apply_union_pw_qpolynomial_fold(
334 __isl_take isl_union_map *umap,
335 __isl_take isl_union_pw_qpolynomial_fold *upwf)
337 isl_ctx *ctx;
338 struct isl_list *list;
339 int tight;
341 ctx = isl_union_map_get_ctx(umap);
342 list = isl_list_alloc(ctx, 2);
343 if (!list)
344 goto error2;
346 list->obj[0].type = isl_obj_union_pw_qpolynomial_fold;
347 list->obj[0].v = isl_union_map_apply_union_pw_qpolynomial_fold(umap,
348 upwf, &tight);
349 list->obj[1].type = isl_obj_bool;
350 list->obj[1].v = tight ? &isl_bool_true : &isl_bool_false;
351 if (tight < 0 || !list->obj[0].v)
352 goto error;
354 return list;
355 error2:
356 isl_union_map_free(umap);
357 isl_union_pw_qpolynomial_fold_free(upwf);
358 error:
359 isl_list_free(list);
360 return NULL;
363 static __isl_give isl_union_pw_qpolynomial *union_pw_qpolynomial_int_mul(
364 __isl_take isl_union_pw_qpolynomial *upwqp, __isl_take isl_int_obj *i)
366 isl_int v;
368 if (!i)
369 goto error;
371 isl_int_init(v);
372 isl_int_obj_get_int(i, &v);
373 upwqp = isl_union_pw_qpolynomial_mul_isl_int(upwqp, v);
374 isl_int_clear(v);
376 isl_int_obj_free(i);
378 return upwqp;
379 error:
380 isl_union_pw_qpolynomial_free(upwqp);
381 return NULL;
384 static __isl_give isl_union_pw_qpolynomial *int_union_pw_qpolynomial_mul(
385 __isl_take isl_int_obj *i, __isl_take isl_union_pw_qpolynomial *upwqp)
387 return union_pw_qpolynomial_int_mul(upwqp, i);
390 static __isl_give isl_union_pw_qpolynomial_fold *union_pw_qpolynomial_fold_int_mul(
391 __isl_take isl_union_pw_qpolynomial_fold *upwf,
392 __isl_take isl_int_obj *i)
394 isl_int v;
396 if (!i)
397 goto error;
399 isl_int_init(v);
400 isl_int_obj_get_int(i, &v);
401 upwf = isl_union_pw_qpolynomial_fold_mul_isl_int(upwf, v);
402 isl_int_clear(v);
404 isl_int_obj_free(i);
406 return upwf;
407 error:
408 isl_union_pw_qpolynomial_fold_free(upwf);
409 return NULL;
412 static __isl_give isl_union_pw_qpolynomial_fold *int_union_pw_qpolynomial_fold_mul(
413 __isl_take isl_int_obj *i,
414 __isl_take isl_union_pw_qpolynomial_fold *upwf)
416 return union_pw_qpolynomial_fold_int_mul(upwf, i);
419 struct isc_bin_op bin_ops[] = {
420 { '+', isl_obj_int, isl_obj_int, isl_obj_int,
421 (isc_bin_op_fn) &isl_int_obj_add },
422 { '-', isl_obj_int, isl_obj_int, isl_obj_int,
423 (isc_bin_op_fn) &isl_int_obj_sub },
424 { '*', isl_obj_int, isl_obj_int, isl_obj_int,
425 (isc_bin_op_fn) &isl_int_obj_mul },
426 { '+', isl_obj_union_set, isl_obj_union_set,
427 isl_obj_union_set,
428 (isc_bin_op_fn) &isl_union_set_union },
429 { '+', isl_obj_union_map, isl_obj_union_map,
430 isl_obj_union_map,
431 (isc_bin_op_fn) &isl_union_map_union },
432 { '-', isl_obj_union_set, isl_obj_union_set,
433 isl_obj_union_set,
434 (isc_bin_op_fn) &isl_union_set_subtract },
435 { '-', isl_obj_union_map, isl_obj_union_map,
436 isl_obj_union_map,
437 (isc_bin_op_fn) &isl_union_map_subtract },
438 { '*', isl_obj_union_set, isl_obj_union_set,
439 isl_obj_union_set,
440 (isc_bin_op_fn) &isl_union_set_intersect },
441 { '*', isl_obj_union_map, isl_obj_union_map,
442 isl_obj_union_map,
443 (isc_bin_op_fn) &isl_union_map_intersect },
444 { '*', isl_obj_union_map, isl_obj_union_set,
445 isl_obj_union_map,
446 (isc_bin_op_fn) &isl_union_map_intersect_domain },
447 { '.', isl_obj_union_map, isl_obj_union_map,
448 isl_obj_union_map,
449 (isc_bin_op_fn) &isl_union_map_apply_range },
450 { '.', isl_obj_union_map, isl_obj_union_pw_qpolynomial,
451 isl_obj_union_pw_qpolynomial,
452 (isc_bin_op_fn) &isl_union_map_apply_union_pw_qpolynomial },
453 { '.', isl_obj_union_map, isl_obj_union_pw_qpolynomial_fold,
454 isl_obj_list,
455 (isc_bin_op_fn) &union_map_apply_union_pw_qpolynomial_fold },
456 { ISL_TOKEN_TO, isl_obj_union_set, isl_obj_union_set,
457 isl_obj_union_map,
458 (isc_bin_op_fn) &isl_union_map_from_domain_and_range },
459 { '=', isl_obj_union_set, isl_obj_union_set, isl_obj_bool,
460 (isc_bin_op_fn) &union_set_is_equal },
461 { '=', isl_obj_union_map, isl_obj_union_map, isl_obj_bool,
462 (isc_bin_op_fn) &union_map_is_equal },
463 { ISL_TOKEN_LE, isl_obj_union_set, isl_obj_union_set,
464 isl_obj_bool, (isc_bin_op_fn) &union_set_is_subset },
465 { ISL_TOKEN_LE, isl_obj_union_map, isl_obj_union_map,
466 isl_obj_bool, (isc_bin_op_fn) &union_map_is_subset },
467 { ISL_TOKEN_LT, isl_obj_union_set, isl_obj_union_set,
468 isl_obj_bool, (isc_bin_op_fn) &union_set_is_strict_subset },
469 { ISL_TOKEN_LT, isl_obj_union_map, isl_obj_union_map,
470 isl_obj_bool, (isc_bin_op_fn) &union_map_is_strict_subset },
471 { ISL_TOKEN_GE, isl_obj_union_set, isl_obj_union_set,
472 isl_obj_bool, (isc_bin_op_fn) &union_set_is_superset },
473 { ISL_TOKEN_GE, isl_obj_union_map, isl_obj_union_map,
474 isl_obj_bool, (isc_bin_op_fn) &union_map_is_superset },
475 { ISL_TOKEN_GT, isl_obj_union_set, isl_obj_union_set,
476 isl_obj_bool, (isc_bin_op_fn) &union_set_is_strict_superset },
477 { ISL_TOKEN_GT, isl_obj_union_map, isl_obj_union_map,
478 isl_obj_bool, (isc_bin_op_fn) &union_map_is_strict_superset },
479 { ISL_TOKEN_LEX_LE, isl_obj_union_set, isl_obj_union_set,
480 isl_obj_union_map,
481 (isc_bin_op_fn) &isl_union_set_lex_le_union_set },
482 { ISL_TOKEN_LEX_LT, isl_obj_union_set, isl_obj_union_set,
483 isl_obj_union_map,
484 (isc_bin_op_fn) &isl_union_set_lex_lt_union_set },
485 { ISL_TOKEN_LEX_GE, isl_obj_union_set, isl_obj_union_set,
486 isl_obj_union_map,
487 (isc_bin_op_fn) &isl_union_set_lex_ge_union_set },
488 { ISL_TOKEN_LEX_GT, isl_obj_union_set, isl_obj_union_set,
489 isl_obj_union_map,
490 (isc_bin_op_fn) &isl_union_set_lex_gt_union_set },
491 { ISL_TOKEN_LEX_LE, isl_obj_union_map, isl_obj_union_map,
492 isl_obj_union_map,
493 (isc_bin_op_fn) &isl_union_map_lex_le_union_map },
494 { ISL_TOKEN_LEX_LT, isl_obj_union_map, isl_obj_union_map,
495 isl_obj_union_map,
496 (isc_bin_op_fn) &isl_union_map_lex_lt_union_map },
497 { ISL_TOKEN_LEX_GE, isl_obj_union_map, isl_obj_union_map,
498 isl_obj_union_map,
499 (isc_bin_op_fn) &isl_union_map_lex_ge_union_map },
500 { ISL_TOKEN_LEX_GT, isl_obj_union_map, isl_obj_union_map,
501 isl_obj_union_map,
502 (isc_bin_op_fn) &isl_union_map_lex_gt_union_map },
503 { '.', isl_obj_union_pw_qpolynomial_fold,
504 isl_obj_union_pw_qpolynomial_fold,
505 isl_obj_union_pw_qpolynomial_fold,
506 (isc_bin_op_fn) &isl_union_pw_qpolynomial_fold_fold },
507 { '+', isl_obj_union_pw_qpolynomial, isl_obj_union_pw_qpolynomial,
508 isl_obj_union_pw_qpolynomial,
509 (isc_bin_op_fn) &isl_union_pw_qpolynomial_add },
510 { '+', isl_obj_union_pw_qpolynomial,
511 isl_obj_union_pw_qpolynomial_fold,
512 isl_obj_union_pw_qpolynomial_fold,
513 (isc_bin_op_fn) &union_pw_qpolynomial_add_union_pw_qpolynomial_fold },
514 { '+', isl_obj_union_pw_qpolynomial_fold,
515 isl_obj_union_pw_qpolynomial,
516 isl_obj_union_pw_qpolynomial_fold,
517 (isc_bin_op_fn) &isl_union_pw_qpolynomial_fold_add_union_pw_qpolynomial },
518 { '-', isl_obj_union_pw_qpolynomial, isl_obj_union_pw_qpolynomial,
519 isl_obj_union_pw_qpolynomial,
520 (isc_bin_op_fn) &isl_union_pw_qpolynomial_sub },
521 { '*', isl_obj_int, isl_obj_union_pw_qpolynomial,
522 isl_obj_union_pw_qpolynomial,
523 (isc_bin_op_fn) &int_union_pw_qpolynomial_mul },
524 { '*', isl_obj_union_pw_qpolynomial, isl_obj_int,
525 isl_obj_union_pw_qpolynomial,
526 (isc_bin_op_fn) &union_pw_qpolynomial_int_mul },
527 { '*', isl_obj_int, isl_obj_union_pw_qpolynomial_fold,
528 isl_obj_union_pw_qpolynomial_fold,
529 (isc_bin_op_fn) &int_union_pw_qpolynomial_fold_mul },
530 { '*', isl_obj_union_pw_qpolynomial_fold, isl_obj_int,
531 isl_obj_union_pw_qpolynomial_fold,
532 (isc_bin_op_fn) &union_pw_qpolynomial_fold_int_mul },
533 { '*', isl_obj_union_pw_qpolynomial, isl_obj_union_pw_qpolynomial,
534 isl_obj_union_pw_qpolynomial,
535 (isc_bin_op_fn) &isl_union_pw_qpolynomial_mul },
536 { '*', isl_obj_union_pw_qpolynomial, isl_obj_union_set,
537 isl_obj_union_pw_qpolynomial,
538 (isc_bin_op_fn) &isl_union_pw_qpolynomial_intersect_domain },
539 { '*', isl_obj_union_pw_qpolynomial_fold, isl_obj_union_set,
540 isl_obj_union_pw_qpolynomial_fold,
541 (isc_bin_op_fn) &isl_union_pw_qpolynomial_fold_intersect_domain },
542 { '@', isl_obj_union_pw_qpolynomial, isl_obj_union_set,
543 isl_obj_union_pw_qpolynomial,
544 (isc_bin_op_fn) &isl_union_pw_qpolynomial_at },
545 { '@', isl_obj_union_pw_qpolynomial_fold, isl_obj_union_set,
546 isl_obj_union_pw_qpolynomial,
547 (isc_bin_op_fn) &isl_union_pw_qpolynomial_fold_at },
548 { '%', isl_obj_union_set, isl_obj_union_set,
549 isl_obj_union_set,
550 (isc_bin_op_fn) &isl_union_set_gist },
551 { '%', isl_obj_union_map, isl_obj_union_map,
552 isl_obj_union_map,
553 (isc_bin_op_fn) &isl_union_map_gist },
554 { '%', isl_obj_union_pw_qpolynomial, isl_obj_union_set,
555 isl_obj_union_pw_qpolynomial,
556 (isc_bin_op_fn) &isl_union_pw_qpolynomial_gist },
557 { '%', isl_obj_union_pw_qpolynomial_fold, isl_obj_union_set,
558 isl_obj_union_pw_qpolynomial_fold,
559 (isc_bin_op_fn) &isl_union_pw_qpolynomial_fold_gist },
560 { '+', isl_obj_str, isl_obj_str, isl_obj_str,
561 (isc_bin_op_fn) &isl_str_concat },
565 static __isl_give isl_union_map *map_after_map(__isl_take isl_union_map *umap1,
566 __isl_take isl_union_map *umap2)
568 return isl_union_map_apply_range(umap2, umap1);
571 static __isl_give isl_union_pw_qpolynomial *qpolynomial_after_map(
572 __isl_take isl_union_pw_qpolynomial *upwqp,
573 __isl_take isl_union_map *umap)
575 return isl_union_map_apply_union_pw_qpolynomial(umap, upwqp);
578 static __isl_give struct isl_list *qpolynomial_fold_after_map(
579 __isl_take isl_union_pw_qpolynomial_fold *upwf,
580 __isl_take isl_union_map *umap)
582 return union_map_apply_union_pw_qpolynomial_fold(umap, upwf);
585 struct isc_named_bin_op named_bin_ops[] = {
586 { "after", { -1, isl_obj_union_map, isl_obj_union_map,
587 isl_obj_union_map,
588 (isc_bin_op_fn) &map_after_map } },
589 { "after", { -1, isl_obj_union_pw_qpolynomial,
590 isl_obj_union_map, isl_obj_union_pw_qpolynomial,
591 (isc_bin_op_fn) &qpolynomial_after_map } },
592 { "after", { -1, isl_obj_union_pw_qpolynomial_fold,
593 isl_obj_union_map, isl_obj_list,
594 (isc_bin_op_fn) &qpolynomial_fold_after_map } },
595 { "before", { -1, isl_obj_union_map, isl_obj_union_map,
596 isl_obj_union_map,
597 (isc_bin_op_fn) &isl_union_map_apply_range } },
598 { "before", { -1, isl_obj_union_map,
599 isl_obj_union_pw_qpolynomial, isl_obj_union_pw_qpolynomial,
600 (isc_bin_op_fn) &isl_union_map_apply_union_pw_qpolynomial } },
601 { "before", { -1, isl_obj_union_map,
602 isl_obj_union_pw_qpolynomial_fold, isl_obj_list,
603 (isc_bin_op_fn) &union_map_apply_union_pw_qpolynomial_fold } },
604 { "cross", { -1, isl_obj_union_set, isl_obj_union_set,
605 isl_obj_union_set,
606 (isc_bin_op_fn) &isl_union_set_product } },
607 { "cross", { -1, isl_obj_union_map, isl_obj_union_map,
608 isl_obj_union_map,
609 (isc_bin_op_fn) &isl_union_map_product } },
610 NULL
613 __isl_give isl_set *union_set_sample(__isl_take isl_union_set *uset)
615 return isl_set_from_basic_set(isl_union_set_sample(uset));
618 __isl_give isl_map *union_map_sample(__isl_take isl_union_map *umap)
620 return isl_map_from_basic_map(isl_union_map_sample(umap));
623 static __isl_give struct isl_list *union_map_power(
624 __isl_take isl_union_map *umap)
626 isl_ctx *ctx;
627 struct isl_list *list;
628 int exact;
630 ctx = isl_union_map_get_ctx(umap);
631 list = isl_list_alloc(ctx, 2);
632 if (!list)
633 goto error2;
635 list->obj[0].type = isl_obj_union_map;
636 list->obj[0].v = isl_union_map_power(umap, &exact);
637 list->obj[1].type = isl_obj_bool;
638 list->obj[1].v = exact ? &isl_bool_true : &isl_bool_false;
639 if (exact < 0 || !list->obj[0].v)
640 goto error;
642 return list;
643 error2:
644 isl_union_map_free(umap);
645 error:
646 isl_list_free(list);
647 return NULL;
650 static __isl_give struct isl_list *union_pw_qpolynomial_upper_bound(
651 __isl_take isl_union_pw_qpolynomial *upwqp)
653 isl_ctx *ctx;
654 struct isl_list *list;
655 int tight;
657 ctx = isl_union_pw_qpolynomial_get_ctx(upwqp);
658 list = isl_list_alloc(ctx, 2);
659 if (!list)
660 goto error2;
662 list->obj[0].type = isl_obj_union_pw_qpolynomial_fold;
663 list->obj[0].v = isl_union_pw_qpolynomial_bound(upwqp,
664 isl_fold_max, &tight);
665 list->obj[1].type = isl_obj_bool;
666 list->obj[1].v = tight ? &isl_bool_true : &isl_bool_false;
667 if (tight < 0 || !list->obj[0].v)
668 goto error;
670 return list;
671 error2:
672 isl_union_pw_qpolynomial_free(upwqp);
673 error:
674 isl_list_free(list);
675 return NULL;
678 #ifdef HAVE_CLOOG
679 void *map_codegen(void *arg)
681 isl_space *dim;
682 isl_union_map *umap = (isl_union_map *)arg;
683 isl_ctx *ctx = isl_union_map_get_ctx(umap);
684 CloogState *state;
685 CloogOptions *options;
686 CloogDomain *context;
687 CloogUnionDomain *ud;
688 CloogInput *input;
689 struct clast_stmt *stmt;
691 state = cloog_isl_state_malloc(ctx);
692 options = cloog_options_malloc(state);
693 options->language = LANGUAGE_C;
694 options->strides = 1;
695 options->sh = 1;
697 ud = cloog_union_domain_from_isl_union_map(isl_union_map_copy(umap));
699 dim = isl_union_map_get_space(umap);
700 context = cloog_domain_from_isl_set(isl_set_universe(dim));
702 input = cloog_input_alloc(context, ud);
704 stmt = cloog_clast_create_from_input(input, options);
705 clast_pprint(stdout, stmt, 0, options);
706 cloog_clast_free(stmt);
708 error:
709 cloog_options_free(options);
710 cloog_state_free(state);
711 isl_union_map_free(umap);
712 return NULL;
715 void *set_codegen(void *arg)
717 isl_space *dim;
718 isl_union_set *uset = (isl_union_set *)arg;
719 isl_ctx *ctx = isl_union_set_get_ctx(uset);
720 CloogState *state;
721 CloogOptions *options;
722 CloogDomain *context;
723 CloogUnionDomain *ud;
724 CloogInput *input;
725 struct clast_stmt *stmt;
727 if (isl_union_set_n_set(uset) > 1)
728 isl_die(ctx, isl_error_invalid,
729 "code generation for more than one domain "
730 "requires a schedule", goto error);
732 state = cloog_isl_state_malloc(ctx);
733 options = cloog_options_malloc(state);
734 options->language = LANGUAGE_C;
735 options->strides = 1;
736 options->sh = 1;
738 ud = cloog_union_domain_from_isl_union_set(isl_union_set_copy(uset));
740 dim = isl_union_set_get_space(uset);
741 context = cloog_domain_from_isl_set(isl_set_universe(dim));
743 input = cloog_input_alloc(context, ud);
745 stmt = cloog_clast_create_from_input(input, options);
746 clast_pprint(stdout, stmt, 0, options);
747 cloog_clast_free(stmt);
749 cloog_options_free(options);
750 cloog_state_free(state);
751 error:
752 isl_union_set_free(uset);
753 return NULL;
755 #endif
757 #ifdef HAVE_PET
758 static __isl_give isl_list *parse(__isl_take isl_str *str)
760 isl_ctx *ctx;
761 struct isl_list *list;
762 struct pet_scop *scop;
763 isl_union_map *sched, *reads, *writes;
764 isl_union_set *domain;
765 struct iscc_options *options;
767 if (!str)
768 return NULL;
769 ctx = str->ctx;
771 options = isl_ctx_peek_iscc_options(ctx);
772 if (!options || !options->io) {
773 isl_str_free(str);
774 isl_die(ctx, isl_error_invalid,
775 "parse_file operation not allowed", return NULL);
778 list = isl_list_alloc(ctx, 4);
779 if (!list)
780 goto error;
782 scop = pet_scop_extract_from_C_source(ctx, str->s, NULL, 1);
783 domain = pet_scop_collect_domains(scop);
784 sched = pet_scop_collect_schedule(scop);
785 reads = pet_scop_collect_reads(scop);
786 writes = pet_scop_collect_writes(scop);
787 pet_scop_free(scop);
789 list->obj[0].type = isl_obj_union_set;
790 list->obj[0].v = domain;
791 list->obj[1].type = isl_obj_union_map;
792 list->obj[1].v = writes;
793 list->obj[2].type = isl_obj_union_map;
794 list->obj[2].v = reads;
795 list->obj[3].type = isl_obj_union_map;
796 list->obj[3].v = sched;
798 if (!list->obj[0].v || !list->obj[1].v ||
799 !list->obj[2].v || !list->obj[3].v)
800 goto error;
802 isl_str_free(str);
803 return list;
804 error:
805 isl_list_free(list);
806 isl_str_free(str);
807 return NULL;
809 #endif
811 static int add_point(__isl_take isl_point *pnt, void *user)
813 isl_union_set **scan = (isl_union_set **) user;
815 *scan = isl_union_set_add_set(*scan, isl_set_from_point(pnt));
817 return 0;
820 static __isl_give isl_union_set *union_set_scan(__isl_take isl_union_set *uset)
822 isl_union_set *scan;
824 scan = isl_union_set_empty(isl_union_set_get_space(uset));
826 if (isl_union_set_foreach_point(uset, add_point, &scan) < 0) {
827 isl_union_set_free(scan);
828 return uset;
831 isl_union_set_free(uset);
832 return scan;
835 static __isl_give isl_union_map *union_map_scan(__isl_take isl_union_map *umap)
837 return isl_union_set_unwrap(union_set_scan(isl_union_map_wrap(umap)));
840 static __isl_give isl_union_pw_qpolynomial *union_pw_qpolynomial_poly(
841 __isl_take isl_union_pw_qpolynomial *upwqp)
843 return isl_union_pw_qpolynomial_to_polynomial(upwqp, 0);
846 static __isl_give isl_union_pw_qpolynomial *union_pw_qpolynomial_lpoly(
847 __isl_take isl_union_pw_qpolynomial *upwqp)
849 return isl_union_pw_qpolynomial_to_polynomial(upwqp, -1);
852 static __isl_give isl_union_pw_qpolynomial *union_pw_qpolynomial_upoly(
853 __isl_take isl_union_pw_qpolynomial *upwqp)
855 return isl_union_pw_qpolynomial_to_polynomial(upwqp, 1);
858 typedef void *(*isc_un_op_fn)(void *arg);
859 struct isc_un_op {
860 enum isl_token_type op;
861 isl_obj_type arg;
862 isl_obj_type res;
863 isc_un_op_fn fn;
865 struct isc_named_un_op {
866 char *name;
867 struct isc_un_op op;
869 struct isc_named_un_op named_un_ops[] = {
870 {"aff", { -1, isl_obj_union_map, isl_obj_union_map,
871 (isc_un_op_fn) &isl_union_map_affine_hull } },
872 {"aff", { -1, isl_obj_union_set, isl_obj_union_set,
873 (isc_un_op_fn) &isl_union_set_affine_hull } },
874 {"card", { -1, isl_obj_union_set,
875 isl_obj_union_pw_qpolynomial,
876 (isc_un_op_fn) &isl_union_set_card } },
877 {"card", { -1, isl_obj_union_map,
878 isl_obj_union_pw_qpolynomial,
879 (isc_un_op_fn) &isl_union_map_card } },
880 {"coalesce", { -1, isl_obj_union_set, isl_obj_union_set,
881 (isc_un_op_fn) &isl_union_set_coalesce } },
882 {"coalesce", { -1, isl_obj_union_map, isl_obj_union_map,
883 (isc_un_op_fn) &isl_union_map_coalesce } },
884 {"coalesce", { -1, isl_obj_union_pw_qpolynomial,
885 isl_obj_union_pw_qpolynomial,
886 (isc_un_op_fn) &isl_union_pw_qpolynomial_coalesce } },
887 {"coalesce", { -1, isl_obj_union_pw_qpolynomial_fold,
888 isl_obj_union_pw_qpolynomial_fold,
889 (isc_un_op_fn) &isl_union_pw_qpolynomial_fold_coalesce } },
890 #ifdef HAVE_CLOOG
891 {"codegen", { -1, isl_obj_union_set, isl_obj_none,
892 &set_codegen } },
893 {"codegen", { -1, isl_obj_union_map, isl_obj_none,
894 &map_codegen } },
895 #endif
896 {"coefficients", { -1, isl_obj_union_set,
897 isl_obj_union_set,
898 (isc_un_op_fn) &isl_union_set_coefficients } },
899 {"solutions", { -1, isl_obj_union_set, isl_obj_union_set,
900 (isc_un_op_fn) &isl_union_set_solutions } },
901 {"deltas", { -1, isl_obj_union_map, isl_obj_union_set,
902 (isc_un_op_fn) &isl_union_map_deltas } },
903 {"deltas_map", { -1, isl_obj_union_map, isl_obj_union_map,
904 (isc_un_op_fn) &isl_union_map_deltas_map } },
905 {"dom", { -1, isl_obj_union_map, isl_obj_union_set,
906 (isc_un_op_fn) &isl_union_map_domain } },
907 {"dom", { -1, isl_obj_union_pw_qpolynomial, isl_obj_union_set,
908 (isc_un_op_fn) &isl_union_pw_qpolynomial_domain } },
909 {"dom", { -1, isl_obj_union_pw_qpolynomial_fold,
910 isl_obj_union_set,
911 (isc_un_op_fn) &isl_union_pw_qpolynomial_fold_domain } },
912 {"domain", { -1, isl_obj_union_map, isl_obj_union_set,
913 (isc_un_op_fn) &isl_union_map_domain } },
914 {"domain", { -1, isl_obj_union_pw_qpolynomial,
915 isl_obj_union_set,
916 (isc_un_op_fn) &isl_union_pw_qpolynomial_domain } },
917 {"domain", { -1, isl_obj_union_pw_qpolynomial_fold,
918 isl_obj_union_set,
919 (isc_un_op_fn) &isl_union_pw_qpolynomial_fold_domain } },
920 {"domain_map", { -1, isl_obj_union_map, isl_obj_union_map,
921 (isc_un_op_fn) &isl_union_map_domain_map } },
922 {"ran", { -1, isl_obj_union_map, isl_obj_union_set,
923 (isc_un_op_fn) &isl_union_map_range } },
924 {"range", { -1, isl_obj_union_map, isl_obj_union_set,
925 (isc_un_op_fn) &isl_union_map_range } },
926 {"range_map", { -1, isl_obj_union_map, isl_obj_union_map,
927 (isc_un_op_fn) &isl_union_map_range_map } },
928 {"identity", { -1, isl_obj_union_set, isl_obj_union_map,
929 (isc_un_op_fn) &isl_union_set_identity } },
930 {"lattice_width", { -1, isl_obj_union_set,
931 isl_obj_union_pw_qpolynomial,
932 (isc_un_op_fn) &isl_union_set_lattice_width } },
933 {"lexmin", { -1, isl_obj_union_map, isl_obj_union_map,
934 (isc_un_op_fn) &isl_union_map_lexmin } },
935 {"lexmax", { -1, isl_obj_union_map, isl_obj_union_map,
936 (isc_un_op_fn) &isl_union_map_lexmax } },
937 {"lexmin", { -1, isl_obj_union_set, isl_obj_union_set,
938 (isc_un_op_fn) &isl_union_set_lexmin } },
939 {"lexmax", { -1, isl_obj_union_set, isl_obj_union_set,
940 (isc_un_op_fn) &isl_union_set_lexmax } },
941 {"lift", { -1, isl_obj_union_set, isl_obj_union_set,
942 (isc_un_op_fn) &isl_union_set_lift } },
943 {"poly", { -1, isl_obj_union_map, isl_obj_union_map,
944 (isc_un_op_fn) &isl_union_map_polyhedral_hull } },
945 {"poly", { -1, isl_obj_union_set, isl_obj_union_set,
946 (isc_un_op_fn) &isl_union_set_polyhedral_hull } },
947 {"poly", { -1, isl_obj_union_pw_qpolynomial,
948 isl_obj_union_pw_qpolynomial,
949 (isc_un_op_fn) &union_pw_qpolynomial_poly } },
950 {"lpoly", { -1, isl_obj_union_pw_qpolynomial,
951 isl_obj_union_pw_qpolynomial,
952 (isc_un_op_fn) &union_pw_qpolynomial_lpoly } },
953 {"upoly", { -1, isl_obj_union_pw_qpolynomial,
954 isl_obj_union_pw_qpolynomial,
955 (isc_un_op_fn) &union_pw_qpolynomial_upoly } },
956 #ifdef HAVE_PET
957 {"parse_file", { -1, isl_obj_str, isl_obj_list,
958 (isc_un_op_fn) &parse } },
959 #endif
960 {"pow", { -1, isl_obj_union_map, isl_obj_list,
961 (isc_un_op_fn) &union_map_power } },
962 {"sample", { -1, isl_obj_union_set, isl_obj_set,
963 (isc_un_op_fn) &union_set_sample } },
964 {"sample", { -1, isl_obj_union_map, isl_obj_map,
965 (isc_un_op_fn) &union_map_sample } },
966 {"scan", { -1, isl_obj_union_set, isl_obj_union_set,
967 (isc_un_op_fn) &union_set_scan } },
968 {"scan", { -1, isl_obj_union_map, isl_obj_union_map,
969 (isc_un_op_fn) &union_map_scan } },
970 {"sum", { -1, isl_obj_union_pw_qpolynomial,
971 isl_obj_union_pw_qpolynomial,
972 (isc_un_op_fn) &isl_union_pw_qpolynomial_sum } },
973 {"ub", { -1, isl_obj_union_pw_qpolynomial, isl_obj_list,
974 (isc_un_op_fn) &union_pw_qpolynomial_upper_bound } },
975 {"unwrap", { -1, isl_obj_union_set, isl_obj_union_map,
976 (isc_un_op_fn) &isl_union_set_unwrap } },
977 {"wrap", { -1, isl_obj_union_map, isl_obj_union_set,
978 (isc_un_op_fn) &isl_union_map_wrap } },
979 {"zip", { -1, isl_obj_union_map, isl_obj_union_map,
980 (isc_un_op_fn) &isl_union_map_zip } },
981 NULL
984 struct isl_named_obj {
985 char *name;
986 struct isl_obj obj;
989 static void free_obj(struct isl_obj obj)
991 obj.type->free(obj.v);
994 static int same_name(const void *entry, const void *val)
996 const struct isl_named_obj *named = (const struct isl_named_obj *)entry;
998 return !strcmp(named->name, val);
1001 static int do_assign(struct isl_ctx *ctx, struct isl_hash_table *table,
1002 char *name, struct isl_obj obj)
1004 struct isl_hash_table_entry *entry;
1005 uint32_t name_hash;
1006 struct isl_named_obj *named;
1008 name_hash = isl_hash_string(isl_hash_init(), name);
1009 entry = isl_hash_table_find(ctx, table, name_hash, same_name, name, 1);
1010 if (!entry)
1011 goto error;
1012 if (entry->data) {
1013 named = entry->data;
1014 free_obj(named->obj);
1015 free(name);
1016 } else {
1017 named = isl_alloc_type(ctx, struct isl_named_obj);
1018 if (!named)
1019 goto error;
1020 named->name = name;
1021 entry->data = named;
1023 named->obj = obj;
1025 return 0;
1026 error:
1027 free_obj(obj);
1028 free(name);
1029 return -1;
1032 static struct isl_obj stored_obj(struct isl_ctx *ctx,
1033 struct isl_hash_table *table, char *name)
1035 struct isl_obj obj = { isl_obj_none, NULL };
1036 struct isl_hash_table_entry *entry;
1037 uint32_t name_hash;
1039 name_hash = isl_hash_string(isl_hash_init(), name);
1040 entry = isl_hash_table_find(ctx, table, name_hash, same_name, name, 0);
1041 if (entry) {
1042 struct isl_named_obj *named;
1043 named = entry->data;
1044 obj = named->obj;
1045 } else if (isdigit(name[0]))
1046 fprintf(stderr, "unknown identifier '$%s'\n", name);
1047 else
1048 fprintf(stderr, "unknown identifier '%s'\n", name);
1050 free(name);
1051 obj.v = obj.type->copy(obj.v);
1052 return obj;
1055 static int is_subtype(struct isl_obj obj, isl_obj_type super)
1057 if (obj.type == super)
1058 return 1;
1059 if (obj.type == isl_obj_map && super == isl_obj_union_map)
1060 return 1;
1061 if (obj.type == isl_obj_set && super == isl_obj_union_set)
1062 return 1;
1063 if (obj.type == isl_obj_pw_qpolynomial &&
1064 super == isl_obj_union_pw_qpolynomial)
1065 return 1;
1066 if (obj.type == isl_obj_pw_qpolynomial_fold &&
1067 super == isl_obj_union_pw_qpolynomial_fold)
1068 return 1;
1069 if (obj.type == isl_obj_union_set && isl_union_set_is_empty(obj.v))
1070 return 1;
1071 if (obj.type == isl_obj_list) {
1072 struct isl_list *list = obj.v;
1073 if (list->n == 2 && list->obj[1].type == isl_obj_bool)
1074 return is_subtype(list->obj[0], super);
1076 if (super == isl_obj_str)
1077 return 1;
1078 return 0;
1081 static struct isl_obj obj_at(struct isl_obj obj, int i)
1083 struct isl_list *list = obj.v;
1085 obj = list->obj[i];
1086 obj.v = obj.type->copy(obj.v);
1088 isl_list_free(list);
1090 return obj;
1093 static struct isl_obj convert(isl_ctx *ctx, struct isl_obj obj,
1094 isl_obj_type type)
1096 if (obj.type == type)
1097 return obj;
1098 if (obj.type == isl_obj_map && type == isl_obj_union_map) {
1099 obj.type = isl_obj_union_map;
1100 obj.v = isl_union_map_from_map(obj.v);
1101 return obj;
1103 if (obj.type == isl_obj_set && type == isl_obj_union_set) {
1104 obj.type = isl_obj_union_set;
1105 obj.v = isl_union_set_from_set(obj.v);
1106 return obj;
1108 if (obj.type == isl_obj_pw_qpolynomial &&
1109 type == isl_obj_union_pw_qpolynomial) {
1110 obj.type = isl_obj_union_pw_qpolynomial;
1111 obj.v = isl_union_pw_qpolynomial_from_pw_qpolynomial(obj.v);
1112 return obj;
1114 if (obj.type == isl_obj_pw_qpolynomial_fold &&
1115 type == isl_obj_union_pw_qpolynomial_fold) {
1116 obj.type = isl_obj_union_pw_qpolynomial_fold;
1117 obj.v = isl_union_pw_qpolynomial_fold_from_pw_qpolynomial_fold(obj.v);
1118 return obj;
1120 if (obj.type == isl_obj_union_set && isl_union_set_is_empty(obj.v)) {
1121 if (type == isl_obj_union_map) {
1122 obj.type = isl_obj_union_map;
1123 return obj;
1125 if (type == isl_obj_union_pw_qpolynomial) {
1126 isl_space *dim = isl_union_set_get_space(obj.v);
1127 isl_union_set_free(obj.v);
1128 obj.v = isl_union_pw_qpolynomial_zero(dim);
1129 obj.type = isl_obj_union_pw_qpolynomial;
1130 return obj;
1132 if (type == isl_obj_union_pw_qpolynomial_fold) {
1133 isl_space *dim = isl_union_set_get_space(obj.v);
1134 isl_union_set_free(obj.v);
1135 obj.v = isl_union_pw_qpolynomial_fold_zero(dim,
1136 isl_fold_list);
1137 obj.type = isl_obj_union_pw_qpolynomial_fold;
1138 return obj;
1141 if (obj.type == isl_obj_list) {
1142 struct isl_list *list = obj.v;
1143 if (list->n == 2 && list->obj[1].type == isl_obj_bool)
1144 return convert(ctx, obj_at(obj, 0), type);
1146 if (type == isl_obj_str) {
1147 isl_str *str;
1148 isl_printer *p;
1149 char *s;
1151 p = isl_printer_to_str(ctx);
1152 if (!p)
1153 goto error;
1154 p = obj.type->print(p, obj.v);
1155 s = isl_printer_get_str(p);
1156 isl_printer_free(p);
1158 str = isl_str_from_string(ctx, s);
1159 if (!str)
1160 goto error;
1161 free_obj(obj);
1162 obj.v = str;
1163 obj.type = isl_obj_str;
1164 return obj;
1167 error:
1168 free_obj(obj);
1169 obj.type = isl_obj_none;
1170 obj.v = NULL;
1171 return obj;
1174 static struct isc_bin_op *read_bin_op_if_available(struct isl_stream *s,
1175 struct isl_obj lhs)
1177 int i;
1178 struct isl_token *tok;
1180 tok = isl_stream_next_token(s);
1181 if (!tok)
1182 return NULL;
1184 for (i = 0; ; ++i) {
1185 if (!bin_ops[i].op)
1186 break;
1187 if (bin_ops[i].op != tok->type)
1188 continue;
1189 if (!is_subtype(lhs, bin_ops[i].lhs))
1190 continue;
1192 isl_token_free(tok);
1193 return &bin_ops[i];
1196 for (i = 0; ; ++i) {
1197 if (!named_bin_ops[i].name)
1198 break;
1199 if (named_bin_ops[i].op.op != tok->type)
1200 continue;
1201 if (!is_subtype(lhs, named_bin_ops[i].op.lhs))
1202 continue;
1204 isl_token_free(tok);
1205 return &named_bin_ops[i].op;
1208 isl_stream_push_token(s, tok);
1210 return NULL;
1213 static struct isc_un_op *read_prefix_un_op_if_available(struct isl_stream *s)
1215 int i;
1216 struct isl_token *tok;
1218 tok = isl_stream_next_token(s);
1219 if (!tok)
1220 return NULL;
1222 for (i = 0; ; ++i) {
1223 if (!named_un_ops[i].name)
1224 break;
1225 if (named_un_ops[i].op.op != tok->type)
1226 continue;
1228 isl_token_free(tok);
1229 return &named_un_ops[i].op;
1232 isl_stream_push_token(s, tok);
1234 return NULL;
1237 static struct isc_un_op *find_matching_un_op(struct isc_un_op *like,
1238 struct isl_obj arg)
1240 int i;
1242 for (i = 0; ; ++i) {
1243 if (!named_un_ops[i].name)
1244 break;
1245 if (named_un_ops[i].op.op != like->op)
1246 continue;
1247 if (!is_subtype(arg, named_un_ops[i].op.arg))
1248 continue;
1250 return &named_un_ops[i].op;
1253 return NULL;
1256 static int is_assign(struct isl_stream *s)
1258 struct isl_token *tok;
1259 struct isl_token *tok2;
1260 int assign;
1262 tok = isl_stream_next_token(s);
1263 if (!tok)
1264 return 0;
1265 if (tok->type != ISL_TOKEN_IDENT) {
1266 isl_stream_push_token(s, tok);
1267 return 0;
1270 tok2 = isl_stream_next_token(s);
1271 if (!tok2) {
1272 isl_stream_push_token(s, tok);
1273 return 0;
1275 assign = tok2->type == ISL_TOKEN_DEF;
1276 isl_stream_push_token(s, tok2);
1277 isl_stream_push_token(s, tok);
1279 return assign;
1282 static struct isl_obj read_obj(struct isl_stream *s,
1283 struct isl_hash_table *table);
1284 static struct isl_obj read_expr(struct isl_stream *s,
1285 struct isl_hash_table *table);
1287 static struct isl_obj read_un_op_expr(struct isl_stream *s,
1288 struct isl_hash_table *table, struct isc_un_op *op)
1290 struct isl_obj obj = { isl_obj_none, NULL };
1292 obj = read_obj(s, table);
1293 if (!obj.v)
1294 goto error;
1296 op = find_matching_un_op(op, obj);
1298 if (!op)
1299 isl_die(s->ctx, isl_error_invalid,
1300 "no such unary operator defined on given operand",
1301 goto error);
1303 obj = convert(s->ctx, obj, op->arg);
1304 obj.v = op->fn(obj.v);
1305 obj.type = op->res;
1307 return obj;
1308 error:
1309 free_obj(obj);
1310 obj.type = isl_obj_none;
1311 obj.v = NULL;
1312 return obj;
1315 static struct isl_obj transitive_closure(struct isl_ctx *ctx, struct isl_obj obj)
1317 struct isl_list *list;
1318 int exact;
1320 if (obj.type != isl_obj_union_map)
1321 obj = convert(ctx, obj, isl_obj_union_map);
1322 isl_assert(ctx, obj.type == isl_obj_union_map, goto error);
1323 list = isl_list_alloc(ctx, 2);
1324 if (!list)
1325 goto error;
1327 list->obj[0].type = isl_obj_union_map;
1328 list->obj[0].v = isl_union_map_transitive_closure(obj.v, &exact);
1329 list->obj[1].type = isl_obj_bool;
1330 list->obj[1].v = exact ? &isl_bool_true : &isl_bool_false;
1331 obj.v = list;
1332 obj.type = isl_obj_list;
1333 if (exact < 0 || !list->obj[0].v)
1334 goto error;
1336 return obj;
1337 error:
1338 free_obj(obj);
1339 obj.type = isl_obj_none;
1340 obj.v = NULL;
1341 return obj;
1344 static struct isl_obj obj_at_index(struct isl_stream *s, struct isl_obj obj)
1346 struct isl_list *list = obj.v;
1347 struct isl_token *tok;
1348 int i;
1350 tok = isl_stream_next_token(s);
1351 if (!tok || tok->type != ISL_TOKEN_VALUE) {
1352 isl_stream_error(s, tok, "expecting index");
1353 if (tok)
1354 isl_stream_push_token(s, tok);
1355 goto error;
1357 i = isl_int_get_si(tok->u.v);
1358 isl_token_free(tok);
1359 isl_assert(s->ctx, i < list->n, goto error);
1360 if (isl_stream_eat(s, ']'))
1361 goto error;
1363 return obj_at(obj, i);
1364 error:
1365 free_obj(obj);
1366 obj.type = isl_obj_none;
1367 obj.v = NULL;
1368 return obj;
1371 static struct isl_obj apply(struct isl_stream *s, __isl_take isl_union_map *umap,
1372 struct isl_hash_table *table)
1374 struct isl_obj obj;
1376 obj = read_expr(s, table);
1377 isl_assert(s->ctx, is_subtype(obj, isl_obj_union_set) ||
1378 is_subtype(obj, isl_obj_union_map), goto error);
1380 if (obj.type == isl_obj_list) {
1381 struct isl_list *list = obj.v;
1382 if (list->n == 2 && list->obj[1].type == isl_obj_bool)
1383 obj = obj_at(obj, 0);
1385 if (obj.type == isl_obj_set)
1386 obj = convert(s->ctx, obj, isl_obj_union_set);
1387 else if (obj.type == isl_obj_map)
1388 obj = convert(s->ctx, obj, isl_obj_union_map);
1389 if (obj.type == isl_obj_union_set) {
1390 obj.v = isl_union_set_apply(obj.v, umap);
1391 } else
1392 obj.v = isl_union_map_apply_range(obj.v, umap);
1393 if (!obj.v)
1394 goto error2;
1396 if (isl_stream_eat(s, ')'))
1397 goto error2;
1399 return obj;
1400 error:
1401 isl_union_map_free(umap);
1402 error2:
1403 free_obj(obj);
1404 obj.type = isl_obj_none;
1405 obj.v = NULL;
1406 return obj;
1409 static struct isl_obj apply_fun(struct isl_stream *s,
1410 struct isl_obj obj, struct isl_hash_table *table)
1412 struct isl_obj arg;
1414 arg = read_expr(s, table);
1415 if (!is_subtype(arg, isl_obj_union_map) &&
1416 !is_subtype(arg, isl_obj_union_set))
1417 isl_die(s->ctx, isl_error_invalid,
1418 "expecting set of map argument", goto error);
1420 if (arg.type == isl_obj_list) {
1421 struct isl_list *list = arg.v;
1422 if (list->n == 2 && list->obj[1].type == isl_obj_bool)
1423 arg = obj_at(arg, 0);
1425 if (arg.type == isl_obj_set)
1426 arg = convert(s->ctx, arg, isl_obj_union_set);
1427 else if (arg.type == isl_obj_map)
1428 arg = convert(s->ctx, arg, isl_obj_union_map);
1429 if (arg.type == isl_obj_union_set) {
1430 arg.v = isl_union_map_from_range(arg.v);
1431 arg.type = isl_obj_union_map;
1433 if (obj.type == isl_obj_union_pw_qpolynomial) {
1434 obj.v = isl_union_map_apply_union_pw_qpolynomial(arg.v, obj.v);
1435 } else {
1436 obj.type = isl_obj_list;
1437 obj.v = union_map_apply_union_pw_qpolynomial_fold(arg.v, obj.v);
1439 if (!obj.v)
1440 goto error2;
1442 if (isl_stream_eat(s, ')'))
1443 goto error2;
1445 return obj;
1446 error:
1447 free_obj(arg);
1448 error2:
1449 free_obj(obj);
1450 obj.type = isl_obj_none;
1451 obj.v = NULL;
1452 return obj;
1455 struct add_vertex_data {
1456 struct isl_list *list;
1457 int i;
1460 static int add_vertex(__isl_take isl_vertex *vertex, void *user)
1462 struct add_vertex_data *data = (struct add_vertex_data *)user;
1463 isl_basic_set *expr;
1465 expr = isl_vertex_get_expr(vertex);
1467 data->list->obj[data->i].type = isl_obj_set;
1468 data->list->obj[data->i].v = isl_set_from_basic_set(expr);
1469 data->i++;
1471 isl_vertex_free(vertex);
1473 return 0;
1476 static int set_vertices(__isl_take isl_set *set, void *user)
1478 isl_ctx *ctx;
1479 isl_basic_set *hull;
1480 isl_vertices *vertices = NULL;
1481 struct isl_list *list = NULL;
1482 int r;
1483 struct add_vertex_data *data = (struct add_vertex_data *)user;
1485 set = isl_set_remove_divs(set);
1486 hull = isl_set_convex_hull(set);
1487 vertices = isl_basic_set_compute_vertices(hull);
1488 isl_basic_set_free(hull);
1490 list = data->list;
1492 ctx = isl_vertices_get_ctx(vertices);
1493 data->list = isl_list_alloc(ctx, isl_vertices_get_n_vertices(vertices));
1494 if (!data->list)
1495 goto error;
1497 data->i = 0;
1498 r = isl_vertices_foreach_vertex(vertices, &add_vertex, user);
1500 data->list = isl_list_concat(list, data->list);
1502 isl_vertices_free(vertices);
1504 return r;
1505 error:
1506 data->list = list;
1507 isl_vertices_free(vertices);
1508 return -1;
1511 static struct isl_obj vertices(struct isl_stream *s,
1512 struct isl_hash_table *table)
1514 isl_ctx *ctx;
1515 struct isl_obj obj;
1516 struct isl_list *list = NULL;
1517 isl_union_set *uset;
1518 struct add_vertex_data data = { NULL };
1520 obj = read_expr(s, table);
1521 obj = convert(s->ctx, obj, isl_obj_union_set);
1522 isl_assert(s->ctx, obj.type == isl_obj_union_set, goto error);
1523 uset = obj.v;
1524 obj.v = NULL;
1526 ctx = isl_union_set_get_ctx(uset);
1527 list = isl_list_alloc(ctx, 0);
1528 if (!list)
1529 goto error;
1531 data.list = list;
1533 if (isl_union_set_foreach_set(uset, &set_vertices, &data) < 0)
1534 goto error;
1536 isl_union_set_free(uset);
1538 obj.type = isl_obj_list;
1539 obj.v = data.list;
1541 return obj;
1542 error:
1543 isl_union_set_free(uset);
1544 isl_list_free(data.list);
1545 free_obj(obj);
1546 obj.type = isl_obj_none;
1547 obj.v = NULL;
1548 return obj;
1551 static struct isl_obj type_of(struct isl_stream *s,
1552 struct isl_hash_table *table)
1554 isl_ctx *ctx;
1555 struct isl_obj obj;
1556 const char *type = "unknown";
1558 obj = read_expr(s, table);
1560 if (obj.type == isl_obj_map ||
1561 obj.type == isl_obj_union_map)
1562 type = "map";
1563 if (obj.type == isl_obj_set ||
1564 obj.type == isl_obj_union_set)
1565 type = "set";
1566 if (obj.type == isl_obj_pw_qpolynomial ||
1567 obj.type == isl_obj_union_pw_qpolynomial)
1568 type = "piecewise quasipolynomial";
1569 if (obj.type == isl_obj_pw_qpolynomial_fold ||
1570 obj.type == isl_obj_union_pw_qpolynomial_fold)
1571 type = "piecewise quasipolynomial fold";
1572 if (obj.type == isl_obj_list)
1573 type = "list";
1574 if (obj.type == isl_obj_bool)
1575 type = "boolean";
1576 if (obj.type == isl_obj_str)
1577 type = "string";
1578 if (obj.type == isl_obj_int)
1579 type = "int";
1581 free_obj(obj);
1582 obj.type = isl_obj_str;
1583 obj.v = isl_str_from_string(s->ctx, strdup(type));
1585 return obj;
1588 static __isl_give isl_union_set *read_set(struct isl_stream *s,
1589 struct isl_hash_table *table)
1591 struct isl_obj obj;
1593 obj = read_obj(s, table);
1594 obj = convert(s->ctx, obj, isl_obj_union_set);
1595 isl_assert(s->ctx, obj.type == isl_obj_union_set, goto error);
1596 return obj.v;
1597 error:
1598 free_obj(obj);
1599 return NULL;
1602 static __isl_give isl_union_map *read_map(struct isl_stream *s,
1603 struct isl_hash_table *table)
1605 struct isl_obj obj;
1607 obj = read_obj(s, table);
1608 obj = convert(s->ctx, obj, isl_obj_union_map);
1609 isl_assert(s->ctx, obj.type == isl_obj_union_map, goto error);
1610 return obj.v;
1611 error:
1612 free_obj(obj);
1613 return NULL;
1616 static struct isl_obj last_any(struct isl_stream *s,
1617 struct isl_hash_table *table, __isl_take isl_union_map *must_source,
1618 __isl_take isl_union_map *may_source)
1620 struct isl_obj obj = { isl_obj_none, NULL };
1621 isl_union_map *sink = NULL;
1622 isl_union_map *schedule = NULL;
1623 isl_union_map *may_dep;
1624 isl_union_map *must_dep;
1626 if (isl_stream_eat(s, iscc_op[ISCC_BEFORE]))
1627 goto error;
1629 sink = read_map(s, table);
1630 if (!sink)
1631 goto error;
1633 if (isl_stream_eat(s, iscc_op[ISCC_UNDER]))
1634 goto error;
1636 schedule = read_map(s, table);
1637 if (!schedule)
1638 goto error;
1640 if (isl_union_map_compute_flow(sink, must_source, may_source,
1641 schedule, &must_dep, &may_dep,
1642 NULL, NULL) < 0)
1643 return obj;
1645 obj.type = isl_obj_union_map;
1646 obj.v = isl_union_map_union(must_dep, may_dep);
1648 return obj;
1649 error:
1650 isl_union_map_free(may_source);
1651 isl_union_map_free(must_source);
1652 isl_union_map_free(sink);
1653 isl_union_map_free(schedule);
1654 free_obj(obj);
1655 obj.type = isl_obj_none;
1656 obj.v = NULL;
1657 return obj;
1660 static struct isl_obj any(struct isl_stream *s, struct isl_hash_table *table)
1662 struct isl_obj obj = { isl_obj_none, NULL };
1663 isl_union_map *must_source = NULL;
1664 isl_union_map *may_source = NULL;
1665 isl_union_map *sink = NULL;
1666 isl_union_map *schedule = NULL;
1667 isl_union_map *may_dep;
1669 may_source = read_map(s, table);
1670 if (!may_source)
1671 goto error;
1673 if (isl_stream_eat_if_available(s, iscc_op[ISCC_LAST])) {
1674 must_source = read_map(s, table);
1675 if (!must_source)
1676 goto error;
1677 return last_any(s, table, must_source, may_source);
1680 if (isl_stream_eat(s, iscc_op[ISCC_BEFORE]))
1681 goto error;
1683 sink = read_map(s, table);
1684 if (!sink)
1685 goto error;
1687 if (isl_stream_eat(s, iscc_op[ISCC_UNDER]))
1688 goto error;
1690 schedule = read_map(s, table);
1691 if (!schedule)
1692 goto error;
1694 must_source = isl_union_map_empty(isl_union_map_get_space(sink));
1695 if (isl_union_map_compute_flow(sink, must_source, may_source,
1696 schedule, NULL, &may_dep,
1697 NULL, NULL) < 0)
1698 return obj;
1700 obj.type = isl_obj_union_map;
1701 obj.v = may_dep;
1703 return obj;
1704 error:
1705 isl_union_map_free(may_source);
1706 isl_union_map_free(must_source);
1707 isl_union_map_free(sink);
1708 isl_union_map_free(schedule);
1709 free_obj(obj);
1710 obj.type = isl_obj_none;
1711 obj.v = NULL;
1712 return obj;
1715 static struct isl_obj last(struct isl_stream *s, struct isl_hash_table *table)
1717 struct isl_obj obj = { isl_obj_none, NULL };
1718 struct isl_list *list = NULL;
1719 isl_union_map *must_source = NULL;
1720 isl_union_map *may_source = NULL;
1721 isl_union_map *sink = NULL;
1722 isl_union_map *schedule = NULL;
1723 isl_union_map *must_dep;
1724 isl_union_map *must_no_source;
1726 must_source = read_map(s, table);
1727 if (!must_source)
1728 goto error;
1730 if (isl_stream_eat_if_available(s, iscc_op[ISCC_ANY])) {
1731 may_source = read_map(s, table);
1732 if (!may_source)
1733 goto error;
1734 return last_any(s, table, must_source, may_source);
1737 list = isl_list_alloc(s->ctx, 2);
1738 if (!list)
1739 goto error;
1741 if (isl_stream_eat(s, iscc_op[ISCC_BEFORE]))
1742 goto error;
1744 sink = read_map(s, table);
1745 if (!sink)
1746 goto error;
1748 if (isl_stream_eat(s, iscc_op[ISCC_UNDER]))
1749 goto error;
1751 schedule = read_map(s, table);
1752 if (!schedule)
1753 goto error;
1755 may_source = isl_union_map_empty(isl_union_map_get_space(sink));
1756 if (isl_union_map_compute_flow(sink, must_source, may_source,
1757 schedule, &must_dep, NULL,
1758 &must_no_source, NULL) < 0) {
1759 isl_list_free(list);
1760 return obj;
1763 list->obj[0].type = isl_obj_union_map;
1764 list->obj[0].v = must_dep;
1765 list->obj[1].type = isl_obj_union_map;
1766 list->obj[1].v = must_no_source;
1768 obj.v = list;
1769 obj.type = isl_obj_list;
1771 return obj;
1772 error:
1773 isl_list_free(list);
1774 isl_union_map_free(may_source);
1775 isl_union_map_free(must_source);
1776 isl_union_map_free(sink);
1777 isl_union_map_free(schedule);
1778 free_obj(obj);
1779 obj.type = isl_obj_none;
1780 obj.v = NULL;
1781 return obj;
1784 static __isl_give isl_schedule *get_schedule(struct isl_stream *s,
1785 struct isl_hash_table *table)
1787 isl_union_set *domain;
1788 isl_union_map *validity;
1789 isl_union_map *proximity;
1791 domain = read_set(s, table);
1792 if (!domain)
1793 return NULL;
1795 validity = isl_union_map_empty(isl_union_set_get_space(domain));
1796 proximity = isl_union_map_empty(isl_union_set_get_space(domain));
1798 for (;;) {
1799 isl_union_map *umap;
1800 if (isl_stream_eat_if_available(s, iscc_op[ISCC_RESPECTING])) {
1801 umap = read_map(s, table);
1802 validity = isl_union_map_union(validity, umap);
1803 } else if (isl_stream_eat_if_available(s, iscc_op[ISCC_MINIMIZING])) {
1804 umap = read_map(s, table);
1805 proximity = isl_union_map_union(proximity, umap);
1806 } else
1807 break;
1810 return isl_union_set_compute_schedule(domain, validity, proximity);
1813 static struct isl_obj schedule(struct isl_stream *s,
1814 struct isl_hash_table *table)
1816 struct isl_obj obj = { isl_obj_none, NULL };
1817 isl_schedule *schedule;
1819 schedule = get_schedule(s, table);
1821 obj.v = isl_schedule_get_map(schedule);
1822 obj.type = isl_obj_union_map;
1824 isl_schedule_free(schedule);
1826 return obj;
1829 static struct isl_obj band_list_to_obj_list(__isl_take isl_band_list *bands);
1831 static struct isl_obj band_to_obj_list(__isl_take isl_band *band)
1833 struct isl_obj obj = { isl_obj_none, NULL };
1834 isl_ctx *ctx = isl_band_get_ctx(band);
1835 struct isl_list *list;
1837 list = isl_list_alloc(ctx, 2);
1838 if (!list)
1839 goto error;
1841 obj.v = list;
1842 obj.type = isl_obj_list;
1844 list->obj[0].type = isl_obj_union_map;
1845 list->obj[0].v = isl_band_get_partial_schedule(band);
1847 if (isl_band_has_children(band)) {
1848 isl_band_list *children;
1850 children = isl_band_get_children(band);
1851 list->obj[1] = band_list_to_obj_list(children);
1852 } else {
1853 list->obj[1].type = isl_obj_list;
1854 list->obj[1].v = isl_list_alloc(ctx, 0);
1857 if (!list->obj[0].v || !list->obj[1].v)
1858 goto error;
1860 isl_band_free(band);
1862 return obj;
1863 error:
1864 isl_band_free(band);
1865 free_obj(obj);
1866 obj.type = isl_obj_none;
1867 obj.v = NULL;
1868 return obj;
1871 static struct isl_obj band_list_to_obj_list(__isl_take isl_band_list *bands)
1873 struct isl_obj obj = { isl_obj_none, NULL };
1874 isl_ctx *ctx = isl_band_list_get_ctx(bands);
1875 struct isl_list *list;
1876 int i, n;
1878 n = isl_band_list_n_band(bands);
1879 list = isl_list_alloc(ctx, n);
1880 if (!list)
1881 goto error;
1883 obj.v = list;
1884 obj.type = isl_obj_list;
1886 for (i = 0; i < n; ++i) {
1887 isl_band *band;
1889 band = isl_band_list_get_band(bands, i);
1890 list->obj[i] = band_to_obj_list(band);
1891 if (!list->obj[i].v)
1892 goto error;
1895 isl_band_list_free(bands);
1897 return obj;
1898 error:
1899 isl_band_list_free(bands);
1900 free_obj(obj);
1901 obj.type = isl_obj_none;
1902 obj.v = NULL;
1903 return obj;
1906 static struct isl_obj schedule_forest(struct isl_stream *s,
1907 struct isl_hash_table *table)
1909 struct isl_obj obj = { isl_obj_none, NULL };
1910 isl_schedule *schedule;
1911 isl_band_list *roots;
1913 schedule = get_schedule(s, table);
1914 if (!schedule)
1915 return obj;
1917 roots = isl_schedule_get_band_forest(schedule);
1918 isl_schedule_free(schedule);
1920 return band_list_to_obj_list(roots);
1923 static struct isl_obj power(struct isl_stream *s, struct isl_obj obj)
1925 struct isl_token *tok;
1927 if (isl_stream_eat_if_available(s, '+'))
1928 return transitive_closure(s->ctx, obj);
1930 tok = isl_stream_next_token(s);
1931 if (!tok || tok->type != ISL_TOKEN_VALUE || isl_int_cmp_si(tok->u.v, -1)) {
1932 isl_stream_error(s, tok, "expecting -1");
1933 if (tok)
1934 isl_stream_push_token(s, tok);
1935 goto error;
1937 isl_token_free(tok);
1938 isl_assert(s->ctx, is_subtype(obj, isl_obj_union_map), goto error);
1939 if (obj.type != isl_obj_union_map)
1940 obj = convert(s->ctx, obj, isl_obj_union_map);
1942 obj.v = isl_union_map_reverse(obj.v);
1943 if (!obj.v)
1944 goto error;
1946 return obj;
1947 error:
1948 free_obj(obj);
1949 obj.type = isl_obj_none;
1950 obj.v = NULL;
1951 return obj;
1954 static struct isl_obj read_from_file(struct isl_stream *s)
1956 struct isl_obj obj;
1957 struct isl_token *tok;
1958 struct isl_stream *s_file;
1959 struct iscc_options *options;
1960 FILE *file;
1962 tok = isl_stream_next_token(s);
1963 if (!tok || tok->type != ISL_TOKEN_STRING) {
1964 isl_stream_error(s, tok, "expecting filename");
1965 isl_token_free(tok);
1966 goto error;
1969 options = isl_ctx_peek_iscc_options(s->ctx);
1970 if (!options || !options->io) {
1971 isl_token_free(tok);
1972 isl_die(s->ctx, isl_error_invalid,
1973 "read operation not allowed", goto error);
1976 file = fopen(tok->u.s, "r");
1977 isl_token_free(tok);
1978 isl_assert(s->ctx, file, goto error);
1980 s_file = isl_stream_new_file(s->ctx, file);
1981 if (!s_file) {
1982 fclose(file);
1983 goto error;
1986 obj = isl_stream_read_obj(s_file);
1988 isl_stream_free(s_file);
1989 fclose(file);
1991 return obj;
1992 error:
1993 obj.type = isl_obj_none;
1994 obj.v = NULL;
1995 return obj;
1998 static struct isl_obj write_to_file(struct isl_stream *s,
1999 struct isl_hash_table *table)
2001 struct isl_obj obj;
2002 struct isl_token *tok;
2003 struct isl_stream *s_file;
2004 struct iscc_options *options;
2005 FILE *file;
2006 isl_printer *p;
2008 tok = isl_stream_next_token(s);
2009 if (!tok || tok->type != ISL_TOKEN_STRING) {
2010 isl_stream_error(s, tok, "expecting filename");
2011 isl_token_free(tok);
2012 goto error;
2015 obj = read_expr(s, table);
2017 options = isl_ctx_peek_iscc_options(s->ctx);
2018 if (!options || !options->io) {
2019 isl_token_free(tok);
2020 isl_die(s->ctx, isl_error_invalid,
2021 "write operation not allowed", goto error);
2024 file = fopen(tok->u.s, "w");
2025 isl_token_free(tok);
2026 if (!file)
2027 isl_die(s->ctx, isl_error_unknown,
2028 "could not open file for writing", goto error);
2030 p = isl_printer_to_file(s->ctx, file);
2031 p = isl_printer_set_output_format(p, options->format);
2032 p = obj.type->print(p, obj.v);
2033 p = isl_printer_end_line(p);
2034 isl_printer_free(p);
2036 fclose(file);
2037 error:
2038 free_obj(obj);
2039 obj.type = isl_obj_none;
2040 obj.v = NULL;
2041 return obj;
2044 static struct isl_obj read_string_if_available(struct isl_stream *s)
2046 struct isl_token *tok;
2047 struct isl_obj obj = { isl_obj_none, NULL };
2049 tok = isl_stream_next_token(s);
2050 if (!tok)
2051 return obj;
2052 if (tok->type == ISL_TOKEN_STRING) {
2053 isl_str *str;
2054 str = isl_str_alloc(s->ctx);
2055 if (!str)
2056 goto error;
2057 str->s = strdup(tok->u.s);
2058 isl_token_free(tok);
2059 obj.v = str;
2060 obj.type = isl_obj_str;
2061 } else
2062 isl_stream_push_token(s, tok);
2063 return obj;
2064 error:
2065 isl_token_free(tok);
2066 return obj;
2069 static struct isl_obj read_bool_if_available(struct isl_stream *s)
2071 struct isl_token *tok;
2072 struct isl_obj obj = { isl_obj_none, NULL };
2074 tok = isl_stream_next_token(s);
2075 if (!tok)
2076 return obj;
2077 if (tok->type == ISL_TOKEN_FALSE || tok->type == ISL_TOKEN_TRUE) {
2078 int is_true = tok->type == ISL_TOKEN_TRUE;
2079 isl_token_free(tok);
2080 obj.v = is_true ? &isl_bool_true : &isl_bool_false;
2081 obj.type = isl_obj_bool;
2082 } else
2083 isl_stream_push_token(s, tok);
2084 return obj;
2085 error:
2086 isl_token_free(tok);
2087 return obj;
2090 static __isl_give char *read_ident(struct isl_stream *s)
2092 char *name;
2093 struct isl_token *tok, *tok2;
2095 name = isl_stream_read_ident_if_available(s);
2096 if (name)
2097 return name;
2099 tok = isl_stream_next_token(s);
2100 if (!tok)
2101 return NULL;
2102 if (tok->type != '$') {
2103 isl_stream_push_token(s, tok);
2104 return NULL;
2106 tok2 = isl_stream_next_token(s);
2107 if (!tok2 || tok2->type != ISL_TOKEN_VALUE) {
2108 if (tok2)
2109 isl_stream_push_token(s, tok2);
2110 isl_stream_push_token(s, tok);
2111 return NULL;
2114 name = isl_int_get_str(tok2->u.v);
2115 isl_token_free(tok);
2116 isl_token_free(tok2);
2118 return name;
2121 static struct isl_obj read_list(struct isl_stream *s,
2122 struct isl_hash_table *table, struct isl_obj obj)
2124 struct isl_list *list;
2126 list = isl_list_alloc(s->ctx, 2);
2127 if (!list)
2128 goto error;
2129 list->obj[0] = obj;
2130 list->obj[1] = read_obj(s, table);
2131 obj.v = list;
2132 obj.type = isl_obj_list;
2134 if (!list->obj[1].v)
2135 goto error;
2137 while (isl_stream_eat_if_available(s, ',')) {
2138 obj.v = list = isl_list_add_obj(list, read_obj(s, table));
2139 if (!obj.v)
2140 goto error;
2143 return obj;
2144 error:
2145 free_obj(obj);
2146 obj.type = isl_obj_none;
2147 obj.v = NULL;
2148 return obj;
2151 static struct isl_obj read_obj(struct isl_stream *s,
2152 struct isl_hash_table *table)
2154 struct isl_obj obj = { isl_obj_none, NULL };
2155 char *name = NULL;
2156 struct isc_un_op *op = NULL;
2158 obj = read_string_if_available(s);
2159 if (obj.v)
2160 return obj;
2161 obj = read_bool_if_available(s);
2162 if (obj.v)
2163 return obj;
2164 if (isl_stream_eat_if_available(s, '(')) {
2165 if (isl_stream_next_token_is(s, ')')) {
2166 obj.type = isl_obj_list;
2167 obj.v = isl_list_alloc(s->ctx, 0);
2168 } else {
2169 obj = read_expr(s, table);
2170 if (obj.v && isl_stream_eat_if_available(s, ','))
2171 obj = read_list(s, table, obj);
2173 if (!obj.v || isl_stream_eat(s, ')'))
2174 goto error;
2175 } else {
2176 op = read_prefix_un_op_if_available(s);
2177 if (op)
2178 return read_un_op_expr(s, table, op);
2180 if (isl_stream_eat_if_available(s, iscc_op[ISCC_READ]))
2181 return read_from_file(s);
2182 if (isl_stream_eat_if_available(s, iscc_op[ISCC_WRITE]))
2183 return write_to_file(s, table);
2184 if (isl_stream_eat_if_available(s, iscc_op[ISCC_VERTICES]))
2185 return vertices(s, table);
2186 if (isl_stream_eat_if_available(s, iscc_op[ISCC_ANY]))
2187 return any(s, table);
2188 if (isl_stream_eat_if_available(s, iscc_op[ISCC_LAST]))
2189 return last(s, table);
2190 if (isl_stream_eat_if_available(s, iscc_op[ISCC_SCHEDULE]))
2191 return schedule(s, table);
2192 if (isl_stream_eat_if_available(s, iscc_op[ISCC_SCHEDULE_FOREST]))
2193 return schedule_forest(s, table);
2194 if (isl_stream_eat_if_available(s, iscc_op[ISCC_TYPEOF]))
2195 return type_of(s, table);
2197 name = read_ident(s);
2198 if (name)
2199 obj = stored_obj(s->ctx, table, name);
2200 else
2201 obj = isl_stream_read_obj(s);
2202 if (!obj.v)
2203 goto error;
2206 if (isl_stream_eat_if_available(s, '^'))
2207 obj = power(s, obj);
2208 else if (obj.type == isl_obj_list && isl_stream_eat_if_available(s, '['))
2209 obj = obj_at_index(s, obj);
2210 else if (is_subtype(obj, isl_obj_union_map) &&
2211 isl_stream_eat_if_available(s, '(')) {
2212 obj = convert(s->ctx, obj, isl_obj_union_map);
2213 obj = apply(s, obj.v, table);
2214 } else if (is_subtype(obj, isl_obj_union_pw_qpolynomial) &&
2215 isl_stream_eat_if_available(s, '(')) {
2216 obj = convert(s->ctx, obj, isl_obj_union_pw_qpolynomial);
2217 obj = apply_fun(s, obj, table);
2218 } else if (is_subtype(obj, isl_obj_union_pw_qpolynomial_fold) &&
2219 isl_stream_eat_if_available(s, '(')) {
2220 obj = convert(s->ctx, obj, isl_obj_union_pw_qpolynomial_fold);
2221 obj = apply_fun(s, obj, table);
2224 return obj;
2225 error:
2226 free_obj(obj);
2227 obj.type = isl_obj_none;
2228 obj.v = NULL;
2229 return obj;
2232 static struct isc_bin_op *find_matching_bin_op(struct isc_bin_op *like,
2233 struct isl_obj lhs, struct isl_obj rhs)
2235 int i;
2237 for (i = 0; ; ++i) {
2238 if (!bin_ops[i].op)
2239 break;
2240 if (bin_ops[i].op != like->op)
2241 continue;
2242 if (!is_subtype(lhs, bin_ops[i].lhs))
2243 continue;
2244 if (!is_subtype(rhs, bin_ops[i].rhs))
2245 continue;
2247 return &bin_ops[i];
2250 for (i = 0; ; ++i) {
2251 if (!named_bin_ops[i].name)
2252 break;
2253 if (named_bin_ops[i].op.op != like->op)
2254 continue;
2255 if (!is_subtype(lhs, named_bin_ops[i].op.lhs))
2256 continue;
2257 if (!is_subtype(rhs, named_bin_ops[i].op.rhs))
2258 continue;
2260 return &named_bin_ops[i].op;
2263 return NULL;
2266 static int next_is_neg_int(struct isl_stream *s)
2268 struct isl_token *tok;
2269 int ret;
2271 tok = isl_stream_next_token(s);
2272 ret = tok && tok->type == ISL_TOKEN_VALUE && isl_int_is_neg(tok->u.v);
2273 isl_stream_push_token(s, tok);
2275 return ret;
2278 static struct isl_obj read_expr(struct isl_stream *s,
2279 struct isl_hash_table *table)
2281 struct isl_obj obj = { isl_obj_none, NULL };
2282 struct isl_obj right_obj = { isl_obj_none, NULL };
2284 obj = read_obj(s, table);
2285 for (; obj.v;) {
2286 struct isc_bin_op *op = NULL;
2288 op = read_bin_op_if_available(s, obj);
2289 if (!op)
2290 break;
2292 right_obj = read_obj(s, table);
2294 op = find_matching_bin_op(op, obj, right_obj);
2296 if (!op)
2297 isl_die(s->ctx, isl_error_invalid,
2298 "no such binary operator defined on given operands",
2299 goto error);
2301 obj = convert(s->ctx, obj, op->lhs);
2302 right_obj = convert(s->ctx, right_obj, op->rhs);
2303 obj.v = op->fn(obj.v, right_obj.v);
2304 obj.type = op->res;
2307 if (obj.type == isl_obj_int && next_is_neg_int(s)) {
2308 right_obj = read_obj(s, table);
2309 obj.v = isl_int_obj_add(obj.v, right_obj.v);
2312 return obj;
2313 error:
2314 free_obj(right_obj);
2315 free_obj(obj);
2316 obj.type = isl_obj_none;
2317 obj.v = NULL;
2318 return obj;
2321 static __isl_give isl_printer *source_file(struct isl_stream *s,
2322 struct isl_hash_table *table, __isl_take isl_printer *p);
2324 static __isl_give isl_printer *read_line(struct isl_stream *s,
2325 struct isl_hash_table *table, __isl_take isl_printer *p, int tty)
2327 struct isl_obj obj = { isl_obj_none, NULL };
2328 char *lhs = NULL;
2329 int assign = 0;
2330 int only_print = 0;
2331 struct isc_bin_op *op = NULL;
2332 char buf[30];
2334 if (!p)
2335 return NULL;
2336 if (isl_stream_is_empty(s))
2337 return p;
2339 if (isl_stream_eat_if_available(s, iscc_op[ISCC_SOURCE]))
2340 return source_file(s, table, p);
2342 assign = is_assign(s);
2343 if (assign) {
2344 lhs = isl_stream_read_ident_if_available(s);
2345 if (isl_stream_eat(s, ISL_TOKEN_DEF))
2346 goto error;
2347 } else if (isl_stream_eat_if_available(s, iscc_op[ISCC_PRINT]))
2348 only_print = 1;
2349 else if (!tty)
2350 only_print = 1;
2352 obj = read_expr(s, table);
2353 if (isl_ctx_last_error(s->ctx) == isl_error_abort) {
2354 fprintf(stderr, "Interrupted\n");
2355 isl_ctx_reset_error(s->ctx);
2357 if (isl_stream_eat(s, ';'))
2358 goto error;
2360 if (only_print) {
2361 if (obj.type != isl_obj_none && obj.v != NULL)
2362 p = obj.type->print(p, obj.v);
2363 p = isl_printer_end_line(p);
2364 free_obj(obj);
2365 return p;
2367 if (!assign && obj.type != isl_obj_none && obj.v != NULL) {
2368 static int count = 0;
2369 snprintf(buf, sizeof(buf), "$%d", count++);
2370 lhs = strdup(buf + 1);
2372 p = isl_printer_print_str(p, buf);
2373 p = isl_printer_print_str(p, " := ");
2374 p = obj.type->print(p, obj.v);
2375 p = isl_printer_end_line(p);
2377 if (lhs && do_assign(s->ctx, table, lhs, obj))
2378 return p;
2380 return p;
2381 error:
2382 isl_stream_flush_tokens(s);
2383 isl_stream_skip_line(s);
2384 free(lhs);
2385 free_obj(obj);
2386 return p;
2389 int free_cb(void **entry, void *user)
2391 struct isl_named_obj *named = *entry;
2393 free_obj(named->obj);
2394 free(named->name);
2395 free(named);
2397 return 0;
2400 static void register_named_ops(struct isl_stream *s)
2402 int i;
2404 for (i = 0; i < ISCC_N_OP; ++i) {
2405 iscc_op[i] = isl_stream_register_keyword(s, op_name[i]);
2406 assert(iscc_op[i] != ISL_TOKEN_ERROR);
2409 for (i = 0; ; ++i) {
2410 if (!named_un_ops[i].name)
2411 break;
2412 named_un_ops[i].op.op = isl_stream_register_keyword(s,
2413 named_un_ops[i].name);
2414 assert(named_un_ops[i].op.op != ISL_TOKEN_ERROR);
2417 for (i = 0; ; ++i) {
2418 if (!named_bin_ops[i].name)
2419 break;
2420 named_bin_ops[i].op.op = isl_stream_register_keyword(s,
2421 named_bin_ops[i].name);
2422 assert(named_bin_ops[i].op.op != ISL_TOKEN_ERROR);
2426 static __isl_give isl_printer *source_file(struct isl_stream *s,
2427 struct isl_hash_table *table, __isl_take isl_printer *p)
2429 struct isl_token *tok;
2430 struct isl_stream *s_file;
2431 FILE *file;
2433 tok = isl_stream_next_token(s);
2434 if (!tok || tok->type != ISL_TOKEN_STRING) {
2435 isl_stream_error(s, tok, "expecting filename");
2436 isl_token_free(tok);
2437 return p;
2440 file = fopen(tok->u.s, "r");
2441 isl_token_free(tok);
2442 isl_assert(s->ctx, file, return p);
2444 s_file = isl_stream_new_file(s->ctx, file);
2445 if (!s_file) {
2446 fclose(file);
2447 return p;
2450 register_named_ops(s_file);
2452 while (!s_file->eof)
2453 p = read_line(s_file, table, p, 0);
2455 isl_stream_free(s_file);
2456 fclose(file);
2458 isl_stream_eat(s, ';');
2460 return p;
2463 int main(int argc, char **argv)
2465 struct isl_ctx *ctx;
2466 struct isl_stream *s;
2467 struct isl_hash_table *table;
2468 struct iscc_options *options;
2469 isl_printer *p;
2470 int tty = isatty(0);
2472 options = iscc_options_new_with_defaults();
2473 assert(options);
2474 argc = iscc_options_parse(options, argc, argv, ISL_ARG_ALL);
2476 ctx = isl_ctx_alloc_with_options(iscc_options_arg, options);
2477 s = isl_stream_new_file(ctx, stdin);
2478 assert(s);
2479 table = isl_hash_table_alloc(ctx, 10);
2480 assert(table);
2481 p = isl_printer_to_file(ctx, stdout);
2482 p = isl_printer_set_output_format(p, options->format);
2483 assert(p);
2485 register_named_ops(s);
2487 install_signal_handler(ctx);
2489 while (p && !s->eof) {
2490 isl_ctx_resume(ctx);
2491 p = read_line(s, table, p, tty);
2494 remove_signal_handler(ctx);
2496 isl_printer_free(p);
2497 isl_hash_table_foreach(ctx, table, free_cb, NULL);
2498 isl_hash_table_free(ctx, table);
2499 isl_stream_free(s);
2500 isl_ctx_free(ctx);
2502 return 0;