Skip to content

Commit 2f1fb16

Browse files
committed
Add mode to ast::parse
1 parent 7333fd1 commit 2f1fb16

File tree

8 files changed

+101
-39
lines changed

8 files changed

+101
-39
lines changed

compiler/src/compile.rs

+1-30
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
//! https://github.com/micropython/micropython/blob/master/py/compile.c
77
88
use crate::error::{CompileError, CompileErrorType};
9+
pub use crate::mode::Mode;
910
use crate::output_stream::{CodeObjectStream, OutputStream};
1011
use crate::peephole::PeepholeOptimizer;
1112
use crate::symboltable::{
@@ -105,36 +106,6 @@ pub fn compile_program_single(
105106
})
106107
}
107108

108-
#[derive(Clone, Copy)]
109-
pub enum Mode {
110-
Exec,
111-
Eval,
112-
Single,
113-
}
114-
115-
impl std::str::FromStr for Mode {
116-
type Err = ModeParseError;
117-
fn from_str(s: &str) -> Result<Self, ModeParseError> {
118-
match s {
119-
"exec" => Ok(Mode::Exec),
120-
"eval" => Ok(Mode::Eval),
121-
"single" => Ok(Mode::Single),
122-
_ => Err(ModeParseError { _priv: () }),
123-
}
124-
}
125-
}
126-
127-
#[derive(Debug)]
128-
pub struct ModeParseError {
129-
_priv: (),
130-
}
131-
132-
impl std::fmt::Display for ModeParseError {
133-
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
134-
write!(f, r#"mode should be "exec", "eval", or "single""#)
135-
}
136-
}
137-
138109
impl<O> Default for Compiler<O>
139110
where
140111
O: OutputStream,

compiler/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ extern crate log;
88

99
pub mod compile;
1010
pub mod error;
11+
pub mod mode;
1112
pub(crate) mod output_stream;
1213
pub mod peephole;
1314
pub mod symboltable;

compiler/src/mode.rs

+40
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
use rustpython_parser::parser;
2+
3+
#[derive(Clone, Copy)]
4+
pub enum Mode {
5+
Exec,
6+
Eval,
7+
Single,
8+
}
9+
10+
impl std::str::FromStr for Mode {
11+
type Err = ModeParseError;
12+
fn from_str(s: &str) -> Result<Self, ModeParseError> {
13+
match s {
14+
"exec" => Ok(Mode::Exec),
15+
"eval" => Ok(Mode::Eval),
16+
"single" => Ok(Mode::Single),
17+
_ => Err(ModeParseError { _priv: () }),
18+
}
19+
}
20+
}
21+
22+
impl Mode {
23+
pub fn to_parser_mode(self) -> parser::Mode {
24+
match self {
25+
Self::Exec | Self::Single => parser::Mode::Program,
26+
Self::Eval => parser::Mode::Statement,
27+
}
28+
}
29+
}
30+
31+
#[derive(Debug)]
32+
pub struct ModeParseError {
33+
_priv: (),
34+
}
35+
36+
impl std::fmt::Display for ModeParseError {
37+
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
38+
write!(f, r#"mode should be "exec", "eval", or "single""#)
39+
}
40+
}

