vm compiles · RustPython/RustPython@bf51082 · GitHub
Skip to content

Commit bf51082

Browse files
committed
vm compiles
1 parent 3253e4c commit bf51082

12 files changed

Lines changed: 88 additions & 35 deletions

File tree

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions

crates/vm/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ psm = { workspace = true }
7878
optional = { workspace = true }
7979
result-like = { workspace = true }
8080
timsort = { workspace = true }
81+
thin-vec = { workspace = true }
8182

8283
## unicode stuff
8384
icu_casemap = { workspace = true }

crates/vm/src/stdlib/_ast.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
//! This module makes use of the parser logic, and translates all ast nodes
55
//! into python ast.AST objects.
66
7+
use thin_vec::ThinVec;
8+
79
pub(crate) use python::_ast::module_def;
810

911
mod pyast;
@@ -559,7 +561,7 @@ fn strip_docstrings(top: &mut ast::Mod) {
559561
}
560562

561563
#[cfg(feature = "parser")]
562-
fn strip_docstring_in_body(body: &mut Vec<ast::Stmt>) {
564+
fn strip_docstring_in_body(body: &mut ThinVec<ast::Stmt>) {
563565
if let Some(range) = take_docstring(body)
564566
&& body.is_empty()
565567
{
@@ -581,7 +583,7 @@ fn strip_docstring_in_body(body: &mut Vec<ast::Stmt>) {
581583
}
582584

583585
#[cfg(feature = "parser")]
584-
fn take_docstring(body: &mut Vec<ast::Stmt>) -> Option<TextRange> {
586+
fn take_docstring(body: &mut ThinVec<ast::Stmt>) -> Option<TextRange> {
585587
let ast::Stmt::Expr(expr_stmt) = body.first()? else {
586588
return None;
587589
};
@@ -791,7 +793,7 @@ pub(crate) fn compile(
791793
Mod::Interactive(ModInteractive { range, body }) => ast::Mod::Module(ast::ModModule {
792794
node_index: Default::default(),
793795
range,
794-
body,
796+
body: body.into(),
795797
}),
796798
Mod::Expression(e) => ast::Mod::Expression(e),
797799
Mod::FunctionType(_) => todo!(),

crates/vm/src/stdlib/_ast/argument.rs

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,50 +1,52 @@
1+
use thin_vec::ThinVec;
2+
13
use super::*;
24
use rustpython_compiler_core::SourceFile;
35

46
pub(super) struct PositionalArguments {
57
pub range: TextRange,
6-
pub args: Box<[ast::Expr]>,
8+
pub args: ThinVec<ast::Expr>,
79
}
810

911
impl Node for PositionalArguments {
1012
fn ast_to_object(self, vm: &VirtualMachine, source_file: &SourceFile) -> PyObjectRef {
1113
let Self { args, range: _ } = self;
12-
BoxedSlice(args).ast_to_object(vm, source_file)
14+
args.ast_to_object(vm, source_file)
1315
}
1416

1517
fn ast_from_object(
1618
vm: &VirtualMachine,
1719
source_file: &SourceFile,
1820
object: PyObjectRef,
1921
) -> PyResult<Self> {
20-
let args: BoxedSlice<_> = Node::ast_from_object(vm, source_file, object)?;
22+
let args: ThinVec<_> = Node::ast_from_object(vm, source_file, object)?;
2123
Ok(Self {
22-
args: args.0,
24+
args,
2325
range: TextRange::default(), // TODO
2426
})
2527
}
2628
}
2729

2830
pub(super) struct KeywordArguments {
2931
pub range: TextRange,
30-
pub keywords: Box<[ast::Keyword]>,
32+
pub keywords: ThinVec<ast::Keyword>,
3133
}
3234

3335
impl Node for KeywordArguments {
3436
fn ast_to_object(self, vm: &VirtualMachine, source_file: &SourceFile) -> PyObjectRef {
3537
let Self { keywords, range: _ } = self;
3638
// TODO: use range
37-
BoxedSlice(keywords).ast_to_object(vm, source_file)
39+
keywords.ast_to_object(vm, source_file)
3840
}
3941

4042
fn ast_from_object(
4143
vm: &VirtualMachine,
4244
source_file: &SourceFile,
4345
object: PyObjectRef,
4446
) -> PyResult<Self> {
45-
let keywords: BoxedSlice<_> = Node::ast_from_object(vm, source_file, object)?;
47+
let keywords: ThinVec<_> = Node::ast_from_object(vm, source_file, object)?;
4648
Ok(Self {
47-
keywords: keywords.0,
49+
keywords,
4850
range: TextRange::default(), // TODO
4951
})
5052
}
@@ -59,7 +61,7 @@ pub(super) fn merge_function_call_arguments(
5961
ast::Arguments {
6062
node_index: Default::default(),
6163
range,
62-
args: pos_args.args,
64+
args: pos_args.args.into(),
6365
keywords: key_args.keywords,
6466
}
6567
}
@@ -82,7 +84,7 @@ pub(super) fn split_function_call_arguments(
8284
// debug_assert!(range.contains_range(positional_arguments_range));
8385
let positional_arguments = PositionalArguments {
8486
range: positional_arguments_range,
85-
args,
87+
args: args.into(),
8688
};
8789

8890
let keyword_arguments_range = keywords
@@ -121,7 +123,7 @@ pub(super) fn split_class_def_args(
121123
// debug_assert!(range.contains_range(positional_arguments_range));
122124
let positional_arguments = PositionalArguments {
123125
range: positional_arguments_range,
124-
args,
126+
args: args.into(),
125127
};
126128

127129
let keyword_arguments_range = keywords
@@ -149,18 +151,18 @@ pub(super) fn merge_class_def_args(
149151
let args = if let Some(positional_arguments) = positional_arguments {
150152
positional_arguments.args
151153
} else {
152-
vec![].into_boxed_slice()
154+
ThinVec::new()
153155
};
154156
let keywords = if let Some(keyword_arguments) = keyword_arguments {
155157
keyword_arguments.keywords
156158
} else {
157-
vec![].into_boxed_slice()
159+
ThinVec::new()
158160
};
159161

160162
Some(Box::new(ast::Arguments {
161163
node_index: Default::default(),
162164
range: Default::default(), // TODO
163-
args,
165+
args: args.into(),
164166
keywords,
165167
}))
166168
}

crates/vm/src/stdlib/_ast/constant.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -332,7 +332,7 @@ fn constant_to_ruff_expr(value: Constant) -> ast::Expr {
332332
node_index: Default::default(),
333333
range,
334334
args: args.into(),
335-
keywords: Box::default(),
335+
keywords: Default::default(),
336336
},
337337
})
338338
}

crates/vm/src/stdlib/_ast/elif_else_clause.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
use thin_vec::ThinVec;
2+
13
use super::*;
24
use rustpython_compiler_core::SourceFile;
35

@@ -55,7 +57,7 @@ pub(super) fn ast_from_object(
5557
) -> PyResult<ast::StmtIf> {
5658
let test = Node::ast_from_object(vm, source_file, get_node_field(vm, &object, "test", "If")?)?;
5759
let body = Node::ast_from_object(vm, source_file, get_node_field(vm, &object, "body", "If")?)?;
58-
let orelse: Vec<ast::Stmt> = Node::ast_from_object(
60+
let orelse: ThinVec<ast::Stmt> = Node::ast_from_object(
5961
vm,
6062
source_file,
6163
get_node_field(vm, &object, "orelse", "If")?,

crates/vm/src/stdlib/_ast/module.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
use thin_vec::ThinVec;
2+
13
use super::*;
24
use crate::stdlib::_ast::type_ignore::TypeIgnore;
35
use rustpython_compiler_core::SourceFile;
@@ -113,7 +115,7 @@ impl Node for ast::ModModule {
113115

114116
pub(super) struct ModInteractive {
115117
pub(crate) range: TextRange,
116-
pub(crate) body: Vec<ast::Stmt>,
118+
pub(crate) body: ThinVec<ast::Stmt>,
117119
}
118120

119121
// constructor

crates/vm/src/stdlib/_ast/node.rs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
use thin_vec::ThinVec;
2+
13
use crate::{PyObjectRef, PyResult, VirtualMachine};
24
use rustpython_compiler_core::SourceFile;
35

@@ -42,6 +44,34 @@ impl<T: Node> Node for Vec<T> {
4244
}
4345
}
4446

47+
impl<T: Node> Node for ThinVec<T> {
48+
fn ast_to_object(self, vm: &VirtualMachine, source_file: &SourceFile) -> PyObjectRef {
49+
vm.ctx
50+
.new_list(
51+
self.into_iter()
52+
.map(|node| node.ast_to_object(vm, source_file))
53+
.collect(),
54+
)
55+
.into()
56+
}
57+
58+
fn ast_from_object(
59+
vm: &VirtualMachine,
60+
source_file: &SourceFile,
61+
object: PyObjectRef,
62+
) -> PyResult<Self> {
63+
// Recursion guard for each element: prevents stack overflow when a
64+
// sequence element transitively references the sequence itself
65+
// (e.g. `l = ast.List(...); l.elts = [l]`). See issue #4862.
66+
vm.extract_elements_with(&object, |obj| {
67+
vm.with_recursion("while traversing AST node", || {
68+
Node::ast_from_object(vm, source_file, obj)
69+
})
70+
})
71+
.map(Into::into)
72+
}
73+
}
74+
4575
impl<T: Node> Node for Box<T> {
4676
fn ast_to_object(self, vm: &VirtualMachine, source_file: &SourceFile) -> PyObjectRef {
4777
(*self).ast_to_object(vm, source_file)

crates/vm/src/stdlib/_ast/parameter.rs

Lines changed: 13 additions & 10 deletions

0 commit comments

Comments
 (0)