mirror of
https://github.com/erg-lang/erg.git
synced 2025-09-30 12:51:10 +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)
|
// _: (Int, Str)
|
||||||
TypeSpec::Tuple(tup) => {
|
TypeSpec::Tuple(tup) => {
|
||||||
let len = tup.len();
|
let len = tup.tys.len();
|
||||||
for (i, t_spec) in tup.into_iter().enumerate() {
|
for (i, t_spec) in tup.tys.into_iter().enumerate() {
|
||||||
if i != 0 && i != len - 1 {
|
if i != 0 && i != len - 1 {
|
||||||
self.dup_top();
|
self.dup_top();
|
||||||
}
|
}
|
||||||
|
|
|
@ -699,9 +699,9 @@ impl Context {
|
||||||
}
|
}
|
||||||
Ok(set_t(elem_t, len))
|
Ok(set_t(elem_t, len))
|
||||||
}
|
}
|
||||||
TypeSpec::Tuple(tys) => {
|
TypeSpec::Tuple(tup) => {
|
||||||
let mut inst_tys = vec![];
|
let mut inst_tys = vec![];
|
||||||
for spec in tys {
|
for spec in tup.tys.iter() {
|
||||||
inst_tys.push(self.instantiate_typespec(
|
inst_tys.push(self.instantiate_typespec(
|
||||||
spec,
|
spec,
|
||||||
opt_decl_t,
|
opt_decl_t,
|
||||||
|
|
|
@ -188,7 +188,11 @@ impl Context {
|
||||||
self.locals.insert(ident.name.clone(), vi);
|
self.locals.insert(ident.name.clone(), vi);
|
||||||
return Ok(());
|
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 muty = Mutability::from(&ident.inspect()[..]);
|
||||||
let py_name = if let Some(vi) = self
|
let py_name = if let Some(vi) = self
|
||||||
.decls
|
.decls
|
||||||
|
@ -201,7 +205,7 @@ impl Context {
|
||||||
};
|
};
|
||||||
let vis = ident.vis();
|
let vis = ident.vis();
|
||||||
let vi = VarInfo::new(
|
let vi = VarInfo::new(
|
||||||
body_t.clone(),
|
var_t,
|
||||||
muty,
|
muty,
|
||||||
vis,
|
vis,
|
||||||
VarKind::Defined(id),
|
VarKind::Defined(id),
|
||||||
|
@ -211,8 +215,12 @@ impl Context {
|
||||||
);
|
);
|
||||||
log!(info "Registered {}::{}: {}", self.name, ident.name, vi);
|
log!(info "Registered {}::{}: {}", self.name, ident.name, vi);
|
||||||
self.locals.insert(ident.name.clone(), vi);
|
self.locals.insert(ident.name.clone(), vi);
|
||||||
|
if let Some(errs) = errs {
|
||||||
|
Err(errs)
|
||||||
|
} else {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// 宣言が既にある場合、opt_decl_tに宣言の型を渡す
|
/// 宣言が既にある場合、opt_decl_tに宣言の型を渡す
|
||||||
fn assign_param(
|
fn assign_param(
|
||||||
|
|
|
@ -159,16 +159,7 @@ impl NestedDisplay for Args {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<Vec<Expr>> for Args {
|
// do not implement From<Vec<Expr>> to Args, because it will miss paren info (use `values`)
|
||||||
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,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl_display_from_nested!(Args);
|
impl_display_from_nested!(Args);
|
||||||
|
|
||||||
|
@ -183,6 +174,8 @@ impl Locational for Args {
|
||||||
self.pos_args.first().unwrap(),
|
self.pos_args.first().unwrap(),
|
||||||
self.pos_args.last().unwrap(),
|
self.pos_args.last().unwrap(),
|
||||||
)
|
)
|
||||||
|
} else if let Some(va) = self.var_args.as_ref() {
|
||||||
|
va.loc()
|
||||||
} else {
|
} else {
|
||||||
Location::Unknown
|
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 {
|
pub fn empty() -> Self {
|
||||||
Self::new(vec![], None, vec![], None)
|
Self::new(vec![], None, vec![], None)
|
||||||
}
|
}
|
||||||
|
|
|
@ -364,7 +364,7 @@ impl ASTLowerer {
|
||||||
array.l_sqbr,
|
array.l_sqbr,
|
||||||
array.r_sqbr,
|
array.r_sqbr,
|
||||||
elem_t,
|
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> {
|
fn lower_normal_tuple(&mut self, tuple: ast::NormalTuple) -> LowerResult<hir::NormalTuple> {
|
||||||
log!(info "entered {}({tuple})", fn_name!());
|
log!(info "entered {}({tuple})", fn_name!());
|
||||||
let mut new_tuple = vec![];
|
let mut new_tuple = vec![];
|
||||||
let (elems, _) = tuple.elems.into_iters();
|
let (elems, .., paren) = tuple.elems.deconstruct();
|
||||||
for elem in elems {
|
for elem in elems {
|
||||||
let elem = self.lower_expr(elem.expr)?;
|
let elem = self.lower_expr(elem.expr)?;
|
||||||
new_tuple.push(elem);
|
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> {
|
fn lower_record(&mut self, record: ast::Record) -> LowerResult<hir::Record> {
|
||||||
|
@ -526,7 +526,7 @@ impl ASTLowerer {
|
||||||
}
|
}
|
||||||
Ok(normal_set)
|
Ok(normal_set)
|
||||||
*/
|
*/
|
||||||
let elems = hir::Args::from(new_set);
|
let elems = hir::Args::values(new_set, None);
|
||||||
// check if elem_t is Eq
|
// check if elem_t is Eq
|
||||||
if let Err(errs) = self.ctx.sub_unify(&elem_t, &mono("Eq"), elems.loc(), None) {
|
if let Err(errs) = self.ctx.sub_unify(&elem_t, &mono("Eq"), elems.loc(), None) {
|
||||||
self.errs.extend(errs);
|
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.
|
/// * Array: `[Int; 3]`, `[Int, Ratio, Complex]`, etc.
|
||||||
/// * Dict: `[Str: Str]`, etc.
|
/// * Dict: `[Str: Str]`, etc.
|
||||||
/// * And (Intersection type): Add and Sub and Mul (== Num), etc.
|
/// * And (Intersection type): Add and Sub and Mul (== Num), etc.
|
||||||
|
@ -1933,7 +1961,7 @@ pub enum TypeSpec {
|
||||||
/* Composite types */
|
/* Composite types */
|
||||||
Array(ArrayTypeSpec),
|
Array(ArrayTypeSpec),
|
||||||
SetWithLen(SetWithLenTypeSpec),
|
SetWithLen(SetWithLenTypeSpec),
|
||||||
Tuple(Vec<TypeSpec>),
|
Tuple(TupleTypeSpec),
|
||||||
Dict(Vec<(TypeSpec, TypeSpec)>),
|
Dict(Vec<(TypeSpec, TypeSpec)>),
|
||||||
Record(Vec<(Identifier, TypeSpec)>),
|
Record(Vec<(Identifier, TypeSpec)>),
|
||||||
// Option(),
|
// Option(),
|
||||||
|
@ -1964,7 +1992,7 @@ impl fmt::Display for TypeSpec {
|
||||||
Self::Or(lhs, rhs) => write!(f, "{lhs} or {rhs}"),
|
Self::Or(lhs, rhs) => write!(f, "{lhs} or {rhs}"),
|
||||||
Self::Array(arr) => write!(f, "{arr}"),
|
Self::Array(arr) => write!(f, "{arr}"),
|
||||||
Self::SetWithLen(set) => write!(f, "{set}"),
|
Self::SetWithLen(set) => write!(f, "{set}"),
|
||||||
Self::Tuple(tys) => write!(f, "({})", fmt_vec(tys)),
|
Self::Tuple(tup) => write!(f, "{tup}"),
|
||||||
Self::Dict(dict) => {
|
Self::Dict(dict) => {
|
||||||
write!(f, "{{")?;
|
write!(f, "{{")?;
|
||||||
for (k, v) in dict.iter() {
|
for (k, v) in dict.iter() {
|
||||||
|
@ -2003,8 +2031,7 @@ impl Locational for TypeSpec {
|
||||||
}
|
}
|
||||||
Self::Array(arr) => arr.loc(),
|
Self::Array(arr) => arr.loc(),
|
||||||
Self::SetWithLen(set) => set.loc(),
|
Self::SetWithLen(set) => set.loc(),
|
||||||
// TODO: ユニット
|
Self::Tuple(tup) => tup.loc(),
|
||||||
Self::Tuple(tys) => Location::concat(tys.first().unwrap(), tys.last().unwrap()),
|
|
||||||
Self::Dict(dict) => Location::concat(&dict.first().unwrap().0, &dict.last().unwrap().1),
|
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::Record(rec) => Location::concat(&rec.first().unwrap().0, &rec.last().unwrap().1),
|
||||||
Self::Enum(set) => set.loc(),
|
Self::Enum(set) => set.loc(),
|
||||||
|
|
|
@ -17,9 +17,9 @@ use crate::ast::{
|
||||||
Identifier, KeyValue, KwArg, Lambda, LambdaSignature, Literal, Methods, MixedRecord, Module,
|
Identifier, KeyValue, KwArg, Lambda, LambdaSignature, Literal, Methods, MixedRecord, Module,
|
||||||
NonDefaultParamSignature, NormalArray, NormalDict, NormalRecord, NormalSet, NormalTuple,
|
NonDefaultParamSignature, NormalArray, NormalDict, NormalRecord, NormalSet, NormalTuple,
|
||||||
ParamPattern, ParamRecordAttr, Params, PatchDef, PosArg, Record, RecordAttrOrIdent,
|
ParamPattern, ParamRecordAttr, Params, PatchDef, PosArg, Record, RecordAttrOrIdent,
|
||||||
RecordAttrs, Set as astSet, SetWithLength, Signature, SubrSignature, Tuple, TypeAppArgs,
|
RecordAttrs, Set as astSet, SetWithLength, Signature, SubrSignature, Tuple, TupleTypeSpec,
|
||||||
TypeBoundSpecs, TypeSpec, TypeSpecWithOp, UnaryOp, VarName, VarPattern, VarRecordAttr,
|
TypeAppArgs, TypeBoundSpecs, TypeSpec, TypeSpecWithOp, UnaryOp, VarName, VarPattern,
|
||||||
VarSignature,
|
VarRecordAttr, VarSignature,
|
||||||
};
|
};
|
||||||
use crate::token::{Token, TokenKind, COLON, DOT};
|
use crate::token::{Token, TokenKind, COLON, DOT};
|
||||||
|
|
||||||
|
@ -766,7 +766,8 @@ impl Desugarer {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if param.t_spec.is_none() {
|
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;
|
param.pat = buf_param;
|
||||||
}
|
}
|
||||||
|
@ -901,7 +902,8 @@ impl Desugarer {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if sig.t_spec.is_none() {
|
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;
|
sig.pat = buf_sig;
|
||||||
insertion_idx
|
insertion_idx
|
||||||
|
|
|
@ -1150,7 +1150,7 @@ impl Parser {
|
||||||
enum_unwrap!(stack.pop(), Some:(ExprOrOp::Expr:(_))),
|
enum_unwrap!(stack.pop(), Some:(ExprOrOp::Expr:(_))),
|
||||||
));
|
));
|
||||||
let tup = self
|
let tup = self
|
||||||
.try_reduce_tuple(first_elem, false)
|
.try_reduce_nonempty_tuple(first_elem, false)
|
||||||
.map_err(|_| self.stack_dec())?;
|
.map_err(|_| self.stack_dec())?;
|
||||||
stack.push(ExprOrOp::Expr(Expr::Tuple(tup)));
|
stack.push(ExprOrOp::Expr(Expr::Tuple(tup)));
|
||||||
}
|
}
|
||||||
|
@ -1329,7 +1329,7 @@ impl Parser {
|
||||||
enum_unwrap!(stack.pop(), Some:(ExprOrOp::Expr:(_))),
|
enum_unwrap!(stack.pop(), Some:(ExprOrOp::Expr:(_))),
|
||||||
));
|
));
|
||||||
let tup = self
|
let tup = self
|
||||||
.try_reduce_tuple(first_elem, line_break)
|
.try_reduce_nonempty_tuple(first_elem, line_break)
|
||||||
.map_err(|_| self.stack_dec())?;
|
.map_err(|_| self.stack_dec())?;
|
||||||
stack.push(ExprOrOp::Expr(Expr::Tuple(tup)));
|
stack.push(ExprOrOp::Expr(Expr::Tuple(tup)));
|
||||||
}
|
}
|
||||||
|
@ -1423,7 +1423,7 @@ impl Parser {
|
||||||
.map_err(|_| self.stack_dec())?;
|
.map_err(|_| self.stack_dec())?;
|
||||||
let first_elem = PosOrKwArg::Kw(KwArg::new(keyword, t_spec, rhs));
|
let first_elem = PosOrKwArg::Kw(KwArg::new(keyword, t_spec, rhs));
|
||||||
let tuple = self
|
let tuple = self
|
||||||
.try_reduce_tuple(first_elem, false)
|
.try_reduce_nonempty_tuple(first_elem, false)
|
||||||
.map_err(|_| self.stack_dec())?;
|
.map_err(|_| self.stack_dec())?;
|
||||||
self.level -= 1;
|
self.level -= 1;
|
||||||
Ok(tuple)
|
Ok(tuple)
|
||||||
|
@ -2097,7 +2097,11 @@ impl Parser {
|
||||||
Err(())
|
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);
|
debug_call_info!(self);
|
||||||
let mut args = match first_elem {
|
let mut args = match first_elem {
|
||||||
PosOrKwArg::Pos(pos) => Args::new(vec![pos], vec![], None),
|
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 {
|
match tuple {
|
||||||
Tuple::Normal(tup) => {
|
Tuple::Normal(tup) => {
|
||||||
let mut tup_spec = vec![];
|
let mut tup_spec = vec![];
|
||||||
let (elems, ..) = tup.elems.deconstruct();
|
let (elems, .., parens) = tup.elems.deconstruct();
|
||||||
for elem in elems.into_iter() {
|
for elem in elems.into_iter() {
|
||||||
let value = Self::expr_to_type_spec(elem.expr)?;
|
let value = Self::expr_to_type_spec(elem.expr)?;
|
||||||
tup_spec.push(value);
|
tup_spec.push(value);
|
||||||
}
|
}
|
||||||
Ok(tup_spec)
|
Ok(TupleTypeSpec::new(parens, tup_spec))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue