Compare commits

...

6 Commits

Author SHA1 Message Date
Noah
a784d2f0f8 Add a std feature to vm 2021-01-14 12:48:54 -06:00
Noah
bf1e9832f7 Make compiler/porcelain no_std compatible 2021-01-14 12:48:54 -06:00
Noah
5f5d36cc74 Make parser no_std compatible 2021-01-14 12:48:52 -06:00
Noah
313c30c51b Make ast no_std compatible 2021-01-14 12:45:32 -06:00
Noah
d375710650 Make compiler no_std compatible 2021-01-14 12:45:32 -06:00
Noah
c49cc8f419 Make bytecode no_std compatible 2021-01-14 12:45:32 -06:00
26 changed files with 201 additions and 99 deletions

22
Cargo.lock generated
View File

@@ -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",
]

View File

@@ -5,4 +5,4 @@ authors = ["RustPython Team"]
edition = "2018"
[dependencies]
num-bigint = "0.3"
num-bigint = { version = "0.3", default-features = false }

View File

@@ -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)]

View File

@@ -1,3 +1,7 @@
#![no_std]
extern crate alloc;
mod ast;
mod location;

View File

@@ -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)]

View File

@@ -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 }

View File

@@ -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> {

View File

@@ -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" }

View File

@@ -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 = ".." }

View File

@@ -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 {

View File

@@ -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 {}

View File

@@ -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;

View File

@@ -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""#)
}
}

View File

@@ -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,
});
}

View File

@@ -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"

View File

@@ -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()
}
}

View File

@@ -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() => {

View File

@@ -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) => {

View File

@@ -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),
}
}

View File

@@ -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;

View File

@@ -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""#)
}
}

View File

@@ -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 {

View File

@@ -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(),
},
};

View File

@@ -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)]

View File

@@ -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"]

View File

@@ -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]