mirror of
https://github.com/erg-lang/erg.git
synced 2025-08-03 10:23:20 +00:00
chore: add TyParam::proj_call
This commit is contained in:
parent
664f265716
commit
1ea2c74aaa
15 changed files with 408 additions and 191 deletions
|
@ -426,7 +426,7 @@ impl Context {
|
|||
},
|
||||
_,
|
||||
) => {
|
||||
if let Ok(evaled) = self.eval_proj_call(
|
||||
if let Ok(evaled) = self.eval_proj_call_t(
|
||||
*l.clone(),
|
||||
attr_name.clone(),
|
||||
args.clone(),
|
||||
|
@ -447,7 +447,7 @@ impl Context {
|
|||
args,
|
||||
},
|
||||
) => {
|
||||
if let Ok(evaled) = self.eval_proj_call(
|
||||
if let Ok(evaled) = self.eval_proj_call_t(
|
||||
*r.clone(),
|
||||
attr_name.clone(),
|
||||
args.clone(),
|
||||
|
|
|
@ -1050,6 +1050,9 @@ impl Context {
|
|||
})?;
|
||||
Ok(TyParam::Value(ValueObj::Type(t)))
|
||||
}
|
||||
TyParam::ProjCall { obj, attr, args } => self
|
||||
.eval_proj_call(*obj, attr, args, &())
|
||||
.map(TyParam::value),
|
||||
TyParam::Value(_) => Ok(p.clone()),
|
||||
_other => feature_error!(self, Location::Unknown, "???"),
|
||||
}
|
||||
|
@ -1145,7 +1148,7 @@ impl Context {
|
|||
attr_name,
|
||||
args,
|
||||
} => self
|
||||
.eval_proj_call(*lhs, attr_name, args, level, t_loc)
|
||||
.eval_proj_call_t(*lhs, attr_name, args, level, t_loc)
|
||||
.map_err(|errs| (Failure, errs)),
|
||||
Type::Ref(l) => match self.eval_t_params(*l, level, t_loc) {
|
||||
Ok(t) => Ok(ref_(t)),
|
||||
|
@ -1405,6 +1408,7 @@ impl Context {
|
|||
let lhs = self.convert_tp_into_type(*obj)?;
|
||||
Ok(lhs.proj(attr))
|
||||
}
|
||||
TyParam::ProjCall { obj, attr, args } => Ok(proj_call(*obj, attr, args)),
|
||||
// TyParam::Erased(_t) => Ok(Type::Obj),
|
||||
TyParam::Value(v) => self.convert_value_into_type(v).map_err(TyParam::Value),
|
||||
// TODO: Dict, Set
|
||||
|
@ -1412,8 +1416,12 @@ impl Context {
|
|||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::only_used_in_recursion)]
|
||||
pub(crate) fn convert_tp_into_value(&self, tp: TyParam) -> Result<ValueObj, TyParam> {
|
||||
match tp {
|
||||
TyParam::FreeVar(fv) if fv.is_linked() => {
|
||||
self.convert_tp_into_value(fv.crack().clone())
|
||||
}
|
||||
TyParam::Value(v) => Ok(v),
|
||||
other => Err(other),
|
||||
}
|
||||
|
@ -1421,6 +1429,9 @@ impl Context {
|
|||
|
||||
pub(crate) fn convert_singular_type_into_value(&self, typ: Type) -> Result<ValueObj, Type> {
|
||||
match typ {
|
||||
Type::FreeVar(fv) if fv.is_linked() => {
|
||||
self.convert_singular_type_into_value(fv.crack().clone())
|
||||
}
|
||||
Type::Refinement(ref refine) => {
|
||||
if let Predicate::Equal { rhs, .. } = refine.pred.as_ref() {
|
||||
self.convert_tp_into_value(rhs.clone()).map_err(|_| typ)
|
||||
|
@ -1537,6 +1548,10 @@ impl Context {
|
|||
|
||||
fn _convert_type_to_dict_type(&self, ty: Type) -> Result<Dict<Type, Type>, ()> {
|
||||
match ty {
|
||||
Type::FreeVar(fv) if fv.is_linked() => {
|
||||
self._convert_type_to_dict_type(fv.crack().clone())
|
||||
}
|
||||
Type::Refinement(refine) => self._convert_type_to_dict_type(*refine.t),
|
||||
Type::Poly { name, params } if &name[..] == "Dict" => {
|
||||
let dict = Dict::try_from(params[0].clone())?;
|
||||
let mut new_dict = dict! {};
|
||||
|
@ -1551,14 +1566,20 @@ impl Context {
|
|||
}
|
||||
}
|
||||
|
||||
fn convert_type_to_array(&self, ty: Type) -> Result<Vec<ValueObj>, Type> {
|
||||
pub(crate) fn convert_type_to_array(&self, ty: Type) -> Result<Vec<ValueObj>, Type> {
|
||||
match ty {
|
||||
Type::FreeVar(fv) if fv.is_linked() => self.convert_type_to_array(fv.crack().clone()),
|
||||
Type::Refinement(refine) => self.convert_type_to_array(*refine.t),
|
||||
Type::Poly { name, params } if &name[..] == "Array" || &name[..] == "Array!" => {
|
||||
let Ok(t) = self.convert_tp_into_type(params[0].clone()) else {
|
||||
log!(err "cannot convert to type: {}", params[0]);
|
||||
return Err(poly(name, params));
|
||||
};
|
||||
let TyParam::Value(ValueObj::Nat(len)) = params[1] else { unreachable!() };
|
||||
Ok(vec![ValueObj::builtin_type(t); len as usize])
|
||||
let Ok(len) = usize::try_from(¶ms[1]) else {
|
||||
log!(err "cannot convert to usize: {}", params[1]);
|
||||
return Err(poly(name, params));
|
||||
};
|
||||
Ok(vec![ValueObj::builtin_type(t); len])
|
||||
}
|
||||
_ => Err(ty),
|
||||
}
|
||||
|
@ -1848,7 +1869,7 @@ impl Context {
|
|||
lhs: TyParam,
|
||||
args: Vec<TyParam>,
|
||||
t_loc: &impl Locational,
|
||||
) -> EvalResult<Type> {
|
||||
) -> EvalResult<ValueObj> {
|
||||
if let ValueObj::Subr(subr) = obj {
|
||||
let mut pos_args = vec![];
|
||||
if subr.sig_t().is_method() {
|
||||
|
@ -1872,13 +1893,107 @@ impl Context {
|
|||
}
|
||||
}
|
||||
let args = ValueArgs::new(pos_args, dict! {});
|
||||
let t = self.call(subr, args, t_loc.loc())?;
|
||||
let t = self
|
||||
.convert_value_into_type(t)
|
||||
.unwrap_or_else(|value| todo!("Type::try_from {value}"));
|
||||
Ok(t)
|
||||
let v = self.call(subr, args, t_loc.loc())?;
|
||||
Ok(v)
|
||||
} else {
|
||||
feature_error!(self, t_loc.loc(), "??")
|
||||
feature_error!(self, t_loc.loc(), "do_proj_call: ??")
|
||||
}
|
||||
}
|
||||
|
||||
fn do_proj_call_t(
|
||||
&self,
|
||||
obj: ValueObj,
|
||||
lhs: TyParam,
|
||||
args: Vec<TyParam>,
|
||||
t_loc: &impl Locational,
|
||||
) -> EvalResult<Type> {
|
||||
let v = self.do_proj_call(obj, lhs, args, t_loc)?;
|
||||
self.convert_value_into_type(v).map_err(|e| {
|
||||
EvalError::feature_error(
|
||||
self.cfg.input.clone(),
|
||||
t_loc.loc(),
|
||||
&format!("converting {e} to a type"),
|
||||
self.caused_by(),
|
||||
)
|
||||
.into()
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn eval_proj_call_t(
|
||||
&self,
|
||||
lhs: TyParam,
|
||||
attr_name: Str,
|
||||
args: Vec<TyParam>,
|
||||
level: usize,
|
||||
t_loc: &impl Locational,
|
||||
) -> EvalResult<Type> {
|
||||
let t = self.get_tp_t(&lhs)?;
|
||||
for ty_ctx in self.get_nominal_super_type_ctxs(&t).ok_or_else(|| {
|
||||
EvalError::type_not_found(
|
||||
self.cfg.input.clone(),
|
||||
line!() as usize,
|
||||
t_loc.loc(),
|
||||
self.caused_by(),
|
||||
&t,
|
||||
)
|
||||
})? {
|
||||
if let Ok(obj) = ty_ctx.get_const_local(&Token::symbol(&attr_name), &self.name) {
|
||||
return self.do_proj_call_t(obj, lhs, args, t_loc);
|
||||
}
|
||||
for (_class, methods) in ty_ctx.methods_list.iter() {
|
||||
if let Ok(obj) = methods.get_const_local(&Token::symbol(&attr_name), &self.name) {
|
||||
return self.do_proj_call_t(obj, lhs, args, t_loc);
|
||||
}
|
||||
}
|
||||
}
|
||||
if let TyParam::FreeVar(fv) = &lhs {
|
||||
if let Some((sub, sup)) = fv.get_subsup() {
|
||||
if self.is_trait(&sup) && !self.trait_impl_exists(&sub, &sup) {
|
||||
// to prevent double error reporting
|
||||
lhs.link(&TyParam::t(Never));
|
||||
let sub = if cfg!(feature = "debug") {
|
||||
sub
|
||||
} else {
|
||||
self.readable_type(sub)
|
||||
};
|
||||
let sup = if cfg!(feature = "debug") {
|
||||
sup
|
||||
} else {
|
||||
self.readable_type(sup)
|
||||
};
|
||||
return Err(EvalErrors::from(EvalError::no_trait_impl_error(
|
||||
self.cfg.input.clone(),
|
||||
line!() as usize,
|
||||
&sub,
|
||||
&sup,
|
||||
t_loc.loc(),
|
||||
self.caused_by(),
|
||||
self.get_simple_type_mismatch_hint(&sup, &sub),
|
||||
)));
|
||||
}
|
||||
}
|
||||
}
|
||||
// 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.coerce_tp(lhs.clone(), t_loc)?;
|
||||
if lhs != coerced {
|
||||
let proj = proj_call(coerced, attr_name, args);
|
||||
self.eval_t_params(proj, level, t_loc)
|
||||
.map(|t| {
|
||||
lhs.coerce();
|
||||
t
|
||||
})
|
||||
.map_err(|(_, errs)| errs)
|
||||
} else {
|
||||
let proj = proj_call(lhs, attr_name, args);
|
||||
Err(EvalErrors::from(EvalError::no_candidate_error(
|
||||
self.cfg.input.clone(),
|
||||
line!() as usize,
|
||||
&proj,
|
||||
t_loc.loc(),
|
||||
self.caused_by(),
|
||||
self.get_no_candidate_hint(&proj),
|
||||
)))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1887,9 +2002,8 @@ impl Context {
|
|||
lhs: TyParam,
|
||||
attr_name: Str,
|
||||
args: Vec<TyParam>,
|
||||
level: usize,
|
||||
t_loc: &impl Locational,
|
||||
) -> EvalResult<Type> {
|
||||
) -> EvalResult<ValueObj> {
|
||||
let t = self.get_tp_t(&lhs)?;
|
||||
for ty_ctx in self.get_nominal_super_type_ctxs(&t).ok_or_else(|| {
|
||||
EvalError::type_not_found(
|
||||
|
@ -1940,13 +2054,7 @@ impl Context {
|
|||
// In many cases, it is still better to determine the type variable than if the target is not found.
|
||||
let coerced = self.coerce_tp(lhs.clone(), t_loc)?;
|
||||
if lhs != coerced {
|
||||
let proj = proj_call(coerced, attr_name, args);
|
||||
self.eval_t_params(proj, level, t_loc)
|
||||
.map(|t| {
|
||||
lhs.coerce();
|
||||
t
|
||||
})
|
||||
.map_err(|(_, errs)| errs)
|
||||
self.eval_proj_call(coerced, attr_name, args, t_loc)
|
||||
} else {
|
||||
let proj = proj_call(lhs, attr_name, args);
|
||||
Err(EvalErrors::from(EvalError::no_candidate_error(
|
||||
|
@ -2087,6 +2195,11 @@ impl Context {
|
|||
)
|
||||
}
|
||||
},
|
||||
TyParam::ProjCall { obj, attr, args } => {
|
||||
let v = self.eval_proj_call(*obj, attr, args, &())?;
|
||||
log!(err "{v}");
|
||||
Ok(v_enum(set![v]))
|
||||
}
|
||||
other => feature_error!(
|
||||
self,
|
||||
Location::Unknown,
|
||||
|
|
|
@ -693,7 +693,7 @@ impl<'c, 'q, 'l, L: Locational> Dereferencer<'c, 'q, 'l, L> {
|
|||
}
|
||||
let proj = self
|
||||
.ctx
|
||||
.eval_proj_call(lhs, attr_name, new_args, self.ctx.level, self.loc)
|
||||
.eval_proj_call_t(lhs, attr_name, new_args, self.ctx.level, self.loc)
|
||||
.unwrap_or(Failure);
|
||||
Ok(proj)
|
||||
}
|
||||
|
|
|
@ -1262,7 +1262,13 @@ impl Context {
|
|||
.register_marker_trait(self, poly(INDEXABLE, vec![ty_tp(input), ty_tp(T.clone())]))
|
||||
.unwrap();
|
||||
array_
|
||||
.register_marker_trait(self, poly(SHAPE, vec![TyParam::Array(vec![N.clone()])]))
|
||||
.register_marker_trait(
|
||||
self,
|
||||
poly(
|
||||
SHAPE,
|
||||
vec![ty_tp(arr_t.clone()).proj_call(FUNC_SHAPE.into(), vec![])],
|
||||
),
|
||||
)
|
||||
.unwrap();
|
||||
let mut array_sized = Self::builtin_methods(Some(mono(SIZED)), 2);
|
||||
array_sized.register_builtin_erg_impl(
|
||||
|
@ -1275,12 +1281,25 @@ impl Context {
|
|||
// union: (self: [Type; _]) -> Type
|
||||
let array_union_t = fn0_met(array_t(Type, TyParam::erased(Nat)), Type).quantify();
|
||||
let union = ValueObj::Subr(ConstSubr::Builtin(BuiltinConstSubr::new(
|
||||
UNION_FUNC,
|
||||
FUNC_UNION,
|
||||
array_union,
|
||||
array_union_t,
|
||||
None,
|
||||
)));
|
||||
array_.register_builtin_const(UNION_FUNC, Visibility::BUILTIN_PUBLIC, union);
|
||||
array_.register_builtin_const(FUNC_UNION, Visibility::BUILTIN_PUBLIC, union);
|
||||
// shape: (self: [Type; _]) -> [Nat; _]
|
||||
let array_shape_t = fn0_met(
|
||||
array_t(Type, TyParam::erased(Nat)),
|
||||
unknown_len_array_t(Nat),
|
||||
)
|
||||
.quantify();
|
||||
let shape = ValueObj::Subr(ConstSubr::Builtin(BuiltinConstSubr::new(
|
||||
FUNC_SHAPE,
|
||||
array_shape,
|
||||
array_shape_t,
|
||||
None,
|
||||
)));
|
||||
array_.register_builtin_const(FUNC_SHAPE, Visibility::BUILTIN_PUBLIC, shape);
|
||||
let mut array_eq = Self::builtin_methods(Some(mono(EQ)), 2);
|
||||
array_eq.register_builtin_erg_impl(
|
||||
OP_EQ,
|
||||
|
@ -1598,7 +1617,7 @@ impl Context {
|
|||
// __Tuple_getitem__: (self: Tuple(Ts), _: {N}) -> Ts[N]
|
||||
let input_t = tp_enum(Nat, set! {N.clone()});
|
||||
let return_t = proj_call(Ts.clone(), FUNDAMENTAL_GETITEM, vec![N.clone()]);
|
||||
let union_t = proj_call(Ts.clone(), UNION_FUNC, vec![]);
|
||||
let union_t = proj_call(Ts.clone(), FUNC_UNION, vec![]);
|
||||
let tuple_getitem_t =
|
||||
fn1_met(_tuple_t.clone(), input_t.clone(), return_t.clone()).quantify();
|
||||
tuple_.register_builtin_py_impl(
|
||||
|
@ -1623,13 +1642,13 @@ impl Context {
|
|||
let mut tuple_iterable = Self::builtin_methods(
|
||||
Some(poly(
|
||||
ITERABLE,
|
||||
vec![ty_tp(proj_call(Ts.clone(), UNION_FUNC, vec![]))],
|
||||
vec![ty_tp(proj_call(Ts.clone(), FUNC_UNION, vec![]))],
|
||||
)),
|
||||
2,
|
||||
);
|
||||
let tuple_iterator = poly(
|
||||
TUPLE_ITERATOR,
|
||||
vec![ty_tp(proj_call(Ts, UNION_FUNC, vec![]))],
|
||||
vec![ty_tp(proj_call(Ts, FUNC_UNION, vec![]))],
|
||||
);
|
||||
// Tuple(Ts) -> TupleIterator(Ts.union())
|
||||
let t = fn0_met(_tuple_t.clone(), tuple_iterator.clone()).quantify();
|
||||
|
@ -1791,7 +1810,7 @@ impl Context {
|
|||
Some(SYMMETRIC_DIFFERENCE),
|
||||
3,
|
||||
);
|
||||
frozenset.register_py_builtin(UNION_FUNC, bin_t, Some(UNION_FUNC), 3);
|
||||
frozenset.register_py_builtin(FUNC_UNION, bin_t, Some(FUNC_UNION), 3);
|
||||
let memview_t = mono(MEMORYVIEW);
|
||||
let mut memoryview = Self::builtin_mono_class(MEMORYVIEW, 2);
|
||||
memoryview.register_superclass(Obj, &obj);
|
||||
|
|
|
@ -1,7 +1,10 @@
|
|||
use std::fmt::Display;
|
||||
use std::mem;
|
||||
|
||||
use erg_common::dict::Dict;
|
||||
use erg_common::enum_unwrap;
|
||||
#[allow(unused_imports)]
|
||||
use erg_common::log;
|
||||
use erg_common::{enum_unwrap, ArcArray};
|
||||
|
||||
use crate::context::Context;
|
||||
use crate::feature_error;
|
||||
|
@ -16,13 +19,42 @@ use super::{DICT_ITEMS, DICT_KEYS, DICT_VALUES};
|
|||
const ERR: Color = THEME.colors.error;
|
||||
const WARN: Color = THEME.colors.warning;
|
||||
|
||||
const SUP_ERR: StyledStr = StyledStr::new("Super", Some(ERR), None);
|
||||
const SUP_WARN: StyledStr = StyledStr::new("Super", Some(WARN), None);
|
||||
const CLASS_ERR: StyledStr = StyledStr::new("Class", Some(ERR), None);
|
||||
const REQ_ERR: StyledStr = StyledStr::new("Requirement", Some(ERR), None);
|
||||
const REQ_WARN: StyledStr = StyledStr::new("Requirement", Some(WARN), None);
|
||||
const BASE_ERR: StyledStr = StyledStr::new("Base", Some(ERR), None);
|
||||
const BASE_WARN: StyledStr = StyledStr::new("Base", Some(WARN), None);
|
||||
fn not_passed(t: impl Display) -> EvalValueError {
|
||||
let text = t.to_string();
|
||||
let param = StyledStr::new(&text, Some(ERR), None);
|
||||
ErrorCore::new(
|
||||
vec![SubMessage::only_loc(Location::Unknown)],
|
||||
format!("{param} is not passed"),
|
||||
line!() as usize,
|
||||
ErrorKind::KeyError,
|
||||
Location::Unknown,
|
||||
)
|
||||
.into()
|
||||
}
|
||||
|
||||
fn no_key(slf: impl Display, key: impl Display) -> EvalValueError {
|
||||
ErrorCore::new(
|
||||
vec![SubMessage::only_loc(Location::Unknown)],
|
||||
format!("{slf} has no key {key}"),
|
||||
line!() as usize,
|
||||
ErrorKind::KeyError,
|
||||
Location::Unknown,
|
||||
)
|
||||
.into()
|
||||
}
|
||||
|
||||
fn type_mismatch(expected: impl Display, got: impl Display, param: &str) -> EvalValueError {
|
||||
let got = StyledString::new(format!("{got}"), Some(ERR), None);
|
||||
let param = StyledStr::new(param, Some(WARN), None);
|
||||
ErrorCore::new(
|
||||
vec![SubMessage::only_loc(Location::Unknown)],
|
||||
format!("non-{expected} object {got} is passed to {param}"),
|
||||
line!() as usize,
|
||||
ErrorKind::TypeError,
|
||||
Location::Unknown,
|
||||
)
|
||||
.into()
|
||||
}
|
||||
|
||||
/// Base := Type or NoneType, Impl := Type -> ClassType
|
||||
pub(crate) fn class_func(mut args: ValueArgs, ctx: &Context) -> EvalValueResult<ValueObj> {
|
||||
|
@ -35,15 +67,7 @@ pub(crate) fn class_func(mut args: ValueArgs, ctx: &Context) -> EvalValueResult<
|
|||
if let Some(base) = value.as_type(ctx) {
|
||||
Ok(ValueObj::gen_t(GenTypeObj::class(t, Some(base), impls)))
|
||||
} else {
|
||||
let base = StyledString::new(format!("{value}"), Some(ERR), None);
|
||||
Err(ErrorCore::new(
|
||||
vec![SubMessage::only_loc(Location::Unknown)],
|
||||
format!("non-type object {base} is passed to {BASE_WARN}",),
|
||||
line!() as usize,
|
||||
ErrorKind::TypeError,
|
||||
Location::Unknown,
|
||||
)
|
||||
.into())
|
||||
Err(type_mismatch("type", value, "Base"))
|
||||
}
|
||||
}
|
||||
None => Ok(ValueObj::gen_t(GenTypeObj::class(t, None, impls))),
|
||||
|
@ -52,27 +76,11 @@ pub(crate) fn class_func(mut args: ValueArgs, ctx: &Context) -> EvalValueResult<
|
|||
|
||||
/// Super: ClassType, Impl := Type, Additional := Type -> ClassType
|
||||
pub(crate) fn inherit_func(mut args: ValueArgs, ctx: &Context) -> EvalValueResult<ValueObj> {
|
||||
let sup = args.remove_left_or_key("Super").ok_or_else(|| {
|
||||
let sup = StyledStr::new("Super", Some(ERR), None);
|
||||
ErrorCore::new(
|
||||
vec![SubMessage::only_loc(Location::Unknown)],
|
||||
format!("{sup} is not passed"),
|
||||
line!() as usize,
|
||||
ErrorKind::KeyError,
|
||||
Location::Unknown,
|
||||
)
|
||||
})?;
|
||||
let sup = args
|
||||
.remove_left_or_key("Super")
|
||||
.ok_or_else(|| not_passed("Super"))?;
|
||||
let Some(sup) = sup.as_type(ctx) else {
|
||||
let sup_ty = StyledString::new(format!("{sup}"), Some(ERR), None);
|
||||
return Err(ErrorCore::new(
|
||||
vec![SubMessage::only_loc(Location::Unknown)],
|
||||
format!(
|
||||
"non-class object {sup_ty} is passed to {SUP_WARN}",
|
||||
),
|
||||
line!() as usize,
|
||||
ErrorKind::TypeError,
|
||||
Location::Unknown,
|
||||
).into());
|
||||
return Err(type_mismatch("class", sup, "Super"));
|
||||
};
|
||||
let impls = args.remove_left_or_key("Impl");
|
||||
let impls = impls.map(|v| v.as_type(ctx).unwrap());
|
||||
|
@ -87,15 +95,9 @@ pub(crate) fn inherit_func(mut args: ValueArgs, ctx: &Context) -> EvalValueResul
|
|||
/// Class: ClassType -> ClassType (with `InheritableType`)
|
||||
/// This function is used by the compiler to mark a class as inheritable and does nothing in terms of actual operation.
|
||||
pub(crate) fn inheritable_func(mut args: ValueArgs, _ctx: &Context) -> EvalValueResult<ValueObj> {
|
||||
let class = args.remove_left_or_key("Class").ok_or_else(|| {
|
||||
ErrorCore::new(
|
||||
vec![SubMessage::only_loc(Location::Unknown)],
|
||||
format!("{CLASS_ERR} is not passed"),
|
||||
line!() as usize,
|
||||
ErrorKind::KeyError,
|
||||
Location::Unknown,
|
||||
)
|
||||
})?;
|
||||
let class = args
|
||||
.remove_left_or_key("Class")
|
||||
.ok_or_else(|| not_passed("Class"))?;
|
||||
match class {
|
||||
ValueObj::Type(TypeObj::Generated(mut gen)) => {
|
||||
if let Some(typ) = gen.impls_mut() {
|
||||
|
@ -124,26 +126,11 @@ pub(crate) fn inheritable_func(mut args: ValueArgs, _ctx: &Context) -> EvalValue
|
|||
|
||||
/// Base: Type, Impl := Type -> TraitType
|
||||
pub(crate) fn trait_func(mut args: ValueArgs, ctx: &Context) -> EvalValueResult<ValueObj> {
|
||||
let req = args.remove_left_or_key("Requirement").ok_or_else(|| {
|
||||
ErrorCore::new(
|
||||
vec![SubMessage::only_loc(Location::Unknown)],
|
||||
format!("{REQ_ERR} is not passed"),
|
||||
line!() as usize,
|
||||
ErrorKind::KeyError,
|
||||
Location::Unknown,
|
||||
)
|
||||
})?;
|
||||
let req = args
|
||||
.remove_left_or_key("Requirement")
|
||||
.ok_or_else(|| not_passed("Requirement"))?;
|
||||
let Some(req) = req.as_type(ctx) else {
|
||||
let req = StyledString::new(format!("{req}"), Some(ERR), None);
|
||||
return Err(ErrorCore::new(
|
||||
vec![SubMessage::only_loc(Location::Unknown)],
|
||||
format!(
|
||||
"non-type object {req} is passed to {REQ_WARN}",
|
||||
),
|
||||
line!() as usize,
|
||||
ErrorKind::TypeError,
|
||||
Location::Unknown,
|
||||
).into());
|
||||
return Err(type_mismatch("type", req, "Requirement"));
|
||||
};
|
||||
let impls = args.remove_left_or_key("Impl");
|
||||
let impls = impls.map(|v| v.as_type(ctx).unwrap());
|
||||
|
@ -153,26 +140,11 @@ pub(crate) fn trait_func(mut args: ValueArgs, ctx: &Context) -> EvalValueResult<
|
|||
|
||||
/// Base: Type, Impl := Type -> Patch
|
||||
pub(crate) fn patch_func(mut args: ValueArgs, ctx: &Context) -> EvalValueResult<ValueObj> {
|
||||
let base = args.remove_left_or_key("Base").ok_or_else(|| {
|
||||
ErrorCore::new(
|
||||
vec![SubMessage::only_loc(Location::Unknown)],
|
||||
format!("{BASE_ERR} is not passed"),
|
||||
line!() as usize,
|
||||
ErrorKind::KeyError,
|
||||
Location::Unknown,
|
||||
)
|
||||
})?;
|
||||
let base = args
|
||||
.remove_left_or_key("Base")
|
||||
.ok_or_else(|| not_passed("Base"))?;
|
||||
let Some(base) = base.as_type(ctx) else {
|
||||
let base = StyledString::new(format!("{base}"), Some(ERR), None);
|
||||
return Err(ErrorCore::new(
|
||||
vec![SubMessage::only_loc(Location::Unknown)],
|
||||
format!(
|
||||
"non-type object {base} is passed to {BASE_WARN}",
|
||||
),
|
||||
line!() as usize,
|
||||
ErrorKind::TypeError,
|
||||
Location::Unknown,
|
||||
).into());
|
||||
return Err(type_mismatch("type", base, "Base"));
|
||||
};
|
||||
let impls = args.remove_left_or_key("Impl");
|
||||
let impls = impls.map(|v| v.as_type(ctx).unwrap());
|
||||
|
@ -182,26 +154,11 @@ pub(crate) fn patch_func(mut args: ValueArgs, ctx: &Context) -> EvalValueResult<
|
|||
|
||||
/// Super: TraitType, Impl := Type, Additional := Type -> TraitType
|
||||
pub(crate) fn subsume_func(mut args: ValueArgs, ctx: &Context) -> EvalValueResult<ValueObj> {
|
||||
let sup = args.remove_left_or_key("Super").ok_or_else(|| {
|
||||
ErrorCore::new(
|
||||
vec![SubMessage::only_loc(Location::Unknown)],
|
||||
format!("{SUP_ERR} is not passed"),
|
||||
line!() as usize,
|
||||
ErrorKind::KeyError,
|
||||
Location::Unknown,
|
||||
)
|
||||
})?;
|
||||
let sup = args
|
||||
.remove_left_or_key("Super")
|
||||
.ok_or_else(|| not_passed("Super"))?;
|
||||
let Some(sup) = sup.as_type(ctx) else {
|
||||
let sup = StyledString::new(format!("{sup}"), Some(ERR), None);
|
||||
return Err(ErrorCore::new(
|
||||
vec![SubMessage::only_loc(Location::Unknown)],
|
||||
format!(
|
||||
"non-trait object {sup} is passed to {SUP_WARN}",
|
||||
),
|
||||
line!() as usize,
|
||||
ErrorKind::TypeError,
|
||||
Location::Unknown,
|
||||
).into());
|
||||
return Err(type_mismatch("trait", sup, "Super"));
|
||||
};
|
||||
let impls = args.remove_left_or_key("Impl");
|
||||
let impls = impls.map(|v| v.as_type(ctx).unwrap());
|
||||
|
@ -214,36 +171,27 @@ pub(crate) fn subsume_func(mut args: ValueArgs, ctx: &Context) -> EvalValueResul
|
|||
}
|
||||
|
||||
pub(crate) fn structural_func(mut args: ValueArgs, ctx: &Context) -> EvalValueResult<ValueObj> {
|
||||
let type_ = args.remove_left_or_key("Type").ok_or_else(|| {
|
||||
ErrorCore::new(
|
||||
vec![SubMessage::only_loc(Location::Unknown)],
|
||||
format!("{BASE_ERR} is not passed"),
|
||||
line!() as usize,
|
||||
ErrorKind::KeyError,
|
||||
Location::Unknown,
|
||||
)
|
||||
})?;
|
||||
let type_ = args
|
||||
.remove_left_or_key("Type")
|
||||
.ok_or_else(|| not_passed("Type"))?;
|
||||
let Some(base) = type_.as_type(ctx) else {
|
||||
let type_ = StyledString::new(format!("{type_}"), Some(ERR), None);
|
||||
return Err(ErrorCore::new(
|
||||
vec![SubMessage::only_loc(Location::Unknown)],
|
||||
format!(
|
||||
"non-type object {type_} is passed to {BASE_WARN}",
|
||||
),
|
||||
line!() as usize,
|
||||
ErrorKind::TypeError,
|
||||
Location::Unknown,
|
||||
).into());
|
||||
return Err(type_mismatch("type", type_, "Type"));
|
||||
};
|
||||
let t = base.typ().clone().structuralize();
|
||||
Ok(ValueObj::gen_t(GenTypeObj::structural(t, base)))
|
||||
}
|
||||
|
||||
pub(crate) fn __array_getitem__(mut args: ValueArgs, ctx: &Context) -> EvalValueResult<ValueObj> {
|
||||
let slf = args
|
||||
.remove_left_or_key("Self")
|
||||
.ok_or_else(|| not_passed("Self"))?;
|
||||
let slf = ctx
|
||||
.convert_value_into_array(args.remove_left_or_key("Self").unwrap())
|
||||
.convert_value_into_array(slf)
|
||||
.unwrap_or_else(|err| panic!("{err}, {args}"));
|
||||
let index = enum_unwrap!(args.remove_left_or_key("Index").unwrap(), ValueObj::Nat);
|
||||
let index = args
|
||||
.remove_left_or_key("Index")
|
||||
.ok_or_else(|| not_passed("Index"))?;
|
||||
let index = enum_unwrap!(index, ValueObj::Nat);
|
||||
if let Some(v) = slf.get(index as usize) {
|
||||
Ok(v.clone())
|
||||
} else {
|
||||
|
@ -328,9 +276,13 @@ pub(crate) fn sub_tpdict_get<'d>(
|
|||
}
|
||||
|
||||
pub(crate) fn __dict_getitem__(mut args: ValueArgs, ctx: &Context) -> EvalValueResult<ValueObj> {
|
||||
let slf = args.remove_left_or_key("Self").unwrap();
|
||||
let slf = args
|
||||
.remove_left_or_key("Self")
|
||||
.ok_or_else(|| not_passed("Self"))?;
|
||||
let slf = enum_unwrap!(slf, ValueObj::Dict);
|
||||
let index = args.remove_left_or_key("Index").unwrap();
|
||||
let index = args
|
||||
.remove_left_or_key("Index")
|
||||
.ok_or_else(|| not_passed("Index"))?;
|
||||
if let Some(v) = slf.get(&index).or_else(|| sub_vdict_get(&slf, &index, ctx)) {
|
||||
Ok(v.clone())
|
||||
} else {
|
||||
|
@ -340,20 +292,15 @@ pub(crate) fn __dict_getitem__(mut args: ValueArgs, ctx: &Context) -> EvalValueR
|
|||
} else {
|
||||
index
|
||||
};
|
||||
Err(ErrorCore::new(
|
||||
vec![SubMessage::only_loc(Location::Unknown)],
|
||||
format!("{slf} has no key {index}"),
|
||||
line!() as usize,
|
||||
ErrorKind::IndexError,
|
||||
Location::Unknown,
|
||||
)
|
||||
.into())
|
||||
Err(no_key(slf, index))
|
||||
}
|
||||
}
|
||||
|
||||
/// `{Str: Int, Int: Float}.keys() == DictKeys(Str or Int)`
|
||||
pub(crate) fn dict_keys(mut args: ValueArgs, ctx: &Context) -> EvalValueResult<ValueObj> {
|
||||
let slf = args.remove_left_or_key("Self").unwrap();
|
||||
let slf = args
|
||||
.remove_left_or_key("Self")
|
||||
.ok_or_else(|| not_passed("Self"))?;
|
||||
let slf = enum_unwrap!(slf, ValueObj::Dict);
|
||||
let slf = slf
|
||||
.into_iter()
|
||||
|
@ -373,7 +320,9 @@ pub(crate) fn dict_keys(mut args: ValueArgs, ctx: &Context) -> EvalValueResult<V
|
|||
|
||||
/// `{Str: Int, Int: Float}.values() == DictValues(Int or Float)`
|
||||
pub(crate) fn dict_values(mut args: ValueArgs, ctx: &Context) -> EvalValueResult<ValueObj> {
|
||||
let slf = args.remove_left_or_key("Self").unwrap();
|
||||
let slf = args
|
||||
.remove_left_or_key("Self")
|
||||
.ok_or_else(|| not_passed("Self"))?;
|
||||
let slf = enum_unwrap!(slf, ValueObj::Dict);
|
||||
let slf = slf
|
||||
.into_iter()
|
||||
|
@ -393,7 +342,9 @@ pub(crate) fn dict_values(mut args: ValueArgs, ctx: &Context) -> EvalValueResult
|
|||
|
||||
/// `{Str: Int, Int: Float}.items() == DictItems((Str, Int) or (Int, Float))`
|
||||
pub(crate) fn dict_items(mut args: ValueArgs, ctx: &Context) -> EvalValueResult<ValueObj> {
|
||||
let slf = args.remove_left_or_key("Self").unwrap();
|
||||
let slf = args
|
||||
.remove_left_or_key("Self")
|
||||
.ok_or_else(|| not_passed("Self"))?;
|
||||
let slf = enum_unwrap!(slf, ValueObj::Dict);
|
||||
let slf = slf
|
||||
.into_iter()
|
||||
|
@ -413,7 +364,9 @@ pub(crate) fn dict_items(mut args: ValueArgs, ctx: &Context) -> EvalValueResult<
|
|||
|
||||
/// `[Int, Str].union() == Int or Str`
|
||||
pub(crate) fn array_union(mut args: ValueArgs, ctx: &Context) -> EvalValueResult<ValueObj> {
|
||||
let slf = args.remove_left_or_key("Self").unwrap();
|
||||
let slf = args
|
||||
.remove_left_or_key("Self")
|
||||
.ok_or_else(|| not_passed("Self"))?;
|
||||
let slf = enum_unwrap!(slf, ValueObj::Array);
|
||||
let slf = slf
|
||||
.iter()
|
||||
|
@ -425,15 +378,70 @@ pub(crate) fn array_union(mut args: ValueArgs, ctx: &Context) -> EvalValueResult
|
|||
Ok(ValueObj::builtin_type(union))
|
||||
}
|
||||
|
||||
// TODO
|
||||
fn _arr_shape(arr: ArcArray<ValueObj>, ctx: &Context) -> Result<Vec<ValueObj>, String> {
|
||||
let mut shape = vec![];
|
||||
let mut arr = arr;
|
||||
loop {
|
||||
shape.push(ValueObj::from(arr.len()));
|
||||
match arr.get(0) {
|
||||
Some(ValueObj::Array(arr_)) => {
|
||||
arr = arr_.clone();
|
||||
}
|
||||
Some(ValueObj::Type(t)) => {
|
||||
let Ok(arr_) = ctx.convert_type_to_array(t.typ().clone()) else {
|
||||
break;
|
||||
};
|
||||
arr = arr_.into();
|
||||
}
|
||||
_ => {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(shape)
|
||||
}
|
||||
|
||||
/// ```erg
|
||||
/// Array(Int, 2).shape() == [2,]
|
||||
/// Array(Array(Int, 2), N).shape() == [N, 2]
|
||||
/// [1, 2].shape() == [2,]
|
||||
/// [[1, 2], [3, 4], [5, 6]].shape() == [3, 2]
|
||||
/// ```
|
||||
pub(crate) fn array_shape(mut args: ValueArgs, ctx: &Context) -> EvalValueResult<ValueObj> {
|
||||
let arr = args
|
||||
.remove_left_or_key("Self")
|
||||
.ok_or_else(|| not_passed("Self"))?;
|
||||
let arr = match arr {
|
||||
ValueObj::Array(arr) => arr,
|
||||
ValueObj::Type(t) => ctx
|
||||
.convert_type_to_array(t.into_typ())
|
||||
.map_err(|arr| type_mismatch("array", arr, "Self"))?
|
||||
.into(),
|
||||
_ => {
|
||||
return Err(type_mismatch("array", arr, "Self"));
|
||||
}
|
||||
};
|
||||
let res = _arr_shape(arr, ctx).unwrap();
|
||||
let arr = ValueObj::Array(ArcArray::from(res));
|
||||
Ok(arr)
|
||||
}
|
||||
|
||||
pub(crate) fn __range_getitem__(mut args: ValueArgs, _ctx: &Context) -> EvalValueResult<ValueObj> {
|
||||
let (_name, fields) = enum_unwrap!(
|
||||
args.remove_left_or_key("Self").unwrap(),
|
||||
args.remove_left_or_key("Self")
|
||||
.ok_or_else(|| not_passed("Self"))?,
|
||||
ValueObj::DataClass { name, fields }
|
||||
);
|
||||
let index = enum_unwrap!(args.remove_left_or_key("Index").unwrap(), ValueObj::Nat);
|
||||
let start = fields.get("start").unwrap();
|
||||
let index = args
|
||||
.remove_left_or_key("Index")
|
||||
.ok_or_else(|| not_passed("Index"))?;
|
||||
let index = enum_unwrap!(index, ValueObj::Nat);
|
||||
let start = fields
|
||||
.get("start")
|
||||
.ok_or_else(|| no_key(&fields, "start"))?;
|
||||
let start = *enum_unwrap!(start, ValueObj::Nat);
|
||||
let end = fields.get("end").unwrap();
|
||||
let end = fields.get("end").ok_or_else(|| no_key(&fields, "end"))?;
|
||||
let end = *enum_unwrap!(end, ValueObj::Nat);
|
||||
// FIXME <= if inclusive
|
||||
if start + index < end {
|
||||
|
|
|
@ -245,7 +245,8 @@ const ISSUBSET: &str = "issubset";
|
|||
const ISSUPERSET: &str = "issuperset";
|
||||
const SYMMETRIC_DIFFERENCE: &str = "symmetric_difference";
|
||||
const MEMORYVIEW: &str = "MemoryView";
|
||||
const UNION_FUNC: &str = "union";
|
||||
const FUNC_UNION: &str = "union";
|
||||
const FUNC_SHAPE: &str = "shape";
|
||||
const FUNC_INC: &str = "inc";
|
||||
const PROC_INC: &str = "inc!";
|
||||
const FUNC_DEC: &str = "dec";
|
||||
|
|
|
@ -347,7 +347,7 @@ impl Context {
|
|||
Some(FUNDAMENTAL_EXIT),
|
||||
);
|
||||
/* Shape */
|
||||
let S = mono_q(TY_S, instanceof(unknown_len_array_t(Nat)));
|
||||
let S = mono_q_tp(TY_S, instanceof(unknown_len_array_t(Nat)));
|
||||
let params = vec![PS::named_nd("S", unknown_len_array_t(Nat))];
|
||||
let shape = Self::builtin_poly_trait(SHAPE, params.clone(), 2);
|
||||
/* Num */
|
||||
|
@ -545,7 +545,7 @@ impl Context {
|
|||
Const,
|
||||
None,
|
||||
);
|
||||
self.register_builtin_type(poly(SHAPE, vec![ty_tp(S)]), shape, vis.clone(), Const, None);
|
||||
self.register_builtin_type(poly(SHAPE, vec![S]), shape, vis.clone(), Const, None);
|
||||
self.register_builtin_type(poly(ADD, ty_params.clone()), add, vis.clone(), Const, None);
|
||||
self.register_builtin_type(poly(SUB, ty_params.clone()), sub, vis.clone(), Const, None);
|
||||
self.register_builtin_type(poly(MUL, ty_params.clone()), mul, vis.clone(), Const, None);
|
||||
|
|
|
@ -2390,7 +2390,7 @@ impl Context {
|
|||
attr_name,
|
||||
args,
|
||||
} => {
|
||||
if let Ok(typ) = self.eval_proj_call(
|
||||
if let Ok(typ) = self.eval_proj_call_t(
|
||||
*lhs.clone(),
|
||||
attr_name.clone(),
|
||||
args.clone(),
|
||||
|
|
|
@ -380,6 +380,18 @@ impl Context {
|
|||
}
|
||||
Ok(TyParam::app(name, new_args))
|
||||
}
|
||||
TyParam::ProjCall { obj, attr, args } => {
|
||||
let obj = self.instantiate_tp(*obj, tmp_tv_cache, loc)?;
|
||||
let mut new_args = Vec::with_capacity(args.len());
|
||||
for arg in args {
|
||||
new_args.push(self.instantiate_tp(arg, tmp_tv_cache, loc)?);
|
||||
}
|
||||
Ok(TyParam::proj_call(obj, attr, new_args))
|
||||
}
|
||||
TyParam::Proj { obj, attr } => {
|
||||
let obj = self.instantiate_tp(*obj, tmp_tv_cache, loc)?;
|
||||
Ok(TyParam::proj(obj, attr))
|
||||
}
|
||||
TyParam::Type(t) => {
|
||||
let t = self.instantiate_t_inner(*t, tmp_tv_cache, loc)?;
|
||||
Ok(TyParam::t(t))
|
||||
|
|
|
@ -1308,7 +1308,10 @@ impl Context {
|
|||
.typ()
|
||||
.typarams()
|
||||
.into_iter()
|
||||
.map(|tp| ParamSpec::t_nd(tp.qual_name().unwrap_or(Str::ever("_"))))
|
||||
.map(|tp| {
|
||||
let name = tp.qual_name().unwrap_or(Str::ever("_"));
|
||||
ParamSpec::named_nd(name, self.get_tp_t(&tp).unwrap_or(Type::Obj))
|
||||
})
|
||||
.collect();
|
||||
let mut ctx = Self::poly_class(
|
||||
gen.typ().qual_name(),
|
||||
|
|
|
@ -379,9 +379,6 @@ impl Context {
|
|||
self.sub_unify_tp(lhs, lhs2, _variance, loc, allow_divergence)?;
|
||||
self.sub_unify_tp(rhs, rhs2, _variance, loc, allow_divergence)
|
||||
}
|
||||
(TyParam::Lambda(_l), TyParam::Lambda(_r)) => {
|
||||
todo!("{_l}/{_r}")
|
||||
}
|
||||
(sub, TyParam::Erased(t)) => {
|
||||
let sub_t = self.get_tp_t(sub)?;
|
||||
if self.subtype_of(&sub_t, t) {
|
||||
|
@ -463,6 +460,24 @@ impl Context {
|
|||
}
|
||||
Ok(())
|
||||
}
|
||||
(
|
||||
TyParam::ProjCall { obj, attr, args },
|
||||
TyParam::ProjCall {
|
||||
obj: o2,
|
||||
attr: a2,
|
||||
args: args2,
|
||||
},
|
||||
) => {
|
||||
if attr == a2 {
|
||||
self.sub_unify_tp(obj, o2, _variance, loc, allow_divergence)?;
|
||||
for (l, r) in args.iter().zip(args2.iter()) {
|
||||
self.sub_unify_tp(l, r, _variance, loc, allow_divergence)?;
|
||||
}
|
||||
Ok(())
|
||||
} else {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
(l, r) => {
|
||||
log!(err "{l} / {r}");
|
||||
type_feature_error!(self, loc.loc(), &format!("unifying {l} and {r}"))
|
||||
|
|
|
@ -9,8 +9,8 @@ use erg_parser::desugar::Desugarer;
|
|||
|
||||
use crate::context::instantiate::TyVarCache;
|
||||
use crate::lower::ASTLowerer;
|
||||
use crate::ty::constructors::{mono, poly, ty_tp, type_q, v_enum};
|
||||
use crate::ty::free::HasLevel;
|
||||
use crate::ty::constructors::{mono, mono_q_tp, poly, v_enum};
|
||||
use crate::ty::free::{Constraint, HasLevel};
|
||||
use crate::ty::value::{GenTypeObj, TypeObj, ValueObj};
|
||||
use crate::ty::{HasType, Type, Visibility};
|
||||
|
||||
|
@ -703,7 +703,10 @@ impl ASTLowerer {
|
|||
let params = subr
|
||||
.non_default_params
|
||||
.iter()
|
||||
.map(|p| ty_tp(type_q(p.name().unwrap_or(&Str::ever("_")))))
|
||||
.map(|p| {
|
||||
let c = Constraint::new_type_of(p.typ().clone());
|
||||
mono_q_tp(p.name().unwrap_or(&Str::ever("_")), c)
|
||||
})
|
||||
.collect();
|
||||
let t = poly(format!("{}{ident}", self.module.context.path()), params);
|
||||
let ty_obj = GenTypeObj::class(t.clone(), None, None);
|
||||
|
|
|
@ -43,7 +43,7 @@ pub use value::ValueObj;
|
|||
use value::ValueObj::{Inf, NegInf};
|
||||
pub use vis::*;
|
||||
|
||||
use self::constructors::subr_t;
|
||||
use self::constructors::{proj_call, subr_t};
|
||||
|
||||
pub const STR_OMIT_THRESHOLD: usize = 16;
|
||||
pub const CONTAINER_OMIT_THRESHOLD: usize = 8;
|
||||
|
@ -2904,7 +2904,7 @@ impl Type {
|
|||
other => other.clone(),
|
||||
})
|
||||
.collect();
|
||||
lhs.proj_call(attr_name.clone(), args)
|
||||
proj_call(lhs, attr_name.clone(), args)
|
||||
}
|
||||
Self::Structural(ty) => ty.derefine().structuralize(),
|
||||
Self::Guard(guard) => {
|
||||
|
@ -3043,7 +3043,7 @@ impl Type {
|
|||
args,
|
||||
} => {
|
||||
let args = args.into_iter().map(|tp| tp.replace(target, to)).collect();
|
||||
lhs.replace(target, to).proj_call(attr_name, args)
|
||||
proj_call(lhs.replace(target, to), attr_name, args)
|
||||
}
|
||||
Self::Structural(ty) => ty._replace(target, to).structuralize(),
|
||||
Self::Guard(guard) => Self::Guard(GuardType::new(
|
||||
|
@ -3086,7 +3086,7 @@ impl Type {
|
|||
args,
|
||||
} => {
|
||||
let args = args.into_iter().map(|tp| tp.normalize()).collect();
|
||||
lhs.normalize().proj_call(attr_name, args)
|
||||
proj_call(lhs.normalize(), attr_name, args)
|
||||
}
|
||||
Self::Ref(t) => Self::Ref(Box::new(t.normalize())),
|
||||
Self::RefMut { before, after } => Self::RefMut {
|
||||
|
|
|
@ -214,6 +214,11 @@ pub enum TyParam {
|
|||
obj: Box<TyParam>,
|
||||
attr: Str,
|
||||
},
|
||||
ProjCall {
|
||||
obj: Box<TyParam>,
|
||||
attr: Str,
|
||||
args: Vec<TyParam>,
|
||||
},
|
||||
App {
|
||||
name: Str,
|
||||
args: Vec<TyParam>,
|
||||
|
@ -343,6 +348,20 @@ impl LimitedDisplay for TyParam {
|
|||
write!(f, ".")?;
|
||||
write!(f, "{attr}")
|
||||
}
|
||||
Self::ProjCall { obj, attr, args } => {
|
||||
obj.limited_fmt(f, limit - 1)?;
|
||||
write!(f, ".")?;
|
||||
write!(f, "{attr}")?;
|
||||
write!(f, "(")?;
|
||||
for (i, arg) in args.iter().enumerate() {
|
||||
if i > 0 {
|
||||
write!(f, ", ")?;
|
||||
}
|
||||
arg.limited_fmt(f, limit - 1)?;
|
||||
}
|
||||
write!(f, ")")?;
|
||||
Ok(())
|
||||
}
|
||||
Self::Array(arr) => {
|
||||
write!(f, "[")?;
|
||||
for (i, t) in arr.iter().enumerate() {
|
||||
|
@ -657,6 +676,17 @@ impl<'a> TryFrom<&'a TyParam> for &'a Type {
|
|||
}
|
||||
}
|
||||
|
||||
impl TryFrom<&TyParam> for usize {
|
||||
type Error = ();
|
||||
fn try_from(tp: &TyParam) -> Result<Self, ()> {
|
||||
match tp {
|
||||
TyParam::FreeVar(fv) if fv.is_linked() => usize::try_from(&*fv.crack()),
|
||||
TyParam::Value(v) => usize::try_from(v),
|
||||
_ => Err(()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl HasLevel for TyParam {
|
||||
fn level(&self) -> Option<Level> {
|
||||
match self {
|
||||
|
@ -839,10 +869,10 @@ impl TyParam {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn proj_call(self, attr_name: Str, args: Vec<TyParam>) -> Type {
|
||||
Type::ProjCall {
|
||||
lhs: Box::new(self),
|
||||
attr_name,
|
||||
pub fn proj_call(self, attr: Str, args: Vec<TyParam>) -> Self {
|
||||
Self::ProjCall {
|
||||
obj: Box::new(self),
|
||||
attr,
|
||||
args,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -832,6 +832,19 @@ impl TryFrom<&ValueObj> for f64 {
|
|||
}
|
||||
}
|
||||
|
||||
impl TryFrom<&ValueObj> for usize {
|
||||
type Error = ();
|
||||
fn try_from(val: &ValueObj) -> Result<usize, Self::Error> {
|
||||
match val {
|
||||
ValueObj::Int(i) => usize::try_from(*i).map_err(|_| ()),
|
||||
ValueObj::Nat(n) => usize::try_from(*n).map_err(|_| ()),
|
||||
ValueObj::Float(f) => Ok(*f as usize),
|
||||
ValueObj::Bool(b) => Ok(if *b { 1 } else { 0 }),
|
||||
_ => Err(()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> TryFrom<&'a ValueObj> for &'a Type {
|
||||
type Error = ();
|
||||
fn try_from(val: &'a ValueObj) -> Result<Self, ()> {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue