From 0ebb0ce94c8e547babae7387e11419a76f32b9cd Mon Sep 17 00:00:00 2001 From: Shunsuke Shibayama Date: Wed, 24 Aug 2022 18:51:12 +0900 Subject: [PATCH] Add LimitedDisplay --- compiler/erg_common/traits.rs | 4 + compiler/erg_common/ty.rs | 279 ++++++++++++++++++++++--------- compiler/erg_compiler/context.rs | 28 ++-- compiler/erg_compiler/hir.rs | 25 ++- compiler/erg_compiler/lower.rs | 43 +++-- compiler/erg_parser/ast.rs | 6 +- 6 files changed, 278 insertions(+), 107 deletions(-) diff --git a/compiler/erg_common/traits.rs b/compiler/erg_common/traits.rs index 20d3c0dc..ab0f9894 100644 --- a/compiler/erg_common/traits.rs +++ b/compiler/erg_common/traits.rs @@ -297,6 +297,10 @@ pub trait ImmutableStream: Sized { } } +pub trait LimitedDisplay { + fn limited_fmt(&self, f: &mut std::fmt::Formatter<'_>, limit: usize) -> std::fmt::Result; +} + // for Runnable::run fn expect_block(src: &str) -> bool { src.ends_with(&['=', ':']) || src.ends_with("->") || src.ends_with("=>") diff --git a/compiler/erg_common/ty.rs b/compiler/erg_common/ty.rs index eda64153..ec23b5fa 100644 --- a/compiler/erg_common/ty.rs +++ b/compiler/erg_common/ty.rs @@ -11,10 +11,10 @@ use crate::codeobj::CodeObj; use crate::dict::Dict; use crate::rccell::RcCell; use crate::set::Set; -use crate::traits::HasType; +use crate::traits::{HasType, LimitedDisplay}; use crate::value::ValueObj::{Inf, NegInf}; use crate::value::{Field, ValueObj}; -use crate::{enum_unwrap, fmt_set_split_with, fmt_vec, fmt_vec_split_with, set, Str}; +use crate::{enum_unwrap, fmt_set_split_with, fmt_vec, set, Str}; #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] #[repr(u8)] @@ -253,6 +253,24 @@ impl fmt::Display for FreeKind { } } +impl LimitedDisplay for FreeKind { + fn limited_fmt(&self, f: &mut fmt::Formatter<'_>, limit: usize) -> fmt::Result { + match self { + Self::Linked(t) => t.limited_fmt(f, limit), + Self::NamedUnbound { + name, + lev, + constraint, + } => write!(f, "?{name}({constraint})[{lev}]"), + Self::Unbound { + id, + lev, + constraint, + } => write!(f, "?{id}({constraint})[{lev}]"), + } + } +} + impl FreeKind { pub const fn unbound(id: Id, lev: Level, constraint: Constraint) -> Self { Self::Unbound { @@ -289,6 +307,12 @@ impl fmt::Display for Free { } } +impl Free { + fn limited_fmt(&self, f: &mut fmt::Formatter<'_>, limit: usize) -> fmt::Result { + self.0.borrow().limited_fmt(f, limit) + } +} + impl Free { pub fn new(f: FreeKind) -> Self { Self(RcCell::new(f)) @@ -582,21 +606,81 @@ pub enum TyParam { impl fmt::Display for TyParam { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + self.limited_fmt(f, 10) + } +} + +impl LimitedDisplay for TyParam { + fn limited_fmt(&self, f: &mut fmt::Formatter<'_>, limit: usize) -> fmt::Result { + if limit == 0 { return write!(f, "...") } match self { - Self::Value(c) => write!(f, "{c}"), - Self::Type(t) => write!(f, "{t}"), - Self::Mono(c) => write!(f, "{c}"), - Self::MonoProj { obj, attr } => write!(f, "{obj}.{attr}"), - Self::Array(a) => write!(f, "[{}]", fmt_vec(a)), - Self::Tuple(t) => write!(f, "({})", fmt_vec(t)), - Self::App { name, args } => write!(f, "{name}({})", fmt_vec(args)), - Self::MonoQVar(name) => write!(f, "'{name}"), - Self::PolyQVar { name, args } => write!(f, "'{name}({})", fmt_vec(args)), - Self::FreeVar(fv) => write!(f, "{fv}"), - Self::UnaryOp { op, val } => write!(f, "{op}{val}"), - Self::BinOp { op, lhs, rhs } => write!(f, "{lhs} {op} {rhs}"), - Self::Erased(t) => write!(f, "_: {t}"), - Self::Failure => write!(f, ""), + Self::Value(v) => write!(f, "{v}"), + Self::Failure => write!(f, ""), + Self::Type(t) => t.limited_fmt(f, limit - 1), + Self::FreeVar(fv) => fv.limited_fmt(f, limit - 1), + Self::UnaryOp { op, val } => { + write!(f, "{}", op)?; + val.limited_fmt(f, limit - 1) + } + Self::BinOp { op, lhs, rhs } => { + lhs.limited_fmt(f, limit - 1)?; + write!(f, " {} ", op)?; + rhs.limited_fmt(f, limit - 1) + } + Self::App { name, args } => { + write!(f, "{}", name)?; + write!(f, "(")?; + for (i, arg) in args.iter().enumerate() { + if i > 0 { + write!(f, ", ")?; + } + arg.limited_fmt(f, limit - 1)?; + } + write!(f, ")")?; + Ok(()) + } + Self::PolyQVar { name, args } => { + write!(f, "'{}", name)?; + write!(f, "(")?; + for (i, arg) in args.iter().enumerate() { + if i > 0 { + write!(f, ", ")?; + } + arg.limited_fmt(f, limit - 1)?; + } + write!(f, ")")?; + Ok(()) + } + Self::Erased(t) => { + write!(f, "_: ")?; + t.limited_fmt(f, limit - 1) + }, + Self::Mono(name) => write!(f, "{}", name), + Self::MonoQVar(name) => write!(f, "'{}", name), + Self::MonoProj { obj, attr } => { + write!(f, "{}.", obj)?; + write!(f, "{}", attr) + } + Self::Array(arr) => { + write!(f, "[")?; + for (i, t) in arr.iter().enumerate() { + if i > 0 { + write!(f, ", ")?; + } + t.limited_fmt(f, limit - 1)?; + } + write!(f, "]") + } + Self::Tuple(tuple) => { + write!(f, "(")?; + for (i, t) in tuple.iter().enumerate() { + if i > 0 { + write!(f, ", ")?; + } + t.limited_fmt(f, limit - 1)?; + } + write!(f, ")") + } } } } @@ -1585,7 +1669,7 @@ pub struct QuantifiedType { impl fmt::Display for QuantifiedType { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "|{}| {}", &self.bounds, self.unbound_callable) + self.limited_fmt(f, 10) } } @@ -1596,6 +1680,11 @@ impl QuantifiedType { bounds, } } + + pub fn limited_fmt(&self, f: &mut fmt::Formatter<'_>, limit: usize) -> fmt::Result { + write!(f, "|{}| ", fmt_set_split_with(&self.bounds, "; "))?; + self.unbound_callable.limited_fmt(f, limit) + } } type SelfType = Type; @@ -1839,6 +1928,85 @@ impl fmt::Display for Type { } } +impl LimitedDisplay for Type { + fn limited_fmt(&self, f: &mut fmt::Formatter<'_>, limit: usize) -> fmt::Result { + if limit == 0 { + return write!(f, "..."); + } + match self { + Self::Mono(name) => write!(f, "{name}"), + Self::Ref(t) | Self::RefMut(t) => { + write!(f, "{}(", self.name())?; + t.limited_fmt(f, limit - 1)?; + write!(f, ")") + } + Self::Subr(sub) => sub.limited_fmt(f, limit - 1), + Self::Callable { param_ts, return_t } => { + write!(f, "Callable((")?; + for (i, t) in param_ts.iter().enumerate() { + if i > 0 { + write!(f, ", ")?; + } + t.limited_fmt(f, limit - 1)?; + } + write!(f, "), ")?; + return_t.limited_fmt(f, limit - 1)?; + write!(f, ")") + } + Self::Record(attrs) => { + write!(f, "{{")?; + if let Some((field, t)) = attrs.iter().next() { + write!(f, "{field} = ")?; + t.limited_fmt(f, limit - 1)?; + } + for (field, t) in attrs.iter().skip(1) { + write!(f, "; {field} = ")?; + t.limited_fmt(f, limit - 1)?; + } + write!(f, "}}") + } + Self::Refinement(refinement) => refinement.limited_fmt(f, limit - 1), + Self::Quantified(quantified) => quantified.limited_fmt(f, limit - 1), + Self::And(lhs, rhs) => { + lhs.limited_fmt(f, limit - 1)?; + write!(f, " and ")?; + rhs.limited_fmt(f, limit - 1) + }, + Self::Not(lhs, rhs) => { + lhs.limited_fmt(f, limit - 1)?; + write!(f, " not ")?; + rhs.limited_fmt(f, limit - 1) + } + Self::Or(lhs, rhs) => { + lhs.limited_fmt(f, limit - 1)?; + write!(f, " or ")?; + rhs.limited_fmt(f, limit - 1) + } + Self::VarArgs(t) => { + write!(f, "...")?; + t.limited_fmt(f, limit - 1) + }, + Self::Poly { name, params } => { + write!(f, "{name}(")?; + for (i, tp) in params.iter().enumerate() { + if i > 0 { + write!(f, ", ")?; + } + tp.limited_fmt(f, limit - 1)?; + } + write!(f, ")") + } + Self::MonoQVar(name) => write!(f, "'{name}"), + Self::FreeVar(fv) => fv.limited_fmt(f, limit - 1), + Self::MonoProj { lhs, rhs } => { + lhs.limited_fmt(f, limit - 1)?; + write!(f, ".{rhs}") + }, + _ => write!(f, "{}", self.name()), + } + } +} + impl Default for Type { fn default() -> Self { Self::Failure @@ -1968,10 +2136,9 @@ impl HasLevel for Type { } subr.return_t.update_level(level); } - Self::And(ts) | Self::Or(ts) | Self::Not(ts) => { - for t in ts.iter() { - t.update_level(level); - } + Self::And(lhs, rhs) | Self::Or(lhs, rhs) | Self::Not(lhs, rhs) => { + lhs.update_level(level); + rhs.update_level(level); } Self::Record(attrs) => { for t in attrs.values() { @@ -2023,10 +2190,9 @@ impl HasLevel for Type { } subr.return_t.lift(); } - Self::And(ts) | Self::Or(ts) | Self::Not(ts) => { - for t in ts.iter() { - t.lift(); - } + Self::And(lhs, rhs) | Self::Or(lhs, rhs) | Self::Not(lhs, rhs) => { + lhs.lift(); + rhs.lift(); } Self::Record(attrs) => { for t in attrs.values() { @@ -2068,45 +2234,6 @@ impl Type { pub const NEVER: &'static Self = &Self::Never; pub const FAILURE: &'static Self = &Self::Failure; - pub fn limited_fmt(&self, f: &mut fmt::Formatter<'_>, limit: usize) -> fmt::Result { - if limit == 0 { - return write!(f, "..."); - } - match self { - Self::Mono(name) => write!(f, "{name}"), - Self::Ref(t) | Self::RefMut(t) => { - write!(f, "{}(", self.name())?; - t.limited_fmt(f, limit - 1)?; - write!(f, ")") - } - Self::Subr(sub) => sub.limited_fmt(f, limit - 1), - Self::Callable { param_ts, return_t } => { - write!(f, "Callable(({}), {return_t})", fmt_vec(param_ts)) - } - Self::Record(attrs) => { - write!(f, "{{")?; - if let Some((field, t)) = attrs.iter().next() { - write!(f, "{field} = {t}")?; - } - for (field, t) in attrs.iter().skip(1) { - write!(f, "; {field} = {t}")?; - } - write!(f, "}}") - } - Self::Refinement(refinement) => write!(f, "{}", refinement), - Self::Quantified(quantified) => write!(f, "{}", quantified), - Self::And(types) => write!(f, "{}", fmt_vec_split_with(types, " and ")), - Self::Not(types) => write!(f, "{}", fmt_vec_split_with(types, " not ")), - Self::Or(types) => write!(f, "{}", fmt_vec_split_with(types, " or ")), - Self::VarArgs(t) => write!(f, "...{t}"), - Self::Poly { name, params } => write!(f, "{name}({})", fmt_vec(params)), - Self::MonoQVar(name) => write!(f, "'{name}"), - Self::FreeVar(fv) => write!(f, "{fv}"), - Self::MonoProj { lhs, rhs } => write!(f, "{lhs}.{rhs}"), - _ => write!(f, "{}", self.name()), - } - } - /// Top := {=} #[allow(non_snake_case)] pub const fn Top() -> Self { @@ -2666,9 +2793,11 @@ impl Type { (Self::Quantified(l), Self::Quantified(r)) => { l.unbound_callable.rec_eq(&r.unbound_callable) && l.bounds == r.bounds } - (Self::And(l), Self::And(r)) - | (Self::Not(l), Self::Not(r)) - | (Self::Or(l), Self::Or(r)) => l.iter().zip(r.iter()).all(|(l, r)| l.rec_eq(r)), + (Self::And(ll, lr), Self::And(rl, rr)) + | (Self::Not(ll, lr), Self::Not(rl, rr)) + | (Self::Or(ll, lr), Self::Or(rl, rr)) => { + ll.rec_eq(rl) && lr.rec_eq(rr) + }, (Self::VarArgs(l), Self::VarArgs(r)) => l.rec_eq(r), ( Self::Poly { @@ -2735,9 +2864,9 @@ impl Type { Self::Inf => "Inf", Self::NegInf => "NegInf", Self::Mono(name) | Self::MonoQVar(name) => name, - Self::And(_) => "And", - Self::Not(_) => "Not", - Self::Or(_) => "Or", + Self::And(_, _) => "And", + Self::Not(_, _) => "Not", + Self::Or(_, _) => "Or", Self::Ref(_) => "Ref", Self::RefMut(_) => "Ref!", Self::Subr(SubrType { @@ -2799,8 +2928,8 @@ impl Type { } } Self::Ref(t) | Self::RefMut(t) | Self::VarArgs(t) => t.has_unbound_var(), - Self::And(param_ts) | Self::Not(param_ts) | Self::Or(param_ts) => { - param_ts.iter().any(|t| t.has_unbound_var()) + Self::And(lhs, rhs) | Self::Not(lhs, rhs) | Self::Or(lhs, rhs) => { + lhs.has_unbound_var() || rhs.has_unbound_var() } Self::Callable { param_ts, return_t } => { param_ts.iter().any(|t| t.has_unbound_var()) || return_t.has_unbound_var() @@ -2838,7 +2967,7 @@ impl Type { match self { // REVIEw: Self::Ref(_) | Self::RefMut(_) => 1, - Self::And(param_ts) | Self::Or(param_ts) => param_ts.len(), + Self::And(_, _) | Self::Or(_, _) | Self::Not(_, _) => 2, Self::Subr(subr) => { subr.kind.inner_len() + subr.non_default_params.len() @@ -2856,8 +2985,8 @@ impl Type { Self::FreeVar(f) if f.is_linked() => f.crack().typarams(), Self::FreeVar(_unbound) => vec![], Self::Ref(t) | Self::RefMut(t) => vec![TyParam::t(*t.clone())], - Self::And(param_ts) | Self::Or(param_ts) | Self::Not(param_ts) => { - param_ts.iter().map(|t| TyParam::t(t.clone())).collect() + Self::And(lhs, rhs) | Self::Not(lhs, rhs) | Self::Or(lhs, rhs) => { + vec![TyParam::t(*lhs.clone()), TyParam::t(*rhs.clone())] } Self::Subr(subr) => { if let Some(self_t) = subr.kind.self_t() { diff --git a/compiler/erg_compiler/context.rs b/compiler/erg_compiler/context.rs index 24466b1d..361752ca 100644 --- a/compiler/erg_compiler/context.rs +++ b/compiler/erg_compiler/context.rs @@ -2042,7 +2042,7 @@ impl Context { Ok(Type::var_args(new_t)) } Type::Callable { .. } => todo!(), - Type::And(_) | Type::Or(_) | Type::Not(_) => todo!(), + Type::And(_, _) | Type::Or(_, _) | Type::Not(_, _) => todo!(), other => Ok(other), } } @@ -3705,12 +3705,20 @@ impl Context { self.structural_supertype_of(q.unbound_callable.as_ref(), r, Some(&q.bounds)) } } - (lhs, Or(tys)) => tys - .iter() - .all(|t| self.structural_supertype_of(lhs, t, bounds)), - (And(tys), rhs) => tys - .iter() - .all(|t| self.structural_supertype_of(t, rhs, bounds)), + (Or(l_or, r_or), rhs) => + self.structural_supertype_of(l_or, rhs, bounds) + || self.structural_supertype_of(r_or, rhs, bounds), + (lhs, Or(or_l, or_r)) => + self.structural_supertype_of(lhs, or_l, bounds) + && self.structural_supertype_of(lhs, or_r, bounds), + (And(l_and, r_and), rhs) => + self.structural_supertype_of(l_and, rhs, bounds) + && self.structural_supertype_of(r_and, rhs, bounds), + (lhs, And(l_and, r_and)) => + self.structural_supertype_of(lhs, l_and, bounds) + || self.structural_supertype_of(lhs, r_and, bounds), + (_lhs, Not(_, _)) => todo!(), + (Not(_, _), _rhs) => todo!(), (VarArgs(lhs), rhs) => self.structural_supertype_of(lhs, rhs, bounds), // TはすべてのRef(T)のメソッドを持つので、Ref(T)のサブタイプ (Ref(lhs), rhs) | (RefMut(lhs), rhs) => self.structural_supertype_of(lhs, rhs, bounds), @@ -3917,7 +3925,7 @@ impl Context { } /// 和集合(A or B)を返す - fn rec_union(&self, lhs: &Type, rhs: &Type) -> Type { + pub(crate) fn rec_union(&self, lhs: &Type, rhs: &Type) -> Type { match ( self.rec_supertype_of(lhs, rhs), self.rec_subtype_of(lhs, rhs), @@ -4101,7 +4109,7 @@ impl Context { /// lhsとrhsが包含関係にあるとき小さいほうを返す /// 関係なければNoneを返す - fn rec_min<'t>(&self, lhs: &'t Type, rhs: &'t Type) -> Option<&'t Type> { + pub(crate) fn rec_min<'t>(&self, lhs: &'t Type, rhs: &'t Type) -> Option<&'t Type> { // 同じならどちらを返しても良い match ( self.rec_supertype_of(lhs, rhs), @@ -4133,7 +4141,7 @@ impl Context { } } - fn min<'t>(&self, lhs: &'t Type, rhs: &'t Type) -> Option<&'t Type> { + pub(crate) fn min<'t>(&self, lhs: &'t Type, rhs: &'t Type) -> Option<&'t Type> { // 同じならどちらを返しても良い match (self.supertype_of(lhs, rhs), self.subtype_of(lhs, rhs)) { (true, true) | (true, false) => Some(rhs), diff --git a/compiler/erg_compiler/hir.rs b/compiler/erg_compiler/hir.rs index 12d86900..eabdf3ea 100644 --- a/compiler/erg_compiler/hir.rs +++ b/compiler/erg_compiler/hir.rs @@ -3,7 +3,7 @@ use std::fmt; use erg_common::error::Location; use erg_common::traits::{HasType, Locational, NestedDisplay, Stream}; -use erg_common::ty::{Constraint, TyParam, Type}; +use erg_common::ty::{TyParam, Type}; use erg_common::value::{Field, ValueObj, Visibility}; use erg_common::Str; use erg_common::{ @@ -140,6 +140,16 @@ impl NestedDisplay for Args { } } +impl From> for Args { + fn from(exprs: Vec) -> Self { + Self { + pos_args: exprs.into_iter().map(PosArg::new).collect(), + kw_args: Vec::new(), + paren: None, + } + } +} + impl_display_from_nested!(Args); impl Locational for Args { @@ -501,8 +511,10 @@ pub struct NormalArray { } impl NestedDisplay for NormalArray { - fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, _level: usize) -> fmt::Result { - write!(f, "[{}](: {})", self.elems, self.t) + fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, level: usize) -> fmt::Result { + writeln!(f, "[")?; + self.elems.fmt_nest(f, level + 1)?; + write!(f, "\n{}](: {})", " ".repeat(level), self.t) } } @@ -511,12 +523,7 @@ impl_locational!(NormalArray, l_sqbr, r_sqbr); impl_t!(NormalArray); impl NormalArray { - pub fn new(l_sqbr: Token, r_sqbr: Token, level: usize, elems: Args) -> Self { - let elem_t = elems - .pos_args - .first() - .map(|a| a.expr.t()) - .unwrap_or_else(|| Type::free_var(level, Constraint::TypeOf(Type::Type))); + pub fn new(l_sqbr: Token, r_sqbr: Token, elem_t: Type, elems: Args) -> Self { let t = Type::array(elem_t, TyParam::value(elems.len())); Self { l_sqbr, diff --git a/compiler/erg_compiler/lower.rs b/compiler/erg_compiler/lower.rs index c4e2b3d4..d9551d80 100644 --- a/compiler/erg_compiler/lower.rs +++ b/compiler/erg_compiler/lower.rs @@ -100,21 +100,42 @@ impl ASTLowerer { fn lower_normal_array(&mut self, array: ast::NormalArray) -> LowerResult { log!("[DEBUG] entered {}({array})", fn_name!()); - let mut hir_array = hir::NormalArray::new( - array.l_sqbr, - array.r_sqbr, - self.ctx.level, - hir::Args::empty(), - ); - let inner_t = hir_array.t.ref_t().inner_ts().first().unwrap().clone(); + let mut new_array = vec![]; let (elems, _) = array.elems.into_iters(); + let mut union = Type::Never; for elem in elems { let elem = self.lower_expr(elem.expr)?; - self.ctx - .sub_unify(elem.ref_t(), &inner_t, Some(elem.loc()), None)?; - hir_array.push(elem); + union = self.ctx.rec_union(&union, elem.ref_t()); + if matches!(union, Type::Or(_, _)) { + return Err(LowerError::syntax_error( + line!() as usize, + elem.loc(), + self.ctx.name.clone(), + switch_lang!( + "japanese" => "配列の要素は全て同じ型である必要があります", + "simplified_chinese" => "数组元素必须全部是相同类型", + "traditional_chinese" => "數組元素必須全部是相同類型", + "english" => "all elements of an array must be of the same type", + ), + Some( + switch_lang!( + "japanese" => "Int or Strなど明示的に型を指定してください", + "simplified_chinese" => "明确指定类型,例如:Int or Str", + "traditional_chinese" => "明確指定類型,例如:Int or Str", + "english" => "please specify the type explicitly, e.g. Int or Str", + ) + .into(), + ), + )); + } + new_array.push(elem); } - Ok(hir_array) + Ok(hir::NormalArray::new( + array.l_sqbr, + array.r_sqbr, + union, + hir::Args::from(new_array), + )) } fn lower_array_with_length( diff --git a/compiler/erg_parser/ast.rs b/compiler/erg_parser/ast.rs index 7bbae434..3d87ec35 100644 --- a/compiler/erg_parser/ast.rs +++ b/compiler/erg_parser/ast.rs @@ -420,8 +420,10 @@ pub struct NormalArray { } impl NestedDisplay for NormalArray { - fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, _level: usize) -> fmt::Result { - write!(f, "[{}]", self.elems) + fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, level: usize) -> fmt::Result { + writeln!(f, "[")?; + self.elems.fmt_nest(f, level + 1)?; + write!(f, "\n{}]", " ".repeat(level)) } }