mirror of
https://github.com/erg-lang/erg.git
synced 2025-09-27 19:59:07 +00:00
fix: some bugs
Fixed: * argument `_` of anonymous function disappears * els crashes * incomplete `.update!` codegen
This commit is contained in:
parent
da7ff0a258
commit
2574de3a68
7 changed files with 121 additions and 50 deletions
|
@ -38,7 +38,9 @@ impl<Checker: BuildRunnable> Server<Checker> {
|
||||||
.filter(|warn| warn.core.main_message.ends_with("is not used"))
|
.filter(|warn| warn.core.main_message.ends_with("is not used"))
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
for warn in warns {
|
for warn in warns {
|
||||||
let range = util::loc_to_range(warn.core.loc).unwrap();
|
let Some(range) = util::loc_to_range(warn.core.loc) else {
|
||||||
|
continue;
|
||||||
|
};
|
||||||
match visitor.get_min_expr(range) {
|
match visitor.get_min_expr(range) {
|
||||||
Some(Expr::Def(def)) => {
|
Some(Expr::Def(def)) => {
|
||||||
let Some(mut range) = util::loc_to_range(def.loc()) else {
|
let Some(mut range) = util::loc_to_range(def.loc()) else {
|
||||||
|
|
|
@ -555,7 +555,8 @@ impl<'a> HIRVisitor<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_lambda_info(&self, lambda: &Lambda, token: &Token) -> Option<VarInfo> {
|
fn get_lambda_info(&self, lambda: &Lambda, token: &Token) -> Option<VarInfo> {
|
||||||
self.get_block_info(&lambda.body, token)
|
self.get_params_info(&lambda.params, token)
|
||||||
|
.or_else(|| self.get_block_info(&lambda.body, token))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_array_info(&self, arr: &Array, token: &Token) -> Option<VarInfo> {
|
fn get_array_info(&self, arr: &Array, token: &Token) -> Option<VarInfo> {
|
||||||
|
@ -583,7 +584,7 @@ impl<'a> HIRVisitor<'a> {
|
||||||
|
|
||||||
fn get_record_info(&self, record: &Record, token: &Token) -> Option<VarInfo> {
|
fn get_record_info(&self, record: &Record, token: &Token) -> Option<VarInfo> {
|
||||||
for field in record.attrs.iter() {
|
for field in record.attrs.iter() {
|
||||||
if let Some(expr) = self.get_block_info(&field.body.block, token) {
|
if let Some(expr) = self.get_def_info(field, token) {
|
||||||
return Some(expr);
|
return Some(expr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -142,7 +142,12 @@ impl<Checker: BuildRunnable> Server<Checker> {
|
||||||
def_loc: &AbsLocation,
|
def_loc: &AbsLocation,
|
||||||
) -> ELSResult<()> {
|
) -> ELSResult<()> {
|
||||||
if let Some(module) = def_loc.module.as_ref() {
|
if let Some(module) = def_loc.module.as_ref() {
|
||||||
let mut def_pos = util::loc_to_range(def_loc.loc).unwrap().start;
|
let mut def_pos = match util::loc_to_range(def_loc.loc) {
|
||||||
|
Some(range) => range.start,
|
||||||
|
None => {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
};
|
||||||
def_pos.line = def_pos.line.saturating_sub(1);
|
def_pos.line = def_pos.line.saturating_sub(1);
|
||||||
let def_uri = util::normalize_url(Url::from_file_path(module).unwrap());
|
let def_uri = util::normalize_url(Url::from_file_path(module).unwrap());
|
||||||
let mut default_code_block = "".to_string();
|
let mut default_code_block = "".to_string();
|
||||||
|
|
|
@ -2195,12 +2195,17 @@ impl PyCodeGenerator {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// X.update! x -> x + 1
|
/// X.update! x -> x + 1
|
||||||
/// X = (x -> x + 1)(X)
|
/// => X = mutate_operator((x -> x + 1)(X))
|
||||||
/// X = X + 1
|
/// TODO: should be `X = X + 1` in the above case
|
||||||
fn emit_call_update_311(&mut self, obj: Expr, mut args: Args) {
|
fn emit_call_update_311(&mut self, obj: Expr, mut args: Args) {
|
||||||
log!(info "entered {}", fn_name!());
|
log!(info "entered {}", fn_name!());
|
||||||
let acc = enum_unwrap!(obj, Expr::Accessor);
|
let acc = enum_unwrap!(obj, Expr::Accessor);
|
||||||
let func = args.remove_left_or_key("f").unwrap();
|
let func = args.remove_left_or_key("f").unwrap();
|
||||||
|
if !self.mutate_op_loaded {
|
||||||
|
self.load_mutate_op();
|
||||||
|
}
|
||||||
|
self.emit_push_null();
|
||||||
|
self.emit_load_name_instr(Identifier::private("#mutate_operator"));
|
||||||
self.emit_push_null();
|
self.emit_push_null();
|
||||||
self.emit_expr(func);
|
self.emit_expr(func);
|
||||||
self.emit_acc(acc.clone());
|
self.emit_acc(acc.clone());
|
||||||
|
@ -2208,23 +2213,32 @@ impl PyCodeGenerator {
|
||||||
// (1 (subroutine) + argc) input objects -> 1 return object
|
// (1 (subroutine) + argc) input objects -> 1 return object
|
||||||
// self.stack_dec_n((1 + 1) - 1);
|
// self.stack_dec_n((1 + 1) - 1);
|
||||||
self.stack_dec();
|
self.stack_dec();
|
||||||
|
self.emit_precall_and_call(1);
|
||||||
|
self.stack_dec();
|
||||||
self.store_acc(acc);
|
self.store_acc(acc);
|
||||||
self.emit_load_const(ValueObj::None);
|
self.emit_load_const(ValueObj::None);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// X.update! x -> x + 1
|
/// X.update! x -> x + 1
|
||||||
/// X = (x -> x + 1)(X)
|
/// X = mutate_operator((x -> x + 1)(X))
|
||||||
/// X = X + 1
|
/// X = X + 1
|
||||||
fn emit_call_update_310(&mut self, obj: Expr, mut args: Args) {
|
fn emit_call_update_310(&mut self, obj: Expr, mut args: Args) {
|
||||||
log!(info "entered {}", fn_name!());
|
log!(info "entered {}", fn_name!());
|
||||||
let acc = enum_unwrap!(obj, Expr::Accessor);
|
let acc = enum_unwrap!(obj, Expr::Accessor);
|
||||||
let func = args.remove_left_or_key("f").unwrap();
|
let func = args.remove_left_or_key("f").unwrap();
|
||||||
|
if !self.mutate_op_loaded {
|
||||||
|
self.load_mutate_op();
|
||||||
|
}
|
||||||
|
self.emit_load_name_instr(Identifier::private("#mutate_operator"));
|
||||||
self.emit_expr(func);
|
self.emit_expr(func);
|
||||||
self.emit_acc(acc.clone());
|
self.emit_acc(acc.clone());
|
||||||
self.write_instr(Opcode310::CALL_FUNCTION);
|
self.write_instr(Opcode310::CALL_FUNCTION);
|
||||||
self.write_arg(1);
|
self.write_arg(1);
|
||||||
// (1 (subroutine) + argc) input objects -> 1 return object
|
// (1 (subroutine) + argc) input objects -> 1 return object
|
||||||
self.stack_dec_n((1 + 1) - 1);
|
self.stack_dec_n((1 + 1) - 1);
|
||||||
|
self.write_instr(Opcode310::CALL_FUNCTION);
|
||||||
|
self.write_arg(1);
|
||||||
|
self.stack_dec();
|
||||||
self.store_acc(acc);
|
self.store_acc(acc);
|
||||||
self.emit_load_const(ValueObj::None);
|
self.emit_load_const(ValueObj::None);
|
||||||
}
|
}
|
||||||
|
|
|
@ -261,13 +261,16 @@ impl Context {
|
||||||
// Literal patterns will be desugared to discard patterns
|
// Literal patterns will be desugared to discard patterns
|
||||||
ast::ParamPattern::Lit(_) => unreachable!(),
|
ast::ParamPattern::Lit(_) => unreachable!(),
|
||||||
ast::ParamPattern::Discard(token) => {
|
ast::ParamPattern::Discard(token) => {
|
||||||
let spec_t = self.instantiate_param_sig_t(
|
let (spec_t, errs) = match self.instantiate_param_sig_t(
|
||||||
&sig.raw,
|
&sig.raw,
|
||||||
opt_decl_t,
|
opt_decl_t,
|
||||||
&mut TyVarCache::new(self.level, self),
|
&mut TyVarCache::new(self.level, self),
|
||||||
Normal,
|
Normal,
|
||||||
kind,
|
kind,
|
||||||
)?;
|
) {
|
||||||
|
Ok(ty) => (ty, TyCheckErrors::empty()),
|
||||||
|
Err(errs) => (Type::Failure, errs),
|
||||||
|
};
|
||||||
let def_id = DefId(get_hash(&(&self.name, "_")));
|
let def_id = DefId(get_hash(&(&self.name, "_")));
|
||||||
let kind = VarKind::parameter(def_id, DefaultInfo::NonDefault);
|
let kind = VarKind::parameter(def_id, DefaultInfo::NonDefault);
|
||||||
let vi = VarInfo::new(
|
let vi = VarInfo::new(
|
||||||
|
@ -282,7 +285,11 @@ impl Context {
|
||||||
);
|
);
|
||||||
sig.vi = vi.clone();
|
sig.vi = vi.clone();
|
||||||
self.params.push((Some(VarName::from_static("_")), vi));
|
self.params.push((Some(VarName::from_static("_")), vi));
|
||||||
|
if errs.is_empty() {
|
||||||
Ok(())
|
Ok(())
|
||||||
|
} else {
|
||||||
|
Err(errs)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ast::ParamPattern::VarName(name) => {
|
ast::ParamPattern::VarName(name) => {
|
||||||
if self
|
if self
|
||||||
|
@ -299,13 +306,16 @@ impl Context {
|
||||||
} else {
|
} else {
|
||||||
// ok, not defined
|
// ok, not defined
|
||||||
let mut dummy_tv_cache = TyVarCache::new(self.level, self);
|
let mut dummy_tv_cache = TyVarCache::new(self.level, self);
|
||||||
let spec_t = self.instantiate_param_sig_t(
|
let (spec_t, mut errs) = match self.instantiate_param_sig_t(
|
||||||
&sig.raw,
|
&sig.raw,
|
||||||
opt_decl_t,
|
opt_decl_t,
|
||||||
&mut dummy_tv_cache,
|
&mut dummy_tv_cache,
|
||||||
Normal,
|
Normal,
|
||||||
kind,
|
kind,
|
||||||
)?;
|
) {
|
||||||
|
Ok(ty) => (ty, TyCheckErrors::empty()),
|
||||||
|
Err(errs) => (Type::Failure, errs),
|
||||||
|
};
|
||||||
let spec_t = if is_var_params {
|
let spec_t = if is_var_params {
|
||||||
unknown_len_array_t(spec_t)
|
unknown_len_array_t(spec_t)
|
||||||
} else {
|
} else {
|
||||||
|
@ -313,7 +323,11 @@ impl Context {
|
||||||
};
|
};
|
||||||
if &name.inspect()[..] == "self" {
|
if &name.inspect()[..] == "self" {
|
||||||
if let Some(self_t) = self.rec_get_self_t() {
|
if let Some(self_t) = self.rec_get_self_t() {
|
||||||
self.sub_unify(&spec_t, &self_t, name.loc(), Some(name.inspect()))?;
|
if let Err(es) =
|
||||||
|
self.sub_unify(&spec_t, &self_t, name.loc(), Some(name.inspect()))
|
||||||
|
{
|
||||||
|
errs.extend(es);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
log!(err "self_t is None");
|
log!(err "self_t is None");
|
||||||
}
|
}
|
||||||
|
@ -336,7 +350,11 @@ impl Context {
|
||||||
}
|
}
|
||||||
sig.vi = vi.clone();
|
sig.vi = vi.clone();
|
||||||
self.params.push((Some(name.clone()), vi));
|
self.params.push((Some(name.clone()), vi));
|
||||||
|
if errs.is_empty() {
|
||||||
Ok(())
|
Ok(())
|
||||||
|
} else {
|
||||||
|
Err(errs)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ast::ParamPattern::Ref(name) => {
|
ast::ParamPattern::Ref(name) => {
|
||||||
|
@ -354,21 +372,26 @@ impl Context {
|
||||||
} else {
|
} else {
|
||||||
// ok, not defined
|
// ok, not defined
|
||||||
let mut dummy_tv_cache = TyVarCache::new(self.level, self);
|
let mut dummy_tv_cache = TyVarCache::new(self.level, self);
|
||||||
let spec_t = self.instantiate_param_sig_t(
|
let (spec_t, mut errs) = match self.instantiate_param_sig_t(
|
||||||
&sig.raw,
|
&sig.raw,
|
||||||
opt_decl_t,
|
opt_decl_t,
|
||||||
&mut dummy_tv_cache,
|
&mut dummy_tv_cache,
|
||||||
Normal,
|
Normal,
|
||||||
kind,
|
kind,
|
||||||
)?;
|
) {
|
||||||
|
Ok(ty) => (ty, TyCheckErrors::empty()),
|
||||||
|
Err(errs) => (Type::Failure, errs),
|
||||||
|
};
|
||||||
if &name.inspect()[..] == "self" {
|
if &name.inspect()[..] == "self" {
|
||||||
if let Some(self_t) = self.rec_get_self_t() {
|
if let Some(self_t) = self.rec_get_self_t() {
|
||||||
self.sub_unify(
|
if let Err(es) = self.sub_unify(
|
||||||
&spec_t,
|
&spec_t,
|
||||||
&ref_(self_t),
|
&ref_(self_t),
|
||||||
name.loc(),
|
name.loc(),
|
||||||
Some(name.inspect()),
|
Some(name.inspect()),
|
||||||
)?;
|
) {
|
||||||
|
errs.extend(es);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
log!(err "self_t is None");
|
log!(err "self_t is None");
|
||||||
}
|
}
|
||||||
|
@ -386,7 +409,11 @@ impl Context {
|
||||||
);
|
);
|
||||||
sig.vi = vi.clone();
|
sig.vi = vi.clone();
|
||||||
self.params.push((Some(name.clone()), vi));
|
self.params.push((Some(name.clone()), vi));
|
||||||
|
if errs.is_empty() {
|
||||||
Ok(())
|
Ok(())
|
||||||
|
} else {
|
||||||
|
Err(errs)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ast::ParamPattern::RefMut(name) => {
|
ast::ParamPattern::RefMut(name) => {
|
||||||
|
@ -404,21 +431,26 @@ impl Context {
|
||||||
} else {
|
} else {
|
||||||
// ok, not defined
|
// ok, not defined
|
||||||
let mut dummy_tv_cache = TyVarCache::new(self.level, self);
|
let mut dummy_tv_cache = TyVarCache::new(self.level, self);
|
||||||
let spec_t = self.instantiate_param_sig_t(
|
let (spec_t, mut errs) = match self.instantiate_param_sig_t(
|
||||||
&sig.raw,
|
&sig.raw,
|
||||||
opt_decl_t,
|
opt_decl_t,
|
||||||
&mut dummy_tv_cache,
|
&mut dummy_tv_cache,
|
||||||
Normal,
|
Normal,
|
||||||
kind,
|
kind,
|
||||||
)?;
|
) {
|
||||||
|
Ok(ty) => (ty, TyCheckErrors::empty()),
|
||||||
|
Err(errs) => (Type::Failure, errs),
|
||||||
|
};
|
||||||
if &name.inspect()[..] == "self" {
|
if &name.inspect()[..] == "self" {
|
||||||
if let Some(self_t) = self.rec_get_self_t() {
|
if let Some(self_t) = self.rec_get_self_t() {
|
||||||
self.sub_unify(
|
if let Err(es) = self.sub_unify(
|
||||||
&spec_t,
|
&spec_t,
|
||||||
&ref_mut(self_t, None),
|
&ref_mut(self_t, None),
|
||||||
name.loc(),
|
name.loc(),
|
||||||
Some(name.inspect()),
|
Some(name.inspect()),
|
||||||
)?;
|
) {
|
||||||
|
errs.extend(es);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
log!(err "self_t is None");
|
log!(err "self_t is None");
|
||||||
}
|
}
|
||||||
|
@ -436,7 +468,11 @@ impl Context {
|
||||||
);
|
);
|
||||||
sig.vi = vi.clone();
|
sig.vi = vi.clone();
|
||||||
self.params.push((Some(name.clone()), vi));
|
self.params.push((Some(name.clone()), vi));
|
||||||
|
if errs.is_empty() {
|
||||||
Ok(())
|
Ok(())
|
||||||
|
} else {
|
||||||
|
Err(errs)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
other => {
|
other => {
|
||||||
|
@ -1045,7 +1081,7 @@ impl Context {
|
||||||
if let Some(sup) =
|
if let Some(sup) =
|
||||||
self.rec_get_const_obj(&gen.base_or_sup().unwrap().typ().local_name())
|
self.rec_get_const_obj(&gen.base_or_sup().unwrap().typ().local_name())
|
||||||
{
|
{
|
||||||
let sup = enum_unwrap!(sup, ValueObj::Type);
|
let ValueObj::Type(sup) = sup else { todo!("{sup}") };
|
||||||
let param_t = match sup {
|
let param_t = match sup {
|
||||||
TypeObj::Builtin(t) => t,
|
TypeObj::Builtin(t) => t,
|
||||||
TypeObj::Generated(t) => t.base_or_sup().unwrap().typ(),
|
TypeObj::Generated(t) => t.base_or_sup().unwrap().typ(),
|
||||||
|
@ -1086,7 +1122,7 @@ impl Context {
|
||||||
2,
|
2,
|
||||||
self.level,
|
self.level,
|
||||||
);
|
);
|
||||||
let req = enum_unwrap!(gen.base_or_sup().unwrap(), TypeObj::Builtin:(Type::Record:(_)));
|
let Some(TypeObj::Builtin(Type::Record(req))) = gen.base_or_sup() else { todo!("{gen}") };
|
||||||
for (field, t) in req.iter() {
|
for (field, t) in req.iter() {
|
||||||
let muty = if field.is_const() {
|
let muty = if field.is_const() {
|
||||||
Mutability::Const
|
Mutability::Const
|
||||||
|
@ -1162,7 +1198,7 @@ impl Context {
|
||||||
}
|
}
|
||||||
GenTypeObj::Patch(_) => {
|
GenTypeObj::Patch(_) => {
|
||||||
if gen.typ().is_monomorphic() {
|
if gen.typ().is_monomorphic() {
|
||||||
let base = enum_unwrap!(gen.base_or_sup().unwrap(), TypeObj::Builtin);
|
let Some(TypeObj::Builtin(base)) = gen.base_or_sup() else { todo!("{gen}") };
|
||||||
let ctx = Self::mono_patch(
|
let ctx = Self::mono_patch(
|
||||||
gen.typ().qual_name(),
|
gen.typ().qual_name(),
|
||||||
base.clone(),
|
base.clone(),
|
||||||
|
@ -1356,7 +1392,7 @@ impl Context {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn import_erg_mod(&self, mod_name: &Literal) -> CompileResult<PathBuf> {
|
fn import_erg_mod(&self, mod_name: &Literal) -> CompileResult<PathBuf> {
|
||||||
let __name__ = enum_unwrap!(mod_name.value.clone(), ValueObj::Str);
|
let ValueObj::Str(__name__) = mod_name.value.clone() else { todo!("{mod_name}") };
|
||||||
let mod_cache = self.mod_cache().unwrap();
|
let mod_cache = self.mod_cache().unwrap();
|
||||||
let py_mod_cache = self.py_mod_cache().unwrap();
|
let py_mod_cache = self.py_mod_cache().unwrap();
|
||||||
let path = match Self::resolve_real_path(&self.cfg, Path::new(&__name__[..])) {
|
let path = match Self::resolve_real_path(&self.cfg, Path::new(&__name__[..])) {
|
||||||
|
@ -1514,7 +1550,7 @@ impl Context {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn import_py_mod(&self, mod_name: &Literal) -> CompileResult<PathBuf> {
|
fn import_py_mod(&self, mod_name: &Literal) -> CompileResult<PathBuf> {
|
||||||
let __name__ = enum_unwrap!(mod_name.value.clone(), ValueObj::Str);
|
let ValueObj::Str(__name__) = mod_name.value.clone() else { todo!("{mod_name}") };
|
||||||
let py_mod_cache = self.py_mod_cache().unwrap();
|
let py_mod_cache = self.py_mod_cache().unwrap();
|
||||||
let path = self.get_path(mod_name, __name__)?;
|
let path = self.get_path(mod_name, __name__)?;
|
||||||
if py_mod_cache.get(&path).is_some() {
|
if py_mod_cache.get(&path).is_some() {
|
||||||
|
@ -1586,12 +1622,7 @@ impl Context {
|
||||||
RegistrationMode::Normal,
|
RegistrationMode::Normal,
|
||||||
false,
|
false,
|
||||||
)?;
|
)?;
|
||||||
let lhs = enum_unwrap!(
|
let Some(hir::Expr::BinOp(hir::BinOp { lhs, .. })) = call.args.get_mut_left_or_key("pred") else { todo!("{}", call.args) };
|
||||||
call.args.get_mut_left_or_key("pred").unwrap(),
|
|
||||||
hir::Expr::BinOp
|
|
||||||
)
|
|
||||||
.lhs
|
|
||||||
.as_mut();
|
|
||||||
match (
|
match (
|
||||||
self.supertype_of(lhs.ref_t(), &cast_to),
|
self.supertype_of(lhs.ref_t(), &cast_to),
|
||||||
self.subtype_of(lhs.ref_t(), &cast_to),
|
self.subtype_of(lhs.ref_t(), &cast_to),
|
||||||
|
@ -1602,7 +1633,7 @@ impl Context {
|
||||||
(false, true) => Ok(()), // TODO: warn (needless)
|
(false, true) => Ok(()), // TODO: warn (needless)
|
||||||
// assert x in Nat (x: Int)
|
// assert x in Nat (x: Int)
|
||||||
(true, false) => {
|
(true, false) => {
|
||||||
if let hir::Expr::Accessor(ref acc) = lhs {
|
if let hir::Expr::Accessor(ref acc) = lhs.as_ref() {
|
||||||
self.change_var_type(acc, cast_to.clone())?;
|
self.change_var_type(acc, cast_to.clone())?;
|
||||||
}
|
}
|
||||||
match lhs.ref_t() {
|
match lhs.ref_t() {
|
||||||
|
|
|
@ -1017,28 +1017,45 @@ impl ASTLowerer {
|
||||||
}
|
}
|
||||||
errs
|
errs
|
||||||
})?;
|
})?;
|
||||||
|
// suppress warns of lambda types, e.g. `(x: Int, y: Int) -> Int`
|
||||||
|
if self.module.context.subtype_of(body.ref_t(), &Type::Type) {
|
||||||
|
for param in params.non_defaults.iter() {
|
||||||
|
self.inc_ref(¶m.vi, param);
|
||||||
|
}
|
||||||
|
if let Some(var_param) = params.var_params.as_deref() {
|
||||||
|
self.inc_ref(&var_param.vi, var_param);
|
||||||
|
}
|
||||||
|
for default in params.defaults.iter() {
|
||||||
|
self.inc_ref(&default.sig.vi, &default.sig);
|
||||||
|
}
|
||||||
|
}
|
||||||
let (non_default_params, default_params): (Vec<_>, Vec<_>) = self
|
let (non_default_params, default_params): (Vec<_>, Vec<_>) = self
|
||||||
.module
|
.module
|
||||||
.context
|
.context
|
||||||
.params
|
.params
|
||||||
.iter()
|
.iter()
|
||||||
.partition(|(_, v)| !v.kind.has_default());
|
.partition(|(_, vi)| !vi.kind.has_default());
|
||||||
let non_default_params = non_default_params
|
#[cfg(not(feature = "py_compatible"))]
|
||||||
.into_iter()
|
let non_default_params = non_default_params.into_iter();
|
||||||
// necessary when `py_compatible` feature is enabled
|
#[cfg(feature = "py_compatible")]
|
||||||
.filter(|(name, _)| {
|
let non_default_params = non_default_params.into_iter().filter(|(name, _)| {
|
||||||
params
|
params
|
||||||
.non_defaults
|
.non_defaults
|
||||||
.iter()
|
.iter()
|
||||||
.any(|nd| nd.name() == name.as_ref())
|
.any(|nd| nd.name() == name.as_ref())
|
||||||
})
|
});
|
||||||
|
let non_default_param_tys = non_default_params
|
||||||
.map(|(name, vi)| {
|
.map(|(name, vi)| {
|
||||||
ParamTy::pos(name.as_ref().map(|n| n.inspect().clone()), vi.t.clone())
|
ParamTy::pos(name.as_ref().map(|n| n.inspect().clone()), vi.t.clone())
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
#[cfg(not(feature = "py_compatible"))]
|
||||||
|
let default_params = default_params.into_iter();
|
||||||
|
#[cfg(feature = "py_compatible")]
|
||||||
let default_params = default_params
|
let default_params = default_params
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.filter(|(name, _)| params.defaults.iter().any(|d| d.name() == name.as_ref()))
|
.filter(|(name, _)| params.defaults.iter().any(|d| d.name() == name.as_ref()));
|
||||||
|
let default_param_tys = default_params
|
||||||
.map(|(name, vi)| ParamTy::kw(name.as_ref().unwrap().inspect().clone(), vi.t.clone()))
|
.map(|(name, vi)| ParamTy::kw(name.as_ref().unwrap().inspect().clone(), vi.t.clone()))
|
||||||
.collect();
|
.collect();
|
||||||
if in_statement {
|
if in_statement {
|
||||||
|
@ -1062,9 +1079,9 @@ impl ASTLowerer {
|
||||||
self.pop_append_errs();
|
self.pop_append_errs();
|
||||||
}
|
}
|
||||||
let ty = if is_procedural {
|
let ty = if is_procedural {
|
||||||
proc(non_default_params, None, default_params, body.t())
|
proc(non_default_param_tys, None, default_param_tys, body.t())
|
||||||
} else {
|
} else {
|
||||||
func(non_default_params, None, default_params, body.t())
|
func(non_default_param_tys, None, default_param_tys, body.t())
|
||||||
};
|
};
|
||||||
let t = if ty.has_qvar() { ty.quantify() } else { ty };
|
let t = if ty.has_qvar() { ty.quantify() } else { ty };
|
||||||
Ok(hir::Lambda::new(id, params, lambda.op, body, t))
|
Ok(hir::Lambda::new(id, params, lambda.op, body, t))
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
i = !1
|
i = !0
|
||||||
|
i.update! _ -> 1
|
||||||
i.update! i -> i * 3
|
i.update! i -> i * 3
|
||||||
assert i == 3
|
assert i == 3
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue