mirror of
https://github.com/RustPython/RustPython.git
synced 2026-10-29 03:04:38 +08:00
fix compile
This commit is contained in:
commit
0a2aa1e64b
53 files changed
+710
-582
No files matched your search
Generated
+35
-11
@@ -174,15 +174,6 @@ dependencies = [
|
||||
"bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "console_error_panic_hook"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"cfg-if 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"wasm-bindgen 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "constant_time_eq"
|
||||
version = "0.1.3"
|
||||
@@ -710,6 +701,23 @@ name = "rustc-demangle"
|
||||
version = "0.1.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "rustc_version"
|
||||
version = "0.2.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc_version_runtime"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustpython"
|
||||
version = "0.0.1"
|
||||
@@ -751,6 +759,7 @@ dependencies = [
|
||||
"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)",
|
||||
"rustc_version_runtime 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rustpython_parser 0.0.1",
|
||||
"serde 1.0.66 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_derive 1.0.66 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@@ -764,7 +773,6 @@ name = "rustpython_wasm"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"cfg-if 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"console_error_panic_hook 0.1.5 (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)",
|
||||
"rustpython_parser 0.0.1",
|
||||
@@ -800,6 +808,19 @@ name = "scoped_threadpool"
|
||||
version = "0.1.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "semver"
|
||||
version = "0.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "semver-parser"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.66"
|
||||
@@ -1223,7 +1244,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
"checksum cfg-if 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "405216fd8fe65f718daa7102ea808a946b6ce40c742998fbfd3463645552de18"
|
||||
"checksum clap 2.31.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f0f16b89cbb9ee36d87483dc939fe9f1e13c05898d56d7b230a0d4dff033a536"
|
||||
"checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f"
|
||||
"checksum console_error_panic_hook 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6c5dd2c094474ec60a6acaf31780af270275e3153bafff2db5995b715295762e"
|
||||
"checksum constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8ff012e225ce166d4422e0e78419d901719760f62ae2b7969ca6b564d1b54a9e"
|
||||
"checksum diff 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "3c2b69f912779fbb121ceb775d74d51e915af17aaebc38d28a592843a2dd0a3a"
|
||||
"checksum digest 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "00a49051fef47a72c9623101b19bd71924a45cca838826caae3eaa4d00772603"
|
||||
@@ -1288,9 +1308,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
"checksum regex-syntax 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7d707a4fa2637f2dca2ef9fd02225ec7661fe01a53623c1e6515b6916511f7a7"
|
||||
"checksum regex-syntax 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8f1ac0f60d675cc6cf13a20ec076568254472551051ad5dd050364d70671bf6b"
|
||||
"checksum rustc-demangle 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "bcfe5b13211b4d78e5c2cadfebd7769197d95c639c35a50057eb4c05de811395"
|
||||
"checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
|
||||
"checksum rustc_version_runtime 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6de8ecd7fad7731f306f69b6e10ec5a3178c61e464dcc06979427aa4cc891145"
|
||||
"checksum rustyline 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6010155119d53aac4f5b987cb8f6ea913d0d64d9b237da36f8f96a90cb3f5385"
|
||||
"checksum ryu 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "eb9e9b8cde282a9fe6a42dd4681319bfb63f121b8a8ee9439c6f4107e58a46f7"
|
||||
"checksum scoped_threadpool 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "1d51f5df5af43ab3f1360b429fa5e0152ac5ce8c0bd6485cae490332e96846a8"
|
||||
"checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403"
|
||||
"checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
|
||||
"checksum serde 1.0.66 (registry+https://github.com/rust-lang/crates.io-index)" = "e9a2d9a9ac5120e0f768801ca2b58ad6eec929dc9d1d616c162f208869c2ce95"
|
||||
"checksum serde_derive 1.0.66 (registry+https://github.com/rust-lang/crates.io-index)" = "0a90213fa7e0f5eac3f7afe2d5ff6b088af515052cc7303bd68c7e3b91a3fb79"
|
||||
"checksum serde_json 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)" = "44dd2cfde475037451fa99b7e5df77aa3cfd1536575fa8e7a538ab36dcde49ae"
|
||||
|
||||
@@ -1,10 +1,34 @@
|
||||
import dis
|
||||
|
||||
dis.disassemble(compile("5 + x + 5 or 2", "", "eval"))
|
||||
dis.dis(compile("5 + x + 5 or 2", "", "eval"))
|
||||
print("\n")
|
||||
dis.disassemble(compile("def f(x):\n return 1", "", "exec"))
|
||||
dis.dis(compile("def f(x):\n return 1", "", "exec"))
|
||||
print("\n")
|
||||
dis.disassemble(compile("if a:\n 1 or 2\nelif x == 'hello':\n 3\nelse:\n 4", "", "exec"))
|
||||
dis.dis(compile("if a:\n 1 or 2\nelif x == 'hello':\n 3\nelse:\n 4", "", "exec"))
|
||||
print("\n")
|
||||
dis.disassemble(compile("f(x=1, y=2)", "", "eval"))
|
||||
dis.dis(compile("f(x=1, y=2)", "", "eval"))
|
||||
print("\n")
|
||||
|
||||
def f():
|
||||
with g():
|
||||
try:
|
||||
for a in {1: 4, 2: 5}:
|
||||
yield [True and False or True, []]
|
||||
except Exception:
|
||||
raise not ValueError({1 for i in [1,2,3]})
|
||||
|
||||
dis.dis(f)
|
||||
|
||||
class A(object):
|
||||
def f():
|
||||
x += 1
|
||||
pass
|
||||
def g():
|
||||
for i in range(5):
|
||||
if i:
|
||||
continue
|
||||
else:
|
||||
break
|
||||
|
||||
print("A.f\n")
|
||||
dis.dis(A.f)
|
||||
@@ -18,6 +18,7 @@ serde_derive = "1.0.66"
|
||||
serde_json = "1.0.26"
|
||||
byteorder = "1.2.6"
|
||||
regex = "1"
|
||||
rustc_version_runtime = "0.1.*"
|
||||
statrs = "0.10.0"
|
||||
caseless = "0.2.1"
|
||||
unicode-segmentation = "1.2.1"
|
||||
|
||||
+4
-1
@@ -3,6 +3,7 @@
|
||||
//! Implements functions listed here: https://docs.python.org/3/library/builtins.html
|
||||
|
||||
// use std::ops::Deref;
|
||||
use std::cell::RefCell;
|
||||
use std::char;
|
||||
use std::io::{self, Write};
|
||||
|
||||
@@ -273,7 +274,9 @@ fn make_scope(vm: &mut VirtualMachine, locals: Option<&PyObjectRef>) -> PyObject
|
||||
};
|
||||
|
||||
PyObject {
|
||||
payload: PyObjectPayload::Scope { scope: scope_inner },
|
||||
payload: PyObjectPayload::Scope {
|
||||
scope: RefCell::new(scope_inner),
|
||||
},
|
||||
typ: None,
|
||||
}
|
||||
.into_ref()
|
||||
|
||||
+28
-7
@@ -17,6 +17,7 @@ struct Compiler {
|
||||
source_path: Option<String>,
|
||||
current_source_location: ast::Location,
|
||||
in_loop: bool,
|
||||
in_function_def: bool,
|
||||
}
|
||||
|
||||
/// Compile a given sourcecode into a bytecode object.
|
||||
@@ -75,6 +76,7 @@ impl Compiler {
|
||||
source_path: None,
|
||||
current_source_location: ast::Location::default(),
|
||||
in_loop: false,
|
||||
in_function_def: false,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -232,9 +234,10 @@ impl Compiler {
|
||||
|
||||
self.compile_test(test, None, Some(else_label), EvalContext::Statement)?;
|
||||
|
||||
let was_in_loop = self.in_loop;
|
||||
self.in_loop = true;
|
||||
self.compile_statements(body)?;
|
||||
self.in_loop = false;
|
||||
self.in_loop = was_in_loop;
|
||||
self.emit(Instruction::Jump {
|
||||
target: start_label,
|
||||
});
|
||||
@@ -295,10 +298,10 @@ impl Compiler {
|
||||
// Start of loop iteration, set targets:
|
||||
self.compile_store(target)?;
|
||||
|
||||
// Body of loop:
|
||||
let was_in_loop = self.in_loop;
|
||||
self.in_loop = true;
|
||||
self.compile_statements(body)?;
|
||||
self.in_loop = false;
|
||||
self.in_loop = was_in_loop;
|
||||
|
||||
self.emit(Instruction::Jump {
|
||||
target: start_label,
|
||||
@@ -431,6 +434,11 @@ impl Compiler {
|
||||
decorator_list,
|
||||
} => {
|
||||
// Create bytecode for this function:
|
||||
// remember to restore self.in_loop to the original after the function is compiled
|
||||
let was_in_loop = self.in_loop;
|
||||
let was_in_function_def = self.in_function_def;
|
||||
self.in_loop = false;
|
||||
self.in_function_def = true;
|
||||
let flags = self.enter_function(name, args)?;
|
||||
self.compile_statements(body)?;
|
||||
|
||||
@@ -458,6 +466,8 @@ impl Compiler {
|
||||
self.emit(Instruction::StoreName {
|
||||
name: name.to_string(),
|
||||
});
|
||||
self.in_loop = was_in_loop;
|
||||
self.in_function_def = was_in_function_def;
|
||||
}
|
||||
ast::Statement::ClassDef {
|
||||
name,
|
||||
@@ -466,6 +476,8 @@ impl Compiler {
|
||||
keywords,
|
||||
decorator_list,
|
||||
} => {
|
||||
let was_in_loop = self.in_loop;
|
||||
self.in_loop = false;
|
||||
self.prepare_decorators(decorator_list)?;
|
||||
self.emit(Instruction::LoadBuildClass);
|
||||
let line_number = self.get_source_line_number();
|
||||
@@ -546,6 +558,7 @@ impl Compiler {
|
||||
self.emit(Instruction::StoreName {
|
||||
name: name.to_string(),
|
||||
});
|
||||
self.in_loop = was_in_loop;
|
||||
}
|
||||
ast::Statement::Assert { test, msg } => {
|
||||
// TODO: if some flag, ignore all assert statements!
|
||||
@@ -584,6 +597,9 @@ impl Compiler {
|
||||
self.emit(Instruction::Continue);
|
||||
}
|
||||
ast::Statement::Return { value } => {
|
||||
if !self.in_function_def {
|
||||
return Err(CompileError::InvalidReturn);
|
||||
}
|
||||
match value {
|
||||
Some(e) => {
|
||||
let size = e.len();
|
||||
@@ -663,7 +679,6 @@ impl Compiler {
|
||||
name: &str,
|
||||
args: &ast::Parameters,
|
||||
) -> Result<bytecode::FunctionOpArg, CompileError> {
|
||||
self.in_loop = false;
|
||||
let have_kwargs = !args.defaults.is_empty();
|
||||
if have_kwargs {
|
||||
// Construct a tuple:
|
||||
@@ -971,6 +986,9 @@ impl Compiler {
|
||||
self.emit(Instruction::BuildSlice { size });
|
||||
}
|
||||
ast::Expression::Yield { value } => {
|
||||
if !self.in_function_def {
|
||||
return Err(CompileError::InvalidYield);
|
||||
}
|
||||
self.mark_generator();
|
||||
match value {
|
||||
Some(expression) => self.compile_expression(expression)?,
|
||||
@@ -1021,6 +1039,7 @@ impl Compiler {
|
||||
}
|
||||
ast::Expression::Lambda { args, body } => {
|
||||
let name = "<lambda>".to_string();
|
||||
// no need to worry about the self.loop_depth because there are no loops in lambda expressions
|
||||
let flags = self.enter_function(&name, args)?;
|
||||
self.compile_expression(body)?;
|
||||
self.emit(Instruction::ReturnValue);
|
||||
@@ -1369,10 +1388,11 @@ impl Compiler {
|
||||
|
||||
// Low level helper functions:
|
||||
fn emit(&mut self, instruction: Instruction) {
|
||||
self.current_code_object().instructions.push(instruction);
|
||||
// TODO: insert source filename
|
||||
let location = self.current_source_location.clone();
|
||||
self.current_code_object().locations.push(location);
|
||||
let cur_code_obj = self.current_code_object();
|
||||
cur_code_obj.instructions.push(instruction);
|
||||
cur_code_obj.locations.push(location);
|
||||
// TODO: insert source filename
|
||||
}
|
||||
|
||||
fn current_code_object(&mut self) -> &mut CodeObject {
|
||||
@@ -1413,6 +1433,7 @@ mod tests {
|
||||
use crate::bytecode::Constant::*;
|
||||
use crate::bytecode::Instruction::*;
|
||||
use rustpython_parser::parser;
|
||||
|
||||
fn compile_exec(source: &str) -> CodeObject {
|
||||
let mut compiler = Compiler::new();
|
||||
compiler.source_path = Some("source_path".to_string());
|
||||
|
||||
+6
-2
@@ -19,6 +19,8 @@ pub enum CompileError {
|
||||
InvalidBreak,
|
||||
/// Continue statement outside of loop.
|
||||
InvalidContinue,
|
||||
InvalidReturn,
|
||||
InvalidYield,
|
||||
}
|
||||
|
||||
impl fmt::Display for CompileError {
|
||||
@@ -29,8 +31,10 @@ impl fmt::Display for CompileError {
|
||||
CompileError::ExpectExpr => write!(f, "Expecting expression, got statement"),
|
||||
CompileError::Parse(err) => write!(f, "{}", err),
|
||||
CompileError::StarArgs => write!(f, "Two starred expressions in assignment"),
|
||||
CompileError::InvalidBreak => write!(f, "break outside loop"),
|
||||
CompileError::InvalidContinue => write!(f, "continue outside loop"),
|
||||
CompileError::InvalidBreak => write!(f, "'break' outside loop"),
|
||||
CompileError::InvalidContinue => write!(f, "'continue' outside loop"),
|
||||
CompileError::InvalidReturn => write!(f, "'return' outside function"),
|
||||
CompileError::InvalidYield => write!(f, "'yield' outside function"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+13
-13
@@ -281,7 +281,7 @@ impl Frame {
|
||||
|
||||
let mut out: Vec<Option<BigInt>> = elements
|
||||
.into_iter()
|
||||
.map(|x| match x.borrow().payload {
|
||||
.map(|x| match x.payload {
|
||||
PyObjectPayload::Integer { ref value } => Some(value.clone()),
|
||||
PyObjectPayload::None => None,
|
||||
_ => panic!("Expect Int or None as BUILD_SLICE arguments, got {:?}", x),
|
||||
@@ -531,7 +531,7 @@ impl Frame {
|
||||
} else {
|
||||
let msg = format!(
|
||||
"Can only raise BaseException derived types, not {}",
|
||||
exception.borrow()
|
||||
exception
|
||||
);
|
||||
let type_error_type = vm.ctx.exceptions.type_error.clone();
|
||||
let type_error = vm.new_exception(type_error_type, msg);
|
||||
@@ -564,7 +564,7 @@ impl Frame {
|
||||
}
|
||||
bytecode::Instruction::PrintExpr => {
|
||||
let expr = self.pop_value();
|
||||
match expr.borrow().payload {
|
||||
match expr.payload {
|
||||
PyObjectPayload::None => (),
|
||||
_ => {
|
||||
let repr = vm.to_repr(&expr)?;
|
||||
@@ -591,9 +591,9 @@ impl Frame {
|
||||
}
|
||||
bytecode::Instruction::StoreLocals => {
|
||||
let locals = self.pop_value();
|
||||
match self.locals.borrow_mut().payload {
|
||||
PyObjectPayload::Scope { ref mut scope } => {
|
||||
scope.locals = locals;
|
||||
match self.locals.payload {
|
||||
PyObjectPayload::Scope { ref scope } => {
|
||||
(*scope.borrow_mut()).locals = locals;
|
||||
}
|
||||
_ => panic!("We really expect our scope to be a scope!"),
|
||||
}
|
||||
@@ -854,8 +854,8 @@ impl Frame {
|
||||
}
|
||||
|
||||
fn delete_name(&mut self, vm: &mut VirtualMachine, name: &str) -> FrameResult {
|
||||
let locals = match self.locals.borrow().payload {
|
||||
PyObjectPayload::Scope { ref scope } => scope.locals.clone(),
|
||||
let locals = match self.locals.payload {
|
||||
PyObjectPayload::Scope { ref scope } => scope.borrow().locals.clone(),
|
||||
_ => panic!("We really expect our scope to be a scope!"),
|
||||
};
|
||||
|
||||
@@ -1127,7 +1127,7 @@ impl fmt::Debug for Frame {
|
||||
let stack_str = self
|
||||
.stack
|
||||
.iter()
|
||||
.map(|elem| format!("\n > {:?}", elem.borrow()))
|
||||
.map(|elem| format!("\n > {:?}", elem))
|
||||
.collect::<Vec<_>>()
|
||||
.join("");
|
||||
let block_str = self
|
||||
@@ -1136,12 +1136,12 @@ impl fmt::Debug for Frame {
|
||||
.map(|elem| format!("\n > {:?}", elem))
|
||||
.collect::<Vec<_>>()
|
||||
.join("");
|
||||
let local_str = match self.locals.borrow().payload {
|
||||
PyObjectPayload::Scope { ref scope } => match scope.locals.borrow().payload {
|
||||
let local_str = match self.locals.payload {
|
||||
PyObjectPayload::Scope { ref scope } => match scope.borrow().locals.payload {
|
||||
PyObjectPayload::Dict { ref elements } => {
|
||||
objdict::get_key_value_pairs_from_content(elements)
|
||||
objdict::get_key_value_pairs_from_content(&elements.borrow())
|
||||
.iter()
|
||||
.map(|elem| format!("\n {:?} = {:?}", elem.0.borrow(), elem.1.borrow()))
|
||||
.map(|elem| format!("\n {:?} = {:?}", elem.0, elem.1))
|
||||
.collect::<Vec<_>>()
|
||||
.join("")
|
||||
}
|
||||
|
||||
@@ -12,17 +12,17 @@ impl IntoPyObject for bool {
|
||||
}
|
||||
|
||||
pub fn boolval(vm: &mut VirtualMachine, obj: PyObjectRef) -> Result<bool, PyObjectRef> {
|
||||
let result = match obj.borrow().payload {
|
||||
let result = match obj.payload {
|
||||
PyObjectPayload::Integer { ref value } => !value.is_zero(),
|
||||
PyObjectPayload::Float { value } => value != 0.0,
|
||||
PyObjectPayload::Sequence { ref elements } => !elements.is_empty(),
|
||||
PyObjectPayload::Dict { ref elements } => !elements.is_empty(),
|
||||
PyObjectPayload::Sequence { ref elements } => !elements.borrow().is_empty(),
|
||||
PyObjectPayload::Dict { ref elements } => !elements.borrow().is_empty(),
|
||||
PyObjectPayload::String { ref value } => !value.is_empty(),
|
||||
PyObjectPayload::None { .. } => false,
|
||||
_ => {
|
||||
if let Ok(f) = vm.get_method(obj.clone(), "__bool__") {
|
||||
let bool_res = vm.invoke(f, PyFuncArgs::default())?;
|
||||
let v = match bool_res.borrow().payload {
|
||||
let v = match bool_res.payload {
|
||||
PyObjectPayload::Integer { ref value } => !value.is_zero(),
|
||||
_ => return Err(vm.new_type_error(String::from("TypeError"))),
|
||||
};
|
||||
@@ -60,7 +60,7 @@ pub fn not(vm: &mut VirtualMachine, obj: &PyObjectRef) -> PyResult {
|
||||
|
||||
// Retrieve inner int value:
|
||||
pub fn get_value(obj: &PyObjectRef) -> bool {
|
||||
if let PyObjectPayload::Integer { value } = &obj.borrow().payload {
|
||||
if let PyObjectPayload::Integer { value } = &obj.payload {
|
||||
!value.is_zero()
|
||||
} else {
|
||||
panic!("Inner error getting inner boolean");
|
||||
|
||||
+13
-13
@@ -1,5 +1,7 @@
|
||||
//! Implementation of the python bytearray object.
|
||||
|
||||
use std::cell::RefCell;
|
||||
|
||||
use crate::pyobject::{PyContext, PyFuncArgs, PyObject, PyObjectPayload, PyResult, TypeProtocol};
|
||||
|
||||
use super::objint;
|
||||
@@ -140,7 +142,12 @@ fn bytearray_new(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
} else {
|
||||
vec![]
|
||||
};
|
||||
Ok(PyObject::new(PyObjectPayload::Bytes { value }, cls.clone()))
|
||||
Ok(PyObject::new(
|
||||
PyObjectPayload::Bytes {
|
||||
value: RefCell::new(value),
|
||||
},
|
||||
cls.clone(),
|
||||
))
|
||||
}
|
||||
|
||||
fn bytesarray_len(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
@@ -283,10 +290,9 @@ fn bytearray_repr(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
|
||||
fn bytearray_clear(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
arg_check!(vm, args, required = [(zelf, Some(vm.ctx.bytearray_type()))]);
|
||||
let mut mut_obj = zelf.borrow_mut();
|
||||
match mut_obj.payload {
|
||||
PyObjectPayload::Bytes { ref mut value } => {
|
||||
value.clear();
|
||||
match zelf.payload {
|
||||
PyObjectPayload::Bytes { ref value } => {
|
||||
value.borrow_mut().clear();
|
||||
Ok(vm.get_none())
|
||||
}
|
||||
_ => panic!("Bytearray has incorrect payload."),
|
||||
@@ -307,17 +313,11 @@ fn bytearray_pop(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
fn bytearray_lower(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
arg_check!(vm, args, required = [(obj, Some(vm.ctx.bytearray_type()))]);
|
||||
let value = get_value(obj).to_vec().to_ascii_lowercase();
|
||||
Ok(PyObject::new(
|
||||
PyObjectPayload::Bytes { value },
|
||||
vm.ctx.bytearray_type(),
|
||||
))
|
||||
Ok(vm.ctx.new_bytearray(value))
|
||||
}
|
||||
|
||||
fn bytearray_upper(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
arg_check!(vm, args, required = [(obj, Some(vm.ctx.bytearray_type()))]);
|
||||
let value = get_value(obj).to_vec().to_ascii_uppercase();
|
||||
Ok(PyObject::new(
|
||||
PyObjectPayload::Bytes { value },
|
||||
vm.ctx.bytearray_type(),
|
||||
))
|
||||
Ok(vm.ctx.new_bytearray(value))
|
||||
}
|
||||
+26
-41
@@ -1,3 +1,8 @@
|
||||
use std::cell::{Cell, RefCell};
|
||||
use std::hash::{Hash, Hasher};
|
||||
use std::ops::Deref;
|
||||
use std::ops::DerefMut;
|
||||
|
||||
use super::objint;
|
||||
use super::objtype;
|
||||
use crate::pyobject::{
|
||||
@@ -5,11 +10,6 @@ use crate::pyobject::{
|
||||
};
|
||||
use crate::vm::VirtualMachine;
|
||||
use num_traits::ToPrimitive;
|
||||
use std::cell::Ref;
|
||||
use std::cell::RefMut;
|
||||
use std::hash::{Hash, Hasher};
|
||||
use std::ops::Deref;
|
||||
use std::ops::DerefMut;
|
||||
|
||||
// Binary data support
|
||||
|
||||
@@ -70,7 +70,12 @@ fn bytes_new(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
vec![]
|
||||
};
|
||||
|
||||
Ok(PyObject::new(PyObjectPayload::Bytes { value }, cls.clone()))
|
||||
Ok(PyObject::new(
|
||||
PyObjectPayload::Bytes {
|
||||
value: RefCell::new(value),
|
||||
},
|
||||
cls.clone(),
|
||||
))
|
||||
}
|
||||
|
||||
fn bytes_eq(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
@@ -98,11 +103,7 @@ fn bytes_ge(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
let result = if objtype::isinstance(b, &vm.ctx.bytes_type()) {
|
||||
get_value(a).to_vec() >= get_value(b).to_vec()
|
||||
} else {
|
||||
return Err(vm.new_type_error(format!(
|
||||
"Cannot compare {} and {} using '>'",
|
||||
a.borrow(),
|
||||
b.borrow()
|
||||
)));
|
||||
return Err(vm.new_type_error(format!("Cannot compare {} and {} using '>'", a, b)));
|
||||
};
|
||||
Ok(vm.ctx.new_bool(result))
|
||||
}
|
||||
@@ -117,11 +118,7 @@ fn bytes_gt(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
let result = if objtype::isinstance(b, &vm.ctx.bytes_type()) {
|
||||
get_value(a).to_vec() > get_value(b).to_vec()
|
||||
} else {
|
||||
return Err(vm.new_type_error(format!(
|
||||
"Cannot compare {} and {} using '>='",
|
||||
a.borrow(),
|
||||
b.borrow()
|
||||
)));
|
||||
return Err(vm.new_type_error(format!("Cannot compare {} and {} using '>='", a, b)));
|
||||
};
|
||||
Ok(vm.ctx.new_bool(result))
|
||||
}
|
||||
@@ -136,11 +133,7 @@ fn bytes_le(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
let result = if objtype::isinstance(b, &vm.ctx.bytes_type()) {
|
||||
get_value(a).to_vec() <= get_value(b).to_vec()
|
||||
} else {
|
||||
return Err(vm.new_type_error(format!(
|
||||
"Cannot compare {} and {} using '<'",
|
||||
a.borrow(),
|
||||
b.borrow()
|
||||
)));
|
||||
return Err(vm.new_type_error(format!("Cannot compare {} and {} using '<'", a, b)));
|
||||
};
|
||||
Ok(vm.ctx.new_bool(result))
|
||||
}
|
||||
@@ -155,11 +148,7 @@ fn bytes_lt(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
let result = if objtype::isinstance(b, &vm.ctx.bytes_type()) {
|
||||
get_value(a).to_vec() < get_value(b).to_vec()
|
||||
} else {
|
||||
return Err(vm.new_type_error(format!(
|
||||
"Cannot compare {} and {} using '<='",
|
||||
a.borrow(),
|
||||
b.borrow()
|
||||
)));
|
||||
return Err(vm.new_type_error(format!("Cannot compare {} and {} using '<='", a, b)));
|
||||
};
|
||||
Ok(vm.ctx.new_bool(result))
|
||||
}
|
||||
@@ -181,23 +170,19 @@ fn bytes_hash(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
}
|
||||
|
||||
pub fn get_value<'a>(obj: &'a PyObjectRef) -> impl Deref<Target = Vec<u8>> + 'a {
|
||||
Ref::map(obj.borrow(), |py_obj| {
|
||||
if let PyObjectPayload::Bytes { ref value } = py_obj.payload {
|
||||
value
|
||||
} else {
|
||||
panic!("Inner error getting bytearray {:?}", obj);
|
||||
}
|
||||
})
|
||||
if let PyObjectPayload::Bytes { ref value } = obj.payload {
|
||||
value.borrow()
|
||||
} else {
|
||||
panic!("Inner error getting bytearray {:?}", obj);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_mut_value<'a>(obj: &'a PyObjectRef) -> impl DerefMut<Target = Vec<u8>> + 'a {
|
||||
RefMut::map(obj.borrow_mut(), |py_obj| {
|
||||
if let PyObjectPayload::Bytes { ref mut value } = py_obj.payload {
|
||||
value
|
||||
} else {
|
||||
panic!("Inner error getting bytearray {:?}", obj);
|
||||
}
|
||||
})
|
||||
if let PyObjectPayload::Bytes { ref value } = obj.payload {
|
||||
value.borrow_mut()
|
||||
} else {
|
||||
panic!("Inner error getting bytearray {:?}", obj);
|
||||
}
|
||||
}
|
||||
|
||||
fn bytes_repr(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
@@ -212,7 +197,7 @@ fn bytes_iter(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
|
||||
let iter_obj = PyObject::new(
|
||||
PyObjectPayload::Iterator {
|
||||
position: 0,
|
||||
position: Cell::new(0),
|
||||
iterated_obj: obj.clone(),
|
||||
},
|
||||
vm.ctx.iter_type(),
|
||||
|
||||
@@ -29,7 +29,7 @@ pub fn init(context: &PyContext) {
|
||||
}
|
||||
|
||||
pub fn get_value(obj: &PyObjectRef) -> bytecode::CodeObject {
|
||||
if let PyObjectPayload::Code { code } = &obj.borrow().payload {
|
||||
if let PyObjectPayload::Code { code } = &obj.payload {
|
||||
code.clone()
|
||||
} else {
|
||||
panic!("Inner error getting code {:?}", obj)
|
||||
|
||||
@@ -45,7 +45,7 @@ pub fn init(context: &PyContext) {
|
||||
}
|
||||
|
||||
pub fn get_value(obj: &PyObjectRef) -> Complex64 {
|
||||
if let PyObjectPayload::Complex { value } = &obj.borrow().payload {
|
||||
if let PyObjectPayload::Complex { value } = &obj.payload {
|
||||
*value
|
||||
} else {
|
||||
panic!("Inner error getting complex");
|
||||
@@ -117,7 +117,7 @@ fn complex_add(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
v1.im,
|
||||
)))
|
||||
} else {
|
||||
Err(vm.new_type_error(format!("Cannot add {} and {}", i.borrow(), i2.borrow())))
|
||||
Err(vm.new_type_error(format!("Cannot add {} and {}", i, i2)))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -136,7 +136,7 @@ fn complex_radd(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
v1.im,
|
||||
)))
|
||||
} else {
|
||||
Err(vm.new_type_error(format!("Cannot add {} and {}", i.borrow(), i2.borrow())))
|
||||
Err(vm.new_type_error(format!("Cannot add {} and {}", i, i2)))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+26
-25
@@ -1,3 +1,7 @@
|
||||
use std::cell::{Cell, RefCell};
|
||||
use std::collections::HashMap;
|
||||
use std::ops::{Deref, DerefMut};
|
||||
|
||||
use super::objiter;
|
||||
use super::objstr;
|
||||
use super::objtype;
|
||||
@@ -6,9 +10,6 @@ use crate::pyobject::{
|
||||
TypeProtocol,
|
||||
};
|
||||
use crate::vm::{ReprGuard, VirtualMachine};
|
||||
use std::cell::{Ref, RefCell, RefMut};
|
||||
use std::collections::HashMap;
|
||||
use std::ops::{Deref, DerefMut};
|
||||
|
||||
// This typedef abstracts the actual dict type used.
|
||||
// pub type DictContentType = HashMap<usize, Vec<(PyObjectRef, PyObjectRef)>>;
|
||||
@@ -19,30 +20,26 @@ pub type DictContentType = HashMap<String, (PyObjectRef, PyObjectRef)>;
|
||||
pub fn new(dict_type: PyObjectRef) -> PyObjectRef {
|
||||
PyObject::new(
|
||||
PyObjectPayload::Dict {
|
||||
elements: HashMap::new(),
|
||||
elements: RefCell::new(HashMap::new()),
|
||||
},
|
||||
dict_type.clone(),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn get_elements<'a>(obj: &'a PyObjectRef) -> impl Deref<Target = DictContentType> + 'a {
|
||||
Ref::map(obj.borrow(), |py_obj| {
|
||||
if let PyObjectPayload::Dict { ref elements } = py_obj.payload {
|
||||
elements
|
||||
} else {
|
||||
panic!("Cannot extract dict elements");
|
||||
}
|
||||
})
|
||||
if let PyObjectPayload::Dict { ref elements } = obj.payload {
|
||||
elements.borrow()
|
||||
} else {
|
||||
panic!("Cannot extract dict elements");
|
||||
}
|
||||
}
|
||||
|
||||
fn get_mut_elements<'a>(obj: &'a PyObjectRef) -> impl DerefMut<Target = DictContentType> + 'a {
|
||||
RefMut::map(obj.borrow_mut(), |py_obj| {
|
||||
if let PyObjectPayload::Dict { ref mut elements } = py_obj.payload {
|
||||
elements
|
||||
} else {
|
||||
panic!("Cannot extract dict elements");
|
||||
}
|
||||
})
|
||||
if let PyObjectPayload::Dict { ref elements } = obj.payload {
|
||||
elements.borrow_mut()
|
||||
} else {
|
||||
panic!("Cannot extract dict elements");
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_item(
|
||||
@@ -262,7 +259,7 @@ fn dict_iter(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
|
||||
let iter_obj = PyObject::new(
|
||||
PyObjectPayload::Iterator {
|
||||
position: 0,
|
||||
position: Cell::new(0),
|
||||
iterated_obj: key_list,
|
||||
},
|
||||
vm.ctx.iter_type(),
|
||||
@@ -309,12 +306,16 @@ fn dict_getitem(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
}
|
||||
|
||||
pub fn create_type(type_type: PyObjectRef, object_type: PyObjectRef, dict_type: PyObjectRef) {
|
||||
(*dict_type.borrow_mut()).payload = PyObjectPayload::Class {
|
||||
name: String::from("dict"),
|
||||
dict: RefCell::new(HashMap::new()),
|
||||
mro: vec![object_type],
|
||||
};
|
||||
(*dict_type.borrow_mut()).typ = Some(type_type.clone());
|
||||
// this is not ideal
|
||||
let ptr = PyObjectRef::into_raw(dict_type.clone()) as *mut PyObject;
|
||||
unsafe {
|
||||
(*ptr).payload = PyObjectPayload::Class {
|
||||
name: String::from("dict"),
|
||||
dict: RefCell::new(HashMap::new()),
|
||||
mro: vec![object_type],
|
||||
};
|
||||
(*ptr).typ = Some(type_type.clone());
|
||||
}
|
||||
}
|
||||
|
||||
pub fn init(context: &PyContext) {
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
use std::cell::RefCell;
|
||||
use std::ops::AddAssign;
|
||||
|
||||
use super::objint;
|
||||
use super::objiter;
|
||||
use crate::pyobject::{PyContext, PyFuncArgs, PyObject, PyObjectPayload, PyResult, TypeProtocol};
|
||||
use crate::vm::VirtualMachine;
|
||||
use num_bigint::BigInt;
|
||||
use num_traits::Zero;
|
||||
use std::ops::AddAssign;
|
||||
|
||||
fn enumerate_new(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
arg_check!(
|
||||
@@ -20,7 +22,10 @@ fn enumerate_new(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
};
|
||||
let iterator = objiter::get_iter(vm, iterable)?;
|
||||
Ok(PyObject::new(
|
||||
PyObjectPayload::EnumerateIterator { counter, iterator },
|
||||
PyObjectPayload::EnumerateIterator {
|
||||
counter: RefCell::new(counter),
|
||||
iterator,
|
||||
},
|
||||
cls.clone(),
|
||||
))
|
||||
}
|
||||
@@ -33,16 +38,16 @@ fn enumerate_next(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
);
|
||||
|
||||
if let PyObjectPayload::EnumerateIterator {
|
||||
ref mut counter,
|
||||
ref mut iterator,
|
||||
} = enumerate.borrow_mut().payload
|
||||
ref counter,
|
||||
ref iterator,
|
||||
} = enumerate.payload
|
||||
{
|
||||
let next_obj = objiter::call_next(vm, iterator)?;
|
||||
let result = vm
|
||||
.ctx
|
||||
.new_tuple(vec![vm.ctx.new_int(counter.clone()), next_obj]);
|
||||
.new_tuple(vec![vm.ctx.new_int(counter.borrow().clone()), next_obj]);
|
||||
|
||||
AddAssign::add_assign(counter, 1);
|
||||
AddAssign::add_assign(&mut counter.borrow_mut() as &mut BigInt, 1);
|
||||
|
||||
Ok(result)
|
||||
} else {
|
||||
|
||||
@@ -25,9 +25,9 @@ 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
|
||||
ref predicate,
|
||||
ref iterator,
|
||||
} = filter.payload
|
||||
{
|
||||
loop {
|
||||
let next_obj = objiter::call_next(vm, iterator)?;
|
||||
|
||||
+9
-19
@@ -3,7 +3,7 @@ use super::objint;
|
||||
use super::objstr;
|
||||
use super::objtype;
|
||||
use crate::pyobject::{
|
||||
PyContext, PyFuncArgs, PyObjectPayload, PyObjectRef, PyResult, TypeProtocol,
|
||||
PyContext, PyFuncArgs, PyObject, PyObjectPayload, PyObjectRef, PyResult, TypeProtocol,
|
||||
};
|
||||
use crate::vm::VirtualMachine;
|
||||
use num_bigint::ToBigInt;
|
||||
@@ -15,14 +15,9 @@ fn float_repr(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
Ok(vm.new_str(v.to_string()))
|
||||
}
|
||||
|
||||
// __init__()
|
||||
fn float_init(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
arg_check!(
|
||||
vm,
|
||||
args,
|
||||
required = [(zelf, Some(vm.ctx.float_type())), (arg, None)]
|
||||
);
|
||||
let val = if objtype::isinstance(arg, &vm.ctx.float_type()) {
|
||||
fn float_new(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
arg_check!(vm, args, required = [(cls, None), (arg, None)]);
|
||||
let value = if objtype::isinstance(arg, &vm.ctx.float_type()) {
|
||||
get_value(arg)
|
||||
} else if objtype::isinstance(arg, &vm.ctx.int_type()) {
|
||||
match objint::get_value(arg).to_f64() {
|
||||
@@ -55,16 +50,15 @@ fn float_init(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
let type_name = objtype::get_type_name(&arg.typ());
|
||||
return Err(vm.new_type_error(format!("can't convert {} to float", type_name)));
|
||||
};
|
||||
set_value(zelf, val);
|
||||
Ok(vm.get_none())
|
||||
Ok(PyObject::new(PyObjectPayload::Float { value }, cls.clone()))
|
||||
}
|
||||
|
||||
// Retrieve inner float value:
|
||||
pub fn get_value(obj: &PyObjectRef) -> f64 {
|
||||
if let PyObjectPayload::Float { value } = &obj.borrow().payload {
|
||||
if let PyObjectPayload::Float { value } = &obj.payload {
|
||||
*value
|
||||
} else {
|
||||
panic!("Inner error getting float");
|
||||
panic!("Inner error getting float: {}", obj);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -81,14 +75,10 @@ pub fn make_float(vm: &mut VirtualMachine, obj: &PyObjectRef) -> Result<f64, PyO
|
||||
)?;
|
||||
Ok(get_value(&res))
|
||||
} else {
|
||||
Err(vm.new_type_error(format!("Cannot cast {} to float", obj.borrow())))
|
||||
Err(vm.new_type_error(format!("Cannot cast {} to float", obj)))
|
||||
}
|
||||
}
|
||||
|
||||
fn set_value(obj: &PyObjectRef, value: f64) {
|
||||
obj.borrow_mut().payload = PyObjectPayload::Float { value };
|
||||
}
|
||||
|
||||
fn float_eq(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
arg_check!(
|
||||
vm,
|
||||
@@ -454,7 +444,7 @@ pub fn init(context: &PyContext) {
|
||||
"__floordiv__",
|
||||
context.new_rustfunc(float_floordiv),
|
||||
);
|
||||
context.set_attr(&float_type, "__init__", context.new_rustfunc(float_init));
|
||||
context.set_attr(&float_type, "__new__", context.new_rustfunc(float_new));
|
||||
context.set_attr(&float_type, "__mod__", context.new_rustfunc(float_mod));
|
||||
context.set_attr(&float_type, "__neg__", context.new_rustfunc(float_neg));
|
||||
context.set_attr(&float_type, "__pow__", context.new_rustfunc(float_pow));
|
||||
|
||||
@@ -31,10 +31,9 @@ fn frame_flocals(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
arg_check!(vm, args, required = [(frame, Some(vm.ctx.frame_type()))]);
|
||||
let frame = get_value(frame);
|
||||
let py_scope = frame.locals.clone();
|
||||
let py_scope = py_scope.borrow();
|
||||
|
||||
if let PyObjectPayload::Scope { scope } = &py_scope.payload {
|
||||
Ok(scope.locals.clone())
|
||||
Ok(scope.borrow().locals.clone())
|
||||
} else {
|
||||
panic!("The scope isn't a scope!");
|
||||
}
|
||||
@@ -46,7 +45,7 @@ fn frame_fcode(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
}
|
||||
|
||||
pub fn get_value(obj: &PyObjectRef) -> Frame {
|
||||
if let PyObjectPayload::Frame { frame } = &obj.borrow().payload {
|
||||
if let PyObjectPayload::Frame { frame } = &obj.payload {
|
||||
frame.clone()
|
||||
} else {
|
||||
panic!("Inner error getting int {:?}", obj);
|
||||
|
||||
@@ -67,7 +67,7 @@ fn bind_method(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
}
|
||||
|
||||
fn function_code(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
match args.args[0].borrow().payload {
|
||||
match args.args[0].payload {
|
||||
PyObjectPayload::Function { ref code, .. } => Ok(code.clone()),
|
||||
_ => Err(vm.new_type_error("no code".to_string())),
|
||||
}
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
* The mythical generator.
|
||||
*/
|
||||
|
||||
use std::cell::RefCell;
|
||||
|
||||
use crate::frame::{ExecutionResult, Frame};
|
||||
use crate::pyobject::{
|
||||
PyContext, PyFuncArgs, PyObject, PyObjectPayload, PyObjectRef, PyResult, TypeProtocol,
|
||||
@@ -28,11 +30,12 @@ pub fn init(context: &PyContext) {
|
||||
}
|
||||
|
||||
pub fn new_generator(vm: &mut VirtualMachine, frame: Frame) -> PyResult {
|
||||
let g = PyObject::new(
|
||||
PyObjectPayload::Generator { frame },
|
||||
Ok(PyObject::new(
|
||||
PyObjectPayload::Generator {
|
||||
frame: RefCell::new(frame),
|
||||
},
|
||||
vm.ctx.generator_type.clone(),
|
||||
);
|
||||
Ok(g)
|
||||
))
|
||||
}
|
||||
|
||||
fn generator_iter(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
@@ -56,9 +59,10 @@ fn generator_send(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
}
|
||||
|
||||
fn send(vm: &mut VirtualMachine, gen: &PyObjectRef, value: &PyObjectRef) -> PyResult {
|
||||
if let PyObjectPayload::Generator { ref mut frame } = gen.borrow_mut().payload {
|
||||
frame.push_value(value.clone());
|
||||
match frame.run_frame(vm)? {
|
||||
if let PyObjectPayload::Generator { ref frame } = gen.payload {
|
||||
let mut frame_mut = frame.borrow_mut();
|
||||
frame_mut.push_value(value.clone());
|
||||
match frame_mut.run_frame(vm)? {
|
||||
ExecutionResult::Yield(value) => Ok(value),
|
||||
ExecutionResult::Return(_value) => {
|
||||
// Stop iteration!
|
||||
|
||||
@@ -94,7 +94,7 @@ pub fn to_int(
|
||||
|
||||
// Retrieve inner int value:
|
||||
pub fn get_value(obj: &PyObjectRef) -> IntType {
|
||||
if let PyObjectPayload::Integer { value } = &obj.borrow().payload {
|
||||
if let PyObjectPayload::Integer { value } = &obj.payload {
|
||||
value.clone()
|
||||
} else {
|
||||
panic!("Inner error getting int {:?}", obj);
|
||||
|
||||
+12
-13
@@ -128,16 +128,15 @@ fn iter_next(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
arg_check!(vm, args, required = [(iter, Some(vm.ctx.iter_type()))]);
|
||||
|
||||
if let PyObjectPayload::Iterator {
|
||||
ref mut position,
|
||||
iterated_obj: ref mut iterated_obj_ref,
|
||||
} = iter.borrow_mut().payload
|
||||
ref position,
|
||||
iterated_obj: ref iterated_obj_ref,
|
||||
} = iter.payload
|
||||
{
|
||||
let iterated_obj = iterated_obj_ref.borrow_mut();
|
||||
match iterated_obj.payload {
|
||||
match iterated_obj_ref.payload {
|
||||
PyObjectPayload::Sequence { ref elements } => {
|
||||
if *position < elements.len() {
|
||||
let obj_ref = elements[*position].clone();
|
||||
*position += 1;
|
||||
if position.get() < elements.borrow().len() {
|
||||
let obj_ref = elements.borrow()[position.get()].clone();
|
||||
position.set(position.get() + 1);
|
||||
Ok(obj_ref)
|
||||
} else {
|
||||
Err(new_stop_iteration(vm))
|
||||
@@ -145,8 +144,8 @@ fn iter_next(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
}
|
||||
|
||||
PyObjectPayload::Range { ref range } => {
|
||||
if let Some(int) = range.get(*position) {
|
||||
*position += 1;
|
||||
if let Some(int) = range.get(position.get()) {
|
||||
position.set(position.get() + 1);
|
||||
Ok(vm.ctx.new_int(int))
|
||||
} else {
|
||||
Err(new_stop_iteration(vm))
|
||||
@@ -154,9 +153,9 @@ fn iter_next(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
}
|
||||
|
||||
PyObjectPayload::Bytes { ref value } => {
|
||||
if *position < value.len() {
|
||||
let obj_ref = vm.ctx.new_int(value[*position]);
|
||||
*position += 1;
|
||||
if position.get() < value.borrow().len() {
|
||||
let obj_ref = vm.ctx.new_int(value.borrow()[position.get()]);
|
||||
position.set(position.get() + 1);
|
||||
Ok(obj_ref)
|
||||
} else {
|
||||
Err(new_stop_iteration(vm))
|
||||
|
||||
+11
-23
@@ -1,3 +1,5 @@
|
||||
use std::cell::{Cell, RefCell};
|
||||
|
||||
use super::objbool;
|
||||
use super::objint;
|
||||
use super::objsequence::{
|
||||
@@ -55,7 +57,9 @@ fn list_new(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
};
|
||||
|
||||
Ok(PyObject::new(
|
||||
PyObjectPayload::Sequence { elements },
|
||||
PyObjectPayload::Sequence {
|
||||
elements: RefCell::new(elements),
|
||||
},
|
||||
cls.clone(),
|
||||
))
|
||||
}
|
||||
@@ -93,11 +97,7 @@ fn list_lt(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
let other = get_elements(other);
|
||||
seq_lt(vm, &zelf, &other)?
|
||||
} else {
|
||||
return Err(vm.new_type_error(format!(
|
||||
"Cannot compare {} and {} using '<'",
|
||||
zelf.borrow(),
|
||||
other.borrow()
|
||||
)));
|
||||
return Err(vm.new_type_error(format!("Cannot compare {} and {} using '<'", zelf, other)));
|
||||
};
|
||||
|
||||
Ok(vm.ctx.new_bool(result))
|
||||
@@ -115,11 +115,7 @@ fn list_gt(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
let other = get_elements(other);
|
||||
seq_gt(vm, &zelf, &other)?
|
||||
} else {
|
||||
return Err(vm.new_type_error(format!(
|
||||
"Cannot compare {} and {} using '>'",
|
||||
zelf.borrow(),
|
||||
other.borrow()
|
||||
)));
|
||||
return Err(vm.new_type_error(format!("Cannot compare {} and {} using '>'", zelf, other)));
|
||||
};
|
||||
|
||||
Ok(vm.ctx.new_bool(result))
|
||||
@@ -137,11 +133,7 @@ fn list_ge(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
let other = get_elements(other);
|
||||
seq_ge(vm, &zelf, &other)?
|
||||
} else {
|
||||
return Err(vm.new_type_error(format!(
|
||||
"Cannot compare {} and {} using '>='",
|
||||
zelf.borrow(),
|
||||
other.borrow()
|
||||
)));
|
||||
return Err(vm.new_type_error(format!("Cannot compare {} and {} using '>='", zelf, other)));
|
||||
};
|
||||
|
||||
Ok(vm.ctx.new_bool(result))
|
||||
@@ -159,11 +151,7 @@ fn list_le(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
let other = get_elements(other);
|
||||
seq_le(vm, &zelf, &other)?
|
||||
} else {
|
||||
return Err(vm.new_type_error(format!(
|
||||
"Cannot compare {} and {} using '<='",
|
||||
zelf.borrow(),
|
||||
other.borrow()
|
||||
)));
|
||||
return Err(vm.new_type_error(format!("Cannot compare {} and {} using '<='", zelf, other)));
|
||||
};
|
||||
|
||||
Ok(vm.ctx.new_bool(result))
|
||||
@@ -182,7 +170,7 @@ fn list_add(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
let elements = e1.iter().chain(e2.iter()).cloned().collect();
|
||||
Ok(vm.ctx.new_list(elements))
|
||||
} else {
|
||||
Err(vm.new_type_error(format!("Cannot add {} and {}", o.borrow(), o2.borrow())))
|
||||
Err(vm.new_type_error(format!("Cannot add {} and {}", o, o2)))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -393,7 +381,7 @@ fn list_iter(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
|
||||
let iter_obj = PyObject::new(
|
||||
PyObjectPayload::Iterator {
|
||||
position: 0,
|
||||
position: Cell::new(0),
|
||||
iterated_obj: list.clone(),
|
||||
},
|
||||
vm.ctx.iter_type(),
|
||||
|
||||
@@ -28,9 +28,9 @@ 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
|
||||
ref mapper,
|
||||
ref iterators,
|
||||
} = map.payload
|
||||
{
|
||||
let next_objs = iterators
|
||||
.iter()
|
||||
|
||||
+14
-10
@@ -2,7 +2,7 @@ use super::objstr;
|
||||
use super::objtype;
|
||||
use crate::pyobject::{
|
||||
AttributeProtocol, DictProtocol, IdProtocol, PyContext, PyFuncArgs, PyObjectPayload,
|
||||
PyObjectRef, PyResult, TypeProtocol,
|
||||
PyObjectRef, PyResult, TypeProtocol, PyObject
|
||||
};
|
||||
use crate::vm::VirtualMachine;
|
||||
use std::cell::RefCell;
|
||||
@@ -16,12 +16,16 @@ pub fn new_instance(vm: &mut VirtualMachine, mut args: PyFuncArgs) -> PyResult {
|
||||
}
|
||||
|
||||
pub fn create_object(type_type: PyObjectRef, object_type: PyObjectRef, _dict_type: PyObjectRef) {
|
||||
(*object_type.borrow_mut()).payload = PyObjectPayload::Class {
|
||||
name: String::from("object"),
|
||||
dict: RefCell::new(HashMap::new()),
|
||||
mro: vec![],
|
||||
};
|
||||
(*object_type.borrow_mut()).typ = Some(type_type.clone());
|
||||
// this is not ideal
|
||||
let ptr = PyObjectRef::into_raw(object_type.clone()) as *mut PyObject;
|
||||
unsafe {
|
||||
(*ptr).payload = PyObjectPayload::Class {
|
||||
name: String::from("object"),
|
||||
dict: RefCell::new(HashMap::new()),
|
||||
mro: vec![],
|
||||
};
|
||||
(*ptr).typ = Some(type_type.clone());
|
||||
}
|
||||
}
|
||||
|
||||
fn object_eq(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
@@ -101,7 +105,7 @@ fn object_delattr(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
]
|
||||
);
|
||||
|
||||
match zelf.borrow().payload {
|
||||
match zelf.payload {
|
||||
PyObjectPayload::Class { ref dict, .. } | PyObjectPayload::Instance { ref dict, .. } => {
|
||||
let attr_name = objstr::get_value(attr);
|
||||
dict.borrow_mut().remove(&attr_name);
|
||||
@@ -174,7 +178,7 @@ fn object_init(vm: &mut VirtualMachine, _args: PyFuncArgs) -> PyResult {
|
||||
}
|
||||
|
||||
fn object_dict(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
match args.args[0].borrow().payload {
|
||||
match args.args[0].payload {
|
||||
PyObjectPayload::Class { ref dict, .. } | PyObjectPayload::Instance { ref dict, .. } => {
|
||||
let new_dict = vm.new_dict();
|
||||
for (attr, value) in dict.borrow().iter() {
|
||||
@@ -230,7 +234,7 @@ fn object_getattribute(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
let attribute_error = vm.context().exceptions.attribute_error.clone();
|
||||
Err(vm.new_exception(
|
||||
attribute_error,
|
||||
format!("{} has no attribute '{}'", obj.borrow(), name),
|
||||
format!("{} has no attribute '{}'", obj, name),
|
||||
))
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,6 @@
|
||||
use std::cell::Cell;
|
||||
use std::ops::Mul;
|
||||
|
||||
use super::objint;
|
||||
use super::objtype;
|
||||
use crate::pyobject::{
|
||||
@@ -8,7 +11,6 @@ use crate::vm::VirtualMachine;
|
||||
use num_bigint::{BigInt, Sign};
|
||||
use num_integer::Integer;
|
||||
use num_traits::{One, Signed, ToPrimitive, Zero};
|
||||
use std::ops::Mul;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct RangeType {
|
||||
@@ -151,7 +153,7 @@ impl RangeType {
|
||||
}
|
||||
|
||||
pub fn get_value(obj: &PyObjectRef) -> RangeType {
|
||||
if let PyObjectPayload::Range { range } = &obj.borrow().payload {
|
||||
if let PyObjectPayload::Range { range } = &obj.payload {
|
||||
range.clone()
|
||||
} else {
|
||||
panic!("Inner error getting range {:?}", obj);
|
||||
@@ -247,7 +249,7 @@ fn range_iter(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
|
||||
Ok(PyObject::new(
|
||||
PyObjectPayload::Iterator {
|
||||
position: 0,
|
||||
position: Cell::new(0),
|
||||
iterated_obj: range.clone(),
|
||||
},
|
||||
vm.ctx.iter_type(),
|
||||
@@ -261,7 +263,7 @@ fn range_reversed(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
|
||||
Ok(PyObject::new(
|
||||
PyObjectPayload::Iterator {
|
||||
position: 0,
|
||||
position: Cell::new(0),
|
||||
iterated_obj: PyObject::new(PyObjectPayload::Range { range }, vm.ctx.range_type()),
|
||||
},
|
||||
vm.ctx.iter_type(),
|
||||
@@ -287,7 +289,7 @@ fn range_getitem(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
|
||||
let range = get_value(zelf);
|
||||
|
||||
match subscript.borrow().payload {
|
||||
match subscript.payload {
|
||||
PyObjectPayload::Integer { ref value } => {
|
||||
if let Some(int) = range.get(value) {
|
||||
Ok(vm.ctx.new_int(int))
|
||||
|
||||
+20
-23
@@ -1,12 +1,13 @@
|
||||
use std::cell::RefCell;
|
||||
use std::marker::Sized;
|
||||
use std::ops::{Deref, DerefMut, Range};
|
||||
|
||||
use super::objbool;
|
||||
use super::objint;
|
||||
use crate::pyobject::{IdProtocol, PyObject, PyObjectPayload, PyObjectRef, PyResult, TypeProtocol};
|
||||
use crate::vm::VirtualMachine;
|
||||
use num_bigint::BigInt;
|
||||
use num_traits::{One, Signed, ToPrimitive, Zero};
|
||||
use std::cell::{Ref, RefMut};
|
||||
use std::marker::Sized;
|
||||
use std::ops::{Deref, DerefMut, Range};
|
||||
|
||||
pub trait PySliceableSequence {
|
||||
fn do_slice(&self, range: Range<usize>) -> Self;
|
||||
@@ -64,7 +65,7 @@ pub trait PySliceableSequence {
|
||||
Self: Sized,
|
||||
{
|
||||
// TODO: we could potentially avoid this copy and use slice
|
||||
match &(slice.borrow()).payload {
|
||||
match &slice.payload {
|
||||
PyObjectPayload::Slice { start, stop, step } => {
|
||||
let step = step.clone().unwrap_or_else(BigInt::one);
|
||||
if step.is_zero() {
|
||||
@@ -140,7 +141,7 @@ pub fn get_item(
|
||||
elements: &[PyObjectRef],
|
||||
subscript: PyObjectRef,
|
||||
) -> PyResult {
|
||||
match &(subscript.borrow()).payload {
|
||||
match &subscript.payload {
|
||||
PyObjectPayload::Integer { value } => match value.to_i32() {
|
||||
Some(value) => {
|
||||
if let Some(pos_index) = elements.to_vec().get_pos(value) {
|
||||
@@ -156,9 +157,9 @@ pub fn get_item(
|
||||
},
|
||||
|
||||
PyObjectPayload::Slice { .. } => Ok(PyObject::new(
|
||||
match &(sequence.borrow()).payload {
|
||||
match &sequence.payload {
|
||||
PyObjectPayload::Sequence { .. } => PyObjectPayload::Sequence {
|
||||
elements: elements.to_vec().get_slice_items(vm, &subscript)?,
|
||||
elements: RefCell::new(elements.to_vec().get_slice_items(vm, &subscript)?),
|
||||
},
|
||||
ref payload => panic!("sequence get_item called for non-sequence: {:?}", payload),
|
||||
},
|
||||
@@ -302,23 +303,19 @@ pub fn seq_mul(elements: &[PyObjectRef], product: &PyObjectRef) -> Vec<PyObjectR
|
||||
}
|
||||
|
||||
pub fn get_elements<'a>(obj: &'a PyObjectRef) -> impl Deref<Target = Vec<PyObjectRef>> + 'a {
|
||||
Ref::map(obj.borrow(), |x| {
|
||||
if let PyObjectPayload::Sequence { ref elements } = x.payload {
|
||||
elements
|
||||
} else {
|
||||
panic!("Cannot extract elements from non-sequence");
|
||||
}
|
||||
})
|
||||
if let PyObjectPayload::Sequence { ref elements } = obj.payload {
|
||||
elements.borrow()
|
||||
} else {
|
||||
panic!("Cannot extract elements from non-sequence");
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_mut_elements<'a>(obj: &'a PyObjectRef) -> impl DerefMut<Target = Vec<PyObjectRef>> + 'a {
|
||||
RefMut::map(obj.borrow_mut(), |x| {
|
||||
if let PyObjectPayload::Sequence { ref mut elements } = x.payload {
|
||||
elements
|
||||
} else {
|
||||
panic!("Cannot extract list elements from non-sequence");
|
||||
// TODO: raise proper error?
|
||||
// Err(vm.new_type_error("list.append is called with no list".to_string()))
|
||||
}
|
||||
})
|
||||
if let PyObjectPayload::Sequence { ref elements } = obj.payload {
|
||||
elements.borrow_mut()
|
||||
} else {
|
||||
panic!("Cannot extract list elements from non-sequence");
|
||||
// TODO: raise proper error?
|
||||
// Err(vm.new_type_error("list.append is called with no list".to_string()))
|
||||
}
|
||||
}
|
||||
+57
-54
@@ -2,6 +2,11 @@
|
||||
* Builtin set type with a sequence of unique items.
|
||||
*/
|
||||
|
||||
use std::cell::{Cell, RefCell};
|
||||
use std::collections::hash_map::DefaultHasher;
|
||||
use std::collections::HashMap;
|
||||
use std::hash::{Hash, Hasher};
|
||||
|
||||
use super::objbool;
|
||||
use super::objint;
|
||||
use super::objiter;
|
||||
@@ -11,13 +16,10 @@ use crate::pyobject::{
|
||||
PyContext, PyFuncArgs, PyObject, PyObjectPayload, PyObjectRef, PyResult, TypeProtocol,
|
||||
};
|
||||
use crate::vm::{ReprGuard, VirtualMachine};
|
||||
use std::collections::hash_map::DefaultHasher;
|
||||
use std::collections::HashMap;
|
||||
use std::hash::{Hash, Hasher};
|
||||
|
||||
pub fn get_elements(obj: &PyObjectRef) -> HashMap<u64, PyObjectRef> {
|
||||
if let PyObjectPayload::Set { elements } = &obj.borrow().payload {
|
||||
elements.clone()
|
||||
if let PyObjectPayload::Set { elements } = &obj.payload {
|
||||
elements.borrow().clone()
|
||||
} else {
|
||||
panic!("Cannot extract set elements from non-set");
|
||||
}
|
||||
@@ -62,10 +64,10 @@ fn set_add(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
args,
|
||||
required = [(s, Some(vm.ctx.set_type())), (item, None)]
|
||||
);
|
||||
let mut mut_obj = s.borrow_mut();
|
||||
|
||||
match mut_obj.payload {
|
||||
PyObjectPayload::Set { ref mut elements } => insert_into_set(vm, elements, item),
|
||||
match s.payload {
|
||||
PyObjectPayload::Set { ref elements } => {
|
||||
insert_into_set(vm, &mut elements.borrow_mut(), item)
|
||||
}
|
||||
_ => Err(vm.new_type_error("set.add is called with no item".to_string())),
|
||||
}
|
||||
}
|
||||
@@ -77,10 +79,8 @@ fn set_remove(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
args,
|
||||
required = [(s, Some(vm.ctx.set_type())), (item, None)]
|
||||
);
|
||||
let mut mut_obj = s.borrow_mut();
|
||||
|
||||
match mut_obj.payload {
|
||||
PyObjectPayload::Set { ref mut elements } => {
|
||||
match s.payload {
|
||||
PyObjectPayload::Set { ref elements } => {
|
||||
fn remove(
|
||||
vm: &mut VirtualMachine,
|
||||
elements: &mut HashMap<u64, PyObjectRef>,
|
||||
@@ -89,13 +89,13 @@ fn set_remove(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
) -> PyResult {
|
||||
match elements.remove(&key) {
|
||||
None => {
|
||||
let item_str = format!("{:?}", value.borrow());
|
||||
let item_str = format!("{:?}", value);
|
||||
Err(vm.new_key_error(item_str))
|
||||
}
|
||||
Some(_) => Ok(vm.get_none()),
|
||||
}
|
||||
}
|
||||
perform_action_with_hash(vm, elements, item, &remove)
|
||||
perform_action_with_hash(vm, &mut elements.borrow_mut(), item, &remove)
|
||||
}
|
||||
_ => Err(vm.new_type_error("set.remove is called with no item".to_string())),
|
||||
}
|
||||
@@ -108,10 +108,8 @@ fn set_discard(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
args,
|
||||
required = [(s, Some(vm.ctx.set_type())), (item, None)]
|
||||
);
|
||||
let mut mut_obj = s.borrow_mut();
|
||||
|
||||
match mut_obj.payload {
|
||||
PyObjectPayload::Set { ref mut elements } => {
|
||||
match s.payload {
|
||||
PyObjectPayload::Set { ref elements } => {
|
||||
fn discard(
|
||||
vm: &mut VirtualMachine,
|
||||
elements: &mut HashMap<u64, PyObjectRef>,
|
||||
@@ -121,7 +119,7 @@ fn set_discard(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
elements.remove(&key);
|
||||
Ok(vm.get_none())
|
||||
}
|
||||
perform_action_with_hash(vm, elements, item, &discard)
|
||||
perform_action_with_hash(vm, &mut elements.borrow_mut(), item, &discard)
|
||||
}
|
||||
_ => Err(vm.new_type_error("set.discard is called with no item".to_string())),
|
||||
}
|
||||
@@ -130,10 +128,9 @@ fn set_discard(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
fn set_clear(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
trace!("set.clear called");
|
||||
arg_check!(vm, args, required = [(s, Some(vm.ctx.set_type()))]);
|
||||
let mut mut_obj = s.borrow_mut();
|
||||
match mut_obj.payload {
|
||||
PyObjectPayload::Set { ref mut elements } => {
|
||||
elements.clear();
|
||||
match s.payload {
|
||||
PyObjectPayload::Set { ref elements } => {
|
||||
elements.borrow_mut().clear();
|
||||
Ok(vm.get_none())
|
||||
}
|
||||
_ => Err(vm.new_type_error("".to_string())),
|
||||
@@ -150,7 +147,7 @@ fn set_new(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
);
|
||||
|
||||
if !objtype::issubclass(cls, &vm.ctx.set_type()) {
|
||||
return Err(vm.new_type_error(format!("{} is not a subtype of set", cls.borrow())));
|
||||
return Err(vm.new_type_error(format!("{} is not a subtype of set", cls)));
|
||||
}
|
||||
|
||||
let elements: HashMap<u64, PyObjectRef> = match iterable {
|
||||
@@ -166,7 +163,9 @@ fn set_new(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
};
|
||||
|
||||
Ok(PyObject::new(
|
||||
PyObjectPayload::Set { elements },
|
||||
PyObjectPayload::Set {
|
||||
elements: RefCell::new(elements),
|
||||
},
|
||||
cls.clone(),
|
||||
))
|
||||
}
|
||||
@@ -183,7 +182,9 @@ fn set_copy(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
arg_check!(vm, args, required = [(s, Some(vm.ctx.set_type()))]);
|
||||
let elements = get_elements(s);
|
||||
Ok(PyObject::new(
|
||||
PyObjectPayload::Set { elements },
|
||||
PyObjectPayload::Set {
|
||||
elements: RefCell::new(elements),
|
||||
},
|
||||
vm.ctx.set_type(),
|
||||
))
|
||||
}
|
||||
@@ -335,7 +336,9 @@ fn set_union(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
elements.extend(get_elements(other).clone());
|
||||
|
||||
Ok(PyObject::new(
|
||||
PyObjectPayload::Set { elements },
|
||||
PyObjectPayload::Set {
|
||||
elements: RefCell::new(elements),
|
||||
},
|
||||
vm.ctx.set_type(),
|
||||
))
|
||||
}
|
||||
@@ -375,7 +378,9 @@ fn set_symmetric_difference(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResu
|
||||
}
|
||||
|
||||
Ok(PyObject::new(
|
||||
PyObjectPayload::Set { elements },
|
||||
PyObjectPayload::Set {
|
||||
elements: RefCell::new(elements),
|
||||
},
|
||||
vm.ctx.set_type(),
|
||||
))
|
||||
}
|
||||
@@ -413,7 +418,9 @@ fn set_combine_inner(
|
||||
}
|
||||
|
||||
Ok(PyObject::new(
|
||||
PyObjectPayload::Set { elements },
|
||||
PyObjectPayload::Set {
|
||||
elements: RefCell::new(elements),
|
||||
},
|
||||
vm.ctx.set_type(),
|
||||
))
|
||||
}
|
||||
@@ -421,13 +428,14 @@ fn set_combine_inner(
|
||||
fn set_pop(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
arg_check!(vm, args, required = [(s, Some(vm.ctx.set_type()))]);
|
||||
|
||||
let mut mut_obj = s.borrow_mut();
|
||||
|
||||
match mut_obj.payload {
|
||||
PyObjectPayload::Set { ref mut elements } => match elements.clone().keys().next() {
|
||||
Some(key) => Ok(elements.remove(key).unwrap()),
|
||||
None => Err(vm.new_key_error("pop from an empty set".to_string())),
|
||||
},
|
||||
match s.payload {
|
||||
PyObjectPayload::Set { ref elements } => {
|
||||
let mut elements = elements.borrow_mut();
|
||||
match elements.clone().keys().next() {
|
||||
Some(key) => Ok(elements.remove(key).unwrap()),
|
||||
None => Err(vm.new_key_error("pop from an empty set".to_string())),
|
||||
}
|
||||
}
|
||||
_ => Err(vm.new_type_error("".to_string())),
|
||||
}
|
||||
}
|
||||
@@ -444,13 +452,11 @@ fn set_ior(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
required = [(zelf, Some(vm.ctx.set_type())), (iterable, None)]
|
||||
);
|
||||
|
||||
let mut mut_obj = zelf.borrow_mut();
|
||||
|
||||
match mut_obj.payload {
|
||||
PyObjectPayload::Set { ref mut elements } => {
|
||||
match zelf.payload {
|
||||
PyObjectPayload::Set { ref elements } => {
|
||||
let iterator = objiter::get_iter(vm, iterable)?;
|
||||
while let Ok(v) = vm.call_method(&iterator, "__next__", vec![]) {
|
||||
insert_into_set(vm, elements, &v)?;
|
||||
insert_into_set(vm, &mut elements.borrow_mut(), &v)?;
|
||||
}
|
||||
}
|
||||
_ => return Err(vm.new_type_error("set.update is called with no other".to_string())),
|
||||
@@ -487,10 +493,9 @@ fn set_combine_update_inner(
|
||||
required = [(zelf, Some(vm.ctx.set_type())), (iterable, None)]
|
||||
);
|
||||
|
||||
let mut mut_obj = zelf.borrow_mut();
|
||||
|
||||
match mut_obj.payload {
|
||||
PyObjectPayload::Set { ref mut elements } => {
|
||||
match zelf.payload {
|
||||
PyObjectPayload::Set { ref elements } => {
|
||||
let mut elements = elements.borrow_mut();
|
||||
for element in elements.clone().iter() {
|
||||
let value = vm.call_method(iterable, "__contains__", vec![element.1.clone()])?;
|
||||
let should_remove = match op {
|
||||
@@ -519,19 +524,17 @@ fn set_ixor(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
required = [(zelf, Some(vm.ctx.set_type())), (iterable, None)]
|
||||
);
|
||||
|
||||
let mut mut_obj = zelf.borrow_mut();
|
||||
|
||||
match mut_obj.payload {
|
||||
PyObjectPayload::Set { ref mut elements } => {
|
||||
let elements_original = elements.clone();
|
||||
match zelf.payload {
|
||||
PyObjectPayload::Set { ref elements } => {
|
||||
let elements_original = elements.borrow().clone();
|
||||
let iterator = objiter::get_iter(vm, iterable)?;
|
||||
while let Ok(v) = vm.call_method(&iterator, "__next__", vec![]) {
|
||||
insert_into_set(vm, elements, &v)?;
|
||||
insert_into_set(vm, &mut elements.borrow_mut(), &v)?;
|
||||
}
|
||||
for element in elements_original.iter() {
|
||||
let value = vm.call_method(iterable, "__contains__", vec![element.1.clone()])?;
|
||||
if objbool::get_value(&value) {
|
||||
elements.remove(&element.0.clone());
|
||||
elements.borrow_mut().remove(&element.0.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -548,7 +551,7 @@ fn set_iter(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
let set_list = vm.ctx.new_list(items);
|
||||
let iter_obj = PyObject::new(
|
||||
PyObjectPayload::Iterator {
|
||||
position: 0,
|
||||
position: Cell::new(0),
|
||||
iterated_obj: set_list,
|
||||
},
|
||||
vm.ctx.iter_type(),
|
||||
|
||||
@@ -59,7 +59,7 @@ fn get_property_value(vm: &mut VirtualMachine, value: &Option<BigInt>) -> PyResu
|
||||
|
||||
fn slice_start(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
arg_check!(vm, args, required = [(slice, Some(vm.ctx.slice_type()))]);
|
||||
if let PyObjectPayload::Slice { start, .. } = &slice.borrow().payload {
|
||||
if let PyObjectPayload::Slice { start, .. } = &slice.payload {
|
||||
get_property_value(vm, start)
|
||||
} else {
|
||||
panic!("Slice has incorrect payload.");
|
||||
@@ -68,7 +68,7 @@ fn slice_start(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
|
||||
fn slice_stop(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
arg_check!(vm, args, required = [(slice, Some(vm.ctx.slice_type()))]);
|
||||
if let PyObjectPayload::Slice { stop, .. } = &slice.borrow().payload {
|
||||
if let PyObjectPayload::Slice { stop, .. } = &slice.payload {
|
||||
get_property_value(vm, stop)
|
||||
} else {
|
||||
panic!("Slice has incorrect payload.");
|
||||
@@ -77,7 +77,7 @@ fn slice_stop(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
|
||||
fn slice_step(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
arg_check!(vm, args, required = [(slice, Some(vm.ctx.slice_type()))]);
|
||||
if let PyObjectPayload::Slice { step, .. } = &slice.borrow().payload {
|
||||
if let PyObjectPayload::Slice { step, .. } = &slice.payload {
|
||||
get_property_value(vm, step)
|
||||
} else {
|
||||
panic!("Slice has incorrect payload.");
|
||||
|
||||
+17
-25
@@ -3,12 +3,10 @@ use super::objsequence::PySliceableSequence;
|
||||
use super::objtype;
|
||||
use crate::format::{FormatParseError, FormatPart, FormatString};
|
||||
use crate::pyobject::{
|
||||
FromPyObject, PyContext, PyFuncArgs, PyObject, PyObjectPayload, PyObjectRef, PyResult,
|
||||
TypeProtocol,
|
||||
FromPyObject, PyContext, PyFuncArgs, PyObjectPayload, PyObjectRef, PyResult, TypeProtocol,
|
||||
};
|
||||
use crate::vm::VirtualMachine;
|
||||
use num_traits::ToPrimitive;
|
||||
use std::cell::Ref;
|
||||
use std::hash::{Hash, Hasher};
|
||||
use std::ops::Range;
|
||||
use std::str::FromStr;
|
||||
@@ -115,21 +113,19 @@ pub fn init(context: &PyContext) {
|
||||
}
|
||||
|
||||
pub fn get_value(obj: &PyObjectRef) -> String {
|
||||
if let PyObjectPayload::String { value } = &obj.borrow().payload {
|
||||
if let PyObjectPayload::String { value } = &obj.payload {
|
||||
value.to_string()
|
||||
} else {
|
||||
panic!("Inner error getting str");
|
||||
}
|
||||
}
|
||||
|
||||
pub fn borrow_value(obj: &PyObjectRef) -> Ref<str> {
|
||||
Ref::map(obj.borrow(), |py_obj| {
|
||||
if let PyObjectPayload::String { value } = &py_obj.payload {
|
||||
value.as_ref()
|
||||
} else {
|
||||
panic!("Inner error getting str");
|
||||
}
|
||||
})
|
||||
pub fn borrow_value(obj: &PyObjectRef) -> &str {
|
||||
if let PyObjectPayload::String { value } = &obj.payload {
|
||||
value.as_str()
|
||||
} else {
|
||||
panic!("Inner error getting str");
|
||||
}
|
||||
}
|
||||
|
||||
fn str_eq(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
@@ -158,7 +154,7 @@ fn str_gt(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
if objtype::isinstance(i2, &vm.ctx.str_type()) {
|
||||
Ok(vm.ctx.new_bool(v1 > get_value(i2)))
|
||||
} else {
|
||||
Err(vm.new_type_error(format!("Cannot compare {} and {}", i.borrow(), i2.borrow())))
|
||||
Err(vm.new_type_error(format!("Cannot compare {} and {}", i, i2)))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -173,7 +169,7 @@ fn str_ge(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
if objtype::isinstance(i2, &vm.ctx.str_type()) {
|
||||
Ok(vm.ctx.new_bool(v1 >= get_value(i2)))
|
||||
} else {
|
||||
Err(vm.new_type_error(format!("Cannot compare {} and {}", i.borrow(), i2.borrow())))
|
||||
Err(vm.new_type_error(format!("Cannot compare {} and {}", i, i2)))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -188,7 +184,7 @@ fn str_lt(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
if objtype::isinstance(i2, &vm.ctx.str_type()) {
|
||||
Ok(vm.ctx.new_bool(v1 < get_value(i2)))
|
||||
} else {
|
||||
Err(vm.new_type_error(format!("Cannot compare {} and {}", i.borrow(), i2.borrow())))
|
||||
Err(vm.new_type_error(format!("Cannot compare {} and {}", i, i2)))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -203,7 +199,7 @@ fn str_le(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
if objtype::isinstance(i2, &vm.ctx.str_type()) {
|
||||
Ok(vm.ctx.new_bool(v1 <= get_value(i2)))
|
||||
} else {
|
||||
Err(vm.new_type_error(format!("Cannot compare {} and {}", i.borrow(), i2.borrow())))
|
||||
Err(vm.new_type_error(format!("Cannot compare {} and {}", i, i2)))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -258,7 +254,7 @@ fn str_add(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
.ctx
|
||||
.new_str(format!("{}{}", get_value(&s), get_value(&s2))))
|
||||
} else {
|
||||
Err(vm.new_type_error(format!("Cannot add {} and {}", s.borrow(), s2.borrow())))
|
||||
Err(vm.new_type_error(format!("Cannot add {} and {}", s, s2)))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -387,11 +383,7 @@ fn str_mul(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
}
|
||||
Ok(vm.ctx.new_str(result))
|
||||
} else {
|
||||
Err(vm.new_type_error(format!(
|
||||
"Cannot multiply {} and {}",
|
||||
s.borrow(),
|
||||
s2.borrow()
|
||||
)))
|
||||
Err(vm.new_type_error(format!("Cannot multiply {} and {}", s, s2)))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1115,7 +1107,7 @@ pub fn subscript(vm: &mut VirtualMachine, value: &str, b: PyObjectRef) -> PyResu
|
||||
}
|
||||
}
|
||||
} else {
|
||||
match (*b.borrow()).payload {
|
||||
match b.payload {
|
||||
PyObjectPayload::Slice { .. } => {
|
||||
let string = value.to_string().get_slice_items(vm, &b)?;
|
||||
Ok(vm.new_str(string))
|
||||
@@ -1130,8 +1122,8 @@ pub fn subscript(vm: &mut VirtualMachine, value: &str, b: PyObjectRef) -> PyResu
|
||||
|
||||
// help get optional string indices
|
||||
fn get_slice(
|
||||
start: Option<&std::rc::Rc<std::cell::RefCell<PyObject>>>,
|
||||
end: Option<&std::rc::Rc<std::cell::RefCell<PyObject>>>,
|
||||
start: Option<&PyObjectRef>,
|
||||
end: Option<&PyObjectRef>,
|
||||
len: usize,
|
||||
) -> Result<(usize, usize), String> {
|
||||
let start_idx = match start {
|
||||
|
||||
+13
-29
@@ -1,3 +1,6 @@
|
||||
use std::cell::{Cell, RefCell};
|
||||
use std::hash::{Hash, Hasher};
|
||||
|
||||
use super::objbool;
|
||||
use super::objint;
|
||||
use super::objsequence::{
|
||||
@@ -7,7 +10,6 @@ use super::objstr;
|
||||
use super::objtype;
|
||||
use crate::pyobject::{PyContext, PyFuncArgs, PyObject, PyObjectPayload, PyResult, TypeProtocol};
|
||||
use crate::vm::{ReprGuard, VirtualMachine};
|
||||
use std::hash::{Hash, Hasher};
|
||||
|
||||
fn tuple_lt(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
arg_check!(
|
||||
@@ -21,11 +23,7 @@ fn tuple_lt(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
let other = get_elements(other);
|
||||
seq_lt(vm, &zelf, &other)?
|
||||
} else {
|
||||
return Err(vm.new_type_error(format!(
|
||||
"Cannot compare {} and {} using '<'",
|
||||
zelf.borrow(),
|
||||
other.borrow()
|
||||
)));
|
||||
return Err(vm.new_type_error(format!("Cannot compare {} and {} using '<'", zelf, other)));
|
||||
};
|
||||
|
||||
Ok(vm.ctx.new_bool(result))
|
||||
@@ -43,11 +41,7 @@ fn tuple_gt(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
let other = get_elements(other);
|
||||
seq_gt(vm, &zelf, &other)?
|
||||
} else {
|
||||
return Err(vm.new_type_error(format!(
|
||||
"Cannot compare {} and {} using '>'",
|
||||
zelf.borrow(),
|
||||
other.borrow()
|
||||
)));
|
||||
return Err(vm.new_type_error(format!("Cannot compare {} and {} using '>'", zelf, other)));
|
||||
};
|
||||
|
||||
Ok(vm.ctx.new_bool(result))
|
||||
@@ -65,11 +59,7 @@ fn tuple_ge(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
let other = get_elements(other);
|
||||
seq_ge(vm, &zelf, &other)?
|
||||
} else {
|
||||
return Err(vm.new_type_error(format!(
|
||||
"Cannot compare {} and {} using '>='",
|
||||
zelf.borrow(),
|
||||
other.borrow()
|
||||
)));
|
||||
return Err(vm.new_type_error(format!("Cannot compare {} and {} using '>='", zelf, other)));
|
||||
};
|
||||
|
||||
Ok(vm.ctx.new_bool(result))
|
||||
@@ -87,11 +77,7 @@ fn tuple_le(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
let other = get_elements(other);
|
||||
seq_le(vm, &zelf, &other)?
|
||||
} else {
|
||||
return Err(vm.new_type_error(format!(
|
||||
"Cannot compare {} and {} using '<='",
|
||||
zelf.borrow(),
|
||||
other.borrow()
|
||||
)));
|
||||
return Err(vm.new_type_error(format!("Cannot compare {} and {} using '<='", zelf, other)));
|
||||
};
|
||||
|
||||
Ok(vm.ctx.new_bool(result))
|
||||
@@ -110,11 +96,7 @@ fn tuple_add(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
let elements = e1.iter().chain(e2.iter()).cloned().collect();
|
||||
Ok(vm.ctx.new_tuple(elements))
|
||||
} else {
|
||||
Err(vm.new_type_error(format!(
|
||||
"Cannot add {} and {}",
|
||||
zelf.borrow(),
|
||||
other.borrow()
|
||||
)))
|
||||
Err(vm.new_type_error(format!("Cannot add {} and {}", zelf, other)))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -169,7 +151,7 @@ fn tuple_iter(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
|
||||
let iter_obj = PyObject::new(
|
||||
PyObjectPayload::Iterator {
|
||||
position: 0,
|
||||
position: Cell::new(0),
|
||||
iterated_obj: tuple.clone(),
|
||||
},
|
||||
vm.ctx.iter_type(),
|
||||
@@ -193,7 +175,7 @@ fn tuple_new(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
);
|
||||
|
||||
if !objtype::issubclass(cls, &vm.ctx.tuple_type()) {
|
||||
return Err(vm.new_type_error(format!("{} is not a subtype of tuple", cls.borrow())));
|
||||
return Err(vm.new_type_error(format!("{} is not a subtype of tuple", cls)));
|
||||
}
|
||||
|
||||
let elements = if let Some(iterable) = iterable {
|
||||
@@ -203,7 +185,9 @@ fn tuple_new(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
};
|
||||
|
||||
Ok(PyObject::new(
|
||||
PyObjectPayload::Sequence { elements },
|
||||
PyObjectPayload::Sequence {
|
||||
elements: RefCell::new(elements),
|
||||
},
|
||||
cls.clone(),
|
||||
))
|
||||
}
|
||||
|
||||
+15
-11
@@ -14,12 +14,16 @@ use std::collections::HashMap;
|
||||
*/
|
||||
|
||||
pub fn create_type(type_type: PyObjectRef, object_type: PyObjectRef, _dict_type: PyObjectRef) {
|
||||
(*type_type.borrow_mut()).payload = PyObjectPayload::Class {
|
||||
name: String::from("type"),
|
||||
dict: RefCell::new(PyAttributes::new()),
|
||||
mro: vec![object_type],
|
||||
};
|
||||
(*type_type.borrow_mut()).typ = Some(type_type.clone());
|
||||
// this is not ideal
|
||||
let ptr = PyObjectRef::into_raw(type_type.clone()) as *mut PyObject;
|
||||
unsafe {
|
||||
(*ptr).payload = PyObjectPayload::Class {
|
||||
name: String::from("type"),
|
||||
dict: RefCell::new(PyAttributes::new()),
|
||||
mro: vec![object_type],
|
||||
};
|
||||
(*ptr).typ = Some(type_type);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn init(context: &PyContext) {
|
||||
@@ -71,7 +75,7 @@ fn type_mro(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
}
|
||||
|
||||
fn _mro(cls: PyObjectRef) -> Option<Vec<PyObjectRef>> {
|
||||
match cls.borrow().payload {
|
||||
match cls.payload {
|
||||
PyObjectPayload::Class { ref mro, .. } => {
|
||||
let mut mro = mro.clone();
|
||||
mro.insert(0, cls.clone());
|
||||
@@ -96,7 +100,7 @@ pub fn issubclass(typ: &PyObjectRef, cls: &PyObjectRef) -> bool {
|
||||
}
|
||||
|
||||
pub fn get_type_name(typ: &PyObjectRef) -> String {
|
||||
if let PyObjectPayload::Class { name, .. } = &typ.borrow().payload {
|
||||
if let PyObjectPayload::Class { name, .. } = &typ.payload {
|
||||
name.clone()
|
||||
} else {
|
||||
panic!("Cannot get type_name of non-type type {:?}", typ);
|
||||
@@ -211,7 +215,7 @@ pub fn type_getattribute(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult
|
||||
let attribute_error = vm.context().exceptions.attribute_error.clone();
|
||||
Err(vm.new_exception(
|
||||
attribute_error,
|
||||
format!("{} has no attribute '{}'", cls.borrow(), name),
|
||||
format!("{} has no attribute '{}'", cls, name),
|
||||
))
|
||||
}
|
||||
}
|
||||
@@ -224,7 +228,7 @@ pub fn get_attributes(obj: &PyObjectRef) -> PyAttributes {
|
||||
let mut base_classes = objtype::base_classes(obj);
|
||||
base_classes.reverse();
|
||||
for bc in base_classes {
|
||||
if let PyObjectPayload::Class { dict, .. } = &bc.borrow().payload {
|
||||
if let PyObjectPayload::Class { dict, .. } = &bc.payload {
|
||||
for (name, value) in dict.borrow().iter() {
|
||||
attributes.insert(name.to_string(), value.clone());
|
||||
}
|
||||
@@ -232,7 +236,7 @@ pub fn get_attributes(obj: &PyObjectRef) -> PyAttributes {
|
||||
}
|
||||
|
||||
// Get instance attributes:
|
||||
if let PyObjectPayload::Instance { dict } = &obj.borrow().payload {
|
||||
if let PyObjectPayload::Instance { dict } = &obj.payload {
|
||||
for (name, value) in dict.borrow().iter() {
|
||||
attributes.insert(name.to_string(), value.clone());
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ fn zip_new(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
fn zip_next(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
arg_check!(vm, args, required = [(zip, Some(vm.ctx.zip_type()))]);
|
||||
|
||||
if let PyObjectPayload::ZipIterator { ref mut iterators } = zip.borrow_mut().payload {
|
||||
if let PyObjectPayload::ZipIterator { ref iterators } = zip.payload {
|
||||
if iterators.is_empty() {
|
||||
Err(objiter::new_stop_iteration(vm))
|
||||
} else {
|
||||
|
||||
+81
-55
@@ -35,7 +35,7 @@ use num_bigint::BigInt;
|
||||
use num_bigint::ToBigInt;
|
||||
use num_complex::Complex64;
|
||||
use num_traits::{One, Zero};
|
||||
use std::cell::RefCell;
|
||||
use std::cell::{Cell, RefCell};
|
||||
use std::collections::HashMap;
|
||||
use std::fmt;
|
||||
use std::rc::{Rc, Weak};
|
||||
@@ -54,21 +54,15 @@ Basically reference counting, but then done by rust.
|
||||
* Good reference: https://github.com/ProgVal/pythonvm-rust/blob/master/src/objects/mod.rs
|
||||
*/
|
||||
|
||||
/*
|
||||
The PyRef type implements
|
||||
https://doc.rust-lang.org/std/cell/index.html#introducing-mutability-inside-of-something-immutable
|
||||
*/
|
||||
pub type PyRef<T> = Rc<RefCell<T>>;
|
||||
|
||||
/// The `PyObjectRef` is one of the most used types. It is a reference to a
|
||||
/// python object. A single python object can have multiple references, and
|
||||
/// this reference counting is accounted for by this type. Use the `.clone()`
|
||||
/// method to create a new reference and increment the amount of references
|
||||
/// to the python object by 1.
|
||||
pub type PyObjectRef = PyRef<PyObject>;
|
||||
pub type PyObjectRef = Rc<PyObject>;
|
||||
|
||||
/// Same as PyObjectRef, except for being a weak reference.
|
||||
pub type PyObjectWeakRef = Weak<RefCell<PyObject>>;
|
||||
pub type PyObjectWeakRef = Weak<PyObject>;
|
||||
|
||||
/// Use this type for function which return a python object or and exception.
|
||||
/// Both the python object and the python exception are `PyObjectRef` types
|
||||
@@ -488,12 +482,19 @@ impl PyContext {
|
||||
}
|
||||
|
||||
pub fn new_bytes(&self, data: Vec<u8>) -> PyObjectRef {
|
||||
PyObject::new(PyObjectPayload::Bytes { value: data }, self.bytes_type())
|
||||
PyObject::new(
|
||||
PyObjectPayload::Bytes {
|
||||
value: RefCell::new(data),
|
||||
},
|
||||
self.bytes_type(),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn new_bytearray(&self, data: Vec<u8>) -> PyObjectRef {
|
||||
PyObject::new(
|
||||
PyObjectPayload::Bytes { value: data },
|
||||
PyObjectPayload::Bytes {
|
||||
value: RefCell::new(data),
|
||||
},
|
||||
self.bytearray_type(),
|
||||
)
|
||||
}
|
||||
@@ -507,24 +508,38 @@ impl PyContext {
|
||||
}
|
||||
|
||||
pub fn new_tuple(&self, elements: Vec<PyObjectRef>) -> PyObjectRef {
|
||||
PyObject::new(PyObjectPayload::Sequence { elements }, self.tuple_type())
|
||||
PyObject::new(
|
||||
PyObjectPayload::Sequence {
|
||||
elements: RefCell::new(elements),
|
||||
},
|
||||
self.tuple_type(),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn new_list(&self, elements: Vec<PyObjectRef>) -> PyObjectRef {
|
||||
PyObject::new(PyObjectPayload::Sequence { elements }, self.list_type())
|
||||
PyObject::new(
|
||||
PyObjectPayload::Sequence {
|
||||
elements: RefCell::new(elements),
|
||||
},
|
||||
self.list_type(),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn new_set(&self) -> PyObjectRef {
|
||||
// Initialized empty, as calling __hash__ is required for adding each object to the set
|
||||
// which requires a VM context - this is done in the objset code itself.
|
||||
let elements: HashMap<u64, PyObjectRef> = HashMap::new();
|
||||
PyObject::new(PyObjectPayload::Set { elements }, self.set_type())
|
||||
PyObject::new(
|
||||
PyObjectPayload::Set {
|
||||
elements: RefCell::new(HashMap::new()),
|
||||
},
|
||||
self.set_type(),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn new_dict(&self) -> PyObjectRef {
|
||||
PyObject::new(
|
||||
PyObjectPayload::Dict {
|
||||
elements: HashMap::new(),
|
||||
elements: RefCell::new(HashMap::new()),
|
||||
},
|
||||
self.dict_type(),
|
||||
)
|
||||
@@ -536,7 +551,7 @@ impl PyContext {
|
||||
|
||||
pub fn new_scope(&self, parent: Option<PyObjectRef>) -> PyObjectRef {
|
||||
let locals = self.new_dict();
|
||||
let scope = Scope { locals, parent };
|
||||
let scope = RefCell::new(Scope { locals, parent });
|
||||
PyObject {
|
||||
payload: PyObjectPayload::Scope { scope },
|
||||
typ: None,
|
||||
@@ -640,6 +655,17 @@ impl PyContext {
|
||||
)
|
||||
}
|
||||
|
||||
// Item set/get:
|
||||
pub fn set_item(&self, obj: &PyObjectRef, key: &str, v: PyObjectRef) {
|
||||
match obj.payload {
|
||||
PyObjectPayload::Dict { ref elements } => {
|
||||
let key = self.new_str(key.to_string());
|
||||
objdict::set_item_in_content(&mut elements.borrow_mut(), &key, &v);
|
||||
}
|
||||
ref k => panic!("TODO {:?}", k),
|
||||
};
|
||||
}
|
||||
|
||||
pub fn get_attr(&self, obj: &PyObjectRef, attr_name: &str) -> Option<PyObjectRef> {
|
||||
// This does not need to be on the PyContext.
|
||||
// We do not require to make a new key as string for this function
|
||||
@@ -648,13 +674,13 @@ impl PyContext {
|
||||
}
|
||||
|
||||
pub fn set_attr(&self, obj: &PyObjectRef, attr_name: &str, value: PyObjectRef) {
|
||||
match obj.borrow().payload {
|
||||
match obj.payload {
|
||||
PyObjectPayload::Module { ref dict, .. } => self.set_attr(dict, attr_name, value),
|
||||
PyObjectPayload::Instance { ref dict } | PyObjectPayload::Class { ref dict, .. } => {
|
||||
dict.borrow_mut().insert(attr_name.to_string(), value);
|
||||
}
|
||||
PyObjectPayload::Scope { ref scope } => {
|
||||
scope.locals.set_item(self, attr_name, value);
|
||||
self.set_item(&scope.borrow().locals, attr_name, value);
|
||||
}
|
||||
ref payload => unimplemented!("set_attr unimplemented for: {:?}", payload),
|
||||
};
|
||||
@@ -697,7 +723,7 @@ pub trait IdProtocol {
|
||||
|
||||
impl IdProtocol for PyObjectRef {
|
||||
fn get_id(&self) -> usize {
|
||||
self.as_ptr() as usize
|
||||
&*self as &PyObject as *const PyObject as usize
|
||||
}
|
||||
|
||||
fn is(&self, other: &PyObjectRef) -> bool {
|
||||
@@ -715,7 +741,7 @@ pub trait TypeProtocol {
|
||||
|
||||
impl TypeProtocol for PyObjectRef {
|
||||
fn typ(&self) -> PyObjectRef {
|
||||
self.borrow().typ()
|
||||
(**self).typ()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -735,15 +761,15 @@ pub trait ParentProtocol {
|
||||
|
||||
impl ParentProtocol for PyObjectRef {
|
||||
fn has_parent(&self) -> bool {
|
||||
match self.borrow().payload {
|
||||
PyObjectPayload::Scope { ref scope } => scope.parent.is_some(),
|
||||
match self.payload {
|
||||
PyObjectPayload::Scope { ref scope } => scope.borrow().parent.is_some(),
|
||||
_ => panic!("Only scopes have parent (not {:?}", self),
|
||||
}
|
||||
}
|
||||
|
||||
fn get_parent(&self) -> PyObjectRef {
|
||||
match self.borrow().payload {
|
||||
PyObjectPayload::Scope { ref scope } => match scope.parent {
|
||||
match self.payload {
|
||||
PyObjectPayload::Scope { ref scope } => match scope.borrow().parent {
|
||||
Some(ref value) => value.clone(),
|
||||
None => panic!("OMG"),
|
||||
},
|
||||
@@ -758,7 +784,6 @@ pub trait AttributeProtocol {
|
||||
}
|
||||
|
||||
fn class_get_item(class: &PyObjectRef, attr_name: &str) -> Option<PyObjectRef> {
|
||||
let class = class.borrow();
|
||||
match class.payload {
|
||||
PyObjectPayload::Class { ref dict, .. } => dict.borrow().get(attr_name).cloned(),
|
||||
_ => panic!("Only classes should be in MRO!"),
|
||||
@@ -766,7 +791,6 @@ fn class_get_item(class: &PyObjectRef, attr_name: &str) -> Option<PyObjectRef> {
|
||||
}
|
||||
|
||||
fn class_has_item(class: &PyObjectRef, attr_name: &str) -> bool {
|
||||
let class = class.borrow();
|
||||
match class.payload {
|
||||
PyObjectPayload::Class { ref dict, .. } => dict.borrow().contains_key(attr_name),
|
||||
_ => panic!("Only classes should be in MRO!"),
|
||||
@@ -775,8 +799,7 @@ fn class_has_item(class: &PyObjectRef, attr_name: &str) -> bool {
|
||||
|
||||
impl AttributeProtocol for PyObjectRef {
|
||||
fn get_attr(&self, attr_name: &str) -> Option<PyObjectRef> {
|
||||
let obj = self.borrow();
|
||||
match obj.payload {
|
||||
match self.payload {
|
||||
PyObjectPayload::Module { ref dict, .. } => dict.get_item(attr_name),
|
||||
PyObjectPayload::Class { ref mro, .. } => {
|
||||
if let Some(item) = class_get_item(self, attr_name) {
|
||||
@@ -795,8 +818,7 @@ impl AttributeProtocol for PyObjectRef {
|
||||
}
|
||||
|
||||
fn has_attr(&self, attr_name: &str) -> bool {
|
||||
let obj = self.borrow();
|
||||
match obj.payload {
|
||||
match self.payload {
|
||||
PyObjectPayload::Module { ref dict, .. } => dict.contains_key(attr_name),
|
||||
PyObjectPayload::Class { ref mro, .. } => {
|
||||
class_has_item(self, attr_name) || mro.iter().any(|d| class_has_item(d, attr_name))
|
||||
@@ -816,45 +838,45 @@ pub trait DictProtocol {
|
||||
|
||||
impl DictProtocol for PyObjectRef {
|
||||
fn contains_key(&self, k: &str) -> bool {
|
||||
match self.borrow().payload {
|
||||
match self.payload {
|
||||
PyObjectPayload::Dict { ref elements } => {
|
||||
objdict::content_contains_key_str(elements, k)
|
||||
objdict::content_contains_key_str(&elements.borrow(), k)
|
||||
}
|
||||
PyObjectPayload::Scope { ref scope } => scope.locals.contains_key(k),
|
||||
PyObjectPayload::Scope { ref scope } => scope.borrow().locals.contains_key(k),
|
||||
ref payload => unimplemented!("TODO {:?}", payload),
|
||||
}
|
||||
}
|
||||
|
||||
fn get_item(&self, k: &str) -> Option<PyObjectRef> {
|
||||
match self.borrow().payload {
|
||||
PyObjectPayload::Dict { ref elements } => objdict::content_get_key_str(elements, k),
|
||||
match self.payload {
|
||||
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.locals.get_item(k),
|
||||
PyObjectPayload::Scope { ref scope } => scope.borrow().locals.get_item(k),
|
||||
ref k => panic!("TODO {:?}", k),
|
||||
}
|
||||
}
|
||||
|
||||
fn get_key_value_pairs(&self) -> Vec<(PyObjectRef, PyObjectRef)> {
|
||||
match self.borrow().payload {
|
||||
match self.payload {
|
||||
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(),
|
||||
PyObjectPayload::Scope { ref scope } => scope.borrow().locals.get_key_value_pairs(),
|
||||
_ => panic!("TODO"),
|
||||
}
|
||||
}
|
||||
|
||||
// Item set/get:
|
||||
fn set_item(&self, ctx: &PyContext, key: &str, v: PyObjectRef) {
|
||||
match self.borrow_mut().payload {
|
||||
PyObjectPayload::Dict { ref mut elements } => {
|
||||
match &self.payload {
|
||||
PyObjectPayload::Dict { elements } => {
|
||||
let key = ctx.new_str(key.to_string());
|
||||
objdict::set_item_in_content(elements, &key, &v);
|
||||
objdict::set_item_in_content(&mut elements.borrow_mut(), &key, &v);
|
||||
}
|
||||
PyObjectPayload::Module { ref mut dict, .. } => {
|
||||
PyObjectPayload::Module { dict, .. } => {
|
||||
dict.set_item(ctx, key, v);
|
||||
}
|
||||
PyObjectPayload::Scope { ref mut scope, .. } => {
|
||||
scope.locals.set_item(ctx, key, v);
|
||||
PyObjectPayload::Scope { scope, .. } => {
|
||||
scope.borrow().locals.set_item(ctx, key, v);
|
||||
}
|
||||
ref k => panic!("TODO {:?}", k),
|
||||
};
|
||||
@@ -1169,23 +1191,23 @@ pub enum PyObjectPayload {
|
||||
value: Complex64,
|
||||
},
|
||||
Bytes {
|
||||
value: Vec<u8>,
|
||||
value: RefCell<Vec<u8>>,
|
||||
},
|
||||
Sequence {
|
||||
elements: Vec<PyObjectRef>,
|
||||
elements: RefCell<Vec<PyObjectRef>>,
|
||||
},
|
||||
Dict {
|
||||
elements: objdict::DictContentType,
|
||||
elements: RefCell<objdict::DictContentType>,
|
||||
},
|
||||
Set {
|
||||
elements: HashMap<u64, PyObjectRef>,
|
||||
elements: RefCell<HashMap<u64, PyObjectRef>>,
|
||||
},
|
||||
Iterator {
|
||||
position: usize,
|
||||
position: Cell<usize>,
|
||||
iterated_obj: PyObjectRef,
|
||||
},
|
||||
EnumerateIterator {
|
||||
counter: BigInt,
|
||||
counter: RefCell<BigInt>,
|
||||
iterator: PyObjectRef,
|
||||
},
|
||||
FilterIterator {
|
||||
@@ -1222,14 +1244,14 @@ pub enum PyObjectPayload {
|
||||
defaults: PyObjectRef,
|
||||
},
|
||||
Generator {
|
||||
frame: Frame,
|
||||
frame: RefCell<Frame>,
|
||||
},
|
||||
BoundMethod {
|
||||
function: PyObjectRef,
|
||||
object: PyObjectRef,
|
||||
},
|
||||
Scope {
|
||||
scope: Scope,
|
||||
scope: RefCell<Scope>,
|
||||
},
|
||||
Module {
|
||||
name: String,
|
||||
@@ -1252,7 +1274,10 @@ pub enum PyObjectPayload {
|
||||
function: Box<Fn(&mut VirtualMachine, PyFuncArgs) -> PyResult>,
|
||||
},
|
||||
Socket {
|
||||
socket: Socket,
|
||||
socket: RefCell<Socket>,
|
||||
},
|
||||
AnyRustValue {
|
||||
value: Box<dyn std::any::Any>,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -1292,6 +1317,7 @@ impl fmt::Debug for PyObjectPayload {
|
||||
PyObjectPayload::RustFunction { .. } => write!(f, "rust function"),
|
||||
PyObjectPayload::Frame { .. } => write!(f, "frame"),
|
||||
PyObjectPayload::Socket { .. } => write!(f, "socket"),
|
||||
PyObjectPayload::AnyRustValue { .. } => write!(f, "some rust value"),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1311,7 +1337,7 @@ impl PyObject {
|
||||
|
||||
// Move this object into a reference object, transferring ownership.
|
||||
pub fn into_ref(self) -> PyObjectRef {
|
||||
Rc::new(RefCell::new(self))
|
||||
Rc::new(self)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+6
-19
@@ -602,23 +602,10 @@ fn ast_parse(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
}
|
||||
|
||||
pub fn mk_module(ctx: &PyContext) -> PyObjectRef {
|
||||
// TODO: maybe we can use some clever macro to generate this?
|
||||
let ast_mod = ctx.new_module("ast", ctx.new_scope(None));
|
||||
|
||||
ctx.set_attr(&ast_mod, "parse", ctx.new_rustfunc(ast_parse));
|
||||
|
||||
ctx.set_attr(
|
||||
&ast_mod,
|
||||
"Module",
|
||||
ctx.new_class("_ast.Module", ctx.object()),
|
||||
);
|
||||
|
||||
ctx.set_attr(
|
||||
&ast_mod,
|
||||
"FunctionDef",
|
||||
ctx.new_class("_ast.FunctionDef", ctx.object()),
|
||||
);
|
||||
ctx.set_attr(&ast_mod, "Call", ctx.new_class("_ast.Call", ctx.object()));
|
||||
|
||||
ast_mod
|
||||
py_module!(ctx, "ast", {
|
||||
"parse" => ctx.new_rustfunc(ast_parse),
|
||||
"Module" => ctx.new_class("_ast.Module", ctx.object()),
|
||||
"FunctionDef" =>ctx.new_class("_ast.FunctionDef", ctx.object()),
|
||||
"Call" => ctx.new_class("_ast.Call", ctx.object())
|
||||
})
|
||||
}
|
||||
@@ -2,6 +2,18 @@ use crate::obj::objcode;
|
||||
use crate::pyobject::{PyContext, PyFuncArgs, PyObjectRef, PyResult, TypeProtocol};
|
||||
use crate::vm::VirtualMachine;
|
||||
|
||||
fn dis_dis(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
arg_check!(vm, args, required = [(obj, None)]);
|
||||
|
||||
// Method or function:
|
||||
let code_name = vm.new_str("__code__".to_string());
|
||||
if let Ok(co) = vm.get_attribute(obj.clone(), code_name) {
|
||||
return dis_disassemble(vm, PyFuncArgs::new(vec![co], vec![]));
|
||||
}
|
||||
|
||||
dis_disassemble(vm, PyFuncArgs::new(vec![obj.clone()], vec![]))
|
||||
}
|
||||
|
||||
fn dis_disassemble(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
arg_check!(vm, args, required = [(co, Some(vm.ctx.code_type()))]);
|
||||
|
||||
@@ -12,6 +24,7 @@ fn dis_disassemble(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
|
||||
pub fn mk_module(ctx: &PyContext) -> PyObjectRef {
|
||||
py_module!(ctx, "dis", {
|
||||
"dis" => ctx.new_rustfunc(dis_dis),
|
||||
"disassemble" => ctx.new_rustfunc(dis_disassemble)
|
||||
})
|
||||
}
|
||||
+13
-9
@@ -7,6 +7,7 @@ use std::collections::HashSet;
|
||||
use std::fs::File;
|
||||
use std::io::prelude::*;
|
||||
use std::io::BufReader;
|
||||
use std::path::PathBuf;
|
||||
|
||||
//3rd party imports
|
||||
use num_bigint::ToBigInt;
|
||||
@@ -23,6 +24,7 @@ use crate::pyobject::{
|
||||
PyResult, TypeProtocol,
|
||||
};
|
||||
|
||||
use crate::import;
|
||||
use crate::vm::VirtualMachine;
|
||||
|
||||
fn compute_c_flag(mode: &str) -> u16 {
|
||||
@@ -84,8 +86,8 @@ fn buffered_reader_read(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
.map_err(|_| vm.new_value_error("IO Error".to_string()))?;
|
||||
|
||||
//Copy bytes from the buffer vector into the results vector
|
||||
if let PyObjectPayload::Bytes { ref mut value } = buffer.borrow_mut().payload {
|
||||
result.extend(value.iter().cloned());
|
||||
if let PyObjectPayload::Bytes { ref value } = buffer.payload {
|
||||
result.extend(value.borrow().iter().cloned());
|
||||
};
|
||||
|
||||
let len = vm.get_method(buffer.clone(), &"__len__".to_string());
|
||||
@@ -167,11 +169,12 @@ fn file_io_readinto(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
let handle = os::rust_file(raw_fd);
|
||||
|
||||
let mut f = handle.take(length);
|
||||
if let PyObjectPayload::Bytes { ref mut value } = obj.borrow_mut().payload {
|
||||
if let PyObjectPayload::Bytes { ref value } = obj.payload {
|
||||
//TODO: Implement for MemoryView
|
||||
|
||||
value.clear();
|
||||
match f.read_to_end(&mut *value) {
|
||||
let mut value_mut = value.borrow_mut();
|
||||
value_mut.clear();
|
||||
match f.read_to_end(&mut value_mut) {
|
||||
Ok(_) => {}
|
||||
Err(_) => return Err(vm.new_value_error("Error reading from Take".to_string())),
|
||||
}
|
||||
@@ -197,9 +200,10 @@ fn file_io_write(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
//to support windows - i.e. raw file_handles
|
||||
let mut handle = os::rust_file(raw_fd);
|
||||
|
||||
match obj.borrow_mut().payload {
|
||||
PyObjectPayload::Bytes { ref mut value } => {
|
||||
match handle.write(&value[..]) {
|
||||
match obj.payload {
|
||||
PyObjectPayload::Bytes { ref value } => {
|
||||
let value_mut = value.borrow();
|
||||
match handle.write(&value_mut[..]) {
|
||||
Ok(len) => {
|
||||
//reset raw fd on the FileIO object
|
||||
let updated = os::raw_file_number(handle);
|
||||
@@ -265,7 +269,7 @@ pub fn io_open(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
optional = [(mode, Some(vm.ctx.str_type()))]
|
||||
);
|
||||
|
||||
let module = mk_module(&vm.ctx);
|
||||
let module = import::import_module(vm, PathBuf::default(), "io").unwrap();
|
||||
|
||||
//mode is optional: 'rt' is the default mode (open from reading text)
|
||||
let rust_mode = mode.map_or("rt".to_string(), |m| objstr::get_value(m));
|
||||
|
||||
@@ -65,7 +65,7 @@ impl<'s> serde::Serialize for PyObjectSerializer<'s> {
|
||||
map.serialize_entry(&key, &self.clone_with_object(&e.1))?;
|
||||
}
|
||||
map.end()
|
||||
} else if let PyObjectPayload::None = self.pyobject.borrow().payload {
|
||||
} else if let PyObjectPayload::None = self.pyobject.payload {
|
||||
serializer.serialize_none()
|
||||
} else {
|
||||
Err(serde::ser::Error::custom(format!(
|
||||
@@ -167,7 +167,7 @@ impl<'de> Visitor<'de> for PyObjectDeserializer<'de> {
|
||||
// than wrapping the given object up and then unwrapping it to determine whether or
|
||||
// not it is a string
|
||||
while let Some((key_obj, value)) = access.next_entry_seed(self.clone(), self.clone())? {
|
||||
let key = match key_obj.borrow().payload {
|
||||
let key = match key_obj.payload {
|
||||
PyObjectPayload::String { ref value } => value.clone(),
|
||||
_ => unimplemented!("map keys must be strings"),
|
||||
};
|
||||
@@ -225,11 +225,6 @@ fn json_loads(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
}
|
||||
|
||||
pub fn mk_module(ctx: &PyContext) -> PyObjectRef {
|
||||
let json_mod = ctx.new_module("json", ctx.new_scope(None));
|
||||
|
||||
ctx.set_attr(&json_mod, "dumps", ctx.new_rustfunc(json_dumps));
|
||||
ctx.set_attr(&json_mod, "loads", ctx.new_rustfunc(json_loads));
|
||||
|
||||
// TODO: Make this a proper type with a constructor
|
||||
let json_decode_error = create_type(
|
||||
"JSONDecodeError",
|
||||
@@ -237,7 +232,10 @@ pub fn mk_module(ctx: &PyContext) -> PyObjectRef {
|
||||
&ctx.exceptions.exception_type,
|
||||
&ctx.dict_type,
|
||||
);
|
||||
ctx.set_attr(&json_mod, "JSONDecodeError", json_decode_error);
|
||||
|
||||
json_mod
|
||||
py_module!(ctx, "json", {
|
||||
"dumps" => ctx.new_rustfunc(json_dumps),
|
||||
"loads" => ctx.new_rustfunc(json_loads),
|
||||
"JSONDecodeError" => json_decode_error
|
||||
})
|
||||
}
|
||||
@@ -18,17 +18,15 @@ fn keyword_iskeyword(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
}
|
||||
|
||||
pub fn mk_module(ctx: &PyContext) -> PyObjectRef {
|
||||
let py_mod = ctx.new_module("keyword", ctx.new_scope(None));
|
||||
|
||||
ctx.set_attr(&py_mod, "iskeyword", ctx.new_rustfunc(keyword_iskeyword));
|
||||
|
||||
let keyword_kwlist = ctx.new_list(
|
||||
lexer::get_keywords()
|
||||
.keys()
|
||||
.map(|k| ctx.new_str(k.to_string()))
|
||||
.collect(),
|
||||
);
|
||||
ctx.set_attr(&py_mod, "kwlist", keyword_kwlist);
|
||||
|
||||
py_mod
|
||||
py_module!(ctx, "keyword", {
|
||||
"iskeyword" => ctx.new_rustfunc(keyword_iskeyword),
|
||||
"kwlist" => keyword_kwlist
|
||||
})
|
||||
}
|
||||
@@ -3,6 +3,7 @@ mod dis;
|
||||
mod json;
|
||||
mod keyword;
|
||||
mod math;
|
||||
mod platform;
|
||||
mod pystruct;
|
||||
mod random;
|
||||
mod re;
|
||||
@@ -33,6 +34,7 @@ pub fn get_module_inits() -> HashMap<String, StdlibInitFunc> {
|
||||
modules.insert("json".to_string(), Box::new(json::mk_module));
|
||||
modules.insert("keyword".to_string(), Box::new(keyword::mk_module));
|
||||
modules.insert("math".to_string(), Box::new(math::mk_module));
|
||||
modules.insert("platform".to_string(), Box::new(platform::mk_module));
|
||||
modules.insert("re".to_string(), Box::new(re::mk_module));
|
||||
modules.insert("random".to_string(), Box::new(random::mk_module));
|
||||
modules.insert("string".to_string(), Box::new(string::mk_module));
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
extern crate rustc_version_runtime;
|
||||
|
||||
use crate::pyobject::{PyContext, PyFuncArgs, PyObjectRef, PyResult};
|
||||
use crate::VirtualMachine;
|
||||
|
||||
pub fn mk_module(ctx: &PyContext) -> PyObjectRef {
|
||||
py_module!(ctx, "platform", {
|
||||
"python_compiler" => ctx.new_rustfunc(platform_python_compiler),
|
||||
"python_implementation" => ctx.new_rustfunc(platform_python_implementation),
|
||||
"python_version" => ctx.new_rustfunc(platform_python_version),
|
||||
})
|
||||
}
|
||||
|
||||
fn platform_python_implementation(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
arg_check!(vm, args);
|
||||
Ok(vm.new_str("RustPython".to_string()))
|
||||
}
|
||||
|
||||
fn platform_python_version(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
arg_check!(vm, args);
|
||||
// TODO: fetch version from somewhere.
|
||||
Ok(vm.new_str("4.0.0".to_string()))
|
||||
}
|
||||
|
||||
fn platform_python_compiler(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
arg_check!(vm, args);
|
||||
let version = rustc_version_runtime::version_meta();
|
||||
Ok(vm.new_str(format!("rustc {}", version.semver)))
|
||||
}
|
||||
@@ -341,10 +341,8 @@ fn struct_unpack(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
}
|
||||
|
||||
pub fn mk_module(ctx: &PyContext) -> PyObjectRef {
|
||||
let py_mod = ctx.new_module(&"struct".to_string(), ctx.new_scope(None));
|
||||
|
||||
ctx.set_attr(&py_mod, "pack", ctx.new_rustfunc(struct_pack));
|
||||
ctx.set_attr(&py_mod, "unpack", ctx.new_rustfunc(struct_unpack));
|
||||
|
||||
py_mod
|
||||
py_module!(ctx, "struct", {
|
||||
"pack" => ctx.new_rustfunc(struct_pack),
|
||||
"unpack" => ctx.new_rustfunc(struct_unpack)
|
||||
})
|
||||
}
|
||||
+42
-52
@@ -1,3 +1,9 @@
|
||||
use std::cell::RefCell;
|
||||
use std::io;
|
||||
use std::io::Read;
|
||||
use std::io::Write;
|
||||
use std::net::{SocketAddr, TcpListener, TcpStream, UdpSocket};
|
||||
|
||||
use crate::obj::objbytes;
|
||||
use crate::obj::objint;
|
||||
use crate::obj::objsequence::get_elements;
|
||||
@@ -8,10 +14,6 @@ use crate::pyobject::{
|
||||
use crate::vm::VirtualMachine;
|
||||
|
||||
use num_traits::ToPrimitive;
|
||||
use std::io;
|
||||
use std::io::Read;
|
||||
use std::io::Write;
|
||||
use std::net::{SocketAddr, TcpListener, TcpStream, UdpSocket};
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
enum AddressFamily {
|
||||
@@ -113,7 +115,7 @@ fn socket_new(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
let address_family = AddressFamily::from_i32(objint::get_value(family_int).to_i32().unwrap());
|
||||
let kind = SocketKind::from_i32(objint::get_value(kind_int).to_i32().unwrap());
|
||||
|
||||
let socket = Socket::new(address_family, kind);
|
||||
let socket = RefCell::new(Socket::new(address_family, kind));
|
||||
|
||||
Ok(PyObject::new(
|
||||
PyObjectPayload::Socket { socket },
|
||||
@@ -134,12 +136,10 @@ fn socket_connect(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
|
||||
let address_string = format!("{}:{}", host, port.to_string());
|
||||
|
||||
let mut mut_obj = zelf.borrow_mut();
|
||||
|
||||
match mut_obj.payload {
|
||||
PyObjectPayload::Socket { ref mut socket } => {
|
||||
match zelf.payload {
|
||||
PyObjectPayload::Socket { ref socket } => {
|
||||
if let Ok(stream) = TcpStream::connect(address_string) {
|
||||
socket.con = Some(Connection::TcpStream(stream));
|
||||
socket.borrow_mut().con = Some(Connection::TcpStream(stream));
|
||||
Ok(vm.get_none())
|
||||
} else {
|
||||
// TODO: Socket error
|
||||
@@ -163,12 +163,10 @@ fn socket_bind(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
|
||||
let address_string = format!("{}:{}", host, port.to_string());
|
||||
|
||||
let mut mut_obj = zelf.borrow_mut();
|
||||
|
||||
match mut_obj.payload {
|
||||
PyObjectPayload::Socket { ref mut socket } => {
|
||||
match zelf.payload {
|
||||
PyObjectPayload::Socket { ref socket } => {
|
||||
if let Ok(stream) = TcpListener::bind(address_string) {
|
||||
socket.con = Some(Connection::TcpListener(stream));
|
||||
socket.borrow_mut().con = Some(Connection::TcpListener(stream));
|
||||
Ok(vm.get_none())
|
||||
} else {
|
||||
// TODO: Socket error
|
||||
@@ -186,11 +184,9 @@ fn socket_listen(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
fn socket_accept(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
arg_check!(vm, args, required = [(zelf, None)]);
|
||||
|
||||
let mut mut_obj = zelf.borrow_mut();
|
||||
|
||||
match mut_obj.payload {
|
||||
PyObjectPayload::Socket { ref mut socket } => {
|
||||
let ret = match socket.con {
|
||||
match zelf.payload {
|
||||
PyObjectPayload::Socket { ref socket } => {
|
||||
let ret = match socket.borrow_mut().con {
|
||||
Some(ref mut v) => v.accept(),
|
||||
None => return Err(vm.new_type_error("".to_string())),
|
||||
};
|
||||
@@ -200,15 +196,15 @@ fn socket_accept(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
_ => return Err(vm.new_type_error("".to_string())),
|
||||
};
|
||||
|
||||
let socket = Socket {
|
||||
address_family: socket.address_family.clone(),
|
||||
sk: socket.sk.clone(),
|
||||
let socket = RefCell::new(Socket {
|
||||
address_family: socket.borrow().address_family.clone(),
|
||||
sk: socket.borrow().sk.clone(),
|
||||
con: Some(Connection::TcpStream(tcp_stream)),
|
||||
};
|
||||
});
|
||||
|
||||
let sock_obj = PyObject::new(PyObjectPayload::Socket { socket }, mut_obj.typ());
|
||||
let sock_obj = PyObject::new(PyObjectPayload::Socket { socket }, zelf.typ());
|
||||
|
||||
let elements = vec![sock_obj, vm.get_none()];
|
||||
let elements = RefCell::new(vec![sock_obj, vm.get_none()]);
|
||||
|
||||
Ok(PyObject::new(
|
||||
PyObjectPayload::Sequence { elements },
|
||||
@@ -225,19 +221,14 @@ fn socket_recv(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
args,
|
||||
required = [(zelf, None), (bufsize, Some(vm.ctx.int_type()))]
|
||||
);
|
||||
let mut mut_obj = zelf.borrow_mut();
|
||||
|
||||
match mut_obj.payload {
|
||||
PyObjectPayload::Socket { ref mut socket } => {
|
||||
match zelf.payload {
|
||||
PyObjectPayload::Socket { ref socket } => {
|
||||
let mut buffer = Vec::new();
|
||||
let _temp = match socket.con {
|
||||
let _temp = match socket.borrow_mut().con {
|
||||
Some(ref mut v) => v.read_to_end(&mut buffer).unwrap(),
|
||||
None => 0,
|
||||
};
|
||||
Ok(PyObject::new(
|
||||
PyObjectPayload::Bytes { value: buffer },
|
||||
vm.ctx.bytes_type(),
|
||||
))
|
||||
Ok(vm.ctx.new_bytes(buffer))
|
||||
}
|
||||
_ => Err(vm.new_type_error("".to_string())),
|
||||
}
|
||||
@@ -249,11 +240,9 @@ fn socket_send(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
args,
|
||||
required = [(zelf, None), (bytes, Some(vm.ctx.bytes_type()))]
|
||||
);
|
||||
let mut mut_obj = zelf.borrow_mut();
|
||||
|
||||
match mut_obj.payload {
|
||||
PyObjectPayload::Socket { ref mut socket } => {
|
||||
match socket.con {
|
||||
match zelf.payload {
|
||||
PyObjectPayload::Socket { ref socket } => {
|
||||
match socket.borrow_mut().con {
|
||||
Some(ref mut v) => v.write(&objbytes::get_value(&bytes)).unwrap(),
|
||||
None => return Err(vm.new_type_error("".to_string())),
|
||||
};
|
||||
@@ -265,19 +254,20 @@ fn socket_send(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
|
||||
fn socket_close(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
arg_check!(vm, args, required = [(zelf, None)]);
|
||||
let mut mut_obj = zelf.borrow_mut();
|
||||
|
||||
match mut_obj.payload {
|
||||
PyObjectPayload::Socket { ref mut socket } => match socket.address_family {
|
||||
AddressFamily::AfInet => match socket.sk {
|
||||
SocketKind::SockStream => {
|
||||
socket.con = None;
|
||||
Ok(vm.get_none())
|
||||
}
|
||||
match zelf.payload {
|
||||
PyObjectPayload::Socket { ref socket } => {
|
||||
let mut socket = socket.borrow_mut();
|
||||
match socket.address_family {
|
||||
AddressFamily::AfInet => match socket.sk {
|
||||
SocketKind::SockStream => {
|
||||
socket.con = None;
|
||||
Ok(vm.get_none())
|
||||
}
|
||||
_ => Err(vm.new_type_error("".to_string())),
|
||||
},
|
||||
_ => Err(vm.new_type_error("".to_string())),
|
||||
},
|
||||
_ => Err(vm.new_type_error("".to_string())),
|
||||
},
|
||||
}
|
||||
}
|
||||
_ => Err(vm.new_type_error("".to_string())),
|
||||
}
|
||||
}
|
||||
|
||||
+11
-13
@@ -6,8 +6,6 @@
|
||||
use crate::pyobject::{PyContext, PyObjectRef};
|
||||
|
||||
pub fn mk_module(ctx: &PyContext) -> PyObjectRef {
|
||||
let py_mod = ctx.new_module(&"string".to_string(), ctx.new_scope(None));
|
||||
|
||||
let ascii_lowercase = "abcdefghijklmnopqrstuvwxyz".to_string();
|
||||
let ascii_uppercase = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".to_string();
|
||||
let ascii_letters = format!("{}{}", ascii_lowercase, ascii_uppercase);
|
||||
@@ -21,15 +19,15 @@ pub fn mk_module(ctx: &PyContext) -> PyObjectRef {
|
||||
*/
|
||||
|
||||
// Constants:
|
||||
ctx.set_attr(&py_mod, "ascii_letters", ctx.new_str(ascii_letters));
|
||||
ctx.set_attr(&py_mod, "ascii_lowercase", ctx.new_str(ascii_lowercase));
|
||||
ctx.set_attr(&py_mod, "ascii_uppercase", ctx.new_str(ascii_uppercase));
|
||||
ctx.set_attr(&py_mod, "digits", ctx.new_str(digits));
|
||||
ctx.set_attr(&py_mod, "hexdigits", ctx.new_str(hexdigits));
|
||||
ctx.set_attr(&py_mod, "octdigits", ctx.new_str(octdigits));
|
||||
// ctx.set_attr(&py_mod, "printable", ctx.new_str(printable));
|
||||
ctx.set_attr(&py_mod, "punctuation", ctx.new_str(punctuation));
|
||||
// ctx.set_attr(&py_mod, "whitespace", ctx.new_str(whitespace));
|
||||
|
||||
py_mod
|
||||
py_module!(ctx, "string", {
|
||||
"ascii_letters" => ctx.new_str(ascii_letters),
|
||||
"ascii_lowercase" => ctx.new_str(ascii_lowercase),
|
||||
"ascii_uppercase" => ctx.new_str(ascii_uppercase),
|
||||
"digits" => ctx.new_str(digits),
|
||||
"hexdigits" => ctx.new_str(hexdigits),
|
||||
"octdigits" => ctx.new_str(octdigits),
|
||||
// "printable", ctx.new_str(printable)
|
||||
"punctuation" => ctx.new_str(punctuation)
|
||||
// "whitespace", ctx.new_str(whitespace)
|
||||
})
|
||||
}
|
||||
@@ -31,10 +31,8 @@ fn time_time(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
}
|
||||
|
||||
pub fn mk_module(ctx: &PyContext) -> PyObjectRef {
|
||||
let py_mod = ctx.new_module("time", ctx.new_scope(None));
|
||||
|
||||
ctx.set_attr(&py_mod, "sleep", ctx.new_rustfunc(time_sleep));
|
||||
ctx.set_attr(&py_mod, "time", ctx.new_rustfunc(time_time));
|
||||
|
||||
py_mod
|
||||
py_module!(ctx, "time", {
|
||||
"sleep" => ctx.new_rustfunc(time_sleep),
|
||||
"time" => ctx.new_rustfunc(time_time)
|
||||
})
|
||||
}
|
||||
@@ -26,10 +26,7 @@ fn tokenize_tokenize(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
// TODO: create main function when called with -m
|
||||
|
||||
pub fn mk_module(ctx: &PyContext) -> PyObjectRef {
|
||||
let py_mod = ctx.new_module("tokenize", ctx.new_scope(None));
|
||||
|
||||
// Number theory functions:
|
||||
ctx.set_attr(&py_mod, "tokenize", ctx.new_rustfunc(tokenize_tokenize));
|
||||
|
||||
py_mod
|
||||
py_module!(ctx, "tokenize", {
|
||||
"tokenize" => ctx.new_rustfunc(tokenize_tokenize)
|
||||
})
|
||||
}
|
||||
+7
-10
@@ -31,14 +31,11 @@ fn types_new_class(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
}
|
||||
|
||||
pub fn mk_module(ctx: &PyContext) -> PyObjectRef {
|
||||
let py_mod = ctx.new_module("types", ctx.new_scope(None));
|
||||
|
||||
// Number theory functions:
|
||||
ctx.set_attr(&py_mod, "new_class", ctx.new_rustfunc(types_new_class));
|
||||
ctx.set_attr(&py_mod, "FunctionType", ctx.function_type());
|
||||
ctx.set_attr(&py_mod, "LambdaType", ctx.function_type());
|
||||
ctx.set_attr(&py_mod, "CodeType", ctx.code_type());
|
||||
ctx.set_attr(&py_mod, "FrameType", ctx.frame_type());
|
||||
|
||||
py_mod
|
||||
py_module!(ctx, "types", {
|
||||
"new_class" => ctx.new_rustfunc(types_new_class),
|
||||
"FunctionType" => ctx.function_type(),
|
||||
"LambdaType" => ctx.function_type(),
|
||||
"CodeType" => ctx.code_type(),
|
||||
"FrameType" => ctx.frame_type()
|
||||
})
|
||||
}
|
||||
@@ -46,7 +46,7 @@ fn ref_call(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
}
|
||||
|
||||
fn get_value(obj: &PyObjectRef) -> PyObjectWeakRef {
|
||||
if let PyObjectPayload::WeakRef { referent } = &obj.borrow().payload {
|
||||
if let PyObjectPayload::WeakRef { referent } = &obj.payload {
|
||||
referent.clone()
|
||||
} else {
|
||||
panic!("Inner error getting weak ref {:?}", obj);
|
||||
|
||||
+1
-1
@@ -30,7 +30,7 @@ fn sys_getrefcount(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
fn sys_getsizeof(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
arg_check!(vm, args, required = [(object, None)]);
|
||||
// TODO: implement default optional argument.
|
||||
let size = mem::size_of_val(&object.borrow());
|
||||
let size = mem::size_of_val(&object);
|
||||
Ok(vm.ctx.new_int(size))
|
||||
}
|
||||
|
||||
|
||||
+5
-9
@@ -196,7 +196,7 @@ impl VirtualMachine {
|
||||
}
|
||||
|
||||
pub fn get_builtin_scope(&mut self) -> PyObjectRef {
|
||||
let a2 = &*self.builtins.borrow();
|
||||
let a2 = &*self.builtins;
|
||||
match a2.payload {
|
||||
PyObjectPayload::Module { ref dict, .. } => dict.clone(),
|
||||
_ => {
|
||||
@@ -277,7 +277,7 @@ impl VirtualMachine {
|
||||
|
||||
pub fn invoke(&mut self, func_ref: PyObjectRef, args: PyFuncArgs) -> PyResult {
|
||||
trace!("Invoke: {:?} {:?}", func_ref, args);
|
||||
match func_ref.borrow().payload {
|
||||
match func_ref.payload {
|
||||
PyObjectPayload::RustFunction { ref function } => function(self, args),
|
||||
PyObjectPayload::Function {
|
||||
ref code,
|
||||
@@ -412,8 +412,8 @@ impl VirtualMachine {
|
||||
// Add missing positional arguments, if we have fewer positional arguments than the
|
||||
// function definition calls for
|
||||
if nargs < nexpected_args {
|
||||
let available_defaults = match defaults.borrow().payload {
|
||||
PyObjectPayload::Sequence { ref elements } => elements.clone(),
|
||||
let available_defaults = match defaults.payload {
|
||||
PyObjectPayload::Sequence { ref elements } => elements.borrow().clone(),
|
||||
PyObjectPayload::None => vec![],
|
||||
_ => panic!("function defaults not tuple or None"),
|
||||
};
|
||||
@@ -499,11 +499,7 @@ impl VirtualMachine {
|
||||
let cls = obj.typ();
|
||||
match cls.get_attr(method_name) {
|
||||
Some(method) => self.call_get_descriptor(method, obj.clone()),
|
||||
None => Err(self.new_type_error(format!(
|
||||
"{} has no method {:?}",
|
||||
obj.borrow(),
|
||||
method_name
|
||||
))),
|
||||
None => Err(self.new_type_error(format!("{} has no method {:?}", obj, method_name))),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,11 +1,15 @@
|
||||
# NOTE: will take a while, up to around a minute, to run.
|
||||
# Expect this page to freeze.
|
||||
from browser import request_animation_frame
|
||||
|
||||
w = 50.0
|
||||
h = 50.0
|
||||
|
||||
y = 0.0
|
||||
while y < h:
|
||||
# to make up for the lack of `global`
|
||||
_y = {'y': 0.0}
|
||||
|
||||
def mandel(_time_elapsed=None):
|
||||
y = _y['y']
|
||||
if y >= h:
|
||||
return
|
||||
x = 0.0
|
||||
while x < w:
|
||||
Zr, Zi, Tr, Ti = 0.0, 0.0, 0.0, 0.0
|
||||
@@ -18,14 +22,17 @@ while y < h:
|
||||
Zr = Tr - Ti + Cr
|
||||
Tr = Zr * Zr
|
||||
Ti = Zi * Zi
|
||||
i = i + 1
|
||||
i += 1
|
||||
|
||||
if Tr + Ti <= 4:
|
||||
print('*', end='')
|
||||
else:
|
||||
print('·', end='')
|
||||
|
||||
x = x + 1
|
||||
x += 1
|
||||
|
||||
print()
|
||||
y = y + 1
|
||||
_y['y'] += 1
|
||||
request_animation_frame(mandel)
|
||||
|
||||
request_animation_frame(mandel)
|
||||
@@ -18,7 +18,6 @@ wasm-bindgen = "0.2"
|
||||
wasm-bindgen-futures = "0.3"
|
||||
js-sys = "0.3"
|
||||
futures = "0.1"
|
||||
console_error_panic_hook = "0.1"
|
||||
|
||||
[dependencies.web-sys]
|
||||
version = "0.3"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use crate::{convert, vm_class::AccessibleVM, wasm_builtins::window};
|
||||
use futures::{future, Future};
|
||||
use js_sys::Promise;
|
||||
use rustpython_vm::obj::objstr;
|
||||
use rustpython_vm::obj::{objint, objstr};
|
||||
use rustpython_vm::pyobject::{PyContext, PyFuncArgs, PyObjectRef, PyResult, TypeProtocol};
|
||||
use rustpython_vm::VirtualMachine;
|
||||
use wasm_bindgen::{prelude::*, JsCast};
|
||||
@@ -125,11 +125,68 @@ fn browser_fetch(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
Ok(vm.get_none())
|
||||
}
|
||||
|
||||
fn browser_request_animation_frame(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
arg_check!(vm, args, required = [(func, Some(vm.ctx.function_type()))]);
|
||||
|
||||
use std::{cell::RefCell, rc::Rc};
|
||||
|
||||
// this basic setup for request_animation_frame taken from:
|
||||
// https://rustwasm.github.io/wasm-bindgen/examples/request-animation-frame.html
|
||||
|
||||
let f = Rc::new(RefCell::new(None));
|
||||
let g = f.clone();
|
||||
|
||||
let func = func.clone();
|
||||
|
||||
let acc_vm = AccessibleVM::from_vm(vm);
|
||||
|
||||
*g.borrow_mut() = Some(Closure::wrap(Box::new(move |time: f64| {
|
||||
let vm = &mut acc_vm
|
||||
.upgrade()
|
||||
.expect("that the vm is valid from inside of request_animation_frame");
|
||||
let func = func.clone();
|
||||
let args = PyFuncArgs {
|
||||
args: vec![vm.ctx.new_float(time)],
|
||||
kwargs: vec![],
|
||||
};
|
||||
let _ = vm.invoke(func, args);
|
||||
|
||||
let closure = f.borrow_mut().take();
|
||||
drop(closure);
|
||||
}) as Box<Fn(f64)>));
|
||||
|
||||
let id = window()
|
||||
.request_animation_frame(&js_sys::Function::from(
|
||||
g.borrow().as_ref().unwrap().as_ref().clone(),
|
||||
))
|
||||
.map_err(|err| convert::js_py_typeerror(vm, err))?;
|
||||
|
||||
Ok(vm.ctx.new_int(id))
|
||||
}
|
||||
|
||||
fn browser_cancel_animation_frame(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
arg_check!(vm, args, required = [(id, Some(vm.ctx.int_type()))]);
|
||||
|
||||
// fine because
|
||||
let id = objint::get_value(id)
|
||||
.to_string()
|
||||
.parse()
|
||||
.expect("bigint.to_string() to be parsable as i32");
|
||||
|
||||
window()
|
||||
.cancel_animation_frame(id)
|
||||
.map_err(|err| convert::js_py_typeerror(vm, err))?;
|
||||
|
||||
Ok(vm.get_none())
|
||||
}
|
||||
|
||||
const BROWSER_NAME: &str = "browser";
|
||||
|
||||
pub fn mk_module(ctx: &PyContext) -> PyObjectRef {
|
||||
py_module!(ctx, BROWSER_NAME, {
|
||||
"fetch" => ctx.new_rustfunc(browser_fetch)
|
||||
"fetch" => ctx.new_rustfunc(browser_fetch),
|
||||
"request_animation_frame" => ctx.new_rustfunc(browser_request_animation_frame),
|
||||
"cancel_animation_frame" => ctx.new_rustfunc(browser_cancel_animation_frame),
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ use crate::wasm_builtins;
|
||||
use js_sys::{SyntaxError, TypeError};
|
||||
use rustpython_vm::{
|
||||
compile,
|
||||
pyobject::{PyFuncArgs, PyObjectRef, PyRef, PyResult},
|
||||
pyobject::{PyFuncArgs, PyObjectRef, PyResult},
|
||||
VirtualMachine,
|
||||
};
|
||||
use std::cell::RefCell;
|
||||
@@ -34,8 +34,8 @@ impl StoredVirtualMachine {
|
||||
// gets compiled down to a normal-ish static varible, like Atomic* types:
|
||||
// https://rustwasm.github.io/2018/10/24/multithreading-rust-and-wasm.html#atomic-instructions
|
||||
thread_local! {
|
||||
static STORED_VMS: PyRef<HashMap<String, PyRef<StoredVirtualMachine>>> = Rc::default();
|
||||
static ACTIVE_VMS: PyRef<HashMap<String, *mut VirtualMachine>> = Rc::default();
|
||||
static STORED_VMS: Rc<RefCell<HashMap<String, Rc<RefCell<StoredVirtualMachine>>>>> = Rc::default();
|
||||
static ACTIVE_VMS: Rc<RefCell<HashMap<String, *mut VirtualMachine>>> = Rc::default();
|
||||
}
|
||||
|
||||
#[wasm_bindgen(js_name = vmStore)]
|
||||
|
||||
Reference in new issue
Block a user