mirror of
https://github.com/exaloop/codon.git
synced 2025-06-03 15:03:52 +08:00
Fix traits
This commit is contained in:
parent
547c744b53
commit
07ffc62511
@ -25,6 +25,15 @@ int ClassType::unify(Type *typ, Unification *us) {
|
|||||||
auto t64 = std::make_shared<IntStaticType>(cache, 64);
|
auto t64 = std::make_shared<IntStaticType>(cache, 64);
|
||||||
return generics[0].type->unify(t64.get(), us);
|
return generics[0].type->unify(t64.get(), us);
|
||||||
}
|
}
|
||||||
|
if (name == "unrealized_type" && tc->name == name) {
|
||||||
|
// instantiate + unify!
|
||||||
|
std::unordered_map<int, types::TypePtr> genericCache;
|
||||||
|
auto l = generics[0].type->instantiate(0, &(cache->unboundCount), &genericCache);
|
||||||
|
genericCache.clear();
|
||||||
|
auto r =
|
||||||
|
tc->generics[0].type->instantiate(0, &(cache->unboundCount), &genericCache);
|
||||||
|
return l->unify(r.get(), us);
|
||||||
|
}
|
||||||
// Check names.
|
// Check names.
|
||||||
if (name != tc->name)
|
if (name != tc->name)
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -49,9 +49,9 @@ int LinkType::unify(Type *typ, Unification *undo) {
|
|||||||
// Identical unbound types get a score of 1
|
// Identical unbound types get a score of 1
|
||||||
if (id == t->id)
|
if (id == t->id)
|
||||||
return 1;
|
return 1;
|
||||||
// Generics must have matching IDs
|
// Generics must have matching IDs unless we are doing non-destructive unification
|
||||||
if (kind != Unbound)
|
if (kind == Generic)
|
||||||
return -1;
|
return undo ? -1 : 1;
|
||||||
// Always merge a newer type into the older type (e.g. keep the types with
|
// Always merge a newer type into the older type (e.g. keep the types with
|
||||||
// lower IDs around).
|
// lower IDs around).
|
||||||
if (id < t->id)
|
if (id < t->id)
|
||||||
@ -176,8 +176,8 @@ std::string LinkType::debugString(char mode) const {
|
|||||||
}
|
}
|
||||||
return (genericName.empty() ? (mode ? "?" : "<unknown type>") : genericName);
|
return (genericName.empty() ? (mode ? "?" : "<unknown type>") : genericName);
|
||||||
}
|
}
|
||||||
if (mode == 2)
|
// if (mode == 2)
|
||||||
return ">" + type->debugString(mode);
|
// return ">" + type->debugString(mode);
|
||||||
return type->debugString(mode);
|
return type->debugString(mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -120,7 +120,8 @@ int CallableTrait::unify(Type *typ, Unification *us) {
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (kwStar < trInArgs->generics.size()) {
|
if (kwStar < trInArgs->generics.size()) {
|
||||||
TypePtr tt = cache->typeCtx->getType(TypecheckVisitor(cache->typeCtx).generateTuple(0));
|
TypePtr tt =
|
||||||
|
cache->typeCtx->getType(TypecheckVisitor(cache->typeCtx).generateTuple(0));
|
||||||
size_t id = 0;
|
size_t id = 0;
|
||||||
if (auto tp = tr->getPartial()) {
|
if (auto tp = tr->getPartial()) {
|
||||||
auto ts = tp->generics[2].type->getClass();
|
auto ts = tp->generics[2].type->getClass();
|
||||||
@ -145,6 +146,7 @@ int CallableTrait::unify(Type *typ, Unification *us) {
|
|||||||
if (args[1]->unify(pf->getRetType().get(), us) == -1)
|
if (args[1]->unify(pf->getRetType().get(), us) == -1)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
// LOG("- {} vs {}: ok", debugString(2), typ->debugString(2));
|
||||||
return 1;
|
return 1;
|
||||||
} else if (auto tl = typ->getLink()) {
|
} else if (auto tl = typ->getLink()) {
|
||||||
if (tl->kind == LinkType::Link)
|
if (tl->kind == LinkType::Link)
|
||||||
@ -191,7 +193,10 @@ std::string CallableTrait::debugString(char mode) const {
|
|||||||
|
|
||||||
TypeTrait::TypeTrait(TypePtr typ) : Trait(typ), type(std::move(typ)) {}
|
TypeTrait::TypeTrait(TypePtr typ) : Trait(typ), type(std::move(typ)) {}
|
||||||
|
|
||||||
int TypeTrait::unify(Type *typ, Unification *us) { return typ->unify(type.get(), us); }
|
int TypeTrait::unify(Type *typ, Unification *us) {
|
||||||
|
if (typ->getClass()) // does not make sense otherwise and results in infinite cycles
|
||||||
|
return typ->unify(type.get(), us);
|
||||||
|
}
|
||||||
|
|
||||||
TypePtr TypeTrait::generalize(int atLevel) {
|
TypePtr TypeTrait::generalize(int atLevel) {
|
||||||
auto c = std::make_shared<TypeTrait>(type->generalize(atLevel));
|
auto c = std::make_shared<TypeTrait>(type->generalize(atLevel));
|
||||||
|
@ -153,7 +153,7 @@ void UnionType::seal() {
|
|||||||
std::vector<TypePtr> typeSet(pendingTypes.begin(), pendingTypes.begin() + i);
|
std::vector<TypePtr> typeSet(pendingTypes.begin(), pendingTypes.begin() + i);
|
||||||
auto name = tv.generateTuple(typeSet.size());
|
auto name = tv.generateTuple(typeSet.size());
|
||||||
auto t = cache->typeCtx->instantiateGeneric(
|
auto t = cache->typeCtx->instantiateGeneric(
|
||||||
cache->typeCtx->forceFind(name)->type->getClass(), typeSet);
|
cache->typeCtx->getType(name)->getClass(), typeSet);
|
||||||
Unification us;
|
Unification us;
|
||||||
generics[0].type->unify(t.get(), &us);
|
generics[0].type->unify(t.get(), &us);
|
||||||
}
|
}
|
||||||
|
@ -90,6 +90,7 @@ void TypecheckVisitor::visit(CallExpr *expr) {
|
|||||||
if (auto f = expr->expr->type->getFunc())
|
if (auto f = expr->expr->type->getFunc())
|
||||||
addFunctionGenerics(f.get());
|
addFunctionGenerics(f.get());
|
||||||
auto a = transformCallArgs(expr->args);
|
auto a = transformCallArgs(expr->args);
|
||||||
|
|
||||||
ctx->popBlock();
|
ctx->popBlock();
|
||||||
if (!a)
|
if (!a)
|
||||||
return;
|
return;
|
||||||
@ -162,7 +163,6 @@ void TypecheckVisitor::visit(CallExpr *expr) {
|
|||||||
newArgs.push_back(part.args);
|
newArgs.push_back(part.args);
|
||||||
auto partialCall = generatePartialCall(part.known, calleeFn->getFunc().get(),
|
auto partialCall = generatePartialCall(part.known, calleeFn->getFunc().get(),
|
||||||
N<TupleExpr>(newArgs), part.kwArgs);
|
N<TupleExpr>(newArgs), part.kwArgs);
|
||||||
|
|
||||||
std::string var = ctx->cache->getTemporaryVar("part");
|
std::string var = ctx->cache->getTemporaryVar("part");
|
||||||
ExprPtr call = nullptr;
|
ExprPtr call = nullptr;
|
||||||
if (!part.var.empty()) {
|
if (!part.var.empty()) {
|
||||||
@ -541,40 +541,40 @@ bool TypecheckVisitor::typecheckCallArgs(const FuncTypePtr &calleeFn,
|
|||||||
if (calleeFn->ast->args[i].status == Param::Generic)
|
if (calleeFn->ast->args[i].status == Param::Generic)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (startswith(calleeFn->ast->args[i].name, "*") && calleeFn->ast->args[i].type &&
|
if (startswith(calleeFn->ast->args[i].name, "*") && calleeFn->ast->args[i].type) {
|
||||||
args[si].value->getCall()) {
|
|
||||||
// Special case: `*args: type` and `**kwargs: type`
|
// Special case: `*args: type` and `**kwargs: type`
|
||||||
auto typ = ctx->getType(transform(clone(calleeFn->ast->args[i].type))->type);
|
if (args[si].value->getCall()) {
|
||||||
auto callExpr = args[si].value;
|
auto typ = ctx->getType(transform(clone(calleeFn->ast->args[i].type))->type);
|
||||||
if (startswith(calleeFn->ast->args[i].name, "**"))
|
auto callExpr = args[si].value;
|
||||||
callExpr = args[si].value->getCall()->args[0].value;
|
if (startswith(calleeFn->ast->args[i].name, "**"))
|
||||||
for (auto &ca : callExpr->getCall()->args) {
|
callExpr = args[si].value->getCall()->args[0].value;
|
||||||
if (wrapExpr(ca.value, typ, calleeFn)) {
|
for (auto &ca : callExpr->getCall()->args) {
|
||||||
unify(ca.value->type, typ);
|
if (wrapExpr(ca.value, typ, calleeFn)) {
|
||||||
|
unify(ca.value->type, typ);
|
||||||
|
} else {
|
||||||
|
wrappingDone = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
auto name = callExpr->type->getClass()->name;
|
||||||
|
auto tup = transform(N<CallExpr>(N<IdExpr>(name), callExpr->getCall()->args));
|
||||||
|
if (startswith(calleeFn->ast->args[i].name, "**")) {
|
||||||
|
args[si].value =
|
||||||
|
transform(N<CallExpr>(N<DotExpr>(N<IdExpr>("NamedTuple"), "__new__"), tup,
|
||||||
|
N<IntExpr>(args[si]
|
||||||
|
.value->type->getClass()
|
||||||
|
->generics[0]
|
||||||
|
.type->getIntStatic()
|
||||||
|
->value)));
|
||||||
} else {
|
} else {
|
||||||
wrappingDone = false;
|
args[si].value = tup;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
auto name = callExpr->type->getClass()->name;
|
|
||||||
auto tup = transform(N<CallExpr>(N<IdExpr>(name), callExpr->getCall()->args));
|
|
||||||
|
|
||||||
if (startswith(calleeFn->ast->args[i].name, "**")) {
|
|
||||||
args[si].value =
|
|
||||||
transform(N<CallExpr>(N<DotExpr>(N<IdExpr>("NamedTuple"), "__new__"), tup,
|
|
||||||
N<IntExpr>(args[si]
|
|
||||||
.value->type->getClass()
|
|
||||||
->generics[0]
|
|
||||||
.type->getIntStatic()
|
|
||||||
->value)));
|
|
||||||
} else {
|
|
||||||
args[si].value = tup;
|
|
||||||
}
|
|
||||||
replacements.push_back(args[si].value->type);
|
replacements.push_back(args[si].value->type);
|
||||||
|
// else this is empty and is a partial call; leave it for later
|
||||||
} else {
|
} else {
|
||||||
if (calleeFn->ast->args[i].type && !calleeFn->getArgTypes()[si]->canRealize()) {
|
if (calleeFn->ast->args[i].type && !calleeFn->getArgTypes()[si]->canRealize()) {
|
||||||
auto t = ctx->instantiate(ctx->getType(calleeFn->ast->args[i].type->type)->generalize(0));
|
auto t = ctx->instantiate(
|
||||||
// calleeFn->ast->args[i].type->
|
ctx->getType(calleeFn->ast->args[i].type->type)->generalize(0));
|
||||||
// ctx->getType(transform(clean_clone(calleeFn->ast->args[i].type))->type);
|
|
||||||
unify(calleeFn->getArgTypes()[si], t);
|
unify(calleeFn->getArgTypes()[si], t);
|
||||||
}
|
}
|
||||||
if (wrapExpr(args[si].value, calleeFn->getArgTypes()[si], calleeFn)) {
|
if (wrapExpr(args[si].value, calleeFn->getArgTypes()[si], calleeFn)) {
|
||||||
|
@ -35,7 +35,10 @@ void TypecheckVisitor::visit(ClassStmt *stmt) {
|
|||||||
ctx->generateCanonicalName(name, !stmt->attributes.has(Attr::Internal),
|
ctx->generateCanonicalName(name, !stmt->attributes.has(Attr::Internal),
|
||||||
/* noSuffix*/ stmt->attributes.has(Attr::Internal));
|
/* noSuffix*/ stmt->attributes.has(Attr::Internal));
|
||||||
|
|
||||||
typ = std::make_shared<types::ClassType>(ctx->cache, canonicalName, name);
|
if (canonicalName == "Union")
|
||||||
|
typ = std::make_shared<types::UnionType>(ctx->cache);
|
||||||
|
else
|
||||||
|
typ = std::make_shared<types::ClassType>(ctx->cache, canonicalName, name);
|
||||||
if (stmt->isRecord())
|
if (stmt->isRecord())
|
||||||
typ->isTuple = true;
|
typ->isTuple = true;
|
||||||
// if (stmt->isRecord() && stmt->hasAttr("__notuple__"))
|
// if (stmt->isRecord() && stmt->hasAttr("__notuple__"))
|
||||||
@ -112,15 +115,6 @@ void TypecheckVisitor::visit(ClassStmt *stmt) {
|
|||||||
auto defType = transformType(clone(a.defaultValue));
|
auto defType = transformType(clone(a.defaultValue));
|
||||||
generic->defaultType = getType(defType);
|
generic->defaultType = getType(defType);
|
||||||
}
|
}
|
||||||
if (auto ti = CAST(a.type, InstantiateExpr)) {
|
|
||||||
// Parse TraitVar
|
|
||||||
seqassert(ti->typeExpr->isId(TYPE_TYPEVAR), "not a TypeVar instantiation");
|
|
||||||
auto l = transformType(ti->typeParams[0])->type;
|
|
||||||
if (l->getLink() && l->getLink()->trait)
|
|
||||||
generic->getLink()->trait = l->getLink()->trait;
|
|
||||||
else
|
|
||||||
generic->getLink()->trait = std::make_shared<types::TypeTrait>(l);
|
|
||||||
}
|
|
||||||
if (auto st = getStaticGeneric(a.type.get())) {
|
if (auto st = getStaticGeneric(a.type.get())) {
|
||||||
if (st > 3)
|
if (st > 3)
|
||||||
transform(a.type); // error check
|
transform(a.type); // error check
|
||||||
@ -128,10 +122,22 @@ void TypecheckVisitor::visit(ClassStmt *stmt) {
|
|||||||
auto val = ctx->addVar(genName, varName, generic);
|
auto val = ctx->addVar(genName, varName, generic);
|
||||||
val->generic = true;
|
val->generic = true;
|
||||||
} else {
|
} else {
|
||||||
|
if (a.type->getIndex()) { // Parse TraitVar
|
||||||
|
transform(a.type);
|
||||||
|
auto ti = a.type->getInstantiate();
|
||||||
|
seqassert(ti && ti->typeExpr->isId(TYPE_TYPEVAR),
|
||||||
|
"not a TypeVar instantiation: {}", a.type);
|
||||||
|
auto l = getType(ti->typeParams[0]);
|
||||||
|
if (l->getLink() && l->getLink()->trait)
|
||||||
|
generic->getLink()->trait = l->getLink()->trait;
|
||||||
|
else
|
||||||
|
generic->getLink()->trait = std::make_shared<types::TypeTrait>(l);
|
||||||
|
}
|
||||||
ctx->addType(genName, varName, generic)->generic = true;
|
ctx->addType(genName, varName, generic)->generic = true;
|
||||||
}
|
}
|
||||||
ClassType::Generic g(varName, genName, generic->generalize(ctx->typecheckLevel),
|
ClassType::Generic g(varName, genName, generic->generalize(ctx->typecheckLevel),
|
||||||
typId, generic->isStatic);
|
typId, generic->isStatic);
|
||||||
|
|
||||||
if (a.status == Param::Generic) {
|
if (a.status == Param::Generic) {
|
||||||
typ->generics.push_back(g);
|
typ->generics.push_back(g);
|
||||||
} else {
|
} else {
|
||||||
@ -787,6 +793,8 @@ void TypecheckVisitor::addClassGenerics(const types::ClassTypePtr &clsTyp,
|
|||||||
if (t->getClass() && !t->getStatic() && !t->is("type"))
|
if (t->getClass() && !t->getStatic() && !t->is("type"))
|
||||||
t = ctx->instantiateGeneric(ctx->getType("type"), {t});
|
t = ctx->instantiateGeneric(ctx->getType("type"), {t});
|
||||||
ctx->addVar(ctx->cache->rev(g.name), g.name, t)->generic = true;
|
ctx->addVar(ctx->cache->rev(g.name), g.name, t)->generic = true;
|
||||||
|
// LOG("=[g]=> {}: {} {:c} {}", clsTyp, g.name, t,
|
||||||
|
// t->getLink() && t->getLink()->trait ? "OK" : "-");
|
||||||
};
|
};
|
||||||
for (auto &g : clsTyp->hiddenGenerics)
|
for (auto &g : clsTyp->hiddenGenerics)
|
||||||
addGen(g);
|
addGen(g);
|
||||||
|
@ -206,13 +206,13 @@ void TypecheckVisitor::visit(FunctionStmt *stmt) {
|
|||||||
kw = stmt->args.back();
|
kw = stmt->args.back();
|
||||||
stmt->args.pop_back();
|
stmt->args.pop_back();
|
||||||
}
|
}
|
||||||
std::array<const char*, 4> op {"", "int", "str", "bool"};
|
std::array<const char *, 4> op{"", "int", "str", "bool"};
|
||||||
for (auto &[c, v] : captures) {
|
for (auto &[c, v] : captures) {
|
||||||
if (v->isType())
|
if (v->isType())
|
||||||
stmt->args.emplace_back(c, N<IdExpr>("type"));
|
stmt->args.emplace_back(c, N<IdExpr>("type"));
|
||||||
else if (auto si = v->isStatic())
|
else if (auto si = v->isStatic())
|
||||||
stmt->args.emplace_back(c, N<IndexExpr>(N<IdExpr>("Static"),
|
stmt->args.emplace_back(c,
|
||||||
N<IdExpr>(op[si])));
|
N<IndexExpr>(N<IdExpr>("Static"), N<IdExpr>(op[si])));
|
||||||
else
|
else
|
||||||
stmt->args.emplace_back(c);
|
stmt->args.emplace_back(c);
|
||||||
partialArgs.emplace_back(c, N<IdExpr>(v->canonicalName));
|
partialArgs.emplace_back(c, N<IdExpr>(v->canonicalName));
|
||||||
@ -279,6 +279,15 @@ void TypecheckVisitor::visit(FunctionStmt *stmt) {
|
|||||||
generic->defaultType = getType(defType);
|
generic->defaultType = getType(defType);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
if (auto ti = CAST(a.type, InstantiateExpr)) {
|
||||||
|
// Parse TraitVar
|
||||||
|
seqassert(ti->typeExpr->isId(TYPE_TYPEVAR), "not a TypeVar instantiation");
|
||||||
|
auto l = transformType(ti->typeParams[0])->type;
|
||||||
|
if (l->getLink() && l->getLink()->trait)
|
||||||
|
generic->getLink()->trait = l->getLink()->trait;
|
||||||
|
else
|
||||||
|
generic->getLink()->trait = std::make_shared<types::TypeTrait>(l);
|
||||||
|
}
|
||||||
auto val = ctx->addType(varName, name, generic);
|
auto val = ctx->addType(varName, name, generic);
|
||||||
val->generic = true;
|
val->generic = true;
|
||||||
if (a.defaultValue) {
|
if (a.defaultValue) {
|
||||||
@ -327,7 +336,10 @@ void TypecheckVisitor::visit(FunctionStmt *stmt) {
|
|||||||
// Parse arguments to the context. Needs to be done after adding generics
|
// Parse arguments to the context. Needs to be done after adding generics
|
||||||
// to support cases like `foo(a: T, T: type)`
|
// to support cases like `foo(a: T, T: type)`
|
||||||
for (auto &a : args) {
|
for (auto &a : args) {
|
||||||
|
// if (a.status == Param::Normal || a.type->is ) // todo)) makes typevar work! need to check why...
|
||||||
a.type = transformType(a.type, false);
|
a.type = transformType(a.type, false);
|
||||||
|
// if (a.type && a.type->type->getLink() && a.type->type->getLink()->trait)
|
||||||
|
// LOG("-> {:c}", a.type->type->getLink()->trait);
|
||||||
a.defaultValue = transform(a.defaultValue, true);
|
a.defaultValue = transform(a.defaultValue, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -413,7 +425,6 @@ void TypecheckVisitor::visit(FunctionStmt *stmt) {
|
|||||||
f->setDone();
|
f->setDone();
|
||||||
|
|
||||||
// Construct the type
|
// Construct the type
|
||||||
// g = ctx->instantiateGeneric(ctx->getType("type"), {g});
|
|
||||||
auto funcTyp = std::make_shared<types::FuncType>(
|
auto funcTyp = std::make_shared<types::FuncType>(
|
||||||
baseType, ctx->cache->functions[canonicalName].ast.get(), explicits);
|
baseType, ctx->cache->functions[canonicalName].ast.get(), explicits);
|
||||||
funcTyp->setSrcInfo(getSrcInfo());
|
funcTyp->setSrcInfo(getSrcInfo());
|
||||||
@ -423,6 +434,7 @@ void TypecheckVisitor::visit(FunctionStmt *stmt) {
|
|||||||
funcTyp = std::static_pointer_cast<types::FuncType>(
|
funcTyp = std::static_pointer_cast<types::FuncType>(
|
||||||
funcTyp->generalize(ctx->typecheckLevel));
|
funcTyp->generalize(ctx->typecheckLevel));
|
||||||
ctx->cache->functions[canonicalName].type = funcTyp;
|
ctx->cache->functions[canonicalName].type = funcTyp;
|
||||||
|
// LOG("-> {:c}", funcTyp);
|
||||||
|
|
||||||
ctx->addFunc(stmt->name, rootName, funcTyp);
|
ctx->addFunc(stmt->name, rootName, funcTyp);
|
||||||
ctx->addFunc(canonicalName, canonicalName, funcTyp);
|
ctx->addFunc(canonicalName, canonicalName, funcTyp);
|
||||||
|
@ -194,7 +194,6 @@ types::TypePtr TypecheckVisitor::realizeType(types::ClassType *type) {
|
|||||||
if (!type || !type->canRealize())
|
if (!type || !type->canRealize())
|
||||||
return nullptr;
|
return nullptr;
|
||||||
// type->_rn = type->ClassType::realizedName();
|
// type->_rn = type->ClassType::realizedName();
|
||||||
|
|
||||||
// Check if the type fields are all initialized
|
// Check if the type fields are all initialized
|
||||||
// (sometimes that's not the case: e.g., `class X: x: List[X]`)
|
// (sometimes that's not the case: e.g., `class X: x: List[X]`)
|
||||||
for (auto &field : ctx->cache->classes[type->name].fields) {
|
for (auto &field : ctx->cache->classes[type->name].fields) {
|
||||||
@ -202,6 +201,10 @@ types::TypePtr TypecheckVisitor::realizeType(types::ClassType *type) {
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// generalize generics to ensure that they do not get unified later!
|
||||||
|
if (type->is("unrealized_type"))
|
||||||
|
type->generics[0].type = type->generics[0].type->generalize(0);
|
||||||
|
|
||||||
// Check if the type was already realized
|
// Check if the type was already realized
|
||||||
auto rn = type->ClassType::realizedName();
|
auto rn = type->ClassType::realizedName();
|
||||||
if (auto r = in(ctx->cache->classes[type->name].realizations, rn)) {
|
if (auto r = in(ctx->cache->classes[type->name].realizations, rn)) {
|
||||||
@ -218,9 +221,7 @@ types::TypePtr TypecheckVisitor::realizeType(types::ClassType *type) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Realize generics
|
// Realize generics
|
||||||
if (type->is("unrealized_type"))
|
if (!type->is("unrealized_type"))
|
||||||
type->generics[0].type->generalize(ctx->typecheckLevel);
|
|
||||||
else
|
|
||||||
for (auto &e : realized->generics) {
|
for (auto &e : realized->generics) {
|
||||||
if (!realize(e.type))
|
if (!realize(e.type))
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
@ -372,7 +372,7 @@ void TypecheckVisitor::visit(InstantiateExpr *expr) {
|
|||||||
transformType(expr->typeParams[i]);
|
transformType(expr->typeParams[i]);
|
||||||
auto t = ctx->instantiate(expr->typeParams[i]->getSrcInfo(),
|
auto t = ctx->instantiate(expr->typeParams[i]->getSrcInfo(),
|
||||||
getType(expr->typeParams[i]));
|
getType(expr->typeParams[i]));
|
||||||
if (expr->typeParams[i]->type->isStaticType() !=
|
if (isUnion || expr->typeParams[i]->type->isStaticType() !=
|
||||||
generics[i].type->isStaticType()) {
|
generics[i].type->isStaticType()) {
|
||||||
if (expr->typeParams[i]->getNone()) // `None` -> `NoneType`
|
if (expr->typeParams[i]->getNone()) // `None` -> `NoneType`
|
||||||
transformType(expr->typeParams[i]);
|
transformType(expr->typeParams[i]);
|
||||||
|
@ -62,7 +62,7 @@ StmtPtr TypecheckVisitor::apply(
|
|||||||
ScopingVisitor::apply(cache, suite);
|
ScopingVisitor::apply(cache, suite);
|
||||||
auto n = tv.inferTypes(suite, true);
|
auto n = tv.inferTypes(suite, true);
|
||||||
if (!n) {
|
if (!n) {
|
||||||
LOG("[error=>] {}", suite->toString(2));
|
// LOG("[error=>] {}", suite->toString(2));
|
||||||
tv.error("cannot typecheck the program");
|
tv.error("cannot typecheck the program");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -238,6 +238,10 @@ ExprPtr TypecheckVisitor::transformType(ExprPtr &expr, bool allowTypeOf) {
|
|||||||
!expr->type->getUnbound()->genericName.empty()) {
|
!expr->type->getUnbound()->genericName.empty()) {
|
||||||
// generic!
|
// generic!
|
||||||
expr->setType(ctx->instantiate(expr->getType()));
|
expr->setType(ctx->instantiate(expr->getType()));
|
||||||
|
} else if (expr->type->getUnbound() &&
|
||||||
|
expr->type->getUnbound()->trait) {
|
||||||
|
// generic (is type)!
|
||||||
|
expr->setType(ctx->instantiate(expr->getType()));
|
||||||
} else {
|
} else {
|
||||||
E(Error::EXPECTED_TYPE, expr, "type");
|
E(Error::EXPECTED_TYPE, expr, "type");
|
||||||
}
|
}
|
||||||
|
@ -362,17 +362,17 @@ class defaultdict(Static[Dict[K,V]]):
|
|||||||
V: type
|
V: type
|
||||||
S: TypeVar[Callable[[], V]]
|
S: TypeVar[Callable[[], V]]
|
||||||
|
|
||||||
# def __init__(self: defaultdict[K, VV, Function[[], V]], VV: TypeVar[V]):
|
def __init__(self: defaultdict[K, VV, Function[[], V]], VV: TypeVar[V]):
|
||||||
# super().__init__()
|
super().__init__()
|
||||||
# self.default_factory = lambda: VV()
|
self.default_factory = lambda: VV()
|
||||||
|
|
||||||
def __init__(self, f: S):
|
def __init__(self, f: S):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
self.default_factory = f
|
self.default_factory = f
|
||||||
|
|
||||||
# def __init__(self: defaultdict[K, VV, Function[[], V]], VV: TypeVar[V], other: Dict[K, V]):
|
def __init__(self: defaultdict[K, VV, Function[[], V]], VV: TypeVar[V], other: Dict[K, V]):
|
||||||
# super().__init__(other)
|
super().__init__(other)
|
||||||
# self.default_factory = lambda: VV()
|
self.default_factory = lambda: VV()
|
||||||
|
|
||||||
def __init__(self, f: S, other: Dict[K, V]):
|
def __init__(self, f: S, other: Dict[K, V]):
|
||||||
super().__init__(other)
|
super().__init__(other)
|
||||||
|
@ -191,12 +191,12 @@ class Dict:
|
|||||||
self._vals[x] = op(dflt if ret != 0 else self._vals[x], other)
|
self._vals[x] = op(dflt if ret != 0 else self._vals[x], other)
|
||||||
|
|
||||||
def update(self, other):
|
def update(self, other):
|
||||||
if isinstance(other, Dict[K, V]):
|
for k, v in other:
|
||||||
for k, v in other.items():
|
self[k] = v
|
||||||
self[k] = v
|
|
||||||
else:
|
def update(self, other: Dict[K, V]):
|
||||||
for k, v in other:
|
for k, v in other.items():
|
||||||
self[k] = v
|
self[k] = v
|
||||||
|
|
||||||
def pop(self, key: K) -> V:
|
def pop(self, key: K) -> V:
|
||||||
x = self._kh_get(key)
|
x = self._kh_get(key)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user