update isl for isl_div_get_ctx
[barvinok/uuh.git] / iscc.c
blob77200820d0ed9e994c430f1a9cce28c835d90407
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;
690 ud = cloog_union_domain_from_isl_union_map(isl_union_map_copy(umap));
692 dim = isl_union_map_get_dim(umap);
693 context = cloog_domain_from_isl_set(isl_set_universe(dim));
695 input = cloog_input_alloc(context, ud);
697 stmt = cloog_clast_create_from_input(input, options);
698 clast_pprint(stdout, stmt, 0, options);
699 cloog_clast_free(stmt);
701 error:
702 cloog_options_free(options);
703 cloog_state_free(state);
704 isl_union_map_free(umap);
705 return NULL;
708 void *set_codegen(void *arg)
710 isl_dim *dim;
711 isl_union_set *uset = (isl_union_set *)arg;
712 isl_ctx *ctx = isl_union_set_get_ctx(uset);
713 CloogState *state;
714 CloogOptions *options;
715 CloogDomain *context;
716 CloogUnionDomain *ud;
717 CloogInput *input;
718 struct clast_stmt *stmt;
720 if (isl_union_set_n_set(uset) > 1)
721 isl_die(ctx, isl_error_invalid,
722 "code generation for more than one domain "
723 "requires a schedule", goto error);
725 state = cloog_isl_state_malloc(ctx);
726 options = cloog_options_malloc(state);
727 options->language = LANGUAGE_C;
728 options->strides = 1;
730 ud = cloog_union_domain_from_isl_union_set(isl_union_set_copy(uset));
732 dim = isl_union_set_get_dim(uset);
733 context = cloog_domain_from_isl_set(isl_set_universe(dim));
735 input = cloog_input_alloc(context, ud);
737 stmt = cloog_clast_create_from_input(input, options);
738 clast_pprint(stdout, stmt, 0, options);
739 cloog_clast_free(stmt);
741 cloog_options_free(options);
742 cloog_state_free(state);
743 error:
744 isl_union_set_free(uset);
745 return NULL;
747 #endif
749 static int add_point(__isl_take isl_point *pnt, void *user)
751 isl_union_set **scan = (isl_union_set **) user;
753 *scan = isl_union_set_add_set(*scan, isl_set_from_point(pnt));
755 return 0;
758 static __isl_give isl_union_set *union_set_scan(__isl_take isl_union_set *uset)
760 isl_union_set *scan;
762 scan = isl_union_set_empty(isl_union_set_get_dim(uset));
764 if (isl_union_set_foreach_point(uset, add_point, &scan) < 0) {
765 isl_union_set_free(scan);
766 return uset;
769 isl_union_set_free(uset);
770 return scan;
773 static __isl_give isl_union_map *union_map_scan(__isl_take isl_union_map *umap)
775 return isl_union_set_unwrap(union_set_scan(isl_union_map_wrap(umap)));
778 static __isl_give isl_union_pw_qpolynomial *union_pw_qpolynomial_poly(
779 __isl_take isl_union_pw_qpolynomial *upwqp)
781 return isl_union_pw_qpolynomial_to_polynomial(upwqp, 0);
784 static __isl_give isl_union_pw_qpolynomial *union_pw_qpolynomial_lpoly(
785 __isl_take isl_union_pw_qpolynomial *upwqp)
787 return isl_union_pw_qpolynomial_to_polynomial(upwqp, -1);
790 static __isl_give isl_union_pw_qpolynomial *union_pw_qpolynomial_upoly(
791 __isl_take isl_union_pw_qpolynomial *upwqp)
793 return isl_union_pw_qpolynomial_to_polynomial(upwqp, 1);
796 typedef void *(*isc_un_op_fn)(void *arg);
797 struct isc_un_op {
798 enum isl_token_type op;
799 isl_obj_type arg;
800 isl_obj_type res;
801 isc_un_op_fn fn;
803 struct isc_named_un_op {
804 char *name;
805 struct isc_un_op op;
807 struct isc_named_un_op named_un_ops[] = {
808 {"aff", { -1, isl_obj_union_map, isl_obj_union_map,
809 (isc_un_op_fn) &isl_union_map_affine_hull } },
810 {"aff", { -1, isl_obj_union_set, isl_obj_union_set,
811 (isc_un_op_fn) &isl_union_set_affine_hull } },
812 {"card", { -1, isl_obj_union_set,
813 isl_obj_union_pw_qpolynomial,
814 (isc_un_op_fn) &isl_union_set_card } },
815 {"card", { -1, isl_obj_union_map,
816 isl_obj_union_pw_qpolynomial,
817 (isc_un_op_fn) &isl_union_map_card } },
818 {"coalesce", { -1, isl_obj_union_set, isl_obj_union_set,
819 (isc_un_op_fn) &isl_union_set_coalesce } },
820 {"coalesce", { -1, isl_obj_union_map, isl_obj_union_map,
821 (isc_un_op_fn) &isl_union_map_coalesce } },
822 {"coalesce", { -1, isl_obj_union_pw_qpolynomial,
823 isl_obj_union_pw_qpolynomial,
824 (isc_un_op_fn) &isl_union_pw_qpolynomial_coalesce } },
825 {"coalesce", { -1, isl_obj_union_pw_qpolynomial_fold,
826 isl_obj_union_pw_qpolynomial_fold,
827 (isc_un_op_fn) &isl_union_pw_qpolynomial_fold_coalesce } },
828 #ifdef HAVE_CLOOG
829 {"codegen", { -1, isl_obj_union_set, isl_obj_none,
830 &set_codegen } },
831 {"codegen", { -1, isl_obj_union_map, isl_obj_none,
832 &map_codegen } },
833 #endif
834 {"coefficients", { -1, isl_obj_union_set,
835 isl_obj_union_set,
836 (isc_un_op_fn) &isl_union_set_coefficients } },
837 {"solutions", { -1, isl_obj_union_set, isl_obj_union_set,
838 (isc_un_op_fn) &isl_union_set_solutions } },
839 {"deltas", { -1, isl_obj_union_map, isl_obj_union_set,
840 (isc_un_op_fn) &isl_union_map_deltas } },
841 {"deltas_map", { -1, isl_obj_union_map, isl_obj_union_map,
842 (isc_un_op_fn) &isl_union_map_deltas_map } },
843 {"dom", { -1, isl_obj_union_map, isl_obj_union_set,
844 (isc_un_op_fn) &isl_union_map_domain } },
845 {"dom", { -1, isl_obj_union_pw_qpolynomial, isl_obj_union_set,
846 (isc_un_op_fn) &isl_union_pw_qpolynomial_domain } },
847 {"dom", { -1, isl_obj_union_pw_qpolynomial_fold,
848 isl_obj_union_set,
849 (isc_un_op_fn) &isl_union_pw_qpolynomial_fold_domain } },
850 {"domain", { -1, isl_obj_union_map, isl_obj_union_set,
851 (isc_un_op_fn) &isl_union_map_domain } },
852 {"domain", { -1, isl_obj_union_pw_qpolynomial,
853 isl_obj_union_set,
854 (isc_un_op_fn) &isl_union_pw_qpolynomial_domain } },
855 {"domain", { -1, isl_obj_union_pw_qpolynomial_fold,
856 isl_obj_union_set,
857 (isc_un_op_fn) &isl_union_pw_qpolynomial_fold_domain } },
858 {"domain_map", { -1, isl_obj_union_map, isl_obj_union_map,
859 (isc_un_op_fn) &isl_union_map_domain_map } },
860 {"ran", { -1, isl_obj_union_map, isl_obj_union_set,
861 (isc_un_op_fn) &isl_union_map_range } },
862 {"range", { -1, isl_obj_union_map, isl_obj_union_set,
863 (isc_un_op_fn) &isl_union_map_range } },
864 {"range_map", { -1, isl_obj_union_map, isl_obj_union_map,
865 (isc_un_op_fn) &isl_union_map_range_map } },
866 {"identity", { -1, isl_obj_union_set, isl_obj_union_map,
867 (isc_un_op_fn) &isl_union_set_identity } },
868 {"lexmin", { -1, isl_obj_union_map, isl_obj_union_map,
869 (isc_un_op_fn) &isl_union_map_lexmin } },
870 {"lexmax", { -1, isl_obj_union_map, isl_obj_union_map,
871 (isc_un_op_fn) &isl_union_map_lexmax } },
872 {"lexmin", { -1, isl_obj_union_set, isl_obj_union_set,
873 (isc_un_op_fn) &isl_union_set_lexmin } },
874 {"lexmax", { -1, isl_obj_union_set, isl_obj_union_set,
875 (isc_un_op_fn) &isl_union_set_lexmax } },
876 {"lift", { -1, isl_obj_union_set, isl_obj_union_set,
877 (isc_un_op_fn) &isl_union_set_lift } },
878 {"poly", { -1, isl_obj_union_map, isl_obj_union_map,
879 (isc_un_op_fn) &isl_union_map_polyhedral_hull } },
880 {"poly", { -1, isl_obj_union_set, isl_obj_union_set,
881 (isc_un_op_fn) &isl_union_set_polyhedral_hull } },
882 {"poly", { -1, isl_obj_union_pw_qpolynomial,
883 isl_obj_union_pw_qpolynomial,
884 (isc_un_op_fn) &union_pw_qpolynomial_poly } },
885 {"lpoly", { -1, isl_obj_union_pw_qpolynomial,
886 isl_obj_union_pw_qpolynomial,
887 (isc_un_op_fn) &union_pw_qpolynomial_lpoly } },
888 {"upoly", { -1, isl_obj_union_pw_qpolynomial,
889 isl_obj_union_pw_qpolynomial,
890 (isc_un_op_fn) &union_pw_qpolynomial_upoly } },
891 {"pow", { -1, isl_obj_union_map, isl_obj_list,
892 (isc_un_op_fn) &union_map_power } },
893 {"sample", { -1, isl_obj_union_set, isl_obj_set,
894 (isc_un_op_fn) &union_set_sample } },
895 {"sample", { -1, isl_obj_union_map, isl_obj_map,
896 (isc_un_op_fn) &union_map_sample } },
897 {"scan", { -1, isl_obj_union_set, isl_obj_union_set,
898 (isc_un_op_fn) &union_set_scan } },
899 {"scan", { -1, isl_obj_union_map, isl_obj_union_map,
900 (isc_un_op_fn) &union_map_scan } },
901 {"sum", { -1, isl_obj_union_pw_qpolynomial,
902 isl_obj_union_pw_qpolynomial,
903 (isc_un_op_fn) &isl_union_pw_qpolynomial_sum } },
904 {"ub", { -1, isl_obj_union_pw_qpolynomial, isl_obj_list,
905 (isc_un_op_fn) &union_pw_qpolynomial_upper_bound } },
906 {"unwrap", { -1, isl_obj_union_set, isl_obj_union_map,
907 (isc_un_op_fn) &isl_union_set_unwrap } },
908 {"wrap", { -1, isl_obj_union_map, isl_obj_union_set,
909 (isc_un_op_fn) &isl_union_map_wrap } },
910 {"zip", { -1, isl_obj_union_map, isl_obj_union_map,
911 (isc_un_op_fn) &isl_union_map_zip } },
912 NULL
915 struct isl_named_obj {
916 char *name;
917 struct isl_obj obj;
920 static void free_obj(struct isl_obj obj)
922 obj.type->free(obj.v);
925 static int same_name(const void *entry, const void *val)
927 const struct isl_named_obj *named = (const struct isl_named_obj *)entry;
929 return !strcmp(named->name, val);
932 static int do_assign(struct isl_ctx *ctx, struct isl_hash_table *table,
933 char *name, struct isl_obj obj)
935 struct isl_hash_table_entry *entry;
936 uint32_t name_hash;
937 struct isl_named_obj *named;
939 name_hash = isl_hash_string(isl_hash_init(), name);
940 entry = isl_hash_table_find(ctx, table, name_hash, same_name, name, 1);
941 if (!entry)
942 goto error;
943 if (entry->data) {
944 named = entry->data;
945 free_obj(named->obj);
946 free(name);
947 } else {
948 named = isl_alloc_type(ctx, struct isl_named_obj);
949 if (!named)
950 goto error;
951 named->name = name;
952 entry->data = named;
954 named->obj = obj;
956 return 0;
957 error:
958 free_obj(obj);
959 free(name);
960 return -1;
963 static struct isl_obj stored_obj(struct isl_ctx *ctx,
964 struct isl_hash_table *table, char *name)
966 struct isl_obj obj = { isl_obj_none, NULL };
967 struct isl_hash_table_entry *entry;
968 uint32_t name_hash;
970 name_hash = isl_hash_string(isl_hash_init(), name);
971 entry = isl_hash_table_find(ctx, table, name_hash, same_name, name, 0);
972 if (entry) {
973 struct isl_named_obj *named;
974 named = entry->data;
975 obj = named->obj;
976 } else if (isdigit(name[0]))
977 fprintf(stderr, "unknown identifier '$%s'\n", name);
978 else
979 fprintf(stderr, "unknown identifier '%s'\n", name);
981 free(name);
982 obj.v = obj.type->copy(obj.v);
983 return obj;
986 static int is_subtype(struct isl_obj obj, isl_obj_type super)
988 if (obj.type == super)
989 return 1;
990 if (obj.type == isl_obj_map && super == isl_obj_union_map)
991 return 1;
992 if (obj.type == isl_obj_set && super == isl_obj_union_set)
993 return 1;
994 if (obj.type == isl_obj_pw_qpolynomial &&
995 super == isl_obj_union_pw_qpolynomial)
996 return 1;
997 if (obj.type == isl_obj_pw_qpolynomial_fold &&
998 super == isl_obj_union_pw_qpolynomial_fold)
999 return 1;
1000 if (obj.type == isl_obj_union_set && isl_union_set_is_empty(obj.v))
1001 return 1;
1002 if (obj.type == isl_obj_list) {
1003 struct isl_list *list = obj.v;
1004 if (list->n == 2 && list->obj[1].type == isl_obj_bool)
1005 return is_subtype(list->obj[0], super);
1007 if (super == isl_obj_str)
1008 return 1;
1009 return 0;
1012 static struct isl_obj obj_at(struct isl_obj obj, int i)
1014 struct isl_list *list = obj.v;
1016 obj = list->obj[i];
1017 obj.v = obj.type->copy(obj.v);
1019 isl_list_free(list);
1021 return obj;
1024 static struct isl_obj convert(isl_ctx *ctx, struct isl_obj obj,
1025 isl_obj_type type)
1027 if (obj.type == type)
1028 return obj;
1029 if (obj.type == isl_obj_map && type == isl_obj_union_map) {
1030 obj.type = isl_obj_union_map;
1031 obj.v = isl_union_map_from_map(obj.v);
1032 return obj;
1034 if (obj.type == isl_obj_set && type == isl_obj_union_set) {
1035 obj.type = isl_obj_union_set;
1036 obj.v = isl_union_set_from_set(obj.v);
1037 return obj;
1039 if (obj.type == isl_obj_pw_qpolynomial &&
1040 type == isl_obj_union_pw_qpolynomial) {
1041 obj.type = isl_obj_union_pw_qpolynomial;
1042 obj.v = isl_union_pw_qpolynomial_from_pw_qpolynomial(obj.v);
1043 return obj;
1045 if (obj.type == isl_obj_pw_qpolynomial_fold &&
1046 type == isl_obj_union_pw_qpolynomial_fold) {
1047 obj.type = isl_obj_union_pw_qpolynomial_fold;
1048 obj.v = isl_union_pw_qpolynomial_fold_from_pw_qpolynomial_fold(obj.v);
1049 return obj;
1051 if (obj.type == isl_obj_union_set && isl_union_set_is_empty(obj.v)) {
1052 if (type == isl_obj_union_map) {
1053 obj.type = isl_obj_union_map;
1054 return obj;
1056 if (type == isl_obj_union_pw_qpolynomial) {
1057 isl_dim *dim = isl_union_set_get_dim(obj.v);
1058 isl_union_set_free(obj.v);
1059 obj.v = isl_union_pw_qpolynomial_zero(dim);
1060 obj.type = isl_obj_union_pw_qpolynomial;
1061 return obj;
1063 if (type == isl_obj_union_pw_qpolynomial_fold) {
1064 isl_dim *dim = isl_union_set_get_dim(obj.v);
1065 isl_union_set_free(obj.v);
1066 obj.v = isl_union_pw_qpolynomial_fold_zero(dim,
1067 isl_fold_list);
1068 obj.type = isl_obj_union_pw_qpolynomial_fold;
1069 return obj;
1072 if (obj.type == isl_obj_list) {
1073 struct isl_list *list = obj.v;
1074 if (list->n == 2 && list->obj[1].type == isl_obj_bool)
1075 return convert(ctx, obj_at(obj, 0), type);
1077 if (type == isl_obj_str) {
1078 isl_str *str;
1079 isl_printer *p;
1080 char *s;
1082 p = isl_printer_to_str(ctx);
1083 if (!p)
1084 goto error;
1085 p = obj.type->print(p, obj.v);
1086 s = isl_printer_get_str(p);
1087 isl_printer_free(p);
1089 str = isl_str_from_string(ctx, s);
1090 if (!str)
1091 goto error;
1092 free_obj(obj);
1093 obj.v = str;
1094 obj.type = isl_obj_str;
1095 return obj;
1098 error:
1099 free_obj(obj);
1100 obj.type = isl_obj_none;
1101 obj.v = NULL;
1102 return obj;
1105 static struct isc_bin_op *read_bin_op_if_available(struct isl_stream *s,
1106 struct isl_obj lhs)
1108 int i;
1109 struct isl_token *tok;
1111 tok = isl_stream_next_token(s);
1112 if (!tok)
1113 return NULL;
1115 for (i = 0; ; ++i) {
1116 if (!bin_ops[i].op)
1117 break;
1118 if (bin_ops[i].op != tok->type)
1119 continue;
1120 if (!is_subtype(lhs, bin_ops[i].lhs))
1121 continue;
1123 isl_token_free(tok);
1124 return &bin_ops[i];
1127 for (i = 0; ; ++i) {
1128 if (!named_bin_ops[i].name)
1129 break;
1130 if (named_bin_ops[i].op.op != tok->type)
1131 continue;
1132 if (!is_subtype(lhs, named_bin_ops[i].op.lhs))
1133 continue;
1135 isl_token_free(tok);
1136 return &named_bin_ops[i].op;
1139 isl_stream_push_token(s, tok);
1141 return NULL;
1144 static struct isc_un_op *read_prefix_un_op_if_available(struct isl_stream *s)
1146 int i;
1147 struct isl_token *tok;
1149 tok = isl_stream_next_token(s);
1150 if (!tok)
1151 return NULL;
1153 for (i = 0; ; ++i) {
1154 if (!named_un_ops[i].name)
1155 break;
1156 if (named_un_ops[i].op.op != tok->type)
1157 continue;
1159 isl_token_free(tok);
1160 return &named_un_ops[i].op;
1163 isl_stream_push_token(s, tok);
1165 return NULL;
1168 static struct isc_un_op *find_matching_un_op(struct isc_un_op *like,
1169 struct isl_obj arg)
1171 int i;
1173 for (i = 0; ; ++i) {
1174 if (!named_un_ops[i].name)
1175 break;
1176 if (named_un_ops[i].op.op != like->op)
1177 continue;
1178 if (!is_subtype(arg, named_un_ops[i].op.arg))
1179 continue;
1181 return &named_un_ops[i].op;
1184 return NULL;
1187 static int is_assign(struct isl_stream *s)
1189 struct isl_token *tok;
1190 struct isl_token *tok2;
1191 int assign;
1193 tok = isl_stream_next_token(s);
1194 if (!tok)
1195 return 0;
1196 if (tok->type != ISL_TOKEN_IDENT) {
1197 isl_stream_push_token(s, tok);
1198 return 0;
1201 tok2 = isl_stream_next_token(s);
1202 if (!tok2) {
1203 isl_stream_push_token(s, tok);
1204 return 0;
1206 assign = tok2->type == ISL_TOKEN_DEF;
1207 isl_stream_push_token(s, tok2);
1208 isl_stream_push_token(s, tok);
1210 return assign;
1213 static struct isl_obj read_obj(struct isl_stream *s,
1214 struct isl_hash_table *table);
1215 static struct isl_obj read_expr(struct isl_stream *s,
1216 struct isl_hash_table *table);
1218 static struct isl_obj read_un_op_expr(struct isl_stream *s,
1219 struct isl_hash_table *table, struct isc_un_op *op)
1221 struct isl_obj obj = { isl_obj_none, NULL };
1223 obj = read_obj(s, table);
1224 if (!obj.v)
1225 goto error;
1227 op = find_matching_un_op(op, obj);
1229 if (!op)
1230 isl_die(s->ctx, isl_error_invalid,
1231 "no such unary operator defined on given operand",
1232 goto error);
1234 obj = convert(s->ctx, obj, op->arg);
1235 obj.v = op->fn(obj.v);
1236 obj.type = op->res;
1238 return obj;
1239 error:
1240 free_obj(obj);
1241 obj.type = isl_obj_none;
1242 obj.v = NULL;
1243 return obj;
1246 static struct isl_obj transitive_closure(struct isl_ctx *ctx, struct isl_obj obj)
1248 struct isl_list *list;
1249 int exact;
1251 if (obj.type != isl_obj_union_map)
1252 obj = convert(ctx, obj, isl_obj_union_map);
1253 isl_assert(ctx, obj.type == isl_obj_union_map, goto error);
1254 list = isl_list_alloc(ctx, 2);
1255 if (!list)
1256 goto error;
1258 list->obj[0].type = isl_obj_union_map;
1259 list->obj[0].v = isl_union_map_transitive_closure(obj.v, &exact);
1260 list->obj[1].type = isl_obj_bool;
1261 list->obj[1].v = exact ? &isl_bool_true : &isl_bool_false;
1262 obj.v = list;
1263 obj.type = isl_obj_list;
1264 if (exact < 0 || !list->obj[0].v)
1265 goto error;
1267 return obj;
1268 error:
1269 free_obj(obj);
1270 obj.type = isl_obj_none;
1271 obj.v = NULL;
1272 return obj;
1275 static struct isl_obj obj_at_index(struct isl_stream *s, struct isl_obj obj)
1277 struct isl_list *list = obj.v;
1278 struct isl_token *tok;
1279 int i;
1281 tok = isl_stream_next_token(s);
1282 if (!tok || tok->type != ISL_TOKEN_VALUE) {
1283 isl_stream_error(s, tok, "expecting index");
1284 if (tok)
1285 isl_stream_push_token(s, tok);
1286 goto error;
1288 i = isl_int_get_si(tok->u.v);
1289 isl_token_free(tok);
1290 isl_assert(s->ctx, i < list->n, goto error);
1291 if (isl_stream_eat(s, ']'))
1292 goto error;
1294 return obj_at(obj, i);
1295 error:
1296 free_obj(obj);
1297 obj.type = isl_obj_none;
1298 obj.v = NULL;
1299 return obj;
1302 static struct isl_obj apply(struct isl_stream *s, __isl_take isl_union_map *umap,
1303 struct isl_hash_table *table)
1305 struct isl_obj obj;
1307 obj = read_expr(s, table);
1308 isl_assert(s->ctx, is_subtype(obj, isl_obj_union_set) ||
1309 is_subtype(obj, isl_obj_union_map), goto error);
1311 if (obj.type == isl_obj_list) {
1312 struct isl_list *list = obj.v;
1313 if (list->n == 2 && list->obj[1].type == isl_obj_bool)
1314 obj = obj_at(obj, 0);
1316 if (obj.type == isl_obj_set)
1317 obj = convert(s->ctx, obj, isl_obj_union_set);
1318 else if (obj.type == isl_obj_map)
1319 obj = convert(s->ctx, obj, isl_obj_union_map);
1320 if (obj.type == isl_obj_union_set) {
1321 obj.v = isl_union_set_apply(obj.v, umap);
1322 } else
1323 obj.v = isl_union_map_apply_range(obj.v, umap);
1324 if (!obj.v)
1325 goto error2;
1327 if (isl_stream_eat(s, ')'))
1328 goto error2;
1330 return obj;
1331 error:
1332 isl_union_map_free(umap);
1333 error2:
1334 free_obj(obj);
1335 obj.type = isl_obj_none;
1336 obj.v = NULL;
1337 return obj;
1340 static struct isl_obj apply_fun(struct isl_stream *s,
1341 struct isl_obj obj, struct isl_hash_table *table)
1343 struct isl_obj arg;
1345 arg = read_expr(s, table);
1346 if (!is_subtype(arg, isl_obj_union_map) &&
1347 !is_subtype(arg, isl_obj_union_set))
1348 isl_die(s->ctx, isl_error_invalid,
1349 "expecting set of map argument", goto error);
1351 if (arg.type == isl_obj_list) {
1352 struct isl_list *list = arg.v;
1353 if (list->n == 2 && list->obj[1].type == isl_obj_bool)
1354 arg = obj_at(arg, 0);
1356 if (arg.type == isl_obj_set)
1357 arg = convert(s->ctx, arg, isl_obj_union_set);
1358 else if (arg.type == isl_obj_map)
1359 arg = convert(s->ctx, arg, isl_obj_union_map);
1360 if (arg.type == isl_obj_union_set) {
1361 arg.v = isl_union_map_from_range(arg.v);
1362 arg.type = isl_obj_union_map;
1364 if (obj.type == isl_obj_union_pw_qpolynomial) {
1365 obj.v = isl_union_map_apply_union_pw_qpolynomial(arg.v, obj.v);
1366 } else {
1367 obj.type = isl_obj_list;
1368 obj.v = union_map_apply_union_pw_qpolynomial_fold(arg.v, obj.v);
1370 if (!obj.v)
1371 goto error2;
1373 if (isl_stream_eat(s, ')'))
1374 goto error2;
1376 return obj;
1377 error:
1378 free_obj(arg);
1379 error2:
1380 free_obj(obj);
1381 obj.type = isl_obj_none;
1382 obj.v = NULL;
1383 return obj;
1386 struct add_vertex_data {
1387 struct isl_list *list;
1388 int i;
1391 static int add_vertex(__isl_take isl_vertex *vertex, void *user)
1393 struct add_vertex_data *data = (struct add_vertex_data *)user;
1394 isl_basic_set *expr;
1396 expr = isl_vertex_get_expr(vertex);
1398 data->list->obj[data->i].type = isl_obj_set;
1399 data->list->obj[data->i].v = isl_set_from_basic_set(expr);
1400 data->i++;
1402 isl_vertex_free(vertex);
1404 return 0;
1407 static int set_vertices(__isl_take isl_set *set, void *user)
1409 isl_ctx *ctx;
1410 isl_basic_set *hull;
1411 isl_vertices *vertices = NULL;
1412 struct isl_list *list = NULL;
1413 int r;
1414 struct add_vertex_data *data = (struct add_vertex_data *)user;
1416 set = isl_set_remove_divs(set);
1417 hull = isl_set_convex_hull(set);
1418 vertices = isl_basic_set_compute_vertices(hull);
1419 isl_basic_set_free(hull);
1421 list = data->list;
1423 ctx = isl_vertices_get_ctx(vertices);
1424 data->list = isl_list_alloc(ctx, isl_vertices_get_n_vertices(vertices));
1425 if (!data->list)
1426 goto error;
1428 data->i = 0;
1429 r = isl_vertices_foreach_vertex(vertices, &add_vertex, user);
1431 data->list = isl_list_concat(list, data->list);
1433 isl_vertices_free(vertices);
1435 return r;
1436 error:
1437 data->list = list;
1438 isl_vertices_free(vertices);
1439 return -1;
1442 static struct isl_obj vertices(struct isl_stream *s,
1443 struct isl_hash_table *table)
1445 isl_ctx *ctx;
1446 struct isl_obj obj;
1447 struct isl_list *list = NULL;
1448 isl_union_set *uset;
1449 struct add_vertex_data data = { NULL };
1451 obj = read_expr(s, table);
1452 obj = convert(s->ctx, obj, isl_obj_union_set);
1453 isl_assert(s->ctx, obj.type == isl_obj_union_set, goto error);
1454 uset = obj.v;
1455 obj.v = NULL;
1457 ctx = isl_union_set_get_ctx(uset);
1458 list = isl_list_alloc(ctx, 0);
1459 if (!list)
1460 goto error;
1462 data.list = list;
1464 if (isl_union_set_foreach_set(uset, &set_vertices, &data) < 0)
1465 goto error;
1467 isl_union_set_free(uset);
1469 obj.type = isl_obj_list;
1470 obj.v = data.list;
1472 return obj;
1473 error:
1474 isl_union_set_free(uset);
1475 isl_list_free(data.list);
1476 free_obj(obj);
1477 obj.type = isl_obj_none;
1478 obj.v = NULL;
1479 return obj;
1482 static struct isl_obj type_of(struct isl_stream *s,
1483 struct isl_hash_table *table)
1485 isl_ctx *ctx;
1486 struct isl_obj obj;
1487 const char *type = "unknown";
1489 obj = read_expr(s, table);
1491 if (obj.type == isl_obj_map ||
1492 obj.type == isl_obj_union_map)
1493 type = "map";
1494 if (obj.type == isl_obj_set ||
1495 obj.type == isl_obj_union_set)
1496 type = "set";
1497 if (obj.type == isl_obj_pw_qpolynomial ||
1498 obj.type == isl_obj_union_pw_qpolynomial)
1499 type = "piecewise quasipolynomial";
1500 if (obj.type == isl_obj_pw_qpolynomial_fold ||
1501 obj.type == isl_obj_union_pw_qpolynomial_fold)
1502 type = "piecewise quasipolynomial fold";
1503 if (obj.type == isl_obj_list)
1504 type = "list";
1505 if (obj.type == isl_obj_bool)
1506 type = "boolean";
1507 if (obj.type == isl_obj_str)
1508 type = "string";
1509 if (obj.type == isl_obj_int)
1510 type = "int";
1512 free_obj(obj);
1513 obj.type = isl_obj_str;
1514 obj.v = isl_str_from_string(s->ctx, strdup(type));
1516 return obj;
1519 static __isl_give isl_union_set *read_set(struct isl_stream *s,
1520 struct isl_hash_table *table)
1522 struct isl_obj obj;
1524 obj = read_obj(s, table);
1525 obj = convert(s->ctx, obj, isl_obj_union_set);
1526 isl_assert(s->ctx, obj.type == isl_obj_union_set, goto error);
1527 return obj.v;
1528 error:
1529 free_obj(obj);
1530 return NULL;
1533 static __isl_give isl_union_map *read_map(struct isl_stream *s,
1534 struct isl_hash_table *table)
1536 struct isl_obj obj;
1538 obj = read_obj(s, table);
1539 obj = convert(s->ctx, obj, isl_obj_union_map);
1540 isl_assert(s->ctx, obj.type == isl_obj_union_map, goto error);
1541 return obj.v;
1542 error:
1543 free_obj(obj);
1544 return NULL;
1547 static struct isl_obj last_any(struct isl_stream *s,
1548 struct isl_hash_table *table, __isl_take isl_union_map *must_source,
1549 __isl_take isl_union_map *may_source)
1551 struct isl_obj obj = { isl_obj_none, NULL };
1552 isl_union_map *sink = NULL;
1553 isl_union_map *schedule = NULL;
1554 isl_union_map *may_dep;
1555 isl_union_map *must_dep;
1557 if (isl_stream_eat(s, iscc_op[ISCC_BEFORE]))
1558 goto error;
1560 sink = read_map(s, table);
1561 if (!sink)
1562 goto error;
1564 if (isl_stream_eat(s, iscc_op[ISCC_UNDER]))
1565 goto error;
1567 schedule = read_map(s, table);
1568 if (!schedule)
1569 goto error;
1571 if (isl_union_map_compute_flow(sink, must_source, may_source,
1572 schedule, &must_dep, &may_dep,
1573 NULL, NULL) < 0)
1574 return obj;
1576 obj.type = isl_obj_union_map;
1577 obj.v = isl_union_map_union(must_dep, may_dep);
1579 return obj;
1580 error:
1581 isl_union_map_free(may_source);
1582 isl_union_map_free(must_source);
1583 isl_union_map_free(sink);
1584 isl_union_map_free(schedule);
1585 free_obj(obj);
1586 obj.type = isl_obj_none;
1587 obj.v = NULL;
1588 return obj;
1591 static struct isl_obj any(struct isl_stream *s, struct isl_hash_table *table)
1593 struct isl_obj obj = { isl_obj_none, NULL };
1594 isl_union_map *must_source = NULL;
1595 isl_union_map *may_source = NULL;
1596 isl_union_map *sink = NULL;
1597 isl_union_map *schedule = NULL;
1598 isl_union_map *may_dep;
1600 may_source = read_map(s, table);
1601 if (!may_source)
1602 goto error;
1604 if (isl_stream_eat_if_available(s, iscc_op[ISCC_LAST])) {
1605 must_source = read_map(s, table);
1606 if (!must_source)
1607 goto error;
1608 return last_any(s, table, must_source, may_source);
1611 if (isl_stream_eat(s, iscc_op[ISCC_BEFORE]))
1612 goto error;
1614 sink = read_map(s, table);
1615 if (!sink)
1616 goto error;
1618 if (isl_stream_eat(s, iscc_op[ISCC_UNDER]))
1619 goto error;
1621 schedule = read_map(s, table);
1622 if (!schedule)
1623 goto error;
1625 must_source = isl_union_map_empty(isl_union_map_get_dim(sink));
1626 if (isl_union_map_compute_flow(sink, must_source, may_source,
1627 schedule, NULL, &may_dep,
1628 NULL, NULL) < 0)
1629 return obj;
1631 obj.type = isl_obj_union_map;
1632 obj.v = may_dep;
1634 return obj;
1635 error:
1636 isl_union_map_free(may_source);
1637 isl_union_map_free(must_source);
1638 isl_union_map_free(sink);
1639 isl_union_map_free(schedule);
1640 free_obj(obj);
1641 obj.type = isl_obj_none;
1642 obj.v = NULL;
1643 return obj;
1646 static struct isl_obj last(struct isl_stream *s, struct isl_hash_table *table)
1648 struct isl_obj obj = { isl_obj_none, NULL };
1649 struct isl_list *list = NULL;
1650 isl_union_map *must_source = NULL;
1651 isl_union_map *may_source = NULL;
1652 isl_union_map *sink = NULL;
1653 isl_union_map *schedule = NULL;
1654 isl_union_map *must_dep;
1655 isl_union_map *must_no_source;
1657 must_source = read_map(s, table);
1658 if (!must_source)
1659 goto error;
1661 if (isl_stream_eat_if_available(s, iscc_op[ISCC_ANY])) {
1662 may_source = read_map(s, table);
1663 if (!may_source)
1664 goto error;
1665 return last_any(s, table, must_source, may_source);
1668 list = isl_list_alloc(s->ctx, 2);
1669 if (!list)
1670 goto error;
1672 if (isl_stream_eat(s, iscc_op[ISCC_BEFORE]))
1673 goto error;
1675 sink = read_map(s, table);
1676 if (!sink)
1677 goto error;
1679 if (isl_stream_eat(s, iscc_op[ISCC_UNDER]))
1680 goto error;
1682 schedule = read_map(s, table);
1683 if (!schedule)
1684 goto error;
1686 may_source = isl_union_map_empty(isl_union_map_get_dim(sink));
1687 if (isl_union_map_compute_flow(sink, must_source, may_source,
1688 schedule, &must_dep, NULL,
1689 &must_no_source, NULL) < 0) {
1690 isl_list_free(list);
1691 return obj;
1694 list->obj[0].type = isl_obj_union_map;
1695 list->obj[0].v = must_dep;
1696 list->obj[1].type = isl_obj_union_map;
1697 list->obj[1].v = must_no_source;
1699 obj.v = list;
1700 obj.type = isl_obj_list;
1702 return obj;
1703 error:
1704 isl_list_free(list);
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 __isl_give isl_schedule *get_schedule(struct isl_stream *s,
1716 struct isl_hash_table *table)
1718 isl_union_set *domain;
1719 isl_union_map *validity;
1720 isl_union_map *proximity;
1722 domain = read_set(s, table);
1723 if (!domain)
1724 return NULL;
1726 validity = isl_union_map_empty(isl_union_set_get_dim(domain));
1727 proximity = isl_union_map_empty(isl_union_set_get_dim(domain));
1729 for (;;) {
1730 isl_union_map *umap;
1731 if (isl_stream_eat_if_available(s, iscc_op[ISCC_RESPECTING])) {
1732 umap = read_map(s, table);
1733 validity = isl_union_map_union(validity, umap);
1734 } else if (isl_stream_eat_if_available(s, iscc_op[ISCC_MINIMIZING])) {
1735 umap = read_map(s, table);
1736 proximity = isl_union_map_union(proximity, umap);
1737 } else
1738 break;
1741 return isl_union_set_compute_schedule(domain, validity, proximity);
1744 static struct isl_obj schedule(struct isl_stream *s,
1745 struct isl_hash_table *table)
1747 struct isl_obj obj = { isl_obj_none, NULL };
1748 isl_schedule *schedule;
1750 schedule = get_schedule(s, table);
1752 obj.v = isl_schedule_get_map(schedule);
1753 obj.type = isl_obj_union_map;
1755 isl_schedule_free(schedule);
1757 return obj;
1760 static struct isl_obj schedule_bands(struct isl_stream *s,
1761 struct isl_hash_table *table)
1763 int i;
1764 int n_band;
1765 struct isl_obj obj = { isl_obj_none, NULL };
1766 struct isl_list *list;
1767 isl_schedule *schedule;
1769 schedule = get_schedule(s, table);
1770 if (!schedule)
1771 return obj;
1773 n_band = isl_schedule_n_band(schedule);
1774 list = isl_list_alloc(s->ctx, n_band);
1775 if (!list)
1776 goto error;
1778 obj.v = list;
1779 obj.type = isl_obj_list;
1781 for (i = 0; i < n_band; ++i) {
1782 list->obj[i].type = isl_obj_union_map;
1783 list->obj[i].v = isl_schedule_get_band(schedule, i);
1784 if (!list->obj[i].v)
1785 goto error;
1788 isl_schedule_free(schedule);
1790 return obj;
1791 error:
1792 isl_schedule_free(schedule);
1793 free_obj(obj);
1794 obj.type = isl_obj_none;
1795 obj.v = NULL;
1796 return obj;
1799 static struct isl_obj power(struct isl_stream *s, struct isl_obj obj)
1801 struct isl_token *tok;
1803 if (isl_stream_eat_if_available(s, '+'))
1804 return transitive_closure(s->ctx, obj);
1806 tok = isl_stream_next_token(s);
1807 if (!tok || tok->type != ISL_TOKEN_VALUE || isl_int_cmp_si(tok->u.v, -1)) {
1808 isl_stream_error(s, tok, "expecting -1");
1809 if (tok)
1810 isl_stream_push_token(s, tok);
1811 goto error;
1813 isl_token_free(tok);
1814 isl_assert(s->ctx, is_subtype(obj, isl_obj_union_map), goto error);
1815 if (obj.type != isl_obj_union_map)
1816 obj = convert(s->ctx, obj, isl_obj_union_map);
1818 obj.v = isl_union_map_reverse(obj.v);
1819 if (!obj.v)
1820 goto error;
1822 return obj;
1823 error:
1824 free_obj(obj);
1825 obj.type = isl_obj_none;
1826 obj.v = NULL;
1827 return obj;
1830 static struct isl_obj read_from_file(struct isl_stream *s)
1832 struct isl_obj obj;
1833 struct isl_token *tok;
1834 struct isl_stream *s_file;
1835 struct iscc_options *options;
1836 FILE *file;
1838 tok = isl_stream_next_token(s);
1839 if (!tok || tok->type != ISL_TOKEN_STRING) {
1840 isl_stream_error(s, tok, "expecting filename");
1841 isl_token_free(tok);
1842 goto error;
1845 options = isl_ctx_peek_iscc_options(s->ctx);
1846 if (!options || !options->io) {
1847 isl_token_free(tok);
1848 isl_die(s->ctx, isl_error_invalid,
1849 "read operation not allowed", goto error);
1852 file = fopen(tok->u.s, "r");
1853 isl_token_free(tok);
1854 isl_assert(s->ctx, file, goto error);
1856 s_file = isl_stream_new_file(s->ctx, file);
1857 if (!s_file) {
1858 fclose(file);
1859 goto error;
1862 obj = isl_stream_read_obj(s_file);
1864 isl_stream_free(s_file);
1865 fclose(file);
1867 return obj;
1868 error:
1869 obj.type = isl_obj_none;
1870 obj.v = NULL;
1871 return obj;
1874 static struct isl_obj write_to_file(struct isl_stream *s,
1875 struct isl_hash_table *table)
1877 struct isl_obj obj;
1878 struct isl_token *tok;
1879 struct isl_stream *s_file;
1880 struct iscc_options *options;
1881 FILE *file;
1882 isl_printer *p;
1884 tok = isl_stream_next_token(s);
1885 if (!tok || tok->type != ISL_TOKEN_STRING) {
1886 isl_stream_error(s, tok, "expecting filename");
1887 isl_token_free(tok);
1888 goto error;
1891 obj = read_expr(s, table);
1893 options = isl_ctx_peek_iscc_options(s->ctx);
1894 if (!options || !options->io) {
1895 isl_token_free(tok);
1896 isl_die(s->ctx, isl_error_invalid,
1897 "write operation not allowed", goto error);
1900 file = fopen(tok->u.s, "w");
1901 isl_token_free(tok);
1902 if (!file)
1903 isl_die(s->ctx, isl_error_unknown,
1904 "could not open file for writing", goto error);
1906 p = isl_printer_to_file(s->ctx, file);
1907 p = isl_printer_set_output_format(p, options->format);
1908 p = obj.type->print(p, obj.v);
1909 p = isl_printer_end_line(p);
1910 isl_printer_free(p);
1912 fclose(file);
1913 error:
1914 free_obj(obj);
1915 obj.type = isl_obj_none;
1916 obj.v = NULL;
1917 return obj;
1920 static struct isl_obj read_string_if_available(struct isl_stream *s)
1922 struct isl_token *tok;
1923 struct isl_obj obj = { isl_obj_none, NULL };
1925 tok = isl_stream_next_token(s);
1926 if (!tok)
1927 return obj;
1928 if (tok->type == ISL_TOKEN_STRING) {
1929 isl_str *str;
1930 str = isl_str_alloc(s->ctx);
1931 if (!str)
1932 goto error;
1933 str->s = strdup(tok->u.s);
1934 isl_token_free(tok);
1935 obj.v = str;
1936 obj.type = isl_obj_str;
1937 } else
1938 isl_stream_push_token(s, tok);
1939 return obj;
1940 error:
1941 isl_token_free(tok);
1942 return obj;
1945 static struct isl_obj read_bool_if_available(struct isl_stream *s)
1947 struct isl_token *tok;
1948 struct isl_obj obj = { isl_obj_none, NULL };
1950 tok = isl_stream_next_token(s);
1951 if (!tok)
1952 return obj;
1953 if (tok->type == ISL_TOKEN_FALSE || tok->type == ISL_TOKEN_TRUE) {
1954 int is_true = tok->type == ISL_TOKEN_TRUE;
1955 isl_token_free(tok);
1956 obj.v = is_true ? &isl_bool_true : &isl_bool_false;
1957 obj.type = isl_obj_bool;
1958 } else
1959 isl_stream_push_token(s, tok);
1960 return obj;
1961 error:
1962 isl_token_free(tok);
1963 return obj;
1966 static __isl_give char *read_ident(struct isl_stream *s)
1968 char *name;
1969 struct isl_token *tok, *tok2;
1971 name = isl_stream_read_ident_if_available(s);
1972 if (name)
1973 return name;
1975 tok = isl_stream_next_token(s);
1976 if (!tok)
1977 return NULL;
1978 if (tok->type != '$') {
1979 isl_stream_push_token(s, tok);
1980 return NULL;
1982 tok2 = isl_stream_next_token(s);
1983 if (!tok2 || tok2->type != ISL_TOKEN_VALUE) {
1984 if (tok2)
1985 isl_stream_push_token(s, tok2);
1986 isl_stream_push_token(s, tok);
1987 return NULL;
1990 name = isl_int_get_str(tok2->u.v);
1991 isl_token_free(tok);
1992 isl_token_free(tok2);
1994 return name;
1997 static struct isl_obj read_list(struct isl_stream *s,
1998 struct isl_hash_table *table, struct isl_obj obj)
2000 struct isl_list *list;
2002 list = isl_list_alloc(s->ctx, 2);
2003 if (!list)
2004 goto error;
2005 list->obj[0] = obj;
2006 list->obj[1] = read_obj(s, table);
2007 obj.v = list;
2008 obj.type = isl_obj_list;
2010 if (!list->obj[1].v)
2011 goto error;
2013 while (isl_stream_eat_if_available(s, ',')) {
2014 obj.v = list = isl_list_add_obj(list, read_obj(s, table));
2015 if (!obj.v)
2016 goto error;
2019 return obj;
2020 error:
2021 free_obj(obj);
2022 obj.type = isl_obj_none;
2023 obj.v = NULL;
2024 return obj;
2027 static struct isl_obj read_obj(struct isl_stream *s,
2028 struct isl_hash_table *table)
2030 struct isl_obj obj = { isl_obj_none, NULL };
2031 char *name = NULL;
2032 struct isc_un_op *op = NULL;
2034 obj = read_string_if_available(s);
2035 if (obj.v)
2036 return obj;
2037 obj = read_bool_if_available(s);
2038 if (obj.v)
2039 return obj;
2040 if (isl_stream_eat_if_available(s, '(')) {
2041 obj = read_expr(s, table);
2042 if (obj.v && isl_stream_eat_if_available(s, ','))
2043 obj = read_list(s, table, obj);
2044 if (!obj.v || isl_stream_eat(s, ')'))
2045 goto error;
2046 } else {
2047 op = read_prefix_un_op_if_available(s);
2048 if (op)
2049 return read_un_op_expr(s, table, op);
2051 if (isl_stream_eat_if_available(s, iscc_op[ISCC_READ]))
2052 return read_from_file(s);
2053 if (isl_stream_eat_if_available(s, iscc_op[ISCC_WRITE]))
2054 return write_to_file(s, table);
2055 if (isl_stream_eat_if_available(s, iscc_op[ISCC_VERTICES]))
2056 return vertices(s, table);
2057 if (isl_stream_eat_if_available(s, iscc_op[ISCC_ANY]))
2058 return any(s, table);
2059 if (isl_stream_eat_if_available(s, iscc_op[ISCC_LAST]))
2060 return last(s, table);
2061 if (isl_stream_eat_if_available(s, iscc_op[ISCC_SCHEDULE]))
2062 return schedule(s, table);
2063 if (isl_stream_eat_if_available(s, iscc_op[ISCC_SCHEDULE_BANDS]))
2064 return schedule_bands(s, table);
2065 if (isl_stream_eat_if_available(s, iscc_op[ISCC_TYPEOF]))
2066 return type_of(s, table);
2068 name = read_ident(s);
2069 if (name)
2070 obj = stored_obj(s->ctx, table, name);
2071 else
2072 obj = isl_stream_read_obj(s);
2073 if (!obj.v)
2074 goto error;
2077 if (isl_stream_eat_if_available(s, '^'))
2078 obj = power(s, obj);
2079 else if (obj.type == isl_obj_list && isl_stream_eat_if_available(s, '['))
2080 obj = obj_at_index(s, obj);
2081 else if (is_subtype(obj, isl_obj_union_map) &&
2082 isl_stream_eat_if_available(s, '(')) {
2083 obj = convert(s->ctx, obj, isl_obj_union_map);
2084 obj = apply(s, obj.v, table);
2085 } else if (is_subtype(obj, isl_obj_union_pw_qpolynomial) &&
2086 isl_stream_eat_if_available(s, '(')) {
2087 obj = convert(s->ctx, obj, isl_obj_union_pw_qpolynomial);
2088 obj = apply_fun(s, obj, table);
2089 } else if (is_subtype(obj, isl_obj_union_pw_qpolynomial_fold) &&
2090 isl_stream_eat_if_available(s, '(')) {
2091 obj = convert(s->ctx, obj, isl_obj_union_pw_qpolynomial_fold);
2092 obj = apply_fun(s, obj, table);
2095 return obj;
2096 error:
2097 free_obj(obj);
2098 obj.type = isl_obj_none;
2099 obj.v = NULL;
2100 return obj;
2103 static struct isc_bin_op *find_matching_bin_op(struct isc_bin_op *like,
2104 struct isl_obj lhs, struct isl_obj rhs)
2106 int i;
2108 for (i = 0; ; ++i) {
2109 if (!bin_ops[i].op)
2110 break;
2111 if (bin_ops[i].op != like->op)
2112 continue;
2113 if (!is_subtype(lhs, bin_ops[i].lhs))
2114 continue;
2115 if (!is_subtype(rhs, bin_ops[i].rhs))
2116 continue;
2118 return &bin_ops[i];
2121 for (i = 0; ; ++i) {
2122 if (!named_bin_ops[i].name)
2123 break;
2124 if (named_bin_ops[i].op.op != like->op)
2125 continue;
2126 if (!is_subtype(lhs, named_bin_ops[i].op.lhs))
2127 continue;
2128 if (!is_subtype(rhs, named_bin_ops[i].op.rhs))
2129 continue;
2131 return &named_bin_ops[i].op;
2134 return NULL;
2137 static int next_is_neg_int(struct isl_stream *s)
2139 struct isl_token *tok;
2140 int ret;
2142 tok = isl_stream_next_token(s);
2143 ret = tok && tok->type == ISL_TOKEN_VALUE && isl_int_is_neg(tok->u.v);
2144 isl_stream_push_token(s, tok);
2146 return ret;
2149 static struct isl_obj read_expr(struct isl_stream *s,
2150 struct isl_hash_table *table)
2152 struct isl_obj obj = { isl_obj_none, NULL };
2153 struct isl_obj right_obj = { isl_obj_none, NULL };
2155 obj = read_obj(s, table);
2156 for (; obj.v;) {
2157 struct isc_bin_op *op = NULL;
2159 op = read_bin_op_if_available(s, obj);
2160 if (!op)
2161 break;
2163 right_obj = read_obj(s, table);
2165 op = find_matching_bin_op(op, obj, right_obj);
2167 if (!op)
2168 isl_die(s->ctx, isl_error_invalid,
2169 "no such binary operator defined on given operands",
2170 goto error);
2172 obj = convert(s->ctx, obj, op->lhs);
2173 right_obj = convert(s->ctx, right_obj, op->rhs);
2174 obj.v = op->fn(obj.v, right_obj.v);
2175 obj.type = op->res;
2178 if (obj.type == isl_obj_int && next_is_neg_int(s)) {
2179 right_obj = read_obj(s, table);
2180 obj.v = isl_int_obj_add(obj.v, right_obj.v);
2183 return obj;
2184 error:
2185 free_obj(right_obj);
2186 free_obj(obj);
2187 obj.type = isl_obj_none;
2188 obj.v = NULL;
2189 return obj;
2192 static __isl_give isl_printer *source_file(struct isl_stream *s,
2193 struct isl_hash_table *table, __isl_take isl_printer *p);
2195 static __isl_give isl_printer *read_line(struct isl_stream *s,
2196 struct isl_hash_table *table, __isl_take isl_printer *p, int tty)
2198 struct isl_obj obj = { isl_obj_none, NULL };
2199 char *lhs = NULL;
2200 int assign = 0;
2201 int only_print = 0;
2202 struct isc_bin_op *op = NULL;
2203 char buf[30];
2205 if (!p)
2206 return NULL;
2207 if (isl_stream_is_empty(s))
2208 return p;
2210 if (isl_stream_eat_if_available(s, iscc_op[ISCC_SOURCE]))
2211 return source_file(s, table, p);
2213 assign = is_assign(s);
2214 if (assign) {
2215 lhs = isl_stream_read_ident_if_available(s);
2216 if (isl_stream_eat(s, ISL_TOKEN_DEF))
2217 goto error;
2218 } else if (isl_stream_eat_if_available(s, iscc_op[ISCC_PRINT]))
2219 only_print = 1;
2220 else if (!tty)
2221 only_print = 1;
2223 obj = read_expr(s, table);
2224 if (isl_ctx_last_error(s->ctx) == isl_error_abort) {
2225 fprintf(stderr, "Interrupted\n");
2226 isl_ctx_reset_error(s->ctx);
2228 if (isl_stream_eat(s, ';'))
2229 goto error;
2231 if (only_print) {
2232 p = obj.type->print(p, obj.v);
2233 p = isl_printer_end_line(p);
2234 free_obj(obj);
2235 return p;
2237 if (!assign && obj.type != isl_obj_none && obj.v != NULL) {
2238 static int count = 0;
2239 snprintf(buf, sizeof(buf), "$%d", count++);
2240 lhs = strdup(buf + 1);
2242 p = isl_printer_print_str(p, buf);
2243 p = isl_printer_print_str(p, " := ");
2244 p = obj.type->print(p, obj.v);
2245 p = isl_printer_end_line(p);
2247 if (lhs && do_assign(s->ctx, table, lhs, obj))
2248 return p;
2250 return p;
2251 error:
2252 isl_stream_flush_tokens(s);
2253 isl_stream_skip_line(s);
2254 free(lhs);
2255 free_obj(obj);
2256 return p;
2259 int free_cb(void **entry, void *user)
2261 struct isl_named_obj *named = *entry;
2263 free_obj(named->obj);
2264 free(named->name);
2265 free(named);
2267 return 0;
2270 static void register_named_ops(struct isl_stream *s)
2272 int i;
2274 for (i = 0; i < ISCC_N_OP; ++i) {
2275 iscc_op[i] = isl_stream_register_keyword(s, op_name[i]);
2276 assert(iscc_op[i] != ISL_TOKEN_ERROR);
2279 for (i = 0; ; ++i) {
2280 if (!named_un_ops[i].name)
2281 break;
2282 named_un_ops[i].op.op = isl_stream_register_keyword(s,
2283 named_un_ops[i].name);
2284 assert(named_un_ops[i].op.op != ISL_TOKEN_ERROR);
2287 for (i = 0; ; ++i) {
2288 if (!named_bin_ops[i].name)
2289 break;
2290 named_bin_ops[i].op.op = isl_stream_register_keyword(s,
2291 named_bin_ops[i].name);
2292 assert(named_bin_ops[i].op.op != ISL_TOKEN_ERROR);
2296 static __isl_give isl_printer *source_file(struct isl_stream *s,
2297 struct isl_hash_table *table, __isl_take isl_printer *p)
2299 struct isl_token *tok;
2300 struct isl_stream *s_file;
2301 FILE *file;
2303 tok = isl_stream_next_token(s);
2304 if (!tok || tok->type != ISL_TOKEN_STRING) {
2305 isl_stream_error(s, tok, "expecting filename");
2306 isl_token_free(tok);
2307 return p;
2310 file = fopen(tok->u.s, "r");
2311 isl_token_free(tok);
2312 isl_assert(s->ctx, file, return p);
2314 s_file = isl_stream_new_file(s->ctx, file);
2315 if (!s_file) {
2316 fclose(file);
2317 return p;
2320 register_named_ops(s_file);
2322 while (!s_file->eof)
2323 p = read_line(s_file, table, p, 0);
2325 isl_stream_free(s_file);
2326 fclose(file);
2328 isl_stream_eat(s, ';');
2330 return p;
2333 int main(int argc, char **argv)
2335 struct isl_ctx *ctx;
2336 struct isl_stream *s;
2337 struct isl_hash_table *table;
2338 struct iscc_options *options;
2339 isl_printer *p;
2340 int tty = isatty(0);
2342 options = iscc_options_new_with_defaults();
2343 assert(options);
2344 argc = iscc_options_parse(options, argc, argv, ISL_ARG_ALL);
2346 ctx = isl_ctx_alloc_with_options(iscc_options_arg, options);
2347 s = isl_stream_new_file(ctx, stdin);
2348 assert(s);
2349 table = isl_hash_table_alloc(ctx, 10);
2350 assert(table);
2351 p = isl_printer_to_file(ctx, stdout);
2352 p = isl_printer_set_output_format(p, options->format);
2353 assert(p);
2355 register_named_ops(s);
2357 install_signal_handler(ctx);
2359 while (p && !s->eof) {
2360 isl_ctx_resume(ctx);
2361 p = read_line(s, table, p, tty);
2364 remove_signal_handler(ctx);
2366 isl_printer_free(p);
2367 isl_hash_table_foreach(ctx, table, free_cb, NULL);
2368 isl_hash_table_free(ctx, table);
2369 isl_stream_free(s);
2370 isl_ctx_free(ctx);
2372 return 0;