diff --git a/compiler/erg_compiler/codegen.rs b/compiler/erg_compiler/codegen.rs index 781554fe..03b6f900 100644 --- a/compiler/erg_compiler/codegen.rs +++ b/compiler/erg_compiler/codegen.rs @@ -4,6 +4,7 @@ use std::fmt; use std::process; +use crate::ty::codeobj::MakeFunctionFlags; use crate::ty::codeobj::{CodeObj, CodeObjFlags}; use erg_common::astr::AtomicStr; use erg_common::cache::CacheSet; @@ -21,7 +22,7 @@ use erg_parser::ast::DefId; use erg_parser::ast::DefKind; use Opcode::*; -use erg_parser::ast::{ParamPattern, ParamSignature, Params, VarName}; +use erg_parser::ast::{NonDefaultParamSignature, ParamPattern, VarName}; use erg_parser::token::{Token, TokenKind}; use crate::compile::{AccessKind, Name, StoreLoadKind}; @@ -29,7 +30,7 @@ use crate::context::eval::type_from_token_kind; use crate::error::CompileError; use crate::hir::{ 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, }; use crate::ty::free::fresh_varname; @@ -858,6 +859,18 @@ impl CodeGenerator { log!(info "entered {} ({lambda})", fn_name!()); let mut make_function_flag = 0u8; 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("".into()), params); if !self.cur_block_codeobj().cellvars.is_empty() { let cellvars_len = self.cur_block_codeobj().cellvars.len() as u8; @@ -867,7 +880,7 @@ impl CodeGenerator { } self.write_instr(BUILD_TUPLE); 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(""); @@ -875,6 +888,9 @@ impl CodeGenerator { self.write_arg(make_function_flag); // stack_dec: + "> -> self.stack_dec(); + if make_function_flag & MakeFunctionFlags::Defaults as u8 != 0 { + self.stack_dec(); + } } 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 param_name = fresh_varname(); 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 = 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 subr_sig = SubrSignature::new(ident, params, __new__.clone()); let mut attrs = vec![]; @@ -1729,7 +1745,7 @@ impl CodeGenerator { let ident = Identifier::public_with_line(Token::dummy(), Str::ever("new"), line); let param_name = fresh_varname(); 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 arg = PosArg::new(Expr::Accessor(Accessor::private_with_line( Str::from(param_name), diff --git a/compiler/erg_compiler/context/eval.rs b/compiler/erg_compiler/context/eval.rs index f7d2ae12..ead98d4a 100644 --- a/compiler/erg_compiler/context/eval.rs +++ b/compiler/erg_compiler/context/eval.rs @@ -512,20 +512,32 @@ impl Context { let tv_ctx = TyVarInstContext::new(self.level, bounds, self); let mut non_default_params = Vec::with_capacity(lambda.sig.params.non_defaults.len()); for sig in lambda.sig.params.non_defaults.iter() { - let pt = - self.instantiate_param_ty(sig, None, Some(&tv_ctx), RegistrationMode::Normal)?; + let pt = self.instantiate_param_ty( + sig, + None, + None, + Some(&tv_ctx), + RegistrationMode::Normal, + )?; non_default_params.push(pt); } 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) } else { None }; let mut default_params = Vec::with_capacity(lambda.sig.params.defaults.len()); for sig in lambda.sig.params.defaults.iter() { - let pt = - self.instantiate_param_ty(sig, None, Some(&tv_ctx), RegistrationMode::Normal)?; + let expr = self.eval_const_expr(&sig.default_val)?; + let pt = self.instantiate_param_ty( + &sig.sig, + Some(expr.t()), + None, + Some(&tv_ctx), + RegistrationMode::Normal, + )?; default_params.push(pt); } // HACK: should avoid cloning diff --git a/compiler/erg_compiler/context/instantiate.rs b/compiler/erg_compiler/context/instantiate.rs index eaa961b0..c1561fbc 100644 --- a/compiler/erg_compiler/context/instantiate.rs +++ b/compiler/erg_compiler/context/instantiate.rs @@ -13,8 +13,8 @@ use erg_common::Str; use erg_common::{assume_unreachable, enum_unwrap, set, try_map_mut}; use ast::{ - ParamSignature, ParamTySpec, PreDeclTypeSpec, SimpleTypeSpec, TypeBoundSpec, TypeBoundSpecs, - TypeSpec, + NonDefaultParamSignature, ParamTySpec, PreDeclTypeSpec, SimpleTypeSpec, TypeBoundSpec, + TypeBoundSpecs, TypeSpec, }; use erg_parser::ast; use erg_parser::token::TokenKind; @@ -507,6 +507,7 @@ impl Context { pub(crate) fn instantiate_sub_sig_t( &self, sig: &ast::SubrSignature, + default_ts: Vec, mode: RegistrationMode, ) -> TyCheckResult { // -> Result { @@ -521,22 +522,34 @@ impl Context { let opt_decl_t = opt_decl_sig_t .as_ref() .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 opt_decl_t = opt_decl_sig_t .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 { None }; 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 .as_ref() .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 opt_decl_t = opt_decl_sig_t @@ -562,7 +575,7 @@ impl Context { /// spec_t == Noneかつリテラル推論が不可能なら型変数を発行する pub(crate) fn instantiate_param_sig_t( &self, - sig: &ParamSignature, + sig: &NonDefaultParamSignature, opt_decl_t: Option<&ParamTy>, tmp_tv_ctx: Option<&TyVarInstContext>, mode: RegistrationMode, @@ -599,21 +612,15 @@ impl Context { pub(crate) fn instantiate_param_ty( &self, - sig: &ParamSignature, + sig: &NonDefaultParamSignature, + opt_default_t: Option, opt_decl_t: Option<&ParamTy>, tmp_tv_ctx: Option<&TyVarInstContext>, mode: RegistrationMode, ) -> TyCheckResult { let t = self.instantiate_param_sig_t(sig, opt_decl_t, tmp_tv_ctx, mode)?; - match (sig.inspect(), &sig.opt_default_val) { - (Some(name), Some(default)) => { - let default = self.instantiate_const_expr(default)?; - Ok(ParamTy::kw_default( - name.clone(), - t, - self.get_tp_t(&default)?, - )) - } + 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!(), diff --git a/compiler/erg_compiler/context/register.rs b/compiler/erg_compiler/context/register.rs index 8b2b82b0..83247364 100644 --- a/compiler/erg_compiler/context/register.rs +++ b/compiler/erg_compiler/context/register.rs @@ -13,9 +13,9 @@ use erg_common::Str; use erg_common::{enum_unwrap, get_hash, log, option_enum_unwrap, set}; 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::value::{GenTypeObj, TypeKind, TypeObj, ValueObj}; use crate::ty::{HasType, ParamTy, SubrType, Type}; @@ -115,19 +115,23 @@ impl Context { _ => None, }) .collect::>(); - let t = self.instantiate_sub_sig_t(sig, PreRegister).map_err(|e| { - let vi = VarInfo::new( - Type::Failure, - muty, - vis, - kind.clone(), - Some(comptime_decos.clone()), - self.impl_of(), - None, - ); - self.decls.insert(sig.ident.name.clone(), vi); - e - })?; + let default_ts = + vec![free_var(self.level, Constraint::new_type_of(Type::Type)); sig.params.len()]; + let t = self + .instantiate_sub_sig_t(sig, default_ts, PreRegister) + .map_err(|e| { + let vi = VarInfo::new( + Type::Failure, + muty, + vis, + kind.clone(), + Some(comptime_decos.clone()), + self.impl_of(), + None, + ); + self.decls.insert(sig.ident.name.clone(), vi); + e + })?; let vi = VarInfo::new( t, muty, @@ -190,7 +194,8 @@ impl Context { /// 宣言が既にある場合、opt_decl_tに宣言の型を渡す fn assign_param( &mut self, - sig: &ast::ParamSignature, + sig: &ast::NonDefaultParamSignature, + default_val_exists: bool, outer: Option, nth: usize, opt_decl_t: Option<&ParamTy>, @@ -222,7 +227,7 @@ impl Context { } else { ParamIdx::Nth(nth) }; - let default = if sig.opt_default_val.is_some() { + let default = if default_val_exists { DefaultInfo::WithDefault } else { DefaultInfo::NonDefault @@ -262,7 +267,7 @@ impl Context { } else { ParamIdx::Nth(nth) }; - let default = if sig.opt_default_val.is_some() { + let default = if default_val_exists { DefaultInfo::WithDefault } else { DefaultInfo::NonDefault @@ -301,7 +306,7 @@ impl Context { } else { ParamIdx::Nth(nth) }; - let default = if sig.opt_default_val.is_some() { + let default = if default_val_exists { DefaultInfo::WithDefault } else { DefaultInfo::NonDefault @@ -324,7 +329,7 @@ impl Context { pub(crate) fn assign_params( &mut self, - params: &ast::Params, + params: &hir::Params, opt_decl_subr_t: Option, ) -> TyCheckResult<()> { if let Some(decl_subr_t) = opt_decl_subr_t { @@ -339,7 +344,7 @@ impl Context { .zip(decl_subr_t.non_default_params.iter()) .enumerate() { - self.assign_param(sig, None, nth, Some(pt))?; + self.assign_param(sig, false, None, nth, Some(pt))?; } for (nth, (sig, pt)) in params .defaults @@ -347,17 +352,14 @@ impl Context { .zip(decl_subr_t.default_params.iter()) .enumerate() { - // TODO: .clone() - self.assign_param(sig, None, nth, Some(pt))?; + self.assign_param(&sig.sig, true, None, nth, Some(pt))?; } } else { - for (nth, sig) in params - .non_defaults - .iter() - .chain(params.defaults.iter()) - .enumerate() - { - self.assign_param(sig, None, nth, None)?; + for (nth, sig) in params.non_defaults.iter().enumerate() { + self.assign_param(sig, false, None, nth, None)?; + } + for (nth, sig) in params.defaults.iter().enumerate() { + self.assign_param(&sig.sig, true, None, nth, None)?; } } Ok(()) @@ -368,23 +370,24 @@ impl Context { /// * AssignError: if `name` has already been registered pub(crate) fn assign_subr( &mut self, - sig: &ast::SubrSignature, + ident: &Identifier, + decorators: &Set, id: DefId, body_t: &Type, ) -> TyCheckResult { // already defined as const - if sig.is_const() { - let vi = self.decls.remove(sig.ident.inspect()).unwrap(); + if ident.is_const() { + let vi = self.decls.remove(ident.inspect()).unwrap(); let t = vi.t.clone(); - self.locals.insert(sig.ident.name.clone(), vi); + self.locals.insert(ident.name.clone(), vi); return Ok(t); } - let muty = if sig.ident.is_const() { + let muty = if ident.is_const() { Mutability::Const } else { Mutability::Immutable }; - let name = &sig.ident.name; + let name = &ident.name; // FIXME: constでない関数 let t = self .get_current_scope_var(name.inspect()) @@ -394,7 +397,7 @@ impl Context { let var_args = t.var_args(); let default_params = t.default_params().unwrap(); 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| { TyCheckErrors::new( 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( non_default_params.clone(), var_args.cloned(), @@ -448,7 +451,7 @@ impl Context { return Err(TyCheckErrors::from(TyCheckError::violate_decl_error( self.cfg.input.clone(), line!() as usize, - sig.loc(), + ident.loc(), self.caused_by(), name.inspect(), &vi.t, @@ -456,8 +459,7 @@ impl Context { ))); } } - let comptime_decos = sig - .decorators + let comptime_decos = decorators .iter() .filter_map(|deco| match &deco.0 { ast::Expr::Accessor(ast::Accessor::Ident(local)) if local.is_const() => { @@ -469,7 +471,7 @@ impl Context { let vi = VarInfo::new( found_t, muty, - sig.ident.vis(), + ident.vis(), VarKind::Defined(id), Some(comptime_decos), self.impl_of(), @@ -481,21 +483,25 @@ impl Context { 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, + failure_t: Type, + ) { // already defined as const - if sig.is_const() { - let vi = self.decls.remove(sig.ident.inspect()).unwrap(); - self.locals.insert(sig.ident.name.clone(), vi); + if ident.is_const() { + let vi = self.decls.remove(ident.inspect()).unwrap(); + self.locals.insert(ident.name.clone(), vi); } - let muty = if sig.ident.is_const() { + let muty = if ident.is_const() { Mutability::Const } else { Mutability::Immutable }; - let name = &sig.ident.name; + let name = &ident.name; self.decls.remove(name); - let comptime_decos = sig - .decorators + let comptime_decos = decorators .iter() .filter_map(|deco| match &deco.0 { ast::Expr::Accessor(ast::Accessor::Ident(local)) if local.is_const() => { @@ -507,7 +513,7 @@ impl Context { let vi = VarInfo::new( failure_t, muty, - sig.ident.vis(), + ident.vis(), VarKind::DoesNotExist, Some(comptime_decos), self.impl_of(), diff --git a/compiler/erg_compiler/hir.rs b/compiler/erg_compiler/hir.rs index 085eb319..d426aa7f 100644 --- a/compiler/erg_compiler/hir.rs +++ b/compiler/erg_compiler/hir.rs @@ -12,7 +12,7 @@ use erg_common::{ 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 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, + pub var_args: Option>, + pub defaults: Vec, + 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, + Option>, + Vec, + Option<(Token, Token)>, +); + +impl Params { + pub const fn new( + non_defaults: Vec, + var_args: Option>, + defaults: Vec, + 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)] pub struct SubrSignature { pub ident: Identifier, diff --git a/compiler/erg_compiler/lower.rs b/compiler/erg_compiler/lower.rs index 2e619569..50279498 100644 --- a/compiler/erg_compiler/lower.rs +++ b/compiler/erg_compiler/lower.rs @@ -759,6 +759,22 @@ impl ASTLowerer { Ok(hir::Call::new(class, Some(attr_name), args)) } + fn lower_params(&mut self, params: ast::Params) -> LowerResult { + 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 fn lower_lambda(&mut self, lambda: ast::Lambda) -> LowerResult { log!(info "entered {}({lambda})", fn_name!()); @@ -775,7 +791,8 @@ impl ASTLowerer { .instantiate_ty_bounds(&lambda.sig.bounds, RegistrationMode::Normal)?; let tv_ctx = TyVarInstContext::new(self.ctx.level, bounds, &self.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()); } if let Err(errs) = self.ctx.preregister(&lambda.body) { @@ -818,7 +835,7 @@ impl ASTLowerer { } else { 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 { @@ -951,7 +968,8 @@ impl ASTLowerer { .unwrap_or(Type::Failure); match 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()); } if let Err(errs) = self.ctx.preregister(&body.block) { @@ -961,9 +979,9 @@ impl ASTLowerer { Ok(block) => { let found_body_t = block.ref_t(); 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( - sig.loc(), + sig.ident.loc(), sig.ident.inspect(), expect_body_t, found_body_t, @@ -972,20 +990,21 @@ impl ASTLowerer { } } let id = body.id; - let t = - self.ctx - .outer - .as_mut() - .unwrap() - .assign_subr(&sig, id, found_body_t)?; + let t = self.ctx.outer.as_mut().unwrap().assign_subr( + &sig.ident, + &sig.decorators, + id, + found_body_t, + )?; 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); Ok(hir::Def::new(hir::Signature::Subr(sig), body)) } Err(errs) => { self.ctx.outer.as_mut().unwrap().assign_subr( - &sig, + &sig.ident, + &sig.decorators, ast::DefId(0), &Type::Failure, )?; @@ -994,20 +1013,21 @@ impl ASTLowerer { } } 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()); } if let Err(errs) = self.ctx.preregister(&body.block) { self.errs.extend(errs.into_iter()); } - self.ctx - .outer - .as_mut() - .unwrap() - .fake_subr_assign(&sig, Type::Failure); + self.ctx.outer.as_mut().unwrap().fake_subr_assign( + &sig.ident, + &sig.decorators, + Type::Failure, + ); let block = self.lower_block(body.block)?; 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); Ok(hir::Def::new(hir::Signature::Subr(sig), body)) } diff --git a/compiler/erg_compiler/ty/codeobj.rs b/compiler/erg_compiler/ty/codeobj.rs index 80b2dbec..39c6ed9e 100644 --- a/compiler/erg_compiler/ty/codeobj.rs +++ b/compiler/erg_compiler/ty/codeobj.rs @@ -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 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. /// /// 各属性をErg側のObjに変換すると遅くなりそうなので、アクサスされたときのみ変換して提供する diff --git a/compiler/erg_parser/ast.rs b/compiler/erg_parser/ast.rs index b4c297d1..ffd4dc1f 100644 --- a/compiler/erg_parser/ast.rs +++ b/compiler/erg_parser/ast.rs @@ -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, - pub opt_default_val: Option, } -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, - opt_default_val: Option, - ) -> Self { - Self { - pat, - t_spec, - opt_default_val, - } +impl NonDefaultParamSignature { + pub const fn new(pat: ParamPattern, t_spec: Option) -> 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, - pub var_args: Option>, - pub defaults: Vec, + pub non_defaults: Vec, + pub var_args: Option>, + pub defaults: Vec, pub parens: Option<(Token, Token)>, } @@ -2654,17 +2660,17 @@ impl Locational for Params { } type RawParams = ( - Vec, - Option>, - Vec, + Vec, + Option>, + Vec, Option<(Token, Token)>, ); impl Params { pub fn new( - non_defaults: Vec, - var_args: Option, - defaults: Vec, + non_defaults: Vec, + var_args: Option, + defaults: Vec, parens: Option<(Token, Token)>, ) -> Self { Self { diff --git a/compiler/erg_parser/desugar.rs b/compiler/erg_parser/desugar.rs index 1776e35f..b8a64751 100644 --- a/compiler/erg_parser/desugar.rs +++ b/compiler/erg_parser/desugar.rs @@ -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! {}, diff --git a/compiler/erg_parser/parse.rs b/compiler/erg_parser/parse.rs index a5003aff..a2517c61 100644 --- a/compiler/erg_parser/parse.rs +++ b/compiler/erg_parser/parse.rs @@ -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 { + ) -> ParseResult { 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 { + ) -> ParseResult { 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 { + fn convert_kw_arg_to_default_param( + &mut self, + arg: KwArg, + ) -> ParseResult { 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 { + ) -> ParseResult { 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 { + fn convert_accessor_to_param_sig( + &mut self, + accessor: Accessor, + ) -> ParseResult { 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) }