mirror of
https://github.com/RustPython/RustPython.git
synced 2026-06-02 19:39:49 +09:00
Compare commits
6 Commits
2025-10-13
...
no_std
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a784d2f0f8 | ||
|
|
bf1e9832f7 | ||
|
|
5f5d36cc74 | ||
|
|
313c30c51b | ||
|
|
d375710650 | ||
|
|
c49cc8f419 |
22
Cargo.lock
generated
22
Cargo.lock
generated
@@ -24,6 +24,12 @@ version = "1.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "aae1277d39aeec15cb388266ecc24b11c80469deae6067e17a1a7aa9e5c1f234"
|
||||
|
||||
[[package]]
|
||||
name = "ahash"
|
||||
version = "0.4.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "739f4a8db6605981345c5654f3a85b056ce52f37a39d34da03f25bf2151ea16e"
|
||||
|
||||
[[package]]
|
||||
name = "ahash"
|
||||
version = "0.6.2"
|
||||
@@ -876,6 +882,9 @@ name = "hashbrown"
|
||||
version = "0.9.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d7afe4a420e3fe79967a00898cc1f4db7c8a49a9333a29f8a4bd76a253d5cd04"
|
||||
dependencies = [
|
||||
"ahash 0.4.7",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hermit-abi"
|
||||
@@ -1875,7 +1884,7 @@ dependencies = [
|
||||
name = "rustpython-compiler-core"
|
||||
version = "0.1.2"
|
||||
dependencies = [
|
||||
"ahash",
|
||||
"ahash 0.6.2",
|
||||
"indexmap",
|
||||
"insta",
|
||||
"itertools",
|
||||
@@ -1885,6 +1894,7 @@ dependencies = [
|
||||
"rustpython-ast",
|
||||
"rustpython-bytecode",
|
||||
"rustpython-parser",
|
||||
"scopeguard",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1922,7 +1932,8 @@ dependencies = [
|
||||
name = "rustpython-parser"
|
||||
version = "0.1.2"
|
||||
dependencies = [
|
||||
"ahash",
|
||||
"ahash 0.6.2",
|
||||
"hashbrown",
|
||||
"lalrpop",
|
||||
"lalrpop-util",
|
||||
"log",
|
||||
@@ -1948,7 +1959,7 @@ name = "rustpython-vm"
|
||||
version = "0.1.2"
|
||||
dependencies = [
|
||||
"adler32",
|
||||
"ahash",
|
||||
"ahash 0.6.2",
|
||||
"atty",
|
||||
"base64",
|
||||
"bitflags",
|
||||
@@ -2233,13 +2244,12 @@ checksum = "ae524f056d7d770e174287294f562e95044c68e88dec909a00d2094805db9d75"
|
||||
|
||||
[[package]]
|
||||
name = "socket2"
|
||||
version = "0.3.17"
|
||||
version = "0.3.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2c29947abdee2a218277abeca306f25789c938e500ea5a9d4b12a5a504466902"
|
||||
checksum = "122e570113d28d773067fab24266b66753f6ea915758651696b6e35e49f88d6e"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"libc",
|
||||
"redox_syscall",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
|
||||
@@ -5,4 +5,4 @@ authors = ["RustPython Team"]
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
num-bigint = "0.3"
|
||||
num-bigint = { version = "0.3", default-features = false }
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
//! location of the node.
|
||||
|
||||
pub use crate::location::Location;
|
||||
use alloc::{boxed::Box, string::String, vec::Vec};
|
||||
use num_bigint::BigInt;
|
||||
|
||||
#[allow(clippy::large_enum_variant)]
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
#![no_std]
|
||||
|
||||
extern crate alloc;
|
||||
|
||||
mod ast;
|
||||
mod location;
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
//! Datatypes to support source location information.
|
||||
|
||||
use std::fmt;
|
||||
use core::fmt;
|
||||
|
||||
/// A location somewhere in the sourcecode.
|
||||
#[derive(Clone, Copy, Debug, Default, PartialEq)]
|
||||
|
||||
@@ -7,13 +7,16 @@ edition = "2018"
|
||||
repository = "https://github.com/RustPython/RustPython"
|
||||
license = "MIT"
|
||||
|
||||
[features]
|
||||
std = ["bstr/std", "itertools/use_std", "lz4_flex/std"]
|
||||
default = ["std"]
|
||||
|
||||
[dependencies]
|
||||
bincode = "1.1"
|
||||
bitflags = "1.1"
|
||||
lz4_flex = "0.7"
|
||||
num-bigint = { version = "0.3", features = ["serde"] }
|
||||
num-complex = { version = "0.3", features = ["serde"] }
|
||||
lz4_flex = { version = "0.7", default-features = false, features = ["safe-decode", "safe-encode"] }
|
||||
num-bigint = { version = "0.3", default-features = false, features = ["serde"] }
|
||||
num-complex = { version = "0.3", default-features = false, features = ["serde"] }
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
itertools = "0.9"
|
||||
bstr = "0.2"
|
||||
itertools = { version = "0.9", default-features = false }
|
||||
bstr = { version = "0.2", default-features = false }
|
||||
|
||||
@@ -3,15 +3,19 @@
|
||||
|
||||
#![doc(html_logo_url = "https://raw.githubusercontent.com/RustPython/RustPython/master/logo.png")]
|
||||
#![doc(html_root_url = "https://docs.rs/rustpython-bytecode/")]
|
||||
#![cfg_attr(not(feature = "std"), no_std)]
|
||||
|
||||
extern crate alloc;
|
||||
|
||||
use alloc::collections::BTreeSet;
|
||||
use alloc::{borrow::ToOwned, boxed::Box, string::String, vec::Vec};
|
||||
use bitflags::bitflags;
|
||||
use bstr::ByteSlice;
|
||||
use core::fmt;
|
||||
use itertools::Itertools;
|
||||
use num_bigint::BigInt;
|
||||
use num_complex::Complex64;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::collections::BTreeSet;
|
||||
use std::fmt;
|
||||
|
||||
/// Sourcecode location.
|
||||
#[derive(Clone, Copy, Debug, Default, PartialEq, Serialize, Deserialize)]
|
||||
@@ -722,6 +726,7 @@ impl fmt::Display for CodeDeserializeError {
|
||||
}
|
||||
}
|
||||
}
|
||||
#[cfg(feature = "std")]
|
||||
impl std::error::Error for CodeDeserializeError {}
|
||||
|
||||
impl CodeObject<ConstantData> {
|
||||
|
||||
@@ -7,15 +7,20 @@ repository = "https://github.com/RustPython/RustPython"
|
||||
license = "MIT"
|
||||
edition = "2018"
|
||||
|
||||
[features]
|
||||
std = ["rustpython-bytecode/std", "itertools/use_std"]
|
||||
default = ["std"]
|
||||
|
||||
[dependencies]
|
||||
indexmap = "1.0"
|
||||
itertools = "0.9"
|
||||
rustpython-bytecode = { path = "../bytecode", version = "0.1.1" }
|
||||
itertools = { version = "0.9", default-features = false }
|
||||
rustpython-bytecode = { path = "../bytecode", version = "0.1.1", default-features = false }
|
||||
rustpython-ast = { path = "../ast" }
|
||||
num-complex = { version = "0.3", features = ["serde"] }
|
||||
num-traits = "0.2"
|
||||
log = "0.4"
|
||||
ahash = "0.6"
|
||||
scopeguard = "1.1"
|
||||
|
||||
[dev-dependencies]
|
||||
rustpython-parser = { path = "../parser" }
|
||||
|
||||
@@ -5,6 +5,10 @@ description = "A usability wrapper around rustpython-parser and rustpython-compi
|
||||
authors = ["RustPython Team"]
|
||||
edition = "2018"
|
||||
|
||||
[features]
|
||||
std = ["rustpython-compiler-core/std", "rustpython-bytecode/std", "rustpython-parser/std"]
|
||||
default = ["std"]
|
||||
|
||||
[dependencies]
|
||||
thiserror = "1.0"
|
||||
rustpython-compiler-core = { path = ".." }
|
||||
|
||||
@@ -10,12 +10,15 @@ use crate::ir::{self, CodeInfo};
|
||||
pub use crate::mode::Mode;
|
||||
use crate::symboltable::{make_symbol_table, statements_to_symbol_table, SymbolScope, SymbolTable};
|
||||
use crate::IndexSet;
|
||||
use alloc::{borrow::ToOwned, boxed::Box, format, string::String, vec, vec::Vec};
|
||||
use itertools::Itertools;
|
||||
use num_complex::Complex64;
|
||||
use num_traits::ToPrimitive;
|
||||
use rustpython_ast as ast;
|
||||
use rustpython_bytecode::{self as bytecode, CodeObject, ConstantData, Instruction};
|
||||
|
||||
pub use crate::mode::Mode;
|
||||
|
||||
type CompileResult<T> = Result<T, CompileError>;
|
||||
|
||||
enum NameUsage {
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
use rustpython_ast::Location;
|
||||
|
||||
use alloc::string::String;
|
||||
use core::fmt;
|
||||
#[cfg(feature = "std")]
|
||||
use std::error::Error;
|
||||
use std::fmt;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct CompileError {
|
||||
@@ -78,6 +80,7 @@ impl fmt::Display for CompileErrorType {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl Error for CompileErrorType {}
|
||||
|
||||
impl fmt::Display for CompileError {
|
||||
@@ -86,8 +89,5 @@ impl fmt::Display for CompileError {
|
||||
}
|
||||
}
|
||||
|
||||
impl Error for CompileError {
|
||||
fn source(&self) -> Option<&(dyn Error + 'static)> {
|
||||
None
|
||||
}
|
||||
}
|
||||
#[cfg(feature = "std")]
|
||||
impl Error for CompileError {}
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
//! Compile a Python AST or source code into bytecode consumable by RustPython.
|
||||
#![doc(html_logo_url = "https://raw.githubusercontent.com/RustPython/RustPython/master/logo.png")]
|
||||
#![doc(html_root_url = "https://docs.rs/rustpython-compiler/")]
|
||||
#![cfg_attr(not(feature = "std"), no_std)]
|
||||
|
||||
extern crate alloc;
|
||||
|
||||
#[macro_use]
|
||||
extern crate log;
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
use core::fmt;
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub enum Mode {
|
||||
Exec,
|
||||
@@ -5,7 +7,7 @@ pub enum Mode {
|
||||
Single,
|
||||
}
|
||||
|
||||
impl std::str::FromStr for Mode {
|
||||
impl core::str::FromStr for Mode {
|
||||
type Err = ModeParseError;
|
||||
fn from_str(s: &str) -> Result<Self, ModeParseError> {
|
||||
match s {
|
||||
@@ -22,8 +24,8 @@ pub struct ModeParseError {
|
||||
_priv: (),
|
||||
}
|
||||
|
||||
impl std::fmt::Display for ModeParseError {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
impl fmt::Display for ModeParseError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, r#"mode should be "exec", "eval", or "single""#)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,8 +9,9 @@ Inspirational file: https://github.com/python/cpython/blob/master/Python/symtabl
|
||||
|
||||
use crate::error::{CompileError, CompileErrorType};
|
||||
use crate::IndexMap;
|
||||
use alloc::{borrow::ToOwned, format, string::String, vec, vec::Vec};
|
||||
use core::fmt;
|
||||
use rustpython_ast::{self as ast, Location};
|
||||
use std::fmt;
|
||||
|
||||
pub fn make_symbol_table(program: &ast::Program) -> Result<SymbolTable, SymbolTableError> {
|
||||
let mut builder = SymbolTableBuilder::default();
|
||||
@@ -187,8 +188,8 @@ impl SymbolTable {
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Debug for SymbolTable {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
impl fmt::Debug for SymbolTable {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"SymbolTable({:?} symbols, {:?} sub scopes)",
|
||||
@@ -209,8 +210,9 @@ fn analyze_symbol_table(symbol_table: &mut SymbolTable) -> SymbolTableResult {
|
||||
type SymbolMap = IndexMap<String, Symbol>;
|
||||
|
||||
mod stack {
|
||||
use std::panic;
|
||||
use std::ptr::NonNull;
|
||||
use alloc::vec::Vec;
|
||||
use core::ptr::NonNull;
|
||||
|
||||
pub struct StackStack<T> {
|
||||
v: Vec<NonNull<T>>,
|
||||
}
|
||||
@@ -227,9 +229,10 @@ mod stack {
|
||||
F: FnOnce(&mut Self) -> R,
|
||||
{
|
||||
self.v.push(x.into());
|
||||
let res = panic::catch_unwind(panic::AssertUnwindSafe(|| f(self)));
|
||||
self.v.pop();
|
||||
res.unwrap_or_else(|x| panic::resume_unwind(x))
|
||||
let mut this = scopeguard::guard(self, |this| {
|
||||
this.v.pop();
|
||||
});
|
||||
f(&mut this)
|
||||
}
|
||||
|
||||
pub fn iter(&self) -> impl Iterator<Item = &T> + DoubleEndedIterator + '_ {
|
||||
@@ -273,7 +276,7 @@ struct SymbolTableAnalyzer {
|
||||
|
||||
impl SymbolTableAnalyzer {
|
||||
fn analyze_symbol_table(&mut self, symbol_table: &mut SymbolTable) -> SymbolTableResult {
|
||||
let symbols = std::mem::take(&mut symbol_table.symbols);
|
||||
let symbols = core::mem::take(&mut symbol_table.symbols);
|
||||
let sub_tables = &mut *symbol_table.sub_tables;
|
||||
|
||||
let mut info = (symbols, symbol_table.typ);
|
||||
@@ -469,7 +472,7 @@ impl SymbolTableAnalyzer {
|
||||
SymbolTableType::Class => {
|
||||
// named expressions are forbidden in comprehensions on class scope
|
||||
return Err(SymbolTableError {
|
||||
error: "assignment expression within a comprehension cannot be used in a class body".to_string(),
|
||||
error: "assignment expression within a comprehension cannot be used in a class body".to_owned(),
|
||||
// TODO: accurate location info, somehow
|
||||
location: Location::default(),
|
||||
});
|
||||
@@ -999,7 +1002,7 @@ impl SymbolTableBuilder {
|
||||
// comprehension iterator definitions
|
||||
if let ExpressionContext::IterDefinitionExp = context {
|
||||
return Err(SymbolTableError {
|
||||
error: "assignment expression cannot be used in a comprehension iterable expression".to_string(),
|
||||
error: "assignment expression cannot be used in a comprehension iterable expression".to_owned(),
|
||||
// TODO: accurate location info, somehow
|
||||
location: Location::default(),
|
||||
});
|
||||
@@ -1218,7 +1221,7 @@ impl SymbolTableBuilder {
|
||||
return Err(SymbolTableError {
|
||||
error:
|
||||
"assignment expression cannot be used in a comprehension iterable expression"
|
||||
.to_string(),
|
||||
.to_owned(),
|
||||
location,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -8,17 +8,22 @@ repository = "https://github.com/RustPython/RustPython"
|
||||
license = "MIT"
|
||||
edition = "2018"
|
||||
|
||||
[features]
|
||||
std = []
|
||||
default = ["std", "lalrpop-util/std", "num-bigint/std"]
|
||||
|
||||
[build-dependencies]
|
||||
lalrpop = "0.19"
|
||||
lalrpop = "0.19.4"
|
||||
|
||||
[dependencies]
|
||||
rustpython-ast = { path = "../ast" }
|
||||
lalrpop-util = "0.19.1"
|
||||
lalrpop-util = { version = "0.19.4", default-features = false }
|
||||
log = "0.4.1"
|
||||
num-bigint = "0.3"
|
||||
num-traits = "0.2"
|
||||
num-bigint = { version = "0.3", default-features = false }
|
||||
num-traits = { version = "0.2", default-features = false }
|
||||
unic-emoji-char = "0.9"
|
||||
unic-ucd-ident = "0.9"
|
||||
unicode_names2 = "0.4"
|
||||
phf = { version = "0.8", features = ["macros"] }
|
||||
ahash = "0.6"
|
||||
hashbrown = "0.9"
|
||||
|
||||
@@ -5,8 +5,10 @@ use lalrpop_util::ParseError as LalrpopError;
|
||||
use crate::ast::Location;
|
||||
use crate::token::Tok;
|
||||
|
||||
use alloc::{boxed::Box, string::String};
|
||||
use core::fmt;
|
||||
#[cfg(feature = "std")]
|
||||
use std::error::Error;
|
||||
use std::fmt;
|
||||
|
||||
/// Represents an error during lexical scanning.
|
||||
#[derive(Debug, PartialEq)]
|
||||
@@ -70,6 +72,16 @@ impl fmt::Display for LexicalErrorType {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl Error for LexicalErrorType {
|
||||
fn source(&self) -> Option<&(dyn Error + 'static)> {
|
||||
match self {
|
||||
LexicalErrorType::FStringError(e) => Some(e),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: consolidate these with ParseError
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub struct FStringError {
|
||||
@@ -119,6 +131,16 @@ impl From<FStringError> for LalrpopError<Location, Tok, LexicalError> {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl Error for FStringErrorType {
|
||||
fn source(&self) -> Option<&(dyn Error + 'static)> {
|
||||
match self {
|
||||
FStringErrorType::InvalidExpression(e) => Some(e.as_ref()),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Represents an error during parsing
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub struct ParseError {
|
||||
@@ -204,14 +226,22 @@ impl fmt::Display for ParseErrorType {
|
||||
}
|
||||
}
|
||||
|
||||
impl Error for ParseErrorType {}
|
||||
#[cfg(feature = "std")]
|
||||
impl Error for ParseErrorType {
|
||||
fn source(&self) -> Option<&(dyn Error + 'static)> {
|
||||
match self {
|
||||
ParseErrorType::Lexical(e) => Some(e),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ParseErrorType {
|
||||
pub fn is_indentation_error(&self) -> bool {
|
||||
match self {
|
||||
ParseErrorType::Lexical(LexicalErrorType::IndentationError) => true,
|
||||
ParseErrorType::UnrecognizedToken(token, expected) => {
|
||||
*token == Tok::Indent || expected.clone() == Some("Indent".to_owned())
|
||||
*token == Tok::Indent || expected.as_ref().map_or(false, |s| s == "Indent")
|
||||
}
|
||||
_ => false,
|
||||
}
|
||||
@@ -225,15 +255,16 @@ impl ParseErrorType {
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::Deref for ParseError {
|
||||
impl core::ops::Deref for ParseError {
|
||||
type Target = ParseErrorType;
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.error
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl Error for ParseError {
|
||||
fn source(&self) -> Option<&(dyn Error + 'static)> {
|
||||
None
|
||||
self.error.source()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
use std::iter;
|
||||
use std::mem;
|
||||
use std::str;
|
||||
use alloc::{borrow::ToOwned, boxed::Box, format, string::String, vec, vec::Vec};
|
||||
use core::{iter, mem, str};
|
||||
|
||||
use crate::ast::{ConversionFlag, Expression, Location, StringGroup};
|
||||
use crate::error::{FStringError, FStringErrorType, ParseError};
|
||||
@@ -81,7 +80,7 @@ impl<'a> FStringParser<'a> {
|
||||
// match a python 3.8 self documenting expression
|
||||
// format '{' PYTHON_EXPRESSION '=' FORMAT_SPECIFIER? '}'
|
||||
'=' if self.chars.peek() != Some(&'=') && delims.is_empty() => {
|
||||
pred_expression_text = expression.to_string(); // safe expression before = to print it
|
||||
pred_expression_text = expression.to_owned(); // safe expression before = to print it
|
||||
}
|
||||
|
||||
':' if delims.is_empty() => {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use ahash::RandomState;
|
||||
use std::collections::HashSet;
|
||||
use alloc::{string::String, vec, vec::Vec};
|
||||
use hashbrown::HashSet;
|
||||
|
||||
use crate::ast;
|
||||
use crate::error::{LexicalError, LexicalErrorType};
|
||||
@@ -46,7 +46,8 @@ pub fn parse_args(func_args: Vec<FunctionArgument>) -> Result<ast::ArgumentList,
|
||||
let mut args = vec![];
|
||||
let mut keywords = vec![];
|
||||
|
||||
let mut keyword_names = HashSet::with_capacity_and_hasher(func_args.len(), RandomState::new());
|
||||
let mut keyword_names =
|
||||
HashSet::with_capacity_and_hasher(func_args.len(), ahash::RandomState::default());
|
||||
for (name, value) in func_args {
|
||||
match name {
|
||||
Some(n) => {
|
||||
|
||||
@@ -5,12 +5,19 @@
|
||||
pub use super::token::Tok;
|
||||
use crate::ast::Location;
|
||||
use crate::error::{LexicalError, LexicalErrorType};
|
||||
use alloc::{
|
||||
borrow::ToOwned,
|
||||
format,
|
||||
string::{String, ToString},
|
||||
vec,
|
||||
vec::Vec,
|
||||
};
|
||||
use core::char;
|
||||
use core::cmp::Ordering;
|
||||
use core::str::FromStr;
|
||||
use num_bigint::BigInt;
|
||||
use num_traits::identities::Zero;
|
||||
use num_traits::Num;
|
||||
use std::char;
|
||||
use std::cmp::Ordering;
|
||||
use std::str::FromStr;
|
||||
use unic_emoji_char::is_emoji_presentation;
|
||||
use unic_ucd_ident::{is_xid_continue, is_xid_start};
|
||||
|
||||
@@ -436,8 +443,8 @@ where
|
||||
}
|
||||
}
|
||||
match p {
|
||||
0xD800..=0xDFFF => Ok(std::char::REPLACEMENT_CHARACTER),
|
||||
_ => std::char::from_u32(p).ok_or(unicode_error),
|
||||
0xD800..=0xDFFF => Ok(char::REPLACEMENT_CHARACTER),
|
||||
_ => char::from_u32(p).ok_or(unicode_error),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -17,6 +17,13 @@
|
||||
|
||||
#![doc(html_logo_url = "https://raw.githubusercontent.com/RustPython/RustPython/master/logo.png")]
|
||||
#![doc(html_root_url = "https://docs.rs/rustpython-parser/")]
|
||||
#![cfg_attr(not(feature = "std"), no_std)]
|
||||
|
||||
extern crate alloc;
|
||||
|
||||
// hack to get around lalrpop hardcoding ::std::* paths
|
||||
#[cfg(not(feature = "std"))]
|
||||
extern crate self as std;
|
||||
|
||||
#[macro_use]
|
||||
extern crate log;
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
use core::fmt;
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub enum Mode {
|
||||
Program,
|
||||
Statement,
|
||||
}
|
||||
|
||||
impl std::str::FromStr for Mode {
|
||||
impl core::str::FromStr for Mode {
|
||||
type Err = ModeParseError;
|
||||
fn from_str(s: &str) -> Result<Self, ModeParseError> {
|
||||
match s {
|
||||
@@ -20,8 +22,8 @@ pub struct ModeParseError {
|
||||
_priv: (),
|
||||
}
|
||||
|
||||
impl std::fmt::Display for ModeParseError {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
impl fmt::Display for ModeParseError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, r#"mode should be "exec", "eval", or "single""#)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,8 @@
|
||||
//! parse a whole program, a single statement, or a single
|
||||
//! expression.
|
||||
|
||||
use std::iter;
|
||||
use alloc::vec::Vec;
|
||||
use core::iter;
|
||||
|
||||
use crate::ast;
|
||||
use crate::error::ParseError;
|
||||
@@ -106,6 +107,7 @@ mod tests {
|
||||
use super::parse_expression;
|
||||
use super::parse_program;
|
||||
use super::parse_statement;
|
||||
use alloc::borrow::ToOwned;
|
||||
use num_bigint::BigInt;
|
||||
|
||||
fn mk_ident(name: &str, row: usize, col: usize) -> ast::Expression {
|
||||
@@ -136,7 +138,7 @@ mod tests {
|
||||
custom: (),
|
||||
node: ast::ExpressionType::String {
|
||||
value: ast::StringGroup::Constant {
|
||||
value: String::from(value),
|
||||
value: value.to_owned(),
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -158,8 +160,8 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_parse_print_hello() {
|
||||
let source = String::from("print('Hello world')");
|
||||
let parse_ast = parse_program(&source).unwrap();
|
||||
let source = "print('Hello world')";
|
||||
let parse_ast = parse_program(source).unwrap();
|
||||
assert_eq!(
|
||||
parse_ast,
|
||||
ast::Program {
|
||||
@@ -184,8 +186,8 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_parse_print_2() {
|
||||
let source = String::from("print('Hello world', 2)");
|
||||
let parse_ast = parse_program(&source).unwrap();
|
||||
let source = "print('Hello world', 2)";
|
||||
let parse_ast = parse_program(source).unwrap();
|
||||
assert_eq!(
|
||||
parse_ast,
|
||||
ast::Program {
|
||||
@@ -210,8 +212,8 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_parse_kwargs() {
|
||||
let source = String::from("my_func('positional', keyword=2)");
|
||||
let parse_ast = parse_program(&source).unwrap();
|
||||
let source = "my_func('positional', keyword=2)";
|
||||
let parse_ast = parse_program(source).unwrap();
|
||||
assert_eq!(
|
||||
parse_ast,
|
||||
ast::Program {
|
||||
@@ -239,8 +241,8 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_parse_if_elif_else() {
|
||||
let source = String::from("if 1: 10\nelif 2: 20\nelse: 30");
|
||||
let parse_ast = parse_statement(&source).unwrap();
|
||||
let source = "if 1: 10\nelif 2: 20\nelse: 30";
|
||||
let parse_ast = parse_statement(source).unwrap();
|
||||
assert_eq!(
|
||||
parse_ast,
|
||||
vec![ast::Statement {
|
||||
@@ -265,8 +267,8 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_parse_lambda() {
|
||||
let source = String::from("lambda x, y: x * y"); // lambda(x, y): x * y");
|
||||
let parse_ast = parse_statement(&source);
|
||||
let source = "lambda x, y: x * y"; // lambda(x, y): x * y");
|
||||
let parse_ast = parse_statement(source);
|
||||
assert_eq!(
|
||||
parse_ast,
|
||||
Ok(vec![as_statement(ast::Expression {
|
||||
@@ -278,12 +280,12 @@ mod tests {
|
||||
args: vec![
|
||||
ast::Parameter {
|
||||
location: ast::Location::new(1, 8),
|
||||
arg: String::from("x"),
|
||||
arg: "x".to_owned(),
|
||||
annotation: None,
|
||||
},
|
||||
ast::Parameter {
|
||||
location: ast::Location::new(1, 11),
|
||||
arg: String::from("y"),
|
||||
arg: "y".to_owned(),
|
||||
annotation: None,
|
||||
}
|
||||
],
|
||||
@@ -309,10 +311,10 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_parse_tuples() {
|
||||
let source = String::from("a, b = 4, 5");
|
||||
let source = "a, b = 4, 5";
|
||||
|
||||
assert_eq!(
|
||||
parse_statement(&source),
|
||||
parse_statement(source),
|
||||
Ok(vec![ast::Statement {
|
||||
location: ast::Location::new(1, 1),
|
||||
custom: (),
|
||||
@@ -338,16 +340,19 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_parse_class() {
|
||||
let source = String::from(
|
||||
"class Foo(A, B):\n def __init__(self):\n pass\n def method_with_default(self, arg='default'):\n pass",
|
||||
);
|
||||
let source = "\
|
||||
class Foo(A, B):
|
||||
def __init__(self):
|
||||
pass
|
||||
def method_with_default(self, arg='default'):
|
||||
pass";
|
||||
assert_eq!(
|
||||
parse_statement(&source),
|
||||
parse_statement(source),
|
||||
Ok(vec![ast::Statement {
|
||||
location: ast::Location::new(1, 1),
|
||||
custom: (),
|
||||
node: ast::StatementType::ClassDef {
|
||||
name: String::from("Foo"),
|
||||
name: "Foo".to_owned(),
|
||||
bases: vec![mk_ident("A", 1, 11), mk_ident("B", 1, 14)],
|
||||
keywords: vec![],
|
||||
body: vec![
|
||||
@@ -356,12 +361,12 @@ mod tests {
|
||||
custom: (),
|
||||
node: ast::StatementType::FunctionDef {
|
||||
is_async: false,
|
||||
name: String::from("__init__"),
|
||||
name: "__init__".to_owned(),
|
||||
args: Box::new(ast::Parameters {
|
||||
posonlyargs_count: 0,
|
||||
args: vec![ast::Parameter {
|
||||
location: ast::Location::new(2, 15),
|
||||
arg: String::from("self"),
|
||||
arg: "self".to_owned(),
|
||||
annotation: None,
|
||||
}],
|
||||
kwonlyargs: vec![],
|
||||
@@ -384,18 +389,18 @@ mod tests {
|
||||
custom: (),
|
||||
node: ast::StatementType::FunctionDef {
|
||||
is_async: false,
|
||||
name: String::from("method_with_default"),
|
||||
name: "method_with_default".to_owned(),
|
||||
args: Box::new(ast::Parameters {
|
||||
posonlyargs_count: 0,
|
||||
args: vec![
|
||||
ast::Parameter {
|
||||
location: ast::Location::new(4, 26),
|
||||
arg: String::from("self"),
|
||||
arg: "self".to_owned(),
|
||||
annotation: None,
|
||||
},
|
||||
ast::Parameter {
|
||||
location: ast::Location::new(4, 32),
|
||||
arg: String::from("arg"),
|
||||
arg: "arg".to_owned(),
|
||||
annotation: None,
|
||||
}
|
||||
],
|
||||
@@ -423,8 +428,8 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_parse_dict_comprehension() {
|
||||
let source = String::from("{x1: x2 for y in z}");
|
||||
let parse_ast = parse_expression(&source).unwrap();
|
||||
let source = "{x1: x2 for y in z}";
|
||||
let parse_ast = parse_expression(source).unwrap();
|
||||
assert_eq!(
|
||||
parse_ast,
|
||||
ast::Expression {
|
||||
@@ -449,8 +454,8 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_parse_list_comprehension() {
|
||||
let source = String::from("[x for y in z]");
|
||||
let parse_ast = parse_expression(&source).unwrap();
|
||||
let source = "[x for y in z]";
|
||||
let parse_ast = parse_expression(source).unwrap();
|
||||
assert_eq!(
|
||||
parse_ast,
|
||||
ast::Expression {
|
||||
@@ -474,8 +479,8 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_parse_double_list_comprehension() {
|
||||
let source = String::from("[x for y, y2 in z for a in b if a < 5 if a > 10]");
|
||||
let parse_ast = parse_expression(&source).unwrap();
|
||||
let source = "[x for y, y2 in z for a in b if a < 5 if a > 10]";
|
||||
let parse_ast = parse_expression(source).unwrap();
|
||||
assert_eq!(
|
||||
parse_ast,
|
||||
ast::Expression {
|
||||
|
||||
@@ -3,13 +3,12 @@
|
||||
// See also: file:///usr/share/doc/python/html/reference/compound_stmts.html#function-definitions
|
||||
// See also: https://greentreesnakes.readthedocs.io/en/latest/nodes.html#keyword
|
||||
|
||||
use std::iter::FromIterator;
|
||||
|
||||
use crate::ast;
|
||||
use crate::fstring::parse_located_fstring;
|
||||
use crate::function::{parse_args, parse_params};
|
||||
use crate::error::LexicalError;
|
||||
use crate::lexer;
|
||||
use alloc::{boxed::Box, string::{String, ToString}, vec, vec::Vec};
|
||||
|
||||
use num_bigint::BigInt;
|
||||
|
||||
@@ -26,7 +25,7 @@ pub Top: ast::Top = {
|
||||
|
||||
Program: ast::Program = {
|
||||
<lines:FileLine*> => ast::Program {
|
||||
statements: Vec::from_iter(lines.into_iter().flatten())
|
||||
statements: lines.into_iter().flatten().collect(),
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
//! Different token definitions.
|
||||
//! Loosely based on token.h from CPython source:
|
||||
use alloc::{string::String, vec::Vec};
|
||||
use core::fmt::{self, Write};
|
||||
use num_bigint::BigInt;
|
||||
use std::fmt::{self, Write};
|
||||
|
||||
/// Python source code can be tokenized in a sequence of these tokens.
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
|
||||
@@ -9,13 +9,14 @@ edition = "2018"
|
||||
include = ["src/**/*.rs", "Cargo.toml", "build.rs", "Lib/**/*.py"]
|
||||
|
||||
[features]
|
||||
default = ["compile-parse", "threading"]
|
||||
default = ["compile-parse", "threading", "std"]
|
||||
vm-tracing-logging = []
|
||||
flame-it = ["flame", "flamer"]
|
||||
freeze-stdlib = ["rustpython-pylib"]
|
||||
jit = ["rustpython-jit"]
|
||||
threading = ["rustpython-common/threading"]
|
||||
compile-parse = ["rustpython-parser", "rustpython-compiler"]
|
||||
std = ["rustpython-compiler/std"] # enables compiler-core/std, parser/std, etc
|
||||
|
||||
ssl = ["openssl", "openssl-sys", "openssl-probe"]
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#![allow(clippy::module_inception)]
|
||||
#![doc(html_logo_url = "https://raw.githubusercontent.com/RustPython/RustPython/master/logo.png")]
|
||||
#![doc(html_root_url = "https://docs.rs/rustpython-vm/")]
|
||||
#![cfg_attr(not(feature = "std"), no_std)]
|
||||
|
||||
#[cfg(feature = "flame-it")]
|
||||
#[macro_use]
|
||||
|
||||
Reference in New Issue
Block a user