Merge pull request #241 from coolreader18/formatted-exceptions

Format exceptions nicely (no more RefCell { value: .. }!)
This commit is contained in:
Windel Bouwman
2018-12-27 09:14:35 +01:00
committed by GitHub
13 changed files with 104 additions and 57 deletions

View File

@@ -408,13 +408,11 @@ fn builtin_len(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
let len_method_name = "__len__".to_string();
match vm.get_method(obj.clone(), &len_method_name) {
Ok(value) => vm.invoke(value, PyFuncArgs::default()),
Err(..) => Err(vm.context().new_str(
format!(
"TypeError: object of this {:?} type has no method {:?}",
obj, len_method_name
)
.to_string(),
)),
Err(..) => Err(vm.new_type_error(format!(
"object of type '{}' has no method {:?}",
objtype::get_type_name(&obj.typ()),
len_method_name
))),
}
}
@@ -596,13 +594,10 @@ fn builtin_ord(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
let string = objstr::get_value(string);
let string_len = string.chars().count();
if string_len > 1 {
return Err(vm.new_type_error(
format!(
"ord() expected a character, but string of length {} found",
string_len
)
.to_string(),
));
return Err(vm.new_type_error(format!(
"ord() expected a character, but string of length {} found",
string_len
)));
}
match string.chars().next() {
Some(character) => Ok(vm

View File

@@ -511,8 +511,8 @@ impl Frame {
Err(exception)
} else {
let msg = format!(
"Can only raise BaseException derived types, not {:?}",
exception
"Can only raise BaseException derived types, not {}",
exception.borrow()
);
let type_error_type = vm.ctx.exceptions.type_error.clone();
let type_error = vm.new_exception(type_error_type, msg);
@@ -850,7 +850,7 @@ impl Frame {
scope = scope.get_parent();
} else {
let name_error_type = vm.ctx.exceptions.name_error.clone();
let msg = format!("Has not attribute '{}'", name);
let msg = format!("name '{}' is not defined", name);
let name_error = vm.new_exception(name_error_type, msg);
break Err(name_error);
}

View File

@@ -68,7 +68,7 @@ fn complex_add(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
if objtype::isinstance(i2, &vm.ctx.complex_type()) {
Ok(vm.ctx.new_complex(v1 + get_value(i2)))
} else {
Err(vm.new_type_error(format!("Cannot add {:?} and {:?}", i, i2)))
Err(vm.new_type_error(format!("Cannot add {} and {}", i.borrow(), i2.borrow())))
}
}

View File

@@ -52,7 +52,7 @@ pub fn make_float(vm: &mut VirtualMachine, obj: &PyObjectRef) -> Result<f64, PyO
)?;
Ok(get_value(&res))
} else {
Err(vm.new_type_error(format!("Cannot cast {:?} to float", obj)))
Err(vm.new_type_error(format!("Cannot cast {} to float", obj.borrow())))
}
}
@@ -159,7 +159,7 @@ fn float_add(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
.ctx
.new_float(v1 + objint::get_value(i2).to_f64().unwrap()))
} else {
Err(vm.new_type_error(format!("Cannot add {:?} and {:?}", i, i2)))
Err(vm.new_type_error(format!("Cannot add {} and {}", i.borrow(), i2.borrow())))
}
}
@@ -176,7 +176,11 @@ fn float_divmod(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
let r2 = float_mod(vm, args.clone());
Ok(vm.ctx.new_tuple(vec![r1.unwrap(), r2.unwrap()]))
} else {
Err(vm.new_type_error(format!("Cannot divmod power {:?} and {:?}", i, i2)))
Err(vm.new_type_error(format!(
"Cannot divmod power {} and {}",
i.borrow(),
i2.borrow()
)))
}
}
@@ -193,7 +197,11 @@ fn float_floordiv(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
.ctx
.new_float((get_value(i) / objint::get_value(i2).to_f64().unwrap()).floor()))
} else {
Err(vm.new_type_error(format!("Cannot floordiv {:?} and {:?}", i, i2)))
Err(vm.new_type_error(format!(
"Cannot floordiv {} and {}",
i.borrow(),
i2.borrow()
)))
}
}
@@ -211,7 +219,7 @@ fn float_sub(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
.ctx
.new_float(v1 - objint::get_value(i2).to_f64().unwrap()))
} else {
Err(vm.new_type_error(format!("Cannot add {:?} and {:?}", i, i2)))
Err(vm.new_type_error(format!("Cannot add {} and {}", i.borrow(), i2.borrow())))
}
}
@@ -228,7 +236,7 @@ fn float_mod(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
.ctx
.new_float(get_value(i) % objint::get_value(i2).to_f64().unwrap()))
} else {
Err(vm.new_type_error(format!("Cannot mod {:?} and {:?}", i, i2)))
Err(vm.new_type_error(format!("Cannot mod {} and {}", i.borrow(), i2.borrow())))
}
}
@@ -254,7 +262,7 @@ fn float_pow(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
let result = v1.powf(objint::get_value(i2).to_f64().unwrap());
Ok(vm.ctx.new_float(result))
} else {
Err(vm.new_type_error(format!("Cannot add {:?} and {:?}", i, i2)))
Err(vm.new_type_error(format!("Cannot add {} and {}", i.borrow(), i2.borrow())))
}
}

