mirror of
https://github.com/RustPython/RustPython.git
synced 2026-10-28 10:44:36 +08:00
* Align compiler and AST behavior with CPython
Update the compiler pipeline, AST module support, and related VM compile/eval paths toward CPython 3.14 behavior.
Use upstream Ruff parser crates directly and keep RustPython-specific syntax preflight handling in the compile path.
Refresh opcode metadata, snapshots, and targeted tests for the aligned bytecode and AST behavior.
* fix
* Fix PR 8138 CI failures
* Fix match mapping wildcard scan complexity
* fixes
* Use Ruff runtime AST fields
* Minimize residual patch diff
* refactor error handling
* Remove _ast conversion context wrappers
* Clean up _ast conversion glue and compiler warning escalation
Rename the Node conversion parameter `ctx` to `vm` throughout the _ast
module.
Remove the unused compile_program, compile_program_single,
compile_block_expression, and compile_expression forwarders; compile_top
stays as the entry point.
Stash an escalated compiler SyntaxWarning so a non-SyntaxWarning category
propagates unchanged instead of being rewritten to SyntaxError, matching
PyErr_ExceptionMatches(SyntaxWarning) in compiler_warn. Drop the now-unused
CompileWarningError::into_codegen_error.
Replace the PositionalArguments two-variant enum with a struct holding a
shared range and a PositionalArgumentsKind enum.
Assisted-by: Claude
* Represent compiler flags as a CompilerFlags bitflags
Replace the loose PY_CF_*/CO_* i32 constants in compile_mode with a
CompilerFlags bitflags covering the PyCF_* flags and __future__
CO_FUTURE_* bits. The Python-visible ast.PyCF_* attribute values are
derived from it via bits(); parser input modes stay plain consts.
builtins::compile and the compile_string flag handling test flags
through CompilerFlags::contains instead of raw bit math.
Assisted-by: Claude
* Fix PR 8138 test regressions
* Fix PR 8138 CI failures
* Avoid shell interpolation in Linux deps action
* Fix review findings in compiler/AST changes
- frame.rs: compute the MATCH_CLASS class name lazily so a successful
match no longer takes the type name lock or allocates; the
__match_args__-not-a-tuple branch reuses it instead of recomputing.
- _ast/constant.rs: add the missing leading space to the with_recursion
label ("maximum recursion depth exceeded during compilation").
- sys.set_int_max_str_digits: restore the "maxdigits must be 0 or larger
than {n}" error text.
- codegen: set CO_MAXBLOCKS to 20 in both ir.rs and compile.rs.
- _ast/exception.rs: extract the duplicated excepthandler node guard
into ensure_excepthandler_node.
- codegen: correct the validate_keywords doc comment.
- Drop redundant "CPython" qualifiers from comments added in this branch.
Assisted-by: Claude
186 lines
7.7 KiB
Rust
186 lines
7.7 KiB
Rust
use super::*;
|
|
use rustpython_compiler_core::SourceFile;
|
|
|
|
// sum
|
|
impl Node for ast::BoolOp {
|
|
fn ast_to_object(self, vm: &VirtualMachine, _source_file: &SourceFile) -> PyObjectRef {
|
|
let node_type = match self {
|
|
Self::And => pyast::NodeBoolOpAnd::static_type(),
|
|
Self::Or => pyast::NodeBoolOpOr::static_type(),
|
|
};
|
|
singleton_node_to_object(vm, node_type)
|
|
}
|
|
|
|
fn ast_from_object(
|
|
vm: &VirtualMachine,
|
|
_source_file: &SourceFile,
|
|
object: PyObjectRef,
|
|
) -> PyResult<Self> {
|
|
Ok(
|
|
if is_node_instance(vm, &object, pyast::NodeBoolOpAnd::static_type())? {
|
|
Self::And
|
|
} else if is_node_instance(vm, &object, pyast::NodeBoolOpOr::static_type())? {
|
|
Self::Or
|
|
} else {
|
|
return Err(vm.new_type_error(format!(
|
|
"expected some sort of boolop, but got {}",
|
|
object.repr(vm)?
|
|
)));
|
|
},
|
|
)
|
|
}
|
|
}
|
|
|
|
// sum
|
|
impl Node for ast::Operator {
|
|
fn ast_to_object(self, vm: &VirtualMachine, _source_file: &SourceFile) -> PyObjectRef {
|
|
let node_type = match self {
|
|
Self::Add => pyast::NodeOperatorAdd::static_type(),
|
|
Self::Sub => pyast::NodeOperatorSub::static_type(),
|
|
Self::Mult => pyast::NodeOperatorMult::static_type(),
|
|
Self::MatMult => pyast::NodeOperatorMatMult::static_type(),
|
|
Self::Div => pyast::NodeOperatorDiv::static_type(),
|
|
Self::Mod => pyast::NodeOperatorMod::static_type(),
|
|
Self::Pow => pyast::NodeOperatorPow::static_type(),
|
|
Self::LShift => pyast::NodeOperatorLShift::static_type(),
|
|
Self::RShift => pyast::NodeOperatorRShift::static_type(),
|
|
Self::BitOr => pyast::NodeOperatorBitOr::static_type(),
|
|
Self::BitXor => pyast::NodeOperatorBitXor::static_type(),
|
|
Self::BitAnd => pyast::NodeOperatorBitAnd::static_type(),
|
|
Self::FloorDiv => pyast::NodeOperatorFloorDiv::static_type(),
|
|
};
|
|
singleton_node_to_object(vm, node_type)
|
|
}
|
|
|
|
fn ast_from_object(
|
|
vm: &VirtualMachine,
|
|
_source_file: &SourceFile,
|
|
object: PyObjectRef,
|
|
) -> PyResult<Self> {
|
|
Ok(
|
|
if is_node_instance(vm, &object, pyast::NodeOperatorAdd::static_type())? {
|
|
Self::Add
|
|
} else if is_node_instance(vm, &object, pyast::NodeOperatorSub::static_type())? {
|
|
Self::Sub
|
|
} else if is_node_instance(vm, &object, pyast::NodeOperatorMult::static_type())? {
|
|
Self::Mult
|
|
} else if is_node_instance(vm, &object, pyast::NodeOperatorMatMult::static_type())? {
|
|
Self::MatMult
|
|
} else if is_node_instance(vm, &object, pyast::NodeOperatorDiv::static_type())? {
|
|
Self::Div
|
|
} else if is_node_instance(vm, &object, pyast::NodeOperatorMod::static_type())? {
|
|
Self::Mod
|
|
} else if is_node_instance(vm, &object, pyast::NodeOperatorPow::static_type())? {
|
|
Self::Pow
|
|
} else if is_node_instance(vm, &object, pyast::NodeOperatorLShift::static_type())? {
|
|
Self::LShift
|
|
} else if is_node_instance(vm, &object, pyast::NodeOperatorRShift::static_type())? {
|
|
Self::RShift
|
|
} else if is_node_instance(vm, &object, pyast::NodeOperatorBitOr::static_type())? {
|
|
Self::BitOr
|
|
} else if is_node_instance(vm, &object, pyast::NodeOperatorBitXor::static_type())? {
|
|
Self::BitXor
|
|
} else if is_node_instance(vm, &object, pyast::NodeOperatorBitAnd::static_type())? {
|
|
Self::BitAnd
|
|
} else if is_node_instance(vm, &object, pyast::NodeOperatorFloorDiv::static_type())? {
|
|
Self::FloorDiv
|
|
} else {
|
|
return Err(vm.new_type_error(format!(
|
|
"expected some sort of operator, but got {}",
|
|
object.repr(vm)?
|
|
)));
|
|
},
|
|
)
|
|
}
|
|
}
|
|
|
|
// sum
|
|
impl Node for ast::UnaryOp {
|
|
fn ast_to_object(self, vm: &VirtualMachine, _source_file: &SourceFile) -> PyObjectRef {
|
|
let node_type = match self {
|
|
Self::Invert => pyast::NodeUnaryOpInvert::static_type(),
|
|
Self::Not => pyast::NodeUnaryOpNot::static_type(),
|
|
Self::UAdd => pyast::NodeUnaryOpUAdd::static_type(),
|
|
Self::USub => pyast::NodeUnaryOpUSub::static_type(),
|
|
};
|
|
singleton_node_to_object(vm, node_type)
|
|
}
|
|
|
|
fn ast_from_object(
|
|
vm: &VirtualMachine,
|
|
_source_file: &SourceFile,
|
|
object: PyObjectRef,
|
|
) -> PyResult<Self> {
|
|
Ok(
|
|
if is_node_instance(vm, &object, pyast::NodeUnaryOpInvert::static_type())? {
|
|
Self::Invert
|
|
} else if is_node_instance(vm, &object, pyast::NodeUnaryOpNot::static_type())? {
|
|
Self::Not
|
|
} else if is_node_instance(vm, &object, pyast::NodeUnaryOpUAdd::static_type())? {
|
|
Self::UAdd
|
|
} else if is_node_instance(vm, &object, pyast::NodeUnaryOpUSub::static_type())? {
|
|
Self::USub
|
|
} else {
|
|
return Err(vm.new_type_error(format!(
|
|
"expected some sort of unaryop, but got {}",
|
|
object.repr(vm)?
|
|
)));
|
|
},
|
|
)
|
|
}
|
|
}
|
|
|
|
// sum
|
|
impl Node for ast::CmpOp {
|
|
fn ast_to_object(self, vm: &VirtualMachine, _source_file: &SourceFile) -> PyObjectRef {
|
|
let node_type = match self {
|
|
Self::Eq => pyast::NodeCmpOpEq::static_type(),
|
|
Self::NotEq => pyast::NodeCmpOpNotEq::static_type(),
|
|
Self::Lt => pyast::NodeCmpOpLt::static_type(),
|
|
Self::LtE => pyast::NodeCmpOpLtE::static_type(),
|
|
Self::Gt => pyast::NodeCmpOpGt::static_type(),
|
|
Self::GtE => pyast::NodeCmpOpGtE::static_type(),
|
|
Self::Is => pyast::NodeCmpOpIs::static_type(),
|
|
Self::IsNot => pyast::NodeCmpOpIsNot::static_type(),
|
|
Self::In => pyast::NodeCmpOpIn::static_type(),
|
|
Self::NotIn => pyast::NodeCmpOpNotIn::static_type(),
|
|
};
|
|
singleton_node_to_object(vm, node_type)
|
|
}
|
|
|
|
fn ast_from_object(
|
|
vm: &VirtualMachine,
|
|
_source_file: &SourceFile,
|
|
object: PyObjectRef,
|
|
) -> PyResult<Self> {
|
|
Ok(
|
|
if is_node_instance(vm, &object, pyast::NodeCmpOpEq::static_type())? {
|
|
Self::Eq
|
|
} else if is_node_instance(vm, &object, pyast::NodeCmpOpNotEq::static_type())? {
|
|
Self::NotEq
|
|
} else if is_node_instance(vm, &object, pyast::NodeCmpOpLt::static_type())? {
|
|
Self::Lt
|
|
} else if is_node_instance(vm, &object, pyast::NodeCmpOpLtE::static_type())? {
|
|
Self::LtE
|
|
} else if is_node_instance(vm, &object, pyast::NodeCmpOpGt::static_type())? {
|
|
Self::Gt
|
|
} else if is_node_instance(vm, &object, pyast::NodeCmpOpGtE::static_type())? {
|
|
Self::GtE
|
|
} else if is_node_instance(vm, &object, pyast::NodeCmpOpIs::static_type())? {
|
|
Self::Is
|
|
} else if is_node_instance(vm, &object, pyast::NodeCmpOpIsNot::static_type())? {
|
|
Self::IsNot
|
|
} else if is_node_instance(vm, &object, pyast::NodeCmpOpIn::static_type())? {
|
|
Self::In
|
|
} else if is_node_instance(vm, &object, pyast::NodeCmpOpNotIn::static_type())? {
|
|
Self::NotIn
|
|
} else {
|
|
return Err(vm.new_type_error(format!(
|
|
"expected some sort of cmpop, but got {}",
|
|
object.repr(vm)?
|
|
)));
|
|
},
|
|
)
|
|
}
|
|
}
|