diff --git a/morphisms/Makefile b/morphisms/Makefile
index 439499a..884f9dc 100644
--- a/morphisms/Makefile
+++ b/morphisms/Makefile
@@ -22,10 +22,10 @@ code-size-benchmark: posint-dec-to-hex-generated-gcc \
 					posint-dec-to-hex-generated-clang \
 				 	posint-dec-to-hex-optimal-gcc \
 					posint-dec-to-hex-optimal-clang
-	INST_COUNT_GEN_GCC=$(shell gdb --batch -ex "file posint-dec-to-hex-generated-gcc" -ex "disassemble main" | wc -l)
-	INST_COUNT_GEN_CLANG=$(shell gdb --batch -ex "file posint-dec-to-hex-generated-clang" -ex "disassemble main" | wc -l)
-	INST_COUNT_OPT_GCC=$(shell gdb --batch -ex "file posint-dec-to-hex-optimal-gcc" -ex "disassemble main" | wc -l)
-	INST_COUNT_OPT_CLANG=$(shell gdb --batch -ex "file posint-dec-to-hex-optimal-clang" -ex "disassemble main" | wc -l)
+	INST_COUNT_GEN_GCC=$(shell gdb --batch -ex "file posint-dec-to-hex-generated-gcc" -ex "disassemble morph_posint_radix" | wc -l)
+	INST_COUNT_GEN_CLANG=$(shell gdb --batch -ex "file posint-dec-to-hex-generated-clang" -ex "disassemble morph_posint_radix" | wc -l)
+	INST_COUNT_OPT_GCC=$(shell gdb --batch -ex "file posint-dec-to-hex-optimal-gcc" -ex "disassemble morph_posint_radix" | wc -l)
+	INST_COUNT_OPT_CLANG=$(shell gdb --batch -ex "file posint-dec-to-hex-optimal-clang" -ex "disassemble posint_radix" | wc -l)
 
 clean:
 	rm $(TARGETS)
diff --git a/morphisms/include/morphisms/length-prefix.h b/morphisms/include/array/length-prefix.h
similarity index 85%
rename from morphisms/include/morphisms/length-prefix.h
rename to morphisms/include/array/length-prefix.h
index d3eb76f..844340c 100644
--- a/morphisms/include/morphisms/length-prefix.h
+++ b/morphisms/include/array/length-prefix.h
@@ -63,17 +63,3 @@ int length_prefix_array_map_64_to_8(
     struct LengthPrefixUInt64Array const * restrict src,
     struct LengthPrefixUInt8Array * restrict dst
 );
-
-
-/*
- * Morphisms
- */
-
-int morph_string_as_nullterm_to_length_prefix(
-    char const * restrict src,
-    struct LengthPrefixUInt8Array * restrict dst
-);
-int morph_string_as_length_prefix_to_nullterm(
-    struct LengthPrefixUInt8Array const * restrict src,
-    char * restrict dst
-);
diff --git a/morphisms/include/morphisms/posint.h b/morphisms/include/morphisms/posint.h
deleted file mode 100644
index 8c458da..0000000
--- a/morphisms/include/morphisms/posint.h
+++ /dev/null
@@ -1,35 +0,0 @@
-#pragma once
-#include <stdint.h>
-#include <morphisms/length-prefix.h>
-
-int morph_digit_as_char_to_uint8(
-    //uint64_t const radix,
-    uint8_t const * restrict src,
-    uint8_t * restrict dst
-);
-int morph_digit_as_char_to_uint64(
-    //uint64_t const radix,
-    uint8_t const * restrict src,
-    uint64_t * restrict dst
-);
-int morph_digit_as_uint8_to_char(
-    //uint64_t const radix,
-    uint8_t const * restrict src,
-    uint8_t * restrict dst
-);
-int morph_digit_as_uint64_to_char(
-    //uint64_t const radix,
-    uint64_t const * restrict src,
-    uint8_t * restrict dst
-);
-int morph_posint_endianness(
-    uint64_t const radix,
-    struct LengthPrefixUInt64Array const * restrict src,
-    struct LengthPrefixUInt64Array * restrict dst
-);
-int morph_posint_radix(
-    uint64_t const src_radix,
-    uint64_t const dst_radix,
-    struct LengthPrefixUInt64Array const * restrict src,
-    struct LengthPrefixUInt64Array * restrict dst
-);
diff --git a/morphisms/morphism-base/digit.morphism-base b/morphisms/morphism-base/digit.morphism-base
new file mode 100644
index 0000000..0abff91
--- /dev/null
+++ b/morphisms/morphism-base/digit.morphism-base
@@ -0,0 +1,67 @@
+morph_digit_as_char_to_uint8 (Radix:ℤ)
+      <Digit Radix> ~ Char ~ Ascii ~ x86.UInt8
+-->   <Digit Radix> ~ x86.UInt8
+```
+    if( *src >= '0' && *src <= '9' )
+        *dst = *src - '0';
+    else if( *src >= 'a' && *src <= 'f')
+        *dst = 0xa + *src - 'a';
+    else if( *src >= 'A' && *src <= 'F')
+        *dst = 0xa + *src - 'A';
+    else
+        return -1;
+
+    if( *dst < Radix ) {
+        return 0;
+    } else {
+        return -1;
+    }
+```
+
+morph_digit_as_char_to_uint64 (Radix:ℤ)
+      <Digit Radix> ~ Char ~ Ascii ~ x86.UInt8
+-->   <Digit Radix> ~ x86.UInt64
+```
+    if( *src >= '0' && *src <= '9' )
+        *dst = *src - '0';
+    else if( *src >= 'a' && *src <= 'f')
+        *dst = 0xa + *src - 'a';
+    else if( *src >= 'A' && *src <= 'F')
+        *dst = 0xa + *src - 'A';
+    else
+        return -1;
+
+    if( *dst < Radix ) {
+        return 0;
+    } else {
+        return -1;
+    }
+```
+
+morph_digit_as_uint8_to_char (Radix:ℤ_16)
+      <Digit Radix> ~ x86.UInt8
+-->   <Digit Radix> ~ Char ~ Ascii ~ x86.UInt8
+```
+    if ( *src < 10 )
+        *dst = *src + '0';
+    else if( *dst < 16 )
+        *dst = *src - 0xa + 'a';
+    else
+        return -1;
+
+    return 0;
+```
+
+morph_digit_as_uint64_to_char (Radix:ℤ_16)
+      <Digit Radix> ~ x86.UInt64
+-->   <Digit Radix> ~ Char ~ Ascii ~ x86.UInt8
+```
+    if ( *src < 10 )
+        *dst = *src + '0';
+    else if( *dst < 16 )
+        *dst = *src - 0xa + 'a';
+    else
+        return -1;
+
+    return 0;
+```
diff --git a/morphisms/morphism-base/length_prefix.morphism-base b/morphisms/morphism-base/length_prefix.morphism-base
index a5d9bd5..e5ad529 100644
--- a/morphisms/morphism-base/length_prefix.morphism-base
+++ b/morphisms/morphism-base/length_prefix.morphism-base
@@ -1,9 +1,24 @@
-morph_string_as_nullterm_to_length_prefix ()
-    <Seq~<ValueDelim '\0'> Char ~ Ascii ~ Byte>
---> <Seq~<LengthPrefix x86.UInt64> Char ~ Ascii ~ Byte>
-@lib/libmorph_length-prefix.so:src/length_prefix.c
+morph_array_as_valterm_to_lenpfx (Terminator:x86.UInt8)
+    <Seq~<ValueTerminated Terminator> x86.UInt8>
+--> <Seq~<LengthPrefix x86.UInt64> x86.UInt8>
+```
+    length_prefix_uint8_array_clear(dst);
+    while( *src != Terminator ) {
+        length_prefix_uint8_array_push(dst, *src);
+        src++;
+    }
 
-morph_string_as_length_prefix_to_nullterm ()
-    <Seq~<LengthPrefix x86.UInt64> Char ~ Ascii ~ Byte>
---> <Seq~<ValueDelim '\0'> Char ~ Ascii ~ Byte>
-@lib/libmorph_length-prefix.so:src/length_prefix.c
+    return 0;
+```
+
+morph_array_as_lenpfx_to_valterm (Terminator:x86.UInt8)
+    <Seq~<LengthPrefix x86.UInt64> x86.UInt8>
+--> <Seq~<ValueTerminated Terminator> x86.UInt8>
+```
+    for( uint64_t i = 0; i < src->len; ++i ) {
+        *dst ++ = src->items[i];
+    }
+    *dst = Terminator;
+
+    return 0;
+```
diff --git a/morphisms/morphism-base/posint.morphism-base b/morphisms/morphism-base/posint.morphism-base
index aeb5e37..81ea945 100644
--- a/morphisms/morphism-base/posint.morphism-base
+++ b/morphisms/morphism-base/posint.morphism-base
@@ -1,21 +1,58 @@
-morph_digit_as_char_to_uint8 (Radix:ℤ_16)
-    <Digit Radix> ~ Char ~ Ascii ~ Byte
---> <Digit Radix> ~ x86.UInt8 ~ Byte
-@lib/libmorph-posint.so:src/posint.c
-
-morph_digit_as_uint8_to_char (Radix:ℤ_16)
-      <Digit Radix> ~ x86.UInt8 ~ Byte
--->   <Digit Radix> ~ Char ~ Ascii ~ Byte
-@lib/libmorph-posint.so:src/posint.c
-
-morph_posint_radix (SrcRadix:ℤ, DstRadix:ℤ)
+morph_posint_radix_le (SrcRadix:ℤ, DstRadix:ℤ)
       ℕ
     ~ <PosInt SrcRadix LittleEndian>
     ~ <Seq~<LengthPrefix x86.UInt64> <Digit SrcRadix>~x86.UInt64>
 -->   ℕ
     ~ <PosInt DstRadix LittleEndian>
+    ~ <Seq~<LenghtPrefix x86.UInt64> <Digit DstRadix>~x86.UInt64>
+```
+    uint64_t value = 0;
+
+    for( uint64_t i = 0; i < src->len; ++i ) {
+        value *= SrcRadix;
+        value += src->items[src->len - i - 1];
+    }
+
+    length_prefix_uint64_array_clear( dst );
+
+    while( value > 0 ) {
+        length_prefix_uint64_array_push( dst, value % DstRadix );
+        value /= DstRadix;
+    }
+
+    return 0;
+```
+
+morph_posint_radix_be (SrcRadix:ℤ, DstRadix:ℤ)
+      ℕ
+    ~ <PosInt SrcRadix BigEndian>
+    ~ <Seq~<LengthPrefix x86.UInt64> <Digit SrcRadix>~x86.UInt64>
+-->   ℕ
+    ~ <PosInt DstRadix BigEndian>
     ~ <Seq~<LengthPrefix x86.UInt64> <Digit DstRadix>~x86.UInt64>
-@lib/libmorph-posint.so:src/posint.c
+```
+    uint64_t value = 0;
+
+    for( uint64_t i = 0; i < src->len; ++i ) {
+        value *= SrcRadix;
+        value += src->items[i];
+    }
+
+    uint64_t v = value;
+    dst->len = 0;
+    while( v ) {
+        dst->len++;
+        v /= DstRadix;
+    }
+
+    uint64_t i = dst->len;
+    while( value > 0 ) {
+        dst->items[--i] = ( dst, value % DstRadix );
+        value /= DstRadix;
+    }
+
+    return 0;
+```
 
 morph_posint_endianness (Radix:ℤ)
       ℕ
@@ -24,7 +61,9 @@ morph_posint_endianness (Radix:ℤ)
 -->   ℕ
     ~ <PosInt Radix BigEndian>
     ~ <Seq~<LengthPrefix x86.UInt64> <Digit Radix> ~ x86.UInt64>
-@lib/libmorph-posint.so:src/posint.c
+```
+    return length_prefix_uint64_array_reverse( src, dst );
+```
 
 morph_posint_endianness (Radix:ℤ)
       ℕ
@@ -33,4 +72,6 @@ morph_posint_endianness (Radix:ℤ)
 -->   ℕ
     ~ <PosInt Radix LittleEndian>
     ~ <Seq~<LengthPrefix x86.UInt64> <Digit Radix> ~ x86.UInt64>
-@lib/libmorph-posint.so:src/posint.c
+```
+    return length_prefix_uint64_array_reverse( src, dst );
+```
diff --git a/morphisms/posint-dec-to-hex-generated.c b/morphisms/posint-dec-to-hex-generated.c
index a942e66..bdba861 100644
--- a/morphisms/posint-dec-to-hex-generated.c
+++ b/morphisms/posint-dec-to-hex-generated.c
@@ -3,12 +3,11 @@
 #include <morphisms/length-prefix.h>
 #include <morphisms/posint.h>
 
-int main() {
-    uint8_t bufA[1024];
-    uint8_t bufB[1024];
-
-    scanf("%s", bufA);
-
+__attribute__((noinline))
+int morph_posint_radix(
+    uint8_t * bufA,
+    uint8_t * bufB
+) {
     // morph to
     //     ℕ ~ <PosInt 10 BigEndian> ~ [~<LengthPrefix x86.UInt64> <Digit 10> ~ Char ~ Ascii]
     {
@@ -23,40 +22,14 @@ int main() {
         struct LengthPrefixUInt8Array * src = (void*) bufB;
         struct LengthPrefixUInt64Array * dst = (void*) bufA;
         length_prefix_array_map_8_to_64( morph_digit_as_char_to_uint64, src, dst );
-/*
-        dst->len = src->len;
-        for( uint64_t i = 0; i < src->len; ++i )
-            morph_digit_as_char_to_uint64( &src->items[i], &dst->items[i] );
-*/
     }
-
-    // morph to
-    //    ℕ ~ <PosInt 10 LittleEndian> ~ [~<LengthPrefix x86.UInt64> <Digit 10> ~ ℤ_10 ~ x86.UInt64]
-    {
-        uint64_t const radix = 10;
-        struct LengthPrefixUInt64Array * src = (void*) bufA;
-        struct LengthPrefixUInt64Array * dst = (void*) bufB;
-        morph_posint_endianness( radix, src, dst );
-    }
-
-    // morph to
     //    ℕ ~ <PosInt 16 LittleEndian> ~ [~<LengthPrefix x86.UInt64> <Digit 16> ~ ℤ_16 ~ x86.UInt64]
     {
         uint64_t const src_radix = 10;
         uint64_t const dst_radix = 16;
         struct LengthPrefixUInt64Array * src = (void*) bufB;
         struct LengthPrefixUInt64Array * dst = (void*) bufA;
-        morph_posint_radix( src_radix, dst_radix, src, dst );
-    }
-
-
-    // morph to
-    //    ℕ ~ <PosInt 16 LittleEndian> ~ [~<LengthPrefix x86.UInt64> <Digit 10> ~ ℤ_10 ~ x86.UInt64]
-    {
-        uint64_t const radix = 16;
-        struct LengthPrefixUInt64Array * src = (void*) bufA;
-        struct LengthPrefixUInt64Array * dst = (void*) bufB;
-        morph_posint_endianness( radix, src, dst );
+        morph_posint_radix_little( src_radix, dst_radix, src, dst );
     }
 
     // morph to
@@ -66,11 +39,6 @@ int main() {
         struct LengthPrefixUInt8Array * dst = (void*) bufA;
 
         length_prefix_array_map_64_to_8( morph_digit_as_uint64_to_char, src, dst );
-/*
-        dst->len = src->len;
-        for( uint64_t i = 0; i < src->len; ++i )
-            morph_digit_as_uint64_to_char( &src->items[i], &dst->items[i] );
-*/
     }
 
     // morph to
@@ -81,6 +49,15 @@ int main() {
         morph_string_as_length_prefix_to_nullterm( src, dst );
     }
 
+    return 0;
+}
+
+int main() {
+    uint8_t bufA[1024];
+    uint8_t bufB[1024];
+
+    scanf("%s", bufA);
+    morph_posint_radix( bufA, bufB );
     printf("%s\n", bufB);
 
     return 0;
diff --git a/morphisms/posint-dec-to-hex-optimal.c b/morphisms/posint-dec-to-hex-optimal.c
index 7118ae0..b9c1ab0 100644
--- a/morphisms/posint-dec-to-hex-optimal.c
+++ b/morphisms/posint-dec-to-hex-optimal.c
@@ -1,6 +1,42 @@
 #include <stdio.h>
 #include <stdint.h>
 
+__attribute__((noinline))
+int morph_posint_radix( char * in, char * out ) {
+    uint64_t value = 0;
+        while( *in ) {
+            if( *in >= '0' && *in <= '9' ) {
+                value *= 10;
+                value += *in - '0';
+            }
+            else
+                return -1;
+
+            in++;
+        }
+
+        uint64_t v = value;
+        while( v ) {
+            out ++;
+            v /= 16;
+        }
+
+        *out-- = '\0';
+        while( value ) {
+            unsigned digit = value % 16;
+            if( digit < 10 ) {
+                *out-- = digit + '0';
+            } else if( digit < 16 ) {
+                *out-- = digit + 'a' - 10;
+            } else {
+                return -1;
+            }
+            value /= 16;
+        }
+
+    return 0;
+}
+
 int main() {
     char bufA[1024];
     char bufB[1024];
@@ -9,38 +45,7 @@ int main() {
     char * out = bufB;
 
     scanf("%s", in);
-
-    uint64_t value = 0;
-    while( *in ) {
-        if( *in >= '0' && *in <= '9' ) {
-            value *= 10;
-            value += *in - '0';
-        }
-        else
-            return -1;
-
-        in++;
-    }
-
-    uint64_t v = value;
-    while( v ) {
-        out ++;
-        v /= 16;
-    }
-
-    *out-- = '\0';
-    while( value ) {
-        unsigned digit = value % 16;
-        if( digit < 10 ) {
-            *out-- = digit + '0';
-        } else if( digit < 16 ) {
-            *out-- = digit + 'a' - 10;
-        } else {
-            return -1;
-        }
-        value /= 16;
-    }
-
+    morph_posint_radix( in, out );
     printf("%s\n", out);
 
     return 0;
diff --git a/morphisms/src/length-prefix.c b/morphisms/src/length-prefix.c
index 32029bf..4a93bec 100644
--- a/morphisms/src/length-prefix.c
+++ b/morphisms/src/length-prefix.c
@@ -1,7 +1,7 @@
 #include <stdio.h>
 #include <stdint.h>
 
-#include <morphisms/length-prefix.h>
+#include <array/length-prefix.h>
 
 void length_prefix_uint64_array_clear(
     struct LengthPrefixUInt64Array * data
@@ -120,28 +120,3 @@ void length_prefix_uint8_array_dump(
     }
     printf("]\n");
 }
-
-int morph_string_as_nullterm_to_length_prefix(
-    char const * restrict src,
-    struct LengthPrefixUInt8Array * restrict dst
-) {
-    length_prefix_uint8_array_clear(dst);
-    while( *src ) {
-        length_prefix_uint8_array_push(dst, *src);
-        src++;
-    }
-
-    return 0;
-}
-
-int morph_string_as_length_prefix_to_nullterm(
-    struct LengthPrefixUInt8Array const * restrict src,
-    char * restrict dst
-) {
-    for( uint64_t i = 0; i < src->len; ++i ) {
-        *dst ++ = src->items[i];
-    }
-    *dst = '\0';
-
-    return 0;
-}
diff --git a/morphisms/src/posint.c b/morphisms/src/posint.c
deleted file mode 100644
index 83cf6be..0000000
--- a/morphisms/src/posint.c
+++ /dev/null
@@ -1,87 +0,0 @@
-#include <stdint.h>
-#include <morphisms/length-prefix.h>
-
-int morph_digit_as_char_to_uint8(
-    //uint64_t const radix,
-    uint8_t const * restrict src,
-    uint8_t * restrict dst
-) {
-    if( *src >= '0' && *src <= '9' )
-        *dst = *src - '0';
-    else if( *src >= 'a' && *src <= 'f')
-        *dst = 0xa + *src - 'a';
-    else if( *src >= 'A' && *src <= 'F')
-        *dst = 0xa + *src - 'A';
-    else
-        return -1;
-
-    return 0;
-}
-
-int morph_digit_as_char_to_uint64(
-    //uint64_t const radix,
-    uint8_t const * restrict src,
-    uint64_t * restrict dst
-) {
-    return morph_digit_as_char_to_uint8(src, (void*)dst);
-}
-
-int morph_digit_as_uint8_to_char(
-    //uint64_t const radix,
-    uint8_t const * restrict src,
-    uint8_t * restrict dst
-) {
-    if ( *src < 10 )
-        *dst = *src + '0';
-    else if( *dst < 16 )
-        *dst = *src - 0xa + 'a';
-    else
-        return -1;
-
-    return 0;
-}
-
-int morph_digit_as_uint64_to_char(
-    //uint64_t const radix,
-    uint64_t const * restrict src,
-    uint8_t * restrict dst
-) {
-    return morph_digit_as_uint8_to_char((void*)src, dst);
-}
-
-/* switches endianness by reversing the digit sequence
- */
-int morph_posint_endianness(
-    uint64_t const radix,
-
-    struct LengthPrefixUInt64Array const * restrict src,
-    struct LengthPrefixUInt64Array * restrict dst
-) {
-    return length_prefix_uint64_array_reverse( src, dst );
-}
-
-/* morph radix in little endian
- */
-int morph_posint_radix(
-    uint64_t const src_radix,
-    uint64_t const dst_radix,
-
-    struct LengthPrefixUInt64Array const * restrict src,
-    struct LengthPrefixUInt64Array * restrict dst
-) {
-    uint64_t value = 0;
-
-    for( uint64_t i = 0; i < src->len; ++i ) {
-        value *= src_radix;
-        value += src->items[src->len - i - 1];
-    }
-
-    length_prefix_uint64_array_clear( dst );
-
-    while( value > 0 ) {
-        length_prefix_uint64_array_push( dst, value % dst_radix );
-        value /= dst_radix;
-    }
-
-    return 0;
-}
diff --git a/src/main.rs b/src/main.rs
index a31db2b..268e4de 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -4,14 +4,20 @@ use {
         prelude::*, text::*
     },
     laddertypes::{
-        dict::TypeDict,
-        parser::ParseLadderType,
-        unparser::UnparseLadderType, BimapTypeDict, MorphismType,
-        Morphism
+        dict::TypeDict, parser::ParseLadderType, subtype_unify, unparser::UnparseLadderType, BimapTypeDict, Morphism, MorphismType
     },
-    std::sync::{Arc, RwLock}
+    std::{any::Any, sync::{Arc, RwLock}}
 };
 
+/*
+*/
+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> {
@@ -45,7 +51,7 @@ pub fn get_c_repr_type(dict: &mut impl TypeDict, t: laddertypes::TypeTerm, skip_
                                 _ => None
                             }
                         }
-                        else if args[0] == laddertypes::TypeTerm::TypeID(dict.get_typeid(&"ValueDelim".into()).unwrap())
+                        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)?;
@@ -69,22 +75,85 @@ pub fn get_c_repr_type(dict: &mut impl TypeDict, t: laddertypes::TypeTerm, skip_
 #[derive(Clone, Debug)]
 struct LdmcPrimCMorphism {
     symbol: String,
-    type_args: Vec<(String, String)>,
+    type_args: Vec<(laddertypes::TypeID, String)>,
     src_type: laddertypes::TypeTerm,
     dst_type: laddertypes::TypeTerm,
-    locations: Vec<String>
+    c_source: String
+}
+
+fn encode_type_to_symbol(dict: &mut impl TypeDict, t: &laddertypes::TypeTerm)-> String {
+    match t {
+        laddertypes::TypeTerm::Char(c) => {
+            match *c {
+                '\0' => { "NULL".into() },
+                '\t' => { "TAB".into() },
+                c => { format!("{}", c) }
+            }
+        },
+        t => dict.unparse(t)
+    }
+}
+
+fn encode_type_to_value(dict: &mut impl TypeDict, t: &laddertypes::TypeTerm) -> String {
+    dict.unparse(t)
 }
 
 impl LdmcPrimCMorphism {
-    pub fn expected_c_type_signature(&self, dict: &mut impl TypeDict) -> String {
+    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.symbol,
+            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_call(&self, dict: &mut impl TypeDict, i: u64) {
+    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)
     }
 }
 
@@ -97,12 +166,12 @@ enum LdmcMorphism {
     },
     ValueDelimMap{
         delim: u64,
-        item_morph: Box<LdmcMorphism>
+        item_morph: Box<LdmcPrimCMorphism>
     }
 }
 
 impl LdmcMorphism {
-    pub fn generate_call(&self, dict: &mut impl TypeDict, i: u64) {
+    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(), true).expect("cant get c-repr type for src type");
@@ -110,6 +179,7 @@ impl LdmcMorphism {
 
                 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*) {};
@@ -119,10 +189,44 @@ impl LdmcMorphism {
                     '{',
                     src_c_type, src_buf,
                     dst_c_type, dst_buf,
-                    prim_morph.symbol,
+                    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, true).expect("cant get c-repr type for src type");
+                let dst_c_type = get_c_repr_type(dict, self.get_type().dst_type, 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"
+                    },
+                    _ => {
+                        "{{ 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");
 
@@ -132,17 +236,14 @@ impl LdmcMorphism {
     {}
             {} const * restrict src = (void*) {};
             {} * restrict dst = (void*) {};
-            length_prefix_array_map_8_to_64( {}, src, dst );
+            value_delim_array_map_8_to_64( {}, src, dst );
     {}"#,
             '{',
                     src_c_type, src_buf,
                     dst_c_type, dst_buf,
-                    item_morph.symbol,
+                    item_morph.instantiated_symbol_name(dict, σ),
                     '}');
             }
-            LdmcMorphism::ValueDelimMap { delim, item_morph } => {
-
-            }
         }
     }
 }
@@ -167,20 +268,21 @@ impl Morphism for LdmcMorphism {
             },
             LdmcMorphism::ValueDelimMap{ delim, item_morph } => {
                 let value_delim_type = laddertypes::TypeTerm::App(vec![]);
-                let item_morph_type = item_morph.get_type();
                 laddertypes::MorphismType {
-                    src_type: laddertypes::TypeTerm::App(vec![ value_delim_type.clone(), item_morph_type.src_type ]),
-                    dst_type: laddertypes::TypeTerm::App(vec![ value_delim_type.clone(), item_morph_type.dst_type ]),
+                    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 {
+/*
+                if seq_type == self.length_prefix_type {
+                */
                     Some(LdmcMorphism::LengthPrefixMap{
                         length_prefix_type: seq_type,
                         item_morph,
@@ -202,34 +304,46 @@ impl Morphism for LdmcMorphism {
  *     NAME '(' [TYPE-ARG-NAME ':' KIND]  ')'
  *           SRC-TYPE
  *     '-->' DST-TYPE
- *     '@' [ LOCATION ':' ]
+ *     ```
+ *          TEMPLATE-CODE
+ *     ```
  */
 fn parser(
     type_dict: Arc<RwLock< BimapTypeDict >>
 ) -> impl Parser<char, Vec<LdmcPrimCMorphism>, Error = Simple<char>> {
 
+    // morph name
     ident().padded()
+
+    // type args
     .then(
         ident().padded()
-        .then_ignore(just(':').padded())
+        .then_ignore(just(":").padded())
         .then(none_of(",)").repeated().padded())
-        .separated_by(just(',').padded())
-        .delimited_by(just('('), just(')'))
+        .separated_by(just(",").padded())
+        .delimited_by(just("("), just(")"))
     )
+
+    // newline
     .then_ignore(just('\n'))
-    .then(
-        take_until(just("-->").ignored())
-        .then(take_until(just('@').ignored()))
-    )
-    .then(
-        none_of(":\n").repeated().separated_by(just(':'))
-    )
+
+    // 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, _))), locations)| {
+        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();
-            for (var, kind) in type_args.iter() {
-                type_dict.add_varname(var.clone());
+            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");
@@ -237,10 +351,10 @@ fn parser(
 
             LdmcPrimCMorphism {
                 symbol,
-                type_args,
+                type_args: ty_args,
                 src_type,
                 dst_type,
-                locations: locations.into_iter().map(|l| l.into_iter().collect()).collect()
+                c_source
             }
         })
         .separated_by(text::newline())
@@ -248,40 +362,22 @@ fn parser(
 
 fn main() {
     let mut type_dict = Arc::new(RwLock::new(BimapTypeDict::new()));
-    type_dict.add_varname("Delim".into());
     let mut morphism_base = laddertypes::MorphismBase::<LdmcMorphism>::new(vec![
-        type_dict.parse("Seq ~ <ValueDelim '\\0'>").expect(""),
-        type_dict.parse("Seq ~ <LengthPrefix x86.UInt64>").expect("")
+        type_dict.parse("Seq~<ValueTerminated '\\0'>").expect(""),
+        type_dict.parse("Seq~<LengthPrefix x86.UInt64>").expect("")
     ]);
-/*
-    let mut t = type_dict.parse("<Seq~<ValueDelim '\0'> Char>~<Seq~<ValueDelim '\0'> Ascii~Byte>").expect("");
 
-    eprintln!("init :: {}\n", t.clone().sugar(&mut type_dict).pretty(&mut type_dict, 0));
-    //t = t.normalize();
-    //eprintln!("LNF :: {}\n", t.clone().sugar(&mut type_dict).pretty(&mut type_dict, 0));
-    t = t.param_normalize();
-    println!("PNF :: {}\n", t.sugar(&mut type_dict).pretty(&mut type_dict, 0));
-
-    return;
-*/
-    for mb_path in std::env::args().skip(1) {
-        let src = std::fs::read_to_string(
-            mb_path
-        ).expect("read");
+    let mut args = std::env::args().skip(1);
+    let src_type_arg = args.next().expect("src type expected");
+    let dst_type_arg = args.next().expect("dst type expected");
 
+    for mb_path in args {
+        let src = std::fs::read_to_string(mb_path).expect("read");
         let result = parser(type_dict.clone()).parse(src.clone());
         match result {
             Ok(morphisms) => {
                 eprintln!("parse ok.");
-                let mut dict = type_dict.write().unwrap();
-
                 for m in morphisms {
-                    /*
-                    eprintln!("{}\n    {}\n---> \n    {}\n", m.symbol,
-                        m.src_type.clone().sugar(&mut *dict).pretty(&mut *dict, 1),
-                        m.dst_type.clone().sugar(&mut *dict).pretty(&mut *dict, 1),
-                    );
-                    */
                     morphism_base.add_morphism(LdmcMorphism::Primitive(m));
                 }
             }
@@ -302,55 +398,78 @@ fn main() {
         }
     }
 
-    let path = morphism_base.find_morphism_path(MorphismType {
-        src_type: type_dict.parse("ℕ ~ <PosInt 10 BigEndian> ~ <Seq~<LengthPrefix x86.UInt64> <Digit 10>~x86.UInt64>").expect(""),
-        dst_type: type_dict.parse("ℕ ~ <PosInt 16 BigEndian> ~ <Seq~<LengthPrefix x86.UInt64> <Digit 16>~x86.UInt64>").expect(""),
-    });
 
+    let path = morphism_base.find_morphism_path(MorphismType {
+        src_type: type_dict.parse( src_type_arg.as_str() ).expect(""),
+        dst_type: type_dict.parse( dst_type_arg.as_str() ).expect(""),
+    });
 
     match path {
         Some(path) => {
-            let mut path = path.into_iter();
-            let mut src_type = path.next().unwrap();
-
             let mut i = 0;
 
+            /* todo: collect include files from morphism base */
             println!(r#"
 #include <stdio.h>
 #include <stdint.h>
-#include <morphisms/length-prefix.h>
-#include <morphisms/posint.h>
+#include <array/length-prefix.h>
+"#);
 
-int main() {}
+            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];
 
     scanf("%s", bufA);
-                "#, '{');
-            for dst_type in path {
-                eprintln!("add morph from {}\nto {}
-                ",
-                src_type.clone().param_normalize().sugar(&mut type_dict).pretty(&mut type_dict, 1),
-                dst_type.clone().param_normalize().sugar(&mut type_dict).pretty(&mut type_dict, 1),
-                );
-                let (m, typ, σ) = morphism_base.find_morphism_with_subtyping(&MorphismType {
-                    src_type: src_type.param_normalize(),
-                    dst_type: dst_type.clone().param_normalize()
-                }).expect("cant find morphism");
-
-                let dst_type = m.get_type().dst_type;
-
+                "#);
+            for morph_inst in path {
                 println!(r#"
-    /* morph to {} */"#,
-                        dst_type.clone().param_normalize().decurry()
-                            .sugar(&mut type_dict)
-                            .pretty(&mut type_dict, 1)
-                    );
-                m.generate_call(&mut type_dict, i);
-                i += 1;
+    /* morph to {}
 
-                src_type = laddertypes::TypeTerm::Ladder(vec![ typ, dst_type ]);
-                src_type = src_type.normalize().apply_substitution(&|k| σ.get(k).cloned()).clone();
+    ...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" };
@@ -358,8 +477,8 @@ int main() {}
     printf("%s\n", {});
 
     return 0;
-{}
-            "#, out_buf, '}');
+}}
+            "#, out_buf);
         }
         None => {
             eprintln!("Error: could not find morphism path");