mirror of
https://github.com/erg-lang/erg.git
synced 2025-09-29 12:24:45 +00:00
Implement default parameter
This commit is contained in:
parent
af65a48355
commit
d0456ec1ee
10 changed files with 375 additions and 171 deletions
|
@ -4,6 +4,7 @@
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::process;
|
use std::process;
|
||||||
|
|
||||||
|
use crate::ty::codeobj::MakeFunctionFlags;
|
||||||
use crate::ty::codeobj::{CodeObj, CodeObjFlags};
|
use crate::ty::codeobj::{CodeObj, CodeObjFlags};
|
||||||
use erg_common::astr::AtomicStr;
|
use erg_common::astr::AtomicStr;
|
||||||
use erg_common::cache::CacheSet;
|
use erg_common::cache::CacheSet;
|
||||||
|
@ -21,7 +22,7 @@ use erg_parser::ast::DefId;
|
||||||
use erg_parser::ast::DefKind;
|
use erg_parser::ast::DefKind;
|
||||||
use Opcode::*;
|
use Opcode::*;
|
||||||
|
|
||||||
use erg_parser::ast::{ParamPattern, ParamSignature, Params, VarName};
|
use erg_parser::ast::{NonDefaultParamSignature, ParamPattern, VarName};
|
||||||
use erg_parser::token::{Token, TokenKind};
|
use erg_parser::token::{Token, TokenKind};
|
||||||
|
|
||||||
use crate::compile::{AccessKind, Name, StoreLoadKind};
|
use crate::compile::{AccessKind, Name, StoreLoadKind};
|
||||||
|
@ -29,7 +30,7 @@ use crate::context::eval::type_from_token_kind;
|
||||||
use crate::error::CompileError;
|
use crate::error::CompileError;
|
||||||
use crate::hir::{
|
use crate::hir::{
|
||||||
Accessor, Args, Array, AttrDef, Attribute, BinOp, Block, Call, ClassDef, Def, DefBody, Expr,
|
Accessor, Args, Array, AttrDef, Attribute, BinOp, Block, Call, ClassDef, Def, DefBody, Expr,
|
||||||
Identifier, Lambda, Literal, PosArg, Record, Signature, SubrSignature, Tuple, UnaryOp,
|
Identifier, Lambda, Literal, Params, PosArg, Record, Signature, SubrSignature, Tuple, UnaryOp,
|
||||||
VarSignature, HIR,
|
VarSignature, HIR,
|
||||||
};
|
};
|
||||||
use crate::ty::free::fresh_varname;
|
use crate::ty::free::fresh_varname;
|
||||||
|
@ -858,6 +859,18 @@ impl CodeGenerator {
|
||||||
log!(info "entered {} ({lambda})", fn_name!());
|
log!(info "entered {} ({lambda})", fn_name!());
|
||||||
let mut make_function_flag = 0u8;
|
let mut make_function_flag = 0u8;
|
||||||
let params = self.gen_param_names(&lambda.params);
|
let params = self.gen_param_names(&lambda.params);
|
||||||
|
if !lambda.params.defaults.is_empty() {
|
||||||
|
let defaults_len = lambda.params.defaults.len();
|
||||||
|
lambda
|
||||||
|
.params
|
||||||
|
.defaults
|
||||||
|
.into_iter()
|
||||||
|
.for_each(|default| self.emit_expr(default.default_val));
|
||||||
|
self.write_instr(BUILD_TUPLE);
|
||||||
|
self.write_arg(defaults_len as u8);
|
||||||
|
self.stack_dec_n(defaults_len - 1);
|
||||||
|
make_function_flag += MakeFunctionFlags::Defaults as u8;
|
||||||
|
}
|
||||||
let code = self.emit_block(lambda.body, Some("<lambda>".into()), params);
|
let code = self.emit_block(lambda.body, Some("<lambda>".into()), params);
|
||||||
if !self.cur_block_codeobj().cellvars.is_empty() {
|
if !self.cur_block_codeobj().cellvars.is_empty() {
|
||||||
let cellvars_len = self.cur_block_codeobj().cellvars.len() as u8;
|
let cellvars_len = self.cur_block_codeobj().cellvars.len() as u8;
|
||||||
|
@ -867,7 +880,7 @@ impl CodeGenerator {
|
||||||
}
|
}
|
||||||
self.write_instr(BUILD_TUPLE);
|
self.write_instr(BUILD_TUPLE);
|
||||||
self.write_arg(cellvars_len);
|
self.write_arg(cellvars_len);
|
||||||
make_function_flag += 8;
|
make_function_flag += MakeFunctionFlags::Closure as u8;
|
||||||
}
|
}
|
||||||
self.emit_load_const(code);
|
self.emit_load_const(code);
|
||||||
self.emit_load_const("<lambda>");
|
self.emit_load_const("<lambda>");
|
||||||
|
@ -875,6 +888,9 @@ impl CodeGenerator {
|
||||||
self.write_arg(make_function_flag);
|
self.write_arg(make_function_flag);
|
||||||
// stack_dec: <lambda code obj> + <name "<lambda>"> -> <function>
|
// stack_dec: <lambda code obj> + <name "<lambda>"> -> <function>
|
||||||
self.stack_dec();
|
self.stack_dec();
|
||||||
|
if make_function_flag & MakeFunctionFlags::Defaults as u8 != 0 {
|
||||||
|
self.stack_dec();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn emit_unaryop(&mut self, unary: UnaryOp) {
|
fn emit_unaryop(&mut self, unary: UnaryOp) {
|
||||||
|
@ -1671,9 +1687,9 @@ impl CodeGenerator {
|
||||||
let ident = Identifier::public_with_line(Token::dummy(), Str::ever("__init__"), line);
|
let ident = Identifier::public_with_line(Token::dummy(), Str::ever("__init__"), line);
|
||||||
let param_name = fresh_varname();
|
let param_name = 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 param = ParamSignature::new(ParamPattern::VarName(param), None, None);
|
let param = NonDefaultParamSignature::new(ParamPattern::VarName(param), None);
|
||||||
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 self_param = ParamSignature::new(ParamPattern::VarName(self_param), None, None);
|
let self_param = NonDefaultParamSignature::new(ParamPattern::VarName(self_param), None);
|
||||||
let params = Params::new(vec![self_param, param], None, vec![], None);
|
let params = Params::new(vec![self_param, param], None, vec![], None);
|
||||||
let subr_sig = SubrSignature::new(ident, params, __new__.clone());
|
let subr_sig = SubrSignature::new(ident, params, __new__.clone());
|
||||||
let mut attrs = vec![];
|
let mut attrs = vec![];
|
||||||
|
@ -1729,7 +1745,7 @@ impl CodeGenerator {
|
||||||
let ident = Identifier::public_with_line(Token::dummy(), Str::ever("new"), line);
|
let ident = Identifier::public_with_line(Token::dummy(), Str::ever("new"), line);
|
||||||
let param_name = fresh_varname();
|
let param_name = 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 param = ParamSignature::new(ParamPattern::VarName(param), None, None);
|
let param = NonDefaultParamSignature::new(ParamPattern::VarName(param), None);
|
||||||
let sig = SubrSignature::new(ident, Params::new(vec![param], None, vec![], None), __new__);
|
let sig = SubrSignature::new(ident, Params::new(vec![param], None, vec![], None), __new__);
|
||||||
let arg = PosArg::new(Expr::Accessor(Accessor::private_with_line(
|
let arg = PosArg::new(Expr::Accessor(Accessor::private_with_line(
|
||||||
Str::from(param_name),
|
Str::from(param_name),
|
||||||
|
|
|
@ -512,20 +512,32 @@ impl Context {
|
||||||
let tv_ctx = TyVarInstContext::new(self.level, bounds, self);
|
let tv_ctx = TyVarInstContext::new(self.level, bounds, self);
|
||||||
let mut non_default_params = Vec::with_capacity(lambda.sig.params.non_defaults.len());
|
let mut non_default_params = Vec::with_capacity(lambda.sig.params.non_defaults.len());
|
||||||
for sig in lambda.sig.params.non_defaults.iter() {
|
for sig in lambda.sig.params.non_defaults.iter() {
|
||||||
let pt =
|
let pt = self.instantiate_param_ty(
|
||||||
self.instantiate_param_ty(sig, None, Some(&tv_ctx), RegistrationMode::Normal)?;
|
sig,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
Some(&tv_ctx),
|
||||||
|
RegistrationMode::Normal,
|
||||||
|
)?;
|
||||||
non_default_params.push(pt);
|
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_args.as_ref() {
|
||||||
let pt = self.instantiate_param_ty(p, None, Some(&tv_ctx), RegistrationMode::Normal)?;
|
let pt =
|
||||||
|
self.instantiate_param_ty(p, None, None, Some(&tv_ctx), RegistrationMode::Normal)?;
|
||||||
Some(pt)
|
Some(pt)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
let mut default_params = Vec::with_capacity(lambda.sig.params.defaults.len());
|
let mut default_params = Vec::with_capacity(lambda.sig.params.defaults.len());
|
||||||
for sig in lambda.sig.params.defaults.iter() {
|
for sig in lambda.sig.params.defaults.iter() {
|
||||||
let pt =
|
let expr = self.eval_const_expr(&sig.default_val)?;
|
||||||
self.instantiate_param_ty(sig, None, Some(&tv_ctx), RegistrationMode::Normal)?;
|
let pt = self.instantiate_param_ty(
|
||||||
|
&sig.sig,
|
||||||
|
Some(expr.t()),
|
||||||
|
None,
|
||||||
|
Some(&tv_ctx),
|
||||||
|
RegistrationMode::Normal,
|
||||||
|
)?;
|
||||||
default_params.push(pt);
|
default_params.push(pt);
|
||||||
}
|
}
|
||||||
// HACK: should avoid cloning
|
// HACK: should avoid cloning
|
||||||
|
|
|
@ -13,8 +13,8 @@ use erg_common::Str;
|
||||||
use erg_common::{assume_unreachable, enum_unwrap, set, try_map_mut};
|
use erg_common::{assume_unreachable, enum_unwrap, set, try_map_mut};
|
||||||
|
|
||||||
use ast::{
|
use ast::{
|
||||||
ParamSignature, ParamTySpec, PreDeclTypeSpec, SimpleTypeSpec, TypeBoundSpec, TypeBoundSpecs,
|
NonDefaultParamSignature, ParamTySpec, PreDeclTypeSpec, SimpleTypeSpec, TypeBoundSpec,
|
||||||
TypeSpec,
|
TypeBoundSpecs, TypeSpec,
|
||||||
};
|
};
|
||||||
use erg_parser::ast;
|
use erg_parser::ast;
|
||||||
use erg_parser::token::TokenKind;
|
use erg_parser::token::TokenKind;
|
||||||
|
@ -507,6 +507,7 @@ impl Context {
|
||||||
pub(crate) fn instantiate_sub_sig_t(
|
pub(crate) fn instantiate_sub_sig_t(
|
||||||
&self,
|
&self,
|
||||||
sig: &ast::SubrSignature,
|
sig: &ast::SubrSignature,
|
||||||
|
default_ts: Vec<Type>,
|
||||||
mode: RegistrationMode,
|
mode: RegistrationMode,
|
||||||
) -> TyCheckResult<Type> {
|
) -> TyCheckResult<Type> {
|
||||||
// -> Result<Type, (Type, TyCheckErrors)> {
|
// -> Result<Type, (Type, TyCheckErrors)> {
|
||||||
|
@ -521,22 +522,34 @@ impl Context {
|
||||||
let opt_decl_t = opt_decl_sig_t
|
let opt_decl_t = opt_decl_sig_t
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.and_then(|subr| subr.non_default_params.get(n));
|
.and_then(|subr| subr.non_default_params.get(n));
|
||||||
non_defaults.push(self.instantiate_param_ty(p, opt_decl_t, Some(&tv_ctx), mode)?);
|
non_defaults.push(self.instantiate_param_ty(
|
||||||
|
p,
|
||||||
|
None,
|
||||||
|
opt_decl_t,
|
||||||
|
Some(&tv_ctx),
|
||||||
|
mode,
|
||||||
|
)?);
|
||||||
}
|
}
|
||||||
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_args.as_ref() {
|
||||||
let opt_decl_t = opt_decl_sig_t
|
let opt_decl_t = opt_decl_sig_t
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.and_then(|subr| subr.var_params.as_ref().map(|v| v.as_ref()));
|
.and_then(|subr| subr.var_params.as_ref().map(|v| v.as_ref()));
|
||||||
Some(self.instantiate_param_ty(var_args, opt_decl_t, Some(&tv_ctx), mode)?)
|
Some(self.instantiate_param_ty(var_args, None, opt_decl_t, Some(&tv_ctx), mode)?)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
let mut defaults = vec![];
|
let mut defaults = vec![];
|
||||||
for (n, p) in sig.params.defaults.iter().enumerate() {
|
for ((n, p), default_t) in sig.params.defaults.iter().enumerate().zip(default_ts) {
|
||||||
let opt_decl_t = opt_decl_sig_t
|
let opt_decl_t = opt_decl_sig_t
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.and_then(|subr| subr.default_params.get(n));
|
.and_then(|subr| subr.default_params.get(n));
|
||||||
defaults.push(self.instantiate_param_ty(p, opt_decl_t, Some(&tv_ctx), mode)?);
|
defaults.push(self.instantiate_param_ty(
|
||||||
|
&p.sig,
|
||||||
|
Some(default_t),
|
||||||
|
opt_decl_t,
|
||||||
|
Some(&tv_ctx),
|
||||||
|
mode,
|
||||||
|
)?);
|
||||||
}
|
}
|
||||||
let spec_return_t = if let Some(s) = sig.return_t_spec.as_ref() {
|
let spec_return_t = if let Some(s) = sig.return_t_spec.as_ref() {
|
||||||
let opt_decl_t = opt_decl_sig_t
|
let opt_decl_t = opt_decl_sig_t
|
||||||
|
@ -562,7 +575,7 @@ impl Context {
|
||||||
/// spec_t == Noneかつリテラル推論が不可能なら型変数を発行する
|
/// spec_t == Noneかつリテラル推論が不可能なら型変数を発行する
|
||||||
pub(crate) fn instantiate_param_sig_t(
|
pub(crate) fn instantiate_param_sig_t(
|
||||||
&self,
|
&self,
|
||||||
sig: &ParamSignature,
|
sig: &NonDefaultParamSignature,
|
||||||
opt_decl_t: Option<&ParamTy>,
|
opt_decl_t: Option<&ParamTy>,
|
||||||
tmp_tv_ctx: Option<&TyVarInstContext>,
|
tmp_tv_ctx: Option<&TyVarInstContext>,
|
||||||
mode: RegistrationMode,
|
mode: RegistrationMode,
|
||||||
|
@ -599,21 +612,15 @@ impl Context {
|
||||||
|
|
||||||
pub(crate) fn instantiate_param_ty(
|
pub(crate) fn instantiate_param_ty(
|
||||||
&self,
|
&self,
|
||||||
sig: &ParamSignature,
|
sig: &NonDefaultParamSignature,
|
||||||
|
opt_default_t: Option<Type>,
|
||||||
opt_decl_t: Option<&ParamTy>,
|
opt_decl_t: Option<&ParamTy>,
|
||||||
tmp_tv_ctx: Option<&TyVarInstContext>,
|
tmp_tv_ctx: Option<&TyVarInstContext>,
|
||||||
mode: RegistrationMode,
|
mode: RegistrationMode,
|
||||||
) -> TyCheckResult<ParamTy> {
|
) -> TyCheckResult<ParamTy> {
|
||||||
let t = self.instantiate_param_sig_t(sig, opt_decl_t, tmp_tv_ctx, mode)?;
|
let t = self.instantiate_param_sig_t(sig, opt_decl_t, tmp_tv_ctx, mode)?;
|
||||||
match (sig.inspect(), &sig.opt_default_val) {
|
match (sig.inspect(), opt_default_t) {
|
||||||
(Some(name), Some(default)) => {
|
(Some(name), Some(default_t)) => Ok(ParamTy::kw_default(name.clone(), t, default_t)),
|
||||||
let default = self.instantiate_const_expr(default)?;
|
|
||||||
Ok(ParamTy::kw_default(
|
|
||||||
name.clone(),
|
|
||||||
t,
|
|
||||||
self.get_tp_t(&default)?,
|
|
||||||
))
|
|
||||||
}
|
|
||||||
(Some(name), None) => Ok(ParamTy::kw(name.clone(), t)),
|
(Some(name), None) => Ok(ParamTy::kw(name.clone(), t)),
|
||||||
(None, None) => Ok(ParamTy::anonymous(t)),
|
(None, None) => Ok(ParamTy::anonymous(t)),
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
|
|
|
@ -13,9 +13,9 @@ use erg_common::Str;
|
||||||
use erg_common::{enum_unwrap, get_hash, log, option_enum_unwrap, set};
|
use erg_common::{enum_unwrap, get_hash, log, option_enum_unwrap, set};
|
||||||
|
|
||||||
use ast::{DefId, Identifier, VarName};
|
use ast::{DefId, Identifier, VarName};
|
||||||
use erg_parser::ast;
|
use erg_parser::ast::{self, Decorator};
|
||||||
|
|
||||||
use crate::ty::constructors::{func, func1, proc, ref_, ref_mut, v_enum};
|
use crate::ty::constructors::{free_var, func, func1, proc, ref_, ref_mut, v_enum};
|
||||||
use crate::ty::free::{Constraint, Cyclicity, FreeKind};
|
use crate::ty::free::{Constraint, Cyclicity, FreeKind};
|
||||||
use crate::ty::value::{GenTypeObj, TypeKind, TypeObj, ValueObj};
|
use crate::ty::value::{GenTypeObj, TypeKind, TypeObj, ValueObj};
|
||||||
use crate::ty::{HasType, ParamTy, SubrType, Type};
|
use crate::ty::{HasType, ParamTy, SubrType, Type};
|
||||||
|
@ -115,19 +115,23 @@ impl Context {
|
||||||
_ => None,
|
_ => None,
|
||||||
})
|
})
|
||||||
.collect::<Set<_>>();
|
.collect::<Set<_>>();
|
||||||
let t = self.instantiate_sub_sig_t(sig, PreRegister).map_err(|e| {
|
let default_ts =
|
||||||
let vi = VarInfo::new(
|
vec![free_var(self.level, Constraint::new_type_of(Type::Type)); sig.params.len()];
|
||||||
Type::Failure,
|
let t = self
|
||||||
muty,
|
.instantiate_sub_sig_t(sig, default_ts, PreRegister)
|
||||||
vis,
|
.map_err(|e| {
|
||||||
kind.clone(),
|
let vi = VarInfo::new(
|
||||||
Some(comptime_decos.clone()),
|
Type::Failure,
|
||||||
self.impl_of(),
|
muty,
|
||||||
None,
|
vis,
|
||||||
);
|
kind.clone(),
|
||||||
self.decls.insert(sig.ident.name.clone(), vi);
|
Some(comptime_decos.clone()),
|
||||||
e
|
self.impl_of(),
|
||||||
})?;
|
None,
|
||||||
|
);
|
||||||
|
self.decls.insert(sig.ident.name.clone(), vi);
|
||||||
|
e
|
||||||
|
})?;
|
||||||
let vi = VarInfo::new(
|
let vi = VarInfo::new(
|
||||||
t,
|
t,
|
||||||
muty,
|
muty,
|
||||||
|
@ -190,7 +194,8 @@ impl Context {
|
||||||
/// 宣言が既にある場合、opt_decl_tに宣言の型を渡す
|
/// 宣言が既にある場合、opt_decl_tに宣言の型を渡す
|
||||||
fn assign_param(
|
fn assign_param(
|
||||||
&mut self,
|
&mut self,
|
||||||
sig: &ast::ParamSignature,
|
sig: &ast::NonDefaultParamSignature,
|
||||||
|
default_val_exists: bool,
|
||||||
outer: Option<ParamIdx>,
|
outer: Option<ParamIdx>,
|
||||||
nth: usize,
|
nth: usize,
|
||||||
opt_decl_t: Option<&ParamTy>,
|
opt_decl_t: Option<&ParamTy>,
|
||||||
|
@ -222,7 +227,7 @@ impl Context {
|
||||||
} else {
|
} else {
|
||||||
ParamIdx::Nth(nth)
|
ParamIdx::Nth(nth)
|
||||||
};
|
};
|
||||||
let default = if sig.opt_default_val.is_some() {
|
let default = if default_val_exists {
|
||||||
DefaultInfo::WithDefault
|
DefaultInfo::WithDefault
|
||||||
} else {
|
} else {
|
||||||
DefaultInfo::NonDefault
|
DefaultInfo::NonDefault
|
||||||
|
@ -262,7 +267,7 @@ impl Context {
|
||||||
} else {
|
} else {
|
||||||
ParamIdx::Nth(nth)
|
ParamIdx::Nth(nth)
|
||||||
};
|
};
|
||||||
let default = if sig.opt_default_val.is_some() {
|
let default = if default_val_exists {
|
||||||
DefaultInfo::WithDefault
|
DefaultInfo::WithDefault
|
||||||
} else {
|
} else {
|
||||||
DefaultInfo::NonDefault
|
DefaultInfo::NonDefault
|
||||||
|
@ -301,7 +306,7 @@ impl Context {
|
||||||
} else {
|
} else {
|
||||||
ParamIdx::Nth(nth)
|
ParamIdx::Nth(nth)
|
||||||
};
|
};
|
||||||
let default = if sig.opt_default_val.is_some() {
|
let default = if default_val_exists {
|
||||||
DefaultInfo::WithDefault
|
DefaultInfo::WithDefault
|
||||||
} else {
|
} else {
|
||||||
DefaultInfo::NonDefault
|
DefaultInfo::NonDefault
|
||||||
|
@ -324,7 +329,7 @@ impl Context {
|
||||||
|
|
||||||
pub(crate) fn assign_params(
|
pub(crate) fn assign_params(
|
||||||
&mut self,
|
&mut self,
|
||||||
params: &ast::Params,
|
params: &hir::Params,
|
||||||
opt_decl_subr_t: Option<SubrType>,
|
opt_decl_subr_t: Option<SubrType>,
|
||||||
) -> TyCheckResult<()> {
|
) -> TyCheckResult<()> {
|
||||||
if let Some(decl_subr_t) = opt_decl_subr_t {
|
if let Some(decl_subr_t) = opt_decl_subr_t {
|
||||||
|
@ -339,7 +344,7 @@ impl Context {
|
||||||
.zip(decl_subr_t.non_default_params.iter())
|
.zip(decl_subr_t.non_default_params.iter())
|
||||||
.enumerate()
|
.enumerate()
|
||||||
{
|
{
|
||||||
self.assign_param(sig, None, nth, Some(pt))?;
|
self.assign_param(sig, false, None, nth, Some(pt))?;
|
||||||
}
|
}
|
||||||
for (nth, (sig, pt)) in params
|
for (nth, (sig, pt)) in params
|
||||||
.defaults
|
.defaults
|
||||||
|
@ -347,17 +352,14 @@ impl Context {
|
||||||
.zip(decl_subr_t.default_params.iter())
|
.zip(decl_subr_t.default_params.iter())
|
||||||
.enumerate()
|
.enumerate()
|
||||||
{
|
{
|
||||||
// TODO: .clone()
|
self.assign_param(&sig.sig, true, None, nth, Some(pt))?;
|
||||||
self.assign_param(sig, None, nth, Some(pt))?;
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (nth, sig) in params
|
for (nth, sig) in params.non_defaults.iter().enumerate() {
|
||||||
.non_defaults
|
self.assign_param(sig, false, None, nth, None)?;
|
||||||
.iter()
|
}
|
||||||
.chain(params.defaults.iter())
|
for (nth, sig) in params.defaults.iter().enumerate() {
|
||||||
.enumerate()
|
self.assign_param(&sig.sig, true, None, nth, None)?;
|
||||||
{
|
|
||||||
self.assign_param(sig, None, nth, None)?;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -368,23 +370,24 @@ impl Context {
|
||||||
/// * AssignError: if `name` has already been registered
|
/// * AssignError: if `name` has already been registered
|
||||||
pub(crate) fn assign_subr(
|
pub(crate) fn assign_subr(
|
||||||
&mut self,
|
&mut self,
|
||||||
sig: &ast::SubrSignature,
|
ident: &Identifier,
|
||||||
|
decorators: &Set<Decorator>,
|
||||||
id: DefId,
|
id: DefId,
|
||||||
body_t: &Type,
|
body_t: &Type,
|
||||||
) -> TyCheckResult<Type> {
|
) -> TyCheckResult<Type> {
|
||||||
// already defined as const
|
// already defined as const
|
||||||
if sig.is_const() {
|
if ident.is_const() {
|
||||||
let vi = self.decls.remove(sig.ident.inspect()).unwrap();
|
let vi = self.decls.remove(ident.inspect()).unwrap();
|
||||||
let t = vi.t.clone();
|
let t = vi.t.clone();
|
||||||
self.locals.insert(sig.ident.name.clone(), vi);
|
self.locals.insert(ident.name.clone(), vi);
|
||||||
return Ok(t);
|
return Ok(t);
|
||||||
}
|
}
|
||||||
let muty = if sig.ident.is_const() {
|
let muty = if ident.is_const() {
|
||||||
Mutability::Const
|
Mutability::Const
|
||||||
} else {
|
} else {
|
||||||
Mutability::Immutable
|
Mutability::Immutable
|
||||||
};
|
};
|
||||||
let name = &sig.ident.name;
|
let name = &ident.name;
|
||||||
// FIXME: constでない関数
|
// FIXME: constでない関数
|
||||||
let t = self
|
let t = self
|
||||||
.get_current_scope_var(name.inspect())
|
.get_current_scope_var(name.inspect())
|
||||||
|
@ -394,7 +397,7 @@ impl Context {
|
||||||
let var_args = t.var_args();
|
let var_args = t.var_args();
|
||||||
let default_params = t.default_params().unwrap();
|
let default_params = t.default_params().unwrap();
|
||||||
if let Some(spec_ret_t) = t.return_t() {
|
if let Some(spec_ret_t) = t.return_t() {
|
||||||
self.sub_unify(body_t, spec_ret_t, sig.loc(), None)
|
self.sub_unify(body_t, spec_ret_t, ident.loc(), None)
|
||||||
.map_err(|errs| {
|
.map_err(|errs| {
|
||||||
TyCheckErrors::new(
|
TyCheckErrors::new(
|
||||||
errs.into_iter()
|
errs.into_iter()
|
||||||
|
@ -413,7 +416,7 @@ impl Context {
|
||||||
)
|
)
|
||||||
})?;
|
})?;
|
||||||
}
|
}
|
||||||
let sub_t = if sig.ident.is_procedural() {
|
let sub_t = if ident.is_procedural() {
|
||||||
proc(
|
proc(
|
||||||
non_default_params.clone(),
|
non_default_params.clone(),
|
||||||
var_args.cloned(),
|
var_args.cloned(),
|
||||||
|
@ -448,7 +451,7 @@ impl Context {
|
||||||
return Err(TyCheckErrors::from(TyCheckError::violate_decl_error(
|
return Err(TyCheckErrors::from(TyCheckError::violate_decl_error(
|
||||||
self.cfg.input.clone(),
|
self.cfg.input.clone(),
|
||||||
line!() as usize,
|
line!() as usize,
|
||||||
sig.loc(),
|
ident.loc(),
|
||||||
self.caused_by(),
|
self.caused_by(),
|
||||||
name.inspect(),
|
name.inspect(),
|
||||||
&vi.t,
|
&vi.t,
|
||||||
|
@ -456,8 +459,7 @@ impl Context {
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let comptime_decos = sig
|
let comptime_decos = decorators
|
||||||
.decorators
|
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|deco| match &deco.0 {
|
.filter_map(|deco| match &deco.0 {
|
||||||
ast::Expr::Accessor(ast::Accessor::Ident(local)) if local.is_const() => {
|
ast::Expr::Accessor(ast::Accessor::Ident(local)) if local.is_const() => {
|
||||||
|
@ -469,7 +471,7 @@ impl Context {
|
||||||
let vi = VarInfo::new(
|
let vi = VarInfo::new(
|
||||||
found_t,
|
found_t,
|
||||||
muty,
|
muty,
|
||||||
sig.ident.vis(),
|
ident.vis(),
|
||||||
VarKind::Defined(id),
|
VarKind::Defined(id),
|
||||||
Some(comptime_decos),
|
Some(comptime_decos),
|
||||||
self.impl_of(),
|
self.impl_of(),
|
||||||
|
@ -481,21 +483,25 @@ impl Context {
|
||||||
Ok(t)
|
Ok(t)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn fake_subr_assign(&mut self, sig: &ast::SubrSignature, failure_t: Type) {
|
pub(crate) fn fake_subr_assign(
|
||||||
|
&mut self,
|
||||||
|
ident: &Identifier,
|
||||||
|
decorators: &Set<Decorator>,
|
||||||
|
failure_t: Type,
|
||||||
|
) {
|
||||||
// already defined as const
|
// already defined as const
|
||||||
if sig.is_const() {
|
if ident.is_const() {
|
||||||
let vi = self.decls.remove(sig.ident.inspect()).unwrap();
|
let vi = self.decls.remove(ident.inspect()).unwrap();
|
||||||
self.locals.insert(sig.ident.name.clone(), vi);
|
self.locals.insert(ident.name.clone(), vi);
|
||||||
}
|
}
|
||||||
let muty = if sig.ident.is_const() {
|
let muty = if ident.is_const() {
|
||||||
Mutability::Const
|
Mutability::Const
|
||||||
} else {
|
} else {
|
||||||
Mutability::Immutable
|
Mutability::Immutable
|
||||||
};
|
};
|
||||||
let name = &sig.ident.name;
|
let name = &ident.name;
|
||||||
self.decls.remove(name);
|
self.decls.remove(name);
|
||||||
let comptime_decos = sig
|
let comptime_decos = decorators
|
||||||
.decorators
|
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|deco| match &deco.0 {
|
.filter_map(|deco| match &deco.0 {
|
||||||
ast::Expr::Accessor(ast::Accessor::Ident(local)) if local.is_const() => {
|
ast::Expr::Accessor(ast::Accessor::Ident(local)) if local.is_const() => {
|
||||||
|
@ -507,7 +513,7 @@ impl Context {
|
||||||
let vi = VarInfo::new(
|
let vi = VarInfo::new(
|
||||||
failure_t,
|
failure_t,
|
||||||
muty,
|
muty,
|
||||||
sig.ident.vis(),
|
ident.vis(),
|
||||||
VarKind::DoesNotExist,
|
VarKind::DoesNotExist,
|
||||||
Some(comptime_decos),
|
Some(comptime_decos),
|
||||||
self.impl_of(),
|
self.impl_of(),
|
||||||
|
|
|
@ -12,7 +12,7 @@ use erg_common::{
|
||||||
impl_nested_display_for_enum, impl_stream_for_wrapper,
|
impl_nested_display_for_enum, impl_stream_for_wrapper,
|
||||||
};
|
};
|
||||||
|
|
||||||
use erg_parser::ast::{fmt_lines, DefId, DefKind, Params, TypeSpec, VarName};
|
use erg_parser::ast::{fmt_lines, DefId, DefKind, NonDefaultParamSignature, TypeSpec, VarName};
|
||||||
use erg_parser::token::{Token, TokenKind};
|
use erg_parser::token::{Token, TokenKind};
|
||||||
|
|
||||||
use crate::ty::constructors::{array_t, dict_t, set_t, tuple_t};
|
use crate::ty::constructors::{array_t, dict_t, set_t, tuple_t};
|
||||||
|
@ -1216,6 +1216,115 @@ impl VarSignature {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Once the default_value is set to Some, all subsequent values must be Some
|
||||||
|
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||||
|
pub struct DefaultParamSignature {
|
||||||
|
pub sig: NonDefaultParamSignature,
|
||||||
|
pub default_val: Expr,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl NestedDisplay for DefaultParamSignature {
|
||||||
|
fn fmt_nest(&self, f: &mut std::fmt::Formatter<'_>, _level: usize) -> std::fmt::Result {
|
||||||
|
write!(f, "{} := {}", self.sig, self.default_val,)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl_display_from_nested!(DefaultParamSignature);
|
||||||
|
|
||||||
|
impl Locational for DefaultParamSignature {
|
||||||
|
fn loc(&self) -> Location {
|
||||||
|
Location::concat(&self.sig, &self.default_val)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DefaultParamSignature {
|
||||||
|
pub const fn new(sig: NonDefaultParamSignature, default_val: Expr) -> Self {
|
||||||
|
Self { sig, default_val }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const fn inspect(&self) -> Option<&Str> {
|
||||||
|
self.sig.pat.inspect()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||||
|
pub struct Params {
|
||||||
|
pub non_defaults: Vec<NonDefaultParamSignature>,
|
||||||
|
pub var_args: Option<Box<NonDefaultParamSignature>>,
|
||||||
|
pub defaults: Vec<DefaultParamSignature>,
|
||||||
|
pub parens: Option<(Token, Token)>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for Params {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
write!(
|
||||||
|
f,
|
||||||
|
"({}, {}, {})",
|
||||||
|
fmt_vec(&self.non_defaults),
|
||||||
|
fmt_option!(pre "...", &self.var_args),
|
||||||
|
fmt_vec(&self.defaults)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Locational for Params {
|
||||||
|
fn loc(&self) -> Location {
|
||||||
|
// FIXME: varargs
|
||||||
|
if let Some((l, r)) = &self.parens {
|
||||||
|
Location::concat(l, r)
|
||||||
|
} else if !self.non_defaults.is_empty() {
|
||||||
|
Location::concat(&self.non_defaults[0], self.non_defaults.last().unwrap())
|
||||||
|
} else if let Some(var_args) = &self.var_args {
|
||||||
|
if !self.defaults.is_empty() {
|
||||||
|
Location::concat(var_args.as_ref(), self.defaults.last().unwrap())
|
||||||
|
} else {
|
||||||
|
var_args.loc()
|
||||||
|
}
|
||||||
|
} else if !self.defaults.is_empty() {
|
||||||
|
Location::concat(&self.defaults[0], self.defaults.last().unwrap())
|
||||||
|
} else {
|
||||||
|
panic!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type RawParams = (
|
||||||
|
Vec<NonDefaultParamSignature>,
|
||||||
|
Option<Box<NonDefaultParamSignature>>,
|
||||||
|
Vec<DefaultParamSignature>,
|
||||||
|
Option<(Token, Token)>,
|
||||||
|
);
|
||||||
|
|
||||||
|
impl Params {
|
||||||
|
pub const fn new(
|
||||||
|
non_defaults: Vec<NonDefaultParamSignature>,
|
||||||
|
var_args: Option<Box<NonDefaultParamSignature>>,
|
||||||
|
defaults: Vec<DefaultParamSignature>,
|
||||||
|
parens: Option<(Token, Token)>,
|
||||||
|
) -> Self {
|
||||||
|
Self {
|
||||||
|
non_defaults,
|
||||||
|
var_args,
|
||||||
|
defaults,
|
||||||
|
parens,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn deconstruct(self) -> RawParams {
|
||||||
|
(self.non_defaults, self.var_args, self.defaults, self.parens)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn len(&self) -> usize {
|
||||||
|
self.non_defaults.len() + self.defaults.len()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn is_empty(&self) -> bool {
|
||||||
|
self.len() == 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||||
pub struct SubrSignature {
|
pub struct SubrSignature {
|
||||||
pub ident: Identifier,
|
pub ident: Identifier,
|
||||||
|
|
|
@ -759,6 +759,22 @@ impl ASTLowerer {
|
||||||
Ok(hir::Call::new(class, Some(attr_name), args))
|
Ok(hir::Call::new(class, Some(attr_name), args))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn lower_params(&mut self, params: ast::Params) -> LowerResult<hir::Params> {
|
||||||
|
log!(info "entered {}({})", fn_name!(), params);
|
||||||
|
let mut hir_defaults = vec![];
|
||||||
|
for default in params.defaults.into_iter() {
|
||||||
|
let default_val = self.lower_expr(default.default_val)?;
|
||||||
|
hir_defaults.push(hir::DefaultParamSignature::new(default.sig, default_val));
|
||||||
|
}
|
||||||
|
let hir_params = hir::Params::new(
|
||||||
|
params.non_defaults,
|
||||||
|
params.var_args,
|
||||||
|
hir_defaults,
|
||||||
|
params.parens,
|
||||||
|
);
|
||||||
|
Ok(hir_params)
|
||||||
|
}
|
||||||
|
|
||||||
/// TODO: varargs
|
/// 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!());
|
||||||
|
@ -775,7 +791,8 @@ impl ASTLowerer {
|
||||||
.instantiate_ty_bounds(&lambda.sig.bounds, RegistrationMode::Normal)?;
|
.instantiate_ty_bounds(&lambda.sig.bounds, RegistrationMode::Normal)?;
|
||||||
let tv_ctx = TyVarInstContext::new(self.ctx.level, bounds, &self.ctx);
|
let tv_ctx = TyVarInstContext::new(self.ctx.level, bounds, &self.ctx);
|
||||||
self.ctx.grow(&name, kind, Private, Some(tv_ctx));
|
self.ctx.grow(&name, kind, Private, Some(tv_ctx));
|
||||||
if let Err(errs) = self.ctx.assign_params(&lambda.sig.params, None) {
|
let params = self.lower_params(lambda.sig.params)?;
|
||||||
|
if let Err(errs) = self.ctx.assign_params(¶ms, None) {
|
||||||
self.errs.extend(errs.into_iter());
|
self.errs.extend(errs.into_iter());
|
||||||
}
|
}
|
||||||
if let Err(errs) = self.ctx.preregister(&lambda.body) {
|
if let Err(errs) = self.ctx.preregister(&lambda.body) {
|
||||||
|
@ -818,7 +835,7 @@ impl ASTLowerer {
|
||||||
} else {
|
} else {
|
||||||
quant(t, bounds)
|
quant(t, bounds)
|
||||||
};
|
};
|
||||||
Ok(hir::Lambda::new(id, lambda.sig.params, lambda.op, body, t))
|
Ok(hir::Lambda::new(id, params, lambda.op, body, t))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn lower_def(&mut self, def: ast::Def) -> LowerResult<hir::Def> {
|
fn lower_def(&mut self, def: ast::Def) -> LowerResult<hir::Def> {
|
||||||
|
@ -951,7 +968,8 @@ impl ASTLowerer {
|
||||||
.unwrap_or(Type::Failure);
|
.unwrap_or(Type::Failure);
|
||||||
match t {
|
match t {
|
||||||
Type::Subr(t) => {
|
Type::Subr(t) => {
|
||||||
if let Err(errs) = self.ctx.assign_params(&sig.params, Some(t.clone())) {
|
let params = self.lower_params(sig.params)?;
|
||||||
|
if let Err(errs) = self.ctx.assign_params(¶ms, Some(t.clone())) {
|
||||||
self.errs.extend(errs.into_iter());
|
self.errs.extend(errs.into_iter());
|
||||||
}
|
}
|
||||||
if let Err(errs) = self.ctx.preregister(&body.block) {
|
if let Err(errs) = self.ctx.preregister(&body.block) {
|
||||||
|
@ -961,9 +979,9 @@ impl ASTLowerer {
|
||||||
Ok(block) => {
|
Ok(block) => {
|
||||||
let found_body_t = block.ref_t();
|
let found_body_t = block.ref_t();
|
||||||
let expect_body_t = t.return_t.as_ref();
|
let expect_body_t = t.return_t.as_ref();
|
||||||
if !sig.is_const() {
|
if !sig.ident.is_const() {
|
||||||
if let Err(e) = self.return_t_check(
|
if let Err(e) = self.return_t_check(
|
||||||
sig.loc(),
|
sig.ident.loc(),
|
||||||
sig.ident.inspect(),
|
sig.ident.inspect(),
|
||||||
expect_body_t,
|
expect_body_t,
|
||||||
found_body_t,
|
found_body_t,
|
||||||
|
@ -972,20 +990,21 @@ impl ASTLowerer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let id = body.id;
|
let id = body.id;
|
||||||
let t =
|
let t = self.ctx.outer.as_mut().unwrap().assign_subr(
|
||||||
self.ctx
|
&sig.ident,
|
||||||
.outer
|
&sig.decorators,
|
||||||
.as_mut()
|
id,
|
||||||
.unwrap()
|
found_body_t,
|
||||||
.assign_subr(&sig, id, found_body_t)?;
|
)?;
|
||||||
let ident = hir::Identifier::bare(sig.ident.dot, sig.ident.name);
|
let ident = hir::Identifier::bare(sig.ident.dot, sig.ident.name);
|
||||||
let sig = hir::SubrSignature::new(ident, sig.params, t);
|
let sig = hir::SubrSignature::new(ident, params, t);
|
||||||
let body = hir::DefBody::new(body.op, block, body.id);
|
let body = hir::DefBody::new(body.op, block, body.id);
|
||||||
Ok(hir::Def::new(hir::Signature::Subr(sig), body))
|
Ok(hir::Def::new(hir::Signature::Subr(sig), body))
|
||||||
}
|
}
|
||||||
Err(errs) => {
|
Err(errs) => {
|
||||||
self.ctx.outer.as_mut().unwrap().assign_subr(
|
self.ctx.outer.as_mut().unwrap().assign_subr(
|
||||||
&sig,
|
&sig.ident,
|
||||||
|
&sig.decorators,
|
||||||
ast::DefId(0),
|
ast::DefId(0),
|
||||||
&Type::Failure,
|
&Type::Failure,
|
||||||
)?;
|
)?;
|
||||||
|
@ -994,20 +1013,21 @@ impl ASTLowerer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Type::Failure => {
|
Type::Failure => {
|
||||||
if let Err(errs) = self.ctx.assign_params(&sig.params, None) {
|
let params = self.lower_params(sig.params)?;
|
||||||
|
if let Err(errs) = self.ctx.assign_params(¶ms, None) {
|
||||||
self.errs.extend(errs.into_iter());
|
self.errs.extend(errs.into_iter());
|
||||||
}
|
}
|
||||||
if let Err(errs) = self.ctx.preregister(&body.block) {
|
if let Err(errs) = self.ctx.preregister(&body.block) {
|
||||||
self.errs.extend(errs.into_iter());
|
self.errs.extend(errs.into_iter());
|
||||||
}
|
}
|
||||||
self.ctx
|
self.ctx.outer.as_mut().unwrap().fake_subr_assign(
|
||||||
.outer
|
&sig.ident,
|
||||||
.as_mut()
|
&sig.decorators,
|
||||||
.unwrap()
|
Type::Failure,
|
||||||
.fake_subr_assign(&sig, Type::Failure);
|
);
|
||||||
let block = self.lower_block(body.block)?;
|
let block = self.lower_block(body.block)?;
|
||||||
let ident = hir::Identifier::bare(sig.ident.dot, sig.ident.name);
|
let ident = hir::Identifier::bare(sig.ident.dot, sig.ident.name);
|
||||||
let sig = hir::SubrSignature::new(ident, sig.params, Type::Failure);
|
let sig = hir::SubrSignature::new(ident, params, Type::Failure);
|
||||||
let body = hir::DefBody::new(body.op, block, body.id);
|
let body = hir::DefBody::new(body.op, block, body.id);
|
||||||
Ok(hir::Def::new(hir::Signature::Subr(sig), body))
|
Ok(hir::Def::new(hir::Signature::Subr(sig), body))
|
||||||
}
|
}
|
||||||
|
|
|
@ -94,6 +94,29 @@ impl CodeObjFlags {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
|
#[repr(u8)]
|
||||||
|
pub enum MakeFunctionFlags {
|
||||||
|
None = 0,
|
||||||
|
Defaults = 1,
|
||||||
|
KwDefaults = 2,
|
||||||
|
Annotations = 4,
|
||||||
|
Closure = 8,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<u8> for MakeFunctionFlags {
|
||||||
|
fn from(flags: u8) -> Self {
|
||||||
|
match flags {
|
||||||
|
0 => Self::None,
|
||||||
|
1 => Self::Defaults,
|
||||||
|
2 => Self::KwDefaults,
|
||||||
|
4 => Self::Annotations,
|
||||||
|
8 => Self::Closure,
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Implementation of `PyCodeObject`, see Include/cpython/code.h in CPython for details.
|
/// Implementation of `PyCodeObject`, see Include/cpython/code.h in CPython for details.
|
||||||
///
|
///
|
||||||
/// 各属性をErg側のObjに変換すると遅くなりそうなので、アクサスされたときのみ変換して提供する
|
/// 各属性をErg側のObjに変換すると遅くなりそうなので、アクサスされたときのみ変換して提供する
|
||||||
|
|
|
@ -2422,7 +2422,7 @@ impl ParamTuplePattern {
|
||||||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||||
pub struct ParamRecordAttr {
|
pub struct ParamRecordAttr {
|
||||||
pub lhs: Identifier,
|
pub lhs: Identifier,
|
||||||
pub rhs: ParamSignature,
|
pub rhs: NonDefaultParamSignature,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl NestedDisplay for ParamRecordAttr {
|
impl NestedDisplay for ParamRecordAttr {
|
||||||
|
@ -2435,7 +2435,7 @@ impl_display_from_nested!(ParamRecordAttr);
|
||||||
impl_locational!(ParamRecordAttr, lhs, rhs);
|
impl_locational!(ParamRecordAttr, lhs, rhs);
|
||||||
|
|
||||||
impl ParamRecordAttr {
|
impl ParamRecordAttr {
|
||||||
pub const fn new(lhs: Identifier, rhs: ParamSignature) -> Self {
|
pub const fn new(lhs: Identifier, rhs: NonDefaultParamSignature) -> Self {
|
||||||
Self { lhs, rhs }
|
Self { lhs, rhs }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2554,35 +2554,22 @@ impl ParamPattern {
|
||||||
|
|
||||||
/// Once the default_value is set to Some, all subsequent values must be Some
|
/// Once the default_value is set to Some, all subsequent values must be Some
|
||||||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||||
pub struct ParamSignature {
|
pub struct NonDefaultParamSignature {
|
||||||
pub pat: ParamPattern,
|
pub pat: ParamPattern,
|
||||||
pub t_spec: Option<TypeSpecWithOp>,
|
pub t_spec: Option<TypeSpecWithOp>,
|
||||||
pub opt_default_val: Option<ConstExpr>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl NestedDisplay for ParamSignature {
|
impl NestedDisplay for NonDefaultParamSignature {
|
||||||
fn fmt_nest(&self, f: &mut std::fmt::Formatter<'_>, _level: usize) -> std::fmt::Result {
|
fn fmt_nest(&self, f: &mut std::fmt::Formatter<'_>, _level: usize) -> std::fmt::Result {
|
||||||
if let Some(default_val) = &self.opt_default_val {
|
write!(f, "{}{}", self.pat, fmt_option!(self.t_spec),)
|
||||||
write!(
|
|
||||||
f,
|
|
||||||
"{}{} := {}",
|
|
||||||
self.pat,
|
|
||||||
fmt_option!(self.t_spec),
|
|
||||||
default_val,
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
write!(f, "{}{}", self.pat, fmt_option!(self.t_spec),)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl_display_from_nested!(ParamSignature);
|
impl_display_from_nested!(NonDefaultParamSignature);
|
||||||
|
|
||||||
impl Locational for ParamSignature {
|
impl Locational for NonDefaultParamSignature {
|
||||||
fn loc(&self) -> Location {
|
fn loc(&self) -> Location {
|
||||||
if let Some(default) = &self.opt_default_val {
|
if let Some(t_spec) = &self.t_spec {
|
||||||
Location::concat(&self.pat, default)
|
|
||||||
} else if let Some(t_spec) = &self.t_spec {
|
|
||||||
Location::concat(&self.pat, t_spec)
|
Location::concat(&self.pat, t_spec)
|
||||||
} else {
|
} else {
|
||||||
self.pat.loc()
|
self.pat.loc()
|
||||||
|
@ -2590,33 +2577,52 @@ impl Locational for ParamSignature {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ParamSignature {
|
impl NonDefaultParamSignature {
|
||||||
pub const fn new(
|
pub const fn new(pat: ParamPattern, t_spec: Option<TypeSpecWithOp>) -> Self {
|
||||||
pat: ParamPattern,
|
Self { pat, t_spec }
|
||||||
t_spec: Option<TypeSpecWithOp>,
|
|
||||||
opt_default_val: Option<ConstExpr>,
|
|
||||||
) -> Self {
|
|
||||||
Self {
|
|
||||||
pat,
|
|
||||||
t_spec,
|
|
||||||
opt_default_val,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const fn inspect(&self) -> Option<&Str> {
|
pub const fn inspect(&self) -> Option<&Str> {
|
||||||
self.pat.inspect()
|
self.pat.inspect()
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn has_default(&self) -> bool {
|
/// Once the default_value is set to Some, all subsequent values must be Some
|
||||||
self.opt_default_val.is_some()
|
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||||
|
pub struct DefaultParamSignature {
|
||||||
|
pub sig: NonDefaultParamSignature,
|
||||||
|
pub default_val: Expr,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl NestedDisplay for DefaultParamSignature {
|
||||||
|
fn fmt_nest(&self, f: &mut std::fmt::Formatter<'_>, _level: usize) -> std::fmt::Result {
|
||||||
|
write!(f, "{} := {}", self.sig, self.default_val,)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl_display_from_nested!(DefaultParamSignature);
|
||||||
|
|
||||||
|
impl Locational for DefaultParamSignature {
|
||||||
|
fn loc(&self) -> Location {
|
||||||
|
Location::concat(&self.sig, &self.default_val)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DefaultParamSignature {
|
||||||
|
pub const fn new(sig: NonDefaultParamSignature, default_val: Expr) -> Self {
|
||||||
|
Self { sig, default_val }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const fn inspect(&self) -> Option<&Str> {
|
||||||
|
self.sig.pat.inspect()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||||
pub struct Params {
|
pub struct Params {
|
||||||
pub non_defaults: Vec<ParamSignature>,
|
pub non_defaults: Vec<NonDefaultParamSignature>,
|
||||||
pub var_args: Option<Box<ParamSignature>>,
|
pub var_args: Option<Box<NonDefaultParamSignature>>,
|
||||||
pub defaults: Vec<ParamSignature>,
|
pub defaults: Vec<DefaultParamSignature>,
|
||||||
pub parens: Option<(Token, Token)>,
|
pub parens: Option<(Token, Token)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2654,17 +2660,17 @@ impl Locational for Params {
|
||||||
}
|
}
|
||||||
|
|
||||||
type RawParams = (
|
type RawParams = (
|
||||||
Vec<ParamSignature>,
|
Vec<NonDefaultParamSignature>,
|
||||||
Option<Box<ParamSignature>>,
|
Option<Box<NonDefaultParamSignature>>,
|
||||||
Vec<ParamSignature>,
|
Vec<DefaultParamSignature>,
|
||||||
Option<(Token, Token)>,
|
Option<(Token, Token)>,
|
||||||
);
|
);
|
||||||
|
|
||||||
impl Params {
|
impl Params {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
non_defaults: Vec<ParamSignature>,
|
non_defaults: Vec<NonDefaultParamSignature>,
|
||||||
var_args: Option<ParamSignature>,
|
var_args: Option<NonDefaultParamSignature>,
|
||||||
defaults: Vec<ParamSignature>,
|
defaults: Vec<DefaultParamSignature>,
|
||||||
parens: Option<(Token, Token)>,
|
parens: Option<(Token, Token)>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
|
|
|
@ -13,8 +13,8 @@ use erg_common::{enum_unwrap, get_hash, log, set};
|
||||||
use crate::ast::{
|
use crate::ast::{
|
||||||
Accessor, Args, Array, ArrayComprehension, ArrayWithLength, BinOp, Block, Call, DataPack, Def,
|
Accessor, Args, Array, ArrayComprehension, ArrayWithLength, BinOp, Block, Call, DataPack, Def,
|
||||||
DefBody, DefId, Dict, Expr, Identifier, KeyValue, KwArg, Lambda, LambdaSignature, Literal,
|
DefBody, DefId, Dict, Expr, Identifier, KeyValue, KwArg, Lambda, LambdaSignature, Literal,
|
||||||
Methods, Module, NormalArray, NormalDict, NormalRecord, NormalSet, NormalTuple, ParamPattern,
|
Methods, Module, NonDefaultParamSignature, NormalArray, NormalDict, NormalRecord, NormalSet,
|
||||||
ParamSignature, Params, PosArg, Record, RecordAttrs, Set as astSet, SetWithLength,
|
NormalTuple, ParamPattern, Params, PosArg, Record, RecordAttrs, Set as astSet, SetWithLength,
|
||||||
ShortenedRecord, Signature, SubrSignature, Tuple, TypeAscription, TypeBoundSpecs, TypeSpec,
|
ShortenedRecord, Signature, SubrSignature, Tuple, TypeAscription, TypeBoundSpecs, TypeSpec,
|
||||||
UnaryOp, VarName, VarPattern, VarRecordAttr, VarSignature,
|
UnaryOp, VarName, VarPattern, VarRecordAttr, VarSignature,
|
||||||
};
|
};
|
||||||
|
@ -255,7 +255,7 @@ impl Desugarer {
|
||||||
name.col_end().unwrap() + 1, // HACK: `(name) %x = ...`という形を想定
|
name.col_end().unwrap() + 1, // HACK: `(name) %x = ...`という形を想定
|
||||||
));
|
));
|
||||||
let param =
|
let param =
|
||||||
ParamSignature::new(ParamPattern::VarName(param), None, None);
|
NonDefaultParamSignature::new(ParamPattern::VarName(param), None);
|
||||||
let params = Params::new(vec![param], None, vec![], None);
|
let params = Params::new(vec![param], None, vec![], None);
|
||||||
let sig = Signature::Subr(SubrSignature::new(
|
let sig = Signature::Subr(SubrSignature::new(
|
||||||
set! {},
|
set! {},
|
||||||
|
|
|
@ -1985,12 +1985,9 @@ impl Parser {
|
||||||
return Err(());
|
return Err(());
|
||||||
}
|
}
|
||||||
// e.g. (x, y:=1) -> ...
|
// e.g. (x, y:=1) -> ...
|
||||||
|
// Syntax error will occur when trying to use it as a tuple
|
||||||
PosOrKwArg::Kw(arg) => {
|
PosOrKwArg::Kw(arg) => {
|
||||||
args.push_kw(arg);
|
args.push_kw(arg);
|
||||||
/*self.level -= 1;
|
|
||||||
let err = ParseError::simple_syntax_error(line!() as usize, arg.loc());
|
|
||||||
self.errs.push(err);
|
|
||||||
return Err(());*/
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2369,7 +2366,7 @@ impl Parser {
|
||||||
&mut self,
|
&mut self,
|
||||||
arg: PosArg,
|
arg: PosArg,
|
||||||
allow_self: bool,
|
allow_self: bool,
|
||||||
) -> ParseResult<ParamSignature> {
|
) -> ParseResult<NonDefaultParamSignature> {
|
||||||
debug_call_info!(self);
|
debug_call_info!(self);
|
||||||
let param = self
|
let param = self
|
||||||
.convert_rhs_to_param(arg.expr, allow_self)
|
.convert_rhs_to_param(arg.expr, allow_self)
|
||||||
|
@ -2382,7 +2379,7 @@ impl Parser {
|
||||||
&mut self,
|
&mut self,
|
||||||
expr: Expr,
|
expr: Expr,
|
||||||
allow_self: bool,
|
allow_self: bool,
|
||||||
) -> ParseResult<ParamSignature> {
|
) -> ParseResult<NonDefaultParamSignature> {
|
||||||
debug_call_info!(self);
|
debug_call_info!(self);
|
||||||
match expr {
|
match expr {
|
||||||
Expr::Accessor(Accessor::Ident(ident)) => {
|
Expr::Accessor(Accessor::Ident(ident)) => {
|
||||||
|
@ -2394,13 +2391,13 @@ impl Parser {
|
||||||
}
|
}
|
||||||
// FIXME deny: public
|
// FIXME deny: public
|
||||||
let pat = ParamPattern::VarName(ident.name);
|
let pat = ParamPattern::VarName(ident.name);
|
||||||
let param = ParamSignature::new(pat, None, None);
|
let param = NonDefaultParamSignature::new(pat, None);
|
||||||
self.level -= 1;
|
self.level -= 1;
|
||||||
Ok(param)
|
Ok(param)
|
||||||
}
|
}
|
||||||
Expr::Lit(lit) => {
|
Expr::Lit(lit) => {
|
||||||
let pat = ParamPattern::Lit(lit);
|
let pat = ParamPattern::Lit(lit);
|
||||||
let param = ParamSignature::new(pat, None, None);
|
let param = NonDefaultParamSignature::new(pat, None);
|
||||||
self.level -= 1;
|
self.level -= 1;
|
||||||
Ok(param)
|
Ok(param)
|
||||||
}
|
}
|
||||||
|
@ -2409,7 +2406,7 @@ impl Parser {
|
||||||
.convert_array_to_param_array_pat(array)
|
.convert_array_to_param_array_pat(array)
|
||||||
.map_err(|_| self.stack_dec())?;
|
.map_err(|_| self.stack_dec())?;
|
||||||
let pat = ParamPattern::Array(array_pat);
|
let pat = ParamPattern::Array(array_pat);
|
||||||
let param = ParamSignature::new(pat, None, None);
|
let param = NonDefaultParamSignature::new(pat, None);
|
||||||
self.level -= 1;
|
self.level -= 1;
|
||||||
Ok(param)
|
Ok(param)
|
||||||
}
|
}
|
||||||
|
@ -2418,7 +2415,7 @@ impl Parser {
|
||||||
.convert_record_to_param_record_pat(record)
|
.convert_record_to_param_record_pat(record)
|
||||||
.map_err(|_| self.stack_dec())?;
|
.map_err(|_| self.stack_dec())?;
|
||||||
let pat = ParamPattern::Record(record_pat);
|
let pat = ParamPattern::Record(record_pat);
|
||||||
let param = ParamSignature::new(pat, None, None);
|
let param = NonDefaultParamSignature::new(pat, None);
|
||||||
self.level -= 1;
|
self.level -= 1;
|
||||||
Ok(param)
|
Ok(param)
|
||||||
}
|
}
|
||||||
|
@ -2427,7 +2424,7 @@ impl Parser {
|
||||||
.convert_tuple_to_param_tuple_pat(tuple)
|
.convert_tuple_to_param_tuple_pat(tuple)
|
||||||
.map_err(|_| self.stack_dec())?;
|
.map_err(|_| self.stack_dec())?;
|
||||||
let pat = ParamPattern::Tuple(tuple_pat);
|
let pat = ParamPattern::Tuple(tuple_pat);
|
||||||
let param = ParamSignature::new(pat, None, None);
|
let param = NonDefaultParamSignature::new(pat, None);
|
||||||
self.level -= 1;
|
self.level -= 1;
|
||||||
Ok(param)
|
Ok(param)
|
||||||
}
|
}
|
||||||
|
@ -2444,7 +2441,7 @@ impl Parser {
|
||||||
let var = option_enum_unwrap!(*var, Expr::Accessor:(Accessor::Ident:(_)))
|
let var = option_enum_unwrap!(*var, Expr::Accessor:(Accessor::Ident:(_)))
|
||||||
.unwrap_or_else(|| todo!());
|
.unwrap_or_else(|| todo!());
|
||||||
let pat = ParamPattern::Ref(var.name);
|
let pat = ParamPattern::Ref(var.name);
|
||||||
let param = ParamSignature::new(pat, None, None);
|
let param = NonDefaultParamSignature::new(pat, None);
|
||||||
self.level -= 1;
|
self.level -= 1;
|
||||||
Ok(param)
|
Ok(param)
|
||||||
}
|
}
|
||||||
|
@ -2453,7 +2450,7 @@ impl Parser {
|
||||||
let var = option_enum_unwrap!(*var, Expr::Accessor:(Accessor::Ident:(_)))
|
let var = option_enum_unwrap!(*var, Expr::Accessor:(Accessor::Ident:(_)))
|
||||||
.unwrap_or_else(|| todo!());
|
.unwrap_or_else(|| todo!());
|
||||||
let pat = ParamPattern::RefMut(var.name);
|
let pat = ParamPattern::RefMut(var.name);
|
||||||
let param = ParamSignature::new(pat, None, None);
|
let param = NonDefaultParamSignature::new(pat, None);
|
||||||
self.level -= 1;
|
self.level -= 1;
|
||||||
Ok(param)
|
Ok(param)
|
||||||
}
|
}
|
||||||
|
@ -2474,11 +2471,14 @@ impl Parser {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn convert_kw_arg_to_default_param(&mut self, arg: KwArg) -> ParseResult<ParamSignature> {
|
fn convert_kw_arg_to_default_param(
|
||||||
|
&mut self,
|
||||||
|
arg: KwArg,
|
||||||
|
) -> ParseResult<DefaultParamSignature> {
|
||||||
debug_call_info!(self);
|
debug_call_info!(self);
|
||||||
let pat = ParamPattern::VarName(VarName::new(arg.keyword));
|
let pat = ParamPattern::VarName(VarName::new(arg.keyword));
|
||||||
let expr = Self::validate_const_expr(arg.expr).map_err(|e| self.errs.push(e))?;
|
let sig = NonDefaultParamSignature::new(pat, arg.t_spec);
|
||||||
let param = ParamSignature::new(pat, arg.t_spec, Some(expr));
|
let param = DefaultParamSignature::new(sig, arg.expr);
|
||||||
self.level -= 1;
|
self.level -= 1;
|
||||||
Ok(param)
|
Ok(param)
|
||||||
}
|
}
|
||||||
|
@ -2532,8 +2532,10 @@ impl Parser {
|
||||||
Record::Shortened(rec) => {
|
Record::Shortened(rec) => {
|
||||||
let mut pats = vec![];
|
let mut pats = vec![];
|
||||||
for ident in rec.idents.into_iter() {
|
for ident in rec.idents.into_iter() {
|
||||||
let rhs =
|
let rhs = NonDefaultParamSignature::new(
|
||||||
ParamSignature::new(ParamPattern::VarName(ident.name.clone()), None, None);
|
ParamPattern::VarName(ident.name.clone()),
|
||||||
|
None,
|
||||||
|
);
|
||||||
pats.push(ParamRecordAttr::new(ident.clone(), rhs));
|
pats.push(ParamRecordAttr::new(ident.clone(), rhs));
|
||||||
}
|
}
|
||||||
let attrs = ParamRecordAttrs::new(pats);
|
let attrs = ParamRecordAttrs::new(pats);
|
||||||
|
@ -2563,13 +2565,13 @@ impl Parser {
|
||||||
&mut self,
|
&mut self,
|
||||||
tasc: TypeAscription,
|
tasc: TypeAscription,
|
||||||
allow_self: bool,
|
allow_self: bool,
|
||||||
) -> ParseResult<ParamSignature> {
|
) -> ParseResult<NonDefaultParamSignature> {
|
||||||
debug_call_info!(self);
|
debug_call_info!(self);
|
||||||
let param = self
|
let param = self
|
||||||
.convert_rhs_to_param(*tasc.expr, allow_self)
|
.convert_rhs_to_param(*tasc.expr, allow_self)
|
||||||
.map_err(|_| self.stack_dec())?;
|
.map_err(|_| self.stack_dec())?;
|
||||||
let t_spec = TypeSpecWithOp::new(tasc.op, tasc.t_spec);
|
let t_spec = TypeSpecWithOp::new(tasc.op, tasc.t_spec);
|
||||||
let param = ParamSignature::new(param.pat, Some(t_spec), None);
|
let param = NonDefaultParamSignature::new(param.pat, Some(t_spec));
|
||||||
self.level -= 1;
|
self.level -= 1;
|
||||||
Ok(param)
|
Ok(param)
|
||||||
}
|
}
|
||||||
|
@ -2596,7 +2598,7 @@ impl Parser {
|
||||||
let arr = self
|
let arr = self
|
||||||
.convert_array_to_param_array_pat(array)
|
.convert_array_to_param_array_pat(array)
|
||||||
.map_err(|_| self.stack_dec())?;
|
.map_err(|_| self.stack_dec())?;
|
||||||
let param = ParamSignature::new(ParamPattern::Array(arr), None, None);
|
let param = NonDefaultParamSignature::new(ParamPattern::Array(arr), None);
|
||||||
let params = Params::new(vec![param], None, vec![], None);
|
let params = Params::new(vec![param], None, vec![], None);
|
||||||
self.level -= 1;
|
self.level -= 1;
|
||||||
Ok(LambdaSignature::new(params, None, TypeBoundSpecs::empty()))
|
Ok(LambdaSignature::new(params, None, TypeBoundSpecs::empty()))
|
||||||
|
@ -2605,7 +2607,7 @@ impl Parser {
|
||||||
let rec = self
|
let rec = self
|
||||||
.convert_record_to_param_record_pat(record)
|
.convert_record_to_param_record_pat(record)
|
||||||
.map_err(|_| self.stack_dec())?;
|
.map_err(|_| self.stack_dec())?;
|
||||||
let param = ParamSignature::new(ParamPattern::Record(rec), None, None);
|
let param = NonDefaultParamSignature::new(ParamPattern::Record(rec), None);
|
||||||
let params = Params::new(vec![param], None, vec![], None);
|
let params = Params::new(vec![param], None, vec![], None);
|
||||||
self.level -= 1;
|
self.level -= 1;
|
||||||
Ok(LambdaSignature::new(params, None, TypeBoundSpecs::empty()))
|
Ok(LambdaSignature::new(params, None, TypeBoundSpecs::empty()))
|
||||||
|
@ -2626,7 +2628,10 @@ impl Parser {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn convert_accessor_to_param_sig(&mut self, accessor: Accessor) -> ParseResult<ParamSignature> {
|
fn convert_accessor_to_param_sig(
|
||||||
|
&mut self,
|
||||||
|
accessor: Accessor,
|
||||||
|
) -> ParseResult<NonDefaultParamSignature> {
|
||||||
debug_call_info!(self);
|
debug_call_info!(self);
|
||||||
match accessor {
|
match accessor {
|
||||||
Accessor::Ident(ident) => {
|
Accessor::Ident(ident) => {
|
||||||
|
@ -2636,7 +2641,7 @@ impl Parser {
|
||||||
ParamPattern::VarName(ident.name)
|
ParamPattern::VarName(ident.name)
|
||||||
};
|
};
|
||||||
self.level -= 1;
|
self.level -= 1;
|
||||||
Ok(ParamSignature::new(pat, None, None))
|
Ok(NonDefaultParamSignature::new(pat, None))
|
||||||
}
|
}
|
||||||
other => {
|
other => {
|
||||||
self.level -= 1;
|
self.level -= 1;
|
||||||
|
@ -2806,7 +2811,7 @@ impl Parser {
|
||||||
});
|
});
|
||||||
let mut defaults = vec![];
|
let mut defaults = vec![];
|
||||||
for param in lambda.sig.params.defaults.into_iter() {
|
for param in lambda.sig.params.defaults.into_iter() {
|
||||||
let param = match (param.pat, param.t_spec) {
|
let param = match (param.sig.pat, param.sig.t_spec) {
|
||||||
(ParamPattern::VarName(name), Some(t_spec_with_op)) => {
|
(ParamPattern::VarName(name), Some(t_spec_with_op)) => {
|
||||||
ParamTySpec::new(Some(name.into_token()), t_spec_with_op.t_spec)
|
ParamTySpec::new(Some(name.into_token()), t_spec_with_op.t_spec)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue