Blame isl-0.16.1/isl_schedule_read.c

Packit fb9d21
#include <string.h>
Packit fb9d21
Packit fb9d21
#include <isl/schedule.h>
Packit fb9d21
#include <isl/stream.h>
Packit fb9d21
#include <isl_schedule_private.h>
Packit fb9d21
#include <isl_schedule_tree.h>
Packit fb9d21
Packit fb9d21
/* An enumeration of the various keys that may appear in a YAML mapping
Packit fb9d21
 * of a schedule.
Packit fb9d21
 */
Packit fb9d21
enum isl_schedule_key {
Packit fb9d21
	isl_schedule_key_error = -1,
Packit fb9d21
	isl_schedule_key_child,
Packit fb9d21
	isl_schedule_key_coincident,
Packit fb9d21
	isl_schedule_key_context,
Packit fb9d21
	isl_schedule_key_contraction,
Packit fb9d21
	isl_schedule_key_domain,
Packit fb9d21
	isl_schedule_key_expansion,
Packit fb9d21
	isl_schedule_key_extension,
Packit fb9d21
	isl_schedule_key_filter,
Packit fb9d21
	isl_schedule_key_guard,
Packit fb9d21
	isl_schedule_key_leaf,
Packit fb9d21
	isl_schedule_key_mark,
Packit fb9d21
	isl_schedule_key_options,
Packit fb9d21
	isl_schedule_key_permutable,
Packit fb9d21
	isl_schedule_key_schedule,
Packit fb9d21
	isl_schedule_key_sequence,
Packit fb9d21
	isl_schedule_key_set
Packit fb9d21
};
Packit fb9d21
Packit fb9d21
/* Extract a mapping key from the token "tok".
Packit fb9d21
 * Return isl_schedule_key_error on error, i.e., if "tok" does not
Packit fb9d21
 * correspond to any known key.
Packit fb9d21
 */
Packit fb9d21
static enum isl_schedule_key extract_key(__isl_keep isl_stream *s,
Packit fb9d21
	struct isl_token *tok)
Packit fb9d21
{
Packit fb9d21
	int type;
Packit fb9d21
	char *name;
Packit fb9d21
	enum isl_schedule_key key;
Packit fb9d21
	isl_ctx *ctx;
Packit fb9d21
Packit fb9d21
	ctx = isl_stream_get_ctx(s);
Packit fb9d21
	type = isl_token_get_type(tok);
Packit fb9d21
	if (type != ISL_TOKEN_IDENT && type != ISL_TOKEN_STRING) {
Packit fb9d21
		isl_stream_error(s, tok, "expecting key");
Packit fb9d21
		return isl_schedule_key_error;
Packit fb9d21
	}
Packit fb9d21
	name = isl_token_get_str(ctx, tok);
Packit fb9d21
	if (!strcmp(name, "child"))
Packit fb9d21
		key = isl_schedule_key_child;
Packit fb9d21
	else if (!strcmp(name, "coincident"))
Packit fb9d21
		key = isl_schedule_key_coincident;
Packit fb9d21
	else if (!strcmp(name, "context"))
Packit fb9d21
		key = isl_schedule_key_context;
Packit fb9d21
	else if (!strcmp(name, "contraction"))
Packit fb9d21
		key = isl_schedule_key_contraction;
Packit fb9d21
	else if (!strcmp(name, "domain"))
Packit fb9d21
		key = isl_schedule_key_domain;
Packit fb9d21
	else if (!strcmp(name, "expansion"))
Packit fb9d21
		key = isl_schedule_key_expansion;
Packit fb9d21
	else if (!strcmp(name, "extension"))
Packit fb9d21
		key = isl_schedule_key_extension;
Packit fb9d21
	else if (!strcmp(name, "filter"))
Packit fb9d21
		key = isl_schedule_key_filter;
Packit fb9d21
	else if (!strcmp(name, "guard"))
Packit fb9d21
		key = isl_schedule_key_guard;
Packit fb9d21
	else if (!strcmp(name, "leaf"))
Packit fb9d21
		key = isl_schedule_key_leaf;
Packit fb9d21
	else if (!strcmp(name, "mark"))
Packit fb9d21
		key = isl_schedule_key_mark;
Packit fb9d21
	else if (!strcmp(name, "options"))
Packit fb9d21
		key = isl_schedule_key_options;
Packit fb9d21
	else if (!strcmp(name, "schedule"))
Packit fb9d21
		key = isl_schedule_key_schedule;
Packit fb9d21
	else if (!strcmp(name, "sequence"))
Packit fb9d21
		key = isl_schedule_key_sequence;
Packit fb9d21
	else if (!strcmp(name, "set"))
Packit fb9d21
		key = isl_schedule_key_set;
Packit fb9d21
	else if (!strcmp(name, "permutable"))
Packit fb9d21
		key = isl_schedule_key_permutable;
Packit fb9d21
	else
Packit fb9d21
		isl_die(ctx, isl_error_invalid, "unknown key",
Packit fb9d21
			key = isl_schedule_key_error);
Packit fb9d21
	free(name);
Packit fb9d21
	return key;
Packit fb9d21
}
Packit fb9d21
Packit fb9d21
/* Read a key from "s" and return the corresponding enum.
Packit fb9d21
 * Return isl_schedule_key_error on error, i.e., if the first token
Packit fb9d21
 * on the stream does not correspond to any known key.
Packit fb9d21
 */
Packit fb9d21
static enum isl_schedule_key get_key(__isl_keep isl_stream *s)
Packit fb9d21
{
Packit fb9d21
	struct isl_token *tok;
Packit fb9d21
	enum isl_schedule_key key;
Packit fb9d21
Packit fb9d21
	tok = isl_stream_next_token(s);
Packit fb9d21
	key = extract_key(s, tok);
Packit fb9d21
	isl_token_free(tok);
Packit fb9d21
Packit fb9d21
	return key;
Packit fb9d21
}
Packit fb9d21
Packit fb9d21
static __isl_give isl_schedule_tree *isl_stream_read_schedule_tree(
Packit fb9d21
	__isl_keep isl_stream *s);
Packit fb9d21
Packit fb9d21
/* Read a subtree with context root node from "s".
Packit fb9d21
 */
Packit fb9d21
static __isl_give isl_schedule_tree *read_context(__isl_keep isl_stream *s)
Packit fb9d21
{
Packit fb9d21
	isl_set *context = NULL;
Packit fb9d21
	isl_schedule_tree *tree;
Packit fb9d21
	isl_ctx *ctx;
Packit fb9d21
	struct isl_token *tok;
Packit fb9d21
	enum isl_schedule_key key;
Packit fb9d21
	char *str;
Packit fb9d21
	int more;
Packit fb9d21
Packit fb9d21
	ctx = isl_stream_get_ctx(s);
Packit fb9d21
Packit fb9d21
	key = get_key(s);
Packit fb9d21
Packit fb9d21
	if (isl_stream_yaml_next(s) < 0)
Packit fb9d21
		return NULL;
Packit fb9d21
Packit fb9d21
	tok = isl_stream_next_token(s);
Packit fb9d21
	if (!tok) {
Packit fb9d21
		isl_stream_error(s, NULL, "unexpected EOF");
Packit fb9d21
		return NULL;
Packit fb9d21
	}
Packit fb9d21
	str = isl_token_get_str(ctx, tok);
Packit fb9d21
	context = isl_set_read_from_str(ctx, str);
Packit fb9d21
	free(str);
Packit fb9d21
	isl_token_free(tok);
Packit fb9d21
Packit fb9d21
	more = isl_stream_yaml_next(s);
Packit fb9d21
	if (more < 0)
Packit fb9d21
		goto error;
Packit fb9d21
	if (!more) {
Packit fb9d21
		tree = isl_schedule_tree_from_context(context);
Packit fb9d21
	} else {
Packit fb9d21
		key = get_key(s);
Packit fb9d21
		if (key != isl_schedule_key_child)
Packit fb9d21
			isl_die(ctx, isl_error_invalid, "expecting child",
Packit fb9d21
				goto error);
Packit fb9d21
		if (isl_stream_yaml_next(s) < 0)
Packit fb9d21
			goto error;
Packit fb9d21
		tree = isl_stream_read_schedule_tree(s);
Packit fb9d21
		tree = isl_schedule_tree_insert_context(tree, context);
Packit fb9d21
	}
Packit fb9d21
Packit fb9d21
	return tree;
Packit fb9d21
error:
Packit fb9d21
	isl_set_free(context);
Packit fb9d21
	return NULL;
Packit fb9d21
}
Packit fb9d21
Packit fb9d21
/* Read a subtree with domain root node from "s".
Packit fb9d21
 */
Packit fb9d21
static __isl_give isl_schedule_tree *read_domain(__isl_keep isl_stream *s)
Packit fb9d21
{
Packit fb9d21
	isl_union_set *domain = NULL;
Packit fb9d21
	isl_schedule_tree *tree;
Packit fb9d21
	isl_ctx *ctx;
Packit fb9d21
	struct isl_token *tok;
Packit fb9d21
	enum isl_schedule_key key;
Packit fb9d21
	char *str;
Packit fb9d21
	int more;
Packit fb9d21
Packit fb9d21
	ctx = isl_stream_get_ctx(s);
Packit fb9d21
Packit fb9d21
	key = get_key(s);
Packit fb9d21
Packit fb9d21
	if (isl_stream_yaml_next(s) < 0)
Packit fb9d21
		return NULL;
Packit fb9d21
Packit fb9d21
	tok = isl_stream_next_token(s);
Packit fb9d21
	if (!tok) {
Packit fb9d21
		isl_stream_error(s, NULL, "unexpected EOF");
Packit fb9d21
		return NULL;
Packit fb9d21
	}
Packit fb9d21
	str = isl_token_get_str(ctx, tok);
Packit fb9d21
	domain = isl_union_set_read_from_str(ctx, str);
Packit fb9d21
	free(str);
Packit fb9d21
	isl_token_free(tok);
Packit fb9d21
Packit fb9d21
	more = isl_stream_yaml_next(s);
Packit fb9d21
	if (more < 0)
Packit fb9d21
		goto error;
Packit fb9d21
	if (!more) {
Packit fb9d21
		tree = isl_schedule_tree_from_domain(domain);
Packit fb9d21
	} else {
Packit fb9d21
		key = get_key(s);
Packit fb9d21
		if (key != isl_schedule_key_child)
Packit fb9d21
			isl_die(ctx, isl_error_invalid, "expecting child",
Packit fb9d21
				goto error);
Packit fb9d21
		if (isl_stream_yaml_next(s) < 0)
Packit fb9d21
			goto error;
Packit fb9d21
		tree = isl_stream_read_schedule_tree(s);
Packit fb9d21
		tree = isl_schedule_tree_insert_domain(tree, domain);
Packit fb9d21
	}
Packit fb9d21
Packit fb9d21
	return tree;
Packit fb9d21
error:
Packit fb9d21
	isl_union_set_free(domain);
Packit fb9d21
	return NULL;
Packit fb9d21
}
Packit fb9d21
Packit fb9d21
/* Read a subtree with expansion root node from "s".
Packit fb9d21
 */
Packit fb9d21
static __isl_give isl_schedule_tree *read_expansion(isl_stream *s)
Packit fb9d21
{
Packit fb9d21
	isl_ctx *ctx;
Packit fb9d21
	isl_union_pw_multi_aff *contraction = NULL;
Packit fb9d21
	isl_union_map *expansion = NULL;
Packit fb9d21
	isl_schedule_tree *tree = NULL;
Packit fb9d21
	int more;
Packit fb9d21
Packit fb9d21
	ctx = isl_stream_get_ctx(s);
Packit fb9d21
Packit fb9d21
	do {
Packit fb9d21
		struct isl_token *tok;
Packit fb9d21
		enum isl_schedule_key key;
Packit fb9d21
		char *str;
Packit fb9d21
Packit fb9d21
		key = get_key(s);
Packit fb9d21
		if (isl_stream_yaml_next(s) < 0)
Packit fb9d21
			goto error;
Packit fb9d21
Packit fb9d21
		switch (key) {
Packit fb9d21
		case isl_schedule_key_contraction:
Packit fb9d21
			isl_union_pw_multi_aff_free(contraction);
Packit fb9d21
			tok = isl_stream_next_token(s);
Packit fb9d21
			str = isl_token_get_str(ctx, tok);
Packit fb9d21
			contraction = isl_union_pw_multi_aff_read_from_str(ctx,
Packit fb9d21
									str);
Packit fb9d21
			free(str);
Packit fb9d21
			isl_token_free(tok);
Packit fb9d21
			if (!contraction)
Packit fb9d21
				goto error;
Packit fb9d21
			break;
Packit fb9d21
		case isl_schedule_key_expansion:
Packit fb9d21
			isl_union_map_free(expansion);
Packit fb9d21
			tok = isl_stream_next_token(s);
Packit fb9d21
			str = isl_token_get_str(ctx, tok);
Packit fb9d21
			expansion = isl_union_map_read_from_str(ctx, str);
Packit fb9d21
			free(str);
Packit fb9d21
			isl_token_free(tok);
Packit fb9d21
			if (!expansion)
Packit fb9d21
				goto error;
Packit fb9d21
			break;
Packit fb9d21
		case isl_schedule_key_child:
Packit fb9d21
			isl_schedule_tree_free(tree);
Packit fb9d21
			tree = isl_stream_read_schedule_tree(s);
Packit fb9d21
			if (!tree)
Packit fb9d21
				goto error;
Packit fb9d21
			break;
Packit fb9d21
		default:
Packit fb9d21
			isl_die(ctx, isl_error_invalid, "unexpected key",
Packit fb9d21
				goto error);
Packit fb9d21
		}
Packit fb9d21
	} while ((more = isl_stream_yaml_next(s)) > 0);
Packit fb9d21
Packit fb9d21
	if (more < 0)
Packit fb9d21
		goto error;
Packit fb9d21
Packit fb9d21
	if (!contraction)
Packit fb9d21
		isl_die(ctx, isl_error_invalid, "missing contraction",
Packit fb9d21
			goto error);
Packit fb9d21
	if (!expansion)
Packit fb9d21
		isl_die(ctx, isl_error_invalid, "missing expansion",
Packit fb9d21
			goto error);
Packit fb9d21
Packit fb9d21
	if (!tree)
Packit fb9d21
		return isl_schedule_tree_from_expansion(contraction, expansion);
Packit fb9d21
	return isl_schedule_tree_insert_expansion(tree, contraction, expansion);
Packit fb9d21
error:
Packit fb9d21
	isl_schedule_tree_free(tree);
Packit fb9d21
	isl_union_pw_multi_aff_free(contraction);
Packit fb9d21
	isl_union_map_free(expansion);
Packit fb9d21
	return NULL;
Packit fb9d21
}
Packit fb9d21
Packit fb9d21
/* Read a subtree with extension root node from "s".
Packit fb9d21
 */
Packit fb9d21
static __isl_give isl_schedule_tree *read_extension(isl_stream *s)
Packit fb9d21
{
Packit fb9d21
	isl_union_map *extension = NULL;
Packit fb9d21
	isl_schedule_tree *tree;
Packit fb9d21
	isl_ctx *ctx;
Packit fb9d21
	struct isl_token *tok;
Packit fb9d21
	enum isl_schedule_key key;
Packit fb9d21
	char *str;
Packit fb9d21
	int more;
Packit fb9d21
Packit fb9d21
	ctx = isl_stream_get_ctx(s);
Packit fb9d21
Packit fb9d21
	key = get_key(s);
Packit fb9d21
Packit fb9d21
	if (isl_stream_yaml_next(s) < 0)
Packit fb9d21
		return NULL;
Packit fb9d21
Packit fb9d21
	tok = isl_stream_next_token(s);
Packit fb9d21
	if (!tok) {
Packit fb9d21
		isl_stream_error(s, NULL, "unexpected EOF");
Packit fb9d21
		return NULL;
Packit fb9d21
	}
Packit fb9d21
	str = isl_token_get_str(ctx, tok);
Packit fb9d21
	extension = isl_union_map_read_from_str(ctx, str);
Packit fb9d21
	free(str);
Packit fb9d21
	isl_token_free(tok);
Packit fb9d21
Packit fb9d21
	more = isl_stream_yaml_next(s);
Packit fb9d21
	if (more < 0)
Packit fb9d21
		goto error;
Packit fb9d21
	if (!more) {
Packit fb9d21
		tree = isl_schedule_tree_from_extension(extension);
Packit fb9d21
	} else {
Packit fb9d21
		key = get_key(s);
Packit fb9d21
		if (key != isl_schedule_key_child)
Packit fb9d21
			isl_die(ctx, isl_error_invalid, "expecting child",
Packit fb9d21
				goto error);
Packit fb9d21
		if (isl_stream_yaml_next(s) < 0)
Packit fb9d21
			goto error;
Packit fb9d21
		tree = isl_stream_read_schedule_tree(s);
Packit fb9d21
		tree = isl_schedule_tree_insert_extension(tree, extension);
Packit fb9d21
	}
Packit fb9d21
Packit fb9d21
	return tree;
Packit fb9d21
error:
Packit fb9d21
	isl_union_map_free(extension);
Packit fb9d21
	return NULL;
Packit fb9d21
}
Packit fb9d21
Packit fb9d21
/* Read a subtree with filter root node from "s".
Packit fb9d21
 */
Packit fb9d21
static __isl_give isl_schedule_tree *read_filter(__isl_keep isl_stream *s)
Packit fb9d21
{
Packit fb9d21
	isl_union_set *filter = NULL;
Packit fb9d21
	isl_schedule_tree *tree;
Packit fb9d21
	isl_ctx *ctx;
Packit fb9d21
	struct isl_token *tok;
Packit fb9d21
	enum isl_schedule_key key;
Packit fb9d21
	char *str;
Packit fb9d21
	int more;
Packit fb9d21
Packit fb9d21
	ctx = isl_stream_get_ctx(s);
Packit fb9d21
Packit fb9d21
	key = get_key(s);
Packit fb9d21
Packit fb9d21
	if (isl_stream_yaml_next(s) < 0)
Packit fb9d21
		return NULL;
Packit fb9d21
Packit fb9d21
	tok = isl_stream_next_token(s);
Packit fb9d21
	if (!tok) {
Packit fb9d21
		isl_stream_error(s, NULL, "unexpected EOF");
Packit fb9d21
		return NULL;
Packit fb9d21
	}
Packit fb9d21
	str = isl_token_get_str(ctx, tok);
Packit fb9d21
	filter = isl_union_set_read_from_str(ctx, str);
Packit fb9d21
	free(str);
Packit fb9d21
	isl_token_free(tok);
Packit fb9d21
Packit fb9d21
	more = isl_stream_yaml_next(s);
Packit fb9d21
	if (more < 0)
Packit fb9d21
		goto error;
Packit fb9d21
	if (!more) {
Packit fb9d21
		tree = isl_schedule_tree_from_filter(filter);
Packit fb9d21
	} else {
Packit fb9d21
		key = get_key(s);
Packit fb9d21
		if (key != isl_schedule_key_child)
Packit fb9d21
			isl_die(ctx, isl_error_invalid, "expecting child",
Packit fb9d21
				goto error);
Packit fb9d21
		if (isl_stream_yaml_next(s) < 0)
Packit fb9d21
			goto error;
Packit fb9d21
		tree = isl_stream_read_schedule_tree(s);
Packit fb9d21
		tree = isl_schedule_tree_insert_filter(tree, filter);
Packit fb9d21
	}
Packit fb9d21
Packit fb9d21
	return tree;
Packit fb9d21
error:
Packit fb9d21
	isl_union_set_free(filter);
Packit fb9d21
	return NULL;
Packit fb9d21
}
Packit fb9d21
Packit fb9d21
/* Read a subtree with guard root node from "s".
Packit fb9d21
 */
Packit fb9d21
static __isl_give isl_schedule_tree *read_guard(isl_stream *s)
Packit fb9d21
{
Packit fb9d21
	isl_set *guard = NULL;
Packit fb9d21
	isl_schedule_tree *tree;
Packit fb9d21
	isl_ctx *ctx;
Packit fb9d21
	struct isl_token *tok;
Packit fb9d21
	enum isl_schedule_key key;
Packit fb9d21
	char *str;
Packit fb9d21
	int more;
Packit fb9d21
Packit fb9d21
	ctx = isl_stream_get_ctx(s);
Packit fb9d21
Packit fb9d21
	key = get_key(s);
Packit fb9d21
Packit fb9d21
	if (isl_stream_yaml_next(s) < 0)
Packit fb9d21
		return NULL;
Packit fb9d21
Packit fb9d21
	tok = isl_stream_next_token(s);
Packit fb9d21
	if (!tok) {
Packit fb9d21
		isl_stream_error(s, NULL, "unexpected EOF");
Packit fb9d21
		return NULL;
Packit fb9d21
	}
Packit fb9d21
	str = isl_token_get_str(ctx, tok);
Packit fb9d21
	guard = isl_set_read_from_str(ctx, str);
Packit fb9d21
	free(str);
Packit fb9d21
	isl_token_free(tok);
Packit fb9d21
Packit fb9d21
	more = isl_stream_yaml_next(s);
Packit fb9d21
	if (more < 0)
Packit fb9d21
		goto error;
Packit fb9d21
	if (!more) {
Packit fb9d21
		tree = isl_schedule_tree_from_guard(guard);
Packit fb9d21
	} else {
Packit fb9d21
		key = get_key(s);
Packit fb9d21
		if (key != isl_schedule_key_child)
Packit fb9d21
			isl_die(ctx, isl_error_invalid, "expecting child",
Packit fb9d21
				goto error);
Packit fb9d21
		if (isl_stream_yaml_next(s) < 0)
Packit fb9d21
			goto error;
Packit fb9d21
		tree = isl_stream_read_schedule_tree(s);
Packit fb9d21
		tree = isl_schedule_tree_insert_guard(tree, guard);
Packit fb9d21
	}
Packit fb9d21
Packit fb9d21
	return tree;
Packit fb9d21
error:
Packit fb9d21
	isl_set_free(guard);
Packit fb9d21
	return NULL;
Packit fb9d21
}
Packit fb9d21
Packit fb9d21
/* Read a subtree with mark root node from "s".
Packit fb9d21
 */
Packit fb9d21
static __isl_give isl_schedule_tree *read_mark(isl_stream *s)
Packit fb9d21
{
Packit fb9d21
	isl_id *mark;
Packit fb9d21
	isl_schedule_tree *tree;
Packit fb9d21
	isl_ctx *ctx;
Packit fb9d21
	struct isl_token *tok;
Packit fb9d21
	enum isl_schedule_key key;
Packit fb9d21
	char *str;
Packit fb9d21
	int more;
Packit fb9d21
Packit fb9d21
	ctx = isl_stream_get_ctx(s);
Packit fb9d21
Packit fb9d21
	key = get_key(s);
Packit fb9d21
Packit fb9d21
	if (isl_stream_yaml_next(s) < 0)
Packit fb9d21
		return NULL;
Packit fb9d21
Packit fb9d21
	tok = isl_stream_next_token(s);
Packit fb9d21
	if (!tok) {
Packit fb9d21
		isl_stream_error(s, NULL, "unexpected EOF");
Packit fb9d21
		return NULL;
Packit fb9d21
	}
Packit fb9d21
	str = isl_token_get_str(ctx, tok);
Packit fb9d21
	mark = isl_id_alloc(ctx, str, NULL);
Packit fb9d21
	free(str);
Packit fb9d21
	isl_token_free(tok);
Packit fb9d21
Packit fb9d21
	more = isl_stream_yaml_next(s);
Packit fb9d21
	if (more < 0)
Packit fb9d21
		goto error;
Packit fb9d21
	if (!more) {
Packit fb9d21
		isl_die(ctx, isl_error_invalid, "expecting child",
Packit fb9d21
			goto error);
Packit fb9d21
	} else {
Packit fb9d21
		key = get_key(s);
Packit fb9d21
		if (key != isl_schedule_key_child)
Packit fb9d21
			isl_die(ctx, isl_error_invalid, "expecting child",
Packit fb9d21
				goto error);
Packit fb9d21
		if (isl_stream_yaml_next(s) < 0)
Packit fb9d21
			goto error;
Packit fb9d21
		tree = isl_stream_read_schedule_tree(s);
Packit fb9d21
		tree = isl_schedule_tree_insert_mark(tree, mark);
Packit fb9d21
	}
Packit fb9d21
Packit fb9d21
	return tree;
Packit fb9d21
error:
Packit fb9d21
	isl_id_free(mark);
Packit fb9d21
	return NULL;
Packit fb9d21
}
Packit fb9d21
Packit fb9d21
/* Read a sequence of integers from "s" (representing the coincident
Packit fb9d21
 * property of a band node).
Packit fb9d21
 */
Packit fb9d21
static __isl_give isl_val_list *read_coincident(__isl_keep isl_stream *s)
Packit fb9d21
{
Packit fb9d21
	isl_ctx *ctx;
Packit fb9d21
	isl_val_list *list;
Packit fb9d21
	int more;
Packit fb9d21
Packit fb9d21
	ctx = isl_stream_get_ctx(s);
Packit fb9d21
Packit fb9d21
	if (isl_stream_yaml_read_start_sequence(s) < 0)
Packit fb9d21
		return NULL;
Packit fb9d21
Packit fb9d21
	list = isl_val_list_alloc(ctx, 0);
Packit fb9d21
	while  ((more = isl_stream_yaml_next(s)) > 0) {
Packit fb9d21
		isl_val *val;
Packit fb9d21
Packit fb9d21
		val = isl_stream_read_val(s);
Packit fb9d21
		list = isl_val_list_add(list, val);
Packit fb9d21
	}
Packit fb9d21
Packit fb9d21
	if (more < 0 || isl_stream_yaml_read_end_sequence(s))
Packit fb9d21
		list = isl_val_list_free(list);
Packit fb9d21
Packit fb9d21
	return list;
Packit fb9d21
}
Packit fb9d21
Packit fb9d21
/* Set the (initial) coincident properties of "band" according to
Packit fb9d21
 * the (initial) elements of "coincident".
Packit fb9d21
 */
