Fil-C on Nix

Filnix wiki

the formal campaign

rocq/backend/Order.v

Prolog's standard order of terms, and the sorted lists the Prolog compiler makes with it: sort/2, msort/2 and the ordsets of library(ordsets). The backend's plans list temporaries, live ranges and thunks in this order, so the Gallina backend sorts by it too.

For the ground terms of Term.v the order is: integers by value, then [ ], then atoms by character code, then compounds, by arity, then by name, then by their arguments from the left. A list that is not empty is the compound '[|]'(Head, Tail).

From Stdlib Require Import String ZArith List Ascii
From Nanofil Require Import Term
Import ListNotations

Comparing

The order of two atoms' names: by character code, a prefix first. Extract.v makes it OCaml's comparison of strings.

20Definition atom_comparea b : string : comparison ≔
String.comparea b

c, or d if c finds its two sides equal: one more key of a comparison by several.

24Definition thencc d : comparison : comparison ≔
match c with
⇒
d
_
⇒
c

As compare(Order, T, U): the standard order of the terms t and u.

29Fixpoint term_comparet u : term {struct t} : comparison ≔
let fix args_compare ts us : listterm {struct ts} : comparison ≔
match ts, us with
[ ], [ ]
⇒
[ ], _ :: _
⇒
_ :: _, [ ]
⇒
t′ :: ts′, u′ :: us′
⇒
thencterm_comparet′ u′ args_comparets′ us′
in
let fix list_compare ts : listterm u : term {struct ts} : comparison ≔
match ts with

The list ts against the term u.

[ ]
⇒
match u with
⇒
⇒
_
⇒
h :: ts′
⇒
match u with
TInt_ | TAtom_ | TList[ ]
⇒
TListh′ :: us′
⇒
thencterm_compareh h′ list_comparets′ TListus′
TAppg b1; b2
⇒
thencatom_compare"[|]" g thencterm_compareh b1 list_comparets′ b2
TApp_ bs
⇒
Nat.compare2 lengthbs
in
match t with
⇒
match u with
⇒
Z.comparen m
_
⇒
⇒
match u with
TInt_ | TList[ ]
⇒
_
⇒
⇒
list_comparets u
TAppf ts
⇒
match u with
TInt_ | TAtom_ | TList[ ]
⇒
TAppg us
⇒
thencNat.comparelengthts lengthus thencatom_comparef g args_comparets us
TListh′ :: us′
⇒
match ts with
_
⇒
Nat.comparelengthts 2

Sorting

80Section Sorting
81Context A : Type cmp : A → A → comparison

The merges below take one element off one list or both at each step, so the two lengths together are steps enough. Each is one function over that count, not a function of xs holding another of ys, so that its C++ extraction is a loop: a merge of two long lists would otherwise be as deep as they are long.

merge in at most n steps.

90Fixpoint merge_stepsn : nat xs ys : listA : listA ≔
match n, xs, ys with
_, [ ], _
⇒
ys
_, _, [ ]
⇒
xs
O, _, _
⇒
xs
Sn′, x :: xs′, y :: ys′
⇒
match cmpx y with
⇒
y :: merge_stepsn′ xs ys′
_
⇒
x :: merge_stepsn′ xs′ ys

The sorted lists xs and ys merged; of two equal elements, xs's comes first.

104Definition mergexs ys : listA : listA ≔
merge_stepslengthxs + lengthys xs ys

A merge sort's stack of sorted runs: the run at depth i, if there is one, has 2^i elements.

109Fixpoint push_runstack : listoptionlistA run : listA : listoptionlistA ≔
match stack with
[ ]
⇒
Somerun
None :: stack′
⇒
Somerun :: stack′
Somerun′ :: stack′
⇒
None :: push_runstack′ mergerun′ run

The runs of a stack merged, the oldest first.

118Fixpoint merge_runsstack : listoptionlistA : listA ≔
match stack with
[ ]
⇒
[ ]
None :: stack′
⇒
merge_runsstack′
Somerun :: stack′
⇒
mergemerge_runsstack′ run

As msort(Xs, Sorted): xs in the order of cmp, equal elements in the order they had (a merge sort, as SWI-Prolog's is).

127Definition msortxs : listA : listA ≔
merge_runsfold_leftλstack x ⇒ push_runstack x xs [ ]

A sorted list with one element of each run of equal ones.

131Fixpoint dedupxs : listA : listA ≔
match xs with
x :: y :: _ as xs′
⇒
match cmpx y with
⇒
dedupxs′
_
⇒
x :: dedupxs′
_
⇒
xs

As sort(Xs, Sorted): xs sorted, without duplicates. Its results are ordsets.

140Definition sortxs : listA : listA ≔

ord_union in at most n steps.

143Fixpoint union_stepsn : nat xs ys : listA : listA ≔
match n, xs, ys with
_, [ ], _
⇒
ys
_, _, [ ]
⇒
xs
O, _, _
⇒
xs
Sn′, x :: xs′, y :: ys′
⇒
match cmpx y with
⇒
x :: union_stepsn′ xs′ ys
⇒
x :: union_stepsn′ xs′ ys′
⇒
y :: union_stepsn′ xs ys′

As ord_union(Xs, Ys, Zs): the union of two ordsets.

157Definition ord_unionxs ys : listA : listA ≔
union_stepslengthxs + lengthys xs ys

ord_subtract in at most n steps.

161Fixpoint subtract_stepsn : nat xs ys : listA : listA ≔
match n, xs, ys with
_, [ ], _
⇒
[ ]
_, _, [ ]
⇒
xs
O, _, _
⇒
xs
Sn′, x :: xs′, y :: ys′
⇒
match cmpx y with
⇒
x :: subtract_stepsn′ xs′ ys
⇒
subtract_stepsn′ xs′ ys′
⇒
subtract_stepsn′ xs ys′

As ord_subtract(Xs, Ys, Zs): the elements of the ordset xs that are not in the ordset ys.

176Definition ord_subtractxs ys : listA : listA ≔
subtract_stepslengthxs + lengthys xs ys

ord_intersection in at most n steps.

180Fixpoint intersection_stepsn : nat xs ys : listA : listA ≔
match n, xs, ys with
_, [ ], _
⇒
[ ]
_, _, [ ]
⇒
[ ]
O, _, _
⇒
[ ]
Sn′, x :: xs′, y :: ys′
⇒
match cmpx y with
⇒
intersection_stepsn′ xs′ ys
⇒
x :: intersection_stepsn′ xs′ ys′
⇒
intersection_stepsn′ xs ys′

As ord_intersection(Xs, Ys, Zs): the elements of the ordset xs that are in the ordset ys too.

195Definition ord_intersectionxs ys : listA : listA ≔
intersection_stepslengthxs + lengthys xs ys

As ord_memberchk(X, Xs): whether x is in the ordset xs.

199Fixpoint ord_memx : A xs : listA : bool ≔
match xs with
[ ]
⇒
false
y :: xs′
⇒
match cmpx y with
⇒
false
⇒
true
⇒
ord_memx xs′

Whether two ordsets of names are the same.

212Fixpoint names_eqbxs ys : listname : bool ≔
match xs, ys with
[ ], [ ]
⇒
true
x :: xs′, y :: ys′
⇒
name_eqbx y && names_eqbxs′ ys′
_, _
⇒
false
219Example order_kinds: msortterm_compare TApp"g" TAtom"a"; TAtom"b"; TListTAtom"a"; TAtom"b"; TApp"-" TAtom"a"; TAtom"b"; TList[ ]; TInt3; TAtom"a"; TInt−1 = TInt−1; TInt3; TList[ ]; TAtom"a"; TAtom"b"; TApp"-" TAtom"a"; TAtom"b"; TListTAtom"a"; TApp"g" TAtom"a"; TAtom"b"
Proof 1 step Qed
reflexivity
228Example sort_dedups: sortZ.compare 3; 1; 2; 3; 1%Z = 1; 2; 3%Z
Proof 1 step Qed
reflexivity