Skip to content

Commit bddaf3e

Browse files
committed
Implement while-else and for-else. Call __neg__ and __invert__ methods on unary operation.
1 parent cb4d66b commit bddaf3e

File tree

7 files changed

+81
-69
lines changed

7 files changed

+81
-69
lines changed

tests/snippets/for.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,12 @@
11
x = 0
2-
for i in [1,2,3,4]:
2+
for i in [1, 2, 3, 4]:
33
x += 1
44

55
assert x == 4
66

7+
for i in [1, 2, 3]:
8+
x = i + 5
9+
else:
10+
x = 3
11+
12+
assert x == 3

vm/src/bytecode.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,9 @@ pub enum Instruction {
124124
CallFunction {
125125
typ: CallType,
126126
},
127-
ForIter,
127+
ForIter {
128+
target: Label,
129+
},
128130
ReturnValue,
129131
YieldValue,
130132
YieldFrom,

vm/src/compile.rs

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -199,13 +199,9 @@ impl Compiler {
199199
}
200200
self.set_label(end_label);
201201
}
202-
ast::Statement::While {
203-
test,
204-
body,
205-
orelse: _,
206-
} => {
207-
// TODO: Handle while-loop else clauses
202+
ast::Statement::While { test, body, orelse } => {
208203
let start_label = self.new_label();
204+
let else_label = self.new_label();
209205
let end_label = self.new_label();
210206
self.emit(Instruction::SetupLoop {
211207
start: start_label,
@@ -214,12 +210,17 @@ impl Compiler {
214210

215211
self.set_label(start_label);
216212

217-
self.compile_test(test, None, Some(end_label), EvalContext::Statement)?;
213+
self.compile_test(test, None, Some(else_label), EvalContext::Statement)?;
218214
self.compile_statements(body)?;
219215
self.emit(Instruction::Jump {
220216
target: start_label,
221217
});
218+
self.set_label(else_label);
219+
if let Some(orelse) = orelse {
220+
self.compile_statements(orelse)?;
221+
}
222222
self.set_label(end_label);
223+
self.emit(Instruction::PopBlock);
223224
}
224225
ast::Statement::With { items, body } => {
225226
let end_label = self.new_label();
@@ -246,9 +247,8 @@ impl Compiler {
246247
target,
247248
iter,
248249
body,
249-
orelse: _,
250+
orelse,
250251
} => {
251-
// TODO: Handle for loop else clauses
252252
// The thing iterated:
253253
for i in iter {
254254
self.compile_expression(i)?;
@@ -259,13 +259,14 @@ impl Compiler {
259259

260260
// Start loop
261261
let start_label = self.new_label();
262+
let else_label = self.new_label();
262263
let end_label = self.new_label();
263264
self.emit(Instruction::SetupLoop {
264265
start: start_label,
265266
end: end_label,
266267
});
267268
self.set_label(start_label);
268-
self.emit(Instruction::ForIter);
269+
self.emit(Instruction::ForIter { target: else_label });
269270

270271
// Start of loop iteration, set targets:
271272
self.compile_store(target)?;
@@ -275,6 +276,10 @@ impl Compiler {
275276
self.emit(Instruction::Jump {
276277
target: start_label,
277278
});
279+
self.set_label(else_label);
280+
if let Some(orelse) = orelse {
281+
self.compile_statements(orelse)?;
282+
}
278283
self.set_label(end_label);
279284
self.emit(Instruction::PopBlock);
280285
}
@@ -1174,7 +1179,7 @@ impl Compiler {
11741179
end: end_label,
11751180
});
11761181
self.set_label(start_label);
1177-
self.emit(Instruction::ForIter);
1182+
self.emit(Instruction::ForIter { target: end_label });
11781183

11791184
self.compile_store(&generator.target)?;
11801185

vm/src/frame.rs

Lines changed: 16 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -408,7 +408,7 @@ impl Frame {
408408
self.push_value(iter_obj);
409409
Ok(None)
410410
}
411-
bytecode::Instruction::ForIter => {
411+
bytecode::Instruction::ForIter { target } => {
412412
// The top of stack contains the iterator, lets push it forward:
413413
let top_of_stack = self.last_value();
414414
let next_obj = objiter::get_next_object(vm, &top_of_stack);
@@ -424,12 +424,7 @@ impl Frame {
424424
self.pop_value();
425425

426426
// End of for loop
427-
let end_label = if let Block::Loop { start: _, end } = self.last_block() {
428-
*end
429-
} else {
430-
panic!("Wrong block type")
431-
};
432-
self.jump(end_label);
427+
self.jump(*target);
433428
Ok(None)
434429
}
435430
Err(next_error) => {
@@ -927,49 +922,18 @@ impl Frame {
927922
) -> FrameResult {
928923
let a = self.pop_value();
929924
let value = match op {
930-
&bytecode::UnaryOperator::Minus => {
931-
// TODO:
932-
// self.invoke('__neg__'
933-
match a.borrow().kind {
934-
PyObjectKind::Integer { value: ref value1 } => vm.ctx.new_int(-value1),
935-
PyObjectKind::Float { value: ref value1 } => vm.ctx.new_float(-*value1),
936-
_ => panic!("Not impl {:?}", a),
937-
}
938-
}
925+
&bytecode::UnaryOperator::Minus => vm.call_method(&a, "__neg__", vec![])?,
926+
&bytecode::UnaryOperator::Plus => vm.call_method(&a, "__pos__", vec![])?,
927+
&bytecode::UnaryOperator::Invert => vm.call_method(&a, "__invert__", vec![])?,
939928
&bytecode::UnaryOperator::Not => {
940929
let value = objbool::boolval(vm, a)?;
941930
vm.ctx.new_bool(!value)
942931
}
943-
_ => panic!("Not impl {:?}", op),
944932
};
945933
self.push_value(value);
946934
Ok(None)
947935
}
948936

949-
fn _eq(&mut self, vm: &mut VirtualMachine, a: PyObjectRef, b: PyObjectRef) -> PyResult {
950-
vm.call_method(&a, "__eq__", vec![b])
951-
}
952-
953-
fn _ne(&mut self, vm: &mut VirtualMachine, a: PyObjectRef, b: PyObjectRef) -> PyResult {
954-
vm.call_method(&a, "__ne__", vec![b])
955-
}
956-
957-
fn _lt(&mut self, vm: &mut VirtualMachine, a: PyObjectRef, b: PyObjectRef) -> PyResult {
958-
vm.call_method(&a, "__lt__", vec![b])
959-
}
960-
961-
fn _le(&mut self, vm: &mut VirtualMachine, a: PyObjectRef, b: PyObjectRef) -> PyResult {
962-
vm.call_method(&a, "__le__", vec![b])
963-
}
964-
965-
fn _gt(&mut self, vm: &mut VirtualMachine, a: PyObjectRef, b: PyObjectRef) -> PyResult {
966-
vm.call_method(&a, "__gt__", vec![b])
967-
}
968-
969-
fn _ge(&mut self, vm: &mut VirtualMachine, a: PyObjectRef, b: PyObjectRef) -> PyResult {
970-
vm.call_method(&a, "__ge__", vec![b])
971-
}
972-
973937
fn _id(&self, a: PyObjectRef) -> usize {
974938
a.get_id()
975939
}
@@ -1035,17 +999,17 @@ impl Frame {
1035999
let b = self.pop_value();
10361000
let a = self.pop_value();
10371001
let value = match op {
1038-
&bytecode::ComparisonOperator::Equal => self._eq(vm, a, b),
1039-
&bytecode::ComparisonOperator::NotEqual => self._ne(vm, a, b),
1040-
&bytecode::ComparisonOperator::Less => self._lt(vm, a, b),
1041-
&bytecode::ComparisonOperator::LessOrEqual => self._le(vm, a, b),
1042-
&bytecode::ComparisonOperator::Greater => self._gt(vm, a, b),
1043-
&bytecode::ComparisonOperator::GreaterOrEqual => self._ge(vm, a, b),
1044-
&bytecode::ComparisonOperator::Is => Ok(vm.ctx.new_bool(self._is(a, b))),
1045-
&bytecode::ComparisonOperator::IsNot => self._is_not(vm, a, b),
1046-
&bytecode::ComparisonOperator::In => self._in(vm, a, b),
1047-
&bytecode::ComparisonOperator::NotIn => self._not_in(vm, a, b),
1048-
}?;
1002+
&bytecode::ComparisonOperator::Equal => vm._eq(&a, b)?,
1003+
&bytecode::ComparisonOperator::NotEqual => vm._ne(&a, b)?,
1004+
&bytecode::ComparisonOperator::Less => vm._lt(&a, b)?,
1005+
&bytecode::ComparisonOperator::LessOrEqual => vm._le(&a, b)?,
1006+
&bytecode::ComparisonOperator::Greater => vm._gt(&a, b)?,
1007+
&bytecode::ComparisonOperator::GreaterOrEqual => vm._ge(&a, b)?,
1008+
&bytecode::ComparisonOperator::Is => vm.ctx.new_bool(self._is(a, b)),
1009+
&bytecode::ComparisonOperator::IsNot => self._is_not(vm, a, b)?,
1010+
&bytecode::ComparisonOperator::In => self._in(vm, a, b)?,
1011+
&bytecode::ComparisonOperator::NotIn => self._not_in(vm, a, b)?,
1012+
};
10491013

10501014
self.push_value(value);
10511015
Ok(None)
@@ -1105,10 +1069,6 @@ impl Frame {
11051069
self.blocks.pop()
11061070
}
11071071

1108-
fn last_block(&self) -> &Block {
1109-
self.blocks.last().unwrap()
1110-
}
1111-
11121072
pub fn push_value(&mut self, obj: PyObjectRef) {
11131073
self.stack.push(obj);
11141074
}

vm/src/obj/objfloat.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,13 @@ fn float_mod(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
225225
}
226226
}
227227

228+
fn float_neg(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
229+
arg_check!(vm, args, required = [(i, Some(vm.ctx.float_type()))]);
230+
231+
let v1 = get_value(i);
232+
Ok(vm.ctx.new_float(-v1))
233+
}
234+
228235
fn float_pow(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
229236
arg_check!(
230237
vm,
@@ -257,6 +264,7 @@ pub fn init(context: &PyContext) {
257264
float_type.set_attr("__floordiv__", context.new_rustfunc(float_floordiv));
258265
float_type.set_attr("__init__", context.new_rustfunc(float_init));
259266
float_type.set_attr("__mod__", context.new_rustfunc(float_mod));
267+
float_type.set_attr("__neg__", context.new_rustfunc(float_neg));
260268
float_type.set_attr("__pow__", context.new_rustfunc(float_pow));
261269
float_type.set_attr("__sub__", context.new_rustfunc(float_sub));
262270
float_type.set_attr("__repr__", context.new_rustfunc(float_repr));

vm/src/obj/objint.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -281,6 +281,12 @@ fn int_mod(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
281281
}
282282
}
283283

284+
fn int_neg(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
285+
arg_check!(vm, args, required = [(i, Some(vm.ctx.int_type()))]);
286+
let i = BigInt::from_pyobj(i);
287+
Ok(vm.ctx.new_int(-i))
288+
}
289+
284290
fn int_pow(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
285291
arg_check!(
286292
vm,
@@ -386,6 +392,7 @@ pub fn init(context: &PyContext) {
386392
int_type.set_attr("__new__", context.new_rustfunc(int_new));
387393
int_type.set_attr("__mod__", context.new_rustfunc(int_mod));
388394
int_type.set_attr("__mul__", context.new_rustfunc(int_mul));
395+
int_type.set_attr("__neg__", context.new_rustfunc(int_neg));
389396
int_type.set_attr("__or__", context.new_rustfunc(int_or));
390397
int_type.set_attr("__pow__", context.new_rustfunc(int_pow));
391398
int_type.set_attr("__repr__", context.new_rustfunc(int_repr));

vm/src/vm.rs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -409,6 +409,30 @@ impl VirtualMachine {
409409
pub fn _and(&mut self, a: PyObjectRef, b: PyObjectRef) -> PyResult {
410410
self.call_method(&a, "__and__", vec![b])
411411
}
412+
413+
pub fn _eq(&mut self, a: &PyObjectRef, b: PyObjectRef) -> PyResult {
414+
self.call_method(a, "__eq__", vec![b])
415+
}
416+
417+
pub fn _ne(&mut self, a: &PyObjectRef, b: PyObjectRef) -> PyResult {
418+
self.call_method(a, "__ne__", vec![b])
419+
}
420+
421+
pub fn _lt(&mut self, a: &PyObjectRef, b: PyObjectRef) -> PyResult {
422+
self.call_method(a, "__lt__", vec![b])
423+
}
424+
425+
pub fn _le(&mut self, a: &PyObjectRef, b: PyObjectRef) -> PyResult {
426+
self.call_method(a, "__le__", vec![b])
427+
}
428+
429+
pub fn _gt(&mut self, a: &PyObjectRef, b: PyObjectRef) -> PyResult {
430+
self.call_method(a, "__gt__", vec![b])
431+
}
432+
433+
pub fn _ge(&mut self, a: &PyObjectRef, b: PyObjectRef) -> PyResult {
434+
self.call_method(a, "__ge__", vec![b])
435+
}
412436
}
413437

414438
#[cfg(test)]

0 commit comments

Comments
 (0)