From e29a5a3475f2de7bec4f238bf8fedaa160e750f6 Mon Sep 17 00:00:00 2001
From: Michael Sippel <micha@fragmental.art>
Date: Thu, 20 Mar 2025 16:16:41 +0100
Subject: [PATCH] generate all length prefix array variants via macro

---
 morphisms/length_prefix.morphism-base         |   4 +-
 morphisms/posint.morphism-base                |  12 +-
 .../runtime/include/array/length-prefix.h     | 153 +++++++++++-------
 morphisms/runtime/src/length-prefix.c         | 137 ----------------
 morphisms/value_delim.morphism-base           |  24 +--
 src/c_gen.rs                                  |  84 +++++++---
 test/test.sh                                  |   2 +-
 7 files changed, 175 insertions(+), 241 deletions(-)
 delete mode 100644 morphisms/runtime/src/length-prefix.c

diff --git a/morphisms/length_prefix.morphism-base b/morphisms/length_prefix.morphism-base
index 92cb803..8ca1b0a 100644
--- a/morphisms/length_prefix.morphism-base
+++ b/morphisms/length_prefix.morphism-base
@@ -7,9 +7,9 @@ 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);
+    length_prefix_uint64_t_array_uint8_t_clear(dst);
     while( *src != Terminator )
-        length_prefix_uint8_array_push(dst, *src++);
+        length_prefix_uint64_t_array_uint8_t_push(dst, *src++);
 
     return 0;
 ```
diff --git a/morphisms/posint.morphism-base b/morphisms/posint.morphism-base
index 64dea71..ccec763 100644
--- a/morphisms/posint.morphism-base
+++ b/morphisms/posint.morphism-base
@@ -40,15 +40,15 @@ morph_posint_radix_le (SrcRadix:ℤ, DstRadix:ℤ)
         value += src->items[src->len - i - 1];
     }
 
-    length_prefix_uint64_array_clear( dst );
+    length_prefix_uint64_t_array_uint64_t_clear( dst );
 
     #if DstRadix==0
-        length_prefix_uint64_array_push( dst, value );
+        length_prefix_uint64_t_array_uint64_t_push( dst, value );
     #else
         if( value == 0 ) {
-            length_prefix_uint64_array_push( dst, 0 );
+            length_prefix_uint64_t_array_uint64_t_push( dst, 0 );
         } else while( value > 0 ) {
-            length_prefix_uint64_array_push( dst, value % DstRadix );
+            length_prefix_uint64_t_array_uint64_t_push( dst, value % DstRadix );
             value /= DstRadix;
         }
     #endif
@@ -103,7 +103,7 @@ morph_posint_endianness (Radix:ℤ)
     ~ <PosInt Radix BigEndian>
     ~ <Seq~<LengthPrefix x86.UInt64> <Digit Radix> ~ x86.UInt64>
 ```
-    return length_prefix_uint64_array_reverse( src, dst );
+    return length_prefix_uint64_t_array_uint64_t_reverse( src, dst );
 ```
 
 morph_posint_endianness (Radix:ℤ)
@@ -114,5 +114,5 @@ morph_posint_endianness (Radix:ℤ)
     ~ <PosInt Radix LittleEndian>
     ~ <Seq~<LengthPrefix x86.UInt64> <Digit Radix> ~ x86.UInt64>
 ```
