mirror of
https://github.com/erg-lang/erg.git
synced 2025-10-02 21:44:34 +00:00
Implement default parameter
This commit is contained in:
parent
af65a48355
commit
d0456ec1ee
10 changed files with 375 additions and 171 deletions
|
@ -2422,7 +2422,7 @@ impl ParamTuplePattern {
|
|||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||
pub struct ParamRecordAttr {
|
||||
pub lhs: Identifier,
|
||||
pub rhs: ParamSignature,
|
||||
pub rhs: NonDefaultParamSignature,
|
||||
}
|
||||
|
||||
impl NestedDisplay for ParamRecordAttr {
|
||||
|
@ -2435,7 +2435,7 @@ impl_display_from_nested!(ParamRecordAttr);
|
|||
impl_locational!(ParamRecordAttr, lhs, rhs);
|
||||
|
||||
impl ParamRecordAttr {
|
||||
pub const fn new(lhs: Identifier, rhs: ParamSignature) -> Self {
|
||||
pub const fn new(lhs: Identifier, rhs: NonDefaultParamSignature) -> Self {
|
||||
Self { lhs, rhs }
|
||||
}
|
||||
}
|
||||
|
@ -2554,35 +2554,22 @@ impl ParamPattern {
|
|||
|
||||
/// Once the default_value is set to Some, all subsequent values must be Some
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||
pub struct ParamSignature {
|
||||
pub struct NonDefaultParamSignature {
|
||||
pub pat: ParamPattern,
|
||||
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 {
|
||||
if let Some(default_val) = &self.opt_default_val {
|
||||
write!(
|
||||
f,
|
||||
"{}{} := {}",
|
||||
self.pat,
|
||||
fmt_option!(self.t_spec),
|
||||
default_val,
|
||||
)
|
||||
} else {
|
||||
write!(f, "{}{}", self.pat, fmt_option!(self.t_spec),)
|
||||
}
|
||||
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 {
|
||||
if let Some(default) = &self.opt_default_val {
|
||||
Location::concat(&self.pat, default)
|
||||
} else if let Some(t_spec) = &self.t_spec {
|
||||
if let Some(t_spec) = &self.t_spec {
|
||||
Location::concat(&self.pat, t_spec)
|
||||
} else {
|
||||
self.pat.loc()
|
||||
|
@ -2590,33 +2577,52 @@ impl Locational for ParamSignature {
|
|||
}
|
||||
}
|
||||
|
||||
impl ParamSignature {
|
||||
pub const fn new(
|
||||
pat: ParamPattern,
|
||||
t_spec: Option<TypeSpecWithOp>,
|
||||
opt_default_val: Option<ConstExpr>,
|
||||
) -> Self {
|
||||
Self {
|
||||
pat,
|
||||
t_spec,
|
||||
opt_default_val,
|
||||
}
|
||||
impl NonDefaultParamSignature {
|
||||
pub const fn new(pat: ParamPattern, t_spec: Option<TypeSpecWithOp>) -> Self {
|
||||
Self { pat, t_spec }
|
||||
}
|
||||
|
||||
pub const fn inspect(&self) -> Option<&Str> {
|
||||
self.pat.inspect()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn has_default(&self) -> bool {
|
||||
self.opt_default_val.is_some()
|
||||
/// 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<ParamSignature>,
|
||||
pub var_args: Option<Box<ParamSignature>>,
|
||||
pub defaults: Vec<ParamSignature>,
|
||||
pub non_defaults: Vec<NonDefaultParamSignature>,
|
||||
pub var_args: Option<Box<NonDefaultParamSignature>>,
|
||||
pub defaults: Vec<DefaultParamSignature>,
|
||||
pub parens: Option<(Token, Token)>,
|
||||
}
|
||||
|
||||
|
@ -2654,17 +2660,17 @@ impl Locational for Params {
|
|||
}
|
||||
|
||||
type RawParams = (
|
||||
Vec<ParamSignature>,
|
||||
Option<Box<ParamSignature>>,
|
||||
Vec<ParamSignature>,
|
||||
Vec<NonDefaultParamSignature>,
|
||||
Option<Box<NonDefaultParamSignature>>,
|
||||
Vec<DefaultParamSignature>,
|
||||
Option<(Token, Token)>,
|
||||
);
|
||||
|
||||
impl Params {
|
||||
pub fn new(
|
||||
non_defaults: Vec<ParamSignature>,
|
||||
var_args: Option<ParamSignature>,
|
||||
defaults: Vec<ParamSignature>,
|
||||
non_defaults: Vec<NonDefaultParamSignature>,
|
||||
var_args: Option<NonDefaultParamSignature>,
|
||||
defaults: Vec<DefaultParamSignature>,
|
||||
parens: Option<(Token, Token)>,
|
||||
) -> Self {
|
||||
Self {
|
||||
|
|
|
@ -13,8 +13,8 @@ use erg_common::{enum_unwrap, get_hash, log, set};
|
|||
use crate::ast::{
|
||||
Accessor, Args, Array, ArrayComprehension, ArrayWithLength, BinOp, Block, Call, DataPack, Def,
|
||||
DefBody, DefId, Dict, Expr, Identifier, KeyValue, KwArg, Lambda, LambdaSignature, Literal,
|
||||
Methods, Module, NormalArray, NormalDict, NormalRecord, NormalSet, NormalTuple, ParamPattern,
|
||||
ParamSignature, Params, PosArg, Record, RecordAttrs, Set as astSet, SetWithLength,
|
||||
Methods, Module, NonDefaultParamSignature, NormalArray, NormalDict, NormalRecord, NormalSet,
|
||||
NormalTuple, ParamPattern, Params, PosArg, Record, RecordAttrs, Set as astSet, SetWithLength,
|
||||
ShortenedRecord, Signature, SubrSignature, Tuple, TypeAscription, TypeBoundSpecs, TypeSpec,
|
||||
UnaryOp, VarName, VarPattern, VarRecordAttr, VarSignature,
|
||||
};
|
||||
|
@ -255,7 +255,7 @@ impl Desugarer {
|
|||
name.col_end().unwrap() + 1, // HACK: `(name) %x = ...`という形を想定
|
||||
));
|
||||
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 sig = Signature::Subr(SubrSignature::new(
|
||||
set! {},
|
||||
|
|
|
@ -1985,12 +1985,9 @@ impl Parser {
|
|||
return Err(());
|
||||
}
|
||||
// e.g. (x, y:=1) -> ...
|
||||
// Syntax error will occur when trying to use it as a tuple
|
||||
PosOrKwArg::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,
|
||||
arg: PosArg,
|
||||
allow_self: bool,
|
||||
) -> ParseResult<ParamSignature> {
|
||||
) -> ParseResult<NonDefaultParamSignature> {
|
||||
debug_call_info!(self);
|
||||
let param = self
|
||||
.convert_rhs_to_param(arg.expr, allow_self)
|
||||
|
@ -2382,7 +2379,7 @@ impl Parser {
|
|||
&mut self,
|
||||
expr: Expr,
|
||||
allow_self: bool,
|
||||
) -> ParseResult<ParamSignature> {
|
||||
) -> ParseResult<NonDefaultParamSignature> {
|
||||
debug_call_info!(self);
|
||||
match expr {
|
||||
Expr::Accessor(Accessor::Ident(ident)) => {
|
||||
|
@ -2394,13 +2391,13 @@ impl Parser {
|
|||
}
|
||||
// FIXME deny: public
|
||||
let pat = ParamPattern::VarName(ident.name);
|
||||
let param = ParamSignature::new(pat, None, None);
|
||||
let param = NonDefaultParamSignature::new(pat, None);
|
||||
self.level -= 1;
|
||||
Ok(param)
|
||||
}
|
||||
Expr::Lit(lit) => {
|
||||
let pat = ParamPattern::Lit(lit);
|
||||
let param = ParamSignature::new(pat, None, None);
|
||||
let param = NonDefaultParamSignature::new(pat, None);
|
||||
self.level -= 1;
|
||||
Ok(param)
|
||||
}
|
||||
|
@ -2409,7 +2406,7 @@ impl Parser {
|
|||
.convert_array_to_param_array_pat(array)
|
||||
.map_err(|_| self.stack_dec())?;
|
||||
let pat = ParamPattern::Array(array_pat);
|
||||
let param = ParamSignature::new(pat, None, None);
|
||||
let param = NonDefaultParamSignature::new(pat, None);
|
||||
self.level -= 1;
|
||||
Ok(param)
|
||||
}
|
||||
|
@ -2418,7 +2415,7 @@ impl Parser {
|
|||
.convert_record_to_param_record_pat(record)
|
||||
.map_err(|_| self.stack_dec())?;
|
||||
let pat = ParamPattern::Record(record_pat);
|
||||
let param = ParamSignature::new(pat, None, None);
|
||||
let param = NonDefaultParamSignature::new(pat, None);
|
||||
self.level -= 1;
|
||||
Ok(param)
|
||||
}
|
||||
|
@ -2427,7 +2424,7 @@ impl Parser {
|
|||
.convert_tuple_to_param_tuple_pat(tuple)
|
||||
.map_err(|_| self.stack_dec())?;
|
||||
let pat = ParamPattern::Tuple(tuple_pat);
|
||||
let param = ParamSignature::new(pat, None, None);
|
||||
let param = NonDefaultParamSignature::new(pat, None);
|
||||
self.level -= 1;
|
||||
Ok(param)
|
||||
}
|
||||
|
@ -2444,7 +2441,7 @@ impl Parser {
|
|||
let var = option_enum_unwrap!(*var, Expr::Accessor:(Accessor::Ident:(_)))
|
||||
.unwrap_or_else(|| todo!());
|
||||
let pat = ParamPattern::Ref(var.name);
|
||||
let param = ParamSignature::new(pat, None, None);
|
||||
let param = NonDefaultParamSignature::new(pat, None);
|
||||
self.level -= 1;
|
||||
Ok(param)
|
||||
}
|
||||
|
@ -2453,7 +2450,7 @@ impl Parser {
|
|||
let var = option_enum_unwrap!(*var, Expr::Accessor:(Accessor::Ident:(_)))
|
||||
.unwrap_or_else(|| todo!());
|
||||
let pat = ParamPattern::RefMut(var.name);
|
||||
let param = ParamSignature::new(pat, None, None);
|
||||
let param = NonDefaultParamSignature::new(pat, None);
|
||||
self.level -= 1;
|
||||
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);
|
||||
let pat = ParamPattern::VarName(VarName::new(arg.keyword));
|
||||
let expr = Self::validate_const_expr(arg.expr).map_err(|e| self.errs.push(e))?;
|
||||
let param = ParamSignature::new(pat, arg.t_spec, Some(expr));
|
||||
let sig = NonDefaultParamSignature::new(pat, arg.t_spec);
|
||||
let param = DefaultParamSignature::new(sig, arg.expr);
|
||||
self.level -= 1;
|
||||
Ok(param)
|
||||
}
|
||||
|
@ -2532,8 +2532,10 @@ impl Parser {
|
|||
Record::Shortened(rec) => {
|
||||
let mut pats = vec![];
|
||||
for ident in rec.idents.into_iter() {
|
||||
let rhs =
|
||||
ParamSignature::new(ParamPattern::VarName(ident.name.clone()), None, None);
|
||||
let rhs = NonDefaultParamSignature::new(
|
||||
ParamPattern::VarName(ident.name.clone()),
|
||||
None,
|
||||
);
|
||||
pats.push(ParamRecordAttr::new(ident.clone(), rhs));
|
||||
}
|
||||
let attrs = ParamRecordAttrs::new(pats);
|
||||
|
@ -2563,13 +2565,13 @@ impl Parser {
|
|||
&mut self,
|
||||
tasc: TypeAscription,
|
||||
allow_self: bool,
|
||||
) -> ParseResult<ParamSignature> {
|
||||
) -> ParseResult<NonDefaultParamSignature> {
|
||||
debug_call_info!(self);
|
||||
let param = self
|
||||
.convert_rhs_to_param(*tasc.expr, allow_self)
|
||||
.map_err(|_| self.stack_dec())?;
|
||||
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;
|
||||
Ok(param)
|
||||
}
|
||||
|
@ -2596,7 +2598,7 @@ impl Parser {
|
|||
let arr = self
|
||||
.convert_array_to_param_array_pat(array)
|
||||
.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);
|
||||
self.level -= 1;
|
||||
Ok(LambdaSignature::new(params, None, TypeBoundSpecs::empty()))
|
||||
|
@ -2605,7 +2607,7 @@ impl Parser {
|
|||
let rec = self
|
||||
.convert_record_to_param_record_pat(record)
|
||||
.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);
|
||||
self.level -= 1;
|
||||
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);
|
||||
match accessor {
|
||||
Accessor::Ident(ident) => {
|
||||
|
@ -2636,7 +2641,7 @@ impl Parser {
|
|||
ParamPattern::VarName(ident.name)
|
||||
};
|
||||
self.level -= 1;
|
||||
Ok(ParamSignature::new(pat, None, None))
|
||||
Ok(NonDefaultParamSignature::new(pat, None))
|
||||
}
|
||||
other => {
|
||||
self.level -= 1;
|
||||
|
@ -2806,7 +2811,7 @@ impl Parser {
|
|||
});
|
||||
let mut defaults = vec![];
|
||||
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)) => {
|
||||
ParamTySpec::new(Some(name.into_token()), t_spec_with_op.t_spec)
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue