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>
14 #include <cloog/isl/cloog.h>
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
},
35 struct barvinok_options
*barvinok
;
39 struct isl_arg iscc_options_arg
[] = {
40 ISL_ARG_CHILD(struct iscc_options
, barvinok
, "barvinok", barvinok_options_arg
,
42 ISL_ARG_CHOICE(struct iscc_options
, format
, 0, "format", \
43 iscc_format
, ISL_FORMAT_ISL
, "output format")
47 ISL_ARG_DEF(iscc_options
, struct iscc_options
, iscc_options_arg
)
49 static void *isl_obj_bool_copy(void *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
,
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");
66 return isl_printer_print_str(p
, "Error");
69 static void *isl_obj_bool_add(void *v1
, void *v2
)
74 struct isl_obj_vtable isl_obj_bool_vtable
= {
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
);
157 enum isl_token_type op
;
163 struct isc_named_bin_op
{
165 struct isc_bin_op op
;
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
;
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
)));
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
)
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
);
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
;
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
)));
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
;
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
);
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
,
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
)
259 struct isl_list
*list
;
262 ctx
= isl_union_map_get_ctx(umap
);
263 list
= isl_list_alloc(ctx
, 2);
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
,
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
)
277 isl_union_map_free(umap
);
278 isl_union_pw_qpolynomial_fold_free(upwf
);
284 struct isc_bin_op bin_ops
[] = {
285 { '+', isl_obj_union_set
, isl_obj_union_set
,
287 (isc_bin_op_fn
) &isl_union_set_union
},
288 { '+', isl_obj_union_map
, isl_obj_union_map
,
290 (isc_bin_op_fn
) &isl_union_map_union
},
291 { '-', isl_obj_union_set
, isl_obj_union_set
,
293 (isc_bin_op_fn
) &isl_union_set_subtract
},
294 { '-', isl_obj_union_map
, isl_obj_union_map
,
296 (isc_bin_op_fn
) &isl_union_map_subtract
},
297 { '*', isl_obj_union_set
, isl_obj_union_set
,
299 (isc_bin_op_fn
) &isl_union_set_intersect
},
300 { '*', isl_obj_union_map
, isl_obj_union_map
,
302 (isc_bin_op_fn
) &isl_union_map_intersect
},
303 { '*', isl_obj_union_map
, isl_obj_union_set
,
305 (isc_bin_op_fn
) &isl_union_map_intersect_domain
},
306 { '.', isl_obj_union_map
, 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
,
314 (isc_bin_op_fn
) &union_map_apply_union_pw_qpolynomial_fold
},
315 { ISL_TOKEN_TO
, isl_obj_union_set
, isl_obj_union_set
,
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_obj_union_pw_qpolynomial_fold
,
339 isl_obj_union_pw_qpolynomial_fold
,
340 isl_obj_union_pw_qpolynomial_fold
,
341 (isc_bin_op_fn
) &isl_union_pw_qpolynomial_fold_fold
},
342 { '+', isl_obj_union_pw_qpolynomial
, isl_obj_union_pw_qpolynomial
,
343 isl_obj_union_pw_qpolynomial
,
344 (isc_bin_op_fn
) &isl_union_pw_qpolynomial_add
},
345 { '+', isl_obj_union_pw_qpolynomial
,
346 isl_obj_union_pw_qpolynomial_fold
,
347 isl_obj_union_pw_qpolynomial_fold
,
348 (isc_bin_op_fn
) &union_pw_qpolynomial_add_union_pw_qpolynomial_fold
},
349 { '+', isl_obj_union_pw_qpolynomial_fold
,
350 isl_obj_union_pw_qpolynomial
,
351 isl_obj_union_pw_qpolynomial_fold
,
352 (isc_bin_op_fn
) &isl_union_pw_qpolynomial_fold_add_union_pw_qpolynomial
},
353 { '-', isl_obj_union_pw_qpolynomial
, isl_obj_union_pw_qpolynomial
,
354 isl_obj_union_pw_qpolynomial
,
355 (isc_bin_op_fn
) &isl_union_pw_qpolynomial_sub
},
356 { '*', isl_obj_union_pw_qpolynomial
, isl_obj_union_pw_qpolynomial
,
357 isl_obj_union_pw_qpolynomial
,
358 (isc_bin_op_fn
) &isl_union_pw_qpolynomial_mul
},
359 { '*', isl_obj_union_pw_qpolynomial
, isl_obj_union_set
,
360 isl_obj_union_pw_qpolynomial
,
361 (isc_bin_op_fn
) &isl_union_pw_qpolynomial_intersect_domain
},
362 { '*', isl_obj_union_pw_qpolynomial_fold
, isl_obj_union_set
,
363 isl_obj_union_pw_qpolynomial_fold
,
364 (isc_bin_op_fn
) &isl_union_pw_qpolynomial_fold_intersect_domain
},
365 { '@', isl_obj_union_pw_qpolynomial
, isl_obj_union_set
,
366 isl_obj_union_pw_qpolynomial
,
367 (isc_bin_op_fn
) &isl_union_pw_qpolynomial_at
},
368 { '@', isl_obj_union_pw_qpolynomial_fold
, isl_obj_union_set
,
369 isl_obj_union_pw_qpolynomial
,
370 (isc_bin_op_fn
) &isl_union_pw_qpolynomial_fold_at
},
371 { '%', isl_obj_union_set
, isl_obj_union_set
,
373 (isc_bin_op_fn
) &isl_union_set_gist
},
374 { '%', isl_obj_union_map
, isl_obj_union_map
,
376 (isc_bin_op_fn
) &isl_union_map_gist
},
377 { '%', isl_obj_union_pw_qpolynomial
, isl_obj_union_set
,
378 isl_obj_union_pw_qpolynomial
,
379 (isc_bin_op_fn
) &isl_union_pw_qpolynomial_gist
},
380 { '%', isl_obj_union_pw_qpolynomial_fold
, isl_obj_union_set
,
381 isl_obj_union_pw_qpolynomial_fold
,
382 (isc_bin_op_fn
) &isl_union_pw_qpolynomial_fold_gist
},
383 { '+', isl_obj_str
, isl_obj_str
, isl_obj_str
,
384 (isc_bin_op_fn
) &isl_str_concat
},
387 struct isc_named_bin_op named_bin_ops
[] = {
388 { "cross", { -1, isl_obj_union_set
, isl_obj_union_set
,
390 (isc_bin_op_fn
) &isl_union_set_product
} },
391 { "cross", { -1, isl_obj_union_map
, isl_obj_union_map
,
393 (isc_bin_op_fn
) &isl_union_map_product
} },
397 __isl_give isl_set
*union_set_sample(__isl_take isl_union_set
*uset
)
399 return isl_set_from_basic_set(isl_union_set_sample(uset
));
402 __isl_give isl_map
*union_map_sample(__isl_take isl_union_map
*umap
)
404 return isl_map_from_basic_map(isl_union_map_sample(umap
));
407 static __isl_give
struct isl_list
*union_pw_qpolynomial_upper_bound(
408 __isl_take isl_union_pw_qpolynomial
*upwqp
)
411 struct isl_list
*list
;
414 ctx
= isl_union_pw_qpolynomial_get_ctx(upwqp
);
415 list
= isl_list_alloc(ctx
, 2);
419 list
->obj
[0].type
= isl_obj_union_pw_qpolynomial_fold
;
420 list
->obj
[0].v
= isl_union_pw_qpolynomial_bound(upwqp
,
421 isl_fold_max
, &tight
);
422 list
->obj
[1].type
= isl_obj_bool
;
423 list
->obj
[1].v
= tight
? &isl_bool_true
: &isl_bool_false
;
424 if (tight
< 0 || !list
->obj
[0].v
)
429 isl_union_pw_qpolynomial_free(upwqp
);
436 void *map_codegen(void *arg
)
439 isl_union_map
*umap
= (isl_union_map
*)arg
;
440 isl_ctx
*ctx
= isl_union_map_get_ctx(umap
);
442 CloogOptions
*options
;
443 CloogDomain
*context
;
444 CloogUnionDomain
*ud
;
446 struct clast_stmt
*stmt
;
448 state
= cloog_isl_state_malloc(ctx
);
449 options
= cloog_options_malloc(state
);
450 options
->language
= LANGUAGE_C
;
451 options
->strides
= 1;
453 ud
= cloog_union_domain_from_isl_union_map(isl_union_map_copy(umap
));
455 dim
= isl_union_map_get_dim(umap
);
456 context
= cloog_domain_from_isl_set(isl_set_universe(dim
));
458 input
= cloog_input_alloc(context
, ud
);
460 stmt
= cloog_clast_create_from_input(input
, options
);
461 clast_pprint(stdout
, stmt
, 0, options
);
462 cloog_clast_free(stmt
);
465 cloog_options_free(options
);
466 cloog_state_free(state
);
467 isl_union_map_free(umap
);
471 void *set_codegen(void *arg
)
474 isl_union_set
*uset
= (isl_union_set
*)arg
;
475 isl_ctx
*ctx
= isl_union_set_get_ctx(uset
);
477 CloogOptions
*options
;
478 CloogDomain
*context
;
479 CloogUnionDomain
*ud
;
481 struct clast_stmt
*stmt
;
483 state
= cloog_isl_state_malloc(ctx
);
484 options
= cloog_options_malloc(state
);
485 options
->language
= LANGUAGE_C
;
486 options
->strides
= 1;
488 ud
= cloog_union_domain_from_isl_union_set(isl_union_set_copy(uset
));
490 dim
= isl_union_set_get_dim(uset
);
491 context
= cloog_domain_from_isl_set(isl_set_universe(dim
));
493 input
= cloog_input_alloc(context
, ud
);
495 stmt
= cloog_clast_create_from_input(input
, options
);
496 clast_pprint(stdout
, stmt
, 0, options
);
497 cloog_clast_free(stmt
);
500 cloog_options_free(options
);
501 cloog_state_free(state
);
502 isl_union_set_free(uset
);
507 typedef void *(*isc_un_op_fn
)(void *arg
);
509 enum isl_token_type op
;
514 struct isc_named_un_op
{
518 struct isc_named_un_op named_un_ops
[] = {
519 {"aff", { -1, isl_obj_union_map
, isl_obj_union_map
,
520 (isc_un_op_fn
) &isl_union_map_affine_hull
} },
521 {"aff", { -1, isl_obj_union_set
, isl_obj_union_set
,
522 (isc_un_op_fn
) &isl_union_set_affine_hull
} },
523 {"card", { -1, isl_obj_union_set
,
524 isl_obj_union_pw_qpolynomial
,
525 (isc_un_op_fn
) &isl_union_set_card
} },
526 {"card", { -1, isl_obj_union_map
,
527 isl_obj_union_pw_qpolynomial
,
528 (isc_un_op_fn
) &isl_union_map_card
} },
529 {"coalesce", { -1, isl_obj_union_set
, isl_obj_union_set
,
530 (isc_un_op_fn
) &isl_union_set_coalesce
} },
531 {"coalesce", { -1, isl_obj_union_map
, isl_obj_union_map
,
532 (isc_un_op_fn
) &isl_union_map_coalesce
} },
533 {"coalesce", { -1, isl_obj_union_pw_qpolynomial
,
534 isl_obj_union_pw_qpolynomial
,
535 (isc_un_op_fn
) &isl_union_pw_qpolynomial_coalesce
} },
536 {"coalesce", { -1, isl_obj_union_pw_qpolynomial_fold
,
537 isl_obj_union_pw_qpolynomial_fold
,
538 (isc_un_op_fn
) &isl_union_pw_qpolynomial_fold_coalesce
} },
540 {"codegen", { -1, isl_obj_union_set
, isl_obj_none
,
542 {"codegen", { -1, isl_obj_union_map
, isl_obj_none
,
545 {"deltas", { -1, isl_obj_union_map
, isl_obj_union_set
,
546 (isc_un_op_fn
) &isl_union_map_deltas
} },
547 {"dom", { -1, isl_obj_union_map
, isl_obj_union_set
,
548 (isc_un_op_fn
) &isl_union_map_domain
} },
549 {"dom", { -1, isl_obj_union_pw_qpolynomial
, isl_obj_union_set
,
550 (isc_un_op_fn
) &isl_union_pw_qpolynomial_domain
} },
551 {"dom", { -1, isl_obj_union_pw_qpolynomial_fold
,
553 (isc_un_op_fn
) &isl_union_pw_qpolynomial_fold_domain
} },
554 {"ran", { -1, isl_obj_union_map
, isl_obj_union_set
,
555 (isc_un_op_fn
) &isl_union_map_range
} },
556 {"lexmin", { -1, isl_obj_union_map
, isl_obj_union_map
,
557 (isc_un_op_fn
) &isl_union_map_lexmin
} },
558 {"lexmax", { -1, isl_obj_union_map
, isl_obj_union_map
,
559 (isc_un_op_fn
) &isl_union_map_lexmax
} },
560 {"lexmin", { -1, isl_obj_union_set
, isl_obj_union_set
,
561 (isc_un_op_fn
) &isl_union_set_lexmin
} },
562 {"lexmax", { -1, isl_obj_union_set
, isl_obj_union_set
,
563 (isc_un_op_fn
) &isl_union_set_lexmax
} },
564 {"sample", { -1, isl_obj_union_set
, isl_obj_set
,
565 (isc_un_op_fn
) &union_set_sample
} },
566 {"sample", { -1, isl_obj_union_map
, isl_obj_map
,
567 (isc_un_op_fn
) &union_map_sample
} },
568 {"sum", { -1, isl_obj_union_pw_qpolynomial
,
569 isl_obj_union_pw_qpolynomial
,
570 (isc_un_op_fn
) &isl_union_pw_qpolynomial_sum
} },
571 {"ub", { -1, isl_obj_union_pw_qpolynomial
, isl_obj_list
,
572 (isc_un_op_fn
) &union_pw_qpolynomial_upper_bound
} },
573 {"unwrap", { -1, isl_obj_union_set
, isl_obj_union_map
,
574 (isc_un_op_fn
) &isl_union_set_unwrap
} },
575 {"wrap", { -1, isl_obj_union_map
, isl_obj_union_set
,
576 (isc_un_op_fn
) &isl_union_map_wrap
} },
580 struct isl_named_obj
{
585 static void free_obj(struct isl_obj obj
)
587 obj
.type
->free(obj
.v
);
590 static int same_name(const void *entry
, const void *val
)
592 const struct isl_named_obj
*named
= (const struct isl_named_obj
*)entry
;
594 return !strcmp(named
->name
, val
);
597 static int do_assign(struct isl_ctx
*ctx
, struct isl_hash_table
*table
,
598 char *name
, struct isl_obj obj
)
600 struct isl_hash_table_entry
*entry
;
602 struct isl_named_obj
*named
;
604 name_hash
= isl_hash_string(isl_hash_init(), name
);
605 entry
= isl_hash_table_find(ctx
, table
, name_hash
, same_name
, name
, 1);
610 free_obj(named
->obj
);
613 named
= isl_alloc_type(ctx
, struct isl_named_obj
);
628 static struct isl_obj
stored_obj(struct isl_ctx
*ctx
,
629 struct isl_hash_table
*table
, char *name
)
631 struct isl_obj obj
= { isl_obj_none
, NULL
};
632 struct isl_hash_table_entry
*entry
;
635 name_hash
= isl_hash_string(isl_hash_init(), name
);
636 entry
= isl_hash_table_find(ctx
, table
, name_hash
, same_name
, name
, 0);
638 struct isl_named_obj
*named
;
642 fprintf(stderr
, "unknown identifier '%s'\n", name
);
645 obj
.v
= obj
.type
->copy(obj
.v
);
649 static int is_subtype(struct isl_obj obj
, isl_obj_type super
)
651 if (obj
.type
== super
)
653 if (obj
.type
== isl_obj_map
&& super
== isl_obj_union_map
)
655 if (obj
.type
== isl_obj_set
&& super
== isl_obj_union_set
)
657 if (obj
.type
== isl_obj_pw_qpolynomial
&&
658 super
== isl_obj_union_pw_qpolynomial
)
660 if (obj
.type
== isl_obj_pw_qpolynomial_fold
&&
661 super
== isl_obj_union_pw_qpolynomial_fold
)
663 if (obj
.type
== isl_obj_union_set
&& isl_union_set_is_empty(obj
.v
))
665 if (obj
.type
== isl_obj_list
) {
666 struct isl_list
*list
= obj
.v
;
667 if (list
->n
== 2 && list
->obj
[1].type
== isl_obj_bool
)
668 return is_subtype(list
->obj
[0], super
);
670 if (super
== isl_obj_str
)
675 static struct isl_obj
obj_at(struct isl_obj obj
, int i
)
677 struct isl_list
*list
= obj
.v
;
680 obj
.v
= obj
.type
->copy(obj
.v
);
687 static struct isl_obj
convert(isl_ctx
*ctx
, struct isl_obj obj
,
690 if (obj
.type
== type
)
692 if (obj
.type
== isl_obj_map
&& type
== isl_obj_union_map
) {
693 obj
.type
= isl_obj_union_map
;
694 obj
.v
= isl_union_map_from_map(obj
.v
);
697 if (obj
.type
== isl_obj_set
&& type
== isl_obj_union_set
) {
698 obj
.type
= isl_obj_union_set
;
699 obj
.v
= isl_union_set_from_set(obj
.v
);
702 if (obj
.type
== isl_obj_pw_qpolynomial
&&
703 type
== isl_obj_union_pw_qpolynomial
) {
704 obj
.type
= isl_obj_union_pw_qpolynomial
;
705 obj
.v
= isl_union_pw_qpolynomial_from_pw_qpolynomial(obj
.v
);
708 if (obj
.type
== isl_obj_pw_qpolynomial_fold
&&
709 type
== isl_obj_union_pw_qpolynomial_fold
) {
710 obj
.type
= isl_obj_union_pw_qpolynomial_fold
;
711 obj
.v
= isl_union_pw_qpolynomial_fold_from_pw_qpolynomial_fold(obj
.v
);
714 if (obj
.type
== isl_obj_union_set
&& isl_union_set_is_empty(obj
.v
)) {
715 if (type
== isl_obj_union_map
) {
716 obj
.type
= isl_obj_union_map
;
719 if (type
== isl_obj_union_pw_qpolynomial
) {
720 isl_dim
*dim
= isl_union_set_get_dim(obj
.v
);
721 isl_union_set_free(obj
.v
);
722 obj
.v
= isl_union_pw_qpolynomial_zero(dim
);
723 obj
.type
= isl_obj_union_pw_qpolynomial
;
726 if (type
== isl_obj_union_pw_qpolynomial_fold
) {
727 isl_dim
*dim
= isl_union_set_get_dim(obj
.v
);
728 isl_union_set_free(obj
.v
);
729 obj
.v
= isl_union_pw_qpolynomial_fold_zero(dim
,
731 obj
.type
= isl_obj_union_pw_qpolynomial_fold
;
735 if (obj
.type
== isl_obj_list
) {
736 struct isl_list
*list
= obj
.v
;
737 if (list
->n
== 2 && list
->obj
[1].type
== isl_obj_bool
)
738 return convert(ctx
, obj_at(obj
, 0), type
);
740 if (type
== isl_obj_str
) {
745 p
= isl_printer_to_str(ctx
);
748 p
= obj
.type
->print(p
, obj
.v
);
749 s
= isl_printer_get_str(p
);
752 str
= isl_str_alloc(ctx
);
760 obj
.type
= isl_obj_str
;
766 obj
.type
= isl_obj_none
;
771 static struct isc_bin_op
*read_bin_op_if_available(struct isl_stream
*s
,
775 struct isl_token
*tok
;
777 tok
= isl_stream_next_token(s
);
784 if (bin_ops
[i
].op
!= tok
->type
)
786 if (!is_subtype(lhs
, bin_ops
[i
].lhs
))
794 if (!named_bin_ops
[i
].name
)
796 if (named_bin_ops
[i
].op
.op
!= tok
->type
)
798 if (!is_subtype(lhs
, named_bin_ops
[i
].op
.lhs
))
802 return &named_bin_ops
[i
].op
;
805 isl_stream_push_token(s
, tok
);
810 static struct isc_un_op
*read_prefix_un_op_if_available(struct isl_stream
*s
)
813 struct isl_token
*tok
;
815 tok
= isl_stream_next_token(s
);
820 if (!named_un_ops
[i
].name
)
822 if (named_un_ops
[i
].op
.op
!= tok
->type
)
826 return &named_un_ops
[i
].op
;
829 isl_stream_push_token(s
, tok
);
834 static struct isc_un_op
*find_matching_un_op(struct isc_un_op
*like
,
840 if (!named_un_ops
[i
].name
)
842 if (named_un_ops
[i
].op
.op
!= like
->op
)
844 if (!is_subtype(arg
, named_un_ops
[i
].op
.arg
))
847 return &named_un_ops
[i
].op
;
853 static int is_assign(struct isl_stream
*s
)
855 struct isl_token
*tok
;
856 struct isl_token
*tok2
;
859 tok
= isl_stream_next_token(s
);
862 if (tok
->type
!= ISL_TOKEN_IDENT
) {
863 isl_stream_push_token(s
, tok
);
867 tok2
= isl_stream_next_token(s
);
869 isl_stream_push_token(s
, tok
);
872 assign
= tok2
->type
== ISL_TOKEN_DEF
;
873 isl_stream_push_token(s
, tok2
);
874 isl_stream_push_token(s
, tok
);
879 static struct isl_obj
read_obj(struct isl_stream
*s
,
880 struct isl_hash_table
*table
);
881 static struct isl_obj
read_expr(struct isl_stream
*s
,
882 struct isl_hash_table
*table
);
884 static struct isl_obj
read_un_op_expr(struct isl_stream
*s
,
885 struct isl_hash_table
*table
, struct isc_un_op
*op
)
887 struct isl_obj obj
= { isl_obj_none
, NULL
};
889 obj
= read_obj(s
, table
);
893 op
= find_matching_un_op(op
, obj
);
895 isl_assert(s
->ctx
, op
, goto error
);
896 obj
= convert(s
->ctx
, obj
, op
->arg
);
897 obj
.v
= op
->fn(obj
.v
);
903 obj
.type
= isl_obj_none
;
908 static struct isl_obj
transitive_closure(struct isl_ctx
*ctx
, struct isl_obj obj
)
910 struct isl_list
*list
;
913 if (obj
.type
!= isl_obj_union_map
)
914 obj
= convert(ctx
, obj
, isl_obj_union_map
);
915 isl_assert(ctx
, obj
.type
== isl_obj_union_map
, goto error
);
916 list
= isl_list_alloc(ctx
, 2);
920 list
->obj
[0].type
= isl_obj_union_map
;
921 list
->obj
[0].v
= isl_union_map_transitive_closure(obj
.v
, &exact
);
922 list
->obj
[1].type
= isl_obj_bool
;
923 list
->obj
[1].v
= exact
? &isl_bool_true
: &isl_bool_false
;
925 obj
.type
= isl_obj_list
;
926 if (exact
< 0 || !list
->obj
[0].v
)
932 obj
.type
= isl_obj_none
;
937 static struct isl_obj
obj_at_index(struct isl_stream
*s
, struct isl_obj obj
)
939 struct isl_list
*list
= obj
.v
;
940 struct isl_token
*tok
;
943 tok
= isl_stream_next_token(s
);
944 if (!tok
|| tok
->type
!= ISL_TOKEN_VALUE
) {
945 isl_stream_error(s
, tok
, "expecting index");
947 isl_stream_push_token(s
, tok
);
950 i
= isl_int_get_si(tok
->u
.v
);
952 isl_assert(s
->ctx
, i
< list
->n
, goto error
);
953 if (isl_stream_eat(s
, ']'))
956 return obj_at(obj
, i
);
959 obj
.type
= isl_obj_none
;
964 static struct isl_obj
apply(struct isl_stream
*s
, __isl_take isl_union_map
*umap
,
965 struct isl_hash_table
*table
)
969 obj
= read_expr(s
, table
);
970 isl_assert(s
->ctx
, is_subtype(obj
, isl_obj_union_set
) ||
971 is_subtype(obj
, isl_obj_union_map
), goto error
);
973 if (obj
.type
== isl_obj_list
) {
974 struct isl_list
*list
= obj
.v
;
975 if (list
->n
== 2 && list
->obj
[1].type
== isl_obj_bool
)
976 obj
= obj_at(obj
, 0);
978 if (obj
.type
== isl_obj_set
)
979 obj
= convert(s
->ctx
, obj
, isl_obj_union_set
);
980 else if (obj
.type
== isl_obj_map
)
981 obj
= convert(s
->ctx
, obj
, isl_obj_union_map
);
982 if (obj
.type
== isl_obj_union_set
) {
983 obj
.v
= isl_union_set_apply(obj
.v
, umap
);
985 obj
.v
= isl_union_map_apply_range(obj
.v
, umap
);
989 if (isl_stream_eat(s
, ')'))
994 isl_union_map_free(umap
);
997 obj
.type
= isl_obj_none
;
1002 struct add_vertex_data
{
1003 struct isl_list
*list
;
1007 static int add_vertex(__isl_take isl_vertex
*vertex
, void *user
)
1009 struct add_vertex_data
*data
= (struct add_vertex_data
*)user
;
1010 isl_basic_set
*expr
;
1012 expr
= isl_vertex_get_expr(vertex
);
1014 data
->list
->obj
[data
->i
].type
= isl_obj_set
;
1015 data
->list
->obj
[data
->i
].v
= isl_set_from_basic_set(expr
);
1018 isl_vertex_free(vertex
);
1023 static int set_vertices(__isl_take isl_set
*set
, void *user
)
1026 isl_basic_set
*hull
;
1027 isl_vertices
*vertices
= NULL
;
1028 struct isl_list
*list
= NULL
;
1030 struct add_vertex_data
*data
= (struct add_vertex_data
*)user
;
1032 set
= isl_set_remove_divs(set
);
1033 hull
= isl_set_convex_hull(set
);
1034 vertices
= isl_basic_set_compute_vertices(hull
);
1035 isl_basic_set_free(hull
);
1039 ctx
= isl_vertices_get_ctx(vertices
);
1040 data
->list
= isl_list_alloc(ctx
, isl_vertices_get_n_vertices(vertices
));
1045 r
= isl_vertices_foreach_vertex(vertices
, &add_vertex
, user
);
1047 data
->list
= isl_list_concat(list
, data
->list
);
1049 isl_vertices_free(vertices
);
1054 isl_vertices_free(vertices
);
1058 static struct isl_obj
vertices(struct isl_stream
*s
,
1059 struct isl_hash_table
*table
)
1063 struct isl_list
*list
= NULL
;
1064 isl_union_set
*uset
;
1065 struct add_vertex_data data
= { NULL
};
1067 obj
= read_expr(s
, table
);
1068 obj
= convert(s
->ctx
, obj
, isl_obj_union_set
);
1069 isl_assert(s
->ctx
, obj
.type
== isl_obj_union_set
, goto error
);
1073 ctx
= isl_union_set_get_ctx(uset
);
1074 list
= isl_list_alloc(ctx
, 0);
1080 if (isl_union_set_foreach_set(uset
, &set_vertices
, &data
) < 0)
1083 isl_union_set_free(uset
);
1085 obj
.type
= isl_obj_list
;
1090 isl_union_set_free(uset
);
1091 isl_list_free(data
.list
);
1093 obj
.type
= isl_obj_none
;
1098 static struct isl_obj
power(struct isl_stream
*s
, struct isl_obj obj
)
1100 struct isl_token
*tok
;
1102 if (isl_stream_eat_if_available(s
, '+'))
1103 return transitive_closure(s
->ctx
, obj
);
1105 tok
= isl_stream_next_token(s
);
1106 if (!tok
|| tok
->type
!= ISL_TOKEN_VALUE
|| isl_int_cmp_si(tok
->u
.v
, -1)) {
1107 isl_stream_error(s
, tok
, "expecting -1");
1109 isl_stream_push_token(s
, tok
);
1112 isl_token_free(tok
);
1113 isl_assert(s
->ctx
, is_subtype(obj
, isl_obj_union_map
), goto error
);
1114 if (obj
.type
!= isl_obj_union_map
)
1115 obj
= convert(s
->ctx
, obj
, isl_obj_union_map
);
1117 obj
.v
= isl_union_map_reverse(obj
.v
);
1124 obj
.type
= isl_obj_none
;
1129 static struct isl_obj
read_from_file(struct isl_stream
*s
)
1132 struct isl_token
*tok
;
1133 struct isl_stream
*s_file
;
1136 tok
= isl_stream_next_token(s
);
1137 if (!tok
|| tok
->type
!= ISL_TOKEN_STRING
) {
1138 isl_stream_error(s
, tok
, "expecting filename");
1139 isl_token_free(tok
);
1143 file
= fopen(tok
->u
.s
, "r");
1144 isl_token_free(tok
);
1145 isl_assert(s
->ctx
, file
, goto error
);
1147 s_file
= isl_stream_new_file(s
->ctx
, file
);
1153 obj
= isl_stream_read_obj(s_file
);
1155 isl_stream_free(s_file
);
1160 obj
.type
= isl_obj_none
;
1165 static struct isl_obj
read_string_if_available(struct isl_stream
*s
)
1167 struct isl_token
*tok
;
1168 struct isl_obj obj
= { isl_obj_none
, NULL
};
1170 tok
= isl_stream_next_token(s
);
1173 if (tok
->type
== ISL_TOKEN_STRING
) {
1175 str
= isl_str_alloc(s
->ctx
);
1178 str
->s
= strdup(tok
->u
.s
);
1179 isl_token_free(tok
);
1181 obj
.type
= isl_obj_str
;
1183 isl_stream_push_token(s
, tok
);
1186 isl_token_free(tok
);
1190 static struct isl_obj
read_obj(struct isl_stream
*s
,
1191 struct isl_hash_table
*table
)
1193 struct isl_obj obj
= { isl_obj_none
, NULL
};
1195 struct isc_un_op
*op
= NULL
;
1197 obj
= read_string_if_available(s
);
1200 if (isl_stream_eat_if_available(s
, '(')) {
1201 obj
= read_expr(s
, table
);
1202 if (!obj
.v
|| isl_stream_eat(s
, ')'))
1205 op
= read_prefix_un_op_if_available(s
);
1207 return read_un_op_expr(s
, table
, op
);
1209 if (isl_stream_eat_if_available(s
, read_op
))
1210 return read_from_file(s
);
1211 if (isl_stream_eat_if_available(s
, vertices_op
))
1212 return vertices(s
, table
);
1214 name
= isl_stream_read_ident_if_available(s
);
1216 obj
= stored_obj(s
->ctx
, table
, name
);
1218 obj
= isl_stream_read_obj(s
);
1223 if (isl_stream_eat_if_available(s
, '^'))
1224 obj
= power(s
, obj
);
1225 else if (obj
.type
== isl_obj_list
&& isl_stream_eat_if_available(s
, '['))
1226 obj
= obj_at_index(s
, obj
);
1227 else if (is_subtype(obj
, isl_obj_union_map
) &&
1228 isl_stream_eat_if_available(s
, '(')) {
1229 obj
= convert(s
->ctx
, obj
, isl_obj_union_map
);
1230 obj
= apply(s
, obj
.v
, table
);
1236 obj
.type
= isl_obj_none
;
1241 static struct isc_bin_op
*find_matching_bin_op(struct isc_bin_op
*like
,
1242 struct isl_obj lhs
, struct isl_obj rhs
)
1246 for (i
= 0; ; ++i
) {
1249 if (bin_ops
[i
].op
!= like
->op
)
1251 if (!is_subtype(lhs
, bin_ops
[i
].lhs
))
1253 if (!is_subtype(rhs
, bin_ops
[i
].rhs
))
1259 for (i
= 0; ; ++i
) {
1260 if (!named_bin_ops
[i
].name
)
1262 if (named_bin_ops
[i
].op
.op
!= like
->op
)
1264 if (!is_subtype(lhs
, named_bin_ops
[i
].op
.lhs
))
1266 if (!is_subtype(rhs
, named_bin_ops
[i
].op
.rhs
))
1269 return &named_bin_ops
[i
].op
;
1275 static struct isl_obj
read_expr(struct isl_stream
*s
,
1276 struct isl_hash_table
*table
)
1278 struct isl_obj obj
= { isl_obj_none
, NULL
};
1279 struct isl_obj right_obj
= { isl_obj_none
, NULL
};
1281 obj
= read_obj(s
, table
);
1283 struct isc_bin_op
*op
= NULL
;
1285 op
= read_bin_op_if_available(s
, obj
);
1289 right_obj
= read_obj(s
, table
);
1291 op
= find_matching_bin_op(op
, obj
, right_obj
);
1293 isl_assert(s
->ctx
, op
, goto error
);
1294 obj
= convert(s
->ctx
, obj
, op
->lhs
);
1295 right_obj
= convert(s
->ctx
, right_obj
, op
->rhs
);
1296 obj
.v
= op
->fn(obj
.v
, right_obj
.v
);
1302 free_obj(right_obj
);
1304 obj
.type
= isl_obj_none
;
1309 static __isl_give isl_printer
*source_file(struct isl_stream
*s
,
1310 struct isl_hash_table
*table
, __isl_take isl_printer
*p
);
1312 static __isl_give isl_printer
*read_line(struct isl_stream
*s
,
1313 struct isl_hash_table
*table
, __isl_take isl_printer
*p
)
1315 struct isl_obj obj
= { isl_obj_none
, NULL
};
1318 struct isc_bin_op
*op
= NULL
;
1322 if (isl_stream_is_empty(s
))
1325 if (isl_stream_eat_if_available(s
, source_op
))
1326 return source_file(s
, table
, p
);
1328 assign
= is_assign(s
);
1330 lhs
= isl_stream_read_ident_if_available(s
);
1331 if (isl_stream_eat(s
, ISL_TOKEN_DEF
))
1335 obj
= read_expr(s
, table
);
1336 if (obj
.type
== isl_obj_none
|| obj
.v
== NULL
)
1338 if (isl_stream_eat(s
, ';'))
1342 if (do_assign(s
->ctx
, table
, lhs
, obj
))
1345 p
= obj
.type
->print(p
, obj
.v
);
1346 p
= isl_printer_end_line(p
);
1352 isl_stream_flush_tokens(s
);
1353 isl_stream_skip_line(s
);
1359 int free_cb(void **entry
, void *user
)
1361 struct isl_named_obj
*named
= *entry
;
1363 free_obj(named
->obj
);
1370 static void register_named_ops(struct isl_stream
*s
)
1374 read_op
= isl_stream_register_keyword(s
, "read");
1375 assert(read_op
!= ISL_TOKEN_ERROR
);
1376 source_op
= isl_stream_register_keyword(s
, "source");
1377 assert(source_op
!= ISL_TOKEN_ERROR
);
1378 vertices_op
= isl_stream_register_keyword(s
, "vertices");
1379 assert(vertices_op
!= ISL_TOKEN_ERROR
);
1381 for (i
= 0; ; ++i
) {
1382 if (!named_un_ops
[i
].name
)
1384 named_un_ops
[i
].op
.op
= isl_stream_register_keyword(s
,
1385 named_un_ops
[i
].name
);
1386 assert(named_un_ops
[i
].op
.op
!= ISL_TOKEN_ERROR
);
1389 for (i
= 0; ; ++i
) {
1390 if (!named_bin_ops
[i
].name
)
1392 named_bin_ops
[i
].op
.op
= isl_stream_register_keyword(s
,
1393 named_bin_ops
[i
].name
);
1394 assert(named_bin_ops
[i
].op
.op
!= ISL_TOKEN_ERROR
);
1398 static __isl_give isl_printer
*source_file(struct isl_stream
*s
,
1399 struct isl_hash_table
*table
, __isl_take isl_printer
*p
)
1401 struct isl_token
*tok
;
1402 struct isl_stream
*s_file
;
1405 tok
= isl_stream_next_token(s
);
1406 if (!tok
|| tok
->type
!= ISL_TOKEN_STRING
) {
1407 isl_stream_error(s
, tok
, "expecting filename");
1408 isl_token_free(tok
);
1412 file
= fopen(tok
->u
.s
, "r");
1413 isl_token_free(tok
);
1414 isl_assert(s
->ctx
, file
, return p
);
1416 s_file
= isl_stream_new_file(s
->ctx
, file
);
1422 register_named_ops(s_file
);
1424 while (!s_file
->eof
)
1425 p
= read_line(s_file
, table
, p
);
1427 isl_stream_free(s_file
);
1430 isl_stream_eat(s
, ';');
1435 int main(int argc
, char **argv
)
1437 struct isl_ctx
*ctx
;
1438 struct isl_stream
*s
;
1439 struct isl_hash_table
*table
;
1440 struct iscc_options
*options
;
1443 options
= iscc_options_new_with_defaults();
1445 argc
= iscc_options_parse(options
, argc
, argv
, ISL_ARG_ALL
);
1447 ctx
= isl_ctx_alloc_with_options(iscc_options_arg
, options
);
1448 s
= isl_stream_new_file(ctx
, stdin
);
1450 table
= isl_hash_table_alloc(ctx
, 10);
1452 p
= isl_printer_to_file(ctx
, stdout
);
1453 p
= isl_printer_set_output_format(p
, options
->format
);
1456 register_named_ops(s
);
1459 p
= read_line(s
, table
, p
);
1462 isl_printer_free(p
);
1463 isl_hash_table_foreach(ctx
, table
, free_cb
, NULL
);
1464 isl_hash_table_free(ctx
, table
);