mirror of https://github.com/exaloop/codon.git
Merge branch 'new-super' of https://github.com/exaloop/codon into new-super
commit
3ef57416b9
|
@ -29,7 +29,6 @@
|
|||
#define TYPE_SLICE "std.internal.types.slice.Slice"
|
||||
#define FN_UNWRAP "std.internal.types.optional.unwrap"
|
||||
#define VAR_ARGV "__argv__"
|
||||
#define VAR_CLSID ".__id__"
|
||||
|
||||
#define MAX_INT_WIDTH 10000
|
||||
#define MAX_REALIZATION_DEPTH 200
|
||||
|
@ -115,6 +114,8 @@ struct Cache : public std::enable_shared_from_this<Cache> {
|
|||
std::string name;
|
||||
/// A corresponding generic field type.
|
||||
types::TypePtr type;
|
||||
/// Base class name (if available)
|
||||
std::string baseClass;
|
||||
};
|
||||
/// A list of class' ClassField instances. List is needed (instead of map) because
|
||||
/// the order of the fields matters.
|
||||
|
@ -149,6 +150,8 @@ struct Cache : public std::enable_shared_from_this<Cache> {
|
|||
/// ClassRealization instance.
|
||||
std::unordered_map<std::string, std::shared_ptr<ClassRealization>> realizations;
|
||||
|
||||
/// Set if a class is polymorphic and has RTTI.
|
||||
bool rtti = false;
|
||||
/// List of virtual method names
|
||||
std::unordered_set<std::string> virtuals;
|
||||
/// MRO
|
||||
|
|
|
@ -86,8 +86,8 @@ void SimplifyVisitor::visit(ClassStmt *stmt) {
|
|||
} else {
|
||||
ctx->addType(genName, varName, a.type->getSrcInfo())->generic = true;
|
||||
}
|
||||
args.emplace_back(Param{varName, transformType(clone(a.type), false),
|
||||
transformType(clone(a.defaultValue), false), a.status});
|
||||
args.emplace_back(varName, transformType(clone(a.type), false),
|
||||
transformType(clone(a.defaultValue), false), a.status);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -108,14 +108,15 @@ void SimplifyVisitor::visit(ClassStmt *stmt) {
|
|||
|
||||
// Collect classes (and their fields) that are to be statically inherited
|
||||
std::vector<ClassStmt *> staticBaseASTs, baseASTs;
|
||||
std::vector<std::string> args_classes(args.size(), "");
|
||||
if (!stmt->attributes.has(Attr::Extend)) {
|
||||
staticBaseASTs = parseBaseClasses(stmt->staticBaseClasses, args, stmt->attributes,
|
||||
canonicalName);
|
||||
staticBaseASTs = parseBaseClasses(stmt->staticBaseClasses, args, args_classes,
|
||||
stmt->attributes, canonicalName);
|
||||
if (ctx->cache->isJit && !stmt->baseClasses.empty())
|
||||
E(Error::CUSTOM, stmt->baseClasses[0],
|
||||
"inheritance is not yet supported in JIT mode");
|
||||
parseBaseClasses(stmt->baseClasses, args, stmt->attributes, canonicalName,
|
||||
transformedTypeAst);
|
||||
parseBaseClasses(stmt->baseClasses, args, args_classes, stmt->attributes,
|
||||
canonicalName, transformedTypeAst);
|
||||
}
|
||||
|
||||
// A ClassStmt will be separated into class variable assignments, method-free
|
||||
|
@ -126,8 +127,9 @@ void SimplifyVisitor::visit(ClassStmt *stmt) {
|
|||
for (auto &a : argsToParse) {
|
||||
if (a.status == Param::Normal) {
|
||||
if (!ClassStmt::isClassVar(a)) {
|
||||
args.emplace_back(Param{a.name, transformType(clone(a.type), false),
|
||||
transform(clone(a.defaultValue), true)});
|
||||
args.emplace_back(a.name, transformType(clone(a.type), false),
|
||||
transform(clone(a.defaultValue), true));
|
||||
args_classes.emplace_back();
|
||||
} else if (!stmt->attributes.has(Attr::Extend)) {
|
||||
// Handle class variables. Transform them later to allow self-references
|
||||
auto name = format("{}.{}", canonicalName, a.name);
|
||||
|
@ -153,7 +155,8 @@ void SimplifyVisitor::visit(ClassStmt *stmt) {
|
|||
if (!stmt->attributes.has(Attr::Extend)) {
|
||||
for (size_t ai = 0; ai < args.size();) {
|
||||
if (args[ai].status == Param::Normal)
|
||||
ctx->cache->classes[canonicalName].fields.push_back({args[ai].name, nullptr});
|
||||
ctx->cache->classes[canonicalName].fields.push_back(
|
||||
Cache::Class::ClassField{args[ai].name, nullptr, args_classes[ai]});
|
||||
ai++;
|
||||
}
|
||||
}
|
||||
|
@ -289,7 +292,8 @@ void SimplifyVisitor::visit(ClassStmt *stmt) {
|
|||
/// @param typeAst Transformed AST for base class type (e.g., `A[T]`).
|
||||
/// Only set when dealing with dynamic polymorphism.
|
||||
std::vector<ClassStmt *> SimplifyVisitor::parseBaseClasses(
|
||||
std::vector<ExprPtr> &baseClasses, std::vector<Param> &args, const Attr &attr,
|
||||
std::vector<ExprPtr> &baseClasses, std::vector<Param> &args,
|
||||
std::vector<std::string> &args_classes, const Attr &attr,
|
||||
const std::string &canonicalName, const ExprPtr &typeAst) {
|
||||
std::vector<ClassStmt *> asts;
|
||||
|
||||
|
@ -327,14 +331,9 @@ std::vector<ClassStmt *> SimplifyVisitor::parseBaseClasses(
|
|||
if (asts.back()->attributes.has(Attr::Internal))
|
||||
E(Error::CLASS_NO_INHERIT, getSrcInfo(), "internal");
|
||||
|
||||
// Add __vtable__ to parent classes if it is not there already
|
||||
auto var = format("{}.{}", VAR_CLSID, name);
|
||||
if (typeAst && (cachedCls->fields.empty() || cachedCls->fields[0].name != var)) {
|
||||
// LOG("[virtual] vtable({}) := {}", name, var);
|
||||
cachedCls->fields.insert(cachedCls->fields.begin(), {var, nullptr});
|
||||
cachedCls->ast->args.insert(cachedCls->ast->args.begin(),
|
||||
Param{var, transformType(N<IdExpr>("int")), nullptr});
|
||||
}
|
||||
// Mark parent classes as polymorphic as well.
|
||||
if (typeAst)
|
||||
cachedCls->rtti = true;
|
||||
|
||||
// Add generics first
|
||||
int nGenerics = 0;
|
||||
|
@ -348,8 +347,10 @@ std::vector<ClassStmt *> SimplifyVisitor::parseBaseClasses(
|
|||
nGenerics, subs.size());
|
||||
args.emplace_back(a.name, a.type, transformType(subs[si++], false),
|
||||
Param::HiddenGeneric);
|
||||
args_classes.emplace_back(asts.back()->name);
|
||||
} else if (a.status == Param::HiddenGeneric) {
|
||||
args.emplace_back(a);
|
||||
args_classes.emplace_back(asts.back()->name);
|
||||
}
|
||||
if (a.status != Param::Normal) {
|
||||
if (auto st = getStaticGeneric(a.type.get())) {
|
||||
|
@ -376,12 +377,14 @@ std::vector<ClassStmt *> SimplifyVisitor::parseBaseClasses(
|
|||
if (i)
|
||||
name = format("{}#{}", name, i);
|
||||
args.emplace_back(name, a.type, a.defaultValue);
|
||||
args_classes.emplace_back(ast->name);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (typeAst) {
|
||||
if (!parentClasses.empty())
|
||||
mro.push_back(parentClasses);
|
||||
ctx->cache->classes[canonicalName].rtti = true;
|
||||
ctx->cache->classes[canonicalName].mro = Cache::mergeC3(mro);
|
||||
if (ctx->cache->classes[canonicalName].mro.empty()) {
|
||||
E(Error::CLASS_BAD_MRO, getSrcInfo());
|
||||
|
@ -423,8 +426,8 @@ SimplifyVisitor::autoDeduceMembers(ClassStmt *stmt, std::vector<Param> &args) {
|
|||
auto varName = ctx->generateCanonicalName(format("T{}", ++i));
|
||||
auto memberName = ctx->cache->rev(varName);
|
||||
ctx->addType(memberName, varName, stmt->getSrcInfo())->generic = true;
|
||||
args.emplace_back(Param{varName, N<IdExpr>("type"), nullptr, Param::Generic});
|
||||
args.emplace_back(Param{m, N<IdExpr>(varName)});
|
||||
args.emplace_back(varName, N<IdExpr>("type"), nullptr, Param::Generic);
|
||||
args.emplace_back(m, N<IdExpr>(varName));
|
||||
}
|
||||
ctx->getBase()->deducedMembers = nullptr;
|
||||
return {transformed, f};
|
||||
|
@ -506,8 +509,7 @@ StmtPtr SimplifyVisitor::codegenMagic(const std::string &op, const ExprPtr &typE
|
|||
|
||||
std::vector<Param> args;
|
||||
for (auto &a : allArgs)
|
||||
if (!startswith(a.name, VAR_CLSID))
|
||||
args.push_back(a);
|
||||
args.push_back(a);
|
||||
|
||||
if (op == "new") {
|
||||
// Classes: @internal def __new__() -> T
|
||||
|
@ -515,9 +517,9 @@ StmtPtr SimplifyVisitor::codegenMagic(const std::string &op, const ExprPtr &typE
|
|||
ret = typExpr->clone();
|
||||
if (isRecord) {
|
||||
for (auto &a : args)
|
||||
fargs.emplace_back(
|
||||
Param{a.name, clone(a.type),
|
||||
a.defaultValue ? clone(a.defaultValue) : N<CallExpr>(clone(a.type))});
|
||||
fargs.emplace_back(a.name, clone(a.type),
|
||||
a.defaultValue ? clone(a.defaultValue)
|
||||
: N<CallExpr>(clone(a.type)));
|
||||
attr.set(Attr::Internal);
|
||||
} else {
|
||||
stmts.emplace_back(N<ReturnStmt>(
|
||||
|
@ -527,17 +529,17 @@ StmtPtr SimplifyVisitor::codegenMagic(const std::string &op, const ExprPtr &typE
|
|||
// Classes: def __init__(self: T, a1: T1, ..., aN: TN) -> void:
|
||||
// self.aI = aI ...
|
||||
ret = I("NoneType");
|
||||
fargs.emplace_back(Param{"self", typExpr->clone()});
|
||||
fargs.emplace_back("self", typExpr->clone());
|
||||
for (auto &a : args) {
|
||||
stmts.push_back(N<AssignStmt>(N<DotExpr>(I("self"), a.name), I(a.name)));
|
||||
fargs.emplace_back(
|
||||
Param{a.name, clone(a.type),
|
||||
a.defaultValue ? clone(a.defaultValue) : N<CallExpr>(clone(a.type))});
|
||||
fargs.emplace_back(a.name, clone(a.type),
|
||||
a.defaultValue ? clone(a.defaultValue)
|
||||
: N<CallExpr>(clone(a.type)));
|
||||
}
|
||||
} else if (op == "raw") {
|
||||
// Classes: def __raw__(self: T) -> Ptr[byte]:
|
||||
// return __internal__.class_raw(self)
|
||||
fargs.emplace_back(Param{"self", typExpr->clone()});
|
||||
fargs.emplace_back("self", typExpr->clone());
|
||||
ret = N<IndexExpr>(I("Ptr"), I("byte"));
|
||||
stmts.emplace_back(N<ReturnStmt>(
|
||||
N<CallExpr>(N<DotExpr>(I("__internal__"), "class_raw"), I("self"))));
|
||||
|
@ -545,8 +547,8 @@ StmtPtr SimplifyVisitor::codegenMagic(const std::string &op, const ExprPtr &typE
|
|||
// Tuples: def __getitem__(self: T, index: int) -> T1:
|
||||
// return __internal__.tuple_getitem[T, T1](self, index)
|
||||
// (error during a realizeFunc() method if T is a heterogeneous tuple)
|
||||
fargs.emplace_back(Param{"self", typExpr->clone()});
|
||||
fargs.emplace_back(Param{"index", I("int")});
|
||||
fargs.emplace_back("self", typExpr->clone());
|
||||
fargs.emplace_back("index", I("int"));
|
||||
ret = !args.empty() ? clone(args[0].type) : I("NoneType");
|
||||
stmts.emplace_back(N<ReturnStmt>(
|
||||
N<CallExpr>(N<DotExpr>(I("__internal__"), "tuple_getitem"), I("self"),
|
||||
|
@ -555,7 +557,7 @@ StmtPtr SimplifyVisitor::codegenMagic(const std::string &op, const ExprPtr &typE
|
|||
// Tuples: def __iter__(self: T) -> Generator[T]:
|
||||
// yield self.aI ...
|
||||
// (error during a realizeFunc() method if T is a heterogeneous tuple)
|
||||
fargs.emplace_back(Param{"self", typExpr->clone()});
|
||||
fargs.emplace_back("self", typExpr->clone());
|
||||
ret = N<IndexExpr>(I("Generator"), !args.empty() ? clone(args[0].type) : I("int"));
|
||||
for (auto &a : args)
|
||||
stmts.emplace_back(N<YieldStmt>(N<DotExpr>("self", a.name)));
|
||||
|
@ -566,8 +568,8 @@ StmtPtr SimplifyVisitor::codegenMagic(const std::string &op, const ExprPtr &typE
|
|||
// Tuples: def __contains__(self: T, what) -> bool:
|
||||
// if isinstance(what, T1): if what == self.a1: return True ...
|
||||
// return False
|
||||
fargs.emplace_back(Param{"self", typExpr->clone()});
|
||||
fargs.emplace_back(Param{"what", nullptr});
|
||||
fargs.emplace_back("self", typExpr->clone());
|
||||
fargs.emplace_back("what", nullptr);
|
||||
ret = I("bool");
|
||||
for (auto &a : args)
|
||||
stmts.push_back(N<IfStmt>(N<CallExpr>(I("isinstance"), I("what"), clone(a.type)),
|
||||
|
@ -579,8 +581,8 @@ StmtPtr SimplifyVisitor::codegenMagic(const std::string &op, const ExprPtr &typE
|
|||
// def __eq__(self: T, other: T) -> bool:
|
||||
// if not self.arg1.__eq__(other.arg1): return False ...
|
||||
// return True
|
||||
fargs.emplace_back(Param{"self", typExpr->clone()});
|
||||
fargs.emplace_back(Param{"other", typExpr->clone()});
|
||||
fargs.emplace_back("self", typExpr->clone());
|
||||
fargs.emplace_back("other", typExpr->clone());
|
||||
ret = I("bool");
|
||||
for (auto &a : args)
|
||||
stmts.push_back(N<IfStmt>(
|
||||
|
@ -593,8 +595,8 @@ StmtPtr SimplifyVisitor::codegenMagic(const std::string &op, const ExprPtr &typE
|
|||
// def __ne__(self: T, other: T) -> bool:
|
||||
// if self.arg1.__ne__(other.arg1): return True ...
|
||||
// return False
|
||||
fargs.emplace_back(Param{"self", typExpr->clone()});
|
||||
fargs.emplace_back(Param{"other", typExpr->clone()});
|
||||
fargs.emplace_back("self", typExpr->clone());
|
||||
fargs.emplace_back("other", typExpr->clone());
|
||||
ret = I("bool");
|
||||
for (auto &a : args)
|
||||
stmts.emplace_back(
|
||||
|
@ -608,8 +610,8 @@ StmtPtr SimplifyVisitor::codegenMagic(const std::string &op, const ExprPtr &typE
|
|||
// elif self.arg1.__eq__(other.arg1):
|
||||
// ... (arg2, ...) ...
|
||||
// return False
|
||||
fargs.emplace_back(Param{"self", typExpr->clone()});
|
||||
fargs.emplace_back(Param{"other", typExpr->clone()});
|
||||
fargs.emplace_back("self", typExpr->clone());
|
||||
fargs.emplace_back("other", typExpr->clone());
|
||||
ret = I("bool");
|
||||
std::vector<StmtPtr> *v = &stmts;
|
||||
for (size_t i = 0; i + 1 < args.size(); i++) {
|
||||
|
@ -638,8 +640,8 @@ StmtPtr SimplifyVisitor::codegenMagic(const std::string &op, const ExprPtr &typE
|
|||
// elif self.arg1.__eq__(other.arg1):
|
||||
// ... (arg2, ...) ...
|
||||
// return True
|
||||
fargs.emplace_back(Param{"self", typExpr->clone()});
|
||||
fargs.emplace_back(Param{"other", typExpr->clone()});
|
||||
fargs.emplace_back("self", typExpr->clone());
|
||||
fargs.emplace_back("other", typExpr->clone());
|
||||
ret = I("bool");
|
||||
std::vector<StmtPtr> *v = &stmts;
|
||||
for (size_t i = 0; i + 1 < args.size(); i++) {
|
||||
|
@ -669,7 +671,7 @@ StmtPtr SimplifyVisitor::codegenMagic(const std::string &op, const ExprPtr &typE
|
|||
// seed ^ ((self.arg1.__hash__() + 2654435769) + ((seed << 6) + (seed >> 2)))
|
||||
// ) ...
|
||||
// return seed
|
||||
fargs.emplace_back(Param{"self", typExpr->clone()});
|
||||
fargs.emplace_back("self", typExpr->clone());
|
||||
ret = I("int");
|
||||
stmts.emplace_back(N<AssignStmt>(I("seed"), N<IntExpr>(0)));
|
||||
for (auto &a : args)
|
||||
|
@ -688,8 +690,8 @@ StmtPtr SimplifyVisitor::codegenMagic(const std::string &op, const ExprPtr &typE
|
|||
} else if (op == "pickle") {
|
||||
// def __pickle__(self: T, dest: Ptr[byte]) -> void:
|
||||
// self.arg1.__pickle__(dest) ...
|
||||
fargs.emplace_back(Param{"self", typExpr->clone()});
|
||||
fargs.emplace_back(Param{"dest", N<IndexExpr>(I("Ptr"), I("byte"))});
|
||||
fargs.emplace_back("self", typExpr->clone());
|
||||
fargs.emplace_back("dest", N<IndexExpr>(I("Ptr"), I("byte")));
|
||||
ret = I("NoneType");
|
||||
for (auto &a : args)
|
||||
stmts.emplace_back(N<ExprStmt>(N<CallExpr>(
|
||||
|
@ -697,7 +699,7 @@ StmtPtr SimplifyVisitor::codegenMagic(const std::string &op, const ExprPtr &typE
|
|||
} else if (op == "unpickle") {
|
||||
// def __unpickle__(src: Ptr[byte]) -> T:
|
||||
// return T(T1.__unpickle__(src),...)
|
||||
fargs.emplace_back(Param{"src", N<IndexExpr>(I("Ptr"), I("byte"))});
|
||||
fargs.emplace_back("src", N<IndexExpr>(I("Ptr"), I("byte")));
|
||||
ret = typExpr->clone();
|
||||
std::vector<ExprPtr> ar;
|
||||
ar.reserve(args.size());
|
||||
|
@ -707,7 +709,7 @@ StmtPtr SimplifyVisitor::codegenMagic(const std::string &op, const ExprPtr &typE
|
|||
} else if (op == "len") {
|
||||
// def __len__(self: T) -> int:
|
||||
// return N (number of args)
|
||||
fargs.emplace_back(Param{"self", typExpr->clone()});
|
||||
fargs.emplace_back("self", typExpr->clone());
|
||||
ret = I("int");
|
||||
stmts.emplace_back(N<ReturnStmt>(N<IntExpr>(args.size())));
|
||||
} else if (op == "to_py") {
|
||||
|
@ -715,7 +717,7 @@ StmtPtr SimplifyVisitor::codegenMagic(const std::string &op, const ExprPtr &typE
|
|||
// o = pyobj._tuple_new(N) (number of args)
|
||||
// pyobj._tuple_set(o, 1, self.arg1.__to_py__()) ...
|
||||
// return o
|
||||
fargs.emplace_back(Param{"self", typExpr->clone()});
|
||||
fargs.emplace_back("self", typExpr->clone());
|
||||
ret = I("cobj");
|
||||
stmts.emplace_back(
|
||||
N<AssignStmt>(I("o"), N<CallExpr>(N<DotExpr>(I("pyobj"), "_tuple_new"),
|
||||
|
@ -728,7 +730,7 @@ StmtPtr SimplifyVisitor::codegenMagic(const std::string &op, const ExprPtr &typE
|
|||
} else if (op == "from_py") {
|
||||
// def __from_py__(src: cobj) -> T:
|
||||
// return T(T1.__from_py__(pyobj._tuple_get(src, 1)), ...)
|
||||
fargs.emplace_back(Param{"src", I("cobj")});
|
||||
fargs.emplace_back("src", I("cobj"));
|
||||
ret = typExpr->clone();
|
||||
std::vector<ExprPtr> ar;
|
||||
ar.reserve(args.size());
|
||||
|
@ -740,23 +742,23 @@ StmtPtr SimplifyVisitor::codegenMagic(const std::string &op, const ExprPtr &typE
|
|||
} else if (op == "to_gpu") {
|
||||
// def __to_gpu__(self: T, cache) -> T:
|
||||
// return __internal__.class_to_gpu(self, cache)
|
||||
fargs.emplace_back(Param{"self", typExpr->clone()});
|
||||
fargs.emplace_back(Param{"cache"});
|
||||
fargs.emplace_back("self", typExpr->clone());
|
||||
fargs.emplace_back("cache");
|
||||
ret = typExpr->clone();
|
||||
stmts.emplace_back(N<ReturnStmt>(N<CallExpr>(
|
||||
N<DotExpr>(I("__internal__"), "class_to_gpu"), I("self"), I("cache"))));
|
||||
} else if (op == "from_gpu") {
|
||||
// def __from_gpu__(self: T, other: T) -> None:
|
||||
// __internal__.class_from_gpu(self, other)
|
||||
fargs.emplace_back(Param{"self", typExpr->clone()});
|
||||
fargs.emplace_back(Param{"other", typExpr->clone()});
|
||||
fargs.emplace_back("self", typExpr->clone());
|
||||
fargs.emplace_back("other", typExpr->clone());
|
||||
ret = I("NoneType");
|
||||
stmts.emplace_back(N<ExprStmt>(N<CallExpr>(
|
||||
N<DotExpr>(I("__internal__"), "class_from_gpu"), I("self"), I("other"))));
|
||||
} else if (op == "from_gpu_new") {
|
||||
// def __from_gpu_new__(other: T) -> T:
|
||||
// return __internal__.class_from_gpu_new(other)
|
||||
fargs.emplace_back(Param{"other", typExpr->clone()});
|
||||
fargs.emplace_back("other", typExpr->clone());
|
||||
ret = typExpr->clone();
|
||||
stmts.emplace_back(N<ReturnStmt>(
|
||||
N<CallExpr>(N<DotExpr>(I("__internal__"), "class_from_gpu_new"), I("other"))));
|
||||
|
@ -767,7 +769,7 @@ StmtPtr SimplifyVisitor::codegenMagic(const std::string &op, const ExprPtr &typE
|
|||
// a.__setitem__(0, self.arg1.__repr__()) ...
|
||||
// n.__setitem__(0, "arg1") ... (if not a Tuple.N; otherwise "")
|
||||
// return __internal__.tuple_str(a.ptr, n.ptr, N)
|
||||
fargs.emplace_back(Param{"self", typExpr->clone()});
|
||||
fargs.emplace_back("self", typExpr->clone());
|
||||
ret = I("str");
|
||||
if (!args.empty()) {
|
||||
stmts.emplace_back(
|
||||
|
@ -798,7 +800,7 @@ StmtPtr SimplifyVisitor::codegenMagic(const std::string &op, const ExprPtr &typE
|
|||
// d = List[str](N)
|
||||
// d.append('arg1') ...
|
||||
// return d
|
||||
fargs.emplace_back(Param{"self", typExpr->clone()});
|
||||
fargs.emplace_back("self", typExpr->clone());
|
||||
stmts.emplace_back(
|
||||
N<AssignStmt>(I("d"), N<CallExpr>(N<IndexExpr>(I("List"), I("str")),
|
||||
N<IntExpr>(args.size()))));
|
||||
|
@ -809,15 +811,15 @@ StmtPtr SimplifyVisitor::codegenMagic(const std::string &op, const ExprPtr &typE
|
|||
} else if (op == "add") {
|
||||
// def __add__(self, tup):
|
||||
// return __internal__.tuple_add(self, tup)
|
||||
fargs.emplace_back(Param{"self", typExpr->clone()});
|
||||
fargs.emplace_back(Param{"tup", nullptr});
|
||||
fargs.emplace_back("self", typExpr->clone());
|
||||
fargs.emplace_back("tup", nullptr);
|
||||
stmts.emplace_back(N<ReturnStmt>(
|
||||
N<CallExpr>(N<DotExpr>(I("__internal__"), "tuple_add"), I("self"), I("tup"))));
|
||||
} else if (op == "mul") {
|
||||
// def __mul__(self, i: Static[int]):
|
||||
// return __internal__.tuple_add(self, tup)
|
||||
fargs.emplace_back(Param{"self", typExpr->clone()});
|
||||
fargs.emplace_back(Param{"i", N<IndexExpr>(I("Static"), I("int"))});
|
||||
fargs.emplace_back("self", typExpr->clone());
|
||||
fargs.emplace_back("i", N<IndexExpr>(I("Static"), I("int")));
|
||||
stmts.emplace_back(N<ReturnStmt>(
|
||||
N<CallExpr>(N<DotExpr>(I("__internal__"), "tuple_mul"), I("self"), I("i"))));
|
||||
} else if (op == "tuplesize") {
|
||||
|
|
|
@ -176,7 +176,8 @@ private: // Node simplification rules
|
|||
/* Classes (class.cpp) */
|
||||
void visit(ClassStmt *) override;
|
||||
std::vector<ClassStmt *> parseBaseClasses(std::vector<ExprPtr> &,
|
||||
std::vector<Param> &, const Attr &,
|
||||
std::vector<Param> &,
|
||||
std::vector<std::string> &, const Attr &,
|
||||
const std::string &,
|
||||
const ExprPtr & = nullptr);
|
||||
std::pair<StmtPtr, FunctionStmt *> autoDeduceMembers(ClassStmt *,
|
||||
|
|
|
@ -194,12 +194,10 @@ ExprPtr TypecheckVisitor::transformDot(DotExpr *expr,
|
|||
if (args) {
|
||||
unify(expr->type, ctx->instantiate(bestMethod, typ));
|
||||
|
||||
// Handle virtual calls
|
||||
auto clsidName = format("{}.{}", VAR_CLSID, typ->name);
|
||||
// A function is deemed virtual if it is marked as such and if a base class has a
|
||||
// vtable
|
||||
// A function is deemed virtual if it is marked as such and
|
||||
// if a base class has a RTTI
|
||||
bool isVirtual = in(ctx->cache->classes[typ->name].virtuals, expr->member);
|
||||
isVirtual &= ctx->findMember(typ->name, clsidName) != nullptr;
|
||||
isVirtual &= ctx->cache->classes[typ->name].rtti;
|
||||
isVirtual &= !expr->expr->isType();
|
||||
if (isVirtual && !bestMethod->ast->attributes.has(Attr::StaticMethod) &&
|
||||
!bestMethod->ast->attributes.has(Attr::Property)) {
|
||||
|
@ -217,12 +215,14 @@ ExprPtr TypecheckVisitor::transformDot(DotExpr *expr,
|
|||
NT<IdExpr>("Function"),
|
||||
std::vector<ExprPtr>{NT<InstantiateExpr>(NT<IdExpr>(name), ids),
|
||||
NT<IdExpr>(fn->getRetType()->realizedName())});
|
||||
// Function[Tuple[TArg1, TArg2, ...],
|
||||
// TRet](__vtables__[expr.__id__][T[VIRTUAL_ID]])
|
||||
// Function[Tuple[TArg1, TArg2, ...],TRet](
|
||||
// __internal__.class_get_rtti_vtable(expr)[T[VIRTUAL_ID]]
|
||||
// )
|
||||
auto e = N<CallExpr>(
|
||||
fnType, N<IndexExpr>(N<IndexExpr>(N<IdExpr>("__vtables__"),
|
||||
N<DotExpr>(expr->expr, clsidName)),
|
||||
N<IntExpr>(vid)));
|
||||
fnType,
|
||||
N<IndexExpr>(N<CallExpr>(N<IdExpr>("__internal__.class_get_rtti_vtable:0"),
|
||||
expr->expr),
|
||||
N<IntExpr>(vid)));
|
||||
return transform(e);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -569,6 +569,8 @@ std::pair<bool, ExprPtr> TypecheckVisitor::transformSpecialCall(CallExpr *expr)
|
|||
return {true, transformRealizedFn(expr)};
|
||||
} else if (val == "std.internal.static.static_print") {
|
||||
return {false, transformStaticPrintFn(expr)};
|
||||
} else if (val == "__has_rtti__") {
|
||||
return {true, transformHasRttiFn(expr)};
|
||||
} else {
|
||||
return transformInternalStaticFn(expr);
|
||||
}
|
||||
|
@ -644,7 +646,7 @@ ExprPtr TypecheckVisitor::transformSuper() {
|
|||
auto typExpr = N<IdExpr>(superTyp->name);
|
||||
typExpr->setType(superTyp);
|
||||
return transform(N<CallExpr>(N<DotExpr>(N<IdExpr>("__internal__"), "class_super"),
|
||||
self, typExpr));
|
||||
self, typExpr, N<IntExpr>(1)));
|
||||
}
|
||||
|
||||
auto name = cands.front(); // the first inherited type
|
||||
|
@ -659,7 +661,7 @@ ExprPtr TypecheckVisitor::transformSuper() {
|
|||
e->type = unify(superTyp, e->type); // see super_tuple test for this line
|
||||
return e;
|
||||
} else {
|
||||
// Case: reference types. Return `__internal__.to_class_ptr(self.__raw__(), T)`
|
||||
// Case: reference types. Return `__internal__.class_super(self, T)`
|
||||
auto self = N<IdExpr>(funcTyp->ast->args[0].name);
|
||||
self->type = typ;
|
||||
return castToSuperClass(self, superTyp);
|
||||
|
@ -945,6 +947,18 @@ ExprPtr TypecheckVisitor::transformStaticPrintFn(CallExpr *expr) {
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
/// Transform __has_rtti__ to a static boolean that indicates RTTI status of a type.
|
||||
ExprPtr TypecheckVisitor::transformHasRttiFn(CallExpr *expr) {
|
||||
expr->staticValue.type = StaticValue::INT;
|
||||
auto funcTyp = expr->expr->type->getFunc();
|
||||
auto t = funcTyp->funcGenerics[0].type->getClass();
|
||||
if (!t)
|
||||
return nullptr;
|
||||
auto c = in(ctx->cache->classes, t->name);
|
||||
seqassert(c, "bad class {}", t->name);
|
||||
return transform(N<BoolExpr>(const_cast<Cache::Class *>(c)->rtti));
|
||||
}
|
||||
|
||||
// Transform internal.static calls
|
||||
std::pair<bool, ExprPtr> TypecheckVisitor::transformInternalStaticFn(CallExpr *expr) {
|
||||
if (expr->expr->isId("std.internal.static.fn_can_call")) {
|
||||
|
|
|
@ -396,19 +396,7 @@ types::TypePtr TypecheckVisitor::realizeFunc(types::FuncType *type, bool force)
|
|||
/// Intended to be called once the typechecking is done.
|
||||
/// TODO: add JIT compatibility.
|
||||
StmtPtr TypecheckVisitor::prepareVTables() {
|
||||
auto rep = "__internal__.class_init_vtables:0";
|
||||
// def class_init_vtables():
|
||||
// return __internal__.class_make_n_vtables(<NUM_REALIZATIONS> + 1)
|
||||
auto &initAllVT = ctx->cache->functions[rep];
|
||||
auto suite = N<SuiteStmt>(N<ReturnStmt>(N<CallExpr>(
|
||||
N<IdExpr>("__internal__.class_make_n_vtables:0"), N<IdExpr>("__vtable_size__"))));
|
||||
initAllVT.ast->suite = suite;
|
||||
auto typ = initAllVT.realizations.begin()->second->type;
|
||||
LOG_REALIZE("[poly] {} : {}", typ, *suite);
|
||||
typ->ast = initAllVT.ast.get();
|
||||
auto fx = realizeFunc(typ.get(), true);
|
||||
|
||||
rep = "__internal__.class_populate_vtables:0";
|
||||
auto rep = "__internal__.class_populate_vtables:0";
|
||||
// def class_populate_vtables(p):
|
||||
// for real in <REALIZATIONS>:
|
||||
// if real.vtables:
|
||||
|
@ -417,7 +405,7 @@ StmtPtr TypecheckVisitor::prepareVTables() {
|
|||
// for f in real.vtables:
|
||||
// p[real.ID].__setitem__(f.ID, Function[<TYPE_F>](f).__raw__())
|
||||
auto &initFn = ctx->cache->functions[rep];
|
||||
suite = N<SuiteStmt>();
|
||||
auto suite = N<SuiteStmt>();
|
||||
for (auto &[_, cls] : ctx->cache->classes) {
|
||||
for (auto &[r, real] : cls.realizations) {
|
||||
size_t vtSz = 0;
|
||||
|
@ -470,41 +458,15 @@ StmtPtr TypecheckVisitor::prepareVTables() {
|
|||
}
|
||||
}
|
||||
initFn.ast->suite = suite;
|
||||
typ = initFn.realizations.begin()->second->type;
|
||||
auto typ = initFn.realizations.begin()->second->type;
|
||||
LOG_REALIZE("[poly] {} : {}", typ, suite->toString(2));
|
||||
typ->ast = initFn.ast.get();
|
||||
realizeFunc(typ.get(), true);
|
||||
|
||||
rep = "__internal__.class_set_obj_vtable:0";
|
||||
// def class_set_obj_vtable(pf):
|
||||
// pf.__vtable__ = __vtables__[pf.__vtable_id___]
|
||||
auto &initObjFns = ctx->cache->functions[rep];
|
||||
auto oldAst = initObjFns.ast;
|
||||
for (auto &[_, real] : initObjFns.realizations) {
|
||||
auto t = real->type;
|
||||
auto clsTyp = t->getArgTypes()[0]->getClass();
|
||||
auto varName = initObjFns.ast->args[0].name;
|
||||
|
||||
const auto &fields = ctx->cache->classes[clsTyp->name].fields;
|
||||
auto suite = N<SuiteStmt>();
|
||||
for (auto &f : fields)
|
||||
if (startswith(f.name, VAR_CLSID)) {
|
||||
suite->stmts.push_back(N<AssignMemberStmt>(
|
||||
N<IdExpr>(varName), f.name,
|
||||
N<DotExpr>(N<IdExpr>(clsTyp->realizedName()), "__id__")));
|
||||
}
|
||||
|
||||
LOG_REALIZE("[poly] {} : {}", t, *suite);
|
||||
initObjFns.ast->suite = suite;
|
||||
t->ast = initObjFns.ast.get();
|
||||
realizeFunc(t.get(), true);
|
||||
}
|
||||
initObjFns.ast = oldAst;
|
||||
|
||||
auto &initDist = ctx->cache->functions["__internal__.class_base_derived_dist:0"];
|
||||
// def class_base_derived_dist(B, D):
|
||||
// return Tuple[<types before B is reached in D>].__elemsize__
|
||||
oldAst = initDist.ast;
|
||||
auto oldAst = initDist.ast;
|
||||
for (auto &[_, real] : initDist.realizations) {
|
||||
auto t = real->type;
|
||||
auto baseTyp = t->funcGenerics[0].type->getClass();
|
||||
|
@ -514,7 +476,7 @@ StmtPtr TypecheckVisitor::prepareVTables() {
|
|||
auto types = std::vector<ExprPtr>{};
|
||||
auto found = false;
|
||||
for (auto &f : fields) {
|
||||
if (endswith(f.name, format(".{}", baseTyp->name))) {
|
||||
if (f.baseClass == baseTyp->name) {
|
||||
found = true;
|
||||
break;
|
||||
} else {
|
||||
|
@ -621,21 +583,16 @@ size_t TypecheckVisitor::getRealizationID(types::ClassType *cp, types::FuncType
|
|||
// <DERIVED>), <DERIVED>
|
||||
// ), <ARGS...>)
|
||||
std::vector<Param> fnArgs;
|
||||
fnArgs.push_back(
|
||||
Param{fp->ast->args[0].name, N<IdExpr>(cp->realizedName()), nullptr});
|
||||
fnArgs.emplace_back(fp->ast->args[0].name, N<IdExpr>(cp->realizedName()),
|
||||
nullptr);
|
||||
for (size_t i = 1; i < args.size(); i++)
|
||||
fnArgs.push_back(Param{fp->ast->args[i].name,
|
||||
N<IdExpr>(args[i]->realizedName()), nullptr});
|
||||
fnArgs.emplace_back(fp->ast->args[i].name, N<IdExpr>(args[i]->realizedName()),
|
||||
nullptr);
|
||||
std::vector<ExprPtr> callArgs;
|
||||
callArgs.emplace_back(N<CallExpr>(
|
||||
N<IdExpr>("__internal__.to_class_ptr:0"),
|
||||
N<BinaryExpr>(
|
||||
N<CallExpr>(N<DotExpr>(N<IdExpr>(fp->ast->args[0].name), "__raw__")),
|
||||
"-",
|
||||
N<CallExpr>(N<IdExpr>("__internal__.class_base_derived_dist:0"),
|
||||
N<IdExpr>(cp->realizedName()),
|
||||
N<IdExpr>(real->type->realizedName()))),
|
||||
NT<IdExpr>(real->type->realizedName())));
|
||||
callArgs.emplace_back(
|
||||
N<CallExpr>(N<IdExpr>("__internal__.class_base_to_derived:0"),
|
||||
N<IdExpr>(fp->ast->args[0].name), N<IdExpr>(cp->realizedName()),
|
||||
N<IdExpr>(real->type->realizedName())));
|
||||
for (size_t i = 1; i < args.size(); i++)
|
||||
callArgs.emplace_back(N<IdExpr>(fp->ast->args[i].name));
|
||||
auto thunkAst = N<FunctionStmt>(
|
||||
|
|
|
@ -451,23 +451,11 @@ ExprPtr TypecheckVisitor::castToSuperClass(ExprPtr expr, ClassTypePtr superTyp,
|
|||
ctx->instantiate(parentField.type, superTyp));
|
||||
}
|
||||
}
|
||||
realize(superTyp);
|
||||
auto typExpr = N<IdExpr>(superTyp->name);
|
||||
typExpr->setType(superTyp);
|
||||
// `dist = expr.__raw__()`
|
||||
ExprPtr dist = N<CallExpr>(N<DotExpr>(expr, "__raw__"));
|
||||
if (isVirtual) {
|
||||
// Virtual inheritance: `dist += class_base_derived_dist(super, type(expr))`
|
||||
dist =
|
||||
N<BinaryExpr>(dist, "+",
|
||||
N<CallExpr>(N<IdExpr>("__internal__.class_base_derived_dist:0"),
|
||||
N<IdExpr>(superTyp->realizedName()),
|
||||
N<CallExpr>(N<IdExpr>("type"), expr)));
|
||||
}
|
||||
realize(superTyp);
|
||||
|
||||
// No inheritance: `__internal__.to_class_ptr(dist, T)`
|
||||
return transform(N<CallExpr>(N<DotExpr>(N<IdExpr>("__internal__"), "to_class_ptr"),
|
||||
dist, typExpr));
|
||||
return transform(
|
||||
N<CallExpr>(N<DotExpr>(N<IdExpr>("__internal__"), "class_super"), expr, typExpr));
|
||||
}
|
||||
|
||||
/// Unpack a Tuple or KwTuple expression into (name, type) vector.
|
||||
|
|
|
@ -145,6 +145,7 @@ private: // Node typechecking rules
|
|||
ExprPtr transformTypeFn(CallExpr *expr);
|
||||
ExprPtr transformRealizedFn(CallExpr *expr);
|
||||
ExprPtr transformStaticPrintFn(CallExpr *expr);
|
||||
ExprPtr transformHasRttiFn(CallExpr *expr);
|
||||
std::pair<bool, ExprPtr> transformInternalStaticFn(CallExpr *expr);
|
||||
std::vector<types::ClassTypePtr> getSuperTypes(const types::ClassTypePtr &cls);
|
||||
void addFunctionGenerics(const types::FuncType *t);
|
||||
|
|
|
@ -196,3 +196,6 @@ def __realized__(fn, args):
|
|||
|
||||
def statictuple(*args):
|
||||
return args
|
||||
|
||||
def __has_rtti__(T: type):
|
||||
pass
|
||||
|
|
|
@ -1,37 +1,81 @@
|
|||
# Copyright (C) 2022-2023 Exaloop Inc. <https://exaloop.io>
|
||||
|
||||
from internal.gc import (
|
||||
alloc, alloc_atomic, alloc_uncollectable, alloc_atomic_uncollectable,
|
||||
free, atomic, sizeof, register_finalizer
|
||||
alloc, alloc_atomic, alloc_atomic_uncollectable,
|
||||
free, sizeof, register_finalizer
|
||||
)
|
||||
|
||||
__vtables__ = Ptr[Ptr[cobj]]()
|
||||
__vtable_size__ = 0
|
||||
|
||||
@extend
|
||||
class __internal__:
|
||||
def class_init_vtables():
|
||||
"""
|
||||
Create a global vtable.
|
||||
"""
|
||||
sz = __vtable_size__ + 1
|
||||
__vtables__ = Ptr[Ptr[cobj]](alloc_atomic_uncollectable(sz * sizeof(Ptr[cobj])))
|
||||
__internal__.class_populate_vtables(__vtables__)
|
||||
|
||||
|
||||
@__internal__
|
||||
class RTTI:
|
||||
id: int
|
||||
|
||||
@extend
|
||||
class __internal__:
|
||||
def yield_final(val):
|
||||
pass
|
||||
|
||||
def yield_in_no_suspend(T: type) -> T:
|
||||
pass
|
||||
|
||||
@pure
|
||||
@derives
|
||||
@llvm
|
||||
def class_raw(obj) -> Ptr[byte]:
|
||||
def class_raw_ptr(obj) -> Ptr[byte]:
|
||||
ret ptr %obj
|
||||
|
||||
@pure
|
||||
@derives
|
||||
@llvm
|
||||
def class_raw_rtti_ptr(obj) -> Ptr[byte]:
|
||||
%0 = extractvalue {ptr, ptr} %obj, i64 0
|
||||
ret ptr %0
|
||||
|
||||
@llvm
|
||||
def class_raw_rtti_rtti(obj: T, T: type) -> Ptr[byte]:
|
||||
%0 = extractvalue {ptr, ptr} %obj, i64 1
|
||||
ret ptr %0
|
||||
|
||||
@pure
|
||||
@derives
|
||||
def class_raw(obj) -> Ptr[byte]:
|
||||
if __has_rtti__(type(obj)):
|
||||
return __internal__.class_raw_rtti_ptr(obj)
|
||||
else:
|
||||
return __internal__.class_raw_ptr(obj)
|
||||
|
||||
def class_alloc(T: type) -> T:
|
||||
"""Allocates a new reference (class) type"""
|
||||
sz = sizeof(tuple(T))
|
||||
p = alloc_atomic(sz) if T.__contents_atomic__ else alloc(sz)
|
||||
register_finalizer(p)
|
||||
return __internal__.to_class_ptr(p, T)
|
||||
if __has_rtti__(T):
|
||||
obj = alloc_atomic(sz) if T.__contents_atomic__ else alloc(sz)
|
||||
register_finalizer(obj)
|
||||
rsz = sizeof(tuple(T))
|
||||
rtti = alloc_atomic(rsz) if RTTI.__contents_atomic__ else alloc(rsz)
|
||||
__internal__.to_class_ptr(rtti, RTTI).id = T.__id__
|
||||
return __internal__.to_class_ptr_rtti((obj, rtti), T)
|
||||
else:
|
||||
obj = alloc_atomic(sz) if T.__contents_atomic__ else alloc(sz)
|
||||
register_finalizer(obj)
|
||||
return __internal__.to_class_ptr(obj, T)
|
||||
|
||||
def class_new(T: type) -> T:
|
||||
def class_new(T: type):
|
||||
"""Create a new reference (class) type"""
|
||||
pf = __internal__.class_alloc(T)
|
||||
__internal__.class_set_obj_vtable(pf)
|
||||
return pf
|
||||
p = __internal__.class_alloc(T)
|
||||
return p
|
||||
|
||||
def class_ctr(T: type, *args, **kwargs) -> T:
|
||||
"""Shorthand for `t = T.__new__(); t.__init__(*args, **kwargs); t`"""
|
||||
|
@ -45,19 +89,12 @@ class __internal__:
|
|||
"""
|
||||
pass
|
||||
|
||||
def class_init_vtables() -> Ptr[Ptr[cobj]]:
|
||||
"""
|
||||
Create a global vtable. Compiler generated.
|
||||
Corresponds to:
|
||||
return __internal__.class_make_n_vtables(<number of class realizations>)
|
||||
"""
|
||||
pass
|
||||
|
||||
def class_make_n_vtables(sz: int) -> Ptr[Ptr[cobj]]:
|
||||
"""Create a global vtable."""
|
||||
p = Ptr[Ptr[cobj]](alloc_atomic_uncollectable(sz * sizeof(Ptr[cobj])))
|
||||
__internal__.class_populate_vtables(p)
|
||||
return p
|
||||
def class_get_rtti_vtable(obj) -> Ptr[byte]:
|
||||
if not __has_rtti__(type(obj)):
|
||||
compile_error("class is not polymorphic")
|
||||
rtti = __internal__.class_raw_rtti_rtti(obj)
|
||||
id = __internal__.to_class_ptr(rtti, RTTI).id
|
||||
return __vtables__[id]
|
||||
|
||||
def class_populate_vtables(p: Ptr[Ptr[cobj]]) -> None:
|
||||
"""
|
||||
|
@ -86,17 +123,32 @@ class __internal__:
|
|||
"""Calculates the byte distance of base class B and derived class D. Compiler generated."""
|
||||
return 0
|
||||
|
||||
@inline
|
||||
def class_base_to_derived(b: B, B: type, D: type) -> D:
|
||||
if not (__has_rtti__(D) and __has_rtti__(B)):
|
||||
compile_error("classes are not polymorphic")
|
||||
off = __internal__.class_base_derived_dist(B, D)
|
||||
ptr = __internal__.class_raw_rtti_ptr(b) - off
|
||||
pr = __internal__.class_raw_rtti_rtti(b)
|
||||
return __internal__.to_class_ptr_rtti((ptr, pr), D)
|
||||
|
||||
def class_copy(obj: T, T: type) -> T:
|
||||
p = __internal__.class_alloc(T)
|
||||
str.memcpy(p.__raw__(), obj.__raw__(), sizeof(tuple(T)))
|
||||
return p
|
||||
|
||||
def class_super(obj: D, B: type, D: type) -> B:
|
||||
pf = __internal__.to_class_ptr(obj.__raw__() + __internal__.class_base_derived_dist(B, D), B)
|
||||
pn = __internal__.class_copy(pf)
|
||||
# Replace vtables
|
||||
__internal__.class_set_obj_vtable(pn) # replace vtables to point to its vtables!
|
||||
return pn
|
||||
def class_super(obj: D, B: type, D: type, change_rtti: Static[int] = 0) -> B:
|
||||
if not __has_rtti__(D): # static inheritance
|
||||
return __internal__.to_class_ptr(obj.__raw__(), B)
|
||||
else:
|
||||
if not __has_rtti__(B):
|
||||
compile_error("classes are not polymorphic")
|
||||
off = __internal__.class_base_derived_dist(B, D)
|
||||
ptr = __internal__.class_raw_rtti_ptr(obj) + off
|
||||
pr = __internal__.class_raw_rtti_rtti(obj)
|
||||
if change_rtti:
|
||||
__internal__.to_class_ptr(pr, RTTI).id = B.__id__
|
||||
return __internal__.to_class_ptr_rtti((ptr, pr), B)
|
||||
|
||||
# Unions
|
||||
|
||||
|
@ -242,6 +294,14 @@ class __internal__:
|
|||
def opt_ref_new(T: type) -> Optional[T]:
|
||||
ret ptr null
|
||||
|
||||
@pure
|
||||
def opt_ref_new_rtti(T: type) -> Optional[T]:
|
||||
obj = Ptr[byte]()
|
||||
rsz = sizeof(tuple(T))
|
||||
rtti = alloc_atomic(rsz) if RTTI.__contents_atomic__ else alloc(rsz)
|
||||
__internal__.to_class_ptr(rtti, RTTI).id = T.__id__
|
||||
return __internal__.opt_ref_new_arg(__internal__.to_class_ptr_rtti((obj, rtti), T))
|
||||
|
||||
@pure
|
||||
@derives
|
||||
@llvm
|
||||
|
@ -255,6 +315,12 @@ class __internal__:
|
|||
def opt_ref_new_arg(what: T, T: type) -> Optional[T]:
|
||||
ret ptr %what
|
||||
|
||||
@pure
|
||||
@derives
|
||||
@llvm
|
||||
def opt_ref_new_arg_rtti(what: T, T: type) -> Optional[T]:
|
||||
ret { ptr, ptr } %what
|
||||
|
||||
@pure
|
||||
@llvm
|
||||
def opt_tuple_bool(what: Optional[T], T: type) -> bool:
|
||||
|
@ -269,6 +335,10 @@ class __internal__:
|
|||
%1 = zext i1 %0 to i8
|
||||
ret i8 %1
|
||||
|
||||
@pure
|
||||
def opt_ref_bool_rtti(what: Optional[T], T: type) -> bool:
|
||||
return __internal__.class_raw_rtti_ptr() != cobj()
|
||||
|
||||
@pure
|
||||
@derives
|
||||
@llvm
|
||||
|
@ -282,12 +352,24 @@ class __internal__:
|
|||
def opt_ref_invert(what: Optional[T], T: type) -> T:
|
||||
ret ptr %what
|
||||
|
||||
@pure
|
||||
@derives
|
||||
@llvm
|
||||
def opt_ref_invert_rtti(what: Optional[T], T: type) -> T:
|
||||
ret { ptr, ptr } %what
|
||||
|
||||
@pure
|
||||
@derives
|
||||
@llvm
|
||||
def to_class_ptr(p: Ptr[byte], T: type) -> T:
|
||||
ret ptr %p
|
||||
|
||||
@pure
|
||||
@derives
|
||||
@llvm
|
||||
def to_class_ptr_rtti(p: Tuple[Ptr[byte], Ptr[byte]], T: type) -> T:
|
||||
ret { ptr, ptr } %p
|
||||
|
||||
def _tuple_offsetof(x, field: Static[int]) -> int:
|
||||
@pure
|
||||
@llvm
|
||||
|
@ -478,9 +560,6 @@ class Function:
|
|||
def __call__(self, *args) -> TR:
|
||||
return Function.__call_internal__(self, args)
|
||||
|
||||
__vtables__ = __internal__.class_init_vtables()
|
||||
def _____(): __vtables__ # make it global!
|
||||
|
||||
|
||||
@tuple
|
||||
class PyObject:
|
||||
|
@ -492,3 +571,6 @@ class PyObject:
|
|||
class PyWrapper[T]:
|
||||
head: PyObject
|
||||
data: T
|
||||
|
||||
|
||||
__internal__.class_init_vtables()
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
import os
|
||||
|
||||
from gc import atomic, alloc_uncollectable
|
||||
from internal.dlopen import *
|
||||
|
||||
# general
|
||||
|
|
|
@ -5,24 +5,32 @@ class Optional:
|
|||
def __new__() -> Optional[T]:
|
||||
if isinstance(T, ByVal):
|
||||
return __internal__.opt_tuple_new(T)
|
||||
elif __has_rtti__(T):
|
||||
return __internal__.opt_ref_new_rtti(T)
|
||||
else:
|
||||
return __internal__.opt_ref_new(T)
|
||||
|
||||
def __new__(what: T) -> Optional[T]:
|
||||
if isinstance(T, ByVal):
|
||||
return __internal__.opt_tuple_new_arg(what, T)
|
||||
elif __has_rtti__(T):
|
||||
return __internal__.opt_ref_new_arg_rtti(what, T)
|
||||
else:
|
||||
return __internal__.opt_ref_new_arg(what, T)
|
||||
|
||||
def __has__(self) -> bool:
|
||||
if isinstance(T, ByVal):
|
||||
return __internal__.opt_tuple_bool(self, T)
|
||||
elif __has_rtti__(T):
|
||||
return __internal__.opt_ref_bool_rtti(T)
|
||||
else:
|
||||
return __internal__.opt_ref_bool(self, T)
|
||||
|
||||
def __val__(self) -> T:
|
||||
if isinstance(T, ByVal):
|
||||
return __internal__.opt_tuple_invert(self, T)
|
||||
elif __has_rtti__(T):
|
||||
return __internal__.opt_ref_invert_rtti(T)
|
||||
else:
|
||||
return __internal__.opt_ref_invert(self, T)
|
||||
|
||||
|
|
Loading…
Reference in New Issue