Packit fb9d21
static __isl_give isl_schedule_band *set_coincident(
Packit fb9d21
	__isl_take isl_schedule_band *band, __isl_take isl_val_list *coincident)
Packit fb9d21
{
Packit fb9d21
	int i;
Packit fb9d21
	int n, m;
Packit fb9d21
Packit fb9d21
	n = isl_schedule_band_n_member(band);
Packit fb9d21
	m = isl_val_list_n_val(coincident);
Packit fb9d21
Packit fb9d21
	for (i = 0; i < n && i < m; ++i) {
Packit fb9d21
		isl_val *v;
Packit fb9d21
Packit fb9d21
		v = isl_val_list_get_val(coincident, i);
Packit fb9d21
		if (!v)
Packit fb9d21
			band = isl_schedule_band_free(band);
Packit fb9d21
		band = isl_schedule_band_member_set_coincident(band, i,
Packit fb9d21
							!isl_val_is_zero(v));
Packit fb9d21
		isl_val_free(v);
Packit fb9d21
	}
Packit fb9d21
	isl_val_list_free(coincident);
Packit fb9d21
	return band;
Packit fb9d21
}
Packit fb9d21
Packit fb9d21
/* Read a subtree with band root node from "s".
Packit fb9d21
 */
Packit fb9d21
static __isl_give isl_schedule_tree *read_band(isl_stream *s)
Packit fb9d21
{
Packit fb9d21
	isl_multi_union_pw_aff *schedule = NULL;
Packit fb9d21
	isl_schedule_tree *tree = NULL;
Packit fb9d21
	isl_val_list *coincident = NULL;
Packit fb9d21
	isl_union_set *options = NULL;
Packit fb9d21
	isl_ctx *ctx;
Packit fb9d21
	isl_schedule_band *band;
Packit fb9d21
	int permutable = 0;
Packit fb9d21
	int more;
Packit fb9d21
Packit fb9d21
	ctx = isl_stream_get_ctx(s);
Packit fb9d21
Packit fb9d21
	do {
Packit fb9d21
		struct isl_token *tok;
Packit fb9d21
		enum isl_schedule_key key;
Packit fb9d21
		char *str;
Packit fb9d21
		isl_val *v;
Packit fb9d21
Packit fb9d21
		key = get_key(s);
Packit fb9d21
		if (isl_stream_yaml_next(s) < 0)
Packit fb9d21
			goto error;
Packit fb9d21
Packit fb9d21
		switch (key) {
Packit fb9d21
		case isl_schedule_key_schedule:
Packit fb9d21
			isl_multi_union_pw_aff_free(schedule);
Packit fb9d21
			tok = isl_stream_next_token(s);
Packit fb9d21
			if (!tok) {
Packit fb9d21
				isl_stream_error(s, NULL, "unexpected EOF");
Packit fb9d21
				goto error;
Packit fb9d21
			}
Packit fb9d21
			str = isl_token_get_str(ctx, tok);
Packit fb9d21
			schedule = isl_multi_union_pw_aff_read_from_str(ctx,
Packit fb9d21
									str);
Packit fb9d21
			free(str);
Packit fb9d21
			isl_token_free(tok);
Packit fb9d21
			if (!schedule)
Packit fb9d21
				goto error;
Packit fb9d21
			break;
Packit fb9d21
		case isl_schedule_key_coincident:
Packit fb9d21
			coincident = read_coincident(s);
Packit fb9d21
			if (!coincident)
Packit fb9d21
				goto error;
Packit fb9d21
			break;
Packit fb9d21
		case isl_schedule_key_permutable:
Packit fb9d21
			v = isl_stream_read_val(s);
Packit fb9d21
			permutable = !isl_val_is_zero(v);
Packit fb9d21
			isl_val_free(v);
Packit fb9d21
			break;
Packit fb9d21
		case isl_schedule_key_options:
Packit fb9d21
			isl_union_set_free(options);
Packit fb9d21
			tok = isl_stream_next_token(s);
Packit fb9d21
			str = isl_token_get_str(ctx, tok);
Packit fb9d21
			options = isl_union_set_read_from_str(ctx, str);
Packit fb9d21
			free(str);
Packit fb9d21
			isl_token_free(tok);
Packit fb9d21
			if (!options)
Packit fb9d21
				goto error;
Packit fb9d21
			break;
Packit fb9d21
		case isl_schedule_key_child:
Packit fb9d21
			isl_schedule_tree_free(tree);
Packit fb9d21
			tree = isl_stream_read_schedule_tree(s);
Packit fb9d21
			if (!tree)
Packit fb9d21
				goto error;
Packit fb9d21
			break;
Packit fb9d21
		default:
Packit fb9d21
			isl_die(ctx, isl_error_invalid, "unexpected key",
Packit fb9d21
				goto error);
Packit fb9d21
		}
Packit fb9d21
	} while ((more = isl_stream_yaml_next(s)) > 0);
Packit fb9d21
Packit fb9d21
	if (more < 0)
Packit fb9d21
		goto error;
Packit fb9d21
Packit fb9d21
	if (!schedule)
Packit fb9d21
		isl_die(ctx, isl_error_invalid, "missing schedule", goto error);
Packit fb9d21
Packit fb9d21
	band = isl_schedule_band_from_multi_union_pw_aff(schedule);
Packit fb9d21
	band = isl_schedule_band_set_permutable(band, permutable);
Packit fb9d21
	if (coincident)
Packit fb9d21
		band = set_coincident(band, coincident);
Packit fb9d21
	if (options)
Packit fb9d21
		band = isl_schedule_band_set_ast_build_options(band, options);
Packit fb9d21
	if (tree)
Packit fb9d21
		tree = isl_schedule_tree_insert_band(tree, band);
Packit fb9d21
	else
Packit fb9d21
		tree = isl_schedule_tree_from_band(band);
Packit fb9d21
Packit fb9d21
	return tree;
Packit fb9d21
error:
Packit fb9d21
	isl_val_list_free(coincident);
Packit fb9d21
	isl_union_set_free(options);
Packit fb9d21
	isl_schedule_tree_free(tree);
Packit fb9d21
	isl_multi_union_pw_aff_free(schedule);
Packit fb9d21
	return NULL;
Packit fb9d21
}
Packit fb9d21
Packit fb9d21
/* Read a subtree with root node of type "type" from "s".
Packit fb9d21
 * The node is represented by a sequence of children.
Packit fb9d21
 */
