diff --git a/src/main/java/avatartranslator/AvatarAttribute.java b/src/main/java/avatartranslator/AvatarAttribute.java
index 8c1d689e87d92ed87bf2a4d2ffec9b313d9dfd11..bd089ee6c5be3f5a56a6a89963b6b1fa7b9f064e 100644
--- a/src/main/java/avatartranslator/AvatarAttribute.java
+++ b/src/main/java/avatartranslator/AvatarAttribute.java
@@ -56,6 +56,7 @@ public class AvatarAttribute extends AvatarLeftHand implements NameChecker.NameS
 
     // Types of parameters
     private AvatarType type;
+    private AvatarDataType dataType;
     private String initialValue;
     private boolean isConstant;
 
@@ -73,8 +74,11 @@ public class AvatarAttribute extends AvatarLeftHand implements NameChecker.NameS
           }
           }*/
         type = _type;
+        dataType = null;
         this.block = _block;
     }
+    public void setDataType(AvatarDataType _adt) { dataType = _adt; }
+    public AvatarDataType getDataType() { return  dataType; }
 
     public AvatarStateMachineOwner getBlock() {
         return this.block;
diff --git a/src/main/java/avatartranslator/AvatarDataType.java b/src/main/java/avatartranslator/AvatarDataType.java
new file mode 100644
index 0000000000000000000000000000000000000000..f9e28f60bbe01f2405a9d0712ea1c53ae3a7f689
--- /dev/null
+++ b/src/main/java/avatartranslator/AvatarDataType.java
@@ -0,0 +1,56 @@
+package avatartranslator;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class AvatarDataType {
+    public final static int INTEGER = 0;
+    public final static int BOOLEAN = 1;
+    public final static int DATATYPE = 2;
+    public static Map<String,AvatarDataType> dataTypeMap = new HashMap<String,AvatarDataType>();
+    private String name;
+    private List<String> fieldNames = new ArrayList<String>();
+    private List<Integer> fieldTypes = new ArrayList<Integer>();
+    private List<String> dataTypeNames = new ArrayList<String>();
+    private int size = -1;
+
+    public AvatarDataType(String _name) {
+        name = _name;
+    }
+    public int getFullSize() { return size; }
+    public int getNbFields() { return fieldNames.size(); }
+    String getFieldName(int _i) { return fieldNames.get(_i); }
+    public int getFieldType(int _i) { return fieldTypes.get(_i); }
+    String getDataTypeNameName(int _i) { return dataTypeNames.get(_i); }
+    public void addField(String _fieldName, int _fieldType, String _dataTypeName) {
+        if (size != -1) return; // DataType has already been finalized
+        if (_fieldType == AvatarDataType.INTEGER || _fieldType == AvatarDataType.BOOLEAN)
+            dataTypeNames.add(null);
+        else if (_fieldType != DATATYPE)
+            return;
+        else
+            dataTypeNames.add(_dataTypeName);
+        fieldTypes.add(_fieldType);
+        fieldNames.add(_fieldName);
+    }
+    public static void finalize(AvatarDataType adt) {
+        if (adt.size != -1) return;
+        int size = 0;
+        int length = adt.getNbFields();
+        for (int i = 0; i < length; i++) {
+            if (adt.getFieldType(i) == AvatarDataType.INTEGER || adt.getFieldType(i) == AvatarDataType.BOOLEAN) {
+                size += 1;
+                continue;
+            }
+            AvatarDataType fieldDataType = dataTypeMap.get(i);
+            if (fieldDataType == null)  return;
+            finalize(fieldDataType); // loops if recursion => recursive types are forbidden
+            int fieldSize = fieldDataType.getFullSize();
+            if (fieldSize == -1)  return;
+            size += fieldSize;
+        }
+        adt.size = size;
+    }
+}
diff --git a/src/main/java/avatartranslator/AvatarSpecification.java b/src/main/java/avatartranslator/AvatarSpecification.java
index 1edc4a6ca960045b773ab24edd61ac03bf3745c9..ae5f7a7047aea99f19856a719a4a97c6aec81594 100644
--- a/src/main/java/avatartranslator/AvatarSpecification.java
+++ b/src/main/java/avatartranslator/AvatarSpecification.java
@@ -73,6 +73,7 @@ public class AvatarSpecification extends AvatarElement implements IBSParamSpec {
     private final List<String> safetyPragmas;
     private final HashMap<String, String> safetyPragmasRefs;
     private final List<AvatarPragmaLatency> latencyPragmas;
+    private final List<AvatarDataType> dataTypes;
     private final List<AvatarConstant> constants;
     private final boolean robustnessMade = false;
     public List<String> checkedIDs;
@@ -95,6 +96,7 @@ public class AvatarSpecification extends AvatarElement implements IBSParamSpec {
         safetyPragmas = new LinkedList<>();
         safetyPragmasRefs = new HashMap<>();
         latencyPragmas = new LinkedList<>();
+        dataTypes = new LinkedList<>();
         this.constants.add(AvatarConstant.FALSE);
         this.constants.add(AvatarConstant.TRUE);
         checkedIDs = new ArrayList<>();
@@ -678,6 +680,8 @@ public class AvatarSpecification extends AvatarElement implements IBSParamSpec {
         return latencyPragmas;
     }
 
+    public List<AvatarDataType> getDataTypes() { return dataTypes; }
+
     public List<AvatarConstant> getAvatarConstants() {
         return constants;
     }
diff --git a/src/main/java/ui/AvatarDesignPanelTranslator.java b/src/main/java/ui/AvatarDesignPanelTranslator.java
index dd3ca1f65fb8bbb5ae21cb8c9a86f1035d92cd8b..f06c19ebc8455fcadad953707f464e71664aed2f 100644
--- a/src/main/java/ui/AvatarDesignPanelTranslator.java
+++ b/src/main/java/ui/AvatarDesignPanelTranslator.java
@@ -47,6 +47,7 @@ import ui.avatarbd.*;
 import ui.avatarsmd.*;
 
 import java.util.*;
+import java.util.function.BiConsumer;
 
 /**
  * Class AvatarDesignPanelTranslator
@@ -107,6 +108,7 @@ public class AvatarDesignPanelTranslator {
         }
         typeAttributesMap = new HashMap<String, List<TAttribute>>();
         nameTypeMap = new HashMap<String, String>();
+        createDataTypes(as);
         createLibraryFunctions(as, libraryFunctions);
         createBlocks(as, blocks);
         //createInterfaces(as, interfaces);
@@ -1034,6 +1036,35 @@ public class AvatarDesignPanelTranslator {
         return optype;
     }
 
+    private class FinalizeAvatarDataType implements BiConsumer<String, AvatarDataType> {
+        List<AvatarDataType> dataTypeList;
+        public FinalizeAvatarDataType(List<AvatarDataType> _dataTypeList){ dataTypeList = _dataTypeList; }
+        public void accept(String n, AvatarDataType d) {
+            AvatarDataType.finalize(d);
+            dataTypeList.add(d);
+        }
+    }
+    public void createDataTypes(AvatarSpecification as) {
+        AvatarDataType.dataTypeMap.clear();
+        for (TGComponent tgc : adp.getAvatarBDPanel().getComponentList())
+            if (tgc instanceof AvatarBDDataType) {
+                AvatarBDDataType tgdt = (AvatarBDDataType)tgc;
+                String dtName = tgdt.getDataTypeName();
+                AvatarDataType dataType = new AvatarDataType(dtName);
+                List<TAttribute> fields = tgdt.getAttributeList();
+                for (TAttribute f : fields) {
+                    if(f.getType() == TAttribute.INTEGER || f.getType() == TAttribute.NATURAL)
+                        dataType.addField(f.getId(), AvatarDataType.INTEGER, null);
+                    else if (f.getType() == TAttribute.BOOLEAN)
+                        dataType.addField(f.getId(), AvatarDataType.BOOLEAN, null);
+                    else
+                        dataType.addField(f.getId(), AvatarDataType.DATATYPE, f.getTypeOther());
+                }
+                AvatarDataType.dataTypeMap.put(dtName, dataType);
+            }
+        AvatarDataType.dataTypeMap.forEach(new FinalizeAvatarDataType(as.getDataTypes()));
+    }
+
     private AvatarAttribute createRegularAttribute(AvatarStateMachineOwner _ab, TAttribute _a, String _preName, TAttribute originAttribute) {
         AvatarType type = AvatarType.UNDEFINED;
         if (_a.getType() == TAttribute.INTEGER) {
@@ -1056,8 +1087,10 @@ public class AvatarDesignPanelTranslator {
         return aa;
     }
 
-    private void addRegularAttribute(AvatarBlock _ab, TAttribute _a, String _preName, TAttribute originAttribute) {
-        _ab.addAttribute(this.createRegularAttribute(_ab, _a, _preName, originAttribute));
+    private AvatarAttribute addRegularAttribute(AvatarBlock _ab, TAttribute _a, String _preName, TAttribute originAttribute) {
+        AvatarAttribute aa = this.createRegularAttribute(_ab, _a, _preName, originAttribute);
+        _ab.addAttribute(aa);
+        return aa;
     }
 
     private void addRegularAttributeInterface(AvatarAMSInterface _ai, TAttribute _a, String _preName, TAttribute originAttribute) {
@@ -1097,8 +1130,12 @@ public class AvatarDesignPanelTranslator {
                         } else {
                             nameTypeMap.put(libraryFunction.getFunctionName() + "." + attr.getId(), attr.getTypeOther());
                             typeAttributesMap.put(attr.getTypeOther(), types);
-                            for (TAttribute type : types)
-                                alf.addParameter(this.createRegularAttribute(alf, type, attr.getId() + "__", attr));
+                            AvatarAttribute aa = this.createRegularAttribute(alf, types.get(0), attr.getId() + "__", attr);
+                            aa.setDataType(AvatarDataType.dataTypeMap.get(attr.getTypeOther()));
+                            alf.addParameter(aa);
+                            int nbFields = types.size();
+                            for (int i = 1; i < nbFields; i++)
+                                alf.addParameter(this.createRegularAttribute(alf, types.get(i), attr.getId() + "__", attr));
                         }
                     }
                 }
@@ -1128,8 +1165,12 @@ public class AvatarDesignPanelTranslator {
                         } else {
                             nameTypeMap.put(libraryFunction.getFunctionName() + "." + attr.getId(), attr.getTypeOther());
                             typeAttributesMap.put(attr.getTypeOther(), types);
-                            for (TAttribute type : types)
-                                alf.addReturnAttribute(this.createRegularAttribute(alf, type, attr.getId() + "__", attr));
+                            AvatarAttribute aa = this.createRegularAttribute(alf, types.get(0), attr.getId() + "__", attr);
+                            aa.setDataType(AvatarDataType.dataTypeMap.get(attr.getTypeOther()));
+                            alf.addReturnAttribute(aa);
+                            int nbFields = types.size();
+                            for (int i = 1; i < nbFields; i++)
+                                alf.addReturnAttribute(this.createRegularAttribute(alf, types.get(i), attr.getId() + "__", attr));
                         }
                     }
                 }
@@ -1159,6 +1200,12 @@ public class AvatarDesignPanelTranslator {
                         } else {
                             nameTypeMap.put(libraryFunction.getFunctionName() + "." + attr.getId(), attr.getTypeOther());
                             typeAttributesMap.put(attr.getTypeOther(), types);
+                            AvatarAttribute aa = this.createRegularAttribute(alf, types.get(0), attr.getId() + "__", attr);
+                            aa.setDataType(AvatarDataType.dataTypeMap.get(attr.getTypeOther()));
+                            alf.addAttribute(aa);
+                            int nbFields = types.size();
+                            for (int i = 1; i < nbFields; i++)
+                                alf.addAttribute(this.createRegularAttribute(alf, types.get(i), attr.getId() + "__", attr));
                             for (TAttribute type : types)
                                 alf.addAttribute(this.createRegularAttribute(alf, type, attr.getId() + "__", attr));
                         }
@@ -1224,9 +1271,11 @@ public class AvatarDesignPanelTranslator {
                         } else {
                             nameTypeMap.put(block.getBlockName() + "." + a.getId(), a.getTypeOther());
                             typeAttributesMap.put(a.getTypeOther(), types);
-                            for (TAttribute type : types) {
-                                addRegularAttribute(ab, type, a.getId() + "__", a);
-                            }
+                            AvatarAttribute aa = addRegularAttribute(ab, types.get(0), a.getId() + "__", a);
+                            aa.setDataType(AvatarDataType.dataTypeMap.get(a.getTypeOther()));
+                            int nbFields = types.size();
+                            for (int i = 1; i < nbFields; i++)
+                                addRegularAttribute(ab, types.get(i), a.getId() + "__", a);
                         }
                     }
                 }
@@ -1413,6 +1462,7 @@ public class AvatarDesignPanelTranslator {
                     else
                         type = AvatarType.INTEGER;
                     aa = new AvatarAttribute("return__" + j++, type, _ab, _block);
+                    if (j==0) aa.setDataType(AvatarDataType.dataTypeMap.get(rt));
                     _atam.addReturnParameter(aa);
                 }
             }
@@ -1437,18 +1487,20 @@ public class AvatarDesignPanelTranslator {
                 AvatarAttribute aa = new AvatarAttribute(typeIds[i], AvatarType.getType(types[i]), _block, _uiam);
                 _atam.addParameter(aa);
             } else {
-                for (TAttribute ta : v) {
+                int nbFields = v.size();
+                for (int j = 0; i < nbFields; i++) {
                     AvatarType type = AvatarType.UNDEFINED;
-                    if (ta.getType() == TAttribute.INTEGER) {
+                    if (v.get(j).getType() == TAttribute.INTEGER) {
                         type = AvatarType.INTEGER;
-                    } else if (ta.getType() == TAttribute.NATURAL) {
+                    } else if (v.get(j).getType() == TAttribute.NATURAL) {
                         type = AvatarType.INTEGER;
-                    } else if (ta.getType() == TAttribute.BOOLEAN) {
+                    } else if (v.get(j).getType() == TAttribute.BOOLEAN) {
                         type = AvatarType.BOOLEAN;
-                    } else if (ta.getType() == TAttribute.TIMER) {
+                    } else if (v.get(j).getType() == TAttribute.TIMER) {
                         type = AvatarType.TIMER;
                     }
-                    AvatarAttribute aa = new AvatarAttribute(typeIds[i] + "__" + ta.getId(), type, _block, _uiam);
+                    AvatarAttribute aa = new AvatarAttribute(typeIds[i] + "__" + v.get(j).getId(), type, _block, _uiam);
+                    if ( j == 0 ) aa.setDataType(AvatarDataType.dataTypeMap.get(types[i]));
                     _atam.addParameter(aa);
                 }
             }
@@ -1742,11 +1794,13 @@ public class AvatarDesignPanelTranslator {
                         if (types == null || types.isEmpty())
                             throw new CheckingError(CheckingError.STRUCTURE_ERROR, "Unknown data type:  " + returnTA.getTypeOther() + " when calling " + libraryFunction.getFunctionName());
 
-                        for (TAttribute type : types) {
-                            String attributeName = dummyName + "__" + type.getId();
+                        int nbFields = types.size();
+                        for (int j = 0; j < nbFields; j++) {
+                            String attributeName = dummyName + "__" + types.get(j).getId();
                             AvatarAttribute attr = _ab.getAvatarAttributeWithName(attributeName);
                             if (attr == null) {
-                                attr = this.createRegularAttribute(_ab, type, dummyName + "__", null);
+                                attr = this.createRegularAttribute(_ab, types.get(j), dummyName + "__", null);
+                                if (j == 0) attr.setDataType(AvatarDataType.dataTypeMap.get(returnTA.getTypeOther()));
                                 _ab.addAttribute(attr);
                             }
                             attrs.add(attr);
@@ -1811,11 +1865,13 @@ public class AvatarDesignPanelTranslator {
                     if (types == null || types.isEmpty())
                         throw new CheckingError(CheckingError.STRUCTURE_ERROR, "Unknown data type:  " + returnTA.getTypeOther() + " when calling " + libraryFunction.getFunctionName());
 
-                    for (TAttribute type : types) {
-                        String attributeName = dummyName + "__" + type.getId();
+                    int nbField = types.size();
+                    for (int j = 0; j < types.size(); j++) {
+                        String attributeName = dummyName + "__" + types.get(j).getId();
                         AvatarAttribute attr = _ab.getAvatarAttributeWithName(attributeName);
                         if (attr == null) {
-                            attr = this.createRegularAttribute(_ab, type, dummyName + "__", null);
+                            attr = this.createRegularAttribute(_ab, types.get(j), dummyName + "__", null);
+                            if (j == 0) attr.setDataType(AvatarDataType.dataTypeMap.get(returnTA.getTypeOther()));
                             _ab.addAttribute(attr);
                         }
                         attrs.add(attr);