From 5188b017947d2cc9675ef88e2df5efea6b0e7a0b Mon Sep 17 00:00:00 2001 From: rschoene Date: Tue, 9 Nov 2021 19:05:05 +0100 Subject: [PATCH 1/5] begin with removing tree and list --- .../src/main/jastadd/NameResolution.jrag | 58 +++++++++++++-- .../src/main/jastadd/RagConnect.relast | 5 ++ .../main/jastadd/parser/ParserRewrites.jrag | 74 +++++++++++++++++++ .../src/main/jastadd/parser/RagConnect.parser | 56 +++++++------- .../src/main/jastadd/scanner/Keywords.flex | 5 +- .../src/test/01-input/list/Test.connect | 12 +-- .../src/test/01-input/singleList/Test.connect | 16 ++-- .../01-input/singleListVariant/Test.connect | 50 ++++++------- .../src/test/01-input/tree/Test.connect | 4 +- .../01-input/treeAllowedTokens/Test.connect | 8 +- 10 files changed, 206 insertions(+), 82 deletions(-) create mode 100644 ragconnect.base/src/main/jastadd/parser/ParserRewrites.jrag diff --git a/ragconnect.base/src/main/jastadd/NameResolution.jrag b/ragconnect.base/src/main/jastadd/NameResolution.jrag index 3b75bc0..80525b5 100644 --- a/ragconnect.base/src/main/jastadd/NameResolution.jrag +++ b/ragconnect.base/src/main/jastadd/NameResolution.jrag @@ -1,18 +1,32 @@ -aspect NameResolution { +aspect RagConnectNameResolution { + // rel EndpointDefinition.Mapping* -> MappingDefinition refine RefResolverStubs eq EndpointDefinition.resolveMappingByToken(String id, int position) { - // return a MappingDefinition + MappingDefinition result = tryResolveMappingByToken(id); + if (result == null) { + System.err.println("Could not resolve MappingDefinition '" + id + "'."); + } + return result; + } + syn MappingDefinition EndpointDefinition.tryResolveMappingByToken(String id) { for (MappingDefinition mappingDefinition : ragconnect().allMappingDefinitionList()) { if (mappingDefinition.getID().equals(id)) { return mappingDefinition; } } - System.err.println("Could not resolve MappingDefinition '" + id + "'."); return null; } + // rel ___ -> TypeComponent refine RefResolverStubs eq ASTNode.globallyResolveTypeComponentByToken(String id) { - // return a TypeComponent. id is of the form 'parent_type_name + "." + child_type_name' + TypeComponent result = tryGloballyResolveTypeComponentByToken(id); + if (result == null) { + System.err.println("Could not resolve TypeComponent '" + id + "'."); + } + return result; + } + syn TypeComponent ASTNode.tryGloballyResolveTypeComponentByToken(String id) { + // id is of the form 'parent_type_name + "." + child_type_name' int dotIndex = id.indexOf("."); String parentTypeName = id.substring(0, dotIndex); String childTypeName = id.substring(dotIndex + 1); @@ -23,12 +37,19 @@ aspect NameResolution { return comp.asTypeComponent(); } } - System.err.println("Could not resolve TypeComponent '" + id + "'."); return null; } + // rel ___ -> Component refine RefResolverStubs eq ASTNode.globallyResolveComponentByToken(String id) { - // return a Component. id is of the form 'parent_type_name + "." + child_type_name' + Component result = tryGloballyResolveComponentByToken(id); + if (result == null) { + System.err.println("Could not resolve Component '" + id + "'."); + } + return result; + } + syn Component ASTNode.tryGloballyResolveComponentByToken(String id) { + // id is of the form 'parent_type_name + "." + child_type_name' int dotIndex = id.indexOf("."); String parentTypeName = id.substring(0, dotIndex); String childTypeName = id.substring(dotIndex + 1); @@ -39,7 +60,30 @@ aspect NameResolution { return comp; } } - System.err.println("Could not resolve Component '" + id + "'."); + return null; + } + + // rel ___ -> TokenComponent (from relast-preprocessor) + // refine here to have an attribute without writing on stderr if not found + refine NameResolution eq ASTNode.globallyResolveTokenComponentByToken(String id) { + TokenComponent result = tryGloballyResolveTokenComponentByToken(id); + if (result == null) { + System.err.println("Could not resolve TokenComponent '" + id + "'."); + } + return result; + } + syn TokenComponent ASTNode.tryGloballyResolveTokenComponentByToken(String id) { + // id is of the form 'type_name + "." + token_name' + int dotIndex = id.indexOf("."); + String typeName = id.substring(0, dotIndex); + String tokenName = id.substring(dotIndex + 1); + TypeDecl type = program().resolveTypeDecl(typeName); + // iterate over components and find the matching tokenComponent + for (Component comp : type.getComponentList()) { + if (comp.isTokenComponent() && comp.getName().equals(tokenName)) { + return comp.asTokenComponent(); + } + } return null; } diff --git a/ragconnect.base/src/main/jastadd/RagConnect.relast b/ragconnect.base/src/main/jastadd/RagConnect.relast index c1cbbb2..3728d41 100644 --- a/ragconnect.base/src/main/jastadd/RagConnect.relast +++ b/ragconnect.base/src/main/jastadd/RagConnect.relast @@ -28,3 +28,8 @@ abstract MappingDefinitionType ::= ; JavaMappingDefinitionType : MappingDefinitionType ::= Type:JavaTypeUse ; JavaArrayMappingDefinitionType : MappingDefinitionType ::= Type:JavaTypeUse ; DefaultMappingDefinition : MappingDefinition ; + +// only used by parser +abstract UntypedEndpointDefinition : EndpointDefinition ::= ; +ReceiveUntypedEndpointDefinition : UntypedEndpointDefinition; +SendUntypedEndpointDefinition : UntypedEndpointDefinition; diff --git a/ragconnect.base/src/main/jastadd/parser/ParserRewrites.jrag b/ragconnect.base/src/main/jastadd/parser/ParserRewrites.jrag new file mode 100644 index 0000000..214fec4 --- /dev/null +++ b/ragconnect.base/src/main/jastadd/parser/ParserRewrites.jrag @@ -0,0 +1,74 @@ +aspect ParserRewrites { + rewrite SendUntypedEndpointDefinition { + when (tryGloballyResolveTypeComponentByToken(getTokenOrType()) != null) + to SendTypeEndpointDefinition { + SendTypeEndpointDefinition result = new SendTypeEndpointDefinition(); + result.applyFrom(this); + if (this.getIndexed()) { + result.setUseList(true); + } + return result; + } + } + + rewrite ReceiveUntypedEndpointDefinition { + when (tryGloballyResolveTypeComponentByToken(getTokenOrType()) != null) + to ReceiveTypeEndpointDefinition { + ReceiveTypeEndpointDefinition result = new ReceiveTypeEndpointDefinition(); + result.applyFrom(this); + if (this.getWithAdd()) { + result.setWithAdd(true); + } + if (this.getIndexed()) { + result.setUseList(true); + } + return result; + } + } + + rewrite SendUntypedEndpointDefinition { + when (tryGloballyResolveTokenComponentByToken(getTokenOrType()) != null) + to SendTokenEndpointDefinition { + SendTokenEndpointDefinition result = new SendTokenEndpointDefinition(); + result.applyFrom(this); + return result; + } + } + + rewrite ReceiveUntypedEndpointDefinition { + when (tryGloballyResolveTokenComponentByToken(getTokenOrType()) != null) + to ReceiveTokenEndpointDefinition { + ReceiveTokenEndpointDefinition result = new ReceiveTokenEndpointDefinition(); + result.applyFrom(this); + return result; + } + } + + protected void TypeEndpointDefinition.applyFrom(UntypedEndpointDefinition def) { + this.setAlwaysApply(def.getAlwaysApply()); + this.setType(TypeComponent.createRef(def.getTokenOrType())); + this.moveMappingsFrom(def); + } + + protected void TokenEndpointDefinition.applyFrom(UntypedEndpointDefinition def) { + this.setAlwaysApply(def.getAlwaysApply()); + this.setToken(TokenComponent.createRef(def.getTokenOrType())); + this.moveMappingsFrom(def); + } + + protected void EndpointDefinition.moveMappingsFrom(UntypedEndpointDefinition def) { + // can safely iterate over list as we get an unmodifyable list + for (MappingDefinition mapping : def.getMappingList().toArray(new MappingDefinition[0])) { + def.removeMapping(mapping); + this.addMapping(mapping); + } + } + + private void UntypedEndpointDefinition.clearMappings() { + } + + eq UntypedEndpointDefinition.targetTypeName() = ""; + syn MEndpointDefinition UntypedEndpointDefinition.toMustache() { + throw new RuntimeException("UntypedEndpoint can not be transformed using toMustache!"); + } +} diff --git a/ragconnect.base/src/main/jastadd/parser/RagConnect.parser b/ragconnect.base/src/main/jastadd/parser/RagConnect.parser index a7ba289..1088ba5 100644 --- a/ragconnect.base/src/main/jastadd/parser/RagConnect.parser +++ b/ragconnect.base/src/main/jastadd/parser/RagConnect.parser @@ -43,49 +43,49 @@ EndpointDefinition endpoint_definition ; EndpointDefinition endpoint_definition_type - = RECEIVE token_ref {: return new ReceiveTokenEndpointDefinition().setToken(token_ref); :} - | SEND token_ref {: return new SendTokenEndpointDefinition().setToken(token_ref); :} - | RECEIVE TREE type_ref {: return new ReceiveTypeEndpointDefinition().setType(type_ref); :} - | RECEIVE TREE WITH ADD type_ref + = SEND ID.type_name DOT ID.child_name {: - ReceiveTypeEndpointDefinition result = new ReceiveTypeEndpointDefinition(); - result.setType(type_ref); - result.setWithAdd(true); + SendUntypedEndpointDefinition result = new SendUntypedEndpointDefinition(); + result.setTokenOrType(type_name + "." + child_name); + return result; + :} + | SEND INDEXED ID.type_name DOT ID.child_name + {: + SendUntypedEndpointDefinition result = new SendUntypedEndpointDefinition(); + result.setTokenOrType(type_name + "." + child_name); + result.setIndexed(true); + return result; + :} + | RECEIVE ID.type_name DOT ID.child_name + {: + ReceiveUntypedEndpointDefinition result = new ReceiveUntypedEndpointDefinition(); + result.setTokenOrType(type_name + "." + child_name); return result; :} - | SEND TREE type_ref {: return new SendTypeEndpointDefinition().setType(type_ref); :} - | RECEIVE LIST type_ref + | RECEIVE INDEXED ID.type_name DOT ID.child_name {: - ReceiveTypeEndpointDefinition result = new ReceiveTypeEndpointDefinition(); - result.setType(type_ref); - result.setUseList(true); + ReceiveUntypedEndpointDefinition result = new ReceiveUntypedEndpointDefinition(); + result.setTokenOrType(type_name + "." + child_name); + result.setIndexed(true); return result; :} - | RECEIVE LIST WITH ADD type_ref + | RECEIVE WITH ADD ID.type_name DOT ID.child_name {: - ReceiveTypeEndpointDefinition result = new ReceiveTypeEndpointDefinition(); - result.setType(type_ref); + ReceiveUntypedEndpointDefinition result = new ReceiveUntypedEndpointDefinition(); + result.setTokenOrType(type_name + "." + child_name); result.setWithAdd(true); - result.setUseList(true); return result; :} - | SEND LIST type_ref + | RECEIVE INDEXED WITH ADD ID.type_name DOT ID.child_name {: - SendTypeEndpointDefinition result = new SendTypeEndpointDefinition(); - result.setType(type_ref); - result.setUseList(true); + ReceiveUntypedEndpointDefinition result = new ReceiveUntypedEndpointDefinition(); + result.setTokenOrType(type_name + "." + child_name); + result.setIndexed(true); + result.setWithAdd(true); return result; :} ; -TokenComponent token_ref - = ID.type_name DOT ID.token_name {: return TokenComponent.createRef(type_name + "." + token_name); :} -; - -TypeComponent type_ref - = ID.parent_type_name DOT ID.child_type_name {: return TypeComponent.createRef(parent_type_name + "." + child_type_name); :} -; - ArrayList string_list = ID | string_list COMMA ID diff --git a/ragconnect.base/src/main/jastadd/scanner/Keywords.flex b/ragconnect.base/src/main/jastadd/scanner/Keywords.flex index 6983010..11f73da 100644 --- a/ragconnect.base/src/main/jastadd/scanner/Keywords.flex +++ b/ragconnect.base/src/main/jastadd/scanner/Keywords.flex @@ -5,7 +5,8 @@ "maps" { return sym(Terminals.MAPS); } "to" { return sym(Terminals.TO); } "as" { return sym(Terminals.AS); } -"tree" { return sym(Terminals.TREE); } -"list" { return sym(Terminals.LIST); } +//"tree" { return sym(Terminals.TREE); } +//"list" { return sym(Terminals.LIST); } "with" { return sym(Terminals.WITH); } +"indexed" { return sym(Terminals.INDEXED); } "add" { return sym(Terminals.ADD); } diff --git a/ragconnect.tests/src/test/01-input/list/Test.connect b/ragconnect.tests/src/test/01-input/list/Test.connect index c0efaea..7720e95 100644 --- a/ragconnect.tests/src/test/01-input/list/Test.connect +++ b/ragconnect.tests/src/test/01-input/list/Test.connect @@ -1,6 +1,6 @@ -send list SenderRoot.A ; -send list SenderRoot.SingleA ; -receive list ReceiverRoot.A ; -receive list ReceiverRoot.FromSingleA ; -receive list with add ReceiverRoot.WithAddFromA ; -receive list with add ReceiverRoot.WithAddFromSingleA ; +send indexed SenderRoot.A ; +send indexed SenderRoot.SingleA ; +receive indexed ReceiverRoot.A ; +receive indexed ReceiverRoot.FromSingleA ; +receive indexed with add ReceiverRoot.WithAddFromA ; +receive indexed with add ReceiverRoot.WithAddFromSingleA ; diff --git a/ragconnect.tests/src/test/01-input/singleList/Test.connect b/ragconnect.tests/src/test/01-input/singleList/Test.connect index 21b2796..8876730 100644 --- a/ragconnect.tests/src/test/01-input/singleList/Test.connect +++ b/ragconnect.tests/src/test/01-input/singleList/Test.connect @@ -1,13 +1,13 @@ -send tree SenderRoot.A1 ; -send tree SenderRoot.A2 ; -send tree SenderRoot.A3 ; -send tree SenderRoot.A4 ; +send SenderRoot.A1 ; +send SenderRoot.A2 ; +send SenderRoot.A3 ; +send SenderRoot.A4 ; send SenderRoot.InOutput using IntToA ; -receive tree ReceiverRoot.A ; -receive tree ReceiverRoot.UsingWildcardA ; -receive tree with add ReceiverRoot.WithAddA ; -receive tree with add ReceiverRoot.UsingWildcardWithAddA ; +receive ReceiverRoot.A ; +receive ReceiverRoot.UsingWildcardA ; +receive with add ReceiverRoot.WithAddA ; +receive with add ReceiverRoot.UsingWildcardWithAddA ; IntToA maps int i to A {: return new A().setID(i); diff --git a/ragconnect.tests/src/test/01-input/singleListVariant/Test.connect b/ragconnect.tests/src/test/01-input/singleListVariant/Test.connect index 2336510..6a33afe 100644 --- a/ragconnect.tests/src/test/01-input/singleListVariant/Test.connect +++ b/ragconnect.tests/src/test/01-input/singleListVariant/Test.connect @@ -1,28 +1,28 @@ -send tree SenderRoot.T_Empty ; -send tree SenderRoot.T_Token ; -send tree SenderRoot.T_OneChild ; -send tree SenderRoot.T_OneOpt ; -send tree SenderRoot.T_OneList ; -send tree SenderRoot.T_TwoChildren ; -send tree SenderRoot.T_OneOfEach ; -send tree SenderRoot.T_Abstract ; +send SenderRoot.T_Empty ; +send SenderRoot.T_Token ; +send SenderRoot.T_OneChild ; +send SenderRoot.T_OneOpt ; +send SenderRoot.T_OneList ; +send SenderRoot.T_TwoChildren ; +send SenderRoot.T_OneOfEach ; +send SenderRoot.T_Abstract ; -receive tree ReceiverRoot.T_Empty ; -receive tree ReceiverRoot.T_Token ; -receive tree ReceiverRoot.T_OneChild ; -receive tree ReceiverRoot.T_OneOpt ; -receive tree ReceiverRoot.T_OneList ; -receive tree ReceiverRoot.T_TwoChildren ; -receive tree ReceiverRoot.T_OneOfEach ; -receive tree ReceiverRoot.T_Abstract ; +receive ReceiverRoot.T_Empty ; +receive ReceiverRoot.T_Token ; +receive ReceiverRoot.T_OneChild ; +receive ReceiverRoot.T_OneOpt ; +receive ReceiverRoot.T_OneList ; +receive ReceiverRoot.T_TwoChildren ; +receive ReceiverRoot.T_OneOfEach ; +receive ReceiverRoot.T_Abstract ; -receive tree ReceiverRoot.MyEmpty ; +receive ReceiverRoot.MyEmpty ; -receive tree with add ReceiverRoot.EmptyWithAdd ; -receive tree with add ReceiverRoot.TokenWithAdd ; -receive tree with add ReceiverRoot.OneChildWithAdd ; -receive tree with add ReceiverRoot.OneOptWithAdd ; -receive tree with add ReceiverRoot.OneListWithAdd ; -receive tree with add ReceiverRoot.TwoChildrenWithAdd ; -receive tree with add ReceiverRoot.OneOfEachWithAdd ; -receive tree with add ReceiverRoot.AbstractWithAdd ; +receive with add ReceiverRoot.EmptyWithAdd ; +receive with add ReceiverRoot.TokenWithAdd ; +receive with add ReceiverRoot.OneChildWithAdd ; +receive with add ReceiverRoot.OneOptWithAdd ; +receive with add ReceiverRoot.OneListWithAdd ; +receive with add ReceiverRoot.TwoChildrenWithAdd ; +receive with add ReceiverRoot.OneOfEachWithAdd ; +receive with add ReceiverRoot.AbstractWithAdd ; diff --git a/ragconnect.tests/src/test/01-input/tree/Test.connect b/ragconnect.tests/src/test/01-input/tree/Test.connect index 857f629..3fc8564 100644 --- a/ragconnect.tests/src/test/01-input/tree/Test.connect +++ b/ragconnect.tests/src/test/01-input/tree/Test.connect @@ -1,2 +1,2 @@ -send tree SenderRoot.Alfa ; -receive tree ReceiverRoot.Alfa ; +send SenderRoot.Alfa ; +receive ReceiverRoot.Alfa ; diff --git a/ragconnect.tests/src/test/01-input/treeAllowedTokens/Test.connect b/ragconnect.tests/src/test/01-input/treeAllowedTokens/Test.connect index d872ce5..c17a58e 100644 --- a/ragconnect.tests/src/test/01-input/treeAllowedTokens/Test.connect +++ b/ragconnect.tests/src/test/01-input/treeAllowedTokens/Test.connect @@ -1,13 +1,13 @@ -send tree SenderRoot.Alfa ; -receive tree ReceiverRoot.Alfa ; +send SenderRoot.Alfa ; +receive ReceiverRoot.Alfa ; receive SenderRoot.Input1WhenFlagIsTrue ; receive SenderRoot.Input1WhenFlagIsFalse ; receive SenderRoot.Input2 ; receive SenderRoot.Input3 ; -send tree SenderRoot.AlfaPrimitive using Alfa2String ; -receive tree ReceiverRoot.AlfaPrimitive using String2Alfa ; +send SenderRoot.AlfaPrimitive using Alfa2String ; +receive ReceiverRoot.AlfaPrimitive using String2Alfa ; Alfa2String maps Alfa alfa to String {: StringBuilder sb = new StringBuilder(); -- GitLab From 9935a0932b9a023d5e82f2a75079b162172ab771 Mon Sep 17 00:00:00 2001 From: rschoene Date: Wed, 10 Nov 2021 13:00:00 +0100 Subject: [PATCH 2/5] begin with removing tree and list - renamed useList to isIndexBasedList (flipped semantics) - fixed readme of test singeList --- .../src/main/jastadd/RagConnect.relast | 2 +- .../main/jastadd/intermediate/Generation.jadd | 6 ++--- .../main/jastadd/intermediate/Mappings.jrag | 4 ++-- .../main/jastadd/parser/ParserRewrites.jrag | 12 +++------- .../main/resources/receiveDefinition.mustache | 22 +++++++++---------- .../src/test/01-input/list/Test.connect | 12 +++++----- .../src/test/01-input/singleList/README.md | 2 +- .../src/test/01-input/singleList/Test.connect | 8 +++---- 8 files changed, 31 insertions(+), 37 deletions(-) diff --git a/ragconnect.base/src/main/jastadd/RagConnect.relast b/ragconnect.base/src/main/jastadd/RagConnect.relast index 3728d41..4301c70 100644 --- a/ragconnect.base/src/main/jastadd/RagConnect.relast +++ b/ragconnect.base/src/main/jastadd/RagConnect.relast @@ -13,7 +13,7 @@ rel TokenEndpointDefinition.Token <-> TokenComponent.TokenEndpointDefinition*; ReceiveTokenEndpointDefinition : TokenEndpointDefinition; SendTokenEndpointDefinition : TokenEndpointDefinition; -abstract TypeEndpointDefinition : EndpointDefinition ::= ; +abstract TypeEndpointDefinition : EndpointDefinition ::= ; rel TypeEndpointDefinition.Type <-> TypeComponent.TypeEndpointDefinition*; ReceiveTypeEndpointDefinition : TypeEndpointDefinition ::= ; diff --git a/ragconnect.base/src/main/jastadd/intermediate/Generation.jadd b/ragconnect.base/src/main/jastadd/intermediate/Generation.jadd index b58b967..f4045d7 100644 --- a/ragconnect.base/src/main/jastadd/intermediate/Generation.jadd +++ b/ragconnect.base/src/main/jastadd/intermediate/Generation.jadd @@ -124,10 +124,10 @@ aspect AttributesForMustache { // --- MTypeEndpointDefinition --- syn boolean MTypeEndpointDefinition.isWithAdd() = endpointDef().isReceiveTypeEndpointDefinition() ? endpointDef().asReceiveTypeEndpointDefinition().getWithAdd() : false; - syn boolean MTypeEndpointDefinition.isUseList() = endpointDef().asTypeEndpointDefinition().getUseList(); + syn boolean MTypeEndpointDefinition.isIndexBasedListAccess() = endpointDef().asTypeEndpointDefinition().getIndexBasedListAccess(); eq MTypeEndpointDefinition.getterMethod() = "get" + typeName() + (typeIsList() ? "List" : ""); eq MTypeEndpointDefinition.parentTypeName() = type().containingTypeDecl().getName(); - eq MTypeEndpointDefinition.entityName() = typeName() + (isUseList() ? "List" : ""); + eq MTypeEndpointDefinition.entityName() = typeName() + (typeIsList() && !isIndexBasedListAccess() ? "List" : ""); // --- MInnerMappingDefinition --- inh boolean MInnerMappingDefinition.isLast(); @@ -398,7 +398,7 @@ aspect GrammarGeneration { syn TokenComponent EndpointDefinition.getTokenToCreate() = null; eq TypeEndpointDefinition.getTokenToCreate() { - if (typeIsList() && !getUseList()) { + if (typeIsList() && getIndexBasedListAccess()) { TokenComponent result = new TokenComponent(); result.setName(idTokenName()); result.setNTA(false); diff --git a/ragconnect.base/src/main/jastadd/intermediate/Mappings.jrag b/ragconnect.base/src/main/jastadd/intermediate/Mappings.jrag index 3a7fce5..99824ff 100644 --- a/ragconnect.base/src/main/jastadd/intermediate/Mappings.jrag +++ b/ragconnect.base/src/main/jastadd/intermediate/Mappings.jrag @@ -220,7 +220,7 @@ aspect Mappings { eq TypeEndpointDefinition.suitableReceiveDefaultMapping() { try { TypeDecl typeDecl = program().resolveTypeDecl(targetTypeName()); - return typeIsList() && getUseList() ? ragconnect().defaultBytesToListTreeMapping(typeDecl.getName()) : ragconnect().defaultBytesToTreeMapping(typeDecl.getName()); + return typeIsList() && !getIndexBasedListAccess() ? ragconnect().defaultBytesToListTreeMapping(typeDecl.getName()) : ragconnect().defaultBytesToTreeMapping(typeDecl.getName()); } catch (Exception ignore) {} return super.suitableReceiveDefaultMapping(); } @@ -256,7 +256,7 @@ aspect Mappings { eq TypeEndpointDefinition.suitableSendDefaultMapping() { try { TypeDecl typeDecl = program().resolveTypeDecl(targetTypeName()); - return typeIsList() && getUseList() ? ragconnect().defaultListTreeToBytesMapping() : ragconnect().defaultTreeToBytesMapping(typeDecl.getName()); + return typeIsList() && !getIndexBasedListAccess() ? ragconnect().defaultListTreeToBytesMapping() : ragconnect().defaultTreeToBytesMapping(typeDecl.getName()); } catch (Exception ignore) {} return super.suitableSendDefaultMapping(); } diff --git a/ragconnect.base/src/main/jastadd/parser/ParserRewrites.jrag b/ragconnect.base/src/main/jastadd/parser/ParserRewrites.jrag index 214fec4..faaf35a 100644 --- a/ragconnect.base/src/main/jastadd/parser/ParserRewrites.jrag +++ b/ragconnect.base/src/main/jastadd/parser/ParserRewrites.jrag @@ -4,9 +4,7 @@ aspect ParserRewrites { to SendTypeEndpointDefinition { SendTypeEndpointDefinition result = new SendTypeEndpointDefinition(); result.applyFrom(this); - if (this.getIndexed()) { - result.setUseList(true); - } + result.setIndexBasedListAccess(this.getIndexed()); return result; } } @@ -16,12 +14,8 @@ aspect ParserRewrites { to ReceiveTypeEndpointDefinition { ReceiveTypeEndpointDefinition result = new ReceiveTypeEndpointDefinition(); result.applyFrom(this); - if (this.getWithAdd()) { - result.setWithAdd(true); - } - if (this.getIndexed()) { - result.setUseList(true); - } + result.setWithAdd(this.getWithAdd()); + result.setIndexBasedListAccess(this.getIndexed()); return result; } } diff --git a/ragconnect.base/src/main/resources/receiveDefinition.mustache b/ragconnect.base/src/main/resources/receiveDefinition.mustache index c29eff1..2fd0ea2 100644 --- a/ragconnect.base/src/main/resources/receiveDefinition.mustache +++ b/ragconnect.base/src/main/resources/receiveDefinition.mustache @@ -1,5 +1,5 @@ {{#typeIsList}} -{{^UseList}} +{{#IndexBasedListAccess}} private int {{parentTypeName}}.{{resolveInListMethodName}}(String topic) { for (int index = 0; index < getNum{{entityName}}(); index++) { if (get{{entityName}}(index).get{{idTokenName}}().equals(topic)) { @@ -8,7 +8,7 @@ private int {{parentTypeName}}.{{resolveInListMethodName}}(String topic) { } return -1; } -{{/UseList}} +{{/IndexBasedListAccess}} {{/typeIsList}} /** @@ -17,13 +17,13 @@ private int {{parentTypeName}}.{{resolveInListMethodName}}(String topic) { * New values are appended to the end of the list. {{/isWithAdd}}{{/typeIsList}} * @param {{connectParameterName}} string describing protocol and path as an URI -{{#typeIsList}}{{^UseList}}{{^isWithAdd}} +{{#typeIsList}}{{#IndexBasedListAccess}}{{^isWithAdd}} * @param index index of node in list to connect (the list is expected to have enough elements) -{{/isWithAdd}}{{/UseList}}{{/typeIsList}} +{{/isWithAdd}}{{/IndexBasedListAccess}}{{/typeIsList}} * @return true if connect was successful, false otherwise * @throws java.io.IOException if connect failed */ -public boolean {{parentTypeName}}.{{connectMethod}}(String {{connectParameterName}}{{#typeIsList}}{{^UseList}}{{^isWithAdd}}, int index{{/isWithAdd}}{{/UseList}}{{/typeIsList}}) throws java.io.IOException { +public boolean {{parentTypeName}}.{{connectMethod}}(String {{connectParameterName}}{{#typeIsList}}{{#IndexBasedListAccess}}{{^isWithAdd}}, int index{{/isWithAdd}}{{/IndexBasedListAccess}}{{/typeIsList}}) throws java.io.IOException { java.util.function.BiConsumer consumer = (topic, message) -> { {{> mappingApplication}} {{#loggingEnabledForReads}} @@ -32,15 +32,15 @@ public boolean {{parentTypeName}}.{{connectMethod}}(String {{connectParameterNam {{#isTypeEndpointDefinition}} {{lastResult}}.treeResolveAll(); {{#typeIsList}} - {{#UseList}} + {{^IndexBasedListAccess}} {{#isWithAdd}} {{getterMethod}}().addAll({{lastResult}}); {{/isWithAdd}} {{^isWithAdd}} set{{entityName}}({{lastResult}}); {{/isWithAdd}} - {{/UseList}} - {{^UseList}} + {{/IndexBasedListAccess}} + {{#IndexBasedListAccess}} {{lastResult}}.set{{idTokenName}}(topic); {{#isWithAdd}} {{getterMethod}}().add({{lastResult}}); @@ -48,7 +48,7 @@ public boolean {{parentTypeName}}.{{connectMethod}}(String {{connectParameterNam {{^isWithAdd}} set{{entityName}}({{lastResult}}, index); {{/isWithAdd}} - {{/UseList}} + {{/IndexBasedListAccess}} {{/typeIsList}} {{^typeIsList}} set{{entityName}}({{lastResult}}); @@ -61,7 +61,7 @@ public boolean {{parentTypeName}}.{{connectMethod}}(String {{connectParameterNam return {{internalConnectMethod}}({{connectParameterName}}, consumer); } -{{#typeIsList}}{{^UseList}}{{^isWithAdd}} +{{#typeIsList}}{{#IndexBasedListAccess}}{{^isWithAdd}} /** * Connects the receive endpoint {{entityName}} using a "wildcard" URI (if supported by the chosen protocol). * @param {{connectParameterName}} string describing protocol and path as an URI @@ -84,7 +84,7 @@ public boolean {{parentTypeName}}.{{connectMethod}}(String {{connectParameterNam }; return {{internalConnectMethod}}({{connectParameterName}}, consumer); } -{{/isWithAdd}}{{/UseList}}{{/typeIsList}} +{{/isWithAdd}}{{/IndexBasedListAccess}}{{/typeIsList}} private boolean {{parentTypeName}}.{{internalConnectMethod}}(String {{connectParameterName}}, java.util.function.BiConsumer consumer) throws java.io.IOException { diff --git a/ragconnect.tests/src/test/01-input/list/Test.connect b/ragconnect.tests/src/test/01-input/list/Test.connect index 7720e95..f069ad8 100644 --- a/ragconnect.tests/src/test/01-input/list/Test.connect +++ b/ragconnect.tests/src/test/01-input/list/Test.connect @@ -1,6 +1,6 @@ -send indexed SenderRoot.A ; -send indexed SenderRoot.SingleA ; -receive indexed ReceiverRoot.A ; -receive indexed ReceiverRoot.FromSingleA ; -receive indexed with add ReceiverRoot.WithAddFromA ; -receive indexed with add ReceiverRoot.WithAddFromSingleA ; +send SenderRoot.A ; +send SenderRoot.SingleA ; +receive ReceiverRoot.A ; +receive ReceiverRoot.FromSingleA ; +receive with add ReceiverRoot.WithAddFromA ; +receive with add ReceiverRoot.WithAddFromSingleA ; diff --git a/ragconnect.tests/src/test/01-input/singleList/README.md b/ragconnect.tests/src/test/01-input/singleList/README.md index 6a76bb4..5d18043 100644 --- a/ragconnect.tests/src/test/01-input/singleList/README.md +++ b/ragconnect.tests/src/test/01-input/singleList/README.md @@ -18,7 +18,7 @@ SenderRoot ReceiverRoot ## Computation -A _n_ = Input _n_ + 1, e.g., A1 = Input1 + 1 +A _n_ = Input _n_ + _n_, e.g., A1 = Input1 + 1 and A3 = Input3 + 3 ## Execution-Trace (SendInitialValue) diff --git a/ragconnect.tests/src/test/01-input/singleList/Test.connect b/ragconnect.tests/src/test/01-input/singleList/Test.connect index 8876730..d4f5dec 100644 --- a/ragconnect.tests/src/test/01-input/singleList/Test.connect +++ b/ragconnect.tests/src/test/01-input/singleList/Test.connect @@ -4,10 +4,10 @@ send SenderRoot.A3 ; send SenderRoot.A4 ; send SenderRoot.InOutput using IntToA ; -receive ReceiverRoot.A ; -receive ReceiverRoot.UsingWildcardA ; -receive with add ReceiverRoot.WithAddA ; -receive with add ReceiverRoot.UsingWildcardWithAddA ; +receive indexed ReceiverRoot.A ; +receive indexed ReceiverRoot.UsingWildcardA ; +receive indexed with add ReceiverRoot.WithAddA ; +receive indexed with add ReceiverRoot.UsingWildcardWithAddA ; IntToA maps int i to A {: return new A().setID(i); -- GitLab From 04268a6fe18d3755053fec54c9b9acca673dd89a Mon Sep 17 00:00:00 2001 From: rschoene Date: Wed, 10 Nov 2021 13:15:44 +0100 Subject: [PATCH 3/5] begin with removing tree and list - fixed test singeListVariant --- .../01-input/singleListVariant/Test.connect | 34 +++++++++---------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/ragconnect.tests/src/test/01-input/singleListVariant/Test.connect b/ragconnect.tests/src/test/01-input/singleListVariant/Test.connect index 6a33afe..eca7f99 100644 --- a/ragconnect.tests/src/test/01-input/singleListVariant/Test.connect +++ b/ragconnect.tests/src/test/01-input/singleListVariant/Test.connect @@ -7,22 +7,22 @@ send SenderRoot.T_TwoChildren ; send SenderRoot.T_OneOfEach ; send SenderRoot.T_Abstract ; -receive ReceiverRoot.T_Empty ; -receive ReceiverRoot.T_Token ; -receive ReceiverRoot.T_OneChild ; -receive ReceiverRoot.T_OneOpt ; -receive ReceiverRoot.T_OneList ; -receive ReceiverRoot.T_TwoChildren ; -receive ReceiverRoot.T_OneOfEach ; -receive ReceiverRoot.T_Abstract ; +receive indexed ReceiverRoot.T_Empty ; +receive indexed ReceiverRoot.T_Token ; +receive indexed ReceiverRoot.T_OneChild ; +receive indexed ReceiverRoot.T_OneOpt ; +receive indexed ReceiverRoot.T_OneList ; +receive indexed ReceiverRoot.T_TwoChildren ; +receive indexed ReceiverRoot.T_OneOfEach ; +receive indexed ReceiverRoot.T_Abstract ; -receive ReceiverRoot.MyEmpty ; +receive indexed ReceiverRoot.MyEmpty ; -receive with add ReceiverRoot.EmptyWithAdd ; -receive with add ReceiverRoot.TokenWithAdd ; -receive with add ReceiverRoot.OneChildWithAdd ; -receive with add ReceiverRoot.OneOptWithAdd ; -receive with add ReceiverRoot.OneListWithAdd ; -receive with add ReceiverRoot.TwoChildrenWithAdd ; -receive with add ReceiverRoot.OneOfEachWithAdd ; -receive with add ReceiverRoot.AbstractWithAdd ; +receive indexed with add ReceiverRoot.EmptyWithAdd ; +receive indexed with add ReceiverRoot.TokenWithAdd ; +receive indexed with add ReceiverRoot.OneChildWithAdd ; +receive indexed with add ReceiverRoot.OneOptWithAdd ; +receive indexed with add ReceiverRoot.OneListWithAdd ; +receive indexed with add ReceiverRoot.TwoChildrenWithAdd ; +receive indexed with add ReceiverRoot.OneOfEachWithAdd ; +receive indexed with add ReceiverRoot.AbstractWithAdd ; -- GitLab From 0d65fe3a3e448f5db47b8e8b5899557ffa31a63c Mon Sep 17 00:00:00 2001 From: rschoene Date: Tue, 23 Nov 2021 13:35:56 +0100 Subject: [PATCH 4/5] cleanup --- pages/docs/using.md | 6 +++--- ragconnect.base/src/main/jastadd/intermediate/Mappings.jrag | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/pages/docs/using.md b/pages/docs/using.md index 43df073..526ce6f 100644 --- a/pages/docs/using.md +++ b/pages/docs/using.md @@ -5,9 +5,9 @@ The full example is available at // B* ; @@ -92,7 +92,7 @@ b1.connectOutputOnB("mqtt://localhost/b1/out", true); b2.connectOutputOnB("mqtt://localhost/b2/out", false); ``` -The first parameter of those connect-methods is always an URI-like String, to identify the protocol to use, the server operating the protocol, and a path to identify the concrete token. +The first parameter of those connect-methods is always a URI-like String, to identify the protocol to use, the server operating the protocol, and a path to identify the concrete token. In case of MQTT, the server is the host running an MQTT broker, and the path is equal to the topic to publish or subscribe to. Please note, that the first leading slash (`/`) is removed for MQTT topics, e.g., for `A.Input` the topic is actually `topic/for/input`. diff --git a/ragconnect.base/src/main/jastadd/intermediate/Mappings.jrag b/ragconnect.base/src/main/jastadd/intermediate/Mappings.jrag index 99824ff..9d12297 100644 --- a/ragconnect.base/src/main/jastadd/intermediate/Mappings.jrag +++ b/ragconnect.base/src/main/jastadd/intermediate/Mappings.jrag @@ -145,7 +145,7 @@ aspect Mappings { // if no mappings are specified, or if first mapping is not suitable. // then prepend the suitable default mapping if (getMappingList().isEmpty() || !getMappingList().get(0).getFromType().isByteArray()) { - result = new java.util.ArrayList(); + result = new java.util.ArrayList<>(); result.add(suitableReceiveDefaultMapping()); result.addAll(getMappingList()); } else { @@ -155,7 +155,7 @@ aspect Mappings { // if no mappings are specified, or if last mapping is not suitable // then append the suitable default mapping if (getMappingList().isEmpty() || !getMappingList().get(getMappingList().size() - 1).getToType().isByteArray()) { - result = new java.util.ArrayList(getMappingList()); + result = new java.util.ArrayList<>(getMappingList()); result.add(suitableSendDefaultMapping()); } else { result = getMappingList(); -- GitLab From 7e806926fdf191c0fb77f874fafd72ca00f46f03 Mon Sep 17 00:00:00 2001 From: rschoene Date: Wed, 24 Nov 2021 14:01:59 +0100 Subject: [PATCH 5/5] Add DSL description to documentation. - contains features still to be implemented --- pages/docs/dsl.md | 89 +++++++++++++++++++++++++++++++++++++++++++++++ pages/mkdocs.yml | 2 ++ 2 files changed, 91 insertions(+) create mode 100644 pages/docs/dsl.md diff --git a/pages/docs/dsl.md b/pages/docs/dsl.md new file mode 100644 index 0000000..11bdae7 --- /dev/null +++ b/pages/docs/dsl.md @@ -0,0 +1,89 @@ +!!! attention + Not all features described here are (fully) implemented yet, please see the [progress of milestone for 1.0.0](https://git-st.inf.tu-dresden.de/jastadd/ragconnect/-/milestones/2) first. + +# The RagConnect Specification Language + +To declare endpoints and mappings, a domain-specific language ([DSL](https://en.wikipedia.org/wiki/Domain-specific_language)) is used. + +## Endpoints + +An endpoint marks an element of an AST as sending or receiving element. +The kind of the element determines, whether an endpoint for it can be receiving, sending, or both at the same time. + +To declare a new endpoints, use the following syntax: + +``` +("send"|"receive") ["indexed"] ["with add"] [.["()"]] ["using" (, )*] ";" +``` + +A breakdown of the parts of that syntax: + +- The first word (`send` or `receive`) defines the kind of endpoint - sending or receiving, respectively. +- The optional `indexed` applies only for list children and lets the endpoint act on elements of that list. + This only works for receiving endpoints, and is further changed by `with add`. + - A lonely `indexed` assigns each incoming "topic" to an index in a list. + This can be useful if multiple instances of this endpoint are connected, or the communication protocol supports wildcard topics. + For the former case, the connect method with an explicit index can be used, whereas the "normal" connect method without the index acts as a method for "wildcard-connect". + - Combining `indexed with add`, incoming data is required to be an element of the list, and will be appended to the list. +- The second optional keyword `with add` can also be used only for receiving endpoints targeting a list children. + As described above, it can be combined with `indexed`. + If used on its own, the incoming data is interpreted as a complete list and its elements will be appended to the current list. +- The `[.["()"]]` notation describes the actual affected node. + - If the target is omitted, all nodes of that non-terminal type can be connected, irrespective of their context. + - The target can be any child on the right-hand side of a production rule, a role of a relation, or an attribute. + The brackets `()` after the target must be used in case of an attribute, and only then. +- Optionally, an endpoint can use one or more [mappings](#mappings). + They will be applied before sending, or after receiving a message. + Mappings will always be applied in the order they are listed after `using`. + +## Mappings + +A mapping is a side effect-free function with one argument (the value that will be transformed) and one result (the transformed value), that will be applied on a value to be sent for a sending endpoint, a received value for a receiving endpoint, or the result of another mapping. +Mappings can be shared between endpoints. + +To declare a mapping, use the following syntax: + +``` + "maps" "to" "To-Type" "{:" + +":}" +``` + +A breakdown of the parts of that syntax: + +- The `` identifies the mapping. +- The `` defines the name of it. +- The `` is the type of the result. The type of the last mapping of a sending endpoint must be `byte[]`. +- Finally, the `` is the actual definition of the mapping using normal Java syntax. + The previously defined input variable can be used via its name here. + This block can contain multiple statements, but must end with a `return` statement. + The validity of this block is not verified by RagConnect itself, but later in the compilation process by the Java compiler. + +Note: There are default mappings provided for all primitive Java types (using their "normal" byte representation), and for all non-terminal types (using their JSON representation converted from/to bytes). +Those default mappings apply to both sending and receiving endpoints, and match their counterparts, e.g., the mapping from `int` to `byte[]` uses the same byte representation as the mapping back from `byte[]` to `int`. +Default mappings are always inserted if either no mapping is present, or if the type of the first/last mapping is not `byte[]` as stated above. +Their main intent is to allow quick prototyping without constraining a more complex use case. + +## Dependency definitions + +!!! note + Deprecated since `1.0.0` + +A dependency definition describes a possible dependency on type-level from a token to an attribute. +Whenever the token changes, the attribute is eagerly re-computed and endpoints attached to it are triggered. + +Such a dependency must be added on instance-level for every token that could have an influence to the attribute. +An alternative for those explicit dependency definitions is [incremental dependency tracking](/using#dependency-tracking-automatically-derived). + +To declare a dependency definition, use the following syntax: + +``` +. "canDependOn" . "as" ";" +``` + +A breakdown of the parts of that syntax: + +- `.` denotes the attribute (and the non-terminal it is defined on) which depends on the token +- `.` denotes the token (and the non-terminal it is defined on) that (potentially) influences the attribute value +- `` identifies the dependency definition and is used for the generated method, which will be defined on `Non-Terminal-1` as `.add( influencingNode)` diff --git a/pages/mkdocs.yml b/pages/mkdocs.yml index c00e8c5..4c2d24f 100644 --- a/pages/mkdocs.yml +++ b/pages/mkdocs.yml @@ -6,6 +6,7 @@ nav: - "RagConnect by Example": using.md - "Use Cases": use_cases.md - "Adding RagConnect to your project": adding.md + - "RagConnect Specification Language": dsl.md - "Compiler options": compiler.md - "Inner workings": inner-workings.md - "Extending RagConnect": extending.md @@ -19,6 +20,7 @@ theme: markdown_extensions: - toc: permalink:  + - admonition plugins: - search -- GitLab