mirror of https://github.com/exaloop/codon.git
Remove RecordType
parent
df94b9061c
commit
f4fe8ec18f
|
@ -3,6 +3,19 @@
|
||||||
#include "error.h"
|
#include "error.h"
|
||||||
|
|
||||||
namespace codon {
|
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 {
|
namespace error {
|
||||||
|
|
||||||
char ParserErrorInfo::ID = 0;
|
char ParserErrorInfo::ID = 0;
|
||||||
|
|
|
@ -23,15 +23,9 @@ struct SrcInfo {
|
||||||
int len;
|
int len;
|
||||||
int id; /// used to differentiate different instances
|
int id; /// used to differentiate different instances
|
||||||
|
|
||||||
SrcInfo(std::string file, int line, int col, int len)
|
SrcInfo();
|
||||||
: file(std::move(file)), line(line), col(col), len(len), id(0) {
|
SrcInfo(std::string file, int line, int col, int len);
|
||||||
static int nextId = 0;
|
bool operator==(const SrcInfo &src) const;
|
||||||
id = nextId++;
|
|
||||||
};
|
|
||||||
|
|
||||||
SrcInfo() : SrcInfo("", 0, 0, 0) {}
|
|
||||||
|
|
||||||
bool operator==(const SrcInfo &src) const { return id == src.id; }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace codon
|
} // namespace codon
|
||||||
|
|
|
@ -396,8 +396,7 @@ ExprPtr TypecheckVisitor::callReorderArguments(FuncTypePtr calleeFn, CallExpr *e
|
||||||
std::vector<std::string> names;
|
std::vector<std::string> names;
|
||||||
std::vector<ExprPtr> values;
|
std::vector<ExprPtr> values;
|
||||||
if (!part.known.empty()) {
|
if (!part.known.empty()) {
|
||||||
auto e =
|
auto e = transform(N<DotExpr>(N<IdExpr>(part.var), "kwargs"));
|
||||||
transform(N<DotExpr>(N<IdExpr>(part.var), "kwargs"));
|
|
||||||
for (auto &[n, ne] : extractNamedTuple(e)) {
|
for (auto &[n, ne] : extractNamedTuple(e)) {
|
||||||
names.emplace_back(n);
|
names.emplace_back(n);
|
||||||
values.emplace_back(transform(ne));
|
values.emplace_back(transform(ne));
|
||||||
|
@ -567,7 +566,8 @@ bool TypecheckVisitor::typecheckCallArgs(const FuncTypePtr &calleeFn,
|
||||||
replacements.push_back(args[si].value->type);
|
replacements.push_back(args[si].value->type);
|
||||||
} else {
|
} else {
|
||||||
if (calleeFn->ast->args[si].type && !calleeFn->getArgTypes()[si]->canRealize()) {
|
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);
|
unify(calleeFn->getArgTypes()[si], t);
|
||||||
}
|
}
|
||||||
if (wrapExpr(args[si].value, calleeFn->getArgTypes()[si], calleeFn)) {
|
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));
|
members.push_back(N<DotExpr>(N<IdExpr>(funcTyp->ast->args[0].name), field.name));
|
||||||
ExprPtr e =
|
ExprPtr e =
|
||||||
transform(N<CallExpr>(N<IdExpr>(generateTuple(members.size())), members));
|
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;
|
return e;
|
||||||
} else {
|
} else {
|
||||||
// Case: reference types. Return `__internal__.class_super(self, T)`
|
// Case: reference types. Return `__internal__.class_super(self, T)`
|
||||||
|
@ -944,8 +950,7 @@ ExprPtr TypecheckVisitor::transformStaticLen(CallExpr *expr) {
|
||||||
if (!typ->getClass()->isRecord())
|
if (!typ->getClass()->isRecord())
|
||||||
E(Error::EXPECTED_TUPLE, expr->args[0].value);
|
E(Error::EXPECTED_TUPLE, expr->args[0].value);
|
||||||
return transform(
|
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.
|
/// Transform hasattr method to a static boolean expression.
|
||||||
|
@ -1031,20 +1036,14 @@ ExprPtr TypecheckVisitor::transformTupleFn(CallExpr *expr) {
|
||||||
return expr->shared_from_this();
|
return expr->shared_from_this();
|
||||||
|
|
||||||
std::vector<ExprPtr> items;
|
std::vector<ExprPtr> items;
|
||||||
ctx->addBlock();
|
auto ft = getClassFieldTypes(cls);
|
||||||
addClassGenerics(cls);
|
|
||||||
auto tn = generateTuple(ctx->cache->classes[cls->name].fields.size());
|
auto tn = generateTuple(ctx->cache->classes[cls->name].fields.size());
|
||||||
for (auto &ft : ctx->cache->classes[cls->name].fields) {
|
for (size_t i = 0; i < ft.size(); i++) {
|
||||||
auto t = ctx->instantiate(ft.type, cls);
|
auto rt = realize(ft[i]);
|
||||||
if (!t->canRealize() && ft.typeExpr) {
|
seqassert(rt, "cannot realize '{}' in {}",
|
||||||
auto tt = ctx->getType(transform(clean_clone(ft.typeExpr))->type);
|
ctx->cache->classes[cls->name].fields[i].name, cls);
|
||||||
unify(t, tt);
|
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));
|
auto e = transform(N<InstantiateExpr>(N<IdExpr>(tn), items));
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
|
@ -1065,7 +1064,8 @@ ExprPtr TypecheckVisitor::transformTypeFn(CallExpr *expr) {
|
||||||
if (!ctx->allowTypeOf)
|
if (!ctx->allowTypeOf)
|
||||||
E(Error::CALL_NO_TYPE, getSrcInfo());
|
E(Error::CALL_NO_TYPE, getSrcInfo());
|
||||||
transform(expr->args[0].value);
|
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))
|
if (!realize(expr->type))
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
|
|
|
@ -203,8 +203,7 @@ types::TypePtr TypecheckVisitor::realizeType(types::ClassType *type) {
|
||||||
|
|
||||||
// Check if the type was already realized
|
// Check if the type was already realized
|
||||||
auto rn = type->ClassType::realizedName();
|
auto rn = type->ClassType::realizedName();
|
||||||
if (auto r =
|
if (auto r = in(ctx->cache->classes[type->name].realizations, rn)) {
|
||||||
in(ctx->cache->classes[type->name].realizations, rn)) {
|
|
||||||
return (*r)->type->getClass();
|
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<ir::types::Type *> typeArgs; // needed for IR
|
||||||
std::vector<std::string> names; // needed for IR
|
std::vector<std::string> names; // needed for IR
|
||||||
std::map<std::string, SrcInfo> memberInfo; // needed for IR
|
std::map<std::string, SrcInfo> memberInfo; // needed for IR
|
||||||
ctx->addBlock();
|
|
||||||
addClassGenerics(realized);
|
const auto &fields = ctx->cache->classes[realized->name].fields;
|
||||||
for (auto &field : ctx->cache->classes[realized->name].fields) {
|
auto fTypes = getClassFieldTypes(realized);
|
||||||
auto ftyp = ctx->instantiate(field.type, realized);
|
for (size_t i = 0; i < fTypes.size(); i++) {
|
||||||
if (!ftyp->canRealize() && field.typeExpr) {
|
if (!realize(fTypes[i])) {
|
||||||
auto t = ctx->getType(transform(clean_clone(field.typeExpr))->type);
|
realize(fTypes[i]);
|
||||||
unify(ftyp, t);
|
E(Error::TYPE_CANNOT_REALIZE_ATTR, getSrcInfo(), fields[i].name,
|
||||||
}
|
|
||||||
if (!realize(ftyp)) {
|
|
||||||
realize(ftyp);
|
|
||||||
E(Error::TYPE_CANNOT_REALIZE_ATTR, getSrcInfo(), field.name,
|
|
||||||
realized->prettyString());
|
realized->prettyString());
|
||||||
}
|
}
|
||||||
// LOG_REALIZE("- member: {} -> {}: {}", field.name, field.type, ftyp);
|
// LOG_REALIZE("- member: {} -> {}: {}", field.name, field.type, fTypes[i]);
|
||||||
realization->fields.emplace_back(field.name, ftyp);
|
realization->fields.emplace_back(fields[i].name, fTypes[i]);
|
||||||
names.emplace_back(field.name);
|
names.emplace_back(fields[i].name);
|
||||||
typeArgs.emplace_back(makeIRType(ftyp->getClass().get()));
|
typeArgs.emplace_back(makeIRType(fTypes[i]->getClass().get()));
|
||||||
memberInfo[field.name] = field.type->getSrcInfo();
|
memberInfo[fields[i].name] = fTypes[i]->getSrcInfo();
|
||||||
}
|
}
|
||||||
ctx->popBlock();
|
|
||||||
|
|
||||||
// Set IR attributes
|
// Set IR attributes
|
||||||
if (!names.empty()) {
|
if (!names.empty()) {
|
||||||
|
@ -663,8 +657,8 @@ ir::types::Type *TypecheckVisitor::makeIRType(types::ClassType *t) {
|
||||||
auto forceFindIRType = [&](const TypePtr &tt) {
|
auto forceFindIRType = [&](const TypePtr &tt) {
|
||||||
auto t = tt->getClass();
|
auto t = tt->getClass();
|
||||||
auto rn = t->ClassType::realizedName();
|
auto rn = t->ClassType::realizedName();
|
||||||
seqassert(t && in(ctx->cache->classes[t->name].realizations, rn),
|
seqassert(t && in(ctx->cache->classes[t->name].realizations, rn), "{} not realized",
|
||||||
"{} not realized", tt);
|
tt);
|
||||||
auto l = ctx->cache->classes[t->name].realizations[rn]->ir;
|
auto l = ctx->cache->classes[t->name].realizations[rn]->ir;
|
||||||
seqassert(l, "no LLVM type for {}", t);
|
seqassert(l, "no LLVM type for {}", t);
|
||||||
return l;
|
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<ir::types::Type *> typeArgs; // needed for IR
|
||||||
std::vector<std::string> names; // needed for IR
|
std::vector<std::string> names; // needed for IR
|
||||||
std::map<std::string, SrcInfo> memberInfo; // needed for IR
|
std::map<std::string, SrcInfo> memberInfo; // needed for IR
|
||||||
ctx->addBlock();
|
|
||||||
auto pp = t->shared_from_this()->getClass();
|
auto ft = getClassFieldTypes(t->getClass());
|
||||||
addClassGenerics(pp);
|
const auto &fields = ctx->cache->classes[t->getClass()->name].fields;
|
||||||
for (auto &field : ctx->cache->classes[t->name].fields) {
|
for (size_t i = 0; i < ft.size(); i++) {
|
||||||
auto ftyp = ctx->instantiate(field.type, pp);
|
if (!realize(ft[i])) {
|
||||||
if (!ftyp->canRealize() && field.typeExpr) {
|
realize(ft[i]);
|
||||||
auto t = ctx->getType(transform(clean_clone(field.typeExpr))->type);
|
E(Error::TYPE_CANNOT_REALIZE_ATTR, getSrcInfo(), fields[i].name,
|
||||||
unify(ftyp, t);
|
|
||||||
}
|
|
||||||
if (!realize(ftyp)) {
|
|
||||||
realize(ftyp);
|
|
||||||
E(Error::TYPE_CANNOT_REALIZE_ATTR, getSrcInfo(), field.name,
|
|
||||||
t->prettyString());
|
t->prettyString());
|
||||||
}
|
}
|
||||||
// LOG_REALIZE("- member: {} -> {}: {}", field.name, field.type, ftyp);
|
names.emplace_back(fields[i].name);
|
||||||
names.emplace_back(field.name);
|
typeArgs.emplace_back(makeIRType(ft[i]->getClass().get()));
|
||||||
typeArgs.emplace_back(makeIRType(ftyp->getClass().get()));
|
memberInfo[fields[i].name] = ft[i]->getSrcInfo();
|
||||||
memberInfo[field.name] = field.type->getSrcInfo();
|
|
||||||
}
|
}
|
||||||
ctx->popBlock();
|
|
||||||
auto record =
|
auto record =
|
||||||
ir::cast<ir::types::RecordType>(module->unsafeGetMemberedType(realizedName));
|
ir::cast<ir::types::RecordType>(module->unsafeGetMemberedType(realizedName));
|
||||||
record->realize(typeArgs, names);
|
record->realize(typeArgs, names);
|
||||||
handle = record;
|
handle = record;
|
||||||
handle->setAttribute(std::make_unique<ir::MemberAttribute>(std::move(memberInfo)));
|
handle->setAttribute(
|
||||||
|
std::make_unique<ir::MemberAttribute>(std::move(memberInfo)));
|
||||||
} else {
|
} else {
|
||||||
handle = module->unsafeGetMemberedType(realizedName, !t->isRecord());
|
handle = module->unsafeGetMemberedType(realizedName, !t->isRecord());
|
||||||
if (ctx->cache->classes[t->name].rtti)
|
if (ctx->cache->classes[t->name].rtti)
|
||||||
|
@ -855,7 +843,8 @@ TypecheckVisitor::generateSpecialAst(types::FuncType *type) {
|
||||||
items.push_back(nullptr);
|
items.push_back(nullptr);
|
||||||
std::vector<std::string> ll;
|
std::vector<std::string> ll;
|
||||||
std::vector<std::string> lla;
|
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 as = type->getArgTypes()[1]->getClass()->generics.size();
|
||||||
auto ag = ast->args[1].name;
|
auto ag = ast->args[1].name;
|
||||||
trimStars(ag);
|
trimStars(ag);
|
||||||
|
|
|
@ -654,6 +654,7 @@ void ScopingVisitor::visit(StringExpr *expr) {
|
||||||
for (auto &p : expr->strings) {
|
for (auto &p : expr->strings) {
|
||||||
if (p.second == "f" || p.second == "F") {
|
if (p.second == "f" || p.second == "F") {
|
||||||
/// Transform an F-string
|
/// Transform an F-string
|
||||||
|
setSrcInfo(expr->getSrcInfo());
|
||||||
exprs.push_back(transformFString(p.first));
|
exprs.push_back(transformFString(p.first));
|
||||||
} else if (!p.second.empty()) {
|
} else if (!p.second.empty()) {
|
||||||
/// Custom prefix strings:
|
/// Custom prefix strings:
|
||||||
|
|
|
@ -696,4 +696,20 @@ types::TypePtr TypecheckVisitor::getType(const ExprPtr &e) {
|
||||||
return t;
|
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
|
} // namespace codon::ast
|
||||||
|
|
|
@ -294,6 +294,8 @@ private:
|
||||||
StmtPtr prepareVTables();
|
StmtPtr prepareVTables();
|
||||||
std::vector<std::pair<std::string, ExprPtr>> extractNamedTuple(ExprPtr);
|
std::vector<std::pair<std::string, ExprPtr>> extractNamedTuple(ExprPtr);
|
||||||
|
|
||||||
|
std::vector<types::TypePtr> getClassFieldTypes(const types::ClassTypePtr &);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
bool wrapExpr(ExprPtr &expr, const types::TypePtr &expectedType,
|
bool wrapExpr(ExprPtr &expr, const types::TypePtr &expectedType,
|
||||||
const types::FuncTypePtr &callee = nullptr, bool allowUnwrap = true);
|
const types::FuncTypePtr &callee = nullptr, bool allowUnwrap = true);
|
||||||
|
|
Loading…
Reference in New Issue