forked from Rust-related/RustPython
Compare commits
4 Commits
0.3.1
...
function_a
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1d1a931011 | ||
|
|
2d78425bab | ||
|
|
43118db1b0 | ||
|
|
647cb08d78 |
@@ -16,6 +16,9 @@ assert bool() == False
|
||||
assert bool(1) == True
|
||||
assert bool({}) == False
|
||||
|
||||
assert bool(NotImplemented) == True
|
||||
assert bool(...) == True
|
||||
|
||||
if not 1:
|
||||
raise BaseException
|
||||
|
||||
|
||||
@@ -285,10 +285,14 @@ impl Frame {
|
||||
|
||||
let mut out: Vec<Option<BigInt>> = elements
|
||||
.into_iter()
|
||||
.map(|x| match x.payload {
|
||||
PyObjectPayload::Integer { ref value } => Some(value.clone()),
|
||||
PyObjectPayload::None => None,
|
||||
_ => panic!("Expect Int or None as BUILD_SLICE arguments, got {:?}", x),
|
||||
.map(|x| {
|
||||
if x.is(&vm.get_none()) {
|
||||
None
|
||||
} else if let PyObjectPayload::Integer { ref value } = x.payload {
|
||||
Some(value.clone())
|
||||
} else {
|
||||
panic!("Expect Int or None as BUILD_SLICE arguments, got {:?}", x);
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
|
||||
@@ -574,9 +578,7 @@ impl Frame {
|
||||
}
|
||||
bytecode::Instruction::PrintExpr => {
|
||||
let expr = self.pop_value();
|
||||
match expr.payload {
|
||||
PyObjectPayload::None => (),
|
||||
_ => {
|
||||
if !expr.is(&vm.get_none()) {
|
||||
let repr = vm.to_repr(&expr)?;
|
||||
builtins::builtin_print(
|
||||
vm,
|
||||
@@ -586,7 +588,6 @@ impl Frame {
|
||||
},
|
||||
)?;
|
||||
}
|
||||
}
|
||||
Ok(None)
|
||||
}
|
||||
bytecode::Instruction::LoadBuildClass => {
|
||||
|
||||
@@ -13,7 +13,7 @@ impl IntoPyObject for bool {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn boolval(vm: &mut VirtualMachine, obj: PyObjectRef) -> Result<bool, PyObjectRef> {
|
||||
pub fn boolval(vm: &mut VirtualMachine, obj: PyObjectRef) -> PyResult<bool> {
|
||||
if let Some(s) = obj.payload::<PyString>() {
|
||||
return Ok(!s.value.is_empty());
|
||||
}
|
||||
@@ -24,7 +24,6 @@ pub fn boolval(vm: &mut VirtualMachine, obj: PyObjectRef) -> Result<bool, PyObje
|
||||
PyObjectPayload::Integer { ref value } => !value.is_zero(),
|
||||
PyObjectPayload::Sequence { ref elements } => !elements.borrow().is_empty(),
|
||||
PyObjectPayload::Dict { ref elements } => !elements.borrow().is_empty(),
|
||||
PyObjectPayload::None { .. } => false,
|
||||
_ => {
|
||||
if let Ok(f) = vm.get_method(obj.clone(), "__bool__") {
|
||||
let bool_res = vm.invoke(f, PyFuncArgs::default())?;
|
||||
|
||||
@@ -311,9 +311,9 @@ pub fn create_type(type_type: PyObjectRef, object_type: PyObjectRef, dict_type:
|
||||
unsafe {
|
||||
(*ptr).payload = PyObjectPayload::Class {
|
||||
name: String::from("dict"),
|
||||
dict: RefCell::new(HashMap::new()),
|
||||
mro: vec![object_type],
|
||||
};
|
||||
(*ptr).dict = Some(RefCell::new(HashMap::new()));
|
||||
(*ptr).typ = Some(type_type.clone());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ pub fn init(context: &PyContext) {
|
||||
let none_type = &context.none.typ();
|
||||
context.set_attr(&none_type, "__new__", context.new_rustfunc(none_new));
|
||||
context.set_attr(&none_type, "__repr__", context.new_rustfunc(none_repr));
|
||||
context.set_attr(&none_type, "__bool__", context.new_rustfunc(none_bool));
|
||||
}
|
||||
|
||||
fn none_new(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
@@ -20,3 +21,8 @@ fn none_repr(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
arg_check!(vm, args, required = [(_zelf, Some(vm.ctx.none().typ()))]);
|
||||
Ok(vm.ctx.new_str("None".to_string()))
|
||||
}
|
||||
|
||||
fn none_bool(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
arg_check!(vm, args, required = [(_zelf, Some(vm.ctx.none().typ()))]);
|
||||
Ok(vm.ctx.new_bool(false))
|
||||
}
|
||||
|
||||
@@ -21,9 +21,9 @@ pub fn create_object(type_type: PyObjectRef, object_type: PyObjectRef, _dict_typ
|
||||
unsafe {
|
||||
(*ptr).payload = PyObjectPayload::Class {
|
||||
name: String::from("object"),
|
||||
dict: RefCell::new(HashMap::new()),
|
||||
mro: vec![],
|
||||
};
|
||||
(*ptr).dict = Some(RefCell::new(HashMap::new()));
|
||||
(*ptr).typ = Some(type_type.clone());
|
||||
}
|
||||
}
|
||||
@@ -105,13 +105,13 @@ fn object_delattr(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
]
|
||||
);
|
||||
|
||||
match zelf.payload {
|
||||
PyObjectPayload::Class { ref dict, .. } | PyObjectPayload::Instance { ref dict, .. } => {
|
||||
match zelf.dict {
|
||||
Some(ref dict) => {
|
||||
let attr_name = objstr::get_value(attr);
|
||||
dict.borrow_mut().remove(&attr_name);
|
||||
Ok(vm.get_none())
|
||||
}
|
||||
_ => Err(vm.new_type_error("TypeError: no dictionary.".to_string())),
|
||||
None => Err(vm.new_type_error("TypeError: no dictionary.".to_string())),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -178,15 +178,14 @@ fn object_init(vm: &mut VirtualMachine, _args: PyFuncArgs) -> PyResult {
|
||||
}
|
||||
|
||||
fn object_dict(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
match args.args[0].payload {
|
||||
PyObjectPayload::Class { ref dict, .. } | PyObjectPayload::Instance { ref dict, .. } => {
|
||||
if let Some(ref dict) = args.args[0].dict {
|
||||
let new_dict = vm.new_dict();
|
||||
for (attr, value) in dict.borrow().iter() {
|
||||
new_dict.set_item(&vm.ctx, &attr, value.clone());
|
||||
}
|
||||
Ok(new_dict)
|
||||
}
|
||||
_ => Err(vm.new_type_error("TypeError: no dictionary.".to_string())),
|
||||
} else {
|
||||
Err(vm.new_type_error("TypeError: no dictionary.".to_string()))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -19,9 +19,9 @@ pub fn create_type(type_type: PyObjectRef, object_type: PyObjectRef, _dict_type:
|
||||
unsafe {
|
||||
(*ptr).payload = PyObjectPayload::Class {
|
||||
name: String::from("type"),
|
||||
dict: RefCell::new(PyAttributes::new()),
|
||||
mro: vec![object_type],
|
||||
};
|
||||
(*ptr).dict = Some(RefCell::new(PyAttributes::new()));
|
||||
(*ptr).typ = Some(type_type);
|
||||
}
|
||||
}
|
||||
@@ -264,26 +264,26 @@ pub fn get_attributes(obj: &PyObjectRef) -> PyAttributes {
|
||||
let mut base_classes = objtype::base_classes(obj);
|
||||
base_classes.reverse();
|
||||
for bc in base_classes {
|
||||
if let PyObjectPayload::Class { dict, .. } = &bc.payload {
|
||||
if let Some(ref dict) = &bc.dict {
|
||||
for (name, value) in dict.borrow().iter() {
|
||||
attributes.insert(name.to_string(), value.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Get instance attributes:
|
||||
if let PyObjectPayload::Instance { dict } = &obj.payload {
|
||||
for (name, value) in dict.borrow().iter() {
|
||||
attributes.insert(name.to_string(), value.clone());
|
||||
}
|
||||
}
|
||||
|
||||
// Get module attributes:
|
||||
if let PyObjectPayload::Module { ref scope, .. } = &obj.payload {
|
||||
for (name, value) in scope.locals.get_key_value_pairs().iter() {
|
||||
attributes.insert(objstr::get_value(name).to_string(), value.clone());
|
||||
}
|
||||
} else {
|
||||
if let Some(ref dict) = &obj.dict {
|
||||
for (name, value) in dict.borrow().iter() {
|
||||
attributes.insert(name.to_string(), value.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
attributes
|
||||
}
|
||||
|
||||
@@ -342,14 +342,15 @@ pub fn new(
|
||||
) -> PyResult {
|
||||
let mros = bases.into_iter().map(|x| _mro(x).unwrap()).collect();
|
||||
let mro = linearise_mro(mros).unwrap();
|
||||
Ok(PyObject::new(
|
||||
PyObjectPayload::Class {
|
||||
Ok(PyObject {
|
||||
payload: PyObjectPayload::Class {
|
||||
name: String::from(name),
|
||||
dict: RefCell::new(dict),
|
||||
mro,
|
||||
},
|
||||
typ,
|
||||
))
|
||||
dict: Some(RefCell::new(dict)),
|
||||
typ: Some(typ),
|
||||
}
|
||||
.into_ref())
|
||||
}
|
||||
|
||||
fn type_repr(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
|
||||
@@ -154,11 +154,8 @@ pub struct PyContext {
|
||||
}
|
||||
|
||||
fn _nothing() -> PyObjectRef {
|
||||
PyObject {
|
||||
payload: PyObjectPayload::None,
|
||||
typ: None,
|
||||
}
|
||||
.into_ref()
|
||||
let obj: PyObject = Default::default();
|
||||
obj.into_ref()
|
||||
}
|
||||
|
||||
pub fn create_type(
|
||||
@@ -223,14 +220,14 @@ impl PyContext {
|
||||
let exceptions = exceptions::ExceptionZoo::new(&type_type, &object_type, &dict_type);
|
||||
|
||||
let none = PyObject::new(
|
||||
PyObjectPayload::None,
|
||||
PyObjectPayload::NoPayload,
|
||||
create_type("NoneType", &type_type, &object_type, &dict_type),
|
||||
);
|
||||
|
||||
let ellipsis = PyObject::new(PyObjectPayload::None, ellipsis_type.clone());
|
||||
let ellipsis = PyObject::new(PyObjectPayload::NoPayload, ellipsis_type.clone());
|
||||
|
||||
let not_implemented = PyObject::new(
|
||||
PyObjectPayload::NotImplemented,
|
||||
PyObjectPayload::NoPayload,
|
||||
create_type("NotImplementedType", &type_type, &object_type, &dict_type),
|
||||
);
|
||||
|
||||
@@ -658,12 +655,12 @@ impl PyContext {
|
||||
} else {
|
||||
PyAttributes::new()
|
||||
};
|
||||
PyObject::new(
|
||||
PyObjectPayload::Instance {
|
||||
dict: RefCell::new(dict),
|
||||
},
|
||||
class,
|
||||
)
|
||||
PyObject {
|
||||
payload: PyObjectPayload::NoPayload,
|
||||
typ: Some(class),
|
||||
dict: Some(RefCell::new(dict)),
|
||||
}
|
||||
.into_ref()
|
||||
}
|
||||
|
||||
// Item set/get:
|
||||
@@ -685,14 +682,12 @@ impl PyContext {
|
||||
}
|
||||
|
||||
pub fn set_attr(&self, obj: &PyObjectRef, attr_name: &str, value: PyObjectRef) {
|
||||
match obj.payload {
|
||||
PyObjectPayload::Module { ref scope, .. } => {
|
||||
if let PyObjectPayload::Module { ref scope, .. } = obj.payload {
|
||||
scope.locals.set_item(self, attr_name, value)
|
||||
}
|
||||
PyObjectPayload::Instance { ref dict } | PyObjectPayload::Class { ref dict, .. } => {
|
||||
} else if let Some(ref dict) = obj.dict {
|
||||
dict.borrow_mut().insert(attr_name.to_string(), value);
|
||||
}
|
||||
ref payload => unimplemented!("set_attr unimplemented for: {:?}", payload),
|
||||
} else {
|
||||
unimplemented!("set_attr unimplemented for: {:?}", obj);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -727,10 +722,11 @@ impl Default for PyContext {
|
||||
/// This is an actual python object. It consists of a `typ` which is the
|
||||
/// python class, and carries some rust payload optionally. This rust
|
||||
/// payload can be a rust float or rust int in case of float and int objects.
|
||||
#[derive(Default)]
|
||||
pub struct PyObject {
|
||||
pub payload: PyObjectPayload,
|
||||
pub typ: Option<PyObjectRef>,
|
||||
// pub dict: HashMap<String, PyObjectRef>, // __dict__ member
|
||||
pub dict: Option<RefCell<PyAttributes>>, // __dict__ member
|
||||
}
|
||||
|
||||
pub trait IdProtocol {
|
||||
@@ -777,16 +773,18 @@ pub trait AttributeProtocol {
|
||||
}
|
||||
|
||||
fn class_get_item(class: &PyObjectRef, attr_name: &str) -> Option<PyObjectRef> {
|
||||
match class.payload {
|
||||
PyObjectPayload::Class { ref dict, .. } => dict.borrow().get(attr_name).cloned(),
|
||||
_ => panic!("Only classes should be in MRO!"),
|
||||
if let Some(ref dict) = class.dict {
|
||||
dict.borrow().get(attr_name).cloned()
|
||||
} else {
|
||||
panic!("Only classes should be in MRO!");
|
||||
}
|
||||
}
|
||||
|
||||
fn class_has_item(class: &PyObjectRef, attr_name: &str) -> bool {
|
||||
match class.payload {
|
||||
PyObjectPayload::Class { ref dict, .. } => dict.borrow().contains_key(attr_name),
|
||||
_ => panic!("Only classes should be in MRO!"),
|
||||
if let Some(ref dict) = class.dict {
|
||||
dict.borrow().contains_key(attr_name)
|
||||
} else {
|
||||
panic!("Only classes should be in MRO!");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -805,8 +803,13 @@ impl AttributeProtocol for PyObjectRef {
|
||||
}
|
||||
None
|
||||
}
|
||||
PyObjectPayload::Instance { ref dict } => dict.borrow().get(attr_name).cloned(),
|
||||
_ => None,
|
||||
_ => {
|
||||
if let Some(ref dict) = self.dict {
|
||||
dict.borrow().get(attr_name).cloned()
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -816,8 +819,13 @@ impl AttributeProtocol for PyObjectRef {
|
||||
PyObjectPayload::Class { ref mro, .. } => {
|
||||
class_has_item(self, attr_name) || mro.iter().any(|d| class_has_item(d, attr_name))
|
||||
}
|
||||
PyObjectPayload::Instance { ref dict } => dict.borrow().contains_key(attr_name),
|
||||
_ => false,
|
||||
_ => {
|
||||
if let Some(ref dict) = self.dict {
|
||||
dict.borrow().contains_key(attr_name)
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1484,11 +1492,9 @@ pub enum PyObjectPayload {
|
||||
name: String,
|
||||
scope: ScopeRef,
|
||||
},
|
||||
None,
|
||||
NotImplemented,
|
||||
NoPayload,
|
||||
Class {
|
||||
name: String,
|
||||
dict: RefCell<PyAttributes>,
|
||||
mro: Vec<PyObjectRef>,
|
||||
},
|
||||
Set {
|
||||
@@ -1497,9 +1503,6 @@ pub enum PyObjectPayload {
|
||||
WeakRef {
|
||||
referent: PyObjectWeakRef,
|
||||
},
|
||||
Instance {
|
||||
dict: RefCell<PyAttributes>,
|
||||
},
|
||||
RustFunction {
|
||||
function: PyNativeFunc,
|
||||
},
|
||||
@@ -1508,6 +1511,12 @@ pub enum PyObjectPayload {
|
||||
},
|
||||
}
|
||||
|
||||
impl Default for PyObjectPayload {
|
||||
fn default() -> Self {
|
||||
PyObjectPayload::NoPayload
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for PyObjectPayload {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self {
|
||||
@@ -1531,10 +1540,8 @@ impl fmt::Debug for PyObjectPayload {
|
||||
ref object,
|
||||
} => write!(f, "bound-method: {:?} of {:?}", function, object),
|
||||
PyObjectPayload::Module { .. } => write!(f, "module"),
|
||||
PyObjectPayload::None => write!(f, "None"),
|
||||
PyObjectPayload::NotImplemented => write!(f, "NotImplemented"),
|
||||
PyObjectPayload::NoPayload => write!(f, "NoPayload"),
|
||||
PyObjectPayload::Class { ref name, .. } => write!(f, "class {:?}", name),
|
||||
PyObjectPayload::Instance { .. } => write!(f, "instance"),
|
||||
PyObjectPayload::RustFunction { .. } => write!(f, "rust function"),
|
||||
PyObjectPayload::Frame { .. } => write!(f, "frame"),
|
||||
PyObjectPayload::AnyRustValue { .. } => write!(f, "some rust value"),
|
||||
@@ -1543,14 +1550,11 @@ impl fmt::Debug for PyObjectPayload {
|
||||
}
|
||||
|
||||
impl PyObject {
|
||||
pub fn new(
|
||||
payload: PyObjectPayload,
|
||||
/* dict: PyObjectRef,*/ typ: PyObjectRef,
|
||||
) -> PyObjectRef {
|
||||
pub fn new(payload: PyObjectPayload, typ: PyObjectRef) -> PyObjectRef {
|
||||
PyObject {
|
||||
payload,
|
||||
typ: Some(typ),
|
||||
// dict: HashMap::new(), // dict,
|
||||
dict: None,
|
||||
}
|
||||
.into_ref()
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ use crate::obj::{
|
||||
objtype,
|
||||
};
|
||||
use crate::pyobject::{
|
||||
create_type, DictProtocol, PyContext, PyFuncArgs, PyObjectPayload, PyObjectRef, PyResult,
|
||||
create_type, DictProtocol, IdProtocol, PyContext, PyFuncArgs, PyObjectRef, PyResult,
|
||||
TypeProtocol,
|
||||
};
|
||||
use crate::VirtualMachine;
|
||||
@@ -69,7 +69,7 @@ impl<'s> serde::Serialize for PyObjectSerializer<'s> {
|
||||
map.serialize_entry(&key, &self.clone_with_object(&e.1))?;
|
||||
}
|
||||
map.end()
|
||||
} else if let PyObjectPayload::None = self.pyobject.payload {
|
||||
} else if self.pyobject.is(&self.vm.get_none()) {
|
||||
serializer.serialize_none()
|
||||
} else {
|
||||
Err(serde::ser::Error::custom(format!(
|
||||
|
||||
13
vm/src/vm.rs
13
vm/src/vm.rs
@@ -330,9 +330,6 @@ impl VirtualMachine {
|
||||
ref function,
|
||||
ref object,
|
||||
} => self.invoke(function.clone(), args.insert(object.clone())),
|
||||
PyObjectPayload::Instance { .. } => {
|
||||
self.call_method_pyargs(&func_ref, "__call__", args)
|
||||
}
|
||||
ref payload => {
|
||||
// TODO: is it safe to just invoke __call__ otherwise?
|
||||
trace!("invoke __call__ for: {:?}", payload);
|
||||
@@ -473,10 +470,12 @@ impl VirtualMachine {
|
||||
// Add missing positional arguments, if we have fewer positional arguments than the
|
||||
// function definition calls for
|
||||
if nargs < nexpected_args {
|
||||
let available_defaults = match defaults.payload {
|
||||
PyObjectPayload::Sequence { ref elements } => elements.borrow().clone(),
|
||||
PyObjectPayload::None => vec![],
|
||||
_ => panic!("function defaults not tuple or None"),
|
||||
let available_defaults = if defaults.is(&self.get_none()) {
|
||||
vec![]
|
||||
} else if let PyObjectPayload::Sequence { ref elements } = defaults.payload {
|
||||
elements.borrow().clone()
|
||||
} else {
|
||||
panic!("function defaults not tuple or None");
|
||||
};
|
||||
|
||||
// Given the number of defaults available, check all the arguments for which we
|
||||
|
||||
Reference in New Issue
Block a user