mirror of
https://github.com/erg-lang/erg.git
synced 2025-09-28 04:09:05 +00:00
feat: support var-args lambda function
This commit is contained in:
parent
cb00efca54
commit
3d310714f1
13 changed files with 123 additions and 47 deletions
|
@ -69,7 +69,10 @@ impl<Checker: BuildRunnable> Server<Checker> {
|
||||||
|
|
||||||
pub(crate) fn quick_check_file(&mut self, uri: Url) -> ELSResult<()> {
|
pub(crate) fn quick_check_file(&mut self, uri: Url) -> ELSResult<()> {
|
||||||
// send_log(format!("checking {uri}"))?;
|
// send_log(format!("checking {uri}"))?;
|
||||||
let mut parser = Parser::new(self.file_cache.get_token_stream(&uri).unwrap().clone());
|
let Some(ts) = self.file_cache.get_token_stream(&uri) else {
|
||||||
|
return Ok(());
|
||||||
|
};
|
||||||
|
let mut parser = Parser::new(ts.clone());
|
||||||
if parser.parse().is_err() {
|
if parser.parse().is_err() {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
|
@ -2782,7 +2782,7 @@ impl PyCodeGenerator {
|
||||||
let mut ident = Identifier::public_with_line(DOT, Str::ever("__init__"), line);
|
let mut ident = Identifier::public_with_line(DOT, Str::ever("__init__"), line);
|
||||||
ident.vi.t = __new__.clone();
|
ident.vi.t = __new__.clone();
|
||||||
let self_param = VarName::from_str_and_line(Str::ever("self"), line);
|
let self_param = VarName::from_str_and_line(Str::ever("self"), line);
|
||||||
let vi = VarInfo::parameter(
|
let vi = VarInfo::nd_parameter(
|
||||||
__new__.return_t().unwrap().clone(),
|
__new__.return_t().unwrap().clone(),
|
||||||
ident.vi.def_loc.clone(),
|
ident.vi.def_loc.clone(),
|
||||||
);
|
);
|
||||||
|
@ -2797,7 +2797,7 @@ impl PyCodeGenerator {
|
||||||
let param = VarName::from_str_and_line(Str::from(param_name.clone()), line);
|
let param = VarName::from_str_and_line(Str::from(param_name.clone()), line);
|
||||||
let raw =
|
let raw =
|
||||||
erg_parser::ast::NonDefaultParamSignature::new(ParamPattern::VarName(param), None);
|
erg_parser::ast::NonDefaultParamSignature::new(ParamPattern::VarName(param), None);
|
||||||
let vi = VarInfo::parameter(new_first_param.typ().clone(), ident.vi.def_loc.clone());
|
let vi = VarInfo::nd_parameter(new_first_param.typ().clone(), ident.vi.def_loc.clone());
|
||||||
let param = NonDefaultParamSignature::new(raw, vi, None);
|
let param = NonDefaultParamSignature::new(raw, vi, None);
|
||||||
let params = Params::new(vec![self_param, param], None, vec![], None);
|
let params = Params::new(vec![self_param, param], None, vec![], None);
|
||||||
(param_name, params)
|
(param_name, params)
|
||||||
|
@ -2876,7 +2876,7 @@ impl PyCodeGenerator {
|
||||||
.map(|s| s.to_string())
|
.map(|s| s.to_string())
|
||||||
.unwrap_or_else(fresh_varname);
|
.unwrap_or_else(fresh_varname);
|
||||||
let param = VarName::from_str_and_line(Str::from(param_name.clone()), line);
|
let param = VarName::from_str_and_line(Str::from(param_name.clone()), line);
|
||||||
let vi = VarInfo::parameter(new_first_param.typ().clone(), ident.vi.def_loc.clone());
|
let vi = VarInfo::nd_parameter(new_first_param.typ().clone(), ident.vi.def_loc.clone());
|
||||||
let raw =
|
let raw =
|
||||||
erg_parser::ast::NonDefaultParamSignature::new(ParamPattern::VarName(param), None);
|
erg_parser::ast::NonDefaultParamSignature::new(ParamPattern::VarName(param), None);
|
||||||
let param = NonDefaultParamSignature::new(raw, vi, None);
|
let param = NonDefaultParamSignature::new(raw, vi, None);
|
||||||
|
|
|
@ -672,6 +672,9 @@ impl Context {
|
||||||
(Structural(l), Structural(r)) => self.structural_supertype_of(l, r),
|
(Structural(l), Structural(r)) => self.structural_supertype_of(l, r),
|
||||||
// TODO: If visibility does not match, it should be reported as a cause of an error
|
// TODO: If visibility does not match, it should be reported as a cause of an error
|
||||||
(Structural(l), r) => {
|
(Structural(l), r) => {
|
||||||
|
if self.supertype_of(l, r) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
let r_fields = self.fields(r);
|
let r_fields = self.fields(r);
|
||||||
for (l_field, l_ty) in self.fields(l) {
|
for (l_field, l_ty) in self.fields(l) {
|
||||||
if let Some((r_field, r_ty)) = r_fields.get_key_value(&l_field) {
|
if let Some((r_field, r_ty)) = r_fields.get_key_value(&l_field) {
|
||||||
|
|
|
@ -67,8 +67,8 @@ impl Context {
|
||||||
let t_show = fn0_met(ref_(Slf), Str).quantify();
|
let t_show = fn0_met(ref_(Slf), Str).quantify();
|
||||||
show.register_builtin_py_decl(TO_STR, t_show, Public, Some(FUNDAMENTAL_STR));
|
show.register_builtin_py_decl(TO_STR, t_show, Public, Some(FUNDAMENTAL_STR));
|
||||||
/* In */
|
/* In */
|
||||||
let mut in_ = Self::builtin_poly_trait(IN, vec![PS::t(TY_T, NonDefault)], 2);
|
let mut in_ = Self::builtin_poly_trait(IN, vec![PS::t_nd(TY_T)], 2);
|
||||||
let params = vec![PS::t(TY_T, NonDefault)];
|
let params = vec![PS::t_nd(TY_T)];
|
||||||
let input = Self::builtin_poly_trait(INPUT, params.clone(), 2);
|
let input = Self::builtin_poly_trait(INPUT, params.clone(), 2);
|
||||||
let output = Self::builtin_poly_trait(OUTPUT, params, 2);
|
let output = Self::builtin_poly_trait(OUTPUT, params, 2);
|
||||||
let T = mono_q(TY_T, instanceof(Type));
|
let T = mono_q(TY_T, instanceof(Type));
|
||||||
|
@ -100,7 +100,7 @@ impl Context {
|
||||||
poly(MUL, vec![]),
|
poly(MUL, vec![]),
|
||||||
], */
|
], */
|
||||||
/* Seq */
|
/* Seq */
|
||||||
let mut seq = Self::builtin_poly_trait(SEQ, vec![PS::t(TY_T, NonDefault)], 2);
|
let mut seq = Self::builtin_poly_trait(SEQ, vec![PS::t_nd(TY_T)], 2);
|
||||||
seq.register_superclass(poly(OUTPUT, vec![ty_tp(T.clone())]), &output);
|
seq.register_superclass(poly(OUTPUT, vec![ty_tp(T.clone())]), &output);
|
||||||
let Slf = mono_q(SELF, subtypeof(poly(SEQ, vec![TyParam::erased(Type)])));
|
let Slf = mono_q(SELF, subtypeof(poly(SEQ, vec![TyParam::erased(Type)])));
|
||||||
let t = fn0_met(Slf.clone(), Nat).quantify();
|
let t = fn0_met(Slf.clone(), Nat).quantify();
|
||||||
|
@ -109,14 +109,14 @@ impl Context {
|
||||||
// Seq.get: |Self <: Seq(T)| Self.(Nat) -> T
|
// Seq.get: |Self <: Seq(T)| Self.(Nat) -> T
|
||||||
seq.register_builtin_erg_decl(FUNC_GET, t, Public);
|
seq.register_builtin_erg_decl(FUNC_GET, t, Public);
|
||||||
/* Iterable */
|
/* Iterable */
|
||||||
let mut iterable = Self::builtin_poly_trait(ITERABLE, vec![PS::t(TY_T, NonDefault)], 2);
|
let mut iterable = Self::builtin_poly_trait(ITERABLE, vec![PS::t_nd(TY_T)], 2);
|
||||||
iterable.register_superclass(poly(OUTPUT, vec![ty_tp(T.clone())]), &output);
|
iterable.register_superclass(poly(OUTPUT, vec![ty_tp(T.clone())]), &output);
|
||||||
let Slf = mono_q(SELF, subtypeof(poly(ITERABLE, vec![ty_tp(T.clone())])));
|
let Slf = mono_q(SELF, subtypeof(poly(ITERABLE, vec![ty_tp(T.clone())])));
|
||||||
let t = fn0_met(Slf.clone(), proj(Slf, ITER)).quantify();
|
let t = fn0_met(Slf.clone(), proj(Slf, ITER)).quantify();
|
||||||
iterable.register_builtin_py_decl(FUNC_ITER, t, Public, Some(FUNDAMENTAL_ITER));
|
iterable.register_builtin_py_decl(FUNC_ITER, t, Public, Some(FUNDAMENTAL_ITER));
|
||||||
iterable.register_builtin_erg_decl(ITER, Type, Public);
|
iterable.register_builtin_erg_decl(ITER, Type, Public);
|
||||||
let R = mono_q(TY_R, instanceof(Type));
|
let R = mono_q(TY_R, instanceof(Type));
|
||||||
let params = vec![PS::t(TY_R, WithDefault)];
|
let params = vec![PS::t(TY_R, false, WithDefault)];
|
||||||
let ty_params = vec![ty_tp(R.clone())];
|
let ty_params = vec![ty_tp(R.clone())];
|
||||||
/* Num */
|
/* Num */
|
||||||
/* Add */
|
/* Add */
|
||||||
|
|
|
@ -97,7 +97,7 @@ impl ClassDefType {
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
pub enum DefaultInfo {
|
pub enum DefaultInfo {
|
||||||
NonDefault,
|
NonDefault, // var-args should be non-default
|
||||||
WithDefault,
|
WithDefault,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -141,6 +141,7 @@ pub struct ParamSpec {
|
||||||
pub(crate) name: Option<&'static str>,
|
pub(crate) name: Option<&'static str>,
|
||||||
// TODO: `:` or `<:`
|
// TODO: `:` or `<:`
|
||||||
pub(crate) t: Type,
|
pub(crate) t: Type,
|
||||||
|
pub is_var_params: bool,
|
||||||
pub default_info: DefaultInfo,
|
pub default_info: DefaultInfo,
|
||||||
loc: AbsLocation,
|
loc: AbsLocation,
|
||||||
}
|
}
|
||||||
|
@ -149,38 +150,59 @@ impl ParamSpec {
|
||||||
pub const fn new(
|
pub const fn new(
|
||||||
name: Option<&'static str>,
|
name: Option<&'static str>,
|
||||||
t: Type,
|
t: Type,
|
||||||
|
is_var_params: bool,
|
||||||
default: DefaultInfo,
|
default: DefaultInfo,
|
||||||
loc: AbsLocation,
|
loc: AbsLocation,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
name,
|
name,
|
||||||
t,
|
t,
|
||||||
|
is_var_params,
|
||||||
default_info: default,
|
default_info: default,
|
||||||
loc,
|
loc,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const fn named(name: &'static str, t: Type, default: DefaultInfo) -> Self {
|
pub const fn named(
|
||||||
Self::new(Some(name), t, default, AbsLocation::unknown())
|
name: &'static str,
|
||||||
|
t: Type,
|
||||||
|
is_var_params: bool,
|
||||||
|
default: DefaultInfo,
|
||||||
|
) -> Self {
|
||||||
|
Self::new(
|
||||||
|
Some(name),
|
||||||
|
t,
|
||||||
|
is_var_params,
|
||||||
|
default,
|
||||||
|
AbsLocation::unknown(),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const fn named_nd(name: &'static str, t: Type) -> Self {
|
pub const fn named_nd(name: &'static str, t: Type) -> Self {
|
||||||
Self::new(
|
Self::new(
|
||||||
Some(name),
|
Some(name),
|
||||||
t,
|
t,
|
||||||
|
false,
|
||||||
DefaultInfo::NonDefault,
|
DefaultInfo::NonDefault,
|
||||||
AbsLocation::unknown(),
|
AbsLocation::unknown(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const fn t(name: &'static str, default: DefaultInfo) -> Self {
|
pub const fn t(name: &'static str, is_var_params: bool, default: DefaultInfo) -> Self {
|
||||||
Self::new(Some(name), Type, default, AbsLocation::unknown())
|
Self::new(
|
||||||
|
Some(name),
|
||||||
|
Type,
|
||||||
|
is_var_params,
|
||||||
|
default,
|
||||||
|
AbsLocation::unknown(),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const fn t_nd(name: &'static str) -> Self {
|
pub const fn t_nd(name: &'static str) -> Self {
|
||||||
Self::new(
|
Self::new(
|
||||||
Some(name),
|
Some(name),
|
||||||
Type,
|
Type,
|
||||||
|
false,
|
||||||
DefaultInfo::NonDefault,
|
DefaultInfo::NonDefault,
|
||||||
AbsLocation::unknown(),
|
AbsLocation::unknown(),
|
||||||
)
|
)
|
||||||
|
@ -487,12 +509,12 @@ impl Context {
|
||||||
for param in params.into_iter() {
|
for param in params.into_iter() {
|
||||||
let id = DefId(get_hash(&(&name, ¶m)));
|
let id = DefId(get_hash(&(&name, ¶m)));
|
||||||
if let Some(name) = param.name {
|
if let Some(name) = param.name {
|
||||||
let kind = VarKind::parameter(id, param.default_info);
|
let kind = VarKind::parameter(id, param.is_var_params, param.default_info);
|
||||||
let muty = Mutability::from(name);
|
let muty = Mutability::from(name);
|
||||||
let vi = VarInfo::new(param.t, muty, Private, kind, None, None, None, param.loc);
|
let vi = VarInfo::new(param.t, muty, Private, kind, None, None, None, param.loc);
|
||||||
params_.push((Some(VarName::new(Token::static_symbol(name))), vi));
|
params_.push((Some(VarName::new(Token::static_symbol(name))), vi));
|
||||||
} else {
|
} else {
|
||||||
let kind = VarKind::parameter(id, param.default_info);
|
let kind = VarKind::parameter(id, param.is_var_params, param.default_info);
|
||||||
let muty = Mutability::Immutable;
|
let muty = Mutability::Immutable;
|
||||||
let vi = VarInfo::new(param.t, muty, Private, kind, None, None, None, param.loc);
|
let vi = VarInfo::new(param.t, muty, Private, kind, None, None, None, param.loc);
|
||||||
params_.push((None, vi));
|
params_.push((None, vi));
|
||||||
|
|
|
@ -321,7 +321,7 @@ impl Context {
|
||||||
Err(errs) => (Type::Failure, errs),
|
Err(errs) => (Type::Failure, errs),
|
||||||
};
|
};
|
||||||
let def_id = DefId(get_hash(&(&self.name, "_")));
|
let def_id = DefId(get_hash(&(&self.name, "_")));
|
||||||
let kind = VarKind::parameter(def_id, DefaultInfo::NonDefault);
|
let kind = VarKind::parameter(def_id, is_var_params, DefaultInfo::NonDefault);
|
||||||
let vi = VarInfo::new(
|
let vi = VarInfo::new(
|
||||||
spec_t,
|
spec_t,
|
||||||
Immutable,
|
Immutable,
|
||||||
|
@ -382,7 +382,7 @@ impl Context {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let def_id = DefId(get_hash(&(&self.name, name)));
|
let def_id = DefId(get_hash(&(&self.name, name)));
|
||||||
let kind = VarKind::parameter(def_id, default);
|
let kind = VarKind::parameter(def_id, is_var_params, default);
|
||||||
let muty = Mutability::from(&name.inspect()[..]);
|
let muty = Mutability::from(&name.inspect()[..]);
|
||||||
let vi = VarInfo::new(
|
let vi = VarInfo::new(
|
||||||
spec_t,
|
spec_t,
|
||||||
|
@ -440,7 +440,11 @@ impl Context {
|
||||||
log!(err "self_t is None");
|
log!(err "self_t is None");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let kind = VarKind::parameter(DefId(get_hash(&(&self.name, name))), default);
|
let kind = VarKind::parameter(
|
||||||
|
DefId(get_hash(&(&self.name, name))),
|
||||||
|
is_var_params,
|
||||||
|
default,
|
||||||
|
);
|
||||||
let vi = VarInfo::new(
|
let vi = VarInfo::new(
|
||||||
spec_t,
|
spec_t,
|
||||||
Immutable,
|
Immutable,
|
||||||
|
@ -499,7 +503,11 @@ impl Context {
|
||||||
log!(err "self_t is None");
|
log!(err "self_t is None");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let kind = VarKind::parameter(DefId(get_hash(&(&self.name, name))), default);
|
let kind = VarKind::parameter(
|
||||||
|
DefId(get_hash(&(&self.name, name))),
|
||||||
|
is_var_params,
|
||||||
|
default,
|
||||||
|
);
|
||||||
let vi = VarInfo::new(
|
let vi = VarInfo::new(
|
||||||
spec_t,
|
spec_t,
|
||||||
Immutable,
|
Immutable,
|
||||||
|
@ -577,6 +585,11 @@ impl Context {
|
||||||
errs.extend(es);
|
errs.extend(es);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if let Some(var_params) = &mut params.var_params {
|
||||||
|
if let Err(es) = self.assign_param(var_params, None, ParamKind::VarParams) {
|
||||||
|
errs.extend(es);
|
||||||
|
}
|
||||||
|
}
|
||||||
for default in params.defaults.iter_mut() {
|
for default in params.defaults.iter_mut() {
|
||||||
if let Err(es) = self.assign_param(
|
if let Err(es) = self.assign_param(
|
||||||
&mut default.sig,
|
&mut default.sig,
|
||||||
|
|
|
@ -1008,7 +1008,6 @@ impl ASTLowerer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// TODO: varargs
|
|
||||||
fn lower_lambda(&mut self, lambda: ast::Lambda) -> LowerResult<hir::Lambda> {
|
fn lower_lambda(&mut self, lambda: ast::Lambda) -> LowerResult<hir::Lambda> {
|
||||||
log!(info "entered {}({lambda})", fn_name!());
|
log!(info "entered {}({lambda})", fn_name!());
|
||||||
let in_statement = cfg!(feature = "py_compatible")
|
let in_statement = cfg!(feature = "py_compatible")
|
||||||
|
@ -1074,7 +1073,20 @@ impl ASTLowerer {
|
||||||
.iter()
|
.iter()
|
||||||
.partition(|(_, vi)| !vi.kind.has_default());
|
.partition(|(_, vi)| !vi.kind.has_default());
|
||||||
#[cfg(not(feature = "py_compatible"))]
|
#[cfg(not(feature = "py_compatible"))]
|
||||||
let non_default_params = non_default_params.into_iter();
|
let (var_params, non_default_params) = {
|
||||||
|
let (var_params, non_default_params): (Vec<_>, Vec<_>) = non_default_params
|
||||||
|
.into_iter()
|
||||||
|
.partition(|(_, vi)| vi.kind.is_var_params());
|
||||||
|
// vi.t: `[T; _]`
|
||||||
|
// pt: `name: T`
|
||||||
|
let var_params = var_params.get(0).map(|(name, vi)| {
|
||||||
|
ParamTy::pos(
|
||||||
|
name.as_ref().map(|n| n.inspect().clone()),
|
||||||
|
vi.t.inner_ts().remove(0),
|
||||||
|
)
|
||||||
|
});
|
||||||
|
(var_params, non_default_params.into_iter())
|
||||||
|
};
|
||||||
#[cfg(feature = "py_compatible")]
|
#[cfg(feature = "py_compatible")]
|
||||||
let non_default_params = non_default_params.into_iter().filter(|(name, _)| {
|
let non_default_params = non_default_params.into_iter().filter(|(name, _)| {
|
||||||
params
|
params
|
||||||
|
@ -1117,9 +1129,19 @@ impl ASTLowerer {
|
||||||
self.pop_append_errs();
|
self.pop_append_errs();
|
||||||
}
|
}
|
||||||
let ty = if is_procedural {
|
let ty = if is_procedural {
|
||||||
proc(non_default_param_tys, None, default_param_tys, body.t())
|
proc(
|
||||||
|
non_default_param_tys,
|
||||||
|
var_params,
|
||||||
|
default_param_tys,
|
||||||
|
body.t(),
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
func(non_default_param_tys, None, default_param_tys, body.t())
|
func(
|
||||||
|
non_default_param_tys,
|
||||||
|
var_params,
|
||||||
|
default_param_tys,
|
||||||
|
body.t(),
|
||||||
|
)
|
||||||
};
|
};
|
||||||
let t = if ty.has_qvar() { ty.quantify() } else { ty };
|
let t = if ty.has_qvar() { ty.quantify() } else { ty };
|
||||||
Ok(hir::Lambda::new(id, params, lambda.op, body, t))
|
Ok(hir::Lambda::new(id, params, lambda.op, body, t))
|
||||||
|
|
|
@ -41,8 +41,11 @@ use Mutability::*;
|
||||||
pub enum VarKind {
|
pub enum VarKind {
|
||||||
Defined(DefId),
|
Defined(DefId),
|
||||||
Declared,
|
Declared,
|
||||||
// TODO: flatten
|
Parameter {
|
||||||
Parameter { def_id: DefId, default: DefaultInfo },
|
def_id: DefId,
|
||||||
|
var: bool,
|
||||||
|
default: DefaultInfo,
|
||||||
|
},
|
||||||
Auto,
|
Auto,
|
||||||
FixedAuto,
|
FixedAuto,
|
||||||
DoesNotExist,
|
DoesNotExist,
|
||||||
|
@ -50,8 +53,12 @@ pub enum VarKind {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl VarKind {
|
impl VarKind {
|
||||||
pub const fn parameter(def_id: DefId, default: DefaultInfo) -> Self {
|
pub const fn parameter(def_id: DefId, var: bool, default: DefaultInfo) -> Self {
|
||||||
Self::Parameter { def_id, default }
|
Self::Parameter {
|
||||||
|
def_id,
|
||||||
|
var,
|
||||||
|
default,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const fn has_default(&self) -> bool {
|
pub const fn has_default(&self) -> bool {
|
||||||
|
@ -65,6 +72,13 @@ impl VarKind {
|
||||||
matches!(self, Self::Parameter { .. })
|
matches!(self, Self::Parameter { .. })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub const fn is_var_params(&self) -> bool {
|
||||||
|
match self {
|
||||||
|
Self::Parameter { var, .. } => *var,
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub const fn is_defined(&self) -> bool {
|
pub const fn is_defined(&self) -> bool {
|
||||||
matches!(self, Self::Defined(_))
|
matches!(self, Self::Defined(_))
|
||||||
}
|
}
|
||||||
|
@ -236,9 +250,10 @@ impl VarInfo {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parameter(t: Type, def_loc: AbsLocation) -> Self {
|
pub fn nd_parameter(t: Type, def_loc: AbsLocation) -> Self {
|
||||||
let kind = VarKind::Parameter {
|
let kind = VarKind::Parameter {
|
||||||
def_id: DefId(0),
|
def_id: DefId(0),
|
||||||
|
var: false,
|
||||||
default: DefaultInfo::NonDefault,
|
default: DefaultInfo::NonDefault,
|
||||||
};
|
};
|
||||||
Self::new(t, Immutable, Private, kind, None, None, None, def_loc)
|
Self::new(t, Immutable, Private, kind, None, None, None, def_loc)
|
||||||
|
|
|
@ -685,23 +685,6 @@ impl Parser {
|
||||||
debug_exit_info!(self);
|
debug_exit_info!(self);
|
||||||
Ok(sig)
|
Ok(sig)
|
||||||
}
|
}
|
||||||
Expr::UnaryOp(unary) => match unary.op.kind {
|
|
||||||
TokenKind::PreStar => {
|
|
||||||
let mut exprs = unary.args.into_iter();
|
|
||||||
let param = self
|
|
||||||
.convert_rhs_to_param(*exprs.next().unwrap(), false)
|
|
||||||
.map_err(|_| self.stack_dec(fn_name!()))?;
|
|
||||||
let params = Params::new(vec![], Some(param), vec![], None);
|
|
||||||
debug_exit_info!(self);
|
|
||||||
Ok(LambdaSignature::new(params, None, TypeBoundSpecs::empty()))
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
let err = ParseError::simple_syntax_error(line!() as usize, unary.op.loc());
|
|
||||||
self.errs.push(err);
|
|
||||||
debug_exit_info!(self);
|
|
||||||
Err(())
|
|
||||||
}
|
|
||||||
},
|
|
||||||
other => {
|
other => {
|
||||||
let err = ParseError::simple_syntax_error(line!() as usize, other.loc());
|
let err = ParseError::simple_syntax_error(line!() as usize, other.loc());
|
||||||
self.errs.push(err);
|
self.errs.push(err);
|
||||||
|
|
|
@ -1703,6 +1703,15 @@ impl Parser {
|
||||||
debug_exit_info!(self);
|
debug_exit_info!(self);
|
||||||
Ok(call_or_acc)
|
Ok(call_or_acc)
|
||||||
}
|
}
|
||||||
|
Some(t) if t.is(PreStar) => {
|
||||||
|
let _ = self.lpop();
|
||||||
|
let expr = self.try_reduce_expr(false, in_type_args, in_brace, false)?;
|
||||||
|
let tuple = self
|
||||||
|
.try_reduce_nonempty_tuple(ArgKind::Var(PosArg::new(expr)), false)
|
||||||
|
.map_err(|_| self.stack_dec(fn_name!()))?;
|
||||||
|
debug_exit_info!(self);
|
||||||
|
Ok(Expr::Tuple(tuple))
|
||||||
|
}
|
||||||
Some(t) if t.category_is(TC::UnaryOp) => {
|
Some(t) if t.category_is(TC::UnaryOp) => {
|
||||||
let unaryop = self
|
let unaryop = self
|
||||||
.try_reduce_unary()
|
.try_reduce_unary()
|
||||||
|
|
|
@ -3,3 +3,6 @@ p! 1, 2, "a" # ERR
|
||||||
|
|
||||||
first *x = x[0]
|
first *x = x[0]
|
||||||
assert first(1, 2, 3) == "b" # ERR
|
assert first(1, 2, 3) == "b" # ERR
|
||||||
|
|
||||||
|
f = (*_: Int) -> None
|
||||||
|
f "a", 1, 2
|
||||||
|
|
|
@ -7,3 +7,6 @@ assert first(1, 2, 3) == 1
|
||||||
sum_ start: Nat, *args: Int =
|
sum_ start: Nat, *args: Int =
|
||||||
sum(args, start:=start)
|
sum(args, start:=start)
|
||||||
assert sum_(0, 1, 2, 3) == 6
|
assert sum_(0, 1, 2, 3) == 6
|
||||||
|
|
||||||
|
f = (*_: Int) -> None
|
||||||
|
f(1, 2, 3)
|
||||||
|
|
|
@ -303,7 +303,7 @@ fn exec_var_args() -> Result<(), ()> {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn exec_var_args_err() -> Result<(), ()> {
|
fn exec_var_args_err() -> Result<(), ()> {
|
||||||
expect_failure("tests/should_err/var_args.er", 2)
|
expect_failure("tests/should_err/var_args.er", 3)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue