diff options
author | Greg Brown <greg.brown01@ed.ac.uk> | 2024-10-29 18:58:45 +0000 |
---|---|---|
committer | Greg Brown <greg.brown01@ed.ac.uk> | 2024-10-29 18:58:45 +0000 |
commit | 82783476f330801b54402bdcc4723add44a963dc (patch) | |
tree | a1f8e77bf4a8fa32bb52e4e26c06f8acbb136df9 /program/reducer.prim | |
parent | 324e22d7297f506f7ba551f0d1e9aac786ae4622 (diff) |
Write a fuelled reducer for System T.
Diffstat (limited to 'program/reducer.prim')
-rw-r--r-- | program/reducer.prim | 123 |
1 files changed, 123 insertions, 0 deletions
diff --git a/program/reducer.prim b/program/reducer.prim new file mode 100644 index 0000000..ead7fbc --- /dev/null +++ b/program/reducer.prim @@ -0,0 +1,123 @@ +let Bool = [T: <>, F: <>] in +let or (x : Bool) (y : Bool) : Bool = case x of {T u => T <>; F u => y} in +let SysT = + (\T => + [ Var: Nat + , Zero: <> + , Suc: T + , Primrec: <Zero: T, Suc: T, Target: T> + , Abs: T + , App: <Fun: T, Arg: T> + ]) +in +let Stepped = <Term: SysT, Smaller: Bool> in +let lift (f : Nat -> Nat) (n : Nat) : Nat = + case !n of {Z u => 0; S k => suc (f k)} +in +let rename (t : SysT) : (Nat -> Nat) -> SysT = + foldcase t by + { Var n => \f => ~(Var (f n)) + ; Zero u => \f => ~(Zero <>) + ; Suc r => \f => ~(Suc (r f)) + ; Primrec p => \f => + ~(Primrec <Zero: p.Zero f, Suc: p.Suc (lift f), Target: p.Target f>) + ; Abs r => \f => ~(Abs (r f)) + ; App p => \f => ~(App <Fun: p.Fun f, Arg: p.Arg f>) + } +in +let index (xs : List SysT) : Nat -> SysT = + foldcase xs by + { N u => \k => ~(Var k) + ; C p => \k => case !k of {Z u => p.H; S k => p.T k} + } +in +let shift = map (\X => List X) SysT SysT (\t => rename t suc) in +let sub (t : SysT) : List SysT -> SysT = + foldcase t by + { Var n => \env => index env n + ; Zero u => \env => ~(Zero <>) + ; Suc f => \env => ~(Suc (f env)) + ; Primrec p => \env => + ~(Primrec + < Zero: p.Zero env + , Suc: p.Suc ~(C <H: ~(Var 0), T: shift env>) + , Target: p.Target env + >) + ; Abs f => \env => ~(Abs (f ~(C <H: ~(Var 0), T: shift env>))) + ; App p => \env => ~(App <Fun: p.Fun env, Arg: p.Arg env>) + } +in +let app (fun : SysT) (arg : SysT) (smaller : Bool) : Stepped = + let default : Stepped = <Term: ~(App <Fun: fun, Arg: arg>), Smaller: smaller> + in + case !fun of + { Var n => default + ; Zero u => default + ; Suc t => default + ; Primrec p => default + ; Abs t => <Term: sub t ~(C <H: arg, T: ~(N <>)>), Smaller: T <>> + ; App t => default + } +in +let rec (z : SysT) (s : SysT) (target : SysT) (smaller : Bool) : Stepped = + let default : Stepped = + <Term: ~(Primrec <Zero: z, Suc: s, Target: target>), Smaller: smaller> + in + case !target of + { Var n => default + ; Zero u => <Term: z, Smaller: T <>> + ; Suc t => + < Term: + sub s ~(C <H: ~(Primrec <Zero: z, Suc: s, Target: t>), T: ~(N <>)>) + , Smaller: T <> + > + ; Primrec p => default + ; Abs t => default + ; App t => default + } +in +let step (t : SysT) : Stepped = + foldcase t by + { Var n => <Term: ~(Var n), Smaller: F <>> + ; Zero u => <Term: ~(Zero <>), Smaller: F <>> + ; Suc t => <Term: ~(Suc t.Term), Smaller: t.Smaller> + ; Primrec t => + case t.Target.Smaller of + { F u => + rec + t.Zero.Term + t.Suc.Term + t.Target.Term + (or t.Zero.Smaller t.Suc.Smaller) + ; T u => + < Term: + ~(Primrec + (map + (\X => <Zero: X, Suc: X, Target: X>) + Stepped + SysT + (\p => p.Term) + t)) + , Smaller: T <> + > + } + ; Abs t => <Term: ~(Abs t.Term), Smaller: t.Smaller> + ; App t => + case t.Arg.Smaller of + { F u => app t.Fun.Term t.Arg.Term t.Fun.Smaller + ; T u => + < Term: + ~(App + (map (\X => <Fun: X, Arg: X>) Stepped SysT (\p => p.Term) t)) + , Smaller: T <> + > + } + } +in +\n => + foldcase n by + { Z u => \t => t + ; S f => \t => + let stepped = step t in + case stepped.Smaller of {F u => stepped.Term; T u => f stepped.Term} + } |