compose_library/foundations/ops/
mod.rs

1mod equality;
2
3use crate::Value;
4use crate::diag::StrResult;
5use compose_library::Heap;
6pub use compose_library::ops::equality::*;
7use ecow::eco_format;
8
9macro_rules! type_error {
10    ($fmt:expr, $($value:expr),* $(,)?) => {
11        return Err(eco_format!($fmt, $($value.ty()),*).into())
12    };
13}
14
15pub fn add(lhs: &Value, rhs: &Value) -> StrResult<Value> {
16    match (lhs, rhs) {
17        (Value::Int(left), Value::Int(right)) => Ok(Value::Int(left + right)),
18        (Value::Str(left), Value::Str(right)) => Ok(Value::Str(left + right)),
19        (left, right) => type_error!("cannot add {} to {}", left, right),
20    }
21}
22
23pub fn mod_(lhs: &Value, rhs: &Value) -> StrResult<Value> {
24    match (lhs, rhs) {
25        (Value::Int(left), Value::Int(right)) => Ok(Value::Int(left % right)),
26        (left, right) => type_error!("cannot mod {} by {}", left, right),
27    }
28}
29
30pub fn logical_and(lhs: &Value, rhs: &Value) -> StrResult<Value> {
31    match (lhs, rhs) {
32        (Value::Bool(left), Value::Bool(right)) => Ok(Value::Bool(*left && *right)),
33        (left, right) => type_error!("cannot `&&` {} and {}", left, right),
34    }
35}
36
37pub fn logical_or(lhs: &Value, rhs: &Value) -> StrResult<Value> {
38    match (lhs, rhs) {
39        (Value::Bool(left), Value::Bool(right)) => Ok(Value::Bool(*left || *right)),
40        (left, right) => type_error!("cannot `||` {} and {}", left, right),
41    }
42}
43
44pub fn sub(lhs: &Value, rhs: &Value) -> StrResult<Value> {
45    match (lhs, rhs) {
46        (Value::Int(left), Value::Int(right)) => Ok(Value::Int(left - right)),
47        (left, right) => type_error!("cannot subtract {} from {}", left, right),
48    }
49}
50
51pub fn mul(lhs: &Value, rhs: &Value) -> StrResult<Value> {
52    match (lhs, rhs) {
53        (Value::Int(left), Value::Int(right)) => Ok(Value::Int(left * right)),
54        (left, right) => type_error!("cannot multiply {} by {}", left, right),
55    }
56}
57
58pub fn div(lhs: &Value, rhs: &Value) -> StrResult<Value> {
59    match (lhs, rhs) {
60        (Value::Int(left), Value::Int(right)) => Ok(Value::Int(left / right)),
61        (left, right) => type_error!("cannot divide {} by {}", left, right),
62    }
63}
64
65pub fn lt(lhs: &Value, rhs: &Value) -> StrResult<Value> {
66    match (lhs, rhs) {
67        (Value::Int(left), Value::Int(right)) => Ok(Value::Bool(left < right)),
68        (left, right) => type_error!("cannot compare {} to {}", left, right),
69    }
70}
71
72pub fn gt(lhs: &Value, rhs: &Value) -> StrResult<Value> {
73    match (lhs, rhs) {
74        (Value::Int(left), Value::Int(right)) => Ok(Value::Bool(left > right)),
75        (left, right) => type_error!("cannot compare {} to {}", left, right),
76    }
77}
78
79pub fn gte(lhs: &Value, rhs: &Value) -> StrResult<Value> {
80    match (lhs, rhs) {
81        (Value::Int(left), Value::Int(right)) => Ok(Value::Bool(left >= right)),
82        (left, right) => type_error!("cannot compare {} to {}", left, right),
83    }
84}
85
86pub fn neq(lhs: &Value, rhs: &Value, heap: &Heap) -> StrResult<Value> {
87    lhs.not_equals(rhs, heap).map(|eq| Value::Bool(eq))
88}
89
90pub fn eq(lhs: &Value, rhs: &Value, heap: &Heap) -> StrResult<Value> {
91    lhs.equals(rhs, heap).map(Value::Bool)
92}
93
94pub fn unary_plus(value: Value) -> StrResult<Value> {
95    use Value::*;
96    match value {
97        Int(value) => Ok(Int(value)),
98        left => type_error!("cannot take the unary plus of {}", left),
99    }
100}
101
102pub fn unary_minus(value: Value) -> StrResult<Value> {
103    use Value::*;
104    match value {
105        Int(value) => Ok(Int(-value)),
106        left => type_error!("cannot take the unary minus of {}", left),
107    }
108}
109
110pub fn unary_not(value: Value) -> StrResult<Value> {
111    use Value::*;
112    match value {
113        Bool(value) => Ok(Bool(!value)),
114        left => type_error!("cannot take the unary not of {}", left),
115    }
116}
117
118pub fn unary_bitwise_not(value: Value) -> StrResult<Value> {
119    use Value::*;
120    match value {
121        Int(value) => Ok(Int(!value)),
122        left => type_error!("cannot take the unary bitwise not of {}", left),
123    }
124}