You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@plc4x.apache.org by cd...@apache.org on 2020/06/12 14:24:18 UTC

[plc4x] branch feature/c-code-generation-tagged-unions updated: - Greatly refactored the C template helper and moved a lot of functionality into a new BaseFreemarkerLanguageTemplateHelper - Finished support of array fields - Finished supporting static function calls in expressions - Finished supporting enum properties in expressions

This is an automated email from the ASF dual-hosted git repository.

cdutz pushed a commit to branch feature/c-code-generation-tagged-unions
in repository https://gitbox.apache.org/repos/asf/plc4x.git


The following commit(s) were added to refs/heads/feature/c-code-generation-tagged-unions by this push:
     new 8fa97ef  - Greatly refactored the C template helper and moved a lot of functionality into a new BaseFreemarkerLanguageTemplateHelper - Finished support of array fields - Finished supporting static function calls in expressions - Finished supporting enum properties in expressions
8fa97ef is described below

commit 8fa97ef6e2e04c2407f17cdc544b0084d68df8eb
Author: Christofer Dutz <ch...@c-ware.de>
AuthorDate: Fri Jun 12 16:24:10 2020 +0200

    - Greatly refactored the C template helper and moved a lot of functionality into a new BaseFreemarkerLanguageTemplateHelper
    - Finished support of array fields
    - Finished supporting static function calls in expressions
    - Finished supporting enum properties in expressions
---
 build-utils/language-base-freemarker/pom.xml       |   5 +
 .../BaseFreemarkerLanguageTemplateHelper.java      | 525 ++++++++++++++++++++
 .../freemarker/FreemarkerLanguageOutput.java       |   6 +-
 build-utils/language-c/pom.xml                     |   5 -
 .../apache/plc4x/language/c/CLanguageOutput.java   |   4 +-
 .../plc4x/language/c/CLanguageTemplateHelper.java  | 543 +++------------------
 .../main/resources/templates/c/enum-template.ftlh  |  15 +-
 .../resources/templates/c/pojo-template-c.ftlh     | 105 ++--
 .../resources/templates/c/pojo-template-h.ftlh     |  24 +-
 .../plc4x/language/java/JavaLanguageOutput.java    |   4 +-
 .../language/java/JavaLanguageTemplateHelper.java  |   8 +-
 .../definitions/DefaultDataIoTypeDefinition.java   |   2 +
 .../model/definitions/DefaultTypeDefinition.java   |   6 +
 .../modbus/includes/modbus_constants.h             |   1 -
 .../generated-sources/modbus/includes/modbus_pdu.h |  40 +-
 .../modbus_pdu_read_file_record_request_item.h     |   1 -
 .../modbus_pdu_read_file_record_response_item.h    |   1 -
 .../modbus_pdu_write_file_record_request_item.h    |   1 -
 .../modbus_pdu_write_file_record_response_item.h   |   1 -
 .../modbus/includes/modbus_serial_adu.h            |   1 -
 .../modbus/includes/modbus_tcp_adu.h               |   1 -
 .../modbus/src/modbus_constants.c                  |   2 +-
 .../generated-sources/modbus/src/modbus_pdu.c      |   2 +-
 .../src/modbus_pdu_read_file_record_request_item.c |   2 +-
 .../modbus_pdu_read_file_record_response_item.c    |  13 +-
 .../modbus_pdu_write_file_record_request_item.c    |  13 +-
 .../modbus_pdu_write_file_record_response_item.c   |  13 +-
 .../modbus/src/modbus_serial_adu.c                 |   2 +-
 .../generated-sources/modbus/src/modbus_tcp_adu.c  |   2 +-
 .../generated-sources/s7/includes/cotp_packet.h    |   8 +
 .../generated-sources/s7/includes/cotp_parameter.h |   5 +
 .../generated-sources/s7/includes/s7_address.h     |   3 +-
 .../generated-sources/s7/includes/s7_message.h     |   6 +-
 .../generated-sources/s7/includes/s7_parameter.h   |   9 +-
 .../s7/includes/s7_parameter_user_data_item.h      |   1 +
 .../generated-sources/s7/includes/s7_payload.h     |  11 +-
 .../s7/includes/s7_payload_user_data_item.h        |   6 +-
 .../s7/includes/s7_var_payload_data_item.h         |   3 +-
 .../s7/includes/s7_var_payload_status_item.h       |   1 -
 .../s7/includes/s7_var_request_parameter_item.h    |   1 +
 .../s7/includes/szl_data_tree_item.h               |   1 -
 .../plc4c/generated-sources/s7/includes/szl_id.h   |   1 -
 .../generated-sources/s7/includes/tpkt_packet.h    |   1 -
 .../generated-sources/s7/includes/transport_size.h |   2 +-
 .../plc4c/generated-sources/s7/src/cotp_packet.c   |  15 +-
 .../generated-sources/s7/src/cotp_parameter.c      |   2 +-
 .../plc4c/generated-sources/s7/src/s7_address.c    |   2 +-
 .../plc4c/generated-sources/s7/src/s7_message.c    |   2 +-
 .../plc4c/generated-sources/s7/src/s7_parameter.c  |   2 +-
 .../s7/src/s7_parameter_user_data_item.c           |   2 +-
 .../plc4c/generated-sources/s7/src/s7_payload.c    |   2 +-
 .../s7/src/s7_payload_user_data_item.c             |   2 +-
 .../s7/src/s7_var_payload_data_item.c              |  16 +-
 .../s7/src/s7_var_payload_status_item.c            |   2 +-
 .../s7/src/s7_var_request_parameter_item.c         |   2 +-
 .../generated-sources/s7/src/szl_data_tree_item.c  |  14 +-
 sandbox/plc4c/generated-sources/s7/src/szl_id.c    |   2 +-
 .../plc4c/generated-sources/s7/src/tpkt_packet.c   |   2 +-
 .../spi/include/plc4c/spi/evaluation_helper.h      |   6 +
 sandbox/plc4c/spi/src/evaluation_helper.c          |   9 +
 60 files changed, 916 insertions(+), 573 deletions(-)

diff --git a/build-utils/language-base-freemarker/pom.xml b/build-utils/language-base-freemarker/pom.xml
index 0885d35..423f13b 100644
--- a/build-utils/language-base-freemarker/pom.xml
+++ b/build-utils/language-base-freemarker/pom.xml
@@ -51,6 +51,11 @@
       <groupId>org.slf4j</groupId>
       <artifactId>slf4j-api</artifactId>
     </dependency>
+    <dependency>
+      <groupId>net.objecthunter</groupId>
+      <artifactId>exp4j</artifactId>
+      <version>0.4.8</version>
+    </dependency>
   </dependencies>
 
 </project>
\ No newline at end of file
diff --git a/build-utils/language-base-freemarker/src/main/java/org/apache/plc4x/plugins/codegenerator/protocol/freemarker/BaseFreemarkerLanguageTemplateHelper.java b/build-utils/language-base-freemarker/src/main/java/org/apache/plc4x/plugins/codegenerator/protocol/freemarker/BaseFreemarkerLanguageTemplateHelper.java
new file mode 100644
index 0000000..5f31929
--- /dev/null
+++ b/build-utils/language-base-freemarker/src/main/java/org/apache/plc4x/plugins/codegenerator/protocol/freemarker/BaseFreemarkerLanguageTemplateHelper.java
@@ -0,0 +1,525 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+package org.apache.plc4x.plugins.codegenerator.protocol.freemarker;
+
+import net.objecthunter.exp4j.Expression;
+import net.objecthunter.exp4j.ExpressionBuilder;
+import org.apache.plc4x.plugins.codegenerator.types.definitions.*;
+import org.apache.plc4x.plugins.codegenerator.types.fields.*;
+import org.apache.plc4x.plugins.codegenerator.types.references.ComplexTypeReference;
+import org.apache.plc4x.plugins.codegenerator.types.references.SimpleTypeReference;
+import org.apache.plc4x.plugins.codegenerator.types.references.TypeReference;
+import org.apache.plc4x.plugins.codegenerator.types.terms.*;
+
+import java.util.*;
+import java.util.stream.Collectors;
+
+public abstract class BaseFreemarkerLanguageTemplateHelper implements FreemarkerLanguageTemplateHelper {
+
+    private final TypeDefinition thisType;
+    private final String protocolName;
+    private final String flavorName;
+    private final Map<String, TypeDefinition> types;
+
+    // In mspec we are using some virtual virtual fields that are useful for code generation.
+    // As they should be shared over all language template implementations,
+    // these are defined here manually.
+    private static Map<String, SimpleTypeReference> builtInFields;
+    {
+        builtInFields = new HashMap<>();
+        builtInFields.put("curPos", new SimpleTypeReference() {
+            @Override
+            public SimpleBaseType getBaseType() {
+                return SimpleBaseType.UINT;
+            }
+
+            @Override
+            public int getSizeInBits() {
+                return 16;
+            }
+        });
+        builtInFields.put("startPos", new SimpleTypeReference() {
+            @Override
+            public SimpleBaseType getBaseType() {
+                return SimpleBaseType.UINT;
+            }
+
+            @Override
+            public int getSizeInBits() {
+                return 16;
+            }
+        });
+    }
+
+    public BaseFreemarkerLanguageTemplateHelper(TypeDefinition thisType, String protocolName, String flavorName, Map<String, TypeDefinition> types) {
+        this.thisType = thisType;
+        this.protocolName = protocolName;
+        this.flavorName = flavorName;
+        this.types = types;
+    }
+
+    protected TypeDefinition getThisTypeDefinition() {
+        return thisType;
+    }
+
+    protected String getProtocolName() {
+        return protocolName;
+    }
+
+    protected String getFlavorName() {
+        return flavorName;
+    }
+
+    protected Map<String, TypeDefinition> getTypeDefinitions() {
+        return types;
+    }
+
+    protected static Map<String, SimpleTypeReference> getBuiltInFieldTypes() {
+        return builtInFields;
+    }
+
+    /* *********************************************************************************
+     * Methods that are language-dependent.
+     **********************************************************************************/
+
+    public abstract String getLanguageTypeNameForField(Field field);
+
+    public abstract String getLanguageTypeNameForTypeReference(TypeReference typeReference);
+
+    public abstract String getReadBufferReadMethodCall(SimpleTypeReference simpleTypeReference);
+
+    public abstract String getWriteBufferReadMethodCall(SimpleTypeReference simpleTypeReference);
+
+    public abstract String getNullValueForTypeReference(TypeReference typeReference);
+
+    public abstract String getDiscriminatorName(Term discriminatorExpression);
+
+    /* *********************************************************************************
+     * Methods related to type-references.
+     **********************************************************************************/
+
+    /**
+     * @param typeReference type reference
+     * @return true if the given type reference is a simple type reference.
+     */
+    public boolean isSimpleTypeReference(TypeReference typeReference) {
+        return typeReference instanceof SimpleTypeReference;
+    }
+
+    /**
+     * @param typeReference type reference
+     * @return true if the given type reference is a complex type reference.
+     */
+    public boolean isComplexTypeReference(TypeReference typeReference) {
+        return typeReference instanceof ComplexTypeReference;
+    }
+
+    /**
+     * Helper for collecting referenced complex types as these usually ned to be
+     * imported in some way.
+     *
+     * @return Collection of all complex type references used in fields or enum constants.
+     */
+    public Collection<ComplexTypeReference> getComplexTypeReferences() {
+        return getComplexTypeReferences(thisType);
+    }
+
+    /**
+     * Helper for collecting referenced complex types as these usually need to be
+     * imported in some way.
+     *
+     * @param baseType the base type we want to get the type references from
+     * @return collection of complex type references used in the type.
+     */
+    public Collection<ComplexTypeReference> getComplexTypeReferences(TypeDefinition baseType) {
+        Set<ComplexTypeReference> complexTypeReferences = new HashSet<>();
+        // If this is a subtype of a discriminated type, we have to add a reference to the parent type.
+        if (baseType instanceof DiscriminatedComplexTypeDefinition) {
+            DiscriminatedComplexTypeDefinition discriminatedComplexTypeDefinition = (DiscriminatedComplexTypeDefinition) baseType;
+            if(!discriminatedComplexTypeDefinition.isAbstract()) {
+                complexTypeReferences.add((ComplexTypeReference)
+                    discriminatedComplexTypeDefinition.getParentType().getTypeReference());
+            }
+        }
+        // If it's a complex type definition, add all the types referenced by any property fields
+        // (Includes any types referenced by sub-types in case this is a discriminated type parent)
+        if (baseType instanceof ComplexTypeDefinition) {
+            ComplexTypeDefinition complexTypeDefinition = (ComplexTypeDefinition) baseType;
+            for (Field field : complexTypeDefinition.getFields()) {
+                if(field instanceof PropertyField) {
+                    PropertyField propertyField = (PropertyField) field;
+                    if (propertyField.getType() instanceof ComplexTypeReference) {
+                        ComplexTypeReference complexTypeReference = (ComplexTypeReference) propertyField.getType();
+                        complexTypeReferences.add(complexTypeReference);
+                    }
+                } else if(field instanceof SwitchField) {
+                    SwitchField switchField = (SwitchField) field;
+                    for (DiscriminatedComplexTypeDefinition switchCase : switchField.getCases()) {
+                        complexTypeReferences.addAll(getComplexTypeReferences(switchCase));
+                    }
+                }
+            }
+        }
+        // In case this is a enum type, we have to check all the constant types.
+        else if (baseType instanceof EnumTypeDefinition) {
+            for (String constantName : ((EnumTypeDefinition) baseType).getConstantNames()) {
+                final TypeReference constantType = ((EnumTypeDefinition) thisType).getConstantType(constantName);
+                if (constantType instanceof ComplexTypeReference) {
+                    ComplexTypeReference complexTypeReference = (ComplexTypeReference) constantType;
+                    complexTypeReferences.add(complexTypeReference);
+                }
+            }
+        }
+        // If the type has any parser arguments, these have to be checked too.
+        if(baseType.getParserArguments() != null) {
+            for (Argument parserArgument : baseType.getParserArguments()) {
+                if (parserArgument.getType() instanceof ComplexTypeReference) {
+                    ComplexTypeReference complexTypeReference = (ComplexTypeReference) parserArgument.getType();
+                    complexTypeReferences.add(complexTypeReference);
+                }
+            }
+        }
+        return complexTypeReferences;
+    }
+
+    /**
+     * Little helper to return the type of a given property.
+     *
+     * @param baseType base type definition that contains the given property.
+     * @param propertyName name of the property
+     * @return the type reference of the given property
+     */
+    public Optional<TypeReference> getTypeReferenceForProperty(ComplexTypeDefinition baseType, String propertyName) {
+        // If this is a built-in type, use that.
+        if(builtInFields.containsKey(propertyName)) {
+            return Optional.of(builtInFields.get(propertyName));
+        }
+        // Check if the expression root is referencing a field
+        final Optional<PropertyField> propertyFieldOptional = baseType.getFields().stream().filter(
+            field -> field instanceof PropertyField).map(field -> (PropertyField) field).filter(
+            propertyField -> propertyField.getName().equals(propertyName)).findFirst();
+        if(propertyFieldOptional.isPresent()) {
+            final PropertyField propertyField = propertyFieldOptional.get();
+            return Optional.of(propertyField.getType());
+        }
+        // Check if the expression is a ImplicitField
+        final Optional<ImplicitField> implicitFieldOptional = baseType.getFields().stream().filter(
+            field -> field instanceof ImplicitField).map(field -> (ImplicitField) field).filter(
+            implicitField -> implicitField.getName().equals(propertyName)).findFirst();
+        if(implicitFieldOptional.isPresent()) {
+            final ImplicitField implicitField = implicitFieldOptional.get();
+            return Optional.of(implicitField.getType());
+        }
+        // Check if the expression root is referencing an argument
+        if(baseType.getParserArguments() != null) {
+            final Optional<Argument> argumentOptional = Arrays.stream(baseType.getParserArguments()).filter(
+                argument -> argument.getName().equals(propertyName)).findFirst();
+            if (argumentOptional.isPresent()) {
+                final Argument argument = argumentOptional.get();
+                return Optional.of(argument.getType());
+            }
+        }
+        // Check if the expression is a DiscriminatorField
+        // This is a more theoretical case where the expression is referencing a discriminator value of the current type
+        final Optional<DiscriminatorField> discriminatorFieldOptional = baseType.getFields().stream().filter(
+            field -> field instanceof DiscriminatorField).map(field -> (DiscriminatorField) field).filter(
+            discriminatorField -> discriminatorField.getName().equals(propertyName)).findFirst();
+        if(discriminatorFieldOptional.isPresent()) {
+            final DiscriminatorField discriminatorField = discriminatorFieldOptional.get();
+            return Optional.of(discriminatorField.getType());
+        }
+        return Optional.empty();
+    }
+
+    /**
+     * Enums are always based on a main type. This helper accesses this information in a safe manner.
+     *
+     * @param typeReference type reference
+     * @return simple type reference for the enum type referenced by the given type reference
+     */
+    public SimpleTypeReference getEnumBaseTypeReference(TypeReference typeReference) {
+        if (!(typeReference instanceof ComplexTypeReference)) {
+            throw new RuntimeException("type reference for enum types must be of type complex type");
+        }
+        ComplexTypeReference complexTypeReference = (ComplexTypeReference) typeReference;
+        final TypeDefinition typeDefinition = types.get(complexTypeReference.getName());
+        if(typeDefinition == null) {
+            throw new RuntimeException("Couldn't find given enum type definition with name " + complexTypeReference.getName());
+        }
+        if(!(typeDefinition instanceof EnumTypeDefinition)) {
+            throw new RuntimeException("Referenced tpye with name " + complexTypeReference.getName() + " is not an enum type");
+        }
+        EnumTypeDefinition enumTypeDefinition = (EnumTypeDefinition) typeDefinition;
+        // Enum types always have simple type references.
+        return (SimpleTypeReference) enumTypeDefinition.getType();
+    }
+
+    /* *********************************************************************************
+     * Methods related to fields.
+     **********************************************************************************/
+
+    public boolean isSwitchField(Field field) {
+        return field instanceof SwitchField;
+    }
+
+    public boolean isEnumField(Field field) {
+        return field instanceof EnumField;
+    }
+
+    public boolean isCountArrayField(Field field) {
+        if(field instanceof ArrayField) {
+            ArrayField arrayField = (ArrayField) field;
+            return arrayField.getLoopType() == ArrayField.LoopType.COUNT;
+        }
+        return false;
+    }
+
+    public boolean isLengthArrayField(Field field) {
+        if(field instanceof ArrayField) {
+            ArrayField arrayField = (ArrayField) field;
+            return arrayField.getLoopType() == ArrayField.LoopType.LENGTH;
+        }
+        return false;
+    }
+
+    public boolean isTerminatedArrayField(Field field) {
+        if(field instanceof ArrayField) {
+            ArrayField arrayField = (ArrayField) field;
+            return arrayField.getLoopType() == ArrayField.LoopType.TERMINATED;
+        }
+        return false;
+    }
+
+    /**
+     * @return switch field of the current base type.
+     */
+    protected SwitchField getSwitchField() {
+        return getSwitchField(thisType);
+    }
+
+    /**
+     * @return switch field of the provided base type.
+     */
+    protected SwitchField getSwitchField(TypeDefinition typeDefinition) {
+        if (typeDefinition instanceof ComplexTypeDefinition) {
+            ComplexTypeDefinition complexTypeDefinition = (ComplexTypeDefinition) typeDefinition;
+            // Sebastian would be proud of me ;-)
+            return (SwitchField) complexTypeDefinition.getFields().stream().filter(
+                field -> field instanceof SwitchField).findFirst().orElse(null);
+        }
+        return null;
+    }
+
+    public Collection<Field> getPropertyAndSwitchFields() {
+        return getPropertyAndSwitchFields(thisType);
+    }
+
+    public Collection<Field> getPropertyAndSwitchFields(TypeDefinition typeDefinition) {
+        if(thisType instanceof ComplexTypeDefinition) {
+            return ((ComplexTypeDefinition) thisType).getFields().stream().filter(
+                field -> (field instanceof PropertyField) || (field instanceof SwitchField)).collect(Collectors.toList());
+        }
+        return Collections.emptyList();
+    }
+
+    /* *********************************************************************************
+     * Methods related to type-definitions.
+     **********************************************************************************/
+
+    public boolean isDiscriminatedParentTypeDefinition(TypeDefinition typeDefinition) {
+        return (typeDefinition instanceof ComplexTypeDefinition) && ((ComplexTypeDefinition) typeDefinition).isAbstract();
+    }
+
+    public boolean isDiscriminatedChildTypeDefinition(TypeDefinition typeDefinition) {
+        return (typeDefinition instanceof DiscriminatedComplexTypeDefinition) && !((ComplexTypeDefinition) typeDefinition).isAbstract();
+    }
+
+    public TypeDefinition getTypeDefinitionForTypeReference(TypeReference typeReference) {
+        if(!(typeReference instanceof ComplexTypeReference)) {
+            throw new RuntimeException("Type reference must be a complex type reference");
+        }
+        return getTypeDefinitions().get(((ComplexTypeReference) typeReference).getName());
+    }
+
+    /**
+     * @return list of sub-types for the current base type or an empty collection, if there are none
+     */
+    public List<DiscriminatedComplexTypeDefinition> getSubTypeDefinitions() {
+        return getSubTypeDefinitions(thisType);
+    }
+
+    /**
+     * @return list of sub-types for a given type definition or an empty collection, if there are none
+     */
+    public List<DiscriminatedComplexTypeDefinition> getSubTypeDefinitions(TypeDefinition type) {
+        SwitchField switchField = getSwitchField(type);
+        if (switchField != null) {
+            return switchField.getCases();
+        }
+        return Collections.emptyList();
+    }
+
+    /* *********************************************************************************
+     * Methods related to terms and expressions.
+     **********************************************************************************/
+
+    /**
+     * Check if the expression doesn't reference any variables.
+     * If this is the case, the expression can be evaluated at code-generation time.
+     *
+     * @param term term
+     * @return true if it doesn't reference any variable literals.
+     */
+    protected boolean isFixedValueExpression(Term term) {
+        if (term instanceof VariableLiteral) {
+            return false;
+        }
+        if (term instanceof UnaryTerm) {
+            UnaryTerm unaryTerm = (UnaryTerm) term;
+            return isFixedValueExpression(unaryTerm.getA());
+        }
+        if (term instanceof BinaryTerm) {
+            BinaryTerm binaryTerm = (BinaryTerm) term;
+            return isFixedValueExpression(binaryTerm.getA()) && isFixedValueExpression(binaryTerm.getB());
+        }
+        if (term instanceof TernaryTerm) {
+            TernaryTerm ternaryTerm = (TernaryTerm) term;
+            return isFixedValueExpression(ternaryTerm.getA()) && isFixedValueExpression(ternaryTerm.getB()) &&
+                isFixedValueExpression(ternaryTerm.getC());
+        }
+        return true;
+    }
+
+    protected int evaluateFixedValueExpression(Term term) {
+        final Expression expression = new ExpressionBuilder(toString(term)).build();
+        return (int) expression.evaluate();
+    }
+
+    protected String toString(Term term) {
+        if (term instanceof NullLiteral) {
+            return "null";
+        }
+        if (term instanceof BooleanLiteral) {
+            return Boolean.toString(((BooleanLiteral) term).getValue());
+        }
+        if (term instanceof NumericLiteral) {
+            return ((NumericLiteral) term).getNumber().toString();
+        }
+        if (term instanceof StringLiteral) {
+            return "\"" + ((StringLiteral) term).getValue() + "\"";
+        }
+        if (term instanceof UnaryTerm) {
+            return ((UnaryTerm) term).getOperation() + toString(((UnaryTerm) term).getA());
+        }
+        if (term instanceof BinaryTerm) {
+            return toString(((BinaryTerm) term).getA()) + ((BinaryTerm) term).getOperation() + toString(((BinaryTerm) term).getB());
+        }
+        if (term instanceof TernaryTerm) {
+            return "(" + toString(((TernaryTerm) term).getA()) + ") ? (" + toString(((TernaryTerm) term).getB()) +
+                ") : (" + toString(((TernaryTerm) term).getC()) + ")";
+        }
+        return "";
+    }
+
+    /* *********************************************************************************
+     * Methods related to discriminators.
+     **********************************************************************************/
+
+    private Optional<TypeReference> getDiscriminatorType(ComplexTypeDefinition parentType, Term disciminatorExpression) {
+        if (!(disciminatorExpression instanceof VariableLiteral)) {
+            throw new RuntimeException("Currently no arithmetic expressions are supported as discriminator expressions.");
+        }
+        VariableLiteral variableLiteral = (VariableLiteral) disciminatorExpression;
+        Optional<TypeReference> type = getTypeReferenceForProperty(parentType, variableLiteral.getName());
+        // If we found something but there's a "rest" left, we got to use the type we
+        // found in this level, get that type's definition and continue from there.
+        if (type.isPresent() && (variableLiteral.getChild() != null)) {
+            TypeReference typeReference = type.get();
+            if (typeReference instanceof ComplexTypeReference) {
+                ComplexTypeReference complexTypeReference = (ComplexTypeReference) typeReference;
+                final TypeDefinition typeDefinition = this.types.get(complexTypeReference.getName());
+                if (typeDefinition instanceof ComplexTypeDefinition) {
+                    return getDiscriminatorType((ComplexTypeDefinition) typeDefinition, variableLiteral.getChild());
+                }
+            }
+        }
+        return type;
+    }
+
+    public Map<String, TypeReference> getDiscriminatorTypes() {
+        // Get the parent type (Which contains the typeSwitch field)
+        ComplexTypeDefinition parentType;
+        if (thisType instanceof DiscriminatedComplexTypeDefinition) {
+            parentType = (ComplexTypeDefinition) thisType.getParentType();
+        } else {
+            parentType = (ComplexTypeDefinition) thisType;
+        }
+        // Get the typeSwitch field from that.
+        final SwitchField switchField = getSwitchField(parentType);
+        if (switchField != null) {
+            Map<String, TypeReference> discriminatorTypes = new TreeMap<>();
+            for (Term discriminatorExpression : switchField.getDiscriminatorExpressions()) {
+                // Get some symbolic name we can use.
+                String discriminatorName = getDiscriminatorName(discriminatorExpression);
+                Optional<TypeReference> discriminatorType = getDiscriminatorType(parentType, discriminatorExpression);
+                discriminatorTypes.put(discriminatorName, discriminatorType.orElse(null));
+            }
+            return discriminatorTypes;
+        }
+        return Collections.emptyMap();
+    }
+
+    public Map<String, Map<String, String>> getDiscriminatorValues() {
+        // Get the parent type (Which contains the typeSwitch field)
+        ComplexTypeDefinition parentType;
+        if (thisType instanceof DiscriminatedComplexTypeDefinition) {
+            parentType = (ComplexTypeDefinition) thisType.getParentType();
+        } else {
+            parentType = (ComplexTypeDefinition) thisType;
+        }
+        // Get the typeSwitch field from that.
+        final SwitchField switchField = getSwitchField(parentType);
+        if (switchField != null) {
+            // Get the symbolic names of all discriminators
+            String[] discriminatorNames = new String[switchField.getDiscriminatorExpressions().length];
+            for (int i = 0; i < switchField.getDiscriminatorExpressions().length; i++) {
+                discriminatorNames[i] = getDiscriminatorName(switchField.getDiscriminatorExpressions()[i]);
+            }
+            // Build a map containing the named discriminator values for every case of the typeSwitch.
+            Map<String, Map<String, String>> discriminatorTypes = new TreeMap<>();
+            for (DiscriminatedComplexTypeDefinition switchCase : switchField.getCases()) {
+                discriminatorTypes.put(switchCase.getName(), new TreeMap<>());
+                for (int i = 0; i < switchField.getDiscriminatorExpressions().length; i++) {
+                    String discriminatorValue;
+                    if (i < switchCase.getDiscriminatorValues().length) {
+                        discriminatorValue = switchCase.getDiscriminatorValues()[i];
+                    } else {
+                        discriminatorValue = null;
+                    }
+                    discriminatorTypes.get(switchCase.getName()).put(discriminatorNames[i], discriminatorValue);
+                }
+            }
+            return discriminatorTypes;
+        }
+        return Collections.emptyMap();
+    }
+
+
+
+}
diff --git a/build-utils/language-base-freemarker/src/main/java/org/apache/plc4x/plugins/codegenerator/protocol/freemarker/FreemarkerLanguageOutput.java b/build-utils/language-base-freemarker/src/main/java/org/apache/plc4x/plugins/codegenerator/protocol/freemarker/FreemarkerLanguageOutput.java
index 50ea54a..7685187 100644
--- a/build-utils/language-base-freemarker/src/main/java/org/apache/plc4x/plugins/codegenerator/protocol/freemarker/FreemarkerLanguageOutput.java
+++ b/build-utils/language-base-freemarker/src/main/java/org/apache/plc4x/plugins/codegenerator/protocol/freemarker/FreemarkerLanguageOutput.java
@@ -64,7 +64,7 @@ public abstract class FreemarkerLanguageOutput implements LanguageOutput {
                 typeContext.put("languageName", languageName);
                 typeContext.put("protocolName", protocolName);
                 typeContext.put("outputFlavor", outputFlavor);
-                typeContext.put("helper", getHelper(types));
+                typeContext.put("helper", getHelper(null, protocolName, outputFlavor, types));
 
                 for(Template template : specTemplates) {
                     try {
@@ -85,7 +85,7 @@ public abstract class FreemarkerLanguageOutput implements LanguageOutput {
                 typeContext.put("outputFlavor", outputFlavor);
                 typeContext.put("typeName", typeEntry.getKey());
                 typeContext.put("type", typeEntry.getValue());
-                typeContext.put("helper", getHelper(types));
+                typeContext.put("helper", getHelper(typeEntry.getValue(), protocolName, outputFlavor, types));
 
                 // Depending on the type, get the corresponding list of templates.
                 List<Template> templateList;
@@ -175,6 +175,6 @@ public abstract class FreemarkerLanguageOutput implements LanguageOutput {
 
     protected abstract List<Template> getDataIoTemplates(Configuration freemarkerConfiguration) throws IOException;
 
-    protected abstract FreemarkerLanguageTemplateHelper getHelper(Map<String, TypeDefinition> types);
+    protected abstract FreemarkerLanguageTemplateHelper getHelper(TypeDefinition thisType, String protocolName, String flavorName, Map<String, TypeDefinition> types);
 
 }
diff --git a/build-utils/language-c/pom.xml b/build-utils/language-c/pom.xml
index f557c02..1ba5709 100644
--- a/build-utils/language-c/pom.xml
+++ b/build-utils/language-c/pom.xml
@@ -53,11 +53,6 @@
       <groupId>org.apache.commons</groupId>
       <artifactId>commons-text</artifactId>
     </dependency>
-    <dependency>
-      <groupId>net.objecthunter</groupId>
-      <artifactId>exp4j</artifactId>
-      <version>0.4.8</version>
-    </dependency>
   </dependencies>
 
 </project>
\ No newline at end of file
diff --git a/build-utils/language-c/src/main/java/org/apache/plc4x/language/c/CLanguageOutput.java b/build-utils/language-c/src/main/java/org/apache/plc4x/language/c/CLanguageOutput.java
index 8b2d292..2846731 100644
--- a/build-utils/language-c/src/main/java/org/apache/plc4x/language/c/CLanguageOutput.java
+++ b/build-utils/language-c/src/main/java/org/apache/plc4x/language/c/CLanguageOutput.java
@@ -66,8 +66,8 @@ public class CLanguageOutput extends FreemarkerLanguageOutput {
     }
 
     @Override
-    protected FreemarkerLanguageTemplateHelper getHelper(Map<String, TypeDefinition> types) {
-        return new CLanguageTemplateHelper(types);
+    protected FreemarkerLanguageTemplateHelper getHelper(TypeDefinition thisType, String protocolName, String flavorName, Map<String, TypeDefinition> types) {
+        return new CLanguageTemplateHelper(thisType, protocolName, flavorName, types);
     }
 
 }
diff --git a/build-utils/language-c/src/main/java/org/apache/plc4x/language/c/CLanguageTemplateHelper.java b/build-utils/language-c/src/main/java/org/apache/plc4x/language/c/CLanguageTemplateHelper.java
index 30173fc..76642a7 100644
--- a/build-utils/language-c/src/main/java/org/apache/plc4x/language/c/CLanguageTemplateHelper.java
+++ b/build-utils/language-c/src/main/java/org/apache/plc4x/language/c/CLanguageTemplateHelper.java
@@ -18,11 +18,9 @@ under the License.
 */
 package org.apache.plc4x.language.c;
 
-import net.objecthunter.exp4j.Expression;
-import net.objecthunter.exp4j.ExpressionBuilder;
 import org.apache.commons.lang3.math.NumberUtils;
 import org.apache.commons.text.WordUtils;
-import org.apache.plc4x.plugins.codegenerator.protocol.freemarker.FreemarkerLanguageTemplateHelper;
+import org.apache.plc4x.plugins.codegenerator.protocol.freemarker.BaseFreemarkerLanguageTemplateHelper;
 import org.apache.plc4x.plugins.codegenerator.types.definitions.*;
 import org.apache.plc4x.plugins.codegenerator.types.enums.EnumValue;
 import org.apache.plc4x.plugins.codegenerator.types.fields.*;
@@ -31,152 +29,19 @@ import org.apache.plc4x.plugins.codegenerator.types.terms.*;
 
 import java.util.*;
 import java.util.function.Function;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-import java.util.stream.Collectors;
 
-public class CLanguageTemplateHelper implements FreemarkerLanguageTemplateHelper {
+public class CLanguageTemplateHelper extends BaseFreemarkerLanguageTemplateHelper {
 
-    private final Map<String, TypeDefinition> types;
-    private TypeDefinition thisType;
-    private String protocolName;
-    private String flavorName;
-
-    private static Map<String, SimpleTypeReference> builtInFields;
-    {
-        builtInFields = new HashMap<>();
-        builtInFields.put("curPos", new SimpleTypeReference() {
-            @Override
-            public SimpleBaseType getBaseType() {
-                return SimpleBaseType.UINT;
-            }
-
-            @Override
-            public int getSizeInBits() {
-                return 16;
-            }
-        });
-        builtInFields.put("startPos", new SimpleTypeReference() {
-            @Override
-            public SimpleBaseType getBaseType() {
-                return SimpleBaseType.UINT;
-            }
-
-            @Override
-            public int getSizeInBits() {
-                return 16;
-            }
-        });
-    }
-
-    public CLanguageTemplateHelper(Map<String, TypeDefinition> types) {
-        this.types = types;
-    }
-
-    public void setConstants(TypeDefinition thisType, String protocolName, String flavorName) {
-        this.thisType = thisType;
-        this.protocolName = protocolName;
-        this.flavorName = flavorName;
+    public CLanguageTemplateHelper(TypeDefinition thisType, String protocolName, String flavorName, Map<String, TypeDefinition> types) {
+        super(thisType, protocolName, flavorName, types);
     }
 
     public String getSourceDirectory() {
-        return String.join("", protocolName.split("-")) + ".src";
+        return String.join("", getProtocolName().split("-")) + ".src";
     }
 
     public String getIncludesDirectory() {
-        return String.join("", protocolName.split("-")) + ".includes";
-    }
-
-    /**
-     * Check if this is an abstract type ...
-     *
-     * @param typeDefinition the type definition
-     * @return true if this is an abstract type
-     */
-    public boolean isAbstractType(ComplexTypeDefinition typeDefinition) {
-        return typeDefinition.isAbstract();
-    }
-
-    public boolean isSimpleType(TypeReference typeReference) {
-        return typeReference instanceof SimpleTypeReference;
-    }
-
-    public boolean isDiscriminatedType(ComplexTypeDefinition typeDefinition) {
-        return typeDefinition instanceof DiscriminatedComplexTypeDefinition;
-    }
-
-    public boolean isSwitchField(Field field) {
-        return field instanceof SwitchField;
-    }
-
-    public boolean isEnumField(Field field) {
-        return field instanceof EnumField;
-    }
-
-    /**
-     * Modified version returning all the normal property fields, but also the typeSwitch fields
-     * As we need to generate the union structs for these.
-     *
-     * @return list of property fields as well as typeSwitch fields.
-     */
-    public Collection<Field> getFields() {
-        return ((ComplexTypeDefinition) thisType).getFields().stream().filter(
-            field -> (field instanceof PropertyField) || (field instanceof SwitchField)).collect(Collectors.toList());
-    }
-
-    private SwitchField getSwitchField() {
-        return getSwitchField(thisType);
-    }
-
-    private SwitchField getSwitchField(TypeDefinition type) {
-        if (type instanceof ComplexTypeDefinition) {
-            ComplexTypeDefinition complexTypeDefinition = (ComplexTypeDefinition) type;
-            // Sebastian would be proud of me ;-)
-            return (SwitchField) complexTypeDefinition.getFields().stream().filter(
-                field -> field instanceof SwitchField).findFirst().orElse(null);
-        }
-        return null;
-    }
-
-    public List<DiscriminatedComplexTypeDefinition> getDiscriminatedSubTypes() {
-        SwitchField switchField = getSwitchField();
-        if (switchField != null) {
-            return switchField.getCases();
-        }
-        return Collections.emptyList();
-    }
-
-    public Collection<ComplexTypeReference> getComplexTypeReferencesInFields() {
-        return getComplexTypeReferencesInFields(thisType);
-    }
-
-    public Collection<ComplexTypeReference> getComplexTypeReferencesInFields(TypeDefinition baseType) {
-        Set<ComplexTypeReference> complexTypeReferences = new HashSet<>();
-        if (baseType instanceof ComplexTypeDefinition) {
-            for (Field field : ((ComplexTypeDefinition) baseType).getFields()) {
-                if(field instanceof PropertyField) {
-                    PropertyField propertyField = (PropertyField) field;
-                    if (propertyField.getType() instanceof ComplexTypeReference) {
-                        ComplexTypeReference complexTypeReference = (ComplexTypeReference) propertyField.getType();
-                        complexTypeReferences.add(complexTypeReference);
-                    }
-                } else if(field instanceof SwitchField) {
-                    SwitchField switchField = (SwitchField) field;
-                    for (DiscriminatedComplexTypeDefinition switchCase : switchField.getCases()) {
-                        complexTypeReferences.addAll(getComplexTypeReferencesInFields(switchCase));
-                    }
-                }
-            }
-        } else if (baseType instanceof EnumTypeDefinition) {
-            for (String constantName : ((EnumTypeDefinition) baseType).getConstantNames()) {
-                final TypeReference constantType = ((EnumTypeDefinition) thisType).getConstantType(constantName);
-                if (constantType instanceof ComplexTypeReference) {
-                    ComplexTypeReference complexTypeReference = (ComplexTypeReference) constantType;
-                    complexTypeReferences.add(complexTypeReference);
-                }
-            }
-        }
-        return complexTypeReferences;
+        return String.join("", getProtocolName().split("-")) + ".includes";
     }
 
     /**
@@ -187,8 +52,9 @@ public class CLanguageTemplateHelper implements FreemarkerLanguageTemplateHelper
      * @return c-style type name
      */
     public String getCTypeName(String typeName) {
-        return camelCaseToSnakeCase(protocolName).toLowerCase() + "_" + camelCaseToSnakeCase(flavorName).toLowerCase() + "_" +
-            camelCaseToSnakeCase(typeName).toLowerCase();
+        return camelCaseToSnakeCase(getProtocolName()).toLowerCase() +
+            "_" + camelCaseToSnakeCase(getFlavorName()).toLowerCase() +
+            "_" + camelCaseToSnakeCase(typeName).toLowerCase();
     }
 
     /**
@@ -232,24 +98,24 @@ public class CLanguageTemplateHelper implements FreemarkerLanguageTemplateHelper
      * @param field field we want to get the type name for
      * @return type name we should use in C
      */
-    public String getLanguageTypeNameForField(TypedField field) {
-        // If the referenced type is a DataIo type, the value is of type plc4c_data.
-        if (field instanceof PropertyField) {
-            PropertyField propertyField = (PropertyField) field;
-            if (propertyField.getType() instanceof ComplexTypeReference) {
-                ComplexTypeReference complexTypeReference = (ComplexTypeReference) propertyField.getType();
-                final TypeDefinition typeDefinition = types.get(complexTypeReference.getName());
-                if (typeDefinition instanceof DataIoTypeDefinition) {
-                    return "plc4c_data*";
-                }
-            }
+    @Override
+    public String getLanguageTypeNameForField(Field field) {
+        if(!(field instanceof TypedField)) {
+            throw new RuntimeException("Field " + field + " is not a TypedField");
         }
         // If this is an array with variable length, then we have to use our "plc4c_list" to store the data.
         if ((field instanceof ArrayField) && (!isFixedValueExpression(((ArrayField) field).getLoopExpression()))) {
             return "plc4c_list";
         }
-        TypeReference typeReference = field.getType();
-        return getLanguageTypeName(typeReference);
+        TypedField typedField = (TypedField) field;
+        TypeReference typeReference = typedField.getType();
+        if (typeReference instanceof ComplexTypeReference) {
+            final TypeDefinition typeDefinition = getTypeDefinitionForTypeReference(typeReference);
+            if (typeDefinition instanceof DataIoTypeDefinition) {
+                return "plc4c_data*";
+            }
+        }
+        return getLanguageTypeNameForTypeReference(typeReference);
     }
 
     /**
@@ -260,7 +126,8 @@ public class CLanguageTemplateHelper implements FreemarkerLanguageTemplateHelper
      * @param typeReference type reference
      * @return c type
      */
-    public String getLanguageTypeName(TypeReference typeReference) {
+    @Override
+    public String getLanguageTypeNameForTypeReference(TypeReference typeReference) {
         if (typeReference instanceof SimpleTypeReference) {
             SimpleTypeReference simpleTypeReference = (SimpleTypeReference) typeReference;
             switch (simpleTypeReference.getBaseType()) {
@@ -376,7 +243,7 @@ public class CLanguageTemplateHelper implements FreemarkerLanguageTemplateHelper
         if ("null".equals(valueString)) {
             // C doesn't like NULL values for enums, so we have to return something else (we'll treat -1 as NULL)
             if (typeReference instanceof ComplexTypeReference) {
-                if (types.get(((ComplexTypeReference) typeReference).getName()) instanceof EnumTypeDefinition) {
+                if (getTypeDefinitionForTypeReference(typeReference) instanceof EnumTypeDefinition) {
                     return "-1";
                 }
             }
@@ -410,7 +277,6 @@ public class CLanguageTemplateHelper implements FreemarkerLanguageTemplateHelper
             if ("null".equals(valueString)) {
                 return "-1";
             }
-            ComplexTypeReference complexTypeReference = (ComplexTypeReference) typeReference;
             String typeName = valueString.substring(0, valueString.indexOf('.'));
             String constantName = valueString.substring(valueString.indexOf('.') + 1);
             return "plc4c_" + getCTypeName(typeName) + "_" + constantName;
@@ -429,64 +295,7 @@ public class CLanguageTemplateHelper implements FreemarkerLanguageTemplateHelper
         return filteredEnumValues.values();
     }
 
-    /**
-     * Check if the expression doesn't reference any variables.
-     * If this is the case, the expression can be evaluated at code-generation time.
-     *
-     * @param term term
-     * @return true if it doesn't reference any variable literals.
-     */
-    private boolean isFixedValueExpression(Term term) {
-        if (term instanceof VariableLiteral) {
-            return false;
-        }
-        if (term instanceof UnaryTerm) {
-            UnaryTerm unaryTerm = (UnaryTerm) term;
-            return isFixedValueExpression(unaryTerm.getA());
-        }
-        if (term instanceof BinaryTerm) {
-            BinaryTerm binaryTerm = (BinaryTerm) term;
-            return isFixedValueExpression(binaryTerm.getA()) && isFixedValueExpression(binaryTerm.getB());
-        }
-        if (term instanceof TernaryTerm) {
-            TernaryTerm ternaryTerm = (TernaryTerm) term;
-            return isFixedValueExpression(ternaryTerm.getA()) && isFixedValueExpression(ternaryTerm.getB()) &&
-                isFixedValueExpression(ternaryTerm.getC());
-        }
-        return true;
-    }
-
-    private int evaluateFixedValueExpression(Term term) {
-        final Expression expression = new ExpressionBuilder(toString(term)).build();
-        return (int) expression.evaluate();
-    }
-
-    private String toString(Term term) {
-        if (term instanceof NullLiteral) {
-            return "null";
-        }
-        if (term instanceof BooleanLiteral) {
-            return Boolean.toString(((BooleanLiteral) term).getValue());
-        }
-        if (term instanceof NumericLiteral) {
-            return ((NumericLiteral) term).getNumber().toString();
-        }
-        if (term instanceof StringLiteral) {
-            return "\"" + ((StringLiteral) term).getValue() + "\"";
-        }
-        if (term instanceof UnaryTerm) {
-            return ((UnaryTerm) term).getOperation() + toString(((UnaryTerm) term).getA());
-        }
-        if (term instanceof BinaryTerm) {
-            return toString(((BinaryTerm) term).getA()) + ((BinaryTerm) term).getOperation() + toString(((BinaryTerm) term).getB());
-        }
-        if (term instanceof TernaryTerm) {
-            return "(" + toString(((TernaryTerm) term).getA()) + ") ? (" + toString(((TernaryTerm) term).getB()) +
-                ") : (" + toString(((TernaryTerm) term).getC()) + ")";
-        }
-        return "";
-    }
-
+    @Override
     public String getReadBufferReadMethodCall(SimpleTypeReference simpleTypeReference) {
         switch (simpleTypeReference.getBaseType()) {
             case BIT: {
@@ -541,6 +350,21 @@ public class CLanguageTemplateHelper implements FreemarkerLanguageTemplateHelper
         return "Hurz";
     }
 
+    @Override
+    public String getWriteBufferReadMethodCall(SimpleTypeReference simpleTypeReference) {
+        return null;
+    }
+
+    @Override
+    public String getNullValueForTypeReference(TypeReference typeReference) {
+        return null;
+    }
+
+
+
+
+
+
     public String toParseExpression(Term term, Argument[] parserArguments) {
         return toExpression(term, term1 -> toVariableParseExpression(term1, parserArguments));
     }
@@ -565,7 +389,7 @@ public class CLanguageTemplateHelper implements FreemarkerLanguageTemplateHelper
             } else if (term instanceof VariableLiteral) {
                 VariableLiteral variableLiteral = (VariableLiteral) term;
                 // If this literal references an Enum type, then we have to output it differently.
-                if (types.get(variableLiteral.getName()) instanceof EnumTypeDefinition) {
+                if (getTypeDefinitions().get(variableLiteral.getName()) instanceof EnumTypeDefinition) {
                     return variableLiteral.getName() + "." + variableLiteral.getChild().getName();
                 } else {
                     return variableExpressionGenerator.apply(term);
@@ -614,83 +438,11 @@ public class CLanguageTemplateHelper implements FreemarkerLanguageTemplateHelper
 
     public String toVariableParseExpression(Term term, Argument[] parserArguments) {
         VariableLiteral vl = (VariableLiteral) term;
-        // CAST expressions are special as we need to add a ".class" to the second parameter in Java.
-        if ("CAST".equals(vl.getName())) {
-            StringBuilder sb = new StringBuilder(vl.getName());
-            if ((vl.getArgs() == null) || (vl.getArgs().size() != 2)) {
-                throw new RuntimeException("A CAST expression expects exactly two arguments.");
-            }
-            sb.append("(").append(toVariableParseExpression(vl.getArgs().get(0), parserArguments))
-                .append(", ").append(((VariableLiteral) vl.getArgs().get(1)).getName()).append(".class)");
-            return sb.toString() + ((vl.getChild() != null) ? "." + toVariableExpressionRest(vl.getChild()) : "");
-        } else if ("COUNT".equals(vl.getName())) {
-            StringBuilder sb = new StringBuilder();
-            if ((vl.getArgs() == null) || (vl.getArgs().size() != 1)) {
-                throw new RuntimeException("A COUNT expression expects exactly one argument.");
-            }
-            sb.append("plc4c_utils_list_size(&").append(((VariableLiteral) vl.getArgs().get(0)).getName()).append(")");
-            return sb.toString();
-        } else if ("STATIC_CALL".equals(vl.getName())) {
-            StringBuilder sb = new StringBuilder();
-            if (!(vl.getArgs().get(0) instanceof StringLiteral)) {
-                throw new RuntimeException("Expecting the first argument of a 'STATIC_CALL' to be a StringLiteral");
-            }
-            // Get the class and method name
-            String methodName = ((StringLiteral) vl.getArgs().get(0)).getValue();
-            // Cut off the double-quptes
-            methodName = methodName.substring(1, methodName.length() - 1);
-            sb.append(methodName).append("(");
-            for (int i = 1; i < vl.getArgs().size(); i++) {
-                Term arg = vl.getArgs().get(i);
-                if (i > 1) {
-                    sb.append(", ");
-                }
-                if (arg instanceof VariableLiteral) {
-                    VariableLiteral va = (VariableLiteral) arg;
-                    // "io" is the default name of the reader argument which is always available.
-                    boolean isParserArg = "io".equals(va.getName());
-                    boolean isTypeArg = "_type".equals(va.getName());
-                    if (!isParserArg && !isTypeArg && parserArguments != null) {
-                        for (Argument parserArgument : parserArguments) {
-                            if (parserArgument.getName().equals(va.getName())) {
-                                isParserArg = true;
-                                break;
-                            }
-                        }
-                    }
-                    if (isParserArg) {
-                        sb.append(va.getName() + ((va.getChild() != null) ? "." + toVariableExpressionRest(va.getChild()) : ""));
-                    }
-                    // We have to manually evaluate the type information at code-generation time.
-                    /*else if (isTypeArg) {
-                        String part = va.getChild().getName();
-                        switch (part) {
-                            case "name":
-                                sb.append("\"").append(field.getTypeName()).append("\"");
-                                break;
-                            case "length":
-                                sb.append("\"").append(((SimpleTypeReference) field).getSizeInBits()).append("\"");
-                                break;
-                            case "encoding":
-                                String encoding = ((StringTypeReference) field.getType()).getEncoding();
-                                // Cut off the single quotes.
-                                encoding = encoding.substring(1, encoding.length() - 1);
-                                sb.append("\"").append(encoding).append("\"");
-                                break;
-                        }
-                    }*/ else {
-                        sb.append(toVariableParseExpression(va, null));
-                    }
-                } else if (arg instanceof StringLiteral) {
-                    sb.append(((StringLiteral) arg).getValue());
-                }
-            }
-            sb.append(")");
-            return sb.toString();
-        }
-        // All uppercase names are not fields, but utility methods.
-        else if (vl.getName().equals(vl.getName().toUpperCase())) {
-            StringBuilder sb = new StringBuilder(vl.getName());
+        // Any name that is full upper-case is considered a function call.
+        // These are generally defined in the spi file evaluation_helper.c.
+        // All should have a name prefix "plc4c_spi_evaluation_helper_".
+        if (vl.getName().equals(vl.getName().toUpperCase())) {
+            StringBuilder sb = new StringBuilder("plc4c_spi_evaluation_helper_" + vl.getName().toLowerCase());
             if (vl.getArgs() != null) {
                 sb.append("(");
                 boolean firstArg = true;
@@ -712,11 +464,12 @@ public class CLanguageTemplateHelper implements FreemarkerLanguageTemplateHelper
         final String name = vl.getName();
 
         // Try to find the type of the addressed property.
-        final Optional<TypeReference> propertyTypeOptional = getTypeReference((ComplexTypeDefinition) thisType, name);
+        final Optional<TypeReference> propertyTypeOptional =
+            getTypeReferenceForProperty((ComplexTypeDefinition) getThisTypeDefinition(), name);
 
         // If we couldn't find the type, we didn't find the property.
         if(!propertyTypeOptional.isPresent()) {
-            throw new RuntimeException("Could not find property with name '" + name + "' in type " + thisType.getName());
+            throw new RuntimeException("Could not find property with name '" + name + "' in type " + getThisTypeDefinition().getName());
         }
 
         final TypeReference propertyType = propertyTypeOptional.get();
@@ -730,7 +483,7 @@ public class CLanguageTemplateHelper implements FreemarkerLanguageTemplateHelper
         }
 
         // If it references a complex, type we need to get that type's definition first.
-        final TypeDefinition propertyTypeDefinition = types.get(((ComplexTypeReference) propertyType).getName());
+        final TypeDefinition propertyTypeDefinition = getTypeDefinitions().get(((ComplexTypeReference) propertyType).getName());
         // If we're not accessing any child property, no need to handle anything special.
         if(vl.getChild() == null) {
             return name;
@@ -738,59 +491,28 @@ public class CLanguageTemplateHelper implements FreemarkerLanguageTemplateHelper
         // If there is a child we need to check if this is a discriminator property.
         // As discriminator properties are not real properties, but saved in the static metadata
         // of a type, we need to generate a different access pattern.
-        final Optional<DiscriminatorField> discriminatorFieldOptional = ((ComplexTypeDefinition) propertyTypeDefinition).getFields().stream().filter(
-            curField -> curField instanceof DiscriminatorField).map(curField -> (DiscriminatorField) curField).filter(
-            discriminatorField -> discriminatorField.getName().equals(vl.getChild().getName())).findFirst();
-        // If child references a discriminator field of the type we found, we have to escape it.
-        if(discriminatorFieldOptional.isPresent()) {
-            return "plc4c_" + getCTypeName(propertyTypeDefinition.getName()) + "_get_discriminator(" + name +"->_type)." + vl.getChild().getName();
+        if(propertyTypeDefinition instanceof ComplexTypeDefinition) {
+            final Optional<DiscriminatorField> discriminatorFieldOptional = ((ComplexTypeDefinition) propertyTypeDefinition).getFields().stream().filter(
+                curField -> curField instanceof DiscriminatorField).map(curField -> (DiscriminatorField) curField).filter(
+                discriminatorField -> discriminatorField.getName().equals(vl.getChild().getName())).findFirst();
+            // If child references a discriminator field of the type we found, we have to escape it.
+            if (discriminatorFieldOptional.isPresent()) {
+                return "plc4c_" + getCTypeName(propertyTypeDefinition.getName()) + "_get_discriminator(" + name + "->_type)." + vl.getChild().getName();
+            }
+        }
+        // Handling enum properties in C is a little more tricky as we have to use the enum value
+        // and pass this to a function that then returns the desired property value.
+        else if(propertyTypeDefinition instanceof EnumTypeDefinition) {
+            EnumTypeDefinition enumTypeDefinition = (EnumTypeDefinition) propertyTypeDefinition;
+            StringBuilder sb = new StringBuilder("plc4c_")
+                .append(getCTypeName(propertyTypeDefinition.getName()))
+                .append("_get_").append(camelCaseToSnakeCase(vl.getChild().getName()));
+            return sb.toString();
         }
         // Else ... generate a simple access path.
         return vl.getName() + ((vl.getChild() != null) ? "." + toVariableExpressionRest(vl.getChild()) : "");
     }
 
-    private Optional<TypeReference> getTypeReference(ComplexTypeDefinition baseType, String propertyName) {
-        // If this is a built-in type, use that.
-        if(builtInFields.containsKey(propertyName)) {
-            return Optional.of(builtInFields.get(propertyName));
-        }
-        // Check if the expression root is referencing a field
-        final Optional<PropertyField> propertyFieldOptional = baseType.getFields().stream().filter(
-            field -> field instanceof PropertyField).map(field -> (PropertyField) field).filter(
-                propertyField -> propertyField.getName().equals(propertyName)).findFirst();
-        if(propertyFieldOptional.isPresent()) {
-            final PropertyField propertyField = propertyFieldOptional.get();
-            return Optional.of(propertyField.getType());
-        }
-        // Check if the expression is a ImplicitField
-        final Optional<ImplicitField> implicitFieldOptional = baseType.getFields().stream().filter(
-            field -> field instanceof ImplicitField).map(field -> (ImplicitField) field).filter(
-            implicitField -> implicitField.getName().equals(propertyName)).findFirst();
-        if(implicitFieldOptional.isPresent()) {
-            final ImplicitField implicitField = implicitFieldOptional.get();
-            return Optional.of(implicitField.getType());
-        }
-        // Check if the expression root is referencing an argument
-        if(baseType.getParserArguments() != null) {
-            final Optional<Argument> argumentOptional = Arrays.stream(baseType.getParserArguments()).filter(
-                argument -> argument.getName().equals(propertyName)).findFirst();
-            if (argumentOptional.isPresent()) {
-                final Argument argument = argumentOptional.get();
-                return Optional.of(argument.getType());
-            }
-        }
-        // Check if the expression is a DiscriminatorField
-        // This is a more theoretical case where the expression is referencing a discriminator value of the current type
-        final Optional<DiscriminatorField> discriminatorFieldOptional = baseType.getFields().stream().filter(
-            field -> field instanceof DiscriminatorField).map(field -> (DiscriminatorField) field).filter(
-                discriminatorField -> discriminatorField.getName().equals(propertyName)).findFirst();
-        if(discriminatorFieldOptional.isPresent()) {
-            final DiscriminatorField discriminatorField = discriminatorFieldOptional.get();
-            return Optional.of(discriminatorField.getType());
-        }
-        return Optional.empty();
-    }
-
     private String toVariableSerializationExpression(Term term, Argument[] serialzerArguments) {
         VariableLiteral vl = (VariableLiteral) term;
         if ("STATIC_CALL".equals(vl.getName())) {
@@ -983,7 +705,7 @@ public class CLanguageTemplateHelper implements FreemarkerLanguageTemplateHelper
     }
 
     public String getReservedValue(ReservedField reservedField) {
-        final String languageTypeName = getLanguageTypeName(reservedField.getType());
+        final String languageTypeName = getLanguageTypeNameForField(reservedField);
         if ("BigInteger".equals(languageTypeName)) {
             return "BigInteger.valueOf(" + reservedField.getReferenceValue() + ")";
         } else {
@@ -991,51 +713,8 @@ public class CLanguageTemplateHelper implements FreemarkerLanguageTemplateHelper
         }
     }
 
-    public SimpleTypeReference getEnumBaseType(TypeReference enumType) {
-        if (!(enumType instanceof ComplexTypeReference)) {
-            throw new RuntimeException("type reference for enum types must be of type complex type");
-        }
-        ComplexTypeReference complexType = (ComplexTypeReference) enumType;
-        EnumTypeDefinition enumTypeDefinition = (EnumTypeDefinition) types.get(complexType.getName());
-        return (SimpleTypeReference) enumTypeDefinition.getType();
-    }
-
-    public Collection<String> getIncludeTypesForHFiles() {
-        Set<String> imports = new TreeSet<>();
-        // Add all the complex types references in parser arguments.
-        if (thisType.getParserArguments() != null) {
-            for (Argument parserArgument : thisType.getParserArguments()) {
-                if (parserArgument.getType() instanceof ComplexTypeReference) {
-                    ComplexTypeReference complexTypeReference = (ComplexTypeReference) parserArgument.getType();
-                    imports.add(camelCaseToSnakeCase(complexTypeReference.getName()));
-                }
-            }
-        }
-        // Add all the complex types referenced in field declarations.
-        for (ComplexTypeReference complexTypeReferencesInField : getComplexTypeReferencesInFields()) {
-            imports.add(camelCaseToSnakeCase(complexTypeReferencesInField.getName()));
-        }
-        // If this is a discriminated type, add an import to the parent type.
-        if (thisType instanceof DiscriminatedComplexTypeDefinition) {
-            DiscriminatedComplexTypeDefinition discriminatedType = (DiscriminatedComplexTypeDefinition) thisType;
-            imports.add(camelCaseToSnakeCase(discriminatedType.getParentType().getName()));
-        }
-        return imports;
-    }
-
-    public Collection<String> getIncludeTypesForCFiles() {
-        List<String> imports = new LinkedList<>();
-        // Add a reference to the current types header file itself.
-        imports.add(camelCaseToSnakeCase(thisType.getName()));
-        return imports;
-    }
-
-    private String getVariableLiteralName(VariableLiteral variableLiteral) {
-        return variableLiteral.getName() + ((variableLiteral.getChild() != null) ?
-            "_" + getVariableLiteralName(variableLiteral.getChild()) : "");
-    }
-
-    private String getDiscriminatorName(Term discriminatorExpression) {
+    @Override
+    public String getDiscriminatorName(Term discriminatorExpression) {
         if(discriminatorExpression instanceof Literal) {
             Literal literal = (Literal) discriminatorExpression;
             if(literal instanceof NullLiteral) {
@@ -1064,83 +743,9 @@ public class CLanguageTemplateHelper implements FreemarkerLanguageTemplateHelper
         return "";
     }
 
-    private Optional<TypeReference> getDiscriminatorType(ComplexTypeDefinition parentType, Term disciminatorExpression) {
-        if (!(disciminatorExpression instanceof VariableLiteral)) {
-            throw new RuntimeException("Currently no arithmetic expressions are supported as discriminator expressions.");
-        }
-        VariableLiteral variableLiteral = (VariableLiteral) disciminatorExpression;
-        Optional<TypeReference> type = getTypeReference(parentType, variableLiteral.getName());
-        // If we found something but there's a "rest" left, we got to use the type we
-        // found in this level, get that type's definition and continue from there.
-        if (type.isPresent() && (variableLiteral.getChild() != null)) {
-            TypeReference typeReference = type.get();
-            if (typeReference instanceof ComplexTypeReference) {
-                ComplexTypeReference complexTypeReference = (ComplexTypeReference) typeReference;
-                final TypeDefinition typeDefinition = this.types.get(complexTypeReference.getName());
-                if (typeDefinition instanceof ComplexTypeDefinition) {
-                    return getDiscriminatorType((ComplexTypeDefinition) typeDefinition, variableLiteral.getChild());
-                }
-            }
-        }
-        return type;
-    }
-
-    public Map<String, TypeReference> getDiscriminatorTypes() {
-        // Get the parent type (Which contains the typeSwitch field)
-        ComplexTypeDefinition parentType;
-        if (thisType instanceof DiscriminatedComplexTypeDefinition) {
-            parentType = (ComplexTypeDefinition) thisType.getParentType();
-        } else {
-            parentType = (ComplexTypeDefinition) thisType;
-        }
-        // Get the typeSwitch field from that.
-        final SwitchField switchField = getSwitchField(parentType);
-        if (switchField != null) {
-            Map<String, TypeReference> discriminatorTypes = new TreeMap<>();
-            for (Term discriminatorExpression : switchField.getDiscriminatorExpressions()) {
-                // Get some symbolic name we can use.
-                String discriminatorName = getDiscriminatorName(discriminatorExpression);
-                Optional<TypeReference> discriminatorType = getDiscriminatorType(parentType, discriminatorExpression);
-                discriminatorTypes.put(discriminatorName, discriminatorType.orElse(null));
-            }
-            return discriminatorTypes;
-        }
-        return Collections.emptyMap();
-    }
-
-    public Map<String, Map<String, String>> getDiscriminatorValues() {
-        // Get the parent type (Which contains the typeSwitch field)
-        ComplexTypeDefinition parentType;
-        if (thisType instanceof DiscriminatedComplexTypeDefinition) {
-            parentType = (ComplexTypeDefinition) thisType.getParentType();
-        } else {
-            parentType = (ComplexTypeDefinition) thisType;
-        }
-        // Get the typeSwitch field from that.
-        final SwitchField switchField = getSwitchField(parentType);
-        if (switchField != null) {
-            // Get the symbolic names of all discriminators
-            String[] discriminatorNames = new String[switchField.getDiscriminatorExpressions().length];
-            for (int i = 0; i < switchField.getDiscriminatorExpressions().length; i++) {
-                discriminatorNames[i] = getDiscriminatorName(switchField.getDiscriminatorExpressions()[i]);
-            }
-            // Build a map containing the named discriminator values for every case of the typeSwitch.
-            Map<String, Map<String, String>> discriminatorTypes = new TreeMap<>();
-            for (DiscriminatedComplexTypeDefinition switchCase : switchField.getCases()) {
-                discriminatorTypes.put(switchCase.getName(), new TreeMap<>());
-                for (int i = 0; i < switchField.getDiscriminatorExpressions().length; i++) {
-                    String discriminatorValue;
-                    if (i < switchCase.getDiscriminatorValues().length) {
-                        discriminatorValue = switchCase.getDiscriminatorValues()[i];
-                    } else {
-                        discriminatorValue = null;
-                    }
-                    discriminatorTypes.get(switchCase.getName()).put(discriminatorNames[i], discriminatorValue);
-                }
-            }
-            return discriminatorTypes;
-        }
-        return Collections.emptyMap();
+    private String getVariableLiteralName(VariableLiteral variableLiteral) {
+        return variableLiteral.getName() + ((variableLiteral.getChild() != null) ?
+            "_" + getVariableLiteralName(variableLiteral.getChild()) : "");
     }
 
 }
diff --git a/build-utils/language-c/src/main/resources/templates/c/enum-template.ftlh b/build-utils/language-c/src/main/resources/templates/c/enum-template.ftlh
index 4c84d58..35994fd 100644
--- a/build-utils/language-c/src/main/resources/templates/c/enum-template.ftlh
+++ b/build-utils/language-c/src/main/resources/templates/c/enum-template.ftlh
@@ -16,7 +16,7 @@
   specific language governing permissions and limitations
   under the License.
 -->
-${helper.setConstants(type, protocolName, outputFlavor)}${helper.getIncludesDirectory()?replace(".", "/")}/${helper.camelCaseToSnakeCase(typeName)}.h
+${helper.getIncludesDirectory()?replace(".", "/")}/${helper.camelCaseToSnakeCase(typeName)}.h
 /*
   Licensed to the Apache Software Foundation (ASF) under one
   or more contributor license agreements.  See the NOTICE file
@@ -43,10 +43,13 @@ extern "C" {
 #endif
 
 #include <stdbool.h>
-<#if helper.getComplexTypeReferencesInFields()?has_content>
-  <#list helper.getComplexTypeReferencesInFields() as complexType>
-#include "${helper.camelCaseToSnakeCase(complexType.getName())}.h"
-  </#list>
+<#--
+    Add any import statements for partent-types, complex types used in properties or parser arguments.
+-->
+<#if helper.getComplexTypeReferences()?has_content>
+    <#list helper.getComplexTypeReferences() as typeReference>
+#include "${helper.camelCaseToSnakeCase(typeReference.name)}.h"
+    </#list>
 </#if>
 
 <#--
@@ -68,7 +71,7 @@ typedef enum plc4c_${helper.getCTypeName(type.name)} plc4c_${helper.getCTypeName
 <#if type.constantNames?has_content>
     <#list type.constantNames as constantName>
 
-${helper.getLanguageTypeName(type.getConstantType(constantName))} plc4c_${helper.getCTypeName(type.name)}_get_${helper.camelCaseToSnakeCase(constantName)}(plc4c_${helper.getCTypeName(type.name)} value) {
+${helper.getLanguageTypeNameForTypeReference(type.getConstantType(constantName))} plc4c_${helper.getCTypeName(type.name)}_get_${helper.camelCaseToSnakeCase(constantName)}(plc4c_${helper.getCTypeName(type.name)} value) {
   switch(value) {
         <#list helper.getUniqueEnumValues(type.enumValues) as enumValue>
     case ${helper.escapeValue(type.type, enumValue.value)}: { /* '${enumValue.value}' */
diff --git a/build-utils/language-c/src/main/resources/templates/c/pojo-template-c.ftlh b/build-utils/language-c/src/main/resources/templates/c/pojo-template-c.ftlh
index d3c7cee..e4952dc 100644
--- a/build-utils/language-c/src/main/resources/templates/c/pojo-template-c.ftlh
+++ b/build-utils/language-c/src/main/resources/templates/c/pojo-template-c.ftlh
@@ -16,7 +16,7 @@
   specific language governing permissions and limitations
   under the License.
 -->
-<#if !helper.isDiscriminatedType(type)>${helper.setConstants(type, protocolName, outputFlavor)}${helper.getSourceDirectory()?replace(".", "/")}/${helper.camelCaseToSnakeCase(typeName)}.c
+<#if !helper.isDiscriminatedChildTypeDefinition(type)>${helper.getSourceDirectory()?replace(".", "/")}/${helper.camelCaseToSnakeCase(typeName)}.c
 /*
   Licensed to the Apache Software Foundation (ASF) under one
   or more contributor license agreements.  See the NOTICE file
@@ -40,15 +40,10 @@
 #include <plc4c/spi/read_buffer.h>
 #include <plc4c/spi/write_buffer.h>
 #include <plc4c/spi/evaluation_helper.h>
-<#-- Add any needed import statements -->
-<#if helper.getIncludeTypesForCFiles()?has_content>
-    <#list helper.getIncludeTypesForCFiles() as typeImport>
-#include "${typeImport}.h"
-    </#list>
-</#if>
-<#-- Helper function to get the discriminator for a given enum type constant -->
-<#if helper.isAbstractType(type)>
+#include "${helper.camelCaseToSnakeCase(type.name)}.h"
 
+<#-- Helper function to get the discriminator for a given enum type constant -->
+<#if helper.isDiscriminatedParentTypeDefinition(type)>
 // Array of discriminator values that match the enum type constants.
 // (The order is identical to the enum constants so we can use the
 // enum constant to directly access a given types discriminator values)
@@ -66,10 +61,10 @@ const plc4c_${helper.getCTypeName(type.name)}_discriminator plc4c_${helper.getCT
 plc4c_${helper.getCTypeName(type.name)}_discriminator plc4c_${helper.getCTypeName(type.name)}_get_discriminator(plc4c_${helper.getCTypeName(type.name)}_type type) {
   return plc4c_${helper.getCTypeName(type.name)}_discriminators[type];
 }
-</#if>
 
+</#if>
 // Parse function.
-plc4c_return_code plc4c_${helper.getCTypeName(type.name)}_parse(plc4c_spi_read_buffer* buf, <#if type.parserArguments?has_content><#list type.parserArguments as parserArgument>${helper.getLanguageTypeName(parserArgument.type)}<#if !helper.isSimpleType(parserArgument.type)>*</#if> ${parserArgument.name}<#sep>, </#list>, </#if>plc4c_${helper.getCTypeName(type.name)}** message) {
+plc4c_return_code plc4c_${helper.getCTypeName(type.name)}_parse(plc4c_spi_read_buffer* buf, <#if type.parserArguments?has_content><#list type.parserArguments as parserArgument>${helper.getLanguageTypeNameForTypeReference(parserArgument.type)}<#if !helper.isSimpleTypeReference(parserArgument.type)>*</#if> ${parserArgument.name}<#sep>, </#list>, </#if>plc4c_${helper.getCTypeName(type.name)}** message) {
   uint16_t startPos = plc4c_spi_read_get_pos(buf);
   uint16_t curPos;
 
@@ -80,8 +75,57 @@ plc4c_return_code plc4c_${helper.getCTypeName(type.name)}_parse(plc4c_spi_read_b
 </#if>
 <#list type.fields as field>
     <#switch field.typeName>
-        <#case "checksum">
+        <#case "array">
+  // Array field (${field.name})
+            <#-- Only update curPos if the length expression uses it -->
+            <#if field.loopExpression.contains("curPos")>
+  curPos = plc4c_spi_read_get_pos(buf) - startPos;
+            </#if>
+            <#-- In all other cases do we have to work with a list, that is later converted to an array -->
+  plc4c_list ${field.name};
+  {
+            <#if helper.isCountArrayField(field)>
+    // Count array
+    uint8_t itemCount = ${helper.toParseExpression(field.loopExpression, type.parserArguments)?no_esc};
+    for(int curItem = 0; curItem < itemCount; curItem++) {
+      <#if !helper.isSimpleTypeReference(field.type)>boolean lastItem = curItem == (itemCount - 1);</#if>
+      <#-- Inizialize a local variable with the simple type (Intentionally keeping the java-style names so they can be used in expressions) -->
+                <#if helper.isSimpleTypeReference(field.type)>
+      ${helper.getLanguageTypeNameForTypeReference(field.type)} value = ${helper.getReadBufferReadMethodCall(field.type)?no_esc};
+                <#else>
+      <#-- Inizialize a local variable with the complex type (Intentionally keeping the java-style names so they can be used in expressions) -->
+      ${helper.getLanguageTypeNameForField(field)}* value = NULL;
+      plc4c_${helper.getCTypeName(field.type.name)}_parse(buf<#if field.params?has_content>, <#list field.params as parserTerm>${helper.toParseExpression(parserTerm, type.parserArguments)}<#sep>, </#sep></#list></#if>, (void*) &${field.name});
+                </#if>
+      plc4c_utils_list_insert_head_value(&${field.name}, &value);
+    }
+            <#-- For a length array, we read data till the read position of the buffer reaches a given position -->
+            <#elseif helper.isLengthArrayField(field)>
+    // Length array
+    uint8_t _${field.name}Length = ${helper.toParseExpression(field.loopExpression, type.parserArguments)?no_esc};
+    uint8_t ${field.name}EndPos = plc4c_spi_read_get_pos(buf) + _${field.name}Length;
+    while(plc4c_spi_read_get_pos(buf) < ${field.name}EndPos) {
+      plc4c_utils_list_insert_head_value(&${field.name}, <#if helper.isSimpleTypeReference(field.type)>${helper.getReadBufferReadMethodCall(field.type)?no_esc}<#else>plc4c_${helper.getCTypeName(field.type.name)}_parse(buf<#if field.params?has_content>, <#list field.params as parserTerm>${helper.toParseExpression(parserTerm, type.parserArguments)}<#sep>, </#sep></#list></#if>, (void*) &${field.name})</#if>);
+                <#-- After parsing, update the current position, but only if it's needed -->
+                <#if field.loopExpression.contains("curPos")>
+      curPos = plc4c_spi_read_get_pos(buf) - startPos;
+                </#if>
+    }
+            <#-- A terminated array keeps on reading data as long as the termination expression evaluates to false -->
+            <#elseif helper.isTerminatedArrayField(field)>
+    // Terminated array
+    while(!((boolean) (${helper.toParseExpression(field.loopExpression, type.parserArguments)?no_esc}))) {
+      plc4c_utils_list_insert_head_value(&${field.name}, <#if helper.isSimpleTypeReference(field.type)>${helper.getReadBufferReadMethodCall(field.type)?no_esc}<#else>${field.type.name}IO.staticParse(io<#if field.params?has_content>, <#list field.params as parserArgument>(${helper.getArgumentType(field.type, parserArgument?index)}) (${helper.toParseExpression(parserArgument, type.parserArguments)?no_esc})<#sep>, </#sep></#list></#if>)</#if>);
+              <#-- After parsing, update the current position, but only if it's needed -->
+              <#if field.loopExpression.contains("curPos")>
+      curPos = plc4c_spi_read_get_pos(buf) - startPos;
+              </#if>
+    }
+            </#if>
+  }
 
+            <#break>
+        <#case "checksum">
   // Checksum Field (${field.name})
   ${helper.getLanguageTypeNameForField(field)} ${field.name} = ${helper.getNullValueForType(field.type)};
   {
@@ -94,47 +138,51 @@ plc4c_return_code plc4c_${helper.getCTypeName(type.name)}_parse(plc4c_spi_read_b
       // throw new ParseException(String.format("Checksum verification failed. Expected %04X but got %04X",_${field.name}Ref & 0xFFFF, ${field.name} & 0xFFFF));
     }
   }
+
             <#break>
         <#case "const">
-
   // Const Field (${field.name})
   ${helper.getLanguageTypeNameForField(field)} ${field.name} = ${helper.getReadBufferReadMethodCall(field.type)?no_esc};
   if(${field.name} != ${helper.getCTypeName(type.name)?upper_case}_${helper.camelCaseToSnakeCase(field.name)?upper_case}) {
     return PARSE_ERROR;
     // throw new ParseException("Expected constant value " + ${typeName}.${field.name?upper_case} + " but got " + ${field.name});
   }
+
             <#break>
         <#case "enum">
-
   // Enum field (${field.name})
-  ${helper.getLanguageTypeNameForField(field)} ${field.name} = ${helper.getReadBufferReadMethodCall(helper.getEnumBaseType(field.type))?no_esc};
+  ${helper.getLanguageTypeNameForField(field)} ${field.name} = ${helper.getReadBufferReadMethodCall(helper.getEnumBaseTypeReference(field.type))?no_esc};
   msg->${helper.camelCaseToSnakeCase(field.name)} = ${field.name};
+
             <#break>
         <#case "discriminator">
-
   // Discriminator Field (${field.name}) (Used as input to a switch field)
   ${helper.getLanguageTypeNameForField(field)} ${field.name} = ${helper.getReadBufferReadMethodCall(field.type)?no_esc};
+
             <#break>
         <#case "implicit">
-
   // Implicit Field (${field.name}) (Used for parsing, but it's value is not stored as it's implicitly given by the objects content)
   ${helper.getLanguageTypeNameForField(field)} ${field.name} = ${helper.getReadBufferReadMethodCall(field.type)?no_esc};
+
             <#break>
-        <#case "manual">
+        <#case "manualArray">
+             <#-- TODO: Implement -->
 
+            <#break>
+        <#case "manual">
   // Manual Field (${field.name})
   ${helper.getLanguageTypeNameForField(field)} ${field.name} = (${helper.getLanguageTypeNameForField(field)}) (${helper.toParseExpression(field.parseExpression, type.parserArguments)});
   msg->${helper.camelCaseToSnakeCase(field.name)} = ${field.name};
+
         <#break>
         <#case "optional">
-
   // Optional Field (${field.name}) (Can be skipped, if a given expression evaluates to false)
             <#if field.conditionExpression.contains("curPos")>
   curPos = plc4c_spi_read_get_pos(buf) - startPos;
             </#if>
-  ${helper.getLanguageTypeNameForField(field)}<#if !helper.isSimpleType(field.type)>*</#if> ${field.name} = <#if !helper.isSimpleType(field.type)>NULL<#else>0</#if>;
+  ${helper.getLanguageTypeNameForField(field)}<#if !helper.isSimpleTypeReference(field.type)>*</#if> ${field.name} = <#if !helper.isSimpleTypeReference(field.type)>NULL<#else>0</#if>;
   if(${helper.toParseExpression(field.conditionExpression, type.parserArguments)?no_esc}) {
-        <#if helper.isSimpleType(field.type)>
+        <#if helper.isSimpleTypeReference(field.type)>
     ${field.name} = ${helper.getReadBufferReadMethodCall(field.type)?no_esc};
         <#else>
     plc4c_${helper.getCTypeName(field.type.name)}* ${field.name} = NULL;
@@ -142,18 +190,18 @@ plc4c_return_code plc4c_${helper.getCTypeName(type.name)}_parse(plc4c_spi_read_b
         </#if>
     msg->${helper.camelCaseToSnakeCase(field.name)} = ${field.name};
   }
+
             <#break>
         <#case "padding">
-
   // Padding Field (${field.name})
   bool _${field.name}NeedsPadding = (bool) ((plc4c_spi_read_has_more(buf, ${helper.getNumBits(field.type)})) && (${helper.toParseExpression(field.paddingCondition, type.parserArguments)?no_esc}));
   if(_${field.name}NeedsPadding) {
     // Just read the padding data and ignore it
     ${helper.getReadBufferReadMethodCall(field.type)?no_esc};
   }
+
             <#break>
         <#case "reserved">
-
   // Reserved Field (Compartmentalized so the "reserved" variable can't leak)
   {
     ${helper.getLanguageTypeNameForField(field)} reserved = ${helper.getReadBufferReadMethodCall(field.type)?no_esc};
@@ -161,12 +209,12 @@ plc4c_return_code plc4c_${helper.getCTypeName(type.name)}_parse(plc4c_spi_read_b
       printf("Expected constant value '%d' but got '%d' for reserved field.", ${field.referenceValue}, reserved);
     }
   }
+
             <#break>
         <#case "simple">
-
   // Simple Field (${field.name})
             <#-- Inizialize a local variable with the simple type (Intentionally keeping the java-style names so they can be used in expressions) -->
-            <#if helper.isSimpleType(field.type)>
+            <#if helper.isSimpleTypeReference(field.type)>
   ${helper.getLanguageTypeNameForField(field)} ${field.name} = ${helper.getReadBufferReadMethodCall(field.type)?no_esc};
             <#else>
             <#-- Inizialize a local variable with the complex type (Intentionally keeping the java-style names so they can be used in expressions) -->
@@ -174,25 +222,26 @@ plc4c_return_code plc4c_${helper.getCTypeName(type.name)}_parse(plc4c_spi_read_b
   plc4c_${helper.getCTypeName(field.type.name)}_parse(buf<#if field.params?has_content>, <#list field.params as parserTerm>${helper.toParseExpression(parserTerm, type.parserArguments)}<#sep>, </#sep></#list></#if>, (void*) &${field.name});
             </#if>
   msg->${helper.camelCaseToSnakeCase(field.name)} = ${field.name};
+
             <#break>
         <#case "switch">
-
   // Switch Field (Depending on the discriminator values, passes the instantiation to a sub-type)
             <#list field.cases as case>
   <#if case.discriminatorValues?has_content>if(<#list case.discriminatorValues as discriminatorValue><#if case.discriminatorValues?size &gt; 1>(</#if>${helper.toVariableParseExpression(field.discriminatorExpressions[discriminatorValue?index], type.parserArguments)?no_esc}<#--${helper.toVariableParseExpressionHurz(field)}--> == ${discriminatorValue}<#if case.discriminatorValues?size &gt; 1>)</#if><#sep> && </#sep></#list>) </#if>{ /* ${case.name} */
                 <#list case.propertyFields as caseField>
-    ${helper.getLanguageTypeNameForField(caseField)}<#if !helper.isSimpleType(caseField.type)>*</#if> ${caseField.name}<#if field.loopType??>${helper.getLoopExpressionSuffix(caseField)}</#if><#if helper.getLanguageTypeNameForField(caseField) == "plc4c_list"><#elseif !helper.isSimpleType(caseField.type)> = NULL<#else> = -1</#if>;
+    ${helper.getLanguageTypeNameForField(caseField)}<#if !helper.isSimpleTypeReference(caseField.type)>*</#if> ${caseField.name}<#if field.loopType??>${helper.getLoopExpressionSuffix(caseField)}</#if><#if helper.getLanguageTypeNameForField(caseField) == "plc4c_list"><#elseif !helper.isSimpleTypeReference(caseField.type)> = NULL<#else> = -1</#if>;
     msg->${helper.camelCaseToSnakeCase(case.name)}_${helper.camelCaseToSnakeCase(caseField.name)} = ${caseField.name};
                     <#sep >
 
                 </#list>
   }<#sep> else </#sep>
             </#list>
+
             <#break>
         <#case "virtual">
-
   // Virtual field (Just declare a local variable so we can access it in the parser)
   ${helper.getLanguageTypeNameForField(field)} ${field.name} = (${helper.getLanguageTypeNameForField(field)}) (${helper.toParseExpression(field.valueExpression, type.parserArguments)});
+
             <#break>
     </#switch>
 </#list>
diff --git a/build-utils/language-c/src/main/resources/templates/c/pojo-template-h.ftlh b/build-utils/language-c/src/main/resources/templates/c/pojo-template-h.ftlh
index 3737ea6..b3599ff 100644
--- a/build-utils/language-c/src/main/resources/templates/c/pojo-template-h.ftlh
+++ b/build-utils/language-c/src/main/resources/templates/c/pojo-template-h.ftlh
@@ -16,7 +16,7 @@
   specific language governing permissions and limitations
   under the License.
 -->
-<#if !helper.isDiscriminatedType(type)>${helper.setConstants(type, protocolName, outputFlavor)}${helper.getIncludesDirectory()?replace(".", "/")}/${helper.camelCaseToSnakeCase(typeName)}.h
+<#if !helper.isDiscriminatedChildTypeDefinition(type)>${helper.getIncludesDirectory()?replace(".", "/")}/${helper.camelCaseToSnakeCase(typeName)}.h
 /*
   Licensed to the Apache Software Foundation (ASF) under one
   or more contributor license agreements.  See the NOTICE file
@@ -47,9 +47,9 @@ extern "C" {
 <#--
     Add any import statements for partent-types, complex types used in properties or parser arguments.
 -->
-<#if helper.getIncludeTypesForHFiles()?has_content>
-    <#list helper.getIncludeTypesForHFiles() as typeImport>
-#include "${typeImport}.h"
+<#if helper.getComplexTypeReferences()?has_content>
+    <#list helper.getComplexTypeReferences() as typeReference>
+#include "${helper.camelCaseToSnakeCase(typeReference.name)}.h"
     </#list>
 </#if>
 <#--
@@ -58,13 +58,13 @@ extern "C" {
     data-structure. So with this enum we're doing exactly this. It will be used in the serializers and
     parsers and stored in discriminated types.
 -->
-<#if helper.isAbstractType(type)>
+<#if helper.isDiscriminatedParentTypeDefinition(type)>
 
 // Structure used to contain the discriminator values for discriminated types using this as a parent
 struct plc4c_${helper.getCTypeName(type.name)}_discriminator {
 <#if helper.getDiscriminatorTypes()?has_content>
     <#list helper.getDiscriminatorTypes()?keys as discriminatorName>
-  ${helper.getLanguageTypeName(helper.getDiscriminatorTypes()[discriminatorName])} ${discriminatorName};
+  ${helper.getLanguageTypeNameForTypeReference(helper.getDiscriminatorTypes()[discriminatorName])} ${discriminatorName};
     </#list>
 </#if>
 };
@@ -72,7 +72,7 @@ typedef struct plc4c_${helper.getCTypeName(type.name)}_discriminator plc4c_${hel
 
 // Enum assigning each sub-type an individual id.
 enum plc4c_${helper.getCTypeName(type.name)}_type {
-    <#list helper.getDiscriminatedSubTypes() as subtype>
+    <#list helper.getSubTypeDefinitions() as subtype>
   plc4c_${helper.getCTypeName(type.name)}_type_${helper.getCTypeName(subtype.name)} = ${subtype?index}<#sep>,
     </#list>
 };
@@ -97,18 +97,18 @@ const ${helper.getLanguageTypeNameForField(field)} ${helper.getCTypeName(type.na
     Create the general data-structure for this type
 -->
 struct plc4c_${helper.getCTypeName(type.name)} {
+<#if helper.isDiscriminatedParentTypeDefinition(type)>
   /* This is an abstract type so this property saves the type of this typed union */
-<#if helper.isAbstractType(type)>
   plc4c_${helper.getCTypeName(type.name)}_type _type;
 </#if>
   /* Properties */
-<#list helper.getFields() as field>
+<#list helper.getPropertyAndSwitchFields() as field>
     <#if helper.isSwitchField(field)>
   union {
         <#list field.cases as case>
     struct { /* ${case.name} */
             <#list case.propertyFields as caseField>
-      ${helper.getLanguageTypeNameForField(caseField)}<#if !helper.isSimpleType(caseField.type)>*</#if> ${helper.camelCaseToSnakeCase(case.name)}_${helper.camelCaseToSnakeCase(caseField.name)}${helper.getTypeSizeForField(caseField)}<#if field.loopType??>${helper.getLoopExpressionSuffix(caseField)}</#if>;
+      ${helper.getLanguageTypeNameForField(caseField)}<#if !helper.isSimpleTypeReference(caseField.type)>*</#if> ${helper.camelCaseToSnakeCase(case.name)}_${helper.camelCaseToSnakeCase(caseField.name)}${helper.getTypeSizeForField(caseField)}<#if field.loopType??>${helper.getLoopExpressionSuffix(caseField)}</#if>;
             </#list>
     };
         </#list>
@@ -116,7 +116,7 @@ struct plc4c_${helper.getCTypeName(type.name)} {
     <#elseif helper.isEnumField(field)>
   ${helper.getLanguageTypeNameForField(field)} ${helper.camelCaseToSnakeCase(field.name)};
     <#else>
-  ${helper.getLanguageTypeNameForField(field)}<#if !helper.isSimpleType(field.type)>*</#if> ${helper.camelCaseToSnakeCase(field.name)}${helper.getTypeSizeForField(field)}<#if field.loopType??>${helper.getLoopExpressionSuffix(field)}</#if>;
+  ${helper.getLanguageTypeNameForField(field)}<#if !helper.isSimpleTypeReference(field.type)>*</#if> ${helper.camelCaseToSnakeCase(field.name)}${helper.getTypeSizeForField(field)}<#if field.loopType??>${helper.getLoopExpressionSuffix(field)}</#if>;
     </#if>
 </#list>
 };
@@ -125,7 +125,7 @@ typedef struct plc4c_${helper.getCTypeName(type.name)} plc4c_${helper.getCTypeNa
 <#--
     Define the parse-method for elements of this tpye
 -->
-plc4c_return_code plc4c_${helper.getCTypeName(type.name)}_parse(plc4c_spi_read_buffer* buf, <#if type.parserArguments?has_content><#list type.parserArguments as parserArgument>${helper.getLanguageTypeName(parserArgument.type)}<#if !helper.isSimpleType(parserArgument.type)>*</#if> ${parserArgument.name}<#sep>, </#list>, </#if>plc4c_${helper.getCTypeName(type.name)}** message);
+plc4c_return_code plc4c_${helper.getCTypeName(type.name)}_parse(plc4c_spi_read_buffer* buf, <#if type.parserArguments?has_content><#list type.parserArguments as parserArgument>${helper.getLanguageTypeNameForTypeReference(parserArgument.type)}<#if !helper.isSimpleTypeReference(parserArgument.type)>*</#if> ${parserArgument.name}<#sep>, </#list>, </#if>plc4c_${helper.getCTypeName(type.name)}** message);
 
 <#--
     Define the serialize-method for elements of this tpye
diff --git a/build-utils/language-java/src/main/java/org/apache/plc4x/language/java/JavaLanguageOutput.java b/build-utils/language-java/src/main/java/org/apache/plc4x/language/java/JavaLanguageOutput.java
index 534765a..f3120a4 100644
--- a/build-utils/language-java/src/main/java/org/apache/plc4x/language/java/JavaLanguageOutput.java
+++ b/build-utils/language-java/src/main/java/org/apache/plc4x/language/java/JavaLanguageOutput.java
@@ -65,8 +65,8 @@ public class JavaLanguageOutput extends FreemarkerLanguageOutput {
     }
 
     @Override
-    protected FreemarkerLanguageTemplateHelper getHelper(Map<String, TypeDefinition> types) {
-        return new JavaLanguageTemplateHelper(types);
+    protected FreemarkerLanguageTemplateHelper getHelper(TypeDefinition thisType, String protocolName, String flavorName, Map<String, TypeDefinition> types) {
+        return new JavaLanguageTemplateHelper(thisType, protocolName, flavorName, types);
     }
 
 }
diff --git a/build-utils/language-java/src/main/java/org/apache/plc4x/language/java/JavaLanguageTemplateHelper.java b/build-utils/language-java/src/main/java/org/apache/plc4x/language/java/JavaLanguageTemplateHelper.java
index 659b4f3..fe235bc 100644
--- a/build-utils/language-java/src/main/java/org/apache/plc4x/language/java/JavaLanguageTemplateHelper.java
+++ b/build-utils/language-java/src/main/java/org/apache/plc4x/language/java/JavaLanguageTemplateHelper.java
@@ -35,9 +35,15 @@ import java.util.regex.Pattern;
 @SuppressWarnings({"unused", "WeakerAccess"})
 public class JavaLanguageTemplateHelper implements FreemarkerLanguageTemplateHelper {
 
+    private final TypeDefinition thisType;
+    private final String protocolName;
+    private final String flavorName;
     private final Map<String, TypeDefinition> types;
 
-    public JavaLanguageTemplateHelper(Map<String, TypeDefinition> types) {
+    public JavaLanguageTemplateHelper(TypeDefinition thisType, String protocolName, String flavorName, Map<String, TypeDefinition> types) {
+        this.thisType = thisType;
+        this.protocolName = protocolName;
+        this.flavorName = flavorName;
         this.types = types;
     }
 
diff --git a/build-utils/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/model/definitions/DefaultDataIoTypeDefinition.java b/build-utils/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/model/definitions/DefaultDataIoTypeDefinition.java
index 0e6e2fd..bbc1480 100644
--- a/build-utils/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/model/definitions/DefaultDataIoTypeDefinition.java
+++ b/build-utils/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/model/definitions/DefaultDataIoTypeDefinition.java
@@ -18,9 +18,11 @@ under the License.
 */
 package org.apache.plc4x.plugins.codegenerator.language.mspec.model.definitions;
 
+import org.apache.plc4x.plugins.codegenerator.language.mspec.model.references.DefaultComplexTypeReference;
 import org.apache.plc4x.plugins.codegenerator.types.definitions.Argument;
 import org.apache.plc4x.plugins.codegenerator.types.definitions.DataIoTypeDefinition;
 import org.apache.plc4x.plugins.codegenerator.types.fields.SwitchField;
+import org.apache.plc4x.plugins.codegenerator.types.references.TypeReference;
 
 public class DefaultDataIoTypeDefinition extends DefaultTypeDefinition implements DataIoTypeDefinition {
 
diff --git a/build-utils/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/model/definitions/DefaultTypeDefinition.java b/build-utils/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/model/definitions/DefaultTypeDefinition.java
index c4ebb22..2e1d7b4 100644
--- a/build-utils/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/model/definitions/DefaultTypeDefinition.java
+++ b/build-utils/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/model/definitions/DefaultTypeDefinition.java
@@ -20,8 +20,10 @@
 package org.apache.plc4x.plugins.codegenerator.language.mspec.model.definitions;
 
 
+import org.apache.plc4x.plugins.codegenerator.language.mspec.model.references.DefaultComplexTypeReference;
 import org.apache.plc4x.plugins.codegenerator.types.definitions.Argument;
 import org.apache.plc4x.plugins.codegenerator.types.definitions.TypeDefinition;
+import org.apache.plc4x.plugins.codegenerator.types.references.TypeReference;
 
 public abstract class DefaultTypeDefinition {
 
@@ -57,4 +59,8 @@ public abstract class DefaultTypeDefinition {
         this.parentType = parentType;
     }
 
+    public TypeReference getTypeReference() {
+        return new DefaultComplexTypeReference(getName());
+    }
+
 }
diff --git a/sandbox/plc4c/generated-sources/modbus/includes/modbus_constants.h b/sandbox/plc4c/generated-sources/modbus/includes/modbus_constants.h
index 2365896..86c511e 100644
--- a/sandbox/plc4c/generated-sources/modbus/includes/modbus_constants.h
+++ b/sandbox/plc4c/generated-sources/modbus/includes/modbus_constants.h
@@ -30,7 +30,6 @@ extern "C" {
 const uint16_t MODBUS_READ_WRITE_MODBUS_CONSTANTS_MODBUS_TCP_DEFAULT_PORT = 502;
 
 struct plc4c_modbus_read_write_modbus_constants {
-  /* This is an abstract type so this property saves the type of this typed union */
   /* Properties */
   uint16_t modbus_tcp_default_port;
 };
diff --git a/sandbox/plc4c/generated-sources/modbus/includes/modbus_pdu.h b/sandbox/plc4c/generated-sources/modbus/includes/modbus_pdu.h
index 7ed9afc..eef9471 100644
--- a/sandbox/plc4c/generated-sources/modbus/includes/modbus_pdu.h
+++ b/sandbox/plc4c/generated-sources/modbus/includes/modbus_pdu.h
@@ -25,10 +25,46 @@ extern "C" {
 #include <stdbool.h>
 #include <stdint.h>
 #include <plc4c/utils/list.h>
-#include "modbus_pdu_read_file_record_request_item.h"
+#include "modbus_pdu.h"
+#include "modbus_pdu.h"
+#include "modbus_pdu.h"
+#include "modbus_pdu.h"
+#include "modbus_pdu.h"
+#include "modbus_pdu.h"
+#include "modbus_pdu.h"
+#include "modbus_pdu.h"
+#include "modbus_pdu.h"
+#include "modbus_pdu.h"
+#include "modbus_pdu.h"
+#include "modbus_pdu.h"
+#include "modbus_pdu.h"
+#include "modbus_pdu.h"
+#include "modbus_pdu.h"
+#include "modbus_pdu.h"
+#include "modbus_pdu.h"
+#include "modbus_pdu.h"
+#include "modbus_pdu.h"
+#include "modbus_pdu.h"
+#include "modbus_pdu_write_file_record_response_item.h"
+#include "modbus_pdu.h"
+#include "modbus_pdu.h"
+#include "modbus_pdu.h"
+#include "modbus_pdu.h"
+#include "modbus_pdu.h"
+#include "modbus_pdu.h"
+#include "modbus_pdu.h"
+#include "modbus_pdu.h"
 #include "modbus_pdu_read_file_record_response_item.h"
+#include "modbus_pdu.h"
+#include "modbus_pdu.h"
 #include "modbus_pdu_write_file_record_request_item.h"
-#include "modbus_pdu_write_file_record_response_item.h"
+#include "modbus_pdu.h"
+#include "modbus_pdu.h"
+#include "modbus_pdu.h"
+#include "modbus_pdu.h"
+#include "modbus_pdu_read_file_record_request_item.h"
+#include "modbus_pdu.h"
+#include "modbus_pdu.h"
 
 // Structure used to contain the discriminator values for discriminated types using this as a parent
 struct plc4c_modbus_read_write_modbus_pdu_discriminator {
diff --git a/sandbox/plc4c/generated-sources/modbus/includes/modbus_pdu_read_file_record_request_item.h b/sandbox/plc4c/generated-sources/modbus/includes/modbus_pdu_read_file_record_request_item.h
index 9386b3c..f5fb10e 100644
--- a/sandbox/plc4c/generated-sources/modbus/includes/modbus_pdu_read_file_record_request_item.h
+++ b/sandbox/plc4c/generated-sources/modbus/includes/modbus_pdu_read_file_record_request_item.h
@@ -27,7 +27,6 @@ extern "C" {
 #include <plc4c/utils/list.h>
 
 struct plc4c_modbus_read_write_modbus_pdu_read_file_record_request_item {
-  /* This is an abstract type so this property saves the type of this typed union */
   /* Properties */
   uint8_t reference_type;
   uint16_t file_number;
diff --git a/sandbox/plc4c/generated-sources/modbus/includes/modbus_pdu_read_file_record_response_item.h b/sandbox/plc4c/generated-sources/modbus/includes/modbus_pdu_read_file_record_response_item.h
index 9aa9a91..142f84b 100644
--- a/sandbox/plc4c/generated-sources/modbus/includes/modbus_pdu_read_file_record_response_item.h
+++ b/sandbox/plc4c/generated-sources/modbus/includes/modbus_pdu_read_file_record_response_item.h
@@ -27,7 +27,6 @@ extern "C" {
 #include <plc4c/utils/list.h>
 
 struct plc4c_modbus_read_write_modbus_pdu_read_file_record_response_item {
-  /* This is an abstract type so this property saves the type of this typed union */
   /* Properties */
   uint8_t reference_type;
   plc4c_list data;
diff --git a/sandbox/plc4c/generated-sources/modbus/includes/modbus_pdu_write_file_record_request_item.h b/sandbox/plc4c/generated-sources/modbus/includes/modbus_pdu_write_file_record_request_item.h
index 3c41ee4..b6d0f89 100644
--- a/sandbox/plc4c/generated-sources/modbus/includes/modbus_pdu_write_file_record_request_item.h
+++ b/sandbox/plc4c/generated-sources/modbus/includes/modbus_pdu_write_file_record_request_item.h
@@ -27,7 +27,6 @@ extern "C" {
 #include <plc4c/utils/list.h>
 
 struct plc4c_modbus_read_write_modbus_pdu_write_file_record_request_item {
-  /* This is an abstract type so this property saves the type of this typed union */
   /* Properties */
   uint8_t reference_type;
   uint16_t file_number;
diff --git a/sandbox/plc4c/generated-sources/modbus/includes/modbus_pdu_write_file_record_response_item.h b/sandbox/plc4c/generated-sources/modbus/includes/modbus_pdu_write_file_record_response_item.h
index 2dfa1f5..5a9316a 100644
--- a/sandbox/plc4c/generated-sources/modbus/includes/modbus_pdu_write_file_record_response_item.h
+++ b/sandbox/plc4c/generated-sources/modbus/includes/modbus_pdu_write_file_record_response_item.h
@@ -27,7 +27,6 @@ extern "C" {
 #include <plc4c/utils/list.h>
 
 struct plc4c_modbus_read_write_modbus_pdu_write_file_record_response_item {
-  /* This is an abstract type so this property saves the type of this typed union */
   /* Properties */
   uint8_t reference_type;
   uint16_t file_number;
diff --git a/sandbox/plc4c/generated-sources/modbus/includes/modbus_serial_adu.h b/sandbox/plc4c/generated-sources/modbus/includes/modbus_serial_adu.h
index ed3951f..308c722 100644
--- a/sandbox/plc4c/generated-sources/modbus/includes/modbus_serial_adu.h
+++ b/sandbox/plc4c/generated-sources/modbus/includes/modbus_serial_adu.h
@@ -28,7 +28,6 @@ extern "C" {
 #include "modbus_pdu.h"
 
 struct plc4c_modbus_read_write_modbus_serial_adu {
-  /* This is an abstract type so this property saves the type of this typed union */
   /* Properties */
   uint16_t transaction_id;
   uint16_t length;
diff --git a/sandbox/plc4c/generated-sources/modbus/includes/modbus_tcp_adu.h b/sandbox/plc4c/generated-sources/modbus/includes/modbus_tcp_adu.h
index 7f3222e..aa3ae1f 100644
--- a/sandbox/plc4c/generated-sources/modbus/includes/modbus_tcp_adu.h
+++ b/sandbox/plc4c/generated-sources/modbus/includes/modbus_tcp_adu.h
@@ -31,7 +31,6 @@ extern "C" {
 const uint16_t MODBUS_READ_WRITE_MODBUS_TCP_ADU_PROTOCOL_IDENTIFIER = 0x0000;
 
 struct plc4c_modbus_read_write_modbus_tcp_adu {
-  /* This is an abstract type so this property saves the type of this typed union */
   /* Properties */
   uint16_t transaction_identifier;
   uint16_t protocol_identifier;
diff --git a/sandbox/plc4c/generated-sources/modbus/src/modbus_constants.c b/sandbox/plc4c/generated-sources/modbus/src/modbus_constants.c
index 7bf422b..92b231e 100644
--- a/sandbox/plc4c/generated-sources/modbus/src/modbus_constants.c
+++ b/sandbox/plc4c/generated-sources/modbus/src/modbus_constants.c
@@ -30,7 +30,6 @@ plc4c_return_code plc4c_modbus_read_write_modbus_constants_parse(plc4c_spi_read_
 
   // Pointer to the parsed data structure.
   plc4c_modbus_read_write_modbus_constants* msg = malloc(sizeof(plc4c_modbus_read_write_modbus_constants));
-
   // Const Field (modbusTcpDefaultPort)
   uint16_t modbusTcpDefaultPort = plc4c_spi_read_unsigned_int(buf, 16);
   if(modbusTcpDefaultPort != MODBUS_READ_WRITE_MODBUS_CONSTANTS_MODBUS_TCP_DEFAULT_PORT) {
@@ -38,6 +37,7 @@ plc4c_return_code plc4c_modbus_read_write_modbus_constants_parse(plc4c_spi_read_
     // throw new ParseException("Expected constant value " + ModbusConstants.MODBUSTCPDEFAULTPORT + " but got " + modbusTcpDefaultPort);
   }
 
+
   return OK;
 }
 
diff --git a/sandbox/plc4c/generated-sources/modbus/src/modbus_pdu.c b/sandbox/plc4c/generated-sources/modbus/src/modbus_pdu.c
index f1fa992..6c88c36 100644
--- a/sandbox/plc4c/generated-sources/modbus/src/modbus_pdu.c
+++ b/sandbox/plc4c/generated-sources/modbus/src/modbus_pdu.c
@@ -113,7 +113,6 @@ plc4c_return_code plc4c_modbus_read_write_modbus_pdu_parse(plc4c_spi_read_buffer
 
   // Pointer to the parsed data structure.
   plc4c_modbus_read_write_modbus_pdu* msg = malloc(sizeof(plc4c_modbus_read_write_modbus_pdu));
-
   // Implicit Field (error) (Used for parsing, but it's value is not stored as it's implicitly given by the objects content)
   bool error = plc4c_spi_read_bit(buf);
 
@@ -334,6 +333,7 @@ plc4c_return_code plc4c_modbus_read_write_modbus_pdu_parse(plc4c_spi_read_buffer
   if((error == false) && (function == 0x2B) && (response == true)) { /* ModbusPDUReadDeviceIdentificationResponse */
   }
 
+
   return OK;
 }
 
diff --git a/sandbox/plc4c/generated-sources/modbus/src/modbus_pdu_read_file_record_request_item.c b/sandbox/plc4c/generated-sources/modbus/src/modbus_pdu_read_file_record_request_item.c
index dde8ef1..f32c60f 100644
--- a/sandbox/plc4c/generated-sources/modbus/src/modbus_pdu_read_file_record_request_item.c
+++ b/sandbox/plc4c/generated-sources/modbus/src/modbus_pdu_read_file_record_request_item.c
@@ -31,7 +31,6 @@ plc4c_return_code plc4c_modbus_read_write_modbus_pdu_read_file_record_request_it
   // Pointer to the parsed data structure.
   plc4c_modbus_read_write_modbus_pdu_read_file_record_request_item* msg = malloc(sizeof(plc4c_modbus_read_write_modbus_pdu_read_file_record_request_item));
 
-
   // Simple Field (referenceType)
   uint8_t referenceType = plc4c_spi_read_unsigned_short(buf, 8);
   msg->reference_type = referenceType;
@@ -48,6 +47,7 @@ plc4c_return_code plc4c_modbus_read_write_modbus_pdu_read_file_record_request_it
   uint16_t recordLength = plc4c_spi_read_unsigned_int(buf, 16);
   msg->record_length = recordLength;
 
+
   return OK;
 }
 
diff --git a/sandbox/plc4c/generated-sources/modbus/src/modbus_pdu_read_file_record_response_item.c b/sandbox/plc4c/generated-sources/modbus/src/modbus_pdu_read_file_record_response_item.c
index bb9f031..8424aeb 100644
--- a/sandbox/plc4c/generated-sources/modbus/src/modbus_pdu_read_file_record_response_item.c
+++ b/sandbox/plc4c/generated-sources/modbus/src/modbus_pdu_read_file_record_response_item.c
@@ -31,7 +31,6 @@ plc4c_return_code plc4c_modbus_read_write_modbus_pdu_read_file_record_response_i
   // Pointer to the parsed data structure.
   plc4c_modbus_read_write_modbus_pdu_read_file_record_response_item* msg = malloc(sizeof(plc4c_modbus_read_write_modbus_pdu_read_file_record_response_item));
 
-
   // Implicit Field (dataLength) (Used for parsing, but it's value is not stored as it's implicitly given by the objects content)
   uint8_t dataLength = plc4c_spi_read_unsigned_short(buf, 8);
 
@@ -39,6 +38,18 @@ plc4c_return_code plc4c_modbus_read_write_modbus_pdu_read_file_record_response_i
   uint8_t referenceType = plc4c_spi_read_unsigned_short(buf, 8);
   msg->reference_type = referenceType;
 
+  // Array field (data)
+  plc4c_list data;
+  {
+    // Length array
+    uint8_t _dataLength = (dataLength) - (1);
+    uint8_t dataEndPos = plc4c_spi_read_get_pos(buf) + _dataLength;
+    while(plc4c_spi_read_get_pos(buf) < dataEndPos) {
+      plc4c_utils_list_insert_head_value(&data, plc4c_spi_read_unsigned_int(buf, 16));
+    }
+  }
+
+
   return OK;
 }
 
diff --git a/sandbox/plc4c/generated-sources/modbus/src/modbus_pdu_write_file_record_request_item.c b/sandbox/plc4c/generated-sources/modbus/src/modbus_pdu_write_file_record_request_item.c
index 119d133..5fe4ade 100644
--- a/sandbox/plc4c/generated-sources/modbus/src/modbus_pdu_write_file_record_request_item.c
+++ b/sandbox/plc4c/generated-sources/modbus/src/modbus_pdu_write_file_record_request_item.c
@@ -31,7 +31,6 @@ plc4c_return_code plc4c_modbus_read_write_modbus_pdu_write_file_record_request_i
   // Pointer to the parsed data structure.
   plc4c_modbus_read_write_modbus_pdu_write_file_record_request_item* msg = malloc(sizeof(plc4c_modbus_read_write_modbus_pdu_write_file_record_request_item));
 
-
   // Simple Field (referenceType)
   uint8_t referenceType = plc4c_spi_read_unsigned_short(buf, 8);
   msg->reference_type = referenceType;
@@ -47,6 +46,18 @@ plc4c_return_code plc4c_modbus_read_write_modbus_pdu_write_file_record_request_i
   // Implicit Field (recordLength) (Used for parsing, but it's value is not stored as it's implicitly given by the objects content)
   uint16_t recordLength = plc4c_spi_read_unsigned_int(buf, 16);
 
+  // Array field (recordData)
+  plc4c_list recordData;
+  {
+    // Length array
+    uint8_t _recordDataLength = (recordLength) * (2);
+    uint8_t recordDataEndPos = plc4c_spi_read_get_pos(buf) + _recordDataLength;
+    while(plc4c_spi_read_get_pos(buf) < recordDataEndPos) {
+      plc4c_utils_list_insert_head_value(&recordData, plc4c_spi_read_unsigned_int(buf, 16));
+    }
+  }
+
+
   return OK;
 }
 
diff --git a/sandbox/plc4c/generated-sources/modbus/src/modbus_pdu_write_file_record_response_item.c b/sandbox/plc4c/generated-sources/modbus/src/modbus_pdu_write_file_record_response_item.c
index 2f7dd3a..e54baa6 100644
--- a/sandbox/plc4c/generated-sources/modbus/src/modbus_pdu_write_file_record_response_item.c
+++ b/sandbox/plc4c/generated-sources/modbus/src/modbus_pdu_write_file_record_response_item.c
@@ -31,7 +31,6 @@ plc4c_return_code plc4c_modbus_read_write_modbus_pdu_write_file_record_response_
   // Pointer to the parsed data structure.
   plc4c_modbus_read_write_modbus_pdu_write_file_record_response_item* msg = malloc(sizeof(plc4c_modbus_read_write_modbus_pdu_write_file_record_response_item));
 
-
   // Simple Field (referenceType)
   uint8_t referenceType = plc4c_spi_read_unsigned_short(buf, 8);
   msg->reference_type = referenceType;
@@ -47,6 +46,18 @@ plc4c_return_code plc4c_modbus_read_write_modbus_pdu_write_file_record_response_
   // Implicit Field (recordLength) (Used for parsing, but it's value is not stored as it's implicitly given by the objects content)
   uint16_t recordLength = plc4c_spi_read_unsigned_int(buf, 16);
 
+  // Array field (recordData)
+  plc4c_list recordData;
+  {
+    // Length array
+    uint8_t _recordDataLength = (recordLength) * (2);
+    uint8_t recordDataEndPos = plc4c_spi_read_get_pos(buf) + _recordDataLength;
+    while(plc4c_spi_read_get_pos(buf) < recordDataEndPos) {
+      plc4c_utils_list_insert_head_value(&recordData, plc4c_spi_read_unsigned_int(buf, 16));
+    }
+  }
+
+
   return OK;
 }
 
diff --git a/sandbox/plc4c/generated-sources/modbus/src/modbus_serial_adu.c b/sandbox/plc4c/generated-sources/modbus/src/modbus_serial_adu.c
index 5445050..8083611 100644
--- a/sandbox/plc4c/generated-sources/modbus/src/modbus_serial_adu.c
+++ b/sandbox/plc4c/generated-sources/modbus/src/modbus_serial_adu.c
@@ -31,7 +31,6 @@ plc4c_return_code plc4c_modbus_read_write_modbus_serial_adu_parse(plc4c_spi_read
   // Pointer to the parsed data structure.
   plc4c_modbus_read_write_modbus_serial_adu* msg = malloc(sizeof(plc4c_modbus_read_write_modbus_serial_adu));
 
-
   // Simple Field (transactionId)
   uint16_t transactionId = plc4c_spi_read_unsigned_int(buf, 16);
   msg->transaction_id = transactionId;
@@ -57,6 +56,7 @@ plc4c_return_code plc4c_modbus_read_write_modbus_serial_adu_parse(plc4c_spi_read
   plc4c_modbus_read_write_modbus_pdu_parse(buf, response, (void*) &pdu);
   msg->pdu = pdu;
 
+
   return OK;
 }
 
diff --git a/sandbox/plc4c/generated-sources/modbus/src/modbus_tcp_adu.c b/sandbox/plc4c/generated-sources/modbus/src/modbus_tcp_adu.c
index 2f1f058..314a825 100644
--- a/sandbox/plc4c/generated-sources/modbus/src/modbus_tcp_adu.c
+++ b/sandbox/plc4c/generated-sources/modbus/src/modbus_tcp_adu.c
@@ -31,7 +31,6 @@ plc4c_return_code plc4c_modbus_read_write_modbus_tcp_adu_parse(plc4c_spi_read_bu
   // Pointer to the parsed data structure.
   plc4c_modbus_read_write_modbus_tcp_adu* msg = malloc(sizeof(plc4c_modbus_read_write_modbus_tcp_adu));
 
-
   // Simple Field (transactionIdentifier)
   uint16_t transactionIdentifier = plc4c_spi_read_unsigned_int(buf, 16);
   msg->transaction_identifier = transactionIdentifier;
@@ -55,6 +54,7 @@ plc4c_return_code plc4c_modbus_read_write_modbus_tcp_adu_parse(plc4c_spi_read_bu
   plc4c_modbus_read_write_modbus_pdu_parse(buf, response, (void*) &pdu);
   msg->pdu = pdu;
 
+
   return OK;
 }
 
diff --git a/sandbox/plc4c/generated-sources/s7/includes/cotp_packet.h b/sandbox/plc4c/generated-sources/s7/includes/cotp_packet.h
index 7708c24..5669cec 100644
--- a/sandbox/plc4c/generated-sources/s7/includes/cotp_packet.h
+++ b/sandbox/plc4c/generated-sources/s7/includes/cotp_packet.h
@@ -25,9 +25,17 @@ extern "C" {
 #include <stdbool.h>
 #include <stdint.h>
 #include <plc4c/utils/list.h>
+#include "cotp_packet.h"
+#include "cotp_packet.h"
+#include "cotp_packet.h"
 #include "cotp_parameter.h"
 #include "cotp_protocol_class.h"
+#include "cotp_protocol_class.h"
+#include "cotp_protocol_class.h"
 #include "s7_message.h"
+#include "cotp_packet.h"
+#include "cotp_packet.h"
+#include "cotp_packet.h"
 
 // Structure used to contain the discriminator values for discriminated types using this as a parent
 struct plc4c_s7_read_write_cotp_packet_discriminator {
diff --git a/sandbox/plc4c/generated-sources/s7/includes/cotp_parameter.h b/sandbox/plc4c/generated-sources/s7/includes/cotp_parameter.h
index 86ed288..9e086aa 100644
--- a/sandbox/plc4c/generated-sources/s7/includes/cotp_parameter.h
+++ b/sandbox/plc4c/generated-sources/s7/includes/cotp_parameter.h
@@ -26,6 +26,11 @@ extern "C" {
 #include <stdint.h>
 #include <plc4c/utils/list.h>
 #include "cotp_tpdu_size.h"
+#include "cotp_parameter.h"
+#include "cotp_parameter.h"
+#include "cotp_parameter.h"
+#include "cotp_parameter.h"
+#include "cotp_parameter.h"
 
 // Structure used to contain the discriminator values for discriminated types using this as a parent
 struct plc4c_s7_read_write_cotp_parameter_discriminator {
diff --git a/sandbox/plc4c/generated-sources/s7/includes/s7_address.h b/sandbox/plc4c/generated-sources/s7/includes/s7_address.h
index 96b1e4b..bcd2f29 100644
--- a/sandbox/plc4c/generated-sources/s7/includes/s7_address.h
+++ b/sandbox/plc4c/generated-sources/s7/includes/s7_address.h
@@ -25,8 +25,9 @@ extern "C" {
 #include <stdbool.h>
 #include <stdint.h>
 #include <plc4c/utils/list.h>
-#include "memory_area.h"
+#include "s7_address.h"
 #include "transport_size.h"
+#include "memory_area.h"
 
 // Structure used to contain the discriminator values for discriminated types using this as a parent
 struct plc4c_s7_read_write_s7_address_discriminator {
diff --git a/sandbox/plc4c/generated-sources/s7/includes/s7_message.h b/sandbox/plc4c/generated-sources/s7/includes/s7_message.h
index 0ba9ee6..a22beaf 100644
--- a/sandbox/plc4c/generated-sources/s7/includes/s7_message.h
+++ b/sandbox/plc4c/generated-sources/s7/includes/s7_message.h
@@ -25,8 +25,12 @@ extern "C" {
 #include <stdbool.h>
 #include <stdint.h>
 #include <plc4c/utils/list.h>
-#include "s7_parameter.h"
 #include "s7_payload.h"
+#include "s7_message.h"
+#include "s7_message.h"
+#include "s7_message.h"
+#include "s7_message.h"
+#include "s7_parameter.h"
 
 // Structure used to contain the discriminator values for discriminated types using this as a parent
 struct plc4c_s7_read_write_s7_message_discriminator {
diff --git a/sandbox/plc4c/generated-sources/s7/includes/s7_parameter.h b/sandbox/plc4c/generated-sources/s7/includes/s7_parameter.h
index b6c87eb..c51996e 100644
--- a/sandbox/plc4c/generated-sources/s7/includes/s7_parameter.h
+++ b/sandbox/plc4c/generated-sources/s7/includes/s7_parameter.h
@@ -25,8 +25,15 @@ extern "C" {
 #include <stdbool.h>
 #include <stdint.h>
 #include <plc4c/utils/list.h>
-#include "s7_parameter_user_data_item.h"
 #include "s7_var_request_parameter_item.h"
+#include "s7_parameter.h"
+#include "s7_parameter.h"
+#include "s7_parameter.h"
+#include "s7_var_request_parameter_item.h"
+#include "s7_parameter.h"
+#include "s7_parameter.h"
+#include "s7_parameter_user_data_item.h"
+#include "s7_parameter.h"
 
 // Structure used to contain the discriminator values for discriminated types using this as a parent
 struct plc4c_s7_read_write_s7_parameter_discriminator {
diff --git a/sandbox/plc4c/generated-sources/s7/includes/s7_parameter_user_data_item.h b/sandbox/plc4c/generated-sources/s7/includes/s7_parameter_user_data_item.h
index 5f3679d..9fbbf91 100644
--- a/sandbox/plc4c/generated-sources/s7/includes/s7_parameter_user_data_item.h
+++ b/sandbox/plc4c/generated-sources/s7/includes/s7_parameter_user_data_item.h
@@ -25,6 +25,7 @@ extern "C" {
 #include <stdbool.h>
 #include <stdint.h>
 #include <plc4c/utils/list.h>
+#include "s7_parameter_user_data_item.h"
 
 // Structure used to contain the discriminator values for discriminated types using this as a parent
 struct plc4c_s7_read_write_s7_parameter_user_data_item_discriminator {
diff --git a/sandbox/plc4c/generated-sources/s7/includes/s7_payload.h b/sandbox/plc4c/generated-sources/s7/includes/s7_payload.h
index b364c99..c059e75 100644
--- a/sandbox/plc4c/generated-sources/s7/includes/s7_payload.h
+++ b/sandbox/plc4c/generated-sources/s7/includes/s7_payload.h
@@ -26,9 +26,18 @@ extern "C" {
 #include <stdint.h>
 #include <plc4c/utils/list.h>
 #include "s7_parameter.h"
-#include "s7_payload_user_data_item.h"
+#include "s7_parameter.h"
+#include "s7_parameter.h"
 #include "s7_var_payload_data_item.h"
+#include "s7_payload.h"
+#include "s7_parameter.h"
+#include "s7_payload.h"
+#include "s7_parameter.h"
+#include "s7_var_payload_data_item.h"
+#include "s7_payload_user_data_item.h"
 #include "s7_var_payload_status_item.h"
+#include "s7_payload.h"
+#include "s7_payload.h"
 
 // Structure used to contain the discriminator values for discriminated types using this as a parent
 struct plc4c_s7_read_write_s7_payload_discriminator {
diff --git a/sandbox/plc4c/generated-sources/s7/includes/s7_payload_user_data_item.h b/sandbox/plc4c/generated-sources/s7/includes/s7_payload_user_data_item.h
index 67a035e..fe22481 100644
--- a/sandbox/plc4c/generated-sources/s7/includes/s7_payload_user_data_item.h
+++ b/sandbox/plc4c/generated-sources/s7/includes/s7_payload_user_data_item.h
@@ -25,10 +25,12 @@ extern "C" {
 #include <stdbool.h>
 #include <stdint.h>
 #include <plc4c/utils/list.h>
+#include "szl_id.h"
 #include "data_transport_error_code.h"
-#include "data_transport_size.h"
+#include "s7_payload_user_data_item.h"
 #include "szl_data_tree_item.h"
-#include "szl_id.h"
+#include "s7_payload_user_data_item.h"
+#include "data_transport_size.h"
 
 // Structure used to contain the discriminator values for discriminated types using this as a parent
 struct plc4c_s7_read_write_s7_payload_user_data_item_discriminator {
diff --git a/sandbox/plc4c/generated-sources/s7/includes/s7_var_payload_data_item.h b/sandbox/plc4c/generated-sources/s7/includes/s7_var_payload_data_item.h
index fa37aee..1e8d765 100644
--- a/sandbox/plc4c/generated-sources/s7/includes/s7_var_payload_data_item.h
+++ b/sandbox/plc4c/generated-sources/s7/includes/s7_var_payload_data_item.h
@@ -25,11 +25,10 @@ extern "C" {
 #include <stdbool.h>
 #include <stdint.h>
 #include <plc4c/utils/list.h>
-#include "data_transport_error_code.h"
 #include "data_transport_size.h"
+#include "data_transport_error_code.h"
 
 struct plc4c_s7_read_write_s7_var_payload_data_item {
-  /* This is an abstract type so this property saves the type of this typed union */
   /* Properties */
   plc4c_s7_read_write_data_transport_error_code return_code;
   plc4c_s7_read_write_data_transport_size transport_size;
diff --git a/sandbox/plc4c/generated-sources/s7/includes/s7_var_payload_status_item.h b/sandbox/plc4c/generated-sources/s7/includes/s7_var_payload_status_item.h
index 196e2b5..500f464 100644
--- a/sandbox/plc4c/generated-sources/s7/includes/s7_var_payload_status_item.h
+++ b/sandbox/plc4c/generated-sources/s7/includes/s7_var_payload_status_item.h
@@ -28,7 +28,6 @@ extern "C" {
 #include "data_transport_error_code.h"
 
 struct plc4c_s7_read_write_s7_var_payload_status_item {
-  /* This is an abstract type so this property saves the type of this typed union */
   /* Properties */
   plc4c_s7_read_write_data_transport_error_code return_code;
 };
diff --git a/sandbox/plc4c/generated-sources/s7/includes/s7_var_request_parameter_item.h b/sandbox/plc4c/generated-sources/s7/includes/s7_var_request_parameter_item.h
index 85ef4a2..eb442d3 100644
--- a/sandbox/plc4c/generated-sources/s7/includes/s7_var_request_parameter_item.h
+++ b/sandbox/plc4c/generated-sources/s7/includes/s7_var_request_parameter_item.h
@@ -26,6 +26,7 @@ extern "C" {
 #include <stdint.h>
 #include <plc4c/utils/list.h>
 #include "s7_address.h"
+#include "s7_var_request_parameter_item.h"
 
 // Structure used to contain the discriminator values for discriminated types using this as a parent
 struct plc4c_s7_read_write_s7_var_request_parameter_item_discriminator {
diff --git a/sandbox/plc4c/generated-sources/s7/includes/szl_data_tree_item.h b/sandbox/plc4c/generated-sources/s7/includes/szl_data_tree_item.h
index 1b9480a..65a0922 100644
--- a/sandbox/plc4c/generated-sources/s7/includes/szl_data_tree_item.h
+++ b/sandbox/plc4c/generated-sources/s7/includes/szl_data_tree_item.h
@@ -27,7 +27,6 @@ extern "C" {
 #include <plc4c/utils/list.h>
 
 struct plc4c_s7_read_write_szl_data_tree_item {
-  /* This is an abstract type so this property saves the type of this typed union */
   /* Properties */
   uint16_t item_index;
   int8_t mlfb[20];
diff --git a/sandbox/plc4c/generated-sources/s7/includes/szl_id.h b/sandbox/plc4c/generated-sources/s7/includes/szl_id.h
index 544460f..8ca6e44 100644
--- a/sandbox/plc4c/generated-sources/s7/includes/szl_id.h
+++ b/sandbox/plc4c/generated-sources/s7/includes/szl_id.h
@@ -29,7 +29,6 @@ extern "C" {
 #include "szl_sublist.h"
 
 struct plc4c_s7_read_write_szl_id {
-  /* This is an abstract type so this property saves the type of this typed union */
   /* Properties */
   plc4c_s7_read_write_szl_module_type_class type_class;
   unsigned int sublist_extract : 4;
diff --git a/sandbox/plc4c/generated-sources/s7/includes/tpkt_packet.h b/sandbox/plc4c/generated-sources/s7/includes/tpkt_packet.h
index 43501e3..1774b50 100644
--- a/sandbox/plc4c/generated-sources/s7/includes/tpkt_packet.h
+++ b/sandbox/plc4c/generated-sources/s7/includes/tpkt_packet.h
@@ -31,7 +31,6 @@ extern "C" {
 const uint8_t S7_READ_WRITE_TPKT_PACKET_PROTOCOL_ID = 0x03;
 
 struct plc4c_s7_read_write_tpkt_packet {
-  /* This is an abstract type so this property saves the type of this typed union */
   /* Properties */
   uint8_t protocol_id;
   plc4c_s7_read_write_cotp_packet* payload;
diff --git a/sandbox/plc4c/generated-sources/s7/includes/transport_size.h b/sandbox/plc4c/generated-sources/s7/includes/transport_size.h
index 9850c8b..044b4ef 100644
--- a/sandbox/plc4c/generated-sources/s7/includes/transport_size.h
+++ b/sandbox/plc4c/generated-sources/s7/includes/transport_size.h
@@ -24,8 +24,8 @@ extern "C" {
 #endif
 
 #include <stdbool.h>
-#include "data_transport_size.h"
 #include "transport_size.h"
+#include "data_transport_size.h"
 
 enum plc4c_s7_read_write_transport_size {
   plc4c_s7_read_write_transport_size_BOOL = 0x01,
diff --git a/sandbox/plc4c/generated-sources/s7/src/cotp_packet.c b/sandbox/plc4c/generated-sources/s7/src/cotp_packet.c
index d5b88c8..9e9630d 100644
--- a/sandbox/plc4c/generated-sources/s7/src/cotp_packet.c
+++ b/sandbox/plc4c/generated-sources/s7/src/cotp_packet.c
@@ -54,7 +54,6 @@ plc4c_return_code plc4c_s7_read_write_cotp_packet_parse(plc4c_spi_read_buffer* b
   // Pointer to the parsed data structure.
   plc4c_s7_read_write_cotp_packet* msg = malloc(sizeof(plc4c_s7_read_write_cotp_packet));
 
-
   // Implicit Field (headerLength) (Used for parsing, but it's value is not stored as it's implicitly given by the objects content)
   uint8_t headerLength = plc4c_spi_read_unsigned_short(buf, 8);
 
@@ -114,6 +113,19 @@ plc4c_return_code plc4c_s7_read_write_cotp_packet_parse(plc4c_spi_read_buffer* b
     msg->cotp_packet_tpdu_error_reject_cause = rejectCause;
   }
 
+  // Array field (parameters)
+  curPos = plc4c_spi_read_get_pos(buf) - startPos;
+  plc4c_list parameters;
+  {
+    // Length array
+    uint8_t _parametersLength = (((headerLength) + (1))) - (curPos);
+    uint8_t parametersEndPos = plc4c_spi_read_get_pos(buf) + _parametersLength;
+    while(plc4c_spi_read_get_pos(buf) < parametersEndPos) {
+      plc4c_utils_list_insert_head_value(&parameters, plc4c_s7_read_write_cotp_parameter_parse(buf, (((headerLength) + (1))) - (curPos), (void*) &parameters));
+      curPos = plc4c_spi_read_get_pos(buf) - startPos;
+    }
+  }
+
   // Optional Field (payload) (Can be skipped, if a given expression evaluates to false)
   curPos = plc4c_spi_read_get_pos(buf) - startPos;
   plc4c_s7_read_write_s7_message* payload = NULL;
@@ -123,6 +135,7 @@ plc4c_return_code plc4c_s7_read_write_cotp_packet_parse(plc4c_spi_read_buffer* b
     msg->payload = payload;
   }
 
+
   return OK;
 }
 
diff --git a/sandbox/plc4c/generated-sources/s7/src/cotp_parameter.c b/sandbox/plc4c/generated-sources/s7/src/cotp_parameter.c
index 50bc779..7a3f295 100644
--- a/sandbox/plc4c/generated-sources/s7/src/cotp_parameter.c
+++ b/sandbox/plc4c/generated-sources/s7/src/cotp_parameter.c
@@ -51,7 +51,6 @@ plc4c_return_code plc4c_s7_read_write_cotp_parameter_parse(plc4c_spi_read_buffer
 
   // Pointer to the parsed data structure.
   plc4c_s7_read_write_cotp_parameter* msg = malloc(sizeof(plc4c_s7_read_write_cotp_parameter));
-
   // Discriminator Field (parameterType) (Used as input to a switch field)
   uint8_t parameterType = plc4c_spi_read_unsigned_short(buf, 8);
 
@@ -80,6 +79,7 @@ plc4c_return_code plc4c_s7_read_write_cotp_parameter_parse(plc4c_spi_read_buffer
     msg->cotp_parameter_disconnect_additional_information_data = data;
   }
 
+
   return OK;
 }
 
diff --git a/sandbox/plc4c/generated-sources/s7/src/s7_address.c b/sandbox/plc4c/generated-sources/s7/src/s7_address.c
index 9b2967e..26b02c4 100644
--- a/sandbox/plc4c/generated-sources/s7/src/s7_address.c
+++ b/sandbox/plc4c/generated-sources/s7/src/s7_address.c
@@ -43,7 +43,6 @@ plc4c_return_code plc4c_s7_read_write_s7_address_parse(plc4c_spi_read_buffer* bu
 
   // Pointer to the parsed data structure.
   plc4c_s7_read_write_s7_address* msg = malloc(sizeof(plc4c_s7_read_write_s7_address));
-
   // Discriminator Field (addressType) (Used as input to a switch field)
   uint8_t addressType = plc4c_spi_read_unsigned_short(buf, 8);
 
@@ -68,6 +67,7 @@ plc4c_return_code plc4c_s7_read_write_s7_address_parse(plc4c_spi_read_buffer* bu
     msg->s7_address_any_bit_address = bitAddress;
   }
 
+
   return OK;
 }
 
diff --git a/sandbox/plc4c/generated-sources/s7/src/s7_message.c b/sandbox/plc4c/generated-sources/s7/src/s7_message.c
index 31e9454..40a6095 100644
--- a/sandbox/plc4c/generated-sources/s7/src/s7_message.c
+++ b/sandbox/plc4c/generated-sources/s7/src/s7_message.c
@@ -50,7 +50,6 @@ plc4c_return_code plc4c_s7_read_write_s7_message_parse(plc4c_spi_read_buffer* bu
   // Pointer to the parsed data structure.
   plc4c_s7_read_write_s7_message* msg = malloc(sizeof(plc4c_s7_read_write_s7_message));
 
-
   // Const Field (protocolId)
   uint8_t protocolId = plc4c_spi_read_unsigned_short(buf, 8);
   if(protocolId != S7_READ_WRITE_S7_MESSAGE_PROTOCOL_ID) {
@@ -115,6 +114,7 @@ plc4c_return_code plc4c_s7_read_write_s7_message_parse(plc4c_spi_read_buffer* bu
     msg->payload = payload;
   }
 
+
   return OK;
 }
 
diff --git a/sandbox/plc4c/generated-sources/s7/src/s7_parameter.c b/sandbox/plc4c/generated-sources/s7/src/s7_parameter.c
index 1a092a3..88bfae7 100644
--- a/sandbox/plc4c/generated-sources/s7/src/s7_parameter.c
+++ b/sandbox/plc4c/generated-sources/s7/src/s7_parameter.c
@@ -53,7 +53,6 @@ plc4c_return_code plc4c_s7_read_write_s7_parameter_parse(plc4c_spi_read_buffer*
 
   // Pointer to the parsed data structure.
   plc4c_s7_read_write_s7_parameter* msg = malloc(sizeof(plc4c_s7_read_write_s7_parameter));
-
   // Discriminator Field (parameterType) (Used as input to a switch field)
   uint8_t parameterType = plc4c_spi_read_unsigned_short(buf, 8);
 
@@ -89,6 +88,7 @@ plc4c_return_code plc4c_s7_read_write_s7_parameter_parse(plc4c_spi_read_buffer*
     msg->s7_parameter_user_data_items = items;
   }
 
+
   return OK;
 }
 
diff --git a/sandbox/plc4c/generated-sources/s7/src/s7_parameter_user_data_item.c b/sandbox/plc4c/generated-sources/s7/src/s7_parameter_user_data_item.c
index b6fad93..34b5f53 100644
--- a/sandbox/plc4c/generated-sources/s7/src/s7_parameter_user_data_item.c
+++ b/sandbox/plc4c/generated-sources/s7/src/s7_parameter_user_data_item.c
@@ -43,7 +43,6 @@ plc4c_return_code plc4c_s7_read_write_s7_parameter_user_data_item_parse(plc4c_sp
 
   // Pointer to the parsed data structure.
   plc4c_s7_read_write_s7_parameter_user_data_item* msg = malloc(sizeof(plc4c_s7_read_write_s7_parameter_user_data_item));
-
   // Discriminator Field (itemType) (Used as input to a switch field)
   uint8_t itemType = plc4c_spi_read_unsigned_short(buf, 8);
 
@@ -74,6 +73,7 @@ plc4c_return_code plc4c_s7_read_write_s7_parameter_user_data_item_parse(plc4c_sp
     msg->s7_parameter_user_data_item_cpu_functions_error_code = errorCode;
   }
 
+
   return OK;
 }
 
diff --git a/sandbox/plc4c/generated-sources/s7/src/s7_payload.c b/sandbox/plc4c/generated-sources/s7/src/s7_payload.c
index 6bc5df8..1faf88d 100644
--- a/sandbox/plc4c/generated-sources/s7/src/s7_payload.c
+++ b/sandbox/plc4c/generated-sources/s7/src/s7_payload.c
@@ -49,7 +49,6 @@ plc4c_return_code plc4c_s7_read_write_s7_payload_parse(plc4c_spi_read_buffer* bu
 
   // Pointer to the parsed data structure.
   plc4c_s7_read_write_s7_payload* msg = malloc(sizeof(plc4c_s7_read_write_s7_payload));
-
   // Switch Field (Depending on the discriminator values, passes the instantiation to a sub-type)
   if((plc4c_s7_read_write_s7_parameter_get_discriminator(parameter->_type).parameterType == 0x04) && (messageType == 0x03)) { /* S7PayloadReadVarResponse */
     plc4c_list* items;
@@ -68,6 +67,7 @@ plc4c_return_code plc4c_s7_read_write_s7_payload_parse(plc4c_spi_read_buffer* bu
     msg->s7_payload_user_data_items = items;
   }
 
+
   return OK;
 }
 
diff --git a/sandbox/plc4c/generated-sources/s7/src/s7_payload_user_data_item.c b/sandbox/plc4c/generated-sources/s7/src/s7_payload_user_data_item.c
index 06e2cc5..885a661 100644
--- a/sandbox/plc4c/generated-sources/s7/src/s7_payload_user_data_item.c
+++ b/sandbox/plc4c/generated-sources/s7/src/s7_payload_user_data_item.c
@@ -46,7 +46,6 @@ plc4c_return_code plc4c_s7_read_write_s7_payload_user_data_item_parse(plc4c_spi_
   // Pointer to the parsed data structure.
   plc4c_s7_read_write_s7_payload_user_data_item* msg = malloc(sizeof(plc4c_s7_read_write_s7_payload_user_data_item));
 
-
   // Enum field (returnCode)
   plc4c_s7_read_write_data_transport_error_code returnCode = plc4c_spi_read_byte(buf, 8);
   msg->return_code = returnCode;
@@ -75,6 +74,7 @@ plc4c_return_code plc4c_s7_read_write_s7_payload_user_data_item_parse(plc4c_spi_
     msg->s7_payload_user_data_item_cpu_function_read_szl_response_items = items;
   }
 
+
   return OK;
 }
 
diff --git a/sandbox/plc4c/generated-sources/s7/src/s7_var_payload_data_item.c b/sandbox/plc4c/generated-sources/s7/src/s7_var_payload_data_item.c
index 63d594d..105a0e5 100644
--- a/sandbox/plc4c/generated-sources/s7/src/s7_var_payload_data_item.c
+++ b/sandbox/plc4c/generated-sources/s7/src/s7_var_payload_data_item.c
@@ -31,7 +31,6 @@ plc4c_return_code plc4c_s7_read_write_s7_var_payload_data_item_parse(plc4c_spi_r
   // Pointer to the parsed data structure.
   plc4c_s7_read_write_s7_var_payload_data_item* msg = malloc(sizeof(plc4c_s7_read_write_s7_var_payload_data_item));
 
-
   // Enum field (returnCode)
   plc4c_s7_read_write_data_transport_error_code returnCode = plc4c_spi_read_byte(buf, 8);
   msg->return_code = returnCode;
@@ -44,13 +43,26 @@ plc4c_return_code plc4c_s7_read_write_s7_var_payload_data_item_parse(plc4c_spi_r
   uint16_t dataLength = plc4c_spi_read_unsigned_int(buf, 16);
   msg->data_length = dataLength;
 
+  // Array field (data)
+  plc4c_list data;
+  {
+    // Count array
+    uint8_t itemCount = ((plc4c_s7_read_write_data_transport_size_get_size_in_bits) ? plc4c_spi_evaluation_helper_ceil((dataLength) / (8.0)) : dataLength);
+    for(int curItem = 0; curItem < itemCount; curItem++) {
+      
+      int8_t value = plc4c_spi_read_byte(buf, 8);
+      plc4c_utils_list_insert_head_value(&data, &value);
+    }
+  }
+
   // Padding Field (pad)
-  bool _padNeedsPadding = (bool) ((plc4c_spi_read_has_more(buf, 8)) && ((!(lastItem)) && (((((plc4c_utils_list_size(&data)) % (2))) == (1)))));
+  bool _padNeedsPadding = (bool) ((plc4c_spi_read_has_more(buf, 8)) && ((!(lastItem)) && (((((plc4c_spi_evaluation_helper_count(data)) % (2))) == (1)))));
   if(_padNeedsPadding) {
     // Just read the padding data and ignore it
     plc4c_spi_read_unsigned_short(buf, 8);
   }
 
+
   return OK;
 }
 
diff --git a/sandbox/plc4c/generated-sources/s7/src/s7_var_payload_status_item.c b/sandbox/plc4c/generated-sources/s7/src/s7_var_payload_status_item.c
index ae8ca78..11f34d3 100644
--- a/sandbox/plc4c/generated-sources/s7/src/s7_var_payload_status_item.c
+++ b/sandbox/plc4c/generated-sources/s7/src/s7_var_payload_status_item.c
@@ -31,11 +31,11 @@ plc4c_return_code plc4c_s7_read_write_s7_var_payload_status_item_parse(plc4c_spi
   // Pointer to the parsed data structure.
   plc4c_s7_read_write_s7_var_payload_status_item* msg = malloc(sizeof(plc4c_s7_read_write_s7_var_payload_status_item));
 
-
   // Enum field (returnCode)
   plc4c_s7_read_write_data_transport_error_code returnCode = plc4c_spi_read_byte(buf, 8);
   msg->return_code = returnCode;
 
+
   return OK;
 }
 
diff --git a/sandbox/plc4c/generated-sources/s7/src/s7_var_request_parameter_item.c b/sandbox/plc4c/generated-sources/s7/src/s7_var_request_parameter_item.c
index c50fbd6..6a2cc50 100644
--- a/sandbox/plc4c/generated-sources/s7/src/s7_var_request_parameter_item.c
+++ b/sandbox/plc4c/generated-sources/s7/src/s7_var_request_parameter_item.c
@@ -43,7 +43,6 @@ plc4c_return_code plc4c_s7_read_write_s7_var_request_parameter_item_parse(plc4c_
 
   // Pointer to the parsed data structure.
   plc4c_s7_read_write_s7_var_request_parameter_item* msg = malloc(sizeof(plc4c_s7_read_write_s7_var_request_parameter_item));
-
   // Discriminator Field (itemType) (Used as input to a switch field)
   uint8_t itemType = plc4c_spi_read_unsigned_short(buf, 8);
 
@@ -53,6 +52,7 @@ plc4c_return_code plc4c_s7_read_write_s7_var_request_parameter_item_parse(plc4c_
     msg->s7_var_request_parameter_item_address_address = address;
   }
 
+
   return OK;
 }
 
diff --git a/sandbox/plc4c/generated-sources/s7/src/szl_data_tree_item.c b/sandbox/plc4c/generated-sources/s7/src/szl_data_tree_item.c
index b6b86b3..d5b9c23 100644
--- a/sandbox/plc4c/generated-sources/s7/src/szl_data_tree_item.c
+++ b/sandbox/plc4c/generated-sources/s7/src/szl_data_tree_item.c
@@ -31,11 +31,22 @@ plc4c_return_code plc4c_s7_read_write_szl_data_tree_item_parse(plc4c_spi_read_bu
   // Pointer to the parsed data structure.
   plc4c_s7_read_write_szl_data_tree_item* msg = malloc(sizeof(plc4c_s7_read_write_szl_data_tree_item));
 
-
   // Simple Field (itemIndex)
   uint16_t itemIndex = plc4c_spi_read_unsigned_int(buf, 16);
   msg->item_index = itemIndex;
 
+  // Array field (mlfb)
+  plc4c_list mlfb;
+  {
+    // Count array
+    uint8_t itemCount = 20;
+    for(int curItem = 0; curItem < itemCount; curItem++) {
+      
+      int8_t value = plc4c_spi_read_byte(buf, 8);
+      plc4c_utils_list_insert_head_value(&mlfb, &value);
+    }
+  }
+
   // Simple Field (moduleTypeId)
   uint16_t moduleTypeId = plc4c_spi_read_unsigned_int(buf, 16);
   msg->module_type_id = moduleTypeId;
@@ -48,6 +59,7 @@ plc4c_return_code plc4c_s7_read_write_szl_data_tree_item_parse(plc4c_spi_read_bu
   uint16_t ausbe = plc4c_spi_read_unsigned_int(buf, 16);
   msg->ausbe = ausbe;
 
+
   return OK;
 }
 
diff --git a/sandbox/plc4c/generated-sources/s7/src/szl_id.c b/sandbox/plc4c/generated-sources/s7/src/szl_id.c
index 87edb3e..7ab2f80 100644
--- a/sandbox/plc4c/generated-sources/s7/src/szl_id.c
+++ b/sandbox/plc4c/generated-sources/s7/src/szl_id.c
@@ -31,7 +31,6 @@ plc4c_return_code plc4c_s7_read_write_szl_id_parse(plc4c_spi_read_buffer* buf, p
   // Pointer to the parsed data structure.
   plc4c_s7_read_write_szl_id* msg = malloc(sizeof(plc4c_s7_read_write_szl_id));
 
-
   // Enum field (typeClass)
   plc4c_s7_read_write_szl_module_type_class typeClass = plc4c_spi_read_byte(buf, 4);
   msg->type_class = typeClass;
@@ -44,6 +43,7 @@ plc4c_return_code plc4c_s7_read_write_szl_id_parse(plc4c_spi_read_buffer* buf, p
   plc4c_s7_read_write_szl_sublist sublistList = plc4c_spi_read_byte(buf, 8);
   msg->sublist_list = sublistList;
 
+
   return OK;
 }
 
diff --git a/sandbox/plc4c/generated-sources/s7/src/tpkt_packet.c b/sandbox/plc4c/generated-sources/s7/src/tpkt_packet.c
index d939c0f..656b44b 100644
--- a/sandbox/plc4c/generated-sources/s7/src/tpkt_packet.c
+++ b/sandbox/plc4c/generated-sources/s7/src/tpkt_packet.c
@@ -31,7 +31,6 @@ plc4c_return_code plc4c_s7_read_write_tpkt_packet_parse(plc4c_spi_read_buffer* b
   // Pointer to the parsed data structure.
   plc4c_s7_read_write_tpkt_packet* msg = malloc(sizeof(plc4c_s7_read_write_tpkt_packet));
 
-
   // Const Field (protocolId)
   uint8_t protocolId = plc4c_spi_read_unsigned_short(buf, 8);
   if(protocolId != S7_READ_WRITE_TPKT_PACKET_PROTOCOL_ID) {
@@ -55,6 +54,7 @@ plc4c_return_code plc4c_s7_read_write_tpkt_packet_parse(plc4c_spi_read_buffer* b
   plc4c_s7_read_write_cotp_packet_parse(buf, (len) - (4), (void*) &payload);
   msg->payload = payload;
 
+
   return OK;
 }
 
diff --git a/sandbox/plc4c/spi/include/plc4c/spi/evaluation_helper.h b/sandbox/plc4c/spi/include/plc4c/spi/evaluation_helper.h
index 41fc1a1..32a6d2c 100644
--- a/sandbox/plc4c/spi/include/plc4c/spi/evaluation_helper.h
+++ b/sandbox/plc4c/spi/include/plc4c/spi/evaluation_helper.h
@@ -19,8 +19,14 @@
 #ifndef PLC4C_SPI_EVALUATION_HELPER_H_
 #define PLC4C_SPI_EVALUATION_HELPER_H_
 
+#include <stdint.h>
 #include <stdbool.h>
+#include <plc4c/utils/list.h>
 
 bool plc4c_spi_evaluation_helper_equals(int a, int b);
 
+double plc4c_spi_evaluation_helper_ceil(double a);
+
+uint8_t plc4c_spi_evaluation_helper_count(plc4c_list a);
+
 #endif  // PLC4C_SPI_EVALUATION_HELPER_H_
diff --git a/sandbox/plc4c/spi/src/evaluation_helper.c b/sandbox/plc4c/spi/src/evaluation_helper.c
index 36d320c..9be479f 100644
--- a/sandbox/plc4c/spi/src/evaluation_helper.c
+++ b/sandbox/plc4c/spi/src/evaluation_helper.c
@@ -20,8 +20,17 @@
 #include <plc4c/spi/evaluation_helper.h>
 
 #include <stdbool.h>
+#include <math.h>
 
 bool plc4c_spi_evaluation_helper_equals(int a, int b) {
   return a == b;
 }
 
+double plc4c_spi_evaluation_helper_ceil(double a) {
+  return ceil(a);
+}
+
+uint8_t plc4c_spi_evaluation_helper_count(plc4c_list a) {
+  return plc4c_utils_list_size(&a);
+}
+