From 712d4e2b7330c9fb65abd93ad9cc5f9901472e64 Mon Sep 17 00:00:00 2001 From: Shunsuke Shibayama Date: Tue, 5 Sep 2023 17:21:59 +0900 Subject: [PATCH] feat: bidi for containers --- crates/erg_common/traits.rs | 23 +++++++++ crates/erg_compiler/context/eval.rs | 57 +++++++++++++++++++-- crates/erg_compiler/lower.rs | 78 ++++++++++++++++++++++------- 3 files changed, 138 insertions(+), 20 deletions(-) diff --git a/crates/erg_common/traits.rs b/crates/erg_common/traits.rs index 412960d7..e8ac89da 100644 --- a/crates/erg_common/traits.rs +++ b/crates/erg_common/traits.rs @@ -1267,3 +1267,26 @@ pub trait StructuralEq { pub trait __Str__ { fn __str__(&self) -> String; } + +pub trait OptionalTranspose { + type Output; + type Fill; + /// `self: Option<_>` + fn transpose(self, fill: Self::Fill) -> Self::Output + where + Self: Sized; +} + +impl OptionalTranspose for Option> { + type Output = Vec>; + type Fill = usize; + fn transpose(self, fill: Self::Fill) -> Self::Output + where + Self: Sized, + { + match self { + Some(v) => v.into_iter().map(Some).collect(), + None => vec![None; fill], + } + } +} diff --git a/crates/erg_compiler/context/eval.rs b/crates/erg_compiler/context/eval.rs index a8acf236..df510408 100644 --- a/crates/erg_compiler/context/eval.rs +++ b/crates/erg_compiler/context/eval.rs @@ -1790,6 +1790,38 @@ impl Context { self.convert_tp_into_value(fv.crack().clone()) } TyParam::Value(v) => Ok(v), + TyParam::Array(arr) => { + let mut new = vec![]; + for elem in arr { + let elem = self.convert_tp_into_value(elem)?; + new.push(elem); + } + Ok(ValueObj::Array(new.into())) + } + TyParam::Tuple(tys) => { + let mut new = vec![]; + for elem in tys { + let elem = self.convert_tp_into_value(elem)?; + new.push(elem); + } + Ok(ValueObj::Tuple(new.into())) + } + TyParam::Record(rec) => { + let mut new = dict! {}; + for (name, elem) in rec { + let elem = self.convert_tp_into_value(elem)?; + new.insert(name, elem); + } + Ok(ValueObj::Record(new)) + } + TyParam::Set(set) => { + let mut new = set! {}; + for elem in set { + let elem = self.convert_tp_into_value(elem)?; + new.insert(elem); + } + Ok(ValueObj::Set(new)) + } other => self.convert_tp_into_type(other).map(ValueObj::builtin_type), } } @@ -1931,12 +1963,12 @@ impl Context { } } - fn _convert_type_to_dict_type(&self, ty: Type) -> Result, ()> { + pub(crate) fn convert_type_to_dict_type(&self, ty: Type) -> Result, ()> { match ty { Type::FreeVar(fv) if fv.is_linked() => { - self._convert_type_to_dict_type(fv.crack().clone()) + self.convert_type_to_dict_type(fv.crack().clone()) } - Type::Refinement(refine) => self._convert_type_to_dict_type(*refine.t), + Type::Refinement(refine) => self.convert_type_to_dict_type(*refine.t), Type::Poly { name, params } if &name[..] == "Dict" => { let dict = Dict::try_from(params[0].clone())?; let mut new_dict = dict! {}; @@ -1951,6 +1983,25 @@ impl Context { } } + pub(crate) fn convert_type_to_tuple_type(&self, ty: Type) -> Result, ()> { + match ty { + Type::FreeVar(fv) if fv.is_linked() => { + self.convert_type_to_tuple_type(fv.crack().clone()) + } + Type::Refinement(refine) => self.convert_type_to_tuple_type(*refine.t), + Type::Poly { name, params } if &name[..] == "Tuple" => { + let tps = Vec::try_from(params[0].clone())?; + let mut tys = vec![]; + for elem in tps.into_iter() { + let elem = self.convert_tp_into_type(elem).map_err(|_| ())?; + tys.push(elem); + } + Ok(tys) + } + _ => Err(()), + } + } + pub(crate) fn convert_type_to_array(&self, ty: Type) -> Result, Type> { match ty { Type::FreeVar(fv) if fv.is_linked() => self.convert_type_to_array(fv.crack().clone()), diff --git a/crates/erg_compiler/lower.rs b/crates/erg_compiler/lower.rs index fc931de4..739b1033 100644 --- a/crates/erg_compiler/lower.rs +++ b/crates/erg_compiler/lower.rs @@ -11,6 +11,7 @@ use erg_common::error::{Location, MultiErrorDisplay}; use erg_common::fresh::FreshNameGenerator; use erg_common::set; use erg_common::set::Set; +use erg_common::traits::OptionalTranspose; use erg_common::traits::{ExitStatus, Locational, NoTypeDisplay, Runnable, Stream}; use erg_common::triple::Triple; use erg_common::{fmt_option, fn_name, log, switch_lang, Str}; @@ -294,15 +295,21 @@ impl ASTLowerer { fn lower_normal_array( &mut self, array: ast::NormalArray, - _expect: Option<&Type>, + expect: Option<&Type>, ) -> LowerResult { log!(info "entered {}({array})", fn_name!()); let mut new_array = vec![]; let eval_result = self.module.context.eval_const_normal_array(&array); let (elems, ..) = array.elems.deconstruct(); + let expect_elem = expect.and_then(|t| { + self.module + .context + .convert_tp_into_type(t.typarams().get(0)?.clone()) + .ok() + }); let mut union = Type::Never; for elem in elems.into_iter() { - let elem = self.lower_expr(elem.expr, None)?; + let elem = self.lower_expr(elem.expr, expect_elem.as_ref())?; let union_ = self.module.context.union(&union, elem.ref_t()); if let Some((l, r)) = union_.union_pair() { match (l.is_unbound_var(), r.is_unbound_var()) { @@ -352,12 +359,18 @@ impl ASTLowerer { fn lower_array_with_length( &mut self, array: ast::ArrayWithLength, - _expect: Option<&Type>, + expect: Option<&Type>, ) -> LowerResult { log!(info "entered {}({array})", fn_name!()); - let elem = self.lower_expr(array.elem.expr, None)?; + let expect_elem = expect.and_then(|t| { + self.module + .context + .convert_tp_into_type(t.typarams().get(0)?.clone()) + .ok() + }); + let elem = self.lower_expr(array.elem.expr, expect_elem.as_ref())?; let array_t = self.gen_array_with_length_type(&elem, &array.len); - let len = self.lower_expr(*array.len, None)?; + let len = self.lower_expr(*array.len, Some(&Type::Nat))?; let hir_array = hir::ArrayWithLength::new(array.l_sqbr, array.r_sqbr, array_t, elem, len); Ok(hir_array) } @@ -384,13 +397,20 @@ impl ASTLowerer { fn lower_normal_tuple( &mut self, tuple: ast::NormalTuple, - _expect: Option<&Type>, + expect: Option<&Type>, ) -> LowerResult { log!(info "entered {}({tuple})", fn_name!()); + let expect = expect.and_then(|exp| { + self.module + .context + .convert_type_to_tuple_type(exp.clone()) + .ok() + }); let mut new_tuple = vec![]; let (elems, .., paren) = tuple.elems.deconstruct(); - for elem in elems { - let elem = self.lower_expr(elem.expr, None)?; + let expect_ts = expect.transpose(elems.len()); + for (elem, expect) in elems.into_iter().zip(expect_ts) { + let elem = self.lower_expr(elem.expr, expect.as_ref())?; new_tuple.push(elem); } Ok(hir::NormalTuple::new(hir::Args::values(new_tuple, paren))) @@ -463,14 +483,20 @@ impl ASTLowerer { fn lower_normal_set( &mut self, set: ast::NormalSet, - _expect: Option<&Type>, + expect: Option<&Type>, ) -> LowerResult { log!(info "entered {}({set})", fn_name!()); let (elems, ..) = set.elems.deconstruct(); + let expect_elem = expect.and_then(|t| { + self.module + .context + .convert_tp_into_type(t.typarams().get(0)?.clone()) + .ok() + }); let mut union = Type::Never; let mut new_set = vec![]; for elem in elems { - let elem = self.lower_expr(elem.expr, None)?; + let elem = self.lower_expr(elem.expr, expect_elem.as_ref())?; union = self.module.context.union(&union, elem.ref_t()); if ERG_MODE && union.is_union_type() { return Err(LowerErrors::from(LowerError::syntax_error( @@ -542,12 +568,18 @@ impl ASTLowerer { fn lower_set_with_length( &mut self, set: ast::SetWithLength, - _expect: Option<&Type>, + expect: Option<&Type>, ) -> LowerResult { log!("entered {}({set})", fn_name!()); - let elem = self.lower_expr(set.elem.expr, None)?; + let expect_elem = expect.and_then(|t| { + self.module + .context + .convert_tp_into_type(t.typarams().get(0)?.clone()) + .ok() + }); + let elem = self.lower_expr(set.elem.expr, expect_elem.as_ref())?; let set_t = self.gen_set_with_length_type(&elem, &set.len); - let len = self.lower_expr(*set.len, None)?; + let len = self.lower_expr(*set.len, Some(&Type::Nat))?; let hir_set = hir::SetWithLength::new(set.l_brace, set.r_brace, set_t, elem, len); Ok(hir_set) } @@ -585,14 +617,23 @@ impl ASTLowerer { fn lower_normal_dict( &mut self, dict: ast::NormalDict, - _expect: Option<&Type>, + expect: Option<&Type>, ) -> LowerResult { log!(info "enter {}({dict})", fn_name!()); let mut union = dict! {}; let mut new_kvs = vec![]; - for kv in dict.kvs { - let key = self.lower_expr(kv.key, None)?; - let value = self.lower_expr(kv.value, None)?; + let expect = expect + .and_then(|exp| { + self.module + .context + .convert_type_to_dict_type(exp.clone()) + .ok() + }) + .map(|dict| dict.into_iter().collect::>()); + let expect_kvs = expect.transpose(dict.kvs.len()); + for (kv, expect) in dict.kvs.into_iter().zip(expect_kvs) { + let key = self.lower_expr(kv.key, expect.as_ref().map(|(k, _)| k))?; + let value = self.lower_expr(kv.value, expect.as_ref().map(|(_, v)| v))?; if let Some(popped_val_t) = union.insert(key.t(), value.t()) { if PYTHON_MODE { let val_t = union.get_mut(key.ref_t()).unwrap(); @@ -2434,6 +2475,9 @@ impl ASTLowerer { .module .context .instantiate_typespec(&tasc.t_spec.t_spec)?; + let expect = expect.map_or(Some(&spec_t), |exp| { + self.module.context.min(exp, &spec_t).ok().or(Some(&spec_t)) + }); let expr = self.lower_expr(*tasc.expr, expect)?; match kind { AscriptionKind::TypeOf | AscriptionKind::AsCast => {