re-export isl_map_universe as isl_space_universe_map
[isl.git] / isl_input.c
blob4ac2bdd7e65315185911eba7b8d5763bd8575c5c
1 /*
2 * Copyright 2008-2009 Katholieke Universiteit Leuven
3 * Copyright 2010 INRIA Saclay
4 * Copyright 2012-2013 Ecole Normale Superieure
5 * Copyright 2019 Cerebras Systems
7 * Use of this software is governed by the MIT license
9 * Written by Sven Verdoolaege, K.U.Leuven, Departement
10 * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium
11 * and INRIA Saclay - Ile-de-France, Parc Club Orsay Universite,
12 * ZAC des vignes, 4 rue Jacques Monod, 91893 Orsay, France
13 * and Ecole Normale Superieure, 45 rue d’Ulm, 75230 Paris, France
14 * and Cerebras Systems, 175 S San Antonio Rd, Los Altos, CA, USA
17 #include <ctype.h>
18 #include <stdio.h>
19 #include <string.h>
20 #include <isl_ctx_private.h>
21 #include <isl_map_private.h>
22 #include <isl_id_private.h>
23 #include <isl/set.h>
24 #include <isl_seq.h>
25 #include <isl_stream_private.h>
26 #include <isl/obj.h>
27 #include "isl_polynomial_private.h"
28 #include <isl/union_set.h>
29 #include <isl/union_map.h>
30 #include <isl_mat_private.h>
31 #include <isl_aff_private.h>
32 #include <isl_vec_private.h>
33 #include <isl/list.h>
34 #include <isl_val_private.h>
36 struct variable {
37 char *name;
38 int pos;
39 struct variable *next;
42 struct vars {
43 struct isl_ctx *ctx;
44 int n;
45 struct variable *v;
48 static struct vars *vars_new(struct isl_ctx *ctx)
50 struct vars *v;
51 v = isl_alloc_type(ctx, struct vars);
52 if (!v)
53 return NULL;
54 v->ctx = ctx;
55 v->n = 0;
56 v->v = NULL;
57 return v;
60 static void variable_free(struct variable *var)
62 while (var) {
63 struct variable *next = var->next;
64 free(var->name);
65 free(var);
66 var = next;
70 static void vars_free(struct vars *v)
72 if (!v)
73 return;
74 variable_free(v->v);
75 free(v);
78 static void vars_drop(struct vars *v, int n)
80 struct variable *var;
82 if (!v || !v->v)
83 return;
85 v->n -= n;
87 var = v->v;
88 while (--n >= 0) {
89 struct variable *next = var->next;
90 free(var->name);
91 free(var);
92 var = next;
94 v->v = var;
97 static struct variable *variable_new(struct vars *v, const char *name, int len,
98 int pos)
100 struct variable *var;
101 var = isl_calloc_type(v->ctx, struct variable);
102 if (!var)
103 goto error;
104 var->name = strdup(name);
105 var->name[len] = '\0';
106 var->pos = pos;
107 var->next = v->v;
108 return var;
109 error:
110 variable_free(v->v);
111 return NULL;
114 static int vars_pos(struct vars *v, const char *s, int len)
116 int pos;
117 struct variable *q;
119 if (len == -1)
120 len = strlen(s);
121 for (q = v->v; q; q = q->next) {
122 if (strncmp(q->name, s, len) == 0 && q->name[len] == '\0')
123 break;
125 if (q)
126 pos = q->pos;
127 else {
128 pos = v->n;
129 v->v = variable_new(v, s, len, v->n);
130 if (!v->v)
131 return -1;
132 v->n++;
134 return pos;
137 static int vars_add_anon(struct vars *v)
139 v->v = variable_new(v, "", 0, v->n);
141 if (!v->v)
142 return -1;
143 v->n++;
145 return 0;
148 /* Obtain next token, with some preprocessing.
149 * In particular, evaluate expressions of the form x^y,
150 * with x and y values.
152 static struct isl_token *next_token(__isl_keep isl_stream *s)
154 struct isl_token *tok, *tok2;
156 tok = isl_stream_next_token(s);
157 if (!tok || tok->type != ISL_TOKEN_VALUE)
158 return tok;
159 if (!isl_stream_eat_if_available(s, '^'))
160 return tok;
161 tok2 = isl_stream_next_token(s);
162 if (!tok2 || tok2->type != ISL_TOKEN_VALUE) {
163 isl_stream_error(s, tok2, "expecting constant value");
164 goto error;
167 isl_int_pow_ui(tok->u.v, tok->u.v, isl_int_get_ui(tok2->u.v));
169 isl_token_free(tok2);
170 return tok;
171 error:
172 isl_token_free(tok);
173 isl_token_free(tok2);
174 return NULL;
177 /* Read an isl_val from "s".
179 * The following token sequences are recognized
181 * "infty" -> infty
182 * "-" "infty" -> -infty
183 * "NaN" -> NaN
184 * n "/" d -> n/d
185 * v -> v
187 * where n, d and v are integer constants.
189 __isl_give isl_val *isl_stream_read_val(__isl_keep isl_stream *s)
191 struct isl_token *tok = NULL;
192 struct isl_token *tok2 = NULL;
193 isl_val *val;
195 tok = next_token(s);
196 if (!tok) {
197 isl_stream_error(s, NULL, "unexpected EOF");
198 goto error;
200 if (tok->type == ISL_TOKEN_INFTY) {
201 isl_token_free(tok);
202 return isl_val_infty(s->ctx);
204 if (tok->type == '-' &&
205 isl_stream_eat_if_available(s, ISL_TOKEN_INFTY)) {
206 isl_token_free(tok);
207 return isl_val_neginfty(s->ctx);
209 if (tok->type == ISL_TOKEN_NAN) {
210 isl_token_free(tok);
211 return isl_val_nan(s->ctx);
213 if (tok->type != ISL_TOKEN_VALUE) {
214 isl_stream_error(s, tok, "expecting value");
215 goto error;
218 if (isl_stream_eat_if_available(s, '/')) {
219 tok2 = next_token(s);
220 if (!tok2) {
221 isl_stream_error(s, NULL, "unexpected EOF");
222 goto error;
224 if (tok2->type != ISL_TOKEN_VALUE) {
225 isl_stream_error(s, tok2, "expecting value");
226 goto error;
228 val = isl_val_rat_from_isl_int(s->ctx, tok->u.v, tok2->u.v);
229 val = isl_val_normalize(val);
230 } else {
231 val = isl_val_int_from_isl_int(s->ctx, tok->u.v);
234 isl_token_free(tok);
235 isl_token_free(tok2);
236 return val;
237 error:
238 isl_token_free(tok);
239 isl_token_free(tok2);
240 return NULL;
243 /* Read an isl_val from "str".
245 __isl_give isl_val *isl_val_read_from_str(isl_ctx *ctx, const char *str)
247 isl_val *val;
248 isl_stream *s = isl_stream_new_str(ctx, str);
249 if (!s)
250 return NULL;
251 val = isl_stream_read_val(s);
252 isl_stream_free(s);
253 return val;
256 /* Perform an integer division on *f and
257 * an integer value read from the stream.
259 static isl_stat int_div_by_cst(__isl_keep isl_stream *s, isl_int *f)
261 struct isl_token *tok;
263 tok = next_token(s);
264 if (!tok || tok->type != ISL_TOKEN_VALUE) {
265 isl_stream_error(s, tok, "expecting constant value");
266 goto error;
269 isl_int_fdiv_q(*f, *f, tok->u.v);
271 isl_token_free(tok);
273 return isl_stat_ok;
274 error:
275 isl_token_free(tok);
276 return isl_stat_error;
279 static isl_stat accept_cst_factor(__isl_keep isl_stream *s, isl_int *f)
281 struct isl_token *tok;
283 tok = next_token(s);
284 if (!tok || tok->type != ISL_TOKEN_VALUE) {
285 isl_stream_error(s, tok, "expecting constant value");
286 goto error;
289 isl_int_mul(*f, *f, tok->u.v);
291 isl_token_free(tok);
293 if (isl_stream_eat_if_available(s, '*'))
294 return accept_cst_factor(s, f);
296 return isl_stat_ok;
297 error:
298 isl_token_free(tok);
299 return isl_stat_error;
302 /* Given an affine expression aff, return an affine expression
303 * for aff % d, with d the next token on the stream, which is
304 * assumed to be a constant.
306 * We introduce an integer division q = [aff/d] and the result
307 * is set to aff - d q.
309 static __isl_give isl_pw_aff *affine_mod(__isl_keep isl_stream *s,
310 struct vars *v, __isl_take isl_pw_aff *aff)
312 struct isl_token *tok;
313 isl_pw_aff *q;
315 tok = next_token(s);
316 if (!tok || tok->type != ISL_TOKEN_VALUE) {
317 isl_stream_error(s, tok, "expecting constant value");
318 goto error;
321 q = isl_pw_aff_copy(aff);
322 q = isl_pw_aff_scale_down(q, tok->u.v);
323 q = isl_pw_aff_floor(q);
324 q = isl_pw_aff_scale(q, tok->u.v);
326 aff = isl_pw_aff_sub(aff, q);
328 isl_token_free(tok);
329 return aff;
330 error:
331 isl_pw_aff_free(aff);
332 isl_token_free(tok);
333 return NULL;
336 static __isl_give isl_pw_aff *accept_affine(__isl_keep isl_stream *s,
337 __isl_take isl_space *space, struct vars *v);
338 static __isl_give isl_pw_aff_list *accept_affine_list(__isl_keep isl_stream *s,
339 __isl_take isl_space *space, struct vars *v);
341 static __isl_give isl_pw_aff *accept_minmax(__isl_keep isl_stream *s,
342 __isl_take isl_space *space, struct vars *v)
344 struct isl_token *tok;
345 isl_pw_aff_list *list = NULL;
346 int min;
348 tok = isl_stream_next_token(s);
349 if (!tok)
350 goto error;
351 min = tok->type == ISL_TOKEN_MIN;
352 isl_token_free(tok);
354 if (isl_stream_eat(s, '('))
355 goto error;
357 list = accept_affine_list(s, isl_space_copy(space), v);
358 if (!list)
359 goto error;
361 if (isl_stream_eat(s, ')'))
362 goto error;
364 isl_space_free(space);
365 return min ? isl_pw_aff_list_min(list) : isl_pw_aff_list_max(list);
366 error:
367 isl_space_free(space);
368 isl_pw_aff_list_free(list);
369 return NULL;
372 /* Is "tok" the start of an integer division?
374 static int is_start_of_div(struct isl_token *tok)
376 if (!tok)
377 return 0;
378 if (tok->type == '[')
379 return 1;
380 if (tok->type == ISL_TOKEN_FLOOR)
381 return 1;
382 if (tok->type == ISL_TOKEN_CEIL)
383 return 1;
384 if (tok->type == ISL_TOKEN_FLOORD)
385 return 1;
386 if (tok->type == ISL_TOKEN_CEILD)
387 return 1;
388 return 0;
391 /* Read an integer division from "s" and return it as an isl_pw_aff.
393 * The integer division can be of the form
395 * [<affine expression>]
396 * floor(<affine expression>)
397 * ceil(<affine expression>)
398 * floord(<affine expression>,<denominator>)
399 * ceild(<affine expression>,<denominator>)
401 static __isl_give isl_pw_aff *accept_div(__isl_keep isl_stream *s,
402 __isl_take isl_space *space, struct vars *v)
404 struct isl_token *tok;
405 int f = 0;
406 int c = 0;
407 int extra = 0;
408 isl_pw_aff *pwaff = NULL;
410 if (isl_stream_eat_if_available(s, ISL_TOKEN_FLOORD))
411 extra = f = 1;
412 else if (isl_stream_eat_if_available(s, ISL_TOKEN_CEILD))
413 extra = c = 1;
414 else if (isl_stream_eat_if_available(s, ISL_TOKEN_FLOOR))
415 f = 1;
416 else if (isl_stream_eat_if_available(s, ISL_TOKEN_CEIL))
417 c = 1;
418 if (f || c) {
419 if (isl_stream_eat(s, '('))
420 goto error;
421 } else {
422 if (isl_stream_eat(s, '['))
423 goto error;
426 pwaff = accept_affine(s, isl_space_copy(space), v);
428 if (extra) {
429 if (isl_stream_eat(s, ','))
430 goto error;
432 tok = next_token(s);
433 if (!tok)
434 goto error;
435 if (tok->type != ISL_TOKEN_VALUE) {
436 isl_stream_error(s, tok, "expected denominator");
437 isl_stream_push_token(s, tok);
438 goto error;
440 pwaff = isl_pw_aff_scale_down(pwaff, tok->u.v);
441 isl_token_free(tok);
444 if (c)
445 pwaff = isl_pw_aff_ceil(pwaff);
446 else
447 pwaff = isl_pw_aff_floor(pwaff);
449 if (f || c) {
450 if (isl_stream_eat(s, ')'))
451 goto error;
452 } else {
453 if (isl_stream_eat(s, ']'))
454 goto error;
457 isl_space_free(space);
458 return pwaff;
459 error:
460 isl_space_free(space);
461 isl_pw_aff_free(pwaff);
462 return NULL;
465 /* Divide "pa" by an integer constant read from the stream.
467 static __isl_give isl_pw_aff *pw_aff_div_by_cst(__isl_keep isl_stream *s,
468 __isl_take isl_pw_aff *pa)
470 isl_int f;
471 isl_int_init(f);
472 isl_int_set_si(f, 1);
473 if (accept_cst_factor(s, &f) < 0)
474 pa = isl_pw_aff_free(pa);
475 pa = isl_pw_aff_scale_down(pa, f);
476 isl_int_clear(f);
478 return pa;
481 static __isl_give isl_pw_aff *accept_affine_factor(__isl_keep isl_stream *s,
482 __isl_take isl_space *space, struct vars *v)
484 struct isl_token *tok = NULL;
485 isl_pw_aff *res = NULL;
487 tok = next_token(s);
488 if (!tok) {
489 isl_stream_error(s, NULL, "unexpected EOF");
490 goto error;
493 if (tok->type == ISL_TOKEN_AFF) {
494 res = isl_pw_aff_copy(tok->u.pwaff);
495 isl_token_free(tok);
496 } else if (tok->type == ISL_TOKEN_IDENT) {
497 int n = v->n;
498 int pos = vars_pos(v, tok->u.s, -1);
499 isl_aff *aff;
501 if (pos < 0)
502 goto error;
503 if (pos >= n) {
504 vars_drop(v, v->n - n);
505 isl_stream_error(s, tok, "unknown identifier");
506 goto error;
509 aff = isl_aff_zero_on_domain(isl_local_space_from_space(isl_space_copy(space)));
510 if (!aff)
511 goto error;
512 isl_int_set_si(aff->v->el[2 + pos], 1);
513 res = isl_pw_aff_from_aff(aff);
514 isl_token_free(tok);
515 } else if (tok->type == ISL_TOKEN_VALUE) {
516 if (isl_stream_eat_if_available(s, '*')) {
517 res = accept_affine_factor(s, isl_space_copy(space), v);
518 res = isl_pw_aff_scale(res, tok->u.v);
519 } else {
520 isl_local_space *ls;
521 isl_aff *aff;
522 ls = isl_local_space_from_space(isl_space_copy(space));
523 aff = isl_aff_zero_on_domain(ls);
524 aff = isl_aff_add_constant(aff, tok->u.v);
525 res = isl_pw_aff_from_aff(aff);
527 isl_token_free(tok);
528 } else if (tok->type == '(') {
529 isl_token_free(tok);
530 tok = NULL;
531 res = accept_affine(s, isl_space_copy(space), v);
532 if (!res)
533 goto error;
534 if (isl_stream_eat(s, ')'))
535 goto error;
536 } else if (is_start_of_div(tok)) {
537 isl_stream_push_token(s, tok);
538 tok = NULL;
539 res = accept_div(s, isl_space_copy(space), v);
540 } else if (tok->type == ISL_TOKEN_MIN || tok->type == ISL_TOKEN_MAX) {
541 isl_stream_push_token(s, tok);
542 tok = NULL;
543 res = accept_minmax(s, isl_space_copy(space), v);
544 } else {
545 isl_stream_error(s, tok, "expecting factor");
546 goto error;
548 if (isl_stream_eat_if_available(s, '%') ||
549 isl_stream_eat_if_available(s, ISL_TOKEN_MOD)) {
550 isl_space_free(space);
551 return affine_mod(s, v, res);
553 if (isl_stream_eat_if_available(s, '*')) {
554 isl_int f;
555 isl_int_init(f);
556 isl_int_set_si(f, 1);
557 if (accept_cst_factor(s, &f) < 0) {
558 isl_int_clear(f);
559 goto error2;
561 res = isl_pw_aff_scale(res, f);
562 isl_int_clear(f);
564 if (isl_stream_eat_if_available(s, '/'))
565 res = pw_aff_div_by_cst(s, res);
566 if (isl_stream_eat_if_available(s, ISL_TOKEN_INT_DIV))
567 res = isl_pw_aff_floor(pw_aff_div_by_cst(s, res));
569 isl_space_free(space);
570 return res;
571 error:
572 isl_token_free(tok);
573 error2:
574 isl_pw_aff_free(res);
575 isl_space_free(space);
576 return NULL;
579 static __isl_give isl_pw_aff *add_cst(__isl_take isl_pw_aff *pwaff, isl_int v)
581 isl_aff *aff;
582 isl_space *space;
584 space = isl_pw_aff_get_domain_space(pwaff);
585 aff = isl_aff_zero_on_domain(isl_local_space_from_space(space));
586 aff = isl_aff_add_constant(aff, v);
588 return isl_pw_aff_add(pwaff, isl_pw_aff_from_aff(aff));
591 /* Return a piecewise affine expression defined on the specified domain
592 * that represents NaN.
594 static __isl_give isl_pw_aff *nan_on_domain(__isl_keep isl_space *space)
596 return isl_pw_aff_nan_on_domain_space(isl_space_copy(space));
599 static __isl_give isl_pw_aff *accept_affine(__isl_keep isl_stream *s,
600 __isl_take isl_space *space, struct vars *v)
602 struct isl_token *tok = NULL;
603 isl_local_space *ls;
604 isl_pw_aff *res;
605 int sign = 1;
607 ls = isl_local_space_from_space(isl_space_copy(space));
608 res = isl_pw_aff_from_aff(isl_aff_zero_on_domain(ls));
609 if (!res)
610 goto error;
612 for (;;) {
613 tok = next_token(s);
614 if (!tok) {
615 isl_stream_error(s, NULL, "unexpected EOF");
616 goto error;
618 if (tok->type == '-') {
619 sign = -sign;
620 isl_token_free(tok);
621 continue;
623 if (tok->type == '(' || is_start_of_div(tok) ||
624 tok->type == ISL_TOKEN_MIN || tok->type == ISL_TOKEN_MAX ||
625 tok->type == ISL_TOKEN_IDENT ||
626 tok->type == ISL_TOKEN_AFF) {
627 isl_pw_aff *term;
628 isl_stream_push_token(s, tok);
629 tok = NULL;
630 term = accept_affine_factor(s,
631 isl_space_copy(space), v);
632 if (sign < 0)
633 res = isl_pw_aff_sub(res, term);
634 else
635 res = isl_pw_aff_add(res, term);
636 if (!res)
637 goto error;
638 sign = 1;
639 } else if (tok->type == ISL_TOKEN_VALUE) {
640 if (sign < 0)
641 isl_int_neg(tok->u.v, tok->u.v);
642 if (isl_stream_eat_if_available(s, '*') ||
643 isl_stream_next_token_is(s, ISL_TOKEN_IDENT)) {
644 isl_pw_aff *term;
645 term = accept_affine_factor(s,
646 isl_space_copy(space), v);
647 term = isl_pw_aff_scale(term, tok->u.v);
648 res = isl_pw_aff_add(res, term);
649 if (!res)
650 goto error;
651 } else {
652 if (isl_stream_eat_if_available(s,
653 ISL_TOKEN_INT_DIV) &&
654 int_div_by_cst(s, &tok->u.v) < 0)
655 goto error;
656 res = add_cst(res, tok->u.v);
658 sign = 1;
659 } else if (tok->type == ISL_TOKEN_NAN) {
660 res = isl_pw_aff_add(res, nan_on_domain(space));
661 } else {
662 isl_stream_error(s, tok, "unexpected isl_token");
663 isl_stream_push_token(s, tok);
664 isl_pw_aff_free(res);
665 isl_space_free(space);
666 return NULL;
668 isl_token_free(tok);
670 tok = next_token(s);
671 if (tok && tok->type == '-') {
672 sign = -sign;
673 isl_token_free(tok);
674 } else if (tok && tok->type == '+') {
675 /* nothing */
676 isl_token_free(tok);
677 } else if (tok && tok->type == ISL_TOKEN_VALUE &&
678 isl_int_is_neg(tok->u.v)) {
679 isl_stream_push_token(s, tok);
680 } else {
681 if (tok)
682 isl_stream_push_token(s, tok);
683 break;
687 isl_space_free(space);
688 return res;
689 error:
690 isl_space_free(space);
691 isl_token_free(tok);
692 isl_pw_aff_free(res);
693 return NULL;
696 /* Is "type" the type of a comparison operator between lists
697 * of affine expressions?
699 static int is_list_comparator_type(int type)
701 switch (type) {
702 case ISL_TOKEN_LEX_LT:
703 case ISL_TOKEN_LEX_GT:
704 case ISL_TOKEN_LEX_LE:
705 case ISL_TOKEN_LEX_GE:
706 return 1;
707 default:
708 return 0;
712 static int is_comparator(struct isl_token *tok)
714 if (!tok)
715 return 0;
716 if (is_list_comparator_type(tok->type))
717 return 1;
719 switch (tok->type) {
720 case ISL_TOKEN_LT:
721 case ISL_TOKEN_GT:
722 case ISL_TOKEN_LE:
723 case ISL_TOKEN_GE:
724 case ISL_TOKEN_NE:
725 case '=':
726 return 1;
727 default:
728 return 0;
732 static __isl_give isl_map *read_formula(__isl_keep isl_stream *s,
733 struct vars *v, __isl_take isl_map *map, int rational);
734 static __isl_give isl_pw_aff *accept_extended_affine(__isl_keep isl_stream *s,
735 __isl_take isl_space *space, struct vars *v, int rational);
737 /* Accept a ternary operator, given the first argument.
739 static __isl_give isl_pw_aff *accept_ternary(__isl_keep isl_stream *s,
740 __isl_take isl_map *cond, struct vars *v, int rational)
742 isl_space *space;
743 isl_pw_aff *pwaff1 = NULL, *pwaff2 = NULL, *pa_cond;
745 if (!cond)
746 return NULL;
748 if (isl_stream_eat(s, '?'))
749 goto error;
751 space = isl_space_wrap(isl_map_get_space(cond));
752 pwaff1 = accept_extended_affine(s, space, v, rational);
753 if (!pwaff1)
754 goto error;
756 if (isl_stream_eat(s, ':'))
757 goto error;
759 space = isl_pw_aff_get_domain_space(pwaff1);
760 pwaff2 = accept_extended_affine(s, space, v, rational);
761 if (!pwaff2)
762 goto error;
764 pa_cond = isl_set_indicator_function(isl_map_wrap(cond));
765 return isl_pw_aff_cond(pa_cond, pwaff1, pwaff2);
766 error:
767 isl_map_free(cond);
768 isl_pw_aff_free(pwaff1);
769 isl_pw_aff_free(pwaff2);
770 return NULL;
773 /* Set *line and *col to those of the next token, if any.
775 static void set_current_line_col(__isl_keep isl_stream *s, int *line, int *col)
777 struct isl_token *tok;
779 tok = isl_stream_next_token(s);
780 if (!tok)
781 return;
783 *line = tok->line;
784 *col = tok->col;
785 isl_stream_push_token(s, tok);
788 /* Push a token encapsulating "pa" onto "s", with the given
789 * line and column.
791 static isl_stat push_aff(__isl_keep isl_stream *s, int line, int col,
792 __isl_take isl_pw_aff *pa)
794 struct isl_token *tok;
796 tok = isl_token_new(s->ctx, line, col, 0);
797 if (!tok)
798 goto error;
799 tok->type = ISL_TOKEN_AFF;
800 tok->u.pwaff = pa;
801 isl_stream_push_token(s, tok);
803 return isl_stat_ok;
804 error:
805 isl_pw_aff_free(pa);
806 return isl_stat_error;
809 /* Is the next token a comparison operator?
811 static int next_is_comparator(__isl_keep isl_stream *s)
813 int is_comp;
814 struct isl_token *tok;
816 tok = isl_stream_next_token(s);
817 if (!tok)
818 return 0;
820 is_comp = is_comparator(tok);
821 isl_stream_push_token(s, tok);
823 return is_comp;
826 /* Accept an affine expression that may involve ternary operators.
827 * We first read an affine expression.
828 * If it is not followed by a comparison operator, we simply return it.
829 * Otherwise, we assume the affine expression is part of the first
830 * argument of a ternary operator and try to parse that.
832 static __isl_give isl_pw_aff *accept_extended_affine(__isl_keep isl_stream *s,
833 __isl_take isl_space *space, struct vars *v, int rational)
835 isl_map *cond;
836 isl_pw_aff *pwaff;
837 int line = -1, col = -1;
839 set_current_line_col(s, &line, &col);
841 pwaff = accept_affine(s, space, v);
842 if (rational)
843 pwaff = isl_pw_aff_set_rational(pwaff);
844 if (!pwaff)
845 return NULL;
846 if (!next_is_comparator(s))
847 return pwaff;
849 space = isl_pw_aff_get_domain_space(pwaff);
850 cond = isl_map_universe(isl_space_unwrap(space));
852 if (push_aff(s, line, col, pwaff) < 0)
853 cond = isl_map_free(cond);
854 if (!cond)
855 return NULL;
857 cond = read_formula(s, v, cond, rational);
859 return accept_ternary(s, cond, v, rational);
862 static __isl_give isl_map *read_var_def(__isl_keep isl_stream *s,
863 __isl_take isl_map *map, enum isl_dim_type type, struct vars *v,
864 int rational)
866 isl_pw_aff *def;
867 isl_size pos;
868 isl_map *def_map;
870 if (type == isl_dim_param)
871 pos = isl_map_dim(map, isl_dim_param);
872 else {
873 pos = isl_map_dim(map, isl_dim_in);
874 if (type == isl_dim_out) {
875 isl_size n_out = isl_map_dim(map, isl_dim_out);
876 if (pos < 0 || n_out < 0)
877 return isl_map_free(map);
878 pos += n_out;
880 type = isl_dim_in;
882 if (pos < 0)
883 return isl_map_free(map);
884 --pos;
886 def = accept_extended_affine(s, isl_space_wrap(isl_map_get_space(map)),
887 v, rational);
888 def_map = isl_map_from_pw_aff(def);
889 def_map = isl_map_equate(def_map, type, pos, isl_dim_out, 0);
890 def_map = isl_set_unwrap(isl_map_domain(def_map));
892 map = isl_map_intersect(map, def_map);
894 return map;
897 static __isl_give isl_pw_aff_list *accept_affine_list(__isl_keep isl_stream *s,
898 __isl_take isl_space *space, struct vars *v)
900 isl_pw_aff *pwaff;
901 isl_pw_aff_list *list;
902 struct isl_token *tok = NULL;
904 pwaff = accept_affine(s, isl_space_copy(space), v);
905 list = isl_pw_aff_list_from_pw_aff(pwaff);
906 if (!list)
907 goto error;
909 for (;;) {
910 tok = isl_stream_next_token(s);
911 if (!tok) {
912 isl_stream_error(s, NULL, "unexpected EOF");
913 goto error;
915 if (tok->type != ',') {
916 isl_stream_push_token(s, tok);
917 break;
919 isl_token_free(tok);
921 pwaff = accept_affine(s, isl_space_copy(space), v);
922 list = isl_pw_aff_list_concat(list,
923 isl_pw_aff_list_from_pw_aff(pwaff));
924 if (!list)
925 goto error;
928 isl_space_free(space);
929 return list;
930 error:
931 isl_space_free(space);
932 isl_pw_aff_list_free(list);
933 return NULL;
936 static __isl_give isl_map *read_defined_var_list(__isl_keep isl_stream *s,
937 struct vars *v, __isl_take isl_map *map, int rational)
939 struct isl_token *tok;
941 while ((tok = isl_stream_next_token(s)) != NULL) {
942 int p;
943 int n = v->n;
945 if (tok->type != ISL_TOKEN_IDENT)
946 break;
948 p = vars_pos(v, tok->u.s, -1);
949 if (p < 0)
950 goto error;
951 if (p < n) {
952 isl_stream_error(s, tok, "expecting unique identifier");
953 goto error;
956 map = isl_map_add_dims(map, isl_dim_out, 1);
958 isl_token_free(tok);
959 tok = isl_stream_next_token(s);
960 if (tok && tok->type == '=') {
961 isl_token_free(tok);
962 map = read_var_def(s, map, isl_dim_out, v, rational);
963 tok = isl_stream_next_token(s);
966 if (!tok || tok->type != ',')
967 break;
969 isl_token_free(tok);
971 if (tok)
972 isl_stream_push_token(s, tok);
974 return map;
975 error:
976 isl_token_free(tok);
977 isl_map_free(map);
978 return NULL;
981 static int next_is_tuple(__isl_keep isl_stream *s)
983 struct isl_token *tok;
984 int is_tuple;
986 tok = isl_stream_next_token(s);
987 if (!tok)
988 return 0;
989 if (tok->type == '[') {
990 isl_stream_push_token(s, tok);
991 return 1;
993 if (tok->type != ISL_TOKEN_IDENT && !tok->is_keyword) {
994 isl_stream_push_token(s, tok);
995 return 0;
998 is_tuple = isl_stream_next_token_is(s, '[');
1000 isl_stream_push_token(s, tok);
1002 return is_tuple;
1005 /* Does the next token mark the end of a tuple element?
1007 static int next_is_end_tuple_element(__isl_keep isl_stream *s)
1009 return isl_stream_next_token_is(s, ',') ||
1010 isl_stream_next_token_is(s, ']');
1013 /* Is the next token one that necessarily forms the start of a condition?
1015 static int next_is_condition_start(__isl_keep isl_stream *s)
1017 return isl_stream_next_token_is(s, ISL_TOKEN_EXISTS) ||
1018 isl_stream_next_token_is(s, ISL_TOKEN_NOT) ||
1019 isl_stream_next_token_is(s, ISL_TOKEN_TRUE) ||
1020 isl_stream_next_token_is(s, ISL_TOKEN_FALSE) ||
1021 isl_stream_next_token_is(s, ISL_TOKEN_MAP);
1024 /* Is "pa" an expression in term of earlier dimensions?
1025 * The alternative is that the dimension is defined to be equal to itself,
1026 * meaning that it has a universe domain and an expression that depends
1027 * on itself. "i" is the position of the expression in a sequence
1028 * of "n" expressions. The final dimensions of "pa" correspond to
1029 * these "n" expressions.
1031 static isl_bool pw_aff_is_expr(__isl_keep isl_pw_aff *pa, int i, int n)
1033 isl_aff *aff;
1035 if (!pa)
1036 return isl_bool_error;
1037 if (pa->n != 1)
1038 return isl_bool_true;
1039 if (!isl_set_plain_is_universe(pa->p[0].set))
1040 return isl_bool_true;
1042 aff = pa->p[0].aff;
1043 if (isl_int_is_zero(aff->v->el[aff->v->size - n + i]))
1044 return isl_bool_true;
1045 return isl_bool_false;
1048 /* Does the tuple contain any dimensions that are defined
1049 * in terms of earlier dimensions?
1051 static isl_bool tuple_has_expr(__isl_keep isl_multi_pw_aff *tuple)
1053 int i;
1054 isl_size n;
1055 isl_bool has_expr = isl_bool_false;
1056 isl_pw_aff *pa;
1058 n = isl_multi_pw_aff_dim(tuple, isl_dim_out);
1059 if (n < 0)
1060 return isl_bool_error;
1061 for (i = 0; i < n; ++i) {
1062 pa = isl_multi_pw_aff_get_pw_aff(tuple, i);
1063 has_expr = pw_aff_is_expr(pa, i, n);
1064 isl_pw_aff_free(pa);
1065 if (has_expr < 0 || has_expr)
1066 break;
1069 return has_expr;
1072 /* Set the name of dimension "pos" in "space" to "name".
1073 * During printing, we add primes if the same name appears more than once
1074 * to distinguish the occurrences. Here, we remove those primes from "name"
1075 * before setting the name of the dimension.
1077 static __isl_give isl_space *space_set_dim_name(__isl_take isl_space *space,
1078 int pos, char *name)
1080 char *prime;
1082 if (!name)
1083 return space;
1085 prime = strchr(name, '\'');
1086 if (prime)
1087 *prime = '\0';
1088 space = isl_space_set_dim_name(space, isl_dim_out, pos, name);
1089 if (prime)
1090 *prime = '\'';
1092 return space;
1095 /* Construct an isl_pw_aff defined on a "space" (with v->n variables)
1096 * that is equal to the last of those variables.
1098 static __isl_give isl_pw_aff *identity_tuple_el_on_space(
1099 __isl_take isl_space *space, struct vars *v)
1101 isl_aff *aff;
1103 aff = isl_aff_zero_on_domain(isl_local_space_from_space(space));
1104 aff = isl_aff_add_coefficient_si(aff, isl_dim_in, v->n - 1, 1);
1105 return isl_pw_aff_from_aff(aff);
1108 /* Construct an isl_pw_aff defined on the domain space of "pa"
1109 * that is equal to the last variable in "v".
1111 * That is, if D is the domain space of "pa", then construct
1113 * D[..., i] -> i.
1115 static __isl_give isl_pw_aff *init_range(__isl_keep isl_pw_aff *pa,
1116 struct vars *v)
1118 isl_space *space;
1120 space = isl_pw_aff_get_domain_space(pa);
1121 return identity_tuple_el_on_space(space, v);
1124 /* Impose the lower bound "lower" on the variable represented by "range_pa".
1126 * In particular, "range_pa" is of the form
1128 * D[..., i] -> i : C
1130 * with D also the domains space of "lower' and "C" some constraints.
1132 * Return the expression
1134 * D[..., i] -> i : C and i >= lower
1136 static __isl_give isl_pw_aff *set_lower(__isl_take isl_pw_aff *range_pa,
1137 __isl_take isl_pw_aff *lower)
1139 isl_set *range;
1141 range = isl_pw_aff_ge_set(isl_pw_aff_copy(range_pa), lower);
1142 return isl_pw_aff_intersect_domain(range_pa, range);
1145 /* Impose the upper bound "upper" on the variable represented by "range_pa".
1147 * In particular, "range_pa" is of the form
1149 * D[..., i] -> i : C
1151 * with D also the domains space of "upper' and "C" some constraints.
1153 * Return the expression
1155 * D[..., i] -> i : C and i <= upper
1157 static __isl_give isl_pw_aff *set_upper(__isl_take isl_pw_aff *range_pa,
1158 __isl_take isl_pw_aff *upper)
1160 isl_set *range;
1162 range = isl_pw_aff_le_set(isl_pw_aff_copy(range_pa), upper);
1163 return isl_pw_aff_intersect_domain(range_pa, range);
1166 /* Construct a piecewise affine expression corresponding
1167 * to the last variable in "v" that is greater than or equal to "pa".
1169 * In particular, if D is the domain space of "pa",
1170 * then construct the expression
1172 * D[..., i] -> i,
1174 * impose lower bound "pa" and return
1176 * D[..., i] -> i : i >= pa
1178 static __isl_give isl_pw_aff *construct_lower(__isl_take isl_pw_aff *pa,
1179 struct vars *v)
1181 return set_lower(init_range(pa, v), pa);
1184 /* Construct a piecewise affine expression corresponding
1185 * to the last variable in "v" that is smaller than or equal to "pa".
1187 * In particular, if D is the domain space of "pa",
1188 * then construct the expression
1190 * D[..., i] -> i,
1192 * impose lower bound "pa" and return
1194 * D[..., i] -> i : i <= pa
1196 static __isl_give isl_pw_aff *construct_upper(__isl_take isl_pw_aff *pa,
1197 struct vars *v)
1199 return set_upper(init_range(pa, v), pa);
1202 /* Construct a piecewise affine expression corresponding
1203 * to the last variable in "v" that ranges between "pa" and "pa2".
1205 * In particular, if D is the domain space of "pa" (and "pa2"),
1206 * then construct the expression
1208 * D[..., i] -> i,
1210 * impose lower bound "pa" and upper bound "pa2" and return
1212 * D[..., i] -> i : pa <= i <= pa2
1214 static __isl_give isl_pw_aff *construct_range(__isl_take isl_pw_aff *pa,
1215 __isl_take isl_pw_aff *pa2, struct vars *v)
1217 return set_upper(set_lower(init_range(pa, v), pa), pa2);
1220 static int resolve_paren_expr(__isl_keep isl_stream *s,
1221 struct vars *v, __isl_take isl_map *map, int rational);
1223 /* Given that the (piecewise) affine expression "pa"
1224 * has just been parsed, followed by a colon,
1225 * continue parsing as part of a piecewise affine expression.
1227 * In particular, check if the colon is followed by a condition.
1228 * If so, parse the conditions(a) on "pa" and include them in the domain.
1229 * Otherwise, if the colon is followed by another (piecewise) affine expression
1230 * then consider the two expressions as endpoints of a range of values and
1231 * return a piecewise affine expression that takes values in that range.
1232 * Note that an affine expression followed by a comparison operator
1233 * is considered to be part of a condition.
1234 * If the colon is not followed by anything (inside the tuple element),
1235 * then consider "pa" as a lower bound on a range of values without upper bound
1236 * and return a piecewise affine expression that takes values in that range.
1238 static __isl_give isl_pw_aff *update_piecewise_affine_colon(
1239 __isl_take isl_pw_aff *pa, __isl_keep isl_stream *s,
1240 struct vars *v, int rational)
1242 isl_space *dom_space;
1243 isl_map *map;
1245 dom_space = isl_pw_aff_get_domain_space(pa);
1246 map = isl_map_universe(isl_space_from_domain(dom_space));
1248 if (isl_stream_next_token_is(s, '('))
1249 if (resolve_paren_expr(s, v, isl_map_copy(map), rational))
1250 goto error;
1251 if (next_is_end_tuple_element(s)) {
1252 isl_map_free(map);
1253 return construct_lower(pa, v);
1255 if (!next_is_condition_start(s)) {
1256 int line = -1, col = -1;
1257 isl_space *space;
1258 isl_pw_aff *pa2;
1260 set_current_line_col(s, &line, &col);
1261 space = isl_space_wrap(isl_map_get_space(map));
1262 pa2 = accept_affine(s, space, v);
1263 if (rational)
1264 pa2 = isl_pw_aff_set_rational(pa2);
1265 if (!next_is_comparator(s)) {
1266 isl_map_free(map);
1267 pa2 = isl_pw_aff_domain_factor_domain(pa2);
1268 return construct_range(pa, pa2, v);
1270 if (push_aff(s, line, col, pa2) < 0)
1271 goto error;
1274 map = read_formula(s, v, map, rational);
1275 pa = isl_pw_aff_intersect_domain(pa, isl_map_domain(map));
1277 return pa;
1278 error:
1279 isl_map_free(map);
1280 isl_pw_aff_free(pa);
1281 return NULL;
1284 /* Accept a piecewise affine expression.
1286 * At the outer level, the piecewise affine expression may be of the form
1288 * aff1 : condition1; aff2 : conditions2; ...
1290 * or one of
1292 * aff :
1293 * aff1 : aff2
1294 * : aff
1297 * or simply
1299 * aff
1301 * each of the affine expressions may in turn include ternary operators.
1303 * If the first token is a colon, then the expression must be
1304 * ":" or ": aff2", depending on whether anything follows the colon
1305 * inside the tuple element.
1306 * The first is considered to represent an arbitrary value.
1307 * The second is considered to represent a range of values
1308 * with the given upper bound and no lower bound.
1310 * There may be parentheses around some subexpression of "aff1"
1311 * around "aff1" itself, around "aff1 : condition1" and/or
1312 * around the entire piecewise affine expression.
1313 * We therefore remove the opening parenthesis (if any) from the stream
1314 * in case the closing parenthesis follows the colon, but if the closing
1315 * parenthesis is the first thing in the stream after the parsed affine
1316 * expression, we push the parsed expression onto the stream and parse
1317 * again in case the parentheses enclose some subexpression of "aff1".
1319 static __isl_give isl_pw_aff *accept_piecewise_affine(__isl_keep isl_stream *s,
1320 __isl_take isl_space *space, struct vars *v, int rational)
1322 isl_pw_aff *res;
1323 isl_space *res_space;
1325 if (isl_stream_eat_if_available(s, ':')) {
1326 if (next_is_end_tuple_element(s))
1327 return identity_tuple_el_on_space(space, v);
1328 else
1329 return construct_upper(accept_affine(s, space, v), v);
1332 res_space = isl_space_from_domain(isl_space_copy(space));
1333 res_space = isl_space_add_dims(res_space, isl_dim_out, 1);
1334 res = isl_pw_aff_empty(res_space);
1335 do {
1336 isl_pw_aff *pa;
1337 int seen_paren;
1338 int line = -1, col = -1;
1340 set_current_line_col(s, &line, &col);
1341 seen_paren = isl_stream_eat_if_available(s, '(');
1342 if (seen_paren)
1343 pa = accept_piecewise_affine(s, isl_space_copy(space),
1344 v, rational);
1345 else
1346 pa = accept_extended_affine(s, isl_space_copy(space),
1347 v, rational);
1348 if (seen_paren && isl_stream_eat_if_available(s, ')')) {
1349 seen_paren = 0;
1350 if (push_aff(s, line, col, pa) < 0)
1351 goto error;
1352 pa = accept_extended_affine(s, isl_space_copy(space),
1353 v, rational);
1355 if (isl_stream_eat_if_available(s, ':'))
1356 pa = update_piecewise_affine_colon(pa, s, v, rational);
1358 res = isl_pw_aff_union_add(res, pa);
1360 if (seen_paren && isl_stream_eat(s, ')'))
1361 goto error;
1362 } while (isl_stream_eat_if_available(s, ';'));
1364 isl_space_free(space);
1366 return res;
1367 error:
1368 isl_space_free(space);
1369 return isl_pw_aff_free(res);
1372 /* Read an affine expression from "s" for use in read_tuple.
1374 * accept_extended_affine requires a wrapped space as input.
1375 * read_tuple on the other hand expects each isl_pw_aff
1376 * to have an anonymous space. We therefore adjust the space
1377 * of the isl_pw_aff before returning it.
1379 static __isl_give isl_pw_aff *read_tuple_var_def(__isl_keep isl_stream *s,
1380 struct vars *v, int rational)
1382 isl_space *space;
1383 isl_pw_aff *def;
1385 space = isl_space_wrap(isl_space_alloc(s->ctx, 0, v->n, 0));
1387 def = accept_piecewise_affine(s, space, v, rational);
1388 def = isl_pw_aff_domain_factor_domain(def);
1390 return def;
1393 /* Read a list of tuple elements by calling "read_el" on each of them and
1394 * return a space with the same number of set dimensions derived from
1395 * the parameter space "space" and possibly updated by "read_el".
1396 * The elements in the list are separated by either "," or "][".
1397 * If "comma" is set then only "," is allowed.
1399 static __isl_give isl_space *read_tuple_list(__isl_keep isl_stream *s,
1400 struct vars *v, __isl_take isl_space *space, int rational, int comma,
1401 __isl_give isl_space *(*read_el)(__isl_keep isl_stream *s,
1402 struct vars *v, __isl_take isl_space *space, int rational,
1403 void *user),
1404 void *user)
1406 if (!space)
1407 return NULL;
1409 space = isl_space_set_from_params(space);
1411 if (isl_stream_next_token_is(s, ']'))
1412 return space;
1414 for (;;) {
1415 struct isl_token *tok;
1417 space = isl_space_add_dims(space, isl_dim_set, 1);
1419 space = read_el(s, v, space, rational, user);
1420 if (!space)
1421 return NULL;
1423 tok = isl_stream_next_token(s);
1424 if (!comma && tok && tok->type == ']' &&
1425 isl_stream_next_token_is(s, '[')) {
1426 isl_token_free(tok);
1427 tok = isl_stream_next_token(s);
1428 } else if (!tok || tok->type != ',') {
1429 if (tok)
1430 isl_stream_push_token(s, tok);
1431 break;
1434 isl_token_free(tok);
1437 return space;
1440 /* Read a tuple space from "s" derived from the parameter space "space".
1441 * Call "read_el" on each element in the tuples.
1443 static __isl_give isl_space *read_tuple_space(__isl_keep isl_stream *s,
1444 struct vars *v, __isl_take isl_space *space, int rational, int comma,
1445 __isl_give isl_space *(*read_el)(__isl_keep isl_stream *s,
1446 struct vars *v, __isl_take isl_space *space, int rational,
1447 void *user),
1448 void *user)
1450 struct isl_token *tok;
1451 char *name = NULL;
1452 isl_space *res = NULL;
1454 tok = isl_stream_next_token(s);
1455 if (!tok)
1456 goto error;
1457 if (tok->type == ISL_TOKEN_IDENT || tok->is_keyword) {
1458 name = strdup(tok->u.s);
1459 isl_token_free(tok);
1460 if (!name)
1461 goto error;
1462 } else
1463 isl_stream_push_token(s, tok);
1464 if (isl_stream_eat(s, '['))
1465 goto error;
1466 if (next_is_tuple(s)) {
1467 isl_space *out;
1468 res = read_tuple_space(s, v, isl_space_copy(space),
1469 rational, comma, read_el, user);
1470 if (isl_stream_eat(s, ISL_TOKEN_TO))
1471 goto error;
1472 out = read_tuple_space(s, v, isl_space_copy(space),
1473 rational, comma, read_el, user);
1474 res = isl_space_product(res, out);
1475 } else
1476 res = read_tuple_list(s, v, isl_space_copy(space),
1477 rational, comma, read_el, user);
1478 if (isl_stream_eat(s, ']'))
1479 goto error;
1481 if (name) {
1482 res = isl_space_set_tuple_name(res, isl_dim_set, name);
1483 free(name);
1486 isl_space_free(space);
1487 return res;
1488 error:
1489 free(name);
1490 isl_space_free(res);
1491 isl_space_free(space);
1492 return NULL;
1495 /* Construct an isl_pw_aff defined on a space with v->n variables
1496 * that is equal to the last of those variables.
1498 static __isl_give isl_pw_aff *identity_tuple_el(struct vars *v)
1500 isl_space *space;
1502 space = isl_space_set_alloc(v->ctx, 0, v->n);
1503 return identity_tuple_el_on_space(space, v);
1506 /* This function is called for each element in a tuple inside read_tuple.
1507 * Add a new variable to "v" and construct a corresponding isl_pw_aff defined
1508 * over a space containing all variables in "v" defined so far.
1509 * The isl_pw_aff expresses the new variable in terms of earlier variables
1510 * if a definition is provided. Otherwise, it is represented as being
1511 * equal to itself.
1512 * Add the isl_pw_aff to *list.
1513 * If the new variable was named, then adjust "space" accordingly and
1514 * return the updated space.
1516 static __isl_give isl_space *read_tuple_pw_aff_el(__isl_keep isl_stream *s,
1517 struct vars *v, __isl_take isl_space *space, int rational, void *user)
1519 isl_pw_aff_list **list = (isl_pw_aff_list **) user;
1520 isl_pw_aff *pa;
1521 struct isl_token *tok;
1522 int new_name = 0;
1524 tok = next_token(s);
1525 if (!tok) {
1526 isl_stream_error(s, NULL, "unexpected EOF");
1527 return isl_space_free(space);
1530 if (tok->type == ISL_TOKEN_IDENT) {
1531 int n = v->n;
1532 int p = vars_pos(v, tok->u.s, -1);
1533 if (p < 0)
1534 goto error;
1535 new_name = p >= n;
1538 if (tok->type == '*') {
1539 if (vars_add_anon(v) < 0)
1540 goto error;
1541 isl_token_free(tok);
1542 pa = identity_tuple_el(v);
1543 } else if (new_name) {
1544 isl_size pos = isl_space_dim(space, isl_dim_out);
1545 if (pos < 0)
1546 goto error;
1547 pos -= 1;
1548 space = space_set_dim_name(space, pos, v->v->name);
1549 isl_token_free(tok);
1550 if (isl_stream_eat_if_available(s, '='))
1551 pa = read_tuple_var_def(s, v, rational);
1552 else
1553 pa = identity_tuple_el(v);
1554 } else {
1555 isl_stream_push_token(s, tok);
1556 tok = NULL;
1557 if (vars_add_anon(v) < 0)
1558 goto error;
1559 pa = read_tuple_var_def(s, v, rational);
1562 *list = isl_pw_aff_list_add(*list, pa);
1563 if (!*list)
1564 return isl_space_free(space);
1566 return space;
1567 error:
1568 isl_token_free(tok);
1569 return isl_space_free(space);
1572 /* Read a tuple and represent it as an isl_multi_pw_aff.
1573 * The range space of the isl_multi_pw_aff is the space of the tuple.
1574 * The domain space is an anonymous space
1575 * with a dimension for each variable in the set of variables in "v",
1576 * including the variables in the range.
1577 * If a given dimension is not defined in terms of earlier dimensions in
1578 * the input, then the corresponding isl_pw_aff is set equal to one time
1579 * the variable corresponding to the dimension being defined.
1581 * The elements in the tuple are collected in a list by read_tuple_pw_aff_el.
1582 * Each element in this list is defined over a space representing
1583 * the variables defined so far. We need to adjust the earlier
1584 * elements to have as many variables in the domain as the final
1585 * element in the list.
1587 static __isl_give isl_multi_pw_aff *read_tuple(__isl_keep isl_stream *s,
1588 struct vars *v, int rational, int comma)
1590 int i;
1591 isl_size n;
1592 isl_space *space;
1593 isl_pw_aff_list *list;
1595 space = isl_space_params_alloc(v->ctx, 0);
1596 list = isl_pw_aff_list_alloc(s->ctx, 0);
1597 space = read_tuple_space(s, v, space, rational, comma,
1598 &read_tuple_pw_aff_el, &list);
1599 n = isl_space_dim(space, isl_dim_set);
1600 if (n < 0)
1601 space = isl_space_free(space);
1602 for (i = 0; i + 1 < n; ++i) {
1603 isl_pw_aff *pa;
1605 pa = isl_pw_aff_list_get_pw_aff(list, i);
1606 pa = isl_pw_aff_add_dims(pa, isl_dim_in, n - (i + 1));
1607 list = isl_pw_aff_list_set_pw_aff(list, i, pa);
1610 space = isl_space_from_range(space);
1611 space = isl_space_add_dims(space, isl_dim_in, v->n);
1612 return isl_multi_pw_aff_from_pw_aff_list(space, list);
1615 /* Add the tuple represented by the isl_multi_pw_aff "tuple" to "map".
1616 * We first create the appropriate space in "map" based on the range
1617 * space of this isl_multi_pw_aff. Then, we add equalities based
1618 * on the affine expressions. These live in an anonymous space,
1619 * however, so we first need to reset the space to that of "map".
1621 static __isl_give isl_map *map_from_tuple(__isl_take isl_multi_pw_aff *tuple,
1622 __isl_take isl_map *map, enum isl_dim_type type, struct vars *v,
1623 int rational)
1625 int i;
1626 isl_size n;
1627 isl_ctx *ctx;
1628 isl_space *space = NULL;
1630 n = isl_multi_pw_aff_dim(tuple, isl_dim_out);
1631 if (!map || n < 0)
1632 goto error;
1633 ctx = isl_multi_pw_aff_get_ctx(tuple);
1634 space = isl_space_range(isl_multi_pw_aff_get_space(tuple));
1635 if (!space)
1636 goto error;
1638 if (type == isl_dim_param) {
1639 if (isl_space_has_tuple_name(space, isl_dim_set) ||
1640 isl_space_is_wrapping(space)) {
1641 isl_die(ctx, isl_error_invalid,
1642 "parameter tuples cannot be named or nested",
1643 goto error);
1645 map = isl_map_add_dims(map, type, n);
1646 for (i = 0; i < n; ++i) {
1647 isl_id *id;
1648 if (!isl_space_has_dim_name(space, isl_dim_set, i))
1649 isl_die(ctx, isl_error_invalid,
1650 "parameters must be named",
1651 goto error);
1652 id = isl_space_get_dim_id(space, isl_dim_set, i);
1653 map = isl_map_set_dim_id(map, isl_dim_param, i, id);
1655 } else if (type == isl_dim_in) {
1656 isl_set *set;
1658 set = isl_set_universe(isl_space_copy(space));
1659 if (rational)
1660 set = isl_set_set_rational(set);
1661 set = isl_set_intersect_params(set, isl_map_params(map));
1662 map = isl_map_from_domain(set);
1663 } else {
1664 isl_set *set;
1666 set = isl_set_universe(isl_space_copy(space));
1667 if (rational)
1668 set = isl_set_set_rational(set);
1669 map = isl_map_from_domain_and_range(isl_map_domain(map), set);
1672 for (i = 0; i < n; ++i) {
1673 isl_pw_aff *pa;
1674 isl_space *space;
1675 isl_aff *aff;
1676 isl_set *set;
1677 isl_map *map_i;
1679 pa = isl_multi_pw_aff_get_pw_aff(tuple, i);
1680 space = isl_pw_aff_get_domain_space(pa);
1681 aff = isl_aff_zero_on_domain(isl_local_space_from_space(space));
1682 aff = isl_aff_add_coefficient_si(aff,
1683 isl_dim_in, v->n - n + i, -1);
1684 pa = isl_pw_aff_add(pa, isl_pw_aff_from_aff(aff));
1685 if (rational)
1686 pa = isl_pw_aff_set_rational(pa);
1687 set = isl_pw_aff_zero_set(pa);
1688 map_i = isl_map_from_range(set);
1689 map_i = isl_map_reset_space(map_i, isl_map_get_space(map));
1690 map = isl_map_intersect(map, map_i);
1693 isl_space_free(space);
1694 isl_multi_pw_aff_free(tuple);
1695 return map;
1696 error:
1697 isl_space_free(space);
1698 isl_multi_pw_aff_free(tuple);
1699 isl_map_free(map);
1700 return NULL;
1703 /* Read a tuple from "s" and add it to "map".
1704 * The tuple is initially represented as an isl_multi_pw_aff and
1705 * then added to "map".
1707 static __isl_give isl_map *read_map_tuple(__isl_keep isl_stream *s,
1708 __isl_take isl_map *map, enum isl_dim_type type, struct vars *v,
1709 int rational, int comma)
1711 isl_multi_pw_aff *tuple;
1713 tuple = read_tuple(s, v, rational, comma);
1714 if (!tuple)
1715 return isl_map_free(map);
1717 return map_from_tuple(tuple, map, type, v, rational);
1720 /* Given two equal-length lists of piecewise affine expression with the space
1721 * of "set" as domain, construct a set in the same space that expresses
1722 * that "left" and "right" satisfy the comparison "type".
1724 * A space is constructed of the same dimension as the number of elements
1725 * in the two lists. The comparison is then expressed in a map from
1726 * this space to itself and wrapped into a set. Finally the two lists
1727 * of piecewise affine expressions are plugged into this set.
1729 * Let S be the space of "set" and T the constructed space.
1730 * The lists are first changed into two isl_multi_pw_affs in S -> T and
1731 * then combined into an isl_multi_pw_aff in S -> [T -> T],
1732 * while the comparison is first expressed in T -> T, then [T -> T]
1733 * and finally in S.
1735 static __isl_give isl_set *list_cmp(__isl_keep isl_set *set, int type,
1736 __isl_take isl_pw_aff_list *left, __isl_take isl_pw_aff_list *right)
1738 isl_space *space;
1739 isl_size n;
1740 isl_multi_pw_aff *mpa1, *mpa2;
1742 n = isl_pw_aff_list_n_pw_aff(left);
1743 if (!set || n < 0 || !right)
1744 goto error;
1746 space = isl_set_get_space(set);
1747 space = isl_space_from_domain(space);
1748 space = isl_space_add_dims(space, isl_dim_out, n);
1749 mpa1 = isl_multi_pw_aff_from_pw_aff_list(isl_space_copy(space), left);
1750 mpa2 = isl_multi_pw_aff_from_pw_aff_list(isl_space_copy(space), right);
1751 mpa1 = isl_multi_pw_aff_range_product(mpa1, mpa2);
1753 space = isl_space_range(space);
1754 switch (type) {
1755 case ISL_TOKEN_LEX_LT:
1756 set = isl_map_wrap(isl_map_lex_lt(space));
1757 break;
1758 case ISL_TOKEN_LEX_GT:
1759 set = isl_map_wrap(isl_map_lex_gt(space));
1760 break;
1761 case ISL_TOKEN_LEX_LE:
1762 set = isl_map_wrap(isl_map_lex_le(space));
1763 break;
1764 case ISL_TOKEN_LEX_GE:
1765 set = isl_map_wrap(isl_map_lex_ge(space));
1766 break;
1767 default:
1768 isl_multi_pw_aff_free(mpa1);
1769 isl_space_free(space);
1770 isl_die(isl_set_get_ctx(set), isl_error_internal,
1771 "unhandled list comparison type", return NULL);
1773 set = isl_set_preimage_multi_pw_aff(set, mpa1);
1774 return set;
1775 error:
1776 isl_pw_aff_list_free(left);
1777 isl_pw_aff_list_free(right);
1778 return NULL;
1781 /* Construct constraints of the form
1783 * a op b
1785 * where a is an element in "left", op is an operator of type "type" and
1786 * b is an element in "right", add the constraints to "set" and return
1787 * the result.
1788 * "rational" is set if the constraints should be treated as
1789 * a rational constraints.
1791 * If "type" is the type of a comparison operator between lists
1792 * of affine expressions, then a single (compound) constraint
1793 * is constructed by list_cmp instead.
1795 static __isl_give isl_set *construct_constraints(
1796 __isl_take isl_set *set, int type,
1797 __isl_keep isl_pw_aff_list *left, __isl_keep isl_pw_aff_list *right,
1798 int rational)
1800 isl_set *cond;
1802 left = isl_pw_aff_list_copy(left);
1803 right = isl_pw_aff_list_copy(right);
1804 if (rational) {
1805 left = isl_pw_aff_list_set_rational(left);
1806 right = isl_pw_aff_list_set_rational(right);
1808 if (is_list_comparator_type(type))
1809 cond = list_cmp(set, type, left, right);
1810 else if (type == ISL_TOKEN_LE)
1811 cond = isl_pw_aff_list_le_set(left, right);
1812 else if (type == ISL_TOKEN_GE)
1813 cond = isl_pw_aff_list_ge_set(left, right);
1814 else if (type == ISL_TOKEN_LT)
1815 cond = isl_pw_aff_list_lt_set(left, right);
1816 else if (type == ISL_TOKEN_GT)
1817 cond = isl_pw_aff_list_gt_set(left, right);
1818 else if (type == ISL_TOKEN_NE)
1819 cond = isl_pw_aff_list_ne_set(left, right);
1820 else
1821 cond = isl_pw_aff_list_eq_set(left, right);
1823 return isl_set_intersect(set, cond);
1826 /* Read a constraint from "s", add it to "map" and return the result.
1827 * "v" contains a description of the identifiers parsed so far.
1828 * "rational" is set if the constraint should be treated as
1829 * a rational constraint.
1830 * The constraint read from "s" may be applied to multiple pairs
1831 * of affine expressions and may be chained.
1832 * In particular, a list of affine expressions is read, followed
1833 * by a comparison operator and another list of affine expressions.
1834 * The comparison operator is then applied to each pair of elements
1835 * in the two lists and the results are added to "map".
1836 * However, if the operator expects two lists of affine expressions,
1837 * then it is applied directly to those lists and the two lists
1838 * are required to have the same length.
1839 * If the next token is another comparison operator, then another
1840 * list of affine expressions is read and the process repeats.
1842 * The processing is performed on a wrapped copy of "map" because
1843 * an affine expression cannot have a binary relation as domain.
1845 static __isl_give isl_map *add_constraint(__isl_keep isl_stream *s,
1846 struct vars *v, __isl_take isl_map *map, int rational)
1848 struct isl_token *tok;
1849 int type;
1850 isl_pw_aff_list *list1 = NULL, *list2 = NULL;
1851 isl_size n1, n2;
1852 isl_set *set;
1854 set = isl_map_wrap(map);
1855 list1 = accept_affine_list(s, isl_set_get_space(set), v);
1856 if (!list1)
1857 goto error;
1858 tok = isl_stream_next_token(s);
1859 if (!is_comparator(tok)) {
1860 isl_stream_error(s, tok, "missing operator");
1861 if (tok)
1862 isl_stream_push_token(s, tok);
1863 goto error;
1865 type = tok->type;
1866 isl_token_free(tok);
1867 for (;;) {
1868 list2 = accept_affine_list(s, isl_set_get_space(set), v);
1869 n1 = isl_pw_aff_list_n_pw_aff(list1);
1870 n2 = isl_pw_aff_list_n_pw_aff(list2);
1871 if (n1 < 0 || n2 < 0)
1872 goto error;
1873 if (is_list_comparator_type(type) && n1 != n2) {
1874 isl_stream_error(s, NULL,
1875 "list arguments not of same size");
1876 goto error;
1879 set = construct_constraints(set, type, list1, list2, rational);
1880 isl_pw_aff_list_free(list1);
1881 list1 = list2;
1883 if (!next_is_comparator(s))
1884 break;
1885 tok = isl_stream_next_token(s);
1886 type = tok->type;
1887 isl_token_free(tok);
1889 isl_pw_aff_list_free(list1);
1891 return isl_set_unwrap(set);
1892 error:
1893 isl_pw_aff_list_free(list1);
1894 isl_pw_aff_list_free(list2);
1895 isl_set_free(set);
1896 return NULL;
1899 static __isl_give isl_map *read_exists(__isl_keep isl_stream *s,
1900 struct vars *v, __isl_take isl_map *map, int rational)
1902 int n = v->n;
1903 int seen_paren = isl_stream_eat_if_available(s, '(');
1905 map = isl_map_from_domain(isl_map_wrap(map));
1906 map = read_defined_var_list(s, v, map, rational);
1908 if (isl_stream_eat(s, ':'))
1909 goto error;
1911 map = read_formula(s, v, map, rational);
1912 map = isl_set_unwrap(isl_map_domain(map));
1914 vars_drop(v, v->n - n);
1915 if (seen_paren && isl_stream_eat(s, ')'))
1916 goto error;
1918 return map;
1919 error:
1920 isl_map_free(map);
1921 return NULL;
1924 /* Parse an expression between parentheses and push the result
1925 * back on the stream.
1927 * The parsed expression may be either an affine expression
1928 * or a condition. The first type is pushed onto the stream
1929 * as an isl_pw_aff, while the second is pushed as an isl_map.
1931 * If the initial token indicates the start of a condition,
1932 * we parse it as such.
1933 * Otherwise, we first parse an affine expression and push
1934 * that onto the stream. If the affine expression covers the
1935 * entire expression between parentheses, we return.
1936 * Otherwise, we assume that the affine expression is the
1937 * start of a condition and continue parsing.
1939 static int resolve_paren_expr(__isl_keep isl_stream *s,
1940 struct vars *v, __isl_take isl_map *map, int rational)
1942 struct isl_token *tok, *tok2;
1943 int has_paren;
1944 int line, col;
1945 isl_pw_aff *pwaff;
1947 tok = isl_stream_next_token(s);
1948 if (!tok || tok->type != '(')
1949 goto error;
1951 if (isl_stream_next_token_is(s, '('))
1952 if (resolve_paren_expr(s, v, isl_map_copy(map), rational))
1953 goto error;
1955 if (next_is_condition_start(s)) {
1956 map = read_formula(s, v, map, rational);
1957 if (isl_stream_eat(s, ')'))
1958 goto error;
1959 tok->type = ISL_TOKEN_MAP;
1960 tok->u.map = map;
1961 isl_stream_push_token(s, tok);
1962 return 0;
1965 tok2 = isl_stream_next_token(s);
1966 if (!tok2)
1967 goto error;
1968 line = tok2->line;
1969 col = tok2->col;
1970 isl_stream_push_token(s, tok2);
1972 pwaff = accept_affine(s, isl_space_wrap(isl_map_get_space(map)), v);
1973 if (!pwaff)
1974 goto error;
1976 has_paren = isl_stream_eat_if_available(s, ')');
1978 if (push_aff(s, line, col, pwaff) < 0)
1979 goto error;
1981 if (has_paren) {
1982 isl_token_free(tok);
1983 isl_map_free(map);
1984 return 0;
1987 map = read_formula(s, v, map, rational);
1988 if (isl_stream_eat(s, ')'))
1989 goto error;
1991 tok->type = ISL_TOKEN_MAP;
1992 tok->u.map = map;
1993 isl_stream_push_token(s, tok);
1995 return 0;
1996 error:
1997 isl_token_free(tok);
1998 isl_map_free(map);
1999 return -1;
2002 static __isl_give isl_map *read_conjunct(__isl_keep isl_stream *s,
2003 struct vars *v, __isl_take isl_map *map, int rational)
2005 if (isl_stream_next_token_is(s, '('))
2006 if (resolve_paren_expr(s, v, isl_map_copy(map), rational))
2007 goto error;
2009 if (isl_stream_next_token_is(s, ISL_TOKEN_MAP)) {
2010 struct isl_token *tok;
2011 tok = isl_stream_next_token(s);
2012 if (!tok)
2013 goto error;
2014 isl_map_free(map);
2015 map = isl_map_copy(tok->u.map);
2016 isl_token_free(tok);
2017 return map;
2020 if (isl_stream_eat_if_available(s, ISL_TOKEN_EXISTS))
2021 return read_exists(s, v, map, rational);
2023 if (isl_stream_eat_if_available(s, ISL_TOKEN_TRUE))
2024 return map;
2026 if (isl_stream_eat_if_available(s, ISL_TOKEN_FALSE)) {
2027 isl_space *space = isl_map_get_space(map);
2028 isl_map_free(map);
2029 return isl_map_empty(space);
2032 return add_constraint(s, v, map, rational);
2033 error:
2034 isl_map_free(map);
2035 return NULL;
2038 static __isl_give isl_map *read_conjuncts(__isl_keep isl_stream *s,
2039 struct vars *v, __isl_take isl_map *map, int rational)
2041 isl_map *res;
2042 int negate;
2044 negate = isl_stream_eat_if_available(s, ISL_TOKEN_NOT);
2045 res = read_conjunct(s, v, isl_map_copy(map), rational);
2046 if (negate)
2047 res = isl_map_subtract(isl_map_copy(map), res);
2049 while (res && isl_stream_eat_if_available(s, ISL_TOKEN_AND)) {
2050 isl_map *res_i;
2052 negate = isl_stream_eat_if_available(s, ISL_TOKEN_NOT);
2053 res_i = read_conjunct(s, v, isl_map_copy(map), rational);
2054 if (negate)
2055 res = isl_map_subtract(res, res_i);
2056 else
2057 res = isl_map_intersect(res, res_i);
2060 isl_map_free(map);
2061 return res;
2064 static __isl_give isl_map *read_disjuncts(__isl_keep isl_stream *s,
2065 struct vars *v, __isl_take isl_map *map, int rational)
2067 isl_map *res;
2069 if (isl_stream_next_token_is(s, '}'))
2070 return map;
2072 res = read_conjuncts(s, v, isl_map_copy(map), rational);
2073 while (isl_stream_eat_if_available(s, ISL_TOKEN_OR)) {
2074 isl_map *res_i;
2076 res_i = read_conjuncts(s, v, isl_map_copy(map), rational);
2077 res = isl_map_union(res, res_i);
2080 isl_map_free(map);
2081 return res;
2084 /* Read a first order formula from "s", add the corresponding
2085 * constraints to "map" and return the result.
2087 * In particular, read a formula of the form
2091 * or
2093 * a implies b
2095 * where a and b are disjunctions.
2097 * In the first case, map is replaced by
2099 * map \cap { [..] : a }
2101 * In the second case, it is replaced by
2103 * (map \setminus { [..] : a}) \cup (map \cap { [..] : b })
2105 static __isl_give isl_map *read_formula(__isl_keep isl_stream *s,
2106 struct vars *v, __isl_take isl_map *map, int rational)
2108 isl_map *res;
2110 res = read_disjuncts(s, v, isl_map_copy(map), rational);
2112 if (isl_stream_eat_if_available(s, ISL_TOKEN_IMPLIES)) {
2113 isl_map *res2;
2115 res = isl_map_subtract(isl_map_copy(map), res);
2116 res2 = read_disjuncts(s, v, map, rational);
2117 res = isl_map_union(res, res2);
2118 } else
2119 isl_map_free(map);
2121 return res;
2124 static isl_size polylib_pos_to_isl_pos(__isl_keep isl_basic_map *bmap, int pos)
2126 isl_size n_out, n_in, n_param, n_div;
2128 n_param = isl_basic_map_dim(bmap, isl_dim_param);
2129 n_in = isl_basic_map_dim(bmap, isl_dim_in);
2130 n_out = isl_basic_map_dim(bmap, isl_dim_out);
2131 n_div = isl_basic_map_dim(bmap, isl_dim_div);
2132 if (n_param < 0 || n_in < 0 || n_out < 0 || n_div < 0)
2133 return isl_size_error;
2135 if (pos < n_out)
2136 return 1 + n_param + n_in + pos;
2137 pos -= n_out;
2139 if (pos < n_in)
2140 return 1 + n_param + pos;
2141 pos -= n_in;
2143 if (pos < n_div)
2144 return 1 + n_param + n_in + n_out + pos;
2145 pos -= n_div;
2147 if (pos < n_param)
2148 return 1 + pos;
2150 return 0;
2153 static __isl_give isl_basic_map *basic_map_read_polylib_constraint(
2154 __isl_keep isl_stream *s, __isl_take isl_basic_map *bmap)
2156 int j;
2157 struct isl_token *tok;
2158 int type;
2159 int k;
2160 isl_int *c;
2161 isl_size total;
2163 if (!bmap)
2164 return NULL;
2166 tok = isl_stream_next_token(s);
2167 if (!tok || tok->type != ISL_TOKEN_VALUE) {
2168 isl_stream_error(s, tok, "expecting coefficient");
2169 if (tok)
2170 isl_stream_push_token(s, tok);
2171 goto error;
2173 if (!tok->on_new_line) {
2174 isl_stream_error(s, tok, "coefficient should appear on new line");
2175 isl_stream_push_token(s, tok);
2176 goto error;
2179 type = isl_int_get_si(tok->u.v);
2180 isl_token_free(tok);
2182 isl_assert(s->ctx, type == 0 || type == 1, goto error);
2183 if (type == 0) {
2184 k = isl_basic_map_alloc_equality(bmap);
2185 c = bmap->eq[k];
2186 } else {
2187 k = isl_basic_map_alloc_inequality(bmap);
2188 c = bmap->ineq[k];
2190 if (k < 0)
2191 goto error;
2193 total = isl_basic_map_dim(bmap, isl_dim_all);
2194 if (total < 0)
2195 return isl_basic_map_free(bmap);
2196 for (j = 0; j < 1 + total; ++j) {
2197 isl_size pos;
2198 tok = isl_stream_next_token(s);
2199 if (!tok || tok->type != ISL_TOKEN_VALUE) {
2200 isl_stream_error(s, tok, "expecting coefficient");
2201 if (tok)
2202 isl_stream_push_token(s, tok);
2203 goto error;
2205 if (tok->on_new_line) {
2206 isl_stream_error(s, tok,
2207 "coefficient should not appear on new line");
2208 isl_stream_push_token(s, tok);
2209 goto error;
2211 pos = polylib_pos_to_isl_pos(bmap, j);
2212 if (pos >= 0)
2213 isl_int_set(c[pos], tok->u.v);
2214 isl_token_free(tok);
2215 if (pos < 0)
2216 return isl_basic_map_free(bmap);
2219 return bmap;
2220 error:
2221 isl_basic_map_free(bmap);
2222 return NULL;
2225 static __isl_give isl_basic_map *basic_map_read_polylib(
2226 __isl_keep isl_stream *s)
2228 int i;
2229 struct isl_token *tok;
2230 struct isl_token *tok2;
2231 int n_row, n_col;
2232 int on_new_line;
2233 unsigned in = 0, out, local = 0;
2234 struct isl_basic_map *bmap = NULL;
2235 int nparam = 0;
2237 tok = isl_stream_next_token(s);
2238 if (!tok) {
2239 isl_stream_error(s, NULL, "unexpected EOF");
2240 return NULL;
2242 tok2 = isl_stream_next_token(s);
2243 if (!tok2) {
2244 isl_token_free(tok);
2245 isl_stream_error(s, NULL, "unexpected EOF");
2246 return NULL;
2248 if (tok->type != ISL_TOKEN_VALUE || tok2->type != ISL_TOKEN_VALUE) {
2249 isl_stream_push_token(s, tok2);
2250 isl_stream_push_token(s, tok);
2251 isl_stream_error(s, NULL,
2252 "expecting constraint matrix dimensions");
2253 return NULL;
2255 n_row = isl_int_get_si(tok->u.v);
2256 n_col = isl_int_get_si(tok2->u.v);
2257 on_new_line = tok2->on_new_line;
2258 isl_token_free(tok2);
2259 isl_token_free(tok);
2260 isl_assert(s->ctx, !on_new_line, return NULL);
2261 isl_assert(s->ctx, n_row >= 0, return NULL);
2262 isl_assert(s->ctx, n_col >= 2 + nparam, return NULL);
2263 tok = isl_stream_next_token_on_same_line(s);
2264 if (tok) {
2265 if (tok->type != ISL_TOKEN_VALUE) {
2266 isl_stream_error(s, tok,
2267 "expecting number of output dimensions");
2268 isl_stream_push_token(s, tok);
2269 goto error;
2271 out = isl_int_get_si(tok->u.v);
2272 isl_token_free(tok);
2274 tok = isl_stream_next_token_on_same_line(s);
2275 if (!tok || tok->type != ISL_TOKEN_VALUE) {
2276 isl_stream_error(s, tok,
2277 "expecting number of input dimensions");
2278 if (tok)
2279 isl_stream_push_token(s, tok);
2280 goto error;
2282 in = isl_int_get_si(tok->u.v);
2283 isl_token_free(tok);
2285 tok = isl_stream_next_token_on_same_line(s);
2286 if (!tok || tok->type != ISL_TOKEN_VALUE) {
2287 isl_stream_error(s, tok,
2288 "expecting number of existentials");
2289 if (tok)
2290 isl_stream_push_token(s, tok);
2291 goto error;
2293 local = isl_int_get_si(tok->u.v);
2294 isl_token_free(tok);
2296 tok = isl_stream_next_token_on_same_line(s);
2297 if (!tok || tok->type != ISL_TOKEN_VALUE) {
2298 isl_stream_error(s, tok,
2299 "expecting number of parameters");
2300 if (tok)
2301 isl_stream_push_token(s, tok);
2302 goto error;
2304 nparam = isl_int_get_si(tok->u.v);
2305 isl_token_free(tok);
2306 if (n_col != 1 + out + in + local + nparam + 1) {
2307 isl_stream_error(s, NULL,
2308 "dimensions don't match");
2309 goto error;
2311 } else
2312 out = n_col - 2 - nparam;
2313 bmap = isl_basic_map_alloc(s->ctx, nparam, in, out, local, n_row, n_row);
2314 if (!bmap)
2315 return NULL;
2317 for (i = 0; i < local; ++i) {
2318 int k = isl_basic_map_alloc_div(bmap);
2319 if (k < 0)
2320 goto error;
2321 isl_seq_clr(bmap->div[k], 1 + 1 + nparam + in + out + local);
2324 for (i = 0; i < n_row; ++i)
2325 bmap = basic_map_read_polylib_constraint(s, bmap);
2327 tok = isl_stream_next_token_on_same_line(s);
2328 if (tok) {
2329 isl_stream_error(s, tok, "unexpected extra token on line");
2330 isl_stream_push_token(s, tok);
2331 goto error;
2334 bmap = isl_basic_map_simplify(bmap);
2335 bmap = isl_basic_map_finalize(bmap);
2336 return bmap;
2337 error:
2338 isl_basic_map_free(bmap);
2339 return NULL;
2342 static __isl_give isl_map *map_read_polylib(__isl_keep isl_stream *s)
2344 struct isl_token *tok;
2345 struct isl_token *tok2;
2346 int i, n;
2347 struct isl_map *map;
2349 tok = isl_stream_next_token(s);
2350 if (!tok) {
2351 isl_stream_error(s, NULL, "unexpected EOF");
2352 return NULL;
2354 tok2 = isl_stream_next_token_on_same_line(s);
2355 if (tok2 && tok2->type == ISL_TOKEN_VALUE) {
2356 isl_stream_push_token(s, tok2);
2357 isl_stream_push_token(s, tok);
2358 return isl_map_from_basic_map(basic_map_read_polylib(s));
2360 if (tok2) {
2361 isl_stream_error(s, tok2, "unexpected token");
2362 isl_stream_push_token(s, tok2);
2363 isl_stream_push_token(s, tok);
2364 return NULL;
2366 n = isl_int_get_si(tok->u.v);
2367 isl_token_free(tok);
2369 isl_assert(s->ctx, n >= 1, return NULL);
2371 map = isl_map_from_basic_map(basic_map_read_polylib(s));
2373 for (i = 1; map && i < n; ++i)
2374 map = isl_map_union(map,
2375 isl_map_from_basic_map(basic_map_read_polylib(s)));
2377 return map;
2380 static int optional_power(__isl_keep isl_stream *s)
2382 int pow;
2383 struct isl_token *tok;
2385 tok = isl_stream_next_token(s);
2386 if (!tok)
2387 return 1;
2388 if (tok->type != '^') {
2389 isl_stream_push_token(s, tok);
2390 return 1;
2392 isl_token_free(tok);
2393 tok = isl_stream_next_token(s);
2394 if (!tok || tok->type != ISL_TOKEN_VALUE) {
2395 isl_stream_error(s, tok, "expecting exponent");
2396 if (tok)
2397 isl_stream_push_token(s, tok);
2398 return 1;
2400 pow = isl_int_get_si(tok->u.v);
2401 isl_token_free(tok);
2402 return pow;
2405 static __isl_give isl_pw_qpolynomial *read_term(__isl_keep isl_stream *s,
2406 __isl_keep isl_map *map, struct vars *v);
2408 static __isl_give isl_pw_qpolynomial *read_factor(__isl_keep isl_stream *s,
2409 __isl_keep isl_map *map, struct vars *v)
2411 isl_pw_qpolynomial *pwqp;
2412 struct isl_token *tok;
2414 tok = next_token(s);
2415 if (!tok) {
2416 isl_stream_error(s, NULL, "unexpected EOF");
2417 return NULL;
2419 if (tok->type == '(') {
2420 int pow;
2422 isl_token_free(tok);
2423 pwqp = read_term(s, map, v);
2424 if (!pwqp)
2425 return NULL;
2426 if (isl_stream_eat(s, ')'))
2427 goto error;
2428 pow = optional_power(s);
2429 pwqp = isl_pw_qpolynomial_pow(pwqp, pow);
2430 } else if (tok->type == ISL_TOKEN_VALUE) {
2431 struct isl_token *tok2;
2432 isl_qpolynomial *qp;
2434 tok2 = isl_stream_next_token(s);
2435 if (tok2 && tok2->type == '/') {
2436 isl_token_free(tok2);
2437 tok2 = next_token(s);
2438 if (!tok2 || tok2->type != ISL_TOKEN_VALUE) {
2439 isl_stream_error(s, tok2, "expected denominator");
2440 isl_token_free(tok);
2441 isl_token_free(tok2);
2442 return NULL;
2444 qp = isl_qpolynomial_rat_cst_on_domain(isl_map_get_space(map),
2445 tok->u.v, tok2->u.v);
2446 isl_token_free(tok2);
2447 } else {
2448 isl_stream_push_token(s, tok2);
2449 qp = isl_qpolynomial_cst_on_domain(isl_map_get_space(map),
2450 tok->u.v);
2452 isl_token_free(tok);
2453 pwqp = isl_pw_qpolynomial_from_qpolynomial(qp);
2454 } else if (tok->type == ISL_TOKEN_INFTY) {
2455 isl_qpolynomial *qp;
2456 isl_token_free(tok);
2457 qp = isl_qpolynomial_infty_on_domain(isl_map_get_space(map));
2458 pwqp = isl_pw_qpolynomial_from_qpolynomial(qp);
2459 } else if (tok->type == ISL_TOKEN_NAN) {
2460 isl_qpolynomial *qp;
2461 isl_token_free(tok);
2462 qp = isl_qpolynomial_nan_on_domain(isl_map_get_space(map));
2463 pwqp = isl_pw_qpolynomial_from_qpolynomial(qp);
2464 } else if (tok->type == ISL_TOKEN_IDENT) {
2465 int n = v->n;
2466 int pos = vars_pos(v, tok->u.s, -1);
2467 int pow;
2468 isl_qpolynomial *qp;
2469 if (pos < 0) {
2470 isl_token_free(tok);
2471 return NULL;
2473 if (pos >= n) {
2474 vars_drop(v, v->n - n);
2475 isl_stream_error(s, tok, "unknown identifier");
2476 isl_token_free(tok);
2477 return NULL;
2479 isl_token_free(tok);
2480 pow = optional_power(s);
2481 qp = isl_qpolynomial_var_pow_on_domain(isl_map_get_space(map), pos, pow);
2482 pwqp = isl_pw_qpolynomial_from_qpolynomial(qp);
2483 } else if (is_start_of_div(tok)) {
2484 isl_pw_aff *pwaff;
2485 int pow;
2487 isl_stream_push_token(s, tok);
2488 pwaff = accept_div(s, isl_map_get_space(map), v);
2489 pow = optional_power(s);
2490 pwqp = isl_pw_qpolynomial_from_pw_aff(pwaff);
2491 pwqp = isl_pw_qpolynomial_pow(pwqp, pow);
2492 } else if (tok->type == '-') {
2493 isl_token_free(tok);
2494 pwqp = read_factor(s, map, v);
2495 pwqp = isl_pw_qpolynomial_neg(pwqp);
2496 } else {
2497 isl_stream_error(s, tok, "unexpected isl_token");
2498 isl_stream_push_token(s, tok);
2499 return NULL;
2502 if (isl_stream_eat_if_available(s, '*') ||
2503 isl_stream_next_token_is(s, ISL_TOKEN_IDENT)) {
2504 isl_pw_qpolynomial *pwqp2;
2506 pwqp2 = read_factor(s, map, v);
2507 pwqp = isl_pw_qpolynomial_mul(pwqp, pwqp2);
2510 return pwqp;
2511 error:
2512 isl_pw_qpolynomial_free(pwqp);
2513 return NULL;
2516 static __isl_give isl_pw_qpolynomial *read_term(__isl_keep isl_stream *s,
2517 __isl_keep isl_map *map, struct vars *v)
2519 struct isl_token *tok;
2520 isl_pw_qpolynomial *pwqp;
2522 pwqp = read_factor(s, map, v);
2524 for (;;) {
2525 tok = next_token(s);
2526 if (!tok)
2527 return pwqp;
2529 if (tok->type == '+') {
2530 isl_pw_qpolynomial *pwqp2;
2532 isl_token_free(tok);
2533 pwqp2 = read_factor(s, map, v);
2534 pwqp = isl_pw_qpolynomial_add(pwqp, pwqp2);
2535 } else if (tok->type == '-') {
2536 isl_pw_qpolynomial *pwqp2;
2538 isl_token_free(tok);
2539 pwqp2 = read_factor(s, map, v);
2540 pwqp = isl_pw_qpolynomial_sub(pwqp, pwqp2);
2541 } else if (tok->type == ISL_TOKEN_VALUE &&
2542 isl_int_is_neg(tok->u.v)) {
2543 isl_pw_qpolynomial *pwqp2;
2545 isl_stream_push_token(s, tok);
2546 pwqp2 = read_factor(s, map, v);
2547 pwqp = isl_pw_qpolynomial_add(pwqp, pwqp2);
2548 } else {
2549 isl_stream_push_token(s, tok);
2550 break;
2554 return pwqp;
2557 static __isl_give isl_map *read_optional_formula(__isl_keep isl_stream *s,
2558 __isl_take isl_map *map, struct vars *v, int rational)
2560 struct isl_token *tok;
2562 tok = isl_stream_next_token(s);
2563 if (!tok) {
2564 isl_stream_error(s, NULL, "unexpected EOF");
2565 goto error;
2567 if (tok->type == ':' ||
2568 (tok->type == ISL_TOKEN_OR && !strcmp(tok->u.s, "|"))) {
2569 isl_token_free(tok);
2570 map = read_formula(s, v, map, rational);
2571 } else
2572 isl_stream_push_token(s, tok);
2574 return map;
2575 error:
2576 isl_map_free(map);
2577 return NULL;
2580 static struct isl_obj obj_read_poly(__isl_keep isl_stream *s,
2581 __isl_take isl_map *map, struct vars *v, int n)
2583 struct isl_obj obj = { isl_obj_pw_qpolynomial, NULL };
2584 isl_pw_qpolynomial *pwqp;
2585 struct isl_set *set;
2587 pwqp = read_term(s, map, v);
2588 map = read_optional_formula(s, map, v, 0);
2589 set = isl_map_range(map);
2591 pwqp = isl_pw_qpolynomial_intersect_domain(pwqp, set);
2593 vars_drop(v, v->n - n);
2595 obj.v = pwqp;
2596 return obj;
2599 static struct isl_obj obj_read_poly_or_fold(__isl_keep isl_stream *s,
2600 __isl_take isl_set *set, struct vars *v, int n)
2602 int min, max;
2603 struct isl_obj obj = { isl_obj_pw_qpolynomial_fold, NULL };
2604 isl_pw_qpolynomial *pwqp;
2605 isl_pw_qpolynomial_fold *pwf = NULL;
2606 enum isl_fold fold;
2608 max = isl_stream_eat_if_available(s, ISL_TOKEN_MAX);
2609 min = !max && isl_stream_eat_if_available(s, ISL_TOKEN_MIN);
2610 if (!min && !max)
2611 return obj_read_poly(s, set, v, n);
2612 fold = max ? isl_fold_max : isl_fold_min;
2614 if (isl_stream_eat(s, '('))
2615 goto error;
2617 pwqp = read_term(s, set, v);
2618 pwf = isl_pw_qpolynomial_fold_from_pw_qpolynomial(fold, pwqp);
2620 while (isl_stream_eat_if_available(s, ',')) {
2621 isl_pw_qpolynomial_fold *pwf_i;
2622 pwqp = read_term(s, set, v);
2623 pwf_i = isl_pw_qpolynomial_fold_from_pw_qpolynomial(fold, pwqp);
2624 pwf = isl_pw_qpolynomial_fold_fold(pwf, pwf_i);
2627 if (isl_stream_eat(s, ')'))
2628 goto error;
2630 set = read_optional_formula(s, set, v, 0);
2631 pwf = isl_pw_qpolynomial_fold_intersect_domain(pwf, set);
2633 vars_drop(v, v->n - n);
2635 obj.v = pwf;
2636 return obj;
2637 error:
2638 isl_set_free(set);
2639 isl_pw_qpolynomial_fold_free(pwf);
2640 obj.type = isl_obj_none;
2641 return obj;
2644 static int is_rational(__isl_keep isl_stream *s)
2646 struct isl_token *tok;
2648 tok = isl_stream_next_token(s);
2649 if (!tok)
2650 return 0;
2651 if (tok->type == ISL_TOKEN_RAT && isl_stream_next_token_is(s, ':')) {
2652 isl_token_free(tok);
2653 isl_stream_eat(s, ':');
2654 return 1;
2657 isl_stream_push_token(s, tok);
2659 return 0;
2662 static struct isl_obj obj_read_body(__isl_keep isl_stream *s,
2663 __isl_take isl_map *map, struct vars *v)
2665 struct isl_token *tok;
2666 struct isl_obj obj = { isl_obj_set, NULL };
2667 int n = v->n;
2668 int rational;
2670 rational = is_rational(s);
2671 if (rational)
2672 map = isl_map_set_rational(map);
2674 if (isl_stream_next_token_is(s, ':')) {
2675 obj.type = isl_obj_set;
2676 obj.v = read_optional_formula(s, map, v, rational);
2677 return obj;
2680 if (!next_is_tuple(s))
2681 return obj_read_poly_or_fold(s, map, v, n);
2683 map = read_map_tuple(s, map, isl_dim_in, v, rational, 0);
2684 if (!map)
2685 goto error;
2686 tok = isl_stream_next_token(s);
2687 if (!tok)
2688 goto error;
2689 if (tok->type == ISL_TOKEN_TO) {
2690 obj.type = isl_obj_map;
2691 isl_token_free(tok);
2692 if (!next_is_tuple(s)) {
2693 isl_set *set = isl_map_domain(map);
2694 return obj_read_poly_or_fold(s, set, v, n);
2696 map = read_map_tuple(s, map, isl_dim_out, v, rational, 0);
2697 if (!map)
2698 goto error;
2699 } else {
2700 map = isl_map_domain(map);
2701 isl_stream_push_token(s, tok);
2704 map = read_optional_formula(s, map, v, rational);
2706 vars_drop(v, v->n - n);
2708 obj.v = map;
2709 return obj;
2710 error:
2711 isl_map_free(map);
2712 obj.type = isl_obj_none;
2713 return obj;
2716 static struct isl_obj to_union(isl_ctx *ctx, struct isl_obj obj)
2718 if (obj.type == isl_obj_map) {
2719 obj.v = isl_union_map_from_map(obj.v);
2720 obj.type = isl_obj_union_map;
2721 } else if (obj.type == isl_obj_set) {
2722 obj.v = isl_union_set_from_set(obj.v);
2723 obj.type = isl_obj_union_set;
2724 } else if (obj.type == isl_obj_pw_qpolynomial) {
2725 obj.v = isl_union_pw_qpolynomial_from_pw_qpolynomial(obj.v);
2726 obj.type = isl_obj_union_pw_qpolynomial;
2727 } else if (obj.type == isl_obj_pw_qpolynomial_fold) {
2728 obj.v = isl_union_pw_qpolynomial_fold_from_pw_qpolynomial_fold(obj.v);
2729 obj.type = isl_obj_union_pw_qpolynomial_fold;
2730 } else
2731 isl_assert(ctx, 0, goto error);
2732 return obj;
2733 error:
2734 obj.type->free(obj.v);
2735 obj.type = isl_obj_none;
2736 return obj;
2739 static struct isl_obj obj_add(__isl_keep isl_stream *s,
2740 struct isl_obj obj1, struct isl_obj obj2)
2742 if (obj2.type == isl_obj_none || !obj2.v)
2743 goto error;
2744 if (obj1.type == isl_obj_set && obj2.type == isl_obj_union_set)
2745 obj1 = to_union(s->ctx, obj1);
2746 if (obj1.type == isl_obj_union_set && obj2.type == isl_obj_set)
2747 obj2 = to_union(s->ctx, obj2);
2748 if (obj1.type == isl_obj_map && obj2.type == isl_obj_union_map)
2749 obj1 = to_union(s->ctx, obj1);
2750 if (obj1.type == isl_obj_union_map && obj2.type == isl_obj_map)
2751 obj2 = to_union(s->ctx, obj2);
2752 if (obj1.type == isl_obj_pw_qpolynomial &&
2753 obj2.type == isl_obj_union_pw_qpolynomial)
2754 obj1 = to_union(s->ctx, obj1);
2755 if (obj1.type == isl_obj_union_pw_qpolynomial &&
2756 obj2.type == isl_obj_pw_qpolynomial)
2757 obj2 = to_union(s->ctx, obj2);
2758 if (obj1.type == isl_obj_pw_qpolynomial_fold &&
2759 obj2.type == isl_obj_union_pw_qpolynomial_fold)
2760 obj1 = to_union(s->ctx, obj1);
2761 if (obj1.type == isl_obj_union_pw_qpolynomial_fold &&
2762 obj2.type == isl_obj_pw_qpolynomial_fold)
2763 obj2 = to_union(s->ctx, obj2);
2764 if (obj1.type != obj2.type) {
2765 isl_stream_error(s, NULL,
2766 "attempt to combine incompatible objects");
2767 goto error;
2769 if (!obj1.type->add)
2770 isl_die(s->ctx, isl_error_internal,
2771 "combination not supported on object type", goto error);
2772 if (obj1.type == isl_obj_map && !isl_map_has_equal_space(obj1.v, obj2.v)) {
2773 obj1 = to_union(s->ctx, obj1);
2774 obj2 = to_union(s->ctx, obj2);
2776 if (obj1.type == isl_obj_set && !isl_set_has_equal_space(obj1.v, obj2.v)) {
2777 obj1 = to_union(s->ctx, obj1);
2778 obj2 = to_union(s->ctx, obj2);
2780 if (obj1.type == isl_obj_pw_qpolynomial &&
2781 !isl_pw_qpolynomial_has_equal_space(obj1.v, obj2.v)) {
2782 obj1 = to_union(s->ctx, obj1);
2783 obj2 = to_union(s->ctx, obj2);
2785 if (obj1.type == isl_obj_pw_qpolynomial_fold &&
2786 !isl_pw_qpolynomial_fold_has_equal_space(obj1.v, obj2.v)) {
2787 obj1 = to_union(s->ctx, obj1);
2788 obj2 = to_union(s->ctx, obj2);
2790 obj1.v = obj1.type->add(obj1.v, obj2.v);
2791 return obj1;
2792 error:
2793 obj1.type->free(obj1.v);
2794 obj2.type->free(obj2.v);
2795 obj1.type = isl_obj_none;
2796 obj1.v = NULL;
2797 return obj1;
2800 /* Are the first two tokens on "s", "domain" (either as a string
2801 * or as an identifier) followed by ":"?
2803 static int next_is_domain_colon(__isl_keep isl_stream *s)
2805 struct isl_token *tok;
2806 char *name;
2807 int res;
2809 tok = isl_stream_next_token(s);
2810 if (!tok)
2811 return 0;
2812 if (tok->type != ISL_TOKEN_IDENT && tok->type != ISL_TOKEN_STRING) {
2813 isl_stream_push_token(s, tok);
2814 return 0;
2817 name = isl_token_get_str(s->ctx, tok);
2818 res = !strcmp(name, "domain") && isl_stream_next_token_is(s, ':');
2819 free(name);
2821 isl_stream_push_token(s, tok);
2823 return res;
2826 /* Do the first tokens on "s" look like a schedule?
2828 * The root of a schedule is always a domain node, so the first thing
2829 * we expect in the stream is a domain key, i.e., "domain" followed
2830 * by ":". If the schedule was printed in YAML flow style, then
2831 * we additionally expect a "{" to open the outer mapping.
2833 static int next_is_schedule(__isl_keep isl_stream *s)
2835 struct isl_token *tok;
2836 int is_schedule;
2838 tok = isl_stream_next_token(s);
2839 if (!tok)
2840 return 0;
2841 if (tok->type != '{') {
2842 isl_stream_push_token(s, tok);
2843 return next_is_domain_colon(s);
2846 is_schedule = next_is_domain_colon(s);
2847 isl_stream_push_token(s, tok);
2849 return is_schedule;
2852 /* Read an isl_schedule from "s" and store it in an isl_obj.
2854 static struct isl_obj schedule_read(__isl_keep isl_stream *s)
2856 struct isl_obj obj;
2858 obj.type = isl_obj_schedule;
2859 obj.v = isl_stream_read_schedule(s);
2861 return obj;
2864 /* Read a disjunction of object bodies from "s".
2865 * That is, read the inside of the braces, but not the braces themselves.
2866 * "v" contains a description of the identifiers parsed so far.
2867 * "map" contains information about the parameters.
2869 static struct isl_obj obj_read_disjuncts(__isl_keep isl_stream *s,
2870 struct vars *v, __isl_keep isl_map *map)
2872 struct isl_obj obj = { isl_obj_set, NULL };
2874 if (isl_stream_next_token_is(s, '}')) {
2875 obj.type = isl_obj_union_set;
2876 obj.v = isl_union_set_empty(isl_map_get_space(map));
2877 return obj;
2880 for (;;) {
2881 struct isl_obj o;
2882 o = obj_read_body(s, isl_map_copy(map), v);
2883 if (!obj.v)
2884 obj = o;
2885 else
2886 obj = obj_add(s, obj, o);
2887 if (obj.type == isl_obj_none || !obj.v)
2888 return obj;
2889 if (!isl_stream_eat_if_available(s, ';'))
2890 break;
2891 if (isl_stream_next_token_is(s, '}'))
2892 break;
2895 return obj;
2898 static struct isl_obj obj_read(__isl_keep isl_stream *s)
2900 isl_map *map = NULL;
2901 struct isl_token *tok;
2902 struct vars *v = NULL;
2903 struct isl_obj obj = { isl_obj_set, NULL };
2905 if (next_is_schedule(s))
2906 return schedule_read(s);
2908 tok = next_token(s);
2909 if (!tok) {
2910 isl_stream_error(s, NULL, "unexpected EOF");
2911 goto error;
2913 if (tok->type == ISL_TOKEN_VALUE) {
2914 struct isl_token *tok2;
2915 struct isl_map *map;
2917 tok2 = isl_stream_next_token(s);
2918 if (!tok2 || tok2->type != ISL_TOKEN_VALUE ||
2919 isl_int_is_neg(tok2->u.v)) {
2920 if (tok2)
2921 isl_stream_push_token(s, tok2);
2922 obj.type = isl_obj_val;
2923 obj.v = isl_val_int_from_isl_int(s->ctx, tok->u.v);
2924 isl_token_free(tok);
2925 return obj;
2927 isl_stream_push_token(s, tok2);
2928 isl_stream_push_token(s, tok);
2929 map = map_read_polylib(s);
2930 if (!map)
2931 goto error;
2932 if (isl_map_may_be_set(map))
2933 obj.v = isl_map_range(map);
2934 else {
2935 obj.type = isl_obj_map;
2936 obj.v = map;
2938 return obj;
2940 v = vars_new(s->ctx);
2941 if (!v) {
2942 isl_stream_push_token(s, tok);
2943 goto error;
2945 map = isl_map_universe(isl_space_params_alloc(s->ctx, 0));
2946 if (tok->type == '[') {
2947 isl_stream_push_token(s, tok);
2948 map = read_map_tuple(s, map, isl_dim_param, v, 0, 0);
2949 if (!map)
2950 goto error;
2951 tok = isl_stream_next_token(s);
2952 if (!tok || tok->type != ISL_TOKEN_TO) {
2953 isl_stream_error(s, tok, "expecting '->'");
2954 if (tok)
2955 isl_stream_push_token(s, tok);
2956 goto error;
2958 isl_token_free(tok);
2959 tok = isl_stream_next_token(s);
2961 if (!tok || tok->type != '{') {
2962 isl_stream_error(s, tok, "expecting '{'");
2963 if (tok)
2964 isl_stream_push_token(s, tok);
2965 goto error;
2967 isl_token_free(tok);
2969 tok = isl_stream_next_token(s);
2970 if (!tok)
2972 else if (tok->type == ISL_TOKEN_IDENT && !strcmp(tok->u.s, "Sym")) {
2973 isl_token_free(tok);
2974 if (isl_stream_eat(s, '='))
2975 goto error;
2976 map = read_map_tuple(s, map, isl_dim_param, v, 0, 1);
2977 if (!map)
2978 goto error;
2979 } else
2980 isl_stream_push_token(s, tok);
2982 obj = obj_read_disjuncts(s, v, map);
2983 if (obj.type == isl_obj_none || !obj.v)
2984 goto error;
2986 tok = isl_stream_next_token(s);
2987 if (tok && tok->type == '}') {
2988 isl_token_free(tok);
2989 } else {
2990 isl_stream_error(s, tok, "unexpected isl_token");
2991 if (tok)
2992 isl_token_free(tok);
2993 goto error;
2996 vars_free(v);
2997 isl_map_free(map);
2999 return obj;
3000 error:
3001 isl_map_free(map);
3002 obj.type->free(obj.v);
3003 if (v)
3004 vars_free(v);
3005 obj.v = NULL;
3006 return obj;
3009 struct isl_obj isl_stream_read_obj(__isl_keep isl_stream *s)
3011 return obj_read(s);
3014 __isl_give isl_map *isl_stream_read_map(__isl_keep isl_stream *s)
3016 struct isl_obj obj;
3018 obj = obj_read(s);
3019 if (obj.v)
3020 isl_assert(s->ctx, obj.type == isl_obj_map ||
3021 obj.type == isl_obj_set, goto error);
3023 if (obj.type == isl_obj_set)
3024 obj.v = isl_map_from_range(obj.v);
3026 return obj.v;
3027 error:
3028 obj.type->free(obj.v);
3029 return NULL;
3032 __isl_give isl_set *isl_stream_read_set(__isl_keep isl_stream *s)
3034 struct isl_obj obj;
3036 obj = obj_read(s);
3037 if (obj.v) {
3038 if (obj.type == isl_obj_map && isl_map_may_be_set(obj.v)) {
3039 obj.v = isl_map_range(obj.v);
3040 obj.type = isl_obj_set;
3042 isl_assert(s->ctx, obj.type == isl_obj_set, goto error);
3045 return obj.v;
3046 error:
3047 obj.type->free(obj.v);
3048 return NULL;
3051 __isl_give isl_union_map *isl_stream_read_union_map(__isl_keep isl_stream *s)
3053 struct isl_obj obj;
3055 obj = obj_read(s);
3056 if (obj.type == isl_obj_map) {
3057 obj.type = isl_obj_union_map;
3058 obj.v = isl_union_map_from_map(obj.v);
3060 if (obj.type == isl_obj_set) {
3061 obj.type = isl_obj_union_set;
3062 obj.v = isl_union_set_from_set(obj.v);
3064 if (obj.v && obj.type == isl_obj_union_set &&
3065 isl_union_set_is_empty(obj.v))
3066 obj.type = isl_obj_union_map;
3067 if (obj.v && obj.type != isl_obj_union_map)
3068 isl_die(s->ctx, isl_error_invalid, "invalid input", goto error);
3070 return obj.v;
3071 error:
3072 obj.type->free(obj.v);
3073 return NULL;
3076 /* Extract an isl_union_set from "obj".
3077 * This only works if the object was detected as either a set
3078 * (in which case it is converted to a union set) or a union set.
3080 static __isl_give isl_union_set *extract_union_set(isl_ctx *ctx,
3081 struct isl_obj obj)
3083 if (obj.type == isl_obj_set) {
3084 obj.type = isl_obj_union_set;
3085 obj.v = isl_union_set_from_set(obj.v);
3087 if (obj.v)
3088 isl_assert(ctx, obj.type == isl_obj_union_set, goto error);
3090 return obj.v;
3091 error:
3092 obj.type->free(obj.v);
3093 return NULL;
3096 /* Read an isl_union_set from "s".
3097 * First read a generic object and then try and extract
3098 * an isl_union_set from that.
3100 __isl_give isl_union_set *isl_stream_read_union_set(__isl_keep isl_stream *s)
3102 struct isl_obj obj;
3104 obj = obj_read(s);
3105 return extract_union_set(s->ctx, obj);
3108 static __isl_give isl_basic_map *basic_map_read(__isl_keep isl_stream *s)
3110 struct isl_obj obj;
3111 struct isl_map *map;
3112 struct isl_basic_map *bmap;
3114 obj = obj_read(s);
3115 if (obj.v && (obj.type != isl_obj_map && obj.type != isl_obj_set))
3116 isl_die(s->ctx, isl_error_invalid, "not a (basic) set or map",
3117 goto error);
3118 map = obj.v;
3119 if (!map)
3120 return NULL;
3122 if (map->n > 1)
3123 isl_die(s->ctx, isl_error_invalid,
3124 "set or map description involves "
3125 "more than one disjunct", goto error);
3127 if (map->n == 0)
3128 bmap = isl_basic_map_empty(isl_map_get_space(map));
3129 else
3130 bmap = isl_basic_map_copy(map->p[0]);
3132 isl_map_free(map);
3134 return bmap;
3135 error:
3136 obj.type->free(obj.v);
3137 return NULL;
3140 static __isl_give isl_basic_set *basic_set_read(__isl_keep isl_stream *s)
3142 isl_basic_map *bmap;
3143 bmap = basic_map_read(s);
3144 if (!bmap)
3145 return NULL;
3146 if (!isl_basic_map_may_be_set(bmap))
3147 isl_die(s->ctx, isl_error_invalid,
3148 "input is not a set", goto error);
3149 return isl_basic_map_range(bmap);
3150 error:
3151 isl_basic_map_free(bmap);
3152 return NULL;
3155 __isl_give isl_basic_map *isl_basic_map_read_from_file(isl_ctx *ctx,
3156 FILE *input)
3158 struct isl_basic_map *bmap;
3159 isl_stream *s = isl_stream_new_file(ctx, input);
3160 if (!s)
3161 return NULL;
3162 bmap = basic_map_read(s);
3163 isl_stream_free(s);
3164 return bmap;
3167 __isl_give isl_basic_set *isl_basic_set_read_from_file(isl_ctx *ctx,
3168 FILE *input)
3170 isl_basic_set *bset;
3171 isl_stream *s = isl_stream_new_file(ctx, input);
3172 if (!s)
3173 return NULL;
3174 bset = basic_set_read(s);
3175 isl_stream_free(s);
3176 return bset;
3179 __isl_give isl_basic_map *isl_basic_map_read_from_str(isl_ctx *ctx,
3180 const char *str)
3182 struct isl_basic_map *bmap;
3183 isl_stream *s = isl_stream_new_str(ctx, str);
3184 if (!s)
3185 return NULL;
3186 bmap = basic_map_read(s);
3187 isl_stream_free(s);
3188 return bmap;
3191 __isl_give isl_basic_set *isl_basic_set_read_from_str(isl_ctx *ctx,
3192 const char *str)
3194 isl_basic_set *bset;
3195 isl_stream *s = isl_stream_new_str(ctx, str);
3196 if (!s)
3197 return NULL;
3198 bset = basic_set_read(s);
3199 isl_stream_free(s);
3200 return bset;
3203 __isl_give isl_map *isl_map_read_from_file(struct isl_ctx *ctx,
3204 FILE *input)
3206 struct isl_map *map;
3207 isl_stream *s = isl_stream_new_file(ctx, input);
3208 if (!s)
3209 return NULL;
3210 map = isl_stream_read_map(s);
3211 isl_stream_free(s);
3212 return map;
3215 __isl_give isl_map *isl_map_read_from_str(struct isl_ctx *ctx,
3216 const char *str)
3218 struct isl_map *map;
3219 isl_stream *s = isl_stream_new_str(ctx, str);
3220 if (!s)
3221 return NULL;
3222 map = isl_stream_read_map(s);
3223 isl_stream_free(s);
3224 return map;
3227 __isl_give isl_set *isl_set_read_from_file(struct isl_ctx *ctx,
3228 FILE *input)
3230 isl_set *set;
3231 isl_stream *s = isl_stream_new_file(ctx, input);
3232 if (!s)
3233 return NULL;
3234 set = isl_stream_read_set(s);
3235 isl_stream_free(s);
3236 return set;
3239 __isl_give isl_set *isl_set_read_from_str(isl_ctx *ctx, const char *str)
3241 isl_set *set;
3242 isl_stream *s = isl_stream_new_str(ctx, str);
3243 if (!s)
3244 return NULL;
3245 set = isl_stream_read_set(s);
3246 isl_stream_free(s);
3247 return set;
3250 __isl_give isl_union_map *isl_union_map_read_from_file(isl_ctx *ctx,
3251 FILE *input)
3253 isl_union_map *umap;
3254 isl_stream *s = isl_stream_new_file(ctx, input);
3255 if (!s)
3256 return NULL;
3257 umap = isl_stream_read_union_map(s);
3258 isl_stream_free(s);
3259 return umap;
3262 __isl_give isl_union_map *isl_union_map_read_from_str(struct isl_ctx *ctx,
3263 const char *str)
3265 isl_union_map *umap;
3266 isl_stream *s = isl_stream_new_str(ctx, str);
3267 if (!s)
3268 return NULL;
3269 umap = isl_stream_read_union_map(s);
3270 isl_stream_free(s);
3271 return umap;
3274 __isl_give isl_union_set *isl_union_set_read_from_file(isl_ctx *ctx,
3275 FILE *input)
3277 isl_union_set *uset;
3278 isl_stream *s = isl_stream_new_file(ctx, input);
3279 if (!s)
3280 return NULL;
3281 uset = isl_stream_read_union_set(s);
3282 isl_stream_free(s);
3283 return uset;
3286 __isl_give isl_union_set *isl_union_set_read_from_str(struct isl_ctx *ctx,
3287 const char *str)
3289 isl_union_set *uset;
3290 isl_stream *s = isl_stream_new_str(ctx, str);
3291 if (!s)
3292 return NULL;
3293 uset = isl_stream_read_union_set(s);
3294 isl_stream_free(s);
3295 return uset;
3298 static __isl_give isl_vec *isl_vec_read_polylib(__isl_keep isl_stream *s)
3300 struct isl_vec *vec = NULL;
3301 struct isl_token *tok;
3302 unsigned size;
3303 int j;
3305 tok = isl_stream_next_token(s);
3306 if (!tok || tok->type != ISL_TOKEN_VALUE) {
3307 isl_stream_error(s, tok, "expecting vector length");
3308 goto error;
3311 size = isl_int_get_si(tok->u.v);
3312 isl_token_free(tok);
3314 vec = isl_vec_alloc(s->ctx, size);
3316 for (j = 0; j < size; ++j) {
3317 tok = isl_stream_next_token(s);
3318 if (!tok || tok->type != ISL_TOKEN_VALUE) {
3319 isl_stream_error(s, tok, "expecting constant value");
3320 goto error;
3322 isl_int_set(vec->el[j], tok->u.v);
3323 isl_token_free(tok);
3326 return vec;
3327 error:
3328 isl_token_free(tok);
3329 isl_vec_free(vec);
3330 return NULL;
3333 static __isl_give isl_vec *vec_read(__isl_keep isl_stream *s)
3335 return isl_vec_read_polylib(s);
3338 __isl_give isl_vec *isl_vec_read_from_file(isl_ctx *ctx, FILE *input)
3340 isl_vec *v;
3341 isl_stream *s = isl_stream_new_file(ctx, input);
3342 if (!s)
3343 return NULL;
3344 v = vec_read(s);
3345 isl_stream_free(s);
3346 return v;
3349 __isl_give isl_pw_qpolynomial *isl_stream_read_pw_qpolynomial(
3350 __isl_keep isl_stream *s)
3352 struct isl_obj obj;
3354 obj = obj_read(s);
3355 if (obj.v)
3356 isl_assert(s->ctx, obj.type == isl_obj_pw_qpolynomial,
3357 goto error);
3359 return obj.v;
3360 error:
3361 obj.type->free(obj.v);
3362 return NULL;
3365 __isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_read_from_str(isl_ctx *ctx,
3366 const char *str)
3368 isl_pw_qpolynomial *pwqp;
3369 isl_stream *s = isl_stream_new_str(ctx, str);
3370 if (!s)
3371 return NULL;
3372 pwqp = isl_stream_read_pw_qpolynomial(s);
3373 isl_stream_free(s);
3374 return pwqp;
3377 __isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_read_from_file(isl_ctx *ctx,
3378 FILE *input)
3380 isl_pw_qpolynomial *pwqp;
3381 isl_stream *s = isl_stream_new_file(ctx, input);
3382 if (!s)
3383 return NULL;
3384 pwqp = isl_stream_read_pw_qpolynomial(s);
3385 isl_stream_free(s);
3386 return pwqp;
3389 /* Read an isl_pw_qpolynomial_fold from "s".
3390 * First read a generic object and
3391 * then check that it is an isl_pw_qpolynomial_fold.
3393 __isl_give isl_pw_qpolynomial_fold *isl_stream_read_pw_qpolynomial_fold(
3394 __isl_keep isl_stream *s)
3396 struct isl_obj obj;
3398 obj = obj_read(s);
3399 if (obj.v && obj.type != isl_obj_pw_qpolynomial_fold)
3400 isl_die(s->ctx, isl_error_invalid, "invalid input", goto error);
3402 return obj.v;
3403 error:
3404 obj.type->free(obj.v);
3405 return NULL;
3408 /* Read an isl_pw_qpolynomial_fold from "str".
3410 __isl_give isl_pw_qpolynomial_fold *isl_pw_qpolynomial_fold_read_from_str(
3411 isl_ctx *ctx, const char *str)
3413 isl_pw_qpolynomial_fold *pwqp;
3414 isl_stream *s;
3416 s = isl_stream_new_str(ctx, str);
3417 if (!s)
3418 return NULL;
3419 pwqp = isl_stream_read_pw_qpolynomial_fold(s);
3420 isl_stream_free(s);
3422 return pwqp;
3425 /* Is the next token an identifier not in "v"?
3427 static int next_is_fresh_ident(__isl_keep isl_stream *s, struct vars *v)
3429 int n = v->n;
3430 int fresh;
3431 struct isl_token *tok;
3433 tok = isl_stream_next_token(s);
3434 if (!tok)
3435 return 0;
3436 fresh = tok->type == ISL_TOKEN_IDENT && vars_pos(v, tok->u.s, -1) >= n;
3437 isl_stream_push_token(s, tok);
3439 vars_drop(v, v->n - n);
3441 return fresh;
3444 /* First read the domain of the affine expression, which may be
3445 * a parameter space or a set.
3446 * The tricky part is that we don't know if the domain is a set or not,
3447 * so when we are trying to read the domain, we may actually be reading
3448 * the affine expression itself (defined on a parameter domains)
3449 * If the tuple we are reading is named, we assume it's the domain.
3450 * Also, if inside the tuple, the first thing we find is a nested tuple
3451 * or a new identifier, we again assume it's the domain.
3452 * Finally, if the tuple is empty, then it must be the domain
3453 * since it does not contain an affine expression.
3454 * Otherwise, we assume we are reading an affine expression.
3456 static __isl_give isl_set *read_aff_domain(__isl_keep isl_stream *s,
3457 __isl_take isl_set *dom, struct vars *v)
3459 struct isl_token *tok, *tok2;
3460 int is_empty;
3462 tok = isl_stream_next_token(s);
3463 if (tok && (tok->type == ISL_TOKEN_IDENT || tok->is_keyword)) {
3464 isl_stream_push_token(s, tok);
3465 return read_map_tuple(s, dom, isl_dim_set, v, 0, 0);
3467 if (!tok || tok->type != '[') {
3468 isl_stream_error(s, tok, "expecting '['");
3469 goto error;
3471 tok2 = isl_stream_next_token(s);
3472 is_empty = tok2 && tok2->type == ']';
3473 if (tok2)
3474 isl_stream_push_token(s, tok2);
3475 if (is_empty || next_is_tuple(s) || next_is_fresh_ident(s, v)) {
3476 isl_stream_push_token(s, tok);
3477 dom = read_map_tuple(s, dom, isl_dim_set, v, 0, 0);
3478 } else
3479 isl_stream_push_token(s, tok);
3481 return dom;
3482 error:
3483 if (tok)
3484 isl_stream_push_token(s, tok);
3485 isl_set_free(dom);
3486 return NULL;
3489 /* Read an affine expression from "s".
3491 __isl_give isl_aff *isl_stream_read_aff(__isl_keep isl_stream *s)
3493 isl_aff *aff;
3494 isl_multi_aff *ma;
3495 isl_size dim;
3497 ma = isl_stream_read_multi_aff(s);
3498 dim = isl_multi_aff_dim(ma, isl_dim_out);
3499 if (dim < 0)
3500 goto error;
3501 if (dim != 1)
3502 isl_die(s->ctx, isl_error_invalid,
3503 "expecting single affine expression",
3504 goto error);
3506 aff = isl_multi_aff_get_aff(ma, 0);
3507 isl_multi_aff_free(ma);
3508 return aff;
3509 error:
3510 isl_multi_aff_free(ma);
3511 return NULL;
3514 /* Read a piecewise affine expression from "s" with domain (space) "dom".
3516 static __isl_give isl_pw_aff *read_pw_aff_with_dom(__isl_keep isl_stream *s,
3517 __isl_take isl_set *dom, struct vars *v)
3519 isl_pw_aff *pwaff = NULL;
3521 if (!isl_set_is_params(dom) && isl_stream_eat(s, ISL_TOKEN_TO))
3522 goto error;
3524 if (isl_stream_eat(s, '['))
3525 goto error;
3527 pwaff = accept_affine(s, isl_set_get_space(dom), v);
3529 if (isl_stream_eat(s, ']'))
3530 goto error;
3532 dom = read_optional_formula(s, dom, v, 0);
3533 pwaff = isl_pw_aff_intersect_domain(pwaff, dom);
3535 return pwaff;
3536 error:
3537 isl_set_free(dom);
3538 isl_pw_aff_free(pwaff);
3539 return NULL;
3542 __isl_give isl_pw_aff *isl_stream_read_pw_aff(__isl_keep isl_stream *s)
3544 struct vars *v;
3545 isl_set *dom = NULL;
3546 isl_set *aff_dom;
3547 isl_pw_aff *pa = NULL;
3548 int n;
3550 v = vars_new(s->ctx);
3551 if (!v)
3552 return NULL;
3554 dom = isl_set_universe(isl_space_params_alloc(s->ctx, 0));
3555 if (next_is_tuple(s)) {
3556 dom = read_map_tuple(s, dom, isl_dim_param, v, 1, 0);
3557 if (isl_stream_eat(s, ISL_TOKEN_TO))
3558 goto error;
3560 if (isl_stream_eat(s, '{'))
3561 goto error;
3563 n = v->n;
3564 aff_dom = read_aff_domain(s, isl_set_copy(dom), v);
3565 pa = read_pw_aff_with_dom(s, aff_dom, v);
3566 vars_drop(v, v->n - n);
3568 while (isl_stream_eat_if_available(s, ';')) {
3569 isl_pw_aff *pa_i;
3571 n = v->n;
3572 aff_dom = read_aff_domain(s, isl_set_copy(dom), v);
3573 pa_i = read_pw_aff_with_dom(s, aff_dom, v);
3574 vars_drop(v, v->n - n);
3576 pa = isl_pw_aff_union_add(pa, pa_i);
3579 if (isl_stream_eat(s, '}'))
3580 goto error;
3582 vars_free(v);
3583 isl_set_free(dom);
3584 return pa;
3585 error:
3586 vars_free(v);
3587 isl_set_free(dom);
3588 isl_pw_aff_free(pa);
3589 return NULL;
3592 __isl_give isl_aff *isl_aff_read_from_str(isl_ctx *ctx, const char *str)
3594 isl_aff *aff;
3595 isl_stream *s = isl_stream_new_str(ctx, str);
3596 if (!s)
3597 return NULL;
3598 aff = isl_stream_read_aff(s);
3599 isl_stream_free(s);
3600 return aff;
3603 __isl_give isl_pw_aff *isl_pw_aff_read_from_str(isl_ctx *ctx, const char *str)
3605 isl_pw_aff *pa;
3606 isl_stream *s = isl_stream_new_str(ctx, str);
3607 if (!s)
3608 return NULL;
3609 pa = isl_stream_read_pw_aff(s);
3610 isl_stream_free(s);
3611 return pa;
3614 /* Extract an isl_multi_pw_aff with domain space "dom_space"
3615 * from a tuple "tuple" read by read_tuple.
3617 * Note that the function read_tuple accepts tuples where some output or
3618 * set dimensions are defined in terms of other output or set dimensions
3619 * since this function is also used to read maps. As a special case,
3620 * read_tuple also accept dimensions that are defined in terms of themselves
3621 * (i.e., that are not defined).
3622 * These cases are not allowed when extracting an isl_multi_pw_aff so check
3623 * that the definitions of the output/set dimensions do not involve any
3624 * output/set dimensions.
3625 * Finally, drop the output dimensions from the domain of the result
3626 * of read_tuple (which is of the form [input, output] -> [output],
3627 * with anonymous domain) and reset the space.
3629 static __isl_give isl_multi_pw_aff *extract_mpa_from_tuple(
3630 __isl_take isl_space *dom_space, __isl_keep isl_multi_pw_aff *tuple)
3632 int i;
3633 isl_size dim, n;
3634 isl_space *space;
3635 isl_multi_pw_aff *mpa;
3637 n = isl_multi_pw_aff_dim(tuple, isl_dim_out);
3638 dim = isl_space_dim(dom_space, isl_dim_all);
3639 if (n < 0 || dim < 0)
3640 dom_space = isl_space_free(dom_space);
3641 space = isl_space_range(isl_multi_pw_aff_get_space(tuple));
3642 space = isl_space_align_params(space, isl_space_copy(dom_space));
3643 if (!isl_space_is_params(dom_space))
3644 space = isl_space_map_from_domain_and_range(
3645 isl_space_copy(dom_space), space);
3646 isl_space_free(dom_space);
3647 mpa = isl_multi_pw_aff_alloc(space);
3649 for (i = 0; i < n; ++i) {
3650 isl_pw_aff *pa;
3651 pa = isl_multi_pw_aff_get_pw_aff(tuple, i);
3652 if (!pa)
3653 return isl_multi_pw_aff_free(mpa);
3654 if (isl_pw_aff_involves_dims(pa, isl_dim_in, dim, i + 1)) {
3655 isl_ctx *ctx = isl_pw_aff_get_ctx(pa);
3656 isl_pw_aff_free(pa);
3657 isl_die(ctx, isl_error_invalid,
3658 "not an affine expression",
3659 return isl_multi_pw_aff_free(mpa));
3661 pa = isl_pw_aff_drop_dims(pa, isl_dim_in, dim, n);
3662 space = isl_multi_pw_aff_get_domain_space(mpa);
3663 pa = isl_pw_aff_reset_domain_space(pa, space);
3664 mpa = isl_multi_pw_aff_set_pw_aff(mpa, i, pa);
3667 return mpa;
3670 /* Read a tuple of affine expressions, together with optional constraints
3671 * on the domain from "s". "dom" represents the initial constraints
3672 * on the domain.
3674 * The isl_multi_aff may live in either a set or a map space.
3675 * First read the first tuple and check if it is followed by a "->".
3676 * If so, convert the tuple into the domain of the isl_multi_pw_aff and
3677 * read in the next tuple. This tuple (or the first tuple if it was
3678 * not followed by a "->") is then converted into an isl_multi_pw_aff
3679 * through a call to extract_mpa_from_tuple.
3680 * The result is converted to an isl_pw_multi_aff and
3681 * its domain is intersected with the domain.
3683 static __isl_give isl_pw_multi_aff *read_conditional_multi_aff(
3684 __isl_keep isl_stream *s, __isl_take isl_set *dom, struct vars *v)
3686 isl_multi_pw_aff *tuple;
3687 isl_multi_pw_aff *mpa;
3688 isl_pw_multi_aff *pma;
3689 int n = v->n;
3691 tuple = read_tuple(s, v, 0, 0);
3692 if (!tuple)
3693 goto error;
3694 if (isl_stream_eat_if_available(s, ISL_TOKEN_TO)) {
3695 isl_map *map = map_from_tuple(tuple, dom, isl_dim_in, v, 0);
3696 dom = isl_map_domain(map);
3697 tuple = read_tuple(s, v, 0, 0);
3698 if (!tuple)
3699 goto error;
3701 mpa = extract_mpa_from_tuple(isl_set_get_space(dom), tuple);
3702 isl_multi_pw_aff_free(tuple);
3703 if (!mpa)
3704 dom = isl_set_free(dom);
3706 dom = read_optional_formula(s, dom, v, 0);
3708 vars_drop(v, v->n - n);
3710 pma = isl_pw_multi_aff_from_multi_pw_aff(mpa);
3711 pma = isl_pw_multi_aff_intersect_domain(pma, dom);
3713 return pma;
3714 error:
3715 isl_set_free(dom);
3716 return NULL;
3719 /* Read an isl_union_pw_multi_aff from "s".
3721 * In particular, first read the parameters and then read a sequence
3722 * of zero or more tuples of affine expressions with optional conditions and
3723 * add them up.
3725 __isl_give isl_union_pw_multi_aff *isl_stream_read_union_pw_multi_aff(
3726 __isl_keep isl_stream *s)
3728 struct vars *v;
3729 isl_set *dom;
3730 isl_union_pw_multi_aff *upma = NULL;
3732 v = vars_new(s->ctx);
3733 if (!v)
3734 return NULL;
3736 dom = isl_set_universe(isl_space_params_alloc(s->ctx, 0));
3737 if (next_is_tuple(s)) {
3738 dom = read_map_tuple(s, dom, isl_dim_param, v, 1, 0);
3739 if (isl_stream_eat(s, ISL_TOKEN_TO))
3740 goto error;
3742 if (isl_stream_eat(s, '{'))
3743 goto error;
3745 upma = isl_union_pw_multi_aff_empty(isl_set_get_space(dom));
3747 do {
3748 isl_pw_multi_aff *pma;
3749 isl_union_pw_multi_aff *upma2;
3751 if (isl_stream_next_token_is(s, '}'))
3752 break;
3754 pma = read_conditional_multi_aff(s, isl_set_copy(dom), v);
3755 upma2 = isl_union_pw_multi_aff_from_pw_multi_aff(pma);
3756 upma = isl_union_pw_multi_aff_union_add(upma, upma2);
3757 if (!upma)
3758 goto error;
3759 } while (isl_stream_eat_if_available(s, ';'));
3761 if (isl_stream_eat(s, '}'))
3762 goto error;
3764 isl_set_free(dom);
3765 vars_free(v);
3766 return upma;
3767 error:
3768 isl_union_pw_multi_aff_free(upma);
3769 isl_set_free(dom);
3770 vars_free(v);
3771 return NULL;
3774 /* Read an isl_pw_multi_aff from "s".
3776 * Read a more generic isl_union_pw_multi_aff first and
3777 * then check that the result lives in a single space.
3779 __isl_give isl_pw_multi_aff *isl_stream_read_pw_multi_aff(
3780 __isl_keep isl_stream *s)
3782 isl_bool single_space;
3783 isl_union_pw_multi_aff *upma;
3785 upma = isl_stream_read_union_pw_multi_aff(s);
3786 single_space = isl_union_pw_multi_aff_isa_pw_multi_aff(upma);
3787 if (single_space < 0)
3788 upma = isl_union_pw_multi_aff_free(upma);
3789 else if (!single_space)
3790 isl_die(s->ctx, isl_error_invalid,
3791 "expecting expression in single space",
3792 upma = isl_union_pw_multi_aff_free(upma));
3793 return isl_union_pw_multi_aff_as_pw_multi_aff(upma);
3796 __isl_give isl_pw_multi_aff *isl_pw_multi_aff_read_from_str(isl_ctx *ctx,
3797 const char *str)
3799 isl_pw_multi_aff *pma;
3800 isl_stream *s = isl_stream_new_str(ctx, str);
3801 if (!s)
3802 return NULL;
3803 pma = isl_stream_read_pw_multi_aff(s);
3804 isl_stream_free(s);
3805 return pma;
3808 /* Read an isl_union_pw_multi_aff from "str".
3810 __isl_give isl_union_pw_multi_aff *isl_union_pw_multi_aff_read_from_str(
3811 isl_ctx *ctx, const char *str)
3813 isl_union_pw_multi_aff *upma;
3814 isl_stream *s = isl_stream_new_str(ctx, str);
3815 if (!s)
3816 return NULL;
3817 upma = isl_stream_read_union_pw_multi_aff(s);
3818 isl_stream_free(s);
3819 return upma;
3822 /* Assuming "pa" represents a single affine expression defined on a universe
3823 * domain, extract this affine expression.
3825 static __isl_give isl_aff *aff_from_pw_aff(__isl_take isl_pw_aff *pa)
3827 isl_aff *aff;
3829 if (!pa)
3830 return NULL;
3831 if (pa->n != 1)
3832 isl_die(isl_pw_aff_get_ctx(pa), isl_error_invalid,
3833 "expecting single affine expression",
3834 goto error);
3835 if (!isl_set_plain_is_universe(pa->p[0].set))
3836 isl_die(isl_pw_aff_get_ctx(pa), isl_error_invalid,
3837 "expecting universe domain",
3838 goto error);
3840 aff = isl_aff_copy(pa->p[0].aff);
3841 isl_pw_aff_free(pa);
3842 return aff;
3843 error:
3844 isl_pw_aff_free(pa);
3845 return NULL;
3848 #undef BASE
3849 #define BASE val
3851 #include <isl_multi_read_no_explicit_domain_templ.c>
3853 #undef BASE
3854 #define BASE id
3856 #include <isl_multi_read_no_explicit_domain_templ.c>
3858 /* Read a multi-affine expression from "s".
3859 * If the multi-affine expression has a domain, then the tuple
3860 * representing this domain cannot involve any affine expressions.
3861 * The tuple representing the actual expressions needs to consist
3862 * of only affine expressions. Moreover, these expressions can
3863 * only depend on parameters and input dimensions and not on other
3864 * output dimensions.
3866 __isl_give isl_multi_aff *isl_stream_read_multi_aff(__isl_keep isl_stream *s)
3868 struct vars *v;
3869 isl_set *dom = NULL;
3870 isl_multi_pw_aff *tuple = NULL;
3871 int i;
3872 isl_size dim, n;
3873 isl_space *space, *dom_space;
3874 isl_multi_aff *ma = NULL;
3876 v = vars_new(s->ctx);
3877 if (!v)
3878 return NULL;
3880 dom = isl_set_universe(isl_space_params_alloc(s->ctx, 0));
3881 if (next_is_tuple(s)) {
3882 dom = read_map_tuple(s, dom, isl_dim_param, v, 1, 0);
3883 if (isl_stream_eat(s, ISL_TOKEN_TO))
3884 goto error;
3886 if (!isl_set_plain_is_universe(dom))
3887 isl_die(s->ctx, isl_error_invalid,
3888 "expecting universe parameter domain", goto error);
3889 if (isl_stream_eat(s, '{'))
3890 goto error;
3892 tuple = read_tuple(s, v, 0, 0);
3893 if (!tuple)
3894 goto error;
3895 if (isl_stream_eat_if_available(s, ISL_TOKEN_TO)) {
3896 isl_set *set;
3897 isl_space *space;
3898 isl_bool has_expr;
3900 has_expr = tuple_has_expr(tuple);
3901 if (has_expr < 0)
3902 goto error;
3903 if (has_expr)
3904 isl_die(s->ctx, isl_error_invalid,
3905 "expecting universe domain", goto error);
3906 space = isl_space_range(isl_multi_pw_aff_get_space(tuple));
3907 set = isl_set_universe(space);
3908 dom = isl_set_intersect_params(set, dom);
3909 isl_multi_pw_aff_free(tuple);
3910 tuple = read_tuple(s, v, 0, 0);
3911 if (!tuple)
3912 goto error;
3915 if (isl_stream_eat(s, '}'))
3916 goto error;
3918 n = isl_multi_pw_aff_dim(tuple, isl_dim_out);
3919 dim = isl_set_dim(dom, isl_dim_all);
3920 if (n < 0 || dim < 0)
3921 goto error;
3922 dom_space = isl_set_get_space(dom);
3923 space = isl_space_range(isl_multi_pw_aff_get_space(tuple));
3924 space = isl_space_align_params(space, isl_space_copy(dom_space));
3925 if (!isl_space_is_params(dom_space))
3926 space = isl_space_map_from_domain_and_range(
3927 isl_space_copy(dom_space), space);
3928 isl_space_free(dom_space);
3929 ma = isl_multi_aff_alloc(space);
3931 for (i = 0; i < n; ++i) {
3932 isl_pw_aff *pa;
3933 isl_aff *aff;
3934 pa = isl_multi_pw_aff_get_pw_aff(tuple, i);
3935 aff = aff_from_pw_aff(pa);
3936 if (!aff)
3937 goto error;
3938 if (isl_aff_involves_dims(aff, isl_dim_in, dim, i + 1)) {
3939 isl_aff_free(aff);
3940 isl_die(s->ctx, isl_error_invalid,
3941 "not an affine expression", goto error);
3943 aff = isl_aff_drop_dims(aff, isl_dim_in, dim, n);
3944 space = isl_multi_aff_get_domain_space(ma);
3945 aff = isl_aff_reset_domain_space(aff, space);
3946 ma = isl_multi_aff_set_aff(ma, i, aff);
3949 isl_multi_pw_aff_free(tuple);
3950 vars_free(v);
3951 isl_set_free(dom);
3952 return ma;
3953 error:
3954 isl_multi_pw_aff_free(tuple);
3955 vars_free(v);
3956 isl_set_free(dom);
3957 isl_multi_aff_free(ma);
3958 return NULL;
3961 __isl_give isl_multi_aff *isl_multi_aff_read_from_str(isl_ctx *ctx,
3962 const char *str)
3964 isl_multi_aff *maff;
3965 isl_stream *s = isl_stream_new_str(ctx, str);
3966 if (!s)
3967 return NULL;
3968 maff = isl_stream_read_multi_aff(s);
3969 isl_stream_free(s);
3970 return maff;
3973 /* Read an isl_multi_pw_aff from "s".
3975 * The input format is similar to that of map, except that any conditions
3976 * on the domains should be specified inside the tuple since each
3977 * piecewise affine expression may have a different domain.
3978 * However, additional, shared conditions can also be specified.
3979 * This is especially useful for setting the explicit domain
3980 * of a zero-dimensional isl_multi_pw_aff.
3982 * Since we do not know in advance if the isl_multi_pw_aff lives
3983 * in a set or a map space, we first read the first tuple and check
3984 * if it is followed by a "->". If so, we convert the tuple into
3985 * the domain of the isl_multi_pw_aff and read in the next tuple.
3986 * This tuple (or the first tuple if it was not followed by a "->")
3987 * is then converted into the isl_multi_pw_aff through a call
3988 * to extract_mpa_from_tuple and the domain of the result
3989 * is intersected with the domain.
3991 __isl_give isl_multi_pw_aff *isl_stream_read_multi_pw_aff(
3992 __isl_keep isl_stream *s)
3994 struct vars *v;
3995 isl_set *dom = NULL;
3996 isl_multi_pw_aff *tuple = NULL;
3997 isl_multi_pw_aff *mpa = NULL;
3999 v = vars_new(s->ctx);
4000 if (!v)
4001 return NULL;
4003 dom = isl_set_universe(isl_space_params_alloc(s->ctx, 0));
4004 if (next_is_tuple(s)) {
4005 dom = read_map_tuple(s, dom, isl_dim_param, v, 1, 0);
4006 if (isl_stream_eat(s, ISL_TOKEN_TO))
4007 goto error;
4009 if (isl_stream_eat(s, '{'))
4010 goto error;
4012 tuple = read_tuple(s, v, 0, 0);
4013 if (!tuple)
4014 goto error;
4015 if (isl_stream_eat_if_available(s, ISL_TOKEN_TO)) {
4016 isl_map *map = map_from_tuple(tuple, dom, isl_dim_in, v, 0);
4017 dom = isl_map_domain(map);
4018 tuple = read_tuple(s, v, 0, 0);
4019 if (!tuple)
4020 goto error;
4023 if (isl_stream_eat_if_available(s, ':'))
4024 dom = read_formula(s, v, dom, 0);
4026 if (isl_stream_eat(s, '}'))
4027 goto error;
4029 mpa = extract_mpa_from_tuple(isl_set_get_space(dom), tuple);
4031 isl_multi_pw_aff_free(tuple);
4032 vars_free(v);
4033 mpa = isl_multi_pw_aff_intersect_domain(mpa, dom);
4034 return mpa;
4035 error:
4036 isl_multi_pw_aff_free(tuple);
4037 vars_free(v);
4038 isl_set_free(dom);
4039 isl_multi_pw_aff_free(mpa);
4040 return NULL;
4043 /* Read an isl_multi_pw_aff from "str".
4045 __isl_give isl_multi_pw_aff *isl_multi_pw_aff_read_from_str(isl_ctx *ctx,
4046 const char *str)
4048 isl_multi_pw_aff *mpa;
4049 isl_stream *s = isl_stream_new_str(ctx, str);
4050 if (!s)
4051 return NULL;
4052 mpa = isl_stream_read_multi_pw_aff(s);
4053 isl_stream_free(s);
4054 return mpa;
4057 /* Read the body of an isl_union_pw_aff from "s" with parameter domain "dom".
4059 static __isl_give isl_union_pw_aff *read_union_pw_aff_with_dom(
4060 __isl_keep isl_stream *s, __isl_take isl_set *dom, struct vars *v)
4062 isl_pw_aff *pa;
4063 isl_union_pw_aff *upa = NULL;
4064 isl_set *aff_dom;
4065 int n;
4067 n = v->n;
4068 aff_dom = read_aff_domain(s, isl_set_copy(dom), v);
4069 pa = read_pw_aff_with_dom(s, aff_dom, v);
4070 vars_drop(v, v->n - n);
4072 upa = isl_union_pw_aff_from_pw_aff(pa);
4074 while (isl_stream_eat_if_available(s, ';')) {
4075 isl_pw_aff *pa_i;
4076 isl_union_pw_aff *upa_i;
4078 n = v->n;
4079 aff_dom = read_aff_domain(s, isl_set_copy(dom), v);
4080 pa_i = read_pw_aff_with_dom(s, aff_dom, v);
4081 vars_drop(v, v->n - n);
4083 upa_i = isl_union_pw_aff_from_pw_aff(pa_i);
4084 upa = isl_union_pw_aff_union_add(upa, upa_i);
4087 isl_set_free(dom);
4088 return upa;
4091 /* Read an isl_union_pw_aff from "s".
4093 * First check if there are any paramters, then read in the opening brace
4094 * and use read_union_pw_aff_with_dom to read in the body of
4095 * the isl_union_pw_aff. Finally, read the closing brace.
4097 __isl_give isl_union_pw_aff *isl_stream_read_union_pw_aff(
4098 __isl_keep isl_stream *s)
4100 struct vars *v;
4101 isl_set *dom;
4102 isl_union_pw_aff *upa = NULL;
4104 v = vars_new(s->ctx);
4105 if (!v)
4106 return NULL;
4108 dom = isl_set_universe(isl_space_params_alloc(s->ctx, 0));
4109 if (next_is_tuple(s)) {
4110 dom = read_map_tuple(s, dom, isl_dim_param, v, 1, 0);
4111 if (isl_stream_eat(s, ISL_TOKEN_TO))
4112 goto error;
4114 if (isl_stream_eat(s, '{'))
4115 goto error;
4117 upa = read_union_pw_aff_with_dom(s, isl_set_copy(dom), v);
4119 if (isl_stream_eat(s, '}'))
4120 goto error;
4122 vars_free(v);
4123 isl_set_free(dom);
4124 return upa;
4125 error:
4126 vars_free(v);
4127 isl_set_free(dom);
4128 isl_union_pw_aff_free(upa);
4129 return NULL;
4132 /* Read an isl_union_pw_aff from "str".
4134 __isl_give isl_union_pw_aff *isl_union_pw_aff_read_from_str(isl_ctx *ctx,
4135 const char *str)
4137 isl_union_pw_aff *upa;
4138 isl_stream *s = isl_stream_new_str(ctx, str);
4139 if (!s)
4140 return NULL;
4141 upa = isl_stream_read_union_pw_aff(s);
4142 isl_stream_free(s);
4143 return upa;
4146 /* This function is called for each element in a tuple inside
4147 * isl_stream_read_multi_union_pw_aff.
4149 * Read a '{', the union piecewise affine expression body and a '}' and
4150 * add the isl_union_pw_aff to *list.
4152 static __isl_give isl_space *read_union_pw_aff_el(__isl_keep isl_stream *s,
4153 struct vars *v, __isl_take isl_space *space, int rational, void *user)
4155 isl_set *dom;
4156 isl_union_pw_aff *upa;
4157 isl_union_pw_aff_list **list = (isl_union_pw_aff_list **) user;
4159 dom = isl_set_universe(isl_space_params(isl_space_copy(space)));
4160 if (isl_stream_eat(s, '{'))
4161 goto error;
4162 upa = read_union_pw_aff_with_dom(s, dom, v);
4163 *list = isl_union_pw_aff_list_add(*list, upa);
4164 if (isl_stream_eat(s, '}'))
4165 return isl_space_free(space);
4166 if (!*list)
4167 return isl_space_free(space);
4168 return space;
4169 error:
4170 isl_set_free(dom);
4171 return isl_space_free(space);
4174 /* Do the next tokens in "s" correspond to an empty tuple?
4175 * In particular, does the stream start with a '[', followed by a ']',
4176 * not followed by a "->"?
4178 static int next_is_empty_tuple(__isl_keep isl_stream *s)
4180 struct isl_token *tok, *tok2, *tok3;
4181 int is_empty_tuple = 0;
4183 tok = isl_stream_next_token(s);
4184 if (!tok)
4185 return 0;
4186 if (tok->type != '[') {
4187 isl_stream_push_token(s, tok);
4188 return 0;
4191 tok2 = isl_stream_next_token(s);
4192 if (tok2 && tok2->type == ']') {
4193 tok3 = isl_stream_next_token(s);
4194 is_empty_tuple = !tok || tok->type != ISL_TOKEN_TO;
4195 if (tok3)
4196 isl_stream_push_token(s, tok3);
4198 if (tok2)
4199 isl_stream_push_token(s, tok2);
4200 isl_stream_push_token(s, tok);
4202 return is_empty_tuple;
4205 /* Do the next tokens in "s" correspond to a tuple of parameters?
4206 * In particular, does the stream start with a '[' that is not
4207 * followed by a '{' or a nested tuple?
4209 static int next_is_param_tuple(__isl_keep isl_stream *s)
4211 struct isl_token *tok, *tok2;
4212 int is_tuple;
4214 tok = isl_stream_next_token(s);
4215 if (!tok)
4216 return 0;
4217 if (tok->type != '[' || next_is_tuple(s)) {
4218 isl_stream_push_token(s, tok);
4219 return 0;
4222 tok2 = isl_stream_next_token(s);
4223 is_tuple = tok2 && tok2->type != '{';
4224 if (tok2)
4225 isl_stream_push_token(s, tok2);
4226 isl_stream_push_token(s, tok);
4228 return is_tuple;
4231 /* Read the core of a body of an isl_multi_union_pw_aff from "s",
4232 * i.e., everything except the parameter specification and
4233 * without shared domain constraints.
4234 * "v" contains a description of the identifiers parsed so far.
4235 * The parameters, if any, are specified by "space".
4237 * The body is of the form
4239 * [{ [..] : ... ; [..] : ... }, { [..] : ... ; [..] : ... }]
4241 * Read the tuple, collecting the individual isl_union_pw_aff
4242 * elements in a list and construct the result from the tuple space and
4243 * the list.
4245 static __isl_give isl_multi_union_pw_aff *read_multi_union_pw_aff_body_core(
4246 __isl_keep isl_stream *s, struct vars *v, __isl_take isl_space *space)
4248 isl_union_pw_aff_list *list;
4249 isl_multi_union_pw_aff *mupa;
4251 list = isl_union_pw_aff_list_alloc(s->ctx, 0);
4252 space = read_tuple_space(s, v, space, 1, 0,
4253 &read_union_pw_aff_el, &list);
4254 mupa = isl_multi_union_pw_aff_from_union_pw_aff_list(space, list);
4256 return mupa;
4259 /* Read the body of an isl_union_set from "s",
4260 * i.e., everything except the parameter specification.
4261 * "v" contains a description of the identifiers parsed so far.
4262 * The parameters, if any, are specified by "space".
4264 * First read a generic disjunction of object bodies and then try and extract
4265 * an isl_union_set from that.
4267 static __isl_give isl_union_set *read_union_set_body(__isl_keep isl_stream *s,
4268 struct vars *v, __isl_take isl_space *space)
4270 struct isl_obj obj = { isl_obj_set, NULL };
4271 isl_map *map;
4273 map = isl_set_universe(space);
4274 if (isl_stream_eat(s, '{') < 0)
4275 goto error;
4276 obj = obj_read_disjuncts(s, v, map);
4277 if (isl_stream_eat(s, '}') < 0)
4278 goto error;
4279 isl_map_free(map);
4281 return extract_union_set(s->ctx, obj);
4282 error:
4283 obj.type->free(obj.v);
4284 isl_map_free(map);
4285 return NULL;
4288 /* Read the body of an isl_multi_union_pw_aff from "s",
4289 * i.e., everything except the parameter specification.
4290 * "v" contains a description of the identifiers parsed so far.
4291 * The parameters, if any, are specified by "space".
4293 * In particular, handle the special case with shared domain constraints.
4294 * These are specified as
4296 * ([...] : ...)
4298 * and are especially useful for setting the explicit domain
4299 * of a zero-dimensional isl_multi_union_pw_aff.
4300 * The core isl_multi_union_pw_aff body ([...]) is read by
4301 * read_multi_union_pw_aff_body_core.
4303 static __isl_give isl_multi_union_pw_aff *read_multi_union_pw_aff_body(
4304 __isl_keep isl_stream *s, struct vars *v, __isl_take isl_space *space)
4306 isl_multi_union_pw_aff *mupa;
4308 if (!isl_stream_next_token_is(s, '('))
4309 return read_multi_union_pw_aff_body_core(s, v, space);
4311 if (isl_stream_eat(s, '(') < 0)
4312 goto error;
4313 mupa = read_multi_union_pw_aff_body_core(s, v, isl_space_copy(space));
4314 if (isl_stream_eat_if_available(s, ':')) {
4315 isl_union_set *dom;
4317 dom = read_union_set_body(s, v, space);
4318 mupa = isl_multi_union_pw_aff_intersect_domain(mupa, dom);
4319 } else {
4320 isl_space_free(space);
4322 if (isl_stream_eat(s, ')') < 0)
4323 return isl_multi_union_pw_aff_free(mupa);
4325 return mupa;
4326 error:
4327 isl_space_free(space);
4328 return NULL;
4331 /* Read an isl_multi_union_pw_aff from "s".
4333 * The input has the form
4335 * [{ [..] : ... ; [..] : ... }, { [..] : ... ; [..] : ... }]
4337 * or
4339 * [..] -> [{ [..] : ... ; [..] : ... }, { [..] : ... ; [..] : ... }]
4341 * Additionally, a shared domain may be specified as
4343 * ([..] : ...)
4345 * or
4347 * [..] -> ([..] : ...)
4349 * The first case is handled by the caller, the second case
4350 * is handled by read_multi_union_pw_aff_body.
4352 * We first check for the special case of an empty tuple "[]".
4353 * Then we check if there are any parameters.
4354 * Finally, read the tuple and construct the result.
4356 static __isl_give isl_multi_union_pw_aff *read_multi_union_pw_aff_core(
4357 __isl_keep isl_stream *s)
4359 struct vars *v;
4360 isl_set *dom = NULL;
4361 isl_space *space;
4362 isl_multi_union_pw_aff *mupa = NULL;
4364 if (next_is_empty_tuple(s)) {
4365 if (isl_stream_eat(s, '['))
4366 return NULL;
4367 if (isl_stream_eat(s, ']'))
4368 return NULL;
4369 space = isl_space_set_alloc(s->ctx, 0, 0);
4370 return isl_multi_union_pw_aff_zero(space);
4373 v = vars_new(s->ctx);
4374 if (!v)
4375 return NULL;
4377 dom = isl_set_universe(isl_space_params_alloc(s->ctx, 0));
4378 if (next_is_param_tuple(s)) {
4379 dom = read_map_tuple(s, dom, isl_dim_param, v, 1, 0);
4380 if (isl_stream_eat(s, ISL_TOKEN_TO))
4381 goto error;
4383 space = isl_set_get_space(dom);
4384 isl_set_free(dom);
4385 mupa = read_multi_union_pw_aff_body(s, v, space);
4387 vars_free(v);
4389 return mupa;
4390 error:
4391 vars_free(v);
4392 isl_set_free(dom);
4393 isl_multi_union_pw_aff_free(mupa);
4394 return NULL;
4397 /* Read an isl_multi_union_pw_aff from "s".
4399 * In particular, handle the special case with shared domain constraints.
4400 * These are specified as
4402 * ([...] : ...)
4404 * and are especially useful for setting the explicit domain
4405 * of a zero-dimensional isl_multi_union_pw_aff.
4406 * The core isl_multi_union_pw_aff ([...]) is read by
4407 * read_multi_union_pw_aff_core.
4409 __isl_give isl_multi_union_pw_aff *isl_stream_read_multi_union_pw_aff(
4410 __isl_keep isl_stream *s)
4412 isl_multi_union_pw_aff *mupa;
4414 if (!isl_stream_next_token_is(s, '('))
4415 return read_multi_union_pw_aff_core(s);
4417 if (isl_stream_eat(s, '(') < 0)
4418 return NULL;
4419 mupa = read_multi_union_pw_aff_core(s);
4420 if (isl_stream_eat_if_available(s, ':')) {
4421 isl_union_set *dom;
4423 dom = isl_stream_read_union_set(s);
4424 mupa = isl_multi_union_pw_aff_intersect_domain(mupa, dom);
4426 if (isl_stream_eat(s, ')') < 0)
4427 return isl_multi_union_pw_aff_free(mupa);
4428 return mupa;
4431 /* Read an isl_multi_union_pw_aff from "str".
4433 __isl_give isl_multi_union_pw_aff *isl_multi_union_pw_aff_read_from_str(
4434 isl_ctx *ctx, const char *str)
4436 isl_multi_union_pw_aff *mupa;
4437 isl_stream *s = isl_stream_new_str(ctx, str);
4438 if (!s)
4439 return NULL;
4440 mupa = isl_stream_read_multi_union_pw_aff(s);
4441 isl_stream_free(s);
4442 return mupa;
4445 __isl_give isl_union_pw_qpolynomial *isl_stream_read_union_pw_qpolynomial(
4446 __isl_keep isl_stream *s)
4448 struct isl_obj obj;
4450 obj = obj_read(s);
4451 if (obj.type == isl_obj_pw_qpolynomial) {
4452 obj.type = isl_obj_union_pw_qpolynomial;
4453 obj.v = isl_union_pw_qpolynomial_from_pw_qpolynomial(obj.v);
4455 if (obj.v)
4456 isl_assert(s->ctx, obj.type == isl_obj_union_pw_qpolynomial,
4457 goto error);
4459 return obj.v;
4460 error:
4461 obj.type->free(obj.v);
4462 return NULL;
4465 __isl_give isl_union_pw_qpolynomial *isl_union_pw_qpolynomial_read_from_str(
4466 isl_ctx *ctx, const char *str)
4468 isl_union_pw_qpolynomial *upwqp;
4469 isl_stream *s = isl_stream_new_str(ctx, str);
4470 if (!s)
4471 return NULL;
4472 upwqp = isl_stream_read_union_pw_qpolynomial(s);
4473 isl_stream_free(s);
4474 return upwqp;