iscc: accept empty lists
[barvinok.git] / iscc.c
blob58815c242394e2fba7b0f997190c02fbf698a39b
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/schedule.h>
11 #include <isl_obj_list.h>
12 #include <isl_obj_str.h>
13 #include <barvinok/isl.h>
14 #include <barvinok/options.h>
16 #include "config.h"
18 #ifdef HAVE_SIGACTION
19 #include <signal.h>
21 static isl_ctx *main_ctx;
23 static void handler(int signum)
25 if (isl_ctx_aborted(main_ctx))
26 exit(EXIT_FAILURE);
27 isl_ctx_abort(main_ctx);
30 static struct sigaction sa_old;
32 static void install_signal_handler(isl_ctx *ctx)
34 struct sigaction sa;
36 main_ctx = ctx;
38 memset(&sa, 0, sizeof(struct sigaction));
39 sa.sa_handler = &handler;
40 sa.sa_flags = SA_RESTART;
41 sigaction(SIGINT, &sa, &sa_old);
44 static void remove_signal_handler(isl_ctx *ctx)
46 sigaction(SIGINT, &sa_old, NULL);
49 #else
51 static void install_signal_handler(isl_ctx *ctx)
55 static void remove_signal_handler(isl_ctx *ctx)
59 #endif
61 #ifdef HAVE_CLOOG
62 #include <cloog/isl/cloog.h>
63 #endif
65 static int isl_bool_false = 0;
66 static int isl_bool_true = 1;
67 static int isl_bool_error = -1;
69 enum iscc_op { ISCC_READ, ISCC_WRITE, ISCC_SOURCE, ISCC_VERTICES,
70 ISCC_LAST, ISCC_ANY, ISCC_BEFORE, ISCC_UNDER,
71 ISCC_SCHEDULE, ISCC_SCHEDULE_BANDS,
72 ISCC_MINIMIZING, ISCC_RESPECTING,
73 ISCC_TYPEOF, ISCC_PRINT,
74 ISCC_N_OP };
75 static const char *op_name[ISCC_N_OP] = {
76 [ISCC_READ] = "read",
77 [ISCC_WRITE] = "write",
78 [ISCC_PRINT] = "print",
79 [ISCC_SOURCE] = "source",
80 [ISCC_VERTICES] = "vertices",
81 [ISCC_LAST] = "last",
82 [ISCC_ANY] = "any",
83 [ISCC_BEFORE] = "before",
84 [ISCC_UNDER] = "under",
85 [ISCC_SCHEDULE] = "schedule",
86 [ISCC_SCHEDULE_BANDS] = "schedule_bands",
87 [ISCC_MINIMIZING] = "minimizing",
88 [ISCC_RESPECTING] = "respecting",
89 [ISCC_TYPEOF] = "typeof"
91 static enum isl_token_type iscc_op[ISCC_N_OP];
93 struct isl_arg_choice iscc_format[] = {
94 {"isl", ISL_FORMAT_ISL},
95 {"omega", ISL_FORMAT_OMEGA},
96 {"polylib", ISL_FORMAT_POLYLIB},
97 {"ext-polylib", ISL_FORMAT_EXT_POLYLIB},
98 {"latex", ISL_FORMAT_LATEX},
99 {"C", ISL_FORMAT_C},
103 struct iscc_options {
104 struct barvinok_options *barvinok;
105 unsigned format;
106 int io;
109 struct isl_arg iscc_options_arg[] = {
110 ISL_ARG_CHILD(struct iscc_options, barvinok, "barvinok", barvinok_options_arg,
111 "barvinok options")
112 ISL_ARG_CHOICE(struct iscc_options, format, 0, "format", \
113 iscc_format, ISL_FORMAT_ISL, "output format")
114 ISL_ARG_BOOL(struct iscc_options, io, 0, "io", 1,
115 "allow read and write operations")
116 ISL_ARG_END
119 ISL_ARG_DEF(iscc_options, struct iscc_options, iscc_options_arg)
120 ISL_ARG_CTX_DEF(iscc_options, struct iscc_options, iscc_options_arg)
122 static void *isl_obj_bool_copy(void *v)
124 return v;
127 static void isl_obj_bool_free(void *v)
131 static __isl_give isl_printer *isl_obj_bool_print(__isl_take isl_printer *p,
132 void *v)
134 if (v == &isl_bool_true)
135 return isl_printer_print_str(p, "True");
136 else if (v == &isl_bool_false)
137 return isl_printer_print_str(p, "False");
138 else
139 return isl_printer_print_str(p, "Error");
142 static void *isl_obj_bool_add(void *v1, void *v2)
144 return v1;
147 struct isl_obj_vtable isl_obj_bool_vtable = {
148 isl_obj_bool_copy,
149 isl_obj_bool_add,
150 isl_obj_bool_print,
151 isl_obj_bool_free
153 #define isl_obj_bool (&isl_obj_bool_vtable)
155 int *isl_bool_from_int(int res)
157 return res < 0 ? &isl_bool_error : res ? &isl_bool_true : &isl_bool_false;
160 int *union_map_is_equal(__isl_take isl_union_map *map1,
161 __isl_take isl_union_map *map2)
163 int res = isl_union_map_is_equal(map1, map2);
164 isl_union_map_free(map1);
165 isl_union_map_free(map2);
166 return isl_bool_from_int(res);
168 int *union_set_is_equal(__isl_take isl_union_set *set1,
169 __isl_take isl_union_set *set2)
171 return union_map_is_equal((isl_union_map *)set1, (isl_union_map *)set2);
174 int *union_map_is_subset(__isl_take isl_union_map *map1,
175 __isl_take isl_union_map *map2)
177 int res = isl_union_map_is_subset(map1, map2);
178 isl_union_map_free(map1);
179 isl_union_map_free(map2);
180 return isl_bool_from_int(res);
182 int *union_set_is_subset(__isl_take isl_union_set *set1,
183 __isl_take isl_union_set *set2)
185 return union_map_is_subset((isl_union_map *)set1, (isl_union_map *)set2);
188 int *union_map_is_strict_subset(__isl_take isl_union_map *map1,
189 __isl_take isl_union_map *map2)
191 int res = isl_union_map_is_strict_subset(map1, map2);
192 isl_union_map_free(map1);
193 isl_union_map_free(map2);
194 return isl_bool_from_int(res);
196 int *union_set_is_strict_subset(__isl_take isl_union_set *set1,
197 __isl_take isl_union_set *set2)
199 return union_map_is_strict_subset((isl_union_map *)set1,
200 (isl_union_map *)set2);
203 int *union_map_is_superset(__isl_take isl_union_map *map1,
204 __isl_take isl_union_map *map2)
206 return union_map_is_subset(map2, map1);
208 int *union_set_is_superset(__isl_take isl_union_set *set1,
209 __isl_take isl_union_set *set2)
211 return union_set_is_subset(set2, set1);
214 int *union_map_is_strict_superset(__isl_take isl_union_map *map1,
215 __isl_take isl_union_map *map2)
217 return union_map_is_strict_subset(map2, map1);
219 int *union_set_is_strict_superset(__isl_take isl_union_set *set1,
220 __isl_take isl_union_set *set2)
222 return union_set_is_strict_subset(set2, set1);
225 extern struct isl_obj_vtable isl_obj_list_vtable;
226 #define isl_obj_list (&isl_obj_list_vtable)
228 typedef void *(*isc_bin_op_fn)(void *lhs, void *rhs);
229 struct isc_bin_op {
230 enum isl_token_type op;
231 isl_obj_type lhs;
232 isl_obj_type rhs;
233 isl_obj_type res;
234 isc_bin_op_fn fn;
236 struct isc_named_bin_op {
237 char *name;
238 struct isc_bin_op op;
241 struct iscc_at {
242 isl_union_pw_qpolynomial *upwqp;
243 isl_union_pw_qpolynomial *res;
246 static int eval_at(__isl_take isl_point *pnt, void *user)
248 struct iscc_at *at = (struct iscc_at *) user;
249 isl_qpolynomial *qp;
250 isl_set *set;
252 set = isl_set_from_point(isl_point_copy(pnt));
253 qp = isl_union_pw_qpolynomial_eval(
254 isl_union_pw_qpolynomial_copy(at->upwqp), pnt);
256 at->res = isl_union_pw_qpolynomial_add(at->res,
257 isl_union_pw_qpolynomial_from_pw_qpolynomial(
258 isl_pw_qpolynomial_alloc(set, qp)));
260 return 0;
263 __isl_give isl_union_pw_qpolynomial *isl_union_pw_qpolynomial_at(
264 __isl_take isl_union_pw_qpolynomial *upwqp,
265 __isl_take isl_union_set *uset)
267 struct iscc_at at;
269 at.upwqp = upwqp;
270 at.res = isl_union_pw_qpolynomial_zero(isl_union_set_get_dim(uset));
272 isl_union_set_foreach_point(uset, eval_at, &at);
274 isl_union_pw_qpolynomial_free(upwqp);
275 isl_union_set_free(uset);
277 return at.res;
280 struct iscc_fold_at {
281 isl_union_pw_qpolynomial_fold *upwf;
282 isl_union_pw_qpolynomial *res;
285 static int eval_fold_at(__isl_take isl_point *pnt, void *user)
287 struct iscc_fold_at *at = (struct iscc_fold_at *) user;
288 isl_qpolynomial *qp;
289 isl_set *set;
291 set = isl_set_from_point(isl_point_copy(pnt));
292 qp = isl_union_pw_qpolynomial_fold_eval(
293 isl_union_pw_qpolynomial_fold_copy(at->upwf), pnt);
295 at->res = isl_union_pw_qpolynomial_add(at->res,
296 isl_union_pw_qpolynomial_from_pw_qpolynomial(
297 isl_pw_qpolynomial_alloc(set, qp)));
299 return 0;
302 __isl_give isl_union_pw_qpolynomial *isl_union_pw_qpolynomial_fold_at(
303 __isl_take isl_union_pw_qpolynomial_fold *upwf,
304 __isl_take isl_union_set *uset)
306 struct iscc_fold_at at;
308 at.upwf = upwf;
309 at.res = isl_union_pw_qpolynomial_zero(isl_union_set_get_dim(uset));
311 isl_union_set_foreach_point(uset, eval_fold_at, &at);
313 isl_union_pw_qpolynomial_fold_free(upwf);
314 isl_union_set_free(uset);
316 return at.res;
319 static __isl_give isl_union_pw_qpolynomial_fold *union_pw_qpolynomial_add_union_pw_qpolynomial_fold(
320 __isl_take isl_union_pw_qpolynomial *upwqp,
321 __isl_take isl_union_pw_qpolynomial_fold *upwf)
323 return isl_union_pw_qpolynomial_fold_add_union_pw_qpolynomial(upwf,
324 upwqp);
327 static __isl_give struct isl_list *union_map_apply_union_pw_qpolynomial_fold(
328 __isl_take isl_union_map *umap,
329 __isl_take isl_union_pw_qpolynomial_fold *upwf)
331 isl_ctx *ctx;
332 struct isl_list *list;
333 int tight;
335 ctx = isl_union_map_get_ctx(umap);
336 list = isl_list_alloc(ctx, 2);
337 if (!list)
338 goto error2;
340 list->obj[0].type = isl_obj_union_pw_qpolynomial_fold;
341 list->obj[0].v = isl_union_map_apply_union_pw_qpolynomial_fold(umap,
342 upwf, &tight);
343 list->obj[1].type = isl_obj_bool;
344 list->obj[1].v = tight ? &isl_bool_true : &isl_bool_false;
345 if (tight < 0 || !list->obj[0].v)
346 goto error;
348 return list;
349 error2:
350 isl_union_map_free(umap);
351 isl_union_pw_qpolynomial_fold_free(upwf);
352 error:
353 isl_list_free(list);
354 return NULL;
357 static __isl_give isl_union_pw_qpolynomial *union_pw_qpolynomial_int_mul(
358 __isl_take isl_union_pw_qpolynomial *upwqp, __isl_take isl_int_obj *i)
360 isl_int v;
362 if (!i)
363 goto error;
365 isl_int_init(v);
366 isl_int_obj_get_int(i, &v);
367 upwqp = isl_union_pw_qpolynomial_mul_isl_int(upwqp, v);
368 isl_int_clear(v);
370 isl_int_obj_free(i);
372 return upwqp;
373 error:
374 isl_union_pw_qpolynomial_free(upwqp);
375 return NULL;
378 static __isl_give isl_union_pw_qpolynomial *int_union_pw_qpolynomial_mul(
379 __isl_take isl_int_obj *i, __isl_take isl_union_pw_qpolynomial *upwqp)
381 return union_pw_qpolynomial_int_mul(upwqp, i);
384 static __isl_give isl_union_pw_qpolynomial_fold *union_pw_qpolynomial_fold_int_mul(
385 __isl_take isl_union_pw_qpolynomial_fold *upwf,
386 __isl_take isl_int_obj *i)
388 isl_int v;
390 if (!i)
391 goto error;
393 isl_int_init(v);
394 isl_int_obj_get_int(i, &v);
395 upwf = isl_union_pw_qpolynomial_fold_mul_isl_int(upwf, v);
396 isl_int_clear(v);
398 isl_int_obj_free(i);
400 return upwf;
401 error:
402 isl_union_pw_qpolynomial_fold_free(upwf);
403 return NULL;
406 static __isl_give isl_union_pw_qpolynomial_fold *int_union_pw_qpolynomial_fold_mul(
407 __isl_take isl_int_obj *i,
408 __isl_take isl_union_pw_qpolynomial_fold *upwf)
410 return union_pw_qpolynomial_fold_int_mul(upwf, i);
413 struct isc_bin_op bin_ops[] = {
414 { '+', isl_obj_int, isl_obj_int, isl_obj_int,
415 (isc_bin_op_fn) &isl_int_obj_add },
416 { '-', isl_obj_int, isl_obj_int, isl_obj_int,
417 (isc_bin_op_fn) &isl_int_obj_sub },
418 { '*', isl_obj_int, isl_obj_int, isl_obj_int,
419 (isc_bin_op_fn) &isl_int_obj_mul },
420 { '+', isl_obj_union_set, isl_obj_union_set,
421 isl_obj_union_set,
422 (isc_bin_op_fn) &isl_union_set_union },
423 { '+', isl_obj_union_map, isl_obj_union_map,
424 isl_obj_union_map,
425 (isc_bin_op_fn) &isl_union_map_union },
426 { '-', isl_obj_union_set, isl_obj_union_set,
427 isl_obj_union_set,
428 (isc_bin_op_fn) &isl_union_set_subtract },
429 { '-', isl_obj_union_map, isl_obj_union_map,
430 isl_obj_union_map,
431 (isc_bin_op_fn) &isl_union_map_subtract },
432 { '*', isl_obj_union_set, isl_obj_union_set,
433 isl_obj_union_set,
434 (isc_bin_op_fn) &isl_union_set_intersect },
435 { '*', isl_obj_union_map, isl_obj_union_map,
436 isl_obj_union_map,
437 (isc_bin_op_fn) &isl_union_map_intersect },
438 { '*', isl_obj_union_map, isl_obj_union_set,
439 isl_obj_union_map,
440 (isc_bin_op_fn) &isl_union_map_intersect_domain },
441 { '.', isl_obj_union_map, isl_obj_union_map,
442 isl_obj_union_map,
443 (isc_bin_op_fn) &isl_union_map_apply_range },
444 { '.', isl_obj_union_map, isl_obj_union_pw_qpolynomial,
445 isl_obj_union_pw_qpolynomial,
446 (isc_bin_op_fn) &isl_union_map_apply_union_pw_qpolynomial },
447 { '.', isl_obj_union_map, isl_obj_union_pw_qpolynomial_fold,
448 isl_obj_list,
449 (isc_bin_op_fn) &union_map_apply_union_pw_qpolynomial_fold },
450 { ISL_TOKEN_TO, isl_obj_union_set, isl_obj_union_set,
451 isl_obj_union_map,
452 (isc_bin_op_fn) &isl_union_map_from_domain_and_range },
453 { '=', isl_obj_union_set, isl_obj_union_set, isl_obj_bool,
454 (isc_bin_op_fn) &union_set_is_equal },
455 { '=', isl_obj_union_map, isl_obj_union_map, isl_obj_bool,
456 (isc_bin_op_fn) &union_map_is_equal },
457 { ISL_TOKEN_LE, isl_obj_union_set, isl_obj_union_set,
458 isl_obj_bool, (isc_bin_op_fn) &union_set_is_subset },
459 { ISL_TOKEN_LE, isl_obj_union_map, isl_obj_union_map,
460 isl_obj_bool, (isc_bin_op_fn) &union_map_is_subset },
461 { ISL_TOKEN_LT, isl_obj_union_set, isl_obj_union_set,
462 isl_obj_bool, (isc_bin_op_fn) &union_set_is_strict_subset },
463 { ISL_TOKEN_LT, isl_obj_union_map, isl_obj_union_map,
464 isl_obj_bool, (isc_bin_op_fn) &union_map_is_strict_subset },
465 { ISL_TOKEN_GE, isl_obj_union_set, isl_obj_union_set,
466 isl_obj_bool, (isc_bin_op_fn) &union_set_is_superset },
467 { ISL_TOKEN_GE, isl_obj_union_map, isl_obj_union_map,
468 isl_obj_bool, (isc_bin_op_fn) &union_map_is_superset },
469 { ISL_TOKEN_GT, isl_obj_union_set, isl_obj_union_set,
470 isl_obj_bool, (isc_bin_op_fn) &union_set_is_strict_superset },
471 { ISL_TOKEN_GT, isl_obj_union_map, isl_obj_union_map,
472 isl_obj_bool, (isc_bin_op_fn) &union_map_is_strict_superset },
473 { ISL_TOKEN_LEX_LE, isl_obj_union_set, isl_obj_union_set,
474 isl_obj_union_map,
475 (isc_bin_op_fn) &isl_union_set_lex_le_union_set },
476 { ISL_TOKEN_LEX_LT, isl_obj_union_set, isl_obj_union_set,
477 isl_obj_union_map,
478 (isc_bin_op_fn) &isl_union_set_lex_lt_union_set },
479 { ISL_TOKEN_LEX_GE, isl_obj_union_set, isl_obj_union_set,
480 isl_obj_union_map,
481 (isc_bin_op_fn) &isl_union_set_lex_ge_union_set },
482 { ISL_TOKEN_LEX_GT, isl_obj_union_set, isl_obj_union_set,
483 isl_obj_union_map,
484 (isc_bin_op_fn) &isl_union_set_lex_gt_union_set },
485 { ISL_TOKEN_LEX_LE, isl_obj_union_map, isl_obj_union_map,
486 isl_obj_union_map,
487 (isc_bin_op_fn) &isl_union_map_lex_le_union_map },
488 { ISL_TOKEN_LEX_LT, isl_obj_union_map, isl_obj_union_map,
489 isl_obj_union_map,
490 (isc_bin_op_fn) &isl_union_map_lex_lt_union_map },
491 { ISL_TOKEN_LEX_GE, isl_obj_union_map, isl_obj_union_map,
492 isl_obj_union_map,
493 (isc_bin_op_fn) &isl_union_map_lex_ge_union_map },
494 { ISL_TOKEN_LEX_GT, isl_obj_union_map, isl_obj_union_map,
495 isl_obj_union_map,
496 (isc_bin_op_fn) &isl_union_map_lex_gt_union_map },
497 { '.', isl_obj_union_pw_qpolynomial_fold,
498 isl_obj_union_pw_qpolynomial_fold,
499 isl_obj_union_pw_qpolynomial_fold,
500 (isc_bin_op_fn) &isl_union_pw_qpolynomial_fold_fold },
501 { '+', isl_obj_union_pw_qpolynomial, isl_obj_union_pw_qpolynomial,
502 isl_obj_union_pw_qpolynomial,
503 (isc_bin_op_fn) &isl_union_pw_qpolynomial_add },
504 { '+', isl_obj_union_pw_qpolynomial,
505 isl_obj_union_pw_qpolynomial_fold,
506 isl_obj_union_pw_qpolynomial_fold,
507 (isc_bin_op_fn) &union_pw_qpolynomial_add_union_pw_qpolynomial_fold },
508 { '+', isl_obj_union_pw_qpolynomial_fold,
509 isl_obj_union_pw_qpolynomial,
510 isl_obj_union_pw_qpolynomial_fold,
511 (isc_bin_op_fn) &isl_union_pw_qpolynomial_fold_add_union_pw_qpolynomial },
512 { '-', isl_obj_union_pw_qpolynomial, isl_obj_union_pw_qpolynomial,
513 isl_obj_union_pw_qpolynomial,
514 (isc_bin_op_fn) &isl_union_pw_qpolynomial_sub },
515 { '*', isl_obj_int, isl_obj_union_pw_qpolynomial,
516 isl_obj_union_pw_qpolynomial,
517 (isc_bin_op_fn) &int_union_pw_qpolynomial_mul },
518 { '*', isl_obj_union_pw_qpolynomial, isl_obj_int,
519 isl_obj_union_pw_qpolynomial,
520 (isc_bin_op_fn) &union_pw_qpolynomial_int_mul },
521 { '*', isl_obj_int, isl_obj_union_pw_qpolynomial_fold,
522 isl_obj_union_pw_qpolynomial_fold,
523 (isc_bin_op_fn) &int_union_pw_qpolynomial_fold_mul },
524 { '*', isl_obj_union_pw_qpolynomial_fold, isl_obj_int,
525 isl_obj_union_pw_qpolynomial_fold,
526 (isc_bin_op_fn) &union_pw_qpolynomial_fold_int_mul },
527 { '*', isl_obj_union_pw_qpolynomial, isl_obj_union_pw_qpolynomial,
528 isl_obj_union_pw_qpolynomial,
529 (isc_bin_op_fn) &isl_union_pw_qpolynomial_mul },
530 { '*', isl_obj_union_pw_qpolynomial, isl_obj_union_set,
531 isl_obj_union_pw_qpolynomial,
532 (isc_bin_op_fn) &isl_union_pw_qpolynomial_intersect_domain },
533 { '*', isl_obj_union_pw_qpolynomial_fold, isl_obj_union_set,
534 isl_obj_union_pw_qpolynomial_fold,
535 (isc_bin_op_fn) &isl_union_pw_qpolynomial_fold_intersect_domain },
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_at },
539 { '@', isl_obj_union_pw_qpolynomial_fold, isl_obj_union_set,
540 isl_obj_union_pw_qpolynomial,
541 (isc_bin_op_fn) &isl_union_pw_qpolynomial_fold_at },
542 { '%', isl_obj_union_set, isl_obj_union_set,
543 isl_obj_union_set,
544 (isc_bin_op_fn) &isl_union_set_gist },
545 { '%', isl_obj_union_map, isl_obj_union_map,
546 isl_obj_union_map,
547 (isc_bin_op_fn) &isl_union_map_gist },
548 { '%', isl_obj_union_pw_qpolynomial, isl_obj_union_set,
549 isl_obj_union_pw_qpolynomial,
550 (isc_bin_op_fn) &isl_union_pw_qpolynomial_gist },
551 { '%', isl_obj_union_pw_qpolynomial_fold, isl_obj_union_set,
552 isl_obj_union_pw_qpolynomial_fold,
553 (isc_bin_op_fn) &isl_union_pw_qpolynomial_fold_gist },
554 { '+', isl_obj_str, isl_obj_str, isl_obj_str,
555 (isc_bin_op_fn) &isl_str_concat },
559 static __isl_give isl_union_map *map_after_map(__isl_take isl_union_map *umap1,
560 __isl_take isl_union_map *umap2)
562 return isl_union_map_apply_range(umap2, umap1);
565 static __isl_give isl_union_pw_qpolynomial *qpolynomial_after_map(
566 __isl_take isl_union_pw_qpolynomial *upwqp,
567 __isl_take isl_union_map *umap)
569 return isl_union_map_apply_union_pw_qpolynomial(umap, upwqp);
572 static __isl_give struct isl_list *qpolynomial_fold_after_map(
573 __isl_take isl_union_pw_qpolynomial_fold *upwf,
574 __isl_take isl_union_map *umap)
576 return union_map_apply_union_pw_qpolynomial_fold(umap, upwf);
579 struct isc_named_bin_op named_bin_ops[] = {
580 { "after", { -1, isl_obj_union_map, isl_obj_union_map,
581 isl_obj_union_map,
582 (isc_bin_op_fn) &map_after_map } },
583 { "after", { -1, isl_obj_union_pw_qpolynomial,
584 isl_obj_union_map, isl_obj_union_pw_qpolynomial,
585 (isc_bin_op_fn) &qpolynomial_after_map } },
586 { "after", { -1, isl_obj_union_pw_qpolynomial_fold,
587 isl_obj_union_map, isl_obj_list,
588 (isc_bin_op_fn) &qpolynomial_fold_after_map } },
589 { "before", { -1, isl_obj_union_map, isl_obj_union_map,
590 isl_obj_union_map,
591 (isc_bin_op_fn) &isl_union_map_apply_range } },
592 { "before", { -1, isl_obj_union_map,
593 isl_obj_union_pw_qpolynomial, isl_obj_union_pw_qpolynomial,
594 (isc_bin_op_fn) &isl_union_map_apply_union_pw_qpolynomial } },
595 { "before", { -1, isl_obj_union_map,
596 isl_obj_union_pw_qpolynomial_fold, isl_obj_list,
597 (isc_bin_op_fn) &union_map_apply_union_pw_qpolynomial_fold } },
598 { "cross", { -1, isl_obj_union_set, isl_obj_union_set,
599 isl_obj_union_set,
600 (isc_bin_op_fn) &isl_union_set_product } },
601 { "cross", { -1, isl_obj_union_map, isl_obj_union_map,
602 isl_obj_union_map,
603 (isc_bin_op_fn) &isl_union_map_product } },
604 NULL
607 __isl_give isl_set *union_set_sample(__isl_take isl_union_set *uset)
609 return isl_set_from_basic_set(isl_union_set_sample(uset));
612 __isl_give isl_map *union_map_sample(__isl_take isl_union_map *umap)
614 return isl_map_from_basic_map(isl_union_map_sample(umap));
617 static __isl_give struct isl_list *union_map_power(
618 __isl_take isl_union_map *umap)
620 isl_ctx *ctx;
621 struct isl_list *list;
622 int exact;
624 ctx = isl_union_map_get_ctx(umap);
625 list = isl_list_alloc(ctx, 2);
626 if (!list)
627 goto error2;
629 list->obj[0].type = isl_obj_union_map;
630 list->obj[0].v = isl_union_map_power(umap, &exact);
631 list->obj[1].type = isl_obj_bool;
632 list->obj[1].v = exact ? &isl_bool_true : &isl_bool_false;
633 if (exact < 0 || !list->obj[0].v)
634 goto error;
636 return list;
637 error2:
638 isl_union_map_free(umap);
639 error:
640 isl_list_free(list);
641 return NULL;
644 static __isl_give struct isl_list *union_pw_qpolynomial_upper_bound(
645 __isl_take isl_union_pw_qpolynomial *upwqp)
647 isl_ctx *ctx;
648 struct isl_list *list;
649 int tight;
651 ctx = isl_union_pw_qpolynomial_get_ctx(upwqp);
652 list = isl_list_alloc(ctx, 2);
653 if (!list)
654 goto error2;
656 list->obj[0].type = isl_obj_union_pw_qpolynomial_fold;
657 list->obj[0].v = isl_union_pw_qpolynomial_bound(upwqp,
658 isl_fold_max, &tight);
659 list->obj[1].type = isl_obj_bool;
660 list->obj[1].v = tight ? &isl_bool_true : &isl_bool_false;
661 if (tight < 0 || !list->obj[0].v)
662 goto error;
664 return list;
665 error2:
666 isl_union_pw_qpolynomial_free(upwqp);
667 error:
668 isl_list_free(list);
669 return NULL;
672 #ifdef HAVE_CLOOG
673 void *map_codegen(void *arg)
675 isl_dim *dim;
676 isl_union_map *umap = (isl_union_map *)arg;
677 isl_ctx *ctx = isl_union_map_get_ctx(umap);
678 CloogState *state;
679 CloogOptions *options;
680 CloogDomain *context;
681 CloogUnionDomain *ud;
682 CloogInput *input;
683 struct clast_stmt *stmt;
685 state = cloog_isl_state_malloc(ctx);
686 options = cloog_options_malloc(state);
687 options->language = LANGUAGE_C;
688 options->strides = 1;
689 options->sh = 1;
691 ud = cloog_union_domain_from_isl_union_map(isl_union_map_copy(umap));
693 dim = isl_union_map_get_dim(umap);
694 context = cloog_domain_from_isl_set(isl_set_universe(dim));
696 input = cloog_input_alloc(context, ud);
698 stmt = cloog_clast_create_from_input(input, options);
699 clast_pprint(stdout, stmt, 0, options);
700 cloog_clast_free(stmt);
702 error:
703 cloog_options_free(options);
704 cloog_state_free(state);
705 isl_union_map_free(umap);
706 return NULL;
709 void *set_codegen(void *arg)
711 isl_dim *dim;
712 isl_union_set *uset = (isl_union_set *)arg;
713 isl_ctx *ctx = isl_union_set_get_ctx(uset);
714 CloogState *state;
715 CloogOptions *options;
716 CloogDomain *context;
717 CloogUnionDomain *ud;
718 CloogInput *input;
719 struct clast_stmt *stmt;
721 if (isl_union_set_n_set(uset) > 1)
722 isl_die(ctx, isl_error_invalid,
723 "code generation for more than one domain "
724 "requires a schedule", goto error);
726 state = cloog_isl_state_malloc(ctx);
727 options = cloog_options_malloc(state);
728 options->language = LANGUAGE_C;
729 options->strides = 1;
730 options->sh = 1;
732 ud = cloog_union_domain_from_isl_union_set(isl_union_set_copy(uset));
734 dim = isl_union_set_get_dim(uset);
735 context = cloog_domain_from_isl_set(isl_set_universe(dim));
737 input = cloog_input_alloc(context, ud);
739 stmt = cloog_clast_create_from_input(input, options);
740 clast_pprint(stdout, stmt, 0, options);
741 cloog_clast_free(stmt);
743 cloog_options_free(options);
744 cloog_state_free(state);
745 error:
746 isl_union_set_free(uset);
747 return NULL;
749 #endif
751 static int add_point(__isl_take isl_point *pnt, void *user)
753 isl_union_set **scan = (isl_union_set **) user;
755 *scan = isl_union_set_add_set(*scan, isl_set_from_point(pnt));
757 return 0;
760 static __isl_give isl_union_set *union_set_scan(__isl_take isl_union_set *uset)
762 isl_union_set *scan;
764 scan = isl_union_set_empty(isl_union_set_get_dim(uset));
766 if (isl_union_set_foreach_point(uset, add_point, &scan) < 0) {
767 isl_union_set_free(scan);
768 return uset;
771 isl_union_set_free(uset);
772 return scan;
775 static __isl_give isl_union_map *union_map_scan(__isl_take isl_union_map *umap)
777 return isl_union_set_unwrap(union_set_scan(isl_union_map_wrap(umap)));
780 static __isl_give isl_union_pw_qpolynomial *union_pw_qpolynomial_poly(
781 __isl_take isl_union_pw_qpolynomial *upwqp)
783 return isl_union_pw_qpolynomial_to_polynomial(upwqp, 0);
786 static __isl_give isl_union_pw_qpolynomial *union_pw_qpolynomial_lpoly(
787 __isl_take isl_union_pw_qpolynomial *upwqp)
789 return isl_union_pw_qpolynomial_to_polynomial(upwqp, -1);
792 static __isl_give isl_union_pw_qpolynomial *union_pw_qpolynomial_upoly(
793 __isl_take isl_union_pw_qpolynomial *upwqp)
795 return isl_union_pw_qpolynomial_to_polynomial(upwqp, 1);
798 typedef void *(*isc_un_op_fn)(void *arg);
799 struct isc_un_op {
800 enum isl_token_type op;
801 isl_obj_type arg;
802 isl_obj_type res;
803 isc_un_op_fn fn;
805 struct isc_named_un_op {
806 char *name;
807 struct isc_un_op op;
809 struct isc_named_un_op named_un_ops[] = {
810 {"aff", { -1, isl_obj_union_map, isl_obj_union_map,
811 (isc_un_op_fn) &isl_union_map_affine_hull } },
812 {"aff", { -1, isl_obj_union_set, isl_obj_union_set,
813 (isc_un_op_fn) &isl_union_set_affine_hull } },
814 {"card", { -1, isl_obj_union_set,
815 isl_obj_union_pw_qpolynomial,
816 (isc_un_op_fn) &isl_union_set_card } },
817 {"card", { -1, isl_obj_union_map,
818 isl_obj_union_pw_qpolynomial,
819 (isc_un_op_fn) &isl_union_map_card } },
820 {"coalesce", { -1, isl_obj_union_set, isl_obj_union_set,
821 (isc_un_op_fn) &isl_union_set_coalesce } },
822 {"coalesce", { -1, isl_obj_union_map, isl_obj_union_map,
823 (isc_un_op_fn) &isl_union_map_coalesce } },
824 {"coalesce", { -1, isl_obj_union_pw_qpolynomial,
825 isl_obj_union_pw_qpolynomial,
826 (isc_un_op_fn) &isl_union_pw_qpolynomial_coalesce } },
827 {"coalesce", { -1, isl_obj_union_pw_qpolynomial_fold,
828 isl_obj_union_pw_qpolynomial_fold,
829 (isc_un_op_fn) &isl_union_pw_qpolynomial_fold_coalesce } },
830 #ifdef HAVE_CLOOG
831 {"codegen", { -1, isl_obj_union_set, isl_obj_none,
832 &set_codegen } },
833 {"codegen", { -1, isl_obj_union_map, isl_obj_none,
834 &map_codegen } },
835 #endif
836 {"coefficients", { -1, isl_obj_union_set,
837 isl_obj_union_set,
838 (isc_un_op_fn) &isl_union_set_coefficients } },
839 {"solutions", { -1, isl_obj_union_set, isl_obj_union_set,
840 (isc_un_op_fn) &isl_union_set_solutions } },
841 {"deltas", { -1, isl_obj_union_map, isl_obj_union_set,
842 (isc_un_op_fn) &isl_union_map_deltas } },
843 {"deltas_map", { -1, isl_obj_union_map, isl_obj_union_map,
844 (isc_un_op_fn) &isl_union_map_deltas_map } },
845 {"dom", { -1, isl_obj_union_map, isl_obj_union_set,
846 (isc_un_op_fn) &isl_union_map_domain } },
847 {"dom", { -1, isl_obj_union_pw_qpolynomial, isl_obj_union_set,
848 (isc_un_op_fn) &isl_union_pw_qpolynomial_domain } },
849 {"dom", { -1, isl_obj_union_pw_qpolynomial_fold,
850 isl_obj_union_set,
851 (isc_un_op_fn) &isl_union_pw_qpolynomial_fold_domain } },
852 {"domain", { -1, isl_obj_union_map, isl_obj_union_set,
853 (isc_un_op_fn) &isl_union_map_domain } },
854 {"domain", { -1, isl_obj_union_pw_qpolynomial,
855 isl_obj_union_set,
856 (isc_un_op_fn) &isl_union_pw_qpolynomial_domain } },
857 {"domain", { -1, isl_obj_union_pw_qpolynomial_fold,
858 isl_obj_union_set,
859 (isc_un_op_fn) &isl_union_pw_qpolynomial_fold_domain } },
860 {"domain_map", { -1, isl_obj_union_map, isl_obj_union_map,
861 (isc_un_op_fn) &isl_union_map_domain_map } },
862 {"ran", { -1, isl_obj_union_map, isl_obj_union_set,
863 (isc_un_op_fn) &isl_union_map_range } },
864 {"range", { -1, isl_obj_union_map, isl_obj_union_set,
865 (isc_un_op_fn) &isl_union_map_range } },
866 {"range_map", { -1, isl_obj_union_map, isl_obj_union_map,
867 (isc_un_op_fn) &isl_union_map_range_map } },
868 {"identity", { -1, isl_obj_union_set, isl_obj_union_map,
869 (isc_un_op_fn) &isl_union_set_identity } },
870 {"lexmin", { -1, isl_obj_union_map, isl_obj_union_map,
871 (isc_un_op_fn) &isl_union_map_lexmin } },
872 {"lexmax", { -1, isl_obj_union_map, isl_obj_union_map,
873 (isc_un_op_fn) &isl_union_map_lexmax } },
874 {"lexmin", { -1, isl_obj_union_set, isl_obj_union_set,
875 (isc_un_op_fn) &isl_union_set_lexmin } },
876 {"lexmax", { -1, isl_obj_union_set, isl_obj_union_set,
877 (isc_un_op_fn) &isl_union_set_lexmax } },
878 {"lift", { -1, isl_obj_union_set, isl_obj_union_set,
879 (isc_un_op_fn) &isl_union_set_lift } },
880 {"poly", { -1, isl_obj_union_map, isl_obj_union_map,
881 (isc_un_op_fn) &isl_union_map_polyhedral_hull } },
882 {"poly", { -1, isl_obj_union_set, isl_obj_union_set,
883 (isc_un_op_fn) &isl_union_set_polyhedral_hull } },
884 {"poly", { -1, isl_obj_union_pw_qpolynomial,
885 isl_obj_union_pw_qpolynomial,
886 (isc_un_op_fn) &union_pw_qpolynomial_poly } },
887 {"lpoly", { -1, isl_obj_union_pw_qpolynomial,
888 isl_obj_union_pw_qpolynomial,
889 (isc_un_op_fn) &union_pw_qpolynomial_lpoly } },
890 {"upoly", { -1, isl_obj_union_pw_qpolynomial,
891 isl_obj_union_pw_qpolynomial,
892 (isc_un_op_fn) &union_pw_qpolynomial_upoly } },
893 {"pow", { -1, isl_obj_union_map, isl_obj_list,
894 (isc_un_op_fn) &union_map_power } },
895 {"sample", { -1, isl_obj_union_set, isl_obj_set,
896 (isc_un_op_fn) &union_set_sample } },
897 {"sample", { -1, isl_obj_union_map, isl_obj_map,
898 (isc_un_op_fn) &union_map_sample } },
899 {"scan", { -1, isl_obj_union_set, isl_obj_union_set,
900 (isc_un_op_fn) &union_set_scan } },
901 {"scan", { -1, isl_obj_union_map, isl_obj_union_map,
902 (isc_un_op_fn) &union_map_scan } },
903 {"sum", { -1, isl_obj_union_pw_qpolynomial,
904 isl_obj_union_pw_qpolynomial,
905 (isc_un_op_fn) &isl_union_pw_qpolynomial_sum } },
906 {"ub", { -1, isl_obj_union_pw_qpolynomial, isl_obj_list,
907 (isc_un_op_fn) &union_pw_qpolynomial_upper_bound } },
908 {"unwrap", { -1, isl_obj_union_set, isl_obj_union_map,
909 (isc_un_op_fn) &isl_union_set_unwrap } },
910 {"wrap", { -1, isl_obj_union_map, isl_obj_union_set,
911 (isc_un_op_fn) &isl_union_map_wrap } },
912 {"zip", { -1, isl_obj_union_map, isl_obj_union_map,
913 (isc_un_op_fn) &isl_union_map_zip } },
914 NULL
917 struct isl_named_obj {
918 char *name;
919 struct isl_obj obj;
922 static void free_obj(struct isl_obj obj)
924 obj.type->free(obj.v);
927 static int same_name(const void *entry, const void *val)
929 const struct isl_named_obj *named = (const struct isl_named_obj *)entry;
931 return !strcmp(named->name, val);
934 static int do_assign(struct isl_ctx *ctx, struct isl_hash_table *table,
935 char *name, struct isl_obj obj)
937 struct isl_hash_table_entry *entry;
938 uint32_t name_hash;
939 struct isl_named_obj *named;
941 name_hash = isl_hash_string(isl_hash_init(), name);
942 entry = isl_hash_table_find(ctx, table, name_hash, same_name, name, 1);
943 if (!entry)
944 goto error;
945 if (entry->data) {
946 named = entry->data;
947 free_obj(named->obj);
948 free(name);
949 } else {
950 named = isl_alloc_type(ctx, struct isl_named_obj);
951 if (!named)
952 goto error;
953 named->name = name;
954 entry->data = named;
956 named->obj = obj;
958 return 0;
959 error:
960 free_obj(obj);
961 free(name);
962 return -1;
965 static struct isl_obj stored_obj(struct isl_ctx *ctx,
966 struct isl_hash_table *table, char *name)
968 struct isl_obj obj = { isl_obj_none, NULL };
969 struct isl_hash_table_entry *entry;
970 uint32_t name_hash;
972 name_hash = isl_hash_string(isl_hash_init(), name);
973 entry = isl_hash_table_find(ctx, table, name_hash, same_name, name, 0);
974 if (entry) {
975 struct isl_named_obj *named;
976 named = entry->data;
977 obj = named->obj;
978 } else if (isdigit(name[0]))
979 fprintf(stderr, "unknown identifier '$%s'\n", name);
980 else
981 fprintf(stderr, "unknown identifier '%s'\n", name);
983 free(name);
984 obj.v = obj.type->copy(obj.v);
985 return obj;
988 static int is_subtype(struct isl_obj obj, isl_obj_type super)
990 if (obj.type == super)
991 return 1;
992 if (obj.type == isl_obj_map && super == isl_obj_union_map)
993 return 1;
994 if (obj.type == isl_obj_set && super == isl_obj_union_set)
995 return 1;
996 if (obj.type == isl_obj_pw_qpolynomial &&
997 super == isl_obj_union_pw_qpolynomial)
998 return 1;
999 if (obj.type == isl_obj_pw_qpolynomial_fold &&
1000 super == isl_obj_union_pw_qpolynomial_fold)
1001 return 1;
1002 if (obj.type == isl_obj_union_set && isl_union_set_is_empty(obj.v))
1003 return 1;
1004 if (obj.type == isl_obj_list) {
1005 struct isl_list *list = obj.v;
1006 if (list->n == 2 && list->obj[1].type == isl_obj_bool)
1007 return is_subtype(list->obj[0], super);
1009 if (super == isl_obj_str)
1010 return 1;
1011 return 0;
1014 static struct isl_obj obj_at(struct isl_obj obj, int i)
1016 struct isl_list *list = obj.v;
1018 obj = list->obj[i];
1019 obj.v = obj.type->copy(obj.v);
1021 isl_list_free(list);
1023 return obj;
1026 static struct isl_obj convert(isl_ctx *ctx, struct isl_obj obj,
1027 isl_obj_type type)
1029 if (obj.type == type)
1030 return obj;
1031 if (obj.type == isl_obj_map && type == isl_obj_union_map) {
1032 obj.type = isl_obj_union_map;
1033 obj.v = isl_union_map_from_map(obj.v);
1034 return obj;
1036 if (obj.type == isl_obj_set && type == isl_obj_union_set) {
1037 obj.type = isl_obj_union_set;
1038 obj.v = isl_union_set_from_set(obj.v);
1039 return obj;
1041 if (obj.type == isl_obj_pw_qpolynomial &&
1042 type == isl_obj_union_pw_qpolynomial) {
1043 obj.type = isl_obj_union_pw_qpolynomial;
1044 obj.v = isl_union_pw_qpolynomial_from_pw_qpolynomial(obj.v);
1045 return obj;
1047 if (obj.type == isl_obj_pw_qpolynomial_fold &&
1048 type == isl_obj_union_pw_qpolynomial_fold) {
1049 obj.type = isl_obj_union_pw_qpolynomial_fold;
1050 obj.v = isl_union_pw_qpolynomial_fold_from_pw_qpolynomial_fold(obj.v);
1051 return obj;
1053 if (obj.type == isl_obj_union_set && isl_union_set_is_empty(obj.v)) {
1054 if (type == isl_obj_union_map) {
1055 obj.type = isl_obj_union_map;
1056 return obj;
1058 if (type == isl_obj_union_pw_qpolynomial) {
1059 isl_dim *dim = isl_union_set_get_dim(obj.v);
1060 isl_union_set_free(obj.v);
1061 obj.v = isl_union_pw_qpolynomial_zero(dim);
1062 obj.type = isl_obj_union_pw_qpolynomial;
1063 return obj;
1065 if (type == isl_obj_union_pw_qpolynomial_fold) {
1066 isl_dim *dim = isl_union_set_get_dim(obj.v);
1067 isl_union_set_free(obj.v);
1068 obj.v = isl_union_pw_qpolynomial_fold_zero(dim,
1069 isl_fold_list);
1070 obj.type = isl_obj_union_pw_qpolynomial_fold;
1071 return obj;
1074 if (obj.type == isl_obj_list) {
1075 struct isl_list *list = obj.v;
1076 if (list->n == 2 && list->obj[1].type == isl_obj_bool)
1077 return convert(ctx, obj_at(obj, 0), type);
1079 if (type == isl_obj_str) {
1080 isl_str *str;
1081 isl_printer *p;
1082 char *s;
1084 p = isl_printer_to_str(ctx);
1085 if (!p)
1086 goto error;
1087 p = obj.type->print(p, obj.v);
1088 s = isl_printer_get_str(p);
1089 isl_printer_free(p);
1091 str = isl_str_from_string(ctx, s);
1092 if (!str)
1093 goto error;
1094 free_obj(obj);
1095 obj.v = str;
1096 obj.type = isl_obj_str;
1097 return obj;
1100 error:
1101 free_obj(obj);
1102 obj.type = isl_obj_none;
1103 obj.v = NULL;
1104 return obj;
1107 static struct isc_bin_op *read_bin_op_if_available(struct isl_stream *s,
1108 struct isl_obj lhs)
1110 int i;
1111 struct isl_token *tok;
1113 tok = isl_stream_next_token(s);
1114 if (!tok)
1115 return NULL;
1117 for (i = 0; ; ++i) {
1118 if (!bin_ops[i].op)
1119 break;
1120 if (bin_ops[i].op != tok->type)
1121 continue;
1122 if (!is_subtype(lhs, bin_ops[i].lhs))
1123 continue;
1125 isl_token_free(tok);
1126 return &bin_ops[i];
1129 for (i = 0; ; ++i) {
1130 if (!named_bin_ops[i].name)
1131 break;
1132 if (named_bin_ops[i].op.op != tok->type)
1133 continue;
1134 if (!is_subtype(lhs, named_bin_ops[i].op.lhs))
1135 continue;
1137 isl_token_free(tok);
1138 return &named_bin_ops[i].op;
1141 isl_stream_push_token(s, tok);
1143 return NULL;
1146 static struct isc_un_op *read_prefix_un_op_if_available(struct isl_stream *s)
1148 int i;
1149 struct isl_token *tok;
1151 tok = isl_stream_next_token(s);
1152 if (!tok)
1153 return NULL;
1155 for (i = 0; ; ++i) {
1156 if (!named_un_ops[i].name)
1157 break;
1158 if (named_un_ops[i].op.op != tok->type)
1159 continue;
1161 isl_token_free(tok);
1162 return &named_un_ops[i].op;
1165 isl_stream_push_token(s, tok);
1167 return NULL;
1170 static struct isc_un_op *find_matching_un_op(struct isc_un_op *like,
1171 struct isl_obj arg)
1173 int i;
1175 for (i = 0; ; ++i) {
1176 if (!named_un_ops[i].name)
1177 break;
1178 if (named_un_ops[i].op.op != like->op)
1179 continue;
1180 if (!is_subtype(arg, named_un_ops[i].op.arg))
1181 continue;
1183 return &named_un_ops[i].op;
1186 return NULL;
1189 static int is_assign(struct isl_stream *s)
1191 struct isl_token *tok;
1192 struct isl_token *tok2;
1193 int assign;
1195 tok = isl_stream_next_token(s);
1196 if (!tok)
1197 return 0;
1198 if (tok->type != ISL_TOKEN_IDENT) {
1199 isl_stream_push_token(s, tok);
1200 return 0;
1203 tok2 = isl_stream_next_token(s);
1204 if (!tok2) {
1205 isl_stream_push_token(s, tok);
1206 return 0;
1208 assign = tok2->type == ISL_TOKEN_DEF;
1209 isl_stream_push_token(s, tok2);
1210 isl_stream_push_token(s, tok);
1212 return assign;
1215 static struct isl_obj read_obj(struct isl_stream *s,
1216 struct isl_hash_table *table);
1217 static struct isl_obj read_expr(struct isl_stream *s,
1218 struct isl_hash_table *table);
1220 static struct isl_obj read_un_op_expr(struct isl_stream *s,
1221 struct isl_hash_table *table, struct isc_un_op *op)
1223 struct isl_obj obj = { isl_obj_none, NULL };
1225 obj = read_obj(s, table);
1226 if (!obj.v)
1227 goto error;
1229 op = find_matching_un_op(op, obj);
1231 if (!op)
1232 isl_die(s->ctx, isl_error_invalid,
1233 "no such unary operator defined on given operand",
1234 goto error);
1236 obj = convert(s->ctx, obj, op->arg);
1237 obj.v = op->fn(obj.v);
1238 obj.type = op->res;
1240 return obj;
1241 error:
1242 free_obj(obj);
1243 obj.type = isl_obj_none;
1244 obj.v = NULL;
1245 return obj;
1248 static struct isl_obj transitive_closure(struct isl_ctx *ctx, struct isl_obj obj)
1250 struct isl_list *list;
1251 int exact;
1253 if (obj.type != isl_obj_union_map)
1254 obj = convert(ctx, obj, isl_obj_union_map);
1255 isl_assert(ctx, obj.type == isl_obj_union_map, goto error);
1256 list = isl_list_alloc(ctx, 2);
1257 if (!list)
1258 goto error;
1260 list->obj[0].type = isl_obj_union_map;
1261 list->obj[0].v = isl_union_map_transitive_closure(obj.v, &exact);
1262 list->obj[1].type = isl_obj_bool;
1263 list->obj[1].v = exact ? &isl_bool_true : &isl_bool_false;
1264 obj.v = list;
1265 obj.type = isl_obj_list;
1266 if (exact < 0 || !list->obj[0].v)
1267 goto error;
1269 return obj;
1270 error:
1271 free_obj(obj);
1272 obj.type = isl_obj_none;
1273 obj.v = NULL;
1274 return obj;
1277 static struct isl_obj obj_at_index(struct isl_stream *s, struct isl_obj obj)
1279 struct isl_list *list = obj.v;
1280 struct isl_token *tok;
1281 int i;
1283 tok = isl_stream_next_token(s);
1284 if (!tok || tok->type != ISL_TOKEN_VALUE) {
1285 isl_stream_error(s, tok, "expecting index");
1286 if (tok)
1287 isl_stream_push_token(s, tok);
1288 goto error;
1290 i = isl_int_get_si(tok->u.v);
1291 isl_token_free(tok);
1292 isl_assert(s->ctx, i < list->n, goto error);
1293 if (isl_stream_eat(s, ']'))
1294 goto error;
1296 return obj_at(obj, i);
1297 error:
1298 free_obj(obj);
1299 obj.type = isl_obj_none;
1300 obj.v = NULL;
1301 return obj;
1304 static struct isl_obj apply(struct isl_stream *s, __isl_take isl_union_map *umap,
1305 struct isl_hash_table *table)
1307 struct isl_obj obj;
1309 obj = read_expr(s, table);
1310 isl_assert(s->ctx, is_subtype(obj, isl_obj_union_set) ||
1311 is_subtype(obj, isl_obj_union_map), goto error);
1313 if (obj.type == isl_obj_list) {
1314 struct isl_list *list = obj.v;
1315 if (list->n == 2 && list->obj[1].type == isl_obj_bool)
1316 obj = obj_at(obj, 0);
1318 if (obj.type == isl_obj_set)
1319 obj = convert(s->ctx, obj, isl_obj_union_set);
1320 else if (obj.type == isl_obj_map)
1321 obj = convert(s->ctx, obj, isl_obj_union_map);
1322 if (obj.type == isl_obj_union_set) {
1323 obj.v = isl_union_set_apply(obj.v, umap);
1324 } else
1325 obj.v = isl_union_map_apply_range(obj.v, umap);
1326 if (!obj.v)
1327 goto error2;
1329 if (isl_stream_eat(s, ')'))
1330 goto error2;
1332 return obj;
1333 error:
1334 isl_union_map_free(umap);
1335 error2:
1336 free_obj(obj);
1337 obj.type = isl_obj_none;
1338 obj.v = NULL;
1339 return obj;
1342 static struct isl_obj apply_fun(struct isl_stream *s,
1343 struct isl_obj obj, struct isl_hash_table *table)
1345 struct isl_obj arg;
1347 arg = read_expr(s, table);
1348 if (!is_subtype(arg, isl_obj_union_map) &&
1349 !is_subtype(arg, isl_obj_union_set))
1350 isl_die(s->ctx, isl_error_invalid,
1351 "expecting set of map argument", goto error);
1353 if (arg.type == isl_obj_list) {
1354 struct isl_list *list = arg.v;
1355 if (list->n == 2 && list->obj[1].type == isl_obj_bool)
1356 arg = obj_at(arg, 0);
1358 if (arg.type == isl_obj_set)
1359 arg = convert(s->ctx, arg, isl_obj_union_set);
1360 else if (arg.type == isl_obj_map)
1361 arg = convert(s->ctx, arg, isl_obj_union_map);
1362 if (arg.type == isl_obj_union_set) {
1363 arg.v = isl_union_map_from_range(arg.v);
1364 arg.type = isl_obj_union_map;
1366 if (obj.type == isl_obj_union_pw_qpolynomial) {
1367 obj.v = isl_union_map_apply_union_pw_qpolynomial(arg.v, obj.v);
1368 } else {
1369 obj.type = isl_obj_list;
1370 obj.v = union_map_apply_union_pw_qpolynomial_fold(arg.v, obj.v);
1372 if (!obj.v)
1373 goto error2;
1375 if (isl_stream_eat(s, ')'))
1376 goto error2;
1378 return obj;
1379 error:
1380 free_obj(arg);
1381 error2:
1382 free_obj(obj);
1383 obj.type = isl_obj_none;
1384 obj.v = NULL;
1385 return obj;
1388 struct add_vertex_data {
1389 struct isl_list *list;
1390 int i;
1393 static int add_vertex(__isl_take isl_vertex *vertex, void *user)
1395 struct add_vertex_data *data = (struct add_vertex_data *)user;
1396 isl_basic_set *expr;
1398 expr = isl_vertex_get_expr(vertex);
1400 data->list->obj[data->i].type = isl_obj_set;
1401 data->list->obj[data->i].v = isl_set_from_basic_set(expr);
1402 data->i++;
1404 isl_vertex_free(vertex);
1406 return 0;
1409 static int set_vertices(__isl_take isl_set *set, void *user)
1411 isl_ctx *ctx;
1412 isl_basic_set *hull;
1413 isl_vertices *vertices = NULL;
1414 struct isl_list *list = NULL;
1415 int r;
1416 struct add_vertex_data *data = (struct add_vertex_data *)user;
1418 set = isl_set_remove_divs(set);
1419 hull = isl_set_convex_hull(set);
1420 vertices = isl_basic_set_compute_vertices(hull);
1421 isl_basic_set_free(hull);
1423 list = data->list;
1425 ctx = isl_vertices_get_ctx(vertices);
1426 data->list = isl_list_alloc(ctx, isl_vertices_get_n_vertices(vertices));
1427 if (!data->list)
1428 goto error;
1430 data->i = 0;
1431 r = isl_vertices_foreach_vertex(vertices, &add_vertex, user);
1433 data->list = isl_list_concat(list, data->list);
1435 isl_vertices_free(vertices);
1437 return r;
1438 error:
1439 data->list = list;
1440 isl_vertices_free(vertices);
1441 return -1;
1444 static struct isl_obj vertices(struct isl_stream *s,
1445 struct isl_hash_table *table)
1447 isl_ctx *ctx;
1448 struct isl_obj obj;
1449 struct isl_list *list = NULL;
1450 isl_union_set *uset;
1451 struct add_vertex_data data = { NULL };
1453 obj = read_expr(s, table);
1454 obj = convert(s->ctx, obj, isl_obj_union_set);
1455 isl_assert(s->ctx, obj.type == isl_obj_union_set, goto error);
1456 uset = obj.v;
1457 obj.v = NULL;
1459 ctx = isl_union_set_get_ctx(uset);
1460 list = isl_list_alloc(ctx, 0);
1461 if (!list)
1462 goto error;
1464 data.list = list;
1466 if (isl_union_set_foreach_set(uset, &set_vertices, &data) < 0)
1467 goto error;
1469 isl_union_set_free(uset);
1471 obj.type = isl_obj_list;
1472 obj.v = data.list;
1474 return obj;
1475 error:
1476 isl_union_set_free(uset);
1477 isl_list_free(data.list);
1478 free_obj(obj);
1479 obj.type = isl_obj_none;
1480 obj.v = NULL;
1481 return obj;
1484 static struct isl_obj type_of(struct isl_stream *s,
1485 struct isl_hash_table *table)
1487 isl_ctx *ctx;
1488 struct isl_obj obj;
1489 const char *type = "unknown";
1491 obj = read_expr(s, table);
1493 if (obj.type == isl_obj_map ||
1494 obj.type == isl_obj_union_map)
1495 type = "map";
1496 if (obj.type == isl_obj_set ||
1497 obj.type == isl_obj_union_set)
1498 type = "set";
1499 if (obj.type == isl_obj_pw_qpolynomial ||
1500 obj.type == isl_obj_union_pw_qpolynomial)
1501 type = "piecewise quasipolynomial";
1502 if (obj.type == isl_obj_pw_qpolynomial_fold ||
1503 obj.type == isl_obj_union_pw_qpolynomial_fold)
1504 type = "piecewise quasipolynomial fold";
1505 if (obj.type == isl_obj_list)
1506 type = "list";
1507 if (obj.type == isl_obj_bool)
1508 type = "boolean";
1509 if (obj.type == isl_obj_str)
1510 type = "string";
1511 if (obj.type == isl_obj_int)
1512 type = "int";
1514 free_obj(obj);
1515 obj.type = isl_obj_str;
1516 obj.v = isl_str_from_string(s->ctx, strdup(type));
1518 return obj;
1521 static __isl_give isl_union_set *read_set(struct isl_stream *s,
1522 struct isl_hash_table *table)
1524 struct isl_obj obj;
1526 obj = read_obj(s, table);
1527 obj = convert(s->ctx, obj, isl_obj_union_set);
1528 isl_assert(s->ctx, obj.type == isl_obj_union_set, goto error);
1529 return obj.v;
1530 error:
1531 free_obj(obj);
1532 return NULL;
1535 static __isl_give isl_union_map *read_map(struct isl_stream *s,
1536 struct isl_hash_table *table)
1538 struct isl_obj obj;
1540 obj = read_obj(s, table);
1541 obj = convert(s->ctx, obj, isl_obj_union_map);
1542 isl_assert(s->ctx, obj.type == isl_obj_union_map, goto error);
1543 return obj.v;
1544 error:
1545 free_obj(obj);
1546 return NULL;
1549 static struct isl_obj last_any(struct isl_stream *s,
1550 struct isl_hash_table *table, __isl_take isl_union_map *must_source,
1551 __isl_take isl_union_map *may_source)
1553 struct isl_obj obj = { isl_obj_none, NULL };
1554 isl_union_map *sink = NULL;
1555 isl_union_map *schedule = NULL;
1556 isl_union_map *may_dep;
1557 isl_union_map *must_dep;
1559 if (isl_stream_eat(s, iscc_op[ISCC_BEFORE]))
1560 goto error;
1562 sink = read_map(s, table);
1563 if (!sink)
1564 goto error;
1566 if (isl_stream_eat(s, iscc_op[ISCC_UNDER]))
1567 goto error;
1569 schedule = read_map(s, table);
1570 if (!schedule)
1571 goto error;
1573 if (isl_union_map_compute_flow(sink, must_source, may_source,
1574 schedule, &must_dep, &may_dep,
1575 NULL, NULL) < 0)
1576 return obj;
1578 obj.type = isl_obj_union_map;
1579 obj.v = isl_union_map_union(must_dep, may_dep);
1581 return obj;
1582 error:
1583 isl_union_map_free(may_source);
1584 isl_union_map_free(must_source);
1585 isl_union_map_free(sink);
1586 isl_union_map_free(schedule);
1587 free_obj(obj);
1588 obj.type = isl_obj_none;
1589 obj.v = NULL;
1590 return obj;
1593 static struct isl_obj any(struct isl_stream *s, struct isl_hash_table *table)
1595 struct isl_obj obj = { isl_obj_none, NULL };
1596 isl_union_map *must_source = NULL;
1597 isl_union_map *may_source = NULL;
1598 isl_union_map *sink = NULL;
1599 isl_union_map *schedule = NULL;
1600 isl_union_map *may_dep;
1602 may_source = read_map(s, table);
1603 if (!may_source)
1604 goto error;
1606 if (isl_stream_eat_if_available(s, iscc_op[ISCC_LAST])) {
1607 must_source = read_map(s, table);
1608 if (!must_source)
1609 goto error;
1610 return last_any(s, table, must_source, may_source);
1613 if (isl_stream_eat(s, iscc_op[ISCC_BEFORE]))
1614 goto error;
1616 sink = read_map(s, table);
1617 if (!sink)
1618 goto error;
1620 if (isl_stream_eat(s, iscc_op[ISCC_UNDER]))
1621 goto error;
1623 schedule = read_map(s, table);
1624 if (!schedule)
1625 goto error;
1627 must_source = isl_union_map_empty(isl_union_map_get_dim(sink));
1628 if (isl_union_map_compute_flow(sink, must_source, may_source,
1629 schedule, NULL, &may_dep,
1630 NULL, NULL) < 0)
1631 return obj;
1633 obj.type = isl_obj_union_map;
1634 obj.v = may_dep;
1636 return obj;
1637 error:
1638 isl_union_map_free(may_source);
1639 isl_union_map_free(must_source);
1640 isl_union_map_free(sink);
1641 isl_union_map_free(schedule);
1642 free_obj(obj);
1643 obj.type = isl_obj_none;
1644 obj.v = NULL;
1645 return obj;
1648 static struct isl_obj last(struct isl_stream *s, struct isl_hash_table *table)
1650 struct isl_obj obj = { isl_obj_none, NULL };
1651 struct isl_list *list = NULL;
1652 isl_union_map *must_source = NULL;
1653 isl_union_map *may_source = NULL;
1654 isl_union_map *sink = NULL;
1655 isl_union_map *schedule = NULL;
1656 isl_union_map *must_dep;
1657 isl_union_map *must_no_source;
1659 must_source = read_map(s, table);
1660 if (!must_source)
1661 goto error;
1663 if (isl_stream_eat_if_available(s, iscc_op[ISCC_ANY])) {
1664 may_source = read_map(s, table);
1665 if (!may_source)
1666 goto error;
1667 return last_any(s, table, must_source, may_source);
1670 list = isl_list_alloc(s->ctx, 2);
1671 if (!list)
1672 goto error;
1674 if (isl_stream_eat(s, iscc_op[ISCC_BEFORE]))
1675 goto error;
1677 sink = read_map(s, table);
1678 if (!sink)
1679 goto error;
1681 if (isl_stream_eat(s, iscc_op[ISCC_UNDER]))
1682 goto error;
1684 schedule = read_map(s, table);
1685 if (!schedule)
1686 goto error;
1688 may_source = isl_union_map_empty(isl_union_map_get_dim(sink));
1689 if (isl_union_map_compute_flow(sink, must_source, may_source,
1690 schedule, &must_dep, NULL,
1691 &must_no_source, NULL) < 0) {
1692 isl_list_free(list);
1693 return obj;
1696 list->obj[0].type = isl_obj_union_map;
1697 list->obj[0].v = must_dep;
1698 list->obj[1].type = isl_obj_union_map;
1699 list->obj[1].v = must_no_source;
1701 obj.v = list;
1702 obj.type = isl_obj_list;
1704 return obj;
1705 error:
1706 isl_list_free(list);
1707 isl_union_map_free(may_source);
1708 isl_union_map_free(must_source);
1709 isl_union_map_free(sink);
1710 isl_union_map_free(schedule);
1711 free_obj(obj);
1712 obj.type = isl_obj_none;
1713 obj.v = NULL;
1714 return obj;
1717 static __isl_give isl_schedule *get_schedule(struct isl_stream *s,
1718 struct isl_hash_table *table)
1720 isl_union_set *domain;
1721 isl_union_map *validity;
1722 isl_union_map *proximity;
1724 domain = read_set(s, table);
1725 if (!domain)
1726 return NULL;
1728 validity = isl_union_map_empty(isl_union_set_get_dim(domain));
1729 proximity = isl_union_map_empty(isl_union_set_get_dim(domain));
1731 for (;;) {
1732 isl_union_map *umap;
1733 if (isl_stream_eat_if_available(s, iscc_op[ISCC_RESPECTING])) {
1734 umap = read_map(s, table);
1735 validity = isl_union_map_union(validity, umap);
1736 } else if (isl_stream_eat_if_available(s, iscc_op[ISCC_MINIMIZING])) {
1737 umap = read_map(s, table);
1738 proximity = isl_union_map_union(proximity, umap);
1739 } else
1740 break;
1743 return isl_union_set_compute_schedule(domain, validity, proximity);
1746 static struct isl_obj schedule(struct isl_stream *s,
1747 struct isl_hash_table *table)
1749 struct isl_obj obj = { isl_obj_none, NULL };
1750 isl_schedule *schedule;
1752 schedule = get_schedule(s, table);
1754 obj.v = isl_schedule_get_map(schedule);
1755 obj.type = isl_obj_union_map;
1757 isl_schedule_free(schedule);
1759 return obj;
1762 static struct isl_obj schedule_bands(struct isl_stream *s,
1763 struct isl_hash_table *table)
1765 int i;
1766 int n_band;
1767 struct isl_obj obj = { isl_obj_none, NULL };
1768 struct isl_list *list;
1769 isl_schedule *schedule;
1771 schedule = get_schedule(s, table);
1772 if (!schedule)
1773 return obj;
1775 n_band = isl_schedule_n_band(schedule);
1776 list = isl_list_alloc(s->ctx, n_band);
1777 if (!list)
1778 goto error;
1780 obj.v = list;
1781 obj.type = isl_obj_list;
1783 for (i = 0; i < n_band; ++i) {
1784 list->obj[i].type = isl_obj_union_map;
1785 list->obj[i].v = isl_schedule_get_band(schedule, i);
1786 if (!list->obj[i].v)
1787 goto error;
1790 isl_schedule_free(schedule);
1792 return obj;
1793 error:
1794 isl_schedule_free(schedule);
1795 free_obj(obj);
1796 obj.type = isl_obj_none;
1797 obj.v = NULL;
1798 return obj;
1801 static struct isl_obj power(struct isl_stream *s, struct isl_obj obj)
1803 struct isl_token *tok;
1805 if (isl_stream_eat_if_available(s, '+'))
1806 return transitive_closure(s->ctx, obj);
1808 tok = isl_stream_next_token(s);
1809 if (!tok || tok->type != ISL_TOKEN_VALUE || isl_int_cmp_si(tok->u.v, -1)) {
1810 isl_stream_error(s, tok, "expecting -1");
1811 if (tok)
1812 isl_stream_push_token(s, tok);
1813 goto error;
1815 isl_token_free(tok);
1816 isl_assert(s->ctx, is_subtype(obj, isl_obj_union_map), goto error);
1817 if (obj.type != isl_obj_union_map)
1818 obj = convert(s->ctx, obj, isl_obj_union_map);
1820 obj.v = isl_union_map_reverse(obj.v);
1821 if (!obj.v)
1822 goto error;
1824 return obj;
1825 error:
1826 free_obj(obj);
1827 obj.type = isl_obj_none;
1828 obj.v = NULL;
1829 return obj;
1832 static struct isl_obj read_from_file(struct isl_stream *s)
1834 struct isl_obj obj;
1835 struct isl_token *tok;
1836 struct isl_stream *s_file;
1837 struct iscc_options *options;
1838 FILE *file;
1840 tok = isl_stream_next_token(s);
1841 if (!tok || tok->type != ISL_TOKEN_STRING) {
1842 isl_stream_error(s, tok, "expecting filename");
1843 isl_token_free(tok);
1844 goto error;
1847 options = isl_ctx_peek_iscc_options(s->ctx);
1848 if (!options || !options->io) {
1849 isl_token_free(tok);
1850 isl_die(s->ctx, isl_error_invalid,
1851 "read operation not allowed", goto error);
1854 file = fopen(tok->u.s, "r");
1855 isl_token_free(tok);
1856 isl_assert(s->ctx, file, goto error);
1858 s_file = isl_stream_new_file(s->ctx, file);
1859 if (!s_file) {
1860 fclose(file);
1861 goto error;
1864 obj = isl_stream_read_obj(s_file);
1866 isl_stream_free(s_file);
1867 fclose(file);
1869 return obj;
1870 error:
1871 obj.type = isl_obj_none;
1872 obj.v = NULL;
1873 return obj;
1876 static struct isl_obj write_to_file(struct isl_stream *s,
1877 struct isl_hash_table *table)
1879 struct isl_obj obj;
1880 struct isl_token *tok;
1881 struct isl_stream *s_file;
1882 struct iscc_options *options;
1883 FILE *file;
1884 isl_printer *p;
1886 tok = isl_stream_next_token(s);
1887 if (!tok || tok->type != ISL_TOKEN_STRING) {
1888 isl_stream_error(s, tok, "expecting filename");
1889 isl_token_free(tok);
1890 goto error;
1893 obj = read_expr(s, table);
1895 options = isl_ctx_peek_iscc_options(s->ctx);
1896 if (!options || !options->io) {
1897 isl_token_free(tok);
1898 isl_die(s->ctx, isl_error_invalid,
1899 "write operation not allowed", goto error);
1902 file = fopen(tok->u.s, "w");
1903 isl_token_free(tok);
1904 if (!file)
1905 isl_die(s->ctx, isl_error_unknown,
1906 "could not open file for writing", goto error);
1908 p = isl_printer_to_file(s->ctx, file);
1909 p = isl_printer_set_output_format(p, options->format);
1910 p = obj.type->print(p, obj.v);
1911 p = isl_printer_end_line(p);
1912 isl_printer_free(p);
1914 fclose(file);
1915 error:
1916 free_obj(obj);
1917 obj.type = isl_obj_none;
1918 obj.v = NULL;
1919 return obj;
1922 static struct isl_obj read_string_if_available(struct isl_stream *s)
1924 struct isl_token *tok;
1925 struct isl_obj obj = { isl_obj_none, NULL };
1927 tok = isl_stream_next_token(s);
1928 if (!tok)
1929 return obj;
1930 if (tok->type == ISL_TOKEN_STRING) {
1931 isl_str *str;
1932 str = isl_str_alloc(s->ctx);
1933 if (!str)
1934 goto error;
1935 str->s = strdup(tok->u.s);
1936 isl_token_free(tok);
1937 obj.v = str;
1938 obj.type = isl_obj_str;
1939 } else
1940 isl_stream_push_token(s, tok);
1941 return obj;
1942 error:
1943 isl_token_free(tok);
1944 return obj;
1947 static struct isl_obj read_bool_if_available(struct isl_stream *s)
1949 struct isl_token *tok;
1950 struct isl_obj obj = { isl_obj_none, NULL };
1952 tok = isl_stream_next_token(s);
1953 if (!tok)
1954 return obj;
1955 if (tok->type == ISL_TOKEN_FALSE || tok->type == ISL_TOKEN_TRUE) {
1956 int is_true = tok->type == ISL_TOKEN_TRUE;
1957 isl_token_free(tok);
1958 obj.v = is_true ? &isl_bool_true : &isl_bool_false;
1959 obj.type = isl_obj_bool;
1960 } else
1961 isl_stream_push_token(s, tok);
1962 return obj;
1963 error:
1964 isl_token_free(tok);
1965 return obj;
1968 static __isl_give char *read_ident(struct isl_stream *s)
1970 char *name;
1971 struct isl_token *tok, *tok2;
1973 name = isl_stream_read_ident_if_available(s);
1974 if (name)
1975 return name;
1977 tok = isl_stream_next_token(s);
1978 if (!tok)
1979 return NULL;
1980 if (tok->type != '$') {
1981 isl_stream_push_token(s, tok);
1982 return NULL;
1984 tok2 = isl_stream_next_token(s);
1985 if (!tok2 || tok2->type != ISL_TOKEN_VALUE) {
1986 if (tok2)
1987 isl_stream_push_token(s, tok2);
1988 isl_stream_push_token(s, tok);
1989 return NULL;
1992 name = isl_int_get_str(tok2->u.v);
1993 isl_token_free(tok);
1994 isl_token_free(tok2);
1996 return name;
1999 static struct isl_obj read_list(struct isl_stream *s,
2000 struct isl_hash_table *table, struct isl_obj obj)
2002 struct isl_list *list;
2004 list = isl_list_alloc(s->ctx, 2);
2005 if (!list)
2006 goto error;
2007 list->obj[0] = obj;
2008 list->obj[1] = read_obj(s, table);
2009 obj.v = list;
2010 obj.type = isl_obj_list;
2012 if (!list->obj[1].v)
2013 goto error;
2015 while (isl_stream_eat_if_available(s, ',')) {
2016 obj.v = list = isl_list_add_obj(list, read_obj(s, table));
2017 if (!obj.v)
2018 goto error;
2021 return obj;
2022 error:
2023 free_obj(obj);
2024 obj.type = isl_obj_none;
2025 obj.v = NULL;
2026 return obj;
2029 static struct isl_obj read_obj(struct isl_stream *s,
2030 struct isl_hash_table *table)
2032 struct isl_obj obj = { isl_obj_none, NULL };
2033 char *name = NULL;
2034 struct isc_un_op *op = NULL;
2036 obj = read_string_if_available(s);
2037 if (obj.v)
2038 return obj;
2039 obj = read_bool_if_available(s);
2040 if (obj.v)
2041 return obj;
2042 if (isl_stream_eat_if_available(s, '(')) {
2043 if (isl_stream_next_token_is(s, ')')) {
2044 obj.type = isl_obj_list;
2045 obj.v = isl_list_alloc(s->ctx, 0);
2046 } else {
2047 obj = read_expr(s, table);
2048 if (obj.v && isl_stream_eat_if_available(s, ','))
2049 obj = read_list(s, table, obj);
2051 if (!obj.v || isl_stream_eat(s, ')'))
2052 goto error;
2053 } else {
2054 op = read_prefix_un_op_if_available(s);
2055 if (op)
2056 return read_un_op_expr(s, table, op);
2058 if (isl_stream_eat_if_available(s, iscc_op[ISCC_READ]))
2059 return read_from_file(s);
2060 if (isl_stream_eat_if_available(s, iscc_op[ISCC_WRITE]))
2061 return write_to_file(s, table);
2062 if (isl_stream_eat_if_available(s, iscc_op[ISCC_VERTICES]))
2063 return vertices(s, table);
2064 if (isl_stream_eat_if_available(s, iscc_op[ISCC_ANY]))
2065 return any(s, table);
2066 if (isl_stream_eat_if_available(s, iscc_op[ISCC_LAST]))
2067 return last(s, table);
2068 if (isl_stream_eat_if_available(s, iscc_op[ISCC_SCHEDULE]))
2069 return schedule(s, table);
2070 if (isl_stream_eat_if_available(s, iscc_op[ISCC_SCHEDULE_BANDS]))
2071 return schedule_bands(s, table);
2072 if (isl_stream_eat_if_available(s, iscc_op[ISCC_TYPEOF]))
2073 return type_of(s, table);
2075 name = read_ident(s);
2076 if (name)
2077 obj = stored_obj(s->ctx, table, name);
2078 else
2079 obj = isl_stream_read_obj(s);
2080 if (!obj.v)
2081 goto error;
2084 if (isl_stream_eat_if_available(s, '^'))
2085 obj = power(s, obj);
2086 else if (obj.type == isl_obj_list && isl_stream_eat_if_available(s, '['))
2087 obj = obj_at_index(s, obj);
2088 else if (is_subtype(obj, isl_obj_union_map) &&
2089 isl_stream_eat_if_available(s, '(')) {
2090 obj = convert(s->ctx, obj, isl_obj_union_map);
2091 obj = apply(s, obj.v, table);
2092 } else if (is_subtype(obj, isl_obj_union_pw_qpolynomial) &&
2093 isl_stream_eat_if_available(s, '(')) {
2094 obj = convert(s->ctx, obj, isl_obj_union_pw_qpolynomial);
2095 obj = apply_fun(s, obj, table);
2096 } else if (is_subtype(obj, isl_obj_union_pw_qpolynomial_fold) &&
2097 isl_stream_eat_if_available(s, '(')) {
2098 obj = convert(s->ctx, obj, isl_obj_union_pw_qpolynomial_fold);
2099 obj = apply_fun(s, obj, table);
2102 return obj;
2103 error:
2104 free_obj(obj);
2105 obj.type = isl_obj_none;
2106 obj.v = NULL;
2107 return obj;
2110 static struct isc_bin_op *find_matching_bin_op(struct isc_bin_op *like,
2111 struct isl_obj lhs, struct isl_obj rhs)
2113 int i;
2115 for (i = 0; ; ++i) {
2116 if (!bin_ops[i].op)
2117 break;
2118 if (bin_ops[i].op != like->op)
2119 continue;
2120 if (!is_subtype(lhs, bin_ops[i].lhs))
2121 continue;
2122 if (!is_subtype(rhs, bin_ops[i].rhs))
2123 continue;
2125 return &bin_ops[i];
2128 for (i = 0; ; ++i) {
2129 if (!named_bin_ops[i].name)
2130 break;
2131 if (named_bin_ops[i].op.op != like->op)
2132 continue;
2133 if (!is_subtype(lhs, named_bin_ops[i].op.lhs))
2134 continue;
2135 if (!is_subtype(rhs, named_bin_ops[i].op.rhs))
2136 continue;
2138 return &named_bin_ops[i].op;
2141 return NULL;
2144 static int next_is_neg_int(struct isl_stream *s)
2146 struct isl_token *tok;
2147 int ret;
2149 tok = isl_stream_next_token(s);
2150 ret = tok && tok->type == ISL_TOKEN_VALUE && isl_int_is_neg(tok->u.v);
2151 isl_stream_push_token(s, tok);
2153 return ret;
2156 static struct isl_obj read_expr(struct isl_stream *s,
2157 struct isl_hash_table *table)
2159 struct isl_obj obj = { isl_obj_none, NULL };
2160 struct isl_obj right_obj = { isl_obj_none, NULL };
2162 obj = read_obj(s, table);
2163 for (; obj.v;) {
2164 struct isc_bin_op *op = NULL;
2166 op = read_bin_op_if_available(s, obj);
2167 if (!op)
2168 break;
2170 right_obj = read_obj(s, table);
2172 op = find_matching_bin_op(op, obj, right_obj);
2174 if (!op)
2175 isl_die(s->ctx, isl_error_invalid,
2176 "no such binary operator defined on given operands",
2177 goto error);
2179 obj = convert(s->ctx, obj, op->lhs);
2180 right_obj = convert(s->ctx, right_obj, op->rhs);
2181 obj.v = op->fn(obj.v, right_obj.v);
2182 obj.type = op->res;
2185 if (obj.type == isl_obj_int && next_is_neg_int(s)) {
2186 right_obj = read_obj(s, table);
2187 obj.v = isl_int_obj_add(obj.v, right_obj.v);
2190 return obj;
2191 error:
2192 free_obj(right_obj);
2193 free_obj(obj);
2194 obj.type = isl_obj_none;
2195 obj.v = NULL;
2196 return obj;
2199 static __isl_give isl_printer *source_file(struct isl_stream *s,
2200 struct isl_hash_table *table, __isl_take isl_printer *p);
2202 static __isl_give isl_printer *read_line(struct isl_stream *s,
2203 struct isl_hash_table *table, __isl_take isl_printer *p, int tty)
2205 struct isl_obj obj = { isl_obj_none, NULL };
2206 char *lhs = NULL;
2207 int assign = 0;
2208 int only_print = 0;
2209 struct isc_bin_op *op = NULL;
2210 char buf[30];
2212 if (!p)
2213 return NULL;
2214 if (isl_stream_is_empty(s))
2215 return p;
2217 if (isl_stream_eat_if_available(s, iscc_op[ISCC_SOURCE]))
2218 return source_file(s, table, p);
2220 assign = is_assign(s);
2221 if (assign) {
2222 lhs = isl_stream_read_ident_if_available(s);
2223 if (isl_stream_eat(s, ISL_TOKEN_DEF))
2224 goto error;
2225 } else if (isl_stream_eat_if_available(s, iscc_op[ISCC_PRINT]))
2226 only_print = 1;
2227 else if (!tty)
2228 only_print = 1;
2230 obj = read_expr(s, table);
2231 if (isl_ctx_last_error(s->ctx) == isl_error_abort) {
2232 fprintf(stderr, "Interrupted\n");
2233 isl_ctx_reset_error(s->ctx);
2235 if (isl_stream_eat(s, ';'))
2236 goto error;
2238 if (only_print) {
2239 p = obj.type->print(p, obj.v);
2240 p = isl_printer_end_line(p);
2241 free_obj(obj);
2242 return p;
2244 if (!assign && obj.type != isl_obj_none && obj.v != NULL) {
2245 static int count = 0;
2246 snprintf(buf, sizeof(buf), "$%d", count++);
2247 lhs = strdup(buf + 1);
2249 p = isl_printer_print_str(p, buf);
2250 p = isl_printer_print_str(p, " := ");
2251 p = obj.type->print(p, obj.v);
2252 p = isl_printer_end_line(p);
2254 if (lhs && do_assign(s->ctx, table, lhs, obj))
2255 return p;
2257 return p;
2258 error:
2259 isl_stream_flush_tokens(s);
2260 isl_stream_skip_line(s);
2261 free(lhs);
2262 free_obj(obj);
2263 return p;
2266 int free_cb(void **entry, void *user)
2268 struct isl_named_obj *named = *entry;
2270 free_obj(named->obj);
2271 free(named->name);
2272 free(named);
2274 return 0;
2277 static void register_named_ops(struct isl_stream *s)
2279 int i;
2281 for (i = 0; i < ISCC_N_OP; ++i) {
2282 iscc_op[i] = isl_stream_register_keyword(s, op_name[i]);
2283 assert(iscc_op[i] != ISL_TOKEN_ERROR);
2286 for (i = 0; ; ++i) {
2287 if (!named_un_ops[i].name)
2288 break;
2289 named_un_ops[i].op.op = isl_stream_register_keyword(s,
2290 named_un_ops[i].name);
2291 assert(named_un_ops[i].op.op != ISL_TOKEN_ERROR);
2294 for (i = 0; ; ++i) {
2295 if (!named_bin_ops[i].name)
2296 break;
2297 named_bin_ops[i].op.op = isl_stream_register_keyword(s,
2298 named_bin_ops[i].name);
2299 assert(named_bin_ops[i].op.op != ISL_TOKEN_ERROR);
2303 static __isl_give isl_printer *source_file(struct isl_stream *s,
2304 struct isl_hash_table *table, __isl_take isl_printer *p)
2306 struct isl_token *tok;
2307 struct isl_stream *s_file;
2308 FILE *file;
2310 tok = isl_stream_next_token(s);
2311 if (!tok || tok->type != ISL_TOKEN_STRING) {
2312 isl_stream_error(s, tok, "expecting filename");
2313 isl_token_free(tok);
2314 return p;
2317 file = fopen(tok->u.s, "r");
2318 isl_token_free(tok);
2319 isl_assert(s->ctx, file, return p);
2321 s_file = isl_stream_new_file(s->ctx, file);
2322 if (!s_file) {
2323 fclose(file);
2324 return p;
2327 register_named_ops(s_file);
2329 while (!s_file->eof)
2330 p = read_line(s_file, table, p, 0);
2332 isl_stream_free(s_file);
2333 fclose(file);
2335 isl_stream_eat(s, ';');
2337 return p;
2340 int main(int argc, char **argv)
2342 struct isl_ctx *ctx;
2343 struct isl_stream *s;
2344 struct isl_hash_table *table;
2345 struct iscc_options *options;
2346 isl_printer *p;
2347 int tty = isatty(0);
2349 options = iscc_options_new_with_defaults();
2350 assert(options);
2351 argc = iscc_options_parse(options, argc, argv, ISL_ARG_ALL);
2353 ctx = isl_ctx_alloc_with_options(iscc_options_arg, options);
2354 s = isl_stream_new_file(ctx, stdin);
2355 assert(s);
2356 table = isl_hash_table_alloc(ctx, 10);
2357 assert(table);
2358 p = isl_printer_to_file(ctx, stdout);
2359 p = isl_printer_set_output_format(p, options->format);
2360 assert(p);
2362 register_named_ops(s);
2364 install_signal_handler(ctx);
2366 while (p && !s->eof) {
2367 isl_ctx_resume(ctx);
2368 p = read_line(s, table, p, tty);
2371 remove_signal_handler(ctx);
2373 isl_printer_free(p);
2374 isl_hash_table_foreach(ctx, table, free_cb, NULL);
2375 isl_hash_table_free(ctx, table);
2376 isl_stream_free(s);
2377 isl_ctx_free(ctx);
2379 return 0;