Skip to content

Commit 0722487

Browse files
authored
Merge pull request #1 from RustPython/master
upstream
2 parents 6752f67 + d6242ac commit 0722487

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

54 files changed

+700
-583
lines changed

Cargo.lock

+35-11
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

parser/src/lexer.rs

+1-3
Original file line numberDiff line numberDiff line change
@@ -687,9 +687,7 @@ where
687687

688688
match self.chr0 {
689689
Some('0'..='9') => return Some(self.lex_number()),
690-
Some('_') | Some('a'..='z') | Some('A'..='Z') => {
691-
return Some(self.lex_identifier())
692-
}
690+
Some('_') | Some('a'..='z') | Some('A'..='Z') => return Some(self.lex_identifier()),
693691
Some('#') => {
694692
self.lex_comment();
695693
continue;

tests/snippets/dismod.py

+28-4
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,34 @@
11
import dis
22

3-
dis.disassemble(compile("5 + x + 5 or 2", "", "eval"))
3+
dis.dis(compile("5 + x + 5 or 2", "", "eval"))
44
print("\n")
5-
dis.disassemble(compile("def f(x):\n return 1", "", "exec"))
5+
dis.dis(compile("def f(x):\n return 1", "", "exec"))
66
print("\n")
7-
dis.disassemble(compile("if a:\n 1 or 2\nelif x == 'hello':\n 3\nelse:\n 4", "", "exec"))
7+
dis.dis(compile("if a:\n 1 or 2\nelif x == 'hello':\n 3\nelse:\n 4", "", "exec"))
88
print("\n")
9-
dis.disassemble(compile("f(x=1, y=2)", "", "eval"))
9+
dis.dis(compile("f(x=1, y=2)", "", "eval"))
1010
print("\n")
11+
12+
def f():
13+
with g():
14+
try:
15+
for a in {1: 4, 2: 5}:
16+
yield [True and False or True, []]
17+
except Exception:
18+
raise not ValueError({1 for i in [1,2,3]})
19+
20+
dis.dis(f)
21+
22+
class A(object):
23+
def f():
24+
x += 1
25+
pass
26+
def g():
27+
for i in range(5):
28+
if i:
29+
continue
30+
else:
31+
break
32+
33+
print("A.f\n")
34+
dis.dis(A.f)

vm/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ serde_derive = "1.0.66"
1818
serde_json = "1.0.26"
1919
byteorder = "1.2.6"
2020
regex = "1"
21+
rustc_version_runtime = "0.1.*"
2122
statrs = "0.10.0"
2223
caseless = "0.2.1"
2324
unicode-segmentation = "1.2.1"

vm/src/builtins.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
//! Implements functions listed here: https://docs.python.org/3/library/builtins.html
44
55
// use std::ops::Deref;
6+
use std::cell::RefCell;
67
use std::char;
78
use std::io::{self, Write};
89

@@ -273,7 +274,9 @@ fn make_scope(vm: &mut VirtualMachine, locals: Option<&PyObjectRef>) -> PyObject
273274
};
274275

275276
PyObject {
276-
payload: PyObjectPayload::Scope { scope: scope_inner },
277+
payload: PyObjectPayload::Scope {
278+
scope: RefCell::new(scope_inner),
279+
},
277280
typ: None,
278281
}
279282
.into_ref()

vm/src/compile.rs

+28-7
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ struct Compiler {
1717
source_path: Option<String>,
1818
current_source_location: ast::Location,
1919
in_loop: bool,
20+
in_function_def: bool,
2021
}
2122

2223
/// Compile a given sourcecode into a bytecode object.
@@ -75,6 +76,7 @@ impl Compiler {
7576
source_path: None,
7677
current_source_location: ast::Location::default(),
7778
in_loop: false,
79+
in_function_def: false,
7880
}
7981
}
8082

