aboutsummaryrefslogtreecommitdiff
path: root/src/Compilers/Named/MapType.v
blob: 06d8063b8dc63eefbbcd1278dc984e1101aae56d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
Require Import Coq.Bool.Sumbool.
Require Import Crypto.Compilers.SmartMap.
Require Import Crypto.Compilers.Syntax.
Require Import Crypto.Compilers.Named.Syntax.

Local Open Scope nexpr_scope.
Section language.
  Context {base_type_code1 base_type_code2 : Type}
          {op1 : flat_type base_type_code1 -> flat_type base_type_code1 -> Type}
          {op2 : flat_type base_type_code2 -> flat_type base_type_code2 -> Type}
          {Name : Type}
          (f_base_type_code : base_type_code1 -> base_type_code2).
  Fixpoint lift_flat_type (t : flat_type base_type_code1) : flat_type base_type_code2
    := match t with
       | Tbase T => Tbase (f_base_type_code T)
       | Unit => Unit
       | Prod A B => Prod (lift_flat_type A) (lift_flat_type B)
       end.
  Context (f_op : forall s d,
              op1 s d
              -> option (op2 (lift_flat_type s) (lift_flat_type d))).

  Fixpoint transfer_interp_flat_type {t}
    : interp_flat_type (fun _ => Name) t
      -> interp_flat_type (fun _ => Name) (lift_flat_type t)
    := match t with
       | Tbase T => fun v => v
       | Unit => fun v => v
       | Prod A B => fun ab : interp_flat_type _ A * interp_flat_type _ B
                     => (@transfer_interp_flat_type _ (fst ab),
                         @transfer_interp_flat_type _ (snd ab))%core
       end.

  Fixpoint mapf_type
           {t} (e : exprf base_type_code1 op1 Name t)
    : option (exprf base_type_code2 op2 Name (lift_flat_type t))
    := match e in exprf _ _ _ t return option (exprf _ _ _ (lift_flat_type t)) with
       | TT => Some TT
       | Var t x => Some (Var x)
       | Op t1 tR opc args
         => let opc := f_op _ _ opc in
            let args := @mapf_type _ args in
            match opc, args with
            | Some opc, Some args => Some (Op opc args)
            | _, _ => None
            end
       | LetIn tx n ex tC eC
         => let n := transfer_interp_flat_type n in
            let ex := @mapf_type _ ex in
            let eC := @mapf_type _ eC in
            match ex, eC with
            | Some ex, Some eC
              => Some (LetIn _ n ex eC)
            | _, _ => None
            end
       | Pair tx ex ty ey
         => let ex := @mapf_type _ ex in
            let ey := @mapf_type _ ey in
            match ex, ey with
            | Some ex, Some ey
              => Some (Pair ex ey)
            | _, _ => None
            end
       end.

  Definition map_type
             {t} (e : expr base_type_code1 op1 Name t)
    : option (expr base_type_code2 op2 Name (Arrow (lift_flat_type (domain t)) (lift_flat_type (codomain t))))
    := let f := invert_Abs e in
       let f := mapf_type f in
       let n := Abs_name e in
       let n := transfer_interp_flat_type n in
       option_map
         (fun f => Abs n f)
         f.
End language.