mirror of https://github.com/exaloop/codon.git
Fix static issues
parent
cff38ea734
commit
cdc8e17955
|
@ -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 {
|
||||
|
|
|
@ -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(),
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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')`
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 = "");
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue