3.4. Binary operators
-
CoreCpp.Typing.expr[complete] -
CoreCpp.Eval.expr[complete] -
CoreCpp.BinOp[complete] -
CoreCpp.Eval.binop[complete]
The arithmetic operators require int on both operands. The left operand is evaluated before the right one. Division and remainder truncate toward zero, as in C++, and a zero divisor is error.
\dfrac{\Gamma \vdash e_1 : \mathsf{int} \qquad \Gamma \vdash e_2 : \mathsf{int}}{\Gamma \vdash e_1 \oplus e_2 : \mathsf{int}}\;\textsf{(T-Arith)}, \quad \oplus \in \{+, -, *, /, \%\}
\dfrac{\rho, \sigma \vdash e_1 \Rightarrow \mathsf{int}\,n_1, \sigma_1 \qquad \rho, \sigma_1 \vdash e_2 \Rightarrow \mathsf{int}\,n_2, \sigma_2}{\rho, \sigma \vdash e_1 \oplus e_2 \Rightarrow \mathsf{int32}(n_1 \oplus n_2), \sigma_2}\;\textsf{(Arith)}, \quad \oplus \in \{+, -, *\}
\dfrac{\begin{array}{c} \rho, \sigma \vdash e_1 \Rightarrow \mathsf{int}\,n_1, \sigma_1 \qquad \rho, \sigma_1 \vdash e_2 \Rightarrow \mathsf{int}\,n_2, \sigma_2 \\ n_2 \neq 0 \end{array}}{\rho, \sigma \vdash e_1 \oslash e_2 \Rightarrow \mathsf{int32}(n_1 \oslash n_2), \sigma_2}\;\textsf{(Div)}, \quad \oslash \in \{/, \%\}
\dfrac{\rho, \sigma \vdash e_1 \Rightarrow \mathsf{int}\,n_1, \sigma_1 \qquad \rho, \sigma_1 \vdash e_2 \Rightarrow \mathsf{int}\,0, \sigma_2}{\rho, \sigma \vdash e_1 \oslash e_2 \Rightarrow \mathsf{error}}\;\textsf{(DivZero)}
In the code, the case Binary of Eval.expr evaluates both operands and calls Eval.binop.
Some of the implementations are partial, so Lean records opaque constants that carry the type and not the body, and no property of them is proved here.
Lean code for Definition3.4.1●4 definitions
Associated Lean declarations
-
CoreCpp.Typing.expr[complete]
-
CoreCpp.Eval.expr[complete]
-
CoreCpp.BinOp[complete]
-
CoreCpp.Eval.binop[complete]
-
CoreCpp.Typing.expr[complete] -
CoreCpp.Eval.expr[complete] -
CoreCpp.BinOp[complete] -
CoreCpp.Eval.binop[complete]
-
opaquedefined in CoreCpp/Typing.leancomplete
opaque CoreCpp.Typing.expr (p : CoreCpp.Program) (Γ : CoreCpp.TEnv) : CoreCpp.Expr → CoreCpp.T CoreCpp.Ty
opaque CoreCpp.Typing.expr (p : CoreCpp.Program) (Γ : CoreCpp.TEnv) : CoreCpp.Expr → CoreCpp.T CoreCpp.Ty
Γ ⊢ e : τ
-
opaquedefined in CoreCpp/Eval.leancomplete
opaque CoreCpp.Eval.expr (fs : CoreCpp.FunEnv) (ρ : CoreCpp.Env) (σ : CoreCpp.Store) (e : CoreCpp.Expr) : CoreCpp.M (CoreCpp.Val × CoreCpp.Store)
opaque CoreCpp.Eval.expr (fs : CoreCpp.FunEnv) (ρ : CoreCpp.Env) (σ : CoreCpp.Store) (e : CoreCpp.Expr) : CoreCpp.M (CoreCpp.Val × CoreCpp.Store)
ρ, σ ⊢ e ⇒ v, σ'
-
inductivedefined in CoreCpp/Syntax.leancomplete
inductive CoreCpp.BinOp : Type
inductive CoreCpp.BinOp : Type
Constructors
CoreCpp.BinOp.add : CoreCpp.BinOp
CoreCpp.BinOp.sub : CoreCpp.BinOp
CoreCpp.BinOp.mul : CoreCpp.BinOp
CoreCpp.BinOp.div : CoreCpp.BinOp
CoreCpp.BinOp.mod : CoreCpp.BinOp
CoreCpp.BinOp.eq : CoreCpp.BinOp
CoreCpp.BinOp.ne : CoreCpp.BinOp
CoreCpp.BinOp.lt : CoreCpp.BinOp
CoreCpp.BinOp.le : CoreCpp.BinOp
CoreCpp.BinOp.gt : CoreCpp.BinOp
CoreCpp.BinOp.ge : CoreCpp.BinOp
CoreCpp.BinOp.and : CoreCpp.BinOp
CoreCpp.BinOp.or : CoreCpp.BinOp
-
defdefined in CoreCpp/Eval.leancomplete
def CoreCpp.Eval.binop : CoreCpp.BinOp → CoreCpp.Val → CoreCpp.Val → CoreCpp.M CoreCpp.Val
def CoreCpp.Eval.binop : CoreCpp.BinOp → CoreCpp.Val → CoreCpp.Val → CoreCpp.M CoreCpp.Val
Arithmetic and relational binary operators, on already evaluated values. ``` ρ, σ ⊢ e₁ ⇒ int n₁, σ₁ ρ, σ₁ ⊢ e₂ ⇒ int n₂, σ₂ ──────────────────────────────────────────────── (Arith, ⊕ ∈ {+, −, ×}) ρ, σ ⊢ e₁ ⊕ e₂ ⇒ int32 (n₁ ⊕ n₂), σ₂ ``` ``` ρ, σ ⊢ e₁ ⇒ int n₁, σ₁ ρ, σ₁ ⊢ e₂ ⇒ int n₂, σ₂ n₂ ≠ 0 ──────────────────────────────────────────────────────── (Div, ⊘ ∈ {/, %}) ρ, σ ⊢ e₁ ⊘ e₂ ⇒ int32 (n₁ ⊘ n₂), σ₂ division truncates toward zero, as in C++ ``` ``` ρ, σ ⊢ e₁ ⇒ int n₁, σ₁ ρ, σ₁ ⊢ e₂ ⇒ int 0, σ₂ ──────────────────────────────────────────────── (DivZero) ρ, σ ⊢ e₁ ⊘ e₂ ⇒ error (division by zero) ``` ``` ρ, σ ⊢ e₁ ⇒ v₁, σ₁ ρ, σ₁ ⊢ e₂ ⇒ v₂, σ₂ ─────────────────────────────────────────── (Rel, ⋈ ∈ {==, !=, <, <=, >, >=}) ρ, σ ⊢ e₁ ⋈ e₂ ⇒ bool (v₁ ⋈ v₂), σ₂ ``` Two pointers are equal when they are the same location. nullptr equals only nullptr. There is no order on pointers. The left operand is evaluated before the right one, the Core C++ choice where C++17 does not specify the order.
-
CoreCpp.Typing.expr[complete] -
CoreCpp.Eval.expr[complete] -
CoreCpp.Eval.binop[complete] -
CoreCpp.Typing.compat[complete]
Equality compares two int, two bool or two pointers, and nullptr against a pointer, the relation \tau_1 \approx \tau_2. Two pointers are equal when they are the same location, and nullptr equals only nullptr. Order compares two int, there is no order on pointers. The result is bool.
\dfrac{\begin{array}{c} \Gamma \vdash e_1 : \tau_1 \qquad \Gamma \vdash e_2 : \tau_2 \qquad \tau_1 \approx \tau_2 \\ \tau_1, \tau_2 \in \{\mathsf{int}, \mathsf{bool}, \tau*, \mathsf{nullptr\_t}\} \end{array}}{\Gamma \vdash e_1 \bowtie e_2 : \mathsf{bool}}\;\textsf{(T-Eq)}, \quad \bowtie \in \{==, \mathrel{!=}\}
\dfrac{\Gamma \vdash e_1 : \mathsf{int} \qquad \Gamma \vdash e_2 : \mathsf{int}}{\Gamma \vdash e_1 \bowtie e_2 : \mathsf{bool}}\;\textsf{(T-Rel)}, \quad \bowtie \in \{<, <=, >, >=\}
\dfrac{\rho, \sigma \vdash e_1 \Rightarrow v_1, \sigma_1 \qquad \rho, \sigma_1 \vdash e_2 \Rightarrow v_2, \sigma_2}{\rho, \sigma \vdash e_1 \bowtie e_2 \Rightarrow \mathsf{bool}(v_1 \bowtie v_2), \sigma_2}\;\textsf{(Rel)}
Some of the implementations are partial, so Lean records opaque constants that carry the type and not the body, and no property of them is proved here.
Lean code for Definition3.4.2●4 definitions
Associated Lean declarations
-
CoreCpp.Typing.expr[complete]
-
CoreCpp.Eval.expr[complete]
-
CoreCpp.Eval.binop[complete]
-
CoreCpp.Typing.compat[complete]
-
CoreCpp.Typing.expr[complete] -
CoreCpp.Eval.expr[complete] -
CoreCpp.Eval.binop[complete] -
CoreCpp.Typing.compat[complete]
-
opaquedefined in CoreCpp/Typing.leancomplete
opaque CoreCpp.Typing.expr (p : CoreCpp.Program) (Γ : CoreCpp.TEnv) : CoreCpp.Expr → CoreCpp.T CoreCpp.Ty
opaque CoreCpp.Typing.expr (p : CoreCpp.Program) (Γ : CoreCpp.TEnv) : CoreCpp.Expr → CoreCpp.T CoreCpp.Ty
Γ ⊢ e : τ
-
opaquedefined in CoreCpp/Eval.leancomplete
opaque CoreCpp.Eval.expr (fs : CoreCpp.FunEnv) (ρ : CoreCpp.Env) (σ : CoreCpp.Store) (e : CoreCpp.Expr) : CoreCpp.M (CoreCpp.Val × CoreCpp.Store)
opaque CoreCpp.Eval.expr (fs : CoreCpp.FunEnv) (ρ : CoreCpp.Env) (σ : CoreCpp.Store) (e : CoreCpp.Expr) : CoreCpp.M (CoreCpp.Val × CoreCpp.Store)
ρ, σ ⊢ e ⇒ v, σ'
-
defdefined in CoreCpp/Eval.leancomplete
def CoreCpp.Eval.binop : CoreCpp.BinOp → CoreCpp.Val → CoreCpp.Val → CoreCpp.M CoreCpp.Val
def CoreCpp.Eval.binop : CoreCpp.BinOp → CoreCpp.Val → CoreCpp.Val → CoreCpp.M CoreCpp.Val
Arithmetic and relational binary operators, on already evaluated values. ``` ρ, σ ⊢ e₁ ⇒ int n₁, σ₁ ρ, σ₁ ⊢ e₂ ⇒ int n₂, σ₂ ──────────────────────────────────────────────── (Arith, ⊕ ∈ {+, −, ×}) ρ, σ ⊢ e₁ ⊕ e₂ ⇒ int32 (n₁ ⊕ n₂), σ₂ ``` ``` ρ, σ ⊢ e₁ ⇒ int n₁, σ₁ ρ, σ₁ ⊢ e₂ ⇒ int n₂, σ₂ n₂ ≠ 0 ──────────────────────────────────────────────────────── (Div, ⊘ ∈ {/, %}) ρ, σ ⊢ e₁ ⊘ e₂ ⇒ int32 (n₁ ⊘ n₂), σ₂ division truncates toward zero, as in C++ ``` ``` ρ, σ ⊢ e₁ ⇒ int n₁, σ₁ ρ, σ₁ ⊢ e₂ ⇒ int 0, σ₂ ──────────────────────────────────────────────── (DivZero) ρ, σ ⊢ e₁ ⊘ e₂ ⇒ error (division by zero) ``` ``` ρ, σ ⊢ e₁ ⇒ v₁, σ₁ ρ, σ₁ ⊢ e₂ ⇒ v₂, σ₂ ─────────────────────────────────────────── (Rel, ⋈ ∈ {==, !=, <, <=, >, >=}) ρ, σ ⊢ e₁ ⋈ e₂ ⇒ bool (v₁ ⋈ v₂), σ₂ ``` Two pointers are equal when they are the same location. nullptr equals only nullptr. There is no order on pointers. The left operand is evaluated before the right one, the Core C++ choice where C++17 does not specify the order. -
defdefined in CoreCpp/Typing.leancomplete
def CoreCpp.Typing.compat (p : CoreCpp.Program) : CoreCpp.Ty → CoreCpp.Ty → Bool
def CoreCpp.Typing.compat (p : CoreCpp.Program) : CoreCpp.Ty → CoreCpp.Ty → Bool
τ ≈ τ', the type τ of a value is accepted where τ' is expected. Equal types, nullptr against a pointer type, or, by subsumption, a pointer to a derived class where a pointer to its base is expected. These and the lambda to `std::function` are the only implicit conversions. ``` D derives from B ──────────────── (Subsumption) D* ≈ B* ``` ``` Γ ⊢ e : D* D derives from B ────────────────────────────── (T-Sub) subsumption where a value is Γ ⊢ e : B* used, wherever ≈ is required ```
-
CoreCpp.Typing.expr[complete] -
CoreCpp.Eval.expr[complete]
Conjunction and disjunction require bool and short circuit. The second operand is evaluated only when the first one does not decide the result.
\dfrac{\Gamma \vdash e_1 : \mathsf{bool} \qquad \Gamma \vdash e_2 : \mathsf{bool}}{\Gamma \vdash e_1 \odot e_2 : \mathsf{bool}}\;\textsf{(T-Logic)}, \quad \odot \in \{\&\&, ||\}
\dfrac{\rho, \sigma \vdash e_1 \Rightarrow \mathsf{bool}\,\mathtt{false}, \sigma_1}{\rho, \sigma \vdash e_1 \mathbin{\&\&} e_2 \Rightarrow \mathsf{bool}\,\mathtt{false}, \sigma_1}\;\textsf{(And-False)}
\dfrac{\rho, \sigma \vdash e_1 \Rightarrow \mathsf{bool}\,\mathtt{true}, \sigma_1 \qquad \rho, \sigma_1 \vdash e_2 \Rightarrow v, \sigma_2}{\rho, \sigma \vdash e_1 \mathbin{\&\&} e_2 \Rightarrow v, \sigma_2}\;\textsf{(And-True)}
\dfrac{\rho, \sigma \vdash e_1 \Rightarrow \mathsf{bool}\,\mathtt{true}, \sigma_1}{\rho, \sigma \vdash e_1 \mathbin{||} e_2 \Rightarrow \mathsf{bool}\,\mathtt{true}, \sigma_1}\;\textsf{(Or-True)}
\dfrac{\rho, \sigma \vdash e_1 \Rightarrow \mathsf{bool}\,\mathtt{false}, \sigma_1 \qquad \rho, \sigma_1 \vdash e_2 \Rightarrow v, \sigma_2}{\rho, \sigma \vdash e_1 \mathbin{||} e_2 \Rightarrow v, \sigma_2}\;\textsf{(Or-False)}
In the code, the cases And and Or of Eval.expr implement the two pairs of rules.
The implementations are partial, so Lean records opaque constants that carry the type and not the body, and no property of them is proved here.
Lean code for Definition3.4.3●2 definitions
Associated Lean declarations
-
CoreCpp.Typing.expr[complete]
-
CoreCpp.Eval.expr[complete]
-
CoreCpp.Typing.expr[complete] -
CoreCpp.Eval.expr[complete]
-
opaquedefined in CoreCpp/Typing.leancomplete
opaque CoreCpp.Typing.expr (p : CoreCpp.Program) (Γ : CoreCpp.TEnv) : CoreCpp.Expr → CoreCpp.T CoreCpp.Ty
opaque CoreCpp.Typing.expr (p : CoreCpp.Program) (Γ : CoreCpp.TEnv) : CoreCpp.Expr → CoreCpp.T CoreCpp.Ty
Γ ⊢ e : τ
-
opaquedefined in CoreCpp/Eval.leancomplete
opaque CoreCpp.Eval.expr (fs : CoreCpp.FunEnv) (ρ : CoreCpp.Env) (σ : CoreCpp.Store) (e : CoreCpp.Expr) : CoreCpp.M (CoreCpp.Val × CoreCpp.Store)
opaque CoreCpp.Eval.expr (fs : CoreCpp.FunEnv) (ρ : CoreCpp.Env) (σ : CoreCpp.Store) (e : CoreCpp.Expr) : CoreCpp.M (CoreCpp.Val × CoreCpp.Store)
ρ, σ ⊢ e ⇒ v, σ'