mirror of
https://github.com/RustPython/RustPython.git
synced 2026-06-09 22:49:57 +09:00
Merge branch 'master' into master
This commit is contained in:
1
Cargo.lock
generated
1
Cargo.lock
generated
@@ -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)",
|
||||
|
||||
@@ -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
|
||||
|
||||
32
tests/snippets/builtin_filter.py
Normal file
32
tests/snippets/builtin_filter.py
Normal 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]
|
||||
34
tests/snippets/builtin_map.py
Normal file
34
tests/snippets/builtin_map.py
Normal 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]
|
||||
@@ -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)
|
||||
|
||||
@@ -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')
|
||||
|
||||
@@ -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())
|
||||
|
||||
@@ -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"}
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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"),
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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) => {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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()));
|
||||
|
||||
@@ -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__",
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
@@ -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))
|
||||
}
|
||||
|
||||
@@ -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
83
vm/src/obj/objfilter.rs
Normal 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));
|
||||
}
|
||||
@@ -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));
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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__",
|
||||
|
||||
@@ -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__",
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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__",
|
||||
|
||||
@@ -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
81
vm/src/obj/objmap.rs
Normal 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));
|
||||
}
|
||||
@@ -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__",
|
||||
|
||||
@@ -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),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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__",
|
||||
|
||||
@@ -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!()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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__",
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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>"),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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()));
|
||||
}
|
||||
|
||||
|
||||
@@ -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))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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`.
|
||||
|
||||
|
||||
@@ -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> {
|
||||
|
||||
Reference in New Issue
Block a user