isl_id_to_id.c: add missing include
[isl.git] / isl_schedule_read.c
blobeafc7208e08462447293ddefbfec75f5c264226c
1 #include <isl/val.h>
2 #include <isl/schedule.h>
3 #include <isl/stream.h>
4 #include <isl_schedule_private.h>
5 #include <isl_schedule_tree.h>
7 /* An enumeration of the various keys that may appear in a YAML mapping
8 * of a schedule.
9 */
10 enum isl_schedule_key {
11 isl_schedule_key_error = -1,
12 isl_schedule_key_child,
13 isl_schedule_key_coincident,
14 isl_schedule_key_context,
15 isl_schedule_key_contraction,
16 isl_schedule_key_domain,
17 isl_schedule_key_expansion,
18 isl_schedule_key_extension,
19 isl_schedule_key_filter,
20 isl_schedule_key_guard,
21 isl_schedule_key_leaf,
22 isl_schedule_key_mark,
23 isl_schedule_key_options,
24 isl_schedule_key_permutable,
25 isl_schedule_key_schedule,
26 isl_schedule_key_sequence,
27 isl_schedule_key_set,
28 isl_schedule_key_end
31 /* Textual representations of the YAML keys for an isl_schedule object.
33 static char *key_str[] = {
34 [isl_schedule_key_child] = "child",
35 [isl_schedule_key_coincident] = "coincident",
36 [isl_schedule_key_context] = "context",
37 [isl_schedule_key_contraction] = "contraction",
38 [isl_schedule_key_domain] = "domain",
39 [isl_schedule_key_expansion] = "expansion",
40 [isl_schedule_key_extension] = "extension",
41 [isl_schedule_key_filter] = "filter",
42 [isl_schedule_key_guard] = "guard",
43 [isl_schedule_key_leaf] = "leaf",
44 [isl_schedule_key_mark] = "mark",
45 [isl_schedule_key_options] = "options",
46 [isl_schedule_key_permutable] = "permutable",
47 [isl_schedule_key_schedule] = "schedule",
48 [isl_schedule_key_sequence] = "sequence",
49 [isl_schedule_key_set] = "set",
52 #undef KEY
53 #define KEY enum isl_schedule_key
54 #undef KEY_ERROR
55 #define KEY_ERROR isl_schedule_key_error
56 #undef KEY_END
57 #define KEY_END isl_schedule_key_end
58 #include "extract_key.c"
60 static __isl_give isl_schedule_tree *isl_stream_read_schedule_tree(
61 __isl_keep isl_stream *s);
63 /* Read a subtree with context root node from "s".
65 static __isl_give isl_schedule_tree *read_context(__isl_keep isl_stream *s)
67 isl_set *context = NULL;
68 isl_schedule_tree *tree;
69 isl_ctx *ctx;
70 struct isl_token *tok;
71 enum isl_schedule_key key;
72 char *str;
73 int more;
75 ctx = isl_stream_get_ctx(s);
77 key = get_key(s);
79 if (isl_stream_yaml_next(s) < 0)
80 return NULL;
82 tok = isl_stream_next_token(s);
83 if (!tok) {
84 isl_stream_error(s, NULL, "unexpected EOF");
85 return NULL;
87 str = isl_token_get_str(ctx, tok);
88 context = isl_set_read_from_str(ctx, str);
89 free(str);
90 isl_token_free(tok);
92 more = isl_stream_yaml_next(s);
93 if (more < 0)
94 goto error;
95 if (!more) {
96 tree = isl_schedule_tree_from_context(context);
97 } else {
98 key = get_key(s);
99 if (key != isl_schedule_key_child)
100 isl_die(ctx, isl_error_invalid, "expecting child",
101 goto error);
102 if (isl_stream_yaml_next(s) < 0)
103 goto error;
104 tree = isl_stream_read_schedule_tree(s);
105 tree = isl_schedule_tree_insert_context(tree, context);
108 return tree;
109 error:
110 isl_set_free(context);
111 return NULL;
114 /* Read a subtree with domain root node from "s".
116 static __isl_give isl_schedule_tree *read_domain(__isl_keep isl_stream *s)
118 isl_union_set *domain = NULL;
119 isl_schedule_tree *tree;
120 isl_ctx *ctx;
121 struct isl_token *tok;
122 enum isl_schedule_key key;
123 char *str;
124 int more;
126 ctx = isl_stream_get_ctx(s);
128 key = get_key(s);
130 if (isl_stream_yaml_next(s) < 0)
131 return NULL;
133 tok = isl_stream_next_token(s);
134 if (!tok) {
135 isl_stream_error(s, NULL, "unexpected EOF");
136 return NULL;
138 str = isl_token_get_str(ctx, tok);
139 domain = isl_union_set_read_from_str(ctx, str);
140 free(str);
141 isl_token_free(tok);
143 more = isl_stream_yaml_next(s);
144 if (more < 0)
145 goto error;
146 if (!more) {
147 tree = isl_schedule_tree_from_domain(domain);
148 } else {
149 key = get_key(s);
150 if (key != isl_schedule_key_child)
151 isl_die(ctx, isl_error_invalid, "expecting child",
152 goto error);
153 if (isl_stream_yaml_next(s) < 0)
154 goto error;
155 tree = isl_stream_read_schedule_tree(s);
156 tree = isl_schedule_tree_insert_domain(tree, domain);
159 return tree;
160 error:
161 isl_union_set_free(domain);
162 return NULL;
165 /* Read a subtree with expansion root node from "s".
167 static __isl_give isl_schedule_tree *read_expansion(isl_stream *s)
169 isl_ctx *ctx;
170 isl_union_pw_multi_aff *contraction = NULL;
171 isl_union_map *expansion = NULL;
172 isl_schedule_tree *tree = NULL;
173 int more;
175 ctx = isl_stream_get_ctx(s);
177 do {
178 struct isl_token *tok;
179 enum isl_schedule_key key;
180 char *str;
182 key = get_key(s);
183 if (isl_stream_yaml_next(s) < 0)
184 goto error;
186 switch (key) {
187 case isl_schedule_key_contraction:
188 isl_union_pw_multi_aff_free(contraction);
189 tok = isl_stream_next_token(s);
190 str = isl_token_get_str(ctx, tok);
191 contraction = isl_union_pw_multi_aff_read_from_str(ctx,
192 str);
193 free(str);
194 isl_token_free(tok);
195 if (!contraction)
196 goto error;
197 break;
198 case isl_schedule_key_expansion:
199 isl_union_map_free(expansion);
200 tok = isl_stream_next_token(s);
201 str = isl_token_get_str(ctx, tok);
202 expansion = isl_union_map_read_from_str(ctx, str);
203 free(str);
204 isl_token_free(tok);
205 if (!expansion)
206 goto error;
207 break;
208 case isl_schedule_key_child:
209 isl_schedule_tree_free(tree);
210 tree = isl_stream_read_schedule_tree(s);
211 if (!tree)
212 goto error;
213 break;
214 default:
215 isl_die(ctx, isl_error_invalid, "unexpected key",
216 goto error);
218 } while ((more = isl_stream_yaml_next(s)) > 0);
220 if (more < 0)
221 goto error;
223 if (!contraction)
224 isl_die(ctx, isl_error_invalid, "missing contraction",
225 goto error);
226 if (!expansion)
227 isl_die(ctx, isl_error_invalid, "missing expansion",
228 goto error);
230 if (!tree)
231 return isl_schedule_tree_from_expansion(contraction, expansion);
232 return isl_schedule_tree_insert_expansion(tree, contraction, expansion);
233 error:
234 isl_schedule_tree_free(tree);
235 isl_union_pw_multi_aff_free(contraction);
236 isl_union_map_free(expansion);
237 return NULL;
240 /* Read a subtree with extension root node from "s".
242 static __isl_give isl_schedule_tree *read_extension(isl_stream *s)
244 isl_union_map *extension = NULL;
245 isl_schedule_tree *tree;
246 isl_ctx *ctx;
247 struct isl_token *tok;
248 enum isl_schedule_key key;
249 char *str;
250 int more;
252 ctx = isl_stream_get_ctx(s);
254 key = get_key(s);
256 if (isl_stream_yaml_next(s) < 0)
257 return NULL;
259 tok = isl_stream_next_token(s);
260 if (!tok) {
261 isl_stream_error(s, NULL, "unexpected EOF");
262 return NULL;
264 str = isl_token_get_str(ctx, tok);
265 extension = isl_union_map_read_from_str(ctx, str);
266 free(str);
267 isl_token_free(tok);
269 more = isl_stream_yaml_next(s);
270 if (more < 0)
271 goto error;
272 if (!more) {
273 tree = isl_schedule_tree_from_extension(extension);
274 } else {
275 key = get_key(s);
276 if (key != isl_schedule_key_child)
277 isl_die(ctx, isl_error_invalid, "expecting child",
278 goto error);
279 if (isl_stream_yaml_next(s) < 0)
280 goto error;
281 tree = isl_stream_read_schedule_tree(s);
282 tree = isl_schedule_tree_insert_extension(tree, extension);
285 return tree;
286 error:
287 isl_union_map_free(extension);
288 return NULL;
291 /* Read a subtree with filter root node from "s".
293 static __isl_give isl_schedule_tree *read_filter(__isl_keep isl_stream *s)
295 isl_union_set *filter = NULL;
296 isl_schedule_tree *tree;
297 isl_ctx *ctx;
298 struct isl_token *tok;
299 enum isl_schedule_key key;
300 char *str;
301 int more;
303 ctx = isl_stream_get_ctx(s);
305 key = get_key(s);
307 if (isl_stream_yaml_next(s) < 0)
308 return NULL;
310 tok = isl_stream_next_token(s);
311 if (!tok) {
312 isl_stream_error(s, NULL, "unexpected EOF");
313 return NULL;
315 str = isl_token_get_str(ctx, tok);
316 filter = isl_union_set_read_from_str(ctx, str);
317 free(str);
318 isl_token_free(tok);
320 more = isl_stream_yaml_next(s);
321 if (more < 0)
322 goto error;
323 if (!more) {
324 tree = isl_schedule_tree_from_filter(filter);
325 } else {
326 key = get_key(s);
327 if (key != isl_schedule_key_child)
328 isl_die(ctx, isl_error_invalid, "expecting child",
329 goto error);
330 if (isl_stream_yaml_next(s) < 0)
331 goto error;
332 tree = isl_stream_read_schedule_tree(s);
333 tree = isl_schedule_tree_insert_filter(tree, filter);
336 return tree;
337 error:
338 isl_union_set_free(filter);
339 return NULL;
342 /* Read a subtree with guard root node from "s".
344 static __isl_give isl_schedule_tree *read_guard(isl_stream *s)
346 isl_set *guard = NULL;
347 isl_schedule_tree *tree;
348 isl_ctx *ctx;
349 struct isl_token *tok;
350 enum isl_schedule_key key;
351 char *str;
352 int more;
354 ctx = isl_stream_get_ctx(s);
356 key = get_key(s);
358 if (isl_stream_yaml_next(s) < 0)
359 return NULL;
361 tok = isl_stream_next_token(s);
362 if (!tok) {
363 isl_stream_error(s, NULL, "unexpected EOF");
364 return NULL;
366 str = isl_token_get_str(ctx, tok);
367 guard = isl_set_read_from_str(ctx, str);
368 free(str);
369 isl_token_free(tok);
371 more = isl_stream_yaml_next(s);
372 if (more < 0)
373 goto error;
374 if (!more) {
375 tree = isl_schedule_tree_from_guard(guard);
376 } else {
377 key = get_key(s);
378 if (key != isl_schedule_key_child)
379 isl_die(ctx, isl_error_invalid, "expecting child",
380 goto error);
381 if (isl_stream_yaml_next(s) < 0)
382 goto error;
383 tree = isl_stream_read_schedule_tree(s);
384 tree = isl_schedule_tree_insert_guard(tree, guard);
387 return tree;
388 error:
389 isl_set_free(guard);
390 return NULL;
393 /* Read a subtree with mark root node from "s".
395 static __isl_give isl_schedule_tree *read_mark(isl_stream *s)
397 isl_id *mark;
398 isl_schedule_tree *tree;
399 isl_ctx *ctx;
400 struct isl_token *tok;
401 enum isl_schedule_key key;
402 char *str;
403 int more;
405 ctx = isl_stream_get_ctx(s);
407 key = get_key(s);
409 if (isl_stream_yaml_next(s) < 0)
410 return NULL;
412 tok = isl_stream_next_token(s);
413 if (!tok) {
414 isl_stream_error(s, NULL, "unexpected EOF");
415 return NULL;
417 str = isl_token_get_str(ctx, tok);
418 mark = isl_id_alloc(ctx, str, NULL);
419 free(str);
420 isl_token_free(tok);
422 more = isl_stream_yaml_next(s);
423 if (more < 0)
424 goto error;
425 if (!more) {
426 isl_die(ctx, isl_error_invalid, "expecting child",
427 goto error);
428 } else {
429 key = get_key(s);
430 if (key != isl_schedule_key_child)
431 isl_die(ctx, isl_error_invalid, "expecting child",
432 goto error);
433 if (isl_stream_yaml_next(s) < 0)
434 goto error;
435 tree = isl_stream_read_schedule_tree(s);
436 tree = isl_schedule_tree_insert_mark(tree, mark);
439 return tree;
440 error:
441 isl_id_free(mark);
442 return NULL;
445 /* Read a sequence of integers from "s" (representing the coincident
446 * property of a band node).
448 static __isl_give isl_val_list *read_coincident(__isl_keep isl_stream *s)
450 isl_ctx *ctx;
451 isl_val_list *list;
452 int more;
454 ctx = isl_stream_get_ctx(s);
456 if (isl_stream_yaml_read_start_sequence(s) < 0)
457 return NULL;
459 list = isl_val_list_alloc(ctx, 0);
460 while ((more = isl_stream_yaml_next(s)) > 0) {
461 isl_val *val;
463 val = isl_stream_read_val(s);
464 list = isl_val_list_add(list, val);
467 if (more < 0 || isl_stream_yaml_read_end_sequence(s))
468 list = isl_val_list_free(list);
470 return list;
473 /* Set the (initial) coincident properties of "band" according to
474 * the (initial) elements of "coincident".
476 static __isl_give isl_schedule_band *set_coincident(
477 __isl_take isl_schedule_band *band, __isl_take isl_val_list *coincident)
479 int i;
480 int n, m;
482 n = isl_schedule_band_n_member(band);
483 m = isl_val_list_n_val(coincident);
485 for (i = 0; i < n && i < m; ++i) {
486 isl_val *v;
488 v = isl_val_list_get_val(coincident, i);
489 if (!v)
490 band = isl_schedule_band_free(band);
491 band = isl_schedule_band_member_set_coincident(band, i,
492 !isl_val_is_zero(v));
493 isl_val_free(v);
495 isl_val_list_free(coincident);
496 return band;
499 /* Read a subtree with band root node from "s".
501 static __isl_give isl_schedule_tree *read_band(isl_stream *s)
503 isl_multi_union_pw_aff *schedule = NULL;
504 isl_schedule_tree *tree = NULL;
505 isl_val_list *coincident = NULL;
506 isl_union_set *options = NULL;
507 isl_ctx *ctx;
508 isl_schedule_band *band;
509 int permutable = 0;
510 int more;
512 ctx = isl_stream_get_ctx(s);
514 do {
515 struct isl_token *tok;
516 enum isl_schedule_key key;
517 char *str;
518 isl_val *v;
520 key = get_key(s);
521 if (isl_stream_yaml_next(s) < 0)
522 goto error;
524 switch (key) {
525 case isl_schedule_key_schedule:
526 schedule = isl_multi_union_pw_aff_free(schedule);
527 tok = isl_stream_next_token(s);
528 if (!tok) {
529 isl_stream_error(s, NULL, "unexpected EOF");
530 goto error;
532 str = isl_token_get_str(ctx, tok);
533 schedule = isl_multi_union_pw_aff_read_from_str(ctx,
534 str);
535 free(str);
536 isl_token_free(tok);
537 if (!schedule)
538 goto error;
539 break;
540 case isl_schedule_key_coincident:
541 coincident = read_coincident(s);
542 if (!coincident)
543 goto error;
544 break;
545 case isl_schedule_key_permutable:
546 v = isl_stream_read_val(s);
547 permutable = !isl_val_is_zero(v);
548 isl_val_free(v);
549 break;
550 case isl_schedule_key_options:
551 isl_union_set_free(options);
552 tok = isl_stream_next_token(s);
553 str = isl_token_get_str(ctx, tok);
554 options = isl_union_set_read_from_str(ctx, str);
555 free(str);
556 isl_token_free(tok);
557 if (!options)
558 goto error;
559 break;
560 case isl_schedule_key_child:
561 isl_schedule_tree_free(tree);
562 tree = isl_stream_read_schedule_tree(s);
563 if (!tree)
564 goto error;
565 break;
566 default:
567 isl_die(ctx, isl_error_invalid, "unexpected key",
568 goto error);
570 } while ((more = isl_stream_yaml_next(s)) > 0);
572 if (more < 0)
573 goto error;
575 if (!schedule)
576 isl_die(ctx, isl_error_invalid, "missing schedule", goto error);
578 band = isl_schedule_band_from_multi_union_pw_aff(schedule);
579 band = isl_schedule_band_set_permutable(band, permutable);
580 if (coincident)
581 band = set_coincident(band, coincident);
582 if (options)
583 band = isl_schedule_band_set_ast_build_options(band, options);
584 if (tree)
585 tree = isl_schedule_tree_insert_band(tree, band);
586 else
587 tree = isl_schedule_tree_from_band(band);
589 return tree;
590 error:
591 isl_val_list_free(coincident);
592 isl_union_set_free(options);
593 isl_schedule_tree_free(tree);
594 isl_multi_union_pw_aff_free(schedule);
595 return NULL;
598 /* Read a subtree with root node of type "type" from "s".
599 * The node is represented by a sequence of children.
601 static __isl_give isl_schedule_tree *read_children(isl_stream *s,
602 enum isl_schedule_node_type type)
604 isl_ctx *ctx;
605 isl_schedule_tree_list *list;
606 int more;
608 ctx = isl_stream_get_ctx(s);
610 isl_token_free(isl_stream_next_token(s));
612 if (isl_stream_yaml_next(s) < 0)
613 return NULL;
615 if (isl_stream_yaml_read_start_sequence(s))
616 return NULL;
618 list = isl_schedule_tree_list_alloc(ctx, 0);
619 while ((more = isl_stream_yaml_next(s)) > 0) {
620 isl_schedule_tree *tree;
622 tree = isl_stream_read_schedule_tree(s);
623 list = isl_schedule_tree_list_add(list, tree);
626 if (more < 0 || isl_stream_yaml_read_end_sequence(s))
627 list = isl_schedule_tree_list_free(list);
629 return isl_schedule_tree_from_children(type, list);
632 /* Read a subtree with sequence root node from "s".
634 static __isl_give isl_schedule_tree *read_sequence(isl_stream *s)
636 return read_children(s, isl_schedule_node_sequence);
639 /* Read a subtree with set root node from "s".
641 static __isl_give isl_schedule_tree *read_set(isl_stream *s)
643 return read_children(s, isl_schedule_node_set);
646 /* Read a schedule (sub)tree from "s".
648 * We first determine the type of the root node based on the first
649 * mapping key and then hand over to a function tailored to reading
650 * nodes of this type.
652 static __isl_give isl_schedule_tree *isl_stream_read_schedule_tree(
653 struct isl_stream *s)
655 enum isl_schedule_key key;
656 struct isl_token *tok;
657 isl_schedule_tree *tree = NULL;
658 int more;
660 if (isl_stream_yaml_read_start_mapping(s))
661 return NULL;
662 more = isl_stream_yaml_next(s);
663 if (more < 0)
664 return NULL;
665 if (!more) {
666 isl_stream_error(s, NULL, "missing key");
667 return NULL;
670 tok = isl_stream_next_token(s);
671 key = extract_key(s, tok);
672 isl_stream_push_token(s, tok);
673 if (key < 0)
674 return NULL;
675 switch (key) {
676 case isl_schedule_key_context:
677 tree = read_context(s);
678 break;
679 case isl_schedule_key_domain:
680 tree = read_domain(s);
681 break;
682 case isl_schedule_key_contraction:
683 case isl_schedule_key_expansion:
684 tree = read_expansion(s);
685 break;
686 case isl_schedule_key_extension:
687 tree = read_extension(s);
688 break;
689 case isl_schedule_key_filter:
690 tree = read_filter(s);
691 break;
692 case isl_schedule_key_guard:
693 tree = read_guard(s);
694 break;
695 case isl_schedule_key_leaf:
696 isl_token_free(isl_stream_next_token(s));
697 tree = isl_schedule_tree_leaf(isl_stream_get_ctx(s));
698 break;
699 case isl_schedule_key_mark:
700 tree = read_mark(s);
701 break;
702 case isl_schedule_key_sequence:
703 tree = read_sequence(s);
704 break;
705 case isl_schedule_key_set:
706 tree = read_set(s);
707 break;
708 case isl_schedule_key_schedule:
709 case isl_schedule_key_coincident:
710 case isl_schedule_key_options:
711 case isl_schedule_key_permutable:
712 tree = read_band(s);
713 break;
714 case isl_schedule_key_child:
715 isl_die(isl_stream_get_ctx(s), isl_error_unsupported,
716 "cannot identity node type", return NULL);
717 case isl_schedule_key_end:
718 case isl_schedule_key_error:
719 return NULL;
722 if (isl_stream_yaml_read_end_mapping(s) < 0) {
723 isl_stream_error(s, NULL, "unexpected extra elements");
724 return isl_schedule_tree_free(tree);
727 return tree;
730 /* Read an isl_schedule from "s".
732 __isl_give isl_schedule *isl_stream_read_schedule(isl_stream *s)
734 isl_ctx *ctx;
735 isl_schedule_tree *tree;
737 if (!s)
738 return NULL;
740 ctx = isl_stream_get_ctx(s);
741 tree = isl_stream_read_schedule_tree(s);
742 return isl_schedule_from_schedule_tree(ctx, tree);
745 /* Read an isl_schedule from "input".
747 __isl_give isl_schedule *isl_schedule_read_from_file(isl_ctx *ctx, FILE *input)
749 struct isl_stream *s;
750 isl_schedule *schedule;
752 s = isl_stream_new_file(ctx, input);
753 if (!s)
754 return NULL;
755 schedule = isl_stream_read_schedule(s);
756 isl_stream_free(s);
758 return schedule;
761 /* Read an isl_schedule from "str".
763 __isl_give isl_schedule *isl_schedule_read_from_str(isl_ctx *ctx,
764 const char *str)
766 struct isl_stream *s;
767 isl_schedule *schedule;
769 s = isl_stream_new_str(ctx, str);
770 if (!s)
771 return NULL;
772 schedule = isl_stream_read_schedule(s);
773 isl_stream_free(s);
775 return schedule;