feat: bidi for containers

This commit is contained in:
Shunsuke Shibayama 2023-09-05 17:21:59 +09:00
parent 0f430199ab
commit 712d4e2b73
3 changed files with 138 additions and 20 deletions

View file

@ -1267,3 +1267,26 @@ pub trait StructuralEq {
pub trait __Str__ { pub trait __Str__ {
fn __str__(&self) -> String; 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<T: Clone> OptionalTranspose for Option<Vec<T>> {
type Output = Vec<Option<T>>;
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],
}
}
}

View file

@ -1790,6 +1790,38 @@ impl Context {
self.convert_tp_into_value(fv.crack().clone()) self.convert_tp_into_value(fv.crack().clone())
} }
TyParam::Value(v) => Ok(v), 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), 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<Dict<Type, Type>, ()> { pub(crate) fn convert_type_to_dict_type(&self, ty: Type) -> Result<Dict<Type, Type>, ()> {
match ty { match ty {
Type::FreeVar(fv) if fv.is_linked() => { 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" => { Type::Poly { name, params } if &name[..] == "Dict" => {
let dict = Dict::try_from(params[0].clone())?; let dict = Dict::try_from(params[0].clone())?;
let mut new_dict = dict! {}; let mut new_dict = dict! {};
@ -1951,6 +1983,25 @@ impl Context {
} }
} }
pub(crate) fn convert_type_to_tuple_type(&self, ty: Type) -> Result<Vec<Type>, ()> {
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<Vec<ValueObj>, Type> { pub(crate) fn convert_type_to_array(&self, ty: Type) -> Result<Vec<ValueObj>, Type> {
match ty { match ty {
Type::FreeVar(fv) if fv.is_linked() => self.convert_type_to_array(fv.crack().clone()), Type::FreeVar(fv) if fv.is_linked() => self.convert_type_to_array(fv.crack().clone()),

View file

@ -11,6 +11,7 @@ use erg_common::error::{Location, MultiErrorDisplay};
use erg_common::fresh::FreshNameGenerator; use erg_common::fresh::FreshNameGenerator;
use erg_common::set; use erg_common::set;
use erg_common::set::Set; use erg_common::set::Set;
use erg_common::traits::OptionalTranspose;
use erg_common::traits::{ExitStatus, Locational, NoTypeDisplay, Runnable, Stream}; use erg_common::traits::{ExitStatus, Locational, NoTypeDisplay, Runnable, Stream};
use erg_common::triple::Triple; use erg_common::triple::Triple;
use erg_common::{fmt_option, fn_name, log, switch_lang, Str}; use erg_common::{fmt_option, fn_name, log, switch_lang, Str};
@ -294,15 +295,21 @@ impl ASTLowerer {
fn lower_normal_array( fn lower_normal_array(
&mut self, &mut self,
array: ast::NormalArray, array: ast::NormalArray,
_expect: Option<&Type>, expect: Option<&Type>,
) -> LowerResult<hir::NormalArray> { ) -> LowerResult<hir::NormalArray> {
log!(info "entered {}({array})", fn_name!()); log!(info "entered {}({array})", fn_name!());
let mut new_array = vec![]; let mut new_array = vec![];
let eval_result = self.module.context.eval_const_normal_array(&array); let eval_result = self.module.context.eval_const_normal_array(&array);
let (elems, ..) = array.elems.deconstruct(); 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; let mut union = Type::Never;
for elem in elems.into_iter() { 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()); let union_ = self.module.context.union(&union, elem.ref_t());
if let Some((l, r)) = union_.union_pair() { if let Some((l, r)) = union_.union_pair() {
match (l.is_unbound_var(), r.is_unbound_var()) { match (l.is_unbound_var(), r.is_unbound_var()) {
@ -352,12 +359,18 @@ impl ASTLowerer {
fn lower_array_with_length( fn lower_array_with_length(
&mut self, &mut self,
array: ast::ArrayWithLength, array: ast::ArrayWithLength,
_expect: Option<&Type>, expect: Option<&Type>,
) -> LowerResult<hir::ArrayWithLength> { ) -> LowerResult<hir::ArrayWithLength> {
log!(info "entered {}({array})", fn_name!()); 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 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); let hir_array = hir::ArrayWithLength::new(array.l_sqbr, array.r_sqbr, array_t, elem, len);
Ok(hir_array) Ok(hir_array)
} }
@ -384,13 +397,20 @@ impl ASTLowerer {
fn lower_normal_tuple( fn lower_normal_tuple(
&mut self, &mut self,
tuple: ast::NormalTuple, tuple: ast::NormalTuple,
_expect: Option<&Type>, expect: Option<&Type>,
) -> LowerResult<hir::NormalTuple> { ) -> LowerResult<hir::NormalTuple> {
log!(info "entered {}({tuple})", fn_name!()); 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 mut new_tuple = vec![];
let (elems, .., paren) = tuple.elems.deconstruct(); let (elems, .., paren) = tuple.elems.deconstruct();
for elem in elems { let expect_ts = expect.transpose(elems.len());
let elem = self.lower_expr(elem.expr, None)?; for (elem, expect) in elems.into_iter().zip(expect_ts) {
let elem = self.lower_expr(elem.expr, expect.as_ref())?;
new_tuple.push(elem); new_tuple.push(elem);
} }
Ok(hir::NormalTuple::new(hir::Args::values(new_tuple, paren))) Ok(hir::NormalTuple::new(hir::Args::values(new_tuple, paren)))
@ -463,14 +483,20 @@ impl ASTLowerer {
fn lower_normal_set( fn lower_normal_set(
&mut self, &mut self,
set: ast::NormalSet, set: ast::NormalSet,
_expect: Option<&Type>, expect: Option<&Type>,
) -> LowerResult<hir::NormalSet> { ) -> LowerResult<hir::NormalSet> {
log!(info "entered {}({set})", fn_name!()); log!(info "entered {}({set})", fn_name!());
let (elems, ..) = set.elems.deconstruct(); 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 union = Type::Never;
let mut new_set = vec![]; let mut new_set = vec![];
for elem in elems { 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()); union = self.module.context.union(&union, elem.ref_t());
if ERG_MODE && union.is_union_type() { if ERG_MODE && union.is_union_type() {
return Err(LowerErrors::from(LowerError::syntax_error( return Err(LowerErrors::from(LowerError::syntax_error(
@ -542,12 +568,18 @@ impl ASTLowerer {
fn lower_set_with_length( fn lower_set_with_length(
&mut self, &mut self,
set: ast::SetWithLength, set: ast::SetWithLength,
_expect: Option<&Type>, expect: Option<&Type>,
) -> LowerResult<hir::SetWithLength> { ) -> LowerResult<hir::SetWithLength> {
log!("entered {}({set})", fn_name!()); 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 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); let hir_set = hir::SetWithLength::new(set.l_brace, set.r_brace, set_t, elem, len);
Ok(hir_set) Ok(hir_set)
} }
@ -585,14 +617,23 @@ impl ASTLowerer {
fn lower_normal_dict( fn lower_normal_dict(
&mut self, &mut self,
dict: ast::NormalDict, dict: ast::NormalDict,
_expect: Option<&Type>, expect: Option<&Type>,
) -> LowerResult<hir::NormalDict> { ) -> LowerResult<hir::NormalDict> {
log!(info "enter {}({dict})", fn_name!()); log!(info "enter {}({dict})", fn_name!());
let mut union = dict! {}; let mut union = dict! {};
let mut new_kvs = vec![]; let mut new_kvs = vec![];
for kv in dict.kvs { let expect = expect
let key = self.lower_expr(kv.key, None)?; .and_then(|exp| {
let value = self.lower_expr(kv.value, None)?; self.module
.context
.convert_type_to_dict_type(exp.clone())
.ok()
})
.map(|dict| dict.into_iter().collect::<Vec<_>>());
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 let Some(popped_val_t) = union.insert(key.t(), value.t()) {
if PYTHON_MODE { if PYTHON_MODE {
let val_t = union.get_mut(key.ref_t()).unwrap(); let val_t = union.get_mut(key.ref_t()).unwrap();
@ -2434,6 +2475,9 @@ impl ASTLowerer {
.module .module
.context .context
.instantiate_typespec(&tasc.t_spec.t_spec)?; .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)?; let expr = self.lower_expr(*tasc.expr, expect)?;
match kind { match kind {
AscriptionKind::TypeOf | AscriptionKind::AsCast => { AscriptionKind::TypeOf | AscriptionKind::AsCast => {