@@ -232,9 +234,10 @@ impl Compiler {
232234

233235
self.compile_test(test, None, Some(else_label), EvalContext::Statement)?;
234236

237+
let was_in_loop = self.in_loop;
235238
self.in_loop = true;
236239
self.compile_statements(body)?;
237-
self.in_loop = false;
240+
self.in_loop = was_in_loop;
238241
self.emit(Instruction::Jump {
239242
target: start_label,
240243
});
@@ -295,10 +298,10 @@ impl Compiler {
295298
// Start of loop iteration, set targets:
296299
self.compile_store(target)?;
297300

298-
// Body of loop:
301+
let was_in_loop = self.in_loop;
299302
self.in_loop = true;
300303
self.compile_statements(body)?;
301-
self.in_loop = false;
304+
self.in_loop = was_in_loop;
302305

303306
self.emit(Instruction::Jump {
304307
target: start_label,
@@ -431,6 +434,11 @@ impl Compiler {
431434
decorator_list,
432435
} => {
433436
// Create bytecode for this function:
437+
// remember to restore self.in_loop to the original after the function is compiled
438+
let was_in_loop = self.in_loop;
439+
let was_in_function_def = self.in_function_def;
440+
self.in_loop = false;
441+
self.in_function_def = true;
434442
let flags = self.enter_function(name, args)?;
435443
self.compile_statements(body)?;
436444

@@ -458,6 +466,8 @@ impl Compiler {
458466
self.emit(Instruction::StoreName {
459467
name: name.to_string(),
460468
});
469+
self.in_loop = was_in_loop;
470+
self.in_function_def = was_in_function_def;
461471
}
462472
ast::Statement::ClassDef {
463473
name,
@@ -466,6 +476,8 @@ impl Compiler {
466476
keywords,
467477
decorator_list,
468478
} => {
479+
let was_in_loop = self.in_loop;
480+
self.in_loop = false;
469481
self.prepare_decorators(decorator_list)?;
470482
self.emit(Instruction::LoadBuildClass);
471483
let line_number = self.get_source_line_number();
@@ -546,6 +558,7 @@ impl Compiler {
546558
self.emit(Instruction::StoreName {
547559
name: name.to_string(),
548560
});
561+
self.in_loop = was_in_loop;
549562
}
550563
ast::Statement::Assert { test, msg } => {
551564
// TODO: if some flag, ignore all assert statements!
@@ -584,6 +597,9 @@ impl Compiler {
584597
self.emit(Instruction::Continue);
585598
}
586599
ast::Statement::Return { value } => {
600+
if !self.in_function_def {
601+
return Err(CompileError::InvalidReturn);
602+
}
587603
match value {
588604
Some(e) => {
589605
let size = e.len();
@@ -663,7 +679,6 @@ impl Compiler {
663679
name: &str,
664680
args: &ast::Parameters,
665681
) -> Result<bytecode::FunctionOpArg, CompileError> {
666-
self.in_loop = false;
667682
let have_kwargs = !args.defaults.is_empty();
668683
if have_kwargs {
669684
// Construct a tuple:
@@ -971,6 +986,9 @@ impl Compiler {
971986
self.emit(Instruction::BuildSlice { size });
972987
}
973988
ast::Expression::Yield { value } => {
989+
if !self.in_function_def {
990+
return Err(CompileError::InvalidYield);
991+
}
974992
self.mark_generator();
975993
match value {
976994
Some(expression) => self.compile_expression(expression)?,
@@ -1021,6 +1039,7 @@ impl Compiler {
10211039
}
10221040
ast::Expression::Lambda { args, body } => {
10231041
let name = "<lambda>".to_string();
1042+
// no need to worry about the self.loop_depth because there are no loops in lambda expressions
10241043
let flags = self.enter_function(&name, args)?;
10251044
self.compile_expression(body)?;
10261045
self.emit(Instruction::ReturnValue);
@@ -1369,10 +1388,11 @@ impl Compiler {
13691388

13701389
// Low level helper functions:
13711390
fn emit(&mut self, instruction: Instruction) {
1372-
self.current_code_object().instructions.push(instruction);
1373-
// TODO: insert source filename
13741391
let location = self.current_source_location.clone();
1375-
self.current_code_object().locations.push(location);
1392+
let mut cur_code_obj = self.current_code_object();
1393+
cur_code_obj.instructions.push(instruction);
1394+
cur_code_obj.locations.push(location);
1395+
// TODO: insert source filename
13761396
}
13771397

13781398
fn current_code_object(&mut self) -> &mut CodeObject {
@@ -1413,6 +1433,7 @@ mod tests {
14131433
use crate::bytecode::Constant::*;
14141434
use crate::bytecode::Instruction::*;
14151435
use rustpython_parser::parser;
1436+
14161437
fn compile_exec(source: &str) -> CodeObject {
14171438
let mut compiler = Compiler::new();
14181439
compiler.source_path = Some("source_path".to_string());

vm/src/error.rs

+6-2
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ pub enum CompileError {
1919
InvalidBreak,
2020
/// Continue statement outside of loop.
2121
InvalidContinue,
22+
InvalidReturn,
23+
InvalidYield,
2224
}
2325

2426
impl fmt::Display for CompileError {
@@ -29,8 +31,10 @@ impl fmt::Display for CompileError {
2931
CompileError::ExpectExpr => write!(f, "Expecting expression, got statement"),
3032
CompileError::Parse(err) => write!(f, "{}", err),
3133
CompileError::StarArgs => write!(f, "Two starred expressions in assignment"),
32-
CompileError::InvalidBreak => write!(f, "break outside loop"),
33-
CompileError::InvalidContinue => write!(f, "continue outside loop"),
34+
CompileError::InvalidBreak => write!(f, "'break' outside loop"),
35+
CompileError::InvalidContinue => write!(f, "'continue' outside loop"),
36+
CompileError::InvalidReturn => write!(f, "'return' outside function"),
37+
CompileError::InvalidYield => write!(f, "'yield' outside function"),
3438
}
3539
}
3640
}

0 commit comments

Comments
 (0)