Implement default parameter

This commit is contained in:
Shunsuke Shibayama 2022-10-18 10:27:57 +09:00
parent af65a48355
commit d0456ec1ee
10 changed files with 375 additions and 171 deletions

View file

@ -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("<lambda>".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("<lambda>");
@ -875,6 +888,9 @@ impl CodeGenerator {
self.write_arg(make_function_flag);
// stack_dec: <lambda code obj> + <name "<lambda>"> -> <function>
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),

View file

@ -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

View file

@ -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<Type>,
mode: RegistrationMode,
) -> TyCheckResult<Type> {
// -> Result<Type, (Type, TyCheckErrors)> {
@ -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<Type>,
opt_decl_t: Option<&ParamTy>,
tmp_tv_ctx: Option<&TyVarInstContext>,
mode: RegistrationMode,
) -> TyCheckResult<ParamTy> {
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!(),

View file

@ -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::<Set<_>>();
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<ParamIdx>,
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<SubrType>,
) -> 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<Decorator>,
id: DefId,
body_t: &Type,
) -> TyCheckResult<Type> {
// 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<Decorator>,
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(),

View file

@ -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<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)]
pub struct SubrSignature {
pub ident: Identifier,

View file

@ -759,6 +759,22 @@ impl ASTLowerer {
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
fn lower_lambda(&mut self, lambda: ast::Lambda) -> LowerResult<hir::Lambda> {
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(&params, 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<hir::Def> {
@ -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(&params, 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(&params, 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))
}

View file

@ -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.
///
/// 各属性をErg側のObjに変換すると遅くなりそうなので、アクサスされたときのみ変換して提供する