update cloog to version 0.16.3
[barvinok.git] / iscc.c
blobf48d2d699d2c08b3a35aa6548a7d819d9a6c4c83
1 #include <assert.h>
2 #include <ctype.h>
3 #include <stdio.h>
4 #include <string.h>
5 #include <unistd.h>
6 #include <isl/obj.h>
7 #include <isl/stream.h>
8 #include <isl/vertices.h>
9 #include <isl/flow.h>
10 #include <isl/band.h>
11 #include <isl/schedule.h>
12 #include <isl_obj_list.h>
13 #include <isl_obj_str.h>
14 #include <barvinok/isl.h>
15 #include <barvinok/options.h>
16 #include "lattice_width.h"
18 #include "config.h"
20 #ifdef HAVE_SIGACTION
21 #include <signal.h>
23 static isl_ctx *main_ctx;
25 static void handler(int signum)
27 if (isl_ctx_aborted(main_ctx))
28 exit(EXIT_FAILURE);
29 isl_ctx_abort(main_ctx);
32 static struct sigaction sa_old;
34 static void install_signal_handler(isl_ctx *ctx)
36 struct sigaction sa;
38 main_ctx = ctx;
40 memset(&sa, 0, sizeof(struct sigaction));
41 sa.sa_handler = &handler;
42 sa.sa_flags = SA_RESTART;
43 sigaction(SIGINT, &sa, &sa_old);
46 static void remove_signal_handler(isl_ctx *ctx)
48 sigaction(SIGINT, &sa_old, NULL);
51 #else
53 static void install_signal_handler(isl_ctx *ctx)
57 static void remove_signal_handler(isl_ctx *ctx)
61 #endif
63 #ifdef HAVE_CLOOG
64 #include <cloog/isl/cloog.h>
65 #endif
67 static int isl_bool_false = 0;
68 static int isl_bool_true = 1;
69 static int isl_bool_error = -1;
71 enum iscc_op { ISCC_READ, ISCC_WRITE, ISCC_SOURCE, ISCC_VERTICES,
72 ISCC_LAST, ISCC_ANY, ISCC_BEFORE, ISCC_UNDER,
73 ISCC_SCHEDULE, ISCC_SCHEDULE_FOREST,
74 ISCC_MINIMIZING, ISCC_RESPECTING,
75 ISCC_TYPEOF, ISCC_PRINT,
76 ISCC_N_OP };
77 static const char *op_name[ISCC_N_OP] = {
78 [ISCC_READ] = "read",
79 [ISCC_WRITE] = "write",
80 [ISCC_PRINT] = "print",
81 [ISCC_SOURCE] = "source",
82 [ISCC_VERTICES] = "vertices",
83 [ISCC_LAST] = "last",
84 [ISCC_ANY] = "any",
85 [ISCC_BEFORE] = "before",
86 [ISCC_UNDER] = "under",
87 [ISCC_SCHEDULE] = "schedule",
88 [ISCC_SCHEDULE_FOREST] = "schedule_forest",
89 [ISCC_MINIMIZING] = "minimizing",
90 [ISCC_RESPECTING] = "respecting",
91 [ISCC_TYPEOF] = "typeof"
93 static enum isl_token_type iscc_op[ISCC_N_OP];
95 struct isl_arg_choice iscc_format[] = {
96 {"isl", ISL_FORMAT_ISL},
97 {"omega", ISL_FORMAT_OMEGA},
98 {"polylib", ISL_FORMAT_POLYLIB},
99 {"ext-polylib", ISL_FORMAT_EXT_POLYLIB},
100 {"latex", ISL_FORMAT_LATEX},
101 {"C", ISL_FORMAT_C},
105 struct iscc_options {
106 struct barvinok_options *barvinok;
107 unsigned format;
108 int io;
111 struct isl_arg iscc_options_arg[] = {
112 ISL_ARG_CHILD(struct iscc_options, barvinok, "barvinok", barvinok_options_arg,
113 "barvinok options")
114 ISL_ARG_CHOICE(struct iscc_options, format, 0, "format", \
115 iscc_format, ISL_FORMAT_ISL, "output format")
116 ISL_ARG_BOOL(struct iscc_options, io, 0, "io", 1,
117 "allow read and write operations")
118 ISL_ARG_END
121 ISL_ARG_DEF(iscc_options, struct iscc_options, iscc_options_arg)
122 ISL_ARG_CTX_DEF(iscc_options, struct iscc_options, iscc_options_arg)
124 static void *isl_obj_bool_copy(void *v)
126 return v;
129 static void isl_obj_bool_free(void *v)
133 static __isl_give isl_printer *isl_obj_bool_print(__isl_take isl_printer *p,
134 void *v)
136 if (v == &isl_bool_true)
137 return isl_printer_print_str(p, "True");
138 else if (v == &isl_bool_false)
139 return isl_printer_print_str(p, "False");
140 else
141 return isl_printer_print_str(p, "Error");
144 static void *isl_obj_bool_add(void *v1, void *v2)
146 return v1;
149 struct isl_obj_vtable isl_obj_bool_vtable = {
150 isl_obj_bool_copy,
151 isl_obj_bool_add,
152 isl_obj_bool_print,
153 isl_obj_bool_free
155 #define isl_obj_bool (&isl_obj_bool_vtable)
157 int *isl_bool_from_int(int res)
159 return res < 0 ? &isl_bool_error : res ? &isl_bool_true : &isl_bool_false;
162 int *union_map_is_equal(__isl_take isl_union_map *map1,
163 __isl_take isl_union_map *map2)
165 int res = isl_union_map_is_equal(map1, map2);
166 isl_union_map_free(map1);
167 isl_union_map_free(map2);
168 return isl_bool_from_int(res);
170 int *union_set_is_equal(__isl_take isl_union_set *set1,
171 __isl_take isl_union_set *set2)
173 return union_map_is_equal((isl_union_map *)set1, (isl_union_map *)set2);
176 int *union_map_is_subset(__isl_take isl_union_map *map1,
177 __isl_take isl_union_map *map2)
179 int res = isl_union_map_is_subset(map1, map2);
180 isl_union_map_free(map1);
181 isl_union_map_free(map2);
182 return isl_bool_from_int(res);
184 int *union_set_is_subset(__isl_take isl_union_set *set1,
185 __isl_take isl_union_set *set2)
187 return union_map_is_subset((isl_union_map *)set1, (isl_union_map *)set2);
190 int *union_map_is_strict_subset(__isl_take isl_union_map *map1,
191 __isl_take isl_union_map *map2)
193 int res = isl_union_map_is_strict_subset(map1, map2);
194 isl_union_map_free(map1);
195 isl_union_map_free(map2);
196 return isl_bool_from_int(res);
198 int *union_set_is_strict_subset(__isl_take isl_union_set *set1,
199 __isl_take isl_union_set *set2)
201 return union_map_is_strict_subset((isl_union_map *)set1,
202 (isl_union_map *)set2);
205 int *union_map_is_superset(__isl_take isl_union_map *map1,
206 __isl_take isl_union_map *map2)
208 return union_map_is_subset(map2, map1);
210 int *union_set_is_superset(__isl_take isl_union_set *set1,
211 __isl_take isl_union_set *set2)
213 return union_set_is_subset(set2, set1);
216 int *union_map_is_strict_superset(__isl_take isl_union_map *map1,
217 __isl_take isl_union_map *map2)
219 return union_map_is_strict_subset(map2, map1);
221 int *union_set_is_strict_superset(__isl_take isl_union_set *set1,
222 __isl_take isl_union_set *set2)
224 return union_set_is_strict_subset(set2, set1);
227 extern struct isl_obj_vtable isl_obj_list_vtable;
228 #define isl_obj_list (&isl_obj_list_vtable)
230 typedef void *(*isc_bin_op_fn)(void *lhs, void *rhs);
231 struct isc_bin_op {
232 enum isl_token_type op;
233 isl_obj_type lhs;
234 isl_obj_type rhs;
235 isl_obj_type res;
236 isc_bin_op_fn fn;
238 struct isc_named_bin_op {
239 char *name;
240 struct isc_bin_op op;
243 struct iscc_at {
244 isl_union_pw_qpolynomial *upwqp;
245 isl_union_pw_qpolynomial *res;
248 static int eval_at(__isl_take isl_point *pnt, void *user)
250 struct iscc_at *at = (struct iscc_at *) user;
251 isl_qpolynomial *qp;
252 isl_set *set;
254 set = isl_set_from_point(isl_point_copy(pnt));
255 qp = isl_union_pw_qpolynomial_eval(
256 isl_union_pw_qpolynomial_copy(at->upwqp), pnt);
258 at->res = isl_union_pw_qpolynomial_add(at->res,
259 isl_union_pw_qpolynomial_from_pw_qpolynomial(
260 isl_pw_qpolynomial_alloc(set, qp)));
262 return 0;
265 __isl_give isl_union_pw_qpolynomial *isl_union_pw_qpolynomial_at(
266 __isl_take isl_union_pw_qpolynomial *upwqp,
267 __isl_take isl_union_set *uset)
269 struct iscc_at at;
271 at.upwqp = upwqp;
272 at.res = isl_union_pw_qpolynomial_zero(isl_union_set_get_dim(uset));
274 isl_union_set_foreach_point(uset, eval_at, &at);
276 isl_union_pw_qpolynomial_free(upwqp);
277 isl_union_set_free(uset);
279 return at.res;
282 struct iscc_fold_at {
283 isl_union_pw_qpolynomial_fold *upwf;
284 isl_union_pw_qpolynomial *res;
287 static int eval_fold_at(__isl_take isl_point *pnt, void *user)
289 struct iscc_fold_at *at = (struct iscc_fold_at *) user;
290 isl_qpolynomial *qp;
291 isl_set *set;
293 set = isl_set_from_point(isl_point_copy(pnt));
294 qp = isl_union_pw_qpolynomial_fold_eval(
295 isl_union_pw_qpolynomial_fold_copy(at->upwf), pnt);
297 at->res = isl_union_pw_qpolynomial_add(at->res,
298 isl_union_pw_qpolynomial_from_pw_qpolynomial(
299 isl_pw_qpolynomial_alloc(set, qp)));
301 return 0;
304 __isl_give isl_union_pw_qpolynomial *isl_union_pw_qpolynomial_fold_at(
305 __isl_take isl_union_pw_qpolynomial_fold *upwf,
306 __isl_take isl_union_set *uset)
308 struct iscc_fold_at at;
310 at.upwf = upwf;
311 at.res = isl_union_pw_qpolynomial_zero(isl_union_set_get_dim(uset));
313 isl_union_set_foreach_point(uset, eval_fold_at, &at);
315 isl_union_pw_qpolynomial_fold_free(upwf);
316 isl_union_set_free(uset);
318 return at.res;
321 static __isl_give isl_union_pw_qpolynomial_fold *union_pw_qpolynomial_add_union_pw_qpolynomial_fold(
322 __isl_take isl_union_pw_qpolynomial *upwqp,
323 __isl_take isl_union_pw_qpolynomial_fold *upwf)
325 return isl_union_pw_qpolynomial_fold_add_union_pw_qpolynomial(upwf,
326 upwqp);
329 static __isl_give struct isl_list *union_map_apply_union_pw_qpolynomial_fold(
330 __isl_take isl_union_map *umap,
331 __isl_take isl_union_pw_qpolynomial_fold *upwf)
333 isl_ctx *ctx;
334 struct isl_list *list;
335 int tight;
337 ctx = isl_union_map_get_ctx(umap);
338 list = isl_list_alloc(ctx, 2);
339 if (!list)
340 goto error2;
342 list->obj[0].type = isl_obj_union_pw_qpolynomial_fold;
343 list->obj[0].v = isl_union_map_apply_union_pw_qpolynomial_fold(umap,
344 upwf, &tight);
345 list->obj[1].type = isl_obj_bool;
346 list->obj[1].v = tight ? &isl_bool_true : &isl_bool_false;
347 if (tight < 0 || !list->obj[0].v)
348 goto error;
350 return list;
351 error2:
352 isl_union_map_free(umap);
353 isl_union_pw_qpolynomial_fold_free(upwf);
354 error:
355 isl_list_free(list);
356 return NULL;
359 static __isl_give isl_union_pw_qpolynomial *union_pw_qpolynomial_int_mul(
360 __isl_take isl_union_pw_qpolynomial *upwqp, __isl_take isl_int_obj *i)
362 isl_int v;
364 if (!i)
365 goto error;
367 isl_int_init(v);
368 isl_int_obj_get_int(i, &v);
369 upwqp = isl_union_pw_qpolynomial_mul_isl_int(upwqp, v);
370 isl_int_clear(v);
372 isl_int_obj_free(i);
374 return upwqp;
375 error:
376 isl_union_pw_qpolynomial_free(upwqp);
377 return NULL;
380 static __isl_give isl_union_pw_qpolynomial *int_union_pw_qpolynomial_mul(
381 __isl_take isl_int_obj *i, __isl_take isl_union_pw_qpolynomial *upwqp)
383 return union_pw_qpolynomial_int_mul(upwqp, i);
386 static __isl_give isl_union_pw_qpolynomial_fold *union_pw_qpolynomial_fold_int_mul(
387 __isl_take isl_union_pw_qpolynomial_fold *upwf,
388 __isl_take isl_int_obj *i)
390 isl_int v;
392 if (!i)
393 goto error;
395 isl_int_init(v);
396 isl_int_obj_get_int(i, &v);
397 upwf = isl_union_pw_qpolynomial_fold_mul_isl_int(upwf, v);
398 isl_int_clear(v);
400 isl_int_obj_free(i);
402 return upwf;
403 error:
404 isl_union_pw_qpolynomial_fold_free(upwf);
405 return NULL;
408 static __isl_give isl_union_pw_qpolynomial_fold *int_union_pw_qpolynomial_fold_mul(
409 __isl_take isl_int_obj *i,
410 __isl_take isl_union_pw_qpolynomial_fold *upwf)
412 return union_pw_qpolynomial_fold_int_mul(upwf, i);
415 struct isc_bin_op bin_ops[] = {
416 { '+', isl_obj_int, isl_obj_int, isl_obj_int,
417 (isc_bin_op_fn) &isl_int_obj_add },
418 { '-', isl_obj_int, isl_obj_int, isl_obj_int,
419 (isc_bin_op_fn) &isl_int_obj_sub },
420 { '*', isl_obj_int, isl_obj_int, isl_obj_int,
421 (isc_bin_op_fn) &isl_int_obj_mul },
422 { '+', isl_obj_union_set, isl_obj_union_set,
423 isl_obj_union_set,
424 (isc_bin_op_fn) &isl_union_set_union },
425 { '+', isl_obj_union_map, isl_obj_union_map,
426 isl_obj_union_map,
427 (isc_bin_op_fn) &isl_union_map_union },
428 { '-', isl_obj_union_set, isl_obj_union_set,
429 isl_obj_union_set,
430 (isc_bin_op_fn) &isl_union_set_subtract },
431 { '-', isl_obj_union_map, isl_obj_union_map,
432 isl_obj_union_map,
433 (isc_bin_op_fn) &isl_union_map_subtract },
434 { '*', isl_obj_union_set, isl_obj_union_set,
435 isl_obj_union_set,
436 (isc_bin_op_fn) &isl_union_set_intersect },
437 { '*', isl_obj_union_map, isl_obj_union_map,
438 isl_obj_union_map,
439 (isc_bin_op_fn) &isl_union_map_intersect },
440 { '*', isl_obj_union_map, isl_obj_union_set,
441 isl_obj_union_map,
442 (isc_bin_op_fn) &isl_union_map_intersect_domain },
443 { '.', isl_obj_union_map, isl_obj_union_map,
444 isl_obj_union_map,
445 (isc_bin_op_fn) &isl_union_map_apply_range },
446 { '.', isl_obj_union_map, isl_obj_union_pw_qpolynomial,
447 isl_obj_union_pw_qpolynomial,
448 (isc_bin_op_fn) &isl_union_map_apply_union_pw_qpolynomial },
449 { '.', isl_obj_union_map, isl_obj_union_pw_qpolynomial_fold,
450 isl_obj_list,
451 (isc_bin_op_fn) &union_map_apply_union_pw_qpolynomial_fold },
452 { ISL_TOKEN_TO, isl_obj_union_set, isl_obj_union_set,
453 isl_obj_union_map,
454 (isc_bin_op_fn) &isl_union_map_from_domain_and_range },
455 { '=', isl_obj_union_set, isl_obj_union_set, isl_obj_bool,
456 (isc_bin_op_fn) &union_set_is_equal },
457 { '=', isl_obj_union_map, isl_obj_union_map, isl_obj_bool,
458 (isc_bin_op_fn) &union_map_is_equal },
459 { ISL_TOKEN_LE, isl_obj_union_set, isl_obj_union_set,
460 isl_obj_bool, (isc_bin_op_fn) &union_set_is_subset },
461 { ISL_TOKEN_LE, isl_obj_union_map, isl_obj_union_map,
462 isl_obj_bool, (isc_bin_op_fn) &union_map_is_subset },
463 { ISL_TOKEN_LT, isl_obj_union_set, isl_obj_union_set,
464 isl_obj_bool, (isc_bin_op_fn) &union_set_is_strict_subset },
465 { ISL_TOKEN_LT, isl_obj_union_map, isl_obj_union_map,
466 isl_obj_bool, (isc_bin_op_fn) &union_map_is_strict_subset },
467 { ISL_TOKEN_GE, isl_obj_union_set, isl_obj_union_set,
468 isl_obj_bool, (isc_bin_op_fn) &union_set_is_superset },
469 { ISL_TOKEN_GE, isl_obj_union_map, isl_obj_union_map,
470 isl_obj_bool, (isc_bin_op_fn) &union_map_is_superset },
471 { ISL_TOKEN_GT, isl_obj_union_set, isl_obj_union_set,
472 isl_obj_bool, (isc_bin_op_fn) &union_set_is_strict_superset },
473 { ISL_TOKEN_GT, isl_obj_union_map, isl_obj_union_map,
474 isl_obj_bool, (isc_bin_op_fn) &union_map_is_strict_superset },
475 { ISL_TOKEN_LEX_LE, isl_obj_union_set, isl_obj_union_set,
476 isl_obj_union_map,
477 (isc_bin_op_fn) &isl_union_set_lex_le_union_set },
478 { ISL_TOKEN_LEX_LT, isl_obj_union_set, isl_obj_union_set,
479 isl_obj_union_map,
480 (isc_bin_op_fn) &isl_union_set_lex_lt_union_set },
481 { ISL_TOKEN_LEX_GE, isl_obj_union_set, isl_obj_union_set,
482 isl_obj_union_map,
483 (isc_bin_op_fn) &isl_union_set_lex_ge_union_set },
484 { ISL_TOKEN_LEX_GT, isl_obj_union_set, isl_obj_union_set,
485 isl_obj_union_map,
486 (isc_bin_op_fn) &isl_union_set_lex_gt_union_set },
487 { ISL_TOKEN_LEX_LE, isl_obj_union_map, isl_obj_union_map,
488 isl_obj_union_map,
489 (isc_bin_op_fn) &isl_union_map_lex_le_union_map },
490 { ISL_TOKEN_LEX_LT, isl_obj_union_map, isl_obj_union_map,
491 isl_obj_union_map,
492 (isc_bin_op_fn) &isl_union_map_lex_lt_union_map },
493 { ISL_TOKEN_LEX_GE, isl_obj_union_map, isl_obj_union_map,
494 isl_obj_union_map,
495 (isc_bin_op_fn) &isl_union_map_lex_ge_union_map },
496 { ISL_TOKEN_LEX_GT, isl_obj_union_map, isl_obj_union_map,
497 isl_obj_union_map,
498 (isc_bin_op_fn) &isl_union_map_lex_gt_union_map },
499 { '.', isl_obj_union_pw_qpolynomial_fold,
500 isl_obj_union_pw_qpolynomial_fold,
501 isl_obj_union_pw_qpolynomial_fold,
502 (isc_bin_op_fn) &isl_union_pw_qpolynomial_fold_fold },
503 { '+', isl_obj_union_pw_qpolynomial, isl_obj_union_pw_qpolynomial,
504 isl_obj_union_pw_qpolynomial,
505 (isc_bin_op_fn) &isl_union_pw_qpolynomial_add },
506 { '+', isl_obj_union_pw_qpolynomial,
507 isl_obj_union_pw_qpolynomial_fold,
508 isl_obj_union_pw_qpolynomial_fold,
509 (isc_bin_op_fn) &union_pw_qpolynomial_add_union_pw_qpolynomial_fold },
510 { '+', isl_obj_union_pw_qpolynomial_fold,
511 isl_obj_union_pw_qpolynomial,
512 isl_obj_union_pw_qpolynomial_fold,
513 (isc_bin_op_fn) &isl_union_pw_qpolynomial_fold_add_union_pw_qpolynomial },
514 { '-', isl_obj_union_pw_qpolynomial, isl_obj_union_pw_qpolynomial,
515 isl_obj_union_pw_qpolynomial,
516 (isc_bin_op_fn) &isl_union_pw_qpolynomial_sub },
517 { '*', isl_obj_int, isl_obj_union_pw_qpolynomial,
518 isl_obj_union_pw_qpolynomial,
519 (isc_bin_op_fn) &int_union_pw_qpolynomial_mul },
520 { '*', isl_obj_union_pw_qpolynomial, isl_obj_int,
521 isl_obj_union_pw_qpolynomial,
522 (isc_bin_op_fn) &union_pw_qpolynomial_int_mul },
523 { '*', isl_obj_int, isl_obj_union_pw_qpolynomial_fold,
524 isl_obj_union_pw_qpolynomial_fold,
525 (isc_bin_op_fn) &int_union_pw_qpolynomial_fold_mul },
526 { '*', isl_obj_union_pw_qpolynomial_fold, isl_obj_int,
527 isl_obj_union_pw_qpolynomial_fold,
528 (isc_bin_op_fn) &union_pw_qpolynomial_fold_int_mul },
529 { '*', isl_obj_union_pw_qpolynomial, isl_obj_union_pw_qpolynomial,
530 isl_obj_union_pw_qpolynomial,
531 (isc_bin_op_fn) &isl_union_pw_qpolynomial_mul },
532 { '*', isl_obj_union_pw_qpolynomial, isl_obj_union_set,
533 isl_obj_union_pw_qpolynomial,
534 (isc_bin_op_fn) &isl_union_pw_qpolynomial_intersect_domain },
535 { '*', isl_obj_union_pw_qpolynomial_fold, isl_obj_union_set,
536 isl_obj_union_pw_qpolynomial_fold,
537 (isc_bin_op_fn) &isl_union_pw_qpolynomial_fold_intersect_domain },
538 { '@', isl_obj_union_pw_qpolynomial, isl_obj_union_set,
539 isl_obj_union_pw_qpolynomial,
540 (isc_bin_op_fn) &isl_union_pw_qpolynomial_at },
541 { '@', isl_obj_union_pw_qpolynomial_fold, isl_obj_union_set,
542 isl_obj_union_pw_qpolynomial,
543 (isc_bin_op_fn) &isl_union_pw_qpolynomial_fold_at },
544 { '%', isl_obj_union_set, isl_obj_union_set,
545 isl_obj_union_set,
546 (isc_bin_op_fn) &isl_union_set_gist },
547 { '%', isl_obj_union_map, isl_obj_union_map,
548 isl_obj_union_map,
549 (isc_bin_op_fn) &isl_union_map_gist },
550 { '%', isl_obj_union_pw_qpolynomial, isl_obj_union_set,
551 isl_obj_union_pw_qpolynomial,
552 (isc_bin_op_fn) &isl_union_pw_qpolynomial_gist },
553 { '%', isl_obj_union_pw_qpolynomial_fold, isl_obj_union_set,
554 isl_obj_union_pw_qpolynomial_fold,
555 (isc_bin_op_fn) &isl_union_pw_qpolynomial_fold_gist },
556 { '+', isl_obj_str, isl_obj_str, isl_obj_str,
557 (isc_bin_op_fn) &isl_str_concat },
561 static __isl_give isl_union_map *map_after_map(__isl_take isl_union_map *umap1,
562 __isl_take isl_union_map *umap2)
564 return isl_union_map_apply_range(umap2, umap1);
567 static __isl_give isl_union_pw_qpolynomial *qpolynomial_after_map(
568 __isl_take isl_union_pw_qpolynomial *upwqp,
569 __isl_take isl_union_map *umap)
571 return isl_union_map_apply_union_pw_qpolynomial(umap, upwqp);
574 static __isl_give struct isl_list *qpolynomial_fold_after_map(
575 __isl_take isl_union_pw_qpolynomial_fold *upwf,
576 __isl_take isl_union_map *umap)
578 return union_map_apply_union_pw_qpolynomial_fold(umap, upwf);
581 struct isc_named_bin_op named_bin_ops[] = {
582 { "after", { -1, isl_obj_union_map, isl_obj_union_map,
583 isl_obj_union_map,
584 (isc_bin_op_fn) &map_after_map } },
585 { "after", { -1, isl_obj_union_pw_qpolynomial,
586 isl_obj_union_map, isl_obj_union_pw_qpolynomial,
587 (isc_bin_op_fn) &qpolynomial_after_map } },
588 { "after", { -1, isl_obj_union_pw_qpolynomial_fold,
589 isl_obj_union_map, isl_obj_list,
590 (isc_bin_op_fn) &qpolynomial_fold_after_map } },
591 { "before", { -1, isl_obj_union_map, isl_obj_union_map,
592 isl_obj_union_map,
593 (isc_bin_op_fn) &isl_union_map_apply_range } },
594 { "before", { -1, isl_obj_union_map,
595 isl_obj_union_pw_qpolynomial, isl_obj_union_pw_qpolynomial,
596 (isc_bin_op_fn) &isl_union_map_apply_union_pw_qpolynomial } },
597 { "before", { -1, isl_obj_union_map,
598 isl_obj_union_pw_qpolynomial_fold, isl_obj_list,
599 (isc_bin_op_fn) &union_map_apply_union_pw_qpolynomial_fold } },
600 { "cross", { -1, isl_obj_union_set, isl_obj_union_set,
601 isl_obj_union_set,
602 (isc_bin_op_fn) &isl_union_set_product } },
603 { "cross", { -1, isl_obj_union_map, isl_obj_union_map,
604 isl_obj_union_map,
605 (isc_bin_op_fn) &isl_union_map_product } },
606 NULL
609 __isl_give isl_set *union_set_sample(__isl_take isl_union_set *uset)
611 return isl_set_from_basic_set(isl_union_set_sample(uset));
614 __isl_give isl_map *union_map_sample(__isl_take isl_union_map *umap)
616 return isl_map_from_basic_map(isl_union_map_sample(umap));
619 static __isl_give struct isl_list *union_map_power(
620 __isl_take isl_union_map *umap)
622 isl_ctx *ctx;
623 struct isl_list *list;
624 int exact;
626 ctx = isl_union_map_get_ctx(umap);
627 list = isl_list_alloc(ctx, 2);
628 if (!list)
629 goto error2;
631 list->obj[0].type = isl_obj_union_map;
632 list->obj[0].v = isl_union_map_power(umap, &exact);
633 list->obj[1].type = isl_obj_bool;
634 list->obj[1].v = exact ? &isl_bool_true : &isl_bool_false;
635 if (exact < 0 || !list->obj[0].v)
636 goto error;
638 return list;
639 error2:
640 isl_union_map_free(umap);
641 error:
642 isl_list_free(list);
643 return NULL;
646 static __isl_give struct isl_list *union_pw_qpolynomial_upper_bound(
647 __isl_take isl_union_pw_qpolynomial *upwqp)
649 isl_ctx *ctx;
650 struct isl_list *list;
651 int tight;
653 ctx = isl_union_pw_qpolynomial_get_ctx(upwqp);
654 list = isl_list_alloc(ctx, 2);
655 if (!list)
656 goto error2;
658 list->obj[0].type = isl_obj_union_pw_qpolynomial_fold;
659 list->obj[0].v = isl_union_pw_qpolynomial_bound(upwqp,
660 isl_fold_max, &tight);
661 list->obj[1].type = isl_obj_bool;
662 list->obj[1].v = tight ? &isl_bool_true : &isl_bool_false;
663 if (tight < 0 || !list->obj[0].v)
664 goto error;
666 return list;
667 error2:
668 isl_union_pw_qpolynomial_free(upwqp);
669 error:
670 isl_list_free(list);
671 return NULL;
674 #ifdef HAVE_CLOOG
675 void *map_codegen(void *arg)
677 isl_dim *dim;
678 isl_union_map *umap = (isl_union_map *)arg;
679 isl_ctx *ctx = isl_union_map_get_ctx(umap);
680 CloogState *state;
681 CloogOptions *options;
682 CloogDomain *context;
683 CloogUnionDomain *ud;
684 CloogInput *input;
685 struct clast_stmt *stmt;
687 state = cloog_isl_state_malloc(ctx);
688 options = cloog_options_malloc(state);
689 options->language = LANGUAGE_C;
690 options->strides = 1;
691 options->sh = 1;
693 ud = cloog_union_domain_from_isl_union_map(isl_union_map_copy(umap));
695 dim = isl_union_map_get_dim(umap);
696 context = cloog_domain_from_isl_set(isl_set_universe(dim));
698 input = cloog_input_alloc(context, ud);
700 stmt = cloog_clast_create_from_input(input, options);
701 clast_pprint(stdout, stmt, 0, options);
702 cloog_clast_free(stmt);
704 error:
705 cloog_options_free(options);
706 cloog_state_free(state);
707 isl_union_map_free(umap);
708 return NULL;
711 void *set_codegen(void *arg)
713 isl_dim *dim;
714 isl_union_set *uset = (isl_union_set *)arg;
715 isl_ctx *ctx = isl_union_set_get_ctx(uset);
716 CloogState *state;
717 CloogOptions *options;
718 CloogDomain *context;
719 CloogUnionDomain *ud;
720 CloogInput *input;
721 struct clast_stmt *stmt;
723 if (isl_union_set_n_set(uset) > 1)
724 isl_die(ctx, isl_error_invalid,
725 "code generation for more than one domain "
726 "requires a schedule", goto error);
728 state = cloog_isl_state_malloc(ctx);
729 options = cloog_options_malloc(state);
730 options->language = LANGUAGE_C;
731 options->strides = 1;
732 options->sh = 1;
734 ud = cloog_union_domain_from_isl_union_set(isl_union_set_copy(uset));
736 dim = isl_union_set_get_dim(uset);
737 context = cloog_domain_from_isl_set(isl_set_universe(dim));
739 input = cloog_input_alloc(context, ud);
741 stmt = cloog_clast_create_from_input(input, options);
742 clast_pprint(stdout, stmt, 0, options);
743 cloog_clast_free(stmt);
745 cloog_options_free(options);
746 cloog_state_free(state);
747 error:
748 isl_union_set_free(uset);
749 return NULL;
751 #endif
753 static int add_point(__isl_take isl_point *pnt, void *user)
755 isl_union_set **scan = (isl_union_set **) user;
757 *scan = isl_union_set_add_set(*scan, isl_set_from_point(pnt));
759 return 0;
762 static __isl_give isl_union_set *union_set_scan(__isl_take isl_union_set *uset)
764 isl_union_set *scan;
766 scan = isl_union_set_empty(isl_union_set_get_dim(uset));
768 if (isl_union_set_foreach_point(uset, add_point, &scan) < 0) {
769 isl_union_set_free(scan);
770 return uset;
773 isl_union_set_free(uset);
774 return scan;
777 static __isl_give isl_union_map *union_map_scan(__isl_take isl_union_map *umap)
779 return isl_union_set_unwrap(union_set_scan(isl_union_map_wrap(umap)));
782 static __isl_give isl_union_pw_qpolynomial *union_pw_qpolynomial_poly(
783 __isl_take isl_union_pw_qpolynomial *upwqp)
785 return isl_union_pw_qpolynomial_to_polynomial(upwqp, 0);
788 static __isl_give isl_union_pw_qpolynomial *union_pw_qpolynomial_lpoly(
789 __isl_take isl_union_pw_qpolynomial *upwqp)
791 return isl_union_pw_qpolynomial_to_polynomial(upwqp, -1);
794 static __isl_give isl_union_pw_qpolynomial *union_pw_qpolynomial_upoly(
795 __isl_take isl_union_pw_qpolynomial *upwqp)
797 return isl_union_pw_qpolynomial_to_polynomial(upwqp, 1);
800 typedef void *(*isc_un_op_fn)(void *arg);
801 struct isc_un_op {
802 enum isl_token_type op;
803 isl_obj_type arg;
804 isl_obj_type res;
805 isc_un_op_fn fn;
807 struct isc_named_un_op {
808 char *name;
809 struct isc_un_op op;
811 struct isc_named_un_op named_un_ops[] = {
812 {"aff", { -1, isl_obj_union_map, isl_obj_union_map,
813 (isc_un_op_fn) &isl_union_map_affine_hull } },
814 {"aff", { -1, isl_obj_union_set, isl_obj_union_set,
815 (isc_un_op_fn) &isl_union_set_affine_hull } },
816 {"card", { -1, isl_obj_union_set,
817 isl_obj_union_pw_qpolynomial,
818 (isc_un_op_fn) &isl_union_set_card } },
819 {"card", { -1, isl_obj_union_map,
820 isl_obj_union_pw_qpolynomial,
821 (isc_un_op_fn) &isl_union_map_card } },
822 {"coalesce", { -1, isl_obj_union_set, isl_obj_union_set,
823 (isc_un_op_fn) &isl_union_set_coalesce } },
824 {"coalesce", { -1, isl_obj_union_map, isl_obj_union_map,
825 (isc_un_op_fn) &isl_union_map_coalesce } },
826 {"coalesce", { -1, isl_obj_union_pw_qpolynomial,
827 isl_obj_union_pw_qpolynomial,
828 (isc_un_op_fn) &isl_union_pw_qpolynomial_coalesce } },
829 {"coalesce", { -1, isl_obj_union_pw_qpolynomial_fold,
830 isl_obj_union_pw_qpolynomial_fold,
831 (isc_un_op_fn) &isl_union_pw_qpolynomial_fold_coalesce } },
832 #ifdef HAVE_CLOOG
833 {"codegen", { -1, isl_obj_union_set, isl_obj_none,
834 &set_codegen } },
835 {"codegen", { -1, isl_obj_union_map, isl_obj_none,
836 &map_codegen } },
837 #endif
838 {"coefficients", { -1, isl_obj_union_set,
839 isl_obj_union_set,
840 (isc_un_op_fn) &isl_union_set_coefficients } },
841 {"solutions", { -1, isl_obj_union_set, isl_obj_union_set,
842 (isc_un_op_fn) &isl_union_set_solutions } },
843 {"deltas", { -1, isl_obj_union_map, isl_obj_union_set,
844 (isc_un_op_fn) &isl_union_map_deltas } },
845 {"deltas_map", { -1, isl_obj_union_map, isl_obj_union_map,
846 (isc_un_op_fn) &isl_union_map_deltas_map } },
847 {"dom", { -1, isl_obj_union_map, isl_obj_union_set,
848 (isc_un_op_fn) &isl_union_map_domain } },
849 {"dom", { -1, isl_obj_union_pw_qpolynomial, isl_obj_union_set,
850 (isc_un_op_fn) &isl_union_pw_qpolynomial_domain } },
851 {"dom", { -1, isl_obj_union_pw_qpolynomial_fold,
852 isl_obj_union_set,
853 (isc_un_op_fn) &isl_union_pw_qpolynomial_fold_domain } },
854 {"domain", { -1, isl_obj_union_map, isl_obj_union_set,
855 (isc_un_op_fn) &isl_union_map_domain } },
856 {"domain", { -1, isl_obj_union_pw_qpolynomial,
857 isl_obj_union_set,
858 (isc_un_op_fn) &isl_union_pw_qpolynomial_domain } },
859 {"domain", { -1, isl_obj_union_pw_qpolynomial_fold,
860 isl_obj_union_set,
861 (isc_un_op_fn) &isl_union_pw_qpolynomial_fold_domain } },
862 {"domain_map", { -1, isl_obj_union_map, isl_obj_union_map,
863 (isc_un_op_fn) &isl_union_map_domain_map } },
864 {"ran", { -1, isl_obj_union_map, isl_obj_union_set,
865 (isc_un_op_fn) &isl_union_map_range } },
866 {"range", { -1, isl_obj_union_map, isl_obj_union_set,
867 (isc_un_op_fn) &isl_union_map_range } },
868 {"range_map", { -1, isl_obj_union_map, isl_obj_union_map,
869 (isc_un_op_fn) &isl_union_map_range_map } },
870 {"identity", { -1, isl_obj_union_set, isl_obj_union_map,
871 (isc_un_op_fn) &isl_union_set_identity } },
872 {"lattice_width", { -1, isl_obj_union_set,
873 isl_obj_union_pw_qpolynomial,
874 (isc_un_op_fn) &isl_union_set_lattice_width } },
875 {"lexmin", { -1, isl_obj_union_map, isl_obj_union_map,
876 (isc_un_op_fn) &isl_union_map_lexmin } },
877 {"lexmax", { -1, isl_obj_union_map, isl_obj_union_map,
878 (isc_un_op_fn) &isl_union_map_lexmax } },
879 {"lexmin", { -1, isl_obj_union_set, isl_obj_union_set,
880 (isc_un_op_fn) &isl_union_set_lexmin } },
881 {"lexmax", { -1, isl_obj_union_set, isl_obj_union_set,
882 (isc_un_op_fn) &isl_union_set_lexmax } },
883 {"lift", { -1, isl_obj_union_set, isl_obj_union_set,
884 (isc_un_op_fn) &isl_union_set_lift } },
885 {"poly", { -1, isl_obj_union_map, isl_obj_union_map,
886 (isc_un_op_fn) &isl_union_map_polyhedral_hull } },
887 {"poly", { -1, isl_obj_union_set, isl_obj_union_set,
888 (isc_un_op_fn) &isl_union_set_polyhedral_hull } },
889 {"poly", { -1, isl_obj_union_pw_qpolynomial,
890 isl_obj_union_pw_qpolynomial,
891 (isc_un_op_fn) &union_pw_qpolynomial_poly } },
892 {"lpoly", { -1, isl_obj_union_pw_qpolynomial,
893 isl_obj_union_pw_qpolynomial,
894 (isc_un_op_fn) &union_pw_qpolynomial_lpoly } },
895 {"upoly", { -1, isl_obj_union_pw_qpolynomial,
896 isl_obj_union_pw_qpolynomial,
897 (isc_un_op_fn) &union_pw_qpolynomial_upoly } },
898 {"pow", { -1, isl_obj_union_map, isl_obj_list,
899 (isc_un_op_fn) &union_map_power } },
900 {"sample", { -1, isl_obj_union_set, isl_obj_set,
901 (isc_un_op_fn) &union_set_sample } },
902 {"sample", { -1, isl_obj_union_map, isl_obj_map,
903 (isc_un_op_fn) &union_map_sample } },
904 {"scan", { -1, isl_obj_union_set, isl_obj_union_set,
905 (isc_un_op_fn) &union_set_scan } },
906 {"scan", { -1, isl_obj_union_map, isl_obj_union_map,
907 (isc_un_op_fn) &union_map_scan } },
908 {"sum", { -1, isl_obj_union_pw_qpolynomial,
909 isl_obj_union_pw_qpolynomial,
910 (isc_un_op_fn) &isl_union_pw_qpolynomial_sum } },
911 {"ub", { -1, isl_obj_union_pw_qpolynomial, isl_obj_list,
912 (isc_un_op_fn) &union_pw_qpolynomial_upper_bound } },
913 {"unwrap", { -1, isl_obj_union_set, isl_obj_union_map,
914 (isc_un_op_fn) &isl_union_set_unwrap } },
915 {"wrap", { -1, isl_obj_union_map, isl_obj_union_set,
916 (isc_un_op_fn) &isl_union_map_wrap } },
917 {"zip", { -1, isl_obj_union_map, isl_obj_union_map,
918 (isc_un_op_fn) &isl_union_map_zip } },
919 NULL
922 struct isl_named_obj {
923 char *name;
924 struct isl_obj obj;
927 static void free_obj(struct isl_obj obj)
929 obj.type->free(obj.v);
932 static int same_name(const void *entry, const void *val)
934 const struct isl_named_obj *named = (const struct isl_named_obj *)entry;
936 return !strcmp(named->name, val);
939 static int do_assign(struct isl_ctx *ctx, struct isl_hash_table *table,
940 char *name, struct isl_obj obj)
942 struct isl_hash_table_entry *entry;
943 uint32_t name_hash;
944 struct isl_named_obj *named;
946 name_hash = isl_hash_string(isl_hash_init(), name);
947 entry = isl_hash_table_find(ctx, table, name_hash, same_name, name, 1);
948 if (!entry)
949 goto error;
950 if (entry->data) {
951 named = entry->data;
952 free_obj(named->obj);
953 free(name);
954 } else {
955 named = isl_alloc_type(ctx, struct isl_named_obj);
956 if (!named)
957 goto error;
958 named->name = name;
959 entry->data = named;
961 named->obj = obj;
963 return 0;
964 error:
965 free_obj(obj);
966 free(name);
967 return -1;
970 static struct isl_obj stored_obj(struct isl_ctx *ctx,
971 struct isl_hash_table *table, char *name)
973 struct isl_obj obj = { isl_obj_none, NULL };
974 struct isl_hash_table_entry *entry;
975 uint32_t name_hash;
977 name_hash = isl_hash_string(isl_hash_init(), name);
978 entry = isl_hash_table_find(ctx, table, name_hash, same_name, name, 0);
979 if (entry) {
980 struct isl_named_obj *named;
981 named = entry->data;
982 obj = named->obj;
983 } else if (isdigit(name[0]))
984 fprintf(stderr, "unknown identifier '$%s'\n", name);
985 else
986 fprintf(stderr, "unknown identifier '%s'\n", name);
988 free(name);
989 obj.v = obj.type->copy(obj.v);
990 return obj;
993 static int is_subtype(struct isl_obj obj, isl_obj_type super)
995 if (obj.type == super)
996 return 1;
997 if (obj.type == isl_obj_map && super == isl_obj_union_map)
998 return 1;
999 if (obj.type == isl_obj_set && super == isl_obj_union_set)
1000 return 1;
1001 if (obj.type == isl_obj_pw_qpolynomial &&
1002 super == isl_obj_union_pw_qpolynomial)
1003 return 1;
1004 if (obj.type == isl_obj_pw_qpolynomial_fold &&
1005 super == isl_obj_union_pw_qpolynomial_fold)
1006 return 1;
1007 if (obj.type == isl_obj_union_set && isl_union_set_is_empty(obj.v))
1008 return 1;
1009 if (obj.type == isl_obj_list) {
1010 struct isl_list *list = obj.v;
1011 if (list->n == 2 && list->obj[1].type == isl_obj_bool)
1012 return is_subtype(list->obj[0], super);
1014 if (super == isl_obj_str)
1015 return 1;
1016 return 0;
1019 static struct isl_obj obj_at(struct isl_obj obj, int i)
1021 struct isl_list *list = obj.v;
1023 obj = list->obj[i];
1024 obj.v = obj.type->copy(obj.v);
1026 isl_list_free(list);
1028 return obj;
1031 static struct isl_obj convert(isl_ctx *ctx, struct isl_obj obj,
1032 isl_obj_type type)
1034 if (obj.type == type)
1035 return obj;
1036 if (obj.type == isl_obj_map && type == isl_obj_union_map) {
1037 obj.type = isl_obj_union_map;
1038 obj.v = isl_union_map_from_map(obj.v);
1039 return obj;
1041 if (obj.type == isl_obj_set && type == isl_obj_union_set) {
1042 obj.type = isl_obj_union_set;
1043 obj.v = isl_union_set_from_set(obj.v);
1044 return obj;
1046 if (obj.type == isl_obj_pw_qpolynomial &&
1047 type == isl_obj_union_pw_qpolynomial) {
1048 obj.type = isl_obj_union_pw_qpolynomial;
1049 obj.v = isl_union_pw_qpolynomial_from_pw_qpolynomial(obj.v);
1050 return obj;
1052 if (obj.type == isl_obj_pw_qpolynomial_fold &&
1053 type == isl_obj_union_pw_qpolynomial_fold) {
1054 obj.type = isl_obj_union_pw_qpolynomial_fold;
1055 obj.v = isl_union_pw_qpolynomial_fold_from_pw_qpolynomial_fold(obj.v);
1056 return obj;
1058 if (obj.type == isl_obj_union_set && isl_union_set_is_empty(obj.v)) {
1059 if (type == isl_obj_union_map) {
1060 obj.type = isl_obj_union_map;
1061 return obj;
1063 if (type == isl_obj_union_pw_qpolynomial) {
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_zero(dim);
1067 obj.type = isl_obj_union_pw_qpolynomial;
1068 return obj;
1070 if (type == isl_obj_union_pw_qpolynomial_fold) {
1071 isl_dim *dim = isl_union_set_get_dim(obj.v);
1072 isl_union_set_free(obj.v);
1073 obj.v = isl_union_pw_qpolynomial_fold_zero(dim,
1074 isl_fold_list);
1075 obj.type = isl_obj_union_pw_qpolynomial_fold;
1076 return obj;
1079 if (obj.type == isl_obj_list) {
1080 struct isl_list *list = obj.v;
1081 if (list->n == 2 && list->obj[1].type == isl_obj_bool)
1082 return convert(ctx, obj_at(obj, 0), type);
1084 if (type == isl_obj_str) {
1085 isl_str *str;
1086 isl_printer *p;
1087 char *s;
1089 p = isl_printer_to_str(ctx);
1090 if (!p)
1091 goto error;
1092 p = obj.type->print(p, obj.v);
1093 s = isl_printer_get_str(p);
1094 isl_printer_free(p);
1096 str = isl_str_from_string(ctx, s);
1097 if (!str)
1098 goto error;
1099 free_obj(obj);
1100 obj.v = str;
1101 obj.type = isl_obj_str;
1102 return obj;
1105 error:
1106 free_obj(obj);
1107 obj.type = isl_obj_none;
1108 obj.v = NULL;
1109 return obj;
1112 static struct isc_bin_op *read_bin_op_if_available(struct isl_stream *s,
1113 struct isl_obj lhs)
1115 int i;
1116 struct isl_token *tok;
1118 tok = isl_stream_next_token(s);
1119 if (!tok)
1120 return NULL;
1122 for (i = 0; ; ++i) {
1123 if (!bin_ops[i].op)
1124 break;
1125 if (bin_ops[i].op != tok->type)
1126 continue;
1127 if (!is_subtype(lhs, bin_ops[i].lhs))
1128 continue;
1130 isl_token_free(tok);
1131 return &bin_ops[i];
1134 for (i = 0; ; ++i) {
1135 if (!named_bin_ops[i].name)
1136 break;
1137 if (named_bin_ops[i].op.op != tok->type)
1138 continue;
1139 if (!is_subtype(lhs, named_bin_ops[i].op.lhs))
1140 continue;
1142 isl_token_free(tok);
1143 return &named_bin_ops[i].op;
1146 isl_stream_push_token(s, tok);
1148 return NULL;
1151 static struct isc_un_op *read_prefix_un_op_if_available(struct isl_stream *s)
1153 int i;
1154 struct isl_token *tok;
1156 tok = isl_stream_next_token(s);
1157 if (!tok)
1158 return NULL;
1160 for (i = 0; ; ++i) {
1161 if (!named_un_ops[i].name)
1162 break;
1163 if (named_un_ops[i].op.op != tok->type)
1164 continue;
1166 isl_token_free(tok);
1167 return &named_un_ops[i].op;
1170 isl_stream_push_token(s, tok);
1172 return NULL;
1175 static struct isc_un_op *find_matching_un_op(struct isc_un_op *like,
1176 struct isl_obj arg)
1178 int i;
1180 for (i = 0; ; ++i) {
1181 if (!named_un_ops[i].name)
1182 break;
1183 if (named_un_ops[i].op.op != like->op)
1184 continue;
1185 if (!is_subtype(arg, named_un_ops[i].op.arg))
1186 continue;
1188 return &named_un_ops[i].op;
1191 return NULL;
1194 static int is_assign(struct isl_stream *s)
1196 struct isl_token *tok;
1197 struct isl_token *tok2;
1198 int assign;
1200 tok = isl_stream_next_token(s);
1201 if (!tok)
1202 return 0;
1203 if (tok->type != ISL_TOKEN_IDENT) {
1204 isl_stream_push_token(s, tok);
1205 return 0;
1208 tok2 = isl_stream_next_token(s);
1209 if (!tok2) {
1210 isl_stream_push_token(s, tok);
1211 return 0;
1213 assign = tok2->type == ISL_TOKEN_DEF;
1214 isl_stream_push_token(s, tok2);
1215 isl_stream_push_token(s, tok);
1217 return assign;
1220 static struct isl_obj read_obj(struct isl_stream *s,
1221 struct isl_hash_table *table);
1222 static struct isl_obj read_expr(struct isl_stream *s,
1223 struct isl_hash_table *table);
1225 static struct isl_obj read_un_op_expr(struct isl_stream *s,
1226 struct isl_hash_table *table, struct isc_un_op *op)
1228 struct isl_obj obj = { isl_obj_none, NULL };
1230 obj = read_obj(s, table);
1231 if (!obj.v)
1232 goto error;
1234 op = find_matching_un_op(op, obj);
1236 if (!op)
1237 isl_die(s->ctx, isl_error_invalid,
1238 "no such unary operator defined on given operand",
1239 goto error);
1241 obj = convert(s->ctx, obj, op->arg);
1242 obj.v = op->fn(obj.v);
1243 obj.type = op->res;
1245 return obj;
1246 error:
1247 free_obj(obj);
1248 obj.type = isl_obj_none;
1249 obj.v = NULL;
1250 return obj;
1253 static struct isl_obj transitive_closure(struct isl_ctx *ctx, struct isl_obj obj)
1255 struct isl_list *list;
1256 int exact;
1258 if (obj.type != isl_obj_union_map)
1259 obj = convert(ctx, obj, isl_obj_union_map);
1260 isl_assert(ctx, obj.type == isl_obj_union_map, goto error);
1261 list = isl_list_alloc(ctx, 2);
1262 if (!list)
1263 goto error;
1265 list->obj[0].type = isl_obj_union_map;
1266 list->obj[0].v = isl_union_map_transitive_closure(obj.v, &exact);
1267 list->obj[1].type = isl_obj_bool;
1268 list->obj[1].v = exact ? &isl_bool_true : &isl_bool_false;
1269 obj.v = list;
1270 obj.type = isl_obj_list;
1271 if (exact < 0 || !list->obj[0].v)
1272 goto error;
1274 return obj;
1275 error:
1276 free_obj(obj);
1277 obj.type = isl_obj_none;
1278 obj.v = NULL;
1279 return obj;
1282 static struct isl_obj obj_at_index(struct isl_stream *s, struct isl_obj obj)
1284 struct isl_list *list = obj.v;
1285 struct isl_token *tok;
1286 int i;
1288 tok = isl_stream_next_token(s);
1289 if (!tok || tok->type != ISL_TOKEN_VALUE) {
1290 isl_stream_error(s, tok, "expecting index");
1291 if (tok)
1292 isl_stream_push_token(s, tok);
1293 goto error;
1295 i = isl_int_get_si(tok->u.v);
1296 isl_token_free(tok);
1297 isl_assert(s->ctx, i < list->n, goto error);
1298 if (isl_stream_eat(s, ']'))
1299 goto error;
1301 return obj_at(obj, i);
1302 error:
1303 free_obj(obj);
1304 obj.type = isl_obj_none;
1305 obj.v = NULL;
1306 return obj;
1309 static struct isl_obj apply(struct isl_stream *s, __isl_take isl_union_map *umap,
1310 struct isl_hash_table *table)
1312 struct isl_obj obj;
1314 obj = read_expr(s, table);
1315 isl_assert(s->ctx, is_subtype(obj, isl_obj_union_set) ||
1316 is_subtype(obj, isl_obj_union_map), goto error);
1318 if (obj.type == isl_obj_list) {
1319 struct isl_list *list = obj.v;
1320 if (list->n == 2 && list->obj[1].type == isl_obj_bool)
1321 obj = obj_at(obj, 0);
1323 if (obj.type == isl_obj_set)
1324 obj = convert(s->ctx, obj, isl_obj_union_set);
1325 else if (obj.type == isl_obj_map)
1326 obj = convert(s->ctx, obj, isl_obj_union_map);
1327 if (obj.type == isl_obj_union_set) {
1328 obj.v = isl_union_set_apply(obj.v, umap);
1329 } else
1330 obj.v = isl_union_map_apply_range(obj.v, umap);
1331 if (!obj.v)
1332 goto error2;
1334 if (isl_stream_eat(s, ')'))
1335 goto error2;
1337 return obj;
1338 error:
1339 isl_union_map_free(umap);
1340 error2:
1341 free_obj(obj);
1342 obj.type = isl_obj_none;
1343 obj.v = NULL;
1344 return obj;
1347 static struct isl_obj apply_fun(struct isl_stream *s,
1348 struct isl_obj obj, struct isl_hash_table *table)
1350 struct isl_obj arg;
1352 arg = read_expr(s, table);
1353 if (!is_subtype(arg, isl_obj_union_map) &&
1354 !is_subtype(arg, isl_obj_union_set))
1355 isl_die(s->ctx, isl_error_invalid,
1356 "expecting set of map argument", goto error);
1358 if (arg.type == isl_obj_list) {
1359 struct isl_list *list = arg.v;
1360 if (list->n == 2 && list->obj[1].type == isl_obj_bool)
1361 arg = obj_at(arg, 0);
1363 if (arg.type == isl_obj_set)
1364 arg = convert(s->ctx, arg, isl_obj_union_set);
1365 else if (arg.type == isl_obj_map)
1366 arg = convert(s->ctx, arg, isl_obj_union_map);
1367 if (arg.type == isl_obj_union_set) {
1368 arg.v = isl_union_map_from_range(arg.v);
1369 arg.type = isl_obj_union_map;
1371 if (obj.type == isl_obj_union_pw_qpolynomial) {
1372 obj.v = isl_union_map_apply_union_pw_qpolynomial(arg.v, obj.v);
1373 } else {
1374 obj.type = isl_obj_list;
1375 obj.v = union_map_apply_union_pw_qpolynomial_fold(arg.v, obj.v);
1377 if (!obj.v)
1378 goto error2;
1380 if (isl_stream_eat(s, ')'))
1381 goto error2;
1383 return obj;
1384 error:
1385 free_obj(arg);
1386 error2:
1387 free_obj(obj);
1388 obj.type = isl_obj_none;
1389 obj.v = NULL;
1390 return obj;
1393 struct add_vertex_data {
1394 struct isl_list *list;
1395 int i;
1398 static int add_vertex(__isl_take isl_vertex *vertex, void *user)
1400 struct add_vertex_data *data = (struct add_vertex_data *)user;
1401 isl_basic_set *expr;
1403 expr = isl_vertex_get_expr(vertex);
1405 data->list->obj[data->i].type = isl_obj_set;
1406 data->list->obj[data->i].v = isl_set_from_basic_set(expr);
1407 data->i++;
1409 isl_vertex_free(vertex);
1411 return 0;
1414 static int set_vertices(__isl_take isl_set *set, void *user)
1416 isl_ctx *ctx;
1417 isl_basic_set *hull;
1418 isl_vertices *vertices = NULL;
1419 struct isl_list *list = NULL;
1420 int r;
1421 struct add_vertex_data *data = (struct add_vertex_data *)user;
1423 set = isl_set_remove_divs(set);
1424 hull = isl_set_convex_hull(set);
1425 vertices = isl_basic_set_compute_vertices(hull);
1426 isl_basic_set_free(hull);
1428 list = data->list;
1430 ctx = isl_vertices_get_ctx(vertices);
1431 data->list = isl_list_alloc(ctx, isl_vertices_get_n_vertices(vertices));
1432 if (!data->list)
1433 goto error;
1435 data->i = 0;
1436 r = isl_vertices_foreach_vertex(vertices, &add_vertex, user);
1438 data->list = isl_list_concat(list, data->list);
1440 isl_vertices_free(vertices);
1442 return r;
1443 error:
1444 data->list = list;
1445 isl_vertices_free(vertices);
1446 return -1;
1449 static struct isl_obj vertices(struct isl_stream *s,
1450 struct isl_hash_table *table)
1452 isl_ctx *ctx;
1453 struct isl_obj obj;
1454 struct isl_list *list = NULL;
1455 isl_union_set *uset;
1456 struct add_vertex_data data = { NULL };
1458 obj = read_expr(s, table);
1459 obj = convert(s->ctx, obj, isl_obj_union_set);
1460 isl_assert(s->ctx, obj.type == isl_obj_union_set, goto error);
1461 uset = obj.v;
1462 obj.v = NULL;
1464 ctx = isl_union_set_get_ctx(uset);
1465 list = isl_list_alloc(ctx, 0);
1466 if (!list)
1467 goto error;
1469 data.list = list;
1471 if (isl_union_set_foreach_set(uset, &set_vertices, &data) < 0)
1472 goto error;
1474 isl_union_set_free(uset);
1476 obj.type = isl_obj_list;
1477 obj.v = data.list;
1479 return obj;
1480 error:
1481 isl_union_set_free(uset);
1482 isl_list_free(data.list);
1483 free_obj(obj);
1484 obj.type = isl_obj_none;
1485 obj.v = NULL;
1486 return obj;
1489 static struct isl_obj type_of(struct isl_stream *s,
1490 struct isl_hash_table *table)
1492 isl_ctx *ctx;
1493 struct isl_obj obj;
1494 const char *type = "unknown";
1496 obj = read_expr(s, table);
1498 if (obj.type == isl_obj_map ||
1499 obj.type == isl_obj_union_map)
1500 type = "map";
1501 if (obj.type == isl_obj_set ||
1502 obj.type == isl_obj_union_set)
1503 type = "set";
1504 if (obj.type == isl_obj_pw_qpolynomial ||
1505 obj.type == isl_obj_union_pw_qpolynomial)
1506 type = "piecewise quasipolynomial";
1507 if (obj.type == isl_obj_pw_qpolynomial_fold ||
1508 obj.type == isl_obj_union_pw_qpolynomial_fold)
1509 type = "piecewise quasipolynomial fold";
1510 if (obj.type == isl_obj_list)
1511 type = "list";
1512 if (obj.type == isl_obj_bool)
1513 type = "boolean";
1514 if (obj.type == isl_obj_str)
1515 type = "string";
1516 if (obj.type == isl_obj_int)
1517 type = "int";
1519 free_obj(obj);
1520 obj.type = isl_obj_str;
1521 obj.v = isl_str_from_string(s->ctx, strdup(type));
1523 return obj;
1526 static __isl_give isl_union_set *read_set(struct isl_stream *s,
1527 struct isl_hash_table *table)
1529 struct isl_obj obj;
1531 obj = read_obj(s, table);
1532 obj = convert(s->ctx, obj, isl_obj_union_set);
1533 isl_assert(s->ctx, obj.type == isl_obj_union_set, goto error);
1534 return obj.v;
1535 error:
1536 free_obj(obj);
1537 return NULL;
1540 static __isl_give isl_union_map *read_map(struct isl_stream *s,
1541 struct isl_hash_table *table)
1543 struct isl_obj obj;
1545 obj = read_obj(s, table);
1546 obj = convert(s->ctx, obj, isl_obj_union_map);
1547 isl_assert(s->ctx, obj.type == isl_obj_union_map, goto error);
1548 return obj.v;
1549 error:
1550 free_obj(obj);
1551 return NULL;
1554 static struct isl_obj last_any(struct isl_stream *s,
1555 struct isl_hash_table *table, __isl_take isl_union_map *must_source,
1556 __isl_take isl_union_map *may_source)
1558 struct isl_obj obj = { isl_obj_none, NULL };
1559 isl_union_map *sink = NULL;
1560 isl_union_map *schedule = NULL;
1561 isl_union_map *may_dep;
1562 isl_union_map *must_dep;
1564 if (isl_stream_eat(s, iscc_op[ISCC_BEFORE]))
1565 goto error;
1567 sink = read_map(s, table);
1568 if (!sink)
1569 goto error;
1571 if (isl_stream_eat(s, iscc_op[ISCC_UNDER]))
1572 goto error;
1574 schedule = read_map(s, table);
1575 if (!schedule)
1576 goto error;
1578 if (isl_union_map_compute_flow(sink, must_source, may_source,
1579 schedule, &must_dep, &may_dep,
1580 NULL, NULL) < 0)
1581 return obj;
1583 obj.type = isl_obj_union_map;
1584 obj.v = isl_union_map_union(must_dep, may_dep);
1586 return obj;
1587 error:
1588 isl_union_map_free(may_source);
1589 isl_union_map_free(must_source);
1590 isl_union_map_free(sink);
1591 isl_union_map_free(schedule);
1592 free_obj(obj);
1593 obj.type = isl_obj_none;
1594 obj.v = NULL;
1595 return obj;
1598 static struct isl_obj any(struct isl_stream *s, struct isl_hash_table *table)
1600 struct isl_obj obj = { isl_obj_none, NULL };
1601 isl_union_map *must_source = NULL;
1602 isl_union_map *may_source = NULL;
1603 isl_union_map *sink = NULL;
1604 isl_union_map *schedule = NULL;
1605 isl_union_map *may_dep;
1607 may_source = read_map(s, table);
1608 if (!may_source)
1609 goto error;
1611 if (isl_stream_eat_if_available(s, iscc_op[ISCC_LAST])) {
1612 must_source = read_map(s, table);
1613 if (!must_source)
1614 goto error;
1615 return last_any(s, table, must_source, may_source);
1618 if (isl_stream_eat(s, iscc_op[ISCC_BEFORE]))
1619 goto error;
1621 sink = read_map(s, table);
1622 if (!sink)
1623 goto error;
1625 if (isl_stream_eat(s, iscc_op[ISCC_UNDER]))
1626 goto error;
1628 schedule = read_map(s, table);
1629 if (!schedule)
1630 goto error;
1632 must_source = isl_union_map_empty(isl_union_map_get_dim(sink));
1633 if (isl_union_map_compute_flow(sink, must_source, may_source,
1634 schedule, NULL, &may_dep,
1635 NULL, NULL) < 0)
1636 return obj;
1638 obj.type = isl_obj_union_map;
1639 obj.v = may_dep;
1641 return obj;
1642 error:
1643 isl_union_map_free(may_source);
1644 isl_union_map_free(must_source);
1645 isl_union_map_free(sink);
1646 isl_union_map_free(schedule);
1647 free_obj(obj);
1648 obj.type = isl_obj_none;
1649 obj.v = NULL;
1650 return obj;
1653 static struct isl_obj last(struct isl_stream *s, struct isl_hash_table *table)
1655 struct isl_obj obj = { isl_obj_none, NULL };
1656 struct isl_list *list = NULL;
1657 isl_union_map *must_source = NULL;
1658 isl_union_map *may_source = NULL;
1659 isl_union_map *sink = NULL;
1660 isl_union_map *schedule = NULL;
1661 isl_union_map *must_dep;
1662 isl_union_map *must_no_source;
1664 must_source = read_map(s, table);
1665 if (!must_source)
1666 goto error;
1668 if (isl_stream_eat_if_available(s, iscc_op[ISCC_ANY])) {
1669 may_source = read_map(s, table);
1670 if (!may_source)
1671 goto error;
1672 return last_any(s, table, must_source, may_source);
1675 list = isl_list_alloc(s->ctx, 2);
1676 if (!list)
1677 goto error;
1679 if (isl_stream_eat(s, iscc_op[ISCC_BEFORE]))
1680 goto error;
1682 sink = read_map(s, table);
1683 if (!sink)
1684 goto error;
1686 if (isl_stream_eat(s, iscc_op[ISCC_UNDER]))
1687 goto error;
1689 schedule = read_map(s, table);
1690 if (!schedule)
1691 goto error;
1693 may_source = isl_union_map_empty(isl_union_map_get_dim(sink));
1694 if (isl_union_map_compute_flow(sink, must_source, may_source,
1695 schedule, &must_dep, NULL,
1696 &must_no_source, NULL) < 0) {
1697 isl_list_free(list);
1698 return obj;
1701 list->obj[0].type = isl_obj_union_map;
1702 list->obj[0].v = must_dep;
1703 list->obj[1].type = isl_obj_union_map;
1704 list->obj[1].v = must_no_source;
1706 obj.v = list;
1707 obj.type = isl_obj_list;
1709 return obj;
1710 error:
1711 isl_list_free(list);
1712 isl_union_map_free(may_source);
1713 isl_union_map_free(must_source);
1714 isl_union_map_free(sink);
1715 isl_union_map_free(schedule);
1716 free_obj(obj);
1717 obj.type = isl_obj_none;
1718 obj.v = NULL;
1719 return obj;
1722 static __isl_give isl_schedule *get_schedule(struct isl_stream *s,
1723 struct isl_hash_table *table)
1725 isl_union_set *domain;
1726 isl_union_map *validity;
1727 isl_union_map *proximity;
1729 domain = read_set(s, table);
1730 if (!domain)
1731 return NULL;
1733 validity = isl_union_map_empty(isl_union_set_get_dim(domain));
1734 proximity = isl_union_map_empty(isl_union_set_get_dim(domain));
1736 for (;;) {
1737 isl_union_map *umap;
1738 if (isl_stream_eat_if_available(s, iscc_op[ISCC_RESPECTING])) {
1739 umap = read_map(s, table);
1740 validity = isl_union_map_union(validity, umap);
1741 } else if (isl_stream_eat_if_available(s, iscc_op[ISCC_MINIMIZING])) {
1742 umap = read_map(s, table);
1743 proximity = isl_union_map_union(proximity, umap);
1744 } else
1745 break;
1748 return isl_union_set_compute_schedule(domain, validity, proximity);
1751 static struct isl_obj schedule(struct isl_stream *s,
1752 struct isl_hash_table *table)
1754 struct isl_obj obj = { isl_obj_none, NULL };
1755 isl_schedule *schedule;
1757 schedule = get_schedule(s, table);
1759 obj.v = isl_schedule_get_map(schedule);
1760 obj.type = isl_obj_union_map;
1762 isl_schedule_free(schedule);
1764 return obj;
1767 static struct isl_obj band_list_to_obj_list(__isl_take isl_band_list *bands);
1769 static struct isl_obj band_to_obj_list(__isl_take isl_band *band)
1771 struct isl_obj obj = { isl_obj_none, NULL };
1772 isl_ctx *ctx = isl_band_get_ctx(band);
1773 struct isl_list *list;
1775 list = isl_list_alloc(ctx, 2);
1776 if (!list)
1777 goto error;
1779 obj.v = list;
1780 obj.type = isl_obj_list;
1782 list->obj[0].type = isl_obj_union_map;
1783 list->obj[0].v = isl_band_get_partial_schedule(band);
1785 if (isl_band_has_children(band)) {
1786 isl_band_list *children;
1788 children = isl_band_get_children(band);
1789 list->obj[1] = band_list_to_obj_list(children);
1790 } else {
1791 list->obj[1].type = isl_obj_list;
1792 list->obj[1].v = isl_list_alloc(ctx, 0);
1795 if (!list->obj[0].v || !list->obj[1].v)
1796 goto error;
1798 isl_band_free(band);
1800 return obj;
1801 error:
1802 isl_band_free(band);
1803 free_obj(obj);
1804 obj.type = isl_obj_none;
1805 obj.v = NULL;
1806 return obj;
1809 static struct isl_obj band_list_to_obj_list(__isl_take isl_band_list *bands)
1811 struct isl_obj obj = { isl_obj_none, NULL };
1812 isl_ctx *ctx = isl_band_list_get_ctx(bands);
1813 struct isl_list *list;
1814 int i, n;
1816 n = isl_band_list_n_band(bands);
1817 list = isl_list_alloc(ctx, n);
1818 if (!list)
1819 goto error;
1821 obj.v = list;
1822 obj.type = isl_obj_list;
1824 for (i = 0; i < n; ++i) {
1825 isl_band *band;
1827 band = isl_band_list_get_band(bands, i);
1828 list->obj[i] = band_to_obj_list(band);
1829 if (!list->obj[i].v)
1830 goto error;
1833 isl_band_list_free(bands);
1835 return obj;
1836 error:
1837 isl_band_list_free(bands);
1838 free_obj(obj);
1839 obj.type = isl_obj_none;
1840 obj.v = NULL;
1841 return obj;
1844 static struct isl_obj schedule_forest(struct isl_stream *s,
1845 struct isl_hash_table *table)
1847 struct isl_obj obj = { isl_obj_none, NULL };
1848 isl_schedule *schedule;
1849 isl_band_list *roots;
1851 schedule = get_schedule(s, table);
1852 if (!schedule)
1853 return obj;
1855 roots = isl_schedule_get_band_forest(schedule);
1856 isl_schedule_free(schedule);
1858 return band_list_to_obj_list(roots);
1861 static struct isl_obj power(struct isl_stream *s, struct isl_obj obj)
1863 struct isl_token *tok;
1865 if (isl_stream_eat_if_available(s, '+'))
1866 return transitive_closure(s->ctx, obj);
1868 tok = isl_stream_next_token(s);
1869 if (!tok || tok->type != ISL_TOKEN_VALUE || isl_int_cmp_si(tok->u.v, -1)) {
1870 isl_stream_error(s, tok, "expecting -1");
1871 if (tok)
1872 isl_stream_push_token(s, tok);
1873 goto error;
1875 isl_token_free(tok);
1876 isl_assert(s->ctx, is_subtype(obj, isl_obj_union_map), goto error);
1877 if (obj.type != isl_obj_union_map)
1878 obj = convert(s->ctx, obj, isl_obj_union_map);
1880 obj.v = isl_union_map_reverse(obj.v);
1881 if (!obj.v)
1882 goto error;
1884 return obj;
1885 error:
1886 free_obj(obj);
1887 obj.type = isl_obj_none;
1888 obj.v = NULL;
1889 return obj;
1892 static struct isl_obj read_from_file(struct isl_stream *s)
1894 struct isl_obj obj;
1895 struct isl_token *tok;
1896 struct isl_stream *s_file;
1897 struct iscc_options *options;
1898 FILE *file;
1900 tok = isl_stream_next_token(s);
1901 if (!tok || tok->type != ISL_TOKEN_STRING) {
1902 isl_stream_error(s, tok, "expecting filename");
1903 isl_token_free(tok);
1904 goto error;
1907 options = isl_ctx_peek_iscc_options(s->ctx);
1908 if (!options || !options->io) {
1909 isl_token_free(tok);
1910 isl_die(s->ctx, isl_error_invalid,
1911 "read operation not allowed", goto error);
1914 file = fopen(tok->u.s, "r");
1915 isl_token_free(tok);
1916 isl_assert(s->ctx, file, goto error);
1918 s_file = isl_stream_new_file(s->ctx, file);
1919 if (!s_file) {
1920 fclose(file);
1921 goto error;
1924 obj = isl_stream_read_obj(s_file);
1926 isl_stream_free(s_file);
1927 fclose(file);
1929 return obj;
1930 error:
1931 obj.type = isl_obj_none;
1932 obj.v = NULL;
1933 return obj;
1936 static struct isl_obj write_to_file(struct isl_stream *s,
1937 struct isl_hash_table *table)
1939 struct isl_obj obj;
1940 struct isl_token *tok;
1941 struct isl_stream *s_file;
1942 struct iscc_options *options;
1943 FILE *file;
1944 isl_printer *p;
1946 tok = isl_stream_next_token(s);
1947 if (!tok || tok->type != ISL_TOKEN_STRING) {
1948 isl_stream_error(s, tok, "expecting filename");
1949 isl_token_free(tok);
1950 goto error;
1953 obj = read_expr(s, table);
1955 options = isl_ctx_peek_iscc_options(s->ctx);
1956 if (!options || !options->io) {
1957 isl_token_free(tok);
1958 isl_die(s->ctx, isl_error_invalid,
1959 "write operation not allowed", goto error);
1962 file = fopen(tok->u.s, "w");
1963 isl_token_free(tok);
1964 if (!file)
1965 isl_die(s->ctx, isl_error_unknown,
1966 "could not open file for writing", goto error);
1968 p = isl_printer_to_file(s->ctx, file);
1969 p = isl_printer_set_output_format(p, options->format);
1970 p = obj.type->print(p, obj.v);
1971 p = isl_printer_end_line(p);
1972 isl_printer_free(p);
1974 fclose(file);
1975 error:
1976 free_obj(obj);
1977 obj.type = isl_obj_none;
1978 obj.v = NULL;
1979 return obj;
1982 static struct isl_obj read_string_if_available(struct isl_stream *s)
1984 struct isl_token *tok;
1985 struct isl_obj obj = { isl_obj_none, NULL };
1987 tok = isl_stream_next_token(s);
1988 if (!tok)
1989 return obj;
1990 if (tok->type == ISL_TOKEN_STRING) {
1991 isl_str *str;
1992 str = isl_str_alloc(s->ctx);
1993 if (!str)
1994 goto error;
1995 str->s = strdup(tok->u.s);
1996 isl_token_free(tok);
1997 obj.v = str;
1998 obj.type = isl_obj_str;
1999 } else
2000 isl_stream_push_token(s, tok);
2001 return obj;
2002 error:
2003 isl_token_free(tok);
2004 return obj;
2007 static struct isl_obj read_bool_if_available(struct isl_stream *s)
2009 struct isl_token *tok;
2010 struct isl_obj obj = { isl_obj_none, NULL };
2012 tok = isl_stream_next_token(s);
2013 if (!tok)
2014 return obj;
2015 if (tok->type == ISL_TOKEN_FALSE || tok->type == ISL_TOKEN_TRUE) {
2016 int is_true = tok->type == ISL_TOKEN_TRUE;
2017 isl_token_free(tok);
2018 obj.v = is_true ? &isl_bool_true : &isl_bool_false;
2019 obj.type = isl_obj_bool;
2020 } else
2021 isl_stream_push_token(s, tok);
2022 return obj;
2023 error:
2024 isl_token_free(tok);
2025 return obj;
2028 static __isl_give char *read_ident(struct isl_stream *s)
2030 char *name;
2031 struct isl_token *tok, *tok2;
2033 name = isl_stream_read_ident_if_available(s);
2034 if (name)
2035 return name;
2037 tok = isl_stream_next_token(s);
2038 if (!tok)
2039 return NULL;
2040 if (tok->type != '$') {
2041 isl_stream_push_token(s, tok);
2042 return NULL;
2044 tok2 = isl_stream_next_token(s);
2045 if (!tok2 || tok2->type != ISL_TOKEN_VALUE) {
2046 if (tok2)
2047 isl_stream_push_token(s, tok2);
2048 isl_stream_push_token(s, tok);
2049 return NULL;
2052 name = isl_int_get_str(tok2->u.v);
2053 isl_token_free(tok);
2054 isl_token_free(tok2);
2056 return name;
2059 static struct isl_obj read_list(struct isl_stream *s,
2060 struct isl_hash_table *table, struct isl_obj obj)
2062 struct isl_list *list;
2064 list = isl_list_alloc(s->ctx, 2);
2065 if (!list)
2066 goto error;
2067 list->obj[0] = obj;
2068 list->obj[1] = read_obj(s, table);
2069 obj.v = list;
2070 obj.type = isl_obj_list;
2072 if (!list->obj[1].v)
2073 goto error;
2075 while (isl_stream_eat_if_available(s, ',')) {
2076 obj.v = list = isl_list_add_obj(list, read_obj(s, table));
2077 if (!obj.v)
2078 goto error;
2081 return obj;
2082 error:
2083 free_obj(obj);
2084 obj.type = isl_obj_none;
2085 obj.v = NULL;
2086 return obj;
2089 static struct isl_obj read_obj(struct isl_stream *s,
2090 struct isl_hash_table *table)
2092 struct isl_obj obj = { isl_obj_none, NULL };
2093 char *name = NULL;
2094 struct isc_un_op *op = NULL;
2096 obj = read_string_if_available(s);
2097 if (obj.v)
2098 return obj;
2099 obj = read_bool_if_available(s);
2100 if (obj.v)
2101 return obj;
2102 if (isl_stream_eat_if_available(s, '(')) {
2103 if (isl_stream_next_token_is(s, ')')) {
2104 obj.type = isl_obj_list;
2105 obj.v = isl_list_alloc(s->ctx, 0);
2106 } else {
2107 obj = read_expr(s, table);
2108 if (obj.v && isl_stream_eat_if_available(s, ','))
2109 obj = read_list(s, table, obj);
2111 if (!obj.v || isl_stream_eat(s, ')'))
2112 goto error;
2113 } else {
2114 op = read_prefix_un_op_if_available(s);
2115 if (op)
2116 return read_un_op_expr(s, table, op);
2118 if (isl_stream_eat_if_available(s, iscc_op[ISCC_READ]))
2119 return read_from_file(s);
2120 if (isl_stream_eat_if_available(s, iscc_op[ISCC_WRITE]))
2121 return write_to_file(s, table);
2122 if (isl_stream_eat_if_available(s, iscc_op[ISCC_VERTICES]))
2123 return vertices(s, table);
2124 if (isl_stream_eat_if_available(s, iscc_op[ISCC_ANY]))
2125 return any(s, table);
2126 if (isl_stream_eat_if_available(s, iscc_op[ISCC_LAST]))
2127 return last(s, table);
2128 if (isl_stream_eat_if_available(s, iscc_op[ISCC_SCHEDULE]))
2129 return schedule(s, table);
2130 if (isl_stream_eat_if_available(s, iscc_op[ISCC_SCHEDULE_FOREST]))
2131 return schedule_forest(s, table);
2132 if (isl_stream_eat_if_available(s, iscc_op[ISCC_TYPEOF]))
2133 return type_of(s, table);
2135 name = read_ident(s);
2136 if (name)
2137 obj = stored_obj(s->ctx, table, name);
2138 else
2139 obj = isl_stream_read_obj(s);
2140 if (!obj.v)
2141 goto error;
2144 if (isl_stream_eat_if_available(s, '^'))
2145 obj = power(s, obj);
2146 else if (obj.type == isl_obj_list && isl_stream_eat_if_available(s, '['))
2147 obj = obj_at_index(s, obj);
2148 else if (is_subtype(obj, isl_obj_union_map) &&
2149 isl_stream_eat_if_available(s, '(')) {
2150 obj = convert(s->ctx, obj, isl_obj_union_map);
2151 obj = apply(s, obj.v, table);
2152 } else if (is_subtype(obj, isl_obj_union_pw_qpolynomial) &&
2153 isl_stream_eat_if_available(s, '(')) {
2154 obj = convert(s->ctx, obj, isl_obj_union_pw_qpolynomial);
2155 obj = apply_fun(s, obj, table);
2156 } else if (is_subtype(obj, isl_obj_union_pw_qpolynomial_fold) &&
2157 isl_stream_eat_if_available(s, '(')) {
2158 obj = convert(s->ctx, obj, isl_obj_union_pw_qpolynomial_fold);
2159 obj = apply_fun(s, obj, table);
2162 return obj;
2163 error:
2164 free_obj(obj);
2165 obj.type = isl_obj_none;
2166 obj.v = NULL;
2167 return obj;
2170 static struct isc_bin_op *find_matching_bin_op(struct isc_bin_op *like,
2171 struct isl_obj lhs, struct isl_obj rhs)
2173 int i;
2175 for (i = 0; ; ++i) {
2176 if (!bin_ops[i].op)
2177 break;
2178 if (bin_ops[i].op != like->op)
2179 continue;
2180 if (!is_subtype(lhs, bin_ops[i].lhs))
2181 continue;
2182 if (!is_subtype(rhs, bin_ops[i].rhs))
2183 continue;
2185 return &bin_ops[i];
2188 for (i = 0; ; ++i) {
2189 if (!named_bin_ops[i].name)
2190 break;
2191 if (named_bin_ops[i].op.op != like->op)
2192 continue;
2193 if (!is_subtype(lhs, named_bin_ops[i].op.lhs))
2194 continue;
2195 if (!is_subtype(rhs, named_bin_ops[i].op.rhs))
2196 continue;
2198 return &named_bin_ops[i].op;
2201 return NULL;
2204 static int next_is_neg_int(struct isl_stream *s)
2206 struct isl_token *tok;
2207 int ret;
2209 tok = isl_stream_next_token(s);
2210 ret = tok && tok->type == ISL_TOKEN_VALUE && isl_int_is_neg(tok->u.v);
2211 isl_stream_push_token(s, tok);
2213 return ret;
2216 static struct isl_obj read_expr(struct isl_stream *s,
2217 struct isl_hash_table *table)
2219 struct isl_obj obj = { isl_obj_none, NULL };
2220 struct isl_obj right_obj = { isl_obj_none, NULL };
2222 obj = read_obj(s, table);
2223 for (; obj.v;) {
2224 struct isc_bin_op *op = NULL;
2226 op = read_bin_op_if_available(s, obj);
2227 if (!op)
2228 break;
2230 right_obj = read_obj(s, table);
2232 op = find_matching_bin_op(op, obj, right_obj);
2234 if (!op)
2235 isl_die(s->ctx, isl_error_invalid,
2236 "no such binary operator defined on given operands",
2237 goto error);
2239 obj = convert(s->ctx, obj, op->lhs);
2240 right_obj = convert(s->ctx, right_obj, op->rhs);
2241 obj.v = op->fn(obj.v, right_obj.v);
2242 obj.type = op->res;
2245 if (obj.type == isl_obj_int && next_is_neg_int(s)) {
2246 right_obj = read_obj(s, table);
2247 obj.v = isl_int_obj_add(obj.v, right_obj.v);
2250 return obj;
2251 error:
2252 free_obj(right_obj);
2253 free_obj(obj);
2254 obj.type = isl_obj_none;
2255 obj.v = NULL;
2256 return obj;
2259 static __isl_give isl_printer *source_file(struct isl_stream *s,
2260 struct isl_hash_table *table, __isl_take isl_printer *p);
2262 static __isl_give isl_printer *read_line(struct isl_stream *s,
2263 struct isl_hash_table *table, __isl_take isl_printer *p, int tty)
2265 struct isl_obj obj = { isl_obj_none, NULL };
2266 char *lhs = NULL;
2267 int assign = 0;
2268 int only_print = 0;
2269 struct isc_bin_op *op = NULL;
2270 char buf[30];
2272 if (!p)
2273 return NULL;
2274 if (isl_stream_is_empty(s))
2275 return p;
2277 if (isl_stream_eat_if_available(s, iscc_op[ISCC_SOURCE]))
2278 return source_file(s, table, p);
2280 assign = is_assign(s);
2281 if (assign) {
2282 lhs = isl_stream_read_ident_if_available(s);
2283 if (isl_stream_eat(s, ISL_TOKEN_DEF))
2284 goto error;
2285 } else if (isl_stream_eat_if_available(s, iscc_op[ISCC_PRINT]))
2286 only_print = 1;
2287 else if (!tty)
2288 only_print = 1;
2290 obj = read_expr(s, table);
2291 if (isl_ctx_last_error(s->ctx) == isl_error_abort) {
2292 fprintf(stderr, "Interrupted\n");
2293 isl_ctx_reset_error(s->ctx);
2295 if (isl_stream_eat(s, ';'))
2296 goto error;
2298 if (only_print) {
2299 p = obj.type->print(p, obj.v);
2300 p = isl_printer_end_line(p);
2301 free_obj(obj);
2302 return p;
2304 if (!assign && obj.type != isl_obj_none && obj.v != NULL) {
2305 static int count = 0;
2306 snprintf(buf, sizeof(buf), "$%d", count++);
2307 lhs = strdup(buf + 1);
2309 p = isl_printer_print_str(p, buf);
2310 p = isl_printer_print_str(p, " := ");
2311 p = obj.type->print(p, obj.v);
2312 p = isl_printer_end_line(p);
2314 if (lhs && do_assign(s->ctx, table, lhs, obj))
2315 return p;
2317 return p;
2318 error:
2319 isl_stream_flush_tokens(s);
2320 isl_stream_skip_line(s);
2321 free(lhs);
2322 free_obj(obj);
2323 return p;
2326 int free_cb(void **entry, void *user)
2328 struct isl_named_obj *named = *entry;
2330 free_obj(named->obj);
2331 free(named->name);
2332 free(named);
2334 return 0;
2337 static void register_named_ops(struct isl_stream *s)
2339 int i;
2341 for (i = 0; i < ISCC_N_OP; ++i) {
2342 iscc_op[i] = isl_stream_register_keyword(s, op_name[i]);
2343 assert(iscc_op[i] != ISL_TOKEN_ERROR);
2346 for (i = 0; ; ++i) {
2347 if (!named_un_ops[i].name)
2348 break;
2349 named_un_ops[i].op.op = isl_stream_register_keyword(s,
2350 named_un_ops[i].name);
2351 assert(named_un_ops[i].op.op != ISL_TOKEN_ERROR);
2354 for (i = 0; ; ++i) {
2355 if (!named_bin_ops[i].name)
2356 break;
2357 named_bin_ops[i].op.op = isl_stream_register_keyword(s,
2358 named_bin_ops[i].name);
2359 assert(named_bin_ops[i].op.op != ISL_TOKEN_ERROR);
2363 static __isl_give isl_printer *source_file(struct isl_stream *s,
2364 struct isl_hash_table *table, __isl_take isl_printer *p)
2366 struct isl_token *tok;
2367 struct isl_stream *s_file;
2368 FILE *file;
2370 tok = isl_stream_next_token(s);
2371 if (!tok || tok->type != ISL_TOKEN_STRING) {
2372 isl_stream_error(s, tok, "expecting filename");
2373 isl_token_free(tok);
2374 return p;
2377 file = fopen(tok->u.s, "r");
2378 isl_token_free(tok);
2379 isl_assert(s->ctx, file, return p);
2381 s_file = isl_stream_new_file(s->ctx, file);
2382 if (!s_file) {
2383 fclose(file);
2384 return p;
2387 register_named_ops(s_file);
2389 while (!s_file->eof)
2390 p = read_line(s_file, table, p, 0);
2392 isl_stream_free(s_file);
2393 fclose(file);
2395 isl_stream_eat(s, ';');
2397 return p;
2400 int main(int argc, char **argv)
2402 struct isl_ctx *ctx;
2403 struct isl_stream *s;
2404 struct isl_hash_table *table;
2405 struct iscc_options *options;
2406 isl_printer *p;
2407 int tty = isatty(0);
2409 options = iscc_options_new_with_defaults();
2410 assert(options);
2411 argc = iscc_options_parse(options, argc, argv, ISL_ARG_ALL);
2413 ctx = isl_ctx_alloc_with_options(iscc_options_arg, options);
2414 s = isl_stream_new_file(ctx, stdin);
2415 assert(s);
2416 table = isl_hash_table_alloc(ctx, 10);
2417 assert(table);
2418 p = isl_printer_to_file(ctx, stdout);
2419 p = isl_printer_set_output_format(p, options->format);
2420 assert(p);
2422 register_named_ops(s);
2424 install_signal_handler(ctx);
2426 while (p && !s->eof) {
2427 isl_ctx_resume(ctx);
2428 p = read_line(s, table, p, tty);
2431 remove_signal_handler(ctx);
2433 isl_printer_free(p);
2434 isl_hash_table_foreach(ctx, table, free_cb, NULL);
2435 isl_hash_table_free(ctx, table);
2436 isl_stream_free(s);
2437 isl_ctx_free(ctx);
2439 return 0;