diff --git a/src/c_gen.rs b/src/c_gen.rs
index ac68a93..7f5c7ea 100644
--- a/src/c_gen.rs
+++ b/src/c_gen.rs
@@ -1,6 +1,6 @@
 use {
-    laddertypes::{TypeDict, TypeTerm, parser::*, unparser::*, morphism::{Morphism, MorphismInstance}},
-    crate::morphism::{LdmcPrimCMorphism, LdmcMorphism}
+    crate::{morphism::{LdmcMorphism, LdmcPrimCMorphism}, struct_layout::{get_type_size, ObjectSize, StructLayout}},
+    laddertypes::{morphism::{Morphism, MorphismInstance}, parser::*, unparser::*, TypeDict, TypeTerm},
 };
 
 /*
@@ -85,7 +85,23 @@ pub fn get_c_repr_type(dict: &mut impl TypeDict, t: laddertypes::TypeTerm, skip_
                             }
                         }
                         else {
-                            None
+
+                            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
+                            }
                         }
                     }
 
@@ -205,14 +221,17 @@ morph {}
 ---> {},
 subst σ = {:?},
 halo  Ψ = {}
-*/"#,
+*/
+{}
+"#,
             type_dict.unparse(&morph_inst.get_type().dst_type.param_normalize().decurry()),
             type_dict.unparse(&morph_inst.m.get_type().src_type),
             type_dict.unparse(&morph_inst.m.get_type().dst_type),
             morph_inst.σ,
             type_dict.unparse(&morph_inst.halo),
+            morph_inst.m.generate_call(type_dict, &morph_inst.σ, i)
         );
-        morph_inst.m.generate_call(type_dict, &morph_inst.σ, i);
+
         i += 1;
     }
 
@@ -322,7 +341,42 @@ int {} ( {} const * restrict src, {} * restrict dst ) {{
 }
 
 impl LdmcMorphism {
-    pub fn generate_call(&self, dict: &mut impl TypeDict, σ: &std::collections::HashMap<laddertypes::TypeID, laddertypes::TypeTerm>, i: u64) {
+    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");
@@ -331,17 +385,16 @@ impl LdmcMorphism {
                 let src_buf = if i%2 == 0 { "bufA" } else { "bufB" };
                 let dst_buf = if i%2 == 0 { "bufB" } else { "bufA" };
 
-                println!(r#"
-    {}
+                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();
@@ -383,18 +436,17 @@ impl LdmcMorphism {
 
                 let src_buf = if i%2 == 0 { "bufA" } else { "bufB" };
                 let dst_buf = if i%2 == 0 { "bufB" } else { "bufA" };
-                println!(r#"
-    {}
+                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");
@@ -402,17 +454,54 @@ impl LdmcMorphism {
 
                 let src_buf = if i%2 == 0 { "bufA" } else { "bufB" };
                 let dst_buf = if i%2 == 0 { "bufB" } else { "bufA" };
-                println!(r#"
-    {}
+                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, σ),
-                    '}');
+                    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/main.rs b/src/main.rs
index 13b8629..8769384 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -3,29 +3,25 @@
 mod morphism;
 mod parser;
 mod c_gen;
+mod struct_layout;
 
 use {
-    ariadne::{Color, Label, Report, ReportKind, Source},
-    chumsky::prelude::*,
-    laddertypes::{
-        parser::ParseLadderType, BimapTypeDict, MorphismType
-    },
-    std::sync::{Arc, RwLock},
-    tiny_ansi::TinyAnsi,
-
-
     crate::{
         morphism::LdmcMorphism,
         parser::morphism_base_parser,
-    }
+    }, ariadne::{Color, Label, Report, ReportKind, Source}, chumsky::prelude::*, laddertypes::{
+        parser::ParseLadderType, unparser::*, BimapTypeDict, MorphismType, 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::MorphismBase::<LdmcMorphism>::new(vec![
+
+    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("Seq~<LengthPrefix native.UInt64>").expect(""),
+        type_dict.parse("Struct").expect("")
     ]);
 
     let mut args = std::env::args().skip(1);
@@ -60,14 +56,105 @@ fn main() {
         }
     }
 
+    let mut γ = HashMap::new();
+    γ.insert(
+        type_dict.get_typeid_creat(&"Byte".into()),
+        type_dict.parse("<Seq~<StaticLength 8> Bit>").expect("parse")
+            .apply_substitution(&|k| γ.get(k).cloned())
+            .clone()
+    );
+    γ.insert(
+        type_dict.get_typeid_creat(&"x86.UInt8".into()),
+        type_dict.parse("ℤ_2^8 ~ <PosInt 2 BigEndian> ~ <Seq~<StaticLength 8> <Digit 2> ~ Bit>").expect("parse")
+            .apply_substitution(&|k| γ.get(k).cloned())
+            .clone()
+    );
+    γ.insert(
+        type_dict.get_typeid_creat(&"x86.UInt16".into()),
+        type_dict.parse("ℤ_2^16 ~ <PosInt 256 LittleEndian> ~ <Seq~<StaticLength 2> <Digit 256> ~ x86.UInt8 >").expect("parse")
+            .apply_substitution(&|k| γ.get(k).cloned())
+            .clone()
+    );
+    γ.insert(
+        type_dict.get_typeid_creat(&"x86.UInt32".into()),
+        type_dict.parse("ℤ_2^32 ~ <PosInt 256 LittleEndian> ~ <Seq~<StaticLength 4> <Digit 256> ~ x86.UInt8 >").expect("parse")
+            .apply_substitution(&|k| γ.get(k).cloned())
+            .clone()
+    );
+    γ.insert(
+        type_dict.get_typeid_creat(&"x86.UInt64".into()),
+        type_dict.parse("ℤ_2^64 ~ <PosInt 256 LittleEndian> ~ <Seq~<StaticLength 8> <Digit 256> ~ x86.UInt8 >").expect("parse")
+            .apply_substitution(&|k| γ.get(k).cloned())
+            .clone()
+    );
+    γ.insert(
+        type_dict.get_typeid_creat(&"x86.Float".into()),
+        type_dict.parse("ℝ ~ IEEE-754.Float32 ~ <Seq~<StaticLength 4> Byte>").expect("parse")
+            .apply_substitution(&|k| γ.get(k).cloned())
+            .clone()
+    );
 
+    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 >
+        >
+    ").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 >
+        >
+    ").expect("parse struct type");
+
+    let m = LdmcMorphism::new_struct_map(&mut type_dict, &morphism_base, struct_type1, struct_type2);
+
+    println!("{}",
+        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("");
 
-    let path = morphism_base.find_morphism_path(MorphismType {
-        src_type: src_type.clone(),
-        dst_type: dst_type.clone(),
-    });
+    let path = laddertypes::morphism_path::ShortestPathProblem::new(
+        &morphism_base,
+        MorphismType {
+            src_type: src_type.clone(),
+            dst_type: dst_type.clone(),
+        }).solve();
 
     match path {
         Some(path) => {
diff --git a/src/morphism.rs b/src/morphism.rs
index a1f2aab..c5a509f 100644
--- a/src/morphism.rs
+++ b/src/morphism.rs
@@ -1,5 +1,6 @@
 
-use laddertypes::morphism::Morphism;
+use laddertypes::{morphism::Morphism, morphism_base::MorphismBase};
+use crate::{c_gen::encode_type_to_symbol, struct_layout::StructLayout};
 
 #[derive(Clone, Debug)]
 pub struct LdmcPrimCMorphism {
@@ -10,9 +11,18 @@ pub struct LdmcPrimCMorphism {
     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>
@@ -20,6 +30,104 @@ pub enum LdmcMorphism {
     ValueDelimMap{
         delim: u64,
         item_morph: Box<LdmcPrimCMorphism>
+    },
+    StructMap{
+        src_struct: StructLayout,
+        dst_struct: StructLayout,
+        member_morphisms: Vec<StructFieldMorphism>
+    }
+}
+
+impl LdmcMorphism {
+    /*
+    pub fn into_prim_c_morphism(self, dict: &mut impl laddertypes::TypeDict, symbol: String) -> LdmcPrimCMorphism {
+
+        let src_c_type = ;
+        let dst_c_type = ;
+
+        let c_source =
+            format!("
+                int {} ( {} const * restrict src, {} * restrict dst ) {{
+                    {}
+                    return 0;
+                }}
+                ",
+                symbol, src_c_type, dst_c_type,
+                self.generate_call(dict, &std::collections::HashMap::new(), 0)
+            );
+
+        LdmcPrimCMorphism {
+            symbol,
+            type_args: Vec::new(),
+            src_type,
+            dst_type,
+            c_source
+        }
+    }
+*/
+    pub fn new_struct_map(
+        dict: &mut impl laddertypes::TypeDict,
+        morph_base: &MorphismBase<LdmcMorphism>,
+        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 mut member_morphisms = Vec::new();
+
+        for (field_name, dst_type) in dst_struct.members.iter() {
+            let mut src_type = None;
+            for (src_name, st) in src_struct.members.iter() {
+                if src_name == field_name {
+                    src_type = Some(st.clone());
+                }
+            }
+            let src_type = src_type.expect(&format!("cant find member {} in src struct", field_name));
+
+            if src_type == *dst_type {
+                member_morphisms.push(
+                    StructFieldMorphism {
+                        field_name: field_name.to_string(),
+                        item_morph: None,
+                        src_offset: src_struct.get_offset( field_name ),
+                        dst_offset: dst_struct.get_offset( field_name ),
+                    }
+                );
+            } else {
+                match morph_base.find_morphism(
+                    &laddertypes::MorphismType {
+                        src_type: src_type.clone(),
+                        dst_type: dst_type.clone()
+                    },
+                    dict
+                ) {
+                    Some(item_morph) => {
+                        let morph_symb = format!("morph_{}_to_{}",
+                            encode_type_to_symbol(dict, &src_type),
+                            encode_type_to_symbol(dict, &dst_type)
+                        );
+                        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.σ))),
+                                src_offset: src_struct.get_offset( field_name ),
+                                dst_offset: dst_struct.get_offset( field_name ),
+                            }
+                        );
+                    },
+
+                    None => {
+                        eprintln!("cant map field {}", field_name);
+                    }
+                }
+            }
+        }
+
+        LdmcMorphism::StructMap {
+            src_struct, dst_struct,
+            member_morphisms
+        }
     }
 }
 
@@ -47,6 +155,12 @@ impl Morphism for LdmcMorphism {
                     src_type: laddertypes::TypeTerm::App(vec![ value_delim_type.clone(), item_morph.src_type.clone() ]),
                     dst_type: laddertypes::TypeTerm::App(vec![ value_delim_type.clone(), item_morph.dst_type.clone() ]),
                 }
+            },
+            LdmcMorphism::StructMap { src_struct, dst_struct, member_morphisms } => {
+                laddertypes::MorphismType {
+                    src_type: src_struct.get_type(),
+                    dst_type: dst_struct.get_type()
+                }
             }
         }.normalize()
     }
diff --git a/src/struct_layout.rs b/src/struct_layout.rs
new file mode 100644
index 0000000..d961602
--- /dev/null
+++ b/src/struct_layout.rs
@@ -0,0 +1,167 @@
+
+use laddertypes::{parser::*, unparser::*, SugaredStructMember, SugaredTypeTerm, TypeDict, TypeTerm};
+
+#[derive(Clone, Copy, Debug)]
+pub enum ObjectSize {
+    Static(u64),
+    Dynamic(/* function to get size at runtime */),
+    Unknown
+}
+
+
+pub fn get_type_size( dict: &mut impl TypeDict, ty: TypeTerm ) -> ObjectSize {
+    let ty = ty.clone().get_lnf_vec().last().unwrap().clone();
+
+    if ty == dict.parse("native.UInt8").expect("") {
+        return ObjectSize::Static(1);
+    }
+    if ty == dict.parse("native.UInt16").expect("") {
+        return ObjectSize::Static(2);
+    }
+    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);
+    }
+
+    if let Some(layout) = StructLayout::parse( dict, ty ) {
+        return layout.get_size();
+    }
+
+    ObjectSize::Unknown
+}
+
+#[derive(Clone, Copy, Debug, PartialEq)]
+enum LayoutType {
+    Natural,
+    Packed
+}
+
+#[derive(Clone, Debug)]
+pub struct StructLayout {
+    ty: laddertypes::TypeTerm,
+    item_type: laddertypes::TypeTerm,
+    pub members: Vec< (String, laddertypes::TypeTerm) >,
+    offsets: std::collections::HashMap< String, u64 >,
+    size: ObjectSize
+}
+
+impl StructLayout {
+    pub fn get_type(&self) -> TypeTerm {
+        self.ty.clone()
+    }
+
+    pub fn get_size(&self) -> ObjectSize {
+        self.size
+    }
+
+    pub fn get_offset(&self, name: &String) -> u64 {
+        *self.offsets.get(name).expect("")
+    }
+
+    pub fn calculate_offsets(&mut self, dict: &mut impl TypeDict) {
+        let layout_type = LayoutType::Natural;
+        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");
+            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);
+                        }
+                    }
+
+                    // take offset
+                    self.offsets.insert(field_name.clone(), offset);
+
+                    // advance by current size
+                    offset += field_size;
+                }
+                ObjectSize::Dynamic() => {
+                    eprintln!("dynamically sized Field in struct!");
+                    self.offsets.insert(field_name.clone(), offset);
+                    self.size = ObjectSize::Dynamic();
+                    return;
+                }
+                ObjectSize::Unknown => {
+                    eprintln!("unknown field size!");
+                    self.offsets.insert(field_name.clone(), offset);
+                    self.size = ObjectSize::Unknown;
+                    return;
+                }
+            }
+        }
+
+        match self.size {
+            ObjectSize::Dynamic() => {
+
+            }
+            _ => {
+                self.size = ObjectSize::Static(offset);
+            }
+        }
+    }
+
+    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> {
+        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)));
+                }
+
+                let mut sl = StructLayout {
+                    ty: TypeTerm::unit(),
+                    item_type,
+                    members,
+                    offsets: std::collections::HashMap::new(),
+                    size: ObjectSize::Unknown
+                };
+
+                sl.calculate_offsets(dict);
+                sl.calculate_type(dict);
+
+                Some(sl)
+            }
+
+            _ => {
+                eprintln!("not a struct");
+                None
+            }
+        }
+    }
+
+    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);
+
+    }
+}