diff --git a/ragconnect.base/src/main/jastadd/Errors.jrag b/ragconnect.base/src/main/jastadd/Errors.jrag index 2836b5f1ab6da646b18370e4d7f2ca794cfa1111..f1924e72f4b5944ee8897390f3db494bfd48c4c9 100644 --- a/ragconnect.base/src/main/jastadd/Errors.jrag +++ b/ragconnect.base/src/main/jastadd/Errors.jrag @@ -27,10 +27,16 @@ aspect Errors { token().effectiveJavaTypeUse()) to RagConnect.errors(); - ContextFreeTypeEndpointTarget contributes error("Context-Free endpoint not allowed for root nodes!") + ContextFreeTypeEndpointTarget contributes error("Context-Free endpoint not allowed for root node " + + getTypeDecl().getName() + "!") when getTypeDecl().occurencesInProductionRules().isEmpty() to RagConnect.errors(); + EndpointDefinition contributes error("Clash with implied, indexed endpoint definition of context-free endpoint in line " + + clashingContextFreeEndpointDefinition().getStartLine() + "!") + when !getSend() && clashingContextFreeEndpointDefinition() != null + to RagConnect.errors(); + DependencyDefinition contributes error("Dependency definition already defined for " + getSource().containingTypeDecl().getName() + " with name " + getID()) when isAlreadyDefined() to RagConnect.errors(); @@ -49,6 +55,18 @@ aspect ErrorHelpers { } return false; } + + syn EndpointDefinition EndpointDefinition.clashingContextFreeEndpointDefinition() { + if (getSend() || !typeIsList() || getIndexBasedListAccess()) { + return null; + } + List<EndpointDefinition> contextFreeEndpointsWithSameType = lookupContextFreeTypeEndpointDefinitions( + getEndpointTarget().asTypeEndpointTarget().getType().getTypeDecl()); + if (!contextFreeEndpointsWithSameType.isEmpty()) { + return contextFreeEndpointsWithSameType.get(0); + } + return null; + } } aspect ErrorMessage { diff --git a/ragconnect.base/src/main/jastadd/parser/ParserRewrites.jrag b/ragconnect.base/src/main/jastadd/parser/ParserRewrites.jrag index f888758f2ca515309e639722d8ef15bd5fe7e1fc..23dbabaef4ce3d4e0ce114591d1c4ee61937b878 100644 --- a/ragconnect.base/src/main/jastadd/parser/ParserRewrites.jrag +++ b/ragconnect.base/src/main/jastadd/parser/ParserRewrites.jrag @@ -3,6 +3,7 @@ aspect ParserRewrites { when (getChildName() != null && tryGloballyResolveTypeComponentByToken(combinedName()) != null) to TypeEndpointTarget { TypeEndpointTarget result = new TypeEndpointTarget(); + result.copyOtherValuesFrom(this); result.setType(TypeComponent.createRef(this.combinedName())); return result; } @@ -10,6 +11,7 @@ aspect ParserRewrites { when (getChildName() != null && tryGloballyResolveTokenComponentByToken(combinedName()) != null) to TokenEndpointTarget { TokenEndpointTarget result = new TokenEndpointTarget(); + result.copyOtherValuesFrom(this); result.setToken(TokenComponent.createRef(this.combinedName())); return result; } @@ -17,6 +19,7 @@ aspect ParserRewrites { when (getChildName() == "") to ContextFreeTypeEndpointTarget { ContextFreeTypeEndpointTarget result = new ContextFreeTypeEndpointTarget(); + result.copyOtherValuesFrom(this); result.setTypeDecl(TypeDecl.createRef(getTypeName())); return result; } @@ -24,6 +27,11 @@ aspect ParserRewrites { syn String UntypedEndpointTarget.combinedName() = getTypeName() + "." + getChildName(); + protected void EndpointTarget.copyOtherValuesFrom(EndpointTarget source) { + this.setStart(source.getStartLine(), source.getStartColumn()); + this.setEnd(source.getEndLine(), source.getEndColumn()); + } + eq UntypedEndpointTarget.senderName() = "<untyped.senderName>"; eq UntypedEndpointTarget.getterMethodName() = "<untyped.getterMethodName>"; eq UntypedEndpointTarget.parentTypeName() = "<untyped.parentTypeName>"; diff --git a/ragconnect.tests/src/test/01-input/contextFreeSimple/Test.connect b/ragconnect.tests/src/test/01-input/contextFreeSimple/Test.connect index 95223256630de1c64de41d2c57467012e0f7d56d..7a6aeab676953fdba30bb04f111c7b1fd6bc0655 100644 --- a/ragconnect.tests/src/test/01-input/contextFreeSimple/Test.connect +++ b/ragconnect.tests/src/test/01-input/contextFreeSimple/Test.connect @@ -1,10 +1,9 @@ receive A; -//// implied -//receive Root.A; +//"receive Root.A;" is implied receive Root.SingleA using PrependPrefix; receive Root.OptA using AddSuffix; -//"receive Root.ListA;" would clash +//"receive Root.ListA;" would clash as "receive indexed Root.ListA" is implied PrependPrefix maps A a to A {: A result = new A(); diff --git a/ragconnect.tests/src/test/01-input/errors/Errors.relast b/ragconnect.tests/src/test/01-input/errors/Errors.relast index fcde7df1d2e48b9591ddea31aaa3b0a9efdd4cfa..f700f39abdcac18174e192bfc6098d95e4720573 100644 --- a/ragconnect.tests/src/test/01-input/errors/Errors.relast +++ b/ragconnect.tests/src/test/01-input/errors/Errors.relast @@ -1,10 +1,10 @@ -A ::= B C D ; +A ::= B C D E* ; // read definitions B ::= /<ErrorNTA:String>/ <ErrorTypeOfFirstMapping:String> <ErrorTypeOfLastMapping:String> <DoubledValue:int> <ErrorTypeMismatch:String> ; // write definitions -C ::= <ErrorNotNTA:String> /<ErrorTypeOfFirstMapping:String>/ /<ErrorTypeOfLastMapping1:String>/ /<ErrorTypeOfLastMapping2:List<String>>/ /<ErrorTypeMismatch:String>/ /<DoubledValue:int>/ ; +C ::= /<ErrorTypeOfFirstMapping:String>/ /<ErrorTypeOfLastMapping1:String>/ /<ErrorTypeOfLastMapping2:List<String>>/ /<ErrorTypeMismatch:String>/ /<DoubledValue:int>/ ; // dependency definitions D ::= <SourceNonExistingTarget> @@ -13,3 +13,6 @@ D ::= <SourceNonExistingTarget> <SourceSameAsListNode> /<TargetSameAsListNode>/ <SourceDoubledValue> /<TargetDoubledValue>/ MyList:D* ; + +// context-free endpoints +E ::= ; diff --git a/ragconnect.tests/src/test/01-input/errors/Standard.connect b/ragconnect.tests/src/test/01-input/errors/Standard.connect index bd57822a6c70198cc36698f790fa90655ed4db73..844c2e97b4f6e32e0e1f3f1392065a2f0ea3efbc 100644 --- a/ragconnect.tests/src/test/01-input/errors/Standard.connect +++ b/ragconnect.tests/src/test/01-input/errors/Standard.connect @@ -1,4 +1,4 @@ -// --- update receive definitions --- +// --- receive definitions --- // Error: there must not be two receive definitions for the same token receive B.DoubledValue ; receive B.DoubledValue using IntToInt ; @@ -18,22 +18,26 @@ receive B.ErrorTypeOfLastMapping using StringToList ; // Error: types of mappings must match (modulo inheritance) receive B.ErrorTypeMismatch using StringToList, IntToInt ; -// --- update send definitions --- +// Error: Context-Free endpoint not allowed for root nodes +receive A; + +// Error: Clash with implied endpoint definition of context-free endpoint +receive E; +receive A.E; + +// --- send definitions --- // NOT HANDLED \\ Error: the token must be resolvable within the parent type // NOT HANDLED \\ receive C.NonExisting ; -// Error: Token must be a TokenNTA (i.e., check for Token.getNTA()) -send C.ErrorNotNTA ; +// NOT HANDLED \\ // Error: from-type of first mapping must be type of Token +// NOT HANDLED \\ send C.ErrorTypeOfFirstMapping using IntToInt ; -// Error: from-type of first mapping must be type of Token -send C.ErrorTypeOfFirstMapping using IntToInt ; +// NOT HANDLED \\ // Error: to-type of last mapping must be byte[] or a supported primitive type +// NOT HANDLED \\ send C.ErrorTypeOfLastMapping1 using StringToList ; +// NOT HANDLED \\ send C.ErrorTypeOfLastMapping2 ; -// Error: to-type of last mapping must be byte[] or a supported primitive type -send C.ErrorTypeOfLastMapping1 using StringToList ; -send C.ErrorTypeOfLastMapping2 ; - -// Error: types of mappings must match (modulo inheritance) -send C.ErrorTypeMismatch using StringToList, IntToInt ; +// NOT HANDLED \\ // Error: types of mappings must match (modulo inheritance) +// NOT HANDLED \\ send C.ErrorTypeMismatch using StringToList, IntToInt ; // Error: no more than one send mapping for each TokenComponent send C.DoubledValue ; @@ -44,8 +48,8 @@ send C.DoubledValue using IntToInt ; // NOT HANDLED \\ D.SourceNonExistingTarget canDependOn D.NonExisting as NonExistingTarget ; // NOT HANDLED \\ D.NonExisting canDependOn D.TargetNonExistingSource as NonExistingSource ; -// Error: There must be a send update definition for the target token -D.SourceNoWriteDef canDependOn D.TargetNoWriteDef as NoWriteDef ; +// NOT HANDLED \\ // Error: There must be a send update definition for the target token +// NOT HANDLED \\ D.SourceNoWriteDef canDependOn D.TargetNoWriteDef as NoWriteDef ; // Error: The name of a dependency definition must not be equal to a list-node on the source D.SourceSameAsListNode canDependOn D.TargetSameAsListNode as MyList ; diff --git a/ragconnect.tests/src/test/01-input/errors/Standard.expected b/ragconnect.tests/src/test/01-input/errors/Standard.expected index 2e14612cc9fc4d7ffae435745e8b8593a22258d5..d258c2c599b54523d4ecff92eb95af8f419a9ec9 100644 --- a/ragconnect.tests/src/test/01-input/errors/Standard.expected +++ b/ragconnect.tests/src/test/01-input/errors/Standard.expected @@ -5,7 +5,9 @@ Standard.connect Line 13, column 1: No suitable default mapping found for type j Standard.connect Line 13, column 1: to-type of last mapping (java.util.List) not assignable to type of the token (String)! Standard.connect Line 16, column 1: to-type of last mapping (List) not assignable to type of the token (String)! Standard.connect Line 19, column 1: to-type of last mapping (int) not assignable to type of the token (String)! -Standard.connect Line 39, column 1: Endpoint definition already defined for C.DoubledValue -Standard.connect Line 40, column 1: Endpoint definition already defined for C.DoubledValue -Standard.connect Line 51, column 1: The name of a dependency definition must not be equal to a list-node on the source -Standard.connect Line 56, column 1: Dependency definition already defined for D with name DoubledValue +Standard.connect Line 22, column 9: Context-Free endpoint not allowed for root node A! +Standard.connect Line 26, column 1: Clash with implied, indexed endpoint definition of context-free endpoint in line 25! +Standard.connect Line 43, column 1: Endpoint definition already defined for C.DoubledValue +Standard.connect Line 44, column 1: Endpoint definition already defined for C.DoubledValue +Standard.connect Line 55, column 1: The name of a dependency definition must not be equal to a list-node on the source +Standard.connect Line 60, column 1: Dependency definition already defined for D with name DoubledValue