Skip to content

Instantly share code, notes, and snippets.

@eernstg
Last active March 9, 2017 08:49
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save eernstg/4e0555a0faf2b472fc0521012227629f to your computer and use it in GitHub Desktop.
Save eernstg/4e0555a0faf2b472fc0521012227629f to your computer and use it in GitHub Desktop.
Coq source for model of voidness preservation criteria
Require Import Coq.Program.Basics.
Require Import List.
Inductive Name : Set := Object | A | B | Iterable | List.
Inductive DartType : Set :=
| dt_void : DartType
| dt_dynamic : DartType
| dt_class : list (Name * list DartType) -> DartType (* Incl. all supertypes *)
| dt_function : DartType -> list DartType -> DartType
| dt_variable : Name -> DartType. (* Type parameter with no bound *)
Definition ClassType : Type := (Name * (list DartType))%type.
Definition ClassTypes : Type := list ClassType.
Inductive VoidnessType : Set :=
| vt_0 : VoidnessType
| vt_1 : VoidnessType
| vt_class : list (Name * list VoidnessType) -> VoidnessType
| vt_function : VoidnessType -> list VoidnessType -> VoidnessType.
Definition VoidnessClassType : Type := prod Name (list VoidnessType).
Definition VoidnessClassTypes : Type := list VoidnessClassType.
Fixpoint voidness (dt : DartType) : VoidnessType :=
match dt with
| dt_void => vt_1
| dt_dynamic => vt_0
| dt_class ctypes =>
vt_class ((fix ctMap (ctypes: ClassTypes) :=
match ctypes with
| nil => nil
| (name, args) :: ctypes => (name, map voidness args) :: (ctMap ctypes)
end) ctypes)
| dt_function ret args => vt_function (voidness ret) (map covoidness args)
| dt_variable name => vt_1
end
with covoidness (dt : DartType) : VoidnessType :=
match dt with
| dt_void => vt_1
| dt_dynamic => vt_1
| dt_class ctypes =>
vt_class ((fix ctMap (ctypes: ClassTypes) :=
match ctypes with
| nil => nil
| (name, args) :: ctypes => (name, map covoidness args) :: (ctMap ctypes)
end) ctypes)
| dt_function ret args => vt_function (covoidness ret) (map voidness args)
| dt_variable name => vt_1
end.
Definition annotationVoidness := covoidness.
Inductive VoidnessPreserves : VoidnessType -> VoidnessType -> Prop :=
| vp_0_any : forall vt, VoidnessPreserves vt_0 vt
| vp_any_1 : forall vt, VoidnessPreserves vt vt_1
| vp_class : forall ctypes1 ctypes2,
VoidnessClassTypesPreserve ctypes1 ctypes2 ->
VoidnessPreserves (vt_class ctypes1) (vt_class ctypes2)
| vp_function : forall ret1 ret2 args1 args2,
VoidnessPreserves ret1 ret2 ->
VoidnessPreservesPairwise args2 args1 ->
VoidnessPreserves (vt_function ret1 args1) (vt_function ret2 args2)
with VoidnessPreservesPairwise : list VoidnessType -> list VoidnessType -> Prop :=
| vpp_nil : VoidnessPreservesPairwise nil nil
| vpp_cons : forall vt1 vt2 vts1 vts2,
VoidnessPreserves vt1 vt2 ->
VoidnessPreservesPairwise vts1 vts2 ->
VoidnessPreservesPairwise (vt1 :: vts1) (vt2 :: vts2)
with VoidnessClassTypesPreserve : VoidnessClassTypes -> VoidnessClassTypes -> Prop :=
| vctsp_nil : forall ctypes,
VoidnessClassTypesPreserve nil ctypes
| vctsp_cons : forall ctype1 ctypes1 ctypes2,
VoidnessClassTypePreserves ctype1 ctypes2 ->
VoidnessClassTypesPreserve ctypes1 ctypes2 ->
VoidnessClassTypesPreserve (ctype1 :: ctypes1) ctypes2
with VoidnessClassTypePreserves : VoidnessClassType -> VoidnessClassTypes -> Prop :=
| vctp_gone : forall ctype ctypes,
VoidnessClassTypeGone ctype ctypes ->
VoidnessClassTypePreserves ctype ctypes
| vctp_some : forall ctype ctypes,
VoidnessClassTypePreservesSome ctype ctypes ->
VoidnessClassTypePreserves ctype ctypes
with VoidnessClassTypeGone : VoidnessClassType -> VoidnessClassTypes -> Prop :=
| vctg_nil : forall ctype,
VoidnessClassTypeGone ctype nil
| vctg_cons : forall name1 args1 name2 args2 ctypes,
name1 <> name2 ->
VoidnessClassTypeGone (name1, args1) ctypes ->
VoidnessClassTypeGone (name1, args1) ((name2, args2) :: ctypes)
with VoidnessClassTypePreservesSome : VoidnessClassType -> VoidnessClassTypes -> Prop :=
| vctps_first : forall name args1 args2 ctypes,
VoidnessPreservesPairwise args1 args2 ->
VoidnessClassTypePreservesSome (name, args1) ((name, args2) :: ctypes)
| vctps_rest : forall ctype1 ctype2 ctypes2,
VoidnessClassTypePreservesSome ctype1 ctypes2 ->
VoidnessClassTypePreservesSome ctype1 (ctype2 :: ctypes2).
Hint Constructors
VoidnessPreserves VoidnessPreservesPairwise
VoidnessClassTypesPreserve VoidnessClassTypePreserves
VoidnessClassTypeGone VoidnessClassTypePreservesSome.
Definition TypeVoidnessPreserves (dt1: DartType) (dt2: DartType) : Prop :=
VoidnessPreserves (voidness dt1) (annotationVoidness dt2).
Hint Unfold TypeVoidnessPreserves.
(* ---------- Lasse's relation ---------- *)
Inductive DartSubtype : DartType -> DartType -> Prop :=
| ds_void : forall dt, DartSubtype dt dt_void
| ds_dynamic : forall dt, DartSubtype dt dt_dynamic
| ds_Object : forall dt, DartSubtype dt (dt_class ((Object, nil) :: nil))
| ds_class : forall ctypes1 ctypes2,
DartSubtypesClassTypes ctypes1 ctypes2 ->
DartSubtype (dt_class ctypes1) (dt_class ctypes2)
| ds_function : forall ret1 args1 ret2 args2,
DartSubtype ret1 ret2 ->
DartSubtypePairwise args2 args1 ->
DartSubtype (dt_function ret1 args1) (dt_function ret2 args2)
| ds_variable : forall name,
DartSubtype (dt_variable name) (dt_variable name)
with DartSubtypePairwise : list DartType -> list DartType -> Prop :=
| dsp_nil : DartSubtypePairwise nil nil
| dsp_cons : forall dt1 dts1 dt2 dts2,
DartSubtype dt1 dt2 ->
DartSubtypePairwise dts1 dts2 ->
DartSubtypePairwise (dt1 :: dts1) (dt2 :: dts2)
with DartSubtypesClassTypes : ClassTypes -> ClassTypes -> Prop :=
| dsscts_nil : forall ctypes,
DartSubtypesClassTypes ctypes nil
| dsscts_cons : forall ctypes1 ctype2 ctypes2,
DartSubtypeClassTypes ctypes1 ctype2 ->
DartSubtypesClassTypes ctypes1 ctypes2 ->
DartSubtypesClassTypes ctypes1 (ctype2 :: ctypes2)
with DartSubtypeClassTypes : ClassTypes -> ClassType -> Prop :=
| dscts_first : forall ctype1 ctypes1 ctype2,
DartSubtypeClassType ctype1 ctype2 ->
DartSubtypeClassTypes (ctype1 :: ctypes1) ctype2
| dscts_rest : forall ctype1 ctypes1 ctype2,
DartSubtypeClassTypes ctypes1 ctype2 ->
DartSubtypeClassTypes (ctype1 :: ctypes1) ctype2
with DartSubtypeClassType : ClassType -> ClassType -> Prop :=
| dsct_args: forall name args1 args2,
DartSubtypePairwise args1 args2 ->
DartSubtypeClassType (name, args1) (name, args2).
Hint Constructors
DartSubtype DartSubtypePairwise
DartSubtypesClassTypes DartSubtypeClassTypes DartSubtypeClassType.
Definition DartAssignable (dt1: DartType) (dt2: DartType) : Prop :=
or (DartSubtype dt1 dt2) (DartSubtype dt2 dt1).
Hint Unfold DartAssignable.
Inductive isNotVariableNamed : Name -> DartType -> Prop :=
| invn_void : forall name,
isNotVariableNamed name dt_void
| invn_dynamic : forall name,
isNotVariableNamed name dt_dynamic
| invn_class : forall name ctypes,
isNotVariableNamed name (dt_class ctypes)
| insn_variable : forall name1 name2,
name1 <> name2 ->
isNotVariableNamed name1 (dt_variable name2).
Hint Constructors isNotVariableNamed.
Inductive ClassTypeNamed : Name -> ClassTypes -> ClassType -> Prop :=
| ctn_first : forall name args ctypes,
ClassTypeNamed name ((name, args) :: ctypes) (name, args)
| ctn_rest : forall name1 ctype ctypes name2 args2,
name1 <> name2 ->
ClassTypeNamed name1 ctypes ctype ->
ClassTypeNamed name1 ((name2, args2) :: ctypes) ctype.
Hint Constructors ClassTypeNamed.
(* NotVoidAssignable typeOfSource typeAnnotationOfTarget: `Target x = source;` will cause a loss of voidness *)
Inductive NotVoidAssignable : DartType -> DartType -> Prop :=
| nva_base : forall T,
T <> dt_void ->
T <> dt_dynamic ->
NotVoidAssignable dt_void T
| nva_class : forall ctypes1 ctypes2,
NotVoidAssignableClassTypes ctypes1 ctypes2 ->
NotVoidAssignable (dt_class ctypes1) (dt_class ctypes2)
| nva_function_ret : forall ret1 args1 ret2 args2,
DartAssignable (dt_function ret1 args1) (dt_function ret2 args2) ->
NotVoidAssignable ret1 ret2 ->
NotVoidAssignable (dt_function ret1 args1) (dt_function ret2 args2)
| nva_function_arg : forall ret1 args1 ret2 args2,
DartAssignable (dt_function ret1 args1) (dt_function ret2 args2) ->
NotVoidAssignablePairwise args2 args1 ->
NotVoidAssignable (dt_function ret1 args1) (dt_function ret2 args2)
| nva_variable : forall name dt,
isNotVariableNamed name dt ->
NotVoidAssignable (dt_variable name) dt
(* NotVoidAssignablePairwise types1 types2: At least one pair (type1, type2) causes a loss of voidness *)
with NotVoidAssignablePairwise : list DartType -> list DartType -> Prop :=
| nvap_cons_first : forall dt1 dts1 dt2 dts2,
NotVoidAssignable dt1 dt2 ->
NotVoidAssignablePairwise (dt1 :: dts1) (dt2 :: dts2)
| nvap_cons_rest : forall dt1 dts1 dt2 dts2,
NotVoidAssignablePairwise dts1 dts2 ->
NotVoidAssignablePairwise (dt1 :: dts1) (dt2 :: dts2)
(* NotVoidAssignableClassTypes classTypes1 classTypes2: `"dt_class classTypes2" x = "dt_class classTypes1"-expression` causes loss of voidness *)
with NotVoidAssignableClassTypes : ClassTypes -> ClassTypes -> Prop :=
| nvact_upcast : forall name args1 ctypes1 args2 ctypes2,
DartSubtypesClassTypes ctypes1 ((name, args2) :: ctypes2) -> (* This is an upcast, to (name, args2) :: ctypes2 *)
ClassTypeNamed name ctypes1 (name, args1) -> (* In ctypes1, the type named name is (name, args1) *)
NotVoidAssignablePairwise args1 args2 -> (* At least one type argument is not-void-assignable *)
NotVoidAssignableClassTypes ctypes1 ((name, args2) :: ctypes2)
| nvact_downcast : forall name args1 ctypes1 args2 ctypes2,
DartSubtypesClassTypes ctypes2 ((name, args1) :: ctypes1) -> (* This is a downcast, to ctypes2 *)
ClassTypeNamed name ctypes2 (name, args2) -> (* In ctypes2, the type named name is (name, args2) *)
NotVoidAssignablePairwise args1 args2 -> (* At least one type argument is not-void-assignable *)
NotVoidAssignableClassTypes ((name, args1) :: ctypes1) ctypes2.
Hint Constructors
NotVoidAssignable NotVoidAssignablePairwise NotVoidAssignableClassTypes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment