update isl for isl_stream_read_obj returning isl_obj_val instead of isl_obj_int
[barvinok.git] / iscc.c
blob4776a2a5a5e400cec3b4fc320839d2439009bd99
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/set.h>
9 #include <isl/map.h>
10 #include <isl/vertices.h>
11 #include <isl/flow.h>
12 #include <isl/band.h>
13 #include <isl/schedule.h>
14 #include <isl/ast_build.h>
15 #include <isl_obj_list.h>
16 #include <isl_obj_str.h>
17 #include <barvinok/isl.h>
18 #include <barvinok/options.h>
19 #include "lattice_width.h"
21 #include "config.h"
23 #ifdef HAVE_SIGACTION
24 #include <signal.h>
26 static isl_ctx *main_ctx;
28 static void handler(int signum)
30 if (isl_ctx_aborted(main_ctx))
31 exit(EXIT_FAILURE);
32 isl_ctx_abort(main_ctx);
35 static struct sigaction sa_old;
37 static void install_signal_handler(isl_ctx *ctx)
39 struct sigaction sa;
41 main_ctx = ctx;
43 memset(&sa, 0, sizeof(struct sigaction));
44 sa.sa_handler = &handler;
45 sa.sa_flags = SA_RESTART;
46 sigaction(SIGINT, &sa, &sa_old);
49 static void remove_signal_handler(isl_ctx *ctx)
51 sigaction(SIGINT, &sa_old, NULL);
54 #else
56 static void install_signal_handler(isl_ctx *ctx)
60 static void remove_signal_handler(isl_ctx *ctx)
64 #endif
66 #ifdef HAVE_PET
67 #include <pet.h>
68 #else
69 struct pet_options;
70 int pet_options_set_autodetect(isl_ctx *ctx, int val)
72 return -1;
74 #endif
76 static int isl_bool_false = 0;
77 static int isl_bool_true = 1;
78 static int isl_bool_error = -1;
80 enum iscc_op { ISCC_READ, ISCC_WRITE, ISCC_SOURCE, ISCC_VERTICES,
81 ISCC_LAST, ISCC_ANY, ISCC_BEFORE, ISCC_UNDER,
82 ISCC_SCHEDULE, ISCC_SCHEDULE_FOREST,
83 ISCC_MINIMIZING, ISCC_RESPECTING,
84 ISCC_CODEGEN, ISCC_USING,
85 ISCC_TYPEOF, ISCC_PRINT, ISCC_ASSERT,
86 ISCC_N_OP };
87 static const char *op_name[ISCC_N_OP] = {
88 [ISCC_ASSERT] = "assert",
89 [ISCC_READ] = "read",
90 [ISCC_WRITE] = "write",
91 [ISCC_PRINT] = "print",
92 [ISCC_SOURCE] = "source",
93 [ISCC_VERTICES] = "vertices",
94 [ISCC_LAST] = "last",
95 [ISCC_ANY] = "any",
96 [ISCC_BEFORE] = "before",
97 [ISCC_UNDER] = "under",
98 [ISCC_SCHEDULE] = "schedule",
99 [ISCC_SCHEDULE_FOREST] = "schedule_forest",
100 [ISCC_MINIMIZING] = "minimizing",
101 [ISCC_RESPECTING] = "respecting",
102 [ISCC_CODEGEN] = "codegen",
103 [ISCC_USING] = "using",
104 [ISCC_TYPEOF] = "typeof"
106 static enum isl_token_type iscc_op[ISCC_N_OP];
108 struct isl_arg_choice iscc_format[] = {
109 {"isl", ISL_FORMAT_ISL},
110 {"omega", ISL_FORMAT_OMEGA},
111 {"polylib", ISL_FORMAT_POLYLIB},
112 {"ext-polylib", ISL_FORMAT_EXT_POLYLIB},
113 {"latex", ISL_FORMAT_LATEX},
114 {"C", ISL_FORMAT_C},
118 struct iscc_options {
119 struct barvinok_options *barvinok;
120 struct pet_options *pet;
121 unsigned format;
122 int io;
125 ISL_ARGS_START(struct iscc_options, iscc_options_args)
126 ISL_ARG_CHILD(struct iscc_options, barvinok, "barvinok", &barvinok_options_args,
127 "barvinok options")
128 #ifdef HAVE_PET
129 ISL_ARG_CHILD(struct iscc_options, pet, "pet", &pet_options_args, "pet options")
130 #endif
131 ISL_ARG_CHOICE(struct iscc_options, format, 0, "format", \
132 iscc_format, ISL_FORMAT_ISL, "output format")
133 ISL_ARG_BOOL(struct iscc_options, io, 0, "io", 1,
134 "allow read and write operations")
135 ISL_ARGS_END
137 ISL_ARG_DEF(iscc_options, struct iscc_options, iscc_options_args)
138 ISL_ARG_CTX_DEF(iscc_options, struct iscc_options, iscc_options_args)
140 static void *isl_obj_bool_copy(void *v)
142 return v;
145 static void isl_obj_bool_free(void *v)
149 static __isl_give isl_printer *isl_obj_bool_print(__isl_take isl_printer *p,
150 void *v)
152 if (v == &isl_bool_true)
153 return isl_printer_print_str(p, "True");
154 else if (v == &isl_bool_false)
155 return isl_printer_print_str(p, "False");
156 else
157 return isl_printer_print_str(p, "Error");
160 static void *isl_obj_bool_add(void *v1, void *v2)
162 return v1;
165 struct isl_obj_vtable isl_obj_bool_vtable = {
166 isl_obj_bool_copy,
167 isl_obj_bool_add,
168 isl_obj_bool_print,
169 isl_obj_bool_free
171 #define isl_obj_bool (&isl_obj_bool_vtable)
173 int *isl_bool_from_int(int res)
175 return res < 0 ? &isl_bool_error : res ? &isl_bool_true : &isl_bool_false;
178 static int isl_union_map_is_superset(__isl_take isl_union_map *map1,
179 __isl_take isl_union_map *map2)
181 return isl_union_map_is_subset(map2, map1);
183 static int isl_union_set_is_superset(__isl_take isl_union_set *set1,
184 __isl_take isl_union_set *set2)
186 return isl_union_set_is_subset(set2, set1);
189 static int isl_union_map_is_strict_superset(__isl_take isl_union_map *map1,
190 __isl_take isl_union_map *map2)
192 return isl_union_map_is_strict_subset(map2, map1);
194 static int isl_union_set_is_strict_superset(__isl_take isl_union_set *set1,
195 __isl_take isl_union_set *set2)
197 return isl_union_set_is_strict_subset(set2, set1);
200 extern struct isl_obj_vtable isl_obj_list_vtable;
201 #define isl_obj_list (&isl_obj_list_vtable)
203 typedef void *(*isc_bin_op_fn)(void *lhs, void *rhs);
204 typedef int (*isc_bin_test_fn)(void *lhs, void *rhs);
205 struct isc_bin_op {
206 enum isl_token_type op;
207 isl_obj_type lhs;
208 isl_obj_type rhs;
209 isl_obj_type res;
210 union {
211 isc_bin_op_fn fn;
212 isc_bin_test_fn test;
213 } o;
215 struct isc_named_bin_op {
216 char *name;
217 struct isc_bin_op op;
220 struct iscc_at {
221 isl_union_pw_qpolynomial *upwqp;
222 isl_union_pw_qpolynomial *res;
225 static int eval_at(__isl_take isl_point *pnt, void *user)
227 struct iscc_at *at = (struct iscc_at *) user;
228 isl_qpolynomial *qp;
229 isl_set *set;
231 set = isl_set_from_point(isl_point_copy(pnt));
232 qp = isl_union_pw_qpolynomial_eval(
233 isl_union_pw_qpolynomial_copy(at->upwqp), pnt);
235 at->res = isl_union_pw_qpolynomial_add(at->res,
236 isl_union_pw_qpolynomial_from_pw_qpolynomial(
237 isl_pw_qpolynomial_alloc(set, qp)));
239 return 0;
242 __isl_give isl_union_pw_qpolynomial *isl_union_pw_qpolynomial_at(
243 __isl_take isl_union_pw_qpolynomial *upwqp,
244 __isl_take isl_union_set *uset)
246 struct iscc_at at;
248 at.upwqp = upwqp;
249 at.res = isl_union_pw_qpolynomial_zero(isl_union_set_get_space(uset));
251 isl_union_set_foreach_point(uset, eval_at, &at);
253 isl_union_pw_qpolynomial_free(upwqp);
254 isl_union_set_free(uset);
256 return at.res;
259 struct iscc_fold_at {
260 isl_union_pw_qpolynomial_fold *upwf;
261 isl_union_pw_qpolynomial *res;
264 static int eval_fold_at(__isl_take isl_point *pnt, void *user)
266 struct iscc_fold_at *at = (struct iscc_fold_at *) user;
267 isl_qpolynomial *qp;
268 isl_set *set;
270 set = isl_set_from_point(isl_point_copy(pnt));
271 qp = isl_union_pw_qpolynomial_fold_eval(
272 isl_union_pw_qpolynomial_fold_copy(at->upwf), pnt);
274 at->res = isl_union_pw_qpolynomial_add(at->res,
275 isl_union_pw_qpolynomial_from_pw_qpolynomial(
276 isl_pw_qpolynomial_alloc(set, qp)));
278 return 0;
281 __isl_give isl_union_pw_qpolynomial *isl_union_pw_qpolynomial_fold_at(
282 __isl_take isl_union_pw_qpolynomial_fold *upwf,
283 __isl_take isl_union_set *uset)
285 struct iscc_fold_at at;
287 at.upwf = upwf;
288 at.res = isl_union_pw_qpolynomial_zero(isl_union_set_get_space(uset));
290 isl_union_set_foreach_point(uset, eval_fold_at, &at);
292 isl_union_pw_qpolynomial_fold_free(upwf);
293 isl_union_set_free(uset);
295 return at.res;
298 static __isl_give isl_union_pw_qpolynomial_fold *union_pw_qpolynomial_add_union_pw_qpolynomial_fold(
299 __isl_take isl_union_pw_qpolynomial *upwqp,
300 __isl_take isl_union_pw_qpolynomial_fold *upwf)
302 return isl_union_pw_qpolynomial_fold_add_union_pw_qpolynomial(upwf,
303 upwqp);
306 static __isl_give struct isl_list *union_map_apply_union_pw_qpolynomial_fold(
307 __isl_take isl_union_map *umap,
308 __isl_take isl_union_pw_qpolynomial_fold *upwf)
310 isl_ctx *ctx;
311 struct isl_list *list;
312 int tight;
314 ctx = isl_union_map_get_ctx(umap);
315 list = isl_list_alloc(ctx, 2);
316 if (!list)
317 goto error2;
319 list->obj[0].type = isl_obj_union_pw_qpolynomial_fold;
320 list->obj[0].v = isl_union_map_apply_union_pw_qpolynomial_fold(umap,
321 upwf, &tight);
322 list->obj[1].type = isl_obj_bool;
323 list->obj[1].v = tight ? &isl_bool_true : &isl_bool_false;
324 if (tight < 0 || !list->obj[0].v)
325 goto error;
327 return list;
328 error2:
329 isl_union_map_free(umap);
330 isl_union_pw_qpolynomial_fold_free(upwf);
331 error:
332 isl_list_free(list);
333 return NULL;
336 static __isl_give struct isl_list *union_set_apply_union_pw_qpolynomial_fold(
337 __isl_take isl_union_set *uset,
338 __isl_take isl_union_pw_qpolynomial_fold *upwf)
340 isl_ctx *ctx;
341 struct isl_list *list;
342 int tight;
344 ctx = isl_union_set_get_ctx(uset);
345 list = isl_list_alloc(ctx, 2);
346 if (!list)
347 goto error2;
349 list->obj[0].type = isl_obj_union_pw_qpolynomial_fold;
350 list->obj[0].v = isl_union_set_apply_union_pw_qpolynomial_fold(uset,
351 upwf, &tight);
352 list->obj[1].type = isl_obj_bool;
353 list->obj[1].v = tight ? &isl_bool_true : &isl_bool_false;
354 if (tight < 0 || !list->obj[0].v)
355 goto error;
357 return list;
358 error2:
359 isl_union_set_free(uset);
360 isl_union_pw_qpolynomial_fold_free(upwf);
361 error:
362 isl_list_free(list);
363 return NULL;
366 static __isl_give isl_union_pw_qpolynomial *isl_val_mul_union_pw_qpolynomial(
367 __isl_take isl_val *v, __isl_take isl_union_pw_qpolynomial *upwqp)
369 return isl_union_pw_qpolynomial_scale_val(upwqp, v);
372 static __isl_give isl_union_pw_qpolynomial_fold *
373 int_val_mul_union_pw_qpolynomial_fold(__isl_take isl_val *v,
374 __isl_take isl_union_pw_qpolynomial_fold *upwf)
376 return isl_union_pw_qpolynomial_fold_scale_val(upwf, v);
379 struct isc_bin_op bin_ops[] = {
380 { '+', isl_obj_val, isl_obj_val, isl_obj_val,
381 (isc_bin_op_fn) &isl_val_add },
382 { '-', isl_obj_val, isl_obj_val, isl_obj_val,
383 (isc_bin_op_fn) &isl_val_sub },
384 { '*', isl_obj_val, isl_obj_val, isl_obj_val,
385 (isc_bin_op_fn) &isl_val_mul },
386 { '+', isl_obj_union_set, isl_obj_union_set,
387 isl_obj_union_set,
388 (isc_bin_op_fn) &isl_union_set_union },
389 { '+', isl_obj_union_map, isl_obj_union_map,
390 isl_obj_union_map,
391 (isc_bin_op_fn) &isl_union_map_union },
392 { '-', isl_obj_union_set, isl_obj_union_set,
393 isl_obj_union_set,
394 (isc_bin_op_fn) &isl_union_set_subtract },
395 { '-', isl_obj_union_map, isl_obj_union_map,
396 isl_obj_union_map,
397 (isc_bin_op_fn) &isl_union_map_subtract },
398 { '*', isl_obj_union_set, isl_obj_union_set,
399 isl_obj_union_set,
400 (isc_bin_op_fn) &isl_union_set_intersect },
401 { '*', isl_obj_union_map, isl_obj_union_map,
402 isl_obj_union_map,
403 (isc_bin_op_fn) &isl_union_map_intersect },
404 { '*', isl_obj_union_map, isl_obj_union_set,
405 isl_obj_union_map,
406 (isc_bin_op_fn) &isl_union_map_intersect_domain },
407 { '.', isl_obj_union_map, isl_obj_union_map,
408 isl_obj_union_map,
409 (isc_bin_op_fn) &isl_union_map_apply_range },
410 { '.', isl_obj_union_map, isl_obj_union_pw_qpolynomial,
411 isl_obj_union_pw_qpolynomial,
412 (isc_bin_op_fn) &isl_union_map_apply_union_pw_qpolynomial },
413 { '.', isl_obj_union_map, isl_obj_union_pw_qpolynomial_fold,
414 isl_obj_list,
415 (isc_bin_op_fn) &union_map_apply_union_pw_qpolynomial_fold },
416 { ISL_TOKEN_TO, isl_obj_union_set, isl_obj_union_set,
417 isl_obj_union_map,
418 (isc_bin_op_fn) &isl_union_map_from_domain_and_range },
419 { '=', isl_obj_union_set, isl_obj_union_set, isl_obj_bool,
420 { .test = (isc_bin_test_fn) &isl_union_set_is_equal } },
421 { '=', isl_obj_union_map, isl_obj_union_map, isl_obj_bool,
422 { .test = (isc_bin_test_fn) &isl_union_map_is_equal } },
423 { ISL_TOKEN_LE, isl_obj_union_set, isl_obj_union_set,
424 isl_obj_bool,
425 { .test = (isc_bin_test_fn) &isl_union_set_is_subset } },
426 { ISL_TOKEN_LE, isl_obj_union_map, isl_obj_union_map,
427 isl_obj_bool,
428 { .test = (isc_bin_test_fn) &isl_union_map_is_subset } },
429 { ISL_TOKEN_LT, isl_obj_union_set, isl_obj_union_set,
430 isl_obj_bool,
431 { .test = (isc_bin_test_fn) &isl_union_set_is_strict_subset } },
432 { ISL_TOKEN_LT, isl_obj_union_map, isl_obj_union_map,
433 isl_obj_bool,
434 { .test = (isc_bin_test_fn) &isl_union_map_is_strict_subset } },
435 { ISL_TOKEN_GE, isl_obj_union_set, isl_obj_union_set,
436 isl_obj_bool,
437 { .test = (isc_bin_test_fn) &isl_union_set_is_superset } },
438 { ISL_TOKEN_GE, isl_obj_union_map, isl_obj_union_map,
439 isl_obj_bool,
440 { .test = (isc_bin_test_fn) &isl_union_map_is_superset } },
441 { ISL_TOKEN_GT, isl_obj_union_set, isl_obj_union_set,
442 isl_obj_bool,
443 { .test =
444 (isc_bin_test_fn) &isl_union_set_is_strict_superset } },
445 { ISL_TOKEN_GT, isl_obj_union_map, isl_obj_union_map,
446 isl_obj_bool,
447 { .test =
448 (isc_bin_test_fn) &isl_union_map_is_strict_superset } },
449 { ISL_TOKEN_LEX_LE, isl_obj_union_set, isl_obj_union_set,
450 isl_obj_union_map,
451 (isc_bin_op_fn) &isl_union_set_lex_le_union_set },
452 { ISL_TOKEN_LEX_LT, isl_obj_union_set, isl_obj_union_set,
453 isl_obj_union_map,
454 (isc_bin_op_fn) &isl_union_set_lex_lt_union_set },
455 { ISL_TOKEN_LEX_GE, isl_obj_union_set, isl_obj_union_set,
456 isl_obj_union_map,
457 (isc_bin_op_fn) &isl_union_set_lex_ge_union_set },
458 { ISL_TOKEN_LEX_GT, isl_obj_union_set, isl_obj_union_set,
459 isl_obj_union_map,
460 (isc_bin_op_fn) &isl_union_set_lex_gt_union_set },
461 { ISL_TOKEN_LEX_LE, isl_obj_union_map, isl_obj_union_map,
462 isl_obj_union_map,
463 (isc_bin_op_fn) &isl_union_map_lex_le_union_map },
464 { ISL_TOKEN_LEX_LT, isl_obj_union_map, isl_obj_union_map,
465 isl_obj_union_map,
466 (isc_bin_op_fn) &isl_union_map_lex_lt_union_map },
467 { ISL_TOKEN_LEX_GE, isl_obj_union_map, isl_obj_union_map,
468 isl_obj_union_map,
469 (isc_bin_op_fn) &isl_union_map_lex_ge_union_map },
470 { ISL_TOKEN_LEX_GT, isl_obj_union_map, isl_obj_union_map,
471 isl_obj_union_map,
472 (isc_bin_op_fn) &isl_union_map_lex_gt_union_map },
473 { '.', isl_obj_union_pw_qpolynomial_fold,
474 isl_obj_union_pw_qpolynomial_fold,
475 isl_obj_union_pw_qpolynomial_fold,
476 (isc_bin_op_fn) &isl_union_pw_qpolynomial_fold_fold },
477 { '+', isl_obj_union_pw_qpolynomial, isl_obj_union_pw_qpolynomial,
478 isl_obj_union_pw_qpolynomial,
479 (isc_bin_op_fn) &isl_union_pw_qpolynomial_add },
480 { '+', isl_obj_union_pw_qpolynomial,
481 isl_obj_union_pw_qpolynomial_fold,
482 isl_obj_union_pw_qpolynomial_fold,
483 (isc_bin_op_fn) &union_pw_qpolynomial_add_union_pw_qpolynomial_fold },
484 { '+', isl_obj_union_pw_qpolynomial_fold,
485 isl_obj_union_pw_qpolynomial,
486 isl_obj_union_pw_qpolynomial_fold,
487 (isc_bin_op_fn) &isl_union_pw_qpolynomial_fold_add_union_pw_qpolynomial },
488 { '-', isl_obj_union_pw_qpolynomial, isl_obj_union_pw_qpolynomial,
489 isl_obj_union_pw_qpolynomial,
490 (isc_bin_op_fn) &isl_union_pw_qpolynomial_sub },
491 { '*', isl_obj_val, isl_obj_union_pw_qpolynomial,
492 isl_obj_union_pw_qpolynomial,
493 (isc_bin_op_fn) &isl_val_mul_union_pw_qpolynomial },
494 { '*', isl_obj_union_pw_qpolynomial, isl_obj_val,
495 isl_obj_union_pw_qpolynomial,
496 (isc_bin_op_fn) &isl_union_pw_qpolynomial_scale_val },
497 { '*', isl_obj_val, isl_obj_union_pw_qpolynomial_fold,
498 isl_obj_union_pw_qpolynomial_fold,
499 (isc_bin_op_fn) &int_val_mul_union_pw_qpolynomial_fold },
500 { '*', isl_obj_union_pw_qpolynomial_fold, isl_obj_val,
501 isl_obj_union_pw_qpolynomial_fold,
502 (isc_bin_op_fn) &isl_union_pw_qpolynomial_fold_scale_val },
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_mul },
506 { '*', isl_obj_union_pw_qpolynomial, isl_obj_union_set,
507 isl_obj_union_pw_qpolynomial,
508 (isc_bin_op_fn) &isl_union_pw_qpolynomial_intersect_domain },
509 { '*', isl_obj_union_pw_qpolynomial_fold, isl_obj_union_set,
510 isl_obj_union_pw_qpolynomial_fold,
511 (isc_bin_op_fn) &isl_union_pw_qpolynomial_fold_intersect_domain },
512 { '@', isl_obj_union_pw_qpolynomial, isl_obj_union_set,
513 isl_obj_union_pw_qpolynomial,
514 (isc_bin_op_fn) &isl_union_pw_qpolynomial_at },
515 { '@', isl_obj_union_pw_qpolynomial_fold, isl_obj_union_set,
516 isl_obj_union_pw_qpolynomial,
517 (isc_bin_op_fn) &isl_union_pw_qpolynomial_fold_at },
518 { '%', isl_obj_union_set, isl_obj_union_set,
519 isl_obj_union_set,
520 (isc_bin_op_fn) &isl_union_set_gist },
521 { '%', isl_obj_union_map, isl_obj_union_map,
522 isl_obj_union_map,
523 (isc_bin_op_fn) &isl_union_map_gist },
524 { '%', isl_obj_union_map, isl_obj_union_set,
525 isl_obj_union_map,
526 (isc_bin_op_fn) &isl_union_map_gist_domain },
527 { '%', isl_obj_union_pw_qpolynomial, isl_obj_union_set,
528 isl_obj_union_pw_qpolynomial,
529 (isc_bin_op_fn) &isl_union_pw_qpolynomial_gist },
530 { '%', isl_obj_union_pw_qpolynomial_fold, isl_obj_union_set,
531 isl_obj_union_pw_qpolynomial_fold,
532 (isc_bin_op_fn) &isl_union_pw_qpolynomial_fold_gist },
533 { ISL_TOKEN_EQ_EQ, isl_obj_union_pw_qpolynomial,
534 isl_obj_union_pw_qpolynomial, isl_obj_bool,
535 { .test = (isc_bin_test_fn)
536 &isl_union_pw_qpolynomial_plain_is_equal } },
537 { ISL_TOKEN_EQ_EQ, isl_obj_union_pw_qpolynomial_fold,
538 isl_obj_union_pw_qpolynomial_fold, isl_obj_bool,
539 { .test = (isc_bin_test_fn)
540 &isl_union_pw_qpolynomial_fold_plain_is_equal } },
541 { '+', isl_obj_str, isl_obj_str, isl_obj_str,
542 (isc_bin_op_fn) &isl_str_concat },
546 static __isl_give isl_union_map *map_after_map(__isl_take isl_union_map *umap1,
547 __isl_take isl_union_map *umap2)
549 return isl_union_map_apply_range(umap2, umap1);
552 static __isl_give isl_union_pw_qpolynomial *qpolynomial_after_map(
553 __isl_take isl_union_pw_qpolynomial *upwqp,
554 __isl_take isl_union_map *umap)
556 return isl_union_map_apply_union_pw_qpolynomial(umap, upwqp);
559 static __isl_give struct isl_list *qpolynomial_fold_after_map(
560 __isl_take isl_union_pw_qpolynomial_fold *upwf,
561 __isl_take isl_union_map *umap)
563 return union_map_apply_union_pw_qpolynomial_fold(umap, upwf);
566 struct isc_named_bin_op named_bin_ops[] = {
567 { "after", { -1, isl_obj_union_map, isl_obj_union_map,
568 isl_obj_union_map,
569 (isc_bin_op_fn) &map_after_map } },
570 { "after", { -1, isl_obj_union_pw_qpolynomial,
571 isl_obj_union_map, isl_obj_union_pw_qpolynomial,
572 (isc_bin_op_fn) &qpolynomial_after_map } },
573 { "after", { -1, isl_obj_union_pw_qpolynomial_fold,
574 isl_obj_union_map, isl_obj_list,
575 (isc_bin_op_fn) &qpolynomial_fold_after_map } },
576 { "before", { -1, isl_obj_union_map, isl_obj_union_map,
577 isl_obj_union_map,
578 (isc_bin_op_fn) &isl_union_map_apply_range } },
579 { "before", { -1, isl_obj_union_map,
580 isl_obj_union_pw_qpolynomial, isl_obj_union_pw_qpolynomial,
581 (isc_bin_op_fn) &isl_union_map_apply_union_pw_qpolynomial } },
582 { "before", { -1, isl_obj_union_map,
583 isl_obj_union_pw_qpolynomial_fold, isl_obj_list,
584 (isc_bin_op_fn) &union_map_apply_union_pw_qpolynomial_fold } },
585 { "cross", { -1, isl_obj_union_set, isl_obj_union_set,
586 isl_obj_union_set,
587 (isc_bin_op_fn) &isl_union_set_product } },
588 { "cross", { -1, isl_obj_union_map, isl_obj_union_map,
589 isl_obj_union_map,
590 (isc_bin_op_fn) &isl_union_map_product } },
591 NULL
594 __isl_give isl_set *union_set_sample(__isl_take isl_union_set *uset)
596 return isl_set_from_basic_set(isl_union_set_sample(uset));
599 __isl_give isl_map *union_map_sample(__isl_take isl_union_map *umap)
601 return isl_map_from_basic_map(isl_union_map_sample(umap));
604 static __isl_give struct isl_list *union_map_power(
605 __isl_take isl_union_map *umap)
607 isl_ctx *ctx;
608 struct isl_list *list;
609 int exact;
611 ctx = isl_union_map_get_ctx(umap);
612 list = isl_list_alloc(ctx, 2);
613 if (!list)
614 goto error2;
616 list->obj[0].type = isl_obj_union_map;
617 list->obj[0].v = isl_union_map_power(umap, &exact);
618 list->obj[1].type = isl_obj_bool;
619 list->obj[1].v = exact ? &isl_bool_true : &isl_bool_false;
620 if (exact < 0 || !list->obj[0].v)
621 goto error;
623 return list;
624 error2:
625 isl_union_map_free(umap);
626 error:
627 isl_list_free(list);
628 return NULL;
631 static __isl_give struct isl_list *union_pw_qpolynomial_upper_bound(
632 __isl_take isl_union_pw_qpolynomial *upwqp)
634 isl_ctx *ctx;
635 struct isl_list *list;
636 int tight;
638 ctx = isl_union_pw_qpolynomial_get_ctx(upwqp);
639 list = isl_list_alloc(ctx, 2);
640 if (!list)
641 goto error2;
643 list->obj[0].type = isl_obj_union_pw_qpolynomial_fold;
644 list->obj[0].v = isl_union_pw_qpolynomial_bound(upwqp,
645 isl_fold_max, &tight);
646 list->obj[1].type = isl_obj_bool;
647 list->obj[1].v = tight ? &isl_bool_true : &isl_bool_false;
648 if (tight < 0 || !list->obj[0].v)
649 goto error;
651 return list;
652 error2:
653 isl_union_pw_qpolynomial_free(upwqp);
654 error:
655 isl_list_free(list);
656 return NULL;
659 #ifdef HAVE_PET
660 static __isl_give isl_list *parse(__isl_take isl_str *str)
662 isl_ctx *ctx;
663 struct isl_list *list;
664 struct pet_scop *scop;
665 isl_union_map *sched, *reads, *writes;
666 isl_union_set *domain;
667 struct iscc_options *options;
669 if (!str)
670 return NULL;
671 ctx = str->ctx;
673 options = isl_ctx_peek_iscc_options(ctx);
674 if (!options || !options->io) {
675 isl_str_free(str);
676 isl_die(ctx, isl_error_invalid,
677 "parse_file operation not allowed", return NULL);
680 list = isl_list_alloc(ctx, 4);
681 if (!list)
682 goto error;
684 scop = pet_scop_extract_from_C_source(ctx, str->s, NULL);
685 domain = pet_scop_collect_domains(scop);
686 sched = pet_scop_collect_schedule(scop);
687 reads = pet_scop_collect_reads(scop);
688 writes = pet_scop_collect_writes(scop);
689 pet_scop_free(scop);
691 list->obj[0].type = isl_obj_union_set;
692 list->obj[0].v = domain;
693 list->obj[1].type = isl_obj_union_map;
694 list->obj[1].v = writes;
695 list->obj[2].type = isl_obj_union_map;
696 list->obj[2].v = reads;
697 list->obj[3].type = isl_obj_union_map;
698 list->obj[3].v = sched;
700 if (!list->obj[0].v || !list->obj[1].v ||
701 !list->obj[2].v || !list->obj[3].v)
702 goto error;
704 isl_str_free(str);
705 return list;
706 error:
707 isl_list_free(list);
708 isl_str_free(str);
709 return NULL;
711 #endif
713 static int add_point(__isl_take isl_point *pnt, void *user)
715 isl_union_set **scan = (isl_union_set **) user;
717 *scan = isl_union_set_add_set(*scan, isl_set_from_point(pnt));
719 return 0;
722 static __isl_give isl_union_set *union_set_scan(__isl_take isl_union_set *uset)
724 isl_union_set *scan;
726 scan = isl_union_set_empty(isl_union_set_get_space(uset));
728 if (isl_union_set_foreach_point(uset, add_point, &scan) < 0) {
729 isl_union_set_free(scan);
730 return uset;
733 isl_union_set_free(uset);
734 return scan;
737 static __isl_give isl_union_map *union_map_scan(__isl_take isl_union_map *umap)
739 return isl_union_set_unwrap(union_set_scan(isl_union_map_wrap(umap)));
742 static __isl_give isl_union_pw_qpolynomial *union_pw_qpolynomial_poly(
743 __isl_take isl_union_pw_qpolynomial *upwqp)
745 return isl_union_pw_qpolynomial_to_polynomial(upwqp, 0);
748 static __isl_give isl_union_pw_qpolynomial *union_pw_qpolynomial_lpoly(
749 __isl_take isl_union_pw_qpolynomial *upwqp)
751 return isl_union_pw_qpolynomial_to_polynomial(upwqp, -1);
754 static __isl_give isl_union_pw_qpolynomial *union_pw_qpolynomial_upoly(
755 __isl_take isl_union_pw_qpolynomial *upwqp)
757 return isl_union_pw_qpolynomial_to_polynomial(upwqp, 1);
760 typedef void *(*isc_un_op_fn)(void *arg);
761 struct isc_un_op {
762 enum isl_token_type op;
763 isl_obj_type arg;
764 isl_obj_type res;
765 isc_un_op_fn fn;
767 struct isc_named_un_op {
768 char *name;
769 struct isc_un_op op;
771 struct isc_named_un_op named_un_ops[] = {
772 {"aff", { -1, isl_obj_union_map, isl_obj_union_map,
773 (isc_un_op_fn) &isl_union_map_affine_hull } },
774 {"aff", { -1, isl_obj_union_set, isl_obj_union_set,
775 (isc_un_op_fn) &isl_union_set_affine_hull } },
776 {"card", { -1, isl_obj_union_set,
777 isl_obj_union_pw_qpolynomial,
778 (isc_un_op_fn) &isl_union_set_card } },
779 {"card", { -1, isl_obj_union_map,
780 isl_obj_union_pw_qpolynomial,
781 (isc_un_op_fn) &isl_union_map_card } },
782 {"coalesce", { -1, isl_obj_union_set, isl_obj_union_set,
783 (isc_un_op_fn) &isl_union_set_coalesce } },
784 {"coalesce", { -1, isl_obj_union_map, isl_obj_union_map,
785 (isc_un_op_fn) &isl_union_map_coalesce } },
786 {"coalesce", { -1, isl_obj_union_pw_qpolynomial,
787 isl_obj_union_pw_qpolynomial,
788 (isc_un_op_fn) &isl_union_pw_qpolynomial_coalesce } },
789 {"coalesce", { -1, isl_obj_union_pw_qpolynomial_fold,
790 isl_obj_union_pw_qpolynomial_fold,
791 (isc_un_op_fn) &isl_union_pw_qpolynomial_fold_coalesce } },
792 {"coefficients", { -1, isl_obj_union_set,
793 isl_obj_union_set,
794 (isc_un_op_fn) &isl_union_set_coefficients } },
795 {"solutions", { -1, isl_obj_union_set, isl_obj_union_set,
796 (isc_un_op_fn) &isl_union_set_solutions } },
797 {"deltas", { -1, isl_obj_union_map, isl_obj_union_set,
798 (isc_un_op_fn) &isl_union_map_deltas } },
799 {"deltas_map", { -1, isl_obj_union_map, isl_obj_union_map,
800 (isc_un_op_fn) &isl_union_map_deltas_map } },
801 {"dom", { -1, isl_obj_union_map, isl_obj_union_set,
802 (isc_un_op_fn) &isl_union_map_domain } },
803 {"dom", { -1, isl_obj_union_pw_qpolynomial, isl_obj_union_set,
804 (isc_un_op_fn) &isl_union_pw_qpolynomial_domain } },
805 {"dom", { -1, isl_obj_union_pw_qpolynomial_fold,
806 isl_obj_union_set,
807 (isc_un_op_fn) &isl_union_pw_qpolynomial_fold_domain } },
808 {"domain", { -1, isl_obj_union_map, isl_obj_union_set,
809 (isc_un_op_fn) &isl_union_map_domain } },
810 {"domain", { -1, isl_obj_union_pw_qpolynomial,
811 isl_obj_union_set,
812 (isc_un_op_fn) &isl_union_pw_qpolynomial_domain } },
813 {"domain", { -1, isl_obj_union_pw_qpolynomial_fold,
814 isl_obj_union_set,
815 (isc_un_op_fn) &isl_union_pw_qpolynomial_fold_domain } },
816 {"domain_map", { -1, isl_obj_union_map, isl_obj_union_map,
817 (isc_un_op_fn) &isl_union_map_domain_map } },
818 {"ran", { -1, isl_obj_union_map, isl_obj_union_set,
819 (isc_un_op_fn) &isl_union_map_range } },
820 {"range", { -1, isl_obj_union_map, isl_obj_union_set,
821 (isc_un_op_fn) &isl_union_map_range } },
822 {"range_map", { -1, isl_obj_union_map, isl_obj_union_map,
823 (isc_un_op_fn) &isl_union_map_range_map } },
824 {"identity", { -1, isl_obj_union_set, isl_obj_union_map,
825 (isc_un_op_fn) &isl_union_set_identity } },
826 {"lattice_width", { -1, isl_obj_union_set,
827 isl_obj_union_pw_qpolynomial,
828 (isc_un_op_fn) &isl_union_set_lattice_width } },
829 {"lexmin", { -1, isl_obj_union_map, isl_obj_union_map,
830 (isc_un_op_fn) &isl_union_map_lexmin } },
831 {"lexmax", { -1, isl_obj_union_map, isl_obj_union_map,
832 (isc_un_op_fn) &isl_union_map_lexmax } },
833 {"lexmin", { -1, isl_obj_union_set, isl_obj_union_set,
834 (isc_un_op_fn) &isl_union_set_lexmin } },
835 {"lexmax", { -1, isl_obj_union_set, isl_obj_union_set,
836 (isc_un_op_fn) &isl_union_set_lexmax } },
837 {"lift", { -1, isl_obj_union_set, isl_obj_union_set,
838 (isc_un_op_fn) &isl_union_set_lift } },
839 {"params", { -1, isl_obj_union_map, isl_obj_set,
840 (isc_un_op_fn) &isl_union_map_params } },
841 {"params", { -1, isl_obj_union_set, isl_obj_set,
842 (isc_un_op_fn) &isl_union_set_params } },
843 {"poly", { -1, isl_obj_union_map, isl_obj_union_map,
844 (isc_un_op_fn) &isl_union_map_polyhedral_hull } },
845 {"poly", { -1, isl_obj_union_set, isl_obj_union_set,
846 (isc_un_op_fn) &isl_union_set_polyhedral_hull } },
847 {"poly", { -1, isl_obj_union_pw_qpolynomial,
848 isl_obj_union_pw_qpolynomial,
849 (isc_un_op_fn) &union_pw_qpolynomial_poly } },
850 {"lpoly", { -1, isl_obj_union_pw_qpolynomial,
851 isl_obj_union_pw_qpolynomial,
852 (isc_un_op_fn) &union_pw_qpolynomial_lpoly } },
853 {"upoly", { -1, isl_obj_union_pw_qpolynomial,
854 isl_obj_union_pw_qpolynomial,
855 (isc_un_op_fn) &union_pw_qpolynomial_upoly } },
856 #ifdef HAVE_PET
857 {"parse_file", { -1, isl_obj_str, isl_obj_list,
858 (isc_un_op_fn) &parse } },
859 #endif
860 {"pow", { -1, isl_obj_union_map, isl_obj_list,
861 (isc_un_op_fn) &union_map_power } },
862 {"sample", { -1, isl_obj_union_set, isl_obj_set,
863 (isc_un_op_fn) &union_set_sample } },
864 {"sample", { -1, isl_obj_union_map, isl_obj_map,
865 (isc_un_op_fn) &union_map_sample } },
866 {"scan", { -1, isl_obj_union_set, isl_obj_union_set,
867 (isc_un_op_fn) &union_set_scan } },
868 {"scan", { -1, isl_obj_union_map, isl_obj_union_map,
869 (isc_un_op_fn) &union_map_scan } },
870 {"sum", { -1, isl_obj_union_pw_qpolynomial,
871 isl_obj_union_pw_qpolynomial,
872 (isc_un_op_fn) &isl_union_pw_qpolynomial_sum } },
873 {"ub", { -1, isl_obj_union_pw_qpolynomial, isl_obj_list,
874 (isc_un_op_fn) &union_pw_qpolynomial_upper_bound } },
875 {"unwrap", { -1, isl_obj_union_set, isl_obj_union_map,
876 (isc_un_op_fn) &isl_union_set_unwrap } },
877 {"wrap", { -1, isl_obj_union_map, isl_obj_union_set,
878 (isc_un_op_fn) &isl_union_map_wrap } },
879 {"zip", { -1, isl_obj_union_map, isl_obj_union_map,
880 (isc_un_op_fn) &isl_union_map_zip } },
881 NULL
884 struct isl_named_obj {
885 char *name;
886 struct isl_obj obj;
889 static void free_obj(struct isl_obj obj)
891 obj.type->free(obj.v);
894 static int same_name(const void *entry, const void *val)
896 const struct isl_named_obj *named = (const struct isl_named_obj *)entry;
898 return !strcmp(named->name, val);
901 static int do_assign(struct isl_ctx *ctx, struct isl_hash_table *table,
902 char *name, struct isl_obj obj)
904 struct isl_hash_table_entry *entry;
905 uint32_t name_hash;
906 struct isl_named_obj *named;
908 name_hash = isl_hash_string(isl_hash_init(), name);
909 entry = isl_hash_table_find(ctx, table, name_hash, same_name, name, 1);
910 if (!entry)
911 goto error;
912 if (entry->data) {
913 named = entry->data;
914 free_obj(named->obj);
915 free(name);
916 } else {
917 named = isl_alloc_type(ctx, struct isl_named_obj);
918 if (!named)
919 goto error;
920 named->name = name;
921 entry->data = named;
923 named->obj = obj;
925 return 0;
926 error:
927 free_obj(obj);
928 free(name);
929 return -1;
932 static struct isl_obj stored_obj(struct isl_ctx *ctx,
933 struct isl_hash_table *table, char *name)
935 struct isl_obj obj = { isl_obj_none, NULL };
936 struct isl_hash_table_entry *entry;
937 uint32_t name_hash;
939 name_hash = isl_hash_string(isl_hash_init(), name);
940 entry = isl_hash_table_find(ctx, table, name_hash, same_name, name, 0);
941 if (entry) {
942 struct isl_named_obj *named;
943 named = entry->data;
944 obj = named->obj;
945 } else if (isdigit(name[0]))
946 fprintf(stderr, "unknown identifier '$%s'\n", name);
947 else
948 fprintf(stderr, "unknown identifier '%s'\n", name);
950 free(name);
951 obj.v = obj.type->copy(obj.v);
952 return obj;
955 static int is_subtype(struct isl_obj obj, isl_obj_type super)
957 if (obj.type == super)
958 return 1;
959 if (obj.type == isl_obj_map && super == isl_obj_union_map)
960 return 1;
961 if (obj.type == isl_obj_set && super == isl_obj_union_set)
962 return 1;
963 if (obj.type == isl_obj_pw_qpolynomial &&
964 super == isl_obj_union_pw_qpolynomial)
965 return 1;
966 if (obj.type == isl_obj_pw_qpolynomial_fold &&
967 super == isl_obj_union_pw_qpolynomial_fold)
968 return 1;
969 if (obj.type == isl_obj_union_set && isl_union_set_is_empty(obj.v))
970 return 1;
971 if (obj.type == isl_obj_list) {
972 struct isl_list *list = obj.v;
973 if (list->n == 2 && list->obj[1].type == isl_obj_bool)
974 return is_subtype(list->obj[0], super);
976 if (super == isl_obj_str)
977 return 1;
978 return 0;
981 static struct isl_obj obj_at(struct isl_obj obj, int i)
983 struct isl_list *list = obj.v;
985 obj = list->obj[i];
986 obj.v = obj.type->copy(obj.v);
988 isl_list_free(list);
990 return obj;
993 static struct isl_obj convert(isl_ctx *ctx, struct isl_obj obj,
994 isl_obj_type type)
996 if (obj.type == type)
997 return obj;
998 if (obj.type == isl_obj_map && type == isl_obj_union_map) {
999 obj.type = isl_obj_union_map;
1000 obj.v = isl_union_map_from_map(obj.v);
1001 return obj;
1003 if (obj.type == isl_obj_set && type == isl_obj_union_set) {
1004 obj.type = isl_obj_union_set;
1005 obj.v = isl_union_set_from_set(obj.v);
1006 return obj;
1008 if (obj.type == isl_obj_pw_qpolynomial &&
1009 type == isl_obj_union_pw_qpolynomial) {
1010 obj.type = isl_obj_union_pw_qpolynomial;
1011 obj.v = isl_union_pw_qpolynomial_from_pw_qpolynomial(obj.v);
1012 return obj;
1014 if (obj.type == isl_obj_pw_qpolynomial_fold &&
1015 type == isl_obj_union_pw_qpolynomial_fold) {
1016 obj.type = isl_obj_union_pw_qpolynomial_fold;
1017 obj.v = isl_union_pw_qpolynomial_fold_from_pw_qpolynomial_fold(obj.v);
1018 return obj;
1020 if (obj.type == isl_obj_union_set && isl_union_set_is_empty(obj.v)) {
1021 if (type == isl_obj_union_map) {
1022 obj.type = isl_obj_union_map;
1023 return obj;
1025 if (type == isl_obj_union_pw_qpolynomial) {
1026 isl_space *dim = isl_union_set_get_space(obj.v);
1027 isl_union_set_free(obj.v);
1028 obj.v = isl_union_pw_qpolynomial_zero(dim);
1029 obj.type = isl_obj_union_pw_qpolynomial;
1030 return obj;
1032 if (type == isl_obj_union_pw_qpolynomial_fold) {
1033 isl_space *dim = isl_union_set_get_space(obj.v);
1034 isl_union_set_free(obj.v);
1035 obj.v = isl_union_pw_qpolynomial_fold_zero(dim,
1036 isl_fold_list);
1037 obj.type = isl_obj_union_pw_qpolynomial_fold;
1038 return obj;
1041 if (obj.type == isl_obj_list) {
1042 struct isl_list *list = obj.v;
1043 if (list->n == 2 && list->obj[1].type == isl_obj_bool)
1044 return convert(ctx, obj_at(obj, 0), type);
1046 if (type == isl_obj_str) {
1047 isl_str *str;
1048 isl_printer *p;
1049 char *s;
1051 p = isl_printer_to_str(ctx);
1052 if (!p)
1053 goto error;
1054 p = obj.type->print(p, obj.v);
1055 s = isl_printer_get_str(p);
1056 isl_printer_free(p);
1058 str = isl_str_from_string(ctx, s);
1059 if (!str)
1060 goto error;
1061 free_obj(obj);
1062 obj.v = str;
1063 obj.type = isl_obj_str;
1064 return obj;
1067 error:
1068 free_obj(obj);
1069 obj.type = isl_obj_none;
1070 obj.v = NULL;
1071 return obj;
1074 static struct isc_bin_op *read_bin_op_if_available(struct isl_stream *s,
1075 struct isl_obj lhs)
1077 int i;
1078 struct isl_token *tok;
1080 tok = isl_stream_next_token(s);
1081 if (!tok)
1082 return NULL;
1084 for (i = 0; ; ++i) {
1085 if (!bin_ops[i].op)
1086 break;
1087 if (bin_ops[i].op != isl_token_get_type(tok))
1088 continue;
1089 if (!is_subtype(lhs, bin_ops[i].lhs))
1090 continue;
1092 isl_token_free(tok);
1093 return &bin_ops[i];
1096 for (i = 0; ; ++i) {
1097 if (!named_bin_ops[i].name)
1098 break;
1099 if (named_bin_ops[i].op.op != isl_token_get_type(tok))
1100 continue;
1101 if (!is_subtype(lhs, named_bin_ops[i].op.lhs))
1102 continue;
1104 isl_token_free(tok);
1105 return &named_bin_ops[i].op;
1108 isl_stream_push_token(s, tok);
1110 return NULL;
1113 static struct isc_un_op *read_prefix_un_op_if_available(struct isl_stream *s)
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 (!named_un_ops[i].name)
1124 break;
1125 if (named_un_ops[i].op.op != isl_token_get_type(tok))
1126 continue;
1128 isl_token_free(tok);
1129 return &named_un_ops[i].op;
1132 isl_stream_push_token(s, tok);
1134 return NULL;
1137 static struct isc_un_op *find_matching_un_op(struct isc_un_op *like,
1138 struct isl_obj arg)
1140 int i;
1142 for (i = 0; ; ++i) {
1143 if (!named_un_ops[i].name)
1144 break;
1145 if (named_un_ops[i].op.op != like->op)
1146 continue;
1147 if (!is_subtype(arg, named_un_ops[i].op.arg))
1148 continue;
1150 return &named_un_ops[i].op;
1153 return NULL;
1156 static int is_assign(struct isl_stream *s)
1158 struct isl_token *tok;
1159 struct isl_token *tok2;
1160 int assign;
1162 tok = isl_stream_next_token(s);
1163 if (!tok)
1164 return 0;
1165 if (isl_token_get_type(tok) != ISL_TOKEN_IDENT) {
1166 isl_stream_push_token(s, tok);
1167 return 0;
1170 tok2 = isl_stream_next_token(s);
1171 if (!tok2) {
1172 isl_stream_push_token(s, tok);
1173 return 0;
1175 assign = isl_token_get_type(tok2) == ISL_TOKEN_DEF;
1176 isl_stream_push_token(s, tok2);
1177 isl_stream_push_token(s, tok);
1179 return assign;
1182 static struct isl_obj read_obj(struct isl_stream *s,
1183 struct isl_hash_table *table);
1184 static struct isl_obj read_expr(struct isl_stream *s,
1185 struct isl_hash_table *table);
1187 static struct isl_obj read_un_op_expr(struct isl_stream *s,
1188 struct isl_hash_table *table, struct isc_un_op *op)
1190 struct isl_obj obj = { isl_obj_none, NULL };
1192 obj = read_obj(s, table);
1193 if (!obj.v)
1194 goto error;
1196 op = find_matching_un_op(op, obj);
1198 if (!op)
1199 isl_die(s->ctx, isl_error_invalid,
1200 "no such unary operator defined on given operand",
1201 goto error);
1203 obj = convert(s->ctx, obj, op->arg);
1204 obj.v = op->fn(obj.v);
1205 obj.type = op->res;
1207 return obj;
1208 error:
1209 free_obj(obj);
1210 obj.type = isl_obj_none;
1211 obj.v = NULL;
1212 return obj;
1215 static struct isl_obj transitive_closure(struct isl_ctx *ctx, struct isl_obj obj)
1217 struct isl_list *list;
1218 int exact;
1220 if (obj.type != isl_obj_union_map)
1221 obj = convert(ctx, obj, isl_obj_union_map);
1222 isl_assert(ctx, obj.type == isl_obj_union_map, goto error);
1223 list = isl_list_alloc(ctx, 2);
1224 if (!list)
1225 goto error;
1227 list->obj[0].type = isl_obj_union_map;
1228 list->obj[0].v = isl_union_map_transitive_closure(obj.v, &exact);
1229 list->obj[1].type = isl_obj_bool;
1230 list->obj[1].v = exact ? &isl_bool_true : &isl_bool_false;
1231 obj.v = list;
1232 obj.type = isl_obj_list;
1233 if (exact < 0 || !list->obj[0].v)
1234 goto error;
1236 return obj;
1237 error:
1238 free_obj(obj);
1239 obj.type = isl_obj_none;
1240 obj.v = NULL;
1241 return obj;
1244 static struct isl_obj obj_at_index(struct isl_stream *s, struct isl_obj obj)
1246 struct isl_list *list = obj.v;
1247 struct isl_token *tok;
1248 isl_val *v;
1249 int i;
1251 tok = isl_stream_next_token(s);
1252 if (!tok || isl_token_get_type(tok) != ISL_TOKEN_VALUE) {
1253 isl_stream_error(s, tok, "expecting index");
1254 if (tok)
1255 isl_stream_push_token(s, tok);
1256 goto error;
1258 v = isl_token_get_val(s->ctx, tok);
1259 i = isl_val_get_num_si(v);
1260 isl_val_free(v);
1261 isl_token_free(tok);
1262 isl_assert(s->ctx, i < list->n, goto error);
1263 if (isl_stream_eat(s, ']'))
1264 goto error;
1266 return obj_at(obj, i);
1267 error:
1268 free_obj(obj);
1269 obj.type = isl_obj_none;
1270 obj.v = NULL;
1271 return obj;
1274 static struct isl_obj apply(struct isl_stream *s, __isl_take isl_union_map *umap,
1275 struct isl_hash_table *table)
1277 struct isl_obj obj;
1279 obj = read_expr(s, table);
1280 isl_assert(s->ctx, is_subtype(obj, isl_obj_union_set) ||
1281 is_subtype(obj, isl_obj_union_map), goto error);
1283 if (obj.type == isl_obj_list) {
1284 struct isl_list *list = obj.v;
1285 if (list->n == 2 && list->obj[1].type == isl_obj_bool)
1286 obj = obj_at(obj, 0);
1288 if (obj.type == isl_obj_set)
1289 obj = convert(s->ctx, obj, isl_obj_union_set);
1290 else if (obj.type == isl_obj_map)
1291 obj = convert(s->ctx, obj, isl_obj_union_map);
1292 if (obj.type == isl_obj_union_set) {
1293 obj.v = isl_union_set_apply(obj.v, umap);
1294 } else
1295 obj.v = isl_union_map_apply_range(obj.v, umap);
1296 if (!obj.v)
1297 goto error2;
1299 if (isl_stream_eat(s, ')'))
1300 goto error2;
1302 return obj;
1303 error:
1304 isl_union_map_free(umap);
1305 error2:
1306 free_obj(obj);
1307 obj.type = isl_obj_none;
1308 obj.v = NULL;
1309 return obj;
1312 static struct isl_obj apply_fun_set(struct isl_obj obj,
1313 __isl_take isl_union_set *uset)
1315 if (obj.type == isl_obj_union_pw_qpolynomial) {
1316 obj.v = isl_union_set_apply_union_pw_qpolynomial(uset, obj.v);
1317 } else {
1318 obj.type = isl_obj_list;
1319 obj.v = union_set_apply_union_pw_qpolynomial_fold(uset, obj.v);
1321 return obj;
1324 static struct isl_obj apply_fun_map(struct isl_obj obj,
1325 __isl_take isl_union_map *umap)
1327 if (obj.type == isl_obj_union_pw_qpolynomial) {
1328 obj.v = isl_union_map_apply_union_pw_qpolynomial(umap, obj.v);
1329 } else {
1330 obj.type = isl_obj_list;
1331 obj.v = union_map_apply_union_pw_qpolynomial_fold(umap, obj.v);
1333 return obj;
1336 static struct isl_obj apply_fun(struct isl_stream *s,
1337 struct isl_obj obj, struct isl_hash_table *table)
1339 struct isl_obj arg;
1341 arg = read_expr(s, table);
1342 if (!is_subtype(arg, isl_obj_union_map) &&
1343 !is_subtype(arg, isl_obj_union_set))
1344 isl_die(s->ctx, isl_error_invalid,
1345 "expecting set of map argument", goto error);
1347 if (arg.type == isl_obj_list) {
1348 struct isl_list *list = arg.v;
1349 if (list->n == 2 && list->obj[1].type == isl_obj_bool)
1350 arg = obj_at(arg, 0);
1352 if (arg.type == isl_obj_set)
1353 arg = convert(s->ctx, arg, isl_obj_union_set);
1354 else if (arg.type == isl_obj_map)
1355 arg = convert(s->ctx, arg, isl_obj_union_map);
1356 if (arg.type == isl_obj_union_set)
1357 obj = apply_fun_set(obj, arg.v);
1358 else
1359 obj = apply_fun_map(obj, arg.v);
1360 if (!obj.v)
1361 goto error2;
1363 if (isl_stream_eat(s, ')'))
1364 goto error2;
1366 return obj;
1367 error:
1368 free_obj(arg);
1369 error2:
1370 free_obj(obj);
1371 obj.type = isl_obj_none;
1372 obj.v = NULL;
1373 return obj;
1376 struct add_vertex_data {
1377 struct isl_list *list;
1378 int i;
1381 static int add_vertex(__isl_take isl_vertex *vertex, void *user)
1383 struct add_vertex_data *data = (struct add_vertex_data *)user;
1384 isl_basic_set *expr;
1386 expr = isl_vertex_get_expr(vertex);
1388 data->list->obj[data->i].type = isl_obj_set;
1389 data->list->obj[data->i].v = isl_set_from_basic_set(expr);
1390 data->i++;
1392 isl_vertex_free(vertex);
1394 return 0;
1397 static int set_vertices(__isl_take isl_set *set, void *user)
1399 isl_ctx *ctx;
1400 isl_basic_set *hull;
1401 isl_vertices *vertices = NULL;
1402 struct isl_list *list = NULL;
1403 int r;
1404 struct add_vertex_data *data = (struct add_vertex_data *)user;
1406 set = isl_set_remove_divs(set);
1407 hull = isl_set_convex_hull(set);
1408 vertices = isl_basic_set_compute_vertices(hull);
1409 isl_basic_set_free(hull);
1411 list = data->list;
1413 ctx = isl_vertices_get_ctx(vertices);
1414 data->list = isl_list_alloc(ctx, isl_vertices_get_n_vertices(vertices));
1415 if (!data->list)
1416 goto error;
1418 data->i = 0;
1419 r = isl_vertices_foreach_vertex(vertices, &add_vertex, user);
1421 data->list = isl_list_concat(list, data->list);
1423 isl_vertices_free(vertices);
1425 return r;
1426 error:
1427 data->list = list;
1428 isl_vertices_free(vertices);
1429 return -1;
1432 static struct isl_obj vertices(struct isl_stream *s,
1433 struct isl_hash_table *table)
1435 isl_ctx *ctx;
1436 struct isl_obj obj;
1437 struct isl_list *list = NULL;
1438 isl_union_set *uset;
1439 struct add_vertex_data data = { NULL };
1441 obj = read_expr(s, table);
1442 obj = convert(s->ctx, obj, isl_obj_union_set);
1443 isl_assert(s->ctx, obj.type == isl_obj_union_set, goto error);
1444 uset = obj.v;
1445 obj.v = NULL;
1447 ctx = isl_union_set_get_ctx(uset);
1448 list = isl_list_alloc(ctx, 0);
1449 if (!list)
1450 goto error;
1452 data.list = list;
1454 if (isl_union_set_foreach_set(uset, &set_vertices, &data) < 0)
1455 goto error;
1457 isl_union_set_free(uset);
1459 obj.type = isl_obj_list;
1460 obj.v = data.list;
1462 return obj;
1463 error:
1464 isl_union_set_free(uset);
1465 isl_list_free(data.list);
1466 free_obj(obj);
1467 obj.type = isl_obj_none;
1468 obj.v = NULL;
1469 return obj;
1472 static struct isl_obj type_of(struct isl_stream *s,
1473 struct isl_hash_table *table)
1475 isl_ctx *ctx;
1476 struct isl_obj obj;
1477 const char *type = "unknown";
1479 obj = read_expr(s, table);
1481 if (obj.type == isl_obj_map ||
1482 obj.type == isl_obj_union_map)
1483 type = "map";
1484 if (obj.type == isl_obj_set ||
1485 obj.type == isl_obj_union_set)
1486 type = "set";
1487 if (obj.type == isl_obj_pw_qpolynomial ||
1488 obj.type == isl_obj_union_pw_qpolynomial)
1489 type = "piecewise quasipolynomial";
1490 if (obj.type == isl_obj_pw_qpolynomial_fold ||
1491 obj.type == isl_obj_union_pw_qpolynomial_fold)
1492 type = "piecewise quasipolynomial fold";
1493 if (obj.type == isl_obj_list)
1494 type = "list";
1495 if (obj.type == isl_obj_bool)
1496 type = "boolean";
1497 if (obj.type == isl_obj_str)
1498 type = "string";
1499 if (obj.type == isl_obj_val)
1500 type = "value";
1502 free_obj(obj);
1503 obj.type = isl_obj_str;
1504 obj.v = isl_str_from_string(s->ctx, strdup(type));
1506 return obj;
1509 static __isl_give isl_union_set *read_set(struct isl_stream *s,
1510 struct isl_hash_table *table)
1512 struct isl_obj obj;
1514 obj = read_obj(s, table);
1515 obj = convert(s->ctx, obj, isl_obj_union_set);
1516 isl_assert(s->ctx, obj.type == isl_obj_union_set, goto error);
1517 return obj.v;
1518 error:
1519 free_obj(obj);
1520 return NULL;
1523 static __isl_give isl_union_map *read_map(struct isl_stream *s,
1524 struct isl_hash_table *table)
1526 struct isl_obj obj;
1528 obj = read_obj(s, table);
1529 obj = convert(s->ctx, obj, isl_obj_union_map);
1530 isl_assert(s->ctx, obj.type == isl_obj_union_map, goto error);
1531 return obj.v;
1532 error:
1533 free_obj(obj);
1534 return NULL;
1537 static struct isl_obj last_any(struct isl_stream *s,
1538 struct isl_hash_table *table, __isl_take isl_union_map *must_source,
1539 __isl_take isl_union_map *may_source)
1541 struct isl_obj obj = { isl_obj_none, NULL };
1542 isl_union_map *sink = NULL;
1543 isl_union_map *schedule = NULL;
1544 isl_union_map *may_dep;
1545 isl_union_map *must_dep;
1547 if (isl_stream_eat(s, iscc_op[ISCC_BEFORE]))
1548 goto error;
1550 sink = read_map(s, table);
1551 if (!sink)
1552 goto error;
1554 if (isl_stream_eat(s, iscc_op[ISCC_UNDER]))
1555 goto error;
1557 schedule = read_map(s, table);
1558 if (!schedule)
1559 goto error;
1561 if (isl_union_map_compute_flow(sink, must_source, may_source,
1562 schedule, &must_dep, &may_dep,
1563 NULL, NULL) < 0)
1564 return obj;
1566 obj.type = isl_obj_union_map;
1567 obj.v = isl_union_map_union(must_dep, may_dep);
1569 return obj;
1570 error:
1571 isl_union_map_free(may_source);
1572 isl_union_map_free(must_source);
1573 isl_union_map_free(sink);
1574 isl_union_map_free(schedule);
1575 free_obj(obj);
1576 obj.type = isl_obj_none;
1577 obj.v = NULL;
1578 return obj;
1581 static struct isl_obj any(struct isl_stream *s, struct isl_hash_table *table)
1583 struct isl_obj obj = { isl_obj_none, NULL };
1584 isl_union_map *must_source = NULL;
1585 isl_union_map *may_source = NULL;
1586 isl_union_map *sink = NULL;
1587 isl_union_map *schedule = NULL;
1588 isl_union_map *may_dep;
1590 may_source = read_map(s, table);
1591 if (!may_source)
1592 goto error;
1594 if (isl_stream_eat_if_available(s, iscc_op[ISCC_LAST])) {
1595 must_source = read_map(s, table);
1596 if (!must_source)
1597 goto error;
1598 return last_any(s, table, must_source, may_source);
1601 if (isl_stream_eat(s, iscc_op[ISCC_BEFORE]))
1602 goto error;
1604 sink = read_map(s, table);
1605 if (!sink)
1606 goto error;
1608 if (isl_stream_eat(s, iscc_op[ISCC_UNDER]))
1609 goto error;
1611 schedule = read_map(s, table);
1612 if (!schedule)
1613 goto error;
1615 must_source = isl_union_map_empty(isl_union_map_get_space(sink));
1616 if (isl_union_map_compute_flow(sink, must_source, may_source,
1617 schedule, NULL, &may_dep,
1618 NULL, NULL) < 0)
1619 return obj;
1621 obj.type = isl_obj_union_map;
1622 obj.v = may_dep;
1624 return obj;
1625 error:
1626 isl_union_map_free(may_source);
1627 isl_union_map_free(must_source);
1628 isl_union_map_free(sink);
1629 isl_union_map_free(schedule);
1630 free_obj(obj);
1631 obj.type = isl_obj_none;
1632 obj.v = NULL;
1633 return obj;
1636 static struct isl_obj last(struct isl_stream *s, struct isl_hash_table *table)
1638 struct isl_obj obj = { isl_obj_none, NULL };
1639 struct isl_list *list = NULL;
1640 isl_union_map *must_source = NULL;
1641 isl_union_map *may_source = NULL;
1642 isl_union_map *sink = NULL;
1643 isl_union_map *schedule = NULL;
1644 isl_union_map *must_dep;
1645 isl_union_map *must_no_source;
1647 must_source = read_map(s, table);
1648 if (!must_source)
1649 goto error;
1651 if (isl_stream_eat_if_available(s, iscc_op[ISCC_ANY])) {
1652 may_source = read_map(s, table);
1653 if (!may_source)
1654 goto error;
1655 return last_any(s, table, must_source, may_source);
1658 list = isl_list_alloc(s->ctx, 2);
1659 if (!list)
1660 goto error;
1662 if (isl_stream_eat(s, iscc_op[ISCC_BEFORE]))
1663 goto error;
1665 sink = read_map(s, table);
1666 if (!sink)
1667 goto error;
1669 if (isl_stream_eat(s, iscc_op[ISCC_UNDER]))
1670 goto error;
1672 schedule = read_map(s, table);
1673 if (!schedule)
1674 goto error;
1676 may_source = isl_union_map_empty(isl_union_map_get_space(sink));
1677 if (isl_union_map_compute_flow(sink, must_source, may_source,
1678 schedule, &must_dep, NULL,
1679 &must_no_source, NULL) < 0) {
1680 isl_list_free(list);
1681 return obj;
1684 list->obj[0].type = isl_obj_union_map;
1685 list->obj[0].v = must_dep;
1686 list->obj[1].type = isl_obj_union_map;
1687 list->obj[1].v = must_no_source;
1689 obj.v = list;
1690 obj.type = isl_obj_list;
1692 return obj;
1693 error:
1694 isl_list_free(list);
1695 isl_union_map_free(may_source);
1696 isl_union_map_free(must_source);
1697 isl_union_map_free(sink);
1698 isl_union_map_free(schedule);
1699 free_obj(obj);
1700 obj.type = isl_obj_none;
1701 obj.v = NULL;
1702 return obj;
1705 static __isl_give isl_schedule *get_schedule(struct isl_stream *s,
1706 struct isl_hash_table *table)
1708 isl_union_set *domain;
1709 isl_union_map *validity;
1710 isl_union_map *proximity;
1712 domain = read_set(s, table);
1713 if (!domain)
1714 return NULL;
1716 validity = isl_union_map_empty(isl_union_set_get_space(domain));
1717 proximity = isl_union_map_empty(isl_union_set_get_space(domain));
1719 for (;;) {
1720 isl_union_map *umap;
1721 if (isl_stream_eat_if_available(s, iscc_op[ISCC_RESPECTING])) {
1722 umap = read_map(s, table);
1723 validity = isl_union_map_union(validity, umap);
1724 } else if (isl_stream_eat_if_available(s, iscc_op[ISCC_MINIMIZING])) {
1725 umap = read_map(s, table);
1726 proximity = isl_union_map_union(proximity, umap);
1727 } else
1728 break;
1731 return isl_union_set_compute_schedule(domain, validity, proximity);
1734 static struct isl_obj schedule(struct isl_stream *s,
1735 struct isl_hash_table *table)
1737 struct isl_obj obj = { isl_obj_none, NULL };
1738 isl_schedule *schedule;
1740 schedule = get_schedule(s, table);
1742 obj.v = isl_schedule_get_map(schedule);
1743 obj.type = isl_obj_union_map;
1745 isl_schedule_free(schedule);
1747 return obj;
1750 /* Read a schedule for code generation.
1751 * If the input is a set rather than a map, then we construct
1752 * an identity schedule on the given set.
1754 static __isl_give isl_union_map *get_codegen_schedule(struct isl_stream *s,
1755 struct isl_hash_table *table)
1757 struct isl_obj obj;
1759 obj = read_obj(s, table);
1761 if (is_subtype(obj, isl_obj_union_map)) {
1762 obj = convert(s->ctx, obj, isl_obj_union_map);
1763 return obj.v;
1766 if (is_subtype(obj, isl_obj_union_set)) {
1767 obj = convert(s->ctx, obj, isl_obj_union_set);
1768 return isl_union_set_identity(obj.v);
1771 free_obj(obj);
1772 isl_die(s->ctx, isl_error_invalid, "expecting set or map", return NULL);
1775 /* Generate an AST for the given schedule and options and print
1776 * the AST on the printer.
1778 static __isl_give isl_printer *print_code(__isl_take isl_printer *p,
1779 __isl_take isl_union_map *schedule,
1780 __isl_take isl_union_map *options)
1782 isl_space *space;
1783 isl_set *context;
1784 isl_ast_build *build;
1785 isl_ast_node *tree;
1786 int format;
1788 space = isl_union_map_get_space(schedule);
1789 context = isl_set_universe(isl_space_params(space));
1791 build = isl_ast_build_from_context(context);
1792 build = isl_ast_build_set_options(build, options);
1793 tree = isl_ast_build_ast_from_schedule(build, schedule);
1794 isl_ast_build_free(build);
1796 if (!tree)
1797 return p;
1799 format = isl_printer_get_output_format(p);
1800 p = isl_printer_set_output_format(p, ISL_FORMAT_C);
1801 p = isl_printer_print_ast_node(p, tree);
1802 p = isl_printer_set_output_format(p, format);
1804 isl_ast_node_free(tree);
1806 return p;
1809 /* Perform the codegen operation.
1810 * In particular, read a schedule, check if the user has specified any options
1811 * and then generate an AST from the schedule (and options) and print it.
1813 static __isl_give isl_printer *codegen(struct isl_stream *s,
1814 struct isl_hash_table *table, __isl_take isl_printer *p)
1816 isl_union_map *schedule;
1817 isl_union_map *options;
1819 schedule = get_codegen_schedule(s, table);
1820 if (!schedule)
1821 return p;
1823 if (isl_stream_eat_if_available(s, iscc_op[ISCC_USING]))
1824 options = read_map(s, table);
1825 else
1826 options = isl_union_map_empty(
1827 isl_union_map_get_space(schedule));
1829 p = print_code(p, schedule, options);
1831 isl_stream_eat(s, ';');
1833 return p;
1836 static struct isl_obj band_list_to_obj_list(__isl_take isl_band_list *bands);
1838 static struct isl_obj band_to_obj_list(__isl_take isl_band *band)
1840 struct isl_obj obj = { isl_obj_none, NULL };
1841 isl_ctx *ctx = isl_band_get_ctx(band);
1842 struct isl_list *list;
1844 list = isl_list_alloc(ctx, 2);
1845 if (!list)
1846 goto error;
1848 obj.v = list;
1849 obj.type = isl_obj_list;
1851 list->obj[0].type = isl_obj_union_map;
1852 list->obj[0].v = isl_band_get_partial_schedule(band);
1854 if (isl_band_has_children(band)) {
1855 isl_band_list *children;
1857 children = isl_band_get_children(band);
1858 list->obj[1] = band_list_to_obj_list(children);
1859 } else {
1860 list->obj[1].type = isl_obj_list;
1861 list->obj[1].v = isl_list_alloc(ctx, 0);
1864 if (!list->obj[0].v || !list->obj[1].v)
1865 goto error;
1867 isl_band_free(band);
1869 return obj;
1870 error:
1871 isl_band_free(band);
1872 free_obj(obj);
1873 obj.type = isl_obj_none;
1874 obj.v = NULL;
1875 return obj;
1878 static struct isl_obj band_list_to_obj_list(__isl_take isl_band_list *bands)
1880 struct isl_obj obj = { isl_obj_none, NULL };
1881 isl_ctx *ctx = isl_band_list_get_ctx(bands);
1882 struct isl_list *list;
1883 int i, n;
1885 n = isl_band_list_n_band(bands);
1886 list = isl_list_alloc(ctx, n);
1887 if (!list)
1888 goto error;
1890 obj.v = list;
1891 obj.type = isl_obj_list;
1893 for (i = 0; i < n; ++i) {
1894 isl_band *band;
1896 band = isl_band_list_get_band(bands, i);
1897 list->obj[i] = band_to_obj_list(band);
1898 if (!list->obj[i].v)
1899 goto error;
1902 isl_band_list_free(bands);
1904 return obj;
1905 error:
1906 isl_band_list_free(bands);
1907 free_obj(obj);
1908 obj.type = isl_obj_none;
1909 obj.v = NULL;
1910 return obj;
1913 static struct isl_obj schedule_forest(struct isl_stream *s,
1914 struct isl_hash_table *table)
1916 struct isl_obj obj = { isl_obj_none, NULL };
1917 isl_schedule *schedule;
1918 isl_band_list *roots;
1920 schedule = get_schedule(s, table);
1921 if (!schedule)
1922 return obj;
1924 roots = isl_schedule_get_band_forest(schedule);
1925 isl_schedule_free(schedule);
1927 return band_list_to_obj_list(roots);
1930 static struct isl_obj power(struct isl_stream *s, struct isl_obj obj)
1932 struct isl_token *tok;
1933 isl_val *v;
1935 if (isl_stream_eat_if_available(s, '+'))
1936 return transitive_closure(s->ctx, obj);
1938 isl_assert(s->ctx, is_subtype(obj, isl_obj_union_map), goto error);
1939 if (obj.type != isl_obj_union_map)
1940 obj = convert(s->ctx, obj, isl_obj_union_map);
1942 tok = isl_stream_next_token(s);
1943 if (!tok || isl_token_get_type(tok) != ISL_TOKEN_VALUE) {
1944 isl_stream_error(s, tok, "expecting integer exponent");
1945 if (tok)
1946 isl_stream_push_token(s, tok);
1947 goto error;
1950 v = isl_token_get_val(s->ctx, tok);
1951 if (isl_val_is_zero(v)) {
1952 isl_stream_error(s, tok, "expecting non-zero exponent");
1953 isl_val_free(v);
1954 if (tok)
1955 isl_stream_push_token(s, tok);
1956 goto error;
1959 obj.v = isl_union_map_fixed_power_val(obj.v, v);
1960 isl_token_free(tok);
1961 if (!obj.v)
1962 goto error;
1964 return obj;
1965 error:
1966 free_obj(obj);
1967 obj.type = isl_obj_none;
1968 obj.v = NULL;
1969 return obj;
1972 static struct isl_obj check_assert(struct isl_stream *s,
1973 struct isl_hash_table *table)
1975 struct isl_obj obj;
1977 obj = read_expr(s, table);
1978 if (obj.type != isl_obj_bool)
1979 isl_die(s->ctx, isl_error_invalid,
1980 "expecting boolean expression", goto error);
1981 if (obj.v != &isl_bool_true)
1982 isl_die(s->ctx, isl_error_unknown,
1983 "assertion failed", abort());
1984 error:
1985 free_obj(obj);
1986 obj.type = isl_obj_none;
1987 obj.v = NULL;
1988 return obj;
1991 static struct isl_obj read_from_file(struct isl_stream *s)
1993 struct isl_obj obj;
1994 struct isl_token *tok;
1995 struct isl_stream *s_file;
1996 struct iscc_options *options;
1997 char *name;
1998 FILE *file;
2000 tok = isl_stream_next_token(s);
2001 if (!tok || isl_token_get_type(tok) != ISL_TOKEN_STRING) {
2002 isl_stream_error(s, tok, "expecting filename");
2003 isl_token_free(tok);
2004 goto error;
2007 options = isl_ctx_peek_iscc_options(s->ctx);
2008 if (!options || !options->io) {
2009 isl_token_free(tok);
2010 isl_die(s->ctx, isl_error_invalid,
2011 "read operation not allowed", goto error);
2014 name = isl_token_get_str(s->ctx, tok);
2015 isl_token_free(tok);
2016 file = fopen(name, "r");
2017 free(name);
2018 isl_assert(s->ctx, file, goto error);
2020 s_file = isl_stream_new_file(s->ctx, file);
2021 if (!s_file) {
2022 fclose(file);
2023 goto error;
2026 obj = isl_stream_read_obj(s_file);
2028 isl_stream_free(s_file);
2029 fclose(file);
2031 return obj;
2032 error:
2033 obj.type = isl_obj_none;
2034 obj.v = NULL;
2035 return obj;
2038 static struct isl_obj write_to_file(struct isl_stream *s,
2039 struct isl_hash_table *table)
2041 struct isl_obj obj;
2042 struct isl_token *tok;
2043 struct isl_stream *s_file;
2044 struct iscc_options *options;
2045 char *name;
2046 FILE *file;
2047 isl_printer *p;
2049 tok = isl_stream_next_token(s);
2050 if (!tok || isl_token_get_type(tok) != ISL_TOKEN_STRING) {
2051 isl_stream_error(s, tok, "expecting filename");
2052 isl_token_free(tok);
2053 goto error;
2056 obj = read_expr(s, table);
2058 options = isl_ctx_peek_iscc_options(s->ctx);
2059 if (!options || !options->io) {
2060 isl_token_free(tok);
2061 isl_die(s->ctx, isl_error_invalid,
2062 "write operation not allowed", goto error);
2065 name = isl_token_get_str(s->ctx, tok);
2066 isl_token_free(tok);
2067 file = fopen(name, "w");
2068 free(name);
2069 if (!file)
2070 isl_die(s->ctx, isl_error_unknown,
2071 "could not open file for writing", goto error);
2073 p = isl_printer_to_file(s->ctx, file);
2074 p = isl_printer_set_output_format(p, options->format);
2075 p = obj.type->print(p, obj.v);
2076 p = isl_printer_end_line(p);
2077 isl_printer_free(p);
2079 fclose(file);
2080 error:
2081 free_obj(obj);
2082 obj.type = isl_obj_none;
2083 obj.v = NULL;
2084 return obj;
2087 static struct isl_obj read_string_if_available(struct isl_stream *s)
2089 struct isl_token *tok;
2090 struct isl_obj obj = { isl_obj_none, NULL };
2092 tok = isl_stream_next_token(s);
2093 if (!tok)
2094 return obj;
2095 if (isl_token_get_type(tok) == ISL_TOKEN_STRING) {
2096 isl_str *str;
2097 str = isl_str_alloc(s->ctx);
2098 if (!str)
2099 goto error;
2100 str->s = isl_token_get_str(s->ctx, tok);
2101 isl_token_free(tok);
2102 obj.v = str;
2103 obj.type = isl_obj_str;
2104 } else
2105 isl_stream_push_token(s, tok);
2106 return obj;
2107 error:
2108 isl_token_free(tok);
2109 return obj;
2112 static struct isl_obj read_bool_if_available(struct isl_stream *s)
2114 struct isl_token *tok;
2115 struct isl_obj obj = { isl_obj_none, NULL };
2116 int type;
2118 tok = isl_stream_next_token(s);
2119 if (!tok)
2120 return obj;
2121 type = isl_token_get_type(tok);
2122 if (type == ISL_TOKEN_FALSE || type == ISL_TOKEN_TRUE) {
2123 int is_true = type == ISL_TOKEN_TRUE;
2124 isl_token_free(tok);
2125 obj.v = is_true ? &isl_bool_true : &isl_bool_false;
2126 obj.type = isl_obj_bool;
2127 } else
2128 isl_stream_push_token(s, tok);
2129 return obj;
2132 static __isl_give char *read_ident(struct isl_stream *s)
2134 char *name;
2135 isl_val *v;
2136 struct isl_token *tok, *tok2;
2138 name = isl_stream_read_ident_if_available(s);
2139 if (name)
2140 return name;
2142 tok = isl_stream_next_token(s);
2143 if (!tok)
2144 return NULL;
2145 if (isl_token_get_type(tok) != '$') {
2146 isl_stream_push_token(s, tok);
2147 return NULL;
2149 tok2 = isl_stream_next_token(s);
2150 if (!tok2 || isl_token_get_type(tok2) != ISL_TOKEN_VALUE) {
2151 if (tok2)
2152 isl_stream_push_token(s, tok2);
2153 isl_stream_push_token(s, tok);
2154 return NULL;
2157 v = isl_token_get_val(s->ctx, tok2);
2158 name = isl_val_to_str(v);
2159 isl_val_free(v);
2160 isl_token_free(tok);
2161 isl_token_free(tok2);
2163 return name;
2166 static struct isl_obj read_list(struct isl_stream *s,
2167 struct isl_hash_table *table, struct isl_obj obj)
2169 struct isl_list *list;
2171 list = isl_list_alloc(s->ctx, 2);
2172 if (!list)
2173 goto error;
2174 list->obj[0] = obj;
2175 list->obj[1] = read_obj(s, table);
2176 obj.v = list;
2177 obj.type = isl_obj_list;
2179 if (!list->obj[1].v)
2180 goto error;
2182 while (isl_stream_eat_if_available(s, ',')) {
2183 obj.v = list = isl_list_add_obj(list, read_obj(s, table));
2184 if (!obj.v)
2185 goto error;
2188 return obj;
2189 error:
2190 free_obj(obj);
2191 obj.type = isl_obj_none;
2192 obj.v = NULL;
2193 return obj;
2196 static struct isl_obj read_obj(struct isl_stream *s,
2197 struct isl_hash_table *table)
2199 struct isl_obj obj = { isl_obj_none, NULL };
2200 char *name = NULL;
2201 struct isc_un_op *op = NULL;
2203 obj = read_string_if_available(s);
2204 if (obj.v)
2205 return obj;
2206 obj = read_bool_if_available(s);
2207 if (obj.v)
2208 return obj;
2209 if (isl_stream_eat_if_available(s, '(')) {
2210 if (isl_stream_next_token_is(s, ')')) {
2211 obj.type = isl_obj_list;
2212 obj.v = isl_list_alloc(s->ctx, 0);
2213 } else {
2214 obj = read_expr(s, table);
2215 if (obj.v && isl_stream_eat_if_available(s, ','))
2216 obj = read_list(s, table, obj);
2218 if (!obj.v || isl_stream_eat(s, ')'))
2219 goto error;
2220 } else {
2221 op = read_prefix_un_op_if_available(s);
2222 if (op)
2223 return read_un_op_expr(s, table, op);
2225 if (isl_stream_eat_if_available(s, iscc_op[ISCC_ASSERT]))
2226 return check_assert(s, table);
2227 if (isl_stream_eat_if_available(s, iscc_op[ISCC_READ]))
2228 return read_from_file(s);
2229 if (isl_stream_eat_if_available(s, iscc_op[ISCC_WRITE]))
2230 return write_to_file(s, table);
2231 if (isl_stream_eat_if_available(s, iscc_op[ISCC_VERTICES]))
2232 return vertices(s, table);
2233 if (isl_stream_eat_if_available(s, iscc_op[ISCC_ANY]))
2234 return any(s, table);
2235 if (isl_stream_eat_if_available(s, iscc_op[ISCC_LAST]))
2236 return last(s, table);
2237 if (isl_stream_eat_if_available(s, iscc_op[ISCC_SCHEDULE]))
2238 return schedule(s, table);
2239 if (isl_stream_eat_if_available(s, iscc_op[ISCC_SCHEDULE_FOREST]))
2240 return schedule_forest(s, table);
2241 if (isl_stream_eat_if_available(s, iscc_op[ISCC_TYPEOF]))
2242 return type_of(s, table);
2244 name = read_ident(s);
2245 if (name)
2246 obj = stored_obj(s->ctx, table, name);
2247 else
2248 obj = isl_stream_read_obj(s);
2249 if (!obj.v)
2250 goto error;
2253 if (isl_stream_eat_if_available(s, '^'))
2254 obj = power(s, obj);
2255 else if (obj.type == isl_obj_list && isl_stream_eat_if_available(s, '['))
2256 obj = obj_at_index(s, obj);
2257 else if (is_subtype(obj, isl_obj_union_map) &&
2258 isl_stream_eat_if_available(s, '(')) {
2259 obj = convert(s->ctx, obj, isl_obj_union_map);
2260 obj = apply(s, obj.v, table);
2261 } else if (is_subtype(obj, isl_obj_union_pw_qpolynomial) &&
2262 isl_stream_eat_if_available(s, '(')) {
2263 obj = convert(s->ctx, obj, isl_obj_union_pw_qpolynomial);
2264 obj = apply_fun(s, obj, table);
2265 } else if (is_subtype(obj, isl_obj_union_pw_qpolynomial_fold) &&
2266 isl_stream_eat_if_available(s, '(')) {
2267 obj = convert(s->ctx, obj, isl_obj_union_pw_qpolynomial_fold);
2268 obj = apply_fun(s, obj, table);
2271 return obj;
2272 error:
2273 free_obj(obj);
2274 obj.type = isl_obj_none;
2275 obj.v = NULL;
2276 return obj;
2279 static struct isc_bin_op *find_matching_bin_op(struct isc_bin_op *like,
2280 struct isl_obj lhs, struct isl_obj rhs)
2282 int i;
2284 for (i = 0; ; ++i) {
2285 if (!bin_ops[i].op)
2286 break;
2287 if (bin_ops[i].op != like->op)
2288 continue;
2289 if (!is_subtype(lhs, bin_ops[i].lhs))
2290 continue;
2291 if (!is_subtype(rhs, bin_ops[i].rhs))
2292 continue;
2294 return &bin_ops[i];
2297 for (i = 0; ; ++i) {
2298 if (!named_bin_ops[i].name)
2299 break;
2300 if (named_bin_ops[i].op.op != like->op)
2301 continue;
2302 if (!is_subtype(lhs, named_bin_ops[i].op.lhs))
2303 continue;
2304 if (!is_subtype(rhs, named_bin_ops[i].op.rhs))
2305 continue;
2307 return &named_bin_ops[i].op;
2310 return NULL;
2313 static int next_is_neg_int(struct isl_stream *s)
2315 struct isl_token *tok;
2316 int ret;
2318 tok = isl_stream_next_token(s);
2319 if (tok && isl_token_get_type(tok) == ISL_TOKEN_VALUE) {
2320 isl_val *v;
2321 v = isl_token_get_val(s->ctx, tok);
2322 ret = isl_val_is_neg(v);
2323 isl_val_free(v);
2324 } else
2325 ret = 0;
2326 isl_stream_push_token(s, tok);
2328 return ret;
2331 static struct isl_obj call_bin_op(isl_ctx *ctx, struct isc_bin_op *op,
2332 struct isl_obj lhs, struct isl_obj rhs)
2334 struct isl_obj obj;
2336 lhs = convert(ctx, lhs, op->lhs);
2337 rhs = convert(ctx, rhs, op->rhs);
2338 if (op->res != isl_obj_bool)
2339 obj.v = op->o.fn(lhs.v, rhs.v);
2340 else {
2341 int res = op->o.test(lhs.v, rhs.v);
2342 free_obj(lhs);
2343 free_obj(rhs);
2344 obj.v = isl_bool_from_int(res);
2346 obj.type = op->res;
2348 return obj;
2351 static struct isl_obj read_expr(struct isl_stream *s,
2352 struct isl_hash_table *table)
2354 struct isl_obj obj = { isl_obj_none, NULL };
2355 struct isl_obj right_obj = { isl_obj_none, NULL };
2357 obj = read_obj(s, table);
2358 for (; obj.v;) {
2359 struct isc_bin_op *op = NULL;
2361 op = read_bin_op_if_available(s, obj);
2362 if (!op)
2363 break;
2365 right_obj = read_obj(s, table);
2367 op = find_matching_bin_op(op, obj, right_obj);
2369 if (!op)
2370 isl_die(s->ctx, isl_error_invalid,
2371 "no such binary operator defined on given operands",
2372 goto error);
2374 obj = call_bin_op(s->ctx, op, obj, right_obj);
2377 if (obj.type == isl_obj_val && next_is_neg_int(s)) {
2378 right_obj = read_obj(s, table);
2379 obj.v = isl_val_add(obj.v, right_obj.v);
2382 return obj;
2383 error:
2384 free_obj(right_obj);
2385 free_obj(obj);
2386 obj.type = isl_obj_none;
2387 obj.v = NULL;
2388 return obj;
2391 static __isl_give isl_printer *source_file(struct isl_stream *s,
2392 struct isl_hash_table *table, __isl_take isl_printer *p);
2394 static __isl_give isl_printer *read_line(struct isl_stream *s,
2395 struct isl_hash_table *table, __isl_take isl_printer *p, int tty)
2397 struct isl_obj obj = { isl_obj_none, NULL };
2398 char *lhs = NULL;
2399 int assign = 0;
2400 int only_print = 0;
2401 struct isc_bin_op *op = NULL;
2402 char buf[30];
2404 if (!p)
2405 return NULL;
2406 if (isl_stream_is_empty(s))
2407 return p;
2409 if (isl_stream_eat_if_available(s, iscc_op[ISCC_SOURCE]))
2410 return source_file(s, table, p);
2411 if (isl_stream_eat_if_available(s, iscc_op[ISCC_CODEGEN]))
2412 return codegen(s, table, p);
2414 assign = is_assign(s);
2415 if (assign) {
2416 lhs = isl_stream_read_ident_if_available(s);
2417 if (isl_stream_eat(s, ISL_TOKEN_DEF))
2418 goto error;
2419 } else if (isl_stream_eat_if_available(s, iscc_op[ISCC_PRINT]))
2420 only_print = 1;
2421 else if (!tty)
2422 only_print = 1;
2424 obj = read_expr(s, table);
2425 if (isl_ctx_last_error(s->ctx) == isl_error_abort) {
2426 fprintf(stderr, "Interrupted\n");
2427 isl_ctx_reset_error(s->ctx);
2429 if (isl_stream_eat(s, ';'))
2430 goto error;
2432 if (only_print) {
2433 if (obj.type != isl_obj_none && obj.v != NULL) {
2434 p = obj.type->print(p, obj.v);
2435 p = isl_printer_end_line(p);
2437 free_obj(obj);
2438 return p;
2440 if (!assign && obj.type != isl_obj_none && obj.v != NULL) {
2441 static int count = 0;
2442 snprintf(buf, sizeof(buf), "$%d", count++);
2443 lhs = strdup(buf + 1);
2445 p = isl_printer_print_str(p, buf);
2446 p = isl_printer_print_str(p, " := ");
2447 p = obj.type->print(p, obj.v);
2448 p = isl_printer_end_line(p);
2450 if (lhs && do_assign(s->ctx, table, lhs, obj))
2451 return p;
2453 return p;
2454 error:
2455 isl_stream_flush_tokens(s);
2456 isl_stream_skip_line(s);
2457 free(lhs);
2458 free_obj(obj);
2459 return p;
2462 int free_cb(void **entry, void *user)
2464 struct isl_named_obj *named = *entry;
2466 free_obj(named->obj);
2467 free(named->name);
2468 free(named);
2470 return 0;
2473 static void register_named_ops(struct isl_stream *s)
2475 int i;
2477 for (i = 0; i < ISCC_N_OP; ++i) {
2478 iscc_op[i] = isl_stream_register_keyword(s, op_name[i]);
2479 assert(iscc_op[i] != ISL_TOKEN_ERROR);
2482 for (i = 0; ; ++i) {
2483 if (!named_un_ops[i].name)
2484 break;
2485 named_un_ops[i].op.op = isl_stream_register_keyword(s,
2486 named_un_ops[i].name);
2487 assert(named_un_ops[i].op.op != ISL_TOKEN_ERROR);
2490 for (i = 0; ; ++i) {
2491 if (!named_bin_ops[i].name)
2492 break;
2493 named_bin_ops[i].op.op = isl_stream_register_keyword(s,
2494 named_bin_ops[i].name);
2495 assert(named_bin_ops[i].op.op != ISL_TOKEN_ERROR);
2499 static __isl_give isl_printer *source_file(struct isl_stream *s,
2500 struct isl_hash_table *table, __isl_take isl_printer *p)
2502 struct isl_token *tok;
2503 struct isl_stream *s_file;
2504 char *name;
2505 FILE *file;
2507 tok = isl_stream_next_token(s);
2508 if (!tok || isl_token_get_type(tok) != ISL_TOKEN_STRING) {
2509 isl_stream_error(s, tok, "expecting filename");
2510 isl_token_free(tok);
2511 return p;
2514 name = isl_token_get_str(s->ctx, tok);
2515 isl_token_free(tok);
2516 file = fopen(name, "r");
2517 free(name);
2518 isl_assert(s->ctx, file, return p);
2520 s_file = isl_stream_new_file(s->ctx, file);
2521 if (!s_file) {
2522 fclose(file);
2523 return p;
2526 register_named_ops(s_file);
2528 while (!s_file->eof)
2529 p = read_line(s_file, table, p, 0);
2531 isl_stream_free(s_file);
2532 fclose(file);
2534 isl_stream_eat(s, ';');
2536 return p;
2539 int main(int argc, char **argv)
2541 struct isl_ctx *ctx;
2542 struct isl_stream *s;
2543 struct isl_hash_table *table;
2544 struct iscc_options *options;
2545 isl_printer *p;
2546 int tty = isatty(0);
2548 options = iscc_options_new_with_defaults();
2549 assert(options);
2551 ctx = isl_ctx_alloc_with_options(&iscc_options_args, options);
2552 pet_options_set_autodetect(ctx, 1);
2553 argc = isl_ctx_parse_options(ctx, argc, argv, ISL_ARG_ALL);
2554 s = isl_stream_new_file(ctx, stdin);
2555 assert(s);
2556 table = isl_hash_table_alloc(ctx, 10);
2557 assert(table);
2558 p = isl_printer_to_file(ctx, stdout);
2559 p = isl_printer_set_output_format(p, options->format);
2560 assert(p);
2562 register_named_ops(s);
2564 install_signal_handler(ctx);
2566 while (p && !s->eof) {
2567 isl_ctx_resume(ctx);
2568 p = read_line(s, table, p, tty);
2571 remove_signal_handler(ctx);
2573 isl_printer_free(p);
2574 isl_hash_table_foreach(ctx, table, free_cb, NULL);
2575 isl_hash_table_free(ctx, table);
2576 isl_stream_free(s);
2577 isl_ctx_free(ctx);
2579 return 0;