mirror of
https://github.com/RustPython/RustPython.git
synced 2026-10-29 03:04:38 +08:00
Implement new features for updated python asdl
This commit is contained in:
1 parent
0d334a9b0e
commit
53b344866f
29 files changed
+182
-156
No files matched your search
Generated
+1
@@ -1723,6 +1723,7 @@ name = "rustpython-ast"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"num-bigint",
|
||||
"rustpython-bytecode",
|
||||
"rustpython-common",
|
||||
]
|
||||
|
||||
|
||||
@@ -13,3 +13,4 @@ unparse = ["rustpython-common"]
|
||||
[dependencies]
|
||||
num-bigint = "0.4.3"
|
||||
rustpython-common = { path = "../common", optional = true }
|
||||
rustpython-bytecode = { path = "../bytecode"}
|
||||
+1
-29
@@ -1,4 +1,5 @@
|
||||
use num_bigint::BigInt;
|
||||
pub use rustpython_bytecode::ConversionFlag;
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub enum Constant {
|
||||
@@ -70,35 +71,6 @@ impl std::fmt::Display for Constant {
|
||||
}
|
||||
}
|
||||
|
||||
/// Transforms a value prior to formatting it.
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||
#[repr(usize)]
|
||||
pub enum ConversionFlag {
|
||||
/// Converts by calling `str(<value>)`.
|
||||
Str = b's' as usize,
|
||||
/// Converts by calling `ascii(<value>)`.
|
||||
Ascii = b'a' as usize,
|
||||
/// Converts by calling `repr(<value>)`.
|
||||
Repr = b'r' as usize,
|
||||
}
|
||||
|
||||
impl ConversionFlag {
|
||||
pub fn try_from_u32(b: usize) -> Option<Self> {
|
||||
match b.try_into().ok()? {
|
||||
b's' => Some(Self::Str),
|
||||
b'a' => Some(Self::Ascii),
|
||||
b'r' => Some(Self::Repr),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<usize> for ConversionFlag {
|
||||
fn from(b: usize) -> Self {
|
||||
Self::try_from_u32(b).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "constant-optimization")]
|
||||
#[non_exhaustive]
|
||||
#[derive(Default)]
|
||||
|
||||
@@ -63,10 +63,4 @@ macro_rules! simple_fold {
|
||||
};
|
||||
}
|
||||
|
||||
simple_fold!(
|
||||
usize,
|
||||
String,
|
||||
bool,
|
||||
constant::Constant,
|
||||
constant::ConversionFlag
|
||||
);
|
||||
simple_fold!(usize, String, bool, constant::Constant);
|
||||
+10
-9
@@ -155,6 +155,7 @@ impl<'a> Unparser<'a> {
|
||||
write!(self, "{}: {}", *k, *v)?;
|
||||
}
|
||||
for d in unpacked {
|
||||
self.p_delim(&mut first, ", ")?;
|
||||
write!(self, "**{}", *d)?;
|
||||
}
|
||||
self.p("}")?;
|
||||
@@ -281,7 +282,7 @@ impl<'a> Unparser<'a> {
|
||||
value,
|
||||
conversion,
|
||||
format_spec,
|
||||
} => self.unparse_formatted(value, (*conversion).into(), format_spec.as_deref())?,
|
||||
} => self.unparse_formatted(value, *conversion, format_spec.as_deref())?,
|
||||
ExprKind::JoinedStr { values } => self.unparse_joinedstr(values, false)?,
|
||||
ExprKind::Constant { value, kind } => {
|
||||
if let Some(kind) = kind {
|
||||
@@ -445,7 +446,7 @@ impl<'a> Unparser<'a> {
|
||||
fn unparse_formatted<U>(
|
||||
&mut self,
|
||||
val: &Expr<U>,
|
||||
conversion: ConversionFlag,
|
||||
conversion: usize,
|
||||
spec: Option<&Expr<U>>,
|
||||
) -> fmt::Result {
|
||||
let buffered = to_string_fmt(|f| Unparser::new(f).unparse_expr(val, precedence::TEST + 1));
|
||||
@@ -459,12 +460,12 @@ impl<'a> Unparser<'a> {
|
||||
self.p(&buffered)?;
|
||||
drop(buffered);
|
||||
|
||||
let flag = match conversion {
|
||||
ConversionFlag::Str => "!s",
|
||||
ConversionFlag::Ascii => "!a",
|
||||
ConversionFlag::Repr => "!r",
|
||||
};
|
||||
self.p(flag)?;
|
||||
if conversion != ConversionFlag::None as usize {
|
||||
self.p("!")?;
|
||||
let buf = &[conversion as u8];
|
||||
let c = std::str::from_utf8(buf).unwrap();
|
||||
self.p(c)?;
|
||||
}
|
||||
|
||||
if let Some(spec) = spec {
|
||||
self.p(":")?;
|
||||
@@ -490,7 +491,7 @@ impl<'a> Unparser<'a> {
|
||||
value,
|
||||
conversion,
|
||||
format_spec,
|
||||
} => self.unparse_formatted(value, (*conversion).into(), format_spec.as_deref()),
|
||||
} => self.unparse_formatted(value, *conversion, format_spec.as_deref()),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
+19
-4
@@ -159,15 +159,30 @@ impl fmt::Display for Label {
|
||||
|
||||
/// Transforms a value prior to formatting it.
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[repr(u8)]
|
||||
pub enum ConversionFlag {
|
||||
/// No conversion
|
||||
None,
|
||||
None = 0,
|
||||
/// Converts by calling `str(<value>)`.
|
||||
Str,
|
||||
Str = b's',
|
||||
/// Converts by calling `ascii(<value>)`.
|
||||
Ascii,
|
||||
Ascii = b'a',
|
||||
/// Converts by calling `repr(<value>)`.
|
||||
Repr,
|
||||
Repr = b'r',
|
||||
}
|
||||
|
||||
impl TryFrom<usize> for ConversionFlag {
|
||||
type Error = usize;
|
||||
fn try_from(b: usize) -> Result<Self, Self::Error> {
|
||||
let b = b.try_into().map_err(|_| b)?;
|
||||
match b {
|
||||
0 => Ok(Self::None),
|
||||
b's' => Ok(Self::Str),
|
||||
b'a' => Ok(Self::Ascii),
|
||||
b'r' => Ok(Self::Repr),
|
||||
b => Err(b as usize),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// The kind of Raise that occurred.
|
||||
|
||||
+28
-30
@@ -680,6 +680,7 @@ impl Compiler {
|
||||
orelse,
|
||||
..
|
||||
} => self.compile_for(target, iter, body, orelse, true)?,
|
||||
Match { subject, cases } => self.compile_match(subject, cases)?,
|
||||
Raise { exc, cause } => {
|
||||
let kind = match exc {
|
||||
Some(value) => {
|
||||
@@ -881,17 +882,19 @@ impl Compiler {
|
||||
});
|
||||
}
|
||||
|
||||
let mut num_kw_only_defaults = 0;
|
||||
for (kw, default) in args.kwonlyargs.iter().zip(&args.kw_defaults) {
|
||||
self.emit_constant(ConstantData::Str {
|
||||
value: kw.node.arg.clone(),
|
||||
});
|
||||
self.compile_expression(default)?;
|
||||
num_kw_only_defaults += 1;
|
||||
}
|
||||
if num_kw_only_defaults > 0 {
|
||||
if !args.kw_defaults.is_empty() {
|
||||
let required_kw_count = args.kwonlyargs.len().saturating_sub(args.kw_defaults.len());
|
||||
for (kw, default) in args.kwonlyargs[required_kw_count..]
|
||||
.iter()
|
||||
.zip(&args.kw_defaults)
|
||||
{
|
||||
self.emit_constant(ConstantData::Str {
|
||||
value: kw.node.arg.clone(),
|
||||
});
|
||||
self.compile_expression(default)?;
|
||||
}
|
||||
self.emit(Instruction::BuildMap {
|
||||
size: num_kw_only_defaults,
|
||||
size: args.kw_defaults.len() as u32,
|
||||
unpack: false,
|
||||
for_call: false,
|
||||
});
|
||||
@@ -901,7 +904,7 @@ impl Compiler {
|
||||
if have_defaults {
|
||||
funcflags |= bytecode::MakeFunctionFlags::DEFAULTS;
|
||||
}
|
||||
if num_kw_only_defaults > 0 {
|
||||
if !args.kw_defaults.is_empty() {
|
||||
funcflags |= bytecode::MakeFunctionFlags::KW_ONLY_DEFAULTS;
|
||||
}
|
||||
|
||||
@@ -1519,6 +1522,16 @@ impl Compiler {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn compile_match(
|
||||
&mut self,
|
||||
subject: &ast::Expr,
|
||||
cases: &[ast::MatchCase],
|
||||
) -> CompileResult<()> {
|
||||
eprintln!("match subject: {subject:?}");
|
||||
eprintln!("match cases: {cases:?}");
|
||||
Err(self.error(CompileErrorType::NotImplementedYet))
|
||||
}
|
||||
|
||||
fn compile_chained_comparison(
|
||||
&mut self,
|
||||
left: &ast::Expr,
|
||||
@@ -1928,11 +1941,7 @@ impl Compiler {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn compile_dict(
|
||||
&mut self,
|
||||
keys: &[ast::Expr],
|
||||
values: &[ast::Expr],
|
||||
) -> CompileResult<()> {
|
||||
fn compile_dict(&mut self, keys: &[ast::Expr], values: &[ast::Expr]) -> CompileResult<()> {
|
||||
let mut size = 0;
|
||||
|
||||
let (packed_values, unpacked_values) = values.split_at(keys.len());
|
||||
@@ -2099,7 +2108,7 @@ impl Compiler {
|
||||
};
|
||||
self.compile_expression(value)?;
|
||||
self.emit(Instruction::FormatValue {
|
||||
conversion: compile_conversion_flag(*conversion),
|
||||
conversion: (*conversion).try_into().expect("invalid conversion flag"),
|
||||
});
|
||||
}
|
||||
Name { id, .. } => self.load_name(id)?,
|
||||
@@ -2454,7 +2463,7 @@ impl Compiler {
|
||||
|
||||
let mut loop_labels = vec![];
|
||||
for generator in generators {
|
||||
if generator.is_async {
|
||||
if generator.is_async > 0 {
|
||||
unimplemented!("async for comprehensions");
|
||||
}
|
||||
|
||||
@@ -2543,7 +2552,7 @@ impl Compiler {
|
||||
return Err(self.error(CompileErrorType::InvalidFuturePlacement));
|
||||
}
|
||||
for feature in features {
|
||||
match &*feature.name {
|
||||
match &*feature.node.name {
|
||||
// Python 3 features; we've already implemented them by default
|
||||
"nested_scopes" | "generators" | "division" | "absolute_import"
|
||||
| "with_statement" | "print_function" | "unicode_literals" => {}
|
||||
@@ -2667,17 +2676,6 @@ fn compile_location(location: &ast::Location) -> bytecode::Location {
|
||||
bytecode::Location::new(location.row(), location.column())
|
||||
}
|
||||
|
||||
fn compile_conversion_flag(
|
||||
conversion_flag: Option<ast::ConversionFlag>,
|
||||
) -> bytecode::ConversionFlag {
|
||||
match conversion_flag {
|
||||
None => bytecode::ConversionFlag::None,
|
||||
Some(ast::ConversionFlag::Ascii) => bytecode::ConversionFlag::Ascii,
|
||||
Some(ast::ConversionFlag::Repr) => bytecode::ConversionFlag::Repr,
|
||||
Some(ast::ConversionFlag::Str) => bytecode::ConversionFlag::Str,
|
||||
}
|
||||
}
|
||||
|
||||
fn compile_constant(value: &ast::Constant) -> ConstantData {
|
||||
match value {
|
||||
ast::Constant::None => ConstantData::None,
|
||||
|
||||
@@ -37,6 +37,7 @@ pub enum CompileErrorType {
|
||||
TooManyStarUnpack,
|
||||
EmptyWithItems,
|
||||
EmptyWithBody,
|
||||
NotImplementedYet, // RustPython marker for unimplemented features
|
||||
}
|
||||
|
||||
impl fmt::Display for CompileErrorType {
|
||||
@@ -78,6 +79,9 @@ impl fmt::Display for CompileErrorType {
|
||||
CompileErrorType::EmptyWithBody => {
|
||||
write!(f, "empty body on With")
|
||||
}
|
||||
CompileErrorType::NotImplementedYet => {
|
||||
write!(f, "RustPython does not implement this feature yet")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+20
-10
@@ -639,7 +639,7 @@ impl SymbolTableBuilder {
|
||||
if let ImportFrom { module, names, .. } = &statement.node {
|
||||
if module.as_deref() == Some("__future__") {
|
||||
for feature in names {
|
||||
if feature.name == "annotations" {
|
||||
if feature.node.name == "annotations" {
|
||||
self.future_annotations = true;
|
||||
}
|
||||
}
|
||||
@@ -739,13 +739,13 @@ impl SymbolTableBuilder {
|
||||
}
|
||||
Import { names } | ImportFrom { names, .. } => {
|
||||
for name in names {
|
||||
if let Some(alias) = &name.asname {
|
||||
if let Some(alias) = &name.node.asname {
|
||||
// `import mymodule as myalias`
|
||||
self.register_name(alias, SymbolUsage::Imported, location)?;
|
||||
} else {
|
||||
// `import module`
|
||||
self.register_name(
|
||||
name.name.split('.').next().unwrap(),
|
||||
name.node.name.split('.').next().unwrap(),
|
||||
SymbolUsage::Imported,
|
||||
location,
|
||||
)?;
|
||||
@@ -782,7 +782,7 @@ impl SymbolTableBuilder {
|
||||
} => {
|
||||
// https://github.com/python/cpython/blob/main/Python/symtable.c#L1233
|
||||
match &target.node {
|
||||
ast::ExprKind::Name { id, .. } if *simple => {
|
||||
ast::ExprKind::Name { id, .. } if *simple > 0 => {
|
||||
self.register_name(id, SymbolUsage::AnnotationAssigned, location)?;
|
||||
}
|
||||
_ => {
|
||||
@@ -823,6 +823,15 @@ impl SymbolTableBuilder {
|
||||
self.scan_statements(orelse)?;
|
||||
self.scan_statements(finalbody)?;
|
||||
}
|
||||
Match {
|
||||
subject: _,
|
||||
cases: _,
|
||||
} => {
|
||||
return Err(SymbolTableError {
|
||||
error: "match expression is not implemented yet".to_owned(),
|
||||
location: Location::default(),
|
||||
});
|
||||
}
|
||||
Raise { exc, cause } => {
|
||||
if let Some(expression) = exc {
|
||||
self.scan_expression(expression, ExpressionContext::Load)?;
|
||||
@@ -875,12 +884,13 @@ impl SymbolTableBuilder {
|
||||
self.scan_expression(value, ExpressionContext::Load)?;
|
||||
}
|
||||
Dict { keys, values } => {
|
||||
for (key, value) in keys.iter().zip(values) {
|
||||
if let Some(key) = key {
|
||||
self.scan_expression(key, context)?;
|
||||
} else {
|
||||
// dict unpacking marker
|
||||
}
|
||||
let (packed, unpacked) = values.split_at(keys.len());
|
||||
for (key, value) in keys.iter().zip(packed) {
|
||||
self.scan_expression(key, context)?;
|
||||
self.scan_expression(value, context)?;
|
||||
}
|
||||
for value in unpacked {
|
||||
// dict unpacking marker
|
||||
self.scan_expression(value, context)?;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -285,7 +285,7 @@ y = {'b': 2, 'c': 2, 'd': 2}
|
||||
z = {'c': 3, 'd': 3, 'e': 3}
|
||||
|
||||
w = {1: 1, **x, 2: 2, **y, 3: 3, **z, 4: 4}
|
||||
assert w == {1: 1, 'a': 1, 'b': 2, 'c': 3, 2: 2, 'd': 3, 3: 3, 'e': 3, 4: 4}
|
||||
assert w == {1: 1, 'a': 1, 'b': 2, 'c': 3, 2: 2, 'd': 3, 3: 3, 'e': 3, 4: 4} # not in cpython test suite
|
||||
|
||||
assert str({True: True, 1.0: 1.0}) == str({True: 1.0})
|
||||
|
||||
|
||||
+57
-16
@@ -268,19 +268,19 @@ ImportDots: usize = {
|
||||
};
|
||||
|
||||
ImportAsNames: Vec<ast::Alias> = {
|
||||
<i:OneOrMore<ImportAsAlias<Identifier>>> => i,
|
||||
"(" <i:OneOrMore<ImportAsAlias<Identifier>>> ","? ")" => i,
|
||||
"*" => {
|
||||
<location:@L> <i:OneOrMore<ImportAsAlias<Identifier>>> => i,
|
||||
<location:@L> "(" <i:OneOrMore<ImportAsAlias<Identifier>>> ","? ")" => i,
|
||||
<location:@L> "*" => {
|
||||
// Star import all
|
||||
vec![ast::Alias(ast::AliasData { name: "*".to_string(), asname: None })]
|
||||
vec![ast::Alias::new(location, ast::AliasData { name: "*".to_string(), asname: None })]
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
#[inline]
|
||||
ImportAsAlias<I>: ast::Alias = {
|
||||
<name:I> <a: ("as" Identifier)?> => ast::Alias { name, asname: a.map(|a| a.1) },
|
||||
};
|
||||
<location:@L> <name:I> <a: ("as" Identifier)?> => ast::Alias::new(location, ast::AliasData { name, asname: a.map(|a| a.1) }),
|
||||
}
|
||||
|
||||
// A name like abc or abc.def.ghi
|
||||
DottedName: String = {
|
||||
@@ -590,20 +590,26 @@ TypedParameter: ast::Arg = {
|
||||
// Use inline here to make sure the "," is not creating an ambiguity.
|
||||
// TODO: figure out another grammar that makes this inline no longer required.
|
||||
#[inline]
|
||||
ParameterListStarArgs<ArgType>: (Option<Box<ast::Arg>>, Vec<ast::Arg>, Vec<Option<Box<ast::Expr>>>, Option<Box<ast::Arg>>) = {
|
||||
ParameterListStarArgs<ArgType>: (Option<Box<ast::Arg>>, Vec<ast::Arg>, Vec<ast::Expr>, Option<Box<ast::Arg>>) = {
|
||||
"*" <va:ArgType?> <kw:("," ParameterDef<ArgType>)*> <kwarg:("," KwargParameter<ArgType>)?> => {
|
||||
// Extract keyword arguments:
|
||||
let mut kwonlyargs = vec![];
|
||||
let mut kw_defaults = vec![];
|
||||
let mut kwonlyargs = Vec::new();
|
||||
let mut kw_defaults = Vec::new();
|
||||
let mut kwargs = Vec::new();
|
||||
for (name, value) in kw.into_iter().map(|x| x.1) {
|
||||
kwonlyargs.push(name);
|
||||
kw_defaults.push(value.map(Box::new));
|
||||
if let Some(value) = value {
|
||||
kwonlyargs.push(name);
|
||||
kw_defaults.push(value);
|
||||
} else {
|
||||
kwargs.push(name);
|
||||
}
|
||||
}
|
||||
kwargs.extend(kwonlyargs.into_iter());
|
||||
|
||||
let kwarg = kwarg.map(|n| n.1).flatten();
|
||||
let va = va.map(Box::new);
|
||||
|
||||
(va, kwonlyargs, kw_defaults, kwarg)
|
||||
(va, kwargs, kw_defaults, kwarg)
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1039,7 +1045,42 @@ Atom: ast::Expr = {
|
||||
}.into())
|
||||
},
|
||||
<location:@L> "{" <e:DictLiteralValues?> "}" => {
|
||||
let (keys, values) = e.unwrap_or_default();
|
||||
let pairs = e.unwrap_or_default();
|
||||
|
||||
let (keys, values) = match pairs.iter().position(|(k,_)| k.is_none()) {
|
||||
Some(unpack_idx) => {
|
||||
let mut pairs = pairs;
|
||||
let (keys, mut values): (_, Vec<_>) = pairs.drain(..unpack_idx).map(|(k, v)| (*k.unwrap(), v)).unzip();
|
||||
|
||||
fn build_map(items: &mut Vec<(ast::Expr, ast::Expr)>) -> ast::Expr {
|
||||
let location = items[0].0.location;
|
||||
let (keys, values) = items.drain(..).unzip();
|
||||
ast::Expr {
|
||||
location,
|
||||
custom: (),
|
||||
node: ast::ExprKind::Dict { keys, values }
|
||||
}
|
||||
}
|
||||
|
||||
let mut items = Vec::new();
|
||||
for (key, value) in pairs.into_iter() {
|
||||
if let Some(key) = key {
|
||||
items.push((*key, value));
|
||||
continue;
|
||||
}
|
||||
if !items.is_empty() {
|
||||
values.push(build_map(&mut items));
|
||||
}
|
||||
values.push(value);
|
||||
}
|
||||
if !items.is_empty() {
|
||||
values.push(build_map(&mut items));
|
||||
}
|
||||
(keys, values)
|
||||
},
|
||||
None => pairs.into_iter().map(|(k, v)| (*k.unwrap(), v)).unzip()
|
||||
};
|
||||
|
||||
ast::Expr {
|
||||
location,
|
||||
custom: (),
|
||||
@@ -1079,8 +1120,8 @@ ListLiteralValues: Vec<ast::Expr> = {
|
||||
<e:OneOrMore<TestOrStarNamedExpr>> ","? => e,
|
||||
};
|
||||
|
||||
DictLiteralValues: (Vec<Option<Box<ast::Expr>>>, Vec<ast::Expr>) = {
|
||||
<elements:OneOrMore<DictElement>> ","? => elements.into_iter().unzip(),
|
||||
DictLiteralValues: Vec<(Option<Box<ast::Expr>>, ast::Expr)> = {
|
||||
<elements:OneOrMore<DictElement>> ","? => elements,
|
||||
};
|
||||
|
||||
DictEntry: (ast::Expr, ast::Expr) = {
|
||||
@@ -1151,7 +1192,7 @@ SingleForComprehension: ast::Comprehension = {
|
||||
target: Box::new(target),
|
||||
iter: Box::new(iter),
|
||||
ifs,
|
||||
is_async
|
||||
is_async: if is_async { 1 } else { 0 },
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -30,7 +30,7 @@ impl<'a> FStringParser<'a> {
|
||||
let mut expression = String::new();
|
||||
let mut spec = None;
|
||||
let mut delims = Vec::new();
|
||||
let mut conversion = ConversionFlag::Str;
|
||||
let mut conversion = ConversionFlag::None;
|
||||
let mut pred_expression_text = String::new();
|
||||
let mut trailing_seq = String::new();
|
||||
|
||||
@@ -115,7 +115,7 @@ impl<'a> FStringParser<'a> {
|
||||
)
|
||||
.parse()?,
|
||||
),
|
||||
conversion: b's' as usize,
|
||||
conversion: ConversionFlag::None as _,
|
||||
format_spec: None,
|
||||
}),
|
||||
);
|
||||
@@ -187,7 +187,7 @@ impl<'a> FStringParser<'a> {
|
||||
parse_fstring_expr(&expression)
|
||||
.map_err(|e| InvalidExpression(Box::new(e.error)))?,
|
||||
),
|
||||
conversion: conversion as usize,
|
||||
conversion: conversion as _,
|
||||
format_spec: spec,
|
||||
})]
|
||||
} else {
|
||||
@@ -205,7 +205,7 @@ impl<'a> FStringParser<'a> {
|
||||
parse_fstring_expr(&expression)
|
||||
.map_err(|e| InvalidExpression(Box::new(e.error)))?,
|
||||
),
|
||||
conversion: conversion as usize,
|
||||
conversion: conversion as _,
|
||||
format_spec: spec,
|
||||
}),
|
||||
]
|
||||
|
||||
+1
-1
@@ -54,7 +54,7 @@ Located {
|
||||
ctx: Load,
|
||||
},
|
||||
},
|
||||
conversion: None,
|
||||
conversion: 0,
|
||||
format_spec: None,
|
||||
},
|
||||
},
|
||||
|
||||
+2
-2
@@ -67,7 +67,7 @@ Located {
|
||||
ctx: Load,
|
||||
},
|
||||
},
|
||||
conversion: None,
|
||||
conversion: 0,
|
||||
format_spec: None,
|
||||
},
|
||||
},
|
||||
@@ -128,7 +128,7 @@ Located {
|
||||
ctx: Load,
|
||||
},
|
||||
},
|
||||
conversion: None,
|
||||
conversion: 0,
|
||||
format_spec: None,
|
||||
},
|
||||
},
|
||||
|
||||
+1
-2
@@ -1,7 +1,6 @@
|
||||
---
|
||||
source: parser/src/fstring.rs
|
||||
expression: parse_ast
|
||||
|
||||
---
|
||||
Located {
|
||||
location: Location {
|
||||
@@ -55,7 +54,7 @@ Located {
|
||||
ctx: Load,
|
||||
},
|
||||
},
|
||||
conversion: None,
|
||||
conversion: 0,
|
||||
format_spec: Some(
|
||||
Located {
|
||||
location: Location {
|
||||
|
||||
@@ -28,7 +28,7 @@ Located {
|
||||
ctx: Load,
|
||||
},
|
||||
},
|
||||
conversion: None,
|
||||
conversion: 0,
|
||||
format_spec: None,
|
||||
},
|
||||
},
|
||||
@@ -50,7 +50,7 @@ Located {
|
||||
ctx: Load,
|
||||
},
|
||||
},
|
||||
conversion: None,
|
||||
conversion: 0,
|
||||
format_spec: None,
|
||||
},
|
||||
},
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
---
|
||||
source: parser/src/fstring.rs
|
||||
expression: parse_ast
|
||||
|
||||
---
|
||||
Located {
|
||||
location: Location {
|
||||
@@ -58,7 +57,7 @@ Located {
|
||||
],
|
||||
},
|
||||
},
|
||||
conversion: None,
|
||||
conversion: 0,
|
||||
format_spec: None,
|
||||
},
|
||||
},
|
||||
|
||||
+3
-4
@@ -1,7 +1,6 @@
|
||||
---
|
||||
source: parser/src/fstring.rs
|
||||
expression: parse_ast
|
||||
|
||||
---
|
||||
Located {
|
||||
location: Location {
|
||||
@@ -29,7 +28,7 @@ Located {
|
||||
ctx: Load,
|
||||
},
|
||||
},
|
||||
conversion: None,
|
||||
conversion: 0,
|
||||
format_spec: Some(
|
||||
Located {
|
||||
location: Location {
|
||||
@@ -85,14 +84,14 @@ Located {
|
||||
ctx: Load,
|
||||
},
|
||||
},
|
||||
conversion: None,
|
||||
conversion: 0,
|
||||
format_spec: None,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
conversion: None,
|
||||
conversion: 0,
|
||||
format_spec: None,
|
||||
},
|
||||
},
|
||||
|
||||
+1
-2
@@ -1,7 +1,6 @@
|
||||
---
|
||||
source: parser/src/fstring.rs
|
||||
expression: parse_ast
|
||||
|
||||
---
|
||||
Located {
|
||||
location: Location {
|
||||
@@ -58,7 +57,7 @@ Located {
|
||||
],
|
||||
},
|
||||
},
|
||||
conversion: None,
|
||||
conversion: 0,
|
||||
format_spec: None,
|
||||
},
|
||||
},
|
||||
|
||||
+1
-2
@@ -1,7 +1,6 @@
|
||||
---
|
||||
source: parser/src/fstring.rs
|
||||
expression: parse_ast
|
||||
|
||||
---
|
||||
Located {
|
||||
location: Location {
|
||||
@@ -29,7 +28,7 @@ Located {
|
||||
ctx: Load,
|
||||
},
|
||||
},
|
||||
conversion: None,
|
||||
conversion: 0,
|
||||
format_spec: Some(
|
||||
Located {
|
||||
location: Location {
|
||||
|
||||
+1
-1
@@ -54,7 +54,7 @@ Located {
|
||||
ctx: Load,
|
||||
},
|
||||
},
|
||||
conversion: None,
|
||||
conversion: 0,
|
||||
format_spec: None,
|
||||
},
|
||||
},
|
||||
|
||||
+1
-1
@@ -54,7 +54,7 @@ Located {
|
||||
ctx: Load,
|
||||
},
|
||||
},
|
||||
conversion: None,
|
||||
conversion: 0,
|
||||
format_spec: None,
|
||||
},
|
||||
},
|
||||
|
||||
+1
-2
@@ -1,7 +1,6 @@
|
||||
---
|
||||
source: parser/src/fstring.rs
|
||||
expression: parse_ast
|
||||
|
||||
---
|
||||
Located {
|
||||
location: Location {
|
||||
@@ -28,7 +27,7 @@ Located {
|
||||
value: None,
|
||||
},
|
||||
},
|
||||
conversion: None,
|
||||
conversion: 0,
|
||||
format_spec: None,
|
||||
},
|
||||
},
|
||||
|
||||
+1
-1
@@ -56,7 +56,7 @@ Located {
|
||||
},
|
||||
},
|
||||
ifs: [],
|
||||
is_async: false,
|
||||
is_async: 0,
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
+2
-3
@@ -1,7 +1,6 @@
|
||||
---
|
||||
source: parser/src/parser.rs
|
||||
expression: parse_ast
|
||||
|
||||
---
|
||||
Located {
|
||||
location: Location {
|
||||
@@ -69,7 +68,7 @@ Located {
|
||||
},
|
||||
},
|
||||
ifs: [],
|
||||
is_async: false,
|
||||
is_async: 0,
|
||||
},
|
||||
Comprehension {
|
||||
target: Located {
|
||||
@@ -172,7 +171,7 @@ Located {
|
||||
},
|
||||
},
|
||||
],
|
||||
is_async: false,
|
||||
is_async: 0,
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
+1
-1
@@ -45,7 +45,7 @@ Located {
|
||||
},
|
||||
},
|
||||
ifs: [],
|
||||
is_async: false,
|
||||
is_async: 0,
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
+9
-15
@@ -71,15 +71,12 @@ impl PyDict {
|
||||
}
|
||||
|
||||
// Used in update and ior.
|
||||
fn merge_object(
|
||||
dict: &DictContentType,
|
||||
other: PyObjectRef,
|
||||
vm: &VirtualMachine,
|
||||
) -> PyResult<()> {
|
||||
pub(crate) fn merge_object(&self, other: PyObjectRef, vm: &VirtualMachine) -> PyResult<()> {
|
||||
let other = match other.downcast_exact(vm) {
|
||||
Ok(dict_other) => return Self::merge_dict(dict, dict_other, vm),
|
||||
Ok(dict_other) => return self.merge_dict(dict_other, vm),
|
||||
Err(other) => other,
|
||||
};
|
||||
let dict = &self.entries;
|
||||
if let Some(keys) = vm.get_method(other.clone(), vm.ctx.intern_str("keys")) {
|
||||
let keys = vm.invoke(&keys?, ())?.get_iter(vm)?;
|
||||
while let PyIterReturn::Return(key) = keys.next(vm)? {
|
||||
@@ -108,11 +105,8 @@ impl PyDict {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn merge_dict(
|
||||
dict: &DictContentType,
|
||||
dict_other: PyDictRef,
|
||||
vm: &VirtualMachine,
|
||||
) -> PyResult<()> {
|
||||
fn merge_dict(&self, dict_other: PyDictRef, vm: &VirtualMachine) -> PyResult<()> {
|
||||
let dict = &self.entries;
|
||||
let dict_size = &dict_other.size();
|
||||
for (key, value) in &dict_other {
|
||||
dict.insert(vm, &*key, value)?;
|
||||
@@ -363,7 +357,7 @@ impl PyDict {
|
||||
vm: &VirtualMachine,
|
||||
) -> PyResult<()> {
|
||||
if let OptionalArg::Present(dict_obj) = dict_obj {
|
||||
Self::merge_object(&self.entries, dict_obj, vm)?;
|
||||
self.merge_object(dict_obj, vm)?;
|
||||
}
|
||||
for (key, value) in kwargs.into_iter() {
|
||||
self.entries.insert(vm, &key, value)?;
|
||||
@@ -373,7 +367,7 @@ impl PyDict {
|
||||
|
||||
#[pymethod(magic)]
|
||||
fn ior(zelf: PyRef<Self>, other: PyObjectRef, vm: &VirtualMachine) -> PyResult<PyRef<Self>> {
|
||||
PyDict::merge_object(&zelf.entries, other, vm)?;
|
||||
zelf.merge_object(other, vm)?;
|
||||
Ok(zelf)
|
||||
}
|
||||
|
||||
@@ -382,7 +376,7 @@ impl PyDict {
|
||||
let dicted: Result<PyDictRef, _> = other.downcast();
|
||||
if let Ok(other) = dicted {
|
||||
let other_cp = other.copy();
|
||||
PyDict::merge_dict(&other_cp.entries, zelf, vm)?;
|
||||
other_cp.merge_dict(zelf, vm)?;
|
||||
return Ok(other_cp.into_pyobject(vm));
|
||||
}
|
||||
Ok(vm.ctx.not_implemented())
|
||||
@@ -393,7 +387,7 @@ impl PyDict {
|
||||
let dicted: Result<PyDictRef, _> = other.downcast();
|
||||
if let Ok(other) = dicted {
|
||||
let self_cp = self.copy();
|
||||
PyDict::merge_dict(&self_cp.entries, other, vm)?;
|
||||
self_cp.merge_dict(other, vm)?;
|
||||
return Ok(self_cp.into_pyobject(vm));
|
||||
}
|
||||
Ok(vm.ctx.not_implemented())
|
||||
|
||||
+5
-3
@@ -679,9 +679,11 @@ impl ExecutingFrame<'_> {
|
||||
} => self.execute_build_map(vm, *size, *unpack, *for_call),
|
||||
bytecode::Instruction::DictUpdate => {
|
||||
let other = self.pop_value();
|
||||
let dict = self.pop_value();
|
||||
let updated = vm.call_method(&dict, "update", (other,))?;
|
||||
self.push_value(updated);
|
||||
let dict = self
|
||||
.last_value_ref()
|
||||
.downcast_ref::<PyDict>()
|
||||
.expect("exact dict expected");
|
||||
dict.merge_object(other, vm)?;
|
||||
Ok(None)
|
||||
}
|
||||
bytecode::Instruction::BuildSlice { step } => self.execute_build_slice(vm, *step),
|
||||
|
||||
@@ -252,8 +252,8 @@ impl Node for ast::ConversionFlag {
|
||||
|
||||
fn ast_from_object(vm: &VirtualMachine, object: PyObjectRef) -> PyResult<Self> {
|
||||
i32::try_from_object(vm, object)?
|
||||
.to_u8()
|
||||
.and_then(ast::ConversionFlag::try_from_byte)
|
||||
.to_usize()
|
||||
.and_then(|f| f.try_into().ok())
|
||||
.ok_or_else(|| vm.new_value_error("invalid conversion flag".to_owned()))
|
||||
}
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user