Fix NTuple handling

typecheck-v2
Ibrahim Numanagić 2024-12-12 19:13:54 -08:00
parent 2cff95109d
commit 04913cd405
5 changed files with 42 additions and 10 deletions

View File

@ -91,10 +91,29 @@ int ClassType::unify(Type *typ, Unification *us) {
} else if (name == "__NTuple__" && tc->name == TYPE_TUPLE) {
auto n1 = generics[0].getType()->getIntStatic();
if (!n1) {
auto t1 = std::make_shared<IntStaticType>(cache, 1);
if (generics[0].type->unify(t1.get(), us) == -1)
auto n = tc->generics.size();
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 generics[1].type->unify(tc, us);
} else {
auto t1 = generics[1].getType()->getClass();
seqassert(t1, "bad ntuples");
@ -106,8 +125,8 @@ int ClassType::unify(Type *typ, Unification *us) {
return -1;
s1 += s;
}
return s1;
}
return s1;
}
// Check names.

View File

@ -82,6 +82,9 @@ void TypecheckVisitor::visit(StringExpr *expr) {
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));
}
}

View File

@ -690,12 +690,12 @@ bool TypecheckVisitor::typecheckCallArgs(FuncType *calleeFn,
// Handle default generics
for (size_t i = 0, j = 0; wrappingDone && i < calleeFn->ast->size(); i++)
if ((*calleeFn->ast)[i].status == Param::Generic) {
if ((*calleeFn->ast)[i].defaultValue &&
if ((*calleeFn->ast)[i].isGeneric()) {
if ((*calleeFn->ast)[i].getDefault() &&
isUnbound(extractFuncGeneric(calleeFn, j))) {
auto def = extractType(withClassGenerics(
calleeFn,
[&]() { return transform(clone((*calleeFn->ast)[i].getDefault())); },
[&]() { return transform(clean_clone((*calleeFn->ast)[i].getDefault())); },
true));
unify(extractFuncGeneric(calleeFn, j), def);
}

View File

@ -491,8 +491,11 @@ ir::types::Type *TypecheckVisitor::makeIRType(types::ClassType *t) {
// Realize if not, and return cached value if it exists
auto realizedName = t->ClassType::realizedName();
auto cls = ctx->cache->getClass(t);
if (!in(cls->realizations, realizedName))
realize(t->getClass());
if (!in(cls->realizations, realizedName)) {
t = realize(t->getClass())->getClass();
realizedName = t->ClassType::realizedName();
cls = ctx->cache->getClass(t);
}
if (auto l = cls->realizations[realizedName]->ir) {
if (cls->rtti)
cast<ir::types::RefType>(l)->setPolymorphic();

View File

@ -850,6 +850,13 @@ print(Tuple[-5, int].__class__.__name__)
print(Tuple[5, int, str].__class__.__name__)
#: 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
class A: