From 89522c6f19c4644ba710bcd5356f6f6a96de5b56 Mon Sep 17 00:00:00 2001 From: Thorulf Neustrup Date: Sat, 12 Aug 2023 04:53:21 +0200 Subject: [PATCH 1/6] Relax validation --- src/StatementBuilder.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/StatementBuilder.cpp b/src/StatementBuilder.cpp index 0e292a5..fe2a68f 100644 --- a/src/StatementBuilder.cpp +++ b/src/StatementBuilder.cpp @@ -159,7 +159,7 @@ void StatementBuilder::struct_field(const char* name) * the type check phase. */ type_t base = type.strip_array(); - if (!base.is_record() && !base.is_scalar() && !base.is_integral()) { + if (!base.is_record() && !base.is_scalar() && !base.is_integral() && !base.is_double() && !base.is_clock()) { handle_error(TypeException{"$Invalid_type_in_structure"}); } } From fed957accd293e834850ffdde017f5de926f1d89 Mon Sep 17 00:00:00 2001 From: Thorulf Neustrup Date: Sat, 12 Aug 2023 05:12:05 +0200 Subject: [PATCH 2/6] Relax typechecking --- src/typechecker.cpp | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/typechecker.cpp b/src/typechecker.cpp index 10ab020..9489bc3 100644 --- a/src/typechecker.cpp +++ b/src/typechecker.cpp @@ -448,12 +448,6 @@ void TypeChecker::checkType(type_t type, bool initialisable, bool inStruct) checkType(type.get_sub(i), true, true); } break; - - case Constants::STRING: - case Constants::DOUBLE: - if (inStruct) { - handleError(type, "$This_type_cannot_be_declared_inside_a_struct"); - } case Constants::INT: case Constants::BOOL: break; From e90fe014f2d319737db0ab5d3294f951f15acae1 Mon Sep 17 00:00:00 2001 From: Thorulf Neustrup Date: Sat, 12 Aug 2023 05:24:34 +0200 Subject: [PATCH 3/6] Remove const or meta error --- src/typechecker.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/typechecker.cpp b/src/typechecker.cpp index 9489bc3..44054a4 100644 --- a/src/typechecker.cpp +++ b/src/typechecker.cpp @@ -448,6 +448,12 @@ void TypeChecker::checkType(type_t type, bool initialisable, bool inStruct) checkType(type.get_sub(i), true, true); } break; + case Constants::STRING: + if (inStruct) { + handleError(type, "$This_type_cannot_be_declared_inside_a_struct"); + } + case Constants::CLOCK: + case Constants::DOUBLE: case Constants::INT: case Constants::BOOL: break; From d0a1307f9c7583d8c754dbe9a4d641b9fe140670 Mon Sep 17 00:00:00 2001 From: Thorulf Neustrup Date: Sat, 12 Aug 2023 08:30:41 +0200 Subject: [PATCH 4/6] Fixed initialization and added parsing tests --- src/StatementBuilder.cpp | 10 +++--- test/test_parser.cpp | 71 +++++++++++++++++++++++++++++++++++++++ test/test_typechecker.cpp | 39 +++++++++++++++++++++ 3 files changed, 114 insertions(+), 6 deletions(-) diff --git a/src/StatementBuilder.cpp b/src/StatementBuilder.cpp index fe2a68f..dfc98b1 100644 --- a/src/StatementBuilder.cpp +++ b/src/StatementBuilder.cpp @@ -181,13 +181,13 @@ void StatementBuilder::decl_typedef(const char* name) frames.top().add_symbol(name, type, position); } -static bool initRec(type_t type, int thisTypeOnly) +static bool initialisable(type_t type) { type = type.strip(); switch (type.get_kind()) { case RECORD: for (size_t i = 0; i < type.size(); i++) { - if (!initRec(type[i], thisTypeOnly)) { + if (!initialisable(type[i])) { return false; } } @@ -197,14 +197,12 @@ static bool initRec(type_t type, int thisTypeOnly) if (type.get_array_size().is_scalar()) { return false; } - return initRec(type.get_sub(), thisTypeOnly); + return initialisable(type.get_sub()); case STRING: return true; - default: return thisTypeOnly == 0 ? type.is_integral() : (thisTypeOnly == 1 ? type.is_clock() : type.is_double()); + default: return type.is_integral() || type.is_clock() || type.is_double(); } } -static bool initialisable(type_t type) { return initRec(type, 0) || initRec(type, 1) || initRec(type, 2); } - static bool mustInitialise(type_t type) { const auto k = type.get_kind(); diff --git a/test/test_parser.cpp b/test/test_parser.cpp index f3b529c..d732910 100644 --- a/test/test_parser.cpp +++ b/test/test_parser.cpp @@ -265,4 +265,75 @@ TEST_CASE("Sim region cleanup causes memory errors (run with ASAN)") auto& templ = doc->get_templates().back(); auto sims = templ.get_simregions(); CHECK(sims.size() == 3); +} + +TEST_CASE("Struct int,int initialization") +{ + auto doc = + document_fixture{}.add_default_process().add_global_decl("const struct { int x; int y; } s = {1, 1};").parse(); + REQUIRE(doc); + auto& errors = doc->get_errors(); + CHECK(errors.size() == 0); + CHECK(doc->get_warnings().size() == 0); +} + +TEST_CASE("Struct int,double initialization") +{ + auto doc = document_fixture{} + .add_default_process() + .add_global_decl("const struct { int x; double y; } s = {1, 1.0};") + .parse(); + REQUIRE(doc); + auto& errors = doc->get_errors(); + CHECK(errors.size() == 0); + CHECK(doc->get_warnings().size() == 0); +} + +TEST_CASE("Struct double,double initialization") +{ + auto doc = document_fixture{} + .add_default_process() + .add_global_decl("const struct { double x; double y; } s = {1.0, 1};") + .parse(); + REQUIRE(doc); + auto& errors = doc->get_errors(); + CHECK(errors.size() == 0); + CHECK(doc->get_warnings().size() == 0); +} + +TEST_CASE("Nested struct int,double initialization") +{ + auto doc = + document_fixture{} + .add_default_process() + .add_global_decl("typedef struct { int x; double y; } S; struct { S s1; S s2; } s = {{5,5.5},{2,2.25}};") + .parse(); + REQUIRE(doc); + auto& errors = doc->get_errors(); + CHECK(errors.size() == 0); + CHECK(doc->get_warnings().size() == 0); +} + +TEST_CASE("Meta struct") +{ + auto doc = document_fixture{} + .add_default_process() + .add_global_decl("meta struct { int x; double y; } s = {1, 1.0};") + .parse(); + REQUIRE(doc); + auto& errors = doc->get_errors(); + CHECK(errors.size() == 0); + CHECK(doc->get_warnings().size() == 0); +} + +TEST_CASE("Struct meta field") +{ + auto doc = document_fixture{} + .add_default_process() + .add_global_decl("meta struct { int x; meta double y; } s = {1, 1.0};") + .parse(); + REQUIRE(doc); + auto& errors = doc->get_errors(); + CHECK(errors.size() == 0); + CHECK(doc->get_warnings().size() == 0); } \ No newline at end of file diff --git a/test/test_typechecker.cpp b/test/test_typechecker.cpp index 2ed4118..757a363 100644 --- a/test/test_typechecker.cpp +++ b/test/test_typechecker.cpp @@ -197,3 +197,42 @@ TEST_SUITE("Error positions for unbound parameters") CHECK(pos.end != pos.unknown_pos); } } + +TEST_CASE("Double in struct") +{ + auto doc = document_fixture{}.add_default_process().add_global_decl("struct { double x; } my_struct;").parse(); + + CHECK(doc->get_globals().variables.size() == 1); + + auto warns = doc->get_warnings(); + CHECK(warns.size() == 0); + auto errs = doc->get_errors(); + CHECK(errs.size() == 0); +} + +TEST_CASE("Clock in struct") +{ + auto doc = document_fixture{}.add_default_process().add_global_decl("struct { clock x; } my_struct;").parse(); + + CHECK(doc->get_globals().variables.size() == 1); + + auto warns = doc->get_warnings(); + CHECK(warns.size() == 0); + auto errs = doc->get_errors(); + CHECK(errs.size() == 0); +} + +TEST_CASE("Nested structs") +{ + auto doc = document_fixture{} + .add_default_process() + .add_global_decl("struct { struct { clock x; } nested } my_struct;") + .parse(); + + CHECK(doc->get_globals().variables.size() == 1); + + auto warns = doc->get_warnings(); + CHECK(warns.size() == 0); + auto errs = doc->get_errors(); + CHECK(errs.size() == 0); +} \ No newline at end of file From 809b621d1d4f6aac2fc34a61d6d515f7b1b01288 Mon Sep 17 00:00:00 2001 From: Thorulf Neustrup Date: Sat, 12 Aug 2023 08:41:51 +0200 Subject: [PATCH 5/6] Updated type checking tests --- test/test_typechecker.cpp | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/test/test_typechecker.cpp b/test/test_typechecker.cpp index 757a363..3ad5c71 100644 --- a/test/test_typechecker.cpp +++ b/test/test_typechecker.cpp @@ -201,9 +201,6 @@ TEST_SUITE("Error positions for unbound parameters") TEST_CASE("Double in struct") { auto doc = document_fixture{}.add_default_process().add_global_decl("struct { double x; } my_struct;").parse(); - - CHECK(doc->get_globals().variables.size() == 1); - auto warns = doc->get_warnings(); CHECK(warns.size() == 0); auto errs = doc->get_errors(); @@ -213,9 +210,6 @@ TEST_CASE("Double in struct") TEST_CASE("Clock in struct") { auto doc = document_fixture{}.add_default_process().add_global_decl("struct { clock x; } my_struct;").parse(); - - CHECK(doc->get_globals().variables.size() == 1); - auto warns = doc->get_warnings(); CHECK(warns.size() == 0); auto errs = doc->get_errors(); @@ -226,13 +220,22 @@ TEST_CASE("Nested structs") { auto doc = document_fixture{} .add_default_process() - .add_global_decl("struct { struct { clock x; } nested } my_struct;") + .add_global_decl("struct { struct { clock x; } nested; } my_struct;") .parse(); - - CHECK(doc->get_globals().variables.size() == 1); - auto warns = doc->get_warnings(); CHECK(warns.size() == 0); auto errs = doc->get_errors(); CHECK(errs.size() == 0); +} + +TEST_CASE("Nested structs") +{ + auto doc = document_fixture{} + .add_default_process() + .add_global_decl("struct { int x; double y; } my_struct = {1.0, 1.0};") + .parse(); + auto warns = doc->get_warnings(); + CHECK(warns.size() == 0); + auto errs = doc->get_errors(); + CHECK(errs.size() == 1); } \ No newline at end of file From 5920fd30eb8bcb0915acc7242b358998f5509a07 Mon Sep 17 00:00:00 2001 From: Thorulf Neustrup Date: Fri, 1 Sep 2023 09:39:03 +0200 Subject: [PATCH 6/6] Added additional tests --- test/test_parser.cpp | 82 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 82 insertions(+) diff --git a/test/test_parser.cpp b/test/test_parser.cpp index d732910..aca5b7a 100644 --- a/test/test_parser.cpp +++ b/test/test_parser.cpp @@ -336,4 +336,86 @@ TEST_CASE("Struct meta field") auto& errors = doc->get_errors(); CHECK(errors.size() == 0); CHECK(doc->get_warnings().size() == 0); +} + +TEST_CASE("Initializing doubles in struct with ints") +{ + auto doc = document_fixture{} + .add_default_process() + .add_global_decl("meta struct { double x; meta double y; } s = {1, 1};") + .parse(); + REQUIRE(doc); + auto& errors = doc->get_errors(); + CHECK(errors.size() == 0); + CHECK(doc->get_warnings().size() == 0); +} + +TEST_CASE("Initializing ints with double value") +{ + auto doc = + document_fixture{}.add_default_process().add_global_decl("struct { int x; int y; } s = {1.1, 1.2};").parse(); + REQUIRE(doc); + auto& errors = doc->get_errors(); + CHECK(errors.size() == 2); + CHECK(doc->get_warnings().size() == 0); +} + +TEST_CASE("Meta field in non meta struct") +{ + auto doc = document_fixture{} + .add_default_process() + .add_global_decl("struct { int x; meta double y; } s = {1, 1.0};") + .parse(); + REQUIRE(doc); + auto& errors = doc->get_errors(); + CHECK(errors.size() == 0); + CHECK(doc->get_warnings().size() == 0); +} + +TEST_CASE("Meta field in non meta struct") +{ + auto doc = document_fixture{} + .add_default_process() + .add_global_decl("struct { int x; meta double y; } s = {1, 1.0};") + .parse(); + REQUIRE(doc); + auto& errors = doc->get_errors(); + CHECK(errors.size() == 0); + CHECK(doc->get_warnings().size() == 0); +} + +TEST_CASE("Nested structs") +{ + auto doc = document_fixture{} + .add_default_process() + .add_global_decl("struct { int x; struct { int y; double d;} data; } s = {1, {5, 5.0}};") + .parse(); + REQUIRE(doc); + auto& errors = doc->get_errors(); + CHECK(errors.size() == 0); + CHECK(doc->get_warnings().size() == 0); +} + +TEST_CASE("Structs with arrays") +{ + auto doc = document_fixture{} + .add_default_process() + .add_global_decl("struct { int x[2]; double y[2]; } s = {{1,1}, {5.0, 5.0}};") + .parse(); + REQUIRE(doc); + auto& errors = doc->get_errors(); + CHECK(errors.size() == 0); + CHECK(doc->get_warnings().size() == 0); +} + +TEST_CASE("Array of structs") +{ + auto doc = document_fixture{} + .add_default_process() + .add_global_decl("struct { int x; double y;} s[2] = {{1,5.0}, {1,2.5}};") + .parse(); + REQUIRE(doc); + auto& errors = doc->get_errors(); + CHECK_MESSAGE(errors.size() == 0, errors.at(0).msg); + CHECK(doc->get_warnings().size() == 0); } \ No newline at end of file