5 #include <isl_stream.h>
6 #include <isl_vertices.h>
7 #include <isl_obj_list.h>
8 #include <barvinok/barvinok.h>
12 static int isl_bool_false
= 0;
13 static int isl_bool_true
= 1;
14 static int isl_bool_error
= -1;
16 static enum isl_token_type read_op
;
17 static enum isl_token_type vertices_op
;
19 struct isl_arg_choice iscc_format
[] = {
20 {"isl", ISL_FORMAT_ISL
},
21 {"omega", ISL_FORMAT_OMEGA
},
22 {"polylib", ISL_FORMAT_POLYLIB
},
23 {"latex", ISL_FORMAT_LATEX
},
29 struct barvinok_options
*barvinok
;
33 struct isl_arg iscc_options_arg
[] = {
34 ISL_ARG_CHILD(struct iscc_options
, barvinok
, "barvinok", barvinok_options_arg
,
36 ISL_ARG_CHOICE(struct iscc_options
, format
, 0, "format", \
37 iscc_format
, ISL_FORMAT_ISL
, "output format")
41 ISL_ARG_DEF(iscc_options
, struct iscc_options
, iscc_options_arg
)
43 static void *isl_obj_bool_copy(void *v
)
48 static void isl_obj_bool_free(void *v
)
52 static __isl_give isl_printer
*isl_obj_bool_print(__isl_take isl_printer
*p
,
55 if (v
== &isl_bool_true
)
56 return isl_printer_print_str(p
, "True");
57 else if (v
== &isl_bool_false
)
58 return isl_printer_print_str(p
, "False");
60 return isl_printer_print_str(p
, "Error");
63 static void *isl_obj_bool_add(void *v1
, void *v2
)
68 struct isl_obj_vtable isl_obj_bool_vtable
= {
74 #define isl_obj_bool (&isl_obj_bool_vtable)
76 int *isl_bool_from_int(int res
)
78 return res
< 0 ? &isl_bool_error
: res
? &isl_bool_true
: &isl_bool_false
;
81 int *map_is_equal(__isl_take isl_map
*map1
, __isl_take isl_map
*map2
)
83 int res
= isl_map_is_equal(map1
, map2
);
86 return isl_bool_from_int(res
);
88 int *set_is_equal(__isl_take isl_set
*set1
, __isl_take isl_set
*set2
)
90 return map_is_equal((isl_map
*)set1
, (isl_map
*)set2
);
93 int *map_is_subset(__isl_take isl_map
*map1
, __isl_take isl_map
*map2
)
95 int res
= isl_map_is_subset(map1
, map2
);
98 return isl_bool_from_int(res
);
100 int *set_is_subset(__isl_take isl_set
*set1
, __isl_take isl_set
*set2
)
102 return map_is_subset((isl_map
*)set1
, (isl_map
*)set2
);
105 int *map_is_strict_subset(__isl_take isl_map
*map1
, __isl_take isl_map
*map2
)
107 int res
= isl_map_is_strict_subset(map1
, map2
);
110 return isl_bool_from_int(res
);
112 int *set_is_strict_subset(__isl_take isl_set
*set1
, __isl_take isl_set
*set2
)
114 return map_is_strict_subset((isl_map
*)set1
, (isl_map
*)set2
);
117 int *map_is_superset(__isl_take isl_map
*map1
, __isl_take isl_map
*map2
)
119 return map_is_subset(map2
, map1
);
121 int *set_is_superset(__isl_take isl_set
*set1
, __isl_take isl_set
*set2
)
123 return set_is_subset(set2
, set1
);
126 int *map_is_strict_superset(__isl_take isl_map
*map1
, __isl_take isl_map
*map2
)
128 return map_is_strict_subset(map2
, map1
);
130 int *set_is_strict_superset(__isl_take isl_set
*set1
, __isl_take isl_set
*set2
)
132 return set_is_strict_subset(set2
, set1
);
135 extern struct isl_obj_vtable isl_obj_list_vtable
;
136 #define isl_obj_list (&isl_obj_list_vtable)
138 typedef void *(*isc_bin_op_fn
)(void *lhs
, void *rhs
);
140 enum isl_token_type op
;
146 struct isc_named_bin_op
{
148 struct isc_bin_op op
;
152 isl_pw_qpolynomial
*pwqp
;
153 isl_pw_qpolynomial
*res
;
156 static int eval_at(__isl_take isl_point
*pnt
, void *user
)
158 struct iscc_at
*at
= (struct iscc_at
*) user
;
162 set
= isl_set_from_point(isl_point_copy(pnt
));
163 qp
= isl_pw_qpolynomial_eval(isl_pw_qpolynomial_copy(at
->pwqp
), pnt
);
165 at
->res
= isl_pw_qpolynomial_add_disjoint(at
->res
,
166 isl_pw_qpolynomial_alloc(set
, qp
));
171 __isl_give isl_pw_qpolynomial
*isl_pw_qpolynomial_at(
172 __isl_take isl_pw_qpolynomial
*pwqp
, __isl_take isl_set
*set
)
177 at
.res
= isl_pw_qpolynomial_zero(isl_set_get_dim(set
));
179 isl_set_foreach_point(set
, eval_at
, &at
);
181 isl_pw_qpolynomial_free(pwqp
);
187 struct iscc_fold_at
{
188 isl_pw_qpolynomial_fold
*pwf
;
189 isl_pw_qpolynomial
*res
;
192 static int eval_fold_at(__isl_take isl_point
*pnt
, void *user
)
194 struct iscc_fold_at
*at
= (struct iscc_fold_at
*) user
;
198 set
= isl_set_from_point(isl_point_copy(pnt
));
199 qp
= isl_pw_qpolynomial_fold_eval(isl_pw_qpolynomial_fold_copy(at
->pwf
),
202 at
->res
= isl_pw_qpolynomial_add_disjoint(at
->res
,
203 isl_pw_qpolynomial_alloc(set
, qp
));
208 __isl_give isl_pw_qpolynomial
*isl_pw_qpolynomial_fold_at(
209 __isl_take isl_pw_qpolynomial_fold
*pwf
, __isl_take isl_set
*set
)
211 struct iscc_fold_at at
;
214 at
.res
= isl_pw_qpolynomial_zero(isl_set_get_dim(set
));
216 isl_set_foreach_point(set
, eval_fold_at
, &at
);
218 isl_pw_qpolynomial_fold_free(pwf
);
224 struct isc_bin_op bin_ops
[] = {
225 { '+', isl_obj_set
, isl_obj_set
,
227 (isc_bin_op_fn
) &isl_set_union
},
228 { '+', isl_obj_map
, isl_obj_map
,
230 (isc_bin_op_fn
) &isl_map_union
},
231 { '-', isl_obj_set
, isl_obj_set
,
233 (isc_bin_op_fn
) &isl_set_subtract
},
234 { '-', isl_obj_map
, isl_obj_map
,
236 (isc_bin_op_fn
) &isl_map_subtract
},
237 { '*', isl_obj_set
, isl_obj_set
,
239 (isc_bin_op_fn
) &isl_set_intersect
},
240 { '*', isl_obj_map
, isl_obj_map
,
242 (isc_bin_op_fn
) &isl_map_intersect
},
243 { '*', isl_obj_map
, isl_obj_set
,
245 (isc_bin_op_fn
) &isl_map_intersect_domain
},
246 { '.', isl_obj_map
, isl_obj_map
,
248 (isc_bin_op_fn
) &isl_map_apply_range
},
249 { ISL_TOKEN_TO
, isl_obj_set
, isl_obj_set
, isl_obj_map
,
250 (isc_bin_op_fn
) &isl_map_from_domain_and_range
},
251 { '=', isl_obj_set
, isl_obj_set
, isl_obj_bool
,
252 (isc_bin_op_fn
) &set_is_equal
},
253 { '=', isl_obj_map
, isl_obj_map
, isl_obj_bool
,
254 (isc_bin_op_fn
) &map_is_equal
},
255 { ISL_TOKEN_LE
, isl_obj_set
, isl_obj_set
, isl_obj_bool
,
256 (isc_bin_op_fn
) &set_is_subset
},
257 { ISL_TOKEN_LE
, isl_obj_map
, isl_obj_map
, isl_obj_bool
,
258 (isc_bin_op_fn
) &map_is_subset
},
259 { ISL_TOKEN_LT
, isl_obj_set
, isl_obj_set
, isl_obj_bool
,
260 (isc_bin_op_fn
) &set_is_strict_subset
},
261 { ISL_TOKEN_LT
, isl_obj_map
, isl_obj_map
, isl_obj_bool
,
262 (isc_bin_op_fn
) &map_is_strict_subset
},
263 { ISL_TOKEN_GE
, isl_obj_set
, isl_obj_set
, isl_obj_bool
,
264 (isc_bin_op_fn
) &set_is_superset
},
265 { ISL_TOKEN_GE
, isl_obj_map
, isl_obj_map
, isl_obj_bool
,
266 (isc_bin_op_fn
) &map_is_superset
},
267 { ISL_TOKEN_GT
, isl_obj_set
, isl_obj_set
, isl_obj_bool
,
268 (isc_bin_op_fn
) &set_is_strict_superset
},
269 { ISL_TOKEN_GT
, isl_obj_map
, isl_obj_map
, isl_obj_bool
,
270 (isc_bin_op_fn
) &map_is_strict_superset
},
271 { '+', isl_obj_pw_qpolynomial
, isl_obj_pw_qpolynomial
,
272 isl_obj_pw_qpolynomial
,
273 (isc_bin_op_fn
) &isl_pw_qpolynomial_add
},
274 { '-', isl_obj_pw_qpolynomial
, isl_obj_pw_qpolynomial
,
275 isl_obj_pw_qpolynomial
,
276 (isc_bin_op_fn
) &isl_pw_qpolynomial_sub
},
277 { '*', isl_obj_pw_qpolynomial
, isl_obj_pw_qpolynomial
,
278 isl_obj_pw_qpolynomial
,
279 (isc_bin_op_fn
) &isl_pw_qpolynomial_mul
},
280 { '*', isl_obj_pw_qpolynomial
, isl_obj_set
,
281 isl_obj_pw_qpolynomial
,
282 (isc_bin_op_fn
) &isl_pw_qpolynomial_intersect_domain
},
283 { '*', isl_obj_pw_qpolynomial_fold
, isl_obj_set
,
284 isl_obj_pw_qpolynomial_fold
,
285 (isc_bin_op_fn
) &isl_pw_qpolynomial_fold_intersect_domain
},
286 { '@', isl_obj_pw_qpolynomial
, isl_obj_set
,
287 isl_obj_pw_qpolynomial
,
288 (isc_bin_op_fn
) &isl_pw_qpolynomial_at
},
289 { '@', isl_obj_pw_qpolynomial_fold
, isl_obj_set
,
290 isl_obj_pw_qpolynomial
,
291 (isc_bin_op_fn
) &isl_pw_qpolynomial_fold_at
},
292 { '%', isl_obj_set
, isl_obj_set
,
294 (isc_bin_op_fn
) &isl_set_gist
},
295 { '%', isl_obj_map
, isl_obj_map
,
297 (isc_bin_op_fn
) &isl_map_gist
},
298 { '%', isl_obj_pw_qpolynomial
, isl_obj_set
,
299 isl_obj_pw_qpolynomial
,
300 (isc_bin_op_fn
) &isl_pw_qpolynomial_gist
},
301 { '%', isl_obj_pw_qpolynomial_fold
, isl_obj_set
,
302 isl_obj_pw_qpolynomial_fold
,
303 (isc_bin_op_fn
) &isl_pw_qpolynomial_fold_gist
},
306 struct isc_named_bin_op named_bin_ops
[] = {
307 { "cross", { -1, isl_obj_set
, isl_obj_set
, isl_obj_set
,
308 (isc_bin_op_fn
) &isl_set_product
} },
309 { "cross", { -1, isl_obj_map
, isl_obj_map
, isl_obj_map
,
310 (isc_bin_op_fn
) &isl_map_product
} },
314 __isl_give isl_set
*set_sample(__isl_take isl_set
*set
)
316 return isl_set_from_basic_set(isl_set_sample(set
));
319 __isl_give isl_map
*map_sample(__isl_take isl_map
*map
)
321 return isl_map_from_basic_map(isl_map_sample(map
));
324 static __isl_give isl_set
*set_affine_hull(__isl_take isl_set
*set
)
326 return isl_set_from_basic_set(isl_set_affine_hull(set
));
329 static __isl_give isl_map
*map_affine_hull(__isl_take isl_map
*map
)
331 return isl_map_from_basic_map(isl_map_affine_hull(map
));
334 static __isl_give
struct isl_list
*pw_qpolynomial_upper_bound(
335 __isl_take isl_pw_qpolynomial
*pwqp
)
338 struct isl_list
*list
;
341 ctx
= isl_pw_qpolynomial_get_ctx(pwqp
);
342 list
= isl_list_alloc(ctx
, 2);
346 list
->obj
[0].type
= isl_obj_pw_qpolynomial_fold
;
347 list
->obj
[0].v
= isl_pw_qpolynomial_bound(pwqp
, isl_fold_max
, &tight
);
348 list
->obj
[1].type
= isl_obj_bool
;
349 list
->obj
[1].v
= tight
? &isl_bool_true
: &isl_bool_false
;
350 if (tight
< 0 || !list
->obj
[0].v
)
359 typedef void *(*isc_un_op_fn
)(void *arg
);
361 enum isl_token_type op
;
366 struct isc_named_un_op
{
370 struct isc_named_un_op named_un_ops
[] = {
371 {"aff", { -1, isl_obj_map
, isl_obj_map
,
372 (isc_un_op_fn
) &map_affine_hull
} },
373 {"aff", { -1, isl_obj_set
, isl_obj_set
,
374 (isc_un_op_fn
) &set_affine_hull
} },
375 {"card", { -1, isl_obj_set
, isl_obj_pw_qpolynomial
,
376 (isc_un_op_fn
) &isl_set_card
} },
377 {"card", { -1, isl_obj_map
, isl_obj_pw_qpolynomial
,
378 (isc_un_op_fn
) &isl_map_card
} },
379 {"coalesce", { -1, isl_obj_set
, isl_obj_set
,
380 (isc_un_op_fn
) &isl_set_coalesce
} },
381 {"coalesce", { -1, isl_obj_map
, isl_obj_map
,
382 (isc_un_op_fn
) &isl_map_coalesce
} },
383 {"coalesce", { -1, isl_obj_pw_qpolynomial
, isl_obj_pw_qpolynomial
,
384 (isc_un_op_fn
) &isl_pw_qpolynomial_coalesce
} },
385 {"coalesce", { -1, isl_obj_pw_qpolynomial_fold
,
386 isl_obj_pw_qpolynomial_fold
,
387 (isc_un_op_fn
) &isl_pw_qpolynomial_fold_coalesce
} },
388 {"deltas", { -1, isl_obj_map
, isl_obj_set
,
389 (isc_un_op_fn
) &isl_map_deltas
} },
390 {"dom", { -1, isl_obj_map
, isl_obj_set
,
391 (isc_un_op_fn
) &isl_map_domain
} },
392 {"dom", { -1, isl_obj_pw_qpolynomial
, isl_obj_set
,
393 (isc_un_op_fn
) &isl_pw_qpolynomial_domain
} },
394 {"dom", { -1, isl_obj_pw_qpolynomial_fold
, isl_obj_set
,
395 (isc_un_op_fn
) &isl_pw_qpolynomial_fold_domain
} },
396 {"ran", { -1, isl_obj_map
, isl_obj_set
,
397 (isc_un_op_fn
) &isl_map_range
} },
398 {"lexmin", { -1, isl_obj_map
, isl_obj_map
,
399 (isc_un_op_fn
) &isl_map_lexmin
} },
400 {"lexmax", { -1, isl_obj_map
, isl_obj_map
,
401 (isc_un_op_fn
) &isl_map_lexmax
} },
402 {"lexmin", { -1, isl_obj_set
, isl_obj_set
,
403 (isc_un_op_fn
) &isl_set_lexmin
} },
404 {"lexmax", { -1, isl_obj_set
, isl_obj_set
,
405 (isc_un_op_fn
) &isl_set_lexmax
} },
406 {"sample", { -1, isl_obj_set
, isl_obj_set
,
407 (isc_un_op_fn
) &set_sample
} },
408 {"sample", { -1, isl_obj_map
, isl_obj_map
,
409 (isc_un_op_fn
) &map_sample
} },
410 {"sum", { -1, isl_obj_pw_qpolynomial
, isl_obj_pw_qpolynomial
,
411 (isc_un_op_fn
) &isl_pw_qpolynomial_sum
} },
412 {"ub", { -1, isl_obj_pw_qpolynomial
, isl_obj_list
,
413 (isc_un_op_fn
) &pw_qpolynomial_upper_bound
} },
417 struct isl_named_obj
{
422 static void free_obj(struct isl_obj obj
)
424 obj
.type
->free(obj
.v
);
427 static int same_name(const void *entry
, const void *val
)
429 const struct isl_named_obj
*named
= (const struct isl_named_obj
*)entry
;
431 return !strcmp(named
->name
, val
);
434 static int do_assign(struct isl_ctx
*ctx
, struct isl_hash_table
*table
,
435 char *name
, struct isl_obj obj
)
437 struct isl_hash_table_entry
*entry
;
439 struct isl_named_obj
*named
;
441 name_hash
= isl_hash_string(isl_hash_init(), name
);
442 entry
= isl_hash_table_find(ctx
, table
, name_hash
, same_name
, name
, 1);
447 free_obj(named
->obj
);
450 named
= isl_alloc_type(ctx
, struct isl_named_obj
);
465 static struct isl_obj
stored_obj(struct isl_ctx
*ctx
,
466 struct isl_hash_table
*table
, char *name
)
468 struct isl_obj obj
= { isl_obj_none
, NULL
};
469 struct isl_hash_table_entry
*entry
;
472 name_hash
= isl_hash_string(isl_hash_init(), name
);
473 entry
= isl_hash_table_find(ctx
, table
, name_hash
, same_name
, name
, 0);
475 struct isl_named_obj
*named
;
481 obj
.v
= obj
.type
->copy(obj
.v
);
485 static struct isc_bin_op
*read_bin_op_if_available(struct isl_stream
*s
,
489 struct isl_token
*tok
;
491 tok
= isl_stream_next_token(s
);
498 if (bin_ops
[i
].op
!= tok
->type
)
500 if (bin_ops
[i
].lhs
!= lhs
)
508 if (!named_bin_ops
[i
].name
)
510 if (named_bin_ops
[i
].op
.op
!= tok
->type
)
512 if (named_bin_ops
[i
].op
.lhs
!= lhs
)
516 return &named_bin_ops
[i
].op
;
519 isl_stream_push_token(s
, tok
);
524 static struct isc_un_op
*read_prefix_un_op_if_available(struct isl_stream
*s
)
527 struct isl_token
*tok
;
529 tok
= isl_stream_next_token(s
);
534 if (!named_un_ops
[i
].name
)
536 if (named_un_ops
[i
].op
.op
!= tok
->type
)
540 return &named_un_ops
[i
].op
;
543 isl_stream_push_token(s
, tok
);
548 static struct isc_un_op
*find_matching_un_op(struct isc_un_op
*like
,
554 if (!named_un_ops
[i
].name
)
556 if (named_un_ops
[i
].op
.op
!= like
->op
)
558 if (named_un_ops
[i
].op
.arg
!= arg
)
561 return &named_un_ops
[i
].op
;
567 static int is_assign(struct isl_stream
*s
)
569 struct isl_token
*tok
;
570 struct isl_token
*tok2
;
573 tok
= isl_stream_next_token(s
);
576 if (tok
->type
!= ISL_TOKEN_IDENT
) {
577 isl_stream_push_token(s
, tok
);
581 tok2
= isl_stream_next_token(s
);
583 isl_stream_push_token(s
, tok
);
586 assign
= tok2
->type
== ISL_TOKEN_DEF
;
587 isl_stream_push_token(s
, tok2
);
588 isl_stream_push_token(s
, tok
);
593 static struct isl_obj
read_obj(struct isl_stream
*s
,
594 struct isl_hash_table
*table
);
595 static struct isl_obj
read_expr(struct isl_stream
*s
,
596 struct isl_hash_table
*table
);
598 static struct isl_obj
read_un_op_expr(struct isl_stream
*s
,
599 struct isl_hash_table
*table
, struct isc_un_op
*op
)
601 struct isl_obj obj
= { isl_obj_none
, NULL
};
603 obj
= read_obj(s
, table
);
607 op
= find_matching_un_op(op
, obj
.type
);
609 isl_assert(s
->ctx
, op
, goto error
);
610 obj
.v
= op
->fn(obj
.v
);
616 obj
.type
= isl_obj_none
;
621 static struct isl_obj
transitive_closure(struct isl_ctx
*ctx
, struct isl_obj obj
)
623 struct isl_list
*list
;
626 isl_assert(ctx
, obj
.type
== isl_obj_map
, goto error
);
627 list
= isl_list_alloc(ctx
, 2);
631 list
->obj
[0].type
= isl_obj_map
;
632 list
->obj
[0].v
= isl_map_transitive_closure(obj
.v
, &exact
);
633 list
->obj
[1].type
= isl_obj_bool
;
634 list
->obj
[1].v
= exact
? &isl_bool_true
: &isl_bool_false
;
636 obj
.type
= isl_obj_list
;
637 if (exact
< 0 || !list
->obj
[0].v
)
643 obj
.type
= isl_obj_none
;
648 static struct isl_obj
obj_at_index(struct isl_stream
*s
, struct isl_obj obj
)
650 struct isl_list
*list
= obj
.v
;
651 struct isl_token
*tok
;
654 tok
= isl_stream_next_token(s
);
655 if (!tok
|| tok
->type
!= ISL_TOKEN_VALUE
) {
656 isl_stream_error(s
, tok
, "expecting index");
658 isl_stream_push_token(s
, tok
);
661 i
= isl_int_get_si(tok
->u
.v
);
663 isl_assert(s
->ctx
, i
< list
->n
, goto error
);
664 if (isl_stream_eat(s
, ']'))
668 obj
.v
= obj
.type
->copy(obj
.v
);
675 obj
.type
= isl_obj_none
;
680 static struct isl_obj
apply(struct isl_stream
*s
, __isl_take isl_map
*map
,
681 struct isl_hash_table
*table
)
685 obj
= read_expr(s
, table
);
686 isl_assert(s
->ctx
, obj
.type
== isl_obj_set
|| obj
.type
== isl_obj_map
,
689 if (obj
.type
== isl_obj_set
) {
690 obj
.v
= isl_set_apply(obj
.v
, map
);
692 obj
.v
= isl_map_apply_range(obj
.v
, map
);
696 if (isl_stream_eat(s
, ')'))
702 obj
.type
= isl_obj_none
;
707 struct add_vertex_data
{
708 struct isl_list
*list
;
712 static int add_vertex(__isl_take isl_vertex
*vertex
, void *user
)
714 struct add_vertex_data
*data
= (struct add_vertex_data
*)user
;
717 expr
= isl_vertex_get_expr(vertex
);
719 data
->list
->obj
[data
->i
].type
= isl_obj_set
;
720 data
->list
->obj
[data
->i
].v
= isl_set_from_basic_set(expr
);
723 isl_vertex_free(vertex
);
728 static struct isl_obj
vertices(struct isl_stream
*s
,
729 struct isl_hash_table
*table
)
735 isl_vertices
*vertices
= NULL
;
736 struct isl_list
*list
= NULL
;
737 struct add_vertex_data data
;
739 obj
= read_expr(s
, table
);
740 isl_assert(s
->ctx
, obj
.type
== isl_obj_set
, goto error
);
743 set
= isl_set_remove_divs(set
);
744 hull
= isl_set_convex_hull(set
);
745 vertices
= isl_basic_set_compute_vertices(hull
);
746 isl_basic_set_free(hull
);
748 ctx
= isl_vertices_get_ctx(vertices
);
749 list
= isl_list_alloc(ctx
, isl_vertices_get_n_vertices(vertices
));
756 if (isl_vertices_foreach_vertex(vertices
, &add_vertex
, &data
) < 0)
759 isl_vertices_free(vertices
);
761 obj
.type
= isl_obj_list
;
766 isl_vertices_free(vertices
);
769 obj
.type
= isl_obj_none
;
774 static struct isl_obj
power(struct isl_stream
*s
, struct isl_obj obj
)
776 struct isl_token
*tok
;
778 if (isl_stream_eat_if_available(s
, '+'))
779 return transitive_closure(s
->ctx
, obj
);
781 tok
= isl_stream_next_token(s
);
782 if (!tok
|| tok
->type
!= ISL_TOKEN_VALUE
|| isl_int_cmp_si(tok
->u
.v
, -1)) {
783 isl_stream_error(s
, tok
, "expecting -1");
785 isl_stream_push_token(s
, tok
);
789 isl_assert(s
->ctx
, obj
.type
== isl_obj_map
, goto error
);
791 obj
.v
= isl_map_reverse(obj
.v
);
798 obj
.type
= isl_obj_none
;
803 static struct isl_obj
read_from_file(struct isl_stream
*s
)
806 struct isl_token
*tok
;
807 struct isl_stream
*s_file
;
810 tok
= isl_stream_next_token(s
);
811 if (!tok
|| tok
->type
!= ISL_TOKEN_STRING
) {
812 isl_stream_error(s
, tok
, "expecting filename");
817 file
= fopen(tok
->u
.s
, "r");
819 isl_assert(s
->ctx
, file
, goto error
);
821 s_file
= isl_stream_new_file(s
->ctx
, file
);
827 obj
= isl_stream_read_obj(s_file
);
829 isl_stream_free(s_file
);
834 obj
.type
= isl_obj_none
;
839 static struct isl_obj
read_obj(struct isl_stream
*s
,
840 struct isl_hash_table
*table
)
842 struct isl_obj obj
= { isl_obj_none
, NULL
};
844 struct isc_un_op
*op
= NULL
;
846 if (isl_stream_eat_if_available(s
, '(')) {
847 obj
= read_expr(s
, table
);
848 if (!obj
.v
|| isl_stream_eat(s
, ')'))
851 op
= read_prefix_un_op_if_available(s
);
853 return read_un_op_expr(s
, table
, op
);
855 if (isl_stream_eat_if_available(s
, read_op
))
856 return read_from_file(s
);
857 if (isl_stream_eat_if_available(s
, vertices_op
))
858 return vertices(s
, table
);
860 name
= isl_stream_read_ident_if_available(s
);
862 obj
= stored_obj(s
->ctx
, table
, name
);
864 obj
= isl_stream_read_obj(s
);
869 if (isl_stream_eat_if_available(s
, '^'))
871 else if (obj
.type
== isl_obj_list
&& isl_stream_eat_if_available(s
, '['))
872 obj
= obj_at_index(s
, obj
);
873 else if (obj
.type
== isl_obj_map
&& isl_stream_eat_if_available(s
, '('))
874 obj
= apply(s
, obj
.v
, table
);
879 obj
.type
= isl_obj_none
;
884 static struct isc_bin_op
*find_matching_bin_op(struct isc_bin_op
*like
,
885 isl_obj_type lhs
, isl_obj_type rhs
)
892 if (bin_ops
[i
].op
!= like
->op
)
894 if (bin_ops
[i
].lhs
!= lhs
)
896 if (bin_ops
[i
].rhs
!= rhs
)
903 if (!named_bin_ops
[i
].name
)
905 if (named_bin_ops
[i
].op
.op
!= like
->op
)
907 if (named_bin_ops
[i
].op
.lhs
!= lhs
)
909 if (named_bin_ops
[i
].op
.rhs
!= rhs
)
912 return &named_bin_ops
[i
].op
;
918 static struct isl_obj
read_expr(struct isl_stream
*s
,
919 struct isl_hash_table
*table
)
921 struct isl_obj obj
= { isl_obj_none
, NULL
};
922 struct isl_obj right_obj
= { isl_obj_none
, NULL
};
924 obj
= read_obj(s
, table
);
926 struct isc_bin_op
*op
= NULL
;
928 op
= read_bin_op_if_available(s
, obj
.type
);
932 right_obj
= read_obj(s
, table
);
934 op
= find_matching_bin_op(op
, obj
.type
, right_obj
.type
);
936 isl_assert(s
->ctx
, op
, goto error
);
937 obj
.v
= op
->fn(obj
.v
, right_obj
.v
);
945 obj
.type
= isl_obj_none
;
950 static __isl_give isl_printer
*read_line(struct isl_stream
*s
,
951 struct isl_hash_table
*table
, __isl_take isl_printer
*p
)
953 struct isl_obj obj
= { isl_obj_none
, NULL
};
956 struct isc_bin_op
*op
= NULL
;
960 if (isl_stream_is_empty(s
))
963 assign
= is_assign(s
);
965 lhs
= isl_stream_read_ident_if_available(s
);
966 if (isl_stream_eat(s
, ISL_TOKEN_DEF
))
970 obj
= read_expr(s
, table
);
971 if (obj
.type
== isl_obj_none
|| obj
.v
== NULL
)
973 if (isl_stream_eat(s
, ';'))
977 if (do_assign(s
->ctx
, table
, lhs
, obj
))
980 p
= obj
.type
->print(p
, obj
.v
);
981 p
= isl_printer_end_line(p
);
987 isl_stream_flush_tokens(s
);
988 isl_stream_skip_line(s
);
994 int free_cb(void *entry
)
996 struct isl_named_obj
*named
= entry
;
998 free_obj(named
->obj
);
1005 static void register_named_ops(struct isl_stream
*s
)
1009 read_op
= isl_stream_register_keyword(s
, "read");
1010 assert(read_op
!= ISL_TOKEN_ERROR
);
1011 vertices_op
= isl_stream_register_keyword(s
, "vertices");
1012 assert(vertices_op
!= ISL_TOKEN_ERROR
);
1014 for (i
= 0; ; ++i
) {
1015 if (!named_un_ops
[i
].name
)
1017 named_un_ops
[i
].op
.op
= isl_stream_register_keyword(s
,
1018 named_un_ops
[i
].name
);
1019 assert(named_un_ops
[i
].op
.op
!= ISL_TOKEN_ERROR
);
1022 for (i
= 0; ; ++i
) {
1023 if (!named_bin_ops
[i
].name
)
1025 named_bin_ops
[i
].op
.op
= isl_stream_register_keyword(s
,
1026 named_bin_ops
[i
].name
);
1027 assert(named_bin_ops
[i
].op
.op
!= ISL_TOKEN_ERROR
);
1031 int main(int argc
, char **argv
)
1033 struct isl_ctx
*ctx
;
1034 struct isl_stream
*s
;
1035 struct isl_hash_table
*table
;
1036 struct iscc_options
*options
;
1039 options
= iscc_options_new_with_defaults();
1041 argc
= iscc_options_parse(options
, argc
, argv
, ISL_ARG_ALL
);
1043 ctx
= isl_ctx_alloc_with_options(iscc_options_arg
, options
);
1044 s
= isl_stream_new_file(ctx
, stdin
);
1046 table
= isl_hash_table_alloc(ctx
, 10);
1048 p
= isl_printer_to_file(ctx
, stdout
);
1049 p
= isl_printer_set_output_format(p
, options
->format
);
1052 register_named_ops(s
);
1055 p
= read_line(s
, table
, p
);
1058 isl_printer_free(p
);
1059 isl_hash_table_foreach(ctx
, table
, free_cb
);
1060 isl_hash_table_free(ctx
, table
);