mirror of https://github.com/mtshiba/pylyzer
feat: use union types for variable defined in if-else
This commit is contained in:
parent
64169a3962
commit
a7801eb145
|
|
@ -145,9 +145,9 @@ checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "els"
|
name = "els"
|
||||||
version = "0.1.59-nightly.2"
|
version = "0.1.59-nightly.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a2f90c210a0919808e48b96ecffd370ac788386ab061203132872e9bf1ad9f7f"
|
checksum = "4b4e110537afd761192ab9cbea35f98d2e1421c1d98520a7c7114d30805ebe8d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"erg_common",
|
"erg_common",
|
||||||
"erg_compiler",
|
"erg_compiler",
|
||||||
|
|
@ -161,9 +161,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "erg_common"
|
name = "erg_common"
|
||||||
version = "0.6.47-nightly.2"
|
version = "0.6.47-nightly.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d41f171eb77bf2763b119893966358ad9da72a3edd43cf278a78cf1c16daa2cf"
|
checksum = "c17933aa843a988726e412295f030a501e1bf4c5c8ed1fa4bb5013a37bce9d8a"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"backtrace-on-stack-overflow",
|
"backtrace-on-stack-overflow",
|
||||||
"erg_proc_macros",
|
"erg_proc_macros",
|
||||||
|
|
@ -174,9 +174,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "erg_compiler"
|
name = "erg_compiler"
|
||||||
version = "0.6.47-nightly.2"
|
version = "0.6.47-nightly.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "93d0486bc668c120faf7af954dd4046224185c28821fb945a97eedcadf3e7d58"
|
checksum = "d3a10f7dd0644d0378bf1ba45cd923d774552757ac6f19d5f9dee090f0ac668b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"erg_common",
|
"erg_common",
|
||||||
"erg_parser",
|
"erg_parser",
|
||||||
|
|
@ -184,9 +184,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "erg_parser"
|
name = "erg_parser"
|
||||||
version = "0.6.47-nightly.2"
|
version = "0.6.47-nightly.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "98c37f58f3aef2e765610e7281ada15dbba707beaa0262a71e7f6958ee058ed0"
|
checksum = "8ca055f88af21585c301b93874cff818477c26e0343cb1dfe3b4c69c928bfe31"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"erg_common",
|
"erg_common",
|
||||||
"erg_proc_macros",
|
"erg_proc_macros",
|
||||||
|
|
@ -195,9 +195,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "erg_proc_macros"
|
name = "erg_proc_macros"
|
||||||
version = "0.6.47-nightly.2"
|
version = "0.6.47-nightly.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "97fa545f626fd04abea193a07c364c4fca3903c228bbe9cca4895500944b5aaf"
|
checksum = "8560abd2df3c3db6183e7495384f0c1d04d42e779bc0e1402589ab488ab0aaec"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"quote",
|
"quote",
|
||||||
"syn 1.0.109",
|
"syn 1.0.109",
|
||||||
|
|
|
||||||
|
|
@ -24,9 +24,9 @@ edition = "2021"
|
||||||
repository = "https://github.com/mtshiba/pylyzer"
|
repository = "https://github.com/mtshiba/pylyzer"
|
||||||
|
|
||||||
[workspace.dependencies]
|
[workspace.dependencies]
|
||||||
erg_common = { version = "0.6.47-nightly.2", features = ["py_compat", "els"] }
|
erg_common = { version = "0.6.47-nightly.4", features = ["py_compat", "els"] }
|
||||||
erg_compiler = { version = "0.6.47-nightly.2", features = ["py_compat", "els"] }
|
erg_compiler = { version = "0.6.47-nightly.4", features = ["py_compat", "els"] }
|
||||||
els = { version = "0.1.59-nightly.2", features = ["py_compat"] }
|
els = { version = "0.1.59-nightly.4", features = ["py_compat"] }
|
||||||
# rustpython-parser = { version = "0.3.0", features = ["all-nodes-with-ranges", "location"] }
|
# rustpython-parser = { version = "0.3.0", features = ["all-nodes-with-ranges", "location"] }
|
||||||
# rustpython-ast = { version = "0.3.0", features = ["all-nodes-with-ranges", "location"] }
|
# rustpython-ast = { version = "0.3.0", features = ["all-nodes-with-ranges", "location"] }
|
||||||
rustpython-parser = { git = "https://github.com/RustPython/Parser", version = "0.4.0", features = ["all-nodes-with-ranges", "location"] }
|
rustpython-parser = { git = "https://github.com/RustPython/Parser", version = "0.4.0", features = ["all-nodes-with-ranges", "location"] }
|
||||||
|
|
|
||||||
|
|
@ -61,18 +61,10 @@ macro_rules! global_binary_collections {
|
||||||
pub const ARROW: Token = Token::dummy(TokenKind::FuncArrow, "->");
|
pub const ARROW: Token = Token::dummy(TokenKind::FuncArrow, "->");
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
pub enum CanShadow {
|
pub enum RenameKind {
|
||||||
Yes,
|
Let,
|
||||||
No,
|
Phi,
|
||||||
}
|
Redef,
|
||||||
|
|
||||||
impl CanShadow {
|
|
||||||
pub const fn is_yes(&self) -> bool {
|
|
||||||
matches!(self, Self::Yes)
|
|
||||||
}
|
|
||||||
pub const fn is_no(&self) -> bool {
|
|
||||||
matches!(self, Self::No)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||||
|
|
@ -97,6 +89,10 @@ impl NameKind {
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
pub enum BlockKind {
|
pub enum BlockKind {
|
||||||
If,
|
If,
|
||||||
|
/// else, except, finally
|
||||||
|
Else {
|
||||||
|
if_block_id: usize,
|
||||||
|
},
|
||||||
For,
|
For,
|
||||||
While,
|
While,
|
||||||
Try,
|
Try,
|
||||||
|
|
@ -117,6 +113,15 @@ impl BlockKind {
|
||||||
pub const fn makes_scope(&self) -> bool {
|
pub const fn makes_scope(&self) -> bool {
|
||||||
matches!(self, Self::Function | Self::AsyncFunction | Self::Class)
|
matches!(self, Self::Function | Self::AsyncFunction | Self::Class)
|
||||||
}
|
}
|
||||||
|
pub const fn is_else(&self) -> bool {
|
||||||
|
matches!(self, Self::Else { .. })
|
||||||
|
}
|
||||||
|
pub const fn if_block_id(&self) -> Option<usize> {
|
||||||
|
match self {
|
||||||
|
Self::Else { if_block_id } => Some(*if_block_id),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Variables are automatically rewritten with `py_compat`,
|
/// Variables are automatically rewritten with `py_compat`,
|
||||||
|
|
@ -308,6 +313,12 @@ impl TypeVarInfo {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct BlockInfo {
|
||||||
|
pub id: usize,
|
||||||
|
pub kind: BlockKind,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct LocalContext {
|
pub struct LocalContext {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
|
|
@ -556,7 +567,7 @@ pub struct ASTConverter {
|
||||||
pyi_types: PyiTypeStorage,
|
pyi_types: PyiTypeStorage,
|
||||||
block_id_counter: usize,
|
block_id_counter: usize,
|
||||||
/// block != scope (if block doesn't make a scope, for example)
|
/// block != scope (if block doesn't make a scope, for example)
|
||||||
block_ids: Vec<usize>,
|
blocks: Vec<BlockInfo>,
|
||||||
contexts: Vec<LocalContext>,
|
contexts: Vec<LocalContext>,
|
||||||
warns: CompileErrors,
|
warns: CompileErrors,
|
||||||
errs: CompileErrors,
|
errs: CompileErrors,
|
||||||
|
|
@ -572,7 +583,10 @@ impl ASTConverter {
|
||||||
cfg,
|
cfg,
|
||||||
comments,
|
comments,
|
||||||
block_id_counter: 0,
|
block_id_counter: 0,
|
||||||
block_ids: vec![0],
|
blocks: vec![BlockInfo {
|
||||||
|
id: 0,
|
||||||
|
kind: BlockKind::Module,
|
||||||
|
}],
|
||||||
contexts: vec![LocalContext::new("<module>".into(), BlockKind::Module)],
|
contexts: vec![LocalContext::new("<module>".into(), BlockKind::Module)],
|
||||||
warns: CompileErrors::empty(),
|
warns: CompileErrors::empty(),
|
||||||
errs: CompileErrors::empty(),
|
errs: CompileErrors::empty(),
|
||||||
|
|
@ -631,11 +645,11 @@ impl ASTConverter {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn cur_block_kind(&self) -> BlockKind {
|
fn cur_block_kind(&self) -> BlockKind {
|
||||||
self.contexts.last().unwrap().kind
|
self.blocks.last().unwrap().kind
|
||||||
}
|
}
|
||||||
|
|
||||||
fn cur_block_id(&self) -> usize {
|
fn cur_block_id(&self) -> usize {
|
||||||
*self.block_ids.last().unwrap()
|
self.blocks.last().unwrap().id
|
||||||
}
|
}
|
||||||
|
|
||||||
/// foo.bar.baz
|
/// foo.bar.baz
|
||||||
|
|
@ -660,7 +674,7 @@ impl ASTConverter {
|
||||||
&self.contexts.last().unwrap().appeared_type_names
|
&self.contexts.last().unwrap().appeared_type_names
|
||||||
}
|
}
|
||||||
|
|
||||||
fn register_name_info(&mut self, name: &str, kind: NameKind) -> CanShadow {
|
fn register_name_info(&mut self, name: &str, kind: NameKind) -> RenameKind {
|
||||||
let cur_namespace = self.cur_namespace();
|
let cur_namespace = self.cur_namespace();
|
||||||
let cur_block_id = self.cur_block_id();
|
let cur_block_id = self.cur_block_id();
|
||||||
let cur_block_kind = self.cur_block_kind();
|
let cur_block_kind = self.cur_block_kind();
|
||||||
|
|
@ -672,13 +686,18 @@ impl ASTConverter {
|
||||||
name_info.defined_in = DefinedPlace::Known(cur_namespace);
|
name_info.defined_in = DefinedPlace::Known(cur_namespace);
|
||||||
name_info.defined_times += 1; // 0 -> 1
|
name_info.defined_times += 1; // 0 -> 1
|
||||||
}
|
}
|
||||||
if cur_block_kind.makes_scope()
|
if cur_block_kind
|
||||||
|
.if_block_id()
|
||||||
|
.is_some_and(|id| id == name_info.defined_block_id)
|
||||||
|
{
|
||||||
|
RenameKind::Phi
|
||||||
|
} else if cur_block_kind.makes_scope()
|
||||||
|| name_info.defined_block_id == cur_block_id
|
|| name_info.defined_block_id == cur_block_id
|
||||||
|| name_info.defined_times == 0
|
|| name_info.defined_times == 0
|
||||||
{
|
{
|
||||||
CanShadow::Yes
|
RenameKind::Let
|
||||||
} else {
|
} else {
|
||||||
CanShadow::No
|
RenameKind::Redef
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// In Erg, classes can only be defined in uppercase
|
// In Erg, classes can only be defined in uppercase
|
||||||
|
|
@ -691,7 +710,7 @@ impl ASTConverter {
|
||||||
let defined_in = DefinedPlace::Known(self.cur_namespace());
|
let defined_in = DefinedPlace::Known(self.cur_namespace());
|
||||||
let info = NameInfo::new(rename, defined_in, self.cur_block_id(), 1);
|
let info = NameInfo::new(rename, defined_in, self.cur_block_id(), 1);
|
||||||
self.define_name(String::from(name), info);
|
self.define_name(String::from(name), info);
|
||||||
CanShadow::Yes
|
RenameKind::Let
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -957,12 +976,15 @@ impl ASTConverter {
|
||||||
let (param, block) = self.convert_opt_expr_to_param(lhs);
|
let (param, block) = self.convert_opt_expr_to_param(lhs);
|
||||||
let params = Params::new(vec![param], None, vec![], None, None);
|
let params = Params::new(vec![param], None, vec![], None, None);
|
||||||
self.block_id_counter += 1;
|
self.block_id_counter += 1;
|
||||||
self.block_ids.push(self.block_id_counter);
|
self.blocks.push(BlockInfo {
|
||||||
|
id: self.block_id_counter,
|
||||||
|
kind: BlockKind::For,
|
||||||
|
});
|
||||||
let body = body
|
let body = body
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|stmt| self.convert_statement(stmt, true))
|
.map(|stmt| self.convert_statement(stmt, true))
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
self.block_ids.pop();
|
self.blocks.pop();
|
||||||
let body = block.into_iter().chain(body).collect();
|
let body = block.into_iter().chain(body).collect();
|
||||||
let sig = LambdaSignature::new(params, None, TypeBoundSpecs::empty());
|
let sig = LambdaSignature::new(params, None, TypeBoundSpecs::empty());
|
||||||
let op = Token::from_str(TokenKind::FuncArrow, "->");
|
let op = Token::from_str(TokenKind::FuncArrow, "->");
|
||||||
|
|
@ -1926,12 +1948,15 @@ impl ASTConverter {
|
||||||
let mut new_block = Vec::new();
|
let mut new_block = Vec::new();
|
||||||
let len = block.len();
|
let len = block.len();
|
||||||
self.block_id_counter += 1;
|
self.block_id_counter += 1;
|
||||||
self.block_ids.push(self.block_id_counter);
|
self.blocks.push(BlockInfo {
|
||||||
|
id: self.block_id_counter,
|
||||||
|
kind,
|
||||||
|
});
|
||||||
for (i, stmt) in block.into_iter().enumerate() {
|
for (i, stmt) in block.into_iter().enumerate() {
|
||||||
let is_last = i == len - 1;
|
let is_last = i == len - 1;
|
||||||
new_block.push(self.convert_statement(stmt, is_last && kind.is_function()));
|
new_block.push(self.convert_statement(stmt, is_last && kind.is_function()));
|
||||||
}
|
}
|
||||||
self.block_ids.pop();
|
self.blocks.pop();
|
||||||
Block::new(new_block)
|
Block::new(new_block)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2483,17 +2508,38 @@ impl ASTConverter {
|
||||||
match *ann_assign.target {
|
match *ann_assign.target {
|
||||||
py_ast::Expr::Name(name) => {
|
py_ast::Expr::Name(name) => {
|
||||||
if let Some(value) = ann_assign.value {
|
if let Some(value) = ann_assign.value {
|
||||||
let block = Block::new(vec![self.convert_expr(*value)]);
|
let expr = self.convert_expr(*value);
|
||||||
let body = DefBody::new(EQUAL, block, DefId(0));
|
|
||||||
// must register after convert_expr because value may be contain name (e.g. i = i + 1)
|
// must register after convert_expr because value may be contain name (e.g. i = i + 1)
|
||||||
self.register_name_info(name.id.as_str(), NameKind::Variable);
|
let rename =
|
||||||
|
self.register_name_info(name.id.as_str(), NameKind::Variable);
|
||||||
let ident = self.convert_ident(name.id.to_string(), name.location());
|
let ident = self.convert_ident(name.id.to_string(), name.location());
|
||||||
let sig = Signature::Var(VarSignature::new(
|
match rename {
|
||||||
VarPattern::Ident(ident),
|
RenameKind::Let => {
|
||||||
Some(t_spec),
|
let block = Block::new(vec![expr]);
|
||||||
));
|
let body = DefBody::new(EQUAL, block, DefId(0));
|
||||||
let def = Def::new(sig, body);
|
let sig = Signature::Var(VarSignature::new(
|
||||||
Expr::Def(def)
|
VarPattern::Ident(ident),
|
||||||
|
Some(t_spec),
|
||||||
|
));
|
||||||
|
let def = Def::new(sig, body);
|
||||||
|
Expr::Def(def)
|
||||||
|
}
|
||||||
|
RenameKind::Phi => {
|
||||||
|
let block = Block::new(vec![expr]);
|
||||||
|
let body = DefBody::new(EQUAL, block, DefId(0));
|
||||||
|
let sig = Signature::Var(VarSignature::new(
|
||||||
|
VarPattern::Phi(ident),
|
||||||
|
Some(t_spec),
|
||||||
|
));
|
||||||
|
let def = Def::new(sig, body);
|
||||||
|
Expr::Def(def)
|
||||||
|
}
|
||||||
|
RenameKind::Redef => {
|
||||||
|
let redef =
|
||||||
|
ReDef::new(Accessor::Ident(ident), Some(t_spec), expr);
|
||||||
|
Expr::ReDef(redef)
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// no registration because it's just a type ascription
|
// no registration because it's just a type ascription
|
||||||
let ident = self.convert_ident(name.id.to_string(), name.location());
|
let ident = self.convert_ident(name.id.to_string(), name.location());
|
||||||
|
|
@ -2557,21 +2603,34 @@ impl ASTConverter {
|
||||||
self.define_type_var(name.id.to_string(), info);
|
self.define_type_var(name.id.to_string(), info);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let can_shadow = self.register_name_info(&name.id, NameKind::Variable);
|
let rename = self.register_name_info(&name.id, NameKind::Variable);
|
||||||
let ident = self.convert_ident(name.id.to_string(), name.location());
|
let ident = self.convert_ident(name.id.to_string(), name.location());
|
||||||
let t_spec = self.get_assign_t_spec(&name, &expr);
|
let t_spec = self.get_assign_t_spec(&name, &expr);
|
||||||
if can_shadow.is_yes() {
|
match rename {
|
||||||
let block = Block::new(vec![expr]);
|
RenameKind::Let => {
|
||||||
let body = DefBody::new(EQUAL, block, DefId(0));
|
let block = Block::new(vec![expr]);
|
||||||
let sig = Signature::Var(VarSignature::new(
|
let body = DefBody::new(EQUAL, block, DefId(0));
|
||||||
VarPattern::Ident(ident),
|
let sig = Signature::Var(VarSignature::new(
|
||||||
t_spec,
|
VarPattern::Ident(ident),
|
||||||
));
|
t_spec,
|
||||||
let def = Def::new(sig, body);
|
));
|
||||||
Expr::Def(def)
|
let def = Def::new(sig, body);
|
||||||
} else {
|
Expr::Def(def)
|
||||||
let redef = ReDef::new(Accessor::Ident(ident), t_spec, expr);
|
}
|
||||||
Expr::ReDef(redef)
|
RenameKind::Phi => {
|
||||||
|
let block = Block::new(vec![expr]);
|
||||||
|
let body = DefBody::new(EQUAL, block, DefId(0));
|
||||||
|
let sig = Signature::Var(VarSignature::new(
|
||||||
|
VarPattern::Phi(ident),
|
||||||
|
t_spec,
|
||||||
|
));
|
||||||
|
let def = Def::new(sig, body);
|
||||||
|
Expr::Def(def)
|
||||||
|
}
|
||||||
|
RenameKind::Redef => {
|
||||||
|
let redef = ReDef::new(Accessor::Ident(ident), t_spec, expr);
|
||||||
|
Expr::ReDef(redef)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
py_ast::Expr::Attribute(attr) => {
|
py_ast::Expr::Attribute(attr) => {
|
||||||
|
|
@ -2654,15 +2713,32 @@ impl ASTConverter {
|
||||||
py_ast::Expr::Name(name) => {
|
py_ast::Expr::Name(name) => {
|
||||||
let body =
|
let body =
|
||||||
DefBody::new(EQUAL, Block::new(vec![value.clone()]), DefId(0));
|
DefBody::new(EQUAL, Block::new(vec![value.clone()]), DefId(0));
|
||||||
self.register_name_info(&name.id, NameKind::Variable);
|
let rename = self.register_name_info(&name.id, NameKind::Variable);
|
||||||
let ident =
|
let ident =
|
||||||
self.convert_ident(name.id.to_string(), name.location());
|
self.convert_ident(name.id.to_string(), name.location());
|
||||||
let sig = Signature::Var(VarSignature::new(
|
match rename {
|
||||||
VarPattern::Ident(ident),
|
RenameKind::Let => {
|
||||||
None,
|
let sig = Signature::Var(VarSignature::new(
|
||||||
));
|
VarPattern::Ident(ident),
|
||||||
let def = Expr::Def(Def::new(sig, body));
|
None,
|
||||||
defs.push(def);
|
));
|
||||||
|
let def = Def::new(sig, body);
|
||||||
|
defs.push(Expr::Def(def));
|
||||||
|
}
|
||||||
|
RenameKind::Phi => {
|
||||||
|
let sig = Signature::Var(VarSignature::new(
|
||||||
|
VarPattern::Phi(ident),
|
||||||
|
None,
|
||||||
|
));
|
||||||
|
let def = Def::new(sig, body);
|
||||||
|
defs.push(Expr::Def(def));
|
||||||
|
}
|
||||||
|
RenameKind::Redef => {
|
||||||
|
let redef =
|
||||||
|
ReDef::new(Accessor::Ident(ident), None, value.clone());
|
||||||
|
defs.push(Expr::ReDef(redef));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
_other => {
|
_other => {
|
||||||
defs.push(Expr::Dummy(Dummy::new(None, vec![])));
|
defs.push(Expr::Dummy(Dummy::new(None, vec![])));
|
||||||
|
|
@ -2770,6 +2846,7 @@ impl ASTConverter {
|
||||||
}
|
}
|
||||||
py_ast::Stmt::If(if_) => {
|
py_ast::Stmt::If(if_) => {
|
||||||
let loc = if_.location();
|
let loc = if_.location();
|
||||||
|
let if_block_id = self.block_id_counter + 1;
|
||||||
let block = self.convert_block(if_.body, BlockKind::If);
|
let block = self.convert_block(if_.body, BlockKind::If);
|
||||||
let params = Params::empty();
|
let params = Params::empty();
|
||||||
let sig = LambdaSignature::new(params.clone(), None, TypeBoundSpecs::empty());
|
let sig = LambdaSignature::new(params.clone(), None, TypeBoundSpecs::empty());
|
||||||
|
|
@ -2778,7 +2855,8 @@ impl ASTConverter {
|
||||||
let if_ident = self.convert_ident("if".to_string(), loc);
|
let if_ident = self.convert_ident("if".to_string(), loc);
|
||||||
let if_acc = Expr::Accessor(Accessor::Ident(if_ident));
|
let if_acc = Expr::Accessor(Accessor::Ident(if_ident));
|
||||||
if !if_.orelse.is_empty() {
|
if !if_.orelse.is_empty() {
|
||||||
let else_block = self.convert_block(if_.orelse, BlockKind::If);
|
let else_block =
|
||||||
|
self.convert_block(if_.orelse, BlockKind::Else { if_block_id });
|
||||||
let sig = LambdaSignature::new(params, None, TypeBoundSpecs::empty());
|
let sig = LambdaSignature::new(params, None, TypeBoundSpecs::empty());
|
||||||
let else_body = Lambda::new(sig, Token::DUMMY, else_block, DefId(0));
|
let else_body = Lambda::new(sig, Token::DUMMY, else_block, DefId(0));
|
||||||
let args = Args::pos_only(
|
let args = Args::pos_only(
|
||||||
|
|
@ -2879,10 +2957,11 @@ impl ASTConverter {
|
||||||
self.convert_from_import(import_from.module, import_from.names, loc)
|
self.convert_from_import(import_from.module, import_from.names, loc)
|
||||||
}
|
}
|
||||||
py_ast::Stmt::Try(try_) => {
|
py_ast::Stmt::Try(try_) => {
|
||||||
|
let if_block_id = self.block_id_counter + 1;
|
||||||
let chunks = self.convert_block(try_.body, BlockKind::Try).into_iter();
|
let chunks = self.convert_block(try_.body, BlockKind::Try).into_iter();
|
||||||
let dummy = chunks
|
let dummy = chunks
|
||||||
.chain(self.convert_block(try_.orelse, BlockKind::Try))
|
.chain(self.convert_block(try_.orelse, BlockKind::Else { if_block_id }))
|
||||||
.chain(self.convert_block(try_.finalbody, BlockKind::Try))
|
.chain(self.convert_block(try_.finalbody, BlockKind::Else { if_block_id }))
|
||||||
.collect();
|
.collect();
|
||||||
Expr::Dummy(Dummy::new(None, dummy))
|
Expr::Dummy(Dummy::new(None, dummy))
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,5 @@
|
||||||
|
from typing import Literal
|
||||||
|
|
||||||
i: int = 0
|
i: int = 0
|
||||||
i: str = "a" # OK
|
i: str = "a" # OK
|
||||||
|
|
||||||
|
|
@ -37,3 +39,24 @@ if True:
|
||||||
left, right = 1, 2
|
left, right = 1, 2
|
||||||
if True:
|
if True:
|
||||||
left, _ = 1, 2
|
left, _ = 1, 2
|
||||||
|
|
||||||
|
def func(label: str) -> str:
|
||||||
|
if True:
|
||||||
|
try:
|
||||||
|
label_bytes = "aaa"
|
||||||
|
except UnicodeEncodeError:
|
||||||
|
return label
|
||||||
|
else:
|
||||||
|
label_bytes = label
|
||||||
|
|
||||||
|
if True:
|
||||||
|
label_bytes = label_bytes[1:]
|
||||||
|
return label_bytes
|
||||||
|
|
||||||
|
if True:
|
||||||
|
y = 1
|
||||||
|
else:
|
||||||
|
y = "a"
|
||||||
|
y: int | str
|
||||||
|
y: Literal[1, "a"] # OK
|
||||||
|
y: Literal[1, "b"] # ERR
|
||||||
|
|
|
||||||
|
|
@ -160,7 +160,7 @@ fn exec_decl() -> Result<(), String> {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn exec_shadowing() -> Result<(), String> {
|
fn exec_shadowing() -> Result<(), String> {
|
||||||
expect("tests/shadowing.py", 0, 3)
|
expect("tests/shadowing.py", 0, 4)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue