feat: support Iterator/Sequence/Mapping

This commit is contained in:
Shunsuke Shibayama 2023-05-10 00:06:10 +09:00
parent fae74465fb
commit 2c8067da95
6 changed files with 79 additions and 24 deletions

32
Cargo.lock generated
View file

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

View file

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

View file

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

View file

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

View file

@ -76,7 +76,7 @@ fn exec_warns() {
#[test]
fn exec_typespec() {
expect("tests/typespec.py", 0, 6);
expect("tests/typespec.py", 0, 7);
}
#[test]

View file

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