compose_library/foundations/
ops.rs

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