Implement new features for updated python asdl

This commit is contained in:
Jeong YunWon committed 2022-08-19 04:52:45 +09:00
1 parent 0d334a9b0e
commit 53b344866f
29 files changed
+182 -156

No files matched your search

Generated
+1
View File
@@ -1723,6 +1723,7 @@ name = "rustpython-ast"
version = "0.1.0"
dependencies = [
"num-bigint",
"rustpython-bytecode",
"rustpython-common",
]
+1
View File
@@ -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
View File
@@ -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)]
+1 -7
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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,
+4
View File
@@ -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
View File
@@ -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)?;
}
}
+1 -1
View File
@@ -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
View File
@@ -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 },
}
}
};
+4 -4
View File
@@ -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,
}),
]
@@ -54,7 +54,7 @@ Located {
ctx: Load,
},
},
conversion: None,
conversion: 0,
format_spec: None,
},
},
@@ -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,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,
},
},
@@ -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,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,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 {
@@ -54,7 +54,7 @@ Located {
ctx: Load,
},
},
conversion: None,
conversion: 0,
format_spec: None,
},
},
@@ -54,7 +54,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 {
@@ -28,7 +27,7 @@ Located {
value: None,
},
},
conversion: None,
conversion: 0,
format_spec: None,
},
},
@@ -56,7 +56,7 @@ Located {
},
},
ifs: [],
is_async: false,
is_async: 0,
},
],
},
@@ -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,
},
],
},
@@ -45,7 +45,7 @@ Located {
},
},
ifs: [],
is_async: false,
is_async: 0,
},
],
},
+9 -15
View File
@@ -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
View File
@@ -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),
+2 -2
View File
@@ -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()))
}
}