mirror of https://github.com/mtshiba/pylyzer
feat: support `dict/tuple` types
This commit is contained in:
parent
964a3d1284
commit
c47397c159
|
|
@ -96,6 +96,8 @@ pylyzer converts Python ASTs to Erg ASTs and passes them to Erg's type checker.
|
||||||
* [x] `Union`
|
* [x] `Union`
|
||||||
* [x] `Optional`
|
* [x] `Optional`
|
||||||
* [x] `list`
|
* [x] `list`
|
||||||
|
* [x] `dict`
|
||||||
|
* [x] `tuple`
|
||||||
* [x] `Literal`
|
* [x] `Literal`
|
||||||
* [ ] `TypedDict`
|
* [ ] `TypedDict`
|
||||||
* [ ] others
|
* [ ] others
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ use erg_compiler::erg_parser::ast::{
|
||||||
NormalTuple, ParamPattern, Params, PosArg, PreDeclTypeSpec, ReDef, Record, RecordAttrs, Set,
|
NormalTuple, ParamPattern, Params, PosArg, PreDeclTypeSpec, ReDef, Record, RecordAttrs, Set,
|
||||||
Signature, SimpleTypeSpec, SubrSignature, Tuple, TypeAscription, TypeBoundSpecs, TypeSpec,
|
Signature, SimpleTypeSpec, SubrSignature, Tuple, TypeAscription, TypeBoundSpecs, TypeSpec,
|
||||||
TypeSpecWithOp, UnaryOp, VarName, VarPattern, VarRecordAttr, VarRecordAttrs, VarRecordPattern,
|
TypeSpecWithOp, UnaryOp, VarName, VarPattern, VarRecordAttr, VarRecordAttrs, VarRecordPattern,
|
||||||
VarSignature, VisModifierSpec, ConstPosArg,
|
VarSignature, VisModifierSpec, ConstPosArg, ConstDict, ConstKeyValue, TupleTypeSpec,
|
||||||
};
|
};
|
||||||
use erg_compiler::erg_parser::desugar::Desugarer;
|
use erg_compiler::erg_parser::desugar::Desugarer;
|
||||||
use erg_compiler::erg_parser::token::{Token, TokenKind, AS, DOT, EQUAL};
|
use erg_compiler::erg_parser::token::{Token, TokenKind, AS, DOT, EQUAL};
|
||||||
|
|
@ -565,6 +565,41 @@ impl ASTConverter {
|
||||||
let len = ConstPosArg::new(len);
|
let len = ConstPosArg::new(len);
|
||||||
TypeSpec::poly(Identifier::private("Array!".into()), ConstArgs::new(vec![elem_t, len], None, vec![], None))
|
TypeSpec::poly(Identifier::private("Array!".into()), ConstArgs::new(vec![elem_t, len], None, vec![], None))
|
||||||
}
|
}
|
||||||
|
"dict" => {
|
||||||
|
let ExpressionType::Tuple { mut elements } = args.node else {
|
||||||
|
return Self::gen_dummy_type_spec(args.location);
|
||||||
|
};
|
||||||
|
let (l_brace, r_brace) = Self::gen_enclosure_tokens(TokenKind::LBrace, elements.iter(), 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 val_t = self.convert_expr(elements.remove(0));
|
||||||
|
let val_t = match Parser::validate_const_expr(val_t) {
|
||||||
|
Ok(val_t) => val_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 dict = ConstPosArg::new(ConstExpr::Dict(ConstDict::new(l_brace, r_brace, vec![ConstKeyValue::new(key_t, val_t)])));
|
||||||
|
TypeSpec::poly(Identifier::private("Dict!".into()), ConstArgs::new(vec![dict], None, vec![], None))
|
||||||
|
}
|
||||||
|
"tuple" => {
|
||||||
|
let ExpressionType::Tuple { elements } = args.node else {
|
||||||
|
return Self::gen_dummy_type_spec(args.location);
|
||||||
|
};
|
||||||
|
let parens = Self::gen_enclosure_tokens(TokenKind::LParen, elements.iter(), args.location);
|
||||||
|
let tys = elements.into_iter().map(|elem| self.convert_type_spec(elem)).collect();
|
||||||
|
let tuple = TupleTypeSpec::new(Some(parens), tys);
|
||||||
|
TypeSpec::Tuple(tuple)
|
||||||
|
}
|
||||||
_ => Self::gen_dummy_type_spec(args.location),
|
_ => Self::gen_dummy_type_spec(args.location),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -653,6 +688,7 @@ impl ASTConverter {
|
||||||
match expr.node {
|
match expr.node {
|
||||||
ExpressionType::Number { value } => {
|
ExpressionType::Number { value } => {
|
||||||
let (kind, cont) = match value {
|
let (kind, cont) = match value {
|
||||||
|
Number::Integer { value } if value >= 0.into() => (TokenKind::NatLit, value.to_string()),
|
||||||
Number::Integer { value } => (TokenKind::IntLit, value.to_string()),
|
Number::Integer { value } => (TokenKind::IntLit, value.to_string()),
|
||||||
Number::Float { value } => (TokenKind::RatioLit, value.to_string()),
|
Number::Float { value } => (TokenKind::RatioLit, value.to_string()),
|
||||||
Number::Complex { .. } => {
|
Number::Complex { .. } => {
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,13 @@ union_arr.append(None) # ERR
|
||||||
|
|
||||||
dic = {"a": 1}
|
dic = {"a": 1}
|
||||||
dic["b"] = 2
|
dic["b"] = 2
|
||||||
|
|
||||||
_ = dic["a"]
|
_ = dic["a"]
|
||||||
_ = dic["b"]
|
_ = dic["b"]
|
||||||
_ = dic["c"] # ERR
|
_ = dic["c"] # ERR
|
||||||
|
|
||||||
|
dic2: dict[str, int] = {"a": 1}
|
||||||
|
_ = dic2["c"] # OK
|
||||||
|
|
||||||
|
t: tuple[int, str] = (1, "a")
|
||||||
|
_ = t[0] == 1 # OK
|
||||||
|
_ = t[1] == 1 # ERR
|
||||||
|
|
|
||||||
|
|
@ -95,6 +95,6 @@ fn exec_casting() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn exec_collection() {
|
fn exec_collections() {
|
||||||
expect("tests/collections.py", 0, 3);
|
expect("tests/collections.py", 0, 4);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue