Add LimitedDisplay

This commit is contained in:
Shunsuke Shibayama 2022-08-24 18:51:12 +09:00
parent 7633618e76
commit 0ebb0ce94c
6 changed files with 278 additions and 107 deletions

View file

@ -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),

View file

@ -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<Vec<Expr>> for Args {
fn from(exprs: Vec<Expr>) -> 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,

View file

@ -100,21 +100,42 @@ impl ASTLowerer {
fn lower_normal_array(&mut self, array: ast::NormalArray) -> LowerResult<hir::NormalArray> {
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(