mirror of
https://github.com/exaloop/codon.git
synced 2025-06-03 15:03:52 +08:00
Fix NTuple handling
This commit is contained in:
parent
2cff95109d
commit
04913cd405
@ -91,10 +91,29 @@ int ClassType::unify(Type *typ, Unification *us) {
|
|||||||
} else if (name == "__NTuple__" && tc->name == TYPE_TUPLE) {
|
} else if (name == "__NTuple__" && tc->name == TYPE_TUPLE) {
|
||||||
auto n1 = generics[0].getType()->getIntStatic();
|
auto n1 = generics[0].getType()->getIntStatic();
|
||||||
if (!n1) {
|
if (!n1) {
|
||||||
auto t1 = std::make_shared<IntStaticType>(cache, 1);
|
auto n = tc->generics.size();
|
||||||
if (generics[0].type->unify(t1.get(), us) == -1)
|
auto tn = std::make_shared<IntStaticType>(cache, n);
|
||||||
|
// If we are unifying NT[N, T] and T[X, X, ...], we assume that N is number of
|
||||||
|
// X's
|
||||||
|
if (generics[0].type->unify(tn.get(), us) == -1)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
auto tv = TypecheckVisitor(cache->typeCtx);
|
||||||
|
TypePtr tt;
|
||||||
|
if (n) {
|
||||||
|
tt = tv.instantiateType(tv.generateTuple(1), {tc->generics[0].getType()});
|
||||||
|
for (size_t i = 1; i < tc->generics.size(); i++) {
|
||||||
|
if ((s = tt->getClass()->generics[0].getType()->unify(
|
||||||
|
tc->generics[i].getType(), us)) == -1)
|
||||||
|
return -1;
|
||||||
|
s1 += s;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
tt = tv.instantiateType(tv.generateTuple(1));
|
||||||
|
// tt = tv.instantiateType(tv.generateTuple(0));
|
||||||
|
}
|
||||||
|
if (generics[1].type->unify(tt.get(), us) == -1)
|
||||||
return -1;
|
return -1;
|
||||||
return generics[1].type->unify(tc, us);
|
|
||||||
} else {
|
} else {
|
||||||
auto t1 = generics[1].getType()->getClass();
|
auto t1 = generics[1].getType()->getClass();
|
||||||
seqassert(t1, "bad ntuples");
|
seqassert(t1, "bad ntuples");
|
||||||
@ -106,8 +125,8 @@ int ClassType::unify(Type *typ, Unification *us) {
|
|||||||
return -1;
|
return -1;
|
||||||
s1 += s;
|
s1 += s;
|
||||||
}
|
}
|
||||||
return s1;
|
|
||||||
}
|
}
|
||||||
|
return s1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check names.
|
// Check names.
|
||||||
|
@ -82,6 +82,9 @@ void TypecheckVisitor::visit(StringExpr *expr) {
|
|||||||
items.emplace_back(N<StringExpr>(p.value));
|
items.emplace_back(N<StringExpr>(p.value));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (items.size() == 1)
|
||||||
|
resultExpr = transform(items.front());
|
||||||
|
else
|
||||||
resultExpr = transform(N<CallExpr>(N<DotExpr>(N<IdExpr>("str"), "cat"), items));
|
resultExpr = transform(N<CallExpr>(N<DotExpr>(N<IdExpr>("str"), "cat"), items));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -690,12 +690,12 @@ bool TypecheckVisitor::typecheckCallArgs(FuncType *calleeFn,
|
|||||||
|
|
||||||
// Handle default generics
|
// Handle default generics
|
||||||
for (size_t i = 0, j = 0; wrappingDone && i < calleeFn->ast->size(); i++)
|
for (size_t i = 0, j = 0; wrappingDone && i < calleeFn->ast->size(); i++)
|
||||||
if ((*calleeFn->ast)[i].status == Param::Generic) {
|
if ((*calleeFn->ast)[i].isGeneric()) {
|
||||||
if ((*calleeFn->ast)[i].defaultValue &&
|
if ((*calleeFn->ast)[i].getDefault() &&
|
||||||
isUnbound(extractFuncGeneric(calleeFn, j))) {
|
isUnbound(extractFuncGeneric(calleeFn, j))) {
|
||||||
auto def = extractType(withClassGenerics(
|
auto def = extractType(withClassGenerics(
|
||||||
calleeFn,
|
calleeFn,
|
||||||
[&]() { return transform(clone((*calleeFn->ast)[i].getDefault())); },
|
[&]() { return transform(clean_clone((*calleeFn->ast)[i].getDefault())); },
|
||||||
true));
|
true));
|
||||||
unify(extractFuncGeneric(calleeFn, j), def);
|
unify(extractFuncGeneric(calleeFn, j), def);
|
||||||
}
|
}
|
||||||
|
@ -491,8 +491,11 @@ ir::types::Type *TypecheckVisitor::makeIRType(types::ClassType *t) {
|
|||||||
// Realize if not, and return cached value if it exists
|
// Realize if not, and return cached value if it exists
|
||||||
auto realizedName = t->ClassType::realizedName();
|
auto realizedName = t->ClassType::realizedName();
|
||||||
auto cls = ctx->cache->getClass(t);
|
auto cls = ctx->cache->getClass(t);
|
||||||
if (!in(cls->realizations, realizedName))
|
if (!in(cls->realizations, realizedName)) {
|
||||||
realize(t->getClass());
|
t = realize(t->getClass())->getClass();
|
||||||
|
realizedName = t->ClassType::realizedName();
|
||||||
|
cls = ctx->cache->getClass(t);
|
||||||
|
}
|
||||||
if (auto l = cls->realizations[realizedName]->ir) {
|
if (auto l = cls->realizations[realizedName]->ir) {
|
||||||
if (cls->rtti)
|
if (cls->rtti)
|
||||||
cast<ir::types::RefType>(l)->setPolymorphic();
|
cast<ir::types::RefType>(l)->setPolymorphic();
|
||||||
|
@ -850,6 +850,13 @@ print(Tuple[-5, int].__class__.__name__)
|
|||||||
print(Tuple[5, int, str].__class__.__name__)
|
print(Tuple[5, int, str].__class__.__name__)
|
||||||
#: Tuple[int,str,int,str,int,str,int,str,int,str]
|
#: Tuple[int,str,int,str,int,str,int,str,int,str]
|
||||||
|
|
||||||
|
def foo(t: Tuple[N, int], N: Static[int]):
|
||||||
|
print("foo", N, t)
|
||||||
|
foo((1, 2, 3))
|
||||||
|
#: foo 3 (1, 2, 3)
|
||||||
|
foo((1, 2, 3, 4, 5))
|
||||||
|
#: foo 5 (1, 2, 3, 4, 5)
|
||||||
|
|
||||||
|
|
||||||
#%% union_hasattr,barebones
|
#%% union_hasattr,barebones
|
||||||
class A:
|
class A:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user