diff options
| author | Edvard Thörnros <edvard.thornros@gmail.com> | 2021-01-31 20:25:06 +0100 |
|---|---|---|
| committer | Edvard Thörnros <edvard.thornros@gmail.com> | 2021-01-31 20:25:06 +0100 |
| commit | bdcdbf7d65b7a05216c33f802f1f1646e1f68718 (patch) | |
| tree | bd8bc20f2f7200e30fe19381e611f89fd03800b3 /src/lib.rs | |
| parent | 28c22a38c465a68f875f27e7190703ef5da4401b (diff) | |
| download | sylt-bdcdbf7d65b7a05216c33f802f1f1646e1f68718.tar.gz | |
basic arithmatic for tuples
Diffstat (limited to 'src/lib.rs')
| -rw-r--r-- | src/lib.rs | 110 |
1 files changed, 110 insertions, 0 deletions
@@ -384,6 +384,109 @@ impl Debug for Value { } } +mod op { + use super::Value; + use std::rc::Rc; + + fn tuple_op(a: &Rc<Vec<Value>>, b: &Rc<Vec<Value>>, f: fn (&Value, &Value) -> Value) -> Value { + Value::Tuple(Rc::new(a.iter().zip(b.iter()).map(|(a, b)| f(a, b)).collect())) + } + + pub fn neg(value: &Value) -> Value { + match value { + Value::Float(a) => Value::Float(-a), + Value::Int(a) => Value::Int(-a), + Value::Tuple(a) => Value::Tuple(Rc::new(a.iter().map(neg).collect())), + _ => Value::Nil, + } + } + + pub fn not(value: &Value) -> Value { + match value { + Value::Bool(a) => Value::Bool(!a), + Value::Tuple(a) => Value::Tuple(Rc::new(a.iter().map(not).collect())), + _ => Value::Nil, + } + } + + + pub fn add(a: &Value, b: &Value) -> Value { + match (a, b) { + (Value::Float(a), Value::Float(b)) => Value::Float(a + b), + (Value::Int(a), Value::Int(b)) => Value::Int(a + b), + (Value::String(a), Value::String(b)) => Value::String(Rc::from(format!("{}{}", a, b))), + (Value::Tuple(a), Value::Tuple(b)) if a.len() == b.len() => tuple_op(a, b, add), + _ => Value::Nil, + } + } + + pub fn sub(a: &Value, b: &Value) -> Value { + add(a, &neg(b)) + } + + pub fn mul(a: &Value, b: &Value) -> Value { + match (a, b) { + (Value::Float(a), Value::Float(b)) => Value::Float(a * b), + (Value::Int(a), Value::Int(b)) => Value::Int(a * b), + (Value::Tuple(a), Value::Tuple(b)) if a.len() == b.len() => tuple_op(a, b, mul), + _ => Value::Nil, + } + } + + pub fn div(a: &Value, b: &Value) -> Value { + match (a, b) { + (Value::Float(a), Value::Float(b)) => Value::Float(a / b), + (Value::Int(a), Value::Int(b)) => Value::Int(a / b), + (Value::Tuple(a), Value::Tuple(b)) if a.len() == b.len() => tuple_op(a, b, div), + _ => Value::Nil, + } + } + + pub fn eq(a: &Value, b: &Value) -> Value { + match (a, b) { + (Value::Float(a), Value::Float(b)) => Value::Bool(a == b), + (Value::Int(a), Value::Int(b)) => Value::Bool(a == b), + (Value::String(a), Value::String(b)) => Value::Bool(a == b), + (Value::Bool(a), Value::Bool(b)) => Value::Bool(a == b), + (Value::Tuple(a), Value::Tuple(b)) if a.len() == b.len() => tuple_op(a, b, eq), + _ => Value::Nil, + } + } + + pub fn less(a: &Value, b: &Value) -> Value { + match (a, b) { + (Value::Float(a), Value::Float(b)) => Value::Bool(a < b), + (Value::Int(a), Value::Int(b)) => Value::Bool(a < b), + (Value::String(a), Value::String(b)) => Value::Bool(a < b), + (Value::Bool(a), Value::Bool(b)) => Value::Bool(a < b), + (Value::Tuple(a), Value::Tuple(b)) if a.len() == b.len() => tuple_op(a, b, less), + _ => Value::Nil, + } + } + + pub fn greater(a: &Value, b: &Value) -> Value { + less(b, a) + } + + pub fn and(a: &Value, b: &Value) -> Value { + match (a, b) { + (Value::Bool(a), Value::Bool(b)) => Value::Bool(*a && *b), + (Value::Tuple(a), Value::Tuple(b)) if a.len() == b.len() => tuple_op(a, b, and), + _ => Value::Nil, + } + } + + pub fn or(a: &Value, b: &Value) -> Value { + match (a, b) { + (Value::Bool(a), Value::Bool(b)) => Value::Bool(*a || *b), + (Value::Tuple(a), Value::Tuple(b)) if a.len() == b.len() => tuple_op(a, b, or), + _ => Value::Nil, + } + } + +} + + impl Value { fn identity(self) -> Self { match self { @@ -394,6 +497,13 @@ impl Value { } } + fn is_nil(&self) -> bool { + match self { + Value::Nil => true, + _ => false, + } + } + fn as_type(&self) -> Type { Type::from(self) } |
