diff --git a/Cargo.lock b/Cargo.lock index 7e6c4dae1a..66bd5aae98 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -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", ] diff --git a/ast/Cargo.toml b/ast/Cargo.toml index 2b8cc2d723..f750b0f8d9 100644 --- a/ast/Cargo.toml +++ b/ast/Cargo.toml @@ -5,4 +5,4 @@ authors = ["RustPython Team"] edition = "2018" [dependencies] -num-bigint = "0.3" +num-bigint = { version = "0.3", default-features = false } diff --git a/ast/src/ast.rs b/ast/src/ast.rs index 43b04ff44e..46cbe0aea7 100644 --- a/ast/src/ast.rs +++ b/ast/src/ast.rs @@ -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)] diff --git a/ast/src/lib.rs b/ast/src/lib.rs index acc0e36214..d92bae3417 100644 --- a/ast/src/lib.rs +++ b/ast/src/lib.rs @@ -1,3 +1,7 @@ +#![no_std] + +extern crate alloc; + mod ast; mod location; diff --git a/ast/src/location.rs b/ast/src/location.rs index 324c2a33c2..3e9f4ee217 100644 --- a/ast/src/location.rs +++ b/ast/src/location.rs @@ -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)] diff --git a/bytecode/Cargo.toml b/bytecode/Cargo.toml index b01c6eacd3..04247553dc 100644 --- a/bytecode/Cargo.toml +++ b/bytecode/Cargo.toml @@ -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 } diff --git a/bytecode/src/lib.rs b/bytecode/src/lib.rs index 691bd507a8..3c231d17ee 100644 --- a/bytecode/src/lib.rs +++ b/bytecode/src/lib.rs @@ -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 { diff --git a/compiler/Cargo.toml b/compiler/Cargo.toml index 9baa8ff4d3..3c1032915d 100644 --- a/compiler/Cargo.toml +++ b/compiler/Cargo.toml @@ -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" } diff --git a/compiler/porcelain/Cargo.toml b/compiler/porcelain/Cargo.toml index e07c746c1a..171f64f8c1 100644 --- a/compiler/porcelain/Cargo.toml +++ b/compiler/porcelain/Cargo.toml @@ -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 = ".." } diff --git a/compiler/src/compile.rs b/compiler/src/compile.rs index 46e0e4c1e4..14d9b832c1 100644 --- a/compiler/src/compile.rs +++ b/compiler/src/compile.rs @@ -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 = Result; enum NameUsage { diff --git a/compiler/src/error.rs b/compiler/src/error.rs index f1fa58e5c0..c41772e4ee 100644 --- a/compiler/src/error.rs +++ b/compiler/src/error.rs @@ -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 {} diff --git a/compiler/src/lib.rs b/compiler/src/lib.rs index 3116547de3..f06dc6767c 100644 --- a/compiler/src/lib.rs +++ b/compiler/src/lib.rs @@ -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; diff --git a/compiler/src/mode.rs b/compiler/src/mode.rs index f926309aff..f28bfbd1f4 100644 --- a/compiler/src/mode.rs +++ b/compiler/src/mode.rs @@ -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 { 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""#) } } diff --git a/compiler/src/symboltable.rs b/compiler/src/symboltable.rs index 4f22b8df5a..e09aab93bf 100644 --- a/compiler/src/symboltable.rs +++ b/compiler/src/symboltable.rs @@ -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 { 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; mod stack { - use std::panic; - use std::ptr::NonNull; + use alloc::vec::Vec; + use core::ptr::NonNull; + pub struct StackStack { v: Vec>, } @@ -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 + 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, }); } diff --git a/parser/Cargo.toml b/parser/Cargo.toml index 2550555fd6..a1a6682728 100644 --- a/parser/Cargo.toml +++ b/parser/Cargo.toml @@ -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" diff --git a/parser/src/error.rs b/parser/src/error.rs index 3fee075ec6..616d0cce6c 100644 --- a/parser/src/error.rs +++ b/parser/src/error.rs @@ -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 for LalrpopError { } } +#[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() } } diff --git a/parser/src/fstring.rs b/parser/src/fstring.rs index b67f9e462d..23772c3b38 100644 --- a/parser/src/fstring.rs +++ b/parser/src/fstring.rs @@ -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() => { diff --git a/parser/src/function.rs b/parser/src/function.rs index 2ff18b44fd..bb8eb9ff51 100644 --- a/parser/src/function.rs +++ b/parser/src/function.rs @@ -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) -> Result { diff --git a/parser/src/lexer.rs b/parser/src/lexer.rs index 268be3863a..5a2e405a71 100644 --- a/parser/src/lexer.rs +++ b/parser/src/lexer.rs @@ -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), } } diff --git a/parser/src/lib.rs b/parser/src/lib.rs index 80030e61b9..0e697c18b7 100644 --- a/parser/src/lib.rs +++ b/parser/src/lib.rs @@ -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; diff --git a/parser/src/mode.rs b/parser/src/mode.rs index 7614aa82f3..92cf394e83 100644 --- a/parser/src/mode.rs +++ b/parser/src/mode.rs @@ -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 { 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""#) } } diff --git a/parser/src/parser.rs b/parser/src/parser.rs index a2659c4280..9d96975161 100644 --- a/parser/src/parser.rs +++ b/parser/src/parser.rs @@ -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 { diff --git a/parser/src/python.lalrpop b/parser/src/python.lalrpop index 4fdfdc2f32..fc1b50cecd 100644 --- a/parser/src/python.lalrpop +++ b/parser/src/python.lalrpop @@ -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 = { => ast::Program { - statements: Vec::from_iter(lines.into_iter().flatten()) + statements: lines.into_iter().flatten().collect(), }, }; diff --git a/parser/src/token.rs b/parser/src/token.rs index 316c34e48e..c7df437ff3 100644 --- a/parser/src/token.rs +++ b/parser/src/token.rs @@ -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)] diff --git a/vm/Cargo.toml b/vm/Cargo.toml index 2088b1f038..ca32f9bbb7 100644 --- a/vm/Cargo.toml +++ b/vm/Cargo.toml @@ -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"] diff --git a/vm/src/lib.rs b/vm/src/lib.rs index ad962df2b1..fc28b1eb5e 100644 --- a/vm/src/lib.rs +++ b/vm/src/lib.rs @@ -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]