From 81c1b10c8ccdc7176b3613ecfb3f120e4a1e0abc Mon Sep 17 00:00:00 2001 From: rschoene <rene.schoene@tu-dresden.de> Date: Wed, 6 May 2020 20:14:46 +0200 Subject: [PATCH] Step forward to working generation. - Copied (and modified) buildSrc from relast. Added compilerLocation property to set a jar to execute. - Completed example code with computation attributes - Fixed various bugs in Generation.jadd - Wrap application of mappings with try/catch and let mapping methods throw Exception - Add grammar modification for TokenComponent used as source in dependency definition - Add grammar extension to include relations generated by dependency definitions - Prepare Ros2Rag.relast for default mappings (not implemented yet) --- src/main/jastadd/Ros2Rag.relast | 7 +- src/main/jastadd/backend/Generation.jadd | 73 +++++++++++++++++-- .../jastadd/ros2rag/compiler/Compiler.java | 8 +- src/main/resources/MqttUpdater.jadd | 2 +- 4 files changed, 73 insertions(+), 17 deletions(-) diff --git a/src/main/jastadd/Ros2Rag.relast b/src/main/jastadd/Ros2Rag.relast index 1669503..1008207 100644 --- a/src/main/jastadd/Ros2Rag.relast +++ b/src/main/jastadd/Ros2Rag.relast @@ -11,11 +11,12 @@ ReadFromMqttDefinition : TokenUpdateDefinition; WriteToMqttDefinition : TokenUpdateDefinition; // example: RobotArm._AppropriateSpeed canDependOn Joint.CurrentPosition as dependency1 -DependencyDefinition ::= <ID> ; -rel DependencyDefinition.Source -> TokenComponent ; -rel DependencyDefinition.Target -> TokenComponent ; +DependencyDefinition ::= <ID>; +rel DependencyDefinition.Source <-> TokenComponent.DependencySourceDefinition*; +rel DependencyDefinition.Target -> TokenComponent; MappingDefinition ::= <ID> FromType:MappingDefinitionType <FromVariableName> ToType:MappingDefinitionType <Content> ; abstract MappingDefinitionType ::= ; JavaMappingDefinitionType : MappingDefinitionType ::= Type:JavaTypeUse ; JavaArrayMappingDefinitionType : MappingDefinitionType ::= Type:JavaTypeUse ; +DefaultMappingDefinition : MappingDefinition ; diff --git a/src/main/jastadd/backend/Generation.jadd b/src/main/jastadd/backend/Generation.jadd index c5f253f..75be20c 100644 --- a/src/main/jastadd/backend/Generation.jadd +++ b/src/main/jastadd/backend/Generation.jadd @@ -11,6 +11,8 @@ aspect GenerationUtils { } aspect AspectGeneration { + syn String TokenComponent.internalName() = getDependencySourceDefinitionList().isEmpty() ? externalName() : "_internal_" + getName(); + syn String TokenComponent.externalName() = getName(); // naming convention attributes syn String TokenUpdateDefinition.connectMethod() = "connect" + getToken().getName(); @@ -24,7 +26,7 @@ aspect AspectGeneration { Character.toUpperCase(getID().charAt(0)) + getID().substring(1); syn String DependencyDefinition.internalRelationPrefix() = "_internal_" + getID(); - syn String DependencyDefinition.internalTokenName() = "_internal" + getSource().getName(); + syn String DependencyDefinition.internalTokenName() = getSource().internalName(); inh String UpdateDefinition.mqttUpdaterAttribute(); inh String MappingDefinition.mqttUpdaterAttribute(); @@ -66,7 +68,7 @@ aspect AspectGeneration { sb.append(ind(1)).append("}\n\n"); // mqttWaitUntilReady - sb.append(ind(1)).append("public void ").append(rootNodeName).append(".") + sb.append(ind(1)).append("public boolean ").append(rootNodeName).append(".") .append(mqttWaitUntilReadyMethod()).append("(long time, java.util.concurrent.TimeUnit unit) {\n"); sb.append(ind(2)).append("return ").append(mqttUpdaterField()).append(".waitUntilReady(time, unit);\n"); sb.append(ind(1)).append("}\n\n"); @@ -111,20 +113,32 @@ aspect AspectGeneration { String initialInputVariableName) { final String resultVariablePrefix = "result"; // we do not need "_" here, because methodName begins with one String inputVariableName = initialInputVariableName; + // last variable need to be declared before begin of try + MappingDefinition lastDefinition = getMappingList().get(getMappingList().size() - 1); + sb.append(ind(indent)).append(lastDefinition.getToType().prettyPrint()).append(" ") + .append(resultVariablePrefix).append(lastDefinition.methodName()).append(";\n"); + sb.append(ind(indent)).append("try {\n"); for (MappingDefinition mappingDefinition : getMappingList()) { String resultVariableName = resultVariablePrefix + mappingDefinition.methodName(); - sb.append(ind(indent)).append(mappingDefinition.getToType().prettyPrint()).append(" ") - .append(resultVariablePrefix).append(mappingDefinition.methodName()) + sb.append(ind(indent + 1)); + if (mappingDefinition != lastDefinition) { + sb.append(mappingDefinition.getToType().prettyPrint()).append(" "); + } + sb.append(resultVariablePrefix).append(mappingDefinition.methodName()) .append(" = ").append(mappingDefinition.methodName()).append("(") .append(inputVariableName).append(");\n"); inputVariableName = resultVariableName; } + sb.append(ind(indent)).append("} catch (Exception e) {\n"); + sb.append(ind(indent + 1)).append("e.printStackTrace();\n"); + sb.append(ind(indent + 1)).append(preemptiveReturnStatement()).append("\n"); + sb.append(ind(indent)).append("}\n"); if (!getAlwaysApply()) { - sb.append(ind(indent)).append("if (get").append(getToken().getName()).append("()"); + sb.append(ind(indent)).append("if (").append(preemptiveExpectedValue()); if (getToken().isPrimitiveType()) { sb.append(" == ").append(inputVariableName); } else { - sb.append(" != null ? get").append(getToken().getName()).append("().equals(") + sb.append(" != null ? ").append(preemptiveExpectedValue()).append(".equals(") .append(inputVariableName).append(")").append(" : ") .append(inputVariableName).append(" == null"); } @@ -133,6 +147,10 @@ aspect AspectGeneration { return inputVariableName; } + syn String TokenUpdateDefinition.preemptiveExpectedValue(); + eq ReadFromMqttDefinition.preemptiveExpectedValue() = "get" + getToken().getName() + "()"; + eq WriteToMqttDefinition.preemptiveExpectedValue() = lastValue(); + syn String TokenUpdateDefinition.preemptiveReturnStatement(); eq ReadFromMqttDefinition.preemptiveReturnStatement() = "return;"; eq WriteToMqttDefinition.preemptiveReturnStatement() = "return false;"; @@ -188,7 +206,8 @@ aspect AspectGeneration { void MappingDefinition.generateAspect(StringBuilder sb) { sb.append(ind(1)).append("protected static ").append(getToType().prettyPrint()) .append(" ASTNode.").append(methodName()).append("(") - .append(getFromType().prettyPrint()).append(" ").append(getFromVariableName()).append(") {\n"); + .append(getFromType().prettyPrint()).append(" ").append(getFromVariableName()) + .append(") throws Exception {\n"); for (String line : getContent().split("\n")) { if (!line.trim().isEmpty()) { sb.append(ind(2)).append(line).append("\n"); @@ -226,7 +245,45 @@ aspect AspectGeneration { sb.append(ind(1)).append("public "); getSource().getJavaTypeUse().generateAbstractGrammar(sb); sb.append(" ").append(sourceParentTypeName).append(".get").append(getSource().getName()).append("() {\n"); - sb.append(ind(2)).append("return get").append(internalTokenName()).append(";\n"); + sb.append(ind(2)).append("return get").append(internalTokenName()).append("();\n"); sb.append(ind(1)).append("}\n\n"); } } + +aspect RelationGeneration { + syn java.util.List<Relation> Ros2Rag.additionalRelations() { + java.util.List<Relation> result = new java.util.ArrayList<>(); + for (DependencyDefinition dd : getDependencyDefinitionList()) { + result.add(dd.getRelationToCreate()); + } + return result; + } + + syn nta Relation DependencyDefinition.getRelationToCreate() { + BidirectionalRelation result = new BidirectionalRelation(); + NavigableRole left = new ListRole(internalRelationPrefix() + "Source"); + left.setType(getTarget().containingTypeDecl()); + NavigableRole right = new ListRole(internalRelationPrefix() + "Target"); + right.setType(getSource().containingTypeDecl()); + result.setLeft(left); + result.setRight(right); + return result; + } +} + +aspect GrammarExtension { + refine BackendAbstractGrammar public void TokenComponent.generateAbstractGrammar(StringBuilder b) { + if (getNTA()) { + b.append("/"); + } + b.append("<"); + if (!getName().equals("")) { + b.append(internalName()).append(":"); + } + getJavaTypeUse().generateAbstractGrammar(b); + b.append(">"); + if (getNTA()) { + b.append("/"); + } + } +} diff --git a/src/main/java/org/jastadd/ros2rag/compiler/Compiler.java b/src/main/java/org/jastadd/ros2rag/compiler/Compiler.java index a4f5bdc..7cd97a3 100644 --- a/src/main/java/org/jastadd/ros2rag/compiler/Compiler.java +++ b/src/main/java/org/jastadd/ros2rag/compiler/Compiler.java @@ -139,11 +139,12 @@ public class Compiler { private Ros2Rag parseProgram(String inputGrammarFileName, String inputRos2RagFileName) throws CompilerException { Program program = new Program(); Ros2Rag ros2Rag; + GrammarFile inputGrammar; try (BufferedReader reader = Files.newBufferedReader(Paths.get(inputGrammarFileName))) { Ros2RagScanner scanner = new Ros2RagScanner(reader); Ros2RagParser parser = new Ros2RagParser(); - GrammarFile inputGrammar = (GrammarFile) parser.parse(scanner); + inputGrammar = (GrammarFile) parser.parse(scanner); inputGrammar.dumpTree(System.out); program.addGrammarFile(inputGrammar); inputGrammar.treeResolveAll(); @@ -159,11 +160,8 @@ public class Compiler { } catch (IOException | Parser.Exception e) { throw new CompilerException("Could not parse ros2rag file " + inputRos2RagFileName, e); } - - ros2Rag.dumpTree(System.out); ros2Rag.treeResolveAll(); - ros2Rag.dumpTree(System.out); - + ros2Rag.additionalRelations().forEach(inputGrammar::addDeclaration); return ros2Rag; } diff --git a/src/main/resources/MqttUpdater.jadd b/src/main/resources/MqttUpdater.jadd index 53fa6cf..ef3e483 100644 --- a/src/main/resources/MqttUpdater.jadd +++ b/src/main/resources/MqttUpdater.jadd @@ -144,7 +144,7 @@ public class MqttUpdater { callbacks.put(topic, callback); // subscribe at broker - Topic[] topicArray = { new Topic(topic, this.qos) }; + org.fusesource.mqtt.client.Topic[] topicArray = { new org.fusesource.mqtt.client.Topic(topic, this.qos) }; connection.subscribe(topicArray, new org.fusesource.mqtt.client.Callback<byte[]>() { @Override public void onSuccess(byte[] qoses) { -- GitLab