mirror of https://github.com/exaloop/codon.git
Remove RecordType
parent
df94b9061c
commit
f4fe8ec18f
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue