mirror of https://github.com/exaloop/codon.git
Add isinstance support for inherited classes; Fix review issues
parent
9dde5be88f
commit
47bea7017b
|
@ -544,6 +544,7 @@ void SimplifyVisitor::visit(FunctionStmt *stmt) {
|
||||||
if (!typeAst && isClassMember && ia == 0 && a.name == "self") {
|
if (!typeAst && isClassMember && ia == 0 && a.name == "self") {
|
||||||
typeAst = ctx->bases[ctx->bases.size() - 2].ast;
|
typeAst = ctx->bases[ctx->bases.size() - 2].ast;
|
||||||
attr.set(".changedSelf");
|
attr.set(".changedSelf");
|
||||||
|
attr.set(Attr::Method);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (attr.has(Attr::C)) {
|
if (attr.has(Attr::C)) {
|
||||||
|
|
|
@ -302,6 +302,8 @@ private:
|
||||||
const std::vector<CallExpr::Arg> &args);
|
const std::vector<CallExpr::Arg> &args);
|
||||||
|
|
||||||
ExprPtr transformSuper(const CallExpr *expr);
|
ExprPtr transformSuper(const CallExpr *expr);
|
||||||
|
std::vector<types::ClassTypePtr> getSuperTypes(const types::ClassTypePtr &cls);
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
types::TypePtr unify(types::TypePtr &a, const types::TypePtr &b,
|
types::TypePtr unify(types::TypePtr &a, const types::TypePtr &b,
|
||||||
|
|
|
@ -1423,8 +1423,15 @@ std::pair<bool, ExprPtr> TypecheckVisitor::transformSpecialCall(CallExpr *expr)
|
||||||
expr->args[1].value =
|
expr->args[1].value =
|
||||||
transformType(expr->args[1].value, /*disableActivation*/ true);
|
transformType(expr->args[1].value, /*disableActivation*/ true);
|
||||||
auto t = expr->args[1].value->type;
|
auto t = expr->args[1].value->type;
|
||||||
auto unifyOK = typ->unify(t.get(), nullptr) >= 0;
|
auto hierarchy = getSuperTypes(typ->getClass());
|
||||||
return {true, transform(N<BoolExpr>(unifyOK))};
|
|
||||||
|
for (auto &tx: hierarchy) {
|
||||||
|
auto unifyOK = tx->unify(t.get(), nullptr) >= 0;
|
||||||
|
if (unifyOK) {
|
||||||
|
return {true, transform(N<BoolExpr>(true))};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {true, transform(N<BoolExpr>(false))};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (val == "staticlen") {
|
} else if (val == "staticlen") {
|
||||||
|
@ -1956,7 +1963,7 @@ ExprPtr TypecheckVisitor::transformSuper(const CallExpr *expr) {
|
||||||
if (ctx->bases.empty() || !ctx->bases.back().type)
|
if (ctx->bases.empty() || !ctx->bases.back().type)
|
||||||
error("no parent classes available");
|
error("no parent classes available");
|
||||||
auto fptyp = ctx->bases.back().type->getFunc();
|
auto fptyp = ctx->bases.back().type->getFunc();
|
||||||
if (!fptyp || fptyp->ast->hasAttr(Attr::Method))
|
if (!fptyp || !fptyp->ast->hasAttr(Attr::Method))
|
||||||
error("no parent classes available");
|
error("no parent classes available");
|
||||||
if (fptyp->args.size() < 2)
|
if (fptyp->args.size() < 2)
|
||||||
error("no parent classes available");
|
error("no parent classes available");
|
||||||
|
@ -2008,5 +2015,31 @@ ExprPtr TypecheckVisitor::transformSuper(const CallExpr *expr) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<ClassTypePtr> TypecheckVisitor::getSuperTypes(const ClassTypePtr &cls) {
|
||||||
|
std::vector<ClassTypePtr> result;
|
||||||
|
if (!cls)
|
||||||
|
return result;
|
||||||
|
result.push_back(cls);
|
||||||
|
int start = 0;
|
||||||
|
for (auto &cand: ctx->cache->classes[cls->name].parentClasses) {
|
||||||
|
auto name = cand.first;
|
||||||
|
int fields = cand.second;
|
||||||
|
auto val = ctx->find(name);
|
||||||
|
seqassert(val, "cannot find '{}'", name);
|
||||||
|
auto ftyp = ctx->instantiate(nullptr, val->type)->getClass();
|
||||||
|
for (int i = start; i < fields; i++) {
|
||||||
|
auto t = ctx->cache->classes[cls->name].fields[i].type;
|
||||||
|
t = ctx->instantiate(nullptr, t, cls.get());
|
||||||
|
auto ft = ctx->cache->classes[name].fields[i].type;
|
||||||
|
ft = ctx->instantiate(nullptr, ft, ftyp.get());
|
||||||
|
unify(t, ft);
|
||||||
|
}
|
||||||
|
start += fields;
|
||||||
|
for (auto &t: getSuperTypes(ftyp))
|
||||||
|
result.push_back(t);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace ast
|
} // namespace ast
|
||||||
} // namespace codon
|
} // namespace codon
|
||||||
|
|
|
@ -600,6 +600,30 @@ print hasattr(int, "__getitem__")
|
||||||
print hasattr([1, 2], "__getitem__", str)
|
print hasattr([1, 2], "__getitem__", str)
|
||||||
#: False
|
#: False
|
||||||
|
|
||||||
|
#%% isinstance_inheritance,barebones
|
||||||
|
class AX[T]:
|
||||||
|
a: T
|
||||||
|
def __init__(self, a: T):
|
||||||
|
self.a = a
|
||||||
|
class Side:
|
||||||
|
def __init__(self):
|
||||||
|
pass
|
||||||
|
class BX[T,U](AX[T], Side):
|
||||||
|
b: U
|
||||||
|
def __init__(self, a: T, b: U):
|
||||||
|
super().__init__(a)
|
||||||
|
self.b = b
|
||||||
|
class CX[T,U](BX[T,U]):
|
||||||
|
c: int
|
||||||
|
def __init__(self, a: T, b: U):
|
||||||
|
super().__init__(a, b)
|
||||||
|
self.c = 1
|
||||||
|
c = CX('a', False)
|
||||||
|
print isinstance(c, CX), isinstance(c, BX), isinstance(c, AX), isinstance(c, Side)
|
||||||
|
#: True True True True
|
||||||
|
print isinstance(c, BX[str, bool]), isinstance(c, BX[str, str]), isinstance(c, AX[int])
|
||||||
|
#: True False False
|
||||||
|
|
||||||
#%% staticlen_err,barebones
|
#%% staticlen_err,barebones
|
||||||
print staticlen([1, 2]) #! List[int] is not a tuple type
|
print staticlen([1, 2]) #! List[int] is not a tuple type
|
||||||
|
|
||||||
|
@ -698,6 +722,56 @@ b = B()
|
||||||
print b.foo() #: A:s
|
print b.foo() #: A:s
|
||||||
print b.baz() #: A:s::6
|
print b.baz() #: A:s::6
|
||||||
|
|
||||||
|
class AX[T]:
|
||||||
|
a: T
|
||||||
|
def __init__(self, a: T):
|
||||||
|
self.a = a
|
||||||
|
def foo(self):
|
||||||
|
return f'[AX:{self.a}]'
|
||||||
|
class BX[T,U](AX[T]):
|
||||||
|
b: U
|
||||||
|
def __init__(self, a: T, b: U):
|
||||||
|
print super().__class__
|
||||||
|
super().__init__(a)
|
||||||
|
self.b = b
|
||||||
|
def foo(self):
|
||||||
|
return f'[BX:{super().foo()}:{self.b}]'
|
||||||
|
class CX[T,U](BX[T,U]):
|
||||||
|
c: int
|
||||||
|
def __init__(self, a: T, b: U):
|
||||||
|
print super().__class__
|
||||||
|
super().__init__(a, b)
|
||||||
|
self.c = 1
|
||||||
|
def foo(self):
|
||||||
|
return f'CX:{super().foo()}:{self.c}'
|
||||||
|
c = CX('a', False)
|
||||||
|
print c.__class__, c.foo()
|
||||||
|
#: BX[str,bool]
|
||||||
|
#: AX[str]
|
||||||
|
#: CX[str,bool] CX:[BX:[AX:a]:False]:1
|
||||||
|
|
||||||
|
|
||||||
|
#%% super_tuple,barebones
|
||||||
|
@tuple
|
||||||
|
class A[T]:
|
||||||
|
a: T
|
||||||
|
x: int
|
||||||
|
def __new__(a: T) -> A[T]:
|
||||||
|
return (a, 1)
|
||||||
|
def foo(self):
|
||||||
|
return f'A:{self.a}'
|
||||||
|
@tuple
|
||||||
|
class B(A[str]):
|
||||||
|
b: int
|
||||||
|
def __new__() -> B:
|
||||||
|
return (*(A('s')), 6)
|
||||||
|
def baz(self):
|
||||||
|
return f'{super().foo()}::{self.b}'
|
||||||
|
|
||||||
|
b = B()
|
||||||
|
print b.foo() #: A:s
|
||||||
|
print b.baz() #: A:s::6
|
||||||
|
|
||||||
|
|
||||||
#%% super_error,barebones
|
#%% super_error,barebones
|
||||||
class A:
|
class A:
|
||||||
|
|
Loading…
Reference in New Issue