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]]
|
[[package]]
|
||||||
name = "els"
|
name = "els"
|
||||||
version = "0.1.19-nightly.0"
|
version = "0.1.19-nightly.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "git+https://github.com/erg-lang/erg?branch=main#0f0d04202014c002fbbafa88ff9d42067d57f201"
|
||||||
checksum = "fc21e1a7815740ad6debfd616bd9f5551dc4b10fa1b4e0e2cec42ddf57dbc7d8"
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"erg_common",
|
"erg_common",
|
||||||
"erg_compiler",
|
"erg_compiler",
|
||||||
|
|
@ -275,8 +274,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "erg_common"
|
name = "erg_common"
|
||||||
version = "0.6.7-nightly.0"
|
version = "0.6.7-nightly.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "git+https://github.com/erg-lang/erg?branch=main#0f0d04202014c002fbbafa88ff9d42067d57f201"
|
||||||
checksum = "d8d2357638900c5d5f2ee751b4fd2254932fda6a1c50939ffbc8a7acd5903ce9"
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"backtrace-on-stack-overflow",
|
"backtrace-on-stack-overflow",
|
||||||
"hermit-abi",
|
"hermit-abi",
|
||||||
|
|
@ -287,8 +285,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "erg_compiler"
|
name = "erg_compiler"
|
||||||
version = "0.6.7-nightly.0"
|
version = "0.6.7-nightly.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "git+https://github.com/erg-lang/erg?branch=main#0f0d04202014c002fbbafa88ff9d42067d57f201"
|
||||||
checksum = "682faa374e190771be607591426293f6fb56f22f8ed08c3d424a27615bb261cd"
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"erg_common",
|
"erg_common",
|
||||||
"erg_parser",
|
"erg_parser",
|
||||||
|
|
@ -297,8 +294,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "erg_parser"
|
name = "erg_parser"
|
||||||
version = "0.6.7-nightly.0"
|
version = "0.6.7-nightly.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "git+https://github.com/erg-lang/erg?branch=main#0f0d04202014c002fbbafa88ff9d42067d57f201"
|
||||||
checksum = "e3e3ee6c10e35b83fe0c6c675ab1697aa72d175e4d10cbcf9a8057485192a604"
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"erg_common",
|
"erg_common",
|
||||||
"unicode-xid 0.2.4",
|
"unicode-xid 0.2.4",
|
||||||
|
|
@ -920,9 +916,9 @@ checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
version = "1.0.108"
|
version = "1.0.109"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d56e159d99e6c2b93995d171050271edb50ecc5288fbc7cc17de8fdce4e58c14"
|
checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
|
|
|
||||||
12
Cargo.toml
12
Cargo.toml
|
|
@ -22,13 +22,13 @@ edition = "2021"
|
||||||
repository = "https://github.com/mtshiba/pylyzer"
|
repository = "https://github.com/mtshiba/pylyzer"
|
||||||
|
|
||||||
[workspace.dependencies]
|
[workspace.dependencies]
|
||||||
erg_common = { version = "0.6.7-nightly.0", features = ["py_compatible", "els"] }
|
# erg_common = { version = "0.6.7-nightly.0", features = ["py_compatible", "els"] }
|
||||||
erg_compiler = { 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"] }
|
# els = { version = "0.1.19-nightly.0", features = ["py_compatible"] }
|
||||||
rustpython-parser = "0.1.2"
|
rustpython-parser = "0.1.2"
|
||||||
# erg_compiler = { git = "https://github.com/erg-lang/erg", branch = "main", features = ["py_compatible", "els"] }
|
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"] }
|
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"] }
|
els = { git = "https://github.com/erg-lang/erg", branch = "main", features = ["py_compatible"] }
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
debug = ["erg_compiler/debug", "erg_common/debug", "py2erg/debug"]
|
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
|
* [x] local scripts resolving
|
||||||
* [ ] local packages resolving
|
* [ ] local packages resolving
|
||||||
* [ ] compound type checking
|
* [ ] 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_common::{log, set};
|
||||||
use erg_compiler::artifact::IncompleteArtifact;
|
use erg_compiler::artifact::IncompleteArtifact;
|
||||||
use erg_compiler::erg_parser::ast::{
|
use erg_compiler::erg_parser::ast::{
|
||||||
Accessor, Args, Array, BinOp, Block, ClassAttr, ClassAttrs, ClassDef, ConstArgs, Decorator,
|
Accessor, Args, Array, ArrayTypeSpec, BinOp, Block, ClassAttr, ClassAttrs, ClassDef,
|
||||||
Def, DefBody, DefId, DefaultParamSignature, Dict, Dummy, Expr, Identifier, KeyValue, Lambda,
|
ConstAccessor, ConstArgs, ConstExpr, Decorator, Def, DefBody, DefId, DefaultParamSignature,
|
||||||
LambdaSignature, Literal, Methods, Module, NonDefaultParamSignature, NormalArray, NormalDict,
|
Dict, Dummy, Expr, Identifier, KeyValue, Lambda, LambdaSignature, Literal, Methods, Module,
|
||||||
NormalRecord, NormalSet, NormalTuple, ParamPattern, Params, PosArg, PreDeclTypeSpec, ReDef,
|
NonDefaultParamSignature, NormalArray, NormalDict, NormalRecord, NormalSet, NormalTuple,
|
||||||
Record, RecordAttrs, Set, Signature, SimpleTypeSpec, SubrSignature, Tuple, TypeAscription,
|
ParamPattern, Params, PosArg, PreDeclTypeSpec, ReDef, Record, RecordAttrs, Set, Signature,
|
||||||
TypeBoundSpecs, TypeSpec, TypeSpecWithOp, UnaryOp, VarName, VarPattern, VarSignature,
|
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::erg_parser::token::{Token, TokenKind, COLON, DOT, EQUAL};
|
||||||
use erg_compiler::error::CompileErrors;
|
use erg_compiler::error::CompileErrors;
|
||||||
|
|
@ -502,17 +503,89 @@ impl ASTConverter {
|
||||||
Lambda::new(sig, op, Block::new(body), DefId(0))
|
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 {
|
fn convert_type_spec(&mut self, expr: Located<ExpressionType>) -> TypeSpec {
|
||||||
|
#[allow(clippy::collapsible_match)]
|
||||||
match expr.node {
|
match expr.node {
|
||||||
ExpressionType::Identifier { name } => TypeSpec::PreDeclTy(PreDeclTypeSpec::Simple(
|
ExpressionType::Identifier { name } => TypeSpec::PreDeclTy(PreDeclTypeSpec::Simple(
|
||||||
SimpleTypeSpec::new(self.convert_ident(name, expr.location), ConstArgs::empty()),
|
self.convert_ident_type_spec(name, expr.location),
|
||||||
)),
|
|
||||||
_other => TypeSpec::Infer(Token::new(
|
|
||||||
TokenKind::UBar,
|
|
||||||
"_",
|
|
||||||
expr.location.row() as u32,
|
|
||||||
expr.location.column() as u32 - 1,
|
|
||||||
)),
|
)),
|
||||||
|
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() {
|
fn exec_warns() {
|
||||||
expect("tests/warns.py", 2, 0);
|
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