From e8eaab35d35fb69af395ff11237914429811e0cd Mon Sep 17 00:00:00 2001 From: rschoene <rene.schoene@tu-dresden.de> Date: Thu, 28 May 2020 18:30:23 +0200 Subject: [PATCH] Integrated default mapping definitions. - supported types: int, short, long, float, double, char, and all their boxed variants, and String - default mapping definitions are NTAs which get reused for every update definition that needs them - change generated check for not always apply (case for boxed types) - cleanup parser --- src/main/jastadd/Analysis.jrag | 3 +- src/main/jastadd/Navigation.jrag | 4 + src/main/jastadd/backend/Generation.jadd | 9 +- src/main/jastadd/backend/Mappings.jrag | 204 +++++++++++++++++++++++ src/main/jastadd/parser/Ros2Rag.parser | 7 - 5 files changed, 216 insertions(+), 11 deletions(-) create mode 100644 src/main/jastadd/backend/Mappings.jrag diff --git a/src/main/jastadd/Analysis.jrag b/src/main/jastadd/Analysis.jrag index 246645f..6c8755e 100644 --- a/src/main/jastadd/Analysis.jrag +++ b/src/main/jastadd/Analysis.jrag @@ -4,8 +4,9 @@ aspect Analysis { syn boolean JavaTypeUse.isPrimitiveType() = false; eq SimpleJavaTypeUse.isPrimitiveType() { switch(getName()) { - case "short": case "int": + case "short": + case "long": case "float": case "double": case "char": diff --git a/src/main/jastadd/Navigation.jrag b/src/main/jastadd/Navigation.jrag index a43beba..ce20294 100644 --- a/src/main/jastadd/Navigation.jrag +++ b/src/main/jastadd/Navigation.jrag @@ -34,4 +34,8 @@ aspect Navigation { } return null; } + + // --- isDefaultMappingDefinition --- + syn boolean MappingDefinition.isDefaultMappingDefinition() = false; + eq DefaultMappingDefinition.isDefaultMappingDefinition() = true; } diff --git a/src/main/jastadd/backend/Generation.jadd b/src/main/jastadd/backend/Generation.jadd index b74743d..e827c68 100644 --- a/src/main/jastadd/backend/Generation.jadd +++ b/src/main/jastadd/backend/Generation.jadd @@ -95,7 +95,7 @@ aspect AspectGeneration { for (UpdateDefinition def : getUpdateDefinitionList()) { def.generateAspect(sb); } - for (MappingDefinition def : getMappingDefinitionList()) { + for (MappingDefinition def : allMappingDefinitions()) { def.generateAspect(sb); } for (DependencyDefinition def : getDependencyDefinitionList()) { @@ -112,11 +112,11 @@ aspect AspectGeneration { 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); + MappingDefinition lastDefinition = effectiveMappings().get(effectiveMappings().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()) { + for (MappingDefinition mappingDefinition : effectiveMappings()) { String resultVariableName = resultVariablePrefix + mappingDefinition.methodName(); sb.append(ind(indent + 1)); if (mappingDefinition != lastDefinition) { @@ -135,6 +135,9 @@ aspect AspectGeneration { sb.append(ind(indent)).append("if (").append(preemptiveExpectedValue()); if (getToken().isPrimitiveType()) { sb.append(" == ").append(inputVariableName); + } else if (effectiveMappings().get(effectiveMappings().size() - 1).isDefaultMappingDefinition()) { + sb.append(" != null && ").append(preemptiveExpectedValue()).append(".equals(") + .append(inputVariableName).append(")"); } else { sb.append(" != null ? ").append(preemptiveExpectedValue()).append(".equals(") .append(inputVariableName).append(")").append(" : ") diff --git a/src/main/jastadd/backend/Mappings.jrag b/src/main/jastadd/backend/Mappings.jrag new file mode 100644 index 0000000..4bfe070 --- /dev/null +++ b/src/main/jastadd/backend/Mappings.jrag @@ -0,0 +1,204 @@ +aspect DefaultMappings { + + private DefaultMappingDefinition Ros2Rag.baseDefaultMappingDefinitionFromBytes(String typeName) { + DefaultMappingDefinition result = new DefaultMappingDefinition(); + result.setID("_DefaultBytesTo" + Character.toUpperCase(typeName.charAt(0)) + typeName.substring(1) + "Mapping"); + result.setFromType(new JavaArrayMappingDefinitionType(new SimpleJavaTypeUse("byte"))); + result.setFromVariableName("bytes"); + result.setToType(new JavaMappingDefinitionType(new SimpleJavaTypeUse(typeName))); + return result; + } + + private DefaultMappingDefinition Ros2Rag.baseDefaultMappingDefinitionToBytes(String typeName) { + DefaultMappingDefinition result = new DefaultMappingDefinition(); + result.setID("_Default" + Character.toUpperCase(typeName.charAt(0)) + typeName.substring(1) + "ToBytesMapping"); + result.setFromType(new JavaMappingDefinitionType(new SimpleJavaTypeUse(typeName))); + result.setFromVariableName("input"); + result.setToType(new JavaArrayMappingDefinitionType(new SimpleJavaTypeUse("byte"))); + return result; + } + + syn nta DefaultMappingDefinition Ros2Rag.defaultBytesToIntMapping() { + DefaultMappingDefinition result = baseDefaultMappingDefinitionFromBytes("int"); + result.setContent("return java.nio.ByteBuffer.wrap(bytes).getInt();"); + return result; + } + + syn nta DefaultMappingDefinition Ros2Rag.defaultBytesToShortMapping() { + DefaultMappingDefinition result = baseDefaultMappingDefinitionFromBytes("short"); + result.setContent("return java.nio.ByteBuffer.wrap(bytes).getShort();"); + return result; + } + + syn nta DefaultMappingDefinition Ros2Rag.defaultBytesToLongMapping() { + DefaultMappingDefinition result = baseDefaultMappingDefinitionFromBytes("long"); + result.setContent("return java.nio.ByteBuffer.wrap(bytes).getLong();"); + return result; + } + + syn nta DefaultMappingDefinition Ros2Rag.defaultBytesToFloatMapping() { + DefaultMappingDefinition result = baseDefaultMappingDefinitionFromBytes("float"); + result.setContent("return java.nio.ByteBuffer.wrap(bytes).getFloat();"); + return result; + } + + syn nta DefaultMappingDefinition Ros2Rag.defaultBytesToDoubleMapping() { + DefaultMappingDefinition result = baseDefaultMappingDefinitionFromBytes("double"); + result.setContent("return java.nio.ByteBuffer.wrap(bytes).getDouble();"); + return result; + } + + syn nta DefaultMappingDefinition Ros2Rag.defaultBytesToCharMapping() { + DefaultMappingDefinition result = baseDefaultMappingDefinitionFromBytes("char"); + result.setContent("return java.nio.ByteBuffer.wrap(bytes).getChar();"); + return result; + } + + syn nta DefaultMappingDefinition Ros2Rag.defaultBytesToStringMapping() { + DefaultMappingDefinition result = baseDefaultMappingDefinitionFromBytes("String"); + result.setContent("return new String(bytes);"); + return result; + } + + syn nta DefaultMappingDefinition Ros2Rag.defaultIntToBytesMapping() { + DefaultMappingDefinition result = baseDefaultMappingDefinitionToBytes("int"); + result.setContent("return java.nio.ByteBuffer.allocate(4).putInt(input).array();"); + return result; + } + + syn nta DefaultMappingDefinition Ros2Rag.defaultShortToBytesMapping() { + DefaultMappingDefinition result = baseDefaultMappingDefinitionToBytes("short"); + result.setContent("return java.nio.ByteBuffer.allocate(2).putShort(input).array();"); + return result; + } + + syn nta DefaultMappingDefinition Ros2Rag.defaultLongToBytesMapping() { + DefaultMappingDefinition result = baseDefaultMappingDefinitionToBytes("long"); + result.setContent("return java.nio.ByteBuffer.allocate(8).putLong(input).array();"); + return result; + } + + syn nta DefaultMappingDefinition Ros2Rag.defaultFloatToBytesMapping() { + DefaultMappingDefinition result = baseDefaultMappingDefinitionToBytes("float"); + result.setContent("return java.nio.ByteBuffer.allocate(4).putFloat(input).array();"); + return result; + } + + syn nta DefaultMappingDefinition Ros2Rag.defaultDoubleToBytesMapping() { + DefaultMappingDefinition result = baseDefaultMappingDefinitionToBytes("double"); + result.setContent("return java.nio.ByteBuffer.allocate(8).putDouble(input).array();"); + return result; + } + + syn nta DefaultMappingDefinition Ros2Rag.defaultCharToBytesMapping() { + DefaultMappingDefinition result = baseDefaultMappingDefinitionToBytes("char"); + result.setContent("return java.nio.ByteBuffer.allocate(2).putChar(input).array();"); + return result; + } + + syn nta DefaultMappingDefinition Ros2Rag.defaultStringToBytesMapping() { + DefaultMappingDefinition result = baseDefaultMappingDefinitionToBytes("String"); + result.setContent("return input.getBytes();"); + return result; + } +} + +aspect Mappings { + // --- effectiveMappings --- + syn java.util.List<MappingDefinition> UpdateDefinition.effectiveMappings(); + eq ReadFromMqttDefinition.effectiveMappings() { + // if there is a first mapping, check if its input type is byte[]. + // or if no mappings are specified. + // then prepend the suitable default mapping + java.util.List<MappingDefinition> result; + if (getMappingList().size() == 0 || !getMappingList().get(0).getFromType().isByteArray()) { + result = new java.util.ArrayList(); + result.add(suitableDefaultMapping()); + result.addAll(getMappingList()); + } else { + result = getMappingList(); + } + return result; + } + eq WriteToMqttDefinition.effectiveMappings() { + // if there is a mapping, check if the output type of the last mapping is byte[]. + // or if no mappings are specified. + // then append the suitable default mapping + java.util.List<MappingDefinition> result; + int numMappings = getMappingList().size(); + if (numMappings == 0 || !getMappingList().get(numMappings - 1).getToType().isByteArray()) { + result = new java.util.ArrayList(); + result.addAll(getMappingList()); + result.add(suitableDefaultMapping()); + } else { + result = getMappingList(); + } + return result; + } + + // --- suitableDefaultMapping --- + syn DefaultMappingDefinition UpdateDefinition.suitableDefaultMapping(); + eq ReadFromMqttDefinition.suitableDefaultMapping() { + String typeName = getToken().getJavaTypeUse().getName(); + switch(typeName) { + case "int": + case "Integer": return ros2rag().defaultBytesToIntMapping(); + case "short": + case "Short": return ros2rag().defaultBytesToShortMapping(); + case "long": + case "Long": return ros2rag().defaultBytesToLongMapping(); + case "float": + case "Float": return ros2rag().defaultBytesToFloatMapping(); + case "double": + case "Double": return ros2rag().defaultBytesToDoubleMapping(); + case "char": + case "Character": return ros2rag().defaultBytesToCharMapping(); + case "String": return ros2rag().defaultBytesToStringMapping(); + default: return null; + } + } + eq WriteToMqttDefinition.suitableDefaultMapping() { + String typeName = getToken().getJavaTypeUse().getName(); + switch(typeName) { + case "int": + case "Integer": return ros2rag().defaultIntToBytesMapping(); + case "short": + case "Short": return ros2rag().defaultShortToBytesMapping(); + case "long": + case "Long": return ros2rag().defaultLongToBytesMapping(); + case "float": + case "Float": return ros2rag().defaultFloatToBytesMapping(); + case "double": + case "Double": return ros2rag().defaultDoubleToBytesMapping(); + case "char": + case "Character": return ros2rag().defaultCharToBytesMapping(); + case "String": return ros2rag().defaultStringToBytesMapping(); + default: return null; + } + } + + // --- isByteArray --- + syn boolean MappingDefinitionType.isByteArray() = false; + eq JavaArrayMappingDefinitionType.isByteArray() = getType().getName().equals("byte"); + + // --- allMappingDefinitions --- + syn java.util.List<MappingDefinition> Ros2Rag.allMappingDefinitions() { + java.util.List<MappingDefinition> result = new java.util.ArrayList<>(); + getMappingDefinitionList().iterator().forEachRemaining(result::add); + result.add(defaultBytesToIntMapping()); + result.add(defaultBytesToShortMapping()); + result.add(defaultBytesToLongMapping()); + result.add(defaultBytesToFloatMapping()); + result.add(defaultBytesToDoubleMapping()); + result.add(defaultBytesToCharMapping()); + result.add(defaultBytesToStringMapping()); + result.add(defaultIntToBytesMapping()); + result.add(defaultShortToBytesMapping()); + result.add(defaultLongToBytesMapping()); + result.add(defaultFloatToBytesMapping()); + result.add(defaultDoubleToBytesMapping()); + result.add(defaultCharToBytesMapping()); + result.add(defaultStringToBytesMapping()); + return result; + } +} diff --git a/src/main/jastadd/parser/Ros2Rag.parser b/src/main/jastadd/parser/Ros2Rag.parser index f2ab264..015b4e6 100644 --- a/src/main/jastadd/parser/Ros2Rag.parser +++ b/src/main/jastadd/parser/Ros2Rag.parser @@ -12,8 +12,6 @@ Ros2Rag ros2rag } :} ; -// read Joint.CurrentPosition using LinkStateToIntPosition ; -// write RobotArm._AppropriateSpeed using CreateSpeedMessage ; UpdateDefinition update_definition = READ ID.type_name DOT ID.token_name SCOL {: @@ -52,7 +50,6 @@ ArrayList string_list | string_list COMMA ID ; -// RobotArm._AppropriateSpeed canDependOn Joint.CurrentPosition as dependency1 ; DependencyDefinition dependency_definition = ID.target_type DOT ID.target_token CAN_DEPEND_ON ID.source_type DOT ID.source_token AS ID.id SCOL {: @@ -64,10 +61,6 @@ DependencyDefinition dependency_definition :} ; -//LinkStateToIntPosition maps protobuf panda.Linkstate.PandaLinkState x to IntPosition y { -// panda.Linkstate.PandaLinkState.Position p = x.getPos(); -// y = IntPosition.of((int) p.getPositionX(), (int) p.getPositionY(), (int) p.getPositionZ()); -//} MappingDefinition mapping_definition = ID.id MAPS mapping_type.from_type ID.from_name TO mapping_type.to_type MAPPING_CONTENT.content {: -- GitLab