diff --git a/compiler/erg_common/error.rs b/compiler/erg_common/error.rs index 90e16a86..e00438bc 100644 --- a/compiler/erg_common/error.rs +++ b/compiler/erg_common/error.rs @@ -488,8 +488,22 @@ pub trait ErrorDisplay { } res + RESET } - Location::LineRange(_begin, _end) => { - todo!() + Location::LineRange(ln_begin, ln_end) => { + let codes = if self.input() == &Input::REPL { + vec![self.input().reread()] + } else { + self.input().reread_lines(ln_begin, ln_end) + }; + let mut res = CYAN.to_string(); + for (i, lineno) in (ln_begin..=ln_end).enumerate() { + let mut pointer = " ".repeat(lineno.to_string().len() + 2); // +2 means `| ` + pointer += &"^".repeat(cmp::max(1, codes[i].len())); + res += &format!( + "{lineno}{VBAR_UNICODE} {code}\n{pointer}\n", + code = codes[i] + ); + } + res + RESET } Location::Line(lineno) => { let code = if self.input() == &Input::REPL { diff --git a/compiler/erg_common/vis.rs b/compiler/erg_common/vis.rs index 4a43778c..ad1c8079 100644 --- a/compiler/erg_common/vis.rs +++ b/compiler/erg_common/vis.rs @@ -22,8 +22,8 @@ impl Visibility { /// same structure as `Identifier`, but only for Record fields. #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct Field { - vis: Visibility, - symbol: Str, + pub vis: Visibility, + pub symbol: Str, } impl fmt::Display for Field { diff --git a/compiler/erg_compiler/codegen.rs b/compiler/erg_compiler/codegen.rs index 837fc64f..7d6e8733 100644 --- a/compiler/erg_compiler/codegen.rs +++ b/compiler/erg_compiler/codegen.rs @@ -13,21 +13,25 @@ use erg_common::Str; use erg_common::{ debug_power_assert, enum_unwrap, fn_name_full, impl_stream_for_wrapper, log, switch_unreachable, }; +use erg_parser::ast::DefId; use erg_type::codeobj::{CodeObj, CodeObjFlags}; use Opcode::*; -use erg_parser::ast::{Identifier, ParamPattern, Params, VarName}; +use erg_parser::ast::{Identifier, ParamPattern, ParamSignature, Params, VarName}; use erg_parser::token::{Token, TokenKind}; +use erg_type::free::fresh_varname; use erg_type::value::TypeKind; use erg_type::value::ValueObj; -use erg_type::{HasType, TypeCode, TypePair}; +use erg_type::{HasType, Type, TypeCode, TypePair}; use crate::compile::{AccessKind, Name, StoreLoadKind}; use crate::context::eval::eval_lit; use crate::error::{CompileError, CompileErrors, CompileResult}; +use crate::hir::AttrDef; +use crate::hir::Attribute; use crate::hir::{ - Accessor, Args, Array, Block, Call, ClassDef, DefBody, Expr, Local, RecordAttrs, Signature, + Accessor, Args, Array, Block, Call, ClassDef, Def, DefBody, Expr, Local, Signature, SubrSignature, Tuple, VarSignature, HIR, }; use AccessKind::*; @@ -197,6 +201,7 @@ fn convert_to_python_attr(class: &str, uniq_obj_name: Option<&str>, name: Str) - ("Array!", _, "push!") => Str::ever("append"), ("Complex" | "Real" | "Int" | "Nat" | "Float", _, "Real") => Str::ever("real"), ("Complex" | "Real" | "Int" | "Nat" | "Float", _, "Imag") => Str::ever("imag"), + ("Type", _, "new" | "__new__") => Str::ever("__call__"), ("StringIO!", _, "getvalue!") => Str::ever("getvalue"), ("Module", Some("importlib"), "reload!") => Str::ever("reload"), ("Module", Some("random"), "randint!") => Str::ever("randint"), @@ -644,6 +649,25 @@ impl CodeGenerator { self.stack_dec(); } + fn store_acc(&mut self, acc: Accessor) { + match acc { + Accessor::Local(local) => { + self.emit_store_instr(Identifier::new(None, VarName::new(local.name)), Name); + } + Accessor::Public(public) => { + self.emit_store_instr( + Identifier::new(Some(public.dot), VarName::new(public.name)), + Name, + ); + } + Accessor::Attr(attr) => { + self.codegen_expr(*attr.obj); + self.emit_store_instr(Identifier::new(None, VarName::new(attr.name)), Attr); + } + acc => todo!("store: {acc}"), + } + } + fn emit_pop_top(&mut self) { self.write_instr(Opcode::POP_TOP); self.write_arg(0u8); @@ -686,38 +710,46 @@ impl CodeGenerator { .collect() } - fn emit_linked_type_def(&mut self, type_def: ClassDef) { - match type_def.def.sig { - Signature::Var(var) => match type_def.kind { - TypeKind::Class => self.emit_mono_class_def(var, type_def.public_methods), - TypeKind::InheritedClass => { - todo!() - } - other => todo!("{other:?} is not supported"), - }, - Signature::Subr(_) => todo!("polymorphic type definition"), - } - } - - fn emit_mono_class_def(&mut self, sig: VarSignature, methods: RecordAttrs) { + fn emit_class_def(&mut self, class_def: ClassDef) { + let ident = class_def.sig.ident().clone(); + let kind = class_def.kind; + let require_or_sup = class_def.require_or_sup.clone(); self.write_instr(Opcode::LOAD_BUILD_CLASS); self.write_arg(0); self.stack_inc(); - let code = self.codegen_typedef_block(sig.inspect().clone(), methods); + let code = self.codegen_typedef_block(class_def); self.emit_load_const(code); - self.emit_load_const(sig.inspect().clone()); + self.emit_load_const(ident.inspect().clone()); self.write_instr(Opcode::MAKE_FUNCTION); self.write_arg(0); - self.emit_load_const(sig.inspect().clone()); + self.emit_load_const(ident.inspect().clone()); + let subclasses_len = self.emit_require_type(kind, *require_or_sup); + // LOAD subclasses self.write_instr(Opcode::CALL_FUNCTION); - self.write_arg(2); - self.stack_dec_n((1 + 2) - 1); - self.emit_store_instr(sig.ident, Name); + self.write_arg(2 + subclasses_len as u8); + self.stack_dec_n((1 + 2 + subclasses_len) - 1); + self.emit_store_instr(ident, Name); } // NOTE: use `TypeVar`, `Generic` in `typing` module // fn emit_poly_type_def(&mut self, sig: SubrSignature, body: DefBody) {} + fn emit_require_type(&mut self, kind: TypeKind, require_or_sup: Expr) -> usize { + match kind { + TypeKind::Class => 0, + TypeKind::Subclass => { + self.codegen_expr(require_or_sup); + 1 // TODO: not always 1 + } + _ => todo!(), + } + } + + fn emit_attr_def(&mut self, attr_def: AttrDef) { + self.codegen_frameless_block(attr_def.block, vec![]); + self.store_acc(attr_def.attr); + } + fn emit_var_def(&mut self, sig: VarSignature, mut body: DefBody) { if body.block.len() == 1 { self.codegen_expr(body.block.remove(0)); @@ -971,6 +1003,9 @@ impl CodeGenerator { } fn emit_call_method(&mut self, obj: Expr, method_name: Token, mut args: Args) { + if &method_name.inspect()[..] == "update!" { + return self.emit_call_update(obj, args); + } let class = obj.ref_t().name(); // これは必ずmethodのあるクラスになっている let uniq_obj_name = obj.__name__().map(Str::rc); self.codegen_expr(obj); @@ -1005,6 +1040,21 @@ impl CodeGenerator { self.stack_dec_n((1 + argc + kwsc) - 1); } + /// X.update! x -> x + 1 + /// X = (x -> x + 1)(X) + /// X = X + 1 + fn emit_call_update(&mut self, obj: Expr, mut args: Args) { + let acc = enum_unwrap!(obj, Expr::Accessor); + let func = args.remove_left_or_key("f").unwrap(); + self.codegen_expr(func); + self.codegen_acc(acc.clone()); + self.write_instr(CALL_FUNCTION); + self.write_arg(1 as u8); + // (1 (subroutine) + argc) input objects -> 1 return object + self.stack_dec_n((1 + 1) - 1); + self.store_acc(acc); + } + // assert takes 1 or 2 arguments (0: cond, 1: message) fn emit_assert_instr(&mut self, mut args: Args) -> CompileResult<()> { self.codegen_expr(args.remove(0)); @@ -1066,7 +1116,8 @@ impl CodeGenerator { Signature::Subr(sig) => self.emit_subr_def(sig, def.body), Signature::Var(sig) => self.emit_var_def(sig, def.body), }, - Expr::ClassDef(def) => self.emit_linked_type_def(def), + Expr::ClassDef(class) => self.emit_class_def(class), + Expr::AttrDef(attr) => self.emit_attr_def(attr), // TODO: Expr::Lambda(lambda) => { let params = self.gen_param_names(&lambda.params); @@ -1323,22 +1374,42 @@ impl CodeGenerator { self.cancel_pop_top(); } - fn codegen_typedef_block(&mut self, name: Str, methods: RecordAttrs) -> CodeObj { + fn codegen_typedef_block(&mut self, class: ClassDef) -> CodeObj { + let name = class.sig.ident().inspect().clone(); self.unit_size += 1; + let firstlineno = match ( + class.private_methods.get(0).and_then(|def| def.ln_begin()), + class.public_methods.get(0).and_then(|def| def.ln_begin()), + ) { + (Some(l), Some(r)) => l.min(r), + (Some(line), None) | (None, Some(line)) => line, + (None, None) => class.sig.ln_begin().unwrap(), + }; self.units.push(CodeGenUnit::new( self.unit_size, vec![], Str::rc(self.cfg.input.enclosed_name()), &name, - methods[0].ln_begin().unwrap(), + firstlineno, )); let mod_name = self.toplevel_block_codeobj().name.clone(); self.emit_load_const(mod_name); self.emit_store_instr(Identifier::public("__module__"), Attr); self.emit_load_const(name); self.emit_store_instr(Identifier::public("__qualname__"), Attr); + if class.need_to_gen_new { + self.emit_auto_new(&class.sig, class.__new__); + } // TODO: サブルーチンはT.subという書式でSTORE - for def in methods.into_iter() { + for def in class.private_methods.into_iter() { + self.codegen_expr(Expr::Def(def)); + // TODO: discard + if self.cur_block().stack_len == 1 { + self.emit_pop_top(); + } + } + for mut def in class.public_methods.into_iter() { + def.sig.ident_mut().dot = Some(Token::dummy()); self.codegen_expr(Expr::Def(def)); // TODO: discard if self.cur_block().stack_len == 1 { @@ -1378,6 +1449,62 @@ impl CodeGenerator { unit.codeobj } + fn emit_auto_new(&mut self, sig: &Signature, __new__: Type) { + let line = sig.ln_begin().unwrap(); + let ident = Identifier::private_with_line(Str::ever("__new__"), line); + let param_name = fresh_varname(); + let param = VarName::from_str_and_line(Str::from(param_name.clone()), line); + let params = Params::new( + vec![ParamSignature::new( + ParamPattern::VarName(param), + None, + None, + )], + None, + vec![], + None, + ); + let sig = Signature::Subr(SubrSignature::new(ident, params.clone(), __new__.clone())); + let mut attrs = vec![]; + match __new__.non_default_params().unwrap()[0].typ() { + // {x = Int; y = Int} + // self.x = %x.x; self.y = %x.y + Type::Record(rec) => { + for field in rec.keys() { + let obj = Expr::Accessor(Accessor::local( + Token::symbol_with_line(¶m_name[..], line), + Type::Failure, + )); + let attr = Accessor::Attr(Attribute::new( + obj, + Token::symbol(&field.symbol[..]), + Type::Failure, + )); + let obj = Expr::Accessor(Accessor::local( + Token::symbol_with_line("self", line), + Type::Failure, + )); + let expr = Expr::Accessor(Accessor::Attr(Attribute::new( + obj, + Token::symbol(&field.symbol[..]), + Type::Failure, + ))); + let attr_def = AttrDef::new(attr, Block::new(vec![expr])); + attrs.push(Expr::AttrDef(attr_def)); + } + } + other => todo!("{other}"), + } + let block = Block::new(attrs); + let body = DefBody::new(Token::dummy(), block, DefId(0)); + let private_new_def = Def::new(sig, body.clone()); + self.codegen_expr(Expr::Def(private_new_def)); + let ident = Identifier::public_with_line(Token::dummy(), Str::ever("new"), line); + let sig = Signature::Subr(SubrSignature::new(ident, params, __new__)); + let new_def = Def::new(sig, body); + self.codegen_expr(Expr::Def(new_def)); + } + fn codegen_block(&mut self, block: Block, opt_name: Option, params: Vec) -> CodeObj { self.unit_size += 1; let name = if let Some(name) = opt_name { diff --git a/compiler/erg_compiler/context/initialize/const_func.rs b/compiler/erg_compiler/context/initialize/const_func.rs index a454f509..863739e0 100644 --- a/compiler/erg_compiler/context/initialize/const_func.rs +++ b/compiler/erg_compiler/context/initialize/const_func.rs @@ -1,6 +1,8 @@ +use std::mem; + use erg_common::Str; -use erg_type::constructors::mono; +use erg_type::constructors::{and, mono}; use erg_type::value::{TypeKind, TypeObj, ValueObj}; use erg_type::Type; use erg_type::ValueArgs; @@ -19,9 +21,9 @@ fn value_obj_to_t(value: ValueObj) -> TypeObj { /// Requirement: Type, Impl := Type -> Class pub fn class_func(mut args: ValueArgs, __name__: Option) -> ValueObj { - let require = args.pos_args.remove(0); + let require = args.remove_left_or_key("Requirement").unwrap(); let require = value_obj_to_t(require); - let impls = args.pos_args.pop().or_else(|| args.kw_args.remove("Impl")); + let impls = args.remove_left_or_key("Impl"); let impls = impls.map(|v| value_obj_to_t(v)); let t = mono(__name__.unwrap_or(Str::ever(""))); ValueObj::gen_t(TypeKind::Class, t, require, impls, None) @@ -29,21 +31,34 @@ pub fn class_func(mut args: ValueArgs, __name__: Option) -> ValueObj { /// Super: Type, Impl := Type, Additional := Type -> Class pub fn inherit_func(mut args: ValueArgs, __name__: Option) -> ValueObj { - let sup = args.pos_args.remove(0); + let sup = args.remove_left_or_key("Super").unwrap(); let sup = value_obj_to_t(sup); - let impls = args.pos_args.pop().or_else(|| args.kw_args.remove("Impl")); + let impls = args.remove_left_or_key("Impl"); let impls = impls.map(|v| value_obj_to_t(v)); - let additional = args - .pos_args - .pop() - .or_else(|| args.kw_args.remove("Additional")); + let additional = args.remove_left_or_key("Additional"); let additional = additional.map(|v| value_obj_to_t(v)); let t = mono(__name__.unwrap_or(Str::ever(""))); - ValueObj::gen_t(TypeKind::InheritedClass, t, sup, impls, additional) + ValueObj::gen_t(TypeKind::Subclass, t, sup, impls, additional) } -/// Class -> Class +/// Class -> Class (with `Inheritable`) /// This function is used by the compiler to mark a class as inheritable and does nothing in terms of actual operation. pub fn inheritable_func(args: ValueArgs, __name__: Option) -> ValueObj { - args.pos_args.into_iter().next().unwrap() + let class = args.pos_args.into_iter().next().unwrap(); + match class { + ValueObj::Type(TypeObj::Generated(mut gen)) => { + if let Some(typ) = &mut gen.impls { + match typ.as_mut() { + TypeObj::Generated(gen) => { + gen.t = and(mem::take(&mut gen.t), mono("Inheritable")); + } + TypeObj::Builtin(t) => { + *t = and(mem::take(t), mono("Inheritable")); + } + } + } + ValueObj::Type(TypeObj::Generated(gen)) + } + _ => todo!(), + } } diff --git a/compiler/erg_compiler/context/initialize/mod.rs b/compiler/erg_compiler/context/initialize/mod.rs index cedbd159..1cfb15d3 100644 --- a/compiler/erg_compiler/context/initialize/mod.rs +++ b/compiler/erg_compiler/context/initialize/mod.rs @@ -57,6 +57,7 @@ impl Context { if self.rec_get_const_obj(name).is_some() { panic!("already registered: {name}"); } else { + // TODO: not all value objects are comparable let vi = VarInfo::new(enum_t(set! {obj.clone()}), Const, Private, Builtin); self.consts.insert(VarName::from_str(Str::rc(name)), obj); self.locals.insert(VarName::from_str(Str::rc(name)), vi); @@ -360,8 +361,6 @@ impl Context { obj.register_builtin_impl("__dict__", fn0_met(Obj, dict(Str, Obj)), Immutable, Public); obj.register_builtin_impl("__bytes__", fn0_met(Obj, mono("Bytes")), Immutable, Public); obj.register_builtin_const("MutType!", ValueObj::builtin_t(mono("Obj!"))); - // let mut record = Self::mono_trait("Record", vec![Obj], Self::TOP_LEVEL); - // let mut class = Self::mono_class("Class", vec![Type, Obj], Self::TOP_LEVEL); let mut int = Self::mono_class( "Int", vec![Ratio, Obj], @@ -1089,7 +1088,7 @@ impl Context { vec![param_t("Impl", Type)], Class, ); - let class = ConstSubr::Builtin(BuiltinConstSubr::new(class_func, class_t)); + let class = ConstSubr::Builtin(BuiltinConstSubr::new("Class", class_func, class_t)); self.register_builtin_const("Class", ValueObj::Subr(class)); let inherit_t = func( vec![param_t("Super", Class)], @@ -1097,11 +1096,15 @@ impl Context { vec![param_t("Impl", Type), param_t("Additional", Type)], Class, ); - let inherit = ConstSubr::Builtin(BuiltinConstSubr::new(inherit_func, inherit_t)); + let inherit = ConstSubr::Builtin(BuiltinConstSubr::new("Inherit", inherit_func, inherit_t)); self.register_builtin_const("Inherit", ValueObj::Subr(inherit)); // decorators - let inheritable = - ConstSubr::Builtin(BuiltinConstSubr::new(inheritable_func, func1(Class, Class))); + let inheritable_t = func1(Class, Class); + let inheritable = ConstSubr::Builtin(BuiltinConstSubr::new( + "Inheritable", + inheritable_func, + inheritable_t, + )); self.register_builtin_const("Inheritable", ValueObj::Subr(inheritable)); } diff --git a/compiler/erg_compiler/context/register.rs b/compiler/erg_compiler/context/register.rs index 534fec46..34161f20 100644 --- a/compiler/erg_compiler/context/register.rs +++ b/compiler/erg_compiler/context/register.rs @@ -525,6 +525,7 @@ impl Context { let gen = enum_unwrap!(t, TypeObj::Generated); self.register_gen_type(gen); } + // TODO: not all value objects are comparable other => { let id = DefId(get_hash(name)); let vi = VarInfo::new( @@ -556,7 +557,7 @@ impl Context { todo!() } } - TypeKind::InheritedClass => { + TypeKind::Subclass => { if gen.t.is_monomorphic() { let super_classes = vec![gen.require_or_sup.typ().clone()]; let super_traits = gen.impls.iter().map(|to| to.typ().clone()).collect(); @@ -568,6 +569,8 @@ impl Context { TypeObj::Builtin(t) => t, TypeObj::Generated(t) => t.require_or_sup.as_ref().typ(), }; + // `Super.Requirement := {x = Int}` and `Self.Additional := {y = Int}` + // => `Self.Requirement := {x = Int; y = Int}` let param_t = if let Some(additional) = &gen.additional { self.rec_intersection(¶m_t, additional.typ()) } else { diff --git a/compiler/erg_compiler/context/tyvar.rs b/compiler/erg_compiler/context/tyvar.rs index 5e4245a5..59ded596 100644 --- a/compiler/erg_compiler/context/tyvar.rs +++ b/compiler/erg_compiler/context/tyvar.rs @@ -493,6 +493,13 @@ impl Context { } Ok(()) } + hir::Expr::AttrDef(attr_def) => { + // REVIEW: attr_def.attr is not dereferenced + for chunk in attr_def.block.iter_mut() { + self.deref_expr_t(chunk)?; + } + Ok(()) + } } } diff --git a/compiler/erg_compiler/hir.rs b/compiler/erg_compiler/hir.rs index 11f3294d..d439ae12 100644 --- a/compiler/erg_compiler/hir.rs +++ b/compiler/erg_compiler/hir.rs @@ -243,6 +243,22 @@ impl Args { .map(|a| &a.expr) } } + + pub fn remove_left_or_key(&mut self, key: &str) -> Option { + if !self.pos_args.is_empty() { + Some(self.pos_args.remove(0).expr) + } else { + if let Some(pos) = self + .kw_args + .iter() + .position(|arg| &arg.keyword.inspect()[..] == key) + { + Some(self.kw_args.remove(pos).expr) + } else { + None + } + } + } } /// represents local variables @@ -894,9 +910,9 @@ impl NestedDisplay for Call { fn fmt_nest(&self, f: &mut std::fmt::Formatter<'_>, level: usize) -> std::fmt::Result { writeln!( f, - "({}){}(: {}):", + "({}){} (: {}):", self.obj, - fmt_option!(pre ".", self.method_name), + fmt_option!(pre ".", self.method_name.as_ref().map(|t| t.inspect())), self.sig_t )?; self.args.fmt_nest(f, level + 1) @@ -1011,6 +1027,7 @@ impl NestedDisplay for VarSignature { impl_display_from_nested!(VarSignature); impl_locational!(VarSignature, ident); +impl_t!(VarSignature); impl VarSignature { pub const fn new(ident: Identifier, t: Type) -> Self { @@ -1041,6 +1058,7 @@ impl NestedDisplay for SubrSignature { impl_display_from_nested!(SubrSignature); impl_locational!(SubrSignature, ident, params); +impl_t!(SubrSignature); impl SubrSignature { pub const fn new(ident: Identifier, params: Params, t: Type) -> Self { @@ -1096,6 +1114,7 @@ pub enum Signature { impl_nested_display_for_chunk_enum!(Signature; Var, Subr); impl_display_for_enum!(Signature; Var, Subr,); +impl_t_for_enum!(Signature; Var, Subr); impl_locational_for_enum!(Signature; Var, Subr,); impl Signature { @@ -1130,6 +1149,13 @@ impl Signature { Self::Subr(s) => &s.ident, } } + + pub fn ident_mut(&mut self) -> &mut Identifier { + match self { + Self::Var(v) => &mut v.ident, + Self::Subr(s) => &mut s.ident, + } + } } /// represents a declaration of a variable @@ -1254,23 +1280,23 @@ impl Def { } #[derive(Debug, Clone)] -pub struct MethodDefs { +pub struct Methods { pub class: TypeSpec, pub vis: Token, // `.` or `::` pub defs: RecordAttrs, // TODO: allow declaration } -impl NestedDisplay for MethodDefs { +impl NestedDisplay for Methods { fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, level: usize) -> fmt::Result { writeln!(f, "{}{}", self.class, self.vis.content)?; self.defs.fmt_nest(f, level + 1) } } -impl_display_from_nested!(MethodDefs); -impl_locational!(MethodDefs, class, defs); +impl_display_from_nested!(Methods); +impl_locational!(Methods, class, defs); -impl HasType for MethodDefs { +impl HasType for Methods { #[inline] fn ref_t(&self) -> &Type { Type::NONE @@ -1289,7 +1315,7 @@ impl HasType for MethodDefs { } } -impl MethodDefs { +impl Methods { pub const fn new(class: TypeSpec, vis: Token, defs: RecordAttrs) -> Self { Self { class, vis, defs } } @@ -1298,21 +1324,25 @@ impl MethodDefs { #[derive(Debug, Clone)] pub struct ClassDef { pub kind: TypeKind, - pub def: Def, + pub sig: Signature, + pub require_or_sup: Box, + /// The type of `new` and `__new__` that is automatically defined if not defined + pub need_to_gen_new: bool, + pub __new__: Type, pub private_methods: RecordAttrs, pub public_methods: RecordAttrs, } impl NestedDisplay for ClassDef { fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, level: usize) -> fmt::Result { - self.def.fmt_nest(f, level)?; + self.sig.fmt_nest(f, level)?; self.private_methods.fmt_nest(f, level)?; self.public_methods.fmt_nest(f, level + 1) } } impl_display_from_nested!(ClassDef); -impl_locational!(ClassDef, def); +impl_locational!(ClassDef, sig); impl HasType for ClassDef { #[inline] @@ -1334,21 +1364,69 @@ impl HasType for ClassDef { } impl ClassDef { - pub const fn new( + pub fn new( kind: TypeKind, - def: Def, + sig: Signature, + require_or_sup: Expr, + need_to_gen_new: bool, + __new__: Type, private_methods: RecordAttrs, public_methods: RecordAttrs, ) -> Self { Self { kind, - def, + sig, + require_or_sup: Box::new(require_or_sup), + need_to_gen_new, + __new__, private_methods, public_methods, } } } +#[derive(Debug, Clone)] +pub struct AttrDef { + pub attr: Accessor, + pub block: Block, +} + +impl NestedDisplay for AttrDef { + fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, level: usize) -> fmt::Result { + self.attr.fmt_nest(f, level)?; + writeln!(f, " = ")?; + self.block.fmt_nest(f, level + 1) + } +} + +impl_display_from_nested!(AttrDef); +impl_locational!(AttrDef, attr, block); + +impl HasType for AttrDef { + #[inline] + fn ref_t(&self) -> &Type { + Type::NONE + } + #[inline] + fn ref_mut_t(&mut self) -> &mut Type { + todo!() + } + #[inline] + fn signature_t(&self) -> Option<&Type> { + None + } + #[inline] + fn signature_mut_t(&mut self) -> Option<&mut Type> { + None + } +} + +impl AttrDef { + pub const fn new(attr: Accessor, block: Block) -> Self { + Self { attr, block } + } +} + #[derive(Debug, Clone)] pub enum Expr { Lit(Literal), @@ -1365,12 +1443,13 @@ pub enum Expr { Decl(Decl), Def(Def), ClassDef(ClassDef), + AttrDef(AttrDef), } -impl_nested_display_for_chunk_enum!(Expr; Lit, Accessor, Array, Tuple, Dict, Record, BinOp, UnaryOp, Call, Lambda, Decl, Def, ClassDef); +impl_nested_display_for_chunk_enum!(Expr; Lit, Accessor, Array, Tuple, Dict, Record, BinOp, UnaryOp, Call, Lambda, Decl, Def, ClassDef, AttrDef); impl_display_from_nested!(Expr); -impl_locational_for_enum!(Expr; Lit, Accessor, Array, Tuple, Dict, Record, BinOp, UnaryOp, Call, Lambda, Decl, Def, ClassDef); -impl_t_for_enum!(Expr; Lit, Accessor, Array, Tuple, Dict, Record, BinOp, UnaryOp, Call, Lambda, Decl, Def, ClassDef); +impl_locational_for_enum!(Expr; Lit, Accessor, Array, Tuple, Dict, Record, BinOp, UnaryOp, Call, Lambda, Decl, Def, ClassDef, AttrDef); +impl_t_for_enum!(Expr; Lit, Accessor, Array, Tuple, Dict, Record, BinOp, UnaryOp, Call, Lambda, Decl, Def, ClassDef, AttrDef); impl Expr { pub fn receiver_t(&self) -> Option<&Type> { diff --git a/compiler/erg_compiler/lower.rs b/compiler/erg_compiler/lower.rs index 84055c79..59560f99 100644 --- a/compiler/erg_compiler/lower.rs +++ b/compiler/erg_compiler/lower.rs @@ -13,13 +13,14 @@ use erg_parser::token::{Token, TokenKind}; use erg_type::constructors::{array, array_mut, free_var, func, mono, poly, proc, quant}; use erg_type::free::Constraint; use erg_type::typaram::TyParam; -use erg_type::value::{TypeKind, ValueObj}; +use erg_type::value::{TypeObj, ValueObj}; use erg_type::{HasType, ParamTy, Type}; use crate::context::{Context, ContextKind, RegistrationMode}; use crate::error::{LowerError, LowerErrors, LowerResult, LowerWarnings}; use crate::hir; use crate::hir::HIR; +use crate::varinfo::VarKind; use Visibility::*; /// Singleton that checks types of an AST, and convert (lower) it into a HIR @@ -548,7 +549,7 @@ impl ASTLowerer { fn lower_class_def(&mut self, class_def: ast::ClassDef) -> LowerResult { log!(info "entered {}({class_def})", fn_name!()); - let hir_def = self.lower_def(class_def.def)?; + let mut hir_def = self.lower_def(class_def.def)?; let mut private_methods = hir::RecordAttrs::empty(); let mut public_methods = hir::RecordAttrs::empty(); for methods in class_def.methods_list.into_iter() { @@ -581,22 +582,44 @@ impl ASTLowerer { } } } - let definition = hir_def.body.block.first().unwrap(); - let call = enum_unwrap!(definition, hir::Expr::Call); - // FIXME: - let kind = match &call.obj.var_full_name().unwrap()[..] { - "Class" | "Inheritable" => TypeKind::Class, - "Inherit" => TypeKind::InheritedClass, - _ => unreachable!(), + let (_, ctx) = self + .ctx + .rec_get_nominal_type_ctx(&mono(hir_def.sig.ident().inspect())) + .unwrap(); + let type_obj = enum_unwrap!(self.ctx.rec_get_const_obj(hir_def.sig.ident().inspect()).unwrap(), ValueObj::Type:(TypeObj::Generated:(_))); + // vi.t.non_default_params().unwrap()[0].typ().clone() + let (__new__, need_to_gen_new) = if let Some(vi) = ctx.get_current_scope_var("new") { + (vi.t.clone(), vi.kind == VarKind::Auto) + } else { + todo!() }; + let require_or_sup = self.get_require_or_sup(hir_def.body.block.remove(0)); Ok(hir::ClassDef::new( - kind, - hir_def, + type_obj.kind, + hir_def.sig, + require_or_sup, + need_to_gen_new, + __new__, private_methods, public_methods, )) } + fn get_require_or_sup(&self, expr: hir::Expr) -> hir::Expr { + match expr { + acc @ hir::Expr::Accessor(_) => acc, + hir::Expr::Call(mut call) => match call.obj.var_full_name().as_ref().map(|s| &s[..]) { + Some("Class") => call.args.remove_left_or_key("Requirement").unwrap(), + Some("Inherit") => call.args.remove_left_or_key("Super").unwrap(), + Some("Inheritable") => { + self.get_require_or_sup(call.args.remove_left_or_key("Class").unwrap()) + } + _ => todo!(), + }, + other => todo!("{other}"), + } + } + // Call.obj == Accessor cannot be type inferred by itself (it can only be inferred with arguments) // so turn off type checking (check=false) fn lower_expr(&mut self, expr: ast::Expr) -> LowerResult { diff --git a/compiler/erg_parser/ast.rs b/compiler/erg_parser/ast.rs index badcd3c8..8d6e8e45 100644 --- a/compiler/erg_parser/ast.rs +++ b/compiler/erg_parser/ast.rs @@ -1872,13 +1872,17 @@ impl Identifier { Self::new(None, VarName::from_str_and_line(name, line)) } + pub fn public_with_line(dot: Token, name: Str, line: usize) -> Self { + Self::new(Some(dot), VarName::from_str_and_line(name, line)) + } + pub fn is_const(&self) -> bool { self.name.is_const() } pub const fn vis(&self) -> Visibility { match &self.dot { - Some(_dot) => Visibility::Public, + Some(_) => Visibility::Public, None => Visibility::Private, } } diff --git a/compiler/erg_parser/token.rs b/compiler/erg_parser/token.rs index 52a78893..386a9117 100644 --- a/compiler/erg_parser/token.rs +++ b/compiler/erg_parser/token.rs @@ -376,6 +376,16 @@ impl Token { Self::from_str(TokenKind::Symbol, cont) } + #[inline] + pub fn symbol_with_line(cont: &str, line: usize) -> Self { + Token { + kind: TokenKind::Symbol, + content: Str::rc(cont), + lineno: line, + col_begin: 0, + } + } + pub const fn static_symbol(s: &'static str) -> Self { Token { kind: TokenKind::Symbol, diff --git a/compiler/erg_type/lib.rs b/compiler/erg_type/lib.rs index 29eb2054..793df2bf 100644 --- a/compiler/erg_type/lib.rs +++ b/compiler/erg_type/lib.rs @@ -142,17 +142,36 @@ impl ValueArgs { pub const fn new(pos_args: Vec, kw_args: Dict) -> Self { ValueArgs { pos_args, kw_args } } + + pub fn remove_left_or_key(&mut self, key: &str) -> Option { + if !self.pos_args.is_empty() { + Some(self.pos_args.remove(0)) + } else { + self.kw_args.remove(key) + } + } } #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct BuiltinConstSubr { + name: &'static str, subr: fn(ValueArgs, Option) -> ValueObj, t: Type, } +impl fmt::Display for BuiltinConstSubr { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "", self.name) + } +} + impl BuiltinConstSubr { - pub const fn new(subr: fn(ValueArgs, Option) -> ValueObj, t: Type) -> Self { - Self { subr, t } + pub const fn new( + name: &'static str, + subr: fn(ValueArgs, Option) -> ValueObj, + t: Type, + ) -> Self { + Self { name, subr, t } } } @@ -165,8 +184,10 @@ pub enum ConstSubr { impl fmt::Display for ConstSubr { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { - ConstSubr::User(_) => write!(f, ""), - ConstSubr::Builtin(_) => write!(f, ""), + ConstSubr::User(subr) => { + write!(f, "", subr.code.name) + } + ConstSubr::Builtin(subr) => write!(f, "{subr}"), } } } @@ -1840,6 +1861,13 @@ impl Type { } } + pub fn contains_intersec(&self, typ: &Type) -> bool { + match self { + Type::And(t1, t2) => t1.contains_intersec(typ) || t2.contains_intersec(typ), + _ => self == typ, + } + } + pub fn tvar_name(&self) -> Option { match self { Self::FreeVar(fv) => fv.unbound_name(), diff --git a/compiler/erg_type/value.rs b/compiler/erg_type/value.rs index a67ed21c..b5d5622f 100644 --- a/compiler/erg_type/value.rs +++ b/compiler/erg_type/value.rs @@ -25,9 +25,9 @@ use crate::{ConstSubr, HasType, Predicate, Type}; #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] pub enum TypeKind { Class, - InheritedClass, + Subclass, Trait, - SubsumedTrait, + Subtrait, StructuralTrait, } @@ -35,7 +35,7 @@ pub enum TypeKind { #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub struct GenTypeObj { pub kind: TypeKind, - pub t: Type, + pub t: Type, // andやorが入る可能性あり pub require_or_sup: Box, pub impls: Option>, pub additional: Option>, @@ -66,8 +66,8 @@ impl GenTypeObj { pub fn meta_type(&self) -> Type { match self.kind { - TypeKind::Class | TypeKind::InheritedClass => Type::Class, - TypeKind::Trait | TypeKind::SubsumedTrait | TypeKind::StructuralTrait => Type::Trait, + TypeKind::Class | TypeKind::Subclass => Type::Class, + TypeKind::Trait | TypeKind::Subtrait | TypeKind::StructuralTrait => Type::Trait, } } }