@@ -15,14 +15,13 @@ use malachite_bigint::BigInt;
1515use num_complex:: Complex ;
1616use num_traits:: { Num , ToPrimitive } ;
1717use ruff_python_ast:: {
18- Alias , Arguments , BoolOp , CmpOp , Comprehension , ConversionFlag , DebugText , Decorator , DictItem , ExceptHandler , ExceptHandlerExceptHandler , Expr , ExprAttribute , ExprBoolOp , ExprFString , ExprList , ExprName , ExprStarred , ExprSubscript , ExprTuple , ExprUnaryOp , FString , FStringElement , FStringElements , FStringPart , Identifier , Int , Keyword , MatchCase , ModExpression , ModModule , Operator , Parameters , Pattern , PatternMatchAs , PatternMatchOr , PatternMatchSingleton , PatternMatchStar , PatternMatchValue , Singleton , Stmt , StmtExpr , TypeParam , TypeParamParamSpec , TypeParamTypeVar , TypeParamTypeVarTuple , TypeParams , UnaryOp , WithItem
18+ Alias , Arguments , BoolOp , CmpOp , Comprehension , ConversionFlag , DebugText , Decorator , DictItem , ExceptHandler , ExceptHandlerExceptHandler , Expr , ExprAttribute , ExprBoolOp , ExprFString , ExprList , ExprName , ExprStarred , ExprSubscript , ExprTuple , ExprUnaryOp , FString , FStringElement , FStringElements , FStringPart , Identifier , Int , Keyword , MatchCase , ModExpression , ModModule , Operator , Parameters , Pattern , PatternMatchAs , PatternMatchOr , PatternMatchSequence , PatternMatchSingleton , PatternMatchStar , PatternMatchValue , Singleton , Stmt , StmtExpr , TypeParam , TypeParamParamSpec , TypeParamTypeVar , TypeParamTypeVarTuple , TypeParams , UnaryOp , WithItem
1919} ;
2020use ruff_source_file:: OneIndexed ;
2121use ruff_text_size:: { Ranged , TextRange } ;
2222// use rustpython_ast::located::{self as located_ast, Located};
2323use rustpython_compiler_core:: {
24- Mode ,
25- bytecode:: { self , Arg as OpArgMarker , CodeObject , ConstantData , Instruction , OpArg , OpArgType } ,
24+ bytecode:: { self , Arg as OpArgMarker , CodeObject , ComparisonOperator , ConstantData , Instruction , OpArg , OpArgType } , Mode
2625} ;
2726use rustpython_compiler_source:: SourceCode ;
2827// use rustpython_parser_core::source_code::{LineNumber, SourceLocation};
@@ -1954,6 +1953,49 @@ impl Compiler<'_> {
19541953 Ok ( ( ) )
19551954 }
19561955
1956+ fn pattern_helper_sequence_subscr (
1957+ & mut self ,
1958+ patterns : & [ Pattern ] ,
1959+ star : usize ,
1960+ pc : & mut PatternContext ,
1961+ ) -> CompileResult < ( ) > {
1962+ // Keep the subject around for extracting elements.
1963+ pc. on_top += 1 ;
1964+ let size = patterns. len ( ) ;
1965+ for i in 0 ..size {
1966+ let pattern = & patterns[ i] ;
1967+ // if pattern.is_wildcard() {
1968+ // continue;
1969+ // }
1970+ if i == star {
1971+ // This must be a starred wildcard.
1972+ // assert!(pattern.is_star_wildcard());
1973+ continue ;
1974+ }
1975+ // Duplicate the subject.
1976+ emit ! ( self , Instruction :: CopyItem { index: 1 as u32 } ) ;
1977+ if i < star {
1978+ // For indices before the star, use a nonnegative index equal to i.
1979+ self . emit_load_const ( ConstantData :: Integer { value : i. into ( ) } ) ;
1980+ } else {
1981+ // For indices after the star, compute a nonnegative index:
1982+ // index = len(subject) - (size - i)
1983+ emit ! ( self , Instruction :: GET_LEN ) ;
1984+ emit ! ( self , Instruction :: LoadConstNew { arg: PyObject :: from_ssize_t( ( size - i) as isize ) } ) ;
1985+ // Subtract to compute the correct index.
1986+ emit ! ( self , Instruction :: BINARY { arg: BinaryOp :: Sub } ) ;
1987+ }
1988+ // Use BINARY_OP/NB_SUBSCR to extract the element.
1989+ emit ! ( self , Instruction :: BINARY_OP { arg: NB_SUBSCR } ) ;
1990+ // Compile the subpattern in irrefutable mode.
1991+ self . compiler_pattern_subpattern ( pattern, pc) ?;
1992+ }
1993+ // Pop the subject off the stack.
1994+ pc. on_top = pc. on_top . saturating_sub ( 1 ) ;
1995+ emit ! ( self , Instruction :: POP_TOP ) ;
1996+ Ok ( ( ) )
1997+ }
1998+
19571999 fn compile_pattern_subpattern (
19582000 & mut self ,
19592001 p : & Pattern ,
@@ -2145,6 +2187,63 @@ impl Compiler<'_> {
21452187 Ok ( ( ) )
21462188 }
21472189
2190+ fn codegen_pattern_sequence ( & mut self , p : & PatternMatchSequence , pc : & mut PatternContext ) -> CompileResult < ( ) > {
2191+ // Ensure the pattern is a MatchSequence.
2192+ let patterns = p. patterns ; // a slice of Pattern
2193+ let size = patterns. len ( ) ;
2194+ let mut star: Option < usize > = None ;
2195+ let mut only_wildcard = true ;
2196+ let mut star_wildcard = false ;
2197+
2198+ // Find a starred pattern, if it exists. There may be at most one.
2199+ for ( i, pattern) in patterns. iter ( ) . enumerate ( ) {
2200+ if pattern. is_match_star ( ) {
2201+ if star. is_some ( ) {
2202+ return Err ( self . error ( CodegenErrorType :: MultipleStarArgs ) ) ;
2203+ // return self._py_compile_error(loc(p), "multiple starred names in sequence pattern");
2204+ }
2205+ // star wildcard check
2206+ star_wildcard = pattern. as_match_star ( ) . map ( |m| m. name . is_none ( ) ) . unwrap_or ( false ) ;
2207+ only_wildcard &= star_wildcard;
2208+ star = Some ( i) ;
2209+ continue ;
2210+ }
2211+ // wildcard check
2212+ only_wildcard &= pattern. as_match_as ( ) . map ( |m| m. name . is_none ( ) ) . unwrap_or ( false ) ;
2213+ }
2214+
2215+ // Keep the subject on top during the sequence and length checks.
2216+ pc. on_top += 1 ;
2217+ emit ! ( self , Instruction :: MatchSequence ) ;
2218+ self . jump_to_fail_pop ( pc, JumpOp :: PopJumpIfFalse ) ?;
2219+
2220+ if star. is_none ( ) {
2221+ // No star: len(subject) == size
2222+ emit ! ( self , Instruction :: GetLen ) ;
2223+ self . emit_load_const ( ConstantData :: Integer { value : size. into ( ) } ) ;
2224+ emit ! ( self , Instruction :: CompareOperation { op: ComparisonOperator :: Equal } ) ;
2225+ self . jump_to_fail_pop ( pc, JumpOp :: PopJumpIfFalse ) ?;
2226+ } else if size > 1 {
2227+ // Star exists: len(subject) >= size - 1
2228+ emit ! ( self , Instruction :: GetLen ) ;
2229+ self . emit_load_const ( ConstantData :: Integer { value : ( size - 1 ) . into ( ) } ) ;
2230+ emit ! ( self , Instruction :: CompareOperation { op: ComparisonOperator :: GreaterOrEqual } ) ;
2231+ self . jump_to_fail_pop ( pc, JumpOp :: PopJumpIfFalse ) ?;
2232+ }
2233+
2234+ // Whatever comes next should consume the subject.
2235+ pc. on_top -= 1 ;
2236+ if only_wildcard {
2237+ // Patterns like: [] / [_] / [_, _] / [*_] / [_, *_] / [_, _, *_] / etc.
2238+ emit ! ( self , Instruction :: Pop ) ;
2239+ } else if star_wildcard {
2240+ self . pattern_helper_sequence_subscr ( patterns, star, pc) ?;
2241+ } else {
2242+ self . pattern_helper_sequence_unpack ( patterns, star, pc) ?;
2243+ }
2244+ Ok ( ( ) )
2245+ }
2246+
21482247 fn compile_pattern_value (
21492248 & mut self ,
21502249 p : & PatternMatchValue ,
0 commit comments