Skip to content

Commit

Permalink
Merge pull request #60 from thorulf4/expanded_structs
Browse files Browse the repository at this point in the history
Expanded structs to support clock and double fields
  • Loading branch information
thorulf4 authored Sep 1, 2023
2 parents b7e7640 + a53649b commit b3a2909
Show file tree
Hide file tree
Showing 4 changed files with 202 additions and 9 deletions.
12 changes: 5 additions & 7 deletions src/StatementBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"});
}
}
Expand All @@ -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;
}
}
Expand All @@ -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();
Expand Down
4 changes: 2 additions & 2 deletions src/typechecker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -448,12 +448,12 @@ 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::CLOCK:
case Constants::DOUBLE:
case Constants::INT:
case Constants::BOOL: break;

Expand Down
153 changes: 153 additions & 0 deletions test/test_parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,159 @@ TEST_CASE("Sim region cleanup causes memory errors (run with ASAN)")
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);
}

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);
}

TEST_CASE("Pre increment precedence bug")
{
auto doc = document_fixture{}
Expand Down
42 changes: 42 additions & 0 deletions test/test_typechecker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -197,3 +197,45 @@ 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();
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();
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();
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);
}

0 comments on commit b3a2909

Please sign in to comment.