From Coq Require Import PeanoNat.
From Coq Require Import List.
From Velus Require Import Common.
From Coq Require Export Classes.EquivDec.
Import List.ListNotations.
Open Scope list_scope.
Module Type OPERATORS.
  
Parameter cvalue : 
Type.
  
Parameter ctype  : 
Type.
  
Parameter cconst : 
Type.
  
Definition enumtag := 
nat.
  
Inductive value :=
  | 
Vscalar : 
cvalue -> 
value
  | 
Venum   : 
enumtag -> 
value.
  
Inductive type :=
  | 
Tprimitive : 
ctype -> 
type
  | 
Tenum      : 
ident -> 
list ident -> 
type.
  
Inductive const :=
  | 
Const: 
cconst -> 
const
  | 
Enum : 
enumtag -> 
const.
  
Parameter ctype_cconst : 
cconst -> 
ctype.
  
Parameter sem_cconst  : 
cconst -> 
cvalue.
  
Parameter init_ctype  : 
ctype -> 
cconst.
  
Parameter unop  : 
Type.
  
Parameter binop : 
Type.
  
Parameter sem_unop  : 
unop -> 
value -> 
type -> 
option value.
  
Parameter sem_binop : 
binop -> 
value -> 
type -> 
value -> 
type -> 
option value.
  
Parameter sem_extern :  
ident -> 
list ctype -> 
list cvalue -> 
ctype -> 
cvalue -> 
Prop.
  
Axiom sem_extern_det : 
forall f tyins ins tyout out1 out2,
      
sem_extern f tyins ins tyout out1 ->
      
sem_extern f tyins ins tyout out2 ->
      
out1 = 
out2.
  
Parameter type_unop  : 
unop -> 
type -> 
option type.
  
Parameter type_binop : 
binop -> 
type -> 
type -> 
option type.
  
Parameter wt_cvalue : 
cvalue -> 
ctype -> 
Prop.
  
Axiom wt_cvalue_cconst : 
forall c, 
wt_cvalue (
sem_cconst c) (
ctype_cconst c).
  
Axiom wt_init_ctype : 
forall ty, 
wt_cvalue (
sem_cconst (
init_ctype ty)) 
ty.
  
Axiom ctype_init_ctype : 
forall ty, 
ctype_cconst (
init_ctype ty) = 
ty.
  
Inductive wt_value: 
value -> 
type -> 
Prop :=
    | 
WTVScalarPrimitive: 
forall v t,
        
wt_cvalue v t ->
        
wt_value (
Vscalar v) (
Tprimitive t)
    | 
WTVEnum: 
forall v tx tn,
        
v < 
length tn ->
        
wt_value (
Venum v) (
Tenum tx tn).
  
Conjecture pres_sem_unop:
    
forall op ty1 ty v1 v,
      
type_unop op ty1 = 
Some ty ->
      
sem_unop op v1 ty1 = 
Some v ->
      
wt_value v1 ty1 ->
      
wt_value v ty.
  
Conjecture pres_sem_binop:
    
forall op ty1 ty2 ty v1 v2 v,
      
type_binop op ty1 ty2 = 
Some ty ->
      
sem_binop op v1 ty1 v2 ty2 = 
Some v ->
      
wt_value v1 ty1 ->
      
wt_value v2 ty2 ->
      
wt_value v ty.
  
Conjecture pres_sem_extern:
    
forall f tyins vins tyout vout,
      
Forall2 wt_cvalue vins tyins ->
      
sem_extern f tyins vins tyout vout ->
      
wt_cvalue vout tyout.
  
Axiom cvalue_dec   : 
forall v1  v2  : 
cvalue,    {
v1 = 
v2}  +  {
v1 <> 
v2}.
  
Axiom ctype_dec  : 
forall t1  t2  : 
ctype,   {
t1 = 
t2}  +  {
t1 <> 
t2}.
  
Axiom cconst_dec : 
forall c1  c2  : 
cconst,  {
c1 = 
c2}  +  {
c1 <> 
c2}.
  
Axiom unop_dec  : 
forall op1 op2 : 
unop,  {
op1 = 
op2} + {
op1 <> 
op2}.
  
Axiom binop_dec : 
forall op1 op2 : 
binop, {
op1 = 
op2} + {
op1 <> 
op2}.
  
Parameter check_unop : 
unop -> 
option value -> 
type -> 
bool.
  
Conjecture check_unop_correct :
    
forall op ov ty,
      
check_unop op ov ty = 
true ->
      
type_unop op ty <> 
None ->
      
forall v,
      
wt_value v ty ->
      
match ov with
      | 
Some v' => 
v' = 
v
      | 
_ => 
True
      end ->
      
sem_unop op v ty <> 
None.
  
Parameter check_binop : 
binop -> 
option value -> 
type -> 
option value -> 
type -> 
bool.
  
Conjecture check_binop_correct :
    
forall op ov1 ty1 ov2 ty2,
      
check_binop op ov1 ty1 ov2 ty2 = 
true ->
      
type_binop op ty1 ty2 <> 
None ->
      
forall v1 v2,
      
wt_value v1 ty1 ->
      
wt_value v2 ty2 ->
      
match ov1 with
      | 
Some v => 
v = 
v1
      | 
_ => 
True
      end ->
      
match ov2 with
      | 
Some v => 
v = 
v2
      | 
_ => 
True
      end ->
      
sem_binop op v1 ty1 v2 ty2 <> 
None.
End OPERATORS.
Module Type OPERATORS_AUX
       (
Import Ids : 
IDS)
       (
Import Ops : 
OPERATORS).
  
Close Scope equiv_scope.
  
Global Instance: 
EqDec cvalue eq := { 
equiv_dec := 
cvalue_dec }.
  
Global Instance: 
EqDec ctype  eq := { 
equiv_dec := 
ctype_dec  }.
  
Global Instance: 
EqDec cconst eq := { 
equiv_dec := 
cconst_dec }.
  
Global Instance: 
EqDec unop   eq := { 
equiv_dec := 
unop_dec   }.
  
Global Instance: 
EqDec binop  eq := { 
equiv_dec := 
binop_dec  }.
  
Definition false_tag : 
enumtag := 0.
  
Definition true_tag : 
enumtag := 1.
  
Lemma enumtag_eqb_eq : 
forall (
x y : 
enumtag),
      (
x ==
b y) = 
true <-> 
x = 
y.
  Proof.
  Lemma enumtag_eqb_neq : 
forall (
x y : 
enumtag),
      (
x ==
b y) = 
false <-> 
x <> 
y.
  Proof.
  Lemma value_dec:
    
forall v1 v2 : 
value,
      {
v1 = 
v2} + {
v1 <> 
v2}.
  Proof.
  Definition sem_const (
c0: 
const) : 
value :=
    
match c0 with
    | 
Const c0 => 
Vscalar (
sem_cconst c0)
    | 
Enum c   => 
Venum c
    end.
  
Definition bool_velus_type := 
Tenum bool_id [
false_id; 
true_id].
  
Definition type_dec (
t1 t2: 
type) : {
t1 = 
t2} + {
t1 <> 
t2}.
    
repeat decide equality.
    
apply ctype_dec.
  Defined.
  
Global Instance: 
EqDec type eq := { 
equiv_dec := 
type_dec }.
A synchronous value is either an absence or a present constant 
  Inductive synchronous (
A : 
Type) :=
  | 
absent
  | 
present (
v: 
A).
  
Arguments absent {
_}.
  
Arguments present {
_}.
  
Definition svalue := 
synchronous value.
  
Definition svalue_dec (
v1 v2: 
svalue) : {
v1 = 
v2} + {
v1 <> 
v2}.
    
repeat decide equality.
    
apply cvalue_dec.
  Defined.
  
Global Instance: 
EqDec svalue eq := { 
equiv_dec := 
svalue_dec }.
  
Lemma not_absent_bool:
    
forall (
x : 
svalue), 
x <> 
absent <-> 
x <>
b absent = 
true.
  Proof.
  Lemma neg_eq_svalue:
    
forall (
x y: 
svalue),
      
negb (
x <>
b y) = (
x ==
b y).
  Proof.
  Lemma svalue_eqb_eq:
    
forall (
x y: 
svalue), 
x ==
b y = 
true <-> 
x = 
y.
  Proof.
  Lemma decidable_eq_svalue:
    
forall (
x y: 
svalue),
      
Decidable.decidable (
x = 
y).
  Proof.
  Inductive wt_type (
types: 
list type): 
type -> 
Prop :=
  | 
WTTPrim: 
forall cty,
      
wt_type types (
Tprimitive cty)
  | 
WTTEnum: 
forall tx tn,
      
In (
Tenum tx tn) 
types ->
      0 < 
length tn ->
      
NoDup tn ->
      
wt_type types (
Tenum tx tn).
  
Inductive wt_const (
enums: 
list type): 
const -> 
type -> 
Prop :=
  | 
WTCConst: 
forall c,
      
wt_const enums (
Const c) (
Tprimitive (
ctype_cconst c))
  | 
WTCEnum: 
forall c tx tn,
      
In (
Tenum tx tn) 
enums ->
      
c < 
length tn ->
      
wt_const enums (
Enum c) (
Tenum tx tn).
  
Definition wt_values vs (
xts: 
list (
ident * 
type))
    := 
List.Forall2 (
fun v xt => 
wt_value v (
snd xt)) 
vs xts.
  
Lemma wt_value_const:
    
forall enums c t,
      
wt_const enums c t ->
      
wt_value (
sem_const c) 
t.
  Proof.
  Definition wt_option_value (
vo: 
option value) (
ty: 
type) : 
Prop :=
    
match vo with
    | 
None => 
True
    | 
Some v => 
wt_value v ty
    end.
  
Definition value_to_bool (
v : 
value) :=
    
match v with
    | 
Venum tag => 
Some (
tag ==
b true_tag)
    | 
_ => 
None
    end.
  
Definition svalue_to_bool (
v : 
svalue) :=
    
match v with
    | 
absent => 
Some false
    | 
present v => 
value_to_bool v
    end.
  
Definition wt_svalue (
v: 
svalue) (
ty: 
type) : 
Prop :=
    
match v with
    | 
absent => 
True
    | 
present v => 
wt_value v ty
    end.
End OPERATORS_AUX.
Module OperatorsAux
       (
Import Ids : 
IDS)
       (
Import Ops : 
OPERATORS) <: 
OPERATORS_AUX Ids Ops.
  
Include OPERATORS_AUX Ids Ops.
End OperatorsAux.