From d2ed27768529e059cb34be1656afe07c745c08b0 Mon Sep 17 00:00:00 2001 From: Shunsuke Shibayama Date: Fri, 2 Sep 2022 14:40:01 +0900 Subject: [PATCH 01/68] Impl `ShortenedRecord` desugaring --- compiler/erg_compiler/eval.rs | 9 +- compiler/erg_compiler/lower.rs | 10 ++- compiler/erg_parser/ast.rs | 48 ++++++++-- compiler/erg_parser/desugar.rs | 155 ++++++++++++++++++++++++++++++++- compiler/erg_parser/parse.rs | 82 ++++++++++++++--- examples/class.er | 6 +- 6 files changed, 281 insertions(+), 29 deletions(-) diff --git a/compiler/erg_compiler/eval.rs b/compiler/erg_compiler/eval.rs index 04113d61..6e5f20f0 100644 --- a/compiler/erg_compiler/eval.rs +++ b/compiler/erg_compiler/eval.rs @@ -264,7 +264,14 @@ impl Evaluator { Some(ValueObj::Array(RcArray::from(elems))) } - fn eval_const_record(&self, record: &NormalRecord, ctx: &Context) -> Option { + fn eval_const_record(&self, record: &Record, ctx: &Context) -> Option { + match record { + Record::Normal(rec) => self.eval_const_normal_record(rec, ctx), + Record::Shortened(_rec) => unreachable!(), // should be desugared + } + } + + fn eval_const_normal_record(&self, record: &NormalRecord, ctx: &Context) -> Option { let mut attrs = vec![]; for attr in record.attrs.iter() { if let Some(elem) = self.eval_const_block(&attr.body.block, ctx) { diff --git a/compiler/erg_compiler/lower.rs b/compiler/erg_compiler/lower.rs index 09206008..1afb6ff0 100644 --- a/compiler/erg_compiler/lower.rs +++ b/compiler/erg_compiler/lower.rs @@ -217,7 +217,15 @@ impl ASTLowerer { Ok(hir::NormalTuple::new(hir::Args::from(new_tuple))) } - fn lower_record(&mut self, record: ast::NormalRecord) -> LowerResult { + fn lower_record(&mut self, record: ast::Record) -> LowerResult { + log!(info "entered {}({record})", fn_name!()); + match record { + ast::Record::Normal(rec) => self.lower_normal_record(rec), + ast::Record::Shortened(_rec) => unreachable!(), // should be desugared + } + } + + fn lower_normal_record(&mut self, record: ast::NormalRecord) -> LowerResult { log!(info "entered {}({record})", fn_name!()); let mut hir_record = hir::Record::new(record.l_brace, record.r_brace, hir::RecordAttrs::new()); diff --git a/compiler/erg_parser/ast.rs b/compiler/erg_parser/ast.rs index aa11ea9e..2cae6145 100644 --- a/compiler/erg_parser/ast.rs +++ b/compiler/erg_parser/ast.rs @@ -6,8 +6,6 @@ use erg_common::error::Location; use erg_common::set::Set as HashSet; use erg_common::traits::{Locational, NestedDisplay, Stream}; use erg_common::vis::{Field, Visibility}; -// use erg_common::ty::SubrKind; -// use erg_common::value::{Field, ValueObj, Visibility}; use erg_common::Str; use erg_common::{ fmt_option, fmt_vec, impl_display_for_enum, impl_display_for_single_struct, @@ -675,6 +673,10 @@ impl From> for RecordAttrs { } impl RecordAttrs { + pub const fn new(attrs: Vec) -> Self { + Self(attrs) + } + pub fn iter(&self) -> impl Iterator { self.0.iter() } @@ -714,12 +716,45 @@ impl NormalRecord { /// e.g. {x; y; z} (syntax sugar of {x = x; y = y; z = z}) #[derive(Clone, Debug, PartialEq, Eq, Hash)] -pub struct SimpleRecord { +pub struct ShortenedRecord { pub l_brace: Token, pub r_brace: Token, - idents: Vec, + pub idents: Vec, } +impl NestedDisplay for ShortenedRecord { + fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, _level: usize) -> fmt::Result { + write!(f, "{{")?; + for ident in self.idents.iter() { + write!(f, "{}; ", ident)?; + } + write!(f, "}}") + } +} + +impl_display_from_nested!(ShortenedRecord); +impl_locational!(ShortenedRecord, l_brace, r_brace); + +impl ShortenedRecord { + pub const fn new(l_brace: Token, r_brace: Token, idents: Vec) -> Self { + Self { + l_brace, + r_brace, + idents, + } + } +} + +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub enum Record { + Normal(NormalRecord), + Shortened(ShortenedRecord), +} + +impl_nested_display_for_enum!(Record; Normal, Shortened); +impl_display_for_enum!(Record; Normal, Shortened); +impl_locational_for_enum!(Record; Normal, Shortened); + #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub struct NormalSet { l_brace: Token, @@ -2610,7 +2645,8 @@ pub struct Def { impl NestedDisplay for Def { fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, level: usize) -> fmt::Result { - writeln!(f, "{} {}", self.sig, self.body.op.content)?; + self.sig.fmt_nest(f, level)?; + writeln!(f, " {}", self.body.op.content)?; self.body.block.fmt_nest(f, level + 1) } } @@ -2671,7 +2707,7 @@ pub enum Expr { Tuple(Tuple), Dict(Dict), Set(Set), - Record(NormalRecord), + Record(Record), BinOp(BinOp), UnaryOp(UnaryOp), Call(Call), diff --git a/compiler/erg_parser/desugar.rs b/compiler/erg_parser/desugar.rs index a67a24a4..b1e18046 100644 --- a/compiler/erg_parser/desugar.rs +++ b/compiler/erg_parser/desugar.rs @@ -11,9 +11,11 @@ use erg_common::Str; use erg_common::{enum_unwrap, get_hash, set}; use crate::ast::{ - Accessor, Args, Block, Call, Def, DefBody, DefId, Expr, Identifier, Lambda, LambdaSignature, - Literal, Local, Module, ParamPattern, ParamSignature, Params, PosArg, Signature, SubrSignature, - TypeBoundSpecs, TypeSpec, VarName, VarPattern, VarSignature, + Accessor, Args, Array, BinOp, Block, Call, Def, DefBody, DefId, Expr, Identifier, KwArg, + Lambda, LambdaSignature, Literal, Local, MethodDefs, Module, NormalArray, NormalRecord, + NormalTuple, ParamPattern, ParamSignature, Params, PosArg, Record, RecordAttrs, + ShortenedRecord, Signature, SubrSignature, Tuple, TypeAscription, TypeBoundSpecs, TypeSpec, + UnaryOp, VarName, VarPattern, VarSignature, }; use crate::token::{Token, TokenKind}; @@ -46,7 +48,9 @@ impl Desugarer { pub fn desugar(&mut self, module: Module) -> Module { let module = self.desugar_multiple_pattern_def(module); - self.desugar_pattern(module) + let module = self.desugar_pattern(module); + let module = self.desugar_shortened_record(module); + module } fn desugar_ubar_lambda(&self, _module: Module) -> Module { @@ -306,6 +310,149 @@ impl Desugarer { } } + /// `{x; y}` -> `{x = x; y = y}` + fn desugar_shortened_record(&self, mut module: Module) -> Module { + let mut new = Module::with_capacity(module.len()); + while let Some(chunk) = module.lpop() { + new.push(self.rec_desugar_shortened_record(chunk)); + } + new + } + + fn rec_desugar_shortened_record(&self, expr: Expr) -> Expr { + match expr { + Expr::Record(Record::Shortened(rec)) => { + let rec = self.desugar_shortened_record_inner(rec); + Expr::Record(Record::Normal(rec)) + } + Expr::Array(array) => match array { + Array::Normal(arr) => { + let (elems, _, _) = arr.elems.deconstruct(); + let elems = elems + .into_iter() + .map(|elem| PosArg::new(self.rec_desugar_shortened_record(elem.expr))) + .collect(); + let elems = Args::new(elems, vec![], None); + let arr = NormalArray::new(arr.l_sqbr, arr.r_sqbr, elems); + Expr::Array(Array::Normal(arr)) + } + _ => todo!(), + }, + Expr::Tuple(tuple) => match tuple { + Tuple::Normal(tup) => { + let (elems, _, paren) = tup.elems.deconstruct(); + let elems = elems + .into_iter() + .map(|elem| PosArg::new(self.rec_desugar_shortened_record(elem.expr))) + .collect(); + let new_tup = Args::new(elems, vec![], paren); + let tup = NormalTuple::new(new_tup); + Expr::Tuple(Tuple::Normal(tup)) + } + }, + Expr::Set(set) => { + todo!("{set}") + } + Expr::Dict(dict) => { + todo!("{dict}") + } + Expr::BinOp(binop) => { + let mut args = vec![]; + for arg in binop.args.into_iter() { + args.push(self.rec_desugar_shortened_record(*arg)); + } + let lhs = args.remove(0); + let rhs = args.remove(0); + Expr::BinOp(BinOp::new(binop.op, lhs, rhs)) + } + Expr::UnaryOp(unaryop) => { + let mut args = vec![]; + for arg in unaryop.args.into_iter() { + args.push(self.rec_desugar_shortened_record(*arg)); + } + let expr = args.remove(0); + Expr::UnaryOp(UnaryOp::new(unaryop.op, expr)) + } + Expr::Call(call) => { + let obj = self.rec_desugar_shortened_record(*call.obj); + let (pos_args, kw_args, paren) = call.args.deconstruct(); + let pos_args = pos_args + .into_iter() + .map(|arg| PosArg::new(self.rec_desugar_shortened_record(arg.expr))) + .collect(); + let kw_args = kw_args + .into_iter() + .map(|arg| { + let expr = self.rec_desugar_shortened_record(arg.expr); + KwArg::new(arg.keyword, arg.t_spec, expr) // TODO: t_spec + }) + .collect(); + let args = Args::new(pos_args, kw_args, paren); + Expr::Call(Call::new(obj, call.method_name, args)) + } + Expr::Def(def) => { + let mut chunks = vec![]; + for chunk in def.body.block.into_iter() { + chunks.push(self.rec_desugar_shortened_record(chunk)); + } + let body = DefBody::new(def.body.op, Block::new(chunks), def.body.id); + Expr::Def(Def::new(def.sig, body)) + } + Expr::Lambda(lambda) => { + let mut chunks = vec![]; + for chunk in lambda.body.into_iter() { + chunks.push(self.rec_desugar_shortened_record(chunk)); + } + let body = Block::new(chunks); + Expr::Lambda(Lambda::new(lambda.sig, lambda.op, body, lambda.id)) + } + Expr::TypeAsc(tasc) => { + let expr = self.rec_desugar_shortened_record(*tasc.expr); + Expr::TypeAsc(TypeAscription::new(expr, tasc.t_spec)) + } + Expr::MethodDefs(method_defs) => { + let mut new_defs = vec![]; + for def in method_defs.defs.into_iter() { + let mut chunks = vec![]; + for chunk in def.body.block.into_iter() { + chunks.push(self.rec_desugar_shortened_record(chunk)); + } + let body = DefBody::new(def.body.op, Block::new(chunks), def.body.id); + new_defs.push(Def::new(def.sig, body)); + } + let new_defs = RecordAttrs::from(new_defs); + Expr::MethodDefs(MethodDefs::new( + method_defs.class, + method_defs.vis, + new_defs, + )) + } + // TODO: Accessorにも一応レコードを入れられる + other => other, + } + } + + fn desugar_shortened_record_inner(&self, rec: ShortenedRecord) -> NormalRecord { + let mut attrs = vec![]; + for attr in rec.idents.into_iter() { + let var = VarSignature::new(VarPattern::Ident(attr.clone()), None); + let sig = Signature::Var(var); + let body = DefBody::new( + Token::from_str(TokenKind::Equal, "="), + Block::new(vec![Expr::local( + attr.inspect(), + attr.ln_begin().unwrap(), + attr.col_begin().unwrap(), + )]), + DefId(get_hash(&(&sig, attr.inspect()))), + ); + let def = Def::new(sig, body); + attrs.push(def); + } + let attrs = RecordAttrs::new(attrs); + NormalRecord::new(rec.l_brace, rec.r_brace, attrs) + } + /// `F(I | I > 0)` -> `F(I: {I: Int | I > 0})` fn desugar_refinement_pattern(&self, _mod: Module) -> Module { todo!() diff --git a/compiler/erg_parser/parse.rs b/compiler/erg_parser/parse.rs index c255a598..083197b9 100644 --- a/compiler/erg_parser/parse.rs +++ b/compiler/erg_parser/parse.rs @@ -64,7 +64,7 @@ pub enum ArrayInner { pub enum BraceContainer { Set(Set), Dict(Dict), - Record(NormalRecord), + Record(Record), } /// Perform recursive descent parsing. @@ -1410,12 +1410,20 @@ impl Parser { match first { Expr::Def(def) => { let record = self - .try_reduce_record(l_brace, def) + .try_reduce_normal_record(l_brace, def) .map_err(|_| self.stack_dec())?; self.level -= 1; - Ok(BraceContainer::Record(record)) + Ok(BraceContainer::Record(Record::Normal(record))) + } + // Dict + Expr::TypeAsc(_) => todo!(), + Expr::Accessor(acc) if self.cur_is(Semi) => { + let record = self + .try_reduce_shortened_record(l_brace, acc) + .map_err(|_| self.stack_dec())?; + self.level -= 1; + Ok(BraceContainer::Record(Record::Shortened(record))) } - Expr::TypeAsc(_) => todo!(), // invalid syntax other => { let set = self .try_reduce_set(l_brace, other) @@ -1426,7 +1434,11 @@ impl Parser { } } - fn try_reduce_record(&mut self, l_brace: Token, first: Def) -> ParseResult { + fn try_reduce_normal_record( + &mut self, + l_brace: Token, + first: Def, + ) -> ParseResult { debug_call_info!(self); let mut attrs = vec![first]; loop { @@ -1459,6 +1471,54 @@ impl Parser { } } + fn try_reduce_shortened_record( + &mut self, + l_brace: Token, + first: Accessor, + ) -> ParseResult { + debug_call_info!(self); + let first = match first { + Accessor::Local(local) => Identifier::new(None, VarName::new(local.symbol)), + Accessor::Public(public) => { + Identifier::new(Some(public.dot), VarName::new(public.symbol)) + } + other => todo!("{other}"), // syntax error + }; + let mut idents = vec![first]; + loop { + match self.peek() { + Some(t) if t.category_is(TC::Separator) => { + self.skip(); + if self.cur_is(Dedent) { + self.skip(); + if self.cur_is(RBrace) { + let r_brace = self.lpop(); + self.level -= 1; + return Ok(ShortenedRecord::new(l_brace, r_brace, idents)); + } else { + todo!() + } + } + let acc = self.try_reduce_acc().map_err(|_| self.stack_dec())?; + let acc = match acc { + Accessor::Local(local) => Identifier::new(None, VarName::new(local.symbol)), + Accessor::Public(public) => { + Identifier::new(Some(public.dot), VarName::new(public.symbol)) + } + other => todo!("{other}"), // syntax error + }; + idents.push(acc); + } + Some(term) if term.is(RBrace) => { + let r_brace = self.lpop(); + self.level -= 1; + return Ok(ShortenedRecord::new(l_brace, r_brace, idents)); + } + _ => todo!(), + } + } + } + fn _try_reduce_dict() -> ParseResult { todo!() } @@ -1594,10 +1654,7 @@ impl Parser { todo!() } - fn convert_record_to_record_pat( - &mut self, - _record: NormalRecord, - ) -> ParseResult { + fn convert_record_to_record_pat(&mut self, _record: Record) -> ParseResult { debug_call_info!(self); todo!() } @@ -1809,7 +1866,7 @@ impl Parser { fn convert_record_to_param_record_pat( &mut self, - _record: NormalRecord, + _record: Record, ) -> ParseResult { debug_call_info!(self); todo!() @@ -1920,10 +1977,7 @@ impl Parser { todo!() } - fn convert_record_to_param_pat( - &mut self, - _record: NormalRecord, - ) -> ParseResult { + fn convert_record_to_param_pat(&mut self, _record: Record) -> ParseResult { debug_call_info!(self); todo!() } diff --git a/examples/class.er b/examples/class.er index 709c5886..babd2815 100644 --- a/examples/class.er +++ b/examples/class.er @@ -1,17 +1,17 @@ @Inheritable Point2D = Class {x = Int; y = Int} Point2D. - new x, y = Self::__new__ {x = x; y = y} + new x, y = Self::__new__ {x; y} norm ref self = self::x**2 + self::y**2 Point3D = Inherit Point2D, Additional := {z = Int} Point3D. @Override - new x, y, z = Self::__new__ {x = x; y = y; z = z} + new x, y, z = Self::__new__ {x; y; z} @Override norm ref self = self::x**2 + self::y**2 + self::z**2 UnpackPoint2D = Class {x = Int; y = Int}, Impl := Unpack p = UnpackPoint2D::{x = 1; y = 2} -UnpackPoint2D::{x = x; y = x} = p +UnpackPoint2D::{x; y} = p From ce94f81066c0e44919abf798937c68bff40b76dd Mon Sep 17 00:00:00 2001 From: Shunsuke Shibayama Date: Fri, 2 Sep 2022 19:37:54 +0900 Subject: [PATCH 02/68] WIP: Add `DataPack` --- compiler/erg_parser/ast.rs | 143 ++++++++++++++++++++++++++------- compiler/erg_parser/desugar.rs | 14 +++- compiler/erg_parser/parse.rs | 55 ++++++++++++- 3 files changed, 178 insertions(+), 34 deletions(-) diff --git a/compiler/erg_parser/ast.rs b/compiler/erg_parser/ast.rs index 2cae6145..4b0d8e58 100644 --- a/compiler/erg_parser/ast.rs +++ b/compiler/erg_parser/ast.rs @@ -6,13 +6,13 @@ use erg_common::error::Location; use erg_common::set::Set as HashSet; use erg_common::traits::{Locational, NestedDisplay, Stream}; use erg_common::vis::{Field, Visibility}; -use erg_common::Str; use erg_common::{ fmt_option, fmt_vec, impl_display_for_enum, impl_display_for_single_struct, impl_display_from_nested, impl_displayable_stream_for_wrapper, impl_locational, impl_locational_for_enum, impl_nested_display_for_chunk_enum, impl_nested_display_for_enum, impl_stream, impl_stream_for_wrapper, }; +use erg_common::{fmt_vec_split_with, Str}; use crate::token::{Token, TokenKind}; @@ -893,6 +893,36 @@ impl Call { } } +/// e.g. `Data::{x = 1; y = 2}` +#[derive(Clone, Debug, PartialEq, Eq, Hash)] +pub struct DataPack { + pub class: Box, + pub args: Record, +} + +impl NestedDisplay for DataPack { + fn fmt_nest(&self, f: &mut std::fmt::Formatter<'_>, _level: usize) -> std::fmt::Result { + write!(f, "{}::{}", self.class, self.args) + } +} + +impl_display_from_nested!(DataPack); + +impl Locational for DataPack { + fn loc(&self) -> Location { + Location::concat(self.class.as_ref(), &self.args) + } +} + +impl DataPack { + pub fn new(class: Expr, args: Record) -> Self { + Self { + class: Box::new(class), + args, + } + } +} + #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub struct Block(Vec); @@ -1942,32 +1972,90 @@ impl VarTuplePattern { } } +#[derive(Clone, Debug, PartialEq, Eq, Hash)] +pub struct VarRecordAttr { + lhs: Identifier, + rhs: Identifier, +} + +impl NestedDisplay for VarRecordAttr { + fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, _level: usize) -> fmt::Result { + write!(f, "{} = {}", self.lhs, self.rhs) + } +} + +impl_display_from_nested!(VarRecordAttr); +impl_locational!(VarRecordAttr, lhs, rhs); + +#[derive(Clone, Debug, PartialEq, Eq, Hash)] +pub struct VarRecordAttrs { + pub(crate) elems: Vec, +} + +impl NestedDisplay for VarRecordAttrs { + fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, _level: usize) -> fmt::Result { + write!(f, "{}", fmt_vec_split_with(&self.elems, "; ")) + } +} + +impl_display_from_nested!(VarRecordAttrs); +impl_stream!(VarRecordAttrs, VarRecordAttr, elems); + +impl VarRecordAttrs { + pub const fn new(elems: Vec) -> Self { + Self { elems } + } + + pub const fn empty() -> Self { + Self::new(vec![]) + } +} + #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub struct VarRecordPattern { l_brace: Token, - // TODO: レコード専用の構造体を作る - pub(crate) elems: Vars, + pub(crate) attrs: VarRecordAttrs, r_brace: Token, } impl fmt::Display for VarRecordPattern { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "{{{}}}", self.elems) + write!(f, "{{{}}}", self.attrs) } } impl_locational!(VarRecordPattern, l_brace, r_brace); impl VarRecordPattern { - pub const fn new(l_brace: Token, elems: Vars, r_brace: Token) -> Self { + pub const fn new(l_brace: Token, attrs: VarRecordAttrs, r_brace: Token) -> Self { Self { l_brace, - elems, + attrs, r_brace, } } } +#[derive(Clone, Debug, PartialEq, Eq, Hash)] +pub struct VarDataPackPattern { + pub class: Identifier, // TODO: allow Attribute + pub args: VarRecordPattern, +} + +impl fmt::Display for VarDataPackPattern { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{}::{}", self.class, self.args) + } +} + +impl_locational!(VarDataPackPattern, class, args); + +impl VarDataPackPattern { + pub const fn new(class: Identifier, args: VarRecordPattern) -> Self { + Self { class, args } + } +} + #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub enum VarPattern { Discard(Token), @@ -1978,6 +2066,8 @@ pub enum VarPattern { Tuple(VarTuplePattern), // e.g. `{name; age}`, `{_; [car, cdr]}` Record(VarRecordPattern), + // e.g. `Data::{x, y}` + DataPack(VarDataPackPattern), } impl NestedDisplay for VarPattern { @@ -1988,12 +2078,13 @@ impl NestedDisplay for VarPattern { Self::Array(a) => write!(f, "{}", a), Self::Tuple(t) => write!(f, "{}", t), Self::Record(r) => write!(f, "{}", r), + Self::DataPack(d) => write!(f, "{}", d), } } } impl_display_from_nested!(VarPattern); -impl_locational_for_enum!(VarPattern; Discard, Ident, Array, Tuple, Record); +impl_locational_for_enum!(VarPattern; Discard, Ident, Array, Tuple, Record, DataPack); impl VarPattern { pub const fn inspect(&self) -> Option<&Str> { @@ -2003,18 +2094,6 @@ impl VarPattern { } } - pub fn inspects(&self) -> Vec<&Str> { - match self { - Self::Ident(ident) => vec![ident.inspect()], - Self::Array(VarArrayPattern { elems, .. }) - | Self::Tuple(VarTuplePattern { elems, .. }) - | Self::Record(VarRecordPattern { elems, .. }) => { - elems.iter().flat_map(|s| s.pat.inspects()).collect() - } - _ => vec![], - } - } - // _!(...) = ... is invalid pub fn is_procedural(&self) -> bool { match self { @@ -2191,26 +2270,27 @@ impl ParamRecordPattern { pub enum ParamPattern { Discard(Token), VarName(VarName), - // TODO: ConstField(), - // e.g. `a` of `[*a, b] = [1, 2, 3]` (a == [1, 2], b == 3) - // `b` of `[a, *b] = [1, 2, 3]` (a == 1, b == [2, 3]) - VarArgsName(VarName), + // TODO: ConstAttr(), Lit(Literal), Array(ParamArrayPattern), Tuple(ParamTuplePattern), Record(ParamRecordPattern), Ref(VarName), RefMut(VarName), + // e.g. `a` of `[...a, b] = [1, 2, 3]` (a == [1, 2], b == 3) + // `b` of `[a, ...b] = [1, 2, 3]` (a == 1, b == [2, 3]) VarArgs(VarName), } -impl_display_for_enum!(ParamPattern; Discard, VarName, VarArgsName, Lit, Array, Tuple, Record, Ref, RefMut, VarArgs); -impl_locational_for_enum!(ParamPattern; Discard, VarName, VarArgsName, Lit, Array, Tuple, Record, Ref, RefMut, VarArgs); +impl_display_for_enum!(ParamPattern; Discard, VarName, Lit, Array, Tuple, Record, Ref, RefMut, VarArgs); +impl_locational_for_enum!(ParamPattern; Discard, VarName, Lit, Array, Tuple, Record, Ref, RefMut, VarArgs); impl ParamPattern { pub const fn inspect(&self) -> Option<&Str> { match self { - Self::VarName(n) | Self::VarArgsName(n) => Some(n.inspect()), + Self::VarName(n) | Self::VarArgs(n) | Self::Ref(n) | Self::RefMut(n) => { + Some(n.inspect()) + } _ => None, } } @@ -2222,7 +2302,9 @@ impl ParamPattern { pub fn is_procedural(&self) -> bool { match self { Self::Discard(_) => true, - Self::VarName(n) | Self::VarArgsName(n) => n.is_procedural(), + Self::VarName(n) | Self::VarArgs(n) | Self::Ref(n) | Self::RefMut(n) => { + n.is_procedural() + } _ => false, } } @@ -2230,7 +2312,7 @@ impl ParamPattern { pub fn is_const(&self) -> bool { match self { Self::Discard(_) => true, - Self::VarName(n) | Self::VarArgsName(n) => n.is_const(), + Self::VarName(n) | Self::VarArgs(n) | Self::Ref(n) | Self::RefMut(n) => n.is_const(), _ => false, } } @@ -2711,15 +2793,16 @@ pub enum Expr { BinOp(BinOp), UnaryOp(UnaryOp), Call(Call), + DataPack(DataPack), Lambda(Lambda), TypeAsc(TypeAscription), Def(Def), MethodDefs(MethodDefs), } -impl_nested_display_for_chunk_enum!(Expr; Lit, Accessor, Array, Tuple, Dict, Set, Record, BinOp, UnaryOp, Call, Lambda, TypeAsc, Def, MethodDefs); +impl_nested_display_for_chunk_enum!(Expr; Lit, Accessor, Array, Tuple, Dict, Set, Record, BinOp, UnaryOp, Call, DataPack, Lambda, TypeAsc, Def, MethodDefs); impl_display_from_nested!(Expr); -impl_locational_for_enum!(Expr; Lit, Accessor, Array, Tuple, Dict, Set, Record, BinOp, UnaryOp, Call, Lambda, TypeAsc, Def, MethodDefs); +impl_locational_for_enum!(Expr; Lit, Accessor, Array, Tuple, Dict, Set, Record, BinOp, UnaryOp, Call, DataPack, Lambda, TypeAsc, Def, MethodDefs); impl Expr { pub fn is_match_call(&self) -> bool { diff --git a/compiler/erg_parser/desugar.rs b/compiler/erg_parser/desugar.rs index b1e18046..1105ac81 100644 --- a/compiler/erg_parser/desugar.rs +++ b/compiler/erg_parser/desugar.rs @@ -11,8 +11,8 @@ use erg_common::Str; use erg_common::{enum_unwrap, get_hash, set}; use crate::ast::{ - Accessor, Args, Array, BinOp, Block, Call, Def, DefBody, DefId, Expr, Identifier, KwArg, - Lambda, LambdaSignature, Literal, Local, MethodDefs, Module, NormalArray, NormalRecord, + Accessor, Args, Array, BinOp, Block, Call, DataPack, Def, DefBody, DefId, Expr, Identifier, + KwArg, Lambda, LambdaSignature, Literal, Local, MethodDefs, Module, NormalArray, NormalRecord, NormalTuple, ParamPattern, ParamSignature, Params, PosArg, Record, RecordAttrs, ShortenedRecord, Signature, SubrSignature, Tuple, TypeAscription, TypeBoundSpecs, TypeSpec, UnaryOp, VarName, VarPattern, VarSignature, @@ -325,6 +325,16 @@ impl Desugarer { let rec = self.desugar_shortened_record_inner(rec); Expr::Record(Record::Normal(rec)) } + Expr::DataPack(pack) => { + if let Record::Shortened(rec) = pack.args { + let class = self.rec_desugar_shortened_record(*pack.class); + let rec = self.desugar_shortened_record_inner(rec); + let args = Record::Normal(rec); + Expr::DataPack(DataPack::new(class, args)) + } else { + Expr::DataPack(pack) + } + } Expr::Array(array) => match array { Array::Normal(arr) => { let (elems, _, _) = arr.elems.deconstruct(); diff --git a/compiler/erg_parser/parse.rs b/compiler/erg_parser/parse.rs index 083197b9..ef6576cb 100644 --- a/compiler/erg_parser/parse.rs +++ b/compiler/erg_parser/parse.rs @@ -441,6 +441,13 @@ impl Parser { let attr = Local::new(token); acc = Accessor::attr(Expr::Accessor(acc), vis, attr); } + // DataPack + LBrace => { + self.restore(token); + self.restore(vis); + break; + } + // MethodDefs Newline => { self.restore(token); self.restore(vis); @@ -600,7 +607,11 @@ impl Parser { { Some(self.try_reduce_args()) } - Some(t) if (t.is(Dot) || t.is(DblColon)) && !self.nth_is(1, Newline) => { + Some(t) + if (t.is(Dot) || t.is(DblColon)) + && !self.nth_is(1, Newline) + && !self.nth_is(1, LBrace) => + { Some(self.try_reduce_args()) } _ => None, @@ -973,7 +984,25 @@ impl Parser { let defs = self .try_reduce_method_defs(maybe_class, vis) .map_err(|_| self.stack_dec())?; - return Ok(Expr::MethodDefs(defs)); + let expr = Expr::MethodDefs(defs); + assert_eq!(stack.len(), 0); + self.level -= 1; + return Ok(expr); + } + l_brace if l_brace.is(LBrace) => { + let maybe_class = enum_unwrap!(stack.pop(), Some:(ExprOrOp::Expr:(_))); + self.restore(l_brace); + let container = self + .try_reduce_brace_container() + .map_err(|_| self.stack_dec())?; + match container { + BraceContainer::Record(args) => { + let pack = DataPack::new(maybe_class, args); + stack.push(ExprOrOp::Expr(Expr::DataPack(pack))); + } + BraceContainer::Dict(dict) => todo!("{dict}"), + BraceContainer::Set(set) => todo!("{set}"), + } } other => { self.restore(other); @@ -1397,6 +1426,7 @@ impl Parser { /// Set, Dict, Record fn try_reduce_brace_container(&mut self) -> ParseResult { debug_call_info!(self); + assert!(self.cur_is(LBrace)); let l_brace = self.lpop(); if self.cur_is(Newline) { self.skip(); @@ -1610,6 +1640,14 @@ impl Parser { self.level -= 1; Ok(Signature::Var(var)) } + Expr::DataPack(pack) => { + let data_pack = self + .convert_data_pack_to_data_pack_pat(pack) + .map_err(|_| self.stack_dec())?; + let var = VarSignature::new(VarPattern::DataPack(data_pack), None); + self.level -= 1; + Ok(Signature::Var(var)) + } Expr::Tuple(tuple) => { let tuple_pat = self .convert_tuple_to_tuple_pat(tuple) @@ -1655,6 +1693,19 @@ impl Parser { } fn convert_record_to_record_pat(&mut self, _record: Record) -> ParseResult { + debug_call_info!(self); + match _record { + Record::Normal(_rec) => { + todo!() + } + _ => todo!(), + } + } + + fn convert_data_pack_to_data_pack_pat( + &mut self, + _pack: DataPack, + ) -> ParseResult { debug_call_info!(self); todo!() } From f0d686cd7b47aa7dead2cd1952ac1baf94c37a7c Mon Sep 17 00:00:00 2001 From: Shunsuke Shibayama Date: Fri, 2 Sep 2022 22:49:34 +0900 Subject: [PATCH 03/68] Change `ref` and `ref!` to unary operators --- compiler/erg_parser/ast.rs | 11 ++++- compiler/erg_parser/desugar.rs | 16 ++----- compiler/erg_parser/lex.rs | 2 + compiler/erg_parser/parse.rs | 87 ++++++++++++++++++++++------------ compiler/erg_parser/token.rs | 26 +++++----- 5 files changed, 87 insertions(+), 55 deletions(-) diff --git a/compiler/erg_parser/ast.rs b/compiler/erg_parser/ast.rs index 4b0d8e58..b74b3298 100644 --- a/compiler/erg_parser/ast.rs +++ b/compiler/erg_parser/ast.rs @@ -1987,6 +1987,12 @@ impl NestedDisplay for VarRecordAttr { impl_display_from_nested!(VarRecordAttr); impl_locational!(VarRecordAttr, lhs, rhs); +impl VarRecordAttr { + pub const fn new(lhs: Identifier, rhs: Identifier) -> Self { + Self { lhs, rhs } + } +} + #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub struct VarRecordAttrs { pub(crate) elems: Vec, @@ -2038,7 +2044,7 @@ impl VarRecordPattern { #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub struct VarDataPackPattern { - pub class: Identifier, // TODO: allow Attribute + pub class: Accessor, // TODO: allow polymorphic pub args: VarRecordPattern, } @@ -2051,7 +2057,7 @@ impl fmt::Display for VarDataPackPattern { impl_locational!(VarDataPackPattern, class, args); impl VarDataPackPattern { - pub const fn new(class: Identifier, args: VarRecordPattern) -> Self { + pub const fn new(class: Accessor, args: VarRecordPattern) -> Self { Self { class, args } } } @@ -2275,6 +2281,7 @@ pub enum ParamPattern { Array(ParamArrayPattern), Tuple(ParamTuplePattern), Record(ParamRecordPattern), + // DataPack(ParamDataPackPattern), Ref(VarName), RefMut(VarName), // e.g. `a` of `[...a, b] = [1, 2, 3]` (a == [1, 2], b == 3) diff --git a/compiler/erg_parser/desugar.rs b/compiler/erg_parser/desugar.rs index 1105ac81..9e288685 100644 --- a/compiler/erg_parser/desugar.rs +++ b/compiler/erg_parser/desugar.rs @@ -367,20 +367,14 @@ impl Desugarer { todo!("{dict}") } Expr::BinOp(binop) => { - let mut args = vec![]; - for arg in binop.args.into_iter() { - args.push(self.rec_desugar_shortened_record(*arg)); - } - let lhs = args.remove(0); - let rhs = args.remove(0); + let mut args = binop.args.into_iter(); + let lhs = self.rec_desugar_shortened_record(*args.next().unwrap()); + let rhs = self.rec_desugar_shortened_record(*args.next().unwrap()); Expr::BinOp(BinOp::new(binop.op, lhs, rhs)) } Expr::UnaryOp(unaryop) => { - let mut args = vec![]; - for arg in unaryop.args.into_iter() { - args.push(self.rec_desugar_shortened_record(*arg)); - } - let expr = args.remove(0); + let mut args = unaryop.args.into_iter(); + let expr = self.rec_desugar_shortened_record(*args.next().unwrap()); Expr::UnaryOp(UnaryOp::new(unaryop.op, expr)) } Expr::Call(call) => { diff --git a/compiler/erg_parser/lex.rs b/compiler/erg_parser/lex.rs index 74fb08af..2425f404 100644 --- a/compiler/erg_parser/lex.rs +++ b/compiler/erg_parser/lex.rs @@ -525,6 +525,8 @@ impl Lexer /*<'a>*/ { "isnot" => IsNotOp, "dot" => DotOp, "cross" => CrossOp, + "ref" => RefOp, + "ref!" => RefMutOp, // これらはリテラルというより定数だが便宜的にリテラルということにしておく "True" | "False" => BoolLit, "None" => NoneLit, diff --git a/compiler/erg_parser/parse.rs b/compiler/erg_parser/parse.rs index ef6576cb..5a55c460 100644 --- a/compiler/erg_parser/parse.rs +++ b/compiler/erg_parser/parse.rs @@ -1692,22 +1692,51 @@ impl Parser { todo!() } - fn convert_record_to_record_pat(&mut self, _record: Record) -> ParseResult { + fn convert_record_to_record_pat(&mut self, record: Record) -> ParseResult { debug_call_info!(self); - match _record { - Record::Normal(_rec) => { - todo!() + match record { + Record::Normal(rec) => { + let mut pats = vec![]; + for mut attr in rec.attrs.into_iter() { + let lhs = + option_enum_unwrap!(attr.sig, Signature::Var).unwrap_or_else(|| todo!()); + let lhs = + option_enum_unwrap!(lhs.pat, VarPattern::Ident).unwrap_or_else(|| todo!()); + assert_eq!(attr.body.block.len(), 1); + let rhs = option_enum_unwrap!(attr.body.block.remove(0), Expr::Accessor) + .unwrap_or_else(|| todo!()); + let rhs = self + .convert_accessor_to_ident(rhs) + .map_err(|_| self.stack_dec())?; + pats.push(VarRecordAttr::new(lhs, rhs)); + } + let attrs = VarRecordAttrs::new(pats); + self.level -= 1; + Ok(VarRecordPattern::new(rec.l_brace, attrs, rec.r_brace)) + } + Record::Shortened(rec) => { + let mut pats = vec![]; + for ident in rec.idents.into_iter() { + pats.push(VarRecordAttr::new(ident.clone(), ident)); + } + let attrs = VarRecordAttrs::new(pats); + self.level -= 1; + Ok(VarRecordPattern::new(rec.l_brace, attrs, rec.r_brace)) } - _ => todo!(), } } fn convert_data_pack_to_data_pack_pat( &mut self, - _pack: DataPack, + pack: DataPack, ) -> ParseResult { debug_call_info!(self); - todo!() + let class = option_enum_unwrap!(*pack.class, Expr::Accessor).unwrap_or_else(|| todo!()); + let args = self + .convert_record_to_record_pat(pack.args) + .map_err(|_| self.stack_dec())?; + self.level -= 1; + Ok(VarDataPackPattern::new(class, args)) } fn convert_tuple_to_tuple_pat(&mut self, tuple: Tuple) -> ParseResult { @@ -1868,30 +1897,26 @@ impl Parser { self.level -= 1; Ok(param) } - Expr::Call(mut call) => match *call.obj { - Expr::Accessor(Accessor::Local(local)) => match &local.inspect()[..] { - "ref" => { - assert_eq!(call.args.len(), 1); - let var = call.args.remove_pos(0).expr; - let var = option_enum_unwrap!(var, Expr::Accessor:(Accessor::Local:(_))) - .unwrap_or_else(|| todo!()); - let pat = ParamPattern::Ref(VarName::new(var.symbol)); - let param = ParamSignature::new(pat, None, None); - self.level -= 1; - Ok(param) - } - "ref!" => { - assert_eq!(call.args.len(), 1); - let var = call.args.remove_pos(0).expr; - let var = option_enum_unwrap!(var, Expr::Accessor:(Accessor::Local:(_))) - .unwrap_or_else(|| todo!()); - let pat = ParamPattern::RefMut(VarName::new(var.symbol)); - let param = ParamSignature::new(pat, None, None); - self.level -= 1; - Ok(param) - } - other => todo!("{other}"), - }, + Expr::UnaryOp(unary) => match unary.op.kind { + TokenKind::RefOp => { + let var = unary.args.into_iter().next().unwrap(); + let var = option_enum_unwrap!(*var, Expr::Accessor:(Accessor::Local:(_))) + .unwrap_or_else(|| todo!()); + let pat = ParamPattern::Ref(VarName::new(var.symbol)); + let param = ParamSignature::new(pat, None, None); + self.level -= 1; + Ok(param) + } + TokenKind::RefMutOp => { + let var = unary.args.into_iter().next().unwrap(); + let var = option_enum_unwrap!(*var, Expr::Accessor:(Accessor::Local:(_))) + .unwrap_or_else(|| todo!()); + let pat = ParamPattern::RefMut(VarName::new(var.symbol)); + let param = ParamSignature::new(pat, None, None); + self.level -= 1; + Ok(param) + } + // Spread other => todo!("{other}"), }, other => todo!("{other}"), // Error diff --git a/compiler/erg_parser/token.rs b/compiler/erg_parser/token.rs index 4dabc27b..52a78893 100644 --- a/compiler/erg_parser/token.rs +++ b/compiler/erg_parser/token.rs @@ -103,6 +103,10 @@ pub enum TokenKind { DotOp, /// `cross` (vector product) CrossOp, + /// `ref` (special unary) + RefOp, + /// `ref!` (special unary) + RefMutOp, /// = Equal, /// := @@ -210,7 +214,7 @@ impl TokenKind { Symbol => TokenCategory::Symbol, NatLit | IntLit | RatioLit | StrLit | BoolLit | NoneLit | EllipsisLit | NoImplLit | InfLit => TokenCategory::Literal, - PrePlus | PreMinus | PreBitNot | Mutate => TokenCategory::UnaryOp, + PrePlus | PreMinus | PreBitNot | Mutate | RefOp | RefMutOp => TokenCategory::UnaryOp, Try => TokenCategory::PostfixOp, Comma | Colon | DblColon | SupertypeOf | SubtypeOf | Dot | Pipe | Walrus => { TokenCategory::SpecialBinOp @@ -234,16 +238,16 @@ impl TokenKind { pub const fn precedence(&self) -> Option { let prec = match self { - Dot | DblColon => 200, // . - Pow => 190, // ** - PrePlus | PreMinus | PreBitNot => 180, // (unary) + - * ~ - Star | Slash | FloorDiv | Mod | CrossOp | DotOp => 170, // * / // % cross dot - Plus | Minus => 160, // + - - Shl | Shr => 150, // << >> - BitAnd => 140, // && - BitXor => 130, // ^^ - BitOr => 120, // || - Closed | LeftOpen | RightOpen | Open => 100, // range operators + Dot | DblColon => 200, // . + Pow => 190, // ** + PrePlus | PreMinus | PreBitNot | RefOp | RefMutOp => 180, // (unary) + - * ~ ref ref! + Star | Slash | FloorDiv | Mod | CrossOp | DotOp => 170, // * / // % cross dot + Plus | Minus => 160, // + - + Shl | Shr => 150, // << >> + BitAnd => 140, // && + BitXor => 130, // ^^ + BitOr => 120, // || + Closed | LeftOpen | RightOpen | Open => 100, // range operators Less | Gre | LessEq | GreEq | DblEq | NotEq | InOp | NotInOp | IsOp | IsNotOp => 90, // < > <= >= == != in notin is isnot AndOp => 80, // and OrOp => 70, // or From c4bff5d54a3c87f2848a2bf0991add42842ccc65 Mon Sep 17 00:00:00 2001 From: Shunsuke Shibayama Date: Sat, 3 Sep 2022 01:45:00 +0900 Subject: [PATCH 04/68] Add some const funcs & Remove `Evaluator` --- compiler/erg_compiler/context/compare.rs | 12 +- .../context/initialize/const_func.rs | 23 ++ .../erg_compiler/context/initialize/mod.rs | 22 +- compiler/erg_compiler/context/inquire.rs | 3 +- compiler/erg_compiler/context/instantiate.rs | 4 +- compiler/erg_compiler/context/mod.rs | 4 - compiler/erg_compiler/context/register.rs | 6 +- compiler/erg_compiler/context/tyvar.rs | 2 +- compiler/erg_compiler/eval.rs | 233 +++++++++--------- compiler/erg_compiler/lower.rs | 4 +- compiler/erg_type/lib.rs | 34 ++- compiler/erg_type/value.rs | 2 +- 12 files changed, 208 insertions(+), 141 deletions(-) create mode 100644 compiler/erg_compiler/context/initialize/const_func.rs diff --git a/compiler/erg_compiler/context/compare.rs b/compiler/erg_compiler/context/compare.rs index 41d1e1d3..78ee084f 100644 --- a/compiler/erg_compiler/context/compare.rs +++ b/compiler/erg_compiler/context/compare.rs @@ -92,7 +92,7 @@ impl Context { (l, r) if l == r => return true, _ => {} } - self.eval.shallow_eq_tp(lhs, rhs, self) + self.shallow_eq_tp(lhs, rhs) } /// e.g. @@ -676,7 +676,7 @@ impl Context { l.try_cmp(r).map(Into::into), // TODO: 型を見て判断する (TyParam::BinOp{ op, lhs, rhs }, r) => { - if let Ok(l) = self.eval.eval_bin_tp(*op, lhs, rhs) { + if let Ok(l) = self.eval_bin_tp(*op, lhs, rhs) { self.rec_try_cmp(&l, r) } else { Some(Any) } }, @@ -690,8 +690,8 @@ impl Context { l @ (TyParam::FreeVar(_) | TyParam::Erased(_) | TyParam::MonoQVar(_)), r @ (TyParam::FreeVar(_) | TyParam::Erased(_) | TyParam::MonoQVar(_)), ) /* if v.is_unbound() */ => { - let l_t = self.eval.get_tp_t(l, self).unwrap(); - let r_t = self.eval.get_tp_t(r, self).unwrap(); + let l_t = self.get_tp_t(l).unwrap(); + let r_t = self.get_tp_t(r).unwrap(); if self.rec_supertype_of(&l_t, &r_t) || self.rec_subtype_of(&l_t, &r_t) { Some(Any) } else { Some(NotEqual) } @@ -702,7 +702,7 @@ impl Context { // try_cmp((n: 2.._), 1) -> Some(Greater) // try_cmp((n: -1.._), 1) -> Some(Any) (l @ (TyParam::Erased(_) | TyParam::FreeVar(_) | TyParam::MonoQVar(_)), p) => { - let t = self.eval.get_tp_t(l, self).unwrap(); + let t = self.get_tp_t(l).unwrap(); let inf = self.rec_inf(&t); let sup = self.rec_sup(&t); if let (Some(inf), Some(sup)) = (inf, sup) { @@ -888,7 +888,7 @@ impl Context { #[inline] fn type_of(&self, p: &TyParam) -> Type { - self.eval.get_tp_t(p, self).unwrap() + self.get_tp_t(p).unwrap() } // sup/inf({±∞}) = ±∞ではあるが、Inf/NegInfにはOrdを実装しない diff --git a/compiler/erg_compiler/context/initialize/const_func.rs b/compiler/erg_compiler/context/initialize/const_func.rs new file mode 100644 index 00000000..de63377b --- /dev/null +++ b/compiler/erg_compiler/context/initialize/const_func.rs @@ -0,0 +1,23 @@ +use erg_common::Str; + +use erg_type::constructors::class; +use erg_type::value::ValueObj; +use erg_type::ValueArgs; + +/// Type -> Type +pub fn class_func(_args: ValueArgs, __name__: Option) -> ValueObj { + let t = class(__name__.unwrap_or(Str::ever(""))); + ValueObj::t(t) +} + +/// Type -> Type +pub fn inherit_func(_args: ValueArgs, __name__: Option) -> ValueObj { + let t = class(__name__.unwrap_or(Str::ever(""))); + ValueObj::t(t) +} + +/// Type -> Type +/// 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() +} diff --git a/compiler/erg_compiler/context/initialize/mod.rs b/compiler/erg_compiler/context/initialize/mod.rs index a456516c..4f524ea1 100644 --- a/compiler/erg_compiler/context/initialize/mod.rs +++ b/compiler/erg_compiler/context/initialize/mod.rs @@ -1,6 +1,7 @@ //! defines type information for builtin objects (in `Context`) //! //! 組み込みオブジェクトの型情報を(Contextに)定義 +pub mod const_func; pub mod importlib; pub mod io; pub mod math; @@ -13,15 +14,16 @@ use erg_common::set; use erg_common::vis::Visibility; use erg_common::Str; -use erg_type::constructors::*; use erg_type::typaram::TyParam; use erg_type::value::ValueObj; -use erg_type::Type; +use erg_type::{constructors::*, BuiltinConstSubr, ConstSubr}; +use erg_type::{HasType, Type}; use ParamSpec as PS; use Type::*; use erg_parser::ast::VarName; +use crate::context::initialize::const_func::{class_func, inherit_func, inheritable_func}; use crate::context::instantiate::{ConstTemplate, TyVarContext}; use crate::context::{Context, ContextKind, DefaultInfo, ParamSpec, TraitInstance}; use crate::varinfo::{Mutability, VarInfo, VarKind}; @@ -55,7 +57,11 @@ impl Context { if self.consts.get(name).is_some() { panic!("already registered: {name}"); } else { + // TODO: visibility (not always private) + // TODO: kind (not always Builtin) + let vi = VarInfo::new(obj.t(), Const, Private, Builtin); self.consts.insert(VarName::from_static(name), obj); + self.locals.insert(VarName::from_static(name), vi); } } @@ -1106,6 +1112,17 @@ impl Context { self.register_impl("quit", t_quit, Const, Private); } + fn init_builtin_const_funcs(&mut self) { + let class = ConstSubr::Builtin(BuiltinConstSubr::new(class_func, func1(Type, Type))); + self.register_const("Class", ValueObj::Subr(class)); + let inherit = ConstSubr::Builtin(BuiltinConstSubr::new(inherit_func, func1(Type, Type))); + self.register_const("Inherit", ValueObj::Subr(inherit)); + // decorators + let inheritable = + ConstSubr::Builtin(BuiltinConstSubr::new(inheritable_func, func1(Type, Type))); + self.register_const("Inheritable", ValueObj::Subr(inheritable)); + } + fn init_builtin_procs(&mut self) { let t_print = proc( vec![], @@ -1297,6 +1314,7 @@ impl Context { // TODO: capacityを正確に把握する let mut ctx = Context::module("".into(), 40); ctx.init_builtin_funcs(); + ctx.init_builtin_const_funcs(); ctx.init_builtin_procs(); ctx.init_builtin_operators(); ctx.init_builtin_traits(); diff --git a/compiler/erg_compiler/context/inquire.rs b/compiler/erg_compiler/context/inquire.rs index e2f28a03..ebd7a8f2 100644 --- a/compiler/erg_compiler/context/inquire.rs +++ b/compiler/erg_compiler/context/inquire.rs @@ -744,7 +744,8 @@ impl Context { ); self.substitute_call(obj, method_name, &instance, pos_args, kw_args)?; log!(info "Substituted:\ninstance: {instance}"); - let res = self.eval.eval_t_params(instance, &self, self.level)?; + let level = self.level; + let res = self.eval_t_params(instance, level)?; log!(info "Params evaluated:\nres: {res}\n"); self.propagate(&res, obj)?; log!(info "Propagated:\nres: {res}\n"); diff --git a/compiler/erg_compiler/context/instantiate.rs b/compiler/erg_compiler/context/instantiate.rs index b856be4c..966a9d23 100644 --- a/compiler/erg_compiler/context/instantiate.rs +++ b/compiler/erg_compiler/context/instantiate.rs @@ -608,9 +608,9 @@ impl Context { _ => assume_unreachable!(), }; let l = self.instantiate_const_expr(lhs); - let l = self.eval.eval_tp(&l, self)?; + let l = self.eval_tp(&l)?; let r = self.instantiate_const_expr(rhs); - let r = self.eval.eval_tp(&r, self)?; + let r = self.eval_tp(&r)?; if let Some(Greater) = self.rec_try_cmp(&l, &r) { panic!("{l}..{r} is not a valid interval type (should be lhs <= rhs)") } diff --git a/compiler/erg_compiler/context/mod.rs b/compiler/erg_compiler/context/mod.rs index b845787d..7ac2ad14 100644 --- a/compiler/erg_compiler/context/mod.rs +++ b/compiler/erg_compiler/context/mod.rs @@ -33,7 +33,6 @@ use erg_parser::token::Token; use crate::context::instantiate::ConstTemplate; use crate::error::{TyCheckError, TyCheckErrors, TyCheckResult}; -use crate::eval::Evaluator; use crate::varinfo::{Mutability, ParamIdx, VarInfo, VarKind}; use Mutability::*; use Visibility::*; @@ -254,7 +253,6 @@ pub struct Context { pub(crate) params: Vec<(Option, VarInfo)>, pub(crate) locals: Dict, pub(crate) consts: Dict, - pub(crate) eval: Evaluator, // {"Nat": ctx, "Int": ctx, ...} pub(crate) mono_types: Dict, // Implementation Contexts for Polymorphic Types @@ -296,7 +294,6 @@ impl fmt::Display for Context { .field("decls", &self.decls) .field("locals", &self.params) .field("consts", &self.consts) - .field("eval", &self.eval) .field("mono_types", &self.mono_types) .field("poly_types", &self.poly_classes) .field("patches", &self.patches) @@ -370,7 +367,6 @@ impl Context { decls: Dict::default(), locals: Dict::with_capacity(capacity), consts: Dict::default(), - eval: Evaluator::default(), mono_types: Dict::default(), poly_classes: Dict::default(), poly_traits: Dict::default(), diff --git a/compiler/erg_compiler/context/register.rs b/compiler/erg_compiler/context/register.rs index 285e62dc..df880afc 100644 --- a/compiler/erg_compiler/context/register.rs +++ b/compiler/erg_compiler/context/register.rs @@ -320,9 +320,9 @@ impl Context { for expr in block.iter() { if let ast::Expr::Def(def) = expr { let id = Some(def.body.id); - let eval_body_t = || { - self.eval - .eval_const_block(&def.body.block, self) + let __name__ = def.sig.ident().map(|i| i.inspect()); + let mut eval_body_t = || { + self.eval_const_block(&def.body.block, __name__) .map(|c| enum_t(set![c])) }; match &def.sig { diff --git a/compiler/erg_compiler/context/tyvar.rs b/compiler/erg_compiler/context/tyvar.rs index 8a86b084..423381c1 100644 --- a/compiler/erg_compiler/context/tyvar.rs +++ b/compiler/erg_compiler/context/tyvar.rs @@ -534,7 +534,7 @@ impl Context { .get_type() .unwrap() .clone(); // fvを参照しないよいにcloneする(あとでborrow_mutするため) - let tp_t = self.eval.get_tp_t(tp, self)?; + let tp_t = self.get_tp_t(tp)?; if self.rec_supertype_of(&fv_t, &tp_t) { // 外部未連携型変数の場合、linkしないで制約を弱めるだけにする(see compiler/inference.md) if fv.level() < Some(self.level) { diff --git a/compiler/erg_compiler/eval.rs b/compiler/erg_compiler/eval.rs index 6e5f20f0..864e16cc 100644 --- a/compiler/erg_compiler/eval.rs +++ b/compiler/erg_compiler/eval.rs @@ -5,7 +5,7 @@ use erg_common::rccell::RcCell; use erg_common::set::Set; use erg_common::traits::Stream; use erg_common::vis::Field; -use erg_common::{fn_name, set}; +use erg_common::{dict, fn_name, set}; use erg_common::{RcArray, Str}; use OpKind::*; @@ -17,7 +17,7 @@ use erg_type::constructors::{ }; use erg_type::typaram::{OpKind, TyParam}; use erg_type::value::ValueObj; -use erg_type::{Predicate, SubrKind, TyBound, Type}; +use erg_type::{Predicate, SubrKind, TyBound, Type, ValueArgs}; use crate::context::instantiate::TyVarContext; use crate::context::Context; @@ -165,26 +165,18 @@ impl SubstContext { } } -#[derive(Debug, Default)] -pub struct Evaluator {} - -impl Evaluator { - #[inline] - pub fn new() -> Self { - Self::default() - } - - fn eval_const_acc(&self, _acc: &Accessor, ctx: &Context) -> Option { +impl Context { + fn eval_const_acc(&self, _acc: &Accessor) -> Option { match _acc { Accessor::Local(local) => { - if let Some(val) = ctx.rec_get_const_obj(local.inspect()) { + if let Some(val) = self.rec_get_const_obj(local.inspect()) { Some(val.clone()) } else { None } } Accessor::Attr(attr) => { - let _obj = self.eval_const_expr(&attr.obj, ctx)?; + let _obj = self.eval_const_expr(&attr.obj, None)?; todo!() } _ => todo!(), @@ -211,18 +203,28 @@ impl Evaluator { } } - // TODO: kw args - fn eval_args(&self, _args: &Args) -> Option> { - todo!() + fn eval_args(&self, args: &Args, __name__: Option<&Str>) -> Option { + let mut evaluated_pos_args = vec![]; + for arg in args.pos_args().iter() { + let val = self.eval_const_expr(&arg.expr, __name__)?; + evaluated_pos_args.push(val); + } + let mut evaluated_kw_args = dict! {}; + for arg in args.kw_args().iter() { + let val = self.eval_const_expr(&arg.expr, __name__)?; + evaluated_kw_args.insert(arg.keyword.inspect().clone(), val); + } + Some(ValueArgs::new(evaluated_pos_args, evaluated_kw_args)) } - fn eval_const_call(&self, call: &Call, ctx: &Context) -> Option { + fn eval_const_call(&self, call: &Call, __name__: Option<&Str>) -> Option { if let Expr::Accessor(acc) = call.obj.as_ref() { match acc { Accessor::Local(name) if name.is_const() => { - if let Some(ValueObj::Subr(subr)) = ctx.rec_get_const_obj(&name.inspect()) { - let args = self.eval_args(&call.args)?; - Some(subr.call(args)) + if let Some(ValueObj::Subr(subr)) = self.rec_get_const_obj(&name.inspect()) { + let subr = subr.clone(); + let args = self.eval_args(&call.args, __name__)?; + Some(subr.call(args, __name__.map(|n| n.clone()))) } else { None } @@ -238,19 +240,19 @@ impl Evaluator { } } - fn eval_const_def(&self, def: &Def) -> Option { + fn eval_const_def(&mut self, def: &Def) -> Option { if def.is_const() { todo!() } None } - fn eval_const_array(&self, arr: &Array, ctx: &Context) -> Option { + fn eval_const_array(&self, arr: &Array) -> Option { let mut elems = vec![]; match arr { Array::Normal(arr) => { for elem in arr.elems.pos_args().iter() { - if let Some(elem) = self.eval_const_expr(&elem.expr, ctx) { + if let Some(elem) = self.eval_const_expr(&elem.expr, None) { elems.push(elem); } else { return None; @@ -264,17 +266,18 @@ impl Evaluator { Some(ValueObj::Array(RcArray::from(elems))) } - fn eval_const_record(&self, record: &Record, ctx: &Context) -> Option { + fn eval_const_record(&mut self, record: &Record) -> Option { match record { - Record::Normal(rec) => self.eval_const_normal_record(rec, ctx), + Record::Normal(rec) => self.eval_const_normal_record(rec), Record::Shortened(_rec) => unreachable!(), // should be desugared } } - fn eval_const_normal_record(&self, record: &NormalRecord, ctx: &Context) -> Option { + fn eval_const_normal_record(&mut self, record: &NormalRecord) -> Option { let mut attrs = vec![]; for attr in record.attrs.iter() { - if let Some(elem) = self.eval_const_block(&attr.body.block, ctx) { + let name = attr.sig.ident().map(|i| i.inspect()); + if let Some(elem) = self.eval_const_block(&attr.body.block, name) { let ident = match &attr.sig { Signature::Var(var) => match &var.pat { VarPattern::Ident(ident) => { @@ -292,27 +295,50 @@ impl Evaluator { Some(ValueObj::Record(attrs.into_iter().collect())) } - // ConstExprを評価するのではなく、コンパイル時関数の式(AST上ではただのExpr)を評価する - // コンパイル時評価できないならNoneを返す - pub(crate) fn eval_const_expr(&self, expr: &Expr, ctx: &Context) -> Option { + pub(crate) fn eval_const_expr(&self, expr: &Expr, __name__: Option<&Str>) -> Option { match expr { Expr::Lit(lit) => Some(eval_lit(lit)), - Expr::Accessor(acc) => self.eval_const_acc(acc, ctx), + Expr::Accessor(acc) => self.eval_const_acc(acc), Expr::BinOp(bin) => self.eval_const_bin(bin), Expr::UnaryOp(unary) => self.eval_const_unary(unary), - Expr::Call(call) => self.eval_const_call(call, ctx), - Expr::Def(def) => self.eval_const_def(def), - Expr::Array(arr) => self.eval_const_array(arr, ctx), - Expr::Record(rec) => self.eval_const_record(rec, ctx), + Expr::Call(call) => self.eval_const_call(call, __name__), + Expr::Array(arr) => self.eval_const_array(arr), + Expr::Record(rec) => todo!("{rec}"), // self.eval_const_record(rec), + Expr::Lambda(lambda) => todo!("{lambda}"), other => todo!("{other}"), } } - pub(crate) fn eval_const_block(&self, block: &Block, ctx: &Context) -> Option { - for chunk in block.iter().rev().skip(1).rev() { - self.eval_const_expr(chunk, ctx)?; + // ConstExprを評価するのではなく、コンパイル時関数の式(AST上ではただのExpr)を評価する + // コンパイル時評価できないならNoneを返す + pub(crate) fn eval_const_chunk( + &mut self, + expr: &Expr, + __name__: Option<&Str>, + ) -> Option { + match expr { + Expr::Lit(lit) => Some(eval_lit(lit)), + Expr::Accessor(acc) => self.eval_const_acc(acc), + Expr::BinOp(bin) => self.eval_const_bin(bin), + Expr::UnaryOp(unary) => self.eval_const_unary(unary), + Expr::Call(call) => self.eval_const_call(call, __name__), + Expr::Def(def) => self.eval_const_def(def), + Expr::Array(arr) => self.eval_const_array(arr), + Expr::Record(rec) => self.eval_const_record(rec), + Expr::Lambda(lambda) => todo!("{lambda}"), + other => todo!("{other}"), } - self.eval_const_expr(block.last().unwrap(), ctx) + } + + pub(crate) fn eval_const_block( + &mut self, + block: &Block, + __name__: Option<&Str>, + ) -> Option { + for chunk in block.iter().rev().skip(1).rev() { + self.eval_const_chunk(chunk, __name__)?; + } + self.eval_const_chunk(block.last().unwrap(), __name__) } fn eval_bin_lit(&self, op: OpKind, lhs: ValueObj, rhs: ValueObj) -> EvalResult { @@ -403,10 +429,10 @@ impl Evaluator { } /// 量化変数などはそのまま返す - pub(crate) fn eval_tp(&self, p: &TyParam, ctx: &Context) -> EvalResult { + pub(crate) fn eval_tp(&self, p: &TyParam) -> EvalResult { match p { - TyParam::FreeVar(fv) if fv.is_linked() => self.eval_tp(&fv.crack(), ctx), - TyParam::Mono(name) => ctx + TyParam::FreeVar(fv) if fv.is_linked() => self.eval_tp(&fv.crack()), + TyParam::Mono(name) => self .rec_get_const_obj(name) .map(|v| TyParam::value(v.clone())) .ok_or_else(|| EvalError::unreachable(fn_name!(), line!())), @@ -422,25 +448,18 @@ impl Evaluator { } } - pub(crate) fn eval_t_params( - &self, - substituted: Type, - ctx: &Context, - level: usize, - ) -> EvalResult { + pub(crate) fn eval_t_params(&self, substituted: Type, level: usize) -> EvalResult { match substituted { - Type::FreeVar(fv) if fv.is_linked() => { - self.eval_t_params(fv.crack().clone(), ctx, level) - } + Type::FreeVar(fv) if fv.is_linked() => self.eval_t_params(fv.crack().clone(), level), Type::Subr(mut subr) => { let kind = match subr.kind { SubrKind::FuncMethod(self_t) => { - SubrKind::fn_met(self.eval_t_params(*self_t, ctx, level)?) + SubrKind::fn_met(self.eval_t_params(*self_t, level)?) } SubrKind::ProcMethod { before, after } => { - let before = self.eval_t_params(*before, ctx, level)?; + let before = self.eval_t_params(*before, level)?; if let Some(after) = after { - let after = self.eval_t_params(*after, ctx, level)?; + let after = self.eval_t_params(*after, level)?; SubrKind::pr_met(before, Some(after)) } else { SubrKind::pr_met(before, None) @@ -449,16 +468,16 @@ impl Evaluator { other => other, }; for pt in subr.non_default_params.iter_mut() { - *pt.typ_mut() = self.eval_t_params(mem::take(pt.typ_mut()), ctx, level)?; + *pt.typ_mut() = self.eval_t_params(mem::take(pt.typ_mut()), level)?; } if let Some(var_args) = subr.var_params.as_mut() { *var_args.typ_mut() = - self.eval_t_params(mem::take(var_args.typ_mut()), ctx, level)?; + self.eval_t_params(mem::take(var_args.typ_mut()), level)?; } for pt in subr.default_params.iter_mut() { - *pt.typ_mut() = self.eval_t_params(mem::take(pt.typ_mut()), ctx, level)?; + *pt.typ_mut() = self.eval_t_params(mem::take(pt.typ_mut()), level)?; } - let return_t = self.eval_t_params(*subr.return_t, ctx, level)?; + let return_t = self.eval_t_params(*subr.return_t, level)?; Ok(subr_t( kind, subr.non_default_params, @@ -470,7 +489,7 @@ impl Evaluator { Type::Refinement(refine) => { let mut preds = Set::with_capacity(refine.preds.len()); for pred in refine.preds.into_iter() { - preds.insert(self.eval_pred(pred, ctx)?); + preds.insert(self.eval_pred(pred)?); } Ok(refinement(refine.var, *refine.t, preds)) } @@ -481,45 +500,45 @@ impl Evaluator { let lhs = match *lhs { Type::FreeVar(fv) if fv.is_unbound() => { fv.lift(); - ctx.deref_tyvar(Type::FreeVar(fv))? + self.deref_tyvar(Type::FreeVar(fv))? } _ => *lhs, }; - for (_ty, ty_ctx) in ctx.rec_get_nominal_super_type_ctxs(&lhs) { - if let Ok(obj) = ty_ctx.get_const_local(&Token::symbol(&rhs), &ctx.name) { + for (_ty, ty_ctx) in self.rec_get_nominal_super_type_ctxs(&lhs) { + if let Ok(obj) = ty_ctx.get_const_local(&Token::symbol(&rhs), &self.name) { if let ValueObj::Type(quant_t) = obj { let subst_ctx = SubstContext::new(&lhs, ty_ctx); - let t = subst_ctx.substitute(*quant_t, ty_ctx, level, ctx)?; - let t = self.eval_t_params(t, ctx, level)?; + let t = subst_ctx.substitute(*quant_t, ty_ctx, level, self)?; + let t = self.eval_t_params(t, level)?; return Ok(t); } else { todo!() } } } - if let Some(outer) = &ctx.outer { - self.eval_t_params(mono_proj(lhs, rhs), outer, level) + if let Some(outer) = self.outer.as_ref() { + outer.eval_t_params(mono_proj(lhs, rhs), level) } else { todo!( "{lhs}.{rhs} not found in [{}]", erg_common::fmt_iter( - ctx.rec_get_nominal_super_type_ctxs(&lhs) + self.rec_get_nominal_super_type_ctxs(&lhs) .map(|(_, ctx)| &ctx.name) ) ) } } - Type::Ref(l) => Ok(ref_(self.eval_t_params(*l, ctx, level)?)), - Type::RefMut(l) => Ok(ref_mut(self.eval_t_params(*l, ctx, level)?)), + Type::Ref(l) => Ok(ref_(self.eval_t_params(*l, level)?)), + Type::RefMut(l) => Ok(ref_mut(self.eval_t_params(*l, level)?)), Type::PolyClass { name, mut params } => { for p in params.iter_mut() { - *p = self.eval_tp(&mem::take(p), ctx)?; + *p = self.eval_tp(&mem::take(p))?; } Ok(poly_class(name, params)) } Type::PolyTrait { name, mut params } => { for p in params.iter_mut() { - *p = self.eval_tp(&mem::take(p), ctx)?; + *p = self.eval_tp(&mem::take(p))?; } Ok(poly_trait(name, params)) } @@ -528,51 +547,35 @@ impl Evaluator { } } - pub(crate) fn _eval_bound( - &self, - bound: TyBound, - ctx: &Context, - level: usize, - ) -> EvalResult { + pub(crate) fn _eval_bound(&self, bound: TyBound, level: usize) -> EvalResult { match bound { TyBound::Sandwiched { sub, mid, sup } => { - let sub = self.eval_t_params(sub, ctx, level)?; - let mid = self.eval_t_params(mid, ctx, level)?; - let sup = self.eval_t_params(sup, ctx, level)?; + let sub = self.eval_t_params(sub, level)?; + let mid = self.eval_t_params(mid, level)?; + let sup = self.eval_t_params(sup, level)?; Ok(TyBound::sandwiched(sub, mid, sup)) } TyBound::Instance { name: inst, t } => { - Ok(TyBound::instance(inst, self.eval_t_params(t, ctx, level)?)) + Ok(TyBound::instance(inst, self.eval_t_params(t, level)?)) } } } - pub(crate) fn eval_pred(&self, p: Predicate, ctx: &Context) -> EvalResult { + pub(crate) fn eval_pred(&self, p: Predicate) -> EvalResult { match p { Predicate::Value(_) | Predicate::Const(_) => Ok(p), - Predicate::Equal { lhs, rhs } => Ok(Predicate::eq(lhs, self.eval_tp(&rhs, ctx)?)), - Predicate::NotEqual { lhs, rhs } => Ok(Predicate::ne(lhs, self.eval_tp(&rhs, ctx)?)), - Predicate::LessEqual { lhs, rhs } => Ok(Predicate::le(lhs, self.eval_tp(&rhs, ctx)?)), - Predicate::GreaterEqual { lhs, rhs } => { - Ok(Predicate::ge(lhs, self.eval_tp(&rhs, ctx)?)) - } - Predicate::And(l, r) => Ok(Predicate::and( - self.eval_pred(*l, ctx)?, - self.eval_pred(*r, ctx)?, - )), - Predicate::Or(l, r) => Ok(Predicate::or( - self.eval_pred(*l, ctx)?, - self.eval_pred(*r, ctx)?, - )), - Predicate::Not(l, r) => Ok(Predicate::not( - self.eval_pred(*l, ctx)?, - self.eval_pred(*r, ctx)?, - )), + Predicate::Equal { lhs, rhs } => Ok(Predicate::eq(lhs, self.eval_tp(&rhs)?)), + Predicate::NotEqual { lhs, rhs } => Ok(Predicate::ne(lhs, self.eval_tp(&rhs)?)), + Predicate::LessEqual { lhs, rhs } => Ok(Predicate::le(lhs, self.eval_tp(&rhs)?)), + Predicate::GreaterEqual { lhs, rhs } => Ok(Predicate::ge(lhs, self.eval_tp(&rhs)?)), + Predicate::And(l, r) => Ok(Predicate::and(self.eval_pred(*l)?, self.eval_pred(*r)?)), + Predicate::Or(l, r) => Ok(Predicate::or(self.eval_pred(*l)?, self.eval_pred(*r)?)), + Predicate::Not(l, r) => Ok(Predicate::not(self.eval_pred(*l)?, self.eval_pred(*r)?)), } } - pub(crate) fn get_tp_t(&self, p: &TyParam, ctx: &Context) -> EvalResult { - let p = self.eval_tp(p, ctx)?; + pub(crate) fn get_tp_t(&self, p: &TyParam) -> EvalResult { + let p = self.eval_tp(p)?; match p { TyParam::Value(ValueObj::Mut(v)) => Ok(v.borrow().class().mutate()), TyParam::Value(v) => Ok(enum_t(set![v])), @@ -585,24 +588,23 @@ impl Evaluator { } } TyParam::Type(_) => Ok(Type::Type), - TyParam::Mono(name) => ctx - .consts - .get(&name) + TyParam::Mono(name) => self + .rec_get_const_obj(&name) .map(|v| enum_t(set![v.clone()])) .ok_or_else(|| EvalError::unreachable(fn_name!(), line!())), TyParam::MonoQVar(name) => { panic!("Not instantiated type variable: {name}") } TyParam::UnaryOp { op, val } => match op { - OpKind::Mutate => Ok(self.get_tp_t(&val, ctx)?.mutate()), + OpKind::Mutate => Ok(self.get_tp_t(&val)?.mutate()), _ => todo!(), }, other => todo!("{other}"), } } - pub(crate) fn _get_tp_class(&self, p: &TyParam, ctx: &Context) -> EvalResult { - let p = self.eval_tp(p, ctx)?; + pub(crate) fn _get_tp_class(&self, p: &TyParam) -> EvalResult { + let p = self.eval_tp(p)?; match p { TyParam::Value(v) => Ok(v.class()), TyParam::Erased(t) => Ok((*t).clone()), @@ -614,9 +616,8 @@ impl Evaluator { } } TyParam::Type(_) => Ok(Type::Type), - TyParam::Mono(name) => ctx - .consts - .get(&name) + TyParam::Mono(name) => self + .rec_get_const_obj(&name) .map(|v| v.class()) .ok_or_else(|| EvalError::unreachable(fn_name!(), line!())), other => todo!("{other}"), @@ -624,7 +625,7 @@ impl Evaluator { } /// NOTE: lとrが型の場合はContextの方で判定する - pub(crate) fn shallow_eq_tp(&self, lhs: &TyParam, rhs: &TyParam, ctx: &Context) -> bool { + pub(crate) fn shallow_eq_tp(&self, lhs: &TyParam, rhs: &TyParam) -> bool { match (lhs, rhs) { (TyParam::Type(l), TyParam::Type(r)) => l == r, (TyParam::Value(l), TyParam::Value(r)) => l == r, @@ -633,7 +634,9 @@ impl Evaluator { (TyParam::Mono(l), TyParam::Mono(r)) => { if l == r { true - } else if let (Some(l), Some(r)) = (ctx.consts.get(l), ctx.consts.get(r)) { + } else if let (Some(l), Some(r)) = + (self.rec_get_const_obj(l), self.rec_get_const_obj(r)) + { l == r } else { // lとrが型の場合は... @@ -644,7 +647,7 @@ impl Evaluator { (TyParam::UnaryOp { .. }, TyParam::UnaryOp { .. }) => todo!(), (TyParam::App { .. }, TyParam::App { .. }) => todo!(), (TyParam::Mono(m), TyParam::Value(l)) | (TyParam::Value(l), TyParam::Mono(m)) => { - if let Some(o) = ctx.consts.get(m) { + if let Some(o) = self.rec_get_const_obj(m) { o == l } else { true diff --git a/compiler/erg_compiler/lower.rs b/compiler/erg_compiler/lower.rs index 1afb6ff0..42326d95 100644 --- a/compiler/erg_compiler/lower.rs +++ b/compiler/erg_compiler/lower.rs @@ -162,7 +162,7 @@ impl ASTLowerer { } fn gen_array_with_length_type(&self, elem: &hir::Expr, len: &ast::Expr) -> Type { - let maybe_len = self.ctx.eval.eval_const_expr(len, &self.ctx); + let maybe_len = self.ctx.eval_const_expr(len, None); match maybe_len { Some(v @ ValueObj::Nat(_)) => { if elem.ref_t().is_mut() { @@ -537,7 +537,7 @@ impl ASTLowerer { ast::Expr::UnaryOp(unary) => Ok(hir::Expr::UnaryOp(self.lower_unary(unary)?)), ast::Expr::Call(call) => Ok(hir::Expr::Call(self.lower_call(call)?)), ast::Expr::Lambda(lambda) => Ok(hir::Expr::Lambda(self.lower_lambda(lambda)?)), - ast::Expr::Def(def) => Ok(hir::Expr::Def(self.lower_def(def)?)), + // ast::Expr::Def(def) => Ok(hir::Expr::Def(self.lower_def(def)?)), other => todo!("{other}"), } } diff --git a/compiler/erg_type/lib.rs b/compiler/erg_type/lib.rs index a803395a..f1353999 100644 --- a/compiler/erg_type/lib.rs +++ b/compiler/erg_type/lib.rs @@ -129,12 +129,31 @@ macro_rules! impl_t_for_enum { #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct UserConstSubr { - code: CodeObj, + code: CodeObj, // may be this should be HIR or AST block +} + +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct ValueArgs { + pub pos_args: Vec, + pub kw_args: Dict, +} + +impl ValueArgs { + pub const fn new(pos_args: Vec, kw_args: Dict) -> Self { + ValueArgs { pos_args, kw_args } + } } #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct BuiltinConstSubr { - subr: fn(Vec) -> ValueObj, + subr: fn(ValueArgs, Option) -> ValueObj, + t: Type, +} + +impl BuiltinConstSubr { + pub const fn new(subr: fn(ValueArgs, Option) -> ValueObj, t: Type) -> Self { + Self { subr, t } + } } #[derive(Debug, Clone, PartialEq, Eq, Hash)] @@ -144,10 +163,17 @@ pub enum ConstSubr { } impl ConstSubr { - pub fn call(&self, args: Vec) -> ValueObj { + pub fn call(&self, args: ValueArgs, __name__: Option) -> ValueObj { match self { ConstSubr::User(_user) => todo!(), - ConstSubr::Builtin(builtin) => (builtin.subr)(args), + ConstSubr::Builtin(builtin) => (builtin.subr)(args, __name__), + } + } + + pub fn class(&self) -> Type { + match self { + ConstSubr::User(_user) => todo!(), + ConstSubr::Builtin(builtin) => builtin.t.clone(), } } } diff --git a/compiler/erg_type/value.rs b/compiler/erg_type/value.rs index e9e0720c..2527dd22 100644 --- a/compiler/erg_type/value.rs +++ b/compiler/erg_type/value.rs @@ -376,7 +376,7 @@ impl ValueObj { Self::Record(rec) => { Type::Record(rec.iter().map(|(k, v)| (k.clone(), v.class())).collect()) } - Self::Subr(_) => todo!(), + Self::Subr(subr) => subr.class(), Self::Type(_) => Type::Type, Self::None => Type::NoneType, Self::Ellipsis => Type::Ellipsis, From e2bd64ebe559f7191560c7536d2b418efa641901 Mon Sep 17 00:00:00 2001 From: Shunsuke Shibayama Date: Sat, 3 Sep 2022 01:52:23 +0900 Subject: [PATCH 05/68] Move python module definition files --- compiler/erg_compiler/context/initialize/mod.rs | 8 +------- .../context/initialize/{ => py_mods}/importlib.rs | 0 .../erg_compiler/context/initialize/{ => py_mods}/io.rs | 0 .../erg_compiler/context/initialize/{ => py_mods}/math.rs | 0 compiler/erg_compiler/context/initialize/py_mods/mod.rs | 7 +++++++ .../context/initialize/{ => py_mods}/random.rs | 0 .../context/initialize/{ => py_mods}/socket.rs | 0 .../erg_compiler/context/initialize/{ => py_mods}/sys.rs | 0 .../erg_compiler/context/initialize/{ => py_mods}/time.rs | 0 9 files changed, 8 insertions(+), 7 deletions(-) rename compiler/erg_compiler/context/initialize/{ => py_mods}/importlib.rs (100%) rename compiler/erg_compiler/context/initialize/{ => py_mods}/io.rs (100%) rename compiler/erg_compiler/context/initialize/{ => py_mods}/math.rs (100%) create mode 100644 compiler/erg_compiler/context/initialize/py_mods/mod.rs rename compiler/erg_compiler/context/initialize/{ => py_mods}/random.rs (100%) rename compiler/erg_compiler/context/initialize/{ => py_mods}/socket.rs (100%) rename compiler/erg_compiler/context/initialize/{ => py_mods}/sys.rs (100%) rename compiler/erg_compiler/context/initialize/{ => py_mods}/time.rs (100%) diff --git a/compiler/erg_compiler/context/initialize/mod.rs b/compiler/erg_compiler/context/initialize/mod.rs index 4f524ea1..83856b66 100644 --- a/compiler/erg_compiler/context/initialize/mod.rs +++ b/compiler/erg_compiler/context/initialize/mod.rs @@ -2,13 +2,7 @@ //! //! 組み込みオブジェクトの型情報を(Contextに)定義 pub mod const_func; -pub mod importlib; -pub mod io; -pub mod math; -pub mod random; -pub mod socket; -pub mod sys; -pub mod time; +pub mod py_mods; use erg_common::set; use erg_common::vis::Visibility; diff --git a/compiler/erg_compiler/context/initialize/importlib.rs b/compiler/erg_compiler/context/initialize/py_mods/importlib.rs similarity index 100% rename from compiler/erg_compiler/context/initialize/importlib.rs rename to compiler/erg_compiler/context/initialize/py_mods/importlib.rs diff --git a/compiler/erg_compiler/context/initialize/io.rs b/compiler/erg_compiler/context/initialize/py_mods/io.rs similarity index 100% rename from compiler/erg_compiler/context/initialize/io.rs rename to compiler/erg_compiler/context/initialize/py_mods/io.rs diff --git a/compiler/erg_compiler/context/initialize/math.rs b/compiler/erg_compiler/context/initialize/py_mods/math.rs similarity index 100% rename from compiler/erg_compiler/context/initialize/math.rs rename to compiler/erg_compiler/context/initialize/py_mods/math.rs diff --git a/compiler/erg_compiler/context/initialize/py_mods/mod.rs b/compiler/erg_compiler/context/initialize/py_mods/mod.rs new file mode 100644 index 00000000..3b5006b4 --- /dev/null +++ b/compiler/erg_compiler/context/initialize/py_mods/mod.rs @@ -0,0 +1,7 @@ +pub mod importlib; +pub mod io; +pub mod math; +pub mod random; +pub mod socket; +pub mod sys; +pub mod time; diff --git a/compiler/erg_compiler/context/initialize/random.rs b/compiler/erg_compiler/context/initialize/py_mods/random.rs similarity index 100% rename from compiler/erg_compiler/context/initialize/random.rs rename to compiler/erg_compiler/context/initialize/py_mods/random.rs diff --git a/compiler/erg_compiler/context/initialize/socket.rs b/compiler/erg_compiler/context/initialize/py_mods/socket.rs similarity index 100% rename from compiler/erg_compiler/context/initialize/socket.rs rename to compiler/erg_compiler/context/initialize/py_mods/socket.rs diff --git a/compiler/erg_compiler/context/initialize/sys.rs b/compiler/erg_compiler/context/initialize/py_mods/sys.rs similarity index 100% rename from compiler/erg_compiler/context/initialize/sys.rs rename to compiler/erg_compiler/context/initialize/py_mods/sys.rs diff --git a/compiler/erg_compiler/context/initialize/time.rs b/compiler/erg_compiler/context/initialize/py_mods/time.rs similarity index 100% rename from compiler/erg_compiler/context/initialize/time.rs rename to compiler/erg_compiler/context/initialize/py_mods/time.rs From e1eebb252fbddb02a14aaa8aafd63ef6e1f8dea5 Mon Sep 17 00:00:00 2001 From: Shunsuke Shibayama Date: Sat, 3 Sep 2022 11:59:18 +0900 Subject: [PATCH 06/68] Fix constant evaluation methods to return `EvalResult` --- compiler/erg_common/error.rs | 1 + .../erg_compiler/context/initialize/mod.rs | 6 +- compiler/erg_compiler/context/register.rs | 68 +++++-- compiler/erg_compiler/error.rs | 18 ++ compiler/erg_compiler/eval.rs | 170 +++++++++++------- compiler/erg_compiler/lower.rs | 26 ++- compiler/erg_parser/ast.rs | 28 ++- 7 files changed, 217 insertions(+), 100 deletions(-) diff --git a/compiler/erg_common/error.rs b/compiler/erg_common/error.rs index 7d54df97..c09ac28d 100644 --- a/compiler/erg_common/error.rs +++ b/compiler/erg_common/error.rs @@ -35,6 +35,7 @@ pub enum ErrorKind { PurityError, HasEffect, MoveError, + NotConstExpr, /* compile warnings */ AttributeWarning = 60, CastWarning, diff --git a/compiler/erg_compiler/context/initialize/mod.rs b/compiler/erg_compiler/context/initialize/mod.rs index 83856b66..eaad99c0 100644 --- a/compiler/erg_compiler/context/initialize/mod.rs +++ b/compiler/erg_compiler/context/initialize/mod.rs @@ -47,15 +47,15 @@ impl Context { } } - fn register_const(&mut self, name: &'static str, obj: ValueObj) { + pub(crate) fn register_const(&mut self, name: &str, obj: ValueObj) { if self.consts.get(name).is_some() { panic!("already registered: {name}"); } else { // TODO: visibility (not always private) // TODO: kind (not always Builtin) let vi = VarInfo::new(obj.t(), Const, Private, Builtin); - self.consts.insert(VarName::from_static(name), obj); - self.locals.insert(VarName::from_static(name), vi); + self.consts.insert(VarName::from_str(Str::rc(name)), obj); + self.locals.insert(VarName::from_str(Str::rc(name)), vi); } } diff --git a/compiler/erg_compiler/context/register.rs b/compiler/erg_compiler/context/register.rs index df880afc..1ac1bf5a 100644 --- a/compiler/erg_compiler/context/register.rs +++ b/compiler/erg_compiler/context/register.rs @@ -1,6 +1,6 @@ use std::option::Option; // conflicting to Type::Option -use erg_common::traits::Locational; +use erg_common::traits::{Locational, Stream}; use erg_common::vis::Visibility; use erg_common::Str; use erg_common::{enum_unwrap, get_hash, log, set}; @@ -315,30 +315,72 @@ impl Context { } } - // 再帰サブルーチン/型の推論を可能にするため、予め登録しておく - pub(crate) fn preregister(&mut self, block: &[ast::Expr]) -> TyCheckResult<()> { + // To allow forward references and recursive definitions + pub(crate) fn preregister(&mut self, block: &ast::Block) -> TyCheckResult<()> { for expr in block.iter() { if let ast::Expr::Def(def) = expr { let id = Some(def.body.id); let __name__ = def.sig.ident().map(|i| i.inspect()); - let mut eval_body_t = || { - self.eval_const_block(&def.body.block, __name__) - .map(|c| enum_t(set![c])) - }; match &def.sig { ast::Signature::Subr(sig) => { - let opt_ret_t = if let Some(spec) = sig.return_t_spec.as_ref() { - Some(self.instantiate_typespec(spec, PreRegister)?) + let const_t = if sig.is_const() { + match self.eval_const_block(&def.body.block, __name__) { + Ok(obj) => { + self.register_const(__name__.unwrap(), obj.clone()); + Some(enum_t(set![obj])) + } + Err(e) => { + return Err(e); + } + } } else { - eval_body_t() + None + }; + let opt_ret_t = if let Some(spec) = sig.return_t_spec.as_ref() { + let spec_t = self.instantiate_typespec(spec, PreRegister)?; + if let Some(const_t) = const_t { + self.sub_unify( + &const_t, + &spec_t, + Some(def.body.loc()), + None, + None, + )?; + } + Some(spec_t) + } else { + const_t }; self.declare_sub(sig, opt_ret_t, id)?; } ast::Signature::Var(sig) if sig.is_const() => { - let t = if let Some(spec) = sig.t_spec.as_ref() { - Some(self.instantiate_typespec(spec, PreRegister)?) + let const_t = if sig.is_const() { + match self.eval_const_block(&def.body.block, __name__) { + Ok(obj) => { + self.register_const(__name__.unwrap(), obj.clone()); + Some(enum_t(set![obj])) + } + Err(e) => { + return Err(e); + } + } } else { - eval_body_t() + None + }; + let t = if let Some(spec) = sig.t_spec.as_ref() { + let spec_t = self.instantiate_typespec(spec, PreRegister)?; + if let Some(const_t) = const_t { + self.sub_unify( + &const_t, + &spec_t, + Some(def.body.loc()), + None, + None, + )?; + } + Some(spec_t) + } else { + const_t }; self.declare_var(sig, t, id)?; } diff --git a/compiler/erg_compiler/error.rs b/compiler/erg_compiler/error.rs index b6081d61..c38f02e8 100644 --- a/compiler/erg_compiler/error.rs +++ b/compiler/erg_compiler/error.rs @@ -1019,6 +1019,24 @@ passed keyword args: {RED}{kw_args_len}{RESET}" caused_by, ) } + + pub fn not_const_expr(errno: usize, loc: Location, caused_by: Str) -> Self { + Self::new( + ErrorCore::new( + errno, + NotConstExpr, + loc, + switch_lang!( + "japanese" => "定数式ではありません", + "simplified_chinese" => "不是常量表达式", + "traditional_chinese" => "不是常量表達式", + "english" => "not a constant expression", + ), + None, + ), + caused_by, + ) + } } #[derive(Debug)] diff --git a/compiler/erg_compiler/eval.rs b/compiler/erg_compiler/eval.rs index 864e16cc..310c9c11 100644 --- a/compiler/erg_compiler/eval.rs +++ b/compiler/erg_compiler/eval.rs @@ -3,9 +3,9 @@ use std::mem; use erg_common::dict::Dict; use erg_common::rccell::RcCell; use erg_common::set::Set; -use erg_common::traits::Stream; +use erg_common::traits::{Locational, Stream}; use erg_common::vis::Field; -use erg_common::{dict, fn_name, set}; +use erg_common::{dict, fn_name, option_enum_unwrap, set}; use erg_common::{RcArray, Str}; use OpKind::*; @@ -13,11 +13,11 @@ use erg_parser::ast::*; use erg_parser::token::{Token, TokenKind}; use erg_type::constructors::{ - enum_t, mono_proj, poly_class, poly_trait, ref_, ref_mut, refinement, subr_t, + class, enum_t, mono_proj, poly_class, poly_trait, ref_, ref_mut, refinement, subr_t, }; use erg_type::typaram::{OpKind, TyParam}; use erg_type::value::ValueObj; -use erg_type::{Predicate, SubrKind, TyBound, Type, ValueArgs}; +use erg_type::{HasType, Predicate, SubrKind, TyBound, Type, ValueArgs}; use crate::context::instantiate::TyVarContext; use crate::context::Context; @@ -41,7 +41,7 @@ pub fn type_from_token_kind(kind: TokenKind) -> Type { } } -fn try_get_op_kind_from_token(kind: TokenKind) -> Result { +fn try_get_op_kind_from_token(kind: TokenKind) -> EvalResult { match kind { TokenKind::Plus => Ok(OpKind::Add), TokenKind::Minus => Ok(OpKind::Sub), @@ -63,7 +63,7 @@ fn try_get_op_kind_from_token(kind: TokenKind) -> Result { TokenKind::Shl => Ok(OpKind::Shl), TokenKind::Shr => Ok(OpKind::Shr), TokenKind::Mutate => Ok(OpKind::Mutate), - _other => Err(()), + _other => todo!("{_other}"), } } @@ -166,44 +166,58 @@ impl SubstContext { } impl Context { - fn eval_const_acc(&self, _acc: &Accessor) -> Option { - match _acc { + fn eval_const_acc(&self, acc: &Accessor) -> EvalResult { + match acc { Accessor::Local(local) => { if let Some(val) = self.rec_get_const_obj(local.inspect()) { - Some(val.clone()) + Ok(val.clone()) } else { - None + if local.is_const() { + Err(EvalError::no_var_error( + line!() as usize, + local.loc(), + self.caused_by(), + local.inspect(), + self.get_similar_name(local.inspect()), + )) + } else { + Err(EvalError::not_const_expr( + line!() as usize, + acc.loc(), + self.caused_by(), + )) + } } } Accessor::Attr(attr) => { - let _obj = self.eval_const_expr(&attr.obj, None)?; + let _obj = self.eval_const_expr(&attr.obj, None); todo!() } _ => todo!(), } } - fn eval_const_bin(&self, bin: &BinOp) -> Option { + fn eval_const_bin(&self, bin: &BinOp) -> EvalResult { match (bin.args[0].as_ref(), bin.args[1].as_ref()) { (Expr::Lit(l), Expr::Lit(r)) => { - let op = try_get_op_kind_from_token(bin.op.kind).ok()?; - self.eval_bin_lit(op, eval_lit(l), eval_lit(r)).ok() + let op = try_get_op_kind_from_token(bin.op.kind)?; + self.eval_bin_lit(op, eval_lit(l), eval_lit(r)) } - _ => None, + _ => todo!(), } } - fn eval_const_unary(&self, unary: &UnaryOp) -> Option { + fn eval_const_unary(&self, unary: &UnaryOp) -> EvalResult { match unary.args[0].as_ref() { Expr::Lit(lit) => { - let op = try_get_op_kind_from_token(unary.op.kind).ok()?; - self.eval_unary_lit(op, eval_lit(lit)).ok() + let op = try_get_op_kind_from_token(unary.op.kind)?; + self.eval_unary_lit(op, eval_lit(lit)) } - _ => None, + _ => todo!(), } } - fn eval_args(&self, args: &Args, __name__: Option<&Str>) -> Option { + fn eval_args(&self, args: &Args, __name__: Option<&Str>) -> EvalResult { let mut evaluated_pos_args = vec![]; for arg in args.pos_args().iter() { let val = self.eval_const_expr(&arg.expr, __name__)?; @@ -214,96 +228,116 @@ impl Context { let val = self.eval_const_expr(&arg.expr, __name__)?; evaluated_kw_args.insert(arg.keyword.inspect().clone(), val); } - Some(ValueArgs::new(evaluated_pos_args, evaluated_kw_args)) + Ok(ValueArgs::new(evaluated_pos_args, evaluated_kw_args)) } - fn eval_const_call(&self, call: &Call, __name__: Option<&Str>) -> Option { + fn eval_const_call(&self, call: &Call, __name__: Option<&Str>) -> EvalResult { if let Expr::Accessor(acc) = call.obj.as_ref() { match acc { - Accessor::Local(name) if name.is_const() => { - if let Some(ValueObj::Subr(subr)) = self.rec_get_const_obj(&name.inspect()) { - let subr = subr.clone(); - let args = self.eval_args(&call.args, __name__)?; - Some(subr.call(args, __name__.map(|n| n.clone()))) - } else { - None - } + Accessor::Local(name) => { + let obj = + self.rec_get_const_obj(&name.inspect()) + .ok_or(EvalError::no_var_error( + line!() as usize, + name.loc(), + self.caused_by(), + name.inspect(), + self.get_similar_name(name.inspect()), + ))?; + let subr = option_enum_unwrap!(obj, ValueObj::Subr) + .ok_or(EvalError::type_mismatch_error( + line!() as usize, + name.loc(), + self.caused_by(), + name.inspect(), + &class("Subroutine"), + &obj.t(), + None, + ))? + .clone(); + let args = self.eval_args(&call.args, __name__)?; + Ok(subr.call(args, __name__.map(|n| n.clone()))) } - Accessor::Local(_) => None, Accessor::Attr(_attr) => todo!(), Accessor::TupleAttr(_attr) => todo!(), Accessor::Public(_name) => todo!(), Accessor::Subscr(_subscr) => todo!(), } } else { - None - } - } - - fn eval_const_def(&mut self, def: &Def) -> Option { - if def.is_const() { todo!() } - None } - fn eval_const_array(&self, arr: &Array) -> Option { + fn eval_const_def(&mut self, def: &Def) -> EvalResult { + if def.is_const() { + let __name__ = def.sig.ident().map(|i| i.inspect()).unwrap(); + let obj = self.eval_const_block(&def.body.block, Some(__name__))?; + erg_common::log!(); + self.register_const(__name__, obj); + Ok(ValueObj::None) + } else { + Err(EvalError::not_const_expr( + line!() as usize, + def.body.block.loc(), + self.caused_by(), + )) + } + } + + fn eval_const_array(&self, arr: &Array) -> EvalResult { let mut elems = vec![]; match arr { Array::Normal(arr) => { for elem in arr.elems.pos_args().iter() { - if let Some(elem) = self.eval_const_expr(&elem.expr, None) { - elems.push(elem); - } else { - return None; - } + let elem = self.eval_const_expr(&elem.expr, None)?; + elems.push(elem); } } _ => { - return None; + todo!() } } - Some(ValueObj::Array(RcArray::from(elems))) + Ok(ValueObj::Array(RcArray::from(elems))) } - fn eval_const_record(&mut self, record: &Record) -> Option { + fn eval_const_record(&self, record: &Record) -> EvalResult { match record { Record::Normal(rec) => self.eval_const_normal_record(rec), Record::Shortened(_rec) => unreachable!(), // should be desugared } } - fn eval_const_normal_record(&mut self, record: &NormalRecord) -> Option { + fn eval_const_normal_record(&self, record: &NormalRecord) -> EvalResult { let mut attrs = vec![]; + let mut record_ctx = Context::default(); // TODO: include outer context for attr in record.attrs.iter() { let name = attr.sig.ident().map(|i| i.inspect()); - if let Some(elem) = self.eval_const_block(&attr.body.block, name) { - let ident = match &attr.sig { - Signature::Var(var) => match &var.pat { - VarPattern::Ident(ident) => { - Field::new(ident.vis(), ident.inspect().clone()) - } - _ => todo!(), - }, + let elem = record_ctx.eval_const_block(&attr.body.block, name)?; + let ident = match &attr.sig { + Signature::Var(var) => match &var.pat { + VarPattern::Ident(ident) => Field::new(ident.vis(), ident.inspect().clone()), _ => todo!(), - }; - attrs.push((ident, elem)); - } else { - return None; - } + }, + _ => todo!(), + }; + attrs.push((ident, elem)); } - Some(ValueObj::Record(attrs.into_iter().collect())) + Ok(ValueObj::Record(attrs.into_iter().collect())) } - pub(crate) fn eval_const_expr(&self, expr: &Expr, __name__: Option<&Str>) -> Option { + pub(crate) fn eval_const_expr( + &self, + expr: &Expr, + __name__: Option<&Str>, + ) -> EvalResult { match expr { - Expr::Lit(lit) => Some(eval_lit(lit)), + Expr::Lit(lit) => Ok(eval_lit(lit)), Expr::Accessor(acc) => self.eval_const_acc(acc), Expr::BinOp(bin) => self.eval_const_bin(bin), Expr::UnaryOp(unary) => self.eval_const_unary(unary), Expr::Call(call) => self.eval_const_call(call, __name__), Expr::Array(arr) => self.eval_const_array(arr), - Expr::Record(rec) => todo!("{rec}"), // self.eval_const_record(rec), + Expr::Record(rec) => self.eval_const_record(rec), Expr::Lambda(lambda) => todo!("{lambda}"), other => todo!("{other}"), } @@ -315,9 +349,9 @@ impl Context { &mut self, expr: &Expr, __name__: Option<&Str>, - ) -> Option { + ) -> EvalResult { match expr { - Expr::Lit(lit) => Some(eval_lit(lit)), + Expr::Lit(lit) => Ok(eval_lit(lit)), Expr::Accessor(acc) => self.eval_const_acc(acc), Expr::BinOp(bin) => self.eval_const_bin(bin), Expr::UnaryOp(unary) => self.eval_const_unary(unary), @@ -334,7 +368,7 @@ impl Context { &mut self, block: &Block, __name__: Option<&Str>, - ) -> Option { + ) -> EvalResult { for chunk in block.iter().rev().skip(1).rev() { self.eval_const_chunk(chunk, __name__)?; } diff --git a/compiler/erg_compiler/lower.rs b/compiler/erg_compiler/lower.rs index 42326d95..b054c163 100644 --- a/compiler/erg_compiler/lower.rs +++ b/compiler/erg_compiler/lower.rs @@ -164,7 +164,7 @@ impl ASTLowerer { fn gen_array_with_length_type(&self, elem: &hir::Expr, len: &ast::Expr) -> Type { let maybe_len = self.ctx.eval_const_expr(len, None); match maybe_len { - Some(v @ ValueObj::Nat(_)) => { + Ok(v @ ValueObj::Nat(_)) => { if elem.ref_t().is_mut() { poly_class( "ArrayWithMutType!", @@ -174,7 +174,7 @@ impl ASTLowerer { array(elem.t(), TyParam::Value(v)) } } - Some(v @ ValueObj::Mut(_)) if v.class() == class("Nat!") => { + Ok(v @ ValueObj::Mut(_)) if v.class() == class("Nat!") => { if elem.ref_t().is_mut() { poly_class( "ArrayWithMutTypeAndLength!", @@ -184,9 +184,9 @@ impl ASTLowerer { array_mut(elem.t(), TyParam::Value(v)) } } - Some(other) => todo!("{other} is not a Nat object"), - // TODO: [T; !_] - None => { + Ok(other) => todo!("{other} is not a Nat object"), + // REVIEW: is it ok to ignore the error? + Err(_e) => { if elem.ref_t().is_mut() { poly_class( "ArrayWithMutType!", @@ -366,12 +366,10 @@ impl ASTLowerer { self.pop_append_errs(); e })?; - self.ctx - .preregister(lambda.body.ref_payload()) - .map_err(|e| { - self.pop_append_errs(); - e - })?; + self.ctx.preregister(&lambda.body).map_err(|e| { + self.pop_append_errs(); + e + })?; let body = self.lower_block(lambda.body).map_err(|e| { self.pop_append_errs(); e @@ -437,7 +435,7 @@ impl ASTLowerer { body: ast::DefBody, ) -> LowerResult { log!(info "entered {}({sig})", fn_name!()); - self.ctx.preregister(body.block.ref_payload())?; + self.ctx.preregister(&body.block)?; let block = self.lower_block(body.block)?; let found_body_t = block.ref_t(); let opt_expect_body_t = self @@ -503,7 +501,7 @@ impl ASTLowerer { .t .clone(); self.ctx.assign_params(&sig.params, None)?; - self.ctx.preregister(body.block.ref_payload())?; + self.ctx.preregister(&body.block)?; let block = self.lower_block(body.block)?; let found_body_t = block.ref_t(); let expect_body_t = t.return_t().unwrap(); @@ -556,7 +554,7 @@ impl ASTLowerer { log!(info "the AST lowering process has started."); log!(info "the type-checking process has started."); let mut module = hir::Module::with_capacity(ast.module.len()); - self.ctx.preregister(ast.module.ref_payload())?; + self.ctx.preregister(ast.module.block())?; for expr in ast.module.into_iter() { match self.lower_expr(expr).and_then(|e| self.use_check(e, mode)) { Ok(expr) => { diff --git a/compiler/erg_parser/ast.rs b/compiler/erg_parser/ast.rs index b74b3298..02cbcd99 100644 --- a/compiler/erg_parser/ast.rs +++ b/compiler/erg_parser/ast.rs @@ -2846,7 +2846,7 @@ impl Expr { } #[derive(Clone, Debug, PartialEq, Eq, Hash)] -pub struct Module(Vec); +pub struct Module(Block); impl fmt::Display for Module { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { @@ -2860,7 +2860,31 @@ impl Locational for Module { } } -impl_stream_for_wrapper!(Module, Expr); +impl Stream for Module { + fn payload(self) -> Vec { + self.0.payload() + } + fn ref_payload(&self) -> &Vec { + self.0.ref_payload() + } + fn ref_mut_payload(&mut self) -> &mut Vec { + self.0.ref_mut_payload() + } +} + +impl Module { + pub const fn empty() -> Self { + Self(Block::empty()) + } + #[inline] + pub fn with_capacity(capacity: usize) -> Self { + Self(Block::with_capacity(capacity)) + } + + pub fn block(&self) -> &Block { + &self.0 + } +} #[derive(Debug)] pub struct AST { From 618f73f0c0cc4e62f6e26d485bfbc64d5757987e Mon Sep 17 00:00:00 2001 From: Shunsuke Shibayama Date: Sat, 3 Sep 2022 12:07:27 +0900 Subject: [PATCH 07/68] Unify `poly_classes` and `poly_traits` of `Context` --- .../erg_compiler/context/initialize/mod.rs | 38 ++----------------- compiler/erg_compiler/context/inquire.rs | 9 +---- compiler/erg_compiler/context/mod.rs | 9 ++--- compiler/erg_compiler/lower.rs | 2 +- 4 files changed, 10 insertions(+), 48 deletions(-) diff --git a/compiler/erg_compiler/context/initialize/mod.rs b/compiler/erg_compiler/context/initialize/mod.rs index eaad99c0..cba1ad7b 100644 --- a/compiler/erg_compiler/context/initialize/mod.rs +++ b/compiler/erg_compiler/context/initialize/mod.rs @@ -71,13 +71,7 @@ impl Context { if t.typarams_len().is_none() { self.register_mono_type(t, ctx, muty); } else { - if t.is_class() { - self.register_poly_class(t, ctx, muty); - } else if t.is_trait() { - self.register_poly_trait(t, ctx, muty); - } else { - todo!() - } + self.register_poly_type(t, ctx, muty); } } @@ -103,10 +97,10 @@ impl Context { } } - fn register_poly_class(&mut self, t: Type, ctx: Self, muty: Mutability) { + fn register_poly_type(&mut self, t: Type, ctx: Self, muty: Mutability) { let mut tv_ctx = TyVarContext::new(self.level, ctx.type_params_bounds(), self); let t = Self::instantiate_t(t, &mut tv_ctx); - if let Some((_, root_ctx)) = self.poly_classes.get_mut(&t.name()) { + if let Some((_, root_ctx)) = self.poly_types.get_mut(&t.name()) { root_ctx.specializations.push((t, ctx)); } else { let name = VarName::from_str(t.name()); @@ -123,31 +117,7 @@ impl Context { ); } } - self.poly_classes.insert(name, (t, ctx)); - } - } - - fn register_poly_trait(&mut self, t: Type, ctx: Self, muty: Mutability) { - if self.poly_traits.contains_key(&t.name()) { - panic!("{} has already been registered", t.name()); - } else { - let mut tv_ctx = TyVarContext::new(self.level, ctx.type_params_bounds(), self); - let t = Self::instantiate_t(t, &mut tv_ctx); - let name = VarName::from_str(t.name()); - self.locals - .insert(name.clone(), VarInfo::new(Type, muty, Private, Builtin)); - self.consts.insert(name.clone(), ValueObj::t(t.clone())); - for impl_trait in ctx.super_traits.iter() { - if let Some(impls) = self.trait_impls.get_mut(&impl_trait.name()) { - impls.push(TraitInstance::new(t.clone(), impl_trait.clone())); - } else { - self.trait_impls.insert( - impl_trait.name(), - vec![TraitInstance::new(t.clone(), impl_trait.clone())], - ); - } - } - self.poly_traits.insert(name, (t, ctx)); + self.poly_types.insert(name, (t, ctx)); } } diff --git a/compiler/erg_compiler/context/inquire.rs b/compiler/erg_compiler/context/inquire.rs index ebd7a8f2..ac5d80d4 100644 --- a/compiler/erg_compiler/context/inquire.rs +++ b/compiler/erg_compiler/context/inquire.rs @@ -1000,13 +1000,8 @@ impl Context { Type::Quantified(_) => { return self.rec_get_nominal_type_ctx(&class("QuantifiedFunction")); } - Type::PolyClass { name, params: _ } => { - if let Some((t, ctx)) = self.poly_classes.get(name) { - return Some((t, ctx)); - } - } - Type::PolyTrait { name, params: _ } => { - if let Some((t, ctx)) = self.poly_traits.get(name) { + Type::PolyClass { name, params: _ } | Type::PolyTrait { name, params: _ } => { + if let Some((t, ctx)) = self.poly_types.get(name) { return Some((t, ctx)); } } diff --git a/compiler/erg_compiler/context/mod.rs b/compiler/erg_compiler/context/mod.rs index 7ac2ad14..a4299f1b 100644 --- a/compiler/erg_compiler/context/mod.rs +++ b/compiler/erg_compiler/context/mod.rs @@ -258,9 +258,7 @@ pub struct Context { // Implementation Contexts for Polymorphic Types // Vec are specialization parameters // e.g. {"Array": [(Array(Nat), ctx), (Array(Int), ctx), (Array(Str), ctx), (Array(Obj), ctx), (Array('T), ctx)], ...} - pub(crate) poly_classes: Dict, - // Traits cannot be specialized - pub(crate) poly_traits: Dict, + pub(crate) poly_types: Dict, // patches can be accessed like normal records // but when used as a fallback to a type, values are traversed instead of accessing by keys pub(crate) patches: Dict, @@ -295,7 +293,7 @@ impl fmt::Display for Context { .field("locals", &self.params) .field("consts", &self.consts) .field("mono_types", &self.mono_types) - .field("poly_types", &self.poly_classes) + .field("poly_types", &self.poly_types) .field("patches", &self.patches) .field("mods", &self.mods) .finish() @@ -368,8 +366,7 @@ impl Context { locals: Dict::with_capacity(capacity), consts: Dict::default(), mono_types: Dict::default(), - poly_classes: Dict::default(), - poly_traits: Dict::default(), + poly_types: Dict::default(), mods: Dict::default(), patches: Dict::default(), _nlocals: 0, diff --git a/compiler/erg_compiler/lower.rs b/compiler/erg_compiler/lower.rs index b054c163..2cea42ef 100644 --- a/compiler/erg_compiler/lower.rs +++ b/compiler/erg_compiler/lower.rs @@ -535,7 +535,7 @@ impl ASTLowerer { ast::Expr::UnaryOp(unary) => Ok(hir::Expr::UnaryOp(self.lower_unary(unary)?)), ast::Expr::Call(call) => Ok(hir::Expr::Call(self.lower_call(call)?)), ast::Expr::Lambda(lambda) => Ok(hir::Expr::Lambda(self.lower_lambda(lambda)?)), - // ast::Expr::Def(def) => Ok(hir::Expr::Def(self.lower_def(def)?)), + ast::Expr::Def(def) => Ok(hir::Expr::Def(self.lower_def(def)?)), other => todo!("{other}"), } } From 78c0b60f3f613da66ed6e50f2bafe4b47defa111 Mon Sep 17 00:00:00 2001 From: Shunsuke Shibayama Date: Sat, 3 Sep 2022 15:22:44 +0900 Subject: [PATCH 08/68] Fix inference bugs --- compiler/erg_common/error.rs | 13 ++- .../erg_compiler/context/initialize/mod.rs | 4 +- compiler/erg_compiler/context/inquire.rs | 68 +++++++++----- compiler/erg_compiler/context/mod.rs | 16 +++- compiler/erg_compiler/context/register.rs | 91 +++++++++---------- compiler/erg_compiler/error.rs | 12 ++- compiler/erg_compiler/eval.rs | 3 +- compiler/erg_compiler/lower.rs | 28 +++--- 8 files changed, 140 insertions(+), 95 deletions(-) diff --git a/compiler/erg_common/error.rs b/compiler/erg_common/error.rs index c09ac28d..90e16a86 100644 --- a/compiler/erg_common/error.rs +++ b/compiler/erg_common/error.rs @@ -36,6 +36,7 @@ pub enum ErrorKind { HasEffect, MoveError, NotConstExpr, + DummyError, /* compile warnings */ AttributeWarning = 60, CastWarning, @@ -317,8 +318,18 @@ impl ErrorCore { } } + pub fn dummy(errno: usize) -> Self { + Self::new( + errno, + DummyError, + Location::Line(errno as usize), + "", + None, + ) + } + pub fn unreachable(fn_name: &str, line: u32) -> Self { - Self::bug(line as usize, Location::Unknown, fn_name, line) + Self::bug(line as usize, Location::Line(line as usize), fn_name, line) } pub fn bug(errno: usize, loc: Location, fn_name: &str, line: u32) -> Self { diff --git a/compiler/erg_compiler/context/initialize/mod.rs b/compiler/erg_compiler/context/initialize/mod.rs index cba1ad7b..0baeeacb 100644 --- a/compiler/erg_compiler/context/initialize/mod.rs +++ b/compiler/erg_compiler/context/initialize/mod.rs @@ -10,8 +10,8 @@ use erg_common::Str; use erg_type::typaram::TyParam; use erg_type::value::ValueObj; +use erg_type::Type; use erg_type::{constructors::*, BuiltinConstSubr, ConstSubr}; -use erg_type::{HasType, Type}; use ParamSpec as PS; use Type::*; @@ -53,7 +53,7 @@ impl Context { } else { // TODO: visibility (not always private) // TODO: kind (not always Builtin) - let vi = VarInfo::new(obj.t(), Const, Private, Builtin); + 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); } diff --git a/compiler/erg_compiler/context/inquire.rs b/compiler/erg_compiler/context/inquire.rs index ac5d80d4..797fdcaf 100644 --- a/compiler/erg_compiler/context/inquire.rs +++ b/compiler/erg_compiler/context/inquire.rs @@ -1,7 +1,7 @@ // (type) getters & validators use std::option::Option; // conflicting to Type::Option -use erg_common::error::ErrorCore; +use erg_common::error::{ErrorCore, ErrorKind}; use erg_common::levenshtein::levenshtein; use erg_common::set::Set; use erg_common::traits::Locational; @@ -226,30 +226,14 @@ impl Context { namespace: &Str, ) -> TyCheckResult { let self_t = obj.t(); - match self_t { - Type => todo!(), - Type::Record(rec) => { - // REVIEW: `rec.get(name.inspect())` returns None (Borrow is implemented for Field). Why? - if let Some(attr) = rec.get(&Field::new(Public, name.inspect().clone())) { - return Ok(attr.clone()); - } else { - let t = Type::Record(rec); - return Err(TyCheckError::no_attr_error( - line!() as usize, - name.loc(), - namespace.clone(), - &t, - name.inspect(), - self.get_similar_attr(&t, name.inspect()), - )); - } - } - Module => { - let mod_ctx = self.get_context(obj, Some(ContextKind::Module), namespace)?; - let t = mod_ctx.rec_get_var_t(name, Public, namespace)?; + match self.get_attr_t_from_t(obj, &self_t, name, namespace) { + Ok(t) => { return Ok(t); } - _ => {} + Err(e) if e.core.kind == ErrorKind::DummyError => {} + Err(e) => { + return Err(e); + } } for (_, ctx) in self.rec_get_nominal_super_type_ctxs(&self_t) { if let Ok(t) = ctx.rec_get_var_t(name, Public, namespace) { @@ -271,6 +255,44 @@ impl Context { } } + fn get_attr_t_from_t( + &self, + obj: &hir::Expr, + t: &Type, + name: &Token, + namespace: &Str, + ) -> TyCheckResult { + match t { + Type => todo!(), + Type::FreeVar(fv) if fv.is_linked() => { + self.get_attr_t_from_t(obj, &fv.crack(), name, namespace) + } + Type::Refinement(refine) => self.get_attr_t_from_t(obj, &refine.t, name, namespace), + Type::Record(record) => { + // REVIEW: `rec.get(name.inspect())` returns None (Borrow is implemented for Field). Why? + if let Some(attr) = record.get(&Field::new(Public, name.inspect().clone())) { + Ok(attr.clone()) + } else { + let t = Type::Record(record.clone()); + Err(TyCheckError::no_attr_error( + line!() as usize, + name.loc(), + namespace.clone(), + &t, + name.inspect(), + self.get_similar_attr(&t, name.inspect()), + )) + } + } + Module => { + let mod_ctx = self.get_context(obj, Some(ContextKind::Module), namespace)?; + let t = mod_ctx.rec_get_var_t(name, Public, namespace)?; + Ok(t) + } + _ => Err(TyCheckError::dummy(line!() as usize)), + } + } + /// 戻り値ではなく、call全体の型を返す fn search_callee_t( &self, diff --git a/compiler/erg_compiler/context/mod.rs b/compiler/erg_compiler/context/mod.rs index a4299f1b..ef9eef24 100644 --- a/compiler/erg_compiler/context/mod.rs +++ b/compiler/erg_compiler/context/mod.rs @@ -214,7 +214,7 @@ pub enum RegistrationMode { /// Represents the context of the current scope /// /// Recursive functions/methods are highlighted with the prefix `rec_`, as performance may be significantly degraded. -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct Context { pub(crate) name: Str, pub(crate) kind: ContextKind, @@ -502,6 +502,20 @@ impl Context { ) } + #[inline] + pub fn instant(name: Str, capacity: usize, outer: Context) -> Self { + Self::with_capacity( + name, + ContextKind::Instant, + vec![], + Some(outer), + vec![], + vec![], + capacity, + Self::TOP_LEVEL, + ) + } + #[inline] pub fn caused_by(&self) -> Str { self.name.clone() diff --git a/compiler/erg_compiler/context/register.rs b/compiler/erg_compiler/context/register.rs index 1ac1bf5a..7b111b4d 100644 --- a/compiler/erg_compiler/context/register.rs +++ b/compiler/erg_compiler/context/register.rs @@ -24,7 +24,8 @@ use RegistrationMode::*; use Visibility::*; impl Context { - fn registered(&self, name: &Str, recursive: bool) -> bool { + /// If it is a constant that is defined, there must be no variable of the same name defined across all scopes + fn registered(&self, name: &Str, is_const: bool) -> bool { if self.params.iter().any(|(maybe_name, _)| { maybe_name .as_ref() @@ -34,9 +35,9 @@ impl Context { { return true; } - if recursive { + if is_const { if let Some(outer) = &self.outer { - outer.registered(name, recursive) + outer.registered(name, is_const) } else { false } @@ -45,7 +46,7 @@ impl Context { } } - fn declare_var( + fn _declare_var( &mut self, sig: &ast::VarSignature, opt_t: Option, @@ -122,6 +123,10 @@ impl Context { body_t: &Type, id: DefId, ) -> TyCheckResult<()> { + // already defined as const + if sig.is_const() { + return Ok(()); + } let ident = match &sig.pat { ast::VarPattern::Ident(ident) => ident, _ => todo!(), @@ -236,6 +241,10 @@ impl Context { id: DefId, body_t: &Type, ) -> TyCheckResult<()> { + // already defined as const + if sig.is_const() { + return Ok(()); + } let muty = if sig.ident.is_const() { Mutability::Const } else { @@ -323,22 +332,16 @@ impl Context { let __name__ = def.sig.ident().map(|i| i.inspect()); match &def.sig { ast::Signature::Subr(sig) => { - let const_t = if sig.is_const() { - match self.eval_const_block(&def.body.block, __name__) { - Ok(obj) => { - self.register_const(__name__.unwrap(), obj.clone()); - Some(enum_t(set![obj])) - } - Err(e) => { - return Err(e); - } - } - } else { - None - }; - let opt_ret_t = if let Some(spec) = sig.return_t_spec.as_ref() { - let spec_t = self.instantiate_typespec(spec, PreRegister)?; - if let Some(const_t) = const_t { + if sig.is_const() { + let (obj, const_t) = + match self.eval_const_block(&def.body.block, __name__) { + Ok(obj) => (obj.clone(), enum_t(set! {obj})), + Err(e) => { + return Err(e); + } + }; + if let Some(spec) = sig.return_t_spec.as_ref() { + let spec_t = self.instantiate_typespec(spec, PreRegister)?; self.sub_unify( &const_t, &spec_t, @@ -347,42 +350,30 @@ impl Context { None, )?; } - Some(spec_t) + self.register_const(__name__.unwrap(), obj); } else { - const_t - }; - self.declare_sub(sig, opt_ret_t, id)?; + let opt_ret_t = if let Some(spec) = sig.return_t_spec.as_ref() { + let spec_t = self.instantiate_typespec(spec, PreRegister)?; + Some(spec_t) + } else { + None + }; + self.declare_sub(sig, opt_ret_t, id)?; + } } ast::Signature::Var(sig) if sig.is_const() => { - let const_t = if sig.is_const() { - match self.eval_const_block(&def.body.block, __name__) { - Ok(obj) => { - self.register_const(__name__.unwrap(), obj.clone()); - Some(enum_t(set![obj])) - } - Err(e) => { - return Err(e); - } + let (obj, const_t) = match self.eval_const_block(&def.body.block, __name__) + { + Ok(obj) => (obj.clone(), enum_t(set! {obj})), + Err(e) => { + return Err(e); } - } else { - None }; - let t = if let Some(spec) = sig.t_spec.as_ref() { + if let Some(spec) = sig.t_spec.as_ref() { let spec_t = self.instantiate_typespec(spec, PreRegister)?; - if let Some(const_t) = const_t { - self.sub_unify( - &const_t, - &spec_t, - Some(def.body.loc()), - None, - None, - )?; - } - Some(spec_t) - } else { - const_t - }; - self.declare_var(sig, t, id)?; + self.sub_unify(&const_t, &spec_t, Some(def.body.loc()), None, None)?; + } + self.register_const(__name__.unwrap(), obj); } _ => {} } diff --git a/compiler/erg_compiler/error.rs b/compiler/erg_compiler/error.rs index c38f02e8..d6118b68 100644 --- a/compiler/erg_compiler/error.rs +++ b/compiler/erg_compiler/error.rs @@ -255,6 +255,10 @@ impl TyCheckError { Self { core, caused_by } } + pub fn dummy(errno: usize) -> Self { + Self::new(ErrorCore::dummy(errno), "".into()) + } + pub fn unreachable(fn_name: &str, line: u32) -> Self { Self::new(ErrorCore::unreachable(fn_name, line), "".into()) } @@ -657,10 +661,10 @@ impl TyCheckError { AssignError, loc, switch_lang!( - "japanese" => format!("定数{name}には再代入できません"), - "simplified_chinese" => format!("不能为不可变变量{name}分配两次"), - "traditional_chinese" => format!("不能為不可變變量{name}分配兩次"), - "english" => format!("cannot assign twice to the immutable variable {name}"), + "japanese" => format!("変数{name}に再代入されています"), + "simplified_chinese" => format!("不能为变量{name}分配两次"), + "traditional_chinese" => format!("不能為變量{name}分配兩次"), + "english" => format!("cannot assign twice to the variable {name}"), ), None, ), diff --git a/compiler/erg_compiler/eval.rs b/compiler/erg_compiler/eval.rs index 310c9c11..8e2e0ec9 100644 --- a/compiler/erg_compiler/eval.rs +++ b/compiler/erg_compiler/eval.rs @@ -309,7 +309,8 @@ impl Context { fn eval_const_normal_record(&self, record: &NormalRecord) -> EvalResult { let mut attrs = vec![]; - let mut record_ctx = Context::default(); // TODO: include outer context + // HACK: should avoid cloning + let mut record_ctx = Context::instant(Str::ever(""), 2, self.clone()); for attr in record.attrs.iter() { let name = attr.sig.ident().map(|i| i.inspect()); let elem = record_ctx.eval_const_block(&attr.body.block, name)?; diff --git a/compiler/erg_compiler/lower.rs b/compiler/erg_compiler/lower.rs index 2cea42ef..1ed7af22 100644 --- a/compiler/erg_compiler/lower.rs +++ b/compiler/erg_compiler/lower.rs @@ -450,10 +450,14 @@ impl ASTLowerer { _ => unreachable!(), }; if let Some(expect_body_t) = opt_expect_body_t { - if let Err(e) = - self.return_t_check(sig.loc(), ident.inspect(), &expect_body_t, found_body_t) - { - self.errs.push(e); + // TODO: expect_body_t is smaller for constants + // TODO: 定数の場合、expect_body_tのほうが小さくなってしまう + if !sig.is_const() { + if let Err(e) = + self.return_t_check(sig.loc(), ident.inspect(), &expect_body_t, found_body_t) + { + self.errs.push(e); + } } } let id = body.id; @@ -493,11 +497,7 @@ impl ASTLowerer { .as_ref() .unwrap() .get_current_scope_var(sig.ident.inspect()) - .unwrap_or_else(|| { - log!(info "{}\n", sig.ident.inspect()); - log!(info "{}\n", self.ctx.outer.as_ref().unwrap()); - panic!() - }) // FIXME: or instantiate + .unwrap() .t .clone(); self.ctx.assign_params(&sig.params, None)?; @@ -505,10 +505,12 @@ impl ASTLowerer { let block = self.lower_block(body.block)?; let found_body_t = block.ref_t(); let expect_body_t = t.return_t().unwrap(); - if let Err(e) = - self.return_t_check(sig.loc(), sig.ident.inspect(), &expect_body_t, found_body_t) - { - self.errs.push(e); + if !sig.is_const() { + if let Err(e) = + self.return_t_check(sig.loc(), sig.ident.inspect(), &expect_body_t, found_body_t) + { + self.errs.push(e); + } } let id = body.id; self.ctx From 094eb499fbc41d2e05544a99525c57324e92a79b Mon Sep 17 00:00:00 2001 From: Shunsuke Shibayama Date: Sat, 3 Sep 2022 15:52:55 +0900 Subject: [PATCH 09/68] Fix refinement inference bugs --- compiler/erg_compiler/context/initialize/mod.rs | 2 ++ compiler/erg_compiler/context/inquire.rs | 6 ++++++ compiler/erg_parser/ast.rs | 2 +- compiler/erg_type/lib.rs | 17 +++++++++++++++++ 4 files changed, 26 insertions(+), 1 deletion(-) diff --git a/compiler/erg_compiler/context/initialize/mod.rs b/compiler/erg_compiler/context/initialize/mod.rs index 0baeeacb..98e424c1 100644 --- a/compiler/erg_compiler/context/initialize/mod.rs +++ b/compiler/erg_compiler/context/initialize/mod.rs @@ -146,6 +146,7 @@ impl Context { // 型境界はすべて各サブルーチンで定義する // push_subtype_boundなどはユーザー定義APIの型境界決定のために使用する fn init_builtin_traits(&mut self) { + let unpack = Self::mono_trait("Unpack", vec![], Self::TOP_LEVEL); let named = Self::mono_trait("Named", vec![], Self::TOP_LEVEL); let mut mutable = Self::mono_trait("Mutable", vec![], Self::TOP_LEVEL); let proj = mono_proj(mono_q("Self"), "ImmutType"); @@ -289,6 +290,7 @@ impl Context { let op_t = quant(op_t, set! {r_bound.clone(), self_bound}); div.register_decl("__div__", op_t, Public); div.register_decl("DivO", Type, Public); + self.register_type(trait_("Unpack"), unpack, Const); self.register_type(trait_("Named"), named, Const); self.register_type(trait_("Mutable"), mutable, Const); self.register_type(trait_("Immutizable"), immutizable, Const); diff --git a/compiler/erg_compiler/context/inquire.rs b/compiler/erg_compiler/context/inquire.rs index 797fdcaf..0597e4d4 100644 --- a/compiler/erg_compiler/context/inquire.rs +++ b/compiler/erg_compiler/context/inquire.rs @@ -539,6 +539,12 @@ impl Context { kw_args: &[hir::KwArg], ) -> TyCheckResult<()> { match instance { + Type::FreeVar(fv) if fv.is_linked() => { + self.substitute_call(obj, method_name, &fv.crack(), pos_args, kw_args) + } + Type::Refinement(refine) => { + self.substitute_call(obj, method_name, &refine.t, pos_args, kw_args) + } Type::Subr(subr) => { let callee = if let Some(name) = method_name { let attr = hir::Attribute::new(obj.clone(), name.clone(), Type::Ellipsis); diff --git a/compiler/erg_parser/ast.rs b/compiler/erg_parser/ast.rs index 02cbcd99..11ef72e8 100644 --- a/compiler/erg_parser/ast.rs +++ b/compiler/erg_parser/ast.rs @@ -2773,7 +2773,7 @@ pub struct MethodDefs { impl NestedDisplay for MethodDefs { fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, level: usize) -> fmt::Result { - writeln!(f, "{}{}", self.class, self.vis)?; + writeln!(f, "{}{}", self.class, self.vis.content)?; self.defs.fmt_nest(f, level + 1) } } diff --git a/compiler/erg_type/lib.rs b/compiler/erg_type/lib.rs index f1353999..4ce9b045 100644 --- a/compiler/erg_type/lib.rs +++ b/compiler/erg_type/lib.rs @@ -1656,6 +1656,7 @@ impl Type { pub fn is_simple_class(&self) -> bool { match self { Self::FreeVar(fv) if fv.is_linked() => fv.crack().is_simple_class(), + Self::Refinement(refine) => refine.t.is_simple_class(), Self::Obj | Self::Int | Self::Nat @@ -1684,6 +1685,7 @@ impl Type { pub fn is_class(&self) -> bool { match self { Self::FreeVar(fv) if fv.is_linked() => fv.crack().is_class(), + Self::Refinement(refine) => refine.t.is_class(), Self::Obj | Self::Int | Self::Nat @@ -1717,6 +1719,7 @@ impl Type { pub fn is_trait(&self) -> bool { match self { Self::FreeVar(fv) if fv.is_linked() => fv.crack().is_trait(), + Self::Refinement(refine) => refine.t.is_trait(), Self::MonoTrait(_) | Self::PolyTrait { .. } => true, _ => false, } @@ -1738,6 +1741,7 @@ impl Type { | Self::PolyTrait { name, .. } | Self::PolyQVar { name, .. } | Self::MonoProj { rhs: name, .. } => name.ends_with('!'), + Self::Refinement(refine) => refine.t.is_mut(), _ => false, } } @@ -1751,6 +1755,7 @@ impl Type { inner_t.is_nonelike() } Self::PolyClass { name, params } if &name[..] == "Tuple" => params.is_empty(), + Self::Refinement(refine) => refine.t.is_nonelike(), _ => false, } } @@ -1780,6 +1785,8 @@ impl Type { false } Self::Subr(subr) => subr.contains_tvar(name), + // TODO: preds + Self::Refinement(refine) => refine.t.contains_tvar(name), _ => false, } } @@ -1787,6 +1794,7 @@ impl Type { pub fn args_ownership(&self) -> ArgsOwnership { match self { Self::FreeVar(fv) if fv.is_linked() => fv.crack().args_ownership(), + Self::Refinement(refine) => refine.t.args_ownership(), Self::Subr(subr) => { let self_ = subr.kind.self_t().map(|t| t.ownership()); let mut nd_args = vec![]; @@ -1817,6 +1825,7 @@ impl Type { pub fn ownership(&self) -> Ownership { match self { Self::FreeVar(fv) if fv.is_linked() => fv.crack().ownership(), + Self::Refinement(refine) => refine.t.ownership(), Self::Ref(_) => Ownership::Ref, Self::RefMut(_) => Ownership::RefMut, _ => Ownership::Owned, @@ -2061,6 +2070,7 @@ impl Type { pub fn typarams_len(&self) -> Option { match self { Self::FreeVar(fv) if fv.is_linked() => fv.crack().typarams_len(), + Self::Refinement(refine) => refine.t.typarams_len(), // REVIEW: Self::Ref(_) | Self::RefMut(_) => Some(1), Self::And(_, _) | Self::Or(_, _) | Self::Not(_, _) => Some(2), @@ -2083,6 +2093,7 @@ impl Type { match self { Self::FreeVar(f) if f.is_linked() => f.crack().typarams(), Self::FreeVar(_unbound) => vec![], + Self::Refinement(refine) => refine.t.typarams(), Self::Ref(t) | Self::RefMut(t) => vec![TyParam::t(*t.clone())], Self::And(lhs, rhs) | Self::Not(lhs, rhs) | Self::Or(lhs, rhs) => { vec![TyParam::t(*lhs.clone()), TyParam::t(*rhs.clone())] @@ -2099,6 +2110,7 @@ impl Type { pub fn self_t(&self) -> Option<&Type> { match self { Self::FreeVar(fv) if fv.is_linked() => todo!("linked: {fv}"), + Self::Refinement(refine) => refine.t.self_t(), Self::Subr(SubrType { kind: SubrKind::FuncMethod(self_t) | SubrKind::ProcMethod { before: self_t, .. }, .. @@ -2110,6 +2122,7 @@ impl Type { pub const fn non_default_params(&self) -> Option<&Vec> { match self { Self::FreeVar(_) => panic!("fv"), + Self::Refinement(refine) => refine.t.non_default_params(), Self::Subr(SubrType { non_default_params, .. }) => Some(non_default_params), @@ -2121,6 +2134,7 @@ impl Type { pub const fn var_args(&self) -> Option<&Box> { match self { Self::FreeVar(_) => panic!("fv"), + Self::Refinement(refine) => refine.t.var_args(), Self::Subr(SubrType { var_params: var_args, .. @@ -2133,6 +2147,7 @@ impl Type { pub const fn default_params(&self) -> Option<&Vec> { match self { Self::FreeVar(_) => panic!("fv"), + Self::Refinement(refine) => refine.t.default_params(), Self::Subr(SubrType { default_params, .. }) => Some(default_params), _ => None, } @@ -2141,6 +2156,7 @@ impl Type { pub const fn return_t(&self) -> Option<&Type> { match self { Self::FreeVar(_) => panic!("fv"), + Self::Refinement(refine) => refine.t.return_t(), Self::Subr(SubrType { return_t, .. }) | Self::Callable { return_t, .. } => { Some(return_t) } @@ -2151,6 +2167,7 @@ impl Type { pub fn mut_return_t(&mut self) -> Option<&mut Type> { match self { Self::FreeVar(_) => panic!("fv"), + Self::Refinement(refine) => refine.t.mut_return_t(), Self::Subr(SubrType { return_t, .. }) | Self::Callable { return_t, .. } => { Some(return_t) } From 924ab27369051b6791f41dd747acc29c2f236d59 Mon Sep 17 00:00:00 2001 From: Shunsuke Shibayama Date: Sat, 3 Sep 2022 15:53:09 +0900 Subject: [PATCH 10/68] Add hir::MethodDefs --- compiler/erg_compiler/context/tyvar.rs | 16 +++++++ compiler/erg_compiler/hir.rs | 59 ++++++++++++++++++++++++-- 2 files changed, 71 insertions(+), 4 deletions(-) diff --git a/compiler/erg_compiler/context/tyvar.rs b/compiler/erg_compiler/context/tyvar.rs index 423381c1..180a9260 100644 --- a/compiler/erg_compiler/context/tyvar.rs +++ b/compiler/erg_compiler/context/tyvar.rs @@ -490,6 +490,22 @@ impl Context { } Ok(()) } + hir::Expr::MethodDefs(method_defs) => { + for def in method_defs.defs.iter_mut() { + match &mut def.sig { + hir::Signature::Var(var) => { + var.t = self.deref_tyvar(mem::take(&mut var.t))?; + } + hir::Signature::Subr(subr) => { + subr.t = self.deref_tyvar(mem::take(&mut subr.t))?; + } + } + for chunk in def.body.block.iter_mut() { + self.deref_expr_t(chunk)?; + } + } + Ok(()) + } } } diff --git a/compiler/erg_compiler/hir.rs b/compiler/erg_compiler/hir.rs index c2253441..5070a81e 100644 --- a/compiler/erg_compiler/hir.rs +++ b/compiler/erg_compiler/hir.rs @@ -11,7 +11,7 @@ use erg_common::{ impl_stream_for_wrapper, }; -use erg_parser::ast::{fmt_lines, DefId, Identifier, Params}; +use erg_parser::ast::{fmt_lines, DefId, Identifier, Params, TypeSpec}; use erg_parser::token::{Token, TokenKind}; use erg_type::constructors::{array, tuple}; @@ -688,6 +688,14 @@ impl NestedDisplay for RecordAttrs { } } +impl_display_from_nested!(RecordAttrs); + +impl Locational for RecordAttrs { + fn loc(&self) -> Location { + Location::concat(self.0.first().unwrap(), self.0.last().unwrap()) + } +} + impl From> for RecordAttrs { fn from(attrs: Vec) -> Self { Self(attrs) @@ -1244,6 +1252,48 @@ impl Def { } } +#[derive(Debug, Clone)] +pub struct MethodDefs { + pub class: TypeSpec, + pub vis: Token, // `.` or `::` + pub defs: RecordAttrs, // TODO: allow declaration +} + +impl NestedDisplay for MethodDefs { + 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 HasType for MethodDefs { + #[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 MethodDefs { + pub const fn new(class: TypeSpec, vis: Token, defs: RecordAttrs) -> Self { + Self { class, vis, defs } + } +} + #[derive(Debug, Clone)] pub enum Expr { Lit(Literal), @@ -1259,12 +1309,13 @@ pub enum Expr { Lambda(Lambda), Decl(Decl), Def(Def), + MethodDefs(MethodDefs), } -impl_nested_display_for_chunk_enum!(Expr; Lit, Accessor, Array, Tuple, Dict, Record, BinOp, UnaryOp, Call, Lambda, Decl, Def); +impl_nested_display_for_chunk_enum!(Expr; Lit, Accessor, Array, Tuple, Dict, Record, BinOp, UnaryOp, Call, Lambda, Decl, Def, MethodDefs); impl_display_from_nested!(Expr); -impl_locational_for_enum!(Expr; Lit, Accessor, Array, Tuple, Dict, Record, BinOp, UnaryOp, Call, Lambda, Decl, Def); -impl_t_for_enum!(Expr; Lit, Accessor, Array, Tuple, Dict, Record, BinOp, UnaryOp, Call, Lambda, Decl, Def); +impl_locational_for_enum!(Expr; Lit, Accessor, Array, Tuple, Dict, Record, BinOp, UnaryOp, Call, Lambda, Decl, Def, MethodDefs); +impl_t_for_enum!(Expr; Lit, Accessor, Array, Tuple, Dict, Record, BinOp, UnaryOp, Call, Lambda, Decl, Def, MethodDefs); impl Expr { pub fn receiver_t(&self) -> Option<&Type> { From e7898c094eeb9e08a0710e031e893613873bf966 Mon Sep 17 00:00:00 2001 From: Shunsuke Shibayama Date: Sat, 3 Sep 2022 20:26:29 +0900 Subject: [PATCH 11/68] Update type/04_class.md --- doc/EN/syntax/type/04_class.md | 10 +++++----- doc/JA/syntax/type/04_class.md | 8 ++++---- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/doc/EN/syntax/type/04_class.md b/doc/EN/syntax/type/04_class.md index 2122edab..b14dc158 100644 --- a/doc/EN/syntax/type/04_class.md +++ b/doc/EN/syntax/type/04_class.md @@ -229,9 +229,9 @@ print! {i = 1}.bar # C.new({i = 1}).bar # ``` -## Difference from data class +## Difference from Data Class -There are two types of classes: regular classes, which are record classes through `Class`, and data classes, which inherit (`Inherit`) from record classes. +There are two types of classes: regular classes, which are generated with `Class(record)`, and data classes, which are generated with `Inherit(record)`. The data class inherits the functionality of the record class and has features such as decomposition assignment, `==` and `hash` implemented by default, etc. On the other hand, the data class has its own equivalence relation and format display. On the other hand, if you want to define your own equivalence relations or formatting displays, you should use the normal class. @@ -243,9 +243,9 @@ print! c # c == d # TypeError: `==` is not implemented for `C` D = Inherit {i = Int} -e = D.new {i = 1} -f = D.new {i = 2} -print! e # D{i = 1} +e = D::{i = 1} # same as `e = D.new {i = 1}` +f = D::{i = 2} +print! e # D(i=1) assert e ! = f ``` diff --git a/doc/JA/syntax/type/04_class.md b/doc/JA/syntax/type/04_class.md index b0f2ea05..5ec14fb2 100644 --- a/doc/JA/syntax/type/04_class.md +++ b/doc/JA/syntax/type/04_class.md @@ -233,7 +233,7 @@ print! C.new({i = 1}).bar # ## データクラスとの違い -クラスには、レコードクラスに`Class`を通した通常のクラスと、レコードクラスを継承(`Inherit`)したデータクラスがあります。 +クラスには、レコードを要求型とする`Class`を通した通常のクラスと、レコードを継承(`Inherit`)したデータクラスがあります。 データクラスはレコードの機能を受け継いでおり、分解代入ができる、`==`や`hash`がデフォルトで実装されているなどの特徴があります。 逆に独自の同値関係やフォーマット表示を定義したい場合は通常のクラスを使用するとよいでしょう。 @@ -245,9 +245,9 @@ print! c # c == d # TypeError: `==` is not implemented for `C` D = Inherit {i = Int} -e = D.new {i = 1} -f = D.new {i = 2} -print! e # D{i = 1} +e = D::{i = 1} # e = D.new {i = 1}と同じ +f = D::{i = 2} +print! e # D(i = 1) assert e != f ``` From 263c43d74b6b070c30808a2abea318a80c9246ed Mon Sep 17 00:00:00 2001 From: Shunsuke Shibayama Date: Sat, 3 Sep 2022 20:58:28 +0900 Subject: [PATCH 12/68] WIP: Impl DataPack type checking --- .../erg_compiler/context/initialize/mod.rs | 2 +- compiler/erg_compiler/context/mod.rs | 15 ++-- compiler/erg_compiler/context/register.rs | 89 +++++++++---------- compiler/erg_compiler/lower.rs | 63 ++++++++++++- compiler/erg_parser/ast.rs | 4 +- compiler/erg_parser/desugar.rs | 2 +- compiler/erg_parser/parse.rs | 2 +- 7 files changed, 119 insertions(+), 58 deletions(-) diff --git a/compiler/erg_compiler/context/initialize/mod.rs b/compiler/erg_compiler/context/initialize/mod.rs index 98e424c1..5645bd2c 100644 --- a/compiler/erg_compiler/context/initialize/mod.rs +++ b/compiler/erg_compiler/context/initialize/mod.rs @@ -101,7 +101,7 @@ impl Context { let mut tv_ctx = TyVarContext::new(self.level, ctx.type_params_bounds(), self); let t = Self::instantiate_t(t, &mut tv_ctx); if let Some((_, root_ctx)) = self.poly_types.get_mut(&t.name()) { - root_ctx.specializations.push((t, ctx)); + root_ctx.method_defs.push((t, ctx)); } else { let name = VarName::from_str(t.name()); self.locals diff --git a/compiler/erg_compiler/context/mod.rs b/compiler/erg_compiler/context/mod.rs index ef9eef24..6c90f753 100644 --- a/compiler/erg_compiler/context/mod.rs +++ b/compiler/erg_compiler/context/mod.rs @@ -192,6 +192,7 @@ pub enum ContextKind { Func, Proc, Class, + MethodDefs, Trait, StructuralTrait, Patch(Type), @@ -230,8 +231,8 @@ pub struct Context { // patchによってsuper class/traitになったものはここに含まれない pub(crate) super_classes: Vec, // if self is a patch, means patch classes pub(crate) super_traits: Vec, // if self is not a trait, means implemented traits - // specialized contexts, If self is a type - pub(crate) specializations: Vec<(Type, Context)>, + // method definitions, if the context is a type + pub(crate) method_defs: Vec<(Type, Context)>, /// K: method name, V: impl patch /// Provided methods can switch implementations on a scope-by-scope basis /// K: メソッド名, V: それを実装するパッチたち @@ -357,7 +358,7 @@ impl Context { outer: outer.map(Box::new), super_classes, super_traits, - specializations: vec![], + method_defs: vec![], const_param_defaults: Dict::default(), method_impl_patches: Dict::default(), trait_impls: Dict::default(), @@ -539,7 +540,7 @@ impl Context { Ok(()) } - pub(crate) fn pop(&mut self) -> Result<(), TyCheckErrors> { + pub(crate) fn pop(&mut self) -> Result { let mut uninited_errs = TyCheckErrors::empty(); for (name, vi) in self.decls.iter() { uninited_errs.push(TyCheckError::uninitialized_error( @@ -551,12 +552,14 @@ impl Context { )); } if let Some(parent) = &mut self.outer { - *self = mem::take(parent); + let parent = mem::take(parent); + let ctx = mem::take(self); + *self = *parent; log!(info "{}: current namespace: {}", fn_name!(), self.name); if !uninited_errs.is_empty() { Err(uninited_errs) } else { - Ok(()) + Ok(ctx) } } else { Err(TyCheckErrors::from(TyCheckError::checker_bug( diff --git a/compiler/erg_compiler/context/register.rs b/compiler/erg_compiler/context/register.rs index 7b111b4d..03e969c7 100644 --- a/compiler/erg_compiler/context/register.rs +++ b/compiler/erg_compiler/context/register.rs @@ -328,56 +328,53 @@ impl Context { pub(crate) fn preregister(&mut self, block: &ast::Block) -> TyCheckResult<()> { for expr in block.iter() { if let ast::Expr::Def(def) = expr { - let id = Some(def.body.id); - let __name__ = def.sig.ident().map(|i| i.inspect()); - match &def.sig { - ast::Signature::Subr(sig) => { - if sig.is_const() { - let (obj, const_t) = - match self.eval_const_block(&def.body.block, __name__) { - Ok(obj) => (obj.clone(), enum_t(set! {obj})), - Err(e) => { - return Err(e); - } - }; - if let Some(spec) = sig.return_t_spec.as_ref() { - let spec_t = self.instantiate_typespec(spec, PreRegister)?; - self.sub_unify( - &const_t, - &spec_t, - Some(def.body.loc()), - None, - None, - )?; - } - self.register_const(__name__.unwrap(), obj); - } else { - let opt_ret_t = if let Some(spec) = sig.return_t_spec.as_ref() { - let spec_t = self.instantiate_typespec(spec, PreRegister)?; - Some(spec_t) - } else { - None - }; - self.declare_sub(sig, opt_ret_t, id)?; + self.preregister_def(def)?; + } + } + Ok(()) + } + + pub(crate) fn preregister_def(&mut self, def: &ast::Def) -> TyCheckResult<()> { + let id = Some(def.body.id); + let __name__ = def.sig.ident().map(|i| i.inspect()); + match &def.sig { + ast::Signature::Subr(sig) => { + if sig.is_const() { + let (obj, const_t) = match self.eval_const_block(&def.body.block, __name__) { + Ok(obj) => (obj.clone(), enum_t(set! {obj})), + Err(e) => { + return Err(e); } + }; + if let Some(spec) = sig.return_t_spec.as_ref() { + let spec_t = self.instantiate_typespec(spec, PreRegister)?; + self.sub_unify(&const_t, &spec_t, Some(def.body.loc()), None, None)?; } - ast::Signature::Var(sig) if sig.is_const() => { - let (obj, const_t) = match self.eval_const_block(&def.body.block, __name__) - { - Ok(obj) => (obj.clone(), enum_t(set! {obj})), - Err(e) => { - return Err(e); - } - }; - if let Some(spec) = sig.t_spec.as_ref() { - let spec_t = self.instantiate_typespec(spec, PreRegister)?; - self.sub_unify(&const_t, &spec_t, Some(def.body.loc()), None, None)?; - } - self.register_const(__name__.unwrap(), obj); - } - _ => {} + self.register_const(__name__.unwrap(), obj); + } else { + let opt_ret_t = if let Some(spec) = sig.return_t_spec.as_ref() { + let spec_t = self.instantiate_typespec(spec, PreRegister)?; + Some(spec_t) + } else { + None + }; + self.declare_sub(sig, opt_ret_t, id)?; } } + ast::Signature::Var(sig) if sig.is_const() => { + let (obj, const_t) = match self.eval_const_block(&def.body.block, __name__) { + Ok(obj) => (obj.clone(), enum_t(set! {obj})), + Err(e) => { + return Err(e); + } + }; + if let Some(spec) = sig.t_spec.as_ref() { + let spec_t = self.instantiate_typespec(spec, PreRegister)?; + self.sub_unify(&const_t, &spec_t, Some(def.body.loc()), None, None)?; + } + self.register_const(__name__.unwrap(), obj); + } + _ => {} } Ok(()) } diff --git a/compiler/erg_compiler/lower.rs b/compiler/erg_compiler/lower.rs index 1ed7af22..50f0b91f 100644 --- a/compiler/erg_compiler/lower.rs +++ b/compiler/erg_compiler/lower.rs @@ -9,6 +9,7 @@ use erg_common::{enum_unwrap, fmt_option, fn_name, get_hash, log, switch_lang, S use erg_parser::ast; use erg_parser::ast::AST; +use erg_parser::token::{Token, TokenKind}; use erg_type::constructors::{array, array_mut, class, free_var, func, poly_class, proc, quant}; use erg_type::free::Constraint; use erg_type::typaram::TyParam; @@ -338,14 +339,36 @@ impl ASTLowerer { hir_args.push_kw(hir::KwArg::new(arg.keyword, self.lower_expr(arg.expr)?)); } let obj = self.lower_expr(*call.obj)?; - let t = self.ctx.get_call_t( + let sig_t = self.ctx.get_call_t( &obj, &call.method_name, &hir_args.pos_args, &hir_args.kw_args, &self.ctx.name, )?; - Ok(hir::Call::new(obj, call.method_name, hir_args, t)) + Ok(hir::Call::new(obj, call.method_name, hir_args, sig_t)) + } + + fn lower_pack(&mut self, pack: ast::DataPack) -> LowerResult { + log!(info "entered {}({pack})", fn_name!()); + let class = self.lower_expr(*pack.class)?; + let args = self.lower_record(pack.args)?; + let args = vec![hir::PosArg::new(hir::Expr::Record(args))]; + let method_name = Token::new( + TokenKind::Symbol, + Str::rc("new"), + pack.connector.lineno, + pack.connector.col_begin, + ); + let sig_t = self.ctx.get_call_t( + &class, + &Some(method_name.clone()), + &args, + &[], + &self.ctx.name, + )?; + let args = hir::Args::new(args, vec![], None); + Ok(hir::Call::new(class, Some(method_name), args, sig_t)) } /// TODO: varargs @@ -523,6 +546,40 @@ impl ASTLowerer { Ok(hir::Def::new(hir::Signature::Subr(sig), body)) } + fn lower_method_defs(&mut self, method_defs: ast::MethodDefs) -> LowerResult { + log!(info "entered {}({method_defs})", fn_name!()); + let mut hir_defs = hir::RecordAttrs::new(); + let class = self + .ctx + .instantiate_typespec(&method_defs.class, RegistrationMode::Normal)?; + self.ctx + .grow(&class.name(), ContextKind::MethodDefs, Private)?; + for def in method_defs.defs.iter() { + self.ctx.preregister_def(def)?; + } + for def in method_defs.defs.into_iter() { + let def = self.lower_def(def)?; + hir_defs.push(def); + } + match self.ctx.pop() { + Ok(ctx) => { + if let Some((_, class_root)) = self.ctx.poly_types.get_mut(&class.name()) { + class_root.method_defs.push((class, ctx)); + } else { + todo!() + } + } + Err(mut errs) => { + self.errs.append(&mut errs); + } + } + Ok(hir::MethodDefs::new( + method_defs.class, + method_defs.vis, + hir_defs, + )) + } + // 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 { @@ -536,8 +593,10 @@ impl ASTLowerer { ast::Expr::BinOp(bin) => Ok(hir::Expr::BinOp(self.lower_bin(bin)?)), ast::Expr::UnaryOp(unary) => Ok(hir::Expr::UnaryOp(self.lower_unary(unary)?)), ast::Expr::Call(call) => Ok(hir::Expr::Call(self.lower_call(call)?)), + ast::Expr::DataPack(pack) => Ok(hir::Expr::Call(self.lower_pack(pack)?)), ast::Expr::Lambda(lambda) => Ok(hir::Expr::Lambda(self.lower_lambda(lambda)?)), ast::Expr::Def(def) => Ok(hir::Expr::Def(self.lower_def(def)?)), + ast::Expr::MethodDefs(defs) => Ok(hir::Expr::MethodDefs(self.lower_method_defs(defs)?)), other => todo!("{other}"), } } diff --git a/compiler/erg_parser/ast.rs b/compiler/erg_parser/ast.rs index 11ef72e8..a1e824b0 100644 --- a/compiler/erg_parser/ast.rs +++ b/compiler/erg_parser/ast.rs @@ -897,6 +897,7 @@ impl Call { #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub struct DataPack { pub class: Box, + pub connector: Token, pub args: Record, } @@ -915,9 +916,10 @@ impl Locational for DataPack { } impl DataPack { - pub fn new(class: Expr, args: Record) -> Self { + pub fn new(class: Expr, connector: Token, args: Record) -> Self { Self { class: Box::new(class), + connector, args, } } diff --git a/compiler/erg_parser/desugar.rs b/compiler/erg_parser/desugar.rs index 9e288685..a4ab3198 100644 --- a/compiler/erg_parser/desugar.rs +++ b/compiler/erg_parser/desugar.rs @@ -330,7 +330,7 @@ impl Desugarer { let class = self.rec_desugar_shortened_record(*pack.class); let rec = self.desugar_shortened_record_inner(rec); let args = Record::Normal(rec); - Expr::DataPack(DataPack::new(class, args)) + Expr::DataPack(DataPack::new(class, pack.connector, args)) } else { Expr::DataPack(pack) } diff --git a/compiler/erg_parser/parse.rs b/compiler/erg_parser/parse.rs index 5a55c460..1c7c1879 100644 --- a/compiler/erg_parser/parse.rs +++ b/compiler/erg_parser/parse.rs @@ -997,7 +997,7 @@ impl Parser { .map_err(|_| self.stack_dec())?; match container { BraceContainer::Record(args) => { - let pack = DataPack::new(maybe_class, args); + let pack = DataPack::new(maybe_class, vis, args); stack.push(ExprOrOp::Expr(Expr::DataPack(pack))); } BraceContainer::Dict(dict) => todo!("{dict}"), From 22cb113fcda82e21c5c064aa00be86390cec130a Mon Sep 17 00:00:00 2001 From: Shunsuke Shibayama Date: Sat, 3 Sep 2022 22:22:49 +0900 Subject: [PATCH 13/68] Unify Type::Class/Trait --- compiler/erg_compiler/context/compare.rs | 49 +-- .../context/initialize/const_func.rs | 6 +- .../erg_compiler/context/initialize/mod.rs | 402 +++++++++--------- .../context/initialize/py_mods/io.rs | 6 +- .../context/initialize/py_mods/random.rs | 6 +- .../context/initialize/py_mods/socket.rs | 6 +- .../context/initialize/py_mods/sys.rs | 12 +- compiler/erg_compiler/context/inquire.rs | 20 +- compiler/erg_compiler/context/instantiate.rs | 33 +- compiler/erg_compiler/context/mod.rs | 2 +- compiler/erg_compiler/context/test.rs | 8 +- compiler/erg_compiler/context/tyvar.rs | 86 +--- compiler/erg_compiler/eval.rs | 16 +- compiler/erg_compiler/lower.rs | 10 +- compiler/erg_type/constructors.rs | 37 +- compiler/erg_type/lib.rs | 222 ++++------ compiler/erg_type/value.rs | 14 +- 17 files changed, 365 insertions(+), 570 deletions(-) diff --git a/compiler/erg_compiler/context/compare.rs b/compiler/erg_compiler/context/compare.rs index 78ee084f..8f3b85ac 100644 --- a/compiler/erg_compiler/context/compare.rs +++ b/compiler/erg_compiler/context/compare.rs @@ -184,44 +184,44 @@ impl Context { && self.supertype_of(&Type, &subr.return_t), ), ( - Type::MonoClass(n), + Type::Mono(n), Subr(SubrType { kind: SubrKind::Func, .. }), ) if &n[..] == "GenericFunc" => (Absolutely, true), ( - Type::MonoClass(n), + Type::Mono(n), Subr(SubrType { kind: SubrKind::Proc, .. }), ) if &n[..] == "GenericProc" => (Absolutely, true), ( - Type::MonoClass(n), + Type::Mono(n), Subr(SubrType { kind: SubrKind::FuncMethod(_), .. }), ) if &n[..] == "GenericFuncMethod" => (Absolutely, true), ( - Type::MonoClass(n), + Type::Mono(n), Subr(SubrType { kind: SubrKind::ProcMethod { .. }, .. }), ) if &n[..] == "GenericProcMethod" => (Absolutely, true), - (Type::MonoClass(l), Type::PolyClass { name: r, .. }) + (Type::Mono(l), Type::Poly { name: r, .. }) if &l[..] == "GenericArray" && &r[..] == "Array" => { (Absolutely, true) } - (Type::MonoClass(l), Type::PolyClass { name: r, .. }) + (Type::Mono(l), Type::Poly { name: r, .. }) if &l[..] == "GenericDict" && &r[..] == "Dict" => { (Absolutely, true) } - (Type::MonoClass(l), Type::MonoClass(r)) + (Type::Mono(l), Type::Mono(r)) if &l[..] == "GenericCallable" && (&r[..] == "GenericFunc" || &r[..] == "GenericProc" @@ -234,7 +234,7 @@ impl Context { Some((Type::Never, Type::Obj)) => (Absolutely, true), _ => (Maybe, false), }, - (Type::MonoClass(n), Subr(_)) if &n[..] == "GenericCallable" => (Absolutely, true), + (Type::Mono(n), Subr(_)) if &n[..] == "GenericCallable" => (Absolutely, true), (lhs, rhs) if lhs.is_simple_class() && rhs.is_simple_class() => (Absolutely, false), _ => (Maybe, false), } @@ -258,7 +258,7 @@ impl Context { } _ => {} } - match self.trait_supertype_of(lhs, rhs) { + match self.classsupertype_of(lhs, rhs) { (Absolutely, judge) => { self.register_cache(rhs, lhs, judge); return judge; @@ -292,9 +292,6 @@ impl Context { } fn classes_supertype_of(&self, lhs: &Type, rhs: &Type) -> (Credibility, bool) { - if !lhs.is_class() || !rhs.is_class() { - return (Maybe, false); - } for (rhs_sup, _) in self.rec_get_nominal_super_class_ctxs(rhs) { match self.cheap_supertype_of(lhs, rhs_sup) { (Absolutely, true) => { @@ -313,11 +310,8 @@ impl Context { // e.g. Eq(Nat) :> Nat // Nat.super_traits = [Add(Nat), Eq(Nat), ...] - fn trait_supertype_of(&self, lhs: &Type, rhs: &Type) -> (Credibility, bool) { - if !lhs.is_trait() { - return (Maybe, false); - } - for (rhs_sup, _) in self.rec_get_nominal_super_trait_ctxs(rhs) { + fn classsupertype_of(&self, lhs: &Type, rhs: &Type) -> (Credibility, bool) { + for (rhs_sup, _) in self.rec_get_nominal_super_classctxs(rhs) { match self.cheap_supertype_of(lhs, rhs_sup) { (Absolutely, true) => { return (Absolutely, true); @@ -575,26 +569,11 @@ impl Context { // REVIEW: RefMut is invariant, maybe (Ref(lhs), rhs) | (RefMut(lhs), rhs) => self.supertype_of(lhs, rhs), ( - PolyClass { + Poly { name: ln, params: lparams, }, - PolyClass { - name: rn, - params: rparams, - }, - ) => { - if ln != rn || lparams.len() != rparams.len() { - return false; - } - self.poly_supertype_of(lhs, lparams, rparams) - } - ( - PolyTrait { - name: ln, - params: lparams, - }, - PolyTrait { + Poly { name: rn, params: rparams, }, @@ -619,7 +598,7 @@ impl Context { pub(crate) fn cyclic_supertype_of(&self, lhs: &FreeTyVar, rhs: &Type) -> bool { // if `rhs` is {S: Str | ... }, `defined_rhs` will be Str let (defined_rhs, _) = self.rec_get_nominal_type_ctx(rhs).unwrap(); - let super_traits = self.rec_get_nominal_super_trait_ctxs(rhs); + let super_traits = self.rec_get_nominal_super_classctxs(rhs); for (sup_trait, _) in super_traits.into_iter() { if self.sup_conforms(lhs, defined_rhs, sup_trait) { return true; diff --git a/compiler/erg_compiler/context/initialize/const_func.rs b/compiler/erg_compiler/context/initialize/const_func.rs index de63377b..e21e1bb6 100644 --- a/compiler/erg_compiler/context/initialize/const_func.rs +++ b/compiler/erg_compiler/context/initialize/const_func.rs @@ -1,18 +1,18 @@ use erg_common::Str; -use erg_type::constructors::class; +use erg_type::constructors::mono; use erg_type::value::ValueObj; use erg_type::ValueArgs; /// Type -> Type pub fn class_func(_args: ValueArgs, __name__: Option) -> ValueObj { - let t = class(__name__.unwrap_or(Str::ever(""))); + let t = mono(__name__.unwrap_or(Str::ever(""))); ValueObj::t(t) } /// Type -> Type pub fn inherit_func(_args: ValueArgs, __name__: Option) -> ValueObj { - let t = class(__name__.unwrap_or(Str::ever(""))); + let t = mono(__name__.unwrap_or(Str::ever(""))); ValueObj::t(t) } diff --git a/compiler/erg_compiler/context/initialize/mod.rs b/compiler/erg_compiler/context/initialize/mod.rs index 5645bd2c..5688e598 100644 --- a/compiler/erg_compiler/context/initialize/mod.rs +++ b/compiler/erg_compiler/context/initialize/mod.rs @@ -152,23 +152,23 @@ impl Context { let proj = mono_proj(mono_q("Self"), "ImmutType"); let f_t = func(vec![param_t("old", proj.clone())], None, vec![], proj); let t = pr1_met(mono_q("Self"), None, f_t, NoneType); - let t = quant(t, set! { subtypeof(mono_q("Self"), trait_("Immutizable")) }); + let t = quant(t, set! { subtypeof(mono_q("Self"), mono("Immutizable")) }); mutable.register_decl("update!", t, Public); let mut immutizable = - Self::mono_trait("Immutizable", vec![trait_("Mutable")], Self::TOP_LEVEL); + Self::mono_trait("Immutizable", vec![mono("Mutable")], Self::TOP_LEVEL); immutizable.register_decl("ImmutType", Type, Public); let mut mutizable = Self::mono_trait("Mutizable", vec![], Self::TOP_LEVEL); mutizable.register_decl("MutType!", Type, Public); let mut in_ = Self::poly_trait( "In", vec![PS::t("T", NonDefault)], - vec![poly_trait("Input", vec![ty_tp(mono_q("T"))])], + vec![poly("Input", vec![ty_tp(mono_q("T"))])], Self::TOP_LEVEL, ); let op_t = fn1_met(mono_q("T"), mono_q("I"), Bool); let op_t = quant( op_t, - set! { static_instance("T", Type), subtypeof(mono_q("I"), poly_trait("In", vec![ty_tp(mono_q("T"))])) }, + set! { static_instance("T", Type), subtypeof(mono_q("I"), poly("In", vec![ty_tp(mono_q("T"))])) }, ); in_.register_decl("__in__", op_t, Public); // Erg does not have a trait equivalent to `PartialEq` in Rust @@ -177,7 +177,7 @@ impl Context { let mut eq = Self::poly_trait( "Eq", vec![PS::t("R", WithDefault)], - vec![poly_trait("Output", vec![ty_tp(mono_q("R"))])], + vec![poly("Output", vec![ty_tp(mono_q("R"))])], Self::TOP_LEVEL, ); // __eq__: |Self <: Eq()| Self.(Self) -> Bool @@ -185,7 +185,7 @@ impl Context { let op_t = quant( op_t, set! { - subtypeof(mono_q("Self"), poly_trait("Eq", vec![ty_tp(mono_q("R"))])), + subtypeof(mono_q("Self"), poly("Eq", vec![ty_tp(mono_q("R"))])), static_instance("R", Type) }, ); @@ -193,49 +193,49 @@ impl Context { let mut partial_ord = Self::poly_trait( "PartialOrd", vec![PS::t("R", WithDefault)], - vec![poly_trait("PartialEq", vec![ty_tp(mono_q("R"))])], + vec![poly("PartialEq", vec![ty_tp(mono_q("R"))])], Self::TOP_LEVEL, ); let op_t = fn1_met(mono_q("Self"), mono_q("R"), Bool); let op_t = quant( op_t, set! { - subtypeof(mono_q("Self"), poly_trait("PartialOrd", vec![ty_tp(mono_q("R"))])), + subtypeof(mono_q("Self"), poly("PartialOrd", vec![ty_tp(mono_q("R"))])), static_instance("R", Type) }, ); partial_ord.register_decl("__lt__", op_t.clone(), Public); let ord = Self::mono_trait( "Ord", - vec![poly_trait("Eq", vec![]), poly_trait("PartialOrd", vec![])], + vec![poly("Eq", vec![]), poly("PartialOrd", vec![])], Self::TOP_LEVEL, ); let num = Self::mono_trait( "Num", vec![ - poly_trait("Add", vec![]), - poly_trait("Sub", vec![]), - poly_trait("Mul", vec![]), + poly("Add", vec![]), + poly("Sub", vec![]), + poly("Mul", vec![]), ], Self::TOP_LEVEL, ); let mut seq = Self::poly_trait( "Seq", vec![PS::t("T", NonDefault)], - vec![poly_trait("Output", vec![ty_tp(mono_q("T"))])], + vec![poly("Output", vec![ty_tp(mono_q("T"))])], Self::TOP_LEVEL, ); let self_t = mono_q("Self"); let t = fn0_met(self_t.clone(), Nat); let t = quant( t, - set! {subtypeof(self_t.clone(), poly_trait("Seq", vec![TyParam::erased(Type)]))}, + set! {subtypeof(self_t.clone(), poly("Seq", vec![TyParam::erased(Type)]))}, ); seq.register_decl("__len__", t, Public); let t = fn1_met(self_t.clone(), Nat, mono_q("T")); let t = quant( t, - set! {subtypeof(self_t, poly_trait("Seq", vec![ty_tp(mono_q("T"))])), static_instance("T", Type)}, + set! {subtypeof(self_t, poly("Seq", vec![ty_tp(mono_q("T"))])), static_instance("T", Type)}, ); // Seq.get: |Self <: Seq(T)| Self.(Nat) -> T seq.register_decl("get", t, Public); @@ -249,10 +249,10 @@ impl Context { let mut add = Self::poly_trait( "Add", params.clone(), - vec![poly_trait("Output", vec![ty_tp(mono_q("R"))])], // Rについて共変(__add__の型とは関係ない) + vec![poly("Output", vec![ty_tp(mono_q("R"))])], // Rについて共変(__add__の型とは関係ない) Self::TOP_LEVEL, ); - let self_bound = subtypeof(mono_q("Self"), poly_trait("Add", ty_params.clone())); + let self_bound = subtypeof(mono_q("Self"), poly("Add", ty_params.clone())); let op_t = fn1_met(mono_q("Self"), r.clone(), mono_proj(mono_q("Self"), "AddO")); let op_t = quant(op_t, set! {r_bound.clone(), self_bound}); add.register_decl("__add__", op_t, Public); @@ -260,61 +260,57 @@ impl Context { let mut sub = Self::poly_trait( "Sub", params.clone(), - vec![poly_trait("Output", vec![ty_tp(mono_q("R"))])], + vec![poly("Output", vec![ty_tp(mono_q("R"))])], Self::TOP_LEVEL, ); let op_t = fn1_met(mono_q("Self"), r.clone(), mono_proj(mono_q("Self"), "SubO")); - let self_bound = subtypeof(mono_q("Self"), poly_trait("Sub", ty_params.clone())); + let self_bound = subtypeof(mono_q("Self"), poly("Sub", ty_params.clone())); let op_t = quant(op_t, set! {r_bound.clone(), self_bound}); sub.register_decl("__sub__", op_t, Public); sub.register_decl("SubO", Type, Public); let mut mul = Self::poly_trait( "Mul", params.clone(), - vec![poly_trait("Output", vec![ty_tp(mono_q("R"))])], + vec![poly("Output", vec![ty_tp(mono_q("R"))])], Self::TOP_LEVEL, ); let op_t = fn1_met(mono_q("Self"), r.clone(), mono_proj(mono_q("Self"), "MulO")); - let self_bound = subtypeof(mono_q("Self"), poly_trait("Mul", ty_params.clone())); + let self_bound = subtypeof(mono_q("Self"), poly("Mul", ty_params.clone())); let op_t = quant(op_t, set! {r_bound.clone(), self_bound}); mul.register_decl("__mul__", op_t, Public); mul.register_decl("MulO", Type, Public); let mut div = Self::poly_trait( "Div", params.clone(), - vec![poly_trait("Output", vec![ty_tp(mono_q("R"))])], + vec![poly("Output", vec![ty_tp(mono_q("R"))])], Self::TOP_LEVEL, ); let op_t = fn1_met(mono_q("Self"), r, mono_proj(mono_q("Self"), "DivO")); - let self_bound = subtypeof(mono_q("Self"), poly_trait("Div", ty_params.clone())); + let self_bound = subtypeof(mono_q("Self"), poly("Div", ty_params.clone())); let op_t = quant(op_t, set! {r_bound.clone(), self_bound}); div.register_decl("__div__", op_t, Public); div.register_decl("DivO", Type, Public); - self.register_type(trait_("Unpack"), unpack, Const); - self.register_type(trait_("Named"), named, Const); - self.register_type(trait_("Mutable"), mutable, Const); - self.register_type(trait_("Immutizable"), immutizable, Const); - self.register_type(trait_("Mutizable"), mutizable, Const); - self.register_type(poly_trait("In", vec![ty_tp(mono_q("T"))]), in_, Const); - self.register_type(poly_trait("Eq", vec![ty_tp(mono_q("R"))]), eq, Const); + self.register_type(mono("Unpack"), unpack, Const); + self.register_type(mono("Named"), named, Const); + self.register_type(mono("Mutable"), mutable, Const); + self.register_type(mono("Immutizable"), immutizable, Const); + self.register_type(mono("Mutizable"), mutizable, Const); + self.register_type(poly("In", vec![ty_tp(mono_q("T"))]), in_, Const); + self.register_type(poly("Eq", vec![ty_tp(mono_q("R"))]), eq, Const); self.register_type( - poly_trait("PartialOrd", vec![ty_tp(mono_q("R"))]), + poly("PartialOrd", vec![ty_tp(mono_q("R"))]), partial_ord, Const, ); - self.register_type(trait_("Ord"), ord, Const); - self.register_type(trait_("Num"), num, Const); - self.register_type(poly_trait("Seq", vec![ty_tp(mono_q("T"))]), seq, Const); - self.register_type(poly_trait("Input", vec![ty_tp(mono_q("T"))]), input, Const); - self.register_type( - poly_trait("Output", vec![ty_tp(mono_q("T"))]), - output, - Const, - ); - self.register_type(poly_trait("Add", ty_params.clone()), add, Const); - self.register_type(poly_trait("Sub", ty_params.clone()), sub, Const); - self.register_type(poly_trait("Mul", ty_params.clone()), mul, Const); - self.register_type(poly_trait("Div", ty_params), div, Const); + self.register_type(mono("Ord"), ord, Const); + self.register_type(mono("Num"), num, Const); + self.register_type(poly("Seq", vec![ty_tp(mono_q("T"))]), seq, Const); + self.register_type(poly("Input", vec![ty_tp(mono_q("T"))]), input, Const); + self.register_type(poly("Output", vec![ty_tp(mono_q("T"))]), output, Const); + self.register_type(poly("Add", ty_params.clone()), add, Const); + self.register_type(poly("Sub", ty_params.clone()), sub, Const); + self.register_type(poly("Mul", ty_params.clone()), mul, Const); + self.register_type(poly("Div", ty_params), div, Const); self.register_const_param_defaults( "Eq", vec![ConstTemplate::Obj(ValueObj::t(mono_q("Self")))], @@ -344,31 +340,31 @@ impl Context { fn init_builtin_classes(&mut self) { let mut obj = Self::mono_class("Obj", vec![], vec![], Self::TOP_LEVEL); let t = fn0_met(mono_q("Self"), mono_q("Self")); - let t = quant(t, set! {subtypeof(mono_q("Self"), class("Obj"))}); + let t = quant(t, set! {subtypeof(mono_q("Self"), mono("Obj"))}); obj.register_impl("clone", t, Const, Public); obj.register_impl("__module__", Str, Const, Public); obj.register_impl("__sizeof__", fn0_met(Obj, Nat), Const, Public); obj.register_impl("__repr__", fn0_met(Obj, Str), Immutable, Public); obj.register_impl("__str__", fn0_met(Obj, Str), Immutable, Public); obj.register_impl("__dict__", fn0_met(Obj, dict(Str, Obj)), Immutable, Public); - obj.register_impl("__bytes__", fn0_met(Obj, class("Bytes")), Immutable, Public); - obj.register_const("MutType!", ValueObj::t(class("Obj!"))); + obj.register_impl("__bytes__", fn0_met(Obj, mono("Bytes")), Immutable, Public); + obj.register_const("MutType!", ValueObj::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], vec![ - trait_("Ord"), - poly_trait("Eq", vec![ty_tp(Int)]), - poly_trait("Add", vec![ty_tp(Int)]), - poly_trait("Sub", vec![ty_tp(Int)]), - poly_trait("Mul", vec![ty_tp(Int)]), - poly_trait("Div", vec![ty_tp(Int)]), - trait_("Num"), - // trait_("Rational"), - // trait_("Integral"), - trait_("Mutizable"), + mono("Ord"), + poly("Eq", vec![ty_tp(Int)]), + poly("Add", vec![ty_tp(Int)]), + poly("Sub", vec![ty_tp(Int)]), + poly("Mul", vec![ty_tp(Int)]), + poly("Div", vec![ty_tp(Int)]), + mono("Num"), + // class("Rational"), + // class("Integral"), + mono("Mutizable"), ], Self::TOP_LEVEL, ); @@ -382,23 +378,23 @@ impl Context { int.register_const("SubO", ValueObj::t(Int)); int.register_const("MulO", ValueObj::t(Int)); int.register_const("DivO", ValueObj::t(Ratio)); - int.register_const("MutType!", ValueObj::t(class("Int!"))); + int.register_const("MutType!", ValueObj::t(mono("Int!"))); int.register_impl("Real", Int, Const, Public); int.register_impl("Imag", Int, Const, Public); let mut nat = Self::mono_class( "Nat", vec![Int, Ratio, Obj], vec![ - trait_("Ord"), - poly_trait("Eq", vec![ty_tp(Nat)]), - poly_trait("Add", vec![ty_tp(Nat)]), - poly_trait("Sub", vec![ty_tp(Nat)]), - poly_trait("Mul", vec![ty_tp(Nat)]), - poly_trait("Div", vec![ty_tp(Nat)]), - trait_("Num"), - // trait_("Rational"), - // trait_("Integral"), - trait_("Mutizable"), + mono("Ord"), + poly("Eq", vec![ty_tp(Nat)]), + poly("Add", vec![ty_tp(Nat)]), + poly("Sub", vec![ty_tp(Nat)]), + poly("Mul", vec![ty_tp(Nat)]), + poly("Div", vec![ty_tp(Nat)]), + mono("Num"), + // class("Rational"), + // class("Integral"), + mono("Mutizable"), ], Self::TOP_LEVEL, ); @@ -423,21 +419,21 @@ impl Context { nat.register_const("SubO", ValueObj::t(Int)); nat.register_const("MulO", ValueObj::t(Nat)); nat.register_const("DivO", ValueObj::t(Ratio)); - nat.register_const("MutType!", ValueObj::t(class("Nat!"))); + nat.register_const("MutType!", ValueObj::t(mono("Nat!"))); nat.register_impl("Real", Nat, Const, Public); nat.register_impl("Imag", Nat, Const, Public); let mut float = Self::mono_class( "Float", vec![Obj], vec![ - trait_("Num"), - // trait_("Eq"), // Float doesn't have an Eq implementation - trait_("Ord"), - poly_trait("Add", vec![ty_tp(Float)]), - poly_trait("Sub", vec![ty_tp(Float)]), - poly_trait("Mul", vec![ty_tp(Float)]), - poly_trait("Div", vec![ty_tp(Float)]), - trait_("Mutizable"), + mono("Num"), + // class("Eq"), // Float doesn't have an Eq implementation + mono("Ord"), + poly("Add", vec![ty_tp(Float)]), + poly("Sub", vec![ty_tp(Float)]), + poly("Mul", vec![ty_tp(Float)]), + poly("Div", vec![ty_tp(Float)]), + mono("Mutizable"), ], Self::TOP_LEVEL, ); @@ -450,21 +446,21 @@ impl Context { float.register_const("SubO", ValueObj::t(Float)); float.register_const("MulO", ValueObj::t(Float)); float.register_const("DivO", ValueObj::t(Float)); - float.register_const("MutType!", ValueObj::t(class("Float!"))); + float.register_const("MutType!", ValueObj::t(mono("Float!"))); float.register_impl("Real", Float, Const, Public); float.register_impl("Imag", Float, Const, Public); let mut ratio = Self::mono_class( "Ratio", vec![Obj], vec![ - trait_("Num"), - poly_trait("Eq", vec![ty_tp(Ratio)]), - trait_("Ord"), - poly_trait("Add", vec![ty_tp(Ratio)]), - poly_trait("Sub", vec![ty_tp(Ratio)]), - poly_trait("Mul", vec![ty_tp(Ratio)]), - poly_trait("Div", vec![ty_tp(Ratio)]), - trait_("Mutizable"), + mono("Num"), + poly("Eq", vec![ty_tp(Ratio)]), + mono("Ord"), + poly("Add", vec![ty_tp(Ratio)]), + poly("Sub", vec![ty_tp(Ratio)]), + poly("Mul", vec![ty_tp(Ratio)]), + poly("Div", vec![ty_tp(Ratio)]), + mono("Mutizable"), ], Self::TOP_LEVEL, ); @@ -477,40 +473,40 @@ impl Context { ratio.register_const("SubO", ValueObj::t(Ratio)); ratio.register_const("MulO", ValueObj::t(Ratio)); ratio.register_const("DivO", ValueObj::t(Ratio)); - ratio.register_const("MutType!", ValueObj::t(class("Ratio!"))); + ratio.register_const("MutType!", ValueObj::t(mono("Ratio!"))); ratio.register_impl("Real", Ratio, Const, Public); ratio.register_impl("Imag", Ratio, Const, Public); let mut bool_ = Self::mono_class( "Bool", vec![Nat, Int, Ratio, Obj], vec![ - trait_("Num"), - // trait_("Rational"), - // trait_("Integral"), - poly_trait("Eq", vec![ty_tp(Bool)]), - poly_trait("Add", vec![ty_tp(Bool)]), - trait_("Ord"), + mono("Num"), + // class("Rational"), + // class("Integral"), + poly("Eq", vec![ty_tp(Bool)]), + poly("Add", vec![ty_tp(Bool)]), + mono("Ord"), // mono("SelfAdd"), // mono("SelfSub"), // mono("SelfMul"), // mono("SelfDiv"), - trait_("Mutizable"), + mono("Mutizable"), ], Self::TOP_LEVEL, ); bool_.register_impl("__and__", fn1_met(Bool, Bool, Bool), Const, Public); bool_.register_impl("__or__", fn1_met(Bool, Bool, Bool), Const, Public); - bool_.register_const("MutType!", ValueObj::t(class("Bool!"))); + bool_.register_const("MutType!", ValueObj::t(mono("Bool!"))); let mut str_ = Self::mono_class( "Str", vec![Obj], vec![ - poly_trait("Eq", vec![ty_tp(Str)]), - trait_("Ord"), - trait_("Mutizable"), - poly_trait("Seq", vec![ty_tp(Str)]), - poly_trait("Add", vec![ty_tp(Str)]), - poly_trait("Mul", vec![ty_tp(Nat)]), + poly("Eq", vec![ty_tp(Str)]), + mono("Ord"), + mono("Mutizable"), + poly("Seq", vec![ty_tp(Str)]), + poly("Add", vec![ty_tp(Str)]), + poly("Mul", vec![ty_tp(Nat)]), ], Self::TOP_LEVEL, ); @@ -534,21 +530,21 @@ impl Context { vec![], None, vec![param_t("encoding", Str), param_t("errors", Str)], - class("Bytes"), + mono("Bytes"), ), Immutable, Public, ); str_.register_const("AddO", ValueObj::t(Str)); str_.register_const("MulO", ValueObj::t(Str)); - str_.register_const("MutType!", ValueObj::t(class("Str!"))); + str_.register_const("MutType!", ValueObj::t(mono("Str!"))); let mut type_ = Self::mono_class( "Type", vec![Obj], vec![ - poly_trait("Eq", vec![ty_tp(Type)]), - poly_trait("In", vec![ty_tp(Obj)]), // x in Type - trait_("Named"), + poly("Eq", vec![ty_tp(Type)]), + poly("In", vec![ty_tp(Obj)]), // x in Type + mono("Named"), ], Self::TOP_LEVEL, ); @@ -556,7 +552,7 @@ impl Context { let module = Self::mono_class( "Module", vec![Obj], - vec![poly_trait("Eq", vec![ty_tp(Module)]), trait_("Named")], + vec![poly("Eq", vec![ty_tp(Module)]), mono("Named")], Self::TOP_LEVEL, ); let mut array_ = Self::poly_class( @@ -564,16 +560,16 @@ impl Context { vec![PS::t_nd("T"), PS::named_nd("N", Nat)], vec![Obj], vec![ - poly_trait( + poly( "Eq", - vec![ty_tp(poly_class( + vec![ty_tp(poly( "Array", vec![ty_tp(mono_q("T")), mono_q_tp("N")], ))], ), - trait_("Mutizable"), - poly_trait("Seq", vec![ty_tp(mono_q("T"))]), - poly_trait("Output", vec![ty_tp(mono_q("T"))]), + mono("Mutizable"), + poly("Seq", vec![ty_tp(mono_q("T"))]), + poly("Output", vec![ty_tp(mono_q("T"))]), ], Self::TOP_LEVEL, ); @@ -608,10 +604,10 @@ impl Context { ); let t = quant( t, - set! {static_instance("N", Nat), static_instance("T", trait_("Mutable"))}, + set! {static_instance("N", Nat), static_instance("T", mono("Mutable"))}, ); array_.register_impl("map!", t, Immutable, Public); - let mut_type = ValueObj::t(poly_class( + let mut_type = ValueObj::t(poly( "Array!", vec![TyParam::t(mono_q("T")), TyParam::mono_q("N").mutate()], )); @@ -619,34 +615,34 @@ impl Context { array_.register_const("MutType!", mut_type); let mut int_mut = Self::mono_class( "Int!", - vec![Int, class("Ratio!"), Obj], - vec![trait_("Mutable")], + vec![Int, mono("Ratio!"), Obj], + vec![mono("Mutable")], Self::TOP_LEVEL, ); // TODO: make Tuple6, Tuple7, ... etc. let tuple_ = Self::mono_class( "Tuple", vec![Obj], - vec![poly_trait("Eq", vec![ty_tp(class("Tuple"))])], + vec![poly("Eq", vec![ty_tp(mono("Tuple"))])], Self::TOP_LEVEL, ); let tuple1 = Self::poly_class( "Tuple1", vec![PS::t_nd("A")], - vec![class("Tuple"), Obj], - vec![poly_trait( + vec![mono("Tuple"), Obj], + vec![poly( "Eq", - vec![ty_tp(poly_class("Tuple1", vec![ty_tp(mono_q("A"))]))], + vec![ty_tp(poly("Tuple1", vec![ty_tp(mono_q("A"))]))], )], Self::TOP_LEVEL, ); let tuple2 = Self::poly_class( "Tuple2", vec![PS::t_nd("A"), PS::t_nd("B")], - vec![class("Tuple"), Obj], - vec![poly_trait( + vec![mono("Tuple"), Obj], + vec![poly( "Eq", - vec![ty_tp(poly_class( + vec![ty_tp(poly( "Tuple2", vec![ty_tp(mono_q("A")), ty_tp(mono_q("B"))], ))], @@ -656,10 +652,10 @@ impl Context { let tuple3 = Self::poly_class( "Tuple3", vec![PS::t_nd("A"), PS::t_nd("B"), PS::t_nd("C")], - vec![class("Tuple"), Obj], - vec![poly_trait( + vec![mono("Tuple"), Obj], + vec![poly( "Eq", - vec![ty_tp(poly_class( + vec![ty_tp(poly( "Tuple3", vec![ty_tp(mono_q("A")), ty_tp(mono_q("B")), ty_tp(mono_q("C"))], ))], @@ -669,10 +665,10 @@ impl Context { let tuple4 = Self::poly_class( "Tuple4", vec![PS::t_nd("A"), PS::t_nd("B"), PS::t_nd("C"), PS::t_nd("D")], - vec![class("Tuple"), Obj], - vec![poly_trait( + vec![mono("Tuple"), Obj], + vec![poly( "Eq", - vec![ty_tp(poly_class( + vec![ty_tp(poly( "Tuple4", vec![ ty_tp(mono_q("A")), @@ -693,10 +689,10 @@ impl Context { PS::t_nd("D"), PS::t_nd("E"), ], - vec![class("Tuple"), Obj], - vec![poly_trait( + vec![mono("Tuple"), Obj], + vec![poly( "Eq", - vec![ty_tp(poly_class( + vec![ty_tp(poly( "Tuple5", vec![ ty_tp(mono_q("A")), @@ -719,10 +715,10 @@ impl Context { PS::t_nd("E"), PS::t_nd("F"), ], - vec![class("Tuple"), Obj], - vec![poly_trait( + vec![mono("Tuple"), Obj], + vec![poly( "Eq", - vec![ty_tp(poly_class( + vec![ty_tp(poly( "Tuple6", vec![ ty_tp(mono_q("A")), @@ -747,10 +743,10 @@ impl Context { PS::t_nd("F"), PS::t_nd("G"), ], - vec![class("Tuple"), Obj], - vec![poly_trait( + vec![mono("Tuple"), Obj], + vec![poly( "Eq", - vec![ty_tp(poly_class( + vec![ty_tp(poly( "Tuple7", vec![ ty_tp(mono_q("A")), @@ -777,10 +773,10 @@ impl Context { PS::t_nd("G"), PS::t_nd("H"), ], - vec![class("Tuple"), Obj], - vec![poly_trait( + vec![mono("Tuple"), Obj], + vec![poly( "Eq", - vec![ty_tp(poly_class( + vec![ty_tp(poly( "Tuple8", vec![ ty_tp(mono_q("A")), @@ -798,83 +794,77 @@ impl Context { ); int_mut.register_const("ImmutType", ValueObj::t(Int)); let f_t = param_t("f", func(vec![param_t("old", Int)], None, vec![], Int)); - let t = pr_met(class("Int!"), None, vec![f_t], None, vec![], NoneType); + let t = pr_met(mono("Int!"), None, vec![f_t], None, vec![], NoneType); int_mut.register_impl("update!", t, Immutable, Public); let mut nat_mut = Self::mono_class( "Nat!", - vec![Nat, class("Int!"), class("Ratio!"), Obj], - vec![trait_("Mutable")], + vec![Nat, mono("Int!"), mono("Ratio!"), Obj], + vec![mono("Mutable")], Self::TOP_LEVEL, ); nat_mut.register_const("ImmutType", ValueObj::t(Nat)); let f_t = param_t("f", func(vec![param_t("old", Nat)], None, vec![], Nat)); - let t = pr_met(class("Nat!"), None, vec![f_t], None, vec![], NoneType); + let t = pr_met(mono("Nat!"), None, vec![f_t], None, vec![], NoneType); nat_mut.register_impl("update!", t, Immutable, Public); let mut float_mut = Self::mono_class( "Float!", vec![Float, Obj], - vec![trait_("Mutable")], + vec![mono("Mutable")], Self::TOP_LEVEL, ); float_mut.register_const("ImmutType", ValueObj::t(Float)); let f_t = param_t("f", func(vec![param_t("old", Float)], None, vec![], Float)); - let t = pr_met(class("Float!"), None, vec![f_t], None, vec![], NoneType); + let t = pr_met(mono("Float!"), None, vec![f_t], None, vec![], NoneType); float_mut.register_impl("update!", t, Immutable, Public); let mut ratio_mut = Self::mono_class( "Ratio!", vec![Ratio, Obj], - vec![trait_("Mutable")], + vec![mono("Mutable")], Self::TOP_LEVEL, ); ratio_mut.register_const("ImmutType", ValueObj::t(Ratio)); let f_t = param_t( "f", func( - vec![param_t("old", class("Ratio"))], + vec![param_t("old", mono("Ratio"))], None, vec![], - class("Ratio"), + mono("Ratio"), ), ); - let t = pr_met(class("Ratio!"), None, vec![f_t], None, vec![], NoneType); + let t = pr_met(mono("Ratio!"), None, vec![f_t], None, vec![], NoneType); ratio_mut.register_impl("update!", t, Immutable, Public); let mut bool_mut = Self::mono_class( "Bool!", - vec![Bool, class("Nat!"), class("Int!"), class("Ratio!"), Obj], - vec![trait_("Mutable")], + vec![Bool, mono("Nat!"), mono("Int!"), mono("Ratio!"), Obj], + vec![mono("Mutable")], Self::TOP_LEVEL, ); bool_mut.register_const("ImmutType", ValueObj::t(Bool)); let f_t = param_t("f", func(vec![param_t("old", Bool)], None, vec![], Bool)); - let t = pr_met(class("Bool!"), None, vec![f_t], None, vec![], NoneType); + let t = pr_met(mono("Bool!"), None, vec![f_t], None, vec![], NoneType); bool_mut.register_impl("update!", t, Immutable, Public); let mut str_mut = Self::mono_class( "Str!", vec![Str, Obj], - vec![trait_("Mutable")], + vec![mono("Mutable")], Self::TOP_LEVEL, ); str_mut.register_const("ImmutType", ValueObj::t(Str)); let f_t = param_t("f", func(vec![param_t("old", Str)], None, vec![], Str)); - let t = pr_met(class("Str!"), None, vec![f_t], None, vec![], NoneType); + let t = pr_met(mono("Str!"), None, vec![f_t], None, vec![], NoneType); str_mut.register_impl("update!", t, Immutable, Public); - let array_mut_t = poly_class("Array!", vec![ty_tp(mono_q("T")), mono_q_tp("N")]); + let array_mut_t = poly("Array!", vec![ty_tp(mono_q("T")), mono_q_tp("N")]); let mut array_mut = Self::poly_class( "Array!", - vec![PS::t_nd("T"), PS::named_nd("N", class("Nat!"))], - vec![ - poly_class("Range", vec![ty_tp(mono_q("T")), mono_q_tp("N")]), - Obj, - ], - vec![ - trait_("Mutizable"), - poly_trait("Seq", vec![ty_tp(mono_q("T"))]), - ], + vec![PS::t_nd("T"), PS::named_nd("N", mono("Nat!"))], + vec![poly("Range", vec![ty_tp(mono_q("T")), mono_q_tp("N")]), Obj], + vec![mono("Mutizable"), poly("Seq", vec![ty_tp(mono_q("T"))])], Self::TOP_LEVEL, ); let t = pr_met( ref_mut(array_mut_t.clone()), - Some(ref_mut(poly_class( + Some(ref_mut(poly( "Array!", vec![ty_tp(mono_q("T")), mono_q_tp("N") + value(1)], ))), @@ -885,7 +875,7 @@ impl Context { ); let t = quant( t, - set! {static_instance("T", Type), static_instance("N", class("Nat!"))}, + set! {static_instance("T", Type), static_instance("N", mono("Nat!"))}, ); array_mut.register_impl("push!", t, Immutable, Public); let f_t = param_t( @@ -899,31 +889,23 @@ impl Context { ); let t = pr_met(array_mut_t.clone(), None, vec![f_t], None, vec![], NoneType); array_mut.register_impl("update!", t, Immutable, Public); - let range_t = poly_class("Range", vec![TyParam::t(mono_q("T"))]); + let range_t = poly("Range", vec![TyParam::t(mono_q("T"))]); let range = Self::poly_class( "Range", vec![PS::t_nd("T")], vec![Obj], vec![ - poly_trait( - "Eq", - vec![ty_tp(poly_class("Range", vec![ty_tp(mono_q("T"))]))], - ), - trait_("Mutizable"), - poly_trait("Seq", vec![ty_tp(mono_q("T"))]), - poly_trait("Output", vec![ty_tp(mono_q("T"))]), + poly("Eq", vec![ty_tp(poly("Range", vec![ty_tp(mono_q("T"))]))]), + mono("Mutizable"), + poly("Seq", vec![ty_tp(mono_q("T"))]), + poly("Output", vec![ty_tp(mono_q("T"))]), ], Self::TOP_LEVEL, ); - let func = Self::mono_class( - "Function", - vec![Obj], - vec![trait_("Named")], - Self::TOP_LEVEL, - ); + let func = Self::mono_class("Function", vec![Obj], vec![mono("Named")], Self::TOP_LEVEL); let qfunc = Self::mono_class( "QuantifiedFunction", - vec![class("Function"), Obj], + vec![mono("Function"), Obj], vec![], Self::TOP_LEVEL, ); @@ -1001,21 +983,21 @@ impl Context { tuple8, Const, ); - self.register_type(class("Int!"), int_mut, Const); - self.register_type(class("Nat!"), nat_mut, Const); - self.register_type(class("Float!"), float_mut, Const); - self.register_type(class("Ratio!"), ratio_mut, Const); - self.register_type(class("Bool!"), bool_mut, Const); - self.register_type(class("Str!"), str_mut, Const); + self.register_type(mono("Int!"), int_mut, Const); + self.register_type(mono("Nat!"), nat_mut, Const); + self.register_type(mono("Float!"), float_mut, Const); + self.register_type(mono("Ratio!"), ratio_mut, Const); + self.register_type(mono("Bool!"), bool_mut, Const); + self.register_type(mono("Str!"), str_mut, Const); self.register_type(array_mut_t, array_mut, Const); self.register_type(range_t, range, Const); - self.register_type(class("Tuple"), tuple_, Const); - self.register_type(class("Function"), func, Const); - self.register_type(class("QuantifiedFunction"), qfunc, Const); + self.register_type(mono("Tuple"), tuple_, Const); + self.register_type(mono("Function"), func, Const); + self.register_type(mono("QuantifiedFunction"), qfunc, Const); } fn init_builtin_funcs(&mut self) { - let t_abs = nd_func(vec![param_t("n", trait_("Num"))], None, Nat); + let t_abs = nd_func(vec![param_t("n", mono("Num"))], None, Nat); let t_assert = func( vec![param_t("condition", Bool)], None, @@ -1054,7 +1036,7 @@ impl Context { vec![ param_t("sep", Str), param_t("end", Str), - param_t("file", class("Write")), + param_t("file", mono("Write")), param_t("flush", Bool), ], NoneType, @@ -1096,7 +1078,7 @@ impl Context { vec![ param_t("sep", Str), param_t("end", Str), - param_t("file", class("Write")), + param_t("file", mono("Write")), param_t("flush", Bool), ], NoneType, @@ -1123,7 +1105,7 @@ impl Context { let t_for = quant(t_for, set! {static_instance("T", Type)}); let t_while = nd_proc( vec![ - param_t("cond", class("Bool!")), + param_t("cond", mono("Bool!")), param_t("p", nd_proc(vec![], None, NoneType)), ], None, @@ -1150,7 +1132,7 @@ impl Context { op_t, set! { static_instance("R", Type), - subtypeof(l.clone(), poly_trait("Add", params.clone())) + subtypeof(l.clone(), poly("Add", params.clone())) }, ); self.register_impl("__add__", op_t, Const, Private); @@ -1159,7 +1141,7 @@ impl Context { op_t, set! { static_instance("R", Type), - subtypeof(l.clone(), poly_trait("Sub", params.clone())) + subtypeof(l.clone(), poly("Sub", params.clone())) }, ); self.register_impl("__sub__", op_t, Const, Private); @@ -1168,7 +1150,7 @@ impl Context { op_t, set! { static_instance("R", Type), - subtypeof(l.clone(), poly_trait("Mul", params.clone())) + subtypeof(l.clone(), poly("Mul", params.clone())) }, ); self.register_impl("__mul__", op_t, Const, Private); @@ -1177,27 +1159,27 @@ impl Context { op_t, set! { static_instance("R", Type), - subtypeof(l, poly_trait("Mul", params.clone())) + subtypeof(l, poly("Mul", params.clone())) }, ); self.register_impl("__div__", op_t, Const, Private); let m = mono_q("M"); let op_t = bin_op(m.clone(), m.clone(), m.clone()); - let op_t = quant(op_t, set! {subtypeof(m, poly_trait("Mul", vec![]))}); + let op_t = quant(op_t, set! {subtypeof(m, poly("Mul", vec![]))}); // TODO: add bound: M == MulO self.register_impl("__pow__", op_t, Const, Private); let d = mono_q("D"); let op_t = bin_op(d.clone(), d.clone(), d.clone()); - let op_t = quant(op_t, set! {subtypeof(d, poly_trait("Div", vec![]))}); + let op_t = quant(op_t, set! {subtypeof(d, poly("Div", vec![]))}); self.register_impl("__mod__", op_t, Const, Private); let e = mono_q("E"); let op_t = bin_op(e.clone(), e.clone(), Bool); - let op_t = quant(op_t, set! {subtypeof(e, poly_trait("Eq", vec![]))}); + let op_t = quant(op_t, set! {subtypeof(e, poly("Eq", vec![]))}); self.register_impl("__eq__", op_t.clone(), Const, Private); self.register_impl("__ne__", op_t, Const, Private); let o = mono_q("O"); let op_t = bin_op(o.clone(), o.clone(), Bool); - let op_t = quant(op_t, set! {subtypeof(o, trait_("Ord"))}); + let op_t = quant(op_t, set! {subtypeof(o, mono("Ord"))}); self.register_impl("__lt__", op_t.clone(), Const, Private); self.register_impl("__le__", op_t.clone(), Const, Private); self.register_impl("__gt__", op_t.clone(), Const, Private); @@ -1206,7 +1188,7 @@ impl Context { self.register_impl("__or__", bin_op(Bool, Bool, Bool), Const, Private); let t = mono_q("T"); let op_t = bin_op(t.clone(), t.clone(), range(t.clone())); - let op_t = quant(op_t, set! {subtypeof(t.clone(), trait_("Ord"))}); + let op_t = quant(op_t, set! {subtypeof(t.clone(), mono("Ord"))}); self.register_decl("__rng__", op_t.clone(), Private); self.register_decl("__lorng__", op_t.clone(), Private); self.register_decl("__rorng__", op_t.clone(), Private); @@ -1215,17 +1197,17 @@ impl Context { let op_t = bin_op(mono_q("T"), mono_q("I"), Bool); let op_t = quant( op_t, - set! { static_instance("T", Type), subtypeof(mono_q("I"), poly_trait("In", vec![ty_tp(mono_q("T"))])) }, + set! { static_instance("T", Type), subtypeof(mono_q("I"), poly("In", vec![ty_tp(mono_q("T"))])) }, ); self.register_impl("__in__", op_t, Const, Private); /* unary */ // TODO: Boolの+/-は警告を出したい let op_t = func1(mono_q("T"), mono_proj(mono_q("T"), "MutType!")); - let op_t = quant(op_t, set! {subtypeof(mono_q("T"), trait_("Mutizable"))}); + let op_t = quant(op_t, set! {subtypeof(mono_q("T"), mono("Mutizable"))}); self.register_impl("__mutate__", op_t, Const, Private); let n = mono_q("N"); let op_t = func1(n.clone(), n.clone()); - let op_t = quant(op_t, set! {subtypeof(n, trait_("Num"))}); + let op_t = quant(op_t, set! {subtypeof(n, mono("Num"))}); self.register_decl("__pos__", op_t.clone(), Private); self.register_decl("__neg__", op_t, Private); } @@ -1247,8 +1229,8 @@ impl Context { params, vec![Type::from(&m..=&n)], vec![ - poly_trait("Add", vec![TyParam::from(&o..=&p)]), - poly_trait("Sub", vec![TyParam::from(&o..=&p)]), + poly("Add", vec![TyParam::from(&o..=&p)]), + poly("Sub", vec![TyParam::from(&o..=&p)]), ], Self::TOP_LEVEL, ); diff --git a/compiler/erg_compiler/context/initialize/py_mods/io.rs b/compiler/erg_compiler/context/initialize/py_mods/io.rs index 00451fbe..f7a87bf2 100644 --- a/compiler/erg_compiler/context/initialize/py_mods/io.rs +++ b/compiler/erg_compiler/context/initialize/py_mods/io.rs @@ -1,7 +1,7 @@ use erg_common::vis::Visibility; use erg_common::Str; -use erg_type::constructors::{class, pr0_met}; +use erg_type::constructors::{mono, pr0_met}; use erg_type::Type; use Type::*; @@ -16,11 +16,11 @@ impl Context { let mut string_io = Context::mono_class(Str::ever("StringIO!"), vec![Obj], vec![], 0); string_io.register_impl( "getvalue!", - pr0_met(class("StringIO!"), None, Str), + pr0_met(mono("StringIO!"), None, Str), Immutable, Public, ); - io.register_type(class("StringIO!"), string_io, Const); + io.register_type(mono("StringIO!"), string_io, Const); io } } diff --git a/compiler/erg_compiler/context/initialize/py_mods/random.rs b/compiler/erg_compiler/context/initialize/py_mods/random.rs index 51773079..ec57add4 100644 --- a/compiler/erg_compiler/context/initialize/py_mods/random.rs +++ b/compiler/erg_compiler/context/initialize/py_mods/random.rs @@ -2,7 +2,7 @@ use erg_common::set; use erg_common::vis::Visibility; use erg_type::constructors::{ - mono_q, nd_proc, param_t, poly_trait, proc, quant, static_instance, trait_, ty_tp, + mono, mono_q, nd_proc, param_t, poly, proc, quant, static_instance, ty_tp, }; use erg_type::Type; use Type::*; @@ -21,7 +21,7 @@ impl Context { vec![], None, vec![ - param_t("a", trait_("Num")), // TODO: NoneType, int, float, str, bytes, bytearray + param_t("a", mono("Num")), // TODO: NoneType, int, float, str, bytes, bytearray param_t("version", Int), ], NoneType, @@ -36,7 +36,7 @@ impl Context { Public, ); let t = nd_proc( - vec![param_t("seq", poly_trait("Seq", vec![ty_tp(mono_q("T"))]))], + vec![param_t("seq", poly("Seq", vec![ty_tp(mono_q("T"))]))], None, mono_q("T"), ); diff --git a/compiler/erg_compiler/context/initialize/py_mods/socket.rs b/compiler/erg_compiler/context/initialize/py_mods/socket.rs index 42ec4c32..20344650 100644 --- a/compiler/erg_compiler/context/initialize/py_mods/socket.rs +++ b/compiler/erg_compiler/context/initialize/py_mods/socket.rs @@ -1,7 +1,7 @@ use erg_common::vis::Visibility; use erg_common::Str; -use erg_type::constructors::{class, func, option, param_t}; +use erg_type::constructors::{func, mono, option, param_t}; use erg_type::Type; use Type::*; @@ -25,12 +25,12 @@ impl Context { param_t("proto", Int), param_t("fileno", option(Int)), ], - class("Socket!"), + mono("Socket!"), ), Immutable, Public, ); - socket.register_type(class("Socket!"), sock, Const); + socket.register_type(mono("Socket!"), sock, Const); socket } } diff --git a/compiler/erg_compiler/context/initialize/py_mods/sys.rs b/compiler/erg_compiler/context/initialize/py_mods/sys.rs index 1ad02502..c06b6993 100644 --- a/compiler/erg_compiler/context/initialize/py_mods/sys.rs +++ b/compiler/erg_compiler/context/initialize/py_mods/sys.rs @@ -1,6 +1,6 @@ use erg_common::vis::Visibility; -use erg_type::constructors::{array, array_mut, class, func0, func1, proc1}; +use erg_type::constructors::{array, array_mut, func0, func1, mono, proc1}; use erg_type::typaram::TyParam; use erg_type::Type; use Type::*; @@ -33,17 +33,17 @@ impl Context { ); sys.register_impl("platform", Str, Immutable, Public); sys.register_impl("prefix", Str, Immutable, Public); - sys.register_impl("ps1", class("Str!"), Immutable, Public); - sys.register_impl("ps2", class("Str!"), Immutable, Public); + sys.register_impl("ps1", mono("Str!"), Immutable, Public); + sys.register_impl("ps2", mono("Str!"), Immutable, Public); sys.register_impl( "setrecursionlimit!", proc1(Int, NoneType), Immutable, Public, ); - sys.register_impl("stderr", class("TextIOWrapper!"), Immutable, Public); - sys.register_impl("stdin", class("TextIOWrapper!"), Immutable, Public); - sys.register_impl("stdout", class("TextIOWrapper!"), Immutable, Public); + sys.register_impl("stderr", mono("TextIOWrapper!"), Immutable, Public); + sys.register_impl("stdin", mono("TextIOWrapper!"), Immutable, Public); + sys.register_impl("stdout", mono("TextIOWrapper!"), Immutable, Public); sys.register_impl("version", Str, Immutable, Public); sys } diff --git a/compiler/erg_compiler/context/inquire.rs b/compiler/erg_compiler/context/inquire.rs index 0597e4d4..605a839a 100644 --- a/compiler/erg_compiler/context/inquire.rs +++ b/compiler/erg_compiler/context/inquire.rs @@ -14,9 +14,7 @@ use ast::VarName; use erg_parser::ast; use erg_parser::token::Token; -use erg_type::constructors::{ - class, func, mono_proj, poly_class, ref_, ref_mut, refinement, subr_t, -}; +use erg_type::constructors::{func, mono, mono_proj, poly, ref_, ref_mut, refinement, subr_t}; use erg_type::free::Constraint; use erg_type::typaram::TyParam; use erg_type::value::ValueObj; @@ -119,9 +117,9 @@ impl Context { pos_arg.loc(), self.caused_by(), "match", - &class("LambdaFunc"), + &mono("LambdaFunc"), t, - self.get_type_mismatch_hint(&class("LambdaFunc"), t), + self.get_type_mismatch_hint(&mono("LambdaFunc"), t), )); } } @@ -441,10 +439,10 @@ impl Context { fv.update_constraint(new_constraint); Ok(Type::FreeVar(fv)) } - Type::PolyTrait { name, params } if params.iter().all(|tp| tp.has_no_unbound_var()) => { + Type::Poly { name, params } if params.iter().all(|tp| tp.has_no_unbound_var()) => { let t_name = name.clone(); let t_params = params.clone(); - let maybe_trait = Type::PolyTrait { name, params }; + let maybe_trait = Type::Poly { name, params }; let mut min = Type::Obj; for pair in self.rec_get_trait_impls(&t_name) { if self.rec_supertype_of(&pair.sup_trait, &maybe_trait) { @@ -466,7 +464,7 @@ impl Context { } } } - Ok(poly_class(t_name, new_params)) + Ok(poly(t_name, new_params)) } else { Ok(min) } @@ -969,7 +967,7 @@ impl Context { concatenated } - pub(crate) fn rec_get_nominal_super_trait_ctxs<'a>( + pub(crate) fn rec_get_nominal_super_classctxs<'a>( &'a self, t: &Type, ) -> impl Iterator { @@ -1026,9 +1024,9 @@ impl Context { return self.rec_get_nominal_type_ctx(&refine.t); } Type::Quantified(_) => { - return self.rec_get_nominal_type_ctx(&class("QuantifiedFunction")); + return self.rec_get_nominal_type_ctx(&mono("QuantifiedFunction")); } - Type::PolyClass { name, params: _ } | Type::PolyTrait { name, params: _ } => { + Type::Poly { name, params: _ } => { if let Some((t, ctx)) = self.poly_types.get(name) { return Some((t, ctx)); } diff --git a/compiler/erg_compiler/context/instantiate.rs b/compiler/erg_compiler/context/instantiate.rs index 966a9d23..9fd9cb8f 100644 --- a/compiler/erg_compiler/context/instantiate.rs +++ b/compiler/erg_compiler/context/instantiate.rs @@ -105,7 +105,7 @@ impl TyVarContext { ) -> Type { if let Some(temp_defaults) = ctx.rec_get_const_param_defaults(&name) { let (_, ctx) = ctx - .rec_get_nominal_type_ctx(&poly_trait(name.clone(), params.clone())) + .rec_get_nominal_type_ctx(&poly(name.clone(), params.clone())) .unwrap_or_else(|| panic!("{} not found", name)); let defined_params_len = ctx.params.len(); let given_params_len = params.len(); @@ -130,9 +130,9 @@ impl TyVarContext { self.push_or_init_typaram(&tp.tvar_name().unwrap(), &tp); inst_defaults.push(tp); } - poly_trait(name, [inst_non_defaults, inst_defaults].concat()) + poly(name, [inst_non_defaults, inst_defaults].concat()) } else { - poly_trait( + poly( name, params .into_iter() @@ -154,18 +154,16 @@ impl TyVarContext { match bound { TyBound::Sandwiched { sub, mid, sup } => { let sub_instance = match sub { - Type::PolyTrait { name, params } => { + Type::Poly { name, params } => { self.instantiate_poly(mid.name(), &name, params, ctx) } - Type::PolyClass { .. } => todo!(), Type::MonoProj { lhs, rhs } => mono_proj(self.instantiate_qvar(*lhs), rhs), sub => sub, }; let sup_instance = match sup { - Type::PolyTrait { name, params } => { + Type::Poly { name, params } => { self.instantiate_poly(mid.name(), &name, params, ctx) } - Type::PolyClass { .. } => todo!(), Type::MonoProj { lhs, rhs } => mono_proj(self.instantiate_qvar(*lhs), rhs), sup => sup, }; @@ -178,8 +176,7 @@ impl TyVarContext { } TyBound::Instance { name, t } => { let t = match t { - Type::PolyClass { .. } => todo!(), - Type::PolyTrait { name, params } => { + Type::Poly { name, params } => { self.instantiate_poly(name.clone(), &name, params, ctx) } t => t, @@ -510,10 +507,10 @@ impl Context { let len = self.instantiate_const_expr(&len.expr); Ok(array(t, len)) } else { - Ok(class("GenericArray")) + Ok(mono("GenericArray")) } } - other if simple.args.is_empty() => Ok(class(Str::rc(other))), + other if simple.args.is_empty() => Ok(mono(Str::rc(other))), other => { // FIXME: kw args let params = simple.args.pos_args().map(|arg| match &arg.expr { @@ -523,7 +520,7 @@ impl Context { } }); // FIXME: if type is a trait - Ok(poly_class(Str::rc(other), params.collect())) + Ok(poly(Str::rc(other), params.collect())) } } } @@ -543,7 +540,7 @@ impl Context { expr: &ast::ConstExpr, ) -> TyCheckResult { match expr { - ast::ConstExpr::Accessor(ast::ConstAccessor::Local(name)) => Ok(class(name.inspect())), + ast::ConstExpr::Accessor(ast::ConstAccessor::Local(name)) => Ok(mono(name.inspect())), _ => todo!(), } } @@ -813,17 +810,11 @@ impl Context { let lhs = Self::instantiate_t(*lhs, tv_ctx); mono_proj(lhs, rhs) } - PolyClass { name, mut params } => { + Poly { name, mut params } => { for param in params.iter_mut() { *param = Self::instantiate_tp(mem::take(param), tv_ctx); } - poly_class(name, params) - } - PolyTrait { name, mut params } => { - for param in params.iter_mut() { - *param = Self::instantiate_tp(mem::take(param), tv_ctx); - } - poly_trait(name, params) + poly(name, params) } Quantified(_) => { panic!("a quantified type should not be instantiated, instantiate the inner type") diff --git a/compiler/erg_compiler/context/mod.rs b/compiler/erg_compiler/context/mod.rs index 6c90f753..c417312e 100644 --- a/compiler/erg_compiler/context/mod.rs +++ b/compiler/erg_compiler/context/mod.rs @@ -84,7 +84,7 @@ pub enum TyParamIdx { impl TyParamIdx { pub fn search(search_from: &Type, target: &Type) -> Option { match search_from { - Type::PolyClass { params, .. } => { + Type::Poly { params, .. } => { for (i, tp) in params.iter().enumerate() { match tp { TyParam::Type(t) if t.as_ref() == target => return Some(Self::Nth(i)), diff --git a/compiler/erg_compiler/context/test.rs b/compiler/erg_compiler/context/test.rs index a2116faa..430cfb7d 100644 --- a/compiler/erg_compiler/context/test.rs +++ b/compiler/erg_compiler/context/test.rs @@ -2,7 +2,7 @@ use erg_common::Str; use erg_common::{enum_unwrap, set}; -use erg_type::constructors::{func1, mono_q, poly_trait, quant, refinement}; +use erg_type::constructors::{func1, mono_q, poly, quant, refinement}; use erg_type::typaram::TyParam; use erg_type::{Predicate, TyBound, Type}; use Type::*; @@ -28,7 +28,7 @@ impl Context { } pub fn test_resolve_trait(&self) -> Result<(), ()> { - let t = poly_trait("Add", vec![TyParam::t(Nat)]); + let t = poly("Add", vec![TyParam::t(Nat)]); match self.resolve_trait(t) { Ok(Nat) => Ok(()), Ok(other) => { @@ -46,7 +46,7 @@ impl Context { pub fn test_resolve_trait_inner1(&self) -> Result<(), ()> { let name = Str::ever("Add"); let params = vec![TyParam::t(Nat)]; - let maybe_trait = poly_trait(name.clone(), params); + let maybe_trait = poly(name.clone(), params); let mut min = Type::Obj; for pair in self.rec_get_trait_impls(&name) { if self.rec_supertype_of(&pair.sup_trait, &maybe_trait) { @@ -62,7 +62,7 @@ impl Context { pub fn test_instantiation_and_generalization(&self) -> Result<(), ()> { let t = mono_q("T"); - let eq = poly_trait("Eq", vec![TyParam::t(t.clone())]); + let eq = poly("Eq", vec![TyParam::t(t.clone())]); let bound = TyBound::subtype_of(t.clone(), eq.clone()); let bounds = set! {bound}; let unbound_t = func1(t.clone(), t.clone()); diff --git a/compiler/erg_compiler/context/tyvar.rs b/compiler/erg_compiler/context/tyvar.rs index 180a9260..9cea5f59 100644 --- a/compiler/erg_compiler/context/tyvar.rs +++ b/compiler/erg_compiler/context/tyvar.rs @@ -158,19 +158,12 @@ impl Context { Callable { .. } => todo!(), Ref(t) => ref_(self.generalize_t_inner(*t, bounds, lazy_inits)), RefMut(t) => ref_mut(self.generalize_t_inner(*t, bounds, lazy_inits)), - PolyClass { name, mut params } => { + Poly { name, mut params } => { let params = params .iter_mut() .map(|p| self.generalize_tp(mem::take(p), bounds, lazy_inits)) .collect::>(); - poly_class(name, params) - } - PolyTrait { name, mut params } => { - let params = params - .iter_mut() - .map(|p| self.generalize_tp(mem::take(p), bounds, lazy_inits)) - .collect::>(); - poly_trait(name, params) + poly(name, params) } // REVIEW: その他何でもそのまま通していいのか? other => other, @@ -313,17 +306,11 @@ impl Context { let t = fv.unwrap_linked(); self.deref_tyvar(t) } - Type::PolyClass { name, mut params } => { + Type::Poly { name, mut params } => { for param in params.iter_mut() { *param = self.deref_tp(mem::take(param))?; } - Ok(Type::PolyClass { name, params }) - } - Type::PolyTrait { name, mut params } => { - for param in params.iter_mut() { - *param = self.deref_tp(mem::take(param))?; - } - let t = Type::PolyTrait { name, params }; + let t = Type::Poly { name, params }; self.resolve_trait(t) } Type::Subr(mut subr) => { @@ -569,7 +556,7 @@ impl Context { } else if allow_divergence && (self.eq_tp(tp, &TyParam::value(Inf)) || self.eq_tp(tp, &TyParam::value(NegInf))) - && self.rec_subtype_of(&fv_t, &trait_("Num")) + && self.rec_subtype_of(&fv_t, &mono("Num")) { fv.link(tp); Ok(()) @@ -844,11 +831,11 @@ impl Context { (Type::Ref(l), r) | (Type::RefMut(l), r) => self.unify(l, r, lhs_loc, rhs_loc), (l, Type::Ref(r)) | (l, Type::RefMut(r)) => self.unify(l, r, lhs_loc, rhs_loc), ( - Type::PolyClass { + Type::Poly { name: ln, params: lps, }, - Type::PolyClass { + Type::Poly { name: rn, params: rps, }, @@ -868,32 +855,7 @@ impl Context { } Ok(()) } - ( - Type::PolyTrait { - name: ln, - params: lps, - }, - Type::PolyTrait { - name: rn, - params: rps, - }, - ) => { - if ln != rn { - return Err(TyCheckError::unification_error( - line!() as usize, - lhs_t, - rhs_t, - lhs_loc, - rhs_loc, - self.caused_by(), - )); - } - for (l, r) in lps.iter().zip(rps.iter()) { - self.unify_tp(l, r, None, false)?; - } - Ok(()) - } - (Type::PolyClass { name: _, params: _ }, _r) => { + (Type::Poly { name: _, params: _ }, _r) => { todo!() } (l, r) => Err(TyCheckError::unification_error( @@ -931,43 +893,17 @@ impl Context { (Type::Ref(l), r) | (Type::RefMut(l), r) => self.reunify(l, r, bef_loc, aft_loc), (l, Type::Ref(r)) | (l, Type::RefMut(r)) => self.reunify(l, r, bef_loc, aft_loc), ( - Type::PolyClass { + Type::Poly { name: ln, params: lps, }, - Type::PolyClass { + Type::Poly { name: rn, params: rps, }, ) => { if ln != rn { - let before_t = poly_class(ln.clone(), lps.clone()); - return Err(TyCheckError::re_unification_error( - line!() as usize, - &before_t, - after_t, - bef_loc, - aft_loc, - self.caused_by(), - )); - } - for (l, r) in lps.iter().zip(rps.iter()) { - self.reunify_tp(l, r)?; - } - Ok(()) - } - ( - Type::PolyTrait { - name: ln, - params: lps, - }, - Type::PolyTrait { - name: rn, - params: rps, - }, - ) => { - if ln != rn { - let before_t = poly_trait(ln.clone(), lps.clone()); + let before_t = poly(ln.clone(), lps.clone()); return Err(TyCheckError::re_unification_error( line!() as usize, &before_t, diff --git a/compiler/erg_compiler/eval.rs b/compiler/erg_compiler/eval.rs index 8e2e0ec9..3d122259 100644 --- a/compiler/erg_compiler/eval.rs +++ b/compiler/erg_compiler/eval.rs @@ -12,9 +12,7 @@ use OpKind::*; use erg_parser::ast::*; use erg_parser::token::{Token, TokenKind}; -use erg_type::constructors::{ - class, enum_t, mono_proj, poly_class, poly_trait, ref_, ref_mut, refinement, subr_t, -}; +use erg_type::constructors::{enum_t, mono, mono_proj, poly, ref_, ref_mut, refinement, subr_t}; use erg_type::typaram::{OpKind, TyParam}; use erg_type::value::ValueObj; use erg_type::{HasType, Predicate, SubrKind, TyBound, Type, ValueArgs}; @@ -250,7 +248,7 @@ impl Context { name.loc(), self.caused_by(), name.inspect(), - &class("Subroutine"), + &mono("Subroutine"), &obj.t(), None, ))? @@ -565,17 +563,11 @@ impl Context { } Type::Ref(l) => Ok(ref_(self.eval_t_params(*l, level)?)), Type::RefMut(l) => Ok(ref_mut(self.eval_t_params(*l, level)?)), - Type::PolyClass { name, mut params } => { + Type::Poly { name, mut params } => { for p in params.iter_mut() { *p = self.eval_tp(&mem::take(p))?; } - Ok(poly_class(name, params)) - } - Type::PolyTrait { name, mut params } => { - for p in params.iter_mut() { - *p = self.eval_tp(&mem::take(p))?; - } - Ok(poly_trait(name, params)) + Ok(poly(name, params)) } other if other.is_monomorphic() => Ok(other), other => todo!("{other}"), diff --git a/compiler/erg_compiler/lower.rs b/compiler/erg_compiler/lower.rs index 50f0b91f..54447516 100644 --- a/compiler/erg_compiler/lower.rs +++ b/compiler/erg_compiler/lower.rs @@ -10,7 +10,7 @@ use erg_parser::ast; use erg_parser::ast::AST; use erg_parser::token::{Token, TokenKind}; -use erg_type::constructors::{array, array_mut, class, free_var, func, poly_class, proc, quant}; +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::ValueObj; @@ -167,7 +167,7 @@ impl ASTLowerer { match maybe_len { Ok(v @ ValueObj::Nat(_)) => { if elem.ref_t().is_mut() { - poly_class( + poly( "ArrayWithMutType!", vec![TyParam::t(elem.t()), TyParam::Value(v)], ) @@ -175,9 +175,9 @@ impl ASTLowerer { array(elem.t(), TyParam::Value(v)) } } - Ok(v @ ValueObj::Mut(_)) if v.class() == class("Nat!") => { + Ok(v @ ValueObj::Mut(_)) if v.class() == mono("Nat!") => { if elem.ref_t().is_mut() { - poly_class( + poly( "ArrayWithMutTypeAndLength!", vec![TyParam::t(elem.t()), TyParam::Value(v)], ) @@ -189,7 +189,7 @@ impl ASTLowerer { // REVIEW: is it ok to ignore the error? Err(_e) => { if elem.ref_t().is_mut() { - poly_class( + poly( "ArrayWithMutType!", vec![TyParam::t(elem.t()), TyParam::erased(Type::Nat)], ) diff --git a/compiler/erg_type/constructors.rs b/compiler/erg_type/constructors.rs index 756df604..693d46a6 100644 --- a/compiler/erg_type/constructors.rs +++ b/compiler/erg_type/constructors.rs @@ -21,25 +21,25 @@ pub fn named_free_var(name: Str, level: usize, constraint: Constraint) -> Type { } pub fn array(elem_t: Type, len: TyParam) -> Type { - poly_class("Array", vec![TyParam::t(elem_t), len]) + poly("Array", vec![TyParam::t(elem_t), len]) } pub fn array_mut(elem_t: Type, len: TyParam) -> Type { - poly_class("Array!", vec![TyParam::t(elem_t), len]) + poly("Array!", vec![TyParam::t(elem_t), len]) } pub fn dict(k_t: Type, v_t: Type) -> Type { - poly_class("Dict", vec![TyParam::t(k_t), TyParam::t(v_t)]) + poly("Dict", vec![TyParam::t(k_t), TyParam::t(v_t)]) } pub fn tuple(args: Vec) -> Type { let name = format!("Tuple{}", args.len()); - poly_class(name, args.into_iter().map(TyParam::t).collect()) + poly(name, args.into_iter().map(TyParam::t).collect()) } #[inline] pub fn range(t: Type) -> Type { - poly_class("Range", vec![TyParam::t(t)]) + poly("Range", vec![TyParam::t(t)]) } pub fn enum_t(s: Set) -> Type { @@ -91,7 +91,7 @@ pub fn int_interval, Q: Into>(op: IntervalOp, l: P, r: } pub fn iter(t: Type) -> Type { - poly_class("Iter", vec![TyParam::t(t)]) + poly("Iter", vec![TyParam::t(t)]) } pub fn ref_(t: Type) -> Type { @@ -103,11 +103,11 @@ pub fn ref_mut(t: Type) -> Type { } pub fn option(t: Type) -> Type { - poly_class("Option", vec![TyParam::t(t)]) + poly("Option", vec![TyParam::t(t)]) } pub fn option_mut(t: Type) -> Type { - poly_class("Option!", vec![TyParam::t(t)]) + poly("Option!", vec![TyParam::t(t)]) } pub fn subr_t( @@ -286,13 +286,8 @@ pub fn callable(param_ts: Vec, return_t: Type) -> Type { } #[inline] -pub fn class>(name: S) -> Type { - Type::MonoClass(name.into()) -} - -#[inline] -pub fn trait_>(name: S) -> Type { - Type::MonoTrait(name.into()) +pub fn mono>(name: S) -> Type { + Type::Mono(name.into()) } #[inline] @@ -301,16 +296,8 @@ pub fn mono_q>(name: S) -> Type { } #[inline] -pub fn poly_class>(name: S, params: Vec) -> Type { - Type::PolyClass { - name: name.into(), - params, - } -} - -#[inline] -pub fn poly_trait>(name: S, params: Vec) -> Type { - Type::PolyTrait { +pub fn poly>(name: S, params: Vec) -> Type { + Type::Poly { name: name.into(), params, } diff --git a/compiler/erg_type/lib.rs b/compiler/erg_type/lib.rs index 4ce9b045..c2c22267 100644 --- a/compiler/erg_type/lib.rs +++ b/compiler/erg_type/lib.rs @@ -18,7 +18,7 @@ use erg_common::vis::Field; use erg_common::{enum_unwrap, fmt_option, fmt_set_split_with, set, Str}; use crate::codeobj::CodeObj; -use crate::constructors::{and, class, int_interval, mono_q}; +use crate::constructors::{and, int_interval, mono, mono_q}; use crate::free::{ fresh_varname, Constraint, Cyclicity, Free, FreeKind, FreeTyVar, HasLevel, Level, }; @@ -1149,8 +1149,7 @@ pub enum Type { NotImplemented, Ellipsis, // これはクラスのほうで型推論用のマーカーではない Never, // {} - MonoClass(Str), - MonoTrait(Str), + Mono(Str), /* Polymorphic types */ Ref(Box), RefMut(Box), @@ -1173,14 +1172,10 @@ pub enum Type { And(Box, Box), Not(Box, Box), Or(Box, Box), - PolyClass { + Poly { name: Str, params: Vec, - }, // T(params) - PolyTrait { - name: Str, - params: Vec, - }, // T(params) + }, /* Special types (inference-time types) */ MonoQVar(Str), // QuantifiedTyの中で使う一般化型変数、利便性のためMonoとは区別する PolyQVar { @@ -1221,9 +1216,7 @@ impl PartialEq for Type { | (Self::NotImplemented, Self::NotImplemented) | (Self::Ellipsis, Self::Ellipsis) | (Self::Never, Self::Never) => true, - (Self::MonoClass(l), Self::MonoClass(r)) | (Self::MonoTrait(l), Self::MonoTrait(r)) => { - l == r - } + (Self::Mono(l), Self::Mono(r)) => l == r, (Self::MonoQVar(l), Self::MonoQVar(r)) => l == r, (Self::Ref(l), Self::Ref(r)) | (Self::RefMut(l), Self::RefMut(r)) => l == r, (Self::Subr(l), Self::Subr(r)) => l == r, @@ -1255,11 +1248,7 @@ impl PartialEq for Type { | (Self::Not(ll, lr), Self::Not(rl, rr)) | (Self::Or(ll, lr), Self::Or(rl, rr)) => ll == rl && lr == rr, ( - Self::PolyClass { - name: ln, - params: lps, - } - | Self::PolyTrait { + Self::Poly { name: ln, params: lps, } @@ -1267,11 +1256,7 @@ impl PartialEq for Type { name: ln, params: lps, }, - Self::PolyClass { - name: rn, - params: rps, - } - | Self::PolyTrait { + Self::Poly { name: rn, params: rps, } @@ -1316,7 +1301,7 @@ impl LimitedDisplay for Type { return write!(f, "..."); } match self { - Self::MonoClass(name) | Self::MonoTrait(name) => write!(f, "{name}"), + Self::Mono(name) => write!(f, "{name}"), Self::Ref(t) | Self::RefMut(t) => { write!(f, "{}(", self.name())?; t.limited_fmt(f, limit - 1)?; @@ -1364,7 +1349,7 @@ impl LimitedDisplay for Type { write!(f, " or ")?; rhs.limited_fmt(f, limit - 1) } - Self::PolyClass { name, params } | Self::PolyTrait { name, params } => { + Self::Poly { name, params } => { write!(f, "{name}(")?; for (i, tp) in params.iter().enumerate() { if i > 0 { @@ -1453,7 +1438,7 @@ impl From<&str> for Type { "Inf" => Self::Inf, "NegInf" => Self::NegInf, "_" => Self::Obj, - other => Self::MonoClass(Str::rc(other)), + other => Self::Mono(Str::rc(other)), } } } @@ -1483,9 +1468,7 @@ impl HasType for Type { // Self::And(ts) | Self::Or(ts) => , Self::Subr(_sub) => todo!(), Self::Callable { param_ts, .. } => param_ts.clone(), - Self::PolyClass { params, .. } | Self::PolyTrait { params, .. } => { - params.iter().filter_map(get_t_from_tp).collect() - } + Self::Poly { params, .. } => params.iter().filter_map(get_t_from_tp).collect(), _ => vec![], } } @@ -1538,7 +1521,7 @@ impl HasLevel for Type { t.update_level(level); } } - Self::PolyClass { params, .. } | Self::PolyTrait { params, .. } => { + Self::Poly { params, .. } => { for p in params.iter() { p.update_level(level); } @@ -1592,7 +1575,7 @@ impl HasLevel for Type { t.lift(); } } - Self::PolyClass { params, .. } | Self::PolyTrait { params, .. } => { + Self::Poly { params, .. } => { for p in params.iter() { p.lift(); } @@ -1643,12 +1626,12 @@ impl Type { fv.link(&t.mutate()); Self::FreeVar(fv) } - Self::Int => class("Int!"), - Self::Nat => class("Nat!"), - Self::Ratio => class("Ratio!"), - Self::Float => class("Float!"), - Self::Bool => class("Bool!"), - Self::Str => class("Str!"), + Self::Int => mono("Int!"), + Self::Nat => mono("Nat!"), + Self::Ratio => mono("Ratio!"), + Self::Float => mono("Float!"), + Self::Bool => mono("Bool!"), + Self::Str => mono("Str!"), _ => todo!(), } } @@ -1682,49 +1665,6 @@ impl Type { } } - pub fn is_class(&self) -> bool { - match self { - Self::FreeVar(fv) if fv.is_linked() => fv.crack().is_class(), - Self::Refinement(refine) => refine.t.is_class(), - Self::Obj - | Self::Int - | Self::Nat - | Self::Ratio - | Self::Float - | Self::Bool - | Self::Str - | Self::NoneType - | Self::Code - | Self::Module - | Self::Frame - | Self::Error - | Self::Inf - | Self::NegInf - | Self::Type - | Self::Class - | Self::Trait - | Self::Patch - | Self::NotImplemented - | Self::Ellipsis - | Self::Never - | Self::Subr(_) - | Self::Callable { .. } - | Self::Record(_) - | Self::Quantified(_) => true, - Self::MonoClass(_) | Self::PolyClass { .. } => true, - _ => false, - } - } - - pub fn is_trait(&self) -> bool { - match self { - Self::FreeVar(fv) if fv.is_linked() => fv.crack().is_trait(), - Self::Refinement(refine) => refine.t.is_trait(), - Self::MonoTrait(_) | Self::PolyTrait { .. } => true, - _ => false, - } - } - pub fn is_mut(&self) -> bool { match self { Self::FreeVar(fv) => { @@ -1734,11 +1674,9 @@ impl Type { fv.unbound_name().unwrap().ends_with('!') } } - Self::MonoClass(name) - | Self::MonoTrait(name) + Self::Mono(name) | Self::MonoQVar(name) - | Self::PolyClass { name, .. } - | Self::PolyTrait { name, .. } + | Self::Poly { name, .. } | Self::PolyQVar { name, .. } | Self::MonoProj { rhs: name, .. } => name.ends_with('!'), Self::Refinement(refine) => refine.t.is_mut(), @@ -1750,11 +1688,11 @@ impl Type { match self { Self::FreeVar(fv) if fv.is_linked() => fv.crack().is_nonelike(), Self::NoneType => true, - Self::PolyClass { name, params } if &name[..] == "Option" || &name[..] == "Option!" => { + Self::Poly { name, params } if &name[..] == "Option" || &name[..] == "Option!" => { let inner_t = enum_unwrap!(params.first().unwrap(), TyParam::Type); inner_t.is_nonelike() } - Self::PolyClass { name, params } if &name[..] == "Tuple" => params.is_empty(), + Self::Poly { name, params } if &name[..] == "Tuple" => params.is_empty(), Self::Refinement(refine) => refine.t.is_nonelike(), _ => false, } @@ -1773,7 +1711,7 @@ impl Type { .map(|(sub, sup)| sub.contains_tvar(name) || sup.contains_tvar(name)) .unwrap_or(false) } - Self::PolyClass { params, .. } | Self::PolyTrait { params, .. } => { + Self::Poly { params, .. } => { for param in params.iter() { match param { TyParam::Type(t) if t.contains_tvar(name) => { @@ -1870,7 +1808,7 @@ impl Type { Self::Error => Str::ever("Error"), Self::Inf => Str::ever("Inf"), Self::NegInf => Str::ever("NegInf"), - Self::MonoClass(name) | Self::MonoTrait(name) | Self::MonoQVar(name) => name.clone(), + Self::Mono(name) | Self::MonoQVar(name) => name.clone(), Self::And(_, _) => Str::ever("And"), Self::Not(_, _) => Str::ever("Not"), Self::Or(_, _) => Str::ever("Or"), @@ -1894,9 +1832,7 @@ impl Type { }) => Str::ever("ProcMethod"), Self::Callable { .. } => Str::ever("Callable"), Self::Record(_) => Str::ever("Record"), - Self::PolyClass { name, .. } - | Self::PolyTrait { name, .. } - | Self::PolyQVar { name, .. } => name.clone(), + Self::Poly { name, .. } | Self::PolyQVar { name, .. } => name.clone(), // NOTE: compiler/codegen/convert_to_python_methodでクラス名を使うため、こうすると都合が良い Self::Refinement(refine) => refine.t.name(), Self::Quantified(_) => Str::ever("Quantified"), @@ -1967,9 +1903,7 @@ impl Type { quant.unbound_callable.has_unbound_var() || quant.bounds.iter().any(|tb| tb.has_qvar()) } - Self::PolyClass { params, .. } | Self::PolyTrait { params, .. } => { - params.iter().any(|tp| tp.has_qvar()) - } + Self::Poly { params, .. } => params.iter().any(|tp| tp.has_qvar()), Self::MonoProj { lhs, .. } => lhs.has_qvar(), _ => false, } @@ -2006,9 +1940,9 @@ impl Type { Self::Quantified(quant) => { quant.unbound_callable.is_cachable() || quant.bounds.iter().all(|b| b.is_cachable()) } - Self::PolyClass { params, .. } - | Self::PolyTrait { params, .. } - | Self::PolyQVar { params, .. } => params.iter().all(|p| p.is_cachable()), + Self::Poly { params, .. } | Self::PolyQVar { params, .. } => { + params.iter().all(|p| p.is_cachable()) + } Self::MonoProj { lhs, .. } => lhs.is_cachable(), _ => true, } @@ -2055,9 +1989,9 @@ impl Type { quant.unbound_callable.has_unbound_var() || quant.bounds.iter().any(|b| b.has_unbound_var()) } - Self::PolyClass { params, .. } - | Self::PolyTrait { params, .. } - | Self::PolyQVar { params, .. } => params.iter().any(|p| p.has_unbound_var()), + Self::Poly { params, .. } | Self::PolyQVar { params, .. } => { + params.iter().any(|p| p.has_unbound_var()) + } Self::MonoProj { lhs, .. } => lhs.has_no_unbound_var(), _ => false, } @@ -2082,9 +2016,7 @@ impl Type { + 1, ), Self::Callable { param_ts, .. } => Some(param_ts.len() + 1), - Self::PolyClass { params, .. } - | Self::PolyTrait { params, .. } - | Self::PolyQVar { params, .. } => Some(params.len()), + Self::Poly { params, .. } | Self::PolyQVar { params, .. } => Some(params.len()), _ => None, } } @@ -2100,9 +2032,7 @@ impl Type { } Self::Subr(subr) => subr.typarams(), Self::Callable { param_ts: _, .. } => todo!(), - Self::PolyClass { params, .. } - | Self::PolyTrait { params, .. } - | Self::PolyQVar { params, .. } => params.clone(), + Self::Poly { params, .. } | Self::PolyQVar { params, .. } => params.clone(), _ => vec![], } } @@ -2227,7 +2157,7 @@ impl From<&Type> for TypeCode { Type::Float => Self::Float64, Type::Bool => Self::Bool, Type::Str => Self::Str, - Type::MonoClass(name) => match &name[..] { + Type::Mono(name) => match &name[..] { "Int!" => Self::Int32, "Nat!" => Self::Nat64, "Float!" => Self::Float64, @@ -2235,7 +2165,7 @@ impl From<&Type> for TypeCode { "Str!" => Self::Str, _ => Self::Other, }, - Type::PolyClass { name, .. } => match &name[..] { + Type::Poly { name, .. } => match &name[..] { "Array" | "Array!" => Self::Array, "Func" => Self::Func, "Proc" => Self::Proc, @@ -2404,98 +2334,98 @@ impl TypePair { (Type::Int, Type::Float) => Self::IntFloat, (Type::Int, Type::Str) => Self::IntStr, (Type::Int, Type::Bool) => Self::IntBool, - (Type::Int, Type::PolyClass { name, .. }) if &name[..] == "Array" => Self::IntArray, - (Type::Int, Type::PolyClass { name, .. }) if &name[..] == "Func" => Self::IntFunc, - (Type::Int, Type::PolyClass { name, .. }) if &name[..] == "Proc" => Self::IntProc, + (Type::Int, Type::Poly { name, .. }) if &name[..] == "Array" => Self::IntArray, + (Type::Int, Type::Poly { name, .. }) if &name[..] == "Func" => Self::IntFunc, + (Type::Int, Type::Poly { name, .. }) if &name[..] == "Proc" => Self::IntProc, (Type::Nat, Type::Int) => Self::NatInt, (Type::Nat, Type::Nat) => Self::NatNat, (Type::Nat, Type::Float) => Self::NatFloat, (Type::Nat, Type::Str) => Self::NatStr, (Type::Nat, Type::Bool) => Self::NatBool, - (Type::Nat, Type::PolyClass { name, .. }) if &name[..] == "Array" => Self::NatArray, - (Type::Nat, Type::PolyClass { name, .. }) if &name[..] == "Func" => Self::NatFunc, - (Type::Nat, Type::PolyClass { name, .. }) if &name[..] == "Proc" => Self::NatProc, + (Type::Nat, Type::Poly { name, .. }) if &name[..] == "Array" => Self::NatArray, + (Type::Nat, Type::Poly { name, .. }) if &name[..] == "Func" => Self::NatFunc, + (Type::Nat, Type::Poly { name, .. }) if &name[..] == "Proc" => Self::NatProc, (Type::Float, Type::Int) => Self::FloatInt, (Type::Float, Type::Nat) => Self::FloatNat, (Type::Float, Type::Float) => Self::FloatFloat, (Type::Float, Type::Str) => Self::FloatStr, (Type::Float, Type::Bool) => Self::FloatBool, - (Type::Float, Type::PolyClass { name, .. }) if &name[..] == "Array" => Self::FloatArray, - (Type::Float, Type::PolyClass { name, .. }) if &name[..] == "Func" => Self::FloatFunc, - (Type::Float, Type::PolyClass { name, .. }) if &name[..] == "Proc" => Self::FloatProc, + (Type::Float, Type::Poly { name, .. }) if &name[..] == "Array" => Self::FloatArray, + (Type::Float, Type::Poly { name, .. }) if &name[..] == "Func" => Self::FloatFunc, + (Type::Float, Type::Poly { name, .. }) if &name[..] == "Proc" => Self::FloatProc, (Type::Bool, Type::Int) => Self::BoolInt, (Type::Bool, Type::Nat) => Self::BoolNat, (Type::Bool, Type::Float) => Self::BoolFloat, (Type::Bool, Type::Str) => Self::BoolStr, (Type::Bool, Type::Bool) => Self::BoolBool, - (Type::Bool, Type::PolyClass { name, .. }) if &name[..] == "Array" => Self::BoolArray, - (Type::Bool, Type::PolyClass { name, .. }) if &name[..] == "Func" => Self::BoolFunc, - (Type::Bool, Type::PolyClass { name, .. }) if &name[..] == "Proc" => Self::BoolProc, + (Type::Bool, Type::Poly { name, .. }) if &name[..] == "Array" => Self::BoolArray, + (Type::Bool, Type::Poly { name, .. }) if &name[..] == "Func" => Self::BoolFunc, + (Type::Bool, Type::Poly { name, .. }) if &name[..] == "Proc" => Self::BoolProc, (Type::Str, Type::Int) => Self::StrInt, (Type::Str, Type::Nat) => Self::StrNat, (Type::Str, Type::Float) => Self::StrFloat, (Type::Str, Type::Bool) => Self::StrBool, (Type::Str, Type::Str) => Self::StrStr, - (Type::Str, Type::PolyClass { name, .. }) if &name[..] == "Array" => Self::StrArray, - (Type::Str, Type::PolyClass { name, .. }) if &name[..] == "Func" => Self::StrFunc, - (Type::Str, Type::PolyClass { name, .. }) if &name[..] == "Proc" => Self::StrProc, + (Type::Str, Type::Poly { name, .. }) if &name[..] == "Array" => Self::StrArray, + (Type::Str, Type::Poly { name, .. }) if &name[..] == "Func" => Self::StrFunc, + (Type::Str, Type::Poly { name, .. }) if &name[..] == "Proc" => Self::StrProc, // 要素数は検査済みなので、気にする必要はない - (Type::PolyClass { name, .. }, Type::Int) if &name[..] == "Array" => Self::ArrayInt, - (Type::PolyClass { name, .. }, Type::Nat) if &name[..] == "Array" => Self::ArrayNat, - (Type::PolyClass { name, .. }, Type::Float) if &name[..] == "Array" => Self::ArrayFloat, - (Type::PolyClass { name, .. }, Type::Str) if &name[..] == "Array" => Self::ArrayStr, - (Type::PolyClass { name, .. }, Type::Bool) if &name[..] == "Array" => Self::ArrayBool, - (Type::PolyClass { name: ln, .. }, Type::PolyClass { name: rn, .. }) + (Type::Poly { name, .. }, Type::Int) if &name[..] == "Array" => Self::ArrayInt, + (Type::Poly { name, .. }, Type::Nat) if &name[..] == "Array" => Self::ArrayNat, + (Type::Poly { name, .. }, Type::Float) if &name[..] == "Array" => Self::ArrayFloat, + (Type::Poly { name, .. }, Type::Str) if &name[..] == "Array" => Self::ArrayStr, + (Type::Poly { name, .. }, Type::Bool) if &name[..] == "Array" => Self::ArrayBool, + (Type::Poly { name: ln, .. }, Type::Poly { name: rn, .. }) if &ln[..] == "Array" && &rn[..] == "Array" => { Self::ArrayArray } - (Type::PolyClass { name: ln, .. }, Type::PolyClass { name: rn, .. }) + (Type::Poly { name: ln, .. }, Type::Poly { name: rn, .. }) if &ln[..] == "Array" && &rn[..] == "Func" => { Self::ArrayFunc } - (Type::PolyClass { name: ln, .. }, Type::PolyClass { name: rn, .. }) + (Type::Poly { name: ln, .. }, Type::Poly { name: rn, .. }) if &ln[..] == "Array" && &rn[..] == "Proc" => { Self::ArrayProc } - (Type::PolyClass { name, .. }, Type::Int) if &name[..] == "Func" => Self::FuncInt, - (Type::PolyClass { name, .. }, Type::Nat) if &name[..] == "Func" => Self::FuncNat, - (Type::PolyClass { name, .. }, Type::Float) if &name[..] == "Func" => Self::FuncFloat, - (Type::PolyClass { name, .. }, Type::Str) if &name[..] == "Func" => Self::FuncStr, - (Type::PolyClass { name, .. }, Type::Bool) if &name[..] == "Func" => Self::FuncBool, - (Type::PolyClass { name: ln, .. }, Type::PolyClass { name: rn, .. }) + (Type::Poly { name, .. }, Type::Int) if &name[..] == "Func" => Self::FuncInt, + (Type::Poly { name, .. }, Type::Nat) if &name[..] == "Func" => Self::FuncNat, + (Type::Poly { name, .. }, Type::Float) if &name[..] == "Func" => Self::FuncFloat, + (Type::Poly { name, .. }, Type::Str) if &name[..] == "Func" => Self::FuncStr, + (Type::Poly { name, .. }, Type::Bool) if &name[..] == "Func" => Self::FuncBool, + (Type::Poly { name: ln, .. }, Type::Poly { name: rn, .. }) if &ln[..] == "Func" && &rn[..] == "Array" => { Self::FuncArray } - (Type::PolyClass { name: ln, .. }, Type::PolyClass { name: rn, .. }) + (Type::Poly { name: ln, .. }, Type::Poly { name: rn, .. }) if &ln[..] == "Func" && &rn[..] == "Func" => { Self::FuncFunc } - (Type::PolyClass { name: ln, .. }, Type::PolyClass { name: rn, .. }) + (Type::Poly { name: ln, .. }, Type::Poly { name: rn, .. }) if &ln[..] == "Func" && &rn[..] == "Proc" => { Self::FuncProc } - (Type::PolyClass { name, .. }, Type::Int) if &name[..] == "Proc" => Self::ProcInt, - (Type::PolyClass { name, .. }, Type::Nat) if &name[..] == "Proc" => Self::ProcNat, - (Type::PolyClass { name, .. }, Type::Float) if &name[..] == "Proc" => Self::ProcFloat, - (Type::PolyClass { name, .. }, Type::Str) if &name[..] == "Proc" => Self::ProcStr, - (Type::PolyClass { name, .. }, Type::Bool) if &name[..] == "Proc" => Self::ProcBool, - (Type::PolyClass { name: ln, .. }, Type::PolyClass { name: rn, .. }) + (Type::Poly { name, .. }, Type::Int) if &name[..] == "Proc" => Self::ProcInt, + (Type::Poly { name, .. }, Type::Nat) if &name[..] == "Proc" => Self::ProcNat, + (Type::Poly { name, .. }, Type::Float) if &name[..] == "Proc" => Self::ProcFloat, + (Type::Poly { name, .. }, Type::Str) if &name[..] == "Proc" => Self::ProcStr, + (Type::Poly { name, .. }, Type::Bool) if &name[..] == "Proc" => Self::ProcBool, + (Type::Poly { name: ln, .. }, Type::Poly { name: rn, .. }) if &ln[..] == "Proc" && &rn[..] == "Array" => { Self::ProcArray } - (Type::PolyClass { name: ln, .. }, Type::PolyClass { name: rn, .. }) + (Type::Poly { name: ln, .. }, Type::Poly { name: rn, .. }) if &ln[..] == "Proc" && &rn[..] == "Func" => { Self::ProcFunc } - (Type::PolyClass { name: ln, .. }, Type::PolyClass { name: rn, .. }) + (Type::Poly { name: ln, .. }, Type::Poly { name: rn, .. }) if &ln[..] == "Proc" && &rn[..] == "Proc" => { Self::ProcProc diff --git a/compiler/erg_type/value.rs b/compiler/erg_type/value.rs index 2527dd22..9936fa9c 100644 --- a/compiler/erg_type/value.rs +++ b/compiler/erg_type/value.rs @@ -17,7 +17,7 @@ use erg_common::{fmt_iter, impl_display_from_debug, switch_lang}; use erg_common::{RcArray, Str}; use crate::codeobj::CodeObj; -use crate::constructors::{array, class, poly_class, refinement, tuple}; +use crate::constructors::{array, mono, poly, refinement, tuple}; use crate::free::fresh_varname; use crate::typaram::TyParam; use crate::{ConstSubr, HasType, Predicate, Type}; @@ -384,12 +384,12 @@ impl ValueObj { Self::Inf => Type::Inf, Self::NegInf => Type::NegInf, Self::Mut(m) => match &*m.borrow() { - Self::Int(_) => class("Int!"), - Self::Nat(_) => class("Nat!"), - Self::Float(_) => class("Float!"), - Self::Str(_) => class("Str!"), - Self::Bool(_) => class("Bool!"), - Self::Array(arr) => poly_class( + Self::Int(_) => mono("Int!"), + Self::Nat(_) => mono("Nat!"), + Self::Float(_) => mono("Float!"), + Self::Str(_) => mono("Str!"), + Self::Bool(_) => mono("Bool!"), + Self::Array(arr) => poly( "Array!", vec![ TyParam::t(arr.iter().next().unwrap().class()), From 18116f14ed0b4cdd322d49d9d42d98433be12fe0 Mon Sep 17 00:00:00 2001 From: Shunsuke Shibayama Date: Sat, 3 Sep 2022 22:23:25 +0900 Subject: [PATCH 14/68] Impl `DataPackVattern` desugaring --- compiler/erg_parser/ast.rs | 10 +-- compiler/erg_parser/desugar.rs | 112 ++++++++++++++++++++++----------- compiler/erg_parser/parse.rs | 9 ++- 3 files changed, 88 insertions(+), 43 deletions(-) diff --git a/compiler/erg_parser/ast.rs b/compiler/erg_parser/ast.rs index a1e824b0..06104050 100644 --- a/compiler/erg_parser/ast.rs +++ b/compiler/erg_parser/ast.rs @@ -1976,8 +1976,8 @@ impl VarTuplePattern { #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub struct VarRecordAttr { - lhs: Identifier, - rhs: Identifier, + pub lhs: Identifier, + pub rhs: VarSignature, } impl NestedDisplay for VarRecordAttr { @@ -1990,7 +1990,7 @@ impl_display_from_nested!(VarRecordAttr); impl_locational!(VarRecordAttr, lhs, rhs); impl VarRecordAttr { - pub const fn new(lhs: Identifier, rhs: Identifier) -> Self { + pub const fn new(lhs: Identifier, rhs: VarSignature) -> Self { Self { lhs, rhs } } } @@ -2046,7 +2046,7 @@ impl VarRecordPattern { #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub struct VarDataPackPattern { - pub class: Accessor, // TODO: allow polymorphic + pub class: TypeSpec, pub args: VarRecordPattern, } @@ -2059,7 +2059,7 @@ impl fmt::Display for VarDataPackPattern { impl_locational!(VarDataPackPattern, class, args); impl VarDataPackPattern { - pub const fn new(class: Accessor, args: VarRecordPattern) -> Self { + pub const fn new(class: TypeSpec, args: VarRecordPattern) -> Self { Self { class, args } } } diff --git a/compiler/erg_parser/desugar.rs b/compiler/erg_parser/desugar.rs index a4ab3198..e73c6f8a 100644 --- a/compiler/erg_parser/desugar.rs +++ b/compiler/erg_parser/desugar.rs @@ -15,7 +15,7 @@ use crate::ast::{ KwArg, Lambda, LambdaSignature, Literal, Local, MethodDefs, Module, NormalArray, NormalRecord, NormalTuple, ParamPattern, ParamSignature, Params, PosArg, Record, RecordAttrs, ShortenedRecord, Signature, SubrSignature, Tuple, TypeAscription, TypeBoundSpecs, TypeSpec, - UnaryOp, VarName, VarPattern, VarSignature, + UnaryOp, VarName, VarPattern, VarRecordAttr, VarSignature, }; use crate::token::{Token, TokenKind}; @@ -164,6 +164,19 @@ impl Desugarer { todo!() } + fn gen_buf_name_and_sig( + &mut self, + line: usize, + t_spec: Option, + ) -> (String, Signature) { + let buf_name = self.fresh_var_name(); + let buf_sig = Signature::Var(VarSignature::new( + VarPattern::Ident(Identifier::private_with_line(Str::rc(&buf_name), line)), + t_spec, + )); + (buf_name, buf_sig) + } + /// `[i, j] = [1, 2]` -> `i = 1; j = 2` /// `[i, j] = l` -> `i = l[0]; j = l[1]` /// `[i, [j, k]] = l` -> `i = l[0]; j = l[1][0]; k = l[1][1]` @@ -178,14 +191,8 @@ impl Desugarer { body, }) => match &v.pat { VarPattern::Tuple(tup) => { - let buf_name = self.fresh_var_name(); - let buf_sig = Signature::Var(VarSignature::new( - VarPattern::Ident(Identifier::private_with_line( - Str::rc(&buf_name), - v.ln_begin().unwrap(), - )), - v.t_spec, - )); + let (buf_name, buf_sig) = + self.gen_buf_name_and_sig(v.ln_begin().unwrap(), v.t_spec); let buf_def = Def::new(buf_sig, body); new.push(Expr::Def(buf_def)); for (n, elem) in tup.elems.iter().enumerate() { @@ -198,14 +205,8 @@ impl Desugarer { } } VarPattern::Array(arr) => { - let buf_name = self.fresh_var_name(); - let buf_sig = Signature::Var(VarSignature::new( - VarPattern::Ident(Identifier::private_with_line( - Str::rc(&buf_name), - v.ln_begin().unwrap(), - )), - v.t_spec, - )); + let (buf_name, buf_sig) = + self.gen_buf_name_and_sig(v.ln_begin().unwrap(), v.t_spec); let buf_def = Def::new(buf_sig, body); new.push(Expr::Def(buf_def)); for (n, elem) in arr.elems.iter().enumerate() { @@ -217,7 +218,36 @@ impl Desugarer { ); } } - VarPattern::Record(_rec) => todo!(), + VarPattern::Record(rec) => { + let (buf_name, buf_sig) = + self.gen_buf_name_and_sig(v.ln_begin().unwrap(), v.t_spec); + let buf_def = Def::new(buf_sig, body); + new.push(Expr::Def(buf_def)); + for VarRecordAttr { lhs, rhs } in rec.attrs.iter() { + self.desugar_nested_var_pattern( + &mut new, + rhs, + &buf_name, + BufIndex::Record(lhs.inspect()), + ); + } + } + VarPattern::DataPack(pack) => { + let (buf_name, buf_sig) = self.gen_buf_name_and_sig( + v.ln_begin().unwrap(), + Some(pack.class.clone()), // TODO: これだとvの型指定の意味がなくなる + ); + let buf_def = Def::new(buf_sig, body); + new.push(Expr::Def(buf_def)); + for VarRecordAttr { lhs, rhs } in pack.args.attrs.iter() { + self.desugar_nested_var_pattern( + &mut new, + rhs, + &buf_name, + BufIndex::Record(lhs.inspect()), + ); + } + } VarPattern::Ident(_i) => { let def = Def::new(Signature::Var(v), body); new.push(Expr::Def(def)); @@ -262,14 +292,7 @@ impl Desugarer { let body = DefBody::new(op, block, id); match &sig.pat { VarPattern::Tuple(tup) => { - let buf_name = self.fresh_var_name(); - let buf_sig = Signature::Var(VarSignature::new( - VarPattern::Ident(Identifier::private_with_line( - Str::rc(&buf_name), - sig.ln_begin().unwrap(), - )), - None, - )); + let (buf_name, buf_sig) = self.gen_buf_name_and_sig(sig.ln_begin().unwrap(), None); let buf_def = Def::new(buf_sig, body); new_module.push(Expr::Def(buf_def)); for (n, elem) in tup.elems.iter().enumerate() { @@ -282,14 +305,7 @@ impl Desugarer { } } VarPattern::Array(arr) => { - let buf_name = self.fresh_var_name(); - let buf_sig = Signature::Var(VarSignature::new( - VarPattern::Ident(Identifier::private_with_line( - Str::rc(&buf_name), - sig.ln_begin().unwrap(), - )), - None, - )); + let (buf_name, buf_sig) = self.gen_buf_name_and_sig(sig.ln_begin().unwrap(), None); let buf_def = Def::new(buf_sig, body); new_module.push(Expr::Def(buf_def)); for (n, elem) in arr.elems.iter().enumerate() { @@ -301,7 +317,33 @@ impl Desugarer { ); } } - VarPattern::Record(_rec) => todo!(), + VarPattern::Record(rec) => { + let (buf_name, buf_sig) = self.gen_buf_name_and_sig(sig.ln_begin().unwrap(), None); + let buf_def = Def::new(buf_sig, body); + new_module.push(Expr::Def(buf_def)); + for VarRecordAttr { lhs, rhs } in rec.attrs.iter() { + self.desugar_nested_var_pattern( + new_module, + rhs, + &buf_name, + BufIndex::Record(lhs.inspect()), + ); + } + } + VarPattern::DataPack(pack) => { + let (buf_name, buf_sig) = + self.gen_buf_name_and_sig(sig.ln_begin().unwrap(), Some(pack.class.clone())); + let buf_def = Def::new(buf_sig, body); + new_module.push(Expr::Def(buf_def)); + for VarRecordAttr { lhs, rhs } in pack.args.attrs.iter() { + self.desugar_nested_var_pattern( + new_module, + rhs, + &buf_name, + BufIndex::Record(lhs.inspect()), + ); + } + } VarPattern::Ident(_ident) => { let def = Def::new(Signature::Var(sig.clone()), body); new_module.push(Expr::Def(def)); diff --git a/compiler/erg_parser/parse.rs b/compiler/erg_parser/parse.rs index 1c7c1879..38952d32 100644 --- a/compiler/erg_parser/parse.rs +++ b/compiler/erg_parser/parse.rs @@ -1706,7 +1706,7 @@ impl Parser { let rhs = option_enum_unwrap!(attr.body.block.remove(0), Expr::Accessor) .unwrap_or_else(|| todo!()); let rhs = self - .convert_accessor_to_ident(rhs) + .convert_accessor_to_var_sig(rhs) .map_err(|_| self.stack_dec())?; pats.push(VarRecordAttr::new(lhs, rhs)); } @@ -1717,7 +1717,8 @@ impl Parser { Record::Shortened(rec) => { let mut pats = vec![]; for ident in rec.idents.into_iter() { - pats.push(VarRecordAttr::new(ident.clone(), ident)); + let rhs = VarSignature::new(VarPattern::Ident(ident.clone()), None); + pats.push(VarRecordAttr::new(ident.clone(), rhs)); } let attrs = VarRecordAttrs::new(pats); self.level -= 1; @@ -1731,7 +1732,9 @@ impl Parser { pack: DataPack, ) -> ParseResult { debug_call_info!(self); - let class = option_enum_unwrap!(*pack.class, Expr::Accessor).unwrap_or_else(|| todo!()); + let class = self + .convert_rhs_to_type_spec(*pack.class) + .map_err(|_| self.stack_dec())?; let args = self .convert_record_to_record_pat(pack.args) .map_err(|_| self.stack_dec())?; From f4cb9f67a5421b3de4bb4e2bbfb6a2f03e581167 Mon Sep 17 00:00:00 2001 From: Shunsuke Shibayama Date: Sat, 3 Sep 2022 22:38:03 +0900 Subject: [PATCH 15/68] Fix a refinement type bug --- compiler/erg_type/lib.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/compiler/erg_type/lib.rs b/compiler/erg_type/lib.rs index c2c22267..cec856e7 100644 --- a/compiler/erg_type/lib.rs +++ b/compiler/erg_type/lib.rs @@ -1639,7 +1639,6 @@ impl Type { pub fn is_simple_class(&self) -> bool { match self { Self::FreeVar(fv) if fv.is_linked() => fv.crack().is_simple_class(), - Self::Refinement(refine) => refine.t.is_simple_class(), Self::Obj | Self::Int | Self::Nat From 174b37d60cb3eb9ff3c1173706f4495f0aef54a2 Mon Sep 17 00:00:00 2001 From: Shunsuke Shibayama Date: Sat, 3 Sep 2022 23:39:29 +0900 Subject: [PATCH 16/68] Impl Display for ConstSubr --- compiler/erg_parser/desugar.rs | 24 ++++++++++++------------ compiler/erg_type/lib.rs | 9 +++++++++ compiler/erg_type/value.rs | 2 +- examples/class.er | 4 ++-- 4 files changed, 24 insertions(+), 15 deletions(-) diff --git a/compiler/erg_parser/desugar.rs b/compiler/erg_parser/desugar.rs index e73c6f8a..8f1cf0e4 100644 --- a/compiler/erg_parser/desugar.rs +++ b/compiler/erg_parser/desugar.rs @@ -50,6 +50,7 @@ impl Desugarer { let module = self.desugar_multiple_pattern_def(module); let module = self.desugar_pattern(module); let module = self.desugar_shortened_record(module); + // let module = self.desugar_self(module); module } @@ -499,21 +500,20 @@ impl Desugarer { NormalRecord::new(rec.l_brace, rec.r_brace, attrs) } - /// `F(I | I > 0)` -> `F(I: {I: Int | I > 0})` - fn desugar_refinement_pattern(&self, _mod: Module) -> Module { + fn desugar_self(&self, mut module: Module) -> Module { + let mut new = Module::with_capacity(module.len()); + while let Some(chunk) = module.lpop() { + new.push(self.rec_desugar_self(chunk)); + } + new + } + + fn rec_desugar_self(&self, _expr: Expr) -> Expr { todo!() } - /// ```erg - /// @deco - /// f x = ... - /// ``` - /// ↓ - /// ```erg - /// _f x = ... - /// f = deco _f - /// ``` - fn desugar_decorators(&self, _mod: Module) -> Module { + /// `F(I | I > 0)` -> `F(I: {I: Int | I > 0})` + fn desugar_refinement_pattern(&self, _mod: Module) -> Module { todo!() } } diff --git a/compiler/erg_type/lib.rs b/compiler/erg_type/lib.rs index cec856e7..0be7ed5c 100644 --- a/compiler/erg_type/lib.rs +++ b/compiler/erg_type/lib.rs @@ -162,6 +162,15 @@ pub enum ConstSubr { Builtin(BuiltinConstSubr), } +impl fmt::Display for ConstSubr { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + ConstSubr::User(_) => write!(f, ""), + ConstSubr::Builtin(_) => write!(f, ""), + } + } +} + impl ConstSubr { pub fn call(&self, args: ValueArgs, __name__: Option) -> ValueObj { match self { diff --git a/compiler/erg_type/value.rs b/compiler/erg_type/value.rs index 9936fa9c..966ac8c4 100644 --- a/compiler/erg_type/value.rs +++ b/compiler/erg_type/value.rs @@ -92,7 +92,7 @@ impl fmt::Debug for ValueObj { } write!(f, "}}") } - Self::Subr(subr) => write!(f, "{subr:?}"), + Self::Subr(subr) => write!(f, "{subr}"), Self::Type(t) => write!(f, "{t}"), Self::None => write!(f, "None"), Self::Ellipsis => write!(f, "Ellipsis"), diff --git a/examples/class.er b/examples/class.er index babd2815..eed35b70 100644 --- a/examples/class.er +++ b/examples/class.er @@ -1,13 +1,13 @@ @Inheritable Point2D = Class {x = Int; y = Int} Point2D. - new x, y = Self::__new__ {x; y} + new x, y = Point2D::__new__ {x; y} norm ref self = self::x**2 + self::y**2 Point3D = Inherit Point2D, Additional := {z = Int} Point3D. @Override - new x, y, z = Self::__new__ {x; y; z} + new x, y, z = Point3D::__new__ {x; y; z} @Override norm ref self = self::x**2 + self::y**2 + self::z**2 From cf0858ddde9f022bacafd911b3ac7be18614e6ba Mon Sep 17 00:00:00 2001 From: Shunsuke Shibayama Date: Sun, 4 Sep 2022 00:46:15 +0900 Subject: [PATCH 17/68] Add TypeObj --- .../context/initialize/const_func.rs | 42 +++++++-- .../erg_compiler/context/initialize/mod.rs | 21 ++++- compiler/erg_compiler/context/instantiate.rs | 6 +- compiler/erg_compiler/eval.rs | 3 +- compiler/erg_type/value.rs | 87 ++++++++++++++++++- 5 files changed, 142 insertions(+), 17 deletions(-) diff --git a/compiler/erg_compiler/context/initialize/const_func.rs b/compiler/erg_compiler/context/initialize/const_func.rs index e21e1bb6..64463c38 100644 --- a/compiler/erg_compiler/context/initialize/const_func.rs +++ b/compiler/erg_compiler/context/initialize/const_func.rs @@ -1,19 +1,45 @@ use erg_common::Str; use erg_type::constructors::mono; -use erg_type::value::ValueObj; +use erg_type::value::{TypeKind, TypeObj, ValueObj}; +use erg_type::Type; use erg_type::ValueArgs; -/// Type -> Type -pub fn class_func(_args: ValueArgs, __name__: Option) -> ValueObj { - let t = mono(__name__.unwrap_or(Str::ever(""))); - ValueObj::t(t) +fn value_obj_to_t(value: ValueObj) -> TypeObj { + match value { + ValueObj::Type(t) => t, + ValueObj::Record(rec) => TypeObj::Builtin(Type::Record( + rec.into_iter() + .map(|(k, v)| (k, value_obj_to_t(v).typ().clone())) + .collect(), + )), + other => todo!("{other}"), + } } -/// Type -> Type -pub fn inherit_func(_args: ValueArgs, __name__: Option) -> ValueObj { +/// Requirement: Type, Impl := Type -> Type +pub fn class_func(mut args: ValueArgs, __name__: Option) -> ValueObj { + let require = args.pos_args.remove(0); + let require = value_obj_to_t(require); + let impls = args.pos_args.pop().or_else(|| args.kw_args.remove("Impl")); + let impls = impls.map(|v| value_obj_to_t(v)); let t = mono(__name__.unwrap_or(Str::ever(""))); - ValueObj::t(t) + ValueObj::gen_t(TypeKind::Class, t, require, impls, None) +} + +/// Super: Type, Impl := Type, Additional := Type -> Type +pub fn inherit_func(mut args: ValueArgs, __name__: Option) -> ValueObj { + let sup = args.pos_args.remove(0); + let sup = value_obj_to_t(sup); + let impls = args.pos_args.pop().or_else(|| args.kw_args.remove("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 = 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) } /// Type -> Type diff --git a/compiler/erg_compiler/context/initialize/mod.rs b/compiler/erg_compiler/context/initialize/mod.rs index 5688e598..6d0921d3 100644 --- a/compiler/erg_compiler/context/initialize/mod.rs +++ b/compiler/erg_compiler/context/initialize/mod.rs @@ -48,7 +48,7 @@ impl Context { } pub(crate) fn register_const(&mut self, name: &str, obj: ValueObj) { - if self.consts.get(name).is_some() { + if self.rec_get_const_obj(name).is_some() { panic!("already registered: {name}"); } else { // TODO: visibility (not always private) @@ -78,6 +78,8 @@ impl Context { fn register_mono_type(&mut self, t: Type, ctx: Self, muty: Mutability) { if self.mono_types.contains_key(&t.name()) { panic!("{} has already been registered", t.name()); + } else if self.rec_get_const_obj(&t.name()).is_some() { + panic!("{} has already been registered as const", t.name()); } else { let name = VarName::from_str(t.name()); self.locals @@ -97,6 +99,7 @@ impl Context { } } + // FIXME: MethodDefsと再代入は違う fn register_poly_type(&mut self, t: Type, ctx: Self, muty: Mutability) { let mut tv_ctx = TyVarContext::new(self.level, ctx.type_params_bounds(), self); let t = Self::instantiate_t(t, &mut tv_ctx); @@ -1061,9 +1064,21 @@ impl Context { } fn init_builtin_const_funcs(&mut self) { - let class = ConstSubr::Builtin(BuiltinConstSubr::new(class_func, func1(Type, Type))); + let class_t = func( + vec![param_t("Requirement", Type)], + None, + vec![param_t("Impl", Type)], + Type, + ); + let class = ConstSubr::Builtin(BuiltinConstSubr::new(class_func, class_t)); self.register_const("Class", ValueObj::Subr(class)); - let inherit = ConstSubr::Builtin(BuiltinConstSubr::new(inherit_func, func1(Type, Type))); + let inherit_t = func( + vec![param_t("Super", Type)], + None, + vec![param_t("Impl", Type), param_t("Additional", Type)], + Type, + ); + let inherit = ConstSubr::Builtin(BuiltinConstSubr::new(inherit_func, inherit_t)); self.register_const("Inherit", ValueObj::Subr(inherit)); // decorators let inheritable = diff --git a/compiler/erg_compiler/context/instantiate.rs b/compiler/erg_compiler/context/instantiate.rs index 9fd9cb8f..b4d07472 100644 --- a/compiler/erg_compiler/context/instantiate.rs +++ b/compiler/erg_compiler/context/instantiate.rs @@ -78,8 +78,8 @@ impl TyVarContext { ) -> TyParam { match ct { ConstTemplate::Obj(o) => match o { - ValueObj::Type(t) if t.is_mono_q() => { - if &t.name()[..] == "Self" { + ValueObj::Type(t) if t.typ().is_mono_q() => { + if &t.typ().name()[..] == "Self" { let constraint = Constraint::type_of(Type); let t = named_free_var(Str::rc(var_name), self.level, constraint); TyParam::t(t) @@ -87,7 +87,7 @@ impl TyVarContext { todo!() } } - ValueObj::Type(t) => TyParam::t(*t.clone()), + ValueObj::Type(t) => TyParam::t(t.typ().clone()), v => TyParam::Value(v.clone()), }, ConstTemplate::App { .. } => { diff --git a/compiler/erg_compiler/eval.rs b/compiler/erg_compiler/eval.rs index 3d122259..fe1494d0 100644 --- a/compiler/erg_compiler/eval.rs +++ b/compiler/erg_compiler/eval.rs @@ -541,7 +541,8 @@ impl Context { if let Ok(obj) = ty_ctx.get_const_local(&Token::symbol(&rhs), &self.name) { if let ValueObj::Type(quant_t) = obj { let subst_ctx = SubstContext::new(&lhs, ty_ctx); - let t = subst_ctx.substitute(*quant_t, ty_ctx, level, self)?; + let t = + subst_ctx.substitute(quant_t.typ().clone(), ty_ctx, level, self)?; let t = self.eval_t_params(t, level)?; return Ok(t); } else { diff --git a/compiler/erg_type/value.rs b/compiler/erg_type/value.rs index 966ac8c4..ac0b037b 100644 --- a/compiler/erg_type/value.rs +++ b/compiler/erg_type/value.rs @@ -22,6 +22,73 @@ use crate::free::fresh_varname; use crate::typaram::TyParam; use crate::{ConstSubr, HasType, Predicate, Type}; +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] +pub enum TypeKind { + Class, + InheritedClass, + Trait, + SubsumedTrait, + StructuralTrait, +} + +/// Class +#[derive(Clone, Debug, PartialEq, Eq, Hash)] +pub struct GenTypeObj { + pub kind: TypeKind, + pub t: Type, + pub require_or_sup: Box, + pub impls: Option>, + pub additional: Option>, +} + +impl fmt::Display for GenTypeObj { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "<{:?} {}>", self.kind, self.t) + } +} + +impl GenTypeObj { + pub fn new( + kind: TypeKind, + t: Type, + require_or_sup: TypeObj, + impls: Option, + additional: Option, + ) -> Self { + Self { + kind, + t, + require_or_sup: Box::new(require_or_sup), + impls: impls.map(Box::new), + additional: additional.map(Box::new), + } + } +} + +#[derive(Clone, Debug, PartialEq, Eq, Hash)] +pub enum TypeObj { + Builtin(Type), + Gen(GenTypeObj), +} + +impl fmt::Display for TypeObj { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + TypeObj::Builtin(t) => write!(f, "{t}"), + TypeObj::Gen(t) => write!(f, "{t}"), + } + } +} + +impl TypeObj { + pub const fn typ(&self) -> &Type { + match self { + TypeObj::Builtin(t) => t, + TypeObj::Gen(t) => &t.t, + } + } +} + /// 値オブジェクト /// コンパイル時評価ができ、シリアライズも可能 #[derive(Clone, PartialEq, Default)] @@ -37,7 +104,7 @@ pub enum ValueObj { Record(Dict), Code(Box), Subr(ConstSubr), - Type(Box), + Type(TypeObj), None, Ellipsis, NotImplemented, @@ -263,7 +330,23 @@ impl HasType for ValueObj { impl ValueObj { pub fn t(t: Type) -> Self { - ValueObj::Type(Box::new(t)) + ValueObj::Type(TypeObj::Builtin(t)) + } + + pub fn gen_t( + kind: TypeKind, + t: Type, + require_or_sup: TypeObj, + impls: Option, + additional: Option, + ) -> Self { + ValueObj::Type(TypeObj::Gen(GenTypeObj::new( + kind, + t, + require_or_sup, + impls, + additional, + ))) } pub fn is_num(&self) -> bool { From e860da2a15a3f1b0a4b074a0057cf9aaa08a835a Mon Sep 17 00:00:00 2001 From: Shunsuke Shibayama Date: Mon, 5 Sep 2022 01:13:14 +0900 Subject: [PATCH 18/68] WIP: impl type checker --- compiler/erg_compiler/context/compare.rs | 17 ++- .../erg_compiler/context/initialize/mod.rs | 55 ++++++++- compiler/erg_compiler/context/inquire.rs | 34 +++++ compiler/erg_compiler/context/mod.rs | 10 ++ compiler/erg_compiler/context/register.rs | 116 ++++++++++++++++-- compiler/erg_compiler/context/tyvar.rs | 17 +++ compiler/erg_parser/ast.rs | 18 ++- compiler/erg_type/free.rs | 29 ++++- compiler/erg_type/value.rs | 4 + 9 files changed, 274 insertions(+), 26 deletions(-) diff --git a/compiler/erg_compiler/context/compare.rs b/compiler/erg_compiler/context/compare.rs index 8f3b85ac..9546777b 100644 --- a/compiler/erg_compiler/context/compare.rs +++ b/compiler/erg_compiler/context/compare.rs @@ -399,8 +399,6 @@ impl Context { && kw_check() // contravariant } - // RefMut, OptionMut are invariant - (Ref(lhs), Ref(rhs)) => self.supertype_of(lhs, rhs), // ?T(<: Nat) !:> ?U(:> Int) // ?T(<: Nat) :> ?U(<: Int) (?U can be smaller than ?T) (FreeVar(lfv), FreeVar(rfv)) => { @@ -490,7 +488,18 @@ impl Context { } true } - // (MonoQuantVar(_), _) | (_, MonoQuantVar(_)) => true, + (Type::Record(lhs), Type::Record(rhs)) => { + for (k, l) in lhs.iter() { + if let Some(r) = rhs.get(k) { + if !self.supertype_of(l, r) { + return false; + } + } else { + return false; + } + } + true + } // REVIEW: maybe this is incomplete // ({I: Int | I >= 0} :> {N: Int | N >= 0}) == true, // ({I: Int | I >= 0} :> {I: Int | I >= 1}) == true, @@ -565,6 +574,8 @@ impl Context { } (_lhs, Not(_, _)) => todo!(), (Not(_, _), _rhs) => todo!(), + // RefMut, OptionMut are invariant + (Ref(lhs), Ref(rhs)) => self.supertype_of(lhs, rhs), // TはすべてのRef(T)のメソッドを持つので、Ref(T)のサブタイプ // REVIEW: RefMut is invariant, maybe (Ref(lhs), rhs) | (RefMut(lhs), rhs) => self.supertype_of(lhs, rhs), diff --git a/compiler/erg_compiler/context/initialize/mod.rs b/compiler/erg_compiler/context/initialize/mod.rs index 6d0921d3..69f794a7 100644 --- a/compiler/erg_compiler/context/initialize/mod.rs +++ b/compiler/erg_compiler/context/initialize/mod.rs @@ -9,7 +9,7 @@ use erg_common::vis::Visibility; use erg_common::Str; use erg_type::typaram::TyParam; -use erg_type::value::ValueObj; +use erg_type::value::{TypeKind, TypeObj, ValueObj}; use erg_type::Type; use erg_type::{constructors::*, BuiltinConstSubr, ConstSubr}; use ParamSpec as PS; @@ -51,11 +51,54 @@ impl Context { if self.rec_get_const_obj(name).is_some() { panic!("already registered: {name}"); } else { - // TODO: visibility (not always private) - // TODO: kind (not always Builtin) - 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); + match obj { + /*ValueObj::Type(TypeObj::Builtin(_builtin)) => { + todo!() + }*/ + ValueObj::Type(TypeObj::Gen(gen)) => match gen.kind { + TypeKind::Class => { + if gen.t.is_monomorphic() { + let super_traits = + gen.impls.into_iter().map(|to| to.typ().clone()).collect(); + let mut ctx = + Self::mono_class(gen.t.name(), vec![], super_traits, self.level); + let require = gen.require_or_sup.typ().clone(); + let new_t = func1(require, gen.t.clone()); + ctx.register_impl("__new__", new_t, Immutable, Private); + self.register_mono_type(gen.t, ctx, Const); + } else { + todo!() + } + } + TypeKind::InheritedClass => { + if gen.t.is_monomorphic() { + let super_classes = vec![gen.require_or_sup.typ().clone()]; + let super_traits = + gen.impls.into_iter().map(|to| to.typ().clone()).collect(); + let mut ctx = Self::mono_class( + gen.t.name(), + super_classes, + super_traits, + self.level, + ); + let sup = gen.require_or_sup.typ().clone(); + let new_t = func1(sup, gen.t.clone()); + ctx.register_impl("__new__", new_t, Immutable, Private); + self.register_mono_type(gen.t, ctx, Const); + } else { + todo!() + } + } + other => todo!("{other:?}"), + }, + other => { + // TODO: visibility (not always private) + // TODO: kind (not always Builtin) + let vi = VarInfo::new(enum_t(set! {other.clone()}), Const, Private, Builtin); + self.consts.insert(VarName::from_str(Str::rc(name)), other); + self.locals.insert(VarName::from_str(Str::rc(name)), vi); + } + } } } diff --git a/compiler/erg_compiler/context/inquire.rs b/compiler/erg_compiler/context/inquire.rs index 605a839a..9d8bcf0b 100644 --- a/compiler/erg_compiler/context/inquire.rs +++ b/compiler/erg_compiler/context/inquire.rs @@ -1020,6 +1020,13 @@ impl Context { typ: &Type, ) -> Option<(&'a Type, &'a Context)> { match typ { + Type::FreeVar(fv) if fv.is_linked() => { + return self.rec_get_nominal_type_ctx(&fv.crack()); + } + Type::FreeVar(fv) => { + let sup = fv.crack_sup()?; + return self.rec_get_nominal_type_ctx(&sup); + } Type::Refinement(refine) => { return self.rec_get_nominal_type_ctx(&refine.t); } @@ -1040,6 +1047,7 @@ impl Context { return Some((t, ctx)); } } + Type::Ref(t) | Type::RefMut(t) => return self.rec_get_nominal_type_ctx(t), other => todo!("{other}"), } if let Some(outer) = &self.outer { @@ -1053,8 +1061,14 @@ impl Context { match obj.ref_t() { // TODO: attr Type::Module => self.rec_get_mod(&obj.var_full_name()?), + Type::Type => self + .rec_get_nominal_type_ctx(&Type::Mono(Str::from(obj.var_full_name().unwrap()))) + .map(|(_, ctx)| ctx), Type::Class => todo!(), Type::Trait => todo!(), + Type::Refinement(refine) => { + self.rec_get_nominal_type_ctx(&refine.t).map(|(_, ctx)| ctx) + } _ => None, } } @@ -1113,4 +1127,24 @@ impl Context { None } } + + pub(crate) fn get_self_t(&self) -> Type { + if self.kind.is_method_def() || self.kind.is_type() { + // TODO: poly type + let name = self.name.split("::").last().unwrap(); + let name = name.split(".").last().unwrap(); + let mono_t = mono(Str::rc(name)); + if let Some((t, _)) = self.rec_get_nominal_type_ctx(&mono_t) { + t.clone() + } else { + todo!("{mono_t}") + } + } else { + if let Some(outer) = &self.outer { + outer.get_self_t() + } else { + todo!() + } + } + } } diff --git a/compiler/erg_compiler/context/mod.rs b/compiler/erg_compiler/context/mod.rs index c417312e..aa42b301 100644 --- a/compiler/erg_compiler/context/mod.rs +++ b/compiler/erg_compiler/context/mod.rs @@ -203,6 +203,16 @@ pub enum ContextKind { Dummy, } +impl ContextKind { + pub const fn is_method_def(&self) -> bool { + matches!(self, Self::MethodDefs) + } + + pub const fn is_type(&self) -> bool { + matches!(self, Self::Class | Self::Trait | Self::StructuralTrait) + } +} + /// 記号表に登録されているモードを表す /// Preregister: サブルーチンまたは定数式、前方参照できる /// Normal: 前方参照できない diff --git a/compiler/erg_compiler/context/register.rs b/compiler/erg_compiler/context/register.rs index 03e969c7..881d2179 100644 --- a/compiler/erg_compiler/context/register.rs +++ b/compiler/erg_compiler/context/register.rs @@ -9,7 +9,7 @@ use erg_type::free::HasLevel; use ast::{DefId, VarName}; use erg_parser::ast; -use erg_type::constructors::{enum_t, func, proc}; +use erg_type::constructors::{enum_t, func, proc, ref_, ref_mut}; use erg_type::value::ValueObj; use erg_type::{HasType, ParamTy, SubrType, TyBound, Type}; use Type::*; @@ -161,18 +161,29 @@ impl Context { opt_decl_t: Option<&ParamTy>, ) -> TyCheckResult<()> { match &sig.pat { + ast::ParamPattern::Lit(_) => Ok(()), ast::ParamPattern::Discard(_token) => Ok(()), - ast::ParamPattern::VarName(v) => { - if self.registered(v.inspect(), v.inspect().is_uppercase()) { + ast::ParamPattern::VarName(name) => { + if self.registered(name.inspect(), name.is_const()) { Err(TyCheckError::reassign_error( line!() as usize, - v.loc(), + name.loc(), self.caused_by(), - v.inspect(), + name.inspect(), )) } else { // ok, not defined let spec_t = self.instantiate_param_sig_t(sig, opt_decl_t, Normal)?; + if &name.inspect()[..] == "self" { + let self_t = self.get_self_t(); + self.sub_unify( + &spec_t, + &self_t, + Some(name.loc()), + None, + Some(name.inspect()), + )?; + } let idx = if let Some(outer) = outer { ParamIdx::nested(outer, nth) } else { @@ -183,16 +194,101 @@ impl Context { } else { DefaultInfo::NonDefault }; - let kind = VarKind::parameter(DefId(get_hash(&(&self.name, v))), idx, default); + let kind = + VarKind::parameter(DefId(get_hash(&(&self.name, name))), idx, default); self.params.push(( - Some(v.clone()), + Some(name.clone()), VarInfo::new(spec_t, Immutable, Private, kind), )); Ok(()) } } - ast::ParamPattern::Lit(_) => Ok(()), - _ => unreachable!(), + ast::ParamPattern::Ref(name) => { + if self.registered(name.inspect(), name.is_const()) { + Err(TyCheckError::reassign_error( + line!() as usize, + name.loc(), + self.caused_by(), + name.inspect(), + )) + } else { + // ok, not defined + let spec_t = self.instantiate_param_sig_t(sig, opt_decl_t, Normal)?; + if &name.inspect()[..] == "self" { + let self_t = self.get_self_t(); + self.sub_unify( + &spec_t, + &self_t, + Some(name.loc()), + None, + Some(name.inspect()), + )?; + } + let spec_t = ref_(spec_t); + let idx = if let Some(outer) = outer { + ParamIdx::nested(outer, nth) + } else { + ParamIdx::Nth(nth) + }; + let default = if sig.opt_default_val.is_some() { + DefaultInfo::WithDefault + } else { + DefaultInfo::NonDefault + }; + let kind = + VarKind::parameter(DefId(get_hash(&(&self.name, name))), idx, default); + self.params.push(( + Some(name.clone()), + VarInfo::new(spec_t, Immutable, Private, kind), + )); + Ok(()) + } + } + ast::ParamPattern::RefMut(name) => { + if self.registered(name.inspect(), name.is_const()) { + Err(TyCheckError::reassign_error( + line!() as usize, + name.loc(), + self.caused_by(), + name.inspect(), + )) + } else { + // ok, not defined + let spec_t = self.instantiate_param_sig_t(sig, opt_decl_t, Normal)?; + if &name.inspect()[..] == "self" { + let self_t = self.get_self_t(); + self.sub_unify( + &spec_t, + &self_t, + Some(name.loc()), + None, + Some(name.inspect()), + )?; + } + let spec_t = ref_mut(spec_t); + let idx = if let Some(outer) = outer { + ParamIdx::nested(outer, nth) + } else { + ParamIdx::Nth(nth) + }; + let default = if sig.opt_default_val.is_some() { + DefaultInfo::WithDefault + } else { + DefaultInfo::NonDefault + }; + let kind = + VarKind::parameter(DefId(get_hash(&(&self.name, name))), idx, default); + self.params.push(( + Some(name.clone()), + VarInfo::new(spec_t, Immutable, Private, kind), + )); + Ok(()) + } + } + other => { + log!(err "{other}"); + unreachable!() + } } } @@ -272,7 +368,7 @@ impl Context { ) })?; } - if self.registered(name.inspect(), name.inspect().is_uppercase()) { + if self.registered(name.inspect(), name.is_const()) { Err(TyCheckError::reassign_error( line!() as usize, name.loc(), diff --git a/compiler/erg_compiler/context/tyvar.rs b/compiler/erg_compiler/context/tyvar.rs index 9cea5f59..1c12f78a 100644 --- a/compiler/erg_compiler/context/tyvar.rs +++ b/compiler/erg_compiler/context/tyvar.rs @@ -1111,6 +1111,23 @@ impl Context { return Ok(()); } (Type::FreeVar(_fv), _r) => todo!(), + (Type::Record(lrec), Type::Record(rrec)) => { + for (k, l) in lrec.iter() { + if let Some(r) = rrec.get(k) { + self.sub_unify(l, r, sub_loc, sup_loc, param_name)?; + } else { + return Err(TyCheckError::subtyping_error( + line!() as usize, + maybe_sub, + maybe_sup, + sub_loc, + sup_loc, + self.caused_by(), + )); + } + } + return Ok(()); + } (Type::Subr(lsub), Type::Subr(rsub)) => { for lpt in lsub.default_params.iter() { if let Some(rpt) = rsub.default_params.iter().find(|rpt| rpt.name() == lpt.name()) { diff --git a/compiler/erg_parser/ast.rs b/compiler/erg_parser/ast.rs index 06104050..d4a9a4bd 100644 --- a/compiler/erg_parser/ast.rs +++ b/compiler/erg_parser/ast.rs @@ -2291,7 +2291,23 @@ pub enum ParamPattern { VarArgs(VarName), } -impl_display_for_enum!(ParamPattern; Discard, VarName, Lit, Array, Tuple, Record, Ref, RefMut, VarArgs); +impl NestedDisplay for ParamPattern { + fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, _level: usize) -> fmt::Result { + match self { + Self::Discard(tok) => write!(f, "{}", tok), + Self::VarName(var_name) => write!(f, "{}", var_name), + Self::Lit(lit) => write!(f, "{}", lit), + Self::Array(array) => write!(f, "{}", array), + Self::Tuple(tuple) => write!(f, "{}", tuple), + Self::Record(record) => write!(f, "{}", record), + Self::Ref(var_name) => write!(f, "ref {}", var_name), + Self::RefMut(var_name) => write!(f, "ref! {}", var_name), + Self::VarArgs(var_name) => write!(f, "...{}", var_name), + } + } +} + +impl_display_from_nested!(ParamPattern); impl_locational_for_enum!(ParamPattern; Discard, VarName, Lit, Array, Tuple, Record, Ref, RefMut, VarArgs); impl ParamPattern { diff --git a/compiler/erg_type/free.rs b/compiler/erg_type/free.rs index 267f376f..be3a1bd9 100644 --- a/compiler/erg_type/free.rs +++ b/compiler/erg_type/free.rs @@ -111,19 +111,28 @@ impl LimitedDisplay for Constraint { (true, false) => { write!(f, "<: ")?; sup.limited_fmt(f, limit - 1)?; - write!(f, "(cyclicity: {cyclicity:?})") + if cfg!(feature = "debug") { + write!(f, "(cyclicity: {cyclicity:?})")?; + } + Ok(()) } (false, true) => { write!(f, ":> ")?; sub.limited_fmt(f, limit - 1)?; - write!(f, "(cyclicity: {cyclicity:?})") + if cfg!(feature = "debug") { + write!(f, "(cyclicity: {cyclicity:?})")?; + } + Ok(()) } (false, false) => { write!(f, ":> ")?; sub.limited_fmt(f, limit - 1)?; write!(f, ", <: ")?; sup.limited_fmt(f, limit - 1)?; - write!(f, "(cyclicity: {cyclicity:?})") + if cfg!(feature = "debug") { + write!(f, "(cyclicity: {cyclicity:?})")?; + } + Ok(()) } }, Self::TypeOf(t) => { @@ -258,7 +267,11 @@ impl LimitedDisplay for FreeKind { } => { write!(f, "?{name}(")?; constraint.limited_fmt(f, limit - 1)?; - write!(f, ")[{lev}]") + write!(f, ")")?; + if cfg!(feature = "debug") { + write!(f, "[{lev}]")?; + } + Ok(()) } Self::Unbound { id, @@ -267,7 +280,11 @@ impl LimitedDisplay for FreeKind { } => { write!(f, "?{id}(")?; constraint.limited_fmt(f, limit - 1)?; - write!(f, ")[{lev}]") + write!(f, ")")?; + if cfg!(feature = "debug") { + write!(f, "[{lev}]")?; + } + Ok(()) } } } @@ -501,7 +518,7 @@ impl Free { .and_then(|c| c.get_type().cloned()) } - pub fn crack_subtype(&self) -> Option { + pub fn crack_sup(&self) -> Option { self.borrow() .constraint() .and_then(|c| c.get_super_type().cloned()) diff --git a/compiler/erg_type/value.rs b/compiler/erg_type/value.rs index ac0b037b..9bfd0686 100644 --- a/compiler/erg_type/value.rs +++ b/compiler/erg_type/value.rs @@ -357,6 +357,10 @@ impl ValueObj { } } + pub const fn is_type(&self) -> bool { + matches!(self, Self::Type(_)) + } + pub const fn is_mut(&self) -> bool { matches!(self, Self::Mut(_)) } From 2320ff0360618594d73fe3c926ebf48b82aedb1e Mon Sep 17 00:00:00 2001 From: Shunsuke Shibayama Date: Mon, 5 Sep 2022 10:11:03 +0900 Subject: [PATCH 19/68] Refactor --- compiler/erg_compiler/context/inquire.rs | 2 +- compiler/erg_compiler/context/instantiate.rs | 13 +++---- compiler/erg_compiler/context/tyvar.rs | 26 +++++++------- compiler/erg_compiler/lower.rs | 2 +- compiler/erg_type/free.rs | 37 ++++++++++---------- compiler/erg_type/typaram.rs | 4 +-- 6 files changed, 42 insertions(+), 42 deletions(-) diff --git a/compiler/erg_compiler/context/inquire.rs b/compiler/erg_compiler/context/inquire.rs index 9d8bcf0b..27859287 100644 --- a/compiler/erg_compiler/context/inquire.rs +++ b/compiler/erg_compiler/context/inquire.rs @@ -435,7 +435,7 @@ impl Context { } ); let (new_sub, new_sup) = (self.resolve_trait(sub)?, self.resolve_trait(sup)?); - let new_constraint = Constraint::sandwiched(new_sub, new_sup, cyclic); + let new_constraint = Constraint::new_sandwiched(new_sub, new_sup, cyclic); fv.update_constraint(new_constraint); Ok(Type::FreeVar(fv)) } diff --git a/compiler/erg_compiler/context/instantiate.rs b/compiler/erg_compiler/context/instantiate.rs index b4d07472..130d5c87 100644 --- a/compiler/erg_compiler/context/instantiate.rs +++ b/compiler/erg_compiler/context/instantiate.rs @@ -80,7 +80,7 @@ impl TyVarContext { ConstTemplate::Obj(o) => match o { ValueObj::Type(t) if t.typ().is_mono_q() => { if &t.typ().name()[..] == "Self" { - let constraint = Constraint::type_of(Type); + let constraint = Constraint::new_type_of(Type); let t = named_free_var(Str::rc(var_name), self.level, constraint); TyParam::t(t) } else { @@ -168,7 +168,8 @@ impl TyVarContext { sup => sup, }; let name = mid.name(); - let constraint = Constraint::sandwiched(sub_instance, sup_instance, Cyclicity::Not); + let constraint = + Constraint::new_sandwiched(sub_instance, sup_instance, Cyclicity::Not); self.push_or_init_tyvar( &name, &named_free_var(name.clone(), self.level, constraint), @@ -181,7 +182,7 @@ impl TyVarContext { } t => t, }; - let constraint = Constraint::type_of(t.clone()); + let constraint = Constraint::new_type_of(t.clone()); // TODO: type-like types if t == Type { if let Some(tv) = self.tyvar_instances.get(&name) { @@ -374,7 +375,7 @@ impl Context { let spec_t = if let Some(s) = t_spec { self.instantiate_typespec(s, mode)? } else { - free_var(self.level, Constraint::type_of(Type)) + free_var(self.level, Constraint::new_type_of(Type)) }; if let Some(eval_t) = opt_eval_t { self.sub_unify(&eval_t, &spec_t, None, t_spec.map(|s| s.loc()), None)?; @@ -425,7 +426,7 @@ impl Context { } else { self.level + 1 }; - free_var(level, Constraint::type_of(Type)) + free_var(level, Constraint::new_type_of(Type)) }; if let Some(eval_ret_t) = eval_ret_t { self.sub_unify( @@ -462,7 +463,7 @@ impl Context { } else { self.level + 1 }; - free_var(level, Constraint::type_of(Type)) + free_var(level, Constraint::new_type_of(Type)) } } }; diff --git a/compiler/erg_compiler/context/tyvar.rs b/compiler/erg_compiler/context/tyvar.rs index 1c12f78a..5c213023 100644 --- a/compiler/erg_compiler/context/tyvar.rs +++ b/compiler/erg_compiler/context/tyvar.rs @@ -239,13 +239,13 @@ impl Context { if cyclic.is_cyclic() { return Err(TyCheckError::dummy_infer_error(fn_name!(), line!())); } - Ok(Constraint::sandwiched( + Ok(Constraint::new_sandwiched( self.deref_tyvar(sub)?, self.deref_tyvar(sup)?, cyclic, )) } - Constraint::TypeOf(t) => Ok(Constraint::type_of(self.deref_tyvar(t)?)), + Constraint::TypeOf(t) => Ok(Constraint::new_type_of(self.deref_tyvar(t)?)), _ => unreachable!(), } } @@ -262,7 +262,7 @@ impl Context { // ?T(:> Never, <: Nat)[n] => Nat Type::FreeVar(fv) if fv.constraint_is_sandwiched() => { let constraint = fv.crack_constraint(); - let (sub_t, super_t) = constraint.get_sub_sup_type().unwrap(); + let (sub_t, super_t) = constraint.get_sub_sup().unwrap(); if self.rec_same_type_of(sub_t, super_t) { self.unify(sub_t, super_t, None, None)?; let t = if sub_t == &Never { @@ -541,7 +541,7 @@ impl Context { if self.rec_supertype_of(&fv_t, &tp_t) { // 外部未連携型変数の場合、linkしないで制約を弱めるだけにする(see compiler/inference.md) if fv.level() < Some(self.level) { - let new_constraint = Constraint::subtype_of(tp_t, Cyclicity::Not); + let new_constraint = Constraint::new_subtype_of(tp_t, Cyclicity::Not); if self.is_sub_constraint_of( fv.borrow().constraint().unwrap(), &new_constraint, @@ -743,7 +743,7 @@ impl Context { } => { t.update_level(*lev); // TODO: constraint.type_of() - if let Some(sup) = constraint.get_super_type_mut() { + if let Some(sup) = constraint.get_super_mut() { // 下のような場合は制約を弱化する // unify(?T(<: Nat), Int): (?T(<: Int)) if self.rec_subtype_of(sup, t) { @@ -754,7 +754,7 @@ impl Context { } } } // &fv is dropped - let new_constraint = Constraint::subtype_of(t.clone(), fv.cyclicity()); + let new_constraint = Constraint::new_subtype_of(t.clone(), fv.cyclicity()); // 外部未連携型変数の場合、linkしないで制約を弱めるだけにする(see compiler/inference.md) // fv == ?T(: Type)の場合は?T(<: U)にする if fv.level() < Some(self.level) { @@ -992,7 +992,7 @@ impl Context { let r_cyc = rfv.cyclicity(); let cyclicity = l_cyc.combine(r_cyc); let new_constraint = if let Some(min) = self.min(&lsup, &rsup) { - Constraint::sandwiched(self.rec_union(&lsub, &rsub), min.clone(), cyclicity) + Constraint::new_sandwiched(self.rec_union(&lsub, &rsub), min.clone(), cyclicity) } else { todo!() }; @@ -1041,16 +1041,16 @@ impl Context { } if let Some(new_sub) = self.rec_max(maybe_sub, sub) { *constraint = - Constraint::sandwiched(new_sub.clone(), mem::take(sup), *cyclicity); + Constraint::new_sandwiched(new_sub.clone(), mem::take(sup), *cyclicity); } else { let new_sub = self.rec_union(maybe_sub, sub); - *constraint = Constraint::sandwiched(new_sub, mem::take(sup), *cyclicity); + *constraint = Constraint::new_sandwiched(new_sub, mem::take(sup), *cyclicity); } } // sub_unify(Nat, ?T(: Type)): (/* ?T(:> Nat) */) Constraint::TypeOf(ty) => { if self.rec_supertype_of(&Type, ty) { - *constraint = Constraint::supertype_of(maybe_sub.clone(), Cyclicity::Not); + *constraint = Constraint::new_supertype_of(maybe_sub.clone(), Cyclicity::Not); } else { todo!() } @@ -1090,16 +1090,16 @@ impl Context { } if let Some(new_sup) = self.rec_min(sup, maybe_sup) { *constraint = - Constraint::sandwiched(mem::take(sub), new_sup.clone(), *cyclicity); + Constraint::new_sandwiched(mem::take(sub), new_sup.clone(), *cyclicity); } else { let new_sup = self.rec_union(sup, maybe_sup); - *constraint = Constraint::sandwiched(mem::take(sub), new_sup, *cyclicity); + *constraint = Constraint::new_sandwiched(mem::take(sub), new_sup, *cyclicity); } } // sub_unify(?T(: Type), Int): (?T(<: Int)) Constraint::TypeOf(ty) => { if self.rec_supertype_of(&Type, ty) { - *constraint = Constraint::subtype_of(maybe_sup.clone(), Cyclicity::Not); + *constraint = Constraint::new_subtype_of(maybe_sup.clone(), Cyclicity::Not); } else { todo!() } diff --git a/compiler/erg_compiler/lower.rs b/compiler/erg_compiler/lower.rs index 54447516..44c62551 100644 --- a/compiler/erg_compiler/lower.rs +++ b/compiler/erg_compiler/lower.rs @@ -138,7 +138,7 @@ impl ASTLowerer { new_array.push(elem); } let elem_t = if union == Type::Never { - free_var(self.ctx.level, Constraint::type_of(Type::Type)) + free_var(self.ctx.level, Constraint::new_type_of(Type::Type)) } else { union }; diff --git a/compiler/erg_type/free.rs b/compiler/erg_type/free.rs index be3a1bd9..1ce5703e 100644 --- a/compiler/erg_type/free.rs +++ b/compiler/erg_type/free.rs @@ -145,7 +145,7 @@ impl LimitedDisplay for Constraint { } impl Constraint { - pub const fn sandwiched(sub: Type, sup: Type, cyclicity: Cyclicity) -> Self { + pub const fn new_sandwiched(sub: Type, sup: Type, cyclicity: Cyclicity) -> Self { Self::Sandwiched { sub, sup, @@ -153,20 +153,20 @@ impl Constraint { } } - pub fn type_of(t: Type) -> Self { + pub fn new_type_of(t: Type) -> Self { if t == Type::Type { - Self::sandwiched(Type::Never, Type::Obj, Not) + Self::new_sandwiched(Type::Never, Type::Obj, Not) } else { Self::TypeOf(t) } } - pub const fn subtype_of(sup: Type, cyclicity: Cyclicity) -> Self { - Self::sandwiched(Type::Never, sup, cyclicity) + pub const fn new_subtype_of(sup: Type, cyclicity: Cyclicity) -> Self { + Self::new_sandwiched(Type::Never, sup, cyclicity) } - pub const fn supertype_of(sub: Type, cyclicity: Cyclicity) -> Self { - Self::sandwiched(sub, Type::Obj, cyclicity) + pub const fn new_supertype_of(sub: Type, cyclicity: Cyclicity) -> Self { + Self::new_sandwiched(sub, Type::Obj, cyclicity) } pub const fn is_uninited(&self) -> bool { @@ -192,28 +192,28 @@ impl Constraint { } } - pub fn get_sub_type(&self) -> Option<&Type> { + pub fn get_sub(&self) -> Option<&Type> { match self { Self::Sandwiched { sub, .. } => Some(sub), _ => None, } } - pub fn get_super_type(&self) -> Option<&Type> { + pub fn get_super(&self) -> Option<&Type> { match self { Self::Sandwiched { sup, .. } => Some(sup), _ => None, } } - pub fn get_sub_sup_type(&self) -> Option<(&Type, &Type)> { + pub fn get_sub_sup(&self) -> Option<(&Type, &Type)> { match self { Self::Sandwiched { sub, sup, .. } => Some((sub, sup)), _ => None, } } - pub fn get_super_type_mut(&mut self) -> Option<&mut Type> { + pub fn get_super_mut(&mut self) -> Option<&mut Type> { match self { Self::Sandwiched { sup, .. } => Some(sup), _ => None, @@ -521,14 +521,13 @@ impl Free { pub fn crack_sup(&self) -> Option { self.borrow() .constraint() - .and_then(|c| c.get_super_type().cloned()) + .and_then(|c| c.get_super().cloned()) } pub fn crack_bound_types(&self) -> Option<(Type, Type)> { - self.borrow().constraint().and_then(|c| { - c.get_sub_sup_type() - .map(|(sub, sup)| (sub.clone(), sup.clone())) - }) + self.borrow() + .constraint() + .and_then(|c| c.get_sub_sup().map(|(sub, sup)| (sub.clone(), sup.clone()))) } pub fn is_unbound(&self) -> bool { @@ -559,7 +558,7 @@ impl Free { matches!( &*self.borrow(), FreeKind::Unbound { constraint, .. } - | FreeKind::NamedUnbound { constraint, .. } if constraint.get_sub_type().is_some() + | FreeKind::NamedUnbound { constraint, .. } if constraint.get_sub().is_some() ) } @@ -567,7 +566,7 @@ impl Free { matches!( &*self.borrow(), FreeKind::Unbound { constraint, .. } - | FreeKind::NamedUnbound { constraint, .. } if constraint.get_super_type().is_some() + | FreeKind::NamedUnbound { constraint, .. } if constraint.get_super().is_some() ) } @@ -575,7 +574,7 @@ impl Free { matches!( &*self.borrow(), FreeKind::Unbound { constraint, .. } - | FreeKind::NamedUnbound { constraint, .. } if constraint.get_sub_sup_type().is_some() + | FreeKind::NamedUnbound { constraint, .. } if constraint.get_sub_sup().is_some() ) } diff --git a/compiler/erg_type/typaram.rs b/compiler/erg_type/typaram.rs index f84ef708..a4a037e2 100644 --- a/compiler/erg_type/typaram.rs +++ b/compiler/erg_type/typaram.rs @@ -448,12 +448,12 @@ impl TyParam { } pub fn free_var(level: usize, t: Type) -> Self { - let constraint = Constraint::type_of(t); + let constraint = Constraint::new_type_of(t); Self::FreeVar(FreeTyParam::new_unbound(level, constraint)) } pub fn named_free_var(name: Str, level: usize, t: Type) -> Self { - let constraint = Constraint::type_of(t); + let constraint = Constraint::new_type_of(t); Self::FreeVar(FreeTyParam::new_named_unbound(name, level, constraint)) } From 25094efd17e7b398e23caa8a2023372082eeeb7f Mon Sep 17 00:00:00 2001 From: Shunsuke Shibayama Date: Mon, 5 Sep 2022 11:09:51 +0900 Subject: [PATCH 20/68] Refactor --- compiler/erg_compiler/context/compare.rs | 6 ++++-- compiler/erg_compiler/context/tyvar.rs | 4 ++-- compiler/erg_parser/lex.rs | 4 +++- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/compiler/erg_compiler/context/compare.rs b/compiler/erg_compiler/context/compare.rs index 9546777b..62db69e0 100644 --- a/compiler/erg_compiler/context/compare.rs +++ b/compiler/erg_compiler/context/compare.rs @@ -80,7 +80,7 @@ impl Context { } (TyParam::FreeVar(fv), other) | (other, TyParam::FreeVar(fv)) => match &*fv.borrow() { FreeKind::Linked(t) | FreeKind::UndoableLinked { t, .. } => { - return self.eq_tp(t, other) + return self.eq_tp(t, other); } FreeKind::Unbound { constraint, .. } | FreeKind::NamedUnbound { constraint, .. } => { @@ -89,7 +89,9 @@ impl Context { return self.structural_supertype_of(t, &other_t); } }, - (l, r) if l == r => return true, + (l, r) if l == r => { + return true; + } _ => {} } self.shallow_eq_tp(lhs, rhs) diff --git a/compiler/erg_compiler/context/tyvar.rs b/compiler/erg_compiler/context/tyvar.rs index 5c213023..d8c607d9 100644 --- a/compiler/erg_compiler/context/tyvar.rs +++ b/compiler/erg_compiler/context/tyvar.rs @@ -526,7 +526,7 @@ impl Context { (TyParam::FreeVar(fv), tp) | (tp, TyParam::FreeVar(fv)) => { match &*fv.borrow() { FreeKind::Linked(l) | FreeKind::UndoableLinked { t: l, .. } => { - return self.unify_tp(l, tp, lhs_variance, allow_divergence) + return self.unify_tp(l, tp, lhs_variance, allow_divergence); } FreeKind::Unbound { .. } | FreeKind::NamedUnbound { .. } => {} } // &fv is dropped @@ -733,7 +733,7 @@ impl Context { (Type::FreeVar(fv), t) | (t, Type::FreeVar(fv)) => { match &mut *fv.borrow_mut() { FreeKind::Linked(l) | FreeKind::UndoableLinked { t: l, .. } => { - return self.unify(l, t, lhs_loc, rhs_loc) + return self.unify(l, t, lhs_loc, rhs_loc); } FreeKind::Unbound { lev, constraint, .. diff --git a/compiler/erg_parser/lex.rs b/compiler/erg_parser/lex.rs index 2425f404..0b106448 100644 --- a/compiler/erg_parser/lex.rs +++ b/compiler/erg_parser/lex.rs @@ -412,7 +412,9 @@ impl Lexer /*<'a>*/ { while let Some(ch) = self.peek_cur_ch() { match ch { // `.` may be a dot operator, don't consume - '.' => return self.lex_num_dot(num), + '.' => { + return self.lex_num_dot(num); + } n if n.is_ascii_digit() || n == '_' => { num.push(self.consume().unwrap()); } From fb0d2f5737db25c9737aec2bddb4ad7e8ff8b302 Mon Sep 17 00:00:00 2001 From: Shunsuke Shibayama Date: Mon, 5 Sep 2022 11:11:57 +0900 Subject: [PATCH 21/68] Refactor --- compiler/erg_compiler/context/compare.rs | 28 +++++++++----------- compiler/erg_compiler/context/hint.rs | 2 +- compiler/erg_compiler/context/instantiate.rs | 2 +- compiler/erg_compiler/context/tyvar.rs | 4 +-- compiler/erg_compiler/eval.rs | 4 +-- compiler/erg_type/free.rs | 6 ++--- compiler/erg_type/lib.rs | 2 +- 7 files changed, 23 insertions(+), 25 deletions(-) diff --git a/compiler/erg_compiler/context/compare.rs b/compiler/erg_compiler/context/compare.rs index 62db69e0..07c71039 100644 --- a/compiler/erg_compiler/context/compare.rs +++ b/compiler/erg_compiler/context/compare.rs @@ -232,7 +232,7 @@ impl Context { { (Absolutely, true) } - (_, Type::FreeVar(fv)) | (Type::FreeVar(fv), _) => match fv.crack_bound_types() { + (_, Type::FreeVar(fv)) | (Type::FreeVar(fv), _) => match fv.get_bound_types() { Some((Type::Never, Type::Obj)) => (Absolutely, true), _ => (Maybe, false), }, @@ -335,7 +335,7 @@ impl Context { /// assert sup_conforms(?E(<: Eq(?R)), base: T, sup_trait: Eq(U)) /// ``` fn sup_conforms(&self, free: &FreeTyVar, base: &Type, sup_trait: &Type) -> bool { - let (_sub, sup) = free.crack_bound_types().unwrap(); + let (_sub, sup) = free.get_bound_types().unwrap(); free.forced_undoable_link(base); let judge = self.supertype_of(&sup, sup_trait); free.undo(); @@ -345,7 +345,7 @@ impl Context { /// assert!(sup_conforms(?E(<: Eq(?E)), {Nat, Eq(Nat)})) /// assert!(sup_conforms(?E(<: Eq(?R)), {Nat, Eq(T)})) fn _sub_conforms(&self, free: &FreeTyVar, inst_pair: &TraitInstance) -> bool { - let (_sub, sup) = free.crack_bound_types().unwrap(); + let (_sub, sup) = free.get_bound_types().unwrap(); log!(info "{free}"); free.forced_undoable_link(&inst_pair.sub_type); log!(info "{free}"); @@ -403,20 +403,18 @@ impl Context { } // ?T(<: Nat) !:> ?U(:> Int) // ?T(<: Nat) :> ?U(<: Int) (?U can be smaller than ?T) - (FreeVar(lfv), FreeVar(rfv)) => { - match (lfv.crack_bound_types(), rfv.crack_bound_types()) { - (Some((_, l_sup)), Some((r_sub, _))) => self.supertype_of(&l_sup, &r_sub), - _ => { - if lfv.is_linked() { - self.supertype_of(&lfv.crack(), rhs) - } else if rfv.is_linked() { - self.supertype_of(lhs, &rfv.crack()) - } else { - false - } + (FreeVar(lfv), FreeVar(rfv)) => match (lfv.get_bound_types(), rfv.get_bound_types()) { + (Some((_, l_sup)), Some((r_sub, _))) => self.supertype_of(&l_sup, &r_sub), + _ => { + if lfv.is_linked() { + self.supertype_of(&lfv.crack(), rhs) + } else if rfv.is_linked() { + self.supertype_of(lhs, &rfv.crack()) + } else { + false } } - } + }, // true if it can be a supertype, false if it cannot (due to type constraints) // No type constraints are imposed here, as subsequent type decisions are made according to the possibilities (FreeVar(lfv), rhs) => { diff --git a/compiler/erg_compiler/context/hint.rs b/compiler/erg_compiler/context/hint.rs index 4a121cff..38999882 100644 --- a/compiler/erg_compiler/context/hint.rs +++ b/compiler/erg_compiler/context/hint.rs @@ -10,7 +10,7 @@ impl Context { if fv.is_linked() { fv.crack().clone() } else { - let (_sub, sup) = fv.crack_bound_types().unwrap(); + let (_sub, sup) = fv.get_bound_types().unwrap(); sup } } else { diff --git a/compiler/erg_compiler/context/instantiate.rs b/compiler/erg_compiler/context/instantiate.rs index 130d5c87..ee69be4a 100644 --- a/compiler/erg_compiler/context/instantiate.rs +++ b/compiler/erg_compiler/context/instantiate.rs @@ -303,7 +303,7 @@ impl TyVarContext { } fn check_cyclicity_and_link(&self, name: &str, fv_inst: &FreeTyVar, tv: &Type) { - let (sub, sup) = enum_unwrap!(tv, Type::FreeVar).crack_bound_types().unwrap(); + let (sub, sup) = enum_unwrap!(tv, Type::FreeVar).get_bound_types().unwrap(); let new_cyclicity = match (sup.contains_tvar(name), sub.contains_tvar(name)) { (true, true) => Cyclicity::Both, // T <: Super diff --git a/compiler/erg_compiler/context/tyvar.rs b/compiler/erg_compiler/context/tyvar.rs index d8c607d9..d7ef9e8a 100644 --- a/compiler/erg_compiler/context/tyvar.rs +++ b/compiler/erg_compiler/context/tyvar.rs @@ -986,9 +986,9 @@ impl Context { (Type::FreeVar(lfv), Type::FreeVar(rfv)) if lfv.constraint_is_sandwiched() && rfv.constraint_is_sandwiched() => { - let (lsub, lsup) = lfv.crack_bound_types().unwrap(); + let (lsub, lsup) = lfv.get_bound_types().unwrap(); let l_cyc = lfv.cyclicity(); - let (rsub, rsup) = rfv.crack_bound_types().unwrap(); + let (rsub, rsup) = rfv.get_bound_types().unwrap(); let r_cyc = rfv.cyclicity(); let cyclicity = l_cyc.combine(r_cyc); let new_constraint = if let Some(min) = self.min(&lsup, &rsup) { diff --git a/compiler/erg_compiler/eval.rs b/compiler/erg_compiler/eval.rs index fe1494d0..81359a45 100644 --- a/compiler/erg_compiler/eval.rs +++ b/compiler/erg_compiler/eval.rs @@ -609,7 +609,7 @@ impl Context { TyParam::Value(v) => Ok(enum_t(set![v])), TyParam::Erased(t) => Ok((*t).clone()), TyParam::FreeVar(fv) => { - if let Some(t) = fv.type_of() { + if let Some(t) = fv.get_type() { Ok(t) } else { todo!() @@ -637,7 +637,7 @@ impl Context { TyParam::Value(v) => Ok(v.class()), TyParam::Erased(t) => Ok((*t).clone()), TyParam::FreeVar(fv) => { - if let Some(t) = fv.type_of() { + if let Some(t) = fv.get_type() { Ok(t) } else { todo!() diff --git a/compiler/erg_type/free.rs b/compiler/erg_type/free.rs index 1ce5703e..8cd0d05c 100644 --- a/compiler/erg_type/free.rs +++ b/compiler/erg_type/free.rs @@ -512,19 +512,19 @@ impl Free { }) } - pub fn type_of(&self) -> Option { + pub fn get_type(&self) -> Option { self.borrow() .constraint() .and_then(|c| c.get_type().cloned()) } - pub fn crack_sup(&self) -> Option { + pub fn get_sup(&self) -> Option { self.borrow() .constraint() .and_then(|c| c.get_super().cloned()) } - pub fn crack_bound_types(&self) -> Option<(Type, Type)> { + pub fn get_bound_types(&self) -> Option<(Type, Type)> { self.borrow() .constraint() .and_then(|c| c.get_sub_sup().map(|(sub, sup)| (sub.clone(), sup.clone()))) diff --git a/compiler/erg_type/lib.rs b/compiler/erg_type/lib.rs index 0be7ed5c..3578e780 100644 --- a/compiler/erg_type/lib.rs +++ b/compiler/erg_type/lib.rs @@ -1715,7 +1715,7 @@ impl Type { Self::FreeVar(fv) => { fv.unbound_name().map(|n| &n[..] == name).unwrap_or(false) || fv - .crack_bound_types() + .get_bound_types() .map(|(sub, sup)| sub.contains_tvar(name) || sup.contains_tvar(name)) .unwrap_or(false) } From d5f2b5f450457490898a8711742d9092181c35cd Mon Sep 17 00:00:00 2001 From: Shunsuke Shibayama Date: Mon, 5 Sep 2022 14:24:30 +0900 Subject: [PATCH 22/68] Add `register_gen_*` `register_*` renamed `register_const_*` --- .../erg_compiler/context/initialize/mod.rs | 467 ++++++++---------- .../context/initialize/py_mods/importlib.rs | 2 +- .../context/initialize/py_mods/io.rs | 4 +- .../context/initialize/py_mods/math.rs | 12 +- .../context/initialize/py_mods/random.rs | 6 +- .../context/initialize/py_mods/socket.rs | 4 +- .../context/initialize/py_mods/sys.rs | 34 +- .../context/initialize/py_mods/time.rs | 4 +- compiler/erg_compiler/context/inquire.rs | 95 +++- compiler/erg_compiler/context/register.rs | 124 ++++- compiler/erg_compiler/eval.rs | 2 +- compiler/erg_type/value.rs | 31 +- 12 files changed, 470 insertions(+), 315 deletions(-) diff --git a/compiler/erg_compiler/context/initialize/mod.rs b/compiler/erg_compiler/context/initialize/mod.rs index 69f794a7..42566ab6 100644 --- a/compiler/erg_compiler/context/initialize/mod.rs +++ b/compiler/erg_compiler/context/initialize/mod.rs @@ -9,7 +9,7 @@ use erg_common::vis::Visibility; use erg_common::Str; use erg_type::typaram::TyParam; -use erg_type::value::{TypeKind, TypeObj, ValueObj}; +use erg_type::value::ValueObj; use erg_type::Type; use erg_type::{constructors::*, BuiltinConstSubr, ConstSubr}; use ParamSpec as PS; @@ -27,7 +27,7 @@ use VarKind::*; use Visibility::*; impl Context { - fn register_decl(&mut self, name: &'static str, t: Type, vis: Visibility) { + fn register_builtin_decl(&mut self, name: &'static str, t: Type, vis: Visibility) { let name = VarName::from_static(name); if self.decls.get(&name).is_some() { panic!("already registered: {name}"); @@ -37,7 +37,13 @@ impl Context { } } - fn register_impl(&mut self, name: &'static str, t: Type, muty: Mutability, vis: Visibility) { + fn register_builtin_impl( + &mut self, + name: &'static str, + t: Type, + muty: Mutability, + vis: Visibility, + ) { let name = VarName::from_static(name); if self.locals.get(&name).is_some() { panic!("already registered: {name}"); @@ -47,58 +53,13 @@ impl Context { } } - pub(crate) fn register_const(&mut self, name: &str, obj: ValueObj) { + fn register_builtin_const(&mut self, name: &str, obj: ValueObj) { if self.rec_get_const_obj(name).is_some() { panic!("already registered: {name}"); } else { - match obj { - /*ValueObj::Type(TypeObj::Builtin(_builtin)) => { - todo!() - }*/ - ValueObj::Type(TypeObj::Gen(gen)) => match gen.kind { - TypeKind::Class => { - if gen.t.is_monomorphic() { - let super_traits = - gen.impls.into_iter().map(|to| to.typ().clone()).collect(); - let mut ctx = - Self::mono_class(gen.t.name(), vec![], super_traits, self.level); - let require = gen.require_or_sup.typ().clone(); - let new_t = func1(require, gen.t.clone()); - ctx.register_impl("__new__", new_t, Immutable, Private); - self.register_mono_type(gen.t, ctx, Const); - } else { - todo!() - } - } - TypeKind::InheritedClass => { - if gen.t.is_monomorphic() { - let super_classes = vec![gen.require_or_sup.typ().clone()]; - let super_traits = - gen.impls.into_iter().map(|to| to.typ().clone()).collect(); - let mut ctx = Self::mono_class( - gen.t.name(), - super_classes, - super_traits, - self.level, - ); - let sup = gen.require_or_sup.typ().clone(); - let new_t = func1(sup, gen.t.clone()); - ctx.register_impl("__new__", new_t, Immutable, Private); - self.register_mono_type(gen.t, ctx, Const); - } else { - todo!() - } - } - other => todo!("{other:?}"), - }, - other => { - // TODO: visibility (not always private) - // TODO: kind (not always Builtin) - let vi = VarInfo::new(enum_t(set! {other.clone()}), Const, Private, Builtin); - self.consts.insert(VarName::from_str(Str::rc(name)), other); - self.locals.insert(VarName::from_str(Str::rc(name)), vi); - } - } + 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); } } @@ -110,7 +71,7 @@ impl Context { } } - fn register_type(&mut self, t: Type, ctx: Self, muty: Mutability) { + fn register_builtin_type(&mut self, t: Type, ctx: Self, muty: Mutability) { if t.typarams_len().is_none() { self.register_mono_type(t, ctx, muty); } else { @@ -119,6 +80,7 @@ impl Context { } fn register_mono_type(&mut self, t: Type, ctx: Self, muty: Mutability) { + // FIXME: recursive search if self.mono_types.contains_key(&t.name()) { panic!("{} has already been registered", t.name()); } else if self.rec_get_const_obj(&t.name()).is_some() { @@ -127,7 +89,8 @@ impl Context { let name = VarName::from_str(t.name()); self.locals .insert(name.clone(), VarInfo::new(Type, muty, Private, Builtin)); - self.consts.insert(name.clone(), ValueObj::t(t.clone())); + self.consts + .insert(name.clone(), ValueObj::builtin_t(t.clone())); for impl_trait in ctx.super_traits.iter() { if let Some(impls) = self.trait_impls.get_mut(&impl_trait.name()) { impls.push(TraitInstance::new(t.clone(), impl_trait.clone())); @@ -146,13 +109,15 @@ impl Context { fn register_poly_type(&mut self, t: Type, ctx: Self, muty: Mutability) { let mut tv_ctx = TyVarContext::new(self.level, ctx.type_params_bounds(), self); let t = Self::instantiate_t(t, &mut tv_ctx); + // FIXME: panic if let Some((_, root_ctx)) = self.poly_types.get_mut(&t.name()) { root_ctx.method_defs.push((t, ctx)); } else { let name = VarName::from_str(t.name()); self.locals .insert(name.clone(), VarInfo::new(Type, muty, Private, Builtin)); - self.consts.insert(name.clone(), ValueObj::t(t.clone())); + self.consts + .insert(name.clone(), ValueObj::builtin_t(t.clone())); for impl_trait in ctx.super_traits.iter() { if let Some(impls) = self.trait_impls.get_mut(&impl_trait.name()) { impls.push(TraitInstance::new(t.clone(), impl_trait.clone())); @@ -167,7 +132,7 @@ impl Context { } } - fn register_patch(&mut self, name: &'static str, ctx: Self, muty: Mutability) { + fn register_builtin_patch(&mut self, name: &'static str, ctx: Self, muty: Mutability) { if self.patches.contains_key(name) { panic!("{} has already been registered", name); } else { @@ -199,12 +164,12 @@ impl Context { let f_t = func(vec![param_t("old", proj.clone())], None, vec![], proj); let t = pr1_met(mono_q("Self"), None, f_t, NoneType); let t = quant(t, set! { subtypeof(mono_q("Self"), mono("Immutizable")) }); - mutable.register_decl("update!", t, Public); + mutable.register_builtin_decl("update!", t, Public); let mut immutizable = Self::mono_trait("Immutizable", vec![mono("Mutable")], Self::TOP_LEVEL); - immutizable.register_decl("ImmutType", Type, Public); + immutizable.register_builtin_decl("ImmutType", Type, Public); let mut mutizable = Self::mono_trait("Mutizable", vec![], Self::TOP_LEVEL); - mutizable.register_decl("MutType!", Type, Public); + mutizable.register_builtin_decl("MutType!", Type, Public); let mut in_ = Self::poly_trait( "In", vec![PS::t("T", NonDefault)], @@ -216,7 +181,7 @@ impl Context { op_t, set! { static_instance("T", Type), subtypeof(mono_q("I"), poly("In", vec![ty_tp(mono_q("T"))])) }, ); - in_.register_decl("__in__", op_t, Public); + in_.register_builtin_decl("__in__", op_t, Public); // Erg does not have a trait equivalent to `PartialEq` in Rust // This means, Erg's `Float` cannot be compared with other `Float` // use `l - r < EPSILON` to check if two floats are almost equal @@ -235,7 +200,7 @@ impl Context { static_instance("R", Type) }, ); - eq.register_decl("__eq__", op_t.clone(), Public); + eq.register_builtin_decl("__eq__", op_t.clone(), Public); let mut partial_ord = Self::poly_trait( "PartialOrd", vec![PS::t("R", WithDefault)], @@ -250,7 +215,7 @@ impl Context { static_instance("R", Type) }, ); - partial_ord.register_decl("__lt__", op_t.clone(), Public); + partial_ord.register_builtin_decl("__lt__", op_t.clone(), Public); let ord = Self::mono_trait( "Ord", vec![poly("Eq", vec![]), poly("PartialOrd", vec![])], @@ -277,14 +242,14 @@ impl Context { t, set! {subtypeof(self_t.clone(), poly("Seq", vec![TyParam::erased(Type)]))}, ); - seq.register_decl("__len__", t, Public); + seq.register_builtin_decl("__len__", t, Public); let t = fn1_met(self_t.clone(), Nat, mono_q("T")); let t = quant( t, set! {subtypeof(self_t, poly("Seq", vec![ty_tp(mono_q("T"))])), static_instance("T", Type)}, ); // Seq.get: |Self <: Seq(T)| Self.(Nat) -> T - seq.register_decl("get", t, Public); + seq.register_builtin_decl("get", t, Public); let params = vec![PS::t("T", NonDefault)]; let input = Self::poly_trait("Input", params.clone(), vec![], Self::TOP_LEVEL); let output = Self::poly_trait("Output", params.clone(), vec![], Self::TOP_LEVEL); @@ -301,8 +266,8 @@ impl Context { let self_bound = subtypeof(mono_q("Self"), poly("Add", ty_params.clone())); let op_t = fn1_met(mono_q("Self"), r.clone(), mono_proj(mono_q("Self"), "AddO")); let op_t = quant(op_t, set! {r_bound.clone(), self_bound}); - add.register_decl("__add__", op_t, Public); - add.register_decl("AddO", Type, Public); + add.register_builtin_decl("__add__", op_t, Public); + add.register_builtin_decl("AddO", Type, Public); let mut sub = Self::poly_trait( "Sub", params.clone(), @@ -312,8 +277,8 @@ impl Context { let op_t = fn1_met(mono_q("Self"), r.clone(), mono_proj(mono_q("Self"), "SubO")); let self_bound = subtypeof(mono_q("Self"), poly("Sub", ty_params.clone())); let op_t = quant(op_t, set! {r_bound.clone(), self_bound}); - sub.register_decl("__sub__", op_t, Public); - sub.register_decl("SubO", Type, Public); + sub.register_builtin_decl("__sub__", op_t, Public); + sub.register_builtin_decl("SubO", Type, Public); let mut mul = Self::poly_trait( "Mul", params.clone(), @@ -323,8 +288,8 @@ impl Context { let op_t = fn1_met(mono_q("Self"), r.clone(), mono_proj(mono_q("Self"), "MulO")); let self_bound = subtypeof(mono_q("Self"), poly("Mul", ty_params.clone())); let op_t = quant(op_t, set! {r_bound.clone(), self_bound}); - mul.register_decl("__mul__", op_t, Public); - mul.register_decl("MulO", Type, Public); + mul.register_builtin_decl("__mul__", op_t, Public); + mul.register_builtin_decl("MulO", Type, Public); let mut div = Self::poly_trait( "Div", params.clone(), @@ -334,32 +299,32 @@ impl Context { let op_t = fn1_met(mono_q("Self"), r, mono_proj(mono_q("Self"), "DivO")); let self_bound = subtypeof(mono_q("Self"), poly("Div", ty_params.clone())); let op_t = quant(op_t, set! {r_bound.clone(), self_bound}); - div.register_decl("__div__", op_t, Public); - div.register_decl("DivO", Type, Public); - self.register_type(mono("Unpack"), unpack, Const); - self.register_type(mono("Named"), named, Const); - self.register_type(mono("Mutable"), mutable, Const); - self.register_type(mono("Immutizable"), immutizable, Const); - self.register_type(mono("Mutizable"), mutizable, Const); - self.register_type(poly("In", vec![ty_tp(mono_q("T"))]), in_, Const); - self.register_type(poly("Eq", vec![ty_tp(mono_q("R"))]), eq, Const); - self.register_type( + div.register_builtin_decl("__div__", op_t, Public); + div.register_builtin_decl("DivO", Type, Public); + self.register_builtin_type(mono("Unpack"), unpack, Const); + self.register_builtin_type(mono("Named"), named, Const); + self.register_builtin_type(mono("Mutable"), mutable, Const); + self.register_builtin_type(mono("Immutizable"), immutizable, Const); + self.register_builtin_type(mono("Mutizable"), mutizable, Const); + self.register_builtin_type(poly("In", vec![ty_tp(mono_q("T"))]), in_, Const); + self.register_builtin_type(poly("Eq", vec![ty_tp(mono_q("R"))]), eq, Const); + self.register_builtin_type( poly("PartialOrd", vec![ty_tp(mono_q("R"))]), partial_ord, Const, ); - self.register_type(mono("Ord"), ord, Const); - self.register_type(mono("Num"), num, Const); - self.register_type(poly("Seq", vec![ty_tp(mono_q("T"))]), seq, Const); - self.register_type(poly("Input", vec![ty_tp(mono_q("T"))]), input, Const); - self.register_type(poly("Output", vec![ty_tp(mono_q("T"))]), output, Const); - self.register_type(poly("Add", ty_params.clone()), add, Const); - self.register_type(poly("Sub", ty_params.clone()), sub, Const); - self.register_type(poly("Mul", ty_params.clone()), mul, Const); - self.register_type(poly("Div", ty_params), div, Const); + self.register_builtin_type(mono("Ord"), ord, Const); + self.register_builtin_type(mono("Num"), num, Const); + self.register_builtin_type(poly("Seq", vec![ty_tp(mono_q("T"))]), seq, Const); + self.register_builtin_type(poly("Input", vec![ty_tp(mono_q("T"))]), input, Const); + self.register_builtin_type(poly("Output", vec![ty_tp(mono_q("T"))]), output, Const); + self.register_builtin_type(poly("Add", ty_params.clone()), add, Const); + self.register_builtin_type(poly("Sub", ty_params.clone()), sub, Const); + self.register_builtin_type(poly("Mul", ty_params.clone()), mul, Const); + self.register_builtin_type(poly("Div", ty_params), div, Const); self.register_const_param_defaults( "Eq", - vec![ConstTemplate::Obj(ValueObj::t(mono_q("Self")))], + vec![ConstTemplate::Obj(ValueObj::builtin_t(mono_q("Self")))], ); self.register_const_param_defaults( "PartialOrd", @@ -367,19 +332,19 @@ impl Context { ); self.register_const_param_defaults( "Add", - vec![ConstTemplate::Obj(ValueObj::t(mono_q("Self")))], + vec![ConstTemplate::Obj(ValueObj::builtin_t(mono_q("Self")))], ); self.register_const_param_defaults( "Sub", - vec![ConstTemplate::Obj(ValueObj::t(mono_q("Self")))], + vec![ConstTemplate::Obj(ValueObj::builtin_t(mono_q("Self")))], ); self.register_const_param_defaults( "Mul", - vec![ConstTemplate::Obj(ValueObj::t(mono_q("Self")))], + vec![ConstTemplate::Obj(ValueObj::builtin_t(mono_q("Self")))], ); self.register_const_param_defaults( "Div", - vec![ConstTemplate::Obj(ValueObj::t(mono_q("Self")))], + vec![ConstTemplate::Obj(ValueObj::builtin_t(mono_q("Self")))], ); } @@ -387,14 +352,14 @@ impl Context { let mut obj = Self::mono_class("Obj", vec![], vec![], Self::TOP_LEVEL); let t = fn0_met(mono_q("Self"), mono_q("Self")); let t = quant(t, set! {subtypeof(mono_q("Self"), mono("Obj"))}); - obj.register_impl("clone", t, Const, Public); - obj.register_impl("__module__", Str, Const, Public); - obj.register_impl("__sizeof__", fn0_met(Obj, Nat), Const, Public); - obj.register_impl("__repr__", fn0_met(Obj, Str), Immutable, Public); - obj.register_impl("__str__", fn0_met(Obj, Str), Immutable, Public); - obj.register_impl("__dict__", fn0_met(Obj, dict(Str, Obj)), Immutable, Public); - obj.register_impl("__bytes__", fn0_met(Obj, mono("Bytes")), Immutable, Public); - obj.register_const("MutType!", ValueObj::t(mono("Obj!"))); + obj.register_builtin_impl("clone", t, Const, Public); + obj.register_builtin_impl("__module__", Str, Const, Public); + obj.register_builtin_impl("__sizeof__", fn0_met(Obj, Nat), Const, Public); + obj.register_builtin_impl("__repr__", fn0_met(Obj, Str), Immutable, Public); + obj.register_builtin_impl("__str__", fn0_met(Obj, Str), Immutable, Public); + 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( @@ -414,19 +379,19 @@ impl Context { ], Self::TOP_LEVEL, ); - int.register_impl("abs", fn0_met(Int, Nat), Immutable, Public); + int.register_builtin_impl("abs", fn0_met(Int, Nat), Immutable, Public); // __div__ is not included in Int (cast to Float) let op_t = fn1_met(Int, Int, Int); - int.register_impl("__add__", op_t.clone(), Const, Public); - int.register_impl("__sub__", op_t.clone(), Const, Public); - int.register_impl("__mul__", op_t, Const, Public); - int.register_const("AddO", ValueObj::t(Int)); - int.register_const("SubO", ValueObj::t(Int)); - int.register_const("MulO", ValueObj::t(Int)); - int.register_const("DivO", ValueObj::t(Ratio)); - int.register_const("MutType!", ValueObj::t(mono("Int!"))); - int.register_impl("Real", Int, Const, Public); - int.register_impl("Imag", Int, Const, Public); + int.register_builtin_impl("__add__", op_t.clone(), Const, Public); + int.register_builtin_impl("__sub__", op_t.clone(), Const, Public); + int.register_builtin_impl("__mul__", op_t, Const, Public); + int.register_builtin_const("AddO", ValueObj::builtin_t(Int)); + int.register_builtin_const("SubO", ValueObj::builtin_t(Int)); + int.register_builtin_const("MulO", ValueObj::builtin_t(Int)); + int.register_builtin_const("DivO", ValueObj::builtin_t(Ratio)); + int.register_builtin_const("MutType!", ValueObj::builtin_t(mono("Int!"))); + int.register_builtin_impl("Real", Int, Const, Public); + int.register_builtin_impl("Imag", Int, Const, Public); let mut nat = Self::mono_class( "Nat", vec![Int, Ratio, Obj], @@ -446,9 +411,9 @@ impl Context { ); // __sub__, __div__ is not included in Nat (cast to Int) let op_t = fn1_met(Nat, Nat, Nat); - nat.register_impl("__add__", op_t.clone(), Const, Public); - nat.register_impl("__mul__", op_t, Const, Public); - nat.register_impl( + nat.register_builtin_impl("__add__", op_t.clone(), Const, Public); + nat.register_builtin_impl("__mul__", op_t, Const, Public); + nat.register_builtin_impl( "times!", pr_met( Nat, @@ -461,13 +426,13 @@ impl Context { Immutable, Public, ); - nat.register_const("AddO", ValueObj::t(Nat)); - nat.register_const("SubO", ValueObj::t(Int)); - nat.register_const("MulO", ValueObj::t(Nat)); - nat.register_const("DivO", ValueObj::t(Ratio)); - nat.register_const("MutType!", ValueObj::t(mono("Nat!"))); - nat.register_impl("Real", Nat, Const, Public); - nat.register_impl("Imag", Nat, Const, Public); + nat.register_builtin_const("AddO", ValueObj::builtin_t(Nat)); + nat.register_builtin_const("SubO", ValueObj::builtin_t(Int)); + nat.register_builtin_const("MulO", ValueObj::builtin_t(Nat)); + nat.register_builtin_const("DivO", ValueObj::builtin_t(Ratio)); + nat.register_builtin_const("MutType!", ValueObj::builtin_t(mono("Nat!"))); + nat.register_builtin_impl("Real", Nat, Const, Public); + nat.register_builtin_impl("Imag", Nat, Const, Public); let mut float = Self::mono_class( "Float", vec![Obj], @@ -484,17 +449,17 @@ impl Context { Self::TOP_LEVEL, ); let op_t = fn1_met(Float, Float, Float); - float.register_impl("__add__", op_t.clone(), Const, Public); - float.register_impl("__sub__", op_t.clone(), Const, Public); - float.register_impl("__mul__", op_t.clone(), Const, Public); - float.register_impl("__div__", op_t, Const, Public); - float.register_const("AddO", ValueObj::t(Float)); - float.register_const("SubO", ValueObj::t(Float)); - float.register_const("MulO", ValueObj::t(Float)); - float.register_const("DivO", ValueObj::t(Float)); - float.register_const("MutType!", ValueObj::t(mono("Float!"))); - float.register_impl("Real", Float, Const, Public); - float.register_impl("Imag", Float, Const, Public); + float.register_builtin_impl("__add__", op_t.clone(), Const, Public); + float.register_builtin_impl("__sub__", op_t.clone(), Const, Public); + float.register_builtin_impl("__mul__", op_t.clone(), Const, Public); + float.register_builtin_impl("__div__", op_t, Const, Public); + float.register_builtin_const("AddO", ValueObj::builtin_t(Float)); + float.register_builtin_const("SubO", ValueObj::builtin_t(Float)); + float.register_builtin_const("MulO", ValueObj::builtin_t(Float)); + float.register_builtin_const("DivO", ValueObj::builtin_t(Float)); + float.register_builtin_const("MutType!", ValueObj::builtin_t(mono("Float!"))); + float.register_builtin_impl("Real", Float, Const, Public); + float.register_builtin_impl("Imag", Float, Const, Public); let mut ratio = Self::mono_class( "Ratio", vec![Obj], @@ -511,17 +476,17 @@ impl Context { Self::TOP_LEVEL, ); let op_t = fn1_met(Ratio, Ratio, Ratio); - ratio.register_impl("__add__", op_t.clone(), Const, Public); - ratio.register_impl("__sub__", op_t.clone(), Const, Public); - ratio.register_impl("__mul__", op_t.clone(), Const, Public); - ratio.register_impl("__div__", op_t, Const, Public); - ratio.register_const("AddO", ValueObj::t(Ratio)); - ratio.register_const("SubO", ValueObj::t(Ratio)); - ratio.register_const("MulO", ValueObj::t(Ratio)); - ratio.register_const("DivO", ValueObj::t(Ratio)); - ratio.register_const("MutType!", ValueObj::t(mono("Ratio!"))); - ratio.register_impl("Real", Ratio, Const, Public); - ratio.register_impl("Imag", Ratio, Const, Public); + ratio.register_builtin_impl("__add__", op_t.clone(), Const, Public); + ratio.register_builtin_impl("__sub__", op_t.clone(), Const, Public); + ratio.register_builtin_impl("__mul__", op_t.clone(), Const, Public); + ratio.register_builtin_impl("__div__", op_t, Const, Public); + ratio.register_builtin_const("AddO", ValueObj::builtin_t(Ratio)); + ratio.register_builtin_const("SubO", ValueObj::builtin_t(Ratio)); + ratio.register_builtin_const("MulO", ValueObj::builtin_t(Ratio)); + ratio.register_builtin_const("DivO", ValueObj::builtin_t(Ratio)); + ratio.register_builtin_const("MutType!", ValueObj::builtin_t(mono("Ratio!"))); + ratio.register_builtin_impl("Real", Ratio, Const, Public); + ratio.register_builtin_impl("Imag", Ratio, Const, Public); let mut bool_ = Self::mono_class( "Bool", vec![Nat, Int, Ratio, Obj], @@ -540,9 +505,9 @@ impl Context { ], Self::TOP_LEVEL, ); - bool_.register_impl("__and__", fn1_met(Bool, Bool, Bool), Const, Public); - bool_.register_impl("__or__", fn1_met(Bool, Bool, Bool), Const, Public); - bool_.register_const("MutType!", ValueObj::t(mono("Bool!"))); + bool_.register_builtin_impl("__and__", fn1_met(Bool, Bool, Bool), Const, Public); + bool_.register_builtin_impl("__or__", fn1_met(Bool, Bool, Bool), Const, Public); + bool_.register_builtin_const("MutType!", ValueObj::builtin_t(mono("Bool!"))); let mut str_ = Self::mono_class( "Str", vec![Obj], @@ -556,8 +521,8 @@ impl Context { ], Self::TOP_LEVEL, ); - str_.register_impl("__add__", fn1_met(Str, Str, Str), Const, Public); - str_.register_impl( + str_.register_builtin_impl("__add__", fn1_met(Str, Str, Str), Const, Public); + str_.register_builtin_impl( "replace", fn_met( Str, @@ -569,7 +534,7 @@ impl Context { Immutable, Public, ); - str_.register_impl( + str_.register_builtin_impl( "encode", fn_met( Str, @@ -581,9 +546,9 @@ impl Context { Immutable, Public, ); - str_.register_const("AddO", ValueObj::t(Str)); - str_.register_const("MulO", ValueObj::t(Str)); - str_.register_const("MutType!", ValueObj::t(mono("Str!"))); + str_.register_builtin_const("AddO", ValueObj::builtin_t(Str)); + str_.register_builtin_const("MulO", ValueObj::builtin_t(Str)); + str_.register_builtin_const("MutType!", ValueObj::builtin_t(mono("Str!"))); let mut type_ = Self::mono_class( "Type", vec![Obj], @@ -594,7 +559,7 @@ impl Context { ], Self::TOP_LEVEL, ); - type_.register_impl("mro", array(Type, TyParam::erased(Nat)), Immutable, Public); + type_.register_builtin_impl("mro", array(Type, TyParam::erased(Nat)), Immutable, Public); let module = Self::mono_class( "Module", vec![Obj], @@ -633,7 +598,7 @@ impl Context { t, set! {static_instance("N", Nat), static_instance("M", Nat)}, ); - array_.register_impl("concat", t, Immutable, Public); + array_.register_builtin_impl("concat", t, Immutable, Public); let n = mono_q_tp("N"); let array_inner = mono_q("T"); let array_t = array(array_inner.clone(), n.clone()); @@ -652,13 +617,13 @@ impl Context { t, set! {static_instance("N", Nat), static_instance("T", mono("Mutable"))}, ); - array_.register_impl("map!", t, Immutable, Public); - let mut_type = ValueObj::t(poly( + array_.register_builtin_impl("map!", t, Immutable, Public); + let mut_type = ValueObj::builtin_t(poly( "Array!", vec![TyParam::t(mono_q("T")), TyParam::mono_q("N").mutate()], )); // [T; N].MutType! = [T; !N] (neither [T!; N] nor [T; N]!) - array_.register_const("MutType!", mut_type); + array_.register_builtin_const("MutType!", mut_type); let mut int_mut = Self::mono_class( "Int!", vec![Int, mono("Ratio!"), Obj], @@ -838,37 +803,37 @@ impl Context { )], Self::TOP_LEVEL, ); - int_mut.register_const("ImmutType", ValueObj::t(Int)); + int_mut.register_builtin_const("ImmutType", ValueObj::builtin_t(Int)); let f_t = param_t("f", func(vec![param_t("old", Int)], None, vec![], Int)); let t = pr_met(mono("Int!"), None, vec![f_t], None, vec![], NoneType); - int_mut.register_impl("update!", t, Immutable, Public); + int_mut.register_builtin_impl("update!", t, Immutable, Public); let mut nat_mut = Self::mono_class( "Nat!", vec![Nat, mono("Int!"), mono("Ratio!"), Obj], vec![mono("Mutable")], Self::TOP_LEVEL, ); - nat_mut.register_const("ImmutType", ValueObj::t(Nat)); + nat_mut.register_builtin_const("ImmutType", ValueObj::builtin_t(Nat)); let f_t = param_t("f", func(vec![param_t("old", Nat)], None, vec![], Nat)); let t = pr_met(mono("Nat!"), None, vec![f_t], None, vec![], NoneType); - nat_mut.register_impl("update!", t, Immutable, Public); + nat_mut.register_builtin_impl("update!", t, Immutable, Public); let mut float_mut = Self::mono_class( "Float!", vec![Float, Obj], vec![mono("Mutable")], Self::TOP_LEVEL, ); - float_mut.register_const("ImmutType", ValueObj::t(Float)); + float_mut.register_builtin_const("ImmutType", ValueObj::builtin_t(Float)); let f_t = param_t("f", func(vec![param_t("old", Float)], None, vec![], Float)); let t = pr_met(mono("Float!"), None, vec![f_t], None, vec![], NoneType); - float_mut.register_impl("update!", t, Immutable, Public); + float_mut.register_builtin_impl("update!", t, Immutable, Public); let mut ratio_mut = Self::mono_class( "Ratio!", vec![Ratio, Obj], vec![mono("Mutable")], Self::TOP_LEVEL, ); - ratio_mut.register_const("ImmutType", ValueObj::t(Ratio)); + ratio_mut.register_builtin_const("ImmutType", ValueObj::builtin_t(Ratio)); let f_t = param_t( "f", func( @@ -879,27 +844,27 @@ impl Context { ), ); let t = pr_met(mono("Ratio!"), None, vec![f_t], None, vec![], NoneType); - ratio_mut.register_impl("update!", t, Immutable, Public); + ratio_mut.register_builtin_impl("update!", t, Immutable, Public); let mut bool_mut = Self::mono_class( "Bool!", vec![Bool, mono("Nat!"), mono("Int!"), mono("Ratio!"), Obj], vec![mono("Mutable")], Self::TOP_LEVEL, ); - bool_mut.register_const("ImmutType", ValueObj::t(Bool)); + bool_mut.register_builtin_const("ImmutType", ValueObj::builtin_t(Bool)); let f_t = param_t("f", func(vec![param_t("old", Bool)], None, vec![], Bool)); let t = pr_met(mono("Bool!"), None, vec![f_t], None, vec![], NoneType); - bool_mut.register_impl("update!", t, Immutable, Public); + bool_mut.register_builtin_impl("update!", t, Immutable, Public); let mut str_mut = Self::mono_class( "Str!", vec![Str, Obj], vec![mono("Mutable")], Self::TOP_LEVEL, ); - str_mut.register_const("ImmutType", ValueObj::t(Str)); + str_mut.register_builtin_const("ImmutType", ValueObj::builtin_t(Str)); let f_t = param_t("f", func(vec![param_t("old", Str)], None, vec![], Str)); let t = pr_met(mono("Str!"), None, vec![f_t], None, vec![], NoneType); - str_mut.register_impl("update!", t, Immutable, Public); + str_mut.register_builtin_impl("update!", t, Immutable, Public); let array_mut_t = poly("Array!", vec![ty_tp(mono_q("T")), mono_q_tp("N")]); let mut array_mut = Self::poly_class( "Array!", @@ -923,7 +888,7 @@ impl Context { t, set! {static_instance("T", Type), static_instance("N", mono("Nat!"))}, ); - array_mut.register_impl("push!", t, Immutable, Public); + array_mut.register_builtin_impl("push!", t, Immutable, Public); let f_t = param_t( "f", func( @@ -934,7 +899,7 @@ impl Context { ), ); let t = pr_met(array_mut_t.clone(), None, vec![f_t], None, vec![], NoneType); - array_mut.register_impl("update!", t, Immutable, Public); + array_mut.register_builtin_impl("update!", t, Immutable, Public); let range_t = poly("Range", vec![TyParam::t(mono_q("T"))]); let range = Self::poly_class( "Range", @@ -955,31 +920,31 @@ impl Context { vec![], Self::TOP_LEVEL, ); - self.register_type(Obj, obj, Const); + self.register_builtin_type(Obj, obj, Const); // self.register_type(mono("Record"), vec![], record, Const); // self.register_type(mono("Class"), vec![], class, Const); - self.register_type(Int, int, Const); - self.register_type(Nat, nat, Const); - self.register_type(Float, float, Const); - self.register_type(Ratio, ratio, Const); - self.register_type(Bool, bool_, Const); - self.register_type(Str, str_, Const); - self.register_type(Type, type_, Const); - self.register_type(Module, module, Const); - self.register_type(array_t, array_, Const); - self.register_type(tuple(vec![mono_q("A")]), tuple1, Const); - self.register_type(tuple(vec![mono_q("A"), mono_q("B")]), tuple2, Const); - self.register_type( + self.register_builtin_type(Int, int, Const); + self.register_builtin_type(Nat, nat, Const); + self.register_builtin_type(Float, float, Const); + self.register_builtin_type(Ratio, ratio, Const); + self.register_builtin_type(Bool, bool_, Const); + self.register_builtin_type(Str, str_, Const); + self.register_builtin_type(Type, type_, Const); + self.register_builtin_type(Module, module, Const); + self.register_builtin_type(array_t, array_, Const); + self.register_builtin_type(tuple(vec![mono_q("A")]), tuple1, Const); + self.register_builtin_type(tuple(vec![mono_q("A"), mono_q("B")]), tuple2, Const); + self.register_builtin_type( tuple(vec![mono_q("A"), mono_q("B"), mono_q("C")]), tuple3, Const, ); - self.register_type( + self.register_builtin_type( tuple(vec![mono_q("A"), mono_q("B"), mono_q("C"), mono_q("D")]), tuple4, Const, ); - self.register_type( + self.register_builtin_type( tuple(vec![ mono_q("A"), mono_q("B"), @@ -990,7 +955,7 @@ impl Context { tuple5, Const, ); - self.register_type( + self.register_builtin_type( tuple(vec![ mono_q("A"), mono_q("B"), @@ -1002,7 +967,7 @@ impl Context { tuple6, Const, ); - self.register_type( + self.register_builtin_type( tuple(vec![ mono_q("A"), mono_q("B"), @@ -1015,7 +980,7 @@ impl Context { tuple7, Const, ); - self.register_type( + self.register_builtin_type( tuple(vec![ mono_q("A"), mono_q("B"), @@ -1029,17 +994,17 @@ impl Context { tuple8, Const, ); - self.register_type(mono("Int!"), int_mut, Const); - self.register_type(mono("Nat!"), nat_mut, Const); - self.register_type(mono("Float!"), float_mut, Const); - self.register_type(mono("Ratio!"), ratio_mut, Const); - self.register_type(mono("Bool!"), bool_mut, Const); - self.register_type(mono("Str!"), str_mut, Const); - self.register_type(array_mut_t, array_mut, Const); - self.register_type(range_t, range, Const); - self.register_type(mono("Tuple"), tuple_, Const); - self.register_type(mono("Function"), func, Const); - self.register_type(mono("QuantifiedFunction"), qfunc, Const); + self.register_builtin_type(mono("Int!"), int_mut, Const); + self.register_builtin_type(mono("Nat!"), nat_mut, Const); + self.register_builtin_type(mono("Float!"), float_mut, Const); + self.register_builtin_type(mono("Ratio!"), ratio_mut, Const); + self.register_builtin_type(mono("Bool!"), bool_mut, Const); + self.register_builtin_type(mono("Str!"), str_mut, Const); + self.register_builtin_type(array_mut_t, array_mut, Const); + self.register_builtin_type(range_t, range, Const); + self.register_builtin_type(mono("Tuple"), tuple_, Const); + self.register_builtin_type(mono("Function"), func, Const); + self.register_builtin_type(mono("QuantifiedFunction"), qfunc, Const); } fn init_builtin_funcs(&mut self) { @@ -1089,21 +1054,21 @@ impl Context { ); let t_pyimport = nd_func(vec![param_t("path", Str)], None, Module); let t_quit = func(vec![], None, vec![param_t("code", Int)], NoneType); - self.register_impl("abs", t_abs, Const, Private); - self.register_impl("assert", t_assert, Const, Private); - self.register_impl("classof", t_classof, Const, Private); - self.register_impl("compile", t_compile, Const, Private); - self.register_impl("cond", t_cond, Const, Private); - self.register_impl("discard", t_discard, Const, Private); - self.register_impl("id", t_id, Const, Private); - self.register_impl("if", t_if, Const, Private); - self.register_impl("log", t_log, Const, Private); - self.register_impl("import", t_import, Const, Private); + self.register_builtin_impl("abs", t_abs, Const, Private); + self.register_builtin_impl("assert", t_assert, Const, Private); + self.register_builtin_impl("classof", t_classof, Const, Private); + self.register_builtin_impl("compile", t_compile, Const, Private); + self.register_builtin_impl("cond", t_cond, Const, Private); + self.register_builtin_impl("discard", t_discard, Const, Private); + self.register_builtin_impl("id", t_id, Const, Private); + self.register_builtin_impl("if", t_if, Const, Private); + self.register_builtin_impl("log", t_log, Const, Private); + self.register_builtin_impl("import", t_import, Const, Private); if cfg!(feature = "debug") { - self.register_impl("py", t_pyimport.clone(), Const, Private); + self.register_builtin_impl("py", t_pyimport.clone(), Const, Private); } - self.register_impl("pyimport", t_pyimport, Const, Private); - self.register_impl("quit", t_quit, Const, Private); + self.register_builtin_impl("pyimport", t_pyimport, Const, Private); + self.register_builtin_impl("quit", t_quit, Const, Private); } fn init_builtin_const_funcs(&mut self) { @@ -1114,7 +1079,7 @@ impl Context { Type, ); let class = ConstSubr::Builtin(BuiltinConstSubr::new(class_func, class_t)); - self.register_const("Class", ValueObj::Subr(class)); + self.register_builtin_const("Class", ValueObj::Subr(class)); let inherit_t = func( vec![param_t("Super", Type)], None, @@ -1122,11 +1087,11 @@ impl Context { Type, ); let inherit = ConstSubr::Builtin(BuiltinConstSubr::new(inherit_func, inherit_t)); - self.register_const("Inherit", ValueObj::Subr(inherit)); + self.register_builtin_const("Inherit", ValueObj::Subr(inherit)); // decorators let inheritable = ConstSubr::Builtin(BuiltinConstSubr::new(inheritable_func, func1(Type, Type))); - self.register_const("Inheritable", ValueObj::Subr(inheritable)); + self.register_builtin_const("Inheritable", ValueObj::Subr(inheritable)); } fn init_builtin_procs(&mut self) { @@ -1169,11 +1134,11 @@ impl Context { None, NoneType, ); - self.register_impl("print!", t_print, Const, Private); - self.register_impl("input!", t_input, Const, Private); - self.register_impl("if!", t_if, Const, Private); - self.register_impl("for!", t_for, Const, Private); - self.register_impl("while!", t_while, Const, Private); + self.register_builtin_impl("print!", t_print, Const, Private); + self.register_builtin_impl("input!", t_input, Const, Private); + self.register_builtin_impl("if!", t_if, Const, Private); + self.register_builtin_impl("for!", t_for, Const, Private); + self.register_builtin_impl("while!", t_while, Const, Private); } fn init_builtin_operators(&mut self) { @@ -1193,7 +1158,7 @@ impl Context { subtypeof(l.clone(), poly("Add", params.clone())) }, ); - self.register_impl("__add__", op_t, Const, Private); + self.register_builtin_impl("__add__", op_t, Const, Private); let op_t = bin_op(l.clone(), r.clone(), mono_proj(mono_q("L"), "SubO")); let op_t = quant( op_t, @@ -1202,7 +1167,7 @@ impl Context { subtypeof(l.clone(), poly("Sub", params.clone())) }, ); - self.register_impl("__sub__", op_t, Const, Private); + self.register_builtin_impl("__sub__", op_t, Const, Private); let op_t = bin_op(l.clone(), r.clone(), mono_proj(mono_q("L"), "MulO")); let op_t = quant( op_t, @@ -1211,7 +1176,7 @@ impl Context { subtypeof(l.clone(), poly("Mul", params.clone())) }, ); - self.register_impl("__mul__", op_t, Const, Private); + self.register_builtin_impl("__mul__", op_t, Const, Private); let op_t = bin_op(l.clone(), r.clone(), mono_proj(mono_q("L"), "DivO")); let op_t = quant( op_t, @@ -1220,54 +1185,54 @@ impl Context { subtypeof(l, poly("Mul", params.clone())) }, ); - self.register_impl("__div__", op_t, Const, Private); + self.register_builtin_impl("__div__", op_t, Const, Private); let m = mono_q("M"); let op_t = bin_op(m.clone(), m.clone(), m.clone()); let op_t = quant(op_t, set! {subtypeof(m, poly("Mul", vec![]))}); // TODO: add bound: M == MulO - self.register_impl("__pow__", op_t, Const, Private); + self.register_builtin_impl("__pow__", op_t, Const, Private); let d = mono_q("D"); let op_t = bin_op(d.clone(), d.clone(), d.clone()); let op_t = quant(op_t, set! {subtypeof(d, poly("Div", vec![]))}); - self.register_impl("__mod__", op_t, Const, Private); + self.register_builtin_impl("__mod__", op_t, Const, Private); let e = mono_q("E"); let op_t = bin_op(e.clone(), e.clone(), Bool); let op_t = quant(op_t, set! {subtypeof(e, poly("Eq", vec![]))}); - self.register_impl("__eq__", op_t.clone(), Const, Private); - self.register_impl("__ne__", op_t, Const, Private); + self.register_builtin_impl("__eq__", op_t.clone(), Const, Private); + self.register_builtin_impl("__ne__", op_t, Const, Private); let o = mono_q("O"); let op_t = bin_op(o.clone(), o.clone(), Bool); let op_t = quant(op_t, set! {subtypeof(o, mono("Ord"))}); - self.register_impl("__lt__", op_t.clone(), Const, Private); - self.register_impl("__le__", op_t.clone(), Const, Private); - self.register_impl("__gt__", op_t.clone(), Const, Private); - self.register_impl("__ge__", op_t, Const, Private); - self.register_impl("__and__", bin_op(Bool, Bool, Bool), Const, Private); - self.register_impl("__or__", bin_op(Bool, Bool, Bool), Const, Private); + self.register_builtin_impl("__lt__", op_t.clone(), Const, Private); + self.register_builtin_impl("__le__", op_t.clone(), Const, Private); + self.register_builtin_impl("__gt__", op_t.clone(), Const, Private); + self.register_builtin_impl("__ge__", op_t, Const, Private); + self.register_builtin_impl("__and__", bin_op(Bool, Bool, Bool), Const, Private); + self.register_builtin_impl("__or__", bin_op(Bool, Bool, Bool), Const, Private); let t = mono_q("T"); let op_t = bin_op(t.clone(), t.clone(), range(t.clone())); let op_t = quant(op_t, set! {subtypeof(t.clone(), mono("Ord"))}); - self.register_decl("__rng__", op_t.clone(), Private); - self.register_decl("__lorng__", op_t.clone(), Private); - self.register_decl("__rorng__", op_t.clone(), Private); - self.register_decl("__orng__", op_t, Private); + self.register_builtin_decl("__rng__", op_t.clone(), Private); + self.register_builtin_decl("__lorng__", op_t.clone(), Private); + self.register_builtin_decl("__rorng__", op_t.clone(), Private); + self.register_builtin_decl("__orng__", op_t, Private); // TODO: use existential type: |T: Type| (T, In(T)) -> Bool let op_t = bin_op(mono_q("T"), mono_q("I"), Bool); let op_t = quant( op_t, set! { static_instance("T", Type), subtypeof(mono_q("I"), poly("In", vec![ty_tp(mono_q("T"))])) }, ); - self.register_impl("__in__", op_t, Const, Private); + self.register_builtin_impl("__in__", op_t, Const, Private); /* unary */ // TODO: Boolの+/-は警告を出したい let op_t = func1(mono_q("T"), mono_proj(mono_q("T"), "MutType!")); let op_t = quant(op_t, set! {subtypeof(mono_q("T"), mono("Mutizable"))}); - self.register_impl("__mutate__", op_t, Const, Private); + self.register_builtin_impl("__mutate__", op_t, Const, Private); let n = mono_q("N"); let op_t = func1(n.clone(), n.clone()); let op_t = quant(op_t, set! {subtypeof(n, mono("Num"))}); - self.register_decl("__pos__", op_t.clone(), Private); - self.register_decl("__neg__", op_t, Private); + self.register_builtin_decl("__pos__", op_t.clone(), Private); + self.register_builtin_decl("__neg__", op_t, Private); } fn init_builtin_patches(&mut self) { @@ -1297,19 +1262,19 @@ impl Context { Type::from(&o..=&p), Type::from(m.clone() + o.clone()..=n.clone() + p.clone()), ); - interval.register_impl("__add__", op_t, Const, Public); + interval.register_builtin_impl("__add__", op_t, Const, Public); let op_t = fn1_met( Type::from(&m..=&n), Type::from(&o..=&p), Type::from(m.clone() - p.clone()..=n.clone() - o.clone()), ); - interval.register_impl("__sub__", op_t, Const, Public); - interval.register_const( + interval.register_builtin_impl("__sub__", op_t, Const, Public); + interval.register_builtin_const( "AddO", - ValueObj::t(Type::from(m.clone() + o.clone()..=n.clone() + p.clone())), + ValueObj::builtin_t(Type::from(m.clone() + o.clone()..=n.clone() + p.clone())), ); - interval.register_const("SubO", ValueObj::t(Type::from(m - p..=n - o))); - self.register_patch("Interval", interval, Const); + interval.register_builtin_const("SubO", ValueObj::builtin_t(Type::from(m - p..=n - o))); + self.register_builtin_patch("Interval", interval, Const); // eq.register_impl("__ne__", op_t, Const, Public); // ord.register_impl("__le__", op_t.clone(), Const, Public); // ord.register_impl("__gt__", op_t.clone(), Const, Public); diff --git a/compiler/erg_compiler/context/initialize/py_mods/importlib.rs b/compiler/erg_compiler/context/initialize/py_mods/importlib.rs index 66e7e4b8..d23f8804 100644 --- a/compiler/erg_compiler/context/initialize/py_mods/importlib.rs +++ b/compiler/erg_compiler/context/initialize/py_mods/importlib.rs @@ -12,7 +12,7 @@ use Visibility::*; impl Context { pub(crate) fn init_py_importlib_mod() -> Self { let mut importlib = Context::module("importlib".into(), 15); - importlib.register_impl("reload!", proc1(Module, NoneType), Immutable, Public); + importlib.register_builtin_impl("reload!", proc1(Module, NoneType), Immutable, Public); importlib } } diff --git a/compiler/erg_compiler/context/initialize/py_mods/io.rs b/compiler/erg_compiler/context/initialize/py_mods/io.rs index f7a87bf2..168da4ff 100644 --- a/compiler/erg_compiler/context/initialize/py_mods/io.rs +++ b/compiler/erg_compiler/context/initialize/py_mods/io.rs @@ -14,13 +14,13 @@ impl Context { pub(crate) fn init_py_io_mod() -> Self { let mut io = Context::module("io".into(), 15); let mut string_io = Context::mono_class(Str::ever("StringIO!"), vec![Obj], vec![], 0); - string_io.register_impl( + string_io.register_builtin_impl( "getvalue!", pr0_met(mono("StringIO!"), None, Str), Immutable, Public, ); - io.register_type(mono("StringIO!"), string_io, Const); + io.register_builtin_type(mono("StringIO!"), string_io, Const); io } } diff --git a/compiler/erg_compiler/context/initialize/py_mods/math.rs b/compiler/erg_compiler/context/initialize/py_mods/math.rs index bf40bcf0..0bd63129 100644 --- a/compiler/erg_compiler/context/initialize/py_mods/math.rs +++ b/compiler/erg_compiler/context/initialize/py_mods/math.rs @@ -12,12 +12,12 @@ use Visibility::*; impl Context { pub(crate) fn init_py_math_mod() -> Self { let mut math = Context::module("math".into(), 10); - math.register_impl("pi", Float, Immutable, Public); - math.register_impl("tau", Float, Immutable, Public); - math.register_impl("e", Float, Immutable, Public); - math.register_impl("sin", func1(Float, Float), Immutable, Public); - math.register_impl("cos", func1(Float, Float), Immutable, Public); - math.register_impl("tan", func1(Float, Float), Immutable, Public); + math.register_builtin_impl("pi", Float, Immutable, Public); + math.register_builtin_impl("tau", Float, Immutable, Public); + math.register_builtin_impl("e", Float, Immutable, Public); + math.register_builtin_impl("sin", func1(Float, Float), Immutable, Public); + math.register_builtin_impl("cos", func1(Float, Float), Immutable, Public); + math.register_builtin_impl("tan", func1(Float, Float), Immutable, Public); math } } diff --git a/compiler/erg_compiler/context/initialize/py_mods/random.rs b/compiler/erg_compiler/context/initialize/py_mods/random.rs index ec57add4..09f02e1a 100644 --- a/compiler/erg_compiler/context/initialize/py_mods/random.rs +++ b/compiler/erg_compiler/context/initialize/py_mods/random.rs @@ -15,7 +15,7 @@ use Visibility::*; impl Context { pub(crate) fn init_py_random_mod() -> Self { let mut random = Context::module("random".into(), 10); - random.register_impl( + random.register_builtin_impl( "seed!", proc( vec![], @@ -29,7 +29,7 @@ impl Context { Immutable, Public, ); - random.register_impl( + random.register_builtin_impl( "randint!", nd_proc(vec![param_t("a", Int), param_t("b", Int)], None, Int), Immutable, @@ -41,7 +41,7 @@ impl Context { mono_q("T"), ); let t = quant(t, set! {static_instance("T", Type)}); - random.register_impl("choice!", t, Immutable, Public); + random.register_builtin_impl("choice!", t, Immutable, Public); random } } diff --git a/compiler/erg_compiler/context/initialize/py_mods/socket.rs b/compiler/erg_compiler/context/initialize/py_mods/socket.rs index 20344650..af2e0f1c 100644 --- a/compiler/erg_compiler/context/initialize/py_mods/socket.rs +++ b/compiler/erg_compiler/context/initialize/py_mods/socket.rs @@ -14,7 +14,7 @@ impl Context { pub(crate) fn init_py_socket_mod() -> Self { let mut socket = Context::module("socket".into(), 15); let mut sock = Context::mono_class(Str::ever("Socket!"), vec![Obj], vec![], 0); - sock.register_impl( + sock.register_builtin_impl( "new", func( vec![], @@ -30,7 +30,7 @@ impl Context { Immutable, Public, ); - socket.register_type(mono("Socket!"), sock, Const); + socket.register_builtin_type(mono("Socket!"), sock, Const); socket } } diff --git a/compiler/erg_compiler/context/initialize/py_mods/sys.rs b/compiler/erg_compiler/context/initialize/py_mods/sys.rs index c06b6993..ae36ea30 100644 --- a/compiler/erg_compiler/context/initialize/py_mods/sys.rs +++ b/compiler/erg_compiler/context/initialize/py_mods/sys.rs @@ -13,38 +13,38 @@ use Visibility::*; impl Context { pub(crate) fn init_py_sys_mod() -> Self { let mut sys = Context::module("sys".into(), 15); - sys.register_impl("argv", array(Str, TyParam::erased(Nat)), Immutable, Public); - sys.register_impl("byteorder", Str, Immutable, Public); - sys.register_impl( + sys.register_builtin_impl("argv", array(Str, TyParam::erased(Nat)), Immutable, Public); + sys.register_builtin_impl("byteorder", Str, Immutable, Public); + sys.register_builtin_impl( "builtin_module_names", array(Str, TyParam::erased(Nat)), Immutable, Public, ); - sys.register_impl("copyright", Str, Immutable, Public); - sys.register_impl("executable", Str, Immutable, Public); - sys.register_impl("exit", func1(Int, Never), Immutable, Public); - sys.register_impl("getdefaultencoding", func0(Str), Immutable, Public); - sys.register_impl( + sys.register_builtin_impl("copyright", Str, Immutable, Public); + sys.register_builtin_impl("executable", Str, Immutable, Public); + sys.register_builtin_impl("exit", func1(Int, Never), Immutable, Public); + sys.register_builtin_impl("getdefaultencoding", func0(Str), Immutable, Public); + sys.register_builtin_impl( "path", array_mut(Str, TyParam::erased(Nat)), Immutable, Public, ); - sys.register_impl("platform", Str, Immutable, Public); - sys.register_impl("prefix", Str, Immutable, Public); - sys.register_impl("ps1", mono("Str!"), Immutable, Public); - sys.register_impl("ps2", mono("Str!"), Immutable, Public); - sys.register_impl( + sys.register_builtin_impl("platform", Str, Immutable, Public); + sys.register_builtin_impl("prefix", Str, Immutable, Public); + sys.register_builtin_impl("ps1", mono("Str!"), Immutable, Public); + sys.register_builtin_impl("ps2", mono("Str!"), Immutable, Public); + sys.register_builtin_impl( "setrecursionlimit!", proc1(Int, NoneType), Immutable, Public, ); - sys.register_impl("stderr", mono("TextIOWrapper!"), Immutable, Public); - sys.register_impl("stdin", mono("TextIOWrapper!"), Immutable, Public); - sys.register_impl("stdout", mono("TextIOWrapper!"), Immutable, Public); - sys.register_impl("version", Str, Immutable, Public); + sys.register_builtin_impl("stderr", mono("TextIOWrapper!"), Immutable, Public); + sys.register_builtin_impl("stdin", mono("TextIOWrapper!"), Immutable, Public); + sys.register_builtin_impl("stdout", mono("TextIOWrapper!"), Immutable, Public); + sys.register_builtin_impl("version", Str, Immutable, Public); sys } } diff --git a/compiler/erg_compiler/context/initialize/py_mods/time.rs b/compiler/erg_compiler/context/initialize/py_mods/time.rs index 4609eb0d..7b91ef9b 100644 --- a/compiler/erg_compiler/context/initialize/py_mods/time.rs +++ b/compiler/erg_compiler/context/initialize/py_mods/time.rs @@ -12,8 +12,8 @@ use Visibility::*; impl Context { pub(crate) fn init_py_time_mod() -> Self { let mut time = Context::module("time".into(), 15); - time.register_impl("sleep!", proc1(Float, NoneType), Immutable, Public); - time.register_impl("time!", proc0(Float), Immutable, Public); + time.register_builtin_impl("sleep!", proc1(Float, NoneType), Immutable, Public); + time.register_builtin_impl("time!", proc0(Float), Immutable, Public); time } } diff --git a/compiler/erg_compiler/context/inquire.rs b/compiler/erg_compiler/context/inquire.rs index 27859287..f1474947 100644 --- a/compiler/erg_compiler/context/inquire.rs +++ b/compiler/erg_compiler/context/inquire.rs @@ -17,7 +17,7 @@ use erg_parser::token::Token; use erg_type::constructors::{func, mono, mono_proj, poly, ref_, ref_mut, refinement, subr_t}; use erg_type::free::Constraint; use erg_type::typaram::TyParam; -use erg_type::value::ValueObj; +use erg_type::value::{TypeObj, ValueObj}; use erg_type::{HasType, ParamTy, SubrKind, SubrType, TyBound, Type}; use crate::context::instantiate::ConstTemplate; @@ -224,7 +224,7 @@ impl Context { namespace: &Str, ) -> TyCheckResult { let self_t = obj.t(); - match self.get_attr_t_from_t(obj, &self_t, name, namespace) { + match self.get_attr_t_from_attributive_t(obj, &self_t, name, namespace) { Ok(t) => { return Ok(t); } @@ -253,7 +253,7 @@ impl Context { } } - fn get_attr_t_from_t( + fn get_attr_t_from_attributive_t( &self, obj: &hir::Expr, t: &Type, @@ -261,11 +261,19 @@ impl Context { namespace: &Str, ) -> TyCheckResult { match t { - Type => todo!(), Type::FreeVar(fv) if fv.is_linked() => { - self.get_attr_t_from_t(obj, &fv.crack(), name, namespace) + self.get_attr_t_from_attributive_t(obj, &fv.crack(), name, namespace) + } + Type::FreeVar(fv) => { + let sup = fv.get_sup().unwrap(); + self.get_attr_t_from_attributive_t(obj, &sup, name, namespace) + } + Type::Ref(t) | Type::RefMut(t) => { + self.get_attr_t_from_attributive_t(obj, t, name, namespace) + } + Type::Refinement(refine) => { + self.get_attr_t_from_attributive_t(obj, &refine.t, name, namespace) } - Type::Refinement(refine) => self.get_attr_t_from_t(obj, &refine.t, name, namespace), Type::Record(record) => { // REVIEW: `rec.get(name.inspect())` returns None (Borrow is implemented for Field). Why? if let Some(attr) = record.get(&Field::new(Public, name.inspect().clone())) { @@ -287,7 +295,20 @@ impl Context { let t = mod_ctx.rec_get_var_t(name, Public, namespace)?; Ok(t) } - _ => Err(TyCheckError::dummy(line!() as usize)), + other => { + if let Some(v) = self.rec_get_const_obj(&other.name()) { + match v { + ValueObj::Type(TypeObj::Generated(gen)) => gen + .get_require_attr_t(&name.inspect()[..]) + .map(|t| t.clone()) + .ok_or(TyCheckError::dummy(line!() as usize)), + ValueObj::Type(TypeObj::Builtin(t)) => todo!("{t}"), + other => todo!("{other}"), + } + } else { + Err(TyCheckError::dummy(line!() as usize)) + } + } } } @@ -753,7 +774,7 @@ impl Context { ) -> TyCheckResult { match obj { hir::Expr::Accessor(hir::Accessor::Local(local)) if &local.inspect()[..] == "match" => { - return self.get_match_call_t(pos_args, kw_args) + return self.get_match_call_t(pos_args, kw_args); } _ => {} } @@ -1021,33 +1042,48 @@ impl Context { ) -> Option<(&'a Type, &'a Context)> { match typ { Type::FreeVar(fv) if fv.is_linked() => { - return self.rec_get_nominal_type_ctx(&fv.crack()); + if let Some(res) = self.rec_get_nominal_type_ctx(&fv.crack()) { + return Some(res); + } } Type::FreeVar(fv) => { - let sup = fv.crack_sup()?; - return self.rec_get_nominal_type_ctx(&sup); + let sup = fv.get_sup().unwrap(); + if let Some(res) = self.rec_get_nominal_type_ctx(&sup) { + return Some(res); + } } Type::Refinement(refine) => { - return self.rec_get_nominal_type_ctx(&refine.t); + if let Some(res) = self.rec_get_nominal_type_ctx(&refine.t) { + return Some(res); + } } Type::Quantified(_) => { - return self.rec_get_nominal_type_ctx(&mono("QuantifiedFunction")); + if let Some(res) = self.rec_get_nominal_type_ctx(&mono("QuantifiedFunction")) { + return Some(res); + } } Type::Poly { name, params: _ } => { - if let Some((t, ctx)) = self.poly_types.get(name) { + if let Some((t, ctx)) = self.rec_get_poly_type(name) { return Some((t, ctx)); } } Type::Record(rec) if rec.values().all(|attr| self.supertype_of(&Type, attr)) => { - return self.rec_get_nominal_type_ctx(&Type) + // TODO: reference RecordType (inherits Type) + if let Some(res) = self.rec_get_nominal_type_ctx(&Type) { + return Some(res); + } } // FIXME: `F()`などの場合、実際は引数が省略されていてもmonomorphicになる other if other.is_monomorphic() => { - if let Some((t, ctx)) = self.mono_types.get(&typ.name()) { + if let Some((t, ctx)) = self.rec_get_mono_type(&other.name()) { return Some((t, ctx)); } } - Type::Ref(t) | Type::RefMut(t) => return self.rec_get_nominal_type_ctx(t), + Type::Ref(t) | Type::RefMut(t) => { + if let Some(res) = self.rec_get_nominal_type_ctx(t) { + return Some(res); + } + } other => todo!("{other}"), } if let Some(outer) = &self.outer { @@ -1119,9 +1155,8 @@ impl Context { pub(crate) fn rec_get_const_param_defaults(&self, name: &str) -> Option<&Vec> { if let Some(impls) = self.const_param_defaults.get(name) { - return Some(impls); - } - if let Some(outer) = &self.outer { + Some(impls) + } else if let Some(outer) = &self.outer { outer.rec_get_const_param_defaults(name) } else { None @@ -1147,4 +1182,24 @@ impl Context { } } } + + fn rec_get_mono_type(&self, name: &str) -> Option<(&Type, &Context)> { + if let Some((t, ctx)) = self.mono_types.get(name) { + Some((t, ctx)) + } else if let Some(outer) = &self.outer { + outer.rec_get_mono_type(name) + } else { + None + } + } + + fn rec_get_poly_type(&self, name: &str) -> Option<(&Type, &Context)> { + if let Some((t, ctx)) = self.poly_types.get(name) { + Some((t, ctx)) + } else if let Some(outer) = &self.outer { + outer.rec_get_poly_type(name) + } else { + None + } + } } diff --git a/compiler/erg_compiler/context/register.rs b/compiler/erg_compiler/context/register.rs index 881d2179..dcb556d3 100644 --- a/compiler/erg_compiler/context/register.rs +++ b/compiler/erg_compiler/context/register.rs @@ -9,12 +9,12 @@ use erg_type::free::HasLevel; use ast::{DefId, VarName}; use erg_parser::ast; -use erg_type::constructors::{enum_t, func, proc, ref_, ref_mut}; -use erg_type::value::ValueObj; +use erg_type::constructors::{enum_t, func, func1, proc, ref_, ref_mut}; +use erg_type::value::{GenTypeObj, TypeKind, TypeObj, ValueObj}; use erg_type::{HasType, ParamTy, SubrType, TyBound, Type}; use Type::*; -use crate::context::{Context, DefaultInfo, RegistrationMode}; +use crate::context::{Context, DefaultInfo, RegistrationMode, TraitInstance}; use crate::error::readable_name; use crate::error::{TyCheckError, TyCheckResult}; use crate::hir; @@ -446,7 +446,7 @@ impl Context { let spec_t = self.instantiate_typespec(spec, PreRegister)?; self.sub_unify(&const_t, &spec_t, Some(def.body.loc()), None, None)?; } - self.register_const(__name__.unwrap(), obj); + self.register_gen_const(__name__.unwrap(), obj); } else { let opt_ret_t = if let Some(spec) = sig.return_t_spec.as_ref() { let spec_t = self.instantiate_typespec(spec, PreRegister)?; @@ -468,13 +468,127 @@ impl Context { let spec_t = self.instantiate_typespec(spec, PreRegister)?; self.sub_unify(&const_t, &spec_t, Some(def.body.loc()), None, None)?; } - self.register_const(__name__.unwrap(), obj); + self.register_gen_const(__name__.unwrap(), obj); } _ => {} } Ok(()) } + fn _register_gen_decl(&mut self, name: &'static str, t: Type, vis: Visibility) { + let name = VarName::from_static(name); + if self.decls.get(&name).is_some() { + panic!("already registered: {name}"); + } else { + self.decls + .insert(name, VarInfo::new(t, Immutable, vis, VarKind::Declared)); + } + } + + fn register_gen_impl( + &mut self, + name: &'static str, + t: Type, + muty: Mutability, + vis: Visibility, + ) { + let name = VarName::from_static(name); + if self.locals.get(&name).is_some() { + panic!("already registered: {name}"); + } else { + let id = DefId(get_hash(&(&self.name, &name))); + self.locals + .insert(name, VarInfo::new(t, muty, vis, VarKind::Defined(id))); + } + } + + pub(crate) fn register_gen_const(&mut self, name: &Str, obj: ValueObj) { + if self.rec_get_const_obj(name).is_some() { + panic!("already registered: {name}"); + } else { + match obj { + ValueObj::Type(t) => { + let gen = enum_unwrap!(t, TypeObj::Generated); + self.register_gen_type(gen); + } + other => { + let id = DefId(get_hash(name)); + let vi = VarInfo::new( + enum_t(set! {other.clone()}), + Const, + Private, + VarKind::Defined(id), + ); + self.consts.insert(VarName::from_str(Str::rc(name)), other); + self.locals.insert(VarName::from_str(Str::rc(name)), vi); + } + } + } + } + + fn register_gen_type(&mut self, gen: GenTypeObj) { + match gen.kind { + TypeKind::Class => { + if gen.t.is_monomorphic() { + let super_traits = gen.impls.iter().map(|to| to.typ().clone()).collect(); + let mut ctx = Self::mono_class(gen.t.name(), vec![], super_traits, self.level); + let require = gen.require_or_sup.typ().clone(); + let new_t = func1(require, gen.t.clone()); + ctx.register_gen_impl("__new__", new_t, Immutable, Private); + self.register_gen_mono_type(gen, ctx, Const); + } else { + todo!() + } + } + TypeKind::InheritedClass => { + 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(); + let mut ctx = + Self::mono_class(gen.t.name(), super_classes, super_traits, self.level); + let sup = gen.require_or_sup.typ().clone(); + let new_t = func1(sup, gen.t.clone()); + ctx.register_gen_impl("__new__", new_t, Immutable, Private); + self.register_gen_mono_type(gen, ctx, Const); + } else { + todo!() + } + } + other => todo!("{other:?}"), + } + } + + fn register_gen_mono_type(&mut self, gen: GenTypeObj, ctx: Self, muty: Mutability) { + // FIXME: not panic but error + // FIXME: recursive search + if self.mono_types.contains_key(&gen.t.name()) { + panic!("{} has already been registered", gen.t.name()); + } else if self.rec_get_const_obj(&gen.t.name()).is_some() { + panic!("{} has already been registered as const", gen.t.name()); + } else { + let t = gen.t.clone(); + let name = VarName::from_str(gen.t.name()); + let id = DefId(get_hash(&(&self.name, &name))); + self.locals.insert( + name.clone(), + VarInfo::new(Type, muty, Private, VarKind::Defined(id)), + ); + self.consts + .insert(name.clone(), ValueObj::Type(TypeObj::Generated(gen))); + for impl_trait in ctx.super_traits.iter() { + if let Some(impls) = self.trait_impls.get_mut(&impl_trait.name()) { + impls.push(TraitInstance::new(t.clone(), impl_trait.clone())); + } else { + self.trait_impls.insert( + impl_trait.name(), + vec![TraitInstance::new(t.clone(), impl_trait.clone())], + ); + } + } + self.mono_types.insert(name, (t, ctx)); + } + } + pub(crate) fn import_mod( &mut self, var_name: &VarName, diff --git a/compiler/erg_compiler/eval.rs b/compiler/erg_compiler/eval.rs index 81359a45..1b62adf6 100644 --- a/compiler/erg_compiler/eval.rs +++ b/compiler/erg_compiler/eval.rs @@ -271,7 +271,7 @@ impl Context { let __name__ = def.sig.ident().map(|i| i.inspect()).unwrap(); let obj = self.eval_const_block(&def.body.block, Some(__name__))?; erg_common::log!(); - self.register_const(__name__, obj); + self.register_gen_const(__name__, obj); Ok(ValueObj::None) } else { Err(EvalError::not_const_expr( diff --git a/compiler/erg_type/value.rs b/compiler/erg_type/value.rs index 9bfd0686..94e4b850 100644 --- a/compiler/erg_type/value.rs +++ b/compiler/erg_type/value.rs @@ -63,19 +63,33 @@ impl GenTypeObj { additional: additional.map(Box::new), } } + + pub fn get_require_attr_t(&self, attr: &str) -> Option<&Type> { + if let Type::Record(rec) = &self.require_or_sup.typ() { + rec.get(attr) + } else if let Some(additional) = &self.additional { + if let Type::Record(gen) = additional.typ() { + gen.get(attr) + } else { + None + } + } else { + None + } + } } #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub enum TypeObj { Builtin(Type), - Gen(GenTypeObj), + Generated(GenTypeObj), } impl fmt::Display for TypeObj { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { TypeObj::Builtin(t) => write!(f, "{t}"), - TypeObj::Gen(t) => write!(f, "{t}"), + TypeObj::Generated(t) => write!(f, "{t}"), } } } @@ -84,7 +98,14 @@ impl TypeObj { pub const fn typ(&self) -> &Type { match self { TypeObj::Builtin(t) => t, - TypeObj::Gen(t) => &t.t, + TypeObj::Generated(t) => &t.t, + } + } + + pub fn get_require_attr_t(&self, attr: &str) -> Option<&Type> { + match self { + TypeObj::Builtin(_t) => None, + TypeObj::Generated(gen) => gen.get_require_attr_t(attr), } } } @@ -329,7 +350,7 @@ impl HasType for ValueObj { } impl ValueObj { - pub fn t(t: Type) -> Self { + pub fn builtin_t(t: Type) -> Self { ValueObj::Type(TypeObj::Builtin(t)) } @@ -340,7 +361,7 @@ impl ValueObj { impls: Option, additional: Option, ) -> Self { - ValueObj::Type(TypeObj::Gen(GenTypeObj::new( + ValueObj::Type(TypeObj::Generated(GenTypeObj::new( kind, t, require_or_sup, From 4a8572a9fe5c1db99d445d07f5c6fba7174ee5da Mon Sep 17 00:00:00 2001 From: Shunsuke Shibayama Date: Mon, 5 Sep 2022 21:55:16 +0900 Subject: [PATCH 23/68] Fix type inference imcompleteness Add intersection type inference --- compiler/erg_common/macros.rs | 3 + compiler/erg_compiler/context/compare.rs | 85 +++++++++++----- compiler/erg_compiler/context/inquire.rs | 119 +++++++++++++++------- compiler/erg_compiler/context/mod.rs | 8 ++ compiler/erg_compiler/context/register.rs | 27 ++++- compiler/erg_compiler/context/tyvar.rs | 21 ++-- compiler/erg_compiler/eval.rs | 6 +- compiler/erg_type/lib.rs | 20 +--- compiler/erg_type/value.rs | 21 ---- 9 files changed, 193 insertions(+), 117 deletions(-) diff --git a/compiler/erg_common/macros.rs b/compiler/erg_common/macros.rs index da3b5ba2..a6b715b4 100644 --- a/compiler/erg_common/macros.rs +++ b/compiler/erg_common/macros.rs @@ -87,6 +87,9 @@ macro_rules! enum_unwrap { ($ex: expr, $Enum: path :( $Cons: path :(_) ) $(,)*) => {{ if let $Enum($Cons(res)) = $ex { res } else { $crate::switch_unreachable!() } }}; + ($ex: expr, $Enum: path :( $Cons: path :( $Cons2: path :(_) ) ) $(,)*) => {{ + if let $Enum($Cons($Cons2(res))) = $ex { res } else { $crate::switch_unreachable!() } + }}; // X::A{a, b} ($ex: expr, $Enum: path {$($fields: ident $(,)*)*}) => {{ if let $Enum{$($fields,)*} = $ex { ($($fields,)*) } else { $crate::switch_unreachable!() } diff --git a/compiler/erg_compiler/context/compare.rs b/compiler/erg_compiler/context/compare.rs index 07c71039..1e7ede79 100644 --- a/compiler/erg_compiler/context/compare.rs +++ b/compiler/erg_compiler/context/compare.rs @@ -1,7 +1,7 @@ //! provides type-comparison use std::option::Option; // conflicting to Type::Option -use erg_type::constructors::or; +use erg_type::constructors::{and, or}; use erg_type::free::fresh_varname; use erg_type::free::{Constraint, Cyclicity, FreeKind, FreeTyVar}; use erg_type::typaram::{TyParam, TyParamOrdering}; @@ -260,7 +260,7 @@ impl Context { } _ => {} } - match self.classsupertype_of(lhs, rhs) { + match self.traits_supertype_of(lhs, rhs) { (Absolutely, judge) => { self.register_cache(rhs, lhs, judge); return judge; @@ -294,17 +294,19 @@ impl Context { } fn classes_supertype_of(&self, lhs: &Type, rhs: &Type) -> (Credibility, bool) { - for (rhs_sup, _) in self.rec_get_nominal_super_class_ctxs(rhs) { - match self.cheap_supertype_of(lhs, rhs_sup) { - (Absolutely, true) => { - return (Absolutely, true); - } - (Maybe, _) => { - if self.structural_supertype_of(lhs, rhs_sup) { + if let Some(sup_classes) = self.rec_get_nominal_super_class_ctxs(rhs) { + for (rhs_sup, _) in sup_classes { + match self.cheap_supertype_of(lhs, rhs_sup) { + (Absolutely, true) => { return (Absolutely, true); } + (Maybe, _) => { + if self.structural_supertype_of(lhs, rhs_sup) { + return (Absolutely, true); + } + } + _ => {} } - _ => {} } } (Maybe, false) @@ -312,19 +314,21 @@ impl Context { // e.g. Eq(Nat) :> Nat // Nat.super_traits = [Add(Nat), Eq(Nat), ...] - fn classsupertype_of(&self, lhs: &Type, rhs: &Type) -> (Credibility, bool) { - for (rhs_sup, _) in self.rec_get_nominal_super_classctxs(rhs) { - match self.cheap_supertype_of(lhs, rhs_sup) { - (Absolutely, true) => { - return (Absolutely, true); - } - (Maybe, _) => { - // nominal type同士の比較なので、nominal_supertype_ofは使わない - if self.structural_supertype_of(lhs, rhs_sup) { + fn traits_supertype_of(&self, lhs: &Type, rhs: &Type) -> (Credibility, bool) { + if let Some(sup_traits) = self.rec_get_nominal_super_trait_ctxs(rhs) { + for (rhs_sup, _) in sup_traits { + match self.cheap_supertype_of(lhs, rhs_sup) { + (Absolutely, true) => { return (Absolutely, true); } + (Maybe, _) => { + // nominal type同士の比較なので、nominal_supertype_ofは使わない + if self.structural_supertype_of(lhs, rhs_sup) { + return (Absolutely, true); + } + } + _ => {} } - _ => {} } } (Maybe, false) @@ -609,15 +613,18 @@ impl Context { pub(crate) fn cyclic_supertype_of(&self, lhs: &FreeTyVar, rhs: &Type) -> bool { // if `rhs` is {S: Str | ... }, `defined_rhs` will be Str let (defined_rhs, _) = self.rec_get_nominal_type_ctx(rhs).unwrap(); - let super_traits = self.rec_get_nominal_super_classctxs(rhs); - for (sup_trait, _) in super_traits.into_iter() { - if self.sup_conforms(lhs, defined_rhs, sup_trait) { - return true; + if let Some(super_traits) = self.rec_get_nominal_super_trait_ctxs(rhs) { + for (sup_trait, _) in super_traits { + if self.sup_conforms(lhs, defined_rhs, sup_trait) { + return true; + } } } - for (sup_class, _) in self.rec_get_nominal_super_class_ctxs(rhs) { - if self.cyclic_supertype_of(lhs, sup_class) { - return true; + if let Some(sup_classes) = self.rec_get_nominal_super_class_ctxs(rhs) { + for (sup_class, _) in sup_classes { + if self.cyclic_supertype_of(lhs, sup_class) { + return true; + } } } false @@ -762,7 +769,7 @@ impl Context { } } - /// 和集合(A or B)を返す + /// returns union of two types (A or B) pub(crate) fn rec_union(&self, lhs: &Type, rhs: &Type) -> Type { match ( self.rec_supertype_of(lhs, rhs), @@ -804,6 +811,28 @@ impl Context { } } + /// returns intersection of two types (A and B) + pub(crate) fn rec_intersection(&self, lhs: &Type, rhs: &Type) -> Type { + match ( + self.rec_supertype_of(lhs, rhs), + self.rec_subtype_of(lhs, rhs), + ) { + (true, true) => return lhs.clone(), // lhs = rhs + (true, false) => return rhs.clone(), // lhs :> rhs + (false, true) => return lhs.clone(), + (false, false) => {} + } + match (lhs, rhs) { + /*(Type::FreeVar(_), _) | (_, Type::FreeVar(_)) => { + todo!() + }*/ + // {.i = Int} and {.s = Str} == {.i = Int; .s = Str} + (Type::Record(l), Type::Record(r)) => Type::Record(l.clone().concat(r.clone())), + (l, r) if self.is_trait(l) && self.is_trait(r) => and(l.clone(), r.clone()), + (_l, _r) => Type::Never, + } + } + /// see doc/LANG/compiler/refinement_subtyping.md /// ```erg /// assert is_super_pred({I >= 0}, {I == 0}) diff --git a/compiler/erg_compiler/context/inquire.rs b/compiler/erg_compiler/context/inquire.rs index f1474947..22809fc3 100644 --- a/compiler/erg_compiler/context/inquire.rs +++ b/compiler/erg_compiler/context/inquire.rs @@ -17,7 +17,7 @@ use erg_parser::token::Token; use erg_type::constructors::{func, mono, mono_proj, poly, ref_, ref_mut, refinement, subr_t}; use erg_type::free::Constraint; use erg_type::typaram::TyParam; -use erg_type::value::{TypeObj, ValueObj}; +use erg_type::value::{GenTypeObj, TypeObj, ValueObj}; use erg_type::{HasType, ParamTy, SubrKind, SubrType, TyBound, Type}; use crate::context::instantiate::ConstTemplate; @@ -233,7 +233,10 @@ impl Context { return Err(e); } } - for (_, ctx) in self.rec_get_nominal_super_type_ctxs(&self_t) { + for (_, ctx) in self + .rec_get_nominal_super_type_ctxs(&self_t) + .ok_or_else(|| todo!())? + { if let Ok(t) = ctx.rec_get_var_t(name, Public, namespace) { return Ok(t); } @@ -298,8 +301,8 @@ impl Context { other => { if let Some(v) = self.rec_get_const_obj(&other.name()) { match v { - ValueObj::Type(TypeObj::Generated(gen)) => gen - .get_require_attr_t(&name.inspect()[..]) + ValueObj::Type(TypeObj::Generated(gen)) => self + .get_gen_t_require_attr_t(gen, &name.inspect()[..]) .map(|t| t.clone()) .ok_or(TyCheckError::dummy(line!() as usize)), ValueObj::Type(TypeObj::Builtin(t)) => todo!("{t}"), @@ -320,7 +323,10 @@ impl Context { namespace: &Str, ) -> TyCheckResult { if let Some(method_name) = method_name.as_ref() { - for (_, ctx) in self.rec_get_nominal_super_type_ctxs(obj.ref_t()) { + for (_, ctx) in self + .rec_get_nominal_super_type_ctxs(obj.ref_t()) + .ok_or_else(|| todo!())? + { if let Some(vi) = ctx.locals.get(method_name.inspect()) { return Ok(vi.t()); } else if let Some(vi) = ctx.decls.get(method_name.inspect()) { @@ -825,7 +831,10 @@ impl Context { namespace: &Str, ) -> TyCheckResult { let self_t = obj.ref_t(); - for (_, ctx) in self.rec_get_nominal_super_type_ctxs(self_t) { + for (_, ctx) in self + .rec_get_nominal_super_type_ctxs(self_t) + .ok_or_else(|| todo!())? + { if let Ok(t) = ctx.get_const_local(name, namespace) { return Ok(t); } @@ -881,7 +890,7 @@ impl Context { } pub(crate) fn get_similar_attr<'a>(&'a self, self_t: &'a Type, name: &str) -> Option<&'a Str> { - for (_, ctx) in self.rec_get_nominal_super_type_ctxs(self_t) { + for (_, ctx) in self.rec_get_nominal_super_type_ctxs(self_t)? { if let Some(name) = ctx.get_similar_name(name) { return Some(name); } @@ -988,52 +997,45 @@ impl Context { concatenated } - pub(crate) fn rec_get_nominal_super_classctxs<'a>( + pub(crate) fn rec_get_nominal_super_trait_ctxs<'a>( &'a self, t: &Type, - ) -> impl Iterator { - if let Some((_ctx_t, ctx)) = self.rec_get_nominal_type_ctx(t) { - ctx.super_traits.iter().map(|sup| { - let (_t, sup_ctx) = self.rec_get_nominal_type_ctx(sup).unwrap(); - (sup, sup_ctx) - }) - } else { - todo!("{t} has no trait, or not a nominal type") - } + ) -> Option> { + let (_ctx_t, ctx) = self.rec_get_nominal_type_ctx(t)?; + Some(ctx.super_traits.iter().map(|sup| { + let (_t, sup_ctx) = self.rec_get_nominal_type_ctx(sup).unwrap(); + (sup, sup_ctx) + })) } pub(crate) fn rec_get_nominal_super_class_ctxs<'a>( &'a self, t: &Type, - ) -> impl Iterator { + ) -> Option> { // if `t` is {S: Str | ...}, `ctx_t` will be Str // else if `t` is Array(Int, 10), `ctx_t` will be Array(T, N) (if Array(Int, 10) is not specialized) - if let Some((_ctx_t, ctx)) = self.rec_get_nominal_type_ctx(t) { - // t: {S: Str | ...} => ctx.super_traits: [Eq(Str), Mul(Nat), ...] - // => return: [(Str, Eq(Str)), (Str, Mul(Nat)), ...] (the content of &'a Type isn't {S: Str | ...}) - ctx.super_classes.iter().map(|sup| { - let (_t, sup_ctx) = self.rec_get_nominal_type_ctx(sup).unwrap(); - (sup, sup_ctx) - }) - } else { - todo!("{t} has no class, or not a nominal type") - } + let (_ctx_t, ctx) = self.rec_get_nominal_type_ctx(t)?; + // t: {S: Str | ...} => ctx.super_traits: [Eq(Str), Mul(Nat), ...] + // => return: [(Str, Eq(Str)), (Str, Mul(Nat)), ...] (the content of &'a Type isn't {S: Str | ...}) + Some(ctx.super_classes.iter().map(|sup| { + let (_t, sup_ctx) = self.rec_get_nominal_type_ctx(sup).unwrap(); + (sup, sup_ctx) + })) } pub(crate) fn rec_get_nominal_super_type_ctxs<'a>( &'a self, t: &Type, - ) -> impl Iterator { - if let Some((t, ctx)) = self.rec_get_nominal_type_ctx(t) { + ) -> Option> { + let (t, ctx) = self.rec_get_nominal_type_ctx(t)?; + Some( vec![(t, ctx)].into_iter().chain( ctx.super_classes .iter() .chain(ctx.super_traits.iter()) .map(|sup| self.rec_get_nominal_type_ctx(&sup).unwrap()), - ) - } else { - todo!("{t} not found") - } + ), + ) } pub(crate) fn rec_get_nominal_type_ctx<'a>( @@ -1067,12 +1069,12 @@ impl Context { return Some((t, ctx)); } } - Type::Record(rec) if rec.values().all(|attr| self.supertype_of(&Type, attr)) => { + /*Type::Record(rec) if rec.values().all(|attr| self.supertype_of(&Type, attr)) => { // TODO: reference RecordType (inherits Type) if let Some(res) = self.rec_get_nominal_type_ctx(&Type) { return Some(res); } - } + }*/ // FIXME: `F()`などの場合、実際は引数が省略されていてもmonomorphicになる other if other.is_monomorphic() => { if let Some((t, ctx)) = self.rec_get_mono_type(&other.name()) { @@ -1084,7 +1086,9 @@ impl Context { return Some(res); } } - other => todo!("{other}"), + other => { + log!("{other} has no nominal definition"); + } } if let Some(outer) = &self.outer { outer.rec_get_nominal_type_ctx(typ) @@ -1202,4 +1206,45 @@ impl Context { None } } + + fn get_gen_t_require_attr_t<'a>(&'a self, gen: &'a GenTypeObj, attr: &str) -> Option<&'a Type> { + match gen.require_or_sup.typ() { + Type::Record(rec) => { + if let Some(t) = rec.get(attr) { + return Some(t); + } + } + other => { + let obj = self.rec_get_const_obj(&other.name()); + let obj = enum_unwrap!(obj, Some:(ValueObj::Type:(TypeObj::Generated:(_)))); + if let Some(t) = self.get_gen_t_require_attr_t(obj, attr) { + return Some(t); + } + } + } + if let Some(additional) = &gen.additional { + if let Type::Record(gen) = additional.typ() { + if let Some(t) = gen.get(attr) { + return Some(t); + } + } + } + None + } + + pub(crate) fn _is_class(&self, typ: &Type) -> bool { + if let Some((_, ctx)) = self.rec_get_nominal_type_ctx(typ) { + ctx.kind.is_class() + } else { + todo!() + } + } + + pub(crate) fn is_trait(&self, typ: &Type) -> bool { + if let Some((_, ctx)) = self.rec_get_nominal_type_ctx(typ) { + ctx.kind.is_trait() + } else { + todo!() + } + } } diff --git a/compiler/erg_compiler/context/mod.rs b/compiler/erg_compiler/context/mod.rs index aa42b301..dedc8c8e 100644 --- a/compiler/erg_compiler/context/mod.rs +++ b/compiler/erg_compiler/context/mod.rs @@ -211,6 +211,14 @@ impl ContextKind { pub const fn is_type(&self) -> bool { matches!(self, Self::Class | Self::Trait | Self::StructuralTrait) } + + pub fn is_class(&self) -> bool { + matches!(self, Self::Class) + } + + pub fn is_trait(&self) -> bool { + matches!(self, Self::Trait | Self::StructuralTrait) + } } /// 記号表に登録されているモードを表す diff --git a/compiler/erg_compiler/context/register.rs b/compiler/erg_compiler/context/register.rs index dcb556d3..eb0460bc 100644 --- a/compiler/erg_compiler/context/register.rs +++ b/compiler/erg_compiler/context/register.rs @@ -534,7 +534,9 @@ impl Context { let mut ctx = Self::mono_class(gen.t.name(), vec![], super_traits, self.level); let require = gen.require_or_sup.typ().clone(); let new_t = func1(require, gen.t.clone()); - ctx.register_gen_impl("__new__", new_t, Immutable, Private); + ctx.register_gen_impl("__new__", new_t.clone(), Immutable, Private); + // 必要なら、ユーザーが独自に上書きする + ctx.register_gen_impl("new", new_t, Immutable, Public); self.register_gen_mono_type(gen, ctx, Const); } else { todo!() @@ -546,10 +548,25 @@ impl Context { let super_traits = gen.impls.iter().map(|to| to.typ().clone()).collect(); let mut ctx = Self::mono_class(gen.t.name(), super_classes, super_traits, self.level); - let sup = gen.require_or_sup.typ().clone(); - let new_t = func1(sup, gen.t.clone()); - ctx.register_gen_impl("__new__", new_t, Immutable, Private); - self.register_gen_mono_type(gen, ctx, Const); + if let Some(sup) = self.rec_get_const_obj(&gen.require_or_sup.typ().name()) { + let sup = enum_unwrap!(sup, ValueObj::Type); + let param_t = match sup { + TypeObj::Builtin(t) => t, + TypeObj::Generated(t) => t.require_or_sup.as_ref().typ(), + }; + let param_t = if let Some(additional) = &gen.additional { + self.rec_intersection(¶m_t, additional.typ()) + } else { + param_t.clone() + }; + let new_t = func1(param_t, gen.t.clone()); + ctx.register_gen_impl("__new__", new_t.clone(), Immutable, Private); + // 必要なら、ユーザーが独自に上書きする + ctx.register_gen_impl("new", new_t, Immutable, Public); + self.register_gen_mono_type(gen, ctx, Const); + } else { + todo!("super class not found") + } } else { todo!() } diff --git a/compiler/erg_compiler/context/tyvar.rs b/compiler/erg_compiler/context/tyvar.rs index d7ef9e8a..90422c89 100644 --- a/compiler/erg_compiler/context/tyvar.rs +++ b/compiler/erg_compiler/context/tyvar.rs @@ -939,7 +939,7 @@ impl Context { /// sub_unify({I: Int | I == 0}, ?T(<: Ord)): (/* OK */) /// sub_unify(Int, ?T(:> Nat)): (?T :> Int) /// sub_unify(Nat, ?T(:> Int)): (/* OK */) - /// sub_unify(Nat, Add(?R, ?O)): (?R => Nat, ?O => Nat) + /// sub_unify(Nat, Add(?R)): (?R => Nat, Nat.AddO => Nat) /// sub_unify([?T; 0], Mutate): (/* OK */) /// ``` pub(crate) fn sub_unify( @@ -981,7 +981,8 @@ impl Context { // lfvのsupは縮小可能(minを取る)、rfvのsubは拡大可能(unionを取る) // sub_unify(?T[0](:> Never, <: Int), ?U[1](:> Never, <: Nat)): (/* ?U[1] --> ?T[0](:> Never, <: Nat)) // sub_unify(?T[1](:> Never, <: Nat), ?U[0](:> Never, <: Int)): (/* ?T[1] --> ?U[0](:> Never, <: Nat)) - // sub_unify(?T[0](:> Never, <: Str), ?U[1](:> Never, <: Int)): (/* Error */) + // sub_unify(?T[0](:> Never, <: Str), ?U[1](:> Never, <: Int)): (?T[0](:> Never, <: Str and Int) --> Error!) + // sub_unify(?T[0](:> Int, <: Add()), ?U[1](:> Never, <: Mul())): (?T[0](:> Int, <: Add() and Mul())) // sub_unify(?T[0](:> Str, <: Obj), ?U[1](:> Int, <: Obj)): (/* ?U[1] --> ?T[0](:> Str or Int) */) (Type::FreeVar(lfv), Type::FreeVar(rfv)) if lfv.constraint_is_sandwiched() && rfv.constraint_is_sandwiched() => @@ -991,10 +992,18 @@ impl Context { let (rsub, rsup) = rfv.get_bound_types().unwrap(); let r_cyc = rfv.cyclicity(); let cyclicity = l_cyc.combine(r_cyc); - let new_constraint = if let Some(min) = self.min(&lsup, &rsup) { - Constraint::new_sandwiched(self.rec_union(&lsub, &rsub), min.clone(), cyclicity) + let intersec = self.rec_intersection(&lsup, &rsup); + let new_constraint = if intersec != Type::Never { + Constraint::new_sandwiched(self.rec_union(&lsub, &rsub), intersec, cyclicity) } else { - todo!() + return Err(TyCheckError::subtyping_error( + line!() as usize, + maybe_sub, + maybe_sup, + sub_loc, + sup_loc, + self.caused_by(), + )); }; if lfv.level().unwrap() <= rfv.level().unwrap() { lfv.update_constraint(new_constraint); @@ -1019,7 +1028,7 @@ impl Context { // sub = max(l, sub) if max exists // * sub_unify(Nat, ?T(:> Int, <: _)): (/* OK */) // * sub_unify(Int, ?T(:> Nat, <: Obj)): (?T(:> Int, <: Obj)) - // * sub_unify(Nat, ?T(:> Never, <: Add(?R, ?O))): (?T(:> Nat, <: Add(?R, ?O)) + // * sub_unify(Nat, ?T(:> Never, <: Add(?R))): (?T(:> Nat, <: Add(?R)) // sub = union(l, sub) if max does not exist // * sub_unify(Str, ?T(:> Int, <: Obj)): (?T(:> Str or Int, <: Obj)) // * sub_unify({0}, ?T(:> {1}, <: Nat)): (?T(:> {0, 1}, <: Nat)) diff --git a/compiler/erg_compiler/eval.rs b/compiler/erg_compiler/eval.rs index 1b62adf6..96dd3740 100644 --- a/compiler/erg_compiler/eval.rs +++ b/compiler/erg_compiler/eval.rs @@ -537,7 +537,10 @@ impl Context { } _ => *lhs, }; - for (_ty, ty_ctx) in self.rec_get_nominal_super_type_ctxs(&lhs) { + for (_ty, ty_ctx) in self + .rec_get_nominal_super_type_ctxs(&lhs) + .ok_or_else(|| todo!())? + { if let Ok(obj) = ty_ctx.get_const_local(&Token::symbol(&rhs), &self.name) { if let ValueObj::Type(quant_t) = obj { let subst_ctx = SubstContext::new(&lhs, ty_ctx); @@ -557,6 +560,7 @@ impl Context { "{lhs}.{rhs} not found in [{}]", erg_common::fmt_iter( self.rec_get_nominal_super_type_ctxs(&lhs) + .unwrap() .map(|(_, ctx)| &ctx.name) ) ) diff --git a/compiler/erg_type/lib.rs b/compiler/erg_type/lib.rs index 3578e780..b262ff36 100644 --- a/compiler/erg_type/lib.rs +++ b/compiler/erg_type/lib.rs @@ -18,7 +18,7 @@ use erg_common::vis::Field; use erg_common::{enum_unwrap, fmt_option, fmt_set_split_with, set, Str}; use crate::codeobj::CodeObj; -use crate::constructors::{and, int_interval, mono, mono_q}; +use crate::constructors::{int_interval, mono, mono_q}; use crate::free::{ fresh_varname, Constraint, Cyclicity, Free, FreeKind, FreeTyVar, HasLevel, Level, }; @@ -1778,24 +1778,6 @@ impl Type { } } - /// 共通部分(A and B)を返す - /// 型同士の包含関係はここでは検査しない(TypeCheckerでする) - pub fn intersection(lhs: &Self, rhs: &Self) -> Self { - if lhs == rhs { - return lhs.clone(); - } - match (lhs, rhs) { - (Self::FreeVar(_), _) | (_, Self::FreeVar(_)) => { - todo!() - } - // { .i: Int } and { .s: Str } == { .i: Int, .s: Str } - (Self::Record(l), Self::Record(r)) => Self::Record(l.clone().concat(r.clone())), - (t, Self::Obj) | (Self::Obj, t) => t.clone(), - (_, Self::Never) | (Self::Never, _) => Self::Never, - (l, r) => and(l.clone(), r.clone()), - } - } - pub fn name(&self) -> Str { match self { Self::Obj => Str::ever("Obj"), diff --git a/compiler/erg_type/value.rs b/compiler/erg_type/value.rs index 94e4b850..a2f4405b 100644 --- a/compiler/erg_type/value.rs +++ b/compiler/erg_type/value.rs @@ -63,20 +63,6 @@ impl GenTypeObj { additional: additional.map(Box::new), } } - - pub fn get_require_attr_t(&self, attr: &str) -> Option<&Type> { - if let Type::Record(rec) = &self.require_or_sup.typ() { - rec.get(attr) - } else if let Some(additional) = &self.additional { - if let Type::Record(gen) = additional.typ() { - gen.get(attr) - } else { - None - } - } else { - None - } - } } #[derive(Clone, Debug, PartialEq, Eq, Hash)] @@ -101,13 +87,6 @@ impl TypeObj { TypeObj::Generated(t) => &t.t, } } - - pub fn get_require_attr_t(&self, attr: &str) -> Option<&Type> { - match self { - TypeObj::Builtin(_t) => None, - TypeObj::Generated(gen) => gen.get_require_attr_t(attr), - } - } } /// 値オブジェクト From 7e08f0b0c60c109e7eccc92bab72443f18fb5ee4 Mon Sep 17 00:00:00 2001 From: Shunsuke Shibayama Date: Mon, 5 Sep 2022 23:46:31 +0900 Subject: [PATCH 24/68] Fix type checker bugs --- compiler/erg_compiler/context/inquire.rs | 85 ++++++++++++++++++++++++ compiler/erg_compiler/context/tyvar.rs | 2 +- compiler/erg_compiler/eval.rs | 7 +- compiler/erg_compiler/lower.rs | 2 +- compiler/erg_type/free.rs | 34 ++++++++-- 5 files changed, 120 insertions(+), 10 deletions(-) diff --git a/compiler/erg_compiler/context/inquire.rs b/compiler/erg_compiler/context/inquire.rs index 22809fc3..f9960711 100644 --- a/compiler/erg_compiler/context/inquire.rs +++ b/compiler/erg_compiler/context/inquire.rs @@ -1097,6 +1097,71 @@ impl Context { } } + pub(crate) fn rec_get_mut_nominal_type_ctx<'a>( + &'a mut self, + typ: &Type, + ) -> Option<(&'a Type, &'a mut Context)> { + // SAFETY: `rec_get_nominal_type_ctx` is called only when `self` is not borrowed + let outer = unsafe { + (&mut self.outer as *mut Option>) + .as_mut() + .unwrap() + }; + match typ { + Type::FreeVar(fv) if fv.is_linked() => { + if let Some(res) = self.rec_get_mut_nominal_type_ctx(&fv.crack()) { + return Some(res); + } + } + Type::FreeVar(fv) => { + let sup = fv.get_sup().unwrap(); + if let Some(res) = self.rec_get_mut_nominal_type_ctx(&sup) { + return Some(res); + } + } + Type::Refinement(refine) => { + if let Some(res) = self.rec_get_mut_nominal_type_ctx(&refine.t) { + return Some(res); + } + } + Type::Quantified(_) => { + if let Some(res) = self.rec_get_mut_nominal_type_ctx(&mono("QuantifiedFunction")) { + return Some(res); + } + } + Type::Poly { name, params: _ } => { + if let Some((t, ctx)) = self.rec_get_mut_poly_type(name) { + return Some((t, ctx)); + } + } + /*Type::Record(rec) if rec.values().all(|attr| self.supertype_of(&Type, attr)) => { + // TODO: reference RecordType (inherits Type) + if let Some(res) = self.rec_get_nominal_type_ctx(&Type) { + return Some(res); + } + }*/ + // FIXME: `F()`などの場合、実際は引数が省略されていてもmonomorphicになる + other if other.is_monomorphic() => { + if let Some((t, ctx)) = self.rec_get_mut_mono_type(&other.name()) { + return Some((t, ctx)); + } + } + Type::Ref(t) | Type::RefMut(t) => { + if let Some(res) = self.rec_get_mut_nominal_type_ctx(t) { + return Some(res); + } + } + other => { + log!("{other} has no nominal definition"); + } + } + if let Some(outer) = outer { + outer.rec_get_mut_nominal_type_ctx(typ) + } else { + None + } + } + fn rec_get_singular_ctx(&self, obj: &hir::Expr) -> Option<&Context> { match obj.ref_t() { // TODO: attr @@ -1207,6 +1272,26 @@ impl Context { } } + fn rec_get_mut_mono_type(&mut self, name: &str) -> Option<(&mut Type, &mut Context)> { + if let Some((t, ctx)) = self.mono_types.get_mut(name) { + Some((t, ctx)) + } else if let Some(outer) = self.outer.as_mut() { + outer.rec_get_mut_mono_type(name) + } else { + None + } + } + + fn rec_get_mut_poly_type(&mut self, name: &str) -> Option<(&mut Type, &mut Context)> { + if let Some((t, ctx)) = self.poly_types.get_mut(name) { + Some((t, ctx)) + } else if let Some(outer) = self.outer.as_mut() { + outer.rec_get_mut_poly_type(name) + } else { + None + } + } + fn get_gen_t_require_attr_t<'a>(&'a self, gen: &'a GenTypeObj, attr: &str) -> Option<&'a Type> { match gen.require_or_sup.typ() { Type::Record(rec) => { diff --git a/compiler/erg_compiler/context/tyvar.rs b/compiler/erg_compiler/context/tyvar.rs index 90422c89..4415fd07 100644 --- a/compiler/erg_compiler/context/tyvar.rs +++ b/compiler/erg_compiler/context/tyvar.rs @@ -273,7 +273,7 @@ impl Context { drop(constraint); fv.link(&t); self.deref_tyvar(Type::FreeVar(fv)) - } else if self.level == 0 || self.level <= fv.level().unwrap() { + } else if self.level <= fv.level().unwrap() { let new_t = if sub_t == &Never { super_t.clone() } else { diff --git a/compiler/erg_compiler/eval.rs b/compiler/erg_compiler/eval.rs index 96dd3740..e9d2fbe9 100644 --- a/compiler/erg_compiler/eval.rs +++ b/compiler/erg_compiler/eval.rs @@ -531,15 +531,18 @@ impl Context { // Currently Erg does not allow projection-types to be evaluated with type variables included. // All type variables will be dereferenced or fail. let lhs = match *lhs { + Type::FreeVar(fv) if fv.is_linked() => { + self.eval_t_params(mono_proj(fv.crack().clone(), rhs.clone()), level)? + } Type::FreeVar(fv) if fv.is_unbound() => { fv.lift(); self.deref_tyvar(Type::FreeVar(fv))? } - _ => *lhs, + other => other, }; for (_ty, ty_ctx) in self .rec_get_nominal_super_type_ctxs(&lhs) - .ok_or_else(|| todo!())? + .ok_or_else(|| todo!("{lhs}"))? { if let Ok(obj) = ty_ctx.get_const_local(&Token::symbol(&rhs), &self.name) { if let ValueObj::Type(quant_t) = obj { diff --git a/compiler/erg_compiler/lower.rs b/compiler/erg_compiler/lower.rs index 44c62551..d82dd0fa 100644 --- a/compiler/erg_compiler/lower.rs +++ b/compiler/erg_compiler/lower.rs @@ -563,7 +563,7 @@ impl ASTLowerer { } match self.ctx.pop() { Ok(ctx) => { - if let Some((_, class_root)) = self.ctx.poly_types.get_mut(&class.name()) { + if let Some((_, class_root)) = self.ctx.rec_get_mut_nominal_type_ctx(&class) { class_root.method_defs.push((class, ctx)); } else { todo!() diff --git a/compiler/erg_type/free.rs b/compiler/erg_type/free.rs index 8cd0d05c..9f69fc2c 100644 --- a/compiler/erg_type/free.rs +++ b/compiler/erg_type/free.rs @@ -180,6 +180,17 @@ impl Constraint { } } + pub fn lift(&self) { + match self { + Self::Sandwiched { sub, sup, .. } => { + sub.lift(); + sup.lift(); + } + Self::TypeOf(t) => t.lift(), + Self::Uninited => {} + } + } + pub fn get_type(&self) -> Option<&Type> { match self { Self::TypeOf(ty) => Some(ty), @@ -259,7 +270,11 @@ impl LimitedDisplay for FreeKind { return write!(f, "..."); } match self { - Self::Linked(t) | Self::UndoableLinked { t, .. } => t.limited_fmt(f, limit), + Self::Linked(t) | Self::UndoableLinked { t, .. } => { + write!(f, "(")?; + t.limited_fmt(f, limit)?; + write!(f, ")") + } Self::NamedUnbound { name, lev, @@ -434,13 +449,17 @@ impl Free { pub fn lift(&self) { match &mut *self.borrow_mut() { - FreeKind::Unbound { lev, .. } | FreeKind::NamedUnbound { lev, .. } => { + FreeKind::Unbound { + lev, constraint, .. + } + | FreeKind::NamedUnbound { + lev, constraint, .. + } => { *lev += 1; + constraint.lift(); } FreeKind::Linked(t) | FreeKind::UndoableLinked { t, .. } => { - if let Some(lev) = t.level() { - t.update_level(lev + 1); - } + t.lift(); } } } @@ -579,7 +598,10 @@ impl Free { } pub fn is_linked(&self) -> bool { - matches!(&*self.borrow(), FreeKind::Linked(_)) + matches!( + &*self.borrow(), + FreeKind::Linked(_) | FreeKind::UndoableLinked { .. } + ) } pub fn unbound_name(&self) -> Option { From fadce087c55cf4b84719d3622a115e17f112739f Mon Sep 17 00:00:00 2001 From: Shunsuke Shibayama Date: Mon, 5 Sep 2022 23:46:40 +0900 Subject: [PATCH 25/68] Update effectcheck.rs --- compiler/erg_compiler/effectcheck.rs | 32 +++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/compiler/erg_compiler/effectcheck.rs b/compiler/erg_compiler/effectcheck.rs index 4c8a1b11..816a1e9a 100644 --- a/compiler/erg_compiler/effectcheck.rs +++ b/compiler/erg_compiler/effectcheck.rs @@ -9,7 +9,7 @@ use erg_common::Str; use Visibility::*; use crate::error::{EffectError, EffectErrors, EffectResult}; -use crate::hir::{Accessor, Def, Expr, Signature, HIR}; +use crate::hir::{Accessor, Array, Def, Expr, Signature, Tuple, HIR}; #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] enum BlockKind { @@ -84,6 +84,11 @@ impl SideEffectChecker { Expr::Def(def) => { self.check_def(def); } + Expr::MethodDefs(method_defs) => { + for def in method_defs.defs.iter() { + self.check_def(def); + } + } Expr::Call(call) => { for parg in call.args.pos_args.iter() { self.check_expr(&parg.expr); @@ -174,6 +179,31 @@ impl SideEffectChecker { Expr::Def(def) => { self.check_def(def); } + Expr::MethodDefs(method_defs) => { + for def in method_defs.defs.iter() { + self.check_def(def); + } + } + Expr::Array(array) => match array { + Array::Normal(arr) => { + for arg in arr.elems.pos_args.iter() { + self.check_expr(&arg.expr); + } + } + other => todo!("{other}"), + }, + Expr::Tuple(tuple) => match tuple { + Tuple::Normal(tup) => { + for arg in tup.elems.pos_args.iter() { + self.check_expr(&arg.expr); + } + } + }, + Expr::Record(record) => { + for attr in record.attrs.iter() { + self.check_def(attr); + } + } // 引数がproceduralでも関数呼び出しなら副作用なし Expr::Call(call) => { if (self.is_procedural(&call.obj) From 1b4c9aa9c3f0d3ac1e82d5e5d8e2919a23f28e7b Mon Sep 17 00:00:00 2001 From: Shunsuke Shibayama Date: Mon, 5 Sep 2022 23:50:32 +0900 Subject: [PATCH 26/68] Move eval.rs to `context` --- compiler/erg_compiler/codegen.rs | 2 +- compiler/erg_compiler/{ => context}/eval.rs | 0 compiler/erg_compiler/context/instantiate.rs | 2 +- compiler/erg_compiler/context/mod.rs | 1 + compiler/erg_compiler/hir.rs | 2 +- compiler/erg_compiler/lib.rs | 2 +- 6 files changed, 5 insertions(+), 4 deletions(-) rename compiler/erg_compiler/{ => context}/eval.rs (100%) diff --git a/compiler/erg_compiler/codegen.rs b/compiler/erg_compiler/codegen.rs index 9a33de76..89bcfe13 100644 --- a/compiler/erg_compiler/codegen.rs +++ b/compiler/erg_compiler/codegen.rs @@ -23,8 +23,8 @@ use erg_type::value::ValueObj; use erg_type::{HasType, TypeCode, TypePair}; use crate::compile::{AccessKind, Name, StoreLoadKind}; +use crate::context::eval::eval_lit; use crate::error::{CompileError, CompileErrors, CompileResult}; -use crate::eval::eval_lit; use crate::hir::{ Accessor, Args, Array, Block, Call, DefBody, Expr, Local, Signature, SubrSignature, Tuple, VarSignature, HIR, diff --git a/compiler/erg_compiler/eval.rs b/compiler/erg_compiler/context/eval.rs similarity index 100% rename from compiler/erg_compiler/eval.rs rename to compiler/erg_compiler/context/eval.rs diff --git a/compiler/erg_compiler/context/instantiate.rs b/compiler/erg_compiler/context/instantiate.rs index ee69be4a..9aa7563b 100644 --- a/compiler/erg_compiler/context/instantiate.rs +++ b/compiler/erg_compiler/context/instantiate.rs @@ -23,9 +23,9 @@ use erg_type::typaram::{IntervalOp, TyParam, TyParamOrdering}; use erg_type::value::ValueObj; use erg_type::{HasType, ParamTy, Predicate, SubrKind, TyBound, Type}; +use crate::context::eval::eval_lit; use crate::context::{Context, RegistrationMode}; use crate::error::TyCheckResult; -use crate::eval::eval_lit; use crate::hir; use RegistrationMode::*; diff --git a/compiler/erg_compiler/context/mod.rs b/compiler/erg_compiler/context/mod.rs index dedc8c8e..fa3abe91 100644 --- a/compiler/erg_compiler/context/mod.rs +++ b/compiler/erg_compiler/context/mod.rs @@ -2,6 +2,7 @@ //! `Context` is used for type inference and type checking. pub mod cache; pub mod compare; +pub mod eval; pub mod hint; pub mod initialize; pub mod inquire; diff --git a/compiler/erg_compiler/hir.rs b/compiler/erg_compiler/hir.rs index 5070a81e..2e70f682 100644 --- a/compiler/erg_compiler/hir.rs +++ b/compiler/erg_compiler/hir.rs @@ -19,8 +19,8 @@ use erg_type::typaram::TyParam; use erg_type::value::ValueObj; use erg_type::{impl_t, impl_t_for_enum, HasType, Type}; +use crate::context::eval::type_from_token_kind; use crate::error::readable_name; -use crate::eval::type_from_token_kind; #[derive(Debug, Clone)] pub struct Literal { diff --git a/compiler/erg_compiler/lib.rs b/compiler/erg_compiler/lib.rs index b0c1974b..199b4448 100644 --- a/compiler/erg_compiler/lib.rs +++ b/compiler/erg_compiler/lib.rs @@ -7,8 +7,8 @@ pub use compile::*; mod codegen; pub mod effectcheck; pub mod error; -pub mod eval; pub mod hir; +pub mod link; pub mod lower; pub use lower::ASTLowerer; pub mod context; From b755fdfa42a2842d60360efdd822c10fa37e9e60 Mon Sep 17 00:00:00 2001 From: Shunsuke Shibayama Date: Mon, 5 Sep 2022 23:52:26 +0900 Subject: [PATCH 27/68] Create link.rs --- compiler/erg_compiler/link.rs | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 compiler/erg_compiler/link.rs diff --git a/compiler/erg_compiler/link.rs b/compiler/erg_compiler/link.rs new file mode 100644 index 00000000..8d8483bc --- /dev/null +++ b/compiler/erg_compiler/link.rs @@ -0,0 +1,3 @@ +/// Combine method definitions across multiple modules, specialized class contexts, etc. +#[derive(Debug)] +pub struct HIRLinker {} From be8c0978f05a67ded5a3849e3b1b958c29e1c429 Mon Sep 17 00:00:00 2001 From: Shunsuke Shibayama Date: Tue, 6 Sep 2022 01:29:56 +0900 Subject: [PATCH 28/68] Add `ClassType` object --- .../context/initialize/const_func.rs | 6 +++--- .../erg_compiler/context/initialize/mod.rs | 21 ++++++++++++++----- compiler/erg_compiler/context/inquire.rs | 3 +-- compiler/erg_compiler/context/register.rs | 3 ++- compiler/erg_type/lib.rs | 4 ++-- compiler/erg_type/value.rs | 13 +++++++++++- 6 files changed, 36 insertions(+), 14 deletions(-) diff --git a/compiler/erg_compiler/context/initialize/const_func.rs b/compiler/erg_compiler/context/initialize/const_func.rs index 64463c38..a454f509 100644 --- a/compiler/erg_compiler/context/initialize/const_func.rs +++ b/compiler/erg_compiler/context/initialize/const_func.rs @@ -17,7 +17,7 @@ fn value_obj_to_t(value: ValueObj) -> TypeObj { } } -/// Requirement: Type, Impl := Type -> Type +/// Requirement: Type, Impl := Type -> Class pub fn class_func(mut args: ValueArgs, __name__: Option) -> ValueObj { let require = args.pos_args.remove(0); let require = value_obj_to_t(require); @@ -27,7 +27,7 @@ pub fn class_func(mut args: ValueArgs, __name__: Option) -> ValueObj { ValueObj::gen_t(TypeKind::Class, t, require, impls, None) } -/// Super: Type, Impl := Type, Additional := Type -> Type +/// 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 = value_obj_to_t(sup); @@ -42,7 +42,7 @@ pub fn inherit_func(mut args: ValueArgs, __name__: Option) -> ValueObj { ValueObj::gen_t(TypeKind::InheritedClass, t, sup, impls, additional) } -/// Type -> Type +/// Class -> Class /// 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() diff --git a/compiler/erg_compiler/context/initialize/mod.rs b/compiler/erg_compiler/context/initialize/mod.rs index 42566ab6..cedbd159 100644 --- a/compiler/erg_compiler/context/initialize/mod.rs +++ b/compiler/erg_compiler/context/initialize/mod.rs @@ -553,13 +553,23 @@ impl Context { "Type", vec![Obj], vec![ - poly("Eq", vec![ty_tp(Type)]), + // poly("Eq", vec![ty_tp(Type)]), poly("In", vec![ty_tp(Obj)]), // x in Type mono("Named"), ], Self::TOP_LEVEL, ); type_.register_builtin_impl("mro", array(Type, TyParam::erased(Nat)), Immutable, Public); + let class_type = Self::mono_class( + "ClassType", + vec![Type, Obj], + vec![ + // poly("Eq", vec![ty_tp(Class)]), + poly("In", vec![ty_tp(Obj)]), // x in Class + mono("Named"), + ], + Self::TOP_LEVEL, + ); let module = Self::mono_class( "Module", vec![Obj], @@ -930,6 +940,7 @@ impl Context { self.register_builtin_type(Bool, bool_, Const); self.register_builtin_type(Str, str_, Const); self.register_builtin_type(Type, type_, Const); + self.register_builtin_type(Class, class_type, Const); self.register_builtin_type(Module, module, Const); self.register_builtin_type(array_t, array_, Const); self.register_builtin_type(tuple(vec![mono_q("A")]), tuple1, Const); @@ -1076,21 +1087,21 @@ impl Context { vec![param_t("Requirement", Type)], None, vec![param_t("Impl", Type)], - Type, + Class, ); let class = ConstSubr::Builtin(BuiltinConstSubr::new(class_func, class_t)); self.register_builtin_const("Class", ValueObj::Subr(class)); let inherit_t = func( - vec![param_t("Super", Type)], + vec![param_t("Super", Class)], None, vec![param_t("Impl", Type), param_t("Additional", Type)], - Type, + Class, ); let inherit = ConstSubr::Builtin(BuiltinConstSubr::new(inherit_func, inherit_t)); self.register_builtin_const("Inherit", ValueObj::Subr(inherit)); // decorators let inheritable = - ConstSubr::Builtin(BuiltinConstSubr::new(inheritable_func, func1(Type, Type))); + ConstSubr::Builtin(BuiltinConstSubr::new(inheritable_func, func1(Class, Class))); self.register_builtin_const("Inheritable", ValueObj::Subr(inheritable)); } diff --git a/compiler/erg_compiler/context/inquire.rs b/compiler/erg_compiler/context/inquire.rs index f9960711..b91fce2c 100644 --- a/compiler/erg_compiler/context/inquire.rs +++ b/compiler/erg_compiler/context/inquire.rs @@ -1166,10 +1166,9 @@ impl Context { match obj.ref_t() { // TODO: attr Type::Module => self.rec_get_mod(&obj.var_full_name()?), - Type::Type => self + Type::Type | Type::Class => self .rec_get_nominal_type_ctx(&Type::Mono(Str::from(obj.var_full_name().unwrap()))) .map(|(_, ctx)| ctx), - Type::Class => todo!(), Type::Trait => todo!(), Type::Refinement(refine) => { self.rec_get_nominal_type_ctx(&refine.t).map(|(_, ctx)| ctx) diff --git a/compiler/erg_compiler/context/register.rs b/compiler/erg_compiler/context/register.rs index eb0460bc..6063fe39 100644 --- a/compiler/erg_compiler/context/register.rs +++ b/compiler/erg_compiler/context/register.rs @@ -584,11 +584,12 @@ impl Context { panic!("{} has already been registered as const", gen.t.name()); } else { let t = gen.t.clone(); + let meta_t = gen.meta_type(); let name = VarName::from_str(gen.t.name()); let id = DefId(get_hash(&(&self.name, &name))); self.locals.insert( name.clone(), - VarInfo::new(Type, muty, Private, VarKind::Defined(id)), + VarInfo::new(meta_t, muty, Private, VarKind::Defined(id)), ); self.consts .insert(name.clone(), ValueObj::Type(TypeObj::Generated(gen))); diff --git a/compiler/erg_type/lib.rs b/compiler/erg_type/lib.rs index b262ff36..29eb2054 100644 --- a/compiler/erg_type/lib.rs +++ b/compiler/erg_type/lib.rs @@ -1789,8 +1789,8 @@ impl Type { Self::Str => Str::ever("Str"), Self::NoneType => Str::ever("NoneType"), Self::Type => Str::ever("Type"), - Self::Class => Str::ever("Class"), - Self::Trait => Str::ever("Trait"), + Self::Class => Str::ever("ClassType"), + Self::Trait => Str::ever("TraitType"), Self::Patch => Str::ever("Patch"), Self::Code => Str::ever("Code"), Self::Module => Str::ever("Module"), diff --git a/compiler/erg_type/value.rs b/compiler/erg_type/value.rs index a2f4405b..a67ed21c 100644 --- a/compiler/erg_type/value.rs +++ b/compiler/erg_type/value.rs @@ -63,6 +63,13 @@ impl GenTypeObj { additional: additional.map(Box::new), } } + + pub fn meta_type(&self) -> Type { + match self.kind { + TypeKind::Class | TypeKind::InheritedClass => Type::Class, + TypeKind::Trait | TypeKind::SubsumedTrait | TypeKind::StructuralTrait => Type::Trait, + } + } } #[derive(Clone, Debug, PartialEq, Eq, Hash)] @@ -464,7 +471,11 @@ impl ValueObj { Type::Record(rec.iter().map(|(k, v)| (k.clone(), v.class())).collect()) } Self::Subr(subr) => subr.class(), - Self::Type(_) => Type::Type, + Self::Type(t_obj) => match t_obj { + // TODO: builtin + TypeObj::Builtin(_t) => Type::Type, + TypeObj::Generated(gen_t) => gen_t.meta_type(), + }, Self::None => Type::NoneType, Self::Ellipsis => Type::Ellipsis, Self::NotImplemented => Type::NotImplemented, From 36aa226d10a0c9e87961347e8b2bcf52ba55635f Mon Sep 17 00:00:00 2001 From: Shunsuke Shibayama Date: Tue, 6 Sep 2022 14:43:01 +0900 Subject: [PATCH 29/68] Impl `Linker` --- compiler/erg_common/traits.rs | 7 +++ compiler/erg_compiler/codegen.rs | 34 ++++++---- compiler/erg_compiler/compile.rs | 8 ++- compiler/erg_compiler/context/eval.rs | 1 + compiler/erg_compiler/context/register.rs | 44 ++++++++----- compiler/erg_compiler/context/tyvar.rs | 4 +- compiler/erg_compiler/effectcheck.rs | 9 +-- compiler/erg_compiler/hir.rs | 73 +++++++++++++++++++--- compiler/erg_compiler/link.rs | 75 ++++++++++++++++++++++- compiler/erg_compiler/lower.rs | 75 ++++++++++++++--------- compiler/erg_compiler/varinfo.rs | 3 +- compiler/erg_parser/ast.rs | 50 ++++++++++++--- compiler/erg_parser/desugar.rs | 10 +-- compiler/erg_parser/parse.rs | 8 +-- 14 files changed, 307 insertions(+), 94 deletions(-) diff --git a/compiler/erg_common/traits.rs b/compiler/erg_common/traits.rs index 7474e868..d0065756 100644 --- a/compiler/erg_common/traits.rs +++ b/compiler/erg_common/traits.rs @@ -119,6 +119,13 @@ pub trait Stream: Sized { fn take_all(&mut self) -> Vec { self.ref_mut_payload().drain(..).collect() } + + fn extend(&mut self, iter: I) + where + I: IntoIterator, + { + self.ref_mut_payload().extend(iter); + } } #[macro_export] diff --git a/compiler/erg_compiler/codegen.rs b/compiler/erg_compiler/codegen.rs index 89bcfe13..837fc64f 100644 --- a/compiler/erg_compiler/codegen.rs +++ b/compiler/erg_compiler/codegen.rs @@ -19,6 +19,7 @@ use Opcode::*; use erg_parser::ast::{Identifier, ParamPattern, Params, VarName}; use erg_parser::token::{Token, TokenKind}; +use erg_type::value::TypeKind; use erg_type::value::ValueObj; use erg_type::{HasType, TypeCode, TypePair}; @@ -26,8 +27,8 @@ use crate::compile::{AccessKind, Name, StoreLoadKind}; use crate::context::eval::eval_lit; use crate::error::{CompileError, CompileErrors, CompileResult}; use crate::hir::{ - Accessor, Args, Array, Block, Call, DefBody, Expr, Local, Signature, SubrSignature, Tuple, - VarSignature, HIR, + Accessor, Args, Array, Block, Call, ClassDef, DefBody, Expr, Local, RecordAttrs, Signature, + SubrSignature, Tuple, VarSignature, HIR, }; use AccessKind::*; @@ -685,11 +686,24 @@ impl CodeGenerator { .collect() } - fn emit_mono_type_def(&mut self, sig: VarSignature, body: DefBody) { + 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) { self.write_instr(Opcode::LOAD_BUILD_CLASS); self.write_arg(0); self.stack_inc(); - let code = self.codegen_typedef_block(sig.inspect().clone(), body.block); + let code = self.codegen_typedef_block(sig.inspect().clone(), methods); self.emit_load_const(code); self.emit_load_const(sig.inspect().clone()); self.write_instr(Opcode::MAKE_FUNCTION); @@ -705,9 +719,6 @@ impl CodeGenerator { // fn emit_poly_type_def(&mut self, sig: SubrSignature, body: DefBody) {} fn emit_var_def(&mut self, sig: VarSignature, mut body: DefBody) { - if body.is_type() { - return self.emit_mono_type_def(sig, body); - } if body.block.len() == 1 { self.codegen_expr(body.block.remove(0)); } else { @@ -1055,6 +1066,7 @@ 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), // TODO: Expr::Lambda(lambda) => { let params = self.gen_param_names(&lambda.params); @@ -1311,14 +1323,14 @@ impl CodeGenerator { self.cancel_pop_top(); } - fn codegen_typedef_block(&mut self, name: Str, block: Block) -> CodeObj { + fn codegen_typedef_block(&mut self, name: Str, methods: RecordAttrs) -> CodeObj { self.unit_size += 1; self.units.push(CodeGenUnit::new( self.unit_size, vec![], Str::rc(self.cfg.input.enclosed_name()), &name, - block[0].ln_begin().unwrap(), + methods[0].ln_begin().unwrap(), )); let mod_name = self.toplevel_block_codeobj().name.clone(); self.emit_load_const(mod_name); @@ -1326,8 +1338,8 @@ impl CodeGenerator { self.emit_load_const(name); self.emit_store_instr(Identifier::public("__qualname__"), Attr); // TODO: サブルーチンはT.subという書式でSTORE - for expr in block.into_iter() { - self.codegen_expr(expr); + for def in methods.into_iter() { + self.codegen_expr(Expr::Def(def)); // TODO: discard if self.cur_block().stack_len == 1 { self.emit_pop_top(); diff --git a/compiler/erg_compiler/compile.rs b/compiler/erg_compiler/compile.rs index d3cca832..913754b3 100644 --- a/compiler/erg_compiler/compile.rs +++ b/compiler/erg_compiler/compile.rs @@ -15,6 +15,7 @@ use erg_parser::ParserRunner; use crate::codegen::CodeGenerator; use crate::effectcheck::SideEffectChecker; use crate::error::{CompileError, CompileErrors, TyCheckErrors}; +use crate::link::Linker; use crate::lower::ASTLowerer; use crate::ownercheck::OwnershipChecker; @@ -158,11 +159,13 @@ impl Compiler { } pub fn compile(&mut self, src: Str, mode: &str) -> Result { - log!(info "the compiling process has started"); + log!(info "the compiling process has started."); let mut cfg = self.cfg.copy(); cfg.input = Input::Str(src); let mut parser = ParserRunner::new(cfg); let ast = parser.parse()?; + let mut linker = Linker::new(); + let ast = linker.link(ast); let (hir, warns) = self .lowerer .lower(ast, mode) @@ -182,8 +185,7 @@ impl Compiler { let codeobj = self.code_generator.codegen(hir); log!(info "code object:\n{}", codeobj.code_info()); log!( - c GREEN, - "the compiling process has completed, found errors: {}", + info "the compiling process has completed, found errors: {}", self.code_generator.errs.len() ); if self.code_generator.errs.is_empty() { diff --git a/compiler/erg_compiler/context/eval.rs b/compiler/erg_compiler/context/eval.rs index e9d2fbe9..d0bb908b 100644 --- a/compiler/erg_compiler/context/eval.rs +++ b/compiler/erg_compiler/context/eval.rs @@ -622,6 +622,7 @@ impl Context { todo!() } } + // TODO: Class, Trait TyParam::Type(_) => Ok(Type::Type), TyParam::Mono(name) => self .rec_get_const_obj(&name) diff --git a/compiler/erg_compiler/context/register.rs b/compiler/erg_compiler/context/register.rs index 6063fe39..534fec46 100644 --- a/compiler/erg_compiler/context/register.rs +++ b/compiler/erg_compiler/context/register.rs @@ -423,8 +423,14 @@ impl Context { // To allow forward references and recursive definitions pub(crate) fn preregister(&mut self, block: &ast::Block) -> TyCheckResult<()> { for expr in block.iter() { - if let ast::Expr::Def(def) = expr { - self.preregister_def(def)?; + match expr { + ast::Expr::Def(def) => { + self.preregister_def(def)?; + } + ast::Expr::ClassDef(class_def) => { + self.preregister_def(&class_def.def)?; + } + _ => {} } } Ok(()) @@ -475,8 +481,23 @@ impl Context { Ok(()) } - fn _register_gen_decl(&mut self, name: &'static str, t: Type, vis: Visibility) { + fn register_auto_impl( + &mut self, + name: &'static str, + t: Type, + muty: Mutability, + vis: Visibility, + ) { let name = VarName::from_static(name); + if self.locals.get(&name).is_some() { + panic!("already registered: {name}"); + } else { + self.locals + .insert(name, VarInfo::new(t, muty, vis, VarKind::Auto)); + } + } + + fn _register_gen_decl(&mut self, name: VarName, t: Type, vis: Visibility) { if self.decls.get(&name).is_some() { panic!("already registered: {name}"); } else { @@ -485,14 +506,7 @@ impl Context { } } - fn register_gen_impl( - &mut self, - name: &'static str, - t: Type, - muty: Mutability, - vis: Visibility, - ) { - let name = VarName::from_static(name); + fn _register_gen_impl(&mut self, name: VarName, t: Type, muty: Mutability, vis: Visibility) { if self.locals.get(&name).is_some() { panic!("already registered: {name}"); } else { @@ -534,9 +548,9 @@ impl Context { let mut ctx = Self::mono_class(gen.t.name(), vec![], super_traits, self.level); let require = gen.require_or_sup.typ().clone(); let new_t = func1(require, gen.t.clone()); - ctx.register_gen_impl("__new__", new_t.clone(), Immutable, Private); + ctx.register_auto_impl("__new__", new_t.clone(), Immutable, Private); // 必要なら、ユーザーが独自に上書きする - ctx.register_gen_impl("new", new_t, Immutable, Public); + ctx.register_auto_impl("new", new_t, Immutable, Public); self.register_gen_mono_type(gen, ctx, Const); } else { todo!() @@ -560,9 +574,9 @@ impl Context { param_t.clone() }; let new_t = func1(param_t, gen.t.clone()); - ctx.register_gen_impl("__new__", new_t.clone(), Immutable, Private); + ctx.register_auto_impl("__new__", new_t.clone(), Immutable, Private); // 必要なら、ユーザーが独自に上書きする - ctx.register_gen_impl("new", new_t, Immutable, Public); + ctx.register_auto_impl("new", new_t, Immutable, Public); self.register_gen_mono_type(gen, ctx, Const); } else { todo!("super class not found") diff --git a/compiler/erg_compiler/context/tyvar.rs b/compiler/erg_compiler/context/tyvar.rs index 4415fd07..53c23fd8 100644 --- a/compiler/erg_compiler/context/tyvar.rs +++ b/compiler/erg_compiler/context/tyvar.rs @@ -477,8 +477,8 @@ impl Context { } Ok(()) } - hir::Expr::MethodDefs(method_defs) => { - for def in method_defs.defs.iter_mut() { + hir::Expr::ClassDef(type_def) => { + for def in type_def.public_methods.iter_mut() { match &mut def.sig { hir::Signature::Var(var) => { var.t = self.deref_tyvar(mem::take(&mut var.t))?; diff --git a/compiler/erg_compiler/effectcheck.rs b/compiler/erg_compiler/effectcheck.rs index 816a1e9a..bc0dafac 100644 --- a/compiler/erg_compiler/effectcheck.rs +++ b/compiler/erg_compiler/effectcheck.rs @@ -84,8 +84,9 @@ impl SideEffectChecker { Expr::Def(def) => { self.check_def(def); } - Expr::MethodDefs(method_defs) => { - for def in method_defs.defs.iter() { + Expr::ClassDef(type_def) => { + // TODO: grow + for def in type_def.public_methods.iter() { self.check_def(def); } } @@ -179,8 +180,8 @@ impl SideEffectChecker { Expr::Def(def) => { self.check_def(def); } - Expr::MethodDefs(method_defs) => { - for def in method_defs.defs.iter() { + Expr::ClassDef(type_def) => { + for def in type_def.public_methods.iter() { self.check_def(def); } } diff --git a/compiler/erg_compiler/hir.rs b/compiler/erg_compiler/hir.rs index 2e70f682..11f3294d 100644 --- a/compiler/erg_compiler/hir.rs +++ b/compiler/erg_compiler/hir.rs @@ -16,7 +16,7 @@ use erg_parser::token::{Token, TokenKind}; use erg_type::constructors::{array, tuple}; use erg_type::typaram::TyParam; -use erg_type::value::ValueObj; +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; @@ -689,6 +689,7 @@ impl NestedDisplay for RecordAttrs { } impl_display_from_nested!(RecordAttrs); +impl_stream_for_wrapper!(RecordAttrs, Def); impl Locational for RecordAttrs { fn loc(&self) -> Location { @@ -703,10 +704,6 @@ impl From> for RecordAttrs { } impl RecordAttrs { - pub const fn new() -> Self { - Self(vec![]) - } - pub fn len(&self) -> usize { self.0.len() } @@ -726,6 +723,10 @@ impl RecordAttrs { pub fn push(&mut self, attr: Def) { self.0.push(attr); } + + pub fn extend(&mut self, attrs: RecordAttrs) { + self.0.extend(attrs.0); + } } #[derive(Clone, Debug)] @@ -1294,6 +1295,60 @@ impl MethodDefs { } } +#[derive(Debug, Clone)] +pub struct ClassDef { + pub kind: TypeKind, + pub def: Def, + 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.private_methods.fmt_nest(f, level)?; + self.public_methods.fmt_nest(f, level + 1) + } +} + +impl_display_from_nested!(ClassDef); +impl_locational!(ClassDef, def); + +impl HasType for ClassDef { + #[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 ClassDef { + pub const fn new( + kind: TypeKind, + def: Def, + private_methods: RecordAttrs, + public_methods: RecordAttrs, + ) -> Self { + Self { + kind, + def, + private_methods, + public_methods, + } + } +} + #[derive(Debug, Clone)] pub enum Expr { Lit(Literal), @@ -1309,13 +1364,13 @@ pub enum Expr { Lambda(Lambda), Decl(Decl), Def(Def), - MethodDefs(MethodDefs), + ClassDef(ClassDef), } -impl_nested_display_for_chunk_enum!(Expr; Lit, Accessor, Array, Tuple, Dict, Record, BinOp, UnaryOp, Call, Lambda, Decl, Def, MethodDefs); +impl_nested_display_for_chunk_enum!(Expr; Lit, Accessor, Array, Tuple, Dict, Record, BinOp, UnaryOp, Call, Lambda, Decl, Def, ClassDef); impl_display_from_nested!(Expr); -impl_locational_for_enum!(Expr; Lit, Accessor, Array, Tuple, Dict, Record, BinOp, UnaryOp, Call, Lambda, Decl, Def, MethodDefs); -impl_t_for_enum!(Expr; Lit, Accessor, Array, Tuple, Dict, Record, BinOp, UnaryOp, Call, Lambda, Decl, Def, MethodDefs); +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 Expr { pub fn receiver_t(&self) -> Option<&Type> { diff --git a/compiler/erg_compiler/link.rs b/compiler/erg_compiler/link.rs index 8d8483bc..2ddbbba8 100644 --- a/compiler/erg_compiler/link.rs +++ b/compiler/erg_compiler/link.rs @@ -1,3 +1,76 @@ +use erg_common::dict::Dict; +use erg_common::log; +use erg_common::traits::Stream; +use erg_common::Str; + +use erg_parser::ast::{ClassDef, Expr, Module, PreDeclTypeSpec, TypeSpec, AST}; + /// Combine method definitions across multiple modules, specialized class contexts, etc. #[derive(Debug)] -pub struct HIRLinker {} +pub struct Linker { + // TODO: inner scope types + pub def_root_pos_map: Dict, +} + +impl Linker { + pub fn new() -> Self { + Self { + def_root_pos_map: Dict::new(), + } + } + + pub fn link(&mut self, mut ast: AST) -> AST { + log!(info "the linking process has started."); + let mut new = vec![]; + while let Some(chunk) = ast.module.lpop() { + match chunk { + Expr::Def(def) => { + match def.body.block.first().unwrap() { + Expr::Call(call) => { + match call.obj.get_name().map(|s| &s[..]) { + // TODO: decorator + Some("Class" | "Inherit" | "Inheritable") => { + self.def_root_pos_map.insert( + def.sig.ident().unwrap().inspect().clone(), + new.len(), + ); + let type_def = ClassDef::new(def, vec![]); + new.push(Expr::ClassDef(type_def)); + } + _ => { + new.push(Expr::Def(def)); + } + } + } + _ => { + new.push(Expr::Def(def)); + } + } + } + Expr::Methods(methods) => match &methods.class { + TypeSpec::PreDeclTy(PreDeclTypeSpec::Simple(simple)) => { + if let Some(pos) = self.def_root_pos_map.get(simple.name.inspect()) { + let mut type_def = match new.remove(*pos) { + Expr::ClassDef(type_def) => type_def, + _ => unreachable!(), + }; + type_def.methods_list.push(methods); + new.insert(*pos, Expr::ClassDef(type_def)); + } else { + log!("{}", simple.name.inspect()); + log!("{}", self.def_root_pos_map); + todo!() + } + } + other => todo!("{other}"), + }, + other => { + new.push(other); + } + } + } + let ast = AST::new(ast.name, Module::new(new)); + log!(info "the linking process has completed:\n{}", ast); + ast + } +} diff --git a/compiler/erg_compiler/lower.rs b/compiler/erg_compiler/lower.rs index d82dd0fa..84055c79 100644 --- a/compiler/erg_compiler/lower.rs +++ b/compiler/erg_compiler/lower.rs @@ -13,7 +13,7 @@ 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::ValueObj; +use erg_type::value::{TypeKind, ValueObj}; use erg_type::{HasType, ParamTy, Type}; use crate::context::{Context, ContextKind, RegistrationMode}; @@ -229,7 +229,7 @@ impl ASTLowerer { fn lower_normal_record(&mut self, record: ast::NormalRecord) -> LowerResult { log!(info "entered {}({record})", fn_name!()); let mut hir_record = - hir::Record::new(record.l_brace, record.r_brace, hir::RecordAttrs::new()); + hir::Record::new(record.l_brace, record.r_brace, hir::RecordAttrs::empty()); self.ctx.grow("", ContextKind::Dummy, Private)?; for attr in record.attrs.into_iter() { let attr = self.lower_def(attr)?; @@ -546,37 +546,54 @@ impl ASTLowerer { Ok(hir::Def::new(hir::Signature::Subr(sig), body)) } - fn lower_method_defs(&mut self, method_defs: ast::MethodDefs) -> LowerResult { - log!(info "entered {}({method_defs})", fn_name!()); - let mut hir_defs = hir::RecordAttrs::new(); - let class = self - .ctx - .instantiate_typespec(&method_defs.class, RegistrationMode::Normal)?; - self.ctx - .grow(&class.name(), ContextKind::MethodDefs, Private)?; - for def in method_defs.defs.iter() { - self.ctx.preregister_def(def)?; - } - for def in method_defs.defs.into_iter() { - let def = self.lower_def(def)?; - hir_defs.push(def); - } - match self.ctx.pop() { - Ok(ctx) => { - if let Some((_, class_root)) = self.ctx.rec_get_mut_nominal_type_ctx(&class) { - class_root.method_defs.push((class, ctx)); + 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 private_methods = hir::RecordAttrs::empty(); + let mut public_methods = hir::RecordAttrs::empty(); + for methods in class_def.methods_list.into_iter() { + let class = self + .ctx + .instantiate_typespec(&methods.class, RegistrationMode::Normal)?; + self.ctx + .grow(&class.name(), ContextKind::MethodDefs, Private)?; + for def in methods.defs.iter() { + self.ctx.preregister_def(def)?; + } + for def in methods.defs.into_iter() { + let def = self.lower_def(def)?; + if methods.vis.is(TokenKind::Dot) { + public_methods.push(def); } else { - todo!() + private_methods.push(def); } } - Err(mut errs) => { - self.errs.append(&mut errs); + match self.ctx.pop() { + Ok(ctx) => { + if let Some((_, class_root)) = self.ctx.rec_get_mut_nominal_type_ctx(&class) { + class_root.method_defs.push((class, ctx)); + } else { + todo!() + } + } + Err(mut errs) => { + self.errs.append(&mut errs); + } } } - Ok(hir::MethodDefs::new( - method_defs.class, - method_defs.vis, - hir_defs, + 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!(), + }; + Ok(hir::ClassDef::new( + kind, + hir_def, + private_methods, + public_methods, )) } @@ -596,7 +613,7 @@ impl ASTLowerer { ast::Expr::DataPack(pack) => Ok(hir::Expr::Call(self.lower_pack(pack)?)), ast::Expr::Lambda(lambda) => Ok(hir::Expr::Lambda(self.lower_lambda(lambda)?)), ast::Expr::Def(def) => Ok(hir::Expr::Def(self.lower_def(def)?)), - ast::Expr::MethodDefs(defs) => Ok(hir::Expr::MethodDefs(self.lower_method_defs(defs)?)), + ast::Expr::ClassDef(defs) => Ok(hir::Expr::ClassDef(self.lower_class_def(defs)?)), other => todo!("{other}"), } } diff --git a/compiler/erg_compiler/varinfo.rs b/compiler/erg_compiler/varinfo.rs index 263d58ae..71560de8 100644 --- a/compiler/erg_compiler/varinfo.rs +++ b/compiler/erg_compiler/varinfo.rs @@ -59,12 +59,13 @@ impl ParamIdx { pub enum VarKind { Defined(DefId), Declared, + // TODO: flatten Parameter { def_id: DefId, idx: ParamIdx, default: DefaultInfo, }, - Generated, + Auto, DoesNotExist, Builtin, } diff --git a/compiler/erg_parser/ast.rs b/compiler/erg_parser/ast.rs index d4a9a4bd..e5de0921 100644 --- a/compiler/erg_parser/ast.rs +++ b/compiler/erg_parser/ast.rs @@ -2783,28 +2783,58 @@ impl Def { /// f(a) = ... /// ``` #[derive(Debug, Clone, PartialEq, Eq, Hash)] -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 MethodDefs { +impl Methods { pub const fn new(class: TypeSpec, vis: Token, defs: RecordAttrs) -> Self { Self { class, vis, defs } } } +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct ClassDef { + pub def: Def, + pub methods_list: Vec, +} + +impl NestedDisplay for ClassDef { + fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, level: usize) -> fmt::Result { + write!(f, "(class)")?; + self.def.fmt_nest(f, level)?; + for methods in self.methods_list.iter() { + write!(f, "(methods)")?; + methods.fmt_nest(f, level + 1)?; + } + Ok(()) + } +} + +impl_display_from_nested!(ClassDef); +impl_locational!(ClassDef, def); + +impl ClassDef { + pub const fn new(def: Def, methods: Vec) -> Self { + Self { + def, + methods_list: methods, + } + } +} + /// Expression(式) #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub enum Expr { @@ -2822,12 +2852,13 @@ pub enum Expr { Lambda(Lambda), TypeAsc(TypeAscription), Def(Def), - MethodDefs(MethodDefs), + Methods(Methods), + ClassDef(ClassDef), } -impl_nested_display_for_chunk_enum!(Expr; Lit, Accessor, Array, Tuple, Dict, Set, Record, BinOp, UnaryOp, Call, DataPack, Lambda, TypeAsc, Def, MethodDefs); +impl_nested_display_for_chunk_enum!(Expr; Lit, Accessor, Array, Tuple, Dict, Set, Record, BinOp, UnaryOp, Call, DataPack, Lambda, TypeAsc, Def, Methods, ClassDef); impl_display_from_nested!(Expr); -impl_locational_for_enum!(Expr; Lit, Accessor, Array, Tuple, Dict, Set, Record, BinOp, UnaryOp, Call, DataPack, Lambda, TypeAsc, Def, MethodDefs); +impl_locational_for_enum!(Expr; Lit, Accessor, Array, Tuple, Dict, Set, Record, BinOp, UnaryOp, Call, DataPack, Lambda, TypeAsc, Def, Methods, ClassDef); impl Expr { pub fn is_match_call(&self) -> bool { @@ -2894,6 +2925,9 @@ impl Module { pub const fn empty() -> Self { Self(Block::empty()) } + pub const fn new(payload: Vec) -> Self { + Self(Block::new(payload)) + } #[inline] pub fn with_capacity(capacity: usize) -> Self { Self(Block::with_capacity(capacity)) diff --git a/compiler/erg_parser/desugar.rs b/compiler/erg_parser/desugar.rs index 8f1cf0e4..e695cf3f 100644 --- a/compiler/erg_parser/desugar.rs +++ b/compiler/erg_parser/desugar.rs @@ -12,7 +12,7 @@ use erg_common::{enum_unwrap, get_hash, set}; use crate::ast::{ Accessor, Args, Array, BinOp, Block, Call, DataPack, Def, DefBody, DefId, Expr, Identifier, - KwArg, Lambda, LambdaSignature, Literal, Local, MethodDefs, Module, NormalArray, NormalRecord, + KwArg, Lambda, LambdaSignature, Literal, Local, Methods, Module, NormalArray, NormalRecord, NormalTuple, ParamPattern, ParamSignature, Params, PosArg, Record, RecordAttrs, ShortenedRecord, Signature, SubrSignature, Tuple, TypeAscription, TypeBoundSpecs, TypeSpec, UnaryOp, VarName, VarPattern, VarRecordAttr, VarSignature, @@ -457,7 +457,7 @@ impl Desugarer { let expr = self.rec_desugar_shortened_record(*tasc.expr); Expr::TypeAsc(TypeAscription::new(expr, tasc.t_spec)) } - Expr::MethodDefs(method_defs) => { + Expr::Methods(method_defs) => { let mut new_defs = vec![]; for def in method_defs.defs.into_iter() { let mut chunks = vec![]; @@ -468,11 +468,7 @@ impl Desugarer { new_defs.push(Def::new(def.sig, body)); } let new_defs = RecordAttrs::from(new_defs); - Expr::MethodDefs(MethodDefs::new( - method_defs.class, - method_defs.vis, - new_defs, - )) + Expr::Methods(Methods::new(method_defs.class, method_defs.vis, new_defs)) } // TODO: Accessorにも一応レコードを入れられる other => other, diff --git a/compiler/erg_parser/parse.rs b/compiler/erg_parser/parse.rs index 38952d32..d8c7fcd4 100644 --- a/compiler/erg_parser/parse.rs +++ b/compiler/erg_parser/parse.rs @@ -832,7 +832,7 @@ impl Parser { } } - fn try_reduce_method_defs(&mut self, class: Expr, vis: Token) -> ParseResult { + fn try_reduce_method_defs(&mut self, class: Expr, vis: Token) -> ParseResult { debug_call_info!(self); if self.cur_is(Indent) { self.skip(); @@ -862,7 +862,7 @@ impl Parser { .convert_rhs_to_type_spec(class) .map_err(|_| self.stack_dec())?; self.level -= 1; - Ok(MethodDefs::new(class, vis, defs)) + Ok(Methods::new(class, vis, defs)) } fn try_reduce_do_block(&mut self) -> ParseResult { @@ -984,7 +984,7 @@ impl Parser { let defs = self .try_reduce_method_defs(maybe_class, vis) .map_err(|_| self.stack_dec())?; - let expr = Expr::MethodDefs(defs); + let expr = Expr::Methods(defs); assert_eq!(stack.len(), 0); self.level -= 1; return Ok(expr); @@ -1042,7 +1042,7 @@ impl Parser { let defs = self .try_reduce_method_defs(maybe_class, vis) .map_err(|_| self.stack_dec())?; - return Ok(Expr::MethodDefs(defs)); + return Ok(Expr::Methods(defs)); } other => { self.restore(other); From de9788a5fad65a2a79123bed1b05c2308bc59a17 Mon Sep 17 00:00:00 2001 From: Shunsuke Shibayama Date: Tue, 6 Sep 2022 22:17:10 +0900 Subject: [PATCH 30/68] Update faq_general.md --- doc/EN/faq_general.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/EN/faq_general.md b/doc/EN/faq_general.md index 331212e5..f69f45a6 100644 --- a/doc/EN/faq_general.md +++ b/doc/EN/faq_general.md @@ -15,10 +15,10 @@ A: Erg code is transpiled into Python bytecode. That is, it runs on the same int We have been influenced by more languages than we can count on both hands, but Python, Rust, Nim, and Haskell have been the strongest influences. We inherited many semantics from Python, expression-oriented and trait from Rust, procedures from Nim, and functional programming-related features from Haskell. -## Languages that can call Python include Julia. Why did you create Erg? +## There are already languages that can call Python, such as Julia. Why did you create Erg? -A: One of the motivations for Erg's design was to have a language that is easy to use, yet has a powerful type system. That is, a language with type inference, Kind, dependent types, etc. -Julia can be typed, but it is really a dynamically typed language and does not have the compile-time error detection benefits of statically typed languages. +A: One of the motivations for Erg's design was to have a language that is easy to use, yet has a powerful type system. That is, a language with type inference, dependent types, etc. +Julia can be typed, but it is really a dynamically typed language and does not have the advantage of perfect compile-time type error detection like statically typed languages. ## Erg supports multiple styles of programming, including functional and object-oriented programming. Isn't this contrary to Python's "There should be one --and preferably only one-- obvious way to do it."? From e021ce71a716bba226183eaa6613c338820972a9 Mon Sep 17 00:00:00 2001 From: Shunsuke Shibayama Date: Tue, 6 Sep 2022 22:20:00 +0900 Subject: [PATCH 31/68] Update docs --- doc/JA/faq_general.md | 2 +- doc/zh_CN/faq_general.md | 6 +++--- doc/zh_TW/faq_general.md | 6 +++--- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/doc/JA/faq_general.md b/doc/JA/faq_general.md index f950b405..e40b60b2 100644 --- a/doc/JA/faq_general.md +++ b/doc/JA/faq_general.md @@ -1,6 +1,6 @@ # Erg FAQ -[![badge](https://img.shields.io/endpoint.svg?url=https%3A%2F%2Fgezf7g7pd5.execute-api.ap-northeast-1.amazonaws.com%2Fdefault%2Fsource_up_to_date%3Fowner%3Derg-lang%26repos%3Derg%26ref%3Dmain%26path%3Ddoc/EN/faq_general.md%26commit_hash%3Deccd113c1512076c367fb87ea73406f91ff83ba7)](https://gezf7g7pd5.execute-api.ap-northeast-1.amazonaws.com/default/source_up_to_date?owner=erg-lang&repos=erg&ref=main&path=doc/EN/faq_general.md&commit_hash=eccd113c1512076c367fb87ea73406f91ff83ba7) +[![badge](https://img.shields.io/endpoint.svg?url=https%3A%2F%2Fgezf7g7pd5.execute-api.ap-northeast-1.amazonaws.com%2Fdefault%2Fsource_up_to_date%3Fowner%3Derg-lang%26repos%3Derg%26ref%3Dmain%26path%3Ddoc/EN/faq_general.md%26commit_hash%3Dde9788a5fad65a2a79123bed1b05c2308bc59a17)](https://gezf7g7pd5.execute-api.ap-northeast-1.amazonaws.com/default/source_up_to_date?owner=erg-lang&repos=erg&ref=main&path=doc/EN/faq_general.md&commit_hash=de9788a5fad65a2a79123bed1b05c2308bc59a17) このFAQは一般のErg入門者向けです。 個別の(よくある)技術的な問題については[こちら](./faq_technical.md)を、文法の決定経緯(なぜこのような文法になったのか)などについては diff --git a/doc/zh_CN/faq_general.md b/doc/zh_CN/faq_general.md index 92293ab9..131c0aae 100644 --- a/doc/zh_CN/faq_general.md +++ b/doc/zh_CN/faq_general.md @@ -1,6 +1,6 @@ # Erg常见问题 -[![badge](https://img.shields.io/endpoint.svg?url=https%3A%2F%2Fgezf7g7pd5.execute-api.ap-northeast-1.amazonaws.com%2Fdefault%2Fsource_up_to_date%3Fowner%3Derg-lang%26repos%3Derg%26ref%3Dmain%26path%3Ddoc/EN/faq_general.md%26commit_hash%3Deccd113c1512076c367fb87ea73406f91ff83ba7)](https://gezf7g7pd5.execute-api.ap-northeast-1.amazonaws.com/default/source_up_to_date?owner=erg-lang&repos=erg&ref=main&path=doc/EN/faq_general.md&commit_hash=eccd113c1512076c367fb87ea73406f91ff83ba7) +[![badge](https://img.shields.io/endpoint.svg?url=https%3A%2F%2Fgezf7g7pd5.execute-api.ap-northeast-1.amazonaws.com%2Fdefault%2Fsource_up_to_date%3Fowner%3Derg-lang%26repos%3Derg%26ref%3Dmain%26path%3Ddoc/EN/faq_general.md%26commit_hash%3Dde9788a5fad65a2a79123bed1b05c2308bc59a17)](https://gezf7g7pd5.execute-api.ap-northeast-1.amazonaws.com/default/source_up_to_date?owner=erg-lang&repos=erg&ref=main&path=doc/EN/faq_general.md&commit_hash=de9788a5fad65a2a79123bed1b05c2308bc59a17) This FAQ is intended for the general Erg beginner. For individual (common) technical issues, please refer to [here](./faq_technical.md) for individual (common) technical issues, and @@ -17,7 +17,7 @@ A: Erg 代码被转译成 Python 字节码。也就是说,它运行在与 Pyth 我们受到的语言多于我们双手所能指望的数量,但 Python、Rust、Nim 和 Haskell 的影响最大。 我们从 Python 继承了许多语义,从 Rust 继承了面向表达式和 trait,从 Nim 继承了过程,从 Haskell 继承了函数式编程相关的特性。 -## 可以调用 Python 的语言包括 Julia。你为什么创建 Erg? +## 已经有一些语言可以调用Python,比如Julia。为什么要创建Erg? 答:Erg 设计的动机之一是拥有一种易于使用且具有强大类型系统的语言。即具有类型推断、种类、依赖类型等的语言。 Julia 是可以有类型的,但它确实是一种动态类型语言,不具备静态类型语言的编译时错误检测优势。 @@ -36,4 +36,4 @@ Julia 是可以有类型的,但它确实是一种动态类型语言,不具 它以cgs单位系统中的能量单位erg命名。它具有双重含义:一种为程序员提供能量的符合人体工程学的语言。 -还有其他几个候选者,但之所以选择它是因为它最短(根据 Ruby 的开发者 Matz 的说法,语言名称越短越好)并且具有相当高的可搜索性。 \ No newline at end of file +还有其他几个候选者,但之所以选择它是因为它最短(根据 Ruby 的开发者 Matz 的说法,语言名称越短越好)并且具有相当高的可搜索性。 diff --git a/doc/zh_TW/faq_general.md b/doc/zh_TW/faq_general.md index b687922b..70ebc27d 100644 --- a/doc/zh_TW/faq_general.md +++ b/doc/zh_TW/faq_general.md @@ -1,6 +1,6 @@ # Erg常見問題 -[![badge](https://img.shields.io/endpoint.svg?url=https%3A%2F%2Fgezf7g7pd5.execute-api.ap-northeast-1.amazonaws.com%2Fdefault%2Fsource_up_to_date%3Fowner%3Derg-lang%26repos%3Derg%26ref%3Dmain%26path%3Ddoc/EN/faq_general.md%26commit_hash%3Deccd113c1512076c367fb87ea73406f91ff83ba7)](https://gezf7g7pd5.execute-api.ap-northeast-1.amazonaws.com/default/source_up_to_date?owner=erg-lang&repos=erg&ref=main&path=doc/EN/faq_general.md&commit_hash=eccd113c1512076c367fb87ea73406f91ff83ba7) +[![badge](https://img.shields.io/endpoint.svg?url=https%3A%2F%2Fgezf7g7pd5.execute-api.ap-northeast-1.amazonaws.com%2Fdefault%2Fsource_up_to_date%3Fowner%3Derg-lang%26repos%3Derg%26ref%3Dmain%26path%3Ddoc/EN/faq_general.md%26commit_hash%3Dde9788a5fad65a2a79123bed1b05c2308bc59a17)](https://gezf7g7pd5.execute-api.ap-northeast-1.amazonaws.com/default/source_up_to_date?owner=erg-lang&repos=erg&ref=main&path=doc/EN/faq_general.md&commit_hash=de9788a5fad65a2a79123bed1b05c2308bc59a17) This FAQ is intended for the general Erg beginner. For individual (common) technical issues, please refer to [here](./faq_technical.md) for individual (common) technical issues, and @@ -17,7 +17,7 @@ A: Erg 代碼被轉譯成 Python 字節碼。也就是說,它運行在與 Pyth 我們受到的語言多于我們雙手所能指望的數量,但 Python、Rust、Nim 和 Haskell 的影響最大。 我們從 Python 繼承了許多語義,從 Rust 繼承了面向表達式和 trait,從 Nim 繼承了過程,從 Haskell 繼承了函數式編程相關的特性。 -## 可以調用 Python 的語言包括 Julia。你為什么創建 Erg? +## 已經有一些語言可以調用Python,比如Julia。為什麼要創建Erg? 答:Erg 設計的動機之一是擁有一種易于使用且具有強大類型系統的語言。即具有類型推斷、種類、依賴類型等的語言。 Julia 是可以有類型的,但它確實是一種動態類型語言,不具備靜態類型語言的編譯時錯誤檢測優勢。 @@ -36,4 +36,4 @@ Julia 是可以有類型的,但它確實是一種動態類型語言,不具 它以cgs單位系統中的能量單位erg命名。它具有雙重含義:一種為程序員提供能量的符合人體工程學的語言。 -還有其他幾個候選者,但之所以選擇它是因為它最短(根據 Ruby 的開發者 Matz 的說法,語言名稱越短越好)并且具有相當高的可搜索性。 \ No newline at end of file +還有其他幾個候選者,但之所以選擇它是因為它最短(根據 Ruby 的開發者 Matz 的說法,語言名稱越短越好)并且具有相當高的可搜索性。 From 5029d71cbeb0ebc6940618a1f52dbc91aa33d047 Mon Sep 17 00:00:00 2001 From: Shunsuke Shibayama Date: Wed, 7 Sep 2022 14:48:02 +0900 Subject: [PATCH 32/68] Impl: auto generating of `new` --- compiler/erg_common/error.rs | 18 +- compiler/erg_common/vis.rs | 4 +- compiler/erg_compiler/codegen.rs | 181 +++++++++++++++--- .../context/initialize/const_func.rs | 39 ++-- .../erg_compiler/context/initialize/mod.rs | 15 +- compiler/erg_compiler/context/register.rs | 5 +- compiler/erg_compiler/context/tyvar.rs | 7 + compiler/erg_compiler/hir.rs | 113 +++++++++-- compiler/erg_compiler/lower.rs | 45 +++-- compiler/erg_parser/ast.rs | 6 +- compiler/erg_parser/token.rs | 10 + compiler/erg_type/lib.rs | 36 +++- compiler/erg_type/value.rs | 10 +- 13 files changed, 401 insertions(+), 88 deletions(-) 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, } } } From 1d38b895e820c993980857943ca2f957ae07ac10 Mon Sep 17 00:00:00 2001 From: Shunsuke Shibayama Date: Wed, 7 Sep 2022 14:53:04 +0900 Subject: [PATCH 33/68] Add debugging displaying for `codegen` --- compiler/erg_compiler/codegen.rs | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/compiler/erg_compiler/codegen.rs b/compiler/erg_compiler/codegen.rs index 7d6e8733..c4c01c10 100644 --- a/compiler/erg_compiler/codegen.rs +++ b/compiler/erg_compiler/codegen.rs @@ -11,7 +11,8 @@ use erg_common::opcode::Opcode; use erg_common::traits::{Locational, Stream}; use erg_common::Str; use erg_common::{ - debug_power_assert, enum_unwrap, fn_name_full, impl_stream_for_wrapper, log, switch_unreachable, + debug_power_assert, enum_unwrap, fn_name, fn_name_full, impl_stream_for_wrapper, log, + switch_unreachable, }; use erg_parser::ast::DefId; use erg_type::codeobj::{CodeObj, CodeObjFlags}; @@ -551,6 +552,7 @@ impl CodeGenerator { } fn emit_load_name_instr(&mut self, ident: Identifier) -> CompileResult<()> { + log!(info "entered {}", fn_name!()); let name = self .local_search(ident.inspect(), Name) .unwrap_or_else(|| self.register_name(ident)); @@ -567,6 +569,7 @@ impl CodeGenerator { } fn emit_import_name_instr(&mut self, ident: Identifier) -> CompileResult<()> { + log!(info "entered {}", fn_name!()); let name = self .local_search(ident.inspect(), Name) .unwrap_or_else(|| self.register_name(ident)); @@ -577,6 +580,7 @@ impl CodeGenerator { } fn emit_import_from_instr(&mut self, ident: Identifier) -> CompileResult<()> { + log!(info "entered {}", fn_name!()); let name = self .local_search(ident.inspect(), Name) .unwrap_or_else(|| self.register_name(ident)); @@ -592,6 +596,7 @@ impl CodeGenerator { uniq_obj_name: Option<&str>, name: Str, ) -> CompileResult<()> { + log!(info "entered {}", fn_name!()); let name = self .local_search(&name, Attr) .unwrap_or_else(|| self.register_attr(class, uniq_obj_name, name)); @@ -612,6 +617,7 @@ impl CodeGenerator { uniq_obj_name: Option<&str>, name: Str, ) -> CompileResult<()> { + log!(info "entered {}", fn_name!()); let name = self .local_search(&name, Method) .unwrap_or_else(|| self.register_method(class, uniq_obj_name, name)); @@ -627,6 +633,7 @@ impl CodeGenerator { } fn emit_store_instr(&mut self, ident: Identifier, acc_kind: AccessKind) { + log!(info "entered {}", fn_name!()); let name = self .local_search(ident.inspect(), acc_kind) .unwrap_or_else(|| self.register_name(ident)); @@ -650,6 +657,7 @@ impl CodeGenerator { } fn store_acc(&mut self, acc: Accessor) { + log!(info "entered {}", fn_name!()); match acc { Accessor::Local(local) => { self.emit_store_instr(Identifier::new(None, VarName::new(local.name)), Name); @@ -711,6 +719,7 @@ impl CodeGenerator { } fn emit_class_def(&mut self, class_def: ClassDef) { + log!(info "entered {}", fn_name!()); let ident = class_def.sig.ident().clone(); let kind = class_def.kind; let require_or_sup = class_def.require_or_sup.clone(); @@ -735,6 +744,7 @@ impl CodeGenerator { // fn emit_poly_type_def(&mut self, sig: SubrSignature, body: DefBody) {} fn emit_require_type(&mut self, kind: TypeKind, require_or_sup: Expr) -> usize { + log!(info "entered {}", fn_name!()); match kind { TypeKind::Class => 0, TypeKind::Subclass => { @@ -746,11 +756,13 @@ impl CodeGenerator { } fn emit_attr_def(&mut self, attr_def: AttrDef) { + log!(info "entered {}", fn_name!()); 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) { + log!(info "entered {}", fn_name!()); if body.block.len() == 1 { self.codegen_expr(body.block.remove(0)); } else { @@ -760,6 +772,7 @@ impl CodeGenerator { } fn emit_subr_def(&mut self, sig: SubrSignature, body: DefBody) { + log!(info "entered {}", fn_name!()); let name = sig.ident.inspect().clone(); let mut opcode_flag = 0u8; let params = self.gen_param_names(&sig.params); @@ -784,6 +797,7 @@ impl CodeGenerator { } fn emit_discard_instr(&mut self, mut args: Args) -> CompileResult<()> { + log!(info "entered {}", fn_name!()); while let Some(arg) = args.try_remove(0) { self.codegen_expr(arg); self.emit_pop_top(); @@ -792,6 +806,7 @@ impl CodeGenerator { } fn emit_if_instr(&mut self, mut args: Args) -> CompileResult<()> { + log!(info "entered {}", fn_name!()); let cond = args.remove(0); self.codegen_expr(cond); let idx_pop_jump_if_false = self.cur_block().lasti; @@ -840,6 +855,7 @@ impl CodeGenerator { } fn emit_for_instr(&mut self, mut args: Args) -> CompileResult<()> { + log!(info "entered {}", fn_name!()); let iterable = args.remove(0); self.codegen_expr(iterable); self.write_instr(GET_ITER); @@ -862,6 +878,7 @@ impl CodeGenerator { } fn emit_match_instr(&mut self, mut args: Args, _use_erg_specific: bool) -> CompileResult<()> { + log!(info "entered {}", fn_name!()); let expr = args.remove(0); self.codegen_expr(expr); let len = args.len(); @@ -898,6 +915,7 @@ impl CodeGenerator { } fn emit_match_pattern(&mut self, pat: ParamPattern) -> CompileResult> { + log!(info "entered {}", fn_name!()); let mut pop_jump_points = vec![]; match pat { ParamPattern::VarName(name) => { @@ -951,6 +969,7 @@ impl CodeGenerator { } fn emit_call(&mut self, call: Call) { + log!(info "entered {}", fn_name!()); if let Some(method_name) = call.method_name { self.emit_call_method(*call.obj, method_name, call.args); } else { @@ -964,6 +983,7 @@ impl CodeGenerator { } fn emit_call_local(&mut self, local: Local, mut args: Args) -> CompileResult<()> { + log!(info "entered {}", fn_name!()); match &local.inspect()[..] { "assert" => self.emit_assert_instr(args), "discard" => self.emit_discard_instr(args), @@ -1003,6 +1023,7 @@ impl CodeGenerator { } fn emit_call_method(&mut self, obj: Expr, method_name: Token, mut args: Args) { + log!(info "entered {}", fn_name!()); if &method_name.inspect()[..] == "update!" { return self.emit_call_update(obj, args); } @@ -1044,6 +1065,7 @@ impl CodeGenerator { /// X = (x -> x + 1)(X) /// X = X + 1 fn emit_call_update(&mut self, obj: Expr, mut args: Args) { + log!(info "entered {}", fn_name!()); let acc = enum_unwrap!(obj, Expr::Accessor); let func = args.remove_left_or_key("f").unwrap(); self.codegen_expr(func); @@ -1057,6 +1079,7 @@ impl CodeGenerator { // assert takes 1 or 2 arguments (0: cond, 1: message) fn emit_assert_instr(&mut self, mut args: Args) -> CompileResult<()> { + log!(info "entered {}", fn_name!()); self.codegen_expr(args.remove(0)); let pop_jump_point = self.cur_block().lasti; self.write_instr(Opcode::POP_JUMP_IF_TRUE); @@ -1077,6 +1100,7 @@ impl CodeGenerator { } fn codegen_expr(&mut self, expr: Expr) { + log!(info "entered {}", fn_name!()); if expr.ln_begin().unwrap_or_else(|| panic!("{expr}")) > self.cur_block().prev_lineno { let sd = self.cur_block().lasti - self.cur_block().prev_lasti; let ld = expr.ln_begin().unwrap() - self.cur_block().prev_lineno; @@ -1315,6 +1339,7 @@ impl CodeGenerator { } fn codegen_acc(&mut self, acc: Accessor) { + log!(info "entered {}", fn_name!()); match acc { Accessor::Local(local) => { self.emit_load_name_instr(Identifier::new(None, VarName::new(local.name))) @@ -1360,6 +1385,7 @@ impl CodeGenerator { /// forブロックなどで使う fn codegen_frameless_block(&mut self, block: Block, params: Vec) { + log!(info "entered {}", fn_name!()); for param in params { self.emit_store_instr(Identifier::private(param), Name); } @@ -1375,6 +1401,7 @@ impl CodeGenerator { } fn codegen_typedef_block(&mut self, class: ClassDef) -> CodeObj { + log!(info "entered {}", fn_name!()); let name = class.sig.ident().inspect().clone(); self.unit_size += 1; let firstlineno = match ( @@ -1450,6 +1477,7 @@ impl CodeGenerator { } fn emit_auto_new(&mut self, sig: &Signature, __new__: Type) { + log!(info "entered {}", fn_name!()); let line = sig.ln_begin().unwrap(); let ident = Identifier::private_with_line(Str::ever("__new__"), line); let param_name = fresh_varname(); @@ -1506,6 +1534,7 @@ impl CodeGenerator { } fn codegen_block(&mut self, block: Block, opt_name: Option, params: Vec) -> CodeObj { + log!(info "entered {}", fn_name!()); self.unit_size += 1; let name = if let Some(name) = opt_name { name From edab3a8ad277e9608a6cf1cde6e6b9e897df7a51 Mon Sep 17 00:00:00 2001 From: Shunsuke Shibayama Date: Wed, 7 Sep 2022 16:37:03 +0900 Subject: [PATCH 34/68] Fix codegen bug --- compiler/erg_compiler/codegen.rs | 140 +++++++++++++++++-------------- 1 file changed, 78 insertions(+), 62 deletions(-) diff --git a/compiler/erg_compiler/codegen.rs b/compiler/erg_compiler/codegen.rs index c4c01c10..641357e3 100644 --- a/compiler/erg_compiler/codegen.rs +++ b/compiler/erg_compiler/codegen.rs @@ -32,7 +32,7 @@ use crate::error::{CompileError, CompileErrors, CompileResult}; use crate::hir::AttrDef; use crate::hir::Attribute; use crate::hir::{ - Accessor, Args, Array, Block, Call, ClassDef, Def, DefBody, Expr, Local, Signature, + Accessor, Args, Array, Block, Call, ClassDef, Def, DefBody, Expr, Literal, Local, Signature, SubrSignature, Tuple, VarSignature, HIR, }; use AccessKind::*; @@ -202,7 +202,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__"), + (_, _, "new" | "__new__") => Str::ever("__call__"), ("StringIO!", _, "getvalue!") => Str::ever("getvalue"), ("Module", Some("importlib"), "reload!") => Str::ever("reload"), ("Module", Some("random"), "randint!") => Str::ever("randint"), @@ -319,7 +319,7 @@ impl_stream_for_wrapper!(CodeGenStack, CodeGenUnit); pub struct CodeGenerator { cfg: ErgConfig, str_cache: CacheSet, - namedtuple_loaded: bool, + prelude_loaded: bool, unit_size: usize, units: CodeGenStack, pub(crate) errs: CompileErrors, @@ -330,7 +330,7 @@ impl CodeGenerator { Self { cfg, str_cache: CacheSet::new(), - namedtuple_loaded: false, + prelude_loaded: false, unit_size: 0, units: CodeGenStack::empty(), errs: CompileErrors::empty(), @@ -596,7 +596,7 @@ impl CodeGenerator { uniq_obj_name: Option<&str>, name: Str, ) -> CompileResult<()> { - log!(info "entered {}", fn_name!()); + log!(info "entered {} ({class}.{name})", fn_name!()); let name = self .local_search(&name, Attr) .unwrap_or_else(|| self.register_attr(class, uniq_obj_name, name)); @@ -617,7 +617,7 @@ impl CodeGenerator { uniq_obj_name: Option<&str>, name: Str, ) -> CompileResult<()> { - log!(info "entered {}", fn_name!()); + log!(info "entered {} ({class}.{name})", fn_name!()); let name = self .local_search(&name, Method) .unwrap_or_else(|| self.register_method(class, uniq_obj_name, name)); @@ -633,14 +633,22 @@ impl CodeGenerator { } fn emit_store_instr(&mut self, ident: Identifier, acc_kind: AccessKind) { - log!(info "entered {}", fn_name!()); + log!(info "entered {} ({ident})", fn_name!()); let name = self .local_search(ident.inspect(), acc_kind) - .unwrap_or_else(|| self.register_name(ident)); + .unwrap_or_else(|| { + if acc_kind.is_local() { + self.register_name(ident) + } else { + self.register_attr("", None, ident.inspect().clone()) + } + }); let instr = match name.kind { StoreLoadKind::Fast => Opcode::STORE_FAST, StoreLoadKind::FastConst => Opcode::ERG_STORE_FAST_IMMUT, - StoreLoadKind::Global | StoreLoadKind::GlobalConst => Opcode::STORE_GLOBAL, + // NOTE: First-time variables are treated as GLOBAL, but they are always first-time variables when assigned, so they are just NAME + // NOTE: 初見の変数はGLOBAL扱いになるが、代入時は必ず初見であるので単なるNAME + StoreLoadKind::Global | StoreLoadKind::GlobalConst => Opcode::STORE_NAME, StoreLoadKind::Deref | StoreLoadKind::DerefConst => Opcode::STORE_DEREF, StoreLoadKind::Local | StoreLoadKind::LocalConst => { match acc_kind { @@ -654,10 +662,13 @@ impl CodeGenerator { self.write_instr(instr); self.write_arg(name.idx as u8); self.stack_dec(); + if instr == Opcode::STORE_ATTR { + self.stack_dec(); + } } fn store_acc(&mut self, acc: Accessor) { - log!(info "entered {}", fn_name!()); + log!(info "entered {} ({acc})", fn_name!()); match acc { Accessor::Local(local) => { self.emit_store_instr(Identifier::new(None, VarName::new(local.name)), Name); @@ -719,7 +730,7 @@ impl CodeGenerator { } fn emit_class_def(&mut self, class_def: ClassDef) { - log!(info "entered {}", fn_name!()); + log!(info "entered {} ({class_def})", fn_name!()); let ident = class_def.sig.ident().clone(); let kind = class_def.kind; let require_or_sup = class_def.require_or_sup.clone(); @@ -732,19 +743,20 @@ impl CodeGenerator { self.write_instr(Opcode::MAKE_FUNCTION); self.write_arg(0); self.emit_load_const(ident.inspect().clone()); - let subclasses_len = self.emit_require_type(kind, *require_or_sup); // LOAD subclasses + let subclasses_len = self.emit_require_type(kind, *require_or_sup); self.write_instr(Opcode::CALL_FUNCTION); self.write_arg(2 + subclasses_len as u8); self.stack_dec_n((1 + 2 + subclasses_len) - 1); self.emit_store_instr(ident, Name); + self.stack_dec(); } // 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 { - log!(info "entered {}", fn_name!()); + log!(info "entered {} ({kind:?}, {require_or_sup})", fn_name!()); match kind { TypeKind::Class => 0, TypeKind::Subclass => { @@ -756,13 +768,13 @@ impl CodeGenerator { } fn emit_attr_def(&mut self, attr_def: AttrDef) { - log!(info "entered {}", fn_name!()); + log!(info "entered {} ({attr_def})", fn_name!()); 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) { - log!(info "entered {}", fn_name!()); + log!(info "entered {} ({sig} = {})", fn_name!(), body.block); if body.block.len() == 1 { self.codegen_expr(body.block.remove(0)); } else { @@ -772,7 +784,7 @@ impl CodeGenerator { } fn emit_subr_def(&mut self, sig: SubrSignature, body: DefBody) { - log!(info "entered {}", fn_name!()); + log!(info "entered {} ({sig} = {})", fn_name!(), body.block); let name = sig.ident.inspect().clone(); let mut opcode_flag = 0u8; let params = self.gen_param_names(&sig.params); @@ -969,7 +981,7 @@ impl CodeGenerator { } fn emit_call(&mut self, call: Call) { - log!(info "entered {}", fn_name!()); + log!(info "entered {} ({call})", fn_name!()); if let Some(method_name) = call.method_name { self.emit_call_method(*call.obj, method_name, call.args); } else { @@ -1100,7 +1112,7 @@ impl CodeGenerator { } fn codegen_expr(&mut self, expr: Expr) { - log!(info "entered {}", fn_name!()); + log!(info "entered {} ({expr})", fn_name!()); if expr.ln_begin().unwrap_or_else(|| panic!("{expr}")) > self.cur_block().prev_lineno { let sd = self.cur_block().lasti - self.cur_block().prev_lasti; let ld = expr.ln_begin().unwrap() - self.cur_block().prev_lineno; @@ -1280,20 +1292,6 @@ impl CodeGenerator { }, Expr::Record(rec) => { let attrs_len = rec.attrs.len(); - // importing namedtuple - if !self.namedtuple_loaded { - self.emit_load_const(0); - self.emit_load_const(ValueObj::Tuple(std::rc::Rc::from([ValueObj::Str( - Str::ever("namedtuple"), - )]))); - let ident = Identifier::public("collections"); - self.emit_import_name_instr(ident).unwrap(); - let ident = Identifier::public("namedtuple"); - self.emit_import_from_instr(ident).unwrap(); - let ident = Identifier::private(Str::ever("#NamedTuple")); - self.emit_store_instr(ident, Name); - self.namedtuple_loaded = true; - } // making record type let ident = Identifier::private(Str::ever("#NamedTuple")); self.emit_load_name_instr(ident).unwrap(); @@ -1339,7 +1337,7 @@ impl CodeGenerator { } fn codegen_acc(&mut self, acc: Accessor) { - log!(info "entered {}", fn_name!()); + log!(info "entered {} ({acc})", fn_name!()); match acc { Accessor::Local(local) => { self.emit_load_name_instr(Identifier::new(None, VarName::new(local.name))) @@ -1421,9 +1419,9 @@ impl CodeGenerator { )); 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_store_instr(Identifier::public("__module__"), Name); self.emit_load_const(name); - self.emit_store_instr(Identifier::public("__qualname__"), Attr); + self.emit_store_instr(Identifier::public("__qualname__"), Name); if class.need_to_gen_new { self.emit_auto_new(&class.sig, class.__new__); } @@ -1479,19 +1477,13 @@ impl CodeGenerator { fn emit_auto_new(&mut self, sig: &Signature, __new__: Type) { log!(info "entered {}", fn_name!()); let line = sig.ln_begin().unwrap(); - let ident = Identifier::private_with_line(Str::ever("__new__"), line); + 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 params = Params::new( - vec![ParamSignature::new( - ParamPattern::VarName(param), - None, - None, - )], - None, - vec![], - None, - ); + let param = ParamSignature::new(ParamPattern::VarName(param), None, 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 params = Params::new(vec![self_param, param], 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() { @@ -1503,34 +1495,32 @@ impl CodeGenerator { 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 obj = Expr::Accessor(Accessor::local( + Token::symbol_with_line("self", line), + Type::Failure, + )); + let attr = 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)); } + let none = Token::new(TokenKind::NoneLit, "None", line, 0); + attrs.push(Expr::Lit(Literal::from(none))); } 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)); + let init_def = Def::new(sig, body.clone()); + self.codegen_expr(Expr::Def(init_def)); } fn codegen_block(&mut self, block: Block, opt_name: Option, params: Vec) -> CodeObj { @@ -1582,7 +1572,10 @@ impl CodeGenerator { // end of flagging let unit = self.units.pop().unwrap(); if !self.units.is_empty() { - let ld = unit.prev_lineno - self.cur_block().prev_lineno; + let ld = unit + .prev_lineno + .checked_sub(self.cur_block().prev_lineno) + .unwrap_or(0); if ld != 0 { if let Some(l) = self.mut_cur_block_codeobj().lnotab.last_mut() { *l += ld as u8; @@ -1593,6 +1586,25 @@ impl CodeGenerator { unit.codeobj } + fn load_prelude(&mut self) { + self.init_record(); + } + + fn init_record(&mut self) { + // importing namedtuple + self.emit_load_const(0); + self.emit_load_const(ValueObj::Tuple(std::rc::Rc::from([ValueObj::Str( + Str::ever("namedtuple"), + )]))); + let ident = Identifier::public("collections"); + self.emit_import_name_instr(ident).unwrap(); + let ident = Identifier::public("namedtuple"); + self.emit_import_from_instr(ident).unwrap(); + let ident = Identifier::private(Str::ever("#NamedTuple")); + self.emit_store_instr(ident, Name); + // self.namedtuple_loaded = true; + } + pub fn codegen(&mut self, hir: HIR) -> CodeObj { log!(info "the code-generating process has started.{RESET}"); self.unit_size += 1; @@ -1603,6 +1615,10 @@ impl CodeGenerator { "", 1, )); + if !self.prelude_loaded { + self.load_prelude(); + self.prelude_loaded = true; + } let mut print_point = 0; if self.input().is_repl() { print_point = self.cur_block().lasti; From a00577248b58b9c8380d1426818f534427b60742 Mon Sep 17 00:00:00 2001 From: Shunsuke Shibayama Date: Wed, 7 Sep 2022 16:37:18 +0900 Subject: [PATCH 35/68] Update example script --- examples/class.er | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/examples/class.er b/examples/class.er index eed35b70..efec6d2a 100644 --- a/examples/class.er +++ b/examples/class.er @@ -11,7 +11,11 @@ Point3D. @Override norm ref self = self::x**2 + self::y**2 + self::z**2 +p = Point3D.new {x = 1; y = 2; z = 3} +print! p.norm() + UnpackPoint2D = Class {x = Int; y = Int}, Impl := Unpack -p = UnpackPoint2D::{x = 1; y = 2} -UnpackPoint2D::{x; y} = p +q = UnpackPoint2D::{x = 1; y = 2} +UnpackPoint2D::{x; y} = q +print! x, y From 3e3b8abaa14e19842bc1b16ff95dd42c0b111daf Mon Sep 17 00:00:00 2001 From: Shunsuke Shibayama Date: Wed, 7 Sep 2022 16:41:08 +0900 Subject: [PATCH 36/68] Update example scripts --- examples/class.er | 6 ------ examples/unpack.er | 5 +++++ 2 files changed, 5 insertions(+), 6 deletions(-) create mode 100644 examples/unpack.er diff --git a/examples/class.er b/examples/class.er index efec6d2a..d35964df 100644 --- a/examples/class.er +++ b/examples/class.er @@ -13,9 +13,3 @@ Point3D. p = Point3D.new {x = 1; y = 2; z = 3} print! p.norm() - -UnpackPoint2D = Class {x = Int; y = Int}, Impl := Unpack - -q = UnpackPoint2D::{x = 1; y = 2} -UnpackPoint2D::{x; y} = q -print! x, y diff --git a/examples/unpack.er b/examples/unpack.er new file mode 100644 index 00000000..b4823e43 --- /dev/null +++ b/examples/unpack.er @@ -0,0 +1,5 @@ +UnpackPoint2D = Class {x = Int; y = Int}, Impl := Unpack + +q = UnpackPoint2D::{x = 1; y = 2} +UnpackPoint2D::{x; y} = q +print! x, y From 521426cba21ed8b6eae5aff965dd14ef99af1228 Mon Sep 17 00:00:00 2001 From: Cai Bingjun <62678643+C-BJ@users.noreply.github.com> Date: Wed, 7 Sep 2022 20:11:23 +0800 Subject: [PATCH 37/68] Update faq_general.md --- doc/EN/faq_general.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/EN/faq_general.md b/doc/EN/faq_general.md index f69f45a6..8f371ab4 100644 --- a/doc/EN/faq_general.md +++ b/doc/EN/faq_general.md @@ -17,7 +17,7 @@ We inherited many semantics from Python, expression-oriented and trait from Rust ## There are already languages that can call Python, such as Julia. Why did you create Erg? -A: One of the motivations for Erg's design was to have a language that is easy to use, yet has a powerful type system. That is, a language with type inference, dependent types, etc. +A: One of the motivations for Erg's design was to have a language that is easy to use, yet has a powerful type system. That is a language with type inference, dependent types, etc. Julia can be typed, but it is really a dynamically typed language and does not have the advantage of perfect compile-time type error detection like statically typed languages. ## Erg supports multiple styles of programming, including functional and object-oriented programming. Isn't this contrary to Python's "There should be one --and preferably only one-- obvious way to do it."? From 7478094ab33750a4c44fb77683d1639fec7300ca Mon Sep 17 00:00:00 2001 From: Cai Bingjun <62678643+C-BJ@users.noreply.github.com> Date: Wed, 7 Sep 2022 20:12:18 +0800 Subject: [PATCH 38/68] Updata commit hash --- doc/JA/faq_general.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/JA/faq_general.md b/doc/JA/faq_general.md index e40b60b2..c86fcc92 100644 --- a/doc/JA/faq_general.md +++ b/doc/JA/faq_general.md @@ -1,6 +1,6 @@ # Erg FAQ -[![badge](https://img.shields.io/endpoint.svg?url=https%3A%2F%2Fgezf7g7pd5.execute-api.ap-northeast-1.amazonaws.com%2Fdefault%2Fsource_up_to_date%3Fowner%3Derg-lang%26repos%3Derg%26ref%3Dmain%26path%3Ddoc/EN/faq_general.md%26commit_hash%3Dde9788a5fad65a2a79123bed1b05c2308bc59a17)](https://gezf7g7pd5.execute-api.ap-northeast-1.amazonaws.com/default/source_up_to_date?owner=erg-lang&repos=erg&ref=main&path=doc/EN/faq_general.md&commit_hash=de9788a5fad65a2a79123bed1b05c2308bc59a17) +[![badge](https://img.shields.io/endpoint.svg?url=https%3A%2F%2Fgezf7g7pd5.execute-api.ap-northeast-1.amazonaws.com%2Fdefault%2Fsource_up_to_date%3Fowner%3Derg-lang%26repos%3Derg%26ref%3Dmain%26path%3Ddoc/EN/faq_general.md%26commit_hash%3D521426cba21ed8b6eae5aff965dd14ef99af1228)](https://gezf7g7pd5.execute-api.ap-northeast-1.amazonaws.com/default/source_up_to_date?owner=erg-lang&repos=erg&ref=main&path=doc/EN/faq_general.md&commit_hash=521426cba21ed8b6eae5aff965dd14ef99af1228) このFAQは一般のErg入門者向けです。 個別の(よくある)技術的な問題については[こちら](./faq_technical.md)を、文法の決定経緯(なぜこのような文法になったのか)などについては From 9c1f5a1ca5f21779fc7e4bc4d3db9e05f63f598a Mon Sep 17 00:00:00 2001 From: Cai Bingjun <62678643+C-BJ@users.noreply.github.com> Date: Wed, 7 Sep 2022 20:13:36 +0800 Subject: [PATCH 39/68] Updata commit hash --- doc/zh_CN/faq_general.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/zh_CN/faq_general.md b/doc/zh_CN/faq_general.md index 131c0aae..8ed5b287 100644 --- a/doc/zh_CN/faq_general.md +++ b/doc/zh_CN/faq_general.md @@ -1,6 +1,6 @@ # Erg常见问题 -[![badge](https://img.shields.io/endpoint.svg?url=https%3A%2F%2Fgezf7g7pd5.execute-api.ap-northeast-1.amazonaws.com%2Fdefault%2Fsource_up_to_date%3Fowner%3Derg-lang%26repos%3Derg%26ref%3Dmain%26path%3Ddoc/EN/faq_general.md%26commit_hash%3Dde9788a5fad65a2a79123bed1b05c2308bc59a17)](https://gezf7g7pd5.execute-api.ap-northeast-1.amazonaws.com/default/source_up_to_date?owner=erg-lang&repos=erg&ref=main&path=doc/EN/faq_general.md&commit_hash=de9788a5fad65a2a79123bed1b05c2308bc59a17) +[![badge](https://img.shields.io/endpoint.svg?url=https%3A%2F%2Fgezf7g7pd5.execute-api.ap-northeast-1.amazonaws.com%2Fdefault%2Fsource_up_to_date%3Fowner%3Derg-lang%26repos%3Derg%26ref%3Dmain%26path%3Ddoc/EN/faq_general.md%26commit_hash%3D521426cba21ed8b6eae5aff965dd14ef99af1228)](https://gezf7g7pd5.execute-api.ap-northeast-1.amazonaws.com/default/source_up_to_date?owner=erg-lang&repos=erg&ref=main&path=doc/EN/faq_general.md&commit_hash=521426cba21ed8b6eae5aff965dd14ef99af1228) This FAQ is intended for the general Erg beginner. For individual (common) technical issues, please refer to [here](./faq_technical.md) for individual (common) technical issues, and From 5afa633468726376458ace1f403301afb38ab7c2 Mon Sep 17 00:00:00 2001 From: Cai Bingjun <62678643+C-BJ@users.noreply.github.com> Date: Wed, 7 Sep 2022 20:13:52 +0800 Subject: [PATCH 40/68] Updata commit hash --- doc/zh_TW/faq_general.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/zh_TW/faq_general.md b/doc/zh_TW/faq_general.md index 70ebc27d..5d74f78e 100644 --- a/doc/zh_TW/faq_general.md +++ b/doc/zh_TW/faq_general.md @@ -1,6 +1,6 @@ # Erg常見問題 -[![badge](https://img.shields.io/endpoint.svg?url=https%3A%2F%2Fgezf7g7pd5.execute-api.ap-northeast-1.amazonaws.com%2Fdefault%2Fsource_up_to_date%3Fowner%3Derg-lang%26repos%3Derg%26ref%3Dmain%26path%3Ddoc/EN/faq_general.md%26commit_hash%3Dde9788a5fad65a2a79123bed1b05c2308bc59a17)](https://gezf7g7pd5.execute-api.ap-northeast-1.amazonaws.com/default/source_up_to_date?owner=erg-lang&repos=erg&ref=main&path=doc/EN/faq_general.md&commit_hash=de9788a5fad65a2a79123bed1b05c2308bc59a17) +[![badge](https://img.shields.io/endpoint.svg?url=https%3A%2F%2Fgezf7g7pd5.execute-api.ap-northeast-1.amazonaws.com%2Fdefault%2Fsource_up_to_date%3Fowner%3Derg-lang%26repos%3Derg%26ref%3Dmain%26path%3Ddoc/EN/faq_general.md%26commit_hash%3D521426cba21ed8b6eae5aff965dd14ef99af1228)](https://gezf7g7pd5.execute-api.ap-northeast-1.amazonaws.com/default/source_up_to_date?owner=erg-lang&repos=erg&ref=main&path=doc/EN/faq_general.md&commit_hash=521426cba21ed8b6eae5aff965dd14ef99af1228) This FAQ is intended for the general Erg beginner. For individual (common) technical issues, please refer to [here](./faq_technical.md) for individual (common) technical issues, and From 533fddcba5f24466cb9975df2579cd53d718fe45 Mon Sep 17 00:00:00 2001 From: Shunsuke Shibayama Date: Wed, 7 Sep 2022 21:42:03 +0900 Subject: [PATCH 41/68] WIP: Fix method searching bugs --- compiler/erg_compiler/context/inquire.rs | 36 +++++++++++++++++++---- compiler/erg_compiler/context/register.rs | 2 +- compiler/erg_compiler/hir.rs | 3 +- 3 files changed, 33 insertions(+), 8 deletions(-) diff --git a/compiler/erg_compiler/context/inquire.rs b/compiler/erg_compiler/context/inquire.rs index addb3971..2718e924 100644 --- a/compiler/erg_compiler/context/inquire.rs +++ b/compiler/erg_compiler/context/inquire.rs @@ -70,6 +70,14 @@ impl Context { }) .map(|(_, vi)| vi) }) + .or_else(|| { + for (_, def) in self.method_defs.iter() { + if let Some(vi) = def.get_current_scope_var(name) { + return Some(vi); + } + } + None + }) } fn get_context( @@ -332,13 +340,27 @@ impl Context { } else if let Some(vi) = ctx.decls.get(method_name.inspect()) { return Ok(vi.t()); } + for (_, methods_ctx) in ctx.method_defs.iter() { + if let Some(vi) = methods_ctx.locals.get(method_name.inspect()) { + return Ok(vi.t()); + } else if let Some(vi) = methods_ctx.decls.get(method_name.inspect()) { + return Ok(vi.t()); + } + } } - if let Some(ctx) = self.rec_get_singular_ctx(obj) { - if let Some(vi) = ctx.locals.get(method_name.inspect()) { + if let Some(singular_ctx) = self.rec_get_singular_ctx(obj) { + if let Some(vi) = singular_ctx.locals.get(method_name.inspect()) { return Ok(vi.t()); - } else if let Some(vi) = ctx.decls.get(method_name.inspect()) { + } else if let Some(vi) = singular_ctx.decls.get(method_name.inspect()) { return Ok(vi.t()); } + for (_, method_ctx) in singular_ctx.method_defs.iter() { + if let Some(vi) = method_ctx.locals.get(method_name.inspect()) { + return Ok(vi.t()); + } else if let Some(vi) = method_ctx.decls.get(method_name.inspect()) { + return Ok(vi.t()); + } + } return Err(TyCheckError::singular_no_attr_error( line!() as usize, method_name.loc(), @@ -1163,12 +1185,14 @@ impl Context { } fn rec_get_singular_ctx(&self, obj: &hir::Expr) -> Option<&Context> { + log!("{}", obj.ref_t()); match obj.ref_t() { // TODO: attr Type::Module => self.rec_get_mod(&obj.var_full_name()?), - Type::Type | Type::Class => self - .rec_get_nominal_type_ctx(&Type::Mono(Str::from(obj.var_full_name().unwrap()))) - .map(|(_, ctx)| ctx), + Type::Type | Type::Class => { + let typ = Type::Mono(Str::from(obj.var_full_name().unwrap())); + self.rec_get_nominal_type_ctx(&typ).map(|(_, ctx)| ctx) + } Type::Trait => todo!(), Type::Refinement(refine) => { self.rec_get_nominal_type_ctx(&refine.t).map(|(_, ctx)| ctx) diff --git a/compiler/erg_compiler/context/register.rs b/compiler/erg_compiler/context/register.rs index 34161f20..d1651959 100644 --- a/compiler/erg_compiler/context/register.rs +++ b/compiler/erg_compiler/context/register.rs @@ -415,7 +415,7 @@ impl Context { // TODO: visibility let vi = VarInfo::new(found_t, muty, Private, VarKind::Defined(id)); log!(info "Registered {}::{name}: {}", self.name, &vi.t); - self.params.push((Some(name.clone()), vi)); + self.locals.insert(name.clone(), vi); Ok(()) } } diff --git a/compiler/erg_compiler/hir.rs b/compiler/erg_compiler/hir.rs index d439ae12..e3c000a8 100644 --- a/compiler/erg_compiler/hir.rs +++ b/compiler/erg_compiler/hir.rs @@ -1336,7 +1336,8 @@ pub struct ClassDef { impl NestedDisplay for ClassDef { fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, level: usize) -> fmt::Result { self.sig.fmt_nest(f, level)?; - self.private_methods.fmt_nest(f, level)?; + writeln!(f, ":")?; + self.private_methods.fmt_nest(f, level + 1)?; self.public_methods.fmt_nest(f, level + 1) } } From a6876f10d0e2e41f17c01c5f44c9d87078ee26a7 Mon Sep 17 00:00:00 2001 From: Shunsuke Shibayama Date: Wed, 7 Sep 2022 21:56:33 +0900 Subject: [PATCH 42/68] Update class.er --- examples/class.er | 1 - 1 file changed, 1 deletion(-) diff --git a/examples/class.er b/examples/class.er index d35964df..755b14e8 100644 --- a/examples/class.er +++ b/examples/class.er @@ -1,7 +1,6 @@ @Inheritable Point2D = Class {x = Int; y = Int} Point2D. - new x, y = Point2D::__new__ {x; y} norm ref self = self::x**2 + self::y**2 Point3D = Inherit Point2D, Additional := {z = Int} From fe552e23b13af50f1a2e2bf21b4e38c7f882ab9b Mon Sep 17 00:00:00 2001 From: Shunsuke Shibayama Date: Thu, 8 Sep 2022 00:55:25 +0900 Subject: [PATCH 43/68] Fix parser bugs --- compiler/erg_parser/parse.rs | 156 +++++++++++++++++++---------------- compiler/erg_parser/token.rs | 9 +- examples/add.er | 2 +- 3 files changed, 89 insertions(+), 78 deletions(-) diff --git a/compiler/erg_parser/parse.rs b/compiler/erg_parser/parse.rs index e56877ca..0f148547 100644 --- a/compiler/erg_parser/parse.rs +++ b/compiler/erg_parser/parse.rs @@ -145,12 +145,6 @@ impl Parser { } } - fn throw_syntax_err(&mut self, l: &L, caused_by: &str) -> ParseError { - log!(err "error caused by: {caused_by}"); - self.next_expr(); - ParseError::simple_syntax_error(0, l.loc()) - } - fn skip_and_throw_syntax_err(&mut self, caused_by: &str) -> ParseError { let loc = self.peek().unwrap().loc(); log!(err "error caused by: {caused_by}"); @@ -275,7 +269,10 @@ impl Parser { Some(t) if t.is(EOF) => { break; } - Some(t) if t.is(Indent) || t.is(Dedent) => { + Some(t) if t.is(Indent) => { + switch_unreachable!() + } + Some(t) if t.is(Dedent) => { switch_unreachable!() } Some(_) => match self.try_reduce_chunk(true) { @@ -284,7 +281,7 @@ impl Parser { } Err(_) => {} }, - _ => switch_unreachable!(), + None => switch_unreachable!(), } } self.level -= 1; @@ -306,29 +303,22 @@ impl Parser { Some(t) if t.category_is(TC::Separator) => { self.skip(); } - Some(t) => { - if t.is(Indent) { - self.skip(); - while self.cur_is(Newline) { - self.skip(); - } - } else if self.cur_is(Dedent) { - self.skip(); - break; - } else if t.is(EOF) { - break; - } - match self.try_reduce_chunk(true) { - Ok(expr) => { - block.push(expr); - if self.cur_is(Dedent) { - self.skip(); - break; - } - } - Err(_) => {} - } + Some(t) if t.is(Indent) => { + self.skip(); } + Some(t) if t.is(Dedent) => { + self.skip(); + break; + } + Some(t) if t.is(EOF) => { + break; + } + Some(_) => match self.try_reduce_chunk(true) { + Ok(expr) => { + block.push(expr); + } + Err(_) => {} + }, _ => switch_unreachable!(), } } @@ -852,13 +842,22 @@ impl Parser { match self.peek() { Some(t) if t.category_is(TC::Separator) => { self.skip(); - if self.cur_is(Dedent) { - self.skip(); - break; - } + } + Some(t) if t.is(Dedent) => { + self.skip(); + break; + } + Some(_) => { let def = self.try_reduce_chunk(false).map_err(|_| self.stack_dec())?; - let def = option_enum_unwrap!(def, Expr::Def).unwrap_or_else(|| todo!()); - defs.push(def); + match def { + Expr::Def(def) => { + defs.push(def); + } + other => { + self.errs + .push(ParseError::simple_syntax_error(0, other.loc())); + } + } } _ => todo!(), } @@ -1066,6 +1065,11 @@ impl Parser { .map_err(|_| self.stack_dec())?; stack.push(ExprOrOp::Expr(Expr::Tuple(tup))); } + Some(t) if t.category_is(TC::Reserved) => { + self.level -= 1; + let err = self.skip_and_throw_syntax_err(caused_by!()); + self.errs.push(err); + } _ => { if stack.len() <= 1 { break; @@ -1208,6 +1212,12 @@ impl Parser { .map_err(|_| self.stack_dec())?; stack.push(ExprOrOp::Expr(Expr::Tuple(tup))); } + Some(t) if t.category_is(TC::Reserved) => { + self.level -= 1; + let err = self.skip_and_throw_syntax_err(caused_by!()); + self.errs.push(err); + return Err(()); + } _ => { if stack.len() <= 1 { break; @@ -1481,20 +1491,17 @@ impl Parser { match self.peek() { Some(t) if t.category_is(TC::Separator) => { self.skip(); - if self.cur_is(Dedent) { - self.skip(); - if self.cur_is(RBrace) { - let r_brace = self.lpop(); - self.level -= 1; - let attrs = RecordAttrs::from(attrs); - return Ok(NormalRecord::new(l_brace, r_brace, attrs)); - } else { - todo!() - } + } + Some(t) if t.is(Dedent) => { + self.skip(); + if self.cur_is(RBrace) { + let r_brace = self.lpop(); + self.level -= 1; + let attrs = RecordAttrs::from(attrs); + return Ok(NormalRecord::new(l_brace, r_brace, attrs)); + } else { + todo!() } - let def = self.try_reduce_chunk(false).map_err(|_| self.stack_dec())?; - let def = option_enum_unwrap!(def, Expr::Def).unwrap_or_else(|| todo!()); - attrs.push(def); } Some(term) if term.is(RBrace) => { let r_brace = self.lpop(); @@ -1502,6 +1509,11 @@ impl Parser { let attrs = RecordAttrs::from(attrs); return Ok(NormalRecord::new(l_brace, r_brace, attrs)); } + Some(_) => { + let def = self.try_reduce_chunk(false).map_err(|_| self.stack_dec())?; + let def = option_enum_unwrap!(def, Expr::Def).unwrap_or_else(|| todo!()); + attrs.push(def); + } _ => todo!(), } } @@ -1525,16 +1537,23 @@ impl Parser { match self.peek() { Some(t) if t.category_is(TC::Separator) => { self.skip(); - if self.cur_is(Dedent) { - self.skip(); - if self.cur_is(RBrace) { - let r_brace = self.lpop(); - self.level -= 1; - return Ok(ShortenedRecord::new(l_brace, r_brace, idents)); - } else { - todo!() - } + } + Some(t) if t.is(Dedent) => { + self.skip(); + if self.cur_is(RBrace) { + let r_brace = self.lpop(); + self.level -= 1; + return Ok(ShortenedRecord::new(l_brace, r_brace, idents)); + } else { + todo!() } + } + Some(term) if term.is(RBrace) => { + let r_brace = self.lpop(); + self.level -= 1; + return Ok(ShortenedRecord::new(l_brace, r_brace, idents)); + } + Some(_) => { let acc = self.try_reduce_acc().map_err(|_| self.stack_dec())?; let acc = match acc { Accessor::Local(local) => Identifier::new(None, VarName::new(local.symbol)), @@ -1545,11 +1564,6 @@ impl Parser { }; idents.push(acc); } - Some(term) if term.is(RBrace) => { - let r_brace = self.lpop(); - self.level -= 1; - return Ok(ShortenedRecord::new(l_brace, r_brace, idents)); - } _ => todo!(), } } @@ -1671,7 +1685,7 @@ impl Parser { } other => { self.level -= 1; - let err = self.throw_syntax_err(&other, caused_by!()); + let err = ParseError::simple_syntax_error(line!() as usize, other.loc()); self.errs.push(err); Err(()) } @@ -1696,7 +1710,7 @@ impl Parser { } other => { self.level -= 1; - let err = self.throw_syntax_err(&other, caused_by!()); + let err = ParseError::simple_syntax_error(line!() as usize, other.loc()); self.errs.push(err); Err(()) } @@ -1815,7 +1829,7 @@ impl Parser { .map_err(|_| self.stack_dec())?, other => { self.level -= 1; - let err = self.throw_syntax_err(&other, caused_by!()); + let err = ParseError::simple_syntax_error(line!() as usize, other.loc()); self.errs.push(err); return Err(()); } @@ -1837,7 +1851,7 @@ impl Parser { } other => { self.level -= 1; - let err = self.throw_syntax_err(&other, caused_by!()); + let err = ParseError::simple_syntax_error(line!() as usize, other.loc()); self.errs.push(err); return Err(()); } @@ -1890,7 +1904,7 @@ impl Parser { Expr::Accessor(Accessor::Local(local)) => { if &local.inspect()[..] == "self" && !allow_self { self.level -= 1; - let err = self.throw_syntax_err(&local, caused_by!()); + let err = ParseError::simple_syntax_error(line!() as usize, local.loc()); self.errs.push(err); return Err(()); } @@ -1962,14 +1976,14 @@ impl Parser { // TODO: Spread _other => { self.level -= 1; - let err = self.throw_syntax_err(&unary, caused_by!()); + let err = ParseError::simple_syntax_error(line!() as usize, unary.loc()); self.errs.push(err); Err(()) } }, other => { self.level -= 1; - let err = self.throw_syntax_err(&other, caused_by!()); + let err = ParseError::simple_syntax_error(line!() as usize, other.loc()); self.errs.push(err); Err(()) } @@ -2068,7 +2082,7 @@ impl Parser { } other => { self.level -= 1; - let err = self.throw_syntax_err(&other, caused_by!()); + let err = ParseError::simple_syntax_error(line!() as usize, other.loc()); self.errs.push(err); Err(()) } diff --git a/compiler/erg_parser/token.rs b/compiler/erg_parser/token.rs index 386a9117..b59efee1 100644 --- a/compiler/erg_parser/token.rs +++ b/compiler/erg_parser/token.rs @@ -187,10 +187,8 @@ pub enum TokenCategory { LambdaOp, /// \n ; Separator, - /// ^ (reserved) - Caret, - /// & - Amper, + /// ^ & + Reserved, /// @ AtSign, /// | @@ -224,8 +222,7 @@ impl TokenKind { Semi | Newline => TokenCategory::Separator, LParen | LBrace | LSqBr | Indent => TokenCategory::LEnclosure, RParen | RBrace | RSqBr | Dedent => TokenCategory::REnclosure, - Caret => TokenCategory::Caret, - Amper => TokenCategory::Amper, + Caret | Amper => TokenCategory::Reserved, AtSign => TokenCategory::AtSign, VBar => TokenCategory::VBar, UBar => TokenCategory::UBar, diff --git a/examples/add.er b/examples/add.er index 3ccac7bf..b0cc46b9 100644 --- a/examples/add.er +++ b/examples/add.er @@ -1,7 +1,7 @@ Point = Class {x = Int; y = Int}, Impl := Add() and Eq() Point. new x, y = Self::__new__ {x; y} - norm &self = self::x**2 + self::y**2 + norm self = self::x**2 + self::y**2 @Impl Add() `+` self, other = Self.new(self::x + other::x, self::y + other::y) From f38c4285fe59194c7b8de80781016c9501507e14 Mon Sep 17 00:00:00 2001 From: Shunsuke Shibayama Date: Thu, 8 Sep 2022 01:19:56 +0900 Subject: [PATCH 44/68] Fix `self` unify bugs --- compiler/erg_compiler/context/inquire.rs | 34 +++++++++++++++++++----- compiler/erg_compiler/ownercheck.rs | 8 ++++-- 2 files changed, 34 insertions(+), 8 deletions(-) diff --git a/compiler/erg_compiler/context/inquire.rs b/compiler/erg_compiler/context/inquire.rs index 2718e924..3224f460 100644 --- a/compiler/erg_compiler/context/inquire.rs +++ b/compiler/erg_compiler/context/inquire.rs @@ -594,7 +594,7 @@ impl Context { } Type::Subr(subr) => { let callee = if let Some(name) = method_name { - let attr = hir::Attribute::new(obj.clone(), name.clone(), Type::Ellipsis); + let attr = hir::Attribute::new(obj.clone(), name.clone(), Type::Uninited); let acc = hir::Expr::Accessor(hir::Accessor::Attr(attr)); acc } else { @@ -615,12 +615,34 @@ impl Context { )); } let mut passed_params = set! {}; - if pos_args.len() >= subr.non_default_params.len() { - let (non_default_args, var_args) = - pos_args.split_at(subr.non_default_params.len()); - for (nd_arg, nd_param) in - non_default_args.iter().zip(subr.non_default_params.iter()) + let non_default_params_len = if method_name.is_some() { + subr.non_default_params.len() - 1 + } else { + subr.non_default_params.len() + }; + if pos_args.len() >= non_default_params_len { + let (non_default_args, var_args) = pos_args.split_at(non_default_params_len); + let non_default_params = if subr + .non_default_params + .iter() + .next() + .map(|p| p.name().map(|s| &s[..]) == Some("self")) + .unwrap_or(false) { + let mut non_default_params = subr.non_default_params.iter(); + let self_pt = non_default_params.next().unwrap(); + self.sub_unify( + obj.ref_t(), + self_pt.typ(), + Some(obj.loc()), + None, + self_pt.name(), + )?; + non_default_params + } else { + subr.non_default_params.iter() + }; + for (nd_arg, nd_param) in non_default_args.iter().zip(non_default_params) { self.substitute_pos_arg( &callee, &nd_arg.expr, diff --git a/compiler/erg_compiler/ownercheck.rs b/compiler/erg_compiler/ownercheck.rs index 1885631a..94ea452d 100644 --- a/compiler/erg_compiler/ownercheck.rs +++ b/compiler/erg_compiler/ownercheck.rs @@ -102,8 +102,12 @@ impl OwnershipChecker { if let Some(ownership) = args_owns.self_ { self.check_expr(&call.obj, ownership); } - let (non_default_args, var_args) = - call.args.pos_args.split_at(args_owns.non_defaults.len()); + let non_defaults_len = if call.method_name.is_some() { + args_owns.non_defaults.len() - 1 + } else { + args_owns.non_defaults.len() + }; + let (non_default_args, var_args) = call.args.pos_args.split_at(non_defaults_len); for (nd_arg, ownership) in non_default_args.iter().zip(args_owns.non_defaults.iter()) { From cba2eaa03cfaff6475f4663bf251501e39b099e2 Mon Sep 17 00:00:00 2001 From: Shunsuke Shibayama Date: Thu, 8 Sep 2022 01:20:00 +0900 Subject: [PATCH 45/68] Update hir.rs --- compiler/erg_compiler/hir.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/compiler/erg_compiler/hir.rs b/compiler/erg_compiler/hir.rs index e3c000a8..f4dbbd10 100644 --- a/compiler/erg_compiler/hir.rs +++ b/compiler/erg_compiler/hir.rs @@ -367,7 +367,11 @@ pub struct Attribute { impl NestedDisplay for Attribute { fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, _level: usize) -> fmt::Result { - write!(f, "({}).{}(: {})", self.obj, self.name.content, self.t) + if self.t != Type::Uninited { + write!(f, "({}).{}(: {})", self.obj, self.name.content, self.t) + } else { + write!(f, "({}).{}", self.obj, self.name.content) + } } } From e3e8a7e63cfae5e757b635f5760c2deb076c521d Mon Sep 17 00:00:00 2001 From: Shunsuke Shibayama Date: Thu, 8 Sep 2022 09:53:32 +0900 Subject: [PATCH 46/68] Impl `Override` feature --- .../erg_compiler/context/initialize/mod.rs | 24 +++++--- compiler/erg_compiler/context/mod.rs | 5 +- compiler/erg_compiler/context/register.rs | 58 ++++++++++++++----- compiler/erg_compiler/error.rs | 37 ++++++++++++ compiler/erg_compiler/lower.rs | 25 ++++++++ compiler/erg_compiler/varinfo.rs | 28 +++++++-- compiler/erg_parser/ast.rs | 2 +- examples/class.er | 5 +- 8 files changed, 152 insertions(+), 32 deletions(-) diff --git a/compiler/erg_compiler/context/initialize/mod.rs b/compiler/erg_compiler/context/initialize/mod.rs index 1cfb15d3..04d07aef 100644 --- a/compiler/erg_compiler/context/initialize/mod.rs +++ b/compiler/erg_compiler/context/initialize/mod.rs @@ -33,7 +33,7 @@ impl Context { panic!("already registered: {name}"); } else { self.decls - .insert(name, VarInfo::new(t, Immutable, vis, Builtin)); + .insert(name, VarInfo::new(t, Immutable, vis, Builtin, None)); } } @@ -49,7 +49,7 @@ impl Context { panic!("already registered: {name}"); } else { self.locals - .insert(name, VarInfo::new(t, muty, vis, Builtin)); + .insert(name, VarInfo::new(t, muty, vis, Builtin, None)); } } @@ -58,7 +58,7 @@ impl Context { panic!("already registered: {name}"); } else { // TODO: not all value objects are comparable - let vi = VarInfo::new(enum_t(set! {obj.clone()}), Const, Private, Builtin); + let vi = VarInfo::new(enum_t(set! {obj.clone()}), Const, Private, Builtin, None); self.consts.insert(VarName::from_str(Str::rc(name)), obj); self.locals.insert(VarName::from_str(Str::rc(name)), vi); } @@ -88,8 +88,10 @@ impl Context { panic!("{} has already been registered as const", t.name()); } else { let name = VarName::from_str(t.name()); - self.locals - .insert(name.clone(), VarInfo::new(Type, muty, Private, Builtin)); + self.locals.insert( + name.clone(), + VarInfo::new(Type, muty, Private, Builtin, None), + ); self.consts .insert(name.clone(), ValueObj::builtin_t(t.clone())); for impl_trait in ctx.super_traits.iter() { @@ -115,8 +117,10 @@ impl Context { root_ctx.method_defs.push((t, ctx)); } else { let name = VarName::from_str(t.name()); - self.locals - .insert(name.clone(), VarInfo::new(Type, muty, Private, Builtin)); + self.locals.insert( + name.clone(), + VarInfo::new(Type, muty, Private, Builtin, None), + ); self.consts .insert(name.clone(), ValueObj::builtin_t(t.clone())); for impl_trait in ctx.super_traits.iter() { @@ -138,8 +142,10 @@ impl Context { panic!("{} has already been registered", name); } else { let name = VarName::from_static(name); - self.locals - .insert(name.clone(), VarInfo::new(Type, muty, Private, Builtin)); + self.locals.insert( + name.clone(), + VarInfo::new(Type, muty, Private, Builtin, None), + ); for method_name in ctx.locals.keys() { if let Some(patches) = self.method_impl_patches.get_mut(method_name) { patches.push(name.clone()); diff --git a/compiler/erg_compiler/context/mod.rs b/compiler/erg_compiler/context/mod.rs index 3db55e46..923955a1 100644 --- a/compiler/erg_compiler/context/mod.rs +++ b/compiler/erg_compiler/context/mod.rs @@ -251,6 +251,7 @@ pub struct Context { pub(crate) super_classes: Vec, // if self is a patch, means patch classes pub(crate) super_traits: Vec, // if self is not a trait, means implemented traits // method definitions, if the context is a type + // specializations are included and needs to be separated out pub(crate) method_defs: Vec<(Type, Context)>, /// K: method name, V: impl patch /// Provided methods can switch implementations on a scope-by-scope basis @@ -360,12 +361,12 @@ impl Context { let idx = ParamIdx::Nth(idx); let kind = VarKind::parameter(id, idx, param.default_info); // TODO: is_const { Const } else { Immutable } - let vi = VarInfo::new(param.t, Immutable, Private, kind); + let vi = VarInfo::new(param.t, Immutable, Private, kind, None); params_.push((Some(VarName::new(Token::static_symbol(name))), vi)); } else { let idx = ParamIdx::Nth(idx); let kind = VarKind::parameter(id, idx, param.default_info); - let vi = VarInfo::new(param.t, Immutable, Private, kind); + let vi = VarInfo::new(param.t, Immutable, Private, kind, None); params_.push((None, vi)); } } diff --git a/compiler/erg_compiler/context/register.rs b/compiler/erg_compiler/context/register.rs index d1651959..51ba88b5 100644 --- a/compiler/erg_compiler/context/register.rs +++ b/compiler/erg_compiler/context/register.rs @@ -75,8 +75,10 @@ impl Context { let kind = id.map_or(VarKind::Declared, VarKind::Defined); let sig_t = self.instantiate_var_sig_t(sig.t_spec.as_ref(), opt_t, PreRegister)?; - self.decls - .insert(ident.name.clone(), VarInfo::new(sig_t, muty, vis, kind)); + self.decls.insert( + ident.name.clone(), + VarInfo::new(sig_t, muty, vis, kind, None), + ); Ok(()) } } @@ -103,7 +105,17 @@ impl Context { )); } let t = self.instantiate_sub_sig_t(sig, opt_ret_t, PreRegister)?; - let vi = VarInfo::new(t, muty, vis, kind); + let comptime_decos = sig + .decorators + .iter() + .filter_map(|deco| match &deco.0 { + ast::Expr::Accessor(ast::Accessor::Local(local)) if local.is_const() => { + Some(local.inspect().clone()) + } + _ => None, + }) + .collect(); + let vi = VarInfo::new(t, muty, vis, kind, Some(comptime_decos)); if let Some(_decl) = self.decls.remove(name) { return Err(TyCheckError::duplicate_decl_error( line!() as usize, @@ -146,7 +158,7 @@ impl Context { // something to do? } let vis = ident.vis(); - let vi = VarInfo::new(generalized, muty, vis, VarKind::Defined(id)); + let vi = VarInfo::new(generalized, muty, vis, VarKind::Defined(id), None); self.locals.insert(ident.name.clone(), vi); Ok(()) } @@ -198,7 +210,7 @@ impl Context { VarKind::parameter(DefId(get_hash(&(&self.name, name))), idx, default); self.params.push(( Some(name.clone()), - VarInfo::new(spec_t, Immutable, Private, kind), + VarInfo::new(spec_t, Immutable, Private, kind, None), )); Ok(()) } @@ -239,7 +251,7 @@ impl Context { VarKind::parameter(DefId(get_hash(&(&self.name, name))), idx, default); self.params.push(( Some(name.clone()), - VarInfo::new(spec_t, Immutable, Private, kind), + VarInfo::new(spec_t, Immutable, Private, kind, None), )); Ok(()) } @@ -280,7 +292,7 @@ impl Context { VarKind::parameter(DefId(get_hash(&(&self.name, name))), idx, default); self.params.push(( Some(name.clone()), - VarInfo::new(spec_t, Immutable, Private, kind), + VarInfo::new(spec_t, Immutable, Private, kind, None), )); Ok(()) } @@ -412,8 +424,23 @@ impl Context { )); } } - // TODO: visibility - let vi = VarInfo::new(found_t, muty, Private, VarKind::Defined(id)); + let comptime_decos = sig + .decorators + .iter() + .filter_map(|deco| match &deco.0 { + ast::Expr::Accessor(ast::Accessor::Local(local)) if local.is_const() => { + Some(local.inspect().clone()) + } + _ => None, + }) + .collect(); + let vi = VarInfo::new( + found_t, + muty, + sig.ident.vis(), + VarKind::Defined(id), + Some(comptime_decos), + ); log!(info "Registered {}::{name}: {}", self.name, &vi.t); self.locals.insert(name.clone(), vi); Ok(()) @@ -493,7 +520,7 @@ impl Context { panic!("already registered: {name}"); } else { self.locals - .insert(name, VarInfo::new(t, muty, vis, VarKind::Auto)); + .insert(name, VarInfo::new(t, muty, vis, VarKind::Auto, None)); } } @@ -501,8 +528,10 @@ impl Context { if self.decls.get(&name).is_some() { panic!("already registered: {name}"); } else { - self.decls - .insert(name, VarInfo::new(t, Immutable, vis, VarKind::Declared)); + self.decls.insert( + name, + VarInfo::new(t, Immutable, vis, VarKind::Declared, None), + ); } } @@ -512,7 +541,7 @@ impl Context { } else { let id = DefId(get_hash(&(&self.name, &name))); self.locals - .insert(name, VarInfo::new(t, muty, vis, VarKind::Defined(id))); + .insert(name, VarInfo::new(t, muty, vis, VarKind::Defined(id), None)); } } @@ -533,6 +562,7 @@ impl Context { Const, Private, VarKind::Defined(id), + None, ); self.consts.insert(VarName::from_str(Str::rc(name)), other); self.locals.insert(VarName::from_str(Str::rc(name)), vi); @@ -606,7 +636,7 @@ impl Context { let id = DefId(get_hash(&(&self.name, &name))); self.locals.insert( name.clone(), - VarInfo::new(meta_t, muty, Private, VarKind::Defined(id)), + VarInfo::new(meta_t, muty, Private, VarKind::Defined(id), None), ); self.consts .insert(name.clone(), ValueObj::Type(TypeObj::Generated(gen))); diff --git a/compiler/erg_compiler/error.rs b/compiler/erg_compiler/error.rs index ab70fc7a..9faab9a1 100644 --- a/compiler/erg_compiler/error.rs +++ b/compiler/erg_compiler/error.rs @@ -1041,6 +1041,43 @@ passed keyword args: {RED}{kw_args_len}{RESET}" caused_by, ) } + + pub fn override_error>( + errno: usize, + name: &str, + name_loc: Location, + superclass: &Type, + caused_by: S, + ) -> Self { + Self::new( + ErrorCore::new( + errno, + NameError, + name_loc, + switch_lang!( + "japanese" => format!( + "{RED}{name}{RESET}は{YELLOW}{superclass}{RESET}で既に定義されています", + ), + "simplified_chinese" => format!( + "{RED}{name}{RESET}已在{YELLOW}{superclass}{RESET}中定义", + ), + "traditional_chinese" => format!( + "{RED}{name}{RESET}已在{YELLOW}{superclass}{RESET}中定義", + ), + "english" => format!( + "{RED}{name}{RESET} is already defined in {YELLOW}{superclass}{RESET}", + ), + ), + Some(switch_lang!( + "japanese" => "デフォルトでオーバーライドはできません(`Override`デコレータを使用してください)", + "simplified_chinese" => "默认不可重写(请使用`Override`装饰器)", + "traditional_chinese" => "默認不可重寫(請使用`Override`裝飾器)", + "english" => "cannot override by default (use `Override` decorator)", + ).into()), + ), + caused_by.into(), + ) + } } #[derive(Debug)] diff --git a/compiler/erg_compiler/lower.rs b/compiler/erg_compiler/lower.rs index 59560f99..7a2f70c8 100644 --- a/compiler/erg_compiler/lower.rs +++ b/compiler/erg_compiler/lower.rs @@ -571,6 +571,7 @@ impl ASTLowerer { } match self.ctx.pop() { Ok(ctx) => { + self.check_override(&class, &ctx); if let Some((_, class_root)) = self.ctx.rec_get_mut_nominal_type_ctx(&class) { class_root.method_defs.push((class, ctx)); } else { @@ -605,6 +606,30 @@ impl ASTLowerer { )) } + fn check_override(&mut self, class: &Type, ctx: &Context) { + if let Some(sups) = self.ctx.rec_get_nominal_super_type_ctxs(class) { + for (sup_t, sup) in sups { + for (method_name, vi) in ctx.locals.iter() { + if let Some(_sup_vi) = sup.get_current_scope_var(&method_name.inspect()) { + // must `@Override` + if let Some(decos) = &vi.comptime_decos { + if decos.contains("Override") { + continue; + } + } + self.errs.push(LowerError::override_error( + line!() as usize, + method_name.inspect(), + method_name.loc(), + sup_t, + ctx.caused_by(), + )); + } + } + } + } + } + fn get_require_or_sup(&self, expr: hir::Expr) -> hir::Expr { match expr { acc @ hir::Expr::Accessor(_) => acc, diff --git a/compiler/erg_compiler/varinfo.rs b/compiler/erg_compiler/varinfo.rs index aee571df..e88339c1 100644 --- a/compiler/erg_compiler/varinfo.rs +++ b/compiler/erg_compiler/varinfo.rs @@ -1,6 +1,8 @@ use std::fmt; +use erg_common::set::Set; use erg_common::vis::Visibility; +use erg_common::Str; use Visibility::*; use erg_parser::ast::DefId; @@ -109,6 +111,7 @@ pub struct VarInfo { pub muty: Mutability, pub vis: Visibility, pub kind: VarKind, + pub comptime_decos: Option>, } impl fmt::Display for VarInfo { @@ -141,11 +144,28 @@ impl HasType for VarInfo { } impl VarInfo { - pub const ILLEGAL: &'static Self = - &VarInfo::new(Type::Failure, Immutable, Private, VarKind::DoesNotExist); + pub const ILLEGAL: &'static Self = &VarInfo::new( + Type::Failure, + Immutable, + Private, + VarKind::DoesNotExist, + None, + ); - pub const fn new(t: Type, muty: Mutability, vis: Visibility, kind: VarKind) -> Self { - Self { t, muty, vis, kind } + pub const fn new( + t: Type, + muty: Mutability, + vis: Visibility, + kind: VarKind, + comptime_decos: Option>, + ) -> Self { + Self { + t, + muty, + vis, + kind, + comptime_decos, + } } pub fn same_id_as(&self, id: DefId) -> bool { diff --git a/compiler/erg_parser/ast.rs b/compiler/erg_parser/ast.rs index 8d6e8e45..3ddf2379 100644 --- a/compiler/erg_parser/ast.rs +++ b/compiler/erg_parser/ast.rs @@ -1724,7 +1724,7 @@ impl Locational for TypeBoundSpecs { /// デコレータは関数を返す関数オブジェクトならば何でも指定できる /// e.g. @(x -> x) #[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub struct Decorator(Expr); +pub struct Decorator(pub Expr); impl Decorator { pub const fn new(expr: Expr) -> Self { diff --git a/examples/class.er b/examples/class.er index 755b14e8..7b49dd21 100644 --- a/examples/class.er +++ b/examples/class.er @@ -1,14 +1,15 @@ @Inheritable Point2D = Class {x = Int; y = Int} Point2D. - norm ref self = self::x**2 + self::y**2 + norm self = self::x**2 + self::y**2 Point3D = Inherit Point2D, Additional := {z = Int} Point3D. + # Overloading is prohibited by default. Remove this decorator and check for errors. @Override new x, y, z = Point3D::__new__ {x; y; z} @Override - norm ref self = self::x**2 + self::y**2 + self::z**2 + norm self = self::x**2 + self::y**2 + self::z**2 p = Point3D.new {x = 1; y = 2; z = 3} print! p.norm() From 60558459c8d97d4b2cea3f52ea03f2589054bb88 Mon Sep 17 00:00:00 2001 From: Shunsuke Shibayama Date: Thu, 8 Sep 2022 09:57:41 +0900 Subject: [PATCH 47/68] Fix parser crashing bug --- compiler/erg_compiler/lower.rs | 2 +- compiler/erg_parser/parse.rs | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/compiler/erg_compiler/lower.rs b/compiler/erg_compiler/lower.rs index 7a2f70c8..bbd0087b 100644 --- a/compiler/erg_compiler/lower.rs +++ b/compiler/erg_compiler/lower.rs @@ -608,7 +608,7 @@ impl ASTLowerer { fn check_override(&mut self, class: &Type, ctx: &Context) { if let Some(sups) = self.ctx.rec_get_nominal_super_type_ctxs(class) { - for (sup_t, sup) in sups { + for (sup_t, sup) in sups.skip(1) { for (method_name, vi) in ctx.locals.iter() { if let Some(_sup_vi) = sup.get_current_scope_var(&method_name.inspect()) { // must `@Override` diff --git a/compiler/erg_parser/parse.rs b/compiler/erg_parser/parse.rs index 0f148547..7d915f66 100644 --- a/compiler/erg_parser/parse.rs +++ b/compiler/erg_parser/parse.rs @@ -835,6 +835,9 @@ impl Parser { } else { todo!() } + while self.cur_is(Newline) { + self.skip(); + } let first = self.try_reduce_chunk(false).map_err(|_| self.stack_dec())?; let first = option_enum_unwrap!(first, Expr::Def).unwrap_or_else(|| todo!()); let mut defs = vec![first]; From 60b7cce52eafe5e3535bb76c0da1553b5793604e Mon Sep 17 00:00:00 2001 From: Shunsuke Shibayama Date: Thu, 8 Sep 2022 13:47:49 +0900 Subject: [PATCH 48/68] Fix bugs related to Ref/RefMut --- compiler/erg_compiler/context/compare.rs | 70 ++-- compiler/erg_compiler/context/eval.rs | 29 +- .../erg_compiler/context/initialize/mod.rs | 75 ++++- .../context/initialize/py_mods/io.rs | 4 +- compiler/erg_compiler/context/inquire.rs | 42 ++- compiler/erg_compiler/context/instantiate.rs | 75 ++--- compiler/erg_compiler/context/register.rs | 2 +- compiler/erg_compiler/context/tyvar.rs | 121 ++++--- compiler/erg_compiler/error.rs | 8 +- compiler/erg_compiler/hir.rs | 2 +- compiler/erg_compiler/ownercheck.rs | 3 - compiler/erg_parser/ast.rs | 62 +--- compiler/erg_type/constructors.rs | 29 +- compiler/erg_type/free.rs | 8 +- compiler/erg_type/lib.rs | 304 ++++++------------ 15 files changed, 363 insertions(+), 471 deletions(-) diff --git a/compiler/erg_compiler/context/compare.rs b/compiler/erg_compiler/context/compare.rs index a991e7ac..e0470e14 100644 --- a/compiler/erg_compiler/context/compare.rs +++ b/compiler/erg_compiler/context/compare.rs @@ -50,9 +50,7 @@ impl Context { pub(crate) fn eq_tp(&self, lhs: &TyParam, rhs: &TyParam) -> bool { match (lhs, rhs) { - (TyParam::Type(lhs), TyParam::Type(rhs)) => { - return self.structural_same_type_of(lhs, rhs) - } + (TyParam::Type(lhs), TyParam::Type(rhs)) => return self.same_type_of(lhs, rhs), (TyParam::Mono(l), TyParam::Mono(r)) => { if let (Some(l), Some(r)) = (self.rec_get_const_obj(l), self.rec_get_const_obj(r)) { return l == r; @@ -61,6 +59,23 @@ impl Context { (TyParam::MonoQVar(name), _other) | (_other, TyParam::MonoQVar(name)) => { panic!("Not instantiated type parameter: {name}") } + (TyParam::UnaryOp { op: lop, val: lval }, TyParam::UnaryOp { op: rop, val: rval }) => { + return lop == rop && self.eq_tp(lval, rval); + } + ( + TyParam::BinOp { + op: lop, + lhs: ll, + rhs: lr, + }, + TyParam::BinOp { + op: rop, + lhs: rl, + rhs: rr, + }, + ) => { + return lop == rop && self.eq_tp(ll, rl) && self.eq_tp(lr, rr); + } ( TyParam::App { name: ln, @@ -86,7 +101,7 @@ impl Context { | FreeKind::NamedUnbound { constraint, .. } => { let t = constraint.get_type().unwrap(); let other_t = self.type_of(other); - return self.structural_supertype_of(t, &other_t); + return self.same_type_of(t, &other_t); } }, (l, r) if l == r => { @@ -146,14 +161,18 @@ impl Context { } } + pub(crate) fn same_type_of(&self, lhs: &Type, rhs: &Type) -> bool { + self.supertype_of(lhs, rhs) && self.subtype_of(lhs, rhs) + } + pub(crate) fn cheap_supertype_of(&self, lhs: &Type, rhs: &Type) -> (Credibility, bool) { if lhs == rhs { return (Absolutely, true); } match (lhs, rhs) { - // FIXME: Obj/Neverはクラス、Top/Bottomは構造型 (Obj, _) | (_, Never) => (Absolutely, true), - (_, Obj) | (Never, _) => (Absolutely, false), + // (_, Obj) if !lhs.is_unbound_var() => (Absolutely, false), + // (Never, _) if !rhs.is_unbound_var() => (Absolutely, false), (Float | Ratio | Int | Nat | Bool, Bool) | (Float | Ratio | Int | Nat, Nat) | (Float | Ratio | Int, Int) @@ -166,14 +185,9 @@ impl Context { ), (Type, Subr(subr)) => ( Absolutely, - subr.kind - .self_t() - .map(|t| self.supertype_of(&Type, t)) - .unwrap_or(true) - && subr - .non_default_params - .iter() - .all(|pt| self.supertype_of(&Type, &pt.typ())) + subr.non_default_params + .iter() + .all(|pt| self.supertype_of(&Type, &pt.typ())) && subr .default_params .iter() @@ -199,20 +213,6 @@ impl Context { .. }), ) if &n[..] == "GenericProc" => (Absolutely, true), - ( - Type::Mono(n), - Subr(SubrType { - kind: SubrKind::FuncMethod(_), - .. - }), - ) if &n[..] == "GenericFuncMethod" => (Absolutely, true), - ( - Type::Mono(n), - Subr(SubrType { - kind: SubrKind::ProcMethod { .. }, - .. - }), - ) if &n[..] == "GenericProcMethod" => (Absolutely, true), (Type::Mono(l), Type::Poly { name: r, .. }) if &l[..] == "GenericArray" && &r[..] == "Array" => { @@ -371,7 +371,7 @@ impl Context { pub(crate) fn structural_supertype_of(&self, lhs: &Type, rhs: &Type) -> bool { log!(info "structural_supertype_of:\nlhs: {lhs}\nrhs: {rhs}"); match (lhs, rhs) { - (Subr(ls), Subr(rs)) if ls.kind.same_kind_as(&rs.kind) => { + (Subr(ls), Subr(rs)) if ls.kind == rs.kind => { let kw_check = || { for lpt in ls.default_params.iter() { if let Some(rpt) = rs @@ -388,9 +388,6 @@ impl Context { } true }; - if ls.kind.self_t().is_some() { - todo!("method type is not supported yet") - } // () -> Never <: () -> Int <: () -> Object // (Object) -> Int <: (Int) -> Int <: (Never) -> Int ls.non_default_params.len() == rs.non_default_params.len() @@ -578,11 +575,12 @@ impl Context { } (_lhs, Not(_, _)) => todo!(), (Not(_, _), _rhs) => todo!(), - // RefMut, OptionMut are invariant - (Ref(lhs), Ref(rhs)) => self.supertype_of(lhs, rhs), + // RefMut are invariant + (Ref(l), Ref(r)) => self.supertype_of(l, r), // TはすべてのRef(T)のメソッドを持つので、Ref(T)のサブタイプ // REVIEW: RefMut is invariant, maybe - (Ref(lhs), rhs) | (RefMut(lhs), rhs) => self.supertype_of(lhs, rhs), + (Ref(l), r) => self.supertype_of(l, r), + (RefMut { before: l, .. }, r) => self.supertype_of(l, r), ( Poly { name: ln, @@ -663,7 +661,7 @@ impl Context { self.structural_supertype_of(rhs, lhs) } - pub(crate) fn structural_same_type_of(&self, lhs: &Type, rhs: &Type) -> bool { + pub(crate) fn _structural_same_type_of(&self, lhs: &Type, rhs: &Type) -> bool { self.structural_supertype_of(lhs, rhs) && self.structural_subtype_of(lhs, rhs) } diff --git a/compiler/erg_compiler/context/eval.rs b/compiler/erg_compiler/context/eval.rs index d0bb908b..4187fb15 100644 --- a/compiler/erg_compiler/context/eval.rs +++ b/compiler/erg_compiler/context/eval.rs @@ -15,7 +15,7 @@ use erg_parser::token::{Token, TokenKind}; use erg_type::constructors::{enum_t, mono, mono_proj, poly, ref_, ref_mut, refinement, subr_t}; use erg_type::typaram::{OpKind, TyParam}; use erg_type::value::ValueObj; -use erg_type::{HasType, Predicate, SubrKind, TyBound, Type, ValueArgs}; +use erg_type::{HasType, Predicate, TyBound, Type, ValueArgs}; use crate::context::instantiate::TyVarContext; use crate::context::Context; @@ -485,21 +485,6 @@ impl Context { match substituted { Type::FreeVar(fv) if fv.is_linked() => self.eval_t_params(fv.crack().clone(), level), Type::Subr(mut subr) => { - let kind = match subr.kind { - SubrKind::FuncMethod(self_t) => { - SubrKind::fn_met(self.eval_t_params(*self_t, level)?) - } - SubrKind::ProcMethod { before, after } => { - let before = self.eval_t_params(*before, level)?; - if let Some(after) = after { - let after = self.eval_t_params(*after, level)?; - SubrKind::pr_met(before, Some(after)) - } else { - SubrKind::pr_met(before, None) - } - } - other => other, - }; for pt in subr.non_default_params.iter_mut() { *pt.typ_mut() = self.eval_t_params(mem::take(pt.typ_mut()), level)?; } @@ -512,7 +497,7 @@ impl Context { } let return_t = self.eval_t_params(*subr.return_t, level)?; Ok(subr_t( - kind, + subr.kind, subr.non_default_params, subr.var_params.map(|v| *v), subr.default_params, @@ -570,7 +555,15 @@ impl Context { } } Type::Ref(l) => Ok(ref_(self.eval_t_params(*l, level)?)), - Type::RefMut(l) => Ok(ref_mut(self.eval_t_params(*l, level)?)), + Type::RefMut { before, after } => { + let before = self.eval_t_params(*before, level)?; + let after = if let Some(after) = after { + Some(self.eval_t_params(*after, level)?) + } else { + None + }; + Ok(ref_mut(before, after)) + } Type::Poly { name, mut params } => { for p in params.iter_mut() { *p = self.eval_tp(&mem::take(p))?; diff --git a/compiler/erg_compiler/context/initialize/mod.rs b/compiler/erg_compiler/context/initialize/mod.rs index 04d07aef..919e41fe 100644 --- a/compiler/erg_compiler/context/initialize/mod.rs +++ b/compiler/erg_compiler/context/initialize/mod.rs @@ -169,7 +169,7 @@ impl Context { let mut mutable = Self::mono_trait("Mutable", vec![], Self::TOP_LEVEL); let proj = mono_proj(mono_q("Self"), "ImmutType"); let f_t = func(vec![param_t("old", proj.clone())], None, vec![], proj); - let t = pr1_met(mono_q("Self"), None, f_t, NoneType); + let t = pr1_met(ref_mut(mono_q("Self"), None), f_t, NoneType); let t = quant(t, set! { subtypeof(mono_q("Self"), mono("Immutizable")) }); mutable.register_builtin_decl("update!", t, Public); let mut immutizable = @@ -422,7 +422,6 @@ impl Context { "times!", pr_met( Nat, - None, vec![param_t("p", nd_proc(vec![], None, NoneType))], None, vec![], @@ -558,7 +557,7 @@ impl Context { "Type", vec![Obj], vec![ - // poly("Eq", vec![ty_tp(Type)]), + poly("Eq", vec![ty_tp(Type)]), poly("In", vec![ty_tp(Obj)]), // x in Type mono("Named"), ], @@ -569,7 +568,7 @@ impl Context { "ClassType", vec![Type, Obj], vec![ - // poly("Eq", vec![ty_tp(Class)]), + poly("Eq", vec![ty_tp(Class)]), poly("In", vec![ty_tp(Obj)]), // x in Class mono("Named"), ], @@ -820,7 +819,13 @@ impl Context { ); int_mut.register_builtin_const("ImmutType", ValueObj::builtin_t(Int)); let f_t = param_t("f", func(vec![param_t("old", Int)], None, vec![], Int)); - let t = pr_met(mono("Int!"), None, vec![f_t], None, vec![], NoneType); + let t = pr_met( + ref_mut(mono("Int!"), None), + vec![f_t], + None, + vec![], + NoneType, + ); int_mut.register_builtin_impl("update!", t, Immutable, Public); let mut nat_mut = Self::mono_class( "Nat!", @@ -830,7 +835,13 @@ impl Context { ); nat_mut.register_builtin_const("ImmutType", ValueObj::builtin_t(Nat)); let f_t = param_t("f", func(vec![param_t("old", Nat)], None, vec![], Nat)); - let t = pr_met(mono("Nat!"), None, vec![f_t], None, vec![], NoneType); + let t = pr_met( + ref_mut(mono("Nat!"), None), + vec![f_t], + None, + vec![], + NoneType, + ); nat_mut.register_builtin_impl("update!", t, Immutable, Public); let mut float_mut = Self::mono_class( "Float!", @@ -840,7 +851,13 @@ impl Context { ); float_mut.register_builtin_const("ImmutType", ValueObj::builtin_t(Float)); let f_t = param_t("f", func(vec![param_t("old", Float)], None, vec![], Float)); - let t = pr_met(mono("Float!"), None, vec![f_t], None, vec![], NoneType); + let t = pr_met( + ref_mut(mono("Float!"), None), + vec![f_t], + None, + vec![], + NoneType, + ); float_mut.register_builtin_impl("update!", t, Immutable, Public); let mut ratio_mut = Self::mono_class( "Ratio!", @@ -858,7 +875,13 @@ impl Context { mono("Ratio"), ), ); - let t = pr_met(mono("Ratio!"), None, vec![f_t], None, vec![], NoneType); + let t = pr_met( + ref_mut(mono("Ratio!"), None), + vec![f_t], + None, + vec![], + NoneType, + ); ratio_mut.register_builtin_impl("update!", t, Immutable, Public); let mut bool_mut = Self::mono_class( "Bool!", @@ -868,7 +891,13 @@ impl Context { ); bool_mut.register_builtin_const("ImmutType", ValueObj::builtin_t(Bool)); let f_t = param_t("f", func(vec![param_t("old", Bool)], None, vec![], Bool)); - let t = pr_met(mono("Bool!"), None, vec![f_t], None, vec![], NoneType); + let t = pr_met( + ref_mut(mono("Bool!"), None), + vec![f_t], + None, + vec![], + NoneType, + ); bool_mut.register_builtin_impl("update!", t, Immutable, Public); let mut str_mut = Self::mono_class( "Str!", @@ -878,7 +907,13 @@ impl Context { ); str_mut.register_builtin_const("ImmutType", ValueObj::builtin_t(Str)); let f_t = param_t("f", func(vec![param_t("old", Str)], None, vec![], Str)); - let t = pr_met(mono("Str!"), None, vec![f_t], None, vec![], NoneType); + let t = pr_met( + ref_mut(mono("Str!"), None), + vec![f_t], + None, + vec![], + NoneType, + ); str_mut.register_builtin_impl("update!", t, Immutable, Public); let array_mut_t = poly("Array!", vec![ty_tp(mono_q("T")), mono_q_tp("N")]); let mut array_mut = Self::poly_class( @@ -889,11 +924,13 @@ impl Context { Self::TOP_LEVEL, ); let t = pr_met( - ref_mut(array_mut_t.clone()), - Some(ref_mut(poly( - "Array!", - vec![ty_tp(mono_q("T")), mono_q_tp("N") + value(1)], - ))), + ref_mut( + array_mut_t.clone(), + Some(poly( + "Array!", + vec![ty_tp(mono_q("T")), mono_q_tp("N") + value(1)], + )), + ), vec![param_t("elem", mono_q("T"))], None, vec![], @@ -913,7 +950,13 @@ impl Context { array_t.clone(), ), ); - let t = pr_met(array_mut_t.clone(), None, vec![f_t], None, vec![], NoneType); + let t = pr_met( + ref_mut(array_mut_t.clone(), None), + vec![f_t], + None, + vec![], + NoneType, + ); array_mut.register_builtin_impl("update!", t, Immutable, Public); let range_t = poly("Range", vec![TyParam::t(mono_q("T"))]); let range = Self::poly_class( diff --git a/compiler/erg_compiler/context/initialize/py_mods/io.rs b/compiler/erg_compiler/context/initialize/py_mods/io.rs index 168da4ff..5f6d053d 100644 --- a/compiler/erg_compiler/context/initialize/py_mods/io.rs +++ b/compiler/erg_compiler/context/initialize/py_mods/io.rs @@ -1,7 +1,7 @@ use erg_common::vis::Visibility; use erg_common::Str; -use erg_type::constructors::{mono, pr0_met}; +use erg_type::constructors::{mono, pr0_met, ref_}; use erg_type::Type; use Type::*; @@ -16,7 +16,7 @@ impl Context { let mut string_io = Context::mono_class(Str::ever("StringIO!"), vec![Obj], vec![], 0); string_io.register_builtin_impl( "getvalue!", - pr0_met(mono("StringIO!"), None, Str), + pr0_met(ref_(mono("StringIO!")), Str), Immutable, Public, ); diff --git a/compiler/erg_compiler/context/inquire.rs b/compiler/erg_compiler/context/inquire.rs index 3224f460..e0970468 100644 --- a/compiler/erg_compiler/context/inquire.rs +++ b/compiler/erg_compiler/context/inquire.rs @@ -18,7 +18,7 @@ use erg_type::constructors::{func, mono, mono_proj, poly, ref_, ref_mut, refinem use erg_type::free::Constraint; use erg_type::typaram::TyParam; use erg_type::value::{GenTypeObj, TypeObj, ValueObj}; -use erg_type::{HasType, ParamTy, SubrKind, SubrType, TyBound, Type}; +use erg_type::{HasType, ParamTy, TyBound, Type}; use crate::context::instantiate::ConstTemplate; use crate::context::{Context, ContextKind, RegistrationMode, TraitInstance, Variance}; @@ -279,8 +279,9 @@ impl Context { let sup = fv.get_sup().unwrap(); self.get_attr_t_from_attributive_t(obj, &sup, name, namespace) } - Type::Ref(t) | Type::RefMut(t) => { - self.get_attr_t_from_attributive_t(obj, t, name, namespace) + Type::Ref(t) => self.get_attr_t_from_attributive_t(obj, t, name, namespace), + Type::RefMut { before, .. } => { + self.get_attr_t_from_attributive_t(obj, before, name, namespace) } Type::Refinement(refine) => { self.get_attr_t_from_attributive_t(obj, &refine.t, name, namespace) @@ -443,15 +444,17 @@ impl Context { /// 可変依存型の変更を伝搬させる fn propagate(&self, t: &Type, callee: &hir::Expr) -> TyCheckResult<()> { - if let Type::Subr(SubrType { - kind: SubrKind::ProcMethod { - after: Some(after), .. - }, - .. - }) = t - { - log!(info "{}, {}", callee.ref_t(), after); - self.reunify(callee.ref_t(), after, Some(callee.loc()), None)?; + if let Type::Subr(subr) = t { + if let Some(after) = subr.self_t().and_then(|self_t| { + if let RefMut { after, .. } = self_t { + after.as_ref() + } else { + None + } + }) { + log!(info "{}, {}", callee.ref_t(), after); + self.reunify(callee.ref_t(), after, Some(callee.loc()), None)?; + } } Ok(()) } @@ -560,9 +563,14 @@ impl Context { let new_t = self.resolve_trait(*t)?; Ok(ref_(new_t)) } - Type::RefMut(t) => { - let new_t = self.resolve_trait(*t)?; - Ok(ref_mut(new_t)) + Type::RefMut { before, after } => { + let new_before = self.resolve_trait(*before)?; + let new_after = if let Some(after) = after { + Some(self.resolve_trait(*after)?) + } else { + None + }; + Ok(ref_mut(new_before, new_after)) } Type::Callable { .. } => todo!(), Type::And(_, _) | Type::Or(_, _) | Type::Not(_, _) => todo!(), @@ -1125,7 +1133,7 @@ impl Context { return Some((t, ctx)); } } - Type::Ref(t) | Type::RefMut(t) => { + Type::Ref(t) | Type::RefMut { before: t, .. } => { if let Some(res) = self.rec_get_nominal_type_ctx(t) { return Some(res); } @@ -1190,7 +1198,7 @@ impl Context { return Some((t, ctx)); } } - Type::Ref(t) | Type::RefMut(t) => { + Type::Ref(t) | Type::RefMut { before: t, .. } => { if let Some(res) = self.rec_get_mut_nominal_type_ctx(t) { return Some(res); } diff --git a/compiler/erg_compiler/context/instantiate.rs b/compiler/erg_compiler/context/instantiate.rs index 9aa7563b..8263ab7d 100644 --- a/compiler/erg_compiler/context/instantiate.rs +++ b/compiler/erg_compiler/context/instantiate.rs @@ -7,21 +7,21 @@ use erg_common::set::Set; use erg_common::traits::{Locational, Stream}; use erg_common::Str; use erg_common::{assume_unreachable, enum_unwrap, set, try_map}; -use erg_type::free::{Constraint, Cyclicity, FreeTyVar}; -use TyParamOrdering::*; -use Type::*; use ast::{ - ParamSignature, ParamTySpec, PreDeclTypeSpec, SimpleTypeSpec, SubrKindSpec, TypeBoundSpec, - TypeBoundSpecs, TypeSpec, + ParamSignature, ParamTySpec, PreDeclTypeSpec, SimpleTypeSpec, TypeBoundSpec, TypeBoundSpecs, + TypeSpec, }; use erg_parser::ast; use erg_parser::token::TokenKind; use erg_type::constructors::*; +use erg_type::free::{Constraint, Cyclicity, FreeTyVar}; use erg_type::typaram::{IntervalOp, TyParam, TyParamOrdering}; use erg_type::value::ValueObj; use erg_type::{HasType, ParamTy, Predicate, SubrKind, TyBound, Type}; +use TyParamOrdering::*; +use Type::*; use crate::context::eval::eval_lit; use crate::context::{Context, RegistrationMode}; @@ -630,7 +630,11 @@ impl Context { .collect(); let return_t = self.instantiate_typespec(&subr.return_t, mode)?; Ok(subr_t( - self.instantiate_subr_kind(&subr.kind)?, + if subr.arrow.is(TokenKind::FuncArrow) { + SubrKind::Func + } else { + SubrKind::Proc + }, non_defaults, var_args, defaults, @@ -640,23 +644,6 @@ impl Context { } } - fn instantiate_subr_kind(&self, kind: &SubrKindSpec) -> TyCheckResult { - match kind { - SubrKindSpec::Func => Ok(SubrKind::Func), - SubrKindSpec::Proc => Ok(SubrKind::Proc), - SubrKindSpec::FuncMethod(spec) => { - Ok(SubrKind::fn_met(self.instantiate_typespec(spec, Normal)?)) - } - SubrKindSpec::ProcMethod { before, after } => Ok(SubrKind::pr_met( - self.instantiate_typespec(before, Normal)?, - after - .as_ref() - .map(|after| self.instantiate_typespec(after, Normal)) - .transpose()?, - )), - } - } - pub(crate) fn instantiate_ty_bound( &self, bound: &TypeBoundSpec, @@ -757,23 +744,6 @@ impl Context { Type::Refinement(refine) } Subr(mut subr) => { - let kind = match subr.kind { - SubrKind::FuncMethod(self_t) => { - let res = Self::instantiate_t(*self_t, tv_ctx); - SubrKind::FuncMethod(Box::new(res)) - } - SubrKind::ProcMethod { before, after } => { - let before = Self::instantiate_t(*before, tv_ctx); - let after = if let Some(after) = after { - let after = Self::instantiate_t(*after, tv_ctx); - Some(after) - } else { - None - }; - SubrKind::pr_met(before, after) - } - other => other, - }; for pt in subr.non_default_params.iter_mut() { *pt.typ_mut() = Self::instantiate_t(mem::take(pt.typ_mut()), tv_ctx); } @@ -786,7 +756,7 @@ impl Context { } let return_t = Self::instantiate_t(*subr.return_t, tv_ctx); subr_t( - kind, + subr.kind, subr.non_default_params, subr.var_params.map(|p| *p), subr.default_params, @@ -803,9 +773,14 @@ impl Context { let t = Self::instantiate_t(*t, tv_ctx); ref_(t) } - RefMut(t) => { - let t = Self::instantiate_t(*t, tv_ctx); - ref_mut(t) + RefMut { before, after } => { + let before = Self::instantiate_t(*before, tv_ctx); + let after = if let Some(after) = after { + Some(Self::instantiate_t(*after, tv_ctx)) + } else { + None + }; + ref_mut(before, after) } MonoProj { lhs, rhs } => { let lhs = Self::instantiate_t(*lhs, tv_ctx); @@ -831,9 +806,15 @@ impl Context { let mut tv_ctx = TyVarContext::new(self.level, quant.bounds, &self); let t = Self::instantiate_t(*quant.unbound_callable, &mut tv_ctx); match &t { - Type::Subr(subr) => match subr.kind.self_t() { - Some(l) => { - self.unify(l, callee.ref_t(), None, Some(callee.loc()))?; + Type::Subr(subr) => match subr.self_t() { + Some(self_t) => { + self.sub_unify( + callee.ref_t(), + self_t, + None, + Some(callee.loc()), + Some(&Str::ever("self")), + )?; } _ => {} }, diff --git a/compiler/erg_compiler/context/register.rs b/compiler/erg_compiler/context/register.rs index 51ba88b5..02496b44 100644 --- a/compiler/erg_compiler/context/register.rs +++ b/compiler/erg_compiler/context/register.rs @@ -277,7 +277,7 @@ impl Context { Some(name.inspect()), )?; } - let spec_t = ref_mut(spec_t); + let spec_t = ref_mut(spec_t.clone(), Some(spec_t)); let idx = if let Some(outer) = outer { ParamIdx::nested(outer, nth) } else { diff --git a/compiler/erg_compiler/context/tyvar.rs b/compiler/erg_compiler/context/tyvar.rs index 59ded596..b5190e50 100644 --- a/compiler/erg_compiler/context/tyvar.rs +++ b/compiler/erg_compiler/context/tyvar.rs @@ -12,7 +12,7 @@ use erg_type::constructors::*; use erg_type::free::{Constraint, Cyclicity, FreeKind, HasLevel}; use erg_type::typaram::TyParam; use erg_type::value::ValueObj; -use erg_type::{HasType, Predicate, SubrKind, TyBound, Type}; +use erg_type::{HasType, Predicate, TyBound, Type}; use crate::context::{Context, Variance}; use crate::error::{TyCheckError, TyCheckResult}; @@ -118,22 +118,6 @@ impl Context { _ => assume_unreachable!(), }, Subr(mut subr) => { - let kind = match subr.kind { - SubrKind::FuncMethod(self_t) => { - let t = self.generalize_t_inner(*self_t, bounds, lazy_inits); - SubrKind::fn_met(t) - } - SubrKind::ProcMethod { before, after } => { - let before = self.generalize_t_inner(*before, bounds, lazy_inits); - if let Some(after) = after { - let after = self.generalize_t_inner(*after, bounds, lazy_inits); - SubrKind::pr_met(before, Some(after)) - } else { - SubrKind::pr_met(before, None) - } - } - other => other, - }; subr.non_default_params.iter_mut().for_each(|nd_param| { *nd_param.typ_mut() = self.generalize_t_inner(mem::take(nd_param.typ_mut()), bounds, lazy_inits); @@ -148,7 +132,7 @@ impl Context { }); let return_t = self.generalize_t_inner(*subr.return_t, bounds, lazy_inits); subr_t( - kind, + subr.kind, subr.non_default_params, subr.var_params.map(|x| *x), subr.default_params, @@ -157,7 +141,14 @@ impl Context { } Callable { .. } => todo!(), Ref(t) => ref_(self.generalize_t_inner(*t, bounds, lazy_inits)), - RefMut(t) => ref_mut(self.generalize_t_inner(*t, bounds, lazy_inits)), + RefMut { before, after } => { + let after = if let Some(after) = after { + Some(self.generalize_t_inner(*after, bounds, lazy_inits)) + } else { + None + }; + ref_mut(self.generalize_t_inner(*before, bounds, lazy_inits), after) + } Poly { name, mut params } => { let params = params .iter_mut() @@ -314,18 +305,6 @@ impl Context { self.resolve_trait(t) } Type::Subr(mut subr) => { - match &mut subr.kind { - SubrKind::FuncMethod(t) => { - *t = Box::new(self.deref_tyvar(mem::take(t))?); - } - SubrKind::ProcMethod { before, after } => { - *before = Box::new(self.deref_tyvar(mem::take(before))?); - if let Some(after) = after { - *after = Box::new(self.deref_tyvar(mem::take(after))?); - } - } - _ => {} - } for param in subr.non_default_params.iter_mut() { *param.typ_mut() = self.deref_tyvar(mem::take(param.typ_mut()))?; } @@ -342,9 +321,14 @@ impl Context { let t = self.deref_tyvar(*t)?; Ok(ref_(t)) } - Type::RefMut(t) => { - let t = self.deref_tyvar(*t)?; - Ok(ref_mut(t)) + Type::RefMut { before, after } => { + let before = self.deref_tyvar(*before)?; + let after = if let Some(after) = after { + Some(self.deref_tyvar(*after)?) + } else { + None + }; + Ok(ref_mut(before, after)) } Type::Callable { .. } => todo!(), Type::Record(mut rec) => { @@ -804,10 +788,7 @@ impl Context { let lhs_t = self.into_refinement(l.clone()); self.unify(&Type::Refinement(lhs_t), rhs_t, lhs_loc, rhs_loc) } - (Type::Subr(ls), Type::Subr(rs)) if ls.kind.same_kind_as(&rs.kind) => { - if let (Some(l), Some(r)) = (ls.kind.self_t(), rs.kind.self_t()) { - self.unify(l, r, lhs_loc, rhs_loc)?; - } + (Type::Subr(ls), Type::Subr(rs)) if ls.kind == rs.kind => { for (l, r) in ls .non_default_params .iter() @@ -831,12 +812,32 @@ impl Context { } self.unify(&ls.return_t, &rs.return_t, lhs_loc, rhs_loc) } - (Type::Ref(l), Type::Ref(r)) | (Type::RefMut(l), Type::RefMut(r)) => { - self.unify(l, r, lhs_loc, rhs_loc) + (Type::Ref(l), Type::Ref(r)) => self.unify(l, r, lhs_loc, rhs_loc), + ( + Type::RefMut { + before: lbefore, + after: lafter, + }, + Type::RefMut { + before: rbefore, + after: rafter, + }, + ) => { + self.unify(lbefore, rbefore, lhs_loc, rhs_loc)?; + match (lafter, rafter) { + (Some(lafter), Some(rafter)) => { + self.unify(lafter, rafter, lhs_loc, rhs_loc)?; + } + (None, None) => {} + _ => todo!(), + } + Ok(()) } + (Type::Ref(l), r) => self.unify(l, r, lhs_loc, rhs_loc), // REVIEW: - (Type::Ref(l), r) | (Type::RefMut(l), r) => self.unify(l, r, lhs_loc, rhs_loc), - (l, Type::Ref(r)) | (l, Type::RefMut(r)) => self.unify(l, r, lhs_loc, rhs_loc), + (Type::RefMut { before, .. }, r) => self.unify(before, r, lhs_loc, rhs_loc), + (l, Type::Ref(r)) => self.unify(l, r, lhs_loc, rhs_loc), + (l, Type::RefMut { before, .. }) => self.unify(l, before, lhs_loc, rhs_loc), ( Type::Poly { name: ln, @@ -893,12 +894,32 @@ impl Context { (l, Type::FreeVar(fv)) if fv.is_linked() => { self.reunify(l, &fv.crack(), bef_loc, aft_loc) } - (Type::Ref(l), Type::Ref(r)) | (Type::RefMut(l), Type::RefMut(r)) => { - self.reunify(l, r, bef_loc, aft_loc) + (Type::Ref(l), Type::Ref(r)) => self.reunify(l, r, bef_loc, aft_loc), + ( + Type::RefMut { + before: lbefore, + after: lafter, + }, + Type::RefMut { + before: rbefore, + after: rafter, + }, + ) => { + self.reunify(lbefore, rbefore, bef_loc, aft_loc)?; + match (lafter, rafter) { + (Some(lafter), Some(rafter)) => { + self.reunify(lafter, rafter, bef_loc, aft_loc)?; + } + (None, None) => {} + _ => todo!(), + } + Ok(()) } + (Type::Ref(l), r) => self.reunify(l, r, bef_loc, aft_loc), // REVIEW: - (Type::Ref(l), r) | (Type::RefMut(l), r) => self.reunify(l, r, bef_loc, aft_loc), - (l, Type::Ref(r)) | (l, Type::RefMut(r)) => self.reunify(l, r, bef_loc, aft_loc), + (Type::RefMut { before, .. }, r) => self.reunify(before, r, bef_loc, aft_loc), + (l, Type::Ref(r)) => self.reunify(l, r, bef_loc, aft_loc), + (l, Type::RefMut { before, .. }) => self.reunify(l, before, bef_loc, aft_loc), ( Type::Poly { name: ln, @@ -1156,6 +1177,14 @@ impl Context { self.unify(&lsub.return_t, &rsub.return_t, sub_loc, sup_loc)?; return Ok(()); } + (_, Type::Ref(t)) => { + self.unify(maybe_sub, t, sub_loc, sup_loc)?; + return Ok(()); + } + (_, Type::RefMut{ before, .. }) => { + self.unify(maybe_sub, before, sub_loc, sup_loc)?; + return Ok(()); + } (Type::MonoProj { .. }, _) => todo!(), (_, Type::MonoProj { .. }) => todo!(), (Refinement(_), Refinement(_)) => todo!(), diff --git a/compiler/erg_compiler/error.rs b/compiler/erg_compiler/error.rs index 9faab9a1..2fffd1aa 100644 --- a/compiler/erg_compiler/error.rs +++ b/compiler/erg_compiler/error.rs @@ -525,10 +525,10 @@ impl TyCheckError { TypeError, loc, switch_lang!( - "japanese" => format!("{name}の型が違います。\n予期した型: {GREEN}{expect}{RESET}\n与えられた型: {RED}{found}{RESET}"), - "simplified_chinese" => format!("{name}的类型不匹配:\n预期:{GREEN}{expect}{RESET}\n但找到:{RED}{found}{RESET}"), - "traditional_chinese" => format!("{name}的類型不匹配:\n預期:{GREEN}{expect}{RESET}\n但找到:{RED}{found}{RESET}"), - "english" => format!("the type of {name} is mismatched:\nexpected: {GREEN}{expect}{RESET}\nbut found: {RED}{found}{RESET}"), + "japanese" => format!("{YELLOW}{name}{RESET}の型が違います。\n予期した型: {GREEN}{expect}{RESET}\n与えられた型: {RED}{found}{RESET}"), + "simplified_chinese" => format!("{YELLOW}{name}{RESET}的类型不匹配:\n预期:{GREEN}{expect}{RESET}\n但找到:{RED}{found}{RESET}"), + "traditional_chinese" => format!("{YELLOW}{name}{RESET}的類型不匹配:\n預期:{GREEN}{expect}{RESET}\n但找到:{RED}{found}{RESET}"), + "english" => format!("the type of {YELLOW}{name}{RESET} is mismatched:\nexpected: {GREEN}{expect}{RESET}\nbut found: {RED}{found}{RESET}"), ), hint, ), diff --git a/compiler/erg_compiler/hir.rs b/compiler/erg_compiler/hir.rs index f4dbbd10..12503eb2 100644 --- a/compiler/erg_compiler/hir.rs +++ b/compiler/erg_compiler/hir.rs @@ -1475,7 +1475,7 @@ impl Expr { pub fn __name__(&self) -> Option<&str> { match self { Expr::Accessor(acc) => acc.__name__(), - _ => todo!(), + _ => None, } } } diff --git a/compiler/erg_compiler/ownercheck.rs b/compiler/erg_compiler/ownercheck.rs index 94ea452d..c83e15ed 100644 --- a/compiler/erg_compiler/ownercheck.rs +++ b/compiler/erg_compiler/ownercheck.rs @@ -99,9 +99,6 @@ impl OwnershipChecker { // TODO: referenced Expr::Call(call) => { let args_owns = call.signature_t().unwrap().args_ownership(); - if let Some(ownership) = args_owns.self_ { - self.check_expr(&call.obj, ownership); - } let non_defaults_len = if call.method_name.is_some() { args_owns.non_defaults.len() - 1 } else { diff --git a/compiler/erg_parser/ast.rs b/compiler/erg_parser/ast.rs index 3ddf2379..4bc36505 100644 --- a/compiler/erg_parser/ast.rs +++ b/compiler/erg_parser/ast.rs @@ -1479,33 +1479,13 @@ impl ParamTySpec { } } -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub enum SubrKindSpec { - Func, - Proc, - FuncMethod(Box), - ProcMethod { - before: Box, - after: Option>, - }, -} - -impl SubrKindSpec { - pub const fn arrow(&self) -> Str { - match self { - Self::Func | Self::FuncMethod(_) => Str::ever("->"), - Self::Proc | Self::ProcMethod { .. } => Str::ever("=>"), - } - } -} - #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub struct SubrTypeSpec { - pub kind: SubrKindSpec, pub lparen: Option, pub non_defaults: Vec, pub var_args: Option>, pub defaults: Vec, + pub arrow: Token, pub return_t: Box, } @@ -1517,7 +1497,7 @@ impl fmt::Display for SubrTypeSpec { fmt_vec(&self.non_defaults), fmt_option!(pre "...", &self.var_args), fmt_vec(&self.defaults), - self.kind.arrow(), + self.arrow.content, self.return_t ) } @@ -1536,19 +1516,19 @@ impl Locational for SubrTypeSpec { impl SubrTypeSpec { pub fn new( - kind: SubrKindSpec, lparen: Option, non_defaults: Vec, var_args: Option, defaults: Vec, + arrow: Token, return_t: TypeSpec, ) -> Self { Self { - kind, lparen, non_defaults, var_args: var_args.map(Box::new), defaults, + arrow, return_t: Box::new(return_t), } } @@ -1647,40 +1627,6 @@ impl TypeSpec { pub const fn interval(op: Token, lhs: ConstExpr, rhs: ConstExpr) -> Self { Self::Interval { op, lhs, rhs } } - - pub fn func( - lparen: Option, - non_defaults: Vec, - var_args: Option, - defaults: Vec, - return_t: TypeSpec, - ) -> Self { - Self::Subr(SubrTypeSpec::new( - SubrKindSpec::Func, - lparen, - non_defaults, - var_args, - defaults, - return_t, - )) - } - - pub fn proc( - lparen: Option, - non_defaults: Vec, - var_args: Option, - defaults: Vec, - return_t: TypeSpec, - ) -> Self { - Self::Subr(SubrTypeSpec::new( - SubrKindSpec::Proc, - lparen, - non_defaults, - var_args, - defaults, - return_t, - )) - } } #[derive(Clone, Debug, PartialEq, Eq, Hash)] diff --git a/compiler/erg_type/constructors.rs b/compiler/erg_type/constructors.rs index 693d46a6..4761c2fa 100644 --- a/compiler/erg_type/constructors.rs +++ b/compiler/erg_type/constructors.rs @@ -98,8 +98,11 @@ pub fn ref_(t: Type) -> Type { Type::Ref(Box::new(t)) } -pub fn ref_mut(t: Type) -> Type { - Type::RefMut(Box::new(t)) +pub fn ref_mut(before: Type, after: Option) -> Type { + Type::RefMut { + before: Box::new(before), + after: after.map(Box::new), + } } pub fn option(t: Type) -> Type { @@ -207,13 +210,14 @@ pub fn proc2(l: Type, r: Type, return_t: Type) -> Type { pub fn fn_met( self_t: Type, - non_default_params: Vec, + mut non_default_params: Vec, var_params: Option, default_params: Vec, return_t: Type, ) -> Type { + non_default_params.insert(0, ParamTy::kw(Str::ever("self"), self_t)); Type::Subr(SubrType::new( - SubrKind::FuncMethod(Box::new(self_t)), + SubrKind::Func, non_default_params, var_params, default_params, @@ -236,15 +240,15 @@ pub fn fn1_met(self_t: Type, input_t: Type, return_t: Type) -> Type { } pub fn pr_met( - self_before: Type, - self_after: Option, - non_default_params: Vec, + self_t: Type, + mut non_default_params: Vec, var_params: Option, default_params: Vec, return_t: Type, ) -> Type { + non_default_params.insert(0, ParamTy::kw(Str::ever("self"), self_t)); Type::Subr(SubrType::new( - SubrKind::pr_met(self_before, self_after), + SubrKind::Proc, non_default_params, var_params, default_params, @@ -252,14 +256,13 @@ pub fn pr_met( )) } -pub fn pr0_met(self_before: Type, self_after: Option, return_t: Type) -> Type { - pr_met(self_before, self_after, vec![], None, vec![], return_t) +pub fn pr0_met(self_t: Type, return_t: Type) -> Type { + pr_met(self_t, vec![], None, vec![], return_t) } -pub fn pr1_met(self_before: Type, self_after: Option, input_t: Type, return_t: Type) -> Type { +pub fn pr1_met(self_t: Type, input_t: Type, return_t: Type) -> Type { pr_met( - self_before, - self_after, + self_t, vec![ParamTy::anonymous(input_t)], None, vec![], diff --git a/compiler/erg_type/free.rs b/compiler/erg_type/free.rs index 9f69fc2c..04f3a0a2 100644 --- a/compiler/erg_type/free.rs +++ b/compiler/erg_type/free.rs @@ -107,7 +107,13 @@ impl LimitedDisplay for Constraint { sup, cyclicity, } => match (sub == &Type::Never, sup == &Type::Obj) { - (true, true) => write!(f, ": Type (:> Never, <: Obj)"), + (true, true) => { + write!(f, ": Type")?; + if cfg!(feature = "debug") { + write!(f, "(:> Never, <: Obj)")?; + } + Ok(()) + } (true, false) => { write!(f, "<: ")?; sup.limited_fmt(f, limit - 1)?; diff --git a/compiler/erg_type/lib.rs b/compiler/erg_type/lib.rs index 793df2bf..c980ec8f 100644 --- a/compiler/erg_type/lib.rs +++ b/compiler/erg_type/lib.rs @@ -241,7 +241,13 @@ impl LimitedDisplay for TyBound { } match self { Self::Sandwiched { sub, mid, sup } => match (sub == &Type::Never, sup == &Type::Obj) { - (true, true) => write!(f, "{mid}: Type (:> Never, <: Obj)"), + (true, true) => { + write!(f, "{mid}: Type")?; + if cfg!(feature = "debug") { + write!(f, "(:> Never, <: Obj)")?; + } + Ok(()) + } (true, false) => { write!(f, "{mid} <: ")?; sup.limited_fmt(f, limit - 1) @@ -744,7 +750,7 @@ impl LimitedDisplay for SubrType { if limit == 0 { return write!(f, "..."); } - write!(f, "{}(", self.kind.prefix())?; + write!(f, "(")?; for (i, param) in self.non_default_params.iter().enumerate() { if i != 0 { write!(f, ", ")?; @@ -786,11 +792,9 @@ impl SubrType { } pub fn contains_tvar(&self, name: &str) -> bool { - self.kind.contains_tvar(name) - || self - .non_default_params - .iter() - .any(|pt| pt.typ().contains_tvar(name)) + self.non_default_params + .iter() + .any(|pt| pt.typ().contains_tvar(name)) || self .var_params .as_ref() @@ -804,8 +808,7 @@ impl SubrType { } pub fn has_qvar(&self) -> bool { - self.kind.has_qvar() - || self.non_default_params.iter().any(|pt| pt.typ().has_qvar()) + self.non_default_params.iter().any(|pt| pt.typ().has_qvar()) || self .var_params .as_ref() @@ -817,11 +820,6 @@ impl SubrType { pub fn typarams(&self) -> Vec { [ - self.kind - .self_t() - .map(|t| TyParam::t(t.clone())) - .into_iter() - .collect(), self.non_default_params .iter() .map(|pt| TyParam::t(pt.typ().clone())) @@ -838,6 +836,13 @@ impl SubrType { ] .concat() } + + pub fn self_t(&self) -> Option<&Type> { + self.non_default_params + .iter() + .find(|p| p.name() == Some(&Str::ever("self")) || p.name() == Some(&Str::ever("Self"))) + .map(|p| p.typ()) + } } #[derive(Debug, Clone, PartialEq, Eq, Hash)] @@ -933,157 +938,17 @@ impl QuantifiedType { } } -type SelfType = Type; - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub enum SubrKind { Func, Proc, - FuncMethod(Box), - ProcMethod { - before: Box, - after: Option>, - }, -} - -impl HasLevel for SubrKind { - fn level(&self) -> Option { - todo!() - } - - fn update_level(&self, level: usize) { - match self { - Self::FuncMethod(t) => t.update_level(level), - Self::ProcMethod { before, after } => { - before.update_level(level); - if let Some(t) = after.as_ref() { - t.update_level(level); - } - } - _ => {} - } - } - - fn lift(&self) { - match self { - Self::FuncMethod(t) => t.lift(), - Self::ProcMethod { before, after } => { - before.lift(); - if let Some(t) = after.as_ref() { - t.lift(); - } - } - _ => {} - } - } } impl SubrKind { - pub fn fn_met(t: SelfType) -> Self { - SubrKind::FuncMethod(Box::new(t)) - } - - pub fn pr_met(before: SelfType, after: Option) -> Self { - Self::ProcMethod { - before: Box::new(before), - after: after.map(Box::new), - } - } - pub const fn arrow(&self) -> Str { match self { - Self::Func | Self::FuncMethod(_) => Str::ever("->"), - Self::Proc | Self::ProcMethod { .. } => Str::ever("=>"), - } - } - - pub const fn inner_len(&self) -> usize { - match self { - Self::Func | Self::Proc => 0, - Self::FuncMethod(_) | Self::ProcMethod { .. } => 1, - } - } - - pub fn prefix(&self) -> String { - match self { - Self::Func | Self::Proc => "".to_string(), - Self::FuncMethod(t) => format!("{t}."), - Self::ProcMethod { before, after } => { - if let Some(after) = after { - format!("({before} ~> {after}).") - } else { - format!("{before}.") - } - } - } - } - - pub fn has_qvar(&self) -> bool { - match self { - Self::Func | Self::Proc => false, - Self::FuncMethod(t) => t.has_qvar(), - Self::ProcMethod { before, after } => { - before.has_qvar() || after.as_ref().map(|t| t.has_qvar()).unwrap_or(false) - } - } - } - - pub fn contains_tvar(&self, name: &str) -> bool { - match self { - Self::Func | Self::Proc => false, - Self::FuncMethod(t) => t.contains_tvar(name), - Self::ProcMethod { before, after } => { - before.contains_tvar(name) - || after - .as_ref() - .map(|t| t.contains_tvar(name)) - .unwrap_or(false) - } - } - } - - pub fn is_cachable(&self) -> bool { - match self { - Self::Func | Self::Proc => true, - Self::FuncMethod(t) => t.is_cachable(), - Self::ProcMethod { before, after } => { - before.is_cachable() && after.as_ref().map(|t| t.is_cachable()).unwrap_or(true) - } - } - } - - pub fn has_unbound_var(&self) -> bool { - match self { - Self::Func | Self::Proc => false, - Self::FuncMethod(t) => t.has_unbound_var(), - Self::ProcMethod { before, after } => { - before.has_unbound_var() - || after.as_ref().map(|t| t.has_unbound_var()).unwrap_or(false) - } - } - } - - pub fn same_kind_as(&self, other: &Self) -> bool { - matches!( - (self, other), - (Self::Func, Self::Func) - | (Self::Proc, Self::Proc) - | (Self::FuncMethod(_), Self::FuncMethod(_)) - | (Self::ProcMethod { .. }, Self::ProcMethod { .. }) - ) - } - - pub fn self_t(&self) -> Option<&SelfType> { - match self { - Self::FuncMethod(t) | Self::ProcMethod { before: t, .. } => Some(t), - _ => None, - } - } - - pub fn self_t_mut(&mut self) -> Option<&mut SelfType> { - match self { - Self::FuncMethod(t) | Self::ProcMethod { before: t, .. } => Some(t), - _ => None, + Self::Func => Str::ever("->"), + Self::Proc => Str::ever("=>"), } } } @@ -1109,7 +974,6 @@ impl Ownership { #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct ArgsOwnership { - pub self_: Option, pub non_defaults: Vec, pub var_params: Option, pub defaults: Vec<(Str, Ownership)>, @@ -1117,9 +981,6 @@ pub struct ArgsOwnership { impl fmt::Display for ArgsOwnership { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - if let Some(self_) = self.self_.as_ref() { - write!(f, "({self_:?}).")?; - } write!(f, "(")?; for (i, o) in self.non_defaults.iter().enumerate() { if i != 0 { @@ -1140,13 +1001,11 @@ impl fmt::Display for ArgsOwnership { impl ArgsOwnership { pub const fn new( - self_: Option, non_defaults: Vec, var_params: Option, defaults: Vec<(Str, Ownership)>, ) -> Self { Self { - self_, non_defaults, var_params, defaults, @@ -1182,7 +1041,10 @@ pub enum Type { Mono(Str), /* Polymorphic types */ Ref(Box), - RefMut(Box), + RefMut { + before: Box, + after: Option>, + }, Subr(SubrType), // CallableはProcの上位型なので、変数に!をつける Callable { @@ -1248,7 +1110,17 @@ impl PartialEq for Type { | (Self::Never, Self::Never) => true, (Self::Mono(l), Self::Mono(r)) => l == r, (Self::MonoQVar(l), Self::MonoQVar(r)) => l == r, - (Self::Ref(l), Self::Ref(r)) | (Self::RefMut(l), Self::RefMut(r)) => l == r, + (Self::Ref(l), Self::Ref(r)) => l == r, + ( + Self::RefMut { + before: l1, + after: l2, + }, + Self::RefMut { + before: r1, + after: r2, + }, + ) => l1 == r1 && l2 == r2, (Self::Subr(l), Self::Subr(r)) => l == r, ( Self::Callable { @@ -1332,11 +1204,20 @@ impl LimitedDisplay for Type { } match self { Self::Mono(name) => write!(f, "{name}"), - Self::Ref(t) | Self::RefMut(t) => { + Self::Ref(t) => { write!(f, "{}(", self.name())?; t.limited_fmt(f, limit - 1)?; write!(f, ")") } + Self::RefMut { before, after } => { + write!(f, "{}(", self.name())?; + before.limited_fmt(f, limit - 1)?; + if let Some(after) = after { + write!(f, " ~> ")?; + after.limited_fmt(f, limit - 1)?; + } + write!(f, ")") + } Self::Callable { param_ts, return_t } => { write!(f, "Callable((")?; for (i, t) in param_ts.iter().enumerate() { @@ -1492,9 +1373,13 @@ impl HasType for Type { } fn inner_ts(&self) -> Vec { match self { - Self::Ref(t) | Self::RefMut(t) => { + Self::Ref(t) => { vec![t.as_ref().clone()] } + Self::RefMut { before, .. } => { + // REVIEW: + vec![before.as_ref().clone()] + } // Self::And(ts) | Self::Or(ts) => , Self::Subr(_sub) => todo!(), Self::Callable { param_ts, .. } => param_ts.clone(), @@ -1522,7 +1407,13 @@ impl HasLevel for Type { fn update_level(&self, level: Level) { match self { Self::FreeVar(v) => v.update_level(level), - Self::Ref(t) | Self::RefMut(t) => t.update_level(level), + Self::Ref(t) => t.update_level(level), + Self::RefMut { before, after } => { + before.update_level(level); + if let Some(after) = after { + after.update_level(level); + } + } Self::Callable { param_ts, return_t } => { for p in param_ts.iter() { p.update_level(level); @@ -1530,7 +1421,6 @@ impl HasLevel for Type { return_t.update_level(level); } Self::Subr(subr) => { - subr.kind.update_level(level); for pt in subr.non_default_params.iter() { pt.typ().update_level(level); } @@ -1578,7 +1468,13 @@ impl HasLevel for Type { fn lift(&self) { match self { Self::FreeVar(v) => v.lift(), - Self::Ref(t) | Self::RefMut(t) => t.lift(), + Self::Ref(t) => t.lift(), + Self::RefMut { before, after } => { + before.lift(); + if let Some(after) = after { + after.lift(); + } + } Self::Callable { param_ts, return_t } => { for p in param_ts.iter() { p.lift(); @@ -1586,7 +1482,6 @@ impl HasLevel for Type { return_t.lift(); } Self::Subr(subr) => { - subr.kind.lift(); for pt in subr.non_default_params.iter() { pt.typ().lift(); } @@ -1763,12 +1658,11 @@ impl Type { Self::FreeVar(fv) if fv.is_linked() => fv.crack().args_ownership(), Self::Refinement(refine) => refine.t.args_ownership(), Self::Subr(subr) => { - let self_ = subr.kind.self_t().map(|t| t.ownership()); let mut nd_args = vec![]; for nd_param in subr.non_default_params.iter() { let ownership = match nd_param.typ() { Self::Ref(_) => Ownership::Ref, - Self::RefMut(_) => Ownership::RefMut, + Self::RefMut { .. } => Ownership::RefMut, _ => Ownership::Owned, }; nd_args.push(ownership); @@ -1778,12 +1672,12 @@ impl Type { for d_param in subr.default_params.iter() { let ownership = match d_param.typ() { Self::Ref(_) => Ownership::Ref, - Self::RefMut(_) => Ownership::RefMut, + Self::RefMut { .. } => Ownership::RefMut, _ => Ownership::Owned, }; d_args.push((d_param.name().unwrap().clone(), ownership)); } - ArgsOwnership::new(self_, nd_args, var_args, d_args) + ArgsOwnership::new(nd_args, var_args, d_args) } _ => todo!(), } @@ -1794,7 +1688,7 @@ impl Type { Self::FreeVar(fv) if fv.is_linked() => fv.crack().ownership(), Self::Refinement(refine) => refine.t.ownership(), Self::Ref(_) => Ownership::Ref, - Self::RefMut(_) => Ownership::RefMut, + Self::RefMut { .. } => Ownership::RefMut, _ => Ownership::Owned, } } @@ -1824,7 +1718,7 @@ impl Type { Self::Not(_, _) => Str::ever("Not"), Self::Or(_, _) => Str::ever("Or"), Self::Ref(_) => Str::ever("Ref"), - Self::RefMut(_) => Str::ever("RefMut"), + Self::RefMut { .. } => Str::ever("RefMut"), Self::Subr(SubrType { kind: SubrKind::Func, .. @@ -1833,14 +1727,6 @@ impl Type { kind: SubrKind::Proc, .. }) => Str::ever("Proc"), - Self::Subr(SubrType { - kind: SubrKind::FuncMethod(_), - .. - }) => Str::ever("FuncMethod"), - Self::Subr(SubrType { - kind: SubrKind::ProcMethod { .. }, - .. - }) => Str::ever("ProcMethod"), Self::Callable { .. } => Str::ever("Callable"), Self::Record(_) => Str::ever("Record"), Self::Poly { name, .. } | Self::PolyQVar { name, .. } => name.clone(), @@ -1891,7 +1777,7 @@ impl Type { matches!(self, Self::Subr { .. } | Self::Callable { .. }) } - pub fn is_tyvar(&self) -> bool { + pub fn is_unbound_var(&self) -> bool { matches!(self, Self::FreeVar(fv) if fv.is_unbound()) } @@ -1905,7 +1791,10 @@ impl Type { fv.crack().has_qvar() } } - Self::Ref(t) | Self::RefMut(t) => t.has_qvar(), + Self::Ref(t) => t.has_qvar(), + Self::RefMut { before, after } => { + before.has_qvar() || after.as_ref().map(|t| t.has_qvar()).unwrap_or(false) + } Self::And(lhs, rhs) | Self::Not(lhs, rhs) | Self::Or(lhs, rhs) => { lhs.has_qvar() || rhs.has_qvar() } @@ -1930,7 +1819,10 @@ impl Type { pub fn is_cachable(&self) -> bool { match self { Self::FreeVar(_) => false, - Self::Ref(t) | Self::RefMut(t) => t.is_cachable(), + Self::Ref(t) => t.is_cachable(), + Self::RefMut { before, after } => { + before.is_cachable() && after.as_ref().map(|t| t.is_cachable()).unwrap_or(true) + } Self::And(lhs, rhs) | Self::Not(lhs, rhs) | Self::Or(lhs, rhs) => { lhs.is_cachable() && rhs.is_cachable() } @@ -1938,15 +1830,13 @@ impl Type { param_ts.iter().all(|t| t.is_cachable()) && return_t.is_cachable() } Self::Subr(subr) => { - subr.kind.is_cachable() - && subr - .non_default_params - .iter() - .all(|pt| pt.typ().has_unbound_var()) + subr.non_default_params + .iter() + .all(|pt| pt.typ().is_cachable()) && subr .var_params .as_ref() - .map(|pt| pt.typ().has_unbound_var()) + .map(|pt| pt.typ().is_cachable()) .unwrap_or(false) && subr.default_params.iter().all(|pt| pt.typ().is_cachable()) && subr.return_t.is_cachable() @@ -1975,7 +1865,11 @@ impl Type { fv.crack().has_unbound_var() } } - Self::Ref(t) | Self::RefMut(t) => t.has_unbound_var(), + Self::Ref(t) => t.has_unbound_var(), + Self::RefMut { before, after } => { + before.has_unbound_var() + || after.as_ref().map(|t| t.has_unbound_var()).unwrap_or(false) + } Self::And(lhs, rhs) | Self::Not(lhs, rhs) | Self::Or(lhs, rhs) => { lhs.has_unbound_var() || rhs.has_unbound_var() } @@ -1983,11 +1877,9 @@ impl Type { param_ts.iter().any(|t| t.has_unbound_var()) || return_t.has_unbound_var() } Self::Subr(subr) => { - subr.kind.has_unbound_var() - || subr - .non_default_params - .iter() - .any(|pt| pt.typ().has_unbound_var()) + subr.non_default_params + .iter() + .any(|pt| pt.typ().has_unbound_var()) || subr .var_params .as_ref() @@ -2024,11 +1916,10 @@ impl Type { Self::FreeVar(fv) if fv.is_linked() => fv.crack().typarams_len(), Self::Refinement(refine) => refine.t.typarams_len(), // REVIEW: - Self::Ref(_) | Self::RefMut(_) => Some(1), + Self::Ref(_) | Self::RefMut { .. } => Some(1), Self::And(_, _) | Self::Or(_, _) | Self::Not(_, _) => Some(2), Self::Subr(subr) => Some( - subr.kind.inner_len() - + subr.non_default_params.len() + subr.non_default_params.len() + subr.var_params.as_ref().map(|_| 1).unwrap_or(0) + subr.default_params.len() + 1, @@ -2044,7 +1935,7 @@ impl Type { Self::FreeVar(f) if f.is_linked() => f.crack().typarams(), Self::FreeVar(_unbound) => vec![], Self::Refinement(refine) => refine.t.typarams(), - Self::Ref(t) | Self::RefMut(t) => vec![TyParam::t(*t.clone())], + Self::Ref(t) | Self::RefMut { before: t, .. } => vec![TyParam::t(*t.clone())], Self::And(lhs, rhs) | Self::Not(lhs, rhs) | Self::Or(lhs, rhs) => { vec![TyParam::t(*lhs.clone()), TyParam::t(*rhs.clone())] } @@ -2059,10 +1950,7 @@ impl Type { match self { Self::FreeVar(fv) if fv.is_linked() => todo!("linked: {fv}"), Self::Refinement(refine) => refine.t.self_t(), - Self::Subr(SubrType { - kind: SubrKind::FuncMethod(self_t) | SubrKind::ProcMethod { before: self_t, .. }, - .. - }) => Some(self_t), + Self::Subr(subr) => subr.self_t(), _ => None, } } From da7b82d868dccc46e34ae73d673ba42f29d6c0b7 Mon Sep 17 00:00:00 2001 From: Shunsuke Shibayama Date: Thu, 8 Sep 2022 13:59:16 +0900 Subject: [PATCH 49/68] Improve error display --- compiler/erg_compiler/context/inquire.rs | 10 +++---- compiler/erg_compiler/hir.rs | 36 +++++++++++++++--------- compiler/erg_compiler/lower.rs | 2 +- 3 files changed, 28 insertions(+), 20 deletions(-) diff --git a/compiler/erg_compiler/context/inquire.rs b/compiler/erg_compiler/context/inquire.rs index e0970468..012dc4ee 100644 --- a/compiler/erg_compiler/context/inquire.rs +++ b/compiler/erg_compiler/context/inquire.rs @@ -714,7 +714,7 @@ impl Context { log!(err "semi-unification failed with {callee}\n{arg_t} !<: {param_t}"); log!(err "errno: {}", e.core.errno); // REVIEW: - let name = callee.var_full_name().unwrap_or_else(|| "".to_string()); + let name = callee.show_acc().unwrap_or_else(|| "".to_string()); let name = name + "::" + param.name().map(|s| readable_name(&s[..])).unwrap_or(""); TyCheckError::type_mismatch_error( line!() as usize, @@ -755,7 +755,7 @@ impl Context { log!(err "semi-unification failed with {callee}\n{arg_t} !<: {param_t}"); log!(err "errno: {}", e.core.errno); // REVIEW: - let name = callee.var_full_name().unwrap_or_else(|| "".to_string()); + let name = callee.show_acc().unwrap_or_else(|| "".to_string()); let name = name + "::" + param.name().map(|s| readable_name(&s[..])).unwrap_or(""); TyCheckError::type_mismatch_error( line!() as usize, @@ -798,7 +798,7 @@ impl Context { log!(err "semi-unification failed with {callee}\n{arg_t} !<: {}", pt.typ()); log!(err "errno: {}", e.core.errno); // REVIEW: - let name = callee.var_full_name().unwrap_or_else(|| "".to_string()); + let name = callee.show_acc().unwrap_or_else(|| "".to_string()); let name = name + "::" + readable_name(kw_name); TyCheckError::type_mismatch_error( line!() as usize, @@ -1218,9 +1218,9 @@ impl Context { log!("{}", obj.ref_t()); match obj.ref_t() { // TODO: attr - Type::Module => self.rec_get_mod(&obj.var_full_name()?), + Type::Module => self.rec_get_mod(&obj.show_acc()?), Type::Type | Type::Class => { - let typ = Type::Mono(Str::from(obj.var_full_name().unwrap())); + let typ = Type::Mono(Str::from(obj.show_acc().unwrap())); self.rec_get_nominal_type_ctx(&typ).map(|(_, ctx)| ctx) } Type::Trait => todo!(), diff --git a/compiler/erg_compiler/hir.rs b/compiler/erg_compiler/hir.rs index 12503eb2..cc289072 100644 --- a/compiler/erg_compiler/hir.rs +++ b/compiler/erg_compiler/hir.rs @@ -475,18 +475,26 @@ impl Accessor { Self::Subscr(Subscript::new(obj, index, t)) } - pub fn var_full_name(&self) -> Option { + pub fn show(&self) -> String { match self { - Self::Local(local) => Some(readable_name(local.inspect()).to_string()), - Self::Attr(attr) => attr - .obj - .var_full_name() - .map(|n| n + "." + readable_name(attr.name.inspect())), - Self::TupleAttr(t_attr) => t_attr - .obj - .var_full_name() - .map(|n| n + "." + t_attr.index.token.inspect()), - Self::Subscr(_) | Self::Public(_) => todo!(), + Self::Local(local) => readable_name(local.inspect()).to_string(), + Self::Public(public) => readable_name(public.inspect()).to_string(), + Self::Attr(attr) => { + attr.obj + .show_acc() + .unwrap_or_else(|| attr.obj.ref_t().to_string()) + + "." + + readable_name(attr.name.inspect()) + } + Self::TupleAttr(t_attr) => { + t_attr + .obj + .show_acc() + .unwrap_or_else(|| t_attr.obj.ref_t().to_string()) + + "." + + t_attr.index.token.inspect() + } + Self::Subscr(_) => todo!(), } } @@ -970,7 +978,7 @@ impl Call { pub fn is_import_call(&self) -> bool { self.obj - .var_full_name() + .show_acc() .map(|s| &s[..] == "import" || &s[..] == "pyimport" || &s[..] == "py") .unwrap_or(false) } @@ -1464,9 +1472,9 @@ impl Expr { } } - pub fn var_full_name(&self) -> Option { + pub fn show_acc(&self) -> Option { match self { - Expr::Accessor(acc) => acc.var_full_name(), + Expr::Accessor(acc) => Some(acc.show()), _ => None, } } diff --git a/compiler/erg_compiler/lower.rs b/compiler/erg_compiler/lower.rs index bbd0087b..e777cfdf 100644 --- a/compiler/erg_compiler/lower.rs +++ b/compiler/erg_compiler/lower.rs @@ -633,7 +633,7 @@ impl ASTLowerer { 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[..]) { + hir::Expr::Call(mut call) => match call.obj.show_acc().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") => { From e6f97dfa777778cb79390078115ccfeea8b19cb6 Mon Sep 17 00:00:00 2001 From: Shunsuke Shibayama Date: Thu, 8 Sep 2022 14:06:14 +0900 Subject: [PATCH 50/68] Update version (v0.4.0-beta.0) --- Cargo.lock | 10 +++++----- Cargo.toml | 10 +++++----- compiler/erg_common/Cargo.toml | 2 +- compiler/erg_compiler/Cargo.toml | 8 ++++---- compiler/erg_parser/Cargo.toml | 4 ++-- compiler/erg_type/Cargo.toml | 4 ++-- 6 files changed, 19 insertions(+), 19 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5ee397d5..ca2d039a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -15,7 +15,7 @@ dependencies = [ [[package]] name = "erg" -version = "0.3.2" +version = "0.4.0-beta.0" dependencies = [ "erg_common", "erg_compiler", @@ -25,14 +25,14 @@ dependencies = [ [[package]] name = "erg_common" -version = "0.3.2" +version = "0.4.0-beta.0" dependencies = [ "atty", ] [[package]] name = "erg_compiler" -version = "0.3.2" +version = "0.4.0-beta.0" dependencies = [ "erg_common", "erg_parser", @@ -41,14 +41,14 @@ dependencies = [ [[package]] name = "erg_parser" -version = "0.3.2" +version = "0.4.0-beta.0" dependencies = [ "erg_common", ] [[package]] name = "erg_type" -version = "0.3.2" +version = "0.4.0-beta.0" dependencies = [ "erg_common", ] diff --git a/Cargo.toml b/Cargo.toml index be687770..8c7d2f70 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "erg" -version = "0.3.2" +version = "0.4.0-beta.0" description = "The Erg programming language" authors = ["Shunsuke Shibayama "] license = "MIT OR Apache-2.0" @@ -46,10 +46,10 @@ traditional_chinese = [ ] [dependencies] -erg_common = { version = "0.3.2", path = "./compiler/erg_common" } -erg_parser = { version = "0.3.2", path = "./compiler/erg_parser" } -erg_compiler = { version = "0.3.2", path = "./compiler/erg_compiler" } -erg_type = { version = "0.3.2", path = "./compiler/erg_type" } +erg_common = { version = "0.4.0-beta.0", path = "./compiler/erg_common" } +erg_parser = { version = "0.4.0-beta.0", path = "./compiler/erg_parser" } +erg_compiler = { version = "0.4.0-beta.0", path = "./compiler/erg_compiler" } +erg_type = { version = "0.4.0-beta.0", path = "./compiler/erg_type" } # [workspace] # member = ["cm", "dyne"] diff --git a/compiler/erg_common/Cargo.toml b/compiler/erg_common/Cargo.toml index 913bb1e4..5405e3a9 100644 --- a/compiler/erg_common/Cargo.toml +++ b/compiler/erg_common/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "erg_common" -version = "0.3.2" +version = "0.4.0-beta.0" description = "A common components library of Erg" authors = ["Shunsuke Shibayama "] license = "MIT OR Apache-2.0" diff --git a/compiler/erg_compiler/Cargo.toml b/compiler/erg_compiler/Cargo.toml index ad8067cc..083ea9be 100644 --- a/compiler/erg_compiler/Cargo.toml +++ b/compiler/erg_compiler/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "erg_compiler" -version = "0.3.2" +version = "0.4.0-beta.0" description = "Centimetre: the Erg compiler" authors = ["Shunsuke Shibayama "] license = "MIT OR Apache-2.0" @@ -17,9 +17,9 @@ simplified_chinese = [ "erg_common/simplified_chinese", "erg_parser/simplified_c traditional_chinese = [ "erg_common/traditional_chinese", "erg_parser/traditional_chinese", "erg_type/traditional_chinese" ] [dependencies] -erg_common = { version = "0.3.2", path = "../erg_common" } -erg_parser = { version = "0.3.2", path = "../erg_parser" } -erg_type = { version = "0.3.2", path = "../erg_type" } +erg_common = { version = "0.4.0-beta.0", path = "../erg_common" } +erg_parser = { version = "0.4.0-beta.0", path = "../erg_parser" } +erg_type = { version = "0.4.0-beta.0", path = "../erg_type" } [lib] path = "lib.rs" diff --git a/compiler/erg_parser/Cargo.toml b/compiler/erg_parser/Cargo.toml index 9769b4d5..e237412f 100644 --- a/compiler/erg_parser/Cargo.toml +++ b/compiler/erg_parser/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "erg_parser" -version = "0.3.2" +version = "0.4.0-beta.0" description = "The Erg parser" authors = ["mtshiba "] license = "MIT OR Apache-2.0" @@ -16,7 +16,7 @@ simplified_chinese = [ "erg_common/simplified_chinese" ] traditional_chinese = [ "erg_common/traditional_chinese" ] [dependencies] -erg_common = { version = "0.3.2", path = "../erg_common" } +erg_common = { version = "0.4.0-beta.0", path = "../erg_common" } [lib] path = "lib.rs" diff --git a/compiler/erg_type/Cargo.toml b/compiler/erg_type/Cargo.toml index e209f605..80e044b2 100644 --- a/compiler/erg_type/Cargo.toml +++ b/compiler/erg_type/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "erg_type" -version = "0.3.2" +version = "0.4.0-beta.0" description = "APIs for Erg types" authors = ["Shunsuke Shibayama "] license = "MIT OR Apache-2.0" @@ -18,7 +18,7 @@ simplified_chinese = [ "erg_common/simplified_chinese" ] traditional_chinese = [ "erg_common/traditional_chinese" ] [dependencies] -erg_common = { version = "0.3.2", path = "../erg_common" } +erg_common = { version = "0.4.0-beta.0", path = "../erg_common" } [lib] path = "lib.rs" From 7573c0e1285529802bd1c85d30acd6cd54090be4 Mon Sep 17 00:00:00 2001 From: Shunsuke Shibayama Date: Fri, 9 Sep 2022 01:07:34 +0900 Subject: [PATCH 51/68] Fix duplicate method definition bugs --- compiler/erg_common/dict.rs | 8 ++++++ compiler/erg_compiler/codegen.rs | 2 +- compiler/erg_compiler/context/inquire.rs | 4 +++ compiler/erg_compiler/context/mod.rs | 14 +++++++++ compiler/erg_compiler/context/register.rs | 35 ++++++++++++++++++++--- compiler/erg_compiler/error.rs | 24 ++++++++++++++++ compiler/erg_compiler/link.rs | 8 +++--- compiler/erg_compiler/lower.rs | 29 +++++++++++++++++-- compiler/erg_compiler/varinfo.rs | 1 + 9 files changed, 113 insertions(+), 12 deletions(-) diff --git a/compiler/erg_common/dict.rs b/compiler/erg_common/dict.rs index 98920f17..6785e9d4 100644 --- a/compiler/erg_common/dict.rs +++ b/compiler/erg_common/dict.rs @@ -153,6 +153,14 @@ impl Dict { self.dict.get_mut(k) } + pub fn get_key_value(&self, k: &Q) -> Option<(&K, &V)> + where + K: Borrow, + Q: Hash + Eq, + { + self.dict.get_key_value(k) + } + #[inline] pub fn contains_key(&self, k: &Q) -> bool where diff --git a/compiler/erg_compiler/codegen.rs b/compiler/erg_compiler/codegen.rs index 641357e3..b17b2720 100644 --- a/compiler/erg_compiler/codegen.rs +++ b/compiler/erg_compiler/codegen.rs @@ -202,7 +202,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"), - (_, _, "new" | "__new__") => Str::ever("__call__"), + (_, _, "__new__") => Str::ever("__call__"), ("StringIO!", _, "getvalue!") => Str::ever("getvalue"), ("Module", Some("importlib"), "reload!") => Str::ever("reload"), ("Module", Some("random"), "randint!") => Str::ever("randint"), diff --git a/compiler/erg_compiler/context/inquire.rs b/compiler/erg_compiler/context/inquire.rs index 012dc4ee..d0a33aed 100644 --- a/compiler/erg_compiler/context/inquire.rs +++ b/compiler/erg_compiler/context/inquire.rs @@ -80,6 +80,10 @@ impl Context { }) } + pub(crate) fn get_local_kv(&self, name: &str) -> Option<(&VarName, &VarInfo)> { + self.locals.get_key_value(name) + } + fn get_context( &self, obj: &hir::Expr, diff --git a/compiler/erg_compiler/context/mod.rs b/compiler/erg_compiler/context/mod.rs index 923955a1..038f0cfa 100644 --- a/compiler/erg_compiler/context/mod.rs +++ b/compiler/erg_compiler/context/mod.rs @@ -490,6 +490,20 @@ impl Context { Self::poly_class(name, vec![], super_classes, super_traits, level) } + #[inline] + pub fn methods>(name: S, level: usize) -> Self { + Self::with_capacity( + name.into(), + ContextKind::MethodDefs, + vec![], + None, + vec![], + vec![], + 2, + level, + ) + } + #[inline] pub fn poly_patch>( name: S, diff --git a/compiler/erg_compiler/context/register.rs b/compiler/erg_compiler/context/register.rs index 02496b44..4727933b 100644 --- a/compiler/erg_compiler/context/register.rs +++ b/compiler/erg_compiler/context/register.rs @@ -508,6 +508,7 @@ impl Context { Ok(()) } + /// e.g. .new fn register_auto_impl( &mut self, name: &'static str, @@ -524,6 +525,23 @@ impl Context { } } + /// e.g. ::__new__ + fn register_fixed_auto_impl( + &mut self, + name: &'static str, + t: Type, + muty: Mutability, + vis: Visibility, + ) { + let name = VarName::from_static(name); + if self.locals.get(&name).is_some() { + panic!("already registered: {name}"); + } else { + self.locals + .insert(name, VarInfo::new(t, muty, vis, VarKind::FixedAuto, None)); + } + } + fn _register_gen_decl(&mut self, name: VarName, t: Type, vis: Visibility) { if self.decls.get(&name).is_some() { panic!("already registered: {name}"); @@ -577,11 +595,13 @@ impl Context { if gen.t.is_monomorphic() { let super_traits = gen.impls.iter().map(|to| to.typ().clone()).collect(); let mut ctx = Self::mono_class(gen.t.name(), vec![], super_traits, self.level); + let mut methods = Self::methods(gen.t.name(), self.level); let require = gen.require_or_sup.typ().clone(); let new_t = func1(require, gen.t.clone()); - ctx.register_auto_impl("__new__", new_t.clone(), Immutable, Private); + methods.register_fixed_auto_impl("__new__", new_t.clone(), Immutable, Private); // 必要なら、ユーザーが独自に上書きする - ctx.register_auto_impl("new", new_t, Immutable, Public); + methods.register_auto_impl("new", new_t, Immutable, Public); + ctx.method_defs.push((gen.t.clone(), methods)); self.register_gen_mono_type(gen, ctx, Const); } else { todo!() @@ -593,6 +613,7 @@ impl Context { let super_traits = gen.impls.iter().map(|to| to.typ().clone()).collect(); let mut ctx = Self::mono_class(gen.t.name(), super_classes, super_traits, self.level); + let mut methods = Self::methods(gen.t.name(), self.level); if let Some(sup) = self.rec_get_const_obj(&gen.require_or_sup.typ().name()) { let sup = enum_unwrap!(sup, ValueObj::Type); let param_t = match sup { @@ -607,9 +628,15 @@ impl Context { param_t.clone() }; let new_t = func1(param_t, gen.t.clone()); - ctx.register_auto_impl("__new__", new_t.clone(), Immutable, Private); + methods.register_fixed_auto_impl( + "__new__", + new_t.clone(), + Immutable, + Private, + ); // 必要なら、ユーザーが独自に上書きする - ctx.register_auto_impl("new", new_t, Immutable, Public); + methods.register_auto_impl("new", new_t, Immutable, Public); + ctx.method_defs.push((gen.t.clone(), methods)); self.register_gen_mono_type(gen, ctx, Const); } else { todo!("super class not found") diff --git a/compiler/erg_compiler/error.rs b/compiler/erg_compiler/error.rs index 2fffd1aa..55544d16 100644 --- a/compiler/erg_compiler/error.rs +++ b/compiler/erg_compiler/error.rs @@ -331,6 +331,30 @@ impl TyCheckError { ) } + pub fn duplicate_definition_error( + errno: usize, + loc: Location, + caused_by: Str, + name: &str, + ) -> Self { + let name = readable_name(name); + Self::new( + ErrorCore::new( + errno, + NameError, + loc, + switch_lang!( + "japanese" => format!("{name}は既に定義されています"), + "simplified_chinese" => format!("{name}已定义"), + "traditional_chinese" => format!("{name}已定義"), + "english" => format!("{name} is already defined"), + ), + Option::::None, + ), + caused_by, + ) + } + pub fn violate_decl_error( errno: usize, loc: Location, diff --git a/compiler/erg_compiler/link.rs b/compiler/erg_compiler/link.rs index 2ddbbba8..cb5deee2 100644 --- a/compiler/erg_compiler/link.rs +++ b/compiler/erg_compiler/link.rs @@ -50,12 +50,12 @@ impl Linker { Expr::Methods(methods) => match &methods.class { TypeSpec::PreDeclTy(PreDeclTypeSpec::Simple(simple)) => { if let Some(pos) = self.def_root_pos_map.get(simple.name.inspect()) { - let mut type_def = match new.remove(*pos) { - Expr::ClassDef(type_def) => type_def, + let mut class_def = match new.remove(*pos) { + Expr::ClassDef(class_def) => class_def, _ => unreachable!(), }; - type_def.methods_list.push(methods); - new.insert(*pos, Expr::ClassDef(type_def)); + class_def.methods_list.push(methods); + new.insert(*pos, Expr::ClassDef(class_def)); } else { log!("{}", simple.name.inspect()); log!("{}", self.def_root_pos_map); diff --git a/compiler/erg_compiler/lower.rs b/compiler/erg_compiler/lower.rs index e777cfdf..a6fd08e2 100644 --- a/compiler/erg_compiler/lower.rs +++ b/compiler/erg_compiler/lower.rs @@ -570,10 +570,33 @@ impl ASTLowerer { } } match self.ctx.pop() { - Ok(ctx) => { - self.check_override(&class, &ctx); + Ok(methods) => { + self.check_override(&class, &methods); if let Some((_, class_root)) = self.ctx.rec_get_mut_nominal_type_ctx(&class) { - class_root.method_defs.push((class, ctx)); + for (newly_defined_name, _vi) in methods.locals.iter() { + for (_, already_defined_methods) in class_root.method_defs.iter_mut() { + // TODO: 特殊化なら同じ名前でもOK + // TODO: 定義のメソッドもエラー表示 + if let Some((_already_defined_name, already_defined_vi)) = + already_defined_methods + .get_local_kv(&newly_defined_name.inspect()) + { + if already_defined_vi.kind != VarKind::Auto { + self.errs.push(LowerError::duplicate_definition_error( + line!() as usize, + newly_defined_name.loc(), + methods.name.clone(), + newly_defined_name.inspect(), + )); + } else { + already_defined_methods + .locals + .remove(&newly_defined_name.inspect()[..]); + } + } + } + } + class_root.method_defs.push((class, methods)); } else { todo!() } diff --git a/compiler/erg_compiler/varinfo.rs b/compiler/erg_compiler/varinfo.rs index e88339c1..5bb4fb11 100644 --- a/compiler/erg_compiler/varinfo.rs +++ b/compiler/erg_compiler/varinfo.rs @@ -68,6 +68,7 @@ pub enum VarKind { default: DefaultInfo, }, Auto, + FixedAuto, DoesNotExist, Builtin, } From c2edad755678f70f1f26e2472b6fb92827ac542c Mon Sep 17 00:00:00 2001 From: Shunsuke Shibayama Date: Fri, 9 Sep 2022 01:08:05 +0900 Subject: [PATCH 52/68] Impl `Location::RangePair` --- compiler/erg_common/error.rs | 108 ++++++++++++++++++++++------------ compiler/erg_common/traits.rs | 10 +++- 2 files changed, 77 insertions(+), 41 deletions(-) diff --git a/compiler/erg_common/error.rs b/compiler/erg_common/error.rs index e00438bc..4b0df9f5 100644 --- a/compiler/erg_common/error.rs +++ b/compiler/erg_common/error.rs @@ -203,9 +203,9 @@ impl From<&str> for ErrorKind { #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub enum Location { RangePair { - ln_begin: usize, + ln_first: (usize, usize), col_first: (usize, usize), - ln_end: usize, + ln_second: (usize, usize), col_second: (usize, usize), }, Range { @@ -240,16 +240,19 @@ impl Location { pub fn pair(lhs: Self, rhs: Self) -> Self { Self::RangePair { - ln_begin: lhs.ln_begin().unwrap(), + ln_first: (lhs.ln_begin().unwrap(), lhs.ln_end().unwrap()), col_first: (lhs.col_begin().unwrap(), lhs.col_end().unwrap()), - ln_end: rhs.ln_end().unwrap(), + ln_second: (rhs.ln_begin().unwrap(), rhs.ln_end().unwrap()), col_second: (rhs.col_begin().unwrap(), rhs.col_end().unwrap()), } } pub const fn ln_begin(&self) -> Option { match self { - Self::RangePair { ln_begin, .. } + Self::RangePair { + ln_first: (ln_begin, _), + .. + } | Self::Range { ln_begin, .. } | Self::LineRange(ln_begin, _) | Self::Line(ln_begin) => Some(*ln_begin), @@ -259,7 +262,10 @@ impl Location { pub const fn ln_end(&self) -> Option { match self { - Self::RangePair { ln_end, .. } + Self::RangePair { + ln_second: (_, ln_end), + .. + } | Self::Range { ln_end, .. } | Self::LineRange(ln_end, _) | Self::Line(ln_end) => Some(*ln_end), @@ -351,6 +357,41 @@ impl ErrorCore { pub const VBAR_UNICODE: &str = "│"; pub const VBAR_BREAK_UNICODE: &str = "·"; +fn format_code_and_pointer( + e: &E, + ln_begin: usize, + ln_end: usize, + col_begin: usize, + col_end: usize, +) -> String { + let codes = if e.input() == &Input::REPL { + vec![e.input().reread()] + } else { + e.input().reread_lines(ln_begin, ln_end) + }; + let mut res = CYAN.to_string(); + let final_step = ln_end - ln_begin; + for (i, lineno) in (ln_begin..=ln_end).enumerate() { + let mut pointer = " ".repeat(lineno.to_string().len() + 2); // +2 means `| ` + if i == 0 && i == final_step { + pointer += &" ".repeat(col_begin); + pointer += &"^".repeat(cmp::max(1, col_end - col_begin)); + } else if i == 0 { + pointer += &" ".repeat(col_begin); + pointer += &"^".repeat(cmp::max(1, codes[i].len() - col_begin)); + } else if i == final_step { + pointer += &"^".repeat(col_end); + } else { + pointer += &"^".repeat(cmp::max(1, codes[i].len())); + } + res += &format!( + "{lineno}{VBAR_UNICODE} {code}\n{pointer}\n", + code = codes[i] + ); + } + res + RESET +} + /// format: /// ```console /// Error[#{.errno}]: File {file}, line {.loc (as line)}, in {.caused_by} @@ -430,13 +471,15 @@ pub trait ErrorDisplay { Location::Range { ln_begin, ln_end, .. } if ln_begin == ln_end => format!(", line {ln_begin}"), - Location::RangePair { - ln_begin, ln_end, .. - } - | Location::Range { + Location::Range { ln_begin, ln_end, .. } | Location::LineRange(ln_begin, ln_end) => format!(", line {ln_begin}..{ln_end}"), + Location::RangePair { + ln_first: (l1, l2), + ln_second: (l3, l4), + .. + } => format!(", line {l1}..{l2}, {l3}..{l4}"), Location::Line(lineno) => format!(", line {lineno}"), Location::Unknown => "".to_string(), }; @@ -454,40 +497,27 @@ pub trait ErrorDisplay { fn format_code_and_pointer(&self) -> String { match self.core().loc { - Location::RangePair { .. } => todo!(), + Location::RangePair { + ln_first, + col_first, + ln_second, + col_second, + } => { + format_code_and_pointer(self, ln_first.0, ln_first.1, col_first.0, col_first.1) + + &format_code_and_pointer( + self, + ln_second.0, + ln_second.1, + col_second.0, + col_second.1, + ) + } Location::Range { ln_begin, col_begin, ln_end, col_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(); - let final_step = ln_end - ln_begin; - for (i, lineno) in (ln_begin..=ln_end).enumerate() { - let mut pointer = " ".repeat(lineno.to_string().len() + 2); // +2 means `| ` - if i == 0 && i == final_step { - pointer += &" ".repeat(col_begin); - pointer += &"^".repeat(cmp::max(1, col_end - col_begin)); - } else if i == 0 { - pointer += &" ".repeat(col_begin); - pointer += &"^".repeat(cmp::max(1, codes[i].len() - col_begin)); - } else if i == final_step { - pointer += &"^".repeat(col_end); - } else { - pointer += &"^".repeat(cmp::max(1, codes[i].len())); - } - res += &format!( - "{lineno}{VBAR_UNICODE} {code}\n{pointer}\n", - code = codes[i] - ); - } - res + RESET - } + } => format_code_and_pointer(self, ln_begin, ln_end, col_begin, col_end), Location::LineRange(ln_begin, ln_end) => { let codes = if self.input() == &Input::REPL { vec![self.input().reread()] diff --git a/compiler/erg_common/traits.rs b/compiler/erg_common/traits.rs index d0065756..e65b2990 100644 --- a/compiler/erg_common/traits.rs +++ b/compiler/erg_common/traits.rs @@ -407,7 +407,10 @@ pub trait Locational { fn ln_begin(&self) -> Option { match self.loc() { - Location::RangePair { ln_begin, .. } + Location::RangePair { + ln_first: (ln_begin, _), + .. + } | Location::Range { ln_begin, .. } | Location::LineRange(ln_begin, _) => Some(ln_begin), Location::Line(lineno) => Some(lineno), @@ -417,7 +420,10 @@ pub trait Locational { fn ln_end(&self) -> Option { match self.loc() { - Location::RangePair { ln_end, .. } + Location::RangePair { + ln_second: (_, ln_end), + .. + } | Location::Range { ln_end, .. } | Location::LineRange(_, ln_end) => Some(ln_end), Location::Line(lineno) => Some(lineno), From 4f6972581177342488be832e73b80f376e8ebecf Mon Sep 17 00:00:00 2001 From: Shunsuke Shibayama Date: Fri, 9 Sep 2022 13:28:35 +0900 Subject: [PATCH 53/68] Impl var_args code generating --- compiler/erg_common/opcode.rs | 6 ++ compiler/erg_compiler/codegen.rs | 153 ++++++++++++++++++++++--------- compiler/erg_compiler/hir.rs | 21 +++-- compiler/erg_compiler/lower.rs | 10 +- compiler/erg_parser/ast.rs | 22 ++--- 5 files changed, 146 insertions(+), 66 deletions(-) diff --git a/compiler/erg_common/opcode.rs b/compiler/erg_common/opcode.rs index 53fdcbfc..61d66882 100644 --- a/compiler/erg_common/opcode.rs +++ b/compiler/erg_common/opcode.rs @@ -63,6 +63,7 @@ pub enum Opcode { PRINT_EXPR = 70, LOAD_BUILD_CLASS = 71, LOAD_ASSERTION_ERROR = 74, + LIST_TO_TUPLE = 82, RETURN_VALUE = 83, /* ↓ These opcodes take an arg */ STORE_NAME = 90, @@ -101,8 +102,10 @@ pub enum Opcode { LOAD_DEREF = 136, STORE_DEREF = 137, CALL_FUNCTION_KW = 141, + CALL_FUNCTION_EX = 142, LOAD_METHOD = 160, CALL_METHOD = 161, + LIST_EXTEND = 162, // Erg-specific opcodes (must have a unary `ERG_`) // Define in descending order from 219, 255 ERG_POP_NTH = 196, @@ -205,6 +208,7 @@ impl From for Opcode { 70 => PRINT_EXPR, 71 => LOAD_BUILD_CLASS, 74 => LOAD_ASSERTION_ERROR, + 82 => LIST_TO_TUPLE, 83 => RETURN_VALUE, /* ↓ These opcodes take an arg */ 90 => STORE_NAME, @@ -243,8 +247,10 @@ impl From for Opcode { 136 => LOAD_DEREF, 137 => STORE_DEREF, 141 => CALL_FUNCTION_KW, + 142 => CALL_FUNCTION_EX, 160 => LOAD_METHOD, 161 => CALL_METHOD, + 162 => LIST_EXTEND, // Erg-specific opcodes 196 => ERG_POP_NTH, 197 => ERG_PEEK_NTH, diff --git a/compiler/erg_compiler/codegen.rs b/compiler/erg_compiler/codegen.rs index b17b2720..79bd84eb 100644 --- a/compiler/erg_compiler/codegen.rs +++ b/compiler/erg_compiler/codegen.rs @@ -32,8 +32,8 @@ use crate::error::{CompileError, CompileErrors, CompileResult}; use crate::hir::AttrDef; use crate::hir::Attribute; use crate::hir::{ - Accessor, Args, Array, Block, Call, ClassDef, Def, DefBody, Expr, Literal, Local, Signature, - SubrSignature, Tuple, VarSignature, HIR, + Accessor, Args, Array, Block, Call, ClassDef, Def, DefBody, Expr, Literal, Local, PosArg, + Signature, SubrSignature, Tuple, VarSignature, HIR, }; use AccessKind::*; @@ -446,7 +446,7 @@ impl CodeGenerator { self.stack_inc(); } - fn local_search(&self, name: &str, acc_kind: AccessKind) -> Option { + fn local_search(&self, name: &str, _acc_kind: AccessKind) -> Option { let current_is_toplevel = self.cur_block() == self.toplevel_block(); if let Some(idx) = self .cur_block_codeobj() @@ -454,11 +454,7 @@ impl CodeGenerator { .iter() .position(|n| &**n == name) { - if current_is_toplevel || !acc_kind.is_local() { - Some(Name::local(idx)) - } else { - Some(Name::global(idx)) - } + Some(Name::local(idx)) } else if let Some(idx) = self .cur_block_codeobj() .varnames @@ -667,6 +663,8 @@ impl CodeGenerator { } } + /// Ergの文法として、属性への代入は存在しない(必ずオブジェクトはすべての属性を初期化しなくてはならないため) + /// この関数はPythonへ落とし込むときに使う fn store_acc(&mut self, acc: Accessor) { log!(info "entered {} ({acc})", fn_name!()); match acc { @@ -719,6 +717,11 @@ impl CodeGenerator { .non_defaults .iter() .map(|p| p.inspect().map(|s| &s[..]).unwrap_or("_")) + .chain(if let Some(var_args) = ¶ms.var_args { + vec![var_args.inspect().map(|s| &s[..]).unwrap_or("_")] + } else { + vec![] + }) .chain( params .defaults @@ -783,7 +786,7 @@ impl CodeGenerator { self.emit_store_instr(sig.ident, Name); } - fn emit_subr_def(&mut self, sig: SubrSignature, body: DefBody) { + fn emit_subr_def(&mut self, class_name: Option<&str>, sig: SubrSignature, body: DefBody) { log!(info "entered {} ({sig} = {})", fn_name!(), body.block); let name = sig.ident.inspect().clone(); let mut opcode_flag = 0u8; @@ -800,7 +803,11 @@ impl CodeGenerator { self.write_arg(cellvars_len); opcode_flag += 8; } - self.emit_load_const(name.clone()); + if let Some(class) = class_name { + self.emit_load_const(Str::from(format!("{class}.{name}"))); + } else { + self.emit_load_const(name); + } self.write_instr(MAKE_FUNCTION); self.write_arg(opcode_flag); // stack_dec: + -> @@ -989,12 +996,15 @@ impl CodeGenerator { Expr::Accessor(Accessor::Local(local)) => { self.emit_call_local(local, call.args).unwrap() } - other => todo!("calling {other}"), + other => { + self.codegen_expr(other); + self.emit_args(call.args); + } } } } - fn emit_call_local(&mut self, local: Local, mut args: Args) -> CompileResult<()> { + fn emit_call_local(&mut self, local: Local, args: Args) -> CompileResult<()> { log!(info "entered {}", fn_name!()); match &local.inspect()[..] { "assert" => self.emit_assert_instr(args), @@ -1008,33 +1018,13 @@ impl CodeGenerator { self.emit_load_name_instr(ident).unwrap_or_else(|e| { self.errs.push(e); }); - let argc = args.len(); - let mut kws = Vec::with_capacity(args.kw_len()); - while let Some(arg) = args.try_remove_pos(0) { - self.codegen_expr(arg.expr); - } - while let Some(arg) = args.try_remove_kw(0) { - kws.push(ValueObj::Str(arg.keyword.content.clone())); - self.codegen_expr(arg.expr); - } - let kwsc = if !kws.is_empty() { - let kws_tuple = ValueObj::from(kws); - self.emit_load_const(kws_tuple); - self.write_instr(CALL_FUNCTION_KW); - 1 - } else { - self.write_instr(CALL_FUNCTION); - 0 - }; - self.write_arg(argc as u8); - // (1 (subroutine) + argc + kwsc) input objects -> 1 return object - self.stack_dec_n((1 + argc + kwsc) - 1); + self.emit_args(args); Ok(()) } } } - fn emit_call_method(&mut self, obj: Expr, method_name: Token, mut args: Args) { + fn emit_call_method(&mut self, obj: Expr, method_name: Token, args: Args) { log!(info "entered {}", fn_name!()); if &method_name.inspect()[..] == "update!" { return self.emit_call_update(obj, args); @@ -1050,11 +1040,29 @@ impl CodeGenerator { .unwrap_or_else(|err| { self.errs.push(err); }); + self.emit_args(args); + } + + fn emit_args(&mut self, mut args: Args) { let argc = args.len(); + let pos_len = args.pos_args.len(); let mut kws = Vec::with_capacity(args.kw_len()); while let Some(arg) = args.try_remove_pos(0) { self.codegen_expr(arg.expr); } + if let Some(var_args) = &args.var_args { + if pos_len > 0 { + self.write_instr(Opcode::BUILD_LIST); + self.write_arg(pos_len as u8); + } + self.codegen_expr(var_args.expr.clone()); + if pos_len > 0 { + self.write_instr(Opcode::LIST_EXTEND); + self.write_arg(1); + self.write_instr(Opcode::LIST_TO_TUPLE); + self.write_arg(0); + } + } while let Some(arg) = args.try_remove_kw(0) { kws.push(ValueObj::Str(arg.keyword.content.clone())); self.codegen_expr(arg.expr); @@ -1063,13 +1071,23 @@ impl CodeGenerator { let kws_tuple = ValueObj::from(kws); self.emit_load_const(kws_tuple); self.write_instr(CALL_FUNCTION_KW); + self.write_arg(argc as u8); 1 } else { - self.write_instr(CALL_METHOD); + if args.var_args.is_some() { + self.write_instr(CALL_FUNCTION_EX); + if kws.is_empty() { + self.write_arg(0); + } else { + self.write_arg(1); + } + } else { + self.write_instr(CALL_FUNCTION); + self.write_arg(argc as u8); + } 0 }; - self.write_arg(argc as u8); - // (1 (method) + argc + kwsc) input objects -> 1 return object + // (1 (subroutine) + argc + kwsc) input objects -> 1 return object self.stack_dec_n((1 + argc + kwsc) - 1); } @@ -1149,7 +1167,7 @@ impl CodeGenerator { } Expr::Accessor(acc) => self.codegen_acc(acc), Expr::Def(def) => match def.sig { - Signature::Subr(sig) => self.emit_subr_def(sig, def.body), + Signature::Subr(sig) => self.emit_subr_def(None, sig, def.body), Signature::Var(sig) => self.emit_var_def(sig, def.body), }, Expr::ClassDef(class) => self.emit_class_def(class), @@ -1420,14 +1438,17 @@ impl CodeGenerator { let mod_name = self.toplevel_block_codeobj().name.clone(); self.emit_load_const(mod_name); self.emit_store_instr(Identifier::public("__module__"), Name); - self.emit_load_const(name); + self.emit_load_const(name.clone()); self.emit_store_instr(Identifier::public("__qualname__"), Name); + self.emit_init_method(&class.sig, class.__new__.clone()); if class.need_to_gen_new { - self.emit_auto_new(&class.sig, class.__new__); + self.emit_new_func(&class.sig, class.__new__); } - // TODO: サブルーチンはT.subという書式でSTORE for def in class.private_methods.into_iter() { - self.codegen_expr(Expr::Def(def)); + match def.sig { + Signature::Subr(sig) => self.emit_subr_def(Some(&name[..]), sig, def.body), + Signature::Var(sig) => self.emit_var_def(sig, def.body), + } // TODO: discard if self.cur_block().stack_len == 1 { self.emit_pop_top(); @@ -1435,7 +1456,10 @@ impl CodeGenerator { } for mut def in class.public_methods.into_iter() { def.sig.ident_mut().dot = Some(Token::dummy()); - self.codegen_expr(Expr::Def(def)); + match def.sig { + Signature::Subr(sig) => self.emit_subr_def(Some(&name[..]), sig, def.body), + Signature::Var(sig) => self.emit_var_def(sig, def.body), + } // TODO: discard if self.cur_block().stack_len == 1 { self.emit_pop_top(); @@ -1474,7 +1498,7 @@ impl CodeGenerator { unit.codeobj } - fn emit_auto_new(&mut self, sig: &Signature, __new__: Type) { + fn emit_init_method(&mut self, sig: &Signature, __new__: Type) { log!(info "entered {}", fn_name!()); let line = sig.ln_begin().unwrap(); let ident = Identifier::public_with_line(Token::dummy(), Str::ever("__init__"), line); @@ -1523,6 +1547,47 @@ impl CodeGenerator { self.codegen_expr(Expr::Def(init_def)); } + /// ```python + /// class C: + /// def new(*x): return C.__call__(*x) + /// ``` + fn emit_new_func(&mut self, sig: &Signature, __new__: Type) { + log!(info "entered {}", fn_name!()); + let class_name = sig.ident().inspect(); + let line = sig.ln_begin().unwrap(); + 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 sig = SubrSignature::new( + ident, + Params::new(vec![], Some(param), vec![], None), + __new__.clone(), + ); + let var_args = PosArg::new(Expr::Accessor(Accessor::local( + Token::symbol_with_line(¶m_name[..], line), + Type::Failure, + ))); + let class = Expr::Accessor(Accessor::local( + Token::symbol_with_line(class_name, line), + Type::Failure, + )); + let class_new = Expr::Accessor(Accessor::attr( + class, + Token::symbol_with_line("__new__", line), + Type::Failure, + )); + let call = Expr::Call(Call::new( + class_new, + None, + Args::new(vec![], Some(var_args), vec![], None), + Type::Failure, + )); + let block = Block::new(vec![call]); + let body = DefBody::new(Token::dummy(), block, DefId(0)); + self.emit_subr_def(Some(&class_name[..]), sig, body); + } + fn codegen_block(&mut self, block: Block, opt_name: Option, params: Vec) -> CodeObj { log!(info "entered {}", fn_name!()); self.unit_size += 1; diff --git a/compiler/erg_compiler/hir.rs b/compiler/erg_compiler/hir.rs index cc289072..80305a0a 100644 --- a/compiler/erg_compiler/hir.rs +++ b/compiler/erg_compiler/hir.rs @@ -119,6 +119,7 @@ impl KwArg { #[derive(Debug, Clone)] pub struct Args { pub pos_args: Vec, + pub var_args: Option>, pub kw_args: Vec, paren: Option<(Token, Token)>, } @@ -128,6 +129,10 @@ impl NestedDisplay for Args { if !self.pos_args.is_empty() { fmt_lines(self.pos_args.iter(), f, level)?; } + if let Some(var_args) = &self.var_args { + writeln!(f, "...")?; + var_args.fmt_nest(f, level)?; + } if !self.kw_args.is_empty() { fmt_lines(self.kw_args.iter(), f, level)?; } @@ -139,6 +144,7 @@ impl From> for Args { fn from(exprs: Vec) -> Self { Self { pos_args: exprs.into_iter().map(PosArg::new).collect(), + var_args: None, kw_args: Vec::new(), paren: None, } @@ -167,30 +173,33 @@ impl Locational for Args { // impl_stream!(Args, KwArg, kw_args); impl Args { - pub const fn new( + pub fn new( pos_args: Vec, + var_args: Option, kw_args: Vec, paren: Option<(Token, Token)>, ) -> Self { Self { pos_args, + var_args: var_args.map(Box::new), kw_args, paren, } } - pub const fn empty() -> Self { - Self::new(vec![], vec![], None) + pub fn empty() -> Self { + Self::new(vec![], None, vec![], None) } #[inline] pub fn len(&self) -> usize { - self.pos_args.len() + self.kw_args.len() + let var_argc = if self.var_args.is_none() { 0 } else { 1 }; + self.pos_args.len() + var_argc + self.kw_args.len() } #[inline] pub fn is_empty(&self) -> bool { - self.pos_args.is_empty() && self.kw_args.is_empty() + self.pos_args.is_empty() && self.var_args.is_none() && self.kw_args.is_empty() } #[inline] @@ -1338,7 +1347,7 @@ pub struct ClassDef { pub kind: TypeKind, pub sig: Signature, pub require_or_sup: Box, - /// The type of `new` and `__new__` that is automatically defined if not defined + /// The type of `new` that is automatically defined if not defined pub need_to_gen_new: bool, pub __new__: Type, pub private_methods: RecordAttrs, diff --git a/compiler/erg_compiler/lower.rs b/compiler/erg_compiler/lower.rs index a6fd08e2..b36ae4ee 100644 --- a/compiler/erg_compiler/lower.rs +++ b/compiler/erg_compiler/lower.rs @@ -330,6 +330,7 @@ impl ASTLowerer { let (pos_args, kw_args, paren) = call.args.deconstruct(); let mut hir_args = hir::Args::new( Vec::with_capacity(pos_args.len()), + None, Vec::with_capacity(kw_args.len()), paren, ); @@ -368,7 +369,7 @@ impl ASTLowerer { &[], &self.ctx.name, )?; - let args = hir::Args::new(args, vec![], None); + let args = hir::Args::new(args, None, vec![], None); Ok(hir::Call::new(class, Some(method_name), args, sig_t)) } @@ -612,8 +613,11 @@ impl ASTLowerer { .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) + let (__new__, need_to_gen_new) = if let (Some(dunder_new_vi), Some(new_vi)) = ( + ctx.get_current_scope_var("__new__"), + ctx.get_current_scope_var("new"), + ) { + (dunder_new_vi.t.clone(), new_vi.kind == VarKind::Auto) } else { todo!() }; diff --git a/compiler/erg_parser/ast.rs b/compiler/erg_parser/ast.rs index 4bc36505..db3312d8 100644 --- a/compiler/erg_parser/ast.rs +++ b/compiler/erg_parser/ast.rs @@ -2236,9 +2236,6 @@ pub enum ParamPattern { // DataPack(ParamDataPackPattern), Ref(VarName), RefMut(VarName), - // e.g. `a` of `[...a, b] = [1, 2, 3]` (a == [1, 2], b == 3) - // `b` of `[a, ...b] = [1, 2, 3]` (a == 1, b == [2, 3]) - VarArgs(VarName), } impl NestedDisplay for ParamPattern { @@ -2252,20 +2249,17 @@ impl NestedDisplay for ParamPattern { Self::Record(record) => write!(f, "{}", record), Self::Ref(var_name) => write!(f, "ref {}", var_name), Self::RefMut(var_name) => write!(f, "ref! {}", var_name), - Self::VarArgs(var_name) => write!(f, "...{}", var_name), } } } impl_display_from_nested!(ParamPattern); -impl_locational_for_enum!(ParamPattern; Discard, VarName, Lit, Array, Tuple, Record, Ref, RefMut, VarArgs); +impl_locational_for_enum!(ParamPattern; Discard, VarName, Lit, Array, Tuple, Record, Ref, RefMut); impl ParamPattern { pub const fn inspect(&self) -> Option<&Str> { match self { - Self::VarName(n) | Self::VarArgs(n) | Self::Ref(n) | Self::RefMut(n) => { - Some(n.inspect()) - } + Self::VarName(n) | Self::Ref(n) | Self::RefMut(n) => Some(n.inspect()), _ => None, } } @@ -2277,9 +2271,7 @@ impl ParamPattern { pub fn is_procedural(&self) -> bool { match self { Self::Discard(_) => true, - Self::VarName(n) | Self::VarArgs(n) | Self::Ref(n) | Self::RefMut(n) => { - n.is_procedural() - } + Self::VarName(n) | Self::Ref(n) | Self::RefMut(n) => n.is_procedural(), _ => false, } } @@ -2287,7 +2279,7 @@ impl ParamPattern { pub fn is_const(&self) -> bool { match self { Self::Discard(_) => true, - Self::VarName(n) | Self::VarArgs(n) | Self::Ref(n) | Self::RefMut(n) => n.is_const(), + Self::VarName(n) | Self::Ref(n) | Self::RefMut(n) => n.is_const(), _ => false, } } @@ -2381,7 +2373,11 @@ impl Locational for Params { } 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 { - Location::concat(var_args.as_ref(), self.defaults.last().unwrap()) + 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 { From c11ea3e892c0a40aea5f5c0948d1cfb9895aa126 Mon Sep 17 00:00:00 2001 From: Shunsuke Shibayama Date: Fri, 9 Sep 2022 14:18:03 +0900 Subject: [PATCH 54/68] Fix a method calling bug --- compiler/erg_compiler/codegen.rs | 33 ++++++++++++++++++-------------- examples/class.er | 9 ++++++--- 2 files changed, 25 insertions(+), 17 deletions(-) diff --git a/compiler/erg_compiler/codegen.rs b/compiler/erg_compiler/codegen.rs index 79bd84eb..f86b82cb 100644 --- a/compiler/erg_compiler/codegen.rs +++ b/compiler/erg_compiler/codegen.rs @@ -32,8 +32,8 @@ use crate::error::{CompileError, CompileErrors, CompileResult}; use crate::hir::AttrDef; use crate::hir::Attribute; use crate::hir::{ - Accessor, Args, Array, Block, Call, ClassDef, Def, DefBody, Expr, Literal, Local, PosArg, - Signature, SubrSignature, Tuple, VarSignature, HIR, + Accessor, Args, Array, Block, Call, ClassDef, DefBody, Expr, Literal, Local, PosArg, Signature, + SubrSignature, Tuple, VarSignature, HIR, }; use AccessKind::*; @@ -998,7 +998,7 @@ impl CodeGenerator { } other => { self.codegen_expr(other); - self.emit_args(call.args); + self.emit_args(call.args, Name); } } } @@ -1018,7 +1018,7 @@ impl CodeGenerator { self.emit_load_name_instr(ident).unwrap_or_else(|e| { self.errs.push(e); }); - self.emit_args(args); + self.emit_args(args, Name); Ok(()) } } @@ -1040,10 +1040,10 @@ impl CodeGenerator { .unwrap_or_else(|err| { self.errs.push(err); }); - self.emit_args(args); + self.emit_args(args, Method); } - fn emit_args(&mut self, mut args: Args) { + fn emit_args(&mut self, mut args: Args, kind: AccessKind) { let argc = args.len(); let pos_len = args.pos_args.len(); let mut kws = Vec::with_capacity(args.kw_len()); @@ -1082,7 +1082,11 @@ impl CodeGenerator { self.write_arg(1); } } else { - self.write_instr(CALL_FUNCTION); + if kind.is_method() { + self.write_instr(CALL_METHOD); + } else { + self.write_instr(CALL_FUNCTION); + } self.write_arg(argc as u8); } 0 @@ -1501,6 +1505,7 @@ impl CodeGenerator { fn emit_init_method(&mut self, sig: &Signature, __new__: Type) { log!(info "entered {}", fn_name!()); let line = sig.ln_begin().unwrap(); + let class_name = sig.ident().inspect(); 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); @@ -1508,7 +1513,7 @@ impl CodeGenerator { let self_param = VarName::from_str_and_line(Str::ever("self"), line); let self_param = ParamSignature::new(ParamPattern::VarName(self_param), None, None); let params = Params::new(vec![self_param, param], None, vec![], None); - let sig = Signature::Subr(SubrSignature::new(ident, params.clone(), __new__.clone())); + let subr_sig = SubrSignature::new(ident, params.clone(), __new__.clone()); let mut attrs = vec![]; match __new__.non_default_params().unwrap()[0].typ() { // {x = Int; y = Int} @@ -1543,13 +1548,13 @@ impl CodeGenerator { } let block = Block::new(attrs); let body = DefBody::new(Token::dummy(), block, DefId(0)); - let init_def = Def::new(sig, body.clone()); - self.codegen_expr(Expr::Def(init_def)); + self.emit_subr_def(Some(class_name), subr_sig, body); } /// ```python /// class C: - /// def new(*x): return C.__call__(*x) + /// # __new__ => __call__ + /// def new(x): return C.__call__(x) /// ``` fn emit_new_func(&mut self, sig: &Signature, __new__: Type) { log!(info "entered {}", fn_name!()); @@ -1561,10 +1566,10 @@ impl CodeGenerator { let param = ParamSignature::new(ParamPattern::VarName(param), None, None); let sig = SubrSignature::new( ident, - Params::new(vec![], Some(param), vec![], None), + Params::new(vec![param], None, vec![], None), __new__.clone(), ); - let var_args = PosArg::new(Expr::Accessor(Accessor::local( + let arg = PosArg::new(Expr::Accessor(Accessor::local( Token::symbol_with_line(¶m_name[..], line), Type::Failure, ))); @@ -1580,7 +1585,7 @@ impl CodeGenerator { let call = Expr::Call(Call::new( class_new, None, - Args::new(vec![], Some(var_args), vec![], None), + Args::new(vec![arg], None, vec![], None), Type::Failure, )); let block = Block::new(vec![call]); diff --git a/examples/class.er b/examples/class.er index 7b49dd21..8320aaab 100644 --- a/examples/class.er +++ b/examples/class.er @@ -7,9 +7,12 @@ Point3D = Inherit Point2D, Additional := {z = Int} Point3D. # Overloading is prohibited by default. Remove this decorator and check for errors. @Override - new x, y, z = Point3D::__new__ {x; y; z} + new x, y, z = + Point3D::__new__ {x; y; z} @Override norm self = self::x**2 + self::y**2 + self::z**2 -p = Point3D.new {x = 1; y = 2; z = 3} -print! p.norm() +p = Point2D.new {x = 1; y = 2} +print! p, p.norm() +q = Point3D.new 1, 2, 3 +print! q, q.norm() From 87b55c6c81bc5d941c15134550deaff562a416c0 Mon Sep 17 00:00:00 2001 From: Shunsuke Shibayama Date: Fri, 9 Sep 2022 14:21:48 +0900 Subject: [PATCH 55/68] Update version (v0.4.0-beta.1) --- Cargo.lock | 10 +++++----- Cargo.toml | 10 +++++----- compiler/erg_common/Cargo.toml | 2 +- compiler/erg_compiler/Cargo.toml | 8 ++++---- compiler/erg_parser/Cargo.toml | 4 ++-- compiler/erg_type/Cargo.toml | 4 ++-- 6 files changed, 19 insertions(+), 19 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ca2d039a..6a94ef02 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -15,7 +15,7 @@ dependencies = [ [[package]] name = "erg" -version = "0.4.0-beta.0" +version = "0.4.0-beta.1" dependencies = [ "erg_common", "erg_compiler", @@ -25,14 +25,14 @@ dependencies = [ [[package]] name = "erg_common" -version = "0.4.0-beta.0" +version = "0.4.0-beta.1" dependencies = [ "atty", ] [[package]] name = "erg_compiler" -version = "0.4.0-beta.0" +version = "0.4.0-beta.1" dependencies = [ "erg_common", "erg_parser", @@ -41,14 +41,14 @@ dependencies = [ [[package]] name = "erg_parser" -version = "0.4.0-beta.0" +version = "0.4.0-beta.1" dependencies = [ "erg_common", ] [[package]] name = "erg_type" -version = "0.4.0-beta.0" +version = "0.4.0-beta.1" dependencies = [ "erg_common", ] diff --git a/Cargo.toml b/Cargo.toml index 8c7d2f70..0069e30f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "erg" -version = "0.4.0-beta.0" +version = "0.4.0-beta.1" description = "The Erg programming language" authors = ["Shunsuke Shibayama "] license = "MIT OR Apache-2.0" @@ -46,10 +46,10 @@ traditional_chinese = [ ] [dependencies] -erg_common = { version = "0.4.0-beta.0", path = "./compiler/erg_common" } -erg_parser = { version = "0.4.0-beta.0", path = "./compiler/erg_parser" } -erg_compiler = { version = "0.4.0-beta.0", path = "./compiler/erg_compiler" } -erg_type = { version = "0.4.0-beta.0", path = "./compiler/erg_type" } +erg_common = { version = "0.4.0-beta.1", path = "./compiler/erg_common" } +erg_parser = { version = "0.4.0-beta.1", path = "./compiler/erg_parser" } +erg_compiler = { version = "0.4.0-beta.1", path = "./compiler/erg_compiler" } +erg_type = { version = "0.4.0-beta.1", path = "./compiler/erg_type" } # [workspace] # member = ["cm", "dyne"] diff --git a/compiler/erg_common/Cargo.toml b/compiler/erg_common/Cargo.toml index 5405e3a9..f95c3f54 100644 --- a/compiler/erg_common/Cargo.toml +++ b/compiler/erg_common/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "erg_common" -version = "0.4.0-beta.0" +version = "0.4.0-beta.1" description = "A common components library of Erg" authors = ["Shunsuke Shibayama "] license = "MIT OR Apache-2.0" diff --git a/compiler/erg_compiler/Cargo.toml b/compiler/erg_compiler/Cargo.toml index 083ea9be..3f5f6a34 100644 --- a/compiler/erg_compiler/Cargo.toml +++ b/compiler/erg_compiler/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "erg_compiler" -version = "0.4.0-beta.0" +version = "0.4.0-beta.1" description = "Centimetre: the Erg compiler" authors = ["Shunsuke Shibayama "] license = "MIT OR Apache-2.0" @@ -17,9 +17,9 @@ simplified_chinese = [ "erg_common/simplified_chinese", "erg_parser/simplified_c traditional_chinese = [ "erg_common/traditional_chinese", "erg_parser/traditional_chinese", "erg_type/traditional_chinese" ] [dependencies] -erg_common = { version = "0.4.0-beta.0", path = "../erg_common" } -erg_parser = { version = "0.4.0-beta.0", path = "../erg_parser" } -erg_type = { version = "0.4.0-beta.0", path = "../erg_type" } +erg_common = { version = "0.4.0-beta.1", path = "../erg_common" } +erg_parser = { version = "0.4.0-beta.1", path = "../erg_parser" } +erg_type = { version = "0.4.0-beta.1", path = "../erg_type" } [lib] path = "lib.rs" diff --git a/compiler/erg_parser/Cargo.toml b/compiler/erg_parser/Cargo.toml index e237412f..93954535 100644 --- a/compiler/erg_parser/Cargo.toml +++ b/compiler/erg_parser/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "erg_parser" -version = "0.4.0-beta.0" +version = "0.4.0-beta.1" description = "The Erg parser" authors = ["mtshiba "] license = "MIT OR Apache-2.0" @@ -16,7 +16,7 @@ simplified_chinese = [ "erg_common/simplified_chinese" ] traditional_chinese = [ "erg_common/traditional_chinese" ] [dependencies] -erg_common = { version = "0.4.0-beta.0", path = "../erg_common" } +erg_common = { version = "0.4.0-beta.1", path = "../erg_common" } [lib] path = "lib.rs" diff --git a/compiler/erg_type/Cargo.toml b/compiler/erg_type/Cargo.toml index 80e044b2..3f9432f9 100644 --- a/compiler/erg_type/Cargo.toml +++ b/compiler/erg_type/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "erg_type" -version = "0.4.0-beta.0" +version = "0.4.0-beta.1" description = "APIs for Erg types" authors = ["Shunsuke Shibayama "] license = "MIT OR Apache-2.0" @@ -18,7 +18,7 @@ simplified_chinese = [ "erg_common/simplified_chinese" ] traditional_chinese = [ "erg_common/traditional_chinese" ] [dependencies] -erg_common = { version = "0.4.0-beta.0", path = "../erg_common" } +erg_common = { version = "0.4.0-beta.1", path = "../erg_common" } [lib] path = "lib.rs" From 25f5e85d95b033df4f0068f656669cf7c4185fa2 Mon Sep 17 00:00:00 2001 From: Shunsuke Shibayama Date: Fri, 9 Sep 2022 14:22:17 +0900 Subject: [PATCH 56/68] Update cargo_publish.bat --- cargo_publish.bat | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cargo_publish.bat b/cargo_publish.bat index c09eeaa2..ea5ac73a 100644 --- a/cargo_publish.bat +++ b/cargo_publish.bat @@ -4,7 +4,7 @@ if %~dp0 == C:%homepath%\GitHub\erg\ ( cd compiler/erg_common echo publish erg_common ... cargo publish - timeout 10 + timeout 12 cd ../erg_type echo publish erg_type ... cargo publish From 892ab6df2f05be0609cd83f9ad1c42b1d93257db Mon Sep 17 00:00:00 2001 From: Shunsuke Shibayama Date: Fri, 9 Sep 2022 15:34:34 +0900 Subject: [PATCH 57/68] Implement inheritance check --- compiler/erg_common/error.rs | 1 + .../context/initialize/const_func.rs | 16 +++++---- .../erg_compiler/context/initialize/mod.rs | 2 ++ compiler/erg_compiler/context/inquire.rs | 14 ++++---- compiler/erg_compiler/error.rs | 18 ++++++++++ compiler/erg_compiler/hir.rs | 16 +++++++++ compiler/erg_compiler/lower.rs | 33 +++++++++++++++++++ compiler/erg_type/lib.rs | 1 + compiler/erg_type/value.rs | 7 ++++ examples/class.er | 1 + 10 files changed, 94 insertions(+), 15 deletions(-) diff --git a/compiler/erg_common/error.rs b/compiler/erg_common/error.rs index 4b0df9f5..93802f0b 100644 --- a/compiler/erg_common/error.rs +++ b/compiler/erg_common/error.rs @@ -36,6 +36,7 @@ pub enum ErrorKind { HasEffect, MoveError, NotConstExpr, + InheritanceError, DummyError, /* compile warnings */ AttributeWarning = 60, diff --git a/compiler/erg_compiler/context/initialize/const_func.rs b/compiler/erg_compiler/context/initialize/const_func.rs index 863739e0..9c658b76 100644 --- a/compiler/erg_compiler/context/initialize/const_func.rs +++ b/compiler/erg_compiler/context/initialize/const_func.rs @@ -19,7 +19,7 @@ fn value_obj_to_t(value: ValueObj) -> TypeObj { } } -/// Requirement: Type, Impl := Type -> Class +/// Requirement: Type, Impl := Type -> ClassType pub fn class_func(mut args: ValueArgs, __name__: Option) -> ValueObj { let require = args.remove_left_or_key("Requirement").unwrap(); let require = value_obj_to_t(require); @@ -29,7 +29,7 @@ pub fn class_func(mut args: ValueArgs, __name__: Option) -> ValueObj { ValueObj::gen_t(TypeKind::Class, t, require, impls, None) } -/// Super: Type, Impl := Type, Additional := Type -> Class +/// Super: Type, Impl := Type, Additional := Type -> ClassType pub fn inherit_func(mut args: ValueArgs, __name__: Option) -> ValueObj { let sup = args.remove_left_or_key("Super").unwrap(); let sup = value_obj_to_t(sup); @@ -41,21 +41,23 @@ pub fn inherit_func(mut args: ValueArgs, __name__: Option) -> ValueObj { ValueObj::gen_t(TypeKind::Subclass, t, sup, impls, additional) } -/// Class -> Class (with `Inheritable`) +/// Class: ClassType -> ClassType (with `InheritableType`) /// 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 { - let class = args.pos_args.into_iter().next().unwrap(); +pub fn inheritable_func(mut args: ValueArgs, __name__: Option) -> ValueObj { + let class = args.remove_left_or_key("Class").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")); + gen.t = and(mem::take(&mut gen.t), mono("InheritableType")); } TypeObj::Builtin(t) => { - *t = and(mem::take(t), mono("Inheritable")); + *t = and(mem::take(t), mono("InheritableType")); } } + } else { + gen.impls = Some(Box::new(TypeObj::Builtin(mono("InheritableType")))); } ValueObj::Type(TypeObj::Generated(gen)) } diff --git a/compiler/erg_compiler/context/initialize/mod.rs b/compiler/erg_compiler/context/initialize/mod.rs index 919e41fe..689e30f7 100644 --- a/compiler/erg_compiler/context/initialize/mod.rs +++ b/compiler/erg_compiler/context/initialize/mod.rs @@ -165,6 +165,7 @@ impl Context { // push_subtype_boundなどはユーザー定義APIの型境界決定のために使用する fn init_builtin_traits(&mut self) { let unpack = Self::mono_trait("Unpack", vec![], Self::TOP_LEVEL); + let inheritable_type = Self::mono_trait("InheritableType", vec![], Self::TOP_LEVEL); let named = Self::mono_trait("Named", vec![], Self::TOP_LEVEL); let mut mutable = Self::mono_trait("Mutable", vec![], Self::TOP_LEVEL); let proj = mono_proj(mono_q("Self"), "ImmutType"); @@ -309,6 +310,7 @@ impl Context { div.register_builtin_decl("__div__", op_t, Public); div.register_builtin_decl("DivO", Type, Public); self.register_builtin_type(mono("Unpack"), unpack, Const); + self.register_builtin_type(mono("InheritableType"), inheritable_type, Const); self.register_builtin_type(mono("Named"), named, Const); self.register_builtin_type(mono("Mutable"), mutable, Const); self.register_builtin_type(mono("Immutizable"), immutizable, Const); diff --git a/compiler/erg_compiler/context/inquire.rs b/compiler/erg_compiler/context/inquire.rs index d0a33aed..7c0bcfec 100644 --- a/compiler/erg_compiler/context/inquire.rs +++ b/compiler/erg_compiler/context/inquire.rs @@ -1084,14 +1084,12 @@ impl Context { t: &Type, ) -> Option> { let (t, ctx) = self.rec_get_nominal_type_ctx(t)?; - Some( - vec![(t, ctx)].into_iter().chain( - ctx.super_classes - .iter() - .chain(ctx.super_traits.iter()) - .map(|sup| self.rec_get_nominal_type_ctx(&sup).unwrap()), - ), - ) + let sups = ctx + .super_classes + .iter() + .chain(ctx.super_traits.iter()) + .map(|sup| self.rec_get_nominal_type_ctx(&sup).unwrap()); + Some(vec![(t, ctx)].into_iter().chain(sups)) } pub(crate) fn rec_get_nominal_type_ctx<'a>( diff --git a/compiler/erg_compiler/error.rs b/compiler/erg_compiler/error.rs index 55544d16..01a523d6 100644 --- a/compiler/erg_compiler/error.rs +++ b/compiler/erg_compiler/error.rs @@ -1102,6 +1102,24 @@ passed keyword args: {RED}{kw_args_len}{RESET}" caused_by.into(), ) } + + pub fn inheritance_error(errno: usize, class: String, loc: Location, caused_by: Str) -> Self { + Self::new( + ErrorCore::new( + errno, + InheritanceError, + loc, + switch_lang!( + "japanese" => format!("{class}は継承できません"), + "simplified_chinese" => format!("{class}不可继承"), + "traditional_chinese" => format!("{class}不可繼承"), + "english" => format!("{class} is not inheritable"), + ), + None, + ), + caused_by, + ) + } } #[derive(Debug)] diff --git a/compiler/erg_compiler/hir.rs b/compiler/erg_compiler/hir.rs index 80305a0a..38ff98f1 100644 --- a/compiler/erg_compiler/hir.rs +++ b/compiler/erg_compiler/hir.rs @@ -268,6 +268,22 @@ impl Args { } } } + + pub fn get_left_or_key(&self, key: &str) -> Option<&Expr> { + if !self.pos_args.is_empty() { + Some(&self.pos_args.get(0)?.expr) + } else { + if let Some(pos) = self + .kw_args + .iter() + .position(|arg| &arg.keyword.inspect()[..] == key) + { + Some(&self.kw_args.get(pos)?.expr) + } else { + None + } + } + } } /// represents local variables diff --git a/compiler/erg_compiler/lower.rs b/compiler/erg_compiler/lower.rs index b36ae4ee..6abc2571 100644 --- a/compiler/erg_compiler/lower.rs +++ b/compiler/erg_compiler/lower.rs @@ -23,6 +23,34 @@ use crate::hir::HIR; use crate::varinfo::VarKind; use Visibility::*; +/// HACK: Cannot be methodized this because a reference has been taken immediately before. +macro_rules! check_inheritable { + ($self: ident, $type_obj: expr, $sup_class: expr, $sub_sig: expr) => { + match $type_obj.require_or_sup.as_ref() { + TypeObj::Generated(gen) => { + if let Some(impls) = gen.impls.as_ref() { + if !impls.contains_intersec(&mono("InheritableType")) { + $self.errs.push(LowerError::inheritance_error( + line!() as usize, + $sup_class.to_string(), + $sup_class.loc(), + $sub_sig.ident().inspect().clone(), + )); + } + } else { + $self.errs.push(LowerError::inheritance_error( + line!() as usize, + $sup_class.to_string(), + $sup_class.loc(), + $sub_sig.ident().inspect().clone(), + )); + } + } + _ => {} + } + }; +} + /// Singleton that checks types of an AST, and convert (lower) it into a HIR #[derive(Debug)] pub struct ASTLowerer { @@ -612,6 +640,11 @@ impl ASTLowerer { .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:(_))); + let sup_type = enum_unwrap!(&hir_def.body.block.first().unwrap(), hir::Expr::Call) + .args + .get_left_or_key("Super") + .unwrap(); + check_inheritable!(self, type_obj, sup_type, &hir_def.sig); // vi.t.non_default_params().unwrap()[0].typ().clone() let (__new__, need_to_gen_new) = if let (Some(dunder_new_vi), Some(new_vi)) = ( ctx.get_current_scope_var("__new__"), diff --git a/compiler/erg_type/lib.rs b/compiler/erg_type/lib.rs index c980ec8f..127fc5a4 100644 --- a/compiler/erg_type/lib.rs +++ b/compiler/erg_type/lib.rs @@ -1747,6 +1747,7 @@ impl Type { } } + /// assert!((A and B).contains_intersec(B)) pub fn contains_intersec(&self, typ: &Type) -> bool { match self { Type::And(t1, t2) => t1.contains_intersec(typ) || t2.contains_intersec(typ), diff --git a/compiler/erg_type/value.rs b/compiler/erg_type/value.rs index b5d5622f..8954e348 100644 --- a/compiler/erg_type/value.rs +++ b/compiler/erg_type/value.rs @@ -94,6 +94,13 @@ impl TypeObj { TypeObj::Generated(t) => &t.t, } } + + pub fn contains_intersec(&self, other: &Type) -> bool { + match self { + TypeObj::Builtin(t) => t.contains_intersec(other), + TypeObj::Generated(t) => t.t.contains_intersec(other), + } + } } /// 値オブジェクト diff --git a/examples/class.er b/examples/class.er index 8320aaab..7b54d73d 100644 --- a/examples/class.er +++ b/examples/class.er @@ -1,3 +1,4 @@ +# Inheritance is prohibited by default. Remove this decorator and check for errors. @Inheritable Point2D = Class {x = Int; y = Int} Point2D. From 7a682db817c5e9d5795b5759e95524cafb9ef187 Mon Sep 17 00:00:00 2001 From: Shunsuke Shibayama Date: Fri, 9 Sep 2022 16:46:36 +0900 Subject: [PATCH 58/68] method_name: Option -> Option --- compiler/erg_compiler/codegen.rs | 4 ++-- compiler/erg_compiler/context/inquire.rs | 18 +++++++++------- compiler/erg_compiler/hir.rs | 6 +++--- compiler/erg_compiler/lower.rs | 18 +++++++++++----- compiler/erg_parser/ast.rs | 8 ++++---- compiler/erg_parser/parse.rs | 26 ++++++++++++++++++++---- 6 files changed, 55 insertions(+), 25 deletions(-) diff --git a/compiler/erg_compiler/codegen.rs b/compiler/erg_compiler/codegen.rs index f86b82cb..b988aac6 100644 --- a/compiler/erg_compiler/codegen.rs +++ b/compiler/erg_compiler/codegen.rs @@ -1024,7 +1024,7 @@ impl CodeGenerator { } } - fn emit_call_method(&mut self, obj: Expr, method_name: Token, args: Args) { + fn emit_call_method(&mut self, obj: Expr, method_name: Identifier, args: Args) { log!(info "entered {}", fn_name!()); if &method_name.inspect()[..] == "update!" { return self.emit_call_update(obj, args); @@ -1035,7 +1035,7 @@ impl CodeGenerator { self.emit_load_method_instr( &class, uniq_obj_name.as_ref().map(|s| &s[..]), - method_name.content, + method_name.name.into_token().content, ) .unwrap_or_else(|err| { self.errs.push(err); diff --git a/compiler/erg_compiler/context/inquire.rs b/compiler/erg_compiler/context/inquire.rs index 7c0bcfec..e7f505ec 100644 --- a/compiler/erg_compiler/context/inquire.rs +++ b/compiler/erg_compiler/context/inquire.rs @@ -11,7 +11,7 @@ use erg_common::{enum_unwrap, fmt_option, fmt_slice, log, set}; use Type::*; use ast::VarName; -use erg_parser::ast; +use erg_parser::ast::{self, Identifier}; use erg_parser::token::Token; use erg_type::constructors::{func, mono, mono_proj, poly, ref_, ref_mut, refinement, subr_t}; @@ -332,7 +332,7 @@ impl Context { fn search_callee_t( &self, obj: &hir::Expr, - method_name: &Option, + method_name: &Option, namespace: &Str, ) -> TyCheckResult { if let Some(method_name) = method_name.as_ref() { @@ -592,7 +592,7 @@ impl Context { fn substitute_call( &self, obj: &hir::Expr, - method_name: &Option, + method_name: &Option, instance: &Type, pos_args: &[hir::PosArg], kw_args: &[hir::KwArg], @@ -605,8 +605,12 @@ impl Context { self.substitute_call(obj, method_name, &refine.t, pos_args, kw_args) } Type::Subr(subr) => { - let callee = if let Some(name) = method_name { - let attr = hir::Attribute::new(obj.clone(), name.clone(), Type::Uninited); + let callee = if let Some(ident) = method_name { + let attr = hir::Attribute::new( + obj.clone(), + ident.name.clone().into_token(), + Type::Uninited, + ); let acc = hir::Expr::Accessor(hir::Accessor::Attr(attr)); acc } else { @@ -829,7 +833,7 @@ impl Context { pub(crate) fn get_call_t( &self, obj: &hir::Expr, - method_name: &Option, + method_name: &Option, pos_args: &[hir::PosArg], kw_args: &[hir::KwArg], namespace: &Str, @@ -843,7 +847,7 @@ impl Context { let found = self.search_callee_t(obj, method_name, namespace)?; log!( "Found:\ncallee: {obj}{}\nfound: {found}", - fmt_option!(pre ".", method_name.as_ref().map(|t| &t.content)) + fmt_option!(pre ".", method_name.as_ref().map(|ident| &ident.name)) ); let instance = self.instantiate(found, obj)?; log!( diff --git a/compiler/erg_compiler/hir.rs b/compiler/erg_compiler/hir.rs index 38ff98f1..0e9515d0 100644 --- a/compiler/erg_compiler/hir.rs +++ b/compiler/erg_compiler/hir.rs @@ -937,7 +937,7 @@ impl UnaryOp { #[derive(Debug, Clone)] pub struct Call { pub obj: Box, - pub method_name: Option, + pub method_name: Option, pub args: Args, /// 全体の型(引数自体の型は関係ない)、e.g. `abs(-1)` -> `Neg -> Nat` pub sig_t: Type, @@ -949,7 +949,7 @@ impl NestedDisplay for Call { f, "({}){} (: {}):", self.obj, - fmt_option!(pre ".", self.method_name.as_ref().map(|t| t.inspect())), + fmt_option!(self.method_name), self.sig_t )?; self.args.fmt_nest(f, level + 1) @@ -992,7 +992,7 @@ impl Locational for Call { } impl Call { - pub fn new(obj: Expr, method_name: Option, args: Args, sig_t: Type) -> Self { + pub fn new(obj: Expr, method_name: Option, args: Args, sig_t: Type) -> Self { Self { obj: Box::new(obj), method_name, diff --git a/compiler/erg_compiler/lower.rs b/compiler/erg_compiler/lower.rs index 6abc2571..54ddd0e5 100644 --- a/compiler/erg_compiler/lower.rs +++ b/compiler/erg_compiler/lower.rs @@ -384,11 +384,19 @@ impl ASTLowerer { let class = self.lower_expr(*pack.class)?; let args = self.lower_record(pack.args)?; let args = vec![hir::PosArg::new(hir::Expr::Record(args))]; - let method_name = Token::new( - TokenKind::Symbol, - Str::rc("new"), - pack.connector.lineno, - pack.connector.col_begin, + let method_name = ast::Identifier::new( + Some(Token::new( + TokenKind::Dot, + Str::ever("."), + pack.connector.lineno, + pack.connector.col_begin, + )), + ast::VarName::new(Token::new( + TokenKind::Symbol, + Str::ever("new"), + pack.connector.lineno, + pack.connector.col_begin, + )), ); let sig_t = self.ctx.get_call_t( &class, diff --git a/compiler/erg_parser/ast.rs b/compiler/erg_parser/ast.rs index db3312d8..172e089a 100644 --- a/compiler/erg_parser/ast.rs +++ b/compiler/erg_parser/ast.rs @@ -856,7 +856,7 @@ impl UnaryOp { #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub struct Call { pub obj: Box, - pub method_name: Option, + pub method_name: Option, pub args: Args, } @@ -864,7 +864,7 @@ impl NestedDisplay for Call { fn fmt_nest(&self, f: &mut std::fmt::Formatter<'_>, level: usize) -> std::fmt::Result { write!(f, "({})", self.obj)?; if let Some(method_name) = self.method_name.as_ref() { - write!(f, ".{}", method_name.content)?; + write!(f, "{}", method_name)?; } writeln!(f, ":")?; self.args.fmt_nest(f, level + 1) @@ -884,7 +884,7 @@ impl Locational for Call { } impl Call { - pub fn new(obj: Expr, method_name: Option, args: Args) -> Self { + pub fn new(obj: Expr, method_name: Option, args: Args) -> Self { Self { obj: Box::new(obj), method_name, @@ -1777,7 +1777,7 @@ impl fmt::Display for Identifier { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match &self.dot { Some(_dot) => write!(f, ".{}", self.name), - None => write!(f, "{}", self.name), + None => write!(f, "::{}", self.name), } } } diff --git a/compiler/erg_parser/parse.rs b/compiler/erg_parser/parse.rs index 7d915f66..2ae1b79d 100644 --- a/compiler/erg_parser/parse.rs +++ b/compiler/erg_parser/parse.rs @@ -980,7 +980,8 @@ impl Parser { .transpose() .map_err(|_| self.stack_dec())? { - let call = Call::new(obj, Some(symbol), args); + let ident = Identifier::new(None, VarName::new(symbol)); + let call = Call::new(obj, Some(ident), args); stack.push(ExprOrOp::Expr(Expr::Call(call))); } else { let acc = Accessor::attr(obj, vis, Local::new(symbol)); @@ -1038,7 +1039,8 @@ impl Parser { .transpose() .map_err(|_| self.stack_dec())? { - let call = Call::new(obj, Some(symbol), args); + let ident = Identifier::new(Some(vis), VarName::new(symbol)); + let call = Call::new(obj, Some(ident), args); stack.push(ExprOrOp::Expr(Expr::Call(call))); } else { let acc = Accessor::attr(obj, vis, Local::new(symbol)); @@ -1192,7 +1194,8 @@ impl Parser { .transpose() .map_err(|_| self.stack_dec())? { - let call = Call::new(obj, Some(symbol), args); + let ident = Identifier::new(Some(vis), VarName::new(symbol)); + let call = Call::new(obj, Some(ident), args); stack.push(ExprOrOp::Expr(Expr::Call(call))); } else { let acc = Accessor::attr(obj, vis, Local::new(symbol)); @@ -1382,7 +1385,22 @@ impl Parser { if let Some(res) = self.opt_reduce_args() { let args = res.map_err(|_| self.stack_dec())?; let (obj, method_name) = match acc { - Accessor::Attr(attr) => (*attr.obj, Some(attr.name.symbol)), + Accessor::Attr(attr) => { + if attr.vis.is(Dot) { + ( + *attr.obj, + Some(Identifier::new( + Some(attr.vis), + VarName::new(attr.name.symbol), + )), + ) + } else { + ( + *attr.obj, + Some(Identifier::new(None, VarName::new(attr.name.symbol))), + ) + } + } Accessor::Local(local) => (Expr::Accessor(Accessor::Local(local)), None), _ => todo!(), }; From 75f3444eb742fcdc9a8532aa7112aef4eb5a4203 Mon Sep 17 00:00:00 2001 From: Shunsuke Shibayama Date: Fri, 9 Sep 2022 17:08:05 +0900 Subject: [PATCH 59/68] WIP: impl visibility validation --- compiler/erg_compiler/context/inquire.rs | 50 ++++++++++++++++++------ compiler/erg_compiler/lower.rs | 11 +++++- compiler/erg_parser/ast.rs | 13 ++++++ 3 files changed, 60 insertions(+), 14 deletions(-) diff --git a/compiler/erg_compiler/context/inquire.rs b/compiler/erg_compiler/context/inquire.rs index e7f505ec..1d5fb115 100644 --- a/compiler/erg_compiler/context/inquire.rs +++ b/compiler/erg_compiler/context/inquire.rs @@ -340,29 +340,41 @@ impl Context { .rec_get_nominal_super_type_ctxs(obj.ref_t()) .ok_or_else(|| todo!())? { - if let Some(vi) = ctx.locals.get(method_name.inspect()) { - return Ok(vi.t()); - } else if let Some(vi) = ctx.decls.get(method_name.inspect()) { + if let Some(vi) = ctx + .locals + .get(method_name.inspect()) + .or_else(|| ctx.decls.get(method_name.inspect())) + { + self.validate_visibility(method_name, vi)?; return Ok(vi.t()); } for (_, methods_ctx) in ctx.method_defs.iter() { - if let Some(vi) = methods_ctx.locals.get(method_name.inspect()) { - return Ok(vi.t()); - } else if let Some(vi) = methods_ctx.decls.get(method_name.inspect()) { + if let Some(vi) = methods_ctx + .locals + .get(method_name.inspect()) + .or_else(|| methods_ctx.decls.get(method_name.inspect())) + { + self.validate_visibility(method_name, vi)?; return Ok(vi.t()); } } } if let Some(singular_ctx) = self.rec_get_singular_ctx(obj) { - if let Some(vi) = singular_ctx.locals.get(method_name.inspect()) { - return Ok(vi.t()); - } else if let Some(vi) = singular_ctx.decls.get(method_name.inspect()) { + if let Some(vi) = singular_ctx + .locals + .get(method_name.inspect()) + .or_else(|| singular_ctx.decls.get(method_name.inspect())) + { + self.validate_visibility(method_name, vi)?; return Ok(vi.t()); } for (_, method_ctx) in singular_ctx.method_defs.iter() { - if let Some(vi) = method_ctx.locals.get(method_name.inspect()) { - return Ok(vi.t()); - } else if let Some(vi) = method_ctx.decls.get(method_name.inspect()) { + if let Some(vi) = method_ctx + .locals + .get(method_name.inspect()) + .or_else(|| method_ctx.decls.get(method_name.inspect())) + { + self.validate_visibility(method_name, vi)?; return Ok(vi.t()); } } @@ -390,6 +402,20 @@ impl Context { } } + fn validate_visibility(&self, ident: &Identifier, vi: &VarInfo) -> TyCheckResult<()> { + if ident.vis() != vi.vis { + Err(TyCheckError::visibility_error( + line!() as usize, + ident.loc(), + self.caused_by(), + ident.inspect(), + vi.vis, + )) + } else { + Ok(()) + } + } + pub(crate) fn get_binop_t( &self, op: &Token, diff --git a/compiler/erg_compiler/lower.rs b/compiler/erg_compiler/lower.rs index 54ddd0e5..7d81d50c 100644 --- a/compiler/erg_compiler/lower.rs +++ b/compiler/erg_compiler/lower.rs @@ -598,11 +598,18 @@ impl ASTLowerer { for def in methods.defs.iter() { self.ctx.preregister_def(def)?; } - for def in methods.defs.into_iter() { - let def = self.lower_def(def)?; + for mut def in methods.defs.into_iter() { if methods.vis.is(TokenKind::Dot) { + def.sig.ident_mut().unwrap().dot = Some(Token::new( + TokenKind::Dot, + ".", + def.sig.ln_begin().unwrap(), + def.sig.col_begin().unwrap(), + )); + let def = self.lower_def(def)?; public_methods.push(def); } else { + let def = self.lower_def(def)?; private_methods.push(def); } } diff --git a/compiler/erg_parser/ast.rs b/compiler/erg_parser/ast.rs index 172e089a..89286408 100644 --- a/compiler/erg_parser/ast.rs +++ b/compiler/erg_parser/ast.rs @@ -2628,6 +2628,19 @@ impl Signature { } } + pub fn ident_mut(&mut self) -> Option<&mut Identifier> { + match self { + Self::Var(var) => { + if let VarPattern::Ident(ident) = &mut var.pat { + Some(ident) + } else { + None + } + } + Self::Subr(subr) => Some(&mut subr.ident), + } + } + pub fn t_spec(&self) -> Option<&TypeSpec> { match self { Self::Var(v) => v.t_spec.as_ref(), From b50c914870d2f75254923af351f92f22b6b6710c Mon Sep 17 00:00:00 2001 From: Shunsuke Shibayama Date: Fri, 9 Sep 2022 17:30:46 +0900 Subject: [PATCH 60/68] Fix accessing to private methods bug --- compiler/erg_compiler/context/inquire.rs | 31 ++++++++++++++++++++---- 1 file changed, 26 insertions(+), 5 deletions(-) diff --git a/compiler/erg_compiler/context/inquire.rs b/compiler/erg_compiler/context/inquire.rs index 1d5fb115..8122bc9a 100644 --- a/compiler/erg_compiler/context/inquire.rs +++ b/compiler/erg_compiler/context/inquire.rs @@ -345,7 +345,7 @@ impl Context { .get(method_name.inspect()) .or_else(|| ctx.decls.get(method_name.inspect())) { - self.validate_visibility(method_name, vi)?; + self.validate_visibility(method_name, vi, ctx)?; return Ok(vi.t()); } for (_, methods_ctx) in ctx.method_defs.iter() { @@ -354,7 +354,7 @@ impl Context { .get(method_name.inspect()) .or_else(|| methods_ctx.decls.get(method_name.inspect())) { - self.validate_visibility(method_name, vi)?; + self.validate_visibility(method_name, vi, ctx)?; return Ok(vi.t()); } } @@ -365,7 +365,7 @@ impl Context { .get(method_name.inspect()) .or_else(|| singular_ctx.decls.get(method_name.inspect())) { - self.validate_visibility(method_name, vi)?; + self.validate_visibility(method_name, vi, singular_ctx)?; return Ok(vi.t()); } for (_, method_ctx) in singular_ctx.method_defs.iter() { @@ -374,7 +374,7 @@ impl Context { .get(method_name.inspect()) .or_else(|| method_ctx.decls.get(method_name.inspect())) { - self.validate_visibility(method_name, vi)?; + self.validate_visibility(method_name, vi, singular_ctx)?; return Ok(vi.t()); } } @@ -402,7 +402,12 @@ impl Context { } } - fn validate_visibility(&self, ident: &Identifier, vi: &VarInfo) -> TyCheckResult<()> { + fn validate_visibility( + &self, + ident: &Identifier, + vi: &VarInfo, + ctx: &Context, + ) -> TyCheckResult<()> { if ident.vis() != vi.vis { Err(TyCheckError::visibility_error( line!() as usize, @@ -411,6 +416,22 @@ impl Context { ident.inspect(), vi.vis, )) + // check if the private variable is loaded from the other scope + } else if vi.vis.is_private() + && self + .outer + .as_ref() + .map(|outer| outer.name.split("::").last().unwrap_or(&outer.name)) + .map(|name| name != &ctx.name[..]) + .unwrap_or(true) + { + Err(TyCheckError::visibility_error( + line!() as usize, + ident.loc(), + self.caused_by(), + ident.inspect(), + Private, + )) } else { Ok(()) } From c96fe956a560c19769064c0112abe8d27883ffe7 Mon Sep 17 00:00:00 2001 From: Shunsuke Shibayama Date: Fri, 9 Sep 2022 17:44:56 +0900 Subject: [PATCH 61/68] Fix `Linker` crashes --- compiler/erg_compiler/compile.rs | 4 ++-- compiler/erg_compiler/link.rs | 29 +++++++++++++++++++++++------ 2 files changed, 25 insertions(+), 8 deletions(-) diff --git a/compiler/erg_compiler/compile.rs b/compiler/erg_compiler/compile.rs index 913754b3..c70bba33 100644 --- a/compiler/erg_compiler/compile.rs +++ b/compiler/erg_compiler/compile.rs @@ -164,8 +164,8 @@ impl Compiler { cfg.input = Input::Str(src); let mut parser = ParserRunner::new(cfg); let ast = parser.parse()?; - let mut linker = Linker::new(); - let ast = linker.link(ast); + let linker = Linker::new(); + let ast = linker.link(ast).map_err(|errs| self.convert(errs))?; let (hir, warns) = self .lowerer .lower(ast, mode) diff --git a/compiler/erg_compiler/link.rs b/compiler/erg_compiler/link.rs index cb5deee2..77f9a80c 100644 --- a/compiler/erg_compiler/link.rs +++ b/compiler/erg_compiler/link.rs @@ -1,25 +1,29 @@ use erg_common::dict::Dict; use erg_common::log; -use erg_common::traits::Stream; +use erg_common::traits::{Locational, Stream}; use erg_common::Str; use erg_parser::ast::{ClassDef, Expr, Module, PreDeclTypeSpec, TypeSpec, AST}; +use crate::error::{TyCheckError, TyCheckErrors}; + /// Combine method definitions across multiple modules, specialized class contexts, etc. #[derive(Debug)] pub struct Linker { // TODO: inner scope types pub def_root_pos_map: Dict, + pub errs: TyCheckErrors, } impl Linker { pub fn new() -> Self { Self { def_root_pos_map: Dict::new(), + errs: TyCheckErrors::empty(), } } - pub fn link(&mut self, mut ast: AST) -> AST { + pub fn link(mut self, mut ast: AST) -> Result { log!(info "the linking process has started."); let mut new = vec![]; while let Some(chunk) = ast.module.lpop() { @@ -57,9 +61,18 @@ impl Linker { class_def.methods_list.push(methods); new.insert(*pos, Expr::ClassDef(class_def)); } else { - log!("{}", simple.name.inspect()); - log!("{}", self.def_root_pos_map); - todo!() + let similar_name = Str::from( + self.def_root_pos_map + .keys() + .fold("".to_string(), |acc, key| acc + &key[..] + ","), + ); + self.errs.push(TyCheckError::no_var_error( + line!() as usize, + methods.class.loc(), + "".into(), + simple.name.inspect(), + Some(&similar_name), + )); } } other => todo!("{other}"), @@ -71,6 +84,10 @@ impl Linker { } let ast = AST::new(ast.name, Module::new(new)); log!(info "the linking process has completed:\n{}", ast); - ast + if self.errs.is_empty() { + Ok(ast) + } else { + Err(self.errs) + } } } From 3895d29669bfaa5fddf6bf25871e2a414e7081e3 Mon Sep 17 00:00:00 2001 From: Shunsuke Shibayama Date: Sat, 10 Sep 2022 01:42:23 +0900 Subject: [PATCH 62/68] Fix visibility bugs --- compiler/erg_compiler/codegen.rs | 189 ++++++++++---------- compiler/erg_compiler/context/eval.rs | 27 ++- compiler/erg_compiler/context/inquire.rs | 114 ++++++------ compiler/erg_compiler/context/register.rs | 4 +- compiler/erg_compiler/context/tyvar.rs | 2 +- compiler/erg_compiler/effectcheck.rs | 4 +- compiler/erg_compiler/hir.rs | 203 +++++++++++----------- compiler/erg_compiler/lower.rs | 56 ++++-- compiler/erg_compiler/ownercheck.rs | 21 +-- compiler/erg_parser/ast.rs | 124 +++---------- compiler/erg_parser/desugar.rs | 14 +- compiler/erg_parser/parse.rs | 102 ++++------- 12 files changed, 372 insertions(+), 488 deletions(-) diff --git a/compiler/erg_compiler/codegen.rs b/compiler/erg_compiler/codegen.rs index b988aac6..31aaabfb 100644 --- a/compiler/erg_compiler/codegen.rs +++ b/compiler/erg_compiler/codegen.rs @@ -18,7 +18,7 @@ use erg_parser::ast::DefId; use erg_type::codeobj::{CodeObj, CodeObjFlags}; use Opcode::*; -use erg_parser::ast::{Identifier, ParamPattern, ParamSignature, Params, VarName}; +use erg_parser::ast::{ParamPattern, ParamSignature, Params, VarName}; use erg_parser::token::{Token, TokenKind}; use erg_type::free::fresh_varname; @@ -32,11 +32,18 @@ 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, Literal, Local, PosArg, Signature, - SubrSignature, Tuple, VarSignature, HIR, + Accessor, Args, Array, Block, Call, ClassDef, DefBody, Expr, Identifier, Literal, PosArg, + Signature, SubrSignature, Tuple, VarSignature, HIR, }; use AccessKind::*; +fn is_python_special(name: &str) -> bool { + match name { + "__call__" | "__init__" => true, + _ => false, + } +} + fn is_python_global(name: &str) -> bool { match name { "ArithmeticError" @@ -214,11 +221,17 @@ fn convert_to_python_attr(class: &str, uniq_obj_name: Option<&str>, name: Str) - } } -fn escape_attr(class: &str, uniq_obj_name: Option<&str>, name: Str) -> Str { - let mut name = convert_to_python_attr(class, uniq_obj_name, name).to_string(); +fn escape_attr(class: &str, uniq_obj_name: Option<&str>, ident: Identifier) -> Str { + let vis = ident.vis(); + let mut name = + convert_to_python_attr(class, uniq_obj_name, ident.name.into_token().content).to_string(); name = name.replace('!', "__erg_proc__"); name = name.replace('$', "__erg_shared__"); - Str::rc(&name) + if vis.is_public() || is_python_global(&name) || is_python_special(&name) { + Str::from(name) + } else { + Str::from("::".to_string() + &name) + } } fn convert_to_python_name(name: Str) -> Str { @@ -254,7 +267,7 @@ fn escape_name(ident: Identifier) -> Str { let mut name = convert_to_python_name(ident.name.into_token().content).to_string(); name = name.replace('!', "__erg_proc__"); name = name.replace('$', "__erg_shared__"); - if vis.is_public() || is_python_global(&name) { + if vis.is_public() || is_python_global(&name) || is_python_special(&name) { Str::from(name) } else { Str::from("::".to_string() + &name) @@ -500,9 +513,8 @@ impl CodeGenerator { Some(StoreLoadKind::Global) } - fn register_name(&mut self, ident: Identifier) -> Name { + fn register_name(&mut self, name: Str) -> Name { let current_is_toplevel = self.cur_block() == self.toplevel_block(); - let name = escape_name(ident); match self.rec_search(&name) { Some(st @ (StoreLoadKind::Local | StoreLoadKind::Global)) => { let st = if current_is_toplevel { @@ -533,25 +545,22 @@ impl CodeGenerator { } } - fn register_attr(&mut self, class: &str, uniq_obj_name: Option<&str>, name: Str) -> Name { - let name = Str::rc(name.split('.').last().unwrap()); - let name = escape_attr(class, uniq_obj_name, name); + fn register_attr(&mut self, name: Str) -> Name { self.mut_cur_block_codeobj().names.push(name); Name::local(self.cur_block_codeobj().names.len() - 1) } - fn register_method(&mut self, class: &str, uniq_obj_name: Option<&str>, name: Str) -> Name { - let name = Str::rc(name.split('.').last().unwrap()); - let name = escape_attr(class, uniq_obj_name, name); + fn register_method(&mut self, name: Str) -> Name { self.mut_cur_block_codeobj().names.push(name); Name::local(self.cur_block_codeobj().names.len() - 1) } fn emit_load_name_instr(&mut self, ident: Identifier) -> CompileResult<()> { log!(info "entered {}", fn_name!()); + let escaped = escape_name(ident); let name = self - .local_search(ident.inspect(), Name) - .unwrap_or_else(|| self.register_name(ident)); + .local_search(&escaped, Name) + .unwrap_or_else(|| self.register_name(escaped)); let instr = match name.kind { StoreLoadKind::Fast | StoreLoadKind::FastConst => Opcode::LOAD_FAST, StoreLoadKind::Global | StoreLoadKind::GlobalConst => Opcode::LOAD_GLOBAL, @@ -566,9 +575,10 @@ impl CodeGenerator { fn emit_import_name_instr(&mut self, ident: Identifier) -> CompileResult<()> { log!(info "entered {}", fn_name!()); + let escaped = escape_name(ident); let name = self - .local_search(ident.inspect(), Name) - .unwrap_or_else(|| self.register_name(ident)); + .local_search(&escaped, Name) + .unwrap_or_else(|| self.register_name(escaped)); self.write_instr(IMPORT_NAME); self.write_arg(name.idx as u8); self.stack_dec(); // (level + from_list) -> module object @@ -577,9 +587,10 @@ impl CodeGenerator { fn emit_import_from_instr(&mut self, ident: Identifier) -> CompileResult<()> { log!(info "entered {}", fn_name!()); + let escaped = escape_name(ident); let name = self - .local_search(ident.inspect(), Name) - .unwrap_or_else(|| self.register_name(ident)); + .local_search(&escaped, Name) + .unwrap_or_else(|| self.register_name(escaped)); self.write_instr(IMPORT_FROM); self.write_arg(name.idx as u8); // self.stack_inc(); (module object) -> attribute @@ -590,12 +601,13 @@ impl CodeGenerator { &mut self, class: &str, uniq_obj_name: Option<&str>, - name: Str, + ident: Identifier, ) -> CompileResult<()> { - log!(info "entered {} ({class}.{name})", fn_name!()); + log!(info "entered {} ({class}{ident})", fn_name!()); + let escaped = escape_attr(class, uniq_obj_name, ident); let name = self - .local_search(&name, Attr) - .unwrap_or_else(|| self.register_attr(class, uniq_obj_name, name)); + .local_search(&escaped, Attr) + .unwrap_or_else(|| self.register_attr(escaped)); let instr = match name.kind { StoreLoadKind::Fast | StoreLoadKind::FastConst => Opcode::LOAD_FAST, StoreLoadKind::Global | StoreLoadKind::GlobalConst => Opcode::LOAD_GLOBAL, @@ -611,12 +623,13 @@ impl CodeGenerator { &mut self, class: &str, uniq_obj_name: Option<&str>, - name: Str, + ident: Identifier, ) -> CompileResult<()> { - log!(info "entered {} ({class}.{name})", fn_name!()); + log!(info "entered {} ({class}{ident})", fn_name!()); + let escaped = escape_attr(class, uniq_obj_name, ident); let name = self - .local_search(&name, Method) - .unwrap_or_else(|| self.register_method(class, uniq_obj_name, name)); + .local_search(&escaped, Method) + .unwrap_or_else(|| self.register_method(escaped)); let instr = match name.kind { StoreLoadKind::Fast | StoreLoadKind::FastConst => Opcode::LOAD_FAST, StoreLoadKind::Global | StoreLoadKind::GlobalConst => Opcode::LOAD_GLOBAL, @@ -630,15 +643,14 @@ impl CodeGenerator { fn emit_store_instr(&mut self, ident: Identifier, acc_kind: AccessKind) { log!(info "entered {} ({ident})", fn_name!()); - let name = self - .local_search(ident.inspect(), acc_kind) - .unwrap_or_else(|| { - if acc_kind.is_local() { - self.register_name(ident) - } else { - self.register_attr("", None, ident.inspect().clone()) - } - }); + let escaped = escape_name(ident); + let name = self.local_search(&escaped, acc_kind).unwrap_or_else(|| { + if acc_kind.is_local() { + self.register_name(escaped) + } else { + self.register_attr(escaped) + } + }); let instr = match name.kind { StoreLoadKind::Fast => Opcode::STORE_FAST, StoreLoadKind::FastConst => Opcode::ERG_STORE_FAST_IMMUT, @@ -668,18 +680,12 @@ impl CodeGenerator { fn store_acc(&mut self, acc: Accessor) { log!(info "entered {} ({acc})", fn_name!()); 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::Ident(ident) => { + self.emit_store_instr(ident, Name); } Accessor::Attr(attr) => { self.codegen_expr(*attr.obj); - self.emit_store_instr(Identifier::new(None, VarName::new(attr.name)), Attr); + self.emit_store_instr(attr.ident, Attr); } acc => todo!("store: {acc}"), } @@ -728,7 +734,8 @@ impl CodeGenerator { .iter() .map(|p| p.inspect().map(|s| &s[..]).unwrap_or("_")), ) - .map(|s| self.get_cached(s)) + .map(|s| format!("::{s}")) + .map(|s| self.get_cached(&s)) .collect() } @@ -938,7 +945,7 @@ impl CodeGenerator { let mut pop_jump_points = vec![]; match pat { ParamPattern::VarName(name) => { - let ident = Identifier::new(None, name); + let ident = Identifier::bare(None, name); self.emit_store_instr(ident, AccessKind::Name); } ParamPattern::Lit(lit) => { @@ -993,8 +1000,8 @@ impl CodeGenerator { self.emit_call_method(*call.obj, method_name, call.args); } else { match *call.obj { - Expr::Accessor(Accessor::Local(local)) => { - self.emit_call_local(local, call.args).unwrap() + Expr::Accessor(Accessor::Ident(ident)) if ident.vis().is_private() => { + self.emit_call_local(ident, call.args).unwrap() } other => { self.codegen_expr(other); @@ -1004,7 +1011,7 @@ impl CodeGenerator { } } - fn emit_call_local(&mut self, local: Local, args: Args) -> CompileResult<()> { + fn emit_call_local(&mut self, local: Identifier, args: Args) -> CompileResult<()> { log!(info "entered {}", fn_name!()); match &local.inspect()[..] { "assert" => self.emit_assert_instr(args), @@ -1013,9 +1020,7 @@ impl CodeGenerator { "if" | "if!" => self.emit_if_instr(args), "match" | "match!" => self.emit_match_instr(args, true), _ => { - let name = VarName::new(local.name); - let ident = Identifier::new(None, name); - self.emit_load_name_instr(ident).unwrap_or_else(|e| { + self.emit_load_name_instr(local).unwrap_or_else(|e| { self.errs.push(e); }); self.emit_args(args, Name); @@ -1032,14 +1037,10 @@ impl CodeGenerator { let class = obj.ref_t().name(); // これは必ずmethodのあるクラスになっている let uniq_obj_name = obj.__name__().map(Str::rc); self.codegen_expr(obj); - self.emit_load_method_instr( - &class, - uniq_obj_name.as_ref().map(|s| &s[..]), - method_name.name.into_token().content, - ) - .unwrap_or_else(|err| { - self.errs.push(err); - }); + self.emit_load_method_instr(&class, uniq_obj_name.as_ref().map(|s| &s[..]), method_name) + .unwrap_or_else(|err| { + self.errs.push(err); + }); self.emit_args(args, Method); } @@ -1361,14 +1362,7 @@ impl CodeGenerator { fn codegen_acc(&mut self, acc: Accessor) { log!(info "entered {} ({acc})", fn_name!()); match acc { - Accessor::Local(local) => { - self.emit_load_name_instr(Identifier::new(None, VarName::new(local.name))) - .unwrap_or_else(|err| { - self.errs.push(err); - }); - } - Accessor::Public(public) => { - let ident = Identifier::new(Some(public.dot), VarName::new(public.name)); + Accessor::Ident(ident) => { self.emit_load_name_instr(ident).unwrap_or_else(|err| { self.errs.push(err); }); @@ -1377,14 +1371,10 @@ impl CodeGenerator { let class = a.obj.ref_t().name(); let uniq_obj_name = a.obj.__name__().map(Str::rc); self.codegen_expr(*a.obj); - self.emit_load_attr_instr( - &class, - uniq_obj_name.as_ref().map(|s| &s[..]), - a.name.content.clone(), - ) - .unwrap_or_else(|err| { - self.errs.push(err); - }); + self.emit_load_attr_instr(&class, uniq_obj_name.as_ref().map(|s| &s[..]), a.ident) + .unwrap_or_else(|err| { + self.errs.push(err); + }); } Accessor::TupleAttr(t_attr) => { self.codegen_expr(*t_attr.obj); @@ -1516,26 +1506,32 @@ impl CodeGenerator { let subr_sig = SubrSignature::new(ident, params.clone(), __new__.clone()); let mut attrs = vec![]; match __new__.non_default_params().unwrap()[0].typ() { + // namedtupleは仕様上::xなどの名前を使えない // {x = Int; y = Int} - // self.x = %x.x; self.y = %x.y + // => self::x = %x.x; self::y = %x.y + // {.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 obj = + Expr::Accessor(Accessor::private_with_line(Str::from(¶m_name), line)); let expr = Expr::Accessor(Accessor::Attr(Attribute::new( obj, - Token::symbol(&field.symbol[..]), + Identifier::bare( + Some(Token::dummy()), + VarName::from_str(field.symbol.clone()), + ), Type::Failure, ))); - let obj = Expr::Accessor(Accessor::local( - Token::symbol_with_line("self", line), - Type::Failure, - )); + let obj = Expr::Accessor(Accessor::private_with_line(Str::ever("self"), line)); + let dot = if field.vis.is_private() { + None + } else { + Some(Token::dummy()) + }; let attr = Accessor::Attr(Attribute::new( obj, - Token::symbol(&field.symbol[..]), + Identifier::bare(dot, VarName::from_str(field.symbol.clone())), Type::Failure, )); let attr_def = AttrDef::new(attr, Block::new(vec![expr])); @@ -1569,17 +1565,14 @@ impl CodeGenerator { Params::new(vec![param], None, vec![], None), __new__.clone(), ); - let arg = PosArg::new(Expr::Accessor(Accessor::local( - Token::symbol_with_line(¶m_name[..], line), - Type::Failure, + let arg = PosArg::new(Expr::Accessor(Accessor::private_with_line( + Str::from(param_name), + line, ))); - let class = Expr::Accessor(Accessor::local( - Token::symbol_with_line(class_name, line), - Type::Failure, - )); + let class = Expr::Accessor(Accessor::private_with_line(class_name.clone(), line)); let class_new = Expr::Accessor(Accessor::attr( class, - Token::symbol_with_line("__new__", line), + Identifier::bare(None, VarName::from_str_and_line(Str::ever("__new__"), line)), Type::Failure, )); let call = Expr::Call(Call::new( diff --git a/compiler/erg_compiler/context/eval.rs b/compiler/erg_compiler/context/eval.rs index 4187fb15..9f37ab12 100644 --- a/compiler/erg_compiler/context/eval.rs +++ b/compiler/erg_compiler/context/eval.rs @@ -166,17 +166,17 @@ impl SubstContext { impl Context { fn eval_const_acc(&self, acc: &Accessor) -> EvalResult { match acc { - Accessor::Local(local) => { - if let Some(val) = self.rec_get_const_obj(local.inspect()) { + Accessor::Ident(ident) => { + if let Some(val) = self.rec_get_const_obj(ident.inspect()) { Ok(val.clone()) } else { - if local.is_const() { + if ident.is_const() { Err(EvalError::no_var_error( line!() as usize, - local.loc(), + ident.loc(), self.caused_by(), - local.inspect(), - self.get_similar_name(local.inspect()), + ident.inspect(), + self.get_similar_name(ident.inspect()), )) } else { Err(EvalError::not_const_expr( @@ -232,22 +232,22 @@ impl Context { fn eval_const_call(&self, call: &Call, __name__: Option<&Str>) -> EvalResult { if let Expr::Accessor(acc) = call.obj.as_ref() { match acc { - Accessor::Local(name) => { + Accessor::Ident(ident) => { let obj = - self.rec_get_const_obj(&name.inspect()) + self.rec_get_const_obj(&ident.inspect()) .ok_or(EvalError::no_var_error( line!() as usize, - name.loc(), + ident.loc(), self.caused_by(), - name.inspect(), - self.get_similar_name(name.inspect()), + ident.inspect(), + self.get_similar_name(ident.inspect()), ))?; let subr = option_enum_unwrap!(obj, ValueObj::Subr) .ok_or(EvalError::type_mismatch_error( line!() as usize, - name.loc(), + ident.loc(), self.caused_by(), - name.inspect(), + ident.inspect(), &mono("Subroutine"), &obj.t(), None, @@ -258,7 +258,6 @@ impl Context { } Accessor::Attr(_attr) => todo!(), Accessor::TupleAttr(_attr) => todo!(), - Accessor::Public(_name) => todo!(), Accessor::Subscr(_subscr) => todo!(), } } else { diff --git a/compiler/erg_compiler/context/inquire.rs b/compiler/erg_compiler/context/inquire.rs index 8122bc9a..d9a7c949 100644 --- a/compiler/erg_compiler/context/inquire.rs +++ b/compiler/erg_compiler/context/inquire.rs @@ -91,17 +91,17 @@ impl Context { namespace: &Str, ) -> TyCheckResult<&Context> { match obj { - hir::Expr::Accessor(hir::Accessor::Local(name)) => { + hir::Expr::Accessor(hir::Accessor::Ident(ident)) => { if kind == Some(ContextKind::Module) { - if let Some(ctx) = self.rec_get_mod(name.inspect()) { + if let Some(ctx) = self.rec_get_mod(ident.inspect()) { Ok(ctx) } else { Err(TyCheckError::no_var_error( line!() as usize, obj.loc(), namespace.clone(), - name.inspect(), - self.get_similar_name(name.inspect()), + ident.inspect(), + self.get_similar_name(ident.inspect()), )) } } else { @@ -197,34 +197,20 @@ impl Context { None } - pub(crate) fn rec_get_var_t( - &self, - name: &Token, - vis: Visibility, - namespace: &Str, - ) -> TyCheckResult { - if let Some(vi) = self.get_current_scope_var(&name.inspect()[..]) { - if vi.vis == vis { - Ok(vi.t()) - } else { - Err(TyCheckError::visibility_error( - line!() as usize, - name.loc(), - namespace.clone(), - name.inspect(), - vi.vis, - )) - } + pub(crate) fn rec_get_var_t(&self, ident: &Identifier, namespace: &Str) -> TyCheckResult { + if let Some(vi) = self.get_current_scope_var(&ident.inspect()[..]) { + // self.validate_visibility(ident, vi, self)?; + Ok(vi.t()) } else { if let Some(parent) = self.outer.as_ref() { - return parent.rec_get_var_t(name, vis, namespace); + return parent.rec_get_var_t(ident, namespace); } Err(TyCheckError::no_var_error( line!() as usize, - name.loc(), + ident.loc(), namespace.clone(), - name.inspect(), - self.get_similar_name(name.inspect()), + ident.inspect(), + self.get_similar_name(ident.inspect()), )) } } @@ -232,11 +218,12 @@ impl Context { pub(crate) fn rec_get_attr_t( &self, obj: &hir::Expr, - name: &Token, + ident: &Identifier, namespace: &Str, ) -> TyCheckResult { let self_t = obj.t(); - match self.get_attr_t_from_attributive_t(obj, &self_t, name, namespace) { + let name = ident.name.token(); + match self.get_attr_t_from_attributive_t(obj, &self_t, ident, namespace) { Ok(t) => { return Ok(t); } @@ -245,17 +232,22 @@ impl Context { return Err(e); } } + if let Some(singular_ctx) = self.rec_get_singular_ctx(obj) { + if let Ok(t) = singular_ctx.rec_get_var_t(ident, namespace) { + return Ok(t); + } + } for (_, ctx) in self .rec_get_nominal_super_type_ctxs(&self_t) .ok_or_else(|| todo!())? { - if let Ok(t) = ctx.rec_get_var_t(name, Public, namespace) { + if let Ok(t) = ctx.rec_get_var_t(ident, namespace) { return Ok(t); } } // TODO: dependent type widening if let Some(parent) = self.outer.as_ref() { - parent.rec_get_attr_t(obj, name, namespace) + parent.rec_get_attr_t(obj, ident, namespace) } else { Err(TyCheckError::no_attr_error( line!() as usize, @@ -272,53 +264,56 @@ impl Context { &self, obj: &hir::Expr, t: &Type, - name: &Token, + ident: &Identifier, namespace: &Str, ) -> TyCheckResult { match t { Type::FreeVar(fv) if fv.is_linked() => { - self.get_attr_t_from_attributive_t(obj, &fv.crack(), name, namespace) + self.get_attr_t_from_attributive_t(obj, &fv.crack(), ident, namespace) } Type::FreeVar(fv) => { let sup = fv.get_sup().unwrap(); - self.get_attr_t_from_attributive_t(obj, &sup, name, namespace) + self.get_attr_t_from_attributive_t(obj, &sup, ident, namespace) } - Type::Ref(t) => self.get_attr_t_from_attributive_t(obj, t, name, namespace), + Type::Ref(t) => self.get_attr_t_from_attributive_t(obj, t, ident, namespace), Type::RefMut { before, .. } => { - self.get_attr_t_from_attributive_t(obj, before, name, namespace) + self.get_attr_t_from_attributive_t(obj, before, ident, namespace) } Type::Refinement(refine) => { - self.get_attr_t_from_attributive_t(obj, &refine.t, name, namespace) + self.get_attr_t_from_attributive_t(obj, &refine.t, ident, namespace) } Type::Record(record) => { // REVIEW: `rec.get(name.inspect())` returns None (Borrow is implemented for Field). Why? - if let Some(attr) = record.get(&Field::new(Public, name.inspect().clone())) { + if let Some(attr) = record.get(&Field::new(Public, ident.inspect().clone())) { Ok(attr.clone()) } else { let t = Type::Record(record.clone()); Err(TyCheckError::no_attr_error( line!() as usize, - name.loc(), + ident.loc(), namespace.clone(), &t, - name.inspect(), - self.get_similar_attr(&t, name.inspect()), + ident.inspect(), + self.get_similar_attr(&t, ident.inspect()), )) } } Module => { let mod_ctx = self.get_context(obj, Some(ContextKind::Module), namespace)?; - let t = mod_ctx.rec_get_var_t(name, Public, namespace)?; + let t = mod_ctx.rec_get_var_t(ident, namespace)?; Ok(t) } other => { if let Some(v) = self.rec_get_const_obj(&other.name()) { match v { ValueObj::Type(TypeObj::Generated(gen)) => self - .get_gen_t_require_attr_t(gen, &name.inspect()[..]) + .get_gen_t_require_attr_t(gen, &ident.inspect()[..]) .map(|t| t.clone()) .ok_or(TyCheckError::dummy(line!() as usize)), - ValueObj::Type(TypeObj::Builtin(t)) => todo!("{t}"), + ValueObj::Type(TypeObj::Builtin(_t)) => { + // FIXME: + Err(TyCheckError::dummy(line!() as usize)) + } other => todo!("{other}"), } } else { @@ -421,8 +416,9 @@ impl Context { && self .outer .as_ref() - .map(|outer| outer.name.split("::").last().unwrap_or(&outer.name)) - .map(|name| name != &ctx.name[..]) + // TODO: also split with `.` + .map(|outer| outer.name.split("::")) + .map(|mut names| names.all(|name| name != &ctx.name[..])) .unwrap_or(true) { Err(TyCheckError::visibility_error( @@ -446,14 +442,17 @@ impl Context { erg_common::debug_power_assert!(args.len() == 2); let cont = binop_to_dname(op.inspect()); let symbol = Token::new(op.kind, Str::rc(cont), op.lineno, op.col_begin); - let t = self.rec_get_var_t(&symbol, Private, namespace)?; - let op = hir::Expr::Accessor(hir::Accessor::local(symbol, t)); + let t = self.rec_get_var_t( + &Identifier::new(None, VarName::new(symbol.clone())), + namespace, + )?; + let op = hir::Expr::Accessor(hir::Accessor::private(symbol, t)); self.get_call_t(&op, &None, args, &[], namespace) .map_err(|e| { - let op = enum_unwrap!(op, hir::Expr::Accessor:(hir::Accessor::Local:(_))); + let op = enum_unwrap!(op, hir::Expr::Accessor:(hir::Accessor::Ident:(_))); let lhs = args[0].expr.clone(); let rhs = args[1].expr.clone(); - let bin = hir::BinOp::new(op.name, lhs, rhs, op.t); + let bin = hir::BinOp::new(op.name.into_token(), lhs, rhs, op.t.clone()); // HACK: dname.loc()はダミーLocationしか返さないので、エラーならop.loc()で上書きする let core = ErrorCore::new( e.core.errno, @@ -475,13 +474,16 @@ impl Context { erg_common::debug_power_assert!(args.len() == 1); let cont = unaryop_to_dname(op.inspect()); let symbol = Token::new(op.kind, Str::rc(cont), op.lineno, op.col_begin); - let t = self.rec_get_var_t(&symbol, Private, namespace)?; - let op = hir::Expr::Accessor(hir::Accessor::local(symbol, t)); + let t = self.rec_get_var_t( + &Identifier::new(None, VarName::new(symbol.clone())), + namespace, + )?; + let op = hir::Expr::Accessor(hir::Accessor::private(symbol, t)); self.get_call_t(&op, &None, args, &[], namespace) .map_err(|e| { - let op = enum_unwrap!(op, hir::Expr::Accessor:(hir::Accessor::Local:(_))); + let op = enum_unwrap!(op, hir::Expr::Accessor:(hir::Accessor::Ident:(_))); let expr = args[0].expr.clone(); - let unary = hir::UnaryOp::new(op.name, expr, op.t); + let unary = hir::UnaryOp::new(op.name.into_token(), expr, op.t.clone()); let core = ErrorCore::new( e.core.errno, e.core.kind, @@ -655,7 +657,7 @@ impl Context { let callee = if let Some(ident) = method_name { let attr = hir::Attribute::new( obj.clone(), - ident.name.clone().into_token(), + hir::Identifier::bare(ident.dot.clone(), ident.name.clone()), Type::Uninited, ); let acc = hir::Expr::Accessor(hir::Accessor::Attr(attr)); @@ -886,7 +888,9 @@ impl Context { namespace: &Str, ) -> TyCheckResult { match obj { - hir::Expr::Accessor(hir::Accessor::Local(local)) if &local.inspect()[..] == "match" => { + hir::Expr::Accessor(hir::Accessor::Ident(local)) + if local.vis().is_private() && &local.inspect()[..] == "match" => + { return self.get_match_call_t(pos_args, kw_args); } _ => {} diff --git a/compiler/erg_compiler/context/register.rs b/compiler/erg_compiler/context/register.rs index 4727933b..2fd2e315 100644 --- a/compiler/erg_compiler/context/register.rs +++ b/compiler/erg_compiler/context/register.rs @@ -109,7 +109,7 @@ impl Context { .decorators .iter() .filter_map(|deco| match &deco.0 { - ast::Expr::Accessor(ast::Accessor::Local(local)) if local.is_const() => { + ast::Expr::Accessor(ast::Accessor::Ident(local)) if local.is_const() => { Some(local.inspect().clone()) } _ => None, @@ -428,7 +428,7 @@ impl Context { .decorators .iter() .filter_map(|deco| match &deco.0 { - ast::Expr::Accessor(ast::Accessor::Local(local)) if local.is_const() => { + ast::Expr::Accessor(ast::Accessor::Ident(local)) if local.is_const() => { Some(local.inspect().clone()) } _ => None, diff --git a/compiler/erg_compiler/context/tyvar.rs b/compiler/erg_compiler/context/tyvar.rs index b5190e50..7b660f83 100644 --- a/compiler/erg_compiler/context/tyvar.rs +++ b/compiler/erg_compiler/context/tyvar.rs @@ -371,7 +371,7 @@ impl Context { self.deref_expr_t(&mut subscr.obj)?; self.deref_expr_t(&mut subscr.index)?; } - hir::Accessor::Local(_) | hir::Accessor::Public(_) => {} + hir::Accessor::Ident(_) => {} } Ok(()) } diff --git a/compiler/erg_compiler/effectcheck.rs b/compiler/erg_compiler/effectcheck.rs index be2c0f7d..0514817b 100644 --- a/compiler/erg_compiler/effectcheck.rs +++ b/compiler/erg_compiler/effectcheck.rs @@ -259,10 +259,10 @@ impl SideEffectChecker { Expr::Lambda(lambda) => lambda.is_procedural(), // 引数がproceduralでも関数呼び出しなら副作用なし Expr::Call(call) => self.is_procedural(&call.obj), - Expr::Accessor(Accessor::Local(local)) => local.name.is_procedural(), + Expr::Accessor(Accessor::Ident(ident)) => ident.name.is_procedural(), // procedural: x.y! (e.g. Array.sample!) // !procedural: !x.y - Expr::Accessor(Accessor::Attr(attr)) => attr.name.is_procedural(), + Expr::Accessor(Accessor::Attr(attr)) => attr.ident.is_procedural(), Expr::Accessor(_) => todo!(), _ => false, } diff --git a/compiler/erg_compiler/hir.rs b/compiler/erg_compiler/hir.rs index 0e9515d0..af75046e 100644 --- a/compiler/erg_compiler/hir.rs +++ b/compiler/erg_compiler/hir.rs @@ -11,7 +11,7 @@ use erg_common::{ impl_stream_for_wrapper, }; -use erg_parser::ast::{fmt_lines, DefId, Identifier, Params, TypeSpec}; +use erg_parser::ast::{fmt_lines, DefId, Params, TypeSpec, VarName}; use erg_parser::token::{Token, TokenKind}; use erg_type::constructors::{array, tuple}; @@ -286,84 +286,55 @@ impl Args { } } -/// represents local variables -#[derive(Debug, Clone)] -pub struct Local { - pub name: Token, - /// オブジェクト自身の名前 - __name__: Option, - pub(crate) t: Type, +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct Identifier { + pub dot: Option, + pub name: VarName, + pub __name__: Option, + pub t: Type, } -impl NestedDisplay for Local { +impl NestedDisplay for Identifier { fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, _level: usize) -> fmt::Result { - let __name__ = if let Some(__name__) = self.__name__() { - format!("(__name__ = {__name__})") - } else { - "".to_string() - }; - write!(f, "{} (: {}){}", self.name.content, self.t, __name__) + match &self.dot { + Some(_dot) => { + write!(f, ".{}", self.name)?; + } + None => { + write!(f, "::{}", self.name)?; + } + } + if let Some(__name__) = &self.__name__ { + write!(f, "(__name__: {})", __name__)?; + } + if self.t != Type::Uninited { + write!(f, "(: {})", self.t)?; + } + Ok(()) } } -impl_display_from_nested!(Local); -impl_t!(Local); +impl_display_from_nested!(Identifier); +impl_t!(Identifier); -impl Locational for Local { - #[inline] +impl Locational for Identifier { fn loc(&self) -> Location { - self.name.loc() - } -} - -impl Local { - pub const fn new(name: Token, __name__: Option, t: Type) -> Self { - Self { name, __name__, t } - } - - // &strにするとクローンしたいときにアロケーションコストがかかるので&Strのままで - #[inline] - pub fn inspect(&self) -> &Str { - &self.name.content - } - - pub const fn __name__(&self) -> Option<&Str> { - self.__name__.as_ref() - } -} - -#[derive(Debug, Clone)] -pub struct Public { - pub dot: Token, - pub name: Token, - /// オブジェクト自身の名前 - __name__: Option, - t: Type, -} - -impl NestedDisplay for Public { - fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, _level: usize) -> fmt::Result { - let __name__ = if let Some(__name__) = self.__name__() { - format!("(__name__ = {__name__})") + if let Some(dot) = &self.dot { + Location::concat(dot, &self.name) } else { - "".to_string() - }; - write!(f, ".{} (: {}){}", self.name.content, self.t, __name__) + self.name.loc() + } } } -impl_display_from_nested!(Public); -impl_t!(Public); - -impl Locational for Public { - #[inline] - fn loc(&self) -> Location { - Location::concat(&self.dot, &self.name) +impl From<&Identifier> for Field { + fn from(ident: &Identifier) -> Self { + Self::new(ident.vis(), ident.inspect().clone()) } } -impl Public { - pub const fn new(dot: Token, name: Token, __name__: Option, t: Type) -> Self { +impl Identifier { + pub const fn new(dot: Option, name: VarName, __name__: Option, t: Type) -> Self { Self { dot, name, @@ -372,43 +343,75 @@ impl Public { } } - // &strにするとクローンしたいときにアロケーションコストがかかるので&Strのままで - #[inline] - pub fn inspect(&self) -> &Str { - &self.name.content + pub fn public(name: &'static str) -> Self { + Self::bare( + Some(Token::from_str(TokenKind::Dot, ".")), + VarName::from_static(name), + ) } - pub const fn __name__(&self) -> Option<&Str> { - self.__name__.as_ref() + pub fn private(name: Str) -> Self { + Self::bare(None, VarName::from_str(name)) + } + + pub fn private_with_line(name: Str, line: usize) -> Self { + Self::bare(None, VarName::from_str_and_line(name, line)) + } + + pub fn public_with_line(dot: Token, name: Str, line: usize) -> Self { + Self::bare(Some(dot), VarName::from_str_and_line(name, line)) + } + + pub const fn bare(dot: Option, name: VarName) -> Self { + Self::new(dot, name, None, Type::Uninited) + } + + pub fn is_const(&self) -> bool { + self.name.is_const() + } + + pub const fn vis(&self) -> Visibility { + match &self.dot { + Some(_) => Visibility::Public, + None => Visibility::Private, + } + } + + pub const fn inspect(&self) -> &Str { + &self.name.inspect() + } + + pub fn is_procedural(&self) -> bool { + self.name.is_procedural() } } #[derive(Debug, Clone)] pub struct Attribute { pub obj: Box, - pub name: Token, + pub ident: Identifier, t: Type, } impl NestedDisplay for Attribute { fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, _level: usize) -> fmt::Result { if self.t != Type::Uninited { - write!(f, "({}).{}(: {})", self.obj, self.name.content, self.t) + write!(f, "({}){}(: {})", self.obj, self.ident, self.t) } else { - write!(f, "({}).{}", self.obj, self.name.content) + write!(f, "({}){}", self.obj, self.ident) } } } impl_display_from_nested!(Attribute); -impl_locational!(Attribute, obj, name); +impl_locational!(Attribute, obj, ident); impl_t!(Attribute); impl Attribute { - pub fn new(obj: Expr, name: Token, t: Type) -> Self { + pub fn new(obj: Expr, ident: Identifier, t: Type) -> Self { Self { obj: Box::new(obj), - name, + ident, t, } } @@ -471,29 +474,32 @@ impl Subscript { #[derive(Debug, Clone)] pub enum Accessor { - Local(Local), - Public(Public), + Ident(Identifier), Attr(Attribute), TupleAttr(TupleAttribute), Subscr(Subscript), } -impl_nested_display_for_enum!(Accessor; Local, Public, Attr, TupleAttr, Subscr); +impl_nested_display_for_enum!(Accessor; Ident, Attr, TupleAttr, Subscr); impl_display_from_nested!(Accessor); -impl_locational_for_enum!(Accessor; Local, Public, Attr, TupleAttr, Subscr); -impl_t_for_enum!(Accessor; Local, Public, Attr, TupleAttr, Subscr); +impl_locational_for_enum!(Accessor; Ident, Attr, TupleAttr, Subscr); +impl_t_for_enum!(Accessor; Ident, Attr, TupleAttr, Subscr); impl Accessor { - pub const fn local(symbol: Token, t: Type) -> Self { - Self::Local(Local::new(symbol, None, t)) + pub fn private_with_line(name: Str, line: usize) -> Self { + Self::Ident(Identifier::private_with_line(name, line)) } - pub const fn public(dot: Token, name: Token, t: Type) -> Self { - Self::Public(Public::new(dot, name, None, t)) + pub fn public_with_line(name: Str, line: usize) -> Self { + Self::Ident(Identifier::public_with_line(Token::dummy(), name, line)) } - pub fn attr(obj: Expr, name: Token, t: Type) -> Self { - Self::Attr(Attribute::new(obj, name, t)) + pub const fn private(name: Token, t: Type) -> Self { + Self::Ident(Identifier::new(None, VarName::new(name), None, t)) + } + + pub fn attr(obj: Expr, ident: Identifier, t: Type) -> Self { + Self::Attr(Attribute::new(obj, ident, t)) } pub fn subscr(obj: Expr, index: Expr, t: Type) -> Self { @@ -502,14 +508,13 @@ impl Accessor { pub fn show(&self) -> String { match self { - Self::Local(local) => readable_name(local.inspect()).to_string(), - Self::Public(public) => readable_name(public.inspect()).to_string(), + Self::Ident(ident) => readable_name(ident.inspect()).to_string(), Self::Attr(attr) => { attr.obj .show_acc() .unwrap_or_else(|| attr.obj.ref_t().to_string()) - + "." - + readable_name(attr.name.inspect()) + + "." // TODO: visibility + + readable_name(attr.ident.inspect()) } Self::TupleAttr(t_attr) => { t_attr @@ -526,8 +531,7 @@ impl Accessor { // 参照するオブジェクト自体が持っている固有の名前 pub fn __name__(&self) -> Option<&str> { match self { - Self::Local(local) => local.__name__().map(|s| &s[..]), - Self::Public(public) => public.__name__().map(|s| &s[..]), + Self::Ident(ident) => ident.__name__.as_ref().map(|s| &s[..]), _ => None, } } @@ -1260,19 +1264,6 @@ impl DefBody { pub const fn new(op: Token, block: Block, id: DefId) -> Self { Self { op, block, id } } - - pub fn is_type(&self) -> bool { - match self.block.first().unwrap() { - Expr::Call(call) => { - if let Expr::Accessor(Accessor::Local(local)) = call.obj.as_ref() { - &local.inspect()[..] == "Type" - } else { - false - } - } - _ => false, - } - } } #[derive(Debug, Clone)] diff --git a/compiler/erg_compiler/lower.rs b/compiler/erg_compiler/lower.rs index 7d81d50c..b12f8db8 100644 --- a/compiler/erg_compiler/lower.rs +++ b/compiler/erg_compiler/lower.rs @@ -271,7 +271,7 @@ impl ASTLowerer { fn lower_acc(&mut self, acc: ast::Accessor) -> LowerResult { log!(info "entered {}({acc})", fn_name!()); match acc { - ast::Accessor::Local(local) => { + /*ast::Accessor::Local(local) => { // `match` is an untypable special form // `match`は型付け不可能な特殊形式 let (t, __name__) = if &local.inspect()[..] == "match" { @@ -279,29 +279,23 @@ impl ASTLowerer { } else { ( self.ctx - .rec_get_var_t(&local.symbol, Private, &self.ctx.name)?, + .rec_get_var_t(&local.symbol, &self.ctx.name)?, self.ctx.get_local_uniq_obj_name(&local.symbol), ) }; let acc = hir::Accessor::Local(hir::Local::new(local.symbol, __name__, t)); Ok(acc) - } - ast::Accessor::Public(public) => { - let (t, __name__) = ( - self.ctx - .rec_get_var_t(&public.symbol, Public, &self.ctx.name)?, - self.ctx.get_local_uniq_obj_name(&public.symbol), - ); - let public = hir::Public::new(public.dot, public.symbol, __name__, t); - let acc = hir::Accessor::Public(public); + }*/ + ast::Accessor::Ident(ident) => { + let ident = self.lower_ident(ident)?; + let acc = hir::Accessor::Ident(ident); Ok(acc) } ast::Accessor::Attr(attr) => { let obj = self.lower_expr(*attr.obj)?; - let t = self - .ctx - .rec_get_attr_t(&obj, &attr.name.symbol, &self.ctx.name)?; - let acc = hir::Accessor::Attr(hir::Attribute::new(obj, attr.name.symbol, t)); + let t = self.ctx.rec_get_attr_t(&obj, &attr.ident, &self.ctx.name)?; + let ident = hir::Identifier::bare(attr.ident.dot, attr.ident.name); + let acc = hir::Accessor::Attr(hir::Attribute::new(obj, ident, t)); Ok(acc) } ast::Accessor::TupleAttr(t_attr) => { @@ -329,6 +323,19 @@ impl ASTLowerer { } } + fn lower_ident(&self, ident: ast::Identifier) -> LowerResult { + let (t, __name__) = if ident.vis().is_private() && &ident.inspect()[..] == "match" { + (Type::Failure, None) + } else { + ( + self.ctx.rec_get_var_t(&ident, &self.ctx.name)?, + self.ctx.get_local_uniq_obj_name(ident.name.token()), + ) + }; + let ident = hir::Identifier::new(ident.dot, ident.name, __name__, t); + Ok(ident) + } + fn lower_bin(&mut self, bin: ast::BinOp) -> LowerResult { log!(info "entered {}({bin})", fn_name!()); let mut args = bin.args.into_iter(); @@ -376,7 +383,17 @@ impl ASTLowerer { &hir_args.kw_args, &self.ctx.name, )?; - Ok(hir::Call::new(obj, call.method_name, hir_args, sig_t)) + let method_name = if let Some(method_name) = call.method_name { + Some(hir::Identifier::new( + method_name.dot, + method_name.name, + None, + Type::Uninited, + )) + } else { + None + }; + Ok(hir::Call::new(obj, method_name, hir_args, sig_t)) } fn lower_pack(&mut self, pack: ast::DataPack) -> LowerResult { @@ -406,6 +423,7 @@ impl ASTLowerer { &self.ctx.name, )?; let args = hir::Args::new(args, None, vec![], None); + let method_name = hir::Identifier::bare(method_name.dot, method_name.name); Ok(hir::Call::new(class, Some(method_name), args, sig_t)) } @@ -540,7 +558,8 @@ impl ASTLowerer { } _other => {} } - let sig = hir::VarSignature::new(ident.clone(), found_body_t.clone()); + let ident = hir::Identifier::bare(ident.dot.clone(), ident.name.clone()); + let sig = hir::VarSignature::new(ident, found_body_t.clone()); let body = hir::DefBody::new(body.op, block, body.id); Ok(hir::Def::new(hir::Signature::Var(sig), body)) } @@ -579,7 +598,8 @@ impl ASTLowerer { .as_mut() .unwrap() .assign_subr(&sig, id, found_body_t)?; - let sig = hir::SubrSignature::new(sig.ident, sig.params, t); + let ident = hir::Identifier::bare(sig.ident.dot, sig.ident.name); + let sig = hir::SubrSignature::new(ident, sig.params, t); 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/ownercheck.rs b/compiler/erg_compiler/ownercheck.rs index c83e15ed..3523b88c 100644 --- a/compiler/erg_compiler/ownercheck.rs +++ b/compiler/erg_compiler/ownercheck.rs @@ -186,26 +186,15 @@ impl OwnershipChecker { fn check_acc(&mut self, acc: &Accessor, ownership: Ownership) { match acc { - Accessor::Local(local) => { - self.check_if_dropped(local.inspect(), local.loc()); + Accessor::Ident(ident) => { + self.check_if_dropped(ident.inspect(), ident.loc()); if acc.ref_t().is_mut() && ownership.is_owned() { log!( "drop: {} (in {})", - local.inspect(), - local.ln_begin().unwrap_or(0) + ident.inspect(), + ident.ln_begin().unwrap_or(0) ); - self.drop(local.inspect(), acc.loc()); - } - } - Accessor::Public(public) => { - self.check_if_dropped(public.inspect(), public.loc()); - if acc.ref_t().is_mut() && ownership.is_owned() { - log!( - "drop: {} (in {})", - public.inspect(), - public.ln_begin().unwrap_or(0) - ); - self.drop(public.inspect(), acc.loc()); + self.drop(ident.inspect(), acc.loc()); } } Accessor::Attr(attr) => { diff --git a/compiler/erg_parser/ast.rs b/compiler/erg_parser/ast.rs index 89286408..5b8add5b 100644 --- a/compiler/erg_parser/ast.rs +++ b/compiler/erg_parser/ast.rs @@ -226,107 +226,26 @@ impl Args { } } -/// represents a local (private) variable -#[derive(Clone, Debug, PartialEq, Eq, Hash)] -pub struct Local { - pub symbol: Token, -} - -impl NestedDisplay for Local { - fn fmt_nest(&self, f: &mut std::fmt::Formatter<'_>, _level: usize) -> std::fmt::Result { - write!(f, "{}", self.symbol.content) - } -} - -impl_display_from_nested!(Local); -impl_locational!(Local, symbol); - -impl Local { - pub const fn new(symbol: Token) -> Self { - Self { symbol } - } - - pub fn static_dummy(name: &'static str) -> Self { - Self::new(Token::static_symbol(name)) - } - - pub fn dummy(name: &str) -> Self { - Self::new(Token::symbol(name)) - } - - pub fn dummy_with_line(name: &str, line: usize) -> Self { - Self::new(Token::new(TokenKind::Symbol, Str::rc(name), line, 0)) - } - - // &strにするとクローンしたいときにアロケーションコストがかかるので&Strのままで - pub const fn inspect(&self) -> &Str { - &self.symbol.content - } - - pub fn is_const(&self) -> bool { - self.symbol.inspect().chars().next().unwrap().is_uppercase() - } -} - -#[derive(Clone, Debug, PartialEq, Eq, Hash)] -pub struct Public { - pub dot: Token, - pub symbol: Token, -} - -impl NestedDisplay for Public { - fn fmt_nest(&self, f: &mut std::fmt::Formatter<'_>, _level: usize) -> std::fmt::Result { - write!(f, ".{}", self.symbol.content) - } -} - -impl_display_from_nested!(Public); -impl_locational!(Public, dot, symbol); - -impl Public { - pub const fn new(dot: Token, symbol: Token) -> Self { - Self { dot, symbol } - } - - pub fn dummy(name: &'static str) -> Self { - Self::new( - Token::from_str(TokenKind::Dot, "."), - Token::from_str(TokenKind::Symbol, name), - ) - } - - // &strにするとクローンしたいときにアロケーションコストがかかるので&Strのままで - pub const fn inspect(&self) -> &Str { - &self.symbol.content - } - - pub fn is_const(&self) -> bool { - self.symbol.inspect().chars().next().unwrap().is_uppercase() - } -} - #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub struct Attribute { pub obj: Box, - pub vis: Token, - pub name: Local, + pub ident: Identifier, } impl NestedDisplay for Attribute { fn fmt_nest(&self, f: &mut std::fmt::Formatter<'_>, _level: usize) -> std::fmt::Result { - write!(f, "({}){}{}", self.obj, self.vis.inspect(), self.name) + write!(f, "({}){}", self.obj, self.ident) } } impl_display_from_nested!(Attribute); -impl_locational!(Attribute, obj, name); +impl_locational!(Attribute, obj, ident); impl Attribute { - pub fn new(obj: Expr, vis: Token, name: Local) -> Self { + pub fn new(obj: Expr, ident: Identifier) -> Self { Self { obj: Box::new(obj), - vis, - name, + ident, } } } @@ -382,28 +301,27 @@ impl Subscript { #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub enum Accessor { - Local(Local), - Public(Public), + Ident(Identifier), Attr(Attribute), TupleAttr(TupleAttribute), Subscr(Subscript), } -impl_nested_display_for_enum!(Accessor; Local, Public, Attr, TupleAttr, Subscr); +impl_nested_display_for_enum!(Accessor; Ident, Attr, TupleAttr, Subscr); impl_display_from_nested!(Accessor); -impl_locational_for_enum!(Accessor; Local, Public, Attr, TupleAttr, Subscr); +impl_locational_for_enum!(Accessor; Ident Attr, TupleAttr, Subscr); impl Accessor { pub const fn local(symbol: Token) -> Self { - Self::Local(Local::new(symbol)) + Self::Ident(Identifier::new(None, VarName::new(symbol))) } pub const fn public(dot: Token, symbol: Token) -> Self { - Self::Public(Public::new(dot, symbol)) + Self::Ident(Identifier::new(Some(dot), VarName::new(symbol))) } - pub fn attr(obj: Expr, vis: Token, name: Local) -> Self { - Self::Attr(Attribute::new(obj, vis, name)) + pub fn attr(obj: Expr, ident: Identifier) -> Self { + Self::Attr(Attribute::new(obj, ident)) } pub fn tuple_attr(obj: Expr, index: Literal) -> Self { @@ -416,19 +334,17 @@ impl Accessor { pub const fn name(&self) -> Option<&Str> { match self { - Self::Local(local) => Some(local.inspect()), - Self::Public(local) => Some(local.inspect()), + Self::Ident(ident) => Some(ident.inspect()), _ => None, } } pub fn is_const(&self) -> bool { match self { - Self::Local(local) => local.is_const(), - Self::Public(public) => public.is_const(), + Self::Ident(ident) => ident.is_const(), Self::Subscr(subscr) => subscr.obj.is_const_acc(), Self::TupleAttr(attr) => attr.obj.is_const_acc(), - Self::Attr(attr) => attr.obj.is_const_acc() && attr.name.is_const(), + Self::Attr(attr) => attr.obj.is_const_acc() && attr.ident.is_const(), } } } @@ -494,7 +410,7 @@ pub struct ArrayComprehension { pub l_sqbr: Token, pub r_sqbr: Token, pub elem: Box, - pub generators: Vec<(Local, Expr)>, + pub generators: Vec<(Identifier, Expr)>, pub guards: Vec, } @@ -522,7 +438,7 @@ impl ArrayComprehension { l_sqbr: Token, r_sqbr: Token, elem: Expr, - generators: Vec<(Local, Expr)>, + generators: Vec<(Identifier, Expr)>, guards: Vec, ) -> Self { Self { @@ -1773,8 +1689,8 @@ pub struct Identifier { pub name: VarName, } -impl fmt::Display for Identifier { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { +impl NestedDisplay for Identifier { + fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, _level: usize) -> fmt::Result { match &self.dot { Some(_dot) => write!(f, ".{}", self.name), None => write!(f, "::{}", self.name), @@ -1782,6 +1698,8 @@ impl fmt::Display for Identifier { } } +impl_display_from_nested!(Identifier); + impl Locational for Identifier { fn loc(&self) -> Location { if let Some(dot) = &self.dot { diff --git a/compiler/erg_parser/desugar.rs b/compiler/erg_parser/desugar.rs index 3ff618cc..8842e749 100644 --- a/compiler/erg_parser/desugar.rs +++ b/compiler/erg_parser/desugar.rs @@ -12,7 +12,7 @@ use erg_common::{enum_unwrap, get_hash, set}; use crate::ast::{ Accessor, Args, Array, BinOp, Block, Call, DataPack, Def, DefBody, DefId, Expr, Identifier, - KwArg, Lambda, LambdaSignature, Literal, Local, Methods, Module, NormalArray, NormalRecord, + KwArg, Lambda, LambdaSignature, Literal, Methods, Module, NormalArray, NormalRecord, NormalTuple, ParamPattern, ParamSignature, Params, PosArg, Record, RecordAttrs, ShortenedRecord, Signature, SubrSignature, Tuple, TypeAscription, TypeBoundSpecs, TypeSpec, UnaryOp, VarName, VarPattern, VarRecordAttr, VarSignature, @@ -79,7 +79,7 @@ impl Desugarer { } else { self.gen_match_call(previous, def) }; - let param_name = enum_unwrap!(&call.args.pos_args().iter().next().unwrap().expr, Expr::Accessor:(Accessor::Local:(_))).inspect(); + let param_name = enum_unwrap!(&call.args.pos_args().iter().next().unwrap().expr, Expr::Accessor:(Accessor::Ident:(_))).inspect(); // FIXME: multiple params let param = VarName::new(Token::new( TokenKind::Symbol, @@ -279,12 +279,12 @@ impl Desugarer { Accessor::subscr(obj, Expr::Lit(Literal::nat(n, sig.ln_begin().unwrap()))) } BufIndex::Record(attr) => { + let ident = Identifier::new( + Some(Token::from_str(TokenKind::Dot, ".")), + VarName::new(Token::symbol_with_line(attr, sig.ln_begin().unwrap())), + ); // TODO: visibility - Accessor::attr( - obj, - Token::from_str(TokenKind::Dot, "."), - Local::dummy_with_line(attr, sig.ln_begin().unwrap()), - ) + Accessor::attr(obj, ident) } }; let id = DefId(get_hash(&(&acc, buf_name))); diff --git a/compiler/erg_parser/parse.rs b/compiler/erg_parser/parse.rs index 2ae1b79d..e38848f3 100644 --- a/compiler/erg_parser/parse.rs +++ b/compiler/erg_parser/parse.rs @@ -56,7 +56,7 @@ pub enum ArrayInner { WithLength(PosArg, Expr), Comprehension { elem: PosArg, - generators: Vec<(Local, Expr)>, + generators: Vec<(Identifier, Expr)>, guards: Vec, }, } @@ -408,8 +408,8 @@ impl Parser { let token = self.lpop(); match token.kind { Symbol => { - let attr = Local::new(token); - acc = Accessor::attr(Expr::Accessor(acc), vis, attr); + let ident = Identifier::new(Some(vis), VarName::new(token)); + acc = Accessor::attr(Expr::Accessor(acc), ident); } NatLit => { let attr = Literal::from(token); @@ -434,8 +434,8 @@ impl Parser { let token = self.lpop(); match token.kind { Symbol => { - let attr = Local::new(token); - acc = Accessor::attr(Expr::Accessor(acc), vis, attr); + let ident = Identifier::new(None, VarName::new(token)); + acc = Accessor::attr(Expr::Accessor(acc), ident); } // DataPack LBrace => { @@ -492,8 +492,8 @@ impl Parser { fn validate_const_expr(&mut self, expr: Expr) -> ParseResult { match expr { Expr::Lit(l) => Ok(ConstExpr::Lit(l)), - Expr::Accessor(Accessor::Local(local)) => { - let local = ConstLocal::new(local.symbol); + Expr::Accessor(Accessor::Ident(local)) => { + let local = ConstLocal::new(local.name.into_token()); Ok(ConstExpr::Accessor(ConstAccessor::Local(local))) } // TODO: App, Array, Record, BinOp, UnaryOp, @@ -744,8 +744,8 @@ impl Parser { // TODO: type specification debug_power_assert!(self.cur_is(Walrus)); self.skip(); - let kw = if let Accessor::Local(n) = acc { - n.symbol + let kw = if let Accessor::Ident(n) = acc { + n.name.into_token() } else { self.next_expr(); self.level -= 1; @@ -789,8 +789,8 @@ impl Parser { let acc = self.try_reduce_acc().map_err(|_| self.stack_dec())?; debug_power_assert!(self.cur_is(Walrus)); self.skip(); - let keyword = if let Accessor::Local(n) = acc { - n.symbol + let keyword = if let Accessor::Ident(n) = acc { + n.name.into_token() } else { self.next_expr(); self.level -= 1; @@ -984,7 +984,8 @@ impl Parser { let call = Call::new(obj, Some(ident), args); stack.push(ExprOrOp::Expr(Expr::Call(call))); } else { - let acc = Accessor::attr(obj, vis, Local::new(symbol)); + let ident = Identifier::new(None, VarName::new(symbol)); + let acc = Accessor::attr(obj, ident); stack.push(ExprOrOp::Expr(Expr::Accessor(acc))); } } @@ -1043,7 +1044,8 @@ impl Parser { let call = Call::new(obj, Some(ident), args); stack.push(ExprOrOp::Expr(Expr::Call(call))); } else { - let acc = Accessor::attr(obj, vis, Local::new(symbol)); + let ident = Identifier::new(Some(vis), VarName::new(symbol)); + let acc = Accessor::attr(obj, ident); stack.push(ExprOrOp::Expr(Expr::Accessor(acc))); } } @@ -1198,7 +1200,8 @@ impl Parser { let call = Call::new(obj, Some(ident), args); stack.push(ExprOrOp::Expr(Expr::Call(call))); } else { - let acc = Accessor::attr(obj, vis, Local::new(symbol)); + let ident = Identifier::new(Some(vis), VarName::new(symbol)); + let acc = Accessor::attr(obj, ident); stack.push(ExprOrOp::Expr(Expr::Accessor(acc))); } } @@ -1385,23 +1388,8 @@ impl Parser { if let Some(res) = self.opt_reduce_args() { let args = res.map_err(|_| self.stack_dec())?; let (obj, method_name) = match acc { - Accessor::Attr(attr) => { - if attr.vis.is(Dot) { - ( - *attr.obj, - Some(Identifier::new( - Some(attr.vis), - VarName::new(attr.name.symbol), - )), - ) - } else { - ( - *attr.obj, - Some(Identifier::new(None, VarName::new(attr.name.symbol))), - ) - } - } - Accessor::Local(local) => (Expr::Accessor(Accessor::Local(local)), None), + Accessor::Attr(attr) => (*attr.obj, Some(attr.ident)), + Accessor::Ident(ident) => (Expr::Accessor(Accessor::Ident(ident)), None), _ => todo!(), }; let call = Call::new(obj, method_name, args); @@ -1547,10 +1535,7 @@ impl Parser { ) -> ParseResult { debug_call_info!(self); let first = match first { - Accessor::Local(local) => Identifier::new(None, VarName::new(local.symbol)), - Accessor::Public(public) => { - Identifier::new(Some(public.dot), VarName::new(public.symbol)) - } + Accessor::Ident(ident) => ident, other => todo!("{other}"), // syntax error }; let mut idents = vec![first]; @@ -1577,10 +1562,7 @@ impl Parser { Some(_) => { let acc = self.try_reduce_acc().map_err(|_| self.stack_dec())?; let acc = match acc { - Accessor::Local(local) => Identifier::new(None, VarName::new(local.symbol)), - Accessor::Public(public) => { - Identifier::new(Some(public.dot), VarName::new(public.symbol)) - } + Accessor::Ident(ident) => ident, other => todo!("{other}"), // syntax error }; idents.push(acc); @@ -1716,16 +1698,8 @@ impl Parser { fn convert_accessor_to_var_sig(&mut self, _accessor: Accessor) -> ParseResult { debug_call_info!(self); match _accessor { - Accessor::Local(local) => { - let pat = VarPattern::Ident(Identifier::new(None, VarName::new(local.symbol))); - self.level -= 1; - Ok(VarSignature::new(pat, None)) - } - Accessor::Public(public) => { - let pat = VarPattern::Ident(Identifier::new( - Some(public.dot), - VarName::new(public.symbol), - )); + Accessor::Ident(ident) => { + let pat = VarPattern::Ident(ident); self.level -= 1; Ok(VarSignature::new(pat, None)) } @@ -1866,10 +1840,7 @@ impl Parser { fn convert_accessor_to_ident(&mut self, _accessor: Accessor) -> ParseResult { debug_call_info!(self); let ident = match _accessor { - Accessor::Local(local) => Identifier::new(None, VarName::new(local.symbol)), - Accessor::Public(public) => { - Identifier::new(Some(public.dot), VarName::new(public.symbol)) - } + Accessor::Ident(ident) => ident, other => { self.level -= 1; let err = ParseError::simple_syntax_error(line!() as usize, other.loc()); @@ -1922,15 +1893,15 @@ impl Parser { ) -> ParseResult { debug_call_info!(self); match expr { - Expr::Accessor(Accessor::Local(local)) => { - if &local.inspect()[..] == "self" && !allow_self { + Expr::Accessor(Accessor::Ident(ident)) => { + if &ident.inspect()[..] == "self" && !allow_self { self.level -= 1; - let err = ParseError::simple_syntax_error(line!() as usize, local.loc()); + let err = ParseError::simple_syntax_error(line!() as usize, ident.loc()); self.errs.push(err); return Err(()); } - let name = VarName::new(local.symbol); - let pat = ParamPattern::VarName(name); + // FIXME deny: public + let pat = ParamPattern::VarName(ident.name); let param = ParamSignature::new(pat, None, None); self.level -= 1; Ok(param) @@ -1978,18 +1949,18 @@ impl Parser { Expr::UnaryOp(unary) => match unary.op.kind { TokenKind::RefOp => { let var = unary.args.into_iter().next().unwrap(); - let var = option_enum_unwrap!(*var, Expr::Accessor:(Accessor::Local:(_))) + let var = option_enum_unwrap!(*var, Expr::Accessor:(Accessor::Ident:(_))) .unwrap_or_else(|| todo!()); - let pat = ParamPattern::Ref(VarName::new(var.symbol)); + let pat = ParamPattern::Ref(var.name); let param = ParamSignature::new(pat, None, None); self.level -= 1; Ok(param) } TokenKind::RefMutOp => { let var = unary.args.into_iter().next().unwrap(); - let var = option_enum_unwrap!(*var, Expr::Accessor:(Accessor::Local:(_))) + let var = option_enum_unwrap!(*var, Expr::Accessor:(Accessor::Ident:(_))) .unwrap_or_else(|| todo!()); - let pat = ParamPattern::RefMut(VarName::new(var.symbol)); + let pat = ParamPattern::RefMut(var.name); let param = ParamSignature::new(pat, None, None); self.level -= 1; Ok(param) @@ -2201,10 +2172,9 @@ impl Parser { ) -> ParseResult { debug_call_info!(self); let t_spec = match accessor { - Accessor::Local(local) => PreDeclTypeSpec::Simple(SimpleTypeSpec::new( - VarName::new(local.symbol), - ConstArgs::empty(), - )), + Accessor::Ident(ident) => { + PreDeclTypeSpec::Simple(SimpleTypeSpec::new(ident.name, ConstArgs::empty())) + } other => todo!("{other}"), }; self.level -= 1; From d986750a6636757e0742fb8930b9b8f327747f28 Mon Sep 17 00:00:00 2001 From: Shunsuke Shibayama Date: Sat, 10 Sep 2022 15:10:55 +0900 Subject: [PATCH 63/68] Fix error handling bugs --- compiler/erg_common/error.rs | 1 + compiler/erg_compiler/context/inquire.rs | 45 +++++++++++--------- compiler/erg_compiler/context/register.rs | 32 +++++--------- compiler/erg_compiler/error.rs | 2 +- compiler/erg_compiler/lower.rs | 52 +++++++++++------------ 5 files changed, 65 insertions(+), 67 deletions(-) diff --git a/compiler/erg_common/error.rs b/compiler/erg_common/error.rs index 93802f0b..1e6a0e8f 100644 --- a/compiler/erg_common/error.rs +++ b/compiler/erg_common/error.rs @@ -37,6 +37,7 @@ pub enum ErrorKind { MoveError, NotConstExpr, InheritanceError, + VisibilityError, DummyError, /* compile warnings */ AttributeWarning = 60, diff --git a/compiler/erg_compiler/context/inquire.rs b/compiler/erg_compiler/context/inquire.rs index d9a7c949..90a2971d 100644 --- a/compiler/erg_compiler/context/inquire.rs +++ b/compiler/erg_compiler/context/inquire.rs @@ -199,7 +199,7 @@ impl Context { pub(crate) fn rec_get_var_t(&self, ident: &Identifier, namespace: &Str) -> TyCheckResult { if let Some(vi) = self.get_current_scope_var(&ident.inspect()[..]) { - // self.validate_visibility(ident, vi, self)?; + self.validate_visibility(ident, vi, namespace)?; Ok(vi.t()) } else { if let Some(parent) = self.outer.as_ref() { @@ -233,16 +233,28 @@ impl Context { } } if let Some(singular_ctx) = self.rec_get_singular_ctx(obj) { - if let Ok(t) = singular_ctx.rec_get_var_t(ident, namespace) { - return Ok(t); + match singular_ctx.rec_get_var_t(ident, namespace) { + Ok(t) => { + return Ok(t); + } + Err(e) if e.core.kind == ErrorKind::NameError => {} + Err(e) => { + return Err(e); + } } } for (_, ctx) in self .rec_get_nominal_super_type_ctxs(&self_t) .ok_or_else(|| todo!())? { - if let Ok(t) = ctx.rec_get_var_t(ident, namespace) { - return Ok(t); + match ctx.rec_get_var_t(ident, namespace) { + Ok(t) => { + return Ok(t); + } + Err(e) if e.core.kind == ErrorKind::NameError => {} + Err(e) => { + return Err(e); + } } } // TODO: dependent type widening @@ -340,7 +352,7 @@ impl Context { .get(method_name.inspect()) .or_else(|| ctx.decls.get(method_name.inspect())) { - self.validate_visibility(method_name, vi, ctx)?; + self.validate_visibility(method_name, vi, namespace)?; return Ok(vi.t()); } for (_, methods_ctx) in ctx.method_defs.iter() { @@ -349,7 +361,7 @@ impl Context { .get(method_name.inspect()) .or_else(|| methods_ctx.decls.get(method_name.inspect())) { - self.validate_visibility(method_name, vi, ctx)?; + self.validate_visibility(method_name, vi, namespace)?; return Ok(vi.t()); } } @@ -360,7 +372,7 @@ impl Context { .get(method_name.inspect()) .or_else(|| singular_ctx.decls.get(method_name.inspect())) { - self.validate_visibility(method_name, vi, singular_ctx)?; + self.validate_visibility(method_name, vi, namespace)?; return Ok(vi.t()); } for (_, method_ctx) in singular_ctx.method_defs.iter() { @@ -369,7 +381,7 @@ impl Context { .get(method_name.inspect()) .or_else(|| method_ctx.decls.get(method_name.inspect())) { - self.validate_visibility(method_name, vi, singular_ctx)?; + self.validate_visibility(method_name, vi, namespace)?; return Ok(vi.t()); } } @@ -401,7 +413,7 @@ impl Context { &self, ident: &Identifier, vi: &VarInfo, - ctx: &Context, + namespace: &str, ) -> TyCheckResult<()> { if ident.vis() != vi.vis { Err(TyCheckError::visibility_error( @@ -413,13 +425,9 @@ impl Context { )) // check if the private variable is loaded from the other scope } else if vi.vis.is_private() - && self - .outer - .as_ref() - // TODO: also split with `.` - .map(|outer| outer.name.split("::")) - .map(|mut names| names.all(|name| name != &ctx.name[..])) - .unwrap_or(true) + && &self.name[..] != "" + && &self.name[..] != namespace + && !namespace.contains(&self.name[..]) { Err(TyCheckError::visibility_error( line!() as usize, @@ -1345,8 +1353,7 @@ impl Context { pub(crate) fn get_self_t(&self) -> Type { if self.kind.is_method_def() || self.kind.is_type() { // TODO: poly type - let name = self.name.split("::").last().unwrap(); - let name = name.split(".").last().unwrap(); + let name = self.name.split(&[':', '.']).last().unwrap(); let mono_t = mono(Str::rc(name)); if let Some((t, _)) = self.rec_get_nominal_type_ctx(&mono_t) { t.clone() diff --git a/compiler/erg_compiler/context/register.rs b/compiler/erg_compiler/context/register.rs index 2fd2e315..37ee0bb2 100644 --- a/compiler/erg_compiler/context/register.rs +++ b/compiler/erg_compiler/context/register.rs @@ -55,32 +55,22 @@ impl Context { let muty = Mutability::from(&sig.inspect().unwrap()[..]); match &sig.pat { ast::VarPattern::Ident(ident) => { - if sig.t_spec.is_none() && opt_t.is_none() { - Err(TyCheckError::no_type_spec_error( + if self.registered(ident.inspect(), ident.is_const()) { + return Err(TyCheckError::duplicate_decl_error( line!() as usize, sig.loc(), self.caused_by(), ident.inspect(), - )) - } else { - if self.registered(ident.inspect(), ident.is_const()) { - return Err(TyCheckError::duplicate_decl_error( - line!() as usize, - sig.loc(), - self.caused_by(), - ident.inspect(), - )); - } - let vis = ident.vis(); - let kind = id.map_or(VarKind::Declared, VarKind::Defined); - let sig_t = - self.instantiate_var_sig_t(sig.t_spec.as_ref(), opt_t, PreRegister)?; - self.decls.insert( - ident.name.clone(), - VarInfo::new(sig_t, muty, vis, kind, None), - ); - Ok(()) + )); } + let vis = ident.vis(); + let kind = id.map_or(VarKind::Declared, VarKind::Defined); + let sig_t = self.instantiate_var_sig_t(sig.t_spec.as_ref(), opt_t, PreRegister)?; + self.decls.insert( + ident.name.clone(), + VarInfo::new(sig_t, muty, vis, kind, None), + ); + Ok(()) } _ => todo!(), } diff --git a/compiler/erg_compiler/error.rs b/compiler/erg_compiler/error.rs index 01a523d6..a05c60da 100644 --- a/compiler/erg_compiler/error.rs +++ b/compiler/erg_compiler/error.rs @@ -1034,7 +1034,7 @@ passed keyword args: {RED}{kw_args_len}{RESET}" Self::new( ErrorCore::new( errno, - NameError, + VisibilityError, loc, switch_lang!( "japanese" => format!("{RED}{name}{RESET}は{visibility}変数です"), diff --git a/compiler/erg_compiler/lower.rs b/compiler/erg_compiler/lower.rs index b12f8db8..ef182c04 100644 --- a/compiler/erg_compiler/lower.rs +++ b/compiler/erg_compiler/lower.rs @@ -261,7 +261,10 @@ impl ASTLowerer { hir::Record::new(record.l_brace, record.r_brace, hir::RecordAttrs::empty()); self.ctx.grow("", ContextKind::Dummy, Private)?; for attr in record.attrs.into_iter() { - let attr = self.lower_def(attr)?; + let attr = self.lower_def(attr).map_err(|e| { + self.pop_append_errs(); + e + })?; hir_record.push(attr); } self.pop_append_errs(); @@ -271,21 +274,6 @@ impl ASTLowerer { fn lower_acc(&mut self, acc: ast::Accessor) -> LowerResult { log!(info "entered {}({acc})", fn_name!()); match acc { - /*ast::Accessor::Local(local) => { - // `match` is an untypable special form - // `match`は型付け不可能な特殊形式 - let (t, __name__) = if &local.inspect()[..] == "match" { - (Type::Failure, None) - } else { - ( - self.ctx - .rec_get_var_t(&local.symbol, &self.ctx.name)?, - self.ctx.get_local_uniq_obj_name(&local.symbol), - ) - }; - let acc = hir::Accessor::Local(hir::Local::new(local.symbol, __name__, t)); - Ok(acc) - }*/ ast::Accessor::Ident(ident) => { let ident = self.lower_ident(ident)?; let acc = hir::Accessor::Ident(ident); @@ -324,6 +312,8 @@ impl ASTLowerer { } fn lower_ident(&self, ident: ast::Identifier) -> LowerResult { + // `match` is an untypable special form + // `match`は型付け不可能な特殊形式 let (t, __name__) = if ident.vis().is_private() && &ident.inspect()[..] == "match" { (Type::Failure, None) } else { @@ -491,20 +481,24 @@ impl ASTLowerer { fn lower_def(&mut self, def: ast::Def) -> LowerResult { log!(info "entered {}({})", fn_name!(), def.sig); - if let Some(name) = def.sig.name_as_str() { - self.ctx.grow(name, ContextKind::Instant, Private)?; + if def.body.block.len() >= 1 { + let name = if let Some(name) = def.sig.name_as_str() { + name + } else { + "" + }; + self.ctx.grow(name, ContextKind::Instant, def.sig.vis())?; let res = match def.sig { ast::Signature::Subr(sig) => self.lower_subr_def(sig, def.body), ast::Signature::Var(sig) => self.lower_var_def(sig, def.body), }; // TODO: Context上の関数に型境界情報を追加 self.pop_append_errs(); - res - } else { - match def.sig { - ast::Signature::Subr(sig) => self.lower_subr_def(sig, def.body), - ast::Signature::Var(sig) => self.lower_var_def(sig, def.body), - } + return res; + } + match def.sig { + ast::Signature::Subr(sig) => self.lower_subr_def(sig, def.body), + ast::Signature::Var(sig) => self.lower_var_def(sig, def.body), } } @@ -626,10 +620,16 @@ impl ASTLowerer { def.sig.ln_begin().unwrap(), def.sig.col_begin().unwrap(), )); - let def = self.lower_def(def)?; + let def = self.lower_def(def).map_err(|e| { + self.pop_append_errs(); + e + })?; public_methods.push(def); } else { - let def = self.lower_def(def)?; + let def = self.lower_def(def).map_err(|e| { + self.pop_append_errs(); + e + })?; private_methods.push(def); } } From ec307951c3107da352e5f3787e438aa45ce745c9 Mon Sep 17 00:00:00 2001 From: Shunsuke Shibayama Date: Sat, 10 Sep 2022 15:10:59 +0900 Subject: [PATCH 64/68] Update test.rs --- compiler/erg_compiler/tests/test.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/erg_compiler/tests/test.rs b/compiler/erg_compiler/tests/test.rs index 68ec1f99..a137e2eb 100644 --- a/compiler/erg_compiler/tests/test.rs +++ b/compiler/erg_compiler/tests/test.rs @@ -17,14 +17,14 @@ fn test_instantiation_and_generalization() -> Result<(), ()> { /* #[test] fn test_resolve_trait() -> Result<(), ()> { - let context = Context::new_root_module(); + let context = Context::new_main_module(); context.test_resolve_trait()?; Ok(()) } #[test] fn test_resolve_trait_inner1() -> Result<(), ()> { - let context = Context::new_root_module(); + let context = Context::new_main_module(); context.test_resolve_trait_inner1()?; Ok(()) } From c5f2d816afc2f842d56228899d52f046eb0e83fa Mon Sep 17 00:00:00 2001 From: Shunsuke Shibayama Date: Sat, 10 Sep 2022 16:32:03 +0900 Subject: [PATCH 65/68] Impl const accessing attributes --- compiler/erg_compiler/context/eval.rs | 74 +++++++++++++++-------- compiler/erg_compiler/context/register.rs | 20 +++--- compiler/erg_compiler/lower.rs | 12 ++-- compiler/erg_parser/ast.rs | 11 ++++ compiler/erg_type/value.rs | 20 ++++++ 5 files changed, 97 insertions(+), 40 deletions(-) diff --git a/compiler/erg_compiler/context/eval.rs b/compiler/erg_compiler/context/eval.rs index 9f37ab12..240dbb36 100644 --- a/compiler/erg_compiler/context/eval.rs +++ b/compiler/erg_compiler/context/eval.rs @@ -188,31 +188,58 @@ impl Context { } } Accessor::Attr(attr) => { - let _obj = self.eval_const_expr(&attr.obj, None); - todo!() + let obj = self.eval_const_expr(&attr.obj, None)?; + self.eval_attr(obj, &attr.ident) } _ => todo!(), } } + fn eval_attr(&self, obj: ValueObj, ident: &Identifier) -> EvalResult { + match obj.try_get_attr(&Field::from(ident)) { + Some(val) => { + return Ok(val); + } + _ => {} + } + match &obj { + ValueObj::Type(t) => { + if let Some(sups) = self.rec_get_nominal_super_type_ctxs(t.typ()) { + for (_, ctx) in sups { + if let Some(val) = ctx.consts.get(ident.inspect()) { + return Ok(val.clone()); + } + for (_, methods) in ctx.method_defs.iter() { + if let Some(v) = methods.consts.get(ident.inspect()) { + return Ok(v.clone()); + } + } + } + } + } + _ => {} + } + Err(EvalError::no_attr_error( + line!() as usize, + ident.loc(), + self.caused_by(), + &obj.t(), + ident.inspect(), + None, + )) + } + fn eval_const_bin(&self, bin: &BinOp) -> EvalResult { - match (bin.args[0].as_ref(), bin.args[1].as_ref()) { - (Expr::Lit(l), Expr::Lit(r)) => { - let op = try_get_op_kind_from_token(bin.op.kind)?; - self.eval_bin_lit(op, eval_lit(l), eval_lit(r)) - } - _ => todo!(), - } + let lhs = self.eval_const_expr(&bin.args[0], None)?; + let rhs = self.eval_const_expr(&bin.args[1], None)?; + let op = try_get_op_kind_from_token(bin.op.kind)?; + self.eval_bin(op, lhs, rhs) } fn eval_const_unary(&self, unary: &UnaryOp) -> EvalResult { - match unary.args[0].as_ref() { - Expr::Lit(lit) => { - let op = try_get_op_kind_from_token(unary.op.kind)?; - self.eval_unary_lit(op, eval_lit(lit)) - } - _ => todo!(), - } + let val = self.eval_const_expr(&unary.args[0], None)?; + let op = try_get_op_kind_from_token(unary.op.kind)?; + self.eval_unary(op, val) } fn eval_args(&self, args: &Args, __name__: Option<&Str>) -> EvalResult { @@ -269,8 +296,7 @@ impl Context { if def.is_const() { let __name__ = def.sig.ident().map(|i| i.inspect()).unwrap(); let obj = self.eval_const_block(&def.body.block, Some(__name__))?; - erg_common::log!(); - self.register_gen_const(__name__, obj); + self.register_gen_const(def.sig.ident().unwrap(), obj); Ok(ValueObj::None) } else { Err(EvalError::not_const_expr( @@ -373,7 +399,7 @@ impl Context { self.eval_const_chunk(block.last().unwrap(), __name__) } - fn eval_bin_lit(&self, op: OpKind, lhs: ValueObj, rhs: ValueObj) -> EvalResult { + fn eval_bin(&self, op: OpKind, lhs: ValueObj, rhs: ValueObj) -> EvalResult { match op { Add => lhs .try_add(rhs) @@ -411,10 +437,10 @@ impl Context { ) -> EvalResult { match (lhs, rhs) { (TyParam::Value(ValueObj::Mut(lhs)), TyParam::Value(rhs)) => self - .eval_bin_lit(op, lhs.borrow().clone(), rhs.clone()) + .eval_bin(op, lhs.borrow().clone(), rhs.clone()) .map(|v| TyParam::Value(ValueObj::Mut(RcCell::new(v)))), (TyParam::Value(lhs), TyParam::Value(rhs)) => self - .eval_bin_lit(op, lhs.clone(), rhs.clone()) + .eval_bin(op, lhs.clone(), rhs.clone()) .map(TyParam::value), (TyParam::FreeVar(fv), r) => { if fv.is_linked() { @@ -435,7 +461,7 @@ impl Context { } } - fn eval_unary_lit(&self, op: OpKind, val: ValueObj) -> EvalResult { + fn eval_unary(&self, op: OpKind, val: ValueObj) -> EvalResult { match op { Pos => todo!(), Neg => todo!(), @@ -447,9 +473,7 @@ impl Context { fn eval_unary_tp(&self, op: OpKind, val: &TyParam) -> EvalResult { match val { - TyParam::Value(c) => self - .eval_unary_lit(op, c.clone()) - .map(|v| TyParam::Value(v)), + TyParam::Value(c) => self.eval_unary(op, c.clone()).map(|v| TyParam::Value(v)), TyParam::FreeVar(fv) if fv.is_linked() => self.eval_unary_tp(op, &*fv.crack()), e @ TyParam::Erased(_) => Ok(e.clone()), other => todo!("{op} {other}"), diff --git a/compiler/erg_compiler/context/register.rs b/compiler/erg_compiler/context/register.rs index 37ee0bb2..3827ba03 100644 --- a/compiler/erg_compiler/context/register.rs +++ b/compiler/erg_compiler/context/register.rs @@ -6,7 +6,7 @@ use erg_common::Str; use erg_common::{enum_unwrap, get_hash, log, set}; use erg_type::free::HasLevel; -use ast::{DefId, VarName}; +use ast::{DefId, Identifier, VarName}; use erg_parser::ast; use erg_type::constructors::{enum_t, func, func1, proc, ref_, ref_mut}; @@ -469,7 +469,7 @@ impl Context { let spec_t = self.instantiate_typespec(spec, PreRegister)?; self.sub_unify(&const_t, &spec_t, Some(def.body.loc()), None, None)?; } - self.register_gen_const(__name__.unwrap(), obj); + self.register_gen_const(def.sig.ident().unwrap(), obj); } else { let opt_ret_t = if let Some(spec) = sig.return_t_spec.as_ref() { let spec_t = self.instantiate_typespec(spec, PreRegister)?; @@ -491,7 +491,7 @@ impl Context { let spec_t = self.instantiate_typespec(spec, PreRegister)?; self.sub_unify(&const_t, &spec_t, Some(def.body.loc()), None, None)?; } - self.register_gen_const(__name__.unwrap(), obj); + self.register_gen_const(sig.ident().unwrap(), obj); } _ => {} } @@ -553,9 +553,9 @@ impl Context { } } - pub(crate) fn register_gen_const(&mut self, name: &Str, obj: ValueObj) { - if self.rec_get_const_obj(name).is_some() { - panic!("already registered: {name}"); + pub(crate) fn register_gen_const(&mut self, ident: &Identifier, obj: ValueObj) { + if self.rec_get_const_obj(ident.inspect()).is_some() { + panic!("already registered: {ident}"); } else { match obj { ValueObj::Type(t) => { @@ -564,16 +564,16 @@ impl Context { } // TODO: not all value objects are comparable other => { - let id = DefId(get_hash(name)); + let id = DefId(get_hash(ident)); let vi = VarInfo::new( enum_t(set! {other.clone()}), Const, - Private, + ident.vis(), VarKind::Defined(id), None, ); - self.consts.insert(VarName::from_str(Str::rc(name)), other); - self.locals.insert(VarName::from_str(Str::rc(name)), vi); + self.consts.insert(ident.name.clone(), other); + self.locals.insert(ident.name.clone(), vi); } } } diff --git a/compiler/erg_compiler/lower.rs b/compiler/erg_compiler/lower.rs index ef182c04..046f49ff 100644 --- a/compiler/erg_compiler/lower.rs +++ b/compiler/erg_compiler/lower.rs @@ -603,16 +603,13 @@ impl ASTLowerer { 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() { + for mut methods in class_def.methods_list.into_iter() { let class = self .ctx .instantiate_typespec(&methods.class, RegistrationMode::Normal)?; self.ctx .grow(&class.name(), ContextKind::MethodDefs, Private)?; - for def in methods.defs.iter() { - self.ctx.preregister_def(def)?; - } - for mut def in methods.defs.into_iter() { + for def in methods.defs.iter_mut() { if methods.vis.is(TokenKind::Dot) { def.sig.ident_mut().unwrap().dot = Some(Token::new( TokenKind::Dot, @@ -620,6 +617,11 @@ impl ASTLowerer { def.sig.ln_begin().unwrap(), def.sig.col_begin().unwrap(), )); + } + self.ctx.preregister_def(def)?; + } + for def in methods.defs.into_iter() { + if methods.vis.is(TokenKind::Dot) { let def = self.lower_def(def).map_err(|e| { self.pop_append_errs(); e diff --git a/compiler/erg_parser/ast.rs b/compiler/erg_parser/ast.rs index 5b8add5b..5e309b3f 100644 --- a/compiler/erg_parser/ast.rs +++ b/compiler/erg_parser/ast.rs @@ -597,6 +597,10 @@ impl RecordAttrs { self.0.iter() } + pub fn iter_mut(&mut self) -> impl Iterator { + self.0.iter_mut() + } + pub fn into_iter(self) -> impl IntoIterator { self.0.into_iter() } @@ -2042,6 +2046,13 @@ impl VarSignature { pub const fn vis(&self) -> Visibility { self.pat.vis() } + + pub fn ident(&self) -> Option<&Identifier> { + match &self.pat { + VarPattern::Ident(ident) => Some(ident), + _ => None, + } + } } #[derive(Clone, Debug, PartialEq, Eq, Hash)] diff --git a/compiler/erg_type/value.rs b/compiler/erg_type/value.rs index 8954e348..704e0a29 100644 --- a/compiler/erg_type/value.rs +++ b/compiler/erg_type/value.rs @@ -746,6 +746,26 @@ impl ValueObj { _ => None, } } + + pub fn try_get_attr(&self, attr: &Field) -> Option { + match self { + Self::Type(typ) => match typ { + TypeObj::Builtin(builtin) => todo!("{builtin}{attr}"), + TypeObj::Generated(gen) => match &gen.t { + Type::Record(rec) => { + let t = rec.get(attr)?; + Some(ValueObj::builtin_t(t.clone())) + } + _ => None, + }, + }, + Self::Record(rec) => { + let v = rec.get(attr)?; + Some(v.clone()) + } + _ => None, + } + } } pub mod value_set { From 048e2812680e12b56eb66f82c32231926c1fda4b Mon Sep 17 00:00:00 2001 From: Shunsuke Shibayama Date: Sat, 10 Sep 2022 17:17:51 +0900 Subject: [PATCH 66/68] Refactor: method_defs -> methods_list --- compiler/erg_compiler/context/eval.rs | 2 +- .../erg_compiler/context/initialize/mod.rs | 2 +- compiler/erg_compiler/context/inquire.rs | 28 +++++++++++-------- compiler/erg_compiler/context/mod.rs | 4 +-- compiler/erg_compiler/context/register.rs | 10 +++---- compiler/erg_compiler/lower.rs | 4 +-- 6 files changed, 28 insertions(+), 22 deletions(-) diff --git a/compiler/erg_compiler/context/eval.rs b/compiler/erg_compiler/context/eval.rs index 240dbb36..7ee818bc 100644 --- a/compiler/erg_compiler/context/eval.rs +++ b/compiler/erg_compiler/context/eval.rs @@ -209,7 +209,7 @@ impl Context { if let Some(val) = ctx.consts.get(ident.inspect()) { return Ok(val.clone()); } - for (_, methods) in ctx.method_defs.iter() { + for (_, methods) in ctx.methods_list.iter() { if let Some(v) = methods.consts.get(ident.inspect()) { return Ok(v.clone()); } diff --git a/compiler/erg_compiler/context/initialize/mod.rs b/compiler/erg_compiler/context/initialize/mod.rs index 689e30f7..b4294cc0 100644 --- a/compiler/erg_compiler/context/initialize/mod.rs +++ b/compiler/erg_compiler/context/initialize/mod.rs @@ -114,7 +114,7 @@ impl Context { let t = Self::instantiate_t(t, &mut tv_ctx); // FIXME: panic if let Some((_, root_ctx)) = self.poly_types.get_mut(&t.name()) { - root_ctx.method_defs.push((t, ctx)); + root_ctx.methods_list.push((t, ctx)); } else { let name = VarName::from_str(t.name()); self.locals.insert( diff --git a/compiler/erg_compiler/context/inquire.rs b/compiler/erg_compiler/context/inquire.rs index 90a2971d..b31fd980 100644 --- a/compiler/erg_compiler/context/inquire.rs +++ b/compiler/erg_compiler/context/inquire.rs @@ -71,8 +71,8 @@ impl Context { .map(|(_, vi)| vi) }) .or_else(|| { - for (_, def) in self.method_defs.iter() { - if let Some(vi) = def.get_current_scope_var(name) { + for (_, methods) in self.methods_list.iter() { + if let Some(vi) = methods.get_current_scope_var(name) { return Some(vi); } } @@ -355,7 +355,7 @@ impl Context { self.validate_visibility(method_name, vi, namespace)?; return Ok(vi.t()); } - for (_, methods_ctx) in ctx.method_defs.iter() { + for (_, methods_ctx) in ctx.methods_list.iter() { if let Some(vi) = methods_ctx .locals .get(method_name.inspect()) @@ -375,7 +375,7 @@ impl Context { self.validate_visibility(method_name, vi, namespace)?; return Ok(vi.t()); } - for (_, method_ctx) in singular_ctx.method_defs.iter() { + for (_, method_ctx) in singular_ctx.methods_list.iter() { if let Some(vi) = method_ctx .locals .get(method_name.inspect()) @@ -1332,8 +1332,14 @@ impl Context { // rec_get_const_localとは違い、位置情報を持たないしエラーとならない pub(crate) fn rec_get_const_obj(&self, name: &str) -> Option<&ValueObj> { if let Some(val) = self.consts.get(name) { - Some(val) - } else if let Some(outer) = &self.outer { + return Some(val); + } + for (_, ctx) in self.methods_list.iter() { + if let Some(val) = ctx.consts.get(name) { + return Some(val); + } + } + if let Some(outer) = &self.outer { outer.rec_get_const_obj(name) } else { None @@ -1350,21 +1356,21 @@ impl Context { } } - pub(crate) fn get_self_t(&self) -> Type { + pub(crate) fn rec_get_self_t(&self) -> Option { if self.kind.is_method_def() || self.kind.is_type() { // TODO: poly type let name = self.name.split(&[':', '.']).last().unwrap(); let mono_t = mono(Str::rc(name)); if let Some((t, _)) = self.rec_get_nominal_type_ctx(&mono_t) { - t.clone() + Some(t.clone()) } else { - todo!("{mono_t}") + None } } else { if let Some(outer) = &self.outer { - outer.get_self_t() + outer.rec_get_self_t() } else { - todo!() + None } } } diff --git a/compiler/erg_compiler/context/mod.rs b/compiler/erg_compiler/context/mod.rs index 038f0cfa..34f1fdd8 100644 --- a/compiler/erg_compiler/context/mod.rs +++ b/compiler/erg_compiler/context/mod.rs @@ -252,7 +252,7 @@ pub struct Context { pub(crate) super_traits: Vec, // if self is not a trait, means implemented traits // method definitions, if the context is a type // specializations are included and needs to be separated out - pub(crate) method_defs: Vec<(Type, Context)>, + pub(crate) methods_list: Vec<(Type, Context)>, /// K: method name, V: impl patch /// Provided methods can switch implementations on a scope-by-scope basis /// K: メソッド名, V: それを実装するパッチたち @@ -378,7 +378,7 @@ impl Context { outer: outer.map(Box::new), super_classes, super_traits, - method_defs: vec![], + methods_list: vec![], const_param_defaults: Dict::default(), method_impl_patches: Dict::default(), trait_impls: Dict::default(), diff --git a/compiler/erg_compiler/context/register.rs b/compiler/erg_compiler/context/register.rs index 3827ba03..affbb9ef 100644 --- a/compiler/erg_compiler/context/register.rs +++ b/compiler/erg_compiler/context/register.rs @@ -177,7 +177,7 @@ impl Context { // ok, not defined let spec_t = self.instantiate_param_sig_t(sig, opt_decl_t, Normal)?; if &name.inspect()[..] == "self" { - let self_t = self.get_self_t(); + let self_t = self.rec_get_self_t().unwrap(); self.sub_unify( &spec_t, &self_t, @@ -217,7 +217,7 @@ impl Context { // ok, not defined let spec_t = self.instantiate_param_sig_t(sig, opt_decl_t, Normal)?; if &name.inspect()[..] == "self" { - let self_t = self.get_self_t(); + let self_t = self.rec_get_self_t().unwrap(); self.sub_unify( &spec_t, &self_t, @@ -258,7 +258,7 @@ impl Context { // ok, not defined let spec_t = self.instantiate_param_sig_t(sig, opt_decl_t, Normal)?; if &name.inspect()[..] == "self" { - let self_t = self.get_self_t(); + let self_t = self.rec_get_self_t().unwrap(); self.sub_unify( &spec_t, &self_t, @@ -591,7 +591,7 @@ impl Context { methods.register_fixed_auto_impl("__new__", new_t.clone(), Immutable, Private); // 必要なら、ユーザーが独自に上書きする methods.register_auto_impl("new", new_t, Immutable, Public); - ctx.method_defs.push((gen.t.clone(), methods)); + ctx.methods_list.push((gen.t.clone(), methods)); self.register_gen_mono_type(gen, ctx, Const); } else { todo!() @@ -626,7 +626,7 @@ impl Context { ); // 必要なら、ユーザーが独自に上書きする methods.register_auto_impl("new", new_t, Immutable, Public); - ctx.method_defs.push((gen.t.clone(), methods)); + ctx.methods_list.push((gen.t.clone(), methods)); self.register_gen_mono_type(gen, ctx, Const); } else { todo!("super class not found") diff --git a/compiler/erg_compiler/lower.rs b/compiler/erg_compiler/lower.rs index 046f49ff..ea98908a 100644 --- a/compiler/erg_compiler/lower.rs +++ b/compiler/erg_compiler/lower.rs @@ -640,7 +640,7 @@ impl ASTLowerer { self.check_override(&class, &methods); if let Some((_, class_root)) = self.ctx.rec_get_mut_nominal_type_ctx(&class) { for (newly_defined_name, _vi) in methods.locals.iter() { - for (_, already_defined_methods) in class_root.method_defs.iter_mut() { + for (_, already_defined_methods) in class_root.methods_list.iter_mut() { // TODO: 特殊化なら同じ名前でもOK // TODO: 定義のメソッドもエラー表示 if let Some((_already_defined_name, already_defined_vi)) = @@ -662,7 +662,7 @@ impl ASTLowerer { } } } - class_root.method_defs.push((class, methods)); + class_root.methods_list.push((class, methods)); } else { todo!() } From fe969299d7aeae086b00e8b235460ded2b725a18 Mon Sep 17 00:00:00 2001 From: Shunsuke Shibayama Date: Sat, 10 Sep 2022 17:52:03 +0900 Subject: [PATCH 67/68] Omit class names in member access --- compiler/erg_compiler/codegen.rs | 20 ++++++++++++++++++-- compiler/erg_compiler/context/inquire.rs | 16 +++++++++++++++- compiler/erg_compiler/hir.rs | 2 +- examples/class.er | 6 ++++++ 4 files changed, 40 insertions(+), 4 deletions(-) diff --git a/compiler/erg_compiler/codegen.rs b/compiler/erg_compiler/codegen.rs index 31aaabfb..5cdd30bc 100644 --- a/compiler/erg_compiler/codegen.rs +++ b/compiler/erg_compiler/codegen.rs @@ -1370,11 +1370,27 @@ impl CodeGenerator { Accessor::Attr(a) => { let class = a.obj.ref_t().name(); let uniq_obj_name = a.obj.__name__().map(Str::rc); - self.codegen_expr(*a.obj); - self.emit_load_attr_instr(&class, uniq_obj_name.as_ref().map(|s| &s[..]), a.ident) + // C = Class ... + // C. + // a = C.x + // ↓ + // class C: + // a = x + if Some(&self.cur_block_codeobj().name[..]) != a.obj.__name__() { + self.codegen_expr(*a.obj); + self.emit_load_attr_instr( + &class, + uniq_obj_name.as_ref().map(|s| &s[..]), + a.ident, + ) .unwrap_or_else(|err| { self.errs.push(err); }); + } else { + self.emit_load_name_instr(a.ident).unwrap_or_else(|err| { + self.errs.push(err); + }); + } } Accessor::TupleAttr(t_attr) => { self.codegen_expr(*t_attr.obj); diff --git a/compiler/erg_compiler/context/inquire.rs b/compiler/erg_compiler/context/inquire.rs index b31fd980..8ef20994 100644 --- a/compiler/erg_compiler/context/inquire.rs +++ b/compiler/erg_compiler/context/inquire.rs @@ -194,6 +194,9 @@ impl Context { if let Some(ctx) = self.rec_get_mod(name.inspect()) { return Some(ctx.name.clone()); } + if let Some((_, ctx)) = self.rec_get_type(name.inspect()) { + return Some(ctx.name.clone()); + } None } @@ -1280,7 +1283,6 @@ impl Context { } fn rec_get_singular_ctx(&self, obj: &hir::Expr) -> Option<&Context> { - log!("{}", obj.ref_t()); match obj.ref_t() { // TODO: attr Type::Module => self.rec_get_mod(&obj.show_acc()?), @@ -1415,6 +1417,18 @@ impl Context { } } + fn rec_get_type(&self, name: &str) -> Option<(&Type, &Context)> { + if let Some((t, ctx)) = self.mono_types.get(name) { + Some((t, ctx)) + } else if let Some((t, ctx)) = self.poly_types.get(name) { + Some((t, ctx)) + } else if let Some(outer) = &self.outer { + outer.rec_get_type(name) + } else { + None + } + } + fn get_gen_t_require_attr_t<'a>(&'a self, gen: &'a GenTypeObj, attr: &str) -> Option<&'a Type> { match gen.require_or_sup.typ() { Type::Record(rec) => { diff --git a/compiler/erg_compiler/hir.rs b/compiler/erg_compiler/hir.rs index af75046e..e50c8804 100644 --- a/compiler/erg_compiler/hir.rs +++ b/compiler/erg_compiler/hir.rs @@ -528,7 +528,7 @@ impl Accessor { } } - // 参照するオブジェクト自体が持っている固有の名前 + // 参照するオブジェクト自体が持っている固有の名前(クラス、モジュールなど) pub fn __name__(&self) -> Option<&str> { match self { Self::Ident(ident) => ident.__name__.as_ref().map(|s| &s[..]), diff --git a/examples/class.er b/examples/class.er index 7b54d73d..49081aeb 100644 --- a/examples/class.er +++ b/examples/class.er @@ -1,7 +1,10 @@ # Inheritance is prohibited by default. Remove this decorator and check for errors. @Inheritable Point2D = Class {x = Int; y = Int} +Point2D:: + one = 1 Point2D. + zero = Point2D::one - 1 norm self = self::x**2 + self::y**2 Point3D = Inherit Point2D, Additional := {z = Int} @@ -13,7 +16,10 @@ Point3D. @Override norm self = self::x**2 + self::y**2 + self::z**2 +# `Point2D::__new__` is private, use `Point2D.new` instead p = Point2D.new {x = 1; y = 2} print! p, p.norm() +print! Point2D.zero +# print! Point2D::one # cannot access private variables q = Point3D.new 1, 2, 3 print! q, q.norm() From 02e0beb84946693fec1cacdcc63a0161985f865d Mon Sep 17 00:00:00 2001 From: Shunsuke Shibayama Date: Sat, 10 Sep 2022 17:57:01 +0900 Subject: [PATCH 68/68] Update desugar.rs --- compiler/erg_parser/desugar.rs | 21 +++++++-------------- 1 file changed, 7 insertions(+), 14 deletions(-) diff --git a/compiler/erg_parser/desugar.rs b/compiler/erg_parser/desugar.rs index 8842e749..4cfe3128 100644 --- a/compiler/erg_parser/desugar.rs +++ b/compiler/erg_parser/desugar.rs @@ -20,10 +20,10 @@ use crate::ast::{ use crate::token::{Token, TokenKind}; #[derive(Debug, Clone, PartialEq, Eq)] -enum BufIndex<'s> { +enum BufIndex<'i> { Array(usize), Tuple(usize), - Record(&'s str), + Record(&'i Identifier), } #[derive(Debug)] @@ -229,7 +229,7 @@ impl Desugarer { &mut new, rhs, &buf_name, - BufIndex::Record(lhs.inspect()), + BufIndex::Record(lhs), ); } } @@ -245,7 +245,7 @@ impl Desugarer { &mut new, rhs, &buf_name, - BufIndex::Record(lhs.inspect()), + BufIndex::Record(lhs), ); } } @@ -278,14 +278,7 @@ impl Desugarer { BufIndex::Array(n) => { Accessor::subscr(obj, Expr::Lit(Literal::nat(n, sig.ln_begin().unwrap()))) } - BufIndex::Record(attr) => { - let ident = Identifier::new( - Some(Token::from_str(TokenKind::Dot, ".")), - VarName::new(Token::symbol_with_line(attr, sig.ln_begin().unwrap())), - ); - // TODO: visibility - Accessor::attr(obj, ident) - } + BufIndex::Record(attr) => Accessor::attr(obj, attr.clone()), }; let id = DefId(get_hash(&(&acc, buf_name))); let block = Block::new(vec![Expr::Accessor(acc)]); @@ -327,7 +320,7 @@ impl Desugarer { new_module, rhs, &buf_name, - BufIndex::Record(lhs.inspect()), + BufIndex::Record(lhs), ); } } @@ -341,7 +334,7 @@ impl Desugarer { new_module, rhs, &buf_name, - BufIndex::Record(lhs.inspect()), + BufIndex::Record(lhs), ); } }