diff --git a/codon/parser/ast/stmt.cpp b/codon/parser/ast/stmt.cpp index 7b8ccc80..3160fb76 100644 --- a/codon/parser/ast/stmt.cpp +++ b/codon/parser/ast/stmt.cpp @@ -564,6 +564,8 @@ void ClassStmt::parseDecorators() { for (auto &d : decorators) { if (d->isId("deduce")) { attributes.customAttr.insert("deduce"); + } else if (d->isId("__notuple__")) { + attributes.customAttr.insert("__notuple__"); } else if (auto c = d->getCall()) { if (c->expr->isId(Attr::Tuple)) { attributes.set(Attr::Tuple); diff --git a/codon/parser/ast/types/class.cpp b/codon/parser/ast/types/class.cpp index 39cb7078..d3ef83f1 100644 --- a/codon/parser/ast/types/class.cpp +++ b/codon/parser/ast/types/class.cpp @@ -130,13 +130,13 @@ std::string ClassType::realizedTypeName() const { RecordType::RecordType(Cache *cache, std::string name, std::string niceName, std::vector generics, std::vector args, - bool isInternal) + bool noTuple) : ClassType(cache, std::move(name), std::move(niceName), std::move(generics)), - args(std::move(args)), isInternal(false) {} + args(std::move(args)), noTuple(false) {} RecordType::RecordType(const ClassTypePtr &base, std::vector args, - bool isInternal) - : ClassType(base), args(std::move(args)), isInternal(isInternal) {} + bool noTuple) + : ClassType(base), args(std::move(args)), noTuple(noTuple) {} int RecordType::unify(Type *typ, Unification *us) { if (auto tr = typ->getRecord()) { @@ -159,8 +159,7 @@ int RecordType::unify(Type *typ, Unification *us) { } // Handle Tuple<->@tuple: when unifying tuples, only record members matter. if (startswith(name, TYPE_TUPLE) || startswith(tr->name, TYPE_TUPLE)) { - if (!args.empty() || - (!isInternal && !tr->isInternal)) // prevent int<->() unification + if (!args.empty() || (!noTuple && !tr->noTuple)) // prevent POD<->() unification return s1 + int(name == tr->name); else return -1; @@ -178,7 +177,7 @@ TypePtr RecordType::generalize(int atLevel) { auto a = args; for (auto &t : a) t = t->generalize(atLevel); - return std::make_shared(c, a, isInternal); + return std::make_shared(c, a, noTuple); } TypePtr RecordType::instantiate(int atLevel, int *unboundCount, @@ -188,7 +187,7 @@ TypePtr RecordType::instantiate(int atLevel, int *unboundCount, auto a = args; for (auto &t : a) t = t->instantiate(atLevel, unboundCount, cache); - return std::make_shared(c, a, isInternal); + return std::make_shared(c, a, noTuple); } std::vector RecordType::getUnbounds() const { diff --git a/codon/parser/ast/types/class.h b/codon/parser/ast/types/class.h index deba8d8f..d22df194 100644 --- a/codon/parser/ast/types/class.h +++ b/codon/parser/ast/types/class.h @@ -77,14 +77,14 @@ using ClassTypePtr = std::shared_ptr; struct RecordType : public ClassType { /// List of tuple arguments. std::vector args; - bool isInternal; + bool noTuple; explicit RecordType( Cache *cache, std::string name, std::string niceName, std::vector generics = std::vector(), - std::vector args = std::vector(), bool isInternal = false); + std::vector args = std::vector(), bool noTuple = false); RecordType(const ClassTypePtr &base, std::vector args, - bool isInternal = false); + bool noTuple = false); public: int unify(Type *typ, Unification *undo) override; diff --git a/codon/parser/visitors/typecheck/class.cpp b/codon/parser/visitors/typecheck/class.cpp index d273041e..1a7a39e0 100644 --- a/codon/parser/visitors/typecheck/class.cpp +++ b/codon/parser/visitors/typecheck/class.cpp @@ -26,8 +26,8 @@ void TypecheckVisitor::visit(ClassStmt *stmt) { auto typ = Type::makeType(ctx->cache, stmt->name, ctx->cache->rev(stmt->name), stmt->isRecord()) ->getClass(); - if (stmt->isRecord() && stmt->hasAttr(Attr::Internal)) - typ->getRecord()->isInternal = true; + if (stmt->isRecord() && stmt->hasAttr("__notuple__")) + typ->getRecord()->noTuple = true; if (stmt->isRecord() && startswith(stmt->name, TYPE_PARTIAL)) { // Special handling of partial types (e.g., `Partial.0001.foo`) if (auto p = in(ctx->cache->partials, stmt->name)) diff --git a/stdlib/internal/core.codon b/stdlib/internal/core.codon index d2927cc4..b6b729a6 100644 --- a/stdlib/internal/core.codon +++ b/stdlib/internal/core.codon @@ -6,28 +6,33 @@ class __internal__: @tuple @__internal__ +@__notuple__ class bool: pass @tuple @__internal__ +@__notuple__ class byte: pass @tuple @__internal__ +@__notuple__ class int: MAX = 9223372036854775807 pass @tuple @__internal__ +@__notuple__ class float: MIN_10_EXP = -307 pass @tuple @__internal__ +@__notuple__ class float32: MIN_10_EXP = -37 pass @@ -44,6 +49,7 @@ class type: @tuple @__internal__ +@__notuple__ class Function[T, TR]: pass @@ -54,27 +60,32 @@ class Callable[T, TR]: @tuple @__internal__ +@__notuple__ class Ptr[T]: pass cobj = Ptr[byte] @tuple @__internal__ +@__notuple__ class Generator[T]: pass @tuple @__internal__ +@__notuple__ class Optional: T: type = NoneType @tuple @__internal__ +@__notuple__ class Int[N: Static[int]]: pass @tuple @__internal__ +@__notuple__ class UInt[N: Static[int]]: pass @@ -105,8 +116,9 @@ function = Function class Ref[T]: pass -@__internal__ @tuple +@__internal__ +@__notuple__ class Union[TU]: # compiler-generated def __new__(val): diff --git a/test/parser/types.codon b/test/parser/types.codon index a9aa9228..4b878632 100644 --- a/test/parser/types.codon +++ b/test/parser/types.codon @@ -1019,7 +1019,8 @@ print [a for a in ()] #: [] def foo(*args): return [a for a in args] args, result = ((), [()]) -print list(foo(*args)) == result #: False +print list(foo(*args)) #: [] +print result #: [()] #%% type_error_reporting