Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement prim 'has default value' #26678

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions frontend/include/chpl/types/Type.h
Original file line number Diff line number Diff line change
Expand Up @@ -347,6 +347,8 @@ class Type {
*/
static bool isPod(Context* context, const Type* t);

static bool isDefaultInitializable(const Type* t);

static bool needsInitDeinitCall(const Type* t);

/// \cond DO_NOT_DOCUMENT
Expand Down
8 changes: 7 additions & 1 deletion frontend/lib/resolution/prims.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1017,6 +1017,12 @@ static QualifiedType primNeedsAutoDestroy(Context* context, const CallInfo& ci)
});
}

static QualifiedType primHasDefaultValue(Context* context, const CallInfo& ci) {
return actualTypeHasProperty(context, ci, [=](auto t) {
return Type::isDefaultInitializable(t);
});
}

static QualifiedType
primIsCoercible(Context* context, const CallInfo& ci) {
if (ci.numActuals() < 2) return QualifiedType();
Expand Down Expand Up @@ -1275,7 +1281,7 @@ CallResolutionResult resolvePrimCall(ResolutionContext* rc,
break;

case PRIM_HAS_DEFAULT_VALUE:
CHPL_UNIMPL("various primitives");
type = primHasDefaultValue(context, ci);
break;

case PRIM_NEEDS_AUTO_DESTROY:
Expand Down
21 changes: 21 additions & 0 deletions frontend/lib/types/Type.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -337,6 +337,27 @@ bool Type::isPod(Context* context, const Type* t) {
return true;
}

bool Type::isDefaultInitializable(const Type* t) {
if (t->isAnySharedType() || t->isAnyOwnedType()) {
return true;
} else if (t->isRecordType() || t->isUnionType()) {
return true;
} else if (t->isBuiltinType()) {
return t->genericity() == Type::CONCRETE;
} else if (auto ct = t->toClassType()) {
return ct->decorator().isNilable();
} else if (auto tup = t->toTupleType()) {
for (int i = 0; i < tup->numElements(); i++) {
if (!isDefaultInitializable(tup->elementType(i).type())) {
return false;
}
}
return true;
}

return !needsInitDeinitCall(t);
}

bool Type::needsInitDeinitCall(const Type* t) {
if (t == nullptr || t->isUnknownType() || t->isErroneousType()) {
// can't do anything with these
Expand Down
98 changes: 68 additions & 30 deletions frontend/test/resolution/testTypePropertyPrimitives.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ struct Test {
};

std::string testName;
bool isChplHomeRequired = false;
bool useStdContext = false;
std::string prelude;
chpl::uast::primtags::PrimitiveTag primitive;
std::vector<PrimitiveCalls> calls;
Expand Down Expand Up @@ -85,23 +85,9 @@ assertParamStringMatch(chpl::types::QualifiedType qt, std::string str,
}

static void testPrimitive(const Test& tpg) {
Context::Configuration config;
if (tpg.isChplHomeRequired) {
if (const char* chplHomeEnv = getenv("CHPL_HOME")) {
config.chplHome = chplHomeEnv;
} else {
std::cout << "CHPL_HOME must be set!" << std::endl;
exit(1);
}
}
Context ctx(config);
Context* context = &ctx;
Context* context = tpg.useStdContext ? buildStdContext() : new Context();
ErrorGuard guard(context);

if (tpg.isChplHomeRequired) {
setupModuleSearchPaths(context, false, false, {}, {});
}

std::stringstream ps;
int counter = 0;
int expectedErrorCount = 0;
Expand Down Expand Up @@ -168,7 +154,7 @@ static void testPrimitive(const Test& tpg) {
static void test0() {
Test tpg {
/* testName */ __FUNCTION__,
/* isChplHomeRequired */ false,
/* useStdContext */ false,
/* prelude */ R"""(
record r1 { var x: int; }
record r2 { type T; var x: T; }
Expand Down Expand Up @@ -235,7 +221,7 @@ static void test0() {
static void test1() {
Test tpg {
/* testName */ __FUNCTION__,
/* isChplHomeRequired */ false,
/* useStdContext */ false,
/* prelude */ R"""(
record r1 { var x: int; }
class c1 { var x: int; }
Expand All @@ -257,7 +243,7 @@ static void test1() {
static void test2() {
Test tpg {
/* testName */ __FUNCTION__,
/* isChplHomeRequired */ false,
/* useStdContext */ false,
/* prelude */ R"""(
record r1 { var x: int; }
class c1 { var x: int; }
Expand All @@ -278,7 +264,7 @@ static void test2() {
static void test3() {
Test tpg {
/* testName */ __FUNCTION__,
/* isChplHomeRequired */ false,
/* useStdContext */ false,
/* prelude */ R"""(
record r1 { var x: int; }
class c1 { var x: int; }
Expand All @@ -300,7 +286,7 @@ static void test3() {
static void test4() {
Test tpg {
/* testName */ __FUNCTION__,
/* isChplHomeRequired */ false,
/* useStdContext */ false,
/* prelude */ R"""(
record r1 { var x: int; }
class c1 { var x: int; }
Expand All @@ -322,7 +308,7 @@ static void test4() {
static void test5() {
Test tpg {
/* testName */ __FUNCTION__,
/* isChplHomeRequired */ false,
/* useStdContext */ false,
/* prelude */ R"""(
record r1 { var x: int; }
class c1 { var x: int; }
Expand All @@ -347,7 +333,7 @@ static void test5() {
static void test6() {
Test tpg {
.testName=__FUNCTION__,
.isChplHomeRequired= true,
.useStdContext= true,
.prelude=R"""(
record r1 { var x: int; }
)""",
Expand All @@ -367,7 +353,7 @@ static void test6() {
static void test7() {
Test tpg {
/* testName */ __FUNCTION__,
/* isChplHomeRequired */ false,
/* useStdContext */ false,
/* prelude */ R"""(
record r1 { var x: int; }
class c1 { var x: int; }
Expand All @@ -391,7 +377,7 @@ static void test7() {
static void test8() {
Test tpg {
/* testName */ __FUNCTION__,
/* isChplHomeRequired */ false,
/* useStdContext */ false,
/* prelude */ R"""(
record r1 { var x: int; }
class c1 { var x: int; }
Expand Down Expand Up @@ -437,7 +423,7 @@ static void test8() {
static void test9() {
Test tpg {
/* testName */ __FUNCTION__,
/* isChplHomeRequired */ false,
/* useStdContext */ false,
/* prelude */ R"""(
record r1 { var x: int; }
class c1 { var x: int; }
Expand Down Expand Up @@ -467,7 +453,7 @@ static void test9() {
static void test10() {
Test tpg {
/* testName */ __FUNCTION__,
/* isChplHomeRequired */ false,
/* useStdContext */ false,
/* prelude */ R"""(
record r1 { var x: int; }
record r2 { type T; var x: T; }
Expand Down Expand Up @@ -520,7 +506,7 @@ static void test10() {
static void test11() {
Test tpg {
/* testName */ __FUNCTION__,
/* isChplHomeRequired */ false,
/* useStdContext */ false,
/* prelude */ R"""(
record r1 { var x: int; }
record r2 { type T; var x: T; }
Expand Down Expand Up @@ -570,7 +556,7 @@ static void test11() {
static void test12() {
Test tpg {
/* testName */ __FUNCTION__,
/* isChplHomeRequired */ false, // TODO: True...
/* useStdContext */ false, // TODO: True...
/* prelude */ R"""(
pragma "ignore noinit"
record r1 {}
Expand Down Expand Up @@ -648,7 +634,7 @@ static void test12() {
static void test13() {
Test tpg {
/* testName */ __FUNCTION__,
/* isChplHomeRequired */ false,
/* useStdContext */ false,
/* prelude */ R"""(
extern type foo;
extern record bar {}
Expand All @@ -664,6 +650,57 @@ static void test13() {
testPrimitive(tpg);
}

static void test14() {
Test tpg {
/* testName */ __FUNCTION__,
/* useStdContext */ true,
/* prelude */ R"""(
class Foo {}
record bar {}
enum color {blue, red}
union baz { var f : owned Foo; }
)""",
/* primitive */ chpl::uast::primtags::PRIM_HAS_DEFAULT_VALUE,
/* calls */ {
/* primitive types */
{ {"bool"}, Test::TRUE },
{ {"int"}, Test::TRUE },
{ {"int(64)"}, Test::TRUE },
{ {"int(32)"}, Test::TRUE },
{ {"uint"}, Test::TRUE },
{ {"real"}, Test::TRUE },
{ {"imag"}, Test::TRUE },
{ {"complex"}, Test::TRUE },
/* record-like builtin types */
{ {"string"}, Test::TRUE },
{ {"bytes"}, Test::TRUE },
{ {"range"}, Test::TRUE },
{ {"sync int"}, Test::TRUE },
{ {"atomic int"}, Test::TRUE },
/* generic builtin types */
{ {"integral"}, Test::FALSE },
{ {"numeric"}, Test::FALSE },
{ {"enum"}, Test::FALSE },
{ {"record"}, Test::FALSE },
{ {"class"}, Test::FALSE },
{ {"class?"}, Test::TRUE },
{ {"shared"}, Test::TRUE },
{ {"shared class"}, Test::FALSE },
{ {"shared class?"}, Test::TRUE },
/* user-defined types */
{ {"bar"}, Test::TRUE },
{ {"owned Foo"}, Test::FALSE },
{ {"owned Foo?"}, Test::TRUE },
{ {"color"}, Test::TRUE },
{ {"(int, bool)"}, Test::TRUE },
{ {"(int, color)"}, Test::TRUE },
{ {"(int, owned Foo)"}, Test::FALSE },
{ {"baz"}, Test::TRUE },
},
};
testPrimitive(tpg);
}

int main() {
test0();
test1();
Expand All @@ -679,4 +716,5 @@ int main() {
test11();
test12();
test13();
test14();
}