diff --git a/src/c_gen.rs b/src/c_gen.rs
index 7f5c7ea..c64a0f6 100644
--- a/src/c_gen.rs
+++ b/src/c_gen.rs
@@ -1,158 +1,286 @@
 use {
-    crate::{morphism::{LdmcMorphism, LdmcPrimCMorphism}, struct_layout::{get_type_size, ObjectSize, StructLayout}},
-    laddertypes::{morphism::{Morphism, MorphismInstance}, parser::*, unparser::*, TypeDict, TypeTerm},
+    crate::{c_gen_types::{encode_morph_type_to_symbol, encode_type_to_symbol, encode_type_to_value, get_c_repr_type}, morphism::LdmcPrimMorph, struct_layout::{get_type_size, LayoutType, ObjectSize, StructLayout}}, chumsky::{chain::Chain, primitive::Container}, laddertypes::{morphism::{Morphism, MorphismInstance}, morphism_sugared::{MorphismInstance2, SugaredMorphismType}, parser::*, substitution_sugared::SugaredSubstitution, unparser::*, Substitution, SugaredEnumVariant, SugaredStructMember, SugaredTypeTerm, TypeDict, TypeTerm}, std::collections::HashMap
 };
 
-/*
-*/
-pub fn get_c_repr_kind(kind: String) -> Option<String> {
-    match kind.as_str() {
-        "ℤ" => Some("uint64_t".into()),
-        _ => None
-    }
-}
 
-/* for a given ladder type `t`, get the corresponding C type
- */
-pub fn get_c_repr_type(dict: &mut impl TypeDict, t: laddertypes::TypeTerm, skip_pointer: bool) -> Option<String> {
-    let lnf = t.normalize().decurry().get_lnf_vec();
 
-    match lnf.last() {
-        Some(t) => {
-            if t == &dict.parse("Byte").expect("parse")
-            || t == &dict.parse("native.UInt8").expect("parse")
-            || t == &dict.parse("<StaticLength 8 Bit>").expect("parse")
-            {
-                Some("uint8_t".into())
-            } else if t == &dict.parse("native.UInt16").expect("parse") {
-                Some("uint16_t".into())
-            } else if t == &dict.parse("native.UInt32").expect("parse") {
-                Some("uint32_t".into())
-            } else if t == &dict.parse("native.UInt64").expect("parse") {
-                Some("uint64_t".into())
-            } else if t == &dict.parse("native.Float").expect("parse") {
-                Some("float".into())
-            } else if t == &dict.parse("native.Double").expect("parse") {
-                Some("double".into())
+
+
+
+
+impl LdmcPrimMorph {
+    pub fn instantiated_symbol_name(&self, dict: &mut impl TypeDict, σ: &impl SugaredSubstitution) -> String {
+        let mut s = self.symbol.clone();
+        for (k_id,v) in self.type_args.iter() {
+            if let Some(val_trm) = σ.get(k_id) {
+                if let laddertypes::TypeID::Var(var_id) = k_id {
+                    let name = dict.get_varname(*var_id).unwrap();
+                    let val_str = encode_type_to_symbol(dict, &val_trm);
+                    s.push_str(&format!("_{}_{}", name, val_str));
+                }
             } else {
-                match t {
-                    laddertypes::TypeTerm::App(args) => {
-                        if args[0] == laddertypes::TypeTerm::TypeID(dict.get_typeid(&"LengthPrefix".into()).unwrap())
-                        {
-                            let length_c_type : String = get_c_repr_type(dict, args[1].clone(), false)?;
-                            let item_c_type : String = get_c_repr_type(dict, args[2].clone(), false)?;
-
-                            match length_c_type.as_str() {
-                                "uint8_t" |
-                                "uint16_t" |
-                                "uint32_t" |
-                                "uint64_t" => {}
-                                _ => {
-                                    eprintln!("invalid length type!");
-                                    return None;
-                                }
-                            }
-                            match item_c_type.as_str() {
-                                "uint8_t" |
-                                "uint16_t" |
-                                "uint32_t" |
-                                "uint64_t" => {}
-                                _ => {
-                                    eprintln!("invalid item type!");
-                                    return None;
-                                }
-                            }
-
-                            Some(format!("LengthPrefix_{}_Array_{}", length_c_type, item_c_type))
-                        }
-                        else if args[0] == laddertypes::TypeTerm::TypeID(dict.get_typeid(&"ValueTerminated".into()).unwrap())
-                        {
-                            let _delim_val = args[1].clone();
-                            let c_type = get_c_repr_type(dict, args[2].clone(), false)?;
-                            if skip_pointer {
-                                Some(c_type)
-                            } else {
-                                Some(format!("{} *", c_type))
-                            }
-                        }
-                        else if args[0] == laddertypes::TypeTerm::TypeID(dict.get_typeid(&"MsbCont".into()).unwrap())
-                        {
-                            let c_type = get_c_repr_type(dict, args[1].clone(), false)?;
-                            if skip_pointer {
-                                Some(c_type)
-                            } else {
-                                Some(format!("{} *", c_type))
-                            }
-                        }
-                        else {
-
-                            if let Some(layout) = StructLayout::parse(dict, t.clone()) {
-                                let mut c_type = String::from("struct {\n");
-
-                                for (field_name, field_type) in layout.members.iter() {
-                                    let field_c_type = get_c_repr_type(dict, field_type.clone(), false).expect("");
-                                    c_type.push_str(&format!("    {} {};\n",
-                                        field_c_type,
-                                        field_name
-                                    ));
-                                }
-
-                                c_type.push_str("}");
-                                Some(c_type)
-                            } else {
-                                None
-                            }
-                        }
-                    }
-
-                    _ => None
+                if let laddertypes::TypeID::Var(var_id) = k_id {
+                    let k = dict.get_varname(*var_id).unwrap();
+                    s.push_str(&format!("_{:?}_MISSING", k));
+                    eprintln!("INCOMPLETE MORPHISM INSTANTIATION, missing type parameter {} ({})", k, var_id);
                 }
             }
         }
-        None => None
+        s
+    }
+
+    pub fn expected_c_type_signature(&self, dict: &mut impl TypeDict,
+        σ: &std::collections::HashMap<laddertypes::TypeID, laddertypes::SugaredTypeTerm>
+    ) -> String {
+        format!("int {} ({} const * restrict src, {} * restrict dst);",
+            self.instantiated_symbol_name(dict, σ),
+            get_c_repr_type(dict, self.ty.src_type.clone(), true).expect("cant get c-repr type for src type"),
+            get_c_repr_type(dict, self.ty.dst_type.clone(), true).expect("cant get c-repr type for dst type"))
+    }
+
+    pub fn generate_instantiation(&self, dict: &mut impl TypeDict, σ: &impl SugaredSubstitution) -> Option<String> {
+        let mut s = String::new();
+        let src_type = self.ty.src_type.clone().apply_subst(σ).clone();
+        let dst_type = self.ty.dst_type.clone().apply_subst(σ).clone();
+
+        let symbol = encode_morph_type_to_symbol(dict, &self.ty);
+        let src_c_symbol = encode_type_to_symbol(dict, &self.ty.src_type);
+        let dst_c_symbol = encode_type_to_symbol(dict, &self.ty.dst_type);
+
+        let src_c_type = get_c_repr_type(dict, self.ty.src_type.clone(), true).expect("cant get c-repr type for src type");
+        let dst_c_type = get_c_repr_type(dict, self.ty.dst_type.clone(), true).expect("cant get c-repr type for src type");
+
+        s.push_str(&format!(r#"
+int {} ( {} const * restrict src, {} * restrict dst ) {{
+"#,
+            self.instantiated_symbol_name(dict, σ),
+            get_c_repr_type(dict, src_type, true).expect("cant get c-repr-type"),
+            get_c_repr_type(dict, dst_type, true).expect("cant get c-repr-type"),
+        ));
+        s.push_str(&self.c_source);
+        s.push_str(&format!(r#"
+    return 0;
+}}
+"#));
+        Some(s)
     }
 }
 
 
-pub fn encode_type_to_symbol(dict: &mut impl TypeDict, t: &laddertypes::TypeTerm)-> String {
-    match t {
-        laddertypes::TypeTerm::Char(c) => {
-            match c {
-                '.' => format!("_dot_"),
-                _ =>
-                format!("{}", (*c as u64))
-            }
-        },
-        laddertypes::TypeTerm::Num(n) => {
-            format!("{}", n)
+
+
+
+pub struct LdmcCTargetMorph {
+    includes: Vec< String >,
+    active_instantiations: Vec< LdmcPrimMorph >,
+}
+
+impl LdmcCTargetMorph {
+    pub fn new() -> Self {
+        LdmcCTargetMorph {
+            includes: Vec::new(),
+            active_instantiations: Vec::new()
         }
-        laddertypes::TypeTerm::TypeID(ty_id) => {
-            if let Some(name) = dict.get_typename(ty_id) {
-                format!("{}", name.replace(".", "_dot_"))
-            } else {
-                format!("")
-            }
+    }
+
+    pub fn add_instantiation(
+        &mut self,
+        dict: &mut impl TypeDict,
+        morph: MorphismInstance2<LdmcPrimMorph>,
+    ) -> Result<LdmcPrimMorph, ()> {
+        let new_inst = self.bake_morphism(dict, morph)?;
+        if ! self.active_instantiations.contains(&new_inst) {
+            self.active_instantiations.push(new_inst.clone());
         }
-        laddertypes::TypeTerm::Ladder(rs) |
-        laddertypes::TypeTerm::App(rs) => {
-            let mut s = String::new();
-            for r in rs {
-                s.push('_');
-                s.push_str(&encode_type_to_symbol(dict, r));
+        Ok(new_inst)
+    }
+
+    pub fn into_c_source(self, dict: &mut impl TypeDict) -> String {
+        let mut source = String::new();
+        for inc in self.includes {
+            source.push_str(&inc);
+        }
+
+        for m in self.active_instantiations {
+            source.push_str(&m.generate_instantiation(dict, &HashMap::new()).expect("cant create function"));
+        }
+
+        source
+    }
+
+    pub fn bake_morphism(
+        &mut self,
+        dict: &mut impl laddertypes::TypeDict,
+        morph_inst: MorphismInstance2<LdmcPrimMorph>,
+    ) -> Result<LdmcPrimMorph, ()> {
+
+        match &morph_inst {
+            MorphismInstance2::Primitive { ψ, σ, morph } => {
+                let mut c_source = String::new();
+                for (ty_id, kind) in morph.type_args.iter() {
+                    if let Some(val) = σ.get(ty_id) {
+                        eprintln!("val = {}", val.pretty(dict, 0));
+                        let type_var_value =
+                            if let Some(c_repr_type) = get_c_repr_type(dict, val.clone(), true) {
+                                c_repr_type
+                            } else {
+                                encode_type_to_value(dict, &val)
+                            };
+
+                        c_source.push_str(&format!("    #define {} {}\n", dict.get_typename(&ty_id).unwrap(), type_var_value));
+                    }
+                }
+                c_source.push_str(&morph.c_source);
+                for (ty_id, kind) in morph.type_args.iter() {
+                    c_source.push_str(&format!("\n    #undef {}", dict.get_typename(&ty_id).unwrap()));
+                }
+
+                Ok(LdmcPrimMorph{
+                    symbol: morph.instantiated_symbol_name(dict, σ),
+                    type_args: Vec::new(),
+                    ty: morph_inst.get_type(),
+                    c_source
+                })
+            },
+            MorphismInstance2::Chain { path } => {
+                let ty = morph_inst.get_type();
+                let symbol = encode_morph_type_to_symbol(dict, &ty);
+
+                let mut c_source = String::new();
+
+                if path.len() > 1 {
+                    c_source.push_str(r#"
+            uint8_t bufA[128];
+            uint8_t bufB[128];
+    "#);
+                }
+
+                for (i,morph) in path.iter().enumerate() {
+                    if let Ok(inst) = self.add_instantiation(dict, morph.clone()) {
+                        let morph_symbol = inst.instantiated_symbol_name(dict, &morph.get_subst());
+
+                        let src_c_type = get_c_repr_type(dict, ty.src_type.clone(), true).expect("cant get c-repr type for src type");
+                        let dst_c_type = get_c_repr_type(dict, ty.dst_type.clone(), true).expect("cant get c-repr type for dst type");
+
+                        let src_buf = if i == 0 { "src" } else if i%2 == 0 { "(void*)bufA" } else { "(void*)bufB" };
+                        let dst_buf = if i+1 == path.len() { "dst" } else if i%2 == 0 { "(void*)bufB" } else { "(void*)bufA" };
+
+                        c_source.push_str(&format!(r#"
+            {{
+                    {} const * restrict src = {};
+                    {} * restrict dst = {};
+                    {} ( src, dst );
+            }}"#,
+                            src_c_type, src_buf,
+                            dst_c_type, dst_buf,
+                            morph_symbol
+                        ));
+                    } else {
+                        eprintln!("failed to add instantiation of item morphism");
+                    }
+                }
+
+                Ok(LdmcPrimMorph {
+                    symbol, type_args: Vec::new(), ty,
+                    c_source
+                })
+            }
+            MorphismInstance2::MapSeq { ψ, seq_repr, item_morph } => {
+                let i = 0; // <--todo
+                self.add_instantiation(dict, item_morph.as_ref().clone());
+                if let Some(seq_repr) = seq_repr {
+
+                    dict.add_varname("LengthType".into());
+                    if let Ok(γ) = laddertypes::unification_sugared::unify(
+                        &dict.parse("<LengthPrefix LengthType>").expect("parse type template").sugar(dict),
+                        seq_repr.as_ref()
+                    ) {
+                        let length_type = γ.get(&dict.get_typeid(&"LengthType".into()).expect("")).expect("cant get LengthType");
+                        let ty = morph_inst.get_type();
+                        let symbol = encode_morph_type_to_symbol(dict, &ty);
+                        let item_morph_symbol = encode_morph_type_to_symbol(dict, &item_morph.get_type());
+
+                        let length_c_type = get_c_repr_type(dict, length_type.clone(), true).expect("cant c-repr type for array length");
+                        let src_item_c_type = get_c_repr_type(dict, item_morph.get_type().src_type, true).expect("cant c-repr type for src item");
+                        let dst_item_c_type = get_c_repr_type(dict, item_morph.get_type().dst_type, true).expect("cant c-repr type for dst item");
+                        let src_c_type = get_c_repr_type(dict, ty.src_type.clone(), true).expect("cant get c-repr type for src type");
+                        let dst_c_type = get_c_repr_type(dict, ty.dst_type.clone(), true).expect("cant get c-repr type for dst type");
+
+                        let map_fn = format!("length_prefix_{}_array_map_{}_to_{}",
+                            length_c_type, src_item_c_type, dst_item_c_type
+                        );
+
+                        let src_buf = if i%2 == 0 { "bufA" } else { "bufB" };
+                        let dst_buf = if i%2 == 0 { "bufB" } else { "bufA" };
+                        let c_source = format!(r#"
+            {{
+                    {} const * restrict src = (void*) {};
+                    {} * restrict dst = (void*) {};
+                    {} ( {}, src, dst );
+            }}"#,
+                            src_c_type, src_buf,
+                            dst_c_type, dst_buf,
+                            map_fn,
+                            item_morph_symbol,
+                        );
+
+                        Ok(LdmcPrimMorph{
+                            symbol, type_args: Vec::new(), ty,
+                            c_source
+                        })
+                    } else {
+                        eprintln!("Error: Unknown Seq- Representation!!");
+                        Err(())
+                    }
+                } else {
+                    eprintln!("Error: missing Seq- Representation!!");
+                    Err(())
+                }
+            },
+            MorphismInstance2::MapStruct { ψ, struct_repr, member_morph } => {
+                let ty = morph_inst.get_type();
+                let symbol =encode_morph_type_to_symbol(dict, &ty);
+
+                let mut c_source = String::new();
+
+                for (name, morph) in member_morph.iter() {
+                    if let Ok(inst) = self.add_instantiation(dict, morph.clone()) {
+                        c_source.push_str(
+                            &format!("
+                                {} ( &src->{}, &dst->{} );
+                            ",
+                            inst.symbol,
+                            name, name
+                        ));
+                    } else {
+                        eprintln!("failed to create morphism instantiation for struct member");
+                        return Err(());
+                    }
+                }
+
+                Ok(LdmcPrimMorph{
+                    symbol, type_args: Vec::new(), ty,
+                    c_source
+                })
+            }
+            MorphismInstance2::MapEnum { ψ, enum_repr, variant_morph } => {
+                todo!();
             }
-            s
         }
     }
 }
 
-pub fn encode_type_to_value(dict: &mut impl TypeDict, t: &laddertypes::TypeTerm) -> String {
-    dict.unparse(t)
-}
 
-
-pub fn generate_main(type_dict: &mut impl TypeDict, path: Vec<MorphismInstance<LdmcMorphism>>, src_type: TypeTerm, dst_type: TypeTerm) {
+/*
+pub fn generate_main(
+    type_dict: &mut impl TypeDict,
+    morph: MorphismInstance2<LdmcPrimMorph>,
+    src_type: TypeTerm, dst_type: TypeTerm
+) {
     let mut i = 0;
 
+
+
     /* todo: collect include files from morphism base */
     println!(r#"
 #include <stdio.h>
@@ -271,238 +399,4 @@ return 0;
 
     eprintln!("Success: generated C code");
 }
-
-impl LdmcPrimCMorphism {
-    pub fn instantiated_symbol_name(&self, dict: &mut impl TypeDict,
-        σ: &std::collections::HashMap<laddertypes::TypeID, laddertypes::TypeTerm>) -> String {
-        let mut s = self.symbol.clone();
-        for (k_id,v) in self.type_args.iter() {
-            if let Some(val_trm) = σ.get(k_id) {
-                if let laddertypes::TypeID::Var(var_id) = k_id {
-                    let name = dict.get_varname(*var_id).unwrap();
-                    let val_str = encode_type_to_symbol(dict, val_trm);
-                    s.push_str(&format!("_{}_{}", name, val_str));
-                }
-            } else {
-                if let laddertypes::TypeID::Var(var_id) = k_id {
-                    let k = dict.get_varname(*var_id).unwrap();
-                    s.push_str(&format!("_{:?}_MISSING", k));
-                    eprintln!("INCOMPLETE MORPHISM INSTANTIATION, missing {} ({})", k, var_id);
-                }
-            }
-        }
-        s
-    }
-
-    pub fn expected_c_type_signature(&self, dict: &mut impl TypeDict,
-        σ: &std::collections::HashMap<laddertypes::TypeID, laddertypes::TypeTerm>) -> String {
-        format!("int {} ({} const * restrict src, {} * restrict dst);",
-            self.instantiated_symbol_name(dict, σ),
-            get_c_repr_type(dict, self.src_type.clone(), true).expect("cant get c-repr type for src type"),
-            get_c_repr_type(dict, self.dst_type.clone(), true).expect("cant get c-repr type for dst type"))
-    }
-
-    pub fn generate_instantiation(&self, dict: &mut impl TypeDict, σ: &std::collections::HashMap<laddertypes::TypeID, laddertypes::TypeTerm>) -> Option<String> {
-        let mut s = String::new();
-
-        s.push_str(&format!(r#"
-int {} ( {} const * restrict src, {} * restrict dst ) {{
-"#,
-            self.instantiated_symbol_name(dict, &σ),
-            get_c_repr_type(dict, self.src_type.clone().apply_substitution(&|k| σ.get(k).cloned()).clone(), true).expect("cant get c-repr-type"),
-            get_c_repr_type(dict, self.dst_type.clone().apply_substitution(&|k| σ.get(k).cloned()).clone(), true).expect("cant get c-repr-type"),
-        ));
-        for (ty_id, kind) in self.type_args.iter() {
-            if let Some(val) = σ.get(ty_id) {
-                eprintln!("val = {}", dict.unparse(&val));
-
-                let type_var_value =
-                    if let Some(c_repr_type) = get_c_repr_type(dict, val.clone(), true) {
-                        c_repr_type
-                    } else {
-                        encode_type_to_value(dict, val)
-                    };
-
-                s.push_str(&format!("    #define {} {}\n", dict.get_typename(&ty_id).unwrap(), type_var_value));
-            }
-        }
-
-        s.push_str(&self.c_source);
-
-        for (ty_id, kind) in self.type_args.iter() {
-            s.push_str(&format!("\n    #undef {}", dict.get_typename(&ty_id).unwrap()));
-        }
-
-        s.push_str(&format!(r#"
-}}
-"#));
-        Some(s)
-    }
-}
-
-impl LdmcMorphism {
-    pub fn into_prim_c_morphism(self, dict: &mut impl laddertypes::TypeDict, symbol: String, σ: &std::collections::HashMap<laddertypes::TypeID, laddertypes::TypeTerm>) -> LdmcPrimCMorphism {
-
-        let src_type = self.get_type().src_type.clone().apply_substitution(&|k| σ.get(k).cloned()).clone();
-        let dst_type = self.get_type().dst_type.clone().apply_substitution(&|k| σ.get(k).cloned()).clone();
-
-        let src_c_type = get_c_repr_type(dict, src_type.clone(), true).expect("cant get c-repr type for src type");
-        let dst_c_type = get_c_repr_type(dict, dst_type.clone(), true).expect("cant get c-repr type for src type");
-
-        let c_source =
-            format!("
-typedef {} {}_src_t;
-
-typedef {} {}_dst_t;
-
-int {} ( {}_src_t const * restrict src, {}_dst_t * restrict dst )
-{{
-{}
-    return 0;
-}}
-                ",
-                src_c_type, symbol,
-                dst_c_type, symbol,
-                symbol, symbol, symbol,
-                self.generate_call(dict, σ, 0)
-            );
-
-        LdmcPrimCMorphism {
-            symbol,
-            type_args: Vec::new(),
-            src_type,
-            dst_type,
-            c_source
-        }
-    }
-
-    pub fn generate_call(&self, dict: &mut impl TypeDict, σ: &std::collections::HashMap<laddertypes::TypeID, laddertypes::TypeTerm>, i: u64) -> String {
-        match self {
-            LdmcMorphism::Primitive(prim_morph) => {
-                let src_c_type = get_c_repr_type(dict, prim_morph.src_type.clone().apply_substitution(&|k| σ.get(k).cloned()).clone(), true).expect("cant get c-repr type for src type");
-                let dst_c_type = get_c_repr_type(dict, prim_morph.dst_type.clone().apply_substitution(&|k| σ.get(k).cloned()).clone(), true).expect("cant get c-repr type for dst type");
-
-                let src_buf = if i%2 == 0 { "bufA" } else { "bufB" };
-                let dst_buf = if i%2 == 0 { "bufB" } else { "bufA" };
-
-                format!(r#"
-    {{
-            {} const * restrict src = (void*) {};
-            {} * restrict dst = (void*) {};
-            {} ( src, dst );
-    }}"#,
-                    src_c_type, src_buf,
-                    dst_c_type, dst_buf,
-                    prim_morph.instantiated_symbol_name(dict, σ),
-                )
-            }
-            LdmcMorphism::LengthPrefixMap { length_prefix_type, item_morph } => {
-                let src_type = self.get_type().src_type.clone().apply_substitution(&|k| σ.get(k).cloned()).clone();
-                let dst_type = self.get_type().dst_type.clone().apply_substitution(&|k| σ.get(k).cloned()).clone();
-
-                eprintln!("length prefix type ={:?}", length_prefix_type);
-                eprintln!("src_type ={:?}", src_type);
-                eprintln!("dst_type = {:?}", dst_type);
-
-                dict.add_varname("S".into());
-
-                let γ_src = laddertypes::unify(
-                    &dict.parse("<Seq~<LengthPrefix S> T>").expect("parse template"),
-                    &src_type
-                ).expect("cant get src item type");
-
-                let γ_dst = laddertypes::unify(
-                    &dict.parse("<Seq~<LengthPrefix S> T>").expect("parse template"),
-                    &dst_type
-                ).expect("cant get dst item type");
-
-                let src_length_type = γ_src.get(&dict.get_typeid(&"S".into()).unwrap()).expect("cant get src-length type").clone();
-                let dst_length_type = γ_src.get(&dict.get_typeid(&"S".into()).unwrap()).expect("cant get dst-length type").clone();
-
-                let length_type = src_length_type;
-
-                let src_item_type = γ_src.get(&dict.get_typeid(&"T".into()).unwrap()).expect("cant get src-item type").clone();
-                let dst_item_type = γ_dst.get(&dict.get_typeid(&"T".into()).unwrap()).expect("cant get src-item type").clone();
-
-                let length_c_type = get_c_repr_type(dict, length_type, true).expect("cant c-repr type for array length");
-                let src_item_c_type = get_c_repr_type(dict, src_item_type, true).expect("cant c-repr type for src item");
-                let dst_item_c_type = get_c_repr_type(dict, dst_item_type, true).expect("cant c-repr type for dst item");
-                let src_c_type = get_c_repr_type(dict, src_type, true).expect("cant get c-repr type for src type");
-                let dst_c_type = get_c_repr_type(dict, dst_type, true).expect("cant get c-repr type for dst type");
-
-                let map_fn = format!("length_prefix_{}_array_map_{}_to_{}",
-                    length_c_type, src_item_c_type, dst_item_c_type
-                );
-
-                let src_buf = if i%2 == 0 { "bufA" } else { "bufB" };
-                let dst_buf = if i%2 == 0 { "bufB" } else { "bufA" };
-                format!(r#"
-    {{
-            {} const * restrict src = (void*) {};
-            {} * restrict dst = (void*) {};
-            {} ( {}, src, dst );
-    }}"#,
-                    src_c_type, src_buf,
-                    dst_c_type, dst_buf,
-                    map_fn,
-                    item_morph.instantiated_symbol_name(dict, σ),
-                )
-            }
-            LdmcMorphism::ValueDelimMap { delim, item_morph } => {
-                let src_c_type = get_c_repr_type(dict, item_morph.src_type.clone(), false).expect("cant get c-repr type for src type");
-                let dst_c_type = get_c_repr_type(dict, item_morph.dst_type.clone(), false).expect("cant get c-repr type for dst type");
-
-                let src_buf = if i%2 == 0 { "bufA" } else { "bufB" };
-                let dst_buf = if i%2 == 0 { "bufB" } else { "bufA" };
-                format!(r#"
-    {{
-            {} const * restrict src = (void*) {};
-            {} * restrict dst = (void*) {};
-            value_delim_array_map_8_to_64( {}, src, dst );
-    }}"#,
-                    src_c_type, src_buf,
-                    dst_c_type, dst_buf,
-                    item_morph.instantiated_symbol_name(dict, σ)
-                )
-            },
-
-            LdmcMorphism::StructMap { src_struct, dst_struct, member_morphisms } => {
-                let mut output = String::new();
-                for member_morph in member_morphisms.iter() {
-                    if let Some(m) = member_morph.item_morph.as_ref() {
-                        //let src_c_type = get_c_repr_type(dict, m.src_type.clone(), false).expect("cant get c-repr type for field member");
-                        //let dst_c_type = get_c_repr_type(dict, m.dst_type.clone(), false).expect("cant get c-repr type for field member");
-
-                        output.push_str(&format!("    {} ( &src->{}, &dst->{} );\n",
-                            m.instantiated_symbol_name(dict, σ),
-                            member_morph.field_name,
-                            member_morph.field_name
-                        ));
-                    } else {
-                        let mut field_type = None;
-                        for (field_name, ft) in src_struct.members.iter() {
-                            if field_name == &member_morph.field_name {
-                                field_type = Some(ft);
-                            }
-                        }
-
-                        let field_type = field_type.expect("cant get field member type");
-                        //if let Some(field_c_type) = get_c_repr_type(dict, field_type.clone(), false).expect("cat get c-repr type for field member");
-
-                        match  get_type_size(dict, field_type.clone()) {
-                            ObjectSize::Static(size) => {
-                                output.push_str(&format!("    memcpy( &dst->{}, &src->{}, sizeof(dst->{}) );\n",
-                                    member_morph.field_name, member_morph.field_name, member_morph.field_name
-                                ));
-                            }
-                            _ => {
-                                eprintln!("cant assign field of unknown size!");
-                            }
-                        }
-                    }
-                }
-                output
-            }
-        }
-    }
-}
+*/
diff --git a/src/c_gen_types.rs b/src/c_gen_types.rs
new file mode 100644
index 0000000..9c0020d
--- /dev/null
+++ b/src/c_gen_types.rs
@@ -0,0 +1,240 @@
+use {
+    crate::{morphism::LdmcPrimMorph, struct_layout::{get_type_size, LayoutType, ObjectSize, StructLayout}}, chumsky::chain::Chain, laddertypes::{morphism::{Morphism, MorphismInstance}, morphism_sugared::{MorphismInstance2, SugaredMorphismType}, parser::*, substitution_sugared::SugaredSubstitution, unparser::*, Substitution, SugaredEnumVariant, SugaredStructMember, SugaredTypeTerm, TypeDict, TypeTerm}
+};
+
+/*
+*/
+pub fn get_c_repr_kind(kind: String) -> Option<String> {
+    match kind.as_str() {
+        "ℤ" => Some("uint64_t".into()),
+        _ => None
+    }
+}
+
+/* for a given ladder type `t`, get the corresponding C type
+ */
+pub fn get_c_repr_type(dict: &mut impl TypeDict, t: SugaredTypeTerm, skip_pointer: bool) -> Option<String> {
+    eprintln!("get c repr of {}", t.pretty(dict,0));
+
+    match t.get_floor_type().1.strip() {
+        SugaredTypeTerm::TypeID(tyid) => {
+            if tyid == dict.get_typeid_creat("native.UInt8") {
+                Some("uint8_t".into())
+            } else if tyid == dict.get_typeid_creat("native.UInt16") {
+                Some("uint16_t".into())
+            } else if tyid == dict.get_typeid_creat("native.UInt32") {
+                Some("uint32_t".into())
+            } else if tyid == dict.get_typeid_creat("native.UInt64") {
+                Some("uint64_t".into())
+            } else if tyid == dict.get_typeid_creat("native.Address") {
+                Some("void*".into())
+            } else if tyid == dict.get_typeid_creat("native.Float32") {
+                Some("float".into())
+            } else if tyid == dict.get_typeid_creat("native.Float64") {
+                Some("double".into())
+            } else {
+                None
+            }
+        }
+
+        SugaredTypeTerm::Seq{ seq_repr, items } => {
+            if let Some(sr_sugar) = seq_repr {
+                let sr = sr_sugar.desugar(dict);
+
+                let item_type = items.first().expect("no item type specified!").clone();
+                let item_c_type : String = get_c_repr_type(dict, item_type, false).expect("cant get item type representation");
+
+                dict.add_varname("Length".into()); // Kind: Num
+                dict.add_varname("LengthType".into()); // Kind: Type
+                dict.add_varname("TermValue".into()); // Kind: Value of Type ItemType
+
+                if let Ok(σ) = laddertypes::unify(
+                    &sr,
+                    &dict.parse("<StaticLength Length>").expect("parse")
+                ) {
+                    let length = match
+                        σ.get(
+                            &dict.get_typeid(&"Length".into()).expect("no Length ID")
+                        ).expect("no length specified!")
+                    {
+                        TypeTerm::Num(l) => l,
+                        _ => {
+                            eprintln!("invalid Length!");
+                            return None;
+                        }
+                    };
+                    Some(format!("{}[{}]", item_c_type, length))
+                }
+                else if let Ok(σ) = laddertypes::unify(
+                    &sr,
+                    &dict.parse("<LengthPrefix LengthType>").expect("parse")
+                ) {
+                    let length_type = σ.get(
+                            &dict.get_typeid(&"LengthType".into()).expect("no LengthType ID")
+                        ).expect("no length type specified")
+                        .clone()
+                        .sugar(dict);
+                    let length_c_type : String = get_c_repr_type(dict, length_type, false).expect("cant get length type representation");
+
+                    match length_c_type.as_str() {
+                        "uint8_t" |
+                        "uint16_t" |
+                        "uint32_t" |
+                        "uint64_t" => {}
+                        s => {
+                                eprintln!("invalid length type '{}' !", s);
+                                return None;
+                            }
+                        }
+                        match item_c_type.as_str() {
+                            "uint8_t" |
+                            "uint16_t" |
+                            "uint32_t" |
+                            "uint64_t" |
+                            "void*" => {}
+                            s => {
+                                eprintln!("invalid item type '{}'!", s);
+                                return None;
+                        }
+                    }
+
+                    Some(format!("LengthPrefix_{}_Array_{}", length_c_type, item_c_type))
+                }
+                else if let Ok(σ) = laddertypes::unify(
+                    &sr,
+                    &dict.parse("<ValueTerminated TermValue>").expect("")
+                ) {
+                    if skip_pointer {
+                        Some(item_c_type)
+                    } else {
+                        Some(format!("{} *", item_c_type))
+                    }
+                }
+                else {
+                    eprintln!("can't get C-repr for sequence type `{}`!", dict.unparse(&sr));
+                    None
+                }
+            } else {
+                eprintln!("no sequence-representation type specified!");
+                None
+            }
+        }
+
+        SugaredTypeTerm::Struct{ struct_repr, members } => {
+            let c_struct_attribute =
+                if let Some(sr) = struct_repr {
+                    let sr = sr.desugar(dict);
+                    match LayoutType::parse(dict, &sr).expect("layout type") {
+                        LayoutType::Aligned => "",
+                        LayoutType::Packed => "__attribute((packed))__"
+                    }
+                } else {""};
+
+            let mut c_type = format!("struct {} {{\n", c_struct_attribute);
+
+            for SugaredStructMember{ symbol, ty } in members {
+                let field_c_type = get_c_repr_type(dict, ty, false).expect("");
+                c_type.push_str(&format!("    {} {};\n",
+                    field_c_type,
+                    symbol
+                ));
+            }
+
+            c_type.push_str("}");
+            Some(c_type)
+        }
+
+        SugaredTypeTerm::Enum { enum_repr, variants } => {
+            let mut c_type = format!("
+struct {{
+    enum {{
+");
+
+            for (i, SugaredEnumVariant{ symbol, ty }) in variants.iter().enumerate() {
+                c_type.push_str(&format!(
+                    "       {} = {}", symbol.to_uppercase(), i
+                ));
+
+                if i+1 < variants.len() {
+                    c_type.push_str(",\n");
+                }
+            }
+
+            c_type.push_str("
+    } tag;
+
+    union {
+");
+
+            for SugaredEnumVariant{ symbol, ty } in variants {
+                let variant_c_type = get_c_repr_type(dict, ty, false).expect("cant get C-Repr type for variant");
+                c_type.push_str(&format!(
+                    "       {} {};\n", variant_c_type, symbol
+                ));
+            }
+
+            c_type.push_str("
+    };
+}");
+
+            Some(c_type)
+        }
+
+        SugaredTypeTerm::Ladder(rungs) => {
+            if let Some(t) = rungs.last() {
+                get_c_repr_type(dict, t.clone(), false)
+            } else {
+                None
+            }
+        }
+
+        _ => { None }
+    }
+}
+
+pub fn encode_type_to_symbol(dict: &mut impl TypeDict, t: &laddertypes::SugaredTypeTerm)-> String {
+    let t = t.clone().desugar(dict);
+    match t {
+        laddertypes::TypeTerm::Char(c) => {
+            match c {
+                '.' => format!("_dot_"),
+                _ =>
+                format!("{}", (c as u64))
+            }
+        },
+        laddertypes::TypeTerm::Num(n) => {
+            format!("{}", n)
+        }
+        laddertypes::TypeTerm::TypeID(ty_id) => {
+            if let Some(name) = dict.get_typename(&ty_id) {
+                format!("{}", name.replace(".", "_dot_"))
+            } else {
+                format!("")
+            }
+        }
+        laddertypes::TypeTerm::Ladder(rs) |
+        laddertypes::TypeTerm::App(rs) => {
+            let mut s = String::new();
+            for r in rs {
+                s.push('_');
+
+                let r = r.sugar(dict);
+                s.push_str(&encode_type_to_symbol(dict, &r));
+            }
+            s
+        }
+    }
+}
+
+pub fn encode_morph_type_to_symbol(dict: &mut impl TypeDict, t: &SugaredMorphismType) -> String {
+    format!(
+        "morph_{}__to_{}",
+        encode_type_to_symbol(dict, &t.src_type),
+        encode_type_to_symbol(dict, &t.dst_type)
+    )
+}
+
+pub fn encode_type_to_value(dict: &mut impl TypeDict, t: &laddertypes::SugaredTypeTerm) -> String {
+    let t = t.clone().desugar(dict);
+    dict.unparse(&t)
+}
diff --git a/src/main.rs b/src/main.rs
index 8769384..7ee2bad 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -3,26 +3,22 @@
 mod morphism;
 mod parser;
 mod c_gen;
+mod c_gen_types;
 mod struct_layout;
 
 use {
     crate::{
-        morphism::LdmcMorphism,
+        morphism::LdmcPrimMorph,
         parser::morphism_base_parser,
-    }, ariadne::{Color, Label, Report, ReportKind, Source}, chumsky::prelude::*, laddertypes::{
-        parser::ParseLadderType, unparser::*, BimapTypeDict, MorphismType, TypeDict
+    }, ariadne::{Color, Label, Report, ReportKind, Source}, c_gen::LdmcCTargetMorph, chumsky::prelude::*, laddertypes::{
+        morphism_path_sugared::SugaredShortestPathProblem, morphism_sugared::{MorphismInstance2, SugaredMorphism, SugaredMorphismType}, parser::ParseLadderType, unparser::*, BimapTypeDict, MorphismType, SugaredTypeTerm, TypeDict
     }, std::{collections::HashMap, sync::{Arc, RwLock}}, tiny_ansi::TinyAnsi
 };
 
 fn main() {
     let mut type_dict = Arc::new(RwLock::new(BimapTypeDict::new()));
 
-    let mut morphism_base = laddertypes::morphism_base::MorphismBase::<LdmcMorphism>::new(vec![
-        //type_dict.parse("Seq~MsbCont").expect(""),
-        //type_dict.parse("Seq~<ValueTerminated '\\0'>").expect(""),
-        type_dict.parse("Seq~<LengthPrefix native.UInt64>").expect(""),
-        type_dict.parse("Struct").expect("")
-    ]);
+    let mut morphism_base = laddertypes::morphism_base_sugared::SugaredMorphismBase::<LdmcPrimMorph>::new();
 
     let mut args = std::env::args().skip(1);
     let src_type_arg = args.next().expect("src type expected");
@@ -36,7 +32,7 @@ fn main() {
                 eprintln!("[{}] parse ok.", mb_path.bright_yellow());
                 println!("{}", includes);
                 for m in morphisms {
-                    morphism_base.add_morphism(LdmcMorphism::Primitive(m));
+                    morphism_base.add_morphism(m);
                 }
             }
             Err(errs) => {
@@ -58,86 +54,103 @@ fn main() {
 
     let mut γ = HashMap::new();
     γ.insert(
-        type_dict.get_typeid_creat(&"Byte".into()),
+        type_dict.get_typeid_creat(&"Byte"),
         type_dict.parse("<Seq~<StaticLength 8> Bit>").expect("parse")
-            .apply_substitution(&|k| γ.get(k).cloned())
+            .apply_subst(&γ)
             .clone()
     );
     γ.insert(
-        type_dict.get_typeid_creat(&"x86.UInt8".into()),
+        type_dict.get_typeid_creat(&"x86.UInt8"),
         type_dict.parse("ℤ_2^8 ~ <PosInt 2 BigEndian> ~ <Seq~<StaticLength 8> <Digit 2> ~ Bit>").expect("parse")
-            .apply_substitution(&|k| γ.get(k).cloned())
+            .apply_subst(&γ)
             .clone()
     );
     γ.insert(
-        type_dict.get_typeid_creat(&"x86.UInt16".into()),
+        type_dict.get_typeid_creat(&"x86.UInt16"),
         type_dict.parse("ℤ_2^16 ~ <PosInt 256 LittleEndian> ~ <Seq~<StaticLength 2> <Digit 256> ~ x86.UInt8 >").expect("parse")
-            .apply_substitution(&|k| γ.get(k).cloned())
+            .apply_subst(&γ)
             .clone()
     );
     γ.insert(
-        type_dict.get_typeid_creat(&"x86.UInt32".into()),
+        type_dict.get_typeid_creat(&"x86.UInt32"),
         type_dict.parse("ℤ_2^32 ~ <PosInt 256 LittleEndian> ~ <Seq~<StaticLength 4> <Digit 256> ~ x86.UInt8 >").expect("parse")
-            .apply_substitution(&|k| γ.get(k).cloned())
-            .clone()
+            .apply_subst(&γ).clone()
     );
     γ.insert(
-        type_dict.get_typeid_creat(&"x86.UInt64".into()),
+        type_dict.get_typeid_creat(&"x86.UInt64"),
         type_dict.parse("ℤ_2^64 ~ <PosInt 256 LittleEndian> ~ <Seq~<StaticLength 8> <Digit 256> ~ x86.UInt8 >").expect("parse")
-            .apply_substitution(&|k| γ.get(k).cloned())
-            .clone()
+            .apply_subst(&γ).clone()
     );
     γ.insert(
-        type_dict.get_typeid_creat(&"x86.Float".into()),
+        type_dict.get_typeid_creat(&"x86.Float32"),
         type_dict.parse("ℝ ~ IEEE-754.Float32 ~ <Seq~<StaticLength 4> Byte>").expect("parse")
-            .apply_substitution(&|k| γ.get(k).cloned())
-            .clone()
+            .apply_subst(&γ).clone()
+    );
+    γ.insert(
+        type_dict.get_typeid_creat(&"x86.Float64"),
+        type_dict.parse("ℝ ~ IEEE-754.Float64 ~ <Seq~<StaticLength 4> Byte>").expect("parse")
+            .apply_subst(&γ).clone()
     );
 
+    let src_type = type_dict.parse( src_type_arg.as_str() ).expect("");
+    let dst_type = type_dict.parse( dst_type_arg.as_str() ).expect("");
+
+/*
     let struct_type1 = type_dict.parse("
-        <Struct
-            <Struct.Field  online-since          TimePoint ~ <TimeSince UnixEpoch> ~ Duration ~ Seconds ~ ℝ ~ <QuantizedLinear 0 1 1000> ~ ℕ ~ native.UInt64 >
-            <Struct.Field  battery-capacity      Energy ~ Wh ~ ℝ ~ <QuantizedLinear 0 1 1000> ~ ℕ ~ native.UInt64 >
-            <Struct.Field  battery-charge        Energy ~ Wh ~ ℝ ~ <QuantizedLinear 0 1 1000> ~ ℕ ~ native.UInt64 >
-            <Struct.Field  min-sampling-period   Duration ~ Seconds ~ ℝ ~ <QuantizedLinear 0 1 1000> ~ ℕ ~ native.UInt32 >
-            <Struct.Field  cur-sampling-period   Duration ~ Seconds ~ ℝ ~ <QuantizedLinear 0 1 1000> ~ ℕ ~ native.UInt32 >
-            <Struct.Field  max-chunk-size        ℕ ~ native.UInt32 >
-            <Struct.Field  cur-chunk-size        ℕ ~ native.UInt32 >
-            <Struct.Field  n-chunks-capacity     ℕ ~ native.UInt32 >
-            <Struct.Field  n-full-data-chunks    ℕ ~ native.UInt32 >
-            <Struct.Field  n-empty-data-chunks   ℕ ~ native.UInt32 >
+        <Struct ~ Aligned
+            <online-since          TimePoint ~ <TimeSince UnixEpoch> ~ Duration ~ Seconds ~ ℝ ~ <QuantizedLinear 0 1 1000> ~ ℕ ~ native.UInt64 >
+            <capacity              Energy ~ Wh ~ ℝ ~ <QuantizedLinear 0 1 1000> ~ ℕ ~ native.UInt64 >
+            <battery-charge        Energy ~ Wh ~ ℝ ~ <QuantizedLinear 0 1 1000> ~ ℕ ~ native.UInt64 >
+            <min-sampling-period   Duration ~ Seconds ~ ℝ ~ <QuantizedLinear 0 1 1000> ~ ℕ ~ native.UInt32 >
+            <cur-sampling-period   Duration ~ Seconds ~ ℝ ~ <QuantizedLinear 0 1 1000> ~ ℕ ~ native.UInt32 >
+            <max-chunk-size        ℕ ~ native.UInt32 >
+            <cur-chunk-size        ℕ ~ native.UInt32 >
+            <n-chunks-capacity     ℕ ~ native.UInt32 >
+            <n-full-data-chunks    ℕ ~ native.UInt32 >
+            <n-empty-data-chunks   ℕ ~ native.UInt32 >
         >
     ").expect("parse struct type");
 
-    eprintln!("{}
-    ",
-    struct_type1.clone().sugar(&mut type_dict).pretty(&type_dict, 0)
-    );
-
-    for m in morphism_base.enum_morphisms( &struct_type1 ) {
-        eprintln!("{:?} -> {:?}",
-            type_dict.read().unwrap().unparse(&m.get_type().src_type),
-            type_dict.read().unwrap().unparse(&m.get_type().dst_type)
-        );
-    }
-    return;
-
     let struct_type2 = type_dict.parse("
-        <Struct
-
-            <Struct.Field  battery-charge        Energy ~ Wh ~ ℝ ~ native.Double >
-            <Struct.Field  battery-capacity      Energy ~ Wh ~ ℝ ~ native.Double >
-            <Struct.Field  min-sampling-period   Duration ~ Seconds ~ ℝ ~ native.Double >
-            <Struct.Field  cur-sampling-period   Duration ~ Seconds ~ ℝ ~ native.Double >
-            <Struct.Field  max-chunk-size        ℕ ~ native.UInt32 >
-            <Struct.Field  cur-chunk-size        ℕ ~ native.UInt32 >
-            <Struct.Field  n-chunks-capacity     ℕ ~ native.UInt32 >
-            <Struct.Field  n-full-data-chunks    ℕ ~ native.UInt32 >
-            <Struct.Field  n-empty-data-chunks   ℕ ~ native.UInt32 >
-
-            <Struct.Field  online-since          TimePoint ~ <TimeSince UnixEpoch> ~ Duration ~ Seconds ~ ℝ ~ native.Double >
+        <Struct ~ Packed
+            <battery-charge        Energy ~ Wh ~ ℝ ~ native.Double >
+            <battery-capacity      Energy ~ Wh ~ ℝ ~ native.Double >
+            <min-sampling-period   Duration ~ Seconds ~ ℝ ~ native.Double >
+            <cur-sampling-period   Duration ~ Seconds ~ ℝ ~ native.Double >
+            <max-chunk-size        ℕ ~ native.UInt32 >
+            <cur-chunk-size        ℕ ~ native.UInt32 >
+            <n-chunks-capacity     ℕ ~ native.UInt32 >
+            <n-full-data-chunks    ℕ ~ native.UInt32 >
+            <n-empty-data-chunks   ℕ ~ native.UInt32 >
+            <online-since          TimePoint ~ <TimeSince UnixEpoch> ~ Duration ~ Seconds ~ ℝ ~ native.Double >
         >
     ").expect("parse struct type");
+*/
+
+/*
+    let struct_type1 = type_dict.parse("
+        RGB~<Struct
+            <red ℝ ~ <QuantizedLinear 0 1 255> ~ ℕ ~ native.UInt8>
+            <green ℝ ~ <QuantizedLinear 0 1 255> ~ ℕ ~ native.UInt8>
+            <blue ℝ ~ <QuantizedLinear 0 1 255> ~ ℕ ~ native.UInt8>
+        >
+        ").expect("parse");
+
+    let struct_type2 = type_dict.parse("
+        RGB~<Struct
+            <red ℝ ~ native.Float64>
+            <green ℝ ~ native.Float64>
+            <blue ℝ ~ native.Float64>
+        >
+    ").expect("parse");
+*/
+
+    let ty = SugaredMorphismType{ src_type: src_type.sugar(&mut type_dict), dst_type: dst_type.sugar(&mut type_dict) };
+    let mut target = LdmcCTargetMorph::new();
+    target.add_instantiation(&mut type_dict, morphism_base.get_morphism_instance( &ty ).expect("cant get instance"));
+    println!("{}", target.into_c_source(&mut type_dict));
+/*
+    return;
 
     let m = LdmcMorphism::new_struct_map(&mut type_dict, &morphism_base, struct_type1, struct_type2);
 
@@ -145,10 +158,9 @@ fn main() {
         m.into_prim_c_morphism(&mut type_dict, "morph_my_struct".into(), &HashMap::new())
             .c_source
     );
-return;
-    let src_type = type_dict.parse( src_type_arg.as_str() ).expect("");
-    let dst_type = type_dict.parse( dst_type_arg.as_str() ).expect("");
 
+
+return;
     let path = laddertypes::morphism_path::ShortestPathProblem::new(
         &morphism_base,
         MorphismType {
@@ -165,4 +177,5 @@ return;
             std::process::exit(-1);
         }
     }
+    */
 }
diff --git a/src/morphism.rs b/src/morphism.rs
index c5a509f..1fb4199 100644
--- a/src/morphism.rs
+++ b/src/morphism.rs
@@ -1,44 +1,16 @@
 
-use laddertypes::{morphism::Morphism, morphism_base::MorphismBase};
-use crate::{c_gen::encode_type_to_symbol, struct_layout::StructLayout};
+use laddertypes::{morphism::Morphism, morphism_base::MorphismBase, morphism_path::ShortestPathProblem, morphism_sugared::{SugaredMorphism, SugaredMorphismType}, SugaredStructMember};
+use crate::{c_gen_types::encode_type_to_symbol, struct_layout::StructLayout};
 
-#[derive(Clone, Debug)]
-pub struct LdmcPrimCMorphism {
+#[derive(Clone, Debug, PartialEq, Eq)]
+pub struct LdmcPrimMorph {
     pub symbol: String,
     pub type_args: Vec<(laddertypes::TypeID, String)>,
-    pub src_type: laddertypes::TypeTerm,
-    pub dst_type: laddertypes::TypeTerm,
+    pub ty: SugaredMorphismType,
     pub c_source: String
 }
 
-#[derive(Clone)]
-pub struct StructFieldMorphism {
-    pub field_name: String,
-    pub item_morph: Option<Box<LdmcPrimCMorphism>>,
-    pub src_offset: u64,
-    pub dst_offset: u64,
-}
-
-#[derive(Clone)]
-pub enum LdmcMorphism {
-    Primitive( LdmcPrimCMorphism ),
-    //Chain(Vec< LdmcPrimCMorphism >),
-    LengthPrefixMap{
-        length_prefix_type: laddertypes::TypeTerm,
-        item_morph: Box<LdmcPrimCMorphism>
-    },
-    ValueDelimMap{
-        delim: u64,
-        item_morph: Box<LdmcPrimCMorphism>
-    },
-    StructMap{
-        src_struct: StructLayout,
-        dst_struct: StructLayout,
-        member_morphisms: Vec<StructFieldMorphism>
-    }
-}
-
-impl LdmcMorphism {
+impl LdmcPrimMorph {
     /*
     pub fn into_prim_c_morphism(self, dict: &mut impl laddertypes::TypeDict, symbol: String) -> LdmcPrimCMorphism {
 
@@ -65,20 +37,22 @@ impl LdmcMorphism {
         }
     }
 */
+/*
+
     pub fn new_struct_map(
         dict: &mut impl laddertypes::TypeDict,
-        morph_base: &MorphismBase<LdmcMorphism>,
+        morph_base: &MorphismBase<LdmcPrimMorph>,
         src: laddertypes::TypeTerm,
         dst: laddertypes::TypeTerm,
     ) -> Self {
-        let src_struct = StructLayout::parse(dict, src).expect("cant parse src struct layout");
-        let dst_struct = StructLayout::parse(dict, dst).expect("cant parse dst struct layout");
+        let src_struct = StructLayout::parse(dict, &src).expect("cant parse src struct layout");
+        let dst_struct = StructLayout::parse(dict, &dst).expect("cant parse dst struct layout");
 
         let mut member_morphisms = Vec::new();
 
-        for (field_name, dst_type) in dst_struct.members.iter() {
+        for SugaredStructMember{ symbol: field_name, ty: dst_type } in dst_struct.members.iter() {
             let mut src_type = None;
-            for (src_name, st) in src_struct.members.iter() {
+            for SugaredStructMember{ symbol: src_name, ty: st } in src_struct.members.iter() {
                 if src_name == field_name {
                     src_type = Some(st.clone());
                 }
@@ -95,14 +69,19 @@ impl LdmcMorphism {
                     }
                 );
             } else {
-                match morph_base.find_morphism(
-                    &laddertypes::MorphismType {
-                        src_type: src_type.clone(),
-                        dst_type: dst_type.clone()
-                    },
-                    dict
-                ) {
-                    Some(item_morph) => {
+                match ShortestPathProblem::new(
+                    &morph_base,
+                    laddertypes::MorphismType {
+                        src_type: src_type.clone().desugar(dict),
+                        dst_type: dst_type.clone().desugar(dict)
+                    }
+                ).solve()
+                {
+                    Some(path) => {
+
+                        let src_type = src_type.clone().desugar(dict);
+                        let dst_type = dst_type.clone().desugar(dict);
+
                         let morph_symb = format!("morph_{}_to_{}",
                             encode_type_to_symbol(dict, &src_type),
                             encode_type_to_symbol(dict, &dst_type)
@@ -110,7 +89,7 @@ impl LdmcMorphism {
                         member_morphisms.push(
                             StructFieldMorphism {
                                 field_name: field_name.to_string(),
-                                item_morph: Some(Box::new(item_morph.m.into_prim_c_morphism(dict, morph_symb, &item_morph.σ))),
+                                item_morph: None,//Some(Box::new(item_morph.m.into_prim_c_morphism(dict, morph_symb, &item_morph.σ))),
                                 src_offset: src_struct.get_offset( field_name ),
                                 dst_offset: dst_struct.get_offset( field_name ),
                             }
@@ -124,13 +103,20 @@ impl LdmcMorphism {
             }
         }
 
-        LdmcMorphism::StructMap {
+        LdmcPrimMorph::StructMap {
             src_struct, dst_struct,
             member_morphisms
         }
     }
+    */
 }
 
+impl SugaredMorphism for LdmcPrimMorph {
+    fn get_type(&self) -> SugaredMorphismType {
+        self.ty.clone()
+    }
+}
+/*
 impl Morphism for LdmcMorphism {
     fn weight(&self) -> u64 {
         1
@@ -188,3 +174,4 @@ impl Morphism for LdmcMorphism {
         }
     }
 }
+*/
diff --git a/src/parser.rs b/src/parser.rs
index f45fddf..49320df 100644
--- a/src/parser.rs
+++ b/src/parser.rs
@@ -1,11 +1,7 @@
 use {
-    chumsky::{
+    crate::morphism::LdmcPrimMorph, chumsky::{
         prelude::*, text::*
-    },
-    std::sync::{Arc, RwLock},
-
-    laddertypes::{TypeDict, BimapTypeDict, parser::*},
-    crate::morphism::LdmcPrimCMorphism
+    }, laddertypes::{morphism_sugared::SugaredMorphismType, parser::*, BimapTypeDict, TypeDict}, std::sync::{Arc, RwLock}
 };
 
 /* morphism-base text format:
@@ -18,7 +14,7 @@ use {
  */
 pub fn morphism_base_parser(
     type_dict: Arc<RwLock< BimapTypeDict >>
-) -> impl Parser<char, (String, Vec<LdmcPrimCMorphism>), Error = Simple<char>> {
+) -> impl Parser<char, (String, Vec<LdmcPrimMorph>), Error = Simple<char>> {
 
     just("```")
     .then(take_until(just("```")))
@@ -63,14 +59,16 @@ pub fn morphism_base_parser(
                 ty_args.push((var_id, kind));
             }
 
-            let src_type = type_dict.parse(&src_type.iter().collect::<String>()).expect("couldnt parse src type");
-            let dst_type = type_dict.parse(&dst_type.iter().collect::<String>()).expect("couldnt parse dst type");
+            let src_type = type_dict.parse(&src_type.iter().collect::<String>()).expect("couldnt parse src type").sugar(&mut *type_dict);
+            let dst_type = type_dict.parse(&dst_type.iter().collect::<String>()).expect("couldnt parse dst type").sugar(&mut *type_dict);
 
-            LdmcPrimCMorphism {
+            LdmcPrimMorph {
                 symbol,
                 type_args: ty_args,
-                src_type,
-                dst_type,
+                ty: SugaredMorphismType{
+                    src_type,
+                    dst_type
+                },
                 c_source
             }
         })
diff --git a/src/struct_layout.rs b/src/struct_layout.rs
index d961602..40be995 100644
--- a/src/struct_layout.rs
+++ b/src/struct_layout.rs
@@ -1,4 +1,6 @@
 
+use std::ops::Deref;
+
 use laddertypes::{parser::*, unparser::*, SugaredStructMember, SugaredTypeTerm, TypeDict, TypeTerm};
 
 #[derive(Clone, Copy, Debug)]
@@ -8,43 +10,137 @@ pub enum ObjectSize {
     Unknown
 }
 
+impl std::ops::Add for ObjectSize {
+    type Output = Self;
 
-pub fn get_type_size( dict: &mut impl TypeDict, ty: TypeTerm ) -> ObjectSize {
-    let ty = ty.clone().get_lnf_vec().last().unwrap().clone();
+    fn add(self, rhs: Self) -> Self {
+        match (self, rhs) {
+            (ObjectSize::Unknown, _) |
+            (_, ObjectSize::Unknown)
+                => ObjectSize::Unknown,
 
-    if ty == dict.parse("native.UInt8").expect("") {
-        return ObjectSize::Static(1);
+            (ObjectSize::Dynamic(), _) |
+            (_, ObjectSize::Dynamic())
+                => ObjectSize::Dynamic(),
+
+            (ObjectSize::Static(s1), ObjectSize::Static(s2)) => ObjectSize::Static(s1 + s2),
+        }
     }
-    if ty == dict.parse("native.UInt16").expect("") {
-        return ObjectSize::Static(2);
+}
+
+impl std::ops::Mul for ObjectSize {
+    type Output = Self;
+
+    fn mul(self, rhs: Self) -> Self {
+        match (self, rhs) {
+            (ObjectSize::Unknown, _) |
+            (_, ObjectSize::Unknown)
+                => ObjectSize::Unknown,
+
+            (ObjectSize::Dynamic(), _) |
+            (_, ObjectSize::Dynamic())
+                => ObjectSize::Dynamic(),
+
+            (ObjectSize::Static(s1), ObjectSize::Static(s2)) => ObjectSize::Static(s1 * s2),
+        }
     }
-    if ty == dict.parse("native.UInt32").expect("") ||
-        ty == dict.parse("native.Float").expect("") {
-        return ObjectSize::Static(4);
-    }
-    if ty == dict.parse("native.UInt64").expect("") ||
-       ty == dict.parse("native.Double").expect("") {
-        return ObjectSize::Static(8);
+}
+
+pub fn get_type_size( dict: &mut impl TypeDict, ty: SugaredTypeTerm ) -> ObjectSize {
+    match &ty {
+        SugaredTypeTerm::TypeID(tyid) => {
+                 if tyid == &dict.get_typeid_creat("native.UInt8") { ObjectSize::Static(1) }
+            else if tyid == &dict.get_typeid_creat("native.UInt16") { ObjectSize::Static(2) }
+            else if tyid == &dict.get_typeid_creat("native.UInt32") { ObjectSize::Static(4) }
+            else if tyid == &dict.get_typeid_creat("native.UInt64") { ObjectSize::Static(8) }
+            else if tyid == &dict.get_typeid_creat("native.Address") { ObjectSize::Static(8) }
+            else if tyid == &dict.get_typeid_creat("native.Float32") { ObjectSize::Static(4) }
+            else if tyid == &dict.get_typeid_creat("native.Float64") { ObjectSize::Static(8) }
+            else {
+                ObjectSize::Unknown
+            }
+        },
+
+        SugaredTypeTerm::Ladder(rungs) => {
+            get_type_size(dict, rungs.last().unwrap().clone() )
+        }
+
+        SugaredTypeTerm::Struct { struct_repr, members } => {
+            let layout = StructLayout::parse_sugared(dict, ty).expect("invalid struct");
+            layout.get_size()
+        }
+
+        SugaredTypeTerm::Seq { seq_repr, items } => {
+            if let Some(seq_repr) = seq_repr {
+                dict.add_typename("Length".into());
+                dict.add_typename("LengthType".into());
+                dict.add_typename("TerminatorValue".into());
+
+                if let Ok(σ) = laddertypes::unify(
+                    &seq_repr.clone().desugar(dict),
+                    &dict.parse("<StaticLength Length>").expect("")
+                ) {
+                    if let Some(TypeTerm::Num(len)) = σ.get(&dict.get_typeid(&"Length".into()).expect("")) {
+                        ObjectSize::Static(*len as u64) * get_type_size(dict, items.first().unwrap().clone())
+                    } else {
+                        ObjectSize::Unknown
+                    }
+                }
+                else if let Ok(σ) = laddertypes::unify(
+                    &seq_repr.clone().desugar(dict),
+                    &dict.parse("<LengthPrefix LengthType>").expect("")
+                ) {
+                    ObjectSize::Dynamic()
+                }
+                else if let Ok(σ) = laddertypes::unify(
+                    &seq_repr.clone().desugar(dict),
+                    &dict.parse("<ValueTerminated TerminatorValue>").expect("")
+                ) {
+                    ObjectSize::Dynamic()
+                }
+                else {
+                    ObjectSize::Unknown
+                }
+            } else {
+                ObjectSize::Unknown
+            }
+        }
+
+        _ => ObjectSize::Unknown
     }
 
-    if let Some(layout) = StructLayout::parse( dict, ty ) {
-        return layout.get_size();
-    }
-
-    ObjectSize::Unknown
 }
 
 #[derive(Clone, Copy, Debug, PartialEq)]
-enum LayoutType {
-    Natural,
+pub enum LayoutType {
+    Aligned,
     Packed
 }
 
-#[derive(Clone, Debug)]
+impl LayoutType {
+    pub fn parse( dict: &mut impl TypeDict, ty: &TypeTerm ) -> Option< LayoutType > {
+        if ty == &dict.parse("Aligned").expect("parse") {
+            Some(LayoutType::Aligned)
+        } else if ty == &dict.parse("Packed").expect("parse") {
+            Some(LayoutType::Packed)
+        } else {
+            None
+        }
+    }
+
+    pub fn unparse(&self, dict: &mut impl TypeDict) -> TypeTerm {
+        match self {
+            LayoutType::Aligned => dict.parse("Aligned").unwrap(),
+            LayoutType::Packed => dict.parse("Packed").unwrap()
+        }
+    }
+}
+
+#[derive(Clone)]
 pub struct StructLayout {
-    ty: laddertypes::TypeTerm,
-    item_type: laddertypes::TypeTerm,
-    pub members: Vec< (String, laddertypes::TypeTerm) >,
+    pub ty: laddertypes::TypeTerm,
+    pub layout: LayoutType,
+    pub members: Vec< SugaredStructMember >,
     offsets: std::collections::HashMap< String, u64 >,
     size: ObjectSize
 }
@@ -62,18 +158,22 @@ impl StructLayout {
         *self.offsets.get(name).expect("")
     }
 
-    pub fn calculate_offsets(&mut self, dict: &mut impl TypeDict) {
-        let layout_type = LayoutType::Natural;
+    pub fn init_offsets(&mut self, dict: &mut impl TypeDict) {
         let mut offset = 0;
 
-        for (field_name, field_type) in self.members.iter() {
+        for SugaredStructMember{symbol: field_name, ty: field_type} in self.members.iter() {
             //let field_c_type = crate::c_gen::get_c_repr_type(dict, field_type.clone(), true).expect("cant get c-repr for struct field");
             match get_type_size( dict, field_type.clone() ) {
                 ObjectSize::Static(field_size) => {
-                    if layout_type == LayoutType::Natural {
-                        // add padding to natural alignment
-                        if offset % field_size > 0 {
-                            offset = field_size * ((offset / field_size)+1);
+                    match self.layout {
+                        LayoutType::Aligned => {
+                            // add padding to get natural alignment of current member
+                            if offset % field_size > 0 {
+                                offset = field_size * ((offset / field_size)+1);
+                            }
+                        }
+                        LayoutType::Packed => {
+                            // no padding
                         }
                     }
 
@@ -90,7 +190,7 @@ impl StructLayout {
                     return;
                 }
                 ObjectSize::Unknown => {
-                    eprintln!("unknown field size!");
+                    eprintln!("Struct member `{}` has unknown size!", field_name);
                     self.offsets.insert(field_name.clone(), offset);
                     self.size = ObjectSize::Unknown;
                     return;
@@ -108,38 +208,30 @@ impl StructLayout {
         }
     }
 
-    pub fn generate_members(&self, dict: &mut impl TypeDict, prefix: &str, base_ptr: &str) {
-        let mut offset = 0;
-
-        for (field_name, field_type) in self.members.iter() {
-            let field_c_type = crate::c_gen::get_c_repr_type(dict, field_type.clone(), true).expect("cant get c-repr for struct field");
-            let offset = self.get_offset(field_name);
-            println!(" {} * restrict {}_{} = {} + {};",
-                field_c_type, prefix, field_name, base_ptr, offset
-            );
-        }
+    pub fn parse(dict: &mut impl TypeDict, struct_type: &TypeTerm) -> Option <Self> {
+        let st = struct_type.clone().strip().param_normalize().sugar(dict);
+        Self::parse_sugared(dict, st)
     }
 
-    pub fn parse(dict: &mut impl TypeDict, struct_type: TypeTerm) -> Option <Self> {
-        match struct_type.sugar(dict) {
-            SugaredTypeTerm::Struct(sugared_members) => {
-                let mut members = Vec::new();
-                let mut item_type = dict.parse("Byte").expect("");
-
-                for SugaredStructMember{ symbol, ty } in sugared_members {
-                    members.push((symbol, ty.desugar(dict)));
-                }
-
+    pub fn parse_sugared(dict: &mut impl TypeDict, st: SugaredTypeTerm) -> Option <Self> {
+        eprintln!("{}", st.pretty(dict, 0));
+        match st.clone() {
+            SugaredTypeTerm::Struct{ struct_repr, members } => {
                 let mut sl = StructLayout {
-                    ty: TypeTerm::unit(),
-                    item_type,
+                    ty: st.desugar(dict),
+                    layout: if let Some(sr) = struct_repr {
+                        let sr = sr.desugar(dict);
+                        LayoutType::parse( dict, &sr ).expect("invalid struct layout type")
+                    } else {
+                        eprintln!("choose default struct repr");
+                        LayoutType::Aligned
+                    },
+
                     members,
                     offsets: std::collections::HashMap::new(),
                     size: ObjectSize::Unknown
                 };
-
-                sl.calculate_offsets(dict);
-                sl.calculate_type(dict);
+                sl.init_offsets(dict);
 
                 Some(sl)
             }
@@ -150,18 +242,4 @@ impl StructLayout {
             }
         }
     }
-
-    fn calculate_type(&mut self, dict: &mut impl TypeDict) {
-        self.ty =
-            SugaredTypeTerm::Struct(
-                self.members
-                    .iter()
-                    .cloned()
-                    .map(|(symbol,ty)|
-                        SugaredStructMember{ symbol, ty:ty.sugar(dict) })
-                    .collect()
-            )
-                .desugar(dict);
-
-    }
 }