aboutsummaryrefslogtreecommitdiffstats
path: root/binop.v
blob: c8f87fd520577835de741fec3e5a880c214dc542 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
Require Import Coq.NArith.BinNat.
Require Import Coq.Strings.Ascii.
Require Import Coq.Strings.String.
From stdpp Require Import fin_sets gmap option.
From mininix Require Import expr maptools shared.

Open Scope string_scope.
Open Scope N_scope.
Open Scope Z_scope.
Open Scope nat_scope.

Definition right_union {A} (bs1 bs2 : gmap string A) : gmap string A :=
  bs2 ∪ bs1.

Variant binop_r : op → value → value → value → Prop :=
  | Bo_PlusInt n1 n2 : binop_r O_Plus (V_Int n1) (V_Int n2) (V_Int (n1 + n2))
  | Bo_PlusStr s1 s2 : binop_r O_Plus (V_Str s1) (V_Str s2) (V_Str (s1 ++ s2))
  | Bo_MinInt n1 n2 : binop_r O_Min (V_Int n1) (V_Int n2) (V_Int (n1 - n2))
  | Bo_UpdAttrset bs1 bs2 :
      binop_r O_Upd (V_Attrset bs1) (V_Attrset bs2)
        (V_Attrset (right_union bs1 bs2))
  | Bo_Eq v1 v2 : binop_r O_Eq v1 v2 (expr_eq v1 v2)
  | Bo_DivInt (n1 n2 : Z) : n2 ≠ 0%Z → binop_r O_Div n1 n2 (n1 / n2)%Z
  | Bo_LtInt (n1 n2 : Z) : binop_r O_Lt n1 n2 (bool_decide (n1 < n2)%Z)
  | Bo_LtStr s1 s2 : binop_r O_Lt (V_Str s1) (V_Str s2) (string_lt s1 s2).

Notation "u1 '⟦' op '⟧' u2 '-⊚->' v" := (binop_r op u1 u2 v) (at level 55).

Definition binop_eval (op : op) (v1 v2 : value) : option value :=
  match op with
  | O_Plus =>
      match v1, v2 with
      | V_Int n1, V_Int n2 => Some (V_Int (n1 + n2))
      | V_Str s1, V_Str s2 => Some (V_Str (s1 ++ s2))
      | _, _ => None
      end
  | O_Min =>
      match v1, v2 with
      | V_Int n1, V_Int n2 => Some (V_Int (n1 - n2))
      | _, _ => None
      end
  | O_Upd =>
      match v1, v2 with
      | V_Attrset bs1, V_Attrset bs2 =>
          Some (V_Attrset (right_union bs1 bs2))
      | _, _ => None
      end
  | O_Eq => Some (V_Bool (expr_eq (X_V v1) (X_V v2)))
  | O_Div =>
      match v1, v2 with
      | V_Int n1, V_Int n2 =>
          if decide (n2 = 0)%Z
          then None
          else Some (V_Int (n1 / n2)%Z)
      | _, _ => None
      end
  | O_Lt =>
      match v1, v2 with
      | V_Int n1, V_Int n2 => Some (V_Bool (bool_decide (n1 < n2)%Z))
      | V_Str s1, V_Str s2 => Some (V_Bool (string_lt s1 s2))
      | _, _ => None
      end
  end.

Theorem binop_eval_sound op u1 u2 v :
  binop_eval op u1 u2 = Some v → binop_r op u1 u2 v.
Proof.
  intros Heval.
  destruct op, u1, u2; try discriminate; simplify_eq/=; try constructor.
  destruct (decide (n0 = 0)%Z); try discriminate.
  simplify_eq/=. by constructor.
Qed.

Theorem binop_eval_complete op u1 u2 v :
  binop_r op u1 u2 v → binop_eval op u1 u2 = Some v.
Proof.
  intros Heval. inv Heval; try done.
  unfold binop_eval. by apply decide_False.
Qed.

Theorem binop_deterministic op u1 u2 v1 v2 :
  u1 ⟦op⟧ u2 --> v1 → u1 ⟦op⟧ u2 --> v2 → v1 = v2.
Proof.
  intros Heval1 Heval2.
  apply binop_eval_complete in Heval1, Heval2.
  congruence.
Qed.