Add user-defined var-params function

This commit is contained in:
Shunsuke Shibayama 2023-01-26 01:20:35 +09:00
parent 4b08fd21a2
commit 23a7e2caf3
28 changed files with 526 additions and 211 deletions

View file

@ -27,6 +27,7 @@ use crate::ty::typaram::{OpKind, TyParam};
use crate::ty::value::{GenTypeObj, TypeObj, ValueObj};
use crate::ty::{ConstSubr, HasType, Predicate, SubrKind, Type, UserConstSubr, ValueArgs};
use crate::context::instantiate::ParamKind;
use crate::context::{ClassDefType, Context, ContextKind, RegistrationMode};
use crate::error::{EvalError, EvalErrors, EvalResult, SingleEvalResult};
@ -451,19 +452,19 @@ impl Context {
let pt = self.instantiate_param_ty(
sig,
None,
None,
&mut tmp_tv_cache,
RegistrationMode::Normal,
ParamKind::NonDefault,
)?;
non_default_params.push(pt);
}
let var_params = if let Some(p) = lambda.sig.params.var_args.as_ref() {
let var_params = if let Some(p) = lambda.sig.params.var_params.as_ref() {
let pt = self.instantiate_param_ty(
p,
None,
None,
&mut tmp_tv_cache,
RegistrationMode::Normal,
ParamKind::VarParams,
)?;
Some(pt)
} else {
@ -474,10 +475,10 @@ impl Context {
let expr = self.eval_const_expr(&sig.default_val)?;
let pt = self.instantiate_param_ty(
&sig.sig,
Some(expr.t()),
None,
&mut tmp_tv_cache,
RegistrationMode::Normal,
ParamKind::Default(expr.t()),
)?;
default_params.push(pt);
}

View file

@ -37,6 +37,7 @@ use crate::{feature_error, hir};
use RegistrationMode::*;
use Visibility::*;
use super::instantiate::ParamKind;
use super::{ContextKind, MethodInfo};
impl Context {
@ -274,6 +275,7 @@ impl Context {
None,
&mut dummy_tv_cache,
Normal,
ParamKind::NonDefault,
)?;
union_pat_t = self.union(&union_pat_t, &rhs);
}

View file

@ -31,12 +31,38 @@ use crate::unreachable_error;
use TyParamOrdering::*;
use Type::*;
use crate::context::{Context, RegistrationMode};
use crate::context::{Context, DefaultInfo, RegistrationMode};
use crate::error::{TyCheckError, TyCheckErrors, TyCheckResult};
use crate::hir;
use crate::AccessKind;
use RegistrationMode::*;
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum ParamKind {
NonDefault,
Default(Type),
VarParams,
KwParams,
}
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_default(&self) -> bool {
matches!(self, ParamKind::Default(_))
}
pub const fn default_info(&self) -> DefaultInfo {
match self {
ParamKind::Default(_) => DefaultInfo::WithDefault,
_ => DefaultInfo::NonDefault,
}
}
}
/// Context for instantiating a quantified type
/// For example, cloning each type variable of quantified type `?T -> ?T` would result in `?1 -> ?2`.
/// To avoid this, an environment to store type variables is needed, which is `TyVarCache`.
@ -252,7 +278,13 @@ impl Context {
let opt_decl_t = opt_decl_sig_t
.as_ref()
.and_then(|subr| subr.non_default_params.get(n));
match self.instantiate_param_ty(param, None, opt_decl_t, &mut tmp_tv_cache, mode) {
match self.instantiate_param_ty(
param,
opt_decl_t,
&mut tmp_tv_cache,
mode,
ParamKind::NonDefault,
) {
Ok(t) => non_defaults.push(t),
Err(es) => {
errs.extend(es);
@ -260,16 +292,16 @@ impl Context {
}
}
}
let var_args = if let Some(var_args) = sig.params.var_args.as_ref() {
let var_args = if let Some(var_args) = sig.params.var_params.as_ref() {
let opt_decl_t = opt_decl_sig_t
.as_ref()
.and_then(|subr| subr.var_params.as_ref().map(|v| v.as_ref()));
let pt = match self.instantiate_param_ty(
var_args,
None,
opt_decl_t,
&mut tmp_tv_cache,
mode,
ParamKind::VarParams,
) {
Ok(pt) => pt,
Err(es) => {
@ -288,10 +320,10 @@ impl Context {
.and_then(|subr| subr.default_params.get(n));
match self.instantiate_param_ty(
&p.sig,
Some(default_t),
opt_decl_t,
&mut tmp_tv_cache,
mode,
ParamKind::Default(default_t),
) {
Ok(t) => defaults.push(t),
Err(es) => {
@ -345,6 +377,7 @@ impl Context {
opt_decl_t: Option<&ParamTy>,
tmp_tv_cache: &mut TyVarCache,
mode: RegistrationMode,
kind: ParamKind,
) -> TyCheckResult<Type> {
let spec_t = if let Some(spec_with_op) = &sig.t_spec {
self.instantiate_typespec(&spec_with_op.t_spec, opt_decl_t, tmp_tv_cache, mode, false)?
@ -365,15 +398,28 @@ impl Context {
}
};
if let Some(decl_pt) = opt_decl_t {
self.sub_unify(
decl_pt.typ(),
&spec_t,
sig.t_spec
.as_ref()
.map(|s| s.loc())
.unwrap_or_else(|| sig.loc()),
None,
)?;
if kind.is_var_params() {
let spec_t = unknown_len_array_t(spec_t.clone());
self.sub_unify(
decl_pt.typ(),
&spec_t,
sig.t_spec
.as_ref()
.map(|s| s.loc())
.unwrap_or_else(|| sig.loc()),
None,
)?;
} else {
self.sub_unify(
decl_pt.typ(),
&spec_t,
sig.t_spec
.as_ref()
.map(|s| s.loc())
.unwrap_or_else(|| sig.loc()),
None,
)?;
}
}
Ok(spec_t)
}
@ -381,17 +427,18 @@ impl Context {
pub(crate) fn instantiate_param_ty(
&self,
sig: &NonDefaultParamSignature,
opt_default_t: Option<Type>,
opt_decl_t: Option<&ParamTy>,
tmp_tv_cache: &mut TyVarCache,
mode: RegistrationMode,
kind: ParamKind,
) -> TyCheckResult<ParamTy> {
let t = self.instantiate_param_sig_t(sig, opt_decl_t, tmp_tv_cache, mode)?;
match (sig.inspect(), opt_default_t) {
(Some(name), Some(default_t)) => Ok(ParamTy::kw_default(name.clone(), t, default_t)),
(Some(name), None) => Ok(ParamTy::kw(name.clone(), t)),
(None, None) => Ok(ParamTy::anonymous(t)),
_ => unreachable!(),
let t = self.instantiate_param_sig_t(sig, opt_decl_t, tmp_tv_cache, mode, kind.clone())?;
match (sig.inspect(), kind) {
(Some(name), ParamKind::Default(default_t)) => {
Ok(ParamTy::kw_default(name.clone(), t, default_t))
}
(Some(name), _) => Ok(ParamTy::kw(name.clone(), t)),
(None, _) => Ok(ParamTy::anonymous(t)),
}
}
@ -919,8 +966,8 @@ impl Context {
let non_defaults = try_map_mut(subr.non_defaults.iter(), |p| {
self.instantiate_func_param_spec(p, opt_decl_t, None, tmp_tv_ctx, mode)
})?;
let var_args = subr
.var_args
let var_params = subr
.var_params
.as_ref()
.map(|p| {
self.instantiate_func_param_spec(p, opt_decl_t, None, tmp_tv_ctx, mode)
@ -947,7 +994,7 @@ impl Context {
Ok(subr_t(
SubrKind::from(subr.arrow.kind),
non_defaults,
var_args,
var_params,
defaults,
return_t,
))

View file

@ -17,7 +17,9 @@ use erg_common::{enum_unwrap, get_hash, log, set};
use ast::{Decorator, DefId, Identifier, OperationKind, SimpleTypeSpec, VarName};
use erg_parser::ast::{self, ConstIdentifier};
use crate::ty::constructors::{free_var, func, func0, func1, proc, ref_, ref_mut, v_enum};
use crate::ty::constructors::{
free_var, func, func0, func1, proc, ref_, ref_mut, unknown_len_array_t, v_enum,
};
use crate::ty::free::{Constraint, FreeKind, HasLevel};
use crate::ty::value::{GenTypeObj, TypeObj, ValueObj};
use crate::ty::{HasType, ParamTy, SubrType, Type};
@ -37,7 +39,7 @@ use Mutability::*;
use RegistrationMode::*;
use Visibility::*;
use super::instantiate::TyVarCache;
use super::instantiate::{ParamKind, TyVarCache};
const UBAR: &Str = &Str::ever("_");
@ -240,14 +242,15 @@ impl Context {
fn assign_param(
&mut self,
sig: &ast::NonDefaultParamSignature,
default_val_exists: bool,
opt_decl_t: Option<&ParamTy>,
kind: ParamKind,
) -> TyCheckResult<()> {
let vis = if cfg!(feature = "py_compatible") {
Public
} else {
Private
};
let default = kind.default_info();
match &sig.pat {
// Literal patterns will be desugared to discard patterns
ast::ParamPattern::Lit(_) => unreachable!(),
@ -257,6 +260,7 @@ impl Context {
opt_decl_t,
&mut TyVarCache::new(self.level, self),
Normal,
kind,
)?;
let def_id = DefId(get_hash(&(&self.name, "_")));
let kind = VarKind::parameter(def_id, DefaultInfo::NonDefault);
@ -288,8 +292,13 @@ impl Context {
} else {
// ok, not defined
let mut dummy_tv_cache = TyVarCache::new(self.level, self);
let spec_t =
self.instantiate_param_sig_t(sig, opt_decl_t, &mut dummy_tv_cache, Normal)?;
let spec_t = self.instantiate_param_sig_t(
sig,
opt_decl_t,
&mut dummy_tv_cache,
Normal,
kind,
)?;
if &name.inspect()[..] == "self" {
if let Some(self_t) = self.rec_get_self_t() {
self.sub_unify(&spec_t, &self_t, name.loc(), Some(name.inspect()))?;
@ -297,11 +306,6 @@ impl Context {
log!(err "self_t is None");
}
}
let default = if default_val_exists {
DefaultInfo::WithDefault
} else {
DefaultInfo::NonDefault
};
let def_id = DefId(get_hash(&(&self.name, name)));
let kind = VarKind::parameter(def_id, default);
let muty = Mutability::from(&name.inspect()[..]);
@ -334,8 +338,13 @@ impl Context {
} else {
// ok, not defined
let mut dummy_tv_cache = TyVarCache::new(self.level, self);
let spec_t =
self.instantiate_param_sig_t(sig, opt_decl_t, &mut dummy_tv_cache, Normal)?;
let spec_t = self.instantiate_param_sig_t(
sig,
opt_decl_t,
&mut dummy_tv_cache,
Normal,
kind,
)?;
if &name.inspect()[..] == "self" {
if let Some(self_t) = self.rec_get_self_t() {
self.sub_unify(&spec_t, &self_t, name.loc(), Some(name.inspect()))?;
@ -344,11 +353,6 @@ impl Context {
}
}
let spec_t = ref_(spec_t);
let default = if default_val_exists {
DefaultInfo::WithDefault
} else {
DefaultInfo::NonDefault
};
let kind = VarKind::parameter(DefId(get_hash(&(&self.name, name))), default);
let vi = VarInfo::new(
spec_t,
@ -379,8 +383,13 @@ impl Context {
} else {
// ok, not defined
let mut dummy_tv_cache = TyVarCache::new(self.level, self);
let spec_t =
self.instantiate_param_sig_t(sig, opt_decl_t, &mut dummy_tv_cache, Normal)?;
let spec_t = self.instantiate_param_sig_t(
sig,
opt_decl_t,
&mut dummy_tv_cache,
Normal,
kind,
)?;
if &name.inspect()[..] == "self" {
if let Some(self_t) = self.rec_get_self_t() {
self.sub_unify(&spec_t, &self_t, name.loc(), Some(name.inspect()))?;
@ -389,11 +398,6 @@ impl Context {
}
}
let spec_t = ref_mut(spec_t.clone(), Some(spec_t));
let default = if default_val_exists {
DefaultInfo::WithDefault
} else {
DefaultInfo::NonDefault
};
let kind = VarKind::parameter(DefId(get_hash(&(&self.name, name))), default);
let vi = VarInfo::new(
spec_t,
@ -433,7 +437,18 @@ impl Context {
.iter()
.zip(decl_subr_t.non_default_params.iter())
{
if let Err(es) = self.assign_param(sig, false, Some(pt)) {
if let Err(es) = self.assign_param(sig, Some(pt), ParamKind::NonDefault) {
errs.extend(es);
}
}
if let Some(var_params) = &params.var_params {
if let Some(pt) = &decl_subr_t.var_params {
let pt = pt.clone().map_type(unknown_len_array_t);
if let Err(es) = self.assign_param(var_params, Some(&pt), ParamKind::VarParams)
{
errs.extend(es);
}
} else if let Err(es) = self.assign_param(var_params, None, ParamKind::VarParams) {
errs.extend(es);
}
}
@ -442,18 +457,22 @@ impl Context {
.iter()
.zip(decl_subr_t.default_params.iter())
{
if let Err(es) = self.assign_param(&sig.sig, true, Some(pt)) {
if let Err(es) =
self.assign_param(&sig.sig, Some(pt), ParamKind::Default(sig.default_val.t()))
{
errs.extend(es);
}
}
} else {
for sig in params.non_defaults.iter() {
if let Err(es) = self.assign_param(sig, false, None) {
if let Err(es) = self.assign_param(sig, None, ParamKind::NonDefault) {
errs.extend(es);
}
}
for sig in params.defaults.iter() {
if let Err(es) = self.assign_param(&sig.sig, true, None) {
if let Err(es) =
self.assign_param(&sig.sig, None, ParamKind::Default(sig.default_val.t()))
{
errs.extend(es);
}
}