Implement ProjMethod

This commit is contained in:
Shunsuke Shibayama 2022-10-11 16:08:49 +09:00
parent 9fd98001fe
commit 9c3acc8e19
22 changed files with 1087 additions and 697 deletions

View file

@ -99,7 +99,7 @@ impl HIRBuilder {
Ok(hir) Ok(hir)
} }
pub fn pop_ctx(&mut self) -> Context { pub fn pop_mod_ctx(&mut self) -> Context {
self.lowerer.ctx.pop() self.lowerer.ctx.pop_mod()
} }
} }

View file

@ -223,6 +223,7 @@ fn convert_to_python_attr(class: &str, uniq_obj_name: Option<&str>, name: Str) -
("File!", _, "read!") => Str::ever("read"), ("File!", _, "read!") => Str::ever("read"),
(_, _, "__new__") => Str::ever("__call__"), (_, _, "__new__") => Str::ever("__call__"),
(_, _, "to_str") => Str::ever("__str__"), (_, _, "to_str") => Str::ever("__str__"),
(_, _, "__Tuple_getitem__") => Str::ever("__getitem__"),
("StringIO!", _, "getvalue!") => Str::ever("getvalue"), ("StringIO!", _, "getvalue!") => Str::ever("getvalue"),
("Module", Some("importlib"), "reload!") => Str::ever("reload"), ("Module", Some("importlib"), "reload!") => Str::ever("reload"),
("Module", Some("random"), "randint!") => Str::ever("randint"), ("Module", Some("random"), "randint!") => Str::ever("randint"),

View file

