diff --git a/compiler/erg_compiler/codegen.rs b/compiler/erg_compiler/codegen.rs index b69ed88c..e6268943 100644 --- a/compiler/erg_compiler/codegen.rs +++ b/compiler/erg_compiler/codegen.rs @@ -1203,6 +1203,17 @@ impl CodeGenerator { } } + fn emit_del_instr(&mut self, mut args: Args) { + let ident = enum_unwrap!(args.remove_left_or_key("obj").unwrap(), Expr::Accessor:(Accessor::Ident:(_))); + log!(info "entered {} ({ident})", fn_name!()); + let escaped = escape_name(ident); + let name = self + .local_search(&escaped, Name) + .unwrap_or_else(|| self.register_name(escaped)); + self.write_instr(DELETE_NAME); + self.write_arg(name.idx as u8); + } + fn emit_discard_instr(&mut self, mut args: Args) { log!(info "entered {}", fn_name!()); while let Some(arg) = args.try_remove(0) { @@ -1446,6 +1457,7 @@ impl CodeGenerator { log!(info "entered {}", fn_name!()); match &local.inspect()[..] { "assert" => self.emit_assert_instr(args), + "Del" => self.emit_del_instr(args), "discard" => self.emit_discard_instr(args), "for" | "for!" => self.emit_for_instr(args), "if" | "if!" => self.emit_if_instr(args), diff --git a/compiler/erg_compiler/context/initialize/mod.rs b/compiler/erg_compiler/context/initialize/mod.rs index fc0f42ce..232d3e55 100644 --- a/compiler/erg_compiler/context/initialize/mod.rs +++ b/compiler/erg_compiler/context/initialize/mod.rs @@ -1586,7 +1586,7 @@ impl Context { mono_q("T"), ); let t_cond = quant(t_cond, set! {static_instance("T", Type)}); - let t_discard = nd_func(vec![param_t("old", Obj)], None, NoneType); + let t_discard = nd_func(vec![param_t("obj", Obj)], None, NoneType); // FIXME: quantify let t_if = func( vec![ @@ -1694,6 +1694,9 @@ impl Context { None, )); self.register_builtin_const("Inheritable", ValueObj::Subr(inheritable)); + // TODO: register Del function object + let t_del = nd_func(vec![param_t("obj", Obj)], None, NoneType); + self.register_builtin_impl("Del", t_del, Immutable, Private); } fn init_builtin_procs(&mut self) { diff --git a/compiler/erg_compiler/context/mod.rs b/compiler/erg_compiler/context/mod.rs index aba208b1..4730f0a0 100644 --- a/compiler/erg_compiler/context/mod.rs +++ b/compiler/erg_compiler/context/mod.rs @@ -274,15 +274,17 @@ pub enum RegistrationMode { Normal, } +/// Some Erg functions require additional operation by the compiler. #[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub enum ImportKind { - ErgImport, +pub enum OperationKind { + Import, PyImport, + Del, } -impl ImportKind { +impl OperationKind { pub const fn is_erg_import(&self) -> bool { - matches!(self, Self::ErgImport) + matches!(self, Self::Import) } pub const fn is_py_import(&self) -> bool { matches!(self, Self::PyImport) diff --git a/compiler/erg_compiler/context/register.rs b/compiler/erg_compiler/context/register.rs index 781931ba..1a7a03e2 100644 --- a/compiler/erg_compiler/context/register.rs +++ b/compiler/erg_compiler/context/register.rs @@ -15,7 +15,7 @@ use erg_parser::ast; use erg_type::constructors::{func, func1, proc, ref_, ref_mut, v_enum}; use erg_type::value::{GenTypeObj, TypeKind, TypeObj, ValueObj}; -use erg_type::{ParamTy, SubrType, TyBound, Type}; +use erg_type::{ParamTy, SubrType, Type}; use crate::build_hir::HIRBuilder; use crate::context::{ @@ -25,6 +25,7 @@ use crate::error::readable_name; use crate::error::{ CompileResult, SingleTyCheckResult, TyCheckError, TyCheckErrors, TyCheckResult, }; +use crate::hir; use crate::hir::Literal; use crate::mod_cache::SharedModuleCache; use crate::varinfo::{Mutability, ParamIdx, VarInfo, VarKind}; @@ -33,7 +34,7 @@ use RegistrationMode::*; use Visibility::*; use super::instantiate::TyVarContext; -use super::ImportKind; +use super::OperationKind; impl Context { /// If it is a constant that is defined, there must be no variable of the same name defined across all scopes @@ -856,7 +857,7 @@ impl Context { pub(crate) fn import_mod( &mut self, - kind: ImportKind, + kind: OperationKind, mod_name: &Literal, ) -> CompileResult { if kind.is_erg_import() { @@ -1031,11 +1032,32 @@ impl Context { Ok(path) } - pub(crate) fn _push_subtype_bound(&mut self, sub: Type, sup: Type) { - self.bounds.push(TyBound::subtype_of(sub, sup)); - } - - pub(crate) fn _push_instance_bound(&mut self, name: Str, t: Type) { - self.bounds.push(TyBound::instance(name, t)); + pub fn del(&mut self, ident: &hir::Identifier) -> CompileResult<()> { + if self.rec_get_const_obj(ident.inspect()).is_some() + || self + .get_builtins() + .unwrap() + .get_local_kv(ident.inspect()) + .is_some() + { + Err(TyCheckErrors::from(TyCheckError::del_error( + self.cfg.input.clone(), + line!() as usize, + ident, + self.caused_by(), + ))) + } else if self.locals.get(ident.inspect()).is_some() { + self.locals.remove(ident.inspect()); + Ok(()) + } else { + Err(TyCheckErrors::from(TyCheckError::no_var_error( + self.cfg.input.clone(), + line!() as usize, + ident.loc(), + self.caused_by(), + ident.inspect(), + self.get_similar_name(ident.inspect()), + ))) + } } } diff --git a/compiler/erg_compiler/error.rs b/compiler/erg_compiler/error.rs index 28de3cab..576e8a6c 100644 --- a/compiler/erg_compiler/error.rs +++ b/compiler/erg_compiler/error.rs @@ -16,7 +16,7 @@ use erg_parser::error::{ParserRunnerError, ParserRunnerErrors}; use erg_type::{Predicate, Type}; -use crate::hir::Expr; +use crate::hir::{Expr, Identifier}; /// dname is for "double under name" pub fn binop_to_dname(op: &str) -> &str { @@ -1305,6 +1305,26 @@ impl LowerError { ) } + pub fn del_error(input: Input, errno: usize, ident: &Identifier, caused_by: AtomicStr) -> Self { + let name = readable_name(ident.inspect()); + Self::new( + ErrorCore::new( + errno, + NameError, + ident.loc(), + switch_lang!( + "japanese" => format!("{YELLOW}{name}{RESET}は削除できません"), + "simplified_chinese" => format!("{YELLOW}{name}{RESET}不能删除"), + "traditional_chinese" => format!("{YELLOW}{name}{RESET}不能刪除"), + "english" => format!("{YELLOW}{name}{RESET} cannot be deleted"), + ), + None, + ), + input, + caused_by, + ) + } + pub fn visibility_error( input: Input, errno: usize, diff --git a/compiler/erg_compiler/hir.rs b/compiler/erg_compiler/hir.rs index 56041e4b..9aae0446 100644 --- a/compiler/erg_compiler/hir.rs +++ b/compiler/erg_compiler/hir.rs @@ -20,7 +20,7 @@ use erg_type::value::{TypeKind, ValueObj}; use erg_type::{impl_t, impl_t_for_enum, HasType, Type}; use crate::context::eval::type_from_token_kind; -use crate::context::ImportKind; +use crate::context::OperationKind; use crate::error::readable_name; #[derive(Debug, Clone)] @@ -1011,10 +1011,11 @@ impl Call { } } - pub fn import_kind(&self) -> Option { + pub fn additional_operation(&self) -> Option { self.obj.show_acc().and_then(|s| match &s[..] { - "import" => Some(ImportKind::ErgImport), - "pyimport" | "py" => Some(ImportKind::PyImport), + "import" => Some(OperationKind::Import), + "pyimport" | "py" => Some(OperationKind::PyImport), + "Del" => Some(OperationKind::Del), _ => None, }) } diff --git a/compiler/erg_compiler/link.rs b/compiler/erg_compiler/link.rs index 215019a2..23e114cb 100644 --- a/compiler/erg_compiler/link.rs +++ b/compiler/erg_compiler/link.rs @@ -14,7 +14,7 @@ use erg_type::typaram::TyParam; use erg_type::value::ValueObj; use erg_type::{HasType, Type}; -use crate::context::ImportKind; +use crate::context::OperationKind; use crate::hir::*; use crate::mod_cache::SharedModuleCache; @@ -85,14 +85,14 @@ impl<'a> Linker<'a> { Expr::UnaryOp(unaryop) => { self.replace_import(&mut unaryop.expr); } - Expr::Call(call) => match call.import_kind() { - Some(ImportKind::ErgImport) => { + Expr::Call(call) => match call.additional_operation() { + Some(OperationKind::Import) => { self.replace_erg_import(expr); } - Some(ImportKind::PyImport) => { + Some(OperationKind::PyImport) => { self.replace_py_import(expr); } - None => { + _ => { for arg in call.args.pos_args.iter_mut() { self.replace_import(&mut arg.expr); } diff --git a/compiler/erg_compiler/lower.rs b/compiler/erg_compiler/lower.rs index 4ff0ec1a..e9e48596 100644 --- a/compiler/erg_compiler/lower.rs +++ b/compiler/erg_compiler/lower.rs @@ -24,7 +24,7 @@ use erg_type::value::{GenTypeObj, TypeKind, TypeObj, ValueObj}; use erg_type::{HasType, ParamTy, Type}; use crate::context::instantiate::TyVarContext; -use crate::context::{ClassDefType, Context, ContextKind, RegistrationMode}; +use crate::context::{ClassDefType, Context, ContextKind, OperationKind, RegistrationMode}; use crate::error::{ CompileError, CompileErrors, LowerError, LowerErrors, LowerResult, LowerWarnings, SingleLowerResult, @@ -457,11 +457,30 @@ impl ASTLowerer { None }; let call = hir::Call::new(obj, method_name, hir_args, sig_t); - if let Some(kind) = call.import_kind() { - let mod_name = enum_unwrap!(call.args.get_left_or_key("Path").unwrap(), hir::Expr::Lit); - if let Err(errs) = self.ctx.import_mod(kind, mod_name) { - self.errs.extend(errs.into_iter()); - }; + match call.additional_operation() { + Some(kind @ (OperationKind::Import | OperationKind::PyImport)) => { + let mod_name = + enum_unwrap!(call.args.get_left_or_key("Path").unwrap(), hir::Expr::Lit); + if let Err(errs) = self.ctx.import_mod(kind, mod_name) { + self.errs.extend(errs.into_iter()); + }; + } + Some(OperationKind::Del) => match call.args.get_left_or_key("obj").unwrap() { + hir::Expr::Accessor(hir::Accessor::Ident(ident)) => { + self.ctx.del(ident)?; + } + other => { + return Err(LowerErrors::from(LowerError::syntax_error( + self.input().clone(), + line!() as usize, + other.loc(), + self.ctx.caused_by(), + "", + None, + ))) + } + }, + _ => {} } Ok(call) } diff --git a/doc/JA/syntax/12_dict.md b/doc/JA/syntax/12_dict.md index 900ac84e..7b9f4231 100644 --- a/doc/JA/syntax/12_dict.md +++ b/doc/JA/syntax/12_dict.md @@ -5,7 +5,7 @@ Dictはキーと値のペアを持つコレクションです。 ```python -ids = {"Alice": 145, "Bob": 214, "Charlie": 301} +ids = {"Alice" >: 145, "Bob": 214, "Charlie": 301} assert ids["Alice"] == 145 ```