Fix static issues

typecheck-v2
Ibrahim Numanagić 2024-01-08 23:09:29 -08:00
parent cff38ea734
commit cdc8e17955
9 changed files with 25 additions and 14 deletions

View File

@ -147,7 +147,13 @@ int RecordType::unify(Type *typ, Unification *us) {
return generics[0].type->unify(t64.get(), us);
}
auto tup2Tup = startswith(name, TYPE_TUPLE) || startswith(tr->name, TYPE_TUPLE);
int s1 = 2, s = 0;
if (!tup2Tup) {
s1 = this->ClassType::unify(tr.get(), us);
if (s1 == -1)
return -1;
}
if (args.size() != tr->args.size())
return -1;
for (int i = 0; i < args.size(); i++) {
@ -157,13 +163,13 @@ int RecordType::unify(Type *typ, Unification *us) {
return -1;
}
// Handle Tuple<->@tuple: when unifying tuples, only record members matter.
if (startswith(name, TYPE_TUPLE) || startswith(tr->name, TYPE_TUPLE)) {
if (tup2Tup) {
if (!args.empty() || (!noTuple && !tr->noTuple)) // prevent POD<->() unification
return s1 + int(name == tr->name);
else
return -1;
}
return this->ClassType::unify(tr.get(), us);
return s1;
} else if (auto t = typ->getLink()) {
return t->unify(this, us);
} else {

View File

@ -23,8 +23,9 @@ int FuncType::unify(Type *typ, Unification *us) {
// Check if names and parents match.
if (ast->name != t->ast->name || (bool(funcParent) ^ bool(t->funcParent)))
return -1;
if (funcParent && (s = funcParent->unify(t->funcParent.get(), us)) == -1)
if (funcParent && (s = funcParent->unify(t->funcParent.get(), us)) == -1) {
return -1;
}
s1 += s;
// Check if function generics match.
seqassert(funcGenerics.size() == t->funcGenerics.size(),

View File

@ -166,6 +166,8 @@ std::string LinkType::debugString(char mode) const {
}
return (genericName.empty() ? (mode ? "?" : "<unknown type>") : genericName);
}
if (mode == 2)
return ">" + type->debugString(mode);
return type->debugString(mode);
}

View File

@ -151,7 +151,7 @@ void StaticType::parseExpr(const ExprPtr &e, std::unordered_set<std::string> &se
if (auto ei = e->getId()) {
if (!in(seen, ei->value)) {
auto val = cache->typeCtx->find(ei->value);
seqassert(val && val->type->isStaticType(), "invalid static expression");
seqassert(val && val->type->isStaticType(), "invalid static expression: {}", e);
auto genTyp = val->type->follow();
auto id = genTyp->getLink() ? genTyp->getLink()->id
: genTyp->getStatic()->generics.empty()

View File

@ -153,10 +153,12 @@ StmtPtr TypecheckVisitor::transformAssignment(AssignStmt *stmt, bool mustExist)
// Check if we can wrap the expression (e.g., `a: float = 3` -> `a = float(3)`)
if (wrapExpr(assign->rhs, assign->lhs->getType()))
unify(assign->lhs->type, assign->rhs->type);
if (stmt->rhs->isType())
if (stmt->rhs->isType()) {
val->type = val->type->getClass();
else if (stmt->rhs->type->getFunc())
val->type = val->type->getFunc();
} else if (stmt->rhs->type->getFunc()) {
unify(val->type, stmt->rhs->type->getFunc());
val->type = stmt->rhs->type->getFunc();
}
auto type = assign->lhs->getType();
// Generalize non-variable types. That way we can support cases like:
// `a = foo(x, ...); a(1); a('s')`

View File

@ -52,8 +52,8 @@ void TypecheckVisitor::visit(IfExpr *expr) {
// Check if both subexpressions are static; if so, this if expression is also
// static and should be marked as such
// TODO: short circuiting?
auto i = transform(clone(expr->ifexpr));
auto e = transform(clone(expr->elsexpr));
auto i = transform(expr->ifexpr);
auto e = transform(expr->elsexpr);
if (i->isStatic() && e->isStatic()) {
expr->staticValue.type = i->staticValue.type;
unify(expr->type,

View File

@ -179,7 +179,7 @@ struct TypeContext : public Context<TypecheckItem> {
/// True if an early return is found (anything afterwards won't be typechecked)
bool returnEarly = false;
/// Stack of static loop control variables (used to emulate goto statements).
std::vector<std::string> staticLoops;
std::vector<std::string> staticLoops = {};
public:
explicit TypeContext(Cache *cache, std::string filename = "");

View File

@ -54,9 +54,9 @@ void TypecheckVisitor::visit(UnaryExpr *expr) {
void TypecheckVisitor::visit(BinaryExpr *expr) {
// Transform lexpr and rexpr. Ignore Nones for now
if (!(startswith(expr->op, "is") && expr->lexpr->getNone()))
transform(expr->lexpr, startswith(expr->op, "is"));
transform(expr->lexpr, true);
if (!(startswith(expr->op, "is") && expr->rexpr->getNone()))
transform(expr->rexpr, startswith(expr->op, "is"));
transform(expr->rexpr, true);
static std::unordered_map<StaticValue::Type, std::unordered_set<std::string>>
staticOps = {{StaticValue::INT,

View File

@ -72,10 +72,10 @@ f[:,0] #: (slice(None, None, None), 0)
Ptr[9.99] #! expected type expression
#%% index_error_b,barebones
Ptr['s'] #! ''s'' does not match expected type 'T'
Ptr['s'] #! expected type expression
#%% index_error_static,barebones
Ptr[1] #! '1' does not match expected type 'T'
Ptr[1] #! expected type expression
#%% index_error_2,barebones
Ptr[int, 's'] #! Ptr takes 1 generics (2 given)