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