From 45453a04f4631503ae8e6e5ff52d186b2ea0224c Mon Sep 17 00:00:00 2001
From: Michael Sippel <micha@fragmental.art>
Date: Sat, 15 Mar 2025 19:37:03 +0100
Subject: [PATCH] split main.rs into separate files

---
 src/c_gen.rs    | 363 ++++++++++++++++++++++++++++++++++
 src/main.rs     | 514 ++----------------------------------------------
 src/morphism.rs |  78 ++++++++
 src/parser.rs   |  80 ++++++++
 4 files changed, 535 insertions(+), 500 deletions(-)
 create mode 100644 src/c_gen.rs
 create mode 100644 src/morphism.rs
 create mode 100644 src/parser.rs

diff --git a/src/c_gen.rs b/src/c_gen.rs
new file mode 100644
index 0000000..8b7f938
--- /dev/null
+++ b/src/c_gen.rs
@@ -0,0 +1,363 @@
+use {
+    laddertypes::{TypeDict, TypeTerm, parser::*, unparser::*, morphism::{Morphism, MorphismInstance}},
+    crate::morphism::{LdmcPrimCMorphism, LdmcMorphism}
+};
+
+/*
+*/
+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("x86.UInt8").expect("parse")
+            || t == &dict.parse("<StaticLength 8 Bit>").expect("parse")
+            {
+                Some("uint8_t".into())
+            } else if t == &dict.parse("x86.UInt16").expect("parse") {
+                Some("uint16_t".into())
+            } else if t == &dict.parse("x86.UInt32").expect("parse") {
+                Some("uint32_t".into())
+            } else if t == &dict.parse("x86.UInt64").expect("parse") {
+                Some("uint64_t".into())
+            } else {
+                match t {
+                    laddertypes::TypeTerm::App(args) => {
+                        if args[0] == laddertypes::TypeTerm::TypeID(dict.get_typeid(&"LengthPrefix".into()).unwrap())
+                        {
+                            let _length_type = args[1].clone();
+                            let item_c_type : String = get_c_repr_type(dict, args[2].clone(), false)?;
+                            match item_c_type.as_str() {
+                                "uint8_t" => Some(format!("struct LengthPrefixUInt8Array")),
+                                "uint16_t" => Some(format!("struct LengthPrefixUInt16Array")),
+                                "uint32_t" => Some(format!("struct LengthPrefixUInt32Array")),
+                                "uint64_t" => Some(format!("struct LengthPrefixUInt64Array")),
+                                _ => None
+                            }
+                        }
+                        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 {
+                            None
+                        }
+                    }
+
+                    _ => None
+                }
+            }
+        }
+        None => None
+    }
+}
+
+
+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)
+        }
+        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('_');
+                s.push_str(&encode_type_to_symbol(dict, r));
+            }
+            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) {
+    let mut i = 0;
+
+    /* todo: collect include files from morphism base */
+    println!(r#"
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdint.h>
+#include <stdbool.h>
+"#);
+
+    let mut existing_instantiations = Vec::new();
+    for morph_inst in path.iter() {
+        match &morph_inst.m {
+            LdmcMorphism::Primitive( item_morph ) => {
+                let name = item_morph.instantiated_symbol_name(type_dict, &morph_inst.σ);
+                if ! existing_instantiations.contains(&name) {
+                    if let Some(s) = item_morph.generate_instantiation(type_dict, &morph_inst.σ) {
+                        println!("{}", s);
+                    } else {
+                        eprintln!("couldnt generate instance {}", name);
+                    }
+                    existing_instantiations.push( name );
+                }
+            }
+            LdmcMorphism::LengthPrefixMap { length_prefix_type, item_morph } => {
+                let name = item_morph.instantiated_symbol_name(type_dict, &morph_inst.σ);
+                if ! existing_instantiations.contains(&name) {
+                    if let Some(s) = item_morph.generate_instantiation(type_dict, &morph_inst.σ) {
+                        println!("{}", s);
+                    } else {
+                        eprintln!("couldnt generate instance {}", name);
+                    }
+
+                    existing_instantiations.push( name );
+                }
+            }
+            _ => {}
+        }
+    }
+
+    println!(r#"
+int main() {{
+uint8_t bufA[1024];
+uint8_t bufB[1024];
+
+char in_str[] = "read :: {} \n";
+char out_str[]= "write:: {} \n";
+write(2, in_str, strlen(in_str));
+write(2, out_str, strlen(out_str));
+
+int l = read(0, bufA, 1024);
+fprintf(stderr, "read  %d bytes\n", l);
+
+        "#,
+        type_dict.unparse(&src_type).replace("\\", "\\\\"),
+        type_dict.unparse(&dst_type).replace("\\", "\\\\") );
+
+    for morph_inst in path.iter() {
+        println!(r#"
+/* morph to {}
+
+...with
+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);
+        i += 1;
+    }
+
+    let out_buf = if i%2==0 { "bufA" } else { "bufB" };
+
+    let is_string = false;
+    if let Ok((halo, σ)) = laddertypes::subtype_unify(
+        &dst_type,
+        &type_dict.parse("<Seq~<ValueTerminated 0> x86.UInt8>").unwrap()
+    ) {
+        println!(r#"
+printf("%s\n", {});"#, out_buf);
+    } else if let Ok((halo, σ)) = laddertypes::subtype_unify(
+        &dst_type,
+        &type_dict.parse("<Seq~<LengthPrefix x86.UInt64> x86.UInt8>").unwrap()
+    ) {
+        println!(r#"
+        /* write output
+         */
+        {{
+            struct LengthPrefixUInt8Array * buf = (void*){};
+            write(1, {}, sizeof(uint64_t) + buf->len);
+        }}"#, out_buf, out_buf);
+    } else {
+        println!(r#"
+write(1, {}, {});"#,
+            out_buf,
+            1024
+        );
+    }
+
+
+    println!(r#"
+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) {
+                s.push_str(&format!("    #define {} {}\n", dict.get_typename(&ty_id).unwrap(), encode_type_to_value(dict, val)));
+            }
+        }
+
+        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 generate_call(&self, dict: &mut impl TypeDict, σ: &std::collections::HashMap<laddertypes::TypeID, laddertypes::TypeTerm>, i: u64) {
+        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" };
+
+                println!(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_c_type = get_c_repr_type(dict, self.get_type().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, self.get_type().dst_type.clone().apply_substitution(&|k| σ.get(k).cloned()).clone(), true).expect("cant get c-repr type for dst type");
+
+                let map_fn = match (src_c_type.as_str(), dst_c_type.as_str()) {
+                    ("struct LengthPrefixUInt64Array", "struct LengthPrefixUInt64Array") => "length_prefix_array_map_64_to_64",
+                    ("struct LengthPrefixUInt8Array", "struct LengthPrefixUInt64Array") => "length_prefix_array_map_8_to_64",
+                    ("struct LengthPrefixUInt64Array", "struct LengthPrefixUInt8Array") => "length_prefix_array_map_64_to_8",
+                    ("struct LengthPrefixUInt8Array", "struct LengthPrefixUInt8Array") => "length_prefix_array_map_8_to_8",
+                    _ => {
+                        "{{ ERROR: no map function implemented }}"
+                    }
+                };
+
+                let src_buf = if i%2 == 0 { "bufA" } else { "bufB" };
+                let dst_buf = if i%2 == 0 { "bufB" } else { "bufA" };
+                println!(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" };
+                println!(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, σ),
+                    '}');
+            }
+        }
+    }
+}
diff --git a/src/main.rs b/src/main.rs
index 13e5516..0e5c87d 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,3 +1,8 @@
+
+mod morphism;
+mod parser;
+mod c_gen;
+
 use {
     ariadne::{Color, Label, Report, ReportKind, Source},
     chumsky::{
@@ -7,395 +12,15 @@ use {
         dict::TypeDict, parser::ParseLadderType, subtype_unify, unparser::UnparseLadderType, BimapTypeDict, Morphism, MorphismType
     },
     std::{any::Any, sync::{Arc, RwLock}},
-    tiny_ansi::TinyAnsi
+    tiny_ansi::TinyAnsi,
+
+
+    crate::{
+        morphism::LdmcMorphism,
+        parser::morphism_base_parser,
+    }
 };
 
-/*
-*/
-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("x86.UInt8").expect("parse")
-            || t == &dict.parse("<StaticLength 8 Bit>").expect("parse")
-            {
-                Some("uint8_t".into())
-            } else if t == &dict.parse("x86.UInt16").expect("parse") {
-                Some("uint16_t".into())
-            } else if t == &dict.parse("x86.UInt32").expect("parse") {
-                Some("uint32_t".into())
-            } else if t == &dict.parse("x86.UInt64").expect("parse") {
-                Some("uint64_t".into())
-            } else {
-                match t {
-                    laddertypes::TypeTerm::App(args) => {
-                        if args[0] == laddertypes::TypeTerm::TypeID(dict.get_typeid(&"LengthPrefix".into()).unwrap())
-                        {
-                            let _length_type = args[1].clone();
-                            let item_c_type : String = get_c_repr_type(dict, args[2].clone(), false)?;
-                            match item_c_type.as_str() {
-                                "uint8_t" => Some(format!("struct LengthPrefixUInt8Array")),
-                                "uint16_t" => Some(format!("struct LengthPrefixUInt16Array")),
-                                "uint32_t" => Some(format!("struct LengthPrefixUInt32Array")),
-                                "uint64_t" => Some(format!("struct LengthPrefixUInt64Array")),
-                                _ => None
-                            }
-                        }
-                        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 {
-                            None
-                        }
-                    }
-
-                    _ => None
-                }
-            }
-        }
-        None => None
-    }
-}
-
-#[derive(Clone, Debug)]
-struct LdmcPrimCMorphism {
-    symbol: String,
-    type_args: Vec<(laddertypes::TypeID, String)>,
-    src_type: laddertypes::TypeTerm,
-    dst_type: laddertypes::TypeTerm,
-    c_source: String
-}
-
-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)
-        }
-        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('_');
-                s.push_str(&encode_type_to_symbol(dict, r));
-            }
-            s
-        }
-    }
-}
-
-fn encode_type_to_value(dict: &mut impl TypeDict, t: &laddertypes::TypeTerm) -> String {
-    dict.unparse(t)
-}
-
-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) {
-                s.push_str(&format!("    #define {} {}\n", dict.get_typename(&ty_id).unwrap(), encode_type_to_value(dict, val)));
-            }
-        }
-
-        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)
-    }
-}
-
-#[derive(Clone)]
-enum LdmcMorphism {
-    Primitive( LdmcPrimCMorphism ),
-    LengthPrefixMap{
-        length_prefix_type: laddertypes::TypeTerm,
-        item_morph: Box<LdmcPrimCMorphism>
-    },
-    ValueDelimMap{
-        delim: u64,
-        item_morph: Box<LdmcPrimCMorphism>
-    }
-}
-
-impl LdmcMorphism {
-    pub fn generate_call(&self, dict: &mut impl TypeDict, σ: &std::collections::HashMap<laddertypes::TypeID, laddertypes::TypeTerm>, i: u64) {
-        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" };
-
-                println!(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_c_type = get_c_repr_type(dict, self.get_type().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, self.get_type().dst_type.clone().apply_substitution(&|k| σ.get(k).cloned()).clone(), true).expect("cant get c-repr type for dst type");
-
-                let map_fn = match (src_c_type.as_str(), dst_c_type.as_str()) {
-                    ("struct LengthPrefixUInt64Array", "struct LengthPrefixUInt64Array") => "length_prefix_array_map_64_to_64",
-                    ("struct LengthPrefixUInt8Array", "struct LengthPrefixUInt64Array") => "length_prefix_array_map_8_to_64",
-                    ("struct LengthPrefixUInt64Array", "struct LengthPrefixUInt8Array") => "length_prefix_array_map_64_to_8",
-                    ("struct LengthPrefixUInt8Array", "struct LengthPrefixUInt8Array") => "length_prefix_array_map_8_to_8",
-                    _ => {
-                        "{{ ERROR: no map function implemented }}"
-                    }
-                };
-
-                let src_buf = if i%2 == 0 { "bufA" } else { "bufB" };
-                let dst_buf = if i%2 == 0 { "bufB" } else { "bufA" };
-                println!(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" };
-                println!(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, σ),
-                    '}');
-            }
-        }
-    }
-}
-
-impl Morphism for LdmcMorphism {
-    fn weight(&self) -> u64 {
-        1
-    }
-
-    fn get_type(&self) -> laddertypes::MorphismType {
-        match self {
-            LdmcMorphism::Primitive(prim_morph) =>
-                laddertypes::MorphismType {
-                    src_type: prim_morph.src_type.clone().normalize(),
-                    dst_type: prim_morph.dst_type.clone().normalize()
-                },
-            LdmcMorphism::LengthPrefixMap{ length_prefix_type, item_morph } => {
-                laddertypes::MorphismType {
-                    src_type: laddertypes::TypeTerm::App(vec![ length_prefix_type.clone(), item_morph.src_type.clone() ]),
-                    dst_type: laddertypes::TypeTerm::App(vec![ length_prefix_type.clone(), item_morph.dst_type.clone() ]),
-                }
-            },
-            LdmcMorphism::ValueDelimMap{ delim, item_morph } => {
-                let value_delim_type = laddertypes::TypeTerm::App(vec![]);
-                laddertypes::MorphismType {
-                    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() ]),
-                }
-            }
-        }.normalize()
-    }
-
-    fn map_morphism(&self, seq_type: laddertypes::TypeTerm) -> Option< Self > {
-        match self {
-            LdmcMorphism::Primitive(prim) => {
-                let item_morph = Box::new(prim.clone());
-/*
-                if seq_type == self.length_prefix_type {
-                */
-                    Some(LdmcMorphism::LengthPrefixMap{
-                        length_prefix_type: seq_type,
-                        item_morph,
-                    })
-                    /*
-                } else if seq_type == self.value_delim_type {
-                    Some(LdmcMorphism::ValueDelimMap { delim, item_morph })
-                } else {
-                    None
-                }
-                */
-            }
-            _ => None
-        }
-    }
-}
-
-/* morphism-base text format:
- *     NAME '(' [TYPE-ARG-NAME ':' KIND]  ')'
- *           SRC-TYPE
- *     '-->' DST-TYPE
- *     ```
- *          TEMPLATE-CODE
- *     ```
- */
-fn parser(
-    type_dict: Arc<RwLock< BimapTypeDict >>
-) -> impl Parser<char, (String, Vec<LdmcPrimCMorphism>), Error = Simple<char>> {
-
-    just("```")
-    .then(take_until(just("```")))
-    .map(
-        move |(a, (b, c))| {
-            b.iter().collect()
-        }
-    )
-
-    // morph name
-    .then(
-        ident().padded()
-
-    // type args
-    .then(
-        ident().padded()
-        .then_ignore(just(":").padded())
-        .then(none_of(",)").repeated().padded())
-        .separated_by(just(",").padded())
-        .delimited_by(just("("), just(")"))
-    )
-
-    // newline
-    .then_ignore(just('\n'))
-
-    // src type
-    .then(take_until(just("-->").ignored()))
-    // dst_type
-    .then(take_until(just("```")))
-
-    // c sourcecode template
-    .then(take_until(just("```")))
-
-    .map(
-        move |((((symbol, type_args), (src_type, _)), (dst_type, _)), (c_source, _))| {
-            let c_source = c_source.iter().collect();
-            let mut type_dict = type_dict.write().unwrap();
-            let type_args : Vec<_> = type_args.into_iter().map(|(v,k)| (v,k.into_iter().collect())).collect();
-            let mut ty_args = Vec::new();
-            for (var, kind) in type_args.into_iter() {
-                let var_id = type_dict.add_varname(var.clone());
-                ty_args.push((var_id, kind));
-            }
-
-            let mut src_type = type_dict.parse(&src_type.iter().collect::<String>()).expect("couldnt parse src type");
-            let mut dst_type = type_dict.parse(&dst_type.iter().collect::<String>()).expect("couldnt parse dst type");
-
-            LdmcPrimCMorphism {
-                symbol,
-                type_args: ty_args,
-                src_type,
-                dst_type,
-                c_source
-            }
-        })
-        .separated_by(text::newline())
-
-    )
-}
-
 fn main() {
     let mut type_dict = Arc::new(RwLock::new(BimapTypeDict::new()));
     let mut morphism_base = laddertypes::MorphismBase::<LdmcMorphism>::new(vec![
@@ -410,7 +35,7 @@ fn main() {
 
     for mb_path in args {
         let src = std::fs::read_to_string(mb_path.clone()).expect("read");
-        let result = parser(type_dict.clone()).parse(src.clone());
+        let result = morphism_base_parser(type_dict.clone()).parse(src.clone());
         match result {
             Ok((includes, morphisms)) => {
                 eprintln!("[{}] parse ok.", mb_path.bright_yellow());
@@ -447,118 +72,7 @@ fn main() {
 
     match path {
         Some(path) => {
-            let mut i = 0;
-
-            /* todo: collect include files from morphism base */
-            println!(r#"
-#include <stdio.h>
-#include <unistd.h>
-#include <string.h>
-#include <stdint.h>
-#include <stdbool.h>
-"#);
-
-            let mut existing_instantiations = Vec::new();
-            for morph_inst in path.iter() {
-                match &morph_inst.m {
-                    LdmcMorphism::Primitive( item_morph ) => {
-                        let name = item_morph.instantiated_symbol_name(&mut type_dict, &morph_inst.σ);
-                        if ! existing_instantiations.contains(&name) {
-                            if let Some(s) = item_morph.generate_instantiation(&mut type_dict, &morph_inst.σ) {
-                                println!("{}", s);
-                            } else {
-                                eprintln!("couldnt generate instance {}", name);
-                            }
-                            existing_instantiations.push( name );
-                        }
-                    }
-                    LdmcMorphism::LengthPrefixMap { length_prefix_type, item_morph } => {
-                        let name = item_morph.instantiated_symbol_name(&mut type_dict, &morph_inst.σ);
-                        if ! existing_instantiations.contains(&name) {
-                            if let Some(s) = item_morph.generate_instantiation(&mut type_dict, &morph_inst.σ) {
-                                println!("{}", s);
-                            } else {
-                                eprintln!("couldnt generate instance {}", name);
-                            }
-
-                            existing_instantiations.push( name );
-                        }
-                    }
-                    _ => {}
-                }
-            }
-
-            println!(r#"
-int main() {{
-    uint8_t bufA[1024];
-    uint8_t bufB[1024];
-
-    char in_str[] = "read :: {} \n";
-    char out_str[]= "write:: {} \n";
-    write(2, in_str, strlen(in_str));
-    write(2, out_str, strlen(out_str));
-
-    int l = read(0, bufA, 1024);
-    fprintf(stderr, "read  %d bytes\n", l);
-
-                "#,
-                type_dict.unparse(&src_type).replace("\\", "\\\\"),
-                type_dict.unparse(&dst_type).replace("\\", "\\\\") );
-            for morph_inst in path.iter() {
-                println!(r#"
-    /* morph to {}
-
-    ...with
-    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(&mut type_dict, &morph_inst.σ, i);
-                i += 1;
-            }
-
-            let out_buf = if i%2==0 { "bufA" } else { "bufB" };
-
-            let is_string = false;
-            if let Ok((halo, σ)) = laddertypes::subtype_unify(
-                &dst_type,
-                &type_dict.parse("<Seq~<ValueTerminated 0> x86.UInt8>").unwrap()
-            ) {
-                println!(r#"
-    printf("%s\n", {});"#, out_buf);
-            } else if let Ok((halo, σ)) = laddertypes::subtype_unify(
-                &dst_type,
-                &type_dict.parse("<Seq~<LengthPrefix x86.UInt64> x86.UInt8>").unwrap()
-            ) {
-                println!(r#"
-                /* write output
-                 */
-                {{
-                    struct LengthPrefixUInt8Array * buf = (void*){};
-                    write(1, {}, sizeof(uint64_t) + buf->len);
-                }}"#, out_buf, out_buf);
-            } else {
-                println!(r#"
-    write(1, {}, {});"#,
-                    out_buf,
-                    1024
-                );
-            }
-
-
-            println!(r#"
-    return 0;
-}}
-            "#);
-
-            eprintln!("Success: generated C code");
+            c_gen::generate_main(&mut type_dict, path, src_type, dst_type);
         }
         None => {
             eprintln!("Error: could not find morphism path");
diff --git a/src/morphism.rs b/src/morphism.rs
new file mode 100644
index 0000000..da573dc
--- /dev/null
+++ b/src/morphism.rs
@@ -0,0 +1,78 @@
+
+use {
+    laddertypes::{TypeDict, morphism::Morphism},
+};
+
+#[derive(Clone, Debug)]
+pub struct LdmcPrimCMorphism {
+    pub symbol: String,
+    pub type_args: Vec<(laddertypes::TypeID, String)>,
+    pub src_type: laddertypes::TypeTerm,
+    pub dst_type: laddertypes::TypeTerm,
+    pub c_source: String
+}
+
+#[derive(Clone)]
+pub enum LdmcMorphism {
+    Primitive( LdmcPrimCMorphism ),
+    LengthPrefixMap{
+        length_prefix_type: laddertypes::TypeTerm,
+        item_morph: Box<LdmcPrimCMorphism>
+    },
+    ValueDelimMap{
+        delim: u64,
+        item_morph: Box<LdmcPrimCMorphism>
+    }
+}
+
+impl Morphism for LdmcMorphism {
+    fn weight(&self) -> u64 {
+        1
+    }
+
+    fn get_type(&self) -> laddertypes::MorphismType {
+        match self {
+            LdmcMorphism::Primitive(prim_morph) =>
+                laddertypes::MorphismType {
+                    src_type: prim_morph.src_type.clone().normalize(),
+                    dst_type: prim_morph.dst_type.clone().normalize()
+                },
+            LdmcMorphism::LengthPrefixMap{ length_prefix_type, item_morph } => {
+                laddertypes::MorphismType {
+                    src_type: laddertypes::TypeTerm::App(vec![ length_prefix_type.clone(), item_morph.src_type.clone() ]),
+                    dst_type: laddertypes::TypeTerm::App(vec![ length_prefix_type.clone(), item_morph.dst_type.clone() ]),
+                }
+            },
+            LdmcMorphism::ValueDelimMap{ delim, item_morph } => {
+                let value_delim_type = laddertypes::TypeTerm::App(vec![]);
+                laddertypes::MorphismType {
+                    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() ]),
+                }
+            }
+        }.normalize()
+    }
+
+    fn map_morphism(&self, seq_type: laddertypes::TypeTerm) -> Option< Self > {
+        match self {
+            LdmcMorphism::Primitive(prim) => {
+                let item_morph = Box::new(prim.clone());
+/*
+                if seq_type == self.length_prefix_type {
+                */
+                    Some(LdmcMorphism::LengthPrefixMap{
+                        length_prefix_type: seq_type,
+                        item_morph,
+                    })
+                    /*
+                } else if seq_type == self.value_delim_type {
+                    Some(LdmcMorphism::ValueDelimMap { delim, item_morph })
+                } else {
+                    None
+                }
+                */
+            }
+            _ => None
+        }
+    }
+}
diff --git a/src/parser.rs b/src/parser.rs
new file mode 100644
index 0000000..76b497c
--- /dev/null
+++ b/src/parser.rs
@@ -0,0 +1,80 @@
+use {
+    chumsky::{
+        prelude::*, text::*
+    },
+    std::sync::{Arc, RwLock},
+
+    laddertypes::{TypeDict, BimapTypeDict, parser::*},
+    crate::morphism::LdmcPrimCMorphism
+};
+
+/* morphism-base text format:
+ *     NAME '(' [TYPE-ARG-NAME ':' KIND]  ')'
+ *           SRC-TYPE
+ *     '-->' DST-TYPE
+ *     ```
+ *          TEMPLATE-CODE
+ *     ```
+ */
+pub fn morphism_base_parser(
+    type_dict: Arc<RwLock< BimapTypeDict >>
+) -> impl Parser<char, (String, Vec<LdmcPrimCMorphism>), Error = Simple<char>> {
+
+    just("```")
+    .then(take_until(just("```")))
+    .map(
+        move |(a, (b, c))| {
+            b.iter().collect()
+        }
+    )
+
+    // morph name
+    .then(
+        ident().padded()
+
+    // type args
+    .then(
+        ident().padded()
+        .then_ignore(just(":").padded())
+        .then(none_of(",)").repeated().padded())
+        .separated_by(just(",").padded())
+        .delimited_by(just("("), just(")"))
+    )
+
+    // newline
+    .then_ignore(just('\n'))
+
+    // src type
+    .then(take_until(just("-->").ignored()))
+    // dst_type
+    .then(take_until(just("```")))
+
+    // c sourcecode template
+    .then(take_until(just("```")))
+
+    .map(
+        move |((((symbol, type_args), (src_type, _)), (dst_type, _)), (c_source, _))| {
+            let c_source = c_source.iter().collect();
+            let mut type_dict = type_dict.write().unwrap();
+            let type_args : Vec<_> = type_args.into_iter().map(|(v,k)| (v,k.into_iter().collect())).collect();
+            let mut ty_args = Vec::new();
+            for (var, kind) in type_args.into_iter() {
+                let var_id = type_dict.add_varname(var.clone());
+                ty_args.push((var_id, kind));
+            }
+
+            let mut src_type = type_dict.parse(&src_type.iter().collect::<String>()).expect("couldnt parse src type");
+            let mut dst_type = type_dict.parse(&dst_type.iter().collect::<String>()).expect("couldnt parse dst type");
+
+            LdmcPrimCMorphism {
+                symbol,
+                type_args: ty_args,
+                src_type,
+                dst_type,
+                c_source
+            }
+        })
+        .separated_by(text::newline())
+
+    )
+}