iscc: add operations on booleans
[barvinok.git] / iscc.c
blob1a6d028cac4391ffe87d71c327addd6da4b96ebc
1 #include <assert.h>
2 #include <ctype.h>
3 #include <stdio.h>
4 #include <string.h>
5 #include <unistd.h>
6 #include <isl/aff.h>
7 #include <isl/obj.h>
8 #include <isl/stream.h>
9 #include <isl/set.h>
10 #include <isl/map.h>
11 #include <isl/vertices.h>
12 #include <isl/flow.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 iscc_bool_false = 0;
77 static int iscc_bool_true = 1;
78 static int iscc_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,
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_MINIMIZING] = "minimizing",
100 [ISCC_RESPECTING] = "respecting",
101 [ISCC_CODEGEN] = "codegen",
102 [ISCC_USING] = "using",
103 [ISCC_TYPEOF] = "typeof"
105 static enum isl_token_type iscc_op[ISCC_N_OP];
107 struct isl_arg_choice iscc_format[] = {
108 {"isl", ISL_FORMAT_ISL},
109 {"omega", ISL_FORMAT_OMEGA},
110 {"polylib", ISL_FORMAT_POLYLIB},
111 {"ext-polylib", ISL_FORMAT_EXT_POLYLIB},
112 {"latex", ISL_FORMAT_LATEX},
113 {"C", ISL_FORMAT_C},
117 struct iscc_options {
118 struct barvinok_options *barvinok;
119 struct pet_options *pet;
120 unsigned format;
121 int io;
124 ISL_ARGS_START(struct iscc_options, iscc_options_args)
125 ISL_ARG_CHILD(struct iscc_options, barvinok, "barvinok", &barvinok_options_args,
126 "barvinok options")
127 #ifdef HAVE_PET
128 ISL_ARG_CHILD(struct iscc_options, pet, "pet", &pet_options_args, "pet options")
129 #endif
130 ISL_ARG_CHOICE(struct iscc_options, format, 0, "format", \
131 iscc_format, ISL_FORMAT_ISL, "output format")
132 ISL_ARG_BOOL(struct iscc_options, io, 0, "io", 1,
133 "allow read and write operations")
134 ISL_ARGS_END
136 ISL_ARG_DEF(iscc_options, struct iscc_options, iscc_options_args)
137 ISL_ARG_CTX_DEF(iscc_options, struct iscc_options, iscc_options_args)
139 static void *isl_obj_bool_copy(void *v)
141 return v;
144 static void isl_obj_bool_free(void *v)
148 static __isl_give isl_printer *isl_obj_bool_print(__isl_take isl_printer *p,
149 void *v)
151 if (v == &iscc_bool_true)
152 return isl_printer_print_str(p, "True");
153 else if (v == &iscc_bool_false)
154 return isl_printer_print_str(p, "False");
155 else
156 return isl_printer_print_str(p, "Error");
159 static void *isl_obj_bool_add(void *v1, void *v2)
161 return v1;
164 struct isl_obj_vtable isl_obj_bool_vtable = {
165 isl_obj_bool_copy,
166 isl_obj_bool_add,
167 isl_obj_bool_print,
168 isl_obj_bool_free
170 #define isl_obj_bool (&isl_obj_bool_vtable)
172 int *iscc_bool_from_int(int res)
174 return res < 0 ? &iscc_bool_error :
175 res ? &iscc_bool_true : &iscc_bool_false;
178 /* Conjunction of "b1" and "b2".
179 * The result is returned as an integer because it is post-processed by
180 * iscc_bool_from_int.
182 static int isl_bool_and(isl_bool *b1, __isl_take isl_bool *b2)
184 if (b1 == &iscc_bool_error || b2 == &iscc_bool_error)
185 return -1;
186 return b1 == &iscc_bool_true && b2 == &iscc_bool_true;
189 /* Disjunction of "b1" and "b2".
190 * The result is returned as an integer because it is post-processed by
191 * iscc_bool_from_int.
193 static int isl_bool_or(isl_bool *b1, __isl_take isl_bool *b2)
195 if (b1 == &iscc_bool_error || b2 == &iscc_bool_error)
196 return -1;
197 return b1 == &iscc_bool_true || b2 == &iscc_bool_true;
200 static int isl_union_map_is_superset(__isl_take isl_union_map *map1,
201 __isl_take isl_union_map *map2)
203 return isl_union_map_is_subset(map2, map1);
205 static int isl_union_set_is_superset(__isl_take isl_union_set *set1,
206 __isl_take isl_union_set *set2)
208 return isl_union_set_is_subset(set2, set1);
211 static int isl_union_map_is_strict_superset(__isl_take isl_union_map *map1,
212 __isl_take isl_union_map *map2)
214 return isl_union_map_is_strict_subset(map2, map1);
216 static int isl_union_set_is_strict_superset(__isl_take isl_union_set *set1,
217 __isl_take isl_union_set *set2)
219 return isl_union_set_is_strict_subset(set2, set1);
222 extern struct isl_obj_vtable isl_obj_list_vtable;
223 #define isl_obj_list (&isl_obj_list_vtable)
225 typedef void *(*isc_bin_op_fn)(void *lhs, void *rhs);
226 typedef int (*isc_bin_test_fn)(void *lhs, void *rhs);
227 struct isc_bin_op {
228 enum isl_token_type op;
229 isl_obj_type lhs;
230 isl_obj_type rhs;
231 isl_obj_type res;
232 union {
233 isc_bin_op_fn fn;
234 isc_bin_test_fn test;
235 } o;
237 struct isc_named_bin_op {
238 char *name;
239 struct isc_bin_op op;
241 /* Compound binary operator.
242 * "full" is only used to generate a unique token number for op.op
243 * in register_named_ops.
244 * "op1" is the first part of the compound operator.
245 * "op2" is the second part of the compound operator.
247 struct iscc_compound_bin_op {
248 char *full;
249 enum isl_token_type op1;
250 enum isl_token_type op2;
251 struct isc_bin_op op;
254 struct iscc_at {
255 isl_union_pw_qpolynomial *upwqp;
256 isl_union_pw_qpolynomial *res;
259 static isl_stat eval_at(__isl_take isl_point *pnt, void *user)
261 struct iscc_at *at = (struct iscc_at *) user;
262 isl_val *v;
263 isl_qpolynomial *qp;
264 isl_set *set;
266 set = isl_set_from_point(isl_point_copy(pnt));
267 v = isl_union_pw_qpolynomial_eval(
268 isl_union_pw_qpolynomial_copy(at->upwqp), pnt);
269 qp = isl_qpolynomial_val_on_domain(isl_set_get_space(set), v);
271 at->res = isl_union_pw_qpolynomial_add(at->res,
272 isl_union_pw_qpolynomial_from_pw_qpolynomial(
273 isl_pw_qpolynomial_alloc(set, qp)));
275 return isl_stat_ok;
278 __isl_give isl_union_pw_qpolynomial *isl_union_pw_qpolynomial_at(
279 __isl_take isl_union_pw_qpolynomial *upwqp,
280 __isl_take isl_union_set *uset)
282 struct iscc_at at;
284 at.upwqp = upwqp;
285 at.res = isl_union_pw_qpolynomial_zero(isl_union_set_get_space(uset));
287 isl_union_set_foreach_point(uset, eval_at, &at);
289 isl_union_pw_qpolynomial_free(upwqp);
290 isl_union_set_free(uset);
292 return at.res;
295 struct iscc_fold_at {
296 isl_union_pw_qpolynomial_fold *upwf;
297 isl_union_pw_qpolynomial *res;
300 static isl_stat eval_fold_at(__isl_take isl_point *pnt, void *user)
302 struct iscc_fold_at *at = (struct iscc_fold_at *) user;
303 isl_val *v;
304 isl_qpolynomial *qp;
305 isl_set *set;
307 set = isl_set_from_point(isl_point_copy(pnt));
308 v = isl_union_pw_qpolynomial_fold_eval(
309 isl_union_pw_qpolynomial_fold_copy(at->upwf), pnt);
310 qp = isl_qpolynomial_val_on_domain(isl_set_get_space(set), v);
312 at->res = isl_union_pw_qpolynomial_add(at->res,
313 isl_union_pw_qpolynomial_from_pw_qpolynomial(
314 isl_pw_qpolynomial_alloc(set, qp)));
316 return isl_stat_ok;
319 __isl_give isl_union_pw_qpolynomial *isl_union_pw_qpolynomial_fold_at(
320 __isl_take isl_union_pw_qpolynomial_fold *upwf,
321 __isl_take isl_union_set *uset)
323 struct iscc_fold_at at;
325 at.upwf = upwf;
326 at.res = isl_union_pw_qpolynomial_zero(isl_union_set_get_space(uset));
328 isl_union_set_foreach_point(uset, eval_fold_at, &at);
330 isl_union_pw_qpolynomial_fold_free(upwf);
331 isl_union_set_free(uset);
333 return at.res;
336 static __isl_give isl_union_pw_qpolynomial_fold *union_pw_qpolynomial_add_union_pw_qpolynomial_fold(
337 __isl_take isl_union_pw_qpolynomial *upwqp,
338 __isl_take isl_union_pw_qpolynomial_fold *upwf)
340 return isl_union_pw_qpolynomial_fold_add_union_pw_qpolynomial(upwf,
341 upwqp);
344 static __isl_give struct isl_list *union_map_apply_union_pw_qpolynomial_fold(
345 __isl_take isl_union_map *umap,
346 __isl_take isl_union_pw_qpolynomial_fold *upwf)
348 isl_ctx *ctx;
349 struct isl_list *list;
350 int tight;
352 ctx = isl_union_map_get_ctx(umap);
353 list = isl_list_alloc(ctx, 2);
354 if (!list)
355 goto error2;
357 list->obj[0].type = isl_obj_union_pw_qpolynomial_fold;
358 list->obj[0].v = isl_union_map_apply_union_pw_qpolynomial_fold(umap,
359 upwf, &tight);
360 list->obj[1].type = isl_obj_bool;
361 list->obj[1].v = tight ? &iscc_bool_true : &iscc_bool_false;
362 if (tight < 0 || !list->obj[0].v)
363 goto error;
365 return list;
366 error2:
367 isl_union_map_free(umap);
368 isl_union_pw_qpolynomial_fold_free(upwf);
369 error:
370 isl_list_free(list);
371 return NULL;
374 static __isl_give struct isl_list *union_set_apply_union_pw_qpolynomial_fold(
375 __isl_take isl_union_set *uset,
376 __isl_take isl_union_pw_qpolynomial_fold *upwf)
378 isl_ctx *ctx;
379 struct isl_list *list;
380 int tight;
382 ctx = isl_union_set_get_ctx(uset);
383 list = isl_list_alloc(ctx, 2);
384 if (!list)
385 goto error2;
387 list->obj[0].type = isl_obj_union_pw_qpolynomial_fold;
388 list->obj[0].v = isl_union_set_apply_union_pw_qpolynomial_fold(uset,
389 upwf, &tight);
390 list->obj[1].type = isl_obj_bool;
391 list->obj[1].v = tight ? &iscc_bool_true : &iscc_bool_false;
392 if (tight < 0 || !list->obj[0].v)
393 goto error;
395 return list;
396 error2:
397 isl_union_set_free(uset);
398 isl_union_pw_qpolynomial_fold_free(upwf);
399 error:
400 isl_list_free(list);
401 return NULL;
404 static __isl_give isl_union_pw_qpolynomial *isl_val_mul_union_pw_qpolynomial(
405 __isl_take isl_val *v, __isl_take isl_union_pw_qpolynomial *upwqp)
407 return isl_union_pw_qpolynomial_scale_val(upwqp, v);
410 static __isl_give isl_union_pw_qpolynomial_fold *
411 int_val_mul_union_pw_qpolynomial_fold(__isl_take isl_val *v,
412 __isl_take isl_union_pw_qpolynomial_fold *upwf)
414 return isl_union_pw_qpolynomial_fold_scale_val(upwf, v);
417 /* Are the two strings "str1" and "str2" equal to each other?
419 static int str_eq(__isl_keep isl_str *str1, __isl_keep isl_str *str2)
421 if (!str1 || !str2)
422 return -1;
424 return !strcmp(str1->s, str2->s);
427 struct isc_bin_op bin_ops[] = {
428 { '+', isl_obj_bool, isl_obj_bool, isl_obj_bool,
429 (isc_bin_op_fn) &isl_bool_or },
430 { '*', isl_obj_bool, isl_obj_bool, isl_obj_bool,
431 (isc_bin_op_fn) &isl_bool_and },
432 { '+', isl_obj_val, isl_obj_val, isl_obj_val,
433 (isc_bin_op_fn) &isl_val_add },
434 { '-', isl_obj_val, isl_obj_val, isl_obj_val,
435 (isc_bin_op_fn) &isl_val_sub },
436 { '*', isl_obj_val, isl_obj_val, isl_obj_val,
437 (isc_bin_op_fn) &isl_val_mul },
438 { '+', isl_obj_pw_multi_aff, isl_obj_pw_multi_aff,
439 isl_obj_pw_multi_aff,
440 (isc_bin_op_fn) &isl_pw_multi_aff_add },
441 { '+', isl_obj_union_set, isl_obj_union_set,
442 isl_obj_union_set,
443 (isc_bin_op_fn) &isl_union_set_union },
444 { '+', isl_obj_union_map, isl_obj_union_map,
445 isl_obj_union_map,
446 (isc_bin_op_fn) &isl_union_map_union },
447 { '-', isl_obj_union_set, isl_obj_union_set,
448 isl_obj_union_set,
449 (isc_bin_op_fn) &isl_union_set_subtract },
450 { '-', isl_obj_union_map, isl_obj_union_map,
451 isl_obj_union_map,
452 (isc_bin_op_fn) &isl_union_map_subtract },
453 { '-', isl_obj_union_map, isl_obj_union_set,
454 isl_obj_union_map,
455 (isc_bin_op_fn) &isl_union_map_subtract_domain },
456 { '*', isl_obj_union_set, isl_obj_union_set,
457 isl_obj_union_set,
458 (isc_bin_op_fn) &isl_union_set_intersect },
459 { '*', isl_obj_union_map, isl_obj_union_map,
460 isl_obj_union_map,
461 (isc_bin_op_fn) &isl_union_map_intersect },
462 { '*', isl_obj_union_map, isl_obj_union_set,
463 isl_obj_union_map,
464 (isc_bin_op_fn) &isl_union_map_intersect_domain },
465 { '.', isl_obj_union_map, isl_obj_union_map,
466 isl_obj_union_map,
467 (isc_bin_op_fn) &isl_union_map_apply_range },
468 { '.', isl_obj_union_map, isl_obj_union_pw_qpolynomial,
469 isl_obj_union_pw_qpolynomial,
470 (isc_bin_op_fn) &isl_union_map_apply_union_pw_qpolynomial },
471 { '.', isl_obj_union_map, isl_obj_union_pw_qpolynomial_fold,
472 isl_obj_list,
473 (isc_bin_op_fn) &union_map_apply_union_pw_qpolynomial_fold },
474 { ISL_TOKEN_TO, isl_obj_union_set, isl_obj_union_set,
475 isl_obj_union_map,
476 (isc_bin_op_fn) &isl_union_map_from_domain_and_range },
477 { '=', isl_obj_union_set, isl_obj_union_set, isl_obj_bool,
478 { .test = (isc_bin_test_fn) &isl_union_set_is_equal } },
479 { '=', isl_obj_union_map, isl_obj_union_map, isl_obj_bool,
480 { .test = (isc_bin_test_fn) &isl_union_map_is_equal } },
481 { ISL_TOKEN_LE, isl_obj_union_set, isl_obj_union_set,
482 isl_obj_bool,
483 { .test = (isc_bin_test_fn) &isl_union_set_is_subset } },
484 { ISL_TOKEN_LE, isl_obj_union_map, isl_obj_union_map,
485 isl_obj_bool,
486 { .test = (isc_bin_test_fn) &isl_union_map_is_subset } },
487 { ISL_TOKEN_LT, isl_obj_union_set, isl_obj_union_set,
488 isl_obj_bool,
489 { .test = (isc_bin_test_fn) &isl_union_set_is_strict_subset } },
490 { ISL_TOKEN_LT, isl_obj_union_map, isl_obj_union_map,
491 isl_obj_bool,
492 { .test = (isc_bin_test_fn) &isl_union_map_is_strict_subset } },
493 { ISL_TOKEN_GE, isl_obj_union_set, isl_obj_union_set,
494 isl_obj_bool,
495 { .test = (isc_bin_test_fn) &isl_union_set_is_superset } },
496 { ISL_TOKEN_GE, isl_obj_union_map, isl_obj_union_map,
497 isl_obj_bool,
498 { .test = (isc_bin_test_fn) &isl_union_map_is_superset } },
499 { ISL_TOKEN_GT, isl_obj_union_set, isl_obj_union_set,
500 isl_obj_bool,
501 { .test =
502 (isc_bin_test_fn) &isl_union_set_is_strict_superset } },
503 { ISL_TOKEN_GT, isl_obj_union_map, isl_obj_union_map,
504 isl_obj_bool,
505 { .test =
506 (isc_bin_test_fn) &isl_union_map_is_strict_superset } },
507 { ISL_TOKEN_LEX_LE, isl_obj_union_set, isl_obj_union_set,
508 isl_obj_union_map,
509 (isc_bin_op_fn) &isl_union_set_lex_le_union_set },
510 { ISL_TOKEN_LEX_LT, isl_obj_union_set, isl_obj_union_set,
511 isl_obj_union_map,
512 (isc_bin_op_fn) &isl_union_set_lex_lt_union_set },
513 { ISL_TOKEN_LEX_GE, isl_obj_union_set, isl_obj_union_set,
514 isl_obj_union_map,
515 (isc_bin_op_fn) &isl_union_set_lex_ge_union_set },
516 { ISL_TOKEN_LEX_GT, isl_obj_union_set, isl_obj_union_set,
517 isl_obj_union_map,
518 (isc_bin_op_fn) &isl_union_set_lex_gt_union_set },
519 { ISL_TOKEN_LEX_LE, isl_obj_union_map, isl_obj_union_map,
520 isl_obj_union_map,
521 (isc_bin_op_fn) &isl_union_map_lex_le_union_map },
522 { ISL_TOKEN_LEX_LT, isl_obj_union_map, isl_obj_union_map,
523 isl_obj_union_map,
524 (isc_bin_op_fn) &isl_union_map_lex_lt_union_map },
525 { ISL_TOKEN_LEX_GE, isl_obj_union_map, isl_obj_union_map,
526 isl_obj_union_map,
527 (isc_bin_op_fn) &isl_union_map_lex_ge_union_map },
528 { ISL_TOKEN_LEX_GT, isl_obj_union_map, isl_obj_union_map,
529 isl_obj_union_map,
530 (isc_bin_op_fn) &isl_union_map_lex_gt_union_map },
531 { '.', isl_obj_union_pw_qpolynomial_fold,
532 isl_obj_union_pw_qpolynomial_fold,
533 isl_obj_union_pw_qpolynomial_fold,
534 (isc_bin_op_fn) &isl_union_pw_qpolynomial_fold_fold },
535 { '+', isl_obj_union_pw_qpolynomial, isl_obj_union_pw_qpolynomial,
536 isl_obj_union_pw_qpolynomial,
537 (isc_bin_op_fn) &isl_union_pw_qpolynomial_add },
538 { '+', isl_obj_union_pw_qpolynomial,
539 isl_obj_union_pw_qpolynomial_fold,
540 isl_obj_union_pw_qpolynomial_fold,
541 (isc_bin_op_fn) &union_pw_qpolynomial_add_union_pw_qpolynomial_fold },
542 { '+', isl_obj_union_pw_qpolynomial_fold,
543 isl_obj_union_pw_qpolynomial,
544 isl_obj_union_pw_qpolynomial_fold,
545 (isc_bin_op_fn) &isl_union_pw_qpolynomial_fold_add_union_pw_qpolynomial },
546 { '-', isl_obj_union_pw_qpolynomial, isl_obj_union_pw_qpolynomial,
547 isl_obj_union_pw_qpolynomial,
548 (isc_bin_op_fn) &isl_union_pw_qpolynomial_sub },
549 { '*', isl_obj_val, isl_obj_union_pw_qpolynomial,
550 isl_obj_union_pw_qpolynomial,
551 (isc_bin_op_fn) &isl_val_mul_union_pw_qpolynomial },
552 { '*', isl_obj_union_pw_qpolynomial, isl_obj_val,
553 isl_obj_union_pw_qpolynomial,
554 (isc_bin_op_fn) &isl_union_pw_qpolynomial_scale_val },
555 { '*', isl_obj_val, isl_obj_union_pw_qpolynomial_fold,
556 isl_obj_union_pw_qpolynomial_fold,
557 (isc_bin_op_fn) &int_val_mul_union_pw_qpolynomial_fold },
558 { '*', isl_obj_union_pw_qpolynomial_fold, isl_obj_val,
559 isl_obj_union_pw_qpolynomial_fold,
560 (isc_bin_op_fn) &isl_union_pw_qpolynomial_fold_scale_val },
561 { '*', isl_obj_union_pw_qpolynomial, isl_obj_union_pw_qpolynomial,
562 isl_obj_union_pw_qpolynomial,
563 (isc_bin_op_fn) &isl_union_pw_qpolynomial_mul },
564 { '*', isl_obj_union_pw_qpolynomial, isl_obj_union_set,
565 isl_obj_union_pw_qpolynomial,
566 (isc_bin_op_fn) &isl_union_pw_qpolynomial_intersect_domain },
567 { '*', isl_obj_union_pw_qpolynomial_fold, isl_obj_union_set,
568 isl_obj_union_pw_qpolynomial_fold,
569 (isc_bin_op_fn) &isl_union_pw_qpolynomial_fold_intersect_domain },
570 { '@', isl_obj_union_pw_qpolynomial, isl_obj_union_set,
571 isl_obj_union_pw_qpolynomial,
572 (isc_bin_op_fn) &isl_union_pw_qpolynomial_at },
573 { '@', isl_obj_union_pw_qpolynomial_fold, isl_obj_union_set,
574 isl_obj_union_pw_qpolynomial,
575 (isc_bin_op_fn) &isl_union_pw_qpolynomial_fold_at },
576 { '%', isl_obj_union_set, isl_obj_union_set,
577 isl_obj_union_set,
578 (isc_bin_op_fn) &isl_union_set_gist },
579 { '%', isl_obj_union_map, isl_obj_union_map,
580 isl_obj_union_map,
581 (isc_bin_op_fn) &isl_union_map_gist },
582 { '%', isl_obj_union_map, isl_obj_union_set,
583 isl_obj_union_map,
584 (isc_bin_op_fn) &isl_union_map_gist_domain },
585 { '%', isl_obj_union_pw_qpolynomial, isl_obj_union_set,
586 isl_obj_union_pw_qpolynomial,
587 (isc_bin_op_fn) &isl_union_pw_qpolynomial_gist },
588 { '%', isl_obj_union_pw_qpolynomial_fold, isl_obj_union_set,
589 isl_obj_union_pw_qpolynomial_fold,
590 (isc_bin_op_fn) &isl_union_pw_qpolynomial_fold_gist },
591 { ISL_TOKEN_EQ_EQ, isl_obj_union_pw_qpolynomial,
592 isl_obj_union_pw_qpolynomial, isl_obj_bool,
593 { .test = (isc_bin_test_fn)
594 &isl_union_pw_qpolynomial_plain_is_equal } },
595 { ISL_TOKEN_EQ_EQ, isl_obj_union_pw_qpolynomial_fold,
596 isl_obj_union_pw_qpolynomial_fold, isl_obj_bool,
597 { .test = (isc_bin_test_fn)
598 &isl_union_pw_qpolynomial_fold_plain_is_equal } },
599 { '+', isl_obj_str, isl_obj_str, isl_obj_str,
600 (isc_bin_op_fn) &isl_str_concat },
601 { '=', isl_obj_str, isl_obj_str, isl_obj_bool,
602 { .test = (isc_bin_test_fn) &str_eq } },
606 struct iscc_compound_bin_op compound_bin_ops[] = {
607 { "->*", ISL_TOKEN_TO, '*',
608 { -1, isl_obj_union_map, isl_obj_union_set,
609 isl_obj_union_map,
610 (isc_bin_op_fn) &isl_union_map_intersect_range } },
611 { "->-", ISL_TOKEN_TO, '-',
612 { -1, isl_obj_union_map, isl_obj_union_set,
613 isl_obj_union_map,
614 (isc_bin_op_fn) &isl_union_map_subtract_range } },
618 static __isl_give isl_union_map *map_after_map(__isl_take isl_union_map *umap1,
619 __isl_take isl_union_map *umap2)
621 return isl_union_map_apply_range(umap2, umap1);
624 static __isl_give isl_union_pw_qpolynomial *qpolynomial_after_map(
625 __isl_take isl_union_pw_qpolynomial *upwqp,
626 __isl_take isl_union_map *umap)
628 return isl_union_map_apply_union_pw_qpolynomial(umap, upwqp);
631 static __isl_give struct isl_list *qpolynomial_fold_after_map(
632 __isl_take isl_union_pw_qpolynomial_fold *upwf,
633 __isl_take isl_union_map *umap)
635 return union_map_apply_union_pw_qpolynomial_fold(umap, upwf);
638 struct isc_named_bin_op named_bin_ops[] = {
639 { "after", { -1, isl_obj_union_map, isl_obj_union_map,
640 isl_obj_union_map,
641 (isc_bin_op_fn) &map_after_map } },
642 { "after", { -1, isl_obj_union_pw_qpolynomial,
643 isl_obj_union_map, isl_obj_union_pw_qpolynomial,
644 (isc_bin_op_fn) &qpolynomial_after_map } },
645 { "after", { -1, isl_obj_union_pw_qpolynomial_fold,
646 isl_obj_union_map, isl_obj_list,
647 (isc_bin_op_fn) &qpolynomial_fold_after_map } },
648 { "before", { -1, isl_obj_union_map, isl_obj_union_map,
649 isl_obj_union_map,
650 (isc_bin_op_fn) &isl_union_map_apply_range } },
651 { "before", { -1, isl_obj_union_map,
652 isl_obj_union_pw_qpolynomial, isl_obj_union_pw_qpolynomial,
653 (isc_bin_op_fn) &isl_union_map_apply_union_pw_qpolynomial } },
654 { "before", { -1, isl_obj_union_map,
655 isl_obj_union_pw_qpolynomial_fold, isl_obj_list,
656 (isc_bin_op_fn) &union_map_apply_union_pw_qpolynomial_fold } },
657 { "cross", { -1, isl_obj_union_set, isl_obj_union_set,
658 isl_obj_union_set,
659 (isc_bin_op_fn) &isl_union_set_product } },
660 { "cross", { -1, isl_obj_union_map, isl_obj_union_map,
661 isl_obj_union_map,
662 (isc_bin_op_fn) &isl_union_map_product } },
663 NULL
666 __isl_give isl_set *union_set_sample(__isl_take isl_union_set *uset)
668 return isl_set_from_basic_set(isl_union_set_sample(uset));
671 __isl_give isl_map *union_map_sample(__isl_take isl_union_map *umap)
673 return isl_map_from_basic_map(isl_union_map_sample(umap));
676 static __isl_give struct isl_list *union_map_power(
677 __isl_take isl_union_map *umap)
679 isl_ctx *ctx;
680 struct isl_list *list;
681 int exact;
683 ctx = isl_union_map_get_ctx(umap);
684 list = isl_list_alloc(ctx, 2);
685 if (!list)
686 goto error2;
688 list->obj[0].type = isl_obj_union_map;
689 list->obj[0].v = isl_union_map_power(umap, &exact);
690 list->obj[1].type = isl_obj_bool;
691 list->obj[1].v = exact ? &iscc_bool_true : &iscc_bool_false;
692 if (exact < 0 || !list->obj[0].v)
693 goto error;
695 return list;
696 error2:
697 isl_union_map_free(umap);
698 error:
699 isl_list_free(list);
700 return NULL;
703 /* Compute a lower or upper bound on "upwqp" depending on "type" and
704 * return a list containing two elements, the bound and a boolean
705 * indicating whether the result is tight.
707 static __isl_give struct isl_list *union_pw_qpolynomial_bound(
708 __isl_take isl_union_pw_qpolynomial *upwqp, enum isl_fold type)
710 isl_ctx *ctx;
711 struct isl_list *list;
712 int tight;
714 ctx = isl_union_pw_qpolynomial_get_ctx(upwqp);
715 list = isl_list_alloc(ctx, 2);
716 if (!list)
717 goto error2;
719 list->obj[0].type = isl_obj_union_pw_qpolynomial_fold;
720 list->obj[0].v = isl_union_pw_qpolynomial_bound(upwqp, type, &tight);
721 list->obj[1].type = isl_obj_bool;
722 list->obj[1].v = tight ? &iscc_bool_true : &iscc_bool_false;
723 if (tight < 0 || !list->obj[0].v)
724 goto error;
726 return list;
727 error2:
728 isl_union_pw_qpolynomial_free(upwqp);
729 error:
730 isl_list_free(list);
731 return NULL;
734 /* Compute a lower bound on "upwqp" and return a list containing
735 * two elements, the bound and a booleanindicating whether
736 * the result is tight.
738 static __isl_give struct isl_list *union_pw_qpolynomial_lower_bound(
739 __isl_take isl_union_pw_qpolynomial *upwqp)
741 return union_pw_qpolynomial_bound(upwqp, isl_fold_min);
744 /* Compute a upper bound on "upwqp" and return a list containing
745 * two elements, the bound and a booleanindicating whether
746 * the result is tight.
748 static __isl_give struct isl_list *union_pw_qpolynomial_upper_bound(
749 __isl_take isl_union_pw_qpolynomial *upwqp)
751 return union_pw_qpolynomial_bound(upwqp, isl_fold_max);
754 #ifdef HAVE_PET
755 static __isl_give isl_list *parse(__isl_take isl_str *str)
757 isl_ctx *ctx;
758 struct isl_list *list;
759 struct pet_scop *scop;
760 isl_schedule *sched;
761 isl_union_map *may_reads, *must_writes, *may_writes;
762 isl_union_set *domain;
763 struct iscc_options *options;
765 if (!str)
766 return NULL;
767 ctx = str->ctx;
769 options = isl_ctx_peek_iscc_options(ctx);
770 if (!options || !options->io) {
771 isl_str_free(str);
772 isl_die(ctx, isl_error_invalid,
773 "parse_file operation not allowed", return NULL);
776 list = isl_list_alloc(ctx, 5);
777 if (!list)
778 goto error;
780 scop = pet_scop_extract_from_C_source(ctx, str->s, NULL);
781 domain = pet_scop_collect_domains(scop);
782 sched = scop ? isl_schedule_copy(scop->schedule) : NULL;
783 may_reads = pet_scop_collect_may_reads(scop);
784 may_writes = pet_scop_collect_may_writes(scop);
785 must_writes = pet_scop_collect_must_writes(scop);
786 pet_scop_free(scop);
788 list->obj[0].type = isl_obj_union_set;
789 list->obj[0].v = domain;
790 list->obj[1].type = isl_obj_union_map;
791 list->obj[1].v = must_writes;
792 list->obj[2].type = isl_obj_union_map;
793 list->obj[2].v = may_writes;
794 list->obj[3].type = isl_obj_union_map;
795 list->obj[3].v = may_reads;
796 list->obj[4].type = isl_obj_schedule;
797 list->obj[4].v = sched;
799 if (!list->obj[0].v || !list->obj[1].v ||
800 !list->obj[2].v || !list->obj[3].v || !list->obj[4].v)
801 goto error;
803 isl_str_free(str);
804 return list;
805 error:
806 isl_list_free(list);
807 isl_str_free(str);
808 return NULL;
810 #endif
812 static isl_stat add_point(__isl_take isl_point *pnt, void *user)
814 isl_union_set **scan = (isl_union_set **) user;
816 *scan = isl_union_set_add_set(*scan, isl_set_from_point(pnt));
818 return isl_stat_ok;
821 static __isl_give isl_union_set *union_set_scan(__isl_take isl_union_set *uset)
823 isl_union_set *scan;
825 scan = isl_union_set_empty(isl_union_set_get_space(uset));
827 if (isl_union_set_foreach_point(uset, add_point, &scan) < 0) {
828 isl_union_set_free(scan);
829 return uset;
832 isl_union_set_free(uset);
833 return scan;
836 static __isl_give isl_union_map *union_map_scan(__isl_take isl_union_map *umap)
838 return isl_union_set_unwrap(union_set_scan(isl_union_map_wrap(umap)));
841 static __isl_give isl_union_pw_qpolynomial *union_pw_qpolynomial_poly(
842 __isl_take isl_union_pw_qpolynomial *upwqp)
844 return isl_union_pw_qpolynomial_to_polynomial(upwqp, 0);
847 static __isl_give isl_union_pw_qpolynomial *union_pw_qpolynomial_lpoly(
848 __isl_take isl_union_pw_qpolynomial *upwqp)
850 return isl_union_pw_qpolynomial_to_polynomial(upwqp, -1);
853 static __isl_give isl_union_pw_qpolynomial *union_pw_qpolynomial_upoly(
854 __isl_take isl_union_pw_qpolynomial *upwqp)
856 return isl_union_pw_qpolynomial_to_polynomial(upwqp, 1);
859 /* Return the domain of "schedule".
861 static __isl_give isl_union_set *schedule_domain(
862 __isl_take isl_schedule *schedule)
864 isl_union_set *domain;
866 domain = isl_schedule_get_domain(schedule);
867 isl_schedule_free(schedule);
869 return domain;
872 /* Convert "schedule" to a union map representation.
874 static __isl_give isl_union_map *schedule_map(__isl_take isl_schedule *schedule)
876 isl_union_map *map;
878 map = isl_schedule_get_map(schedule);
879 isl_schedule_free(schedule);
881 return map;
884 typedef void *(*isc_un_op_fn)(void *arg);
885 struct isc_un_op {
886 enum isl_token_type op;
887 isl_obj_type arg;
888 isl_obj_type res;
889 isc_un_op_fn fn;
891 struct isc_named_un_op {
892 char *name;
893 struct isc_un_op op;
895 struct isc_named_un_op named_un_ops[] = {
896 {"aff", { -1, isl_obj_union_map, isl_obj_union_map,
897 (isc_un_op_fn) &isl_union_map_affine_hull } },
898 {"aff", { -1, isl_obj_union_set, isl_obj_union_set,
899 (isc_un_op_fn) &isl_union_set_affine_hull } },
900 {"card", { -1, isl_obj_union_set,
901 isl_obj_union_pw_qpolynomial,
902 (isc_un_op_fn) &isl_union_set_card } },
903 {"card", { -1, isl_obj_union_map,
904 isl_obj_union_pw_qpolynomial,
905 (isc_un_op_fn) &isl_union_map_card } },
906 {"coalesce", { -1, isl_obj_union_set, isl_obj_union_set,
907 (isc_un_op_fn) &isl_union_set_coalesce } },
908 {"coalesce", { -1, isl_obj_union_map, isl_obj_union_map,
909 (isc_un_op_fn) &isl_union_map_coalesce } },
910 {"coalesce", { -1, isl_obj_union_pw_qpolynomial,
911 isl_obj_union_pw_qpolynomial,
912 (isc_un_op_fn) &isl_union_pw_qpolynomial_coalesce } },
913 {"coalesce", { -1, isl_obj_union_pw_qpolynomial_fold,
914 isl_obj_union_pw_qpolynomial_fold,
915 (isc_un_op_fn) &isl_union_pw_qpolynomial_fold_coalesce } },
916 {"coefficients", { -1, isl_obj_union_set,
917 isl_obj_union_set,
918 (isc_un_op_fn) &isl_union_set_coefficients } },
919 {"solutions", { -1, isl_obj_union_set, isl_obj_union_set,
920 (isc_un_op_fn) &isl_union_set_solutions } },
921 {"deltas", { -1, isl_obj_union_map, isl_obj_union_set,
922 (isc_un_op_fn) &isl_union_map_deltas } },
923 {"deltas_map", { -1, isl_obj_union_map, isl_obj_union_map,
924 (isc_un_op_fn) &isl_union_map_deltas_map } },
925 {"dom", { -1, isl_obj_schedule, isl_obj_union_set,
926 (isc_un_op_fn) &schedule_domain } },
927 {"dom", { -1, isl_obj_union_map, isl_obj_union_set,
928 (isc_un_op_fn) &isl_union_map_domain } },
929 {"dom", { -1, isl_obj_union_pw_qpolynomial, isl_obj_union_set,
930 (isc_un_op_fn) &isl_union_pw_qpolynomial_domain } },
931 {"dom", { -1, isl_obj_union_pw_qpolynomial_fold,
932 isl_obj_union_set,
933 (isc_un_op_fn) &isl_union_pw_qpolynomial_fold_domain } },
934 {"domain", { -1, isl_obj_schedule, isl_obj_union_set,
935 (isc_un_op_fn) &schedule_domain } },
936 {"domain", { -1, isl_obj_union_map, isl_obj_union_set,
937 (isc_un_op_fn) &isl_union_map_domain } },
938 {"domain", { -1, isl_obj_union_pw_qpolynomial,
939 isl_obj_union_set,
940 (isc_un_op_fn) &isl_union_pw_qpolynomial_domain } },
941 {"domain", { -1, isl_obj_union_pw_qpolynomial_fold,
942 isl_obj_union_set,
943 (isc_un_op_fn) &isl_union_pw_qpolynomial_fold_domain } },
944 {"domain_map", { -1, isl_obj_union_map, isl_obj_union_map,
945 (isc_un_op_fn) &isl_union_map_domain_map } },
946 {"ran", { -1, isl_obj_union_map, isl_obj_union_set,
947 (isc_un_op_fn) &isl_union_map_range } },
948 {"range", { -1, isl_obj_union_map, isl_obj_union_set,
949 (isc_un_op_fn) &isl_union_map_range } },
950 {"range_map", { -1, isl_obj_union_map, isl_obj_union_map,
951 (isc_un_op_fn) &isl_union_map_range_map } },
952 {"identity", { -1, isl_obj_union_set, isl_obj_union_map,
953 (isc_un_op_fn) &isl_union_set_identity } },
954 {"lattice_width", { -1, isl_obj_union_set,
955 isl_obj_union_pw_qpolynomial,
956 (isc_un_op_fn) &isl_union_set_lattice_width } },
957 {"lb", { -1, isl_obj_union_pw_qpolynomial, isl_obj_list,
958 (isc_un_op_fn) &union_pw_qpolynomial_lower_bound } },
959 {"lexmin", { -1, isl_obj_union_map, isl_obj_union_map,
960 (isc_un_op_fn) &isl_union_map_lexmin } },
961 {"lexmax", { -1, isl_obj_union_map, isl_obj_union_map,
962 (isc_un_op_fn) &isl_union_map_lexmax } },
963 {"lexmin", { -1, isl_obj_union_set, isl_obj_union_set,
964 (isc_un_op_fn) &isl_union_set_lexmin } },
965 {"lexmax", { -1, isl_obj_union_set, isl_obj_union_set,
966 (isc_un_op_fn) &isl_union_set_lexmax } },
967 {"lift", { -1, isl_obj_union_set, isl_obj_union_set,
968 (isc_un_op_fn) &isl_union_set_lift } },
969 {"map", { -1, isl_obj_schedule, isl_obj_union_map,
970 (isc_un_op_fn) &schedule_map } },
971 {"params", { -1, isl_obj_union_map, isl_obj_set,
972 (isc_un_op_fn) &isl_union_map_params } },
973 {"params", { -1, isl_obj_union_set, isl_obj_set,
974 (isc_un_op_fn) &isl_union_set_params } },
975 {"poly", { -1, isl_obj_union_map, isl_obj_union_map,
976 (isc_un_op_fn) &isl_union_map_polyhedral_hull } },
977 {"poly", { -1, isl_obj_union_set, isl_obj_union_set,
978 (isc_un_op_fn) &isl_union_set_polyhedral_hull } },
979 {"poly", { -1, isl_obj_union_pw_qpolynomial,
980 isl_obj_union_pw_qpolynomial,
981 (isc_un_op_fn) &union_pw_qpolynomial_poly } },
982 {"lpoly", { -1, isl_obj_union_pw_qpolynomial,
983 isl_obj_union_pw_qpolynomial,
984 (isc_un_op_fn) &union_pw_qpolynomial_lpoly } },
985 {"upoly", { -1, isl_obj_union_pw_qpolynomial,
986 isl_obj_union_pw_qpolynomial,
987 (isc_un_op_fn) &union_pw_qpolynomial_upoly } },
988 #ifdef HAVE_PET
989 {"parse_file", { -1, isl_obj_str, isl_obj_list,
990 (isc_un_op_fn) &parse } },
991 #endif
992 {"pow", { -1, isl_obj_union_map, isl_obj_list,
993 (isc_un_op_fn) &union_map_power } },
994 {"sample", { -1, isl_obj_union_set, isl_obj_set,
995 (isc_un_op_fn) &union_set_sample } },
996 {"sample", { -1, isl_obj_union_map, isl_obj_map,
997 (isc_un_op_fn) &union_map_sample } },
998 {"scan", { -1, isl_obj_union_set, isl_obj_union_set,
999 (isc_un_op_fn) &union_set_scan } },
1000 {"scan", { -1, isl_obj_union_map, isl_obj_union_map,
1001 (isc_un_op_fn) &union_map_scan } },
1002 {"sum", { -1, isl_obj_union_pw_qpolynomial,
1003 isl_obj_union_pw_qpolynomial,
1004 (isc_un_op_fn) &isl_union_pw_qpolynomial_sum } },
1005 {"ub", { -1, isl_obj_union_pw_qpolynomial, isl_obj_list,
1006 (isc_un_op_fn) &union_pw_qpolynomial_upper_bound } },
1007 {"unwrap", { -1, isl_obj_union_set, isl_obj_union_map,
1008 (isc_un_op_fn) &isl_union_set_unwrap } },
1009 {"wrap", { -1, isl_obj_union_map, isl_obj_union_set,
1010 (isc_un_op_fn) &isl_union_map_wrap } },
1011 {"zip", { -1, isl_obj_union_map, isl_obj_union_map,
1012 (isc_un_op_fn) &isl_union_map_zip } },
1013 NULL
1016 struct isl_named_obj {
1017 char *name;
1018 struct isl_obj obj;
1021 static void free_obj(struct isl_obj obj)
1023 obj.type->free(obj.v);
1026 static int same_name(const void *entry, const void *val)
1028 const struct isl_named_obj *named = (const struct isl_named_obj *)entry;
1030 return !strcmp(named->name, val);
1033 static int do_assign(struct isl_ctx *ctx, struct isl_hash_table *table,
1034 char *name, struct isl_obj obj)
1036 struct isl_hash_table_entry *entry;
1037 uint32_t name_hash;
1038 struct isl_named_obj *named;
1040 name_hash = isl_hash_string(isl_hash_init(), name);
1041 entry = isl_hash_table_find(ctx, table, name_hash, same_name, name, 1);
1042 if (!entry)
1043 goto error;
1044 if (entry->data) {
1045 named = entry->data;
1046 free_obj(named->obj);
1047 free(name);
1048 } else {
1049 named = isl_alloc_type(ctx, struct isl_named_obj);
1050 if (!named)
1051 goto error;
1052 named->name = name;
1053 entry->data = named;
1055 named->obj = obj;
1057 return 0;
1058 error:
1059 free_obj(obj);
1060 free(name);
1061 return -1;
1064 static struct isl_obj stored_obj(struct isl_ctx *ctx,
1065 struct isl_hash_table *table, char *name)
1067 struct isl_obj obj = { isl_obj_none, NULL };
1068 struct isl_hash_table_entry *entry;
1069 uint32_t name_hash;
1071 name_hash = isl_hash_string(isl_hash_init(), name);
1072 entry = isl_hash_table_find(ctx, table, name_hash, same_name, name, 0);
1073 if (entry) {
1074 struct isl_named_obj *named;
1075 named = entry->data;
1076 obj = named->obj;
1077 } else if (isdigit(name[0]))
1078 fprintf(stderr, "unknown identifier '$%s'\n", name);
1079 else
1080 fprintf(stderr, "unknown identifier '%s'\n", name);
1082 free(name);
1083 obj.v = obj.type->copy(obj.v);
1084 return obj;
1087 static int is_subtype(struct isl_obj obj, isl_obj_type super)
1089 if (obj.type == super)
1090 return 1;
1091 if (obj.type == isl_obj_map && super == isl_obj_union_map)
1092 return 1;
1093 if (obj.type == isl_obj_set && super == isl_obj_union_set)
1094 return 1;
1095 if (obj.type == isl_obj_schedule && super == isl_obj_union_map)
1096 return 1;
1097 if (obj.type == isl_obj_pw_multi_aff && super == isl_obj_union_set) {
1098 isl_space *space = isl_pw_multi_aff_get_space(obj.v);
1099 int is_set = isl_space_is_set(space);
1100 isl_space_free(space);
1101 return is_set;
1103 if (obj.type == isl_obj_pw_qpolynomial &&
1104 super == isl_obj_union_pw_qpolynomial)
1105 return 1;
1106 if (obj.type == isl_obj_pw_qpolynomial_fold &&
1107 super == isl_obj_union_pw_qpolynomial_fold)
1108 return 1;
1109 if (obj.type == isl_obj_union_set && isl_union_set_is_empty(obj.v))
1110 return 1;
1111 if (obj.type == isl_obj_list) {
1112 struct isl_list *list = obj.v;
1113 if (list->n == 2 && list->obj[1].type == isl_obj_bool)
1114 return is_subtype(list->obj[0], super);
1116 if (super == isl_obj_str)
1117 return 1;
1118 return 0;
1121 static struct isl_obj obj_at(struct isl_obj obj, int i)
1123 struct isl_list *list = obj.v;
1125 obj = list->obj[i];
1126 obj.v = obj.type->copy(obj.v);
1128 isl_list_free(list);
1130 return obj;
1133 static struct isl_obj convert(isl_ctx *ctx, struct isl_obj obj,
1134 isl_obj_type type)
1136 if (obj.type == type)
1137 return obj;
1138 if (obj.type == isl_obj_pw_multi_aff && type == isl_obj_union_set) {
1139 isl_set *set = isl_set_from_pw_multi_aff(obj.v);
1140 obj.type = isl_obj_union_set;
1141 obj.v = isl_union_set_from_set(set);
1142 return obj;
1144 if (obj.type == isl_obj_map && type == isl_obj_union_map) {
1145 obj.type = isl_obj_union_map;
1146 obj.v = isl_union_map_from_map(obj.v);
1147 return obj;
1149 if (obj.type == isl_obj_schedule && type == isl_obj_union_map) {
1150 obj.type = isl_obj_union_map;
1151 obj.v = schedule_map(obj.v);
1152 return obj;
1154 if (obj.type == isl_obj_set && type == isl_obj_union_set) {
1155 obj.type = isl_obj_union_set;
1156 obj.v = isl_union_set_from_set(obj.v);
1157 return obj;
1159 if (obj.type == isl_obj_pw_qpolynomial &&
1160 type == isl_obj_union_pw_qpolynomial) {
1161 obj.type = isl_obj_union_pw_qpolynomial;
1162 obj.v = isl_union_pw_qpolynomial_from_pw_qpolynomial(obj.v);
1163 return obj;
1165 if (obj.type == isl_obj_pw_qpolynomial_fold &&
1166 type == isl_obj_union_pw_qpolynomial_fold) {
1167 obj.type = isl_obj_union_pw_qpolynomial_fold;
1168 obj.v = isl_union_pw_qpolynomial_fold_from_pw_qpolynomial_fold(obj.v);
1169 return obj;
1171 if (obj.type == isl_obj_union_set && isl_union_set_is_empty(obj.v)) {
1172 if (type == isl_obj_union_map) {
1173 obj.type = isl_obj_union_map;
1174 return obj;
1176 if (type == isl_obj_union_pw_qpolynomial) {
1177 isl_space *dim = isl_union_set_get_space(obj.v);
1178 isl_union_set_free(obj.v);
1179 obj.v = isl_union_pw_qpolynomial_zero(dim);
1180 obj.type = isl_obj_union_pw_qpolynomial;
1181 return obj;
1183 if (type == isl_obj_union_pw_qpolynomial_fold) {
1184 isl_space *dim = isl_union_set_get_space(obj.v);
1185 isl_union_set_free(obj.v);
1186 obj.v = isl_union_pw_qpolynomial_fold_zero(dim,
1187 isl_fold_list);
1188 obj.type = isl_obj_union_pw_qpolynomial_fold;
1189 return obj;
1192 if (obj.type == isl_obj_list) {
1193 struct isl_list *list = obj.v;
1194 if (list->n == 2 && list->obj[1].type == isl_obj_bool)
1195 return convert(ctx, obj_at(obj, 0), type);
1197 if (type == isl_obj_str) {
1198 isl_str *str;
1199 isl_printer *p;
1200 char *s;
1202 p = isl_printer_to_str(ctx);
1203 if (!p)
1204 goto error;
1205 p = obj.type->print(p, obj.v);
1206 s = isl_printer_get_str(p);
1207 isl_printer_free(p);
1209 str = isl_str_from_string(ctx, s);
1210 if (!str)
1211 goto error;
1212 free_obj(obj);
1213 obj.v = str;
1214 obj.type = isl_obj_str;
1215 return obj;
1218 error:
1219 free_obj(obj);
1220 obj.type = isl_obj_none;
1221 obj.v = NULL;
1222 return obj;
1225 static struct isc_bin_op *read_bin_op_if_available(struct isl_stream *s,
1226 struct isl_obj lhs)
1228 int i;
1229 int read_tok2 = 0;
1230 struct isl_token *tok, *tok2;
1232 tok = isl_stream_next_token(s);
1233 if (!tok)
1234 return NULL;
1236 for (i = 0; ; ++i) {
1237 if (!bin_ops[i].op)
1238 break;
1239 if (bin_ops[i].op != isl_token_get_type(tok))
1240 continue;
1241 if (!is_subtype(lhs, bin_ops[i].lhs))
1242 continue;
1244 isl_token_free(tok);
1245 return &bin_ops[i];
1248 for (i = 0; ; ++i) {
1249 if (!named_bin_ops[i].name)
1250 break;
1251 if (named_bin_ops[i].op.op != isl_token_get_type(tok))
1252 continue;
1253 if (!is_subtype(lhs, named_bin_ops[i].op.lhs))
1254 continue;
1256 isl_token_free(tok);
1257 return &named_bin_ops[i].op;
1260 for (i = 0; ; ++i) {
1261 if (!compound_bin_ops[i].full)
1262 break;
1263 if (compound_bin_ops[i].op1 != isl_token_get_type(tok))
1264 continue;
1265 if (!read_tok2)
1266 tok2 = isl_stream_next_token(s);
1267 read_tok2 = 1;
1268 if (compound_bin_ops[i].op2 != isl_token_get_type(tok2))
1269 continue;
1270 if (!is_subtype(lhs, compound_bin_ops[i].op.lhs))
1271 continue;
1273 isl_token_free(tok2);
1274 isl_token_free(tok);
1275 return &compound_bin_ops[i].op;
1278 if (read_tok2)
1279 isl_stream_push_token(s, tok2);
1280 isl_stream_push_token(s, tok);
1282 return NULL;
1285 static struct isc_un_op *read_prefix_un_op_if_available(struct isl_stream *s)
1287 int i;
1288 struct isl_token *tok;
1290 tok = isl_stream_next_token(s);
1291 if (!tok)
1292 return NULL;
1294 for (i = 0; ; ++i) {
1295 if (!named_un_ops[i].name)
1296 break;
1297 if (named_un_ops[i].op.op != isl_token_get_type(tok))
1298 continue;
1300 isl_token_free(tok);
1301 return &named_un_ops[i].op;
1304 isl_stream_push_token(s, tok);
1306 return NULL;
1309 static struct isc_un_op *find_matching_un_op(struct isc_un_op *like,
1310 struct isl_obj arg)
1312 int i;
1314 for (i = 0; ; ++i) {
1315 if (!named_un_ops[i].name)
1316 break;
1317 if (named_un_ops[i].op.op != like->op)
1318 continue;
1319 if (!is_subtype(arg, named_un_ops[i].op.arg))
1320 continue;
1322 return &named_un_ops[i].op;
1325 return NULL;
1328 static int is_assign(struct isl_stream *s)
1330 struct isl_token *tok;
1331 struct isl_token *tok2;
1332 int assign;
1334 tok = isl_stream_next_token(s);
1335 if (!tok)
1336 return 0;
1337 if (isl_token_get_type(tok) != ISL_TOKEN_IDENT) {
1338 isl_stream_push_token(s, tok);
1339 return 0;
1342 tok2 = isl_stream_next_token(s);
1343 if (!tok2) {
1344 isl_stream_push_token(s, tok);
1345 return 0;
1347 assign = isl_token_get_type(tok2) == ISL_TOKEN_DEF;
1348 isl_stream_push_token(s, tok2);
1349 isl_stream_push_token(s, tok);
1351 return assign;
1354 static struct isl_obj read_obj(struct isl_stream *s,
1355 struct isl_hash_table *table);
1356 static struct isl_obj read_expr(struct isl_stream *s,
1357 struct isl_hash_table *table);
1359 static struct isl_obj read_un_op_expr(struct isl_stream *s,
1360 struct isl_hash_table *table, struct isc_un_op *op)
1362 isl_ctx *ctx;
1363 struct isl_obj obj = { isl_obj_none, NULL };
1365 obj = read_obj(s, table);
1366 if (!obj.v)
1367 goto error;
1369 op = find_matching_un_op(op, obj);
1371 ctx = isl_stream_get_ctx(s);
1372 if (!op)
1373 isl_die(ctx, isl_error_invalid,
1374 "no such unary operator defined on given operand",
1375 goto error);
1377 obj = convert(ctx, obj, op->arg);
1378 obj.v = op->fn(obj.v);
1379 obj.type = op->res;
1381 return obj;
1382 error:
1383 free_obj(obj);
1384 obj.type = isl_obj_none;
1385 obj.v = NULL;
1386 return obj;
1389 static struct isl_obj transitive_closure(struct isl_ctx *ctx, struct isl_obj obj)
1391 struct isl_list *list;
1392 int exact;
1394 if (obj.type != isl_obj_union_map)
1395 obj = convert(ctx, obj, isl_obj_union_map);
1396 isl_assert(ctx, obj.type == isl_obj_union_map, goto error);
1397 list = isl_list_alloc(ctx, 2);
1398 if (!list)
1399 goto error;
1401 list->obj[0].type = isl_obj_union_map;
1402 list->obj[0].v = isl_union_map_transitive_closure(obj.v, &exact);
1403 list->obj[1].type = isl_obj_bool;
1404 list->obj[1].v = exact ? &iscc_bool_true : &iscc_bool_false;
1405 obj.v = list;
1406 obj.type = isl_obj_list;
1407 if (exact < 0 || !list->obj[0].v)
1408 goto error;
1410 return obj;
1411 error:
1412 free_obj(obj);
1413 obj.type = isl_obj_none;
1414 obj.v = NULL;
1415 return obj;
1418 static struct isl_obj obj_at_index(struct isl_stream *s, struct isl_obj obj)
1420 struct isl_list *list = obj.v;
1421 struct isl_token *tok;
1422 isl_ctx *ctx;
1423 isl_val *v;
1424 int i;
1426 tok = isl_stream_next_token(s);
1427 if (!tok || isl_token_get_type(tok) != ISL_TOKEN_VALUE) {
1428 isl_stream_error(s, tok, "expecting index");
1429 if (tok)
1430 isl_stream_push_token(s, tok);
1431 goto error;
1433 ctx = isl_stream_get_ctx(s);
1434 v = isl_token_get_val(ctx, tok);
1435 i = isl_val_get_num_si(v);
1436 isl_val_free(v);
1437 isl_token_free(tok);
1438 isl_assert(ctx, i < list->n, goto error);
1439 if (isl_stream_eat(s, ']'))
1440 goto error;
1442 return obj_at(obj, i);
1443 error:
1444 free_obj(obj);
1445 obj.type = isl_obj_none;
1446 obj.v = NULL;
1447 return obj;
1450 static struct isl_obj apply(struct isl_stream *s, __isl_take isl_union_map *umap,
1451 struct isl_hash_table *table)
1453 isl_ctx *ctx;
1454 struct isl_obj obj;
1456 obj = read_expr(s, table);
1457 ctx = isl_stream_get_ctx(s);
1458 isl_assert(ctx, is_subtype(obj, isl_obj_union_set) ||
1459 is_subtype(obj, isl_obj_union_map), goto error);
1461 if (obj.type == isl_obj_list) {
1462 struct isl_list *list = obj.v;
1463 if (list->n == 2 && list->obj[1].type == isl_obj_bool)
1464 obj = obj_at(obj, 0);
1466 if (obj.type == isl_obj_set)
1467 obj = convert(ctx, obj, isl_obj_union_set);
1468 else if (obj.type == isl_obj_map)
1469 obj = convert(ctx, obj, isl_obj_union_map);
1470 if (obj.type == isl_obj_union_set) {
1471 obj.v = isl_union_set_apply(obj.v, umap);
1472 } else
1473 obj.v = isl_union_map_apply_range(obj.v, umap);
1474 if (!obj.v)
1475 goto error2;
1477 if (isl_stream_eat(s, ')'))
1478 goto error2;
1480 return obj;
1481 error:
1482 isl_union_map_free(umap);
1483 error2:
1484 free_obj(obj);
1485 obj.type = isl_obj_none;
1486 obj.v = NULL;
1487 return obj;
1490 static struct isl_obj apply_fun_set(struct isl_obj obj,
1491 __isl_take isl_union_set *uset)
1493 if (obj.type == isl_obj_union_pw_qpolynomial) {
1494 obj.v = isl_union_set_apply_union_pw_qpolynomial(uset, obj.v);
1495 } else {
1496 obj.type = isl_obj_list;
1497 obj.v = union_set_apply_union_pw_qpolynomial_fold(uset, obj.v);
1499 return obj;
1502 static struct isl_obj apply_fun_map(struct isl_obj obj,
1503 __isl_take isl_union_map *umap)
1505 if (obj.type == isl_obj_union_pw_qpolynomial) {
1506 obj.v = isl_union_map_apply_union_pw_qpolynomial(umap, obj.v);
1507 } else {
1508 obj.type = isl_obj_list;
1509 obj.v = union_map_apply_union_pw_qpolynomial_fold(umap, obj.v);
1511 return obj;
1514 static struct isl_obj apply_fun(struct isl_stream *s,
1515 struct isl_obj obj, struct isl_hash_table *table)
1517 struct isl_obj arg;
1518 isl_ctx *ctx;
1520 arg = read_expr(s, table);
1521 ctx = isl_stream_get_ctx(s);
1522 if (!is_subtype(arg, isl_obj_union_map) &&
1523 !is_subtype(arg, isl_obj_union_set))
1524 isl_die(ctx, isl_error_invalid,
1525 "expecting set of map argument", goto error);
1527 if (arg.type == isl_obj_list) {
1528 struct isl_list *list = arg.v;
1529 if (list->n == 2 && list->obj[1].type == isl_obj_bool)
1530 arg = obj_at(arg, 0);
1532 if (arg.type == isl_obj_set)
1533 arg = convert(ctx, arg, isl_obj_union_set);
1534 else if (arg.type == isl_obj_map)
1535 arg = convert(ctx, arg, isl_obj_union_map);
1536 if (arg.type == isl_obj_union_set)
1537 obj = apply_fun_set(obj, arg.v);
1538 else
1539 obj = apply_fun_map(obj, arg.v);
1540 if (!obj.v)
1541 goto error2;
1543 if (isl_stream_eat(s, ')'))
1544 goto error2;
1546 return obj;
1547 error:
1548 free_obj(arg);
1549 error2:
1550 free_obj(obj);
1551 obj.type = isl_obj_none;
1552 obj.v = NULL;
1553 return obj;
1556 struct add_vertex_data {
1557 struct isl_list *list;
1558 int i;
1561 static isl_stat add_vertex(__isl_take isl_vertex *vertex, void *user)
1563 struct add_vertex_data *data = (struct add_vertex_data *)user;
1564 isl_multi_aff *ma;
1565 isl_set *dom;
1567 ma = isl_vertex_get_expr(vertex);
1568 dom = isl_set_from_basic_set(isl_vertex_get_domain(vertex));
1570 data->list->obj[data->i].type = isl_obj_pw_multi_aff;
1571 data->list->obj[data->i].v = isl_pw_multi_aff_alloc(dom, ma);
1572 data->i++;
1574 isl_vertex_free(vertex);
1576 return isl_stat_ok;
1579 static isl_stat set_vertices(__isl_take isl_set *set, void *user)
1581 isl_ctx *ctx;
1582 isl_basic_set *hull;
1583 isl_vertices *vertices = NULL;
1584 struct isl_list *list = NULL;
1585 isl_stat r;
1586 struct add_vertex_data *data = (struct add_vertex_data *)user;
1588 set = isl_set_remove_divs(set);
1589 hull = isl_set_convex_hull(set);
1590 vertices = isl_basic_set_compute_vertices(hull);
1591 isl_basic_set_free(hull);
1593 list = data->list;
1595 ctx = isl_vertices_get_ctx(vertices);
1596 data->list = isl_list_alloc(ctx, isl_vertices_get_n_vertices(vertices));
1597 if (!data->list)
1598 goto error;
1600 data->i = 0;
1601 r = isl_vertices_foreach_vertex(vertices, &add_vertex, user);
1603 data->list = isl_list_concat(list, data->list);
1605 isl_vertices_free(vertices);
1607 return r;
1608 error:
1609 data->list = list;
1610 isl_vertices_free(vertices);
1611 return isl_stat_error;
1614 static struct isl_obj vertices(struct isl_stream *s,
1615 struct isl_hash_table *table)
1617 isl_ctx *ctx;
1618 struct isl_obj obj;
1619 struct isl_list *list = NULL;
1620 isl_union_set *uset = NULL;
1621 struct add_vertex_data data = { NULL };
1623 obj = read_expr(s, table);
1624 ctx = isl_stream_get_ctx(s);
1625 obj = convert(ctx, obj, isl_obj_union_set);
1626 isl_assert(ctx, obj.type == isl_obj_union_set, goto error);
1627 uset = obj.v;
1628 obj.v = NULL;
1630 list = isl_list_alloc(ctx, 0);
1631 if (!list)
1632 goto error;
1634 data.list = list;
1636 if (isl_union_set_foreach_set(uset, &set_vertices, &data) < 0)
1637 goto error;
1639 isl_union_set_free(uset);
1641 obj.type = isl_obj_list;
1642 obj.v = data.list;
1644 return obj;
1645 error:
1646 isl_union_set_free(uset);
1647 isl_list_free(data.list);
1648 free_obj(obj);
1649 obj.type = isl_obj_none;
1650 obj.v = NULL;
1651 return obj;
1654 static struct isl_obj type_of(struct isl_stream *s,
1655 struct isl_hash_table *table)
1657 isl_ctx *ctx;
1658 struct isl_obj obj;
1659 const char *type = "unknown";
1661 obj = read_expr(s, table);
1663 if (obj.type == isl_obj_map ||
1664 obj.type == isl_obj_union_map)
1665 type = "map";
1666 if (obj.type == isl_obj_set ||
1667 obj.type == isl_obj_union_set)
1668 type = "set";
1669 if (obj.type == isl_obj_pw_multi_aff)
1670 type = "piecewise multi-quasiaffine expression";
1671 if (obj.type == isl_obj_pw_qpolynomial ||
1672 obj.type == isl_obj_union_pw_qpolynomial)
1673 type = "piecewise quasipolynomial";
1674 if (obj.type == isl_obj_pw_qpolynomial_fold ||
1675 obj.type == isl_obj_union_pw_qpolynomial_fold)
1676 type = "piecewise quasipolynomial fold";
1677 if (obj.type == isl_obj_list)
1678 type = "list";
1679 if (obj.type == isl_obj_bool)
1680 type = "boolean";
1681 if (obj.type == isl_obj_str)
1682 type = "string";
1683 if (obj.type == isl_obj_val)
1684 type = "value";
1685 if (obj.type == isl_obj_schedule)
1686 type = "schedule";
1688 free_obj(obj);
1689 obj.type = isl_obj_str;
1690 obj.v = isl_str_from_string(isl_stream_get_ctx(s), strdup(type));
1692 return obj;
1695 static __isl_give isl_union_set *read_set(struct isl_stream *s,
1696 struct isl_hash_table *table)
1698 struct isl_obj obj;
1699 isl_ctx *ctx;
1701 obj = read_obj(s, table);
1702 ctx = isl_stream_get_ctx(s);
1703 obj = convert(ctx, obj, isl_obj_union_set);
1704 isl_assert(ctx, obj.type == isl_obj_union_set, goto error);
1705 return obj.v;
1706 error:
1707 free_obj(obj);
1708 return NULL;
1711 static __isl_give isl_union_map *read_map(struct isl_stream *s,
1712 struct isl_hash_table *table)
1714 struct isl_obj obj;
1715 isl_ctx *ctx;
1717 obj = read_obj(s, table);
1718 ctx = isl_stream_get_ctx(s);
1719 obj = convert(ctx, obj, isl_obj_union_map);
1720 isl_assert(ctx, obj.type == isl_obj_union_map, goto error);
1721 return obj.v;
1722 error:
1723 free_obj(obj);
1724 return NULL;
1727 /* Read a schedule in the form of either a schedule (tree) or a union map
1728 * from "s" and store the schedule in "access".
1730 static __isl_give isl_union_access_info *access_info_set_schedule(
1731 __isl_take isl_union_access_info *access, struct isl_stream *s,
1732 struct isl_hash_table *table)
1734 struct isl_obj obj;
1735 isl_ctx *ctx;
1737 obj = read_obj(s, table);
1738 if (obj.type == isl_obj_schedule)
1739 return isl_union_access_info_set_schedule(access, obj.v);
1740 ctx = isl_stream_get_ctx(s);
1741 obj = convert(ctx, obj, isl_obj_union_map);
1743 return isl_union_access_info_set_schedule_map(access, obj.v);
1746 static struct isl_obj last_any(struct isl_stream *s,
1747 struct isl_hash_table *table, __isl_take isl_union_map *must_source,
1748 __isl_take isl_union_map *may_source)
1750 struct isl_obj obj = { isl_obj_none, NULL };
1751 isl_union_access_info *access;
1752 isl_union_flow *flow;
1753 isl_union_map *sink = NULL;
1754 isl_union_map *may_dep;
1756 if (isl_stream_eat(s, iscc_op[ISCC_BEFORE]))
1757 goto error;
1759 sink = read_map(s, table);
1760 if (!sink)
1761 goto error;
1763 if (isl_stream_eat(s, iscc_op[ISCC_UNDER]))
1764 goto error;
1766 access = isl_union_access_info_from_sink(sink);
1767 access = isl_union_access_info_set_must_source(access, must_source);
1768 access = isl_union_access_info_set_may_source(access, may_source);
1769 access = access_info_set_schedule(access, s, table);
1770 flow = isl_union_access_info_compute_flow(access);
1771 may_dep = isl_union_flow_get_may_dependence(flow);
1772 isl_union_flow_free(flow);
1774 if (!may_dep)
1775 return obj;
1777 obj.type = isl_obj_union_map;
1778 obj.v = may_dep;
1780 return obj;
1781 error:
1782 isl_union_map_free(may_source);
1783 isl_union_map_free(must_source);
1784 isl_union_map_free(sink);
1785 free_obj(obj);
1786 obj.type = isl_obj_none;
1787 obj.v = NULL;
1788 return obj;
1791 static struct isl_obj any(struct isl_stream *s, struct isl_hash_table *table)
1793 struct isl_obj obj = { isl_obj_none, NULL };
1794 isl_union_access_info *access;
1795 isl_union_flow *flow;
1796 isl_union_map *may_source = NULL;
1797 isl_union_map *sink = NULL;
1798 isl_union_map *may_dep;
1800 may_source = read_map(s, table);
1801 if (!may_source)
1802 goto error;
1804 if (isl_stream_eat_if_available(s, iscc_op[ISCC_LAST])) {
1805 isl_union_map *must_source;
1806 must_source = read_map(s, table);
1807 if (!must_source)
1808 goto error;
1809 return last_any(s, table, must_source, may_source);
1812 if (isl_stream_eat(s, iscc_op[ISCC_BEFORE]))
1813 goto error;
1815 sink = read_map(s, table);
1816 if (!sink)
1817 goto error;
1819 if (isl_stream_eat(s, iscc_op[ISCC_UNDER]))
1820 goto error;
1822 access = isl_union_access_info_from_sink(sink);
1823 access = isl_union_access_info_set_may_source(access, may_source);
1824 access = access_info_set_schedule(access, s, table);
1825 flow = isl_union_access_info_compute_flow(access);
1826 may_dep = isl_union_flow_get_may_dependence(flow);
1827 isl_union_flow_free(flow);
1829 if (!may_dep)
1830 return obj;
1832 obj.type = isl_obj_union_map;
1833 obj.v = may_dep;
1835 return obj;
1836 error:
1837 isl_union_map_free(may_source);
1838 isl_union_map_free(sink);
1839 free_obj(obj);
1840 obj.type = isl_obj_none;
1841 obj.v = NULL;
1842 return obj;
1845 static struct isl_obj last(struct isl_stream *s, struct isl_hash_table *table)
1847 struct isl_obj obj = { isl_obj_none, NULL };
1848 struct isl_list *list = NULL;
1849 isl_union_access_info *access;
1850 isl_union_flow *flow;
1851 isl_union_map *must_source = NULL;
1852 isl_union_map *sink = NULL;
1853 isl_union_map *must_dep;
1854 isl_union_map *must_no_source;
1856 must_source = read_map(s, table);
1857 if (!must_source)
1858 goto error;
1860 if (isl_stream_eat_if_available(s, iscc_op[ISCC_ANY])) {
1861 isl_union_map *may_source;
1862 may_source = read_map(s, table);
1863 if (!may_source)
1864 goto error;
1865 return last_any(s, table, must_source, may_source);
1868 list = isl_list_alloc(isl_stream_get_ctx(s), 2);
1869 if (!list)
1870 goto error;
1872 if (isl_stream_eat(s, iscc_op[ISCC_BEFORE]))
1873 goto error;
1875 sink = read_map(s, table);
1876 if (!sink)
1877 goto error;
1879 if (isl_stream_eat(s, iscc_op[ISCC_UNDER]))
1880 goto error;
1882 access = isl_union_access_info_from_sink(sink);
1883 access = isl_union_access_info_set_must_source(access, must_source);
1884 access = access_info_set_schedule(access, s, table);
1885 flow = isl_union_access_info_compute_flow(access);
1886 must_dep = isl_union_flow_get_must_dependence(flow);
1887 must_no_source = isl_union_flow_get_must_no_source(flow);
1888 isl_union_flow_free(flow);
1890 list->obj[0].type = isl_obj_union_map;
1891 list->obj[0].v = must_dep;
1892 list->obj[1].type = isl_obj_union_map;
1893 list->obj[1].v = must_no_source;
1895 if (!must_dep || !must_no_source) {
1896 isl_list_free(list);
1897 return obj;
1900 obj.v = list;
1901 obj.type = isl_obj_list;
1903 return obj;
1904 error:
1905 isl_list_free(list);
1906 isl_union_map_free(must_source);
1907 isl_union_map_free(sink);
1908 free_obj(obj);
1909 obj.type = isl_obj_none;
1910 obj.v = NULL;
1911 return obj;
1914 static __isl_give isl_schedule *get_schedule(struct isl_stream *s,
1915 struct isl_hash_table *table)
1917 isl_union_set *domain;
1918 isl_union_map *validity;
1919 isl_union_map *proximity;
1921 domain = read_set(s, table);
1922 if (!domain)
1923 return NULL;
1925 validity = isl_union_map_empty(isl_union_set_get_space(domain));
1926 proximity = isl_union_map_empty(isl_union_set_get_space(domain));
1928 for (;;) {
1929 isl_union_map *umap;
1930 if (isl_stream_eat_if_available(s, iscc_op[ISCC_RESPECTING])) {
1931 umap = read_map(s, table);
1932 validity = isl_union_map_union(validity, umap);
1933 } else if (isl_stream_eat_if_available(s, iscc_op[ISCC_MINIMIZING])) {
1934 umap = read_map(s, table);
1935 proximity = isl_union_map_union(proximity, umap);
1936 } else
1937 break;
1940 return isl_union_set_compute_schedule(domain, validity, proximity);
1943 static struct isl_obj schedule(struct isl_stream *s,
1944 struct isl_hash_table *table)
1946 struct isl_obj obj = { isl_obj_none, NULL };
1947 isl_schedule *schedule;
1949 schedule = get_schedule(s, table);
1951 obj.v = schedule;
1952 obj.type = isl_obj_schedule;
1954 return obj;
1957 /* Read a schedule for code generation in the form of either
1958 * a schedule tree or a union map.
1959 * If the input is a set rather than a map, then we construct
1960 * an identity union map schedule on the given set.
1962 static struct isl_obj get_codegen_schedule(struct isl_stream *s,
1963 struct isl_hash_table *table)
1965 struct isl_obj obj;
1966 isl_ctx *ctx;
1968 obj = read_obj(s, table);
1969 ctx = isl_stream_get_ctx(s);
1971 if (obj.type == isl_obj_schedule)
1972 return obj;
1973 if (is_subtype(obj, isl_obj_union_set)) {
1974 obj = convert(ctx, obj, isl_obj_union_set);
1975 obj.v = isl_union_set_identity(obj.v);
1976 obj.type = isl_obj_union_map;
1978 if (is_subtype(obj, isl_obj_union_map))
1979 return convert(ctx, obj, isl_obj_union_map);
1981 free_obj(obj);
1982 obj.v = NULL;
1983 obj.type = isl_obj_none;
1984 isl_die(ctx, isl_error_invalid, "expecting schedule, set or map",
1985 return obj);
1988 /* Generate an AST for the given schedule and options and return the AST.
1990 static __isl_give isl_ast_node *get_ast_from_union_map(
1991 __isl_take isl_union_map *schedule, __isl_take isl_union_map *options)
1993 isl_space *space;
1994 isl_set *context;
1995 isl_ast_build *build;
1996 isl_ast_node *tree;
1998 space = isl_union_map_get_space(schedule);
1999 context = isl_set_universe(isl_space_params(space));
2001 build = isl_ast_build_from_context(context);
2002 build = isl_ast_build_set_options(build, options);
2003 tree = isl_ast_build_ast_from_schedule(build, schedule);
2004 isl_ast_build_free(build);
2006 return tree;
2009 /* Generate an AST for the given schedule and return the AST.
2011 static __isl_give isl_ast_node *get_ast_from_schedule(
2012 __isl_take isl_schedule *schedule)
2014 isl_ast_build *build;
2015 isl_ast_node *tree;
2017 build = isl_ast_build_alloc(isl_schedule_get_ctx(schedule));
2018 tree = isl_ast_build_node_from_schedule(build, schedule);
2019 isl_ast_build_free(build);
2021 return tree;
2024 /* Print the AST "tree" on the printer "p".
2026 static __isl_give isl_printer *print_ast(__isl_take isl_printer *p,
2027 __isl_take isl_ast_node *tree)
2029 int format;
2031 format = isl_printer_get_output_format(p);
2032 p = isl_printer_set_output_format(p, ISL_FORMAT_C);
2033 p = isl_printer_print_ast_node(p, tree);
2034 p = isl_printer_set_output_format(p, format);
2036 isl_ast_node_free(tree);
2038 return p;
2041 /* Perform the codegen operation.
2042 * In particular, read a schedule, check if the user has specified any options
2043 * and then generate an AST from the schedule (and options) and print it.
2044 * In case the schedule is specified as a schedule tree, the AST generation
2045 * options are embedded in the schedule, so they are not read in separately.
2047 static __isl_give isl_printer *codegen(struct isl_stream *s,
2048 struct isl_hash_table *table, __isl_take isl_printer *p)
2050 struct isl_obj obj;
2051 isl_ast_node *tree;
2053 obj = get_codegen_schedule(s, table);
2054 if (!obj.v)
2055 return p;
2057 if (obj.type == isl_obj_schedule) {
2058 isl_schedule *schedule = obj.v;
2060 tree = get_ast_from_schedule(schedule);
2061 } else {
2062 isl_union_map *schedule = obj.v;
2063 isl_union_map *options;
2065 if (isl_stream_eat_if_available(s, iscc_op[ISCC_USING]))
2066 options = read_map(s, table);
2067 else
2068 options = isl_union_map_empty(
2069 isl_union_map_get_space(schedule));
2071 tree = get_ast_from_union_map(schedule, options);
2074 p = print_ast(p, tree);
2076 isl_stream_eat(s, ';');
2078 return p;
2081 static struct isl_obj power(struct isl_stream *s, struct isl_obj obj)
2083 struct isl_token *tok;
2084 isl_ctx *ctx;
2085 isl_val *v;
2087 ctx = isl_stream_get_ctx(s);
2088 if (isl_stream_eat_if_available(s, '+'))
2089 return transitive_closure(ctx, obj);
2091 isl_assert(ctx, is_subtype(obj, isl_obj_union_map), goto error);
2092 if (obj.type != isl_obj_union_map)
2093 obj = convert(ctx, obj, isl_obj_union_map);
2095 tok = isl_stream_next_token(s);
2096 if (!tok || isl_token_get_type(tok) != ISL_TOKEN_VALUE) {
2097 isl_stream_error(s, tok, "expecting integer exponent");
2098 if (tok)
2099 isl_stream_push_token(s, tok);
2100 goto error;
2103 v = isl_token_get_val(ctx, tok);
2104 if (isl_val_is_zero(v)) {
2105 isl_stream_error(s, tok, "expecting non-zero exponent");
2106 isl_val_free(v);
2107 if (tok)
2108 isl_stream_push_token(s, tok);
2109 goto error;
2112 obj.v = isl_union_map_fixed_power_val(obj.v, v);
2113 isl_token_free(tok);
2114 if (!obj.v)
2115 goto error;
2117 return obj;
2118 error:
2119 free_obj(obj);
2120 obj.type = isl_obj_none;
2121 obj.v = NULL;
2122 return obj;
2125 static struct isl_obj check_assert(struct isl_stream *s,
2126 struct isl_hash_table *table)
2128 struct isl_obj obj;
2129 isl_ctx *ctx;
2131 obj = read_expr(s, table);
2132 ctx = isl_stream_get_ctx(s);
2133 if (obj.type != isl_obj_bool)
2134 isl_die(ctx, isl_error_invalid,
2135 "expecting boolean expression", goto error);
2136 if (obj.v != &iscc_bool_true)
2137 isl_die(ctx, isl_error_unknown,
2138 "assertion failed", abort());
2139 error:
2140 free_obj(obj);
2141 obj.type = isl_obj_none;
2142 obj.v = NULL;
2143 return obj;
2146 static struct isl_obj read_from_file(struct isl_stream *s)
2148 isl_ctx *ctx;
2149 struct isl_obj obj;
2150 struct isl_token *tok;
2151 struct isl_stream *s_file;
2152 struct iscc_options *options;
2153 char *name;
2154 FILE *file;
2156 tok = isl_stream_next_token(s);
2157 if (!tok || isl_token_get_type(tok) != ISL_TOKEN_STRING) {
2158 isl_stream_error(s, tok, "expecting filename");
2159 isl_token_free(tok);
2160 goto error;
2163 ctx = isl_stream_get_ctx(s);
2164 options = isl_ctx_peek_iscc_options(ctx);
2165 if (!options || !options->io) {
2166 isl_token_free(tok);
2167 isl_die(ctx, isl_error_invalid,
2168 "read operation not allowed", goto error);
2171 name = isl_token_get_str(ctx, tok);
2172 isl_token_free(tok);
2173 file = fopen(name, "r");
2174 free(name);
2175 isl_assert(ctx, file, goto error);
2177 s_file = isl_stream_new_file(ctx, file);
2178 if (!s_file) {
2179 fclose(file);
2180 goto error;
2183 obj = isl_stream_read_obj(s_file);
2185 isl_stream_free(s_file);
2186 fclose(file);
2188 return obj;
2189 error:
2190 obj.type = isl_obj_none;
2191 obj.v = NULL;
2192 return obj;
2195 static struct isl_obj write_to_file(struct isl_stream *s,
2196 struct isl_hash_table *table)
2198 struct isl_obj obj;
2199 struct isl_token *tok;
2200 struct isl_stream *s_file;
2201 struct iscc_options *options;
2202 char *name;
2203 FILE *file;
2204 isl_ctx *ctx;
2205 isl_printer *p;
2207 tok = isl_stream_next_token(s);
2208 if (!tok || isl_token_get_type(tok) != ISL_TOKEN_STRING) {
2209 isl_stream_error(s, tok, "expecting filename");
2210 isl_token_free(tok);
2211 goto error;
2214 obj = read_expr(s, table);
2216 ctx = isl_stream_get_ctx(s);
2217 options = isl_ctx_peek_iscc_options(ctx);
2218 if (!options || !options->io) {
2219 isl_token_free(tok);
2220 isl_die(ctx, isl_error_invalid,
2221 "write operation not allowed", goto error);
2224 name = isl_token_get_str(ctx, tok);
2225 isl_token_free(tok);
2226 file = fopen(name, "w");
2227 free(name);
2228 if (!file)
2229 isl_die(ctx, isl_error_unknown,
2230 "could not open file for writing", goto error);
2232 p = isl_printer_to_file(ctx, file);
2233 p = isl_printer_set_output_format(p, options->format);
2234 p = obj.type->print(p, obj.v);
2235 p = isl_printer_end_line(p);
2236 isl_printer_free(p);
2238 fclose(file);
2239 error:
2240 free_obj(obj);
2241 obj.type = isl_obj_none;
2242 obj.v = NULL;
2243 return obj;
2246 static struct isl_obj read_string_if_available(struct isl_stream *s)
2248 struct isl_token *tok;
2249 struct isl_obj obj = { isl_obj_none, NULL };
2251 tok = isl_stream_next_token(s);
2252 if (!tok)
2253 return obj;
2254 if (isl_token_get_type(tok) == ISL_TOKEN_STRING) {
2255 isl_str *str;
2256 str = isl_str_alloc(isl_stream_get_ctx(s));
2257 if (!str)
2258 goto error;
2259 str->s = isl_token_get_str(isl_stream_get_ctx(s), tok);
2260 isl_token_free(tok);
2261 obj.v = str;
2262 obj.type = isl_obj_str;
2263 } else
2264 isl_stream_push_token(s, tok);
2265 return obj;
2266 error:
2267 isl_token_free(tok);
2268 return obj;
2271 static struct isl_obj read_bool_if_available(struct isl_stream *s)
2273 struct isl_token *tok;
2274 struct isl_obj obj = { isl_obj_none, NULL };
2275 int type;
2277 tok = isl_stream_next_token(s);
2278 if (!tok)
2279 return obj;
2280 type = isl_token_get_type(tok);
2281 if (type == ISL_TOKEN_FALSE || type == ISL_TOKEN_TRUE) {
2282 int is_true = type == ISL_TOKEN_TRUE;
2283 isl_token_free(tok);
2284 obj.v = is_true ? &iscc_bool_true : &iscc_bool_false;
2285 obj.type = isl_obj_bool;
2286 } else
2287 isl_stream_push_token(s, tok);
2288 return obj;
2291 static __isl_give char *read_ident(struct isl_stream *s)
2293 char *name;
2294 isl_val *v;
2295 struct isl_token *tok, *tok2;
2297 name = isl_stream_read_ident_if_available(s);
2298 if (name)
2299 return name;
2301 tok = isl_stream_next_token(s);
2302 if (!tok)
2303 return NULL;
2304 if (isl_token_get_type(tok) != '$') {
2305 isl_stream_push_token(s, tok);
2306 return NULL;
2308 tok2 = isl_stream_next_token(s);
2309 if (!tok2 || isl_token_get_type(tok2) != ISL_TOKEN_VALUE) {
2310 if (tok2)
2311 isl_stream_push_token(s, tok2);
2312 isl_stream_push_token(s, tok);
2313 return NULL;
2316 v = isl_token_get_val(isl_stream_get_ctx(s), tok2);
2317 name = isl_val_to_str(v);
2318 isl_val_free(v);
2319 isl_token_free(tok);
2320 isl_token_free(tok2);
2322 return name;
2325 static struct isl_obj read_list(struct isl_stream *s,
2326 struct isl_hash_table *table, struct isl_obj obj)
2328 struct isl_list *list;
2330 list = isl_list_alloc(isl_stream_get_ctx(s), 2);
2331 if (!list)
2332 goto error;
2333 list->obj[0] = obj;
2334 list->obj[1] = read_obj(s, table);
2335 obj.v = list;
2336 obj.type = isl_obj_list;
2338 if (!list->obj[1].v)
2339 goto error;
2341 while (isl_stream_eat_if_available(s, ',')) {
2342 obj.v = list = isl_list_add_obj(list, read_obj(s, table));
2343 if (!obj.v)
2344 goto error;
2347 return obj;
2348 error:
2349 free_obj(obj);
2350 obj.type = isl_obj_none;
2351 obj.v = NULL;
2352 return obj;
2355 static struct isl_obj read_obj(struct isl_stream *s,
2356 struct isl_hash_table *table)
2358 isl_ctx *ctx;
2359 struct isl_obj obj = { isl_obj_none, NULL };
2360 char *name = NULL;
2361 struct isc_un_op *op = NULL;
2363 obj = read_string_if_available(s);
2364 if (obj.v)
2365 return obj;
2366 obj = read_bool_if_available(s);
2367 if (obj.v)
2368 return obj;
2369 ctx = isl_stream_get_ctx(s);
2370 if (isl_stream_eat_if_available(s, '(')) {
2371 if (isl_stream_next_token_is(s, ')')) {
2372 obj.type = isl_obj_list;
2373 obj.v = isl_list_alloc(ctx, 0);
2374 } else {
2375 obj = read_expr(s, table);
2376 if (obj.v && isl_stream_eat_if_available(s, ','))
2377 obj = read_list(s, table, obj);
2379 if (!obj.v || isl_stream_eat(s, ')'))
2380 goto error;
2381 } else {
2382 op = read_prefix_un_op_if_available(s);
2383 if (op)
2384 return read_un_op_expr(s, table, op);
2386 if (isl_stream_eat_if_available(s, iscc_op[ISCC_ASSERT]))
2387 return check_assert(s, table);
2388 if (isl_stream_eat_if_available(s, iscc_op[ISCC_READ]))
2389 return read_from_file(s);
2390 if (isl_stream_eat_if_available(s, iscc_op[ISCC_WRITE]))
2391 return write_to_file(s, table);
2392 if (isl_stream_eat_if_available(s, iscc_op[ISCC_VERTICES]))
2393 return vertices(s, table);
2394 if (isl_stream_eat_if_available(s, iscc_op[ISCC_ANY]))
2395 return any(s, table);
2396 if (isl_stream_eat_if_available(s, iscc_op[ISCC_LAST]))
2397 return last(s, table);
2398 if (isl_stream_eat_if_available(s, iscc_op[ISCC_SCHEDULE]))
2399 return schedule(s, table);
2400 if (isl_stream_eat_if_available(s, iscc_op[ISCC_TYPEOF]))
2401 return type_of(s, table);
2403 name = read_ident(s);
2404 if (name)
2405 obj = stored_obj(ctx, table, name);
2406 else
2407 obj = isl_stream_read_obj(s);
2408 if (!obj.v)
2409 goto error;
2412 if (isl_stream_eat_if_available(s, '^'))
2413 obj = power(s, obj);
2414 else if (obj.type == isl_obj_list && isl_stream_eat_if_available(s, '['))
2415 obj = obj_at_index(s, obj);
2416 else if (is_subtype(obj, isl_obj_union_map) &&
2417 isl_stream_eat_if_available(s, '(')) {
2418 obj = convert(ctx, obj, isl_obj_union_map);
2419 obj = apply(s, obj.v, table);
2420 } else if (is_subtype(obj, isl_obj_union_pw_qpolynomial) &&
2421 isl_stream_eat_if_available(s, '(')) {
2422 obj = convert(ctx, obj, isl_obj_union_pw_qpolynomial);
2423 obj = apply_fun(s, obj, table);
2424 } else if (is_subtype(obj, isl_obj_union_pw_qpolynomial_fold) &&
2425 isl_stream_eat_if_available(s, '(')) {
2426 obj = convert(ctx, obj, isl_obj_union_pw_qpolynomial_fold);
2427 obj = apply_fun(s, obj, table);
2430 return obj;
2431 error:
2432 free_obj(obj);
2433 obj.type = isl_obj_none;
2434 obj.v = NULL;
2435 return obj;
2438 static struct isc_bin_op *find_matching_bin_op(struct isc_bin_op *like,
2439 struct isl_obj lhs, struct isl_obj rhs)
2441 int i;
2443 for (i = 0; ; ++i) {
2444 if (!bin_ops[i].op)
2445 break;
2446 if (bin_ops[i].op != like->op)
2447 continue;
2448 if (!is_subtype(lhs, bin_ops[i].lhs))
2449 continue;
2450 if (!is_subtype(rhs, bin_ops[i].rhs))
2451 continue;
2453 return &bin_ops[i];
2456 for (i = 0; ; ++i) {
2457 if (!named_bin_ops[i].name)
2458 break;
2459 if (named_bin_ops[i].op.op != like->op)
2460 continue;
2461 if (!is_subtype(lhs, named_bin_ops[i].op.lhs))
2462 continue;
2463 if (!is_subtype(rhs, named_bin_ops[i].op.rhs))
2464 continue;
2466 return &named_bin_ops[i].op;
2469 for (i = 0; ; ++i) {
2470 if (!compound_bin_ops[i].full)
2471 break;
2472 if (compound_bin_ops[i].op.op != like->op)
2473 continue;
2474 if (!is_subtype(lhs, compound_bin_ops[i].op.lhs))
2475 continue;
2476 if (!is_subtype(rhs, compound_bin_ops[i].op.rhs))
2477 continue;
2479 return &compound_bin_ops[i].op;
2482 return NULL;
2485 static int next_is_neg_int(struct isl_stream *s)
2487 struct isl_token *tok;
2488 int ret;
2490 tok = isl_stream_next_token(s);
2491 if (tok && isl_token_get_type(tok) == ISL_TOKEN_VALUE) {
2492 isl_val *v;
2493 v = isl_token_get_val(isl_stream_get_ctx(s), tok);
2494 ret = isl_val_is_neg(v);
2495 isl_val_free(v);
2496 } else
2497 ret = 0;
2498 isl_stream_push_token(s, tok);
2500 return ret;
2503 static struct isl_obj call_bin_op(isl_ctx *ctx, struct isc_bin_op *op,
2504 struct isl_obj lhs, struct isl_obj rhs)
2506 struct isl_obj obj;
2508 lhs = convert(ctx, lhs, op->lhs);
2509 rhs = convert(ctx, rhs, op->rhs);
2510 if (op->res != isl_obj_bool)
2511 obj.v = op->o.fn(lhs.v, rhs.v);
2512 else {
2513 int res = op->o.test(lhs.v, rhs.v);
2514 free_obj(lhs);
2515 free_obj(rhs);
2516 obj.v = iscc_bool_from_int(res);
2518 obj.type = op->res;
2520 return obj;
2523 static struct isl_obj read_expr(struct isl_stream *s,
2524 struct isl_hash_table *table)
2526 isl_ctx *ctx;
2527 struct isl_obj obj = { isl_obj_none, NULL };
2528 struct isl_obj right_obj = { isl_obj_none, NULL };
2530 obj = read_obj(s, table);
2531 ctx = isl_stream_get_ctx(s);
2532 for (; obj.v;) {
2533 struct isc_bin_op *op = NULL;
2535 op = read_bin_op_if_available(s, obj);
2536 if (!op)
2537 break;
2539 right_obj = read_obj(s, table);
2541 op = find_matching_bin_op(op, obj, right_obj);
2543 if (!op)
2544 isl_die(ctx, isl_error_invalid,
2545 "no such binary operator defined on given operands",
2546 goto error);
2548 obj = call_bin_op(ctx, op, obj, right_obj);
2551 if (obj.type == isl_obj_val && next_is_neg_int(s)) {
2552 right_obj = read_obj(s, table);
2553 obj.v = isl_val_add(obj.v, right_obj.v);
2556 return obj;
2557 error:
2558 free_obj(right_obj);
2559 free_obj(obj);
2560 obj.type = isl_obj_none;
2561 obj.v = NULL;
2562 return obj;
2565 static __isl_give isl_printer *source_file(struct isl_stream *s,
2566 struct isl_hash_table *table, __isl_take isl_printer *p);
2568 /* Print "obj" to the printer "p".
2569 * If the object is a schedule, then print it in block format.
2571 static __isl_give isl_printer *print_obj(__isl_take isl_printer *p,
2572 struct isl_obj obj)
2574 if (obj.type != isl_obj_schedule)
2575 return obj.type->print(p, obj.v);
2577 p = isl_printer_set_yaml_style(p, ISL_YAML_STYLE_BLOCK);
2578 p = obj.type->print(p, obj.v);
2579 p = isl_printer_set_yaml_style(p, ISL_YAML_STYLE_FLOW);
2581 return p;
2584 static __isl_give isl_printer *read_line(struct isl_stream *s,
2585 struct isl_hash_table *table, __isl_take isl_printer *p, int tty)
2587 isl_ctx *ctx;
2588 struct isl_obj obj = { isl_obj_none, NULL };
2589 char *lhs = NULL;
2590 int assign = 0;
2591 int only_print = 0;
2592 struct isc_bin_op *op = NULL;
2593 char buf[30];
2595 if (!p)
2596 return NULL;
2597 if (isl_stream_is_empty(s))
2598 return p;
2600 if (isl_stream_eat_if_available(s, iscc_op[ISCC_SOURCE]))
2601 return source_file(s, table, p);
2602 if (isl_stream_eat_if_available(s, iscc_op[ISCC_CODEGEN]))
2603 return codegen(s, table, p);
2605 assign = is_assign(s);
2606 if (assign) {
2607 lhs = isl_stream_read_ident_if_available(s);
2608 if (isl_stream_eat(s, ISL_TOKEN_DEF))
2609 goto error;
2610 } else if (isl_stream_eat_if_available(s, iscc_op[ISCC_PRINT]))
2611 only_print = 1;
2612 else if (!tty)
2613 only_print = 1;
2615 obj = read_expr(s, table);
2616 ctx = isl_stream_get_ctx(s);
2617 if (isl_ctx_last_error(ctx) == isl_error_abort) {
2618 fprintf(stderr, "Interrupted\n");
2619 isl_ctx_reset_error(ctx);
2621 if (isl_stream_eat(s, ';'))
2622 goto error;
2624 if (only_print) {
2625 if (obj.type != isl_obj_none && obj.v != NULL) {
2626 p = print_obj(p, obj);
2627 p = isl_printer_end_line(p);
2629 free_obj(obj);
2630 return p;
2632 if (!assign && obj.type != isl_obj_none && obj.v != NULL) {
2633 static int count = 0;
2634 snprintf(buf, sizeof(buf), "$%d", count++);
2635 lhs = strdup(buf + 1);
2637 p = isl_printer_print_str(p, buf);
2638 p = isl_printer_print_str(p, " := ");
2639 p = obj.type->print(p, obj.v);
2640 p = isl_printer_end_line(p);
2642 if (lhs && do_assign(ctx, table, lhs, obj))
2643 return p;
2645 return p;
2646 error:
2647 isl_stream_flush_tokens(s);
2648 isl_stream_skip_line(s);
2649 free(lhs);
2650 free_obj(obj);
2651 return p;
2654 static isl_stat free_cb(void **entry, void *user)
2656 struct isl_named_obj *named = *entry;
2658 free_obj(named->obj);
2659 free(named->name);
2660 free(named);
2662 return isl_stat_ok;
2665 static void register_named_ops(struct isl_stream *s)
2667 int i;
2669 for (i = 0; i < ISCC_N_OP; ++i) {
2670 iscc_op[i] = isl_stream_register_keyword(s, op_name[i]);
2671 assert(iscc_op[i] != ISL_TOKEN_ERROR);
2674 for (i = 0; ; ++i) {
2675 if (!named_un_ops[i].name)
2676 break;
2677 named_un_ops[i].op.op = isl_stream_register_keyword(s,
2678 named_un_ops[i].name);
2679 assert(named_un_ops[i].op.op != ISL_TOKEN_ERROR);
2682 for (i = 0; ; ++i) {
2683 if (!named_bin_ops[i].name)
2684 break;
2685 named_bin_ops[i].op.op = isl_stream_register_keyword(s,
2686 named_bin_ops[i].name);
2687 assert(named_bin_ops[i].op.op != ISL_TOKEN_ERROR);
2690 for (i = 0; ; ++i) {
2691 if (!compound_bin_ops[i].full)
2692 break;
2693 compound_bin_ops[i].op.op = isl_stream_register_keyword(s,
2694 compound_bin_ops[i].full);
2695 assert(compound_bin_ops[i].op.op != ISL_TOKEN_ERROR);
2699 static __isl_give isl_printer *source_file(struct isl_stream *s,
2700 struct isl_hash_table *table, __isl_take isl_printer *p)
2702 isl_ctx *ctx;
2703 struct isl_token *tok;
2704 struct isl_stream *s_file;
2705 struct iscc_options *options;
2706 char *name;
2707 FILE *file;
2709 tok = isl_stream_next_token(s);
2710 if (!tok || isl_token_get_type(tok) != ISL_TOKEN_STRING) {
2711 isl_stream_error(s, tok, "expecting filename");
2712 isl_token_free(tok);
2713 return p;
2716 isl_stream_eat(s, ';');
2718 ctx = isl_stream_get_ctx(s);
2719 options = isl_ctx_peek_iscc_options(ctx);
2720 if (!options || !options->io) {
2721 isl_token_free(tok);
2722 isl_die(ctx, isl_error_invalid,
2723 "source operation not allowed", return p);
2726 name = isl_token_get_str(ctx, tok);
2727 isl_token_free(tok);
2728 file = fopen(name, "r");
2729 free(name);
2730 isl_assert(ctx, file, return p);
2732 s_file = isl_stream_new_file(ctx, file);
2733 if (!s_file) {
2734 fclose(file);
2735 return p;
2738 register_named_ops(s_file);
2740 while (!isl_stream_is_empty(s_file))
2741 p = read_line(s_file, table, p, 0);
2743 isl_stream_free(s_file);
2744 fclose(file);
2746 return p;
2749 int main(int argc, char **argv)
2751 struct isl_ctx *ctx;
2752 struct isl_stream *s;
2753 struct isl_hash_table *table;
2754 struct iscc_options *options;
2755 isl_printer *p;
2756 int tty = isatty(0);
2758 options = iscc_options_new_with_defaults();
2759 assert(options);
2761 ctx = isl_ctx_alloc_with_options(&iscc_options_args, options);
2762 pet_options_set_autodetect(ctx, 1);
2763 argc = isl_ctx_parse_options(ctx, argc, argv, ISL_ARG_ALL);
2764 s = isl_stream_new_file(ctx, stdin);
2765 assert(s);
2766 table = isl_hash_table_alloc(ctx, 10);
2767 assert(table);
2768 p = isl_printer_to_file(ctx, stdout);
2769 p = isl_printer_set_output_format(p, options->format);
2770 assert(p);
2772 register_named_ops(s);
2774 install_signal_handler(ctx);
2776 while (p && !isl_stream_is_empty(s)) {
2777 isl_ctx_resume(ctx);
2778 p = read_line(s, table, p, tty);
2781 remove_signal_handler(ctx);
2783 isl_printer_free(p);
2784 isl_hash_table_foreach(ctx, table, free_cb, NULL);
2785 isl_hash_table_free(ctx, table);
2786 isl_stream_free(s);
2787 isl_ctx_free(ctx);
2789 return 0;