From 3f952cdf0e76b3ecf3f5c9c11be13404376a8931 Mon Sep 17 00:00:00 2001 From: rvcas Date: Mon, 14 Nov 2022 14:42:10 -0500 Subject: [PATCH] feat: add new Data type to prelude and allow it to unify with any user defined type --- crates/lang/src/builtins.rs | 42 +++++++++++++++++++++-------- crates/lang/src/tipo/environment.rs | 22 ++++++++++++++- 2 files changed, 52 insertions(+), 12 deletions(-) diff --git a/crates/lang/src/builtins.rs b/crates/lang/src/builtins.rs index f033b917..193aaab2 100644 --- a/crates/lang/src/builtins.rs +++ b/crates/lang/src/builtins.rs @@ -13,13 +13,14 @@ use crate::{ IdGenerator, }; -const BYTE_ARRAY: &str = "ByteArray"; -const BOOL: &str = "Bool"; -const INT: &str = "Int"; -const LIST: &str = "List"; -const NIL: &str = "Nil"; -const RESULT: &str = "Result"; -const STRING: &str = "String"; +pub const BYTE_ARRAY: &str = "ByteArray"; +pub const BOOL: &str = "Bool"; +pub const INT: &str = "Int"; +pub const DATA: &str = "Data"; +pub const LIST: &str = "List"; +pub const NIL: &str = "Nil"; +pub const RESULT: &str = "Result"; +pub const STRING: &str = "String"; /// Build a prelude that can be injected /// into a compiler pipeline @@ -46,6 +47,18 @@ pub fn prelude(id_gen: &IdGenerator) -> TypeInfo { }, ); + // Data + prelude.types.insert( + DATA.to_string(), + TypeConstructor { + parameters: vec![], + tipo: data(), + location: Span::empty(), + module: "".to_string(), + public: true, + }, + ); + // ByteArray prelude.types.insert( BYTE_ARRAY.to_string(), @@ -372,14 +385,12 @@ pub fn from_default_function( DefaultFunction::UnIData => None, DefaultFunction::UnBData => None, DefaultFunction::EqualsData => { - let arg = generic_var(id_gen.next()); - - let tipo = function(vec![arg.clone(), arg], bool()); + let tipo = function(vec![data(), data()], bool()); Some((tipo, 1)) } DefaultFunction::SerialiseData => { - let tipo = function(vec![generic_var(id_gen.next())], byte_array()); + let tipo = function(vec![data()], byte_array()); Some((tipo, 1)) } @@ -412,6 +423,15 @@ pub fn int() -> Arc { }) } +pub fn data() -> Arc { + Arc::new(Type::App { + public: true, + name: DATA.to_string(), + module: "".to_string(), + args: vec![], + }) +} + pub fn byte_array() -> Arc { Arc::new(Type::App { args: vec![], diff --git a/crates/lang/src/tipo/environment.rs b/crates/lang/src/tipo/environment.rs index a4828c67..27d9bfca 100644 --- a/crates/lang/src/tipo/environment.rs +++ b/crates/lang/src/tipo/environment.rs @@ -12,7 +12,7 @@ use crate::{ RecordConstructor, RecordConstructorArg, Span, TypeAlias, TypedDefinition, UnqualifiedImport, UntypedDefinition, Use, PIPE_VARIABLE, }, - builtins::{function, generic_var, unbound_var}, + builtins::{self, function, generic_var, unbound_var}, tipo::fields::FieldMap, IdGenerator, }; @@ -29,6 +29,14 @@ pub struct ScopeResetData { local_values: HashMap, } +const EXCLUDE_DATA_UNIFY: [&str; 5] = [ + builtins::INT, + builtins::BYTE_ARRAY, + builtins::STRING, + builtins::BOOL, + builtins::LIST, +]; + #[derive(Debug)] pub struct Environment<'a> { /// Accessors defined in the current module @@ -1099,6 +1107,18 @@ impl<'a> Environment<'a> { return Ok(()); } + if let (Type::App { name: name1, .. }, Type::App { name: name2, .. }) = + (t1.deref(), t2.deref()) + { + if name1 == "Data" && !EXCLUDE_DATA_UNIFY.contains(&name2.as_str()) { + return Ok(()); + } + + if name2 == "Data" && !EXCLUDE_DATA_UNIFY.contains(&name1.as_str()) { + return Ok(()); + } + } + // Collapse right hand side type links. Left hand side will be collapsed in the next block. if let Type::Var { tipo } = t2.deref() { if let TypeVar::Link { tipo } = tipo.borrow().deref() {