diff --git a/compiler/erg_compiler/codegen.rs b/compiler/erg_compiler/codegen.rs index 98e0b3f6..952c343e 100644 --- a/compiler/erg_compiler/codegen.rs +++ b/compiler/erg_compiler/codegen.rs @@ -1859,8 +1859,8 @@ impl PyCodeGenerator { } // _: (Int, Str) TypeSpec::Tuple(tup) => { - let len = tup.len(); - for (i, t_spec) in tup.into_iter().enumerate() { + let len = tup.tys.len(); + for (i, t_spec) in tup.tys.into_iter().enumerate() { if i != 0 && i != len - 1 { self.dup_top(); } diff --git a/compiler/erg_compiler/context/instantiate.rs b/compiler/erg_compiler/context/instantiate.rs index c7326fb2..2889e914 100644 --- a/compiler/erg_compiler/context/instantiate.rs +++ b/compiler/erg_compiler/context/instantiate.rs @@ -699,9 +699,9 @@ impl Context { } Ok(set_t(elem_t, len)) } - TypeSpec::Tuple(tys) => { + TypeSpec::Tuple(tup) => { let mut inst_tys = vec![]; - for spec in tys { + for spec in tup.tys.iter() { inst_tys.push(self.instantiate_typespec( spec, opt_decl_t, diff --git a/compiler/erg_compiler/context/register.rs b/compiler/erg_compiler/context/register.rs index ee21ec04..51b5e888 100644 --- a/compiler/erg_compiler/context/register.rs +++ b/compiler/erg_compiler/context/register.rs @@ -188,7 +188,11 @@ impl Context { self.locals.insert(ident.name.clone(), vi); return Ok(()); } - self.validate_var_sig_t(ident, sig.t_spec.as_ref(), body_t, Normal)?; + let (var_t, errs) = + match self.validate_var_sig_t(ident, sig.t_spec.as_ref(), body_t, Normal) { + Ok(()) => (body_t.clone(), None), + Err(errs) => (Type::Failure, Some(errs)), + }; let muty = Mutability::from(&ident.inspect()[..]); let py_name = if let Some(vi) = self .decls @@ -201,7 +205,7 @@ impl Context { }; let vis = ident.vis(); let vi = VarInfo::new( - body_t.clone(), + var_t, muty, vis, VarKind::Defined(id), @@ -211,7 +215,11 @@ impl Context { ); log!(info "Registered {}::{}: {}", self.name, ident.name, vi); self.locals.insert(ident.name.clone(), vi); - Ok(()) + if let Some(errs) = errs { + Err(errs) + } else { + Ok(()) + } } /// 宣言が既にある場合、opt_decl_tに宣言の型を渡す diff --git a/compiler/erg_compiler/hir.rs b/compiler/erg_compiler/hir.rs index 45700145..a2dad602 100644 --- a/compiler/erg_compiler/hir.rs +++ b/compiler/erg_compiler/hir.rs @@ -159,16 +159,7 @@ impl NestedDisplay for Args { } } -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, - } - } -} +// do not implement From> to Args, because it will miss paren info (use `values`) impl_display_from_nested!(Args); @@ -183,6 +174,8 @@ impl Locational for Args { self.pos_args.first().unwrap(), self.pos_args.last().unwrap(), ) + } else if let Some(va) = self.var_args.as_ref() { + va.loc() } else { Location::Unknown } @@ -206,6 +199,15 @@ impl Args { } } + pub fn values(exprs: Vec, paren: Option<(Token, Token)>) -> Self { + Self::new( + exprs.into_iter().map(PosArg::new).collect(), + None, + vec![], + paren, + ) + } + pub fn empty() -> Self { Self::new(vec![], None, vec![], None) } diff --git a/compiler/erg_compiler/lower.rs b/compiler/erg_compiler/lower.rs index c1338433..07f95369 100644 --- a/compiler/erg_compiler/lower.rs +++ b/compiler/erg_compiler/lower.rs @@ -364,7 +364,7 @@ impl ASTLowerer { array.l_sqbr, array.r_sqbr, elem_t, - hir::Args::from(new_array), + hir::Args::values(new_array, None), )) } @@ -428,12 +428,12 @@ impl ASTLowerer { fn lower_normal_tuple(&mut self, tuple: ast::NormalTuple) -> LowerResult { log!(info "entered {}({tuple})", fn_name!()); let mut new_tuple = vec![]; - let (elems, _) = tuple.elems.into_iters(); + let (elems, .., paren) = tuple.elems.deconstruct(); for elem in elems { let elem = self.lower_expr(elem.expr)?; new_tuple.push(elem); } - Ok(hir::NormalTuple::new(hir::Args::from(new_tuple))) + Ok(hir::NormalTuple::new(hir::Args::values(new_tuple, paren))) } fn lower_record(&mut self, record: ast::Record) -> LowerResult { @@ -526,7 +526,7 @@ impl ASTLowerer { } Ok(normal_set) */ - let elems = hir::Args::from(new_set); + let elems = hir::Args::values(new_set, None); // check if elem_t is Eq if let Err(errs) = self.ctx.sub_unify(&elem_t, &mono("Eq"), elems.loc(), None) { self.errs.extend(errs); diff --git a/compiler/erg_parser/ast.rs b/compiler/erg_parser/ast.rs index 5eb72307..a34225d7 100644 --- a/compiler/erg_parser/ast.rs +++ b/compiler/erg_parser/ast.rs @@ -1916,6 +1916,34 @@ impl SetWithLenTypeSpec { } } +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct TupleTypeSpec { + pub parens: Option<(Token, Token)>, + pub tys: Vec, +} + +impl fmt::Display for TupleTypeSpec { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "({})", fmt_vec(&self.tys)) + } +} + +impl Locational for TupleTypeSpec { + fn loc(&self) -> Location { + if let Some((lparen, rparen)) = &self.parens { + Location::concat(lparen, rparen) + } else { + Location::concat(self.tys.first().unwrap(), self.tys.last().unwrap()) + } + } +} + +impl TupleTypeSpec { + pub fn new(parens: Option<(Token, Token)>, tys: Vec) -> Self { + Self { parens, tys } + } +} + /// * Array: `[Int; 3]`, `[Int, Ratio, Complex]`, etc. /// * Dict: `[Str: Str]`, etc. /// * And (Intersection type): Add and Sub and Mul (== Num), etc. @@ -1933,7 +1961,7 @@ pub enum TypeSpec { /* Composite types */ Array(ArrayTypeSpec), SetWithLen(SetWithLenTypeSpec), - Tuple(Vec), + Tuple(TupleTypeSpec), Dict(Vec<(TypeSpec, TypeSpec)>), Record(Vec<(Identifier, TypeSpec)>), // Option(), @@ -1964,7 +1992,7 @@ impl fmt::Display for TypeSpec { Self::Or(lhs, rhs) => write!(f, "{lhs} or {rhs}"), Self::Array(arr) => write!(f, "{arr}"), Self::SetWithLen(set) => write!(f, "{set}"), - Self::Tuple(tys) => write!(f, "({})", fmt_vec(tys)), + Self::Tuple(tup) => write!(f, "{tup}"), Self::Dict(dict) => { write!(f, "{{")?; for (k, v) in dict.iter() { @@ -2003,8 +2031,7 @@ impl Locational for TypeSpec { } Self::Array(arr) => arr.loc(), Self::SetWithLen(set) => set.loc(), - // TODO: ユニット - Self::Tuple(tys) => Location::concat(tys.first().unwrap(), tys.last().unwrap()), + Self::Tuple(tup) => tup.loc(), Self::Dict(dict) => Location::concat(&dict.first().unwrap().0, &dict.last().unwrap().1), Self::Record(rec) => Location::concat(&rec.first().unwrap().0, &rec.last().unwrap().1), Self::Enum(set) => set.loc(), diff --git a/compiler/erg_parser/desugar.rs b/compiler/erg_parser/desugar.rs index 08bbe4f2..58fb4d5f 100644 --- a/compiler/erg_parser/desugar.rs +++ b/compiler/erg_parser/desugar.rs @@ -17,9 +17,9 @@ use crate::ast::{ Identifier, KeyValue, KwArg, Lambda, LambdaSignature, Literal, Methods, MixedRecord, Module, NonDefaultParamSignature, NormalArray, NormalDict, NormalRecord, NormalSet, NormalTuple, ParamPattern, ParamRecordAttr, Params, PatchDef, PosArg, Record, RecordAttrOrIdent, - RecordAttrs, Set as astSet, SetWithLength, Signature, SubrSignature, Tuple, TypeAppArgs, - TypeBoundSpecs, TypeSpec, TypeSpecWithOp, UnaryOp, VarName, VarPattern, VarRecordAttr, - VarSignature, + RecordAttrs, Set as astSet, SetWithLength, Signature, SubrSignature, Tuple, TupleTypeSpec, + TypeAppArgs, TypeBoundSpecs, TypeSpec, TypeSpecWithOp, UnaryOp, VarName, VarPattern, + VarRecordAttr, VarSignature, }; use crate::token::{Token, TokenKind, COLON, DOT}; @@ -766,7 +766,8 @@ impl Desugarer { ); } if param.t_spec.is_none() { - param.t_spec = Some(TypeSpecWithOp::new(COLON, TypeSpec::Tuple(tys))); + let t_spec = TypeSpec::Tuple(TupleTypeSpec::new(tup.elems.parens.clone(), tys)); + param.t_spec = Some(TypeSpecWithOp::new(COLON, t_spec)); } param.pat = buf_param; } @@ -901,7 +902,8 @@ impl Desugarer { ); } if sig.t_spec.is_none() { - sig.t_spec = Some(TypeSpecWithOp::new(COLON, TypeSpec::Tuple(tys))); + let t_spec = TypeSpec::Tuple(TupleTypeSpec::new(tup.elems.parens.clone(), tys)); + sig.t_spec = Some(TypeSpecWithOp::new(COLON, t_spec)); } sig.pat = buf_sig; insertion_idx diff --git a/compiler/erg_parser/parse.rs b/compiler/erg_parser/parse.rs index bf98dd60..474870a6 100644 --- a/compiler/erg_parser/parse.rs +++ b/compiler/erg_parser/parse.rs @@ -1150,7 +1150,7 @@ impl Parser { enum_unwrap!(stack.pop(), Some:(ExprOrOp::Expr:(_))), )); let tup = self - .try_reduce_tuple(first_elem, false) + .try_reduce_nonempty_tuple(first_elem, false) .map_err(|_| self.stack_dec())?; stack.push(ExprOrOp::Expr(Expr::Tuple(tup))); } @@ -1329,7 +1329,7 @@ impl Parser { enum_unwrap!(stack.pop(), Some:(ExprOrOp::Expr:(_))), )); let tup = self - .try_reduce_tuple(first_elem, line_break) + .try_reduce_nonempty_tuple(first_elem, line_break) .map_err(|_| self.stack_dec())?; stack.push(ExprOrOp::Expr(Expr::Tuple(tup))); } @@ -1423,7 +1423,7 @@ impl Parser { .map_err(|_| self.stack_dec())?; let first_elem = PosOrKwArg::Kw(KwArg::new(keyword, t_spec, rhs)); let tuple = self - .try_reduce_tuple(first_elem, false) + .try_reduce_nonempty_tuple(first_elem, false) .map_err(|_| self.stack_dec())?; self.level -= 1; Ok(tuple) @@ -2097,7 +2097,11 @@ impl Parser { Err(()) } - fn try_reduce_tuple(&mut self, first_elem: PosOrKwArg, line_break: bool) -> ParseResult { + fn try_reduce_nonempty_tuple( + &mut self, + first_elem: PosOrKwArg, + line_break: bool, + ) -> ParseResult { debug_call_info!(self); let mut args = match first_elem { PosOrKwArg::Pos(pos) => Args::new(vec![pos], vec![], None), @@ -3284,16 +3288,16 @@ impl Parser { } } - fn tuple_to_tuple_type_spec(tuple: Tuple) -> Result, ParseError> { + fn tuple_to_tuple_type_spec(tuple: Tuple) -> Result { match tuple { Tuple::Normal(tup) => { let mut tup_spec = vec![]; - let (elems, ..) = tup.elems.deconstruct(); + let (elems, .., parens) = tup.elems.deconstruct(); for elem in elems.into_iter() { let value = Self::expr_to_type_spec(elem.expr)?; tup_spec.push(value); } - Ok(tup_spec) + Ok(TupleTypeSpec::new(parens, tup_spec)) } } }