fix: array pattern matching

This commit is contained in:
Shunsuke Shibayama 2023-08-27 20:29:40 +09:00
parent 5a6cea0df1
commit 952e6ccd2e
5 changed files with 121 additions and 2 deletions

View file

@ -290,6 +290,13 @@ impl PyCodeGenerator {
self.cur_block().lasti
}
#[inline]
#[allow(dead_code)]
fn debug_print(&mut self, value: impl Into<ValueObj>) {
self.emit_load_const(value);
self.emit_print_expr();
}
#[inline]
#[allow(dead_code)]
fn emit_print_expr(&mut self) {

View file

@ -252,8 +252,8 @@ impl ASTLowerer {
arr.l_sqbr,
arr.r_sqbr,
Type::Failure,
len,
elem,
len,
)))
}
ast::Array::Normal(arr) => {

View file

@ -2128,6 +2128,21 @@ impl_nested_display_for_chunk_enum!(ConstExpr; Lit, Accessor, App, Array, Set, D
impl_display_from_nested!(ConstExpr);
impl_locational_for_enum!(ConstExpr; Lit, Accessor, App, Array, Set, Dict, Tuple, Record, BinOp, UnaryOp, Def, Lambda, Set, TypeAsc);
impl TryFrom<&ParamPattern> for ConstExpr {
type Error = ();
fn try_from(value: &ParamPattern) -> Result<Self, Self::Error> {
match value {
ParamPattern::VarName(name) => {
Ok(ConstExpr::Accessor(ConstAccessor::local(name.0.clone())))
}
ParamPattern::Lit(lit) => Ok(ConstExpr::Lit(lit.clone())),
ParamPattern::Array(array) => ConstExpr::try_from(array),
ParamPattern::Tuple(tuple) => ConstExpr::try_from(tuple),
_ => Err(()),
}
}
}
impl ConstExpr {
pub fn need_to_be_closed(&self) -> bool {
match self {
@ -2249,6 +2264,10 @@ impl ConstArgs {
Self::new(pos_args, None, vec![], paren)
}
pub fn single(expr: ConstExpr) -> Self {
Self::pos_only(vec![ConstPosArg::new(expr)], None)
}
#[allow(clippy::type_complexity)]
pub fn deconstruct(
self,
@ -3691,6 +3710,41 @@ impl NestedDisplay for ParamArrayPattern {
impl_display_from_nested!(ParamArrayPattern);
impl_locational!(ParamArrayPattern, l_sqbr, r_sqbr);
impl TryFrom<&ParamArrayPattern> for Expr {
type Error = ();
fn try_from(value: &ParamArrayPattern) -> Result<Self, Self::Error> {
let mut new = vec![];
for elem in value.elems.non_defaults.iter() {
new.push(PosArg::new(Expr::try_from(&elem.pat)?));
}
let elems = Args::pos_only(new, None);
Ok(Expr::Array(Array::Normal(NormalArray::new(
value.l_sqbr.clone(),
value.r_sqbr.clone(),
elems,
))))
}
}
impl TryFrom<&ParamArrayPattern> for ConstExpr {
type Error = ();
fn try_from(value: &ParamArrayPattern) -> Result<Self, Self::Error> {
let mut new = vec![];
for elem in value.elems.non_defaults.iter() {
new.push(ConstPosArg::new(ConstExpr::try_from(&elem.pat)?));
}
let elems = ConstArgs::pos_only(new, None);
Ok(ConstExpr::Array(ConstArray::Normal(ConstNormalArray::new(
value.l_sqbr.clone(),
value.r_sqbr.clone(),
elems,
None,
))))
}
}
impl ParamArrayPattern {
pub const fn new(l_sqbr: Token, elems: Params, r_sqbr: Token) -> Self {
Self {
@ -3722,6 +3776,32 @@ impl NestedDisplay for ParamTuplePattern {
impl_display_from_nested!(ParamTuplePattern);
impl_locational!(ParamTuplePattern, elems);
impl TryFrom<&ParamTuplePattern> for Expr {
type Error = ();
fn try_from(value: &ParamTuplePattern) -> Result<Self, Self::Error> {
let mut new = vec![];
for elem in value.elems.non_defaults.iter() {
new.push(PosArg::new(Expr::try_from(&elem.pat)?));
}
let elems = Args::pos_only(new, value.elems.parens.clone());
Ok(Expr::Tuple(Tuple::Normal(NormalTuple::new(elems))))
}
}
impl TryFrom<&ParamTuplePattern> for ConstExpr {
type Error = ();
fn try_from(value: &ParamTuplePattern) -> Result<Self, Self::Error> {
let mut new = vec![];
for elem in value.elems.non_defaults.iter() {
new.push(ConstPosArg::new(ConstExpr::try_from(&elem.pat)?));
}
let elems = ConstArgs::pos_only(new, value.elems.parens.clone());
Ok(ConstExpr::Tuple(ConstTuple::new(elems)))
}
}
impl ParamTuplePattern {
pub const fn new(elems: Params) -> Self {
Self { elems }
@ -3829,6 +3909,20 @@ impl NestedDisplay for ParamPattern {
}
}
impl TryFrom<&ParamPattern> for Expr {
type Error = ();
fn try_from(value: &ParamPattern) -> Result<Self, Self::Error> {
match value {
// ParamPattern::Discard(token) => Ok(Expr::Accessor(Accessor::local(token.clone()))),
ParamPattern::VarName(name) => Ok(Expr::Accessor(Accessor::local(name.0.clone()))),
ParamPattern::Lit(lit) => Ok(Expr::Literal(lit.clone())),
ParamPattern::Array(array) => Expr::try_from(array),
ParamPattern::Tuple(tuple) => Expr::try_from(tuple),
_ => Err(()),
}
}
}
impl_display_from_nested!(ParamPattern);
impl_locational_for_enum!(ParamPattern; Discard, VarName, Lit, Array, Tuple, Record, Ref, RefMut);

View file

@ -1068,6 +1068,7 @@ impl Desugarer {
param.pat = buf_param;
}
ParamPattern::Array(arr) => {
let expr = Expr::try_from(&*arr);
let (buf_name, buf_param) = self.gen_buf_nd_param(arr.loc());
for (n, elem) in arr.elems.non_defaults.iter_mut().enumerate() {
insertion_idx = self.desugar_nested_param_pattern(
@ -1093,7 +1094,17 @@ impl Desugarer {
ConstExpr::Lit(len.clone()),
Some((arr.l_sqbr.clone(), arr.r_sqbr.clone())),
);
let t_spec_as_expr = Self::dummy_array_expr(len);
// [1, 2] -> ...
// => _: {[1, 2]} -> ...
let t_spec_as_expr = if let Ok(expr) = expr {
Expr::Set(astSet::Normal(NormalSet::new(
Token::DUMMY,
Token::DUMMY,
Args::single(PosArg::new(expr)),
)))
} else {
Self::dummy_array_expr(len)
};
param.t_spec = Some(TypeSpecWithOp::new(
Token::dummy(TokenKind::Colon, ":"),
TypeSpec::Array(t_spec),

View file

@ -51,6 +51,13 @@ match! k:
0 => print! "zero"
_ => print! "\{k}"
ab = match ["a", "b"]:
["a", "a"] -> "aa"
["b", "a"] -> "ba"
["a", "b"] -> "ab"
[_, _] -> "other"
assert ab == "ab"
arrs = [[0, 1], [2, 3]]
for! arrs, arr =>