parser/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ mod fstring;
1111
mod function;
1212
pub mod lexer;
1313
pub mod location;
14+
pub mod mode;
1415
pub mod parser;
1516
lalrpop_mod!(
1617
#[allow(clippy::all)]

parser/src/mode.rs

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
#[derive(Clone, Copy)]
2+
pub enum Mode {
3+
Program,
4+
Statement,
5+
}
6+
7+
impl std::str::FromStr for Mode {
8+
type Err = ModeParseError;
9+
fn from_str(s: &str) -> Result<Self, ModeParseError> {
10+
match s {
11+
"exec" | "single" => Ok(Mode::Program),
12+
"eval" => Ok(Mode::Statement),
13+
_ => Err(ModeParseError { _priv: () }),
14+
}
15+
}
16+
}
17+
18+
#[derive(Debug)]
19+
pub struct ModeParseError {
20+
_priv: (),
21+
}
22+
23+
impl std::fmt::Display for ModeParseError {
24+
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
25+
write!(f, r#"mode should be "exec", "eval", or "single""#)
26+
}
27+
}

parser/src/parser.rs

+15
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use std::iter;
33
use crate::ast;
44
use crate::error::ParseError;
55
use crate::lexer;
6+
pub use crate::mode::Mode;
67
use crate::python;
78
use crate::token;
89

@@ -73,6 +74,20 @@ pub fn parse_expression(source: &str) -> Result<ast::Expression, ParseError> {
7374
do_lalr_parsing!(source, Expression, StartExpression)
7475
}
7576

77+
// Parse a given source code
78+
pub fn parse(source: &str, mode: Mode) -> Result<ast::Top, ParseError> {
79+
Ok(match mode {
80+
Mode::Program => {
81+
let ast = parse_program(source)?;
82+
ast::Top::Program(ast)
83+
}
84+
Mode::Statement => {
85+
let statement = parse_statement(source)?;
86+
ast::Top::Statement(statement)
87+
}
88+
})
89+
}
90+
7691
#[cfg(test)]
7792
mod tests {
7893
use super::ast;

vm/src/builtins.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,10 @@ use crate::pyobject::{
2929
TryFromObject, TypeProtocol,
3030
};
3131
use crate::scope::Scope;
32-
use crate::vm::VirtualMachine;
3332
use crate::stdlib::ast;
3433
#[cfg(not(target_arch = "wasm32"))]
3534
use crate::stdlib::io::io_open;
35+
use crate::vm::VirtualMachine;
3636

3737
fn builtin_abs(x: PyObjectRef, vm: &VirtualMachine) -> PyResult {
3838
let method = vm.get_method_or_type_error(x.clone(), "__abs__", || {
@@ -143,11 +143,11 @@ fn builtin_compile(args: CompileArgs, vm: &VirtualMachine) -> PyResult {
143143
.map_or(Ok(0), |v| i32::try_from_object(vm, v.into_object()))?;
144144

145145
if (flags & ast::PY_COMPILE_FLAG_AST_ONLY).is_zero() {
146-
vm.compile(&source, mode, args.filename.value.to_string())
146+
vm.compile(&source, mode, args.filename.as_str().to_string())
147147
.map(|o| o.into_object())
148148
.map_err(|err| vm.new_syntax_error(&err))
149149
} else {
150-
ast::source_to_ast(&vm, &source)
150+
ast::parse(&vm, &source, mode.to_parser_mode())
151151
}
152152
}
153153

vm/src/stdlib/ast.rs

+13-6
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use std::ops::Deref;
77

88
use num_complex::Complex64;
99

10-
use rustpython_parser::{ast, parser};
10+
use rustpython_parser::{ast, mode::Mode, parser};
1111

1212
use crate::obj::objlist::PyListRef;
1313
use crate::obj::objtype::PyClassRef;
@@ -50,11 +50,12 @@ macro_rules! node {
5050
}
5151
}
5252

53-
pub(crate) fn source_to_ast(vm: &VirtualMachine, source: &str) -> PyResult {
54-
let internal_ast =
55-
parser::parse_program(source).map_err(|err| vm.new_value_error(format!("{}", err)))?;
56-
let py_body = statements_to_ast(vm, &internal_ast.statements)?;
57-
Ok(node!(vm, Module, { body => py_body }).into_object())
53+
fn top_to_ast(vm: &VirtualMachine, top: &ast::Top) -> PyResult<PyListRef> {
54+
match top {
55+
ast::Top::Program(program) => statements_to_ast(vm, &program.statements),
56+
ast::Top::Statement(statements) => statements_to_ast(vm, statements),
57+
ast::Top::Expression(_) => unimplemented!("top_to_ast unimplemented ast::Top::Expression"),
58+
}
5859
}
5960

6061
// Create a node class instance
@@ -634,6 +635,12 @@ fn string_to_ast(vm: &VirtualMachine, string: &ast::StringGroup) -> PyResult<Ast
634635
Ok(string)
635636
}
636637

638+
pub(crate) fn parse(vm: &VirtualMachine, source: &str, mode: Mode) -> PyResult {
639+
let ast = parser::parse(source, mode).map_err(|err| vm.new_value_error(format!("{}", err)))?;
640+
let py_body = top_to_ast(vm, &ast)?;
641+
Ok(node!(vm, Module, { body => py_body }).into_object())
642+
}
643+
637644
pub fn make_module(vm: &VirtualMachine) -> PyObjectRef {
638645
let ctx = &vm.ctx;
639646

0 commit comments

Comments
 (0)