diff --git a/codon/parser/cache.h b/codon/parser/cache.h index bef3629d..63f7161f 100644 --- a/codon/parser/cache.h +++ b/codon/parser/cache.h @@ -133,7 +133,8 @@ struct Cache : public std::enable_shared_from_this { /// Realization lookup table that maps a realized class name to the corresponding /// ClassRealization instance. std::unordered_map> realizations; - + /// List of inherited class. We also keep the number of fields each of inherited + /// class. std::vector> parentClasses; Class() : ast(nullptr), originalAst(nullptr) {} diff --git a/codon/parser/visitors/simplify/simplify.cpp b/codon/parser/visitors/simplify/simplify.cpp index 4dca7099..6c149a94 100644 --- a/codon/parser/visitors/simplify/simplify.cpp +++ b/codon/parser/visitors/simplify/simplify.cpp @@ -88,7 +88,7 @@ SimplifyVisitor::apply(Cache *cache, const StmtPtr &node, const std::string &fil } // Reserve the following static identifiers. for (auto name : {"staticlen", "compile_error", "isinstance", "hasattr", "type", - "TypeVar", "Callable", "argv", "super", "superf", "fn"}) + "TypeVar", "Callable", "argv", "super", "superf"}) stdlib->generateCanonicalName(name); stdlib->add(SimplifyItem::Var, "super", "super", true); stdlib->add(SimplifyItem::Var, "superf", "superf", true); diff --git a/codon/parser/visitors/typecheck/typecheck_expr.cpp b/codon/parser/visitors/typecheck/typecheck_expr.cpp index 3ea805c2..168431de 100644 --- a/codon/parser/visitors/typecheck/typecheck_expr.cpp +++ b/codon/parser/visitors/typecheck/typecheck_expr.cpp @@ -1958,12 +1958,14 @@ ExprPtr TypecheckVisitor::transformSuper(const CallExpr *expr) { auto fptyp = ctx->bases.back().type->getFunc(); if (!fptyp || fptyp->ast->hasAttr(Attr::Method)) error("no parent classes available"); + if (fptyp->args.size() < 2) + error("no parent classes available"); ClassTypePtr typ = fptyp->args[1]->getClass(); auto &cands = ctx->cache->classes[typ->name].parentClasses; if (cands.empty()) error("no parent classes available"); - if (typ->getRecord()) - error("cannot use super on tuple types"); + // if (typ->getRecord()) + // error("cannot use super on tuple types"); // find parent typ // unify top N args with parent typ args @@ -1976,22 +1978,34 @@ ExprPtr TypecheckVisitor::transformSuper(const CallExpr *expr) { seqassert(val, "cannot find '{}'", name); auto ftyp = ctx->instantiate(expr, val->type)->getClass(); - for (int i = 0; i < fields; i++) { - auto t = ctx->cache->classes[typ->name].fields[i].type; - t = ctx->instantiate(expr, t, typ.get()); + if (typ->getRecord()) { + std::vector members; + for (int i = 0; i < fields; i++) + members.push_back(N(N(fptyp->ast->args[0].name), + ctx->cache->classes[typ->name].fields[i].name)); + ExprPtr e = transform( + N(N(format(TYPE_TUPLE "{}", members.size())), members)); + unify(e->type, ftyp); + e->type = ftyp; + return e; + } else { + for (int i = 0; i < fields; i++) { + auto t = ctx->cache->classes[typ->name].fields[i].type; + t = ctx->instantiate(expr, t, typ.get()); - auto ft = ctx->cache->classes[name].fields[i].type; - ft = ctx->instantiate(expr, ft, ftyp.get()); - unify(t, ft); + auto ft = ctx->cache->classes[name].fields[i].type; + ft = ctx->instantiate(expr, ft, ftyp.get()); + unify(t, ft); + } + + ExprPtr typExpr = N(name); + typExpr->setType(ftyp); + auto self = fptyp->ast->args[0].name; + ExprPtr e = transform( + N(N(N("__internal__"), "to_class_ptr"), + N(N(N(self), "__raw__")), typExpr)); + return e; } - - ExprPtr typExpr = N(name); - typExpr->setType(ftyp); - auto self = fptyp->ast->args[0].name; - ExprPtr e = transform( - N(N(N("__internal__"), "to_class_ptr"), - N(N(N(self), "__raw__")), typExpr)); - return e; } } // namespace ast diff --git a/stdlib/internal/internal.codon b/stdlib/internal/internal.codon index dfcc1de2..cfe19211 100644 --- a/stdlib/internal/internal.codon +++ b/stdlib/internal/internal.codon @@ -131,6 +131,7 @@ class __internal__: %0 = bitcast i8* %ptr to {=T} ret {=T} %0 + @pure def _tuple_offsetof(x, field: Static[int]): @llvm def _llvm_offsetof(T: type, idx: Static[int], TE: type) -> int: