diff --git a/src/main/java/de/hhu/stups/codegenerator/generators/DeclarationGenerator.java b/src/main/java/de/hhu/stups/codegenerator/generators/DeclarationGenerator.java
index b167d5bf8cca1cceedb174f140545d30dd0466f8..be0a8742ba9e07ace5ef48b282edb7f62fff446c 100644
--- a/src/main/java/de/hhu/stups/codegenerator/generators/DeclarationGenerator.java
+++ b/src/main/java/de/hhu/stups/codegenerator/generators/DeclarationGenerator.java
@@ -1,24 +1,31 @@
 package de.hhu.stups.codegenerator.generators;
 
 
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+
 import de.hhu.stups.codegenerator.analyzers.DeferredSetAnalyzer;
 import de.hhu.stups.codegenerator.handlers.NameHandler;
 import de.hhu.stups.codegenerator.handlers.TemplateHandler;
 import de.prob.parser.ast.nodes.DeclarationNode;
 import de.prob.parser.ast.nodes.EnumeratedSetDeclarationNode;
+import de.prob.parser.ast.nodes.FreetypeBaseElementNode;
+import de.prob.parser.ast.nodes.FreetypeConstructorNode;
+import de.prob.parser.ast.nodes.FreetypeDeclarationNode;
+import de.prob.parser.ast.nodes.FreetypeElementNode;
 import de.prob.parser.ast.nodes.MachineNode;
 import de.prob.parser.ast.nodes.MachineReferenceNode;
 import de.prob.parser.ast.nodes.OperationNode;
-import de.prob.parser.ast.types.CoupleType;
 import de.prob.parser.ast.types.SetType;
+
 import org.stringtemplate.v4.ST;
 import org.stringtemplate.v4.STGroup;
 
-import java.util.*;
-import java.util.function.Function;
-import java.util.stream.Collectors;
-import java.util.stream.IntStream;
-
 public class DeclarationGenerator {
 
     private final STGroup currentGroup;
@@ -37,6 +44,8 @@ public class DeclarationGenerator {
 
     private final DeferredSetAnalyzer deferredSetAnalyzer;
 
+    private final Map<String, String> freetypeToMachine;
+
 
     public DeclarationGenerator(final STGroup currentGroup, final MachineGenerator machineGenerator, final TypeGenerator typeGenerator,
                                 final ImportGenerator importGenerator, final NameHandler nameHandler, final DeferredSetAnalyzer deferredSetAnalyzer) {
@@ -49,6 +58,7 @@ public class DeclarationGenerator {
         this.deferredSetAnalyzer = deferredSetAnalyzer;
         this.setToEnum = new HashMap<>();
         this.enumToMachine = new HashMap<>();
+        this.freetypeToMachine = new HashMap<>();
     }
 
     /*
@@ -354,4 +364,52 @@ public class DeclarationGenerator {
         return enumToMachine;
     }
 
+    public Map<String, String> getFreetypeToMachine() {
+        return freetypeToMachine;
+    }
+
+    /*
+     * Generate all declarations for the freetypes included in the given machine.
+     */
+    public List<String> generateFreetypeDeclarations(MachineNode node) {
+        node.getFreetypes().forEach(ft -> {
+            freetypeToMachine.put(ft.getFreetypeDeclarationNode().getName(), node.getName());
+        });
+        return node.getFreetypes().stream()
+                       .flatMap(ft -> this.declareFreetype(ft).stream())
+                       .collect(Collectors.toList());
+    }
+
+    /*
+     * Generate the declaration for one freetype.
+     */
+    private List<String> declareFreetype(FreetypeDeclarationNode node) {
+        List<String> result = new ArrayList<>();
+
+        String ftName = nameHandler.handleIdentifier(node.getFreetypeDeclarationNode().getName(), NameHandler.IdentifierHandlingEnum.FUNCTION_NAMES);
+
+        ST ftDeclaration = currentGroup.getInstanceOf("freetype_declaration");
+        TemplateHandler.add(ftDeclaration, "name", ftName);
+        result.add(ftDeclaration.render());
+
+        for (FreetypeBaseElementNode element : node.getElements()) {
+            ST ftElement;
+            if (element instanceof FreetypeElementNode) {
+                ftElement = currentGroup.getInstanceOf("freetype_element_declaration");
+            } else if (element instanceof FreetypeConstructorNode) {
+                FreetypeConstructorNode c = (FreetypeConstructorNode) element;
+                ftElement = currentGroup.getInstanceOf("freetype_constructor_declaration");
+                SetType type = (SetType) c.getExpr().getType();
+                TemplateHandler.add(ftElement, "subtype", typeGenerator.generate(type.getSubType()));
+            } else {
+                throw new AssertionError();
+            }
+
+            TemplateHandler.add(ftElement, "freetype", ftName);
+            TemplateHandler.add(ftElement, "name", nameHandler.handleIdentifier(element.getName(), NameHandler.IdentifierHandlingEnum.FUNCTION_NAMES));
+            result.add(ftElement.render());
+        }
+
+        return result;
+    }
 }
diff --git a/src/main/java/de/hhu/stups/codegenerator/generators/MachineGenerator.java b/src/main/java/de/hhu/stups/codegenerator/generators/MachineGenerator.java
index 84cb6906c01027322cb58b1ce8c9ce58359e61d7..925b70a0941ac7c623d8679453cbb17fa214846a 100755
--- a/src/main/java/de/hhu/stups/codegenerator/generators/MachineGenerator.java
+++ b/src/main/java/de/hhu/stups/codegenerator/generators/MachineGenerator.java
@@ -1,5 +1,13 @@
 package de.hhu.stups.codegenerator.generators;
 
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.stream.Collectors;
+
 import de.hhu.stups.codegenerator.CodeGeneratorUtils;
 import de.hhu.stups.codegenerator.GeneratorMode;
 import de.hhu.stups.codegenerator.MachineConstantsOptimizer;
@@ -11,7 +19,11 @@ import de.hhu.stups.codegenerator.handlers.NameHandler;
 import de.hhu.stups.codegenerator.handlers.ParallelConstructHandler;
 import de.hhu.stups.codegenerator.handlers.TemplateHandler;
 import de.hhu.stups.codegenerator.json.modelchecker.ModelCheckingInfo;
-import de.prob.parser.ast.nodes.*;
+import de.prob.parser.ast.nodes.DeclarationNode;
+import de.prob.parser.ast.nodes.MachineNode;
+import de.prob.parser.ast.nodes.MachineReferenceNode;
+import de.prob.parser.ast.nodes.Node;
+import de.prob.parser.ast.nodes.OperationNode;
 import de.prob.parser.ast.nodes.expression.ExprNode;
 import de.prob.parser.ast.nodes.expression.ExpressionOperatorNode;
 import de.prob.parser.ast.nodes.expression.IdentifierExprNode;
@@ -54,12 +66,10 @@ import de.prob.parser.ast.nodes.substitution.WhileSubstitutionNode;
 import de.prob.parser.ast.types.CoupleType;
 import de.prob.parser.ast.types.UntypedType;
 import de.prob.parser.ast.visitors.AbstractVisitor;
+
 import org.stringtemplate.v4.ST;
 import org.stringtemplate.v4.STGroup;
 
-import java.util.*;
-import java.util.stream.Collectors;
-
 /*
 * The code generator is implemented by using the visitor pattern
 */
@@ -326,6 +336,7 @@ public class MachineGenerator implements AbstractVisitor<String, Void> {
 		enumIdentifier.addAll(identifier);
 		TemplateHandler.add(machine, "enum_imports", importGenerator.getImportedEnums());
 		TemplateHandler.add(machine, "sets", declarationGenerator.generateSetDeclarations(node));
+		TemplateHandler.add(machine, "freetypes", declarationGenerator.generateFreetypeDeclarations(node));
 		TemplateHandler.add(machine, "declarations", declarationGenerator.visitDeclarations(node.getVariables()));
 		TemplateHandler.add(machine, "includes", declarationGenerator.generateIncludes(node));
 		TemplateHandler.add(machine, "initialization", substitutionGenerator.visitInitialization(node));
diff --git a/src/main/java/de/hhu/stups/codegenerator/generators/TypeGenerator.java b/src/main/java/de/hhu/stups/codegenerator/generators/TypeGenerator.java
index bd79323f898faa11fee07f929fdcd130fa4f6348..6e9696a5768af0e6289ae3a71b7d8bbaae53d784 100644
--- a/src/main/java/de/hhu/stups/codegenerator/generators/TypeGenerator.java
+++ b/src/main/java/de/hhu/stups/codegenerator/generators/TypeGenerator.java
@@ -8,6 +8,7 @@ import de.prob.parser.ast.types.BoolType;
 import de.prob.parser.ast.types.CoupleType;
 import de.prob.parser.ast.types.DeferredSetElementType;
 import de.prob.parser.ast.types.EnumeratedSetElementType;
+import de.prob.parser.ast.types.FreetypeType;
 import de.prob.parser.ast.types.IntegerType;
 import de.prob.parser.ast.types.RecordType;
 import de.prob.parser.ast.types.SetType;
@@ -53,14 +54,17 @@ public class TypeGenerator {
             return generateEnumeratedSetElement((EnumeratedSetElementType) type);
         } else if(type instanceof DeferredSetElementType) {
             return generateDeferredSetElement((DeferredSetElementType) type);
+        } else if(type instanceof FreetypeType) {
+            return generateFreetype((FreetypeType) type);
         } else if(type instanceof CoupleType) {
             return generateBTuple((CoupleType) type);
         } else if(type instanceof RecordType) {
             return generateBStruct((RecordType) type);
         } else if(type instanceof UntypedType) {
             return generateUntyped();
+        } else {
+            throw new IllegalArgumentException("Unsupported type: " + type);
         }
-        return "";
     }
 
     /*
@@ -165,6 +169,18 @@ public class TypeGenerator {
         return template.render();
     }
 
+    /*
+     * This function generates code for the type of a freetype
+     */
+    private String generateFreetype(FreetypeType type) {
+        ST template = group.getInstanceOf("type");
+        TemplateHandler.add(template, "fromOtherMachine", declarationGenerator.getFreetypeToMachine().get(type.getName()) != null && !machineGenerator.getMachineName().equals(declarationGenerator.getFreetypeToMachine().get(type.getName())));
+        TemplateHandler.add(template, "otherMachine", declarationGenerator.getFreetypeToMachine().get(type.getName()));
+        TemplateHandler.add(template, "fromOutside", fromOutside);
+        TemplateHandler.add(template, "type", nameHandler.handleIdentifier(type.toString(), NameHandler.IdentifierHandlingEnum.FUNCTION_NAMES));
+        return template.render();
+    }
+
     /*
     * This function generates code for untyped nodes.
     */
diff --git a/src/main/java/de/hhu/stups/codegenerator/handlers/NameHandler.java b/src/main/java/de/hhu/stups/codegenerator/handlers/NameHandler.java
index a49f7a5a8f7026f88c976cdc643fd82b68d22591..03729fb05659341a234c5dc7d6ee1e37a3433870 100644
--- a/src/main/java/de/hhu/stups/codegenerator/handlers/NameHandler.java
+++ b/src/main/java/de/hhu/stups/codegenerator/handlers/NameHandler.java
@@ -1,12 +1,5 @@
 package de.hhu.stups.codegenerator.handlers;
 
-import de.hhu.stups.codegenerator.GeneratorMode;
-import de.hhu.stups.codegenerator.generators.MachineGenerator;
-import de.prob.parser.ast.nodes.DeclarationNode;
-import de.prob.parser.ast.nodes.MachineNode;
-import org.stringtemplate.v4.ST;
-import org.stringtemplate.v4.STGroup;
-
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.HashMap;
@@ -14,6 +7,14 @@ import java.util.List;
 import java.util.Map;
 import java.util.stream.Collectors;
 
+import de.hhu.stups.codegenerator.GeneratorMode;
+import de.hhu.stups.codegenerator.generators.MachineGenerator;
+import de.prob.parser.ast.nodes.DeclarationNode;
+import de.prob.parser.ast.nodes.MachineNode;
+
+import org.stringtemplate.v4.ST;
+import org.stringtemplate.v4.STGroup;
+
 import static de.hhu.stups.codegenerator.handlers.NameHandler.IdentifierHandlingEnum.FUNCTION_NAMES;
 import static de.hhu.stups.codegenerator.handlers.NameHandler.IdentifierHandlingEnum.INCLUDED_MACHINES;
 import static de.hhu.stups.codegenerator.handlers.NameHandler.IdentifierHandlingEnum.MACHINES;
@@ -51,12 +52,15 @@ public class NameHandler {
 
     private List<String> deferredTypes;
 
+    private Map<String, List<String>> freeTypes;
+
     public NameHandler(final MachineGenerator machineGenerator, final STGroup group) {
         this.machineGenerator = machineGenerator;
         this.group = group;
         this.globals = new ArrayList<>();
         this.enumTypes = new HashMap<>();
         this.deferredTypes = new ArrayList<>();
+        this.freeTypes = new HashMap<>();
         this.reservedMachines = new ArrayList<>();
         this.reservedMachinesWithIncludedMachines = new ArrayList<>();
         this.reservedMachinesAndFunctions = new ArrayList<>();
@@ -75,6 +79,14 @@ public class NameHandler {
             }
         });
         deferredTypes.addAll(node.getDeferredSets().stream().map(DeclarationNode::getName).collect(Collectors.toList()));
+        node.getFreetypes().forEach(ft -> {
+            List<String> elementsAsString = ft.getElements().stream().map(DeclarationNode::getName).collect(Collectors.toList());
+            if (node.getPrefix() != null && !node.equals(machineGenerator.getMachineNode())) {
+                freeTypes.put(node.getPrefix() + "." + ft.getFreetypeDeclarationNode().getName(), elementsAsString);
+            } else {
+                freeTypes.put(ft.getFreetypeDeclarationNode().getName(), elementsAsString);
+            }
+        });
         reservedMachines.addAll(node.getMachineReferences().stream()
                 .map(reference -> handle(reference.getMachineName()))
                 .collect(Collectors.toList()));
@@ -199,6 +211,10 @@ public class NameHandler {
         return deferredTypes;
     }
 
+    public Map<String, List<String>> getFreeTypes() {
+        return freeTypes;
+    }
+
     public Map<String, String> getEnumToMachine() {
         return machineGenerator.getDeclarationGenerator().getEnumToMachine();
     }
diff --git a/src/main/resources/de/hhu/stups/codegenerator/JavaTemplate.stg b/src/main/resources/de/hhu/stups/codegenerator/JavaTemplate.stg
index c1a28afcb5d75dabc98bc788ad1a37aeddc6a8c3..2083b9dd0a129cbaecbc90392dbde5b0cb197f2d 100644
--- a/src/main/resources/de/hhu/stups/codegenerator/JavaTemplate.stg
+++ b/src/main/resources/de/hhu/stups/codegenerator/JavaTemplate.stg
@@ -3,7 +3,7 @@ abstract, assert, boolean, break, byte, case, catch, char, class, continue, defa
 >>
 
 
-machine(forModelChecking, imports, machine, projectionClasses, structs, constants_declarations, includes, enums, sets, declarations, initialization, mainMethod, copyConstructor, operations, addition, getters, transitions, projection, invariant, copy, hash_equal, modelcheck, lambdaFunctions, choicePoints, choicePointsGetters, choicePointOperationFlags, choicePointOperationFlagGetters, choicePointOperationFlagResets, choicePointOperationTriggered, choicePointOperationTriggeredResets, choicePointOperationTriggeredFlags, choicePointOperationApplies, externalFunctions) ::= <<
+machine(forModelChecking, imports, machine, projectionClasses, structs, constants_declarations, includes, enums, freetypes, sets, declarations, initialization, mainMethod, copyConstructor, operations, addition, getters, transitions, projection, invariant, copy, hash_equal, modelcheck, lambdaFunctions, choicePoints, choicePointsGetters, choicePointOperationFlags, choicePointOperationFlagGetters, choicePointOperationFlagResets, choicePointOperationTriggered, choicePointOperationTriggeredResets, choicePointOperationTriggeredFlags, choicePointOperationApplies, externalFunctions) ::= <<
 <imports; separator="\n">
 <if(forModelChecking)>
 import java.util.HashMap;
@@ -87,6 +87,8 @@ public class <machine> {
 
     <enums; separator="\n\n">
 
+    <freetypes; separator="\n\n">
+
     <sets; separator="\n">
 
     <declarations; separator="\n">
@@ -586,6 +588,91 @@ public enum <name> implements BObject {
 }
 >>
 
+freetype_declaration(name) ::= <<
+public static abstract class <name> extends BFreetype {
+
+    protected <name>() {
+    }
+}
+>>
+
+freetype_element_declaration(name,freetype) ::= <<
+public static final class <name> extends <freetype> {
+
+    public static final <name> INSTANCE = new <name>();
+
+    private <name>() {
+    }
+
+    public BBoolean equal(<freetype> o) {
+        return new BBoolean(this.equals(o));
+    }
+
+    public BBoolean unequal(<freetype> o) {
+        return this.equal(o).not();
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        return o instanceof <name>;
+    }
+
+    @Override
+    public int hashCode() {
+        return this.getClass().hashCode();
+    }
+
+    @Override
+    public String toString() {
+        return "<name>";
+    }
+}
+>>
+
+freetype_constructor_declaration(name,freetype,subtype) ::= <<
+public final class <name> extends <freetype> {
+
+    private final <subtype> value;
+
+    public <name>(<subtype> value) {
+        this.value = value;
+    }
+
+    public <subtype> getValue() {
+        return this.value;
+    }
+
+    public BBoolean equal(<freetype> o) {
+        return new BBoolean(this.equals(o));
+    }
+
+    public BBoolean unequal(<freetype> o) {
+        return this.equal(o).not();
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) {
+            return true;
+        } else if (!(o instanceof <name>)) {
+            return false;
+        } else {
+            return this.value.equals(((<name>) o).value);
+        }
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(this.getClass(), this.value);
+    }
+
+    @Override
+    public String toString() {
+        return "<name>(" + this.value + ")";
+    }
+}
+>>
+
 bool() ::= <<
 BUtils.BOOL
 >>