Remove RecordType

typecheck-v2
Ibrahim Numanagić 2024-03-13 12:54:30 -07:00
parent df94b9061c
commit f4fe8ec18f
7 changed files with 87 additions and 72 deletions

View File

@ -3,6 +3,19 @@
#include "error.h"
namespace codon {
SrcInfo::SrcInfo(std::string file, int line, int col, int len)
: file(std::move(file)), line(line), col(col), len(len), id(0) {
if (this->file.empty() && line != 0)
line++;
static int nextId = 0;
id = nextId++;
};
SrcInfo::SrcInfo() : SrcInfo("", 0, 0, 0) {}
bool SrcInfo::operator==(const SrcInfo &src) const { return id == src.id; }
namespace error {
char ParserErrorInfo::ID = 0;

View File

@ -23,15 +23,9 @@ struct SrcInfo {
int len;
int id; /// used to differentiate different instances
SrcInfo(std::string file, int line, int col, int len)
: file(std::move(file)), line(line), col(col), len(len), id(0) {
static int nextId = 0;
id = nextId++;
};
SrcInfo() : SrcInfo("", 0, 0, 0) {}
bool operator==(const SrcInfo &src) const { return id == src.id; }
SrcInfo();
SrcInfo(std::string file, int line, int col, int len);
bool operator==(const SrcInfo &src) const;
};
} // namespace codon

View File

@ -396,8 +396,7 @@ ExprPtr TypecheckVisitor::callReorderArguments(FuncTypePtr calleeFn, CallExpr *e
std::vector<std::string> names;
std::vector<ExprPtr> values;
if (!part.known.empty()) {
auto e =
transform(N<DotExpr>(N<IdExpr>(part.var), "kwargs"));
auto e = transform(N<DotExpr>(N<IdExpr>(part.var), "kwargs"));
for (auto &[n, ne] : extractNamedTuple(e)) {
names.emplace_back(n);
values.emplace_back(transform(ne));
@ -567,7 +566,8 @@ bool TypecheckVisitor::typecheckCallArgs(const FuncTypePtr &calleeFn,
replacements.push_back(args[si].value->type);
} else {
if (calleeFn->ast->args[si].type && !calleeFn->getArgTypes()[si]->canRealize()) {
auto t = ctx->getType(transform(clean_clone(calleeFn->ast->args[si].type))->type);
auto t =
ctx->getType(transform(clean_clone(calleeFn->ast->args[si].type))->type);
unify(calleeFn->getArgTypes()[si], t);
}
if (wrapExpr(args[si].value, calleeFn->getArgTypes()[si], calleeFn)) {
@ -819,7 +819,13 @@ ExprPtr TypecheckVisitor::transformSuper() {
members.push_back(N<DotExpr>(N<IdExpr>(funcTyp->ast->args[0].name), field.name));
ExprPtr e =
transform(N<CallExpr>(N<IdExpr>(generateTuple(members.size())), members));
e->type = unify(superTyp, e->type); // see super_tuple test for this line
auto ft = getClassFieldTypes(superTyp);
for (size_t i = 0; i < ft.size(); i++)
unify(
ft[i],
e->type->getClass()->generics[i].type); // see super_tuple test for this line
e->type = superTyp;
return e;
} else {
// Case: reference types. Return `__internal__.class_super(self, T)`
@ -944,8 +950,7 @@ ExprPtr TypecheckVisitor::transformStaticLen(CallExpr *expr) {
if (!typ->getClass()->isRecord())
E(Error::EXPECTED_TUPLE, expr->args[0].value);
return transform(
N<IntExpr>(ctx->cache->classes[typ->getClass()->name].fields.size())
);
N<IntExpr>(ctx->cache->classes[typ->getClass()->name].fields.size()));
}
/// Transform hasattr method to a static boolean expression.
@ -1031,20 +1036,14 @@ ExprPtr TypecheckVisitor::transformTupleFn(CallExpr *expr) {
return expr->shared_from_this();
std::vector<ExprPtr> items;
ctx->addBlock();
addClassGenerics(cls);
auto ft = getClassFieldTypes(cls);
auto tn = generateTuple(ctx->cache->classes[cls->name].fields.size());
for (auto &ft : ctx->cache->classes[cls->name].fields) {
auto t = ctx->instantiate(ft.type, cls);
if (!t->canRealize() && ft.typeExpr) {
auto tt = ctx->getType(transform(clean_clone(ft.typeExpr))->type);
unify(t, tt);
for (size_t i = 0; i < ft.size(); i++) {
auto rt = realize(ft[i]);
seqassert(rt, "cannot realize '{}' in {}",
ctx->cache->classes[cls->name].fields[i].name, cls);
items.push_back(N<IdExpr>(rt->realizedName()));
}
auto rt = realize(t);
seqassert(rt, "cannot realize '{}' in {}", t, ft.name);
items.push_back(N<IdExpr>(t->realizedName()));
}
ctx->popBlock();
auto e = transform(N<InstantiateExpr>(N<IdExpr>(tn), items));
return e;
}
@ -1065,7 +1064,8 @@ ExprPtr TypecheckVisitor::transformTypeFn(CallExpr *expr) {
if (!ctx->allowTypeOf)
E(Error::CALL_NO_TYPE, getSrcInfo());
transform(expr->args[0].value);
unify(expr->type, ctx->instantiateGeneric(ctx->getType("type"), {expr->args[0].value->getType()}));
unify(expr->type, ctx->instantiateGeneric(ctx->getType("type"),
{expr->args[0].value->getType()}));
if (!realize(expr->type))
return nullptr;

View File

@ -203,8 +203,7 @@ types::TypePtr TypecheckVisitor::realizeType(types::ClassType *type) {
// Check if the type was already realized
auto rn = type->ClassType::realizedName();
if (auto r =
in(ctx->cache->classes[type->name].realizations, rn)) {
if (auto r = in(ctx->cache->classes[type->name].realizations, rn)) {
return (*r)->type->getClass();
}
@ -244,26 +243,21 @@ types::TypePtr TypecheckVisitor::realizeType(types::ClassType *type) {
std::vector<ir::types::Type *> typeArgs; // needed for IR
std::vector<std::string> names; // needed for IR
std::map<std::string, SrcInfo> memberInfo; // needed for IR
ctx->addBlock();
addClassGenerics(realized);
for (auto &field : ctx->cache->classes[realized->name].fields) {
auto ftyp = ctx->instantiate(field.type, realized);
if (!ftyp->canRealize() && field.typeExpr) {
auto t = ctx->getType(transform(clean_clone(field.typeExpr))->type);
unify(ftyp, t);
}
if (!realize(ftyp)) {
realize(ftyp);
E(Error::TYPE_CANNOT_REALIZE_ATTR, getSrcInfo(), field.name,
const auto &fields = ctx->cache->classes[realized->name].fields;
auto fTypes = getClassFieldTypes(realized);
for (size_t i = 0; i < fTypes.size(); i++) {
if (!realize(fTypes[i])) {
realize(fTypes[i]);
E(Error::TYPE_CANNOT_REALIZE_ATTR, getSrcInfo(), fields[i].name,
realized->prettyString());
}
// LOG_REALIZE("- member: {} -> {}: {}", field.name, field.type, ftyp);
realization->fields.emplace_back(field.name, ftyp);
names.emplace_back(field.name);
typeArgs.emplace_back(makeIRType(ftyp->getClass().get()));
memberInfo[field.name] = field.type->getSrcInfo();
// LOG_REALIZE("- member: {} -> {}: {}", field.name, field.type, fTypes[i]);
realization->fields.emplace_back(fields[i].name, fTypes[i]);
names.emplace_back(fields[i].name);
typeArgs.emplace_back(makeIRType(fTypes[i]->getClass().get()));
memberInfo[fields[i].name] = fTypes[i]->getSrcInfo();
}
ctx->popBlock();
// Set IR attributes
if (!names.empty()) {
@ -663,8 +657,8 @@ ir::types::Type *TypecheckVisitor::makeIRType(types::ClassType *t) {
auto forceFindIRType = [&](const TypePtr &tt) {
auto t = tt->getClass();
auto rn = t->ClassType::realizedName();
seqassert(t && in(ctx->cache->classes[t->name].realizations, rn),
"{} not realized", tt);
seqassert(t && in(ctx->cache->classes[t->name].realizations, rn), "{} not realized",
tt);
auto l = ctx->cache->classes[t->name].realizations[rn]->ir;
seqassert(l, "no LLVM type for {}", t);
return l;
@ -737,31 +731,25 @@ ir::types::Type *TypecheckVisitor::makeIRType(types::ClassType *t) {
std::vector<ir::types::Type *> typeArgs; // needed for IR
std::vector<std::string> names; // needed for IR
std::map<std::string, SrcInfo> memberInfo; // needed for IR
ctx->addBlock();
auto pp = t->shared_from_this()->getClass();
addClassGenerics(pp);
for (auto &field : ctx->cache->classes[t->name].fields) {
auto ftyp = ctx->instantiate(field.type, pp);
if (!ftyp->canRealize() && field.typeExpr) {
auto t = ctx->getType(transform(clean_clone(field.typeExpr))->type);
unify(ftyp, t);
}
if (!realize(ftyp)) {
realize(ftyp);
E(Error::TYPE_CANNOT_REALIZE_ATTR, getSrcInfo(), field.name,
auto ft = getClassFieldTypes(t->getClass());
const auto &fields = ctx->cache->classes[t->getClass()->name].fields;
for (size_t i = 0; i < ft.size(); i++) {
if (!realize(ft[i])) {
realize(ft[i]);
E(Error::TYPE_CANNOT_REALIZE_ATTR, getSrcInfo(), fields[i].name,
t->prettyString());
}
// LOG_REALIZE("- member: {} -> {}: {}", field.name, field.type, ftyp);
names.emplace_back(field.name);
typeArgs.emplace_back(makeIRType(ftyp->getClass().get()));
memberInfo[field.name] = field.type->getSrcInfo();
names.emplace_back(fields[i].name);
typeArgs.emplace_back(makeIRType(ft[i]->getClass().get()));
memberInfo[fields[i].name] = ft[i]->getSrcInfo();
}
ctx->popBlock();
auto record =
ir::cast<ir::types::RecordType>(module->unsafeGetMemberedType(realizedName));
record->realize(typeArgs, names);
handle = record;
handle->setAttribute(std::make_unique<ir::MemberAttribute>(std::move(memberInfo)));
handle->setAttribute(
std::make_unique<ir::MemberAttribute>(std::move(memberInfo)));
} else {
handle = module->unsafeGetMemberedType(realizedName, !t->isRecord());
if (ctx->cache->classes[t->name].rtti)
@ -855,7 +843,8 @@ TypecheckVisitor::generateSpecialAst(types::FuncType *type) {
items.push_back(nullptr);
std::vector<std::string> ll;
std::vector<std::string> lla;
seqassert(startswith(type->getArgTypes()[1]->getClass()->name, TYPE_TUPLE), "bad function base");
seqassert(startswith(type->getArgTypes()[1]->getClass()->name, TYPE_TUPLE),
"bad function base");
auto as = type->getArgTypes()[1]->getClass()->generics.size();
auto ag = ast->args[1].name;
trimStars(ag);

View File

@ -654,6 +654,7 @@ void ScopingVisitor::visit(StringExpr *expr) {
for (auto &p : expr->strings) {
if (p.second == "f" || p.second == "F") {
/// Transform an F-string
setSrcInfo(expr->getSrcInfo());
exprs.push_back(transformFString(p.first));
} else if (!p.second.empty()) {
/// Custom prefix strings:

View File

@ -696,4 +696,20 @@ types::TypePtr TypecheckVisitor::getType(const ExprPtr &e) {
return t;
}
std::vector<types::TypePtr> TypecheckVisitor::getClassFieldTypes(const types::ClassTypePtr &cls) {
std::vector<types::TypePtr> result;
ctx->addBlock();
addClassGenerics(cls);
for (auto &field : ctx->cache->classes[cls->name].fields) {
auto ftyp = ctx->instantiate(field.type, cls);
if (!ftyp->canRealize() && field.typeExpr) {
auto t = ctx->getType(transform(clean_clone(field.typeExpr))->type);
unify(ftyp, t);
}
result.push_back(ftyp);
}
ctx->popBlock();
return result;
}
} // namespace codon::ast

View File

@ -294,6 +294,8 @@ private:
StmtPtr prepareVTables();
std::vector<std::pair<std::string, ExprPtr>> extractNamedTuple(ExprPtr);
std::vector<types::TypePtr> getClassFieldTypes(const types::ClassTypePtr &);
public:
bool wrapExpr(ExprPtr &expr, const types::TypePtr &expectedType,
const types::FuncTypePtr &callee = nullptr, bool allowUnwrap = true);