Skip to content

Commit b8cb9f7

Browse files
Merge branch 'master' into add_check_byte_value
2 parents 51f6ec2 + f588f58 commit b8cb9f7

File tree

5 files changed

+79
-3
lines changed

5 files changed

+79
-3
lines changed

tests/snippets/bytearray.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,25 @@
3737
try:
3838
bytearray([400])
3939
except ValueError:
40+
pass
41+
else:
42+
assert False
43+
44+
b = bytearray(b'test')
45+
assert len(b) == 4
46+
b.pop()
47+
assert len(b) == 3
48+
49+
c = bytearray([123, 255, 111])
50+
assert len(c) == 3
51+
c.pop()
52+
assert len(c) == 2
53+
c.pop()
54+
c.pop()
55+
56+
try:
57+
c.pop()
58+
except IndexError:
4059
pass
4160
else:
4261
assert False

tests/snippets/control_flow.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
# break from a nested for loop
2+
13
def foo():
24
sum = 0
35
for i in range(10):
@@ -8,3 +10,24 @@ def foo():
810
return sum
911

1012
assert foo() == 45
13+
14+
15+
# continue statement
16+
17+
def primes(limit):
18+
"""Finds all the primes from 2 up to a given number using the Sieve of Eratosthenes."""
19+
sieve = [False] * (limit + 1)
20+
for i in range(2, limit + 1):
21+
if sieve[i]:
22+
continue
23+
yield i
24+
25+
for j in range(2 * i, limit + 1, i):
26+
sieve[j] = True
27+
28+
29+
assert list(primes(1)) == []
30+
assert list(primes(2)) == [2]
31+
assert list(primes(10)) == [2, 3, 5, 7]
32+
assert list(primes(13)) == [2, 3, 5, 7, 11, 13]
33+

vm/src/frame.rs

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -542,7 +542,10 @@ impl Frame {
542542
bytecode::Instruction::Break => {
543543
let block = self.unwind_loop(vm);
544544
if let BlockType::Loop { end, .. } = block.typ {
545+
self.pop_block();
545546
self.jump(end);
547+
} else {
548+
unreachable!()
546549
}
547550
Ok(None)
548551
}
@@ -555,7 +558,7 @@ impl Frame {
555558
if let BlockType::Loop { start, .. } = block.typ {
556559
self.jump(start);
557560
} else {
558-
assert!(false);
561+
unreachable!();
559562
}
560563
Ok(None)
561564
}
@@ -745,7 +748,7 @@ impl Frame {
745748

746749
fn unwind_loop(&mut self, vm: &mut VirtualMachine) -> Block {
747750
loop {
748-
let block = self.pop_block().expect("not in a loop");
751+
let block = self.current_block().cloned().expect("not in a loop");
749752
match block.typ {
750753
BlockType::Loop { .. } => break block,
751754
BlockType::TryExcept { .. } => {
@@ -760,6 +763,8 @@ impl Frame {
760763
}
761764
},
762765
}
766+
767+
self.pop_block();
763768
}
764769
}
765770

@@ -1080,6 +1085,10 @@ impl Frame {
10801085
Some(block)
10811086
}
10821087

1088+
fn current_block(&self) -> Option<&Block> {
1089+
self.blocks.last()
1090+
}
1091+
10831092
pub fn push_value(&mut self, obj: PyObjectRef) {
10841093
self.stack.push(obj);
10851094
}

vm/src/obj/objbytearray.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ use super::super::pyobject::{
77
use super::objint;
88

99
use super::super::vm::VirtualMachine;
10+
use super::objbytes::get_mut_value;
1011
use super::objbytes::get_value;
1112
use super::objtype;
1213
use num_traits::ToPrimitive;
@@ -100,6 +101,7 @@ pub fn init(context: &PyContext) {
100101
"clear",
101102
context.new_rustfunc(bytearray_clear),
102103
);
104+
context.set_attr(&bytearray_type, "pop", context.new_rustfunc(bytearray_pop));
103105
}
104106

105107
fn bytearray_new(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
@@ -282,3 +284,14 @@ fn bytearray_clear(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
282284
_ => panic!("Bytearray has incorrect payload."),
283285
}
284286
}
287+
288+
fn bytearray_pop(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
289+
arg_check!(vm, args, required = [(obj, Some(vm.ctx.bytearray_type()))]);
290+
let mut value = get_mut_value(obj);
291+
292+
if let Some(i) = value.pop() {
293+
Ok(vm.ctx.new_int(i))
294+
} else {
295+
Err(vm.new_index_error("pop from empty bytearray".to_string()))
296+
}
297+
}

vm/src/obj/objbytes.rs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,10 @@ use super::objint;
66
use super::objtype;
77
use num_traits::ToPrimitive;
88
use std::cell::Ref;
9+
use std::cell::RefMut;
910
use std::hash::{Hash, Hasher};
1011
use std::ops::Deref;
12+
use std::ops::DerefMut;
1113

1214
// Binary data support
1315

@@ -183,7 +185,17 @@ pub fn get_value<'a>(obj: &'a PyObjectRef) -> impl Deref<Target = Vec<u8>> + 'a
183185
if let PyObjectPayload::Bytes { ref value } = py_obj.payload {
184186
value
185187
} else {
186-
panic!("Inner error getting int {:?}", obj);
188+
panic!("Inner error getting bytearray {:?}", obj);
189+
}
190+
})
191+
}
192+
193+
pub fn get_mut_value<'a>(obj: &'a PyObjectRef) -> impl DerefMut<Target = Vec<u8>> + 'a {
194+
RefMut::map(obj.borrow_mut(), |py_obj| {
195+
if let PyObjectPayload::Bytes { ref mut value } = py_obj.payload {
196+
value
197+
} else {
198+
panic!("Inner error getting bytearray {:?}", obj);
187199
}
188200
})
189201
}

0 commit comments

Comments
 (0)