mirror of
https://github.com/erg-lang/erg.git
synced 2025-09-30 04:44:44 +00:00
Fix #282
This commit is contained in:
parent
a395938413
commit
4ed278e75c
8 changed files with 80 additions and 37 deletions
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,8 +215,12 @@ impl Context {
|
|||
);
|
||||
log!(info "Registered {}::{}: {}", self.name, ident.name, vi);
|
||||
self.locals.insert(ident.name.clone(), vi);
|
||||
if let Some(errs) = errs {
|
||||
Err(errs)
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// 宣言が既にある場合、opt_decl_tに宣言の型を渡す
|
||||
fn assign_param(
|
||||
|
|
|
@ -159,16 +159,7 @@ impl NestedDisplay for Args {
|
|||
}
|
||||
}
|
||||
|
||||
impl From<Vec<Expr>> for Args {
|
||||
fn from(exprs: Vec<Expr>) -> Self {
|
||||
Self {
|
||||
pos_args: exprs.into_iter().map(PosArg::new).collect(),
|
||||
var_args: None,
|
||||
kw_args: Vec::new(),
|
||||
paren: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
// do not implement From<Vec<Expr>> 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<Expr>, 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)
|
||||
}
|
||||
|
|
|
@ -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<hir::NormalTuple> {
|
||||
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<hir::Record> {
|
||||
|
@ -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);
|
||||
|
|
|
@ -1916,6 +1916,34 @@ impl SetWithLenTypeSpec {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
pub struct TupleTypeSpec {
|
||||
pub parens: Option<(Token, Token)>,
|
||||
pub tys: Vec<TypeSpec>,
|
||||
}
|
||||
|
||||
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<TypeSpec>) -> 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<TypeSpec>),
|
||||
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(),
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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<Tuple> {
|
||||
fn try_reduce_nonempty_tuple(
|
||||
&mut self,
|
||||
first_elem: PosOrKwArg,
|
||||
line_break: bool,
|
||||
) -> ParseResult<Tuple> {
|
||||
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<Vec<TypeSpec>, ParseError> {
|
||||
fn tuple_to_tuple_type_spec(tuple: Tuple) -> Result<TupleTypeSpec, ParseError> {
|
||||
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))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue