mirror of
https://github.com/exaloop/codon.git
synced 2025-06-03 15:03:52 +08:00
Fix #156
This commit is contained in:
parent
b74601244d
commit
49d9097e94
@ -783,16 +783,31 @@ ExprPtr TypecheckVisitor::transformHasAttr(CallExpr *expr) {
|
|||||||
.type->getStatic()
|
.type->getStatic()
|
||||||
->evaluate()
|
->evaluate()
|
||||||
.getString();
|
.getString();
|
||||||
std::vector<TypePtr> args{typ};
|
std::vector<std::pair<std::string, TypePtr>> args{{"", typ}};
|
||||||
if (expr->expr->isId("hasattr:0")) {
|
if (expr->expr->isId("hasattr:0")) {
|
||||||
// Case: the first hasattr overload allows passing argument types via *args
|
// Case: the first hasattr overload allows passing argument types via *args
|
||||||
auto tup = expr->args[1].value->getTuple();
|
auto tup = expr->args[1].value->getTuple();
|
||||||
seqassert(tup, "not a tuple");
|
seqassert(tup, "not a tuple");
|
||||||
for (auto &a : tup->items) {
|
for (auto &a : tup->items) {
|
||||||
transformType(a);
|
transform(a);
|
||||||
if (!a->getType()->getClass())
|
if (!a->getType()->getClass())
|
||||||
return nullptr;
|
return nullptr;
|
||||||
args.push_back(a->getType());
|
args.push_back({"", a->getType()});
|
||||||
|
}
|
||||||
|
auto kwtup = expr->args[2].value->origExpr->getCall();
|
||||||
|
seqassert(expr->args[2].value->origExpr && expr->args[2].value->origExpr->getCall(),
|
||||||
|
"expected call: {}", expr->args[2].value->origExpr);
|
||||||
|
auto kw = expr->args[2].value->origExpr->getCall();
|
||||||
|
auto kwCls =
|
||||||
|
in(ctx->cache->classes, expr->args[2].value->getType()->getClass()->name);
|
||||||
|
seqassert(kwCls, "cannot find {}",
|
||||||
|
expr->args[2].value->getType()->getClass()->name);
|
||||||
|
for (size_t i = 0; i < kw->args.size(); i++) {
|
||||||
|
auto &a = kw->args[i].value;
|
||||||
|
transform(a);
|
||||||
|
if (!a->getType()->getClass())
|
||||||
|
return nullptr;
|
||||||
|
args.push_back({kwCls->fields[i].name, a->getType()});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -382,9 +382,8 @@ StmtPtr TypecheckVisitor::prepareVTables() {
|
|||||||
// def class_init_vtables():
|
// def class_init_vtables():
|
||||||
// return __internal__.class_make_n_vtables(<NUM_REALIZATIONS> + 1)
|
// return __internal__.class_make_n_vtables(<NUM_REALIZATIONS> + 1)
|
||||||
auto &initAllVT = ctx->cache->functions[rep];
|
auto &initAllVT = ctx->cache->functions[rep];
|
||||||
auto suite = N<SuiteStmt>(
|
auto suite = N<SuiteStmt>(N<ReturnStmt>(N<CallExpr>(
|
||||||
N<ReturnStmt>(N<CallExpr>(N<IdExpr>("__internal__.class_make_n_vtables:0"),
|
N<IdExpr>("__internal__.class_make_n_vtables:0"), N<IdExpr>("__vtable_size__"))));
|
||||||
N<IdExpr>("__vtable_size__"))));
|
|
||||||
initAllVT.ast->suite = suite;
|
initAllVT.ast->suite = suite;
|
||||||
auto typ = initAllVT.realizations.begin()->second->type;
|
auto typ = initAllVT.realizations.begin()->second->type;
|
||||||
LOG_REALIZE("[poly] {} : {}", typ, *suite);
|
LOG_REALIZE("[poly] {} : {}", typ, *suite);
|
||||||
@ -416,10 +415,9 @@ StmtPtr TypecheckVisitor::prepareVTables() {
|
|||||||
std::vector<ExprPtr>{NT<IdExpr>("cobj")}),
|
std::vector<ExprPtr>{NT<IdExpr>("cobj")}),
|
||||||
N<IntExpr>(vtSz + 2)))));
|
N<IntExpr>(vtSz + 2)))));
|
||||||
// __internal__.class_set_typeinfo(p[real.ID], real.ID)
|
// __internal__.class_set_typeinfo(p[real.ID], real.ID)
|
||||||
suite->stmts.push_back(N<ExprStmt>(
|
suite->stmts.push_back(N<ExprStmt>(N<CallExpr>(
|
||||||
N<CallExpr>(N<IdExpr>("__internal__.class_set_typeinfo:0"),
|
N<IdExpr>("__internal__.class_set_typeinfo:0"),
|
||||||
N<IndexExpr>(N<IdExpr>(var), N<IntExpr>(real->id)),
|
N<IndexExpr>(N<IdExpr>(var), N<IntExpr>(real->id)), N<IntExpr>(real->id))));
|
||||||
N<IntExpr>(real->id))));
|
|
||||||
vtSz = 0;
|
vtSz = 0;
|
||||||
for (auto &[base, vtable] : real->vtables) {
|
for (auto &[base, vtable] : real->vtables) {
|
||||||
if (!vtable.ir) {
|
if (!vtable.ir) {
|
||||||
@ -842,9 +840,8 @@ TypecheckVisitor::generateSpecialAst(types::FuncType *type) {
|
|||||||
auto unionType = type->funcParent->getUnion();
|
auto unionType = type->funcParent->getUnion();
|
||||||
seqassert(unionType, "expected union, got {}", type->funcParent);
|
seqassert(unionType, "expected union, got {}", type->funcParent);
|
||||||
|
|
||||||
StmtPtr suite = N<ReturnStmt>(
|
StmtPtr suite = N<ReturnStmt>(N<CallExpr>(
|
||||||
N<CallExpr>(N<IdExpr>("__internal__.new_union:0"),
|
N<IdExpr>("__internal__.new_union:0"), N<IdExpr>(type->ast->args[0].name),
|
||||||
N<IdExpr>(type->ast->args[0].name),
|
|
||||||
N<IdExpr>(unionType->realizedTypeName())));
|
N<IdExpr>(unionType->realizedTypeName())));
|
||||||
ast->suite = suite;
|
ast->suite = suite;
|
||||||
} else if (startswith(ast->name, "__internal__.new_union:0")) {
|
} else if (startswith(ast->name, "__internal__.new_union:0")) {
|
||||||
@ -885,7 +882,6 @@ TypecheckVisitor::generateSpecialAst(types::FuncType *type) {
|
|||||||
}
|
}
|
||||||
suite->stmts.push_back(N<ExprStmt>(N<CallExpr>(
|
suite->stmts.push_back(N<ExprStmt>(N<CallExpr>(
|
||||||
N<IdExpr>("compile_error"), N<StringExpr>("invalid union constructor"))));
|
N<IdExpr>("compile_error"), N<StringExpr>("invalid union constructor"))));
|
||||||
LOG("-> {}", suite->toString(2));
|
|
||||||
ast->suite = suite;
|
ast->suite = suite;
|
||||||
} else if (startswith(ast->name, "__internal__.get_union:0")) {
|
} else if (startswith(ast->name, "__internal__.get_union:0")) {
|
||||||
// Special case: __internal__.get_union
|
// Special case: __internal__.get_union
|
||||||
@ -932,21 +928,29 @@ TypecheckVisitor::generateSpecialAst(types::FuncType *type) {
|
|||||||
auto suite = N<SuiteStmt>();
|
auto suite = N<SuiteStmt>();
|
||||||
int tag = 0;
|
int tag = 0;
|
||||||
for (auto &t : unionTypes) {
|
for (auto &t : unionTypes) {
|
||||||
suite->stmts.push_back(N<IfStmt>(
|
auto callee =
|
||||||
N<BinaryExpr>(N<CallExpr>(N<IdExpr>("__internal__.union_get_tag:0"),
|
|
||||||
N<IdExpr>(selfVar)),
|
|
||||||
"==", N<IntExpr>(tag)),
|
|
||||||
N<ReturnStmt>(N<CallExpr>(
|
|
||||||
N<DotExpr>(N<CallExpr>(N<IdExpr>("__internal__.union_get_data:0"),
|
N<DotExpr>(N<CallExpr>(N<IdExpr>("__internal__.union_get_data:0"),
|
||||||
N<IdExpr>(selfVar), NT<IdExpr>(t->realizedName())),
|
N<IdExpr>(selfVar), NT<IdExpr>(t->realizedName())),
|
||||||
fnName),
|
fnName);
|
||||||
N<StarExpr>(N<IdExpr>(ast->args[2].name.substr(1))),
|
auto args = N<StarExpr>(N<IdExpr>(ast->args[2].name.substr(1)));
|
||||||
N<KeywordStarExpr>(N<IdExpr>(ast->args[3].name.substr(2)))))));
|
auto kwargs = N<KeywordStarExpr>(N<IdExpr>(ast->args[3].name.substr(2)));
|
||||||
|
std::vector<CallExpr::Arg> callArgs;
|
||||||
|
ExprPtr check =
|
||||||
|
N<CallExpr>(N<IdExpr>("hasattr"), callee->clone(), N<StringExpr>(fnName),
|
||||||
|
args->clone(), kwargs->clone());
|
||||||
|
suite->stmts.push_back(N<IfStmt>(
|
||||||
|
N<BinaryExpr>(
|
||||||
|
check, "&&",
|
||||||
|
N<BinaryExpr>(N<CallExpr>(N<IdExpr>("__internal__.union_get_tag:0"),
|
||||||
|
N<IdExpr>(selfVar)),
|
||||||
|
"==", N<IntExpr>(tag))),
|
||||||
|
N<ReturnStmt>(N<CallExpr>(callee, args, kwargs))));
|
||||||
tag++;
|
tag++;
|
||||||
}
|
}
|
||||||
suite->stmts.push_back(
|
suite->stmts.push_back(
|
||||||
N<ThrowStmt>(N<CallExpr>(N<IdExpr>("std.internal.types.error.TypeError"),
|
N<ThrowStmt>(N<CallExpr>(N<IdExpr>("std.internal.types.error.TypeError"),
|
||||||
N<StringExpr>("invalid union call"))));
|
N<StringExpr>("invalid union call"))));
|
||||||
|
suite->stmts.push_back(N<ReturnStmt>(N<NoneExpr>()));
|
||||||
unify(type->getRetType(), ctx->instantiate(ctx->getType("Union")));
|
unify(type->getRetType(), ctx->instantiate(ctx->getType("Union")));
|
||||||
ast->suite = suite;
|
ast->suite = suite;
|
||||||
} else if (startswith(ast->name, "__internal__.get_union_first:0")) {
|
} else if (startswith(ast->name, "__internal__.get_union_first:0")) {
|
||||||
|
@ -200,6 +200,21 @@ types::FuncTypePtr TypecheckVisitor::findBestMethod(const ClassTypePtr &typ,
|
|||||||
return m.empty() ? nullptr : m[0];
|
return m.empty() ? nullptr : m[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Select the best method indicated of an object that matches the given argument
|
||||||
|
/// types. See @c findMatchingMethods for details.
|
||||||
|
types::FuncTypePtr TypecheckVisitor::findBestMethod(
|
||||||
|
const ClassTypePtr &typ, const std::string &member,
|
||||||
|
const std::vector<std::pair<std::string, types::TypePtr>> &args) {
|
||||||
|
std::vector<CallExpr::Arg> callArgs;
|
||||||
|
for (auto &[n, a] : args) {
|
||||||
|
callArgs.push_back({n, std::make_shared<NoneExpr>()}); // dummy expression
|
||||||
|
callArgs.back().value->setType(a);
|
||||||
|
}
|
||||||
|
auto methods = ctx->findMethod(typ->name, member, false);
|
||||||
|
auto m = findMatchingMethods(typ, methods, callArgs);
|
||||||
|
return m.empty() ? nullptr : m[0];
|
||||||
|
}
|
||||||
|
|
||||||
/// Select the best method among the provided methods given the list of arguments.
|
/// Select the best method among the provided methods given the list of arguments.
|
||||||
/// See @c reorderNamedArgs for details.
|
/// See @c reorderNamedArgs for details.
|
||||||
std::vector<types::FuncTypePtr>
|
std::vector<types::FuncTypePtr>
|
||||||
|
@ -210,6 +210,9 @@ private:
|
|||||||
types::FuncTypePtr findBestMethod(const types::ClassTypePtr &typ,
|
types::FuncTypePtr findBestMethod(const types::ClassTypePtr &typ,
|
||||||
const std::string &member,
|
const std::string &member,
|
||||||
const std::vector<ExprPtr> &args);
|
const std::vector<ExprPtr> &args);
|
||||||
|
types::FuncTypePtr
|
||||||
|
findBestMethod(const types::ClassTypePtr &typ, const std::string &member,
|
||||||
|
const std::vector<std::pair<std::string, types::TypePtr>> &args);
|
||||||
std::vector<types::FuncTypePtr>
|
std::vector<types::FuncTypePtr>
|
||||||
findMatchingMethods(const types::ClassTypePtr &typ,
|
findMatchingMethods(const types::ClassTypePtr &typ,
|
||||||
const std::vector<types::FuncTypePtr> &methods,
|
const std::vector<types::FuncTypePtr> &methods,
|
||||||
|
@ -155,7 +155,7 @@ def isinstance(obj, what):
|
|||||||
def overload():
|
def overload():
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def hasattr(obj, attr: Static[str], *args):
|
def hasattr(obj, attr: Static[str], *args, **kwargs):
|
||||||
"""Special handling"""
|
"""Special handling"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user