diff --git a/tests/snippets/strings.py b/tests/snippets/strings.py index b95e5edc0..68a9d2d68 100644 --- a/tests/snippets/strings.py +++ b/tests/snippets/strings.py @@ -8,3 +8,10 @@ assert "\n" == """ """ assert len(""" " \" """) == 5 + +assert type("") is str + +assert str(1) == "1" +assert str(2.1) == "2.1" +assert str() == "" +assert str("abc") == "abc" diff --git a/vm/src/builtins.rs b/vm/src/builtins.rs index fbeb3d98b..de52e4243 100644 --- a/vm/src/builtins.rs +++ b/vm/src/builtins.rs @@ -307,25 +307,6 @@ fn builtin_setattr(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { // builtin_sorted // builtin_staticmethod -// TODO: should with following format -// class str(object='') -// class str(object=b'', encoding='utf-8', errors='strict') -fn builtin_str(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { - if args.args.len() != 1 { - panic!("str expects exactly one parameter"); - }; - let s = match args.args[0].borrow().kind { - PyObjectKind::Integer { value: _ } | PyObjectKind::String { value: _ } => { - args.args[0].borrow().str() - } - _ => { - return Err(vm - .context() - .new_str("TypeError: object of this type cannot be converted to str".to_string())) - } - }; - Ok(vm.new_str(s)) -} // builtin_sum // builtin_super // builtin_vars diff --git a/vm/src/objstr.rs b/vm/src/objstr.rs index c4d0092b1..4bebfed12 100644 --- a/vm/src/objstr.rs +++ b/vm/src/objstr.rs @@ -1,7 +1,29 @@ use super::objsequence::PySliceableSequence; -use super::pyobject::{PyObjectKind, PyObjectRef, PyResult}; +use super::pyobject::{ + AttributeProtocol, PyContext, PyFuncArgs, PyObjectKind, PyObjectRef, PyResult, +}; use super::vm::VirtualMachine; +pub fn init(context: &PyContext) { + let ref str_type = context.str_type; + str_type.set_attr("__new__", context.new_rustfunc(str_new)); +} + +// TODO: should with following format +// class str(object='') +// class str(object=b'', encoding='utf-8', errors='strict') +fn str_new(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { + if args.args.len() == 1 { + return Ok(vm.new_str("".to_string())); + } + + if args.args.len() > 2 { + panic!("str expects exactly one parameter"); + }; + let s = args.args[1].borrow().str(); + Ok(vm.new_str(s)) +} + impl PySliceableSequence for String { fn do_slice(&self, start: usize, stop: usize) -> Self { self[start..stop].to_string() diff --git a/vm/src/pyobject.rs b/vm/src/pyobject.rs index 2fe351f11..62315d02a 100644 --- a/vm/src/pyobject.rs +++ b/vm/src/pyobject.rs @@ -5,6 +5,7 @@ use super::objfunction; use super::objint; use super::objlist; use super::objobject; +use super::objstr; use super::objtype; use super::vm::VirtualMachine; use std::cell::RefCell; @@ -139,6 +140,7 @@ impl PyContext { objdict::init(&context); objfunction::init(&context); objint::init(&context); + objstr::init(&context); exceptions::init(&context); // TODO: create exception hierarchy here? // exceptions::create_zoo(&context); @@ -154,7 +156,7 @@ impl PyContext { } pub fn new_str(&self, s: String) -> PyObjectRef { - PyObject::new(PyObjectKind::String { value: s }, self.type_type.clone()) + PyObject::new(PyObjectKind::String { value: s }, self.str_type.clone()) } pub fn new_bool(&self, b: bool) -> PyObjectRef {