300 [Pretty.brk 1, str "| _ => DSeq.empty)"] |
300 [Pretty.brk 1, str "| _ => DSeq.empty)"] |
301 else [str ")"]))) |
301 else [str ")"]))) |
302 end; |
302 end; |
303 |
303 |
304 fun modename module s (iss, is) gr = |
304 fun modename module s (iss, is) gr = |
305 let val (gr', id) = if s = "op =" then (gr, ("", "equal")) |
305 let val (id, gr') = if s = @{const_name "op ="} then (("", "equal"), gr) |
306 else mk_const_id module s gr |
306 else mk_const_id module s gr |
307 in (gr', space_implode "__" |
307 in (space_implode "__" |
308 (mk_qual_id module id :: |
308 (mk_qual_id module id :: |
309 map (space_implode "_" o map string_of_int) (List.mapPartial I iss @ [is]))) |
309 map (space_implode "_" o map string_of_int) (List.mapPartial I iss @ [is])), gr') |
310 end; |
310 end; |
311 |
311 |
312 fun mk_funcomp brack s k p = (if brack then parens else I) |
312 fun mk_funcomp brack s k p = (if brack then parens else I) |
313 (Pretty.block [Pretty.block ((if k = 0 then [] else [str "("]) @ |
313 (Pretty.block [Pretty.block ((if k = 0 then [] else [str "("]) @ |
314 separate (Pretty.brk 1) (str s :: replicate k (str "|> ???")) @ |
314 separate (Pretty.brk 1) (str s :: replicate k (str "|> ???")) @ |
315 (if k = 0 then [] else [str ")"])), Pretty.brk 1, p]); |
315 (if k = 0 then [] else [str ")"])), Pretty.brk 1, p]); |
316 |
316 |
317 fun compile_expr thy defs dep module brack modes (gr, (NONE, t)) = |
317 fun compile_expr thy defs dep module brack modes (NONE, t) gr = |
318 apsnd single (invoke_codegen thy defs dep module brack (gr, t)) |
318 apfst single (invoke_codegen thy defs dep module brack t gr) |
319 | compile_expr _ _ _ _ _ _ (gr, (SOME _, Var ((name, _), _))) = |
319 | compile_expr _ _ _ _ _ _ (SOME _, Var ((name, _), _)) gr = |
320 (gr, [str name]) |
320 ([str name], gr) |
321 | compile_expr thy defs dep module brack modes (gr, (SOME (Mode (mode, _, ms)), t)) = |
321 | compile_expr thy defs dep module brack modes (SOME (Mode (mode, _, ms)), t) gr = |
322 (case strip_comb t of |
322 (case strip_comb t of |
323 (Const (name, _), args) => |
323 (Const (name, _), args) => |
324 if name = "op =" orelse AList.defined op = modes name then |
324 if name = @{const_name "op ="} orelse AList.defined op = modes name then |
325 let |
325 let |
326 val (args1, args2) = chop (length ms) args; |
326 val (args1, args2) = chop (length ms) args; |
327 val (gr', (ps, mode_id)) = foldl_map |
327 val ((ps, mode_id), gr') = gr |> fold_map |
328 (compile_expr thy defs dep module true modes) (gr, ms ~~ args1) |>>> |
328 (compile_expr thy defs dep module true modes) (ms ~~ args1) |
329 modename module name mode; |
329 ||>> modename module name mode; |
330 val (gr'', ps') = (case mode of |
330 val (ps', gr'') = (case mode of |
331 ([], []) => (gr', [str "()"]) |
331 ([], []) => ([str "()"], gr') |
332 | _ => foldl_map |
332 | _ => fold_map |
333 (invoke_codegen thy defs dep module true) (gr', args2)) |
333 (invoke_codegen thy defs dep module true) args2 gr') |
334 in (gr', (if brack andalso not (null ps andalso null ps') then |
334 in ((if brack andalso not (null ps andalso null ps') then |
335 single o parens o Pretty.block else I) |
335 single o parens o Pretty.block else I) |
336 (List.concat (separate [Pretty.brk 1] |
336 (List.concat (separate [Pretty.brk 1] |
337 ([str mode_id] :: ps @ map single ps')))) |
337 ([str mode_id] :: ps @ map single ps'))), gr') |
338 end |
338 end |
339 else apsnd (single o mk_funcomp brack "??" (length (binder_types (fastype_of t)))) |
339 else apfst (single o mk_funcomp brack "??" (length (binder_types (fastype_of t)))) |
340 (invoke_codegen thy defs dep module true (gr, t)) |
340 (invoke_codegen thy defs dep module true t gr) |
341 | _ => apsnd (single o mk_funcomp brack "??" (length (binder_types (fastype_of t)))) |
341 | _ => apfst (single o mk_funcomp brack "??" (length (binder_types (fastype_of t)))) |
342 (invoke_codegen thy defs dep module true (gr, t))); |
342 (invoke_codegen thy defs dep module true t gr)); |
343 |
343 |
344 fun compile_clause thy defs gr dep module all_vs arg_vs modes (iss, is) (ts, ps) inp = |
344 fun compile_clause thy defs dep module all_vs arg_vs modes (iss, is) (ts, ps) inp gr = |
345 let |
345 let |
346 val modes' = modes @ List.mapPartial |
346 val modes' = modes @ List.mapPartial |
347 (fn (_, NONE) => NONE | (v, SOME js) => SOME (v, [([], js)])) |
347 (fn (_, NONE) => NONE | (v, SOME js) => SOME (v, [([], js)])) |
348 (arg_vs ~~ iss); |
348 (arg_vs ~~ iss); |
349 |
349 |
350 fun check_constrt ((names, eqs), t) = |
350 fun check_constrt ((names, eqs), t) = |
351 if is_constrt thy t then ((names, eqs), t) else |
351 if is_constrt thy t then ((names, eqs), t) else |
352 let val s = Name.variant names "x"; |
352 let val s = Name.variant names "x"; |
353 in ((s::names, (s, t)::eqs), Var ((s, 0), fastype_of t)) end; |
353 in ((s::names, (s, t)::eqs), Var ((s, 0), fastype_of t)) end; |
354 |
354 |
355 fun compile_eq (gr, (s, t)) = |
355 fun compile_eq (s, t) gr = |
356 apsnd (Pretty.block o cons (str (s ^ " = ")) o single) |
356 apfst (Pretty.block o cons (str (s ^ " = ")) o single) |
357 (invoke_codegen thy defs dep module false (gr, t)); |
357 (invoke_codegen thy defs dep module false t gr); |
358 |
358 |
359 val (in_ts, out_ts) = get_args is 1 ts; |
359 val (in_ts, out_ts) = get_args is 1 ts; |
360 val ((all_vs', eqs), in_ts') = |
360 val ((all_vs', eqs), in_ts') = |
361 foldl_map check_constrt ((all_vs, []), in_ts); |
361 foldl_map check_constrt ((all_vs, []), in_ts); |
362 |
362 |
363 fun compile_prems out_ts' vs names gr [] = |
363 fun compile_prems out_ts' vs names [] gr = |
364 let |
364 let |
365 val (gr2, out_ps) = foldl_map |
365 val (out_ps, gr2) = fold_map |
366 (invoke_codegen thy defs dep module false) (gr, out_ts); |
366 (invoke_codegen thy defs dep module false) out_ts gr; |
367 val (gr3, eq_ps) = foldl_map compile_eq (gr2, eqs); |
367 val (eq_ps, gr3) = fold_map compile_eq eqs gr2; |
368 val ((names', eqs'), out_ts'') = |
368 val ((names', eqs'), out_ts'') = |
369 foldl_map check_constrt ((names, []), out_ts'); |
369 foldl_map check_constrt ((names, []), out_ts'); |
370 val (nvs, out_ts''') = foldl_map distinct_v |
370 val (nvs, out_ts''') = foldl_map distinct_v |
371 ((names', map (fn x => (x, [x])) vs), out_ts''); |
371 ((names', map (fn x => (x, [x])) vs), out_ts''); |
372 val (gr4, out_ps') = foldl_map |
372 val (out_ps', gr4) = fold_map |
373 (invoke_codegen thy defs dep module false) (gr3, out_ts'''); |
373 (invoke_codegen thy defs dep module false) (out_ts''') gr3; |
374 val (gr5, eq_ps') = foldl_map compile_eq (gr4, eqs') |
374 val (eq_ps', gr5) = fold_map compile_eq eqs' gr4; |
375 in |
375 in |
376 (gr5, compile_match (snd nvs) (eq_ps @ eq_ps') out_ps' |
376 (compile_match (snd nvs) (eq_ps @ eq_ps') out_ps' |
377 (Pretty.block [str "DSeq.single", Pretty.brk 1, mk_tuple out_ps]) |
377 (Pretty.block [str "DSeq.single", Pretty.brk 1, mk_tuple out_ps]) |
378 (exists (not o is_exhaustive) out_ts''')) |
378 (exists (not o is_exhaustive) out_ts'''), gr5) |
379 end |
379 end |
380 | compile_prems out_ts vs names gr ps = |
380 | compile_prems out_ts vs names ps gr = |
381 let |
381 let |
382 val vs' = distinct (op =) (List.concat (vs :: map term_vs out_ts)); |
382 val vs' = distinct (op =) (List.concat (vs :: map term_vs out_ts)); |
383 val SOME (p, mode as SOME (Mode (_, js, _))) = |
383 val SOME (p, mode as SOME (Mode (_, js, _))) = |
384 select_mode_prem thy modes' vs' ps; |
384 select_mode_prem thy modes' vs' ps; |
385 val ps' = filter_out (equal p) ps; |
385 val ps' = filter_out (equal p) ps; |
386 val ((names', eqs), out_ts') = |
386 val ((names', eqs), out_ts') = |
387 foldl_map check_constrt ((names, []), out_ts); |
387 foldl_map check_constrt ((names, []), out_ts); |
388 val (nvs, out_ts'') = foldl_map distinct_v |
388 val (nvs, out_ts'') = foldl_map distinct_v |
389 ((names', map (fn x => (x, [x])) vs), out_ts'); |
389 ((names', map (fn x => (x, [x])) vs), out_ts'); |
390 val (gr0, out_ps) = foldl_map |
390 val (out_ps, gr0) = fold_map |
391 (invoke_codegen thy defs dep module false) (gr, out_ts''); |
391 (invoke_codegen thy defs dep module false) out_ts'' gr; |
392 val (gr1, eq_ps) = foldl_map compile_eq (gr0, eqs) |
392 val (eq_ps, gr1) = fold_map compile_eq eqs gr0; |
393 in |
393 in |
394 (case p of |
394 (case p of |
395 Prem (us, t, is_set) => |
395 Prem (us, t, is_set) => |
396 let |
396 let |
397 val (in_ts, out_ts''') = get_args js 1 us; |
397 val (in_ts, out_ts''') = get_args js 1 us; |
398 val (gr2, in_ps) = foldl_map |
398 val (in_ps, gr2) = fold_map |
399 (invoke_codegen thy defs dep module true) (gr1, in_ts); |
399 (invoke_codegen thy defs dep module true) in_ts gr1; |
400 val (gr3, ps) = |
400 val (ps, gr3) = |
401 if not is_set then |
401 if not is_set then |
402 apsnd (fn ps => ps @ |
402 apfst (fn ps => ps @ |
403 (if null in_ps then [] else [Pretty.brk 1]) @ |
403 (if null in_ps then [] else [Pretty.brk 1]) @ |
404 separate (Pretty.brk 1) in_ps) |
404 separate (Pretty.brk 1) in_ps) |
405 (compile_expr thy defs dep module false modes |
405 (compile_expr thy defs dep module false modes |
406 (gr2, (mode, t))) |
406 (mode, t) gr2) |
407 else |
407 else |
408 apsnd (fn p => [str "DSeq.of_list", Pretty.brk 1, p]) |
408 apfst (fn p => [str "DSeq.of_list", Pretty.brk 1, p]) |
409 (invoke_codegen thy defs dep module true (gr2, t)); |
409 (invoke_codegen thy defs dep module true t gr2); |
410 val (gr4, rest) = compile_prems out_ts''' vs' (fst nvs) gr3 ps'; |
410 val (rest, gr4) = compile_prems out_ts''' vs' (fst nvs) ps' gr3; |
411 in |
411 in |
412 (gr4, compile_match (snd nvs) eq_ps out_ps |
412 (compile_match (snd nvs) eq_ps out_ps |
413 (Pretty.block (ps @ |
413 (Pretty.block (ps @ |
414 [str " :->", Pretty.brk 1, rest])) |
414 [str " :->", Pretty.brk 1, rest])) |
415 (exists (not o is_exhaustive) out_ts'')) |
415 (exists (not o is_exhaustive) out_ts''), gr4) |
416 end |
416 end |
417 | Sidecond t => |
417 | Sidecond t => |
418 let |
418 let |
419 val (gr2, side_p) = invoke_codegen thy defs dep module true (gr1, t); |
419 val (side_p, gr2) = invoke_codegen thy defs dep module true t gr1; |
420 val (gr3, rest) = compile_prems [] vs' (fst nvs) gr2 ps'; |
420 val (rest, gr3) = compile_prems [] vs' (fst nvs) ps' gr2; |
421 in |
421 in |
422 (gr3, compile_match (snd nvs) eq_ps out_ps |
422 (compile_match (snd nvs) eq_ps out_ps |
423 (Pretty.block [str "?? ", side_p, |
423 (Pretty.block [str "?? ", side_p, |
424 str " :->", Pretty.brk 1, rest]) |
424 str " :->", Pretty.brk 1, rest]) |
425 (exists (not o is_exhaustive) out_ts'')) |
425 (exists (not o is_exhaustive) out_ts''), gr3) |
426 end) |
426 end) |
427 end; |
427 end; |
428 |
428 |
429 val (gr', prem_p) = compile_prems in_ts' arg_vs all_vs' gr ps; |
429 val (prem_p, gr') = compile_prems in_ts' arg_vs all_vs' ps gr ; |
430 in |
430 in |
431 (gr', Pretty.block [str "DSeq.single", Pretty.brk 1, inp, |
431 (Pretty.block [str "DSeq.single", Pretty.brk 1, inp, |
432 str " :->", Pretty.brk 1, prem_p]) |
432 str " :->", Pretty.brk 1, prem_p], gr') |
433 end; |
433 end; |
434 |
434 |
435 fun compile_pred thy defs gr dep module prfx all_vs arg_vs modes s cls mode = |
435 fun compile_pred thy defs dep module prfx all_vs arg_vs modes s cls mode gr = |
436 let |
436 let |
437 val xs = map str (Name.variant_list arg_vs |
437 val xs = map str (Name.variant_list arg_vs |
438 (map (fn i => "x" ^ string_of_int i) (snd mode))); |
438 (map (fn i => "x" ^ string_of_int i) (snd mode))); |
439 val (gr', (cl_ps, mode_id)) = |
439 val ((cl_ps, mode_id), gr') = gr |> |
440 foldl_map (fn (gr, cl) => compile_clause thy defs |
440 fold_map (fn cl => compile_clause thy defs |
441 gr dep module all_vs arg_vs modes mode cl (mk_tuple xs)) (gr, cls) |>>> |
441 dep module all_vs arg_vs modes mode cl (mk_tuple xs)) cls ||>> |
442 modename module s mode |
442 modename module s mode |
443 in |
443 in |
444 ((gr', "and "), Pretty.block |
444 (Pretty.block |
445 ([Pretty.block (separate (Pretty.brk 1) |
445 ([Pretty.block (separate (Pretty.brk 1) |
446 (str (prfx ^ mode_id) :: |
446 (str (prfx ^ mode_id) :: |
447 map str arg_vs @ |
447 map str arg_vs @ |
448 (case mode of ([], []) => [str "()"] | _ => xs)) @ |
448 (case mode of ([], []) => [str "()"] | _ => xs)) @ |
449 [str " ="]), |
449 [str " ="]), |
450 Pretty.brk 1] @ |
450 Pretty.brk 1] @ |
451 List.concat (separate [str " ++", Pretty.brk 1] (map single cl_ps)))) |
451 List.concat (separate [str " ++", Pretty.brk 1] (map single cl_ps))), (gr', "and ")) |
452 end; |
452 end; |
453 |
453 |
454 fun compile_preds thy defs gr dep module all_vs arg_vs modes preds = |
454 fun compile_preds thy defs dep module all_vs arg_vs modes preds gr = |
455 let val ((gr', _), prs) = foldl_map (fn ((gr, prfx), (s, cls)) => |
455 let val (prs, (gr', _)) = fold_map (fn (s, cls) => |
456 foldl_map (fn ((gr', prfx'), mode) => compile_pred thy defs gr' |
456 fold_map (fn mode => fn (gr', prfx') => compile_pred thy defs |
457 dep module prfx' all_vs arg_vs modes s cls mode) |
457 dep module prfx' all_vs arg_vs modes s cls mode gr') |
458 ((gr, prfx), ((the o AList.lookup (op =) modes) s))) ((gr, "fun "), preds) |
458 (((the o AList.lookup (op =) modes) s))) preds (gr, "fun ") |
459 in |
459 in |
460 (gr', space_implode "\n\n" (map string_of (List.concat prs)) ^ ";\n\n") |
460 (space_implode "\n\n" (map string_of (List.concat prs)) ^ ";\n\n", gr') |
461 end; |
461 end; |
462 |
462 |
463 (**** processing of introduction rules ****) |
463 (**** processing of introduction rules ****) |
464 |
464 |
465 exception Modes of |
465 exception Modes of |
659 val no_loose = forall (fn t => not (loose_bvar (t, 0))) |
657 val no_loose = forall (fn t => not (loose_bvar (t, 0))) |
660 in |
658 in |
661 if null (duplicates op = ots) andalso |
659 if null (duplicates op = ots) andalso |
662 no_loose ts1 andalso no_loose its |
660 no_loose ts1 andalso no_loose its |
663 then |
661 then |
664 let val (gr', call_p) = mk_ind_call thy defs gr dep module true |
662 let val (call_p, gr') = mk_ind_call thy defs dep module true |
665 s T (ts1 @ ts2') names thyname k intrs |
663 s T (ts1 @ ts2') names thyname k intrs gr |
666 in SOME (gr', (if brack then parens else I) (Pretty.block |
664 in SOME ((if brack then parens else I) (Pretty.block |
667 [str "DSeq.list_of", Pretty.brk 1, str "(", |
665 [str "DSeq.list_of", Pretty.brk 1, str "(", |
668 conv_ntuple fs ots call_p, str ")"])) |
666 conv_ntuple fs ots call_p, str ")"]), gr') |
669 end |
667 end |
670 else NONE |
668 else NONE |
671 end |
669 end |
672 | _ => NONE) |
670 | _ => NONE) |
673 | _ => NONE |
671 | _ => NONE |
674 end |
672 end |
675 | (Const (s, T), ts) => (case Symtab.lookup (#eqns (CodegenData.get thy)) s of |
673 | (Const (s, T), ts) => (case Symtab.lookup (#eqns (CodegenData.get thy)) s of |
676 NONE => (case (get_clauses thy s, get_assoc_code thy (s, T)) of |
674 NONE => (case (get_clauses thy s, get_assoc_code thy (s, T)) of |
677 (SOME (names, thyname, k, intrs), NONE) => |
675 (SOME (names, thyname, k, intrs), NONE) => |
678 if length ts < k then NONE else SOME |
676 if length ts < k then NONE else SOME |
679 (let val (gr', call_p) = mk_ind_call thy defs gr dep module false |
677 (let val (call_p, gr') = mk_ind_call thy defs dep module false |
680 s T (map Term.no_dummy_patterns ts) names thyname k intrs |
678 s T (map Term.no_dummy_patterns ts) names thyname k intrs gr |
681 in (gr', mk_funcomp brack "?!" |
679 in (mk_funcomp brack "?!" |
682 (length (binder_types T) - length ts) (parens call_p)) |
680 (length (binder_types T) - length ts) (parens call_p), gr') |
683 end handle TERM _ => mk_ind_call thy defs gr dep module true |
681 end handle TERM _ => mk_ind_call thy defs dep module true |
684 s T ts names thyname k intrs) |
682 s T ts names thyname k intrs gr ) |
685 | _ => NONE) |
683 | _ => NONE) |
686 | SOME eqns => |
684 | SOME eqns => |
687 let |
685 let |
688 val (_, thyname) :: _ = eqns; |
686 val (_, thyname) :: _ = eqns; |
689 val (gr', id) = mk_fun thy defs s (preprocess thy (map fst (rev eqns))) |
687 val (id, gr') = mk_fun thy defs s (preprocess thy (map fst (rev eqns))) |
690 dep module (if_library thyname module) gr; |
688 dep module (if_library thyname module) gr; |
691 val (gr'', ps) = foldl_map |
689 val (ps, gr'') = fold_map |
692 (invoke_codegen thy defs dep module true) (gr', ts); |
690 (invoke_codegen thy defs dep module true) ts gr'; |
693 in SOME (gr'', mk_app brack (str id) ps) |
691 in SOME (mk_app brack (str id) ps, gr'') |
694 end) |
692 end) |
695 | _ => NONE); |
693 | _ => NONE); |
696 |
694 |
697 val setup = |
695 val setup = |
698 add_codegen "inductive" inductive_codegen #> |
696 add_codegen "inductive" inductive_codegen #> |