mirror of
https://github.com/mtshiba/pylyzer.git
synced 2025-08-04 14:28:24 +00:00
feat: support Iterator/Sequence/Mapping
This commit is contained in:
parent
fae74465fb
commit
2c8067da95
6 changed files with 79 additions and 24 deletions
32
Cargo.lock
generated
32
Cargo.lock
generated
|
@ -252,9 +252,9 @@ checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91"
|
|||
|
||||
[[package]]
|
||||
name = "els"
|
||||
version = "0.1.24-nightly.6"
|
||||
version = "0.1.25-nightly.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3db3f0318812d7401d51a3232f256faaa15963f30f4bf7bc07dc8bc73b849353"
|
||||
checksum = "b2718d575740fbdcd8f91262e3f3c100190ee74344c22a58b8bb201b91a5b4aa"
|
||||
dependencies = [
|
||||
"erg_common",
|
||||
"erg_compiler",
|
||||
|
@ -274,9 +274,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "erg_common"
|
||||
version = "0.6.12"
|
||||
version = "0.6.13-nightly.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "66b4ff41ccf97d9c20f0e94a45c50ffc26f612cbb09202179f5df9dc3bca3283"
|
||||
checksum = "a9ffa2366ff45440b95e7854897574238b17e2ceeae419563f6eacb764dd294e"
|
||||
dependencies = [
|
||||
"backtrace-on-stack-overflow",
|
||||
"hermit-abi",
|
||||
|
@ -286,9 +286,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "erg_compiler"
|
||||
version = "0.6.12"
|
||||
version = "0.6.13-nightly.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "37116c511348405b7f8c16a4083115fd0950715dbf8b09e2396b05356933f071"
|
||||
checksum = "920553db0288f2d09ca30f218aeb810874071e898963591b0b3b2fc13ea7b8a6"
|
||||
dependencies = [
|
||||
"erg_common",
|
||||
"erg_parser",
|
||||
|
@ -296,9 +296,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "erg_parser"
|
||||
version = "0.6.12"
|
||||
version = "0.6.13-nightly.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7320f26c6d1eec2f30133ba32799feee9a329953e0635b369071b61b1ca4b715"
|
||||
checksum = "f6c591017fbe24f97c1bcc7b8a0ba52c68129c9a039ac169c12e804703f94a4b"
|
||||
dependencies = [
|
||||
"erg_common",
|
||||
"unicode-xid 0.2.4",
|
||||
|
@ -430,9 +430,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
|||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.142"
|
||||
version = "0.2.144"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6a987beff54b60ffa6d51982e1aa1146bc42f19bd26be28b0586f252fccf5317"
|
||||
checksum = "2b00cc1c228a6782d0f076e7b232802e0c5689d41bb5df366f2a6b6621cfdfe1"
|
||||
|
||||
[[package]]
|
||||
name = "log"
|
||||
|
@ -622,9 +622,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.26"
|
||||
version = "1.0.27"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4424af4bf778aae2051a77b60283332f386554255d722233d09fbfc7e30da2fc"
|
||||
checksum = "8f4f29d145265ec1c483c7c654450edde0bfe043d3938d6972630663356d9500"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
@ -826,18 +826,18 @@ checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041"
|
|||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.160"
|
||||
version = "1.0.162"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bb2f3770c8bce3bcda7e149193a069a0f4365bda1fa5cd88e03bca26afc1216c"
|
||||
checksum = "71b2f6e1ab5c2b98c05f0f35b236b22e8df7ead6ffbf51d7808da7f8817e7ab6"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.160"
|
||||
version = "1.0.162"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "291a097c63d8497e00160b166a967a4a79c64f3facdd01cbd7502231688d77df"
|
||||
checksum = "a2a0814352fd64b58489904a44ea8d90cb1a91dcb6b4f5ebabc32c8318e93cb6"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
|
|
@ -22,9 +22,9 @@ edition = "2021"
|
|||
repository = "https://github.com/mtshiba/pylyzer"
|
||||
|
||||
[workspace.dependencies]
|
||||
erg_common = { version = "0.6.12", features = ["py_compat", "els"] }
|
||||
erg_compiler = { version = "0.6.12", features = ["py_compat", "els"] }
|
||||
els = { version = "0.1.24-nightly.6", features = ["py_compat"] }
|
||||
erg_common = { version = "0.6.13-nightly.2", features = ["py_compat", "els"] }
|
||||
erg_compiler = { version = "0.6.13-nightly.2", features = ["py_compat", "els"] }
|
||||
els = { version = "0.1.25-nightly.2", features = ["py_compat"] }
|
||||
rustpython-parser = "0.1.2"
|
||||
# erg_compiler = { git = "https://github.com/erg-lang/erg", branch = "main", features = ["py_compat", "els"] }
|
||||
# erg_common = { git = "https://github.com/erg-lang/erg", branch = "main", features = ["py_compat", "els"] }
|
||||
|
|
|
@ -120,3 +120,13 @@ pub fn length(expr: &ExpressionType) -> usize {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn accessor_name(expr: ExpressionType) -> Option<String> {
|
||||
match expr {
|
||||
ExpressionType::Identifier { name } => Some(name),
|
||||
ExpressionType::Attribute { value, name } => {
|
||||
accessor_name(value.node).map(|value| format!("{value}.{name}"))
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,7 +25,7 @@ use rustpython_parser::ast::{
|
|||
Program, StatementType, StringGroup, Suite, UnaryOperator,
|
||||
};
|
||||
|
||||
use crate::ast_util::length;
|
||||
use crate::ast_util::{length, accessor_name};
|
||||
use crate::clone::clone_loc_expr;
|
||||
use crate::error::*;
|
||||
|
||||
|
@ -88,6 +88,8 @@ fn escape_name(name: String) -> String {
|
|||
"tuple" => "GenericTuple".into(),
|
||||
"type" => "Type".into(),
|
||||
"ModuleType" => "GeneticModule".into(),
|
||||
"MutableSequence" => "Sequence!".into(),
|
||||
"MutableMapping" => "Mapping!".into(),
|
||||
_ => name,
|
||||
}
|
||||
}
|
||||
|
@ -581,7 +583,8 @@ impl ASTConverter {
|
|||
let ret = self.convert_type_spec(elements.remove(0));
|
||||
TypeSpec::Subr(SubrTypeSpec::new(TypeBoundSpecs::empty(), None, non_defaults, None, vec![], ARROW, ret))
|
||||
}
|
||||
"Iterable" => {
|
||||
"Iterable" | "Iterator" | "Collection" | "Container"
|
||||
| "Sequence" | "MutableSequence" => {
|
||||
let elem_t = self.convert_expr(args);
|
||||
let elem_t = match Parser::validate_const_expr(elem_t) {
|
||||
Ok(elem_t) => elem_t,
|
||||
|
@ -593,9 +596,37 @@ impl ASTConverter {
|
|||
};
|
||||
let elem_t = ConstPosArg::new(elem_t);
|
||||
let global = ConstExpr::Accessor(ConstAccessor::Local(Identifier::private("global".into())));
|
||||
let acc = ConstAccessor::Attr(ConstAttribute::new(global, Identifier::private("Iterable".into())));
|
||||
let acc = ConstAccessor::Attr(ConstAttribute::new(global, Identifier::private(escape_name(name).into())));
|
||||
TypeSpec::poly(acc, ConstArgs::pos_only(vec![elem_t], None))
|
||||
}
|
||||
"Mapping" | "MutableMapping" => {
|
||||
let ExpressionType::Tuple { mut elements } = args.node else {
|
||||
return Self::gen_dummy_type_spec(args.location);
|
||||
};
|
||||
let key_t = self.convert_expr(elements.remove(0));
|
||||
let key_t = match Parser::validate_const_expr(key_t) {
|
||||
Ok(key_t) => key_t,
|
||||
Err(err) => {
|
||||
let err = CompileError::new(err.into(), self.cfg.input.clone(), self.cur_namespace());
|
||||
self.errs.push(err);
|
||||
ConstExpr::Accessor(ConstAccessor::Local(Identifier::private("Obj".into())))
|
||||
}
|
||||
};
|
||||
let key_t = ConstPosArg::new(key_t);
|
||||
let value_t = self.convert_expr(elements.remove(0));
|
||||
let value_t = match Parser::validate_const_expr(value_t) {
|
||||
Ok(value_t) => value_t,
|
||||
Err(err) => {
|
||||
let err = CompileError::new(err.into(), self.cfg.input.clone(), self.cur_namespace());
|
||||
self.errs.push(err);
|
||||
ConstExpr::Accessor(ConstAccessor::Local(Identifier::private("Obj".into())))
|
||||
}
|
||||
};
|
||||
let value_t = ConstPosArg::new(value_t);
|
||||
let global = ConstExpr::Accessor(ConstAccessor::Local(Identifier::private("global".into())));
|
||||
let acc = ConstAccessor::Attr(ConstAttribute::new(global, Identifier::private(escape_name(name).into())));
|
||||
TypeSpec::poly(acc, ConstArgs::pos_only(vec![key_t, value_t], None))
|
||||
}
|
||||
"list" => {
|
||||
let len = ConstExpr::Accessor(ConstAccessor::Local(
|
||||
self.convert_ident("_".into(), args.location),
|
||||
|
@ -669,6 +700,17 @@ impl ASTConverter {
|
|||
}
|
||||
ExpressionType::Subscript { a, b } => match a.node {
|
||||
ExpressionType::Identifier { name } => self.convert_compound_type_spec(name, *b),
|
||||
ExpressionType::Attribute { value, name } => {
|
||||
match accessor_name(value.node).as_ref().map(|s| &s[..]) {
|
||||
Some("typing" | "collections.abc") => {
|
||||
self.convert_compound_type_spec(name, *b)
|
||||
},
|
||||
_ => {
|
||||
log!(err "unknown: .{name}");
|
||||
Self::gen_dummy_type_spec(a.location)
|
||||
}
|
||||
}
|
||||
}
|
||||
other => {
|
||||
log!(err "unknown: {other:?}");
|
||||
Self::gen_dummy_type_spec(a.location)
|
||||
|
|
|
@ -76,7 +76,7 @@ fn exec_warns() {
|
|||
|
||||
#[test]
|
||||
fn exec_typespec() {
|
||||
expect("tests/typespec.py", 0, 6);
|
||||
expect("tests/typespec.py", 0, 7);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
from typing import Union, Optional, Literal, Callable
|
||||
from collections.abc import Iterable
|
||||
from collections.abc import Iterable, Mapping
|
||||
|
||||
i: Union[int, str] = 1 # OK
|
||||
j: Union[int, str] = "aa" # OK
|
||||
|
@ -26,3 +26,6 @@ _: Iterable[int] = [1] # OK
|
|||
_: Iterable[int] = {1} # OK
|
||||
_: Iterable[int] = (1, 2) # OK
|
||||
_: Iterable[int] = ["a"] # ERR
|
||||
|
||||
_: Mapping[str, int] = {"a": 1, "c": 2} # OK
|
||||
_: Mapping[str, int] = {1: "a", 2: "b"} # ERR
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue