mirror of
https://github.com/RustPython/RustPython.git
synced 2026-10-28 10:44:36 +08:00
* Borrow tp_descr_get/tp_init arguments and by-value public helpers - DescrGetFunc and GetDescriptor::descr_get take (&PyObject, Option<&PyObject>, Option<&PyObject>); impls call .to_owned() where they store or return an argument. - InitFunc takes &PyObject and Initializer::init takes &Py<Self>. - VirtualMachine::get_attribute_opt, print_exception, call_get_descriptor(_specific) and other helpers flagged by clippy::needless_pass_by_value take &PyObject / &Py<T>; callers in crates/, examples/ and tests/ drop the clones made for the call. Assisted-by: Claude Code:claude-opus-5-5 Assisted-by: Grok CLI:grok-4.7 * Pass the borrowed zelf to internal_close in WindowsConsoleIO init Assisted-by: Claude Code:claude-opus-5-5 * Fix borrowed signatures missed by the rebase OrderedDict.init, classmethod_descriptor.descr_get, and the warnings get_attribute_opt callers still used owned handles. Assisted-by: Grok CLI:grok-4.7
1824 lines
63 KiB
Rust
1824 lines
63 KiB
Rust
use super::*;
|
|
use crate::stdlib::_ast::argument::{
|
|
KeywordArguments, PositionalArguments, merge_class_def_args, split_class_def_args,
|
|
};
|
|
use crate::stdlib::_ast::exception::except_handler_from_object_unvalidated_range;
|
|
use crate::stdlib::_ast::type_parameters::type_params_from_field;
|
|
use rustpython_compiler_core::SourceFile;
|
|
|
|
fn runtime_decorator_expr_list(values: &[Option<ast::Decorator>]) -> Vec<Option<ast::Expr>> {
|
|
values
|
|
.iter()
|
|
.map(|value| value.as_ref().map(|decorator| decorator.expression.clone()))
|
|
.collect()
|
|
}
|
|
|
|
fn lower_runtime_decorator_list(values: Vec<Option<ast::Decorator>>) -> Vec<ast::Decorator> {
|
|
values
|
|
.into_iter()
|
|
.map(|value| {
|
|
value.unwrap_or_else(|| ast::Decorator {
|
|
range: Default::default(),
|
|
node_index: Default::default(),
|
|
expression: runtime_null_expr_placeholder(),
|
|
})
|
|
})
|
|
.collect()
|
|
}
|
|
|
|
fn definition_range_from_name(
|
|
source_file: &SourceFile,
|
|
name_start: TextSize,
|
|
end: TextSize,
|
|
keyword: &str,
|
|
) -> TextRange {
|
|
let source_code = source_file.to_source_code();
|
|
let line = source_code.line_index(name_start);
|
|
let line_start = source_code.line_start(line);
|
|
let keyword_start = source_code
|
|
.slice(TextRange::new(line_start, name_start))
|
|
.rfind(keyword)
|
|
.map_or(line_start, |offset| {
|
|
line_start + TextSize::new(offset as u32)
|
|
});
|
|
TextRange::new(keyword_start, end)
|
|
}
|
|
|
|
fn runtime_stmt_type_comment(
|
|
vm: &VirtualMachine,
|
|
type_comment: Option<PyObjectRef>,
|
|
) -> (Option<Box<str>>, Option<Vec<u8>>) {
|
|
type_comment.map_or((None, None), |type_comment| {
|
|
super::constant::runtime_string_from_pyobject(vm, &type_comment)
|
|
})
|
|
}
|
|
|
|
fn runtime_stmt_type_comment_object(
|
|
vm: &VirtualMachine,
|
|
value: Option<Box<str>>,
|
|
bytes: Option<Vec<u8>>,
|
|
) -> PyObjectRef {
|
|
super::constant::runtime_stmt_type_comment_object(vm, value, bytes)
|
|
.unwrap_or_else(|| vm.ctx.none())
|
|
}
|
|
|
|
// sum
|
|
impl Node for ast::Stmt {
|
|
fn ast_to_object(self, vm: &VirtualMachine, source_file: &SourceFile) -> PyObjectRef {
|
|
match self {
|
|
Self::FunctionDef(cons) => cons.ast_to_object(vm, source_file),
|
|
Self::ClassDef(cons) => cons.ast_to_object(vm, source_file),
|
|
Self::Return(cons) => cons.ast_to_object(vm, source_file),
|
|
Self::Delete(cons) => cons.ast_to_object(vm, source_file),
|
|
Self::Assign(cons) => cons.ast_to_object(vm, source_file),
|
|
Self::TypeAlias(cons) => cons.ast_to_object(vm, source_file),
|
|
Self::AugAssign(cons) => cons.ast_to_object(vm, source_file),
|
|
Self::AnnAssign(cons) => cons.ast_to_object(vm, source_file),
|
|
Self::For(cons) => cons.ast_to_object(vm, source_file),
|
|
Self::While(cons) => cons.ast_to_object(vm, source_file),
|
|
Self::If(cons) => cons.ast_to_object(vm, source_file),
|
|
Self::With(cons) => cons.ast_to_object(vm, source_file),
|
|
Self::Match(cons) => cons.ast_to_object(vm, source_file),
|
|
Self::Raise(cons) => cons.ast_to_object(vm, source_file),
|
|
Self::Try(cons) => cons.ast_to_object(vm, source_file),
|
|
Self::Assert(cons) => cons.ast_to_object(vm, source_file),
|
|
Self::Import(cons) => cons.ast_to_object(vm, source_file),
|
|
Self::ImportFrom(cons) => cons.ast_to_object(vm, source_file),
|
|
Self::Global(cons) => cons.ast_to_object(vm, source_file),
|
|
Self::Nonlocal(cons) => cons.ast_to_object(vm, source_file),
|
|
Self::Expr(cons) => cons.ast_to_object(vm, source_file),
|
|
Self::Pass(cons) => cons.ast_to_object(vm, source_file),
|
|
Self::Break(cons) => cons.ast_to_object(vm, source_file),
|
|
Self::Continue(cons) => cons.ast_to_object(vm, source_file),
|
|
Self::IpyEscapeCommand(_) => {
|
|
unreachable!("IPython escape command is not part of Python AST")
|
|
}
|
|
}
|
|
}
|
|
|
|
fn ast_from_object(
|
|
vm: &VirtualMachine,
|
|
source_file: &SourceFile,
|
|
object: PyObjectRef,
|
|
) -> PyResult<Self> {
|
|
if vm.is_none(&object) {
|
|
return Err(vm.new_value_error("None disallowed in statement list"));
|
|
}
|
|
enum StmtKind {
|
|
FunctionDef { is_async: bool },
|
|
ClassDef,
|
|
Return,
|
|
Delete,
|
|
Assign,
|
|
TypeAlias,
|
|
AugAssign,
|
|
AnnAssign,
|
|
For { is_async: bool },
|
|
While,
|
|
If,
|
|
With { is_async: bool },
|
|
Match,
|
|
Raise,
|
|
Try { is_star: bool },
|
|
Assert,
|
|
Import,
|
|
ImportFrom,
|
|
Global,
|
|
Nonlocal,
|
|
Expr,
|
|
Pass,
|
|
Break,
|
|
Continue,
|
|
}
|
|
let kind = if is_node_instance(vm, &object, pyast::NodeStmtFunctionDef::static_type())? {
|
|
StmtKind::FunctionDef { is_async: false }
|
|
} else if is_node_instance(vm, &object, pyast::NodeStmtAsyncFunctionDef::static_type())? {
|
|
StmtKind::FunctionDef { is_async: true }
|
|
} else if is_node_instance(vm, &object, pyast::NodeStmtClassDef::static_type())? {
|
|
StmtKind::ClassDef
|
|
} else if is_node_instance(vm, &object, pyast::NodeStmtReturn::static_type())? {
|
|
StmtKind::Return
|
|
} else if is_node_instance(vm, &object, pyast::NodeStmtDelete::static_type())? {
|
|
StmtKind::Delete
|
|
} else if is_node_instance(vm, &object, pyast::NodeStmtAssign::static_type())? {
|
|
StmtKind::Assign
|
|
} else if is_node_instance(vm, &object, pyast::NodeStmtTypeAlias::static_type())? {
|
|
StmtKind::TypeAlias
|
|
} else if is_node_instance(vm, &object, pyast::NodeStmtAugAssign::static_type())? {
|
|
StmtKind::AugAssign
|
|
} else if is_node_instance(vm, &object, pyast::NodeStmtAnnAssign::static_type())? {
|
|
StmtKind::AnnAssign
|
|
} else if is_node_instance(vm, &object, pyast::NodeStmtFor::static_type())? {
|
|
StmtKind::For { is_async: false }
|
|
} else if is_node_instance(vm, &object, pyast::NodeStmtAsyncFor::static_type())? {
|
|
StmtKind::For { is_async: true }
|
|
} else if is_node_instance(vm, &object, pyast::NodeStmtWhile::static_type())? {
|
|
StmtKind::While
|
|
} else if is_node_instance(vm, &object, pyast::NodeStmtIf::static_type())? {
|
|
StmtKind::If
|
|
} else if is_node_instance(vm, &object, pyast::NodeStmtWith::static_type())? {
|
|
StmtKind::With { is_async: false }
|
|
} else if is_node_instance(vm, &object, pyast::NodeStmtAsyncWith::static_type())? {
|
|
StmtKind::With { is_async: true }
|
|
} else if is_node_instance(vm, &object, pyast::NodeStmtMatch::static_type())? {
|
|
StmtKind::Match
|
|
} else if is_node_instance(vm, &object, pyast::NodeStmtRaise::static_type())? {
|
|
StmtKind::Raise
|
|
} else if is_node_instance(vm, &object, pyast::NodeStmtTry::static_type())? {
|
|
StmtKind::Try { is_star: false }
|
|
} else if is_node_instance(vm, &object, pyast::NodeStmtTryStar::static_type())? {
|
|
StmtKind::Try { is_star: true }
|
|
} else if is_node_instance(vm, &object, pyast::NodeStmtAssert::static_type())? {
|
|
StmtKind::Assert
|
|
} else if is_node_instance(vm, &object, pyast::NodeStmtImport::static_type())? {
|
|
StmtKind::Import
|
|
} else if is_node_instance(vm, &object, pyast::NodeStmtImportFrom::static_type())? {
|
|
StmtKind::ImportFrom
|
|
} else if is_node_instance(vm, &object, pyast::NodeStmtGlobal::static_type())? {
|
|
StmtKind::Global
|
|
} else if is_node_instance(vm, &object, pyast::NodeStmtNonlocal::static_type())? {
|
|
StmtKind::Nonlocal
|
|
} else if is_node_instance(vm, &object, pyast::NodeStmtExpr::static_type())? {
|
|
StmtKind::Expr
|
|
} else if is_node_instance(vm, &object, pyast::NodeStmtPass::static_type())? {
|
|
StmtKind::Pass
|
|
} else if is_node_instance(vm, &object, pyast::NodeStmtBreak::static_type())? {
|
|
StmtKind::Break
|
|
} else if is_node_instance(vm, &object, pyast::NodeStmtContinue::static_type())? {
|
|
StmtKind::Continue
|
|
} else {
|
|
return Err(vm.new_type_error(format!(
|
|
"expected some sort of stmt, but got {}",
|
|
object.repr(vm)?
|
|
)));
|
|
};
|
|
let range = stmt_range_from_object(vm, source_file, &object)?;
|
|
Ok(match kind {
|
|
StmtKind::FunctionDef { is_async } => {
|
|
Self::FunctionDef(stmt_function_def_from_object_with_range(
|
|
vm,
|
|
source_file,
|
|
&object,
|
|
range,
|
|
is_async,
|
|
)?)
|
|
}
|
|
StmtKind::ClassDef => Self::ClassDef(stmt_class_def_from_object_with_range(
|
|
vm,
|
|
source_file,
|
|
&object,
|
|
range,
|
|
)?),
|
|
StmtKind::Return => Self::Return(stmt_return_from_object_with_range(
|
|
vm,
|
|
source_file,
|
|
&object,
|
|
range,
|
|
)?),
|
|
StmtKind::Delete => Self::Delete(stmt_delete_from_object_with_range(
|
|
vm,
|
|
source_file,
|
|
&object,
|
|
range,
|
|
)?),
|
|
StmtKind::Assign => Self::Assign(stmt_assign_from_object_with_range(
|
|
vm,
|
|
source_file,
|
|
&object,
|
|
range,
|
|
)?),
|
|
StmtKind::TypeAlias => Self::TypeAlias(stmt_type_alias_from_object_with_range(
|
|
vm,
|
|
source_file,
|
|
&object,
|
|
range,
|
|
)?),
|
|
StmtKind::AugAssign => Self::AugAssign(stmt_aug_assign_from_object_with_range(
|
|
vm,
|
|
source_file,
|
|
&object,
|
|
range,
|
|
)?),
|
|
StmtKind::AnnAssign => Self::AnnAssign(stmt_ann_assign_from_object_with_range(
|
|
vm,
|
|
source_file,
|
|
&object,
|
|
range,
|
|
)?),
|
|
StmtKind::For { is_async } => Self::For(stmt_for_from_object_with_range(
|
|
vm,
|
|
source_file,
|
|
&object,
|
|
range,
|
|
is_async,
|
|
)?),
|
|
StmtKind::While => Self::While(stmt_while_from_object_with_range(
|
|
vm,
|
|
source_file,
|
|
&object,
|
|
range,
|
|
)?),
|
|
StmtKind::If => Self::If(elif_else_clause::ast_from_object_with_range(
|
|
vm,
|
|
source_file,
|
|
&object,
|
|
range,
|
|
)?),
|
|
StmtKind::With { is_async } => Self::With(stmt_with_from_object_with_range(
|
|
vm,
|
|
source_file,
|
|
&object,
|
|
range,
|
|
is_async,
|
|
)?),
|
|
StmtKind::Match => Self::Match(stmt_match_from_object_with_range(
|
|
vm,
|
|
source_file,
|
|
&object,
|
|
range,
|
|
)?),
|
|
StmtKind::Raise => Self::Raise(stmt_raise_from_object_with_range(
|
|
vm,
|
|
source_file,
|
|
&object,
|
|
range,
|
|
)?),
|
|
StmtKind::Try { is_star } => Self::Try(stmt_try_from_object_with_range(
|
|
vm,
|
|
source_file,
|
|
&object,
|
|
range,
|
|
is_star,
|
|
)?),
|
|
StmtKind::Assert => Self::Assert(stmt_assert_from_object_with_range(
|
|
vm,
|
|
source_file,
|
|
&object,
|
|
range,
|
|
)?),
|
|
StmtKind::Import => Self::Import(stmt_import_from_object_with_range(
|
|
vm,
|
|
source_file,
|
|
&object,
|
|
range,
|
|
)?),
|
|
StmtKind::ImportFrom => Self::ImportFrom(stmt_import_from_from_object_with_range(
|
|
vm,
|
|
source_file,
|
|
&object,
|
|
range,
|
|
)?),
|
|
StmtKind::Global => Self::Global(stmt_global_from_object_with_range(
|
|
vm,
|
|
source_file,
|
|
&object,
|
|
range,
|
|
)?),
|
|
StmtKind::Nonlocal => Self::Nonlocal(stmt_nonlocal_from_object_with_range(
|
|
vm,
|
|
source_file,
|
|
&object,
|
|
range,
|
|
)?),
|
|
StmtKind::Expr => Self::Expr(stmt_expr_from_object_with_range(
|
|
vm,
|
|
source_file,
|
|
&object,
|
|
range,
|
|
)?),
|
|
StmtKind::Pass => Self::Pass(stmt_pass_from_object_with_range(range)),
|
|
StmtKind::Break => Self::Break(stmt_break_from_object_with_range(range)),
|
|
StmtKind::Continue => Self::Continue(stmt_continue_from_object_with_range(range)),
|
|
})
|
|
}
|
|
}
|
|
|
|
// constructor
|
|
fn stmt_function_def_from_object_with_range(
|
|
vm: &VirtualMachine,
|
|
source_file: &SourceFile,
|
|
object: &PyObject,
|
|
range: TextRange,
|
|
is_async: bool,
|
|
) -> PyResult<ast::StmtFunctionDef> {
|
|
let typ = if is_async {
|
|
"AsyncFunctionDef"
|
|
} else {
|
|
"FunctionDef"
|
|
};
|
|
let name = get_required_identifier_field(vm, source_file, object, "name", typ)?;
|
|
let parameters = Node::ast_from_object(
|
|
vm,
|
|
source_file,
|
|
get_node_field_required(vm, object, "args", typ)?,
|
|
)?;
|
|
let body: Vec<Option<ast::Stmt>> = get_node_list_field(vm, source_file, object, "body", typ)?;
|
|
let decorator_list: Vec<Option<ast::Decorator>> =
|
|
get_node_list_field(vm, source_file, object, "decorator_list", typ)?;
|
|
let runtime_decorator_exprs = runtime_decorator_expr_list(&decorator_list);
|
|
let runtime_body = runtime_stmt_list_metadata(&body);
|
|
let runtime_decorator_list = runtime_expr_list_metadata(&runtime_decorator_exprs);
|
|
let body = lower_runtime_stmt_list(body);
|
|
let decorator_list = lower_runtime_decorator_list(decorator_list);
|
|
let returns = get_node_field_opt(vm, object, "returns")?
|
|
.map(|obj| Node::ast_from_object(vm, source_file, obj))
|
|
.transpose()?;
|
|
let (runtime_type_comment, runtime_type_comment_bytes) =
|
|
runtime_stmt_type_comment(vm, get_ast_string_field_opt(vm, object, "type_comment")?);
|
|
let type_params = type_params_from_field(vm, source_file, object, "type_params", typ)?;
|
|
Ok(ast::StmtFunctionDef {
|
|
node_index: Default::default(),
|
|
name,
|
|
parameters,
|
|
body,
|
|
decorator_list: decorator_list.into(),
|
|
returns,
|
|
type_params,
|
|
range,
|
|
is_async,
|
|
runtime_decorator_list,
|
|
runtime_type_comment,
|
|
runtime_type_comment_bytes,
|
|
runtime_body,
|
|
})
|
|
}
|
|
|
|
impl Node for ast::StmtFunctionDef {
|
|
fn ast_to_object(self, vm: &VirtualMachine, source_file: &SourceFile) -> PyObjectRef {
|
|
let Self {
|
|
node_index: _,
|
|
name,
|
|
parameters,
|
|
body,
|
|
decorator_list,
|
|
returns,
|
|
type_params,
|
|
is_async,
|
|
range,
|
|
runtime_decorator_list,
|
|
runtime_type_comment,
|
|
runtime_type_comment_bytes,
|
|
runtime_body,
|
|
} = self;
|
|
let range = definition_range_from_name(
|
|
source_file,
|
|
name.range.start(),
|
|
range.end(),
|
|
if is_async { "async" } else { "def" },
|
|
);
|
|
|
|
let cls = if !is_async {
|
|
pyast::NodeStmtFunctionDef::static_type().to_owned()
|
|
} else {
|
|
pyast::NodeStmtAsyncFunctionDef::static_type().to_owned()
|
|
};
|
|
|
|
let node = NodeAst.into_ref_with_type(vm, cls).unwrap();
|
|
let dict = node.as_object().dict().unwrap();
|
|
dict.set_item("name", name.ast_to_object(vm, source_file), vm)
|
|
.unwrap();
|
|
dict.set_item("args", parameters.ast_to_object(vm, source_file), vm)
|
|
.unwrap();
|
|
let body = runtime_body.map_or_else(
|
|
|| body.ast_to_object(vm, source_file),
|
|
|values| values.ast_to_object(vm, source_file),
|
|
);
|
|
dict.set_item("body", body, vm).unwrap();
|
|
dict.set_item(
|
|
"decorator_list",
|
|
runtime_decorator_list.map_or_else(
|
|
|| decorator_list.ast_to_object(vm, source_file),
|
|
|values| values.ast_to_object(vm, source_file),
|
|
),
|
|
vm,
|
|
)
|
|
.unwrap();
|
|
dict.set_item("returns", returns.ast_to_object(vm, source_file), vm)
|
|
.unwrap();
|
|
dict.set_item(
|
|
"type_comment",
|
|
runtime_stmt_type_comment_object(vm, runtime_type_comment, runtime_type_comment_bytes),
|
|
vm,
|
|
)
|
|
.unwrap();
|
|
dict.set_item(
|
|
"type_params",
|
|
type_params.map_or_else(
|
|
|| vm.ctx.new_list(vec![]).into(),
|
|
|tp| tp.ast_to_object(vm, source_file),
|
|
),
|
|
vm,
|
|
)
|
|
.unwrap();
|
|
node_add_location(&dict, range, vm, source_file);
|
|
node.into()
|
|
}
|
|
|
|
fn ast_from_object(
|
|
vm: &VirtualMachine,
|
|
source_file: &SourceFile,
|
|
_object: PyObjectRef,
|
|
) -> PyResult<Self> {
|
|
let is_async =
|
|
is_node_instance(vm, &_object, pyast::NodeStmtAsyncFunctionDef::static_type())?;
|
|
let typ = if is_async {
|
|
"AsyncFunctionDef"
|
|
} else {
|
|
"FunctionDef"
|
|
};
|
|
let range = range_from_object(vm, source_file, &_object, typ)?;
|
|
stmt_function_def_from_object_with_range(vm, source_file, &_object, range, is_async)
|
|
}
|
|
}
|
|
|
|
// constructor
|
|
fn stmt_class_def_from_object_with_range(
|
|
vm: &VirtualMachine,
|
|
source_file: &SourceFile,
|
|
object: &PyObject,
|
|
range: TextRange,
|
|
) -> PyResult<ast::StmtClassDef> {
|
|
let name = get_required_identifier_field(vm, source_file, object, "name", "ClassDef")?;
|
|
let bases = PositionalArguments::ast_from_field(vm, source_file, object, "bases", "ClassDef")?;
|
|
let keywords =
|
|
KeywordArguments::ast_from_field(vm, source_file, object, "keywords", "ClassDef")?;
|
|
let body: Vec<Option<ast::Stmt>> =
|
|
get_node_list_field(vm, source_file, object, "body", "ClassDef")?;
|
|
let decorator_list: Vec<Option<ast::Decorator>> =
|
|
get_node_list_field(vm, source_file, object, "decorator_list", "ClassDef")?;
|
|
let runtime_decorator_exprs = runtime_decorator_expr_list(&decorator_list);
|
|
let runtime_body = runtime_stmt_list_metadata(&body);
|
|
let runtime_decorator_list = runtime_expr_list_metadata(&runtime_decorator_exprs);
|
|
let body = lower_runtime_stmt_list(body);
|
|
let decorator_list = lower_runtime_decorator_list(decorator_list);
|
|
let type_params = type_params_from_field(vm, source_file, object, "type_params", "ClassDef")?;
|
|
Ok(ast::StmtClassDef {
|
|
node_index: Default::default(),
|
|
name,
|
|
arguments: merge_class_def_args(Some(bases), Some(keywords)),
|
|
body,
|
|
decorator_list: decorator_list.into(),
|
|
type_params,
|
|
range,
|
|
runtime_decorator_list,
|
|
runtime_body,
|
|
})
|
|
}
|
|
|
|
impl Node for ast::StmtClassDef {
|
|
fn ast_to_object(self, vm: &VirtualMachine, source_file: &SourceFile) -> PyObjectRef {
|
|
let Self {
|
|
node_index: _,
|
|
name,
|
|
arguments,
|
|
body,
|
|
decorator_list,
|
|
type_params,
|
|
range,
|
|
runtime_decorator_list,
|
|
runtime_body,
|
|
} = self;
|
|
let (bases, keywords) = split_class_def_args(arguments);
|
|
let range =
|
|
definition_range_from_name(source_file, name.range.start(), range.end(), "class");
|
|
let node = NodeAst
|
|
.into_ref_with_type(vm, pyast::NodeStmtClassDef::static_type().to_owned())
|
|
.unwrap();
|
|
let dict = node.as_object().dict().unwrap();
|
|
dict.set_item("name", name.ast_to_object(vm, source_file), vm)
|
|
.unwrap();
|
|
dict.set_item(
|
|
"bases",
|
|
bases.map_or_else(
|
|
|| vm.ctx.new_list(vec![]).into(),
|
|
|b| b.ast_to_object(vm, source_file),
|
|
),
|
|
vm,
|
|
)
|
|
.unwrap();
|
|
dict.set_item(
|
|
"keywords",
|
|
keywords.map_or_else(
|
|
|| vm.ctx.new_list(vec![]).into(),
|
|
|k| k.ast_to_object(vm, source_file),
|
|
),
|
|
vm,
|
|
)
|
|
.unwrap();
|
|
let body = runtime_body.map_or_else(
|
|
|| body.ast_to_object(vm, source_file),
|
|
|values| values.ast_to_object(vm, source_file),
|
|
);
|
|
dict.set_item("body", body, vm).unwrap();
|
|
dict.set_item(
|
|
"decorator_list",
|
|
runtime_decorator_list.map_or_else(
|
|
|| decorator_list.ast_to_object(vm, source_file),
|
|
|values| values.ast_to_object(vm, source_file),
|
|
),
|
|
vm,
|
|
)
|
|
.unwrap();
|
|
dict.set_item(
|
|
"type_params",
|
|
type_params.map_or_else(
|
|
|| vm.ctx.new_list(vec![]).into(),
|
|
|tp| tp.ast_to_object(vm, source_file),
|
|
),
|
|
vm,
|
|
)
|
|
.unwrap();
|
|
node_add_location(&dict, range, vm, source_file);
|
|
node.into()
|
|
}
|
|
fn ast_from_object(
|
|
vm: &VirtualMachine,
|
|
source_file: &SourceFile,
|
|
_object: PyObjectRef,
|
|
) -> PyResult<Self> {
|
|
let range = range_from_object(vm, source_file, &_object, "ClassDef")?;
|
|
stmt_class_def_from_object_with_range(vm, source_file, &_object, range)
|
|
}
|
|
}
|
|
// constructor
|
|
fn stmt_return_from_object_with_range(
|
|
vm: &VirtualMachine,
|
|
source_file: &SourceFile,
|
|
object: &PyObject,
|
|
range: TextRange,
|
|
) -> PyResult<ast::StmtReturn> {
|
|
Ok(ast::StmtReturn {
|
|
node_index: Default::default(),
|
|
value: get_node_field_opt(vm, object, "value")?
|
|
.map(|obj| Node::ast_from_object(vm, source_file, obj))
|
|
.transpose()?,
|
|
range,
|
|
})
|
|
}
|
|
|
|
impl Node for ast::StmtReturn {
|
|
fn ast_to_object(self, vm: &VirtualMachine, source_file: &SourceFile) -> PyObjectRef {
|
|
let Self {
|
|
node_index: _,
|
|
value,
|
|
range: _range,
|
|
} = self;
|
|
let node = NodeAst
|
|
.into_ref_with_type(vm, pyast::NodeStmtReturn::static_type().to_owned())
|
|
.unwrap();
|
|
let dict = node.as_object().dict().unwrap();
|
|
dict.set_item("value", value.ast_to_object(vm, source_file), vm)
|
|
.unwrap();
|
|
node_add_location(&dict, _range, vm, source_file);
|
|
node.into()
|
|
}
|
|
fn ast_from_object(
|
|
vm: &VirtualMachine,
|
|
source_file: &SourceFile,
|
|
_object: PyObjectRef,
|
|
) -> PyResult<Self> {
|
|
let range = range_from_object(vm, source_file, &_object, "Return")?;
|
|
stmt_return_from_object_with_range(vm, source_file, &_object, range)
|
|
}
|
|
}
|
|
// constructor
|
|
fn stmt_delete_from_object_with_range(
|
|
vm: &VirtualMachine,
|
|
source_file: &SourceFile,
|
|
object: &PyObject,
|
|
range: TextRange,
|
|
) -> PyResult<ast::StmtDelete> {
|
|
let targets: Vec<Option<ast::Expr>> =
|
|
get_node_list_field(vm, source_file, object, "targets", "Delete")?;
|
|
let (runtime_targets, targets) = runtime_expr_list_from_values(targets);
|
|
Ok(ast::StmtDelete {
|
|
node_index: Default::default(),
|
|
targets,
|
|
range,
|
|
runtime_targets,
|
|
})
|
|
}
|
|
|
|
impl Node for ast::StmtDelete {
|
|
fn ast_to_object(self, vm: &VirtualMachine, source_file: &SourceFile) -> PyObjectRef {
|
|
let Self {
|
|
node_index: _,
|
|
targets,
|
|
range: _range,
|
|
runtime_targets,
|
|
} = self;
|
|
let node = NodeAst
|
|
.into_ref_with_type(vm, pyast::NodeStmtDelete::static_type().to_owned())
|
|
.unwrap();
|
|
let dict = node.as_object().dict().unwrap();
|
|
let targets = runtime_targets.map_or_else(
|
|
|| targets.ast_to_object(vm, source_file),
|
|
|values| values.ast_to_object(vm, source_file),
|
|
);
|
|
dict.set_item("targets", targets, vm).unwrap();
|
|
node_add_location(&dict, _range, vm, source_file);
|
|
node.into()
|
|
}
|
|
fn ast_from_object(
|
|
vm: &VirtualMachine,
|
|
source_file: &SourceFile,
|
|
_object: PyObjectRef,
|
|
) -> PyResult<Self> {
|
|
let range = range_from_object(vm, source_file, &_object, "Delete")?;
|
|
stmt_delete_from_object_with_range(vm, source_file, &_object, range)
|
|
}
|
|
}
|
|
|
|
// constructor
|
|
fn stmt_assign_from_object_with_range(
|
|
vm: &VirtualMachine,
|
|
source_file: &SourceFile,
|
|
object: &PyObject,
|
|
range: TextRange,
|
|
) -> PyResult<ast::StmtAssign> {
|
|
let targets: Vec<Option<ast::Expr>> =
|
|
get_node_list_field(vm, source_file, object, "targets", "Assign")?;
|
|
let (runtime_targets, targets) = runtime_expr_list_from_values(targets);
|
|
let value = get_required_node_field(vm, source_file, object, "value", "Assign")?;
|
|
let (runtime_type_comment, runtime_type_comment_bytes) =
|
|
runtime_stmt_type_comment(vm, get_ast_string_field_opt(vm, object, "type_comment")?);
|
|
Ok(ast::StmtAssign {
|
|
node_index: Default::default(),
|
|
targets,
|
|
value,
|
|
range,
|
|
runtime_targets,
|
|
runtime_type_comment,
|
|
runtime_type_comment_bytes,
|
|
})
|
|
}
|
|
|
|
impl Node for ast::StmtAssign {
|
|
fn ast_to_object(self, vm: &VirtualMachine, source_file: &SourceFile) -> PyObjectRef {
|
|
let Self {
|
|
node_index: _,
|
|
targets,
|
|
value,
|
|
range,
|
|
runtime_targets,
|
|
runtime_type_comment,
|
|
runtime_type_comment_bytes,
|
|
} = self;
|
|
let node = NodeAst
|
|
.into_ref_with_type(vm, pyast::NodeStmtAssign::static_type().to_owned())
|
|
.unwrap();
|
|
let dict = node.as_object().dict().unwrap();
|
|
let targets = runtime_targets.map_or_else(
|
|
|| targets.ast_to_object(vm, source_file),
|
|
|values| values.ast_to_object(vm, source_file),
|
|
);
|
|
dict.set_item("targets", targets, vm).unwrap();
|
|
dict.set_item("value", value.ast_to_object(vm, source_file), vm)
|
|
.unwrap();
|
|
dict.set_item(
|
|
"type_comment",
|
|
runtime_stmt_type_comment_object(vm, runtime_type_comment, runtime_type_comment_bytes),
|
|
vm,
|
|
)
|
|
.unwrap();
|
|
node_add_location(&dict, range, vm, source_file);
|
|
node.into()
|
|
}
|
|
fn ast_from_object(
|
|
vm: &VirtualMachine,
|
|
source_file: &SourceFile,
|
|
object: PyObjectRef,
|
|
) -> PyResult<Self> {
|
|
let range = range_from_object(vm, source_file, &object, "Assign")?;
|
|
stmt_assign_from_object_with_range(vm, source_file, &object, range)
|
|
}
|
|
}
|
|
|
|
// constructor
|
|
fn stmt_type_alias_from_object_with_range(
|
|
vm: &VirtualMachine,
|
|
source_file: &SourceFile,
|
|
object: &PyObject,
|
|
range: TextRange,
|
|
) -> PyResult<ast::StmtTypeAlias> {
|
|
Ok(ast::StmtTypeAlias {
|
|
node_index: Default::default(),
|
|
name: get_required_node_field(vm, source_file, object, "name", "TypeAlias")?,
|
|
type_params: type_params_from_field(vm, source_file, object, "type_params", "TypeAlias")?,
|
|
value: get_required_node_field(vm, source_file, object, "value", "TypeAlias")?,
|
|
range,
|
|
})
|
|
}
|
|
|
|
impl Node for ast::StmtTypeAlias {
|
|
fn ast_to_object(self, vm: &VirtualMachine, source_file: &SourceFile) -> PyObjectRef {
|
|
let Self {
|
|
node_index: _,
|
|
name,
|
|
type_params,
|
|
value,
|
|
range: _range,
|
|
} = self;
|
|
let node = NodeAst
|
|
.into_ref_with_type(vm, pyast::NodeStmtTypeAlias::static_type().to_owned())
|
|
.unwrap();
|
|
let dict = node.as_object().dict().unwrap();
|
|
dict.set_item("name", name.ast_to_object(vm, source_file), vm)
|
|
.unwrap();
|
|
dict.set_item(
|
|
"type_params",
|
|
type_params.map_or_else(
|
|
|| vm.ctx.new_list(Vec::new()).into(),
|
|
|tp| tp.ast_to_object(vm, source_file),
|
|
),
|
|
vm,
|
|
)
|
|
.unwrap();
|
|
dict.set_item("value", value.ast_to_object(vm, source_file), vm)
|
|
.unwrap();
|
|
node_add_location(&dict, _range, vm, source_file);
|
|
node.into()
|
|
}
|
|
|
|
fn ast_from_object(
|
|
vm: &VirtualMachine,
|
|
source_file: &SourceFile,
|
|
_object: PyObjectRef,
|
|
) -> PyResult<Self> {
|
|
let range = range_from_object(vm, source_file, &_object, "TypeAlias")?;
|
|
stmt_type_alias_from_object_with_range(vm, source_file, &_object, range)
|
|
}
|
|
}
|
|
|
|
// constructor
|
|
fn stmt_aug_assign_from_object_with_range(
|
|
vm: &VirtualMachine,
|
|
source_file: &SourceFile,
|
|
object: &PyObject,
|
|
range: TextRange,
|
|
) -> PyResult<ast::StmtAugAssign> {
|
|
Ok(ast::StmtAugAssign {
|
|
node_index: Default::default(),
|
|
target: get_required_node_field(vm, source_file, object, "target", "AugAssign")?,
|
|
op: Node::ast_from_object(
|
|
vm,
|
|
source_file,
|
|
get_node_field_required(vm, object, "op", "AugAssign")?,
|
|
)?,
|
|
value: get_required_node_field(vm, source_file, object, "value", "AugAssign")?,
|
|
range,
|
|
})
|
|
}
|
|
|
|
impl Node for ast::StmtAugAssign {
|
|
fn ast_to_object(self, vm: &VirtualMachine, source_file: &SourceFile) -> PyObjectRef {
|
|
let Self {
|
|
node_index: _,
|
|
target,
|
|
op,
|
|
value,
|
|
range: _range,
|
|
} = self;
|
|
let node = NodeAst
|
|
.into_ref_with_type(vm, pyast::NodeStmtAugAssign::static_type().to_owned())
|
|
.unwrap();
|
|
let dict = node.as_object().dict().unwrap();
|
|
dict.set_item("target", target.ast_to_object(vm, source_file), vm)
|
|
.unwrap();
|
|
dict.set_item("op", op.ast_to_object(vm, source_file), vm)
|
|
.unwrap();
|
|
dict.set_item("value", value.ast_to_object(vm, source_file), vm)
|
|
.unwrap();
|
|
node_add_location(&dict, _range, vm, source_file);
|
|
node.into()
|
|
}
|
|
fn ast_from_object(
|
|
vm: &VirtualMachine,
|
|
source_file: &SourceFile,
|
|
_object: PyObjectRef,
|
|
) -> PyResult<Self> {
|
|
let range = range_from_object(vm, source_file, &_object, "AugAssign")?;
|
|
stmt_aug_assign_from_object_with_range(vm, source_file, &_object, range)
|
|
}
|
|
}
|
|
|
|
// constructor
|
|
fn stmt_ann_assign_from_object_with_range(
|
|
vm: &VirtualMachine,
|
|
source_file: &SourceFile,
|
|
object: &PyObject,
|
|
range: TextRange,
|
|
) -> PyResult<ast::StmtAnnAssign> {
|
|
let simple_obj = get_node_field(vm, object, "simple", "AnnAssign")?;
|
|
let simple = node_object_to_i32(vm, &simple_obj)?;
|
|
let runtime_simple = if simple != 0 && simple != 1 {
|
|
Some(simple)
|
|
} else {
|
|
None
|
|
};
|
|
Ok(ast::StmtAnnAssign {
|
|
node_index: Default::default(),
|
|
target: get_required_node_field(vm, source_file, object, "target", "AnnAssign")?,
|
|
annotation: get_required_node_field(vm, source_file, object, "annotation", "AnnAssign")?,
|
|
value: get_node_field_opt(vm, object, "value")?
|
|
.map(|obj| Node::ast_from_object(vm, source_file, obj))
|
|
.transpose()?,
|
|
simple: simple != 0,
|
|
range,
|
|
runtime_simple,
|
|
})
|
|
}
|
|
|
|
impl Node for ast::StmtAnnAssign {
|
|
fn ast_to_object(self, vm: &VirtualMachine, source_file: &SourceFile) -> PyObjectRef {
|
|
let Self {
|
|
node_index: _,
|
|
target,
|
|
annotation,
|
|
value,
|
|
simple,
|
|
range: _range,
|
|
runtime_simple,
|
|
} = self;
|
|
let node = NodeAst
|
|
.into_ref_with_type(vm, pyast::NodeStmtAnnAssign::static_type().to_owned())
|
|
.unwrap();
|
|
let dict = node.as_object().dict().unwrap();
|
|
dict.set_item("target", target.ast_to_object(vm, source_file), vm)
|
|
.unwrap();
|
|
dict.set_item("annotation", annotation.ast_to_object(vm, source_file), vm)
|
|
.unwrap();
|
|
dict.set_item("value", value.ast_to_object(vm, source_file), vm)
|
|
.unwrap();
|
|
let simple = runtime_simple.map_or_else(
|
|
|| simple.ast_to_object(vm, source_file),
|
|
|simple| vm.ctx.new_int(simple).into(),
|
|
);
|
|
dict.set_item("simple", simple, vm).unwrap();
|
|
node_add_location(&dict, _range, vm, source_file);
|
|
node.into()
|
|
}
|
|
fn ast_from_object(
|
|
vm: &VirtualMachine,
|
|
source_file: &SourceFile,
|
|
_object: PyObjectRef,
|
|
) -> PyResult<Self> {
|
|
let range = range_from_object(vm, source_file, &_object, "AnnAssign")?;
|
|
stmt_ann_assign_from_object_with_range(vm, source_file, &_object, range)
|
|
}
|
|
}
|
|
|
|
// constructor
|
|
fn stmt_for_from_object_with_range(
|
|
vm: &VirtualMachine,
|
|
source_file: &SourceFile,
|
|
object: &PyObject,
|
|
range: TextRange,
|
|
is_async: bool,
|
|
) -> PyResult<ast::StmtFor> {
|
|
let typ = if is_async { "AsyncFor" } else { "For" };
|
|
let target = get_required_node_field(vm, source_file, object, "target", typ)?;
|
|
let iter = get_required_node_field(vm, source_file, object, "iter", typ)?;
|
|
let body: Vec<Option<ast::Stmt>> = get_node_list_field(vm, source_file, object, "body", typ)?;
|
|
let orelse: Vec<Option<ast::Stmt>> =
|
|
get_node_list_field(vm, source_file, object, "orelse", typ)?;
|
|
let runtime_body = runtime_stmt_list_metadata(&body);
|
|
let runtime_orelse = runtime_stmt_list_metadata(&orelse);
|
|
let body = lower_runtime_stmt_list(body);
|
|
let orelse = lower_runtime_stmt_list(orelse);
|
|
let (runtime_type_comment, runtime_type_comment_bytes) =
|
|
runtime_stmt_type_comment(vm, get_ast_string_field_opt(vm, object, "type_comment")?);
|
|
Ok(ast::StmtFor {
|
|
node_index: Default::default(),
|
|
target,
|
|
iter,
|
|
body,
|
|
orelse,
|
|
range,
|
|
is_async,
|
|
runtime_type_comment,
|
|
runtime_type_comment_bytes,
|
|
runtime_body,
|
|
runtime_orelse,
|
|
})
|
|
}
|
|
|
|
impl Node for ast::StmtFor {
|
|
fn ast_to_object(self, vm: &VirtualMachine, source_file: &SourceFile) -> PyObjectRef {
|
|
let Self {
|
|
node_index: _,
|
|
is_async,
|
|
target,
|
|
iter,
|
|
body,
|
|
orelse,
|
|
range: _range,
|
|
runtime_type_comment,
|
|
runtime_type_comment_bytes,
|
|
runtime_body,
|
|
runtime_orelse,
|
|
} = self;
|
|
|
|
let cls = if !is_async {
|
|
pyast::NodeStmtFor::static_type().to_owned()
|
|
} else {
|
|
pyast::NodeStmtAsyncFor::static_type().to_owned()
|
|
};
|
|
|
|
let node = NodeAst.into_ref_with_type(vm, cls).unwrap();
|
|
let dict = node.as_object().dict().unwrap();
|
|
dict.set_item("target", target.ast_to_object(vm, source_file), vm)
|
|
.unwrap();
|
|
dict.set_item("iter", iter.ast_to_object(vm, source_file), vm)
|
|
.unwrap();
|
|
let body = runtime_body.map_or_else(
|
|
|| body.ast_to_object(vm, source_file),
|
|
|values| values.ast_to_object(vm, source_file),
|
|
);
|
|
dict.set_item("body", body, vm).unwrap();
|
|
let orelse = runtime_orelse.map_or_else(
|
|
|| orelse.ast_to_object(vm, source_file),
|
|
|values| values.ast_to_object(vm, source_file),
|
|
);
|
|
dict.set_item("orelse", orelse, vm).unwrap();
|
|
dict.set_item(
|
|
"type_comment",
|
|
runtime_stmt_type_comment_object(vm, runtime_type_comment, runtime_type_comment_bytes),
|
|
vm,
|
|
)
|
|
.unwrap();
|
|
node_add_location(&dict, _range, vm, source_file);
|
|
node.into()
|
|
}
|
|
|
|
fn ast_from_object(
|
|
vm: &VirtualMachine,
|
|
source_file: &SourceFile,
|
|
_object: PyObjectRef,
|
|
) -> PyResult<Self> {
|
|
debug_assert!(
|
|
is_node_instance(vm, &_object, pyast::NodeStmtFor::static_type())?
|
|
|| is_node_instance(vm, &_object, pyast::NodeStmtAsyncFor::static_type())?
|
|
);
|
|
let is_async = is_node_instance(vm, &_object, pyast::NodeStmtAsyncFor::static_type())?;
|
|
let typ = if is_async { "AsyncFor" } else { "For" };
|
|
let range = range_from_object(vm, source_file, &_object, typ)?;
|
|
stmt_for_from_object_with_range(vm, source_file, &_object, range, is_async)
|
|
}
|
|
}
|
|
|
|
// constructor
|
|
fn stmt_while_from_object_with_range(
|
|
vm: &VirtualMachine,
|
|
source_file: &SourceFile,
|
|
object: &PyObject,
|
|
range: TextRange,
|
|
) -> PyResult<ast::StmtWhile> {
|
|
let body: Vec<Option<ast::Stmt>> =
|
|
get_node_list_field(vm, source_file, object, "body", "While")?;
|
|
let orelse: Vec<Option<ast::Stmt>> =
|
|
get_node_list_field(vm, source_file, object, "orelse", "While")?;
|
|
let runtime_body = runtime_stmt_list_metadata(&body);
|
|
let runtime_orelse = runtime_stmt_list_metadata(&orelse);
|
|
Ok(ast::StmtWhile {
|
|
node_index: Default::default(),
|
|
test: get_required_node_field(vm, source_file, object, "test", "While")?,
|
|
body: lower_runtime_stmt_list(body),
|
|
orelse: lower_runtime_stmt_list(orelse),
|
|
range,
|
|
runtime_body,
|
|
runtime_orelse,
|
|
})
|
|
}
|
|
|
|
impl Node for ast::StmtWhile {
|
|
fn ast_to_object(self, vm: &VirtualMachine, source_file: &SourceFile) -> PyObjectRef {
|
|
let Self {
|
|
node_index: _,
|
|
test,
|
|
body,
|
|
orelse,
|
|
range: _range,
|
|
runtime_body,
|
|
runtime_orelse,
|
|
} = self;
|
|
let node = NodeAst
|
|
.into_ref_with_type(vm, pyast::NodeStmtWhile::static_type().to_owned())
|
|
.unwrap();
|
|
let dict = node.as_object().dict().unwrap();
|
|
dict.set_item("test", test.ast_to_object(vm, source_file), vm)
|
|
.unwrap();
|
|
let body = runtime_body.map_or_else(
|
|
|| body.ast_to_object(vm, source_file),
|
|
|values| values.ast_to_object(vm, source_file),
|
|
);
|
|
dict.set_item("body", body, vm).unwrap();
|
|
let orelse = runtime_orelse.map_or_else(
|
|
|| orelse.ast_to_object(vm, source_file),
|
|
|values| values.ast_to_object(vm, source_file),
|
|
);
|
|
dict.set_item("orelse", orelse, vm).unwrap();
|
|
node_add_location(&dict, _range, vm, source_file);
|
|
node.into()
|
|
}
|
|
|
|
fn ast_from_object(
|
|
vm: &VirtualMachine,
|
|
source_file: &SourceFile,
|
|
_object: PyObjectRef,
|
|
) -> PyResult<Self> {
|
|
let range = range_from_object(vm, source_file, &_object, "While")?;
|
|
stmt_while_from_object_with_range(vm, source_file, &_object, range)
|
|
}
|
|
}
|
|
// constructor
|
|
impl Node for ast::StmtIf {
|
|
fn ast_to_object(self, vm: &VirtualMachine, source_file: &SourceFile) -> PyObjectRef {
|
|
let Self {
|
|
node_index,
|
|
test,
|
|
body,
|
|
range,
|
|
elif_else_clauses,
|
|
runtime_body,
|
|
} = self;
|
|
elif_else_clause::ast_to_object(
|
|
ast::ElifElseClause {
|
|
node_index,
|
|
range,
|
|
test: Some(*test),
|
|
body,
|
|
runtime_body,
|
|
runtime_orelse: None,
|
|
},
|
|
elif_else_clauses.into_iter(),
|
|
vm,
|
|
source_file,
|
|
)
|
|
}
|
|
fn ast_from_object(
|
|
vm: &VirtualMachine,
|
|
source_file: &SourceFile,
|
|
object: PyObjectRef,
|
|
) -> PyResult<Self> {
|
|
let range = range_from_object(vm, source_file, &object, "If")?;
|
|
elif_else_clause::ast_from_object_with_range(vm, source_file, &object, range)
|
|
}
|
|
}
|
|
// constructor
|
|
fn stmt_with_from_object_with_range(
|
|
vm: &VirtualMachine,
|
|
source_file: &SourceFile,
|
|
object: &PyObject,
|
|
range: TextRange,
|
|
is_async: bool,
|
|
) -> PyResult<ast::StmtWith> {
|
|
let typ = if is_async { "AsyncWith" } else { "With" };
|
|
let items = get_node_list_field(vm, source_file, object, "items", typ)?;
|
|
let body: Vec<Option<ast::Stmt>> = get_node_list_field(vm, source_file, object, "body", typ)?;
|
|
let (runtime_body, body) = runtime_stmt_list_from_values(body);
|
|
let (runtime_type_comment, runtime_type_comment_bytes) =
|
|
runtime_stmt_type_comment(vm, get_ast_string_field_opt(vm, object, "type_comment")?);
|
|
Ok(ast::StmtWith {
|
|
node_index: Default::default(),
|
|
items,
|
|
body,
|
|
range,
|
|
is_async,
|
|
runtime_type_comment,
|
|
runtime_type_comment_bytes,
|
|
runtime_body,
|
|
})
|
|
}
|
|
|
|
impl Node for ast::StmtWith {
|
|
fn ast_to_object(self, vm: &VirtualMachine, source_file: &SourceFile) -> PyObjectRef {
|
|
let Self {
|
|
node_index: _,
|
|
is_async,
|
|
items,
|
|
body,
|
|
range: _range,
|
|
runtime_type_comment,
|
|
runtime_type_comment_bytes,
|
|
runtime_body,
|
|
} = self;
|
|
|
|
let cls = if !is_async {
|
|
pyast::NodeStmtWith::static_type().to_owned()
|
|
} else {
|
|
pyast::NodeStmtAsyncWith::static_type().to_owned()
|
|
};
|
|
|
|
let node = NodeAst.into_ref_with_type(vm, cls).unwrap();
|
|
let dict = node.as_object().dict().unwrap();
|
|
dict.set_item("items", items.ast_to_object(vm, source_file), vm)
|
|
.unwrap();
|
|
let body = runtime_body.map_or_else(
|
|
|| body.ast_to_object(vm, source_file),
|
|
|values| values.ast_to_object(vm, source_file),
|
|
);
|
|
dict.set_item("body", body, vm).unwrap();
|
|
dict.set_item(
|
|
"type_comment",
|
|
runtime_stmt_type_comment_object(vm, runtime_type_comment, runtime_type_comment_bytes),
|
|
vm,
|
|
)
|
|
.unwrap();
|
|
node_add_location(&dict, _range, vm, source_file);
|
|
node.into()
|
|
}
|
|
fn ast_from_object(
|
|
vm: &VirtualMachine,
|
|
source_file: &SourceFile,
|
|
_object: PyObjectRef,
|
|
) -> PyResult<Self> {
|
|
debug_assert!(
|
|
is_node_instance(vm, &_object, pyast::NodeStmtWith::static_type())?
|
|
|| is_node_instance(vm, &_object, pyast::NodeStmtAsyncWith::static_type())?
|
|
);
|
|
let is_async = is_node_instance(vm, &_object, pyast::NodeStmtAsyncWith::static_type())?;
|
|
let typ = if is_async { "AsyncWith" } else { "With" };
|
|
let range = range_from_object(vm, source_file, &_object, typ)?;
|
|
stmt_with_from_object_with_range(vm, source_file, &_object, range, is_async)
|
|
}
|
|
}
|
|
// constructor
|
|
fn stmt_match_from_object_with_range(
|
|
vm: &VirtualMachine,
|
|
source_file: &SourceFile,
|
|
object: &PyObject,
|
|
range: TextRange,
|
|
) -> PyResult<ast::StmtMatch> {
|
|
Ok(ast::StmtMatch {
|
|
node_index: Default::default(),
|
|
subject: get_required_node_field(vm, source_file, object, "subject", "Match")?,
|
|
cases: get_node_list_field(vm, source_file, object, "cases", "Match")?,
|
|
range,
|
|
})
|
|
}
|
|
|
|
impl Node for ast::StmtMatch {
|
|
fn ast_to_object(self, vm: &VirtualMachine, source_file: &SourceFile) -> PyObjectRef {
|
|
let Self {
|
|
node_index: _,
|
|
subject,
|
|
cases,
|
|
range: _range,
|
|
} = self;
|
|
let node = NodeAst
|
|
.into_ref_with_type(vm, pyast::NodeStmtMatch::static_type().to_owned())
|
|
.unwrap();
|
|
let dict = node.as_object().dict().unwrap();
|
|
dict.set_item("subject", subject.ast_to_object(vm, source_file), vm)
|
|
.unwrap();
|
|
dict.set_item("cases", cases.ast_to_object(vm, source_file), vm)
|
|
.unwrap();
|
|
node_add_location(&dict, _range, vm, source_file);
|
|
node.into()
|
|
}
|
|
fn ast_from_object(
|
|
vm: &VirtualMachine,
|
|
source_file: &SourceFile,
|
|
_object: PyObjectRef,
|
|
) -> PyResult<Self> {
|
|
let range = range_from_object(vm, source_file, &_object, "Match")?;
|
|
stmt_match_from_object_with_range(vm, source_file, &_object, range)
|
|
}
|
|
}
|
|
// constructor
|
|
fn stmt_raise_from_object_with_range(
|
|
vm: &VirtualMachine,
|
|
source_file: &SourceFile,
|
|
object: &PyObject,
|
|
range: TextRange,
|
|
) -> PyResult<ast::StmtRaise> {
|
|
Ok(ast::StmtRaise {
|
|
node_index: Default::default(),
|
|
exc: get_node_field_opt(vm, object, "exc")?
|
|
.map(|obj| Node::ast_from_object(vm, source_file, obj))
|
|
.transpose()?,
|
|
cause: get_node_field_opt(vm, object, "cause")?
|
|
.map(|obj| Node::ast_from_object(vm, source_file, obj))
|
|
.transpose()?,
|
|
range,
|
|
})
|
|
}
|
|
|
|
impl Node for ast::StmtRaise {
|
|
fn ast_to_object(self, vm: &VirtualMachine, source_file: &SourceFile) -> PyObjectRef {
|
|
let Self {
|
|
node_index: _,
|
|
exc,
|
|
cause,
|
|
range: _range,
|
|
} = self;
|
|
let node = NodeAst
|
|
.into_ref_with_type(vm, pyast::NodeStmtRaise::static_type().to_owned())
|
|
.unwrap();
|
|
let dict = node.as_object().dict().unwrap();
|
|
dict.set_item("exc", exc.ast_to_object(vm, source_file), vm)
|
|
.unwrap();
|
|
dict.set_item("cause", cause.ast_to_object(vm, source_file), vm)
|
|
.unwrap();
|
|
node_add_location(&dict, _range, vm, source_file);
|
|
node.into()
|
|
}
|
|
fn ast_from_object(
|
|
vm: &VirtualMachine,
|
|
source_file: &SourceFile,
|
|
_object: PyObjectRef,
|
|
) -> PyResult<Self> {
|
|
let range = range_from_object(vm, source_file, &_object, "Raise")?;
|
|
stmt_raise_from_object_with_range(vm, source_file, &_object, range)
|
|
}
|
|
}
|
|
// constructor
|
|
fn stmt_try_from_object_with_range(
|
|
vm: &VirtualMachine,
|
|
source_file: &SourceFile,
|
|
object: &PyObject,
|
|
range: TextRange,
|
|
is_star: bool,
|
|
) -> PyResult<ast::StmtTry> {
|
|
let typ = if is_star { "TryStar" } else { "Try" };
|
|
let body: Vec<Option<ast::Stmt>> = get_node_list_field(vm, source_file, object, "body", typ)?;
|
|
let orelse: Vec<Option<ast::Stmt>> =
|
|
get_node_list_field(vm, source_file, object, "orelse", typ)?;
|
|
let finalbody: Vec<Option<ast::Stmt>> =
|
|
get_node_list_field(vm, source_file, object, "finalbody", typ)?;
|
|
let (runtime_handler_values, handlers) =
|
|
except_handler_list_from_field(vm, source_file, object, typ, is_star, range)?;
|
|
let runtime_body = runtime_stmt_list_metadata(&body);
|
|
let runtime_orelse = runtime_stmt_list_metadata(&orelse);
|
|
let runtime_finalbody = runtime_stmt_list_metadata(&finalbody);
|
|
let runtime_handlers = runtime_except_handler_list_metadata(&runtime_handler_values);
|
|
Ok(ast::StmtTry {
|
|
node_index: Default::default(),
|
|
body: lower_runtime_stmt_list(body),
|
|
handlers,
|
|
orelse: lower_runtime_stmt_list(orelse),
|
|
finalbody: lower_runtime_stmt_list(finalbody),
|
|
range,
|
|
is_star,
|
|
runtime_body,
|
|
runtime_handlers,
|
|
runtime_orelse,
|
|
runtime_finalbody,
|
|
})
|
|
}
|
|
|
|
fn except_handler_list_from_field(
|
|
vm: &VirtualMachine,
|
|
source_file: &SourceFile,
|
|
object: &PyObject,
|
|
typ: &str,
|
|
is_try_star: bool,
|
|
range: TextRange,
|
|
) -> PyResult<(Vec<Option<ast::ExceptHandler>>, Vec<ast::ExceptHandler>)> {
|
|
let value = get_node_list_field_object(vm, object, "handlers", typ)?;
|
|
let list = value.downcast_ref::<PyList>().unwrap();
|
|
let len = list.borrow_vec().len();
|
|
let mut result = Vec::with_capacity(len);
|
|
let mut runtime_values = Vec::with_capacity(len);
|
|
let recursion_context = format!(" while traversing '{typ}' node");
|
|
for i in 0..len {
|
|
let item = {
|
|
let items = list.borrow_vec();
|
|
if items.len() != len {
|
|
return Err(vm.new_runtime_error(format!(
|
|
r#"{typ} field "handlers" changed size during iteration"#
|
|
)));
|
|
}
|
|
items[i].clone()
|
|
};
|
|
let runtime_handler = if vm.is_none(&item) {
|
|
None
|
|
} else {
|
|
Some(vm.with_recursion(&recursion_context, || {
|
|
if is_try_star {
|
|
except_handler_from_object_unvalidated_range(vm, source_file, &item)
|
|
} else {
|
|
Node::ast_from_object(vm, source_file, item)
|
|
}
|
|
})?)
|
|
};
|
|
let handler = runtime_handler.clone().unwrap_or_else(|| {
|
|
ast::ExceptHandler::ExceptHandler(ast::ExceptHandlerExceptHandler {
|
|
node_index: Default::default(),
|
|
range,
|
|
type_: None,
|
|
name: None,
|
|
body: Vec::new().into(),
|
|
runtime_body: None,
|
|
})
|
|
});
|
|
runtime_values.push(runtime_handler);
|
|
result.push(handler);
|
|
if list.borrow_vec().len() != len {
|
|
return Err(vm.new_runtime_error(format!(
|
|
r#"{typ} field "handlers" changed size during iteration"#
|
|
)));
|
|
}
|
|
}
|
|
Ok((runtime_values, result))
|
|
}
|
|
|
|
impl Node for ast::StmtTry {
|
|
fn ast_to_object(self, vm: &VirtualMachine, source_file: &SourceFile) -> PyObjectRef {
|
|
let Self {
|
|
node_index: _,
|
|
body,
|
|
handlers,
|
|
orelse,
|
|
finalbody,
|
|
range: _range,
|
|
is_star,
|
|
runtime_body,
|
|
runtime_handlers,
|
|
runtime_orelse,
|
|
runtime_finalbody,
|
|
} = self;
|
|
|
|
let cls = if is_star {
|
|
pyast::NodeStmtTryStar::static_type()
|
|
} else {
|
|
pyast::NodeStmtTry::static_type()
|
|
}
|
|
.to_owned();
|
|
|
|
let node = NodeAst.into_ref_with_type(vm, cls).unwrap();
|
|
let dict = node.as_object().dict().unwrap();
|
|
let body = runtime_body.map_or_else(
|
|
|| body.ast_to_object(vm, source_file),
|
|
|values| values.ast_to_object(vm, source_file),
|
|
);
|
|
dict.set_item("body", body, vm).unwrap();
|
|
let handlers = runtime_handlers.map_or_else(
|
|
|| handlers.ast_to_object(vm, source_file),
|
|
|values| values.ast_to_object(vm, source_file),
|
|
);
|
|
dict.set_item("handlers", handlers, vm).unwrap();
|
|
let orelse = runtime_orelse.map_or_else(
|
|
|| orelse.ast_to_object(vm, source_file),
|
|
|values| values.ast_to_object(vm, source_file),
|
|
);
|
|
dict.set_item("orelse", orelse, vm).unwrap();
|
|
let finalbody = runtime_finalbody.map_or_else(
|
|
|| finalbody.ast_to_object(vm, source_file),
|
|
|values| values.ast_to_object(vm, source_file),
|
|
);
|
|
dict.set_item("finalbody", finalbody, vm).unwrap();
|
|
node_add_location(&dict, _range, vm, source_file);
|
|
node.into()
|
|
}
|
|
fn ast_from_object(
|
|
vm: &VirtualMachine,
|
|
source_file: &SourceFile,
|
|
_object: PyObjectRef,
|
|
) -> PyResult<Self> {
|
|
let is_star = is_node_instance(vm, &_object, pyast::NodeStmtTryStar::static_type())?;
|
|
debug_assert!(
|
|
is_node_instance(vm, &_object, pyast::NodeStmtTry::static_type())?
|
|
|| is_node_instance(vm, &_object, pyast::NodeStmtTryStar::static_type())?
|
|
);
|
|
let typ = if is_star { "TryStar" } else { "Try" };
|
|
let range = range_from_object(vm, source_file, &_object, typ)?;
|
|
stmt_try_from_object_with_range(vm, source_file, &_object, range, is_star)
|
|
}
|
|
}
|
|
|
|
// constructor
|
|
fn stmt_assert_from_object_with_range(
|
|
vm: &VirtualMachine,
|
|
source_file: &SourceFile,
|
|
object: &PyObject,
|
|
range: TextRange,
|
|
) -> PyResult<ast::StmtAssert> {
|
|
Ok(ast::StmtAssert {
|
|
node_index: Default::default(),
|
|
test: get_required_node_field(vm, source_file, object, "test", "Assert")?,
|
|
msg: get_node_field_opt(vm, object, "msg")?
|
|
.map(|obj| Node::ast_from_object(vm, source_file, obj))
|
|
.transpose()?,
|
|
range,
|
|
})
|
|
}
|
|
|
|
impl Node for ast::StmtAssert {
|
|
fn ast_to_object(self, vm: &VirtualMachine, source_file: &SourceFile) -> PyObjectRef {
|
|
let Self {
|
|
node_index: _,
|
|
test,
|
|
msg,
|
|
range: _range,
|
|
} = self;
|
|
let node = NodeAst
|
|
.into_ref_with_type(vm, pyast::NodeStmtAssert::static_type().to_owned())
|
|
.unwrap();
|
|
let dict = node.as_object().dict().unwrap();
|
|
dict.set_item("test", test.ast_to_object(vm, source_file), vm)
|
|
.unwrap();
|
|
dict.set_item("msg", msg.ast_to_object(vm, source_file), vm)
|
|
.unwrap();
|
|
node_add_location(&dict, _range, vm, source_file);
|
|
node.into()
|
|
}
|
|
fn ast_from_object(
|
|
vm: &VirtualMachine,
|
|
source_file: &SourceFile,
|
|
_object: PyObjectRef,
|
|
) -> PyResult<Self> {
|
|
let range = range_from_object(vm, source_file, &_object, "Assert")?;
|
|
stmt_assert_from_object_with_range(vm, source_file, &_object, range)
|
|
}
|
|
}
|
|
// constructor
|
|
fn stmt_import_from_object_with_range(
|
|
vm: &VirtualMachine,
|
|
source_file: &SourceFile,
|
|
object: &PyObject,
|
|
range: TextRange,
|
|
) -> PyResult<ast::StmtImport> {
|
|
Ok(ast::StmtImport {
|
|
node_index: Default::default(),
|
|
names: get_node_list_field(vm, source_file, object, "names", "Import")?,
|
|
range,
|
|
is_lazy: false,
|
|
})
|
|
}
|
|
|
|
impl Node for ast::StmtImport {
|
|
fn ast_to_object(self, vm: &VirtualMachine, source_file: &SourceFile) -> PyObjectRef {
|
|
let Self {
|
|
node_index: _,
|
|
names,
|
|
range: _range,
|
|
is_lazy: _,
|
|
} = self;
|
|
let node = NodeAst
|
|
.into_ref_with_type(vm, pyast::NodeStmtImport::static_type().to_owned())
|
|
.unwrap();
|
|
let dict = node.as_object().dict().unwrap();
|
|
dict.set_item("names", names.ast_to_object(vm, source_file), vm)
|
|
.unwrap();
|
|
node_add_location(&dict, _range, vm, source_file);
|
|
node.into()
|
|
}
|
|
|
|
fn ast_from_object(
|
|
vm: &VirtualMachine,
|
|
source_file: &SourceFile,
|
|
_object: PyObjectRef,
|
|
) -> PyResult<Self> {
|
|
let range = range_from_object(vm, source_file, &_object, "Import")?;
|
|
stmt_import_from_object_with_range(vm, source_file, &_object, range)
|
|
}
|
|
}
|
|
// constructor
|
|
fn stmt_import_from_from_object_with_range(
|
|
vm: &VirtualMachine,
|
|
source_file: &SourceFile,
|
|
object: &PyObject,
|
|
range: TextRange,
|
|
) -> PyResult<ast::StmtImportFrom> {
|
|
let (level, raw_level) = import_from_level_from_field(vm, object)?;
|
|
let runtime_level = raw_level.filter(|level| *level < 0);
|
|
Ok(ast::StmtImportFrom {
|
|
node_index: Default::default(),
|
|
module: get_node_field_opt(vm, object, "module")?
|
|
.map(|obj| Node::ast_from_object(vm, source_file, obj))
|
|
.transpose()?,
|
|
names: get_node_list_field(vm, source_file, object, "names", "ImportFrom")?,
|
|
level,
|
|
range,
|
|
is_lazy: false,
|
|
runtime_level,
|
|
})
|
|
}
|
|
|
|
fn import_from_level_from_field(
|
|
vm: &VirtualMachine,
|
|
object: &PyObject,
|
|
) -> PyResult<(u32, Option<i32>)> {
|
|
let Some(value) = get_node_field_opt(vm, object, "level")? else {
|
|
return Ok((0, None));
|
|
};
|
|
let level = vm.with_recursion(" while traversing 'ImportFrom' node", || {
|
|
node_object_to_i32(vm, &value)
|
|
})?;
|
|
if level < 0 {
|
|
return Ok((0, Some(level)));
|
|
}
|
|
Ok((level as u32, None))
|
|
}
|
|
|
|
impl Node for ast::StmtImportFrom {
|
|
fn ast_to_object(self, vm: &VirtualMachine, source_file: &SourceFile) -> PyObjectRef {
|
|
let Self {
|
|
node_index: _,
|
|
module,
|
|
names,
|
|
level,
|
|
range,
|
|
is_lazy: _,
|
|
runtime_level,
|
|
} = self;
|
|
let node = NodeAst
|
|
.into_ref_with_type(vm, pyast::NodeStmtImportFrom::static_type().to_owned())
|
|
.unwrap();
|
|
let dict = node.as_object().dict().unwrap();
|
|
dict.set_item("module", module.ast_to_object(vm, source_file), vm)
|
|
.unwrap();
|
|
dict.set_item("names", names.ast_to_object(vm, source_file), vm)
|
|
.unwrap();
|
|
let level = runtime_level.map_or_else(
|
|
|| vm.ctx.new_int(level).to_pyobject(vm),
|
|
|level| vm.ctx.new_int(level).to_pyobject(vm),
|
|
);
|
|
dict.set_item("level", level, vm).unwrap();
|
|
node_add_location(&dict, range, vm, source_file);
|
|
node.into()
|
|
}
|
|
|
|
fn ast_from_object(
|
|
vm: &VirtualMachine,
|
|
source_file: &SourceFile,
|
|
_object: PyObjectRef,
|
|
) -> PyResult<Self> {
|
|
let range = range_from_object(vm, source_file, &_object, "ImportFrom")?;
|
|
stmt_import_from_from_object_with_range(vm, source_file, &_object, range)
|
|
}
|
|
}
|
|
// constructor
|
|
fn stmt_global_from_object_with_range(
|
|
vm: &VirtualMachine,
|
|
source_file: &SourceFile,
|
|
object: &PyObject,
|
|
range: TextRange,
|
|
) -> PyResult<ast::StmtGlobal> {
|
|
Ok(ast::StmtGlobal {
|
|
node_index: Default::default(),
|
|
names: get_node_list_field(vm, source_file, object, "names", "Global")?,
|
|
range,
|
|
})
|
|
}
|
|
|
|
impl Node for ast::StmtGlobal {
|
|
fn ast_to_object(self, vm: &VirtualMachine, source_file: &SourceFile) -> PyObjectRef {
|
|
let Self {
|
|
node_index: _,
|
|
names,
|
|
range: _range,
|
|
} = self;
|
|
let node = NodeAst
|
|
.into_ref_with_type(vm, pyast::NodeStmtGlobal::static_type().to_owned())
|
|
.unwrap();
|
|
let dict = node.as_object().dict().unwrap();
|
|
dict.set_item("names", names.ast_to_object(vm, source_file), vm)
|
|
.unwrap();
|
|
node_add_location(&dict, _range, vm, source_file);
|
|
node.into()
|
|
}
|
|
fn ast_from_object(
|
|
vm: &VirtualMachine,
|
|
source_file: &SourceFile,
|
|
_object: PyObjectRef,
|
|
) -> PyResult<Self> {
|
|
let range = range_from_object(vm, source_file, &_object, "Global")?;
|
|
stmt_global_from_object_with_range(vm, source_file, &_object, range)
|
|
}
|
|
}
|
|
// constructor
|
|
fn stmt_nonlocal_from_object_with_range(
|
|
vm: &VirtualMachine,
|
|
source_file: &SourceFile,
|
|
object: &PyObject,
|
|
range: TextRange,
|
|
) -> PyResult<ast::StmtNonlocal> {
|
|
Ok(ast::StmtNonlocal {
|
|
node_index: Default::default(),
|
|
names: get_node_list_field(vm, source_file, object, "names", "Nonlocal")?,
|
|
range,
|
|
})
|
|
}
|
|
|
|
impl Node for ast::StmtNonlocal {
|
|
fn ast_to_object(self, vm: &VirtualMachine, source_file: &SourceFile) -> PyObjectRef {
|
|
let Self {
|
|
node_index: _,
|
|
names,
|
|
range: _range,
|
|
} = self;
|
|
let node = NodeAst
|
|
.into_ref_with_type(vm, pyast::NodeStmtNonlocal::static_type().to_owned())
|
|
.unwrap();
|
|
let dict = node.as_object().dict().unwrap();
|
|
dict.set_item("names", names.ast_to_object(vm, source_file), vm)
|
|
.unwrap();
|
|
node_add_location(&dict, _range, vm, source_file);
|
|
node.into()
|
|
}
|
|
fn ast_from_object(
|
|
vm: &VirtualMachine,
|
|
source_file: &SourceFile,
|
|
_object: PyObjectRef,
|
|
) -> PyResult<Self> {
|
|
let range = range_from_object(vm, source_file, &_object, "Nonlocal")?;
|
|
stmt_nonlocal_from_object_with_range(vm, source_file, &_object, range)
|
|
}
|
|
}
|
|
// constructor
|
|
fn stmt_expr_from_object_with_range(
|
|
vm: &VirtualMachine,
|
|
source_file: &SourceFile,
|
|
object: &PyObject,
|
|
range: TextRange,
|
|
) -> PyResult<ast::StmtExpr> {
|
|
Ok(ast::StmtExpr {
|
|
node_index: Default::default(),
|
|
value: get_required_node_field(vm, source_file, object, "value", "Expr")?,
|
|
range,
|
|
})
|
|
}
|
|
|
|
impl Node for ast::StmtExpr {
|
|
fn ast_to_object(self, vm: &VirtualMachine, source_file: &SourceFile) -> PyObjectRef {
|
|
let Self {
|
|
node_index: _,
|
|
value,
|
|
range: _range,
|
|
} = self;
|
|
let node = NodeAst
|
|
.into_ref_with_type(vm, pyast::NodeStmtExpr::static_type().to_owned())
|
|
.unwrap();
|
|
let dict = node.as_object().dict().unwrap();
|
|
dict.set_item("value", value.ast_to_object(vm, source_file), vm)
|
|
.unwrap();
|
|
node_add_location(&dict, _range, vm, source_file);
|
|
node.into()
|
|
}
|
|
fn ast_from_object(
|
|
vm: &VirtualMachine,
|
|
source_file: &SourceFile,
|
|
_object: PyObjectRef,
|
|
) -> PyResult<Self> {
|
|
let range = range_from_object(vm, source_file, &_object, "Expr")?;
|
|
stmt_expr_from_object_with_range(vm, source_file, &_object, range)
|
|
}
|
|
}
|
|
// constructor
|
|
fn stmt_pass_from_object_with_range(range: TextRange) -> ast::StmtPass {
|
|
ast::StmtPass {
|
|
node_index: Default::default(),
|
|
range,
|
|
}
|
|
}
|
|
|
|
impl Node for ast::StmtPass {
|
|
fn ast_to_object(self, vm: &VirtualMachine, source_file: &SourceFile) -> PyObjectRef {
|
|
let Self {
|
|
node_index: _,
|
|
range: _range,
|
|
} = self;
|
|
let node = NodeAst
|
|
.into_ref_with_type(vm, pyast::NodeStmtPass::static_type().to_owned())
|
|
.unwrap();
|
|
let dict = node.as_object().dict().unwrap();
|
|
let location = super::text_range_to_source_range(source_file, _range);
|
|
let start_row = location.start.row.get();
|
|
let start_col = location.start.column.get();
|
|
let mut end_row = location.end.row.get();
|
|
|
|
// Align with CPython: when docstring optimization replaces a lone
|
|
// docstring with `pass`, the end position is on the same line even if
|
|
// it extends past the physical line length.
|
|
let end_col = if end_row != start_row && _range.len() == TextSize::from(4) {
|
|
end_row = start_row;
|
|
start_col + 4
|
|
} else {
|
|
location.end.column.get()
|
|
};
|
|
|
|
dict.set_item("lineno", vm.ctx.new_int(start_row).into(), vm)
|
|
.unwrap();
|
|
dict.set_item("col_offset", vm.ctx.new_int(start_col).into(), vm)
|
|
.unwrap();
|
|
dict.set_item("end_lineno", vm.ctx.new_int(end_row).into(), vm)
|
|
.unwrap();
|
|
dict.set_item("end_col_offset", vm.ctx.new_int(end_col).into(), vm)
|
|
.unwrap();
|
|
node.into()
|
|
}
|
|
fn ast_from_object(
|
|
vm: &VirtualMachine,
|
|
source_file: &SourceFile,
|
|
_object: PyObjectRef,
|
|
) -> PyResult<Self> {
|
|
let range = range_from_object(vm, source_file, &_object, "Pass")?;
|
|
Ok(stmt_pass_from_object_with_range(range))
|
|
}
|
|
}
|
|
// constructor
|
|
fn stmt_break_from_object_with_range(range: TextRange) -> ast::StmtBreak {
|
|
ast::StmtBreak {
|
|
node_index: Default::default(),
|
|
range,
|
|
}
|
|
}
|
|
|
|
impl Node for ast::StmtBreak {
|
|
fn ast_to_object(self, vm: &VirtualMachine, source_file: &SourceFile) -> PyObjectRef {
|
|
let Self {
|
|
node_index: _,
|
|
range: _range,
|
|
} = self;
|
|
let node = NodeAst
|
|
.into_ref_with_type(vm, pyast::NodeStmtBreak::static_type().to_owned())
|
|
.unwrap();
|
|
let dict = node.as_object().dict().unwrap();
|
|
node_add_location(&dict, _range, vm, source_file);
|
|
node.into()
|
|
}
|
|
|
|
fn ast_from_object(
|
|
vm: &VirtualMachine,
|
|
source_file: &SourceFile,
|
|
_object: PyObjectRef,
|
|
) -> PyResult<Self> {
|
|
let range = range_from_object(vm, source_file, &_object, "Break")?;
|
|
Ok(stmt_break_from_object_with_range(range))
|
|
}
|
|
}
|
|
|
|
// constructor
|
|
fn stmt_continue_from_object_with_range(range: TextRange) -> ast::StmtContinue {
|
|
ast::StmtContinue {
|
|
node_index: Default::default(),
|
|
range,
|
|
}
|
|
}
|
|
|
|
impl Node for ast::StmtContinue {
|
|
fn ast_to_object(self, vm: &VirtualMachine, source_file: &SourceFile) -> PyObjectRef {
|
|
let Self {
|
|
node_index: _,
|
|
range: _range,
|
|
} = self;
|
|
let node = NodeAst
|
|
.into_ref_with_type(vm, pyast::NodeStmtContinue::static_type().to_owned())
|
|
.unwrap();
|
|
let dict = node.as_object().dict().unwrap();
|
|
node_add_location(&dict, _range, vm, source_file);
|
|
node.into()
|
|
}
|
|
fn ast_from_object(
|
|
vm: &VirtualMachine,
|
|
source_file: &SourceFile,
|
|
_object: PyObjectRef,
|
|
) -> PyResult<Self> {
|
|
let range = range_from_object(vm, source_file, &_object, "Continue")?;
|
|
Ok(stmt_continue_from_object_with_range(range))
|
|
}
|
|
}
|