compose_library/foundations/
ops.rs1use 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}