Home | History | Annotate | Line # | Download | only in dist
      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>
      7 
      8 /* An enumeration of the various keys that may appear in a YAML mapping
      9  * of a schedule.
     10  */
     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
     30 };
     31 
     32 /* Textual representations of the YAML keys for an isl_schedule object.
     33  */
     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",
     51 };
     52 
     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"
     66 
     67 static __isl_give isl_schedule_tree *isl_stream_read_schedule_tree(
     68 	__isl_keep isl_stream *s);
     69 
     70 /* Read a subtree with context root node from "s".
     71  */
     72 static __isl_give isl_schedule_tree *read_context(__isl_keep isl_stream *s)
     73 {
     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;
     81 
     82 	ctx = isl_stream_get_ctx(s);
     83 
     84 	key = get_key(s);
     85 
     86 	if (isl_stream_yaml_next(s) < 0)
     87 		return NULL;
     88 
     89 	tok = isl_stream_next_token(s);
     90 	if (!tok) {
     91 		isl_stream_error(s, NULL, "unexpected EOF");
     92 		return NULL;
     93 	}
     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);
     98 
     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);
    113 	}
    114 
    115 	return tree;
    116 error:
    117 	isl_set_free(context);
    118 	return NULL;
    119 }
    120 
    121 /* Read a subtree with domain root node from "s".
    122  */
    123 static __isl_give isl_schedule_tree *read_domain(__isl_keep isl_stream *s)
    124 {
    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;
    132 
    133 	ctx = isl_stream_get_ctx(s);
    134 
    135 	key = get_key(s);
    136 
    137 	if (isl_stream_yaml_next(s) < 0)
    138 		return NULL;
    139 
    140 	tok = isl_stream_next_token(s);
    141 	if (!tok) {
    142 		isl_stream_error(s, NULL, "unexpected EOF");
    143 		return NULL;
    144 	}
    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);
    149 
    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);
    164 	}
    165 
    166 	return tree;
    167 error:
    168 	isl_union_set_free(domain);
    169 	return NULL;
    170 }
    171 
    172 /* Read a subtree with expansion root node from "s".
    173  */
    174 static __isl_give isl_schedule_tree *read_expansion(isl_stream *s)
    175 {
    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;
    181 
    182 	ctx = isl_stream_get_ctx(s);
    183 
    184 	do {
    185 		struct isl_token *tok;
    186 		enum isl_schedule_key key;
    187 		char *str;
    188 
    189 		key = get_key(s);
    190 		if (isl_stream_yaml_next(s) < 0)
    191 			goto error;
    192 
    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);
    224 		}
    225 	} while ((more = isl_stream_yaml_next(s)) == isl_bool_true);
    226 
    227 	if (more < 0)
    228 		goto error;
    229 
    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);
    236 
    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;
    245 }
    246 
    247 /* Read a subtree with extension root node from "s".
    248  */
    249 static __isl_give isl_schedule_tree *read_extension(isl_stream *s)
    250 {
    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;
    258 
    259 	ctx = isl_stream_get_ctx(s);
    260 
    261 	key = get_key(s);
    262 
    263 	if (isl_stream_yaml_next(s) < 0)
    264 		return NULL;
    265 
    266 	tok = isl_stream_next_token(s);
    267 	if (!tok) {
    268 		isl_stream_error(s, NULL, "unexpected EOF");
    269 		return NULL;
    270 	}
    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);
    275 
    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);
    290 	}
    291 
    292 	return tree;
    293 error:
    294 	isl_union_map_free(extension);
    295 	return NULL;
    296 }
    297 
    298 /* Read a subtree with filter root node from "s".
    299  */
    300 static __isl_give isl_schedule_tree *read_filter(__isl_keep isl_stream *s)
    301 {
    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;
    309 
    310 	ctx = isl_stream_get_ctx(s);
    311 
    312 	key = get_key(s);
    313 
    314 	if (isl_stream_yaml_next(s) < 0)
    315 		return NULL;
    316 
    317 	tok = isl_stream_next_token(s);
    318 	if (!tok) {
    319 		isl_stream_error(s, NULL, "unexpected EOF");
    320 		return NULL;
    321 	}
    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);
    326 
    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);
    341 	}
    342 
    343 	return tree;
    344 error:
    345 	isl_union_set_free(filter);
    346 	return NULL;
    347 }
    348 
    349 /* Read a subtree with guard root node from "s".
    350  */
    351 static __isl_give isl_schedule_tree *read_guard(isl_stream *s)
    352 {
    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;
    360 
    361 	ctx = isl_stream_get_ctx(s);
    362 
    363 	key = get_key(s);
    364 
    365 	if (isl_stream_yaml_next(s) < 0)
    366 		return NULL;
    367 
    368 	tok = isl_stream_next_token(s);
    369 	if (!tok) {
    370 		isl_stream_error(s, NULL, "unexpected EOF");
    371 		return NULL;
    372 	}
    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);
    377 
    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);
    392 	}
    393 
    394 	return tree;
    395 error:
    396 	isl_set_free(guard);
    397 	return NULL;
    398 }
    399 
    400 /* Read a subtree with mark root node from "s".
    401  */
    402 static __isl_give isl_schedule_tree *read_mark(isl_stream *s)
    403 {
    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;
    411 
    412 	ctx = isl_stream_get_ctx(s);
    413 
    414 	key = get_key(s);
    415 
    416 	if (isl_stream_yaml_next(s) < 0)
    417 		return NULL;
    418 
    419 	tok = isl_stream_next_token(s);
    420 	if (!tok) {
    421 		isl_stream_error(s, NULL, "unexpected EOF");
    422 		return NULL;
    423 	}
    424 	str = isl_token_get_str(ctx, tok);
    425 	mark = isl_id_alloc(ctx, str, NULL);
    426 	free(str);
    427 	isl_token_free(tok);
    428 
    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);
    444 	}
    445 
    446 	return tree;
    447 error:
    448 	isl_id_free(mark);
    449 	return NULL;
    450 }
    451 
    452 #undef EL_BASE
    453 #define EL_BASE val
    454 
    455 #include <isl_list_read_yaml_templ.c>
    456 
    457 /* Read a sequence of integers from "s" (representing the coincident
    458  * property of a band node).
    459  */
    460 static __isl_give isl_val_list *read_coincident(__isl_keep isl_stream *s)
    461 {
    462 	return isl_stream_yaml_read_val_list(s);
    463 }
    464 
    465 /* Set the (initial) coincident properties of "band" according to
    466  * the (initial) elements of "coincident".
    467  */
    468 static __isl_give isl_schedule_band *set_coincident(
    469 	__isl_take isl_schedule_band *band, __isl_take isl_val_list *coincident)
    470 {
    471 	int i;
    472 	isl_size n, m;
    473 
    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);
    478 
    479 	for (i = 0; i < n && i < m; ++i) {
    480 		isl_val *v;
    481 
    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);
    488 	}
    489 	isl_val_list_free(coincident);
    490 	return band;
    491 }
    492 
    493 /* Read a subtree with band root node from "s".
    494  */
    495 static __isl_give isl_schedule_tree *read_band(isl_stream *s)
    496 {
    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;
    505 
    506 	ctx = isl_stream_get_ctx(s);
    507 
    508 	do {
    509 		struct isl_token *tok;
    510 		enum isl_schedule_key key;
    511 		char *str;
    512 		isl_val *v;
    513 
    514 		key = get_key(s);
    515 		if (isl_stream_yaml_next(s) < 0)
    516 			goto error;
    517 
    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;
    525 			}
    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);
    563 		}
    564 	} while ((more = isl_stream_yaml_next(s)) == isl_bool_true);
    565 
    566 	if (more < 0)
    567 		goto error;
    568 
    569 	if (!schedule)
    570 		isl_die(ctx, isl_error_invalid, "missing schedule", goto error);
    571 
    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);
    582 
    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;
    590 }
    591 
    592 #undef EL_BASE
    593 #define EL_BASE schedule_tree
    594 
    595 #include <isl_list_read_yaml_templ.c>
    596 
    597 /* Read a subtree with root node of type "type" from "s".
    598  * The node is represented by a sequence of children.
    599  */
    600 static __isl_give isl_schedule_tree *read_children(isl_stream *s,
    601 	enum isl_schedule_node_type type)
    602 {
    603 	isl_schedule_tree_list *list;
    604 
    605 	isl_token_free(isl_stream_next_token(s));
    606 
    607 	if (isl_stream_yaml_next(s) < 0)
    608 		return NULL;
    609 
    610 	list = isl_stream_yaml_read_schedule_tree_list(s);
    611 
    612 	return isl_schedule_tree_from_children(type, list);
    613 }
    614 
    615 /* Read a subtree with sequence root node from "s".
    616  */
    617 static __isl_give isl_schedule_tree *read_sequence(isl_stream *s)
    618 {
    619 	return read_children(s, isl_schedule_node_sequence);
    620 }
    621 
    622 /* Read a subtree with set root node from "s".
    623  */
    624 static __isl_give isl_schedule_tree *read_set(isl_stream *s)
    625 {
    626 	return read_children(s, isl_schedule_node_set);
    627 }
    628 
    629 /* Read a schedule (sub)tree from "s".
    630  *
    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.
    634  */
    635 static __isl_give isl_schedule_tree *isl_stream_read_schedule_tree(
    636 	struct isl_stream *s)
    637 {
    638 	enum isl_schedule_key key;
    639 	struct isl_token *tok;
    640 	isl_schedule_tree *tree = NULL;
    641 	isl_bool more;
    642 
    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;
    651 	}
    652 
    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;
    703 	}
    704 
    705 	if (isl_stream_yaml_read_end_mapping(s) < 0)
    706 		return isl_schedule_tree_free(tree);
    707 
    708 	return tree;
    709 }
    710 
    711 /* Read an isl_schedule from "s".
    712  */
    713 __isl_give isl_schedule *isl_stream_read_schedule(isl_stream *s)
    714 {
    715 	isl_ctx *ctx;
    716 	isl_schedule_tree *tree;
    717 
    718 	if (!s)
    719 		return NULL;
    720 
    721 	ctx = isl_stream_get_ctx(s);
    722 	tree = isl_stream_read_schedule_tree(s);
    723 	return isl_schedule_from_schedule_tree(ctx, tree);
    724 }
    725 
    726 /* Read an isl_schedule from "input".
    727  */
    728 __isl_give isl_schedule *isl_schedule_read_from_file(isl_ctx *ctx, FILE *input)
    729 {
    730 	struct isl_stream *s;
    731 	isl_schedule *schedule;
    732 
    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);
    738 
    739 	return schedule;
    740 }
    741 
    742 #undef TYPE_BASE
    743 #define TYPE_BASE	schedule
    744 #include "isl_read_from_str_templ.c"
    745