isl_test_cpp17-generic.cc: work around std::optional::value issue in older macOS
[isl.git] / isl_schedule_read.c
blobb98b72b7dc76133220d23fc769e062d2061ec383
1 #include <isl/id.h>
2 #include <isl/val.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,
29 isl_schedule_key_end
32 /* Textual representations of the YAML keys for an isl_schedule object.
34 static char *key_str[] = {
35 [isl_schedule_key_child] = "child",
36 [isl_schedule_key_coincident] = "coincident",
37 [isl_schedule_key_context] = "context",
38 [isl_schedule_key_contraction] = "contraction",
39 [isl_schedule_key_domain] = "domain",
40 [isl_schedule_key_expansion] = "expansion",
41 [isl_schedule_key_extension] = "extension",
42 [isl_schedule_key_filter] = "filter",
43 [isl_schedule_key_guard] = "guard",
44 [isl_schedule_key_leaf] = "leaf",
45 [isl_schedule_key_mark] = "mark",
46 [isl_schedule_key_options] = "options",
47 [isl_schedule_key_permutable] = "permutable",
48 [isl_schedule_key_schedule] = "schedule",
49 [isl_schedule_key_sequence] = "sequence",
50 [isl_schedule_key_set] = "set",
53 #undef KEY
54 #define KEY enum isl_schedule_key
55 #undef KEY_ERROR
56 #define KEY_ERROR isl_schedule_key_error
57 #undef KEY_END
58 #define KEY_END isl_schedule_key_end
59 #undef KEY_STR
60 #define KEY_STR key_str
61 #undef KEY_EXTRACT
62 #define KEY_EXTRACT extract_key
63 #undef KEY_GET
64 #define KEY_GET get_key
65 #include "extract_key.c"
67 static __isl_give isl_schedule_tree *isl_stream_read_schedule_tree(
68 __isl_keep isl_stream *s);
70 /* Read a subtree with context root node from "s".
72 static __isl_give isl_schedule_tree *read_context(__isl_keep isl_stream *s)
74 isl_set *context = NULL;
75 isl_schedule_tree *tree;
76 isl_ctx *ctx;
77 struct isl_token *tok;
78 enum isl_schedule_key key;
79 char *str;
80 isl_bool more;
82 ctx = isl_stream_get_ctx(s);
84 key = get_key(s);
86 if (isl_stream_yaml_next(s) < 0)
87 return NULL;
89 tok = isl_stream_next_token(s);
90 if (!tok) {
91 isl_stream_error(s, NULL, "unexpected EOF");
92 return NULL;
94 str = isl_token_get_str(ctx, tok);
95 context = isl_set_read_from_str(ctx, str);
96 free(str);
97 isl_token_free(tok);
99 more = isl_stream_yaml_next(s);
100 if (more < 0)
101 goto error;
102 if (!more) {
103 tree = isl_schedule_tree_from_context(context);
104 } else {
105 key = get_key(s);
106 if (key != isl_schedule_key_child)
107 isl_die(ctx, isl_error_invalid, "expecting child",
108 goto error);
109 if (isl_stream_yaml_next(s) < 0)
110 goto error;
111 tree = isl_stream_read_schedule_tree(s);
112 tree = isl_schedule_tree_insert_context(tree, context);
115 return tree;
116 error:
117 isl_set_free(context);
118 return NULL;
121 /* Read a subtree with domain root node from "s".
123 static __isl_give isl_schedule_tree *read_domain(__isl_keep isl_stream *s)
125 isl_union_set *domain = NULL;
126 isl_schedule_tree *tree;
127 isl_ctx *ctx;
128 struct isl_token *tok;
129 enum isl_schedule_key key;
130 char *str;
131 isl_bool more;
133 ctx = isl_stream_get_ctx(s);
135 key = get_key(s);
137 if (isl_stream_yaml_next(s) < 0)
138 return NULL;
140 tok = isl_stream_next_token(s);
141 if (!tok) {
142 isl_stream_error(s, NULL, "unexpected EOF");
143 return NULL;
145 str = isl_token_get_str(ctx, tok);
146 domain = isl_union_set_read_from_str(ctx, str);
147 free(str);
148 isl_token_free(tok);
150 more = isl_stream_yaml_next(s);
151 if (more < 0)
152 goto error;
153 if (!more) {
154 tree = isl_schedule_tree_from_domain(domain);
155 } else {
156 key = get_key(s);
157 if (key != isl_schedule_key_child)
158 isl_die(ctx, isl_error_invalid, "expecting child",
159 goto error);
160 if (isl_stream_yaml_next(s) < 0)
161 goto error;
162 tree = isl_stream_read_schedule_tree(s);
163 tree = isl_schedule_tree_insert_domain(tree, domain);
166 return tree;
167 error:
168 isl_union_set_free(domain);
169 return NULL;
172 /* Read a subtree with expansion root node from "s".
174 static __isl_give isl_schedule_tree *read_expansion(isl_stream *s)
176 isl_ctx *ctx;
177 isl_union_pw_multi_aff *contraction = NULL;
178 isl_union_map *expansion = NULL;
179 isl_schedule_tree *tree = NULL;
180 isl_bool more;
182 ctx = isl_stream_get_ctx(s);
184 do {
185 struct isl_token *tok;
186 enum isl_schedule_key key;
187 char *str;
189 key = get_key(s);
190 if (isl_stream_yaml_next(s) < 0)
191 goto error;
193 switch (key) {
194 case isl_schedule_key_contraction:
195 isl_union_pw_multi_aff_free(contraction);
196 tok = isl_stream_next_token(s);
197 str = isl_token_get_str(ctx, tok);
198 contraction = isl_union_pw_multi_aff_read_from_str(ctx,
199 str);
200 free(str);
201 isl_token_free(tok);
202 if (!contraction)
203 goto error;
204 break;
205 case isl_schedule_key_expansion:
206 isl_union_map_free(expansion);
207 tok = isl_stream_next_token(s);
208 str = isl_token_get_str(ctx, tok);
209 expansion = isl_union_map_read_from_str(ctx, str);
210 free(str);
211 isl_token_free(tok);
212 if (!expansion)
213 goto error;
214 break;
215 case isl_schedule_key_child:
216 isl_schedule_tree_free(tree);
217 tree = isl_stream_read_schedule_tree(s);
218 if (!tree)
219 goto error;
220 break;
221 default:
222 isl_die(ctx, isl_error_invalid, "unexpected key",
223 goto error);
225 } while ((more = isl_stream_yaml_next(s)) == isl_bool_true);
227 if (more < 0)
228 goto error;
230 if (!contraction)
231 isl_die(ctx, isl_error_invalid, "missing contraction",
232 goto error);
233 if (!expansion)
234 isl_die(ctx, isl_error_invalid, "missing expansion",
235 goto error);
237 if (!tree)
238 return isl_schedule_tree_from_expansion(contraction, expansion);
239 return isl_schedule_tree_insert_expansion(tree, contraction, expansion);
240 error:
241 isl_schedule_tree_free(tree);
242 isl_union_pw_multi_aff_free(contraction);
243 isl_union_map_free(expansion);
244 return NULL;
247 /* Read a subtree with extension root node from "s".
249 static __isl_give isl_schedule_tree *read_extension(isl_stream *s)
251 isl_union_map *extension = NULL;
252 isl_schedule_tree *tree;
253 isl_ctx *ctx;
254 struct isl_token *tok;
255 enum isl_schedule_key key;
256 char *str;
257 isl_bool more;
259 ctx = isl_stream_get_ctx(s);
261 key = get_key(s);
263 if (isl_stream_yaml_next(s) < 0)
264 return NULL;
266 tok = isl_stream_next_token(s);
267 if (!tok) {
268 isl_stream_error(s, NULL, "unexpected EOF");
269 return NULL;
271 str = isl_token_get_str(ctx, tok);
272 extension = isl_union_map_read_from_str(ctx, str);
273 free(str);
274 isl_token_free(tok);
276 more = isl_stream_yaml_next(s);
277 if (more < 0)
278 goto error;
279 if (!more) {
280 tree = isl_schedule_tree_from_extension(extension);
281 } else {
282 key = get_key(s);
283 if (key != isl_schedule_key_child)
284 isl_die(ctx, isl_error_invalid, "expecting child",
285 goto error);
286 if (isl_stream_yaml_next(s) < 0)
287 goto error;
288 tree = isl_stream_read_schedule_tree(s);
289 tree = isl_schedule_tree_insert_extension(tree, extension);
292 return tree;
293 error:
294 isl_union_map_free(extension);
295 return NULL;
298 /* Read a subtree with filter root node from "s".
300 static __isl_give isl_schedule_tree *read_filter(__isl_keep isl_stream *s)
302 isl_union_set *filter = NULL;
303 isl_schedule_tree *tree;
304 isl_ctx *ctx;
305 struct isl_token *tok;
306 enum isl_schedule_key key;
307 char *str;
308 isl_bool more;
310 ctx = isl_stream_get_ctx(s);
312 key = get_key(s);
314 if (isl_stream_yaml_next(s) < 0)
315 return NULL;
317 tok = isl_stream_next_token(s);
318 if (!tok) {
319 isl_stream_error(s, NULL, "unexpected EOF");
320 return NULL;
322 str = isl_token_get_str(ctx, tok);
323 filter = isl_union_set_read_from_str(ctx, str);
324 free(str);
325 isl_token_free(tok);
327 more = isl_stream_yaml_next(s);
328 if (more < 0)
329 goto error;
330 if (!more) {
331 tree = isl_schedule_tree_from_filter(filter);
332 } else {
333 key = get_key(s);
334 if (key != isl_schedule_key_child)
335 isl_die(ctx, isl_error_invalid, "expecting child",
336 goto error);
337 if (isl_stream_yaml_next(s) < 0)
338 goto error;
339 tree = isl_stream_read_schedule_tree(s);
340 tree = isl_schedule_tree_insert_filter(tree, filter);
343 return tree;
344 error:
345 isl_union_set_free(filter);
346 return NULL;
349 /* Read a subtree with guard root node from "s".
351 static __isl_give isl_schedule_tree *read_guard(isl_stream *s)
353 isl_set *guard = NULL;
354 isl_schedule_tree *tree;
355 isl_ctx *ctx;
356 struct isl_token *tok;
357 enum isl_schedule_key key;
358 char *str;
359 isl_bool more;
361 ctx = isl_stream_get_ctx(s);
363 key = get_key(s);
365 if (isl_stream_yaml_next(s) < 0)
366 return NULL;
368 tok = isl_stream_next_token(s);
369 if (!tok) {
370 isl_stream_error(s, NULL, "unexpected EOF");
371 return NULL;
373 str = isl_token_get_str(ctx, tok);
374 guard = isl_set_read_from_str(ctx, str);
375 free(str);
376 isl_token_free(tok);
378 more = isl_stream_yaml_next(s);
379 if (more < 0)
380 goto error;
381 if (!more) {
382 tree = isl_schedule_tree_from_guard(guard);
383 } else {
384 key = get_key(s);
385 if (key != isl_schedule_key_child)
386 isl_die(ctx, isl_error_invalid, "expecting child",
387 goto error);
388 if (isl_stream_yaml_next(s) < 0)
389 goto error;
390 tree = isl_stream_read_schedule_tree(s);
391 tree = isl_schedule_tree_insert_guard(tree, guard);
394 return tree;
395 error:
396 isl_set_free(guard);
397 return NULL;
400 /* Read a subtree with mark root node from "s".
402 static __isl_give isl_schedule_tree *read_mark(isl_stream *s)
404 isl_id *mark;
405 isl_schedule_tree *tree;
406 isl_ctx *ctx;
407 struct isl_token *tok;
408 enum isl_schedule_key key;
409 char *str;
410 isl_bool more;
412 ctx = isl_stream_get_ctx(s);
414 key = get_key(s);
416 if (isl_stream_yaml_next(s) < 0)
417 return NULL;
419 tok = isl_stream_next_token(s);
420 if (!tok) {
421 isl_stream_error(s, NULL, "unexpected EOF");
422 return NULL;
424 str = isl_token_get_str(ctx, tok);
425 mark = isl_id_alloc(ctx, str, NULL);
426 free(str);
427 isl_token_free(tok);
429 more = isl_stream_yaml_next(s);
430 if (more < 0)
431 goto error;
432 if (!more) {
433 isl_die(ctx, isl_error_invalid, "expecting child",
434 goto error);
435 } else {
436 key = get_key(s);
437 if (key != isl_schedule_key_child)
438 isl_die(ctx, isl_error_invalid, "expecting child",
439 goto error);
440 if (isl_stream_yaml_next(s) < 0)
441 goto error;
442 tree = isl_stream_read_schedule_tree(s);
443 tree = isl_schedule_tree_insert_mark(tree, mark);
446 return tree;
447 error:
448 isl_id_free(mark);
449 return NULL;
452 #undef EL_BASE
453 #define EL_BASE val
455 #include <isl_list_read_yaml_templ.c>
457 /* Read a sequence of integers from "s" (representing the coincident
458 * property of a band node).
460 static __isl_give isl_val_list *read_coincident(__isl_keep isl_stream *s)
462 return isl_stream_yaml_read_val_list(s);
465 /* Set the (initial) coincident properties of "band" according to
466 * the (initial) elements of "coincident".
468 static __isl_give isl_schedule_band *set_coincident(
469 __isl_take isl_schedule_band *band, __isl_take isl_val_list *coincident)
471 int i;
472 isl_size n, m;
474 n = isl_schedule_band_n_member(band);
475 m = isl_val_list_n_val(coincident);
476 if (n < 0 || m < 0)
477 band = isl_schedule_band_free(band);
479 for (i = 0; i < n && i < m; ++i) {
480 isl_val *v;
482 v = isl_val_list_get_val(coincident, i);
483 if (!v)
484 band = isl_schedule_band_free(band);
485 band = isl_schedule_band_member_set_coincident(band, i,
486 !isl_val_is_zero(v));
487 isl_val_free(v);
489 isl_val_list_free(coincident);
490 return band;
493 /* Read a subtree with band root node from "s".
495 static __isl_give isl_schedule_tree *read_band(isl_stream *s)
497 isl_multi_union_pw_aff *schedule = NULL;
498 isl_schedule_tree *tree = NULL;
499 isl_val_list *coincident = NULL;
500 isl_union_set *options = NULL;
501 isl_ctx *ctx;
502 isl_schedule_band *band;
503 int permutable = 0;
504 isl_bool more;
506 ctx = isl_stream_get_ctx(s);
508 do {
509 struct isl_token *tok;
510 enum isl_schedule_key key;
511 char *str;
512 isl_val *v;
514 key = get_key(s);
515 if (isl_stream_yaml_next(s) < 0)
516 goto error;
518 switch (key) {
519 case isl_schedule_key_schedule:
520 schedule = isl_multi_union_pw_aff_free(schedule);
521 tok = isl_stream_next_token(s);
522 if (!tok) {
523 isl_stream_error(s, NULL, "unexpected EOF");
524 goto error;
526 str = isl_token_get_str(ctx, tok);
527 schedule = isl_multi_union_pw_aff_read_from_str(ctx,
528 str);
529 free(str);
530 isl_token_free(tok);
531 if (!schedule)
532 goto error;
533 break;
534 case isl_schedule_key_coincident:
535 coincident = read_coincident(s);
536 if (!coincident)
537 goto error;
538 break;
539 case isl_schedule_key_permutable:
540 v = isl_stream_read_val(s);
541 permutable = !isl_val_is_zero(v);
542 isl_val_free(v);
543 break;
544 case isl_schedule_key_options:
545 isl_union_set_free(options);
546 tok = isl_stream_next_token(s);
547 str = isl_token_get_str(ctx, tok);
548 options = isl_union_set_read_from_str(ctx, str);
549 free(str);
550 isl_token_free(tok);
551 if (!options)
552 goto error;
553 break;
554 case isl_schedule_key_child:
555 isl_schedule_tree_free(tree);
556 tree = isl_stream_read_schedule_tree(s);
557 if (!tree)
558 goto error;
559 break;
560 default:
561 isl_die(ctx, isl_error_invalid, "unexpected key",
562 goto error);
564 } while ((more = isl_stream_yaml_next(s)) == isl_bool_true);
566 if (more < 0)
567 goto error;
569 if (!schedule)
570 isl_die(ctx, isl_error_invalid, "missing schedule", goto error);
572 band = isl_schedule_band_from_multi_union_pw_aff(schedule);
573 band = isl_schedule_band_set_permutable(band, permutable);
574 if (coincident)
575 band = set_coincident(band, coincident);
576 if (options)
577 band = isl_schedule_band_set_ast_build_options(band, options);
578 if (tree)
579 tree = isl_schedule_tree_insert_band(tree, band);
580 else
581 tree = isl_schedule_tree_from_band(band);
583 return tree;
584 error:
585 isl_val_list_free(coincident);
586 isl_union_set_free(options);
587 isl_schedule_tree_free(tree);
588 isl_multi_union_pw_aff_free(schedule);
589 return NULL;
592 #undef EL_BASE
593 #define EL_BASE schedule_tree
595 #include <isl_list_read_yaml_templ.c>
597 /* Read a subtree with root node of type "type" from "s".
598 * The node is represented by a sequence of children.
600 static __isl_give isl_schedule_tree *read_children(isl_stream *s,
601 enum isl_schedule_node_type type)
603 isl_schedule_tree_list *list;
605 isl_token_free(isl_stream_next_token(s));
607 if (isl_stream_yaml_next(s) < 0)
608 return NULL;
610 list = isl_stream_yaml_read_schedule_tree_list(s);
612 return isl_schedule_tree_from_children(type, list);
615 /* Read a subtree with sequence root node from "s".
617 static __isl_give isl_schedule_tree *read_sequence(isl_stream *s)
619 return read_children(s, isl_schedule_node_sequence);
622 /* Read a subtree with set root node from "s".
624 static __isl_give isl_schedule_tree *read_set(isl_stream *s)
626 return read_children(s, isl_schedule_node_set);
629 /* Read a schedule (sub)tree from "s".
631 * We first determine the type of the root node based on the first
632 * mapping key and then hand over to a function tailored to reading
633 * nodes of this type.
635 static __isl_give isl_schedule_tree *isl_stream_read_schedule_tree(
636 struct isl_stream *s)
638 enum isl_schedule_key key;
639 struct isl_token *tok;
640 isl_schedule_tree *tree = NULL;
641 isl_bool more;
643 if (isl_stream_yaml_read_start_mapping(s) < 0)
644 return NULL;
645 more = isl_stream_yaml_next(s);
646 if (more < 0)
647 return NULL;
648 if (!more) {
649 isl_stream_error(s, NULL, "missing key");
650 return NULL;
653 tok = isl_stream_next_token(s);
654 key = extract_key(s, tok);
655 isl_stream_push_token(s, tok);
656 if (key < 0)
657 return NULL;
658 switch (key) {
659 case isl_schedule_key_context:
660 tree = read_context(s);
661 break;
662 case isl_schedule_key_domain:
663 tree = read_domain(s);
664 break;
665 case isl_schedule_key_contraction:
666 case isl_schedule_key_expansion:
667 tree = read_expansion(s);
668 break;
669 case isl_schedule_key_extension:
670 tree = read_extension(s);
671 break;
672 case isl_schedule_key_filter:
673 tree = read_filter(s);
674 break;
675 case isl_schedule_key_guard:
676 tree = read_guard(s);
677 break;
678 case isl_schedule_key_leaf:
679 isl_token_free(isl_stream_next_token(s));
680 tree = isl_schedule_tree_leaf(isl_stream_get_ctx(s));
681 break;
682 case isl_schedule_key_mark:
683 tree = read_mark(s);
684 break;
685 case isl_schedule_key_sequence:
686 tree = read_sequence(s);
687 break;
688 case isl_schedule_key_set:
689 tree = read_set(s);
690 break;
691 case isl_schedule_key_schedule:
692 case isl_schedule_key_coincident:
693 case isl_schedule_key_options:
694 case isl_schedule_key_permutable:
695 tree = read_band(s);
696 break;
697 case isl_schedule_key_child:
698 isl_die(isl_stream_get_ctx(s), isl_error_unsupported,
699 "cannot identify node type", return NULL);
700 case isl_schedule_key_end:
701 case isl_schedule_key_error:
702 return NULL;
705 if (isl_stream_yaml_read_end_mapping(s) < 0)
706 return isl_schedule_tree_free(tree);
708 return tree;
711 /* Read an isl_schedule from "s".
713 __isl_give isl_schedule *isl_stream_read_schedule(isl_stream *s)
715 isl_ctx *ctx;
716 isl_schedule_tree *tree;
718 if (!s)
719 return NULL;
721 ctx = isl_stream_get_ctx(s);
722 tree = isl_stream_read_schedule_tree(s);
723 return isl_schedule_from_schedule_tree(ctx, tree);
726 /* Read an isl_schedule from "input".
728 __isl_give isl_schedule *isl_schedule_read_from_file(isl_ctx *ctx, FILE *input)
730 struct isl_stream *s;
731 isl_schedule *schedule;
733 s = isl_stream_new_file(ctx, input);
734 if (!s)
735 return NULL;
736 schedule = isl_stream_read_schedule(s);
737 isl_stream_free(s);
739 return schedule;
742 #undef TYPE_BASE
743 #define TYPE_BASE schedule
744 #include "isl_read_from_str_templ.c"