mirror of https://github.com/mtshiba/pylyzer
feat: fix #4
This commit is contained in:
parent
5d5b4713dd
commit
deb7382dcb
|
|
@ -253,8 +253,7 @@ checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91"
|
|||
[[package]]
|
||||
name = "els"
|
||||
version = "0.1.19-nightly.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fc21e1a7815740ad6debfd616bd9f5551dc4b10fa1b4e0e2cec42ddf57dbc7d8"
|
||||
source = "git+https://github.com/erg-lang/erg?branch=main#0f0d04202014c002fbbafa88ff9d42067d57f201"
|
||||
dependencies = [
|
||||
"erg_common",
|
||||
"erg_compiler",
|
||||
|
|
@ -275,8 +274,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "erg_common"
|
||||
version = "0.6.7-nightly.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d8d2357638900c5d5f2ee751b4fd2254932fda6a1c50939ffbc8a7acd5903ce9"
|
||||
source = "git+https://github.com/erg-lang/erg?branch=main#0f0d04202014c002fbbafa88ff9d42067d57f201"
|
||||
dependencies = [
|
||||
"backtrace-on-stack-overflow",
|
||||
"hermit-abi",
|
||||
|
|
@ -287,8 +285,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "erg_compiler"
|
||||
version = "0.6.7-nightly.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "682faa374e190771be607591426293f6fb56f22f8ed08c3d424a27615bb261cd"
|
||||
source = "git+https://github.com/erg-lang/erg?branch=main#0f0d04202014c002fbbafa88ff9d42067d57f201"
|
||||
dependencies = [
|
||||
"erg_common",
|
||||
"erg_parser",
|
||||
|
|
@ -297,8 +294,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "erg_parser"
|
||||
version = "0.6.7-nightly.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e3e3ee6c10e35b83fe0c6c675ab1697aa72d175e4d10cbcf9a8057485192a604"
|
||||
source = "git+https://github.com/erg-lang/erg?branch=main#0f0d04202014c002fbbafa88ff9d42067d57f201"
|
||||
dependencies = [
|
||||
"erg_common",
|
||||
"unicode-xid 0.2.4",
|
||||
|
|
@ -920,9 +916,9 @@ checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
|
|||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.108"
|
||||
version = "1.0.109"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d56e159d99e6c2b93995d171050271edb50ecc5288fbc7cc17de8fdce4e58c14"
|
||||
checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
|
|
|||
12
Cargo.toml
12
Cargo.toml
|
|
@ -22,13 +22,13 @@ edition = "2021"
|
|||
repository = "https://github.com/mtshiba/pylyzer"
|
||||
|
||||
[workspace.dependencies]
|
||||
erg_common = { version = "0.6.7-nightly.0", features = ["py_compatible", "els"] }
|
||||
erg_compiler = { version = "0.6.7-nightly.0", features = ["py_compatible", "els"] }
|
||||
els = { version = "0.1.19-nightly.0", features = ["py_compatible"] }
|
||||
# erg_common = { version = "0.6.7-nightly.0", features = ["py_compatible", "els"] }
|
||||
# erg_compiler = { version = "0.6.7-nightly.0", features = ["py_compatible", "els"] }
|
||||
# els = { version = "0.1.19-nightly.0", features = ["py_compatible"] }
|
||||
rustpython-parser = "0.1.2"
|
||||
# erg_compiler = { git = "https://github.com/erg-lang/erg", branch = "main", features = ["py_compatible", "els"] }
|
||||
# erg_common = { git = "https://github.com/erg-lang/erg", branch = "main", features = ["py_compatible", "els"] }
|
||||
# els = { git = "https://github.com/erg-lang/erg", branch = "main", features = ["py_compatible"] }
|
||||
erg_compiler = { git = "https://github.com/erg-lang/erg", branch = "main", features = ["py_compatible", "els"] }
|
||||
erg_common = { git = "https://github.com/erg-lang/erg", branch = "main", features = ["py_compatible", "els"] }
|
||||
els = { git = "https://github.com/erg-lang/erg", branch = "main", features = ["py_compatible"] }
|
||||
|
||||
[features]
|
||||
debug = ["erg_compiler/debug", "erg_common/debug", "py2erg/debug"]
|
||||
|
|
|
|||
|
|
@ -90,7 +90,11 @@ pylyzer converts Python ASTs to Erg ASTs and passes them to Erg's type checker.
|
|||
* [x] local scripts resolving
|
||||
* [ ] local packages resolving
|
||||
* [ ] compound type checking
|
||||
* [ ] type assertion
|
||||
* [x] `Union`
|
||||
* [x] `Optional`
|
||||
* [x] `list`
|
||||
* [ ] others
|
||||
* [ ] type assertion (`typing.cast`)
|
||||
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -6,12 +6,13 @@ use erg_common::traits::{Locational, Stream};
|
|||
use erg_common::{log, set};
|
||||
use erg_compiler::artifact::IncompleteArtifact;
|
||||
use erg_compiler::erg_parser::ast::{
|
||||
Accessor, Args, Array, BinOp, Block, ClassAttr, ClassAttrs, ClassDef, ConstArgs, Decorator,
|
||||
Def, DefBody, DefId, DefaultParamSignature, Dict, Dummy, Expr, Identifier, KeyValue, Lambda,
|
||||
LambdaSignature, Literal, Methods, Module, NonDefaultParamSignature, NormalArray, NormalDict,
|
||||
NormalRecord, NormalSet, NormalTuple, ParamPattern, Params, PosArg, PreDeclTypeSpec, ReDef,
|
||||
Record, RecordAttrs, Set, Signature, SimpleTypeSpec, SubrSignature, Tuple, TypeAscription,
|
||||
TypeBoundSpecs, TypeSpec, TypeSpecWithOp, UnaryOp, VarName, VarPattern, VarSignature,
|
||||
Accessor, Args, Array, ArrayTypeSpec, BinOp, Block, ClassAttr, ClassAttrs, ClassDef,
|
||||
ConstAccessor, ConstArgs, ConstExpr, Decorator, Def, DefBody, DefId, DefaultParamSignature,
|
||||
Dict, Dummy, Expr, Identifier, KeyValue, Lambda, LambdaSignature, Literal, Methods, Module,
|
||||
NonDefaultParamSignature, NormalArray, NormalDict, NormalRecord, NormalSet, NormalTuple,
|
||||
ParamPattern, Params, PosArg, PreDeclTypeSpec, ReDef, Record, RecordAttrs, Set, Signature,
|
||||
SimpleTypeSpec, SubrSignature, Tuple, TypeAscription, TypeBoundSpecs, TypeSpec, TypeSpecWithOp,
|
||||
UnaryOp, VarName, VarPattern, VarSignature,
|
||||
};
|
||||
use erg_compiler::erg_parser::token::{Token, TokenKind, COLON, DOT, EQUAL};
|
||||
use erg_compiler::error::CompileErrors;
|
||||
|
|
@ -502,17 +503,89 @@ impl ASTConverter {
|
|||
Lambda::new(sig, op, Block::new(body), DefId(0))
|
||||
}
|
||||
|
||||
fn convert_ident_type_spec(&mut self, name: String, loc: PyLocation) -> SimpleTypeSpec {
|
||||
SimpleTypeSpec::new(self.convert_ident(name, loc), ConstArgs::empty())
|
||||
}
|
||||
|
||||
fn gen_dummy_type_spec(loc: PyLocation) -> TypeSpec {
|
||||
TypeSpec::Infer(Token::new(
|
||||
TokenKind::UBar,
|
||||
"_",
|
||||
loc.row() as u32,
|
||||
loc.column() as u32 - 1,
|
||||
))
|
||||
}
|
||||
|
||||
// TODO:
|
||||
fn convert_compound_type_spec(
|
||||
&mut self,
|
||||
name: String,
|
||||
args: Located<ExpressionType>,
|
||||
) -> TypeSpec {
|
||||
match &name[..] {
|
||||
"Union" => {
|
||||
let ExpressionType::Tuple { mut elements } = args.node else {
|
||||
return Self::gen_dummy_type_spec(args.location);
|
||||
};
|
||||
let lhs = self.convert_type_spec(elements.remove(0));
|
||||
let rhs = self.convert_type_spec(elements.remove(0));
|
||||
TypeSpec::or(lhs, rhs)
|
||||
}
|
||||
"Optional" => {
|
||||
let loc = args.location;
|
||||
let t = self.convert_type_spec(args);
|
||||
let ident = Identifier::private_with_line("NoneType".into(), loc.row() as u32);
|
||||
let none = TypeSpec::PreDeclTy(PreDeclTypeSpec::Simple(SimpleTypeSpec::new(
|
||||
ident,
|
||||
ConstArgs::empty(),
|
||||
)));
|
||||
TypeSpec::or(t, none)
|
||||
}
|
||||
"list" => {
|
||||
let len = ConstExpr::Accessor(ConstAccessor::Local(
|
||||
self.convert_ident("_".into(), args.location),
|
||||
));
|
||||
let elem_t = self.convert_type_spec(args);
|
||||
TypeSpec::Array(ArrayTypeSpec::new(elem_t, len))
|
||||
}
|
||||
_ => Self::gen_dummy_type_spec(args.location),
|
||||
}
|
||||
}
|
||||
|
||||
fn convert_type_spec(&mut self, expr: Located<ExpressionType>) -> TypeSpec {
|
||||
#[allow(clippy::collapsible_match)]
|
||||
match expr.node {
|
||||
ExpressionType::Identifier { name } => TypeSpec::PreDeclTy(PreDeclTypeSpec::Simple(
|
||||
SimpleTypeSpec::new(self.convert_ident(name, expr.location), ConstArgs::empty()),
|
||||
)),
|
||||
_other => TypeSpec::Infer(Token::new(
|
||||
TokenKind::UBar,
|
||||
"_",
|
||||
expr.location.row() as u32,
|
||||
expr.location.column() as u32 - 1,
|
||||
self.convert_ident_type_spec(name, expr.location),
|
||||
)),
|
||||
ExpressionType::Attribute { value, name } => {
|
||||
let namespace = Box::new(self.convert_expr(*value));
|
||||
let t = self.convert_ident_type_spec(name, expr.location);
|
||||
let predecl = PreDeclTypeSpec::Attr { namespace, t };
|
||||
TypeSpec::PreDeclTy(predecl)
|
||||
}
|
||||
ExpressionType::Subscript { a, b } => match a.node {
|
||||
ExpressionType::Identifier { name } => self.convert_compound_type_spec(name, *b),
|
||||
other => {
|
||||
log!(err "unknown: {other:?}");
|
||||
Self::gen_dummy_type_spec(a.location)
|
||||
}
|
||||
},
|
||||
ExpressionType::Binop { a, op, b } => {
|
||||
match op {
|
||||
// A | B
|
||||
Operator::BitOr => {
|
||||
let lhs = self.convert_type_spec(*a);
|
||||
let rhs = self.convert_type_spec(*b);
|
||||
TypeSpec::or(lhs, rhs)
|
||||
}
|
||||
_ => Self::gen_dummy_type_spec(expr.location),
|
||||
}
|
||||
}
|
||||
other => {
|
||||
log!(err "unknown: {other:?}");
|
||||
Self::gen_dummy_type_spec(expr.location)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -70,3 +70,8 @@ fn exec_errors() {
|
|||
fn exec_warns() {
|
||||
expect("tests/warns.py", 2, 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn exec_typespec() {
|
||||
expect("tests/typespec.py", 0, 2);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,8 @@
|
|||
from typing import Union, Optional
|
||||
|
||||
i: Union[int, str] = 1 # OK
|
||||
j: Union[int, str] = "aa" # OK
|
||||
k: Union[list[int], str] = 1 # ERR
|
||||
l: Union[list[int], str] = [1] # OK
|
||||
o: Optional[int] = None # OK
|
||||
p: Optional[int] = "a" # ERR
|
||||
Loading…
Reference in New Issue