extract out shared isl_pw_*_union_opt_cmp
[isl.git] / isl_schedule_read.c
blob5409a49c7a3109f1359b07d3e3cdc5c5929154a5
1 #include <string.h>
3 #include <isl/schedule.h>
4 #include <isl/stream.h>
5 #include <isl_schedule_private.h>
6 #include <isl_schedule_tree.h>
8 /* An enumeration of the various keys that may appear in a YAML mapping
9 * of a schedule.
11 enum isl_schedule_key {
12 isl_schedule_key_error = -1,
13 isl_schedule_key_child,
14 isl_schedule_key_coincident,
15 isl_schedule_key_context,
16 isl_schedule_key_contraction,
17 isl_schedule_key_domain,
18 isl_schedule_key_expansion,
19 isl_schedule_key_extension,
20 isl_schedule_key_filter,
21 isl_schedule_key_guard,
22 isl_schedule_key_leaf,
23 isl_schedule_key_mark,
24 isl_schedule_key_options,
25 isl_schedule_key_permutable,
26 isl_schedule_key_schedule,
27 isl_schedule_key_sequence,
28 isl_schedule_key_set
31 /* Extract a mapping key from the token "tok".
32 * Return isl_schedule_key_error on error, i.e., if "tok" does not
33 * correspond to any known key.
35 static enum isl_schedule_key extract_key(__isl_keep isl_stream *s,
36 struct isl_token *tok)
38 int type;
39 char *name;
40 enum isl_schedule_key key;
41 isl_ctx *ctx;
43 ctx = isl_stream_get_ctx(s);
44 type = isl_token_get_type(tok);
45 if (type != ISL_TOKEN_IDENT && type != ISL_TOKEN_STRING) {
46 isl_stream_error(s, tok, "expecting key");
47 return isl_schedule_key_error;
49 name = isl_token_get_str(ctx, tok);
50 if (!strcmp(name, "child"))
51 key = isl_schedule_key_child;
52 else if (!strcmp(name, "coincident"))
53 key = isl_schedule_key_coincident;
54 else if (!strcmp(name, "context"))
55 key = isl_schedule_key_context;
56 else if (!strcmp(name, "contraction"))
57 key = isl_schedule_key_contraction;
58 else if (!strcmp(name, "domain"))
59 key = isl_schedule_key_domain;
60 else if (!strcmp(name, "expansion"))
61 key = isl_schedule_key_expansion;
62 else if (!strcmp(name, "extension"))
63 key = isl_schedule_key_extension;
64 else if (!strcmp(name, "filter"))
65 key = isl_schedule_key_filter;
66 else if (!strcmp(name, "guard"))
67 key = isl_schedule_key_guard;
68 else if (!strcmp(name, "leaf"))
69 key = isl_schedule_key_leaf;
70 else if (!strcmp(name, "mark"))
71 key = isl_schedule_key_mark;
72 else if (!strcmp(name, "options"))
73 key = isl_schedule_key_options;
74 else if (!strcmp(name, "schedule"))
75 key = isl_schedule_key_schedule;
76 else if (!strcmp(name, "sequence"))
77 key = isl_schedule_key_sequence;
78 else if (!strcmp(name, "set"))
79 key = isl_schedule_key_set;
80 else if (!strcmp(name, "permutable"))
81 key = isl_schedule_key_permutable;
82 else
83 isl_die(ctx, isl_error_invalid, "unknown key",
84 key = isl_schedule_key_error);
85 free(name);
86 return key;
89 /* Read a key from "s" and return the corresponding enum.
90 * Return isl_schedule_key_error on error, i.e., if the first token
91 * on the stream does not correspond to any known key.
93 static enum isl_schedule_key get_key(__isl_keep isl_stream *s)
95 struct isl_token *tok;
96 enum isl_schedule_key key;
98 tok = isl_stream_next_token(s);
99 key = extract_key(s, tok);
100 isl_token_free(tok);
102 return key;
105 static __isl_give isl_schedule_tree *isl_stream_read_schedule_tree(
106 __isl_keep isl_stream *s);
108 /* Read a subtree with context root node from "s".
110 static __isl_give isl_schedule_tree *read_context(__isl_keep isl_stream *s)
112 isl_set *context = NULL;
113 isl_schedule_tree *tree;
114 isl_ctx *ctx;
115 struct isl_token *tok;
116 enum isl_schedule_key key;
117 char *str;
118 int more;
120 ctx = isl_stream_get_ctx(s);
122 key = get_key(s);
124 if (isl_stream_yaml_next(s) < 0)
125 return NULL;
127 tok = isl_stream_next_token(s);
128 if (!tok) {
129 isl_stream_error(s, NULL, "unexpected EOF");
130 return NULL;
132 str = isl_token_get_str(ctx, tok);
133 context = isl_set_read_from_str(ctx, str);
134 free(str);
135 isl_token_free(tok);
137 more = isl_stream_yaml_next(s);
138 if (more < 0)
139 goto error;
140 if (!more) {
141 tree = isl_schedule_tree_from_context(context);
142 } else {
143 key = get_key(s);
144 if (key != isl_schedule_key_child)
145 isl_die(ctx, isl_error_invalid, "expecting child",
146 goto error);
147 if (isl_stream_yaml_next(s) < 0)
148 goto error;
149 tree = isl_stream_read_schedule_tree(s);
150 tree = isl_schedule_tree_insert_context(tree, context);
153 return tree;
154 error:
155 isl_set_free(context);
156 return NULL;
159 /* Read a subtree with domain root node from "s".
161 static __isl_give isl_schedule_tree *read_domain(__isl_keep isl_stream *s)
163 isl_union_set *domain = NULL;
164 isl_schedule_tree *tree;
165 isl_ctx *ctx;
166 struct isl_token *tok;
167 enum isl_schedule_key key;
168 char *str;
169 int more;
171 ctx = isl_stream_get_ctx(s);
173 key = get_key(s);
175 if (isl_stream_yaml_next(s) < 0)
176 return NULL;
178 tok = isl_stream_next_token(s);
179 if (!tok) {
180 isl_stream_error(s, NULL, "unexpected EOF");
181 return NULL;
183 str = isl_token_get_str(ctx, tok);
184 domain = isl_union_set_read_from_str(ctx, str);
185 free(str);
186 isl_token_free(tok);
188 more = isl_stream_yaml_next(s);
189 if (more < 0)
190 goto error;
191 if (!more) {
192 tree = isl_schedule_tree_from_domain(domain);
193 } else {
194 key = get_key(s);
195 if (key != isl_schedule_key_child)
196 isl_die(ctx, isl_error_invalid, "expecting child",
197 goto error);
198 if (isl_stream_yaml_next(s) < 0)
199 goto error;
200 tree = isl_stream_read_schedule_tree(s);
201 tree = isl_schedule_tree_insert_domain(tree, domain);
204 return tree;
205 error:
206 isl_union_set_free(domain);
207 return NULL;
210 /* Read a subtree with expansion root node from "s".
212 static __isl_give isl_schedule_tree *read_expansion(isl_stream *s)
214 isl_ctx *ctx;
215 isl_union_pw_multi_aff *contraction = NULL;
216 isl_union_map *expansion = NULL;
217 isl_schedule_tree *tree = NULL;
218 int more;
220 ctx = isl_stream_get_ctx(s);
222 do {
223 struct isl_token *tok;
224 enum isl_schedule_key key;
225 char *str;
227 key = get_key(s);
228 if (isl_stream_yaml_next(s) < 0)
229 goto error;
231 switch (key) {
232 case isl_schedule_key_contraction:
233 isl_union_pw_multi_aff_free(contraction);
234 tok = isl_stream_next_token(s);
235 str = isl_token_get_str(ctx, tok);
236 contraction = isl_union_pw_multi_aff_read_from_str(ctx,
237 str);
238 free(str);
239 isl_token_free(tok);
240 if (!contraction)
241 goto error;
242 break;
243 case isl_schedule_key_expansion:
244 isl_union_map_free(expansion);
245 tok = isl_stream_next_token(s);
246 str = isl_token_get_str(ctx, tok);
247 expansion = isl_union_map_read_from_str(ctx, str);
248 free(str);
249 isl_token_free(tok);
250 if (!expansion)
251 goto error;
252 break;
253 case isl_schedule_key_child:
254 isl_schedule_tree_free(tree);
255 tree = isl_stream_read_schedule_tree(s);
256 if (!tree)
257 goto error;
258 break;
259 default:
260 isl_die(ctx, isl_error_invalid, "unexpected key",
261 goto error);
263 } while ((more = isl_stream_yaml_next(s)) > 0);
265 if (more < 0)
266 goto error;
268 if (!contraction)
269 isl_die(ctx, isl_error_invalid, "missing contraction",
270 goto error);
271 if (!expansion)
272 isl_die(ctx, isl_error_invalid, "missing expansion",
273 goto error);
275 if (!tree)
276 return isl_schedule_tree_from_expansion(contraction, expansion);
277 return isl_schedule_tree_insert_expansion(tree, contraction, expansion);
278 error:
279 isl_schedule_tree_free(tree);
280 isl_union_pw_multi_aff_free(contraction);
281 isl_union_map_free(expansion);
282 return NULL;
285 /* Read a subtree with extension root node from "s".
287 static __isl_give isl_schedule_tree *read_extension(isl_stream *s)
289 isl_union_map *extension = NULL;
290 isl_schedule_tree *tree;
291 isl_ctx *ctx;
292 struct isl_token *tok;
293 enum isl_schedule_key key;
294 char *str;
295 int more;
297 ctx = isl_stream_get_ctx(s);
299 key = get_key(s);
301 if (isl_stream_yaml_next(s) < 0)
302 return NULL;
304 tok = isl_stream_next_token(s);
305 if (!tok) {
306 isl_stream_error(s, NULL, "unexpected EOF");
307 return NULL;
309 str = isl_token_get_str(ctx, tok);
310 extension = isl_union_map_read_from_str(ctx, str);
311 free(str);
312 isl_token_free(tok);
314 more = isl_stream_yaml_next(s);
315 if (more < 0)
316 goto error;
317 if (!more) {
318 tree = isl_schedule_tree_from_extension(extension);
319 } else {
320 key = get_key(s);
321 if (key != isl_schedule_key_child)
322 isl_die(ctx, isl_error_invalid, "expecting child",
323 goto error);
324 if (isl_stream_yaml_next(s) < 0)
325 goto error;
326 tree = isl_stream_read_schedule_tree(s);
327 tree = isl_schedule_tree_insert_extension(tree, extension);
330 return tree;
331 error:
332 isl_union_map_free(extension);
333 return NULL;
336 /* Read a subtree with filter root node from "s".
338 static __isl_give isl_schedule_tree *read_filter(__isl_keep isl_stream *s)
340 isl_union_set *filter = NULL;
341 isl_schedule_tree *tree;
342 isl_ctx *ctx;
343 struct isl_token *tok;
344 enum isl_schedule_key key;
345 char *str;
346 int more;
348 ctx = isl_stream_get_ctx(s);
350 key = get_key(s);
352 if (isl_stream_yaml_next(s) < 0)
353 return NULL;
355 tok = isl_stream_next_token(s);
356 if (!tok) {
357 isl_stream_error(s, NULL, "unexpected EOF");
358 return NULL;
360 str = isl_token_get_str(ctx, tok);
361 filter = isl_union_set_read_from_str(ctx, str);
362 free(str);
363 isl_token_free(tok);
365 more = isl_stream_yaml_next(s);
366 if (more < 0)
367 goto error;
368 if (!more) {
369 tree = isl_schedule_tree_from_filter(filter);
370 } else {
371 key = get_key(s);
372 if (key != isl_schedule_key_child)
373 isl_die(ctx, isl_error_invalid, "expecting child",
374 goto error);
375 if (isl_stream_yaml_next(s) < 0)
376 goto error;
377 tree = isl_stream_read_schedule_tree(s);
378 tree = isl_schedule_tree_insert_filter(tree, filter);
381 return tree;
382 error:
383 isl_union_set_free(filter);
384 return NULL;
387 /* Read a subtree with guard root node from "s".
389 static __isl_give isl_schedule_tree *read_guard(isl_stream *s)
391 isl_set *guard = NULL;
392 isl_schedule_tree *tree;
393 isl_ctx *ctx;
394 struct isl_token *tok;
395 enum isl_schedule_key key;
396 char *str;
397 int more;
399 ctx = isl_stream_get_ctx(s);
401 key = get_key(s);
403 if (isl_stream_yaml_next(s) < 0)
404 return NULL;
406 tok = isl_stream_next_token(s);
407 if (!tok) {
408 isl_stream_error(s, NULL, "unexpected EOF");
409 return NULL;
411 str = isl_token_get_str(ctx, tok);
412 guard = isl_set_read_from_str(ctx, str);
413 free(str);
414 isl_token_free(tok);
416 more = isl_stream_yaml_next(s);
417 if (more < 0)
418 goto error;
419 if (!more) {
420 tree = isl_schedule_tree_from_guard(guard);
421 } else {
422 key = get_key(s);
423 if (key != isl_schedule_key_child)
424 isl_die(ctx, isl_error_invalid, "expecting child",
425 goto error);
426 if (isl_stream_yaml_next(s) < 0)
427 goto error;
428 tree = isl_stream_read_schedule_tree(s);
429 tree = isl_schedule_tree_insert_guard(tree, guard);
432 return tree;
433 error:
434 isl_set_free(guard);
435 return NULL;
438 /* Read a subtree with mark root node from "s".
440 static __isl_give isl_schedule_tree *read_mark(isl_stream *s)
442 isl_id *mark;
443 isl_schedule_tree *tree;
444 isl_ctx *ctx;
445 struct isl_token *tok;
446 enum isl_schedule_key key;
447 char *str;
448 int more;
450 ctx = isl_stream_get_ctx(s);
452 key = get_key(s);
454 if (isl_stream_yaml_next(s) < 0)
455 return NULL;
457 tok = isl_stream_next_token(s);
458 if (!tok) {
459 isl_stream_error(s, NULL, "unexpected EOF");
460 return NULL;
462 str = isl_token_get_str(ctx, tok);
463 mark = isl_id_alloc(ctx, str, NULL);
464 free(str);
465 isl_token_free(tok);
467 more = isl_stream_yaml_next(s);
468 if (more < 0)
469 goto error;
470 if (!more) {
471 isl_die(ctx, isl_error_invalid, "expecting child",
472 goto error);
473 } else {
474 key = get_key(s);
475 if (key != isl_schedule_key_child)
476 isl_die(ctx, isl_error_invalid, "expecting child",
477 goto error);
478 if (isl_stream_yaml_next(s) < 0)
479 goto error;
480 tree = isl_stream_read_schedule_tree(s);
481 tree = isl_schedule_tree_insert_mark(tree, mark);
484 return tree;
485 error:
486 isl_id_free(mark);
487 return NULL;
490 /* Read a sequence of integers from "s" (representing the coincident
491 * property of a band node).
493 static __isl_give isl_val_list *read_coincident(__isl_keep isl_stream *s)
495 isl_ctx *ctx;
496 isl_val_list *list;
497 int more;
499 ctx = isl_stream_get_ctx(s);
501 if (isl_stream_yaml_read_start_sequence(s) < 0)
502 return NULL;
504 list = isl_val_list_alloc(ctx, 0);
505 while ((more = isl_stream_yaml_next(s)) > 0) {
506 isl_val *val;
508 val = isl_stream_read_val(s);
509 list = isl_val_list_add(list, val);
512 if (more < 0 || isl_stream_yaml_read_end_sequence(s))
513 list = isl_val_list_free(list);
515 return list;
518 /* Set the (initial) coincident properties of "band" according to
519 * the (initial) elements of "coincident".
521 static __isl_give isl_schedule_band *set_coincident(
522 __isl_take isl_schedule_band *band, __isl_take isl_val_list *coincident)
524 int i;
525 int n, m;
527 n = isl_schedule_band_n_member(band);
528 m = isl_val_list_n_val(coincident);
530 for (i = 0; i < n && i < m; ++i) {
531 isl_val *v;
533 v = isl_val_list_get_val(coincident, i);
534 if (!v)
535 band = isl_schedule_band_free(band);
536 band = isl_schedule_band_member_set_coincident(band, i,
537 !isl_val_is_zero(v));
538 isl_val_free(v);
540 isl_val_list_free(coincident);
541 return band;
544 /* Read a subtree with band root node from "s".
546 static __isl_give isl_schedule_tree *read_band(isl_stream *s)
548 isl_multi_union_pw_aff *schedule = NULL;
549 isl_schedule_tree *tree = NULL;
550 isl_val_list *coincident = NULL;
551 isl_union_set *options = NULL;
552 isl_ctx *ctx;
553 isl_schedule_band *band;
554 int permutable = 0;
555 int more;
557 ctx = isl_stream_get_ctx(s);
559 do {
560 struct isl_token *tok;
561 enum isl_schedule_key key;
562 char *str;
563 isl_val *v;
565 key = get_key(s);
566 if (isl_stream_yaml_next(s) < 0)
567 goto error;
569 switch (key) {
570 case isl_schedule_key_schedule:
571 isl_multi_union_pw_aff_free(schedule);
572 tok = isl_stream_next_token(s);
573 if (!tok) {
574 isl_stream_error(s, NULL, "unexpected EOF");
575 goto error;
577 str = isl_token_get_str(ctx, tok);
578 schedule = isl_multi_union_pw_aff_read_from_str(ctx,
579 str);
580 free(str);
581 isl_token_free(tok);
582 if (!schedule)
583 goto error;
584 break;
585 case isl_schedule_key_coincident:
586 coincident = read_coincident(s);
587 if (!coincident)
588 goto error;
589 break;
590 case isl_schedule_key_permutable:
591 v = isl_stream_read_val(s);
592 permutable = !isl_val_is_zero(v);
593 isl_val_free(v);
594 break;
595 case isl_schedule_key_options:
596 isl_union_set_free(options);
597 tok = isl_stream_next_token(s);
598 str = isl_token_get_str(ctx, tok);
599 options = isl_union_set_read_from_str(ctx, str);
600 free(str);
601 isl_token_free(tok);
602 if (!options)
603 goto error;
604 break;
605 case isl_schedule_key_child:
606 isl_schedule_tree_free(tree);
607 tree = isl_stream_read_schedule_tree(s);
608 if (!tree)
609 goto error;
610 break;
611 default:
612 isl_die(ctx, isl_error_invalid, "unexpected key",
613 goto error);
615 } while ((more = isl_stream_yaml_next(s)) > 0);
617 if (more < 0)
618 goto error;
620 if (!schedule)
621 isl_die(ctx, isl_error_invalid, "missing schedule", goto error);
623 band = isl_schedule_band_from_multi_union_pw_aff(schedule);
624 band = isl_schedule_band_set_permutable(band, permutable);
625 if (coincident)
626 band = set_coincident(band, coincident);
627 if (options)
628 band = isl_schedule_band_set_ast_build_options(band, options);
629 if (tree)
630 tree = isl_schedule_tree_insert_band(tree, band);
631 else
632 tree = isl_schedule_tree_from_band(band);
634 return tree;
635 error:
636 isl_val_list_free(coincident);
637 isl_union_set_free(options);
638 isl_schedule_tree_free(tree);
639 isl_multi_union_pw_aff_free(schedule);
640 return NULL;
643 /* Read a subtree with root node of type "type" from "s".
644 * The node is represented by a sequence of children.
646 static __isl_give isl_schedule_tree *read_children(isl_stream *s,
647 enum isl_schedule_node_type type)
649 isl_ctx *ctx;
650 isl_schedule_tree_list *list;
651 int more;
653 ctx = isl_stream_get_ctx(s);
655 isl_token_free(isl_stream_next_token(s));
657 if (isl_stream_yaml_next(s) < 0)
658 return NULL;
660 if (isl_stream_yaml_read_start_sequence(s))
661 return NULL;
663 list = isl_schedule_tree_list_alloc(ctx, 0);
664 while ((more = isl_stream_yaml_next(s)) > 0) {
665 isl_schedule_tree *tree;
667 tree = isl_stream_read_schedule_tree(s);
668 list = isl_schedule_tree_list_add(list, tree);
671 if (more < 0 || isl_stream_yaml_read_end_sequence(s))
672 list = isl_schedule_tree_list_free(list);
674 return isl_schedule_tree_from_children(type, list);
677 /* Read a subtree with sequence root node from "s".
679 static __isl_give isl_schedule_tree *read_sequence(isl_stream *s)
681 return read_children(s, isl_schedule_node_sequence);
684 /* Read a subtree with set root node from "s".
686 static __isl_give isl_schedule_tree *read_set(isl_stream *s)
688 return read_children(s, isl_schedule_node_set);
691 /* Read a schedule (sub)tree from "s".
693 * We first determine the type of the root node based on the first
694 * mapping key and then hand over to a function tailored to reading
695 * nodes of this type.
697 static __isl_give isl_schedule_tree *isl_stream_read_schedule_tree(
698 struct isl_stream *s)
700 enum isl_schedule_key key;
701 struct isl_token *tok;
702 isl_schedule_tree *tree = NULL;
703 int more;
705 if (isl_stream_yaml_read_start_mapping(s))
706 return NULL;
707 more = isl_stream_yaml_next(s);
708 if (more < 0)
709 return NULL;
710 if (!more) {
711 isl_stream_error(s, NULL, "missing key");
712 return NULL;
715 tok = isl_stream_next_token(s);
716 key = extract_key(s, tok);
717 isl_stream_push_token(s, tok);
718 if (key < 0)
719 return NULL;
720 switch (key) {
721 case isl_schedule_key_context:
722 tree = read_context(s);
723 break;
724 case isl_schedule_key_domain:
725 tree = read_domain(s);
726 break;
727 case isl_schedule_key_contraction:
728 case isl_schedule_key_expansion:
729 tree = read_expansion(s);
730 break;
731 case isl_schedule_key_extension:
732 tree = read_extension(s);
733 break;
734 case isl_schedule_key_filter:
735 tree = read_filter(s);
736 break;
737 case isl_schedule_key_guard:
738 tree = read_guard(s);
739 break;
740 case isl_schedule_key_leaf:
741 isl_token_free(isl_stream_next_token(s));
742 tree = isl_schedule_tree_leaf(isl_stream_get_ctx(s));
743 break;
744 case isl_schedule_key_mark:
745 tree = read_mark(s);
746 break;
747 case isl_schedule_key_sequence:
748 tree = read_sequence(s);
749 break;
750 case isl_schedule_key_set:
751 tree = read_set(s);
752 break;
753 case isl_schedule_key_schedule:
754 case isl_schedule_key_coincident:
755 case isl_schedule_key_options:
756 case isl_schedule_key_permutable:
757 tree = read_band(s);
758 break;
759 case isl_schedule_key_child:
760 isl_die(isl_stream_get_ctx(s), isl_error_unsupported,
761 "cannot identity node type", return NULL);
762 case isl_schedule_key_error:
763 return NULL;
766 if (isl_stream_yaml_read_end_mapping(s) < 0) {
767 isl_stream_error(s, NULL, "unexpected extra elements");
768 return isl_schedule_tree_free(tree);
771 return tree;
774 /* Read an isl_schedule from "s".
776 __isl_give isl_schedule *isl_stream_read_schedule(isl_stream *s)
778 isl_ctx *ctx;
779 isl_schedule_tree *tree;
781 if (!s)
782 return NULL;
784 ctx = isl_stream_get_ctx(s);
785 tree = isl_stream_read_schedule_tree(s);
786 return isl_schedule_from_schedule_tree(ctx, tree);
789 /* Read an isl_schedule from "input".
791 __isl_give isl_schedule *isl_schedule_read_from_file(isl_ctx *ctx, FILE *input)
793 struct isl_stream *s;
794 isl_schedule *schedule;
796 s = isl_stream_new_file(ctx, input);
797 if (!s)
798 return NULL;
799 schedule = isl_stream_read_schedule(s);
800 isl_stream_free(s);
802 return schedule;
805 /* Read an isl_schedule from "str".
807 __isl_give isl_schedule *isl_schedule_read_from_str(isl_ctx *ctx,
808 const char *str)
810 struct isl_stream *s;
811 isl_schedule *schedule;
813 s = isl_stream_new_str(ctx, str);
814 if (!s)
815 return NULL;
816 schedule = isl_stream_read_schedule(s);
817 isl_stream_free(s);
819 return schedule;