mirror of
https://github.com/erg-lang/erg.git
synced 2025-09-30 12:51:10 +00:00
Implement ProjMethod
This commit is contained in:
parent
9fd98001fe
commit
9c3acc8e19
22 changed files with 1087 additions and 697 deletions
|
@ -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()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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"),
|
||||||
|
|
|
@ -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(<);
|
||||||
let sup = self.sup(&t);
|
let l_sup = self.sup(<);
|
||||||
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)
|
||||||
|
|
|
@ -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!(),
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
|
}
|
||||||
|
|
|
@ -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(
|
||||||
|
|
|
@ -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)),
|
||||||
|
|
|
@ -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() {
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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(()),
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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 => {
|
||||||
|
|
|
@ -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{
|
||||||
|
|
|
@ -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,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)),
|
||||||
|
|
|
@ -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
|
|
||||||
|
|
|
@ -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")
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue