fix: incorrect typing & method resolution

This commit is contained in:
Shunsuke Shibayama 2024-09-26 11:34:15 +09:00
parent 21caf6fe7e
commit a129141234
6 changed files with 178 additions and 79 deletions

View file

@ -87,6 +87,13 @@ impl Context {
Some(FUNDAMENTAL_FORMAT), Some(FUNDAMENTAL_FORMAT),
14, 14,
); );
obj.register_builtin_py_impl(
FUNDAMENTAL_CALL,
func0(Obj),
Immutable,
Visibility::BUILTIN_PUBLIC,
Some(FUNDAMENTAL_CALL),
);
// Obj does not implement Eq // Obj does not implement Eq
let mut complex = Self::builtin_mono_class(COMPLEX, 2); let mut complex = Self::builtin_mono_class(COMPLEX, 2);
complex.register_superclass(Obj, &obj); complex.register_superclass(Obj, &obj);

View file

@ -351,8 +351,8 @@ impl Context {
) )
.quantify(); .quantify();
let t_slice = no_var_func( let t_slice = no_var_func(
vec![kw(KW_START, Int)], vec![kw(KW_START, Int | NoneType)],
vec![kw(KW_STOP, Int), kw(KW_STEP, Int)], vec![kw(KW_STOP, Int | NoneType), kw(KW_STEP, Int | NoneType)],
mono(SLICE), mono(SLICE),
); );
let t_sorted = nd_func( let t_sorted = nd_func(
@ -975,6 +975,40 @@ impl Context {
Visibility::BUILTIN_PUBLIC, Visibility::BUILTIN_PUBLIC,
None, None,
); );
let t_exec = func(
vec![kw(KW_CODE, Str)],
None,
vec![
kw(KW_GLOBALS, mono(GENERIC_DICT)),
kw(KW_LOCALS, mono(GENERIC_DICT)),
],
None,
NoneType,
);
self.register_builtin_py_impl(
FUNC_EXEC,
t_exec,
Immutable,
Visibility::BUILTIN_PUBLIC,
Some(FUNC_EXEC),
);
let t_eval = func(
vec![kw(KW_CODE, Str)],
None,
vec![
kw(KW_GLOBALS, mono(GENERIC_DICT)),
kw(KW_LOCALS, mono(GENERIC_DICT)),
],
None,
NoneType,
);
self.register_builtin_py_impl(
FUNC_EVAL,
t_eval,
Immutable,
Visibility::BUILTIN_PUBLIC,
Some(FUNC_EVAL),
);
} }
pub(super) fn init_builtin_operators(&mut self) { pub(super) fn init_builtin_operators(&mut self) {

View file

@ -547,6 +547,8 @@ const FUNC_HASATTR: &str = "hasattr";
const FUNC_GETATTR: &str = "getattr"; const FUNC_GETATTR: &str = "getattr";
const FUNC_SETATTR: &str = "setattr"; const FUNC_SETATTR: &str = "setattr";
const FUNC_DELATTR: &str = "delattr"; const FUNC_DELATTR: &str = "delattr";
const FUNC_EXEC: &str = "exec";
const FUNC_EVAL: &str = "eval";
const FUNC_NEARLY_EQ: &str = "nearly_eq"; const FUNC_NEARLY_EQ: &str = "nearly_eq";
const FUNC_RESOLVE_PATH: &str = "ResolvePath"; const FUNC_RESOLVE_PATH: &str = "ResolvePath";
const FUNC_RESOLVE_DECL_PATH: &str = "ResolveDeclPath"; const FUNC_RESOLVE_DECL_PATH: &str = "ResolveDeclPath";
@ -732,6 +734,8 @@ const KW_NUMBER: &str = "number";
const KW_ITERABLE1: &str = "iterable1"; const KW_ITERABLE1: &str = "iterable1";
const KW_ITERABLE2: &str = "iterable2"; const KW_ITERABLE2: &str = "iterable2";
const KW_CODE: &str = "code"; const KW_CODE: &str = "code";
const KW_GLOBALS: &str = "globals";
const KW_LOCALS: &str = "locals";
const KW_STOP: &str = "stop"; const KW_STOP: &str = "stop";
const KW_STEP: &str = "step"; const KW_STEP: &str = "step";
const KW_REQUIREMENT: &str = "Requirement"; const KW_REQUIREMENT: &str = "Requirement";

View file

@ -273,6 +273,11 @@ impl Context {
}) })
} }
/// ```erg
/// get_singular_ctxs_by_hir_expr(1) == Err
/// get_singular_ctxs_by_hir_expr(Int) == [<type Int>, <type Type>, ...]
/// get_singular_ctxs_by_hir_expr(math) == [<module math>]
/// ```
pub fn get_singular_ctxs_by_hir_expr( pub fn get_singular_ctxs_by_hir_expr(
&self, &self,
obj: &hir::Expr, obj: &hir::Expr,
@ -1342,6 +1347,20 @@ impl Context {
} }
_ => {} _ => {}
} }
if let Ok(singular_ctxs) = self.get_singular_ctxs_by_hir_expr(obj, namespace) {
for ctx in singular_ctxs {
if let Some(vi) = ctx.get_current_scope_non_param(&attr_name.name) {
self.validate_visibility(attr_name, vi, input, namespace)?;
return Ok(vi.clone());
}
for method_ctx in ctx.methods_list.iter() {
if let Some(vi) = method_ctx.get_current_scope_non_param(&attr_name.name) {
self.validate_visibility(attr_name, vi, input, namespace)?;
return Ok(vi.clone());
}
}
}
}
for ctx in self for ctx in self
.get_nominal_super_type_ctxs(obj.ref_t()) .get_nominal_super_type_ctxs(obj.ref_t())
.ok_or_else(|| { .ok_or_else(|| {
@ -1376,30 +1395,6 @@ impl Context {
} }
} }
} }
if let Ok(singular_ctxs) = self.get_singular_ctxs_by_hir_expr(obj, namespace) {
for ctx in singular_ctxs {
if let Some(vi) = ctx.get_current_scope_non_param(&attr_name.name) {
self.validate_visibility(attr_name, vi, input, namespace)?;
return Ok(vi.clone());
}
for method_ctx in ctx.methods_list.iter() {
if let Some(vi) = method_ctx.get_current_scope_non_param(&attr_name.name) {
self.validate_visibility(attr_name, vi, input, namespace)?;
return Ok(vi.clone());
}
}
}
return Err(TyCheckError::singular_no_attr_error(
self.cfg.input.clone(),
line!() as usize,
attr_name.loc(),
namespace.name.to_string(),
obj.qual_name().as_deref().unwrap_or("?"),
obj.ref_t(),
attr_name.inspect(),
self.get_similar_attr_from_singular(obj, attr_name.inspect()),
));
}
match self.get_attr_type_by_name(obj, attr_name, namespace) { match self.get_attr_type_by_name(obj, attr_name, namespace) {
Triple::Ok(method) => { Triple::Ok(method) => {
let def_t = self let def_t = self
@ -1436,7 +1431,7 @@ impl Context {
); );
return Ok(vi); return Ok(vi);
} }
} } else {
for patch in self.find_patches_of(obj.ref_t()) { for patch in self.find_patches_of(obj.ref_t()) {
if let Some(vi) = patch.get_current_scope_non_param(&attr_name.name) { if let Some(vi) = patch.get_current_scope_non_param(&attr_name.name) {
self.validate_visibility(attr_name, vi, input, namespace)?; self.validate_visibility(attr_name, vi, input, namespace)?;
@ -1449,6 +1444,7 @@ impl Context {
} }
} }
} }
}
let coerced = self let coerced = self
.coerce(obj.t(), &()) .coerce(obj.t(), &())
.map_err(|mut errs| errs.remove(0))?; .map_err(|mut errs| errs.remove(0))?;
@ -1487,6 +1483,20 @@ impl Context {
} }
_ => {} _ => {}
} }
if let Ok(singular_ctxs) = self.get_singular_ctxs_by_hir_expr(obj, namespace) {
for ctx in singular_ctxs {
if let Some(vi) = ctx.get_current_scope_callable(&attr_name.name) {
self.validate_visibility(attr_name, vi, input, namespace)?;
return Ok(vi.clone());
}
for method_ctx in ctx.methods_list.iter() {
if let Some(vi) = method_ctx.get_current_scope_callable(&attr_name.name) {
self.validate_visibility(attr_name, vi, input, namespace)?;
return Ok(vi.clone());
}
}
}
}
for ctx in self for ctx in self
.get_nominal_super_type_ctxs(obj.ref_t()) .get_nominal_super_type_ctxs(obj.ref_t())
.ok_or_else(|| { .ok_or_else(|| {
@ -1521,30 +1531,6 @@ impl Context {
} }
} }
} }
if let Ok(singular_ctxs) = self.get_singular_ctxs_by_hir_expr(obj, namespace) {
for ctx in singular_ctxs {
if let Some(vi) = ctx.get_current_scope_callable(&attr_name.name) {
self.validate_visibility(attr_name, vi, input, namespace)?;
return Ok(vi.clone());
}
for method_ctx in ctx.methods_list.iter() {
if let Some(vi) = method_ctx.get_current_scope_callable(&attr_name.name) {
self.validate_visibility(attr_name, vi, input, namespace)?;
return Ok(vi.clone());
}
}
}
return Err(TyCheckError::singular_no_attr_error(
self.cfg.input.clone(),
line!() as usize,
attr_name.loc(),
namespace.name.to_string(),
obj.qual_name().as_deref().unwrap_or("?"),
obj.ref_t(),
attr_name.inspect(),
self.get_similar_attr_from_singular(obj, attr_name.inspect()),
));
}
match self.get_attr_type_by_name(obj, attr_name, namespace) { match self.get_attr_type_by_name(obj, attr_name, namespace) {
Triple::Ok(method) => { Triple::Ok(method) => {
let def_t = self let def_t = self
@ -1581,7 +1567,7 @@ impl Context {
); );
return Ok(vi); return Ok(vi);
} }
} } else {
for patch in self.find_patches_of(obj.ref_t()) { for patch in self.find_patches_of(obj.ref_t()) {
if let Some(vi) = patch.get_current_scope_callable(&attr_name.name) { if let Some(vi) = patch.get_current_scope_callable(&attr_name.name) {
self.validate_visibility(attr_name, vi, input, namespace)?; self.validate_visibility(attr_name, vi, input, namespace)?;
@ -1594,6 +1580,7 @@ impl Context {
} }
} }
} }
}
let coerced = self let coerced = self
.coerce(obj.t(), &()) .coerce(obj.t(), &())
.map_err(|mut errs| errs.remove(0))?; .map_err(|mut errs| errs.remove(0))?;
@ -2824,7 +2811,7 @@ impl Context {
) )
} }
pub(crate) fn get_similar_attr_from_singular<'a>( pub(crate) fn _get_similar_attr_from_singular<'a>(
&'a self, &'a self,
obj: &hir::Expr, obj: &hir::Expr,
name: &str, name: &str,
@ -3023,6 +3010,10 @@ impl Context {
opt_max opt_max
} }
/// ```erg
/// get_nominal_super_type_ctx(Nat) == [<Nat>, <Int>, <Float>, ..., <Obj>, <Eq>, ...]
/// get_nominal_super_type_ctx({Nat}) == [<Type>, <Obj>, <Eq>, ...]
/// ```
pub fn get_nominal_super_type_ctxs<'a>(&'a self, t: &Type) -> Option<Vec<&'a TypeContext>> { pub fn get_nominal_super_type_ctxs<'a>(&'a self, t: &Type) -> Option<Vec<&'a TypeContext>> {
match t { match t {
Type::FreeVar(fv) if fv.is_linked() => self.get_nominal_super_type_ctxs(&fv.crack()), Type::FreeVar(fv) if fv.is_linked() => self.get_nominal_super_type_ctxs(&fv.crack()),

View file

@ -8,21 +8,21 @@
.TypeAlias: ClassType .TypeAlias: ClassType
.Tuple: ClassType .Tuple: ClassType
.Tuple. .Tuple.
__getitem__: (*Type) -> Type __getitem__: (HomogenousTuple Type) -> Type
.Union: ClassType .Union: ClassType
.Union. .Union.
__getitem__: (*Type) -> Type __getitem__: (HomogenousTuple Type) -> Type
.Optional: ClassType .Optional: ClassType
.Optional. .Optional.
__getitem__: (Type) -> Type __getitem__: (HomogenousTuple Type) -> Type
.Callable: ClassType .Callable: ClassType
.Callable. .Callable.
__getitem__: (params: [Type; _], Type) -> Type __getitem__: (HomogenousTuple Type) -> Type
.Concatenate: (*Type) -> Type .Concatenate: (*Type) -> Type
.Type: (Type) -> Type .Type: (Type) -> Type
.Literal: ClassType .Literal: ClassType
.Literal. .Literal.
__getitem__: (*Obj) -> Type __getitem__: (HomogenousTuple Obj) -> Type
.ClassVar: (Type) -> Type .ClassVar: (Type) -> Type
.Final: (Type) -> Type .Final: (Type) -> Type
.Required: (Type) -> Type .Required: (Type) -> Type
@ -64,24 +64,42 @@
.AnyStr: ClassType .AnyStr: ClassType
.Protocol: (Type := NoneType) -> Type .Protocol: (Type := NoneType) -> Type
.NamedTuple: ClassType .NamedTuple: ClassType
.NamedTuple.
__call__: (typename: Str, it := global::Iterable(Obj)) -> Type
.NewType: ClassType .NewType: ClassType
.NewType. .NewType.
__module__: Str __module__: Str
__name__: Str __name__: Str
__supertype__: Type __supertype__: Type
__call__: (name: Str, tp: Type) -> NewType __call__: (name: Str, tp: Type) -> NewType
.TypedDict: (Str, Type) -> Type .TypedDict: (typename: Str, it := global::Iterable(Obj)) -> Type
.Dict: (Type, Type) -> Type .Dict: (Type, Type) -> Type
.List: (Type) -> Type .List: (Type) -> Type
.Set: (Type) -> Type .Set: (Type) -> Type
.FrozenSet: (Type) -> Type .FrozenSet: (Type) -> ClassType
.OrderedDict: (Type, Type) -> Type .FrozenSet.
__getitem__: Type -> Type
.OrderedDict: (Type, Type) -> ClassType
.OrderedDict.
__getitem__: (kv: (Type, Type)) -> Type
.ChainMap: (Type, Type) -> Type .ChainMap: (Type, Type) -> Type
.Counter: (Type, Int) -> Type .Counter: (Type, Int) -> Type
.Deque: (Type) -> Type .Deque: (T: Type) -> ClassType
.IO: ClassType .Deque.
__call__: |T|(iter: global::Iterable(T)) -> Deque T
__getitem__: (Type) -> Type
.IO: Type -> ClassType
.IO.
__call__: () -> IO Obj
__getitem__: (Type) -> Type
.TextIO: ClassType .TextIO: ClassType
.TextIO <: IO Str
.TextIO.
__call__: () -> TextIO
.BinaryIO: ClassType .BinaryIO: ClassType
.BinaryIO <: IO Bytes
.BinaryIO.
__call__: () -> BinaryIO
.Pattern: ClassType .Pattern: ClassType
.Match: ClassType .Match: ClassType
.Text: ClassType .Text: ClassType
@ -127,20 +145,40 @@
.KeysView: ClassType .KeysView: ClassType
.Mapping: ClassType .Mapping: ClassType
.Mapping. .Mapping.
__getitem__: (Type, Type) -> Type __getitem__: (kv: (Type, Type)) -> Type
.MappingView: ClassType .MappingView: ClassType
.MappingView.
__getitem__: (Type) -> Type
.MutableMapping: ClassType .MutableMapping: ClassType
.MutableMapping.
__getitem__: (kv: (Type, Type)) -> Type
.MutableSequence: ClassType .MutableSequence: ClassType
.MutableSequence.
__getitem__: Type -> Type
.MutableSet: ClassType .MutableSet: ClassType
.MutableSet.
__getitem__: Type -> Type
.Sized: ClassType .Sized: ClassType
.ValuesView: ClassType .ValuesView: ClassType
.Awaitable: ClassType .Awaitable: ClassType
.AsyncIterator: ClassType .AsyncIterator: ClassType
.AsyncIterator.
__getitem__: Type -> Type
.AsyncIterable: ClassType .AsyncIterable: ClassType
.AsyncIterable.
__getitem__: Type -> Type
.Coroutine: ClassType .Coroutine: ClassType
.Coroutine.
__getitem__: (t: (Type, Type, Type)) -> Type
.Collection: ClassType .Collection: ClassType
.Collection.
__getitem__: Type -> Type
.AsyncGenerator: ClassType .AsyncGenerator: ClassType
.AsyncGenerator.
__getitem__: (t: (Type, Type)) -> Type
.AsyncContextManager: ClassType .AsyncContextManager: ClassType
.AsyncContextManager.
__getitem__: Type -> Type
.SupportsAbs: ClassType .SupportsAbs: ClassType
.SupportsBytes: ClassType .SupportsBytes: ClassType
.SupportsComplex: ClassType .SupportsComplex: ClassType
@ -149,5 +187,9 @@
.SupportsInt: ClassType .SupportsInt: ClassType
.SupportsRound: ClassType .SupportsRound: ClassType
.Genertor: ClassType .Generator: ClassType
.Generator.
__getitem__: (t: (Type, Type, Type)) -> Type
.Reversible: ClassType .Reversible: ClassType
.Reversible.
__getitem__: Type -> Type

View file

@ -0,0 +1,21 @@
.urlparse: (urlstring: Str, scheme := Str, allow_fragments := Bool) -> NamedTuple {
.scheme = Str;
.netloc = Str;
.path = Str;
.params = Str;
.query = Str;
.fragment = Str;
.username = Str or NoneType;
.password = Str or NoneType;
.hostname = Str or NoneType;
.port = Int or NoneType;
}
.parse_qs: (
qs: Str,
keep_blank_values := Bool,
strict_parsing := Bool,
encoding := Str,
errors := Str,
max_num_fields := Nat or NoneType,
separator := Str,
) -> {Str: [Str; _]}