mirror of
https://github.com/erg-lang/erg.git
synced 2025-09-29 12:24:45 +00:00
Add LimitedDisplay
This commit is contained in:
parent
7633618e76
commit
0ebb0ce94c
6 changed files with 278 additions and 107 deletions
|
@ -297,6 +297,10 @@ pub trait ImmutableStream<T>: Sized {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub trait LimitedDisplay {
|
||||||
|
fn limited_fmt(&self, f: &mut std::fmt::Formatter<'_>, limit: usize) -> std::fmt::Result;
|
||||||
|
}
|
||||||
|
|
||||||
// for Runnable::run
|
// for Runnable::run
|
||||||
fn expect_block(src: &str) -> bool {
|
fn expect_block(src: &str) -> bool {
|
||||||
src.ends_with(&['=', ':']) || src.ends_with("->") || src.ends_with("=>")
|
src.ends_with(&['=', ':']) || src.ends_with("->") || src.ends_with("=>")
|
||||||
|
|
|
@ -11,10 +11,10 @@ use crate::codeobj::CodeObj;
|
||||||
use crate::dict::Dict;
|
use crate::dict::Dict;
|
||||||
use crate::rccell::RcCell;
|
use crate::rccell::RcCell;
|
||||||
use crate::set::Set;
|
use crate::set::Set;
|
||||||
use crate::traits::HasType;
|
use crate::traits::{HasType, LimitedDisplay};
|
||||||
use crate::value::ValueObj::{Inf, NegInf};
|
use crate::value::ValueObj::{Inf, NegInf};
|
||||||
use crate::value::{Field, ValueObj};
|
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)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
#[repr(u8)]
|
#[repr(u8)]
|
||||||
|
@ -253,6 +253,24 @@ impl<T: fmt::Display> fmt::Display for FreeKind<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<T: LimitedDisplay> LimitedDisplay for FreeKind<T> {
|
||||||
|
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<T> FreeKind<T> {
|
impl<T> FreeKind<T> {
|
||||||
pub const fn unbound(id: Id, lev: Level, constraint: Constraint) -> Self {
|
pub const fn unbound(id: Id, lev: Level, constraint: Constraint) -> Self {
|
||||||
Self::Unbound {
|
Self::Unbound {
|
||||||
|
@ -289,6 +307,12 @@ impl<T: fmt::Display> fmt::Display for Free<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<T: LimitedDisplay> Free<T> {
|
||||||
|
fn limited_fmt(&self, f: &mut fmt::Formatter<'_>, limit: usize) -> fmt::Result {
|
||||||
|
self.0.borrow().limited_fmt(f, limit)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<T: Clone + HasLevel> Free<T> {
|
impl<T: Clone + HasLevel> Free<T> {
|
||||||
pub fn new(f: FreeKind<T>) -> Self {
|
pub fn new(f: FreeKind<T>) -> Self {
|
||||||
Self(RcCell::new(f))
|
Self(RcCell::new(f))
|
||||||
|
@ -582,21 +606,81 @@ pub enum TyParam {
|
||||||
|
|
||||||
impl fmt::Display for TyParam {
|
impl fmt::Display for TyParam {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
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 {
|
match self {
|
||||||
Self::Value(c) => write!(f, "{c}"),
|
Self::Value(v) => write!(f, "{v}"),
|
||||||
Self::Type(t) => write!(f, "{t}"),
|
Self::Failure => write!(f, "<Failure>"),
|
||||||
Self::Mono(c) => write!(f, "{c}"),
|
Self::Type(t) => t.limited_fmt(f, limit - 1),
|
||||||
Self::MonoProj { obj, attr } => write!(f, "{obj}.{attr}"),
|
Self::FreeVar(fv) => fv.limited_fmt(f, limit - 1),
|
||||||
Self::Array(a) => write!(f, "[{}]", fmt_vec(a)),
|
Self::UnaryOp { op, val } => {
|
||||||
Self::Tuple(t) => write!(f, "({})", fmt_vec(t)),
|
write!(f, "{}", op)?;
|
||||||
Self::App { name, args } => write!(f, "{name}({})", fmt_vec(args)),
|
val.limited_fmt(f, limit - 1)
|
||||||
Self::MonoQVar(name) => write!(f, "'{name}"),
|
}
|
||||||
Self::PolyQVar { name, args } => write!(f, "'{name}({})", fmt_vec(args)),
|
Self::BinOp { op, lhs, rhs } => {
|
||||||
Self::FreeVar(fv) => write!(f, "{fv}"),
|
lhs.limited_fmt(f, limit - 1)?;
|
||||||
Self::UnaryOp { op, val } => write!(f, "{op}{val}"),
|
write!(f, " {} ", op)?;
|
||||||
Self::BinOp { op, lhs, rhs } => write!(f, "{lhs} {op} {rhs}"),
|
rhs.limited_fmt(f, limit - 1)
|
||||||
Self::Erased(t) => write!(f, "_: {t}"),
|
}
|
||||||
Self::Failure => write!(f, "<failure>"),
|
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 {
|
impl fmt::Display for QuantifiedType {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
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,
|
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;
|
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 {
|
impl Default for Type {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self::Failure
|
Self::Failure
|
||||||
|
@ -1968,10 +2136,9 @@ impl HasLevel for Type {
|
||||||
}
|
}
|
||||||
subr.return_t.update_level(level);
|
subr.return_t.update_level(level);
|
||||||
}
|
}
|
||||||
Self::And(ts) | Self::Or(ts) | Self::Not(ts) => {
|
Self::And(lhs, rhs) | Self::Or(lhs, rhs) | Self::Not(lhs, rhs) => {
|
||||||
for t in ts.iter() {
|
lhs.update_level(level);
|
||||||
t.update_level(level);
|
rhs.update_level(level);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Self::Record(attrs) => {
|
Self::Record(attrs) => {
|
||||||
for t in attrs.values() {
|
for t in attrs.values() {
|
||||||
|
@ -2023,10 +2190,9 @@ impl HasLevel for Type {
|
||||||
}
|
}
|
||||||
subr.return_t.lift();
|
subr.return_t.lift();
|
||||||
}
|
}
|
||||||
Self::And(ts) | Self::Or(ts) | Self::Not(ts) => {
|
Self::And(lhs, rhs) | Self::Or(lhs, rhs) | Self::Not(lhs, rhs) => {
|
||||||
for t in ts.iter() {
|
lhs.lift();
|
||||||
t.lift();
|
rhs.lift();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Self::Record(attrs) => {
|
Self::Record(attrs) => {
|
||||||
for t in attrs.values() {
|
for t in attrs.values() {
|
||||||
|
@ -2068,45 +2234,6 @@ impl Type {
|
||||||
pub const NEVER: &'static Self = &Self::Never;
|
pub const NEVER: &'static Self = &Self::Never;
|
||||||
pub const FAILURE: &'static Self = &Self::Failure;
|
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 := {=}
|
/// Top := {=}
|
||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
pub const fn Top() -> Self {
|
pub const fn Top() -> Self {
|
||||||
|
@ -2666,9 +2793,11 @@ impl Type {
|
||||||
(Self::Quantified(l), Self::Quantified(r)) => {
|
(Self::Quantified(l), Self::Quantified(r)) => {
|
||||||
l.unbound_callable.rec_eq(&r.unbound_callable) && l.bounds == r.bounds
|
l.unbound_callable.rec_eq(&r.unbound_callable) && l.bounds == r.bounds
|
||||||
}
|
}
|
||||||
(Self::And(l), Self::And(r))
|
(Self::And(ll, lr), Self::And(rl, rr))
|
||||||
| (Self::Not(l), Self::Not(r))
|
| (Self::Not(ll, lr), Self::Not(rl, rr))
|
||||||
| (Self::Or(l), Self::Or(r)) => l.iter().zip(r.iter()).all(|(l, r)| l.rec_eq(r)),
|
| (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::VarArgs(l), Self::VarArgs(r)) => l.rec_eq(r),
|
||||||
(
|
(
|
||||||
Self::Poly {
|
Self::Poly {
|
||||||
|
@ -2735,9 +2864,9 @@ impl Type {
|
||||||
Self::Inf => "Inf",
|
Self::Inf => "Inf",
|
||||||
Self::NegInf => "NegInf",
|
Self::NegInf => "NegInf",
|
||||||
Self::Mono(name) | Self::MonoQVar(name) => name,
|
Self::Mono(name) | Self::MonoQVar(name) => name,
|
||||||
Self::And(_) => "And",
|
Self::And(_, _) => "And",
|
||||||
Self::Not(_) => "Not",
|
Self::Not(_, _) => "Not",
|
||||||
Self::Or(_) => "Or",
|
Self::Or(_, _) => "Or",
|
||||||
Self::Ref(_) => "Ref",
|
Self::Ref(_) => "Ref",
|
||||||
Self::RefMut(_) => "Ref!",
|
Self::RefMut(_) => "Ref!",
|
||||||
Self::Subr(SubrType {
|
Self::Subr(SubrType {
|
||||||
|
@ -2799,8 +2928,8 @@ impl Type {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Self::Ref(t) | Self::RefMut(t) | Self::VarArgs(t) => t.has_unbound_var(),
|
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) => {
|
Self::And(lhs, rhs) | Self::Not(lhs, rhs) | Self::Or(lhs, rhs) => {
|
||||||
param_ts.iter().any(|t| t.has_unbound_var())
|
lhs.has_unbound_var() || rhs.has_unbound_var()
|
||||||
}
|
}
|
||||||
Self::Callable { param_ts, return_t } => {
|
Self::Callable { param_ts, return_t } => {
|
||||||
param_ts.iter().any(|t| t.has_unbound_var()) || return_t.has_unbound_var()
|
param_ts.iter().any(|t| t.has_unbound_var()) || return_t.has_unbound_var()
|
||||||
|
@ -2838,7 +2967,7 @@ impl Type {
|
||||||
match self {
|
match self {
|
||||||
// REVIEw:
|
// REVIEw:
|
||||||
Self::Ref(_) | Self::RefMut(_) => 1,
|
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) => {
|
Self::Subr(subr) => {
|
||||||
subr.kind.inner_len()
|
subr.kind.inner_len()
|
||||||
+ subr.non_default_params.len()
|
+ subr.non_default_params.len()
|
||||||
|
@ -2856,8 +2985,8 @@ impl Type {
|
||||||
Self::FreeVar(f) if f.is_linked() => f.crack().typarams(),
|
Self::FreeVar(f) if f.is_linked() => f.crack().typarams(),
|
||||||
Self::FreeVar(_unbound) => vec![],
|
Self::FreeVar(_unbound) => vec![],
|
||||||
Self::Ref(t) | Self::RefMut(t) => vec![TyParam::t(*t.clone())],
|
Self::Ref(t) | Self::RefMut(t) => vec![TyParam::t(*t.clone())],
|
||||||
Self::And(param_ts) | Self::Or(param_ts) | Self::Not(param_ts) => {
|
Self::And(lhs, rhs) | Self::Not(lhs, rhs) | Self::Or(lhs, rhs) => {
|
||||||
param_ts.iter().map(|t| TyParam::t(t.clone())).collect()
|
vec![TyParam::t(*lhs.clone()), TyParam::t(*rhs.clone())]
|
||||||
}
|
}
|
||||||
Self::Subr(subr) => {
|
Self::Subr(subr) => {
|
||||||
if let Some(self_t) = subr.kind.self_t() {
|
if let Some(self_t) = subr.kind.self_t() {
|
||||||
|
|
|
@ -2042,7 +2042,7 @@ impl Context {
|
||||||
Ok(Type::var_args(new_t))
|
Ok(Type::var_args(new_t))
|
||||||
}
|
}
|
||||||
Type::Callable { .. } => todo!(),
|
Type::Callable { .. } => todo!(),
|
||||||
Type::And(_) | Type::Or(_) | Type::Not(_) => todo!(),
|
Type::And(_, _) | Type::Or(_, _) | Type::Not(_, _) => todo!(),
|
||||||
other => Ok(other),
|
other => Ok(other),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3705,12 +3705,20 @@ impl Context {
|
||||||
self.structural_supertype_of(q.unbound_callable.as_ref(), r, Some(&q.bounds))
|
self.structural_supertype_of(q.unbound_callable.as_ref(), r, Some(&q.bounds))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
(lhs, Or(tys)) => tys
|
(Or(l_or, r_or), rhs) =>
|
||||||
.iter()
|
self.structural_supertype_of(l_or, rhs, bounds)
|
||||||
.all(|t| self.structural_supertype_of(lhs, t, bounds)),
|
|| self.structural_supertype_of(r_or, rhs, bounds),
|
||||||
(And(tys), rhs) => tys
|
(lhs, Or(or_l, or_r)) =>
|
||||||
.iter()
|
self.structural_supertype_of(lhs, or_l, bounds)
|
||||||
.all(|t| self.structural_supertype_of(t, rhs, 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),
|
(VarArgs(lhs), rhs) => self.structural_supertype_of(lhs, rhs, bounds),
|
||||||
// TはすべてのRef(T)のメソッドを持つので、Ref(T)のサブタイプ
|
// TはすべてのRef(T)のメソッドを持つので、Ref(T)のサブタイプ
|
||||||
(Ref(lhs), rhs) | (RefMut(lhs), rhs) => self.structural_supertype_of(lhs, rhs, bounds),
|
(Ref(lhs), rhs) | (RefMut(lhs), rhs) => self.structural_supertype_of(lhs, rhs, bounds),
|
||||||
|
@ -3917,7 +3925,7 @@ impl Context {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 和集合(A or B)を返す
|
/// 和集合(A or B)を返す
|
||||||
fn rec_union(&self, lhs: &Type, rhs: &Type) -> Type {
|
pub(crate) fn rec_union(&self, lhs: &Type, rhs: &Type) -> Type {
|
||||||
match (
|
match (
|
||||||
self.rec_supertype_of(lhs, rhs),
|
self.rec_supertype_of(lhs, rhs),
|
||||||
self.rec_subtype_of(lhs, rhs),
|
self.rec_subtype_of(lhs, rhs),
|
||||||
|
@ -4101,7 +4109,7 @@ impl Context {
|
||||||
|
|
||||||
/// lhsとrhsが包含関係にあるとき小さいほうを返す
|
/// lhsとrhsが包含関係にあるとき小さいほうを返す
|
||||||
/// 関係なければNoneを返す
|
/// 関係なければ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 (
|
match (
|
||||||
self.rec_supertype_of(lhs, rhs),
|
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)) {
|
match (self.supertype_of(lhs, rhs), self.subtype_of(lhs, rhs)) {
|
||||||
(true, true) | (true, false) => Some(rhs),
|
(true, true) | (true, false) => Some(rhs),
|
||||||
|
|
|
@ -3,7 +3,7 @@ use std::fmt;
|
||||||
|
|
||||||
use erg_common::error::Location;
|
use erg_common::error::Location;
|
||||||
use erg_common::traits::{HasType, Locational, NestedDisplay, Stream};
|
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::value::{Field, ValueObj, Visibility};
|
||||||
use erg_common::Str;
|
use erg_common::Str;
|
||||||
use erg_common::{
|
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_display_from_nested!(Args);
|
||||||
|
|
||||||
impl Locational for Args {
|
impl Locational for Args {
|
||||||
|
@ -501,8 +511,10 @@ pub struct NormalArray {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl NestedDisplay for NormalArray {
|
impl NestedDisplay for NormalArray {
|
||||||
fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, _level: usize) -> fmt::Result {
|
fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, level: usize) -> fmt::Result {
|
||||||
write!(f, "[{}](: {})", self.elems, self.t)
|
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_t!(NormalArray);
|
||||||
|
|
||||||
impl NormalArray {
|
impl NormalArray {
|
||||||
pub fn new(l_sqbr: Token, r_sqbr: Token, level: usize, elems: Args) -> Self {
|
pub fn new(l_sqbr: Token, r_sqbr: Token, elem_t: Type, 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)));
|
|
||||||
let t = Type::array(elem_t, TyParam::value(elems.len()));
|
let t = Type::array(elem_t, TyParam::value(elems.len()));
|
||||||
Self {
|
Self {
|
||||||
l_sqbr,
|
l_sqbr,
|
||||||
|
|
|
@ -100,21 +100,42 @@ impl ASTLowerer {
|
||||||
|
|
||||||
fn lower_normal_array(&mut self, array: ast::NormalArray) -> LowerResult<hir::NormalArray> {
|
fn lower_normal_array(&mut self, array: ast::NormalArray) -> LowerResult<hir::NormalArray> {
|
||||||
log!("[DEBUG] entered {}({array})", fn_name!());
|
log!("[DEBUG] entered {}({array})", fn_name!());
|
||||||
let mut hir_array = hir::NormalArray::new(
|
let mut new_array = vec![];
|
||||||
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 (elems, _) = array.elems.into_iters();
|
let (elems, _) = array.elems.into_iters();
|
||||||
|
let mut union = Type::Never;
|
||||||
for elem in elems {
|
for elem in elems {
|
||||||
let elem = self.lower_expr(elem.expr)?;
|
let elem = self.lower_expr(elem.expr)?;
|
||||||
self.ctx
|
union = self.ctx.rec_union(&union, elem.ref_t());
|
||||||
.sub_unify(elem.ref_t(), &inner_t, Some(elem.loc()), None)?;
|
if matches!(union, Type::Or(_, _)) {
|
||||||
hir_array.push(elem);
|
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(
|
fn lower_array_with_length(
|
||||||
|
|
|
@ -420,8 +420,10 @@ pub struct NormalArray {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl NestedDisplay for NormalArray {
|
impl NestedDisplay for NormalArray {
|
||||||
fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, _level: usize) -> fmt::Result {
|
fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, level: usize) -> fmt::Result {
|
||||||
write!(f, "[{}]", self.elems)
|
writeln!(f, "[")?;
|
||||||
|
self.elems.fmt_nest(f, level + 1)?;
|
||||||
|
write!(f, "\n{}]", " ".repeat(level))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue