feat: add SubrType::kw_var_params

This commit is contained in:
Shunsuke Shibayama 2023-11-12 12:22:48 +09:00
parent a3c267da37
commit 4407999c19
19 changed files with 388 additions and 149 deletions

View file

@ -941,6 +941,24 @@ impl Context {
}
}
}
let kw_var_params = if let Some(p) = lambda.sig.params.kw_var_params.as_ref() {
match self.instantiate_param_ty(
p,
None,
&mut tmp_tv_cache,
RegistrationMode::Normal,
ParamKind::KwVarParams,
false,
) {
Ok(pt) => Some(pt),
Err((pt, err)) => {
errs.extend(err);
Some(pt)
}
}
} else {
None
};
// HACK: should avoid cloning
let mut lambda_ctx = Context::instant(
Str::ever("<lambda>"),
@ -955,6 +973,7 @@ impl Context {
non_default_params.clone(),
var_params,
default_params.clone(),
kw_var_params,
return_t,
);
let block =
@ -1600,12 +1619,20 @@ impl Context {
Err((_, errs)) => return Err((Subr(subr), errs)),
};
}
if let Some(kw_var_args) = subr.kw_var_params.as_mut() {
*kw_var_args.typ_mut() =
match self.eval_t_params(mem::take(kw_var_args.typ_mut()), level, t_loc) {
Ok(t) => t,
Err((_, errs)) => return Err((Subr(subr), errs)),
};
}
match self.eval_t_params(*subr.return_t, level, t_loc) {
Ok(return_t) => Ok(subr_t(
subr.kind,
subr.non_default_params,
subr.var_params.map(|v| *v),
subr.default_params,
subr.kw_var_params.map(|v| *v),
return_t,
)),
Err((_, errs)) => {
@ -1614,6 +1641,7 @@ impl Context {
subr.non_default_params,
subr.var_params.map(|v| *v),
subr.default_params,
subr.kw_var_params.map(|v| *v),
Failure,
);
Err((subr, errs))

View file

@ -99,6 +99,9 @@ impl Generalizer {
.into_iter()
.map(|pt| pt.map_type(|t| self.generalize_t(t, uninit)))
.collect::<Vec<_>>();
let kw_var_params = lambda
.kw_var_params
.map(|pt| pt.map_type(|t| self.generalize_t(t, uninit)));
let body = lambda
.body
.into_iter()
@ -109,6 +112,7 @@ impl Generalizer {
nd_params,
var_params,
d_params,
kw_var_params,
body,
))
}
@ -213,6 +217,7 @@ impl Generalizer {
subr.non_default_params,
subr.var_params.map(|x| *x),
subr.default_params,
subr.kw_var_params.map(|x| *x),
return_t,
)
}
@ -496,6 +501,10 @@ impl<'c, 'q, 'l, L: Locational> Dereferencer<'c, 'q, 'l, L> {
.into_iter()
.map(|pt| pt.try_map_type(|t| self.deref_tyvar(t)))
.collect::<TyCheckResult<_>>()?;
let kw_var_params = lambda
.kw_var_params
.map(|pt| pt.try_map_type(|t| self.deref_tyvar(t)))
.transpose()?;
let body = lambda
.body
.into_iter()
@ -506,6 +515,7 @@ impl<'c, 'q, 'l, L: Locational> Dereferencer<'c, 'q, 'l, L> {
nd_params,
var_params,
d_params,
kw_var_params,
body,
)))
}

View file

@ -90,12 +90,7 @@ impl Context {
Visibility::BUILTIN_PUBLIC,
Some(FUNC_CONJUGATE),
);
let t = func(
vec![],
None,
vec![kw(REAL, Float), kw(IMAG, Float)],
Complex,
);
let t = no_var_func(vec![], vec![kw(REAL, Float), kw(IMAG, Float)], Complex);
complex.register_builtin_py_impl(
FUNDAMENTAL_CALL,
t,
@ -153,6 +148,7 @@ impl Context {
vec![kw(KW_OTHER, Float)],
None,
vec![kw(KW_EPSILON, Float)],
None,
Bool,
);
float.register_builtin_erg_impl(
@ -442,7 +438,7 @@ impl Context {
38,
);
int.register_py_builtin(FUNC_BIT_COUNT, fn0_met(Int, Nat), Some(FUNC_BIT_COUNT), 27);
let t_from_bytes = func(
let t_from_bytes = no_var_func(
vec![kw(
BYTES,
or(
@ -450,7 +446,6 @@ impl Context {
array_t(Type::from(value(0)..=value(255)), TyParam::erased(Nat)),
),
)],
None,
vec![kw(
FUNC_BYTEORDER,
v_enum(
@ -460,9 +455,8 @@ impl Context {
Int,
);
int.register_py_builtin(FUNC_FROM_BYTES, t_from_bytes, Some(FUNC_FROM_BYTES), 40);
let t_to_bytes = func(
let t_to_bytes = no_var_func(
vec![kw(KW_SELF, Int)],
None,
vec![
kw(KW_LENGTH, Nat),
kw(
@ -475,7 +469,7 @@ impl Context {
mono(BYTES),
);
int.register_py_builtin(FUNC_TO_BYTES, t_to_bytes, Some(FUNC_TO_BYTES), 55);
let t_call = func(vec![pos(Obj)], None, vec![kw("base", Nat)], Int);
let t_call = no_var_func(vec![pos(Obj)], vec![kw("base", Nat)], Int);
int.register_builtin_erg_impl(
FUNDAMENTAL_CALL,
t_call,
@ -614,7 +608,7 @@ impl Context {
Some(FUNC_TIMES),
13,
);
let t_call = func(vec![pos(Obj)], None, vec![kw("base", Nat)], Nat);
let t_call = no_var_func(vec![pos(Obj)], vec![kw("base", Nat)], Nat);
nat.register_builtin_erg_impl(
FUNDAMENTAL_CALL,
t_call,
@ -763,6 +757,7 @@ impl Context {
vec![kw(KW_PAT, Str), kw(KW_INTO, Str)],
None,
vec![],
None,
Str,
),
Immutable,
@ -775,6 +770,7 @@ impl Context {
vec![],
None,
vec![kw(KW_ENCODING, Str), kw(KW_ERRORS, Str)],
None,
mono(BYTES),
),
Some(FUNC_ENCODE),
@ -782,25 +778,25 @@ impl Context {
);
str_.register_builtin_erg_impl(
FUNC_FORMAT,
fn_met(Str, vec![], Some(kw(KW_ARGS, Obj)), vec![], Str),
fn_met(Str, vec![], Some(kw(KW_ARGS, Obj)), vec![], None, Str),
Immutable,
Visibility::BUILTIN_PUBLIC,
);
str_.register_builtin_erg_impl(
FUNC_LOWER,
fn_met(Str, vec![], None, vec![], Str),
fn_met(Str, vec![], None, vec![], None, Str),
Immutable,
Visibility::BUILTIN_PUBLIC,
);
str_.register_builtin_erg_impl(
FUNC_UPPER,
fn_met(Str, vec![], None, vec![], Str),
fn_met(Str, vec![], None, vec![], None, Str),
Immutable,
Visibility::BUILTIN_PUBLIC,
);
str_.register_builtin_erg_impl(
FUNC_TO_INT,
fn_met(Str, vec![], None, vec![], or(Int, NoneType)),
fn_met(Str, vec![], None, vec![], None, or(Int, NoneType)),
Immutable,
Visibility::BUILTIN_PUBLIC,
);
@ -824,6 +820,7 @@ impl Context {
vec![kw(KW_SEP, Str)],
None,
vec![kw(KW_MAXSPLIT, Nat)],
None,
unknown_len_array_t(Str),
),
Immutable,
@ -837,6 +834,7 @@ impl Context {
vec![],
None,
vec![kw(KW_KEEPENDS, Bool)],
None,
unknown_len_array_t(Str),
),
Immutable,
@ -857,6 +855,7 @@ impl Context {
vec![kw(KW_SUB, Str)],
None,
vec![kw(KW_START, Nat), kw(KW_END, Nat)],
None,
or(Nat, Never),
),
Some(FUNC_INDEX),
@ -869,6 +868,7 @@ impl Context {
vec![kw(KW_SUB, Str)],
None,
vec![kw(KW_START, Nat), kw(KW_END, Nat)],
None,
or(Nat, Never),
),
Immutable,
@ -882,6 +882,7 @@ impl Context {
vec![kw(KW_SUB, Str)],
None,
vec![kw(KW_START, Nat), kw(KW_END, Nat)],
None,
or(Nat, v_enum(set! {(-1).into()})),
),
Some(FUNC_FIND),
@ -894,6 +895,7 @@ impl Context {
vec![kw(KW_SUB, Str)],
None,
vec![kw(KW_START, Nat), kw(KW_END, Nat)],
None,
or(Nat, v_enum(set! {(-1).into()})),
),
Immutable,
@ -907,6 +909,7 @@ impl Context {
vec![kw(KW_SUB, Str)],
None,
vec![kw(KW_START, Nat), kw(KW_END, Nat)],
None,
Nat,
),
Some(FUNC_COUNT),
@ -926,7 +929,14 @@ impl Context {
);
str_.register_builtin_py_impl(
FUNC_STRIP,
fn_met(Str, vec![], None, vec![kw(KW_CHARS, Str | NoneType)], Str),
fn_met(
Str,
vec![],
None,
vec![kw(KW_CHARS, Str | NoneType)],
None,
Str,
),
Immutable,
Visibility::BUILTIN_PUBLIC,
Some(FUNC_STRIP),
@ -1038,7 +1048,7 @@ impl Context {
);
str_.register_marker_trait(self, poly(INDEXABLE, vec![ty_tp(Nat), ty_tp(Str)]))
.unwrap();
let t_call = func(vec![], None, vec![kw("object", Obj)], Str);
let t_call = func(vec![], None, vec![kw("object", Obj)], None, Str);
str_.register_builtin_erg_impl(
FUNDAMENTAL_CALL,
t_call,
@ -1415,22 +1425,20 @@ impl Context {
.register_marker_trait(self, poly(OUTPUT, vec![ty_tp(T.clone())]))
.unwrap();
let arr_t = array_t(T.clone(), N.clone());
let t = fn_met(
let t = no_var_fn_met(
arr_t.clone(),
vec![kw(KW_RHS, array_t(T.clone(), M.clone()))],
None,
vec![],
array_t(T.clone(), N.clone() + M.clone()),
)
.quantify();
array_.register_py_builtin(FUNC_CONCAT, t.clone(), Some(OP_ADD), 9);
let t_count =
fn_met(arr_t.clone(), vec![kw(KW_X, T.clone())], None, vec![], Nat).quantify();
no_var_fn_met(arr_t.clone(), vec![kw(KW_X, T.clone())], vec![], Nat).quantify();
array_.register_py_builtin(FUNC_COUNT, t_count, Some(FUNC_COUNT), 17);
let t_get = fn_met(
let t_get = no_var_fn_met(
arr_t.clone(),
vec![pos(Nat)],
None,
vec![ParamTy::kw_default(KW_DEFAULT.into(), U.clone(), NoneType)],
or(T.clone(), U.clone()),
)
@ -1451,10 +1459,9 @@ impl Context {
ValueObj::builtin_class(out_t),
);
array_.register_trait(arr_t.clone(), array_add);
let t = fn_met(
let t = no_var_fn_met(
arr_t.clone(),
vec![kw(KW_ELEM, T.clone())],
None,
vec![],
array_t(T.clone(), N.clone() + value(1usize)),
)
@ -1587,10 +1594,9 @@ impl Context {
]),
);
array_.register_py_builtin(FUNC_PARTITION, t.quantify(), Some(FUNC_PARTITION), 37);
let t = fn_met(
let t = no_var_fn_met(
array_t(T.clone(), TyParam::erased(Nat)),
vec![],
None,
vec![kw(
"same_bucket",
or(func2(T.clone(), T.clone(), Bool), NoneType),
@ -1633,10 +1639,9 @@ impl Context {
set_.register_superclass(mono(GENERIC_SET), &generic_set);
set_.register_marker_trait(self, poly(OUTPUT, vec![ty_tp(T.clone())]))
.unwrap();
let t = fn_met(
let t = no_var_fn_met(
set_t.clone(),
vec![kw(KW_RHS, set_t.clone())],
None,
vec![],
set_t.clone(),
)
@ -1833,10 +1838,9 @@ impl Context {
)));
dict_.register_builtin_const(FUNC_AS_RECORD, Visibility::BUILTIN_PUBLIC, as_record);
let Def = type_q("Default");
let get_t = fn_met(
let get_t = no_var_fn_met(
dict_t.clone(),
vec![kw("key", T.clone())],
None,
vec![kw_default("default", Def.clone(), NoneType)],
or(
proj_call(D.clone(), FUNDAMENTAL_GETITEM, vec![ty_tp(T.clone())]),
@ -2261,7 +2265,7 @@ impl Context {
Visibility::BUILTIN_PUBLIC,
ValueObj::builtin_class(Obj),
);
let f_t = kw(KW_FUNC, func(vec![kw(KW_OLD, Int)], None, vec![], Int));
let f_t = kw(KW_FUNC, no_var_func(vec![kw(KW_OLD, Int)], vec![], Int));
let t = pr_met(
ref_mut(mono(MUTABLE_OBJ), None),
vec![f_t],
@ -2285,7 +2289,7 @@ impl Context {
Visibility::BUILTIN_PUBLIC,
ValueObj::builtin_class(Float),
);
let f_t = kw(KW_FUNC, func(vec![kw(KW_OLD, Float)], None, vec![], Float));
let f_t = kw(KW_FUNC, no_var_func(vec![kw(KW_OLD, Float)], vec![], Float));
let t = pr_met(
ref_mut(mono(MUT_FLOAT), None),
vec![f_t],
@ -2310,7 +2314,7 @@ impl Context {
Visibility::BUILTIN_PUBLIC,
ValueObj::builtin_class(Ratio),
);
let f_t = kw(KW_FUNC, func(vec![kw(KW_OLD, Ratio)], None, vec![], Ratio));
let f_t = kw(KW_FUNC, no_var_func(vec![kw(KW_OLD, Ratio)], vec![], Ratio));
let t = pr_met(
ref_mut(mono(MUT_RATIO), None),
vec![f_t],
@ -2351,7 +2355,7 @@ impl Context {
Visibility::BUILTIN_PUBLIC,
ValueObj::builtin_class(Int),
);
let f_t = kw(KW_FUNC, func(vec![kw(KW_OLD, Int)], None, vec![], Int));
let f_t = kw(KW_FUNC, no_var_func(vec![kw(KW_OLD, Int)], vec![], Int));
let t = pr_met(
ref_mut(mono(MUT_INT), None),
vec![f_t],
@ -2377,7 +2381,7 @@ impl Context {
Visibility::BUILTIN_PUBLIC,
ValueObj::builtin_class(Nat),
);
let f_t = kw(KW_FUNC, func(vec![kw(KW_OLD, Nat)], None, vec![], Nat));
let f_t = kw(KW_FUNC, no_var_func(vec![kw(KW_OLD, Nat)], vec![], Nat));
let t = pr_met(
ref_mut(mono(MUT_NAT), None),
vec![f_t],
@ -2403,7 +2407,7 @@ impl Context {
Visibility::BUILTIN_PUBLIC,
ValueObj::builtin_class(Bool),
);
let f_t = kw(KW_FUNC, func(vec![kw(KW_OLD, Bool)], None, vec![], Bool));
let f_t = kw(KW_FUNC, no_var_func(vec![kw(KW_OLD, Bool)], vec![], Bool));
let t = pr_met(
ref_mut(mono(MUT_BOOL), None),
vec![f_t],
@ -2436,7 +2440,7 @@ impl Context {
Visibility::BUILTIN_PUBLIC,
ValueObj::builtin_class(Str),
);
let f_t = kw(KW_FUNC, func(vec![kw(KW_OLD, Str)], None, vec![], Str));
let f_t = kw(KW_FUNC, no_var_func(vec![kw(KW_OLD, Str)], vec![], Str));
let t = pr_met(
ref_mut(mono(MUT_STR), None),
vec![f_t],
@ -2642,7 +2646,7 @@ impl Context {
None,
vec![kw(
KW_KEY,
func(vec![kw(KW_X, T.clone())], None, vec![], mono(ORD)),
no_var_func(vec![kw(KW_X, T.clone())], vec![], mono(ORD)),
)],
NoneType,
)
@ -2670,7 +2674,7 @@ impl Context {
array_mut_.register_py_builtin(PROC_UPDATE_NTH, t_update_nth, Some(FUNC_UPDATE_NTH), 105);
let f_t = kw(
KW_FUNC,
func(vec![kw(KW_OLD, arr_t.clone())], None, vec![], arr_t.clone()),
no_var_func(vec![kw(KW_OLD, arr_t.clone())], vec![], arr_t.clone()),
);
let t = pr_met(
ref_mut(array_mut_t.clone(), None),
@ -2885,7 +2889,7 @@ impl Context {
);
let f_t = kw(
KW_FUNC,
func(vec![kw(KW_OLD, set_t.clone())], None, vec![], set_t.clone()),
no_var_func(vec![kw(KW_OLD, set_t.clone())], vec![], set_t.clone()),
);
let t = pr_met(
ref_mut(set_mut_t.clone(), None),

View file

@ -24,37 +24,28 @@ impl Context {
let U = mono_q(TY_U, instanceof(Type));
let Path = mono_q_tp(PATH, instanceof(Str));
let t_abs = nd_func(vec![kw(KW_N, mono(NUM))], None, Nat);
let t_all = func(
let t_all = no_var_func(
vec![kw(KW_ITERABLE, poly(ITERABLE, vec![ty_tp(Bool)]))],
None,
vec![],
Bool,
);
let t_any = func(
let t_any = no_var_func(
vec![kw(KW_ITERABLE, poly(ITERABLE, vec![ty_tp(Bool)]))],
None,
vec![],
Bool,
);
let t_ascii = nd_func(vec![kw(KW_OBJECT, Obj)], None, Str);
let t_array = func(
let t_array = no_var_func(
vec![],
None,
vec![kw(KW_ITERABLE, poly(ITERABLE, vec![ty_tp(T.clone())]))],
array_t(T.clone(), TyParam::erased(Nat)),
)
.quantify();
let t_assert = func(
vec![kw(KW_TEST, Bool)],
None,
vec![kw(KW_MSG, Str)],
NoneType,
);
let t_assert = no_var_func(vec![kw(KW_TEST, Bool)], vec![kw(KW_MSG, Str)], NoneType);
let t_bin = nd_func(vec![kw(KW_N, Int)], None, Str);
let t_bytes = func0(mono(BYTES))
& func(
& no_var_func(
vec![kw(KW_STR, Str), kw(KW_ENCODING, Str)],
None,
vec![kw(KW_ERRORS, Str)],
mono(BYTES),
)
@ -64,9 +55,8 @@ impl Context {
None,
mono(BYTES),
);
let t_bytes_array = func(
let t_bytes_array = no_var_func(
vec![],
None,
vec![kw(KW_ITERABLE, poly(ITERABLE, vec![ty_tp(Int)]))],
mono(BYTEARRAY),
);
@ -89,9 +79,8 @@ impl Context {
T.clone(),
)
.quantify();
let t_dict = func(
let t_dict = no_var_func(
vec![],
None,
vec![kw(
KW_ITERABLE,
poly(ITERABLE, vec![ty_tp(tuple_t(vec![T.clone(), U.clone()]))]),
@ -100,9 +89,8 @@ impl Context {
)
.quantify();
let t_discard = nd_func(vec![kw(KW_OBJ, Obj)], None, NoneType);
let t_enumerate = func(
let t_enumerate = no_var_func(
vec![kw(KW_ITERABLE, poly(ITERABLE, vec![ty_tp(T.clone())]))],
None,
vec![kw(KW_START, Int)],
poly(ENUMERATE, vec![ty_tp(T.clone())]),
)
@ -122,21 +110,19 @@ impl Context {
poly(FROZENSET, vec![ty_tp(T.clone())]),
)
.quantify();
let getattr_t = func(
let getattr_t = no_var_func(
vec![kw(KW_OBJ, Obj), kw(KW_NAME, Str)],
None,
vec![kw_default(KW_DEFAULT, T.clone(), Obj)],
T.clone(),
)
.quantify();
let hasattr_t = func(vec![kw(KW_OBJ, Obj), kw(KW_NAME, Str)], None, vec![], Bool);
let hasattr_t = no_var_func(vec![kw(KW_OBJ, Obj), kw(KW_NAME, Str)], vec![], Bool);
let t_hash = func1(mono(HASH), Int);
let t_if = func(
let t_if = no_var_func(
vec![
kw(KW_COND, Bool),
kw(KW_THEN, nd_func(vec![], None, T.clone())),
],
None,
vec![kw_default(
KW_ELSE,
nd_func(vec![], None, U.clone()),
@ -145,7 +131,7 @@ impl Context {
or(T.clone(), U.clone()),
)
.quantify();
let t_int = func(vec![kw(KW_OBJ, Obj)], None, vec![kw(KW_BASE, Nat)], Int);
let t_int = no_var_func(vec![kw(KW_OBJ, Obj)], vec![kw(KW_BASE, Nat)], Int);
let t_import = nd_func(
vec![anon(tp_enum(Str, set! {Path.clone()}))],
None,
@ -191,6 +177,7 @@ impl Context {
kw(KW_FILE, mono(WRITE)),
kw(KW_FLUSH, Bool),
],
None,
NoneType,
);
let t_map = nd_func(
@ -251,7 +238,7 @@ impl Context {
None,
Code,
);
let t_quit = func(vec![], None, vec![kw(KW_CODE, Int)], Never);
let t_quit = no_var_func(vec![], vec![kw(KW_CODE, Int)], Never);
let t_exit = t_quit.clone();
let t_repr = nd_func(vec![kw(KW_OBJECT, Obj)], None, Str);
let t_reversed = nd_func(
@ -261,16 +248,14 @@ impl Context {
)
.quantify();
let t_round = nd_func(vec![kw(KW_NUMBER, Float)], None, Int);
let t_set = func(
let t_set = no_var_func(
vec![],
None,
vec![kw(KW_ITERABLE, poly(ITERABLE, vec![ty_tp(T.clone())]))],
set_t(T.clone(), TyParam::erased(Nat)),
)
.quantify();
let t_slice = func(
let t_slice = no_var_func(
vec![kw(KW_START, Int)],
None,
vec![kw(KW_STOP, Int), kw(KW_STEP, Int)],
mono(SLICE),
);
@ -284,9 +269,8 @@ impl Context {
let t_str = nd_func(vec![kw(KW_OBJECT, Obj)], None, Str);
let A = mono_q(TY_A, Constraint::Uninited);
let A = mono_q(TY_A, subtypeof(poly(ADD, vec![ty_tp(A)])));
let t_sum = func(
let t_sum = no_var_func(
vec![kw(KW_ITERABLE, poly(ITERABLE, vec![ty_tp(A.clone())]))],
None,
vec![kw_default(KW_START, or(A.clone(), Int), Int)],
A,
)
@ -600,17 +584,15 @@ impl Context {
} else {
Visibility::BUILTIN_PRIVATE
};
let class_t = func(
let class_t = no_var_func(
vec![],
None,
vec![kw(KW_REQUIREMENT, or(Type, Ellipsis)), kw(KW_IMPL, Type)],
ClassType,
);
let class = ConstSubr::Builtin(BuiltinConstSubr::new(CLASS, class_func, class_t, None));
self.register_builtin_const(CLASS, vis.clone(), ValueObj::Subr(class));
let inherit_t = func(
let inherit_t = no_var_func(
vec![kw(KW_SUPER, ClassType)],
None,
vec![kw(KW_IMPL, Type), kw(KW_ADDITIONAL, Type)],
ClassType,
);
@ -621,17 +603,15 @@ impl Context {
None,
));
self.register_builtin_const(INHERIT, vis.clone(), ValueObj::Subr(inherit));
let trait_t = func(
let trait_t = no_var_func(
vec![kw(KW_REQUIREMENT, Type)],
None,
vec![kw(KW_IMPL, Type)],
TraitType,
);
let trait_ = ConstSubr::Builtin(BuiltinConstSubr::new(TRAIT, trait_func, trait_t, None));
self.register_builtin_const(TRAIT, vis.clone(), ValueObj::Subr(trait_));
let subsume_t = func(
let subsume_t = no_var_func(
vec![kw(KW_SUPER, TraitType)],
None,
vec![kw(KW_IMPL, Type), kw(KW_ADDITIONAL, Type)],
TraitType,
);
@ -670,9 +650,8 @@ impl Context {
// TODO: register Del function object
let t_del = nd_func(vec![kw(KW_OBJ, Obj)], None, NoneType);
self.register_builtin_erg_impl(DEL, t_del, Immutable, vis.clone());
let patch_t = func(
let patch_t = no_var_func(
vec![kw(KW_REQUIREMENT, Type)],
None,
vec![kw(KW_IMPL, Type)],
TraitType,
);
@ -681,9 +660,8 @@ impl Context {
}
pub(super) fn init_builtin_py_specific_funcs(&mut self) {
let setattr_t = func(
let setattr_t = no_var_func(
vec![kw(KW_OBJ, Obj), kw(KW_NAME, Str), kw(KW_VALUE, Obj)],
None,
vec![],
NoneType,
);
@ -694,12 +672,7 @@ impl Context {
Visibility::BUILTIN_PUBLIC,
None,
);
let delattr_t = func(
vec![kw(KW_OBJ, Obj), kw(KW_NAME, Str)],
None,
vec![],
NoneType,
);
let delattr_t = no_var_func(vec![kw(KW_OBJ, Obj), kw(KW_NAME, Str)], vec![], NoneType);
self.register_builtin_py_impl(
FUNC_DELATTR,
delattr_t,

View file

@ -902,9 +902,8 @@ impl Context {
.iter()
.filter_map(|ps| ps.has_default().then_some(ParamTy::from(ps)))
.collect::<Vec<_>>();
let meta_t = func(
let meta_t = no_var_func(
nd_params.clone(),
None,
d_params.clone(),
v_enum(set! { ret_val }),
)

View file

@ -20,9 +20,8 @@ impl Context {
};
let T = mono_q("T", instanceof(Type));
let U = mono_q("U", instanceof(Type));
let t_dir = proc(
let t_dir = no_var_proc(
vec![kw("obj", ref_(Obj))],
None,
vec![],
array_t(Str, TyParam::erased(Nat)),
);
@ -35,16 +34,16 @@ impl Context {
kw("file", mono("Writable!")),
kw("flush", Bool),
],
None,
NoneType,
);
let t_id = nd_func(vec![kw("old", Obj)], None, Nat);
let t_input = proc(vec![], None, vec![kw("msg", Str)], Str);
let t_if = proc(
let t_input = no_var_proc(vec![], vec![kw("msg", Str)], Str);
let t_if = no_var_proc(
vec![
kw("cond", Bool),
kw("then", nd_proc(vec![], None, T.clone())),
],
None,
vec![kw_default(
"else",
nd_proc(vec![], None, U.clone()),
@ -62,8 +61,8 @@ impl Context {
NoneType,
)
.quantify();
let t_globals = proc(vec![], None, vec![], dict! { Str => Obj }.into());
let t_locals = proc(vec![], None, vec![], dict! { Str => Obj }.into());
let t_globals = no_var_proc(vec![], vec![], dict! { Str => Obj }.into());
let t_locals = no_var_proc(vec![], vec![], dict! { Str => Obj }.into());
let t_next = nd_proc(
vec![kw(
"iterable",
@ -88,9 +87,8 @@ impl Context {
NoneType,
);
let P = mono_q("P", subtypeof(mono("PathLike")));
let t_open = proc(
let t_open = no_var_proc(
vec![kw("file", P)],
None,
vec![
kw("mode", Str),
kw("buffering", Int),

View file

@ -35,7 +35,7 @@ impl Context {
let mut mutable = Self::builtin_mono_trait(MUTABLE, 2);
let Slf = mono_q(SELF, subtypeof(mono(IMMUTIZABLE)));
let immut_t = proj(Slf.clone(), IMMUT_TYPE);
let f_t = func(vec![kw(KW_OLD, immut_t.clone())], None, vec![], immut_t);
let f_t = no_var_func(vec![kw(KW_OLD, immut_t.clone())], vec![], immut_t);
let t = pr1_met(ref_mut(Slf, None), f_t, NoneType).quantify();
mutable.register_builtin_erg_decl(PROC_UPDATE, t, Visibility::BUILTIN_PUBLIC);
// REVIEW: Immutatable?
@ -339,14 +339,13 @@ impl Context {
Visibility::BUILTIN_PUBLIC,
Some(FUNDAMENTAL_ENTER),
);
let t = fn_met(
let t = no_var_fn_met(
Slf,
vec![
kw(EXC_TYPE, ClassType),
kw(EXC_VALUE, Obj),
kw(TRACEBACK, Obj), // TODO:
],
None,
vec![],
NoneType,
)

View file

@ -519,9 +519,9 @@ impl Context {
let param_ty = ParamTy::Pos(match_target_expr_t.clone());
let param_ts = [vec![param_ty], branch_ts.to_vec()].concat();
let t = if kind.is_func() {
func(param_ts, None, vec![], return_t)
func(param_ts, None, vec![], None, return_t)
} else {
proc(param_ts, None, vec![], return_t)
proc(param_ts, None, vec![], None, return_t)
};
let vi = VarInfo {
t,
@ -985,6 +985,7 @@ impl Context {
vec![],
Some(ParamTy::Pos(ref_(Obj))),
vec![],
Some(ParamTy::Pos(ref_(Obj))),
Failure,
)),
..VarInfo::default()
@ -1019,6 +1020,7 @@ impl Context {
vec![],
Some(ParamTy::Pos(ref_(Obj))),
vec![],
Some(ParamTy::Pos(ref_(Obj))),
Failure,
)),
..VarInfo::default()
@ -1057,6 +1059,7 @@ impl Context {
.iter()
.map(|kw| ParamTy::kw(kw.keyword.content.clone(), kw.expr.t()))
.collect(),
None,
Obj,
);
for ty in intersecs.iter() {
@ -1130,7 +1133,7 @@ impl Context {
})
.collect::<Vec<_>>();
let return_t = free_var(self.level, Constraint::new_type_of(Type));
let subr_t = fn_met(obj.t(), nd_params, None, d_params, return_t);
let subr_t = fn_met(obj.t(), nd_params, None, d_params, None, return_t);
if let Some(fv) = obj.ref_t().as_free() {
if fv.get_sub().is_some() {
let vis = self.instantiate_vis_modifier(&attr_name.vis).unwrap();
@ -1669,7 +1672,7 @@ impl Context {
};
let ret_t = free_var(self.level, Constraint::new_type_of(Type));
let non_default_params = pos_args.iter().map(|a| anon(a.expr.t())).collect();
let subr_t = subr_t(kind, non_default_params, None, vec![], ret_t);
let subr_t = subr_t(kind, non_default_params, None, vec![], None, ret_t);
self.occur(&subr_t, instance, obj)?;
instance.destructive_link(&subr_t);
Ok(SubstituteResult::Ok)
@ -1704,7 +1707,7 @@ impl Context {
subr.non_default_params.len() + subr.default_params.len()
};
if (params_len < pos_args.len() || params_len < pos_args.len() + kw_args.len())
&& subr.var_params.is_none()
&& subr.is_no_var()
{
return Err(
self.gen_too_many_args_error(&callee, subr, is_method, pos_args, kw_args)
@ -2183,6 +2186,8 @@ impl Context {
.collect(),
)
})?;
} else if let Some(kw_var) = subr_ty.kw_var_params.as_deref() {
self.sub_unify(arg_t, kw_var.typ(), arg, Some(kw_name))?;
} else {
let similar =
levenshtein::get_similar_name(subr_ty.param_names(), arg.keyword.inspect());
@ -3360,8 +3365,9 @@ impl Context {
let subr = SubrType::new(
subr.kind,
subr.non_default_params.clone(),
subr.var_params.as_ref().map(|p| *p.clone()),
subr.var_params.as_deref().cloned(),
subr.default_params.clone(),
subr.kw_var_params.as_deref().cloned(),
ret_t,
);
Type::Subr(subr)

View file

@ -455,6 +455,10 @@ impl Context {
.into_iter()
.map(|pt| pt.try_map_type(|t| self.instantiate_t_inner(t, tmp_tv_cache, loc)))
.collect::<TyCheckResult<_>>()?;
let kw_var_params = lambda
.kw_var_params
.map(|pt| pt.try_map_type(|t| self.instantiate_t_inner(t, tmp_tv_cache, loc)))
.transpose()?;
let body = lambda
.body
.into_iter()
@ -465,6 +469,7 @@ impl Context {
nd_params,
var_params,
d_params,
kw_var_params,
body,
)))
}
@ -728,6 +733,7 @@ impl Context {
subr.non_default_params,
subr.var_params.map(|p| *p),
subr.default_params,
subr.kw_var_params.map(|p| *p),
return_t,
);
Ok(res)

View file

@ -65,15 +65,15 @@ pub enum ParamKind {
NonDefault,
Default(Type),
VarParams,
KwParams,
KwVarParams,
}
impl ParamKind {
pub const fn is_var_params(&self) -> bool {
matches!(self, ParamKind::VarParams)
}
pub const fn is_kw_params(&self) -> bool {
matches!(self, ParamKind::KwParams)
pub const fn is_kw_var_params(&self) -> bool {
matches!(self, ParamKind::KwVarParams)
}
pub const fn is_default(&self) -> bool {
matches!(self, ParamKind::Default(_))
@ -302,6 +302,28 @@ impl Context {
}
}
}
let kw_var_args = if let Some(kw_var_args) = sig.params.kw_var_params.as_ref() {
let opt_decl_t = opt_decl_sig_t
.as_ref()
.and_then(|subr| subr.kw_var_params.as_ref().map(|v| v.as_ref()));
let pt = match self.instantiate_param_ty(
kw_var_args,
opt_decl_t,
&mut tmp_tv_cache,
mode,
ParamKind::KwVarParams,
false,
) {
Ok(pt) => pt,
Err((pt, es)) => {
errs.extend(es);
pt
}
};
Some(pt)
} else {
None
};
let spec_return_t = if let Some(t_spec) = sig.return_t_spec.as_ref() {
let opt_decl_t = opt_decl_sig_t
.as_ref()
@ -330,9 +352,9 @@ impl Context {
};
// tmp_tv_cache.warn_isolated_vars(self);
let typ = if sig.ident.is_procedural() {
proc(non_defaults, var_args, defaults, spec_return_t)
proc(non_defaults, var_args, defaults, kw_var_args, spec_return_t)
} else {
func(non_defaults, var_args, defaults, spec_return_t)
func(non_defaults, var_args, defaults, kw_var_args, spec_return_t)
};
if errs.is_empty() {
Ok(typ)
@ -1117,6 +1139,21 @@ impl Context {
.map_err(|(_, errs)| errs)?;
d_params.push(pt);
}
let kw_var_params = if let Some(p) = lambda.sig.params.kw_var_params.as_ref() {
let pt = self
.instantiate_param_ty(
p,
None,
tmp_tv_cache,
RegistrationMode::Normal,
ParamKind::KwVarParams,
not_found_is_qvar,
)
.map_err(|(_, errs)| errs)?;
Some(pt)
} else {
None
};
let mut body = vec![];
for expr in lambda.body.iter() {
let param =
@ -1129,6 +1166,7 @@ impl Context {
nd_params,
var_params,
d_params,
kw_var_params,
body,
)))
}
@ -1274,6 +1312,7 @@ impl Context {
lambda.nd_params,
lambda.var_params,
lambda.d_params,
lambda.kw_var_params,
return_t,
);
Ok(Type::Subr(subr))
@ -1639,6 +1678,20 @@ impl Context {
})?
.into_iter()
.collect();
let kw_var_params = subr
.kw_var_params
.as_ref()
.map(|p| {
self.instantiate_func_param_spec(
p,
opt_decl_t,
None,
tmp_tv_ctx,
mode,
not_found_is_qvar,
)
})
.transpose()?;
let return_t = self.instantiate_typespec_full(
&subr.return_t,
opt_decl_t,
@ -1652,6 +1705,7 @@ impl Context {
non_defaults,
var_params,
defaults,
kw_var_params,
return_t,
))
}

View file

@ -20,7 +20,8 @@ use ast::{
use erg_parser::ast::{self, ClassAttr, TypeSpecWithOp};
use crate::ty::constructors::{
free_var, func, func0, func1, proc, ref_, ref_mut, tp_enum, unknown_len_array_t, v_enum,
free_var, func, func0, func1, proc, ref_, ref_mut, str_dict_t, tp_enum, unknown_len_array_t,
v_enum,
};
use crate::ty::free::{Constraint, HasLevel};
use crate::ty::typaram::TyParam;
@ -332,7 +333,7 @@ impl Context {
Visibility::private(self.name.clone())
};
let default = kind.default_info();
let is_var_params = kind.is_var_params();
let is_var_params = kind.is_var_params() || kind.is_kw_var_params();
match &sig.raw.pat {
// Literal patterns will be desugared to discard patterns
ast::ParamPattern::Lit(_) => unreachable!(),
@ -606,6 +607,20 @@ impl Context {
errs.extend(es);
}
}
if let Some(kw_var_params) = &mut params.kw_var_params {
if let Some(pt) = &subr_t.var_params {
let pt = pt.clone().map_type(str_dict_t);
if let Err(es) =
self.assign_param(kw_var_params, Some(&pt), ParamKind::KwVarParams)
{
errs.extend(es);
}
} else if let Err(es) =
self.assign_param(kw_var_params, None, ParamKind::KwVarParams)
{
errs.extend(es);
}
}
} else {
for non_default in params.non_defaults.iter_mut() {
if let Err(es) = self.assign_param(non_default, None, ParamKind::NonDefault) {
@ -626,6 +641,11 @@ impl Context {
errs.extend(es);
}
}
if let Some(kw_var_params) = &mut params.kw_var_params {
if let Err(es) = self.assign_param(kw_var_params, None, ParamKind::KwVarParams) {
errs.extend(es);
}
}
}
if errs.is_empty() {
Ok(())
@ -765,6 +785,7 @@ impl Context {
subr_t.non_default_params.clone(),
subr_t.var_params.as_deref().cloned(),
subr_t.default_params.clone(),
subr_t.kw_var_params.as_deref().cloned(),
return_t,
)
} else {
@ -772,6 +793,7 @@ impl Context {
subr_t.non_default_params.clone(),
subr_t.var_params.as_deref().cloned(),
subr_t.default_params.clone(),
subr_t.kw_var_params.as_deref().cloned(),
return_t,
)
};
@ -1953,7 +1975,7 @@ impl Context {
))
})
.collect();
let meta_t = func(params, None, vec![], v_enum(set! { val.clone() })).quantify();
let meta_t = func(params, None, vec![], None, v_enum(set! { val.clone() })).quantify();
let name = &ident.name;
let id = DefId(get_hash(&(&self.name, &name)));
let vi = VarInfo::new(