add isl_schedule_node_get_prefix_schedule_multi_union_pw_aff
[isl.git] / isl_schedule_read.c
blobff51d83a2da75c762cea81caf39230724a0e1471
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_filter,
20 isl_schedule_key_leaf,
21 isl_schedule_key_options,
22 isl_schedule_key_permutable,
23 isl_schedule_key_schedule,
24 isl_schedule_key_sequence,
25 isl_schedule_key_set
28 /* Extract a mapping key from the token "tok".
29 * Return isl_schedule_key_error on error, i.e., if "tok" does not
30 * correspond to any known key.
32 static enum isl_schedule_key extract_key(__isl_keep isl_stream *s,
33 struct isl_token *tok)
35 int type;
36 char *name;
37 enum isl_schedule_key key;
38 isl_ctx *ctx;
40 ctx = isl_stream_get_ctx(s);
41 type = isl_token_get_type(tok);
42 if (type != ISL_TOKEN_IDENT && type != ISL_TOKEN_STRING) {
43 isl_stream_error(s, tok, "expecting key");
44 return isl_schedule_key_error;
46 name = isl_token_get_str(ctx, tok);
47 if (!strcmp(name, "child"))
48 key = isl_schedule_key_child;
49 else if (!strcmp(name, "coincident"))
50 key = isl_schedule_key_coincident;
51 else if (!strcmp(name, "context"))
52 key = isl_schedule_key_context;
53 else if (!strcmp(name, "contraction"))
54 key = isl_schedule_key_contraction;
55 else if (!strcmp(name, "domain"))
56 key = isl_schedule_key_domain;
57 else if (!strcmp(name, "expansion"))
58 key = isl_schedule_key_expansion;
59 else if (!strcmp(name, "filter"))
60 key = isl_schedule_key_filter;
61 else if (!strcmp(name, "leaf"))
62 key = isl_schedule_key_leaf;
63 else if (!strcmp(name, "options"))
64 key = isl_schedule_key_options;
65 else if (!strcmp(name, "schedule"))
66 key = isl_schedule_key_schedule;
67 else if (!strcmp(name, "sequence"))
68 key = isl_schedule_key_sequence;
69 else if (!strcmp(name, "set"))
70 key = isl_schedule_key_set;
71 else if (!strcmp(name, "permutable"))
72 key = isl_schedule_key_permutable;
73 else
74 isl_die(ctx, isl_error_invalid, "unknown key",
75 key = isl_schedule_key_error);
76 free(name);
77 return key;
80 /* Read a key from "s" and return the corresponding enum.
81 * Return isl_schedule_key_error on error, i.e., if the first token
82 * on the stream does not correspond to any known key.
84 static enum isl_schedule_key get_key(__isl_keep isl_stream *s)
86 struct isl_token *tok;
87 enum isl_schedule_key key;
89 tok = isl_stream_next_token(s);
90 key = extract_key(s, tok);
91 isl_token_free(tok);
93 return key;
96 static __isl_give isl_schedule_tree *isl_stream_read_schedule_tree(
97 __isl_keep isl_stream *s);
99 /* Read a subtree with context root node from "s".
101 static __isl_give isl_schedule_tree *read_context(__isl_keep isl_stream *s)
103 isl_set *context = NULL;
104 isl_schedule_tree *tree;
105 isl_ctx *ctx;
106 struct isl_token *tok;
107 enum isl_schedule_key key;
108 char *str;
109 int more;
111 ctx = isl_stream_get_ctx(s);
113 key = get_key(s);
115 if (isl_stream_yaml_next(s) < 0)
116 return NULL;
118 tok = isl_stream_next_token(s);
119 if (!tok) {
120 isl_stream_error(s, NULL, "unexpected EOF");
121 return NULL;
123 str = isl_token_get_str(ctx, tok);
124 context = isl_set_read_from_str(ctx, str);
125 free(str);
126 isl_token_free(tok);
128 more = isl_stream_yaml_next(s);
129 if (more < 0)
130 goto error;
131 if (!more) {
132 tree = isl_schedule_tree_from_context(context);
133 } else {
134 key = get_key(s);
135 if (key != isl_schedule_key_child)
136 isl_die(ctx, isl_error_invalid, "expecting child",
137 goto error);
138 if (isl_stream_yaml_next(s) < 0)
139 goto error;
140 tree = isl_stream_read_schedule_tree(s);
141 tree = isl_schedule_tree_insert_context(tree, context);
144 return tree;
145 error:
146 isl_set_free(context);
147 return NULL;
150 /* Read a subtree with domain root node from "s".
152 static __isl_give isl_schedule_tree *read_domain(__isl_keep isl_stream *s)
154 isl_union_set *domain = NULL;
155 isl_schedule_tree *tree;
156 isl_ctx *ctx;
157 struct isl_token *tok;
158 enum isl_schedule_key key;
159 char *str;
160 int more;
162 ctx = isl_stream_get_ctx(s);
164 key = get_key(s);
166 if (isl_stream_yaml_next(s) < 0)
167 return NULL;
169 tok = isl_stream_next_token(s);
170 if (!tok) {
171 isl_stream_error(s, NULL, "unexpected EOF");
172 return NULL;
174 str = isl_token_get_str(ctx, tok);
175 domain = isl_union_set_read_from_str(ctx, str);
176 free(str);
177 isl_token_free(tok);
179 more = isl_stream_yaml_next(s);
180 if (more < 0)
181 goto error;
182 if (!more) {
183 tree = isl_schedule_tree_from_domain(domain);
184 } else {
185 key = get_key(s);
186 if (key != isl_schedule_key_child)
187 isl_die(ctx, isl_error_invalid, "expecting child",
188 goto error);
189 if (isl_stream_yaml_next(s) < 0)
190 goto error;
191 tree = isl_stream_read_schedule_tree(s);
192 tree = isl_schedule_tree_insert_domain(tree, domain);
195 return tree;
196 error:
197 isl_union_set_free(domain);
198 return NULL;
201 /* Read a subtree with expansion root node from "s".
203 static __isl_give isl_schedule_tree *read_expansion(isl_stream *s)
205 isl_ctx *ctx;
206 isl_union_pw_multi_aff *contraction = NULL;
207 isl_union_map *expansion = NULL;
208 isl_schedule_tree *tree = NULL;
209 int more;
211 ctx = isl_stream_get_ctx(s);
213 do {
214 struct isl_token *tok;
215 enum isl_schedule_key key;
216 char *str;
218 key = get_key(s);
219 if (isl_stream_yaml_next(s) < 0)
220 goto error;
222 switch (key) {
223 case isl_schedule_key_contraction:
224 isl_union_pw_multi_aff_free(contraction);
225 tok = isl_stream_next_token(s);
226 str = isl_token_get_str(ctx, tok);
227 contraction = isl_union_pw_multi_aff_read_from_str(ctx,
228 str);
229 free(str);
230 isl_token_free(tok);
231 if (!contraction)
232 goto error;
233 break;
234 case isl_schedule_key_expansion:
235 isl_union_map_free(expansion);
236 tok = isl_stream_next_token(s);
237 str = isl_token_get_str(ctx, tok);
238 expansion = isl_union_map_read_from_str(ctx, str);
239 free(str);
240 isl_token_free(tok);
241 if (!expansion)
242 goto error;
243 break;
244 case isl_schedule_key_child:
245 isl_schedule_tree_free(tree);
246 tree = isl_stream_read_schedule_tree(s);
247 if (!tree)
248 goto error;
249 break;
250 default:
251 isl_die(ctx, isl_error_invalid, "unexpected key",
252 goto error);
254 } while ((more = isl_stream_yaml_next(s)) > 0);
256 if (more < 0)
257 goto error;
259 if (!contraction)
260 isl_die(ctx, isl_error_invalid, "missing contraction",
261 goto error);
262 if (!expansion)
263 isl_die(ctx, isl_error_invalid, "missing expansion",
264 goto error);
266 if (!tree)
267 return isl_schedule_tree_from_expansion(contraction, expansion);
268 return isl_schedule_tree_insert_expansion(tree, contraction, expansion);
269 error:
270 isl_schedule_tree_free(tree);
271 isl_union_pw_multi_aff_free(contraction);
272 isl_union_map_free(expansion);
273 return NULL;
276 /* Read a subtree with filter root node from "s".
278 static __isl_give isl_schedule_tree *read_filter(__isl_keep isl_stream *s)
280 isl_union_set *filter = NULL;
281 isl_schedule_tree *tree;
282 isl_ctx *ctx;
283 struct isl_token *tok;
284 enum isl_schedule_key key;
285 char *str;
286 int more;
288 ctx = isl_stream_get_ctx(s);
290 key = get_key(s);
292 if (isl_stream_yaml_next(s) < 0)
293 return NULL;
295 tok = isl_stream_next_token(s);
296 if (!tok) {
297 isl_stream_error(s, NULL, "unexpected EOF");
298 return NULL;
300 str = isl_token_get_str(ctx, tok);
301 filter = isl_union_set_read_from_str(ctx, str);
302 free(str);
303 isl_token_free(tok);
305 more = isl_stream_yaml_next(s);
306 if (more < 0)
307 goto error;
308 if (!more) {
309 tree = isl_schedule_tree_from_filter(filter);
310 } else {
311 key = get_key(s);
312 if (key != isl_schedule_key_child)
313 isl_die(ctx, isl_error_invalid, "expecting child",
314 goto error);
315 if (isl_stream_yaml_next(s) < 0)
316 goto error;
317 tree = isl_stream_read_schedule_tree(s);
318 tree = isl_schedule_tree_insert_filter(tree, filter);
321 return tree;
322 error:
323 isl_union_set_free(filter);
324 return NULL;
327 /* Read a sequence of integers from "s" (representing the coincident
328 * property of a band node).
330 static __isl_give isl_val_list *read_coincident(__isl_keep isl_stream *s)
332 isl_ctx *ctx;
333 isl_val_list *list;
334 int more;
336 ctx = isl_stream_get_ctx(s);
338 if (isl_stream_yaml_read_start_sequence(s) < 0)
339 return NULL;
341 list = isl_val_list_alloc(ctx, 0);
342 while ((more = isl_stream_yaml_next(s)) > 0) {
343 isl_val *val;
345 val = isl_stream_read_val(s);
346 list = isl_val_list_add(list, val);
349 if (more < 0 || isl_stream_yaml_read_end_sequence(s))
350 list = isl_val_list_free(list);
352 return list;
355 /* Set the (initial) coincident properties of "band" according to
356 * the (initial) elements of "coincident".
358 static __isl_give isl_schedule_band *set_coincident(
359 __isl_take isl_schedule_band *band, __isl_take isl_val_list *coincident)
361 int i;
362 int n, m;
364 n = isl_schedule_band_n_member(band);
365 m = isl_val_list_n_val(coincident);
367 for (i = 0; i < n && i < m; ++i) {
368 isl_val *v;
370 v = isl_val_list_get_val(coincident, i);
371 if (!v)
372 band = isl_schedule_band_free(band);
373 band = isl_schedule_band_member_set_coincident(band, i,
374 !isl_val_is_zero(v));
375 isl_val_free(v);
377 isl_val_list_free(coincident);
378 return band;
381 /* Read a subtree with band root node from "s".
383 static __isl_give isl_schedule_tree *read_band(isl_stream *s)
385 isl_multi_union_pw_aff *schedule = NULL;
386 isl_schedule_tree *tree = NULL;
387 isl_val_list *coincident = NULL;
388 isl_union_set *options = NULL;
389 isl_ctx *ctx;
390 isl_schedule_band *band;
391 int permutable = 0;
392 int more;
394 ctx = isl_stream_get_ctx(s);
396 do {
397 struct isl_token *tok;
398 enum isl_schedule_key key;
399 char *str;
400 isl_val *v;
402 key = get_key(s);
403 if (isl_stream_yaml_next(s) < 0)
404 goto error;
406 switch (key) {
407 case isl_schedule_key_schedule:
408 isl_multi_union_pw_aff_free(schedule);
409 tok = isl_stream_next_token(s);
410 if (!tok) {
411 isl_stream_error(s, NULL, "unexpected EOF");
412 goto error;
414 str = isl_token_get_str(ctx, tok);
415 schedule = isl_multi_union_pw_aff_read_from_str(ctx,
416 str);
417 free(str);
418 isl_token_free(tok);
419 if (!schedule)
420 goto error;
421 break;
422 case isl_schedule_key_coincident:
423 coincident = read_coincident(s);
424 if (!coincident)
425 goto error;
426 break;
427 case isl_schedule_key_permutable:
428 v = isl_stream_read_val(s);
429 permutable = !isl_val_is_zero(v);
430 isl_val_free(v);
431 break;
432 case isl_schedule_key_options:
433 isl_union_set_free(options);
434 tok = isl_stream_next_token(s);
435 str = isl_token_get_str(ctx, tok);
436 options = isl_union_set_read_from_str(ctx, str);
437 free(str);
438 isl_token_free(tok);
439 if (!options)
440 goto error;
441 break;
442 case isl_schedule_key_child:
443 isl_schedule_tree_free(tree);
444 tree = isl_stream_read_schedule_tree(s);
445 if (!tree)
446 goto error;
447 break;
448 default:
449 isl_die(ctx, isl_error_invalid, "unexpected key",
450 goto error);
452 } while ((more = isl_stream_yaml_next(s)) > 0);
454 if (more < 0)
455 goto error;
457 if (!schedule)
458 isl_die(ctx, isl_error_invalid, "missing schedule", goto error);
460 band = isl_schedule_band_from_multi_union_pw_aff(schedule);
461 band = isl_schedule_band_set_permutable(band, permutable);
462 if (coincident)
463 band = set_coincident(band, coincident);
464 if (options)
465 band = isl_schedule_band_set_ast_build_options(band, options);
466 if (tree)
467 tree = isl_schedule_tree_insert_band(tree, band);
468 else
469 tree = isl_schedule_tree_from_band(band);
471 return tree;
472 error:
473 isl_val_list_free(coincident);
474 isl_union_set_free(options);
475 isl_schedule_tree_free(tree);
476 isl_multi_union_pw_aff_free(schedule);
477 return NULL;
480 /* Read a subtree with root node of type "type" from "s".
481 * The node is represented by a sequence of children.
483 static __isl_give isl_schedule_tree *read_children(isl_stream *s,
484 enum isl_schedule_node_type type)
486 isl_ctx *ctx;
487 isl_schedule_tree_list *list;
488 int more;
490 ctx = isl_stream_get_ctx(s);
492 isl_token_free(isl_stream_next_token(s));
494 if (isl_stream_yaml_next(s) < 0)
495 return NULL;
497 if (isl_stream_yaml_read_start_sequence(s))
498 return NULL;
500 list = isl_schedule_tree_list_alloc(ctx, 0);
501 while ((more = isl_stream_yaml_next(s)) > 0) {
502 isl_schedule_tree *tree;
504 tree = isl_stream_read_schedule_tree(s);
505 list = isl_schedule_tree_list_add(list, tree);
508 if (more < 0 || isl_stream_yaml_read_end_sequence(s))
509 list = isl_schedule_tree_list_free(list);
511 return isl_schedule_tree_from_children(type, list);
514 /* Read a subtree with sequence root node from "s".
516 static __isl_give isl_schedule_tree *read_sequence(isl_stream *s)
518 return read_children(s, isl_schedule_node_sequence);
521 /* Read a subtree with set root node from "s".
523 static __isl_give isl_schedule_tree *read_set(isl_stream *s)
525 return read_children(s, isl_schedule_node_set);
528 /* Read a schedule (sub)tree from "s".
530 * We first determine the type of the root node based on the first
531 * mapping key and then hand over to a function tailored to reading
532 * nodes of this type.
534 static __isl_give isl_schedule_tree *isl_stream_read_schedule_tree(
535 struct isl_stream *s)
537 enum isl_schedule_key key;
538 struct isl_token *tok;
539 isl_schedule_tree *tree = NULL;
540 int more;
542 if (isl_stream_yaml_read_start_mapping(s))
543 return NULL;
544 more = isl_stream_yaml_next(s);
545 if (more < 0)
546 return NULL;
547 if (!more) {
548 isl_stream_error(s, NULL, "missing key");
549 return NULL;
552 tok = isl_stream_next_token(s);
553 key = extract_key(s, tok);
554 isl_stream_push_token(s, tok);
555 if (key < 0)
556 return NULL;
557 switch (key) {
558 case isl_schedule_key_context:
559 tree = read_context(s);
560 break;
561 case isl_schedule_key_domain:
562 tree = read_domain(s);
563 break;
564 case isl_schedule_key_contraction:
565 case isl_schedule_key_expansion:
566 tree = read_expansion(s);
567 break;
568 case isl_schedule_key_filter:
569 tree = read_filter(s);
570 break;
571 case isl_schedule_key_leaf:
572 isl_token_free(isl_stream_next_token(s));
573 tree = isl_schedule_tree_leaf(isl_stream_get_ctx(s));
574 break;
575 case isl_schedule_key_sequence:
576 tree = read_sequence(s);
577 break;
578 case isl_schedule_key_set:
579 tree = read_set(s);
580 break;
581 case isl_schedule_key_schedule:
582 case isl_schedule_key_coincident:
583 case isl_schedule_key_options:
584 case isl_schedule_key_permutable:
585 tree = read_band(s);
586 break;
587 case isl_schedule_key_child:
588 isl_die(isl_stream_get_ctx(s), isl_error_unsupported,
589 "cannot identity node type", return NULL);
590 case isl_schedule_key_error:
591 return NULL;
594 if (isl_stream_yaml_read_end_mapping(s) < 0) {
595 isl_stream_error(s, NULL, "unexpected extra elements");
596 return isl_schedule_tree_free(tree);
599 return tree;
602 /* Read an isl_schedule from "s".
604 __isl_give isl_schedule *isl_stream_read_schedule(isl_stream *s)
606 isl_ctx *ctx;
607 isl_schedule_tree *tree;
609 if (!s)
610 return NULL;
612 ctx = isl_stream_get_ctx(s);
613 tree = isl_stream_read_schedule_tree(s);
614 return isl_schedule_from_schedule_tree(ctx, tree);
617 /* Read an isl_schedule from "input".
619 __isl_give isl_schedule *isl_schedule_read_from_file(isl_ctx *ctx, FILE *input)
621 struct isl_stream *s;
622 isl_schedule *schedule;
624 s = isl_stream_new_file(ctx, input);
625 if (!s)
626 return NULL;
627 schedule = isl_stream_read_schedule(s);
628 isl_stream_free(s);
630 return schedule;
633 /* Read an isl_schedule from "str".
635 __isl_give isl_schedule *isl_schedule_read_from_str(isl_ctx *ctx,
636 const char *str)
638 struct isl_stream *s;
639 isl_schedule *schedule;
641 s = isl_stream_new_str(ctx, str);
642 if (!s)
643 return NULL;
644 schedule = isl_stream_read_schedule(s);
645 isl_stream_free(s);
647 return schedule;