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
6  *
7  * Use of this software is governed by the MIT license
8  *
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
15  */
16 
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>
35 
36 struct variable {
37 	char    	    	*name;
38 	int	     		 pos;
39 	struct variable		*next;
40 };
41 
42 struct vars {
43 	struct isl_ctx	*ctx;
44 	int		 n;
45 	struct variable	*v;
46 };
47 
vars_new(struct isl_ctx * ctx)48 static struct vars *vars_new(struct isl_ctx *ctx)
49 {
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;
58 }
59 
variable_free(struct variable * var)60 static void variable_free(struct variable *var)
61 {
62 	while (var) {
63 		struct variable *next = var->next;
64 		free(var->name);
65 		free(var);
66 		var = next;
67 	}
68 }
69 
vars_free(struct vars * v)70 static void vars_free(struct vars *v)
71 {
72 	if (!v)
73 		return;
74 	variable_free(v->v);
75 	free(v);
76 }
77 
vars_drop(struct vars * v,int n)78 static void vars_drop(struct vars *v, int n)
79 {
80 	struct variable *var;
81 
82 	if (!v || !v->v)
83 		return;
84 
85 	v->n -= n;
86 
87 	var = v->v;
88 	while (--n >= 0) {
89 		struct variable *next = var->next;
90 		free(var->name);
91 		free(var);
92 		var = next;
93 	}
94 	v->v = var;
95 }
96 
variable_new(struct vars * v,const char * name,int len,int pos)97 static struct variable *variable_new(struct vars *v, const char *name, int len,
98 				int pos)
99 {
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;
112 }
113 
vars_pos(struct vars * v,const char * s,int len)114 static int vars_pos(struct vars *v, const char *s, int len)
115 {
116 	int pos;
117 	struct variable *q;
118 
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;
124 	}
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++;
133 	}
134 	return pos;
135 }
136 
vars_add_anon(struct vars * v)137 static int vars_add_anon(struct vars *v)
138 {
139 	v->v = variable_new(v, "", 0, v->n);
140 
141 	if (!v->v)
142 		return -1;
143 	v->n++;
144 
145 	return 0;
146 }
147 
148 /* Obtain next token, with some preprocessing.
149  * In particular, evaluate expressions of the form x^y,
150  * with x and y values.
151  */
next_token(__isl_keep isl_stream * s)152 static struct isl_token *next_token(__isl_keep isl_stream *s)
153 {
154 	struct isl_token *tok, *tok2;
155 
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;
165 	}
166 
167 	isl_int_pow_ui(tok->u.v, tok->u.v, isl_int_get_ui(tok2->u.v));
168 
169 	isl_token_free(tok2);
170 	return tok;
171 error:
172 	isl_token_free(tok);
173 	isl_token_free(tok2);
174 	return NULL;
175 }
176 
177 /* Read an isl_val from "s".
178  *
179  * The following token sequences are recognized
180  *
181  *	"infty"		->	infty
182  *	"-" "infty"	->	-infty
183  *	"NaN"		->	NaN
184  *	n "/" d		->	n/d
185  *	v		->	v
186  *
187  * where n, d and v are integer constants.
188  */
isl_stream_read_val(__isl_keep isl_stream * s)189 __isl_give isl_val *isl_stream_read_val(__isl_keep isl_stream *s)
190 {
191 	struct isl_token *tok = NULL;
192 	struct isl_token *tok2 = NULL;
193 	isl_val *val;
194 
195 	tok = next_token(s);
196 	if (!tok) {
197 		isl_stream_error(s, NULL, "unexpected EOF");
198 		goto error;
199 	}
200 	if (tok->type == ISL_TOKEN_INFTY) {
201 		isl_token_free(tok);
202 		return isl_val_infty(s->ctx);
203 	}
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);
208 	}
209 	if (tok->type == ISL_TOKEN_NAN) {
210 		isl_token_free(tok);
211 		return isl_val_nan(s->ctx);
212 	}
213 	if (tok->type != ISL_TOKEN_VALUE) {
214 		isl_stream_error(s, tok, "expecting value");
215 		goto error;
216 	}
217 
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;
223 		}
224 		if (tok2->type != ISL_TOKEN_VALUE) {
225 			isl_stream_error(s, tok2, "expecting value");
226 			goto error;
227 		}
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);
232 	}
233 
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;
241 }
242 
243 /* Read an isl_val from "str".
244  */
isl_val_read_from_str(isl_ctx * ctx,const char * str)245 __isl_give isl_val *isl_val_read_from_str(isl_ctx *ctx, const char *str)
246 {
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;
254 }
255 
256 /* Perform an integer division on *f and
257  * an integer value read from the stream.
258  */
int_div_by_cst(__isl_keep isl_stream * s,isl_int * f)259 static isl_stat int_div_by_cst(__isl_keep isl_stream *s, isl_int *f)
260 {
261 	struct isl_token *tok;
262 
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;
267 	}
268 
269 	isl_int_fdiv_q(*f, *f, tok->u.v);
270 
271 	isl_token_free(tok);
272 
273 	return isl_stat_ok;
274 error:
275 	isl_token_free(tok);
276 	return isl_stat_error;
277 }
278 
accept_cst_factor(__isl_keep isl_stream * s,isl_int * f)279 static isl_stat accept_cst_factor(__isl_keep isl_stream *s, isl_int *f)
280 {
281 	struct isl_token *tok;
282 
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;
287 	}
288 
289 	isl_int_mul(*f, *f, tok->u.v);
290 
291 	isl_token_free(tok);
292 
293 	if (isl_stream_eat_if_available(s, '*'))
294 		return accept_cst_factor(s, f);
295 
296 	return isl_stat_ok;
297 error:
298 	isl_token_free(tok);
299 	return isl_stat_error;
300 }
301 
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.
305  *
306  * We introduce an integer division q = [aff/d] and the result
307  * is set to aff - d q.
308  */
affine_mod(__isl_keep isl_stream * s,struct vars * v,__isl_take isl_pw_aff * aff)309 static __isl_give isl_pw_aff *affine_mod(__isl_keep isl_stream *s,
310 	struct vars *v, __isl_take isl_pw_aff *aff)
311 {
312 	struct isl_token *tok;
313 	isl_pw_aff *q;
314 
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;
319 	}
320 
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);
325 
326 	aff = isl_pw_aff_sub(aff, q);
327 
328 	isl_token_free(tok);
329 	return aff;
330 error:
331 	isl_pw_aff_free(aff);
332 	isl_token_free(tok);
333 	return NULL;
334 }
335 
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);
340 
accept_minmax(__isl_keep isl_stream * s,__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)
343 {
344 	struct isl_token *tok;
345 	isl_pw_aff_list *list = NULL;
346 	int min;
347 
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);
353 
354 	if (isl_stream_eat(s, '('))
355 		goto error;
356 
357 	list = accept_affine_list(s, isl_space_copy(space), v);
358 	if (!list)
359 		goto error;
360 
361 	if (isl_stream_eat(s, ')'))
362 		goto error;
363 
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;
370 }
371 
372 /* Is "tok" the start of an integer division?
373  */
is_start_of_div(struct isl_token * tok)374 static int is_start_of_div(struct isl_token *tok)
375 {
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;
389 }
390 
391 /* Read an integer division from "s" and return it as an isl_pw_aff.
392  *
393  * The integer division can be of the form
394  *
395  *	[<affine expression>]
396  *	floor(<affine expression>)
397  *	ceil(<affine expression>)
398  *	floord(<affine expression>,<denominator>)
399  *	ceild(<affine expression>,<denominator>)
400  */
accept_div(__isl_keep isl_stream * s,__isl_take isl_space * space,struct vars * v)401 static __isl_give isl_pw_aff *accept_div(__isl_keep isl_stream *s,
402 	__isl_take isl_space *space, struct vars *v)
403 {
404 	struct isl_token *tok;
405 	int f = 0;
406 	int c = 0;
407 	int extra = 0;
408 	isl_pw_aff *pwaff = NULL;
409 
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;
424 	}
425 
426 	pwaff = accept_affine(s, isl_space_copy(space), v);
427 
428 	if (extra) {
429 		if (isl_stream_eat(s, ','))
430 			goto error;
431 
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;
439 		}
440 		pwaff = isl_pw_aff_scale_down(pwaff,  tok->u.v);
441 		isl_token_free(tok);
442 	}
443 
444 	if (c)
445 		pwaff = isl_pw_aff_ceil(pwaff);
446 	else
447 		pwaff = isl_pw_aff_floor(pwaff);
448 
449 	if (f || c) {
450 		if (isl_stream_eat(s, ')'))
451 			goto error;
452 	} else {
453 		if (isl_stream_eat(s, ']'))
454 			goto error;
455 	}
456 
457 	isl_space_free(space);
458 	return pwaff;
459 error:
460 	isl_space_free(space);
461 	isl_pw_aff_free(pwaff);
462 	return NULL;
463 }
464 
465 /* Divide "pa" by an integer constant read from the stream.
466  */
pw_aff_div_by_cst(__isl_keep isl_stream * s,__isl_take isl_pw_aff * pa)467 static __isl_give isl_pw_aff *pw_aff_div_by_cst(__isl_keep isl_stream *s,
468 	__isl_take isl_pw_aff *pa)
469 {
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);
477 
478 	return pa;
479 }
480 
accept_affine_factor(__isl_keep isl_stream * s,__isl_take isl_space * space,struct vars * v)481 static __isl_give isl_pw_aff *accept_affine_factor(__isl_keep isl_stream *s,
482 	__isl_take isl_space *space, struct vars *v)
483 {
484 	struct isl_token *tok = NULL;
485 	isl_pw_aff *res = NULL;
486 
487 	tok = next_token(s);
488 	if (!tok) {
489 		isl_stream_error(s, NULL, "unexpected EOF");
490 		goto error;
491 	}
492 
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;
500 
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;
507 		}
508 
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);
526 		}
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;
547 	}
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);
552 	}
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;
560 		}
561 		res = isl_pw_aff_scale(res, f);
562 		isl_int_clear(f);
563 	}
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));
568 
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;
577 }
578 
add_cst(__isl_take isl_pw_aff * pwaff,isl_int v)579 static __isl_give isl_pw_aff *add_cst(__isl_take isl_pw_aff *pwaff, isl_int v)
580 {
581 	isl_aff *aff;
582 	isl_space *space;
583 
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);
587 
588 	return isl_pw_aff_add(pwaff, isl_pw_aff_from_aff(aff));
589 }
590 
591 /* Return a piecewise affine expression defined on the specified domain
592  * that represents NaN.
593  */
nan_on_domain(__isl_keep isl_space * space)594 static __isl_give isl_pw_aff *nan_on_domain(__isl_keep isl_space *space)
595 {
596 	return isl_pw_aff_nan_on_domain_space(isl_space_copy(space));
597 }
598 
accept_affine(__isl_keep isl_stream * s,__isl_take isl_space * space,struct vars * v)599 static __isl_give isl_pw_aff *accept_affine(__isl_keep isl_stream *s,
600 	__isl_take isl_space *space, struct vars *v)
601 {
602 	struct isl_token *tok = NULL;
603 	isl_local_space *ls;
604 	isl_pw_aff *res;
605 	int sign = 1;
606 
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;
611 
612 	for (;;) {
613 		tok = next_token(s);
614 		if (!tok) {
615 			isl_stream_error(s, NULL, "unexpected EOF");
616 			goto error;
617 		}
618 		if (tok->type == '-') {
619 			sign = -sign;
620 			isl_token_free(tok);
621 			continue;
622 		}
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);
657 			}
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;
667 		}
668 		isl_token_free(tok);
669 
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;
684 		}
685 	}
686 
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;
694 }
695 
696 /* Is "type" the type of a comparison operator between lists
697  * of affine expressions?
698  */
is_list_comparator_type(int type)699 static int is_list_comparator_type(int type)
700 {
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;
709 	}
710 }
711 
is_comparator(struct isl_token * tok)712 static int is_comparator(struct isl_token *tok)
713 {
714 	if (!tok)
715 		return 0;
716 	if (is_list_comparator_type(tok->type))
717 		return 1;
718 
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;
729 	}
730 }
731 
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);
736 
737 /* Accept a ternary operator, given the first argument.
738  */
accept_ternary(__isl_keep isl_stream * s,__isl_take isl_map * cond,struct vars * v,int rational)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)
741 {
742 	isl_space *space;
743 	isl_pw_aff *pwaff1 = NULL, *pwaff2 = NULL, *pa_cond;
744 
745 	if (!cond)
746 		return NULL;
747 
748 	if (isl_stream_eat(s, '?'))
749 		goto error;
750 
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;
755 
756 	if (isl_stream_eat(s, ':'))
757 		goto error;
758 
759 	space = isl_pw_aff_get_domain_space(pwaff1);
760 	pwaff2 = accept_extended_affine(s, space, v, rational);
761 	if (!pwaff2)
762 		goto error;
763 
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;
771 }
772 
773 /* Set *line and *col to those of the next token, if any.
774  */
set_current_line_col(__isl_keep isl_stream * s,int * line,int * col)775 static void set_current_line_col(__isl_keep isl_stream *s, int *line, int *col)
776 {
777 	struct isl_token *tok;
778 
779 	tok = isl_stream_next_token(s);
780 	if (!tok)
781 		return;
782 
783 	*line = tok->line;
784 	*col = tok->col;
785 	isl_stream_push_token(s, tok);
786 }
787 
788 /* Push a token encapsulating "pa" onto "s", with the given
789  * line and column.
790  */
push_aff(__isl_keep isl_stream * s,int line,int col,__isl_take isl_pw_aff * pa)791 static isl_stat push_aff(__isl_keep isl_stream *s, int line, int col,
792 	__isl_take isl_pw_aff *pa)
793 {
794 	struct isl_token *tok;
795 
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);
802 
803 	return isl_stat_ok;
804 error:
805 	isl_pw_aff_free(pa);
806 	return isl_stat_error;
807 }
808 
809 /* Is the next token a comparison operator?
810  */
next_is_comparator(__isl_keep isl_stream * s)811 static int next_is_comparator(__isl_keep isl_stream *s)
812 {
813 	int is_comp;
814 	struct isl_token *tok;
815 
816 	tok = isl_stream_next_token(s);
817 	if (!tok)
818 		return 0;
819 
820 	is_comp = is_comparator(tok);
821 	isl_stream_push_token(s, tok);
822 
823 	return is_comp;
824 }
825 
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.
831  */
accept_extended_affine(__isl_keep isl_stream * s,__isl_take isl_space * space,struct vars * v,int rational)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)
834 {
835 	isl_map *cond;
836 	isl_pw_aff *pwaff;
837 	int line = -1, col = -1;
838 
839 	set_current_line_col(s, &line, &col);
840 
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;
848 
849 	space = isl_pw_aff_get_domain_space(pwaff);
850 	cond = isl_map_universe(isl_space_unwrap(space));
851 
852 	if (push_aff(s, line, col, pwaff) < 0)
853 		cond = isl_map_free(cond);
854 	if (!cond)
855 		return NULL;
856 
857 	cond = read_formula(s, v, cond, rational);
858 
859 	return accept_ternary(s, cond, v, rational);
860 }
861 
read_var_def(__isl_keep isl_stream * s,__isl_take isl_map * map,enum isl_dim_type type,struct vars * v,int 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)
865 {
866 	isl_pw_aff *def;
867 	isl_size pos;
868 	isl_map *def_map;
869 
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;
879 		}
880 		type = isl_dim_in;
881 	}
882 	if (pos < 0)
883 		return isl_map_free(map);
884 	--pos;
885 
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));
891 
892 	map = isl_map_intersect(map, def_map);
893 
894 	return map;
895 }
896 
accept_affine_list(__isl_keep isl_stream * s,__isl_take isl_space * space,struct vars * v)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)
899 {
900 	isl_pw_aff *pwaff;
901 	isl_pw_aff_list *list;
902 	struct isl_token *tok = NULL;
903 
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;
908 
909 	for (;;) {
910 		tok = isl_stream_next_token(s);
911 		if (!tok) {
912 			isl_stream_error(s, NULL, "unexpected EOF");
913 			goto error;
914 		}
915 		if (tok->type != ',') {
916 			isl_stream_push_token(s, tok);
917 			break;
918 		}
919 		isl_token_free(tok);
920 
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;
926 	}
927 
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;
934 }
935 
read_defined_var_list(__isl_keep isl_stream * s,struct vars * v,__isl_take isl_map * map,int rational)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)
938 {
939 	struct isl_token *tok;
940 
941 	while ((tok = isl_stream_next_token(s)) != NULL) {
942 		int p;
943 		int n = v->n;
944 
945 		if (tok->type != ISL_TOKEN_IDENT)
946 			break;
947 
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;
954 		}
955 
956 		map = isl_map_add_dims(map, isl_dim_out, 1);
957 
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);
964 		}
965 
966 		if (!tok || tok->type != ',')
967 			break;
968 
969 		isl_token_free(tok);
970 	}
971 	if (tok)
972 		isl_stream_push_token(s, tok);
973 
974 	return map;
975 error:
976 	isl_token_free(tok);
977 	isl_map_free(map);
978 	return NULL;
979 }
980 
next_is_tuple(__isl_keep isl_stream * s)981 static int next_is_tuple(__isl_keep isl_stream *s)
982 {
983 	struct isl_token *tok;
984 	int is_tuple;
985 
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;
992 	}
993 	if (tok->type != ISL_TOKEN_IDENT && !tok->is_keyword) {
994 		isl_stream_push_token(s, tok);
995 		return 0;
996 	}
997 
998 	is_tuple = isl_stream_next_token_is(s, '[');
999 
1000 	isl_stream_push_token(s, tok);
1001 
1002 	return is_tuple;
1003 }
1004 
1005 /* Does the next token mark the end of a tuple element?
1006  */
next_is_end_tuple_element(__isl_keep isl_stream * s)1007 static int next_is_end_tuple_element(__isl_keep isl_stream *s)
1008 {
1009 	return isl_stream_next_token_is(s, ',') ||
1010 	    isl_stream_next_token_is(s, ']');
1011 }
1012 
1013 /* Is the next token one that necessarily forms the start of a condition?
1014  */
next_is_condition_start(__isl_keep isl_stream * s)1015 static int next_is_condition_start(__isl_keep isl_stream *s)
1016 {
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);
1022 }
1023 
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.
1030  */
pw_aff_is_expr(__isl_keep isl_pw_aff * pa,int i,int n)1031 static isl_bool pw_aff_is_expr(__isl_keep isl_pw_aff *pa, int i, int n)
1032 {
1033 	isl_aff *aff;
1034 
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;
1041 
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;
1046 }
1047 
1048 /* Does the tuple contain any dimensions that are defined
1049  * in terms of earlier dimensions?
1050  */
tuple_has_expr(__isl_keep isl_multi_pw_aff * tuple)1051 static isl_bool tuple_has_expr(__isl_keep isl_multi_pw_aff *tuple)
1052 {
1053 	int i;
1054 	isl_size n;
1055 	isl_bool has_expr = isl_bool_false;
1056 	isl_pw_aff *pa;
1057 
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;
1067 	}
1068 
1069 	return has_expr;
1070 }
1071 
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.
1076  */
space_set_dim_name(__isl_take isl_space * space,int pos,char * name)1077 static __isl_give isl_space *space_set_dim_name(__isl_take isl_space *space,
1078 	int pos, char *name)
1079 {
1080 	char *prime;
1081 
1082 	if (!name)
1083 		return space;
1084 
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 = '\'';
1091 
1092 	return space;
1093 }
1094 
1095 /* Construct an isl_pw_aff defined on a "space" (with v->n variables)
1096  * that is equal to the last of those variables.
1097  */
identity_tuple_el_on_space(__isl_take isl_space * space,struct vars * v)1098 static __isl_give isl_pw_aff *identity_tuple_el_on_space(
1099 	__isl_take isl_space *space, struct vars *v)
1100 {
1101 	isl_aff *aff;
1102 
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);
1106 }
1107 
1108 /* Construct an isl_pw_aff defined on the domain space of "pa"
1109  * that is equal to the last variable in "v".
1110  *
1111  * That is, if D is the domain space of "pa", then construct
1112  *
1113  *	D[..., i] -> i.
1114  */
init_range(__isl_keep isl_pw_aff * pa,struct vars * v)1115 static __isl_give isl_pw_aff *init_range(__isl_keep isl_pw_aff *pa,
1116 	struct vars *v)
1117 {
1118 	isl_space *space;
1119 
1120 	space = isl_pw_aff_get_domain_space(pa);
1121 	return identity_tuple_el_on_space(space, v);
1122 }
1123 
1124 /* Impose the lower bound "lower" on the variable represented by "range_pa".
1125  *
1126  * In particular, "range_pa" is of the form
1127  *
1128  *	D[..., i] -> i : C
1129  *
1130  * with D also the domains space of "lower' and "C" some constraints.
1131  *
1132  * Return the expression
1133  *
1134  *	D[..., i] -> i : C and i >= lower
1135  */
set_lower(__isl_take isl_pw_aff * range_pa,__isl_take isl_pw_aff * lower)1136 static __isl_give isl_pw_aff *set_lower(__isl_take isl_pw_aff *range_pa,
1137 	__isl_take isl_pw_aff *lower)
1138 {
1139 	isl_set *range;
1140 
1141 	range = isl_pw_aff_ge_set(isl_pw_aff_copy(range_pa), lower);
1142 	return isl_pw_aff_intersect_domain(range_pa, range);
1143 }
1144 
1145 /* Impose the upper bound "upper" on the variable represented by "range_pa".
1146  *
1147  * In particular, "range_pa" is of the form
1148  *
1149  *	D[..., i] -> i : C
1150  *
1151  * with D also the domains space of "upper' and "C" some constraints.
1152  *
1153  * Return the expression
1154  *
1155  *	D[..., i] -> i : C and i <= upper
1156  */
set_upper(__isl_take isl_pw_aff * range_pa,__isl_take isl_pw_aff * upper)1157 static __isl_give isl_pw_aff *set_upper(__isl_take isl_pw_aff *range_pa,
1158 	__isl_take isl_pw_aff *upper)
1159 {
1160 	isl_set *range;
1161 
1162 	range = isl_pw_aff_le_set(isl_pw_aff_copy(range_pa), upper);
1163 	return isl_pw_aff_intersect_domain(range_pa, range);
1164 }
1165 
1166 /* Construct a piecewise affine expression corresponding
1167  * to the last variable in "v" that is greater than or equal to "pa".
1168  *
1169  * In particular, if D is the domain space of "pa",
1170  * then construct the expression
1171  *
1172  *	D[..., i] -> i,
1173  *
1174  * impose lower bound "pa" and return
1175  *
1176  *	D[..., i] -> i : i >= pa
1177  */
construct_lower(__isl_take isl_pw_aff * pa,struct vars * v)1178 static __isl_give isl_pw_aff *construct_lower(__isl_take isl_pw_aff *pa,
1179 	struct vars *v)
1180 {
1181 	return set_lower(init_range(pa, v), pa);
1182 }
1183 
1184 /* Construct a piecewise affine expression corresponding
1185  * to the last variable in "v" that is smaller than or equal to "pa".
1186  *
1187  * In particular, if D is the domain space of "pa",
1188  * then construct the expression
1189  *
1190  *	D[..., i] -> i,
1191  *
1192  * impose lower bound "pa" and return
1193  *
1194  *	D[..., i] -> i : i <= pa
1195  */
construct_upper(__isl_take isl_pw_aff * pa,struct vars * v)1196 static __isl_give isl_pw_aff *construct_upper(__isl_take isl_pw_aff *pa,
1197 	struct vars *v)
1198 {
1199 	return set_upper(init_range(pa, v), pa);
1200 }
1201 
1202 /* Construct a piecewise affine expression corresponding
1203  * to the last variable in "v" that ranges between "pa" and "pa2".
1204  *
1205  * In particular, if D is the domain space of "pa" (and "pa2"),
1206  * then construct the expression
1207  *
1208  *	D[..., i] -> i,
1209  *
1210  * impose lower bound "pa" and upper bound "pa2" and return
1211  *
1212  *	D[..., i] -> i : pa <= i <= pa2
1213  */
construct_range(__isl_take isl_pw_aff * pa,__isl_take isl_pw_aff * pa2,struct vars * v)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)
1216 {
1217 	return set_upper(set_lower(init_range(pa, v), pa), pa2);
1218 }
1219 
1220 static int resolve_paren_expr(__isl_keep isl_stream *s,
1221 	struct vars *v, __isl_take isl_map *map, int rational);
1222 
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.
1226  *
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.
1237  */
update_piecewise_affine_colon(__isl_take isl_pw_aff * pa,__isl_keep isl_stream * s,struct vars * v,int rational)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)
1241 {
1242 	isl_space *dom_space;
1243 	isl_map *map;
1244 
1245 	dom_space = isl_pw_aff_get_domain_space(pa);
1246 	map = isl_map_universe(isl_space_from_domain(dom_space));
1247 
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);
1254 	}
1255 	if (!next_is_condition_start(s)) {
1256 		int line = -1, col = -1;
1257 		isl_space *space;
1258 		isl_pw_aff *pa2;
1259 
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);
1269 		}
1270 		if (push_aff(s, line, col, pa2) < 0)
1271 			goto error;
1272 	}
1273 
1274 	map = read_formula(s, v, map, rational);
1275 	pa = isl_pw_aff_intersect_domain(pa, isl_map_domain(map));
1276 
1277 	return pa;
1278 error:
1279 	isl_map_free(map);
1280 	isl_pw_aff_free(pa);
1281 	return NULL;
1282 }
1283 
1284 /* Accept a piecewise affine expression.
1285  *
1286  * At the outer level, the piecewise affine expression may be of the form
1287  *
1288  *	aff1 : condition1; aff2 : conditions2; ...
1289  *
1290  * or one of
1291  *
1292  *	aff :
1293  *	aff1 : aff2
1294  *	: aff
1295  *	:
1296  *
1297  * or simply
1298  *
1299  *	aff
1300  *
1301  * each of the affine expressions may in turn include ternary operators.
1302  *
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.
1309  *
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".
1318  */
accept_piecewise_affine(__isl_keep isl_stream * s,__isl_take isl_space * space,struct vars * v,int rational)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)
1321 {
1322 	isl_pw_aff *res;
1323 	isl_space *res_space;
1324 
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);
1330 	}
1331 
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;
1339 
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);
1354 		}
1355 		if (isl_stream_eat_if_available(s, ':'))
1356 			pa = update_piecewise_affine_colon(pa, s, v, rational);
1357 
1358 		res = isl_pw_aff_union_add(res, pa);
1359 
1360 		if (seen_paren && isl_stream_eat(s, ')'))
1361 			goto error;
1362 	} while (isl_stream_eat_if_available(s, ';'));
1363 
1364 	isl_space_free(space);
1365 
1366 	return res;
1367 error:
1368 	isl_space_free(space);
1369 	return isl_pw_aff_free(res);
1370 }
1371 
1372 /* Read an affine expression from "s" for use in read_tuple.
1373  *
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.
1378  */
read_tuple_var_def(__isl_keep isl_stream * s,struct vars * v,int rational)1379 static __isl_give isl_pw_aff *read_tuple_var_def(__isl_keep isl_stream *s,
1380 	struct vars *v, int rational)
1381 {
1382 	isl_space *space;
1383 	isl_pw_aff *def;
1384 
1385 	space = isl_space_wrap(isl_space_alloc(s->ctx, 0, v->n, 0));
1386 
1387 	def = accept_piecewise_affine(s, space, v, rational);
1388 	def = isl_pw_aff_domain_factor_domain(def);
1389 
1390 	return def;
1391 }
1392 
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.
1398  */
read_tuple_list(__isl_keep isl_stream * s,struct vars * v,__isl_take isl_space * space,int rational,int comma,__isl_give isl_space * (* read_el)(__isl_keep isl_stream * s,struct vars * v,__isl_take isl_space * space,int rational,void * user),void * user)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)
1405 {
1406 	if (!space)
1407 		return NULL;
1408 
1409 	space = isl_space_set_from_params(space);
1410 
1411 	if (isl_stream_next_token_is(s, ']'))
1412 		return space;
1413 
1414 	for (;;) {
1415 		struct isl_token *tok;
1416 
1417 		space = isl_space_add_dims(space, isl_dim_set, 1);
1418 
1419 		space = read_el(s, v, space, rational, user);
1420 		if (!space)
1421 			return NULL;
1422 
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;
1432 		}
1433 
1434 		isl_token_free(tok);
1435 	}
1436 
1437 	return space;
1438 }
1439 
1440 /* Read a tuple space from "s" derived from the parameter space "space".
1441  * Call "read_el" on each element in the tuples.
1442  */
read_tuple_space(__isl_keep isl_stream * s,struct vars * v,__isl_take isl_space * space,int rational,int comma,__isl_give isl_space * (* read_el)(__isl_keep isl_stream * s,struct vars * v,__isl_take isl_space * space,int rational,void * user),void * user)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)
1449 {
1450 	struct isl_token *tok;
1451 	char *name = NULL;
1452 	isl_space *res = NULL;
1453 
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;
1480 
1481 	if (name) {
1482 		res = isl_space_set_tuple_name(res, isl_dim_set, name);
1483 		free(name);
1484 	}
1485 
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;
1493 }
1494 
1495 /* Construct an isl_pw_aff defined on a space with v->n variables
1496  * that is equal to the last of those variables.
1497  */
identity_tuple_el(struct vars * v)1498 static __isl_give isl_pw_aff *identity_tuple_el(struct vars *v)
1499 {
1500 	isl_space *space;
1501 
1502 	space = isl_space_set_alloc(v->ctx, 0, v->n);
1503 	return identity_tuple_el_on_space(space, v);
1504 }
1505 
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.
1515  */
read_tuple_pw_aff_el(__isl_keep isl_stream * s,struct vars * v,__isl_take isl_space * space,int rational,void * user)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)
1518 {
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;
1523 
1524 	tok = next_token(s);
1525 	if (!tok) {
1526 		isl_stream_error(s, NULL, "unexpected EOF");
1527 		return isl_space_free(space);
1528 	}
1529 
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;
1536 	}
1537 
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);
1560 	}
1561 
1562 	*list = isl_pw_aff_list_add(*list, pa);
1563 	if (!*list)
1564 		return isl_space_free(space);
1565 
1566 	return space;
1567 error:
1568 	isl_token_free(tok);
1569 	return isl_space_free(space);
1570 }
1571 
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.
1580  *
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.
1586  */
read_tuple(__isl_keep isl_stream * s,struct vars * v,int rational,int comma)1587 static __isl_give isl_multi_pw_aff *read_tuple(__isl_keep isl_stream *s,
1588 	struct vars *v, int rational, int comma)
1589 {
1590 	int i;
1591 	isl_size n;
1592 	isl_space *space;
1593 	isl_pw_aff_list *list;
1594 
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;
1604 
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);
1608 	}
1609 
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);
1613 }
1614 
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".
1620  */
map_from_tuple(__isl_take isl_multi_pw_aff * tuple,__isl_take isl_map * map,enum isl_dim_type type,struct vars * v,int rational)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)
1624 {
1625 	int i;
1626 	isl_size n;
1627 	isl_ctx *ctx;
1628 	isl_space *space = NULL;
1629 
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;
1637 
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);
1644 		}
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);
1654 		}
1655 	} else if (type == isl_dim_in) {
1656 		isl_set *set;
1657 
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;
1665 
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);
1670 	}
1671 
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;
1678 
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);
1691 	}
1692 
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;
1701 }
1702 
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".
1706  */
read_map_tuple(__isl_keep isl_stream * s,__isl_take isl_map * map,enum isl_dim_type type,struct vars * v,int rational,int comma)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)
1710 {
1711 	isl_multi_pw_aff *tuple;
1712 
1713 	tuple = read_tuple(s, v, rational, comma);
1714 	if (!tuple)
1715 		return isl_map_free(map);
1716 
1717 	return map_from_tuple(tuple, map, type, v, rational);
1718 }
1719 
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".
1723  *
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.
1728  *
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.
1734  */
list_cmp(__isl_keep isl_set * set,int type,__isl_take isl_pw_aff_list * left,__isl_take isl_pw_aff_list * right)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)
1737 {
1738 	isl_space *space;
1739 	isl_size n;
1740 	isl_multi_pw_aff *mpa1, *mpa2;
1741 
1742 	n = isl_pw_aff_list_n_pw_aff(left);
1743 	if (!set || n < 0 || !right)
1744 		goto error;
1745 
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);
1752 
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);
1772 	}
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;
1779 }
1780 
1781 /* Construct constraints of the form
1782  *
1783  *	a op b
1784  *
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.
1790  *
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.
1794  */
construct_constraints(__isl_take isl_set * set,int type,__isl_keep isl_pw_aff_list * left,__isl_keep isl_pw_aff_list * right,int rational)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)
1799 {
1800 	isl_set *cond;
1801 
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);
1807 	}
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);
1822 
1823 	return isl_set_intersect(set, cond);
1824 }
1825 
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.
1841  *
1842  * The processing is performed on a wrapped copy of "map" because
1843  * an affine expression cannot have a binary relation as domain.
1844  */
add_constraint(__isl_keep isl_stream * s,struct vars * v,__isl_take isl_map * map,int rational)1845 static __isl_give isl_map *add_constraint(__isl_keep isl_stream *s,
1846 	struct vars *v, __isl_take isl_map *map, int rational)
1847 {
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;
1853 
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;
1864 	}
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;
1877 		}
1878 
1879 		set = construct_constraints(set, type, list1, list2, rational);
1880 		isl_pw_aff_list_free(list1);
1881 		list1 = list2;
1882 
1883 		if (!next_is_comparator(s))
1884 			break;
1885 		tok = isl_stream_next_token(s);
1886 		type = tok->type;
1887 		isl_token_free(tok);
1888 	}
1889 	isl_pw_aff_list_free(list1);
1890 
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;
1897 }
1898 
read_exists(__isl_keep isl_stream * s,struct vars * v,__isl_take isl_map * map,int rational)1899 static __isl_give isl_map *read_exists(__isl_keep isl_stream *s,
1900 	struct vars *v, __isl_take isl_map *map, int rational)
1901 {
1902 	int n = v->n;
1903 	int seen_paren = isl_stream_eat_if_available(s, '(');
1904 
1905 	map = isl_map_from_domain(isl_map_wrap(map));
1906 	map = read_defined_var_list(s, v, map, rational);
1907 
1908 	if (isl_stream_eat(s, ':'))
1909 		goto error;
1910 
1911 	map = read_formula(s, v, map, rational);
1912 	map = isl_set_unwrap(isl_map_domain(map));
1913 
1914 	vars_drop(v, v->n - n);
1915 	if (seen_paren && isl_stream_eat(s, ')'))
1916 		goto error;
1917 
1918 	return map;
1919 error:
1920 	isl_map_free(map);
1921 	return NULL;
1922 }
1923 
1924 /* Parse an expression between parentheses and push the result
1925  * back on the stream.
1926  *
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.
1930  *
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.
1938  */
resolve_paren_expr(__isl_keep isl_stream * s,struct vars * v,__isl_take isl_map * map,int rational)1939 static int resolve_paren_expr(__isl_keep isl_stream *s,
1940 	struct vars *v, __isl_take isl_map *map, int rational)
1941 {
1942 	struct isl_token *tok, *tok2;
1943 	int has_paren;
1944 	int line, col;
1945 	isl_pw_aff *pwaff;
1946 
1947 	tok = isl_stream_next_token(s);
1948 	if (!tok || tok->type != '(')
1949 		goto error;
1950 
1951 	if (isl_stream_next_token_is(s, '('))
1952 		if (resolve_paren_expr(s, v, isl_map_copy(map), rational))
1953 			goto error;
1954 
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;
1963 	}
1964 
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);
1971 
1972 	pwaff = accept_affine(s, isl_space_wrap(isl_map_get_space(map)), v);
1973 	if (!pwaff)
1974 		goto error;
1975 
1976 	has_paren = isl_stream_eat_if_available(s, ')');
1977 
1978 	if (push_aff(s, line, col, pwaff) < 0)
1979 		goto error;
1980 
1981 	if (has_paren) {
1982 		isl_token_free(tok);
1983 		isl_map_free(map);
1984 		return 0;
1985 	}
1986 
1987 	map = read_formula(s, v, map, rational);
1988 	if (isl_stream_eat(s, ')'))
1989 		goto error;
1990 
1991 	tok->type = ISL_TOKEN_MAP;
1992 	tok->u.map = map;
1993 	isl_stream_push_token(s, tok);
1994 
1995 	return 0;
1996 error:
1997 	isl_token_free(tok);
1998 	isl_map_free(map);
1999 	return -1;
2000 }
2001 
read_conjunct(__isl_keep isl_stream * s,struct vars * v,__isl_take isl_map * map,int rational)2002 static __isl_give isl_map *read_conjunct(__isl_keep isl_stream *s,
2003 	struct vars *v, __isl_take isl_map *map, int rational)
2004 {
2005 	if (isl_stream_next_token_is(s, '('))
2006 		if (resolve_paren_expr(s, v, isl_map_copy(map), rational))
2007 			goto error;
2008 
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;
2018 	}
2019 
2020 	if (isl_stream_eat_if_available(s, ISL_TOKEN_EXISTS))
2021 		return read_exists(s, v, map, rational);
2022 
2023 	if (isl_stream_eat_if_available(s, ISL_TOKEN_TRUE))
2024 		return map;
2025 
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);
2030 	}
2031 
2032 	return add_constraint(s, v, map, rational);
2033 error:
2034 	isl_map_free(map);
2035 	return NULL;
2036 }
2037 
read_conjuncts(__isl_keep isl_stream * s,struct vars * v,__isl_take isl_map * map,int rational)2038 static __isl_give isl_map *read_conjuncts(__isl_keep isl_stream *s,
2039 	struct vars *v, __isl_take isl_map *map, int rational)
2040 {
2041 	isl_map *res;
2042 	int negate;
2043 
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);
2048 
2049 	while (res && isl_stream_eat_if_available(s, ISL_TOKEN_AND)) {
2050 		isl_map *res_i;
2051 
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);
2058 	}
2059 
2060 	isl_map_free(map);
2061 	return res;
2062 }
2063 
read_disjuncts(__isl_keep isl_stream * s,struct vars * v,__isl_take isl_map * map,int rational)2064 static __isl_give isl_map *read_disjuncts(__isl_keep isl_stream *s,
2065 	struct vars *v, __isl_take isl_map *map, int rational)
2066 {
2067 	isl_map *res;
2068 
2069 	if (isl_stream_next_token_is(s, '}'))
2070 		return map;
2071 
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;
2075 
2076 		res_i = read_conjuncts(s, v, isl_map_copy(map), rational);
2077 		res = isl_map_union(res, res_i);
2078 	}
2079 
2080 	isl_map_free(map);
2081 	return res;
2082 }
2083 
2084 /* Read a first order formula from "s", add the corresponding
2085  * constraints to "map" and return the result.
2086  *
2087  * In particular, read a formula of the form
2088  *
2089  *	a
2090  *
2091  * or
2092  *
2093  *	a implies b
2094  *
2095  * where a and b are disjunctions.
2096  *
2097  * In the first case, map is replaced by
2098  *
2099  *	map \cap { [..] : a }
2100  *
2101  * In the second case, it is replaced by
2102  *
2103  *	(map \setminus { [..] : a}) \cup (map \cap { [..] : b })
2104  */
read_formula(__isl_keep isl_stream * s,struct vars * v,__isl_take isl_map * map,int rational)2105 static __isl_give isl_map *read_formula(__isl_keep isl_stream *s,
2106 	struct vars *v, __isl_take isl_map *map, int rational)
2107 {
2108 	isl_map *res;
2109 
2110 	res = read_disjuncts(s, v, isl_map_copy(map), rational);
2111 
2112 	if (isl_stream_eat_if_available(s, ISL_TOKEN_IMPLIES)) {
2113 		isl_map *res2;
2114 
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);
2120 
2121 	return res;
2122 }
2123 
polylib_pos_to_isl_pos(__isl_keep isl_basic_map * bmap,int pos)2124 static isl_size polylib_pos_to_isl_pos(__isl_keep isl_basic_map *bmap, int pos)
2125 {
2126 	isl_size n_out, n_in, n_param, n_div;
2127 
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;
2134 
2135 	if (pos < n_out)
2136 		return 1 + n_param + n_in + pos;
2137 	pos -= n_out;
2138 
2139 	if (pos < n_in)
2140 		return 1 + n_param + pos;
2141 	pos -= n_in;
2142 
2143 	if (pos < n_div)
2144 		return 1 + n_param + n_in + n_out + pos;
2145 	pos -= n_div;
2146 
2147 	if (pos < n_param)
2148 		return 1 + pos;
2149 
2150 	return 0;
2151 }
2152 
basic_map_read_polylib_constraint(__isl_keep isl_stream * s,__isl_take isl_basic_map * bmap)2153 static __isl_give isl_basic_map *basic_map_read_polylib_constraint(
2154 	__isl_keep isl_stream *s, __isl_take isl_basic_map *bmap)
2155 {
2156 	int j;
2157 	struct isl_token *tok;
2158 	int type;
2159 	int k;
2160 	isl_int *c;
2161 	isl_size total;
2162 
2163 	if (!bmap)
2164 		return NULL;
2165 
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;
2172 	}
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;
2177 	}
2178 
2179 	type = isl_int_get_si(tok->u.v);
2180 	isl_token_free(tok);
2181 
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];
2189 	}
2190 	if (k < 0)
2191 		goto error;
2192 
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;
2204 		}
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;
2210 		}
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);
2217 	}
2218 
2219 	return bmap;
2220 error:
2221 	isl_basic_map_free(bmap);
2222 	return NULL;
2223 }
2224 
basic_map_read_polylib(__isl_keep isl_stream * s)2225 static __isl_give isl_basic_map *basic_map_read_polylib(
2226 	__isl_keep isl_stream *s)
2227 {
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;
2236 
2237 	tok = isl_stream_next_token(s);
2238 	if (!tok) {
2239 		isl_stream_error(s, NULL, "unexpected EOF");
2240 		return NULL;
2241 	}
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;
2247 	}
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;
2254 	}
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;
2270 		}
2271 		out = isl_int_get_si(tok->u.v);
2272 		isl_token_free(tok);
2273 
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;
2281 		}
2282 		in = isl_int_get_si(tok->u.v);
2283 		isl_token_free(tok);
2284 
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;
2292 		}
2293 		local = isl_int_get_si(tok->u.v);
2294 		isl_token_free(tok);
2295 
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;
2303 		}
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;
2310 		}
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;
2316 
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);
2322 	}
2323 
2324 	for (i = 0; i < n_row; ++i)
2325 		bmap = basic_map_read_polylib_constraint(s, bmap);
2326 
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;
2332 	}
2333 
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;
2340 }
2341 
map_read_polylib(__isl_keep isl_stream * s)2342 static __isl_give isl_map *map_read_polylib(__isl_keep isl_stream *s)
2343 {
2344 	struct isl_token *tok;
2345 	struct isl_token *tok2;
2346 	int i, n;
2347 	struct isl_map *map;
2348 
2349 	tok = isl_stream_next_token(s);
2350 	if (!tok) {
2351 		isl_stream_error(s, NULL, "unexpected EOF");
2352 		return NULL;
2353 	}
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));
2359 	}
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;
2365 	}
2366 	n = isl_int_get_si(tok->u.v);
2367 	isl_token_free(tok);
2368 
2369 	isl_assert(s->ctx, n >= 1, return NULL);
2370 
2371 	map = isl_map_from_basic_map(basic_map_read_polylib(s));
2372 
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)));
2376 
2377 	return map;
2378 }
2379 
optional_power(__isl_keep isl_stream * s)2380 static int optional_power(__isl_keep isl_stream *s)
2381 {
2382 	int pow;
2383 	struct isl_token *tok;
2384 
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;
2391 	}
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;
2399 	}
2400 	pow = isl_int_get_si(tok->u.v);
2401 	isl_token_free(tok);
2402 	return pow;
2403 }
2404 
2405 static __isl_give isl_pw_qpolynomial *read_term(__isl_keep isl_stream *s,
2406 	__isl_keep isl_map *map, struct vars *v);
2407 
read_factor(__isl_keep isl_stream * s,__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)
2410 {
2411 	isl_pw_qpolynomial *pwqp;
2412 	struct isl_token *tok;
2413 
2414 	tok = next_token(s);
2415 	if (!tok) {
2416 		isl_stream_error(s, NULL, "unexpected EOF");
2417 		return NULL;
2418 	}
2419 	if (tok->type == '(') {
2420 		int pow;
2421 
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;
2433 
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;
2443 			}
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);
2451 		}
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;
2472 		}
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;
2478 		}
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;
2486 
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;
2500 	}
2501 
2502 	if (isl_stream_eat_if_available(s, '*') ||
2503 	    isl_stream_next_token_is(s, ISL_TOKEN_IDENT)) {
2504 		isl_pw_qpolynomial *pwqp2;
2505 
2506 		pwqp2 = read_factor(s, map, v);
2507 		pwqp = isl_pw_qpolynomial_mul(pwqp, pwqp2);
2508 	}
2509 
2510 	return pwqp;
2511 error:
2512 	isl_pw_qpolynomial_free(pwqp);
2513 	return NULL;
2514 }
2515 
read_term(__isl_keep isl_stream * s,__isl_keep isl_map * map,struct vars * v)2516 static __isl_give isl_pw_qpolynomial *read_term(__isl_keep isl_stream *s,
2517 	__isl_keep isl_map *map, struct vars *v)
2518 {
2519 	struct isl_token *tok;
2520 	isl_pw_qpolynomial *pwqp;
2521 
2522 	pwqp = read_factor(s, map, v);
2523 
2524 	for (;;) {
2525 		tok = next_token(s);
2526 		if (!tok)
2527 			return pwqp;
2528 
2529 		if (tok->type == '+') {
2530 			isl_pw_qpolynomial *pwqp2;
2531 
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;
2537 
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;
2544 
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;
2551 		}
2552 	}
2553 
2554 	return pwqp;
2555 }
2556 
read_optional_formula(__isl_keep isl_stream * s,__isl_take isl_map * map,struct vars * v,int rational)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)
2559 {
2560 	struct isl_token *tok;
2561 
2562 	tok = isl_stream_next_token(s);
2563 	if (!tok) {
2564 		isl_stream_error(s, NULL, "unexpected EOF");
2565 		goto error;
2566 	}
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);
2573 
2574 	return map;
2575 error:
2576 	isl_map_free(map);
2577 	return NULL;
2578 }
2579 
obj_read_poly(__isl_keep isl_stream * s,__isl_take isl_map * map,struct vars * v,int n)2580 static struct isl_obj obj_read_poly(__isl_keep isl_stream *s,
2581 	__isl_take isl_map *map, struct vars *v, int n)
2582 {
2583 	struct isl_obj obj = { isl_obj_pw_qpolynomial, NULL };
2584 	isl_pw_qpolynomial *pwqp;
2585 	struct isl_set *set;
2586 
2587 	pwqp = read_term(s, map, v);
2588 	map = read_optional_formula(s, map, v, 0);
2589 	set = isl_map_range(map);
2590 
2591 	pwqp = isl_pw_qpolynomial_intersect_domain(pwqp, set);
2592 
2593 	vars_drop(v, v->n - n);
2594 
2595 	obj.v = pwqp;
2596 	return obj;
2597 }
2598 
obj_read_poly_or_fold(__isl_keep isl_stream * s,__isl_take isl_set * set,struct vars * v,int n)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)
2601 {
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;
2607 
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;
2613 
2614 	if (isl_stream_eat(s, '('))
2615 		goto error;
2616 
2617 	pwqp = read_term(s, set, v);
2618 	pwf = isl_pw_qpolynomial_fold_from_pw_qpolynomial(fold, pwqp);
2619 
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);
2625 	}
2626 
2627 	if (isl_stream_eat(s, ')'))
2628 		goto error;
2629 
2630 	set = read_optional_formula(s, set, v, 0);
2631 	pwf = isl_pw_qpolynomial_fold_intersect_domain(pwf, set);
2632 
2633 	vars_drop(v, v->n - n);
2634 
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;
2642 }
2643 
is_rational(__isl_keep isl_stream * s)2644 static int is_rational(__isl_keep isl_stream *s)
2645 {
2646 	struct isl_token *tok;
2647 
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;
2655 	}
2656 
2657 	isl_stream_push_token(s, tok);
2658 
2659 	return 0;
2660 }
2661 
obj_read_body(__isl_keep isl_stream * s,__isl_take isl_map * map,struct vars * v)2662 static struct isl_obj obj_read_body(__isl_keep isl_stream *s,
2663 	__isl_take isl_map *map, struct vars *v)
2664 {
2665 	struct isl_token *tok;
2666 	struct isl_obj obj = { isl_obj_set, NULL };
2667 	int n = v->n;
2668 	int rational;
2669 
2670 	rational = is_rational(s);
2671 	if (rational)
2672 		map = isl_map_set_rational(map);
2673 
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;
2678 	}
2679 
2680 	if (!next_is_tuple(s))
2681 		return obj_read_poly_or_fold(s, map, v, n);
2682 
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);
2695 		}
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);
2702 	}
2703 
2704 	map = read_optional_formula(s, map, v, rational);
2705 
2706 	vars_drop(v, v->n - n);
2707 
2708 	obj.v = map;
2709 	return obj;
2710 error:
2711 	isl_map_free(map);
2712 	obj.type = isl_obj_none;
2713 	return obj;
2714 }
2715 
to_union(isl_ctx * ctx,struct isl_obj obj)2716 static struct isl_obj to_union(isl_ctx *ctx, struct isl_obj obj)
2717 {
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;
2737 }
2738 
obj_add(__isl_keep isl_stream * s,struct isl_obj obj1,struct isl_obj obj2)2739 static struct isl_obj obj_add(__isl_keep isl_stream *s,
2740 	struct isl_obj obj1, struct isl_obj obj2)
2741 {
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;
2768 	}
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);
2775 	}
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);
2779 	}
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);
2784 	}
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);
2789 	}
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;
2798 }
2799 
2800 /* Are the first two tokens on "s", "domain" (either as a string
2801  * or as an identifier) followed by ":"?
2802  */
next_is_domain_colon(__isl_keep isl_stream * s)2803 static int next_is_domain_colon(__isl_keep isl_stream *s)
2804 {
2805 	struct isl_token *tok;
2806 	char *name;
2807 	int res;
2808 
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;
2815 	}
2816 
2817 	name = isl_token_get_str(s->ctx, tok);
2818 	res = !strcmp(name, "domain") && isl_stream_next_token_is(s, ':');
2819 	free(name);
2820 
2821 	isl_stream_push_token(s, tok);
2822 
2823 	return res;
2824 }
2825 
2826 /* Do the first tokens on "s" look like a schedule?
2827  *
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.
2832  */
next_is_schedule(__isl_keep isl_stream * s)2833 static int next_is_schedule(__isl_keep isl_stream *s)
2834 {
2835 	struct isl_token *tok;
2836 	int is_schedule;
2837 
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);
2844 	}
2845 
2846 	is_schedule = next_is_domain_colon(s);
2847 	isl_stream_push_token(s, tok);
2848 
2849 	return is_schedule;
2850 }
2851 
2852 /* Read an isl_schedule from "s" and store it in an isl_obj.
2853  */
schedule_read(__isl_keep isl_stream * s)2854 static struct isl_obj schedule_read(__isl_keep isl_stream *s)
2855 {
2856 	struct isl_obj obj;
2857 
2858 	obj.type = isl_obj_schedule;
2859 	obj.v = isl_stream_read_schedule(s);
2860 
2861 	return obj;
2862 }
2863 
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.
2868  */
obj_read_disjuncts(__isl_keep isl_stream * s,struct vars * v,__isl_keep isl_map * map)2869 static struct isl_obj obj_read_disjuncts(__isl_keep isl_stream *s,
2870 	struct vars *v, __isl_keep isl_map *map)
2871 {
2872 	struct isl_obj obj = { isl_obj_set, NULL };
2873 
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;
2878 	}
2879 
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;
2893 	}
2894 
2895 	return obj;
2896 }
2897 
obj_read(__isl_keep isl_stream * s)2898 static struct isl_obj obj_read(__isl_keep isl_stream *s)
2899 {
2900 	isl_map *map = NULL;
2901 	struct isl_token *tok;
2902 	struct vars *v = NULL;
2903 	struct isl_obj obj = { isl_obj_set, NULL };
2904 
2905 	if (next_is_schedule(s))
2906 		return schedule_read(s);
2907 
2908 	tok = next_token(s);
2909 	if (!tok) {
2910 		isl_stream_error(s, NULL, "unexpected EOF");
2911 		goto error;
2912 	}
2913 	if (tok->type == ISL_TOKEN_VALUE) {
2914 		struct isl_token *tok2;
2915 		struct isl_map *map;
2916 
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;
2926 		}
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;
2937 		}
2938 		return obj;
2939 	}
2940 	v = vars_new(s->ctx);
2941 	if (!v) {
2942 		isl_stream_push_token(s, tok);
2943 		goto error;
2944 	}
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;
2957 		}
2958 		isl_token_free(tok);
2959 		tok = isl_stream_next_token(s);
2960 	}
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;
2966 	}
2967 	isl_token_free(tok);
2968 
2969 	tok = isl_stream_next_token(s);
2970 	if (!tok)
2971 		;
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);
2981 
2982 	obj = obj_read_disjuncts(s, v, map);
2983 	if (obj.type == isl_obj_none || !obj.v)
2984 		goto error;
2985 
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;
2994 	}
2995 
2996 	vars_free(v);
2997 	isl_map_free(map);
2998 
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;
3007 }
3008 
isl_stream_read_obj(__isl_keep isl_stream * s)3009 struct isl_obj isl_stream_read_obj(__isl_keep isl_stream *s)
3010 {
3011 	return obj_read(s);
3012 }
3013 
isl_stream_read_map(__isl_keep isl_stream * s)3014 __isl_give isl_map *isl_stream_read_map(__isl_keep isl_stream *s)
3015 {
3016 	struct isl_obj obj;
3017 
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);
3022 
3023 	if (obj.type == isl_obj_set)
3024 		obj.v = isl_map_from_range(obj.v);
3025 
3026 	return obj.v;
3027 error:
3028 	obj.type->free(obj.v);
3029 	return NULL;
3030 }
3031 
isl_stream_read_set(__isl_keep isl_stream * s)3032 __isl_give isl_set *isl_stream_read_set(__isl_keep isl_stream *s)
3033 {
3034 	struct isl_obj obj;
3035 
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;
3041 		}
3042 		isl_assert(s->ctx, obj.type == isl_obj_set, goto error);
3043 	}
3044 
3045 	return obj.v;
3046 error:
3047 	obj.type->free(obj.v);
3048 	return NULL;
3049 }
3050 
isl_stream_read_union_map(__isl_keep isl_stream * s)3051 __isl_give isl_union_map *isl_stream_read_union_map(__isl_keep isl_stream *s)
3052 {
3053 	struct isl_obj obj;
3054 
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);
3059 	}
3060 	if (obj.type == isl_obj_set) {
3061 		obj.type = isl_obj_union_set;
3062 		obj.v = isl_union_set_from_set(obj.v);
3063 	}
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);
3069 
3070 	return obj.v;
3071 error:
3072 	obj.type->free(obj.v);
3073 	return NULL;
3074 }
3075 
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.
3079  */
extract_union_set(isl_ctx * ctx,struct isl_obj obj)3080 static __isl_give isl_union_set *extract_union_set(isl_ctx *ctx,
3081 	struct isl_obj obj)
3082 {
3083 	if (obj.type == isl_obj_set) {
3084 		obj.type = isl_obj_union_set;
3085 		obj.v = isl_union_set_from_set(obj.v);
3086 	}
3087 	if (obj.v)
3088 		isl_assert(ctx, obj.type == isl_obj_union_set, goto error);
3089 
3090 	return obj.v;
3091 error:
3092 	obj.type->free(obj.v);
3093 	return NULL;
3094 }
3095 
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.
3099  */
isl_stream_read_union_set(__isl_keep isl_stream * s)3100 __isl_give isl_union_set *isl_stream_read_union_set(__isl_keep isl_stream *s)
3101 {
3102 	struct isl_obj obj;
3103 
3104 	obj = obj_read(s);
3105 	return extract_union_set(s->ctx, obj);
3106 }
3107 
basic_map_read(__isl_keep isl_stream * s)3108 static __isl_give isl_basic_map *basic_map_read(__isl_keep isl_stream *s)
3109 {
3110 	struct isl_obj obj;
3111 	struct isl_map *map;
3112 	struct isl_basic_map *bmap;
3113 
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;
3121 
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);
3126 
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]);
3131 
3132 	isl_map_free(map);
3133 
3134 	return bmap;
3135 error:
3136 	obj.type->free(obj.v);
3137 	return NULL;
3138 }
3139 
basic_set_read(__isl_keep isl_stream * s)3140 static __isl_give isl_basic_set *basic_set_read(__isl_keep isl_stream *s)
3141 {
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;
3153 }
3154 
isl_basic_map_read_from_file(isl_ctx * ctx,FILE * input)3155 __isl_give isl_basic_map *isl_basic_map_read_from_file(isl_ctx *ctx,
3156 	FILE *input)
3157 {
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;
3165 }
3166 
isl_basic_set_read_from_file(isl_ctx * ctx,FILE * input)3167 __isl_give isl_basic_set *isl_basic_set_read_from_file(isl_ctx *ctx,
3168 	FILE *input)
3169 {
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;
3177 }
3178 
isl_basic_map_read_from_str(isl_ctx * ctx,const char * str)3179 __isl_give isl_basic_map *isl_basic_map_read_from_str(isl_ctx *ctx,
3180 	const char *str)
3181 {
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;
3189 }
3190 
isl_basic_set_read_from_str(isl_ctx * ctx,const char * str)3191 __isl_give isl_basic_set *isl_basic_set_read_from_str(isl_ctx *ctx,
3192 	const char *str)
3193 {
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;
3201 }
3202 
isl_map_read_from_file(struct isl_ctx * ctx,FILE * input)3203 __isl_give isl_map *isl_map_read_from_file(struct isl_ctx *ctx,
3204 	FILE *input)
3205 {
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;
3213 }
3214 
isl_map_read_from_str(struct isl_ctx * ctx,const char * str)3215 __isl_give isl_map *isl_map_read_from_str(struct isl_ctx *ctx,
3216 	const char *str)
3217 {
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;
3225 }
3226 
isl_set_read_from_file(struct isl_ctx * ctx,FILE * input)3227 __isl_give isl_set *isl_set_read_from_file(struct isl_ctx *ctx,
3228 	FILE *input)
3229 {
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;
3237 }
3238 
isl_set_read_from_str(isl_ctx * ctx,const char * str)3239 __isl_give isl_set *isl_set_read_from_str(isl_ctx *ctx, const char *str)
3240 {
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;
3248 }
3249 
isl_union_map_read_from_file(isl_ctx * ctx,FILE * input)3250 __isl_give isl_union_map *isl_union_map_read_from_file(isl_ctx *ctx,
3251 	FILE *input)
3252 {
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;
3260 }
3261 
isl_union_map_read_from_str(struct isl_ctx * ctx,const char * str)3262 __isl_give isl_union_map *isl_union_map_read_from_str(struct isl_ctx *ctx,
3263 		const char *str)
3264 {
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;
3272 }
3273 
isl_union_set_read_from_file(isl_ctx * ctx,FILE * input)3274 __isl_give isl_union_set *isl_union_set_read_from_file(isl_ctx *ctx,
3275 	FILE *input)
3276 {
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;
3284 }
3285 
isl_union_set_read_from_str(struct isl_ctx * ctx,const char * str)3286 __isl_give isl_union_set *isl_union_set_read_from_str(struct isl_ctx *ctx,
3287 		const char *str)
3288 {
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;
3296 }
3297 
isl_vec_read_polylib(__isl_keep isl_stream * s)3298 static __isl_give isl_vec *isl_vec_read_polylib(__isl_keep isl_stream *s)
3299 {
3300 	struct isl_vec *vec = NULL;
3301 	struct isl_token *tok;
3302 	unsigned size;
3303 	int j;
3304 
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;
3309 	}
3310 
3311 	size = isl_int_get_si(tok->u.v);
3312 	isl_token_free(tok);
3313 
3314 	vec = isl_vec_alloc(s->ctx, size);
3315 
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;
3321 		}
3322 		isl_int_set(vec->el[j], tok->u.v);
3323 		isl_token_free(tok);
3324 	}
3325 
3326 	return vec;
3327 error:
3328 	isl_token_free(tok);
3329 	isl_vec_free(vec);
3330 	return NULL;
3331 }
3332 
vec_read(__isl_keep isl_stream * s)3333 static __isl_give isl_vec *vec_read(__isl_keep isl_stream *s)
3334 {
3335 	return isl_vec_read_polylib(s);
3336 }
3337 
isl_vec_read_from_file(isl_ctx * ctx,FILE * input)3338 __isl_give isl_vec *isl_vec_read_from_file(isl_ctx *ctx, FILE *input)
3339 {
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;
3347 }
3348 
isl_stream_read_pw_qpolynomial(__isl_keep isl_stream * s)3349 __isl_give isl_pw_qpolynomial *isl_stream_read_pw_qpolynomial(
3350 	__isl_keep isl_stream *s)
3351 {
3352 	struct isl_obj obj;
3353 
3354 	obj = obj_read(s);
3355 	if (obj.v)
3356 		isl_assert(s->ctx, obj.type == isl_obj_pw_qpolynomial,
3357 			   goto error);
3358 
3359 	return obj.v;
3360 error:
3361 	obj.type->free(obj.v);
3362 	return NULL;
3363 }
3364 
isl_pw_qpolynomial_read_from_str(isl_ctx * ctx,const char * str)3365 __isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_read_from_str(isl_ctx *ctx,
3366 		const char *str)
3367 {
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;
3375 }
3376 
isl_pw_qpolynomial_read_from_file(isl_ctx * ctx,FILE * input)3377 __isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_read_from_file(isl_ctx *ctx,
3378 		FILE *input)
3379 {
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;
3387 }
3388 
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.
3392  */
isl_stream_read_pw_qpolynomial_fold(__isl_keep isl_stream * s)3393 __isl_give isl_pw_qpolynomial_fold *isl_stream_read_pw_qpolynomial_fold(
3394 	__isl_keep isl_stream *s)
3395 {
3396 	struct isl_obj obj;
3397 
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);
3401 
3402 	return obj.v;
3403 error:
3404 	obj.type->free(obj.v);
3405 	return NULL;
3406 }
3407 
3408 /* Read an isl_pw_qpolynomial_fold from "str".
3409  */
isl_pw_qpolynomial_fold_read_from_str(isl_ctx * ctx,const char * str)3410 __isl_give isl_pw_qpolynomial_fold *isl_pw_qpolynomial_fold_read_from_str(
3411 	isl_ctx *ctx, const char *str)
3412 {
3413 	isl_pw_qpolynomial_fold *pwqp;
3414 	isl_stream *s;
3415 
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);
3421 
3422 	return pwqp;
3423 }
3424 
3425 /* Is the next token an identifier not in "v"?
3426  */
next_is_fresh_ident(__isl_keep isl_stream * s,struct vars * v)3427 static int next_is_fresh_ident(__isl_keep isl_stream *s, struct vars *v)
3428 {
3429 	int n = v->n;
3430 	int fresh;
3431 	struct isl_token *tok;
3432 
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);
3438 
3439 	vars_drop(v, v->n - n);
3440 
3441 	return fresh;
3442 }
3443 
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.
3455  */
read_aff_domain(__isl_keep isl_stream * s,__isl_take isl_set * dom,struct vars * v)3456 static __isl_give isl_set *read_aff_domain(__isl_keep isl_stream *s,
3457 	__isl_take isl_set *dom, struct vars *v)
3458 {
3459 	struct isl_token *tok, *tok2;
3460 	int is_empty;
3461 
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);
3466 	}
3467 	if (!tok || tok->type != '[') {
3468 		isl_stream_error(s, tok, "expecting '['");
3469 		goto error;
3470 	}
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);
3480 
3481 	return dom;
3482 error:
3483 	if (tok)
3484 		isl_stream_push_token(s, tok);
3485 	isl_set_free(dom);
3486 	return NULL;
3487 }
3488 
3489 /* Read an affine expression from "s".
3490  */
isl_stream_read_aff(__isl_keep isl_stream * s)3491 __isl_give isl_aff *isl_stream_read_aff(__isl_keep isl_stream *s)
3492 {
3493 	isl_aff *aff;
3494 	isl_multi_aff *ma;
3495 	isl_size dim;
3496 
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);
3505 
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;
3512 }
3513 
3514 /* Read a piecewise affine expression from "s" with domain (space) "dom".
3515  */
read_pw_aff_with_dom(__isl_keep isl_stream * s,__isl_take isl_set * dom,struct vars * v)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)
3518 {
3519 	isl_pw_aff *pwaff = NULL;
3520 
3521 	if (!isl_set_is_params(dom) && isl_stream_eat(s, ISL_TOKEN_TO))
3522 		goto error;
3523 
3524 	if (isl_stream_eat(s, '['))
3525 		goto error;
3526 
3527 	pwaff = accept_affine(s, isl_set_get_space(dom), v);
3528 
3529 	if (isl_stream_eat(s, ']'))
3530 		goto error;
3531 
3532 	dom = read_optional_formula(s, dom, v, 0);
3533 	pwaff = isl_pw_aff_intersect_domain(pwaff, dom);
3534 
3535 	return pwaff;
3536 error:
3537 	isl_set_free(dom);
3538 	isl_pw_aff_free(pwaff);
3539 	return NULL;
3540 }
3541 
isl_stream_read_pw_aff(__isl_keep isl_stream * s)3542 __isl_give isl_pw_aff *isl_stream_read_pw_aff(__isl_keep isl_stream *s)
3543 {
3544 	struct vars *v;
3545 	isl_set *dom = NULL;
3546 	isl_set *aff_dom;
3547 	isl_pw_aff *pa = NULL;
3548 	int n;
3549 
3550 	v = vars_new(s->ctx);
3551 	if (!v)
3552 		return NULL;
3553 
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;
3559 	}
3560 	if (isl_stream_eat(s, '{'))
3561 		goto error;
3562 
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);
3567 
3568 	while (isl_stream_eat_if_available(s, ';')) {
3569 		isl_pw_aff *pa_i;
3570 
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);
3575 
3576 		pa = isl_pw_aff_union_add(pa, pa_i);
3577 	}
3578 
3579 	if (isl_stream_eat(s, '}'))
3580 		goto error;
3581 
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;
3590 }
3591 
isl_aff_read_from_str(isl_ctx * ctx,const char * str)3592 __isl_give isl_aff *isl_aff_read_from_str(isl_ctx *ctx, const char *str)
3593 {
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;
3601 }
3602 
isl_pw_aff_read_from_str(isl_ctx * ctx,const char * str)3603 __isl_give isl_pw_aff *isl_pw_aff_read_from_str(isl_ctx *ctx, const char *str)
3604 {
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;
3612 }
3613 
3614 /* Extract an isl_multi_pw_aff with domain space "dom_space"
3615  * from a tuple "tuple" read by read_tuple.
3616  *
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.
3628  */
extract_mpa_from_tuple(__isl_take isl_space * dom_space,__isl_keep isl_multi_pw_aff * tuple)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)
3631 {
3632 	int i;
3633 	isl_size dim, n;
3634 	isl_space *space;
3635 	isl_multi_pw_aff *mpa;
3636 
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);
3648 
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));
3660 		}
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);
3665 	}
3666 
3667 	return mpa;
3668 }
3669 
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.
3673  *
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.
3682  */
read_conditional_multi_aff(__isl_keep isl_stream * s,__isl_take isl_set * dom,struct vars * v)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)
3685 {
3686 	isl_multi_pw_aff *tuple;
3687 	isl_multi_pw_aff *mpa;
3688 	isl_pw_multi_aff *pma;
3689 	int n = v->n;
3690 
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;
3700 	}
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);
3705 
3706 	dom = read_optional_formula(s, dom, v, 0);
3707 
3708 	vars_drop(v, v->n - n);
3709 
3710 	pma = isl_pw_multi_aff_from_multi_pw_aff(mpa);
3711 	pma = isl_pw_multi_aff_intersect_domain(pma, dom);
3712 
3713 	return pma;
3714 error:
3715 	isl_set_free(dom);
3716 	return NULL;
3717 }
3718 
3719 /* Read an isl_union_pw_multi_aff from "s".
3720  *
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.
3724  */
isl_stream_read_union_pw_multi_aff(__isl_keep isl_stream * s)3725 __isl_give isl_union_pw_multi_aff *isl_stream_read_union_pw_multi_aff(
3726 	__isl_keep isl_stream *s)
3727 {
3728 	struct vars *v;
3729 	isl_set *dom;
3730 	isl_union_pw_multi_aff *upma = NULL;
3731 
3732 	v = vars_new(s->ctx);
3733 	if (!v)
3734 		return NULL;
3735 
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;
3741 	}
3742 	if (isl_stream_eat(s, '{'))
3743 		goto error;
3744 
3745 	upma = isl_union_pw_multi_aff_empty(isl_set_get_space(dom));
3746 
3747 	do {
3748 		isl_pw_multi_aff *pma;
3749 		isl_union_pw_multi_aff *upma2;
3750 
3751 		if (isl_stream_next_token_is(s, '}'))
3752 			break;
3753 
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, ';'));
3760 
3761 	if (isl_stream_eat(s, '}'))
3762 		goto error;
3763 
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;
3772 }
3773 
3774 /* Read an isl_pw_multi_aff from "s".
3775  *
3776  * Read a more generic isl_union_pw_multi_aff first and
3777  * then check that the result lives in a single space.
3778  */
isl_stream_read_pw_multi_aff(__isl_keep isl_stream * s)3779 __isl_give isl_pw_multi_aff *isl_stream_read_pw_multi_aff(
3780 	__isl_keep isl_stream *s)
3781 {
3782 	isl_bool single_space;
3783 	isl_union_pw_multi_aff *upma;
3784 
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);
3794 }
3795 
isl_pw_multi_aff_read_from_str(isl_ctx * ctx,const char * str)3796 __isl_give isl_pw_multi_aff *isl_pw_multi_aff_read_from_str(isl_ctx *ctx,
3797 	const char *str)
3798 {
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;
3806 }
3807 
3808 /* Read an isl_union_pw_multi_aff from "str".
3809  */
isl_union_pw_multi_aff_read_from_str(isl_ctx * ctx,const char * str)3810 __isl_give isl_union_pw_multi_aff *isl_union_pw_multi_aff_read_from_str(
3811 	isl_ctx *ctx, const char *str)
3812 {
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;
3820 }
3821 
3822 /* Assuming "pa" represents a single affine expression defined on a universe
3823  * domain, extract this affine expression.
3824  */
aff_from_pw_aff(__isl_take isl_pw_aff * pa)3825 static __isl_give isl_aff *aff_from_pw_aff(__isl_take isl_pw_aff *pa)
3826 {
3827 	isl_aff *aff;
3828 
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);
3839 
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;
3846 }
3847 
3848 #undef BASE
3849 #define BASE val
3850 
3851 #include <isl_multi_read_no_explicit_domain_templ.c>
3852 
3853 #undef BASE
3854 #define BASE id
3855 
3856 #include <isl_multi_read_no_explicit_domain_templ.c>
3857 
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.
3865  */
isl_stream_read_multi_aff(__isl_keep isl_stream * s)3866 __isl_give isl_multi_aff *isl_stream_read_multi_aff(__isl_keep isl_stream *s)
3867 {
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;
3875 
3876 	v = vars_new(s->ctx);
3877 	if (!v)
3878 		return NULL;
3879 
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;
3885 	}
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;
3891 
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;
3899 
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;
3913 	}
3914 
3915 	if (isl_stream_eat(s, '}'))
3916 		goto error;
3917 
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);
3930 
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);
3942 		}
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);
3947 	}
3948 
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;
3959 }
3960 
isl_multi_aff_read_from_str(isl_ctx * ctx,const char * str)3961 __isl_give isl_multi_aff *isl_multi_aff_read_from_str(isl_ctx *ctx,
3962 	const char *str)
3963 {
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;
3971 }
3972 
3973 /* Read an isl_multi_pw_aff from "s".
3974  *
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.
3981  *
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.
3990  */
isl_stream_read_multi_pw_aff(__isl_keep isl_stream * s)3991 __isl_give isl_multi_pw_aff *isl_stream_read_multi_pw_aff(
3992 	__isl_keep isl_stream *s)
3993 {
3994 	struct vars *v;
3995 	isl_set *dom = NULL;
3996 	isl_multi_pw_aff *tuple = NULL;
3997 	isl_multi_pw_aff *mpa = NULL;
3998 
3999 	v = vars_new(s->ctx);
4000 	if (!v)
4001 		return NULL;
4002 
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;
4008 	}
4009 	if (isl_stream_eat(s, '{'))
4010 		goto error;
4011 
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;
4021 	}
4022 
4023 	if (isl_stream_eat_if_available(s, ':'))
4024 		dom = read_formula(s, v, dom, 0);
4025 
4026 	if (isl_stream_eat(s, '}'))
4027 		goto error;
4028 
4029 	mpa = extract_mpa_from_tuple(isl_set_get_space(dom), tuple);
4030 
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;
4041 }
4042 
4043 /* Read an isl_multi_pw_aff from "str".
4044  */
isl_multi_pw_aff_read_from_str(isl_ctx * ctx,const char * str)4045 __isl_give isl_multi_pw_aff *isl_multi_pw_aff_read_from_str(isl_ctx *ctx,
4046 	const char *str)
4047 {
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;
4055 }
4056 
4057 /* Read the body of an isl_union_pw_aff from "s" with parameter domain "dom".
4058  */
read_union_pw_aff_with_dom(__isl_keep isl_stream * s,__isl_take isl_set * dom,struct vars * v)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)
4061 {
4062 	isl_pw_aff *pa;
4063 	isl_union_pw_aff *upa = NULL;
4064 	isl_set *aff_dom;
4065 	int n;
4066 
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);
4071 
4072 	upa = isl_union_pw_aff_from_pw_aff(pa);
4073 
4074 	while (isl_stream_eat_if_available(s, ';')) {
4075 		isl_pw_aff *pa_i;
4076 		isl_union_pw_aff *upa_i;
4077 
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);
4082 
4083 		upa_i = isl_union_pw_aff_from_pw_aff(pa_i);
4084 		upa = isl_union_pw_aff_union_add(upa, upa_i);
4085 	}
4086 
4087 	isl_set_free(dom);
4088 	return upa;
4089 }
4090 
4091 /* Read an isl_union_pw_aff from "s".
4092  *
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.
4096  */
isl_stream_read_union_pw_aff(__isl_keep isl_stream * s)4097 __isl_give isl_union_pw_aff *isl_stream_read_union_pw_aff(
4098 	__isl_keep isl_stream *s)
4099 {
4100 	struct vars *v;
4101 	isl_set *dom;
4102 	isl_union_pw_aff *upa = NULL;
4103 
4104 	v = vars_new(s->ctx);
4105 	if (!v)
4106 		return NULL;
4107 
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;
4113 	}
4114 	if (isl_stream_eat(s, '{'))
4115 		goto error;
4116 
4117 	upa = read_union_pw_aff_with_dom(s, isl_set_copy(dom), v);
4118 
4119 	if (isl_stream_eat(s, '}'))
4120 		goto error;
4121 
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;
4130 }
4131 
4132 /* Read an isl_union_pw_aff from "str".
4133  */
isl_union_pw_aff_read_from_str(isl_ctx * ctx,const char * str)4134 __isl_give isl_union_pw_aff *isl_union_pw_aff_read_from_str(isl_ctx *ctx,
4135 	const char *str)
4136 {
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;
4144 }
4145 
4146 /* This function is called for each element in a tuple inside
4147  * isl_stream_read_multi_union_pw_aff.
4148  *
4149  * Read a '{', the union piecewise affine expression body and a '}' and
4150  * add the isl_union_pw_aff to *list.
4151  */
read_union_pw_aff_el(__isl_keep isl_stream * s,struct vars * v,__isl_take isl_space * space,int rational,void * user)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)
4154 {
4155 	isl_set *dom;
4156 	isl_union_pw_aff *upa;
4157 	isl_union_pw_aff_list **list = (isl_union_pw_aff_list **) user;
4158 
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);
4172 }
4173 
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 "->"?
4177  */
next_is_empty_tuple(__isl_keep isl_stream * s)4178 static int next_is_empty_tuple(__isl_keep isl_stream *s)
4179 {
4180 	struct isl_token *tok, *tok2, *tok3;
4181 	int is_empty_tuple = 0;
4182 
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;
4189 	}
4190 
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);
4197 	}
4198 	if (tok2)
4199 		isl_stream_push_token(s, tok2);
4200 	isl_stream_push_token(s, tok);
4201 
4202 	return is_empty_tuple;
4203 }
4204 
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?
4208  */
next_is_param_tuple(__isl_keep isl_stream * s)4209 static int next_is_param_tuple(__isl_keep isl_stream *s)
4210 {
4211 	struct isl_token *tok, *tok2;
4212 	int is_tuple;
4213 
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;
4220 	}
4221 
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);
4227 
4228 	return is_tuple;
4229 }
4230 
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".
4236  *
4237  * The body is of the form
4238  *
4239  *	[{ [..] : ... ; [..] : ... }, { [..] : ... ; [..] : ... }]
4240  *
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.
4244  */
read_multi_union_pw_aff_body_core(__isl_keep isl_stream * s,struct vars * v,__isl_take isl_space * space)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)
4247 {
4248 	isl_union_pw_aff_list *list;
4249 	isl_multi_union_pw_aff *mupa;
4250 
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);
4255 
4256 	return mupa;
4257 }
4258 
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".
4263  *
4264  * First read a generic disjunction of object bodies and then try and extract
4265  * an isl_union_set from that.
4266  */
read_union_set_body(__isl_keep isl_stream * s,struct vars * v,__isl_take isl_space * space)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)
4269 {
4270 	struct isl_obj obj = { isl_obj_set, NULL };
4271 	isl_map *map;
4272 
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);
4280 
4281 	return extract_union_set(s->ctx, obj);
4282 error:
4283 	obj.type->free(obj.v);
4284 	isl_map_free(map);
4285 	return NULL;
4286 }
4287 
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".
4292  *
4293  * In particular, handle the special case with shared domain constraints.
4294  * These are specified as
4295  *
4296  *	([...] : ...)
4297  *
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.
4302  */
read_multi_union_pw_aff_body(__isl_keep isl_stream * s,struct vars * v,__isl_take isl_space * space)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)
4305 {
4306 	isl_multi_union_pw_aff *mupa;
4307 
4308 	if (!isl_stream_next_token_is(s, '('))
4309 		return read_multi_union_pw_aff_body_core(s, v, space);
4310 
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;
4316 
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);
4321 	}
4322 	if (isl_stream_eat(s, ')') < 0)
4323 		return isl_multi_union_pw_aff_free(mupa);
4324 
4325 	return mupa;
4326 error:
4327 	isl_space_free(space);
4328 	return NULL;
4329 }
4330 
4331 /* Read an isl_multi_union_pw_aff from "s".
4332  *
4333  * The input has the form
4334  *
4335  *	[{ [..] : ... ; [..] : ... }, { [..] : ... ; [..] : ... }]
4336  *
4337  * or
4338  *
4339  *	[..] -> [{ [..] : ... ; [..] : ... }, { [..] : ... ; [..] : ... }]
4340  *
4341  * Additionally, a shared domain may be specified as
4342  *
4343  *	([..] : ...)
4344  *
4345  * or
4346  *
4347  *	[..] -> ([..] : ...)
4348  *
4349  * The first case is handled by the caller, the second case
4350  * is handled by read_multi_union_pw_aff_body.
4351  *
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.
4355  */
read_multi_union_pw_aff_core(__isl_keep isl_stream * s)4356 static __isl_give isl_multi_union_pw_aff *read_multi_union_pw_aff_core(
4357 	__isl_keep isl_stream *s)
4358 {
4359 	struct vars *v;
4360 	isl_set *dom = NULL;
4361 	isl_space *space;
4362 	isl_multi_union_pw_aff *mupa = NULL;
4363 
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);
4371 	}
4372 
4373 	v = vars_new(s->ctx);
4374 	if (!v)
4375 		return NULL;
4376 
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;
4382 	}
4383 	space = isl_set_get_space(dom);
4384 	isl_set_free(dom);
4385 	mupa = read_multi_union_pw_aff_body(s, v, space);
4386 
4387 	vars_free(v);
4388 
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;
4395 }
4396 
4397 /* Read an isl_multi_union_pw_aff from "s".
4398  *
4399  * In particular, handle the special case with shared domain constraints.
4400  * These are specified as
4401  *
4402  *	([...] : ...)
4403  *
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.
4408  */
isl_stream_read_multi_union_pw_aff(__isl_keep isl_stream * s)4409 __isl_give isl_multi_union_pw_aff *isl_stream_read_multi_union_pw_aff(
4410 	__isl_keep isl_stream *s)
4411 {
4412 	isl_multi_union_pw_aff *mupa;
4413 
4414 	if (!isl_stream_next_token_is(s, '('))
4415 		return read_multi_union_pw_aff_core(s);
4416 
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;
4422 
4423 		dom = isl_stream_read_union_set(s);
4424 		mupa = isl_multi_union_pw_aff_intersect_domain(mupa, dom);
4425 	}
4426 	if (isl_stream_eat(s, ')') < 0)
4427 		return isl_multi_union_pw_aff_free(mupa);
4428 	return mupa;
4429 }
4430 
4431 /* Read an isl_multi_union_pw_aff from "str".
4432  */
isl_multi_union_pw_aff_read_from_str(isl_ctx * ctx,const char * str)4433 __isl_give isl_multi_union_pw_aff *isl_multi_union_pw_aff_read_from_str(
4434 	isl_ctx *ctx, const char *str)
4435 {
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;
4443 }
4444 
isl_stream_read_union_pw_qpolynomial(__isl_keep isl_stream * s)4445 __isl_give isl_union_pw_qpolynomial *isl_stream_read_union_pw_qpolynomial(
4446 	__isl_keep isl_stream *s)
4447 {
4448 	struct isl_obj obj;
4449 
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);
4454 	}
4455 	if (obj.v)
4456 		isl_assert(s->ctx, obj.type == isl_obj_union_pw_qpolynomial,
4457 			   goto error);
4458 
4459 	return obj.v;
4460 error:
4461 	obj.type->free(obj.v);
4462 	return NULL;
4463 }
4464 
isl_union_pw_qpolynomial_read_from_str(isl_ctx * ctx,const char * str)4465 __isl_give isl_union_pw_qpolynomial *isl_union_pw_qpolynomial_read_from_str(
4466 	isl_ctx *ctx, const char *str)
4467 {
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;
4475 }
4476