mirror of
https://github.com/RustPython/RustPython.git
synced 2026-10-28 18:59:04 +08:00
Support signed numeric constants in match pattern ASTs (#9279)
Recognize numeric Expr::Constant values when validating signed literal patterns, alongside parser-produced NumberLiteral nodes. Python AST conversion uses the former representation. Accept unary plus as well as minus and fold signed real/imaginary and complex patterns consistently. Boolean and non-numeric constants remain excluded. Preserve the existing parser-produced literal path and do not change source grammar. Assisted-by: OpenAI Codex:model-version-unavailable
This commit is contained in:
1 parent
aba1f5cf69
commit
43368209c5
2 files changed
+24
-9
No files matched your search
@@ -12288,12 +12288,12 @@ impl<'warnings> Compiler<'warnings> {
|
||||
&mut self,
|
||||
expr: &ast::Expr,
|
||||
) -> CompileResult<Option<ConstantData>> {
|
||||
// CPython 3.14 ast_preprocess.c::fold_const_match_patterns()
|
||||
// CPython ast_preprocess.c::fold_const_match_patterns()
|
||||
// folds only the constant forms needed by match patterns before
|
||||
// codegen_pattern_value()/codegen_pattern_mapping_key() visit them.
|
||||
Ok(match expr {
|
||||
ast::Expr::UnaryOp(ast::ExprUnaryOp {
|
||||
op: ast::UnaryOp::USub,
|
||||
op: op @ (ast::UnaryOp::UAdd | ast::UnaryOp::USub),
|
||||
operand,
|
||||
..
|
||||
}) => {
|
||||
@@ -12301,7 +12301,11 @@ impl<'warnings> Compiler<'warnings> {
|
||||
else {
|
||||
return Ok(None);
|
||||
};
|
||||
Self::try_negate_match_pattern_constant(constant)
|
||||
if *op == ast::UnaryOp::USub {
|
||||
Self::try_negate_match_pattern_constant(constant)
|
||||
} else {
|
||||
Some(constant)
|
||||
}
|
||||
}
|
||||
ast::Expr::BinOp(ast::ExprBinOp {
|
||||
left, op, right, ..
|
||||
@@ -12326,7 +12330,7 @@ impl<'warnings> Compiler<'warnings> {
|
||||
return Ok(Some(constant));
|
||||
}
|
||||
let ast::Expr::UnaryOp(ast::ExprUnaryOp {
|
||||
op: ast::UnaryOp::USub,
|
||||
op: op @ (ast::UnaryOp::UAdd | ast::UnaryOp::USub),
|
||||
operand,
|
||||
..
|
||||
}) = expr
|
||||
@@ -12336,7 +12340,11 @@ impl<'warnings> Compiler<'warnings> {
|
||||
let Some(constant) = self.try_compile_match_pattern_real_constant(operand)? else {
|
||||
return Ok(None);
|
||||
};
|
||||
Ok(Self::try_negate_match_pattern_constant(constant))
|
||||
Ok(if *op == ast::UnaryOp::USub {
|
||||
Self::try_negate_match_pattern_constant(constant)
|
||||
} else {
|
||||
Some(constant)
|
||||
})
|
||||
}
|
||||
|
||||
fn try_compile_match_pattern_real_constant(
|
||||
|
||||
@@ -191,6 +191,13 @@ fn validate_interpolated_elements<'a>(
|
||||
}
|
||||
|
||||
fn ensure_literal_number(expr: &ast::Expr, allow_real: bool, allow_imaginary: bool) -> bool {
|
||||
if let Some(constant) = ast_constant_value(expr) {
|
||||
return match constant {
|
||||
ConstantData::Integer { .. } | ConstantData::Float { .. } => allow_real,
|
||||
ConstantData::Complex { .. } => allow_imaginary,
|
||||
_ => false,
|
||||
};
|
||||
}
|
||||
let ast::Expr::NumberLiteral(number) = expr else {
|
||||
return false;
|
||||
};
|
||||
@@ -200,11 +207,11 @@ fn ensure_literal_number(expr: &ast::Expr, allow_real: bool, allow_imaginary: bo
|
||||
}
|
||||
}
|
||||
|
||||
fn ensure_literal_negative(expr: &ast::Expr, allow_real: bool, allow_imaginary: bool) -> bool {
|
||||
fn ensure_literal_signed(expr: &ast::Expr, allow_real: bool, allow_imaginary: bool) -> bool {
|
||||
let ast::Expr::UnaryOp(unary) = expr else {
|
||||
return false;
|
||||
};
|
||||
if unary.op != ast::UnaryOp::USub {
|
||||
if !matches!(unary.op, ast::UnaryOp::UAdd | ast::UnaryOp::USub) {
|
||||
return false;
|
||||
}
|
||||
ensure_literal_number(&unary.operand, allow_real, allow_imaginary)
|
||||
@@ -218,7 +225,7 @@ fn ensure_literal_complex(expr: &ast::Expr) -> bool {
|
||||
return false;
|
||||
}
|
||||
let real_left = ensure_literal_number(&bin.left, true, false)
|
||||
|| ensure_literal_negative(&bin.left, true, false);
|
||||
|| ensure_literal_signed(&bin.left, true, false);
|
||||
real_left && ensure_literal_number(&bin.right, false, true)
|
||||
}
|
||||
|
||||
@@ -244,7 +251,7 @@ fn validate_pattern_match_value(vm: &VirtualMachine, expr: &ast::Expr) -> PyResu
|
||||
Ok(())
|
||||
}
|
||||
ast::Expr::Attribute(_) => Ok(()),
|
||||
ast::Expr::UnaryOp(_) if ensure_literal_negative(expr, true, true) => Ok(()),
|
||||
ast::Expr::UnaryOp(_) if ensure_literal_signed(expr, true, true) => Ok(()),
|
||||
ast::Expr::BinOp(_) if ensure_literal_complex(expr) => Ok(()),
|
||||
ast::Expr::FString(_) | ast::Expr::TString(_) => Ok(()),
|
||||
ast::Expr::BooleanLiteral(_)
|
||||
|
||||
Reference in new issue
Block a user