mirror of
https://github.com/RustPython/RustPython.git
synced 2026-10-29 11:14:38 +08:00
Merge branch 'master' into wasm-fetch-builtin
This commit is contained in:
110 files changed
+1970
-1078
No files matched your search
+18
@@ -32,6 +32,7 @@ matrix:
|
||||
env:
|
||||
- TRAVIS_RUST_VERSION=stable
|
||||
- REGULAR_TEST=false
|
||||
- CODE_COVERAGE=false
|
||||
script: tests/.travis-runner.sh
|
||||
- language: python
|
||||
python: 3.6
|
||||
@@ -45,6 +46,7 @@ matrix:
|
||||
env:
|
||||
- TRAVIS_RUST_VERSION=beta
|
||||
- REGULAR_TEST=false
|
||||
- CODE_COVERAGE=false
|
||||
script: tests/.travis-runner.sh
|
||||
- name: rustfmt
|
||||
language: rust
|
||||
@@ -97,6 +99,22 @@ matrix:
|
||||
- cargo clippy
|
||||
env:
|
||||
- REGULAR_TEST=true
|
||||
- name: Code Coverage
|
||||
language: python
|
||||
python: 3.6
|
||||
cache:
|
||||
pip: true
|
||||
# Because we're using the Python Travis environment, we can't use
|
||||
# the built-in cargo cacher
|
||||
directories:
|
||||
- /home/travis/.cargo
|
||||
- target
|
||||
script:
|
||||
- tests/.travis-runner.sh
|
||||
env:
|
||||
- TRAVIS_RUST_VERSION=nightly
|
||||
- REGULAR_TEST=false
|
||||
- CODE_COVERAGE=true
|
||||
allow_failures:
|
||||
- rust: nightly
|
||||
env: REGULAR_TEST=true
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
name = "rustpython"
|
||||
version = "0.0.1"
|
||||
authors = ["Windel Bouwman", "Shing Lyu <shing.lyu@gmail.com>"]
|
||||
edition = "2018"
|
||||
|
||||
[workspace]
|
||||
members = [".", "vm", "wasm/lib", "parser"]
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
A Python-3 (CPython >= 3.5.0) Interpreter written in Rust :snake: :scream: :metal:.
|
||||
|
||||
[](https://travis-ci.org/RustPython/RustPython)
|
||||
[](https://dev.azure.com/ryan0463/ryan/_build/latest?definitionId=1&branchName=master)
|
||||
[](https://codecov.io/gh/RustPython/RustPython)
|
||||
[](https://opensource.org/licenses/MIT)
|
||||
[](https://github.com/RustPython/RustPython/graphs/contributors)
|
||||
[](https://gitter.im/rustpython/Lobby)
|
||||
@@ -25,6 +27,14 @@ Or use the interactive shell:
|
||||
>>>>> 2+2
|
||||
4
|
||||
|
||||
# Disclaimer
|
||||
|
||||
RustPython is in a development phase and should not be used in production or a fault intolerant setting.
|
||||
|
||||
Our current build supports only a subset of Python syntax.
|
||||
|
||||
Contribution is also more than welcome! See our contribution section for more information on this.
|
||||
|
||||
# Goals
|
||||
|
||||
- Full Python-3 environment entirely in Rust (not CPython bindings)
|
||||
@@ -32,7 +42,7 @@ Or use the interactive shell:
|
||||
|
||||
# Documentation
|
||||
|
||||
Currently the project is in an early phase, and so is the documentation.
|
||||
Currently along with other areas of the project, documentation is still in an early phase.
|
||||
|
||||
You can read the [online documentation](https://rustpython.github.io/website/rustpython/index.html) for the latest code on master.
|
||||
|
||||
@@ -45,7 +55,7 @@ $ cargo doc --no-deps --all # Excluding all dependencies
|
||||
|
||||
Documentation HTML files can then be found in the `target/doc` directory.
|
||||
|
||||
If you wish to update the online documentation. Push directly to the `release` branch (or ask a maintainer to do so), this will trigger a Travis build that updates the documentation and WebAssembly demo page.
|
||||
If you wish to update the online documentation, push directly to the `release` branch (or ask a maintainer to do so). This will trigger a Travis build that updates the documentation and WebAssembly demo page.
|
||||
|
||||
# Code organization
|
||||
|
||||
@@ -62,12 +72,14 @@ If you wish to update the online documentation. Push directly to the `release` b
|
||||
|
||||
# Contributing
|
||||
|
||||
To start contributing, there are a lot of things that need to be done.
|
||||
Contributions are more than welcome, and in many cases we are happy to guide contributors through PRs or on gitter.
|
||||
|
||||
With that in mind, please note this project is maintained by volunteers, some of the best ways to get started are below:
|
||||
|
||||
Most tasks are listed in the [issue tracker](https://github.com/RustPython/RustPython/issues).
|
||||
Check issues labeled with `good first issue` if you wish to start coding.
|
||||
|
||||
Another approach is to checkout the sourcecode: builtin functions and object methods are often the simplest
|
||||
Another approach is to checkout the source code: builtin functions and object methods are often the simplest
|
||||
and easiest way to contribute.
|
||||
|
||||
You can also simply run
|
||||
@@ -85,7 +97,7 @@ $ pipenv install
|
||||
$ pipenv run pytest -v
|
||||
```
|
||||
|
||||
There also are some unittests, you can run those will cargo:
|
||||
There also are some unit tests, you can run those will cargo:
|
||||
|
||||
```shell
|
||||
$ cargo test --all
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
trigger:
|
||||
- master
|
||||
|
||||
jobs:
|
||||
|
||||
- job: 'Test'
|
||||
pool:
|
||||
vmImage: 'vs2017-win2016'
|
||||
strategy:
|
||||
matrix:
|
||||
Python37:
|
||||
python.version: '3.7'
|
||||
maxParallel: 10
|
||||
|
||||
steps:
|
||||
- task: UsePythonVersion@0
|
||||
inputs:
|
||||
versionSpec: '$(python.version)'
|
||||
architecture: 'x64'
|
||||
|
||||
- script: |
|
||||
"C:\Program Files\Git\mingw64\bin\curl.exe" -sSf -o rustup-init.exe https://win.rustup.rs/
|
||||
.\rustup-init.exe -y
|
||||
set PATH=%PATH%;%USERPROFILE%\.cargo\bin
|
||||
rustc -V
|
||||
cargo -V
|
||||
displayName: 'Installing Rust'
|
||||
|
||||
- script: |
|
||||
set PATH=%PATH%;%USERPROFILE%\.cargo\bin
|
||||
cargo build --verbose --all
|
||||
displayName: 'Build'
|
||||
|
||||
- script: |
|
||||
set PATH=%PATH%;%USERPROFILE%\.cargo\bin
|
||||
cargo test --verbose --all
|
||||
displayName: 'Run tests'
|
||||
|
||||
- script: |
|
||||
pip install pipenv
|
||||
pushd tests
|
||||
pipenv install
|
||||
popd
|
||||
displayName: 'Install pipenv and python packages'
|
||||
|
||||
- script: |
|
||||
set PATH=%PATH%;%USERPROFILE%\.cargo\bin
|
||||
cargo build --verbose --release
|
||||
displayName: 'Build release'
|
||||
|
||||
- script: |
|
||||
set PATH=%PATH%;%USERPROFILE%\.cargo\bin
|
||||
pushd tests
|
||||
pipenv run pytest
|
||||
popd
|
||||
displayName: 'Run snippet tests'
|
||||
@@ -3,6 +3,7 @@ name = "rustpython_parser"
|
||||
version = "0.0.1"
|
||||
authors = [ "Shing Lyu", "Windel Bouwman" ]
|
||||
build = "build.rs"
|
||||
edition = "2018"
|
||||
|
||||
[build-dependencies]
|
||||
lalrpop="0.15.1"
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
extern crate lalrpop;
|
||||
use lalrpop;
|
||||
|
||||
fn main() {
|
||||
lalrpop::process_root().unwrap();
|
||||
|
||||
@@ -219,6 +219,50 @@ pub enum Expression {
|
||||
None,
|
||||
}
|
||||
|
||||
impl Expression {
|
||||
/// Returns a short name for the node suitable for use in error messages.
|
||||
pub fn name(&self) -> &'static str {
|
||||
use self::Expression::*;
|
||||
use self::StringGroup::*;
|
||||
|
||||
match self {
|
||||
BoolOp { .. } | Binop { .. } | Unop { .. } => "operator",
|
||||
Subscript { .. } => "subscript",
|
||||
Yield { .. } | YieldFrom { .. } => "yield expression",
|
||||
Compare { .. } => "comparison",
|
||||
Attribute { .. } => "attribute",
|
||||
Call { .. } => "function call",
|
||||
Number { .. }
|
||||
| String {
|
||||
value: Constant { .. },
|
||||
}
|
||||
| Bytes { .. } => "literal",
|
||||
List { .. } => "list",
|
||||
Tuple { .. } => "tuple",
|
||||
Dict { .. } => "dict display",
|
||||
Set { .. } => "set display",
|
||||
Comprehension { kind, .. } => match **kind {
|
||||
ComprehensionKind::List { .. } => "list comprehension",
|
||||
ComprehensionKind::Dict { .. } => "dict comprehension",
|
||||
ComprehensionKind::Set { .. } => "set comprehension",
|
||||
ComprehensionKind::GeneratorExpression { .. } => "generator expression",
|
||||
},
|
||||
Starred { .. } => "starred",
|
||||
Slice { .. } => "slice",
|
||||
String {
|
||||
value: Joined { .. },
|
||||
}
|
||||
| String {
|
||||
value: FormattedValue { .. },
|
||||
} => "f-string expression",
|
||||
Identifier { .. } => "named expression",
|
||||
Lambda { .. } => "lambda",
|
||||
IfExpression { .. } => "conditional expression",
|
||||
True | False | None => "keyword",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* In cpython this is called arguments, but we choose parameters to
|
||||
* distinguish between function parameters and actual call arguments.
|
||||
|
||||
+2
-2
@@ -3,8 +3,8 @@
|
||||
extern crate lalrpop_util;
|
||||
use self::lalrpop_util::ParseError as InnerError;
|
||||
|
||||
use lexer::{LexicalError, Location};
|
||||
use token::Tok;
|
||||
use crate::lexer::{LexicalError, Location};
|
||||
use crate::token::Tok;
|
||||
|
||||
use std::error::Error;
|
||||
use std::fmt;
|
||||
|
||||
+7
-7
@@ -541,7 +541,7 @@ where
|
||||
|
||||
fn is_char(&self) -> bool {
|
||||
match self.chr0 {
|
||||
Some('a'...'z') | Some('A'...'Z') | Some('_') | Some('0'...'9') => true,
|
||||
Some('a'..='z') | Some('A'..='Z') | Some('_') | Some('0'..='9') => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
@@ -549,19 +549,19 @@ where
|
||||
fn is_number(&self, radix: u32) -> bool {
|
||||
match radix {
|
||||
2 => match self.chr0 {
|
||||
Some('0'...'1') => true,
|
||||
Some('0'..='1') => true,
|
||||
_ => false,
|
||||
},
|
||||
8 => match self.chr0 {
|
||||
Some('0'...'7') => true,
|
||||
Some('0'..='7') => true,
|
||||
_ => false,
|
||||
},
|
||||
10 => match self.chr0 {
|
||||
Some('0'...'9') => true,
|
||||
Some('0'..='9') => true,
|
||||
_ => false,
|
||||
},
|
||||
16 => match self.chr0 {
|
||||
Some('0'...'9') | Some('a'...'f') | Some('A'...'F') => true,
|
||||
Some('0'..='9') | Some('a'..='f') | Some('A'..='F') => true,
|
||||
_ => false,
|
||||
},
|
||||
x => unimplemented!("Radix not implemented: {}", x),
|
||||
@@ -686,8 +686,8 @@ where
|
||||
}
|
||||
|
||||
match self.chr0 {
|
||||
Some('0'...'9') => return Some(self.lex_number()),
|
||||
Some('_') | Some('a'...'z') | Some('A'...'Z') => return Some(self.lex_identifier()),
|
||||
Some('0'..='9') => return Some(self.lex_number()),
|
||||
Some('_') | Some('a'..='z') | Some('A'..='Z') => return Some(self.lex_identifier()),
|
||||
Some('#') => {
|
||||
self.lex_comment();
|
||||
continue;
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
#[macro_use]
|
||||
extern crate log;
|
||||
|
||||
extern crate num_bigint;
|
||||
extern crate num_traits;
|
||||
|
||||
pub mod ast;
|
||||
pub mod error;
|
||||
pub mod lexer;
|
||||
|
||||
@@ -1,12 +1,10 @@
|
||||
extern crate lalrpop_util;
|
||||
|
||||
use std::iter;
|
||||
|
||||
use super::ast;
|
||||
use super::error::ParseError;
|
||||
use super::lexer;
|
||||
use super::python;
|
||||
use super::token;
|
||||
use crate::ast;
|
||||
use crate::error::ParseError;
|
||||
use crate::lexer;
|
||||
use crate::python;
|
||||
use crate::token;
|
||||
|
||||
/*
|
||||
* Parse python code.
|
||||
|
||||
@@ -613,17 +613,26 @@ ClassDef: ast::LocatedStatement = {
|
||||
},
|
||||
};
|
||||
|
||||
Path: ast::Expression = {
|
||||
<n:Identifier> => ast::Expression::Identifier { name: n },
|
||||
<p:Path> "." <n:name> => {
|
||||
ast::Expression::Attribute {
|
||||
value: Box::new(p),
|
||||
name: n,
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
// Decorators:
|
||||
Decorator: ast::Expression = {
|
||||
"@" <n:DottedName> <a: ("(" ArgumentList ")")?> "\n" => {
|
||||
let name = ast::Expression::Identifier { name: n };
|
||||
"@" <p:Path> <a: ("(" ArgumentList ")")?> "\n" => {
|
||||
match a {
|
||||
Some((_, args, _)) => ast::Expression::Call {
|
||||
function: Box::new(name),
|
||||
function: Box::new(p),
|
||||
args: args.0,
|
||||
keywords: args.1,
|
||||
},
|
||||
None => name,
|
||||
None => p,
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
name = "py_code_object"
|
||||
version = "0.1.0"
|
||||
authors = ["Shing Lyu <shing.lyu@gmail.com>"]
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
log = "0.3"
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
name = "python_compiler"
|
||||
version = "0.1.0"
|
||||
authors = ["Shing Lyu <shing.lyu@gmail.com>"]
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
cpython = { git = "https://github.com/dgrunwald/rust-cpython.git" }
|
||||
|
||||
+4
-7
@@ -19,10 +19,7 @@ use rustpython_vm::{
|
||||
util, VirtualMachine,
|
||||
};
|
||||
use rustyline::{error::ReadlineError, Editor};
|
||||
use std::{
|
||||
error::Error,
|
||||
path::{Path, PathBuf},
|
||||
};
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
fn main() {
|
||||
env_logger::init();
|
||||
@@ -81,7 +78,7 @@ fn _run_string(vm: &mut VirtualMachine, source: &str, source_path: String) -> Py
|
||||
)
|
||||
.map_err(|err| {
|
||||
let syntax_error = vm.context().exceptions.syntax_error.clone();
|
||||
vm.new_exception(syntax_error, err.description().to_string())
|
||||
vm.new_exception(syntax_error, err.to_string())
|
||||
})?;
|
||||
// trace!("Code object: {:?}", code_obj.borrow());
|
||||
let builtins = vm.get_builtin_scope();
|
||||
@@ -151,12 +148,12 @@ fn shell_exec(
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(target_family = "unix"))]
|
||||
#[cfg(not(unix))]
|
||||
fn get_history_path() -> PathBuf {
|
||||
PathBuf::from(".repl_history.txt")
|
||||
}
|
||||
|
||||
#[cfg(target_family = "unix")]
|
||||
#[cfg(unix)]
|
||||
fn get_history_path() -> PathBuf {
|
||||
//work around for windows dependent builds. The xdg crate is unix specific
|
||||
//so access to the BaseDirectories struct breaks builds on python.
|
||||
|
||||
+26
-1
@@ -10,7 +10,32 @@ pip install pipenv
|
||||
(cd tests; pipenv install)
|
||||
|
||||
# Build outside of the test runner
|
||||
cargo build --verbose --release
|
||||
if [ $CODE_COVERAGE = "true" ]
|
||||
then
|
||||
find . -name '*.gcda' -delete
|
||||
|
||||
export CARGO_INCREMENTAL=0
|
||||
export RUSTFLAGS="-Zprofile -Ccodegen-units=1 -Cinline-threshold=0 -Clink-dead-code -Coverflow-checks=off -Zno-landing-pads"
|
||||
|
||||
cargo build --verbose
|
||||
else
|
||||
cargo build --verbose --release
|
||||
fi
|
||||
|
||||
# Run the tests
|
||||
(cd tests; pipenv run pytest)
|
||||
|
||||
if [ $CODE_COVERAGE = "true" ]
|
||||
then
|
||||
cargo test --verbose --all
|
||||
zip -0 ccov.zip `find . \( -name "rustpython*.gc*" \) -print`
|
||||
|
||||
# Install grcov
|
||||
curl -L https://github.com/mozilla/grcov/releases/download/v0.4.1/grcov-linux-x86_64.tar.bz2 | tar jxf -
|
||||
|
||||
./grcov ccov.zip -s . -t lcov --llvm --branch --ignore-not-existing --ignore-dir "/*" -p "x" > lcov.info
|
||||
|
||||
# Install codecov.io reporter
|
||||
curl -s https://codecov.io/bash -o codecov.sh
|
||||
bash codecov.sh -f lcov.info
|
||||
fi
|
||||
@@ -38,3 +38,9 @@ assert b.real == 0
|
||||
|
||||
assert a.imag == 4
|
||||
assert b.imag == 4
|
||||
|
||||
# int and complex addition
|
||||
assert 1 + 1j == complex(1, 1)
|
||||
assert 1j + 1 == complex(1, 1)
|
||||
assert (1j + 1) + 3 == complex(4, 1)
|
||||
assert 3 + (1j + 1) == complex(4, 1)
|
||||
@@ -1,17 +1,8 @@
|
||||
from testutils import assert_raises
|
||||
|
||||
assert divmod(11, 3) == (3, 2)
|
||||
assert divmod(8,11) == (0, 8)
|
||||
assert divmod(0.873, 0.252) == (3.0, 0.11699999999999999)
|
||||
|
||||
try:
|
||||
divmod(5, 0)
|
||||
except ZeroDivisionError:
|
||||
pass
|
||||
else:
|
||||
assert False, "Expected divmod by zero to throw ZeroDivisionError"
|
||||
|
||||
try:
|
||||
divmod(5.0, 0.0)
|
||||
except ZeroDivisionError:
|
||||
pass
|
||||
else:
|
||||
assert False, "Expected divmod by zero to throw ZeroDivisionError"
|
||||
assert_raises(ZeroDivisionError, lambda: divmod(5, 0), 'divmod by zero')
|
||||
assert_raises(ZeroDivisionError, lambda: divmod(5.0, 0.0), 'divmod by zero')
|
||||
@@ -1,17 +1,9 @@
|
||||
from testutils import assert_raises
|
||||
|
||||
assert format(5, "b") == "101"
|
||||
|
||||
try:
|
||||
format(2, 3)
|
||||
except TypeError:
|
||||
pass
|
||||
else:
|
||||
assert False, "TypeError not raised when format is called with a number"
|
||||
assert_raises(TypeError, lambda: format(2, 3), 'format called with number')
|
||||
|
||||
assert format({}) == "{}"
|
||||
|
||||
try:
|
||||
format({}, 'b')
|
||||
except TypeError:
|
||||
pass
|
||||
else:
|
||||
assert False, "TypeError not raised when format_spec not empty for dict"
|
||||
assert_raises(TypeError, lambda: format({}, 'b'), 'format_spec not empty for dict')
|
||||
@@ -1,9 +1,6 @@
|
||||
from testutils import assert_raises
|
||||
|
||||
assert hex(16) == '0x10'
|
||||
assert hex(-16) == '-0x10'
|
||||
|
||||
try:
|
||||
hex({})
|
||||
except TypeError:
|
||||
pass
|
||||
else:
|
||||
assert False, "TypeError not raised when ord() is called with a dict"
|
||||
assert_raises(TypeError, lambda: hex({}), 'ord() called with dict')
|
||||
@@ -1,3 +1,5 @@
|
||||
from testutils import assert_raises
|
||||
|
||||
# simple values
|
||||
assert max(0, 0) == 0
|
||||
assert max(1, 0) == 1
|
||||
@@ -14,32 +16,17 @@ assert max({
|
||||
}) == "b"
|
||||
assert max([1, 2], default=0) == 2
|
||||
assert max([], default=0) == 0
|
||||
try:
|
||||
max([])
|
||||
except ValueError:
|
||||
pass
|
||||
else:
|
||||
assert False, "ValueError was not raised"
|
||||
assert_raises(ValueError, lambda: max([]))
|
||||
|
||||
# key parameter
|
||||
assert max(1, 2, -3, key=abs) == -3
|
||||
assert max([1, 2, -3], key=abs) == -3
|
||||
|
||||
# no argument
|
||||
try:
|
||||
max()
|
||||
except TypeError:
|
||||
pass
|
||||
else:
|
||||
assert False, "TypeError was not raised"
|
||||
assert_raises(TypeError, lambda: max())
|
||||
|
||||
# one non-iterable argument
|
||||
try:
|
||||
max(1)
|
||||
except TypeError:
|
||||
pass
|
||||
else:
|
||||
assert False, "TypeError was not raised"
|
||||
assert_raises(TypeError, lambda: max(1))
|
||||
|
||||
|
||||
# custom class
|
||||
@@ -64,9 +51,4 @@ class MyNotComparable():
|
||||
pass
|
||||
|
||||
|
||||
try:
|
||||
max(MyNotComparable(), MyNotComparable())
|
||||
except TypeError:
|
||||
pass
|
||||
else:
|
||||
assert False, "TypeError was not raised"
|
||||
assert_raises(TypeError, lambda: max(MyNotComparable(), MyNotComparable()))
|
||||
@@ -1,3 +1,5 @@
|
||||
from testutils import assert_raises
|
||||
|
||||
# simple values
|
||||
assert min(0, 0) == 0
|
||||
assert min(1, 0) == 0
|
||||
@@ -14,32 +16,18 @@ assert min({
|
||||
}) == "a"
|
||||
assert min([1, 2], default=0) == 1
|
||||
assert min([], default=0) == 0
|
||||
try:
|
||||
min([])
|
||||
except ValueError:
|
||||
pass
|
||||
else:
|
||||
assert False, "ValueError was not raised"
|
||||
|
||||
assert_raises(ValueError, lambda: min([]))
|
||||
|
||||
# key parameter
|
||||
assert min(1, 2, -3, key=abs) == 1
|
||||
assert min([1, 2, -3], key=abs) == 1
|
||||
|
||||
# no argument
|
||||
try:
|
||||
min()
|
||||
except TypeError:
|
||||
pass
|
||||
else:
|
||||
assert False, "TypeError was not raised"
|
||||
assert_raises(TypeError, lambda: min())
|
||||
|
||||
# one non-iterable argument
|
||||
try:
|
||||
min(1)
|
||||
except TypeError:
|
||||
pass
|
||||
else:
|
||||
assert False, "TypeError was not raised"
|
||||
assert_raises(TypeError, lambda: min(1))
|
||||
|
||||
|
||||
# custom class
|
||||
@@ -64,9 +52,4 @@ class MyNotComparable():
|
||||
pass
|
||||
|
||||
|
||||
try:
|
||||
min(MyNotComparable(), MyNotComparable())
|
||||
except TypeError:
|
||||
pass
|
||||
else:
|
||||
assert False, "TypeError was not raised"
|
||||
assert_raises(TypeError, lambda: min(MyNotComparable(), MyNotComparable()))
|
||||
@@ -1,8 +1,6 @@
|
||||
from testutils import assert_raises
|
||||
|
||||
fd = open('README.md')
|
||||
assert 'RustPython' in fd.read()
|
||||
|
||||
try:
|
||||
open('DoesNotExist')
|
||||
assert False
|
||||
except FileNotFoundError:
|
||||
pass
|
||||
assert_raises(FileNotFoundError, lambda: open('DoesNotExist'))
|
||||
@@ -1,23 +1,9 @@
|
||||
from testutils import assert_raises
|
||||
|
||||
assert ord("a") == 97
|
||||
assert ord("é") == 233
|
||||
assert ord("🤡") == 129313
|
||||
try:
|
||||
ord()
|
||||
except TypeError:
|
||||
pass
|
||||
else:
|
||||
assert False, "TypeError not raised when ord() is called with no argument"
|
||||
|
||||
try:
|
||||
ord("")
|
||||
except TypeError:
|
||||
pass
|
||||
else:
|
||||
assert False, "TypeError not raised when ord() is called with an empty string"
|
||||
|
||||
try:
|
||||
ord("ab")
|
||||
except TypeError:
|
||||
pass
|
||||
else:
|
||||
assert False, "TypeError not raised when ord() is called with more than one character"
|
||||
assert_raises(TypeError, lambda: ord(), "ord() is called with no argument")
|
||||
assert_raises(TypeError, lambda: ord(""), "ord() is called with an empty string")
|
||||
assert_raises(TypeError, lambda: ord("ab"), "ord() is called with more than one character")
|
||||
@@ -1,20 +1,4 @@
|
||||
def assert_raises(expr, exc_type):
|
||||
"""
|
||||
Helper function to assert `expr` raises an exception of type `exc_type`
|
||||
Args:
|
||||
expr: Callable
|
||||
exec_type: Exception
|
||||
Returns:
|
||||
None
|
||||
Raises:
|
||||
Assertion error on failure
|
||||
"""
|
||||
try:
|
||||
expr(None)
|
||||
except exc_type:
|
||||
assert True
|
||||
else:
|
||||
assert False
|
||||
from testutils import assert_raises
|
||||
|
||||
assert range(2**63+1)[2**63] == 9223372036854775808
|
||||
|
||||
@@ -29,15 +13,10 @@ assert range(4, 10).index(6) == 2
|
||||
assert range(4, 10, 2).index(6) == 1
|
||||
assert range(10, 4, -2).index(8) == 1
|
||||
|
||||
# index raises value error on out of bounds
|
||||
assert_raises(lambda _: range(10).index(-1), ValueError)
|
||||
assert_raises(lambda _: range(10).index(10), ValueError)
|
||||
|
||||
# index raises value error if out of step
|
||||
assert_raises(lambda _: range(4, 10, 2).index(5), ValueError)
|
||||
|
||||
# index raises value error if needle is not an int
|
||||
assert_raises(lambda _: range(10).index('foo'), ValueError)
|
||||
assert_raises(ValueError, lambda: range(10).index(-1), 'out of bounds')
|
||||
assert_raises(ValueError, lambda: range(10).index(10), 'out of bounds')
|
||||
assert_raises(ValueError, lambda: range(4, 10, 2).index(5), 'out of step')
|
||||
assert_raises(ValueError, lambda: range(10).index('foo'), 'not an int')
|
||||
|
||||
# count tests
|
||||
assert range(10).count(2) == 1
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
from testutils import assert_raises
|
||||
|
||||
a = []
|
||||
assert a[:] == []
|
||||
@@ -18,12 +19,7 @@ assert b[-10:1] == [1]
|
||||
assert b[0:0] == []
|
||||
assert b[1:0] == []
|
||||
|
||||
try:
|
||||
_ = b[::0]
|
||||
except ValueError:
|
||||
pass
|
||||
else:
|
||||
assert False, "Zero step slice should raise ValueError"
|
||||
assert_raises(ValueError, lambda: b[::0], 'zero step slice')
|
||||
|
||||
assert b[::-1] == [2, 1]
|
||||
assert b[1::-1] == [2, 1]
|
||||
|
||||
@@ -18,14 +18,50 @@ assert not bytearray(b'abc1').isalpha()
|
||||
assert bytearray(b'1234567890').isdigit()
|
||||
assert not bytearray(b'12ab').isdigit()
|
||||
|
||||
assert bytearray(b'lower').islower()
|
||||
l = bytearray(b'lower')
|
||||
assert l.islower()
|
||||
assert not l.isupper()
|
||||
assert l.upper().isupper()
|
||||
assert not bytearray(b'Super Friends').islower()
|
||||
|
||||
assert bytearray(b' \n\t').isspace()
|
||||
assert not bytearray(b'\td\n').isspace()
|
||||
|
||||
assert bytearray(b'UPPER').isupper()
|
||||
b = bytearray(b'UPPER')
|
||||
assert b.isupper()
|
||||
assert not b.islower()
|
||||
assert b.lower().islower()
|
||||
assert not bytearray(b'tuPpEr').isupper()
|
||||
|
||||
assert bytearray(b'Is Title Case').istitle()
|
||||
assert not bytearray(b'is Not title casE').istitle()
|
||||
|
||||
a = bytearray(b'abcd')
|
||||
a.clear()
|
||||
assert len(a) == 0
|
||||
|
||||
try:
|
||||
bytearray([400])
|
||||
except ValueError:
|
||||
pass
|
||||
else:
|
||||
assert False
|
||||
|
||||
b = bytearray(b'test')
|
||||
assert len(b) == 4
|
||||
b.pop()
|
||||
assert len(b) == 3
|
||||
|
||||
c = bytearray([123, 255, 111])
|
||||
assert len(c) == 3
|
||||
c.pop()
|
||||
assert len(c) == 2
|
||||
c.pop()
|
||||
c.pop()
|
||||
|
||||
try:
|
||||
c.pop()
|
||||
except IndexError:
|
||||
pass
|
||||
else:
|
||||
assert False
|
||||
@@ -0,0 +1,33 @@
|
||||
# break from a nested for loop
|
||||
|
||||
def foo():
|
||||
sum = 0
|
||||
for i in range(10):
|
||||
sum += i
|
||||
for j in range(10):
|
||||
sum += j
|
||||
break
|
||||
return sum
|
||||
|
||||
assert foo() == 45
|
||||
|
||||
|
||||
# continue statement
|
||||
|
||||
def primes(limit):
|
||||
"""Finds all the primes from 2 up to a given number using the Sieve of Eratosthenes."""
|
||||
sieve = [False] * (limit + 1)
|
||||
for i in range(2, limit + 1):
|
||||
if sieve[i]:
|
||||
continue
|
||||
yield i
|
||||
|
||||
for j in range(2 * i, limit + 1, i):
|
||||
sieve[j] = True
|
||||
|
||||
|
||||
assert list(primes(1)) == []
|
||||
assert list(primes(2)) == [2]
|
||||
assert list(primes(10)) == [2, 3, 5, 7]
|
||||
assert list(primes(13)) == [2, 3, 5, 7, 11, 13]
|
||||
|
||||
@@ -14,3 +14,15 @@ c = add(10, 3)
|
||||
|
||||
assert c == 14
|
||||
|
||||
|
||||
def f(func): return lambda: 42
|
||||
class A: pass
|
||||
a = A()
|
||||
a.a = A()
|
||||
a.a.x = f
|
||||
|
||||
@a.a.x
|
||||
def func():
|
||||
pass
|
||||
|
||||
assert func() == 42
|
||||
@@ -14,3 +14,6 @@ c['d'] = 3
|
||||
c['a']['g'] = 2
|
||||
assert dict_eq(a, {'g': 2})
|
||||
assert dict_eq(b, {'a': a, 'd': 9})
|
||||
|
||||
a.clear()
|
||||
assert len(a) == 0
|
||||
@@ -0,0 +1,10 @@
|
||||
import dis
|
||||
|
||||
dis.disassemble(compile("5 + x + 5 or 2", "", "eval"))
|
||||
print("\n")
|
||||
dis.disassemble(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"))
|
||||
print("\n")
|
||||
dis.disassemble(compile("f(x=1, y=2)", "", "eval"))
|
||||
print("\n")
|
||||
@@ -1,55 +1,11 @@
|
||||
try:
|
||||
5 / 0
|
||||
except ZeroDivisionError:
|
||||
pass
|
||||
else:
|
||||
assert False, 'Expected ZeroDivisionError'
|
||||
from testutils import assert_raises
|
||||
|
||||
try:
|
||||
5 / -0.0
|
||||
except ZeroDivisionError:
|
||||
pass
|
||||
else:
|
||||
assert False, 'Expected ZeroDivisionError'
|
||||
assert_raises(ZeroDivisionError, lambda: 5 / 0)
|
||||
assert_raises(ZeroDivisionError, lambda: 5 / -0.0)
|
||||
assert_raises(ZeroDivisionError, lambda: 5 / (2-2))
|
||||
assert_raises(ZeroDivisionError, lambda: 5 % 0)
|
||||
assert_raises(ZeroDivisionError, lambda: 5 // 0)
|
||||
assert_raises(ZeroDivisionError, lambda: 5.3 // (-0.0))
|
||||
assert_raises(ZeroDivisionError, lambda: divmod(5, 0))
|
||||
|
||||
try:
|
||||
5 / (2-2)
|
||||
except ZeroDivisionError:
|
||||
pass
|
||||
else:
|
||||
assert False, 'Expected ZeroDivisionError'
|
||||
|
||||
try:
|
||||
5 % 0
|
||||
except ZeroDivisionError:
|
||||
pass
|
||||
else:
|
||||
assert False, 'Expected ZeroDivisionError'
|
||||
|
||||
try:
|
||||
5 // 0
|
||||
except ZeroDivisionError:
|
||||
pass
|
||||
else:
|
||||
assert False, 'Expected ZeroDivisionError'
|
||||
|
||||
try:
|
||||
5.3 // (-0.0)
|
||||
except ZeroDivisionError:
|
||||
pass
|
||||
else:
|
||||
assert False, 'Expected ZeroDivisionError'
|
||||
|
||||
try:
|
||||
divmod(5, 0)
|
||||
except ZeroDivisionError:
|
||||
pass
|
||||
else:
|
||||
assert False, 'Expected ZeroDivisionError'
|
||||
|
||||
try:
|
||||
raise ZeroDivisionError('Is an ArithmeticError subclass?')
|
||||
except ArithmeticError:
|
||||
pass
|
||||
else:
|
||||
assert False, 'Expected ZeroDivisionError'
|
||||
assert issubclass(ZeroDivisionError, ArithmeticError)
|
||||
@@ -1,3 +1,5 @@
|
||||
from testutils import assert_raises
|
||||
|
||||
# 2.456984346552728
|
||||
res = 10**500 / (4 * 10**499 + 7 * 10**497 + 3 * 10**494)
|
||||
assert 2.456984 <= res <= 2.456985
|
||||
@@ -8,20 +10,10 @@ assert 95.238095 <= res <= 95.238096
|
||||
|
||||
assert 10**500 / (2*10**(500-308)) == 5e307
|
||||
assert 10**500 / (10**(500-308)) == 1e308
|
||||
try:
|
||||
10**500 / (10**(500-309))
|
||||
except OverflowError:
|
||||
pass
|
||||
else:
|
||||
assert False, 'Expected overflow on too big result'
|
||||
assert_raises(OverflowError, lambda: 10**500 / (10**(500-309)), 'too big result')
|
||||
|
||||
# a bit more than f64::MAX = 1.7976931348623157e+308_f64
|
||||
assert (2 * 10**308) / 2 == 1e308
|
||||
|
||||
# when dividing too big int by a float, the operation should fail
|
||||
try:
|
||||
(2 * 10**308) / 2.0
|
||||
except OverflowError:
|
||||
pass
|
||||
else:
|
||||
assert False, 'Expected overflow on division of a big int by a float'
|
||||
assert_raises(OverflowError, lambda: (2 * 10**308) / 2.0, 'division of big int by float')
|
||||
@@ -1,22 +1,6 @@
|
||||
import math
|
||||
|
||||
def assert_raises(expr, exc_type):
|
||||
"""
|
||||
Helper function to assert `expr` raises an exception of type `exc_type`
|
||||
Args:
|
||||
expr: Callable
|
||||
exec_type: Exception
|
||||
Returns:
|
||||
None
|
||||
Raises:
|
||||
Assertion error on failure
|
||||
"""
|
||||
try:
|
||||
expr(None)
|
||||
except exc_type:
|
||||
assert True
|
||||
else:
|
||||
assert False
|
||||
from testutils import assert_raises
|
||||
|
||||
1 + 1.1
|
||||
|
||||
@@ -79,8 +63,8 @@ assert float('2.99e-23') == 2.99e-23
|
||||
assert float(b'3.14') == 3.14
|
||||
assert float(b'2.99e-23') == 2.99e-23
|
||||
|
||||
assert_raises(lambda _: float('foo'), ValueError)
|
||||
assert_raises(lambda _: float(2**10000), OverflowError)
|
||||
assert_raises(ValueError, lambda: float('foo'))
|
||||
assert_raises(OverflowError, lambda: float(2**10000))
|
||||
|
||||
# check that magic methods are implemented for ints and floats
|
||||
|
||||
|
||||
@@ -1,21 +1,12 @@
|
||||
from testutils import assert_raises
|
||||
|
||||
def no_args():
|
||||
pass
|
||||
|
||||
no_args()
|
||||
|
||||
try:
|
||||
no_args('one_arg')
|
||||
except TypeError:
|
||||
pass
|
||||
else:
|
||||
assert False, 'no TypeError raised: 1 arg to no_args'
|
||||
|
||||
try:
|
||||
no_args(kw='should fail')
|
||||
except TypeError:
|
||||
pass
|
||||
else:
|
||||
assert False, 'no TypeError raised: kwarg to no_args'
|
||||
assert_raises(TypeError, lambda: no_args('one_arg'), '1 arg to no_args')
|
||||
assert_raises(TypeError, lambda: no_args(kw='should fail'), 'kwarg to no_args')
|
||||
|
||||
|
||||
def one_arg(arg):
|
||||
@@ -24,40 +15,20 @@ def one_arg(arg):
|
||||
one_arg('one_arg')
|
||||
assert "arg" == one_arg(arg="arg")
|
||||
|
||||
try:
|
||||
one_arg()
|
||||
except TypeError:
|
||||
pass
|
||||
else:
|
||||
assert False, 'no TypeError raised: no args to one_arg'
|
||||
assert_raises(TypeError, lambda: one_arg(), 'no args to one_arg')
|
||||
assert_raises(TypeError,
|
||||
lambda: one_arg(wrong_arg='wont work'),
|
||||
'incorrect kwarg to one_arg')
|
||||
assert_raises(TypeError,
|
||||
lambda: one_arg('one_arg', 'two_arg'),
|
||||
'two args to one_arg')
|
||||
assert_raises(TypeError,
|
||||
lambda: one_arg('one_arg', extra_arg='wont work'),
|
||||
'no TypeError raised: extra kwarg to one_arg')
|
||||
|
||||
try:
|
||||
one_arg(wrong_arg='wont work')
|
||||
except TypeError:
|
||||
pass
|
||||
else:
|
||||
assert False, 'no TypeError raised: incorrect kwarg to one_arg'
|
||||
|
||||
try:
|
||||
one_arg('one_arg', 'two_arg')
|
||||
except TypeError:
|
||||
pass
|
||||
else:
|
||||
assert False, 'no TypeError raised: two args to one_arg'
|
||||
|
||||
try:
|
||||
one_arg('one_arg', extra_arg='wont work')
|
||||
except TypeError:
|
||||
pass
|
||||
else:
|
||||
assert False, 'no TypeError raised: extra kwarg to one_arg'
|
||||
|
||||
try:
|
||||
one_arg('one_arg', arg='duplicate')
|
||||
except TypeError:
|
||||
pass
|
||||
else:
|
||||
assert False, 'no TypeError raised: same pos and kwarg to one_arg'
|
||||
assert_raises(TypeError,
|
||||
lambda: one_arg('one_arg', arg='duplicate'),
|
||||
'same pos and kwarg to one_arg')
|
||||
|
||||
|
||||
def one_default_arg(arg="default"):
|
||||
@@ -67,12 +38,9 @@ assert 'default' == one_default_arg()
|
||||
assert 'arg' == one_default_arg('arg')
|
||||
assert 'kwarg' == one_default_arg(arg='kwarg')
|
||||
|
||||
try:
|
||||
one_default_arg('one_arg', 'two_arg')
|
||||
except TypeError:
|
||||
pass
|
||||
else:
|
||||
assert False, 'no TypeError raised: two args to one_default_arg'
|
||||
assert_raises(TypeError,
|
||||
lambda: one_default_arg('one_arg', 'two_arg'),
|
||||
'two args to one_default_arg')
|
||||
|
||||
|
||||
def one_normal_one_default_arg(pos, arg="default"):
|
||||
@@ -81,19 +49,13 @@ def one_normal_one_default_arg(pos, arg="default"):
|
||||
assert ('arg', 'default') == one_normal_one_default_arg('arg')
|
||||
assert ('arg', 'arg2') == one_normal_one_default_arg('arg', 'arg2')
|
||||
|
||||
try:
|
||||
one_normal_one_default_arg()
|
||||
except TypeError:
|
||||
pass
|
||||
else:
|
||||
assert False, 'no TypeError raised: no args to one_normal_one_default_arg'
|
||||
assert_raises(TypeError,
|
||||
lambda: one_normal_one_default_arg(),
|
||||
'no args to one_normal_one_default_arg')
|
||||
|
||||
try:
|
||||
one_normal_one_default_arg('one', 'two', 'three')
|
||||
except TypeError:
|
||||
pass
|
||||
else:
|
||||
assert False, 'no TypeError raised: three args to one_normal_one_default_arg'
|
||||
assert_raises(TypeError,
|
||||
lambda: one_normal_one_default_arg('one', 'two', 'three'),
|
||||
'three args to one_normal_one_default_arg')
|
||||
|
||||
|
||||
def two_pos(a, b):
|
||||
|
||||
@@ -0,0 +1,109 @@
|
||||
class InPlace:
|
||||
def __init__(self, val):
|
||||
self.val = val
|
||||
|
||||
def __ipow__(self, other):
|
||||
self.val **= other
|
||||
return self
|
||||
|
||||
def __imul__(self, other):
|
||||
self.val *= other
|
||||
return self
|
||||
|
||||
def __imatmul__(self, other):
|
||||
# I guess you could think of an int as a 1x1 matrix
|
||||
self.val *= other
|
||||
return self
|
||||
|
||||
def __itruediv__(self, other):
|
||||
self.val /= other
|
||||
return self
|
||||
|
||||
def __ifloordiv__(self, other):
|
||||
self.val //= other
|
||||
return self
|
||||
|
||||
def __imod__(self, other):
|
||||
self.val %= other
|
||||
return self
|
||||
|
||||
def __iadd__(self, other):
|
||||
self.val += other
|
||||
return self
|
||||
|
||||
def __isub__(self, other):
|
||||
self.val -= other
|
||||
return self
|
||||
|
||||
def __ilshift__(self, other):
|
||||
self.val <<= other
|
||||
return self
|
||||
|
||||
def __irshift__(self, other):
|
||||
self.val >>= other
|
||||
return self
|
||||
|
||||
def __iand__(self, other):
|
||||
self.val &= other
|
||||
return self
|
||||
|
||||
def __ixor__(self, other):
|
||||
self.val ^= other
|
||||
return self
|
||||
|
||||
def __ior__(self, other):
|
||||
self.val |= other
|
||||
return self
|
||||
|
||||
|
||||
i = InPlace(2)
|
||||
i **= 3
|
||||
assert i.val == 8
|
||||
|
||||
i = InPlace(2)
|
||||
i *= 2
|
||||
assert i.val == 4
|
||||
|
||||
i = InPlace(2)
|
||||
i @= 2
|
||||
assert i.val == 4
|
||||
|
||||
i = InPlace(1)
|
||||
i /= 2
|
||||
assert i.val == 0.5
|
||||
|
||||
i = InPlace(1)
|
||||
i //= 2
|
||||
assert i.val == 0
|
||||
|
||||
i = InPlace(10)
|
||||
i %= 3
|
||||
assert i.val == 1
|
||||
|
||||
i = InPlace(1)
|
||||
i += 1
|
||||
assert i.val == 2
|
||||
|
||||
i = InPlace(2)
|
||||
i -= 1
|
||||
assert i.val == 1
|
||||
|
||||
i = InPlace(2)
|
||||
i <<= 3
|
||||
assert i.val == 16
|
||||
|
||||
i = InPlace(16)
|
||||
i >>= 3
|
||||
assert i.val == 2
|
||||
|
||||
i = InPlace(0b010101)
|
||||
i &= 0b111000
|
||||
assert i.val == 0b010000
|
||||
|
||||
i = InPlace(0b010101)
|
||||
i ^= 0b111000
|
||||
assert i.val == 0b101101
|
||||
|
||||
i = InPlace(0b010101)
|
||||
i |= 0b111000
|
||||
assert i.val == 0b111101
|
||||
@@ -32,6 +32,11 @@ assert (2).__rmul__(1) == 2
|
||||
assert (2).__truediv__(1) == 2.0
|
||||
assert (2).__rtruediv__(1) == 0.5
|
||||
|
||||
# real/imag attributes
|
||||
assert (1).real == 1
|
||||
assert (1).imag == 0
|
||||
|
||||
|
||||
assert (1).__eq__(1.0) == NotImplemented
|
||||
assert (1).__ne__(1.0) == NotImplemented
|
||||
assert (1).__gt__(1.0) == NotImplemented
|
||||
|
||||
+53
-24
@@ -1,3 +1,5 @@
|
||||
from testutils import assert_raises
|
||||
|
||||
x = [1, 2, 3]
|
||||
assert x[0] == 1
|
||||
assert x[1] == 2
|
||||
@@ -16,12 +18,7 @@ assert x * 2 == [1, 2, 3, 1, 2, 3], "list __mul__ by 2 failed"
|
||||
# index()
|
||||
assert ['a', 'b', 'c'].index('b') == 1
|
||||
assert [5, 6, 7].index(7) == 2
|
||||
try:
|
||||
['a', 'b', 'c'].index('z')
|
||||
except ValueError:
|
||||
pass
|
||||
else:
|
||||
assert False, "ValueError was not raised"
|
||||
assert_raises(ValueError, lambda: ['a', 'b', 'c'].index('z'))
|
||||
|
||||
x = [[1,0,-3], 'a', 1]
|
||||
y = [[3,2,1], 'z', 2]
|
||||
@@ -33,12 +30,7 @@ assert x > y, "list __gt__ failed"
|
||||
|
||||
|
||||
assert [1,2,'a'].pop() == 'a', "list pop failed"
|
||||
try:
|
||||
[].pop()
|
||||
except IndexError:
|
||||
pass
|
||||
else:
|
||||
assert False, "IndexError was not raised"
|
||||
assert_raises(IndexError, lambda: [].pop())
|
||||
|
||||
recursive = []
|
||||
recursive.append(recursive)
|
||||
@@ -61,12 +53,7 @@ x = ['a', 'b', 'c']
|
||||
x.insert(-100, 'z')
|
||||
assert x == ['z', 'a', 'b', 'c']
|
||||
|
||||
try:
|
||||
x.insert(100000000000000000000, 'z')
|
||||
except OverflowError:
|
||||
pass
|
||||
else:
|
||||
assert False, "OverflowError was not raised"
|
||||
assert_raises(OverflowError, lambda: x.insert(100000000000000000000, 'z'))
|
||||
|
||||
x = [[], 2, {}]
|
||||
y = x.copy()
|
||||
@@ -82,9 +69,51 @@ a.remove(1)
|
||||
assert len(a) == 2
|
||||
assert not 1 in a
|
||||
|
||||
try:
|
||||
a.remove(10)
|
||||
except ValueError:
|
||||
pass
|
||||
else:
|
||||
assert False, "Remove not exist element should raise ValueError"
|
||||
assert_raises(ValueError, lambda: a.remove(10), 'Remove not exist element')
|
||||
|
||||
foo = bar = [1]
|
||||
foo += [2]
|
||||
assert (foo, bar) == ([1, 2], [1, 2])
|
||||
|
||||
|
||||
x = [1]
|
||||
x.append(x)
|
||||
assert x in x
|
||||
assert x.index(x) == 1
|
||||
assert x.count(x) == 1
|
||||
x.remove(x)
|
||||
assert x not in x
|
||||
|
||||
class Foo(object):
|
||||
def __eq__(self, x):
|
||||
return False
|
||||
|
||||
foo = Foo()
|
||||
foo1 = Foo()
|
||||
x = [1, foo, 2, foo, []]
|
||||
assert x == x
|
||||
assert foo in x
|
||||
assert 2 in x
|
||||
assert x.index(foo) == 1
|
||||
assert x.count(foo) == 2
|
||||
assert x.index(2) == 2
|
||||
assert [] in x
|
||||
assert x.index([]) == 4
|
||||
assert foo1 not in x
|
||||
x.remove(foo)
|
||||
assert x.index(foo) == 2
|
||||
assert x.count(foo) == 1
|
||||
|
||||
x = []
|
||||
x.append(x)
|
||||
assert x == x
|
||||
|
||||
a = [1, 2, 3]
|
||||
b = [1, 2, 3]
|
||||
c = [a, b]
|
||||
a.append(c)
|
||||
b.append(c)
|
||||
|
||||
assert a == b
|
||||
|
||||
assert [foo] == [foo]
|
||||
@@ -1,3 +1,5 @@
|
||||
from testutils import assert_raises
|
||||
|
||||
# test lists
|
||||
assert 3 in [1, 2, 3]
|
||||
assert 3 not in [1, 2]
|
||||
@@ -19,12 +21,7 @@ assert b"5" <= b"5"
|
||||
assert b"4" > b"2"
|
||||
assert not b"1" >= b"2"
|
||||
assert b"10" >= b"10"
|
||||
try:
|
||||
bytes() > 2
|
||||
except TypeError:
|
||||
pass
|
||||
else:
|
||||
assert False, "TypeError not raised"
|
||||
assert_raises(TypeError, lambda: bytes() > 2)
|
||||
|
||||
# test tuple
|
||||
assert 1 in (1, 2)
|
||||
@@ -53,12 +50,7 @@ class MyNotContainingClass():
|
||||
pass
|
||||
|
||||
|
||||
try:
|
||||
1 in MyNotContainingClass()
|
||||
except TypeError:
|
||||
pass
|
||||
else:
|
||||
assert False, "TypeError not raised"
|
||||
assert_raises(TypeError, lambda: 1 in MyNotContainingClass())
|
||||
|
||||
|
||||
class MyContainingClass():
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
import os
|
||||
|
||||
assert os.name == 'posix'
|
||||
assert os.name == 'posix' or os.name == 'nt'
|
||||
@@ -1,18 +1,9 @@
|
||||
from testutils import assert_raises
|
||||
|
||||
print(2 + 3)
|
||||
|
||||
try:
|
||||
print('test', end=4)
|
||||
except TypeError:
|
||||
pass
|
||||
else:
|
||||
assert False, 'Expected TypeError on wrong type passed to end'
|
||||
|
||||
try:
|
||||
print('test', sep=['a'])
|
||||
except TypeError:
|
||||
pass
|
||||
else:
|
||||
assert False, 'Expected TypeError on wrong type passed to sep'
|
||||
assert_raises(TypeError, lambda: print('test', end=4), 'wrong type passed to end')
|
||||
assert_raises(TypeError, lambda: print('test', sep=['a']), 'wrong type passed to sep')
|
||||
|
||||
try:
|
||||
print('test', end=None, sep=None, flush=None)
|
||||
|
||||
+70
-14
@@ -1,3 +1,5 @@
|
||||
from testutils import assert_raises, assertRaises
|
||||
|
||||
assert set([1,2]) == set([1,2])
|
||||
assert not set([1,2,3]) == set([1,2])
|
||||
|
||||
@@ -69,22 +71,76 @@ assert set([1,2,3]).symmetric_difference(set([5,6])) == set([1,2,3,5,6])
|
||||
assert set([1,2,3]) ^ set([4,5]) == set([1,2,3,4,5])
|
||||
assert set([1,2,3]) ^ set([1,2,3,4,5]) == set([4,5])
|
||||
|
||||
try:
|
||||
set([[]])
|
||||
except TypeError:
|
||||
pass
|
||||
else:
|
||||
assert False, "TypeError was not raised"
|
||||
|
||||
try:
|
||||
set().add([])
|
||||
except TypeError:
|
||||
pass
|
||||
else:
|
||||
assert False, "TypeError was not raised"
|
||||
assert_raises(TypeError, lambda: set([[]]))
|
||||
assert_raises(TypeError, lambda: set().add([]))
|
||||
|
||||
a = set([1, 2, 3])
|
||||
assert a.discard(1) is None
|
||||
assert not 1 in a
|
||||
|
||||
assert a.discard(42) is None
|
||||
|
||||
a = set([1,2,3])
|
||||
b = a.copy()
|
||||
assert len(a) == 3
|
||||
assert len(b) == 3
|
||||
b.clear()
|
||||
assert len(a) == 3
|
||||
assert len(b) == 0
|
||||
|
||||
a = set([1,2])
|
||||
b = a.pop()
|
||||
assert b in [1,2]
|
||||
c = a.pop()
|
||||
assert (c in [1,2] and c != b)
|
||||
assert_raises(KeyError, lambda: a.pop())
|
||||
|
||||
a = set([1,2,3])
|
||||
a.update([3,4,5])
|
||||
assert a == set([1,2,3,4,5])
|
||||
assert_raises(TypeError, lambda: a.update(1))
|
||||
|
||||
a = set([1,2,3])
|
||||
b = set()
|
||||
for e in a:
|
||||
assert e == 1 or e == 2 or e == 3
|
||||
b.add(e)
|
||||
assert a == b
|
||||
|
||||
a = set([1,2,3])
|
||||
a |= set([3,4,5])
|
||||
assert a == set([1,2,3,4,5])
|
||||
with assertRaises(TypeError):
|
||||
a |= 1
|
||||
|
||||
a = set([1,2,3])
|
||||
a.intersection_update([2,3,4,5])
|
||||
assert a == set([2,3])
|
||||
assert_raises(TypeError, lambda: a.intersection_update(1))
|
||||
|
||||
a = set([1,2,3])
|
||||
a &= set([2,3,4,5])
|
||||
assert a == set([2,3])
|
||||
with assertRaises(TypeError):
|
||||
a &= 1
|
||||
|
||||
a = set([1,2,3])
|
||||
a.difference_update([3,4,5])
|
||||
assert a == set([1,2])
|
||||
assert_raises(TypeError, lambda: a.difference_update(1))
|
||||
|
||||
a = set([1,2,3])
|
||||
a -= set([3,4,5])
|
||||
assert a == set([1,2])
|
||||
with assertRaises(TypeError):
|
||||
a -= 1
|
||||
|
||||
a = set([1,2,3])
|
||||
a.symmetric_difference_update([3,4,5])
|
||||
assert a == set([1,2,4,5])
|
||||
assert_raises(TypeError, lambda: a.difference_update(1))
|
||||
|
||||
a = set([1,2,3])
|
||||
a ^= set([3,4,5])
|
||||
assert a == set([1,2,4,5])
|
||||
with assertRaises(TypeError):
|
||||
a ^= 1
|
||||
@@ -1,13 +1,11 @@
|
||||
import os
|
||||
|
||||
from testutils import assert_raises
|
||||
|
||||
assert os.open('README.md', 0) > 0
|
||||
|
||||
|
||||
try:
|
||||
os.open('DOES_NOT_EXIST', 0)
|
||||
assert False
|
||||
except FileNotFoundError:
|
||||
pass
|
||||
assert_raises(FileNotFoundError, lambda: os.open('DOES_NOT_EXIST', 0))
|
||||
|
||||
|
||||
assert os.O_RDONLY == 0
|
||||
|
||||
@@ -1,20 +1,4 @@
|
||||
def assert_raises(expr, exc_type):
|
||||
"""
|
||||
Helper function to assert `expr` raises an exception of type `exc_type`
|
||||
Args:
|
||||
expr: Callable
|
||||
exec_type: Exception
|
||||
Returns:
|
||||
None
|
||||
Raises:
|
||||
Assertion error on failure
|
||||
"""
|
||||
try:
|
||||
expr(None)
|
||||
except exc_type:
|
||||
assert True
|
||||
else:
|
||||
assert False
|
||||
from testutils import assert_raises
|
||||
|
||||
#
|
||||
# Tests
|
||||
@@ -23,15 +7,15 @@ assert 8 >> 3 == 1
|
||||
assert 8 << 3 == 64
|
||||
|
||||
# Left shift raises type error
|
||||
assert_raises(lambda _: 1 << 0.1, TypeError)
|
||||
assert_raises(lambda _: 1 << "abc", TypeError)
|
||||
assert_raises(TypeError, lambda: 1 << 0.1)
|
||||
assert_raises(TypeError, lambda: 1 << "abc")
|
||||
|
||||
# Right shift raises type error
|
||||
assert_raises(lambda _: 1 >> 0.1, TypeError)
|
||||
assert_raises(lambda _: 1 >> "abc", TypeError)
|
||||
assert_raises(TypeError, lambda: 1 >> 0.1)
|
||||
assert_raises(TypeError, lambda: 1 >> "abc")
|
||||
|
||||
# Left shift raises value error on negative
|
||||
assert_raises(lambda _: 1 << -1, ValueError)
|
||||
assert_raises(ValueError, lambda: 1 << -1)
|
||||
|
||||
# Right shift raises value error on negative
|
||||
assert_raises(lambda _: 1 >> -1, ValueError)
|
||||
assert_raises(ValueError, lambda: 1 >> -1)
|
||||
@@ -0,0 +1,36 @@
|
||||
def assert_raises(exc_type, expr, msg=None):
|
||||
"""
|
||||
Helper function to assert `expr` raises an exception of type `exc_type`.
|
||||
Args:
|
||||
expr: Callable
|
||||
exec_type: Exception
|
||||
Returns:
|
||||
None
|
||||
Raises:
|
||||
Assertion error on failure
|
||||
"""
|
||||
try:
|
||||
expr()
|
||||
except exc_type:
|
||||
pass
|
||||
else:
|
||||
failmsg = '{!s} was not raised'.format(exc_type.__name__)
|
||||
if msg is not None:
|
||||
failmsg += ': {!s}'.format(msg)
|
||||
assert False, failmsg
|
||||
|
||||
|
||||
class assertRaises:
|
||||
def __init__(self, expected):
|
||||
self.expected = expected
|
||||
|
||||
def __enter__(self):
|
||||
return self
|
||||
|
||||
def __exit__(self, exc_type, exc_val, exc_tb):
|
||||
if exc_type is None:
|
||||
failmsg = '{!s} was not raised'.format(self.expected.__name_)
|
||||
assert False, failmsg
|
||||
if not issubclass(exc_type, self.expected):
|
||||
return False
|
||||
return True
|
||||
@@ -27,3 +27,10 @@ assert repr(recursive) == "([(...)],)"
|
||||
|
||||
assert (None, "", 1).index(1) == 2
|
||||
assert 1 in (None, "", 1)
|
||||
|
||||
class Foo(object):
|
||||
def __eq__(self, x):
|
||||
return False
|
||||
|
||||
foo = Foo()
|
||||
assert (foo,) == (foo,)
|
||||
@@ -77,8 +77,12 @@ def run_via_rustpython(filename, test_type):
|
||||
log_level = 'info' if test_type == _TestType.benchmark else 'trace'
|
||||
env['RUST_LOG'] = '{},cargo=error,jobserver=error'.format(log_level)
|
||||
env['RUST_BACKTRACE'] = '1'
|
||||
subprocess.check_call(
|
||||
['cargo', 'run', '--release', filename], env=env)
|
||||
if env.get('CODE_COVERAGE', 'false') == 'true':
|
||||
subprocess.check_call(
|
||||
['cargo', 'run', filename], env=env)
|
||||
else:
|
||||
subprocess.check_call(
|
||||
['cargo', 'run', '--release', filename], env=env)
|
||||
|
||||
|
||||
def create_test_function(cls, filename, method, test_type):
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
name = "rustpython_vm"
|
||||
version = "0.1.0"
|
||||
authors = ["Shing Lyu <shing.lyu@gmail.com>"]
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
bitflags = "1.0.4"
|
||||
|
||||
+99
-139
@@ -4,26 +4,25 @@
|
||||
|
||||
// use std::ops::Deref;
|
||||
use std::char;
|
||||
use std::error::Error;
|
||||
use std::io::{self, Write};
|
||||
|
||||
use super::compile;
|
||||
use super::obj::objbool;
|
||||
use super::obj::objdict;
|
||||
use super::obj::objint;
|
||||
use super::obj::objiter;
|
||||
use super::obj::objstr;
|
||||
use super::obj::objtype;
|
||||
use crate::compile;
|
||||
use crate::obj::objbool;
|
||||
use crate::obj::objdict;
|
||||
use crate::obj::objint;
|
||||
use crate::obj::objiter;
|
||||
use crate::obj::objstr;
|
||||
use crate::obj::objtype;
|
||||
|
||||
use super::pyobject::{
|
||||
use crate::pyobject::{
|
||||
AttributeProtocol, IdProtocol, PyContext, PyFuncArgs, PyObject, PyObjectPayload, PyObjectRef,
|
||||
PyResult, Scope, TypeProtocol,
|
||||
};
|
||||
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
use super::stdlib::io::io_open;
|
||||
use crate::stdlib::io::io_open;
|
||||
|
||||
use super::vm::VirtualMachine;
|
||||
use crate::vm::VirtualMachine;
|
||||
use num_traits::{Signed, ToPrimitive};
|
||||
|
||||
fn get_locals(vm: &mut VirtualMachine) -> PyObjectRef {
|
||||
@@ -154,7 +153,7 @@ fn builtin_compile(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
|
||||
compile::compile(&source, &mode, filename, vm.ctx.code_type()).map_err(|err| {
|
||||
let syntax_error = vm.context().exceptions.syntax_error.clone();
|
||||
vm.new_exception(syntax_error, err.description().to_string())
|
||||
vm.new_exception(syntax_error, err.to_string())
|
||||
})
|
||||
}
|
||||
|
||||
@@ -208,7 +207,7 @@ fn builtin_eval(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
compile::compile(&source, &mode, "<string>".to_string(), vm.ctx.code_type()).map_err(
|
||||
|err| {
|
||||
let syntax_error = vm.context().exceptions.syntax_error.clone();
|
||||
vm.new_exception(syntax_error, err.description().to_string())
|
||||
vm.new_exception(syntax_error, err.to_string())
|
||||
},
|
||||
)?
|
||||
} else {
|
||||
@@ -243,7 +242,7 @@ fn builtin_exec(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
compile::compile(&source, &mode, "<string>".to_string(), vm.ctx.code_type()).map_err(
|
||||
|err| {
|
||||
let syntax_error = vm.context().exceptions.syntax_error.clone();
|
||||
vm.new_exception(syntax_error, err.description().to_string())
|
||||
vm.new_exception(syntax_error, err.to_string())
|
||||
},
|
||||
)?
|
||||
} else if objtype::isinstance(source, &vm.ctx.code_type()) {
|
||||
@@ -705,135 +704,96 @@ fn builtin_sum(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
// builtin___import__
|
||||
|
||||
pub fn make_module(ctx: &PyContext) -> PyObjectRef {
|
||||
let mod_name = "__builtins__";
|
||||
let py_mod = ctx.new_module(mod_name, ctx.new_scope(None));
|
||||
let py_mod = py_module!(ctx, "__builtins__", {
|
||||
//set __name__ fixes: https://github.com/RustPython/RustPython/issues/146
|
||||
"__name__" => ctx.new_str(String::from("__main__")),
|
||||
|
||||
//set __name__ fixes: https://github.com/RustPython/RustPython/issues/146
|
||||
ctx.set_attr(&py_mod, "__name__", ctx.new_str(String::from("__main__")));
|
||||
"abs" => ctx.new_rustfunc(builtin_abs),
|
||||
"all" => ctx.new_rustfunc(builtin_all),
|
||||
"any" => ctx.new_rustfunc(builtin_any),
|
||||
"bin" => ctx.new_rustfunc(builtin_bin),
|
||||
"bool" => ctx.bool_type(),
|
||||
"bytearray" => ctx.bytearray_type(),
|
||||
"bytes" => ctx.bytes_type(),
|
||||
"callable" => ctx.new_rustfunc(builtin_callable),
|
||||
"chr" => ctx.new_rustfunc(builtin_chr),
|
||||
"classmethod" => ctx.classmethod_type(),
|
||||
"compile" => ctx.new_rustfunc(builtin_compile),
|
||||
"complex" => ctx.complex_type(),
|
||||
"delattr" => ctx.new_rustfunc(builtin_delattr),
|
||||
"dict" => ctx.dict_type(),
|
||||
"divmod" => ctx.new_rustfunc(builtin_divmod),
|
||||
"dir" => ctx.new_rustfunc(builtin_dir),
|
||||
"enumerate" => ctx.enumerate_type(),
|
||||
"eval" => ctx.new_rustfunc(builtin_eval),
|
||||
"exec" => ctx.new_rustfunc(builtin_exec),
|
||||
"float" => ctx.float_type(),
|
||||
"frozenset" => ctx.frozenset_type(),
|
||||
"filter" => ctx.filter_type(),
|
||||
"format" => ctx.new_rustfunc(builtin_format),
|
||||
"getattr" => ctx.new_rustfunc(builtin_getattr),
|
||||
"hasattr" => ctx.new_rustfunc(builtin_hasattr),
|
||||
"hash" => ctx.new_rustfunc(builtin_hash),
|
||||
"hex" => ctx.new_rustfunc(builtin_hex),
|
||||
"id" => ctx.new_rustfunc(builtin_id),
|
||||
"int" => ctx.int_type(),
|
||||
"isinstance" => ctx.new_rustfunc(builtin_isinstance),
|
||||
"issubclass" => ctx.new_rustfunc(builtin_issubclass),
|
||||
"iter" => ctx.new_rustfunc(builtin_iter),
|
||||
"len" => ctx.new_rustfunc(builtin_len),
|
||||
"list" => ctx.list_type(),
|
||||
"locals" => ctx.new_rustfunc(builtin_locals),
|
||||
"map" => ctx.map_type(),
|
||||
"max" => ctx.new_rustfunc(builtin_max),
|
||||
"memoryview" => ctx.memoryview_type(),
|
||||
"min" => ctx.new_rustfunc(builtin_min),
|
||||
"object" => ctx.object(),
|
||||
"oct" => ctx.new_rustfunc(builtin_oct),
|
||||
"ord" => ctx.new_rustfunc(builtin_ord),
|
||||
"next" => ctx.new_rustfunc(builtin_next),
|
||||
"pow" => ctx.new_rustfunc(builtin_pow),
|
||||
"print" => ctx.new_rustfunc(builtin_print),
|
||||
"property" => ctx.property_type(),
|
||||
"range" => ctx.range_type(),
|
||||
"repr" => ctx.new_rustfunc(builtin_repr),
|
||||
"reversed" => ctx.new_rustfunc(builtin_reversed),
|
||||
"round" => ctx.new_rustfunc(builtin_round),
|
||||
"set" => ctx.set_type(),
|
||||
"setattr" => ctx.new_rustfunc(builtin_setattr),
|
||||
"slice" => ctx.slice_type(),
|
||||
"staticmethod" => ctx.staticmethod_type(),
|
||||
"str" => ctx.str_type(),
|
||||
"sum" => ctx.new_rustfunc(builtin_sum),
|
||||
"super" => ctx.super_type(),
|
||||
"tuple" => ctx.tuple_type(),
|
||||
"type" => ctx.type_type(),
|
||||
"zip" => ctx.zip_type(),
|
||||
|
||||
// Constants
|
||||
"NotImplemented" => ctx.not_implemented.clone(),
|
||||
|
||||
// Exceptions:
|
||||
"BaseException" => ctx.exceptions.base_exception_type.clone(),
|
||||
"Exception" => ctx.exceptions.exception_type.clone(),
|
||||
"ArithmeticError" => ctx.exceptions.arithmetic_error.clone(),
|
||||
"AssertionError" => ctx.exceptions.assertion_error.clone(),
|
||||
"AttributeError" => ctx.exceptions.attribute_error.clone(),
|
||||
"NameError" => ctx.exceptions.name_error.clone(),
|
||||
"OverflowError" => ctx.exceptions.overflow_error.clone(),
|
||||
"RuntimeError" => ctx.exceptions.runtime_error.clone(),
|
||||
"NotImplementedError" => ctx.exceptions.not_implemented_error.clone(),
|
||||
"TypeError" => ctx.exceptions.type_error.clone(),
|
||||
"ValueError" => ctx.exceptions.value_error.clone(),
|
||||
"IndexError" => ctx.exceptions.index_error.clone(),
|
||||
"ImportError" => ctx.exceptions.import_error.clone(),
|
||||
"FileNotFoundError" => ctx.exceptions.file_not_found_error.clone(),
|
||||
"StopIteration" => ctx.exceptions.stop_iteration.clone(),
|
||||
"ZeroDivisionError" => ctx.exceptions.zero_division_error.clone(),
|
||||
"KeyError" => ctx.exceptions.key_error.clone(),
|
||||
});
|
||||
|
||||
ctx.set_attr(&py_mod, "abs", ctx.new_rustfunc(builtin_abs));
|
||||
ctx.set_attr(&py_mod, "all", ctx.new_rustfunc(builtin_all));
|
||||
ctx.set_attr(&py_mod, "any", ctx.new_rustfunc(builtin_any));
|
||||
ctx.set_attr(&py_mod, "bin", ctx.new_rustfunc(builtin_bin));
|
||||
ctx.set_attr(&py_mod, "bool", ctx.bool_type());
|
||||
ctx.set_attr(&py_mod, "bytearray", ctx.bytearray_type());
|
||||
ctx.set_attr(&py_mod, "bytes", ctx.bytes_type());
|
||||
ctx.set_attr(&py_mod, "callable", ctx.new_rustfunc(builtin_callable));
|
||||
ctx.set_attr(&py_mod, "chr", ctx.new_rustfunc(builtin_chr));
|
||||
ctx.set_attr(&py_mod, "classmethod", ctx.classmethod_type());
|
||||
ctx.set_attr(&py_mod, "compile", ctx.new_rustfunc(builtin_compile));
|
||||
ctx.set_attr(&py_mod, "complex", ctx.complex_type());
|
||||
ctx.set_attr(&py_mod, "delattr", ctx.new_rustfunc(builtin_delattr));
|
||||
ctx.set_attr(&py_mod, "dict", ctx.dict_type());
|
||||
ctx.set_attr(&py_mod, "divmod", ctx.new_rustfunc(builtin_divmod));
|
||||
ctx.set_attr(&py_mod, "dir", ctx.new_rustfunc(builtin_dir));
|
||||
ctx.set_attr(&py_mod, "enumerate", ctx.enumerate_type());
|
||||
ctx.set_attr(&py_mod, "eval", ctx.new_rustfunc(builtin_eval));
|
||||
ctx.set_attr(&py_mod, "exec", ctx.new_rustfunc(builtin_exec));
|
||||
ctx.set_attr(&py_mod, "float", ctx.float_type());
|
||||
ctx.set_attr(&py_mod, "frozenset", ctx.frozenset_type());
|
||||
ctx.set_attr(&py_mod, "filter", ctx.filter_type());
|
||||
ctx.set_attr(&py_mod, "format", ctx.new_rustfunc(builtin_format));
|
||||
ctx.set_attr(&py_mod, "getattr", ctx.new_rustfunc(builtin_getattr));
|
||||
ctx.set_attr(&py_mod, "hasattr", ctx.new_rustfunc(builtin_hasattr));
|
||||
ctx.set_attr(&py_mod, "hash", ctx.new_rustfunc(builtin_hash));
|
||||
ctx.set_attr(&py_mod, "hex", ctx.new_rustfunc(builtin_hex));
|
||||
ctx.set_attr(&py_mod, "id", ctx.new_rustfunc(builtin_id));
|
||||
ctx.set_attr(&py_mod, "int", ctx.int_type());
|
||||
ctx.set_attr(&py_mod, "isinstance", ctx.new_rustfunc(builtin_isinstance));
|
||||
ctx.set_attr(&py_mod, "issubclass", ctx.new_rustfunc(builtin_issubclass));
|
||||
ctx.set_attr(&py_mod, "iter", ctx.new_rustfunc(builtin_iter));
|
||||
ctx.set_attr(&py_mod, "len", ctx.new_rustfunc(builtin_len));
|
||||
ctx.set_attr(&py_mod, "list", ctx.list_type());
|
||||
ctx.set_attr(&py_mod, "locals", ctx.new_rustfunc(builtin_locals));
|
||||
ctx.set_attr(&py_mod, "map", ctx.map_type());
|
||||
ctx.set_attr(&py_mod, "max", ctx.new_rustfunc(builtin_max));
|
||||
ctx.set_attr(&py_mod, "memoryview", ctx.memoryview_type());
|
||||
ctx.set_attr(&py_mod, "min", ctx.new_rustfunc(builtin_min));
|
||||
ctx.set_attr(&py_mod, "object", ctx.object());
|
||||
ctx.set_attr(&py_mod, "oct", ctx.new_rustfunc(builtin_oct));
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
ctx.set_attr(&py_mod, "open", ctx.new_rustfunc(io_open));
|
||||
ctx.set_attr(&py_mod, "ord", ctx.new_rustfunc(builtin_ord));
|
||||
ctx.set_attr(&py_mod, "next", ctx.new_rustfunc(builtin_next));
|
||||
ctx.set_attr(&py_mod, "pow", ctx.new_rustfunc(builtin_pow));
|
||||
ctx.set_attr(&py_mod, "print", ctx.new_rustfunc(builtin_print));
|
||||
ctx.set_attr(&py_mod, "property", ctx.property_type());
|
||||
ctx.set_attr(&py_mod, "range", ctx.range_type());
|
||||
ctx.set_attr(&py_mod, "repr", ctx.new_rustfunc(builtin_repr));
|
||||
ctx.set_attr(&py_mod, "reversed", ctx.new_rustfunc(builtin_reversed));
|
||||
ctx.set_attr(&py_mod, "round", ctx.new_rustfunc(builtin_round));
|
||||
ctx.set_attr(&py_mod, "set", ctx.set_type());
|
||||
ctx.set_attr(&py_mod, "setattr", ctx.new_rustfunc(builtin_setattr));
|
||||
ctx.set_attr(&py_mod, "slice", ctx.slice_type());
|
||||
ctx.set_attr(&py_mod, "staticmethod", ctx.staticmethod_type());
|
||||
ctx.set_attr(&py_mod, "str", ctx.str_type());
|
||||
ctx.set_attr(&py_mod, "sum", ctx.new_rustfunc(builtin_sum));
|
||||
ctx.set_attr(&py_mod, "super", ctx.super_type());
|
||||
ctx.set_attr(&py_mod, "tuple", ctx.tuple_type());
|
||||
ctx.set_attr(&py_mod, "type", ctx.type_type());
|
||||
ctx.set_attr(&py_mod, "zip", ctx.zip_type());
|
||||
|
||||
// Constants
|
||||
ctx.set_attr(&py_mod, "NotImplemented", ctx.not_implemented.clone());
|
||||
|
||||
// Exceptions:
|
||||
ctx.set_attr(
|
||||
&py_mod,
|
||||
"BaseException",
|
||||
ctx.exceptions.base_exception_type.clone(),
|
||||
);
|
||||
ctx.set_attr(&py_mod, "Exception", ctx.exceptions.exception_type.clone());
|
||||
ctx.set_attr(
|
||||
&py_mod,
|
||||
"ArithmeticError",
|
||||
ctx.exceptions.arithmetic_error.clone(),
|
||||
);
|
||||
ctx.set_attr(
|
||||
&py_mod,
|
||||
"AssertionError",
|
||||
ctx.exceptions.assertion_error.clone(),
|
||||
);
|
||||
ctx.set_attr(
|
||||
&py_mod,
|
||||
"AttributeError",
|
||||
ctx.exceptions.attribute_error.clone(),
|
||||
);
|
||||
ctx.set_attr(&py_mod, "NameError", ctx.exceptions.name_error.clone());
|
||||
ctx.set_attr(
|
||||
&py_mod,
|
||||
"OverflowError",
|
||||
ctx.exceptions.overflow_error.clone(),
|
||||
);
|
||||
ctx.set_attr(
|
||||
&py_mod,
|
||||
"RuntimeError",
|
||||
ctx.exceptions.runtime_error.clone(),
|
||||
);
|
||||
ctx.set_attr(
|
||||
&py_mod,
|
||||
"NotImplementedError",
|
||||
ctx.exceptions.not_implemented_error.clone(),
|
||||
);
|
||||
ctx.set_attr(&py_mod, "TypeError", ctx.exceptions.type_error.clone());
|
||||
ctx.set_attr(&py_mod, "ValueError", ctx.exceptions.value_error.clone());
|
||||
ctx.set_attr(&py_mod, "IndexError", ctx.exceptions.index_error.clone());
|
||||
ctx.set_attr(&py_mod, "ImportError", ctx.exceptions.import_error.clone());
|
||||
ctx.set_attr(
|
||||
&py_mod,
|
||||
"FileNotFoundError",
|
||||
ctx.exceptions.file_not_found_error.clone(),
|
||||
);
|
||||
ctx.set_attr(
|
||||
&py_mod,
|
||||
"StopIteration",
|
||||
ctx.exceptions.stop_iteration.clone(),
|
||||
);
|
||||
ctx.set_attr(
|
||||
&py_mod,
|
||||
"ZeroDivisionError",
|
||||
ctx.exceptions.zero_division_error.clone(),
|
||||
);
|
||||
|
||||
py_mod
|
||||
}
|
||||
|
||||
+121
-12
@@ -8,7 +8,7 @@
|
||||
use num_bigint::BigInt;
|
||||
use num_complex::Complex64;
|
||||
use rustpython_parser::ast;
|
||||
use std::collections::HashMap;
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::fmt;
|
||||
|
||||
/// Primary container of a single code object. Each python function has
|
||||
@@ -71,6 +71,7 @@ pub enum Instruction {
|
||||
},
|
||||
BinaryOperation {
|
||||
op: BinaryOperator,
|
||||
inplace: bool,
|
||||
},
|
||||
LoadAttr {
|
||||
name: String,
|
||||
@@ -172,6 +173,8 @@ pub enum Instruction {
|
||||
},
|
||||
}
|
||||
|
||||
use self::Instruction::*;
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub enum CallType {
|
||||
Positional(usize),
|
||||
@@ -276,17 +279,123 @@ impl CodeObject {
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for CodeObject {
|
||||
impl fmt::Display for CodeObject {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
let inst_str = self
|
||||
.instructions
|
||||
.iter()
|
||||
.zip(self.locations.iter())
|
||||
.enumerate()
|
||||
.map(|(i, inst)| format!("Inst {}: {:?}", i, inst))
|
||||
.collect::<Vec<_>>()
|
||||
.join("\n");
|
||||
let labelmap_str = format!("label_map: {:?}", self.label_map);
|
||||
write!(f, "Code Object {{ \n{}\n{} }}", inst_str, labelmap_str)
|
||||
let label_targets: HashSet<&usize> = self.label_map.values().collect();
|
||||
for (offset, instruction) in self.instructions.iter().enumerate() {
|
||||
let arrow = if label_targets.contains(&offset) {
|
||||
">>"
|
||||
} else {
|
||||
" "
|
||||
};
|
||||
write!(f, " {} {:5} ", arrow, offset)?;
|
||||
instruction.fmt_dis(f, &self.label_map)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl Instruction {
|
||||
fn fmt_dis(&self, f: &mut fmt::Formatter, label_map: &HashMap<Label, usize>) -> fmt::Result {
|
||||
macro_rules! w {
|
||||
($variant:ident) => {
|
||||
write!(f, "{:20}\n", stringify!($variant))
|
||||
};
|
||||
($variant:ident, $var:expr) => {
|
||||
write!(f, "{:20} ({})\n", stringify!($variant), $var)
|
||||
};
|
||||
($variant:ident, $var1:expr, $var2:expr) => {
|
||||
write!(f, "{:20} ({}, {})\n", stringify!($variant), $var1, $var2)
|
||||
};
|
||||
}
|
||||
|
||||
match self {
|
||||
Import { name, symbol } => w!(Import, name, format!("{:?}", symbol)),
|
||||
ImportStar { name } => w!(ImportStar, name),
|
||||
LoadName { name } => w!(LoadName, name),
|
||||
StoreName { name } => w!(StoreName, name),
|
||||
DeleteName { name } => w!(DeleteName, name),
|
||||
StoreSubscript => w!(StoreSubscript),
|
||||
DeleteSubscript => w!(DeleteSubscript),
|
||||
StoreAttr { name } => w!(StoreAttr, name),
|
||||
DeleteAttr { name } => w!(DeleteAttr, name),
|
||||
LoadConst { value } => w!(LoadConst, value),
|
||||
UnaryOperation { op } => w!(UnaryOperation, format!("{:?}", op)),
|
||||
BinaryOperation { op, inplace } => w!(BinaryOperation, format!("{:?}", op), inplace),
|
||||
LoadAttr { name } => w!(LoadAttr, name),
|
||||
CompareOperation { op } => w!(CompareOperation, format!("{:?}", op)),
|
||||
Pop => w!(Pop),
|
||||
Rotate { amount } => w!(Rotate, amount),
|
||||
Duplicate => w!(Duplicate),
|
||||
GetIter => w!(GetIter),
|
||||
Pass => w!(Pass),
|
||||
Continue => w!(Continue),
|
||||
Break => w!(Break),
|
||||
Jump { target } => w!(Jump, label_map[target]),
|
||||
JumpIf { target } => w!(JumpIf, label_map[target]),
|
||||
JumpIfFalse { target } => w!(JumpIfFalse, label_map[target]),
|
||||
MakeFunction { flags } => w!(MakeFunction, format!("{:?}", flags)),
|
||||
CallFunction { typ } => w!(CallFunction, format!("{:?}", typ)),
|
||||
ForIter { target } => w!(ForIter, label_map[target]),
|
||||
ReturnValue => w!(ReturnValue),
|
||||
YieldValue => w!(YieldValue),
|
||||
YieldFrom => w!(YieldFrom),
|
||||
SetupLoop { start, end } => w!(SetupLoop, label_map[start], label_map[end]),
|
||||
SetupExcept { handler } => w!(SetupExcept, handler),
|
||||
SetupWith { end } => w!(SetupWith, end),
|
||||
CleanupWith { end } => w!(CleanupWith, end),
|
||||
PopBlock => w!(PopBlock),
|
||||
Raise { argc } => w!(Raise, argc),
|
||||
BuildString { size } => w!(BuildString, size),
|
||||
BuildTuple { size, unpack } => w!(BuildTuple, size, unpack),
|
||||
BuildList { size, unpack } => w!(BuildList, size, unpack),
|
||||
BuildSet { size, unpack } => w!(BuildSet, size, unpack),
|
||||
BuildMap { size, unpack } => w!(BuildMap, size, unpack),
|
||||
BuildSlice { size } => w!(BuildSlice, size),
|
||||
ListAppend { i } => w!(ListAppend, i),
|
||||
SetAdd { i } => w!(SetAdd, i),
|
||||
MapAdd { i } => w!(MapAdd, i),
|
||||
PrintExpr => w!(PrintExpr),
|
||||
LoadBuildClass => w!(LoadBuildClass),
|
||||
StoreLocals => w!(StoreLocals),
|
||||
UnpackSequence { size } => w!(UnpackSequence, size),
|
||||
UnpackEx { before, after } => w!(UnpackEx, before, after),
|
||||
Unpack => w!(Unpack),
|
||||
FormatValue { spec } => w!(FormatValue, spec),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Constant {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self {
|
||||
Constant::Integer { value } => write!(f, "{}", value),
|
||||
Constant::Float { value } => write!(f, "{}", value),
|
||||
Constant::Complex { value } => write!(f, "{}", value),
|
||||
Constant::Boolean { value } => write!(f, "{}", value),
|
||||
Constant::String { value } => write!(f, "{:?}", value),
|
||||
Constant::Bytes { value } => write!(f, "{:?}", value),
|
||||
Constant::Code { code } => write!(f, "{:?}", code),
|
||||
Constant::Tuple { elements } => write!(
|
||||
f,
|
||||
"({})",
|
||||
elements
|
||||
.iter()
|
||||
.map(|e| format!("{}", e))
|
||||
.collect::<Vec<_>>()
|
||||
.join(", ")
|
||||
),
|
||||
Constant::None => write!(f, "None"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for CodeObject {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"<code object {} at ??? file {:?}, line {}>",
|
||||
self.obj_name, self.source_path, self.first_line_number
|
||||
)
|
||||
}
|
||||
}
|
||||
+39
-22
@@ -5,9 +5,9 @@
|
||||
//! https://github.com/python/cpython/blob/master/Python/compile.c
|
||||
//! https://github.com/micropython/micropython/blob/master/py/compile.c
|
||||
|
||||
use super::bytecode::{self, CallType, CodeObject, Instruction};
|
||||
use super::error::CompileError;
|
||||
use super::pyobject::{PyObject, PyObjectPayload, PyObjectRef};
|
||||
use crate::bytecode::{self, CallType, CodeObject, Instruction};
|
||||
use crate::error::CompileError;
|
||||
use crate::pyobject::{PyObject, PyObjectPayload, PyObjectRef};
|
||||
use num_complex::Complex64;
|
||||
use rustpython_parser::{ast, parser};
|
||||
|
||||
@@ -16,6 +16,7 @@ struct Compiler {
|
||||
nxt_label: usize,
|
||||
source_path: Option<String>,
|
||||
current_source_location: ast::Location,
|
||||
in_loop: bool,
|
||||
}
|
||||
|
||||
/// Compile a given sourcecode into a bytecode object.
|
||||
@@ -73,6 +74,7 @@ impl Compiler {
|
||||
nxt_label: 0,
|
||||
source_path: None,
|
||||
current_source_location: ast::Location::default(),
|
||||
in_loop: false,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -229,16 +231,19 @@ impl Compiler {
|
||||
self.set_label(start_label);
|
||||
|
||||
self.compile_test(test, None, Some(else_label), EvalContext::Statement)?;
|
||||
|
||||
self.in_loop = true;
|
||||
self.compile_statements(body)?;
|
||||
self.in_loop = false;
|
||||
self.emit(Instruction::Jump {
|
||||
target: start_label,
|
||||
});
|
||||
self.set_label(else_label);
|
||||
self.emit(Instruction::PopBlock);
|
||||
if let Some(orelse) = orelse {
|
||||
self.compile_statements(orelse)?;
|
||||
}
|
||||
self.set_label(end_label);
|
||||
self.emit(Instruction::PopBlock);
|
||||
}
|
||||
ast::Statement::With { items, body } => {
|
||||
let end_label = self.new_label();
|
||||
@@ -267,14 +272,6 @@ impl Compiler {
|
||||
body,
|
||||
orelse,
|
||||
} => {
|
||||
// The thing iterated:
|
||||
for i in iter {
|
||||
self.compile_expression(i)?;
|
||||
}
|
||||
|
||||
// Retrieve iterator
|
||||
self.emit(Instruction::GetIter);
|
||||
|
||||
// Start loop
|
||||
let start_label = self.new_label();
|
||||
let else_label = self.new_label();
|
||||
@@ -283,6 +280,15 @@ impl Compiler {
|
||||
start: start_label,
|
||||
end: end_label,
|
||||
});
|
||||
|
||||
// The thing iterated:
|
||||
for i in iter {
|
||||
self.compile_expression(i)?;
|
||||
}
|
||||
|
||||
// Retrieve Iterator
|
||||
self.emit(Instruction::GetIter);
|
||||
|
||||
self.set_label(start_label);
|
||||
self.emit(Instruction::ForIter { target: else_label });
|
||||
|
||||
@@ -290,16 +296,19 @@ impl Compiler {
|
||||
self.compile_store(target)?;
|
||||
|
||||
// Body of loop:
|
||||
self.in_loop = true;
|
||||
self.compile_statements(body)?;
|
||||
self.in_loop = false;
|
||||
|
||||
self.emit(Instruction::Jump {
|
||||
target: start_label,
|
||||
});
|
||||
self.set_label(else_label);
|
||||
self.emit(Instruction::PopBlock);
|
||||
if let Some(orelse) = orelse {
|
||||
self.compile_statements(orelse)?;
|
||||
}
|
||||
self.set_label(end_label);
|
||||
self.emit(Instruction::PopBlock);
|
||||
}
|
||||
ast::Statement::Raise { exception, cause } => match exception {
|
||||
Some(value) => {
|
||||
@@ -563,9 +572,15 @@ impl Compiler {
|
||||
self.set_label(end_label);
|
||||
}
|
||||
ast::Statement::Break => {
|
||||
if !self.in_loop {
|
||||
return Err(CompileError::InvalidBreak);
|
||||
}
|
||||
self.emit(Instruction::Break);
|
||||
}
|
||||
ast::Statement::Continue => {
|
||||
if !self.in_loop {
|
||||
return Err(CompileError::InvalidContinue);
|
||||
}
|
||||
self.emit(Instruction::Continue);
|
||||
}
|
||||
ast::Statement::Return { value } => {
|
||||
@@ -608,7 +623,7 @@ impl Compiler {
|
||||
self.compile_expression(value)?;
|
||||
|
||||
// Perform operation:
|
||||
self.compile_op(op);
|
||||
self.compile_op(op, true);
|
||||
self.compile_store(target)?;
|
||||
}
|
||||
ast::Statement::Delete { targets } => {
|
||||
@@ -631,7 +646,7 @@ impl Compiler {
|
||||
self.emit(Instruction::DeleteSubscript);
|
||||
}
|
||||
_ => {
|
||||
return Err(CompileError::Delete);
|
||||
return Err(CompileError::Delete(target.name()));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -648,6 +663,7 @@ 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:
|
||||
@@ -750,14 +766,14 @@ impl Compiler {
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
return Err(CompileError::Assign(format!("{:?}", target)));
|
||||
return Err(CompileError::Assign(target.name()));
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn compile_op(&mut self, op: &ast::Operator) {
|
||||
fn compile_op(&mut self, op: &ast::Operator, inplace: bool) {
|
||||
let i = match op {
|
||||
ast::Operator::Add => bytecode::BinaryOperator::Add,
|
||||
ast::Operator::Sub => bytecode::BinaryOperator::Subtract,
|
||||
@@ -773,7 +789,7 @@ impl Compiler {
|
||||
ast::Operator::BitXor => bytecode::BinaryOperator::Xor,
|
||||
ast::Operator::BitAnd => bytecode::BinaryOperator::And,
|
||||
};
|
||||
self.emit(Instruction::BinaryOperation { op: i });
|
||||
self.emit(Instruction::BinaryOperation { op: i, inplace });
|
||||
}
|
||||
|
||||
fn compile_test(
|
||||
@@ -852,13 +868,14 @@ impl Compiler {
|
||||
self.compile_expression(b)?;
|
||||
|
||||
// Perform operation:
|
||||
self.compile_op(op);
|
||||
self.compile_op(op, false);
|
||||
}
|
||||
ast::Expression::Subscript { a, b } => {
|
||||
self.compile_expression(a)?;
|
||||
self.compile_expression(b)?;
|
||||
self.emit(Instruction::BinaryOperation {
|
||||
op: bytecode::BinaryOperator::Subscript,
|
||||
inplace: false,
|
||||
});
|
||||
}
|
||||
ast::Expression::Unop { op, a } => {
|
||||
@@ -1384,10 +1401,10 @@ impl Compiler {
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::bytecode::CodeObject;
|
||||
use super::bytecode::Constant::*;
|
||||
use super::bytecode::Instruction::*;
|
||||
use super::Compiler;
|
||||
use crate::bytecode::CodeObject;
|
||||
use crate::bytecode::Constant::*;
|
||||
use crate::bytecode::Instruction::*;
|
||||
use rustpython_parser::parser;
|
||||
fn compile_exec(source: &str) -> CodeObject {
|
||||
let mut compiler = Compiler::new();
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use super::obj::objbool;
|
||||
use super::obj::objint;
|
||||
use super::pyobject::{IdProtocol, PyObjectRef, PyResult};
|
||||
use super::vm::VirtualMachine;
|
||||
use crate::obj::objbool;
|
||||
use crate::obj::objint;
|
||||
use crate::pyobject::{IdProtocol, PyObjectRef, PyResult};
|
||||
use crate::vm::VirtualMachine;
|
||||
use num_traits::ToPrimitive;
|
||||
/// Ordered dictionary implementation.
|
||||
/// Inspired by: https://morepypy.blogspot.com/2015/01/faster-more-memory-efficient-and-more.html
|
||||
|
||||
+16
-10
@@ -5,26 +5,32 @@ use std::fmt;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum CompileError {
|
||||
// Invalid assignment, cannot store value in target.
|
||||
Assign(String),
|
||||
// Invalid delete
|
||||
Delete,
|
||||
// Expected an expression got a statement
|
||||
/// Invalid assignment, cannot store value in target.
|
||||
Assign(&'static str),
|
||||
/// Invalid delete
|
||||
Delete(&'static str),
|
||||
/// Expected an expression got a statement
|
||||
ExpectExpr,
|
||||
// Parser error
|
||||
/// Parser error
|
||||
Parse(ParseError),
|
||||
// Multiple `*` detected
|
||||
/// Multiple `*` detected
|
||||
StarArgs,
|
||||
/// Break statement outside of loop.
|
||||
InvalidBreak,
|
||||
/// Continue statement outside of loop.
|
||||
InvalidContinue,
|
||||
}
|
||||
|
||||
impl fmt::Display for CompileError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self {
|
||||
CompileError::Assign(expr) => write!(f, "Invalid assignment: {}", expr),
|
||||
CompileError::Delete => write!(f, "Invalid delete statement"),
|
||||
CompileError::Assign(target) => write!(f, "can't assign to {}", target),
|
||||
CompileError::Delete(target) => write!(f, "can't delete {}", target),
|
||||
CompileError::ExpectExpr => write!(f, "Expecting expression, got statement"),
|
||||
CompileError::Parse(err) => err.fmt(f),
|
||||
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"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+3
-3
@@ -2,9 +2,9 @@ extern crate rustpython_parser;
|
||||
|
||||
use std::error::Error;
|
||||
|
||||
use super::compile;
|
||||
use super::pyobject::{PyObjectRef, PyResult};
|
||||
use super::vm::VirtualMachine;
|
||||
use crate::compile;
|
||||
use crate::pyobject::{PyObjectRef, PyResult};
|
||||
use crate::vm::VirtualMachine;
|
||||
|
||||
pub fn eval(
|
||||
vm: &mut VirtualMachine,
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
use super::obj::objsequence;
|
||||
use super::obj::objstr;
|
||||
use super::obj::objtype;
|
||||
use super::pyobject::{
|
||||
use crate::obj::objsequence;
|
||||
use crate::obj::objstr;
|
||||
use crate::obj::objtype;
|
||||
use crate::pyobject::{
|
||||
create_type, AttributeProtocol, PyContext, PyFuncArgs, PyObjectRef, PyResult, TypeProtocol,
|
||||
};
|
||||
use super::vm::VirtualMachine;
|
||||
use crate::vm::VirtualMachine;
|
||||
|
||||
fn exception_init(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
let zelf = args.args[0].clone();
|
||||
|
||||
+98
-64
@@ -5,25 +5,33 @@ use std::fmt;
|
||||
use std::mem;
|
||||
use std::path::PathBuf;
|
||||
|
||||
use super::builtins;
|
||||
use super::bytecode;
|
||||
use super::import::{import, import_module};
|
||||
use super::obj::objbool;
|
||||
use super::obj::objcode;
|
||||
use super::obj::objdict;
|
||||
use super::obj::objiter;
|
||||
use super::obj::objlist;
|
||||
use super::obj::objstr;
|
||||
use super::obj::objtype;
|
||||
use super::pyobject::{
|
||||
use crate::builtins;
|
||||
use crate::bytecode;
|
||||
use crate::import::{import, import_module};
|
||||
use crate::obj::objbool;
|
||||
use crate::obj::objcode;
|
||||
use crate::obj::objdict;
|
||||
use crate::obj::objiter;
|
||||
use crate::obj::objlist;
|
||||
use crate::obj::objstr;
|
||||
use crate::obj::objtype;
|
||||
use crate::pyobject::{
|
||||
DictProtocol, IdProtocol, ParentProtocol, PyFuncArgs, PyObject, PyObjectPayload, PyObjectRef,
|
||||
PyResult, TypeProtocol,
|
||||
};
|
||||
use super::vm::VirtualMachine;
|
||||
use crate::vm::VirtualMachine;
|
||||
use num_bigint::BigInt;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
enum Block {
|
||||
struct Block {
|
||||
/// The type of block.
|
||||
typ: BlockType,
|
||||
/// The level of the value stack when the block was entered.
|
||||
level: usize,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
enum BlockType {
|
||||
Loop {
|
||||
start: bytecode::Label,
|
||||
end: bytecode::Label,
|
||||
@@ -316,7 +324,9 @@ impl Frame {
|
||||
vm.call_method(&dict_obj, "__setitem__", vec![key, value])?;
|
||||
Ok(None)
|
||||
}
|
||||
bytecode::Instruction::BinaryOperation { ref op } => self.execute_binop(vm, op),
|
||||
bytecode::Instruction::BinaryOperation { ref op, inplace } => {
|
||||
self.execute_binop(vm, op, *inplace)
|
||||
}
|
||||
bytecode::Instruction::LoadAttr { ref name } => self.load_attr(vm, name),
|
||||
bytecode::Instruction::StoreAttr { ref name } => self.store_attr(vm, name),
|
||||
bytecode::Instruction::DeleteAttr { ref name } => self.delete_attr(vm, name),
|
||||
@@ -355,21 +365,21 @@ impl Frame {
|
||||
}
|
||||
}
|
||||
bytecode::Instruction::SetupLoop { start, end } => {
|
||||
self.push_block(Block::Loop {
|
||||
self.push_block(BlockType::Loop {
|
||||
start: *start,
|
||||
end: *end,
|
||||
});
|
||||
Ok(None)
|
||||
}
|
||||
bytecode::Instruction::SetupExcept { handler } => {
|
||||
self.push_block(Block::TryExcept { handler: *handler });
|
||||
self.push_block(BlockType::TryExcept { handler: *handler });
|
||||
Ok(None)
|
||||
}
|
||||
bytecode::Instruction::SetupWith { end } => {
|
||||
let context_manager = self.pop_value();
|
||||
// Call enter:
|
||||
let obj = vm.call_method(&context_manager, "__enter__", vec![])?;
|
||||
self.push_block(Block::With {
|
||||
self.push_block(BlockType::With {
|
||||
end: *end,
|
||||
context_manager: context_manager.clone(),
|
||||
});
|
||||
@@ -378,22 +388,23 @@ impl Frame {
|
||||
}
|
||||
bytecode::Instruction::CleanupWith { end: end1 } => {
|
||||
let block = self.pop_block().unwrap();
|
||||
if let Block::With {
|
||||
if let BlockType::With {
|
||||
end: end2,
|
||||
context_manager,
|
||||
} = &block
|
||||
} = &block.typ
|
||||
{
|
||||
assert!(end1 == end2);
|
||||
debug_assert!(end1 == end2);
|
||||
|
||||
// call exit now with no exception:
|
||||
self.with_exit(vm, context_manager, None)?;
|
||||
Ok(None)
|
||||
self.with_exit(vm, &context_manager, None)?;
|
||||
} else {
|
||||
panic!("Block stack is incorrect, expected a with block");
|
||||
unreachable!("Block stack is incorrect, expected a with block");
|
||||
}
|
||||
|
||||
Ok(None)
|
||||
}
|
||||
bytecode::Instruction::PopBlock => {
|
||||
self.pop_block();
|
||||
self.pop_block().expect("no pop to block");
|
||||
Ok(None)
|
||||
}
|
||||
bytecode::Instruction::GetIter => {
|
||||
@@ -530,8 +541,11 @@ impl Frame {
|
||||
|
||||
bytecode::Instruction::Break => {
|
||||
let block = self.unwind_loop(vm);
|
||||
if let Block::Loop { end, .. } = block {
|
||||
if let BlockType::Loop { end, .. } = block.typ {
|
||||
self.pop_block();
|
||||
self.jump(end);
|
||||
} else {
|
||||
unreachable!()
|
||||
}
|
||||
Ok(None)
|
||||
}
|
||||
@@ -541,10 +555,10 @@ impl Frame {
|
||||
}
|
||||
bytecode::Instruction::Continue => {
|
||||
let block = self.unwind_loop(vm);
|
||||
if let Block::Loop { start, .. } = block {
|
||||
if let BlockType::Loop { start, .. } = block.typ {
|
||||
self.jump(start);
|
||||
} else {
|
||||
assert!(false);
|
||||
unreachable!();
|
||||
}
|
||||
Ok(None)
|
||||
}
|
||||
@@ -709,16 +723,15 @@ impl Frame {
|
||||
|
||||
// Unwind all blocks:
|
||||
fn unwind_blocks(&mut self, vm: &mut VirtualMachine) -> Option<PyObjectRef> {
|
||||
loop {
|
||||
let block = self.pop_block();
|
||||
match block {
|
||||
Some(Block::Loop { .. }) => {}
|
||||
Some(Block::TryExcept { .. }) => {
|
||||
while let Some(block) = self.pop_block() {
|
||||
match block.typ {
|
||||
BlockType::Loop { .. } => {}
|
||||
BlockType::TryExcept { .. } => {
|
||||
// TODO: execute finally handler
|
||||
}
|
||||
Some(Block::With {
|
||||
BlockType::With {
|
||||
context_manager, ..
|
||||
}) => {
|
||||
} => {
|
||||
match self.with_exit(vm, &context_manager, None) {
|
||||
Ok(..) => {}
|
||||
Err(exc) => {
|
||||
@@ -727,29 +740,31 @@ impl Frame {
|
||||
}
|
||||
}
|
||||
}
|
||||
None => break None,
|
||||
}
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
fn unwind_loop(&mut self, vm: &mut VirtualMachine) -> Block {
|
||||
loop {
|
||||
let block = self.pop_block();
|
||||
match block {
|
||||
Some(Block::Loop { .. }) => break block.unwrap(),
|
||||
Some(Block::TryExcept { .. }) => {
|
||||
let block = self.current_block().cloned().expect("not in a loop");
|
||||
match block.typ {
|
||||
BlockType::Loop { .. } => break block,
|
||||
BlockType::TryExcept { .. } => {
|
||||
// TODO: execute finally handler
|
||||
}
|
||||
Some(Block::With {
|
||||
BlockType::With {
|
||||
context_manager, ..
|
||||
}) => match self.with_exit(vm, &context_manager, None) {
|
||||
} => match self.with_exit(vm, &context_manager, None) {
|
||||
Ok(..) => {}
|
||||
Err(exc) => {
|
||||
panic!("Exception in with __exit__ {:?}", exc);
|
||||
}
|
||||
},
|
||||
None => panic!("No block to break / continue"),
|
||||
}
|
||||
|
||||
self.pop_block();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -759,18 +774,17 @@ impl Frame {
|
||||
exc: PyObjectRef,
|
||||
) -> Option<PyObjectRef> {
|
||||
// unwind block stack on exception and find any handlers:
|
||||
loop {
|
||||
let block = self.pop_block();
|
||||
match block {
|
||||
Some(Block::TryExcept { handler }) => {
|
||||
while let Some(block) = self.pop_block() {
|
||||
match block.typ {
|
||||
BlockType::TryExcept { handler } => {
|
||||
self.push_value(exc);
|
||||
self.jump(handler);
|
||||
return None;
|
||||
}
|
||||
Some(Block::With {
|
||||
BlockType::With {
|
||||
end,
|
||||
context_manager,
|
||||
}) => {
|
||||
} => {
|
||||
match self.with_exit(vm, &context_manager, Some(exc.clone())) {
|
||||
Ok(exit_action) => {
|
||||
match objbool::boolval(vm, exit_action) {
|
||||
@@ -795,15 +809,14 @@ impl Frame {
|
||||
}
|
||||
}
|
||||
}
|
||||
Some(Block::Loop { .. }) => {}
|
||||
None => break,
|
||||
BlockType::Loop { .. } => {}
|
||||
}
|
||||
}
|
||||
Some(exc)
|
||||
}
|
||||
|
||||
fn with_exit(
|
||||
&mut self,
|
||||
&self,
|
||||
vm: &mut VirtualMachine,
|
||||
context_manager: &PyObjectRef,
|
||||
exc: Option<PyObjectRef>,
|
||||
@@ -893,27 +906,39 @@ impl Frame {
|
||||
&mut self,
|
||||
vm: &mut VirtualMachine,
|
||||
op: &bytecode::BinaryOperator,
|
||||
inplace: bool,
|
||||
) -> FrameResult {
|
||||
let b_ref = self.pop_value();
|
||||
let a_ref = self.pop_value();
|
||||
let value = match *op {
|
||||
bytecode::BinaryOperator::Subtract if inplace => vm._isub(a_ref, b_ref),
|
||||
bytecode::BinaryOperator::Subtract => vm._sub(a_ref, b_ref),
|
||||
bytecode::BinaryOperator::Add if inplace => vm._iadd(a_ref, b_ref),
|
||||
bytecode::BinaryOperator::Add => vm._add(a_ref, b_ref),
|
||||
bytecode::BinaryOperator::Multiply if inplace => vm._imul(a_ref, b_ref),
|
||||
bytecode::BinaryOperator::Multiply => vm._mul(a_ref, b_ref),
|
||||
bytecode::BinaryOperator::MatrixMultiply => {
|
||||
vm.call_method(&a_ref, "__matmul__", vec![b_ref])
|
||||
}
|
||||
bytecode::BinaryOperator::MatrixMultiply if inplace => vm._imatmul(a_ref, b_ref),
|
||||
bytecode::BinaryOperator::MatrixMultiply => vm._matmul(a_ref, b_ref),
|
||||
bytecode::BinaryOperator::Power if inplace => vm._ipow(a_ref, b_ref),
|
||||
bytecode::BinaryOperator::Power => vm._pow(a_ref, b_ref),
|
||||
bytecode::BinaryOperator::Divide => vm._div(a_ref, b_ref),
|
||||
bytecode::BinaryOperator::FloorDivide => {
|
||||
vm.call_method(&a_ref, "__floordiv__", vec![b_ref])
|
||||
}
|
||||
bytecode::BinaryOperator::Divide if inplace => vm._itruediv(a_ref, b_ref),
|
||||
bytecode::BinaryOperator::Divide => vm._truediv(a_ref, b_ref),
|
||||
bytecode::BinaryOperator::FloorDivide if inplace => vm._ifloordiv(a_ref, b_ref),
|
||||
bytecode::BinaryOperator::FloorDivide => vm._floordiv(a_ref, b_ref),
|
||||
// TODO: Subscript should probably have its own op
|
||||
bytecode::BinaryOperator::Subscript if inplace => unreachable!(),
|
||||
bytecode::BinaryOperator::Subscript => self.subscript(vm, a_ref, b_ref),
|
||||
bytecode::BinaryOperator::Modulo => vm._modulo(a_ref, b_ref),
|
||||
bytecode::BinaryOperator::Lshift => vm.call_method(&a_ref, "__lshift__", vec![b_ref]),
|
||||
bytecode::BinaryOperator::Rshift => vm.call_method(&a_ref, "__rshift__", vec![b_ref]),
|
||||
bytecode::BinaryOperator::Modulo if inplace => vm._imod(a_ref, b_ref),
|
||||
bytecode::BinaryOperator::Modulo => vm._mod(a_ref, b_ref),
|
||||
bytecode::BinaryOperator::Lshift if inplace => vm._ilshift(a_ref, b_ref),
|
||||
bytecode::BinaryOperator::Lshift => vm._lshift(a_ref, b_ref),
|
||||
bytecode::BinaryOperator::Rshift if inplace => vm._irshift(a_ref, b_ref),
|
||||
bytecode::BinaryOperator::Rshift => vm._rshift(a_ref, b_ref),
|
||||
bytecode::BinaryOperator::Xor if inplace => vm._ixor(a_ref, b_ref),
|
||||
bytecode::BinaryOperator::Xor => vm._xor(a_ref, b_ref),
|
||||
bytecode::BinaryOperator::Or if inplace => vm._ior(a_ref, b_ref),
|
||||
bytecode::BinaryOperator::Or => vm._or(a_ref, b_ref),
|
||||
bytecode::BinaryOperator::And if inplace => vm._iand(a_ref, b_ref),
|
||||
bytecode::BinaryOperator::And => vm._and(a_ref, b_ref),
|
||||
}?;
|
||||
|
||||
@@ -1047,12 +1072,21 @@ impl Frame {
|
||||
self.code.locations[self.lasti].clone()
|
||||
}
|
||||
|
||||
fn push_block(&mut self, block: Block) {
|
||||
self.blocks.push(block);
|
||||
fn push_block(&mut self, typ: BlockType) {
|
||||
self.blocks.push(Block {
|
||||
typ,
|
||||
level: self.stack.len(),
|
||||
});
|
||||
}
|
||||
|
||||
fn pop_block(&mut self) -> Option<Block> {
|
||||
self.blocks.pop()
|
||||
let block = self.blocks.pop()?;
|
||||
self.stack.truncate(block.level);
|
||||
Some(block)
|
||||
}
|
||||
|
||||
fn current_block(&self) -> Option<&Block> {
|
||||
self.blocks.last()
|
||||
}
|
||||
|
||||
pub fn push_value(&mut self, obj: PyObjectRef) {
|
||||
|
||||
+5
-5
@@ -5,11 +5,11 @@
|
||||
use std::error::Error;
|
||||
use std::path::PathBuf;
|
||||
|
||||
use super::compile;
|
||||
use super::pyobject::{AttributeProtocol, DictProtocol, PyResult};
|
||||
use super::util;
|
||||
use super::vm::VirtualMachine;
|
||||
use obj::{objsequence, objstr};
|
||||
use crate::compile;
|
||||
use crate::obj::{objsequence, objstr};
|
||||
use crate::pyobject::{AttributeProtocol, DictProtocol, PyResult};
|
||||
use crate::util;
|
||||
use crate::vm::VirtualMachine;
|
||||
|
||||
fn import_uncached_module(
|
||||
vm: &mut VirtualMachine,
|
||||
|
||||
+22
-1
@@ -1,3 +1,4 @@
|
||||
// count number of tokens given as arguments.
|
||||
// see: https://danielkeep.github.io/tlborm/book/blk-counting.html
|
||||
#[macro_export]
|
||||
macro_rules! replace_expr {
|
||||
@@ -17,7 +18,7 @@ macro_rules! type_check {
|
||||
// None indicates that we have no type requirement (i.e. we accept any type)
|
||||
if let Some(expected_type) = $arg_type {
|
||||
let arg = &$args.args[$arg_count];
|
||||
if !objtype::isinstance(arg, &expected_type) {
|
||||
if !$crate::obj::objtype::isinstance(arg, &expected_type) {
|
||||
let arg_typ = arg.typ();
|
||||
let expected_type_name = $vm.to_pystr(&expected_type)?;
|
||||
let actual_type = $vm.to_pystr(&arg_typ)?;
|
||||
@@ -48,9 +49,11 @@ macro_rules! arg_check {
|
||||
( $vm: ident, $args:ident, required=[$( ($arg_name:ident, $arg_type:expr) ),*], optional=[$( ($optional_arg_name:ident, $optional_arg_type:expr) ),*] ) => {
|
||||
let mut arg_count = 0;
|
||||
|
||||
// use macro magic to compile-time count number of required and optional arguments
|
||||
let minimum_arg_count = count_tts!($($arg_name)*);
|
||||
let maximum_arg_count = minimum_arg_count + count_tts!($($optional_arg_name)*);
|
||||
|
||||
// verify that the number of given arguments is right
|
||||
if $args.args.len() < minimum_arg_count || $args.args.len() > maximum_arg_count {
|
||||
let expected_str = if minimum_arg_count == maximum_arg_count {
|
||||
format!("{}", minimum_arg_count)
|
||||
@@ -64,6 +67,9 @@ macro_rules! arg_check {
|
||||
)));
|
||||
};
|
||||
|
||||
// for each required parameter:
|
||||
// check if the type matches. If not, return with error
|
||||
// assign the arg to a variable
|
||||
$(
|
||||
type_check!($vm, $args, arg_count, $arg_name, $arg_type);
|
||||
let $arg_name = &$args.args[arg_count];
|
||||
@@ -73,6 +79,9 @@ macro_rules! arg_check {
|
||||
}
|
||||
)*
|
||||
|
||||
// for each optional parameter, if there are enough positional arguments:
|
||||
// check if the type matches. If not, return with error
|
||||
// assign the arg to a variable
|
||||
$(
|
||||
let $optional_arg_name = if arg_count < $args.args.len() {
|
||||
type_check!($vm, $args, arg_count, $optional_arg_name, $optional_arg_type);
|
||||
@@ -101,3 +110,15 @@ macro_rules! no_kwargs {
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! py_module {
|
||||
( $ctx:expr, $module_name:expr, { $($name:expr => $value:expr),* $(,)* }) => {
|
||||
{
|
||||
let py_mod = $ctx.new_module($module_name, $ctx.new_scope(None));
|
||||
$(
|
||||
$ctx.set_attr(&py_mod, $name, $value);
|
||||
)*
|
||||
py_mod
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,8 @@
|
||||
use super::super::pyobject::{
|
||||
use super::objtype;
|
||||
use crate::pyobject::{
|
||||
PyContext, PyFuncArgs, PyObjectPayload, PyObjectRef, PyResult, TypeProtocol,
|
||||
};
|
||||
use super::super::vm::VirtualMachine;
|
||||
use super::objtype;
|
||||
use crate::vm::VirtualMachine;
|
||||
use num_traits::Zero;
|
||||
|
||||
pub fn boolval(vm: &mut VirtualMachine, obj: PyObjectRef) -> Result<bool, PyObjectRef> {
|
||||
|
||||
@@ -1,14 +1,13 @@
|
||||
//! Implementation of the python bytearray object.
|
||||
|
||||
use super::super::pyobject::{
|
||||
PyContext, PyFuncArgs, PyObject, PyObjectPayload, PyResult, TypeProtocol,
|
||||
};
|
||||
use crate::pyobject::{PyContext, PyFuncArgs, PyObject, PyObjectPayload, PyResult, TypeProtocol};
|
||||
|
||||
use super::objint;
|
||||
|
||||
use super::super::vm::VirtualMachine;
|
||||
use super::objbytes::get_mut_value;
|
||||
use super::objbytes::get_value;
|
||||
use super::objtype;
|
||||
use crate::vm::VirtualMachine;
|
||||
use num_traits::ToPrimitive;
|
||||
|
||||
// Binary data support
|
||||
@@ -95,6 +94,22 @@ pub fn init(context: &PyContext) {
|
||||
"istitle",
|
||||
context.new_rustfunc(bytearray_istitle),
|
||||
);
|
||||
context.set_attr(
|
||||
&bytearray_type,
|
||||
"clear",
|
||||
context.new_rustfunc(bytearray_clear),
|
||||
);
|
||||
context.set_attr(&bytearray_type, "pop", context.new_rustfunc(bytearray_pop));
|
||||
context.set_attr(
|
||||
&bytearray_type,
|
||||
"lower",
|
||||
context.new_rustfunc(bytearray_lower),
|
||||
);
|
||||
context.set_attr(
|
||||
&bytearray_type,
|
||||
"upper",
|
||||
context.new_rustfunc(bytearray_upper),
|
||||
);
|
||||
}
|
||||
|
||||
fn bytearray_new(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
@@ -114,7 +129,11 @@ fn bytearray_new(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
let mut data_bytes = vec![];
|
||||
for elem in elements.iter() {
|
||||
let v = objint::to_int(vm, elem, 10)?;
|
||||
data_bytes.push(v.to_u8().unwrap());
|
||||
if let Some(i) = v.to_u8() {
|
||||
data_bytes.push(i);
|
||||
} else {
|
||||
return Err(vm.new_value_error("byte must be in range(0, 256)".to_string()));
|
||||
}
|
||||
}
|
||||
data_bytes
|
||||
// return Err(vm.new_type_error("Cannot construct bytes".to_string()));
|
||||
@@ -177,7 +196,7 @@ fn bytearray_islower(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
!bytes.is_empty()
|
||||
&& bytes
|
||||
.iter()
|
||||
.filter(|x| char::from(**x).is_whitespace())
|
||||
.filter(|x| !char::from(**x).is_whitespace())
|
||||
.all(|x| char::from(*x).is_lowercase()),
|
||||
))
|
||||
}
|
||||
@@ -261,3 +280,44 @@ fn bytearray_repr(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
let data = String::from_utf8(value.to_vec()).unwrap();
|
||||
Ok(vm.new_str(format!("bytearray(b'{}')", data)))
|
||||
}
|
||||
|
||||
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();
|
||||
Ok(vm.get_none())
|
||||
}
|
||||
_ => panic!("Bytearray has incorrect payload."),
|
||||
}
|
||||
}
|
||||
|
||||
fn bytearray_pop(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
arg_check!(vm, args, required = [(obj, Some(vm.ctx.bytearray_type()))]);
|
||||
let mut value = get_mut_value(obj);
|
||||
|
||||
if let Some(i) = value.pop() {
|
||||
Ok(vm.ctx.new_int(i))
|
||||
} else {
|
||||
Err(vm.new_index_error("pop from empty bytearray".to_string()))
|
||||
}
|
||||
}
|
||||
|
||||
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(),
|
||||
))
|
||||
}
|
||||
|
||||
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(),
|
||||
))
|
||||
}
|
||||
+17
-5
@@ -1,13 +1,15 @@
|
||||
use super::super::pyobject::{
|
||||
PyContext, PyFuncArgs, PyObject, PyObjectPayload, PyObjectRef, PyResult, TypeProtocol,
|
||||
};
|
||||
use super::super::vm::VirtualMachine;
|
||||
use super::objint;
|
||||
use super::objtype;
|
||||
use crate::pyobject::{
|
||||
PyContext, PyFuncArgs, PyObject, PyObjectPayload, PyObjectRef, PyResult, TypeProtocol,
|
||||
};
|
||||
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
|
||||
|
||||
@@ -183,7 +185,17 @@ pub fn get_value<'a>(obj: &'a PyObjectRef) -> impl Deref<Target = Vec<u8>> + 'a
|
||||
if let PyObjectPayload::Bytes { ref value } = py_obj.payload {
|
||||
value
|
||||
} else {
|
||||
panic!("Inner error getting int {:?}", obj);
|
||||
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);
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -2,12 +2,11 @@
|
||||
|
||||
*/
|
||||
|
||||
use super::super::bytecode;
|
||||
use super::super::pyobject::{
|
||||
use crate::bytecode;
|
||||
use crate::pyobject::{
|
||||
IdProtocol, PyContext, PyFuncArgs, PyObjectPayload, PyObjectRef, PyResult, TypeProtocol,
|
||||
};
|
||||
use super::super::vm::VirtualMachine;
|
||||
use super::objtype;
|
||||
use crate::vm::VirtualMachine;
|
||||
|
||||
pub fn init(context: &PyContext) {
|
||||
let code_type = &context.code_type;
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
use super::super::pyobject::{
|
||||
PyContext, PyFuncArgs, PyObject, PyObjectPayload, PyObjectRef, PyResult, TypeProtocol,
|
||||
};
|
||||
use super::super::vm::VirtualMachine;
|
||||
use super::objfloat;
|
||||
use super::objint;
|
||||
use super::objtype;
|
||||
use crate::pyobject::{
|
||||
PyContext, PyFuncArgs, PyObject, PyObjectPayload, PyObjectRef, PyResult, TypeProtocol,
|
||||
};
|
||||
use crate::vm::VirtualMachine;
|
||||
use num_complex::Complex64;
|
||||
use num_traits::ToPrimitive;
|
||||
|
||||
@@ -17,6 +17,11 @@ pub fn init(context: &PyContext) {
|
||||
|
||||
context.set_attr(&complex_type, "__abs__", context.new_rustfunc(complex_abs));
|
||||
context.set_attr(&complex_type, "__add__", context.new_rustfunc(complex_add));
|
||||
context.set_attr(
|
||||
&complex_type,
|
||||
"__radd__",
|
||||
context.new_rustfunc(complex_radd),
|
||||
);
|
||||
context.set_attr(&complex_type, "__eq__", context.new_rustfunc(complex_eq));
|
||||
context.set_attr(&complex_type, "__neg__", context.new_rustfunc(complex_neg));
|
||||
context.set_attr(&complex_type, "__new__", context.new_rustfunc(complex_new));
|
||||
@@ -106,6 +111,30 @@ fn complex_add(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
let v1 = get_value(i);
|
||||
if objtype::isinstance(i2, &vm.ctx.complex_type()) {
|
||||
Ok(vm.ctx.new_complex(v1 + get_value(i2)))
|
||||
} else if objtype::isinstance(i2, &vm.ctx.int_type()) {
|
||||
Ok(vm.ctx.new_complex(Complex64::new(
|
||||
v1.re + objint::get_value(i2).to_f64().unwrap(),
|
||||
v1.im,
|
||||
)))
|
||||
} else {
|
||||
Err(vm.new_type_error(format!("Cannot add {} and {}", i.borrow(), i2.borrow())))
|
||||
}
|
||||
}
|
||||
|
||||
fn complex_radd(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
arg_check!(
|
||||
vm,
|
||||
args,
|
||||
required = [(i, Some(vm.ctx.complex_type())), (i2, None)]
|
||||
);
|
||||
|
||||
let v1 = get_value(i);
|
||||
|
||||
if objtype::isinstance(i2, &vm.ctx.int_type()) {
|
||||
Ok(vm.ctx.new_complex(Complex64::new(
|
||||
v1.re + objint::get_value(i2).to_f64().unwrap(),
|
||||
v1.im,
|
||||
)))
|
||||
} else {
|
||||
Err(vm.new_type_error(format!("Cannot add {} and {}", i.borrow(), i2.borrow())))
|
||||
}
|
||||
|
||||
+12
-5
@@ -1,11 +1,11 @@
|
||||
use super::super::pyobject::{
|
||||
PyAttributes, PyContext, PyFuncArgs, PyObject, PyObjectPayload, PyObjectRef, PyResult,
|
||||
TypeProtocol,
|
||||
};
|
||||
use super::super::vm::{ReprGuard, VirtualMachine};
|
||||
use super::objiter;
|
||||
use super::objstr;
|
||||
use super::objtype;
|
||||
use crate::pyobject::{
|
||||
PyAttributes, PyContext, PyFuncArgs, PyObject, PyObjectPayload, PyObjectRef, PyResult,
|
||||
TypeProtocol,
|
||||
};
|
||||
use crate::vm::{ReprGuard, VirtualMachine};
|
||||
use std::cell::{Ref, RefCell, RefMut};
|
||||
use std::collections::HashMap;
|
||||
use std::ops::{Deref, DerefMut};
|
||||
@@ -244,6 +244,12 @@ fn dict_delitem(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
}
|
||||
}
|
||||
|
||||
fn dict_clear(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
arg_check!(vm, args, required = [(dict, Some(vm.ctx.dict_type()))]);
|
||||
get_mut_elements(dict).clear();
|
||||
Ok(vm.get_none())
|
||||
}
|
||||
|
||||
/// When iterating over a dictionary, we iterate over the keys of it.
|
||||
fn dict_iter(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
arg_check!(vm, args, required = [(dict, Some(vm.ctx.dict_type()))]);
|
||||
@@ -337,4 +343,5 @@ pub fn init(context: &PyContext) {
|
||||
"__setitem__",
|
||||
context.new_rustfunc(dict_setitem),
|
||||
);
|
||||
context.set_attr(&dict_type, "clear", context.new_rustfunc(dict_clear));
|
||||
}
|
||||
@@ -1,10 +1,7 @@
|
||||
use super::super::pyobject::{
|
||||
PyContext, PyFuncArgs, PyObject, PyObjectPayload, PyResult, TypeProtocol,
|
||||
};
|
||||
use super::super::vm::VirtualMachine;
|
||||
use super::objint;
|
||||
use super::objiter;
|
||||
use super::objtype; // Required for arg_check! to use isinstance
|
||||
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;
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
use super::super::pyobject::{
|
||||
IdProtocol, PyContext, PyFuncArgs, PyObject, PyObjectPayload, PyResult, TypeProtocol,
|
||||
};
|
||||
use super::super::vm::VirtualMachine;
|
||||
use super::objbool;
|
||||
use super::objiter;
|
||||
use super::objtype; // Required for arg_check! to use isinstance
|
||||
use crate::pyobject::{
|
||||
IdProtocol, PyContext, PyFuncArgs, PyObject, PyObjectPayload, PyResult, TypeProtocol,
|
||||
};
|
||||
use crate::vm::VirtualMachine; // Required for arg_check! to use isinstance
|
||||
|
||||
fn filter_new(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
arg_check!(
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
use super::super::pyobject::{
|
||||
PyContext, PyFuncArgs, PyObjectPayload, PyObjectRef, PyResult, TypeProtocol,
|
||||
};
|
||||
use super::super::vm::VirtualMachine;
|
||||
use super::objbytes;
|
||||
use super::objint;
|
||||
use super::objstr;
|
||||
use super::objtype;
|
||||
use crate::pyobject::{
|
||||
PyContext, PyFuncArgs, PyObjectPayload, PyObjectRef, PyResult, TypeProtocol,
|
||||
};
|
||||
use crate::vm::VirtualMachine;
|
||||
use num_bigint::ToBigInt;
|
||||
use num_traits::ToPrimitive;
|
||||
|
||||
|
||||
@@ -2,12 +2,11 @@
|
||||
|
||||
*/
|
||||
|
||||
use super::super::frame::Frame;
|
||||
use super::super::pyobject::{
|
||||
use crate::frame::Frame;
|
||||
use crate::pyobject::{
|
||||
PyContext, PyFuncArgs, PyObjectPayload, PyObjectRef, PyResult, TypeProtocol,
|
||||
};
|
||||
use super::super::vm::VirtualMachine;
|
||||
use super::objtype;
|
||||
use crate::vm::VirtualMachine;
|
||||
|
||||
pub fn init(context: &PyContext) {
|
||||
let frame_type = &context.frame_type;
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
use super::super::pyobject::{
|
||||
use crate::pyobject::{
|
||||
AttributeProtocol, IdProtocol, PyContext, PyFuncArgs, PyObjectPayload, PyResult, TypeProtocol,
|
||||
};
|
||||
use super::super::vm::VirtualMachine;
|
||||
use super::objtype;
|
||||
use crate::vm::VirtualMachine;
|
||||
|
||||
pub fn init(context: &PyContext) {
|
||||
let function_type = &context.function_type;
|
||||
|
||||
@@ -2,12 +2,11 @@
|
||||
* The mythical generator.
|
||||
*/
|
||||
|
||||
use super::super::frame::{ExecutionResult, Frame};
|
||||
use super::super::pyobject::{
|
||||
use crate::frame::{ExecutionResult, Frame};
|
||||
use crate::pyobject::{
|
||||
PyContext, PyFuncArgs, PyObject, PyObjectPayload, PyObjectRef, PyResult, TypeProtocol,
|
||||
};
|
||||
use super::super::vm::VirtualMachine;
|
||||
use super::objtype;
|
||||
use crate::vm::VirtualMachine;
|
||||
|
||||
pub fn init(context: &PyContext) {
|
||||
let generator_type = &context.generator_type;
|
||||
|
||||
+20
-6
@@ -1,12 +1,12 @@
|
||||
use super::super::format::FormatSpec;
|
||||
use super::super::pyobject::{
|
||||
FromPyObjectRef, PyContext, PyFuncArgs, PyObject, PyObjectPayload, PyObjectRef, PyResult,
|
||||
TypeProtocol,
|
||||
};
|
||||
use super::super::vm::VirtualMachine;
|
||||
use super::objfloat;
|
||||
use super::objstr;
|
||||
use super::objtype;
|
||||
use crate::format::FormatSpec;
|
||||
use crate::pyobject::{
|
||||
FromPyObjectRef, PyContext, PyFuncArgs, PyObject, PyObjectPayload, PyObjectRef, PyResult,
|
||||
TypeProtocol,
|
||||
};
|
||||
use crate::vm::VirtualMachine;
|
||||
use num_bigint::{BigInt, ToBigInt};
|
||||
use num_integer::Integer;
|
||||
use num_traits::{Pow, Signed, ToPrimitive, Zero};
|
||||
@@ -608,6 +608,18 @@ fn int_conjugate(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
Ok(vm.ctx.new_int(v))
|
||||
}
|
||||
|
||||
fn int_real(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
arg_check!(vm, args, required = [(zelf, Some(vm.ctx.int_type()))]);
|
||||
let value = BigInt::from_pyobj(zelf);
|
||||
Ok(vm.ctx.new_int(value))
|
||||
}
|
||||
|
||||
fn int_imag(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
arg_check!(vm, args, required = [(_zelf, Some(vm.ctx.int_type()))]);
|
||||
let value = BigInt::from(0);
|
||||
Ok(vm.ctx.new_int(value))
|
||||
}
|
||||
|
||||
pub fn init(context: &PyContext) {
|
||||
let int_doc = "int(x=0) -> integer
|
||||
int(x, base=10) -> integer
|
||||
@@ -680,4 +692,6 @@ Base 0 means to interpret the base from the string as an integer literal.
|
||||
);
|
||||
context.set_attr(&int_type, "__doc__", context.new_str(int_doc.to_string()));
|
||||
context.set_attr(&int_type, "conjugate", context.new_rustfunc(int_conjugate));
|
||||
context.set_attr(&int_type, "real", context.new_property(int_real));
|
||||
context.set_attr(&int_type, "imag", context.new_property(int_imag));
|
||||
}
|
||||
@@ -2,11 +2,11 @@
|
||||
* Various types to support iteration.
|
||||
*/
|
||||
|
||||
use super::super::pyobject::{
|
||||
use super::objbool;
|
||||
use crate::pyobject::{
|
||||
PyContext, PyFuncArgs, PyObjectPayload, PyObjectRef, PyResult, TypeProtocol,
|
||||
};
|
||||
use super::super::vm::VirtualMachine;
|
||||
use super::objbool;
|
||||
use crate::vm::VirtualMachine;
|
||||
// use super::objstr;
|
||||
use super::objtype; // Required for arg_check! to use isinstance
|
||||
|
||||
|
||||
+43
-8
@@ -1,7 +1,3 @@
|
||||
use super::super::pyobject::{
|
||||
PyContext, PyFuncArgs, PyObject, PyObjectPayload, PyObjectRef, PyResult, TypeProtocol,
|
||||
};
|
||||
use super::super::vm::{ReprGuard, VirtualMachine};
|
||||
use super::objbool;
|
||||
use super::objint;
|
||||
use super::objsequence::{
|
||||
@@ -10,6 +6,11 @@ use super::objsequence::{
|
||||
};
|
||||
use super::objstr;
|
||||
use super::objtype;
|
||||
use crate::pyobject::{
|
||||
IdProtocol, PyContext, PyFuncArgs, PyObject, PyObjectPayload, PyObjectRef, PyResult,
|
||||
TypeProtocol,
|
||||
};
|
||||
use crate::vm::{ReprGuard, VirtualMachine};
|
||||
use num_traits::ToPrimitive;
|
||||
|
||||
// set_item:
|
||||
@@ -66,6 +67,10 @@ fn list_eq(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
required = [(zelf, Some(vm.ctx.list_type())), (other, None)]
|
||||
);
|
||||
|
||||
if zelf.is(&other) {
|
||||
return Ok(vm.ctx.new_bool(true));
|
||||
}
|
||||
|
||||
let result = if objtype::isinstance(other, &vm.ctx.list_type()) {
|
||||
let zelf = get_elements(zelf);
|
||||
let other = get_elements(other);
|
||||
@@ -181,6 +186,21 @@ fn list_add(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
}
|
||||
}
|
||||
|
||||
fn list_iadd(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
arg_check!(
|
||||
vm,
|
||||
args,
|
||||
required = [(zelf, Some(vm.ctx.list_type())), (other, None)]
|
||||
);
|
||||
|
||||
if objtype::isinstance(other, &vm.ctx.list_type()) {
|
||||
get_mut_elements(zelf).extend_from_slice(&get_elements(other));
|
||||
Ok(zelf.clone())
|
||||
} else {
|
||||
Ok(vm.ctx.not_implemented())
|
||||
}
|
||||
}
|
||||
|
||||
fn list_repr(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
arg_check!(vm, args, required = [(o, Some(vm.ctx.list_type()))]);
|
||||
|
||||
@@ -234,9 +254,13 @@ fn list_count(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
let elements = get_elements(zelf);
|
||||
let mut count: usize = 0;
|
||||
for element in elements.iter() {
|
||||
let is_eq = vm._eq(element.clone(), value.clone())?;
|
||||
if objbool::boolval(vm, is_eq)? {
|
||||
if value.is(&element) {
|
||||
count += 1;
|
||||
} else {
|
||||
let is_eq = vm._eq(element.clone(), value.clone())?;
|
||||
if objbool::boolval(vm, is_eq)? {
|
||||
count += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(vm.context().new_int(count))
|
||||
@@ -262,6 +286,9 @@ fn list_index(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
required = [(list, Some(vm.ctx.list_type())), (needle, None)]
|
||||
);
|
||||
for (index, element) in get_elements(list).iter().enumerate() {
|
||||
if needle.is(&element) {
|
||||
return Ok(vm.context().new_int(index));
|
||||
}
|
||||
let py_equal = vm._eq(needle.clone(), element.clone())?;
|
||||
if objbool::get_value(&py_equal) {
|
||||
return Ok(vm.context().new_int(index));
|
||||
@@ -335,6 +362,9 @@ fn list_contains(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
required = [(list, Some(vm.ctx.list_type())), (needle, None)]
|
||||
);
|
||||
for element in get_elements(list).iter() {
|
||||
if needle.is(&element) {
|
||||
return Ok(vm.new_bool(true));
|
||||
}
|
||||
match vm._eq(needle.clone(), element.clone()) {
|
||||
Ok(value) => {
|
||||
if objbool::get_value(&value) {
|
||||
@@ -416,9 +446,12 @@ fn list_remove(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
required = [(list, Some(vm.ctx.list_type())), (needle, None)]
|
||||
);
|
||||
|
||||
let mut elements = get_mut_elements(list);
|
||||
let mut ri: Option<usize> = None;
|
||||
for (index, element) in elements.iter().enumerate() {
|
||||
for (index, element) in get_elements(list).iter().enumerate() {
|
||||
if needle.is(&element) {
|
||||
ri = Some(index);
|
||||
break;
|
||||
}
|
||||
let py_equal = vm._eq(needle.clone(), element.clone())?;
|
||||
if objbool::get_value(&py_equal) {
|
||||
ri = Some(index);
|
||||
@@ -427,6 +460,7 @@ fn list_remove(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
}
|
||||
|
||||
if let Some(index) = ri {
|
||||
let mut elements = get_mut_elements(list);
|
||||
elements.remove(index);
|
||||
Ok(vm.get_none())
|
||||
} else {
|
||||
@@ -443,6 +477,7 @@ pub fn init(context: &PyContext) {
|
||||
The argument must be an iterable if specified.";
|
||||
|
||||
context.set_attr(&list_type, "__add__", context.new_rustfunc(list_add));
|
||||
context.set_attr(&list_type, "__iadd__", context.new_rustfunc(list_iadd));
|
||||
context.set_attr(
|
||||
&list_type,
|
||||
"__contains__",
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
use super::super::pyobject::{
|
||||
PyContext, PyFuncArgs, PyObject, PyObjectPayload, PyResult, TypeProtocol,
|
||||
};
|
||||
use super::super::vm::VirtualMachine;
|
||||
use super::objiter;
|
||||
use super::objtype; // Required for arg_check! to use isinstance
|
||||
use crate::pyobject::{PyContext, PyFuncArgs, PyObject, PyObjectPayload, PyResult, TypeProtocol};
|
||||
use crate::vm::VirtualMachine; // Required for arg_check! to use isinstance
|
||||
|
||||
fn map_new(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
no_kwargs!(vm, args);
|
||||
|
||||
@@ -1,9 +1,5 @@
|
||||
use super::objtype;
|
||||
|
||||
use super::super::pyobject::{
|
||||
PyContext, PyFuncArgs, PyObject, PyObjectPayload, PyResult, TypeProtocol,
|
||||
};
|
||||
use super::super::vm::VirtualMachine;
|
||||
use crate::pyobject::{PyContext, PyFuncArgs, PyObject, PyObjectPayload, PyResult, TypeProtocol};
|
||||
use crate::vm::VirtualMachine;
|
||||
|
||||
pub fn new_memory_view(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
arg_check!(vm, args, required = [(cls, None), (bytes_object, None)]);
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
use super::super::pyobject::{PyContext, PyFuncArgs, PyResult, TypeProtocol};
|
||||
use super::super::vm::VirtualMachine;
|
||||
use super::objtype;
|
||||
use crate::pyobject::{PyContext, PyFuncArgs, PyResult, TypeProtocol};
|
||||
use crate::vm::VirtualMachine;
|
||||
|
||||
pub fn init(context: &PyContext) {
|
||||
let none_type = &context.none.typ();
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
use super::super::pyobject::{
|
||||
use super::objstr;
|
||||
use super::objtype;
|
||||
use crate::pyobject::{
|
||||
AttributeProtocol, IdProtocol, PyContext, PyFuncArgs, PyObjectPayload, PyObjectRef, PyResult,
|
||||
TypeProtocol,
|
||||
};
|
||||
use super::super::vm::VirtualMachine;
|
||||
use super::objstr;
|
||||
use super::objtype;
|
||||
use crate::vm::VirtualMachine;
|
||||
use std::cell::RefCell;
|
||||
use std::collections::HashMap;
|
||||
|
||||
|
||||
@@ -2,9 +2,8 @@
|
||||
|
||||
*/
|
||||
|
||||
use super::super::pyobject::{PyContext, PyFuncArgs, PyResult, TypeProtocol};
|
||||
use super::super::vm::VirtualMachine;
|
||||
use super::objtype;
|
||||
use crate::pyobject::{PyContext, PyFuncArgs, PyResult, TypeProtocol};
|
||||
use crate::vm::VirtualMachine;
|
||||
|
||||
pub fn init(context: &PyContext) {
|
||||
let property_type = &context.property_type;
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
use super::super::pyobject::{
|
||||
PyContext, PyFuncArgs, PyObject, PyObjectPayload, PyObjectRef, PyResult, TypeProtocol,
|
||||
};
|
||||
use super::super::vm::VirtualMachine;
|
||||
use super::objint;
|
||||
use super::objtype;
|
||||
use crate::pyobject::{
|
||||
PyContext, PyFuncArgs, PyObject, PyObjectPayload, PyObjectRef, PyResult, TypeProtocol,
|
||||
};
|
||||
use crate::vm::VirtualMachine;
|
||||
use num_bigint::{BigInt, Sign};
|
||||
use num_integer::Integer;
|
||||
use num_traits::{One, Signed, ToPrimitive, Zero};
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use super::super::pyobject::{PyObject, PyObjectPayload, PyObjectRef, PyResult, TypeProtocol};
|
||||
use super::super::vm::VirtualMachine;
|
||||
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};
|
||||
@@ -178,10 +178,12 @@ pub fn seq_equal(
|
||||
) -> Result<bool, PyObjectRef> {
|
||||
if zelf.len() == other.len() {
|
||||
for (a, b) in Iterator::zip(zelf.iter(), other.iter()) {
|
||||
let eq = vm._eq(a.clone(), b.clone())?;
|
||||
let value = objbool::boolval(vm, eq)?;
|
||||
if !value {
|
||||
return Ok(false);
|
||||
if !a.is(&b) {
|
||||
let eq = vm._eq(a.clone(), b.clone())?;
|
||||
let value = objbool::boolval(vm, eq)?;
|
||||
if !value {
|
||||
return Ok(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(true)
|
||||
|
||||
+176
-4
@@ -2,15 +2,15 @@
|
||||
* Builtin set type with a sequence of unique items.
|
||||
*/
|
||||
|
||||
use super::super::pyobject::{
|
||||
PyContext, PyFuncArgs, PyObject, PyObjectPayload, PyObjectRef, PyResult, TypeProtocol,
|
||||
};
|
||||
use super::super::vm::{ReprGuard, VirtualMachine};
|
||||
use super::objbool;
|
||||
use super::objint;
|
||||
use super::objiter;
|
||||
use super::objstr;
|
||||
use super::objtype;
|
||||
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};
|
||||
@@ -178,6 +178,16 @@ fn set_len(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
Ok(vm.context().new_int(elements.len()))
|
||||
}
|
||||
|
||||
fn set_copy(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
trace!("set.copy called with: {:?}", args);
|
||||
arg_check!(vm, args, required = [(s, Some(vm.ctx.set_type()))]);
|
||||
let elements = get_elements(s);
|
||||
Ok(PyObject::new(
|
||||
PyObjectPayload::Set { elements },
|
||||
vm.ctx.set_type(),
|
||||
))
|
||||
}
|
||||
|
||||
fn set_repr(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
arg_check!(vm, args, required = [(o, Some(vm.ctx.set_type()))]);
|
||||
|
||||
@@ -408,6 +418,145 @@ 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())),
|
||||
},
|
||||
_ => Err(vm.new_type_error("".to_string())),
|
||||
}
|
||||
}
|
||||
|
||||
fn set_update(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
set_ior(vm, args)?;
|
||||
Ok(vm.get_none())
|
||||
}
|
||||
|
||||
fn set_ior(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
arg_check!(
|
||||
vm,
|
||||
args,
|
||||
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 iterator = objiter::get_iter(vm, iterable)?;
|
||||
while let Ok(v) = vm.call_method(&iterator, "__next__", vec![]) {
|
||||
insert_into_set(vm, elements, &v)?;
|
||||
}
|
||||
}
|
||||
_ => return Err(vm.new_type_error("set.update is called with no other".to_string())),
|
||||
}
|
||||
Ok(zelf.clone())
|
||||
}
|
||||
|
||||
fn set_intersection_update(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
set_combine_update_inner(vm, args, SetCombineOperation::Intersection)?;
|
||||
Ok(vm.get_none())
|
||||
}
|
||||
|
||||
fn set_iand(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
set_combine_update_inner(vm, args, SetCombineOperation::Intersection)
|
||||
}
|
||||
|
||||
fn set_difference_update(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
set_combine_update_inner(vm, args, SetCombineOperation::Difference)?;
|
||||
Ok(vm.get_none())
|
||||
}
|
||||
|
||||
fn set_isub(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
set_combine_update_inner(vm, args, SetCombineOperation::Difference)
|
||||
}
|
||||
|
||||
fn set_combine_update_inner(
|
||||
vm: &mut VirtualMachine,
|
||||
args: PyFuncArgs,
|
||||
op: SetCombineOperation,
|
||||
) -> PyResult {
|
||||
arg_check!(
|
||||
vm,
|
||||
args,
|
||||
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 } => {
|
||||
for element in elements.clone().iter() {
|
||||
let value = vm.call_method(iterable, "__contains__", vec![element.1.clone()])?;
|
||||
let should_remove = match op {
|
||||
SetCombineOperation::Intersection => !objbool::get_value(&value),
|
||||
SetCombineOperation::Difference => objbool::get_value(&value),
|
||||
};
|
||||
if should_remove {
|
||||
elements.remove(&element.0.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => return Err(vm.new_type_error("".to_string())),
|
||||
}
|
||||
Ok(zelf.clone())
|
||||
}
|
||||
|
||||
fn set_symmetric_difference_update(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
set_ixor(vm, args)?;
|
||||
Ok(vm.get_none())
|
||||
}
|
||||
|
||||
fn set_ixor(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
arg_check!(
|
||||
vm,
|
||||
args,
|
||||
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();
|
||||
let iterator = objiter::get_iter(vm, iterable)?;
|
||||
while let Ok(v) = vm.call_method(&iterator, "__next__", vec![]) {
|
||||
insert_into_set(vm, elements, &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());
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => return Err(vm.new_type_error("".to_string())),
|
||||
}
|
||||
|
||||
Ok(zelf.clone())
|
||||
}
|
||||
|
||||
fn set_iter(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
arg_check!(vm, args, required = [(zelf, Some(vm.ctx.set_type()))]);
|
||||
|
||||
let items = get_elements(zelf).values().map(|x| x.clone()).collect();
|
||||
let set_list = vm.ctx.new_list(items);
|
||||
let iter_obj = PyObject::new(
|
||||
PyObjectPayload::Iterator {
|
||||
position: 0,
|
||||
iterated_obj: set_list,
|
||||
},
|
||||
vm.ctx.iter_type(),
|
||||
);
|
||||
|
||||
Ok(iter_obj)
|
||||
}
|
||||
|
||||
fn frozenset_repr(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
arg_check!(vm, args, required = [(o, Some(vm.ctx.frozenset_type()))]);
|
||||
|
||||
@@ -477,6 +626,29 @@ pub fn init(context: &PyContext) {
|
||||
context.set_attr(&set_type, "remove", context.new_rustfunc(set_remove));
|
||||
context.set_attr(&set_type, "discard", context.new_rustfunc(set_discard));
|
||||
context.set_attr(&set_type, "clear", context.new_rustfunc(set_clear));
|
||||
context.set_attr(&set_type, "copy", context.new_rustfunc(set_copy));
|
||||
context.set_attr(&set_type, "pop", context.new_rustfunc(set_pop));
|
||||
context.set_attr(&set_type, "update", context.new_rustfunc(set_update));
|
||||
context.set_attr(&set_type, "__ior__", context.new_rustfunc(set_ior));
|
||||
context.set_attr(
|
||||
&set_type,
|
||||
"intersection_update",
|
||||
context.new_rustfunc(set_intersection_update),
|
||||
);
|
||||
context.set_attr(&set_type, "__iand__", context.new_rustfunc(set_iand));
|
||||
context.set_attr(
|
||||
&set_type,
|
||||
"difference_update",
|
||||
context.new_rustfunc(set_difference_update),
|
||||
);
|
||||
context.set_attr(&set_type, "__isub__", context.new_rustfunc(set_isub));
|
||||
context.set_attr(
|
||||
&set_type,
|
||||
"symmetric_difference_update",
|
||||
context.new_rustfunc(set_symmetric_difference_update),
|
||||
);
|
||||
context.set_attr(&set_type, "__ixor__", context.new_rustfunc(set_ixor));
|
||||
context.set_attr(&set_type, "__iter__", context.new_rustfunc(set_iter));
|
||||
|
||||
let frozenset_type = &context.frozenset_type;
|
||||
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
use super::super::pyobject::{
|
||||
use super::objint;
|
||||
use crate::pyobject::{
|
||||
PyContext, PyFuncArgs, PyObject, PyObjectPayload, PyObjectRef, PyResult, TypeProtocol,
|
||||
};
|
||||
use super::super::vm::VirtualMachine;
|
||||
use super::objint;
|
||||
use super::objtype; // Required for arg_check! to use isinstance
|
||||
use crate::vm::VirtualMachine;
|
||||
use num_bigint::BigInt;
|
||||
|
||||
fn slice_new(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
use super::super::format::{FormatParseError, FormatPart, FormatString};
|
||||
use super::super::pyobject::{
|
||||
PyContext, PyFuncArgs, PyObject, PyObjectPayload, PyObjectRef, PyResult, TypeProtocol,
|
||||
};
|
||||
use super::super::vm::VirtualMachine;
|
||||
use super::objint;
|
||||
use super::objsequence::PySliceableSequence;
|
||||
use super::objtype;
|
||||
use crate::format::{FormatParseError, FormatPart, FormatString};
|
||||
use crate::pyobject::{
|
||||
PyContext, PyFuncArgs, PyObject, PyObjectPayload, PyObjectRef, PyResult, TypeProtocol,
|
||||
};
|
||||
use crate::vm::VirtualMachine;
|
||||
use num_traits::ToPrimitive;
|
||||
use std::cell::Ref;
|
||||
use std::hash::{Hash, Hasher};
|
||||
|
||||
@@ -6,9 +6,9 @@ https://github.com/python/cpython/blob/50b48572d9a90c5bb36e2bef6179548ea927a35a/
|
||||
|
||||
*/
|
||||
|
||||
use super::super::pyobject::{PyContext, PyFuncArgs, PyResult, TypeProtocol};
|
||||
use super::super::vm::VirtualMachine;
|
||||
use super::objtype;
|
||||
use crate::pyobject::{PyContext, PyFuncArgs, PyResult, TypeProtocol};
|
||||
use crate::vm::VirtualMachine;
|
||||
|
||||
pub fn init(context: &PyContext) {
|
||||
let super_type = &context.super_type;
|
||||
|
||||
@@ -1,7 +1,3 @@
|
||||
use super::super::pyobject::{
|
||||
PyContext, PyFuncArgs, PyObject, PyObjectPayload, PyResult, TypeProtocol,
|
||||
};
|
||||
use super::super::vm::{ReprGuard, VirtualMachine};
|
||||
use super::objbool;
|
||||
use super::objint;
|
||||
use super::objsequence::{
|
||||
@@ -9,6 +5,8 @@ use super::objsequence::{
|
||||
};
|
||||
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 {
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
use super::super::pyobject::{
|
||||
AttributeProtocol, IdProtocol, PyAttributes, PyContext, PyFuncArgs, PyObject, PyObjectPayload,
|
||||
PyObjectRef, PyResult, TypeProtocol,
|
||||
};
|
||||
use super::super::vm::VirtualMachine;
|
||||
use super::objdict;
|
||||
use super::objstr;
|
||||
use super::objtype; // Required for arg_check! to use isinstance
|
||||
use crate::pyobject::{
|
||||
AttributeProtocol, IdProtocol, PyAttributes, PyContext, PyFuncArgs, PyObject, PyObjectPayload,
|
||||
PyObjectRef, PyResult, TypeProtocol,
|
||||
};
|
||||
use crate::vm::VirtualMachine;
|
||||
use std::cell::RefCell;
|
||||
use std::collections::HashMap;
|
||||
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
use super::super::pyobject::{
|
||||
PyContext, PyFuncArgs, PyObject, PyObjectPayload, PyResult, TypeProtocol,
|
||||
};
|
||||
use super::super::vm::VirtualMachine;
|
||||
use super::objiter;
|
||||
use super::objtype; // Required for arg_check! to use isinstance
|
||||
use crate::pyobject::{PyContext, PyFuncArgs, PyObject, PyObjectPayload, PyResult, TypeProtocol};
|
||||
use crate::vm::VirtualMachine; // Required for arg_check! to use isinstance
|
||||
|
||||
fn zip_new(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
no_kwargs!(vm, args);
|
||||
|
||||
+32
-32
@@ -1,35 +1,35 @@
|
||||
use super::bytecode;
|
||||
use super::exceptions;
|
||||
use super::frame::Frame;
|
||||
use super::obj::objbool;
|
||||
use super::obj::objbytearray;
|
||||
use super::obj::objbytes;
|
||||
use super::obj::objcode;
|
||||
use super::obj::objcomplex;
|
||||
use super::obj::objdict;
|
||||
use super::obj::objenumerate;
|
||||
use super::obj::objfilter;
|
||||
use super::obj::objfloat;
|
||||
use super::obj::objframe;
|
||||
use super::obj::objfunction;
|
||||
use super::obj::objgenerator;
|
||||
use super::obj::objint;
|
||||
use super::obj::objiter;
|
||||
use super::obj::objlist;
|
||||
use super::obj::objmap;
|
||||
use super::obj::objmemory;
|
||||
use super::obj::objnone;
|
||||
use super::obj::objobject;
|
||||
use super::obj::objproperty;
|
||||
use super::obj::objrange;
|
||||
use super::obj::objset;
|
||||
use super::obj::objslice;
|
||||
use super::obj::objstr;
|
||||
use super::obj::objsuper;
|
||||
use super::obj::objtuple;
|
||||
use super::obj::objtype;
|
||||
use super::obj::objzip;
|
||||
use super::vm::VirtualMachine;
|
||||
use crate::bytecode;
|
||||
use crate::exceptions;
|
||||
use crate::frame::Frame;
|
||||
use crate::obj::objbool;
|
||||
use crate::obj::objbytearray;
|
||||
use crate::obj::objbytes;
|
||||
use crate::obj::objcode;
|
||||
use crate::obj::objcomplex;
|
||||
use crate::obj::objdict;
|
||||
use crate::obj::objenumerate;
|
||||
use crate::obj::objfilter;
|
||||
use crate::obj::objfloat;
|
||||
use crate::obj::objframe;
|
||||
use crate::obj::objfunction;
|
||||
use crate::obj::objgenerator;
|
||||
use crate::obj::objint;
|
||||
use crate::obj::objiter;
|
||||
use crate::obj::objlist;
|
||||
use crate::obj::objmap;
|
||||
use crate::obj::objmemory;
|
||||
use crate::obj::objnone;
|
||||
use crate::obj::objobject;
|
||||
use crate::obj::objproperty;
|
||||
use crate::obj::objrange;
|
||||
use crate::obj::objset;
|
||||
use crate::obj::objslice;
|
||||
use crate::obj::objstr;
|
||||
use crate::obj::objsuper;
|
||||
use crate::obj::objtuple;
|
||||
use crate::obj::objtype;
|
||||
use crate::obj::objzip;
|
||||
use crate::vm::VirtualMachine;
|
||||
use num_bigint::BigInt;
|
||||
use num_bigint::ToBigInt;
|
||||
use num_complex::Complex64;
|
||||
|
||||
@@ -6,9 +6,9 @@
|
||||
extern crate rustpython_parser;
|
||||
|
||||
use self::rustpython_parser::{ast, parser};
|
||||
use super::super::obj::{objstr, objtype};
|
||||
use super::super::pyobject::{PyContext, PyFuncArgs, PyObjectRef, PyResult, TypeProtocol};
|
||||
use super::super::VirtualMachine;
|
||||
use crate::obj::objstr;
|
||||
use crate::pyobject::{PyContext, PyFuncArgs, PyObjectRef, PyResult, TypeProtocol};
|
||||
use crate::VirtualMachine;
|
||||
use num_complex::Complex64;
|
||||
use std::ops::Deref;
|
||||
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
use crate::obj::objcode;
|
||||
use crate::pyobject::{PyContext, PyFuncArgs, PyObjectRef, PyResult, TypeProtocol};
|
||||
use crate::vm::VirtualMachine;
|
||||
|
||||
fn dis_disassemble(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
arg_check!(vm, args, required = [(co, Some(vm.ctx.code_type()))]);
|
||||
|
||||
let code = objcode::get_value(co);
|
||||
print!("{}", code);
|
||||
Ok(vm.get_none())
|
||||
}
|
||||
|
||||
pub fn mk_module(ctx: &PyContext) -> PyObjectRef {
|
||||
py_module!(ctx, "dis", {
|
||||
"disassemble" => ctx.new_rustfunc(dis_disassemble)
|
||||
})
|
||||
}
|
||||
+9
-10
@@ -13,18 +13,17 @@ use num_bigint::ToBigInt;
|
||||
use num_traits::ToPrimitive;
|
||||
|
||||
//custom imports
|
||||
use super::super::obj::objbytes;
|
||||
use super::super::obj::objint;
|
||||
use super::super::obj::objstr;
|
||||
use super::super::obj::objtype;
|
||||
use super::os;
|
||||
use crate::obj::objbytes;
|
||||
use crate::obj::objint;
|
||||
use crate::obj::objstr;
|
||||
|
||||
use super::super::pyobject::{
|
||||
use crate::pyobject::{
|
||||
AttributeProtocol, BufferProtocol, PyContext, PyFuncArgs, PyObjectPayload, PyObjectRef,
|
||||
PyResult, TypeProtocol,
|
||||
};
|
||||
|
||||
use super::super::vm::VirtualMachine;
|
||||
use crate::vm::VirtualMachine;
|
||||
|
||||
fn compute_c_flag(mode: &str) -> u16 {
|
||||
match mode {
|
||||
@@ -421,18 +420,18 @@ pub fn mk_module(ctx: &PyContext) -> PyObjectRef {
|
||||
};
|
||||
ctx.set_attr(&py_mod, "TextIOWrapper", text_io_wrapper.clone());
|
||||
|
||||
// BytesIO: in-memory bytes
|
||||
//StringIO: in-memory text
|
||||
let string_io = {
|
||||
let string_io = ctx.new_class("StringIO", io_base.clone());
|
||||
let string_io = ctx.new_class("StringIO", text_io_base.clone());
|
||||
ctx.set_attr(&string_io, "__init__", ctx.new_rustfunc(string_io_init));
|
||||
ctx.set_attr(&string_io, "getvalue", ctx.new_rustfunc(string_io_getvalue));
|
||||
string_io
|
||||
};
|
||||
ctx.set_attr(&py_mod, "StringIO", string_io);
|
||||
|
||||
// StringIO: in-memory text
|
||||
//BytesIO: in-memory bytes
|
||||
let bytes_io = {
|
||||
let bytes_io = ctx.new_class("BytesIO", io_base.clone());
|
||||
let bytes_io = ctx.new_class("BytesIO", buffered_io_base.clone());
|
||||
ctx.set_attr(&bytes_io, "__init__", ctx.new_rustfunc(bytes_io_init));
|
||||
ctx.set_attr(&bytes_io, "getvalue", ctx.new_rustfunc(bytes_io_getvalue));
|
||||
bytes_io
|
||||
|
||||
@@ -5,12 +5,12 @@ use serde::de::{DeserializeSeed, Visitor};
|
||||
use serde::ser::{SerializeMap, SerializeSeq};
|
||||
use serde_json;
|
||||
|
||||
use super::super::obj::{objbool, objdict, objfloat, objint, objsequence, objstr, objtype};
|
||||
use super::super::pyobject::{
|
||||
use crate::obj::{objbool, objdict, objfloat, objint, objsequence, objstr, objtype};
|
||||
use crate::pyobject::{
|
||||
create_type, DictProtocol, PyContext, PyFuncArgs, PyObjectPayload, PyObjectRef, PyResult,
|
||||
TypeProtocol,
|
||||
};
|
||||
use super::super::VirtualMachine;
|
||||
use crate::VirtualMachine;
|
||||
use num_traits::cast::ToPrimitive;
|
||||
|
||||
// We need to have a VM available to serialise a PyObject based on its subclass, so we implement
|
||||
|
||||
@@ -4,9 +4,9 @@
|
||||
|
||||
extern crate rustpython_parser;
|
||||
use self::rustpython_parser::lexer;
|
||||
use super::super::obj::{objstr, objtype};
|
||||
use super::super::pyobject::{PyContext, PyFuncArgs, PyObjectRef, PyResult, TypeProtocol};
|
||||
use super::super::VirtualMachine;
|
||||
use crate::obj::objstr;
|
||||
use crate::pyobject::{PyContext, PyFuncArgs, PyObjectRef, PyResult, TypeProtocol};
|
||||
use crate::VirtualMachine;
|
||||
|
||||
fn keyword_iskeyword(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
arg_check!(vm, args, required = [(s, Some(vm.ctx.str_type()))]);
|
||||
|
||||
+48
-50
@@ -3,9 +3,9 @@
|
||||
*
|
||||
*/
|
||||
|
||||
use super::super::obj::{objfloat, objtype};
|
||||
use super::super::pyobject::{PyContext, PyFuncArgs, PyObjectRef, PyResult, TypeProtocol};
|
||||
use super::super::VirtualMachine;
|
||||
use crate::obj::objfloat;
|
||||
use crate::pyobject::{PyContext, PyFuncArgs, PyObjectRef, PyResult, TypeProtocol};
|
||||
use crate::VirtualMachine;
|
||||
use statrs::function::erf::{erf, erfc};
|
||||
use statrs::function::gamma::{gamma, ln_gamma};
|
||||
use std;
|
||||
@@ -172,57 +172,55 @@ fn math_lgamma(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
}
|
||||
|
||||
pub fn mk_module(ctx: &PyContext) -> PyObjectRef {
|
||||
let py_mod = ctx.new_module(&"math".to_string(), ctx.new_scope(None));
|
||||
py_module!(ctx, "math", {
|
||||
// Number theory functions:
|
||||
"fabs" => ctx.new_rustfunc(math_fabs),
|
||||
"isfinite" => ctx.new_rustfunc(math_isfinite),
|
||||
"isinf" => ctx.new_rustfunc(math_isinf),
|
||||
"isnan" => ctx.new_rustfunc(math_isnan),
|
||||
|
||||
// Number theory functions:
|
||||
ctx.set_attr(&py_mod, "fabs", ctx.new_rustfunc(math_fabs));
|
||||
ctx.set_attr(&py_mod, "isfinite", ctx.new_rustfunc(math_isfinite));
|
||||
ctx.set_attr(&py_mod, "isinf", ctx.new_rustfunc(math_isinf));
|
||||
ctx.set_attr(&py_mod, "isnan", ctx.new_rustfunc(math_isnan));
|
||||
// Power and logarithmic functions:
|
||||
"exp" => ctx.new_rustfunc(math_exp),
|
||||
"expm1" => ctx.new_rustfunc(math_expm1),
|
||||
"log" => ctx.new_rustfunc(math_log),
|
||||
"log1p" => ctx.new_rustfunc(math_log1p),
|
||||
"log2" => ctx.new_rustfunc(math_log2),
|
||||
"log10" => ctx.new_rustfunc(math_log10),
|
||||
"pow" => ctx.new_rustfunc(math_pow),
|
||||
"sqrt" => ctx.new_rustfunc(math_sqrt),
|
||||
|
||||
// Power and logarithmic functions:
|
||||
ctx.set_attr(&py_mod, "exp", ctx.new_rustfunc(math_exp));
|
||||
ctx.set_attr(&py_mod, "expm1", ctx.new_rustfunc(math_expm1));
|
||||
ctx.set_attr(&py_mod, "log", ctx.new_rustfunc(math_log));
|
||||
ctx.set_attr(&py_mod, "log1p", ctx.new_rustfunc(math_log1p));
|
||||
ctx.set_attr(&py_mod, "log2", ctx.new_rustfunc(math_log2));
|
||||
ctx.set_attr(&py_mod, "log10", ctx.new_rustfunc(math_log10));
|
||||
ctx.set_attr(&py_mod, "pow", ctx.new_rustfunc(math_pow));
|
||||
ctx.set_attr(&py_mod, "sqrt", ctx.new_rustfunc(math_sqrt));
|
||||
// Trigonometric functions:
|
||||
"acos" => ctx.new_rustfunc(math_acos),
|
||||
"asin" => ctx.new_rustfunc(math_asin),
|
||||
"atan" => ctx.new_rustfunc(math_atan),
|
||||
"atan2" => ctx.new_rustfunc(math_atan2),
|
||||
"cos" => ctx.new_rustfunc(math_cos),
|
||||
"hypot" => ctx.new_rustfunc(math_hypot),
|
||||
"sin" => ctx.new_rustfunc(math_sin),
|
||||
"tan" => ctx.new_rustfunc(math_tan),
|
||||
|
||||
// Trigonometric functions:
|
||||
ctx.set_attr(&py_mod, "acos", ctx.new_rustfunc(math_acos));
|
||||
ctx.set_attr(&py_mod, "asin", ctx.new_rustfunc(math_asin));
|
||||
ctx.set_attr(&py_mod, "atan", ctx.new_rustfunc(math_atan));
|
||||
ctx.set_attr(&py_mod, "atan2", ctx.new_rustfunc(math_atan2));
|
||||
ctx.set_attr(&py_mod, "cos", ctx.new_rustfunc(math_cos));
|
||||
ctx.set_attr(&py_mod, "hypot", ctx.new_rustfunc(math_hypot));
|
||||
ctx.set_attr(&py_mod, "sin", ctx.new_rustfunc(math_sin));
|
||||
ctx.set_attr(&py_mod, "tan", ctx.new_rustfunc(math_tan));
|
||||
"degrees" => ctx.new_rustfunc(math_degrees),
|
||||
"radians" => ctx.new_rustfunc(math_radians),
|
||||
|
||||
ctx.set_attr(&py_mod, "degrees", ctx.new_rustfunc(math_degrees));
|
||||
ctx.set_attr(&py_mod, "radians", ctx.new_rustfunc(math_radians));
|
||||
// Hyperbolic functions:
|
||||
"acosh" => ctx.new_rustfunc(math_acosh),
|
||||
"asinh" => ctx.new_rustfunc(math_asinh),
|
||||
"atanh" => ctx.new_rustfunc(math_atanh),
|
||||
"cosh" => ctx.new_rustfunc(math_cosh),
|
||||
"sinh" => ctx.new_rustfunc(math_sinh),
|
||||
"tanh" => ctx.new_rustfunc(math_tanh),
|
||||
|
||||
// Hyperbolic functions:
|
||||
ctx.set_attr(&py_mod, "acosh", ctx.new_rustfunc(math_acosh));
|
||||
ctx.set_attr(&py_mod, "asinh", ctx.new_rustfunc(math_asinh));
|
||||
ctx.set_attr(&py_mod, "atanh", ctx.new_rustfunc(math_atanh));
|
||||
ctx.set_attr(&py_mod, "cosh", ctx.new_rustfunc(math_cosh));
|
||||
ctx.set_attr(&py_mod, "sinh", ctx.new_rustfunc(math_sinh));
|
||||
ctx.set_attr(&py_mod, "tanh", ctx.new_rustfunc(math_tanh));
|
||||
// Special functions:
|
||||
"erf" => ctx.new_rustfunc(math_erf),
|
||||
"erfc" => ctx.new_rustfunc(math_erfc),
|
||||
"gamma" => ctx.new_rustfunc(math_gamma),
|
||||
"lgamma" => ctx.new_rustfunc(math_lgamma),
|
||||
|
||||
// Special functions:
|
||||
ctx.set_attr(&py_mod, "erf", ctx.new_rustfunc(math_erf));
|
||||
ctx.set_attr(&py_mod, "erfc", ctx.new_rustfunc(math_erfc));
|
||||
ctx.set_attr(&py_mod, "gamma", ctx.new_rustfunc(math_gamma));
|
||||
ctx.set_attr(&py_mod, "lgamma", ctx.new_rustfunc(math_lgamma));
|
||||
|
||||
// Constants:
|
||||
ctx.set_attr(&py_mod, "pi", ctx.new_float(std::f64::consts::PI)); // 3.14159...
|
||||
ctx.set_attr(&py_mod, "e", ctx.new_float(std::f64::consts::E)); // 2.71..
|
||||
ctx.set_attr(&py_mod, "tau", ctx.new_float(2.0 * std::f64::consts::PI));
|
||||
ctx.set_attr(&py_mod, "inf", ctx.new_float(std::f64::INFINITY));
|
||||
ctx.set_attr(&py_mod, "nan", ctx.new_float(std::f64::NAN));
|
||||
|
||||
py_mod
|
||||
// Constants:
|
||||
"pi" => ctx.new_float(std::f64::consts::PI), // 3.14159...
|
||||
"e" => ctx.new_float(std::f64::consts::E), // 2.71..
|
||||
"tau" => ctx.new_float(2.0 * std::f64::consts::PI),
|
||||
"inf" => ctx.new_float(std::f64::INFINITY),
|
||||
"nan" => ctx.new_float(std::f64::NAN)
|
||||
})
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
mod ast;
|
||||
mod dis;
|
||||
mod json;
|
||||
mod keyword;
|
||||
mod math;
|
||||
@@ -17,13 +18,14 @@ pub mod io;
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
mod os;
|
||||
|
||||
use super::pyobject::{PyContext, PyObjectRef};
|
||||
use crate::pyobject::{PyContext, PyObjectRef};
|
||||
|
||||
pub type StdlibInitFunc = fn(&PyContext) -> PyObjectRef;
|
||||
|
||||
pub fn get_module_inits() -> HashMap<String, StdlibInitFunc> {
|
||||
let mut modules = HashMap::new();
|
||||
modules.insert("ast".to_string(), ast::mk_module as StdlibInitFunc);
|
||||
modules.insert("dis".to_string(), dis::mk_module as StdlibInitFunc);
|
||||
modules.insert("json".to_string(), json::mk_module as StdlibInitFunc);
|
||||
modules.insert("keyword".to_string(), keyword::mk_module as StdlibInitFunc);
|
||||
modules.insert("math".to_string(), math::mk_module as StdlibInitFunc);
|
||||
|
||||
+19
-10
@@ -8,36 +8,35 @@ use std::io::ErrorKind;
|
||||
use num_traits::cast::ToPrimitive;
|
||||
|
||||
//custom imports
|
||||
use super::super::obj::objint;
|
||||
use super::super::obj::objstr;
|
||||
use super::super::obj::objtype;
|
||||
// use super::super::obj::objdict;
|
||||
use crate::obj::objint;
|
||||
use crate::obj::objstr;
|
||||
// use crate::obj::objdict;
|
||||
|
||||
use super::super::pyobject::{PyContext, PyFuncArgs, PyObjectRef, PyResult, TypeProtocol};
|
||||
use super::super::vm::VirtualMachine;
|
||||
use crate::pyobject::{PyContext, PyFuncArgs, PyObjectRef, PyResult, TypeProtocol};
|
||||
use crate::vm::VirtualMachine;
|
||||
|
||||
#[cfg(target_family = "unix")]
|
||||
#[cfg(unix)]
|
||||
pub fn raw_file_number(handle: File) -> i64 {
|
||||
use std::os::unix::io::IntoRawFd;
|
||||
|
||||
i64::from(handle.into_raw_fd())
|
||||
}
|
||||
|
||||
#[cfg(target_family = "unix")]
|
||||
#[cfg(unix)]
|
||||
pub fn rust_file(raw_fileno: i64) -> File {
|
||||
use std::os::unix::io::FromRawFd;
|
||||
|
||||
unsafe { File::from_raw_fd(raw_fileno as i32) }
|
||||
}
|
||||
|
||||
#[cfg(target_family = "windows")]
|
||||
#[cfg(windows)]
|
||||
pub fn raw_file_number(handle: File) -> i64 {
|
||||
use std::os::windows::io::IntoRawHandle;
|
||||
|
||||
handle.into_raw_handle() as i64
|
||||
}
|
||||
|
||||
#[cfg(target_family = "windows")]
|
||||
#[cfg(windows)]
|
||||
pub fn rust_file(raw_fileno: i64) -> File {
|
||||
use std::ffi::c_void;
|
||||
use std::os::windows::io::FromRawHandle;
|
||||
@@ -46,6 +45,16 @@ pub fn rust_file(raw_fileno: i64) -> File {
|
||||
unsafe { File::from_raw_handle(raw_fileno as *mut c_void) }
|
||||
}
|
||||
|
||||
#[cfg(all(not(unix), not(windows)))]
|
||||
pub fn rust_file(raw_fileno: i64) -> File {
|
||||
unimplemented!();
|
||||
}
|
||||
|
||||
#[cfg(all(not(unix), not(windows)))]
|
||||
pub fn raw_file_number(handle: File) -> i64 {
|
||||
unimplemented!();
|
||||
}
|
||||
|
||||
pub fn os_close(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
arg_check!(vm, args, required = [(fileno, Some(vm.ctx.int_type()))]);
|
||||
|
||||
|
||||
@@ -10,9 +10,9 @@
|
||||
extern crate byteorder;
|
||||
use self::byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
|
||||
|
||||
use super::super::obj::{objbool, objbytes, objfloat, objint, objstr, objtype};
|
||||
use super::super::pyobject::{PyContext, PyFuncArgs, PyObjectRef, PyResult, TypeProtocol};
|
||||
use super::super::VirtualMachine;
|
||||
use crate::obj::{objbool, objbytes, objfloat, objint, objstr, objtype};
|
||||
use crate::pyobject::{PyContext, PyFuncArgs, PyObjectRef, PyResult, TypeProtocol};
|
||||
use crate::VirtualMachine;
|
||||
use num_bigint::BigInt;
|
||||
use num_traits::ToPrimitive;
|
||||
use std::io::{Cursor, Read, Write};
|
||||
|
||||
+10
-15
@@ -2,23 +2,18 @@
|
||||
|
||||
extern crate rand;
|
||||
|
||||
use super::super::obj::{objfloat, objtype};
|
||||
use super::super::pyobject::{PyContext, PyFuncArgs, PyObjectRef, PyResult, TypeProtocol};
|
||||
use super::super::VirtualMachine;
|
||||
use stdlib::random::rand::distributions::{Distribution, Normal};
|
||||
use crate::obj::objfloat;
|
||||
use crate::pyobject::{PyContext, PyFuncArgs, PyObjectRef, PyResult, TypeProtocol};
|
||||
use crate::stdlib::random::rand::distributions::{Distribution, Normal};
|
||||
use crate::VirtualMachine;
|
||||
|
||||
pub fn mk_module(ctx: &PyContext) -> PyObjectRef {
|
||||
let py_mod = ctx.new_module(&"random".to_string(), ctx.new_scope(None));
|
||||
ctx.set_attr(&py_mod, "gauss", ctx.new_rustfunc(random_gauss));
|
||||
ctx.set_attr(
|
||||
&py_mod,
|
||||
"normalvariate",
|
||||
ctx.new_rustfunc(random_normalvariate),
|
||||
);
|
||||
ctx.set_attr(&py_mod, "random", ctx.new_rustfunc(random_random));
|
||||
// py_mod.set_attr("weibull", ctx.new_rustfunc(random_weibullvariate));
|
||||
// TODO: implement more random functions.
|
||||
py_mod
|
||||
py_module!(ctx, "random", {
|
||||
"guass" => ctx.new_rustfunc(random_gauss),
|
||||
"normalvariate" => ctx.new_rustfunc(random_normalvariate),
|
||||
"random" => ctx.new_rustfunc(random_random),
|
||||
// "weibull", ctx.new_rustfunc(random_weibullvariate),
|
||||
})
|
||||
}
|
||||
|
||||
fn random_gauss(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
|
||||
+3
-3
@@ -8,9 +8,9 @@
|
||||
extern crate regex;
|
||||
use self::regex::Regex;
|
||||
|
||||
use super::super::obj::{objstr, objtype};
|
||||
use super::super::pyobject::{PyContext, PyFuncArgs, PyObjectRef, PyResult, TypeProtocol};
|
||||
use super::super::VirtualMachine;
|
||||
use crate::obj::objstr;
|
||||
use crate::pyobject::{PyContext, PyFuncArgs, PyObjectRef, PyResult, TypeProtocol};
|
||||
use crate::VirtualMachine;
|
||||
|
||||
fn re_match(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
// TODO:
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
*
|
||||
*/
|
||||
|
||||
use super::super::pyobject::{PyContext, PyObjectRef};
|
||||
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));
|
||||
|
||||
Loaded 100 of 110 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user