From fa3aec318ed5a28f976f41833e1cf3fff926d590 Mon Sep 17 00:00:00 2001
From: Cookiebowser <lucas.doering@live.de>
Date: Thu, 9 Feb 2023 13:01:16 +0100
Subject: [PATCH] support for const-sets and some cleanup

constant Sets/Relations result in the generation of smaller Data-structures, only capable of holding the defined values.
This only works for SetTypes that are only used in a constant context. ConstSets of a type that also appear in a dynamic set behave just like their dynamic counterpart.
---
 .../main/rust_embedded/bmachine/Cargo.toml    |   3 -
 .../rust_embedded/btypes/src/brelation.rs     |  77 ++++++---
 .../src/main/rust_embedded/btypes/src/bset.rs | 148 +++++++++++-------
 .../stups/codegenerator/CodeGenerator.java    |  22 +--
 .../codegenerator/CodeGeneratorUtils.java     |   8 +-
 .../stups/codegenerator/GeneratorMode.java    |   2 +-
 .../definitions/SetDefinition.java            |  59 ++++++-
 .../definitions/SetDefinitions.java           |   2 +
 .../generators/DeclarationGenerator.java      |  28 ++--
 .../generators/ExpressionGenerator.java       |  68 +++++++-
 .../generators/MachineGenerator.java          |  10 +-
 .../generators/MachineReferenceGenerator.java |   4 +-
 .../generators/TypeGenerator.java             |  60 ++++---
 .../stups/codegenerator/RustTemplate_e.stg    |  56 ++++---
 14 files changed, 375 insertions(+), 172 deletions(-)

diff --git a/btypes_primitives/src/main/rust_embedded/bmachine/Cargo.toml b/btypes_primitives/src/main/rust_embedded/bmachine/Cargo.toml
index bcdbecfd5..2e001c335 100644
--- a/btypes_primitives/src/main/rust_embedded/bmachine/Cargo.toml
+++ b/btypes_primitives/src/main/rust_embedded/bmachine/Cargo.toml
@@ -7,9 +7,6 @@ edition = "2018"
 
 [dependencies]
 btypes = { path = "../btypes" }
-derivative = "2.2.0"
-threadpool = "1.8.1"
-dashmap = "~5.1.0"
 
 [profile.release]
 opt-level = 3
diff --git a/btypes_primitives/src/main/rust_embedded/btypes/src/brelation.rs b/btypes_primitives/src/main/rust_embedded/btypes/src/brelation.rs
index 8612337a7..aea2a1420 100644
--- a/btypes_primitives/src/main/rust_embedded/btypes/src/brelation.rs
+++ b/btypes_primitives/src/main/rust_embedded/btypes/src/brelation.rs
@@ -1,16 +1,17 @@
 #![ allow( non_snake_case) ]
 
 use core::marker::PhantomData;
-use crate::bset::{BSet, Set, SetItem};
+use crate::binteger::BInteger;
+use crate::bset::{BSet, PowSetItem, Set, SetItem};
 
 #[derive(Debug, Clone, Eq, PartialEq, Hash, PartialOrd, Ord)]
-pub struct BRelation<L: SetItem<LS>, const LS: usize, R: SetItem<RS>, const RS: usize> {
+pub struct BRelation<L: SetItem<LS>, const LS: usize, R: SetItem<RS>, const RS: usize, const REL_SIZE: usize> {
     rel: [[bool; RS]; LS], // indexing: rel[l_idx][r_idx]
     _p: core::marker::PhantomData<L>,
     _p2: core::marker::PhantomData<R>,
 }
 
-impl<L, const LS: usize, R, const RS: usize> Default for BRelation<L, LS, R, RS>
+impl<L, const LS: usize, R, const RS: usize, const REL_SIZE: usize> Default for BRelation<L, LS, R, RS, REL_SIZE>
 where L: SetItem<LS>,
       R: SetItem<RS>{
     fn default() -> Self {
@@ -18,7 +19,44 @@ where L: SetItem<LS>,
     }
 }
 
-impl<L, const LS: usize, R, const RS: usize> BRelation<L, LS, R, RS>
+pub trait RelLeftItem<const LEFT_SIZE: usize, RightItem: SetItem<RIGHT_SIZE>, const RIGHT_SIZE: usize, const REL_VARIANTS: usize, const REL_SIZE: usize>: SetItem<LEFT_SIZE> {
+    type RelEnum: PowSetItem<REL_VARIANTS, REL_SIZE>;
+
+    fn rel_to_idx(rel_arr: [[bool; RIGHT_SIZE]; LEFT_SIZE]) -> usize {
+        let mut flat_arr = [false; REL_SIZE];
+        for left_idx in 0..6 {
+            for right_idx in 0..6 {
+                flat_arr[left_idx * 6 + right_idx] = rel_arr[left_idx][right_idx];
+            }
+        }
+        return Self::RelEnum::arr_to_idx(flat_arr);
+    }
+
+    fn idx_to_rel(idx: usize) -> [[bool; RIGHT_SIZE]; LEFT_SIZE] {
+        let flat_arr = Self::RelEnum::idx_to_arr(idx);
+        let mut result = [[false; RIGHT_SIZE]; LEFT_SIZE];
+        for left_idx in 0..LEFT_SIZE {
+            for right_idx in 0..RIGHT_SIZE {
+                result[left_idx][right_idx] = flat_arr[left_idx * 6 + right_idx];
+            }
+        }
+        return result;
+    }
+}
+
+impl<L, const LS: usize, R, const RS: usize, const SIZE: usize, const REL_SIZE: usize> SetItem<SIZE> for BRelation<L, LS, R, RS, REL_SIZE>
+where L: SetItem<LS> + RelLeftItem<LS, R, RS, SIZE, REL_SIZE>,
+      R: SetItem<RS>{
+    fn as_idx(&self) -> usize {
+        return L::rel_to_idx(self.rel);
+    }
+
+    fn from_idx(idx: usize) -> Self {
+        return BRelation { rel: L::idx_to_rel(idx), _p: PhantomData, _p2: PhantomData };
+    }
+}
+
+impl<L, const LS: usize, R, const RS: usize, const REL_SIZE: usize> BRelation<L, LS, R, RS, REL_SIZE>
     where L: SetItem<LS>,
           R: SetItem<RS>{
     
@@ -35,11 +73,12 @@ impl<L, const LS: usize, R, const RS: usize> BRelation<L, LS, R, RS>
         let left_idx = left_item.as_idx();
         let right_idx = right_item.as_idx();
         result.rel[left_idx] = [false; RS];
-        result.rel[left_idx][right_item.as_idx()] = true;
+        result.rel[left_idx][right_idx] = true;
         return result;
     }
 
     pub fn add_tuple(&mut self, left_item: &L, right_item: &R) {
+        //println!("adding tuple ({:?},{:?}), idx = [{}][{}]", left_item, right_item, left_item.as_idx(), right_item.as_idx());
         self.rel[left_item.as_idx()][right_item.as_idx()] = true;
     }
 
@@ -66,6 +105,16 @@ impl<L, const LS: usize, R, const RS: usize> BRelation<L, LS, R, RS>
         return result;
     }
 
+    pub fn card(&self) -> BInteger {
+        let mut result: BInteger = 0;
+        for left_idx in 0..LS {
+            for right_idx in 0..RS {
+                result += self.rel[left_idx][right_idx] as BInteger;
+            }
+        }
+        return result;
+    }
+
     //this name is also hard-coded...
     //checks if self.domain is a subset of the given set
     pub fn checkDomain(&self, domain: &BSet<L, LS>) -> bool {
@@ -145,24 +194,6 @@ impl<L, const LS: usize, R, const RS: usize> BRelation<L, LS, R, RS>
         return result;
     }
 }
-/*
-impl<L, const LS: usize, R, const RS: usize> BRelation<L, LS, R, RS>
-    where L: SetItem<LS> + SetEnum<LS>,
-          R: SetItem<RS> + SetEnum<RS>{
-
-
-
-    pub fn function_call(&self, key: L) -> BSet<R, RS> {
-        let result_set: [bool; RS] = self.rel[key.as_idx()];
-        for i in 0..RS {
-            if result_set[i] { return <R as SetEnum<RS>>::from_idx(i) }
-        }
-        panic!("ERROR: key {:?} not found in set!", key);
-    }
-
-
-}
-*/
 
 #[macro_export]
 macro_rules! brel {
diff --git a/btypes_primitives/src/main/rust_embedded/btypes/src/bset.rs b/btypes_primitives/src/main/rust_embedded/btypes/src/bset.rs
index f775708c7..9c55da831 100644
--- a/btypes_primitives/src/main/rust_embedded/btypes/src/bset.rs
+++ b/btypes_primitives/src/main/rust_embedded/btypes/src/bset.rs
@@ -4,33 +4,47 @@ use core::fmt::Debug;
 use core::marker::PhantomData;
 use crate::binteger::BInteger;
 
-
+/// Used to map an Enum to the position in a Set of it's type. \
+/// This is necessary since, even though a [BSet] is alway represented as a flat, 1D-array,
+/// we want to interact with the Set via more readable names, like the Enum itself. \
+/// Especially when it comes to nested sets, we need to be able to consistently convert the subsets
+/// into the corresponding array-index. This Trait, with its associated functions, allows us
+/// (and Rust) to make sure that such a conversion[^note] always exists and is consistent.
+///
+/// Ex.: Assume the EnumeratedSet `Counters = {C1, C2, C3}` \
+/// This will lead to the following enum in Rust (excerpt):
+/// ```rust
+/// pub enum Counters {
+///     C1 = 0,
+///     C2 = 1,
+///     C3 = 2,
+/// }
+/// impl SetItem<3> for Counters{/*...*/}
+/// type set_Counters = BSet<Counters, 3>;
+/// ```
+/// If we now create a set with that type, we can add elements to it simply by using these enums.
+/// ```rust
+/// let c: set_Counters = set_Counters::empty();
+/// c.add(Counters::C2);
+/// ```
+///
+/// [^note]: This conversion always goes in both directions, from enum to index and from index to enum.
 pub trait SetItem<const VARIANTS: usize>: Default + Debug {
-    //type SetEnumType: SetEnum<VARIANTS>;
-    const VARIANTS: usize = VARIANTS; // number of variatins this SetItem has (i.e. lenght of an array necessary to build the maximum set)
+
+    /// Number of variations this SetItem has (i.e. size of the biggest set of this type)
+    const VARIANTS: usize = VARIANTS;
+
+    /// converts this SetItem into the index it corresponds to in any [BSet] of its type.
     fn as_idx(&self) -> usize;
+
+    /// converts an index of any [BSet] of this SetItem's type into the SetItem. \
+    /// Note: this is the inverse to [SetItem::as_idx], `set_item = SetItem::from_idx(set_item.as_idx())`
     fn from_idx(idx: usize) -> Self;
 }
 
-pub trait SetEnum<const ITEMVARIANTS: usize> { // Enum representing sets, Enum SetFoo = BSet<Foo>
-    //type ItemType: SetItem<SIZE>;
-    // SIZE = max-lenght of the Set
-    fn as_idx(set_arr: [bool; ITEMVARIANTS]) -> usize;
-    fn from_idx(idx: usize) -> [bool; ITEMVARIANTS];
-}
-/*
-pub trait EnumRepresented<const SIZE: usize> {
-    type SetRepr: SetEnum<SIZE>;
-}
-*/
-pub trait PowEnumRepresented<const SETVARIANTS: usize, const ITEMVARIANTS: usize> {
-    const SETVARIANTS: usize = SETVARIANTS;
-    //Implemented on top of SetItems, connects a SetItem to the Enum-representation of its Set
-    type SetRepr: SetEnum<ITEMVARIANTS>;
-}
+
 
 pub trait Set<const SIZE: usize>: Default {
-    //type SetRepr: SetEnum<SIZE>;
     type ItemType: SetItem<SIZE>;
 
     fn as_arr(&self) -> [bool; SIZE];
@@ -38,30 +52,9 @@ pub trait Set<const SIZE: usize>: Default {
     fn contains_idx(&self, idx: usize) -> bool;
     //checks if self is a subset of other
     fn subset_of(&self, other: &Self) -> bool;
-    //fn as_idx(&self) { Self::SetRepr::as_idx(self.as_arr()) }
 
-    //fn contains(&self, other: T) {
-    //    self[other.as_idx()]
-    //}
 }
-/*
-impl<const SIZE: usize, I, T> SetItem<SIZE> for T
-where I: SetItem<SIZE> ,
-      T: Set<I, SIZE> {
-    type SetEnumType = T::SetRepr;
-    fn as_idx(&self) -> usize { T::SetRepr::as_idx(self.as_arr()) }
-    fn from_idx(idx: usize) -> Self { T::from_arr(T::SetRepr::from_idx(idx)) }
-}*/
-/*
-Set<Person>::contains(Person)
-  --> Set[Persion.idx()]
-  --> SetEnum = PowPerson
-
-Set<Set<Person>>::contains(Set<Person>)
-  -> Set[Set<Persion>.idx()]
-  ->
-
-*/
+
 #[derive(Debug, Clone, Eq, PartialEq, Hash, PartialOrd, Ord)]
 pub struct BSet<I: SetItem<SIZE>, const SIZE: usize> {
     arr: [bool; SIZE],
@@ -85,24 +78,65 @@ impl<I: SetItem<SIZE>, const SIZE: usize> Set<SIZE> for BSet<I, SIZE> {
     }
 }
 
+/// Used to link the Enum-representation of a Set to the Enum-representation of it's subtype wich
+/// allows the use of [BSet]s as [SetItem]s.
+///
+/// In the generated code, we want to be able to use [BSet]s themselves as SetItems.
+/// This way, we can write `let some_set: BSet<BSet<Counters>>` which not only makes the type
+/// itself more readable, but any methods on `some_set` automatically use the 'correct' types. (i.e.
+/// iterating through the elements of `some_set` would automatically iterate through elements of type
+/// `BSet<Counters>`, instead of some enum-type.
+///
+/// To do this, [BSet] has to implement the [SetItem]-trait, which in turn requires an enum defining
+/// every possible variation of that Set. Unfortunately, we cannot implement that trait for the
+/// specific [BSet]s which need it during code-generation (Rust does not allow implementing external-traits
+/// for external structs). \
+/// However, we can implement the trait for [BSet] generically by defining some requirements that are
+/// needed for the implementation to work correctly. This requirement is the existence of an enum
+/// that fully represents the Set (i.e. carries one element for each possible SubSet). \
+/// That enum is then linked to the enum of it's subtype via this [PowSetItem]-trait, which the
+/// Rust-compiler can use to generate the specific impl's of the given Set (via the impl-definitions
+/// defined below).
+///
+/// todo(): example?
+///
+///
+/// SETVARIANTS-parameter is necessary to pass value along to SetItem-impl
+/// (caclulation on the fly is not possible (yet, generic_const_exprs is unstable/nightly)
+pub trait PowSetItem<const SETVARIANTS: usize, const ITEMVARIANTS: usize> {
+    //const SETVARIANTS: usize = SETVARIANTS;
+    //Implemented on top of SetItems, connects a SetItem to the Enum-representation of its Set
+    //SetRepr used to impl PowSetItem for BSet
+    type SetRepr: SetItem<SETVARIANTS>;
+    fn arr_to_idx(set_arr: [bool; ITEMVARIANTS]) -> usize;
+    fn idx_to_arr(idx: usize) -> [bool; ITEMVARIANTS];
+}
+
 impl<const SIZE: usize, const POWSIZE: usize, I> SetItem<POWSIZE> for BSet<I, SIZE>
-    where I: SetItem<SIZE> + PowEnumRepresented<POWSIZE, SIZE> {
+    where I: SetItem<SIZE> + PowSetItem<POWSIZE, SIZE> {
+    fn as_idx(&self) -> usize { I::arr_to_idx(self.as_arr()) }
+    fn from_idx(idx: usize) -> Self { Self::const_from_arr(I::idx_to_arr(idx)) }
+}
 
-    fn as_idx(&self) -> usize { I::SetRepr::as_idx(self.as_arr()) }
-    fn from_idx(idx: usize) -> Self { Self::const_from_arr(I::SetRepr::from_idx(idx)) }
+impl<const SETVARIANTS: usize, const ITEMVARIANTS: usize, const A: usize, I> PowSetItem<SETVARIANTS, ITEMVARIANTS> for BSet<I, A>
+    where I: SetItem<A> + PowSetItem<ITEMVARIANTS, A>,
+          I::SetRepr: SetItem<ITEMVARIANTS> + PowSetItem<SETVARIANTS, ITEMVARIANTS> {
+    type SetRepr = <<I as PowSetItem<ITEMVARIANTS, A>>::SetRepr as PowSetItem<SETVARIANTS, ITEMVARIANTS>>::SetRepr;
+    fn arr_to_idx(set_arr: [bool; ITEMVARIANTS]) -> usize { I::SetRepr::arr_to_idx(set_arr) }
+    fn idx_to_arr(idx: usize) -> [bool; ITEMVARIANTS] { I::SetRepr::idx_to_arr(idx) }
 }
 
 pub trait PowAble<const SETLEN: usize, const ITEMVARS: usize>: Set<SETLEN> + SetItem<ITEMVARS> {
     fn pow(&self) -> BSet<Self, ITEMVARS>;
 }
 
+/// To generate the powerset of a BSet we need the corresponding enum already generated.
+/// This is the case if the BSet implements the [SetItem]-trait, so here we generically implement
+/// the pow-function for any struct that implements [Set] and [SetItem]
+/// (In theory, this would then automatically extend to BRelations as well, if we implement the traits there)
 impl<const SETLEN: usize, const ITEMVARS: usize , I> PowAble<SETLEN, ITEMVARS> for I
     where I: Set<SETLEN> + SetItem<ITEMVARS>{
 
-    //Self = BSet<SOCKET>
-    //SETLEN = 2
-    //ITEMVARS = 4
-
     fn pow(&self) -> BSet<Self, ITEMVARS> {
         let mut result = BSet::<Self, ITEMVARS>::empty();
         for idx in 0..ITEMVARS {
@@ -187,15 +221,11 @@ impl<I: SetItem<SIZE>, const SIZE: usize> Iterator for BSetIter<I, SIZE> {
     }
 }
 
-/*
-impl<I: SetItem<SIZE> + PowEnumRepresented<SIZE>, const SIZE: usize> BSet<I, SIZE> {
-    pub const fn to_idx(&self) -> usize {
-        I::SetRepr::
-    }
-}
-*/
-
-// cannot make this const in rust yet, since we can't have const fns in traits
+/// Macro to simplify the creation of [Bset]s.
+/// Originally, this was supposed to only use constant expressions, so that
+/// these could be evaluated at compile-time. However, in rust it is currently
+/// not possible to define trait-functions as const, which would be necessary to make this
+/// work generically.
 #[macro_export]
 macro_rules! bset {
     ($set_type:ty$(, $e:expr )* ) => {
@@ -207,4 +237,4 @@ macro_rules! bset {
             BSet::<$set_type, { <$set_type>::VARIANTS }>::const_from_arr(__temp_gen_arr__)
         }
     };
-}
\ No newline at end of file
+}
diff --git a/src/main/java/de/hhu/stups/codegenerator/CodeGenerator.java b/src/main/java/de/hhu/stups/codegenerator/CodeGenerator.java
index 6abe8d212..7734ed558 100755
--- a/src/main/java/de/hhu/stups/codegenerator/CodeGenerator.java
+++ b/src/main/java/de/hhu/stups/codegenerator/CodeGenerator.java
@@ -77,6 +77,7 @@ public class CodeGenerator {
 		String serverLink = cmd.getOptionValue("sl") == null ? "." : cmd.getOptionValue("sl");
 		String simulationFile = cmd.getOptionValue("sim") == null ? "" : cmd.getOptionValue("sim");
 		String addition = cmd.getOptionValue("a");
+		boolean embedded = cmd.hasOption("e");
 
 		checkPath(path);
 		checkIntegerRange(useBigInteger, minint, maxint);
@@ -87,7 +88,7 @@ public class CodeGenerator {
 		if(forVisualisation && mode != GeneratorMode.TS) {
 			throw new CodeGenerationException("Generating a visualisation is only supported for TypeScript");
 		}
-		codeGenerator.generate(path, mode, useBigInteger, minint, maxint, deferredSetSize, forModelChecking, useConstraintSolving, true, addition, false, forVisualisation, visualisationFile, serverLink);
+		codeGenerator.generate(path, mode, useBigInteger, minint, maxint, deferredSetSize, forModelChecking, useConstraintSolving, true, addition, false, forVisualisation, visualisationFile, serverLink, embedded);
 
 		if(!simulationFile.isEmpty()) {
 			SimulationRewriter.rewriteConfigurationFromJSON(new File(simulationFile), new File(simulationFile.replaceAll(".json", "_new.json")));
@@ -97,6 +98,7 @@ public class CodeGenerator {
 	private static CommandLine processArgs(String[] args) {
 		options = new Options();
 		options.addOption("l", "language", true, "Target Language");
+		options.addOption("e", "embedded", false, "Toggle embedded code generation (no std)");
 		options.addOption("bi", "big_integer", true, "Use Big Integer");
 		options.addOption("min", "minint", true, "MININT");
 		options.addOption("max", "maxint", true, "MAXINT");
@@ -114,7 +116,7 @@ public class CodeGenerator {
 			return parser.parse(options, args);
 		} catch (ParseException e) {
 			System.out.println(e.getMessage());
-			new HelpFormatter().printHelp("{-l <language> -bi <use_big_integer> -min <minint> -max <maxint> -dss <deferred_set_size> -cs <use_constraint_solving> -mc <forModelChecking> -f <filename> -v <visualisation> -a <additionalMain>} | -sim <simb_file>", options);
+			new HelpFormatter().printHelp("{-l <language> [-e] -bi <use_big_integer> -min <minint> -max <maxint> -dss <deferred_set_size> -cs <use_constraint_solving> -mc <forModelChecking> -f <filename> -v <visualisation> -a <additionalMain>} | -sim <simb_file>", options);
 		}
 		return null;
 	}
@@ -141,9 +143,7 @@ public class CodeGenerator {
 			mode = GeneratorMode.PL;
 		} else if("rs".equals(languageOption)) {
 			mode = GeneratorMode.RS;
-		} else if("rs_e".equals(languageOption)) {
-		    mode = GeneratorMode.RS_E;
-	    } else {
+		} else {
 			throw new RuntimeException(String.format("Wrong argument '%s' for language (must be java, python, c, cpp, clojure, ts, rs)", languageOption));
 		}
 		return mode;
@@ -219,15 +219,15 @@ public class CodeGenerator {
 														 boolean isMain, String addition, boolean isIncludedMachine,
 														 boolean forVisualisation,
 														 String visualisationFile,
-							   							 String serverLink) throws CodeGenerationException, IOException {
+							   							 String serverLink, boolean embedded) throws CodeGenerationException, IOException {
 		if(isMain) {
 			paths.clear();
 		}
 
 		BProject project = parseProject(path);
 		Path additionPath = Paths.get(path.getParent().toString(), addition != null ? addition: "");
-		machineReferenceGenerator.generateIncludedMachines(project, path, mode, useBigInteger, minint, maxint, deferredSetSize, forModelChecking, useConstraintSolving, forVisualisation, serverLink);
-		paths.add(generateCode(path, mode, useBigInteger, minint, maxint, deferredSetSize, forModelChecking, useConstraintSolving, project.getMainMachine(), addition != null ? additionPath : null, isIncludedMachine, forVisualisation, visualisationFile, project, serverLink));
+		machineReferenceGenerator.generateIncludedMachines(project, path, mode, useBigInteger, minint, maxint, deferredSetSize, forModelChecking, useConstraintSolving, forVisualisation, serverLink, embedded);
+		paths.add(generateCode(path, mode, useBigInteger, minint, maxint, deferredSetSize, forModelChecking, useConstraintSolving, project.getMainMachine(), addition != null ? additionPath : null, isIncludedMachine, forVisualisation, visualisationFile, project, serverLink, embedded));
 		return paths;
 	}
 
@@ -238,10 +238,10 @@ public class CodeGenerator {
 							  String minint, String maxint, String deferredSetSize,
 							  boolean forModelChecking, boolean useConstraintSolving, MachineNode node,
 							  Path addition, boolean isIncludedMachine, boolean forVisualisation, String visualisationFile,
-							  BProject project, String serverLink) throws IOException {
+							  BProject project, String serverLink, boolean embedded) throws IOException {
 		MachineGenerator generator =
 				new MachineGenerator(mode, useBigInteger, minint, maxint, deferredSetSize, forModelChecking,
-									useConstraintSolving, addition, isIncludedMachine, forVisualisation, serverLink);
+									useConstraintSolving, addition, isIncludedMachine, forVisualisation, serverLink, embedded);
 		machineReferenceGenerator.updateNameHandler(generator);
 		machineReferenceGenerator.updateDeclarationGenerator(generator);
 		machineReferenceGenerator.updateRecordStructGenerator(generator);
@@ -320,7 +320,7 @@ public class CodeGenerator {
 	/*
 	* This function executes parsing and semantic checking on a project
 	*/
-	private BProject parseProject(Path path) throws CodeGenerationException {
+	public static BProject parseProject(Path path) throws CodeGenerationException {
 		BProject project;
 		try {
 			project = Antlr4BParser.createBProjectFromMainMachineFile(path.toFile());
diff --git a/src/main/java/de/hhu/stups/codegenerator/CodeGeneratorUtils.java b/src/main/java/de/hhu/stups/codegenerator/CodeGeneratorUtils.java
index 7a1470c81..1b5d804c5 100644
--- a/src/main/java/de/hhu/stups/codegenerator/CodeGeneratorUtils.java
+++ b/src/main/java/de/hhu/stups/codegenerator/CodeGeneratorUtils.java
@@ -28,6 +28,7 @@ public class CodeGeneratorUtils {
     private static final STGroup RS_E_GROUP;
 
     private static final Map<GeneratorMode, STGroup> TEMPLATE_MAP = new HashMap<>();
+    private static final Map<GeneratorMode, STGroup> TEMPLATE_MAP_EMBEDDED = new HashMap<>();
 
     static {
         JAVA_GROUP = new STGroupFile("de/hhu/stups/codegenerator/JavaTemplate.stg");
@@ -49,10 +50,11 @@ public class CodeGeneratorUtils {
         TEMPLATE_MAP.put(TS, TS_GROUP);
         TEMPLATE_MAP.put(PL, PL_GROUP);
         TEMPLATE_MAP.put(RS, RS_GROUP);
-        TEMPLATE_MAP.put(RS_E, RS_E_GROUP);
+        TEMPLATE_MAP_EMBEDDED.put(RS, RS_E_GROUP);
     }
 
-    public static STGroup getGroup(GeneratorMode mode) {
-        return TEMPLATE_MAP.get(mode);
+    public static STGroup getGroup(GeneratorMode mode, boolean embedded) {
+        if (!embedded) return TEMPLATE_MAP.get(mode);
+        else return TEMPLATE_MAP_EMBEDDED.get(mode);
     }
 }
diff --git a/src/main/java/de/hhu/stups/codegenerator/GeneratorMode.java b/src/main/java/de/hhu/stups/codegenerator/GeneratorMode.java
index 84477466d..8b6a96bc6 100755
--- a/src/main/java/de/hhu/stups/codegenerator/GeneratorMode.java
+++ b/src/main/java/de/hhu/stups/codegenerator/GeneratorMode.java
@@ -2,5 +2,5 @@ package de.hhu.stups.codegenerator;
 
 
 public enum GeneratorMode {
-    JAVA, C, CPP, PY, CLJ, TS, HTML, JS, PL, RS, RS_E
+    JAVA, C, CPP, PY, CLJ, TS, HTML, JS, PL, RS
 }
diff --git a/src/main/java/de/hhu/stups/codegenerator/definitions/SetDefinition.java b/src/main/java/de/hhu/stups/codegenerator/definitions/SetDefinition.java
index 6e7e702e4..6751cc8a1 100644
--- a/src/main/java/de/hhu/stups/codegenerator/definitions/SetDefinition.java
+++ b/src/main/java/de/hhu/stups/codegenerator/definitions/SetDefinition.java
@@ -1,6 +1,8 @@
 package de.hhu.stups.codegenerator.definitions;
 
 import de.prob.parser.ast.types.BType;
+import de.prob.parser.ast.types.SetType;
+import org.stringtemplate.v4.ST;
 
 import java.util.ArrayList;
 import java.util.HashMap;
@@ -10,28 +12,48 @@ import java.util.function.Function;
 import java.util.stream.Collectors;
 import java.util.stream.IntStream;
 
+/**
+ * setType = POW(SomeSet) <=> elements : SomeSet
+ * represents every subset of {@code setType}
+ */
 public class SetDefinition {
 
     private String name;
     private final BType setType;
     private final List<String> elements;
+
+    private boolean isConstant = false;
     private List<List<String>> subSets = null;
     private List<boolean[]> subSetVecs = null;
+    private Map<String, boolean[]> elementToBitArr = null;
 
     public SetDefinition(BType setType, List<String> elements) {
         this.setType = setType;
         this.elements = elements;
     }
 
+    public SetDefinition(BType setType, List<String> elements, Map<String, boolean[]> elementToBitArr) {
+        this.setType = setType;
+        this.elements = elements;
+        this.elementToBitArr = elementToBitArr;
+    }
+
     public void setVariations() {
+        throw new RuntimeException("should variation generation be done here?");
+    }
+
+    public SetDefinition getPowSetDefinition(ST setElementNameGenerator) {
         int maxCard = elements.size();
         //TODO: limit may become configurable?
         if (maxCard >= 12) throw new RuntimeException(String.format("Set %s is too large with its size of 2^%d", setType.toString(), maxCard));
+
         final int variantCount = (1 << maxCard);
-        subSets = new ArrayList<>(variantCount);
-        subSetVecs = new ArrayList<>(variantCount);
-        subSets.add(0, new ArrayList<>());
-        subSetVecs.add(0, new boolean[maxCard]);
+        List<String> powElements = new ArrayList<>(variantCount);
+        String emptySet = elementSetToSetElement(setElementNameGenerator, new ArrayList<>());
+        powElements.add(emptySet);
+        Map<String, boolean[]> powElementToBitArr = new HashMap<>();
+        powElementToBitArr.put(emptySet, new boolean[maxCard]);
+
         for (int i = 1; i < variantCount; i++) { //i is current subset as binary
             ArrayList<String> currentSubSet = new ArrayList<>(maxCard);
             boolean[] currentBitVec = new boolean[maxCard];
@@ -41,9 +63,18 @@ public class SetDefinition {
                     currentBitVec[j] = true;
                 }
             }
-            subSets.add(i, currentSubSet);
-            subSetVecs.add(i, currentBitVec);
+            String elementName = elementSetToSetElement(setElementNameGenerator, currentSubSet);
+            powElements.add(elementName);
+            powElementToBitArr.put(elementName, currentBitVec);
         }
+
+        return new SetDefinition(new SetType(this.setType), powElements, powElementToBitArr);
+    }
+
+    private String elementSetToSetElement(ST setElementNameGenerator, List<String> elementSet) {
+        setElementNameGenerator.remove("elements");
+        setElementNameGenerator.add("elements", elementSet);
+        return setElementNameGenerator.render();
     }
 
     public String getName() { return this.name; }
@@ -52,6 +83,18 @@ public class SetDefinition {
     public BType getSetType() { return this.setType; }
 
     public List<String> getElements() { return this.elements; }
+    public void addElement(String element, boolean[] bitArr) {
+        if (!this.elements.contains(element)) {
+            this.elements.add(element);
+            this.elementToBitArr.put(element, bitArr);
+        }
+    }
+
+    public boolean isConstant() { return this.isConstant; }
+    public void makeConstant() {
+        this.isConstant = true;
+        this.elementToBitArr = new HashMap<>();
+    }
     public List<List<String>> getSubSets() {
         if (subSets == null) setVariations();
         return this.subSets;
@@ -61,6 +104,10 @@ public class SetDefinition {
         return listIndexed(elements);
     }
 
+    public Map<Integer, boolean[]> bitArrIndexed() {
+        return elementsIndexed().keySet().stream().collect(Collectors.toMap(Function.identity(), idx -> elementToBitArr.get(elements.get(idx))));
+    }
+
     public Map<Integer, List<String>> subSetsIndexed() { return listIndexed(getSubSets()); }
 
     public Map<Integer, boolean[]> subSetVecsIndexed() {
diff --git a/src/main/java/de/hhu/stups/codegenerator/definitions/SetDefinitions.java b/src/main/java/de/hhu/stups/codegenerator/definitions/SetDefinitions.java
index 84e3804a6..11fd571d2 100644
--- a/src/main/java/de/hhu/stups/codegenerator/definitions/SetDefinitions.java
+++ b/src/main/java/de/hhu/stups/codegenerator/definitions/SetDefinitions.java
@@ -16,6 +16,8 @@ public class SetDefinitions {
         this.relNameGenerator = typeNameTemplate;
     }
 
+    public int size() { return this.setDefinitions.size(); }
+
     public void addDefinition(SetDefinition definition) {
         if (!containsDefinition(definition.getSetType())) {
             setDefinitions.put(definition.getSetType().toString(), definition);
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 8dc24cd83..47d42d725 100644
--- a/src/main/java/de/hhu/stups/codegenerator/generators/DeclarationGenerator.java
+++ b/src/main/java/de/hhu/stups/codegenerator/generators/DeclarationGenerator.java
@@ -2,7 +2,6 @@ package de.hhu.stups.codegenerator.generators;
 
 
 import de.hhu.stups.codegenerator.analyzers.DeferredSetAnalyzer;
-import de.hhu.stups.codegenerator.definitions.EnumType;
 import de.hhu.stups.codegenerator.definitions.SetDefinition;
 import de.hhu.stups.codegenerator.definitions.SetDefinitions;
 import de.hhu.stups.codegenerator.handlers.NameHandler;
@@ -123,7 +122,7 @@ public class DeclarationGenerator {
     */
     public String generateConstantDeclaration(DeclarationNode constant) {
         ST declaration = currentGroup.getInstanceOf("constant_declaration");
-        TemplateHandler.add(declaration, "type", typeGenerator.generate(constant.getType()));
+        TemplateHandler.add(declaration, "type", typeGenerator.generate(constant.getType(), true));
         TemplateHandler.add(declaration, "identifier", nameHandler.handleIdentifier(constant.getName(), NameHandler.IdentifierHandlingEnum.FUNCTION_NAMES));
         return declaration.render();
     }
@@ -249,10 +248,7 @@ public class DeclarationGenerator {
                 .map(element -> nameHandler.handleEnum(element.getName(), node.getElements().stream().map(DeclarationNode::getName).collect(Collectors.toList())))
                 .collect(Collectors.toList());
         TemplateHandler.add(enumDeclaration, "enums", enums);
-
-        //SetDefinition setDef = new SetDefinition(new EnumeratedSetElementType(enumName, null), enums);
-        //setDef.setName(enumName);
-        //setDefinitions.addDefinition(setDef);
+        typeGenerator.addSetDefinition(((SetType)node.getSetDeclarationNode().getType()).getSubType());
         Map<Integer, String> enumsCounted = enums.stream().collect(Collectors.toMap(enums::indexOf, Function.identity()));
         TemplateHandler.add(enumDeclaration, "enumsCounted", enumsCounted);
         TemplateHandler.add(enumDeclaration, "exprCount", machineGenerator.getAndIncCurrentExpressionCount());
@@ -278,6 +274,7 @@ public class DeclarationGenerator {
     public List<String> generateSetDefinitions() {
         return setDefinitions.getSetDefinitions().map(def -> {
             if (def.getSetType() instanceof CoupleType) return generateRelationDefinition(def);
+            else if (def.getSetType() instanceof EnumeratedSetElementType) return ""; //TODO?
             else return generateSetDefinition(def);
         }).collect(Collectors.toList());
     }
@@ -285,11 +282,19 @@ public class DeclarationGenerator {
     private String generateSetDefinition(SetDefinition setDefinition) {
         ST declTemplate = currentGroup.getInstanceOf("enum_set_declaration");
         SetType setType = (SetType) setDefinition.getSetType();
+        Map<Integer, boolean[]> idxToBitArr = setDefinition.bitArrIndexed();
         declTemplate.add("name", generateSetEnumName(setType));
         declTemplate.add("elementType", generateSetEnumName(setType.getSubType()));
-        declTemplate.add("elementVariantsCount", setDefinition.getElements().size());
-        declTemplate.add("idx2elements", setDefinition.subSetsIndexed());
-        declTemplate.add("idx2bools", setDefinition.subSetVecsIndexed());
+        declTemplate.add("elementVariantsCount", idxToBitArr.get(0).length);
+        declTemplate.add("idx2elements", setDefinition.elementsIndexed());
+        declTemplate.add("idx2bools", idxToBitArr);
+
+        BType subType = ((SetType) setDefinition.getSetType()).getSubType();
+        if (subType instanceof CoupleType) {
+            declTemplate.add("leftType", typeGenerator.generate(((CoupleType) subType).getLeft()));
+            declTemplate.add("rightType", typeGenerator.generate(((CoupleType) subType).getRight()));
+        }
+
         return declTemplate.render();
     }
 
@@ -308,6 +313,10 @@ public class DeclarationGenerator {
         if (type instanceof BoolType) return "BOOL"; //TODO?
 
         SetDefinition setDef = setDefinitions.getDefinition(type);
+        if (setDef == null) {
+            setDef = new SetDefinition(type, new ArrayList<>()); //TODO?
+            if (setDef.isConstant()) setDef.makeConstant();
+        }
         if (setDef.getName() != null) return setDef.getName();
         String result;
         if(type instanceof CoupleType) {
@@ -334,7 +343,6 @@ public class DeclarationGenerator {
     */
     public String visitEnumeratedSetDeclarationNode(EnumeratedSetDeclarationNode node, String templateName) {
         BType setType = node.getSetDeclarationNode().getType();
-        this.typeGenerator.addSetDefinition(setType);
         importGenerator.addImport(setType);
         ST setDeclaration = currentGroup.getInstanceOf(templateName);
         String type = nameHandler.handleIdentifier(node.getSetDeclarationNode().getName(), NameHandler.IdentifierHandlingEnum.FUNCTION_NAMES);
diff --git a/src/main/java/de/hhu/stups/codegenerator/generators/ExpressionGenerator.java b/src/main/java/de/hhu/stups/codegenerator/generators/ExpressionGenerator.java
index dc146905b..45c8a7080 100644
--- a/src/main/java/de/hhu/stups/codegenerator/generators/ExpressionGenerator.java
+++ b/src/main/java/de/hhu/stups/codegenerator/generators/ExpressionGenerator.java
@@ -2,6 +2,8 @@ package de.hhu.stups.codegenerator.generators;
 
 
 import de.hhu.stups.codegenerator.GeneratorMode;
+import de.hhu.stups.codegenerator.definitions.SetDefinition;
+import de.hhu.stups.codegenerator.definitions.SetDefinitions;
 import de.hhu.stups.codegenerator.handlers.IterationConstructHandler;
 import de.hhu.stups.codegenerator.handlers.NameHandler;
 import de.hhu.stups.codegenerator.handlers.TemplateHandler;
@@ -33,13 +35,7 @@ import de.prob.parser.ast.types.UntypedType;
 import org.stringtemplate.v4.ST;
 import org.stringtemplate.v4.STGroup;
 
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
+import java.util.*;
 import java.util.stream.Collectors;
 
 import static de.prob.parser.ast.nodes.expression.ExpressionOperatorNode.ExpressionOperator.BOOL;
@@ -175,10 +171,12 @@ public class ExpressionGenerator {
 
     private final IterationConstructHandler iterationConstructHandler;
 
+    private SetDefinitions setDefinitions;
+
     public ExpressionGenerator(final GeneratorMode mode, final STGroup currentGroup, final MachineGenerator machineGenerator, boolean useBigInteger, String minint, String maxint, final NameHandler nameHandler,
                                final ImportGenerator importGenerator, final DeclarationGenerator declarationGenerator,
                                final IdentifierGenerator identifierGenerator, final TypeGenerator typeGenerator,
-                               final IterationConstructHandler iterationConstructHandler, final RecordStructGenerator recordStructGenerator) {
+                               final IterationConstructHandler iterationConstructHandler, final RecordStructGenerator recordStructGenerator, SetDefinitions setDefinitions) {
         this.mode = mode;
         this.currentGroup = currentGroup;
         this.machineGenerator = machineGenerator;
@@ -193,6 +191,7 @@ public class ExpressionGenerator {
         this.iterationConstructHandler = iterationConstructHandler;
         this.iterationConstructHandler.setExpressionGenerator(this);
         this.recordStructGenerator = recordStructGenerator;
+        this.setDefinitions = setDefinitions;
     }
 
     /*
@@ -434,6 +433,7 @@ public class ExpressionGenerator {
             return generateBoolean(operator);
         } else if(node.getOperator() == SET_ENUMERATION) {
             List<String> expressionList = node.getExpressionNodes().stream().map(this::visitExprNode).collect(Collectors.toList());
+            addElementToConstSet(node);
             return generateSetEnumeration(node.getType(), expressionList);
         } else if(node.getOperator() == SEQ_ENUMERATION) {
             List<String> expressionList = node.getExpressionNodes().stream().map(this::visitExprNode).collect(Collectors.toList());
@@ -474,6 +474,57 @@ public class ExpressionGenerator {
         throw new RuntimeException("Given operator is not implemented: " + node.getOperator());
     }
 
+    private void addElementToConstSet(ExprNode expr) {
+        if (!(expr.getType() instanceof SetType)) return;
+        BType subType = ((SetType) expr.getType()).getSubType();
+        typeGenerator.addSetDefinition(subType, true); //making sure that a setDef for this type exists
+        SetDefinition setDef = this.setDefinitions.getDefinition(subType);
+        if (!setDef.isConstant()) return;
+        if (expr instanceof ExpressionOperatorNode) {
+            ExpressionOperatorNode opNode = (ExpressionOperatorNode) expr;
+            switch (opNode.getOperator()) {
+                case SET_ENUMERATION:
+                    opNode.getExpressionNodes().stream().forEach(this::getExprAsElementString);
+                    break;
+                case COUPLE:
+                    ST relElementGenerator = currentGroup.getInstanceOf("relation_element_name");
+                    relElementGenerator.add("leftElement", getExprAsElementString(opNode.getExpressionNodes().get(0)));
+                    relElementGenerator.add("rightElement", getExprAsElementString(opNode.getExpressionNodes().get(1)));
+                    //TODO: setDef.addElement(relElementGenerator.render());
+                    break;
+            }
+        }
+    }
+
+    private String getExprAsElementString(ExprNode exprNode) {
+        if (exprNode instanceof IdentifierExprNode) {
+            return ((IdentifierExprNode)exprNode).getName();
+        }
+        if (exprNode instanceof ExpressionOperatorNode) {
+            ExpressionOperatorNode opNode = (ExpressionOperatorNode) exprNode;
+            if (opNode.getOperator() == SET_ENUMERATION) {
+                BType subtype = ((SetType)opNode.getType()).getSubType();
+                typeGenerator.addSetDefinition(subtype, true); //making sure that a setDef for this type exists
+                List<String> subElements = setDefinitions.getDefinition(subtype).getElements();
+                boolean[] bitArr = new boolean[subElements.size()];
+                List<String> elements = opNode.getExpressionNodes().stream().map(this::getExprAsElementString).sorted(Comparator.comparingInt(subElements::indexOf)).collect(Collectors.toList());
+                elements.forEach(e -> bitArr[subElements.indexOf(e)] = true);
+                ST setElementName = currentGroup.getInstanceOf("set_element_name");
+                setElementName.add("elements", elements);
+                String result = setElementName.render();
+                this.setDefinitions.getDefinition(opNode.getType()).addElement(result, bitArr);
+                return result;
+            }
+            if (opNode.getOperator() == COUPLE) {
+                ST relElementNameGenerator =currentGroup.getInstanceOf("relation_element_name");
+                relElementNameGenerator.add("leftElement", getExprAsElementString(opNode.getExpressionNodes().get(0)));
+                relElementNameGenerator.add("rightElement", getExprAsElementString(opNode.getExpressionNodes().get(1)));
+                return relElementNameGenerator.render();
+            }
+        }
+        throw new RuntimeException(String.format("Cannot convert Expression %s to set-element!", exprNode.toString()));
+    }
+
     /*
     * This function generates code for an unary expression with the given operator and arguments.
     */
@@ -553,6 +604,7 @@ public class ExpressionGenerator {
                 operatorName = "max";
                 break;
             case POW:
+                //TODO: embedded: make sure to generate setDef!
                 operatorName = "pow";
                 break;
             case POW1:
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 035bf91b4..15e8c808e 100755
--- a/src/main/java/de/hhu/stups/codegenerator/generators/MachineGenerator.java
+++ b/src/main/java/de/hhu/stups/codegenerator/generators/MachineGenerator.java
@@ -149,9 +149,9 @@ public class MachineGenerator implements AbstractVisitor<String, Void> {
 
 	public MachineGenerator(GeneratorMode mode, boolean useBigInteger, String minint, String maxint, String deferredSetSize,
 							boolean forModelChecking, boolean useConstraintSolving, Path addition, boolean isIncludedMachine,
-							boolean forVisualisation, String serverLink) {
+							boolean forVisualisation, String serverLink, boolean embedded) {
 		this.mode = mode;
-		this.currentGroup = CodeGeneratorUtils.getGroup(mode);
+		this.currentGroup = CodeGeneratorUtils.getGroup(mode, embedded);
 		this.forModelChecking = forModelChecking;
 		this.forVisualisation = forVisualisation;
 		this.useBigInteger = useBigInteger;
@@ -177,7 +177,7 @@ public class MachineGenerator implements AbstractVisitor<String, Void> {
 		this.recordStructGenerator = new RecordStructGenerator(currentGroup, this, typeGenerator, importGenerator, nameHandler);
 		this.declarationGenerator = new DeclarationGenerator(currentGroup, this, typeGenerator, importGenerator, nameHandler, deferredSetAnalyzer, setDefinitions);
 		this.expressionGenerator = new ExpressionGenerator(mode, currentGroup, this, useBigInteger, minint, maxint, nameHandler, importGenerator,
-				declarationGenerator, identifierGenerator, typeGenerator, iterationConstructHandler, recordStructGenerator);
+				declarationGenerator, identifierGenerator, typeGenerator, iterationConstructHandler, recordStructGenerator, setDefinitions);
 		this.predicateGenerator = new PredicateGenerator(currentGroup, this, nameHandler, importGenerator, iterationConstructHandler, infiniteSetGenerator);
 		this.lambdaFunctionGenerator = new LambdaFunctionGenerator(currentGroup, expressionGenerator, predicateGenerator, typeGenerator, declarationGenerator);
 		this.recordStructAnalyzer = new RecordStructAnalyzer(recordStructGenerator);
@@ -451,6 +451,8 @@ public class MachineGenerator implements AbstractVisitor<String, Void> {
 		return expressionGenerator.visitExprNode(node);
 	}
 
+//	public String visitExprNode(ExprNode node, Void expected, )
+
 	@Override
 	public String visitExprOperatorNode(ExpressionOperatorNode node, Void expected) {
 		return expressionGenerator.visitExprOperatorNode(node);
@@ -811,4 +813,6 @@ public class MachineGenerator implements AbstractVisitor<String, Void> {
 		return serverLink;
 	}
 
+	public SetDefinitions getSetDefinitions() { return this.setDefinitions; }
+
 }
diff --git a/src/main/java/de/hhu/stups/codegenerator/generators/MachineReferenceGenerator.java b/src/main/java/de/hhu/stups/codegenerator/generators/MachineReferenceGenerator.java
index 2ad3552b9..bc547e916 100755
--- a/src/main/java/de/hhu/stups/codegenerator/generators/MachineReferenceGenerator.java
+++ b/src/main/java/de/hhu/stups/codegenerator/generators/MachineReferenceGenerator.java
@@ -32,11 +32,11 @@ public class MachineReferenceGenerator {
     /*
     * This function generates code for all included machines from the given options
     */
-    public void generateIncludedMachines(BProject project, Path path, GeneratorMode mode, boolean useBigInteger, String minint, String maxint, String deferredSetSize, boolean forModelChecking, boolean useConstraintSolving, boolean forVisualisation, String serverLink) throws IOException {
+    public void generateIncludedMachines(BProject project, Path path, GeneratorMode mode, boolean useBigInteger, String minint, String maxint, String deferredSetSize, boolean forModelChecking, boolean useConstraintSolving, boolean forVisualisation, String serverLink, boolean embedded) throws IOException {
         for(MachineReferenceNode referenceNode : project.getMainMachine().getMachineReferences()) {
             Path currentPath = Paths.get(path.getParent().toString(), referenceNode.getMachineName() + ".mch");
             if(!codeGenerator.getPaths().contains(currentPath)) {
-                codeGenerator.generate(currentPath, mode, useBigInteger, minint, maxint, deferredSetSize, forModelChecking, useConstraintSolving, false, null, true, forVisualisation, null, serverLink);
+                codeGenerator.generate(currentPath, mode, useBigInteger, minint, maxint, deferredSetSize, forModelChecking, useConstraintSolving, false, null, true, forVisualisation, null, serverLink, embedded);
             }
         }
     }
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 800ee8191..4bcf7290f 100644
--- a/src/main/java/de/hhu/stups/codegenerator/generators/TypeGenerator.java
+++ b/src/main/java/de/hhu/stups/codegenerator/generators/TypeGenerator.java
@@ -18,6 +18,7 @@ import de.prob.parser.ast.types.UntypedType;
 import org.stringtemplate.v4.ST;
 import org.stringtemplate.v4.STGroup;
 
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
 import java.util.function.Function;
@@ -47,10 +48,12 @@ public class TypeGenerator {
         this.declarationGenerator = null;
     }
 
-    /*
+    public String generate(BType type) { return this.generate(type, false); }
+    /**
     * This function generates code for a type with the given type and the information whether the type is generated for casting an object
-    */
-    public String generate(BType type) {
+    * @param constant: indicates if this type is used for a constant, used to optimize embedded code-generation
+    **/
+    public String generate(BType type, boolean constant) {
         if(type instanceof IntegerType) {
             return generateBInteger();
         } else if(type instanceof BoolType) {
@@ -58,7 +61,7 @@ public class TypeGenerator {
         } else if(type instanceof StringType) {
             return generateBString();
         } else if(type instanceof SetType) {
-            return generateBSet((SetType) type);
+            return generateBSet((SetType) type, constant);
         } else if(type instanceof EnumeratedSetElementType) {
             return generateEnumeratedSetElement((EnumeratedSetElementType) type);
         } else if(type instanceof DeferredSetElementType) {
@@ -125,12 +128,12 @@ public class TypeGenerator {
     /*
     * This function generates code for BSet and its subtypes from the given type
     */
-    private String generateBSet(SetType type) {
+    private String generateBSet(SetType type, boolean constant) {
         BType subType = type.getSubType();
         if(subType instanceof CoupleType) {
-            return generateBRelation((CoupleType) subType);
+            return generateBRelation((CoupleType) subType, constant);
         } else {
-            addSetDefinition(type);
+            addSetDefinition(subType, constant);
             ST template = group.getInstanceOf("set_type");
             TemplateHandler.add(template, "fromOtherMachine", false);
             if(!(subType instanceof UntypedType)) { // subType is a type other than couple type and void type
@@ -144,29 +147,48 @@ public class TypeGenerator {
     /*
     * This function generates code for the subtypes of a relation from the given couple type
     */
-    private String generateBRelation(CoupleType type) {
-        addSetDefinition(type);
+    private String generateBRelation(CoupleType type, boolean constant) {
         ST template = group.getInstanceOf("relation_type");
-        TemplateHandler.add(template, "leftType", generate(type.getLeft()));
+        TemplateHandler.add(template, "leftType", generate(type.getLeft(), constant));
+        addSetDefinition(type.getLeft(), constant);
         TemplateHandler.add(template, "leftName", declarationGenerator.generateSetEnumName(type.getLeft()));
-        TemplateHandler.add(template, "rightType", generate(type.getRight()));
+        TemplateHandler.add(template, "rightType", generate(type.getRight(), constant));
+        addSetDefinition(type.getRight(), constant);
         TemplateHandler.add(template, "rightName", declarationGenerator.generateSetEnumName(type.getRight()));
         return template.render();
     }
 
-    public void addSetDefinition(BType type) {
-        if (this.setDefinitions.containsDefinition(type)) return;
+    public SetDefinition addSetDefinition(BType type) { return this.addSetDefinition(type, false); }
+    public SetDefinition addSetDefinition(BType type, boolean constant) {
+        if (this.setDefinitions.containsDefinition(type)) return this.setDefinitions.getDefinition(type); //TODO: const check
 
         List<String> variants;
+        String name = null;
         if (type instanceof SetType) {
-            variants = getTypeVariants(((SetType)type).getSubType());
-        } else if(type instanceof CoupleType) {
+            if (constant) {
+                variants = new ArrayList<>();
+            } else {
+                BType subType = ((SetType) type).getSubType();
+                SetDefinition subDefinition = this.setDefinitions.getDefinition(subType);
+                if (subDefinition == null) subDefinition = addSetDefinition(subType);
+                SetDefinition result = subDefinition.getPowSetDefinition(group.getInstanceOf("set_element_name"));
+                this.setDefinitions.addDefinition(result);
+                return result;
+            }
+        } else if (type instanceof CoupleType) {
             variants = getTypeVariants(type);
+        } else if (type instanceof EnumeratedSetElementType) {
+            EnumeratedSetElementType enumType = (EnumeratedSetElementType) type;
+            variants = enumType.getElements();
+            name = nameHandler.handleIdentifier(enumType.getSetName(), NameHandler.IdentifierHandlingEnum.FUNCTION_NAMES);
         } else {
             throw new RuntimeException("cannot add setDef for type "+type);
         }
         SetDefinition setDefinition = new SetDefinition(type, variants);
+        if (constant) setDefinition.makeConstant();
+        if (name != null) setDefinition.setName(name);
         this.setDefinitions.addDefinition(setDefinition);
+        return setDefinition;
     }
 
     private List<String> getTypeVariants(BType type) {
@@ -181,14 +203,16 @@ public class TypeGenerator {
     public List<String> getSetVariants(SetType type) {
         if(!this.setDefinitions.containsDefinition(type)) {
             //TODO: try to generate missing set-types on the fly?
-            throw new RuntimeException("Could not find SetDefinition for type "+type);
-        }
+            addSetDefinition(type);
+            //throw new RuntimeException("Could not find SetDefinition for type "+type);
+        }/*
         ST setElementName = group.getInstanceOf("set_element_name");
         return this.setDefinitions.getDefinition(type).getSubSets().stream().map(subset -> {
             setElementName.remove("elements");
             setElementName.add("elements", subset);
             return setElementName.render();
-        }).collect(Collectors.toList());
+        }).collect(Collectors.toList());*/
+        return setDefinitions.getDefinition(type).getElements();
     }
 
     public List<String> getRelationVariants(CoupleType relType) {
diff --git a/src/main/resources/de/hhu/stups/codegenerator/RustTemplate_e.stg b/src/main/resources/de/hhu/stups/codegenerator/RustTemplate_e.stg
index 8c753877a..2d418f2ad 100644
--- a/src/main/resources/de/hhu/stups/codegenerator/RustTemplate_e.stg
+++ b/src/main/resources/de/hhu/stups/codegenerator/RustTemplate_e.stg
@@ -9,9 +9,9 @@ use btypes::{bset, brel};
 //use btypes::set::{BSet, SetItem, BRelation, RelItem};
 use btypes::bset::BSet;
 use btypes::bset::SetItem;
-use btypes::bset::SetEnum;
-use btypes::bset::PowEnumRepresented;
+use btypes::bset::PowSetItem;
 use btypes::brelation::BRelation;
+use btypes::brelation::RelLeftItem;
 use btypes::bboolean::BBoolean;
 use btypes::binteger::BInteger;
 
@@ -400,32 +400,51 @@ impl SetItem\<<length(enums)>\> for <name> {
     fn as_idx(&self) -> usize { self.to_idx() }
     fn from_idx(idx: usize) -> Self { Self::from_idx(idx) }
 }
+
+type set_<name> = BSet\<<name>, <length(enums)>\>;
 //set_enum_declaration done
 >>
 set_name(elementType) ::= <<
 Set<elementType>
 >>
 set_element_name(elements) ::= <<
-SET_<elements; separator="_">_TES
+SET_<elements; separator="__">_TES
 >>
 
 bool_arr(arr) ::= <<
 [<arr; separator=", ">]
 >>
 
-enum_set_declaration(name, elementType, elementVariantsCount, idx2elements, idx2bools) ::= <<
+enum_set_declaration(name, elementType, elementVariantsCount, idx2elements, idx2bools, leftType, rightType) ::= <<
 //enum_set_declaration start
 #[derive(Default, Debug, Clone, Copy)]
+// each enum value corresponds to one BSet
 pub enum <name> {
     #[default]
     <idx2elements.keys:{k | <set_element_name(idx2elements.(k))> = <k>}; separator=", \n">
 }
-type set_<elementType> = BSet\<<elementType>, <elementVariantsCount>\>;
+type set_<name> = BSet\<<if(leftType)>rel<else>set<endif>_<elementType>, <length(idx2elements)>\>;
 
-impl PowEnumRepresented\<<length(idx2elements)>, <elementVariantsCount>\> for <elementType> {
+impl PowSetItem\<<length(idx2elements)>, <elementVariantsCount>\> for <elementType> {
     type SetRepr = <name>;
+    fn arr_to_idx(set: [bool; <elementVariantsCount>]) -> usize {
+        match set {
+            <idx2bools.keys:{idx | <bool_arr(idx2bools.(idx))> => <idx>,}; separator="\n">
+            _ => panic!("Attempting to convert non-existing set to index!") // only happens if this is a const-set and code-generation missed a necessary value
+        }
+    }
+    fn idx_to_arr(idx: usize) -> [bool; <elementVariantsCount>] {
+        match idx {
+            <idx2bools.keys:{idx | <idx> => <bool_arr(idx2bools.(idx))>,}; separator="\n">
+            _ => panic!("<name> index out of range! {:?}", idx)
+        }
+    }
 }
-
+<if(leftType && rightType)>
+impl RelLeftItem\<{<leftType>::VARIANTS}, <rightType>, { <rightType>::VARIANTS}, <length(idx2elements)>, <elementVariantsCount>\> for <leftType> {
+    type RelEnum = <elementType>;
+}
+<endif>
 impl <name> {
     pub const fn to_idx(self) -> usize { self as usize }
     pub fn from_idx(idx: usize) -> Self {
@@ -441,19 +460,6 @@ impl SetItem\<<length(idx2elements)>\> for <name> {
     fn from_idx(idx: usize) -> Self { Self::from_idx(idx) }
 }
 
-impl SetEnum\<<elementVariantsCount>\> for <name> {
-    fn as_idx(set: [bool; <elementVariantsCount>]) -> usize {
-        match set {
-            <idx2bools.keys:{idx | <bool_arr(idx2bools.(idx))> => <idx>}; separator=",\n">
-        }
-    }
-    fn from_idx(idx: usize) -> [bool; <elementVariantsCount>] {
-        match idx {
-            <idx2bools.keys:{idx | <idx> => <bool_arr(idx2bools.(idx))>,}; separator="\n">
-            _ => panic!("<name> index out of range! {:?}", idx)
-        }
-    }
-}
 //enum_set_declaration done
 >>
 
@@ -467,15 +473,15 @@ relation_element_name(leftElement, rightElement) ::= <<
 >>
 relation_declaration(name, leftType, rightType, elements) ::= <<
 //relation_declaration
+<if(elements)>
 #[derive(Default, Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
 pub enum <name> {
     #[default]
     <elements.keys:{k | <elements.(k)> = <k>}; separator=", \n">
 }
-//set_def![set_<name>, <name>, <length(elements)>];
-//rel_def![set_<name>, set_<leftType>, set_<rightType>];
-type rel_<name> = BRelation\<<leftType>, { <leftType>::VARIANTS }, <rightType>, { <rightType>::VARIANTS }>;
-
+<endif>
+type rel_<name> = BRelation\<<leftType>, { <leftType>::VARIANTS }, <rightType>, { <rightType>::VARIANTS }, <length(elements)>\>;
+<if(false)>
 impl <name> {
     pub fn equal(&self, other: &<name>) -> bool { *self == *other }
     pub fn unequal(&self, other: &<name>) -> bool { *self != *other }
@@ -487,7 +493,7 @@ impl <name> {
         }
     }
 }
-
+<endif>
 //relation_declaration done
 >>
 
-- 
GitLab