View File

@@ -188,9 +188,9 @@ fn int_add(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
arg_check!(
vm,
args,
required = [(i, Some(vm.ctx.int_type())), (i2, None)]
required = [(_i, Some(vm.ctx.int_type())), (i2, None)]
);
let i = BigInt::from_pyobj(i);
let i = BigInt::from_pyobj(_i);
if objtype::isinstance(i2, &vm.ctx.int_type()) {
Ok(vm.ctx.new_int(i + get_value(i2)))
} else if objtype::isinstance(i2, &vm.ctx.float_type()) {
@@ -198,7 +198,7 @@ fn int_add(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
.ctx
.new_float(i.to_f64().unwrap() + objfloat::get_value(i2)))
} else {
Err(vm.new_type_error(format!("Cannot add {:?} and {:?}", i, i2)))
Err(vm.new_type_error(format!("Cannot add {} and {}", _i.borrow(), i2.borrow())))
}
}
@@ -217,7 +217,11 @@ fn int_floordiv(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
if objtype::isinstance(i2, &vm.ctx.int_type()) {
Ok(vm.ctx.new_int(get_value(i) / get_value(i2)))
} else {
Err(vm.new_type_error(format!("Cannot floordiv {:?} and {:?}", i, i2)))
Err(vm.new_type_error(format!(
"Cannot floordiv {} and {}",
i.borrow(),
i2.borrow()
)))
}
}
@@ -243,9 +247,9 @@ fn int_sub(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
arg_check!(
vm,
args,
required = [(i, Some(vm.ctx.int_type())), (i2, None)]
required = [(_i, Some(vm.ctx.int_type())), (i2, None)]
);
let i = BigInt::from_pyobj(i);
let i = BigInt::from_pyobj(_i);
if objtype::isinstance(i2, &vm.ctx.int_type()) {
Ok(vm.ctx.new_int(i - get_value(i2)))
} else if objtype::isinstance(i2, &vm.ctx.float_type()) {
@@ -253,7 +257,11 @@ fn int_sub(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
.ctx
.new_float(i.to_f64().unwrap() - objfloat::get_value(i2)))
} else {
Err(vm.new_not_implemented_error(format!("Cannot substract {:?} and {:?}", i, i2)))
Err(vm.new_not_implemented_error(format!(
"Cannot substract {} and {}",
_i.borrow(),
i2.borrow()
)))
}
}
@@ -270,7 +278,11 @@ fn int_mul(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
.ctx
.new_float(get_value(i).to_f64().unwrap() * objfloat::get_value(i2)))
} else {
Err(vm.new_type_error(format!("Cannot multiply {:?} and {:?}", i, i2)))
Err(vm.new_type_error(format!(
"Cannot multiply {} and {}",
i.borrow(),
i2.borrow()
)))
}
}
@@ -290,7 +302,7 @@ fn int_truediv(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
.ctx
.new_float(v1.to_f64().unwrap() / objfloat::get_value(i2)))
} else {
Err(vm.new_type_error(format!("Cannot divide {:?} and {:?}", i, i2)))
Err(vm.new_type_error(format!("Cannot divide {} and {}", i.borrow(), i2.borrow())))
}
}
@@ -304,7 +316,7 @@ fn int_mod(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
if objtype::isinstance(i2, &vm.ctx.int_type()) {
Ok(vm.ctx.new_int(v1 % get_value(i2)))
} else {
Err(vm.new_type_error(format!("Cannot modulo {:?} and {:?}", i, i2)))
Err(vm.new_type_error(format!("Cannot modulo {} and {}", i.borrow(), i2.borrow())))
}
}
@@ -333,7 +345,11 @@ fn int_pow(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
let v2 = objfloat::get_value(i2);
Ok(vm.ctx.new_float((v1.to_f64().unwrap()).powf(v2)))
} else {
Err(vm.new_type_error(format!("Cannot raise power {:?} and {:?}", i, i2)))
Err(vm.new_type_error(format!(
"Cannot raise power {} and {}",
i.borrow(),
i2.borrow()
)))
}
}
@@ -349,7 +365,11 @@ fn int_divmod(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
let r2 = int_mod(vm, args.clone());
Ok(vm.ctx.new_tuple(vec![r1.unwrap(), r2.unwrap()]))
} else {
Err(vm.new_type_error(format!("Cannot divmod power {:?} and {:?}", i, i2)))
Err(vm.new_type_error(format!(
"Cannot divmod power {} and {}",
i.borrow(),
i2.borrow()
)))
}
}
@@ -364,7 +384,7 @@ fn int_xor(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
let v2 = get_value(i2);
Ok(vm.ctx.new_int(v1 ^ v2))
} else {
Err(vm.new_type_error(format!("Cannot xor {:?} and {:?}", i, i2)))
Err(vm.new_type_error(format!("Cannot xor {} and {}", i.borrow(), i2.borrow())))
}
}
@@ -379,7 +399,7 @@ fn int_or(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
let v2 = get_value(i2);
Ok(vm.ctx.new_int(v1 | v2))
} else {
Err(vm.new_type_error(format!("Cannot or {:?} and {:?}", i, i2)))
Err(vm.new_type_error(format!("Cannot or {} and {}", i.borrow(), i2.borrow())))
}
}
@@ -394,7 +414,7 @@ fn int_and(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
let v2 = get_value(i2);
Ok(vm.ctx.new_int(v1 & v2))
} else {
Err(vm.new_type_error(format!("Cannot and {:?} and {:?}", i, i2)))
Err(vm.new_type_error(format!("Cannot and {} and {}", i.borrow(), i2.borrow())))
}
}

View File

@@ -86,7 +86,7 @@ fn list_add(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
let elements = e1.iter().chain(e2.iter()).map(|e| e.clone()).collect();
Ok(vm.ctx.new_list(elements))
} else {
Err(vm.new_type_error(format!("Cannot add {:?} and {:?}", o, o2)))
Err(vm.new_type_error(format!("Cannot add {} and {}", o.borrow(), o2.borrow())))
}
}

View File

@@ -164,7 +164,7 @@ fn object_getattribute(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
let attribute_error = vm.context().exceptions.attribute_error.clone();
Err(vm.new_exception(
attribute_error,
format!("{:?} object has no attribute {}", cls, name),
format!("{} has no attribute '{}'", obj.borrow(), name),
))
}
}

View File

@@ -58,7 +58,7 @@ fn set_new(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
);
if !objtype::issubclass(cls, &vm.ctx.set_type()) {
return Err(vm.new_type_error(format!("{:?} is not a subtype of set", cls)));
return Err(vm.new_type_error(format!("{} is not a subtype of set", cls.borrow())));
}
let elements = match iterable {

View File

@@ -144,7 +144,7 @@ fn str_add(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
.ctx
.new_str(format!("{}{}", get_value(&s), get_value(&s2))))
} else {
Err(vm.new_type_error(format!("Cannot add {:?} and {:?}", s, s2)))
Err(vm.new_type_error(format!("Cannot add {} and {}", s.borrow(), s2.borrow())))
}
}
@@ -273,7 +273,11 @@ fn str_mul(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
}
Ok(vm.ctx.new_str(result))
} else {
Err(vm.new_type_error(format!("Cannot multiply {:?} and {:?}", s, s2)))
Err(vm.new_type_error(format!(
"Cannot multiply {} and {}",
s.borrow(),
s2.borrow()
)))
}
}

View File

@@ -85,7 +85,7 @@ fn tuple_new(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
);
if !objtype::issubclass(cls, &vm.ctx.tuple_type()) {
return Err(vm.new_type_error(format!("{:?} is not a subtype of tuple", cls)));
return Err(vm.new_type_error(format!("{} is not a subtype of tuple", cls.borrow())));
}
let elements = if let Some(iterable) = iterable {

View File

@@ -205,7 +205,7 @@ pub fn type_getattribute(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult
let attribute_error = vm.context().exceptions.attribute_error.clone();
Err(vm.new_exception(
attribute_error,
format!("{:?} object {:?} has no attribute {}", mcl, cls, name),
format!("{} has no attribute '{}'", cls.borrow(), name),
))
}
}

View File

@@ -25,7 +25,7 @@ use super::vm::VirtualMachine;
use num_bigint::BigInt;
use num_complex::Complex64;
use num_traits::{One, Zero};
use std::cell::{Ref, RefCell};
use std::cell::RefCell;
use std::collections::HashMap;
use std::fmt;
use std::rc::{Rc, Weak};
@@ -65,12 +65,25 @@ pub type PyObjectWeakRef = Weak<RefCell<PyObject>>;
/// since exceptions are also python objects.
pub type PyResult = Result<PyObjectRef, PyObjectRef>; // A valid value, or an exception
/*
impl fmt::Display for PyObjectRef {
impl fmt::Display for PyObject {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "Obj {:?}", self)
use self::TypeProtocol;
match &self.kind {
PyObjectKind::Module { name, .. } => write!(f, "module '{}'", name),
PyObjectKind::Class { name, .. } => {
let type_name = objtype::get_type_name(&self.typ());
// We don't have access to a vm, so just assume that if its parent's name
// is type, it's a type
if type_name == "type" {
write!(f, "type object '{}'", name)
} else {
write!(f, "'{}' object", type_name)
}
}
_ => write!(f, "'{}' object", objtype::get_type_name(&self.typ())),
}
}
}*/
}
/*
// Idea: implement the iterator trait upon PyObjectRef
@@ -588,7 +601,13 @@ pub trait TypeProtocol {
impl TypeProtocol for PyObjectRef {
fn typ(&self) -> PyObjectRef {
match self.borrow().typ {
self.borrow().typ()
}
}
impl TypeProtocol for PyObject {
fn typ(&self) -> PyObjectRef {
match self.typ {
Some(ref typ) => typ.clone(),
None => panic!("Object {:?} doesn't have a type!", self),
}

View File

@@ -464,10 +464,11 @@ impl VirtualMachine {
let cls = obj.typ();
match cls.get_attr(method_name) {
Some(method) => self.call_get_descriptor(method, obj.clone()),
None => {
Err(self
.new_type_error(format!("{:?} object has no method {:?}", obj, method_name)))
}
None => Err(self.new_type_error(format!(
"{} has no method {:?}",
obj.borrow(),
method_name
))),
}
}