Skip to content

Commit 41d73c4

Browse files
Merge branch 'master' into range-builtin
2 parents 64bd33e + 2b22cd4 commit 41d73c4

22 files changed

+259
-156
lines changed

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.

parser/src/ast.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,9 +65,9 @@ pub enum Statement {
6565
value: Expression,
6666
},
6767
AugAssign {
68-
target: Expression,
68+
target: Box<Expression>,
6969
op: Operator,
70-
value: Expression,
70+
value: Box<Expression>,
7171
},
7272
Expression {
7373
expression: Expression,

parser/src/lexer.rs

Lines changed: 20 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -64,10 +64,7 @@ pub struct Location {
6464

6565
impl Location {
6666
pub fn new(row: usize, column: usize) -> Self {
67-
Location {
68-
row: row,
69-
column: column,
70-
}
67+
Location { row, column }
7168
}
7269

7370
pub fn get_row(&self) -> usize {
@@ -126,8 +123,7 @@ pub type Spanned<Tok> = Result<(Location, Tok, Location), LexicalError>;
126123
pub fn make_tokenizer<'a>(source: &'a str) -> impl Iterator<Item = Spanned<Tok>> + 'a {
127124
let nlh = NewlineHandler::new(source.chars());
128125
let lch = LineContinationHandler::new(nlh);
129-
let lexer = Lexer::new(lch);
130-
lexer
126+
Lexer::new(lch)
131127
}
132128

133129
// The newline handler is an iterator which collapses different newline
@@ -144,7 +140,7 @@ where
144140
{
145141
pub fn new(source: T) -> Self {
146142
let mut nlh = NewlineHandler {
147-
source: source,
143+
source,
148144
chr0: None,
149145
chr1: None,
150146
};
@@ -200,7 +196,7 @@ where
200196
{
201197
pub fn new(source: T) -> Self {
202198
let mut nlh = LineContinationHandler {
203-
source: source,
199+
source,
204200
chr0: None,
205201
chr1: None,
206202
};
@@ -313,7 +309,7 @@ where
313309
if keywords.contains_key(&name) {
314310
Ok((start_pos, keywords.remove(&name).unwrap(), end_pos))
315311
} else {
316-
Ok((start_pos, Tok::Name { name: name }, end_pos))
312+
Ok((start_pos, Tok::Name { name }, end_pos))
317313
}
318314
}
319315

@@ -358,7 +354,7 @@ where
358354

359355
let end_pos = self.get_pos();
360356
let value = BigInt::from_str_radix(&value_text, radix).unwrap();
361-
Ok((start_pos, Tok::Int { value: value }, end_pos))
357+
Ok((start_pos, Tok::Int { value }, end_pos))
362358
}
363359

364360
fn lex_normal_number(&mut self) -> Spanned<Tok> {
@@ -410,26 +406,19 @@ where
410406
))
411407
} else {
412408
let end_pos = self.get_pos();
413-
Ok((start_pos, Tok::Float { value: value }, end_pos))
409+
Ok((start_pos, Tok::Float { value }, end_pos))
414410
}
415411
} else {
416412
// Parse trailing 'j':
417413
if self.chr0 == Some('j') {
418414
self.next_char();
419415
let end_pos = self.get_pos();
420416
let imag = f64::from_str(&value_text).unwrap();
421-
Ok((
422-
start_pos,
423-
Tok::Complex {
424-
real: 0.0,
425-
imag: imag,
426-
},
427-
end_pos,
428-
))
417+
Ok((start_pos, Tok::Complex { real: 0.0, imag }, end_pos))
429418
} else {
430419
let end_pos = self.get_pos();
431420
let value = value_text.parse::<BigInt>().unwrap();
432-
Ok((start_pos, Tok::Int { value: value }, end_pos))
421+
Ok((start_pos, Tok::Int { value }, end_pos))
433422
}
434423
}
435424
}
@@ -548,33 +537,33 @@ where
548537
}
549538
};
550539

551-
return Ok((start_pos, tok, end_pos));
540+
Ok((start_pos, tok, end_pos))
552541
}
553542

554543
fn is_char(&self) -> bool {
555544
match self.chr0 {
556-
Some('a'...'z') | Some('A'...'Z') | Some('_') | Some('0'...'9') => return true,
557-
_ => return false,
545+
Some('a'...'z') | Some('A'...'Z') | Some('_') | Some('0'...'9') => true,
546+
_ => false,
558547
}
559548
}
560549

561550
fn is_number(&self, radix: u32) -> bool {
562551
match radix {
563552
2 => match self.chr0 {
564-
Some('0'...'1') => return true,
565-
_ => return false,
553+
Some('0'...'1') => true,
554+
_ => false,
566555
},
567556
8 => match self.chr0 {
568-
Some('0'...'7') => return true,
569-
_ => return false,
557+
Some('0'...'7') => true,
558+
_ => false,
570559
},
571560
10 => match self.chr0 {
572-
Some('0'...'9') => return true,
573-
_ => return false,
561+
Some('0'...'9') => true,
562+
_ => false,
574563
},
575564
16 => match self.chr0 {
576-
Some('0'...'9') | Some('a'...'f') | Some('A'...'F') => return true,
577-
_ => return false,
565+
Some('0'...'9') | Some('a'...'f') | Some('A'...'F') => true,
566+
_ => false,
578567
},
579568
x => unimplemented!("Radix not implemented: {}", x),
580569
}

parser/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ extern crate num_traits;
77
pub mod ast;
88
pub mod lexer;
99
pub mod parser;
10+
#[cfg_attr(rustfmt, rustfmt_skip)]
1011
mod python;
1112
pub mod token;
1213

parser/src/python.lalrpop

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,11 @@ ExpressionStatement: ast::LocatedStatement = {
105105
let rhs = e2.into_iter().next().unwrap();
106106
ast::LocatedStatement {
107107
location: loc,
108-
node: ast::Statement::AugAssign { target: expr, op: op, value: rhs },
108+
node: ast::Statement::AugAssign {
109+
target: Box::new(expr),
110+
op,
111+
value: Box::new(rhs)
112+
},
109113
}
110114
},
111115
};

src/main.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ fn main() {
7070
}
7171

7272
fn _run_string(vm: &mut VirtualMachine, source: &str, source_path: Option<String>) -> PyResult {
73-
let code_obj = compile::compile(vm, source, compile::Mode::Exec, source_path)?;
73+
let code_obj = compile::compile(vm, source, &compile::Mode::Exec, source_path)?;
7474
// trace!("Code object: {:?}", code_obj.borrow());
7575
let builtins = vm.get_builtin_scope();
7676
let vars = vm.context().new_scope(Some(builtins)); // Keep track of local variables
@@ -115,7 +115,7 @@ fn run_script(vm: &mut VirtualMachine, script_file: &str) -> PyResult {
115115
}
116116

117117
fn shell_exec(vm: &mut VirtualMachine, source: &str, scope: PyObjectRef) -> bool {
118-
match compile::compile(vm, source, compile::Mode::Single, None) {
118+
match compile::compile(vm, source, &compile::Mode::Single, None) {
119119
Ok(code) => {
120120
match vm.run_code_obj(code, scope) {
121121
Ok(_value) => {

tests/snippets/basic_types.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@
4545
assert type(a) is complex
4646
assert type(a + a) is complex
4747

48+
a = 1
49+
assert a.conjugate() == a
4850

4951
a = 12345
5052

tests/snippets/bools.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,3 +46,5 @@ def __bool__(self):
4646
assert False * 7 == 0
4747
assert True > 0
4848
assert int(True) == 1
49+
assert True.conjugate() == 1
50+
assert isinstance(True.conjugate(), int)

tests/snippets/tuple.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
y = (1,)
77
assert y[0] == 1
88

9+
assert x + y == (1, 2, 1)
10+
911
assert x * 3 == (1, 2, 1, 2, 1, 2)
1012
# assert 3 * x == (1, 2, 1, 2, 1, 2)
1113
assert x * 0 == ()

tests/snippets/unicode_slicing.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
def test_slice_bounds(s):
2+
# End out of range
3+
assert s[0:100] == s
4+
assert s[0:-100] == ''
5+
# Start out of range
6+
assert s[100:1] == ''
7+
# Out of range both sides
8+
# This is the behaviour in cpython
9+
# assert s[-100:100] == s
10+
11+
def expect_index_error(s, index):
12+
try:
13+
s[index]
14+
except IndexError:
15+
pass
16+
else:
17+
assert False
18+
19+
unicode_str = "∀∂"
20+
assert unicode_str[0] == "∀"
21+
assert unicode_str[1] == "∂"
22+
assert unicode_str[-1] == "∂"
23+
24+
test_slice_bounds(unicode_str)
25+
expect_index_error(unicode_str, 100)
26+
expect_index_error(unicode_str, -100)
27+
28+
ascii_str = "hello world"
29+
test_slice_bounds(ascii_str)
30+
assert ascii_str[0] == "h"
31+
assert ascii_str[1] == "e"
32+
assert ascii_str[-1] == "d"
33+

vm/Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,4 +17,5 @@ serde_json = "1.0.26"
1717
byteorder = "1.2.6"
1818
regex = "1"
1919
statrs = "0.10.0"
20-
caseless = "0.2.1"
20+
caseless = "0.2.1"
21+
unicode-segmentation = "1.2.1"

vm/src/builtins.rs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@ fn builtin_compile(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
151151

152152
let filename = objstr::get_value(filename);
153153

154-
compile::compile(vm, &source, mode, Some(filename))
154+
compile::compile(vm, &source, &mode, Some(filename))
155155
}
156156

157157
fn builtin_delattr(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
@@ -203,6 +203,8 @@ fn builtin_enumerate(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
203203
Ok(vm.ctx.new_list(new_items))
204204
}
205205

206+
/// Implements `eval`.
207+
/// See also: https://docs.python.org/3/library/functions.html#eval
206208
fn builtin_eval(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
207209
arg_check!(
208210
vm,
@@ -222,7 +224,7 @@ fn builtin_eval(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
222224
let source = objstr::get_value(source);
223225
// TODO: fix this newline bug:
224226
let source = format!("{}\n", source);
225-
compile::compile(vm, &source, mode, None)?
227+
compile::compile(vm, &source, &mode, None)?
226228
} else {
227229
return Err(vm.new_type_error("code argument must be str or code object".to_string()));
228230
};
@@ -249,6 +251,8 @@ fn builtin_eval(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
249251
vm.run_code_obj(code_obj.clone(), scope)
250252
}
251253

254+
/// Implements `exec`
255+
/// https://docs.python.org/3/library/functions.html#exec
252256
fn builtin_exec(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
253257
arg_check!(
254258
vm,
@@ -266,7 +270,7 @@ fn builtin_exec(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
266270
let source = objstr::get_value(source);
267271
// TODO: fix this newline bug:
268272
let source = format!("{}\n", source);
269-
compile::compile(vm, &source, mode, None)?
273+
compile::compile(vm, &source, &mode, None)?
270274
} else if objtype::isinstance(source, &vm.ctx.code_type()) {
271275
source.clone()
272276
} else {

0 commit comments

Comments
 (0)