From 68ea4a31e315922c345e90fa91d9ce7e4ec0af86 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Edvard=20Th=C3=B6rnros?= Date: Mon, 8 Mar 2021 19:02:20 +0100 Subject: add union type and union value --- src/lib.rs | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) (limited to 'src/lib.rs') diff --git a/src/lib.rs b/src/lib.rs index a138c33..d0a45f6 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -86,6 +86,7 @@ pub enum Type { Bool, String, Tuple(Vec), + Union(Vec), Function(Vec, Box), Blob(Rc), Instance(Rc), @@ -104,6 +105,9 @@ impl PartialEq for Type { (Type::Tuple(a), Type::Tuple(b)) => { a.iter().zip(b.iter()).all(|(a, b)| a == b) } + (Type::Union(a), b) | (b, Type::Union(a)) => { + a.iter().any(|x| x == b) + } (Type::Function(a_args, a_ret), Type::Function(b_args, b_ret)) => a_args == b_args && a_ret == b_ret, _ => false, @@ -119,6 +123,9 @@ impl From<&Value> for Type { Value::Tuple(v) => { Type::Tuple(v.iter().map(|x| Type::from(x)).collect()) } + Value::Union(v) => { + Type::Union(v.iter().map(|x| Type::from(x)).collect()) + } Value::Int(_) => Type::Int, Value::Float(_) => Type::Float, Value::Bool(_) => Type::Bool, @@ -147,6 +154,9 @@ impl From<&Type> for Value { Type::Tuple(fields) => { Value::Tuple(Rc::new(fields.iter().map(Value::from).collect())) } + Type::Union(v) => { + Value::Union(v.iter().map(Value::from).collect()) + } Type::Unknown => Value::Unknown, Type::Int => Value::Int(1), Type::Float => Value::Float(1.0), @@ -172,6 +182,7 @@ pub enum Value { Blob(Rc), Instance(Rc, Rc>>), Tuple(Rc>), + Union(Vec), Float(f64), Int(i64), Bool(bool), @@ -200,6 +211,7 @@ impl Debug for Value { Value::Unknown => write!(fmt, "(unknown)"), Value::Nil => write!(fmt, "(nil)"), Value::Tuple(v) => write!(fmt, "({:?})", v), + Value::Union(v) => write!(fmt, "(U {:?})", v), } } } @@ -214,6 +226,9 @@ impl PartialEq for Value { (Value::Tuple(a), Value::Tuple(b)) => { a.len() == b.len() && a.iter().zip(b.iter()).all(|(a, b)| a == b) } + (Value::Union(a), b) | (b, Value::Union(a)) => { + a.iter().any(|x| x == b) + } (Value::Nil, Value::Nil) => true, _ => false, } @@ -575,11 +590,34 @@ mod op { Value::Tuple(Rc::new(a.iter().map(f).collect())) } + fn union_un_op(a: &Vec, f: fn (&Value) -> Value) -> Value { + a.iter().find_map(|x| { + let x = f(x); + if x.is_nil() { + None + } else { + Some(x) + } + }).unwrap_or(Value::Nil) + } + + fn union_bin_op(a: &Vec, b: &Value, f: fn (&Value, &Value) -> Value) -> Value { + a.iter().find_map(|x| { + let x = f(x, b); + if x.is_nil() { + None + } else { + Some(x) + } + }).unwrap_or(Value::Nil) + } + pub fn neg(value: &Value) -> Value { match value { Value::Float(a) => Value::Float(-*a), Value::Int(a) => Value::Int(-*a), Value::Tuple(a) => tuple_un_op(a, neg), + Value::Union(v) => union_un_op(&v, neg), Value::Unknown => Value::Unknown, _ => Value::Nil, } @@ -589,6 +627,7 @@ mod op { match value { Value::Bool(a) => Value::Bool(!*a), Value::Tuple(a) => tuple_un_op(a, not), + Value::Union(v) => union_un_op(&v, not), Value::Unknown => Value::from(Type::Bool), _ => Value::Nil, } @@ -603,6 +642,7 @@ mod op { (Value::Tuple(a), Value::Tuple(b)) if a.len() == b.len() => tuple_bin_op(a, b, add), (Value::Unknown, a) | (a, Value::Unknown) if !matches!(a, Value::Unknown) => add(a, a), (Value::Unknown, Value::Unknown) => Value::Unknown, + (Value::Union(a), b) | (b, Value::Union(a)) => union_bin_op(&a, b, add), _ => Value::Nil, } } @@ -618,6 +658,7 @@ mod op { (Value::Tuple(a), Value::Tuple(b)) if a.len() == b.len() => tuple_bin_op(a, b, mul), (Value::Unknown, a) | (a, Value::Unknown) if !matches!(a, Value::Unknown) => mul(a, a), (Value::Unknown, Value::Unknown) => Value::Unknown, + (Value::Union(a), b) | (b, Value::Union(a)) => union_bin_op(&a, b, mul), _ => Value::Nil, } } @@ -629,6 +670,7 @@ mod op { (Value::Tuple(a), Value::Tuple(b)) if a.len() == b.len() => tuple_bin_op(a, b, div), (Value::Unknown, a) | (a, Value::Unknown) if !matches!(a, Value::Unknown) => div(a, a), (Value::Unknown, Value::Unknown) => Value::Unknown, + (Value::Union(a), b) | (b, Value::Union(a)) => union_bin_op(&a, b, div), _ => Value::Nil, } } @@ -642,6 +684,7 @@ mod op { (Value::Tuple(a), Value::Tuple(b)) if a.len() == b.len() => tuple_bin_op(a, b, eq), (Value::Unknown, a) | (a, Value::Unknown) if !matches!(a, Value::Unknown) => eq(a, a), (Value::Unknown, Value::Unknown) => Value::Unknown, + (Value::Union(a), b) | (b, Value::Union(a)) => union_bin_op(&a, b, eq), _ => Value::Nil, } } @@ -655,6 +698,7 @@ mod op { (Value::Tuple(a), Value::Tuple(b)) if a.len() == b.len() => tuple_bin_op(a, b, less), (Value::Unknown, a) | (a, Value::Unknown) if !matches!(a, Value::Unknown) => less(a, a), (Value::Unknown, Value::Unknown) => Value::Unknown, + (Value::Union(a), b) | (b, Value::Union(a)) => union_bin_op(&a, b, less), _ => Value::Nil, } } @@ -669,6 +713,7 @@ mod op { (Value::Tuple(a), Value::Tuple(b)) if a.len() == b.len() => tuple_bin_op(a, b, and), (Value::Unknown, a) | (a, Value::Unknown) if !matches!(a, Value::Unknown) => and(a, a), (Value::Unknown, Value::Unknown) => Value::Unknown, + (Value::Union(a), b) | (b, Value::Union(a)) => union_bin_op(&a, b, and), _ => Value::Nil, } } @@ -679,6 +724,7 @@ mod op { (Value::Tuple(a), Value::Tuple(b)) if a.len() == b.len() => tuple_bin_op(a, b, or), (Value::Unknown, a) | (a, Value::Unknown) if !matches!(a, Value::Unknown) => or(a, a), (Value::Unknown, Value::Unknown) => Value::Unknown, + (Value::Union(a), b) | (b, Value::Union(a)) => union_bin_op(&a, b, or), _ => Value::Nil, } } -- cgit v1.2.1 From 4e6ef21576d9ec6a8861246464b1905819b68efe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Edvard=20Th=C3=B6rnros?= Date: Mon, 8 Mar 2021 21:57:52 +0100 Subject: fix some nice tests for the nullable_types --- src/lib.rs | 1 + 1 file changed, 1 insertion(+) (limited to 'src/lib.rs') diff --git a/src/lib.rs b/src/lib.rs index d0a45f6..e7c4a35 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -685,6 +685,7 @@ mod op { (Value::Unknown, a) | (a, Value::Unknown) if !matches!(a, Value::Unknown) => eq(a, a), (Value::Unknown, Value::Unknown) => Value::Unknown, (Value::Union(a), b) | (b, Value::Union(a)) => union_bin_op(&a, b, eq), + (Value::Nil, Value::Nil) => Value::Bool(true), _ => Value::Nil, } } -- cgit v1.2.1 From fe3909375bd0b200989b9d88158e8c3412b3d639 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Edvard=20Th=C3=B6rnros?= Date: Mon, 8 Mar 2021 23:39:59 +0100 Subject: change how tuple comparison functions --- src/lib.rs | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) (limited to 'src/lib.rs') diff --git a/src/lib.rs b/src/lib.rs index e7c4a35..c085cca 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -681,7 +681,13 @@ mod op { (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_bin_op(a, b, eq), + (Value::Tuple(a), Value::Tuple(b)) if a.len() == b.len() => { + a.iter().zip(b.iter()).find_map( + |(a, b)| match eq(a, b) { + Value::Bool(true) => None, + a => Some(a), + }).unwrap_or(Value::Bool(true)) + } (Value::Unknown, a) | (a, Value::Unknown) if !matches!(a, Value::Unknown) => eq(a, a), (Value::Unknown, Value::Unknown) => Value::Unknown, (Value::Union(a), b) | (b, Value::Union(a)) => union_bin_op(&a, b, eq), @@ -696,7 +702,13 @@ mod op { (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_bin_op(a, b, less), + (Value::Tuple(a), Value::Tuple(b)) if a.len() == b.len() => { + a.iter().zip(b.iter()).find_map( + |(a, b)| match less(a, b) { + Value::Bool(true) => None, + a => Some(a), + }).unwrap_or(Value::Bool(true)) + } (Value::Unknown, a) | (a, Value::Unknown) if !matches!(a, Value::Unknown) => less(a, a), (Value::Unknown, Value::Unknown) => Value::Unknown, (Value::Union(a), b) | (b, Value::Union(a)) => union_bin_op(&a, b, less), -- cgit v1.2.1 From 9ef8eaa4564b2e498c56cad50491f2fdcea9d643 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Edvard=20Th=C3=B6rnros?= Date: Tue, 9 Mar 2021 17:01:53 +0100 Subject: change union to hashset from vector --- src/lib.rs | 50 ++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 48 insertions(+), 2 deletions(-) (limited to 'src/lib.rs') diff --git a/src/lib.rs b/src/lib.rs index c085cca..6f63ad7 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,5 +1,5 @@ use std::cell::RefCell; -use std::collections::HashMap; +use std::collections::{HashMap, HashSet}; use std::collections::hash_map::Entry; use std::fmt::Debug; use std::path::{Path, PathBuf}; @@ -86,12 +86,56 @@ pub enum Type { Bool, String, Tuple(Vec), - Union(Vec), + Union(HashSet), Function(Vec, Box), Blob(Rc), Instance(Rc), } +impl Hash for Type { + fn hash(&self, h: &mut H) { + match self { + Type::Void => 0, + Type::Unknown => 1, + Type::Int => 2, + Type::Float => 3, + Type::Bool => 4, + Type::String => 5, + Type::Tuple(ts) => { + for t in ts.iter() { + t.hash(h); + } + 6 + } + Type::Union(ts) => { + for t in ts { + t.hash(h); + } + 7 + } + Type::Function(args, ret) => { + ret.hash(h); + for t in args.iter() { + t.hash(h); + } + 8 + } + Type::Blob(b) => { + for (_, t) in b.fields.values() { + t.hash(h); + } + 10 + } + Type::Instance(b) => { + for (_, t) in b.fields.values() { + t.hash(h); + } + 11 + } + }.hash(h); + } +} + impl PartialEq for Type { fn eq(&self, other: &Self) -> bool { match (self, other) { @@ -115,6 +159,8 @@ impl PartialEq for Type { } } +impl Eq for Type {} + impl From<&Value> for Type { fn from(value: &Value) -> Type { match value { -- cgit v1.2.1 From 64faa5bad78b74fff1aca73987b010cb2961c027 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Edvard=20Th=C3=B6rnros?= Date: Tue, 9 Mar 2021 17:46:37 +0100 Subject: more hash sets! --- src/lib.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'src/lib.rs') diff --git a/src/lib.rs b/src/lib.rs index 6f63ad7..5ea0b63 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -228,7 +228,7 @@ pub enum Value { Blob(Rc), Instance(Rc, Rc>>), Tuple(Rc>), - Union(Vec), + Union(HashSet), Float(f64), Int(i64), Bool(bool), @@ -627,6 +627,7 @@ pub enum Op { mod op { use super::{Type, Value}; use std::rc::Rc; + use std::collections::HashSet; fn tuple_bin_op(a: &Rc>, b: &Rc>, f: fn (&Value, &Value) -> Value) -> Value { Value::Tuple(Rc::new(a.iter().zip(b.iter()).map(|(a, b)| f(a, b)).collect())) @@ -636,7 +637,7 @@ mod op { Value::Tuple(Rc::new(a.iter().map(f).collect())) } - fn union_un_op(a: &Vec, f: fn (&Value) -> Value) -> Value { + fn union_un_op(a: &HashSet, f: fn (&Value) -> Value) -> Value { a.iter().find_map(|x| { let x = f(x); if x.is_nil() { @@ -647,7 +648,7 @@ mod op { }).unwrap_or(Value::Nil) } - fn union_bin_op(a: &Vec, b: &Value, f: fn (&Value, &Value) -> Value) -> Value { + fn union_bin_op(a: &HashSet, b: &Value, f: fn (&Value, &Value) -> Value) -> Value { a.iter().find_map(|x| { let x = f(x, b); if x.is_nil() { -- cgit v1.2.1