mirror of https://github.com/exaloop/codon.git
Fix call tests [wip]
parent
abadfeb03e
commit
bef36e016a
|
@ -357,7 +357,7 @@ const std::string Attr::HasSelf = ".__hasself__";
|
|||
const std::string Attr::Extend = "extend";
|
||||
const std::string Attr::Tuple = "tuple";
|
||||
const std::string Attr::Test = "std.internal.attributes.test";
|
||||
const std::string Attr::Overload = "overload";
|
||||
const std::string Attr::Overload = "overload:0";
|
||||
const std::string Attr::Export = "std.internal.attributes.export";
|
||||
|
||||
FunctionStmt::FunctionStmt(std::string name, ExprPtr ret, std::vector<Param> args,
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
#define TYPE_CALLABLE "Callable"
|
||||
#define TYPE_OPTIONAL "Optional"
|
||||
#define TYPE_SLICE "std.internal.types.slice.Slice"
|
||||
#define FN_UNWRAP "std.internal.types.optional.unwrap.0"
|
||||
#define FN_UNWRAP "std.internal.types.optional.unwrap.0:0"
|
||||
#define VAR_ARGV "__argv__"
|
||||
|
||||
#define MAX_INT_WIDTH 10000
|
||||
|
|
|
@ -148,7 +148,7 @@ void TranslateVisitor::defaultVisit(Expr *n) {
|
|||
}
|
||||
|
||||
void TranslateVisitor::visit(NoneExpr *expr) {
|
||||
auto f = expr->type->realizedName() + ":Optional.__new__";
|
||||
auto f = expr->type->realizedName() + ":Optional.__new__:0";
|
||||
auto val = ctx->find(f);
|
||||
seqassert(val, "cannot find '{}'", f);
|
||||
result = make<ir::CallInstr>(expr, make<ir::VarValue>(expr, val->getFunc()),
|
||||
|
@ -263,7 +263,7 @@ void TranslateVisitor::visit(CallExpr *expr) {
|
|||
expr->args[0].value->getId()->value);
|
||||
result = make<ir::PointerValue>(expr, val->getVar());
|
||||
return;
|
||||
} else if (expr->expr->isId("__array__.__new__")) {
|
||||
} else if (expr->expr->isId("__array__.__new__:0")) {
|
||||
auto fnt = expr->expr->type->getFunc();
|
||||
auto szt = fnt->funcGenerics[0].type->getStatic();
|
||||
auto sz = szt->evaluate().getInt();
|
||||
|
|
|
@ -22,8 +22,8 @@ using namespace types;
|
|||
/// For tuple identifiers, generate appropriate class. See @c generateTuple for
|
||||
/// details.
|
||||
void TypecheckVisitor::visit(IdExpr *expr) {
|
||||
if (isTuple(expr->value))
|
||||
generateTuple(std::stoi(expr->value.substr(sizeof(TYPE_TUPLE) - 1)));
|
||||
// if (isTuple(expr->value))
|
||||
// generateTuple(std::stoi(expr->value.substr(sizeof(TYPE_TUPLE) - 1)));
|
||||
|
||||
auto val = ctx->find(expr->value);
|
||||
// if (!val && ctx->getBase()->pyCaptures) {
|
||||
|
@ -39,8 +39,11 @@ void TypecheckVisitor::visit(IdExpr *expr) {
|
|||
// ctx->cache->typeCtx->dump();
|
||||
E(Error::ID_NOT_FOUND, expr, expr->value);
|
||||
}
|
||||
if (expr->type->getUnbound() && in(ctx->cache->overloads, val->canonicalName))
|
||||
auto o = in(ctx->cache->overloads, val->canonicalName);
|
||||
if (expr->type->getUnbound() && o && o->size() > 1) {
|
||||
// LOG("dispatch: {}", val->canonicalName);
|
||||
val = ctx->forceFind(getDispatch(val->canonicalName)->ast->name);
|
||||
}
|
||||
|
||||
// If we are accessing an outside variable, capture it or raise an error
|
||||
auto captured = checkCapture(val);
|
||||
|
@ -414,10 +417,10 @@ ExprPtr TypecheckVisitor::transformDot(DotExpr *expr,
|
|||
// __internal__.class_get_rtti_vtable(expr)[T[VIRTUAL_ID]]
|
||||
// )
|
||||
auto e = N<CallExpr>(
|
||||
fnType,
|
||||
N<IndexExpr>(N<CallExpr>(N<IdExpr>("__internal__.class_get_rtti_vtable"),
|
||||
expr->expr),
|
||||
N<IntExpr>(vid)));
|
||||
fnType, N<IndexExpr>(N<CallExpr>(N<DotExpr>(N<IdExpr>("__internal__"),
|
||||
"class_get_rtti_vtable"),
|
||||
expr->expr),
|
||||
N<IntExpr>(vid)));
|
||||
return transform(e);
|
||||
}
|
||||
}
|
||||
|
@ -529,7 +532,7 @@ ExprPtr TypecheckVisitor::getClassMember(DotExpr *expr,
|
|||
// Case: transform `union.m` to `__internal__.get_union_method(union, "m", ...)`
|
||||
if (typ->getUnion()) {
|
||||
return transform(N<CallExpr>(
|
||||
N<IdExpr>("__internal__.get_union_method"),
|
||||
N<DotExpr>(N<IdExpr>("__internal__"), "get_union_method"),
|
||||
std::vector<CallExpr::Arg>{{"union", expr->expr},
|
||||
{"method", N<StringExpr>(expr->member)},
|
||||
{"", N<EllipsisExpr>(EllipsisExpr::PARTIAL)}}));
|
||||
|
|
|
@ -19,7 +19,7 @@ void TypecheckVisitor::visit(NoneExpr *expr) {
|
|||
if (realize(expr->type)) {
|
||||
// Realize the appropriate `Optional.__new__` for the translation stage
|
||||
auto cls = expr->type->getClass();
|
||||
auto f = ctx->forceFind(TYPE_OPTIONAL ".__new__")->type;
|
||||
auto f = ctx->forceFind(TYPE_OPTIONAL ".__new__:0")->type;
|
||||
auto t = realize(ctx->instantiate(f, cls)->getFunc());
|
||||
expr->setDone();
|
||||
}
|
||||
|
|
|
@ -60,6 +60,18 @@ void TypecheckVisitor::visit(EllipsisExpr *expr) {
|
|||
/// See @c transformCallArgs , @c getCalleeFn , @c callReorderArguments ,
|
||||
/// @c typecheckCallArgs , @c transformSpecialCall and @c wrapExpr for more details.
|
||||
void TypecheckVisitor::visit(CallExpr *expr) {
|
||||
// Special case!
|
||||
if (expr->type->getUnbound()) {
|
||||
auto callExpr = transform(clean_clone(expr->expr));
|
||||
if (callExpr->isId("std.collections.namedtuple.0")) {
|
||||
resultExpr = transformNamedTuple(expr);
|
||||
return;
|
||||
} else if (callExpr->isId("std.functools.partial.0:0")) {
|
||||
resultExpr = transformFunctoolsPartial(expr);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Transform and expand arguments. Return early if it cannot be done yet
|
||||
if (!transformCallArgs(expr->args))
|
||||
return;
|
||||
|
@ -423,7 +435,7 @@ ExprPtr TypecheckVisitor::callReorderArguments(FuncTypePtr calleeFn, CallExpr *e
|
|||
|
||||
// Reorder arguments if needed
|
||||
part.args = part.kwArgs = nullptr; // Stores partial *args/**kwargs expression
|
||||
if (expr->hasAttr(ExprAttr::OrderedCall) || expr->expr->isId("superf")) {
|
||||
if (expr->hasAttr(ExprAttr::OrderedCall)) {
|
||||
args = expr->args;
|
||||
} else {
|
||||
ctx->reorderNamedArgs(
|
||||
|
@ -598,26 +610,23 @@ std::pair<bool, ExprPtr> TypecheckVisitor::transformSpecialCall(CallExpr *expr)
|
|||
if (!expr->expr->getId())
|
||||
return {false, nullptr};
|
||||
auto val = expr->expr->getId()->value;
|
||||
// LOG(".. {}", val);
|
||||
if (val == "tuple" && expr->args.size() == 1 &&
|
||||
CAST(expr->args.front().value, GeneratorExpr)) {
|
||||
return {true, transformTupleGenerator(expr)};
|
||||
} else if (val == "std.collections.namedtuple.0") {
|
||||
return {true, transformNamedTuple(expr)};
|
||||
} else if (val == "std.functools.partial.0") {
|
||||
return {true, transformFunctoolsPartial(expr)};
|
||||
} else if (val == "superf") {
|
||||
return {true, transformSuperF(expr)};
|
||||
} else if (val == "super") {
|
||||
} else if (val == "super:0") {
|
||||
return {true, transformSuper()};
|
||||
} else if (val == "__ptr__") {
|
||||
return {true, transformPtr(expr)};
|
||||
} else if (val == "__array__.__new__") {
|
||||
} else if (val == "__array__.__new__:0") {
|
||||
return {true, transformArray(expr)};
|
||||
} else if (val == "isinstance") {
|
||||
return {true, transformIsInstance(expr)};
|
||||
} else if (val == "staticlen") {
|
||||
return {true, transformStaticLen(expr)};
|
||||
} else if (val == "hasattr" || val == "hasattr:1") {
|
||||
} else if (startswith(val, "hasattr:")) {
|
||||
return {true, transformHasAttr(expr)};
|
||||
} else if (val == "getattr") {
|
||||
return {true, transformGetAttr(expr)};
|
||||
|
@ -661,18 +670,15 @@ ExprPtr TypecheckVisitor::transformTupleGenerator(CallExpr *expr) {
|
|||
/// b: int```
|
||||
ExprPtr TypecheckVisitor::transformNamedTuple(CallExpr *expr) {
|
||||
// Ensure that namedtuple call is valid
|
||||
if (expr->args.size() != 1 || !expr->args[0].value->origExpr->getList())
|
||||
if (expr->args.size() != 2 || !(expr->args[0].value->getString()) ||
|
||||
!(expr->args[1].value->getList()))
|
||||
E(Error::CALL_NAMEDTUPLE, getSrcInfo());
|
||||
|
||||
auto name = expr->expr->type->getFunc()
|
||||
->funcGenerics[0]
|
||||
.type->getStatic()
|
||||
->evaluate()
|
||||
.getString();
|
||||
auto name = expr->args[0].value->getString()->getValue();
|
||||
// Construct the class statement
|
||||
std::vector<Param> generics, params;
|
||||
int ti = 1;
|
||||
for (auto &i : expr->args[0].value->origExpr->getList()->items) {
|
||||
for (auto &i : expr->args[1].value->getList()->items) {
|
||||
if (auto s = i->getString()) {
|
||||
generics.emplace_back(format("T{}", ti), N<IdExpr>("type"), nullptr, true);
|
||||
params.emplace_back(s->getValue(), N<IdExpr>(format("T{}", ti++)), nullptr);
|
||||
|
@ -737,11 +743,18 @@ ExprPtr TypecheckVisitor::transformSuperF(CallExpr *expr) {
|
|||
}
|
||||
if (supers.empty())
|
||||
E(Error::CALL_SUPERF, expr);
|
||||
|
||||
seqassert(expr->args.size() == 1 && expr->args[0].value->getCall(),
|
||||
"bad superf call");
|
||||
std::vector<CallExpr::Arg> newArgs;
|
||||
for (auto &a : expr->args[0].value->getCall()->args)
|
||||
newArgs.push_back({"", a.value});
|
||||
auto m = findMatchingMethods(
|
||||
func->funcParent ? func->funcParent->getClass() : nullptr, supers, expr->args);
|
||||
func->funcParent ? func->funcParent->getClass() : nullptr, supers, newArgs);
|
||||
if (m.empty())
|
||||
E(Error::CALL_SUPERF, expr);
|
||||
return transform(N<CallExpr>(N<IdExpr>(m[0]->ast->name), expr->args));
|
||||
auto c = transform(N<CallExpr>(N<IdExpr>(m[0]->ast->name), newArgs));
|
||||
return c;
|
||||
}
|
||||
|
||||
/// Typecheck and transform super method. Replace it with the current self object cast
|
||||
|
@ -782,8 +795,8 @@ ExprPtr TypecheckVisitor::transformSuper() {
|
|||
std::vector<ExprPtr> members;
|
||||
for (auto &field : ctx->cache->classes[name].fields)
|
||||
members.push_back(N<DotExpr>(N<IdExpr>(funcTyp->ast->args[0].name), field.name));
|
||||
ExprPtr e = transform(
|
||||
N<CallExpr>(N<IdExpr>(format(TYPE_TUPLE "{}", members.size())), members));
|
||||
ExprPtr e =
|
||||
transform(N<CallExpr>(N<IdExpr>(generateTuple(members.size())), members));
|
||||
e->type = unify(superTyp, e->type); // see super_tuple test for this line
|
||||
return e;
|
||||
} else {
|
||||
|
@ -867,7 +880,8 @@ ExprPtr TypecheckVisitor::transformIsInstance(CallExpr *expr) {
|
|||
if (tag == -1)
|
||||
return transform(N<BoolExpr>(false));
|
||||
return transform(N<BinaryExpr>(
|
||||
N<CallExpr>(N<IdExpr>("__internal__.union_get_tag"), expr->args[0].value),
|
||||
N<CallExpr>(N<DotExpr>(N<IdExpr>("__internal__"), "union_get_tag"),
|
||||
expr->args[0].value),
|
||||
"==", N<IntExpr>(tag)));
|
||||
} else if (typExpr->type->is("pyobj") && !typExpr->isType()) {
|
||||
if (typ->is("pyobj")) {
|
||||
|
@ -931,15 +945,14 @@ ExprPtr TypecheckVisitor::transformHasAttr(CallExpr *expr) {
|
|||
->evaluate()
|
||||
.getString();
|
||||
std::vector<std::pair<std::string, TypePtr>> args{{"", typ}};
|
||||
if (expr->expr->isId("hasattr")) {
|
||||
if (expr->expr->isId("hasattr:0")) {
|
||||
// Case: the first hasattr overload allows passing argument types via *args
|
||||
auto tup = expr->args[1].value->getTuple();
|
||||
seqassert(tup, "not a tuple");
|
||||
for (auto &a : tup->items) {
|
||||
transform(a);
|
||||
if (!a->getType()->getClass())
|
||||
auto tup = expr->args[1].value->getCall();
|
||||
seqassert(tup, "not a tuple call");
|
||||
for (auto &a : tup->args) {
|
||||
if (!a.value->getType()->getClass())
|
||||
return nullptr;
|
||||
args.emplace_back("", a->getType());
|
||||
args.emplace_back("", a.value->getType());
|
||||
}
|
||||
seqassert(expr->args[2].value->origExpr && expr->args[2].value->origExpr->getCall(),
|
||||
"expected call: {}", expr->args[2].value->origExpr);
|
||||
|
@ -1038,9 +1051,9 @@ ExprPtr TypecheckVisitor::transformTupleFn(CallExpr *expr) {
|
|||
for (auto &field : ctx->cache->classes[cls->name].fields)
|
||||
args.emplace_back(N<DotExpr>(N<IdExpr>(var), field.name));
|
||||
|
||||
return transform(N<StmtExpr>(
|
||||
N<AssignStmt>(N<IdExpr>(var), expr->args.front().value),
|
||||
N<CallExpr>(N<IdExpr>(format("{}{}", TYPE_TUPLE, args.size())), args)));
|
||||
return transform(
|
||||
N<StmtExpr>(N<AssignStmt>(N<IdExpr>(var), expr->args.front().value),
|
||||
N<CallExpr>(N<IdExpr>(generateTuple(args.size())), args)));
|
||||
}
|
||||
|
||||
/// Transform type function to a type IdExpr identifier.
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#include "codon/parser/ast.h"
|
||||
#include "codon/parser/cache.h"
|
||||
#include "codon/parser/common.h"
|
||||
#include "codon/parser/visitors/format/format.h"
|
||||
#include "codon/parser/visitors/typecheck/typecheck.h"
|
||||
|
||||
using fmt::format;
|
||||
|
@ -151,7 +152,7 @@ void TypecheckVisitor::visit(ClassStmt *stmt) {
|
|||
}
|
||||
|
||||
// Collect classes (and their fields) that are to be statically inherited
|
||||
std::vector<ClassStmt *> staticBaseASTs, baseASTs;
|
||||
std::vector<types::ClassTypePtr> staticBaseASTs;
|
||||
if (!stmt->attributes.has(Attr::Extend)) {
|
||||
staticBaseASTs = parseBaseClasses(stmt->staticBaseClasses, args, stmt->attributes,
|
||||
canonicalName, nullptr, typ);
|
||||
|
@ -183,7 +184,7 @@ void TypecheckVisitor::visit(ClassStmt *stmt) {
|
|||
// stmt->attributes.has(Attr::Extend)
|
||||
// ? a.name
|
||||
// : ctx->generateCanonicalName(a.name);
|
||||
args.emplace_back(varName, clone(a.type),
|
||||
args.emplace_back(varName, transformType(clean_clone(a.type)),
|
||||
transform(clone(a.defaultValue), true));
|
||||
ctx->cache->classes[canonicalName].fields.push_back(
|
||||
Cache::Class::ClassField{varName, nullptr, canonicalName});
|
||||
|
@ -203,17 +204,16 @@ void TypecheckVisitor::visit(ClassStmt *stmt) {
|
|||
if (!stmt->attributes.has(Attr::Extend)) {
|
||||
ctx->typecheckLevel++; // to avoid unifying generics early
|
||||
auto &fields = ctx->cache->classes[canonicalName].fields;
|
||||
for (auto ai = 0, aj = 0; ai < stmt->args.size(); ai++)
|
||||
if (stmt->args[ai].status == Param::Normal &&
|
||||
!ClassStmt::isClassVar(stmt->args[ai])) {
|
||||
fields[aj].type = transformType(stmt->args[ai].type)
|
||||
->getType()
|
||||
->generalize(ctx->typecheckLevel - 1);
|
||||
fields[aj].type->setSrcInfo(stmt->args[ai].type->getSrcInfo());
|
||||
for (auto ai = 0, aj = 0; ai < args.size(); ai++) {
|
||||
if (args[ai].status == Param::Normal && !ClassStmt::isClassVar(args[ai])) {
|
||||
fields[aj].type =
|
||||
args[ai].type->getType()->generalize(ctx->typecheckLevel - 1);
|
||||
fields[aj].type->setSrcInfo(args[ai].type->getSrcInfo());
|
||||
if (stmt->isRecord())
|
||||
typ->getRecord()->args.push_back(fields[aj].type);
|
||||
aj++;
|
||||
}
|
||||
}
|
||||
ctx->typecheckLevel--;
|
||||
}
|
||||
|
||||
|
@ -256,10 +256,11 @@ void TypecheckVisitor::visit(ClassStmt *stmt) {
|
|||
for (auto &mm : ctx->cache->classes[base->name].methods)
|
||||
for (auto &mf : ctx->cache->overloads[mm.second]) {
|
||||
auto f = ctx->cache->functions[mf].origAst;
|
||||
if (!f->attributes.has("autogenerated")) {
|
||||
LOG("=> adding {} . {} to {} : {}", base->name, f->name, name,
|
||||
f->toString(2));
|
||||
if (f && !f->attributes.has("autogenerated")) {
|
||||
ctx->addBlock();
|
||||
addClassGenerics(base);
|
||||
fnStmts.push_back(transform(clean_clone(f)));
|
||||
ctx->popBlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -365,12 +366,12 @@ void TypecheckVisitor::visit(ClassStmt *stmt) {
|
|||
/// @param args Class fields that are to be updated with base classes' fields.
|
||||
/// @param typeAst Transformed AST for base class type (e.g., `A[T]`).
|
||||
/// Only set when dealing with dynamic polymorphism.
|
||||
std::vector<ClassStmt *>
|
||||
std::vector<types::ClassTypePtr>
|
||||
TypecheckVisitor::parseBaseClasses(std::vector<ExprPtr> &baseClasses,
|
||||
std::vector<Param> &args, const Attr &attr,
|
||||
const std::string &canonicalName,
|
||||
const ExprPtr &typeAst, types::ClassTypePtr &typ) {
|
||||
std::vector<ClassStmt *> asts;
|
||||
std::vector<types::ClassTypePtr> asts;
|
||||
|
||||
// MAJOR TODO: fix MRO it to work with generic classes (maybe replacements? IDK...)
|
||||
std::vector<std::vector<ExprPtr>> mro{{typeAst}};
|
||||
|
@ -382,28 +383,22 @@ TypecheckVisitor::parseBaseClasses(std::vector<ExprPtr> &baseClasses,
|
|||
// Get the base class and generic replacements (e.g., if there is Bar[T],
|
||||
// Bar in Foo(Bar[int]) will have `T = int`)
|
||||
transformType(cls);
|
||||
if (auto i = cls->getId()) {
|
||||
name = i->value;
|
||||
} else if (auto e = CAST(cls, InstantiateExpr)) {
|
||||
if (auto ei = e->typeExpr->getId()) {
|
||||
name = ei->value;
|
||||
subs = e->typeParams;
|
||||
}
|
||||
}
|
||||
if (!cls->type->getClass())
|
||||
E(Error::CLASS_ID_NOT_FOUND, getSrcInfo(), FormatVisitor::apply(cls));
|
||||
|
||||
Cache::Class *cachedCls = in(ctx->cache->classes, name);
|
||||
if (!cachedCls)
|
||||
E(Error::CLASS_ID_NOT_FOUND, getSrcInfo(), ctx->cache->rev(name));
|
||||
asts.push_back(cachedCls->ast.get());
|
||||
auto clsTyp = cls->type->getClass();
|
||||
name = clsTyp->name;
|
||||
asts.push_back(clsTyp);
|
||||
parentClasses.push_back(clone(cls));
|
||||
Cache::Class *cachedCls = in(ctx->cache->classes, name);
|
||||
mro.push_back(cachedCls->mro);
|
||||
|
||||
// Sanity checks
|
||||
if (attr.has(Attr::Tuple) && typeAst)
|
||||
E(Error::CLASS_NO_INHERIT, getSrcInfo(), "tuple");
|
||||
if (!attr.has(Attr::Tuple) && asts.back()->attributes.has(Attr::Tuple))
|
||||
if (!attr.has(Attr::Tuple) && cachedCls->ast->attributes.has(Attr::Tuple))
|
||||
E(Error::CLASS_TUPLE_INHERIT, getSrcInfo());
|
||||
if (asts.back()->attributes.has(Attr::Internal))
|
||||
if (cachedCls->ast->attributes.has(Attr::Internal))
|
||||
E(Error::CLASS_NO_INHERIT, getSrcInfo(), "internal");
|
||||
|
||||
// Mark parent classes as polymorphic as well.
|
||||
|
@ -411,67 +406,18 @@ TypecheckVisitor::parseBaseClasses(std::vector<ExprPtr> &baseClasses,
|
|||
cachedCls->rtti = true;
|
||||
}
|
||||
|
||||
// Add generics first
|
||||
int nGenerics = 0;
|
||||
for (auto &a : asts.back()->args)
|
||||
nGenerics += a.status == Param::Generic;
|
||||
int si = 0;
|
||||
for (auto &a : asts.back()->args) {
|
||||
if (a.status == Param::Normal)
|
||||
continue;
|
||||
|
||||
if (a.status == Param::Generic) {
|
||||
if (si == subs.size())
|
||||
E(Error::GENERICS_MISMATCH, cls, ctx->cache->rev(asts.back()->name),
|
||||
nGenerics, subs.size());
|
||||
args.emplace_back(a.name, a.type, transformType(subs[si++], false),
|
||||
Param::HiddenGeneric);
|
||||
} else if (a.status == Param::HiddenGeneric) {
|
||||
args.emplace_back(a);
|
||||
}
|
||||
|
||||
auto generic = ctx->getUnbound();
|
||||
auto typId = generic->id;
|
||||
generic->getLink()->genericName = ctx->cache->rev(a.name);
|
||||
if (args.back().defaultValue) {
|
||||
auto defType = transformType(clone(args.back().defaultValue));
|
||||
// Hidden generics can be outright replaced (e.g., `T=int`).
|
||||
// Unify them immediately.
|
||||
unify(defType->type, generic);
|
||||
}
|
||||
if (auto ti = CAST(a.type, InstantiateExpr)) {
|
||||
// Parse TraitVar
|
||||
seqassert(ti->typeExpr->isId(TYPE_TYPEVAR), "not a TypeVar instantiation");
|
||||
auto l = transformType(ti->typeParams[0])->type;
|
||||
if (l->getLink() && l->getLink()->trait)
|
||||
generic->getLink()->trait = l->getLink()->trait;
|
||||
else
|
||||
generic->getLink()->trait = std::make_shared<types::TypeTrait>(l);
|
||||
}
|
||||
|
||||
if (auto st = getStaticGeneric(a.type.get())) {
|
||||
generic->isStatic = st;
|
||||
auto val = ctx->addVar(ctx->cache->rev(a.name), a.name, generic);
|
||||
val->generic = true;
|
||||
val->staticType = st;
|
||||
} else {
|
||||
ctx->addType(ctx->cache->rev(a.name), a.name, generic)->generic = true;
|
||||
}
|
||||
ClassType::Generic g{a.name, a.name, generic->generalize(ctx->typecheckLevel),
|
||||
typId};
|
||||
if (args.back().status == Param::Generic) {
|
||||
typ->generics.push_back(g);
|
||||
} else {
|
||||
typ->hiddenGenerics.push_back(g);
|
||||
}
|
||||
}
|
||||
if (si != subs.size())
|
||||
E(Error::GENERICS_MISMATCH, cls, ctx->cache->rev(asts.back()->name), nGenerics,
|
||||
subs.size());
|
||||
// Add hidden generics
|
||||
for (auto &g : clsTyp->generics)
|
||||
typ->hiddenGenerics.push_back(g);
|
||||
for (auto &g : clsTyp->hiddenGenerics)
|
||||
typ->hiddenGenerics.push_back(g);
|
||||
}
|
||||
// Add normal fields
|
||||
for (auto &ast : asts) {
|
||||
for (auto &clsTyp : asts) {
|
||||
int ai = 0;
|
||||
auto ast = ctx->cache->classes[clsTyp->name].ast;
|
||||
ctx->addBlock();
|
||||
addClassGenerics(clsTyp);
|
||||
for (auto &a : ast->args) {
|
||||
if (a.status == Param::Normal && !ClassStmt::isClassVar(a)) {
|
||||
auto name = a.name;
|
||||
|
@ -491,6 +437,7 @@ TypecheckVisitor::parseBaseClasses(std::vector<ExprPtr> &baseClasses,
|
|||
ai++;
|
||||
}
|
||||
}
|
||||
ctx->popBlock();
|
||||
}
|
||||
if (typeAst) {
|
||||
if (!parentClasses.empty()) {
|
||||
|
@ -791,4 +738,20 @@ int TypecheckVisitor::generateKwId(const std::vector<std::string> &names) {
|
|||
}
|
||||
}
|
||||
|
||||
void TypecheckVisitor::addClassGenerics(const types::ClassTypePtr &clsTyp) {
|
||||
auto addGen = [&](auto g) {
|
||||
if (auto st = g.type->getStatic()) {
|
||||
auto val = ctx->addVar(ctx->cache->rev(g.name), g.name, st);
|
||||
val->generic = true;
|
||||
val->staticType = st->expr->staticValue.type;
|
||||
} else {
|
||||
ctx->addType(ctx->cache->rev(g.name), g.name, g.type)->generic = true;
|
||||
}
|
||||
};
|
||||
for (auto &g : clsTyp->hiddenGenerics)
|
||||
addGen(g);
|
||||
for (auto &g : clsTyp->generics)
|
||||
addGen(g);
|
||||
}
|
||||
|
||||
} // namespace codon::ast
|
||||
|
|
|
@ -152,16 +152,17 @@ void TypecheckVisitor::visit(FunctionStmt *stmt) {
|
|||
// Case 2: function overload
|
||||
if (auto c = ctx->find(stmt->name)) {
|
||||
if (c->isFunc() && c->getModule() == ctx->getModule() &&
|
||||
c->getBaseName() == ctx->getBaseName())
|
||||
rootName = ctx->cache->functions[c->canonicalName].rootName;
|
||||
c->getBaseName() == ctx->getBaseName()) {
|
||||
rootName = c->canonicalName;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (rootName.empty())
|
||||
rootName = ctx->generateCanonicalName(stmt->name, true, isClassMember);
|
||||
// Append overload number to the name
|
||||
auto canonicalName = rootName;
|
||||
if (!ctx->cache->overloads[rootName].empty())
|
||||
canonicalName += format(":{}", ctx->cache->overloads[rootName].size());
|
||||
// if (!ctx->cache->overloads[rootName].empty())
|
||||
canonicalName += format(":{}", ctx->cache->overloads[rootName].size());
|
||||
ctx->cache->reverseIdentifierLookup[canonicalName] = stmt->name;
|
||||
|
||||
if (isClassMember) {
|
||||
|
@ -179,8 +180,6 @@ void TypecheckVisitor::visit(FunctionStmt *stmt) {
|
|||
|
||||
// Handle captures. Add additional argument to the function for every capture.
|
||||
// Make sure to account for **kwargs if present
|
||||
if (stmt->name == "fromkeys")
|
||||
LOG("--");
|
||||
std::map<std::string, TypeContext::Item> captures;
|
||||
for (auto &[c, t] : stmt->attributes.captures) {
|
||||
if (auto v = ctx->find(c)) {
|
||||
|
@ -406,12 +405,12 @@ void TypecheckVisitor::visit(FunctionStmt *stmt) {
|
|||
if (isClassMember && stmt->attributes.has(Attr::Method)) {
|
||||
funcTyp->funcParent = ctx->find(stmt->attributes.parentClass)->type;
|
||||
}
|
||||
if (startswith(funcTyp->toString(), "std.collections.defaultdict.0.__init__:5"))
|
||||
LOG("-> realizing ... {:D}", funcTyp);
|
||||
funcTyp = std::static_pointer_cast<types::FuncType>(
|
||||
funcTyp->generalize(ctx->typecheckLevel));
|
||||
ctx->cache->functions[canonicalName].type = funcTyp;
|
||||
auto val = ctx->addFunc(stmt->name, canonicalName, funcTyp);
|
||||
|
||||
ctx->addFunc(stmt->name, rootName, funcTyp);
|
||||
ctx->addFunc(canonicalName, canonicalName, funcTyp);
|
||||
if (stmt->attributes.has(Attr::Overload)) {
|
||||
ctx->remove(stmt->name); // first overload will handle it!
|
||||
} else if (isClassMember) {
|
||||
|
@ -435,6 +434,7 @@ void TypecheckVisitor::visit(FunctionStmt *stmt) {
|
|||
// Hack so that we can later use same helpers for class overloads
|
||||
ctx->cache->classes[".toplevel"].methods[stmt->name] = rootName;
|
||||
}
|
||||
// LOG("-> {} {} {} {}", getSrcInfo(), stmt->name, rootName, canonicalName);
|
||||
|
||||
// Ensure that functions with @C, @force_realize, and @export attributes can be
|
||||
// realized
|
||||
|
@ -461,9 +461,9 @@ void TypecheckVisitor::visit(FunctionStmt *stmt) {
|
|||
a.value = clone(a.value);
|
||||
}
|
||||
// todo)) right now this adds a capture hook for recursive calls
|
||||
f->suite = N<SuiteStmt>(
|
||||
N<AssignStmt>(N<IdExpr>(rootName), N<CallExpr>(N<IdExpr>(rootName), pa)),
|
||||
suite);
|
||||
f->suite = N<SuiteStmt>(N<AssignStmt>(N<IdExpr>(canonicalName),
|
||||
N<CallExpr>(N<IdExpr>(canonicalName), pa)),
|
||||
suite);
|
||||
}
|
||||
|
||||
// Parse remaining decorators
|
||||
|
@ -577,8 +577,14 @@ std::pair<bool, std::string> TypecheckVisitor::getDecorator(const ExprPtr &e) {
|
|||
if (id && id->getId()) {
|
||||
auto ci = ctx->find(id->getId()->value);
|
||||
if (ci && ci->isFunc()) {
|
||||
return {ctx->cache->functions[ci->canonicalName].ast->attributes.isAttribute,
|
||||
ci->canonicalName};
|
||||
if (auto f = in(ctx->cache->functions, ci->canonicalName)) {
|
||||
return {ctx->cache->functions[ci->canonicalName].ast->attributes.isAttribute,
|
||||
ci->canonicalName};
|
||||
} else if (ctx->cache->overloads[ci->canonicalName].size() == 1) {
|
||||
return {ctx->cache->functions[ctx->cache->overloads[ci->canonicalName][0]]
|
||||
.ast->attributes.isAttribute,
|
||||
ci->canonicalName};
|
||||
}
|
||||
}
|
||||
}
|
||||
return {false, ""};
|
||||
|
|
|
@ -349,9 +349,9 @@ StmtPtr TypecheckVisitor::transformNewImport(const ImportFile &file) {
|
|||
// TODO: Make sure to register the global variables and set their assignments as
|
||||
// updates. Note: signatures/classes/functions are not wrapped Create import
|
||||
// function manually with ForceRealize
|
||||
auto fn =
|
||||
StmtPtr fn =
|
||||
N<FunctionStmt>(importVar, N<IdExpr>("NoneType"), std::vector<Param>{}, suite);
|
||||
tv.transform(fn);
|
||||
fn = tv.transform(fn);
|
||||
tv.realize(ictx->forceFind(importVar)->type);
|
||||
preamble->push_back(fn);
|
||||
// return fn;
|
||||
|
|
|
@ -424,7 +424,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_populate_vtables"; // see internal.codon
|
||||
auto rep = "__internal__.class_populate_vtables:0"; // see internal.codon
|
||||
if (!in(ctx->cache->functions, rep))
|
||||
return nullptr;
|
||||
auto &initFn = ctx->cache->functions[rep];
|
||||
|
@ -440,7 +440,7 @@ StmtPtr TypecheckVisitor::prepareVTables() {
|
|||
continue;
|
||||
// __internal__.class_set_rtti_vtable(real.ID, size, real.type)
|
||||
suite->stmts.push_back(N<ExprStmt>(
|
||||
N<CallExpr>(N<IdExpr>("__internal__.class_set_rtti_vtable"),
|
||||
N<CallExpr>(N<DotExpr>(N<IdExpr>("__internal__"), "class_set_rtti_vtable"),
|
||||
N<IntExpr>(real->id), N<IntExpr>(vtSz + 2), NT<IdExpr>(r))));
|
||||
// LOG("[poly] {} -> {}", r, real->id);
|
||||
vtSz = 0;
|
||||
|
@ -454,18 +454,16 @@ StmtPtr TypecheckVisitor::prepareVTables() {
|
|||
// p[real.ID].__setitem__(f.ID, Function[<TYPE_F>](f).__raw__())
|
||||
LOG_REALIZE("[poly] vtable[{}][{}] = {}", real->id, vtSz + id, fn);
|
||||
suite->stmts.push_back(N<ExprStmt>(N<CallExpr>(
|
||||
N<IdExpr>("__internal__.class_set_rtti_vtable_fn"),
|
||||
N<DotExpr>(N<IdExpr>("__internal__"), "class_set_rtti_vtable_fn"),
|
||||
N<IntExpr>(real->id), N<IntExpr>(vtSz + id),
|
||||
N<CallExpr>(N<DotExpr>(
|
||||
N<CallExpr>(
|
||||
NT<InstantiateExpr>(
|
||||
NT<IdExpr>("Function"),
|
||||
std::vector<ExprPtr>{
|
||||
NT<InstantiateExpr>(
|
||||
NT<IdExpr>(format("{}{}", TYPE_TUPLE, ids.size())),
|
||||
ids),
|
||||
NT<IdExpr>(fn->getRetType()->realizedName())}),
|
||||
N<IdExpr>(fn->realizedName())),
|
||||
N<CallExpr>(NT<InstantiateExpr>(
|
||||
NT<IdExpr>("Function"),
|
||||
std::vector<ExprPtr>{
|
||||
NT<InstantiateExpr>(
|
||||
NT<IdExpr>(generateTuple(ids.size())), ids),
|
||||
NT<IdExpr>(fn->getRetType()->realizedName())}),
|
||||
N<IdExpr>(fn->realizedName())),
|
||||
"__raw__")),
|
||||
NT<IdExpr>(r))));
|
||||
}
|
||||
|
@ -480,7 +478,7 @@ StmtPtr TypecheckVisitor::prepareVTables() {
|
|||
typ->ast = initFn.ast.get();
|
||||
realizeFunc(typ.get(), true);
|
||||
|
||||
auto &initDist = ctx->cache->functions["__internal__.class_base_derived_dist"];
|
||||
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__
|
||||
auto oldAst = initDist.ast;
|
||||
|
@ -505,8 +503,7 @@ StmtPtr TypecheckVisitor::prepareVTables() {
|
|||
"cannot find distance between {} and {}", derivedTyp->name,
|
||||
baseTyp->name);
|
||||
StmtPtr suite = N<ReturnStmt>(
|
||||
N<DotExpr>(NT<InstantiateExpr>(
|
||||
NT<IdExpr>(format("{}{}", TYPE_TUPLE, types.size())), types),
|
||||
N<DotExpr>(NT<InstantiateExpr>(NT<IdExpr>(generateTuple(types.size())), types),
|
||||
"__elemsize__"));
|
||||
LOG_REALIZE("[poly] {} : {}", t, *suite);
|
||||
initDist.ast->suite = suite;
|
||||
|
@ -606,7 +603,7 @@ size_t TypecheckVisitor::getRealizationID(types::ClassType *cp, types::FuncType
|
|||
nullptr);
|
||||
std::vector<ExprPtr> callArgs;
|
||||
callArgs.emplace_back(
|
||||
N<CallExpr>(N<IdExpr>("__internal__.class_base_to_derived"),
|
||||
N<CallExpr>(N<DotExpr>(N<IdExpr>("__internal__"), "class_base_to_derived"),
|
||||
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++)
|
||||
|
@ -842,8 +839,8 @@ TypecheckVisitor::generateSpecialAst(types::FuncType *type) {
|
|||
seqassert(unionType, "expected union, got {}", type->funcParent);
|
||||
|
||||
StmtPtr suite = N<ReturnStmt>(N<CallExpr>(
|
||||
N<IdExpr>("__internal__.new_union"), N<IdExpr>(type->ast->args[0].name),
|
||||
N<IdExpr>(unionType->realizedTypeName())));
|
||||
N<DotExpr>(N<IdExpr>("__internal__"), "new_union"),
|
||||
N<IdExpr>(type->ast->args[0].name), N<IdExpr>(unionType->realizedTypeName())));
|
||||
ast->suite = suite;
|
||||
} else if (startswith(ast->name, "__internal__.new_union")) {
|
||||
// Special case: __internal__.new_union
|
||||
|
@ -865,7 +862,7 @@ TypecheckVisitor::generateSpecialAst(types::FuncType *type) {
|
|||
suite->stmts.push_back(N<IfStmt>(
|
||||
N<CallExpr>(N<IdExpr>("isinstance"), N<IdExpr>(objVar),
|
||||
NT<IdExpr>(t->realizedName())),
|
||||
N<ReturnStmt>(N<CallExpr>(N<IdExpr>("__internal__.union_make"),
|
||||
N<ReturnStmt>(N<CallExpr>(N<DotExpr>(N<IdExpr>("__internal__"), "union_make"),
|
||||
N<IntExpr>(tag), N<IdExpr>(objVar),
|
||||
N<IdExpr>(unionType->realizedTypeName())))));
|
||||
// Check for Union[T]
|
||||
|
@ -874,11 +871,11 @@ TypecheckVisitor::generateSpecialAst(types::FuncType *type) {
|
|||
N<IdExpr>("isinstance"), N<IdExpr>(objVar),
|
||||
NT<InstantiateExpr>(NT<IdExpr>("Union"),
|
||||
std::vector<ExprPtr>{NT<IdExpr>(t->realizedName())})),
|
||||
N<ReturnStmt>(
|
||||
N<CallExpr>(N<IdExpr>("__internal__.union_make"), N<IntExpr>(tag),
|
||||
N<CallExpr>(N<IdExpr>("__internal__.get_union"),
|
||||
N<IdExpr>(objVar), NT<IdExpr>(t->realizedName())),
|
||||
N<IdExpr>(unionType->realizedTypeName())))));
|
||||
N<ReturnStmt>(N<CallExpr>(
|
||||
N<DotExpr>(N<IdExpr>("__internal__"), "union_make"), N<IntExpr>(tag),
|
||||
N<CallExpr>(N<DotExpr>(N<IdExpr>("__internal__"), "get_union"),
|
||||
N<IdExpr>(objVar), NT<IdExpr>(t->realizedName())),
|
||||
N<IdExpr>(unionType->realizedTypeName())))));
|
||||
tag++;
|
||||
}
|
||||
suite->stmts.push_back(N<ExprStmt>(N<CallExpr>(
|
||||
|
@ -901,12 +898,13 @@ TypecheckVisitor::generateSpecialAst(types::FuncType *type) {
|
|||
for (const auto &t : unionTypes) {
|
||||
if (t->realizedName() == targetType->realizedName()) {
|
||||
suite->stmts.push_back(N<IfStmt>(
|
||||
N<BinaryExpr>(N<CallExpr>(N<IdExpr>("__internal__.union_get_tag"),
|
||||
N<IdExpr>(selfVar)),
|
||||
"==", N<IntExpr>(tag)),
|
||||
N<ReturnStmt>(N<CallExpr>(N<IdExpr>("__internal__.union_get_data"),
|
||||
N<IdExpr>(selfVar),
|
||||
NT<IdExpr>(t->realizedName())))));
|
||||
N<BinaryExpr>(
|
||||
N<CallExpr>(N<DotExpr>(N<IdExpr>("__internal__"), "union_get_tag"),
|
||||
N<IdExpr>(selfVar)),
|
||||
"==", N<IntExpr>(tag)),
|
||||
N<ReturnStmt>(
|
||||
N<CallExpr>(N<DotExpr>(N<IdExpr>("__internal__"), "union_get_data"),
|
||||
N<IdExpr>(selfVar), NT<IdExpr>(t->realizedName())))));
|
||||
}
|
||||
tag++;
|
||||
}
|
||||
|
@ -929,21 +927,21 @@ TypecheckVisitor::generateSpecialAst(types::FuncType *type) {
|
|||
auto suite = N<SuiteStmt>();
|
||||
int tag = 0;
|
||||
for (auto &t : unionTypes) {
|
||||
auto callee =
|
||||
N<DotExpr>(N<CallExpr>(N<IdExpr>("__internal__.union_get_data"),
|
||||
N<IdExpr>(selfVar), NT<IdExpr>(t->realizedName())),
|
||||
fnName);
|
||||
auto callee = N<DotExpr>(
|
||||
N<CallExpr>(N<DotExpr>(N<IdExpr>("__internal__"), "union_get_data"),
|
||||
N<IdExpr>(selfVar), NT<IdExpr>(t->realizedName())),
|
||||
fnName);
|
||||
auto args = N<StarExpr>(N<IdExpr>(ast->args[2].name.substr(1)));
|
||||
auto kwargs = N<KeywordStarExpr>(N<IdExpr>(ast->args[3].name.substr(2)));
|
||||
std::vector<CallExpr::Arg> callArgs;
|
||||
ExprPtr check = N<CallExpr>(N<IdExpr>("hasattr"), NT<IdExpr>(t->realizedName()),
|
||||
N<StringExpr>(fnName), clone(args), clone(kwargs));
|
||||
suite->stmts.push_back(N<IfStmt>(
|
||||
N<BinaryExpr>(
|
||||
check, "&&",
|
||||
N<BinaryExpr>(N<CallExpr>(N<IdExpr>("__internal__.union_get_tag"),
|
||||
N<IdExpr>(selfVar)),
|
||||
"==", N<IntExpr>(tag))),
|
||||
N<BinaryExpr>(check, "&&",
|
||||
N<BinaryExpr>(N<CallExpr>(N<DotExpr>(N<IdExpr>("__internal__"),
|
||||
"union_get_tag"),
|
||||
N<IdExpr>(selfVar)),
|
||||
"==", N<IntExpr>(tag))),
|
||||
N<SuiteStmt>(N<ReturnStmt>(N<CallExpr>(callee, args, kwargs)))));
|
||||
tag++;
|
||||
}
|
||||
|
@ -961,8 +959,8 @@ TypecheckVisitor::generateSpecialAst(types::FuncType *type) {
|
|||
|
||||
auto selfVar = ast->args[0].name;
|
||||
auto suite = N<SuiteStmt>(N<ReturnStmt>(
|
||||
N<CallExpr>(N<IdExpr>("__internal__.union_get_data"), N<IdExpr>(selfVar),
|
||||
NT<IdExpr>(unionTypes[0]->realizedName()))));
|
||||
N<CallExpr>(N<DotExpr>(N<IdExpr>("__internal__"), "union_get_data"),
|
||||
N<IdExpr>(selfVar), NT<IdExpr>(unionTypes[0]->realizedName()))));
|
||||
ast->suite = suite;
|
||||
} else if (startswith(ast->name, "__internal__.namedkeys")) {
|
||||
auto n = type->funcGenerics[0].type->getStatic()->evaluate().getInt();
|
||||
|
|
|
@ -272,7 +272,7 @@ void TypecheckVisitor::visit(IndexExpr *expr) {
|
|||
if (expr->expr->isId("tuple") || expr->expr->isId("Tuple")) {
|
||||
// Special case: tuples. Change to Tuple.N
|
||||
auto t = expr->index->getTuple();
|
||||
expr->expr = NT<IdExpr>(format(TYPE_TUPLE "{}", t ? t->items.size() : 1));
|
||||
expr->expr = NT<IdExpr>(generateTuple(t ? t->items.size() : 1));
|
||||
} else {
|
||||
transform(expr->expr, true);
|
||||
}
|
||||
|
@ -828,9 +828,9 @@ TypecheckVisitor::transformStaticTupleIndex(const ClassTypePtr &tuple,
|
|||
E(Error::TUPLE_RANGE_BOUNDS, index, sz - 1, i);
|
||||
te.push_back(N<DotExpr>(clone(var), classItem->fields[i].name));
|
||||
}
|
||||
ExprPtr e = transform(N<StmtExpr>(
|
||||
std::vector<StmtPtr>{ass},
|
||||
N<CallExpr>(N<DotExpr>(format(TYPE_TUPLE "{}", te.size()), "__new__"), te)));
|
||||
ExprPtr e = transform(
|
||||
N<StmtExpr>(std::vector<StmtPtr>{ass},
|
||||
N<CallExpr>(N<DotExpr>(generateTuple(te.size()), "__new__"), te)));
|
||||
return {true, e};
|
||||
}
|
||||
|
||||
|
|
|
@ -504,7 +504,7 @@ bool TypecheckVisitor::wrapExpr(ExprPtr &expr, const TypePtr &expectedType,
|
|||
expr = transform(N<CallExpr>(expr, N<EllipsisExpr>(EllipsisExpr::PARTIAL)));
|
||||
else
|
||||
expr = transform(N<CallExpr>(
|
||||
N<IdExpr>("__internal__.class_ctr"),
|
||||
N<DotExpr>(N<IdExpr>("__internal__"), "class_ctr"),
|
||||
std::vector<CallExpr::Arg>{{"T", expr},
|
||||
{"", N<EllipsisExpr>(EllipsisExpr::PARTIAL)}}));
|
||||
}
|
||||
|
@ -555,8 +555,8 @@ bool TypecheckVisitor::wrapExpr(ExprPtr &expr, const TypePtr &expectedType,
|
|||
!expectedClass->getUnion()) {
|
||||
// Extract union types via __internal__.get_union
|
||||
if (auto t = realize(expectedClass)) {
|
||||
expr = transform(N<CallExpr>(N<IdExpr>("__internal__.get_union"), expr,
|
||||
N<IdExpr>(t->realizedName())));
|
||||
expr = transform(N<CallExpr>(N<DotExpr>(N<IdExpr>("__internal__"), "get_union"),
|
||||
expr, N<IdExpr>(t->realizedName())));
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
@ -566,8 +566,8 @@ bool TypecheckVisitor::wrapExpr(ExprPtr &expr, const TypePtr &expectedType,
|
|||
expectedClass->getUnion()->addType(exprClass);
|
||||
if (auto t = realize(expectedClass)) {
|
||||
if (expectedClass->unify(exprClass.get(), nullptr) == -1)
|
||||
expr = transform(N<CallExpr>(N<IdExpr>("__internal__.new_union"), expr,
|
||||
NT<IdExpr>(t->realizedName())));
|
||||
expr = transform(N<CallExpr>(N<DotExpr>(N<IdExpr>("__internal__"), "new_union"),
|
||||
expr, NT<IdExpr>(t->realizedName())));
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -235,10 +235,9 @@ private: // Node typechecking rules
|
|||
|
||||
/* Classes (class.cpp) */
|
||||
void visit(ClassStmt *) override;
|
||||
std::vector<ClassStmt *> parseBaseClasses(std::vector<ExprPtr> &,
|
||||
std::vector<Param> &, const Attr &,
|
||||
const std::string &, const ExprPtr &,
|
||||
types::ClassTypePtr &);
|
||||
std::vector<types::ClassTypePtr>
|
||||
parseBaseClasses(std::vector<ExprPtr> &, std::vector<Param> &, const Attr &,
|
||||
const std::string &, const ExprPtr &, types::ClassTypePtr &);
|
||||
std::pair<StmtPtr, FunctionStmt *> autoDeduceMembers(ClassStmt *,
|
||||
std::vector<Param> &);
|
||||
std::vector<StmtPtr> getClassMethods(const StmtPtr &s);
|
||||
|
@ -248,6 +247,7 @@ private: // Node typechecking rules
|
|||
bool);
|
||||
std::string generateTuple(size_t);
|
||||
int generateKwId(const std::vector<std::string> & = {});
|
||||
void addClassGenerics(const types::ClassTypePtr &);
|
||||
|
||||
/* The rest (typecheck.cpp) */
|
||||
void visit(SuiteStmt *) override;
|
||||
|
|
|
@ -16,10 +16,10 @@ from internal.types.float import *
|
|||
from internal.types.byte import *
|
||||
from internal.types.generator import *
|
||||
from internal.types.optional import *
|
||||
from internal.internal import *
|
||||
from internal.types.slice import *
|
||||
from internal.types.range import *
|
||||
from internal.types.complex import *
|
||||
from internal.internal import *
|
||||
|
||||
__argv__ = Array[str](0)
|
||||
|
||||
|
|
|
@ -2,8 +2,9 @@
|
|||
|
||||
# Core library
|
||||
|
||||
from internal.core import *
|
||||
from internal.attributes import *
|
||||
from internal.static import static_print as __static_print__
|
||||
|
||||
from internal.types.ptr import *
|
||||
from internal.types.str import *
|
||||
from internal.types.int import *
|
||||
|
@ -15,9 +16,13 @@ from internal.types.float import *
|
|||
from internal.types.byte import *
|
||||
from internal.types.generator import *
|
||||
from internal.types.optional import *
|
||||
from internal.internal import *
|
||||
from internal.types.slice import *
|
||||
from internal.types.range import *
|
||||
from internal.internal import *
|
||||
from internal.types.complex import *
|
||||
|
||||
__argv__ = Array[str](0)
|
||||
|
||||
from internal.types.strbuf import strbuf as _strbuf
|
||||
from internal.types.collections.list import *
|
||||
import internal.c_stubs as _C
|
||||
|
@ -143,6 +148,21 @@ class str:
|
|||
|
||||
return str(self.ptr + i, j - i)
|
||||
|
||||
def join(self, l: Generator[str]) -> str:
|
||||
buf = _strbuf()
|
||||
if len(self) == 0:
|
||||
for a in l:
|
||||
buf.append(a)
|
||||
else:
|
||||
first = True
|
||||
for a in l:
|
||||
if first:
|
||||
first = False
|
||||
else:
|
||||
buf.append(self)
|
||||
buf.append(a)
|
||||
return buf.__str__()
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return f"'{self}'"
|
||||
|
||||
|
|
|
@ -31,7 +31,7 @@ class Exception(Static[BaseException]):
|
|||
_pytype: ClassVar[cobj] = cobj()
|
||||
def __init__(self, typename: str, msg: str = ""):
|
||||
super().__init__(typename, msg)
|
||||
if (hasattr(self.__class__, "_pytype")):
|
||||
if hasattr(self.__class__, "_pytype"):
|
||||
self.python_type = self.__class__._pytype
|
||||
|
||||
class NameError(Static[Exception]):
|
||||
|
|
|
@ -407,23 +407,23 @@ auto getTypeTests(const vector<string> &files) {
|
|||
INSTANTIATE_TEST_SUITE_P(
|
||||
TypeTests, SeqTest,
|
||||
testing::ValuesIn(getTypeTests({
|
||||
"parser/typecheck/access.codon",
|
||||
"parser/typecheck/assign.codon",
|
||||
"parser/typecheck/basic.codon",
|
||||
"parser/typecheck/call.codon",
|
||||
"parser/typecheck/class.codon",
|
||||
"parser/typecheck/collections.codon",
|
||||
"parser/typecheck/cond.codon",
|
||||
"parser/typecheck/ctx.codon",
|
||||
"parser/typecheck/error.codon",
|
||||
"parser/typecheck/function.codon",
|
||||
"parser/typecheck/import.codon",
|
||||
"parser/typecheck/infer.codon",
|
||||
"parser/typecheck/loops.codon",
|
||||
"parser/typecheck/op.codon",
|
||||
"parser/typecheck/parser.codon",
|
||||
"parser/typecheck/python.codon",
|
||||
"parser/typecheck/typecheck.codon"
|
||||
"parser/typecheck/test_access.codon",
|
||||
"parser/typecheck/test_assign.codon",
|
||||
"parser/typecheck/test_basic.codon",
|
||||
"parser/typecheck/test_call.codon",
|
||||
"parser/typecheck/test_class.codon",
|
||||
"parser/typecheck/test_collections.codon",
|
||||
"parser/typecheck/test_cond.codon",
|
||||
"parser/typecheck/test_ctx.codon",
|
||||
"parser/typecheck/test_error.codon",
|
||||
"parser/typecheck/test_function.codon",
|
||||
"parser/typecheck/test_import.codon",
|
||||
"parser/typecheck/test_infer.codon",
|
||||
"parser/typecheck/test_loops.codon",
|
||||
"parser/typecheck/test_op.codon",
|
||||
"parser/typecheck/test_parser.codon",
|
||||
"parser/typecheck/test_python.codon",
|
||||
"parser/typecheck/test_typecheck.codon"
|
||||
})),
|
||||
getTypeTestNameFromParam);
|
||||
|
||||
|
|
|
@ -227,7 +227,7 @@ class Foo:
|
|||
print('foo')
|
||||
def method(self, a):
|
||||
print(a)
|
||||
Foo().clsmethod() #! 'Foo' object has no method 'clsmethod' with arguments (Foo)
|
||||
Foo().clsmethod() #! clsmethod() takes 0 arguments (1 given)
|
||||
|
||||
#%% nested_class_error,barebones
|
||||
class X:
|
|
@ -171,7 +171,7 @@ def doo[R, T](a: Callable[[T], R], b: Generator[T], c: Optional[T], d: T):
|
|||
l = [1, 2, 3]
|
||||
doo(b=l, d=Optional(5), c=l[0], a=lambda x: x+1)
|
||||
#: int int
|
||||
#: ._lambda Generator[int]
|
||||
#: %_lambda Generator[int]
|
||||
#: 2
|
||||
#: 3
|
||||
#: 4
|
|
@ -5,12 +5,12 @@ assert True, "blah"
|
|||
try:
|
||||
assert False
|
||||
except AssertionError as e:
|
||||
print e.message[:15], e.message[-24:] #: Assert failed ( simplify_stmt.codon:164)
|
||||
print e.message[:15], e.message[-19:] #: Assert failed ( test_error.codon:6)
|
||||
|
||||
try:
|
||||
assert False, f"hehe {1}"
|
||||
except AssertionError as e:
|
||||
print e.message[:23], e.message[-24:] #: Assert failed: hehe 1 ( simplify_stmt.codon:169)
|
||||
print e.message[:23], e.message[-20:] #: Assert failed: hehe 1 ( test_error.codon:11)
|
||||
|
||||
#%% try_throw,barebones
|
||||
class MyError(Static[Exception]):
|
||||
|
@ -27,8 +27,8 @@ try:
|
|||
except MyError:
|
||||
print "my"
|
||||
except OSError as o:
|
||||
print "os", o.typename, len(o.message), o.file[-20:], o.line
|
||||
#: os OSError 9 typecheck_stmt.codon 249
|
||||
print "os", o.typename, len(o.message), o.file[-16:], o.line
|
||||
#: os OSError 9 test_error.codon 24
|
||||
finally:
|
||||
print "whoa" #: whoa
|
||||
|
Loading…
Reference in New Issue