pet 0.04
[pet.git] / parse.c
blobfd25934ae3bd6d00a4e60753ea3d6be016d23225
1 /*
2 * Copyright 2011 Leiden University. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above
12 * copyright notice, this list of conditions and the following
13 * disclaimer in the documentation and/or other materials provided
14 * with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY LEIDEN UNIVERSITY ''AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL LEIDEN UNIVERSITY OR
20 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
23 * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 * The views and conclusions contained in the software and documentation
29 * are those of the authors and should not be interpreted as
30 * representing official policies, either expressed or implied, of
31 * Leiden University.
32 */
34 #include <stdlib.h>
35 #include <yaml.h>
37 #include "scop.h"
38 #include "scop_yaml.h"
40 static char *extract_string(isl_ctx *ctx, yaml_document_t *document,
41 yaml_node_t *node)
43 if (node->type != YAML_SCALAR_NODE)
44 isl_die(ctx, isl_error_invalid, "expecting scalar node",
45 return NULL);
47 return strdup((char *) node->data.scalar.value);
50 static int extract_int(isl_ctx *ctx, yaml_document_t *document,
51 yaml_node_t *node)
53 if (node->type != YAML_SCALAR_NODE)
54 isl_die(ctx, isl_error_invalid, "expecting scalar node",
55 return -1);
57 return atoi((char *) node->data.scalar.value);
60 static double extract_double(isl_ctx *ctx, yaml_document_t *document,
61 yaml_node_t *node)
63 if (node->type != YAML_SCALAR_NODE)
64 isl_die(ctx, isl_error_invalid, "expecting scalar node",
65 return -1);
67 return strtod((char *) node->data.scalar.value, NULL);
70 static enum pet_expr_type extract_type(isl_ctx *ctx, yaml_document_t *document,
71 yaml_node_t *node)
73 if (node->type != YAML_SCALAR_NODE)
74 isl_die(ctx, isl_error_invalid, "expecting scalar node",
75 return -1);
77 return pet_str_type((char *) node->data.scalar.value);
80 static enum pet_op_type extract_op(isl_ctx *ctx, yaml_document_t *document,
81 yaml_node_t *node)
83 if (node->type != YAML_SCALAR_NODE)
84 isl_die(ctx, isl_error_invalid, "expecting scalar node",
85 return -1);
87 return pet_str_op((char *) node->data.scalar.value);
90 static __isl_give isl_set *extract_set(isl_ctx *ctx, yaml_document_t *document,
91 yaml_node_t *node)
93 if (node->type != YAML_SCALAR_NODE)
94 isl_die(ctx, isl_error_invalid, "expecting scalar node",
95 return NULL);
97 return isl_set_read_from_str(ctx, (char *) node->data.scalar.value);
100 static __isl_give isl_map *extract_map(isl_ctx *ctx, yaml_document_t *document,
101 yaml_node_t *node)
103 if (node->type != YAML_SCALAR_NODE)
104 isl_die(ctx, isl_error_invalid, "expecting scalar node",
105 return NULL);
107 return isl_map_read_from_str(ctx, (char *) node->data.scalar.value);
110 static struct pet_array *extract_array(isl_ctx *ctx, yaml_document_t *document,
111 yaml_node_t *node)
113 struct pet_array *array;
114 yaml_node_pair_t * pair;
116 if (node->type != YAML_MAPPING_NODE)
117 isl_die(ctx, isl_error_invalid, "expecting mapping",
118 return NULL);
120 array = isl_calloc_type(ctx, struct pet_array);
121 if (!array)
122 return NULL;
124 for (pair = node->data.mapping.pairs.start;
125 pair < node->data.mapping.pairs.top; ++pair) {
126 yaml_node_t *key, *value;
128 key = yaml_document_get_node(document, pair->key);
129 value = yaml_document_get_node(document, pair->value);
131 if (key->type != YAML_SCALAR_NODE)
132 isl_die(ctx, isl_error_invalid, "expecting scalar key",
133 return pet_array_free(array));
135 if (!strcmp((char *) key->data.scalar.value, "context"))
136 array->context = extract_set(ctx, document, value);
137 if (!strcmp((char *) key->data.scalar.value, "extent"))
138 array->extent = extract_set(ctx, document, value);
139 if (!strcmp((char *) key->data.scalar.value, "value_bounds"))
140 array->value_bounds = extract_set(ctx, document, value);
141 if (!strcmp((char *) key->data.scalar.value, "element_type"))
142 array->element_type =
143 extract_string(ctx, document, value);
144 if (!strcmp((char *) key->data.scalar.value, "element_size"))
145 array->element_size = extract_int(ctx, document, value);
146 if (!strcmp((char *) key->data.scalar.value, "live_out"))
147 array->live_out = extract_int(ctx, document, value);
148 if (!strcmp((char *) key->data.scalar.value,
149 "uniquely_defined"))
150 array->uniquely_defined =
151 extract_int(ctx, document, value);
152 if (!strcmp((char *) key->data.scalar.value, "declared"))
153 array->declared = extract_int(ctx, document, value);
154 if (!strcmp((char *) key->data.scalar.value, "exposed"))
155 array->exposed = extract_int(ctx, document, value);
158 return array;
161 static struct pet_scop *extract_arrays(isl_ctx *ctx, yaml_document_t *document,
162 yaml_node_t *node, struct pet_scop *scop)
164 int i;
165 yaml_node_item_t *item;
167 if (node->type != YAML_SEQUENCE_NODE)
168 isl_die(ctx, isl_error_invalid, "expecting sequence",
169 return NULL);
171 scop->n_array = node->data.sequence.items.top
172 - node->data.sequence.items.start;
173 scop->arrays = isl_calloc_array(ctx, struct pet_array *, scop->n_array);
174 if (!scop->arrays)
175 return pet_scop_free(scop);
177 for (item = node->data.sequence.items.start, i = 0;
178 item < node->data.sequence.items.top; ++item, ++i) {
179 yaml_node_t *n;
181 n = yaml_document_get_node(document, *item);
182 scop->arrays[i] = extract_array(ctx, document, n);
183 if (!scop->arrays[i])
184 return pet_scop_free(scop);
187 return scop;
190 static struct pet_expr *extract_expr(isl_ctx *ctx, yaml_document_t *document,
191 yaml_node_t *node);
193 static struct pet_expr *extract_arguments(isl_ctx *ctx,
194 yaml_document_t *document, yaml_node_t *node, struct pet_expr *expr)
196 int i;
197 yaml_node_item_t *item;
199 if (node->type != YAML_SEQUENCE_NODE)
200 isl_die(ctx, isl_error_invalid, "expecting sequence",
201 return pet_expr_free(expr));
203 expr->n_arg = node->data.sequence.items.top
204 - node->data.sequence.items.start;
205 expr->args = isl_calloc_array(ctx, struct pet_expr *, expr->n_arg);
206 if (!expr->args)
207 return pet_expr_free(expr);
209 for (item = node->data.sequence.items.start, i = 0;
210 item < node->data.sequence.items.top; ++item, ++i) {
211 yaml_node_t *n;
213 n = yaml_document_get_node(document, *item);
214 expr->args[i] = extract_expr(ctx, document, n);
215 if (!expr->args[i])
216 return pet_expr_free(expr);
219 return expr;
222 /* Extract pet_expr_double specific fields from "node" and
223 * update "expr" accordingly.
225 static struct pet_expr *extract_expr_double(isl_ctx *ctx,
226 yaml_document_t *document, yaml_node_t *node, struct pet_expr *expr)
228 yaml_node_pair_t *pair;
230 for (pair = node->data.mapping.pairs.start;
231 pair < node->data.mapping.pairs.top; ++pair) {
232 yaml_node_t *key, *value;
234 key = yaml_document_get_node(document, pair->key);
235 value = yaml_document_get_node(document, pair->value);
237 if (key->type != YAML_SCALAR_NODE)
238 isl_die(ctx, isl_error_invalid, "expecting scalar key",
239 return pet_expr_free(expr));
241 if (!strcmp((char *) key->data.scalar.value, "value"))
242 expr->d.val = extract_double(ctx, document, value);
243 if (!strcmp((char *) key->data.scalar.value, "string"))
244 expr->d.s = extract_string(ctx, document, value);
247 return expr;
250 /* Extract pet_expr_access specific fields from "node" and
251 * update "expr" accordingly.
253 static struct pet_expr *extract_expr_access(isl_ctx *ctx,
254 yaml_document_t *document, yaml_node_t *node, struct pet_expr *expr)
256 yaml_node_pair_t *pair;
258 for (pair = node->data.mapping.pairs.start;
259 pair < node->data.mapping.pairs.top; ++pair) {
260 yaml_node_t *key, *value;
262 key = yaml_document_get_node(document, pair->key);
263 value = yaml_document_get_node(document, pair->value);
265 if (key->type != YAML_SCALAR_NODE)
266 isl_die(ctx, isl_error_invalid, "expecting scalar key",
267 return pet_expr_free(expr));
269 if (!strcmp((char *) key->data.scalar.value, "relation"))
270 expr->acc.access = extract_map(ctx, document, value);
271 if (!strcmp((char *) key->data.scalar.value, "read"))
272 expr->acc.read = extract_int(ctx, document, value);
273 if (!strcmp((char *) key->data.scalar.value, "write"))
274 expr->acc.write = extract_int(ctx, document, value);
277 return expr;
280 /* Extract operation expression specific fields from "node" and
281 * update "expr" accordingly.
283 static struct pet_expr *extract_expr_op(isl_ctx *ctx,
284 yaml_document_t *document, yaml_node_t *node, struct pet_expr *expr)
286 yaml_node_pair_t *pair;
288 for (pair = node->data.mapping.pairs.start;
289 pair < node->data.mapping.pairs.top; ++pair) {
290 yaml_node_t *key, *value;
292 key = yaml_document_get_node(document, pair->key);
293 value = yaml_document_get_node(document, pair->value);
295 if (key->type != YAML_SCALAR_NODE)
296 isl_die(ctx, isl_error_invalid, "expecting scalar key",
297 return pet_expr_free(expr));
299 if (!strcmp((char *) key->data.scalar.value, "operation"))
300 expr->op = extract_op(ctx, document, value);
303 return expr;
306 /* Extract pet_expr_call specific fields from "node" and
307 * update "expr" accordingly.
309 static struct pet_expr *extract_expr_call(isl_ctx *ctx,
310 yaml_document_t *document, yaml_node_t *node, struct pet_expr *expr)
312 yaml_node_pair_t *pair;
314 for (pair = node->data.mapping.pairs.start;
315 pair < node->data.mapping.pairs.top; ++pair) {
316 yaml_node_t *key, *value;
318 key = yaml_document_get_node(document, pair->key);
319 value = yaml_document_get_node(document, pair->value);
321 if (key->type != YAML_SCALAR_NODE)
322 isl_die(ctx, isl_error_invalid, "expecting scalar key",
323 return pet_expr_free(expr));
325 if (!strcmp((char *) key->data.scalar.value, "name"))
326 expr->name = extract_string(ctx, document, value);
329 return expr;
332 /* Extract pet_expr_cast specific fields from "node" and
333 * update "expr" accordingly.
335 static struct pet_expr *extract_expr_cast(isl_ctx *ctx,
336 yaml_document_t *document, yaml_node_t *node, struct pet_expr *expr)
338 yaml_node_pair_t *pair;
340 for (pair = node->data.mapping.pairs.start;
341 pair < node->data.mapping.pairs.top; ++pair) {
342 yaml_node_t *key, *value;
344 key = yaml_document_get_node(document, pair->key);
345 value = yaml_document_get_node(document, pair->value);
347 if (key->type != YAML_SCALAR_NODE)
348 isl_die(ctx, isl_error_invalid, "expecting scalar key",
349 return pet_expr_free(expr));
351 if (!strcmp((char *) key->data.scalar.value, "type_name"))
352 expr->type_name = extract_string(ctx, document, value);
355 return expr;
358 /* Extract a pet_expr from "node".
360 * We first extract the type and arguments of the expression and
361 * then extract additional fields depending on the type.
363 static struct pet_expr *extract_expr(isl_ctx *ctx, yaml_document_t *document,
364 yaml_node_t *node)
366 struct pet_expr *expr;
367 yaml_node_pair_t *pair;
369 if (node->type != YAML_MAPPING_NODE)
370 isl_die(ctx, isl_error_invalid, "expecting mapping",
371 return NULL);
373 expr = isl_calloc_type(ctx, struct pet_expr);
374 if (!expr)
375 return NULL;
377 for (pair = node->data.mapping.pairs.start;
378 pair < node->data.mapping.pairs.top; ++pair) {
379 yaml_node_t *key, *value;
381 key = yaml_document_get_node(document, pair->key);
382 value = yaml_document_get_node(document, pair->value);
384 if (key->type != YAML_SCALAR_NODE)
385 isl_die(ctx, isl_error_invalid, "expecting scalar key",
386 return pet_expr_free(expr));
388 if (!strcmp((char *) key->data.scalar.value, "type"))
389 expr->type = extract_type(ctx, document, value);
391 if (!strcmp((char *) key->data.scalar.value, "arguments"))
392 expr = extract_arguments(ctx, document, value, expr);
393 if (!expr)
394 return NULL;
397 switch (expr->type) {
398 case pet_expr_access:
399 expr = extract_expr_access(ctx, document, node, expr);
400 break;
401 case pet_expr_double:
402 expr = extract_expr_double(ctx, document, node, expr);
403 break;
404 case pet_expr_call:
405 expr = extract_expr_call(ctx, document, node, expr);
406 break;
407 case pet_expr_cast:
408 expr = extract_expr_cast(ctx, document, node, expr);
409 break;
410 case pet_expr_unary:
411 case pet_expr_binary:
412 case pet_expr_ternary:
413 expr = extract_expr_op(ctx, document, node, expr);
414 break;
417 return expr;
420 static struct pet_stmt *extract_stmt_arguments(isl_ctx *ctx,
421 yaml_document_t *document, yaml_node_t *node, struct pet_stmt *stmt)
423 int i;
424 yaml_node_item_t *item;
426 if (node->type != YAML_SEQUENCE_NODE)
427 isl_die(ctx, isl_error_invalid, "expecting sequence",
428 return pet_stmt_free(stmt));
430 stmt->n_arg = node->data.sequence.items.top
431 - node->data.sequence.items.start;
432 stmt->args = isl_calloc_array(ctx, struct pet_expr *, stmt->n_arg);
433 if (!stmt->args)
434 return pet_stmt_free(stmt);
436 for (item = node->data.sequence.items.start, i = 0;
437 item < node->data.sequence.items.top; ++item, ++i) {
438 yaml_node_t *n;
440 n = yaml_document_get_node(document, *item);
441 stmt->args[i] = extract_expr(ctx, document, n);
442 if (!stmt->args[i])
443 return pet_stmt_free(stmt);
446 return stmt;
449 static struct pet_stmt *extract_stmt(isl_ctx *ctx, yaml_document_t *document,
450 yaml_node_t *node)
452 struct pet_stmt *stmt;
453 yaml_node_pair_t * pair;
455 if (node->type != YAML_MAPPING_NODE)
456 isl_die(ctx, isl_error_invalid, "expecting mapping",
457 return NULL);
459 stmt = isl_calloc_type(ctx, struct pet_stmt);
460 if (!stmt)
461 return NULL;
463 for (pair = node->data.mapping.pairs.start;
464 pair < node->data.mapping.pairs.top; ++pair) {
465 yaml_node_t *key, *value;
467 key = yaml_document_get_node(document, pair->key);
468 value = yaml_document_get_node(document, pair->value);
470 if (key->type != YAML_SCALAR_NODE)
471 isl_die(ctx, isl_error_invalid, "expecting scalar key",
472 return pet_stmt_free(stmt));
474 if (!strcmp((char *) key->data.scalar.value, "line"))
475 stmt->line = extract_int(ctx, document, value);
476 if (!strcmp((char *) key->data.scalar.value, "domain"))
477 stmt->domain = extract_set(ctx, document, value);
478 if (!strcmp((char *) key->data.scalar.value, "schedule"))
479 stmt->schedule = extract_map(ctx, document, value);
480 if (!strcmp((char *) key->data.scalar.value, "body"))
481 stmt->body = extract_expr(ctx, document, value);
483 if (!strcmp((char *) key->data.scalar.value, "arguments"))
484 stmt = extract_stmt_arguments(ctx, document,
485 value, stmt);
486 if (!stmt)
487 return NULL;
490 return stmt;
493 static struct pet_scop *extract_statements(isl_ctx *ctx,
494 yaml_document_t *document, yaml_node_t *node, struct pet_scop *scop)
496 int i;
497 yaml_node_item_t *item;
499 if (node->type != YAML_SEQUENCE_NODE)
500 isl_die(ctx, isl_error_invalid, "expecting sequence",
501 return NULL);
503 scop->n_stmt = node->data.sequence.items.top
504 - node->data.sequence.items.start;
505 scop->stmts = isl_calloc_array(ctx, struct pet_stmt *, scop->n_stmt);
506 if (!scop->stmts)
507 return pet_scop_free(scop);
509 for (item = node->data.sequence.items.start, i = 0;
510 item < node->data.sequence.items.top; ++item, ++i) {
511 yaml_node_t *n;
513 n = yaml_document_get_node(document, *item);
514 scop->stmts[i] = extract_stmt(ctx, document, n);
515 if (!scop->stmts[i])
516 return pet_scop_free(scop);
519 return scop;
522 static struct pet_scop *extract_scop(isl_ctx *ctx, yaml_document_t *document,
523 yaml_node_t *node)
525 struct pet_scop *scop;
526 yaml_node_pair_t * pair;
528 if (!node)
529 return NULL;
531 if (node->type != YAML_MAPPING_NODE)
532 isl_die(ctx, isl_error_invalid, "expecting mapping",
533 return NULL);
535 scop = pet_scop_alloc(ctx);
536 if (!scop)
537 return NULL;
539 for (pair = node->data.mapping.pairs.start;
540 pair < node->data.mapping.pairs.top; ++pair) {
541 yaml_node_t *key, *value;
543 key = yaml_document_get_node(document, pair->key);
544 value = yaml_document_get_node(document, pair->value);
546 if (key->type != YAML_SCALAR_NODE)
547 isl_die(ctx, isl_error_invalid, "expecting scalar key",
548 return pet_scop_free(scop));
549 if (!strcmp((char *) key->data.scalar.value, "context"))
550 scop->context = extract_set(ctx, document, value);
551 if (!strcmp((char *) key->data.scalar.value, "context_value"))
552 scop->context_value = extract_set(ctx, document, value);
553 if (!strcmp((char *) key->data.scalar.value, "arrays"))
554 scop = extract_arrays(ctx, document, value, scop);
555 if (!strcmp((char *) key->data.scalar.value, "statements"))
556 scop = extract_statements(ctx, document, value, scop);
557 if (!scop)
558 return NULL;
561 if (!scop->context_value) {
562 isl_space *space = isl_space_params_alloc(ctx, 0);
563 scop->context_value = isl_set_universe(space);
564 if (!scop->context_value)
565 return pet_scop_free(scop);
568 return scop;
571 /* Extract a pet_scop from the YAML description in "in".
573 struct pet_scop *pet_scop_parse(isl_ctx *ctx, FILE *in)
575 struct pet_scop *scop = NULL;
576 yaml_parser_t parser;
577 yaml_node_t *root;
578 yaml_document_t document = { 0 };
580 yaml_parser_initialize(&parser);
582 yaml_parser_set_input_file(&parser, in);
584 if (!yaml_parser_load(&parser, &document))
585 goto error;
587 root = yaml_document_get_root_node(&document);
589 scop = extract_scop(ctx, &document, root);
591 yaml_document_delete(&document);
593 yaml_parser_delete(&parser);
595 return scop;
596 error:
597 yaml_parser_delete(&parser);
598 pet_scop_free(scop);
599 return NULL;