Skip to content

Commit 6f59609

Browse files
Merge pull request RustPython#1533 from RustPython/coolreader18/cleanupstuff
Clean up the REPL and CodeFlags
2 parents b212682 + 64674d2 commit 6f59609

File tree

12 files changed

+241
-197
lines changed

12 files changed

+241
-197
lines changed

bytecode/src/bytecode.rs

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -37,27 +37,28 @@ pub struct CodeObject {
3737
/// Jump targets.
3838
pub label_map: HashMap<Label, usize>,
3939
pub locations: Vec<Location>,
40+
pub flags: CodeFlags,
4041
pub arg_names: Vec<String>, // Names of positional arguments
4142
pub varargs: Varargs, // *args or *
4243
pub kwonlyarg_names: Vec<String>,
4344
pub varkeywords: Varargs, // **kwargs or **
4445
pub source_path: String,
4546
pub first_line_number: usize,
4647
pub obj_name: String, // Name of the object that created this code object
47-
pub is_generator: bool,
4848
}
4949

5050
bitflags! {
5151
#[derive(Serialize, Deserialize)]
52-
pub struct FunctionOpArg: u8 {
52+
pub struct CodeFlags: u8 {
5353
const HAS_DEFAULTS = 0x01;
5454
const HAS_KW_ONLY_DEFAULTS = 0x02;
5555
const HAS_ANNOTATIONS = 0x04;
5656
const NEW_LOCALS = 0x08;
57+
const IS_GENERATOR = 0x10;
5758
}
5859
}
5960

60-
impl Default for FunctionOpArg {
61+
impl Default for CodeFlags {
6162
fn default() -> Self {
6263
Self::NEW_LOCALS
6364
}
@@ -176,9 +177,7 @@ pub enum Instruction {
176177
JumpIfFalseOrPop {
177178
target: Label,
178179
},
179-
MakeFunction {
180-
flags: FunctionOpArg,
181-
},
180+
MakeFunction,
182181
CallFunction {
183182
typ: CallType,
184183
},
@@ -354,7 +353,9 @@ pub enum BlockType {
354353
*/
355354

356355
impl CodeObject {
356+
#[allow(clippy::too_many_arguments)]
357357
pub fn new(
358+
flags: CodeFlags,
358359
arg_names: Vec<String>,
359360
varargs: Varargs,
360361
kwonlyarg_names: Vec<String>,
@@ -367,14 +368,14 @@ impl CodeObject {
367368
instructions: Vec::new(),
368369
label_map: HashMap::new(),
369370
locations: Vec::new(),
371+
flags,
370372
arg_names,
371373
varargs,
372374
kwonlyarg_names,
373375
varkeywords,
374376
source_path,
375377
first_line_number,
376378
obj_name,
377-
is_generator: false,
378379
}
379380
}
380381

@@ -513,7 +514,7 @@ impl Instruction {
513514
JumpIfFalse { target } => w!(JumpIfFalse, label_map[target]),
514515
JumpIfTrueOrPop { target } => w!(JumpIfTrueOrPop, label_map[target]),
515516
JumpIfFalseOrPop { target } => w!(JumpIfFalseOrPop, label_map[target]),
516-
MakeFunction { flags } => w!(MakeFunction, format!("{:?}", flags)),
517+
MakeFunction => w!(MakeFunction),
517518
CallFunction { typ } => w!(CallFunction, format!("{:?}", typ)),
518519
ForIter { target } => w!(ForIter, label_map[target]),
519520
ReturnValue => w!(ReturnValue),

compiler/src/compile.rs

Lines changed: 24 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,7 @@ impl<O: OutputStream> Compiler<O> {
137137
fn push_new_code_object(&mut self, obj_name: String) {
138138
let line_number = self.get_source_line_number();
139139
self.push_output(CodeObject::new(
140+
Default::default(),
140141
Vec::new(),
141142
Varargs::None,
142143
Vec::new(),
@@ -595,11 +596,7 @@ impl<O: OutputStream> Compiler<O> {
595596
Ok(())
596597
}
597598

598-
fn enter_function(
599-
&mut self,
600-
name: &str,
601-
args: &ast::Parameters,
602-
) -> Result<bytecode::FunctionOpArg, CompileError> {
599+
fn enter_function(&mut self, name: &str, args: &ast::Parameters) -> Result<(), CompileError> {
603600
let have_defaults = !args.defaults.is_empty();
604601
if have_defaults {
605602
// Construct a tuple:
@@ -633,8 +630,17 @@ impl<O: OutputStream> Compiler<O> {
633630
});
634631
}
635632

633+
let mut flags = bytecode::CodeFlags::default();
634+
if have_defaults {
635+
flags |= bytecode::CodeFlags::HAS_DEFAULTS;
636+
}
637+
if num_kw_only_defaults > 0 {
638+
flags |= bytecode::CodeFlags::HAS_KW_ONLY_DEFAULTS;
639+
}
640+
636641
let line_number = self.get_source_line_number();
637642
self.push_output(CodeObject::new(
643+
flags,
638644
args.args.iter().map(|a| a.arg.clone()).collect(),
639645
compile_varargs(&args.vararg),
640646
args.kwonlyargs.iter().map(|a| a.arg.clone()).collect(),
@@ -645,15 +651,7 @@ impl<O: OutputStream> Compiler<O> {
645651
));
646652
self.enter_scope();
647653

648-
let mut flags = bytecode::FunctionOpArg::default();
649-
if have_defaults {
650-
flags |= bytecode::FunctionOpArg::HAS_DEFAULTS;
651-
}
652-
if num_kw_only_defaults > 0 {
653-
flags |= bytecode::FunctionOpArg::HAS_KW_ONLY_DEFAULTS;
654-
}
655-
656-
Ok(flags)
654+
Ok(())
657655
}
658656

659657
fn prepare_decorators(
@@ -813,7 +811,7 @@ impl<O: OutputStream> Compiler<O> {
813811

814812
self.prepare_decorators(decorator_list)?;
815813

816-
let mut flags = self.enter_function(name, args)?;
814+
self.enter_function(name, args)?;
817815

818816
let (body, doc_str) = get_doc(body);
819817

@@ -832,7 +830,7 @@ impl<O: OutputStream> Compiler<O> {
832830
}
833831
}
834832

835-
let code = self.pop_code_object();
833+
let mut code = self.pop_code_object();
836834
self.leave_scope();
837835

838836
// Prepare type annotations:
@@ -864,7 +862,7 @@ impl<O: OutputStream> Compiler<O> {
864862
}
865863

866864
if num_annotations > 0 {
867-
flags |= bytecode::FunctionOpArg::HAS_ANNOTATIONS;
865+
code.flags |= bytecode::CodeFlags::HAS_ANNOTATIONS;
868866
self.emit(Instruction::BuildMap {
869867
size: num_annotations,
870868
unpack: false,
@@ -884,7 +882,7 @@ impl<O: OutputStream> Compiler<O> {
884882
});
885883

886884
// Turn code object into function object:
887-
self.emit(Instruction::MakeFunction { flags });
885+
self.emit(Instruction::MakeFunction);
888886
self.store_docstring(doc_str);
889887
self.apply_decorators(decorator_list);
890888

@@ -915,6 +913,7 @@ impl<O: OutputStream> Compiler<O> {
915913
self.emit(Instruction::LoadBuildClass);
916914
let line_number = self.get_source_line_number();
917915
self.push_output(CodeObject::new(
916+
Default::default(),
918917
vec![],
919918
Varargs::None,
920919
vec![],
@@ -950,7 +949,8 @@ impl<O: OutputStream> Compiler<O> {
950949
});
951950
self.emit(Instruction::ReturnValue);
952951

953-
let code = self.pop_code_object();
952+
let mut code = self.pop_code_object();
953+
code.flags &= !bytecode::CodeFlags::NEW_LOCALS;
954954
self.leave_scope();
955955

956956
self.emit(Instruction::LoadConst {
@@ -965,9 +965,7 @@ impl<O: OutputStream> Compiler<O> {
965965
});
966966

967967
// Turn code object into function object:
968-
self.emit(Instruction::MakeFunction {
969-
flags: bytecode::FunctionOpArg::default() & !bytecode::FunctionOpArg::NEW_LOCALS,
970-
});
968+
self.emit(Instruction::MakeFunction);
971969

972970
self.emit(Instruction::LoadConst {
973971
value: bytecode::Constant::String {
@@ -1615,7 +1613,7 @@ impl<O: OutputStream> Compiler<O> {
16151613
Lambda { args, body } => {
16161614
let name = "<lambda>".to_string();
16171615
// no need to worry about the self.loop_depth because there are no loops in lambda expressions
1618-
let flags = self.enter_function(&name, args)?;
1616+
self.enter_function(&name, args)?;
16191617
self.compile_expression(body)?;
16201618
self.emit(Instruction::ReturnValue);
16211619
let code = self.pop_code_object();
@@ -1629,7 +1627,7 @@ impl<O: OutputStream> Compiler<O> {
16291627
value: bytecode::Constant::String { value: name },
16301628
});
16311629
// Turn code object into function object:
1632-
self.emit(Instruction::MakeFunction { flags });
1630+
self.emit(Instruction::MakeFunction);
16331631
}
16341632
Comprehension { kind, generators } => {
16351633
self.compile_comprehension(kind, generators)?;
@@ -1810,6 +1808,7 @@ impl<O: OutputStream> Compiler<O> {
18101808
let line_number = self.get_source_line_number();
18111809
// Create magnificent function <listcomp>:
18121810
self.push_output(CodeObject::new(
1811+
Default::default(),
18131812
vec![".0".to_string()],
18141813
Varargs::None,
18151814
vec![],
@@ -1945,9 +1944,7 @@ impl<O: OutputStream> Compiler<O> {
19451944
});
19461945

19471946
// Turn code object into function object:
1948-
self.emit(Instruction::MakeFunction {
1949-
flags: bytecode::FunctionOpArg::default(),
1950-
});
1947+
self.emit(Instruction::MakeFunction);
19511948

19521949
// Evaluate iterated item:
19531950
self.compile_expression(&generators[0].iter)?;

compiler/src/output_stream.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use rustpython_bytecode::bytecode::{CodeObject, Instruction, Label, Location};
1+
use rustpython_bytecode::bytecode::{CodeFlags, CodeObject, Instruction, Label, Location};
22

33
pub trait OutputStream: From<CodeObject> + Into<CodeObject> {
44
/// Output an instruction
@@ -34,6 +34,6 @@ impl OutputStream for CodeObjectStream {
3434
self.code.label_map.insert(label, position);
3535
}
3636
fn mark_generator(&mut self) {
37-
self.code.is_generator = true;
37+
self.code.flags |= CodeFlags::IS_GENERATOR;
3838
}
3939
}

src/shell.rs

Lines changed: 3 additions & 109 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
mod readline;
12
#[cfg(not(target_os = "wasi"))]
23
mod rustyline_helper;
34

@@ -10,11 +11,8 @@ use rustpython_vm::{
1011
scope::Scope,
1112
VirtualMachine,
1213
};
13-
#[cfg(not(target_os = "wasi"))]
14-
use rustyline_helper::ShellHelper;
1514

16-
use std::io;
17-
use std::path::Path;
15+
use readline::{Readline, ReadlineResult};
1816

1917
enum ShellExecResult {
2018
Ok,
@@ -45,110 +43,6 @@ fn shell_exec(vm: &VirtualMachine, source: &str, scope: Scope) -> ShellExecResul
4543
}
4644
}
4745

48-
enum ReadlineResult {
49-
Line(String),
50-
EOF,
51-
Interrupt,
52-
IO(std::io::Error),
53-
EncodingError,
54-
Other(Box<dyn std::error::Error>),
55-
}
56-
57-
#[allow(unused)]
58-
struct BasicReadline;
59-
60-
#[allow(unused)]
61-
impl BasicReadline {
62-
fn new(_vm: &VirtualMachine, _scope: Scope) -> Self {
63-
BasicReadline
64-
}
65-
66-
fn load_history(&mut self, _path: &Path) -> io::Result<()> {
67-
Ok(())
68-
}
69-
70-
fn save_history(&mut self, _path: &Path) -> io::Result<()> {
71-
Ok(())
72-
}
73-
74-
fn add_history_entry(&mut self, _entry: &str) {}
75-
76-
fn readline(&mut self, prompt: &str) -> ReadlineResult {
77-
use std::io::prelude::*;
78-
print!("{}", prompt);
79-
if let Err(e) = io::stdout().flush() {
80-
return ReadlineResult::IO(e);
81-
}
82-
83-
match io::stdin().lock().lines().next() {
84-
Some(Ok(line)) => ReadlineResult::Line(line),
85-
None => ReadlineResult::EOF,
86-
Some(Err(e)) => match e.kind() {
87-
io::ErrorKind::Interrupted => ReadlineResult::Interrupt,
88-
io::ErrorKind::InvalidData => ReadlineResult::EncodingError,
89-
_ => ReadlineResult::IO(e),
90-
},
91-
}
92-
}
93-
}
94-
95-
#[cfg(target_os = "wasi")]
96-
type Readline = BasicReadline;
97-
98-
#[cfg(not(target_os = "wasi"))]
99-
struct RustylineReadline<'vm> {
100-
repl: rustyline::Editor<ShellHelper<'vm>>,
101-
}
102-
#[cfg(not(target_os = "wasi"))]
103-
impl<'vm> RustylineReadline<'vm> {
104-
fn new(vm: &'vm VirtualMachine, scope: Scope) -> Self {
105-
use rustyline::{CompletionType, Config, Editor};
106-
let mut repl = Editor::with_config(
107-
Config::builder()
108-
.completion_type(CompletionType::List)
109-
.tab_stop(4)
110-
.build(),
111-
);
112-
repl.set_helper(Some(ShellHelper::new(vm, scope)));
113-
RustylineReadline { repl }
114-
}
115-
116-
fn load_history(&mut self, path: &Path) -> rustyline::Result<()> {
117-
self.repl.load_history(path)
118-
}
119-
120-
fn save_history(&mut self, path: &Path) -> rustyline::Result<()> {
121-
if !path.exists() {
122-
if let Some(parent) = path.parent() {
123-
std::fs::create_dir_all(parent)?;
124-
}
125-
}
126-
self.repl.save_history(path)
127-
}
128-
129-
fn add_history_entry(&mut self, entry: &str) {
130-
self.repl.add_history_entry(entry);
131-
}
132-
133-
fn readline(&mut self, prompt: &str) -> ReadlineResult {
134-
use rustyline::error::ReadlineError;
135-
match self.repl.readline(prompt) {
136-
Ok(line) => ReadlineResult::Line(line),
137-
Err(ReadlineError::Interrupted) => ReadlineResult::Interrupt,
138-
Err(ReadlineError::Eof) => ReadlineResult::EOF,
139-
Err(ReadlineError::Io(e)) => ReadlineResult::IO(e),
140-
#[cfg(unix)]
141-
Err(ReadlineError::Utf8Error) => ReadlineResult::EncodingError,
142-
#[cfg(windows)]
143-
Err(ReadlineError::Decode(_)) => ReadlineResult::EncodingError,
144-
Err(e) => ReadlineResult::Other(e.into()),
145-
}
146-
}
147-
}
148-
149-
#[cfg(not(target_os = "wasi"))]
150-
type Readline<'a> = RustylineReadline<'a>;
151-
15246
pub fn run_shell(vm: &VirtualMachine, scope: Scope) -> PyResult<()> {
15347
println!(
15448
"Welcome to the magnificent Rust Python {} interpreter \u{1f631} \u{1f596}",
@@ -187,7 +81,7 @@ pub fn run_shell(vm: &VirtualMachine, scope: Scope) -> PyResult<()> {
18781
ReadlineResult::Line(line) => {
18882
debug!("You entered {:?}", line);
18983

190-
repl.add_history_entry(line.trim_end());
84+
repl.add_history_entry(line.trim_end()).unwrap();
19185

19286
let stop_continuing = line.is_empty();
19387

0 commit comments

Comments
 (0)