@@ -183,6 +183,24 @@ inductive HasType : TypeEnv → Expr → WokeType → Prop where
183183 | tMulInt : ∀ Γ e₁ e₂,
184184 HasType Γ e₁ .int → HasType Γ e₂ .int →
185185 HasType Γ (.binOp .mul e₁ e₂) .int
186+ | tLt : ∀ Γ e₁ e₂,
187+ HasType Γ e₁ .int → HasType Γ e₂ .int →
188+ HasType Γ (.binOp .lt e₁ e₂) .bool
189+ | tGt : ∀ Γ e₁ e₂,
190+ HasType Γ e₁ .int → HasType Γ e₂ .int →
191+ HasType Γ (.binOp .gt e₁ e₂) .bool
192+ | tLe : ∀ Γ e₁ e₂,
193+ HasType Γ e₁ .int → HasType Γ e₂ .int →
194+ HasType Γ (.binOp .le e₁ e₂) .bool
195+ | tGe : ∀ Γ e₁ e₂,
196+ HasType Γ e₁ .int → HasType Γ e₂ .int →
197+ HasType Γ (.binOp .ge e₁ e₂) .bool
198+ | tDivInt : ∀ Γ e₁ e₂,
199+ HasType Γ e₁ .int → HasType Γ e₂ .int →
200+ HasType Γ (.binOp .div e₁ e₂) .int
201+ | tModInt : ∀ Γ e₁ e₂,
202+ HasType Γ e₁ .int → HasType Γ e₂ .int →
203+ HasType Γ (.binOp .mod e₁ e₂) .int
186204 | tNegInt : ∀ Γ e,
187205 HasType Γ e .int →
188206 HasType Γ (.unOp .neg e) .int
@@ -262,6 +280,30 @@ inductive Step : Expr → Env → Expr → Env → Prop where
262280 | sMulInt : ∀ n₁ n₂ ρ,
263281 Step (.binOp .mul (.lit (.vInt n₁)) (.lit (.vInt n₂))) ρ
264282 (.lit (.vInt (n₁ * n₂))) ρ
283+ | sLt : ∀ n₁ n₂ ρ,
284+ Step (.binOp .lt (.lit (.vInt n₁)) (.lit (.vInt n₂))) ρ
285+ (.lit (.vBool (decide (n₁ < n₂)))) ρ
286+ | sGt : ∀ n₁ n₂ ρ,
287+ Step (.binOp .gt (.lit (.vInt n₁)) (.lit (.vInt n₂))) ρ
288+ (.lit (.vBool (decide (n₁ > n₂)))) ρ
289+ | sLe : ∀ n₁ n₂ ρ,
290+ Step (.binOp .le (.lit (.vInt n₁)) (.lit (.vInt n₂))) ρ
291+ (.lit (.vBool (decide (n₁ ≤ n₂)))) ρ
292+ | sGe : ∀ n₁ n₂ ρ,
293+ Step (.binOp .ge (.lit (.vInt n₁)) (.lit (.vInt n₂))) ρ
294+ (.lit (.vBool (decide (n₁ ≥ n₂)))) ρ
295+ | sDivInt : ∀ n₁ n₂ ρ, n₂ ≠ 0 →
296+ Step (.binOp .div (.lit (.vInt n₁)) (.lit (.vInt n₂))) ρ
297+ (.lit (.vInt (n₁ / n₂))) ρ
298+ | sDivZero : ∀ n₁ n₂ ρ, n₂ = 0 →
299+ Step (.binOp .div (.lit (.vInt n₁)) (.lit (.vInt n₂))) ρ
300+ (.error "Division by zero" ) ρ
301+ | sModInt : ∀ n₁ n₂ ρ, n₂ ≠ 0 →
302+ Step (.binOp .mod (.lit (.vInt n₁)) (.lit (.vInt n₂))) ρ
303+ (.lit (.vInt (n₁ % n₂))) ρ
304+ | sModZero : ∀ n₁ n₂ ρ, n₂ = 0 →
305+ Step (.binOp .mod (.lit (.vInt n₁)) (.lit (.vInt n₂))) ρ
306+ (.error "Modulo by zero" ) ρ
265307 | sUnOpCong : ∀ op e e' ρ ρ',
266308 Step e ρ e' ρ' →
267309 Step (.unOp op e) ρ (.unOp op e') ρ'
@@ -554,6 +596,154 @@ theorem progress : ∀ e t,
554596 | inr hstp =>
555597 obtain ⟨e₁', ρ', hs₁⟩ := hstp
556598 exact ⟨.binOp .mul e₁' e₂, ρ', .sBinOpLeft .mul _ e₁' e₂ emptyEnv ρ' hs₁⟩
599+ | tLt e₁ e₂ h₁ h₂ ih₁ ih₂ =>
600+ right
601+ cases ih₁ with
602+ | inl hv₁ =>
603+ cases hv₁ with
604+ | lit v₁ =>
605+ cases ih₂ with
606+ | inl hv₂ =>
607+ cases hv₂ with
608+ | lit v₂ =>
609+ have ⟨n₁, hn₁⟩ := canonical_forms_int v₁ h₁
610+ have ⟨n₂, hn₂⟩ := canonical_forms_int v₂ h₂
611+ subst hn₁; subst hn₂
612+ exact ⟨.lit (.vBool (decide (n₁ < n₂))), emptyEnv, .sLt n₁ n₂ emptyEnv⟩
613+ | error msg =>
614+ exact ⟨.error msg, emptyEnv, .sBinOpErrRight .lt v₁ msg emptyEnv⟩
615+ | inr hstp =>
616+ obtain ⟨e₂', ρ', hs₂⟩ := hstp
617+ exact ⟨.binOp .lt (.lit v₁) e₂', ρ', .sBinOpRight .lt v₁ _ e₂' emptyEnv ρ' (.lit v₁) hs₂⟩
618+ | error msg =>
619+ exact ⟨.error msg, emptyEnv, .sBinOpErrLeft .lt msg e₂ emptyEnv⟩
620+ | inr hstp =>
621+ obtain ⟨e₁', ρ', hs₁⟩ := hstp
622+ exact ⟨.binOp .lt e₁' e₂, ρ', .sBinOpLeft .lt _ e₁' e₂ emptyEnv ρ' hs₁⟩
623+ | tGt e₁ e₂ h₁ h₂ ih₁ ih₂ =>
624+ right
625+ cases ih₁ with
626+ | inl hv₁ =>
627+ cases hv₁ with
628+ | lit v₁ =>
629+ cases ih₂ with
630+ | inl hv₂ =>
631+ cases hv₂ with
632+ | lit v₂ =>
633+ have ⟨n₁, hn₁⟩ := canonical_forms_int v₁ h₁
634+ have ⟨n₂, hn₂⟩ := canonical_forms_int v₂ h₂
635+ subst hn₁; subst hn₂
636+ exact ⟨.lit (.vBool (decide (n₁ > n₂))), emptyEnv, .sGt n₁ n₂ emptyEnv⟩
637+ | error msg =>
638+ exact ⟨.error msg, emptyEnv, .sBinOpErrRight .gt v₁ msg emptyEnv⟩
639+ | inr hstp =>
640+ obtain ⟨e₂', ρ', hs₂⟩ := hstp
641+ exact ⟨.binOp .gt (.lit v₁) e₂', ρ', .sBinOpRight .gt v₁ _ e₂' emptyEnv ρ' (.lit v₁) hs₂⟩
642+ | error msg =>
643+ exact ⟨.error msg, emptyEnv, .sBinOpErrLeft .gt msg e₂ emptyEnv⟩
644+ | inr hstp =>
645+ obtain ⟨e₁', ρ', hs₁⟩ := hstp
646+ exact ⟨.binOp .gt e₁' e₂, ρ', .sBinOpLeft .gt _ e₁' e₂ emptyEnv ρ' hs₁⟩
647+ | tLe e₁ e₂ h₁ h₂ ih₁ ih₂ =>
648+ right
649+ cases ih₁ with
650+ | inl hv₁ =>
651+ cases hv₁ with
652+ | lit v₁ =>
653+ cases ih₂ with
654+ | inl hv₂ =>
655+ cases hv₂ with
656+ | lit v₂ =>
657+ have ⟨n₁, hn₁⟩ := canonical_forms_int v₁ h₁
658+ have ⟨n₂, hn₂⟩ := canonical_forms_int v₂ h₂
659+ subst hn₁; subst hn₂
660+ exact ⟨.lit (.vBool (decide (n₁ ≤ n₂))), emptyEnv, .sLe n₁ n₂ emptyEnv⟩
661+ | error msg =>
662+ exact ⟨.error msg, emptyEnv, .sBinOpErrRight .le v₁ msg emptyEnv⟩
663+ | inr hstp =>
664+ obtain ⟨e₂', ρ', hs₂⟩ := hstp
665+ exact ⟨.binOp .le (.lit v₁) e₂', ρ', .sBinOpRight .le v₁ _ e₂' emptyEnv ρ' (.lit v₁) hs₂⟩
666+ | error msg =>
667+ exact ⟨.error msg, emptyEnv, .sBinOpErrLeft .le msg e₂ emptyEnv⟩
668+ | inr hstp =>
669+ obtain ⟨e₁', ρ', hs₁⟩ := hstp
670+ exact ⟨.binOp .le e₁' e₂, ρ', .sBinOpLeft .le _ e₁' e₂ emptyEnv ρ' hs₁⟩
671+ | tGe e₁ e₂ h₁ h₂ ih₁ ih₂ =>
672+ right
673+ cases ih₁ with
674+ | inl hv₁ =>
675+ cases hv₁ with
676+ | lit v₁ =>
677+ cases ih₂ with
678+ | inl hv₂ =>
679+ cases hv₂ with
680+ | lit v₂ =>
681+ have ⟨n₁, hn₁⟩ := canonical_forms_int v₁ h₁
682+ have ⟨n₂, hn₂⟩ := canonical_forms_int v₂ h₂
683+ subst hn₁; subst hn₂
684+ exact ⟨.lit (.vBool (decide (n₁ ≥ n₂))), emptyEnv, .sGe n₁ n₂ emptyEnv⟩
685+ | error msg =>
686+ exact ⟨.error msg, emptyEnv, .sBinOpErrRight .ge v₁ msg emptyEnv⟩
687+ | inr hstp =>
688+ obtain ⟨e₂', ρ', hs₂⟩ := hstp
689+ exact ⟨.binOp .ge (.lit v₁) e₂', ρ', .sBinOpRight .ge v₁ _ e₂' emptyEnv ρ' (.lit v₁) hs₂⟩
690+ | error msg =>
691+ exact ⟨.error msg, emptyEnv, .sBinOpErrLeft .ge msg e₂ emptyEnv⟩
692+ | inr hstp =>
693+ obtain ⟨e₁', ρ', hs₁⟩ := hstp
694+ exact ⟨.binOp .ge e₁' e₂, ρ', .sBinOpLeft .ge _ e₁' e₂ emptyEnv ρ' hs₁⟩
695+ | tDivInt e₁ e₂ h₁ h₂ ih₁ ih₂ =>
696+ right
697+ cases ih₁ with
698+ | inl hv₁ =>
699+ cases hv₁ with
700+ | lit v₁ =>
701+ cases ih₂ with
702+ | inl hv₂ =>
703+ cases hv₂ with
704+ | lit v₂ =>
705+ have ⟨n₁, hn₁⟩ := canonical_forms_int v₁ h₁
706+ have ⟨n₂, hn₂⟩ := canonical_forms_int v₂ h₂
707+ subst hn₁; subst hn₂
708+ by_cases hz : n₂ = 0
709+ · exact ⟨.error "Division by zero" , emptyEnv, .sDivZero n₁ n₂ emptyEnv hz⟩
710+ · exact ⟨.lit (.vInt (n₁ / n₂)), emptyEnv, .sDivInt n₁ n₂ emptyEnv hz⟩
711+ | error msg =>
712+ exact ⟨.error msg, emptyEnv, .sBinOpErrRight .div v₁ msg emptyEnv⟩
713+ | inr hstp =>
714+ obtain ⟨e₂', ρ', hs₂⟩ := hstp
715+ exact ⟨.binOp .div (.lit v₁) e₂', ρ', .sBinOpRight .div v₁ _ e₂' emptyEnv ρ' (.lit v₁) hs₂⟩
716+ | error msg =>
717+ exact ⟨.error msg, emptyEnv, .sBinOpErrLeft .div msg e₂ emptyEnv⟩
718+ | inr hstp =>
719+ obtain ⟨e₁', ρ', hs₁⟩ := hstp
720+ exact ⟨.binOp .div e₁' e₂, ρ', .sBinOpLeft .div _ e₁' e₂ emptyEnv ρ' hs₁⟩
721+ | tModInt e₁ e₂ h₁ h₂ ih₁ ih₂ =>
722+ right
723+ cases ih₁ with
724+ | inl hv₁ =>
725+ cases hv₁ with
726+ | lit v₁ =>
727+ cases ih₂ with
728+ | inl hv₂ =>
729+ cases hv₂ with
730+ | lit v₂ =>
731+ have ⟨n₁, hn₁⟩ := canonical_forms_int v₁ h₁
732+ have ⟨n₂, hn₂⟩ := canonical_forms_int v₂ h₂
733+ subst hn₁; subst hn₂
734+ by_cases hz : n₂ = 0
735+ · exact ⟨.error "Modulo by zero" , emptyEnv, .sModZero n₁ n₂ emptyEnv hz⟩
736+ · exact ⟨.lit (.vInt (n₁ % n₂)), emptyEnv, .sModInt n₁ n₂ emptyEnv hz⟩
737+ | error msg =>
738+ exact ⟨.error msg, emptyEnv, .sBinOpErrRight .mod v₁ msg emptyEnv⟩
739+ | inr hstp =>
740+ obtain ⟨e₂', ρ', hs₂⟩ := hstp
741+ exact ⟨.binOp .mod (.lit v₁) e₂', ρ', .sBinOpRight .mod v₁ _ e₂' emptyEnv ρ' (.lit v₁) hs₂⟩
742+ | error msg =>
743+ exact ⟨.error msg, emptyEnv, .sBinOpErrLeft .mod msg e₂ emptyEnv⟩
744+ | inr hstp =>
745+ obtain ⟨e₁', ρ', hs₁⟩ := hstp
746+ exact ⟨.binOp .mod e₁' e₂, ρ', .sBinOpLeft .mod _ e₁' e₂ emptyEnv ρ' hs₁⟩
557747 | tNegInt e h₁ ih =>
558748 right
559749 cases ih with
@@ -676,6 +866,12 @@ theorem preservation : ∀ e e' t ρ ρ',
676866 | tOr _ _ h₁ h₂ => exact .tOr _ _ _ (ih _ h₁) h₂
677867 | tSubInt _ _ h₁ h₂ => exact .tSubInt _ _ _ (ih _ h₁) h₂
678868 | tMulInt _ _ h₁ h₂ => exact .tMulInt _ _ _ (ih _ h₁) h₂
869+ | tLt _ _ h₁ h₂ => exact .tLt _ _ _ (ih _ h₁) h₂
870+ | tGt _ _ h₁ h₂ => exact .tGt _ _ _ (ih _ h₁) h₂
871+ | tLe _ _ h₁ h₂ => exact .tLe _ _ _ (ih _ h₁) h₂
872+ | tGe _ _ h₁ h₂ => exact .tGe _ _ _ (ih _ h₁) h₂
873+ | tDivInt _ _ h₁ h₂ => exact .tDivInt _ _ _ (ih _ h₁) h₂
874+ | tModInt _ _ h₁ h₂ => exact .tModInt _ _ _ (ih _ h₁) h₂
679875 | sBinOpRight op v₁ e₂ e₂' ρ ρ' _hv hs₂ ih =>
680876 cases ht with
681877 | tAddInt _ _ h₁ h₂ => exact .tAddInt _ _ _ h₁ (ih _ h₂)
@@ -686,6 +882,12 @@ theorem preservation : ∀ e e' t ρ ρ',
686882 | tOr _ _ h₁ h₂ => exact .tOr _ _ _ h₁ (ih _ h₂)
687883 | tSubInt _ _ h₁ h₂ => exact .tSubInt _ _ _ h₁ (ih _ h₂)
688884 | tMulInt _ _ h₁ h₂ => exact .tMulInt _ _ _ h₁ (ih _ h₂)
885+ | tLt _ _ h₁ h₂ => exact .tLt _ _ _ h₁ (ih _ h₂)
886+ | tGt _ _ h₁ h₂ => exact .tGt _ _ _ h₁ (ih _ h₂)
887+ | tLe _ _ h₁ h₂ => exact .tLe _ _ _ h₁ (ih _ h₂)
888+ | tGe _ _ h₁ h₂ => exact .tGe _ _ _ h₁ (ih _ h₂)
889+ | tDivInt _ _ h₁ h₂ => exact .tDivInt _ _ _ h₁ (ih _ h₂)
890+ | tModInt _ _ h₁ h₂ => exact .tModInt _ _ _ h₁ (ih _ h₂)
689891 | sAddInt n₁ n₂ _ =>
690892 cases ht with
691893 | tAddInt _ _ h₁ h₂ => exact .tInt _ _
@@ -719,6 +921,30 @@ theorem preservation : ∀ e e' t ρ ρ',
719921 | sMulInt n₁ n₂ _ =>
720922 cases ht with
721923 | tMulInt _ _ h₁ h₂ => exact .tInt _ _
924+ | sLt n₁ n₂ _ =>
925+ cases ht with
926+ | tLt _ _ h₁ h₂ => exact .tBool _ _
927+ | sGt n₁ n₂ _ =>
928+ cases ht with
929+ | tGt _ _ h₁ h₂ => exact .tBool _ _
930+ | sLe n₁ n₂ _ =>
931+ cases ht with
932+ | tLe _ _ h₁ h₂ => exact .tBool _ _
933+ | sGe n₁ n₂ _ =>
934+ cases ht with
935+ | tGe _ _ h₁ h₂ => exact .tBool _ _
936+ | sDivInt n₁ n₂ _ _ =>
937+ cases ht with
938+ | tDivInt _ _ h₁ h₂ => exact .tInt _ _
939+ | sDivZero n₁ n₂ _ _ =>
940+ cases ht with
941+ | tDivInt _ _ h₁ h₂ => exact .tError _ _ _
942+ | sModInt n₁ n₂ _ _ =>
943+ cases ht with
944+ | tModInt _ _ h₁ h₂ => exact .tInt _ _
945+ | sModZero n₁ n₂ _ _ =>
946+ cases ht with
947+ | tModInt _ _ h₁ h₂ => exact .tError _ _ _
722948 | sNegInt n _ =>
723949 cases ht with
724950 | tNegInt _ h₁ => exact .tInt _ _
@@ -774,6 +1000,12 @@ theorem preservation : ∀ e e' t ρ ρ',
7741000 | tOr _ _ h₁ h₂ => exact .tError _ msg _
7751001 | tSubInt _ _ h₁ h₂ => exact .tError _ msg _
7761002 | tMulInt _ _ h₁ h₂ => exact .tError _ msg _
1003+ | tLt _ _ h₁ h₂ => exact .tError _ msg _
1004+ | tGt _ _ h₁ h₂ => exact .tError _ msg _
1005+ | tLe _ _ h₁ h₂ => exact .tError _ msg _
1006+ | tGe _ _ h₁ h₂ => exact .tError _ msg _
1007+ | tDivInt _ _ h₁ h₂ => exact .tError _ msg _
1008+ | tModInt _ _ h₁ h₂ => exact .tError _ msg _
7771009 | sBinOpErrRight op v₁ msg _ =>
7781010 cases ht with
7791011 | tAddInt _ _ h₁ h₂ => exact .tError _ msg _
@@ -784,6 +1016,12 @@ theorem preservation : ∀ e e' t ρ ρ',
7841016 | tOr _ _ h₁ h₂ => exact .tError _ msg _
7851017 | tSubInt _ _ h₁ h₂ => exact .tError _ msg _
7861018 | tMulInt _ _ h₁ h₂ => exact .tError _ msg _
1019+ | tLt _ _ h₁ h₂ => exact .tError _ msg _
1020+ | tGt _ _ h₁ h₂ => exact .tError _ msg _
1021+ | tLe _ _ h₁ h₂ => exact .tError _ msg _
1022+ | tGe _ _ h₁ h₂ => exact .tError _ msg _
1023+ | tDivInt _ _ h₁ h₂ => exact .tError _ msg _
1024+ | tModInt _ _ h₁ h₂ => exact .tError _ msg _
7871025 | sUnOpErr op msg _ =>
7881026 cases ht with
7891027 | tNegInt _ h₁ => exact .tError _ msg _
0 commit comments