@ -1,11 +1,13 @@
//! provides type-comparison //! provides type-comparison
use std::option::Option; // conflicting to Type::Option use std::option::Option; // conflicting to Type::Option
use erg_common::error::Location; use erg_common::error::{Location, MultiErrorDisplay};
use erg_type::constructors::{and, or}; use erg_type::constructors::{and, or};
use erg_type::free::fresh_varname; use erg_type::free::fresh_varname;
use erg_type::free::{Constraint, Cyclicity, FreeKind, FreeTyVar}; use erg_type::free::{Constraint, Cyclicity, FreeKind, FreeTyVar};
use erg_type::typaram::{TyParam, TyParamOrdering}; use erg_type::typaram::{OpKind, TyParam, TyParamOrdering};
use erg_type::value::ValueObj;
use erg_type::value::ValueObj::Inf; use erg_type::value::ValueObj::Inf;
use erg_type::{Predicate, RefinementType, SubrKind, SubrType, Type}; use erg_type::{Predicate, RefinementType, SubrKind, SubrType, Type};
use Predicate as Pred; use Predicate as Pred;
@ -103,6 +105,9 @@ impl Context {
FreeKind::Unbound { constraint, .. } FreeKind::Unbound { constraint, .. }
| FreeKind::NamedUnbound { constraint, .. } => { | FreeKind::NamedUnbound { constraint, .. } => {
let t = constraint.get_type().unwrap(); let t = constraint.get_type().unwrap();
if cfg!(feature = "debug") && t == &Uninited {
panic!("Uninited type variable: {fv}");
}
let other_t = self.type_of(other); let other_t = self.type_of(other);
return self.same_type_of(t, &other_t); return self.same_type_of(t, &other_t);
} }
@ -168,6 +173,7 @@ impl Context {
Absolutely, Absolutely,
rec.iter().all(|(_, attr)| self.supertype_of(&Type, attr)), rec.iter().all(|(_, attr)| self.supertype_of(&Type, attr)),
), ),
(Type::Uninited, _) | (_, Type::Uninited) => panic!("used an uninited type variable"),
(Type, Subr(subr)) => ( (Type, Subr(subr)) => (
Absolutely, Absolutely,
subr.non_default_params subr.non_default_params
@ -628,7 +634,23 @@ impl Context {
if ln != rn || lparams.len() != rparams.len() { if ln != rn || lparams.len() != rparams.len() {
return false; return false;
} }
self.poly_supertype_of(lhs, lparams, rparams) // [Int; 2] :> [Int; 3]
if &ln[..] == "Array" || &ln[..] == "Set" {
let lt = &lparams[0].as_type().unwrap();
let rt = &rparams[0].as_type().unwrap();
let llen = &lparams[1];
let rlen = &rparams[1];
self.supertype_of(lt, rt)
&& self
.eval_bin_tp(OpKind::Le, llen, rlen)
.map(|tp| matches!(tp, TyParam::Value(ValueObj::Bool(true))))
.unwrap_or_else(|e| {
e.fmt_all_stderr();
todo!();
})
} else {
self.poly_supertype_of(lhs, lparams, rparams)
}
} }
// `Eq(Set(T, N)) :> Set(T, N)` will be false, such cases are judged by nominal_supertype_of // `Eq(Set(T, N)) :> Set(T, N)` will be false, such cases are judged by nominal_supertype_of
( (
@ -654,7 +676,7 @@ impl Context {
(l, MonoQVar(name)) | (l, PolyQVar { name, .. }) => { (l, MonoQVar(name)) | (l, PolyQVar { name, .. }) => {
panic!("internal error: not instantiated type variable: '{name}, l: {l}") panic!("internal error: not instantiated type variable: '{name}, l: {l}")
} }
(MonoProj { .. }, _) => { (Proj { .. }, _) => {
if let Some(cands) = self.get_candidates(lhs) { if let Some(cands) = self.get_candidates(lhs) {
for cand in cands.into_iter() { for cand in cands.into_iter() {
if self.supertype_of(&cand, rhs) { if self.supertype_of(&cand, rhs) {
@ -664,7 +686,7 @@ impl Context {
} }
false false
} }
(_, MonoProj { .. }) => { (_, Proj { .. }) => {
if let Some(cands) = self.get_candidates(rhs) { if let Some(cands) = self.get_candidates(rhs) {
for cand in cands.into_iter() { for cand in cands.into_iter() {
if self.supertype_of(lhs, &cand) { if self.supertype_of(lhs, &cand) {
@ -700,7 +722,6 @@ impl Context {
super_class super_class
}; };
if self.cyclic_supertype_of(lhs, &sup_class) { if self.cyclic_supertype_of(lhs, &sup_class) {
log!(err "引っかかった: {lhs}, {sup_class}");
return true; return true;
} }
} }
@ -714,6 +735,11 @@ impl Context {
lparams: &[TyParam], lparams: &[TyParam],
rparams: &[TyParam], rparams: &[TyParam],
) -> bool { ) -> bool {
log!(
"poly_supertype_of: {typ}, {}, {}",
erg_common::fmt_vec(lparams),
erg_common::fmt_vec(rparams)
);
let ctx = self let ctx = self
.get_nominal_type_ctx(typ) .get_nominal_type_ctx(typ)
.unwrap_or_else(|| panic!("{typ} is not found")); .unwrap_or_else(|| panic!("{typ} is not found"));
@ -731,6 +757,18 @@ impl Context {
// if matches!(r.as_ref(), &Type::Refinement(_)) { log!(info "{l}, {r}, {}", self.structural_supertype_of(l, r, bounds, Some(lhs_variance))); } // if matches!(r.as_ref(), &Type::Refinement(_)) { log!(info "{l}, {r}, {}", self.structural_supertype_of(l, r, bounds, Some(lhs_variance))); }
self.supertype_of(l, r) self.supertype_of(l, r)
} }
(TyParam::FreeVar(fv), _, _) if fv.is_unbound() => {
let fv_t = fv.get_type().unwrap();
let rp_t = self.get_tp_t(rp).unwrap();
log!("{fv_t}, {rp_t}, {variance}");
if variance == &Variance::Contravariant {
self.subtype_of(&fv_t, &rp_t)
} else if variance == &Variance::Covariant {
self.supertype_of(&fv_t, &rp_t)
} else {
self.same_type_of(&fv_t, &rp_t)
}
}
// Invariant // Invariant
_ => self.eq_tp(lp, rp), _ => self.eq_tp(lp, rp),
}) })
@ -777,10 +815,10 @@ impl Context {
// try_cmp((n: 2.._), 1) -> Some(Greater) // try_cmp((n: 2.._), 1) -> Some(Greater)
// try_cmp((n: -1.._), 1) -> Some(Any) // try_cmp((n: -1.._), 1) -> Some(Any)
(l @ (TyParam::Erased(_) | TyParam::FreeVar(_) | TyParam::MonoQVar(_)), p) => { (l @ (TyParam::Erased(_) | TyParam::FreeVar(_) | TyParam::MonoQVar(_)), p) => {
let t = self.get_tp_t(l).unwrap(); let lt = self.get_tp_t(l).unwrap();
let inf = self.inf(&t); let l_inf = self.inf(&lt);
let sup = self.sup(&t); let l_sup = self.sup(&lt);
if let (Some(inf), Some(sup)) = (inf, sup) { if let (Some(inf), Some(sup)) = (l_inf, l_sup) {
// (n: Int, 1) -> (-inf..inf, 1) -> (cmp(-inf, 1), cmp(inf, 1)) -> (Less, Greater) -> Any // (n: Int, 1) -> (-inf..inf, 1) -> (cmp(-inf, 1), cmp(inf, 1)) -> (Less, Greater) -> Any
// (n: 5..10, 2) -> (cmp(5..10, 2), cmp(5..10, 2)) -> (Greater, Greater) -> Greater // (n: 5..10, 2) -> (cmp(5..10, 2), cmp(5..10, 2)) -> (Greater, Greater) -> Greater
match ( match (
@ -935,7 +973,7 @@ impl Context {
(Pred::Equal { rhs, .. }, Pred::Equal { rhs: rhs2, .. }) (Pred::Equal { rhs, .. }, Pred::Equal { rhs: rhs2, .. })
| (Pred::NotEqual { rhs, .. }, Pred::NotEqual { rhs: rhs2, .. }) => self | (Pred::NotEqual { rhs, .. }, Pred::NotEqual { rhs: rhs2, .. }) => self
.try_cmp(rhs, rhs2) .try_cmp(rhs, rhs2)
.map(|ord| ord.is_eq()) .map(|ord| ord.canbe_eq())
.unwrap_or(false), .unwrap_or(false),
// {T >= 0} :> {T >= 1}, {T >= 0} :> {T == 1} // {T >= 0} :> {T >= 1}, {T >= 0} :> {T == 1}
( (
@ -943,14 +981,14 @@ impl Context {
Pred::GreaterEqual { rhs: rhs2, .. } | Pred::Equal { rhs: rhs2, .. }, Pred::GreaterEqual { rhs: rhs2, .. } | Pred::Equal { rhs: rhs2, .. },
) => self ) => self
.try_cmp(rhs, rhs2) .try_cmp(rhs, rhs2)
.map(|ord| ord.is_le()) .map(|ord| ord.canbe_le())
.unwrap_or(false), .unwrap_or(false),
( (
Pred::LessEqual { rhs, .. }, Pred::LessEqual { rhs, .. },
Pred::LessEqual { rhs: rhs2, .. } | Pred::Equal { rhs: rhs2, .. }, Pred::LessEqual { rhs: rhs2, .. } | Pred::Equal { rhs: rhs2, .. },
) => self ) => self
.try_cmp(rhs, rhs2) .try_cmp(rhs, rhs2)
.map(|ord| ord.is_ge()) .map(|ord| ord.canbe_ge())
.unwrap_or(false), .unwrap_or(false),
(lhs @ (Pred::GreaterEqual { .. } | Pred::LessEqual { .. }), Pred::And(l, r)) => { (lhs @ (Pred::GreaterEqual { .. } | Pred::LessEqual { .. }), Pred::And(l, r)) => {
self.is_super_pred_of(lhs, l) || self.is_super_pred_of(lhs, r) self.is_super_pred_of(lhs, l) || self.is_super_pred_of(lhs, r)

View file

@ -15,8 +15,9 @@ use OpKind::*;
use erg_parser::ast::*; use erg_parser::ast::*;
use erg_parser::token::{Token, TokenKind}; use erg_parser::token::{Token, TokenKind};
use erg_type::constructors::proj_method;
use erg_type::constructors::{ use erg_type::constructors::{
builtin_mono, builtin_poly, mono_proj, not, poly, ref_, ref_mut, refinement, subr_t, v_enum, array, builtin_mono, builtin_poly, not, poly, proj, ref_, ref_mut, refinement, subr_t, v_enum,
}; };
use erg_type::typaram::{OpKind, TyParam}; use erg_type::typaram::{OpKind, TyParam};
use erg_type::value::ValueObj; use erg_type::value::ValueObj;
@ -130,7 +131,9 @@ impl<'c> SubstContext<'c> {
/// ///
/// `ctx` is used to obtain information on the names and variance of the parameters. /// `ctx` is used to obtain information on the names and variance of the parameters.
pub fn new(substituted: &Type, ctx: &'c Context, loc: Location) -> Self { pub fn new(substituted: &Type, ctx: &'c Context, loc: Location) -> Self {
let ty_ctx = ctx.get_nominal_type_ctx(substituted).unwrap(); let ty_ctx = ctx
.get_nominal_type_ctx(substituted)
.unwrap_or_else(|| todo!("{substituted} not found"));
let bounds = ty_ctx.type_params_bounds(); let bounds = ty_ctx.type_params_bounds();
let param_names = ty_ctx.params.iter().map(|(opt_name, _)| { let param_names = ty_ctx.params.iter().map(|(opt_name, _)| {
opt_name opt_name
@ -203,7 +206,7 @@ impl<'c> SubstContext<'c> {
TyParam::Type(t) => { TyParam::Type(t) => {
self.substitute_t(t)?; self.substitute_t(t)?;
} }
TyParam::MonoProj { obj, .. } => { TyParam::Proj { obj, .. } => {
self.substitute_tp(obj)?; self.substitute_tp(obj)?;
} }
_ => {} _ => {}
@ -240,7 +243,7 @@ impl<'c> SubstContext<'c> {
self.substitute_t(l)?; self.substitute_t(l)?;
self.substitute_t(r)?; self.substitute_t(r)?;
} }
Type::MonoProj { lhs, .. } => { Type::Proj { lhs, .. } => {
self.substitute_t(lhs)?; self.substitute_t(lhs)?;
} }
Type::Record(rec) => { Type::Record(rec) => {
@ -678,6 +681,20 @@ impl Context {
line!(), line!(),
)) ))
}), }),
Lt => lhs.try_lt(rhs).ok_or_else(|| {
EvalErrors::from(EvalError::unreachable(
self.cfg.input.clone(),
fn_name!(),
line!(),
))
}),
Le => lhs.try_le(rhs).ok_or_else(|| {
EvalErrors::from(EvalError::unreachable(
self.cfg.input.clone(),
fn_name!(),
line!(),
))
}),
Eq => lhs.try_eq(rhs).ok_or_else(|| { Eq => lhs.try_eq(rhs).ok_or_else(|| {
EvalErrors::from(EvalError::unreachable( EvalErrors::from(EvalError::unreachable(
self.cfg.input.clone(), self.cfg.input.clone(),
@ -710,8 +727,10 @@ impl Context {
.eval_bin(op, lhs.clone(), rhs.clone()) .eval_bin(op, lhs.clone(), rhs.clone())
.map(TyParam::value), .map(TyParam::value),
(TyParam::FreeVar(fv), r) if fv.is_linked() => self.eval_bin_tp(op, &*fv.crack(), r), (TyParam::FreeVar(fv), r) if fv.is_linked() => self.eval_bin_tp(op, &*fv.crack(), r),
(TyParam::FreeVar(_), _) if op.is_comparison() => Ok(TyParam::value(true)),
(TyParam::FreeVar(_), _) => Ok(TyParam::bin(op, lhs.clone(), rhs.clone())), (TyParam::FreeVar(_), _) => Ok(TyParam::bin(op, lhs.clone(), rhs.clone())),
(l, TyParam::FreeVar(fv)) if fv.is_linked() => self.eval_bin_tp(op, l, &*fv.crack()), (l, TyParam::FreeVar(fv)) if fv.is_linked() => self.eval_bin_tp(op, l, &*fv.crack()),
(_, TyParam::FreeVar(_)) if op.is_comparison() => Ok(TyParam::value(true)),
(_, TyParam::FreeVar(_)) => Ok(TyParam::bin(op, lhs.clone(), rhs.clone())), (_, TyParam::FreeVar(_)) => Ok(TyParam::bin(op, lhs.clone(), rhs.clone())),
(e @ TyParam::Erased(_), _) | (_, e @ TyParam::Erased(_)) => Ok(e.clone()), (e @ TyParam::Erased(_), _) | (_, e @ TyParam::Erased(_)) => Ok(e.clone()),
(l, r) => todo!("{l} {op} {r}"), (l, r) => todo!("{l} {op} {r}"),
@ -759,6 +778,20 @@ impl Context {
TyParam::BinOp { op, lhs, rhs } => self.eval_bin_tp(*op, lhs, rhs), TyParam::BinOp { op, lhs, rhs } => self.eval_bin_tp(*op, lhs, rhs),
TyParam::UnaryOp { op, val } => self.eval_unary_tp(*op, val), TyParam::UnaryOp { op, val } => self.eval_unary_tp(*op, val),
TyParam::App { name, args } => self.eval_app(name, args), TyParam::App { name, args } => self.eval_app(name, args),
TyParam::Array(tps) => {
let mut new_tps = Vec::with_capacity(tps.len());
for tp in tps {
new_tps.push(self.eval_tp(tp)?);
}
Ok(TyParam::Array(new_tps))
}
TyParam::Tuple(tps) => {
let mut new_tps = Vec::with_capacity(tps.len());
for tp in tps {
new_tps.push(self.eval_tp(tp)?);
}
Ok(TyParam::Tuple(new_tps))
}
p @ (TyParam::Type(_) p @ (TyParam::Type(_)
| TyParam::Erased(_) | TyParam::Erased(_)
| TyParam::Value(_) | TyParam::Value(_)
@ -813,106 +846,12 @@ impl Context {
// [?T; 0].MutType! == [?T; !0] // [?T; 0].MutType! == [?T; !0]
// ?T(<: Add(?R(:> Int))).Output == ?T(<: Add(?R)).Output // ?T(<: Add(?R(:> Int))).Output == ?T(<: Add(?R)).Output
// ?T(:> Int, <: Add(?R(:> Int))).Output == Int // ?T(:> Int, <: Add(?R(:> Int))).Output == Int
Type::MonoProj { lhs, rhs } => { Type::Proj { lhs, rhs } => self.eval_proj(*lhs, rhs, level, t_loc),
// Currently Erg does not allow projection-types to be evaluated with type variables included. Type::ProjMethod {
// All type variables will be dereferenced or fail. lhs,
let (sub, opt_sup) = match *lhs.clone() { method_name,
Type::FreeVar(fv) if fv.is_linked() => { args,
return self.eval_t_params(mono_proj(fv.crack().clone(), rhs), level, t_loc) } => self.eval_proj_method(*lhs, method_name, args, level, t_loc),
}
Type::FreeVar(fv) if fv.is_unbound() => {
let (sub, sup) = fv.get_bound_types().unwrap();
(sub, Some(sup))
}
other => (other, None),
};
// cannot determine at this point
if sub == Type::Never {
return Ok(mono_proj(*lhs, rhs));
}
for ty_ctx in self.get_nominal_super_type_ctxs(&sub).ok_or_else(|| {
EvalError::no_var_error(
self.cfg.input.clone(),
line!() as usize,
t_loc,
self.caused_by(),
&rhs,
None, // TODO:
)
})? {
if let Ok(obj) = ty_ctx.get_const_local(&Token::symbol(&rhs), &self.name) {
if let ValueObj::Type(quant_t) = obj {
let subst_ctx = SubstContext::new(&sub, self, t_loc);
let t = subst_ctx.substitute(quant_t.typ().clone())?;
let t = self.eval_t_params(t, level, t_loc)?;
return Ok(t);
} else {
todo!()
}
}
for (class, methods) in ty_ctx.methods_list.iter() {
match (class, &opt_sup) {
(ClassDefType::ImplTrait { impl_trait, .. }, Some(sup)) => {
if !self.supertype_of(impl_trait, sup) {
continue;
}
}
(ClassDefType::ImplTrait { impl_trait, .. }, None) => {
if !self.supertype_of(impl_trait, &sub) {
continue;
}
}
_ => {}
}
if let Ok(obj) = methods.get_const_local(&Token::symbol(&rhs), &self.name) {
if let ValueObj::Type(quant_t) = obj {
let subst_ctx = SubstContext::new(&sub, self, t_loc);
let t = subst_ctx.substitute(quant_t.typ().clone())?;
let t = self.eval_t_params(t, level, t_loc)?;
return Ok(t);
} else {
todo!()
}
}
}
}
if lhs.is_unbound_var() {
let (sub, sup) = enum_unwrap!(lhs.as_ref(), Type::FreeVar)
.get_bound_types()
.unwrap();
if self.is_trait(&sup) && !self.trait_impl_exists(&sub, &sup) {
return Err(EvalErrors::from(EvalError::no_trait_impl_error(
self.cfg.input.clone(),
line!() as usize,
&sub,
&sup,
t_loc,
self.caused_by(),
None,
)));
}
}
// if the target can't be found in the supertype, the type will be dereferenced.
// In many cases, it is still better to determine the type variable than if the target is not found.
let coerced = self.deref_tyvar(*lhs.clone(), Variance::Covariant, t_loc)?;
if lhs.as_ref() != &coerced {
let proj = mono_proj(coerced, rhs);
self.eval_t_params(proj, level, t_loc).map(|t| {
self.coerce(&lhs);
t
})
} else {
let proj = mono_proj(*lhs, rhs);
Err(EvalErrors::from(EvalError::no_candidate_error(
self.cfg.input.clone(),
line!() as usize,
&proj,
t_loc,
self.caused_by(),
self.get_no_candidate_hint(&proj),
)))
}
}
Type::Ref(l) => Ok(ref_(self.eval_t_params(*l, level, t_loc)?)), Type::Ref(l) => Ok(ref_(self.eval_t_params(*l, level, t_loc)?)),
Type::RefMut { before, after } => { Type::RefMut { before, after } => {
let before = self.eval_t_params(*before, level, t_loc)?; let before = self.eval_t_params(*before, level, t_loc)?;
@ -964,6 +903,197 @@ impl Context {
} }
} }
fn eval_proj(&self, lhs: Type, rhs: Str, level: usize, t_loc: Location) -> EvalResult<Type> {
// Currently Erg does not allow projection-types to be evaluated with type variables included.
// All type variables will be dereferenced or fail.
let (sub, opt_sup) = match lhs.clone() {
Type::FreeVar(fv) if fv.is_linked() => {
return self.eval_t_params(proj(fv.crack().clone(), rhs), level, t_loc)
}
Type::FreeVar(fv) if fv.is_unbound() => {
let (sub, sup) = fv.get_bound_types().unwrap();
(sub, Some(sup))
}
other => (other, None),
};
// cannot determine at this point
if sub == Type::Never {
return Ok(proj(lhs, rhs));
}
for ty_ctx in self.get_nominal_super_type_ctxs(&sub).ok_or_else(|| {
EvalError::no_var_error(
self.cfg.input.clone(),
line!() as usize,
t_loc,
self.caused_by(),
&rhs,
None, // TODO:
)
})? {
if let Ok(obj) = ty_ctx.get_const_local(&Token::symbol(&rhs), &self.name) {
if let ValueObj::Type(quant_t) = obj {
let subst_ctx = SubstContext::new(&sub, self, t_loc);
let t = subst_ctx.substitute(quant_t.typ().clone())?;
let t = self.eval_t_params(t, level, t_loc)?;
return Ok(t);
} else {
todo!()
}
}
for (class, methods) in ty_ctx.methods_list.iter() {
match (class, &opt_sup) {
(ClassDefType::ImplTrait { impl_trait, .. }, Some(sup)) => {
if !self.supertype_of(impl_trait, sup) {
continue;
}
}
(ClassDefType::ImplTrait { impl_trait, .. }, None) => {
if !self.supertype_of(impl_trait, &sub) {
continue;
}
}
_ => {}
}
if let Ok(obj) = methods.get_const_local(&Token::symbol(&rhs), &self.name) {
if let ValueObj::Type(quant_t) = obj {
let subst_ctx = SubstContext::new(&sub, self, t_loc);
let t = subst_ctx.substitute(quant_t.typ().clone())?;
let t = self.eval_t_params(t, level, t_loc)?;
return Ok(t);
} else {
todo!()
}
}
}
}
if lhs.is_unbound_var() {
let (sub, sup) = enum_unwrap!(&lhs, Type::FreeVar).get_bound_types().unwrap();
if self.is_trait(&sup) && !self.trait_impl_exists(&sub, &sup) {
return Err(EvalErrors::from(EvalError::no_trait_impl_error(
self.cfg.input.clone(),
line!() as usize,
&sub,
&sup,
t_loc,
self.caused_by(),
None,
)));
}
}
// if the target can't be found in the supertype, the type will be dereferenced.
// In many cases, it is still better to determine the type variable than if the target is not found.
let coerced = self.deref_tyvar(lhs.clone(), Variance::Covariant, t_loc)?;
if lhs != coerced {
let proj = proj(coerced, rhs);
self.eval_t_params(proj, level, t_loc).map(|t| {
self.coerce(&lhs);
t
})
} else {
let proj = proj(lhs, rhs);
Err(EvalErrors::from(EvalError::no_candidate_error(
self.cfg.input.clone(),
line!() as usize,
&proj,
t_loc,
self.caused_by(),
self.get_no_candidate_hint(&proj),
)))
}
}
fn eval_proj_method(
&self,
lhs: TyParam,
method_name: Str,
args: Vec<TyParam>,
level: usize,
t_loc: Location,
) -> EvalResult<Type> {
let t = self.get_tp_t(&lhs)?;
for ty_ctx in self.get_nominal_super_type_ctxs(&t).ok_or_else(|| {
EvalError::no_var_error(
self.cfg.input.clone(),
line!() as usize,
t_loc,
self.caused_by(),
&method_name,
None, // TODO:
)
})? {
if let Ok(obj) = ty_ctx.get_const_local(&Token::symbol(&method_name), &self.name) {
if let ValueObj::Subr(subr) = obj {
let is_method = subr.sig_t().self_t().is_some();
let mut pos_args = vec![];
if is_method {
pos_args.push(ValueObj::try_from(lhs).unwrap());
}
for pos_arg in args.into_iter() {
pos_args.push(ValueObj::try_from(pos_arg).unwrap());
}
let args = ValueArgs::new(pos_args, dict! {});
let t = self.call(subr, args, None, t_loc)?;
let t = enum_unwrap!(t, ValueObj::Type); // TODO: error handling
return Ok(t.into_typ());
} else {
todo!()
}
}
for (_class, methods) in ty_ctx.methods_list.iter() {
if let Ok(obj) = methods.get_const_local(&Token::symbol(&method_name), &self.name) {
if let ValueObj::Subr(subr) = obj {
let mut pos_args = vec![];
for pos_arg in args.into_iter() {
pos_args.push(ValueObj::try_from(pos_arg).unwrap());
}
let args = ValueArgs::new(pos_args, dict! {});
let t = self.call(subr, args, None, t_loc)?;
let t = enum_unwrap!(t, ValueObj::Type); // TODO: error handling
return Ok(t.into_typ());
} else {
todo!()
}
}
}
}
if lhs.is_unbound_var() {
let (sub, sup) = enum_unwrap!(&lhs, TyParam::FreeVar)
.get_bound_types()
.unwrap();
if self.is_trait(&sup) && !self.trait_impl_exists(&sub, &sup) {
return Err(EvalErrors::from(EvalError::no_trait_impl_error(
self.cfg.input.clone(),
line!() as usize,
&sub,
&sup,
t_loc,
self.caused_by(),
None,
)));
}
}
// if the target can't be found in the supertype, the type will be dereferenced.
// In many cases, it is still better to determine the type variable than if the target is not found.
let coerced = self.deref_tp(lhs.clone(), Variance::Covariant, t_loc)?;
if lhs != coerced {
let proj = proj_method(coerced, method_name, args);
self.eval_t_params(proj, level, t_loc).map(|t| {
self.coerce_tp(&lhs);
t
})
} else {
let proj = proj_method(lhs, method_name, args);
Err(EvalErrors::from(EvalError::no_candidate_error(
self.cfg.input.clone(),
line!() as usize,
&proj,
t_loc,
self.caused_by(),
self.get_no_candidate_hint(&proj),
)))
}
}
pub(crate) fn _eval_bound( pub(crate) fn _eval_bound(
&self, &self,
bound: TyBound, bound: TyBound,
@ -1010,8 +1140,18 @@ impl Context {
todo!() todo!()
} }
} }
// TODO: Class, Trait TyParam::Type(typ) => {
TyParam::Type(_) => Ok(Type::Type), if let Some(ctx) = self.get_nominal_type_ctx(&typ) {
let t = match ctx.kind {
ContextKind::Class => Type::ClassType,
ContextKind::Trait | ContextKind::StructuralTrait => Type::TraitType,
_ => unreachable!(),
};
Ok(t)
} else {
Ok(Type::Type)
}
}
TyParam::Mono(name) => self TyParam::Mono(name) => self
.rec_get_const_obj(&name) .rec_get_const_obj(&name)
.map(|v| v_enum(set![v.clone()])) .map(|v| v_enum(set![v.clone()]))
@ -1025,6 +1165,11 @@ impl Context {
TyParam::MonoQVar(name) => { TyParam::MonoQVar(name) => {
panic!("Not instantiated type variable: {name}") panic!("Not instantiated type variable: {name}")
} }
TyParam::Array(tps) => {
let tp_t = self.get_tp_t(&tps[0])?;
let t = array(tp_t, TyParam::value(tps.len()));
Ok(t)
}
TyParam::UnaryOp { op, val } => match op { TyParam::UnaryOp { op, val } => match op {
OpKind::Mutate => Ok(self.get_tp_t(&val)?.mutate()), OpKind::Mutate => Ok(self.get_tp_t(&val)?.mutate()),
_ => todo!(), _ => todo!(),

View file

@ -49,7 +49,7 @@ impl Context {
pub(crate) fn get_no_candidate_hint(&self, proj: &Type) -> Option<AtomicStr> { pub(crate) fn get_no_candidate_hint(&self, proj: &Type) -> Option<AtomicStr> {
match proj { match proj {
Type::MonoProj { lhs, rhs: _ } => { Type::Proj { lhs, rhs: _ } => {
if let Type::FreeVar(fv) = lhs.as_ref() { if let Type::FreeVar(fv) = lhs.as_ref() {
let (sub, sup) = fv.get_bound_types()?; let (sub, sup) = fv.get_bound_types()?;
// TODO: automating // TODO: automating

View file

@ -1,7 +1,7 @@
use std::mem; use std::mem;
use std::path::PathBuf; use std::path::PathBuf;
use erg_common::Str; use erg_common::{enum_unwrap, Str};
use erg_common::astr::AtomicStr; use erg_common::astr::AtomicStr;
use erg_common::color::{RED, RESET, YELLOW}; use erg_common::color::{RED, RESET, YELLOW};
@ -197,3 +197,25 @@ pub fn subsume_func(
additional, additional,
)) ))
} }
pub fn __array_getitem__(
mut args: ValueArgs,
_path: PathBuf,
__name__: Option<Str>,
) -> EvalValueResult<ValueObj> {
let _self = enum_unwrap!(args.remove_left_or_key("Self").unwrap(), ValueObj::Array);
let index = enum_unwrap!(args.remove_left_or_key("Index").unwrap(), ValueObj::Nat);
let res = _self[index as usize].clone();
Ok(res)
}
pub fn __dict_getitem__(
mut args: ValueArgs,
_path: PathBuf,
__name__: Option<Str>,
) -> EvalValueResult<ValueObj> {
let _self = enum_unwrap!(args.remove_left_or_key("Self").unwrap(), ValueObj::Dict);
let index = args.remove_left_or_key("Index").unwrap();
let res = _self.get(&index).unwrap().clone();
Ok(res)
}

View file

@ -61,12 +61,12 @@ impl Context {
} }
} }
fn register_builtin_const(&mut self, name: &str, obj: ValueObj) { fn register_builtin_const(&mut self, name: &str, vis: Visibility, obj: ValueObj) {
if self.rec_get_const_obj(name).is_some() { if self.rec_get_const_obj(name).is_some() {
panic!("already registered: {name}"); panic!("already registered: {name}");
} else { } else {
// TODO: not all value objects are comparable // TODO: not all value objects are comparable
let vi = VarInfo::new(v_enum(set! {obj.clone()}), Const, Private, Builtin, None); let vi = VarInfo::new(v_enum(set! {obj.clone()}), Const, vis, Builtin, None);
self.consts.insert(VarName::from_str(Str::rc(name)), obj); self.consts.insert(VarName::from_str(Str::rc(name)), obj);
self.locals.insert(VarName::from_str(Str::rc(name)), vi); self.locals.insert(VarName::from_str(Str::rc(name)), vi);
} }
@ -238,8 +238,8 @@ impl Context {
let inheritable_type = Self::builtin_mono_trait("InheritableType", 2); let inheritable_type = Self::builtin_mono_trait("InheritableType", 2);
let named = Self::builtin_mono_trait("Named", 2); let named = Self::builtin_mono_trait("Named", 2);
let mut mutable = Self::builtin_mono_trait("Mutable", 2); let mut mutable = Self::builtin_mono_trait("Mutable", 2);
let proj = mono_proj(mono_q("Self"), "ImmutType"); let immut_t = proj(mono_q("Self"), "ImmutType");
let f_t = func(vec![kw("old", proj.clone())], None, vec![], proj); let f_t = func(vec![kw("old", immut_t.clone())], None, vec![], immut_t);
let t = pr1_met(ref_mut(mono_q("Self"), None), f_t, NoneType); let t = pr1_met(ref_mut(mono_q("Self"), None), f_t, NoneType);
let t = quant( let t = quant(
t, t,
@ -362,22 +362,14 @@ impl Context {
// Rについて共変(__add__の型とは関係ない) // Rについて共変(__add__の型とは関係ない)
add.register_superclass(builtin_poly("Output", vec![ty_tp(mono_q("R"))]), &output); add.register_superclass(builtin_poly("Output", vec![ty_tp(mono_q("R"))]), &output);
let self_bound = subtypeof(mono_q("Self"), builtin_poly("Add", ty_params.clone())); let self_bound = subtypeof(mono_q("Self"), builtin_poly("Add", ty_params.clone()));
let op_t = fn1_met( let op_t = fn1_met(mono_q("Self"), r.clone(), proj(mono_q("Self"), "Output"));
mono_q("Self"),
r.clone(),
mono_proj(mono_q("Self"), "Output"),
);
let op_t = quant(op_t, set! {r_bound.clone(), self_bound}); let op_t = quant(op_t, set! {r_bound.clone(), self_bound});
add.register_builtin_decl("__add__", op_t, Public); add.register_builtin_decl("__add__", op_t, Public);
add.register_builtin_decl("Output", Type, Public); add.register_builtin_decl("Output", Type, Public);
/* Sub */ /* Sub */
let mut sub = Self::builtin_poly_trait("Sub", params.clone(), 2); let mut sub = Self::builtin_poly_trait("Sub", params.clone(), 2);
sub.register_superclass(builtin_poly("Output", vec![ty_tp(mono_q("R"))]), &output); sub.register_superclass(builtin_poly("Output", vec![ty_tp(mono_q("R"))]), &output);
let op_t = fn1_met( let op_t = fn1_met(mono_q("Self"), r.clone(), proj(mono_q("Self"), "Output"));
mono_q("Self"),
r.clone(),
mono_proj(mono_q("Self"), "Output"),
);
let self_bound = subtypeof(mono_q("Self"), builtin_poly("Sub", ty_params.clone())); let self_bound = subtypeof(mono_q("Self"), builtin_poly("Sub", ty_params.clone()));
let op_t = quant(op_t, set! {r_bound.clone(), self_bound}); let op_t = quant(op_t, set! {r_bound.clone(), self_bound});
sub.register_builtin_decl("__sub__", op_t, Public); sub.register_builtin_decl("__sub__", op_t, Public);
@ -385,11 +377,7 @@ impl Context {
/* Mul */ /* Mul */
let mut mul = Self::builtin_poly_trait("Mul", params.clone(), 2); let mut mul = Self::builtin_poly_trait("Mul", params.clone(), 2);
mul.register_superclass(builtin_poly("Output", vec![ty_tp(mono_q("R"))]), &output); mul.register_superclass(builtin_poly("Output", vec![ty_tp(mono_q("R"))]), &output);
let op_t = fn1_met( let op_t = fn1_met(mono_q("Self"), r.clone(), proj(mono_q("Self"), "Output"));
mono_q("Self"),
r.clone(),
mono_proj(mono_q("Self"), "Output"),
);
let self_bound = subtypeof(mono_q("Self"), builtin_poly("Mul", ty_params.clone())); let self_bound = subtypeof(mono_q("Self"), builtin_poly("Mul", ty_params.clone()));
let op_t = quant(op_t, set! {r_bound.clone(), self_bound}); let op_t = quant(op_t, set! {r_bound.clone(), self_bound});
mul.register_builtin_decl("__mul__", op_t, Public); mul.register_builtin_decl("__mul__", op_t, Public);
@ -397,7 +385,7 @@ impl Context {
/* Div */ /* Div */
let mut div = Self::builtin_poly_trait("Div", params, 2); let mut div = Self::builtin_poly_trait("Div", params, 2);
div.register_superclass(builtin_poly("Output", vec![ty_tp(mono_q("R"))]), &output); div.register_superclass(builtin_poly("Output", vec![ty_tp(mono_q("R"))]), &output);
let op_t = fn1_met(mono_q("Self"), r, mono_proj(mono_q("Self"), "Output")); let op_t = fn1_met(mono_q("Self"), r, proj(mono_q("Self"), "Output"));
let self_bound = subtypeof(mono_q("Self"), builtin_poly("Div", ty_params.clone())); let self_bound = subtypeof(mono_q("Self"), builtin_poly("Div", ty_params.clone()));
let op_t = quant(op_t, set! {r_bound, self_bound}); let op_t = quant(op_t, set! {r_bound, self_bound});
div.register_builtin_decl("__div__", op_t, Public); div.register_builtin_decl("__div__", op_t, Public);
@ -487,7 +475,11 @@ impl Context {
obj_in.register_builtin_impl("__in__", fn1_met(Obj, Type, Bool), Const, Public); obj_in.register_builtin_impl("__in__", fn1_met(Obj, Type, Bool), Const, Public);
obj.register_trait(Obj, builtin_poly("In", vec![ty_tp(Type)]), obj_in); obj.register_trait(Obj, builtin_poly("In", vec![ty_tp(Type)]), obj_in);
let mut obj_mutizable = Self::builtin_methods("Mutizable", 1); let mut obj_mutizable = Self::builtin_methods("Mutizable", 1);
obj_mutizable.register_builtin_const("MutType!", ValueObj::builtin_t(builtin_mono("Obj!"))); obj_mutizable.register_builtin_const(
"MutType!",
Public,
ValueObj::builtin_t(builtin_mono("Obj!")),
);
obj.register_trait(Obj, builtin_mono("Mutizable"), obj_mutizable); obj.register_trait(Obj, builtin_mono("Mutizable"), obj_mutizable);
// Obj does not implement Eq // Obj does not implement Eq
@ -495,7 +487,7 @@ impl Context {
let mut float = Self::builtin_mono_class("Float", 2); let mut float = Self::builtin_mono_class("Float", 2);
float.register_superclass(Obj, &obj); float.register_superclass(Obj, &obj);
// TODO: support multi platform // TODO: support multi platform
float.register_builtin_const("EPSILON", ValueObj::Float(2.220446049250313e-16)); float.register_builtin_const("EPSILON", Public, ValueObj::Float(2.220446049250313e-16));
float.register_builtin_impl("Real", Float, Const, Public); float.register_builtin_impl("Real", Float, Const, Public);
float.register_builtin_impl("Imag", Float, Const, Public); float.register_builtin_impl("Imag", Float, Const, Public);
float.register_marker_trait(builtin_mono("Num")); float.register_marker_trait(builtin_mono("Num"));
@ -516,25 +508,28 @@ impl Context {
let op_t = fn1_met(Float, Float, Float); let op_t = fn1_met(Float, Float, Float);
let mut float_add = Self::builtin_methods("Add", 2); let mut float_add = Self::builtin_methods("Add", 2);
float_add.register_builtin_impl("__add__", op_t.clone(), Const, Public); float_add.register_builtin_impl("__add__", op_t.clone(), Const, Public);
float_add.register_builtin_const("Output", ValueObj::builtin_t(Float)); float_add.register_builtin_const("Output", Public, ValueObj::builtin_t(Float));
float.register_trait(Float, builtin_poly("Add", vec![ty_tp(Float)]), float_add); float.register_trait(Float, builtin_poly("Add", vec![ty_tp(Float)]), float_add);
let mut float_sub = Self::builtin_methods("Sub", 2); let mut float_sub = Self::builtin_methods("Sub", 2);
float_sub.register_builtin_impl("__sub__", op_t.clone(), Const, Public); float_sub.register_builtin_impl("__sub__", op_t.clone(), Const, Public);
float_sub.register_builtin_const("Output", ValueObj::builtin_t(Float)); float_sub.register_builtin_const("Output", Public, ValueObj::builtin_t(Float));
float.register_trait(Float, builtin_poly("Sub", vec![ty_tp(Float)]), float_sub); float.register_trait(Float, builtin_poly("Sub", vec![ty_tp(Float)]), float_sub);
let mut float_mul = Self::builtin_methods("Mul", 2); let mut float_mul = Self::builtin_methods("Mul", 2);
float_mul.register_builtin_impl("__mul__", op_t.clone(), Const, Public); float_mul.register_builtin_impl("__mul__", op_t.clone(), Const, Public);
float_mul.register_builtin_const("Output", ValueObj::builtin_t(Float)); float_mul.register_builtin_const("Output", Public, ValueObj::builtin_t(Float));
float_mul.register_builtin_const("PowOutput", ValueObj::builtin_t(Float)); float_mul.register_builtin_const("PowOutput", Public, ValueObj::builtin_t(Float));
float.register_trait(Float, builtin_poly("Mul", vec![ty_tp(Float)]), float_mul); float.register_trait(Float, builtin_poly("Mul", vec![ty_tp(Float)]), float_mul);
let mut float_div = Self::builtin_methods("Div", 2); let mut float_div = Self::builtin_methods("Div", 2);
float_div.register_builtin_impl("__div__", op_t, Const, Public); float_div.register_builtin_impl("__div__", op_t, Const, Public);
float_div.register_builtin_const("Output", ValueObj::builtin_t(Float)); float_div.register_builtin_const("Output", Public, ValueObj::builtin_t(Float));
float_div.register_builtin_const("ModOutput", ValueObj::builtin_t(Float)); float_div.register_builtin_const("ModOutput", Public, ValueObj::builtin_t(Float));
float.register_trait(Float, builtin_poly("Div", vec![ty_tp(Float)]), float_div); float.register_trait(Float, builtin_poly("Div", vec![ty_tp(Float)]), float_div);
let mut float_mutizable = Self::builtin_methods("Mutizable", 2); let mut float_mutizable = Self::builtin_methods("Mutizable", 2);
float_mutizable float_mutizable.register_builtin_const(
.register_builtin_const("MutType!", ValueObj::builtin_t(builtin_mono("Float!"))); "MutType!",
Public,
ValueObj::builtin_t(builtin_mono("Float!")),
);
float.register_trait(Float, builtin_mono("Mutizable"), float_mutizable); float.register_trait(Float, builtin_mono("Mutizable"), float_mutizable);
let mut float_show = Self::builtin_methods("Show", 1); let mut float_show = Self::builtin_methods("Show", 1);
let t = fn0_met(Float, Str); let t = fn0_met(Float, Str);
@ -567,25 +562,28 @@ impl Context {
let op_t = fn1_met(Ratio, Ratio, Ratio); let op_t = fn1_met(Ratio, Ratio, Ratio);
let mut ratio_add = Self::builtin_methods("Add", 2); let mut ratio_add = Self::builtin_methods("Add", 2);
ratio_add.register_builtin_impl("__add__", op_t.clone(), Const, Public); ratio_add.register_builtin_impl("__add__", op_t.clone(), Const, Public);
ratio_add.register_builtin_const("Output", ValueObj::builtin_t(Ratio)); ratio_add.register_builtin_const("Output", Public, ValueObj::builtin_t(Ratio));
ratio.register_trait(Ratio, builtin_poly("Add", vec![ty_tp(Ratio)]), ratio_add); ratio.register_trait(Ratio, builtin_poly("Add", vec![ty_tp(Ratio)]), ratio_add);
let mut ratio_sub = Self::builtin_methods("Sub", 2); let mut ratio_sub = Self::builtin_methods("Sub", 2);
ratio_sub.register_builtin_impl("__sub__", op_t.clone(), Const, Public); ratio_sub.register_builtin_impl("__sub__", op_t.clone(), Const, Public);
ratio_sub.register_builtin_const("Output", ValueObj::builtin_t(Ratio)); ratio_sub.register_builtin_const("Output", Public, ValueObj::builtin_t(Ratio));
ratio.register_trait(Ratio, builtin_poly("Sub", vec![ty_tp(Ratio)]), ratio_sub); ratio.register_trait(Ratio, builtin_poly("Sub", vec![ty_tp(Ratio)]), ratio_sub);
let mut ratio_mul = Self::builtin_methods("Mul", 2); let mut ratio_mul = Self::builtin_methods("Mul", 2);
ratio_mul.register_builtin_impl("__mul__", op_t.clone(), Const, Public); ratio_mul.register_builtin_impl("__mul__", op_t.clone(), Const, Public);
ratio_mul.register_builtin_const("Output", ValueObj::builtin_t(Ratio)); ratio_mul.register_builtin_const("Output", Public, ValueObj::builtin_t(Ratio));
ratio_mul.register_builtin_const("PowOutput", ValueObj::builtin_t(Ratio)); ratio_mul.register_builtin_const("PowOutput", Public, ValueObj::builtin_t(Ratio));
ratio.register_trait(Ratio, builtin_poly("Mul", vec![ty_tp(Ratio)]), ratio_mul); ratio.register_trait(Ratio, builtin_poly("Mul", vec![ty_tp(Ratio)]), ratio_mul);
let mut ratio_div = Self::builtin_methods("Div", 2); let mut ratio_div = Self::builtin_methods("Div", 2);
ratio_div.register_builtin_impl("__div__", op_t, Const, Public); ratio_div.register_builtin_impl("__div__", op_t, Const, Public);
ratio_div.register_builtin_const("Output", ValueObj::builtin_t(Ratio)); ratio_div.register_builtin_const("Output", Public, ValueObj::builtin_t(Ratio));
ratio_div.register_builtin_const("ModOutput", ValueObj::builtin_t(Ratio)); ratio_div.register_builtin_const("ModOutput", Public, ValueObj::builtin_t(Ratio));
ratio.register_trait(Ratio, builtin_poly("Div", vec![ty_tp(Ratio)]), ratio_div); ratio.register_trait(Ratio, builtin_poly("Div", vec![ty_tp(Ratio)]), ratio_div);
let mut ratio_mutizable = Self::builtin_methods("Mutizable", 2); let mut ratio_mutizable = Self::builtin_methods("Mutizable", 2);
ratio_mutizable ratio_mutizable.register_builtin_const(
.register_builtin_const("MutType!", ValueObj::builtin_t(builtin_mono("Ratio!"))); "MutType!",
Public,
ValueObj::builtin_t(builtin_mono("Ratio!")),
);
ratio.register_trait(Ratio, builtin_mono("Mutizable"), ratio_mutizable); ratio.register_trait(Ratio, builtin_mono("Mutizable"), ratio_mutizable);
let mut ratio_show = Self::builtin_methods("Show", 1); let mut ratio_show = Self::builtin_methods("Show", 1);
let t = fn0_met(Ratio, Str); let t = fn0_met(Ratio, Str);
@ -620,19 +618,23 @@ impl Context {
let op_t = fn1_met(Int, Int, Int); let op_t = fn1_met(Int, Int, Int);
let mut int_add = Self::builtin_methods("Add", 2); let mut int_add = Self::builtin_methods("Add", 2);
int_add.register_builtin_impl("__add__", op_t.clone(), Const, Public); int_add.register_builtin_impl("__add__", op_t.clone(), Const, Public);
int_add.register_builtin_const("Output", ValueObj::builtin_t(Int)); int_add.register_builtin_const("Output", Public, ValueObj::builtin_t(Int));
int.register_trait(Int, builtin_poly("Add", vec![ty_tp(Int)]), int_add); int.register_trait(Int, builtin_poly("Add", vec![ty_tp(Int)]), int_add);
let mut int_sub = Self::builtin_methods("Sub", 2); let mut int_sub = Self::builtin_methods("Sub", 2);
int_sub.register_builtin_impl("__sub__", op_t.clone(), Const, Public); int_sub.register_builtin_impl("__sub__", op_t.clone(), Const, Public);
int_sub.register_builtin_const("Output", ValueObj::builtin_t(Int)); int_sub.register_builtin_const("Output", Public, ValueObj::builtin_t(Int));
int.register_trait(Int, builtin_poly("Sub", vec![ty_tp(Int)]), int_sub); int.register_trait(Int, builtin_poly("Sub", vec![ty_tp(Int)]), int_sub);
let mut int_mul = Self::builtin_methods("Mul", 2); let mut int_mul = Self::builtin_methods("Mul", 2);
int_mul.register_builtin_impl("__mul__", op_t, Const, Public); int_mul.register_builtin_impl("__mul__", op_t, Const, Public);
int_mul.register_builtin_const("Output", ValueObj::builtin_t(Int)); int_mul.register_builtin_const("Output", Public, ValueObj::builtin_t(Int));
int_mul.register_builtin_const("PowOutput", ValueObj::builtin_t(Nat)); int_mul.register_builtin_const("PowOutput", Public, ValueObj::builtin_t(Nat));
int.register_trait(Int, builtin_poly("Mul", vec![ty_tp(Int)]), int_mul); int.register_trait(Int, builtin_poly("Mul", vec![ty_tp(Int)]), int_mul);
let mut int_mutizable = Self::builtin_methods("Mutizable", 2); let mut int_mutizable = Self::builtin_methods("Mutizable", 2);
int_mutizable.register_builtin_const("MutType!", ValueObj::builtin_t(builtin_mono("Int!"))); int_mutizable.register_builtin_const(
"MutType!",
Public,
ValueObj::builtin_t(builtin_mono("Int!")),
);
int.register_trait(Int, builtin_mono("Mutizable"), int_mutizable); int.register_trait(Int, builtin_mono("Mutizable"), int_mutizable);
let mut int_show = Self::builtin_methods("Show", 1); let mut int_show = Self::builtin_methods("Show", 1);
let t = fn0_met(Int, Str); let t = fn0_met(Int, Str);
@ -679,14 +681,18 @@ impl Context {
let op_t = fn1_met(Nat, Nat, Nat); let op_t = fn1_met(Nat, Nat, Nat);
let mut nat_add = Self::builtin_methods("Add", 2); let mut nat_add = Self::builtin_methods("Add", 2);
nat_add.register_builtin_impl("__add__", op_t.clone(), Const, Public); nat_add.register_builtin_impl("__add__", op_t.clone(), Const, Public);
nat_add.register_builtin_const("Output", ValueObj::builtin_t(Nat)); nat_add.register_builtin_const("Output", Public, ValueObj::builtin_t(Nat));
nat.register_trait(Nat, builtin_poly("Add", vec![ty_tp(Nat)]), nat_add); nat.register_trait(Nat, builtin_poly("Add", vec![ty_tp(Nat)]), nat_add);
let mut nat_mul = Self::builtin_methods("Mul", 2); let mut nat_mul = Self::builtin_methods("Mul", 2);
nat_mul.register_builtin_impl("__mul__", op_t, Const, Public); nat_mul.register_builtin_impl("__mul__", op_t, Const, Public);
nat_mul.register_builtin_const("Output", ValueObj::builtin_t(Nat)); nat_mul.register_builtin_const("Output", Public, ValueObj::builtin_t(Nat));
nat.register_trait(Nat, builtin_poly("Mul", vec![ty_tp(Nat)]), nat_mul); nat.register_trait(Nat, builtin_poly("Mul", vec![ty_tp(Nat)]), nat_mul);
let mut nat_mutizable = Self::builtin_methods("Mutizable", 2); let mut nat_mutizable = Self::builtin_methods("Mutizable", 2);
nat_mutizable.register_builtin_const("MutType!", ValueObj::builtin_t(builtin_mono("Nat!"))); nat_mutizable.register_builtin_const(
"MutType!",
Public,
ValueObj::builtin_t(builtin_mono("Nat!")),
);
nat.register_trait(Nat, builtin_mono("Mutizable"), nat_mutizable); nat.register_trait(Nat, builtin_mono("Mutizable"), nat_mutizable);
nat.register_builtin_impl("Real", Nat, Const, Public); nat.register_builtin_impl("Real", Nat, Const, Public);
nat.register_builtin_impl("Imag", Nat, Const, Public); nat.register_builtin_impl("Imag", Nat, Const, Public);
@ -718,11 +724,14 @@ impl Context {
bool_.register_trait(Bool, builtin_poly("Eq", vec![ty_tp(Bool)]), bool_eq); bool_.register_trait(Bool, builtin_poly("Eq", vec![ty_tp(Bool)]), bool_eq);
let mut bool_add = Self::builtin_methods("Add", 2); let mut bool_add = Self::builtin_methods("Add", 2);
bool_add.register_builtin_impl("__add__", fn1_met(Bool, Bool, Int), Const, Public); bool_add.register_builtin_impl("__add__", fn1_met(Bool, Bool, Int), Const, Public);
bool_add.register_builtin_const("Output", ValueObj::builtin_t(Nat)); bool_add.register_builtin_const("Output", Public, ValueObj::builtin_t(Nat));
bool_.register_trait(Bool, builtin_poly("Add", vec![ty_tp(Bool)]), bool_add); bool_.register_trait(Bool, builtin_poly("Add", vec![ty_tp(Bool)]), bool_add);
let mut bool_mutizable = Self::builtin_methods("Mutizable", 2); let mut bool_mutizable = Self::builtin_methods("Mutizable", 2);
bool_mutizable bool_mutizable.register_builtin_const(
.register_builtin_const("MutType!", ValueObj::builtin_t(builtin_mono("Bool!"))); "MutType!",
Public,
ValueObj::builtin_t(builtin_mono("Bool!")),
);
bool_.register_trait(Bool, builtin_mono("Mutizable"), bool_mutizable); bool_.register_trait(Bool, builtin_mono("Mutizable"), bool_mutizable);
let mut bool_show = Self::builtin_methods("Show", 1); let mut bool_show = Self::builtin_methods("Show", 1);
bool_show.register_builtin_impl("to_str", fn0_met(Bool, Str), Immutable, Public); bool_show.register_builtin_impl("to_str", fn0_met(Bool, Str), Immutable, Public);
@ -765,14 +774,18 @@ impl Context {
str_.register_trait(Str, builtin_poly("Seq", vec![ty_tp(Str)]), str_seq); str_.register_trait(Str, builtin_poly("Seq", vec![ty_tp(Str)]), str_seq);
let mut str_add = Self::builtin_methods("Add", 2); let mut str_add = Self::builtin_methods("Add", 2);
str_add.register_builtin_impl("__add__", fn1_met(Str, Str, Str), Const, Public); str_add.register_builtin_impl("__add__", fn1_met(Str, Str, Str), Const, Public);
str_add.register_builtin_const("Output", ValueObj::builtin_t(Str)); str_add.register_builtin_const("Output", Public, ValueObj::builtin_t(Str));
str_.register_trait(Str, builtin_poly("Add", vec![ty_tp(Str)]), str_add); str_.register_trait(Str, builtin_poly("Add", vec![ty_tp(Str)]), str_add);
let mut str_mul = Self::builtin_methods("Mul", 2); let mut str_mul = Self::builtin_methods("Mul", 2);
str_mul.register_builtin_impl("__mul__", fn1_met(Str, Nat, Str), Const, Public); str_mul.register_builtin_impl("__mul__", fn1_met(Str, Nat, Str), Const, Public);
str_mul.register_builtin_const("Output", ValueObj::builtin_t(Str)); str_mul.register_builtin_const("Output", Public, ValueObj::builtin_t(Str));
str_.register_trait(Str, builtin_poly("Mul", vec![ty_tp(Nat)]), str_mul); str_.register_trait(Str, builtin_poly("Mul", vec![ty_tp(Nat)]), str_mul);
let mut str_mutizable = Self::builtin_methods("Mutizable", 2); let mut str_mutizable = Self::builtin_methods("Mutizable", 2);
str_mutizable.register_builtin_const("MutType!", ValueObj::builtin_t(builtin_mono("Str!"))); str_mutizable.register_builtin_const(
"MutType!",
Public,
ValueObj::builtin_t(builtin_mono("Str!")),
);
str_.register_trait(Str, builtin_mono("Mutizable"), str_mutizable); str_.register_trait(Str, builtin_mono("Mutizable"), str_mutizable);
let mut str_show = Self::builtin_methods("Show", 1); let mut str_show = Self::builtin_methods("Show", 1);
str_show.register_builtin_impl("to_str", fn0_met(Str, Str), Immutable, Public); str_show.register_builtin_impl("to_str", fn0_met(Str, Str), Immutable, Public);
@ -877,7 +890,19 @@ impl Context {
vec![TyParam::t(mono_q("T")), TyParam::mono_q("N").mutate()], vec![TyParam::t(mono_q("T")), TyParam::mono_q("N").mutate()],
)); ));
// [T; N].MutType! = [T; !N] (neither [T!; N] nor [T; N]!) // [T; N].MutType! = [T; !N] (neither [T!; N] nor [T; N]!)
array_.register_builtin_const("MutType!", mut_type); array_.register_builtin_const("MutType!", Public, mut_type);
let getitem_t = fn1_kw_met(
builtin_mono("GenericArray"), // TODO:
kw("Index", Nat),
mono_q("T"),
);
let get_item = ValueObj::Subr(ConstSubr::Builtin(BuiltinConstSubr::new(
"__getitem__",
__array_getitem__,
getitem_t,
None,
)));
array_.register_builtin_const("__getitem__", Public, get_item);
let mut array_eq = Self::builtin_methods("Eq", 2); let mut array_eq = Self::builtin_methods("Eq", 2);
array_eq.register_builtin_impl( array_eq.register_builtin_impl(
"__eq__", "__eq__",
@ -932,7 +957,7 @@ impl Context {
"Set!", "Set!",
vec![TyParam::t(mono_q("T")), TyParam::mono_q("N").mutate()], vec![TyParam::t(mono_q("T")), TyParam::mono_q("N").mutate()],
)); ));
set_.register_builtin_const("MutType!", mut_type); set_.register_builtin_const("MutType!", Public, mut_type);
let mut set_eq = Self::builtin_methods("Eq", 2); let mut set_eq = Self::builtin_methods("Eq", 2);
set_eq.register_builtin_impl( set_eq.register_builtin_impl(
"__eq__", "__eq__",
@ -958,237 +983,79 @@ impl Context {
); );
set_type.register_superclass(set_t.clone(), &set_); set_type.register_superclass(set_t.clone(), &set_);
set_type.register_superclass(Type, &type_); set_type.register_superclass(Type, &type_);
let g_dict_t = builtin_mono("GenericDict");
let mut generic_dict = Self::builtin_mono_class("GenericDict", 2);
generic_dict.register_superclass(Obj, &obj);
let mut generic_dict_eq = Self::builtin_methods("Eq", 2);
generic_dict_eq.register_builtin_impl(
"__eq__",
fn1_met(g_dict_t.clone(), g_dict_t.clone(), Bool),
Const,
Public,
);
generic_dict.register_trait(
g_dict_t.clone(),
builtin_poly("Eq", vec![ty_tp(g_dict_t.clone())]),
generic_dict_eq,
);
let dict_t = builtin_poly("Dict", vec![mono_q_tp("D")]); let dict_t = builtin_poly("Dict", vec![mono_q_tp("D")]);
let mut dict_ = let mut dict_ =
// TODO: D <: GenericDict // TODO: D <: GenericDict
Self::builtin_poly_class("Dict", vec![PS::named_nd("D", builtin_mono("GenericDict"))], 10); Self::builtin_poly_class("Dict", vec![PS::named_nd("D", builtin_mono("GenericDict"))], 10);
dict_.register_superclass(Obj, &obj); dict_.register_superclass(g_dict_t.clone(), &generic_dict);
dict_.register_marker_trait(builtin_poly("Output", vec![ty_tp(mono_q("D"))])); dict_.register_marker_trait(builtin_poly("Output", vec![ty_tp(mono_q("D"))]));
let dict_getitem_t = fn1_kw_met(
builtin_mono("GenericDict"), // TODO:
kw("Index", mono_q("K")),
proj_method(mono_q_tp("D"), "__getitem__", vec![mono_q_tp("K")]),
);
let dict_getitem_t = quant(dict_getitem_t, set! {static_instance("K", Type)});
let get_item = ValueObj::Subr(ConstSubr::Builtin(BuiltinConstSubr::new(
"__getitem__",
__dict_getitem__,
dict_getitem_t,
None,
)));
dict_.register_builtin_const("__getitem__", Public, get_item);
/* Bytes */ /* Bytes */
let mut bytes = Self::builtin_mono_class("Bytes", 2); let mut bytes = Self::builtin_mono_class("Bytes", 2);
bytes.register_superclass(Obj, &obj); bytes.register_superclass(Obj, &obj);
// FIXME: replace to Tuple Ts (e.g. Tuple [Int, Str]) let mut generic_tuple = Self::builtin_mono_class("GenericTuple", 1);
let mut tuple_ = Self::builtin_mono_class("Tuple", 2); generic_tuple.register_superclass(Obj, &obj);
tuple_.register_superclass(Obj, &obj);
let mut tuple_eq = Self::builtin_methods("Eq", 2); let mut tuple_eq = Self::builtin_methods("Eq", 2);
tuple_eq.register_builtin_impl( tuple_eq.register_builtin_impl(
"__eq__", "__eq__",
fn1_met(builtin_mono("Tuple"), builtin_mono("Tuple"), Bool), fn1_met(
builtin_mono("GenericTuple"),
builtin_mono("GenericTuple"),
Bool,
),
Const, Const,
Public, Public,
); );
tuple_.register_trait( generic_tuple.register_trait(
builtin_mono("Tuple"), builtin_mono("GenericTuple"),
builtin_poly("Eq", vec![ty_tp(builtin_mono("Tuple"))]), builtin_poly("Eq", vec![ty_tp(builtin_mono("GenericTuple"))]),
tuple_eq, tuple_eq,
); );
let mut tuple1 = Self::builtin_poly_class("Tuple1", vec![PS::t_nd("A")], 2); // Ts <: GenericArray
tuple1.register_superclass(builtin_mono("Tuple"), &tuple_); let tuple_t = builtin_poly("Tuple", vec![mono_q_tp("Ts")]);
let mut tuple1_eq = Self::builtin_methods("Eq", 2); let mut tuple_ =
tuple1_eq.register_builtin_impl( Self::builtin_poly_class("Tuple", vec![PS::named_nd("Ts", mono_q("Ts"))], 2);
"__eq__", tuple_.register_superclass(builtin_mono("GenericTuple"), &generic_tuple);
fn1_met( tuple_.register_marker_trait(builtin_poly("Output", vec![ty_tp(mono_q("Ts"))]));
builtin_poly("Tuple1", vec![ty_tp(mono_q("A"))]), // __Tuple_getitem__: (self: Tuple(Ts), _: {N}) -> Ts[N]
builtin_poly("Tuple1", vec![ty_tp(mono_q("A"))]), let return_t = proj_method(mono_q_tp("Ts"), "__getitem__", vec![mono_q_tp("N")]);
Bool, let tuple_getitem_t = fn1_met(
), tuple_t.clone(),
Const, tp_enum(Nat, set! {mono_q_tp("N")}),
Public, return_t,
); );
tuple1.register_trait( let tuple_getitem_t = quant(
builtin_poly("Tuple1", vec![ty_tp(mono_q("A"))]), tuple_getitem_t,
builtin_poly( set! {static_instance("Ts", array(Type, mono_q_tp("N"))), static_instance("N", Nat)},
"Eq",
vec![ty_tp(builtin_poly("Tuple1", vec![ty_tp(mono_q("A"))]))],
),
tuple1_eq,
);
/* Tuple(n) */
let mut tuple2 = Self::builtin_poly_class("Tuple2", vec![PS::t_nd("A"), PS::t_nd("B")], 2);
tuple2.register_superclass(builtin_mono("Tuple"), &tuple_);
let mut tuple2_eq = Self::builtin_methods("Eq", 2);
tuple2_eq.register_builtin_impl(
"__eq__",
fn1_met(
builtin_poly("Tuple2", vec![ty_tp(mono_q("A")), ty_tp(mono_q("B"))]),
builtin_poly("Tuple2", vec![ty_tp(mono_q("A")), ty_tp(mono_q("B"))]),
Bool,
),
Const,
Public,
);
tuple2.register_trait(
builtin_poly("Tuple2", vec![ty_tp(mono_q("A")), ty_tp(mono_q("B"))]),
builtin_poly(
"Eq",
vec![ty_tp(builtin_poly(
"Tuple2",
vec![ty_tp(mono_q("A")), ty_tp(mono_q("B"))],
))],
),
tuple2_eq,
);
let mut tuple3 = Self::builtin_poly_class(
"Tuple3",
vec![PS::t_nd("A"), PS::t_nd("B"), PS::t_nd("C")],
2,
);
tuple3.register_superclass(builtin_mono("Tuple"), &tuple_);
let mut tuple3_eq = Self::builtin_methods("Eq", 2);
tuple3_eq.register_builtin_impl(
"__eq__",
fn1_met(
builtin_poly(
"Tuple3",
vec![ty_tp(mono_q("A")), ty_tp(mono_q("B")), ty_tp(mono_q("C"))],
),
builtin_poly(
"Tuple3",
vec![ty_tp(mono_q("A")), ty_tp(mono_q("B")), ty_tp(mono_q("C"))],
),
Bool,
),
Const,
Public,
);
tuple3.register_trait(
builtin_poly(
"Tuple3",
vec![ty_tp(mono_q("A")), ty_tp(mono_q("B")), ty_tp(mono_q("C"))],
),
builtin_poly(
"Eq",
vec![ty_tp(builtin_poly(
"Tuple3",
vec![ty_tp(mono_q("A")), ty_tp(mono_q("B")), ty_tp(mono_q("C"))],
))],
),
tuple3_eq,
);
let mut tuple4 = Self::builtin_poly_class(
"Tuple4",
vec![PS::t_nd("A"), PS::t_nd("B"), PS::t_nd("C"), PS::t_nd("D")],
2,
);
tuple4.register_superclass(builtin_mono("Tuple"), &tuple_);
let mut tuple4_eq = Self::builtin_methods("Eq", 2);
tuple4_eq.register_builtin_impl(
"__eq__",
fn1_met(
builtin_poly(
"Tuple4",
vec![
ty_tp(mono_q("A")),
ty_tp(mono_q("B")),
ty_tp(mono_q("C")),
ty_tp(mono_q("D")),
],
),
builtin_poly(
"Tuple4",
vec![
ty_tp(mono_q("A")),
ty_tp(mono_q("B")),
ty_tp(mono_q("C")),
ty_tp(mono_q("D")),
],
),
Bool,
),
Const,
Public,
);
tuple4.register_trait(
builtin_poly(
"Tuple4",
vec![
ty_tp(mono_q("A")),
ty_tp(mono_q("B")),
ty_tp(mono_q("C")),
ty_tp(mono_q("D")),
],
),
builtin_poly(
"Eq",
vec![ty_tp(builtin_poly(
"Tuple4",
vec![
ty_tp(mono_q("A")),
ty_tp(mono_q("B")),
ty_tp(mono_q("C")),
ty_tp(mono_q("D")),
],
))],
),
tuple4_eq,
);
let mut tuple5 = Self::builtin_poly_class(
"Tuple5",
vec![
PS::t_nd("A"),
PS::t_nd("B"),
PS::t_nd("C"),
PS::t_nd("D"),
PS::t_nd("E"),
],
2,
);
tuple5.register_superclass(builtin_mono("Tuple"), &tuple_);
let mut tuple5_eq = Self::builtin_methods("Eq", 2);
tuple5_eq.register_builtin_impl(
"__eq__",
fn1_met(
builtin_poly(
"Tuple5",
vec![
ty_tp(mono_q("A")),
ty_tp(mono_q("B")),
ty_tp(mono_q("C")),
ty_tp(mono_q("D")),
ty_tp(mono_q("E")),
],
),
builtin_poly(
"Tuple5",
vec![
ty_tp(mono_q("A")),
ty_tp(mono_q("B")),
ty_tp(mono_q("C")),
ty_tp(mono_q("D")),
ty_tp(mono_q("E")),
],
),
Bool,
),
Const,
Public,
);
tuple5.register_trait(
builtin_poly(
"Tuple5",
vec![
ty_tp(mono_q("A")),
ty_tp(mono_q("B")),
ty_tp(mono_q("C")),
ty_tp(mono_q("D")),
ty_tp(mono_q("E")),
],
),
builtin_poly(
"Eq",
vec![ty_tp(builtin_poly(
"Tuple5",
vec![
ty_tp(mono_q("A")),
ty_tp(mono_q("B")),
ty_tp(mono_q("C")),
ty_tp(mono_q("D")),
ty_tp(mono_q("E")),
],
))],
),
tuple5_eq,
); );
tuple_.register_builtin_impl("__Tuple_getitem__", tuple_getitem_t, Const, Public);
/* record */ /* record */
let mut record = Self::builtin_mono_class("Record", 2); let mut record = Self::builtin_mono_class("Record", 2);
record.register_superclass(Obj, &obj); record.register_superclass(Obj, &obj);
@ -1203,7 +1070,7 @@ impl Context {
let mut float_mut = Self::builtin_mono_class("Float!", 2); let mut float_mut = Self::builtin_mono_class("Float!", 2);
float_mut.register_superclass(Float, &float); float_mut.register_superclass(Float, &float);
let mut float_mut_mutable = Self::builtin_methods("Mutable", 2); let mut float_mut_mutable = Self::builtin_methods("Mutable", 2);
float_mut_mutable.register_builtin_const("ImmutType", ValueObj::builtin_t(Float)); float_mut_mutable.register_builtin_const("ImmutType", Public, ValueObj::builtin_t(Float));
let f_t = kw("f", func(vec![kw("old", Float)], None, vec![], Float)); let f_t = kw("f", func(vec![kw("old", Float)], None, vec![], Float));
let t = pr_met( let t = pr_met(
ref_mut(builtin_mono("Float!"), None), ref_mut(builtin_mono("Float!"), None),
@ -1222,7 +1089,7 @@ impl Context {
let mut ratio_mut = Self::builtin_mono_class("Ratio!", 2); let mut ratio_mut = Self::builtin_mono_class("Ratio!", 2);
ratio_mut.register_superclass(Ratio, &ratio); ratio_mut.register_superclass(Ratio, &ratio);
let mut ratio_mut_mutable = Self::builtin_methods("Mutable", 2); let mut ratio_mut_mutable = Self::builtin_methods("Mutable", 2);
ratio_mut_mutable.register_builtin_const("ImmutType", ValueObj::builtin_t(Ratio)); ratio_mut_mutable.register_builtin_const("ImmutType", Public, ValueObj::builtin_t(Ratio));
let f_t = kw("f", func(vec![kw("old", Ratio)], None, vec![], Ratio)); let f_t = kw("f", func(vec![kw("old", Ratio)], None, vec![], Ratio));
let t = pr_met( let t = pr_met(
ref_mut(builtin_mono("Ratio!"), None), ref_mut(builtin_mono("Ratio!"), None),
@ -1242,7 +1109,7 @@ impl Context {
int_mut.register_superclass(Int, &int); int_mut.register_superclass(Int, &int);
int_mut.register_superclass(builtin_mono("Float!"), &float_mut); int_mut.register_superclass(builtin_mono("Float!"), &float_mut);
let mut int_mut_mutable = Self::builtin_methods("Mutable", 2); let mut int_mut_mutable = Self::builtin_methods("Mutable", 2);
int_mut_mutable.register_builtin_const("ImmutType", ValueObj::builtin_t(Int)); int_mut_mutable.register_builtin_const("ImmutType", Public, ValueObj::builtin_t(Int));
let f_t = kw("f", func(vec![kw("old", Int)], None, vec![], Int)); let f_t = kw("f", func(vec![kw("old", Int)], None, vec![], Int));
let t = pr_met( let t = pr_met(
ref_mut(builtin_mono("Int!"), None), ref_mut(builtin_mono("Int!"), None),
@ -1262,7 +1129,7 @@ impl Context {
nat_mut.register_superclass(builtin_mono("Int!"), &int_mut); nat_mut.register_superclass(builtin_mono("Int!"), &int_mut);
/* Nat_mut */ /* Nat_mut */
let mut nat_mut_mutable = Self::builtin_methods("Mutable", 2); let mut nat_mut_mutable = Self::builtin_methods("Mutable", 2);
nat_mut_mutable.register_builtin_const("ImmutType", ValueObj::builtin_t(Nat)); nat_mut_mutable.register_builtin_const("ImmutType", Public, ValueObj::builtin_t(Nat));
let f_t = kw("f", func(vec![kw("old", Nat)], None, vec![], Nat)); let f_t = kw("f", func(vec![kw("old", Nat)], None, vec![], Nat));
let t = pr_met( let t = pr_met(
ref_mut(builtin_mono("Nat!"), None), ref_mut(builtin_mono("Nat!"), None),
@ -1282,7 +1149,7 @@ impl Context {
bool_mut.register_superclass(Bool, &bool_); bool_mut.register_superclass(Bool, &bool_);
bool_mut.register_superclass(builtin_mono("Nat!"), &nat_mut); bool_mut.register_superclass(builtin_mono("Nat!"), &nat_mut);
let mut bool_mut_mutable = Self::builtin_methods("Mutable", 2); let mut bool_mut_mutable = Self::builtin_methods("Mutable", 2);
bool_mut_mutable.register_builtin_const("ImmutType", ValueObj::builtin_t(Bool)); bool_mut_mutable.register_builtin_const("ImmutType", Public, ValueObj::builtin_t(Bool));
let f_t = kw("f", func(vec![kw("old", Bool)], None, vec![], Bool)); let f_t = kw("f", func(vec![kw("old", Bool)], None, vec![], Bool));
let t = pr_met( let t = pr_met(
ref_mut(builtin_mono("Bool!"), None), ref_mut(builtin_mono("Bool!"), None),
@ -1301,7 +1168,7 @@ impl Context {
let mut str_mut = Self::builtin_mono_class("Str!", 2); let mut str_mut = Self::builtin_mono_class("Str!", 2);
str_mut.register_superclass(Str, &nonetype); str_mut.register_superclass(Str, &nonetype);
let mut str_mut_mutable = Self::builtin_methods("Mutable", 2); let mut str_mut_mutable = Self::builtin_methods("Mutable", 2);
str_mut_mutable.register_builtin_const("ImmutType", ValueObj::builtin_t(Str)); str_mut_mutable.register_builtin_const("ImmutType", Public, ValueObj::builtin_t(Str));
let f_t = kw("f", func(vec![kw("old", Str)], None, vec![], Str)); let f_t = kw("f", func(vec![kw("old", Str)], None, vec![], Str));
let t = pr_met( let t = pr_met(
ref_mut(builtin_mono("Str!"), None), ref_mut(builtin_mono("Str!"), None),
@ -1500,31 +1367,11 @@ impl Context {
self.register_builtin_type(array_type_t, array_type, Const); self.register_builtin_type(array_type_t, array_type, Const);
self.register_builtin_type(set_t, set_, Const); self.register_builtin_type(set_t, set_, Const);
self.register_builtin_type(set_type_t, set_type, Const); self.register_builtin_type(set_type_t, set_type, Const);
self.register_builtin_type(g_dict_t, generic_dict, Const);
self.register_builtin_type(dict_t, dict_, Const); self.register_builtin_type(dict_t, dict_, Const);
self.register_builtin_type(builtin_mono("Bytes"), bytes, Const); self.register_builtin_type(builtin_mono("Bytes"), bytes, Const);
self.register_builtin_type(tuple(vec![mono_q("A")]), tuple1, Const); self.register_builtin_type(builtin_mono("GenericTuple"), generic_tuple, Const);
self.register_builtin_type(tuple(vec![mono_q("A"), mono_q("B")]), tuple2, Const); self.register_builtin_type(tuple_t, tuple_, Const);
self.register_builtin_type(
tuple(vec![mono_q("A"), mono_q("B"), mono_q("C")]),
tuple3,
Const,
);
self.register_builtin_type(
tuple(vec![mono_q("A"), mono_q("B"), mono_q("C"), mono_q("D")]),
tuple4,
Const,
);
self.register_builtin_type(
tuple(vec![
mono_q("A"),
mono_q("B"),
mono_q("C"),
mono_q("D"),
mono_q("E"),
]),
tuple5,
Const,
);
self.register_builtin_type(builtin_mono("Record"), record, Const); self.register_builtin_type(builtin_mono("Record"), record, Const);
self.register_builtin_type(builtin_mono("RecordType"), record_type, Const); self.register_builtin_type(builtin_mono("RecordType"), record_type, Const);
self.register_builtin_type(or_t, or, Const); self.register_builtin_type(or_t, or, Const);
@ -1538,7 +1385,6 @@ impl Context {
self.register_builtin_type(array_mut_t, array_mut_, Const); self.register_builtin_type(array_mut_t, array_mut_, Const);
self.register_builtin_type(set_mut_t, set_mut_, Const); self.register_builtin_type(set_mut_t, set_mut_, Const);
self.register_builtin_type(range_t, range, Const); self.register_builtin_type(range_t, range, Const);
self.register_builtin_type(builtin_mono("Tuple"), tuple_, Const);
self.register_builtin_type(builtin_mono("Proc"), proc, Const); self.register_builtin_type(builtin_mono("Proc"), proc, Const);
self.register_builtin_type(builtin_mono("NamedProc"), named_proc, Const); self.register_builtin_type(builtin_mono("NamedProc"), named_proc, Const);
self.register_builtin_type(builtin_mono("Func"), func, Const); self.register_builtin_type(builtin_mono("Func"), func, Const);
@ -1690,7 +1536,7 @@ impl Context {
ClassType, ClassType,
); );
let class = ConstSubr::Builtin(BuiltinConstSubr::new("Class", class_func, class_t, None)); let class = ConstSubr::Builtin(BuiltinConstSubr::new("Class", class_func, class_t, None));
self.register_builtin_const("Class", ValueObj::Subr(class)); self.register_builtin_const("Class", Private, ValueObj::Subr(class));
let inherit_t = func( let inherit_t = func(
vec![kw("Super", ClassType)], vec![kw("Super", ClassType)],
None, None,
@ -1703,7 +1549,7 @@ impl Context {
inherit_t, inherit_t,
None, None,
)); ));
self.register_builtin_const("Inherit", ValueObj::Subr(inherit)); self.register_builtin_const("Inherit", Private, ValueObj::Subr(inherit));
let trait_t = func( let trait_t = func(
vec![kw("Requirement", Type)], vec![kw("Requirement", Type)],
None, None,
@ -1711,7 +1557,7 @@ impl Context {
TraitType, TraitType,
); );
let trait_ = ConstSubr::Builtin(BuiltinConstSubr::new("Trait", trait_func, trait_t, None)); let trait_ = ConstSubr::Builtin(BuiltinConstSubr::new("Trait", trait_func, trait_t, None));
self.register_builtin_const("Trait", ValueObj::Subr(trait_)); self.register_builtin_const("Trait", Private, ValueObj::Subr(trait_));
let subsume_t = func( let subsume_t = func(
vec![kw("Super", TraitType)], vec![kw("Super", TraitType)],
None, None,
@ -1724,7 +1570,7 @@ impl Context {
subsume_t, subsume_t,
None, None,
)); ));
self.register_builtin_const("Subsume", ValueObj::Subr(subsume)); self.register_builtin_const("Subsume", Private, ValueObj::Subr(subsume));
// decorators // decorators
let inheritable_t = func1(ClassType, ClassType); let inheritable_t = func1(ClassType, ClassType);
let inheritable = ConstSubr::Builtin(BuiltinConstSubr::new( let inheritable = ConstSubr::Builtin(BuiltinConstSubr::new(
@ -1733,7 +1579,7 @@ impl Context {
inheritable_t, inheritable_t,
None, None,
)); ));
self.register_builtin_const("Inheritable", ValueObj::Subr(inheritable)); self.register_builtin_const("Inheritable", Private, ValueObj::Subr(inheritable));
// TODO: register Del function object // TODO: register Del function object
let t_del = nd_func(vec![kw("obj", Obj)], None, NoneType); let t_del = nd_func(vec![kw("obj", Obj)], None, NoneType);
self.register_builtin_impl("Del", t_del, Immutable, Private); self.register_builtin_impl("Del", t_del, Immutable, Private);
@ -1836,7 +1682,7 @@ impl Context {
let op_t = nd_func( let op_t = nd_func(
vec![kw("lhs", l.clone()), kw("rhs", r.clone())], vec![kw("lhs", l.clone()), kw("rhs", r.clone())],
None, None,
mono_proj(mono_q("L"), "Output"), proj(mono_q("L"), "Output"),
); );
let op_t = quant( let op_t = quant(
op_t, op_t,
@ -1846,7 +1692,7 @@ impl Context {
}, },
); );
self.register_builtin_impl("__add__", op_t, Const, Private); self.register_builtin_impl("__add__", op_t, Const, Private);
let op_t = bin_op(l.clone(), r.clone(), mono_proj(mono_q("L"), "Output")); let op_t = bin_op(l.clone(), r.clone(), proj(mono_q("L"), "Output"));
let op_t = quant( let op_t = quant(
op_t, op_t,
set! { set! {
@ -1855,7 +1701,7 @@ impl Context {
}, },
); );
self.register_builtin_impl("__sub__", op_t, Const, Private); self.register_builtin_impl("__sub__", op_t, Const, Private);
let op_t = bin_op(l.clone(), r.clone(), mono_proj(mono_q("L"), "Output")); let op_t = bin_op(l.clone(), r.clone(), proj(mono_q("L"), "Output"));
let op_t = quant( let op_t = quant(
op_t, op_t,
set! { set! {
@ -1864,7 +1710,7 @@ impl Context {
}, },
); );
self.register_builtin_impl("__mul__", op_t, Const, Private); self.register_builtin_impl("__mul__", op_t, Const, Private);
let op_t = bin_op(l.clone(), r.clone(), mono_proj(mono_q("L"), "Output")); let op_t = bin_op(l.clone(), r.clone(), proj(mono_q("L"), "Output"));
let op_t = quant( let op_t = quant(
op_t, op_t,
set! { set! {
@ -1874,12 +1720,12 @@ impl Context {
); );
self.register_builtin_impl("__div__", op_t, Const, Private); self.register_builtin_impl("__div__", op_t, Const, Private);
let m = mono_q("M"); let m = mono_q("M");
let op_t = bin_op(m.clone(), m.clone(), mono_proj(m.clone(), "PowOutput")); let op_t = bin_op(m.clone(), m.clone(), proj(m.clone(), "PowOutput"));
let op_t = quant(op_t, set! {subtypeof(m, builtin_poly("Mul", vec![]))}); let op_t = quant(op_t, set! {subtypeof(m, builtin_poly("Mul", vec![]))});
// TODO: add bound: M == M.Output // TODO: add bound: M == M.Output
self.register_builtin_impl("__pow__", op_t, Const, Private); self.register_builtin_impl("__pow__", op_t, Const, Private);
let d = mono_q("D"); let d = mono_q("D");
let op_t = bin_op(d.clone(), d.clone(), mono_proj(d.clone(), "ModOutput")); let op_t = bin_op(d.clone(), d.clone(), proj(d.clone(), "ModOutput"));
let op_t = quant(op_t, set! {subtypeof(d, builtin_poly("Div", vec![]))}); let op_t = quant(op_t, set! {subtypeof(d, builtin_poly("Div", vec![]))});
self.register_builtin_impl("__mod__", op_t, Const, Private); self.register_builtin_impl("__mod__", op_t, Const, Private);
let e = mono_q("E"); let e = mono_q("E");
@ -1917,7 +1763,7 @@ impl Context {
self.register_builtin_impl("__in__", op_t, Const, Private); self.register_builtin_impl("__in__", op_t, Const, Private);
/* unary */ /* unary */
// TODO: Boolの+/-は警告を出したい // TODO: Boolの+/-は警告を出したい
let op_t = func1(mono_q("T"), mono_proj(mono_q("T"), "MutType!")); let op_t = func1(mono_q("T"), proj(mono_q("T"), "MutType!"));
let op_t = quant( let op_t = quant(
op_t, op_t,
set! {subtypeof(mono_q("T"), builtin_mono("Mutizable"))}, set! {subtypeof(mono_q("T"), builtin_mono("Mutizable"))},
@ -1952,6 +1798,7 @@ impl Context {
interval_add.register_builtin_impl("__add__", op_t, Const, Public); interval_add.register_builtin_impl("__add__", op_t, Const, Public);
interval_add.register_builtin_const( interval_add.register_builtin_const(
"Output", "Output",
Public,
ValueObj::builtin_t(Type::from(m.clone() + o.clone()..=n.clone() + p.clone())), ValueObj::builtin_t(Type::from(m.clone() + o.clone()..=n.clone() + p.clone())),
); );
interval.register_trait( interval.register_trait(
@ -1968,6 +1815,7 @@ impl Context {
interval_sub.register_builtin_impl("__sub__", op_t, Const, Public); interval_sub.register_builtin_impl("__sub__", op_t, Const, Public);
interval_sub.register_builtin_const( interval_sub.register_builtin_const(
"Output", "Output",
Public,
ValueObj::builtin_t(Type::from(m.clone() - p.clone()..=n.clone() - o.clone())), ValueObj::builtin_t(Type::from(m.clone() - p.clone()..=n.clone() - o.clone())),
); );
interval.register_trait( interval.register_trait(

View file

@ -17,7 +17,7 @@ use erg_parser::ast::{self, Identifier};
use erg_parser::token::Token; use erg_parser::token::Token;
use erg_type::constructors::{ use erg_type::constructors::{
anon, builtin_mono, builtin_poly, free_var, func, module, mono_proj, subr_t, v_enum, anon, builtin_mono, builtin_poly, free_var, func, module, proj, subr_t, v_enum,
}; };
use erg_type::free::Constraint; use erg_type::free::Constraint;
use erg_type::typaram::TyParam; use erg_type::typaram::TyParam;
@ -1864,7 +1864,7 @@ impl Context {
// TODO: params, polymorphic types // TODO: params, polymorphic types
pub(crate) fn get_candidates(&self, t: &Type) -> Option<Set<Type>> { pub(crate) fn get_candidates(&self, t: &Type) -> Option<Set<Type>> {
match t { match t {
Type::MonoProj { lhs, rhs } => Some(self.get_proj_candidates(lhs, rhs)), Type::Proj { lhs, rhs } => Some(self.get_proj_candidates(lhs, rhs)),
Type::Subr(subr) => { Type::Subr(subr) => {
let candidates = self.get_candidates(&subr.return_t)?; let candidates = self.get_candidates(&subr.return_t)?;
Some( Some(
@ -1896,7 +1896,7 @@ impl Context {
let candidates = insts.into_iter().filter_map(move |inst| { let candidates = insts.into_iter().filter_map(move |inst| {
if self.supertype_of(&inst.sup_trait, &sup) { if self.supertype_of(&inst.sup_trait, &sup) {
self.eval_t_params( self.eval_t_params(
mono_proj(inst.sub_type, rhs), proj(inst.sub_type, rhs),
self.level, self.level,
Location::Unknown, Location::Unknown,
) )
@ -1920,7 +1920,7 @@ impl Context {
Type::FreeVar(fv) if fv.is_linked() => self.is_class(&fv.crack()), Type::FreeVar(fv) if fv.is_linked() => self.is_class(&fv.crack()),
Type::FreeVar(_) => false, Type::FreeVar(_) => false,
Type::Or(l, r) => self.is_class(l) && self.is_class(r), Type::Or(l, r) => self.is_class(l) && self.is_class(r),
Type::MonoProj { lhs, rhs } => self Type::Proj { lhs, rhs } => self
.get_proj_candidates(lhs, rhs) .get_proj_candidates(lhs, rhs)
.iter() .iter()
.all(|t| self.is_class(t)), .all(|t| self.is_class(t)),
@ -1943,7 +1943,7 @@ impl Context {
Type::FreeVar(fv) if fv.is_linked() => self.is_class(&fv.crack()), Type::FreeVar(fv) if fv.is_linked() => self.is_class(&fv.crack()),
Type::FreeVar(_) => false, Type::FreeVar(_) => false,
Type::And(l, r) | Type::Or(l, r) => self.is_trait(l) && self.is_trait(r), Type::And(l, r) | Type::Or(l, r) => self.is_trait(l) && self.is_trait(r),
Type::MonoProj { lhs, rhs } => self Type::Proj { lhs, rhs } => self
.get_proj_candidates(lhs, rhs) .get_proj_candidates(lhs, rhs)
.iter() .iter()
.all(|t| self.is_trait(t)), .all(|t| self.is_trait(t)),

View file

@ -159,13 +159,13 @@ impl TyVarContext {
Type::BuiltinPoly { name, params } => { Type::BuiltinPoly { name, params } => {
self.instantiate_poly(None, mid.name(), &name, params, ctx) self.instantiate_poly(None, mid.name(), &name, params, ctx)
} }
Type::MonoProj { lhs, rhs } => { Type::Proj { lhs, rhs } => {
let lhs = if lhs.has_qvar() { let lhs = if lhs.has_qvar() {
self.instantiate_qvar(*lhs) self.instantiate_qvar(*lhs)
} else { } else {
*lhs *lhs
}; };
mono_proj(lhs, rhs) proj(lhs, rhs)
} }
Type::Ref(t) if t.has_qvar() => ref_(self.instantiate_qvar(*t)), Type::Ref(t) if t.has_qvar() => ref_(self.instantiate_qvar(*t)),
Type::RefMut { before, after } => { Type::RefMut { before, after } => {
@ -242,6 +242,7 @@ impl TyVarContext {
} }
TyBound::Instance { name, t } => { TyBound::Instance { name, t } => {
let t = match t { let t = match t {
Type::FreeVar(fv) if fv.is_linked() => todo!(),
Type::BuiltinPoly { name, params } => { Type::BuiltinPoly { name, params } => {
self.instantiate_poly(None, name.clone(), &name, params, ctx) self.instantiate_poly(None, name.clone(), &name, params, ctx)
} }
@ -251,8 +252,7 @@ impl TyVarContext {
t => t, t => t,
}; };
let constraint = Constraint::new_type_of(t.clone()); let constraint = Constraint::new_type_of(t.clone());
// TODO: type-like types if t.is_type() {
if t == Type {
if let Some(tv) = self.tyvar_instances.get(&name) { if let Some(tv) = self.tyvar_instances.get(&name) {
tv.update_constraint(constraint); tv.update_constraint(constraint);
} else if let Some(tp) = self.typaram_instances.get(&name) { } else if let Some(tp) = self.typaram_instances.get(&name) {
@ -438,7 +438,10 @@ impl TyVarContext {
pub(crate) fn push_or_init_typaram(&mut self, name: &Str, tp: &TyParam) { pub(crate) fn push_or_init_typaram(&mut self, name: &Str, tp: &TyParam) {
// FIXME: // FIXME:
if self.tyvar_instances.get(name).is_some() || self.typaram_instances.get(name).is_some() { if let Some(_tp) = self.typaram_instances.get(name) {
return;
}
if let Some(_t) = self.tyvar_instances.get(name) {
return; return;
} }
self.typaram_instances.insert(name.clone(), tp.clone()); self.typaram_instances.insert(name.clone(), tp.clone());
@ -1053,9 +1056,20 @@ impl Context {
.transpose()?; .transpose()?;
Ok(ref_mut(before, after)) Ok(ref_mut(before, after))
} }
MonoProj { lhs, rhs } => { Proj { lhs, rhs } => {
let lhs = self.instantiate_t(*lhs, tmp_tv_ctx, loc)?; let lhs = self.instantiate_t(*lhs, tmp_tv_ctx, loc)?;
Ok(mono_proj(lhs, rhs)) Ok(proj(lhs, rhs))
}
ProjMethod {
lhs,
method_name,
mut args,
} => {
let lhs = self.instantiate_tp(*lhs, tmp_tv_ctx, loc)?;
for arg in args.iter_mut() {
*arg = self.instantiate_tp(mem::take(arg), tmp_tv_ctx, loc)?;
}
Ok(proj_method(lhs, method_name, args))
} }
BuiltinPoly { name, mut params } => { BuiltinPoly { name, mut params } => {
for param in params.iter_mut() { for param in params.iter_mut() {

View file

@ -870,6 +870,15 @@ impl Context {
log!(info "{}: current namespace: {}", fn_name!(), self.name); log!(info "{}: current namespace: {}", fn_name!(), self.name);
ctx ctx
} else { } else {
panic!("cannot pop the top-level context (or use `pop_mod`)");
}
}
pub fn pop_mod(&mut self) -> Context {
if self.outer.is_some() {
panic!("not in the top-level context");
} else {
log!(info "{}: current namespace: <builtins>", fn_name!());
// toplevel // toplevel
mem::take(self) mem::take(self)
} }

View file

@ -938,11 +938,11 @@ impl Context {
HIRBuilder::new_with_cache(cfg, __name__, mod_cache.clone(), py_mod_cache.clone()); HIRBuilder::new_with_cache(cfg, __name__, mod_cache.clone(), py_mod_cache.clone());
match builder.build(src, "exec") { match builder.build(src, "exec") {
Ok(hir) => { Ok(hir) => {
mod_cache.register(path.clone(), Some(hir), builder.pop_ctx()); mod_cache.register(path.clone(), Some(hir), builder.pop_mod_ctx());
} }
Err((maybe_hir, errs)) => { Err((maybe_hir, errs)) => {
if let Some(hir) = maybe_hir { if let Some(hir) = maybe_hir {
mod_cache.register(path, Some(hir), builder.pop_ctx()); mod_cache.register(path, Some(hir), builder.pop_mod_ctx());
} }
return Err(errs); return Err(errs);
} }
@ -1037,11 +1037,11 @@ impl Context {
HIRBuilder::new_with_cache(cfg, __name__, py_mod_cache.clone(), py_mod_cache.clone()); HIRBuilder::new_with_cache(cfg, __name__, py_mod_cache.clone(), py_mod_cache.clone());
match builder.build(src, "declare") { match builder.build(src, "declare") {
Ok(hir) => { Ok(hir) => {
py_mod_cache.register(path.clone(), Some(hir), builder.pop_ctx()); py_mod_cache.register(path.clone(), Some(hir), builder.pop_mod_ctx());
} }
Err((maybe_hir, errs)) => { Err((maybe_hir, errs)) => {
if let Some(hir) = maybe_hir { if let Some(hir) = maybe_hir {
py_mod_cache.register(path, Some(hir), builder.pop_ctx()); py_mod_cache.register(path, Some(hir), builder.pop_mod_ctx());
} }
return Err(errs); return Err(errs);
} }

View file

@ -195,9 +195,20 @@ impl Context {
.collect::<Vec<_>>(); .collect::<Vec<_>>();
poly(path, name, params) poly(path, name, params)
} }
MonoProj { lhs, rhs } => { Proj { lhs, rhs } => {
let lhs = self.generalize_t_inner(*lhs, bounds, lazy_inits); let lhs = self.generalize_t_inner(*lhs, bounds, lazy_inits);
mono_proj(lhs, rhs) proj(lhs, rhs)
}
ProjMethod {
lhs,
method_name,
mut args,
} => {
let lhs = self.generalize_tp(*lhs, bounds, lazy_inits);
for arg in args.iter_mut() {
*arg = self.generalize_tp(mem::take(arg), bounds, lazy_inits);
}
proj_method(lhs, method_name, args)
} }
And(l, r) => { And(l, r) => {
let l = self.generalize_t_inner(*l, bounds, lazy_inits); let l = self.generalize_t_inner(*l, bounds, lazy_inits);
@ -249,7 +260,7 @@ impl Context {
} }
} }
fn deref_tp( pub(crate) fn deref_tp(
&self, &self,
tp: TyParam, tp: TyParam,
variance: Variance, variance: Variance,
@ -274,8 +285,21 @@ impl Context {
} }
TyParam::BinOp { .. } => todo!(), TyParam::BinOp { .. } => todo!(),
TyParam::UnaryOp { .. } => todo!(), TyParam::UnaryOp { .. } => todo!(),
TyParam::Array(_) | TyParam::Tuple(_) => todo!(), TyParam::Array(tps) => {
TyParam::MonoProj { .. } let mut new_tps = vec![];
for tp in tps {
new_tps.push(self.deref_tp(tp, variance, loc)?);
}
Ok(TyParam::Array(new_tps))
}
TyParam::Tuple(tps) => {
let mut new_tps = vec![];
for tp in tps {
new_tps.push(self.deref_tp(tp, variance, loc)?);
}
Ok(TyParam::Tuple(new_tps))
}
TyParam::Proj { .. }
| TyParam::MonoQVar(_) | TyParam::MonoQVar(_)
| TyParam::PolyQVar { .. } | TyParam::PolyQVar { .. }
| TyParam::Failure | TyParam::Failure
@ -617,6 +641,16 @@ impl Context {
} }
} }
pub(crate) fn coerce_tp(&self, tp: &TyParam) {
match tp {
TyParam::FreeVar(fv) if fv.is_linked() => {
self.coerce_tp(&fv.crack());
}
TyParam::Type(t) => self.coerce(t),
_ => {}
}
}
/// Check if all types are resolvable (if traits, check if an implementation exists) /// Check if all types are resolvable (if traits, check if an implementation exists)
/// And replace them if resolvable /// And replace them if resolvable
pub(crate) fn resolve( pub(crate) fn resolve(
@ -1080,7 +1114,7 @@ impl Context {
} }
/// predは正規化されているとする /// predは正規化されているとする
fn _sub_unify_pred( fn sub_unify_pred(
&self, &self,
l_pred: &Predicate, l_pred: &Predicate,
r_pred: &Predicate, r_pred: &Predicate,
@ -1098,8 +1132,8 @@ impl Context {
| (Pred::Or(l1, r1), Pred::Or(l2, r2)) | (Pred::Or(l1, r1), Pred::Or(l2, r2))
| (Pred::Not(l1, r1), Pred::Not(l2, r2)) => { | (Pred::Not(l1, r1), Pred::Not(l2, r2)) => {
match ( match (
self._sub_unify_pred(l1, l2, loc), self.sub_unify_pred(l1, l2, loc),
self._sub_unify_pred(r1, r2, loc), self.sub_unify_pred(r1, r2, loc),
) { ) {
(Ok(()), Ok(())) => Ok(()), (Ok(()), Ok(())) => Ok(()),
(Ok(()), Err(e)) | (Err(e), Ok(())) | (Err(e), Err(_)) => Err(e), (Ok(()), Err(e)) | (Err(e), Ok(())) | (Err(e), Err(_)) => Err(e),
@ -1304,6 +1338,7 @@ impl Context {
return Ok(()); return Ok(());
} }
if !maybe_sub_is_sub { if !maybe_sub_is_sub {
log!(err "{maybe_sub} !<: {maybe_sup}");
return Err(TyCheckErrors::from(TyCheckError::type_mismatch_error( return Err(TyCheckErrors::from(TyCheckError::type_mismatch_error(
self.cfg.input.clone(), self.cfg.input.clone(),
line!() as usize, line!() as usize,
@ -1545,9 +1580,19 @@ impl Context {
self.sub_unify(maybe_sub, before, loc, param_name)?; self.sub_unify(maybe_sub, before, loc, param_name)?;
Ok(()) Ok(())
} }
(Type::MonoProj { .. }, _) => todo!(), (Type::Proj { .. }, _) => todo!(),
(_, Type::MonoProj { .. }) => todo!(), (_, Type::Proj { .. }) => todo!(),
(Refinement(_), Refinement(_)) => todo!(), (Refinement(l), Refinement(r)) => {
log!(err "{l}, {r}");
if l.preds.len() == 1 && r.preds.len() == 1 {
let l_first = l.preds.iter().next().unwrap();
let r_first = r.preds.iter().next().unwrap();
self.sub_unify_pred(l_first, r_first, loc)?;
log!("{l}, {r}");
return Ok(());
}
todo!("{l}, {r}")
},
(Type::Subr(_) | Type::Record(_), Type) => Ok(()), (Type::Subr(_) | Type::Record(_), Type) => Ok(()),
// TODO Tuple2, ... // TODO Tuple2, ...
(Type::BuiltinPoly{ name, .. }, Type) if &name[..] == "Array" || &name[..] == "Tuple" => Ok(()), (Type::BuiltinPoly{ name, .. }, Type) if &name[..] == "Array" || &name[..] == "Tuple" => Ok(()),

View file

@ -735,7 +735,6 @@ impl ASTLowerer {
}, },
_ => { _ => {
if let Some(type_spec) = opt_cast_to { if let Some(type_spec) = opt_cast_to {
log!(err "cast({type_spec}): {call}");
self.ctx.cast(type_spec, &mut call)?; self.ctx.cast(type_spec, &mut call)?;
} }
} }
@ -898,43 +897,54 @@ impl ASTLowerer {
if let Err(errs) = self.ctx.preregister(&body.block) { if let Err(errs) = self.ctx.preregister(&body.block) {
self.errs.extend(errs.into_iter()); self.errs.extend(errs.into_iter());
} }
let block = self.lower_block(body.block).map_err(|e| { match self.lower_block(body.block) {
self.pop_append_errs(); Ok(block) => {
e let found_body_t = block.ref_t();
})?; let opt_expect_body_t = self
let found_body_t = block.ref_t(); .ctx
let opt_expect_body_t = self .outer
.ctx .as_ref()
.outer .unwrap()
.as_ref() .get_current_scope_var(sig.inspect().unwrap())
.unwrap() .map(|vi| vi.t.clone());
.get_current_scope_var(sig.inspect().unwrap()) let ident = match &sig.pat {
.map(|vi| vi.t.clone()); ast::VarPattern::Ident(ident) => ident,
let ident = match &sig.pat { _ => unreachable!(),
ast::VarPattern::Ident(ident) => ident, };
_ => unreachable!(), if let Some(expect_body_t) = opt_expect_body_t {
}; // TODO: expect_body_t is smaller for constants
if let Some(expect_body_t) = opt_expect_body_t { // TODO: 定数の場合、expect_body_tのほうが小さくなってしまう
// TODO: expect_body_t is smaller for constants if !sig.is_const() {
// TODO: 定数の場合、expect_body_tのほうが小さくなってしまう if let Err(e) = self.return_t_check(
if !sig.is_const() { sig.loc(),
if let Err(e) = ident.inspect(),
self.return_t_check(sig.loc(), ident.inspect(), &expect_body_t, found_body_t) &expect_body_t,
{ found_body_t,
self.errs.push(e); ) {
self.errs.push(e);
}
}
} }
let id = body.id;
self.ctx
.outer
.as_mut()
.unwrap()
.assign_var_sig(&sig, found_body_t, id)?;
let ident = hir::Identifier::bare(ident.dot.clone(), ident.name.clone());
let sig = hir::VarSignature::new(ident, found_body_t.clone());
let body = hir::DefBody::new(body.op, block, body.id);
Ok(hir::Def::new(hir::Signature::Var(sig), body))
}
Err(errs) => {
self.ctx.outer.as_mut().unwrap().assign_var_sig(
&sig,
&Type::Never,
ast::DefId(0),
)?;
Err(errs)
} }
} }
let id = body.id;
self.ctx
.outer
.as_mut()
.unwrap()
.assign_var_sig(&sig, found_body_t, id)?;
let ident = hir::Identifier::bare(ident.dot.clone(), ident.name.clone());
let sig = hir::VarSignature::new(ident, found_body_t.clone());
let body = hir::DefBody::new(body.op, block, body.id);
Ok(hir::Def::new(hir::Signature::Var(sig), body))
} }
// NOTE: 呼ばれている間はinner scopeなので注意 // NOTE: 呼ばれている間はinner scopeなので注意
@ -960,33 +970,41 @@ impl ASTLowerer {
if let Err(errs) = self.ctx.preregister(&body.block) { if let Err(errs) = self.ctx.preregister(&body.block) {
self.errs.extend(errs.into_iter()); self.errs.extend(errs.into_iter());
} }
let block = self.lower_block(body.block).map_err(|e| { match self.lower_block(body.block) {
self.pop_append_errs(); Ok(block) => {
e let found_body_t = block.ref_t();
})?; let expect_body_t = t.return_t.as_ref();
let found_body_t = block.ref_t(); if !sig.is_const() {
let expect_body_t = t.return_t.as_ref(); if let Err(e) = self.return_t_check(
if !sig.is_const() { sig.loc(),
if let Err(e) = self.return_t_check( sig.ident.inspect(),
sig.loc(), expect_body_t,
sig.ident.inspect(), found_body_t,
expect_body_t, ) {
found_body_t, self.errs.push(e);
) { }
self.errs.push(e); }
let id = body.id;
let t =
self.ctx
.outer
.as_mut()
.unwrap()
.assign_subr(&sig, id, found_body_t)?;
let ident = hir::Identifier::bare(sig.ident.dot, sig.ident.name);
let sig = hir::SubrSignature::new(ident, sig.params, t);
let body = hir::DefBody::new(body.op, block, body.id);
Ok(hir::Def::new(hir::Signature::Subr(sig), body))
}
Err(errs) => {
self.ctx.outer.as_mut().unwrap().assign_subr(
&sig,
ast::DefId(0),
&Type::Failure,
)?;
Err(errs)
} }
} }
let id = body.id;
let t = self
.ctx
.outer
.as_mut()
.unwrap()
.assign_subr(&sig, id, found_body_t)?;
let ident = hir::Identifier::bare(sig.ident.dot, sig.ident.name);
let sig = hir::SubrSignature::new(ident, sig.params, t);
let body = hir::DefBody::new(body.op, block, body.id);
Ok(hir::Def::new(hir::Signature::Subr(sig), body))
} }
Type::Failure => { Type::Failure => {
if let Err(errs) = self.ctx.assign_params(&sig.params, None) { if let Err(errs) = self.ctx.assign_params(&sig.params, None) {
@ -995,15 +1013,12 @@ impl ASTLowerer {
if let Err(errs) = self.ctx.preregister(&body.block) { if let Err(errs) = self.ctx.preregister(&body.block) {
self.errs.extend(errs.into_iter()); self.errs.extend(errs.into_iter());
} }
let block = self.lower_block(body.block).map_err(|e| {
self.pop_append_errs();
e
})?;
self.ctx self.ctx
.outer .outer
.as_mut() .as_mut()
.unwrap() .unwrap()
.fake_subr_assign(&sig, Type::Failure); .fake_subr_assign(&sig, Type::Never);
let block = self.lower_block(body.block)?;
let ident = hir::Identifier::bare(sig.ident.dot, sig.ident.name); let ident = hir::Identifier::bare(sig.ident.dot, sig.ident.name);
let sig = hir::SubrSignature::new(ident, sig.params, Type::Failure); let sig = hir::SubrSignature::new(ident, sig.params, Type::Failure);
let body = hir::DefBody::new(body.op, block, body.id); let body = hir::DefBody::new(body.op, block, body.id);

View file

@ -145,6 +145,7 @@ impl Locational for Args {
if let Some((l, r)) = &self.paren { if let Some((l, r)) = &self.paren {
Location::concat(l, r) Location::concat(l, r)
} else { } else {
// TODO: kw, var_args
Location::concat(&self.pos_args[0], self.pos_args.last().unwrap()) Location::concat(&self.pos_args[0], self.pos_args.last().unwrap())
} }
} }
@ -306,6 +307,7 @@ impl TupleAttribute {
pub struct Subscript { pub struct Subscript {
pub obj: Box<Expr>, pub obj: Box<Expr>,
pub index: Box<Expr>, pub index: Box<Expr>,
pub r_sqbr: Token,
} }
impl NestedDisplay for Subscript { impl NestedDisplay for Subscript {
@ -319,13 +321,14 @@ impl NestedDisplay for Subscript {
} }
impl_display_from_nested!(Subscript); impl_display_from_nested!(Subscript);
impl_locational!(Subscript, obj, index); impl_locational!(Subscript, obj, r_sqbr);
impl Subscript { impl Subscript {
pub fn new(obj: Expr, index: Expr) -> Self { pub fn new(obj: Expr, index: Expr, r_sqbr: Token) -> Self {
Self { Self {
obj: Box::new(obj), obj: Box::new(obj),
index: Box::new(index), index: Box::new(index),
r_sqbr,
} }
} }
} }
@ -415,8 +418,8 @@ impl Accessor {
Self::TupleAttr(TupleAttribute::new(obj, index)) Self::TupleAttr(TupleAttribute::new(obj, index))
} }
pub fn subscr(obj: Expr, index: Expr) -> Self { pub fn subscr(obj: Expr, index: Expr, r_sqbr: Token) -> Self {
Self::Subscr(Subscript::new(obj, index)) Self::Subscr(Subscript::new(obj, index, r_sqbr))
} }
pub const fn name(&self) -> Option<&Str> { pub const fn name(&self) -> Option<&Str> {
@ -944,11 +947,7 @@ impl_display_from_nested!(Call);
impl Locational for Call { impl Locational for Call {
fn loc(&self) -> Location { fn loc(&self) -> Location {
if self.args.is_empty() { Location::concat(self.obj.as_ref(), &self.args)
self.obj.loc()
} else {
Location::concat(self.obj.as_ref(), &self.args)
}
} }
} }

View file

@ -52,6 +52,7 @@ impl Desugarer {
let module = self.desugar_multiple_pattern_def(module); let module = self.desugar_multiple_pattern_def(module);
let module = self.desugar_pattern(module); let module = self.desugar_pattern(module);
let module = Self::desugar_shortened_record(module); let module = Self::desugar_shortened_record(module);
let module = Self::desugar_acc(module);
log!(info "AST (desugared):\n{module}"); log!(info "AST (desugared):\n{module}");
log!(info "the desugaring process has completed."); log!(info "the desugaring process has completed.");
module module
@ -442,7 +443,17 @@ impl Desugarer {
Accessor::tuple_attr(obj, Literal::nat(n, sig.ln_begin().unwrap())) Accessor::tuple_attr(obj, Literal::nat(n, sig.ln_begin().unwrap()))
} }
BufIndex::Array(n) => { BufIndex::Array(n) => {
Accessor::subscr(obj, Expr::Lit(Literal::nat(n, sig.ln_begin().unwrap()))) let r_brace = Token::new(
TokenKind::RBrace,
"]",
sig.ln_begin().unwrap(),
sig.col_begin().unwrap(),
);
Accessor::subscr(
obj,
Expr::Lit(Literal::nat(n, sig.ln_begin().unwrap())),
r_brace,
)
} }
BufIndex::Record(attr) => Accessor::attr(obj, attr.clone()), BufIndex::Record(attr) => Accessor::attr(obj, attr.clone()),
}; };
@ -584,13 +595,61 @@ impl Desugarer {
fn desugar_acc(mut module: Module) -> Module { fn desugar_acc(mut module: Module) -> Module {
let mut new = Module::with_capacity(module.len()); let mut new = Module::with_capacity(module.len());
while let Some(chunk) = module.lpop() { while let Some(chunk) = module.lpop() {
new.push(Self::desugar_acc_inner(chunk)); new.push(Self::rec_desugar_acc(chunk));
} }
new new
} }
fn desugar_acc_inner(_expr: Expr) -> Expr { fn rec_desugar_acc(expr: Expr) -> Expr {
todo!() match expr {
Expr::Accessor(acc) => Self::desugar_acc_inner(acc),
expr => Self::perform_desugar(Self::rec_desugar_acc, expr),
}
}
fn desugar_acc_inner(acc: Accessor) -> Expr {
match acc {
// x[y] => x.__getitem__(y)
Accessor::Subscr(subscr) => {
let args = Args::new(vec![PosArg::new(*subscr.index)], vec![], None);
let line = subscr.obj.ln_begin().unwrap();
let call = Call::new(
Self::rec_desugar_acc(*subscr.obj),
Some(Identifier::public_with_line(
Token::dummy(),
Str::ever("__getitem__"),
line,
)),
args,
);
Expr::Call(call)
}
// x.0 => x.__Tuple_getitem__(0)
Accessor::TupleAttr(tattr) => {
let args = Args::new(vec![PosArg::new(Expr::Lit(tattr.index))], vec![], None);
let line = tattr.obj.ln_begin().unwrap();
let call = Call::new(
Self::rec_desugar_acc(*tattr.obj),
Some(Identifier::public_with_line(
Token::dummy(),
Str::ever("__Tuple_getitem__"),
line,
)),
args,
);
Expr::Call(call)
}
Accessor::TypeApp(mut tapp) => {
tapp.obj = Box::new(Self::rec_desugar_acc(*tapp.obj));
// REVIEW: tapp.type_args
Expr::Accessor(Accessor::TypeApp(tapp))
}
Accessor::Attr(mut attr) => {
attr.obj = Box::new(Self::rec_desugar_acc(*attr.obj));
Expr::Accessor(Accessor::Attr(attr))
}
other => Expr::Accessor(other),
}
} }
} }

View file

@ -10,10 +10,12 @@ use erg_common::config::Input;
use erg_common::error::Location; use erg_common::error::Location;
use erg_common::option_enum_unwrap; use erg_common::option_enum_unwrap;
use erg_common::set::Set as HashSet; use erg_common::set::Set as HashSet;
use erg_common::str::Str;
use erg_common::traits::Runnable; use erg_common::traits::Runnable;
use erg_common::traits::{Locational, Stream}; use erg_common::traits::{Locational, Stream};
use erg_common::{ use erg_common::{
caused_by, debug_power_assert, enum_unwrap, fn_name, log, set, switch_lang, switch_unreachable, caused_by, debug_power_assert, enum_unwrap, fn_name, impl_locational_for_enum, log, set,
switch_lang, switch_unreachable,
}; };
use crate::ast::*; use crate::ast::*;
@ -65,6 +67,8 @@ pub enum BraceContainer {
Record(Record), Record(Record),
} }
impl_locational_for_enum!(BraceContainer; Set, Dict, Record);
/// Perform recursive descent parsing. /// Perform recursive descent parsing.
/// ///
/// `level` is raised by 1 by `debug_call_info!` in each analysis method and lowered by 1 when leaving (`.map_err` is called to lower the level). /// `level` is raised by 1 by `debug_call_info!` in each analysis method and lowered by 1 when leaving (`.map_err` is called to lower the level).
@ -391,9 +395,9 @@ impl Parser {
} }
} }
fn try_reduce_acc(&mut self, in_type_args: bool) -> ParseResult<Accessor> { fn try_reduce_acc_lhs(&mut self) -> ParseResult<Accessor> {
debug_call_info!(self); debug_call_info!(self);
let mut acc = match self.peek() { let acc = match self.peek() {
Some(t) if t.is(Symbol) || t.is(UBar) => Accessor::local(self.lpop()), Some(t) if t.is(Symbol) || t.is(UBar) => Accessor::local(self.lpop()),
Some(t) if t.is(Dot) => { Some(t) if t.is(Dot) => {
let dot = self.lpop(); let dot = self.lpop();
@ -414,99 +418,6 @@ impl Parser {
return Err(()); return Err(());
} }
}; };
loop {
match self.peek() {
Some(t) if t.is(Dot) => {
let vis = self.lpop();
let token = self.lpop();
match token.kind {
Symbol => {
let ident = Identifier::new(Some(vis), VarName::new(token));
acc = Accessor::attr(Expr::Accessor(acc), ident);
}
NatLit => {
let attr = Literal::from(token);
acc = Accessor::tuple_attr(Expr::Accessor(acc), attr);
}
Newline => {
self.restore(token);
self.restore(vis);
break;
}
_ => {
self.restore(token);
self.level -= 1;
let err = self.skip_and_throw_syntax_err(caused_by!());
self.errs.push(err);
return Err(());
}
}
}
Some(t) if t.is(DblColon) => {
let vis = self.lpop();
let token = self.lpop();
match token.kind {
Symbol => {
let ident = Identifier::new(None, VarName::new(token));
acc = Accessor::attr(Expr::Accessor(acc), ident);
}
// DataPack
LBrace => {
self.restore(token);
self.restore(vis);
break;
}
// MethodDefs
Newline => {
self.restore(token);
self.restore(vis);
break;
}
_ => {
self.restore(token);
self.level -= 1;
let err = self.skip_and_throw_syntax_err(caused_by!());
self.errs.push(err);
return Err(());
}
}
}
// x[...] (`x [...]` will interpreted as `x([...])`)
Some(t) if t.is(LSqBr) && acc.col_end().unwrap() == t.col_begin().unwrap() => {
self.skip();
let index = self
.try_reduce_expr(false, false, false)
.map_err(|_| self.stack_dec())?;
if self.cur_is(RSqBr) {
self.skip();
} else {
self.level -= 1;
let err = self.skip_and_throw_syntax_err(caused_by!());
self.errs.push(err);
return Err(());
}
acc = Accessor::subscr(Expr::Accessor(acc), index);
if self.cur_is(RSqBr) {
self.lpop();
} else {
self.level -= 1;
// TODO: error report: RSqBr not found
let err = self.skip_and_throw_syntax_err(caused_by!());
self.errs.push(err);
return Err(());
}
}
Some(t) if t.is(VBar) && !in_type_args => {
let type_args = self
.try_reduce_type_app_args()
.map_err(|_| self.stack_dec())?;
acc = Accessor::TypeApp(TypeApp::new(Expr::Accessor(acc), type_args));
}
_ => {
break;
}
}
}
self.level -= 1; self.level -= 1;
Ok(acc) Ok(acc)
} }
@ -755,9 +666,7 @@ impl Parser {
return Ok(PosOrKwArg::Pos(PosArg::new(Expr::Lambda(lambda)))); return Ok(PosOrKwArg::Pos(PosArg::new(Expr::Lambda(lambda))));
} }
if self.nth_is(1, Walrus) { if self.nth_is(1, Walrus) {
let acc = self let acc = self.try_reduce_acc_lhs().map_err(|_| self.stack_dec())?;
.try_reduce_acc(in_type_args)
.map_err(|_| self.stack_dec())?;
// TODO: type specification // TODO: type specification
debug_power_assert!(self.cur_is(Walrus)); debug_power_assert!(self.cur_is(Walrus));
self.skip(); self.skip();
@ -799,9 +708,7 @@ impl Parser {
match self.peek() { match self.peek() {
Some(t) if t.is(Symbol) => { Some(t) if t.is(Symbol) => {
if self.nth_is(1, Walrus) { if self.nth_is(1, Walrus) {
let acc = self let acc = self.try_reduce_acc_lhs().map_err(|_| self.stack_dec())?;
.try_reduce_acc(in_type_args)
.map_err(|_| self.stack_dec())?;
debug_power_assert!(self.cur_is(Walrus)); debug_power_assert!(self.cur_is(Walrus));
self.skip(); self.skip();
let keyword = if let Accessor::Ident(n) = acc { let keyword = if let Accessor::Ident(n) = acc {
@ -1473,30 +1380,144 @@ impl Parser {
#[inline] #[inline]
fn try_reduce_call_or_acc(&mut self, in_type_args: bool) -> ParseResult<Expr> { fn try_reduce_call_or_acc(&mut self, in_type_args: bool) -> ParseResult<Expr> {
debug_call_info!(self); debug_call_info!(self);
let acc = self let acc = self.try_reduce_acc_lhs().map_err(|_| self.stack_dec())?;
.try_reduce_acc(in_type_args) let mut call_or_acc = self.try_reduce_acc_chain(acc, in_type_args)?;
.map_err(|_| self.stack_dec())?; while let Some(res) = self.opt_reduce_args(in_type_args) {
if let Some(res) = self.opt_reduce_args(in_type_args) {
let args = res.map_err(|_| self.stack_dec())?; let args = res.map_err(|_| self.stack_dec())?;
let (obj, method_name) = match acc { let (receiver, method_name) = match call_or_acc {
Accessor::Attr(attr) => (*attr.obj, Some(attr.ident)), Expr::Accessor(Accessor::Attr(attr)) => (*attr.obj, Some(attr.ident)),
other => (Expr::Accessor(other), None), other => (other, None),
}; };
let mut call = Expr::Call(Call::new(obj, method_name, args)); let call = Call::new(receiver, method_name, args);
// e.g. call_or_acc = Expr::Call(call);
// f(x).y == Attr { obj: f(x) attr: .y }
// f(x) .y == Call { obj: f(x), args: [.y] } (with warning)
// f(x) g(x) == f(x)(g(x))
while let Some(res) = self.opt_reduce_args(in_type_args) {
let args = res.map_err(|_| self.stack_dec())?;
call = Expr::Call(Call::new(call, None, args));
}
self.level -= 1;
Ok(call)
} else {
self.level -= 1;
Ok(Expr::Accessor(acc))
} }
self.level -= 1;
Ok(call_or_acc)
}
/// [y], .0, .attr, .method(...), (...)
#[inline]
fn try_reduce_acc_chain(&mut self, acc: Accessor, in_type_args: bool) -> ParseResult<Expr> {
debug_call_info!(self);
let mut obj = Expr::Accessor(acc);
loop {
match self.peek() {
Some(t) if t.is(LSqBr) && obj.col_end() == t.col_begin() => {
let _l_sqbr = self.lpop();
let index = self
.try_reduce_expr(true, false, false)
.map_err(|_| self.stack_dec())?;
let r_sqbr = if self.cur_is(RSqBr) {
self.lpop()
} else {
self.level -= 1;
// TODO: error report: RSqBr not found
let err = self.skip_and_throw_syntax_err(caused_by!());
self.errs.push(err);
return Err(());
};
obj = Expr::Accessor(Accessor::subscr(obj, index, r_sqbr));
}
Some(t) if t.is(Dot) && obj.col_end() == t.col_begin() => {
let vis = self.lpop();
let token = self.lpop();
match token.kind {
Symbol => {
let ident = Identifier::new(Some(vis), VarName::new(token));
obj = Expr::Accessor(Accessor::attr(obj, ident));
}
NatLit => {
let index = Literal::from(token);
obj = Expr::Accessor(Accessor::tuple_attr(obj, index));
}
Newline => {
self.restore(token);
self.restore(vis);
break;
}
_ => {
self.restore(token);
self.level -= 1;
let err = self.skip_and_throw_syntax_err(caused_by!());
self.errs.push(err);
return Err(());
}
}
}
// e.g. l[0].0
Some(t) if t.is(RatioLit) && obj.col_end() == t.col_begin() => {
let mut token = self.lpop();
token.content = Str::rc(&token.content[1..]);
token.kind = NatLit;
token.col_begin += 1;
let index = Literal::from(token);
obj = Expr::Accessor(Accessor::tuple_attr(obj, index));
}
Some(t) if t.is(DblColon) && obj.col_end() == t.col_begin() => {
let vis = self.lpop();
let token = self.lpop();
match token.kind {
Symbol => {
let ident = Identifier::new(None, VarName::new(token));
obj = Expr::Accessor(Accessor::attr(obj, ident));
}
LBrace => {
self.restore(token);
let args = self
.try_reduce_brace_container()
.map_err(|_| self.stack_dec())?;
match args {
BraceContainer::Record(args) => {
obj = Expr::DataPack(DataPack::new(obj, vis, args));
}
other => {
self.level -= 1;
let err = ParseError::simple_syntax_error(
line!() as usize,
other.loc(),
);
self.errs.push(err);
return Err(());
}
}
}
// MethodDefs
Newline => {
self.restore(token);
self.restore(vis);
break;
}
_ => {
self.restore(token);
self.level -= 1;
let err = self.skip_and_throw_syntax_err(caused_by!());
self.errs.push(err);
return Err(());
}
}
}
Some(t) if t.is(LParen) && obj.col_end() == t.col_begin() => {
let args = self.try_reduce_args(false).map_err(|_| self.stack_dec())?;
let (receiver, method_name) = match obj {
Expr::Accessor(Accessor::Attr(attr)) => (*attr.obj, Some(attr.ident)),
other => (other, None),
};
let call = Call::new(receiver, method_name, args);
obj = Expr::Call(call);
}
Some(t) if t.is(VBar) && !in_type_args => {
let type_args = self
.try_reduce_type_app_args()
.map_err(|_| self.stack_dec())?;
obj = Expr::Accessor(Accessor::TypeApp(TypeApp::new(obj, type_args)));
}
_ => {
break;
}
}
}
self.level -= 1;
Ok(obj)
} }
#[inline] #[inline]
@ -1754,7 +1775,7 @@ impl Parser {
return Ok(ShortenedRecord::new(l_brace, r_brace, idents)); return Ok(ShortenedRecord::new(l_brace, r_brace, idents));
} }
Some(_) => { Some(_) => {
let acc = self.try_reduce_acc(false).map_err(|_| self.stack_dec())?; let acc = self.try_reduce_acc_lhs().map_err(|_| self.stack_dec())?;
let acc = match acc { let acc = match acc {
Accessor::Ident(ident) => ident, Accessor::Ident(ident) => ident,
other => { other => {

View file

@ -35,10 +35,11 @@ pub fn array_mut(elem_t: Type, len: TyParam) -> Type {
builtin_poly("Array!", vec![TyParam::t(elem_t), len]) builtin_poly("Array!", vec![TyParam::t(elem_t), len])
} }
// FIXME
pub fn tuple(args: Vec<Type>) -> Type { pub fn tuple(args: Vec<Type>) -> Type {
let name = format!("Tuple{}", args.len()); builtin_poly(
builtin_poly(name, args.into_iter().map(TyParam::t).collect()) "Tuple",
vec![TyParam::Array(args.into_iter().map(TyParam::t).collect())],
)
} }
pub fn set_t(elem_t: Type, len: TyParam) -> Type { pub fn set_t(elem_t: Type, len: TyParam) -> Type {
@ -280,6 +281,10 @@ pub fn fn1_met(self_t: Type, input_t: Type, return_t: Type) -> Type {
) )
} }
pub fn fn1_kw_met(self_t: Type, input: ParamTy, return_t: Type) -> Type {
fn_met(self_t, vec![input], None, vec![], return_t)
}
pub fn pr_met( pub fn pr_met(
self_t: Type, self_t: Type,
mut non_default_params: Vec<ParamTy>, mut non_default_params: Vec<ParamTy>,
@ -383,13 +388,22 @@ pub fn poly<P: Into<PathBuf>, T: Into<Str>>(path: P, name: T, params: Vec<TyPara
} }
#[inline] #[inline]
pub fn mono_proj<S: Into<Str>>(lhs: Type, rhs: S) -> Type { pub fn proj<S: Into<Str>>(lhs: Type, rhs: S) -> Type {
Type::MonoProj { Type::Proj {
lhs: Box::new(lhs), lhs: Box::new(lhs),
rhs: rhs.into(), rhs: rhs.into(),
} }
} }
#[inline]
pub fn proj_method<S: Into<Str>>(lhs: TyParam, method_name: S, args: Vec<TyParam>) -> Type {
Type::ProjMethod {
lhs: Box::new(lhs),
method_name: method_name.into(),
args,
}
}
/// ```rust /// ```rust
/// {I: Int | I >= 0} /// {I: Int | I >= 0}
/// => Refinement{ /// => Refinement{

View file

@ -1171,10 +1171,15 @@ pub enum Type {
name: Str, name: Str,
params: Vec<TyParam>, params: Vec<TyParam>,
}, },
MonoProj { Proj {
lhs: Box<Type>, lhs: Box<Type>,
rhs: Str, rhs: Str,
}, // e.g. T.U }, // e.g. T.U
ProjMethod {
lhs: Box<TyParam>,
method_name: Str,
args: Vec<TyParam>,
}, // e.g. Ts.__getitem__(N)
FreeVar(FreeTyVar), // a reference to the type of other expression, see docs/compiler/inference.md FreeVar(FreeTyVar), // a reference to the type of other expression, see docs/compiler/inference.md
Failure, // when failed to infer (e.g. get the type of `match`) Failure, // when failed to infer (e.g. get the type of `match`)
/// used to represent `TyParam` is not initialized (see `erg_compiler::context::instantiate_tp`) /// used to represent `TyParam` is not initialized (see `erg_compiler::context::instantiate_tp`)
@ -1279,12 +1284,24 @@ impl PartialEq for Type {
}, },
) => ln == rn && lps == rps, ) => ln == rn && lps == rps,
( (
Self::MonoProj { lhs, rhs }, Self::Proj { lhs, rhs },
Self::MonoProj { Self::Proj {
lhs: rlhs, lhs: rlhs,
rhs: rrhs, rhs: rrhs,
}, },
) => lhs == rlhs && rhs == rrhs, ) => lhs == rlhs && rhs == rrhs,
(
Self::ProjMethod {
lhs,
method_name,
args,
},
Self::ProjMethod {
lhs: r,
method_name: rm,
args: ra,
},
) => lhs == r && method_name == rm && args == ra,
(Self::FreeVar(fv), other) if fv.is_linked() => &*fv.crack() == other, (Self::FreeVar(fv), other) if fv.is_linked() => &*fv.crack() == other,
(_self, Self::FreeVar(fv)) if fv.is_linked() => _self == &*fv.crack(), (_self, Self::FreeVar(fv)) if fv.is_linked() => _self == &*fv.crack(),
(Self::FreeVar(l), Self::FreeVar(r)) => l == r, (Self::FreeVar(l), Self::FreeVar(r)) => l == r,
@ -1406,10 +1423,25 @@ impl LimitedDisplay for Type {
write!(f, "{name}") write!(f, "{name}")
} }
Self::FreeVar(fv) => fv.limited_fmt(f, limit), Self::FreeVar(fv) => fv.limited_fmt(f, limit),
Self::MonoProj { lhs, rhs } => { Self::Proj { lhs, rhs } => {
lhs.limited_fmt(f, limit - 1)?; lhs.limited_fmt(f, limit - 1)?;
write!(f, ".{rhs}") write!(f, ".{rhs}")
} }
Self::ProjMethod {
lhs,
method_name,
args,
} => {
lhs.limited_fmt(f, limit - 1)?;
write!(f, ".{method_name}(")?;
for (i, arg) in args.iter().enumerate() {
if i != 0 {
write!(f, ", ")?;
}
arg.limited_fmt(f, limit - 1)?;
}
write!(f, ")")
}
_ => write!(f, "{}", self.name()), _ => write!(f, "{}", self.name()),
} }
} }
@ -1553,7 +1585,7 @@ impl HasLevel for Type {
p.update_level(level); p.update_level(level);
} }
} }
Self::MonoProj { lhs, .. } => { Self::Proj { lhs, .. } => {
lhs.update_level(level); lhs.update_level(level);
} }
Self::Refinement(refine) => { Self::Refinement(refine) => {
@ -1616,7 +1648,7 @@ impl HasLevel for Type {
p.lift(); p.lift();
} }
} }
Self::MonoProj { lhs, .. } => { Self::Proj { lhs, .. } => {
lhs.lift(); lhs.lift();
} }
Self::Refinement(refine) => { Self::Refinement(refine) => {
@ -1728,7 +1760,7 @@ impl Type {
| Self::Poly { name, .. } | Self::Poly { name, .. }
| Self::BuiltinPoly { name, .. } | Self::BuiltinPoly { name, .. }
| Self::PolyQVar { name, .. } | Self::PolyQVar { name, .. }
| Self::MonoProj { rhs: name, .. } => name.ends_with('!'), | Self::Proj { rhs: name, .. } => name.ends_with('!'),
Self::Refinement(refine) => refine.t.is_mut_type(), Self::Refinement(refine) => refine.t.is_mut_type(),
_ => false, _ => false,
} }
@ -1899,8 +1931,9 @@ impl Type {
FreeKind::Linked(t) | FreeKind::UndoableLinked { t, .. } => t.name(), FreeKind::Linked(t) | FreeKind::UndoableLinked { t, .. } => t.name(),
FreeKind::NamedUnbound { name, .. } => name.clone(), FreeKind::NamedUnbound { name, .. } => name.clone(),
FreeKind::Unbound { id, .. } => Str::from(format!("%{id}")), FreeKind::Unbound { id, .. } => Str::from(format!("%{id}")),
}, // TODO: 中身がSomeなら表示したい },
Self::MonoProj { .. } => Str::ever("MonoProj"), Self::Proj { .. } => Str::ever("MonoProj"),
Self::ProjMethod { .. } => Str::ever("MonoProjMethod"),
Self::Failure => Str::ever("Failure"), Self::Failure => Str::ever("Failure"),
Self::Uninited => Str::ever("Uninited"), Self::Uninited => Str::ever("Uninited"),
} }
@ -1979,7 +2012,7 @@ impl Type {
Self::Poly { params, .. } | Self::BuiltinPoly { params, .. } => { Self::Poly { params, .. } | Self::BuiltinPoly { params, .. } => {
params.iter().any(|tp| tp.has_qvar()) params.iter().any(|tp| tp.has_qvar())
} }
Self::MonoProj { lhs, .. } => lhs.has_qvar(), Self::Proj { lhs, .. } => lhs.has_qvar(),
_ => false, _ => false,
} }
} }
@ -2023,7 +2056,7 @@ impl Type {
Self::Poly { params, .. } Self::Poly { params, .. }
| Self::BuiltinPoly { params, .. } | Self::BuiltinPoly { params, .. }
| Self::PolyQVar { params, .. } => params.iter().all(|p| p.is_cachable()), | Self::PolyQVar { params, .. } => params.iter().all(|p| p.is_cachable()),
Self::MonoProj { lhs, .. } => lhs.is_cachable(), Self::Proj { lhs, .. } => lhs.is_cachable(),
_ => true, _ => true,
} }
} }
@ -2074,7 +2107,7 @@ impl Type {
Self::Poly { params, .. } Self::Poly { params, .. }
| Self::BuiltinPoly { params, .. } | Self::BuiltinPoly { params, .. }
| Self::PolyQVar { params, .. } => params.iter().any(|p| p.has_unbound_var()), | Self::PolyQVar { params, .. } => params.iter().any(|p| p.has_unbound_var()),
Self::MonoProj { lhs, .. } => lhs.has_no_unbound_var(), Self::Proj { lhs, .. } => lhs.has_no_unbound_var(),
_ => false, _ => false,
} }
} }

View file

@ -1,7 +1,9 @@
use std::cmp::Ordering; use std::cmp::Ordering;
use std::fmt; use std::fmt;
use std::ops::{Add, Div, Mul, Neg, Range, RangeInclusive, Sub}; use std::ops::{Add, Div, Mul, Neg, Range, RangeInclusive, Sub};
use std::rc::Rc;
use erg_common::dict;
use erg_common::dict::Dict; use erg_common::dict::Dict;
use erg_common::traits::LimitedDisplay; use erg_common::traits::LimitedDisplay;
@ -69,6 +71,15 @@ impl fmt::Display for OpKind {
} }
} }
impl OpKind {
pub fn is_comparison(&self) -> bool {
matches!(
self,
Self::Gt | Self::Lt | Self::Ge | Self::Le | Self::Eq | Self::Ne
)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum IntervalOp { pub enum IntervalOp {
/// .. /// ..
@ -130,7 +141,7 @@ pub enum TyParam {
Tuple(Vec<TyParam>), Tuple(Vec<TyParam>),
Dict(Dict<TyParam, TyParam>), Dict(Dict<TyParam, TyParam>),
Mono(Str), Mono(Str),
MonoProj { Proj {
obj: Box<TyParam>, obj: Box<TyParam>,
attr: Str, attr: Str,
}, },
@ -166,8 +177,8 @@ impl PartialEq for TyParam {
(Self::Tuple(l), Self::Tuple(r)) => l == r, (Self::Tuple(l), Self::Tuple(r)) => l == r,
(Self::Mono(l), Self::Mono(r)) | (Self::MonoQVar(l), Self::MonoQVar(r)) => l == r, (Self::Mono(l), Self::Mono(r)) | (Self::MonoQVar(l), Self::MonoQVar(r)) => l == r,
( (
Self::MonoProj { obj, attr }, Self::Proj { obj, attr },
Self::MonoProj { Self::Proj {
obj: r_obj, obj: r_obj,
attr: r_attr, attr: r_attr,
}, },
@ -278,7 +289,7 @@ impl LimitedDisplay for TyParam {
} }
Self::Mono(name) => write!(f, "{}", name), Self::Mono(name) => write!(f, "{}", name),
Self::MonoQVar(name) => write!(f, "'{}", name), Self::MonoQVar(name) => write!(f, "'{}", name),
Self::MonoProj { obj, attr } => { Self::Proj { obj, attr } => {
write!(f, "{}.", obj)?; write!(f, "{}.", obj)?;
write!(f, "{}", attr) write!(f, "{}", attr)
} }
@ -395,6 +406,39 @@ impl<V: Into<ValueObj>> From<V> for TyParam {
} }
} }
impl TryFrom<TyParam> for ValueObj {
type Error = ();
fn try_from(tp: TyParam) -> Result<Self, ()> {
match tp {
TyParam::Array(tps) => {
let mut vals = vec![];
for tp in tps {
vals.push(ValueObj::try_from(tp)?);
}
Ok(ValueObj::Array(Rc::from(vals)))
}
TyParam::Tuple(tps) => {
let mut vals = vec![];
for tp in tps {
vals.push(ValueObj::try_from(tp)?);
}
Ok(ValueObj::Tuple(Rc::from(vals)))
}
TyParam::Dict(tps) => {
let mut vals = dict! {};
for (k, v) in tps {
vals.insert(ValueObj::try_from(k)?, ValueObj::try_from(v)?);
}
Ok(ValueObj::Dict(vals))
}
TyParam::FreeVar(fv) if fv.is_linked() => ValueObj::try_from(fv.crack().clone()),
TyParam::Type(t) => Ok(ValueObj::builtin_t(*t)),
TyParam::Value(v) => Ok(v),
_ => panic!("Expected value, got {:?}", tp),
}
}
}
impl HasLevel for TyParam { impl HasLevel for TyParam {
fn level(&self) -> Option<Level> { fn level(&self) -> Option<Level> {
match self { match self {
@ -454,8 +498,8 @@ impl TyParam {
Self::MonoQVar(name.into()) Self::MonoQVar(name.into())
} }
pub fn mono_proj<S: Into<Str>>(obj: TyParam, attr: S) -> Self { pub fn proj<S: Into<Str>>(obj: TyParam, attr: S) -> Self {
Self::MonoProj { Self::Proj {
obj: Box::new(obj), obj: Box::new(obj),
attr: attr.into(), attr: attr.into(),
} }
@ -485,6 +529,14 @@ impl TyParam {
} }
} }
pub fn as_type(&self) -> Option<Type> {
match self {
Self::Type(t) => Some(t.as_ref().clone()),
// TODO: Array, Dict, Set
_ => None,
}
}
#[inline] #[inline]
pub fn mutate(self) -> Self { pub fn mutate(self) -> Self {
Self::unary(OpKind::Mutate, self) Self::unary(OpKind::Mutate, self)
@ -580,7 +632,7 @@ impl TyParam {
} }
} }
Self::Type(t) => t.has_qvar(), Self::Type(t) => t.has_qvar(),
Self::MonoProj { obj, .. } => obj.has_qvar(), Self::Proj { obj, .. } => obj.has_qvar(),
Self::Array(ts) | Self::Tuple(ts) | Self::Set(ts) => ts.iter().any(|t| t.has_qvar()), Self::Array(ts) | Self::Tuple(ts) | Self::Set(ts) => ts.iter().any(|t| t.has_qvar()),
Self::UnaryOp { val, .. } => val.has_qvar(), Self::UnaryOp { val, .. } => val.has_qvar(),
Self::BinOp { lhs, rhs, .. } => lhs.has_qvar() || rhs.has_qvar(), Self::BinOp { lhs, rhs, .. } => lhs.has_qvar() || rhs.has_qvar(),
@ -594,7 +646,7 @@ impl TyParam {
match self { match self {
Self::FreeVar(_) => false, Self::FreeVar(_) => false,
Self::Type(t) => t.is_cachable(), Self::Type(t) => t.is_cachable(),
Self::MonoProj { obj, .. } => obj.is_cachable(), Self::Proj { obj, .. } => obj.is_cachable(),
Self::Array(ts) => ts.iter().all(|t| t.is_cachable()), Self::Array(ts) => ts.iter().all(|t| t.is_cachable()),
Self::Tuple(ts) => ts.iter().all(|t| t.is_cachable()), Self::Tuple(ts) => ts.iter().all(|t| t.is_cachable()),
Self::Set(ts) => ts.iter().all(|t| t.is_cachable()), Self::Set(ts) => ts.iter().all(|t| t.is_cachable()),
@ -606,6 +658,10 @@ impl TyParam {
} }
} }
pub fn is_unbound_var(&self) -> bool {
matches!(self, Self::FreeVar(fv) if fv.is_unbound() || fv.crack().is_unbound_var())
}
pub fn has_unbound_var(&self) -> bool { pub fn has_unbound_var(&self) -> bool {
match self { match self {
Self::FreeVar(fv) => { Self::FreeVar(fv) => {
@ -616,7 +672,7 @@ impl TyParam {
} }
} }
Self::Type(t) => t.has_unbound_var(), Self::Type(t) => t.has_unbound_var(),
Self::MonoProj { obj, .. } => obj.has_unbound_var(), Self::Proj { obj, .. } => obj.has_unbound_var(),
Self::Array(ts) | Self::Tuple(ts) => ts.iter().any(|t| t.has_unbound_var()), Self::Array(ts) | Self::Tuple(ts) => ts.iter().any(|t| t.has_unbound_var()),
Self::UnaryOp { val, .. } => val.has_unbound_var(), Self::UnaryOp { val, .. } => val.has_unbound_var(),
Self::BinOp { lhs, rhs, .. } => lhs.has_unbound_var() || rhs.has_unbound_var(), Self::BinOp { lhs, rhs, .. } => lhs.has_unbound_var() || rhs.has_unbound_var(),
@ -651,8 +707,14 @@ impl TyParam {
} }
pub fn update_constraint(&self, new_constraint: Constraint) { pub fn update_constraint(&self, new_constraint: Constraint) {
if let Self::Type(t) = self { match self {
t.update_constraint(new_constraint); Self::Type(t) => {
t.update_constraint(new_constraint);
}
Self::FreeVar(fv) => {
fv.update_constraint(new_constraint);
}
_ => {}
} }
} }
} }
@ -695,6 +757,24 @@ impl TryFrom<TyParamOrdering> for Ordering {
} }
impl TyParamOrdering { impl TyParamOrdering {
pub const fn canbe_eq(self) -> bool {
matches!(self, LessEqual | GreaterEqual | Equal | Any)
}
pub const fn canbe_lt(self) -> bool {
matches!(self, Less | LessEqual | NotEqual | Any)
}
pub const fn canbe_gt(self) -> bool {
matches!(self, Greater | GreaterEqual | NotEqual | Any)
}
pub const fn canbe_le(self) -> bool {
matches!(self, Less | LessEqual | Equal | Any)
}
pub const fn canbe_ge(self) -> bool {
matches!(self, Greater | GreaterEqual | Equal | Any)
}
pub const fn canbe_ne(self) -> bool {
matches!(self, NotEqual | Any)
}
pub const fn is_lt(&self) -> bool { pub const fn is_lt(&self) -> bool {
matches!(self, Less | LessEqual | Any) matches!(self, Less | LessEqual | Any)
} }

View file

@ -502,7 +502,7 @@ impl ValueObj {
Self::Float(_) => Type::Float, Self::Float(_) => Type::Float,
Self::Str(_) => Type::Str, Self::Str(_) => Type::Str,
Self::Bool(_) => Type::Bool, Self::Bool(_) => Type::Bool,
// TODO: // TODO: Zero
Self::Array(arr) => array( Self::Array(arr) => array(
arr.iter().next().unwrap().class(), arr.iter().next().unwrap().class(),
TyParam::value(arr.len()), TyParam::value(arr.len()),
@ -733,6 +733,52 @@ impl ValueObj {
} }
} }
pub fn try_lt(self, other: Self) -> Option<Self> {
match (self, other) {
(Self::Int(l), Self::Int(r)) => Some(Self::from(l < r)),
(Self::Nat(l), Self::Nat(r)) => Some(Self::from(l < r)),
(Self::Float(l), Self::Float(r)) => Some(Self::from(l < r)),
(Self::Int(l), Self::Nat(r)) => Some(Self::from(l < r as i32)),
(Self::Nat(l), Self::Int(r)) => Some(Self::from((l as i32) < r)),
(Self::Float(l), Self::Nat(r)) => Some(Self::from(l < r as f64)),
(Self::Nat(l), Self::Float(r)) => Some(Self::from((l as f64) < r)),
(Self::Float(l), Self::Int(r)) => Some(Self::from(l < r as f64)),
(Self::Int(l), Self::Float(r)) => Some(Self::from((l as f64) < r)),
(Self::Mut(m), other) => {
{
let ref_m = &mut *m.borrow_mut();
*ref_m = mem::take(ref_m).try_lt(other)?;
}
Some(Self::Mut(m))
}
(self_, Self::Mut(m)) => self_.try_lt(m.borrow().clone()),
_ => None,
}
}
pub fn try_le(self, other: Self) -> Option<Self> {
match (self, other) {
(Self::Int(l), Self::Int(r)) => Some(Self::from(l <= r)),
(Self::Nat(l), Self::Nat(r)) => Some(Self::from(l <= r)),
(Self::Float(l), Self::Float(r)) => Some(Self::from(l <= r)),
(Self::Int(l), Self::Nat(r)) => Some(Self::from(l <= r as i32)),
(Self::Nat(l), Self::Int(r)) => Some(Self::from((l as i32) <= r)),
(Self::Float(l), Self::Nat(r)) => Some(Self::from(l <= r as f64)),
(Self::Nat(l), Self::Float(r)) => Some(Self::from((l as f64) <= r)),
(Self::Float(l), Self::Int(r)) => Some(Self::from(l <= r as f64)),
(Self::Int(l), Self::Float(r)) => Some(Self::from((l as f64) <= r)),
(Self::Mut(m), other) => {
{
let ref_m = &mut *m.borrow_mut();
*ref_m = mem::take(ref_m).try_le(other)?;
}
Some(Self::Mut(m))
}
(self_, Self::Mut(m)) => self_.try_le(m.borrow().clone()),
_ => None,
}
}
pub fn try_eq(self, other: Self) -> Option<Self> { pub fn try_eq(self, other: Self) -> Option<Self> {
match (self, other) { match (self, other) {
(Self::Int(l), Self::Int(r)) => Some(Self::from(l == r)), (Self::Int(l), Self::Int(r)) => Some(Self::from(l == r)),

View file

@ -1,7 +1,3 @@
immut_dict: {Str: Int} = {"Alice": 1, "Bob": 2, "Charlie": 3} immut_dict = {"Alice": 1, "Bob": 2, "Charlie": 3}
# can insert / remove an element assert immut_dict["Alice"] == 1
telescoping_dict = {"Alice": 1, "Bob": 2, "Charlie": 3}.into {Str: Int; !*} assert immut_dict["Bob"] == 2
telescoping_dict.insert!("Dave", 4)
_ = telescoping_dict.remove!("Alice")
mut_content_dict: {Str: !Int} = {"Alice": !1, "Bob": !2, "Charlie": !3}
mut_content_dict["Bob"].update! 0

View file

@ -21,6 +21,11 @@ fn exec_class() -> Result<(), ()> {
expect_success("examples/class.er") expect_success("examples/class.er")
} }
/*#[test]
fn exec_dict() -> Result<(), ()> {
expect_success("examples/dict.er")
}*/
#[test] #[test]
fn exec_fib() -> Result<(), ()> { fn exec_fib() -> Result<(), ()> {
expect_success("examples/fib.er") expect_success("examples/fib.er")