Local Open Scope logic.
Record module {reptype: Type} :=  {
mf_rep: reptype;
mf_Gimport: list (ident*funspec);
mf_Gexport :  list (reptype -> ident*funspec);
mf_Gintern :  list (reptype -> ident*funspec);
mf_G' :=  map (fun f => f mf_rep)
(mf_Gexport ++ mf_Gintern);
mf_G := mf_Gimport ++ mf_G';
mf_V : varspecs;
mf_funs: list (ident * fundef);
mf_funs_correct: forall (Espec: OracleKind),
semax_func mf_V mf_G mf_funs mf_G'
}.
Definition builtins:  list (ident * globdef fundef type) :=
((___builtin_fabs,
Gfun(External (EF_builtin ___builtin_fabs
(mksignature (AST.Tfloat :: nil) (Some AST.Tfloat)))
(Tcons tdouble Tnil) tdouble)) ::
(___builtin_memcpy_aligned,
Gfun(External (EF_builtin ___builtin_memcpy_aligned
(mksignature
(AST.Tint :: AST.Tint :: AST.Tint :: AST.Tint :: nil)
None))
(Tcons (tptr tvoid)
(Tcons (tptr tvoid) (Tcons tuint (Tcons tuint Tnil)))) tvoid)) ::
(___builtin_annot_intval,
Gfun(External (EF_builtin ___builtin_annot_intval
(mksignature (AST.Tint :: AST.Tint :: nil)
(Some AST.Tint)))
(Tcons (tptr tschar) (Tcons tint Tnil)) tint)) :: nil).
Definition Gbuiltins := do_builtins builtins.
Fixpoint varspecs_sub (al bl: varspecs) : bool :=
match al, bl with
| (a,v)::al', (b,w)::bl' =>
match Pos.compare a b
with Lt => false
| Eq => if eqb_type v w then varspecs_sub al' bl' else false
| Gt => varspecs_sub al' bl
end
| nil, _ => true
| _::_, _ => false
end.
Fixpoint funspecs_sub (al bl: funspecs) : Prop :=
match al, bl with
| (a,v)::al', (b,w)::bl' =>
match Pos.compare a b
with Lt => False
| Eq => v=w /\ funspecs_sub al' bl'
| Gt => funspecs_sub al' bl
end
| nil, _ => True
| _::_, _ => False
end.
Admitted.
Ltac next_module H :=
first
[ apply semax_func_cons; [ reflexivity | apply H | ]
| eapply semax_func_app;
[apply H | | reflexivity | reflexivity
|   try apply varspecs_sub_refl; try reflexivity
|   try apply varspecs_sub_refl; try reflexivity
|   try apply funspecs_sub_refl; try (repeat split; simpl; auto)
|   try apply funspecs_sub_refl; try (repeat split; simpl; auto)
]
].
(**************************************************************)
Instance QS: listspec t_struct_elem _next.
Admitted.
Admitted.
Admitted.
Definition funcs := ((_fifo_new, Internal f_fifo_new) ::
(_fifo_put, Internal f_fifo_put) ::
(_fifo_empty, Internal f_fifo_empty) ::
(_fifo_get, Internal f_fifo_get) :: nil).
Definition module_fifo : module := {|
mf_rep := fifo;
mf_Gimport := (mallocN_spec :: freeN_spec :: nil);
mf_Gexport := (fifo_new_spec :: fifo_put_spec
:: fifo_empty_spec :: fifo_get_spec :: nil);
mf_Gintern := nil;
mf_V := nil;
mf_funs := ((_fifo_new, Internal f_fifo_new) ::
(_fifo_put, Internal f_fifo_put) ::
(_fifo_empty, Internal f_fifo_empty) ::
(_fifo_get, Internal f_fifo_get) :: nil);
mf_funs_correct := funcs_correct
|}.
(***************************************************)
Definition make_elem_spec :=
DECLARE _make_elem
WITH a: int, b: int
PRE  [ _a OF tint, _b OF tint ]
PROP() LOCAL(`(eq (Vint a)) (eval_id _a); `(eq (Vint b)) (eval_id _b)) SEP()
POST [ (tptr t_struct_elem) ] `(elemrep (a,b)) retval.
Definition main_spec :=
DECLARE _main
WITH u : unit
PRE  [] main_pre prog tt u
POST [ tint ] main_post prog u.
Definition Vprog : varspecs := nil.
Definition Gprog : funspecs :=   ltac:(with_library prog
(mallocN_spec :: freeN_spec ::
(map (fun f => f module_fifo.(mf_rep)) module_fifo.(mf_Gexport))
++ make_elem_spec :: main_spec::nil)).
Definition Gtot := do_builtins (prog_defs prog) ++ Gprog.
Admitted.
Admitted.
Existing Instance NullExtension.Espec.
Parameter body_mallocN:
semax_external
(EF_external _mallocN
{| sig_args := AST.Tint :: nil; sig_res := Some AST.Tint |}) int
(fun n : int => PROP (4 <= Int.signed n) LOCAL (`(eq (Vint n)) (eval_id 1%positive)) SEP ())
(fun n : int => `(memory_block Tsh n) retval).
Parameter body_freeN:
semax_external
(EF_external _freeN
{| sig_args := AST.Tint :: AST.Tint :: nil; sig_res := None |}) unit
(fun _ : unit =>
PROP() LOCAL () SEP (`(memory_block Tsh) (`force_int (eval_id 2%positive)) (eval_id 1%positive)))
(fun _ : unit => emp).

Lemma extern_correct:
semax_func Vprog Gtot
((_mallocN,(External (EF_external _mallocN
(mksignature (AST.Tint :: nil) (Some AST.Tint)))
(Tcons tint Tnil) (tptr tvoid))) ::
(_freeN,
(External (EF_external _freeN
(mksignature (AST.Tint :: AST.Tint :: nil) None))
(Tcons (tptr tvoid) (Tcons tint Tnil)) tvoid)) :: nil)
(mallocN_spec::freeN_spec::nil).