-    return length_prefix_uint64_array_reverse( src, dst );
+    return length_prefix_uint64_t_array_uint64_t_reverse( src, dst );
 ```
diff --git a/morphisms/runtime/include/array/length-prefix.h b/morphisms/runtime/include/array/length-prefix.h
index 6831aad..9017950 100644
--- a/morphisms/runtime/include/array/length-prefix.h
+++ b/morphisms/runtime/include/array/length-prefix.h
@@ -1,70 +1,101 @@
 #pragma once
+
+#include <stdio.h>
 #include <stdint.h>
 
-/* UInt8 */
+// Macro to define length-prefixed array structures and functions
+#define DEFINE_LENGTH_PREFIX_ARRAY(LEN_TYPE, ITEM_TYPE)                        \
+    typedef struct {                                                           \
+        LEN_TYPE len;                                                          \
+        ITEM_TYPE items[];                                                     \
+    } LengthPrefix_##LEN_TYPE##_Array_##ITEM_TYPE;                             \
+                                                                               \
+    static inline void length_prefix_##LEN_TYPE##_array_##ITEM_TYPE##_clear(   \
+        LengthPrefix_##LEN_TYPE##_Array_##ITEM_TYPE *data) {                   \
+        data->len = 0;                                                         \
+    }                                                                          \
+                                                                               \
+    static inline void length_prefix_##LEN_TYPE##_array_##ITEM_TYPE##_push(    \
+        LengthPrefix_##LEN_TYPE##_Array_##ITEM_TYPE *data,                     \
+        ITEM_TYPE value) {                                                     \
+        data->items[data->len++] = value;                                      \
+    }                                                                          \
+                                                                               \
+    static inline int length_prefix_##LEN_TYPE##_array_##ITEM_TYPE##_reverse(  \
+        LengthPrefix_##LEN_TYPE##_Array_##ITEM_TYPE const * restrict src,      \
+        LengthPrefix_##LEN_TYPE##_Array_##ITEM_TYPE *restrict dst) {           \
+        for (LEN_TYPE i = 0; i < src->len; i++) {                              \
+            dst->items[i] = src->items[src->len - 1 - i];                      \
+        }                                                                      \
+        dst->len = src->len;                                                   \
+        return 0;                                                              \
+    }                                                                          \
+                                                                               \
+    static inline void length_prefix_##LEN_TYPE##_array_##ITEM_TYPE##_dump(    \
+        LengthPrefix_##LEN_TYPE##_Array_##ITEM_TYPE const * data) {            \
+        printf("Length: %llu\n", (unsigned long long) data->len);              \
+        for (LEN_TYPE i = 0; i < data->len; i++) {                             \
+            printf("%llu ", (unsigned long long) data->items[i]);              \
+        }                                                                      \
+        printf("\n");                                                          \
+    }
 
-struct LengthPrefixUInt8Array {
-    uint64_t len;
-    uint8_t items[];
-};
 
-void length_prefix_uint8_array_clear(
-    struct LengthPrefixUInt8Array * data
-);
-void length_prefix_uint8_array_push(
-    struct LengthPrefixUInt8Array * data,
-    uint8_t value
-);
-int length_prefix_uint8_array_reverse(
-    struct LengthPrefixUInt8Array const * restrict src,
-    struct LengthPrefixUInt8Array * restrict dst
-);
-void length_prefix_uint8_array_dump(
-    struct LengthPrefixUInt8Array const * data
-);
-
-/* UInt64 */
-
-struct LengthPrefixUInt64Array {
-    uint64_t len;
-    uint64_t items[];
-};
-
-void length_prefix_uint64_array_clear(
-    struct LengthPrefixUInt64Array * data
-);
-void length_prefix_uint64_array_push(
-    struct LengthPrefixUInt64Array * data,
-    uint64_t value
-);
-int length_prefix_uint64_array_reverse(
-    struct LengthPrefixUInt64Array const * restrict src,
-    struct LengthPrefixUInt64Array * restrict dst
-);
-void length_prefix_uint64_array_dump(
-    struct LengthPrefixUInt64Array const * data
-);
+// Define all combinations of length and item types
+DEFINE_LENGTH_PREFIX_ARRAY(uint8_t, uint8_t)
+DEFINE_LENGTH_PREFIX_ARRAY(uint8_t, uint16_t)
+DEFINE_LENGTH_PREFIX_ARRAY(uint8_t, uint32_t)
+DEFINE_LENGTH_PREFIX_ARRAY(uint8_t, uint64_t)
+DEFINE_LENGTH_PREFIX_ARRAY(uint16_t, uint8_t)
+DEFINE_LENGTH_PREFIX_ARRAY(uint16_t, uint16_t)
+DEFINE_LENGTH_PREFIX_ARRAY(uint16_t, uint32_t)
+DEFINE_LENGTH_PREFIX_ARRAY(uint16_t, uint64_t)
+DEFINE_LENGTH_PREFIX_ARRAY(uint32_t, uint8_t)
+DEFINE_LENGTH_PREFIX_ARRAY(uint32_t, uint16_t)
+DEFINE_LENGTH_PREFIX_ARRAY(uint32_t, uint32_t)
+DEFINE_LENGTH_PREFIX_ARRAY(uint32_t, uint64_t)
+DEFINE_LENGTH_PREFIX_ARRAY(uint64_t, uint8_t)
+DEFINE_LENGTH_PREFIX_ARRAY(uint64_t, uint16_t)
+DEFINE_LENGTH_PREFIX_ARRAY(uint64_t, uint32_t)
+DEFINE_LENGTH_PREFIX_ARRAY(uint64_t, uint64_t)
 
 /*
  * Map
  */
-int length_prefix_array_map_64_to_64(
-    int (*f) ( uint64_t const * restrict, uint64_t * restrict ),
-    struct LengthPrefixUInt64Array const * restrict src,
-    struct LengthPrefixUInt64Array * restrict dst
-);
-int length_prefix_array_map_8_to_64(
-    int (*f) ( uint8_t const * restrict, uint64_t * restrict ),
-    struct LengthPrefixUInt8Array const * restrict src,
-    struct LengthPrefixUInt64Array * restrict dst
-);
-int length_prefix_array_map_64_to_8(
-    int (*f) ( uint64_t const * restrict, uint8_t * restrict ),
-    struct LengthPrefixUInt64Array const * restrict src,
-    struct LengthPrefixUInt8Array * restrict dst
-);
-int length_prefix_array_map_8_to_8(
-    int (*f) ( uint8_t const * restrict, uint8_t * restrict ),
-    struct LengthPrefixUInt8Array const * restrict src,
-    struct LengthPrefixUInt8Array * restrict dst
-);
+// Macro to define map function between different item types
+#define DEFINE_LENGTH_PREFIX_ARRAY_MAP(LEN_TYPE, SRC_ITEM_TYPE, DST_ITEM_TYPE) \
+    static inline int length_prefix_##LEN_TYPE##_array_map_##SRC_ITEM_TYPE##_to_##DST_ITEM_TYPE( \
+        int (*f)(SRC_ITEM_TYPE const * restrict, DST_ITEM_TYPE * restrict),    \
+        LengthPrefix_##LEN_TYPE##_Array_##SRC_ITEM_TYPE const * restrict src,  \
+        LengthPrefix_##LEN_TYPE##_Array_##DST_ITEM_TYPE * restrict dst)        \
+    {                                                                          \
+        if (dst->len < src->len) return -1; /* Ensure enough space */          \
+        for (LEN_TYPE i = 0; i < src->len; i++) {                              \
+            if (f(&src->items[i], &dst->items[i]) != 0) return -1;             \
+        }                                                                      \
+        dst->len = src->len;                                                   \
+        return 0;                                                              \
+    }
+
+#define DEFINE_ALL_MAPS(LEN_TYPE)                        \
+    DEFINE_LENGTH_PREFIX_ARRAY_MAP(LEN_TYPE, uint8_t, uint8_t)  \
+    DEFINE_LENGTH_PREFIX_ARRAY_MAP(LEN_TYPE, uint8_t, uint16_t)  \
+    DEFINE_LENGTH_PREFIX_ARRAY_MAP(LEN_TYPE, uint8_t, uint32_t)  \
+    DEFINE_LENGTH_PREFIX_ARRAY_MAP(LEN_TYPE, uint8_t, uint64_t)  \
+    DEFINE_LENGTH_PREFIX_ARRAY_MAP(LEN_TYPE, uint16_t, uint8_t)  \
+    DEFINE_LENGTH_PREFIX_ARRAY_MAP(LEN_TYPE, uint16_t, uint16_t)  \
+    DEFINE_LENGTH_PREFIX_ARRAY_MAP(LEN_TYPE, uint16_t, uint32_t) \
+    DEFINE_LENGTH_PREFIX_ARRAY_MAP(LEN_TYPE, uint16_t, uint64_t) \
+    DEFINE_LENGTH_PREFIX_ARRAY_MAP(LEN_TYPE, uint32_t, uint8_t)  \
+    DEFINE_LENGTH_PREFIX_ARRAY_MAP(LEN_TYPE, uint32_t, uint16_t) \
+    DEFINE_LENGTH_PREFIX_ARRAY_MAP(LEN_TYPE, uint32_t, uint32_t) \
+    DEFINE_LENGTH_PREFIX_ARRAY_MAP(LEN_TYPE, uint32_t, uint64_t) \
+    DEFINE_LENGTH_PREFIX_ARRAY_MAP(LEN_TYPE, uint64_t, uint8_t)  \
+    DEFINE_LENGTH_PREFIX_ARRAY_MAP(LEN_TYPE, uint64_t, uint16_t) \
+    DEFINE_LENGTH_PREFIX_ARRAY_MAP(LEN_TYPE, uint64_t, uint32_t) \
+    DEFINE_LENGTH_PREFIX_ARRAY_MAP(LEN_TYPE, uint64_t, uint64_t)
+
+DEFINE_ALL_MAPS(uint8_t)
+DEFINE_ALL_MAPS(uint16_t)
+DEFINE_ALL_MAPS(uint32_t)
+DEFINE_ALL_MAPS(uint64_t)
diff --git a/morphisms/runtime/src/length-prefix.c b/morphisms/runtime/src/length-prefix.c
deleted file mode 100644
index 281a8cb..0000000
--- a/morphisms/runtime/src/length-prefix.c
+++ /dev/null
@@ -1,137 +0,0 @@
-#include <stdio.h>
-#include <stdint.h>
-
-#include <array/length-prefix.h>
-
-void length_prefix_uint64_array_clear(
-    struct LengthPrefixUInt64Array * data
-) {
-    data->len = 0;
-}
-
-void length_prefix_uint64_array_push(
-    struct LengthPrefixUInt64Array * data,
-    uint64_t value
-) {
-    data->items[ data->len ] = value;
-    data->len += 1;
-}
-
-int length_prefix_uint64_array_reverse(
-    struct LengthPrefixUInt64Array const * restrict src,
-    struct LengthPrefixUInt64Array * restrict dst
-) {
-    dst->len = src->len;
-    for(uint64_t i = 0; i < src->len; ++i) {
-        dst->items[i] = src->items[src->len - i - 1];
-    }
-    return 0;
-}
-
-int length_prefix_array_map_8_to_8(
-    int (*f) ( uint8_t const * restrict, uint8_t * restrict ),
-    struct LengthPrefixUInt8Array const * restrict src,
-    struct LengthPrefixUInt8Array * restrict dst
-) {
-    dst->len = src->len;
-    for( uint64_t i = 0; i < src->len; ++i ) {
-        int result = f( &src->items[i], &dst->items[i] );
-        if( result ) {
-            return result;
-        }
-    }
-    return 0;
-}
-
-int length_prefix_array_map_64_to_64(
-    int (*f) ( uint64_t const * restrict, uint64_t * restrict ),
-    struct LengthPrefixUInt64Array const * restrict src,
-    struct LengthPrefixUInt64Array * restrict dst
-) {
-    dst->len = src->len;
-    for( uint64_t i = 0; i < src->len; ++i ) {
-        int result = f( &src->items[i], &dst->items[i] );
-        if( result ) {
-            return result;
-        }
-    }
-    return 0;
-}
-
-int length_prefix_array_map_8_to_64(
-    int (*f) ( uint8_t const * restrict, uint64_t * restrict ),
-    struct LengthPrefixUInt8Array const * restrict src,
-    struct LengthPrefixUInt64Array * restrict dst
-) {
-    dst->len = src->len;
-    for( uint64_t i = 0; i < src->len; ++i ) {
-        int result = f( &src->items[i], &dst->items[i] );
-        if( result ) {
-            return result;
-        }
-    }
-    return 0;
-}
-
-int length_prefix_array_map_64_to_8(
-    int (*f) ( uint64_t const * restrict, uint8_t * restrict ),
-    struct LengthPrefixUInt64Array const * restrict src,
-    struct LengthPrefixUInt8Array * restrict dst
-) {
-    dst->len = src->len;
-    for( uint64_t i = 0; i < src->len; ++i ) {
-        int result = f( &src->items[i], &dst->items[i] );
-        if( result ) {
-            return result;
-        }
-    }
-    return 0;
-}
-
-void length_prefix_uint64_array_dump(
-    struct LengthPrefixUInt64Array const * data
-) {
-    printf("Len = %d, [", data->len);
-    for( uint64_t i = 0; i < data->len; ++i ) {
-        printf("%d; ", data->items[i]);
-    }
-    printf("]\n");
-}
-
-
-
-
-void length_prefix_uint8_array_clear(
-    struct LengthPrefixUInt8Array * data
-) {
-    data->len = 0;
-}
-
-void length_prefix_uint8_array_push(
-    struct LengthPrefixUInt8Array * data,
-    uint8_t value
-) {
-    data->items[ data->len ] = value;
-    data->len += 1;
-}
-
-int length_prefix_uint8_array_reverse(
-    struct LengthPrefixUInt8Array const * restrict src,
-    struct LengthPrefixUInt8Array * restrict dst
-) {
-    dst->len = src->len;
-    for(uint64_t i = 0; i < src->len; ++i) {
-        dst->items[i] = src->items[src->len - i - 1];
-    }
-    return 0;
-}
-
-void length_prefix_uint8_array_dump(
-    struct LengthPrefixUInt8Array const * data
-) {
-    printf("Len = %d, [", data->len);
-    for( uint64_t i = 0; i < data->len; ++i ) {
-        printf("%d; ", data->items[i]);
-    }
-    printf("]\n");
-}
diff --git a/morphisms/value_delim.morphism-base b/morphisms/value_delim.morphism-base
index cab2c32..f1354bd 100644
--- a/morphisms/value_delim.morphism-base
+++ b/morphisms/value_delim.morphism-base
@@ -12,19 +12,19 @@ morph_seqseq_valsep_uint8 (T: Type, SrcDelim: T, DstDelim: T)
     ~ < ValueSep DstDelim T >
     ~ < Seq~<LengthPrefix x86.UInt64> T >
 ```
-    length_prefix_uint8_array_clear( dst );
+    length_prefix_uint64_t_array_uint8_t_clear( dst );
 
     uint8_t * dst_items = dst->items;
     for( uint64_t i = 0; i < src->len; ++i ) {
         if( src->items[i] == SrcDelim ) {
-            length_prefix_uint8_array_push( dst, DstDelim );
+            length_prefix_uint64_t_array_uint8_t_push( dst, DstDelim );
         } else if( src->items[i] == DstDelim ) {
             if( DstDelim == '\n' ) {
-                length_prefix_uint8_array_push( dst, '\\' );
-                length_prefix_uint8_array_push( dst, 'n' );
+                length_prefix_uint64_t_array_uint8_t_push( dst, '\\' );
+                length_prefix_uint64_t_array_uint8_t_push( dst, 'n' );
             }
         } else {
-            length_prefix_uint8_array_push( dst, src->items[i] );
+            length_prefix_uint64_t_array_uint8_t_push( dst, src->items[i] );
         }
     }
 
@@ -44,9 +44,9 @@ morph_seqseq_as_valsep_to_lenpfx (T: Type, Delim: T, EscKey: T)
         ~ x86.UInt64
     >
 ```
-    length_prefix_uint64_array_clear( dst );
+    length_prefix_uint64_t_array_uint64_t_clear( dst );
 
-    struct LengthPrefixUInt8Array * cur_item = NULL;
+    struct LengthPrefix_uint64_t_Array_uint8_t * cur_item = NULL;
 
     uint8_t const * start = &src->items[0];
     uint8_t const * cur = start;
@@ -60,7 +60,7 @@ morph_seqseq_as_valsep_to_lenpfx (T: Type, Delim: T, EscKey: T)
             cur_item->len = len;
             memcpy( cur_item->items, start, len );
 
-            length_prefix_uint64_array_push( dst, (uint64_t)cur_item );
+            length_prefix_uint64_t_array_uint64_t_push( dst, (uint64_t)cur_item );
             start = ++cur;
         } else {
             cur++;
@@ -81,17 +81,17 @@ morph_seqeq_as_lenpfx_to_valsep (T: Type, Delim: T, EscKey: T)
     ~ < ValueSep T Delim >
     ~ < Seq~<LengthPrefix x86.UInt64> T >
 ```
-    length_prefix_uint8_array_clear( dst );
+    length_prefix_uint64_t_array_uint8_t_clear( dst );
 
     for( uint64_t i = 0; i < src->len; ++i ) {
-        LengthPrefixUInt8Array * item = src->items[i];
+        LengthPrefix_uint64_t_Array_uint8_t * item = src->items[i];
 
         for( uint64_t j = 0; j < item->len; ++j ) {
-            length_prefix_uint8_array_push( items->items[j] );
+            length_prefix_uint64_t_array_uint8_t_push( items->items[j] );
         }
 
         if( i+1 < src->len ) {
-            length_prefix_uint8_array_push( Delim );
+            length_prefix_uint64_t_array_uint8_t_push( Delim );
         }
     }
 
diff --git a/src/c_gen.rs b/src/c_gen.rs
index e13a4d3..a34050c 100644
--- a/src/c_gen.rs
+++ b/src/c_gen.rs
@@ -39,15 +39,31 @@ pub fn get_c_repr_type(dict: &mut impl TypeDict, t: laddertypes::TypeTerm, skip_
                     laddertypes::TypeTerm::App(args) => {
                         if args[0] == laddertypes::TypeTerm::TypeID(dict.get_typeid(&"LengthPrefix".into()).unwrap())
                         {
-                            let _length_type = args[1].clone();
+                            let length_c_type : String = get_c_repr_type(dict, args[1].clone(), false)?;
                             let item_c_type : String = get_c_repr_type(dict, args[2].clone(), false)?;
-                            match 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
+
+                            match length_c_type.as_str() {
+                                "uint8_t" |
+                                "uint16_t" |
+                                "uint32_t" |
+                                "uint64_t" => {}
+                                _ => {
+                                    eprintln!("invalid length type!");
+                                    return None;
+                                }
                             }
+                            match item_c_type.as_str() {
+                                "uint8_t" |
+                                "uint16_t" |
+                                "uint32_t" |
+                                "uint64_t" => {}
+                                _ => {
+                                    eprintln!("invalid item type!");
+                                    return None;
+                                }
+                            }
+
+                            Some(format!("LengthPrefix_{}_Array_{}", length_c_type, item_c_type))
                         }
                         else if args[0] == laddertypes::TypeTerm::TypeID(dict.get_typeid(&"ValueTerminated".into()).unwrap())
                         {
@@ -174,7 +190,7 @@ write(2, in_str, strlen(in_str));
 write(2, out_str, strlen(out_str));
 
 int l = read(0, bufA, sizeof(bufA));
-fprintf(stderr, "read  %d bytes\n", l);
+//fprintf(stderr, "read  %d bytes\n", l);
 
         "#,
         type_dict.unparse(&src_type).replace("\\", "\\\\"),
@@ -217,14 +233,14 @@ printf("%s\n", {});"#, out_buf);
         /* write output
          */
         {{
-            struct LengthPrefixUInt8Array * buf = (void*){};
+            LengthPrefix_uint64_t_Array_uint8_t * buf = (void*){};
             write(1, {}, sizeof(uint64_t) + buf->len);
         }}"#, out_buf, out_buf);
     } else {
         println!(r#"
-write(1, {}, {});"#,
+write(1, {}, sizeof({}));"#,
             out_buf,
-            "sizeof(bufA)"
+            out_buf
         );
     }
 
@@ -319,18 +335,42 @@ impl LdmcMorphism {
                     '}');
             }
             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 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 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 }}"
-                    }
-                };
+                eprintln!("length prefix type ={:?}", length_prefix_type);
+                eprintln!("src_type ={:?}", src_type);
+                eprintln!("dst_type = {:?}", dst_type);
+
+                dict.add_varname("S".into());
+
+                let γ_src = laddertypes::unify(
+                    &dict.parse("<Seq~<LengthPrefix S> T>").expect("parse template"),
+                    &src_type
+                ).expect("cant get src item type");
+
+                let γ_dst = laddertypes::unify(
+                    &dict.parse("<Seq~<LengthPrefix S> T>").expect("parse template"),
+                    &dst_type
+                ).expect("cant get dst item type");
+
+                let src_length_type = γ_src.get(&dict.get_typeid(&"S".into()).unwrap()).expect("cant get src-length type").clone();
+                let dst_length_type = γ_src.get(&dict.get_typeid(&"S".into()).unwrap()).expect("cant get dst-length type").clone();
+
+                let length_type = src_length_type;
+
+                let src_item_type = γ_src.get(&dict.get_typeid(&"T".into()).unwrap()).expect("cant get src-item type").clone();
+                let dst_item_type = γ_dst.get(&dict.get_typeid(&"T".into()).unwrap()).expect("cant get src-item type").clone();
+
+                let length_c_type = get_c_repr_type(dict, length_type, true).expect("cant c-repr type for array length");
+                let src_item_c_type = get_c_repr_type(dict, src_item_type, true).expect("cant c-repr type for src item");
+                let dst_item_c_type = get_c_repr_type(dict, dst_item_type, true).expect("cant c-repr type for dst item");
+                let src_c_type = get_c_repr_type(dict, src_type, true).expect("cant get c-repr type for src type");
+                let dst_c_type = get_c_repr_type(dict, dst_type, true).expect("cant get c-repr type for dst type");
+
+                let map_fn = format!("length_prefix_{}_array_map_{}_to_{}",
+                    length_c_type, src_item_c_type, dst_item_c_type
+                );
 
                 let src_buf = if i%2 == 0 { "bufA" } else { "bufB" };
                 let dst_buf = if i%2 == 0 { "bufB" } else { "bufA" };
diff --git a/test/test.sh b/test/test.sh
index 402e9f1..16ebcb1 100755
--- a/test/test.sh
+++ b/test/test.sh
@@ -11,7 +11,7 @@ Running test case ${TEST_NAME}"
     ldmc "${SRC_TYPE}" "${DST_TYPE}" ../morphisms/*.morphism-base 2>|.tmp/ldmc_err 1>| target/src/${TEST_NAME}.c \
     || (echo "... error at generation:"; cat .tmp/ldmc_err; return -1);
 
-    gcc -I../morphisms/runtime/include target/src/${TEST_NAME}.c ../morphisms/runtime/src/*.c -o target/${TEST_NAME} \
+    gcc -I../morphisms/runtime/include target/src/${TEST_NAME}.c -o target/${TEST_NAME} \
     || (echo "... error at compilation:"; return -2);