From 20200ec810d9fd699ad9b48cccacbb95af50a7e1 Mon Sep 17 00:00:00 2001 From: Thorulf Neustrup Date: Thu, 17 Aug 2023 10:20:11 +0200 Subject: [PATCH 01/13] Allowed double and clock combination --- src/typechecker.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/typechecker.cpp b/src/typechecker.cpp index 10ab020..25c5764 100644 --- a/src/typechecker.cpp +++ b/src/typechecker.cpp @@ -1517,11 +1517,12 @@ expression_t TypeChecker::checkInitialiser(type_t type, expression_t init) */ bool TypeChecker::areInlineIfCompatible(type_t t1, type_t t2) const { - if (t1.is_integral() && t2.is_integral()) { + if (t1.is_integral() && t2.is_integral()) return true; - } else { - return areEquivalent(t1, t2); - } + if (t1.is_double() && t2.is_clock() || t1.is_clock() && t2.is_double()) + return true; + + return areEquivalent(t1, t2); } /** From d8afe9acf7a8e8ccf51e0a8fad57dc2ba07c2f7a Mon Sep 17 00:00:00 2001 From: Thorulf Neustrup Date: Thu, 17 Aug 2023 10:31:15 +0200 Subject: [PATCH 02/13] Relax for integers --- src/typechecker.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/typechecker.cpp b/src/typechecker.cpp index 25c5764..fa89f85 100644 --- a/src/typechecker.cpp +++ b/src/typechecker.cpp @@ -1519,7 +1519,7 @@ bool TypeChecker::areInlineIfCompatible(type_t t1, type_t t2) const { if (t1.is_integral() && t2.is_integral()) return true; - if (t1.is_double() && t2.is_clock() || t1.is_clock() && t2.is_double()) + if ((t1.is_double() || t1.is_integer()) && t2.is_clock() || t1.is_clock() && (t2.is_double() || t2.is_integer())) return true; return areEquivalent(t1, t2); From 55e2b46d0eecf8de9cce483d64ce7df5222a070a Mon Sep 17 00:00:00 2001 From: Thorulf Neustrup Date: Thu, 17 Aug 2023 10:47:24 +0200 Subject: [PATCH 03/13] Added tests for ternary operator with implicit conversions --- test/test_typechecker.cpp | 40 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/test/test_typechecker.cpp b/test/test_typechecker.cpp index 2ed4118..3ca2f7b 100644 --- a/test/test_typechecker.cpp +++ b/test/test_typechecker.cpp @@ -197,3 +197,43 @@ TEST_SUITE("Error positions for unbound parameters") CHECK(pos.end != pos.unknown_pos); } } + +TEST_CASE("Ternary operator with clock and double") +{ + auto doc = document_fixture{} + .add_global_decl("clock c; double x; void f() { x = true? c : 1.0; }") + .add_default_process() + .parse(); + CHECK(doc->get_errors().size() == 0); + CHECK(doc->get_warnings().size() == 0); +} + +TEST_CASE("Ternary operator with clock and integer") +{ + auto doc = document_fixture{} + .add_global_decl("clock c; double x; void f() { x = true? c : 1; }") + .add_default_process() + .parse(); + CHECK(doc->get_errors().size() == 0); + CHECK(doc->get_warnings().size() == 0); +} + +TEST_CASE("Ternary operator with clock and bool") +{ + auto doc = document_fixture{} + .add_global_decl("clock c; double x; void f() { x = true? c : true; };") + .add_default_process() + .parse(); + CHECK(doc->get_errors().size() == 1); + CHECK(doc->get_warnings().size() == 0); +} + +TEST_CASE("Ternary operator with clock and clock") +{ + auto doc = document_fixture{} + .add_global_decl("clock c; double x; void f() { x = true? c : c; }") + .add_default_process() + .parse(); + CHECK(doc->get_errors().size() == 0); + CHECK(doc->get_warnings().size() == 0); +} From f9e499ba0017b226f65ea804110d1c5c09062808 Mon Sep 17 00:00:00 2001 From: Thorulf Neustrup Date: Thu, 17 Aug 2023 10:57:13 +0200 Subject: [PATCH 04/13] Unrelaxed integer conversion --- src/typechecker.cpp | 2 +- test/test_typechecker.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/typechecker.cpp b/src/typechecker.cpp index fa89f85..25c5764 100644 --- a/src/typechecker.cpp +++ b/src/typechecker.cpp @@ -1519,7 +1519,7 @@ bool TypeChecker::areInlineIfCompatible(type_t t1, type_t t2) const { if (t1.is_integral() && t2.is_integral()) return true; - if ((t1.is_double() || t1.is_integer()) && t2.is_clock() || t1.is_clock() && (t2.is_double() || t2.is_integer())) + if (t1.is_double() && t2.is_clock() || t1.is_clock() && t2.is_double()) return true; return areEquivalent(t1, t2); diff --git a/test/test_typechecker.cpp b/test/test_typechecker.cpp index 3ca2f7b..c242436 100644 --- a/test/test_typechecker.cpp +++ b/test/test_typechecker.cpp @@ -214,7 +214,7 @@ TEST_CASE("Ternary operator with clock and integer") .add_global_decl("clock c; double x; void f() { x = true? c : 1; }") .add_default_process() .parse(); - CHECK(doc->get_errors().size() == 0); + CHECK(doc->get_errors().size() == 1); CHECK(doc->get_warnings().size() == 0); } From ab5ca115bf887557970bf57662071dc288326b44 Mon Sep 17 00:00:00 2001 From: Thorulf Neustrup Date: Thu, 17 Aug 2023 11:19:13 +0200 Subject: [PATCH 05/13] Propagate the proper type --- src/ExpressionBuilder.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/ExpressionBuilder.cpp b/src/ExpressionBuilder.cpp index f7ada92..ef31c6a 100644 --- a/src/ExpressionBuilder.cpp +++ b/src/ExpressionBuilder.cpp @@ -543,7 +543,11 @@ void ExpressionBuilder::expr_inline_if() expression_t t = fragments[1]; expression_t e = fragments[0]; fragments.pop(3); - fragments.push(expression_t::create_ternary(INLINE_IF, c, t, e, position, t.get_type())); + + // Handle special case where clock is implicitly converted to double + type_t type = t.get_type().is_clock() && e.get_type().is_double() ? e.get_type() : t.get_type(); + + fragments.push(expression_t::create_ternary(INLINE_IF, c, t, e, position, type)); } void ExpressionBuilder::expr_comma() From 75a54de37bdaf536d501c623566d0d92df5326a1 Mon Sep 17 00:00:00 2001 From: Thorulf Neustrup Date: Thu, 17 Aug 2023 11:51:37 +0200 Subject: [PATCH 06/13] Added further checks to ensure correct conversion --- include/utap/typechecker.h | 2 +- src/typechecker.cpp | 8 ++++---- test/test_typechecker.cpp | 10 ++++++++++ 3 files changed, 15 insertions(+), 5 deletions(-) diff --git a/include/utap/typechecker.h b/include/utap/typechecker.h index 754ed3d..2f591e4 100644 --- a/include/utap/typechecker.h +++ b/include/utap/typechecker.h @@ -69,7 +69,7 @@ class TypeChecker : public DocumentVisitor, public AbstractStatementVisitor expression_t checkInitialiser(type_t type, expression_t init); bool areAssignmentCompatible(type_t lvalue, type_t rvalue, bool init = false) const; - bool areInlineIfCompatible(type_t thenArg, type_t elseArg) const; + bool areInlineIfCompatible(type_t result_type, type_t thenArg, type_t elseArg) const; bool areEqCompatible(type_t t1, type_t t2) const; bool areEquivalent(type_t, type_t) const; bool isLValue(expression_t) const; diff --git a/src/typechecker.cpp b/src/typechecker.cpp index 25c5764..0682867 100644 --- a/src/typechecker.cpp +++ b/src/typechecker.cpp @@ -1515,11 +1515,11 @@ expression_t TypeChecker::checkInitialiser(type_t type, expression_t init) same size and the subtypes must be compatible. In case of records, they must have the same type name. */ -bool TypeChecker::areInlineIfCompatible(type_t t1, type_t t2) const +bool TypeChecker::areInlineIfCompatible(type_t result_type, type_t t1, type_t t2) const { if (t1.is_integral() && t2.is_integral()) return true; - if (t1.is_double() && t2.is_clock() || t1.is_clock() && t2.is_double()) + if (result_type.is_double() && (t1.is_double() && t2.is_clock() || t1.is_clock() && t2.is_double())) return true; return areEquivalent(t1, t2); @@ -2085,11 +2085,11 @@ bool TypeChecker::checkExpression(expression_t expr) handleError(expr, "$First_argument_of_inline_if_must_be_an_integer"); return false; } - if (!areInlineIfCompatible(expr[1].get_type(), expr[2].get_type())) { + if (!areInlineIfCompatible(expr.get_type(), expr[1].get_type(), expr[2].get_type())) { handleError(expr, "$Incompatible_arguments_to_inline_if"); return false; } - type = expr[1].get_type(); + type = expr.get_type(); break; case COMMA: diff --git a/test/test_typechecker.cpp b/test/test_typechecker.cpp index c242436..bb3c41b 100644 --- a/test/test_typechecker.cpp +++ b/test/test_typechecker.cpp @@ -208,6 +208,16 @@ TEST_CASE("Ternary operator with clock and double") CHECK(doc->get_warnings().size() == 0); } +TEST_CASE("Ternary operator with double and clock") +{ + auto doc = document_fixture{} + .add_global_decl("clock c; double x; void f() { x = true? 1.0 : c; }") + .add_default_process() + .parse(); + CHECK(doc->get_errors().size() == 0); + CHECK(doc->get_warnings().size() == 0); +} + TEST_CASE("Ternary operator with clock and integer") { auto doc = document_fixture{} From 398e3dea0328645c48493d810a3b864ccda3584b Mon Sep 17 00:00:00 2001 From: Thorulf Neustrup Date: Thu, 31 Aug 2023 10:38:44 +0200 Subject: [PATCH 07/13] Fixed unary minus typing and added tests --- src/ExpressionBuilder.cpp | 2 +- test/test_typechecker.cpp | 41 ++++++++++++++++++++++++++++++--------- 2 files changed, 33 insertions(+), 10 deletions(-) diff --git a/src/ExpressionBuilder.cpp b/src/ExpressionBuilder.cpp index ef31c6a..7a531bd 100644 --- a/src/ExpressionBuilder.cpp +++ b/src/ExpressionBuilder.cpp @@ -460,7 +460,7 @@ void ExpressionBuilder::expr_unary(kind_t unaryop) // 1 expr case MINUS: unaryop = UNARY_MINUS; /* Fall through! */ - default: fragments[0] = expression_t::create_unary(unaryop, fragments[0], position); + default: fragments[0] = expression_t::create_unary(unaryop, fragments[0], position, fragments[0].get_type()); } } diff --git a/test/test_typechecker.cpp b/test/test_typechecker.cpp index bb3c41b..449070a 100644 --- a/test/test_typechecker.cpp +++ b/test/test_typechecker.cpp @@ -81,7 +81,7 @@ TEST_SUITE("Quantifier forall") df.add_system_decl("bool b[3] = {1,1,1};"); df.add_system_decl("bool x = forall(i : int[0,2]) b[i];"); auto doc = df.add_default_process().parse(); - CHECK(doc->get_warnings().size() == 0); + CHECK_MESSAGE(doc->get_warnings().size() == 0, doc->get_warnings()[0].msg); const auto errors = doc->get_errors(); REQUIRE(errors.size() == 1); CHECK(errors[0].msg == "$Must_be_computable_at_compile_time"); @@ -204,8 +204,8 @@ TEST_CASE("Ternary operator with clock and double") .add_global_decl("clock c; double x; void f() { x = true? c : 1.0; }") .add_default_process() .parse(); - CHECK(doc->get_errors().size() == 0); - CHECK(doc->get_warnings().size() == 0); + CHECK_MESSAGE(doc->get_errors().size() == 0, doc->get_errors()[0].msg); + CHECK_MESSAGE(doc->get_warnings().size() == 0, doc->get_warnings()[0].msg); } TEST_CASE("Ternary operator with double and clock") @@ -214,8 +214,8 @@ TEST_CASE("Ternary operator with double and clock") .add_global_decl("clock c; double x; void f() { x = true? 1.0 : c; }") .add_default_process() .parse(); - CHECK(doc->get_errors().size() == 0); - CHECK(doc->get_warnings().size() == 0); + CHECK_MESSAGE(doc->get_errors().size() == 0, doc->get_errors()[0].msg); + CHECK_MESSAGE(doc->get_warnings().size() == 0, doc->get_warnings()[0].msg); } TEST_CASE("Ternary operator with clock and integer") @@ -225,7 +225,7 @@ TEST_CASE("Ternary operator with clock and integer") .add_default_process() .parse(); CHECK(doc->get_errors().size() == 1); - CHECK(doc->get_warnings().size() == 0); + CHECK_MESSAGE(doc->get_warnings().size() == 0, doc->get_warnings()[0].msg); } TEST_CASE("Ternary operator with clock and bool") @@ -235,7 +235,7 @@ TEST_CASE("Ternary operator with clock and bool") .add_default_process() .parse(); CHECK(doc->get_errors().size() == 1); - CHECK(doc->get_warnings().size() == 0); + CHECK_MESSAGE(doc->get_warnings().size() == 0, doc->get_warnings()[0].msg); } TEST_CASE("Ternary operator with clock and clock") @@ -244,6 +244,29 @@ TEST_CASE("Ternary operator with clock and clock") .add_global_decl("clock c; double x; void f() { x = true? c : c; }") .add_default_process() .parse(); - CHECK(doc->get_errors().size() == 0); - CHECK(doc->get_warnings().size() == 0); + CHECK_MESSAGE(doc->get_errors().size() == 0, doc->get_errors()[0].msg); + CHECK_MESSAGE(doc->get_warnings().size() == 0, doc->get_warnings()[0].msg); } + +TEST_CASE("Ternary operator with constant double") +{ + auto doc = document_fixture{} + .add_global_decl("const double VAL = 2;") + .add_global_decl("double x; void f() { x = true? -VAL : VAL; }") + .add_default_process() + .parse(); + CHECK_MESSAGE(doc->get_errors().size() == 0, doc->get_errors()[0].msg); + CHECK_MESSAGE(doc->get_warnings().size() == 0, doc->get_warnings()[0].msg); +} + +TEST_CASE("Ternary operator with constant double and clock") +{ + auto doc = document_fixture{} + .add_global_decl("const double VAL = 2;") + .add_global_decl("clock c;") + .add_global_decl("double x; void f() { x = true? -VAL : c; }") + .add_default_process() + .parse(); + CHECK_MESSAGE(doc->get_errors().size() == 0, doc->get_errors()[0].msg); + CHECK_MESSAGE(doc->get_warnings().size() == 0, doc->get_warnings()[0].msg); +} \ No newline at end of file From 50c2b63ed50c05b54d2176d5f2e091780659c716 Mon Sep 17 00:00:00 2001 From: Thorulf Neustrup Date: Thu, 31 Aug 2023 13:38:28 +0200 Subject: [PATCH 08/13] Make tests non trivially optimizable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Marius Mikučionis --- test/test_typechecker.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/test/test_typechecker.cpp b/test/test_typechecker.cpp index 449070a..d6315d1 100644 --- a/test/test_typechecker.cpp +++ b/test/test_typechecker.cpp @@ -201,7 +201,7 @@ TEST_SUITE("Error positions for unbound parameters") TEST_CASE("Ternary operator with clock and double") { auto doc = document_fixture{} - .add_global_decl("clock c; double x; void f() { x = true? c : 1.0; }") + .add_global_decl("clock c; double x; void f(bool b) { x = b ? c : 1.0; }") .add_default_process() .parse(); CHECK_MESSAGE(doc->get_errors().size() == 0, doc->get_errors()[0].msg); @@ -211,7 +211,7 @@ TEST_CASE("Ternary operator with clock and double") TEST_CASE("Ternary operator with double and clock") { auto doc = document_fixture{} - .add_global_decl("clock c; double x; void f() { x = true? 1.0 : c; }") + .add_global_decl("clock c; double x; void f(bool b) { x = b ? 1.0 : c; }") .add_default_process() .parse(); CHECK_MESSAGE(doc->get_errors().size() == 0, doc->get_errors()[0].msg); @@ -221,7 +221,7 @@ TEST_CASE("Ternary operator with double and clock") TEST_CASE("Ternary operator with clock and integer") { auto doc = document_fixture{} - .add_global_decl("clock c; double x; void f() { x = true? c : 1; }") + .add_global_decl("clock c; double x; void f(bool b) { x = b ? c : 1; }") .add_default_process() .parse(); CHECK(doc->get_errors().size() == 1); @@ -231,7 +231,7 @@ TEST_CASE("Ternary operator with clock and integer") TEST_CASE("Ternary operator with clock and bool") { auto doc = document_fixture{} - .add_global_decl("clock c; double x; void f() { x = true? c : true; };") + .add_global_decl("clock c; double x; void f(bool b) { x = b ? c : true; };") .add_default_process() .parse(); CHECK(doc->get_errors().size() == 1); @@ -241,7 +241,7 @@ TEST_CASE("Ternary operator with clock and bool") TEST_CASE("Ternary operator with clock and clock") { auto doc = document_fixture{} - .add_global_decl("clock c; double x; void f() { x = true? c : c; }") + .add_global_decl("clock c; double x; void f(bool b) { x = b ? c : c; }") .add_default_process() .parse(); CHECK_MESSAGE(doc->get_errors().size() == 0, doc->get_errors()[0].msg); @@ -252,7 +252,7 @@ TEST_CASE("Ternary operator with constant double") { auto doc = document_fixture{} .add_global_decl("const double VAL = 2;") - .add_global_decl("double x; void f() { x = true? -VAL : VAL; }") + .add_global_decl("double x; void f(bool b) { x = b ? -VAL : VAL; }") .add_default_process() .parse(); CHECK_MESSAGE(doc->get_errors().size() == 0, doc->get_errors()[0].msg); @@ -264,7 +264,7 @@ TEST_CASE("Ternary operator with constant double and clock") auto doc = document_fixture{} .add_global_decl("const double VAL = 2;") .add_global_decl("clock c;") - .add_global_decl("double x; void f() { x = true? -VAL : c; }") + .add_global_decl("double x; void f(bool b) { x = b ? -VAL : c; }") .add_default_process() .parse(); CHECK_MESSAGE(doc->get_errors().size() == 0, doc->get_errors()[0].msg); From 207766749e769dae68a51663dd1b61ff47643d08 Mon Sep 17 00:00:00 2001 From: Thorulf Neustrup Date: Thu, 31 Aug 2023 15:53:54 +0200 Subject: [PATCH 09/13] Used concept of common type from c++ and added more tests --- include/utap/typechecker.h | 2 +- src/ExpressionBuilder.cpp | 20 ++++++++++++++-- src/typechecker.cpp | 6 ++--- test/test_typechecker.cpp | 47 +++++++++++++++++++++++++++++++++++++- 4 files changed, 67 insertions(+), 8 deletions(-) diff --git a/include/utap/typechecker.h b/include/utap/typechecker.h index 2f591e4..3f75eae 100644 --- a/include/utap/typechecker.h +++ b/include/utap/typechecker.h @@ -71,7 +71,6 @@ class TypeChecker : public DocumentVisitor, public AbstractStatementVisitor bool areAssignmentCompatible(type_t lvalue, type_t rvalue, bool init = false) const; bool areInlineIfCompatible(type_t result_type, type_t thenArg, type_t elseArg) const; bool areEqCompatible(type_t t1, type_t t2) const; - bool areEquivalent(type_t, type_t) const; bool isLValue(expression_t) const; bool isModifiableLValue(expression_t) const; bool isUniqueReference(expression_t expr) const; @@ -86,6 +85,7 @@ class TypeChecker : public DocumentVisitor, public AbstractStatementVisitor void checkType(type_t, bool initialisable = false, bool inStruct = false); public: + static bool areEquivalent(type_t, type_t); explicit TypeChecker(Document& doc, bool refinement = false); void visitTemplateAfter(template_t&) override; bool visitTemplateBefore(template_t&) override; diff --git a/src/ExpressionBuilder.cpp b/src/ExpressionBuilder.cpp index 7a531bd..33ee3c1 100644 --- a/src/ExpressionBuilder.cpp +++ b/src/ExpressionBuilder.cpp @@ -21,6 +21,8 @@ #include "utap/ExpressionBuilder.hpp" +#include "utap/typechecker.h" + #include #include #include @@ -544,10 +546,24 @@ void ExpressionBuilder::expr_inline_if() expression_t e = fragments[0]; fragments.pop(3); - // Handle special case where clock is implicitly converted to double + // Find the common type of expression t and e + type_t t1 = t.get_type(); + type_t t2 = e.get_type(); + type_t common_type; + if (t1.is_record()) + common_type = t1; + else if (t2.is_record()) + common_type = t2; + else if (t1.is_clock() && !t2.is_clock() || !t1.is_clock() && t2.is_clock()) + common_type = type_t{DOUBLE, {}, 0}; + else if (TypeChecker::areEquivalent(t1, t2)) + common_type = t1; + else + handle_error(TypeException{"$Incompatible_arguments_to_inline_if"}); + type_t type = t.get_type().is_clock() && e.get_type().is_double() ? e.get_type() : t.get_type(); - fragments.push(expression_t::create_ternary(INLINE_IF, c, t, e, position, type)); + fragments.push(expression_t::create_ternary(INLINE_IF, c, t, e, position, common_type)); } void ExpressionBuilder::expr_comma() diff --git a/src/typechecker.cpp b/src/typechecker.cpp index 0682867..027d6c1 100644 --- a/src/typechecker.cpp +++ b/src/typechecker.cpp @@ -1517,9 +1517,7 @@ expression_t TypeChecker::checkInitialiser(type_t type, expression_t init) */ bool TypeChecker::areInlineIfCompatible(type_t result_type, type_t t1, type_t t2) const { - if (t1.is_integral() && t2.is_integral()) - return true; - if (result_type.is_double() && (t1.is_double() && t2.is_clock() || t1.is_clock() && t2.is_double())) + if (areAssignmentCompatible(result_type, t1) && areAssignmentCompatible(result_type, t1)) return true; return areEquivalent(t1, t2); @@ -1530,7 +1528,7 @@ bool TypeChecker::areInlineIfCompatible(type_t result_type, type_t t1, type_t t2 * equivalent. However, CONST, SYSTEM_META, and REF are ignored. Scalar sets * are checked using named equivalence. */ -bool TypeChecker::areEquivalent(type_t a, type_t b) const +bool TypeChecker::areEquivalent(type_t a, type_t b) { if (a.is_integer() && b.is_integer()) { return !a.is(RANGE) || !b.is(RANGE) || diff --git a/test/test_typechecker.cpp b/test/test_typechecker.cpp index 449070a..b47038b 100644 --- a/test/test_typechecker.cpp +++ b/test/test_typechecker.cpp @@ -224,7 +224,7 @@ TEST_CASE("Ternary operator with clock and integer") .add_global_decl("clock c; double x; void f() { x = true? c : 1; }") .add_default_process() .parse(); - CHECK(doc->get_errors().size() == 1); + CHECK_MESSAGE(doc->get_errors().size() == 0, doc->get_errors()[0].msg); CHECK_MESSAGE(doc->get_warnings().size() == 0, doc->get_warnings()[0].msg); } @@ -269,4 +269,49 @@ TEST_CASE("Ternary operator with constant double and clock") .parse(); CHECK_MESSAGE(doc->get_errors().size() == 0, doc->get_errors()[0].msg); CHECK_MESSAGE(doc->get_warnings().size() == 0, doc->get_warnings()[0].msg); +} + +TEST_CASE("Ternary operator with boolean and clock") +{ + auto doc = document_fixture{} + .add_global_decl("clock c;") + .add_global_decl("double x; void f() { x = true? true : c; }") + .add_default_process() + .parse(); + CHECK_MESSAGE(doc->get_errors().size() == 0, doc->get_errors()[0].msg); + CHECK_MESSAGE(doc->get_warnings().size() == 0, doc->get_warnings()[0].msg); +} + +TEST_CASE("Ternary operator with struct and double") +{ + auto doc = document_fixture{} + .add_global_decl("struct { int x; } s;") + .add_global_decl("double x; void f() { x = true? s : 0.5; }") + .add_default_process() + .parse(); + CHECK(doc->get_errors().size() == 1); + CHECK_MESSAGE(doc->get_warnings().size() == 0, doc->get_warnings()[0].msg); +} + +TEST_CASE("Ternary operator with struct and double") +{ + auto doc = document_fixture{} + .add_global_decl("struct { int x; } s;") + .add_global_decl("double x; void f() { x = true? s : 0.5; }") + .add_default_process() + .parse(); + CHECK(doc->get_errors().size() == 1); + CHECK_MESSAGE(doc->get_warnings().size() == 0, doc->get_warnings()[0].msg); +} + +TEST_CASE("Ternary operator with struct and struct") +{ + auto doc = document_fixture{} + .add_global_decl("typedef struct { int x; } S;") + .add_global_decl("S s; S x = {5}; S y = {2};") + .add_global_decl("void f() { s = true? x : y; }") + .add_default_process() + .parse(); + CHECK_MESSAGE(doc->get_errors().size() == 0, doc->get_errors()[0].msg); + CHECK_MESSAGE(doc->get_warnings().size() == 0, doc->get_warnings()[0].msg); } \ No newline at end of file From 43d4ac5816eda68db4caaf9a10cb3ca5a9c4143e Mon Sep 17 00:00:00 2001 From: Thorulf Neustrup Date: Thu, 31 Aug 2023 15:55:40 +0200 Subject: [PATCH 10/13] Made tests more consistent --- test/test_typechecker.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/test_typechecker.cpp b/test/test_typechecker.cpp index af13cd9..2fe486c 100644 --- a/test/test_typechecker.cpp +++ b/test/test_typechecker.cpp @@ -275,7 +275,7 @@ TEST_CASE("Ternary operator with boolean and clock") { auto doc = document_fixture{} .add_global_decl("clock c;") - .add_global_decl("double x; void f() { x = true? true : c; }") + .add_global_decl("double x; void f(bool b) { x = b? true : c; }") .add_default_process() .parse(); CHECK_MESSAGE(doc->get_errors().size() == 0, doc->get_errors()[0].msg); @@ -286,7 +286,7 @@ TEST_CASE("Ternary operator with struct and double") { auto doc = document_fixture{} .add_global_decl("struct { int x; } s;") - .add_global_decl("double x; void f() { x = true? s : 0.5; }") + .add_global_decl("double x; void f(bool b) { x = b? s : 0.5; }") .add_default_process() .parse(); CHECK(doc->get_errors().size() == 1); @@ -297,7 +297,7 @@ TEST_CASE("Ternary operator with struct and double") { auto doc = document_fixture{} .add_global_decl("struct { int x; } s;") - .add_global_decl("double x; void f() { x = true? s : 0.5; }") + .add_global_decl("double x; void f(bool b) { x = b? s : 0.5; }") .add_default_process() .parse(); CHECK(doc->get_errors().size() == 1); @@ -309,7 +309,7 @@ TEST_CASE("Ternary operator with struct and struct") auto doc = document_fixture{} .add_global_decl("typedef struct { int x; } S;") .add_global_decl("S s; S x = {5}; S y = {2};") - .add_global_decl("void f() { s = true? x : y; }") + .add_global_decl("void f(bool b) { s = b? x : y; }") .add_default_process() .parse(); CHECK_MESSAGE(doc->get_errors().size() == 0, doc->get_errors()[0].msg); From 04caf75e38cca0ee1612389ad12f9f8e35af9086 Mon Sep 17 00:00:00 2001 From: Thorulf Neustrup Date: Fri, 1 Sep 2023 14:24:55 +0200 Subject: [PATCH 11/13] Added more tests --- test/test_typechecker.cpp | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/test/test_typechecker.cpp b/test/test_typechecker.cpp index cb43dcd..851d84d 100644 --- a/test/test_typechecker.cpp +++ b/test/test_typechecker.cpp @@ -198,6 +198,36 @@ TEST_SUITE("Error positions for unbound parameters") } } +TEST_CASE("Ternary operator with arrays clock and double") +{ + auto doc = document_fixture{} + .add_global_decl("clock c; double x[2]; void f(bool b) { (b?x[0]:x[1]) = c; }") + .add_default_process() + .parse(); + CHECK_MESSAGE(doc->get_errors().size() == 0, doc->get_errors()[0].msg); + CHECK_MESSAGE(doc->get_warnings().size() == 0, doc->get_warnings()[0].msg); +} + +TEST_CASE("Ternary operator with arrays clock and double") +{ + auto doc = document_fixture{} + .add_global_decl("clock c; double x[2]; void f(bool b) { x[0] = b ? c : x[1]; }") + .add_default_process() + .parse(); + CHECK_MESSAGE(doc->get_errors().size() == 0, doc->get_errors()[0].msg); + CHECK_MESSAGE(doc->get_warnings().size() == 0, doc->get_warnings()[0].msg); +} + +TEST_CASE("Ternary operator with struct clock and double") +{ + auto doc = document_fixture{} + .add_global_decl("struct{ clock c; double x; }z; void f(bool b) { z.x = b ? z.c : 1.0; }") + .add_default_process() + .parse(); + CHECK_MESSAGE(doc->get_errors().size() == 0, doc->get_errors()[0].msg); + CHECK_MESSAGE(doc->get_warnings().size() == 0, doc->get_warnings()[0].msg); +} + TEST_CASE("Ternary operator with clock and double") { auto doc = document_fixture{} From fd9f12a9c510dc06ea3de15e5b700f7b0fca76ce Mon Sep 17 00:00:00 2001 From: Thorulf Neustrup Date: Fri, 1 Sep 2023 14:31:39 +0200 Subject: [PATCH 12/13] Added additional test and improved naming --- test/test_typechecker.cpp | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/test/test_typechecker.cpp b/test/test_typechecker.cpp index 851d84d..22c39cc 100644 --- a/test/test_typechecker.cpp +++ b/test/test_typechecker.cpp @@ -198,7 +198,18 @@ TEST_SUITE("Error positions for unbound parameters") } } -TEST_CASE("Ternary operator with arrays clock and double") +TEST_CASE("Ternary operator with reference to integer array") +{ + auto doc = document_fixture{} + .add_global_decl("int x[2]; int y[2]; int z[2];") + .add_global_decl("void f(bool b) { z = (b?x:y); }") + .add_default_process() + .parse(); + CHECK_MESSAGE(doc->get_errors().size() == 0, doc->get_errors()[0].msg); + CHECK_MESSAGE(doc->get_warnings().size() == 0, doc->get_warnings()[0].msg); +} + +TEST_CASE("Assign clock to terneray operator using double array") { auto doc = document_fixture{} .add_global_decl("clock c; double x[2]; void f(bool b) { (b?x[0]:x[1]) = c; }") From b3c6954fcbfba3c86bcbbf3bb621fac7b393933d Mon Sep 17 00:00:00 2001 From: Thorulf Neustrup Date: Fri, 1 Sep 2023 14:36:01 +0200 Subject: [PATCH 13/13] Moved tests --- test/test_typechecker.cpp | 83 ++++++++++++++++++++------------------- 1 file changed, 42 insertions(+), 41 deletions(-) diff --git a/test/test_typechecker.cpp b/test/test_typechecker.cpp index 22c39cc..4df6ee1 100644 --- a/test/test_typechecker.cpp +++ b/test/test_typechecker.cpp @@ -198,47 +198,6 @@ TEST_SUITE("Error positions for unbound parameters") } } -TEST_CASE("Ternary operator with reference to integer array") -{ - auto doc = document_fixture{} - .add_global_decl("int x[2]; int y[2]; int z[2];") - .add_global_decl("void f(bool b) { z = (b?x:y); }") - .add_default_process() - .parse(); - CHECK_MESSAGE(doc->get_errors().size() == 0, doc->get_errors()[0].msg); - CHECK_MESSAGE(doc->get_warnings().size() == 0, doc->get_warnings()[0].msg); -} - -TEST_CASE("Assign clock to terneray operator using double array") -{ - auto doc = document_fixture{} - .add_global_decl("clock c; double x[2]; void f(bool b) { (b?x[0]:x[1]) = c; }") - .add_default_process() - .parse(); - CHECK_MESSAGE(doc->get_errors().size() == 0, doc->get_errors()[0].msg); - CHECK_MESSAGE(doc->get_warnings().size() == 0, doc->get_warnings()[0].msg); -} - -TEST_CASE("Ternary operator with arrays clock and double") -{ - auto doc = document_fixture{} - .add_global_decl("clock c; double x[2]; void f(bool b) { x[0] = b ? c : x[1]; }") - .add_default_process() - .parse(); - CHECK_MESSAGE(doc->get_errors().size() == 0, doc->get_errors()[0].msg); - CHECK_MESSAGE(doc->get_warnings().size() == 0, doc->get_warnings()[0].msg); -} - -TEST_CASE("Ternary operator with struct clock and double") -{ - auto doc = document_fixture{} - .add_global_decl("struct{ clock c; double x; }z; void f(bool b) { z.x = b ? z.c : 1.0; }") - .add_default_process() - .parse(); - CHECK_MESSAGE(doc->get_errors().size() == 0, doc->get_errors()[0].msg); - CHECK_MESSAGE(doc->get_warnings().size() == 0, doc->get_warnings()[0].msg); -} - TEST_CASE("Ternary operator with clock and double") { auto doc = document_fixture{} @@ -356,6 +315,48 @@ TEST_CASE("Ternary operator with struct and struct") CHECK_MESSAGE(doc->get_errors().size() == 0, doc->get_errors()[0].msg); CHECK_MESSAGE(doc->get_warnings().size() == 0, doc->get_warnings()[0].msg); } + +TEST_CASE("Ternary operator with reference to integer array") +{ + auto doc = document_fixture{} + .add_global_decl("int x[2]; int y[2]; int z[2];") + .add_global_decl("void f(bool b) { z = (b?x:y); }") + .add_default_process() + .parse(); + CHECK_MESSAGE(doc->get_errors().size() == 0, doc->get_errors()[0].msg); + CHECK_MESSAGE(doc->get_warnings().size() == 0, doc->get_warnings()[0].msg); +} + +TEST_CASE("Ternary operator with arrays clock and double") +{ + auto doc = document_fixture{} + .add_global_decl("clock c; double x[2]; void f(bool b) { x[0] = b ? c : x[1]; }") + .add_default_process() + .parse(); + CHECK_MESSAGE(doc->get_errors().size() == 0, doc->get_errors()[0].msg); + CHECK_MESSAGE(doc->get_warnings().size() == 0, doc->get_warnings()[0].msg); +} + +TEST_CASE("Ternary operator with struct clock and double") +{ + auto doc = document_fixture{} + .add_global_decl("struct{ clock c; double x; }z; void f(bool b) { z.x = b ? z.c : 1.0; }") + .add_default_process() + .parse(); + CHECK_MESSAGE(doc->get_errors().size() == 0, doc->get_errors()[0].msg); + CHECK_MESSAGE(doc->get_warnings().size() == 0, doc->get_warnings()[0].msg); +} + +TEST_CASE("Terneray operator returning c++ reference to doubles with assignment") +{ + auto doc = document_fixture{} + .add_global_decl("clock c; double x[2]; void f(bool b) { (b?x[0]:x[1]) = c; }") + .add_default_process() + .parse(); + CHECK_MESSAGE(doc->get_errors().size() == 0, doc->get_errors()[0].msg); + CHECK_MESSAGE(doc->get_warnings().size() == 0, doc->get_warnings()[0].msg); +} + TEST_CASE("Double in struct") { auto doc = document_fixture{}.add_default_process().add_global_decl("struct { double x; } my_struct;").parse();