isl_schedule_read.c: extract_key: store key strings in array
[isl.git] / isl_schedule_read.c
blobf801852ee9b9d609c70f384b47bd2d1696772f0f
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,
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 /* Extract a mapping key from the token "tok".
54 * Return isl_schedule_key_error on error, i.e., if "tok" does not
55 * correspond to any known key.
57 static enum isl_schedule_key extract_key(__isl_keep isl_stream *s,
58 struct isl_token *tok)
60 int type;
61 char *name;
62 enum isl_schedule_key key;
63 isl_ctx *ctx;
65 ctx = isl_stream_get_ctx(s);
66 type = isl_token_get_type(tok);
67 if (type != ISL_TOKEN_IDENT && type != ISL_TOKEN_STRING) {
68 isl_stream_error(s, tok, "expecting key");
69 return isl_schedule_key_error;
71 name = isl_token_get_str(ctx, tok);
72 for (key = 0; key < isl_schedule_key_end; ++key) {
73 if (!strcmp(name, key_str[key]))
74 break;
76 free(name);
78 if (key >= isl_schedule_key_end)
79 isl_die(ctx, isl_error_invalid, "unknown key",
80 return isl_schedule_key_error);
81 return key;
84 /* Read a key from "s" and return the corresponding enum.
85 * Return isl_schedule_key_error on error, i.e., if the first token
86 * on the stream does not correspond to any known key.
88 static enum isl_schedule_key get_key(__isl_keep isl_stream *s)
90 struct isl_token *tok;
91 enum isl_schedule_key key;
93 tok = isl_stream_next_token(s);
94 key = extract_key(s, tok);
95 isl_token_free(tok);
97 return key;
100 static __isl_give isl_schedule_tree *isl_stream_read_schedule_tree(
101 __isl_keep isl_stream *s);
103 /* Read a subtree with context root node from "s".
105 static __isl_give isl_schedule_tree *read_context(__isl_keep isl_stream *s)
107 isl_set *context = NULL;
108 isl_schedule_tree *tree;
109 isl_ctx *ctx;
110 struct isl_token *tok;
111 enum isl_schedule_key key;
112 char *str;
113 int more;
115 ctx = isl_stream_get_ctx(s);
117 key = get_key(s);
119 if (isl_stream_yaml_next(s) < 0)
120 return NULL;
122 tok = isl_stream_next_token(s);
123 if (!tok) {
124 isl_stream_error(s, NULL, "unexpected EOF");
125 return NULL;
127 str = isl_token_get_str(ctx, tok);
128 context = isl_set_read_from_str(ctx, str);
129 free(str);
130 isl_token_free(tok);
132 more = isl_stream_yaml_next(s);
133 if (more < 0)
134 goto error;
135 if (!more) {
136 tree = isl_schedule_tree_from_context(context);
137 } else {
138 key = get_key(s);
139 if (key != isl_schedule_key_child)
140 isl_die(ctx, isl_error_invalid, "expecting child",
141 goto error);
142 if (isl_stream_yaml_next(s) < 0)
143 goto error;
144 tree = isl_stream_read_schedule_tree(s);
145 tree = isl_schedule_tree_insert_context(tree, context);
148 return tree;
149 error:
150 isl_set_free(context);
151 return NULL;
154 /* Read a subtree with domain root node from "s".
156 static __isl_give isl_schedule_tree *read_domain(__isl_keep isl_stream *s)
158 isl_union_set *domain = NULL;
159 isl_schedule_tree *tree;
160 isl_ctx *ctx;
161 struct isl_token *tok;
162 enum isl_schedule_key key;
163 char *str;
164 int more;
166 ctx = isl_stream_get_ctx(s);
168 key = get_key(s);
170 if (isl_stream_yaml_next(s) < 0)
171 return NULL;
173 tok = isl_stream_next_token(s);
174 if (!tok) {
175 isl_stream_error(s, NULL, "unexpected EOF");
176 return NULL;
178 str = isl_token_get_str(ctx, tok);
179 domain = isl_union_set_read_from_str(ctx, str);
180 free(str);
181 isl_token_free(tok);
183 more = isl_stream_yaml_next(s);
184 if (more < 0)
185 goto error;
186 if (!more) {
187 tree = isl_schedule_tree_from_domain(domain);
188 } else {
189 key = get_key(s);
190 if (key != isl_schedule_key_child)
191 isl_die(ctx, isl_error_invalid, "expecting child",
192 goto error);
193 if (isl_stream_yaml_next(s) < 0)
194 goto error;
195 tree = isl_stream_read_schedule_tree(s);
196 tree = isl_schedule_tree_insert_domain(tree, domain);
199 return tree;
200 error:
201 isl_union_set_free(domain);
202 return NULL;
205 /* Read a subtree with expansion root node from "s".
207 static __isl_give isl_schedule_tree *read_expansion(isl_stream *s)
209 isl_ctx *ctx;
210 isl_union_pw_multi_aff *contraction = NULL;
211 isl_union_map *expansion = NULL;
212 isl_schedule_tree *tree = NULL;
213 int more;
215 ctx = isl_stream_get_ctx(s);
217 do {
218 struct isl_token *tok;
219 enum isl_schedule_key key;
220 char *str;
222 key = get_key(s);
223 if (isl_stream_yaml_next(s) < 0)
224 goto error;
226 switch (key) {
227 case isl_schedule_key_contraction:
228 isl_union_pw_multi_aff_free(contraction);
229 tok = isl_stream_next_token(s);
230 str = isl_token_get_str(ctx, tok);
231 contraction = isl_union_pw_multi_aff_read_from_str(ctx,
232 str);
233 free(str);
234 isl_token_free(tok);
235 if (!contraction)
236 goto error;
237 break;
238 case isl_schedule_key_expansion:
239 isl_union_map_free(expansion);
240 tok = isl_stream_next_token(s);
241 str = isl_token_get_str(ctx, tok);
242 expansion = isl_union_map_read_from_str(ctx, str);
243 free(str);
244 isl_token_free(tok);
245 if (!expansion)
246 goto error;
247 break;
248 case isl_schedule_key_child:
249 isl_schedule_tree_free(tree);
250 tree = isl_stream_read_schedule_tree(s);
251 if (!tree)
252 goto error;
253 break;
254 default:
255 isl_die(ctx, isl_error_invalid, "unexpected key",
256 goto error);
258 } while ((more = isl_stream_yaml_next(s)) > 0);
260 if (more < 0)
261 goto error;
263 if (!contraction)
264 isl_die(ctx, isl_error_invalid, "missing contraction",
265 goto error);
266 if (!expansion)
267 isl_die(ctx, isl_error_invalid, "missing expansion",
268 goto error);
270 if (!tree)
271 return isl_schedule_tree_from_expansion(contraction, expansion);
272 return isl_schedule_tree_insert_expansion(tree, contraction, expansion);
273 error:
274 isl_schedule_tree_free(tree);
275 isl_union_pw_multi_aff_free(contraction);
276 isl_union_map_free(expansion);
277 return NULL;
280 /* Read a subtree with extension root node from "s".
282 static __isl_give isl_schedule_tree *read_extension(isl_stream *s)
284 isl_union_map *extension = NULL;
285 isl_schedule_tree *tree;
286 isl_ctx *ctx;
287 struct isl_token *tok;
288 enum isl_schedule_key key;
289 char *str;
290 int more;
292 ctx = isl_stream_get_ctx(s);
294 key = get_key(s);
296 if (isl_stream_yaml_next(s) < 0)
297 return NULL;
299 tok = isl_stream_next_token(s);
300 if (!tok) {
301 isl_stream_error(s, NULL, "unexpected EOF");
302 return NULL;
304 str = isl_token_get_str(ctx, tok);
305 extension = isl_union_map_read_from_str(ctx, str);
306 free(str);
307 isl_token_free(tok);
309 more = isl_stream_yaml_next(s);
310 if (more < 0)
311 goto error;
312 if (!more) {
313 tree = isl_schedule_tree_from_extension(extension);
314 } else {
315 key = get_key(s);
316 if (key != isl_schedule_key_child)
317 isl_die(ctx, isl_error_invalid, "expecting child",
318 goto error);
319 if (isl_stream_yaml_next(s) < 0)
320 goto error;
321 tree = isl_stream_read_schedule_tree(s);
322 tree = isl_schedule_tree_insert_extension(tree, extension);
325 return tree;
326 error:
327 isl_union_map_free(extension);
328 return NULL;
331 /* Read a subtree with filter root node from "s".
333 static __isl_give isl_schedule_tree *read_filter(__isl_keep isl_stream *s)
335 isl_union_set *filter = NULL;
336 isl_schedule_tree *tree;
337 isl_ctx *ctx;
338 struct isl_token *tok;
339 enum isl_schedule_key key;
340 char *str;
341 int more;
343 ctx = isl_stream_get_ctx(s);
345 key = get_key(s);
347 if (isl_stream_yaml_next(s) < 0)
348 return NULL;
350 tok = isl_stream_next_token(s);
351 if (!tok) {
352 isl_stream_error(s, NULL, "unexpected EOF");
353 return NULL;
355 str = isl_token_get_str(ctx, tok);
356 filter = isl_union_set_read_from_str(ctx, str);
357 free(str);
358 isl_token_free(tok);
360 more = isl_stream_yaml_next(s);
361 if (more < 0)
362 goto error;
363 if (!more) {
364 tree = isl_schedule_tree_from_filter(filter);
365 } else {
366 key = get_key(s);
367 if (key != isl_schedule_key_child)
368 isl_die(ctx, isl_error_invalid, "expecting child",
369 goto error);
370 if (isl_stream_yaml_next(s) < 0)
371 goto error;
372 tree = isl_stream_read_schedule_tree(s);
373 tree = isl_schedule_tree_insert_filter(tree, filter);
376 return tree;
377 error:
378 isl_union_set_free(filter);
379 return NULL;
382 /* Read a subtree with guard root node from "s".
384 static __isl_give isl_schedule_tree *read_guard(isl_stream *s)
386 isl_set *guard = NULL;
387 isl_schedule_tree *tree;
388 isl_ctx *ctx;
389 struct isl_token *tok;
390 enum isl_schedule_key key;
391 char *str;
392 int more;
394 ctx = isl_stream_get_ctx(s);
396 key = get_key(s);
398 if (isl_stream_yaml_next(s) < 0)
399 return NULL;
401 tok = isl_stream_next_token(s);
402 if (!tok) {
403 isl_stream_error(s, NULL, "unexpected EOF");
404 return NULL;
406 str = isl_token_get_str(ctx, tok);
407 guard = isl_set_read_from_str(ctx, str);
408 free(str);
409 isl_token_free(tok);
411 more = isl_stream_yaml_next(s);
412 if (more < 0)
413 goto error;
414 if (!more) {
415 tree = isl_schedule_tree_from_guard(guard);
416 } else {
417 key = get_key(s);
418 if (key != isl_schedule_key_child)
419 isl_die(ctx, isl_error_invalid, "expecting child",
420 goto error);
421 if (isl_stream_yaml_next(s) < 0)
422 goto error;
423 tree = isl_stream_read_schedule_tree(s);
424 tree = isl_schedule_tree_insert_guard(tree, guard);
427 return tree;
428 error:
429 isl_set_free(guard);
430 return NULL;
433 /* Read a subtree with mark root node from "s".
435 static __isl_give isl_schedule_tree *read_mark(isl_stream *s)
437 isl_id *mark;
438 isl_schedule_tree *tree;
439 isl_ctx *ctx;
440 struct isl_token *tok;
441 enum isl_schedule_key key;
442 char *str;
443 int more;
445 ctx = isl_stream_get_ctx(s);
447 key = get_key(s);
449 if (isl_stream_yaml_next(s) < 0)
450 return NULL;
452 tok = isl_stream_next_token(s);
453 if (!tok) {
454 isl_stream_error(s, NULL, "unexpected EOF");
455 return NULL;
457 str = isl_token_get_str(ctx, tok);
458 mark = isl_id_alloc(ctx, str, NULL);
459 free(str);
460 isl_token_free(tok);
462 more = isl_stream_yaml_next(s);
463 if (more < 0)
464 goto error;
465 if (!more) {
466 isl_die(ctx, isl_error_invalid, "expecting child",
467 goto error);
468 } else {
469 key = get_key(s);
470 if (key != isl_schedule_key_child)
471 isl_die(ctx, isl_error_invalid, "expecting child",
472 goto error);
473 if (isl_stream_yaml_next(s) < 0)
474 goto error;
475 tree = isl_stream_read_schedule_tree(s);
476 tree = isl_schedule_tree_insert_mark(tree, mark);
479 return tree;
480 error:
481 isl_id_free(mark);
482 return NULL;
485 /* Read a sequence of integers from "s" (representing the coincident
486 * property of a band node).
488 static __isl_give isl_val_list *read_coincident(__isl_keep isl_stream *s)
490 isl_ctx *ctx;
491 isl_val_list *list;
492 int more;
494 ctx = isl_stream_get_ctx(s);
496 if (isl_stream_yaml_read_start_sequence(s) < 0)
497 return NULL;
499 list = isl_val_list_alloc(ctx, 0);
500 while ((more = isl_stream_yaml_next(s)) > 0) {
501 isl_val *val;
503 val = isl_stream_read_val(s);
504 list = isl_val_list_add(list, val);
507 if (more < 0 || isl_stream_yaml_read_end_sequence(s))
508 list = isl_val_list_free(list);
510 return list;
513 /* Set the (initial) coincident properties of "band" according to
514 * the (initial) elements of "coincident".
516 static __isl_give isl_schedule_band *set_coincident(
517 __isl_take isl_schedule_band *band, __isl_take isl_val_list *coincident)
519 int i;
520 int n, m;
522 n = isl_schedule_band_n_member(band);
523 m = isl_val_list_n_val(coincident);
525 for (i = 0; i < n && i < m; ++i) {
526 isl_val *v;
528 v = isl_val_list_get_val(coincident, i);
529 if (!v)
530 band = isl_schedule_band_free(band);
531 band = isl_schedule_band_member_set_coincident(band, i,
532 !isl_val_is_zero(v));
533 isl_val_free(v);
535 isl_val_list_free(coincident);
536 return band;
539 /* Read a subtree with band root node from "s".
541 static __isl_give isl_schedule_tree *read_band(isl_stream *s)
543 isl_multi_union_pw_aff *schedule = NULL;
544 isl_schedule_tree *tree = NULL;
545 isl_val_list *coincident = NULL;
546 isl_union_set *options = NULL;
547 isl_ctx *ctx;
548 isl_schedule_band *band;
549 int permutable = 0;
550 int more;
552 ctx = isl_stream_get_ctx(s);
554 do {
555 struct isl_token *tok;
556 enum isl_schedule_key key;
557 char *str;
558 isl_val *v;
560 key = get_key(s);
561 if (isl_stream_yaml_next(s) < 0)
562 goto error;
564 switch (key) {
565 case isl_schedule_key_schedule:
566 schedule = isl_multi_union_pw_aff_free(schedule);
567 tok = isl_stream_next_token(s);
568 if (!tok) {
569 isl_stream_error(s, NULL, "unexpected EOF");
570 goto error;
572 str = isl_token_get_str(ctx, tok);
573 schedule = isl_multi_union_pw_aff_read_from_str(ctx,
574 str);
575 free(str);
576 isl_token_free(tok);
577 if (!schedule)
578 goto error;
579 break;
580 case isl_schedule_key_coincident:
581 coincident = read_coincident(s);
582 if (!coincident)
583 goto error;
584 break;
585 case isl_schedule_key_permutable:
586 v = isl_stream_read_val(s);
587 permutable = !isl_val_is_zero(v);
588 isl_val_free(v);
589 break;
590 case isl_schedule_key_options:
591 isl_union_set_free(options);
592 tok = isl_stream_next_token(s);
593 str = isl_token_get_str(ctx, tok);
594 options = isl_union_set_read_from_str(ctx, str);
595 free(str);
596 isl_token_free(tok);
597 if (!options)
598 goto error;
599 break;
600 case isl_schedule_key_child:
601 isl_schedule_tree_free(tree);
602 tree = isl_stream_read_schedule_tree(s);
603 if (!tree)
604 goto error;
605 break;
606 default:
607 isl_die(ctx, isl_error_invalid, "unexpected key",
608 goto error);
610 } while ((more = isl_stream_yaml_next(s)) > 0);
612 if (more < 0)
613 goto error;
615 if (!schedule)
616 isl_die(ctx, isl_error_invalid, "missing schedule", goto error);
618 band = isl_schedule_band_from_multi_union_pw_aff(schedule);
619 band = isl_schedule_band_set_permutable(band, permutable);
620 if (coincident)
621 band = set_coincident(band, coincident);
622 if (options)
623 band = isl_schedule_band_set_ast_build_options(band, options);
624 if (tree)
625 tree = isl_schedule_tree_insert_band(tree, band);
626 else
627 tree = isl_schedule_tree_from_band(band);
629 return tree;
630 error:
631 isl_val_list_free(coincident);
632 isl_union_set_free(options);
633 isl_schedule_tree_free(tree);
634 isl_multi_union_pw_aff_free(schedule);
635 return NULL;
638 /* Read a subtree with root node of type "type" from "s".
639 * The node is represented by a sequence of children.
641 static __isl_give isl_schedule_tree *read_children(isl_stream *s,
642 enum isl_schedule_node_type type)
644 isl_ctx *ctx;
645 isl_schedule_tree_list *list;
646 int more;
648 ctx = isl_stream_get_ctx(s);
650 isl_token_free(isl_stream_next_token(s));
652 if (isl_stream_yaml_next(s) < 0)
653 return NULL;
655 if (isl_stream_yaml_read_start_sequence(s))
656 return NULL;
658 list = isl_schedule_tree_list_alloc(ctx, 0);
659 while ((more = isl_stream_yaml_next(s)) > 0) {
660 isl_schedule_tree *tree;
662 tree = isl_stream_read_schedule_tree(s);
663 list = isl_schedule_tree_list_add(list, tree);
666 if (more < 0 || isl_stream_yaml_read_end_sequence(s))
667 list = isl_schedule_tree_list_free(list);
669 return isl_schedule_tree_from_children(type, list);
672 /* Read a subtree with sequence root node from "s".
674 static __isl_give isl_schedule_tree *read_sequence(isl_stream *s)
676 return read_children(s, isl_schedule_node_sequence);
679 /* Read a subtree with set root node from "s".
681 static __isl_give isl_schedule_tree *read_set(isl_stream *s)
683 return read_children(s, isl_schedule_node_set);
686 /* Read a schedule (sub)tree from "s".
688 * We first determine the type of the root node based on the first
689 * mapping key and then hand over to a function tailored to reading
690 * nodes of this type.
692 static __isl_give isl_schedule_tree *isl_stream_read_schedule_tree(
693 struct isl_stream *s)
695 enum isl_schedule_key key;
696 struct isl_token *tok;
697 isl_schedule_tree *tree = NULL;
698 int more;
700 if (isl_stream_yaml_read_start_mapping(s))
701 return NULL;
702 more = isl_stream_yaml_next(s);
703 if (more < 0)
704 return NULL;
705 if (!more) {
706 isl_stream_error(s, NULL, "missing key");
707 return NULL;
710 tok = isl_stream_next_token(s);
711 key = extract_key(s, tok);
712 isl_stream_push_token(s, tok);
713 if (key < 0)
714 return NULL;
715 switch (key) {
716 case isl_schedule_key_context:
717 tree = read_context(s);
718 break;
719 case isl_schedule_key_domain:
720 tree = read_domain(s);
721 break;
722 case isl_schedule_key_contraction:
723 case isl_schedule_key_expansion:
724 tree = read_expansion(s);
725 break;
726 case isl_schedule_key_extension:
727 tree = read_extension(s);
728 break;
729 case isl_schedule_key_filter:
730 tree = read_filter(s);
731 break;
732 case isl_schedule_key_guard:
733 tree = read_guard(s);
734 break;
735 case isl_schedule_key_leaf:
736 isl_token_free(isl_stream_next_token(s));
737 tree = isl_schedule_tree_leaf(isl_stream_get_ctx(s));
738 break;
739 case isl_schedule_key_mark:
740 tree = read_mark(s);
741 break;
742 case isl_schedule_key_sequence:
743 tree = read_sequence(s);
744 break;
745 case isl_schedule_key_set:
746 tree = read_set(s);
747 break;
748 case isl_schedule_key_schedule:
749 case isl_schedule_key_coincident:
750 case isl_schedule_key_options:
751 case isl_schedule_key_permutable:
752 tree = read_band(s);
753 break;
754 case isl_schedule_key_child:
755 isl_die(isl_stream_get_ctx(s), isl_error_unsupported,
756 "cannot identity node type", return NULL);
757 case isl_schedule_key_end:
758 case isl_schedule_key_error:
759 return NULL;
762 if (isl_stream_yaml_read_end_mapping(s) < 0) {
763 isl_stream_error(s, NULL, "unexpected extra elements");
764 return isl_schedule_tree_free(tree);
767 return tree;
770 /* Read an isl_schedule from "s".
772 __isl_give isl_schedule *isl_stream_read_schedule(isl_stream *s)
774 isl_ctx *ctx;
775 isl_schedule_tree *tree;
777 if (!s)
778 return NULL;
780 ctx = isl_stream_get_ctx(s);
781 tree = isl_stream_read_schedule_tree(s);
782 return isl_schedule_from_schedule_tree(ctx, tree);
785 /* Read an isl_schedule from "input".
787 __isl_give isl_schedule *isl_schedule_read_from_file(isl_ctx *ctx, FILE *input)
789 struct isl_stream *s;
790 isl_schedule *schedule;
792 s = isl_stream_new_file(ctx, input);
793 if (!s)
794 return NULL;
795 schedule = isl_stream_read_schedule(s);
796 isl_stream_free(s);
798 return schedule;
801 /* Read an isl_schedule from "str".
803 __isl_give isl_schedule *isl_schedule_read_from_str(isl_ctx *ctx,
804 const char *str)
806 struct isl_stream *s;
807 isl_schedule *schedule;
809 s = isl_stream_new_str(ctx, str);
810 if (!s)
811 return NULL;
812 schedule = isl_stream_read_schedule(s);
813 isl_stream_free(s);
815 return schedule;