Merge simplify & typecheck [wip]

typecheck-v2
Ibrahim Numanagić 2023-07-05 11:58:22 +02:00
parent 9cad341b25
commit 87419e9ac3
10 changed files with 27 additions and 16 deletions

View File

@ -198,7 +198,7 @@ void TranslateVisitor::visit(CallExpr *expr) {
expr->args[0].value->getId()->value);
result = make<ir::PointerValue>(expr, val->getVar());
return;
} else if (expr->expr->isId("__array__.__new__:0")) {
} else if (expr->expr->isId("__array__.__new__")) {
auto fnt = expr->expr->type->getFunc();
auto szt = fnt->funcGenerics[0].type->getStatic();
auto sz = szt->evaluate().getInt();
@ -209,7 +209,7 @@ void TranslateVisitor::visit(CallExpr *expr) {
result = make<ir::StackAllocInstr>(expr, arrayType, sz);
return;
} else if (expr->expr->getId() && startswith(expr->expr->getId()->value,
"__internal__.yield_in_no_suspend:0")) {
"__internal__.yield_in_no_suspend")) {
result = make<ir::YieldInInstr>(expr, getType(expr->getType()), false);
return;
}

View File

@ -31,7 +31,7 @@ void TypecheckVisitor::visit(AssignExpr *expr) {
transform(expr->var);
leaveConditionalBlock(s);
} else {
s = transform(s);
transform(s);
transform(expr->var);
}
std::swap(avoidDomination, ctx->avoidDomination);

View File

@ -1217,6 +1217,7 @@ std::pair<bool, ExprPtr> TypecheckVisitor::transformInternalStaticFn(CallExpr *e
}
idx++;
}
LOG("-> {}", tupleItems);
return {true, transform(N<TupleExpr>(tupleItems))};
} else if (expr->expr->isId("std.internal.static.tuple_type.0")) {
auto funcTyp = expr->expr->type->getFunc();

View File

@ -97,6 +97,7 @@ void TypecheckVisitor::visit(ClassStmt *stmt) {
generic->getUnbound()->id = val->type->getLink()->id;
ctx->addType(ctx->cache->rev(val->canonicalName), val->canonicalName, generic)
->generic = true;
args.emplace_back(val->canonicalName, nullptr, nullptr, a.status);
}
} else {
// Add all generics before parent classes, fields and methods
@ -345,7 +346,8 @@ void TypecheckVisitor::visit(ClassStmt *stmt) {
for (auto &m : ctx->cache->classes[canonicalName].fields)
LOG(" - member: {}: {:D}", m.name, m.type);
for (auto &m : ctx->cache->classes[canonicalName].methods)
LOG(" - method: {}: {}", m.first, m.second);
LOG(" - method: {}: {} ({:D})", m.first, m.second,
ctx->cache->functions[m.second].type);
} catch (const exc::ParserException &) {
if (!stmt->attributes.has(Attr::Tuple))
ctx->remove(name);

View File

@ -33,8 +33,8 @@ TypeContext::TypeContext(Cache *cache, std::string filename)
void TypeContext::add(const std::string &name, const TypeContext::Item &var) {
seqassert(!var->scope.empty(), "bad scope for '{}'", name);
// LOG("[ctx] {} @ {}: + {}: {} ({})", getModule(), getSrcInfo(), name,
// var->canonicalName, var->scope);
// LOG("[ctx] {} @ {}: + {}: {} ({:D})", getModule(), getSrcInfo(), name,
// var->canonicalName, var->type);
Context<TypecheckItem>::add(name, var);
}
@ -86,6 +86,7 @@ TypeContext::Item TypeContext::addFunc(const std::string &name,
}
TypeContext::Item TypeContext::addAlwaysVisible(const TypeContext::Item &item) {
add(item->canonicalName, item);
if (!cache->typeCtx->Context<TypecheckItem>::find(item->canonicalName)) {
cache->typeCtx->add(item->canonicalName, item);

View File

@ -268,8 +268,9 @@ void TypecheckVisitor::visit(FunctionStmt *stmt) {
// auto parentClassAST =
// ctx->cache->classes[stmt->attributes.parentClass].ast.get();
parentClass = ctx->forceFind(stmt->attributes.parentClass)->type->getClass();
parentClass = parentClass->instantiate(ctx->typecheckLevel - 1, nullptr, nullptr)
->getClass();
// parentClass = parentClass->instantiate(ctx->typecheckLevel - 1, nullptr,
// nullptr)
// ->getClass();
// seqassert(parentClass, "parent class not set");
// for (int i = 0, j = 0, k = 0; i < parentClassAST->args.size(); i++) {
// if (parentClassAST->args[i].status != Param::Normal) {
@ -439,7 +440,7 @@ void TypecheckVisitor::visit(FunctionStmt *stmt) {
}
// Debug information
LOG("[stmt] added func {}: {}", canonicalName, funcTyp->debugString(2));
// LOG("[stmt] added func {}: {}", canonicalName, funcTyp->debugString(2));
// Expression to be used if function binding is modified by captures or decorators
ExprPtr finalExpr = nullptr;

View File

@ -326,6 +326,7 @@ types::TypePtr TypecheckVisitor::realizeFunc(types::FuncType *type, bool force)
trimStars(varName);
auto v = ctx->addVar(ctx->cache->rev(varName), varName,
std::make_shared<LinkType>(type->getArgTypes()[j++]));
// LOG("[param] {} -> {}", v->canonicalName, v->type);
}
// Populate realization table in advance to support recursive realizations
@ -342,10 +343,11 @@ types::TypePtr TypecheckVisitor::realizeFunc(types::FuncType *type, bool force)
std::make_shared<TypecheckItem>(key, "", ctx->getModule(), type->getFunc());
ctx->addAlwaysVisible(val);
auto ast_suite = clone(ast->suite);
if (hasAst) {
auto oldBlockLevel = ctx->blockLevel;
ctx->blockLevel = 0;
auto ret = inferTypes(ast->suite);
auto ret = inferTypes(ast_suite);
ctx->blockLevel = oldBlockLevel;
if (!ret) {
@ -354,7 +356,7 @@ types::TypePtr TypecheckVisitor::realizeFunc(types::FuncType *type, bool force)
// Lambda typecheck failures are "ignored" as they are treated as statements,
// not functions.
// TODO: generalize this further.
LOG("[error=>] {}", ast->suite->toString(2));
LOG("[error=>] {}", ast_suite->toString(2));
// inferTypes(ast->suite, ctx);
error("cannot typecheck the program");
}
@ -364,6 +366,8 @@ types::TypePtr TypecheckVisitor::realizeFunc(types::FuncType *type, bool force)
getLogger().level--;
this->ctx = oldCtx;
return nullptr; // inference must be delayed
} else {
ast_suite = ret;
}
// Use NoneType as the return type when the return type is not specified and
@ -383,7 +387,7 @@ types::TypePtr TypecheckVisitor::realizeFunc(types::FuncType *type, bool force)
args.emplace_back(varName, nullptr, nullptr, i.status);
}
r->ast = N<FunctionStmt>(ast->getSrcInfo(), r->type->realizedName(), nullptr, args,
ast->suite);
ast_suite);
r->ast->attributes = ast->attributes;
if (!in(ctx->cache->pendingRealizations,

View File

@ -30,8 +30,8 @@ void TypecheckVisitor::visit(UnaryExpr *expr) {
if (expr->op == "!") {
// `not expr` -> `expr.__bool__().__invert__()`
resultExpr = transform(N<CallExpr>(N<DotExpr>(
N<CallExpr>(N<DotExpr>(clone(expr->expr), "__bool__")), "__invert__")));
resultExpr = transform(N<CallExpr>(
N<DotExpr>(N<CallExpr>(N<DotExpr>(expr->expr, "__bool__")), "__invert__")));
} else {
std::string magic;
if (expr->op == "~")
@ -43,7 +43,7 @@ void TypecheckVisitor::visit(UnaryExpr *expr) {
else
seqassert(false, "invalid unary operator '{}'", expr->op);
resultExpr =
transform(N<CallExpr>(N<DotExpr>(clone(expr->expr), format("__{}__", magic))));
transform(N<CallExpr>(N<DotExpr>(expr->expr, format("__{}__", magic))));
}
}

View File

@ -293,6 +293,8 @@ void TypecheckVisitor::defaultVisit(Stmt *s) {
/// Typecheck statement expressions.
void TypecheckVisitor::visit(StmtExpr *expr) {
auto done = true;
if (expr->expr->isId("chain.0"))
LOG("--");
for (auto &s : expr->stmts) {
transform(s);
done &= s->isDone();

View File

@ -8,7 +8,7 @@ from internal.static import vars_types, tuple_type, vars as _vars
def vars(obj, with_index: Static[int] = 0):
__static_print__(with_index)
__static_print__(obj, with_index)
return _vars(obj, with_index)