Fix merge conflicts

This commit is contained in:
coolreader18 committed 2019-02-27 12:44:42 -06:00
commit e3db472f37
22 files changed
+237 -42

No files matched your search

Generated
+1
View File
@@ -775,6 +775,7 @@ dependencies = [
"cfg-if 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
"futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)",
"js-sys 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
"num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
"rustpython_parser 0.0.1",
"rustpython_vm 0.1.0",
"wasm-bindgen 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)",
+5 -2
View File
@@ -55,6 +55,7 @@ pub struct Lexer<T: Iterator<Item = char>> {
pub enum LexicalError {
StringError,
NestingError,
UnrecognizedToken { tok: char },
}
#[derive(Clone, Debug, Default, PartialEq)]
@@ -687,7 +688,9 @@ where
match self.chr0 {
Some('0'..='9') => return Some(self.lex_number()),
Some('_') | Some('a'..='z') | Some('A'..='Z') => return Some(self.lex_identifier()),
Some('_') | Some('a'..='z') | Some('A'..='Z') => {
return Some(self.lex_identifier());
}
Some('#') => {
self.lex_comment();
continue;
@@ -1033,7 +1036,7 @@ where
None => return None,
_ => {
let c = self.next_char();
panic!("Not impl {:?}", c)
return Some(Err(LexicalError::UnrecognizedToken { tok: c.unwrap() }));
} // Ignore all the rest..
}
}
+3 -1
View File
@@ -306,7 +306,9 @@ mod tests {
#[test]
fn test_parse_class() {
let source = String::from("class Foo(A, B):\n def __init__(self):\n pass\n def method_with_default(self, arg='default'):\n pass\n");
let source = String::from(
"class Foo(A, B):\n def __init__(self):\n pass\n def method_with_default(self, arg='default'):\n pass\n",
);
assert_eq!(
parse_statement(&source),
Ok(ast::LocatedStatement {
+1
View File
@@ -0,0 +1 @@
edition = "2018"
+3
View File
@@ -1,3 +1,5 @@
from testutils import assert_raises
# int to int comparisons
assert 1 == 1
@@ -36,6 +38,7 @@ assert (2).__rtruediv__(1) == 0.5
assert (1).real == 1
assert (1).imag == 0
assert_raises(OverflowError, lambda: 1 << 10 ** 100000)
assert (1).__eq__(1.0) == NotImplemented
assert (1).__ne__(1.0) == NotImplemented
+39
View File
@@ -117,3 +117,42 @@ b.append(c)
assert a == b
assert [foo] == [foo]
for size in [1, 2, 3, 4, 5, 8, 10, 100, 1000]:
lst = list(range(size))
orig = lst[:]
lst.sort()
assert lst == orig
assert sorted(lst) == orig
assert_raises(ZeroDivisionError, lambda: sorted(lst, key=lambda x: 1/x))
lst.reverse()
assert sorted(lst) == orig
assert sorted(lst, reverse=True) == lst
assert sorted(lst, key=lambda x: -x) == lst
assert sorted(lst, key=lambda x: -x, reverse=True) == orig
assert sorted([(1, 2, 3), (0, 3, 6)]) == [(0, 3, 6), (1, 2, 3)]
assert sorted([(1, 2, 3), (0, 3, 6)], key=lambda x: x[0]) == [(0, 3, 6), (1, 2, 3)]
assert sorted([(1, 2, 3), (0, 3, 6)], key=lambda x: x[1]) == [(1, 2, 3), (0, 3, 6)]
assert sorted([(1, 2), (), (5,)], key=len) == [(), (5,), (1, 2)]
lst = [3, 1, 5, 2, 4]
class C:
def __init__(self, x): self.x = x
def __lt__(self, other): return self.x < other.x
lst.sort(key=C)
assert lst == [1, 2, 3, 4, 5]
lst = [3, 1, 5, 2, 4]
class C:
def __init__(self, x): self.x = x
def __gt__(self, other): return self.x > other.x
lst.sort(key=C)
assert lst == [1, 2, 3, 4, 5]
lst = [5, 1, 2, 3, 4]
def f(x):
lst.append(1)
return x
assert_raises(ValueError, lambda: lst.sort(key=f)) # "list modified during sort"
assert lst == [1, 2, 3, 4, 5]
+11 -1
View File
@@ -689,7 +689,16 @@ fn builtin_setattr(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
}
// builtin_slice
// builtin_sorted
fn builtin_sorted(vm: &mut VirtualMachine, mut args: PyFuncArgs) -> PyResult {
arg_check!(vm, args, required = [(iterable, None)]);
let items = vm.extract_elements(iterable)?;
let lst = vm.ctx.new_list(items);
args.shift();
vm.call_method_pyargs(&lst, "sort", args)?;
Ok(lst)
}
fn builtin_sum(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
arg_check!(vm, args, required = [(iterable, None)]);
@@ -763,6 +772,7 @@ pub fn make_module(ctx: &PyContext) -> PyObjectRef {
"round" => ctx.new_rustfunc(builtin_round),
"set" => ctx.set_type(),
"setattr" => ctx.new_rustfunc(builtin_setattr),
"sorted" => ctx.new_rustfunc(builtin_sorted),
"slice" => ctx.slice_type(),
"staticmethod" => ctx.staticmethod_type(),
"str" => ctx.str_type(),
+1 -1
View File
@@ -1389,7 +1389,7 @@ impl Compiler {
// Low level helper functions:
fn emit(&mut self, instruction: Instruction) {
let location = self.current_source_location.clone();
let mut cur_code_obj = self.current_code_object();
let cur_code_obj = self.current_code_object();
cur_code_obj.instructions.push(instruction);
cur_code_obj.locations.push(location);
// TODO: insert source filename
+1 -1
View File
@@ -60,7 +60,7 @@ pub fn import_module(
return Ok(module);
}
let module = import_uncached_module(vm, current_path, module_name)?;
vm.ctx.set_item(&sys_modules, module_name, module.clone());
sys_modules.set_item(&vm.ctx, module_name, module.clone());
Ok(module)
}
+2 -4
View File
@@ -246,8 +246,7 @@ fn int_lshift(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
match get_value(i2) {
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));
Err(vm.new_overflow_error("the number is too large to convert to int".to_string()))
}
_ => panic!("Failed converting {} to rust usize", get_value(i2)),
}
@@ -276,8 +275,7 @@ fn int_rshift(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
match get_value(i2) {
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));
Err(vm.new_overflow_error("the number is too large to convert to int".to_string()))
}
_ => panic!("Failed converting {} to rust usize", get_value(i2)),
}
+93 -6
View File
@@ -3,8 +3,8 @@ use std::cell::{Cell, RefCell};
use super::objbool;
use super::objint;
use super::objsequence::{
get_elements, get_item, get_mut_elements, seq_equal, seq_ge, seq_gt, seq_le, seq_lt, seq_mul,
PySliceableSequence,
get_elements, get_elements_cell, get_item, get_mut_elements, seq_equal, seq_ge, seq_gt, seq_le,
seq_lt, seq_mul, PySliceableSequence,
};
use super::objstr;
use super::objtype;
@@ -334,12 +334,99 @@ fn list_reverse(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
Ok(vm.get_none())
}
fn quicksort(
vm: &mut VirtualMachine,
keys: &mut [PyObjectRef],
values: &mut [PyObjectRef],
) -> PyResult<()> {
let len = values.len();
if len >= 2 {
let pivot = partition(vm, keys, values)?;
quicksort(vm, &mut keys[0..pivot], &mut values[0..pivot])?;
quicksort(vm, &mut keys[pivot + 1..len], &mut values[pivot + 1..len])?;
}
Ok(())
}
fn partition(
vm: &mut VirtualMachine,
keys: &mut [PyObjectRef],
values: &mut [PyObjectRef],
) -> PyResult<usize> {
let len = values.len();
let pivot = len / 2;
values.swap(pivot, len - 1);
keys.swap(pivot, len - 1);
let mut store_idx = 0;
for i in 0..len - 1 {
let result = vm._lt(keys[i].clone(), keys[len - 1].clone())?;
let boolval = objbool::boolval(vm, result)?;
if boolval {
values.swap(i, store_idx);
keys.swap(i, store_idx);
store_idx += 1;
}
}
values.swap(store_idx, len - 1);
keys.swap(store_idx, len - 1);
Ok(store_idx)
}
fn do_sort(
vm: &mut VirtualMachine,
values: &mut Vec<PyObjectRef>,
key_func: Option<PyObjectRef>,
reverse: bool,
) -> PyResult<()> {
// build a list of keys. If no keyfunc is provided, it's a copy of the list.
let mut keys: Vec<PyObjectRef> = vec![];
for x in values.iter() {
keys.push(match &key_func {
None => x.clone(),
Some(ref func) => vm.invoke(
(*func).clone(),
PyFuncArgs {
args: vec![x.clone()],
kwargs: vec![],
},
)?,
});
}
quicksort(vm, &mut keys, values)?;
if reverse {
values.reverse();
}
Ok(())
}
fn list_sort(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
arg_check!(vm, args, required = [(list, Some(vm.ctx.list_type()))]);
let mut _elements = get_mut_elements(list);
unimplemented!("TODO: figure out how to invoke `sort_by` on a Vec");
// elements.sort_by();
// Ok(vm.get_none())
let key_func = args.get_optional_kwarg("key");
let reverse = args.get_optional_kwarg("reverse");
let reverse = match reverse {
None => false,
Some(val) => objbool::boolval(vm, val)?,
};
let elements_cell = get_elements_cell(list);
// replace list contents with [] for duration of sort.
// this prevents keyfunc from messing with the list and makes it easy to
// check if it tries to append elements to it.
let mut elements = elements_cell.replace(vec![]);
do_sort(vm, &mut elements, key_func, reverse)?;
let temp_elements = elements_cell.replace(elements);
if !temp_elements.is_empty() {
return Err(vm.new_value_error("list modified during sort".to_string()));
}
Ok(vm.get_none())
}
fn list_contains(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
+3 -3
View File
@@ -1,8 +1,8 @@
use super::objstr;
use super::objtype;
use crate::pyobject::{
AttributeProtocol, IdProtocol, PyContext, PyFuncArgs, PyObject, PyObjectPayload, PyObjectRef,
PyResult, TypeProtocol,
AttributeProtocol, DictProtocol, IdProtocol, PyContext, PyFuncArgs, PyObject, PyObjectPayload,
PyObjectRef, PyResult, TypeProtocol,
};
use crate::vm::VirtualMachine;
use std::cell::RefCell;
@@ -182,7 +182,7 @@ fn object_dict(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
PyObjectPayload::Class { ref dict, .. } | PyObjectPayload::Instance { ref dict, .. } => {
let new_dict = vm.new_dict();
for (attr, value) in dict.borrow().iter() {
vm.ctx.set_item(&new_dict, &attr, value.clone());
new_dict.set_item(&vm.ctx, &attr, value.clone());
}
Ok(new_dict)
}
+8
View File
@@ -302,6 +302,14 @@ pub fn seq_mul(elements: &[PyObjectRef], product: &PyObjectRef) -> Vec<PyObjectR
new_elements
}
pub fn get_elements_cell<'a>(obj: &'a PyObjectRef) -> &'a RefCell<Vec<PyObjectRef>> {
if let PyObjectPayload::Sequence { ref elements } = obj.payload {
elements
} else {
panic!("Cannot extract elements from non-sequence");
}
}
pub fn get_elements<'a>(obj: &'a PyObjectRef) -> impl Deref<Target = Vec<PyObjectRef>> + 'a {
if let PyObjectPayload::Sequence { ref elements } = obj.payload {
elements.borrow()
+20 -1
View File
@@ -833,6 +833,7 @@ pub trait DictProtocol {
fn contains_key(&self, k: &str) -> bool;
fn get_item(&self, k: &str) -> Option<PyObjectRef>;
fn get_key_value_pairs(&self) -> Vec<(PyObjectRef, PyObjectRef)>;
fn set_item(&self, ctx: &PyContext, key: &str, v: PyObjectRef);
}
impl DictProtocol for PyObjectRef {
@@ -851,8 +852,9 @@ impl DictProtocol for PyObjectRef {
PyObjectPayload::Dict { ref elements } => {
objdict::content_get_key_str(&elements.borrow(), k)
}
PyObjectPayload::Module { ref dict, .. } => dict.get_item(k),
PyObjectPayload::Scope { ref scope } => scope.borrow().locals.get_item(k),
_ => panic!("TODO"),
ref k => panic!("TODO {:?}", k),
}
}
@@ -864,6 +866,23 @@ impl DictProtocol for PyObjectRef {
_ => panic!("TODO"),
}
}
// Item set/get:
fn set_item(&self, ctx: &PyContext, key: &str, v: PyObjectRef) {
match &self.payload {
PyObjectPayload::Dict { elements } => {
let key = ctx.new_str(key.to_string());
objdict::set_item_in_content(&mut elements.borrow_mut(), &key, &v);
}
PyObjectPayload::Module { dict, .. } => {
dict.set_item(ctx, key, v);
}
PyObjectPayload::Scope { scope, .. } => {
scope.borrow().locals.set_item(ctx, key, v);
}
ref k => panic!("TODO {:?}", k),
};
}
}
pub trait BufferProtocol {
+1 -1
View File
@@ -171,7 +171,7 @@ impl<'de> Visitor<'de> for PyObjectDeserializer<'de> {
PyObjectPayload::String { ref value } => value.clone(),
_ => unimplemented!("map keys must be strings"),
};
self.vm.ctx.set_item(&dict, &key, value);
dict.set_item(&self.vm.ctx, &key, value);
}
Ok(dict)
}
+2 -2
View File
@@ -1,4 +1,4 @@
use crate::pyobject::{PyContext, PyFuncArgs, PyObjectRef, PyResult, TypeProtocol};
use crate::pyobject::{DictProtocol, PyContext, PyFuncArgs, PyObjectRef, PyResult, TypeProtocol};
use crate::vm::VirtualMachine;
use std::rc::Rc;
use std::{env, mem};
@@ -132,7 +132,7 @@ settrace() -- set the global debug tracing function
"_getframe" => ctx.new_rustfunc(getframe),
});
ctx.set_item(&modules, sys_name, sys_mod.clone());
modules.set_item(&ctx, sys_name, sys_mod.clone());
ctx.set_attr(&sys_mod, "modules", modules);
sys_mod
+8 -2
View File
@@ -26,6 +26,7 @@ use crate::pyobject::{
};
use crate::stdlib;
use crate::sysmodule;
use num_bigint::ToBigInt;
// use objects::objects;
@@ -53,7 +54,7 @@ impl VirtualMachine {
// Add builtins as builtins module:
let modules = sysmod.get_attr("modules").unwrap();
ctx.set_item(&modules, "builtins", builtins.clone());
modules.set_item(&ctx, "builtins", builtins.clone());
let stdlib_inits = stdlib::get_module_inits();
VirtualMachine {
@@ -76,6 +77,11 @@ impl VirtualMachine {
self.ctx.new_str(s)
}
/// Create a new python int object.
pub fn new_int<T: ToBigInt>(&self, i: T) -> PyObjectRef {
self.ctx.new_int(i)
}
/// Create a new python bool object.
pub fn new_bool(&self, b: bool) -> PyObjectRef {
self.ctx.new_bool(b)
@@ -395,7 +401,7 @@ impl VirtualMachine {
self.ctx.set_attr(scope, &name, value);
} else if let Some(d) = &kwargs {
self.ctx.set_item(d, &name, value);
d.set_item(&self.ctx, &name, value);
} else {
return Err(
self.new_type_error(format!("Got an unexpected keyword argument '{}'", name))
+15 -9
View File
@@ -12,7 +12,11 @@ const editor = CodeMirror.fromTextArea(document.getElementById('code'), {
'Cmd-Enter': runCodeFromTextarea,
'Shift-Tab': 'indentLess',
'Ctrl-/': 'toggleComment',
'Cmd-/': 'toggleComment'
'Cmd-/': 'toggleComment',
Tab: editor => {
var spaces = Array(editor.getOption('indentUnit') + 1).join(' ');
editor.replaceSelection(spaces);
}
},
lineNumbers: true,
mode: 'text/x-python',
@@ -20,10 +24,10 @@ const editor = CodeMirror.fromTextArea(document.getElementById('code'), {
autofocus: true
});
function runCodeFromTextarea() {
const consoleElement = document.getElementById('console');
const errorElement = document.getElementById('error');
const consoleElement = document.getElementById('console');
const errorElement = document.getElementById('error');
function runCodeFromTextarea() {
// Clean the console and errors
consoleElement.value = '';
errorElement.textContent = '';
@@ -51,7 +55,7 @@ document
const snippets = document.getElementById('snippets');
snippets.addEventListener('change', () => {
const updateSnippet = () => {
const selected = snippets.value;
// the require here creates a webpack context; it's fine to use it
@@ -60,9 +64,11 @@ snippets.addEventListener('change', () => {
const snippet = require(`raw-loader!../snippets/${selected}.py`);
editor.setValue(snippet);
runCodeFromTextarea();
});
};
// Run once for demo
runCodeFromTextarea();
snippets.addEventListener('change', updateSnippet);
// Run once for demo (updateSnippet b/c the browser might try to keep the same
// option selected for the `select`, but the textarea won't be updated)
updateSnippet();
+1
View File
@@ -18,6 +18,7 @@ wasm-bindgen = "0.2"
wasm-bindgen-futures = "0.3"
js-sys = "0.3"
futures = "0.1"
num-traits = "0.2"
[dependencies.web-sys]
version = "0.3"
+7 -5
View File
@@ -1,6 +1,7 @@
use crate::{convert, vm_class::AccessibleVM, wasm_builtins::window};
use futures::Future;
use js_sys::Promise;
use num_traits::cast::ToPrimitive;
use rustpython_vm::obj::{objint, objstr};
use rustpython_vm::pyobject::{
PyContext, PyFuncArgs, PyObject, PyObjectPayload, PyObjectRef, PyResult, TypeProtocol,
@@ -139,11 +140,12 @@ fn browser_request_animation_frame(vm: &mut VirtualMachine, args: PyFuncArgs) ->
fn browser_cancel_animation_frame(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
arg_check!(vm, args, required = [(id, Some(vm.ctx.int_type()))]);
// questionable, but it's probably fine
let id = objint::get_value(id)
.to_string()
.parse()
.expect("bigint.to_string() to be parsable as i32");
let id = objint::get_value(id).to_i32().ok_or_else(|| {
vm.new_exception(
vm.ctx.exceptions.value_error.clone(),
"Integer too large to convert to i32 for animationFrame id".into(),
)
})?;
window()
.cancel_animation_frame(id)
+2 -3
View File
@@ -2,7 +2,7 @@ use crate::browser_module;
use crate::vm_class::{AccessibleVM, WASMVirtualMachine};
use js_sys::{Array, ArrayBuffer, Object, Promise, Reflect, Uint8Array};
use rustpython_vm::obj::{objbytes, objtype};
use rustpython_vm::pyobject::{self, PyFuncArgs, PyObjectRef, PyResult};
use rustpython_vm::pyobject::{self, DictProtocol, PyFuncArgs, PyObjectRef, PyResult};
use rustpython_vm::VirtualMachine;
use wasm_bindgen::{closure::Closure, prelude::*, JsCast};
@@ -147,8 +147,7 @@ pub fn js_to_py(vm: &mut VirtualMachine, js_val: JsValue) -> PyObjectRef {
for pair in object_entries(&Object::from(js_val)) {
let (key, val) = pair.expect("iteration over object to not fail");
let py_val = js_to_py(vm, val);
vm.ctx
.set_item(&dict, &String::from(js_sys::JsString::from(key)), py_val);
dict.set_item(&vm.ctx, &String::from(js_sys::JsString::from(key)), py_val);
}
dict
}
+10
View File
@@ -26,8 +26,18 @@ pub fn print_to_html(text: &str, selector: &str) -> Result<(), JsValue> {
let textarea = element
.dyn_ref::<HtmlTextAreaElement>()
.ok_or_else(|| js_sys::TypeError::new("Element must be a textarea"))?;
let value = textarea.value();
let scroll_height = textarea.scroll_height();
let scrolled_to_bottom = scroll_height - textarea.scroll_top() == textarea.client_height();
textarea.set_value(&format!("{}{}", value, text));
if scrolled_to_bottom {
textarea.scroll_with_x_and_y(0.0, scroll_height.into());
}
Ok(())
}