Merge branch 'master' into master

This commit is contained in:
Benedykt Jaworski
2019-02-06 10:24:59 +01:00
committed by GitHub
48 changed files with 612 additions and 376 deletions

1
Cargo.lock generated
View File

@@ -709,6 +709,7 @@ dependencies = [
"log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
"num-bigint 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"num-complex 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)",
"num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",

View File

@@ -44,6 +44,9 @@ assert int() == 0
a = complex(2, 4)
assert type(a) is complex
assert type(a + a) is complex
assert repr(a) == '(2+4j)'
a = 10j
assert repr(a) == '10j'
a = 1
assert a.conjugate() == a

View File

@@ -0,0 +1,32 @@
assert list(filter(lambda x: ((x % 2) == 0), [0, 1, 2])) == [0, 2]
# None implies identity
assert list(filter(None, [0, 1, 2])) == [1, 2]
assert type(filter(None, [])) == filter
# test infinite iterator
class Counter(object):
counter = 0
def __next__(self):
self.counter += 1
return self.counter
def __iter__(self):
return self
it = filter(lambda x: ((x % 2) == 0), Counter())
assert next(it) == 2
assert next(it) == 4
def predicate(x):
if x == 0:
raise StopIteration()
return True
assert list(filter(predicate, [1, 2, 0, 4, 5])) == [1, 2]

View File

@@ -0,0 +1,34 @@
a = list(map(str, [1, 2, 3]))
assert a == ['1', '2', '3']
b = list(map(lambda x, y: x + y, [1, 2, 4], [3, 5]))
assert b == [4, 7]
assert type(map(lambda x: x, [])) == map
# test infinite iterator
class Counter(object):
counter = 0
def __next__(self):
self.counter += 1
return self.counter
def __iter__(self):
return self
it = map(lambda x: x+1, Counter())
assert next(it) == 2
assert next(it) == 3
def mapping(x):
if x == 0:
raise StopIteration()
return x
assert list(map(mapping, [1, 2, 0, 4, 5])) == [1, 2]

View File

@@ -1,5 +1,36 @@
def assert_raises(expr, exc_type):
"""
Helper function to assert `expr` raises an exception of type `exc_type`
Args:
expr: Callable
exec_type: Exception
Returns:
None
Raises:
Assertion error on failure
"""
try:
expr(None)
except exc_type:
assert True
else:
assert False
assert range(2**63+1)[2**63] == 9223372036854775808
# len tests
assert len(range(10, 5)) == 0, 'Range with no elements should have length = 0'
assert len(range(10, 5, -2)) == 3, 'Expected length 3, for elements: 10, 8, 6'
assert len(range(5, 10, 2)) == 3, 'Expected length 3, for elements: 5, 7, 9'
# index tests
assert range(10).index(6) == 6
assert range(4, 10).index(6) == 2
assert range(4, 10, 2).index(6) == 1
# index raises value error on out of bounds
assert_raises(lambda _: range(10).index(-1), ValueError)
assert_raises(lambda _: range(10).index(10), ValueError)
# index raises value error if out of step
assert_raises(lambda _: range(4, 10, 2).index(5), ValueError)

View File

@@ -1,8 +1,4 @@
a = list(map(str, [1, 2, 3]))
assert a == ['1', '2', '3']
x = sum(map(int, a))
x = sum(map(int, ['1', '2', '3']))
assert x == 6
assert callable(type)
@@ -15,8 +11,6 @@ assert type(frozenset) is type
assert list(zip(['a', 'b', 'c'], range(3), [9, 8, 7, 99])) == [('a', 0, 9), ('b', 1, 8), ('c', 2, 7)]
assert list(filter(lambda x: ((x % 2) == 0), [0, 1, 2])) == [0, 2]
assert 3 == eval('1+2')
code = compile('5+3', 'x.py', 'eval')

View File

@@ -18,4 +18,12 @@ assert -a == -4
assert +a == 4
# import math
# print(math.cos(1.2))
# assert(math.exp(2) == math.exp(2.0))
# assert(math.exp(True) == math.exp(1.0))
#
# class Conversible():
# def __float__(self):
# print("Converting to float now!")
# return 1.1111
#
# assert math.log(1.1111) == math.log(Conversible())

View File

@@ -8,6 +8,7 @@ bitflags = "1.0.4"
num-complex = "0.2"
num-bigint = "0.2.1"
num-traits = "0.2"
num-integer = "0.1.39"
rand = "0.5"
log = "0.3"
rustpython_parser = {path = "../parser"}

View File

@@ -301,29 +301,6 @@ fn builtin_exec(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
vm.run_code_obj(code_obj, scope)
}
fn builtin_filter(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
arg_check!(vm, args, required = [(function, None), (iterable, None)]);
// TODO: process one element at a time from iterators.
let iterable = vm.extract_elements(iterable)?;
let mut new_items = vec![];
for element in iterable {
// apply function:
let args = PyFuncArgs {
args: vec![element.clone()],
kwargs: vec![],
};
let result = vm.invoke(function.clone(), args)?;
let result = objbool::boolval(vm, result)?;
if result {
new_items.push(element);
}
}
Ok(vm.ctx.new_list(new_items))
}
fn builtin_format(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
arg_check!(
vm,
@@ -428,33 +405,6 @@ fn builtin_locals(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
Ok(vm.get_locals())
}
fn builtin_map(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
arg_check!(vm, args, required = [(function, None), (iter_target, None)]);
let iterator = objiter::get_iter(vm, iter_target)?;
let mut elements = vec![];
loop {
match vm.call_method(&iterator, "__next__", vec![]) {
Ok(v) => {
// Now apply function:
let mapped_value = vm.invoke(
function.clone(),
PyFuncArgs {
args: vec![v],
kwargs: vec![],
},
)?;
elements.push(mapped_value);
}
Err(_) => break,
}
}
trace!("Mapped elements: {:?}", elements);
// TODO: when iterators are implemented, we can improve this function.
Ok(vm.ctx.new_list(elements))
}
fn builtin_max(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
let candidates = if args.args.len() > 1 {
args.args.clone()
@@ -465,7 +415,7 @@ fn builtin_max(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
return Err(vm.new_type_error("Expected 1 or more arguments".to_string()));
};
if candidates.len() == 0 {
if candidates.is_empty() {
let default = args.get_optional_kwarg("default");
if default.is_none() {
return Err(vm.new_value_error("max() arg is an empty sequence".to_string()));
@@ -516,7 +466,7 @@ fn builtin_min(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
return Err(vm.new_type_error("Expected 1 or more arguments".to_string()));
};
if candidates.len() == 0 {
if candidates.is_empty() {
let default = args.get_optional_kwarg("default");
if default.is_none() {
return Err(vm.new_value_error("min() arg is an empty sequence".to_string()));
@@ -749,7 +699,7 @@ pub fn make_module(ctx: &PyContext) -> PyObjectRef {
ctx.set_attr(&py_mod, "exec", ctx.new_rustfunc(builtin_exec));
ctx.set_attr(&py_mod, "float", ctx.float_type());
ctx.set_attr(&py_mod, "frozenset", ctx.frozenset_type());
ctx.set_attr(&py_mod, "filter", ctx.new_rustfunc(builtin_filter));
ctx.set_attr(&py_mod, "filter", ctx.filter_type());
ctx.set_attr(&py_mod, "format", ctx.new_rustfunc(builtin_format));
ctx.set_attr(&py_mod, "getattr", ctx.new_rustfunc(builtin_getattr));
ctx.set_attr(&py_mod, "hasattr", ctx.new_rustfunc(builtin_hasattr));
@@ -763,7 +713,7 @@ pub fn make_module(ctx: &PyContext) -> PyObjectRef {
ctx.set_attr(&py_mod, "len", ctx.new_rustfunc(builtin_len));
ctx.set_attr(&py_mod, "list", ctx.list_type());
ctx.set_attr(&py_mod, "locals", ctx.new_rustfunc(builtin_locals));
ctx.set_attr(&py_mod, "map", ctx.new_rustfunc(builtin_map));
ctx.set_attr(&py_mod, "map", ctx.map_type());
ctx.set_attr(&py_mod, "max", ctx.new_rustfunc(builtin_max));
ctx.set_attr(&py_mod, "memoryview", ctx.memoryview_type());
ctx.set_attr(&py_mod, "min", ctx.new_rustfunc(builtin_min));
@@ -829,6 +779,11 @@ pub fn make_module(ctx: &PyContext) -> PyObjectRef {
ctx.set_attr(&py_mod, "ValueError", ctx.exceptions.value_error.clone());
ctx.set_attr(&py_mod, "IndexError", ctx.exceptions.index_error.clone());
ctx.set_attr(&py_mod, "ImportError", ctx.exceptions.import_error.clone());
ctx.set_attr(
&py_mod,
"StopIteration",
ctx.exceptions.stop_iteration.clone(),
);
ctx.set_attr(
&py_mod,
"ZeroDivisionError",

View File

@@ -674,14 +674,14 @@ impl Compiler {
Ok(flags)
}
fn prepare_decorators(&mut self, decorator_list: &Vec<ast::Expression>) -> Result<(), String> {
fn prepare_decorators(&mut self, decorator_list: &[ast::Expression]) -> Result<(), String> {
for decorator in decorator_list {
self.compile_expression(decorator)?;
}
Ok(())
}
fn apply_decorators(&mut self, decorator_list: &Vec<ast::Expression>) {
fn apply_decorators(&mut self, decorator_list: &[ast::Expression]) {
// Apply decorators:
for _ in decorator_list {
self.emit(Instruction::CallFunction {
@@ -1036,8 +1036,8 @@ impl Compiler {
fn compile_call(
&mut self,
function: &ast::Expression,
args: &Vec<ast::Expression>,
keywords: &Vec<ast::Keyword>,
args: &[ast::Expression],
keywords: &[ast::Keyword],
) -> Result<(), String> {
self.compile_expression(function)?;
let count = args.len() + keywords.len();
@@ -1123,7 +1123,7 @@ impl Compiler {
// Given a vector of expr / star expr generate code which gives either
// a list of expressions on the stack, or a list of tuples.
fn gather_elements(&mut self, elements: &Vec<ast::Expression>) -> Result<bool, String> {
fn gather_elements(&mut self, elements: &[ast::Expression]) -> Result<bool, String> {
// First determine if we have starred elements:
let has_stars = elements.iter().any(|e| {
if let ast::Expression::Starred { .. } = e {
@@ -1153,10 +1153,10 @@ impl Compiler {
fn compile_comprehension(
&mut self,
kind: &ast::ComprehensionKind,
generators: &Vec<ast::Comprehension>,
generators: &[ast::Comprehension],
) -> Result<(), String> {
// We must have at least one generator:
assert!(generators.len() > 0);
assert!(!generators.is_empty());
let name = match kind {
ast::ComprehensionKind::GeneratorExpression { .. } => "<genexpr>",
@@ -1201,8 +1201,7 @@ impl Compiler {
let mut loop_labels = vec![];
for generator in generators {
let first = loop_labels.len() == 0;
if first {
if loop_labels.is_empty() {
// Load iterator onto stack (passed as first argument):
self.emit(Instruction::LoadName {
name: String::from(".0"),

View File

@@ -87,7 +87,7 @@ fn parse_align(text: &str) -> (Option<FormatAlign>, &str) {
fn parse_fill_and_align(text: &str) -> (Option<char>, Option<FormatAlign>, &str) {
let char_indices: Vec<(usize, char)> = text.char_indices().take(3).collect();
if char_indices.len() == 0 {
if char_indices.is_empty() {
(None, None, text)
} else if char_indices.len() == 1 {
let (maybe_align, remaining) = parse_align(text);
@@ -438,14 +438,14 @@ impl FormatString {
fn parse_literal(text: &str) -> Result<(FormatPart, &str), FormatParseError> {
let mut cur_text = text;
let mut result_string = String::new();
while cur_text.len() > 0 {
while !cur_text.is_empty() {
match FormatString::parse_literal_single(cur_text) {
Ok((next_char, remaining)) => {
result_string.push(next_char);
cur_text = remaining;
}
Err(err) => {
if result_string.len() > 0 {
if !result_string.is_empty() {
return Ok((FormatPart::Literal(result_string.to_string()), cur_text));
} else {
return Err(err);
@@ -467,7 +467,7 @@ impl FormatString {
String::new()
};
if arg_part.len() == 0 {
if arg_part.is_empty() {
return Ok(FormatPart::AutoSpec(format_spec));
}
@@ -500,7 +500,7 @@ impl FormatString {
pub fn from_str(text: &str) -> Result<FormatString, FormatParseError> {
let mut cur_text: &str = text;
let mut parts: Vec<FormatPart> = Vec::new();
while cur_text.len() > 0 {
while !cur_text.is_empty() {
// Try to parse both literals and bracketed format parts util we
// run out of text
cur_text = FormatString::parse_literal(cur_text)

View File

@@ -522,7 +522,7 @@ impl Frame {
bytecode::Instruction::Break => {
let block = self.unwind_loop(vm);
if let Block::Loop { start: _, end } = block {
if let Block::Loop { end, .. } = block {
self.jump(end);
}
Ok(None)
@@ -533,7 +533,7 @@ impl Frame {
}
bytecode::Instruction::Continue => {
let block = self.unwind_loop(vm);
if let Block::Loop { start, end: _ } = block {
if let Block::Loop { start, .. } = block {
self.jump(start);
} else {
assert!(false);
@@ -708,8 +708,7 @@ impl Frame {
// TODO: execute finally handler
}
Some(Block::With {
end: _,
context_manager,
context_manager, ..
}) => {
match self.with_exit(vm, &context_manager, None) {
Ok(..) => {}
@@ -728,13 +727,12 @@ impl Frame {
loop {
let block = self.pop_block();
match block {
Some(Block::Loop { start: _, end: __ }) => break block.unwrap(),
Some(Block::Loop { .. }) => break block.unwrap(),
Some(Block::TryExcept { .. }) => {
// TODO: execute finally handler
}
Some(Block::With {
end: _,
context_manager,
context_manager, ..
}) => match self.with_exit(vm, &context_manager, None) {
Ok(..) => {}
Err(exc) => {

View File

@@ -12,6 +12,7 @@ extern crate log;
// extern crate env_logger;
extern crate num_bigint;
extern crate num_complex;
extern crate num_integer;
extern crate num_traits;
extern crate serde;
extern crate serde_json;

View File

@@ -6,6 +6,7 @@ pub mod objbytes;
pub mod objcode;
pub mod objcomplex;
pub mod objdict;
pub mod objfilter;
pub mod objfloat;
pub mod objframe;
pub mod objfunction;
@@ -13,6 +14,7 @@ pub mod objgenerator;
pub mod objint;
pub mod objiter;
pub mod objlist;
pub mod objmap;
pub mod objmemory;
pub mod objobject;
pub mod objproperty;

View File

@@ -30,13 +30,13 @@ pub fn boolval(vm: &mut VirtualMachine, obj: PyObjectRef) -> Result<bool, PyObje
}
pub fn init(context: &PyContext) {
let ref bool_type = context.bool_type;
let bool_doc = "bool(x) -> bool
Returns True when the argument x is true, False otherwise.
The builtins True and False are the only two instances of the class bool.
The class bool is a subclass of the class int, and cannot be subclassed.";
let bool_type = &context.bool_type;
context.set_attr(&bool_type, "__new__", context.new_rustfunc(bool_new));
context.set_attr(&bool_type, "__repr__", context.new_rustfunc(bool_repr));
context.set_attr(&bool_type, "__doc__", context.new_str(bool_doc.to_string()));

View File

@@ -16,7 +16,7 @@ use num_traits::ToPrimitive;
/// Fill bytearray class methods dictionary.
pub fn init(context: &PyContext) {
let ref bytearray_type = context.bytearray_type;
let bytearray_type = &context.bytearray_type;
context.set_attr(
&bytearray_type,
"__eq__",

View File

@@ -14,12 +14,13 @@ use std::ops::Deref;
// Fill bytes class methods:
pub fn init(context: &PyContext) {
let ref bytes_type = context.bytes_type;
let bytes_type = &context.bytes_type;
context.set_attr(bytes_type, "__eq__", context.new_rustfunc(bytes_eq));
context.set_attr(bytes_type, "__hash__", context.new_rustfunc(bytes_hash));
context.set_attr(bytes_type, "__new__", context.new_rustfunc(bytes_new));
context.set_attr(bytes_type, "__repr__", context.new_rustfunc(bytes_repr));
context.set_attr(bytes_type, "__len__", context.new_rustfunc(bytes_len));
context.set_attr(bytes_type, "__iter__", context.new_rustfunc(bytes_iter))
}
fn bytes_new(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
@@ -101,3 +102,17 @@ fn bytes_repr(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
let data = String::from_utf8(value.to_vec()).unwrap();
Ok(vm.new_str(format!("b'{}'", data)))
}
fn bytes_iter(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
arg_check!(vm, args, required = [(obj, Some(vm.ctx.bytes_type()))]);
let iter_obj = PyObject::new(
PyObjectPayload::Iterator {
position: 0,
iterated_obj: obj.clone(),
},
vm.ctx.iter_type(),
);
Ok(iter_obj)
}

View File

@@ -10,7 +10,7 @@ use super::super::vm::VirtualMachine;
use super::objtype;
pub fn init(context: &PyContext) {
let ref code_type = context.code_type;
let code_type = &context.code_type;
context.set_attr(code_type, "__new__", context.new_rustfunc(code_new));
context.set_attr(code_type, "__repr__", context.new_rustfunc(code_repr));
}

View File

@@ -7,7 +7,7 @@ use super::objtype;
use num_complex::Complex64;
pub fn init(context: &PyContext) {
let ref complex_type = context.complex_type;
let complex_type = &context.complex_type;
context.set_attr(&complex_type, "__add__", context.new_rustfunc(complex_add));
context.set_attr(&complex_type, "__new__", context.new_rustfunc(complex_new));
context.set_attr(
@@ -85,5 +85,10 @@ fn complex_conjugate(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
fn complex_repr(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
arg_check!(vm, args, required = [(obj, Some(vm.ctx.complex_type()))]);
let v = get_value(obj);
Ok(vm.new_str(v.to_string()))
let repr = if v.re == 0. {
format!("{}j", v.im)
} else {
format!("({}+{}j)", v.re, v.im)
};
Ok(vm.new_str(repr))
}

View File

@@ -284,7 +284,7 @@ pub fn create_type(type_type: PyObjectRef, object_type: PyObjectRef, dict_type:
}
pub fn init(context: &PyContext) {
let ref dict_type = context.dict_type;
let dict_type = &context.dict_type;
context.set_attr(&dict_type, "__len__", context.new_rustfunc(dict_len));
context.set_attr(
&dict_type,

83
vm/src/obj/objfilter.rs Normal file
View File

@@ -0,0 +1,83 @@
use super::super::pyobject::{
IdProtocol, PyContext, PyFuncArgs, PyObject, PyObjectPayload, PyObjectRef, PyResult,
TypeProtocol,
};
use super::super::vm::VirtualMachine;
use super::objbool;
use super::objiter;
use super::objtype; // Required for arg_check! to use isinstance
pub fn filter_new(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
arg_check!(
vm,
args,
required = [(cls, None), (function, None), (iterable, None)]
);
let iterator = objiter::get_iter(vm, iterable)?;
Ok(PyObject::new(
PyObjectPayload::FilterIterator {
predicate: function.clone(),
iterator,
},
cls.clone(),
))
}
fn filter_iter(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
arg_check!(vm, args, required = [(filter, Some(vm.ctx.filter_type()))]);
// Return self:
Ok(filter.clone())
}
fn filter_contains(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
arg_check!(
vm,
args,
required = [(filter, Some(vm.ctx.filter_type())), (needle, None)]
);
objiter::contains(vm, filter, needle)
}
fn filter_next(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
arg_check!(vm, args, required = [(filter, Some(vm.ctx.filter_type()))]);
if let PyObjectPayload::FilterIterator {
ref mut predicate,
ref mut iterator,
} = filter.borrow_mut().payload
{
loop {
let next_obj = objiter::call_next(vm, iterator)?;
let predicate_value = if predicate.is(&vm.get_none()) {
next_obj.clone()
} else {
// the predicate itself can raise StopIteration which does stop the filter
// iteration
vm.invoke(
predicate.clone(),
PyFuncArgs {
args: vec![next_obj.clone()],
kwargs: vec![],
},
)?
};
if objbool::boolval(vm, predicate_value)? {
return Ok(next_obj);
}
}
} else {
panic!("filter doesn't have correct payload");
}
}
pub fn init(context: &PyContext) {
let filter_type = &context.filter_type;
context.set_attr(
&filter_type,
"__contains__",
context.new_rustfunc(filter_contains),
);
context.set_attr(&filter_type, "__iter__", context.new_rustfunc(filter_iter));
context.set_attr(&filter_type, "__new__", context.new_rustfunc(filter_new));
context.set_attr(&filter_type, "__next__", context.new_rustfunc(filter_next));
}

View File

@@ -267,7 +267,7 @@ fn float_pow(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
}
pub fn init(context: &PyContext) {
let ref float_type = context.float_type;
let float_type = &context.float_type;
context.set_attr(&float_type, "__eq__", context.new_rustfunc(float_eq));
context.set_attr(&float_type, "__lt__", context.new_rustfunc(float_lt));
context.set_attr(&float_type, "__le__", context.new_rustfunc(float_le));

View File

@@ -10,7 +10,7 @@ use super::super::vm::VirtualMachine;
use super::objtype;
pub fn init(context: &PyContext) {
let ref frame_type = context.frame_type;
let frame_type = &context.frame_type;
context.set_attr(&frame_type, "__new__", context.new_rustfunc(frame_new));
context.set_attr(&frame_type, "__repr__", context.new_rustfunc(frame_repr));
context.set_attr(&frame_type, "f_locals", context.new_property(frame_flocals));

View File

@@ -6,17 +6,17 @@ use super::super::vm::VirtualMachine;
use super::objtype;
pub fn init(context: &PyContext) {
let ref function_type = context.function_type;
let function_type = &context.function_type;
context.set_attr(&function_type, "__get__", context.new_rustfunc(bind_method));
let ref member_descriptor_type = context.member_descriptor_type;
let member_descriptor_type = &context.member_descriptor_type;
context.set_attr(
&member_descriptor_type,
"__get__",
context.new_rustfunc(member_get),
);
let ref classmethod_type = context.classmethod_type;
let classmethod_type = &context.classmethod_type;
context.set_attr(
&classmethod_type,
"__get__",
@@ -28,7 +28,7 @@ pub fn init(context: &PyContext) {
context.new_rustfunc(classmethod_new),
);
let ref staticmethod_type = context.staticmethod_type;
let staticmethod_type = &context.staticmethod_type;
context.set_attr(
staticmethod_type,
"__get__",

View File

@@ -10,7 +10,7 @@ use super::super::vm::VirtualMachine;
use super::objtype;
pub fn init(context: &PyContext) {
let ref generator_type = context.generator_type;
let generator_type = &context.generator_type;
context.set_attr(
&generator_type,
"__iter__",

View File

@@ -205,9 +205,7 @@ fn int_lshift(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
// i2 failed `to_usize()` conversion
match get_value(i2) {
ref v if *v < BigInt::zero() => {
return Err(vm.new_value_error("negative shift count".to_string()));
}
ref v if *v < BigInt::zero() => Err(vm.new_value_error("negative shift count".to_string())),
ref v if *v > BigInt::from(usize::max_value()) => {
// TODO: raise OverflowError
panic!("Failed converting {} to rust usize", get_value(i2));
@@ -237,9 +235,7 @@ fn int_rshift(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
// i2 failed `to_usize()` conversion
match get_value(i2) {
ref v if *v < BigInt::zero() => {
return Err(vm.new_value_error("negative shift count".to_string()));
}
ref v if *v < BigInt::zero() => Err(vm.new_value_error("negative shift count".to_string())),
ref v if *v > BigInt::from(usize::max_value()) => {
// TODO: raise OverflowError
panic!("Failed converting {} to rust usize", get_value(i2));
@@ -524,7 +520,6 @@ fn int_conjugate(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
}
pub fn init(context: &PyContext) {
let ref int_type = context.int_type;
let int_doc = "int(x=0) -> integer
int(x, base=10) -> integer
@@ -539,6 +534,8 @@ by whitespace. The base defaults to 10. Valid bases are 0 and 2-36.
Base 0 means to interpret the base from the string as an integer literal.
>>> int('0b100', base=0)
4";
let int_type = &context.int_type;
context.set_attr(&int_type, "__eq__", context.new_rustfunc(int_eq));
context.set_attr(&int_type, "__lt__", context.new_rustfunc(int_lt));
context.set_attr(&int_type, "__le__", context.new_rustfunc(int_le));

View File

@@ -23,6 +23,10 @@ pub fn get_iter(vm: &mut VirtualMachine, iter_target: &PyObjectRef) -> PyResult
// return Err(type_error);
}
pub fn call_next(vm: &mut VirtualMachine, iter_obj: &PyObjectRef) -> PyResult {
vm.call_method(iter_obj, "__next__", vec![])
}
/*
* Helper function to retrieve the next object (or none) from an iterator.
*/
@@ -30,7 +34,7 @@ pub fn get_next_object(
vm: &mut VirtualMachine,
iter_obj: &PyObjectRef,
) -> Result<Option<PyObjectRef>, PyObjectRef> {
let next_obj: PyResult = vm.call_method(iter_obj, "__next__", vec![]);
let next_obj: PyResult = call_next(vm, iter_obj);
match next_obj {
Ok(value) => Ok(Some(value)),
@@ -61,6 +65,21 @@ pub fn get_all(
Ok(elements)
}
pub fn contains(vm: &mut VirtualMachine, iter: &PyObjectRef, needle: &PyObjectRef) -> PyResult {
loop {
if let Some(element) = get_next_object(vm, iter)? {
let equal = vm.call_method(needle, "__eq__", vec![element.clone()])?;
if objbool::get_value(&equal) {
return Ok(vm.new_bool(true));
} else {
continue;
}
} else {
return Ok(vm.new_bool(false));
}
}
}
// Sequence iterator:
fn iter_new(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
arg_check!(vm, args, required = [(iter_target, None)]);
@@ -80,21 +99,7 @@ fn iter_contains(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
args,
required = [(iter, Some(vm.ctx.iter_type())), (needle, None)]
);
loop {
match vm.call_method(&iter, "__next__", vec![]) {
Ok(element) => match vm.call_method(needle, "__eq__", vec![element.clone()]) {
Ok(value) => {
if objbool::get_value(&value) {
return Ok(vm.new_bool(true));
} else {
continue;
}
}
Err(_) => return Err(vm.new_type_error("".to_string())),
},
Err(_) => return Ok(vm.new_bool(false)),
}
}
contains(vm, iter, needle)
}
fn iter_next(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
@@ -131,6 +136,20 @@ fn iter_next(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
Err(stop_iteration)
}
}
PyObjectPayload::Bytes { ref value } => {
if *position < value.len() {
let obj_ref = vm.ctx.new_int(value[*position].to_bigint().unwrap());
*position += 1;
Ok(obj_ref)
} else {
let stop_iteration_type = vm.ctx.exceptions.stop_iteration.clone();
let stop_iteration =
vm.new_exception(stop_iteration_type, "End of iterator".to_string());
Err(stop_iteration)
}
}
_ => {
panic!("NOT IMPL");
}
@@ -141,7 +160,7 @@ fn iter_next(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
}
pub fn init(context: &PyContext) {
let ref iter_type = context.iter_type;
let iter_type = &context.iter_type;
context.set_attr(
&iter_type,
"__contains__",

View File

@@ -365,7 +365,7 @@ fn list_pop(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
}
pub fn init(context: &PyContext) {
let ref list_type = context.list_type;
let list_type = &context.list_type;
context.set_attr(&list_type, "__add__", context.new_rustfunc(list_add));
context.set_attr(
&list_type,

81
vm/src/obj/objmap.rs Normal file
View File

@@ -0,0 +1,81 @@
use super::super::pyobject::{
PyContext, PyFuncArgs, PyObject, PyObjectPayload, PyObjectRef, PyResult, TypeProtocol,
};
use super::super::vm::VirtualMachine;
use super::objiter;
use super::objtype; // Required for arg_check! to use isinstance
pub fn map_new(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
no_kwargs!(vm, args);
let cls = &args.args[0];
if args.args.len() < 3 {
Err(vm.new_type_error("map() must have at least two arguments.".to_owned()))
} else {
let function = &args.args[1];
let iterables = &args.args[2..];
let iterators = iterables
.into_iter()
.map(|iterable| objiter::get_iter(vm, iterable))
.collect::<Result<Vec<_>, _>>()?;
Ok(PyObject::new(
PyObjectPayload::MapIterator {
mapper: function.clone(),
iterators,
},
cls.clone(),
))
}
}
fn map_iter(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
arg_check!(vm, args, required = [(map, Some(vm.ctx.map_type()))]);
// Return self:
Ok(map.clone())
}
fn map_contains(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
arg_check!(
vm,
args,
required = [(map, Some(vm.ctx.map_type())), (needle, None)]
);
objiter::contains(vm, map, needle)
}
fn map_next(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
arg_check!(vm, args, required = [(map, Some(vm.ctx.map_type()))]);
if let PyObjectPayload::MapIterator {
ref mut mapper,
ref mut iterators,
} = map.borrow_mut().payload
{
let next_objs = iterators
.iter()
.map(|iterator| objiter::call_next(vm, iterator))
.collect::<Result<Vec<_>, _>>()?;
// the mapper itself can raise StopIteration which does stop the map iteration
vm.invoke(
mapper.clone(),
PyFuncArgs {
args: next_objs,
kwargs: vec![],
},
)
} else {
panic!("map doesn't have correct payload");
}
}
pub fn init(context: &PyContext) {
let map_type = &context.map_type;
context.set_attr(
&map_type,
"__contains__",
context.new_rustfunc(map_contains),
);
context.set_attr(&map_type, "__iter__", context.new_rustfunc(map_iter));
context.set_attr(&map_type, "__new__", context.new_rustfunc(map_new));
context.set_attr(&map_type, "__next__", context.new_rustfunc(map_next));
}

View File

@@ -17,7 +17,7 @@ pub fn new_memory_view(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
}
pub fn init(ctx: &PyContext) {
let ref memoryview_type = ctx.memoryview_type;
let memoryview_type = &ctx.memoryview_type;
ctx.set_attr(
&memoryview_type,
"__new__",

View File

@@ -86,7 +86,9 @@ fn object_repr(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
}
pub fn init(context: &PyContext) {
let ref object = context.object;
let object = &context.object;
let object_doc = "The most base type";
context.set_attr(&object, "__new__", context.new_rustfunc(new_instance));
context.set_attr(&object, "__init__", context.new_rustfunc(object_init));
context.set_attr(&object, "__eq__", context.new_rustfunc(object_eq));
@@ -105,6 +107,7 @@ pub fn init(context: &PyContext) {
"__getattribute__",
context.new_rustfunc(object_getattribute),
);
context.set_attr(&object, "__doc__", context.new_str(object_doc.to_string()));
}
fn object_init(vm: &mut VirtualMachine, _args: PyFuncArgs) -> PyResult {
@@ -151,21 +154,19 @@ fn object_getattribute(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
Ok(obj_attr)
} else if let Some(attr) = cls.get_attr(&name) {
vm.call_get_descriptor(attr, obj.clone())
} else if let Some(getter) = cls.get_attr("__getattr__") {
vm.invoke(
getter,
PyFuncArgs {
args: vec![cls, name_str.clone()],
kwargs: vec![],
},
)
} else {
if let Some(getter) = cls.get_attr("__getattr__") {
vm.invoke(
getter,
PyFuncArgs {
args: vec![cls, name_str.clone()],
kwargs: vec![],
},
)
} else {
let attribute_error = vm.context().exceptions.attribute_error.clone();
Err(vm.new_exception(
attribute_error,
format!("{} has no attribute '{}'", obj.borrow(), name),
))
}
let attribute_error = vm.context().exceptions.attribute_error.clone();
Err(vm.new_exception(
attribute_error,
format!("{} has no attribute '{}'", obj.borrow(), name),
))
}
}

View File

@@ -9,7 +9,7 @@ use super::super::vm::VirtualMachine;
use super::objtype;
pub fn init(context: &PyContext) {
let ref property_type = context.property_type;
let property_type = &context.property_type;
context.set_attr(
&property_type,
"__get__",

View File

@@ -5,6 +5,7 @@ use super::super::vm::VirtualMachine;
use super::objint;
use super::objtype;
use num_bigint::{BigInt, Sign, ToBigInt};
use num_integer::Integer;
use num_traits::{One, Signed, ToPrimitive, Zero};
#[derive(Debug, Clone)]
@@ -37,6 +38,20 @@ impl RangeType {
self.try_len().unwrap()
}
#[inline]
pub fn index_of(&self, value: &BigInt) -> Option<BigInt> {
if value < &self.start || value >= &self.end {
return None;
}
let offset = value - &self.start;
if offset.is_multiple_of(&self.step) {
Some(offset / &self.step)
} else {
None
}
}
#[inline]
pub fn is_empty(&self) -> bool {
(self.start <= self.end && self.step.is_negative())
@@ -82,6 +97,7 @@ pub fn init(context: &PyContext) {
context.new_rustfunc(range_getitem),
);
context.set_attr(&range_type, "__repr__", context.new_rustfunc(range_repr));
context.set_attr(&range_type, "index", context.new_rustfunc(range_index));
}
fn range_new(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
@@ -228,3 +244,23 @@ fn range_repr(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
Ok(vm.ctx.new_str(s))
}
fn range_index(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
arg_check!(
vm,
args,
required = [(zelf, Some(vm.ctx.range_type())), (needle, None)]
);
if let PyObjectPayload::Range { ref range } = zelf.borrow().payload {
match needle.borrow().payload {
PyObjectPayload::Integer { ref value } => match range.index_of(value) {
Some(idx) => Ok(vm.ctx.new_int(idx)),
None => Err(vm.new_value_error(format!("{} is not in range", value))),
},
_ => Err(vm.new_value_error("sequence.index(x): x not in sequence".to_string())),
}
} else {
unreachable!()
}
}

View File

@@ -90,13 +90,10 @@ pub fn get_item(
Err(vm.new_index_error("cannot fit 'int' into an index-sized integer".to_string()))
}
},
PyObjectPayload::Slice {
start: _,
stop: _,
step: _,
} => Ok(PyObject::new(
PyObjectPayload::Slice { .. } => Ok(PyObject::new(
match &(sequence.borrow()).payload {
PyObjectPayload::Sequence { elements: _ } => PyObjectPayload::Sequence {
PyObjectPayload::Sequence { .. } => PyObjectPayload::Sequence {
elements: elements.to_vec().get_slice_items(&subscript),
},
ref payload => panic!("sequence get_item called for non-sequence: {:?}", payload),
@@ -112,8 +109,8 @@ pub fn get_item(
pub fn seq_equal(
vm: &mut VirtualMachine,
zelf: &Vec<PyObjectRef>,
other: &Vec<PyObjectRef>,
zelf: &[PyObjectRef],
other: &[PyObjectRef],
) -> Result<bool, PyObjectRef> {
if zelf.len() == other.len() {
for (a, b) in Iterator::zip(zelf.iter(), other.iter()) {
@@ -131,8 +128,8 @@ pub fn seq_equal(
pub fn seq_lt(
vm: &mut VirtualMachine,
zelf: &Vec<PyObjectRef>,
other: &Vec<PyObjectRef>,
zelf: &[PyObjectRef],
other: &[PyObjectRef],
) -> Result<bool, PyObjectRef> {
if zelf.len() == other.len() {
for (a, b) in Iterator::zip(zelf.iter(), other.iter()) {
@@ -171,8 +168,8 @@ pub fn seq_lt(
pub fn seq_gt(
vm: &mut VirtualMachine,
zelf: &Vec<PyObjectRef>,
other: &Vec<PyObjectRef>,
zelf: &[PyObjectRef],
other: &[PyObjectRef],
) -> Result<bool, PyObjectRef> {
if zelf.len() == other.len() {
for (a, b) in Iterator::zip(zelf.iter(), other.iter()) {
@@ -210,21 +207,21 @@ pub fn seq_gt(
pub fn seq_ge(
vm: &mut VirtualMachine,
zelf: &Vec<PyObjectRef>,
other: &Vec<PyObjectRef>,
zelf: &[PyObjectRef],
other: &[PyObjectRef],
) -> Result<bool, PyObjectRef> {
Ok(seq_gt(vm, zelf, other)? || seq_equal(vm, zelf, other)?)
}
pub fn seq_le(
vm: &mut VirtualMachine,
zelf: &Vec<PyObjectRef>,
other: &Vec<PyObjectRef>,
zelf: &[PyObjectRef],
other: &[PyObjectRef],
) -> Result<bool, PyObjectRef> {
Ok(seq_lt(vm, zelf, other)? || seq_equal(vm, zelf, other)?)
}
pub fn seq_mul(elements: &Vec<PyObjectRef>, product: &PyObjectRef) -> Vec<PyObjectRef> {
pub fn seq_mul(elements: &[PyObjectRef], product: &PyObjectRef) -> Vec<PyObjectRef> {
let counter = objint::get_value(&product).to_isize().unwrap();
let current_len = elements.len();
@@ -232,7 +229,7 @@ pub fn seq_mul(elements: &Vec<PyObjectRef>, product: &PyObjectRef) -> Vec<PyObje
let mut new_elements = Vec::with_capacity(new_len);
for _ in 0..counter {
new_elements.extend(elements.clone());
new_elements.extend(elements.clone().to_owned());
}
new_elements

View File

@@ -22,7 +22,7 @@ pub fn get_elements(obj: &PyObjectRef) -> HashMap<usize, PyObjectRef> {
}
}
pub fn sequence_to_hashmap(iterable: &Vec<PyObjectRef>) -> HashMap<usize, PyObjectRef> {
pub fn sequence_to_hashmap(iterable: &[PyObjectRef]) -> HashMap<usize, PyObjectRef> {
let mut elements = HashMap::new();
for item in iterable {
let key = item.get_id();
@@ -98,7 +98,7 @@ fn set_repr(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
arg_check!(vm, args, required = [(o, Some(vm.ctx.set_type()))]);
let elements = get_elements(o);
let s = if elements.len() == 0 {
let s = if elements.is_empty() {
"set()".to_string()
} else {
let mut str_parts = vec![];
@@ -136,7 +136,7 @@ fn frozenset_repr(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
arg_check!(vm, args, required = [(o, Some(vm.ctx.frozenset_type()))]);
let elements = get_elements(o);
let s = if elements.len() == 0 {
let s = if elements.is_empty() {
"frozenset()".to_string()
} else {
let mut str_parts = vec![];
@@ -151,7 +151,7 @@ fn frozenset_repr(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
}
pub fn init(context: &PyContext) {
let ref set_type = context.set_type;
let set_type = &context.set_type;
context.set_attr(
&set_type,
"__contains__",
@@ -162,7 +162,7 @@ pub fn init(context: &PyContext) {
context.set_attr(&set_type, "__repr__", context.new_rustfunc(set_repr));
context.set_attr(&set_type, "add", context.new_rustfunc(set_add));
let ref frozenset_type = context.frozenset_type;
let frozenset_type = &context.frozenset_type;
context.set_attr(
&frozenset_type,
"__contains__",

View File

@@ -16,7 +16,7 @@ extern crate unicode_segmentation;
use self::unicode_segmentation::UnicodeSegmentation;
pub fn init(context: &PyContext) {
let ref str_type = context.str_type;
let str_type = &context.str_type;
context.set_attr(&str_type, "__add__", context.new_rustfunc(str_add));
context.set_attr(&str_type, "__eq__", context.new_rustfunc(str_eq));
context.set_attr(
@@ -208,7 +208,7 @@ fn str_add(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
}
fn str_format(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
if args.args.len() == 0 {
if args.args.is_empty() {
return Err(
vm.new_type_error("descriptor 'format' of 'str' object needs an argument".to_string())
);
@@ -238,9 +238,9 @@ fn str_format(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
fn call_object_format(
vm: &mut VirtualMachine,
argument: PyObjectRef,
format_spec: &String,
format_spec: &str,
) -> PyResult {
let returned_type = vm.ctx.new_str(format_spec.clone());
let returned_type = vm.ctx.new_str(format_spec.to_string());
let result = vm.call_method(&argument, "__format__", vec![returned_type])?;
if !objtype::isinstance(&result, &vm.ctx.str_type()) {
let result_type = result.typ();
@@ -450,12 +450,8 @@ fn str_isidentifier(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
&& !value.chars().nth(0).unwrap().is_digit(10)
{
for c in value.chars() {
if c != "_".chars().nth(0).unwrap() {
if !c.is_digit(10) {
if !c.is_alphabetic() {
is_identifier = false;
}
}
if c != "_".chars().nth(0).unwrap() && !c.is_digit(10) && !c.is_alphabetic() {
is_identifier = false;
}
}
} else {
@@ -1030,11 +1026,9 @@ pub fn subscript(vm: &mut VirtualMachine, value: &str, b: PyObjectRef) -> PyResu
}
} else {
match &(*b.borrow()).payload {
&PyObjectPayload::Slice {
start: _,
stop: _,
step: _,
} => Ok(vm.new_str(value.to_string().get_slice_items(&b).to_string())),
&PyObjectPayload::Slice { .. } => {
Ok(vm.new_str(value.to_string().get_slice_items(&b).to_string()))
}
_ => panic!(
"TypeError: indexing type {:?} with index {:?} is not supported (yet?)",
value, b
@@ -1081,5 +1075,5 @@ fn make_title(s: &str) -> String {
capitalize_char = true;
}
}
return titled_str;
titled_str
}

View File

@@ -11,7 +11,7 @@ use super::super::vm::VirtualMachine;
use super::objtype;
pub fn init(context: &PyContext) {
let ref super_type = context.super_type;
let super_type = &context.super_type;
context.set_attr(&super_type, "__init__", context.new_rustfunc(super_init));
}

View File

@@ -275,7 +275,7 @@ pub fn tuple_contains(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
}
pub fn init(context: &PyContext) {
let ref tuple_type = context.tuple_type;
let tuple_type = &context.tuple_type;
context.set_attr(&tuple_type, "__add__", context.new_rustfunc(tuple_add));
context.set_attr(&tuple_type, "__eq__", context.new_rustfunc(tuple_eq));
context.set_attr(

View File

@@ -22,7 +22,7 @@ pub fn create_type(type_type: PyObjectRef, object_type: PyObjectRef, dict_type:
}
pub fn init(context: &PyContext) {
let ref type_type = context.type_type;
let type_type = &context.type_type;
context.set_attr(&type_type, "__call__", context.new_rustfunc(type_call));
context.set_attr(&type_type, "__new__", context.new_rustfunc(type_new));
context.set_attr(
@@ -89,12 +89,7 @@ pub fn issubclass(typ: &PyObjectRef, cls: &PyObjectRef) -> bool {
}
pub fn get_type_name(typ: &PyObjectRef) -> String {
if let PyObjectPayload::Class {
name,
dict: _,
mro: _,
} = &typ.borrow().payload
{
if let PyObjectPayload::Class { name, .. } = &typ.borrow().payload {
name.clone()
} else {
panic!("Cannot get type_name of non-type type {:?}", typ);
@@ -192,22 +187,20 @@ pub fn type_getattribute(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult
Ok(cls_attr)
} else if let Some(attr) = mcl.get_attr(&name) {
vm.call_get_descriptor(attr, cls.clone())
} else if let Some(getter) = cls.get_attr("__getattr__") {
vm.invoke(
getter,
PyFuncArgs {
args: vec![mcl, name_str.clone()],
kwargs: vec![],
},
)
} else {
if let Some(getter) = cls.get_attr("__getattr__") {
vm.invoke(
getter,
PyFuncArgs {
args: vec![mcl, name_str.clone()],
kwargs: vec![],
},
)
} else {
let attribute_error = vm.context().exceptions.attribute_error.clone();
Err(vm.new_exception(
attribute_error,
format!("{} has no attribute '{}'", cls.borrow(), name),
))
}
let attribute_error = vm.context().exceptions.attribute_error.clone();
Err(vm.new_exception(
attribute_error,
format!("{} has no attribute '{}'", cls.borrow(), name),
))
}
}
@@ -219,12 +212,7 @@ pub fn get_attributes(obj: &PyObjectRef) -> HashMap<String, PyObjectRef> {
let mut base_classes = objtype::base_classes(obj);
base_classes.reverse();
for bc in base_classes {
if let PyObjectPayload::Class {
name: _,
dict,
mro: _,
} = &bc.borrow().payload
{
if let PyObjectPayload::Class { dict, .. } = &bc.borrow().payload {
let elements = objdict::get_key_value_pairs(dict);
for (name, value) in elements.iter() {
let name = objstr::get_value(name);
@@ -263,7 +251,7 @@ fn take_next_base(
}
if let Some(head) = next {
for ref mut item in &mut bases {
for item in &mut bases {
if item[0].get_id() == head.get_id() {
item.remove(0);
}

View File

@@ -7,6 +7,7 @@ use super::obj::objbytes;
use super::obj::objcode;
use super::obj::objcomplex;
use super::obj::objdict;
use super::obj::objfilter;
use super::obj::objfloat;
use super::obj::objframe;
use super::obj::objfunction;
@@ -14,6 +15,7 @@ use super::obj::objgenerator;
use super::obj::objint;
use super::obj::objiter;
use super::obj::objlist;
use super::obj::objmap;
use super::obj::objmemory;
use super::obj::objobject;
use super::obj::objproperty;
@@ -106,6 +108,7 @@ pub struct PyContext {
pub classmethod_type: PyObjectRef,
pub code_type: PyObjectRef,
pub dict_type: PyObjectRef,
pub filter_type: PyObjectRef,
pub float_type: PyObjectRef,
pub frame_type: PyObjectRef,
pub frozenset_type: PyObjectRef,
@@ -116,6 +119,7 @@ pub struct PyContext {
pub true_value: PyObjectRef,
pub false_value: PyObjectRef,
pub list_type: PyObjectRef,
pub map_type: PyObjectRef,
pub memoryview_type: PyObjectRef,
pub none: PyObjectRef,
pub tuple_type: PyObjectRef,
@@ -200,6 +204,8 @@ impl PyContext {
let bytearray_type = create_type("bytearray", &type_type, &object_type, &dict_type);
let tuple_type = create_type("tuple", &type_type, &object_type, &dict_type);
let iter_type = create_type("iter", &type_type, &object_type, &dict_type);
let filter_type = create_type("filter", &type_type, &object_type, &dict_type);
let map_type = create_type("map", &type_type, &object_type, &dict_type);
let bool_type = create_type("bool", &type_type, &int_type, &dict_type);
let memoryview_type = create_type("memoryview", &type_type, &object_type, &dict_type);
let code_type = create_type("code", &type_type, &int_type, &dict_type);
@@ -240,6 +246,8 @@ impl PyContext {
false_value,
tuple_type,
iter_type,
filter_type,
map_type,
dict_type,
none: none,
str_type: str_type,
@@ -275,6 +283,8 @@ impl PyContext {
objsuper::init(&context);
objtuple::init(&context);
objiter::init(&context);
objfilter::init(&context);
objmap::init(&context);
objbool::init(&context);
objcode::init(&context);
objframe::init(&context);
@@ -346,6 +356,14 @@ impl PyContext {
self.iter_type.clone()
}
pub fn filter_type(&self) -> PyObjectRef {
self.filter_type.clone()
}
pub fn map_type(&self) -> PyObjectRef {
self.map_type.clone()
}
pub fn str_type(&self) -> PyObjectRef {
self.str_type.clone()
}
@@ -436,17 +454,11 @@ impl PyContext {
}
pub fn new_tuple(&self, elements: Vec<PyObjectRef>) -> PyObjectRef {
PyObject::new(
PyObjectPayload::Sequence { elements: elements },
self.tuple_type(),
)
PyObject::new(PyObjectPayload::Sequence { elements }, self.tuple_type())
}
pub fn new_list(&self, elements: Vec<PyObjectRef>) -> PyObjectRef {
PyObject::new(
PyObjectPayload::Sequence { elements: elements },
self.list_type(),
)
PyObject::new(PyObjectPayload::Sequence { elements }, self.list_type())
}
pub fn new_set(&self, elements: Vec<PyObjectRef>) -> PyObjectRef {
@@ -469,12 +481,11 @@ impl PyContext {
pub fn new_scope(&self, parent: Option<PyObjectRef>) -> PyObjectRef {
let locals = self.new_dict();
let scope = Scope {
locals: locals,
parent: parent,
};
let scope = Scope { locals, parent };
PyObject {
payload: PyObjectPayload::Scope { scope: scope },
payload: PyObjectPayload::Scope { scope },
typ: None,
}
.into_ref()
@@ -553,10 +564,7 @@ impl PyContext {
pub fn new_bound_method(&self, function: PyObjectRef, object: PyObjectRef) -> PyObjectRef {
PyObject::new(
PyObjectPayload::BoundMethod {
function: function,
object: object,
},
PyObjectPayload::BoundMethod { function, object },
self.bound_method_type(),
)
}
@@ -581,10 +589,7 @@ impl PyContext {
let key = self.new_str(key.to_string());
objdict::set_item_in_content(elements, &key, &v);
}
PyObjectPayload::Module {
name: _,
ref mut dict,
} => self.set_item(dict, key, v),
PyObjectPayload::Module { ref mut dict, .. } => self.set_item(dict, key, v),
PyObjectPayload::Scope { ref mut scope } => {
self.set_item(&scope.locals, key, v);
}
@@ -601,13 +606,9 @@ impl PyContext {
pub fn set_attr(&self, obj: &PyObjectRef, attr_name: &str, value: PyObjectRef) {
match obj.borrow().payload {
PyObjectPayload::Module { name: _, ref dict } => self.set_item(dict, attr_name, value),
PyObjectPayload::Module { ref dict, .. } => self.set_item(dict, attr_name, value),
PyObjectPayload::Instance { ref dict } => self.set_item(dict, attr_name, value),
PyObjectPayload::Class {
name: _,
ref dict,
mro: _,
} => self.set_item(dict, attr_name, value),
PyObjectPayload::Class { ref dict, .. } => self.set_item(dict, attr_name, value),
ref payload => unimplemented!("set_attr unimplemented for: {:?}", payload),
};
}
@@ -717,7 +718,7 @@ impl AttributeProtocol for PyObjectRef {
if let Some(item) = class_get_item(self, attr_name) {
return Some(item);
}
for ref class in mro {
for class in mro {
if let Some(item) = class_get_item(class, attr_name) {
return Some(item);
}
@@ -732,7 +733,7 @@ impl AttributeProtocol for PyObjectRef {
fn has_attr(&self, attr_name: &str) -> bool {
let obj = self.borrow();
match obj.payload {
PyObjectPayload::Module { name: _, ref dict } => dict.contains_key(attr_name),
PyObjectPayload::Module { ref dict, .. } => dict.contains_key(attr_name),
PyObjectPayload::Class { ref mro, .. } => {
class_has_item(self, attr_name)
|| mro.into_iter().any(|d| class_has_item(d, attr_name))
@@ -755,7 +756,7 @@ impl DictProtocol for PyObjectRef {
PyObjectPayload::Dict { ref elements } => {
objdict::content_contains_key_str(elements, k)
}
PyObjectPayload::Module { name: _, ref dict } => dict.contains_key(k),
PyObjectPayload::Module { ref dict, .. } => dict.contains_key(k),
PyObjectPayload::Scope { ref scope } => scope.locals.contains_key(k),
ref payload => unimplemented!("TODO {:?}", payload),
}
@@ -764,7 +765,7 @@ impl DictProtocol for PyObjectRef {
fn get_item(&self, k: &str) -> Option<PyObjectRef> {
match self.borrow().payload {
PyObjectPayload::Dict { ref elements } => objdict::content_get_key_str(elements, k),
PyObjectPayload::Module { name: _, ref dict } => dict.get_item(k),
PyObjectPayload::Module { ref dict, .. } => dict.get_item(k),
PyObjectPayload::Scope { ref scope } => scope.locals.get_item(k),
_ => panic!("TODO"),
}
@@ -772,8 +773,8 @@ impl DictProtocol for PyObjectRef {
fn get_key_value_pairs(&self) -> Vec<(PyObjectRef, PyObjectRef)> {
match self.borrow().payload {
PyObjectPayload::Dict { elements: _ } => objdict::get_key_value_pairs(self),
PyObjectPayload::Module { name: _, ref dict } => dict.get_key_value_pairs(),
PyObjectPayload::Dict { .. } => objdict::get_key_value_pairs(self),
PyObjectPayload::Module { ref dict, .. } => dict.get_key_value_pairs(),
PyObjectPayload::Scope { ref scope } => scope.locals.get_key_value_pairs(),
_ => panic!("TODO"),
}
@@ -815,10 +816,7 @@ impl PyFuncArgs {
for name in kwarg_names.iter().rev() {
kwargs.push((name.clone(), args.pop().unwrap()));
}
PyFuncArgs {
args: args,
kwargs: kwargs,
}
PyFuncArgs { args, kwargs }
}
pub fn insert(&self, item: PyObjectRef) -> PyFuncArgs {
@@ -827,7 +825,7 @@ impl PyFuncArgs {
kwargs: self.kwargs.clone(),
};
args.args.insert(0, item);
return args;
args
}
pub fn shift(&mut self) -> PyObjectRef {
@@ -886,6 +884,14 @@ pub enum PyObjectPayload {
position: usize,
iterated_obj: PyObjectRef,
},
FilterIterator {
predicate: PyObjectRef,
iterator: PyObjectRef,
},
MapIterator {
mapper: PyObjectRef,
iterators: Vec<PyObjectRef>,
},
Slice {
start: Option<i32>,
stop: Option<i32>,
@@ -948,37 +954,28 @@ impl fmt::Debug for PyObjectPayload {
PyObjectPayload::Complex { ref value } => write!(f, "complex {}", value),
PyObjectPayload::Bytes { ref value } => write!(f, "bytes/bytearray {:?}", value),
PyObjectPayload::MemoryView { ref obj } => write!(f, "bytes/bytearray {:?}", obj),
PyObjectPayload::Sequence { elements: _ } => write!(f, "list or tuple"),
PyObjectPayload::Dict { elements: _ } => write!(f, "dict"),
PyObjectPayload::Set { elements: _ } => write!(f, "set"),
PyObjectPayload::Sequence { .. } => write!(f, "list or tuple"),
PyObjectPayload::Dict { .. } => write!(f, "dict"),
PyObjectPayload::Set { .. } => write!(f, "set"),
PyObjectPayload::WeakRef { .. } => write!(f, "weakref"),
PyObjectPayload::Iterator {
position: _,
iterated_obj: _,
} => write!(f, "iterator"),
PyObjectPayload::Slice {
start: _,
stop: _,
step: _,
} => write!(f, "slice"),
&PyObjectPayload::Range { range: _ } => write!(f, "range"),
&PyObjectPayload::Code { ref code } => write!(f, "code: {:?}", code),
&PyObjectPayload::Function { .. } => write!(f, "function"),
&PyObjectPayload::Generator { .. } => write!(f, "generator"),
&PyObjectPayload::BoundMethod {
PyObjectPayload::Range { .. } => write!(f, "range"),
PyObjectPayload::Iterator { .. } => write!(f, "iterator"),
PyObjectPayload::FilterIterator { .. } => write!(f, "filter"),
PyObjectPayload::MapIterator { .. } => write!(f, "map"),
PyObjectPayload::Slice { .. } => write!(f, "slice"),
PyObjectPayload::Code { ref code } => write!(f, "code: {:?}", code),
PyObjectPayload::Function { .. } => write!(f, "function"),
PyObjectPayload::Generator { .. } => write!(f, "generator"),
PyObjectPayload::BoundMethod {
ref function,
ref object,
} => write!(f, "bound-method: {:?} of {:?}", function, object),
PyObjectPayload::Module { name: _, dict: _ } => write!(f, "module"),
PyObjectPayload::Scope { scope: _ } => write!(f, "scope"),
PyObjectPayload::Module { .. } => write!(f, "module"),
PyObjectPayload::Scope { .. } => write!(f, "scope"),
PyObjectPayload::None => write!(f, "None"),
PyObjectPayload::Class {
ref name,
dict: _,
mro: _,
} => write!(f, "class {:?}", name),
PyObjectPayload::Instance { dict: _ } => write!(f, "instance"),
PyObjectPayload::RustFunction { function: _ } => write!(f, "rust function"),
PyObjectPayload::Class { ref name, .. } => write!(f, "class {:?}", name),
PyObjectPayload::Instance { .. } => write!(f, "instance"),
PyObjectPayload::RustFunction { .. } => write!(f, "rust function"),
PyObjectPayload::Frame { .. } => write!(f, "frame"),
}
}
@@ -1035,16 +1032,17 @@ impl PyObject {
PyObjectPayload::Class {
ref name,
dict: ref _dict,
mro: _,
..
} => format!("<class '{}'>", name),
PyObjectPayload::Instance { dict: _ } => format!("<instance>"),
PyObjectPayload::Code { code: _ } => format!("<code>"),
PyObjectPayload::Function { .. } => format!("<func>"),
PyObjectPayload::Generator { .. } => format!("<generator>"),
PyObjectPayload::Frame { .. } => format!("<frame>"),
PyObjectPayload::BoundMethod { .. } => format!("<bound-method>"),
PyObjectPayload::RustFunction { function: _ } => format!("<rustfunc>"),
PyObjectPayload::Module { ref name, dict: _ } => format!("<module '{}'>", name),
PyObjectPayload::Instance { .. } => "<instance>".to_string(),
PyObjectPayload::Code { .. } => "<code>".to_string(),
PyObjectPayload::Function { .. } => "<func>".to_string(),
PyObjectPayload::Generator { .. } => "<generator>".to_string(),
PyObjectPayload::Frame { .. } => "<frame>".to_string(),
PyObjectPayload::BoundMethod { .. } => "<bound-method>".to_string(),
PyObjectPayload::RustFunction { .. } => "<rustfunc>".to_string(),
PyObjectPayload::Module { ref name, .. } => format!("<module '{}'>", name),
PyObjectPayload::Scope { ref scope } => format!("<scope '{:?}'>", scope),
PyObjectPayload::Slice {
ref start,
@@ -1060,6 +1058,8 @@ impl PyObject {
position,
iterated_obj.borrow_mut().str()
),
PyObjectPayload::FilterIterator { .. } => format!("<filter>"),
PyObjectPayload::MapIterator { .. } => format!("<map>"),
}
}

View File

@@ -64,9 +64,8 @@ fn statement_to_ast(ctx: &PyContext, statement: &ast::LocatedStatement) -> PyObj
ast::Statement::ClassDef {
name,
body,
bases: _,
keywords: _,
decorator_list,
..
} => {
let node = create_node(ctx, "ClassDef");
@@ -239,7 +238,7 @@ fn statement_to_ast(ctx: &PyContext, statement: &ast::LocatedStatement) -> PyObj
node
}
fn expressions_to_ast(ctx: &PyContext, expressions: &Vec<ast::Expression>) -> PyObjectRef {
fn expressions_to_ast(ctx: &PyContext, expressions: &[ast::Expression]) -> PyObjectRef {
let mut py_expression_nodes = vec![];
for expression in expressions {
py_expression_nodes.push(expression_to_ast(ctx, expression));
@@ -249,11 +248,7 @@ fn expressions_to_ast(ctx: &PyContext, expressions: &Vec<ast::Expression>) -> Py
fn expression_to_ast(ctx: &PyContext, expression: &ast::Expression) -> PyObjectRef {
let node = match &expression {
ast::Expression::Call {
function,
args,
keywords: _,
} => {
ast::Expression::Call { function, args, .. } => {
let node = create_node(ctx, "Call");
let py_func_ast = expression_to_ast(ctx, function);

View File

@@ -26,7 +26,7 @@ use super::super::pyobject::{
use super::super::vm::VirtualMachine;
fn compute_c_flag(mode: &String) -> u16 {
fn compute_c_flag(mode: &str) -> u16 {
match mode.as_ref() {
"w" => 512,
"x" => 512,
@@ -295,7 +295,7 @@ pub fn io_open(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
.filter(|a| raw_modes.contains(&a.to_string()))
.collect();
if modes.len() == 0 || modes.len() > 1 {
if modes.is_empty() || modes.len() > 1 {
return Err(vm.new_value_error("Invalid Mode".to_string()));
}

View File

@@ -14,8 +14,8 @@ use std;
macro_rules! make_math_func {
( $fname:ident, $fun:ident ) => {
fn $fname(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
arg_check!(vm, args, required = [(value, Some(vm.ctx.float_type()))]);
let value = objfloat::get_value(value);
arg_check!(vm, args, required = [(value, None)]);
let value = objfloat::make_float(vm, value)?;
let value = value.$fun();
let value = vm.ctx.new_float(value);
Ok(value)
@@ -27,20 +27,20 @@ macro_rules! make_math_func {
make_math_func!(math_fabs, abs);
fn math_isfinite(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
arg_check!(vm, args, required = [(value, Some(vm.ctx.float_type()))]);
let value = objfloat::get_value(value).is_finite();
arg_check!(vm, args, required = [(value, None)]);
let value = objfloat::make_float(vm, value)?.is_finite();
Ok(vm.ctx.new_bool(value))
}
fn math_isinf(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
arg_check!(vm, args, required = [(value, Some(vm.ctx.float_type()))]);
let value = objfloat::get_value(value).is_infinite();
arg_check!(vm, args, required = [(value, None)]);
let value = objfloat::make_float(vm, value)?.is_infinite();
Ok(vm.ctx.new_bool(value))
}
fn math_isnan(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
arg_check!(vm, args, required = [(value, Some(vm.ctx.float_type()))]);
let value = objfloat::get_value(value).is_nan();
arg_check!(vm, args, required = [(value, None)]);
let value = objfloat::make_float(vm, value)?.is_nan();
Ok(vm.ctx.new_bool(value))
}
@@ -49,25 +49,20 @@ make_math_func!(math_exp, exp);
make_math_func!(math_expm1, exp_m1);
fn math_log(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
arg_check!(
vm,
args,
required = [(x, Some(vm.ctx.float_type()))],
optional = [(base, Some(vm.ctx.float_type()))]
);
let x = objfloat::get_value(x);
arg_check!(vm, args, required = [(x, None)], optional = [(base, None)]);
let x = objfloat::make_float(vm, x)?;
match base {
None => Ok(vm.ctx.new_float(x.ln())),
Some(base) => {
let base = objfloat::get_value(base);
let base = objfloat::make_float(vm, base)?;
Ok(vm.ctx.new_float(x.log(base)))
}
}
}
fn math_log1p(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
arg_check!(vm, args, required = [(x, Some(vm.ctx.float_type()))]);
let x = objfloat::get_value(x);
arg_check!(vm, args, required = [(x, None)]);
let x = objfloat::make_float(vm, x)?;
Ok(vm.ctx.new_float((x + 1.0).ln()))
}
@@ -75,16 +70,9 @@ make_math_func!(math_log2, log2);
make_math_func!(math_log10, log10);
fn math_pow(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
arg_check!(
vm,
args,
required = [
(x, Some(vm.ctx.float_type())),
(y, Some(vm.ctx.float_type()))
]
);
let x = objfloat::get_value(x);
let y = objfloat::get_value(y);
arg_check!(vm, args, required = [(x, None), (y, None)]);
let x = objfloat::make_float(vm, x)?;
let y = objfloat::make_float(vm, y)?;
Ok(vm.ctx.new_float(x.powf(y)))
}
@@ -96,32 +84,18 @@ make_math_func!(math_asin, asin);
make_math_func!(math_atan, atan);
fn math_atan2(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
arg_check!(
vm,
args,
required = [
(y, Some(vm.ctx.float_type())),
(x, Some(vm.ctx.float_type()))
]
);
let y = objfloat::get_value(y);
let x = objfloat::get_value(x);
arg_check!(vm, args, required = [(y, None), (x, None)]);
let y = objfloat::make_float(vm, y)?;
let x = objfloat::make_float(vm, x)?;
Ok(vm.ctx.new_float(y.atan2(x)))
}
make_math_func!(math_cos, cos);
fn math_hypot(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
arg_check!(
vm,
args,
required = [
(x, Some(vm.ctx.float_type())),
(y, Some(vm.ctx.float_type()))
]
);
let x = objfloat::get_value(x);
let y = objfloat::get_value(y);
arg_check!(vm, args, required = [(x, None), (y, None)]);
let x = objfloat::make_float(vm, x)?;
let y = objfloat::make_float(vm, y)?;
Ok(vm.ctx.new_float(x.hypot(y)))
}
@@ -129,14 +103,14 @@ make_math_func!(math_sin, sin);
make_math_func!(math_tan, tan);
fn math_degrees(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
arg_check!(vm, args, required = [(value, Some(vm.ctx.float_type()))]);
let x = objfloat::get_value(value);
arg_check!(vm, args, required = [(value, None)]);
let x = objfloat::make_float(vm, value)?;
Ok(vm.ctx.new_float(x * (180.0 / std::f64::consts::PI)))
}
fn math_radians(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
arg_check!(vm, args, required = [(value, Some(vm.ctx.float_type()))]);
let x = objfloat::get_value(value);
arg_check!(vm, args, required = [(value, None)]);
let x = objfloat::make_float(vm, value)?;
Ok(vm.ctx.new_float(x * (std::f64::consts::PI / 180.0)))
}
@@ -150,8 +124,8 @@ make_math_func!(math_tanh, tanh);
// Special functions:
fn math_erf(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
arg_check!(vm, args, required = [(value, Some(vm.ctx.float_type()))]);
let x = objfloat::get_value(value);
arg_check!(vm, args, required = [(value, None)]);
let x = objfloat::make_float(vm, value)?;
if x.is_nan() {
Ok(vm.ctx.new_float(x))
@@ -161,8 +135,8 @@ fn math_erf(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
}
fn math_erfc(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
arg_check!(vm, args, required = [(value, Some(vm.ctx.float_type()))]);
let x = objfloat::get_value(value);
arg_check!(vm, args, required = [(value, None)]);
let x = objfloat::make_float(vm, value)?;
if x.is_nan() {
Ok(vm.ctx.new_float(x))
@@ -172,32 +146,28 @@ fn math_erfc(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
}
fn math_gamma(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
arg_check!(vm, args, required = [(value, Some(vm.ctx.float_type()))]);
let x = objfloat::get_value(value);
arg_check!(vm, args, required = [(value, None)]);
let x = objfloat::make_float(vm, value)?;
if x.is_finite() {
Ok(vm.ctx.new_float(gamma(x)))
} else if x.is_nan() || x.is_sign_positive() {
Ok(vm.ctx.new_float(x))
} else {
if x.is_nan() || x.is_sign_positive() {
Ok(vm.ctx.new_float(x))
} else {
Ok(vm.ctx.new_float(std::f64::NAN))
}
Ok(vm.ctx.new_float(std::f64::NAN))
}
}
fn math_lgamma(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
arg_check!(vm, args, required = [(value, Some(vm.ctx.float_type()))]);
let x = objfloat::get_value(value);
arg_check!(vm, args, required = [(value, None)]);
let x = objfloat::make_float(vm, value)?;
if x.is_finite() {
Ok(vm.ctx.new_float(ln_gamma(x)))
} else if x.is_nan() {
Ok(vm.ctx.new_float(x))
} else {
if x.is_nan() {
Ok(vm.ctx.new_float(x))
} else {
Ok(vm.ctx.new_float(std::f64::INFINITY))
}
Ok(vm.ctx.new_float(std::f64::INFINITY))
}
}

View File

@@ -169,7 +169,7 @@ fn pack_f64(
}
fn struct_pack(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
if args.args.len() < 1 {
if args.args.is_empty() {
Err(vm.new_type_error(format!(
"Expected at least 1 argument (got: {})",
args.args.len()

View File

@@ -174,7 +174,7 @@ impl VirtualMachine {
pub fn get_builtin_scope(&mut self) -> PyObjectRef {
let a2 = &*self.builtins.borrow();
match a2.payload {
PyObjectPayload::Module { name: _, ref dict } => dict.clone(),
PyObjectPayload::Module { ref dict, .. } => dict.clone(),
_ => {
panic!("OMG");
}
@@ -260,11 +260,7 @@ impl VirtualMachine {
ref scope,
ref defaults,
} => self.invoke_python_function(code, scope, defaults, args),
PyObjectPayload::Class {
name: _,
dict: _,
mro: _,
} => self.call_method_pyargs(&func_ref, "__call__", args),
PyObjectPayload::Class { .. } => self.call_method_pyargs(&func_ref, "__call__", args),
PyObjectPayload::BoundMethod {
ref function,
ref object,

View File

@@ -7,7 +7,7 @@
<body>
<h1>RustPython Demo</h1>
<p>
RustPython is a Python interpreter writter in Rust. This demo is
RustPython is a Python interpreter written in Rust. This demo is
compiled from Rust to WebAssembly so it runs in the browser.<br>
Please input your Python code below and click <kbd>Run</kbd>, or you
can open up your browser's devtools and play with
@@ -44,7 +44,7 @@ while count < until:
<ul>
<li>
<code>stdout</code>: either a string with a css selector
to a textarea element or a function that recieves a
to a textarea element or a function that receives a
string when the <code>print</code> function is called in
python. The default value is <code>console.log</code>.
</li>
@@ -57,7 +57,7 @@ while count < until:
</ul>
</li>
<li>
JS functions that get passed to python will recieve positional
JS functions that get passed to python will receive positional
args as positional args and kwargs as the
<code>this</code> argument
</li>

View File

@@ -28,7 +28,7 @@ pyEval(code, options?);
- `vars?`: `{ [key: string]: any }`: Variables passed to the VM that can be
accessed in Python with the variable `js_vars`. Functions do work, and
recieve the Python kwargs as the `this` argument.
receive the Python kwargs as the `this` argument.
- `stdout?`: `(out: string) => void`: A function to replace the native print
function, by default `console.log`.

View File

@@ -11,7 +11,7 @@ use rustpython_vm::pyobject::{self, PyFuncArgs, PyObjectRef, PyResult};
use rustpython_vm::VirtualMachine;
use wasm_bindgen::{prelude::*, JsCast};
// Hack to comment out wasm-bindgen's typescript definitons
// Hack to comment out wasm-bindgen's typescript definitions
#[wasm_bindgen(typescript_custom_section)]
const TS_CMT_START: &'static str = "/*";
@@ -141,7 +141,7 @@ fn eval(vm: &mut VirtualMachine, source: &str, vars: PyObjectRef) -> PyResult {
///
/// - `vars?`: `{ [key: string]: any }`: Variables passed to the VM that can be
/// accessed in Python with the variable `js_vars`. Functions do work, and
/// recieve the Python kwargs as the `this` argument.
/// receive the Python kwargs as the `this` argument.
/// - `stdout?`: `(out: string) => void`: A function to replace the native print
/// function, by default `console.log`.
pub fn eval_py(source: &str, options: Option<Object>) -> Result<JsValue, JsValue> {