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),
14,
);
obj.register_builtin_py_impl(
FUNDAMENTAL_CALL,
func0(Obj),
Immutable,
Visibility::BUILTIN_PUBLIC,
Some(FUNDAMENTAL_CALL),
);
// Obj does not implement Eq
let mut complex = Self::builtin_mono_class(COMPLEX, 2);
complex.register_superclass(Obj, &obj);

View file

@ -351,8 +351,8 @@ impl Context {
)
.quantify();
let t_slice = no_var_func(
vec![kw(KW_START, Int)],
vec![kw(KW_STOP, Int), kw(KW_STEP, Int)],
vec![kw(KW_START, Int | NoneType)],
vec![kw(KW_STOP, Int | NoneType), kw(KW_STEP, Int | NoneType)],
mono(SLICE),
);
let t_sorted = nd_func(
@ -975,6 +975,40 @@ impl Context {
Visibility::BUILTIN_PUBLIC,
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) {

View file

@ -547,6 +547,8 @@ const FUNC_HASATTR: &str = "hasattr";
const FUNC_GETATTR: &str = "getattr";
const FUNC_SETATTR: &str = "setattr";
const FUNC_DELATTR: &str = "delattr";
const FUNC_EXEC: &str = "exec";
const FUNC_EVAL: &str = "eval";
const FUNC_NEARLY_EQ: &str = "nearly_eq";
const FUNC_RESOLVE_PATH: &str = "ResolvePath";
const FUNC_RESOLVE_DECL_PATH: &str = "ResolveDeclPath";
@ -732,6 +734,8 @@ const KW_NUMBER: &str = "number";
const KW_ITERABLE1: &str = "iterable1";
const KW_ITERABLE2: &str = "iterable2";
const KW_CODE: &str = "code";
const KW_GLOBALS: &str = "globals";
const KW_LOCALS: &str = "locals";
const KW_STOP: &str = "stop";
const KW_STEP: &str = "step";
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(
&self,
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
.get_nominal_super_type_ctxs(obj.ref_t())
.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) {
Triple::Ok(method) => {
let def_t = self
@ -1436,17 +1431,18 @@ impl Context {
);
return Ok(vi);
}
}
for patch in self.find_patches_of(obj.ref_t()) {
if let Some(vi) = patch.get_current_scope_non_param(&attr_name.name) {
self.validate_visibility(attr_name, vi, input, namespace)?;
return Ok(vi.clone());
}
for methods_ctx in patch.methods_list.iter() {
if let Some(vi) = methods_ctx.get_current_scope_non_param(&attr_name.name) {
} else {
for patch in self.find_patches_of(obj.ref_t()) {
if let Some(vi) = patch.get_current_scope_non_param(&attr_name.name) {
self.validate_visibility(attr_name, vi, input, namespace)?;
return Ok(vi.clone());
}
for methods_ctx in patch.methods_list.iter() {
if let Some(vi) = methods_ctx.get_current_scope_non_param(&attr_name.name) {
self.validate_visibility(attr_name, vi, input, namespace)?;
return Ok(vi.clone());
}
}
}
}
let coerced = self
@ -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
.get_nominal_super_type_ctxs(obj.ref_t())
.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) {
Triple::Ok(method) => {
let def_t = self
@ -1581,17 +1567,18 @@ impl Context {
);
return Ok(vi);
}
}
for patch in self.find_patches_of(obj.ref_t()) {
if let Some(vi) = patch.get_current_scope_callable(&attr_name.name) {
self.validate_visibility(attr_name, vi, input, namespace)?;
return Ok(vi.clone());
}
for methods_ctx in patch.methods_list.iter() {
if let Some(vi) = methods_ctx.get_current_scope_callable(&attr_name.name) {
} else {
for patch in self.find_patches_of(obj.ref_t()) {
if let Some(vi) = patch.get_current_scope_callable(&attr_name.name) {
self.validate_visibility(attr_name, vi, input, namespace)?;
return Ok(vi.clone());
}
for methods_ctx in patch.methods_list.iter() {
if let Some(vi) = methods_ctx.get_current_scope_callable(&attr_name.name) {
self.validate_visibility(attr_name, vi, input, namespace)?;
return Ok(vi.clone());
}
}
}
}
let coerced = self
@ -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,
obj: &hir::Expr,
name: &str,
@ -3023,6 +3010,10 @@ impl Context {
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>> {
match t {
Type::FreeVar(fv) if fv.is_linked() => self.get_nominal_super_type_ctxs(&fv.crack()),

View file

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