diff --git a/com.rockwellcollins.atc.agree.tests/README.md b/com.rockwellcollins.atc.agree.tests/README.md index 2db5a9ffa..206e703ba 100644 --- a/com.rockwellcollins.atc.agree.tests/README.md +++ b/com.rockwellcollins.atc.agree.tests/README.md @@ -49,28 +49,21 @@ The validation tests are declared in [AgreeValidationTest.java](https://github.c To insert a new test, insert `@Test` and then define the test as `public void test{GrammarElement}{ValidationCheckDescription}() throws Exception{...}` (e.g., `public void testProveStatementMustContainClaimError() throws Exception{...}`). Every test should like like this (or something very similar) with its own specific `String test` and testing functionality indicated by `...`: ``` -String test = "package TestPackage\r\n" - + "public\r\n" - + "\r\n" + "with Base_Types;\r\n" + "\r\n" + "annex agree {**\r\n" - + " const TEST_VAL: real = 10; -- should throw an error;\r\n" - + "**};\r\n" - + "\r\n" - + "system A\r\n" + " features\r\n" + " Input_Val: in data port Base_Types::Float;\r\n" - + " Output_Val: out data port Base_Types::Float;\r\n" + " annex agree {**\r\n" - + " assume A1 \"\" : Input_Val < 20; -- should throw an error\r\n" + " **};\r\n" + "end A;\r\n" - + "\r\n" - + "system S\r\n" + " features\r\n" + " Input_Val: in data port Base_Types::Float;\r\n" - + " Output_Val: out data port Base_Types::Float;\r\n" + " annex agree {**\r\n" - + " assume A1 \"\" : Input_Val < TEST_VAL;\r\n" - + " **};\r\n" - + "end S;\r\n" - + "\r\n" - + "system implementation S.impl\r\n" + " subcomponents\r\n" + " A: system A;\r\n" - + " connections\r\n" + " c1_a: port Input_Val -> A.Input_Val; \r\n" - + " c2_a: port A.Output_Val -> Output_Val;\r\n" + "end S.impl;\r\n" - + "\r\n" - + "end TestPackage;"; - FluentIssueCollection issueCollection = testHelper.testString(test); +@Test +public void testEnumStatementMultipleUsesOfValueError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + " \r\n" + + "annex agree {**\r\n" + + " enum test1 = {alpha, beta, gamma};\r\n" + + " enum test2 = {gamma, phi, epsilon};\r\n" + + "**};\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues, "Multiple uses of the same enum value 'gamma' in 'TestPackage::test1' and 'TestPackage::test2'")); ... } ``` diff --git a/com.rockwellcollins.atc.agree.tests/src/com/rockwellcollins/atc/agree/tests/AgreeValidationTest.java b/com.rockwellcollins.atc.agree.tests/src/com/rockwellcollins/atc/agree/tests/AgreeValidationTest.java index eb1e5561d..2cb86f1a3 100644 --- a/com.rockwellcollins.atc.agree.tests/src/com/rockwellcollins/atc/agree/tests/AgreeValidationTest.java +++ b/com.rockwellcollins.atc.agree.tests/src/com/rockwellcollins/atc/agree/tests/AgreeValidationTest.java @@ -2,12 +2,15 @@ import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; import java.util.List; +import org.eclipse.xtext.diagnostics.Severity; import org.eclipse.xtext.testing.InjectWith; import org.eclipse.xtext.testing.XtextRunner; import org.eclipse.xtext.validation.Issue; +import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; import org.osate.testsupport.TestHelper; @@ -25,34 +28,5161 @@ public class AgreeValidationTest extends XtextTest { TestHelper testHelper; @Test - public void testConstStatementTypeMismatch() throws Exception { + public void testEnumStatementNoErrors() throws Exception { String test = "package TestPackage\r\n" + "public\r\n" - + "\r\n" + "with Base_Types;\r\n" + "\r\n" + "annex agree {**\r\n" - + " const TEST_VAL: real = 10; -- should throw an error;\r\n" + + " \r\n" + + "annex agree {**\r\n" + + " enum test = {alpha, beta, gamma};\r\n" + "**};\r\n" + "\r\n" - + "system A\r\n" + " features\r\n" + " Input_Val: in data port Base_Types::Float;\r\n" - + " Output_Val: out data port Base_Types::Float;\r\n" + " annex agree {**\r\n" - + " assume A1 \"\" : Input_Val < 20; -- should throw an error\r\n" + " **};\r\n" + "end A;\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + assertTrue(issueCollection.getIssues().isEmpty()); + } + + @Test + public void testEnumStatementMultipleUsesOfValueError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + " \r\n" + + "annex agree {**\r\n" + + " enum test1 = {alpha, beta, gamma};\r\n" + + " enum test2 = {gamma, phi, epsilon};\r\n" + + "**};\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues, "Multiple uses of the same enum value 'gamma' in 'TestPackage::test1' and 'TestPackage::test2'")); + } + + @Test + public void testEnumStatementDefinedOnlyInAADLPkgError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + "\r\n" + + "system sys\r\n" + + " annex agree {**\r\n" + + " enum test = {alpha, beta, gamma};\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues, "Enumerations can be defined only in AADL packages")); + } + + @Test + public void testConnectionStatementNoErrors() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + "\r\n" + + "system sys\r\n" + + "end sys;\r\n" + + "\r\n" + + "system implementation sys.impl\r\n" + + " subcomponents\r\n" + + " this_sensor: device TestSensor;\r\n" + + " this_other_sensor: device TestSensor;\r\n" + + " connections\r\n" + + " sensor_conn: port this_sensor.data_out -> this_other_sensor.data_in;\r\n" + + " annex agree{**\r\n" + + " connection sensor_conn: true;\r\n" + + " **};\r\n" + + "end sys.impl;\r\n" + + "\r\n" + + "device TestSensor\r\n" + + " features\r\n" + + " data_in: in event port;\r\n" + + " data_out: out event port;\r\n" + + "end TestSensor;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + for(Issue i : issueCollection.getIssues()) { + assertFalse(i.getSeverity()==Severity.ERROR); + } + } + + @Test + public void testConnectionStatementLabelNotConnectionError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + "\r\n" + + "system sys\r\n" + + "end sys;\r\n" + + "\r\n" + + "system implementation sys.impl\r\n" + + " subcomponents\r\n" + + " this_sensor: device TestSensor;\r\n" + + " this_other_sensor: device TestSensor;\r\n" + + " connections\r\n" + + " sensor_conn: port this_sensor.data_out -> this_other_sensor.data_in;\r\n" + + " annex agree{**\r\n" + + " connection this_sensor: true;\r\n" + + " **};\r\n" + + "end sys.impl;\r\n" + + "\r\n" + + "device TestSensor\r\n" + + " features\r\n" + + " data_in: in event port;\r\n" + + " data_out: out event port;\r\n" + + "end TestSensor;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues, "The connection label in the connection statement is not a connection")); + } + + @Test + public void testConnectionStatementTypeMustBeBoolTypeError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + "\r\n" + + "system sys\r\n" + + "end sys;\r\n" + + "\r\n" + + "system implementation sys.impl\r\n" + + " subcomponents\r\n" + + " this_sensor: device TestSensor;\r\n" + + " this_other_sensor: device TestSensor;\r\n" + + " connections\r\n" + + " sensor_conn: port this_sensor.data_out -> this_other_sensor.data_in;\r\n" + + " annex agree{**\r\n" + + " connection sensor_conn: 1.0;\r\n" + + " **};\r\n" + + "end sys.impl;\r\n" + + "\r\n" + + "device TestSensor\r\n" + + " features\r\n" + + " data_in: in event port;\r\n" + + " data_out: out event port;\r\n" + + "end TestSensor;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues, "The expression for the connection statement is of type 'real' but must be of type 'bool'")); + } + + @Test + public void testConnectionStatementAllowedOnlyInComponentImplError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + "\r\n" + + "system sys\r\n" + + " annex agree{**\r\n" + + " connection test: true;\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "system implementation sys.impl\r\n" + + "end sys.impl;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues, "Connection statements are allowed only in component implementations.")); + } + + @Test + public void testConnectionStatementDepreciatedWarning() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + "\r\n" + + "system sys\r\n" + + "end sys;\r\n" + + "\r\n" + + "system implementation sys.impl\r\n" + + " subcomponents\r\n" + + " this_sensor: device TestSensor;\r\n" + + " this_other_sensor: device TestSensor;\r\n" + + " connections\r\n" + + " sensor_conn: port this_sensor.data_out -> this_other_sensor.data_in;\r\n" + + " annex agree{**\r\n" + + " connection sensor_conn: true;\r\n" + + " **};\r\n" + + "end sys.impl;\r\n" + + "\r\n" + + "device TestSensor\r\n" + + " features\r\n" + + " data_in: in event port;\r\n" + + " data_out: out event port;\r\n" + + "end TestSensor;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getWarning(issues, "Connection statements are deprecated and will be removed in a future version of AGREE.")); + } + + @Test + public void testOrderStatementNoErrors() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + "\r\n" + + "system sys\r\n" + + "end sys;\r\n" + + "\r\n" + + "system implementation sys.impl\r\n" + + " subcomponents\r\n" + + " this_sensor: device TestSensor;\r\n" + + " this_other_sensor: device TestSensor;\r\n" + + " annex agree{**\r\n" + + " ordering : this_sensor, this_other_sensor;\r\n" + + " **};\r\n" + + "end sys.impl;\r\n" + + "\r\n" + + "device TestSensor\r\n" + + "end TestSensor;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + assertTrue(issueCollection.getIssues().isEmpty()); + } + + @Test + public void testOrderStatementNotSubcomponentError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + "\r\n" + + "system sys\r\n" + + " features\r\n" + + " data_in : in event port;\r\n" + + "end sys;\r\n" + + "\r\n" + + "system implementation sys.impl\r\n" + + " subcomponents\r\n" + + " this_sensor: device TestSensor;\r\n" + + " this_other_sensor: device TestSensor;\r\n" + + " annex agree{**\r\n" + + " ordering : this_sensor, this_other_sensor, data_in;\r\n" + + " **};\r\n" + + "end sys.impl;\r\n" + + "\r\n" + + "device TestSensor\r\n" + + "end TestSensor;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues, "Element 'data_in' is not a subcomponent of 'sys.impl'")); + } + + @Test + public void testOrderStatementSubcomponentsNotPresentError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + "\r\n" + + "system sys\r\n" + + " features\r\n" + + " data_in : in event port;\r\n" + + "end sys;\r\n" + + "\r\n" + + "system implementation sys.impl\r\n" + + " subcomponents\r\n" + + " this_sensor: device TestSensor;\r\n" + + " this_other_sensor: device TestSensor;\r\n" + + " annex agree{**\r\n" + + " ordering : this_sensor;\r\n" + + " **};\r\n" + + "end sys.impl;\r\n" + + "\r\n" + + "device TestSensor\r\n" + + "end TestSensor;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues, "The following subcomponents are not present in the ordering: this_other_sensor")); + } + + @Test + public void testOrderStatementAppearOnlyInComponentImplError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + "\r\n" + + "system sys\r\n" + + " features\r\n" + + " data_in : in event port;\r\n" + + " annex agree{**\r\n" + + " ordering : data_in;\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues, "Ordering statements can appear only in component implementations")); + } + + @Test + public void testAssignStatementNoErrors() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + " with Base_Types;\r\n" + + "\r\n" + + "system sys\r\n" + + " features\r\n" + + " data_out : out data port Base_Types::Float;\r\n" + + "end sys;\r\n" + + "\r\n" + + "system implementation sys.impl\r\n" + + " annex agree{**\r\n" + + " assign data_out = 5.0;\r\n" + + " **};\r\n" + + "end sys.impl;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + assertTrue(issueCollection.getIssues().isEmpty()); + } + + @Test + public void testAssignStatementAllowedOnlyInComponentImplError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + " with Base_Types;\r\n" + + "\r\n" + + "system sys\r\n" + + " features\r\n" + + " data_out : out data port Base_Types::Float;\r\n" + + " annex agree{**\r\n" + + " assign data_out = 5.0;\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues, "Assignment statements are allowed only in component implementations")); + } + + @Test + public void testAssignStatementInputVariablesError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + " with Base_Types;\r\n" + + "\r\n" + + "system sys\r\n" + + " features\r\n" + + " data_out : out data port Base_Types::Float;\r\n" + + " annex agree{**\r\n" + + " agree_input a: real;\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "system implementation sys.impl\r\n" + + " annex agree{**\r\n" + + " assign a = 5.0;\r\n" + + " **};\r\n" + + "end sys.impl;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues, "Assignment to agree_input variables is illegal.")); + } + + @Test + public void testAssignStatementLHSMustBeEqOrOutputPortError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + " with Base_Types;\r\n" + + "\r\n" + + "system sys\r\n" + + " features\r\n" + + " data_out : out data port Base_Types::Float;\r\n" + + "end sys;\r\n" + + "\r\n" + + "system implementation sys.impl\r\n" + + " annex agree{**\r\n" + + " property test = true;\r\n" + + " assign test = false;\r\n" + + " **};\r\n" + + "end sys.impl;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues,"LHS of assignment must be an AGREE 'eq' variable or an output port of this component")); + } + + @Test + public void testAssignStatementTypeMismatchError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + " with Base_Types;\r\n" + + "\r\n" + + "system sys\r\n" + + " features\r\n" + + " data_out : out data port Base_Types::Float;\r\n" + + "end sys;\r\n" + + "\r\n" + + "system implementation sys.impl\r\n" + + " annex agree{**\r\n" + + " assign data_out = 1;\r\n" + + " **};\r\n" + + "end sys.impl;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues, "The left hand side of the assignment statement is of type 'real' but the right hand side is of type 'int'")); + } + + @Test + public void testAssignStatementMultipleAssignmentsError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + " with Base_Types;\r\n" + + "\r\n" + + "system sys\r\n" + + " features\r\n" + + " data_out : out data port Base_Types::Float;\r\n" + + "end sys;\r\n" + + "\r\n" + + "system implementation sys.impl\r\n" + + " annex agree{**\r\n" + + " assign data_out = 1.0;\r\n" + + " assign data_out = 2.0;\r\n" + + " **};\r\n" + + "end sys.impl;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues,"Multiple assignments to variable 'data_out'")); + } + + @Test + public void testAssignStatementMultipleEqAssignmentsError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + "\r\n" + + "system sys\r\n" + + "end sys;\r\n" + + "\r\n" + + "system implementation sys.impl\r\n" + + " annex agree{**\r\n" + + " eq test : bool = true;\r\n" + + " assign test = true;\r\n" + + " **};\r\n" + + "end sys.impl;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues,"Multiple assignments to variable 'test'")); + } + + @Test + public void testArgTypeRangeMustBeOfTypeIntOrRealError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + " \r\n" + + "system sys\r\n" + + "end sys;\r\n" + + "\r\n" + + "system implementation sys.impl\r\n" + + " annex agree{**\r\n" + + " eq test : bool[0,1];\r\n" + + " **};\r\n" + + "end sys.impl;\r\n" + + "\r\n" + + "end TestPackage;\r\n"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues,"Ranged variables must be of type 'int' or of type 'real'")); + } + + @Test + public void testArgTypeContainsRealIntervalError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + " \r\n" + + "system sys\r\n" + + "end sys;\r\n" + + "\r\n" + + "system implementation sys.impl\r\n" + + " annex agree{**\r\n" + + " eq test : int[0.0, 10];\r\n" + + " **};\r\n" + + "end sys.impl;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues,"Ranged variable of type 'int' contains a 'real' value in its interval")); + } + + @Test + public void testArgTypeContainsIntIntervalError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + " \r\n" + + "system sys\r\n" + + "end sys;\r\n" + + "\r\n" + + "system implementation sys.impl\r\n" + + " annex agree{**\r\n" + + " eq test : real[0, 10.0];\r\n" + + " **};\r\n" + + "end sys.impl;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues,"Ranged variable of type 'real' contains an 'int' value in its interval")); + } + + @Test + public void testArgTypeLowValueGreaterThanHighValueError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + " \r\n" + + "system sys\r\n" + + "end sys;\r\n" + + "\r\n" + + "system implementation sys.impl\r\n" + + " annex agree{**\r\n" + + " eq test : int[15, 10];\r\n" + + " **};\r\n" + + "end sys.impl;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues,"The low value of the interval is greater than or equal to the high end")); + } + + @Test + public void testArgTypeMustBeRecordArrayDataImplEnumDatatypeError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + " \r\n" + + "system sys\r\n" + + "end sys;\r\n" + + "\r\n" + + "system implementation sys.impl\r\n" + + " annex agree{**\r\n" + + " fun test_fn(x : real) : real = x;\r\n" + + " eq test : test_fn;\r\n" + + " **};\r\n" + + "end sys.impl;\r\n" + + "\r\n" + + "end TestPackage;\r\n"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues,"types must be record definition, array definition, data implementation, enumeration, or datatype")); + } + + @Test + public void testArgTypeDataImplWithoutSubcomponentMustExtendBaseTypeError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + " \r\n" + + "system sys\r\n" + + "end sys;\r\n" + + "\r\n" + + "system implementation sys.impl\r\n" + + " annex agree{**\r\n" + + " eq test : TestData.impl;\r\n" + + " **};\r\n" + + "end sys.impl;\r\n" + + "\r\n" + + "data TestData\r\n" + + "end TestData;\r\n" + + "\r\n" + + "data implementation TestData.impl\r\n" + + "end TestData.impl;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues,"Data Implementations with no subcomponents must extend" + + " a Base_Type that AGREE can reason about.")); + } + + @Ignore + public void testArgTypeDataImplWithSubcomponentCannotExtendBaseTypeError() throws Exception { + // TODO: Issue #128 + } + + @Test + public void testArgTypeAADLDatatypesMustExtendBaseTypeError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + " \r\n" + + "system sys\r\n" + + "end sys;\r\n" + + "\r\n" + + "system implementation sys.impl\r\n" + + " annex agree{**\r\n" + + " eq test : TestData;\r\n" + + " **};\r\n" + + "end sys.impl;\r\n" + + "\r\n" + + "data TestData\r\n" + + "end TestData;\r\n" + + "\r\n" + + "data implementation TestData.impl\r\n" + + "end TestData.impl;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues,"AADL Datatypes must extend a Base_Type that AGREE can reason about.")); + } + + @Test + public void testFloorCastNoErrors() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + "\r\n" + + "system sys\r\n" + + " features\r\n" + + " data_in : in event port;\r\n" + + " annex agree{**\r\n" + + " const test : int = floor(3.14);\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + assertTrue(issueCollection.getIssues().isEmpty()); + } + + @Test + public void testFloorCastNotAllowedInLinearizationBodyError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + "\r\n" + + "system sys\r\n" + + " annex agree{**\r\n" + + " linearization test (x : real) over [0.0 .. 10.0] within 0.1: floor(x);\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues,"'floor' expressions not allowed in linearization body expressions")); + } + + @Test + public void testFloorCastNamedThingMustBeAnExprWithTypeError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + "\r\n" + + "system sys\r\n" + + " features\r\n" + + " data_in : in event port;\r\n" + + " annex agree{**\r\n" + + " eq test : int = floor(data_in);\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues,"named thing must be an expression with a type")); + } + + @Test + public void testFloorCastMustBeOfTypeRealError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + "\r\n" + + "system sys\r\n" + + " features\r\n" + + " data_in : in event port;\r\n" + + " annex agree{**\r\n" + + " const test : int = floor(3);\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues,"Argument of floor cast is of type 'int' but must be of type 'real'")); + } + + @Test + public void testRealCastNoErrors() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + "\r\n" + + "system sys\r\n" + + " annex agree{**\r\n" + + " const test : real = real(3);\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + assertTrue(issueCollection.getIssues().isEmpty()); + } + + @Test + public void testRealCastNotAllowedInLinearizationBodyError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + "\r\n" + + "system sys\r\n" + + " annex agree{**\r\n" + + " linearization test (x : real) over [0.0 .. 10.0] within 0.1: real(x);\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues,"'real' expressions not allowed in linearization body expressions")); + } + + @Test + public void testRealCastNamedThingMustBeAnExprWithTypeError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + "\r\n" + + "system sys\r\n" + + " features\r\n" + + " data_in : in event port;\r\n" + + " annex agree{**\r\n" + + " eq test : real = real(data_in);\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues,"named thing must be an expression with a type")); + } + + @Test + public void testRealCastMustBeOfTypeIntError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + "\r\n" + + "system sys\r\n" + + " annex agree{**\r\n" + + " const test : real = real(3.0);\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues,"Argument of real cast is of type 'real' but must be of type 'int'")); + } + + @Test + public void testEventExprNoErrors() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + "\r\n" + + "system sys\r\n" + + " features\r\n" + + " data_in : in event port;\r\n" + + " annex agree{**\r\n" + + " property test = event(data_in);\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + assertTrue(issueCollection.getIssues().isEmpty()); + } + + @Test + public void testEventExprNotAllowedInLinearizationBodyError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + "\r\n" + + "system sys\r\n" + + " features\r\n" + + " data_in : in event port;\r\n" + + " annex agree{**\r\n" + + " linearization test (x : real) over [0.0 .. 10.0] within 0.1: event(data_in);\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues,"'event' expressions not allowed in linearization body expressions")); + } + + @Test + public void testEventExprArgMustBeEventOrEventDataPortError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + "\r\n" + + "system sys\r\n" + + " annex agree{**\r\n" + + " property test = event(1);\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues,"Argument of event expression must be an event port or event data port")); + } + + @Test + public void testLatchedExprNoErrors() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + " with Base_Types;\r\n" + + "\r\n" + + "system sys\r\n" + + " features\r\n" + + " data_in : in data port Base_Types::Boolean;\r\n" + + "end sys;\r\n" + + "\r\n" + + "system implementation sys.impl\r\n" + + " annex agree{**\r\n" + + " synchrony : latched;\r\n" + + " eq test : bool = latched(data_in);\r\n" + + " **};\r\n" + + "end sys.impl;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + assertTrue(issueCollection.getIssues().isEmpty()); + } + + @Test + public void testLatchedExprAppearOnlyInComponentImplThatContainLatchedSynchStatementError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + " with Base_Types;\r\n" + + "\r\n" + + "system sys\r\n" + + " features\r\n" + + " data_in : in data port Base_Types::Boolean;\r\n" + + " \r\n" + + "end sys;\r\n" + + "\r\n" + + "system implementation sys.impl\r\n" + + " annex agree{**\r\n" + + " eq test : bool = latched(data_in);\r\n" + + " **};\r\n" + + "end sys.impl;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues,"Latched expressions can appear only in component implementations " + + "that contain a latched synchrony statement")); + } + + @Test + public void testLatchedExprAppearOnlyInComponentImplError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + " with Base_Types;\r\n" + + "\r\n" + + "system sys\r\n" + + " features\r\n" + + " data_in : in data port Base_Types::Boolean;\r\n" + + " annex agree{**\r\n" + + " eq test : bool = latched(data_in);\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues,"Latched expressions can appear only in component implementations")); + } + + @Test + public void testLatchedExprValidOnlyForInputDataPortsOrEventExprError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + "\r\n" + + "system sys\r\n" + + " features\r\n" + + " data_in : in event port;\r\n" + + "end sys;\r\n" + + "\r\n" + + "system implementation sys.impl\r\n" + + " annex agree{**\r\n" + + " synchrony : latched;\r\n" + + " eq test : bool = latched(data_in);\r\n" + + " **};\r\n" + + "end sys.impl;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues,"Latched expressions are valid only for input data ports or event expressions over input event data ports")); + } + + @Test + public void testSynchStatementNoErrors() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + "\r\n" + + "system sys\r\n" + + "end sys;\r\n" + + "\r\n" + + "system implementation sys.impl\r\n" + + " annex agree{**\r\n" + + " synchrony : 1;\r\n" + + " **};\r\n" + + "end sys.impl;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + assertTrue(issueCollection.getIssues().isEmpty()); + } + + @Test + public void testSynchStatementAppearOnlyInComponentImplError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + "\r\n" + + "system sys\r\n" + + " annex agree{**\r\n" + + " synchrony : 1;\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues,"Synchrony statements can appear only in component implementations")); + } + + @Test + public void testSynchStatementSecondValueMustBeGreaterThanZeroError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + "\r\n" + + "system sys\r\n" + + "end sys;\r\n" + + "\r\n" + + "system implementation sys.impl\r\n" + + " annex agree{**\r\n" + + " synchrony : 2, 0;\r\n" + + " **};\r\n" + + "end sys.impl;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues,"The second value of a synchrony statment must be greater than zero")); + } + + @Test + public void testSynchStatementSecondValueMustBeLessThanFirstError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + "\r\n" + + "system sys\r\n" + + "end sys;\r\n" + + "\r\n" + + "system implementation sys.impl\r\n" + + " annex agree{**\r\n" + + " synchrony : 2, 3;\r\n" + + " **};\r\n" + + "end sys.impl;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues,"The second value of a synchrony argument must be less than the first")); + } + + @Test + public void testMNSynchStatementNoErrors() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + "\r\n" + + "system sys\r\n" + + "end sys;\r\n" + + "\r\n" + + "system implementation sys.impl\r\n" + + " subcomponents\r\n" + + " this_sensor : device TestSensor;\r\n" + + " this_other_sensor : device TestSensor;\r\n" + + " annex agree{**\r\n" + + " synchrony : this_sensor, this_other_sensor : 5, 3;\r\n" + + " **};\r\n" + + "end sys.impl;\r\n" + + "\r\n" + + "device TestSensor\r\n" + + "end TestSensor;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + assertTrue(issueCollection.getIssues().isEmpty()); + } + + @Test + public void testMNSynchStatementAppearOnlyInComponentImplError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + "\r\n" + + "system sys\r\n" + + " annex agree{**\r\n" + + " synchrony : this_sensor, this_other_sensor : 5, 3;\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "system implementation sys.impl\r\n" + + " subcomponents\r\n" + + " this_sensor : device TestSensor;\r\n" + + " this_other_sensor : device TestSensor;\r\n" + + "end sys.impl;\r\n" + + "\r\n" + + "device TestSensor\r\n" + + "end TestSensor;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues,"Synchrony statements can appear only in component implementations")); + } + + @Ignore + public void testMNSynchStatementMismatchedNumberSubcomponentsAndTimingRangesError() throws Exception { + //TODO + } + + @Test + public void testMNSynchStatementElement1IsNotSubcomponentError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + "\r\n" + + "system sys\r\n" + + " features\r\n" + + " data_in : in event port;\r\n" + + "end sys;\r\n" + + "\r\n" + + "system implementation sys.impl\r\n" + + " subcomponents\r\n" + + " this_sensor : device TestSensor;\r\n" + + " this_other_sensor : device TestSensor;\r\n" + + " annex agree{**\r\n" + + " synchrony : data_in, this_other_sensor : 5, 3;\r\n" + + " **};\r\n" + + "end sys.impl;\r\n" + + "\r\n" + + "device TestSensor\r\n" + + "end TestSensor;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues,"Element 'data_in' is not a subcomponent of 'sys.impl'")); + } + + @Test + public void testMNSynchStatementElement2IsNotSubcomponentError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + "\r\n" + + "system sys\r\n" + + " features\r\n" + + " data_in : in event port;\r\n" + + "end sys;\r\n" + + "\r\n" + + "system implementation sys.impl\r\n" + + " subcomponents\r\n" + + " this_sensor : device TestSensor;\r\n" + + " this_other_sensor : device TestSensor;\r\n" + + " annex agree{**\r\n" + + " synchrony : this_sensor, data_in : 5, 3;\r\n" + + " **};\r\n" + + "end sys.impl;\r\n" + + "\r\n" + + "device TestSensor\r\n" + + "end TestSensor;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues,"Element 'data_in' is not a subcomponent of 'sys.impl'")); + } + + @Test + public void testMNSynchStatementQuasiSynchValueMustBeGreaterThanZeroError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + "\r\n" + + "system sys\r\n" + + " features\r\n" + + " data_in : in event port;\r\n" + + "end sys;\r\n" + + "\r\n" + + "system implementation sys.impl\r\n" + + " subcomponents\r\n" + + " this_sensor : device TestSensor;\r\n" + + " this_other_sensor : device TestSensor;\r\n" + + " annex agree{**\r\n" + + " synchrony : this_sensor, this_other_sensor : 1, 0;\r\n" + + " **};\r\n" + + "end sys.impl;\r\n" + + "\r\n" + + "device TestSensor\r\n" + + "end TestSensor;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues,"Quasi-synchronous values must be greater than zero")); + } + + @Test + public void testMNSynchStatementLHSQuasiSynchValueMustBeGreaterThanRHSError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + "\r\n" + + "system sys\r\n" + + " features\r\n" + + " data_in : in event port;\r\n" + + "end sys;\r\n" + + "\r\n" + + "system implementation sys.impl\r\n" + + " subcomponents\r\n" + + " this_sensor : device TestSensor;\r\n" + + " this_other_sensor : device TestSensor;\r\n" + + " annex agree{**\r\n" + + " synchrony : this_sensor, this_other_sensor : 2, 3;\r\n" + + " **};\r\n" + + "end sys.impl;\r\n" + + "\r\n" + + "device TestSensor\r\n" + + "end TestSensor;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues,"Left hand side quasi-synchronous values must be greater than the right hand side")); + } + + @Test + public void testCalenStatementNoErrors() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + "\r\n" + + "system sys\r\n" + + "end sys;\r\n" + + "\r\n" + + "system implementation sys.impl\r\n" + + " subcomponents\r\n" + + " this_sensor : device TestSensor;\r\n" + + " annex agree{**\r\n" + + " calendar : this_sensor;\r\n" + + " **};\r\n" + + "end sys.impl;\r\n" + + "\r\n" + + "device TestSensor\r\n" + + "end TestSensor;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + assertTrue(issueCollection.getIssues().isEmpty()); + } + + @Test + public void testCalenStatementAppearOnlyInComponentImplError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + "\r\n" + + "system sys\r\n" + + " features\r\n" + + " data_in : in event port;\r\n" + + " annex agree{**\r\n" + + " calendar : data_in;\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues,"Calendar statements can appear only in component implementations")); + } + + @Test + public void testCalenStatementElementNotSubcomponentError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + "\r\n" + + "system sys\r\n" + + " features\r\n" + + " data_in : in event port;\r\n" + + "end sys;\r\n" + + "\r\n" + + "system implementation sys.impl\r\n" + + " annex agree{**\r\n" + + " calendar : data_in;\r\n" + + " **};\r\n" + + "end sys.impl;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues,"Element 'data_in' is not a subcomponent of 'sys.impl'")); + } + + @Test + public void testAsynchStatementNoErrors() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + "\r\n" + + "system sys\r\n" + + "end sys;\r\n" + + "\r\n" + + "system implementation sys.impl\r\n" + + " annex agree{**\r\n" + + " synchrony : asynchronous;\r\n" + + " **};\r\n" + + "end sys.impl;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + assertTrue(issueCollection.getIssues().isEmpty()); + } + + @Test + public void testAsynchStatementAppearOnlyInComponentImplError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + "\r\n" + + "system sys\r\n" + + " annex agree{**\r\n" + + " synchrony : asynchronous;\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues,"Synchrony statements can appear only in component implementations")); + } + + @Test + public void testLatchedStatementNoErrors() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + "\r\n" + + "system sys\r\n" + + "end sys;\r\n" + + "\r\n" + + "system implementation sys.impl\r\n" + + " annex agree{**\r\n" + + " synchrony : latched;\r\n" + + " **};\r\n" + + "end sys.impl;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + assertTrue(issueCollection.getIssues().isEmpty()); + } + + @Test + public void testLatchedStatementAppearOnlyInComponentImplError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + "\r\n" + + "system sys\r\n" + + " annex agree{**\r\n" + + " synchrony : latched;\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues,"Synchrony statements can appear only in component implementations")); + } + + @Ignore + public void testDuplicateIdInSpecNoErrors() throws Exception { + //TODO + } + + @Ignore + public void testDuplicateIdInSpecDuplicateIdError() throws Exception { + //TODO + } + + @Test + public void testAssumeStatementNoErrors() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + "\r\n" + + "system sys\r\n" + + " annex agree{**\r\n" + + " assume A1 \"SimpleTest\" : true;\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + assertTrue(issueCollection.getIssues().isEmpty()); + } + + @Test + public void testAssumeStatementAllowedOnlyInComponentTypesError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + "\r\n" + + "system sys\r\n" + + "end sys;\r\n" + + "\r\n" + + "system implementation sys.impl\r\n" + + " annex agree{**\r\n" + + " assume A1 \"SimpleTest\" : true;\r\n" + + " **};\r\n" + + "end sys.impl;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues,"Assume statements are allowed only in component types")); + } + + @Test + public void testAssumeStatementMustBeOfTypeBoolError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + "\r\n" + + "system sys\r\n" + + " annex agree{**\r\n" + + " assume A1 \"SimpleTest\" : 1;\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues,"Expression for assume statement is of type 'int' but must be of type 'bool'")); + } + + @Test + public void testAssumeStatementNamedInfoMessage() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + "\r\n" + + "system sys\r\n" + + " annex agree{**\r\n" + + " assume \"SimpleTest\" : true;\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getInfo(issues,"It is recommended that assume statements be named." + + " (Hint: an identifier may be placed between the \"assume\" keyword and the quoted description.)")); + } + + @Test + public void testInitialStatementNoErrors() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + "\r\n" + + "system sys\r\n" + + " annex agree{**\r\n" + + " initially : true;\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + assertTrue(issueCollection.getIssues().isEmpty()); + } + + @Test + public void testInitialStatementAllowedOnlyInComponentTypesError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + "\r\n" + + "system sys\r\n" + + "end sys;\r\n" + + "\r\n" + + "system implementation sys.impl\r\n" + + " annex agree{**\r\n" + + " initially : true;\r\n" + + " **};\r\n" + + "end sys.impl;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues,"Initial statements are allowed only in component types")); + } + + @Test + public void testInitialStatementMustBeOfTypeBoolError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + "\r\n" + + "system sys\r\n" + + " annex agree{**\r\n" + + " initially : 1;\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues,"Expression for 'initially' statement is of type 'int' but must be of type 'bool'")); + } + + @Test + public void testLiftContractNoErrors() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + "\r\n" + + "system sys\r\n" + + "end sys;\r\n" + + "\r\n" + + "system implementation sys.impl\r\n" + + " subcomponents\r\n" + + " this_sensor : device TestSensor;\r\n" + + " annex agree{**\r\n" + + " lift contract;\r\n" + + " **};\r\n" + + "end sys.impl;\r\n" + + "\r\n" + + "device TestSensor\r\n" + + "end TestSensor;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + assertTrue(issueCollection.getIssues().isEmpty()); + } + + @Test + public void testLiftContractNotAllowedInComponentImplWithAGREEAnnex() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + "\r\n" + + "system sys\r\n" + + " annex agree{**\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "system implementation sys.impl\r\n" + + " subcomponents\r\n" + + " this_sensor : device TestSensor;\r\n" + + " annex agree{**\r\n" + + " lift contract;\r\n" + + " **};\r\n" + + "end sys.impl;\r\n" + + "\r\n" + + "device TestSensor\r\n" + + "end TestSensor;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues,"'lift contract;' statement is not allowed in component implementation whose type has an AGREE annex.")); + } + + @Test + public void testLiftContractNotAllowedWithImplWithMoreThanOneSourceChildConnectionOutOfSameOutputError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + "\r\n" + + "system sys\r\n" + + "end sys;\r\n" + + "\r\n" + + "system implementation sys.impl\r\n" + + " subcomponents\r\n" + + " this_sensor : device TestSensor;\r\n" + + " connections\r\n" + + " sensor_conn : port this_sensor.data_out -> this_sensor.data_in;\r\n" + + " other_sensor_conn : port this_sensor.data_out -> this_sensor.more_data_in;\r\n" + + " annex agree{**\r\n" + + " lift contract;\r\n" + + " **};\r\n" + + "end sys.impl;\r\n" + + "\r\n" + + "device TestSensor\r\n" + + " features\r\n" + + " data_in : in data port;\r\n" + + " data_out : out data port;\r\n" + + " more_data_in : in data port;\r\n" + + "end TestSensor;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues,"'lift contract;' statement is not allowed in component implementation with more than one connection out of same output TestPackage::TestSensor.data_out.")); + } + + @Test + public void testLiftContractNotAllowedWithImplWithMoreThanOneSourceParentConnectionOutOfSameInputError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + "\r\n" + + "system sys\r\n" + + " features\r\n" + + " data_in : in data port;\r\n" + + "end sys;\r\n" + + "\r\n" + + "system implementation sys.impl\r\n" + + " subcomponents\r\n" + + " this_sensor : device TestSensor;\r\n" + + " connections\r\n" + + " sensor_conn : port data_in -> this_sensor.data_in;\r\n" + + " other_sensor_conn : port data_in -> this_sensor.more_data_in;\r\n" + + " annex agree{**\r\n" + + " lift contract;\r\n" + + " **};\r\n" + + "end sys.impl;\r\n" + + "\r\n" + + "device TestSensor\r\n" + + " features\r\n" + + " data_in : in data port;\r\n" + + " more_data_in : in data port;\r\n" + + "end TestSensor;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues,"'lift contract;' statement is not allowed in component implementation with more than one connection out of same input TestPackage::sys.data_in.")); + } + + @Test + public void testLiftContractNotAllowedWithImplWithMoreThanOneDestinationChildConnectionIntoSameInputError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + "\r\n" + + "system sys\r\n" + + "end sys;\r\n" + + "\r\n" + + "system implementation sys.impl\r\n" + + " subcomponents\r\n" + + " this_sensor : device TestSensor;\r\n" + + " connections\r\n" + + " sensor_conn : port this_sensor.data_out -> this_sensor.data_in;\r\n" + + " other_sensor_conn : port this_sensor.more_data_out -> this_sensor.data_in;\r\n" + + " annex agree{**\r\n" + + " lift contract;\r\n" + + " **};\r\n" + + "end sys.impl;\r\n" + + "\r\n" + + "device TestSensor\r\n" + + " features\r\n" + + " data_in : in data port;\r\n" + + " data_out : out data port;\r\n" + + " more_data_out : out data port;\r\n" + + "end TestSensor;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues,"'lift contract;' statement is not allowed in component implementation with more than one connection into same input TestPackage::TestSensor.data_in.")); + } + + @Test + public void testLiftContractNotAllowedWithImplWithMoreThanOneDestinationParentConnectionIntoSameOutputError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + "\r\n" + + "system sys\r\n" + + " features\r\n" + + " data_out : out data port;\r\n" + + "end sys;\r\n" + + "\r\n" + + "system implementation sys.impl\r\n" + + " subcomponents\r\n" + + " this_sensor : device TestSensor;\r\n" + + " connections\r\n" + + " sensor_conn : port this_sensor.data_out -> data_out;\r\n" + + " other_sensor_conn : port this_sensor.more_data_out -> data_out;\r\n" + + " annex agree{**\r\n" + + " lift contract;\r\n" + + " **};\r\n" + + "end sys.impl;\r\n" + + "\r\n" + + "device TestSensor\r\n" + + " features\r\n" + + " data_out : out data port;\r\n" + + " more_data_out : out data port;\r\n" + + "end TestSensor;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues,"'lift contract;' statement is not allowed in component implementation with more than one connection into same output TestPackage::sys.data_out.")); + } + + @Test + public void testLiftContractNotAllowedWithImplWithoutParentConnectionFromInputError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + "\r\n" + + "system sys\r\n" + + " features\r\n" + + " data_in : in event port;\r\n" + + "end sys;\r\n" + + "\r\n" + + "system implementation sys.impl\r\n" + + " subcomponents\r\n" + + " this_sensor : device TestSensor;\r\n" + + " annex agree{**\r\n" + + " lift contract;\r\n" + + " **};\r\n" + + "end sys.impl;\r\n" + + "\r\n" + + "device TestSensor\r\n" + + "end TestSensor;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues,"'lift contract;' statement is not allowed in component implementation without connection from input TestPackage::sys.data_in.")); + } + + @Test + public void testLiftContractNotAllowedWithImplWithoutParentConnectionFromOutputError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + "\r\n" + + "system sys\r\n" + + " features\r\n" + + " data_out : out event port;\r\n" + + "end sys;\r\n" + + "\r\n" + + "system implementation sys.impl\r\n" + + " subcomponents\r\n" + + " this_sensor : device TestSensor;\r\n" + + " annex agree{**\r\n" + + " lift contract;\r\n" + + " **};\r\n" + + "end sys.impl;\r\n" + + "\r\n" + + "device TestSensor\r\n" + + "end TestSensor;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues,"'lift contract;' statement is not allowed in component implementation without connection to output TestPackage::sys.data_out.")); + } + + @Test + public void testLiftContractNotAllowedWithImplWithoutChildConnectionFromInputError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + "\r\n" + + "system sys\r\n" + + "end sys;\r\n" + + "\r\n" + + "system implementation sys.impl\r\n" + + " subcomponents\r\n" + + " this_sensor : device TestSensor;\r\n" + + " annex agree{**\r\n" + + " lift contract;\r\n" + + " **};\r\n" + + "end sys.impl;\r\n" + + "\r\n" + + "device TestSensor\r\n" + + " features\r\n" + + " data_in : in data port;\r\n" + + "end TestSensor;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues,"'lift contract;' statement is not allowed in component implementation without connection into TestPackage::TestSensor.data_in.")); + } + + @Test + public void testLiftContractNotAllowedWithImplWithoutChildConnectionFromOutputError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + "\r\n" + + "system sys\r\n" + + "end sys;\r\n" + + "\r\n" + + "system implementation sys.impl\r\n" + + " subcomponents\r\n" + + " this_sensor : device TestSensor;\r\n" + + " annex agree{**\r\n" + + " lift contract;\r\n" + + " **};\r\n" + + "end sys.impl;\r\n" + + "\r\n" + + "device TestSensor\r\n" + + " features\r\n" + + " data_out : out data port;\r\n" + + "end TestSensor;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues,"'lift contract;' statement is not allowed in component implementation without connection out of TestPackage::TestSensor.data_out.")); + } + + @Test + public void testLiftContractNotAllowedInCompImplWithoutExactlyOneSubcomponentError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + "\r\n" + + "system sys\r\n" + + "end sys;\r\n" + + "\r\n" + + "system implementation sys.impl\r\n" + + " subcomponents\r\n" + + " this_sensor : device TestSensor;\r\n" + + " this_other_sensor : device TestSensor;\r\n" + + " annex agree{**\r\n" + + " lift contract;\r\n" + + " **};\r\n" + + "end sys.impl;\r\n" + + "\r\n" + + "device TestSensor\r\n" + + "end TestSensor;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues,"'lift contract;' statement is not allowed in component implementation without exactly one subcomponent.")); + } + + @Test + public void testLiftContractNotAllowedInComponentInterfaceError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + "\r\n" + + "system sys\r\n" + + " annex agree{**\r\n" + + " lift contract;\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "system implementation sys.impl\r\n" + + " subcomponents\r\n" + + " this_sensor : device TestSensor;\r\n" + + "end sys.impl;\r\n" + + "\r\n" + + "device TestSensor\r\n" + + "end TestSensor;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues,"'lift contract;' statement is not allowed in component interface.")); + } + + @Test + public void testAssertStatementNoErrors() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + "\r\n" + + "system sys\r\n" + + "end sys;\r\n" + + "\r\n" + + "system implementation sys.impl\r\n" + + " annex agree{**\r\n" + + " assert AS1 \"SimpleTest\" : true;\r\n" + + " **};\r\n" + + "end sys.impl;\r\n" + + "\r\n" + + "device TestSensor\r\n" + + "end TestSensor;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + for(Issue i : issueCollection.getIssues()) { + assertFalse(i.getSeverity()==Severity.ERROR); + } + } + + @Test + public void testAssertStatementAllowedOnlyInComponentImplError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + "\r\n" + + "system sys\r\n" + + " annex agree{**\r\n" + + " assert AS1 \"SimpleTest\" : true;\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "system implementation sys.impl\r\n" + + "end sys.impl;\r\n" + + "\r\n" + + "device TestSensor\r\n" + + "end TestSensor;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues,"Assert statements are allowed only in component implementations.")); + } + + @Test + public void testAssertStatementMustBeOfTypeBoolError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + "\r\n" + + "system sys\r\n" + + "end sys;\r\n" + + "\r\n" + + "system implementation sys.impl\r\n" + + " annex agree{**\r\n" + + " assert AS1 \"SimpleTest\" : 1;\r\n" + + " **};\r\n" + + "end sys.impl;\r\n" + + "\r\n" + + "device TestSensor\r\n" + + "end TestSensor;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues,"Expression for assert statement is of type 'int' but must be of type 'bool'")); + } + + @Test + public void testAssertStatementDiscourageAssertWarning() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + "\r\n" + + "system sys\r\n" + + "end sys;\r\n" + + "\r\n" + + "system implementation sys.impl\r\n" + + " annex agree{**\r\n" + + " assert AS1 \"SimpleTest\" : true;\r\n" + + " **};\r\n" + + "end sys.impl;\r\n" + + "\r\n" + + "device TestSensor\r\n" + + "end TestSensor;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getWarning(issues,"We highly discourage the use of assert statements. " + + "They can easily lead to inconsistent or unrealizable systems. " + + "Note that our realizability check does not verify that component " + + "assertions are realizable. It is likely that you can specify the " + + "behavior you want by changing the subcomponent contracts or by using assignment statements.")); + } + + @Test + public void testAssertStatementNamedInfoMessage() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + "\r\n" + + "system sys\r\n" + + "end sys;\r\n" + + "\r\n" + + "system implementation sys.impl\r\n" + + " annex agree{**\r\n" + + " assert \"SimpleTest\" : true;\r\n" + + " **};\r\n" + + "end sys.impl;\r\n" + + "\r\n" + + "device TestSensor\r\n" + + "end TestSensor;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getInfo(issues, "It is recommended that assert statements be named." + + " (Hint: an identifier may be placed between the \"assert\" keyword and the quoted description.)")); + } + + @Test + public void testAADLEnumeratorNoErrors() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + " with Data_Model;\r\n" + + " \r\n" + + " data Primary_Color\r\n" + + " properties\r\n" + + " Data_Model::Data_Representation => Enum;\r\n" + + " Data_Model::Enumerators => (\"Red\", \"Green\", \"Blue\");\r\n" + + " end Primary_Color;\r\n" + + " \r\n" + + " system sys\r\n" + + " annex agree {**\r\n" + + " eq test : Primary_Color = enum(Primary_Color, Red);\r\n" + + " **};\r\n" + + " end sys;\r\n" + + " \r\n" + + " end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + assertTrue(issueCollection.getIssues().isEmpty()); + } + + @Test + public void testAADLEnumeratorMustReferToDataTypeEnumError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + " \r\n" + + "system sys\r\n" + + " annex agree {**\r\n" + + " type test_struct = struct{a : int};\r\n" + + " eq test : test_struct = enum(test_struct, a);\r\n" + + " **};\r\n" + + "end sys;\r\n" + + " \r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues, "AADL Enumerations must refer to a Data Type with \"Enum\" data representation " + + "property and have an \"Enumerators\' property value list.")); + } + + @Test + public void testAADLEnumeratorDoesNotHaveEnumValueError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + " with Data_Model;\r\n" + + " \r\n" + + "data Primary_Color\r\n" + + " properties\r\n" + + " Data_Model::Data_Representation => Enum;\r\n" + + " Data_Model::Enumerators => (\"Red\", \"Green\", \"Blue\");\r\n" + + "end Primary_Color;\r\n" + + "\r\n" + + "system sys\r\n" + + " annex agree {**\r\n" + + " eq test : Primary_Color = enum(Primary_Color, Orange);\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues, "AADL Enumeration TestPackage::Primary_Color does not have an enumeration value Orange")); + } + + @Test + public void testGuaranteeStatementNoErrors() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + " \r\n" + + "system sys\r\n" + + " annex agree {**\r\n" + + " guarantee G1 \"SimpleTest\" : true;\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + assertTrue(issueCollection.getIssues().isEmpty()); + } + + @Test + public void testGuaranteeStatementAllowedOnlyInComponentTypesError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + " \r\n" + + "system sys\r\n" + + "end sys;\r\n" + + "\r\n" + + "system implementation sys.impl\r\n" + + " annex agree {**\r\n" + + " guarantee G1 \"SimpleTest\" : true;\r\n" + + " **};\r\n" + + "end sys.impl;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues, "Guarantee statements are allowed only in component types")); + } + + @Test + public void testGuaranteeStatementMustBeOfTypeBoolError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + " \r\n" + + "system sys\r\n" + + " annex agree {**\r\n" + + " guarantee G1 \"SimpleTest\" : 1;\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues, "Expression for guarantee statement is of type 'int' but must be of type 'bool'")); + } + + @Test + public void testGuaranteeStatementNamedInfoMessage() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + " \r\n" + + "system sys\r\n" + + " annex agree {**\r\n" + + " guarantee \"SimpleTest\" : true;\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getInfo(issues, "It is recommended that guarantee statements be named." + + " (Hint: an identifier may be placed between the \"guarantee\" keyword and the quoted description.)")); + } + + @Test + public void testReachableStatementNoErrors() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + " \r\n" + + "system sys\r\n" + + "end sys;\r\n" + + "\r\n" + + "system implementation sys.impl\r\n" + + " annex agree {**\r\n" + + " reachable R1 \"SimpleTest\" : true;\r\n" + + " **};\r\n" + + "end sys.impl;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + assertTrue(issueCollection.getIssues().isEmpty()); + } + + @Test + public void testReachableStatementAllowedOnlyInComponentImplError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + " \r\n" + + "system sys\r\n" + + " annex agree {**\r\n" + + " reachable R1 \"SimpleTest\" : true;\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues, "Reachable statements are allowed only in component implementations")); + } + + @Test + public void testReachableStatementMustBeOfTypeBoolError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + " \r\n" + + "system sys\r\n" + + "end sys;\r\n" + + "\r\n" + + "system implementation sys.impl\r\n" + + " annex agree {**\r\n" + + " reachable R1 \"SimpleTest\" : 1;\r\n" + + " **};\r\n" + + "end sys.impl;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues, "Expression for reachable statement is of type 'int' but must be of type 'bool'")); + } + + @Test + public void testReachableStatementNamedInfoMessage() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + " \r\n" + + "system sys\r\n" + + "end sys;\r\n" + + "\r\n" + + "system implementation sys.impl\r\n" + + " annex agree {**\r\n" + + " reachable \"SimpleTest\" : true;\r\n" + + " **};\r\n" + + "end sys.impl;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getInfo(issues, "It is recommended that reachable statements be named." + + " (Hint: an identifier may be placed between the \"reachable\" keyword and the quoted description.)")); + } + + @Test + public void testPeriodicStatementNoErrors() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + " \r\n" + + "system sys\r\n" + + " annex agree {**\r\n" + + " eq test_cond : bool = true;\r\n" + + " assume test \"SimpleTest\": condition test_cond occurs each 3.0 with jitter 1.0;\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + assertTrue(issueCollection.getIssues().isEmpty()); + } + + @Test + public void testPeriodicStatementCanContainOnlyIdentifiersError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + " \r\n" + + "system sys\r\n" + + " annex agree {**\r\n" + + " assume test \"SimpleTest\": condition true occurs each 3.0 with jitter 1.0;\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues, "Patterns can contain only identifiers (not general expressions)")); + } + + @Test + public void testPeriodicStatementMustBeOfTypeBoolError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + " \r\n" + + "system sys\r\n" + + " annex agree {**\r\n" + + " eq test_cond : int = 1;\r\n" + + " assume test \"SimpleTest\": condition test_cond occurs each 3.0 with jitter 1.0;\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues, "Expression is of type 'int' but must be of type 'bool'")); + } + + @Test + public void testPeriodicStatementJitterMustBeRealError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + " \r\n" + + "system sys\r\n" + + " annex agree {**\r\n" + + " eq test_cond : bool = true;\r\n" + + " assume test \"SimpleTest\": condition test_cond occurs each 3 with jitter 1;\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues, "The specified jitter must be a positive real literal")); + } + + @Test + public void testPeriodicStatementPeriodMustBeRealError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + " \r\n" + + "system sys\r\n" + + " annex agree {**\r\n" + + " eq test_cond : bool = true;\r\n" + + " assume test \"SimpleTest\": condition test_cond occurs each 3 with jitter 1.0;\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues, "The specified period must be a positive real literal")); + } + + @Test + public void testSporadicStatementNoErrors() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + " \r\n" + + "system sys\r\n" + + " annex agree {**\r\n" + + " eq test_cond : bool = true;\r\n" + + " assume test \"SimpleTest\": condition test_cond occurs sporadic with IAT 5.0 with jitter 1.0;\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + assertTrue(issueCollection.getIssues().isEmpty()); + } + + @Test + public void testSporadicStatementCanContainOnlyIdentifiersError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + " \r\n" + + "system sys\r\n" + + " annex agree {**\r\n" + + " assume test \"SimpleTest\": condition true occurs sporadic with IAT 5.0 with jitter 1.0;\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues, "Patterns can contain only identifiers (not general expressions)")); + } + + @Test + public void testSporadicStatementMustBeOfTypeBoolError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + " \r\n" + + "system sys\r\n" + + " annex agree {**\r\n" + + " eq test_cond : int = 1;\r\n" + + " assume test \"SimpleTest\": condition 1 occurs sporadic with IAT 5.0 with jitter 1.0;\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues,"Expression is of type 'int' but must be of type 'bool'")); + } + + @Test + public void testSporadicStatementJitterMustBeRealError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + " \r\n" + + "system sys\r\n" + + " annex agree {**\r\n" + + " eq test_cond : bool = true;\r\n" + + " assume test \"SimpleTest\": condition test_cond occurs sporadic with IAT 5.0 with jitter 1;\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues,"The specified jitter must be a positive real literal")); + } + + @Test + public void testSporadicStatementInterarrivalMustBeRealError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + " \r\n" + + "system sys\r\n" + + " annex agree {**\r\n" + + " eq test_cond : bool = true;\r\n" + + " assume test \"SimpleTest\": condition test_cond occurs sporadic with IAT 5 with jitter 1.0;\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues,"The specified interarrival time must be a positive real literal")); + } + + @Test + public void testWhenHoldsStatementNoErrors() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + " \r\n" + + "system sys\r\n" + + " annex agree {**\r\n" + + " eq test_cond : bool = true;\r\n" + + " eq test_event : bool = true;\r\n" + + " assume test \"SimpleTest\": when test_cond holds during [0.0, 3.0] test_event exclusively occurs during [3.0, 5.0];\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + assertTrue(issueCollection.getIssues().isEmpty()); + } + + @Test + public void testWhenHoldsStatementLowerBoundMustBeZeroError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + " \r\n" + + "system sys\r\n" + + " annex agree {**\r\n" + + " eq test_cond : bool = true;\r\n" + + " eq test_event : bool = true;\r\n" + + " assume test \"SimpleTest\": when test_cond holds during [0.5, 3.0] test_event exclusively occurs during [3.0, 5.0];\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues,"The lower bound of this interval must be zero")); + } + + @Test + public void testWhenHoldsStatementMustHaveCauseIntervalError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + " \r\n" + + "system sys\r\n" + + " annex agree {**\r\n" + + " eq test_cond : bool = true;\r\n" + + " eq test_event : bool = true;\r\n" + + " assume test \"SimpleTest\": when test_cond holds during test_event exclusively occurs during [3.0, 5.0];\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues,"Statement must have a cause interval")); + } + + @Test + public void testWhenHoldsStatementConditionMustBeOfTypeBoolError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + " \r\n" + + "system sys\r\n" + + " annex agree {**\r\n" + + " eq test_cond : int = 1;\r\n" + + " eq test_event : bool = true;\r\n" + + " assume test \"SimpleTest\": when test_cond holds during [0.0, 3.0] test_event exclusively occurs during [3.0, 5.0];\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues,"The condition of a when statement is of type 'int' but must be of type 'bool'")); + } + + @Test + public void testWhenHoldsStatementEffectMustBeOfTypeBoolError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + " \r\n" + + "system sys\r\n" + + " annex agree {**\r\n" + + " eq test_cond : bool = true;\r\n" + + " eq test_event : real = 1.0;\r\n" + + " assume test \"SimpleTest\": when test_cond holds during [0.0, 3.0] test_event exclusively occurs during [3.0, 5.0];\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues,"The effect of a when statement is of type 'real' but must be of type 'bool'")); + } + + @Test + public void testWhenOccursStatementNoErrors() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + " \r\n" + + "system sys\r\n" + + " annex agree {**\r\n" + + " eq test_cond : bool = true;\r\n" + + " eq test_event : bool = true;\r\n" + + " assume test \"SimpleTest\": when test_cond occurs 3 times during [0.0, 5.0] exclusively raises test_event;\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + assertTrue(issueCollection.getIssues().isEmpty()); + } + + @Test + public void testWhenOccursStatementConditionMustBeOfTypeBoolError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + " \r\n" + + "system sys\r\n" + + " annex agree {**\r\n" + + " eq test_cond : real = 0.0;\r\n" + + " eq test_event : bool = true;\r\n" + + " assume test \"SimpleTest\": when test_cond occurs 3 times during [0.0, 5.0] exclusively raises test_event;\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues,"The condition of the 'when' statement is of type 'real' but must be of type 'bool'")); + } + + @Test + public void testWhenOccursStatementEffectMustBeOfTypeBoolError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + " \r\n" + + "system sys\r\n" + + " annex agree {**\r\n" + + " eq test_cond : bool = true;\r\n" + + " eq test_event : int = 1;\r\n" + + " assume test \"SimpleTest\": when test_cond occurs 3 times during [0.0, 5.0] exclusively raises test_event;\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues,"The effect of the 'when' statement is of type 'int' but must be of type 'bool'")); + } + + @Test + public void testWhenOccursStatementTimesMustBeOfTypeIntError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + " \r\n" + + "system sys\r\n" + + " annex agree {**\r\n" + + " eq test_cond : bool = true;\r\n" + + " eq test_event : bool = true;\r\n" + + " assume test \"SimpleTest\": when test_cond occurs 3.0 times during [0.0, 5.0] exclusively raises test_event;\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues,"The 'times' of the 'when' statement is of type 'real' but must be of type 'int'")); + } + + @Test + public void testWheneverOccursStatementNoErrors() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + " \r\n" + + "system sys\r\n" + + " annex agree {**\r\n" + + " eq test_cond : bool = true;\r\n" + + " eq test_effect : bool = true;\r\n" + + " assume test \"SimpleTest\": whenever test_cond occurs test_effect exclusively occurs during [0.0, 1.0];\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + assertTrue(issueCollection.getIssues().isEmpty()); + } + + @Test + public void testWheneverOccursStatementCauseMustBeOfTypeBoolError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + " \r\n" + + "system sys\r\n" + + " annex agree {**\r\n" + + " eq test_cond : int = 1;\r\n" + + " eq test_effect : bool = true;\r\n" + + " assume test \"SimpleTest\": whenever test_cond occurs test_effect exclusively occurs during [0.0, 1.0];\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues,"The cause of the 'whenever' statement is of type 'int' but must be of type 'bool'")); + } + + @Test + public void testWheneverOccursStatementEffectMustBeOfTypeBoolError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + " \r\n" + + "system sys\r\n" + + " annex agree {**\r\n" + + " eq test_cond : bool = true;\r\n" + + " eq test_effect : int = 0;\r\n" + + " assume test \"SimpleTest\": whenever test_cond occurs test_effect exclusively occurs during [0.0, 1.0];\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues,"The effect of the 'whenever' statement is of type 'int' but must be of type 'bool'")); + } + + @Test + public void testWheneverBecomesTrueStatementNoErrors() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + " \r\n" + + "system sys\r\n" + + " annex agree {**\r\n" + + " eq test_cond : bool = true;\r\n" + + " eq test_effect : bool = true;\r\n" + + " assume test \"SimpleTest\": whenever test_cond becomes true test_effect exclusively occurs during (0.0, 1.0];\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + assertTrue(issueCollection.getIssues().isEmpty()); + } + + @Test + public void testWheneverBecomesTrueStatementCauseMustBeOfTypeBoolError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + " \r\n" + + "system sys\r\n" + + " annex agree {**\r\n" + + " eq test_cond : int = 0;\r\n" + + " eq test_effect : bool = true;\r\n" + + " assume test \"SimpleTest\": whenever test_cond becomes true test_effect exclusively occurs during (0.0, 1.0];\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues,"The cause of the 'whenever' statement is of type 'int' but must be of type 'bool'")); + } + + @Test + public void testWheneverBecomesTrueStatementEffectMustBeOfTypeBoolError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + " \r\n" + + "system sys\r\n" + + " annex agree {**\r\n" + + " eq test_cond : bool = true;\r\n" + + " eq test_effect : int = 1;\r\n" + + " assume test \"SimpleTest\": whenever test_cond becomes true test_effect exclusively occurs during (0.0, 1.0];\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues,"The effect of the 'whenever' statement is of type 'int' but must be of type 'bool'")); + } + + @Test + public void testWheneverHoldsStatementNoErrors() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + " \r\n" + + "system sys\r\n" + + " annex agree {**\r\n" + + " eq test_cond : bool = true;\r\n" + + " eq test_effect : bool = true;\r\n" + + " assume test \"SimpleTest\": whenever test_cond occurs test_effect exclusively holds during [0.0, 1.0);\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + assertTrue(issueCollection.getIssues().isEmpty()); + } + + @Test + public void testWheneverHoldsStatementCauseMustBeOfTypeBoolError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + " \r\n" + + "system sys\r\n" + + " annex agree {**\r\n" + + " eq test_cond : int = 0;\r\n" + + " eq test_effect : bool = true;\r\n" + + " assume test \"SimpleTest\": whenever test_cond occurs test_effect exclusively holds during [0.0, 1.0);\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues, "The cause of the 'whenever' statement is of type 'int' but must be of type 'bool'")); + } + + @Test + public void testWheneverHoldsStatementEffectMustBeOfTypeBoolError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + " \r\n" + + "system sys\r\n" + + " annex agree {**\r\n" + + " eq test_cond : bool = true;\r\n" + + " eq test_effect : real = 0.0;\r\n" + + " assume test \"SimpleTest\": whenever test_cond occurs test_effect exclusively holds during [0.0, 1.0);\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues, "The effect of the 'whenever' statement is of type 'real' but must be of type 'bool'")); + } + + @Test + public void testWheneverImpliesStatementNoErrors() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + " \r\n" + + "system sys\r\n" + + " annex agree {**\r\n" + + " eq test_cond : bool = true;\r\n" + + " eq test_lhs : bool = true;\r\n" + + " eq test_rhs : bool = true;\r\n" + + " assume test \"SimpleTest\": whenever test_cond occurs test_lhs implies test_rhs exclusively during (0.0, 1.0);\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + assertTrue(issueCollection.getIssues().isEmpty()); + } + + @Test + public void testWheneverImpliesStatementCauseMustBeOfTypeBoolError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + " \r\n" + + "system sys\r\n" + + " annex agree {**\r\n" + + " eq test_cond : int = 1;\r\n" + + " eq test_lhs : bool = true;\r\n" + + " eq test_rhs : bool = true;\r\n" + + " assume test \"SimpleTest\": whenever test_cond occurs test_lhs implies test_rhs exclusively during (0.0, 1.0);\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues, "The cause of the 'whenever' statement is of type 'int' but must be of type 'bool'")); + } + + @Test + public void testWheneverImpliesStatementLHSMustBeOfTypeBoolError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + " \r\n" + + "system sys\r\n" + + " annex agree {**\r\n" + + " eq test_cond : bool = true;\r\n" + + " eq test_lhs : int = 0;\r\n" + + " eq test_rhs : bool = true;\r\n" + + " assume test \"SimpleTest\": whenever test_cond occurs test_lhs implies test_rhs exclusively during (0.0, 1.0);\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues, "The left hand side of the 'implies' of the 'whenever' statement is of type 'int' but must be of type 'bool'")); + } + + @Test + public void testWheneverImpliesStatementRHSMustBeOfTypeBoolError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + " \r\n" + + "system sys\r\n" + + " annex agree {**\r\n" + + " eq test_cond : bool = true;\r\n" + + " eq test_lhs : bool = true;\r\n" + + " eq test_rhs : int = 1;\r\n" + + " assume test \"SimpleTest\": whenever test_cond occurs test_lhs implies test_rhs exclusively during (0.0, 1.0);\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues, "The rhs hand side of the 'implies' of the 'whenever' statement is of type 'int' but must be of type 'bool'")); + } + + @Test + public void testTimeIntervalLowerMustBeRealError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + " \r\n" + + "system sys\r\n" + + " annex agree {**\r\n" + + " eq test_cond : bool = true;\r\n" + + " eq test_event : bool = true;\r\n" + + " assume test \"SimpleTest\": when test_cond occurs 3 times during [0, 5.0] exclusively raises test_event;\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues, "Lower interval must be a real valued literal")); + } + + @Test + public void testTimeIntervalHigherMustBeRealError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + " \r\n" + + "system sys\r\n" + + " annex agree {**\r\n" + + " eq test_cond : bool = true;\r\n" + + " eq test_event : bool = true;\r\n" + + " assume test \"SimpleTest\": when test_cond occurs 3 times during [0.0, 5] exclusively raises test_event;\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues,"Higher interval must be a real valued literal")); + } + + @Test + public void testTimeRiseNoErrors() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + " with Base_Types;\r\n" + + " \r\n" + + "system sys\r\n" + + " features\r\n" + + " data_in : in data port Base_Types::Boolean;\r\n" + + " annex agree {**\r\n" + + " eq test : real = timerise(data_in);\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + assertTrue(issueCollection.getIssues().isEmpty()); + } + + @Test + public void testTimeRiseAppliedOnlyToBooleanIdentifiersError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + " with Base_Types;\r\n" + + " \r\n" + + "system sys\r\n" + + " features\r\n" + + " data_in : in data port Base_Types::Integer;\r\n" + + " annex agree {**\r\n" + + " eq test : real = timerise(data_in);\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues,"Time functions can be applied only to Boolean identifiers")); + } + + @Test + public void testTimeFallNoErrors() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + " with Base_Types;\r\n" + + " \r\n" + + "system sys\r\n" + + " features\r\n" + + " data_in : in data port Base_Types::Boolean;\r\n" + + " annex agree {**\r\n" + + " eq test : real = timefall(data_in);\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + assertTrue(issueCollection.getIssues().isEmpty()); + } + + @Test + public void testTimeFallAppliedOnlyToBooleanIdentifiersError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + " with Base_Types;\r\n" + + " \r\n" + + "system sys\r\n" + + " features\r\n" + + " data_in : in data port Base_Types::Float;\r\n" + + " annex agree {**\r\n" + + " eq test : real = timefall(data_in);\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues,"Time functions can be applied only to Boolean identifiers")); + } + + @Test + public void testTimeOfNoErrors() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + " with Base_Types;\r\n" + + " \r\n" + + "system sys\r\n" + + " features\r\n" + + " data_in : in data port Base_Types::Boolean;\r\n" + + " annex agree {**\r\n" + + " eq test : real = timeof(data_in);\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + assertTrue(issueCollection.getIssues().isEmpty()); + } + + @Test + public void testTimeOfAppliedOnlyToBooleanIdentifiersError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + " \r\n" + + "system sys\r\n" + + " features\r\n" + + " data_in : in event port;\r\n" + + " annex agree {**\r\n" + + " eq test : real = timeof(data_in);\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues,"Time functions can be applied only to Boolean identifiers")); + } + + @Test + public void testLemmaStatementNoErrors() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + " \r\n" + + "system sys\r\n" + + "end sys;\r\n" + + "\r\n" + + "system implementation sys.impl\r\n" + + " annex agree {**\r\n" + + " lemma L1 \"SimpleTest\" : true;\r\n" + + " **};\r\n" + + "end sys.impl;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + assertTrue(issueCollection.getIssues().isEmpty()); + } + + @Test + public void testLemmaStatementAllowedOnlyInComponentImplError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + " \r\n" + + "system sys\r\n" + + " annex agree {**\r\n" + + " lemma L1 \"SimpleTest\" : true;\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues,"Lemma statements are allowed only in component implementations and nodes")); + } + + @Test + public void testLemmaStatementMustBeOfTypeBoolError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + " \r\n" + + "system sys\r\n" + + "end sys;\r\n" + + "\r\n" + + "system implementation sys.impl\r\n" + + " annex agree {**\r\n" + + " lemma L1 \"SimpleTest\" : 1;\r\n" + + " **};\r\n" + + "end sys.impl;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues,"Expression for lemma statement is of type 'int' but must be of type 'bool'")); + } + + @Test + public void testLemmaStatementNamedInfoMessage() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + " \r\n" + + "system sys\r\n" + + "end sys;\r\n" + + "\r\n" + + "system implementation sys.impl\r\n" + + " annex agree {**\r\n" + + " lemma \"SimpleTest\" : true;\r\n" + + " **};\r\n" + + "end sys.impl;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getInfo(issues,"It is recommended that lemma statements be named." + + " (Hint: an identifier may be placed between the \"lemma\" keyword and the quoted description.)")); + } + + @Test + public void testUnaryExprNoErrors() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + " \r\n" + + "system sys\r\n" + + " annex agree {**\r\n" + + " property test = not false;\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + assertTrue(issueCollection.getIssues().isEmpty()); + } + + @Test + public void testUnaryExprNamedThingMustBeAnExprWithTypeError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + " \r\n" + + "system sys\r\n" + + " features\r\n" + + " data_in : in event port;\r\n" + + " annex agree {**\r\n" + + " property test = not data_in;\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues,"named thing must be an expression with a type")); + } + + @Test + public void testUnaryExprRHSMustBeOfTypeIntOrRealError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + " \r\n" + + "system sys\r\n" + + " annex agree {**\r\n" + + " property test = -true;\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues,"right side of unary expression '-' is of type 'bool' but must be of type 'int' or 'real'")); + } + + @Test + public void testUnaryExprRHSMustBeOfTypeBoolError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + " \r\n" + + "system sys\r\n" + + " annex agree {**\r\n" + + " eq test : int = not 1;\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues,"right side of unary expression 'not' is of type 'int' but must be of type 'bool'")); + } + + @Test + public void testPropertyStatementNoErrors() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + " \r\n" + + "system sys\r\n" + + " annex agree {**\r\n" + + " property test = false;\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + assertTrue(issueCollection.getIssues().isEmpty()); + } + + @Test + public void testPropertyStatementAllowedOnlyInComponentAnnexError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + " \r\n" + + "annex agree {**\r\n" + + " property test = false;\r\n" + + "**};\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues,"Property statments are allowed only in component annexes")); + } + + @Test + public void testPropertyStatementMustBeOfTypeBoolError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + " \r\n" + + "system sys\r\n" + + " annex agree {**\r\n" + + " property test = 10;\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues,"Property statement 'test' is of type 'int' but must be of type 'bool'")); + } + + @Test + public void testInputStatementNoErrors() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + " \r\n" + + "system sys\r\n" + + " annex agree {**\r\n" + + " agree_input a : bool, b : int;\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + assertTrue(issueCollection.getIssues().isEmpty()); + } + + @Test + public void testInputStatementAllowedOnlyInComponentTypesError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + " \r\n" + + "annex agree {**\r\n" + + " agree_input a : bool, b : int;\r\n" + + "**};\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues,"Input statements are allowed only in component types")); + } + + @Test + public void testRecordUpdateExprNoErrors() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + " \r\n" + + "system sys\r\n" + + " annex agree {**\r\n" + + " type test = struct{a: bool};\r\n" + + " eq foo : test = test{a = true};\r\n" + + " eq foo2 : test = foo{a := false};\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + assertTrue(issueCollection.getIssues().isEmpty()); + } + + @Test + public void testRecordUpdateExprNotAllowedInLinearizationBodyError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + " \r\n" + + "system sys\r\n" + + " annex agree {**\r\n" + + " type test = struct{a: bool};\r\n" + + " eq foo : test = test{a = true};\r\n" + + " eq foo2 : test = foo{a := false};\r\n" + + " linearization test_ln (x : real) over [0.0 .. 10.0] within 0.1 : foo{a := true};\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues,"Record update expressions not allowed in linearization body expression")); + } + + @Test + public void testRecordUpdateExprTypeMismatchError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + " \r\n" + + "system sys\r\n" + + " annex agree {**\r\n" + + " type test = struct{a: bool};\r\n" + + " eq foo : test = test{a = true};\r\n" + + " eq foo2 : test = foo{a := 1};\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues,"the update field is of type 'bool', but the expression is of type 'int'")); + } + + @Test + public void testRecordUpdateExprMustBeDataImplOrAGREERecordTypeError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + " \r\n" + + "system sys\r\n" + + " annex agree {**\r\n" + + " type test = struct{a: int};\r\n" + + " eq foo : int = 2;\r\n" + + " eq foo2 : test = foo{a := 1};\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues,"Record to be updated must be a data implementation or AGREE record type. Found type 'int'.")); + } + + @Test + public void testArrayLiteralExprNoErrors() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + " \r\n" + + "system sys\r\n" + + " annex agree {**\r\n" + + " eq test_arr : real[3] = [| 1.1, 2.2, 3.3|];\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + assertTrue(issueCollection.getIssues().isEmpty()); + } + + @Test + public void testArrayLiteralExprMustHaveAtLeastOneElementError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + " \r\n" + + "system sys\r\n" + + " annex agree {**\r\n" + + " eq test_arr : real[0] = [| |];\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues,"Array literal must have at least one element")); + } + + @Test + public void testArrayLiteralExprNamedThingMustBeAnExprWithTypeError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + " \r\n" + + "system sys\r\n" + + " features\r\n" + + " data_in : in event port;\r\n" + + " annex agree {**\r\n" + + " eq test_arr : real[1] = [|data_in|];\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues,"named thing must be an expression with a type")); + } + + @Test + public void testArrayLiteralExprTypeMismatchError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + " \r\n" + + "system sys\r\n" + + " annex agree {**\r\n" + + " eq test_arr : real[3] = [|1.1, 2.2, 3|];\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues,"type of array element must be 'real', but has type 'int'")); + } + + @Test + public void testArrayUpdateExprNoErrors() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + " \r\n" + + "system sys\r\n" + + " annex agree {**\r\n" + + " eq test_arr : real[3] = test_arr[| 1:= 3.0|];\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + assertTrue(issueCollection.getIssues().isEmpty()); + } + + @Test + public void testArrayUpdateExprNamedThingMustBeAnExprWithTypeError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + " \r\n" + + "system sys\r\n" + + " features\r\n" + + " data_in : in event port;\r\n" + + " annex agree {**\r\n" + + " eq test_arr : real[3] = data_in[| 1:= 3.0|];\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues,"named thing must be an expression with a type")); + } + + @Test + public void testArrayUpdateExprTypeMismatchError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + " \r\n" + + "system sys\r\n" + + " annex agree {**\r\n" + + " eq test_arr : real[3] = test_arr[| 1:= 3|];\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues,"type of array element must be 'real', but has type 'int'")); + } + + @Test + public void testArrayUpdateExprMustEvaluateToAnArrayError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + " with Base_Types;\r\n" + + " \r\n" + + "system sys\r\n" + + " features\r\n" + + " data_in : in data port Base_Types::Float;\r\n" + + " annex agree {**\r\n" + + " eq test_arr : real[3] = data_in[| 1:= 3.0|];\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues,"expression must evaluate to an array")); + } + + @Test + public void testArraySubExprNoErrors() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + " \r\n" + + "system sys\r\n" + + " annex agree {**\r\n" + + " eq test_arr : real[3];\r\n" + + " eq test : real = test_arr[1];\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + assertTrue(issueCollection.getIssues().isEmpty()); + } + + @Test + public void testArraySubExprExprNamedThingMustBeAnExprWithTypeError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + " \r\n" + + "system sys\r\n" + + " features\r\n" + + " data_in : in data port;\r\n" + + " annex agree {**\r\n" + + " eq test : real = data_in[1];\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues,"named thing must be an expression with a type")); + } + + @Test + public void testArraySubExprIndexNamedThingMustBeAnExprWithTypeError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + " \r\n" + + "system sys\r\n" + + " features\r\n" + + " data_in : in data port;\r\n" + + " annex agree {**\r\n" + + " eq test_arr : real[3];\r\n" + + " eq test : real = test_arr[data_in];\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues,"named thing must be an expression with a type")); + } + + @Test + public void testArraySubExprIndexMustBeOfTypeIntError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + " \r\n" + + "system sys\r\n" + + " annex agree {**\r\n" + + " eq test_arr : real[3];\r\n" + + " eq test : real = test_arr[1.0];\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues,"index must be of type 'int'")); + } + + @Test + public void testArraySubExprIndexIsOutOfBoundsError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + " \r\n" + + "system sys\r\n" + + " annex agree {**\r\n" + + " eq test_arr : real[3];\r\n" + + " eq test : real = test_arr[4];\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues,"Index value 4 is out of array bounds [1 .. 3]")); + } + + @Test + public void testArraySubExprCouldNotStaticallyComputeArrayIndexValueError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + " with Base_Types;\r\n" + + " \r\n" + + "system sys\r\n" + + " features\r\n" + + " data_in : in data port Base_Types::Integer;\r\n" + + " annex agree {**\r\n" + + " eq test_arr : real[3];\r\n" + + " eq test : real = test_arr[data_in];\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getWarning(issues,"Could not statically compute array index value")); + } + + @Test + public void testArraySubExprMustEvaluateToAnArrayError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + " with Base_Types;\r\n" + + " \r\n" + + "system sys\r\n" + + " features\r\n" + + " data_in : in data port Base_Types::Float;\r\n" + + " annex agree {**\r\n" + + " eq test : real = data_in[1];\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues,"expression must evaluate to an array")); + } + + @Test + public void testRecordLitExprNoErrors() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + " \r\n" + + "system sys\r\n" + + " annex agree {**\r\n" + + " type test = struct{a : int, b : real, c : bool};\r\n" + + " eq foo : test = test{a = 3; b = 3.3; c = true};\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + assertTrue(issueCollection.getIssues().isEmpty()); + } + + @Test + public void testRecordLitExprArgMustBeFeatureGroupOrRecordTypeDefError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + " \r\n" + + "system sys\r\n" + + " annex agree {**\r\n" + + " type test = struct{a : int, b : real, c : bool};\r\n" + + " property test_type = true;\r\n" + + " eq foo : test = test_type{a = 3; b = 3.3; c = true};\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues,"Record type 'test_type' must be a feature group or a record type definition")); + } + + @Test + public void testRecordLitExprIncorrectNumOfArgsError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + " \r\n" + + "system sys\r\n" + + " annex agree {**\r\n" + + " type test = struct{a : int, b : real, c : bool};\r\n" + + " eq foo : test = test{a = 3; b = 3.3};\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues,"Incorrect number of arguments")); + } + + @Test + public void testRecordLitExprNoAssignmentToVarInRecordExprError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + " \r\n" + + "system sys\r\n" + + " annex agree {**\r\n" + + " type test = struct{a : int, b : real, c : bool};\r\n" + + " eq foo : test = test{a = 3; b = 3.3; b = 4.0};\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues,"No assignment to defined variable 'c' in record expression.")); + } + + @Test + public void testRecordLitExprTypeMismatchError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + " \r\n" + + "system sys\r\n" + + " annex agree {**\r\n" + + " type test = struct{a : int, b : real, c : bool};\r\n" + + " eq foo : test = test{a = 3.0; b = 3.3; c = true};\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues,"The expression assigned to 'a' does not match its definition type of 'int'")); + } + + @Test + public void testRecordDefExprNoErrors() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + " \r\n" + + "system sys\r\n" + + " annex agree {**\r\n" + + " type test = struct{a : int, b : real, c : bool};\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + assertTrue(issueCollection.getIssues().isEmpty()); + } + + @Test + public void testRecordDefExprInvolvedInCyclicDefError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + " \r\n" + + "system sys\r\n" + + " annex agree {**\r\n" + + " type test = struct{a : test, b : real, c : bool};\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues,"The definition of type 'test' is involved in a cyclic definition")); + } + + @Test + public void testConstStatementNoErrors() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + " \r\n" + + "system sys\r\n" + + " annex agree {**\r\n" + + " const test : real = 3.14;\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + assertTrue(issueCollection.getIssues().isEmpty()); + } + + @Test + public void testConstStatementTypeMismatchError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + " \r\n" + + "system sys\r\n" + + " annex agree {**\r\n" + + " const test : real = true;\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues, "The assumed type of constant statement 'test' is 'real' but the actual type is 'bool'")); + } + + @Test + public void testConstStatemntExprIsPartOfCyclicDefError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + "\r\n" + + "system sys\r\n" + + " annex agree {**\r\n" + + " const test : int = test + 1;\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues, + "Cyclic reference to variable 'test'")); + } + + @Test + public void testConstStatementNonConstExprInConstDeclarationError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + " with Base_Types;\r\n" + + "\r\n" + + "system sys\r\n" + + " features\r\n" + + " data_in : in data port Base_Types::Float;\r\n" + + " annex agree{**\r\n" + + " const test : real = data_in * 3.14;\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues,"Non-constant expression in constant declaration")); + } + + @Test + public void testNamedElementSameNameInAnnexAndFeatureError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + "\r\n" + + "system sys\r\n" + + " features\r\n" + + " test : in event port;\r\n" + + " annex agree {**\r\n" + + " const test : int = 100;\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues,"Element of the same name ('test') in AGREE Annex in 'sys'")); + assertNotNull(UtilityFunctions.getError(issues,"Feature of the same name ('test') in component type")); + } + + @Ignore + public void testNamedElementSameNameInAnnexAndSubcomponentError() throws Exception { + // TODO: Issue #130 - Once resolved, change "@Ignore" to "@Test" + String test = "package TestPackage\r\n" + + "public\r\n" + + "\r\n" + + "system sys\r\n" + + " annex agree {**\r\n" + + " eq test : int = 100;\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "system implementation sys.impl\r\n" + + " subcomponents\r\n" + + " test : device TestSensor;\r\n" + + "end sys.impl;\r\n" + + "\r\n" + + "device TestSensor\r\n" + + "end TestSensor;\r\n" + + "\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues,"Element of the same name ('test') in AGREE Annex in 'sys'")); + assertNotNull(UtilityFunctions.getError(issues, + "Subcomponent of the same name ('test') in component implementation")); + } + + @Test + public void testEqStatementNoErrors() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + " \r\n" + + "system sys\r\n" + + " annex agree {**\r\n" + + " eq test : bool = true;\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + assertTrue(issueCollection.getIssues().isEmpty()); + } + + @Test + public void testEqStatementAllowedOnlyInComponentAnnexError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + " \r\n" + + "annex agree {**\r\n" + + " eq test : bool = true;\r\n" + + "**};\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues,"Equation statments are allowed only in component annexes")); + } + + @Test + public void testEqStatementCyclicReferenceToVarError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + "\r\n" + + "system sys\r\n" + + " annex agree {**\r\n" + + " eq test : int = test + 100;\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues,"Cyclic reference to variable 'test'")); + } + + @Test + public void testEqStatementCannotContainRangedValueAndRHSExprError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + "\r\n" + + "system sys\r\n" + + " annex agree {**\r\n" + + " eq test : real[1.0, 3.0] = 2.4;\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues,"Equation statements cannot contain a ranged value and a right hand side expression")); + } + + @Test + public void testEqStatementVariableNumMismatchError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + "\r\n" + + "system sys\r\n" + + " annex agree {**\r\n" + + " eq test : int, test2 : real = 2;\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues,"Equation assigns 2 variables, but right side returns 1 values")); + } + + @Test + public void testEqStatementTypeMismatchError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + "\r\n" + + "system sys\r\n" + + " annex agree {**\r\n" + + " eq test : bool = 1;\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues,"The variable 'test' on the left side of equation is of type 'bool' but must be of type 'int'")); + } + + @Test + public void testNameOverlapMultipleSynchOrCalendarStatementError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + "\r\n" + + "system sys\r\n" + + "end sys;\r\n" + + "\r\n" + + "system implementation sys.impl\r\n" + + " annex agree {**\r\n" + + " synchrony : latched;\r\n" + + " synchrony : asynchronous;\r\n" + + " **};\r\n" + + "end sys.impl;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues,"Multiple synchrony or calender statements in a single contract")); + } + + @Test + public void testNameOverlapMultipleInitiallyStatementsError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + "\r\n" + + "system sys\r\n" + + " annex agree {**\r\n" + + " initially : true;\r\n" + + " initially : false;\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues,"Multiple initially statements in a single contract")); + } + + @Test + public void testNameOverlapMultipleConnectionOverridesError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + "\r\n" + + "system sys\r\n" + + "end sys;\r\n" + + "\r\n" + + "system implementation sys.impl\r\n" + + " subcomponents\r\n" + + " this_sensor : device TestSensor;\r\n" + + " connections\r\n" + + " sensor_conn : port this_sensor.data_out -> this_sensor.data_in;\r\n" + + " annex agree {**\r\n" + + " connection sensor_conn : true;\r\n" + + " connection sensor_conn : true;\r\n" + + " **};\r\n" + + "end sys.impl;\r\n" + + "\r\n" + + "device TestSensor\r\n" + + " features\r\n" + + " data_in : in data port;\r\n" + + " data_out : out data port;\r\n" + + "end TestSensor;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues,"Multiple connection overrides for connection 'sensor_conn'")); + } + + @Test + public void testNameOverlapAlreadyDefinedInComponentTypeContractError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + "\r\n" + + "system sys\r\n" + + " annex agree {**\r\n" + + " property test = true;\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "system implementation sys.impl\r\n" + + " annex agree {**\r\n" + + " property test = false; \r\n" + + " **};\r\n" + + "end sys.impl;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues,"'test' already defined in component type contract")); + } + + @Test + public void testNodeEqNoErrors() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + "\r\n" + + "system sys\r\n" + + " annex agree {**\r\n" + + " node test(data_in : bool) returns (data_out : bool);\r\n" + + " let\r\n" + + " data_out = true;\r\n" + + " tel;\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + assertTrue(issueCollection.getIssues().isEmpty()); + } + + @Ignore + public void testNodeEqMustBeContainedInANodeBodyError() throws Exception { + // TODO + } + + @Ignore + public void testNodeEqMustBeContainedInANodeDefError() throws Exception { + // TODO + } + + @Ignore + public void testNodeEqLHSMustBeAReturnVarOrLocalVarError() throws Exception { + // TODO + } + + @Ignore + public void testNodeEqSomethingWentWrongWithCycleCheckerError() throws Exception { + // TODO + } + + @Ignore + public void testNodeEqCyclicReferenceToVarError() throws Exception { + // TODO + } + + @Ignore + public void testNodeEqCannotContainRangedValueAndRHSExprError() throws Exception { + // TODO + } + + @Ignore + public void testNodeEqTypeMismatchError() throws Exception { + // TODO + } + + @Test + public void testNodeLemmaNoErrors() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + "\r\n" + + "system sys\r\n" + + " annex agree {**\r\n" + + " node test(data_in : bool) returns (data_out : bool);\r\n" + + " let\r\n" + + " data_out = true;\r\n" + + " lemma \"Always True\" : true;\r\n" + + " tel;\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + assertTrue(issueCollection.getIssues().isEmpty()); + } + + @Test + public void testNodeLemmaMustBeOfTypeBoolError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + "\r\n" + + "system sys\r\n" + + " annex agree {**\r\n" + + " node test(data_in : bool) returns (data_out : bool);\r\n" + + " let\r\n" + + " data_out = true;\r\n" + + " lemma \"Always True\" : 1;\r\n" + + " tel;\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues,"Expression for lemma statement is of type 'int' but must be of type 'bool'")); + } + + @Ignore + public void testNodeStmtNoErrors() throws Exception { + // TODO + } + + @Ignore + public void testNodeStmtOnlyArgumentsConstantsAndNodeCallsAllowedError() throws Exception { + // TODO + } + + @Ignore + public void testNodeDefNoErrors() throws Exception { + // TODO + } + + @Ignore + public void testNodeDefNotAssignableValueError() throws Exception { + // TODO + } + + @Ignore + public void testNodeDefVariableNeverAssignedError() throws Exception { + // TODO + } + + @Ignore + public void testNodeDefAssignedMultipleTimesError() throws Exception { + // TODO + } + + @Test + public void testLinearizationDefNoErrors() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + "\r\n" + + "system sys\r\n" + + " annex agree {**\r\n" + + " linearization test (x : real) over [0.0 .. 10.0] within 0.1: x^2;\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + assertTrue(issueCollection.getIssues().isEmpty()); + } + + @Test + public void testLinearizationDefLimitedToFunctionsOfOneVariableError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + "\r\n" + + "system sys\r\n" + + " annex agree {**\r\n" + + " linearization test (x : real, y: real) over [0.0 .. 10.0, 0.0 .. 10.0] : (x*y)^2;\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues,"Linearization definitions are limited to functions of one variable.")); + } + + @Test + public void testLinearizationDefArgMustBeOfRealTypeError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + "\r\n" + + "system sys\r\n" + + " annex agree {**\r\n" + + " linearization test (x : int) over [0.0 .. 10.0] : x^2;\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues,"Linearizations formal arguments must be of 'real' type, but found type 'int'.")); + } + + @Test + public void testLinearizationDefNumberOfFormalVarAndIntervalsDoesNotMatchError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + "\r\n" + + "system sys\r\n" + + " annex agree {**\r\n" + + " linearization test (x : real) over [0.0 .. 10.0, 0.0 .. 10.0] : x^2;\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues,"Number of formal variables and intervals does not match.")); + } + + @Test + public void testLinearizationDefPrecisionMustBeOfRealTypeError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + "\r\n" + + "system sys\r\n" + + " annex agree {**\r\n" + + " linearization test (x : real) over [0.0 .. 10.0] within 1 : x^2;\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues,"Linearization precision must be of 'real' type, but found type 'int'.")); + } + + @Test + public void testLinearizationDefPrecisionMustBeConstantExprError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + "\r\n" + + "system sys\r\n" + + " annex agree {**\r\n" + + " linearization test (x : real) over [0.0 .. 10.0] within x*0.1 : x^2;\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues, "Linearization precision must be constant expression of 'real' type, found non-constant expression.")); + } + + @Test + public void testLinearizationIntervalStartMustBeOfRealTypeError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + "\r\n" + + "system sys\r\n" + + " annex agree {**\r\n" + + " linearization test (x : real) over [0 .. 10.0] within 0.1 : x^2;\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues,"Linearization interval endpoints must be constant expressions of 'real' type, found type 'int'.")); + } + + @Test + public void testLinearizationIntervalEndMustBeOfRealTypeError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + "\r\n" + + "system sys\r\n" + + " annex agree {**\r\n" + + " linearization test (x : real) over [0.0 .. 10] within 0.1 : x^2;\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues,"Linearization interval endpoints must be constant expressions of 'real' type, found type 'int'.")); + } + + @Test + public void testLinearizationIntervalStartMustBeConstantError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + "\r\n" + + "system sys\r\n" + + " annex agree {**\r\n" + + " linearization test (x : real) over [0.0*x .. 10.0] within 0.1 : x^2;\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues,"Linearization interval endpoints must be constant expressions of 'real' type, found non-constant expression.")); + } + + @Test + public void testLinearizationIntervalEndMustBeConstantError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + "\r\n" + + "system sys\r\n" + + " annex agree {**\r\n" + + " linearization test (x : real) over [0.0 .. 10.0*x] within 0.1 : x^2;\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues,"Linearization interval endpoints must be constant expressions of 'real' type, found non-constant expression.")); + } + + @Test + public void testGetPropertyExprNoErrors() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + " with SEI;\r\n" + + "\r\n" + + "system sys\r\n" + + " properties\r\n" + + " SEI::NetWeight => 10.0kg;\r\n" + + " annex agree {**\r\n" + + " const test : real = Get_Property(this, SEI::NetWeight);\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + assertTrue(issueCollection.getIssues().isEmpty()); + } + + @Test + public void testGetPropertyExprExpectedAADLPropertyOrPropertyConstError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + " with SEI;\r\n" + + " with Base_Types;\r\n" + + "\r\n" + + "system sys\r\n" + + " features\r\n" + + " data_in : in data port Base_Types::Integer;\r\n" + + " properties\r\n" + + " SEI::NetWeight => 10.0kg;\r\n" + + " annex agree {**\r\n" + + " const test : int = Get_Property(this, data_in);\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues,"Expected AADL property or property constant")); + } + + @Ignore + public void testGetPropertyExprPropertyDoesNotApplyError() throws Exception { + // TODO + } + + @Test + public void testPrevExprNoErrors() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + "\r\n" + + "system sys\r\n" + + " annex agree {**\r\n" + + " eq test : int = prev(test+1, 0);\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + assertTrue(issueCollection.getIssues().isEmpty()); + } + + @Test + public void testPrevExprTypeMismatchError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + "\r\n" + + "system sys\r\n" + + " annex agree {**\r\n" + + " eq test : int = prev(test+1, 0.0);\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues,"The first and second arguments of the 'prev' function are of non-matching types 'int' and 'real'.")); + } + + @Test + public void testPrevExprNotAllowedInLinearizationBodyError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + "\r\n" + + "system sys\r\n" + + " annex agree {**\r\n" + + " linearization test_ln (x : real) over [0.0 .. 10.0] within 0.1 : prev(x+1.0, 0.0);\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues,"'prev' expressions are not allowed in linearization body expressions.")); + } + + @Test + public void testPrevExprNotAllowedInConstantExprError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + "\r\n" + + "system sys\r\n" + + " annex agree {**\r\n" + + " const test : int = prev(test+1, 0);\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues,"'prev' expressions are not allowed in constant expressions.")); + } + + @Test + public void testCallExprNoErrors() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + "\r\n" + + "system sys\r\n" + + " annex agree {**\r\n" + + " fun test_fn(x : real) : bool = true;\r\n" + + " property test1 = test_fn(1.0);\r\n" + + " node test_node(data_in: bool) returns (data_out: bool);\r\n" + + " let\r\n" + + " data_out = true;\r\n" + + " tel;\r\n" + + " property test2 = test_node(true); \r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + assertTrue(issueCollection.getIssues().isEmpty()); + } + + @Test + public void testCallExprNodeDefCannotBeAppliedInLinearizationDefError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + "\r\n" + + "system sys\r\n" + + " annex agree {**\r\n" + + " node test_node(data_in: bool) returns (data_out: bool);\r\n" + + " let\r\n" + + " data_out = true;\r\n" + + " tel;\r\n" + + " linearization test_ln (x : real) over [0.0 .. 10.0] within 0.1 : test_node(true); \r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues,"Node definitions cannot be applied in a linearization definition")); + } + + @Test + public void testCallExprLibraryFndRealError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + " with DReal;\r\n" + + "\r\n" + + "system sys\r\n" + + " annex agree {**\r\n" + + " eq test : real = DReal::exp(1.23);\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull( + UtilityFunctions.getWarning(issues, "dReal library functions require the use of the dReal solver")); + } + + @Test + public void testCallExprLibraryFnCannotBeCalledFromLogicError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + "\r\n" + + "system sys\r\n" + + " annex agree {**\r\n" + + " external test_libfn(x : int) : int;\r\n" + + " eq test : int = test_libfn(5); \r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues,"Library functions cannot be called from the logic")); + } + + @Test + public void testCallExprFunctionArgumentNumberError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + "\r\n" + + "system sys\r\n" + + " annex agree {**\r\n" + + " fun test_fn(x : real) : bool = true;\r\n" + + " property test = test_fn(1.0, 2.0);\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues,"Function definition 'test_fn' requires 1 arguments, but this function call provides 2 arguments")); + } + + @Test + public void testCallExprFunctionArgumentTypeMismatchError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + "\r\n" + + "system sys\r\n" + + " annex agree {**\r\n" + + " fun test_fn(x : real) : bool = true;\r\n" + + " property test = test_fn(1);\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues,"Argument 0 of function call 'test_fn' is of type 'int' but must be of type 'real'.")); + } + + @Test + public void testFnDefNoErrors() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + "\r\n" + + "system sys\r\n" + + " annex agree {**\r\n" + + " fun test(x : real) : bool = false;\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + assertTrue(issueCollection.getIssues().isEmpty()); + } + + @Test + public void testFnDefTypeMismatchError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + "\r\n" + + "system sys\r\n" + + " annex agree {**\r\n" + + " fun test(x : real) : bool = x;\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues,"Function 'test' is of type 'bool' but its expression is of type 'real'.")); + } + + @Ignore + public void testAbstractionNoErrors() throws Exception { + // TODO + } + + @Ignore + public void testAbstractionRecursiveDependencyError() throws Exception { + // TODO + } + + @Test + public void testIfThenElseExprNoErrors() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + "\r\n" + + "system sys\r\n" + + " annex agree {**\r\n" + + " property test = if true then false else true;\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + assertTrue(issueCollection.getIssues().isEmpty()); + } + + @Test + public void testIfThenElseExprNotAllowedInLinearizationBodyExprError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + "\r\n" + + "system sys\r\n" + + " annex agree {**\r\n" + + " linearization test_ln (x : real) over [0.0 .. 10.0] within 0.1 : if x < 5.0 then x + 1.0 else x * 2.0;\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues,"If-then-else expressions not allowed in linearization body expressions")); + } + + @Test + public void testIfThenElseExprConditionMustBeOfTypeBoolError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + "\r\n" + + "system sys\r\n" + + " annex agree {**\r\n" + + " property test = if 1 then false else true;\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues,"The condition of the if statement is of type 'int' but must be of type 'bool'")); + } + + @Test + public void testIfThenElseExprThenElseTypeMismatchError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + "\r\n" + + "system sys\r\n" + + " annex agree {**\r\n" + + " property test = if true then false else 0;\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues,"The 'then' and 'else' expressions are of non-matching types 'bool' and 'int'")); + } + + @Test + public void testPreExprNoErrors() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + "\r\n" + + "system sys\r\n" + + " annex agree {**\r\n" + + " eq test : int = 0 -> pre(test+1);\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + assertTrue(issueCollection.getIssues().isEmpty()); + } + + @Test + public void testPreExprNotAllowedInLinearizationBodyError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + "\r\n" + + "system sys\r\n" + + " annex agree {**\r\n" + + " linearization test_ln (x : real) over [0.0 .. 10.0] within 0.1 : 0 -> pre(x+1.0);\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues,"'pre' expressions are not allowed in linearization body expressions.")); + } + + @Test + public void testPreExprNotAllowedInConstantExprError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + "\r\n" + + "system sys\r\n" + + " annex agree {**\r\n" + + " const test : int = pre(test+1);\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues,"'pre' expressions are not allowed in constant expressions.")); + } + + @Test + public void testBinaryExprNoErrors() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + "\r\n" + + "system sys\r\n" + + " annex agree {**\r\n" + + " eq test1 : bool = true -> false;\r\n" + + " eq test2 : bool = true => true;\r\n" + + " eq test3 : bool = true <=> true;\r\n" + + " eq test4 : bool = true and true;\r\n" + + " eq test5 : bool = true or false;\r\n" + + " eq test6 : bool = 1 = 2;\r\n" + + " eq test7 : bool = 1 <> 1;\r\n" + + " eq test8 : bool = 1 != 1;\r\n" + + " eq test9 : bool = 3.4 < 4.0;\r\n" + + " eq test10 : bool = 3.4 <= 4.0;\r\n" + + " eq test11 : bool = 3.4 > 4.0;\r\n" + + " eq test12 : bool = 3.4 >= 4.0;\r\n" + + " eq test13 : int = 4 + 5;\r\n" + + " eq test14 : int = 4 - 5;\r\n" + + " eq test15 : int = 4 * 5;\r\n" + + " eq test16 : int = 20 mod 5;\r\n" + + " eq test17 : int = 20 div 4;\r\n" + + " eq test18 : real = 15.0 / 3.0;\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + assertTrue(issueCollection.getIssues().isEmpty()); + } + + @Test + public void testBinaryExprArrowExprNotAllowedInLinearizationBodyExprError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + "\r\n" + + "system sys\r\n" + + " annex agree {**\r\n" + + " linearization test (x : real) over [0.0 .. 10.0] within 0.1: true -> false;\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues,"Arrow '->' expressions are not allowed in linearization body expressions.")); + } + + @Test + public void testBinaryExprArrowExprNotAllowedInConstantExprError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + "\r\n" - + "system S\r\n" + " features\r\n" + " Input_Val: in data port Base_Types::Float;\r\n" - + " Output_Val: out data port Base_Types::Float;\r\n" + " annex agree {**\r\n" - + " assume A1 \"\" : Input_Val < TEST_VAL;\r\n" + + "system sys\r\n" + + " annex agree {**\r\n" + + " const test : int = 0 -> pre(test+1);\r\n" + " **};\r\n" - + "end S;\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues,"Arrow '->' expressions are not allowed in constant expressions.")); + } + + @Test + public void testBinaryExprArrowExprLHSAndRHSTypeMismatchError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + "\r\n" - + "system implementation S.impl\r\n" + " subcomponents\r\n" + " A: system A;\r\n" - + " connections\r\n" + " c1_a: port Input_Val -> A.Input_Val; \r\n" - + " c2_a: port A.Output_Val -> Output_Val;\r\n" + "end S.impl;\r\n" + + "system sys\r\n" + + " annex agree {**\r\n" + + " eq test : bool = true -> 0;\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues, "left and right sides of binary expression '->' are of type 'bool' and 'int', but must be of the same type")); + } + + @Test + public void testBinaryExprLogicalExprNotAllowedInLinearizationBodyExprError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + "\r\n" + + "system sys\r\n" + + " annex agree {**\r\n" + + " linearization test (x : real) over [0.0 .. 10.0] within 0.1: true or false;\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues,"Logical expressions (like 'or') are not allowed in linearization body expressions.")); + } + + @Test + public void testBinaryExprLogicalExprLHSMustBeOfTypeBoolError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + "\r\n" + + "system sys\r\n" + + " annex agree {**\r\n" + + " eq test : bool = 0.0 <=> false;\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues,"left side of binary expression '<=>' is of type 'real' but must be of type 'bool'")); + } + + @Test + public void testBinaryExprLogicalExprRHSMustBeOfTypeBoolError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + "\r\n" + + "system sys\r\n" + + " annex agree {**\r\n" + + " eq test : bool = true and 1;\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues,"right side of binary expression 'and' is of type 'int' but must be of type 'bool'")); + } + + @Test + public void testBinaryExprLogicalComparisonExprNotAllowedInLinearizationBodyExprError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + "\r\n" + + "system sys\r\n" + + " annex agree {**\r\n" + + " linearization test (x : real) over [0.0 .. 10.0] within 0.1: 1 = 1;\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues,"Logical comparison expressions (like '=') are not allowed in linearization body expressions.")); + } + + @Test + public void testBinaryExprLogicalComparisonExprTypeMismatchError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + "\r\n" + + "system sys\r\n" + + " annex agree {**\r\n" + + " eq test : bool = 0.0 != 0;\r\n" + + " **};\r\n" + + "end sys;\r\n" + "\r\n" + "end TestPackage;"; FluentIssueCollection issueCollection = testHelper.testString(test); List issues = issueCollection.getIssues(); assertFalse(issues.isEmpty()); assertNotNull(UtilityFunctions.getError(issues, - "The assumed type of constant statement 'TEST_VAL' is 'RealTypeDef' but the actual type is 'IntTypeDef'")); - assertNotNull(UtilityFunctions.getError(issues, - "left and right sides of binary expression '<' are of type 'real' and 'int', but must be of the same type")); + "left and right sides of binary expression '!=' are of type 'real' and 'int', but must be of the same type")); + } + + @Test + public void testBinaryExprComparisonExprNotAllowedInLinearizationBodyExprError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + "\r\n" + + "system sys\r\n" + + " annex agree {**\r\n" + + " linearization test (x : real) over [0.0 .. 10.0] within 0.1: 3.4 < 4.0;\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues,"Comparison expressions (like '<') are not allowed in linearization body expressions.")); + } + + @Test + public void testBinaryExprComparisonExprTypeMismatchError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + "\r\n" + + "system sys\r\n" + + " annex agree {**\r\n" + + " eq test : bool = 1 >= 0.5;\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues,"left and right sides of binary expression '>=' are of type 'int' and 'real', but must be of the same type")); + } + + @Test + public void testBinaryExprComparisonExprLHSMustBeOfTypeIntOrRealError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + "\r\n" + + "system sys\r\n" + + " annex agree {**\r\n" + + " eq test : bool = true > 1;\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues,"left side of binary expression '>' is of type 'bool' but must be of type 'int' or 'real'")); + } + + @Test + public void testBinaryExprComparisonExprRHSMustBeOfTypeIntOrRealError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + "\r\n" + + "system sys\r\n" + + " annex agree {**\r\n" + + " eq test : bool = 0 < false;\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues,"right side of binary expression '<' is of type 'bool' but must be of type 'int' or 'real'")); + } + + @Test + public void testBinaryExprAddSubMultExprTypeMismatchError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + "\r\n" + + "system sys\r\n" + + " annex agree {**\r\n" + + " eq test : int = 1 + 2.2;\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues,"left and right sides of binary expression '+' are of type 'int' and 'real', but must be of the same type")); + } + + @Test + public void testBinaryExprAddSubMultExprLHSMustBeOfTypeIntOrRealError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + "\r\n" + + "system sys\r\n" + + " annex agree {**\r\n" + + " eq test : int = true + 2;\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues,"left side of binary expression '+' is of type 'bool' but must be of type 'int' or 'real'")); + } + + @Test + public void testBinaryExprAddSubMultExprRHSMustBeOfTypeIntOrRealError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + "\r\n" + + "system sys\r\n" + + " annex agree {**\r\n" + + " eq test : real = 0.0 * false;\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues,"right side of binary expression '*' is of type 'bool' but must be of type 'int' or 'real'")); + } + + @Test + public void testBinaryExprAddSubMultExprNotConstantWarning() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + " with Base_Types;\r\n" + + "\r\n" + + "system sys\r\n" + + " features\r\n" + + " data_in : in data port Base_Types::Integer;\r\n" + + " annex agree {**\r\n" + + " eq inc_test : int = prev(inc_test + 1, 0);\r\n" + + " eq test : int = data_in*inc_test;\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getWarning(issues,"neither the right nor the left side of binary expression '*' is constant'. Non-linear expressions are allowed only with z3 and dReal." + + " With z3 they are not recomended.")); + } + + @Test + public void testBinaryExprModDivExprNotAllowedInLinearizationBodyExprError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + "\r\n" + + "system sys\r\n" + + " annex agree {**\r\n" + + " linearization test (x : real) over [0.0 .. 10.0] within 0.1: 20 mod 5;\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues,"Integer operation expressions (like 'mod') are not allowed in linearization body expressions.")); + } + + @Test + public void testBinaryExprModDivExprLHSMustBeOfTypeIntError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + "\r\n" + + "system sys\r\n" + + " annex agree {**\r\n" + + " eq test : real = 20.0 mod 4;\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues,"left side of binary expression 'mod' is of type 'real' but must be of type 'int'")); + } + + @Test + public void testBinaryExprModDivExprRHSMustBeOfTypeIntError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + "\r\n" + + "system sys\r\n" + + " annex agree {**\r\n" + + " eq test : int = 50 div true;\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues,"right side of binary expression 'div' is of type 'bool' but must be of type 'int'")); + } + + @Test + public void testBinaryExprModDivRHSNotConstantWarning() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + " with Base_Types;\r\n" + + "\r\n" + + "system sys\r\n" + + " features\r\n" + + " data_in : in data port Base_Types::Integer;\r\n" + + " annex agree {**\r\n" + + " eq test : int = 50 div data_in;\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getWarning(issues, "right side of binary expression 'div' is not constant." + + " Non-linear expressions are allowed only with z3." + + " Even with z3 they are not recomended...")); + } + + @Test + public void testBinaryExprDivideExprLHSMustBeOfTypeRealError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + "\r\n" + + "system sys\r\n" + + " annex agree {**\r\n" + + " eq test : int = 20 / 1.0;\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues,"left side of binary expression '/' is of type 'int' but must be of type 'real'")); + } + + @Test + public void testBinaryExprDivideExprRHSMustBeOfTypeRealError() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + "\r\n" + + "system sys\r\n" + + " annex agree {**\r\n" + + " eq test : real = 50.0 / 4;\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getError(issues,"right side of binary expression '/' is of type 'int' but must be of type 'real'")); + } + + @Test + public void testBinaryExprDivideExprRHSNotConstantWarning() throws Exception { + String test = "package TestPackage\r\n" + + "public\r\n" + + " with Base_Types;\r\n" + + "\r\n" + + "system sys\r\n" + + " features\r\n" + + " data_in : in data port Base_Types::Float;\r\n" + + " annex agree {**\r\n" + + " eq test : real = 50.0 / data_in;\r\n" + + " **};\r\n" + + "end sys;\r\n" + + "\r\n" + + "end TestPackage;"; + FluentIssueCollection issueCollection = testHelper.testString(test); + List issues = issueCollection.getIssues(); + assertFalse(issues.isEmpty()); + assertNotNull(UtilityFunctions.getWarning(issues, "right side of binary expression '/' is not constant." + + " Non-linear expressions are allowed only with z3." + + " Even with z3 they are not recomended...")); } + } \ No newline at end of file diff --git a/com.rockwellcollins.atc.agree.tests/src/com/rockwellcollins/atc/agree/tests/UtilityFunctions.java b/com.rockwellcollins.atc.agree.tests/src/com/rockwellcollins/atc/agree/tests/UtilityFunctions.java index b0527feb1..7b66c0f83 100644 --- a/com.rockwellcollins.atc.agree.tests/src/com/rockwellcollins/atc/agree/tests/UtilityFunctions.java +++ b/com.rockwellcollins.atc.agree.tests/src/com/rockwellcollins/atc/agree/tests/UtilityFunctions.java @@ -998,4 +998,20 @@ public static Issue getWarning(List issues, String message) { } return null; } + + /** + * Takes an list of issues and returns the info message with the matching message + * + * @param issues the list of issues + * @param message the message of the info message + * @return the info message with the matching message + */ + public static Issue getInfo(List issues, String message) { + for (Issue i : issues) { + if (i.getMessage().equals(message) && i.getSeverity() == Severity.INFO) { + return i; + } + } + return null; + } } diff --git a/com.rockwellcollins.atc.agree/src/com/rockwellcollins/atc/agree/validation/AgreeValidator.java b/com.rockwellcollins.atc.agree/src/com/rockwellcollins/atc/agree/validation/AgreeValidator.java index 61b4fe11c..385375d1b 100644 --- a/com.rockwellcollins.atc.agree/src/com/rockwellcollins/atc/agree/validation/AgreeValidator.java +++ b/com.rockwellcollins.atc.agree/src/com/rockwellcollins/atc/agree/validation/AgreeValidator.java @@ -37,6 +37,7 @@ import java.util.stream.Collectors; import org.eclipse.emf.common.util.EList; +import org.eclipse.emf.common.util.URI; import org.eclipse.emf.ecore.EObject; import org.eclipse.xtext.EcoreUtil2; import org.eclipse.xtext.validation.Check; @@ -181,13 +182,18 @@ public class AgreeValidator extends AbstractAgreeValidator { protected boolean isResponsible(Map context, EObject eObject) { // return (eObject.eClass().getEPackage() == AgreePackage.eINSTANCE) || eObject instanceof AadlPackage; return eObject.eClass().getEPackage() == AgreePackage.eINSTANCE - // || eObject.eClass().getEPackage() == Aadl2Package.eINSTANCE || super.isResponsible(context, eObject); } @Check(CheckType.FAST) public void checkEnumStatement(EnumStatement statement) { - String contextProject = statement.eResource().getURI().segment(1); + URI contextUri = statement.eResource().getURI(); + String contextProject; + if (contextUri.segmentCount() == 1) { + contextProject = contextUri.segment(0); // Required for tests since we parse a string instead of a file + } else { + contextProject = contextUri.segment(1); + } Map enumMap; if (!enumSets.containsKey(contextProject)) { enumMap = new HashMap<>(); @@ -324,12 +330,6 @@ private static List flattenFeatureGroups(List comple @Check(CheckType.FAST) public void checkAssign(AssignStatement assign) { - - if (!(assign.getId() instanceof NamedElement)) { - error(assign.getId(), - "The Id on the left hand side of an assignment statement " + "must not contain a \".\""); - return; - } NamedElement namedEl = assign.getId(); Expr expr = assign.getExpr(); @@ -395,17 +395,17 @@ public void checkAssign(AssignStatement assign) { if (spec instanceof AssignStatement && spec != assign) { NamedElement otherEl = ((AssignStatement) spec).getId(); if (otherEl.equals(namedEl)) { - error(spec, "Mulitiple assignments to variable '" + namedEl.getName() + "'"); - error(assign, "Mulitiple assignments to variable '" + namedEl.getName() + "'"); + error(spec, "Multiple assignments to variable '" + namedEl.getName() + "'"); + error(assign, "Multiple assignments to variable '" + namedEl.getName() + "'"); } } else if (spec instanceof EqStatement) { EqStatement eqStmt = (EqStatement) spec; for (NamedElement otherEl : eqStmt.getLhs()) { if (eqStmt.getExpr() != null && otherEl.equals(namedEl)) { error(spec, - "Mulitiple assignments to variable '" + namedEl.getName() + "'"); + "Multiple assignments to variable '" + namedEl.getName() + "'"); error(assign, - "Mulitiple assignments to variable '" + namedEl.getName() + "'"); + "Multiple assignments to variable '" + namedEl.getName() + "'"); } } } @@ -436,15 +436,11 @@ protected void checkArgType(Type type) { boolean rangeLowDot = rangeLow.contains("."); boolean rangeHighDot = rangeHigh.contains("."); - if (rangeLowDot != rangeHighDot) { - error(type, "The range intervals are of differing types"); - } - - if (strType.equals("int") && (rangeLowDot || rangeHighDot)) { + if (!(strType.equals("int") || strType.equals("real"))) { + error(type, "Ranged variables must be of type 'int' or of type 'real'"); + } else if (strType.equals("int") && (rangeLowDot || rangeHighDot)) { error(type, "Ranged variable of type 'int' contains a 'real' value in its interval"); - } - - if (strType.equals("real") && (!rangeLowDot || !rangeHighDot)) { + } else if (strType.equals("real") && (!rangeLowDot || !rangeHighDot)) { error(type, "Ranged variable of type 'real' contains an 'int' value in its interval"); } @@ -512,27 +508,10 @@ public void checkArg(Arg arg) { checkArgType(arg.getType()); } - @Check(CheckType.FAST) - public void checkCalenStatement(CalenStatement calen) { - Classifier container = calen.getContainingClassifier(); - if (!(container instanceof ComponentImplementation)) { - error(calen, "Calendar statements can appear only in component implementations"); - return; - } - - for (int index = 0; index < calen.getEls().size(); ++index) { - NamedElement el = calen.getEls().get(index); - if (!(el instanceof Subcomponent) || !((Subcomponent) el).getContainingComponentImpl().equals(container)) { - error("Element '" + el.getName() + "' is not a subcomponent of '" + container.getName() + "'", calen, - AgreePackage.Literals.CALEN_STATEMENT__ELS, index); - } - } - } - @Check(CheckType.FAST) public void checkFloorCast(FloorCast floor) { if (isInLinearizationBody(floor)) { - error(floor, "'event' expressions not allowed in linearization body expressions"); + error(floor, "'floor' expressions not allowed in linearization body expressions"); return; } checkTypeExists(floor.getExpr()); @@ -547,7 +526,7 @@ public void checkFloorCast(FloorCast floor) { @Check(CheckType.FAST) public void checkRealCast(RealCast real) { if (isInLinearizationBody(real)) { - error(real, "'event' expressions not allowed in linearization body expressions"); + error(real, "'real' expressions not allowed in linearization body expressions"); return; } @@ -647,7 +626,8 @@ public void checkLatchedExpr(LatchedExpr latched) { public void checkSynchStatement(SynchStatement sync) { Classifier container = sync.getContainingClassifier(); - if (!(container instanceof ComponentImplementation)) { + // CalenStatement has a separate check for this + if (!(container instanceof ComponentImplementation) && !(sync instanceof CalenStatement)) { error(sync, "Synchrony statements can appear only in component implementations"); } @@ -656,11 +636,6 @@ public void checkSynchStatement(SynchStatement sync) { return; } - // TODO: I'm pretty sure INT_LITs are always positive anyway. - // So this may be redundant - if (Integer.valueOf(sync.getVal()) < 0) { - error(sync, "The value of synchrony statments must be positive"); - } String val2 = sync.getVal2(); if (val2 != null) { if (Integer.valueOf(val2) <= 0) { @@ -677,7 +652,6 @@ public void checkSynchStatement(SynchStatement sync) { public void checkMNSynchStatement(MNSynchStatement sync) { ComponentImplementation compImpl = sync.getContainingComponentImpl(); if (compImpl == null) { - // This should already be checked by checkSynchStatement return; } compImpl.getAllSubcomponents(); @@ -725,6 +699,23 @@ public void checkMNSynchStatement(MNSynchStatement sync) { } } + @Check(CheckType.FAST) + public void checkCalenStatement(CalenStatement calen) { + Classifier container = calen.getContainingClassifier(); + if (!(container instanceof ComponentImplementation)) { + error(calen, "Calendar statements can appear only in component implementations"); + return; + } + + for (int index = 0; index < calen.getEls().size(); ++index) { + NamedElement el = calen.getEls().get(index); + if (!(el instanceof Subcomponent) || !((Subcomponent) el).getContainingComponentImpl().equals(container)) { + error("Element '" + el.getName() + "' is not a subcomponent of '" + container.getName() + "'", calen, + AgreePackage.Literals.CALEN_STATEMENT__ELS, index); + } + } + } + private void getPackageDependencies(AadlPackage pkg, Set pkgs) { // Add the parent package if it's not there, otherwise return @@ -923,7 +914,7 @@ public void checkLiftContract(LiftContractStatement lcst) { if (usedChildOutPorts.contains(sourceNe.getName())) { error(lcst, - "'lift contract;' statement is not allowed in component implementation whith more than one connection out of same output " + "'lift contract;' statement is not allowed in component implementation with more than one connection out of same output " + sourceNe.getQualifiedName() + "."); } @@ -933,7 +924,7 @@ public void checkLiftContract(LiftContractStatement lcst) { if (ctPlusAllExtended.contains(sourceNe.getContainingClassifier())) { if (usedParentInPorts.contains(sourceNe.getName())) { error(lcst, - "'lift contract;' statement is not allowed in component implementation whith more than one connection out of same input " + "'lift contract;' statement is not allowed in component implementation with more than one connection out of same input " + sourceNe.getQualifiedName() + "."); } @@ -949,7 +940,7 @@ public void checkLiftContract(LiftContractStatement lcst) { if (usedChildInPorts.contains(destNe.getName())) { error(lcst, - "'lift contract;' statement is not allowed in component implementation whith more than one connection into same input " + "'lift contract;' statement is not allowed in component implementation with more than one connection into same input " + destNe.getQualifiedName() + "."); } @@ -960,7 +951,7 @@ public void checkLiftContract(LiftContractStatement lcst) { if (usedParentOutPorts.contains(destNe.getName())) { error(lcst, - "'lift contract;' statement is not allowed in component implementation whith more than one connection into same output " + "'lift contract;' statement is not allowed in component implementation with more than one connection into same output " + destNe.getQualifiedName() + "."); } usedParentOutPorts.add(destNe.getName()); @@ -983,14 +974,14 @@ public void checkLiftContract(LiftContractStatement lcst) { if (isIn) { if (!usedParentInPorts.contains(feat.getName())) { error(lcst, - "'lift contract;' statement is not allowed in component implementation whithout connection from input " + "'lift contract;' statement is not allowed in component implementation without connection from input " + feat.getQualifiedName() + "."); } } else { if (!usedParentOutPorts.contains(feat.getName())) { error(lcst, - "'lift contract;' statement is not allowed in component implementation whithout connection to output " + "'lift contract;' statement is not allowed in component implementation without connection to output " + feat.getQualifiedName() + "."); } @@ -1012,14 +1003,14 @@ public void checkLiftContract(LiftContractStatement lcst) { if (isIn) { if (!usedChildInPorts.contains(feat.getName())) { error(lcst, - "'lift contract;' statement is not allowed in component implementation whithout connection into " + "'lift contract;' statement is not allowed in component implementation without connection into " + feat.getQualifiedName() + "."); } } else { if (!usedChildOutPorts.contains(feat.getName())) { error(lcst, - "'lift contract;' statement is not allowed in component implementation whithout connection out of " + "'lift contract;' statement is not allowed in component implementation without connection out of " + feat.getQualifiedName() + "."); } @@ -1032,7 +1023,7 @@ public void checkLiftContract(LiftContractStatement lcst) { } else { error(lcst, - "'lift contract;' statement is not allowed in component implementation whithout exactly one subcomponent."); + "'lift contract;' statement is not allowed in component implementation without exactly one subcomponent."); } @@ -1075,11 +1066,6 @@ public void checkAssert(AssertStatement asser) { public void checkAADLEnumerator(EnumLitExpr aadlEnum) { DoubleDotRef enumType = aadlEnum.getEnumType(); NamedElement enumTypeNamedElement = enumType.getElm(); -// ======= -// public void checkAADLEnumerator(AADLEnumerator aadlEnum) { -// DoubleDotRef enumType = aadlEnum.getEnumType(); -// NamedElement enumTypeNamedElement = enumType.getElm(); -// >>>>>>> origin/develop if (!AgreeAADLEnumerationUtils.isAADLEnumeration(enumTypeNamedElement)) { error(enumType, "AADL Enumerations must refer to a Data Type with \"Enum\" data representation " + "property and have an \"Enumerators\' property value list."); @@ -1157,27 +1143,17 @@ public void checkPeriodicStatement(PeriodicStatement statement) { TypeDef eventType = AgreeTypeSystem.infer(event); if (!AgreeTypeSystem.typesEqual(AgreeTypeSystem.Prim.BoolTypeDef, eventType)) { - error(event, "Expression is of type '" + eventType + "' but must be of type 'bool'"); + error(event, "Expression is of type '" + nameOfTypeDef(eventType) + "' but must be of type 'bool'"); } if (jitter != null) { if (!(jitter instanceof RealLitExpr || isTimingConst(jitter))) { - error(jitter, "The specified jitter must be a real literal"); - } else { - Double val = getRealConstVal(jitter); - if (val < 0) { - error(jitter, "The specified jitter must be positive"); - } + error(jitter, "The specified jitter must be a positive real literal"); } } if (!(period instanceof RealLitExpr || isTimingConst(period))) { - error(period, "The specified period must be a real literal"); - } else { - Double val = getRealConstVal(period); - if (val < 0) { - error(period, "The specified period must be positive"); - } + error(period, "The specified period must be a positive real literal"); } } @@ -1206,27 +1182,17 @@ public void checkSporadicStatement(SporadicStatement statement) { TypeDef eventType = AgreeTypeSystem.infer(event); if (!AgreeTypeSystem.typesEqual(AgreeTypeSystem.Prim.BoolTypeDef, eventType)) { - error(event, "Expression is of type '" + eventType + "' but must be of type 'bool'"); + error(event, "Expression is of type '" + nameOfTypeDef(eventType) + "' but must be of type 'bool'"); } if (jitter != null) { if (!(jitter instanceof RealLitExpr || isTimingConst(jitter))) { - error(jitter, "The specified jitter must be a real literal"); - } else { - Double val = getRealConstVal(jitter); - if (val < 0) { - error(jitter, "The specified jitter must be positive"); - } + error(jitter, "The specified jitter must be a positive real literal"); } } if (!(iat instanceof RealLitExpr || isTimingConst(iat))) { - error(iat, "The specified interarrival time must be a real literal"); - } else { - Double val = getRealConstVal(iat); - if (val < 0) { - error(iat, "The specified interarrival time must be positive"); - } + error(iat, "The specified interarrival time must be a positive real literal"); } } @@ -1248,17 +1214,19 @@ public void checkWhenHoldsStatement(WhenHoldsStatement when) { } } } else { - error(when, "Statement most of a cause interval"); + error(when, "Statement must have a cause interval"); } TypeDef type = AgreeTypeSystem.infer(condition); if (!AgreeTypeSystem.typesEqual(AgreeTypeSystem.Prim.BoolTypeDef, type)) { error(condition, - "The condition of a when statement is of type '" + type + "'" + " but must be of type 'bool'"); + "The condition of a when statement is of type '" + nameOfTypeDef(type) + "'" + + " but must be of type 'bool'"); } type = AgreeTypeSystem.infer(event); if (!AgreeTypeSystem.typesEqual(AgreeTypeSystem.Prim.BoolTypeDef, type)) { - error(event, "The effect of a when statement is of type '" + type + "'" + " but must be of type 'bool'"); + error(event, "The effect of a when statement is of type '" + nameOfTypeDef(type) + "'" + + " but must be of type 'bool'"); } } @@ -1274,17 +1242,20 @@ public void checkWhenOccursStatment(WhenOccursStatment when) { TypeDef type = AgreeTypeSystem.infer(condition); if (!AgreeTypeSystem.typesEqual(AgreeTypeSystem.Prim.BoolTypeDef, type)) { error(condition, - "The condition of the 'when' statement is of type '" + type + "'" + " but must be of type 'bool'"); + "The condition of the 'when' statement is of type '" + nameOfTypeDef(type) + "'" + + " but must be of type 'bool'"); } type = AgreeTypeSystem.infer(event); if (!AgreeTypeSystem.typesEqual(AgreeTypeSystem.Prim.BoolTypeDef, type)) { error(event, - "The effect of the 'when' statement is of type '" + type + "'" + " but must be of type 'bool'"); + "The effect of the 'when' statement is of type '" + nameOfTypeDef(type) + "'" + + " but must be of type 'bool'"); } type = AgreeTypeSystem.infer(times); if (!AgreeTypeSystem.typesEqual(AgreeTypeSystem.Prim.IntTypeDef, type)) { error(event, - "The 'times' of the 'when' statement is of type '" + type + "'" + " but must be of type 'int'"); + "The 'times' of the 'when' statement is of type '" + nameOfTypeDef(type) + "'" + + " but must be of type 'int'"); } } @@ -1300,12 +1271,14 @@ public void checkWheneverOccursStatement(WheneverOccursStatement whenever) { TypeDef type = AgreeTypeSystem.infer(cause); if (!AgreeTypeSystem.typesEqual(AgreeTypeSystem.Prim.BoolTypeDef, type)) { error(cause, - "The cause of the 'whenever' statement is of type '" + type + "' " + "but must be of type 'bool'"); + "The cause of the 'whenever' statement is of type '" + nameOfTypeDef(type) + "' " + + "but must be of type 'bool'"); } type = AgreeTypeSystem.infer(effect); if (!AgreeTypeSystem.typesEqual(AgreeTypeSystem.Prim.BoolTypeDef, type)) { error(effect, - "The effect of the 'whenever' statement is of type '" + type + "' " + "but must be of type 'bool'"); + "The effect of the 'whenever' statement is of type '" + nameOfTypeDef(type) + "' " + + "but must be of type 'bool'"); } } @@ -1320,12 +1293,14 @@ public void checkWheneverBecomesTrueStatement(WheneverBecomesTrueStatement whene TypeDef type = AgreeTypeSystem.infer(cause); if (!AgreeTypeSystem.typesEqual(AgreeTypeSystem.Prim.BoolTypeDef, type)) { error(cause, - "The cause of the 'whenever' statement is of type '" + type + "' " + "but must be of type 'bool'"); + "The cause of the 'whenever' statement is of type '" + nameOfTypeDef(type) + "' " + + "but must be of type 'bool'"); } type = AgreeTypeSystem.infer(effect); if (!AgreeTypeSystem.typesEqual(AgreeTypeSystem.Prim.BoolTypeDef, type)) { error(effect, - "The effect of the 'whenever' statement is of type '" + type + "' " + "but must be of type 'bool'"); + "The effect of the 'whenever' statement is of type '" + nameOfTypeDef(type) + "' " + + "but must be of type 'bool'"); } } @@ -1340,12 +1315,14 @@ public void checkWheneverHoldsStatement(WheneverHoldsStatement whenever) { TypeDef type = AgreeTypeSystem.infer(cause); if (!AgreeTypeSystem.typesEqual(AgreeTypeSystem.Prim.BoolTypeDef, type)) { error(cause, - "The cause of the 'whenever' statement is of type '" + type + "' " + "but must be of type 'bool'"); + "The cause of the 'whenever' statement is of type '" + nameOfTypeDef(type) + "' " + + "but must be of type 'bool'"); } type = AgreeTypeSystem.infer(effect); if (!AgreeTypeSystem.typesEqual(AgreeTypeSystem.Prim.BoolTypeDef, type)) { error(effect, - "The effect of the 'whenever' statement is of type '" + type + "' " + "but must be of type 'bool'"); + "The effect of the 'whenever' statement is of type '" + nameOfTypeDef(type) + "' " + + "but must be of type 'bool'"); } } @@ -1362,18 +1339,22 @@ public void checkWheneverImpliesStatement(WheneverImpliesStatement whenever) { TypeDef type = AgreeTypeSystem.infer(cause); if (!AgreeTypeSystem.typesEqual(AgreeTypeSystem.Prim.BoolTypeDef, type)) { error(cause, - "The cause of the 'whenever' statement is of type '" + type + "' " + "but must be of type 'bool'"); + "The cause of the 'whenever' statement is of type '" + nameOfTypeDef(type) + "' " + + "but must be of type 'bool'"); } type = AgreeTypeSystem.infer(lhs); if (!AgreeTypeSystem.typesEqual(AgreeTypeSystem.Prim.BoolTypeDef, type)) { - error(lhs, "The left hand side of the 'implies' of the 'whenever' statement is of type '" + type + "' " + error(lhs, + "The left hand side of the 'implies' of the 'whenever' statement is of type '" + nameOfTypeDef(type) + + "' " + "but must be of type 'bool'"); } type = AgreeTypeSystem.infer(rhs); if (!AgreeTypeSystem.typesEqual(AgreeTypeSystem.Prim.BoolTypeDef, type)) { - error(lhs, "The rhs hand side of the 'implies' of the 'whenever' statement is of type '" + type + "' " + error(lhs, "The rhs hand side of the 'implies' of the 'whenever' statement is of type '" + + nameOfTypeDef(type) + "' " + "but must be of type 'bool'"); } } @@ -1388,7 +1369,7 @@ public void checkTimeInterval(TimeInterval interval) { } if (!(higher instanceof RealLitExpr || isTimingConst(higher))) { - error(higher, "higher interval must be a real valued literal"); + error(higher, "Higher interval must be a real valued literal"); } } @@ -1484,13 +1465,13 @@ public void checkUnaryExpr(UnaryExpr unaryExpr) { case "-": if (!AgreeTypeSystem.typesEqual(AgreeTypeSystem.Prim.IntTypeDef, typeRight) && !AgreeTypeSystem.typesEqual(AgreeTypeSystem.Prim.RealTypeDef, typeRight)) { - error(unaryExpr, "right side of unary expression '" + op + "' is of type '" + typeRight + error(unaryExpr, "right side of unary expression '" + op + "' is of type '" + nameOfTypeDef(typeRight) + "' but must be of type 'int' or 'real'"); } break; case "not": if (!AgreeTypeSystem.typesEqual(AgreeTypeSystem.Prim.BoolTypeDef, typeRight)) { - error(unaryExpr, "right side of unary expression '" + op + "' is of type '" + typeRight + error(unaryExpr, "right side of unary expression '" + op + "' is of type '" + nameOfTypeDef(typeRight) + "' but must be of type 'bool'"); } break; @@ -1508,7 +1489,7 @@ public void checkPropertyStatement(PropertyStatement propStat) { TypeDef exprType = AgreeTypeSystem.infer(propStat.getExpr()); if (!AgreeTypeSystem.typesEqual(AgreeTypeSystem.Prim.BoolTypeDef, exprType)) { - error(propStat, "Property statement '" + propStat.getName() + "' is of type '" + exprType + error(propStat, "Property statement '" + propStat.getName() + "' is of type '" + nameOfTypeDef(exprType) + "' but must be of type 'bool'"); } @@ -1531,7 +1512,6 @@ public void checkRecordUpdateExpr(RecordUpdateExpr upExpr) { return; } - checkTypeExists(upExpr.getRecord()); TypeDef recordType = AgreeTypeSystem.infer(upExpr.getRecord()); if (recordType instanceof RecordTypeDef) { @@ -1539,7 +1519,6 @@ public void checkRecordUpdateExpr(RecordUpdateExpr upExpr) { // scoping should ensure the key is a proper Arg Arg arg = (Arg) upExpr.getKey(); TypeDef keyType = AgreeTypeSystem.typeDefFromType(arg.getType()); - checkTypeExists(upExpr.getExpr()); TypeDef expType = AgreeTypeSystem.infer(upExpr.getExpr()); if (!AgreeTypeSystem.typesEqual(keyType, expType)) { @@ -1555,17 +1534,11 @@ public void checkRecordUpdateExpr(RecordUpdateExpr upExpr) { } @Check(CheckType.FAST) - public void checkArrayLiteralExpr(ArrayLiteralExpr alit) { -// ======= -// public void checkRecordType(RecordType recType) { -// DoubleDotRef recId = recType.getRecord(); -// NamedElement finalId = recId.getElm(); -// >>>>>>> origin/develop - List exprs = alit.getElems(); - if (exprs.size() == 0) { + if (exprs.isEmpty()) { error(alit, "Array literal must have at least one element"); + return; } Expr target = exprs.get(0); @@ -1575,7 +1548,8 @@ public void checkArrayLiteralExpr(ArrayLiteralExpr alit) { checkTypeExists(e); TypeDef t2 = AgreeTypeSystem.infer(e); if (!AgreeTypeSystem.typesEqual(t1, t2)) { - error(e, "type of element must be " + nameOfTypeDef(t1) + ", but has type " + nameOfTypeDef(t2)); + error(e, "type of array element must be '" + nameOfTypeDef(t1) + "', but has type '" + nameOfTypeDef(t2) + + "'"); } } @@ -1596,7 +1570,8 @@ public void checkArrayUpdateExpr(ArrayUpdateExpr arrup) { TypeDef elmType = AgreeTypeSystem.infer(exprs.get(0)); if (!AgreeTypeSystem.typesEqual(elmType, t)) { error(exprs.get(0), - "type of element must be " + nameOfTypeDef(elmType) + ", but has type " + nameOfTypeDef(t)); + "type of array element must be '" + nameOfTypeDef(t) + "', but has type '" + + nameOfTypeDef(elmType) + "'"); } } else { @@ -1614,7 +1589,7 @@ public void checkArraySubExpr(ArraySubExpr asub) { checkTypeExists(index); TypeDef indexType = AgreeTypeSystem.infer(index); if (!AgreeTypeSystem.typesEqual(indexType, AgreeTypeSystem.Prim.IntTypeDef)) { - error(index, "index must be an int"); + error(index, "index must be of type 'int'"); } if (arrType instanceof ArrayTypeDef) { @@ -1681,44 +1656,26 @@ private BigInteger evaluateIndexNamedElement(NamedElement namedElement) { @Check(CheckType.FAST) public void checkRecordLitExpr(RecordLitExpr recExpr) { DoubleDotRef recType = recExpr.getRecordType(); -// ======= -// DoubleDotRef recType = recExpr.getRecord(); -// >>>>>>> origin/develop List defArgs = getArgNames(recType); EList exprArgs = recExpr.getArgs(); EList argExprs = recExpr.getArgExpr(); - NamedElement finalId = recExpr.getRecordType().getElm(); - if (!(finalId instanceof DataImplementation) && !(finalId instanceof RecordDef)) { - error(recType, "types must be record definition or data implementation"); -// ======= -// DoubleDotRef recId = recExpr.getRecord(); -// NamedElement finalId = recId.getElm(); -// -// if (!(finalId instanceof DataImplementation) && !(finalId instanceof RecordDefExpr)) { -// error(recId, "types must be record definition or data implementation"); -// } -// -// if (finalId instanceof DataImplementation) { -// dataImplCycleCheck(recId); -// >>>>>>> origin/develop - } - if (exprArgs.size() != defArgs.size()) { error(recExpr, "Incorrect number of arguments"); return; } - for (NamedElement argDefName : defArgs) { + for (NamedElement argDef : defArgs) { boolean foundArg = false; for (NamedElement argExprEl : exprArgs) { - if (argExprEl.getName().equals(argDefName.getName())) { + if (argExprEl.getName().equals(argDef.getName())) { foundArg = true; break; } } if (!foundArg) { - error(recExpr, "No assignment to defined variable '" + argDefName + "' in record expression."); + error(recExpr, + "No assignment to defined variable '" + argDef.getName() + "' in record expression."); } } @@ -1728,13 +1685,11 @@ public void checkRecordLitExpr(RecordLitExpr recExpr) { NamedElement actArg = recExpr.getArgs().get(i); String actArgName = actArg.getName(); TypeDef defType = argNameMap.get(actArgName); - - checkTypeExists(argExprs.get(i)); TypeDef exprType = AgreeTypeSystem.infer(argExprs.get(i)); if (!AgreeTypeSystem.typesEqual(defType, exprType)) { error(recExpr, "The expression assigned to '" + actArgName + "' does not match its definition type of '" - + defType + "'"); + + nameOfTypeDef(defType) + "'"); } } } @@ -1742,11 +1697,6 @@ public void checkRecordLitExpr(RecordLitExpr recExpr) { private List getArgNames(DoubleDotRef recType) { NamedElement rec = recType.getElm(); -// ======= -// private List getArgNames(DoubleDotRef recId) { -// -// NamedElement rec = recId.getElm(); -// >>>>>>> origin/develop List names = new ArrayList<>(); if (rec instanceof RecordDef) { @@ -1770,12 +1720,6 @@ private Map getFieldTypes(DoubleDotRef recType) { NamedElement rec = recType.getElm(); Map typeMap = new HashMap<>(); -// ======= -// private Map getArgNameMap(DoubleDotRef recId) { -// -// NamedElement rec = recId.getElm(); -// Map typeMap = new HashMap<>(); -// >>>>>>> origin/develop if (rec instanceof RecordDef) { RecordDef recDef = (RecordDef) rec; @@ -1794,26 +1738,25 @@ private Map getFieldTypes(DoubleDotRef recType) { return typeMap; } -// ======= -//// private List getArgTypes(NestedDotID recId){ -//// -//// NamedElement rec = getFinalNestId(recId); -//// List types = new ArrayList(); -//// -//// if(rec instanceof RecordDefExpr){ -//// RecordDefExpr recDef = (RecordDefExpr)rec; -//// for(Arg arg : recDef.getArgs()){ -//// types.add(getAgreeType(arg.getType())); -//// } -//// }else if(rec instanceof FeatureGroupType){ -//// FeatureGroupType featGroup = (FeatureGroupType)rec; -//// for(Feature feat : featGroup.getAllFeatures()){ -//// types.add(getAgreeType(feat)); -//// } -//// } -//// -//// return types; -//// } +// private List getArgTypes(NestedDotID recId){ +// +// NamedElement rec = getFinalNestId(recId); +// List types = new ArrayList(); +// +// if(rec instanceof RecordDefExpr){ +// RecordDefExpr recDef = (RecordDefExpr)rec; +// for(Arg arg : recDef.getArgs()){ +// types.add(getAgreeType(arg.getType())); +// } +// }else if(rec instanceof FeatureGroupType){ +// FeatureGroupType featGroup = (FeatureGroupType)rec; +// for(Feature feat : featGroup.getAllFeatures()){ +// types.add(getAgreeType(feat)); +// } +// } +// +// return types; +// } // // private void dataImplCycleCheck(NestedDotID dataID) { // NamedElement finalId = dataID.getBase(); @@ -1859,7 +1802,6 @@ private Map getFieldTypes(DoubleDotRef recType) { // } while (!prevClosure.equals(dataClosure)); // // } -// >>>>>>> origin/develop @Check(CheckType.FAST) public void checkRecordDefExpr(RecordDef recordDef) { @@ -1872,12 +1814,6 @@ public void checkRecordDefExpr(RecordDef recordDef) { if (type instanceof DoubleDotRef) { NamedElement finalId = ((DoubleDotRef) type).getElm(); -// ======= -// if (type instanceof RecordType) { -// DoubleDotRef subRec = ((RecordType) type).getRecord(); -// NamedElement finalId = subRec.getElm(); -// >>>>>>> origin/develop - if (finalId instanceof RecordDef) { recordClosure.add((RecordDef) finalId); } @@ -1900,13 +1836,6 @@ public void checkRecordDefExpr(RecordDef recordDef) { NamedElement subFinalEl = ((DoubleDotRef) type).getElm(); if (subFinalEl instanceof RecordDef) { recordClosure.add((RecordDef) subFinalEl); -// ======= -// if (type instanceof RecordType) { -// DoubleDotRef subRecId = ((RecordType) type).getRecord(); -// NamedElement subFinalEl = subRecId.getElm(); -// if (subFinalEl instanceof RecordDefExpr) { -// recordClosure.add((RecordDefExpr) subFinalEl); -// >>>>>>> origin/develop } } } @@ -1920,49 +1849,20 @@ public void checkConstStatement(ConstStatement constStat) { TypeDef actual = AgreeTypeSystem.infer(constStat.getExpr()); if (!AgreeTypeSystem.typesEqual(expected, actual)) { - error(constStat, "The assumed type of constant statement '" + constStat.getName() + "' is '" + expected - + "' but the actual type is '" + actual + "'"); + error(constStat, "The assumed type of constant statement '" + constStat.getName() + "' is '" + + nameOfTypeDef(expected) + "' but the actual type is '" + nameOfTypeDef(actual) + "'"); } - // check for constant cycles - Set constClosure = new HashSet<>(); - Set prevClosure; - constClosure.add(constStat); - - // quick and dirty cycle check - do { - prevClosure = new HashSet<>(constClosure); - for (ConstStatement constFrontElem : prevClosure) { - List nestIds = EcoreUtil2.getAllContentsOfType(constFrontElem, SelectionExpr.class); - for (Expr nestId : nestIds) { - while (nestId instanceof SelectionExpr) { - NamedElement base = ((SelectionExpr) nestId).getField(); - if (base instanceof ConstStatement) { - ConstStatement closConst = (ConstStatement) base; - if (closConst.equals(constStat)) { - error(constStat, "The expression for constant statment '" + constStat.getName() - + "' is part of a cyclic definition"); - break; - } - constClosure.add(closConst); - } - nestId = ((SelectionExpr) nestId).getTarget(); - } - - NamedElement base = ((NamedElmExpr) nestId).getElm(); - if (base instanceof ConstStatement) { - ConstStatement closConst = (ConstStatement) base; - if (closConst.equals(constStat)) { - error(constStat, "The expression for constant statment '" + constStat.getName() - + "' is part of a cyclic definition"); - break; - } - constClosure.add(closConst); - } - - } + ExprCycleVisitor cycleVisitor = new ExprCycleVisitor(); + Set cycleObjects = cycleVisitor.doSwitch(constStat.getExpr()); + if (cycleObjects == null) { + throw new IllegalArgumentException("something went wrong with the cycle checker"); + } + for (EObject obj : cycleObjects) { + if (obj.equals(constStat)) { + error(constStat.getExpr(), "Cyclic reference to variable '" + constStat.getName() + "'"); } - } while (!prevClosure.equals(constClosure)); + } for (Expr e : EcoreUtil2.getAllContentsOfType(constStat.getExpr(), Expr.class)) { if (!exprIsConstant(e)) { @@ -2024,7 +1924,6 @@ public void checkNamedElement(NamedElement namedEl) { if (container instanceof ComponentImplementation) { compImpl = (ComponentImplementation) container; type = compImpl.getType(); - checkDupNames(namedEl, type, compImpl); } else if (container instanceof ComponentType) { type = (ComponentType) container; } @@ -2037,47 +1936,18 @@ public void checkNamedElement(NamedElement namedEl) { error(namedEl, "Feature of the same name ('" + namedEl.getName() + "') in component type"); } } - } - - // check name space collision with enumerated types - - } - - private void checkDupNames(NamedElement namedEl, ComponentType type, ComponentImplementation compImpl) { - NamedElement match = matchedInAgreeAnnex(type, namedEl.getName()); - - if (match != null) { - error(match, "Element of the same name ('" + namedEl.getName() + "') in component implementation '" - + compImpl.getName() + "'"); - error(namedEl, "Element of the same name ('" + namedEl.getName() + "') in component type"); - } - - for (Subcomponent sub : compImpl.getAllSubcomponents()) { - if (namedEl.getName().equals(sub.getName())) { - error(sub, "Element of the same name ('" + namedEl.getName() + "') in AGREE Annex in '" - + compImpl.getName() + "'"); - error(namedEl, - "Subcomponent of the same name ('" + namedEl.getName() + "') in component implementation"); - } - } - } - - private NamedElement matchedInAgreeAnnex(ComponentClassifier compClass, String name) { - - for (AnnexSubclause subClause : AnnexUtil.getAllAnnexSubclauses(compClass, - AgreePackage.eINSTANCE.getAgreeSubclause())) { - if (subClause instanceof AgreeSubclause) { - AgreeContract contr = (AgreeContract) subClause.getChildren().get(0); - for (EObject obj : contr.getChildren()) { - if (obj instanceof NamedElement) { - if (name.equals(((NamedElement) obj).getName())) { - return (NamedElement) obj; - } + if (compImpl != null) { + for (Subcomponent sub : compImpl.getAllSubcomponents()) { + if (namedEl.getName().equals(sub.getName())) { + error(sub, "Element of the same name ('" + namedEl.getName() + "') in AGREE Annex in '" + + (compImpl == null ? type.getName() : compImpl.getName()) + "'"); + error(namedEl, "Subcomponent of the same name ('" + namedEl.getName() + + "') in component implementation"); } } } } - return null; + // TODO: check name space collision with enumerated types } private boolean argsContainRangeValue(List args) { @@ -2101,14 +1971,15 @@ private void checkMultiAssignEq(EObject src, List lhsArgs, Expr rhsExpr) { if (lhsArgs.size() == 1) { // we should only need to check for cycles for single equations - String name = lhsArgs.get(0).getName(); - ExprCycleVisitor cycleVisitor = new ExprCycleVisitor(name); + ExprCycleVisitor cycleVisitor = new ExprCycleVisitor(); Set cycleObjects = cycleVisitor.doSwitch(rhsExpr); if (cycleObjects == null) { throw new IllegalArgumentException("something went wrong with the cycle checker"); } for (EObject obj : cycleObjects) { - error(obj, "Cyclic reference to variable '" + name + "'"); + if (obj.equals(lhsArgs.get(0))) { + error(rhsExpr, "Cyclic reference to variable '" + lhsArgs.get(0).getName() + "'"); + } } } @@ -2214,8 +2085,8 @@ public void checkNameOverlap(AgreeContract contract) { break; } if (conn0.equals(conn1)) { - error(connStat0, "Multiple connection overrides for connection: '" + conn0.getName() + "'"); - error(connStat1, "Multiple connection overrides for connection: '" + conn1.getName() + "'"); + error(connStat0, "Multiple connection overrides for connection '" + conn0.getName() + "'"); + error(connStat1, "Multiple connection overrides for connection '" + conn1.getName() + "'"); } } } @@ -2231,12 +2102,8 @@ public void checkNameOverlap(AgreeContract contract) { for (NamedElement e : es) { if (!(e.eContainer() instanceof NodeDef || e instanceof NamedSpecStatement)) { // ignore elements in node defs - if (parentNames.contains(e.getName())) { -// ======= -// if (!(e.eContainer() instanceof NodeDefExpr)) { // ignore elements in node defs -// if (e.getName() != null && parentNames.contains(e.getName())) { -// >>>>>>> origin/develop - error(e, e.getName() + " already defined in component type contract"); + if (e.getName() != null && parentNames.contains(e.getName())) { + error(e, "'" + e.getName() + "' already defined in component type contract"); } } } @@ -2299,7 +2166,8 @@ public void checkNodeEq(NodeEq nodeEq) { public void checkNodeLemma(NodeLemma nodeLemma) { TypeDef exprType = AgreeTypeSystem.infer(nodeLemma.getExpr()); if (!AgreeTypeSystem.typesEqual(AgreeTypeSystem.Prim.BoolTypeDef, exprType)) { - error(nodeLemma, "Expression for lemma statement is of type '" + exprType + "' but must be of type 'bool'"); + error(nodeLemma, "Expression for lemma statement is of type '" + nameOfTypeDef(exprType) + + "' but must be of type 'bool'"); } } @@ -2382,6 +2250,19 @@ public static boolean isInLinearizationBody(Expr expr) { return result; } + public static boolean isInConstBody(Expr expr) { + boolean result = false; + EObject current = expr; + while (current != null && current instanceof Expr) { + EObject container = current.eContainer(); + if (container instanceof ConstStatement) { + result = ((ConstStatement) container).getExpr().equals(current); + } + current = container; + } + return result; + } + @Check(CheckType.FAST) public void checkLinearizationDefExpr(LinearizationDef linDefExpr) { // Check that allowable number of formal args are defined @@ -2393,7 +2274,7 @@ public void checkLinearizationDefExpr(LinearizationDef linDefExpr) { for (Arg arg : linDefExpr.getArgs()) { TypeDef argType = AgreeTypeSystem.typeDefFromType(arg.getType()); if (!AgreeTypeSystem.typesEqual(argType, AgreeTypeSystem.Prim.RealTypeDef)) { - error(arg, "Linearizations formal arguments must be of real type, but found type " + argType); + error(arg, "Linearizations formal arguments must be of 'real' type, but found type '" + nameOfTypeDef(argType) + "'."); } } @@ -2410,10 +2291,11 @@ public void checkLinearizationDefExpr(LinearizationDef linDefExpr) { TypeDef precisionExprType = AgreeTypeSystem.infer(precisionExpr); if (!AgreeTypeSystem.typesEqual(AgreeTypeSystem.Prim.RealTypeDef, precisionExprType)) { error(precisionExpr, - "Linearization precision must be of real type, but found type " + precisionExprType); + "Linearization precision must be of 'real' type, but found type '" + + nameOfTypeDef(precisionExprType) + "'."); } if (!exprIsConst(precisionExpr)) { - error(precisionExpr, "Linearization precision must be constant expression of real type" + error(precisionExpr, "Linearization precision must be constant expression of 'real' type" + ", found non-constant expression."); } } @@ -2421,7 +2303,7 @@ public void checkLinearizationDefExpr(LinearizationDef linDefExpr) { @Check(CheckType.FAST) public void checkLinearizationInterval(LinearizationInterval linInterval) { - final String message = "Linearization interval endpoints must be constant expressions of real type"; + final String message = "Linearization interval endpoints must be constant expressions of 'real' type"; Expr startExpr = linInterval.getStart(); Expr endExpr = linInterval.getEnd(); TypeDef startExprType = AgreeTypeSystem.infer(startExpr); @@ -2429,17 +2311,17 @@ public void checkLinearizationInterval(LinearizationInterval linInterval) { // The type of the interval start and end must be of real type if (!AgreeTypeSystem.typesEqual(AgreeTypeSystem.Prim.RealTypeDef, startExprType)) { - error(startExpr, message + ", found type " + startExprType + "."); + error(startExpr, message + ", found type '" + nameOfTypeDef(startExprType) + "'."); } if (!AgreeTypeSystem.typesEqual(AgreeTypeSystem.Prim.RealTypeDef, endExprType)) { - error(endExpr, message + ", found type " + endExprType + "."); + error(endExpr, message + ", found type '" + nameOfTypeDef(endExprType) + "'."); } // The interval start and end expressions must be constant if (!exprIsConst(startExpr)) { - error(endExpr, message + ", found non-constant expression."); + error(startExpr, message + ", found non-constant expression."); } - if (!exprIsConst(startExpr)) { + if (!exprIsConst(endExpr)) { error(endExpr, message + ", found non-constant expression."); } } @@ -2462,7 +2344,7 @@ public void checkGetPropertyExpr(GetPropertyExpr getPropExpr) { NamedElement prop = getPropExpr.getProp(); if (!(prop instanceof Property || prop instanceof PropertyConstant)) { - error(getPropExpr.getProp(), "Expected AADL property or property constant"); + error(getPropExpr, "Expected AADL property or property constant"); } if (prop instanceof Property) { @@ -2485,11 +2367,13 @@ public void checkPrevExpr(PrevExpr prevExpr) { if (!AgreeTypeSystem.typesEqual(initType, delayType)) { error(prevExpr, "The first and second arguments of the 'prev' function are of non-matching types '" - + delayType + "' and '" + initType + "'"); + + nameOfTypeDef(delayType) + "' and '" + nameOfTypeDef(initType) + "'."); } if (isInLinearizationBody(prevExpr)) { error(prevExpr, "'prev' expressions are not allowed in linearization body expressions."); + } else if (isInConstBody(prevExpr)) { + error(prevExpr, "'prev' expressions are not allowed in constant expressions."); } } @@ -2504,13 +2388,6 @@ public List typeDefsFromArgs(List args) { public void checkInputsVsActuals(CallExpr call) { DoubleDotRef dotId = call.getRef(); NamedElement namedEl = dotId.getElm(); -// ======= -// public void checkInputsVsActuals(FnCallExpr fnCall) { -// -// // if the id has a 'tag' then it is using a resrved variable -// -// NamedElement namedEl = fnCall.getFn().getBase(); -// >>>>>>> origin/develop if (!(namedEl instanceof Abstraction)) { // this error will be caught elsewhere @@ -2567,26 +2444,18 @@ public void checkInputsVsActuals(CallExpr call) { TypeDef defType = inDefTypes.get(i); if (!AgreeTypeSystem.typesEqual(defType, callType)) { - error(call, "Argument " + i + " of function call '" + callName + "' is of type '" + callType - + "' but must be of type '" + defType + "'"); + error(call, "Argument " + i + " of function call '" + callName + "' is of type '" + + nameOfTypeDef(callType) + "' but must be of type '" + nameOfTypeDef(defType) + "'."); } } } @Check(CheckType.FAST) - public void checkCallExpr(CallExpr call) { NamedElement fn = call.getRef().getElm(); if (isInLinearizationBody(call)) { if (fn instanceof NodeDef) { error(call, "Node definitions cannot be applied in a linearization definition"); -// ======= -// public void checkFnCallExpr(FnCallExpr fnCall) { -// NamedElement fn = (fnCall.getFn().getBase()); -// if (isInLinearizationBody(fnCall)) { -// if (fn instanceof NodeDefExpr) { -// error(fnCall, "Node definitions cannot be applied in a linearization definition"); -// >>>>>>> origin/develop } } else { if (fn instanceof LibraryFnDef) { @@ -2608,7 +2477,7 @@ public void checkFnDefExpr(FnDef fnDef) { TypeDef exprType = AgreeTypeSystem.infer(fnDef.getExpr()); if (!AgreeTypeSystem.typesEqual(exprType, fnType)) { error(fnDef, "Function '" + fnDef.getName() + "' is of type '" + nameOfTypeDef(fnType) - + "' but its expression is of type '" + nameOfTypeDef(exprType) + "'"); + + "' but its expression is of type '" + nameOfTypeDef(exprType) + "'."); } } @@ -2659,19 +2528,22 @@ public void checkIfThenElseExpr(IfThenElseExpr expr) { TypeDef elseType = AgreeTypeSystem.infer(expr.getC()); if (!AgreeTypeSystem.typesEqual(AgreeTypeSystem.Prim.BoolTypeDef, condType)) { - error(expr, "The condition of the if statement is of type '" + condType + "' but must be of type 'bool'"); + error(expr, "The condition of the if statement is of type '" + nameOfTypeDef(condType) + + "' but must be of type 'bool'"); } if (!AgreeTypeSystem.typesEqual(elseType, thenType)) { - error(expr, "The 'then' and 'else' expressions are of non-matching types '" + thenType + "' and '" - + elseType + "'"); + error(expr, "The 'then' and 'else' expressions are of non-matching types '" + nameOfTypeDef(thenType) + + "' and '" + nameOfTypeDef(elseType) + "'"); } } @Check(CheckType.FAST) public void checkPreExpr(PreExpr expr) { if (isInLinearizationBody(expr)) { - error(expr, "'pre' expressions not allowed in linearization body expressions"); + error(expr, "'pre' expressions are not allowed in linearization body expressions."); + } else if (isInConstBody(expr)) { + error(expr, "'pre' expressions are not allowed in constant expressions."); } } @@ -2695,6 +2567,8 @@ public void checkBinaryExpr(BinaryExpr binExpr) { case "->": if (isInLinearizationBodyExpr) { error(binExpr, "Arrow '->' expressions are not allowed in linearization body expressions."); + } else if (isInConstBody(binExpr)) { + error(binExpr, "Arrow '->' expressions are not allowed in constant expressions."); } else { if (!AgreeTypeSystem.typesEqual(typeRight, typeLeft)) { error(binExpr, @@ -2757,12 +2631,12 @@ public void checkBinaryExpr(BinaryExpr binExpr) { if (!AgreeTypeSystem.typesEqual(AgreeTypeSystem.Prim.IntTypeDef, typeLeft) && !AgreeTypeSystem.typesEqual(AgreeTypeSystem.Prim.RealTypeDef, typeLeft)) { error(binExpr, "left side of binary expression '" + op + "' is of type '" + nameOfTypeDef(typeLeft) - + "' but must be of type" + "'int' or 'real'"); + + "' but must be of type " + "'int' or 'real'"); } if (!AgreeTypeSystem.typesEqual(AgreeTypeSystem.Prim.IntTypeDef, typeRight) && !AgreeTypeSystem.typesEqual(AgreeTypeSystem.Prim.RealTypeDef, typeRight)) { error(binExpr, "right side of binary expression '" + op + "' is of type '" - + nameOfTypeDef(typeRight) + "' but must be of type" + "'int' or 'real'"); + + nameOfTypeDef(typeRight) + "' but must be of type " + "'int' or 'real'"); } } return; @@ -2778,12 +2652,12 @@ public void checkBinaryExpr(BinaryExpr binExpr) { if (!AgreeTypeSystem.typesEqual(AgreeTypeSystem.Prim.IntTypeDef, typeLeft) && !AgreeTypeSystem.typesEqual(AgreeTypeSystem.Prim.RealTypeDef, typeLeft)) { error(binExpr, "left side of binary expression '" + op + "' is of type '" + nameOfTypeDef(typeLeft) - + "' but must be of type" + "'int' or 'real'"); + + "' but must be of type " + "'int' or 'real'"); } if (!AgreeTypeSystem.typesEqual(AgreeTypeSystem.Prim.IntTypeDef, typeRight) && !AgreeTypeSystem.typesEqual(AgreeTypeSystem.Prim.RealTypeDef, typeRight)) { error(binExpr, "right side of binary expression '" + op + "' is of type '" + nameOfTypeDef(typeRight) - + "' but must be of type" + "'int' or 'real'"); + + "' but must be of type " + "'int' or 'real'"); } if (op.equals("*") && !isInLinearizationBodyExpr) { @@ -2942,466 +2816,464 @@ public static boolean exprIsConstant(Expr expr) { } } -// ======= -//// // TODO: Don't we need more validation here? What if the Id of the IdExpr -//// private Boolean hasCallDefParent(Element e) { -//// while (e != null) { -//// if (e instanceof CallDef) { -//// return true; -//// } -//// e = e.getOwner(); -//// } -//// return false; -//// } -//// -//// private void checkScope(Expr expr, NamedElement id) { -//// if (hasCallDefParent(expr)) { -//// if (!hasCallDefParent(id) && !(id instanceof ConstStatement)) { -//// error("Unknown identifier Id: '" + id -//// + "' (Note that nodes can refer only to inputs, outputs, and local variables and global constants)."); -//// } -//// } -//// } -// -// public static NamedElement getFinalNestId(NestedDotID dotId) { -// while (dotId.getSub() != null) { -// dotId = dotId.getSub(); -// } -// -// return dotId.getBase(); -// } -// -// public String getNestedDotIDTag(NestedDotID dotId) { -// while (dotId.getSub() != null) { -// dotId = dotId.getSub(); -// } -// -// return dotId.getTag(); -// } -// -// public AgreeType getAgreeType(Arg arg) { -// return getAgreeType(arg.getType()); -// } -// -// private AgreeType getAgreeType(UnaryExpr unaryExpr) { -// return getAgreeType(unaryExpr.getExpr()); -// } -// -// -// private AgreeType getAgreeType(NestedDotID nestDotIdExpr) { -// -// String tag = getNestedDotIDTag(nestDotIdExpr); -// -// if (tag != null) { -// switch (tag) { -// case "_CLK": -// case "_INSERT": -// case "_REMOVE": -// return BOOL; -// case "_COUNT": -// return INT; -// default: -// return ERROR; -// } -// } -// -// return getAgreeType(getFinalNestId(nestDotIdExpr)); -// } -// -// protected AgreeType getAgreeType(NamedElement namedEl) { -// if (namedEl instanceof DataSubcomponent) { -// // this is for checking "Base_Types::Boolean" etc... -// ComponentClassifier compClass = ((DataSubcomponent) namedEl).getAllClassifier(); -// if (compClass instanceof DataImplementation) { -// return getAgreeType((DataImplementation) compClass); -// } -// return getAgreeType(compClass); -// } else if (namedEl instanceof Arg) { -// return getAgreeType((Arg) namedEl); -// } else if (namedEl instanceof ClassifierType || namedEl instanceof Subcomponent) { -// return new AgreeType("component"); -// } else if (namedEl instanceof PropertyStatement) { -// return getAgreeType((PropertyStatement) namedEl); -// } else if (namedEl instanceof ConstStatement) { -// return getAgreeType((ConstStatement) namedEl); -// } else if (namedEl instanceof EqStatement) { -// return getAgreeType(namedEl); -// } else if (namedEl instanceof DataPort) { -// return getAgreeType(((DataPort) namedEl).getDataFeatureClassifier()); -// } else if (namedEl instanceof EventDataPort) { -// return getAgreeType(((EventDataPort) namedEl).getDataFeatureClassifier()); -// } else if (namedEl instanceof DataAccess) { -// return getAgreeType((NamedElement) ((DataAccess) namedEl).getFeatureClassifier()); -// } else if (namedEl instanceof DataType) { -// return getAgreeType((ComponentClassifier) namedEl); -// } else if (namedEl instanceof DataImplementation) { -// return getAgreeType((DataImplementation) namedEl); -// } else if (namedEl instanceof NamedID) { -// return getAgreeType((NamedID) namedEl); -// } -// -// return ERROR; -// } -// -// private AgreeType getAgreeType(NamedID id) { -// EObject container = id.eContainer(); -// if (!(container instanceof EnumStatement)) { -// throw new IllegalArgumentException("NamedIDs allowed only in enum statements."); -// } -// return getAgreeType((EnumStatement) container); -// } -// -// private AgreeType getAgreeType(EnumStatement statement) { -// String name = statement.getName(); -// EObject container = statement.eContainer(); -// -// while (!(container instanceof AadlPackage)) { -// if (container instanceof ComponentClassifier) { -// name = ((ComponentClassifier) container).getName() + "::" + name; -// } -// container = container.eContainer(); -// } -// name = ((AadlPackage) container).getName() + "::" + name; -// return new AgreeType(name); -// } -// -// private AgreeType getAgreeType(DataImplementation dataImpl) { -// -// AgreeType nativeType = getNativeType(dataImpl); -// if (nativeType != null) { -// return nativeType; -// } -// -// AadlPackage aadlPack = (AadlPackage) dataImpl.eContainer().eContainer(); -// -// String typeStr = aadlPack.getName() + "::" + dataImpl.getName(); -// -// return new AgreeType(typeStr); -// } -// -// private AgreeType getNativeType(DataImplementation dataImpl) { -// EList subComps = dataImpl.getAllSubcomponents(); -// // if there are no subcomponents, use the component type -// if (subComps.size() == 0) { -// return getAgreeType((ComponentClassifier) dataImpl.getType()); -// } -// return null; -// } -// -// private AgreeType getAgreeType(ComponentClassifier dataClass) { -// -// while (dataClass != null) { -// switch (dataClass.getQualifiedName()) { -// case "Base_Types::Boolean": -// return BOOL; -// case "Base_Types::Integer": -// return INT; -// case "Base_Types::Float": -// return REAL; -// } -// -// boolean is_aadl_enum = AgreeAADLEnumerationUtils.isAADLEnumeration(dataClass); -// if (is_aadl_enum) { -// String name = dataClass.getName(); -// EObject container = dataClass.eContainer(); -// -// while (!(container instanceof AadlPackage)) { -// if (container instanceof ComponentClassifier) { -// name = ((ComponentClassifier) container).getName() + "::" + name; -// } -// container = container.eContainer(); -// } -// name = ((AadlPackage) container).getName() + "::" + name; -// return new AgreeType(name); -// } -// -// DataType dataType = (DataType) dataClass; -// dataClass = dataType.getExtended(); -// } -// -// return ERROR; -// } -// -// private AgreeType getAgreeType(ComponentType compType) { -// -// while (compType.getExtended() != null) { -// compType = compType.getExtended(); -// } -// -// String qualName = compType.getQualifiedName(); -// switch (qualName) { -// case "Base_Types::Boolean": -// return BOOL; -// case "Base_Types::Integer": -// return INT; -// case "Base_Types::Float": -// return REAL; -// } -// -// return new AgreeType(qualName); -// -// } -// -// private AgreeType getAgreeType(DataSubcomponentType data) { -// if (data instanceof DataType) { -// ComponentType compType = ((DataType) data).getExtended(); -// if (compType != null && !AgreeAADLEnumerationUtils.isAADLEnumeration(data)) { -// return getAgreeType(compType); -// } -// } -// String qualName = data.getQualifiedName(); -// if (qualName == null) { -// return ERROR; -// } -// switch (qualName) { -// case "Base_Types::Boolean": -// return BOOL; -// case "Base_Types::Integer": -// return INT; -// case "Base_Types::Float": -// return REAL; -// } -// return new AgreeType(qualName); -// } -// -// private AgreeType getAgreeType(PropertyStatement propStat) { -// return getAgreeType(propStat.getExpr()); -// } -// -// private AgreeType getAgreeType(ConstStatement constStat) { -// return getAgreeType(constStat.getType()); -// } -// -// private AgreeType getAgreeType(GetPropertyExpr getPropExpr) { -// NamedElement namedEl = getPropExpr.getProp(); -// if ((namedEl instanceof Property) || namedEl instanceof PropertyConstant) { -// PropertyType propType; -// if (namedEl instanceof Property) { -// propType = ((Property) namedEl).getPropertyType(); -// } else { -// propType = ((PropertyConstant) namedEl).getPropertyType(); -// } -// -// if (propType instanceof AadlBoolean) { -// return BOOL; -// } else if (propType instanceof AadlString || propType instanceof EnumerationType) { -// return new AgreeType("string"); -// } else if (propType instanceof AadlInteger) { -// return INT; -// } else if (propType instanceof AadlReal) { -// return REAL; -// } else if (propType instanceof ClassifierType) { -// return new AgreeType("component"); -// } -// } -// return ERROR; -// } -// -// private AgreeType getAgreeType(PrevExpr prevExpr) { -// return getAgreeType(prevExpr.getDelay()); -// } -// -// private List getAgreeTypes(List exprs) { -// ArrayList list = new ArrayList<>(); -// for (Expr expr : exprs) { -// list.add(getAgreeType(expr)); -// } -// return list; -// } -// -// public List typesFromArgs(List args) { -// ArrayList list = new ArrayList<>(); -// for (Arg arg : args) { -// list.add(getAgreeType(arg)); -// } -// return list; -// } -// -// private AgreeType getAgreeType(FnCallExpr fnCall) { -// // TODO: Examine type system in more detail -// // TODO: Fix to make support type lists. -// -// NamedElement namedEl = fnCall.getFn().getBase(); -// -// if (isInLinearizationBody(fnCall)) { -// // extract in/out arguments -// if (namedEl instanceof FnDefExpr || namedEl instanceof NodeDefExpr) { -// error(fnCall, "Calls to AGREE nodes and functions not allowed in linearization bodies"); -// return ERROR; -// } else if (namedEl instanceof LinearizationDefExpr) { -// return REAL; -// } else if (namedEl instanceof LibraryFnDefExpr) { -// LibraryFnDefExpr fnDef = (LibraryFnDefExpr) namedEl; -// return getAgreeType(fnDef.getType()); -// } else { -// error(fnCall, "Node, function or linearization definition name expected."); -// return ERROR; -// } -// -// } else { -// // extract in/out arguments -// if (namedEl instanceof FnDefExpr) { -// FnDefExpr fnDef = (FnDefExpr) namedEl; -// return getAgreeType(fnDef.getType()); -// } else if (namedEl instanceof NodeDefExpr) { -// NodeDefExpr nodeDef = (NodeDefExpr) namedEl; -// List outDefTypes = typesFromArgs(nodeDef.getRets()); -// if (outDefTypes.size() == 1) { -// return outDefTypes.get(0); -// } else { -// error(fnCall, "Nodes embedded in expressions must have exactly one return value." + " Node " -// + nodeDef.getName() + " contains " + outDefTypes.size() + " return values"); -// return ERROR; -// } -// } else if (namedEl instanceof LinearizationDefExpr) { -// return REAL; -// } else if (namedEl instanceof LibraryFnDefExpr) { -// LibraryFnDefExpr fnDef = (LibraryFnDefExpr) namedEl; -// return getAgreeType(fnDef.getType()); -// } else { -// error(fnCall, "Node, function or linearization definition name expected."); -// return ERROR; -// } -// } -// } -// -// private AgreeType getAgreeType(BinaryExpr binExpr) { -// AgreeType typeLeft = getAgreeType(binExpr.getLeft()); -// String op = binExpr.getOp(); -// -// switch (op) { -// case "->": -// return typeLeft; -// case "=>": -// case "<=>": -// case "and": -// case "or": -// return BOOL; -// case "<>": -// case "!=": -// return BOOL; -// case "<": -// case "<=": -// case ">": -// case ">=": -// case "=": -// return BOOL; -// case "+": -// case "-": -// case "*": -// case "/": -// case "mod": -// case "div": -// case "^": -// return typeLeft; -// } -// -// return ERROR; -// } -// -// protected AgreeType getAgreeType(Expr expr) { -// if (expr instanceof BinaryExpr) { -// return getAgreeType((BinaryExpr) expr); -// } else if (expr instanceof FnCallExpr) { -// return getAgreeType((FnCallExpr) expr); -// } else if (expr instanceof IfThenElseExpr) { -// return getAgreeType(expr); -// } else if (expr instanceof PrevExpr) { -// return getAgreeType((PrevExpr) expr); -// } else if (expr instanceof GetPropertyExpr) { -// return getAgreeType((GetPropertyExpr) expr); -// } else if (expr instanceof DoubleDotRef) { -// return getAgreeType((DoubleDotRef) expr); -// } else if (expr instanceof NestedDotID) { -// return getAgreeType((NestedDotID) expr); -// } else if (expr instanceof NestedDotID) { -// return getAgreeType((NestedDotID) expr); -// } else if (expr instanceof UnaryExpr) { -// return getAgreeType((UnaryExpr) expr); -// } else if (expr instanceof IntLitExpr) { -// return INT; -// } else if (expr instanceof RealLitExpr) { -// return REAL; -// } else if (expr instanceof BoolLitExpr) { -// return BOOL; -// } else if (expr instanceof ThisExpr) { -// return new AgreeType("component"); -// } else if (expr instanceof PreExpr) { -// return getAgreeType(((PreExpr) expr).getExpr()); -// } else if (expr instanceof RecordExpr) { -// return getAgreeType((RecordExpr) expr); -// } else if (expr instanceof RecordUpdateExpr) { -// return getAgreeType((RecordUpdateExpr) expr); -// } else if (expr instanceof FloorCast) { -// return INT; -// } else if (expr instanceof RealCast) { -// return REAL; -// } else if (expr instanceof EventExpr) { -// return BOOL; -// } else if (expr instanceof TimeExpr) { -// return REAL; -// } else if (expr instanceof AADLEnumerator) { -// return getAgreeType((AADLEnumerator) expr); -// } else if (expr instanceof LatchedExpr) { -// return getAgreeType(((LatchedExpr) expr).getExpr()); -// } else if (expr instanceof TimeOfExpr || expr instanceof TimeRiseExpr || expr instanceof TimeFallExpr) { -// return REAL; -// } /* -// * else if (expr instanceof UnaryNonLinearExpr || -// * expr instanceof BinaryNonLinearExpr) { -// * return REAL; -// * } -// */ -// -// return ERROR; -// } -// -// private AgreeType getAgreeType(AADLEnumerator enumExpr) { -// return getAgreeType(enumExpr.getEnumType()); -// } -// -// private AgreeType getAgreeType(DoubleDotRef DoubleDotRef) { -// return getAgreeType(DoubleDotRef.getElm()); -// } -// -// private AgreeType getAgreeType(RecordUpdateExpr upExpr) { -// return getAgreeType(upExpr.getRecord()); -// } -// -// private AgreeType getAgreeType(RecordExpr recExpr) { -// return getNamedElmAsType(recExpr.getRecord().getElm()); -// } -// -// public static boolean matches(AgreeType expected, AgreeType actual) { -// if (expected.equals(ERROR) || actual.equals(ERROR)) { -// return false; -// } else if (integerMatch(expected, actual)) { -// return true; -// } else if (floatingPointMatch(expected, actual)) { -// return true; -// } -// return expected.equals(actual); -// } -// -// private static boolean floatingPointMatch(AgreeType expected, AgreeType actual) { -// if (expected.toString().equals("real") && actual.toString().startsWith("Base_Types::Float")) { -// return true; -// } -// if (actual.toString().equals("real") && expected.toString().startsWith("Base_Types::Float")) { -// return true; -// } -// return false; -// } -// -// private static boolean integerMatch(AgreeType expected, AgreeType actual) { -// if (expected.toString().equals("int") && actual.toString().startsWith("Base_Types::Integer")) { -// return true; -// } -// if (actual.toString().equals("int") && expected.toString().startsWith("Base_Types::Integer")) { -// return true; -// } -// return false; -// } -// >>>>>>> origin/develop +// // TODO: Don't we need more validation here? What if the Id of the IdExpr +// private Boolean hasCallDefParent(Element e) { +// while (e != null) { +// if (e instanceof CallDef) { +// return true; +// } +// e = e.getOwner(); +// } +// return false; +// } +// +// private void checkScope(Expr expr, NamedElement id) { +// if (hasCallDefParent(expr)) { +// if (!hasCallDefParent(id) && !(id instanceof ConstStatement)) { +// error("Unknown identifier Id: '" + id +// + "' (Note that nodes can refer only to inputs, outputs, and local variables and global constants)."); +// } +// } +// } +// +// public static NamedElement getFinalNestId(NestedDotID dotId) { +// while (dotId.getSub() != null) { +// dotId = dotId.getSub(); +// } +// +// return dotId.getBase(); +// } +// +// public String getNestedDotIDTag(NestedDotID dotId) { +// while (dotId.getSub() != null) { +// dotId = dotId.getSub(); +// } +// +// return dotId.getTag(); +// } +// +// public AgreeType getAgreeType(Arg arg) { +// return getAgreeType(arg.getType()); +// } +// +// private AgreeType getAgreeType(UnaryExpr unaryExpr) { +// return getAgreeType(unaryExpr.getExpr()); +// } +// +// +// private AgreeType getAgreeType(NestedDotID nestDotIdExpr) { +// +// String tag = getNestedDotIDTag(nestDotIdExpr); +// +// if (tag != null) { +// switch (tag) { +// case "_CLK": +// case "_INSERT": +// case "_REMOVE": +// return BOOL; +// case "_COUNT": +// return INT; +// default: +// return ERROR; +// } +// } +// +// return getAgreeType(getFinalNestId(nestDotIdExpr)); +// } +// +// protected AgreeType getAgreeType(NamedElement namedEl) { +// if (namedEl instanceof DataSubcomponent) { +// // this is for checking "Base_Types::Boolean" etc... +// ComponentClassifier compClass = ((DataSubcomponent) namedEl).getAllClassifier(); +// if (compClass instanceof DataImplementation) { +// return getAgreeType((DataImplementation) compClass); +// } +// return getAgreeType(compClass); +// } else if (namedEl instanceof Arg) { +// return getAgreeType((Arg) namedEl); +// } else if (namedEl instanceof ClassifierType || namedEl instanceof Subcomponent) { +// return new AgreeType("component"); +// } else if (namedEl instanceof PropertyStatement) { +// return getAgreeType((PropertyStatement) namedEl); +// } else if (namedEl instanceof ConstStatement) { +// return getAgreeType((ConstStatement) namedEl); +// } else if (namedEl instanceof EqStatement) { +// return getAgreeType(namedEl); +// } else if (namedEl instanceof DataPort) { +// return getAgreeType(((DataPort) namedEl).getDataFeatureClassifier()); +// } else if (namedEl instanceof EventDataPort) { +// return getAgreeType(((EventDataPort) namedEl).getDataFeatureClassifier()); +// } else if (namedEl instanceof DataAccess) { +// return getAgreeType((NamedElement) ((DataAccess) namedEl).getFeatureClassifier()); +// } else if (namedEl instanceof DataType) { +// return getAgreeType((ComponentClassifier) namedEl); +// } else if (namedEl instanceof DataImplementation) { +// return getAgreeType((DataImplementation) namedEl); +// } else if (namedEl instanceof NamedID) { +// return getAgreeType((NamedID) namedEl); +// } +// +// return ERROR; +// } +// +// private AgreeType getAgreeType(NamedID id) { +// EObject container = id.eContainer(); +// if (!(container instanceof EnumStatement)) { +// throw new IllegalArgumentException("NamedIDs allowed only in enum statements."); +// } +// return getAgreeType((EnumStatement) container); +// } +// +// private AgreeType getAgreeType(EnumStatement statement) { +// String name = statement.getName(); +// EObject container = statement.eContainer(); +// +// while (!(container instanceof AadlPackage)) { +// if (container instanceof ComponentClassifier) { +// name = ((ComponentClassifier) container).getName() + "::" + name; +// } +// container = container.eContainer(); +// } +// name = ((AadlPackage) container).getName() + "::" + name; +// return new AgreeType(name); +// } +// +// private AgreeType getAgreeType(DataImplementation dataImpl) { +// +// AgreeType nativeType = getNativeType(dataImpl); +// if (nativeType != null) { +// return nativeType; +// } +// +// AadlPackage aadlPack = (AadlPackage) dataImpl.eContainer().eContainer(); +// +// String typeStr = aadlPack.getName() + "::" + dataImpl.getName(); +// +// return new AgreeType(typeStr); +// } +// +// private AgreeType getNativeType(DataImplementation dataImpl) { +// EList subComps = dataImpl.getAllSubcomponents(); +// // if there are no subcomponents, use the component type +// if (subComps.size() == 0) { +// return getAgreeType((ComponentClassifier) dataImpl.getType()); +// } +// return null; +// } +// +// private AgreeType getAgreeType(ComponentClassifier dataClass) { +// +// while (dataClass != null) { +// switch (dataClass.getQualifiedName()) { +// case "Base_Types::Boolean": +// return BOOL; +// case "Base_Types::Integer": +// return INT; +// case "Base_Types::Float": +// return REAL; +// } +// +// boolean is_aadl_enum = AgreeAADLEnumerationUtils.isAADLEnumeration(dataClass); +// if (is_aadl_enum) { +// String name = dataClass.getName(); +// EObject container = dataClass.eContainer(); +// +// while (!(container instanceof AadlPackage)) { +// if (container instanceof ComponentClassifier) { +// name = ((ComponentClassifier) container).getName() + "::" + name; +// } +// container = container.eContainer(); +// } +// name = ((AadlPackage) container).getName() + "::" + name; +// return new AgreeType(name); +// } +// +// DataType dataType = (DataType) dataClass; +// dataClass = dataType.getExtended(); +// } +// +// return ERROR; +// } +// +// private AgreeType getAgreeType(ComponentType compType) { +// +// while (compType.getExtended() != null) { +// compType = compType.getExtended(); +// } +// +// String qualName = compType.getQualifiedName(); +// switch (qualName) { +// case "Base_Types::Boolean": +// return BOOL; +// case "Base_Types::Integer": +// return INT; +// case "Base_Types::Float": +// return REAL; +// } +// +// return new AgreeType(qualName); +// +// } +// +// private AgreeType getAgreeType(DataSubcomponentType data) { +// if (data instanceof DataType) { +// ComponentType compType = ((DataType) data).getExtended(); +// if (compType != null && !AgreeAADLEnumerationUtils.isAADLEnumeration(data)) { +// return getAgreeType(compType); +// } +// } +// String qualName = data.getQualifiedName(); +// if (qualName == null) { +// return ERROR; +// } +// switch (qualName) { +// case "Base_Types::Boolean": +// return BOOL; +// case "Base_Types::Integer": +// return INT; +// case "Base_Types::Float": +// return REAL; +// } +// return new AgreeType(qualName); +// } +// +// private AgreeType getAgreeType(PropertyStatement propStat) { +// return getAgreeType(propStat.getExpr()); +// } +// +// private AgreeType getAgreeType(ConstStatement constStat) { +// return getAgreeType(constStat.getType()); +// } +// +// private AgreeType getAgreeType(GetPropertyExpr getPropExpr) { +// NamedElement namedEl = getPropExpr.getProp(); +// if ((namedEl instanceof Property) || namedEl instanceof PropertyConstant) { +// PropertyType propType; +// if (namedEl instanceof Property) { +// propType = ((Property) namedEl).getPropertyType(); +// } else { +// propType = ((PropertyConstant) namedEl).getPropertyType(); +// } +// +// if (propType instanceof AadlBoolean) { +// return BOOL; +// } else if (propType instanceof AadlString || propType instanceof EnumerationType) { +// return new AgreeType("string"); +// } else if (propType instanceof AadlInteger) { +// return INT; +// } else if (propType instanceof AadlReal) { +// return REAL; +// } else if (propType instanceof ClassifierType) { +// return new AgreeType("component"); +// } +// } +// return ERROR; +// } +// +// private AgreeType getAgreeType(PrevExpr prevExpr) { +// return getAgreeType(prevExpr.getDelay()); +// } +// +// private List getAgreeTypes(List exprs) { +// ArrayList list = new ArrayList<>(); +// for (Expr expr : exprs) { +// list.add(getAgreeType(expr)); +// } +// return list; +// } +// +// public List typesFromArgs(List args) { +// ArrayList list = new ArrayList<>(); +// for (Arg arg : args) { +// list.add(getAgreeType(arg)); +// } +// return list; +// } +// +// private AgreeType getAgreeType(FnCallExpr fnCall) { +// // TODO: Examine type system in more detail +// // TODO: Fix to make support type lists. +// +// NamedElement namedEl = fnCall.getFn().getBase(); +// +// if (isInLinearizationBody(fnCall)) { +// // extract in/out arguments +// if (namedEl instanceof FnDefExpr || namedEl instanceof NodeDefExpr) { +// error(fnCall, "Calls to AGREE nodes and functions not allowed in linearization bodies"); +// return ERROR; +// } else if (namedEl instanceof LinearizationDefExpr) { +// return REAL; +// } else if (namedEl instanceof LibraryFnDefExpr) { +// LibraryFnDefExpr fnDef = (LibraryFnDefExpr) namedEl; +// return getAgreeType(fnDef.getType()); +// } else { +// error(fnCall, "Node, function or linearization definition name expected."); +// return ERROR; +// } +// +// } else { +// // extract in/out arguments +// if (namedEl instanceof FnDefExpr) { +// FnDefExpr fnDef = (FnDefExpr) namedEl; +// return getAgreeType(fnDef.getType()); +// } else if (namedEl instanceof NodeDefExpr) { +// NodeDefExpr nodeDef = (NodeDefExpr) namedEl; +// List outDefTypes = typesFromArgs(nodeDef.getRets()); +// if (outDefTypes.size() == 1) { +// return outDefTypes.get(0); +// } else { +// error(fnCall, "Nodes embedded in expressions must have exactly one return value." + " Node " +// + nodeDef.getName() + " contains " + outDefTypes.size() + " return values"); +// return ERROR; +// } +// } else if (namedEl instanceof LinearizationDefExpr) { +// return REAL; +// } else if (namedEl instanceof LibraryFnDefExpr) { +// LibraryFnDefExpr fnDef = (LibraryFnDefExpr) namedEl; +// return getAgreeType(fnDef.getType()); +// } else { +// error(fnCall, "Node, function or linearization definition name expected."); +// return ERROR; +// } +// } +// } +// +// private AgreeType getAgreeType(BinaryExpr binExpr) { +// AgreeType typeLeft = getAgreeType(binExpr.getLeft()); +// String op = binExpr.getOp(); +// +// switch (op) { +// case "->": +// return typeLeft; +// case "=>": +// case "<=>": +// case "and": +// case "or": +// return BOOL; +// case "<>": +// case "!=": +// return BOOL; +// case "<": +// case "<=": +// case ">": +// case ">=": +// case "=": +// return BOOL; +// case "+": +// case "-": +// case "*": +// case "/": +// case "mod": +// case "div": +// case "^": +// return typeLeft; +// } +// +// return ERROR; +// } +// +// protected AgreeType getAgreeType(Expr expr) { +// if (expr instanceof BinaryExpr) { +// return getAgreeType((BinaryExpr) expr); +// } else if (expr instanceof FnCallExpr) { +// return getAgreeType((FnCallExpr) expr); +// } else if (expr instanceof IfThenElseExpr) { +// return getAgreeType(expr); +// } else if (expr instanceof PrevExpr) { +// return getAgreeType((PrevExpr) expr); +// } else if (expr instanceof GetPropertyExpr) { +// return getAgreeType((GetPropertyExpr) expr); +// } else if (expr instanceof DoubleDotRef) { +// return getAgreeType((DoubleDotRef) expr); +// } else if (expr instanceof NestedDotID) { +// return getAgreeType((NestedDotID) expr); +// } else if (expr instanceof NestedDotID) { +// return getAgreeType((NestedDotID) expr); +// } else if (expr instanceof UnaryExpr) { +// return getAgreeType((UnaryExpr) expr); +// } else if (expr instanceof IntLitExpr) { +// return INT; +// } else if (expr instanceof RealLitExpr) { +// return REAL; +// } else if (expr instanceof BoolLitExpr) { +// return BOOL; +// } else if (expr instanceof ThisExpr) { +// return new AgreeType("component"); +// } else if (expr instanceof PreExpr) { +// return getAgreeType(((PreExpr) expr).getExpr()); +// } else if (expr instanceof RecordExpr) { +// return getAgreeType((RecordExpr) expr); +// } else if (expr instanceof RecordUpdateExpr) { +// return getAgreeType((RecordUpdateExpr) expr); +// } else if (expr instanceof FloorCast) { +// return INT; +// } else if (expr instanceof RealCast) { +// return REAL; +// } else if (expr instanceof EventExpr) { +// return BOOL; +// } else if (expr instanceof TimeExpr) { +// return REAL; +// } else if (expr instanceof AADLEnumerator) { +// return getAgreeType((AADLEnumerator) expr); +// } else if (expr instanceof LatchedExpr) { +// return getAgreeType(((LatchedExpr) expr).getExpr()); +// } else if (expr instanceof TimeOfExpr || expr instanceof TimeRiseExpr || expr instanceof TimeFallExpr) { +// return REAL; +// } /* +// * else if (expr instanceof UnaryNonLinearExpr || +// * expr instanceof BinaryNonLinearExpr) { +// * return REAL; +// * } +// */ +// +// return ERROR; +// } +// +// private AgreeType getAgreeType(AADLEnumerator enumExpr) { +// return getAgreeType(enumExpr.getEnumType()); +// } +// +// private AgreeType getAgreeType(DoubleDotRef DoubleDotRef) { +// return getAgreeType(DoubleDotRef.getElm()); +// } +// +// private AgreeType getAgreeType(RecordUpdateExpr upExpr) { +// return getAgreeType(upExpr.getRecord()); +// } +// +// private AgreeType getAgreeType(RecordExpr recExpr) { +// return getNamedElmAsType(recExpr.getRecord().getElm()); +// } +// +// public static boolean matches(AgreeType expected, AgreeType actual) { +// if (expected.equals(ERROR) || actual.equals(ERROR)) { +// return false; +// } else if (integerMatch(expected, actual)) { +// return true; +// } else if (floatingPointMatch(expected, actual)) { +// return true; +// } +// return expected.equals(actual); +// } +// +// private static boolean floatingPointMatch(AgreeType expected, AgreeType actual) { +// if (expected.toString().equals("real") && actual.toString().startsWith("Base_Types::Float")) { +// return true; +// } +// if (actual.toString().equals("real") && expected.toString().startsWith("Base_Types::Float")) { +// return true; +// } +// return false; +// } +// +// private static boolean integerMatch(AgreeType expected, AgreeType actual) { +// if (expected.toString().equals("int") && actual.toString().startsWith("Base_Types::Integer")) { +// return true; +// } +// if (actual.toString().equals("int") && expected.toString().startsWith("Base_Types::Integer")) { +// return true; +// } +// return false; +// } } diff --git a/com.rockwellcollins.atc.agree/src/com/rockwellcollins/atc/agree/validation/CallRecursionHelper.java b/com.rockwellcollins.atc.agree/src/com/rockwellcollins/atc/agree/validation/CallRecursionHelper.java index 7d2f19458..1c6090a1c 100644 --- a/com.rockwellcollins.atc.agree/src/com/rockwellcollins/atc/agree/validation/CallRecursionHelper.java +++ b/com.rockwellcollins.atc.agree/src/com/rockwellcollins/atc/agree/validation/CallRecursionHelper.java @@ -150,15 +150,6 @@ public Expr caseCallExpr(CallExpr object) { try { callDef = (Abstraction) id.getElm(); -//======= -// public Expr caseFnCallExpr(FnCallExpr object) { -// -// CallDef callDef = null; -// -// try { -// callDef = (CallDef) object.getFn().getBase(); -//>>>>>>> origin/develop:fm-workbench/agree/com.rockwellcollins.atc.agree/src/com/rockwellcollins/atc/agree/validation/FnCallRecursionHelper.java -// } catch (ClassCastException e) { return null; } diff --git a/com.rockwellcollins.atc.agree/src/com/rockwellcollins/atc/agree/visitors/ExprCycleVisitor.java b/com.rockwellcollins.atc.agree/src/com/rockwellcollins/atc/agree/visitors/ExprCycleVisitor.java index 04b5c8bb8..6e9b06b3b 100644 --- a/com.rockwellcollins.atc.agree/src/com/rockwellcollins/atc/agree/visitors/ExprCycleVisitor.java +++ b/com.rockwellcollins.atc.agree/src/com/rockwellcollins/atc/agree/visitors/ExprCycleVisitor.java @@ -35,22 +35,35 @@ import com.rockwellcollins.atc.agree.agree.GetPropertyExpr; import com.rockwellcollins.atc.agree.agree.IfThenElseExpr; import com.rockwellcollins.atc.agree.agree.IntLitExpr; +import com.rockwellcollins.atc.agree.agree.NamedElmExpr; import com.rockwellcollins.atc.agree.agree.PreExpr; import com.rockwellcollins.atc.agree.agree.PrevExpr; import com.rockwellcollins.atc.agree.agree.RealCast; import com.rockwellcollins.atc.agree.agree.RealLitExpr; import com.rockwellcollins.atc.agree.agree.RecordLitExpr; import com.rockwellcollins.atc.agree.agree.RecordUpdateExpr; +import com.rockwellcollins.atc.agree.agree.SelectionExpr; import com.rockwellcollins.atc.agree.agree.UnaryExpr; import com.rockwellcollins.atc.agree.agree.util.AgreeSwitch; public class ExprCycleVisitor extends AgreeSwitch> { - @SuppressWarnings("unused") - private String id; + public ExprCycleVisitor() { + } - public ExprCycleVisitor(String id) { - this.id = id; + @Override + public Set caseNamedElmExpr(NamedElmExpr e) { + Set result = new HashSet<>(); + result.add(e.getElm()); + return result; + } + + @Override + public Set caseSelectionExpr(SelectionExpr e) { + Set result = new HashSet<>(); + result.add(e.getTarget()); + result.add(e.getField()); + return result; } @Override