isl_ast_build_node_from_schedule: handle basic AST build options
[isl.git] / isl_schedule_read.c
blobaa9d41b100f96ddaa925eaf102814abd0d44d604
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_domain,
16 isl_schedule_key_filter,
17 isl_schedule_key_leaf,
18 isl_schedule_key_options,
19 isl_schedule_key_permutable,
20 isl_schedule_key_schedule,
21 isl_schedule_key_sequence,
22 isl_schedule_key_set
25 /* Extract a mapping key from the token "tok".
26 * Return isl_schedule_key_error on error, i.e., if "tok" does not
27 * correspond to any known key.
29 static enum isl_schedule_key extract_key(__isl_keep isl_stream *s,
30 struct isl_token *tok)
32 int type;
33 char *name;
34 enum isl_schedule_key key;
35 isl_ctx *ctx;
37 ctx = isl_stream_get_ctx(s);
38 type = isl_token_get_type(tok);
39 if (type != ISL_TOKEN_IDENT && type != ISL_TOKEN_STRING) {
40 isl_stream_error(s, tok, "expecting key");
41 return isl_schedule_key_error;
43 name = isl_token_get_str(ctx, tok);
44 if (!strcmp(name, "child"))
45 key = isl_schedule_key_child;
46 else if (!strcmp(name, "coincident"))
47 key = isl_schedule_key_coincident;
48 else if (!strcmp(name, "domain"))
49 key = isl_schedule_key_domain;
50 else if (!strcmp(name, "filter"))
51 key = isl_schedule_key_filter;
52 else if (!strcmp(name, "leaf"))
53 key = isl_schedule_key_leaf;
54 else if (!strcmp(name, "options"))
55 key = isl_schedule_key_options;
56 else if (!strcmp(name, "schedule"))
57 key = isl_schedule_key_schedule;
58 else if (!strcmp(name, "sequence"))
59 key = isl_schedule_key_sequence;
60 else if (!strcmp(name, "set"))
61 key = isl_schedule_key_set;
62 else if (!strcmp(name, "permutable"))
63 key = isl_schedule_key_permutable;
64 else
65 isl_die(ctx, isl_error_invalid, "unknown key",
66 key = isl_schedule_key_error);
67 free(name);
68 return key;
71 /* Read a key from "s" and return the corresponding enum.
72 * Return isl_schedule_key_error on error, i.e., if the first token
73 * on the stream does not correspond to any known key.
75 static enum isl_schedule_key get_key(__isl_keep isl_stream *s)
77 struct isl_token *tok;
78 enum isl_schedule_key key;
80 tok = isl_stream_next_token(s);
81 key = extract_key(s, tok);
82 isl_token_free(tok);
84 return key;
87 static __isl_give isl_schedule_tree *isl_stream_read_schedule_tree(
88 __isl_keep isl_stream *s);
90 /* Read a subtree with domain root node from "s".
92 static __isl_give isl_schedule_tree *read_domain(__isl_keep isl_stream *s)
94 isl_union_set *domain = NULL;
95 isl_schedule_tree *tree;
96 isl_ctx *ctx;
97 struct isl_token *tok;
98 enum isl_schedule_key key;
99 char *str;
100 int more;
102 ctx = isl_stream_get_ctx(s);
104 key = get_key(s);
106 if (isl_stream_yaml_next(s) < 0)
107 return NULL;
109 tok = isl_stream_next_token(s);
110 if (!tok) {
111 isl_stream_error(s, NULL, "unexpected EOF");
112 return NULL;
114 str = isl_token_get_str(ctx, tok);
115 domain = isl_union_set_read_from_str(ctx, str);
116 free(str);
117 isl_token_free(tok);
119 more = isl_stream_yaml_next(s);
120 if (more < 0)
121 goto error;
122 if (!more) {
123 tree = isl_schedule_tree_from_domain(domain);
124 } else {
125 key = get_key(s);
126 if (key != isl_schedule_key_child)
127 isl_die(ctx, isl_error_invalid, "expecting child",
128 goto error);
129 if (isl_stream_yaml_next(s) < 0)
130 goto error;
131 tree = isl_stream_read_schedule_tree(s);
132 tree = isl_schedule_tree_insert_domain(tree, domain);
135 return tree;
136 error:
137 isl_union_set_free(domain);
138 return NULL;
141 /* Read a subtree with filter root node from "s".
143 static __isl_give isl_schedule_tree *read_filter(__isl_keep isl_stream *s)
145 isl_union_set *filter = NULL;
146 isl_schedule_tree *tree;
147 isl_ctx *ctx;
148 struct isl_token *tok;
149 enum isl_schedule_key key;
150 char *str;
151 int more;
153 ctx = isl_stream_get_ctx(s);
155 key = get_key(s);
157 if (isl_stream_yaml_next(s) < 0)
158 return NULL;
160 tok = isl_stream_next_token(s);
161 if (!tok) {
162 isl_stream_error(s, NULL, "unexpected EOF");
163 return NULL;
165 str = isl_token_get_str(ctx, tok);
166 filter = isl_union_set_read_from_str(ctx, str);
167 free(str);
168 isl_token_free(tok);
170 more = isl_stream_yaml_next(s);
171 if (more < 0)
172 goto error;
173 if (!more) {
174 tree = isl_schedule_tree_from_filter(filter);
175 } else {
176 key = get_key(s);
177 if (key != isl_schedule_key_child)
178 isl_die(ctx, isl_error_invalid, "expecting child",
179 goto error);
180 if (isl_stream_yaml_next(s) < 0)
181 goto error;
182 tree = isl_stream_read_schedule_tree(s);
183 tree = isl_schedule_tree_insert_filter(tree, filter);
186 return tree;
187 error:
188 isl_union_set_free(filter);
189 return NULL;
192 /* Read a sequence of integers from "s" (representing the coincident
193 * property of a band node).
195 static __isl_give isl_val_list *read_coincident(__isl_keep isl_stream *s)
197 isl_ctx *ctx;
198 isl_val_list *list;
199 int more;
201 ctx = isl_stream_get_ctx(s);
203 if (isl_stream_yaml_read_start_sequence(s) < 0)
204 return NULL;
206 list = isl_val_list_alloc(ctx, 0);
207 while ((more = isl_stream_yaml_next(s)) > 0) {
208 isl_val *val;
210 val = isl_stream_read_val(s);
211 list = isl_val_list_add(list, val);
214 if (more < 0 || isl_stream_yaml_read_end_sequence(s))
215 list = isl_val_list_free(list);
217 return list;
220 /* Set the (initial) coincident properties of "band" according to
221 * the (initial) elements of "coincident".
223 static __isl_give isl_schedule_band *set_coincident(
224 __isl_take isl_schedule_band *band, __isl_take isl_val_list *coincident)
226 int i;
227 int n, m;
229 n = isl_schedule_band_n_member(band);
230 m = isl_val_list_n_val(coincident);
232 for (i = 0; i < n && i < m; ++i) {
233 isl_val *v;
235 v = isl_val_list_get_val(coincident, i);
236 if (!v)
237 band = isl_schedule_band_free(band);
238 band = isl_schedule_band_member_set_coincident(band, i,
239 !isl_val_is_zero(v));
240 isl_val_free(v);
242 isl_val_list_free(coincident);
243 return band;
246 /* Read a subtree with band root node from "s".
248 static __isl_give isl_schedule_tree *read_band(isl_stream *s)
250 isl_multi_union_pw_aff *schedule = NULL;
251 isl_schedule_tree *tree = NULL;
252 isl_val_list *coincident = NULL;
253 isl_union_set *options = NULL;
254 isl_ctx *ctx;
255 isl_schedule_band *band;
256 int permutable = 0;
257 int more;
259 ctx = isl_stream_get_ctx(s);
261 do {
262 struct isl_token *tok;
263 enum isl_schedule_key key;
264 char *str;
265 isl_val *v;
267 key = get_key(s);
268 if (isl_stream_yaml_next(s) < 0)
269 goto error;
271 switch (key) {
272 case isl_schedule_key_schedule:
273 isl_multi_union_pw_aff_free(schedule);
274 tok = isl_stream_next_token(s);
275 if (!tok) {
276 isl_stream_error(s, NULL, "unexpected EOF");
277 goto error;
279 str = isl_token_get_str(ctx, tok);
280 schedule = isl_multi_union_pw_aff_read_from_str(ctx,
281 str);
282 free(str);
283 isl_token_free(tok);
284 if (!schedule)
285 goto error;
286 break;
287 case isl_schedule_key_coincident:
288 coincident = read_coincident(s);
289 if (!coincident)
290 goto error;
291 break;
292 case isl_schedule_key_permutable:
293 v = isl_stream_read_val(s);
294 permutable = !isl_val_is_zero(v);
295 isl_val_free(v);
296 break;
297 case isl_schedule_key_options:
298 isl_union_set_free(options);
299 tok = isl_stream_next_token(s);
300 str = isl_token_get_str(ctx, tok);
301 options = isl_union_set_read_from_str(ctx, str);
302 free(str);
303 isl_token_free(tok);
304 if (!options)
305 goto error;
306 break;
307 case isl_schedule_key_child:
308 isl_schedule_tree_free(tree);
309 tree = isl_stream_read_schedule_tree(s);
310 if (!tree)
311 goto error;
312 break;
313 default:
314 isl_die(ctx, isl_error_invalid, "unexpected key",
315 goto error);
317 } while ((more = isl_stream_yaml_next(s)) > 0);
319 if (more < 0)
320 goto error;
322 if (!schedule)
323 isl_die(ctx, isl_error_invalid, "missing schedule", goto error);
325 band = isl_schedule_band_from_multi_union_pw_aff(schedule);
326 band = isl_schedule_band_set_permutable(band, permutable);
327 if (coincident)
328 band = set_coincident(band, coincident);
329 if (options)
330 band = isl_schedule_band_set_ast_build_options(band, options);
331 if (tree)
332 tree = isl_schedule_tree_insert_band(tree, band);
333 else
334 tree = isl_schedule_tree_from_band(band);
336 return tree;
337 error:
338 isl_val_list_free(coincident);
339 isl_union_set_free(options);
340 isl_schedule_tree_free(tree);
341 isl_multi_union_pw_aff_free(schedule);
342 return NULL;
345 /* Read a subtree with root node of type "type" from "s".
346 * The node is represented by a sequence of children.
348 static __isl_give isl_schedule_tree *read_children(isl_stream *s,
349 enum isl_schedule_node_type type)
351 isl_ctx *ctx;
352 isl_schedule_tree_list *list;
353 int more;
355 ctx = isl_stream_get_ctx(s);
357 isl_token_free(isl_stream_next_token(s));
359 if (isl_stream_yaml_next(s) < 0)
360 return NULL;
362 if (isl_stream_yaml_read_start_sequence(s))
363 return NULL;
365 list = isl_schedule_tree_list_alloc(ctx, 0);
366 while ((more = isl_stream_yaml_next(s)) > 0) {
367 isl_schedule_tree *tree;
369 tree = isl_stream_read_schedule_tree(s);
370 list = isl_schedule_tree_list_add(list, tree);
373 if (more < 0 || isl_stream_yaml_read_end_sequence(s))
374 list = isl_schedule_tree_list_free(list);
376 return isl_schedule_tree_from_children(type, list);
379 /* Read a subtree with sequence root node from "s".
381 static __isl_give isl_schedule_tree *read_sequence(isl_stream *s)
383 return read_children(s, isl_schedule_node_sequence);
386 /* Read a subtree with set root node from "s".
388 static __isl_give isl_schedule_tree *read_set(isl_stream *s)
390 return read_children(s, isl_schedule_node_set);
393 /* Read a schedule (sub)tree from "s".
395 * We first determine the type of the root node based on the first
396 * mapping key and then hand over to a function tailored to reading
397 * nodes of this type.
399 static __isl_give isl_schedule_tree *isl_stream_read_schedule_tree(
400 struct isl_stream *s)
402 enum isl_schedule_key key;
403 struct isl_token *tok;
404 isl_schedule_tree *tree = NULL;
405 int more;
407 if (isl_stream_yaml_read_start_mapping(s))
408 return NULL;
409 more = isl_stream_yaml_next(s);
410 if (more < 0)
411 return NULL;
412 if (!more) {
413 isl_stream_error(s, NULL, "missing key");
414 return NULL;
417 tok = isl_stream_next_token(s);
418 key = extract_key(s, tok);
419 isl_stream_push_token(s, tok);
420 if (key < 0)
421 return NULL;
422 switch (key) {
423 case isl_schedule_key_domain:
424 tree = read_domain(s);
425 break;
426 case isl_schedule_key_filter:
427 tree = read_filter(s);
428 break;
429 case isl_schedule_key_leaf:
430 isl_token_free(isl_stream_next_token(s));
431 tree = isl_schedule_tree_leaf(isl_stream_get_ctx(s));
432 break;
433 case isl_schedule_key_sequence:
434 tree = read_sequence(s);
435 break;
436 case isl_schedule_key_set:
437 tree = read_set(s);
438 break;
439 case isl_schedule_key_schedule:
440 case isl_schedule_key_coincident:
441 case isl_schedule_key_options:
442 case isl_schedule_key_permutable:
443 tree = read_band(s);
444 break;
445 case isl_schedule_key_child:
446 isl_die(isl_stream_get_ctx(s), isl_error_unsupported,
447 "cannot identity node type", return NULL);
448 case isl_schedule_key_error:
449 return NULL;
452 if (isl_stream_yaml_read_end_mapping(s) < 0) {
453 isl_stream_error(s, NULL, "unexpected extra elements");
454 return isl_schedule_tree_free(tree);
457 return tree;
460 /* Read an isl_schedule from "s".
462 __isl_give isl_schedule *isl_stream_read_schedule(isl_stream *s)
464 isl_ctx *ctx;
465 isl_schedule_tree *tree;
467 if (!s)
468 return NULL;
470 ctx = isl_stream_get_ctx(s);
471 tree = isl_stream_read_schedule_tree(s);
472 return isl_schedule_from_schedule_tree(ctx, tree);
475 /* Read an isl_schedule from "input".
477 __isl_give isl_schedule *isl_schedule_read_from_file(isl_ctx *ctx, FILE *input)
479 struct isl_stream *s;
480 isl_schedule *schedule;
482 s = isl_stream_new_file(ctx, input);
483 if (!s)
484 return NULL;
485 schedule = isl_stream_read_schedule(s);
486 isl_stream_free(s);
488 return schedule;
491 /* Read an isl_schedule from "str".
493 __isl_give isl_schedule *isl_schedule_read_from_str(isl_ctx *ctx,
494 const char *str)
496 struct isl_stream *s;
497 isl_schedule *schedule;
499 s = isl_stream_new_str(ctx, str);
500 if (!s)
501 return NULL;
502 schedule = isl_stream_read_schedule(s);
503 isl_stream_free(s);
505 return schedule;