iscc: add lexicographic operators
[barvinok.git] / iscc.c
blobd675ca17788c38e5ef6c7e124bb44a3cd10a133f
1 #include <assert.h>
2 #include <stdio.h>
3 #include <string.h>
4 #include <isl_obj.h>
5 #include <isl_stream.h>
6 #include <isl_vertices.h>
7 #include <isl_obj_list.h>
8 #include <isl_obj_str.h>
9 #include <barvinok/barvinok.h>
11 #include "config.h"
13 #ifdef HAVE_CLOOG
14 #include <cloog/isl/cloog.h>
15 #endif
17 static int isl_bool_false = 0;
18 static int isl_bool_true = 1;
19 static int isl_bool_error = -1;
21 static enum isl_token_type read_op;
22 static enum isl_token_type source_op;
23 static enum isl_token_type vertices_op;
25 struct isl_arg_choice iscc_format[] = {
26 {"isl", ISL_FORMAT_ISL},
27 {"omega", ISL_FORMAT_OMEGA},
28 {"polylib", ISL_FORMAT_POLYLIB},
29 {"latex", ISL_FORMAT_LATEX},
30 {"C", ISL_FORMAT_C},
31 {0}
34 struct iscc_options {
35 struct barvinok_options *barvinok;
36 unsigned format;
39 struct isl_arg iscc_options_arg[] = {
40 ISL_ARG_CHILD(struct iscc_options, barvinok, "barvinok", barvinok_options_arg,
41 "barvinok options")
42 ISL_ARG_CHOICE(struct iscc_options, format, 0, "format", \
43 iscc_format, ISL_FORMAT_ISL, "output format")
44 ISL_ARG_END
47 ISL_ARG_DEF(iscc_options, struct iscc_options, iscc_options_arg)
49 static void *isl_obj_bool_copy(void *v)
51 return v;
54 static void isl_obj_bool_free(void *v)
58 static __isl_give isl_printer *isl_obj_bool_print(__isl_take isl_printer *p,
59 void *v)
61 if (v == &isl_bool_true)
62 return isl_printer_print_str(p, "True");
63 else if (v == &isl_bool_false)
64 return isl_printer_print_str(p, "False");
65 else
66 return isl_printer_print_str(p, "Error");
69 static void *isl_obj_bool_add(void *v1, void *v2)
71 return v1;
74 struct isl_obj_vtable isl_obj_bool_vtable = {
75 isl_obj_bool_copy,
76 isl_obj_bool_add,
77 isl_obj_bool_print,
78 isl_obj_bool_free
80 #define isl_obj_bool (&isl_obj_bool_vtable)
82 int *isl_bool_from_int(int res)
84 return res < 0 ? &isl_bool_error : res ? &isl_bool_true : &isl_bool_false;
87 int *union_map_is_equal(__isl_take isl_union_map *map1,
88 __isl_take isl_union_map *map2)
90 int res = isl_union_map_is_equal(map1, map2);
91 isl_union_map_free(map1);
92 isl_union_map_free(map2);
93 return isl_bool_from_int(res);
95 int *union_set_is_equal(__isl_take isl_union_set *set1,
96 __isl_take isl_union_set *set2)
98 return union_map_is_equal((isl_union_map *)set1, (isl_union_map *)set2);
101 int *union_map_is_subset(__isl_take isl_union_map *map1,
102 __isl_take isl_union_map *map2)
104 int res = isl_union_map_is_subset(map1, map2);
105 isl_union_map_free(map1);
106 isl_union_map_free(map2);
107 return isl_bool_from_int(res);
109 int *union_set_is_subset(__isl_take isl_union_set *set1,
110 __isl_take isl_union_set *set2)
112 return union_map_is_subset((isl_union_map *)set1, (isl_union_map *)set2);
115 int *union_map_is_strict_subset(__isl_take isl_union_map *map1,
116 __isl_take isl_union_map *map2)
118 int res = isl_union_map_is_strict_subset(map1, map2);
119 isl_union_map_free(map1);
120 isl_union_map_free(map2);
121 return isl_bool_from_int(res);
123 int *union_set_is_strict_subset(__isl_take isl_union_set *set1,
124 __isl_take isl_union_set *set2)
126 return union_map_is_strict_subset((isl_union_map *)set1,
127 (isl_union_map *)set2);
130 int *union_map_is_superset(__isl_take isl_union_map *map1,
131 __isl_take isl_union_map *map2)
133 return union_map_is_subset(map2, map1);
135 int *union_set_is_superset(__isl_take isl_union_set *set1,
136 __isl_take isl_union_set *set2)
138 return union_set_is_subset(set2, set1);
141 int *union_map_is_strict_superset(__isl_take isl_union_map *map1,
142 __isl_take isl_union_map *map2)
144 return union_map_is_strict_subset(map2, map1);
146 int *union_set_is_strict_superset(__isl_take isl_union_set *set1,
147 __isl_take isl_union_set *set2)
149 return union_set_is_strict_subset(set2, set1);
152 extern struct isl_obj_vtable isl_obj_list_vtable;
153 #define isl_obj_list (&isl_obj_list_vtable)
155 typedef void *(*isc_bin_op_fn)(void *lhs, void *rhs);
156 struct isc_bin_op {
157 enum isl_token_type op;
158 isl_obj_type lhs;
159 isl_obj_type rhs;
160 isl_obj_type res;
161 isc_bin_op_fn fn;
163 struct isc_named_bin_op {
164 char *name;
165 struct isc_bin_op op;
168 struct iscc_at {
169 isl_union_pw_qpolynomial *upwqp;
170 isl_union_pw_qpolynomial *res;
173 static int eval_at(__isl_take isl_point *pnt, void *user)
175 struct iscc_at *at = (struct iscc_at *) user;
176 isl_qpolynomial *qp;
177 isl_set *set;
179 set = isl_set_from_point(isl_point_copy(pnt));
180 qp = isl_union_pw_qpolynomial_eval(
181 isl_union_pw_qpolynomial_copy(at->upwqp), pnt);
183 at->res = isl_union_pw_qpolynomial_add(at->res,
184 isl_union_pw_qpolynomial_from_pw_qpolynomial(
185 isl_pw_qpolynomial_alloc(set, qp)));
187 return 0;
190 __isl_give isl_union_pw_qpolynomial *isl_union_pw_qpolynomial_at(
191 __isl_take isl_union_pw_qpolynomial *upwqp,
192 __isl_take isl_union_set *uset)
194 struct iscc_at at;
196 at.upwqp = upwqp;
197 at.res = isl_union_pw_qpolynomial_zero(isl_union_set_get_dim(uset));
199 isl_union_set_foreach_point(uset, eval_at, &at);
201 isl_union_pw_qpolynomial_free(upwqp);
202 isl_union_set_free(uset);
204 return at.res;
207 struct iscc_fold_at {
208 isl_union_pw_qpolynomial_fold *upwf;
209 isl_union_pw_qpolynomial *res;
212 static int eval_fold_at(__isl_take isl_point *pnt, void *user)
214 struct iscc_fold_at *at = (struct iscc_fold_at *) user;
215 isl_qpolynomial *qp;
216 isl_set *set;
218 set = isl_set_from_point(isl_point_copy(pnt));
219 qp = isl_union_pw_qpolynomial_fold_eval(
220 isl_union_pw_qpolynomial_fold_copy(at->upwf), pnt);
222 at->res = isl_union_pw_qpolynomial_add(at->res,
223 isl_union_pw_qpolynomial_from_pw_qpolynomial(
224 isl_pw_qpolynomial_alloc(set, qp)));
226 return 0;
229 __isl_give isl_union_pw_qpolynomial *isl_union_pw_qpolynomial_fold_at(
230 __isl_take isl_union_pw_qpolynomial_fold *upwf,
231 __isl_take isl_union_set *uset)
233 struct iscc_fold_at at;
235 at.upwf = upwf;
236 at.res = isl_union_pw_qpolynomial_zero(isl_union_set_get_dim(uset));
238 isl_union_set_foreach_point(uset, eval_fold_at, &at);
240 isl_union_pw_qpolynomial_fold_free(upwf);
241 isl_union_set_free(uset);
243 return at.res;
246 static __isl_give isl_union_pw_qpolynomial_fold *union_pw_qpolynomial_add_union_pw_qpolynomial_fold(
247 __isl_take isl_union_pw_qpolynomial *upwqp,
248 __isl_take isl_union_pw_qpolynomial_fold *upwf)
250 return isl_union_pw_qpolynomial_fold_add_union_pw_qpolynomial(upwf,
251 upwqp);
254 static __isl_give struct isl_list *union_map_apply_union_pw_qpolynomial_fold(
255 __isl_take isl_union_map *umap,
256 __isl_take isl_union_pw_qpolynomial_fold *upwf)
258 isl_ctx *ctx;
259 struct isl_list *list;
260 int tight;
262 ctx = isl_union_map_get_ctx(umap);
263 list = isl_list_alloc(ctx, 2);
264 if (!list)
265 goto error2;
267 list->obj[0].type = isl_obj_union_pw_qpolynomial_fold;
268 list->obj[0].v = isl_union_map_apply_union_pw_qpolynomial_fold(umap,
269 upwf, &tight);
270 list->obj[1].type = isl_obj_bool;
271 list->obj[1].v = tight ? &isl_bool_true : &isl_bool_false;
272 if (tight < 0 || !list->obj[0].v)
273 goto error;
275 return list;
276 error2:
277 isl_union_map_free(umap);
278 isl_union_pw_qpolynomial_fold_free(upwf);
279 error:
280 isl_list_free(list);
281 return NULL;
284 struct isc_bin_op bin_ops[] = {
285 { '+', isl_obj_union_set, isl_obj_union_set,
286 isl_obj_union_set,
287 (isc_bin_op_fn) &isl_union_set_union },
288 { '+', isl_obj_union_map, isl_obj_union_map,
289 isl_obj_union_map,
290 (isc_bin_op_fn) &isl_union_map_union },
291 { '-', isl_obj_union_set, isl_obj_union_set,
292 isl_obj_union_set,
293 (isc_bin_op_fn) &isl_union_set_subtract },
294 { '-', isl_obj_union_map, isl_obj_union_map,
295 isl_obj_union_map,
296 (isc_bin_op_fn) &isl_union_map_subtract },
297 { '*', isl_obj_union_set, isl_obj_union_set,
298 isl_obj_union_set,
299 (isc_bin_op_fn) &isl_union_set_intersect },
300 { '*', isl_obj_union_map, isl_obj_union_map,
301 isl_obj_union_map,
302 (isc_bin_op_fn) &isl_union_map_intersect },
303 { '*', isl_obj_union_map, isl_obj_union_set,
304 isl_obj_union_map,
305 (isc_bin_op_fn) &isl_union_map_intersect_domain },
306 { '.', isl_obj_union_map, isl_obj_union_map,
307 isl_obj_union_map,
308 (isc_bin_op_fn) &isl_union_map_apply_range },
309 { '.', isl_obj_union_map, isl_obj_union_pw_qpolynomial,
310 isl_obj_union_pw_qpolynomial,
311 (isc_bin_op_fn) &isl_union_map_apply_union_pw_qpolynomial },
312 { '.', isl_obj_union_map, isl_obj_union_pw_qpolynomial_fold,
313 isl_obj_list,
314 (isc_bin_op_fn) &union_map_apply_union_pw_qpolynomial_fold },
315 { ISL_TOKEN_TO, isl_obj_union_set, isl_obj_union_set,
316 isl_obj_union_map,
317 (isc_bin_op_fn) &isl_union_map_from_domain_and_range },
318 { '=', isl_obj_union_set, isl_obj_union_set, isl_obj_bool,
319 (isc_bin_op_fn) &union_set_is_equal },
320 { '=', isl_obj_union_map, isl_obj_union_map, isl_obj_bool,
321 (isc_bin_op_fn) &union_map_is_equal },
322 { ISL_TOKEN_LE, isl_obj_union_set, isl_obj_union_set,
323 isl_obj_bool, (isc_bin_op_fn) &union_set_is_subset },
324 { ISL_TOKEN_LE, isl_obj_union_map, isl_obj_union_map,
325 isl_obj_bool, (isc_bin_op_fn) &union_map_is_subset },
326 { ISL_TOKEN_LT, isl_obj_union_set, isl_obj_union_set,
327 isl_obj_bool, (isc_bin_op_fn) &union_set_is_strict_subset },
328 { ISL_TOKEN_LT, isl_obj_union_map, isl_obj_union_map,
329 isl_obj_bool, (isc_bin_op_fn) &union_map_is_strict_subset },
330 { ISL_TOKEN_GE, isl_obj_union_set, isl_obj_union_set,
331 isl_obj_bool, (isc_bin_op_fn) &union_set_is_superset },
332 { ISL_TOKEN_GE, isl_obj_union_map, isl_obj_union_map,
333 isl_obj_bool, (isc_bin_op_fn) &union_map_is_superset },
334 { ISL_TOKEN_GT, isl_obj_union_set, isl_obj_union_set,
335 isl_obj_bool, (isc_bin_op_fn) &union_set_is_strict_superset },
336 { ISL_TOKEN_GT, isl_obj_union_map, isl_obj_union_map,
337 isl_obj_bool, (isc_bin_op_fn) &union_map_is_strict_superset },
338 { ISL_TOKEN_LEX_LE, isl_obj_union_set, isl_obj_union_set,
339 isl_obj_union_map,
340 (isc_bin_op_fn) &isl_union_set_lex_le_union_set },
341 { ISL_TOKEN_LEX_LT, isl_obj_union_set, isl_obj_union_set,
342 isl_obj_union_map,
343 (isc_bin_op_fn) &isl_union_set_lex_lt_union_set },
344 { ISL_TOKEN_LEX_GE, isl_obj_union_set, isl_obj_union_set,
345 isl_obj_union_map,
346 (isc_bin_op_fn) &isl_union_set_lex_ge_union_set },
347 { ISL_TOKEN_LEX_GT, isl_obj_union_set, isl_obj_union_set,
348 isl_obj_union_map,
349 (isc_bin_op_fn) &isl_union_set_lex_gt_union_set },
350 { ISL_TOKEN_LEX_LE, isl_obj_union_map, isl_obj_union_map,
351 isl_obj_union_map,
352 (isc_bin_op_fn) &isl_union_map_lex_le_union_map },
353 { ISL_TOKEN_LEX_LT, isl_obj_union_map, isl_obj_union_map,
354 isl_obj_union_map,
355 (isc_bin_op_fn) &isl_union_map_lex_lt_union_map },
356 { ISL_TOKEN_LEX_GE, isl_obj_union_map, isl_obj_union_map,
357 isl_obj_union_map,
358 (isc_bin_op_fn) &isl_union_map_lex_ge_union_map },
359 { ISL_TOKEN_LEX_GT, isl_obj_union_map, isl_obj_union_map,
360 isl_obj_union_map,
361 (isc_bin_op_fn) &isl_union_map_lex_gt_union_map },
362 { '.', isl_obj_union_pw_qpolynomial_fold,
363 isl_obj_union_pw_qpolynomial_fold,
364 isl_obj_union_pw_qpolynomial_fold,
365 (isc_bin_op_fn) &isl_union_pw_qpolynomial_fold_fold },
366 { '+', isl_obj_union_pw_qpolynomial, isl_obj_union_pw_qpolynomial,
367 isl_obj_union_pw_qpolynomial,
368 (isc_bin_op_fn) &isl_union_pw_qpolynomial_add },
369 { '+', isl_obj_union_pw_qpolynomial,
370 isl_obj_union_pw_qpolynomial_fold,
371 isl_obj_union_pw_qpolynomial_fold,
372 (isc_bin_op_fn) &union_pw_qpolynomial_add_union_pw_qpolynomial_fold },
373 { '+', isl_obj_union_pw_qpolynomial_fold,
374 isl_obj_union_pw_qpolynomial,
375 isl_obj_union_pw_qpolynomial_fold,
376 (isc_bin_op_fn) &isl_union_pw_qpolynomial_fold_add_union_pw_qpolynomial },
377 { '-', isl_obj_union_pw_qpolynomial, isl_obj_union_pw_qpolynomial,
378 isl_obj_union_pw_qpolynomial,
379 (isc_bin_op_fn) &isl_union_pw_qpolynomial_sub },
380 { '*', isl_obj_union_pw_qpolynomial, isl_obj_union_pw_qpolynomial,
381 isl_obj_union_pw_qpolynomial,
382 (isc_bin_op_fn) &isl_union_pw_qpolynomial_mul },
383 { '*', isl_obj_union_pw_qpolynomial, isl_obj_union_set,
384 isl_obj_union_pw_qpolynomial,
385 (isc_bin_op_fn) &isl_union_pw_qpolynomial_intersect_domain },
386 { '*', isl_obj_union_pw_qpolynomial_fold, isl_obj_union_set,
387 isl_obj_union_pw_qpolynomial_fold,
388 (isc_bin_op_fn) &isl_union_pw_qpolynomial_fold_intersect_domain },
389 { '@', isl_obj_union_pw_qpolynomial, isl_obj_union_set,
390 isl_obj_union_pw_qpolynomial,
391 (isc_bin_op_fn) &isl_union_pw_qpolynomial_at },
392 { '@', isl_obj_union_pw_qpolynomial_fold, isl_obj_union_set,
393 isl_obj_union_pw_qpolynomial,
394 (isc_bin_op_fn) &isl_union_pw_qpolynomial_fold_at },
395 { '%', isl_obj_union_set, isl_obj_union_set,
396 isl_obj_union_set,
397 (isc_bin_op_fn) &isl_union_set_gist },
398 { '%', isl_obj_union_map, isl_obj_union_map,
399 isl_obj_union_map,
400 (isc_bin_op_fn) &isl_union_map_gist },
401 { '%', isl_obj_union_pw_qpolynomial, isl_obj_union_set,
402 isl_obj_union_pw_qpolynomial,
403 (isc_bin_op_fn) &isl_union_pw_qpolynomial_gist },
404 { '%', isl_obj_union_pw_qpolynomial_fold, isl_obj_union_set,
405 isl_obj_union_pw_qpolynomial_fold,
406 (isc_bin_op_fn) &isl_union_pw_qpolynomial_fold_gist },
407 { '+', isl_obj_str, isl_obj_str, isl_obj_str,
408 (isc_bin_op_fn) &isl_str_concat },
411 struct isc_named_bin_op named_bin_ops[] = {
412 { "cross", { -1, isl_obj_union_set, isl_obj_union_set,
413 isl_obj_union_set,
414 (isc_bin_op_fn) &isl_union_set_product } },
415 { "cross", { -1, isl_obj_union_map, isl_obj_union_map,
416 isl_obj_union_map,
417 (isc_bin_op_fn) &isl_union_map_product } },
418 NULL
421 __isl_give isl_set *union_set_sample(__isl_take isl_union_set *uset)
423 return isl_set_from_basic_set(isl_union_set_sample(uset));
426 __isl_give isl_map *union_map_sample(__isl_take isl_union_map *umap)
428 return isl_map_from_basic_map(isl_union_map_sample(umap));
431 static __isl_give struct isl_list *union_pw_qpolynomial_upper_bound(
432 __isl_take isl_union_pw_qpolynomial *upwqp)
434 isl_ctx *ctx;
435 struct isl_list *list;
436 int tight;
438 ctx = isl_union_pw_qpolynomial_get_ctx(upwqp);
439 list = isl_list_alloc(ctx, 2);
440 if (!list)
441 goto error2;
443 list->obj[0].type = isl_obj_union_pw_qpolynomial_fold;
444 list->obj[0].v = isl_union_pw_qpolynomial_bound(upwqp,
445 isl_fold_max, &tight);
446 list->obj[1].type = isl_obj_bool;
447 list->obj[1].v = tight ? &isl_bool_true : &isl_bool_false;
448 if (tight < 0 || !list->obj[0].v)
449 goto error;
451 return list;
452 error2:
453 isl_union_pw_qpolynomial_free(upwqp);
454 error:
455 isl_list_free(list);
456 return NULL;
459 #ifdef HAVE_CLOOG
460 void *map_codegen(void *arg)
462 isl_dim *dim;
463 isl_union_map *umap = (isl_union_map *)arg;
464 isl_ctx *ctx = isl_union_map_get_ctx(umap);
465 CloogState *state;
466 CloogOptions *options;
467 CloogDomain *context;
468 CloogUnionDomain *ud;
469 CloogInput *input;
470 struct clast_stmt *stmt;
472 state = cloog_isl_state_malloc(ctx);
473 options = cloog_options_malloc(state);
474 options->language = LANGUAGE_C;
475 options->strides = 1;
477 ud = cloog_union_domain_from_isl_union_map(isl_union_map_copy(umap));
479 dim = isl_union_map_get_dim(umap);
480 context = cloog_domain_from_isl_set(isl_set_universe(dim));
482 input = cloog_input_alloc(context, ud);
484 stmt = cloog_clast_create_from_input(input, options);
485 clast_pprint(stdout, stmt, 0, options);
486 cloog_clast_free(stmt);
488 error:
489 cloog_options_free(options);
490 cloog_state_free(state);
491 isl_union_map_free(umap);
492 return NULL;
495 void *set_codegen(void *arg)
497 isl_dim *dim;
498 isl_union_set *uset = (isl_union_set *)arg;
499 isl_ctx *ctx = isl_union_set_get_ctx(uset);
500 CloogState *state;
501 CloogOptions *options;
502 CloogDomain *context;
503 CloogUnionDomain *ud;
504 CloogInput *input;
505 struct clast_stmt *stmt;
507 state = cloog_isl_state_malloc(ctx);
508 options = cloog_options_malloc(state);
509 options->language = LANGUAGE_C;
510 options->strides = 1;
512 ud = cloog_union_domain_from_isl_union_set(isl_union_set_copy(uset));
514 dim = isl_union_set_get_dim(uset);
515 context = cloog_domain_from_isl_set(isl_set_universe(dim));
517 input = cloog_input_alloc(context, ud);
519 stmt = cloog_clast_create_from_input(input, options);
520 clast_pprint(stdout, stmt, 0, options);
521 cloog_clast_free(stmt);
523 error:
524 cloog_options_free(options);
525 cloog_state_free(state);
526 isl_union_set_free(uset);
527 return NULL;
529 #endif
531 typedef void *(*isc_un_op_fn)(void *arg);
532 struct isc_un_op {
533 enum isl_token_type op;
534 isl_obj_type arg;
535 isl_obj_type res;
536 isc_un_op_fn fn;
538 struct isc_named_un_op {
539 char *name;
540 struct isc_un_op op;
542 struct isc_named_un_op named_un_ops[] = {
543 {"aff", { -1, isl_obj_union_map, isl_obj_union_map,
544 (isc_un_op_fn) &isl_union_map_affine_hull } },
545 {"aff", { -1, isl_obj_union_set, isl_obj_union_set,
546 (isc_un_op_fn) &isl_union_set_affine_hull } },
547 {"card", { -1, isl_obj_union_set,
548 isl_obj_union_pw_qpolynomial,
549 (isc_un_op_fn) &isl_union_set_card } },
550 {"card", { -1, isl_obj_union_map,
551 isl_obj_union_pw_qpolynomial,
552 (isc_un_op_fn) &isl_union_map_card } },
553 {"coalesce", { -1, isl_obj_union_set, isl_obj_union_set,
554 (isc_un_op_fn) &isl_union_set_coalesce } },
555 {"coalesce", { -1, isl_obj_union_map, isl_obj_union_map,
556 (isc_un_op_fn) &isl_union_map_coalesce } },
557 {"coalesce", { -1, isl_obj_union_pw_qpolynomial,
558 isl_obj_union_pw_qpolynomial,
559 (isc_un_op_fn) &isl_union_pw_qpolynomial_coalesce } },
560 {"coalesce", { -1, isl_obj_union_pw_qpolynomial_fold,
561 isl_obj_union_pw_qpolynomial_fold,
562 (isc_un_op_fn) &isl_union_pw_qpolynomial_fold_coalesce } },
563 #ifdef HAVE_CLOOG
564 {"codegen", { -1, isl_obj_union_set, isl_obj_none,
565 &set_codegen } },
566 {"codegen", { -1, isl_obj_union_map, isl_obj_none,
567 &map_codegen } },
568 #endif
569 {"deltas", { -1, isl_obj_union_map, isl_obj_union_set,
570 (isc_un_op_fn) &isl_union_map_deltas } },
571 {"dom", { -1, isl_obj_union_map, isl_obj_union_set,
572 (isc_un_op_fn) &isl_union_map_domain } },
573 {"dom", { -1, isl_obj_union_pw_qpolynomial, isl_obj_union_set,
574 (isc_un_op_fn) &isl_union_pw_qpolynomial_domain } },
575 {"dom", { -1, isl_obj_union_pw_qpolynomial_fold,
576 isl_obj_union_set,
577 (isc_un_op_fn) &isl_union_pw_qpolynomial_fold_domain } },
578 {"ran", { -1, isl_obj_union_map, isl_obj_union_set,
579 (isc_un_op_fn) &isl_union_map_range } },
580 {"lexmin", { -1, isl_obj_union_map, isl_obj_union_map,
581 (isc_un_op_fn) &isl_union_map_lexmin } },
582 {"lexmax", { -1, isl_obj_union_map, isl_obj_union_map,
583 (isc_un_op_fn) &isl_union_map_lexmax } },
584 {"lexmin", { -1, isl_obj_union_set, isl_obj_union_set,
585 (isc_un_op_fn) &isl_union_set_lexmin } },
586 {"lexmax", { -1, isl_obj_union_set, isl_obj_union_set,
587 (isc_un_op_fn) &isl_union_set_lexmax } },
588 {"sample", { -1, isl_obj_union_set, isl_obj_set,
589 (isc_un_op_fn) &union_set_sample } },
590 {"sample", { -1, isl_obj_union_map, isl_obj_map,
591 (isc_un_op_fn) &union_map_sample } },
592 {"sum", { -1, isl_obj_union_pw_qpolynomial,
593 isl_obj_union_pw_qpolynomial,
594 (isc_un_op_fn) &isl_union_pw_qpolynomial_sum } },
595 {"ub", { -1, isl_obj_union_pw_qpolynomial, isl_obj_list,
596 (isc_un_op_fn) &union_pw_qpolynomial_upper_bound } },
597 {"unwrap", { -1, isl_obj_union_set, isl_obj_union_map,
598 (isc_un_op_fn) &isl_union_set_unwrap } },
599 {"wrap", { -1, isl_obj_union_map, isl_obj_union_set,
600 (isc_un_op_fn) &isl_union_map_wrap } },
601 NULL
604 struct isl_named_obj {
605 char *name;
606 struct isl_obj obj;
609 static void free_obj(struct isl_obj obj)
611 obj.type->free(obj.v);
614 static int same_name(const void *entry, const void *val)
616 const struct isl_named_obj *named = (const struct isl_named_obj *)entry;
618 return !strcmp(named->name, val);
621 static int do_assign(struct isl_ctx *ctx, struct isl_hash_table *table,
622 char *name, struct isl_obj obj)
624 struct isl_hash_table_entry *entry;
625 uint32_t name_hash;
626 struct isl_named_obj *named;
628 name_hash = isl_hash_string(isl_hash_init(), name);
629 entry = isl_hash_table_find(ctx, table, name_hash, same_name, name, 1);
630 if (!entry)
631 goto error;
632 if (entry->data) {
633 named = entry->data;
634 free_obj(named->obj);
635 free(name);
636 } else {
637 named = isl_alloc_type(ctx, struct isl_named_obj);
638 if (!named)
639 goto error;
640 named->name = name;
641 entry->data = named;
643 named->obj = obj;
645 return 0;
646 error:
647 free_obj(obj);
648 free(name);
649 return -1;
652 static struct isl_obj stored_obj(struct isl_ctx *ctx,
653 struct isl_hash_table *table, char *name)
655 struct isl_obj obj = { isl_obj_none, NULL };
656 struct isl_hash_table_entry *entry;
657 uint32_t name_hash;
659 name_hash = isl_hash_string(isl_hash_init(), name);
660 entry = isl_hash_table_find(ctx, table, name_hash, same_name, name, 0);
661 if (entry) {
662 struct isl_named_obj *named;
663 named = entry->data;
664 obj = named->obj;
665 } else
666 fprintf(stderr, "unknown identifier '%s'\n", name);
668 free(name);
669 obj.v = obj.type->copy(obj.v);
670 return obj;
673 static int is_subtype(struct isl_obj obj, isl_obj_type super)
675 if (obj.type == super)
676 return 1;
677 if (obj.type == isl_obj_map && super == isl_obj_union_map)
678 return 1;
679 if (obj.type == isl_obj_set && super == isl_obj_union_set)
680 return 1;
681 if (obj.type == isl_obj_pw_qpolynomial &&
682 super == isl_obj_union_pw_qpolynomial)
683 return 1;
684 if (obj.type == isl_obj_pw_qpolynomial_fold &&
685 super == isl_obj_union_pw_qpolynomial_fold)
686 return 1;
687 if (obj.type == isl_obj_union_set && isl_union_set_is_empty(obj.v))
688 return 1;
689 if (obj.type == isl_obj_list) {
690 struct isl_list *list = obj.v;
691 if (list->n == 2 && list->obj[1].type == isl_obj_bool)
692 return is_subtype(list->obj[0], super);
694 if (super == isl_obj_str)
695 return 1;
696 return 0;
699 static struct isl_obj obj_at(struct isl_obj obj, int i)
701 struct isl_list *list = obj.v;
703 obj = list->obj[i];
704 obj.v = obj.type->copy(obj.v);
706 isl_list_free(list);
708 return obj;
711 static struct isl_obj convert(isl_ctx *ctx, struct isl_obj obj,
712 isl_obj_type type)
714 if (obj.type == type)
715 return obj;
716 if (obj.type == isl_obj_map && type == isl_obj_union_map) {
717 obj.type = isl_obj_union_map;
718 obj.v = isl_union_map_from_map(obj.v);
719 return obj;
721 if (obj.type == isl_obj_set && type == isl_obj_union_set) {
722 obj.type = isl_obj_union_set;
723 obj.v = isl_union_set_from_set(obj.v);
724 return obj;
726 if (obj.type == isl_obj_pw_qpolynomial &&
727 type == isl_obj_union_pw_qpolynomial) {
728 obj.type = isl_obj_union_pw_qpolynomial;
729 obj.v = isl_union_pw_qpolynomial_from_pw_qpolynomial(obj.v);
730 return obj;
732 if (obj.type == isl_obj_pw_qpolynomial_fold &&
733 type == isl_obj_union_pw_qpolynomial_fold) {
734 obj.type = isl_obj_union_pw_qpolynomial_fold;
735 obj.v = isl_union_pw_qpolynomial_fold_from_pw_qpolynomial_fold(obj.v);
736 return obj;
738 if (obj.type == isl_obj_union_set && isl_union_set_is_empty(obj.v)) {
739 if (type == isl_obj_union_map) {
740 obj.type = isl_obj_union_map;
741 return obj;
743 if (type == isl_obj_union_pw_qpolynomial) {
744 isl_dim *dim = isl_union_set_get_dim(obj.v);
745 isl_union_set_free(obj.v);
746 obj.v = isl_union_pw_qpolynomial_zero(dim);
747 obj.type = isl_obj_union_pw_qpolynomial;
748 return obj;
750 if (type == isl_obj_union_pw_qpolynomial_fold) {
751 isl_dim *dim = isl_union_set_get_dim(obj.v);
752 isl_union_set_free(obj.v);
753 obj.v = isl_union_pw_qpolynomial_fold_zero(dim,
754 isl_fold_list);
755 obj.type = isl_obj_union_pw_qpolynomial_fold;
756 return obj;
759 if (obj.type == isl_obj_list) {
760 struct isl_list *list = obj.v;
761 if (list->n == 2 && list->obj[1].type == isl_obj_bool)
762 return convert(ctx, obj_at(obj, 0), type);
764 if (type == isl_obj_str) {
765 isl_str *str;
766 isl_printer *p;
767 char *s;
769 p = isl_printer_to_str(ctx);
770 if (!p)
771 goto error;
772 p = obj.type->print(p, obj.v);
773 s = isl_printer_get_str(p);
774 isl_printer_free(p);
776 str = isl_str_alloc(ctx);
777 if (!str) {
778 free(s);
779 goto error;
781 str->s = s;
782 free_obj(obj);
783 obj.v = str;
784 obj.type = isl_obj_str;
785 return obj;
788 error:
789 free_obj(obj);
790 obj.type = isl_obj_none;
791 obj.v = NULL;
792 return obj;
795 static struct isc_bin_op *read_bin_op_if_available(struct isl_stream *s,
796 struct isl_obj lhs)
798 int i;
799 struct isl_token *tok;
801 tok = isl_stream_next_token(s);
802 if (!tok)
803 return NULL;
805 for (i = 0; ; ++i) {
806 if (!bin_ops[i].op)
807 break;
808 if (bin_ops[i].op != tok->type)
809 continue;
810 if (!is_subtype(lhs, bin_ops[i].lhs))
811 continue;
813 isl_token_free(tok);
814 return &bin_ops[i];
817 for (i = 0; ; ++i) {
818 if (!named_bin_ops[i].name)
819 break;
820 if (named_bin_ops[i].op.op != tok->type)
821 continue;
822 if (!is_subtype(lhs, named_bin_ops[i].op.lhs))
823 continue;
825 isl_token_free(tok);
826 return &named_bin_ops[i].op;
829 isl_stream_push_token(s, tok);
831 return NULL;
834 static struct isc_un_op *read_prefix_un_op_if_available(struct isl_stream *s)
836 int i;
837 struct isl_token *tok;
839 tok = isl_stream_next_token(s);
840 if (!tok)
841 return NULL;
843 for (i = 0; ; ++i) {
844 if (!named_un_ops[i].name)
845 break;
846 if (named_un_ops[i].op.op != tok->type)
847 continue;
849 isl_token_free(tok);
850 return &named_un_ops[i].op;
853 isl_stream_push_token(s, tok);
855 return NULL;
858 static struct isc_un_op *find_matching_un_op(struct isc_un_op *like,
859 struct isl_obj arg)
861 int i;
863 for (i = 0; ; ++i) {
864 if (!named_un_ops[i].name)
865 break;
866 if (named_un_ops[i].op.op != like->op)
867 continue;
868 if (!is_subtype(arg, named_un_ops[i].op.arg))
869 continue;
871 return &named_un_ops[i].op;
874 return NULL;
877 static int is_assign(struct isl_stream *s)
879 struct isl_token *tok;
880 struct isl_token *tok2;
881 int assign;
883 tok = isl_stream_next_token(s);
884 if (!tok)
885 return 0;
886 if (tok->type != ISL_TOKEN_IDENT) {
887 isl_stream_push_token(s, tok);
888 return 0;
891 tok2 = isl_stream_next_token(s);
892 if (!tok2) {
893 isl_stream_push_token(s, tok);
894 return 0;
896 assign = tok2->type == ISL_TOKEN_DEF;
897 isl_stream_push_token(s, tok2);
898 isl_stream_push_token(s, tok);
900 return assign;
903 static struct isl_obj read_obj(struct isl_stream *s,
904 struct isl_hash_table *table);
905 static struct isl_obj read_expr(struct isl_stream *s,
906 struct isl_hash_table *table);
908 static struct isl_obj read_un_op_expr(struct isl_stream *s,
909 struct isl_hash_table *table, struct isc_un_op *op)
911 struct isl_obj obj = { isl_obj_none, NULL };
913 obj = read_obj(s, table);
914 if (!obj.v)
915 goto error;
917 op = find_matching_un_op(op, obj);
919 isl_assert(s->ctx, op, goto error);
920 obj = convert(s->ctx, obj, op->arg);
921 obj.v = op->fn(obj.v);
922 obj.type = op->res;
924 return obj;
925 error:
926 free_obj(obj);
927 obj.type = isl_obj_none;
928 obj.v = NULL;
929 return obj;
932 static struct isl_obj transitive_closure(struct isl_ctx *ctx, struct isl_obj obj)
934 struct isl_list *list;
935 int exact;
937 if (obj.type != isl_obj_union_map)
938 obj = convert(ctx, obj, isl_obj_union_map);
939 isl_assert(ctx, obj.type == isl_obj_union_map, goto error);
940 list = isl_list_alloc(ctx, 2);
941 if (!list)
942 goto error;
944 list->obj[0].type = isl_obj_union_map;
945 list->obj[0].v = isl_union_map_transitive_closure(obj.v, &exact);
946 list->obj[1].type = isl_obj_bool;
947 list->obj[1].v = exact ? &isl_bool_true : &isl_bool_false;
948 obj.v = list;
949 obj.type = isl_obj_list;
950 if (exact < 0 || !list->obj[0].v)
951 goto error;
953 return obj;
954 error:
955 free_obj(obj);
956 obj.type = isl_obj_none;
957 obj.v = NULL;
958 return obj;
961 static struct isl_obj obj_at_index(struct isl_stream *s, struct isl_obj obj)
963 struct isl_list *list = obj.v;
964 struct isl_token *tok;
965 int i;
967 tok = isl_stream_next_token(s);
968 if (!tok || tok->type != ISL_TOKEN_VALUE) {
969 isl_stream_error(s, tok, "expecting index");
970 if (tok)
971 isl_stream_push_token(s, tok);
972 goto error;
974 i = isl_int_get_si(tok->u.v);
975 isl_token_free(tok);
976 isl_assert(s->ctx, i < list->n, goto error);
977 if (isl_stream_eat(s, ']'))
978 goto error;
980 return obj_at(obj, i);
981 error:
982 free_obj(obj);
983 obj.type = isl_obj_none;
984 obj.v = NULL;
985 return obj;
988 static struct isl_obj apply(struct isl_stream *s, __isl_take isl_union_map *umap,
989 struct isl_hash_table *table)
991 struct isl_obj obj;
993 obj = read_expr(s, table);
994 isl_assert(s->ctx, is_subtype(obj, isl_obj_union_set) ||
995 is_subtype(obj, isl_obj_union_map), goto error);
997 if (obj.type == isl_obj_list) {
998 struct isl_list *list = obj.v;
999 if (list->n == 2 && list->obj[1].type == isl_obj_bool)
1000 obj = obj_at(obj, 0);
1002 if (obj.type == isl_obj_set)
1003 obj = convert(s->ctx, obj, isl_obj_union_set);
1004 else if (obj.type == isl_obj_map)
1005 obj = convert(s->ctx, obj, isl_obj_union_map);
1006 if (obj.type == isl_obj_union_set) {
1007 obj.v = isl_union_set_apply(obj.v, umap);
1008 } else
1009 obj.v = isl_union_map_apply_range(obj.v, umap);
1010 if (!obj.v)
1011 goto error2;
1013 if (isl_stream_eat(s, ')'))
1014 goto error2;
1016 return obj;
1017 error:
1018 isl_union_map_free(umap);
1019 error2:
1020 free_obj(obj);
1021 obj.type = isl_obj_none;
1022 obj.v = NULL;
1023 return obj;
1026 struct add_vertex_data {
1027 struct isl_list *list;
1028 int i;
1031 static int add_vertex(__isl_take isl_vertex *vertex, void *user)
1033 struct add_vertex_data *data = (struct add_vertex_data *)user;
1034 isl_basic_set *expr;
1036 expr = isl_vertex_get_expr(vertex);
1038 data->list->obj[data->i].type = isl_obj_set;
1039 data->list->obj[data->i].v = isl_set_from_basic_set(expr);
1040 data->i++;
1042 isl_vertex_free(vertex);
1044 return 0;
1047 static int set_vertices(__isl_take isl_set *set, void *user)
1049 isl_ctx *ctx;
1050 isl_basic_set *hull;
1051 isl_vertices *vertices = NULL;
1052 struct isl_list *list = NULL;
1053 int r;
1054 struct add_vertex_data *data = (struct add_vertex_data *)user;
1056 set = isl_set_remove_divs(set);
1057 hull = isl_set_convex_hull(set);
1058 vertices = isl_basic_set_compute_vertices(hull);
1059 isl_basic_set_free(hull);
1061 list = data->list;
1063 ctx = isl_vertices_get_ctx(vertices);
1064 data->list = isl_list_alloc(ctx, isl_vertices_get_n_vertices(vertices));
1065 if (!data->list)
1066 goto error;
1068 data->i = 0;
1069 r = isl_vertices_foreach_vertex(vertices, &add_vertex, user);
1071 data->list = isl_list_concat(list, data->list);
1073 isl_vertices_free(vertices);
1075 return r;
1076 error:
1077 data->list = list;
1078 isl_vertices_free(vertices);
1079 return -1;
1082 static struct isl_obj vertices(struct isl_stream *s,
1083 struct isl_hash_table *table)
1085 isl_ctx *ctx;
1086 struct isl_obj obj;
1087 struct isl_list *list = NULL;
1088 isl_union_set *uset;
1089 struct add_vertex_data data = { NULL };
1091 obj = read_expr(s, table);
1092 obj = convert(s->ctx, obj, isl_obj_union_set);
1093 isl_assert(s->ctx, obj.type == isl_obj_union_set, goto error);
1094 uset = obj.v;
1095 obj.v = NULL;
1097 ctx = isl_union_set_get_ctx(uset);
1098 list = isl_list_alloc(ctx, 0);
1099 if (!list)
1100 goto error;
1102 data.list = list;
1104 if (isl_union_set_foreach_set(uset, &set_vertices, &data) < 0)
1105 goto error;
1107 isl_union_set_free(uset);
1109 obj.type = isl_obj_list;
1110 obj.v = data.list;
1112 return obj;
1113 error:
1114 isl_union_set_free(uset);
1115 isl_list_free(data.list);
1116 free_obj(obj);
1117 obj.type = isl_obj_none;
1118 obj.v = NULL;
1119 return obj;
1122 static struct isl_obj power(struct isl_stream *s, struct isl_obj obj)
1124 struct isl_token *tok;
1126 if (isl_stream_eat_if_available(s, '+'))
1127 return transitive_closure(s->ctx, obj);
1129 tok = isl_stream_next_token(s);
1130 if (!tok || tok->type != ISL_TOKEN_VALUE || isl_int_cmp_si(tok->u.v, -1)) {
1131 isl_stream_error(s, tok, "expecting -1");
1132 if (tok)
1133 isl_stream_push_token(s, tok);
1134 goto error;
1136 isl_token_free(tok);
1137 isl_assert(s->ctx, is_subtype(obj, isl_obj_union_map), goto error);
1138 if (obj.type != isl_obj_union_map)
1139 obj = convert(s->ctx, obj, isl_obj_union_map);
1141 obj.v = isl_union_map_reverse(obj.v);
1142 if (!obj.v)
1143 goto error;
1145 return obj;
1146 error:
1147 free_obj(obj);
1148 obj.type = isl_obj_none;
1149 obj.v = NULL;
1150 return obj;
1153 static struct isl_obj read_from_file(struct isl_stream *s)
1155 struct isl_obj obj;
1156 struct isl_token *tok;
1157 struct isl_stream *s_file;
1158 FILE *file;
1160 tok = isl_stream_next_token(s);
1161 if (!tok || tok->type != ISL_TOKEN_STRING) {
1162 isl_stream_error(s, tok, "expecting filename");
1163 isl_token_free(tok);
1164 goto error;
1167 file = fopen(tok->u.s, "r");
1168 isl_token_free(tok);
1169 isl_assert(s->ctx, file, goto error);
1171 s_file = isl_stream_new_file(s->ctx, file);
1172 if (!s_file) {
1173 fclose(file);
1174 goto error;
1177 obj = isl_stream_read_obj(s_file);
1179 isl_stream_free(s_file);
1180 fclose(file);
1182 return obj;
1183 error:
1184 obj.type = isl_obj_none;
1185 obj.v = NULL;
1186 return obj;
1189 static struct isl_obj read_string_if_available(struct isl_stream *s)
1191 struct isl_token *tok;
1192 struct isl_obj obj = { isl_obj_none, NULL };
1194 tok = isl_stream_next_token(s);
1195 if (!tok)
1196 return obj;
1197 if (tok->type == ISL_TOKEN_STRING) {
1198 isl_str *str;
1199 str = isl_str_alloc(s->ctx);
1200 if (!str)
1201 goto error;
1202 str->s = strdup(tok->u.s);
1203 isl_token_free(tok);
1204 obj.v = str;
1205 obj.type = isl_obj_str;
1206 } else
1207 isl_stream_push_token(s, tok);
1208 return obj;
1209 error:
1210 isl_token_free(tok);
1211 return obj;
1214 static struct isl_obj read_obj(struct isl_stream *s,
1215 struct isl_hash_table *table)
1217 struct isl_obj obj = { isl_obj_none, NULL };
1218 char *name = NULL;
1219 struct isc_un_op *op = NULL;
1221 obj = read_string_if_available(s);
1222 if (obj.v)
1223 return obj;
1224 if (isl_stream_eat_if_available(s, '(')) {
1225 obj = read_expr(s, table);
1226 if (!obj.v || isl_stream_eat(s, ')'))
1227 goto error;
1228 } else {
1229 op = read_prefix_un_op_if_available(s);
1230 if (op)
1231 return read_un_op_expr(s, table, op);
1233 if (isl_stream_eat_if_available(s, read_op))
1234 return read_from_file(s);
1235 if (isl_stream_eat_if_available(s, vertices_op))
1236 return vertices(s, table);
1238 name = isl_stream_read_ident_if_available(s);
1239 if (name)
1240 obj = stored_obj(s->ctx, table, name);
1241 else
1242 obj = isl_stream_read_obj(s);
1243 if (!obj.v)
1244 goto error;
1247 if (isl_stream_eat_if_available(s, '^'))
1248 obj = power(s, obj);
1249 else if (obj.type == isl_obj_list && isl_stream_eat_if_available(s, '['))
1250 obj = obj_at_index(s, obj);
1251 else if (is_subtype(obj, isl_obj_union_map) &&
1252 isl_stream_eat_if_available(s, '(')) {
1253 obj = convert(s->ctx, obj, isl_obj_union_map);
1254 obj = apply(s, obj.v, table);
1257 return obj;
1258 error:
1259 free_obj(obj);
1260 obj.type = isl_obj_none;
1261 obj.v = NULL;
1262 return obj;
1265 static struct isc_bin_op *find_matching_bin_op(struct isc_bin_op *like,
1266 struct isl_obj lhs, struct isl_obj rhs)
1268 int i;
1270 for (i = 0; ; ++i) {
1271 if (!bin_ops[i].op)
1272 break;
1273 if (bin_ops[i].op != like->op)
1274 continue;
1275 if (!is_subtype(lhs, bin_ops[i].lhs))
1276 continue;
1277 if (!is_subtype(rhs, bin_ops[i].rhs))
1278 continue;
1280 return &bin_ops[i];
1283 for (i = 0; ; ++i) {
1284 if (!named_bin_ops[i].name)
1285 break;
1286 if (named_bin_ops[i].op.op != like->op)
1287 continue;
1288 if (!is_subtype(lhs, named_bin_ops[i].op.lhs))
1289 continue;
1290 if (!is_subtype(rhs, named_bin_ops[i].op.rhs))
1291 continue;
1293 return &named_bin_ops[i].op;
1296 return NULL;
1299 static struct isl_obj read_expr(struct isl_stream *s,
1300 struct isl_hash_table *table)
1302 struct isl_obj obj = { isl_obj_none, NULL };
1303 struct isl_obj right_obj = { isl_obj_none, NULL };
1305 obj = read_obj(s, table);
1306 for (; obj.v;) {
1307 struct isc_bin_op *op = NULL;
1309 op = read_bin_op_if_available(s, obj);
1310 if (!op)
1311 break;
1313 right_obj = read_obj(s, table);
1315 op = find_matching_bin_op(op, obj, right_obj);
1317 isl_assert(s->ctx, op, goto error);
1318 obj = convert(s->ctx, obj, op->lhs);
1319 right_obj = convert(s->ctx, right_obj, op->rhs);
1320 obj.v = op->fn(obj.v, right_obj.v);
1321 obj.type = op->res;
1324 return obj;
1325 error:
1326 free_obj(right_obj);
1327 free_obj(obj);
1328 obj.type = isl_obj_none;
1329 obj.v = NULL;
1330 return obj;
1333 static __isl_give isl_printer *source_file(struct isl_stream *s,
1334 struct isl_hash_table *table, __isl_take isl_printer *p);
1336 static __isl_give isl_printer *read_line(struct isl_stream *s,
1337 struct isl_hash_table *table, __isl_take isl_printer *p)
1339 struct isl_obj obj = { isl_obj_none, NULL };
1340 char *lhs = NULL;
1341 int assign = 0;
1342 struct isc_bin_op *op = NULL;
1344 if (!p)
1345 return NULL;
1346 if (isl_stream_is_empty(s))
1347 return p;
1349 if (isl_stream_eat_if_available(s, source_op))
1350 return source_file(s, table, p);
1352 assign = is_assign(s);
1353 if (assign) {
1354 lhs = isl_stream_read_ident_if_available(s);
1355 if (isl_stream_eat(s, ISL_TOKEN_DEF))
1356 goto error;
1359 obj = read_expr(s, table);
1360 if (obj.type == isl_obj_none || obj.v == NULL)
1361 goto error;
1362 if (isl_stream_eat(s, ';'))
1363 goto error;
1365 if (assign) {
1366 if (do_assign(s->ctx, table, lhs, obj))
1367 return;
1368 } else {
1369 p = obj.type->print(p, obj.v);
1370 p = isl_printer_end_line(p);
1371 free_obj(obj);
1374 return p;
1375 error:
1376 isl_stream_flush_tokens(s);
1377 isl_stream_skip_line(s);
1378 free(lhs);
1379 free_obj(obj);
1380 return p;
1383 int free_cb(void **entry, void *user)
1385 struct isl_named_obj *named = *entry;
1387 free_obj(named->obj);
1388 free(named->name);
1389 free(named);
1391 return 0;
1394 static void register_named_ops(struct isl_stream *s)
1396 int i;
1398 read_op = isl_stream_register_keyword(s, "read");
1399 assert(read_op != ISL_TOKEN_ERROR);
1400 source_op = isl_stream_register_keyword(s, "source");
1401 assert(source_op != ISL_TOKEN_ERROR);
1402 vertices_op = isl_stream_register_keyword(s, "vertices");
1403 assert(vertices_op != ISL_TOKEN_ERROR);
1405 for (i = 0; ; ++i) {
1406 if (!named_un_ops[i].name)
1407 break;
1408 named_un_ops[i].op.op = isl_stream_register_keyword(s,
1409 named_un_ops[i].name);
1410 assert(named_un_ops[i].op.op != ISL_TOKEN_ERROR);
1413 for (i = 0; ; ++i) {
1414 if (!named_bin_ops[i].name)
1415 break;
1416 named_bin_ops[i].op.op = isl_stream_register_keyword(s,
1417 named_bin_ops[i].name);
1418 assert(named_bin_ops[i].op.op != ISL_TOKEN_ERROR);
1422 static __isl_give isl_printer *source_file(struct isl_stream *s,
1423 struct isl_hash_table *table, __isl_take isl_printer *p)
1425 struct isl_token *tok;
1426 struct isl_stream *s_file;
1427 FILE *file;
1429 tok = isl_stream_next_token(s);
1430 if (!tok || tok->type != ISL_TOKEN_STRING) {
1431 isl_stream_error(s, tok, "expecting filename");
1432 isl_token_free(tok);
1433 return p;
1436 file = fopen(tok->u.s, "r");
1437 isl_token_free(tok);
1438 isl_assert(s->ctx, file, return p);
1440 s_file = isl_stream_new_file(s->ctx, file);
1441 if (!s_file) {
1442 fclose(file);
1443 return p;
1446 register_named_ops(s_file);
1448 while (!s_file->eof)
1449 p = read_line(s_file, table, p);
1451 isl_stream_free(s_file);
1452 fclose(file);
1454 isl_stream_eat(s, ';');
1456 return p;
1459 int main(int argc, char **argv)
1461 struct isl_ctx *ctx;
1462 struct isl_stream *s;
1463 struct isl_hash_table *table;
1464 struct iscc_options *options;
1465 isl_printer *p;
1467 options = iscc_options_new_with_defaults();
1468 assert(options);
1469 argc = iscc_options_parse(options, argc, argv, ISL_ARG_ALL);
1471 ctx = isl_ctx_alloc_with_options(iscc_options_arg, options);
1472 s = isl_stream_new_file(ctx, stdin);
1473 assert(s);
1474 table = isl_hash_table_alloc(ctx, 10);
1475 assert(table);
1476 p = isl_printer_to_file(ctx, stdout);
1477 p = isl_printer_set_output_format(p, options->format);
1478 assert(p);
1480 register_named_ops(s);
1482 while (!s->eof) {
1483 p = read_line(s, table, p);
1486 isl_printer_free(p);
1487 isl_hash_table_foreach(ctx, table, free_cb, NULL);
1488 isl_hash_table_free(ctx, table);
1489 isl_stream_free(s);
1490 isl_ctx_free(ctx);
1492 return 0;