298 else |
298 else |
299 [KK.TupleSet [], upper_bound_for_rep R]) |
299 [KK.TupleSet [], upper_bound_for_rep R]) |
300 | bound_for_plain_rel _ _ u = |
300 | bound_for_plain_rel _ _ u = |
301 raise NUT ("Nitpick_Kodkod.bound_for_plain_rel", [u]) |
301 raise NUT ("Nitpick_Kodkod.bound_for_plain_rel", [u]) |
302 |
302 |
|
303 fun is_datatype_nat_like ({typ, constrs, ...} : datatype_spec) = |
|
304 case constrs |> map (snd o #const) |> List.partition is_fun_type of |
|
305 ([Type (_, Ts1)], [T2]) => forall (curry (op =) typ) (T2 :: Ts1) |
|
306 | _ => false |
|
307 |
303 fun bound_for_sel_rel ctxt debug need_vals dtypes |
308 fun bound_for_sel_rel ctxt debug need_vals dtypes |
304 (FreeRel (x, T as Type (@{type_name fun}, [T1, T2]), |
309 (FreeRel (x, T as Type (@{type_name fun}, [T1, T2]), |
305 R as Func (Atom (_, j0), R2), nick)) = |
310 R as Func (Atom (_, j0), R2), nick)) = |
306 let |
311 let |
307 val constr_s = original_name nick |
312 val constr_s = original_name nick |
342 if T1 = T2 andalso epsilon > delta andalso |
347 if T1 = T2 andalso epsilon > delta andalso |
343 is_datatype_acyclic dtype then |
348 is_datatype_acyclic dtype then |
344 index_seq delta (epsilon - delta) |
349 index_seq delta (epsilon - delta) |
345 |> map (fn j => |
350 |> map (fn j => |
346 KK.TupleProduct (KK.TupleSet [KK.Tuple [j + j0]], |
351 KK.TupleProduct (KK.TupleSet [KK.Tuple [j + j0]], |
347 KK.TupleAtomSeq (j, j0))) |
352 if is_datatype_nat_like dtype then |
|
353 KK.TupleAtomSeq (1, j + j0 - 1) |
|
354 else |
|
355 KK.TupleAtomSeq (j, j0))) |
348 |> foldl1 KK.TupleUnion |
356 |> foldl1 KK.TupleUnion |
349 else |
357 else |
350 KK.TupleProduct (upper_bound_ts (), upper_bound_for_rep R2)] |
358 KK.TupleProduct (upper_bound_ts (), upper_bound_for_rep R2)] |
351 end) |
359 end) |
352 end |
360 end |