diff --git a/compiler/erg_compiler/codegen.rs b/compiler/erg_compiler/codegen.rs index 14667b31..484ebd55 100644 --- a/compiler/erg_compiler/codegen.rs +++ b/compiler/erg_compiler/codegen.rs @@ -29,8 +29,8 @@ use crate::compile::{AccessKind, Name, StoreLoadKind}; use crate::context::eval::type_from_token_kind; use crate::error::CompileError; use crate::hir::{ - Accessor, Args, Array, AttrDef, Attribute, BinOp, Block, Call, ClassDef, Def, DefBody, Expr, - Identifier, Lambda, Literal, Params, PosArg, Record, Signature, SubrSignature, Tuple, UnaryOp, + Accessor, Args, Array, AttrDef, BinOp, Block, Call, ClassDef, Def, DefBody, Expr, Identifier, + Lambda, Literal, Params, PosArg, Record, Signature, SubrSignature, Tuple, UnaryOp, VarSignature, HIR, }; use crate::ty::free::fresh_varname; @@ -1717,22 +1717,19 @@ impl CodeGenerator { for field in rec.keys() { let obj = Expr::Accessor(Accessor::private_with_line(Str::from(¶m_name), line)); - let expr = Expr::Accessor(Accessor::Attr(Attribute::new( - obj, - Identifier::bare( - Some(Token::dummy()), - VarName::from_str(field.symbol.clone()), - ), - ))); + let expr = obj.attr_expr(Identifier::bare( + Some(Token::dummy()), + VarName::from_str(field.symbol.clone()), + )); 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, - Identifier::bare(dot, VarName::from_str(field.symbol.clone())), + let attr = obj.attr(Identifier::bare( + dot, + VarName::from_str(field.symbol.clone()), )); let attr_def = AttrDef::new(attr, Block::new(vec![expr])); attrs.push(Expr::AttrDef(attr_def)); @@ -1769,12 +1766,8 @@ impl CodeGenerator { let mut new_ident = Identifier::bare(None, VarName::from_str_and_line(Str::ever("__new__"), line)); new_ident.vi.py_name = Some(Str::ever("__call__")); - let class_new = Expr::Accessor(Accessor::attr(class, new_ident)); - let call = Expr::Call(Call::new( - class_new, - None, - Args::new(vec![arg], None, vec![], None), - )); + let class_new = class.attr_expr(new_ident); + let call = class_new.call_expr(Args::new(vec![arg], None, vec![], None)); let block = Block::new(vec![call]); let body = DefBody::new(Token::dummy(), block, DefId(0)); self.emit_subr_def(Some(class_ident.inspect()), sig, body); diff --git a/compiler/erg_compiler/desugar_hir.rs b/compiler/erg_compiler/desugar_hir.rs index 1c3bb47b..41c92f9b 100644 --- a/compiler/erg_compiler/desugar_hir.rs +++ b/compiler/erg_compiler/desugar_hir.rs @@ -39,7 +39,7 @@ impl HIRDesugarer { .into_iter() .map(|expr| match expr { Expr::Def(def) => { - let acc = Accessor::attr(class.clone(), def.sig.into_ident()); + let acc = class.clone().attr(def.sig.into_ident()); let attr_def = AttrDef::new(acc, def.body.block); Expr::AttrDef(attr_def) } diff --git a/compiler/erg_compiler/hir.rs b/compiler/erg_compiler/hir.rs index d426aa7f..32480443 100644 --- a/compiler/erg_compiler/hir.rs +++ b/compiler/erg_compiler/hir.rs @@ -1836,6 +1836,33 @@ impl Expr { pub fn is_type_asc(&self) -> bool { matches!(self, Expr::TypeAsc(_)) } + + pub fn call(self, args: Args) -> Call { + match self { + Self::Accessor(Accessor::Attr(attr)) => Call::new(*attr.obj, Some(attr.ident), args), + other => Call::new(other, None, args), + } + } + + pub fn call_expr(self, args: Args) -> Self { + Self::Call(self.call(args)) + } + + pub fn attr(self, ident: Identifier) -> Accessor { + Accessor::attr(self, ident) + } + + pub fn attr_expr(self, ident: Identifier) -> Self { + Self::Accessor(self.attr(ident)) + } + + pub fn type_asc(self, t_spec: TypeSpec) -> TypeAscription { + TypeAscription::new(self, t_spec) + } + + pub fn type_asc_expr(self, t_spec: TypeSpec) -> Self { + Self::TypeAsc(self.type_asc(t_spec)) + } } /// Toplevel grammar unit diff --git a/compiler/erg_compiler/link.rs b/compiler/erg_compiler/link.rs index bbe763b6..556e7b29 100644 --- a/compiler/erg_compiler/link.rs +++ b/compiler/erg_compiler/link.rs @@ -185,7 +185,7 @@ impl<'a> Linker<'a> { let module_type = Expr::Accessor(Accessor::private_with_line(Str::ever("#ModuleType"), line)); let args = Args::new(vec![PosArg::new(mod_name.clone())], None, vec![], None); - let block = Block::new(vec![Expr::Call(Call::new(module_type, None, args))]); + let block = Block::new(vec![module_type.call_expr(args)]); let tmp = Identifier::private_with_line(Str::from(fresh_varname()), expr.ln_begin().unwrap()); let mod_def = Expr::Def(Def::new( @@ -194,9 +194,9 @@ impl<'a> Linker<'a> { )); let module = Expr::Accessor(Accessor::Ident(tmp)); let __dict__ = Identifier::public("__dict__"); - let m_dict = Expr::Accessor(Accessor::attr(module.clone(), __dict__)); + let m_dict = module.clone().attr_expr(__dict__); let locals = Expr::Accessor(Accessor::public_with_line(Str::ever("locals"), line)); - let locals_call = Expr::Call(Call::new(locals, None, Args::empty())); + let locals_call = locals.call_expr(Args::empty()); let args = Args::new(vec![PosArg::new(locals_call)], None, vec![], None); let mod_update = Expr::Call(Call::new( m_dict.clone(), @@ -210,7 +210,7 @@ impl<'a> Linker<'a> { vec![], None, ); - let exec_code = Expr::Call(Call::new(exec, None, args)); + let exec_code = exec.call_expr(args); let compound = Block::new(vec![mod_def, mod_update, exec_code, module]); *expr = Expr::Compound(compound); } @@ -256,15 +256,13 @@ impl<'a> Linker<'a> { args.insert_pos(0, PosArg::new(mod_name)); let line = expr.ln_begin().unwrap_or(0); for attr in comps { - *expr = Expr::Accessor(Accessor::attr( - // instead of mem::take(), - mem::replace(expr, Expr::Code(Block::empty())), + *expr = mem::replace(expr, Expr::Code(Block::empty())).attr_expr( Identifier::public_with_line( Token::dummy(), Str::rc(attr.as_os_str().to_str().unwrap()), line, ), - )); + ); } } } diff --git a/compiler/erg_compiler/lower.rs b/compiler/erg_compiler/lower.rs index 50279498..fc744b39 100644 --- a/compiler/erg_compiler/lower.rs +++ b/compiler/erg_compiler/lower.rs @@ -1418,7 +1418,7 @@ impl ASTLowerer { expr.loc(), Some(&Str::from(expr.to_string())), )?; - Ok(hir::TypeAscription::new(expr, tasc.t_spec)) + Ok(expr.type_asc(tasc.t_spec)) } // Call.obj == Accessor cannot be type inferred by itself (it can only be inferred with arguments) @@ -1527,8 +1527,7 @@ impl ASTLowerer { ast::Expr::Accessor(ast::Accessor::Attr(attr)) => { let obj = self.fake_lower_obj(*attr.obj)?; let ident = hir::Identifier::bare(attr.ident.dot, attr.ident.name); - let acc = hir::Accessor::attr(obj, ident); - Ok(hir::Expr::Accessor(acc)) + Ok(obj.attr_expr(ident)) } other => Err(LowerErrors::from(LowerError::declare_error( self.cfg.input.clone(), @@ -1596,10 +1595,7 @@ impl ASTLowerer { let py_name = Str::rc(ident.inspect().trim_end_matches('!')); let vi = VarInfo::new(t, muty, vis, VarKind::Declared, None, None, Some(py_name)); let ident = hir::Identifier::new(ident.dot, ident.name, None, vi); - Ok(hir::TypeAscription::new( - hir::Expr::Accessor(hir::Accessor::Ident(ident)), - tasc.t_spec, - )) + Ok(hir::Expr::Accessor(hir::Accessor::Ident(ident)).type_asc(tasc.t_spec)) } ast::Expr::Accessor(ast::Accessor::Attr(attr)) => { let py_name = Str::rc(attr.ident.inspect().trim_end_matches('!')); @@ -1625,11 +1621,8 @@ impl ASTLowerer { let py_name = Str::rc(attr.ident.inspect().trim_end_matches('!')); let vi = VarInfo::new(t, muty, vis, VarKind::Declared, None, None, Some(py_name)); let ident = hir::Identifier::new(attr.ident.dot, attr.ident.name, None, vi); - let attr = hir::Accessor::attr(obj, ident); - Ok(hir::TypeAscription::new( - hir::Expr::Accessor(attr), - tasc.t_spec, - )) + let attr = obj.attr_expr(ident); + Ok(attr.type_asc(tasc.t_spec)) } other => Err(LowerErrors::from(LowerError::declare_error( self.cfg.input.clone(), diff --git a/compiler/erg_parser/ast.rs b/compiler/erg_parser/ast.rs index fd3ed429..8be69cc5 100644 --- a/compiler/erg_parser/ast.rs +++ b/compiler/erg_parser/ast.rs @@ -3222,6 +3222,49 @@ impl Expr { pub fn static_local(name: &'static str) -> Self { Self::Accessor(Accessor::local(Token::static_symbol(name))) } + + pub fn attr(self, ident: Identifier) -> Accessor { + Accessor::attr(self, ident) + } + + pub fn attr_expr(self, ident: Identifier) -> Self { + Self::Accessor(self.attr(ident)) + } + + pub fn subscr(self, index: Expr, r_sqbr: Token) -> Accessor { + Accessor::subscr(self, index, r_sqbr) + } + + pub fn subscr_expr(self, index: Expr, r_sqbr: Token) -> Self { + Self::Accessor(self.subscr(index, r_sqbr)) + } + + pub fn tuple_attr(self, index: Literal) -> Accessor { + Accessor::tuple_attr(self, index) + } + + pub fn tuple_attr_expr(self, index: Literal) -> Self { + Self::Accessor(self.tuple_attr(index)) + } + + pub fn call(self, args: Args) -> Call { + match self { + Self::Accessor(Accessor::Attr(attr)) => Call::new(*attr.obj, Some(attr.ident), args), + other => Call::new(other, None, args), + } + } + + pub fn call_expr(self, args: Args) -> Self { + Self::Call(self.call(args)) + } + + pub fn type_asc(self, op: Token, t_spec: TypeSpec) -> TypeAscription { + TypeAscription::new(self, op, t_spec) + } + + pub fn type_asc_expr(self, op: Token, t_spec: TypeSpec) -> Self { + Self::TypeAsc(self.type_asc(op, t_spec)) + } } #[derive(Clone, Debug, PartialEq, Eq, Hash)] diff --git a/compiler/erg_parser/desugar.rs b/compiler/erg_parser/desugar.rs index b8a64751..a2f22f03 100644 --- a/compiler/erg_parser/desugar.rs +++ b/compiler/erg_parser/desugar.rs @@ -15,8 +15,8 @@ use crate::ast::{ DefBody, DefId, Dict, Expr, Identifier, KeyValue, KwArg, Lambda, LambdaSignature, Literal, Methods, Module, NonDefaultParamSignature, NormalArray, NormalDict, NormalRecord, NormalSet, NormalTuple, ParamPattern, Params, PosArg, Record, RecordAttrs, Set as astSet, SetWithLength, - ShortenedRecord, Signature, SubrSignature, Tuple, TypeAscription, TypeBoundSpecs, TypeSpec, - UnaryOp, VarName, VarPattern, VarRecordAttr, VarSignature, + ShortenedRecord, Signature, SubrSignature, Tuple, TypeBoundSpecs, TypeSpec, UnaryOp, VarName, + VarPattern, VarRecordAttr, VarSignature, }; use crate::token::{Token, TokenKind}; @@ -201,7 +201,7 @@ impl Desugarer { } Expr::TypeAsc(tasc) => { let expr = desugar(*tasc.expr); - Expr::TypeAsc(TypeAscription::new(expr, tasc.op, tasc.t_spec)) + expr.type_asc_expr(tasc.op, tasc.t_spec) } Expr::Methods(method_defs) => { let mut new_defs = vec![]; @@ -323,7 +323,7 @@ impl Desugarer { vec![], None, ); - let call = Call::new(match_symbol, None, args); + let call = match_symbol.call(args); (call, return_t_spec) } @@ -439,9 +439,7 @@ impl Desugarer { ) { let obj = Expr::local(buf_name, sig.ln_begin().unwrap(), sig.col_begin().unwrap()); let acc = match buf_index { - BufIndex::Tuple(n) => { - Accessor::tuple_attr(obj, Literal::nat(n, sig.ln_begin().unwrap())) - } + BufIndex::Tuple(n) => obj.tuple_attr(Literal::nat(n, sig.ln_begin().unwrap())), BufIndex::Array(n) => { let r_brace = Token::new( TokenKind::RBrace, @@ -449,13 +447,9 @@ impl Desugarer { sig.ln_begin().unwrap(), sig.col_begin().unwrap(), ); - Accessor::subscr( - obj, - Expr::Lit(Literal::nat(n, sig.ln_begin().unwrap())), - r_brace, - ) + obj.subscr(Expr::Lit(Literal::nat(n, sig.ln_begin().unwrap())), r_brace) } - BufIndex::Record(attr) => Accessor::attr(obj, attr.clone()), + BufIndex::Record(attr) => obj.attr(attr.clone()), }; let id = DefId(get_hash(&(&acc, buf_name))); let block = Block::new(vec![Expr::Accessor(acc)]); diff --git a/compiler/erg_parser/parse.rs b/compiler/erg_parser/parse.rs index 08887339..02b11b92 100644 --- a/compiler/erg_parser/parse.rs +++ b/compiler/erg_parser/parse.rs @@ -885,7 +885,7 @@ impl Parser { Some(arg) if arg.is(Symbol) || arg.category_is(TC::Literal) => { let args = self.try_reduce_args(false).map_err(|_| self.stack_dec())?; let obj = enum_unwrap!(stack.pop(), Some:(ExprOrOp::Expr:(_))); - stack.push(ExprOrOp::Expr(Expr::Call(Call::new(obj, None, args)))); + stack.push(ExprOrOp::Expr(obj.call_expr(args))); } Some(op) if op.category_is(TC::DefOp) => { let op = self.lpop(); @@ -934,7 +934,7 @@ impl Parser { .try_reduce_expr(false, false, false, false) .map_err(|_| self.stack_dec())?; let t_spec = Self::expr_to_type_spec(t_spec).map_err(|e| self.errs.push(e))?; - let expr = Expr::TypeAsc(TypeAscription::new(lhs, op, t_spec)); + let expr = lhs.type_asc_expr(op, t_spec); stack.push(ExprOrOp::Expr(expr)); } Some(op) if op.category_is(TC::BinOp) => { @@ -985,8 +985,7 @@ impl Parser { stack.push(ExprOrOp::Expr(Expr::Call(call))); } else { let ident = Identifier::new(None, VarName::new(symbol)); - let acc = Accessor::attr(obj, ident); - stack.push(ExprOrOp::Expr(Expr::Accessor(acc))); + stack.push(ExprOrOp::Expr(obj.attr_expr(ident))); } } line_break if line_break.is(Newline) => { @@ -1049,13 +1048,12 @@ impl Parser { let mut call = Expr::Call(Call::new(obj, Some(ident), args)); while let Some(res) = self.opt_reduce_args(false) { let args = res.map_err(|_| self.stack_dec())?; - call = Expr::Call(Call::new(call, None, args)); + call = call.call_expr(args); } stack.push(ExprOrOp::Expr(call)); } else { let ident = Identifier::new(Some(vis), VarName::new(symbol)); - let acc = Accessor::attr(obj, ident); - stack.push(ExprOrOp::Expr(Expr::Accessor(acc))); + stack.push(ExprOrOp::Expr(obj.attr_expr(ident))); } } line_break if line_break.is(Newline) => { @@ -1201,7 +1199,7 @@ impl Parser { .try_reduce_expr(false, in_type_args, in_brace, false) .map_err(|_| self.stack_dec())?; let t_spec = Self::expr_to_type_spec(t_spec).map_err(|e| self.errs.push(e))?; - let expr = Expr::TypeAsc(TypeAscription::new(lhs, op, t_spec)); + let expr = lhs.type_asc_expr(op, t_spec); stack.push(ExprOrOp::Expr(expr)); } Some(op) if op.category_is(TC::BinOp) => { @@ -1252,8 +1250,7 @@ impl Parser { stack.push(ExprOrOp::Expr(Expr::Call(call))); } else { let ident = Identifier::new(Some(vis), VarName::new(symbol)); - let acc = Accessor::attr(obj, ident); - stack.push(ExprOrOp::Expr(Expr::Accessor(acc))); + stack.push(ExprOrOp::Expr(obj.attr_expr(ident))); } } other => { @@ -1353,10 +1350,10 @@ impl Parser { Signature::Var(var) => { let mut last = def.body.block.pop().unwrap(); for deco in decos.into_iter() { - last = Expr::Call(Call::new( - deco.into_expr(), + last = deco.into_expr().call_expr(Args::new( + vec![PosArg::new(last)], + vec![], None, - Args::new(vec![PosArg::new(last)], vec![], None), )); } def.body.block.push(last); @@ -1501,11 +1498,11 @@ impl Parser { match token.kind { Symbol => { let ident = Identifier::new(Some(vis), VarName::new(token)); - obj = Expr::Accessor(Accessor::attr(obj, ident)); + obj = obj.attr_expr(ident); } NatLit => { let index = Literal::from(token); - obj = Expr::Accessor(Accessor::tuple_attr(obj, index)); + obj = obj.tuple_attr_expr(index); } Newline => { self.restore(token); @@ -1527,8 +1524,7 @@ impl Parser { token.content = Str::rc(&token.content[1..]); token.kind = NatLit; token.col_begin += 1; - let index = Literal::from(token); - obj = Expr::Accessor(Accessor::tuple_attr(obj, index)); + obj = obj.tuple_attr_expr(Literal::from(token)); } Some(t) if t.is(DblColon) && obj.col_end() == t.col_begin() => { let vis = self.lpop(); @@ -1536,7 +1532,7 @@ impl Parser { match token.kind { Symbol => { let ident = Identifier::new(None, VarName::new(token)); - obj = Expr::Accessor(Accessor::attr(obj, ident)); + obj = obj.attr_expr(ident); } LBrace => { self.restore(token);