Packit fb9d21
static __isl_give isl_schedule_tree *read_children(isl_stream *s,
Packit fb9d21
	enum isl_schedule_node_type type)
Packit fb9d21
{
Packit fb9d21
	isl_ctx *ctx;
Packit fb9d21
	isl_schedule_tree_list *list;
Packit fb9d21
	int more;
Packit fb9d21
Packit fb9d21
	ctx = isl_stream_get_ctx(s);
Packit fb9d21
Packit fb9d21
	isl_token_free(isl_stream_next_token(s));
Packit fb9d21
Packit fb9d21
	if (isl_stream_yaml_next(s) < 0)
Packit fb9d21
		return NULL;
Packit fb9d21
Packit fb9d21
	if (isl_stream_yaml_read_start_sequence(s))
Packit fb9d21
		return NULL;
Packit fb9d21
Packit fb9d21
	list = isl_schedule_tree_list_alloc(ctx, 0);
Packit fb9d21
	while ((more = isl_stream_yaml_next(s)) > 0) {
Packit fb9d21
		isl_schedule_tree *tree;
Packit fb9d21
Packit fb9d21
		tree = isl_stream_read_schedule_tree(s);
Packit fb9d21
		list = isl_schedule_tree_list_add(list, tree);
Packit fb9d21
	}
Packit fb9d21
Packit fb9d21
	if (more < 0 || isl_stream_yaml_read_end_sequence(s))
Packit fb9d21
		list = isl_schedule_tree_list_free(list);
Packit fb9d21
Packit fb9d21
	return isl_schedule_tree_from_children(type, list);
Packit fb9d21
}
Packit fb9d21
Packit fb9d21
/* Read a subtree with sequence root node from "s".
Packit fb9d21
 */
Packit fb9d21
static __isl_give isl_schedule_tree *read_sequence(isl_stream *s)
Packit fb9d21
{
Packit fb9d21
	return read_children(s, isl_schedule_node_sequence);
Packit fb9d21
}
Packit fb9d21
Packit fb9d21
/* Read a subtree with set root node from "s".
Packit fb9d21
 */
Packit fb9d21
static __isl_give isl_schedule_tree *read_set(isl_stream *s)
Packit fb9d21
{
Packit fb9d21
	return read_children(s, isl_schedule_node_set);
Packit fb9d21
}
Packit fb9d21
Packit fb9d21
/* Read a schedule (sub)tree from "s".
Packit fb9d21
 *
Packit fb9d21
 * We first determine the type of the root node based on the first
Packit fb9d21
 * mapping key and then hand over to a function tailored to reading
Packit fb9d21
 * nodes of this type.
Packit fb9d21
 */
Packit fb9d21
static __isl_give isl_schedule_tree *isl_stream_read_schedule_tree(
Packit fb9d21
	struct isl_stream *s)
Packit fb9d21
{
Packit fb9d21
	enum isl_schedule_key key;
Packit fb9d21
	struct isl_token *tok;
Packit fb9d21
	isl_schedule_tree *tree = NULL;
Packit fb9d21
	int more;
Packit fb9d21
Packit fb9d21
	if (isl_stream_yaml_read_start_mapping(s))
Packit fb9d21
		return NULL;
Packit fb9d21
	more = isl_stream_yaml_next(s);
Packit fb9d21
	if (more < 0)
Packit fb9d21
		return NULL;
Packit fb9d21
	if (!more) {
Packit fb9d21
		isl_stream_error(s, NULL, "missing key");
Packit fb9d21
		return NULL;
Packit fb9d21
	}
Packit fb9d21
Packit fb9d21
	tok = isl_stream_next_token(s);
Packit fb9d21
	key = extract_key(s, tok);
Packit fb9d21
	isl_stream_push_token(s, tok);
Packit fb9d21
	if (key < 0)
Packit fb9d21
		return NULL;
Packit fb9d21
	switch (key) {
Packit fb9d21
	case isl_schedule_key_context:
Packit fb9d21
		tree = read_context(s);
Packit fb9d21
		break;
Packit fb9d21
	case isl_schedule_key_domain:
Packit fb9d21
		tree = read_domain(s);
Packit fb9d21
		break;
Packit fb9d21
	case isl_schedule_key_contraction:
Packit fb9d21
	case isl_schedule_key_expansion:
Packit fb9d21
		tree = read_expansion(s);
Packit fb9d21
		break;
Packit fb9d21
	case isl_schedule_key_extension:
Packit fb9d21
		tree = read_extension(s);
Packit fb9d21
		break;
Packit fb9d21
	case isl_schedule_key_filter:
Packit fb9d21
		tree = read_filter(s);
Packit fb9d21
		break;
Packit fb9d21
	case isl_schedule_key_guard:
Packit fb9d21
		tree = read_guard(s);
Packit fb9d21
		break;
Packit fb9d21
	case isl_schedule_key_leaf:
Packit fb9d21
		isl_token_free(isl_stream_next_token(s));
Packit fb9d21
		tree = isl_schedule_tree_leaf(isl_stream_get_ctx(s));
Packit fb9d21
		break;
Packit fb9d21
	case isl_schedule_key_mark:
Packit fb9d21
		tree = read_mark(s);
Packit fb9d21
		break;
Packit fb9d21
	case isl_schedule_key_sequence:
Packit fb9d21
		tree = read_sequence(s);
Packit fb9d21
		break;
Packit fb9d21
	case isl_schedule_key_set:
Packit fb9d21
		tree = read_set(s);
Packit fb9d21
		break;
Packit fb9d21
	case isl_schedule_key_schedule:
Packit fb9d21
	case isl_schedule_key_coincident:
Packit fb9d21
	case isl_schedule_key_options:
Packit fb9d21
	case isl_schedule_key_permutable:
Packit fb9d21
		tree = read_band(s);
Packit fb9d21
		break;
Packit fb9d21
	case isl_schedule_key_child:
Packit fb9d21
		isl_die(isl_stream_get_ctx(s), isl_error_unsupported,
Packit fb9d21
			"cannot identity node type", return NULL);
Packit fb9d21
	case isl_schedule_key_error:
Packit fb9d21
		return NULL;
Packit fb9d21
	}
Packit fb9d21
Packit fb9d21
	if (isl_stream_yaml_read_end_mapping(s) < 0) {
Packit fb9d21
		isl_stream_error(s, NULL, "unexpected extra elements");
Packit fb9d21
		return isl_schedule_tree_free(tree);
Packit fb9d21
	}
Packit fb9d21
Packit fb9d21
	return tree;
Packit fb9d21
}
Packit fb9d21
Packit fb9d21
/* Read an isl_schedule from "s".
Packit fb9d21
 */
Packit fb9d21
__isl_give isl_schedule *isl_stream_read_schedule(isl_stream *s)
Packit fb9d21
{
Packit fb9d21
	isl_ctx *ctx;
Packit fb9d21
	isl_schedule_tree *tree;
Packit fb9d21
Packit fb9d21
	if (!s)
Packit fb9d21
		return NULL;
Packit fb9d21
Packit fb9d21
	ctx = isl_stream_get_ctx(s);
Packit fb9d21
	tree = isl_stream_read_schedule_tree(s);
Packit fb9d21
	return isl_schedule_from_schedule_tree(ctx, tree);
Packit fb9d21
}
Packit fb9d21
Packit fb9d21
/* Read an isl_schedule from "input".
Packit fb9d21
 */
Packit fb9d21
__isl_give isl_schedule *isl_schedule_read_from_file(isl_ctx *ctx, FILE *input)
Packit fb9d21
{
Packit fb9d21
	struct isl_stream *s;
Packit fb9d21
	isl_schedule *schedule;
Packit fb9d21
Packit fb9d21
	s = isl_stream_new_file(ctx, input);
Packit fb9d21
	if (!s)
Packit fb9d21
		return NULL;
Packit fb9d21
	schedule = isl_stream_read_schedule(s);
Packit fb9d21
	isl_stream_free(s);
Packit fb9d21
Packit fb9d21
	return schedule;
Packit fb9d21
}
Packit fb9d21
Packit fb9d21
/* Read an isl_schedule from "str".
Packit fb9d21
 */
Packit fb9d21
__isl_give isl_schedule *isl_schedule_read_from_str(isl_ctx *ctx,
Packit fb9d21
	const char *str)
Packit fb9d21
{
Packit fb9d21
	struct isl_stream *s;
Packit fb9d21
	isl_schedule *schedule;
Packit fb9d21
Packit fb9d21
	s = isl_stream_new_str(ctx, str);
Packit fb9d21
	if (!s)
Packit fb9d21
		return NULL;
Packit fb9d21
	schedule = isl_stream_read_schedule(s);
Packit fb9d21
	isl_stream_free(s);
Packit fb9d21
Packit fb9d21
	return schedule;
Packit fb9d21
}