5 #include <isl_stream.h>
6 #include <isl_obj_list.h>
7 #include <barvinok/barvinok.h>
8 #include <bound_common.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
;
18 struct isl_arg_choice iscc_format
[] = {
19 {"isl", ISL_FORMAT_ISL
},
20 {"omega", ISL_FORMAT_OMEGA
},
21 {"polylib", ISL_FORMAT_POLYLIB
},
22 {"latex", ISL_FORMAT_LATEX
},
28 struct isl_options
*isl
;
32 struct isl_arg iscc_options_arg
[] = {
33 ISL_ARG_CHILD(struct iscc_options
, isl
, "isl", isl_options_arg
)
34 ISL_ARG_CHOICE(struct iscc_options
, format
, 0, "format", \
35 iscc_format
, ISL_FORMAT_ISL
)
39 ISL_ARG_DEF(iscc_options
, struct iscc_options
, iscc_options_arg
)
41 static void *isl_obj_bool_copy(void *v
)
46 static void isl_obj_bool_free(void *v
)
50 static __isl_give isl_printer
*isl_obj_bool_print(__isl_take isl_printer
*p
,
53 if (v
== &isl_bool_true
)
54 return isl_printer_print_str(p
, "True");
55 else if (v
== &isl_bool_false
)
56 return isl_printer_print_str(p
, "False");
58 return isl_printer_print_str(p
, "Error");
61 static void *isl_obj_bool_add(void *v1
, void *v2
)
66 struct isl_obj_vtable isl_obj_bool_vtable
= {
72 #define isl_obj_bool (&isl_obj_bool_vtable)
74 int *isl_bool_from_int(int res
)
76 return res
< 0 ? &isl_bool_error
: res
? &isl_bool_true
: &isl_bool_false
;
79 int *map_is_equal(__isl_take isl_map
*map1
, __isl_take isl_map
*map2
)
81 int res
= isl_map_is_equal(map1
, map2
);
84 return isl_bool_from_int(res
);
86 int *set_is_equal(__isl_take isl_set
*set1
, __isl_take isl_set
*set2
)
88 return map_is_equal((isl_map
*)set1
, (isl_map
*)set2
);
91 int *map_is_subset(__isl_take isl_map
*map1
, __isl_take isl_map
*map2
)
93 int res
= isl_map_is_subset(map1
, map2
);
96 return isl_bool_from_int(res
);
98 int *set_is_subset(__isl_take isl_set
*set1
, __isl_take isl_set
*set2
)
100 return map_is_subset((isl_map
*)set1
, (isl_map
*)set2
);
103 int *map_is_strict_subset(__isl_take isl_map
*map1
, __isl_take isl_map
*map2
)
105 int res
= isl_map_is_strict_subset(map1
, map2
);
108 return isl_bool_from_int(res
);
110 int *set_is_strict_subset(__isl_take isl_set
*set1
, __isl_take isl_set
*set2
)
112 return map_is_strict_subset((isl_map
*)set1
, (isl_map
*)set2
);
115 int *map_is_superset(__isl_take isl_map
*map1
, __isl_take isl_map
*map2
)
117 return map_is_subset(map2
, map1
);
119 int *set_is_superset(__isl_take isl_set
*set1
, __isl_take isl_set
*set2
)
121 return set_is_subset(set2
, set1
);
124 int *map_is_strict_superset(__isl_take isl_map
*map1
, __isl_take isl_map
*map2
)
126 return map_is_strict_subset(map2
, map1
);
128 int *set_is_strict_superset(__isl_take isl_set
*set1
, __isl_take isl_set
*set2
)
130 return set_is_strict_subset(set2
, set1
);
133 extern struct isl_obj_vtable isl_obj_list_vtable
;
134 #define isl_obj_list (&isl_obj_list_vtable)
136 typedef void *(*isc_bin_op_fn
)(void *lhs
, void *rhs
);
138 enum isl_token_type op
;
144 struct isc_named_bin_op
{
146 struct isc_bin_op op
;
150 isl_pw_qpolynomial
*pwqp
;
151 isl_pw_qpolynomial
*res
;
154 static int eval_at(__isl_take isl_point
*pnt
, void *user
)
156 struct iscc_at
*at
= (struct iscc_at
*) user
;
160 set
= isl_set_from_point(isl_point_copy(pnt
));
161 qp
= isl_pw_qpolynomial_eval(isl_pw_qpolynomial_copy(at
->pwqp
), pnt
);
163 at
->res
= isl_pw_qpolynomial_add_disjoint(at
->res
,
164 isl_pw_qpolynomial_alloc(set
, qp
));
169 __isl_give isl_pw_qpolynomial
*isl_pw_qpolynomial_at(
170 __isl_take isl_pw_qpolynomial
*pwqp
, __isl_take isl_set
*set
)
175 at
.res
= isl_pw_qpolynomial_zero(isl_set_get_dim(set
));
177 isl_set_foreach_point(set
, eval_at
, &at
);
179 isl_pw_qpolynomial_free(pwqp
);
185 struct iscc_fold_at
{
186 isl_pw_qpolynomial_fold
*pwf
;
187 isl_pw_qpolynomial
*res
;
190 static int eval_fold_at(__isl_take isl_point
*pnt
, void *user
)
192 struct iscc_fold_at
*at
= (struct iscc_fold_at
*) user
;
196 set
= isl_set_from_point(isl_point_copy(pnt
));
197 qp
= isl_pw_qpolynomial_fold_eval(isl_pw_qpolynomial_fold_copy(at
->pwf
),
200 at
->res
= isl_pw_qpolynomial_add_disjoint(at
->res
,
201 isl_pw_qpolynomial_alloc(set
, qp
));
206 __isl_give isl_pw_qpolynomial
*isl_pw_qpolynomial_fold_at(
207 __isl_take isl_pw_qpolynomial_fold
*pwf
, __isl_take isl_set
*set
)
209 struct iscc_fold_at at
;
212 at
.res
= isl_pw_qpolynomial_zero(isl_set_get_dim(set
));
214 isl_set_foreach_point(set
, eval_fold_at
, &at
);
216 isl_pw_qpolynomial_fold_free(pwf
);
222 struct isc_bin_op bin_ops
[] = {
223 { '+', isl_obj_set
, isl_obj_set
,
225 (isc_bin_op_fn
) &isl_set_union
},
226 { '+', isl_obj_map
, isl_obj_map
,
228 (isc_bin_op_fn
) &isl_map_union
},
229 { '-', isl_obj_set
, isl_obj_set
,
231 (isc_bin_op_fn
) &isl_set_subtract
},
232 { '-', isl_obj_map
, isl_obj_map
,
234 (isc_bin_op_fn
) &isl_map_subtract
},
235 { '*', isl_obj_set
, isl_obj_set
,
237 (isc_bin_op_fn
) &isl_set_intersect
},
238 { '*', isl_obj_map
, isl_obj_map
,
240 (isc_bin_op_fn
) &isl_map_intersect
},
241 { '*', isl_obj_map
, isl_obj_set
,
243 (isc_bin_op_fn
) &isl_map_intersect_domain
},
244 { '.', isl_obj_map
, isl_obj_map
,
246 (isc_bin_op_fn
) &isl_map_apply_range
},
247 { ISL_TOKEN_TO
, isl_obj_set
, isl_obj_set
, isl_obj_map
,
248 (isc_bin_op_fn
) &isl_map_from_domain_and_range
},
249 { '=', isl_obj_set
, isl_obj_set
, isl_obj_bool
,
250 (isc_bin_op_fn
) &set_is_equal
},
251 { '=', isl_obj_map
, isl_obj_map
, isl_obj_bool
,
252 (isc_bin_op_fn
) &map_is_equal
},
253 { ISL_TOKEN_LE
, isl_obj_set
, isl_obj_set
, isl_obj_bool
,
254 (isc_bin_op_fn
) &set_is_subset
},
255 { ISL_TOKEN_LE
, isl_obj_map
, isl_obj_map
, isl_obj_bool
,
256 (isc_bin_op_fn
) &map_is_subset
},
257 { ISL_TOKEN_LT
, isl_obj_set
, isl_obj_set
, isl_obj_bool
,
258 (isc_bin_op_fn
) &set_is_strict_subset
},
259 { ISL_TOKEN_LT
, isl_obj_map
, isl_obj_map
, isl_obj_bool
,
260 (isc_bin_op_fn
) &map_is_strict_subset
},
261 { ISL_TOKEN_GE
, isl_obj_set
, isl_obj_set
, isl_obj_bool
,
262 (isc_bin_op_fn
) &set_is_superset
},
263 { ISL_TOKEN_GE
, isl_obj_map
, isl_obj_map
, isl_obj_bool
,
264 (isc_bin_op_fn
) &map_is_superset
},
265 { ISL_TOKEN_GT
, isl_obj_set
, isl_obj_set
, isl_obj_bool
,
266 (isc_bin_op_fn
) &set_is_strict_superset
},
267 { ISL_TOKEN_GT
, isl_obj_map
, isl_obj_map
, isl_obj_bool
,
268 (isc_bin_op_fn
) &map_is_strict_superset
},
269 { '+', isl_obj_pw_qpolynomial
, isl_obj_pw_qpolynomial
,
270 isl_obj_pw_qpolynomial
,
271 (isc_bin_op_fn
) &isl_pw_qpolynomial_add
},
272 { '-', isl_obj_pw_qpolynomial
, isl_obj_pw_qpolynomial
,
273 isl_obj_pw_qpolynomial
,
274 (isc_bin_op_fn
) &isl_pw_qpolynomial_sub
},
275 { '*', isl_obj_pw_qpolynomial
, isl_obj_pw_qpolynomial
,
276 isl_obj_pw_qpolynomial
,
277 (isc_bin_op_fn
) &isl_pw_qpolynomial_mul
},
278 { '*', isl_obj_pw_qpolynomial
, isl_obj_set
,
279 isl_obj_pw_qpolynomial
,
280 (isc_bin_op_fn
) &isl_pw_qpolynomial_intersect_domain
},
281 { '*', isl_obj_pw_qpolynomial_fold
, isl_obj_set
,
282 isl_obj_pw_qpolynomial_fold
,
283 (isc_bin_op_fn
) &isl_pw_qpolynomial_fold_intersect_domain
},
284 { '@', isl_obj_pw_qpolynomial
, isl_obj_set
,
285 isl_obj_pw_qpolynomial
,
286 (isc_bin_op_fn
) &isl_pw_qpolynomial_at
},
287 { '@', isl_obj_pw_qpolynomial_fold
, isl_obj_set
,
288 isl_obj_pw_qpolynomial
,
289 (isc_bin_op_fn
) &isl_pw_qpolynomial_fold_at
},
290 { '%', isl_obj_set
, isl_obj_set
,
292 (isc_bin_op_fn
) &isl_set_gist
},
293 { '%', isl_obj_map
, isl_obj_map
,
295 (isc_bin_op_fn
) &isl_map_gist
},
296 { '%', isl_obj_pw_qpolynomial
, isl_obj_set
,
297 isl_obj_pw_qpolynomial
,
298 (isc_bin_op_fn
) &isl_pw_qpolynomial_gist
},
299 { '%', isl_obj_pw_qpolynomial_fold
, isl_obj_set
,
300 isl_obj_pw_qpolynomial_fold
,
301 (isc_bin_op_fn
) &isl_pw_qpolynomial_fold_gist
},
304 struct isc_named_bin_op named_bin_ops
[] = {
305 { "cross", { -1, isl_obj_set
, isl_obj_set
, isl_obj_set
,
306 (isc_bin_op_fn
) &isl_set_product
} },
307 { "cross", { -1, isl_obj_map
, isl_obj_map
, isl_obj_map
,
308 (isc_bin_op_fn
) &isl_map_product
} },
312 __isl_give isl_set
*set_sample(__isl_take isl_set
*set
)
314 return isl_set_from_basic_set(isl_set_sample(set
));
317 __isl_give isl_map
*map_sample(__isl_take isl_map
*map
)
319 return isl_map_from_basic_map(isl_map_sample(map
));
322 static __isl_give isl_set
*set_affine_hull(__isl_take isl_set
*set
)
324 return isl_set_from_basic_set(isl_set_affine_hull(set
));
327 static __isl_give isl_map
*map_affine_hull(__isl_take isl_map
*map
)
329 return isl_map_from_basic_map(isl_map_affine_hull(map
));
332 static __isl_give isl_pw_qpolynomial_fold
*pw_qpolynomial_upper_bound(
333 __isl_take isl_pw_qpolynomial
*pwqp
)
336 return isl_pw_qpolynomial_bound(pwqp
, isl_fold_max
, BV_BOUND_BERNSTEIN
);
338 return isl_pw_qpolynomial_bound(pwqp
, isl_fold_max
, BV_BOUND_RANGE
);
342 typedef void *(*isc_un_op_fn
)(void *arg
);
344 enum isl_token_type op
;
349 struct isc_named_un_op
{
353 struct isc_named_un_op named_un_ops
[] = {
354 {"aff", { -1, isl_obj_map
, isl_obj_map
,
355 (isc_un_op_fn
) &map_affine_hull
} },
356 {"aff", { -1, isl_obj_set
, isl_obj_set
,
357 (isc_un_op_fn
) &set_affine_hull
} },
358 {"card", { -1, isl_obj_set
, isl_obj_pw_qpolynomial
,
359 (isc_un_op_fn
) &isl_set_card
} },
360 {"card", { -1, isl_obj_map
, isl_obj_pw_qpolynomial
,
361 (isc_un_op_fn
) &isl_map_card
} },
362 {"coalesce", { -1, isl_obj_set
, isl_obj_set
,
363 (isc_un_op_fn
) &isl_set_coalesce
} },
364 {"coalesce", { -1, isl_obj_map
, isl_obj_map
,
365 (isc_un_op_fn
) &isl_map_coalesce
} },
366 {"coalesce", { -1, isl_obj_pw_qpolynomial
, isl_obj_pw_qpolynomial
,
367 (isc_un_op_fn
) &isl_pw_qpolynomial_coalesce
} },
368 {"coalesce", { -1, isl_obj_pw_qpolynomial_fold
,
369 isl_obj_pw_qpolynomial_fold
,
370 (isc_un_op_fn
) &isl_pw_qpolynomial_fold_coalesce
} },
371 {"deltas", { -1, isl_obj_map
, isl_obj_set
,
372 (isc_un_op_fn
) &isl_map_deltas
} },
373 {"dom", { -1, isl_obj_map
, isl_obj_set
,
374 (isc_un_op_fn
) &isl_map_domain
} },
375 {"dom", { -1, isl_obj_pw_qpolynomial
, isl_obj_set
,
376 (isc_un_op_fn
) &isl_pw_qpolynomial_domain
} },
377 {"dom", { -1, isl_obj_pw_qpolynomial_fold
, isl_obj_set
,
378 (isc_un_op_fn
) &isl_pw_qpolynomial_fold_domain
} },
379 {"ran", { -1, isl_obj_map
, isl_obj_set
,
380 (isc_un_op_fn
) &isl_map_range
} },
381 {"lexmin", { -1, isl_obj_map
, isl_obj_map
,
382 (isc_un_op_fn
) &isl_map_lexmin
} },
383 {"lexmax", { -1, isl_obj_map
, isl_obj_map
,
384 (isc_un_op_fn
) &isl_map_lexmax
} },
385 {"lexmin", { -1, isl_obj_set
, isl_obj_set
,
386 (isc_un_op_fn
) &isl_set_lexmin
} },
387 {"lexmax", { -1, isl_obj_set
, isl_obj_set
,
388 (isc_un_op_fn
) &isl_set_lexmax
} },
389 {"sample", { -1, isl_obj_set
, isl_obj_set
,
390 (isc_un_op_fn
) &set_sample
} },
391 {"sample", { -1, isl_obj_map
, isl_obj_map
,
392 (isc_un_op_fn
) &map_sample
} },
393 {"sum", { -1, isl_obj_pw_qpolynomial
, isl_obj_pw_qpolynomial
,
394 (isc_un_op_fn
) &isl_pw_qpolynomial_sum
} },
395 {"ub", { -1, isl_obj_pw_qpolynomial
, isl_obj_pw_qpolynomial_fold
,
396 (isc_un_op_fn
) &pw_qpolynomial_upper_bound
} },
400 struct isl_named_obj
{
405 static void free_obj(struct isl_obj obj
)
407 obj
.type
->free(obj
.v
);
410 static int same_name(const void *entry
, const void *val
)
412 const struct isl_named_obj
*named
= (const struct isl_named_obj
*)entry
;
414 return !strcmp(named
->name
, val
);
417 static int do_assign(struct isl_ctx
*ctx
, struct isl_hash_table
*table
,
418 char *name
, struct isl_obj obj
)
420 struct isl_hash_table_entry
*entry
;
422 struct isl_named_obj
*named
;
424 name_hash
= isl_hash_string(isl_hash_init(), name
);
425 entry
= isl_hash_table_find(ctx
, table
, name_hash
, same_name
, name
, 1);
430 free_obj(named
->obj
);
433 named
= isl_alloc_type(ctx
, struct isl_named_obj
);
448 static struct isl_obj
stored_obj(struct isl_ctx
*ctx
,
449 struct isl_hash_table
*table
, char *name
)
451 struct isl_obj obj
= { isl_obj_none
, NULL
};
452 struct isl_hash_table_entry
*entry
;
455 name_hash
= isl_hash_string(isl_hash_init(), name
);
456 entry
= isl_hash_table_find(ctx
, table
, name_hash
, same_name
, name
, 0);
458 struct isl_named_obj
*named
;
464 obj
.v
= obj
.type
->copy(obj
.v
);
468 static struct isc_bin_op
*read_bin_op_if_available(struct isl_stream
*s
,
472 struct isl_token
*tok
;
474 tok
= isl_stream_next_token(s
);
481 if (bin_ops
[i
].op
!= tok
->type
)
483 if (bin_ops
[i
].lhs
!= lhs
)
491 if (!named_bin_ops
[i
].name
)
493 if (named_bin_ops
[i
].op
.op
!= tok
->type
)
495 if (named_bin_ops
[i
].op
.lhs
!= lhs
)
499 return &named_bin_ops
[i
].op
;
502 isl_stream_push_token(s
, tok
);
507 static struct isc_un_op
*read_prefix_un_op_if_available(struct isl_stream
*s
)
510 struct isl_token
*tok
;
512 tok
= isl_stream_next_token(s
);
517 if (!named_un_ops
[i
].name
)
519 if (named_un_ops
[i
].op
.op
!= tok
->type
)
523 return &named_un_ops
[i
].op
;
526 isl_stream_push_token(s
, tok
);
531 static struct isc_un_op
*find_matching_un_op(struct isc_un_op
*like
,
537 if (!named_un_ops
[i
].name
)
539 if (named_un_ops
[i
].op
.op
!= like
->op
)
541 if (named_un_ops
[i
].op
.arg
!= arg
)
544 return &named_un_ops
[i
].op
;
550 static int is_assign(struct isl_stream
*s
)
552 struct isl_token
*tok
;
553 struct isl_token
*tok2
;
556 tok
= isl_stream_next_token(s
);
559 if (tok
->type
!= ISL_TOKEN_IDENT
) {
560 isl_stream_push_token(s
, tok
);
564 tok2
= isl_stream_next_token(s
);
566 isl_stream_push_token(s
, tok
);
569 assign
= tok2
->type
== ISL_TOKEN_DEF
;
570 isl_stream_push_token(s
, tok2
);
571 isl_stream_push_token(s
, tok
);
576 static struct isl_obj
read_obj(struct isl_stream
*s
,
577 struct isl_hash_table
*table
);
578 static struct isl_obj
read_expr(struct isl_stream
*s
,
579 struct isl_hash_table
*table
);
581 static struct isl_obj
read_un_op_expr(struct isl_stream
*s
,
582 struct isl_hash_table
*table
, struct isc_un_op
*op
)
584 struct isl_obj obj
= { isl_obj_none
, NULL
};
586 obj
= read_obj(s
, table
);
588 op
= find_matching_un_op(op
, obj
.type
);
590 isl_assert(s
->ctx
, op
, goto error
);
591 obj
.v
= op
->fn(obj
.v
);
597 obj
.type
= isl_obj_none
;
602 static struct isl_obj
transitive_closure(struct isl_ctx
*ctx
, struct isl_obj obj
)
604 struct isl_list
*list
;
607 isl_assert(ctx
, obj
.type
== isl_obj_map
, goto error
);
608 list
= isl_list_alloc(ctx
, 2);
612 list
->obj
[0].type
= isl_obj_map
;
613 list
->obj
[0].v
= isl_map_transitive_closure(obj
.v
, &exact
);
614 list
->obj
[1].type
= isl_obj_bool
;
615 list
->obj
[1].v
= exact
? &isl_bool_true
: &isl_bool_false
;
617 obj
.type
= isl_obj_list
;
618 if (exact
< 0 || !list
->obj
[0].v
)
624 obj
.type
= isl_obj_none
;
629 static struct isl_obj
obj_at_index(struct isl_stream
*s
, struct isl_obj obj
)
631 struct isl_list
*list
= obj
.v
;
632 struct isl_token
*tok
;
635 tok
= isl_stream_next_token(s
);
636 if (!tok
|| tok
->type
!= ISL_TOKEN_VALUE
) {
637 isl_stream_error(s
, tok
, "expecting index");
639 isl_stream_push_token(s
, tok
);
642 i
= isl_int_get_si(tok
->u
.v
);
644 isl_assert(s
, i
< list
->n
, goto error
);
645 if (isl_stream_eat(s
, ']'))
649 obj
.v
= obj
.type
->copy(obj
.v
);
656 obj
.type
= isl_obj_none
;
661 static struct isl_obj
apply(struct isl_stream
*s
, __isl_take isl_map
*map
,
662 struct isl_hash_table
*table
)
666 obj
= read_expr(s
, table
);
667 isl_assert(s
->ctx
, obj
.type
== isl_obj_set
|| obj
.type
== isl_obj_map
,
670 if (obj
.type
== isl_obj_set
) {
671 obj
.v
= isl_set_apply(obj
.v
, map
);
673 obj
.v
= isl_map_apply_range(obj
.v
, map
);
677 if (isl_stream_eat(s
, ')'))
683 obj
.type
= isl_obj_none
;
688 static struct isl_obj
power(struct isl_stream
*s
, struct isl_obj obj
)
690 struct isl_token
*tok
;
692 if (isl_stream_eat_if_available(s
, '+'))
693 return transitive_closure(s
->ctx
, obj
);
695 tok
= isl_stream_next_token(s
);
696 if (!tok
|| tok
->type
!= ISL_TOKEN_VALUE
|| isl_int_cmp_si(tok
->u
.v
, -1)) {
697 isl_stream_error(s
, tok
, "expecting -1");
699 isl_stream_push_token(s
, tok
);
703 isl_assert(s
->ctx
, obj
.type
== isl_obj_map
, goto error
);
705 obj
.v
= isl_map_reverse(obj
.v
);
712 obj
.type
= isl_obj_none
;
717 static struct isl_obj
read_from_file(struct isl_stream
*s
)
720 struct isl_token
*tok
;
721 struct isl_stream
*s_file
;
724 tok
= isl_stream_next_token(s
);
725 if (!tok
|| tok
->type
!= ISL_TOKEN_STRING
) {
726 isl_stream_error(s
, tok
, "expecting filename");
731 file
= fopen(tok
->u
.s
, "r");
733 isl_assert(s
->ctx
, file
, goto error
);
735 s_file
= isl_stream_new_file(s
->ctx
, file
);
741 obj
= isl_stream_read_obj(s_file
);
743 isl_stream_free(s_file
);
748 obj
.type
= isl_obj_none
;
753 static struct isl_obj
read_obj(struct isl_stream
*s
,
754 struct isl_hash_table
*table
)
756 struct isl_obj obj
= { isl_obj_none
, NULL
};
758 struct isc_un_op
*op
= NULL
;
760 if (isl_stream_eat_if_available(s
, '(')) {
761 obj
= read_expr(s
, table
);
762 if (isl_stream_eat(s
, ')'))
765 op
= read_prefix_un_op_if_available(s
);
767 return read_un_op_expr(s
, table
, op
);
769 if (isl_stream_eat_if_available(s
, read_op
))
770 return read_from_file(s
);
772 name
= isl_stream_read_ident_if_available(s
);
774 obj
= stored_obj(s
->ctx
, table
, name
);
776 obj
= isl_stream_read_obj(s
);
781 if (isl_stream_eat_if_available(s
, '^'))
783 else if (obj
.type
== isl_obj_list
&& isl_stream_eat_if_available(s
, '['))
784 obj
= obj_at_index(s
, obj
);
785 else if (obj
.type
== isl_obj_map
&& isl_stream_eat_if_available(s
, '('))
786 obj
= apply(s
, obj
.v
, table
);
791 obj
.type
= isl_obj_none
;
796 static struct isc_bin_op
*find_matching_bin_op(struct isc_bin_op
*like
,
797 isl_obj_type lhs
, isl_obj_type rhs
)
804 if (bin_ops
[i
].op
!= like
->op
)
806 if (bin_ops
[i
].lhs
!= lhs
)
808 if (bin_ops
[i
].rhs
!= rhs
)
815 if (!named_bin_ops
[i
].name
)
817 if (named_bin_ops
[i
].op
.op
!= like
->op
)
819 if (named_bin_ops
[i
].op
.lhs
!= lhs
)
821 if (named_bin_ops
[i
].op
.rhs
!= rhs
)
824 return &named_bin_ops
[i
].op
;
830 static struct isl_obj
read_expr(struct isl_stream
*s
,
831 struct isl_hash_table
*table
)
833 struct isl_obj obj
= { isl_obj_none
, NULL
};
834 struct isl_obj right_obj
= { isl_obj_none
, NULL
};
836 obj
= read_obj(s
, table
);
838 struct isc_bin_op
*op
= NULL
;
840 op
= read_bin_op_if_available(s
, obj
.type
);
844 right_obj
= read_obj(s
, table
);
846 op
= find_matching_bin_op(op
, obj
.type
, right_obj
.type
);
848 isl_assert(s
->ctx
, op
, goto error
);
849 obj
.v
= op
->fn(obj
.v
, right_obj
.v
);
857 obj
.type
= isl_obj_none
;
862 static __isl_give isl_printer
*read_line(struct isl_stream
*s
,
863 struct isl_hash_table
*table
, __isl_take isl_printer
*p
)
865 struct isl_obj obj
= { isl_obj_none
, NULL
};
868 struct isc_bin_op
*op
= NULL
;
872 if (isl_stream_is_empty(s
))
875 assign
= is_assign(s
);
877 lhs
= isl_stream_read_ident_if_available(s
);
878 if (isl_stream_eat(s
, ISL_TOKEN_DEF
))
882 obj
= read_expr(s
, table
);
883 if (obj
.type
== isl_obj_none
|| obj
.v
== NULL
)
885 if (isl_stream_eat(s
, ';'))
889 if (do_assign(s
->ctx
, table
, lhs
, obj
))
892 p
= obj
.type
->print(p
, obj
.v
);
893 p
= isl_printer_end_line(p
);
904 int free_cb(void *entry
)
906 struct isl_named_obj
*named
= entry
;
908 free_obj(named
->obj
);
915 static void register_named_ops(struct isl_stream
*s
)
919 read_op
= isl_stream_register_keyword(s
, "read");
920 assert(read_op
!= ISL_TOKEN_ERROR
);
923 if (!named_un_ops
[i
].name
)
925 named_un_ops
[i
].op
.op
= isl_stream_register_keyword(s
,
926 named_un_ops
[i
].name
);
927 assert(named_un_ops
[i
].op
.op
!= ISL_TOKEN_ERROR
);
931 if (!named_bin_ops
[i
].name
)
933 named_bin_ops
[i
].op
.op
= isl_stream_register_keyword(s
,
934 named_bin_ops
[i
].name
);
935 assert(named_bin_ops
[i
].op
.op
!= ISL_TOKEN_ERROR
);
939 int main(int argc
, char **argv
)
942 struct isl_stream
*s
;
943 struct isl_hash_table
*table
;
944 struct iscc_options
*options
;
947 options
= iscc_options_new_with_defaults();
949 argc
= iscc_options_parse(options
, argc
, argv
, ISL_ARG_ALL
);
951 ctx
= isl_ctx_alloc_with_options(options
->isl
);
953 s
= isl_stream_new_file(ctx
, stdin
);
955 table
= isl_hash_table_alloc(ctx
, 10);
957 p
= isl_printer_to_file(ctx
, stdout
);
958 p
= isl_printer_set_output_format(p
, options
->format
);
961 register_named_ops(s
);
964 p
= read_line(s
, table
, p
);
968 isl_hash_table_foreach(ctx
, table
, free_cb
);
969 isl_hash_table_free(ctx
, table
);