Compare commits

..

No commits in common. "wip-struct" and "master" have entirely different histories.

34 changed files with 783 additions and 1596 deletions

View file

@ -8,5 +8,3 @@ chumsky = "0.9.0"
ariadne = "0.2"
laddertypes = { path = "../lib-laddertypes", features = ["pretty"] }
tiny-ansi = { version = "0.1.0" }
clap = { version = "4.5.37", features = ["derive"] }
walkdir = "2.5.0"

View file

@ -1 +0,0 @@
build/

View file

@ -1,14 +0,0 @@
#include "morphisms.h"
int main(int argc, char* argv[]) {
if( argc > 1 ) {
uint64_t value;
demarshal( argv[1], &value );
uint64_t result = value * value;
char buf[256];
marshal( &result, buf );
printf("%s\n", buf);
}
}

View file

@ -1,23 +0,0 @@
all: build/square
.PHONY: build clean
build:
mkdir -p build
build/morphisms.h: build
ldmc \
-m "marshal: \
~ native.UInt64 \
--> ~ <PosInt 10 BigEndian> ~ <Seq~<ValueTerminated 0> <Digit 10>~Char~Ascii~native.UInt8> \
" \
-m "demarshal: \
~ <PosInt 10 BigEndian> ~ <Seq~<ValueTerminated 0> <Digit 10>~Char~Ascii~native.UInt8> \
--> ~ native.UInt64 \
" \
-o build/morphisms.h
build/square: build build/morphisms.h
gcc -Os -I../../morphisms/runtime/include/ -Ibuild main.c -o build/square
clean:
rm build/ -rf

View file

@ -3,44 +3,70 @@
```
morph_angle_as_degrees_to_turns_float ()
Angle ~ Degrees ~ ~ native.Float32
--> Angle ~ Turns ~ ~ native.Float32
```*dst = *src / 360.0;```
Angle ~ Degrees ~ ~ native.Float
--> Angle ~ Turns ~ ~ native.Float
```
*dst = *src / 360.0;
return 0;
```
morph_angle_as_degrees_to_turns_double ()
Angle ~ Degrees ~ ~ native.Float64
--> Angle ~ Turns ~ ~ native.Float64
```*dst = *src / 360.0;```
Angle ~ Degrees ~ ~ native.Double
--> Angle ~ Turns ~ ~ native.Double
```
*dst = *src / 360.0;
return 0;
```
morph_angle_as_turns_to_degrees_float ()
Angle ~ Turns ~ ~ native.Float32
--> Angle ~ Degrees ~ ~ native.Float32
```*dst = *src * 360.0;```
Angle ~ Turns ~ ~ native.Float
--> Angle ~ Degrees ~ ~ native.Float
```
*dst = *src * 360.0;
return 0;
```
morph_angle_as_turns_to_degrees_double ()
Angle ~ Turns ~ ~ native.Float64
--> Angle ~ Degrees ~ ~ native.Float64
```*dst = *src * 360.0;```
Angle ~ Turns ~ ~ native.Double
--> Angle ~ Degrees ~ ~ native.Double
```
*dst = *src * 360.0;
return 0;
```
morph_angle_as_radians_to_turns_float ()
Angle ~ Radians ~ ~ native.Float32
--> Angle ~ Turns ~ ~ native.Float32
```*dst = *src / PHI;```
Angle ~ Radians ~ ~ native.Float
--> Angle ~ Turns ~ ~ native.Float
```
*dst = *src / PHI;
return 0;
```
morph_angle_as_radians_to_turns_double ()
Angle ~ Radians ~ ~ native.Float64
--> Angle ~ Turns ~ ~ native.Float64
```*dst = *src / PHI;```
Angle ~ Radians ~ ~ native.Double
--> Angle ~ Turns ~ ~ native.Double
```
*dst = *src / PHI;
return 0;
```
morph_angle_as_turns_to_radians_float ()
Angle ~ Turns ~ ~ native.Float32
--> Angle ~ Radians ~ ~ native.Float32
```*dst = *src * PHI;```
Angle ~ Turns ~ ~ native.Float
--> Angle ~ Radians ~ ~ native.Float
```
*dst = *src * PHI;
return 0;
```
morph_angle_as_degrees_to_radians_double ()
Angle ~ Turns ~ ~ native.Float64
--> Angle ~ Radians ~ ~ native.Float64
```*dst = *src * PHI;```
Angle ~ Turns ~ ~ native.Double
--> Angle ~ Radians ~ ~ native.Double
```
*dst = *src * PHI;
return 0;
```

View file

@ -36,7 +36,7 @@ morph_digit_as_char_to_uint64 (Radix:)
else if( *src >= 'A' && *src <= 'F')
*dst = 0xa + *src - 'A';
else {
fprintf(stderr, "invalid digit 0x%x (radix %u)\n", *src, Radix);
fprintf(stderr, "invalid digit 0x%x\n", *src);
return -1;
}
@ -60,6 +60,8 @@ morph_digit_as_uint8_to_char (Radix:_16)
fprintf(stderr, "digit %u is out of rage for char\n", *dst);
return -1;
}
return 0;
```
morph_digit_as_uint64_to_char (Radix:_16)
@ -74,4 +76,6 @@ morph_digit_as_uint64_to_char (Radix:_16)
fprintf(stderr, "digit %u is out of rage for char\n", *dst);
return -1;
}
return 0;
```

View file

@ -3,44 +3,28 @@
#include <array/length-prefix.h>
```
morph_array_as_static_to_lenpfx (Len: , T: Type)
<Seq~<StaticLength Len> T>
--> <Seq~<LengthPrefix native.UInt64> T>
morph_array_as_valterm_to_lenpfx (Terminator:native.UInt8)
<Seq~<ValueTerminated Terminator> native.UInt8>
--> <Seq~<LengthPrefix native.UInt64> native.UInt8>
```
PRESCAN_LENGTH_PREFIX_CALL(nativeUInt64, T, clear)( dst );
for( nativeUInt64 i = 0; i < Len; ++i )
PRESCAN_LENGTH_PREFIX_CALL(nativeUInt64, T, push)( dst, src->items[i] );
```
morph_array_as_lenpfx_to_static (Len: , T: Type)
<Seq~<LengthPrefix native.UInt64> T>
--> <Seq~<StaticLength Len> T>
```
nativeUInt64 i;
for( i = 0; i < Len && i < src->len; ++i )
dst->items[i] = src->items[i];
if( i < Len )
memset( &dst[i], 0, (Len-i) * sizeof(T) );
```
morph_array_as_valterm_to_lenpfx (T: Type, Terminator:T)
<Seq~<ValueTerminated Terminator> T>
--> <Seq~<LengthPrefix native.UInt64> T>
```
PRESCAN_LENGTH_PREFIX_CALL(nativeUInt64, T, push)( dst );
length_prefix_uint64_t_array_uint8_t_clear(dst);
while( *src != Terminator )
PRESCAN_LENGTH_PREFIX_CALL(nativeUInt64, T, push)( dst, *src++ );
length_prefix_uint64_t_array_uint8_t_push(dst, *src++);
return 0;
```
morph_array_as_lenpfx_to_valterm (T: Type, Terminator: T)
<Seq~<LengthPrefix native.UInt64> T>
--> <Seq~<ValueTerminated Terminator> T>
morph_array_as_lenpfx_to_valterm (Terminator:native.UInt8)
<Seq~<LengthPrefix native.UInt64> native.UInt8>
--> <Seq~<ValueTerminated Terminator> native.UInt8>
```
for( uint64_t i = 0; i < src->len; ++i )
*dst++ = src->items[i];
*dst = Terminator;
return 0;
```
morph_array_as_lenpfx_to_continuation_bit (T:Type)
@ -49,13 +33,15 @@ morph_array_as_lenpfx_to_continuation_bit (T:Type)
```
for( uint64_t i = 0; i < src->len; ++i ) {
const size_t n_bits = 8*sizeof(T);
if( src->items[i] & ((uint64_t)1<<(n_bits-1)) ) {
fprintf(stderr, "error: value has MSB set, while being used in MsbContinuation sequence!\n");
if( src->items[i] & (1<<(n_bits-1)) ) {
fprintf(stderr, "error: value to high for MsbContinuation\n");
return -1;
}
dst[i] = src->items[i];
if( i+1 < src->len )
dst[i] |= ((uint64_t)1<<(n_bits-1));
dst[i] |= (1<<(n_bits-1));
}
return 0;
```

View file

@ -11,6 +11,7 @@ morph_nat_as_u64_to_pos ()
```
dst->len = 1;
dst->items[0] = *src;
return 0;
```
morph_nat_as_pos_to_u64 (Endianness:Type)
@ -21,6 +22,7 @@ morph_nat_as_pos_to_u64 (Endianness:Type)
~ native.UInt64
```
*dst = src->items[0];
return 0;
```
morph_posint_radix_le (SrcRadix:, DstRadix:)
@ -38,18 +40,20 @@ morph_posint_radix_le (SrcRadix:, DstRadix:)
value += src->items[src->len - i - 1];
}
length_prefix_nativeUInt64_array_nativeUInt64_clear( dst );
length_prefix_uint64_t_array_uint64_t_clear( dst );
#if DstRadix==0
length_prefix_nativeUInt64_array_nativeUInt64_push( dst, value );
length_prefix_uint64_t_array_uint64_t_push( dst, value );
#else
if( value == 0 ) {
length_prefix_nativeUInt64_array_nativeUInt64_push( dst, 0 );
length_prefix_uint64_t_array_uint64_t_push( dst, 0 );
} else while( value > 0 ) {
length_prefix_nativeUInt64_array_nativeUInt64_push( dst, value % DstRadix );
length_prefix_uint64_t_array_uint64_t_push( dst, value % DstRadix );
value /= DstRadix;
}
#endif
return 0;
```
morph_posint_radix_be (SrcRadix:, DstRadix:)
@ -87,6 +91,8 @@ morph_posint_radix_be (SrcRadix:, DstRadix:)
value /= DstRadix;
}
#endif
return 0;
```
morph_posint_endianness (Radix:)
@ -97,7 +103,7 @@ morph_posint_endianness (Radix:)
~ <PosInt Radix BigEndian>
~ <Seq~<LengthPrefix native.UInt64> <Digit Radix> ~ native.UInt64>
```
return length_prefix_nativeUInt64_array_nativeUInt64_reverse( src, dst );
return length_prefix_uint64_t_array_uint64_t_reverse( src, dst );
```
morph_posint_endianness (Radix:)
@ -108,5 +114,5 @@ morph_posint_endianness (Radix:)
~ <PosInt Radix LittleEndian>
~ <Seq~<LengthPrefix native.UInt64> <Digit Radix> ~ native.UInt64>
```
return length_prefix_nativeUInt64_array_nativeUInt64_reverse( src, dst );
return length_prefix_uint64_t_array_uint64_t_reverse( src, dst );
```

View file

@ -4,87 +4,102 @@
morph_real_as_decimalstr_to_float ()
~ <PosInt 10 BigEndian> ~ <Seq~<ValueTerminated 0> <Digit 10>~Char~Ascii~native.UInt8>
--> ~ native.Float32
```sscanf(src, "%f", dst);```
--> ~ native.Float
```
sscanf(src, "%f", dst);
return 0;
```
morph_real_as_decimalstr_to_double ()
~ <PosInt 10 BigEndian> ~ <Seq~<ValueTerminated 0> <Digit 10>~Char~Ascii~native.UInt8>
--> ~ native.Float64
```sscanf(src, "%lf", dst);```
--> ~ native.Double
```
sscanf(src, "%lf", dst);
return 0;
```
morph_real_as_float_to_decimalstr ()
~ native.Float32
~ native.Float
--> ~ <PosInt 10 BigEndian> ~ <Seq~<ValueTerminated 0> <Digit 10>~Char~Ascii~native.UInt8>
```sprintf(dst, "%f", *src);```
```
sprintf(dst, "%f", *src);
return 0;
```
morph_real_as_double_to_decimalstr ()
~ native.Float64
~ native.Double
--> ~ <PosInt 10 BigEndian> ~ <Seq~<ValueTerminated 0> <Digit 10>~Char~Ascii~native.UInt8>
```sprintf(dst, "%f", *src);```
```
sprintf(dst, "%f", *src);
return 0;
```
morph_real_as_float_to_double ()
~ native.Float32
--> ~ native.Float64
```*dst = *src;```
~ native.Float
--> ~ native.Double
```
*dst = *src;
return 0;
```
morph_real_as_double_to_float ()
~ native.Float64
--> ~ native.Float32
~ native.Double
--> ~ native.Float
```
fprintf(stderr, "Warning: morphin Double -> Float. Precision loss!");
*dst = *src;
return 0;
```
morph_real_as_u64_to_float ()
~ ~ native.UInt64
--> ~ native.Float32
--> ~ native.Float
```
fprintf(stderr, "Warning: morphin UInt64 -> Float. Precision loss!");
*dst = *src;
return 0;
```
morph_real_as_u64_to_double ()
~ ~ native.UInt64
--> ~ native.Float64
--> ~ native.Double
```
fprintf(stderr, "Warning: morphin UInt64 -> Double. Precision loss!");
*dst = *src;
```
morph_real_as_nat_to_quantized_linear ()
~ ~ native.UInt64
--> ~ <QuantizedLinear 0 1 1> ~ ~ native.UInt64
```
*dst = *src;
return 0;
```
morph_real_as_quantized_linear_to_float (Begin: , End: , Steps: )
~ <QuantizedLinear Begin End Steps> ~ ~ native.UInt64
--> ~ native.Float32
--> ~ native.Float
```
*dst = (float)Begin + ( *src * ((float)End - (float)Begin) ) / (float)Steps;
return 0;
```
morph_real_as_float_to_quantized_linear (Begin: , End: , Steps: )
~ native.Float32
~ native.Float
--> ~ <QuantizedLinear Begin End Steps> ~ ~ native.UInt64
```
*dst = ((*src - (float)Begin) * (float)Steps) / ((float)End - (float)Begin);
return 0;
```
morph_real_as_quantized_linear_to_double (Begin: , End: , Steps: )
~ <QuantizedLinear Begin End Steps> ~ ~ native.UInt64
--> ~ native.Float64
--> ~ native.Double
```
*dst = (double)Begin + ( *src * ((double)End - (double)Begin) ) / (double)Steps;
return 0;
```
morph_real_as_double_to_quantized_linear (Begin: , End: , Steps: )
~ native.Float64
~ native.Double
--> ~ <QuantizedLinear Begin End Steps> ~ ~ native.UInt64
```
*dst = ((*src - (double)Begin) * (double)Steps) / ((double)End - (double)Begin);
return 0;
```

View file

@ -2,37 +2,27 @@
#include <stdio.h>
#include <stdint.h>
/*
typedef struct { \
LEN_TYPE len; \
ITEM_TYPE items[]; \
} __Seq__LengthPrefix_##LEN_TYPE##___##ITEM_TYPE##_; \
*/ \
#define LENGTH_PREFIX_ARRAY_TYPE(LEN_TYPE, ITEM_TYPE) \
__Seq__LengthPrefix_##LEN_TYPE##___##ITEM_TYPE##_
#define LENGTH_PREFIX_ARRAY_CALL(LEN_TYPE, ITEM_TYPE, METHOD) \
length_prefix_##LEN_TYPE##_array_##ITEM_TYPE##_ ## METHOD
#define PRESCAN_LENGTH_PREFIX_CALL(LEN, ITEM, METHOD) \
LENGTH_PREFIX_ARRAY_CALL(LEN, ITEM, METHOD)
#define DEFINE_LENGTH_PREFIX_ARRAY(LEN_TYPE, ITEM_TYPE) \
static inline void PRESCAN_LENGTH_PREFIX_CALL(LEN_TYPE, ITEM_TYPE, clear) \
(__Seq__LengthPrefix_##LEN_TYPE##___##ITEM_TYPE##_ *data) { \
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 PRESCAN_LENGTH_PREFIX_CALL(LEN_TYPE, ITEM_TYPE, push) \
(__Seq__LengthPrefix_##LEN_TYPE##___##ITEM_TYPE##_ *data, \
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 PRESCAN_LENGTH_PREFIX_CALL(LEN_TYPE, ITEM_TYPE, reverse) \
( __Seq__LengthPrefix_##LEN_TYPE##___##ITEM_TYPE##_ const * restrict src, \
__Seq__LengthPrefix_##LEN_TYPE##___##ITEM_TYPE##_ *restrict dst) { \
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]; \
} \
@ -40,11 +30,60 @@ typedef struct { \
return 0; \
} \
\
static inline void PRESCAN_LENGTH_PREFIX_CALL(LEN_TYPE, ITEM_TYPE, dump) \
( __Seq__LengthPrefix_##LEN_TYPE##___##ITEM_TYPE##_ const * data) { \
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"); \
}
#define DEFINE_ALL_LENGTH_PREFIX_ARRAYS(LEN_TYPE) \
DEFINE_LENGTH_PREFIX_ARRAY(LEN_TYPE, uint8_t) \
DEFINE_LENGTH_PREFIX_ARRAY(LEN_TYPE, uint16_t) \
DEFINE_LENGTH_PREFIX_ARRAY(LEN_TYPE, uint32_t) \
DEFINE_LENGTH_PREFIX_ARRAY(LEN_TYPE, uint64_t)
DEFINE_ALL_LENGTH_PREFIX_ARRAYS(uint8_t)
DEFINE_ALL_LENGTH_PREFIX_ARRAYS(uint16_t)
DEFINE_ALL_LENGTH_PREFIX_ARRAYS(uint32_t)
DEFINE_ALL_LENGTH_PREFIX_ARRAYS(uint64_t)
#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)

View file

@ -2,21 +2,33 @@
```
morph_celsius_to_kelvin ()
Temperature ~ Celsius ~ ~ native.Float32
--> Temperature ~ Kelvin ~ ~ native.Float32
```*dst = *src + 273.15;```
Temperature ~ Celsius ~ ~ native.Float
--> Temperature ~ Kelvin ~ ~ native.Float
```
*dst = *src + 273.15;
return 0;
```
morph_kelvin_to_celsius ()
Temperature ~ Kelvin ~ ~ native.Float32
--> Temperature ~ Celsius ~ ~ native.Float32
```*dst = *src - 273.15;```
Temperature ~ Kelvin ~ ~ native.Float
--> Temperature ~ Celsius ~ ~ native.Float
```
*dst = *src - 273.15;
return 0;
```
morph_celsius_to_fahrenheit ()
Temperature ~ Celsius ~ ~ native.Float32
--> Temperature ~ Fahrenheit ~ ~ native.Float32
```*dst = (*src * 9.0 / 5.0) + 32.0;```
Temperature ~ Celsius ~ ~ native.Float
--> Temperature ~ Fahrenheit ~ ~ native.Float
```
*dst = (*src * 9.0 / 5.0) + 32.0;
return 0;
```
morph_fahrenheit_to_celsius ()
Temperature ~ Fahrenheit ~ ~ native.Float32
--> Temperature ~ Celsius ~ ~ native.Float32
```*dst = (*src - 32.0) * 5.0 / 9.0;```
Temperature ~ Fahrenheit ~ ~ native.Float
--> Temperature ~ Celsius ~ ~ native.Float
```
*dst = (*src - 32.0) * 5.0 / 9.0;
return 0;
```

View file

@ -11,4 +11,5 @@ morph_unixtime_to_iso ()
if (!timeinfo) return -1;
strftime((char*)dst, 20, "%Y-%m-%dT%H:%M:%SZ", timeinfo);
return 0;
```

View file

@ -1,17 +0,0 @@
```
```
morph_nat_as_u8_to_u16 ()
~ native.UInt8
--> ~ native.UInt16
```*dst = *src;```
morph_nat_as_u16_to_u32 ()
~ native.UInt16
--> ~ native.UInt32
```*dst = *src;```
morph_nat_as_u32_to_u64 ()
~ native.UInt32
--> ~ native.UInt64
```*dst = *src;```

View file

@ -28,6 +28,7 @@ morph_string_as_utf8_to_ascii ()
}
}
*dst = 0;
return 0;
```
morph_string_as_ascii_to_utf32 ()
@ -38,6 +39,7 @@ morph_string_as_ascii_to_utf32 ()
```
while( *src ) { *dst++ = *src++; }
*dst = 0;
return 0;
```
morph_string_as_utf8_to_utf32 ()
@ -87,4 +89,6 @@ morph_string_as_utf8_to_utf32 ()
*dst++ = val;
*dst++ = 0;
return 0;
```

View file

@ -3,7 +3,7 @@
#include <stdlib.h>
```
morph_valsep_delim (T: Type, SrcDelim: T, DstDelim: T)
morph_seqseq_valsep_uint8 (T: Type, SrcDelim: T, DstDelim: T)
< Seq <Seq T> >
~ < ValueSep SrcDelim T >
~ < Seq~<LengthPrefix native.UInt64> T >
@ -12,24 +12,23 @@ morph_valsep_delim (T: Type, SrcDelim: T, DstDelim: T)
~ < ValueSep DstDelim T >
~ < Seq~<LengthPrefix native.UInt64> T >
```
PRESCAN_LENGTH_PREFIX_CALL(nativeUInt64, T, 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 ) {
PRESCAN_LENGTH_PREFIX_CALL(nativeUInt64, T, push)( dst, DstDelim );
length_prefix_uint64_t_array_uint8_t_push( dst, DstDelim );
} else if( src->items[i] == DstDelim ) {
if( DstDelim == '\n' ) {
PRESCAN_LENGTH_PREFIX_CALL(nativeUInt64, T, push)( dst, '\\' );
PRESCAN_LENGTH_PREFIX_CALL(nativeUInt64, T, push)( dst, 'n' );
} else {
PRESCAN_LENGTH_PREFIX_CALL(nativeUInt64, T, push)( dst, '\\' );
PRESCAN_LENGTH_PREFIX_CALL(nativeUInt64, T, push)( dst, DstDelim );
length_prefix_uint64_t_array_uint8_t_push( dst, '\\' );
length_prefix_uint64_t_array_uint8_t_push( dst, 'n' );
}
} else {
PRESCAN_LENGTH_PREFIX_CALL(nativeUInt64, T, push)( dst, src->items[i] );
length_prefix_uint64_t_array_uint8_t_push( dst, src->items[i] );
}
}
return 0;
```
@ -45,28 +44,30 @@ morph_seqseq_as_valsep_to_lenpfx (T: Type, Delim: T, EscKey: T)
~ native.UInt64
>
```
length_prefix_nativeUInt64_array_nativeUInt64_clear( dst );
length_prefix_uint64_t_array_uint64_t_clear( dst );
LENGTH_PREFIX_ARRAY_TYPE( nativeUInt64, T ) * cur_item = NULL;
struct LengthPrefix_uint64_t_Array_uint8_t * cur_item = NULL;
T const * start = &src->items[0];
T const * cur = start;
T const * end = &src->items[src->len];
uint8_t const * start = &src->items[0];
uint8_t const * cur = start;
uint8_t const * end = &src->items[src->len];
while( cur < end ) {
if( *cur == Delim || cur+1 == end ) {
uint64_t len = cur - start;
cur_item = malloc( sizeof(uint64_t) + sizeof(T) * len );
cur_item = malloc( sizeof(uint64_t) + sizeof(uint8_t) * len );
cur_item->len = len;
memcpy( cur_item->items, start, len );
length_prefix_nativeUInt64_array_nativeUInt64_push( dst, (uint64_t)cur_item );
length_prefix_uint64_t_array_uint64_t_push( dst, (uint64_t)cur_item );
start = ++cur;
} else {
cur++;
}
}
return 0;
```
morph_seqeq_as_lenpfx_to_valsep (T: Type, Delim: T, EscKey: T)
@ -80,17 +81,19 @@ morph_seqeq_as_lenpfx_to_valsep (T: Type, Delim: T, EscKey: T)
~ < ValueSep T Delim >
~ < Seq~<LengthPrefix native.UInt64> T >
```
PRESCAN_LENGTH_PREFIX_CALL(nativeUInt64, T, clear)( dst );
length_prefix_uint64_t_array_uint8_t_clear( dst );
for( uint64_t i = 0; i < src->len; ++i ) {
LENGTH_PREFIX_ARRAY_TYPE( nativeUInt64, T ) * item = src->items[i];
LengthPrefix_uint64_t_Array_uint8_t * item = src->items[i];
for( uint64_t j = 0; j < item->len; ++j ) {
PRESCAN_LENGTH_PREFIX_CALL( nativeUInt64, T, push )( items->items[j] );
length_prefix_uint64_t_array_uint8_t_push( items->items[j] );
}
if( i+1 < src->len ) {
PRESCAN_LENGTH_PREFIX_CALL( nativeUInt64, T, push )( Delim );
length_prefix_uint64_t_array_uint8_t_push( Delim );
}
}
return 0;
```

View file

@ -10,6 +10,8 @@ morph_i64_as_twos_complement_to_zigzag ()
} else {
*dst = (2 * (uint64_t)(- *src)) - 1;
}
return 0;
```
morph_i64_as_zigzag_to_twos_complement ()

View file

@ -1,100 +0,0 @@
type UTF8-String = <Seq Char~Unicode> ~ UTF-8 ~ <Seq~<ValueTerminated 0> native.UInt8> ;
type SerializedJson.Value = json.Value
~ <Enum
<Null json.Null ~ SerializedJson.Null >
<String json.String ~ SerializedJson.String >
<Number json.Number ~ SerializedJson.Number >
<Bool json.Bool ~ SerializedJson.Bool >
<Array json.Array ~ SerializedJson.Array >
<Object json.Object ~ SerializedJson.Object >>
~ <Seq Char> ;
type SerializedJson.Null = < Struct~<Seq Char> "\"null\"" > ;
type SerializedJson.String = <Seq Char>
~ <Struct~<Seq Char> "\"" <Seq Char> "\"">
~ <Seq Char> ;
type SerializedJson.Number =
~ <PosInt 10 BigEndian>
~ <Seq <Digit 10> ~ Char> ;
type SerializedJson.Bool = Bool
~ <Enum~<Seq Char>
<True~"\"true\"" <>>
<False~"\"false\"" <>>>
~ <Seq Char> ;
type SerializedJson.Array = <Struct~<Seq Char>
"["
<Seq json.Value>
~ <ValueSep ',' Char>
~ <Seq Char>
"]" >
~ <Seq Char> ;
type SerializedJson.Object = <Struct~<Seq Char>
"{"
<members <Seq
<Struct~<Seq Char>
<key json.String>
":"
<value json.Value>>>>
"}"
>
~ <Seq Char>;
type parsedJson.Value = json.Value ~ <Enum~native.UInt8
< parsedJson_Null~0 <> >
< parsedJson_String~1 <Ref UTF8-String> ~ native.Address >
< parsedJson_Int~2 ~~native.UInt64 >
< parsedJson_Float~2 ~native.Float64 >
< parsedJson_Bool~3 Bool ~ native.UInt8 >
< parsedJson_Array~4 <Ref <Seq ~ <LengthPrefix native.UInt64>
parsedJsonValue
>
>
~ native.Address >
< parsedJson_Object~5 <Ref <Seq ~ <LengthPrefix native.UInt64>
<Struct
<key <Ref UTF8-String> ~ native.Address>
<val parsedJsonValue>
>
>
~ native.Address >>
~ <Struct
<tag native.UInt8>
native.UInt64 >;
parse_json_value ()
json.Value ~ UTF8-String
--> json.Value ~ parsedJsonValue
```
{
dst->tag = PARSED_JSON_NULL;
dst->parsedJson_Null;
}
{
dst->tag = PARSED_JSON_STRING;
dst->parsedJson_String = malloc(len);
strncpy(dst->parsedJson_String, src, len);
src += len;
}
{
dst->tag = PARSED_JSON_NUMBER;
MORPH(
" ~ ~ <PosInt 10 BigEndian> ~ <Seq <Digit 10> ~ Char> ~ UTF8-String",
" ~ ~ native.UInt64",
src,
&dst->parsedJson_Number
);
}
```

View file

View file

@ -1,3 +0,0 @@
type protobuf.Varint = ~ <PosInt 128 LittleEndian> ~ <Seq~MsbCont <Digit 128> ~ _128 ~ native.UInt8> ;
type protobuf.String = <Seq Char ~ Unicode> ~ UTF-8 ~ <Seq ~ <LengthPrefix protobuf.Varint> Byte> ;

View file

View file

@ -1,5 +0,0 @@
type x86.UInt64 = _2/\64 ~ <PosInt 256 LittleEndian> ~ <Seq~<StaticLength 8> <Digit 256> ~ x86.UInt8 >;
type x86.UInt32 = _2/\32 ~ <PosInt 256 LittleEndian> ~ <Seq~<StaticLength 4> <Digit 256> ~ x86.UInt8 >;
type x86.UInt16 = _2^16 ~ <PosInt 256 LittleEndian> ~ <Seq~<StaticLength 2> <Digit 256> ~ x86.UInt8 >;
type x86.UInt8 = _256 ~ <Posint 2 BigEndian> ~ <Seq~<StaticLength 8> <Digit 2> ~ Bit>;

419
src/c_gen.rs Normal file
View file

@ -0,0 +1,419 @@
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("native.UInt8").expect("parse")
|| t == &dict.parse("<StaticLength 8 Bit>").expect("parse")
{
Some("uint8_t".into())
} else if t == &dict.parse("native.UInt16").expect("parse") {
Some("uint16_t".into())
} else if t == &dict.parse("native.UInt32").expect("parse") {
Some("uint32_t".into())
} else if t == &dict.parse("native.UInt64").expect("parse") {
Some("uint64_t".into())
} else if t == &dict.parse("native.Float").expect("parse") {
Some("float".into())
} else if t == &dict.parse("native.Double").expect("parse") {
Some("double".into())
} else {
match t {
laddertypes::TypeTerm::App(args) => {
if args[0] == laddertypes::TypeTerm::TypeID(dict.get_typeid(&"LengthPrefix".into()).unwrap())
{
let length_c_type : String = get_c_repr_type(dict, args[1].clone(), false)?;
let item_c_type : String = get_c_repr_type(dict, args[2].clone(), false)?;
match length_c_type.as_str() {
"uint8_t" |
"uint16_t" |
"uint32_t" |
"uint64_t" => {}
_ => {
eprintln!("invalid length type!");
return None;
}
}
match item_c_type.as_str() {
"uint8_t" |
"uint16_t" |
"uint32_t" |
"uint64_t" => {}
_ => {
eprintln!("invalid item type!");
return None;
}
}
Some(format!("LengthPrefix_{}_Array_{}", length_c_type, item_c_type))
}
else if args[0] == laddertypes::TypeTerm::TypeID(dict.get_typeid(&"ValueTerminated".into()).unwrap())
{
let _delim_val = args[1].clone();
let c_type = get_c_repr_type(dict, args[2].clone(), false)?;
if skip_pointer {
Some(c_type)
} else {
Some(format!("{} *", c_type))
}
}
else if args[0] == laddertypes::TypeTerm::TypeID(dict.get_typeid(&"MsbCont".into()).unwrap())
{
let c_type = get_c_repr_type(dict, args[1].clone(), false)?;
if skip_pointer {
Some(c_type)
} else {
Some(format!("{} *", c_type))
}
}
else {
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[128];
uint8_t bufB[128];
memset(bufA, 0, sizeof(bufA));
memset(bufB, 0, sizeof(bufB));
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, sizeof(bufA));
//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> native.UInt8>").unwrap()
) {
println!(r#"
printf("%s\n", {});"#, out_buf);
} else if let Ok((halo, σ)) = laddertypes::subtype_unify(
&dst_type,
&type_dict.parse("<Seq~<LengthPrefix native.UInt64> native.UInt8>").unwrap()
) {
println!(r#"
/* write output
*/
{{
LengthPrefix_uint64_t_Array_uint8_t * buf = (void*){};
write(1, {}, sizeof(uint64_t) + buf->len);
}}"#, out_buf, out_buf);
} else {
println!(r#"
write(1, {}, sizeof({}));"#,
out_buf,
out_buf
);
}
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) {
eprintln!("val = {}", dict.unparse(&val));
let type_var_value =
if let Some(c_repr_type) = get_c_repr_type(dict, val.clone(), true) {
c_repr_type
} else {
encode_type_to_value(dict, val)
};
s.push_str(&format!(" #define {} {}\n", dict.get_typename(&ty_id).unwrap(), type_var_value));
}
}
s.push_str(&self.c_source);
for (ty_id, kind) in self.type_args.iter() {
s.push_str(&format!("\n #undef {}", dict.get_typename(&ty_id).unwrap()));
}
s.push_str(&format!(r#"
}}
"#));
Some(s)
}
}
impl LdmcMorphism {
pub fn 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_type = self.get_type().src_type.clone().apply_substitution(&|k| σ.get(k).cloned()).clone();
let dst_type = self.get_type().dst_type.clone().apply_substitution(&|k| σ.get(k).cloned()).clone();
eprintln!("length prefix type ={:?}", length_prefix_type);
eprintln!("src_type ={:?}", src_type);
eprintln!("dst_type = {:?}", dst_type);
dict.add_varname("S".into());
let γ_src = laddertypes::unify(
&dict.parse("<Seq~<LengthPrefix S> T>").expect("parse template"),
&src_type
).expect("cant get src item type");
let γ_dst = laddertypes::unify(
&dict.parse("<Seq~<LengthPrefix S> T>").expect("parse template"),
&dst_type
).expect("cant get dst item type");
let src_length_type = γ_src.get(&dict.get_typeid(&"S".into()).unwrap()).expect("cant get src-length type").clone();
let dst_length_type = γ_src.get(&dict.get_typeid(&"S".into()).unwrap()).expect("cant get dst-length type").clone();
let length_type = src_length_type;
let src_item_type = γ_src.get(&dict.get_typeid(&"T".into()).unwrap()).expect("cant get src-item type").clone();
let dst_item_type = γ_dst.get(&dict.get_typeid(&"T".into()).unwrap()).expect("cant get src-item type").clone();
let length_c_type = get_c_repr_type(dict, length_type, true).expect("cant c-repr type for array length");
let src_item_c_type = get_c_repr_type(dict, src_item_type, true).expect("cant c-repr type for src item");
let dst_item_c_type = get_c_repr_type(dict, dst_item_type, true).expect("cant c-repr type for dst item");
let src_c_type = get_c_repr_type(dict, src_type, true).expect("cant get c-repr type for src type");
let dst_c_type = get_c_repr_type(dict, dst_type, true).expect("cant get c-repr type for dst type");
let map_fn = format!("length_prefix_{}_array_map_{}_to_{}",
length_c_type, src_item_c_type, dst_item_c_type
);
let src_buf = if i%2 == 0 { "bufA" } else { "bufB" };
let dst_buf = if i%2 == 0 { "bufB" } else { "bufA" };
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, σ),
'}');
}
}
}
}

View file

@ -1,82 +0,0 @@
use {
super::types::get_c_repr_arg_type, crate::{c_gen::LdmcCTargetMorph, LdmcPrimMorph}, laddertypes::{morphism::MorphismInstance, parser::*, MorphismType, TypeDict}, std::collections::HashMap
};
pub fn generate_lib(
dict: &mut impl TypeDict,
include_blocks: Vec< String >,
include_dependencies: HashMap< MorphismType, usize >,
morphisms: Vec< (String, MorphismInstance<LdmcPrimMorph>) >
) -> Result<String, ()> {
let mut target = LdmcCTargetMorph::new( include_blocks, include_dependencies );
let mut wrappers = String::new();
for (name, morph) in morphisms {
match target.add_instantiation(dict, morph) {
Ok(inst) => {
if name == "main" {
let mut c_source = String::new();
c_source.push_str(&format!(r#"
#include <unistd.h>
int main() {{
uint8_t bufIn[4096];
uint8_t bufOut[4096];"#));
if let Ok(_) = laddertypes::subtype_unify(
&inst.ty.src_type,
&dict.parse("<Seq~<ValueTerminated '\\n'> Char~Ascii~native.UInt8>").expect("")
) {
c_source.push_str("scanf(\"%s\", bufIn);\n");
} else {
c_source.push_str("read(0, bufIn, sizeof(bufIn));\n");
}
c_source.push_str(
&format!(r#"FUSE( {}, (void const*)bufIn, (void*)bufOut );
"#,
inst.instantiated_symbol_name(dict, &HashMap::new()))
);
if let Ok(ψ) = laddertypes::subtype_unify(
&inst.ty.dst_type,
&dict.parse("<Seq~<ValueTerminated 0> native.UInt8>").expect("")
) {
c_source.push_str("printf(\"%s\\n\", bufOut);\n");
} else {
c_source.push_str("write(1, bufOut, sizeof(bufOut));\n");
}
c_source.push_str("
return 0;
}");
wrappers.push_str(&c_source);
} else {
target.add_type(dict, inst.ty.src_type.clone());
target.add_type(dict, inst.ty.dst_type.clone());
wrappers.push_str(&format!("
int {} (
{} const * restrict src,
{} * restrict dst
) {{
return {}( (void*)src, (void*)dst );
}}
", name,
get_c_repr_arg_type(dict, &inst.ty.src_type),
get_c_repr_arg_type(dict, &inst.ty.dst_type),
inst.instantiated_symbol_name(dict, &HashMap::new())
));
}
}
Err(_err) => {
eprintln!("failed to create morphism instatiation");
return Err(());
}
}
}
let mut c_source = target.into_c_source(dict);
c_source.push_str(&wrappers);
Ok(c_source)
}

View file

@ -1,7 +0,0 @@
pub mod types;
pub mod morph;
pub mod gen_lib;
pub use {
morph::target_morph::LdmcCTargetMorph
};

View file

@ -1,76 +0,0 @@
pub mod target_morph;
use {
crate::{
c_gen::types::{
get_c_repr_arg_type,
get_c_repr_definition,
get_c_repr_type
},
morphism::LdmcPrimMorph
},
laddertypes::{TypeDict, Substitution},
};
impl LdmcPrimMorph {
pub fn instantiated_symbol_name(&self, dict: &mut impl TypeDict, σ: &impl Substitution) -> 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 {
//if self.get_type().strip_halo().src_type.contains_var(*var_id) ||
//self.get_type().strip_halo().dst_type.contains_var(*var_id) {
let name = dict.get_varname(*var_id).unwrap();
let val_str = get_c_repr_type(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 type parameter {} ({})", 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_definition(dict, self.ty.src_type.clone(), true).expect("cant get c-repr type for src type"),
get_c_repr_definition(dict, self.ty.dst_type.clone(), true).expect("cant get c-repr type for dst type"))
}
pub fn generate_instantiation(&self, dict: &mut impl TypeDict, σ: &impl Substitution) -> Option<String> {
let mut s = String::new();
let symbol = self.instantiated_symbol_name(dict, σ);
eprintln!("generate instantiation:");
let ty = self.ty.clone();
eprintln!("full type: {} ----> {}", ty.src_type.pretty(dict, 0), ty.dst_type.pretty(dict,0));
let ty = ty.strip_halo().apply_subst(σ);
eprintln!("stripped type: {} ----> {}", ty.src_type.pretty(dict, 0), ty.dst_type.pretty(dict,0));
let src_c_symbol = get_c_repr_arg_type(dict, &ty.src_type);
let dst_c_symbol = get_c_repr_arg_type(dict, &ty.dst_type);
s.push_str(&format!(r#"
int {} ( {} const * restrict src, {} * restrict dst ) {{
"#,
symbol, src_c_symbol, dst_c_symbol,
));
s.push_str(&self.c_source);
s.push_str(&format!(r#"
return 0;
}}
"#));
Some(s)
}
}

View file

@ -1,375 +0,0 @@
use {
crate::{
c_gen::types::{
encode_morph_type_to_symbol, encode_type_to_value, get_c_repr_definition, get_c_repr_kind, get_c_repr_type
},
morphism::LdmcPrimMorph
},
laddertypes::{
parser::*, Morphism, MorphismInstance, MorphismType, TypeDict, TypeTerm
},
std::collections::HashMap
};
pub struct LdmcCTargetMorph {
header_blocks: Vec< String >,
header_dependencies: HashMap< MorphismType, usize >,
active_headers: Vec< usize >,
active_types: Vec< TypeTerm >,
active_morphisms: Vec< LdmcPrimMorph >,
active_lenpfx_types: Vec< (TypeTerm, TypeTerm) >,
typedefs: Vec< String >,
macro_calls: Vec< String >
}
impl LdmcCTargetMorph {
pub fn add_required_header_block(&mut self, block: String) {
let i = self.header_blocks.len();
self.active_headers.push(i);
self.header_blocks.push(block);
}
pub fn new(
include_blocks: Vec< String >,
include_dependencies: HashMap< MorphismType, usize >
) -> Self {
let mut m = LdmcCTargetMorph {
header_blocks: include_blocks,
header_dependencies: include_dependencies,
active_headers: Vec::new(),
active_morphisms: Vec::new(),
active_types: Vec::new(),
active_lenpfx_types: Vec::new(),
typedefs: Vec::new(),
macro_calls: Vec::new()
};
m.add_required_header_block(
"/* default ldmc header */
#include <stdint.h>
#define FUSE(morph, src, dst) { int result = morph(src,dst); if(result) return result; }
".into()
);
m
}
pub fn add_type(&mut self, dict: &mut impl TypeDict, ty: TypeTerm) {
let ty = ty.strip();
if ! self.active_types.contains(&ty) {
eprintln!("add type {}", ty.pretty(dict,0));
let (ht,ft) = ty.get_floor_type();
if ht.is_empty() {
match &ft {
TypeTerm::Seq { seq_repr, items } => {
let item_type = items.first().unwrap().clone();
self.add_type(dict, item_type.clone());
if let Some(seq_repr) = seq_repr {
dict.add_varname("LengthType".into());
if let Ok(σ) =
laddertypes::constraint_system::unify(
seq_repr.as_ref(),
&dict.parse_desugared("<LengthPrefix LengthType>").expect("").sugar(dict)
)
{
let length_type = σ.get(&dict.get_typeid(&"LengthType".into()).expect("")).expect("cant get Length type");
self.add_type(dict, length_type.clone());
self.macro_calls.push(
format!("DEFINE_LENGTH_PREFIX_ARRAY({}, {})\n",
get_c_repr_type(dict, &length_type),
get_c_repr_type(dict, &item_type)
)
);
}
}
}
_ => {}
}
self.active_types.push(ty.clone());
if let Some(type_def) = get_c_repr_definition(dict, ft, false) {
let type_name = get_c_repr_type(dict, &ty);
self.typedefs.push(format!("typedef {} {};\n", type_def, type_name));
} else {
eprintln!("cant get c-repr type for type '{}'", ty.pretty(dict,0));
}
} else {
let type_name = get_c_repr_type(dict, &ty);
let type_def = get_c_repr_type(dict, &ft);
self.add_type(dict, ft);
self.typedefs.push(format!("typedef {} {};\n", type_def, type_name));
}
}
}
pub fn add_instantiation(
&mut self,
dict: &mut impl TypeDict,
morph: MorphismInstance<LdmcPrimMorph>,
) -> Result<LdmcPrimMorph, ()> {
let new_inst = self.bake_morphism(dict, morph)?;
if ! self.active_morphisms.contains(&new_inst) {
self.active_morphisms.push(new_inst.clone());
}
let ty = new_inst.get_type().strip_halo();
self.add_type(dict, ty.src_type);
self.add_type(dict, ty.dst_type);
Ok(new_inst)
}
pub fn into_c_source(mut self, dict: &mut impl TypeDict) -> String {
let mut source = String::new();
self.active_headers.dedup();
self.typedefs.dedup();
self.macro_calls.dedup();
for i in self.active_headers {
source.push_str( &self.header_blocks[i] );
source.push('\n');
}
source.push('\n');
for typedef in self.typedefs {
source.push_str(&typedef);
}
source.push('\n');
for m in self.macro_calls {
source.push_str(&m);
source.push('\n');
}
source.push('\n');
for m in self.active_morphisms {
source.push_str(&m.generate_instantiation(dict, &HashMap::new()).expect("cant create function"));
}
source
}
pub fn bake_morphism(
&mut self,
dict: &mut impl laddertypes::TypeDict,
morph_inst: MorphismInstance<LdmcPrimMorph>,
) -> Result<LdmcPrimMorph, ()> {
let ty = morph_inst.get_type();
let symbol = encode_morph_type_to_symbol(dict, &ty);
match &morph_inst {
MorphismInstance::Id { ψ } => {
self.add_required_header_block("#include <string.h>".into());
Ok(LdmcPrimMorph {
symbol,
type_args: Vec::new(),
ty: MorphismType { src_type: ψ.clone(), dst_type: ψ.clone() },
c_source: String::from("memcpy(dst, src, sizeof(*src));")
})
}
MorphismInstance::Primitive { ψ, σ, morph } => {
if let Some(i) = self.header_dependencies.get(&morph.get_type()) {
self.active_headers.push(*i);
}
let mut c_source = String::new();
for (ty_id, kind) in morph.type_args.iter() {
if let laddertypes::TypeID::Var(var_id) = ty_id {
if let Some(val) = σ.get(ty_id) {
let type_var_value =
if kind == "Type" {
get_c_repr_type(dict, val)
} else {
encode_type_to_value(dict, val)
};
c_source.push_str(&format!(" #define {} {}\n", dict.get_typename(&ty_id).unwrap(), type_var_value));
}
}
}
c_source.push_str(&morph.c_source);
for (ty_id, kind) in morph.type_args.iter() {
if let laddertypes::TypeID::Var(var_id) = ty_id {
c_source.push_str(&format!("\n #undef {}", dict.get_typename(&ty_id).unwrap()));
}
}
Ok(LdmcPrimMorph{
symbol: morph.instantiated_symbol_name(dict, σ),
type_args: Vec::new(),
ty: morph_inst.get_type().apply_subst(σ).strip_halo(),
c_source
})
},
MorphismInstance::Chain { path } => {
let mut c_source = String::new();
if path.len() > 1 {
c_source.push_str(r#"
uint8_t bufA[4096];
uint8_t bufB[4096];
"#);
}
for (i,morph) in path.iter().enumerate() {
if let Ok(inst) = self.add_instantiation(dict, morph.clone()) {
let morph_symbol = inst.instantiated_symbol_name(dict, &morph.get_subst());
let src_buf = if i == 0 { "(void*)src" } else if i%2 == 0 { "(void*)bufA" } else { "(void*)bufB" };
let dst_buf = if i+1 == path.len() { "(void*)dst" } else if i%2 == 0 { "(void*)bufB" } else { "(void*)bufA" };
c_source.push_str(&format!(r#"
FUSE( {}, {}, {} );"#,
morph_symbol, src_buf, dst_buf,
));
} else {
c_source.push_str(&format!("/* ERROR: missing morphism */"));
eprintln!("failed to add instantiation of item morphism");
}
}
Ok(LdmcPrimMorph {
symbol, type_args: Vec::new(), ty,
c_source
})
}
MorphismInstance::MapSeq { ψ, seq_repr, item_morph } => {
if let Ok(item_morph_inst) = self.add_instantiation(dict, item_morph.as_ref().clone()) {
if let Some(seq_repr) = seq_repr {
dict.add_varname("Length".into());
dict.add_varname("LengthType".into());
dict.add_varname("TerminatorValue".into());
if let Ok(γ) = laddertypes::constraint_system::unify(
&dict.parse_desugared("<StaticLength Length>").expect("parse type template").sugar(dict),
seq_repr.as_ref()
) {
let length = γ.get(&dict.get_typeid(&"Length".into()).expect("")).expect("cant get Length");
match length {
TypeTerm::Num(l) => {
let item_morph_symbol = item_morph_inst.instantiated_symbol_name(dict, &HashMap::new());
self.add_type( dict, morph_inst.get_type().strip_halo().src_type );
self.add_type( dict, morph_inst.get_type().strip_halo().dst_type );
let c_source = format!(r#"
for( size_t i = 0; i < {}; ++i ) {{
FUSE( {}, &src->items[i], &dst->items[i] );
}}
"#,
l,
item_morph_symbol,
);
Ok(LdmcPrimMorph{
symbol, type_args: Vec::new(), ty,
c_source
})
}
_ => {
eprintln!("invalid length '{}'", length.pretty(dict, 0));
Err(())
}
}
}
else if let Ok(γ) = laddertypes::constraint_system::unify(
&dict.parse_desugared("<LengthPrefix LengthType>").expect("parse type template").sugar(dict),
seq_repr.as_ref()
) {
// todo: assert that length type is native.UIntX
//let length_type = γ.get(&dict.get_typeid(&"LengthType".into()).expect("")).expect("cant get LengthType");
let item_morph_symbol = item_morph_inst.instantiated_symbol_name(dict, &HashMap::new());
self.add_type( dict, morph_inst.get_type().strip_halo().src_type );
self.add_type( dict, morph_inst.get_type().strip_halo().dst_type );
let c_source = format!(r#"
for( size_t i = 0; i < src->len; ++i ) {{
FUSE( {}, &src->items[i], &dst->items[i] );
}}
dst->len = src->len;
"#,
item_morph_symbol,
);
Ok(LdmcPrimMorph{
symbol, type_args: Vec::new(), ty,
c_source
})
}
else if let Ok(γ) = laddertypes::constraint_system::unify(
&dict.parse_desugared("<ValueTerminated TerminatorValue>").expect("parse type template").sugar(dict),
seq_repr.as_ref()
) {
let terminator_value = γ.get(&dict.get_typeid(&"TerminatorValue".into()).expect("")).expect("cant get TerminatorValue");
let item_morph_symbol = item_morph_inst.instantiated_symbol_name(dict, &HashMap::new());
let terminator = encode_type_to_value(dict, terminator_value);
let c_source = format!(r#"
while( *src != {} ) {{
FUSE( {}, src, dst );
++src;
++dst;
}}
*dst = {};"#,
terminator,
item_morph_symbol,
terminator
);
Ok(LdmcPrimMorph{
symbol, type_args: Vec::new(), ty,
c_source
})
}
else {
eprintln!("Error: Unknown Seq- Representation!!");
Err(())
}
} else {
eprintln!("Error: missing Seq- Representation!!");
Err(())
}
} else {
eprintln!("failed to add item-morph instantiation");
Err(())
}
},
MorphismInstance::MapStruct { ψ, src_struct_repr, dst_struct_repr, member_morph } => {
let mut c_source = String::new();
for (name, morph) in member_morph.iter() {
if let Ok(inst) = self.add_instantiation(dict, morph.clone()) {
let name = name.replace("-", "_").replace(".","_dot_");
c_source.push_str(
&format!("
FUSE( {}, &src->{}, &dst->{} );",
inst.symbol,
name, name
));
} else {
c_source.push_str(&format!("/* ERROR: missing morphism for struct member '{}' */", name));
eprintln!("failed to create morphism instantiation for struct member");
return Err(());
}
}
Ok(LdmcPrimMorph{
symbol, type_args: Vec::new(), ty,
c_source
})
}
MorphismInstance::MapEnum { ψ, enum_repr, variant_morph } => {
todo!();
}
}
}
}

View file

@ -1,257 +0,0 @@
use {
crate::struct_layout::LayoutType,
chumsky::chain::Chain, laddertypes::{morphism::MorphismType,
parser::*,
substitution::Substitution,
unparser::*, EnumVariant, StructMember, TypeTerm, TypeDict}
};
/*
*/
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_definition(dict: &mut impl TypeDict, t: TypeTerm, skip_pointer: bool) -> Option<String> {
match t {
TypeTerm::TypeID(tyid) => {
if tyid == dict.get_typeid_creat("native.UInt8") {
Some("uint8_t".into())
} else if tyid == dict.get_typeid_creat("native.UInt16") {
Some("uint16_t".into())
} else if tyid == dict.get_typeid_creat("native.UInt32") {
Some("uint32_t".into())
} else if tyid == dict.get_typeid_creat("native.UInt64") {
Some("uint64_t".into())
} else if tyid == dict.get_typeid_creat("native.Address") {
Some("void*".into())
} else if tyid == dict.get_typeid_creat("native.Float32") {
Some("float".into())
} else if tyid == dict.get_typeid_creat("native.Float64") {
Some("double".into())
} else {
None
}
}
TypeTerm::Seq{ seq_repr, items } => {
if let Some(seq_repr) = seq_repr {
let item_type = items.first().expect("no item type specified!").clone();
let item_c_type : String = get_c_repr_type(dict, &item_type);
dict.add_varname("Length".into()); // Kind: Num
dict.add_varname("LengthType".into()); // Kind: Type
dict.add_varname("TermValue".into()); // Kind: Value of Type ItemType
if let Ok((ψ, σ)) = laddertypes::constraint_system::subtype_unify(
seq_repr.as_ref(),
&dict.parse_desugared("<StaticLength Length>").expect("parse template type").sugar(dict)
) {
let length = match
σ.get(
&dict.get_typeid(&"Length".into()).expect("no Length ID")
).expect("no length specified!")
{
TypeTerm::Num(l) => l,
_ => {
eprintln!("invalid Length!");
return None;
}
};
Some(format!("struct {{ {} items[{}]; }} ", item_c_type, length))
}
else if let Ok((ψ, σ)) = laddertypes::constraint_system::subtype_unify(
seq_repr.as_ref(),
&dict.parse_desugared("<LengthPrefix LengthType>").expect("parse template type").sugar(dict)
) {
let length_type = σ.get(
&dict.get_typeid(&"LengthType".into()).expect("no LengthType ID")
).expect("no length type specified");
let length_c_type = get_c_repr_type(dict, &length_type);
Some(format!("struct {{ {} len; {} items[]; }} ", length_c_type, item_c_type))
}
else if let Ok((ψ, σ)) = laddertypes::constraint_system::subtype_unify(
seq_repr.as_ref(),
&dict.parse_desugared("<ValueTerminated TermValue>").expect("parse template type").sugar(dict)
) {
if skip_pointer {
Some(item_c_type)
} else {
Some(format!("{} *", item_c_type))
}
}
else if let Ok((ψ, σ)) = laddertypes::constraint_system::subtype_unify(
seq_repr.as_ref(),
&dict.parse_desugared("MsbCont").expect("parse template type").sugar(dict)
) {
if skip_pointer {
Some(item_c_type)
} else {
Some(format!("{} *", item_c_type))
}
}
else {
eprintln!("can't get C-repr for sequence type `{}`!", seq_repr.pretty(dict, 0));
None
}
} else {
eprintln!("no sequence-representation type specified!");
None
}
}
TypeTerm::Struct{ struct_repr, members } => {
let c_struct_attribute =
if let Some(sr) = struct_repr {
let sr = sr.desugar(dict);
match LayoutType::parse(dict, &sr).expect("layout type") {
LayoutType::Aligned => "",
LayoutType::Packed => "__attribute((packed))__"
}
} else {""};
let mut c_type = format!("struct {} {{\n", c_struct_attribute);
for StructMember{ symbol, ty } in members {
let field_c_type = get_c_repr_definition(dict, ty, false).expect("");
c_type.push_str(&format!(" {} {};\n",
field_c_type,
symbol.replace("-", "_").replace(".","_dot_")
));
}
c_type.push_str("}");
Some(c_type)
}
TypeTerm::Enum { enum_repr, variants } => {
let mut c_type = format!("
struct {{
enum {{
");
for (i, EnumVariant{ symbol, ty }) in variants.iter().enumerate() {
c_type.push_str(&format!(
" {} = {}", symbol.replace("-", "_").replace(".","_dot_").to_uppercase(), i
));
if i+1 < variants.len() {
c_type.push_str(",\n");
}
}
c_type.push_str("
} tag;
union {
");
for EnumVariant{ symbol, ty } in variants {
let variant_c_type = get_c_repr_definition(dict, ty, false).expect("cant get C-Repr type for variant");
c_type.push_str(&format!(
" {} {};\n", variant_c_type, symbol.replace("-", "_").replace(".","_dot_")
));
}
c_type.push_str("
};
}");
Some(c_type)
}
TypeTerm::Ladder(rungs) => {
if let Some(t) = rungs.last() {
get_c_repr_definition(dict, t.clone(), false)
} else {
None
}
}
_ => { None }
}
}
pub fn get_c_repr_type(dict: &mut impl TypeDict, t: &laddertypes::TypeTerm)-> String {
let t = t.clone().strip();
match t.desugar(dict) {
laddertypes::DesugaredTypeTerm::Char(c) => {
match c {
'.' => format!("_dot_"),
'-' => format!("_minus_"),
_ =>
format!("{}", (c as u64))
}
},
laddertypes::DesugaredTypeTerm::Num(n) => {
format!("{}", n)
}
laddertypes::DesugaredTypeTerm::TypeID(ty_id) => {
if let Some(name) = dict.get_typename(&ty_id) {
name
.replace("-", "_")
.replace(".", "")
} else {
format!("")
}
}
laddertypes::DesugaredTypeTerm::Ladder(rs) |
laddertypes::DesugaredTypeTerm::App(rs) => {
let mut s = String::new();
s.push('_');
for r in rs {
let r = r.sugar(dict);
s.push_str(&get_c_repr_type(dict, &r));
s.push('_');
}
s
}
}
}
pub fn get_c_repr_arg_type(dict: &mut impl TypeDict, t: &laddertypes::TypeTerm)-> String {
let t = t.clone().strip().get_floor_type().1;
dict.add_varname("TerminatorValue".into());
match &t {
TypeTerm::Seq { seq_repr, items } => {
if let Some(seq_repr) = seq_repr.as_ref() {
if let Ok(ψ) = laddertypes::constraint_system::subtype_unify(
seq_repr,
&dict.parse_desugared("<ValueTerminated TerminatorValue>").expect("").sugar(dict)
) {
return get_c_repr_type(dict, &items[0].clone().strip().get_floor_type().1);
}
else if let Ok(ψ) = laddertypes::constraint_system::subtype_unify(
seq_repr,
&dict.parse_desugared("MsbCont").expect("").sugar(dict)
) {
return get_c_repr_type(dict, &items[0].clone().strip().get_floor_type().1);
}
}
}
_ => {}
}
get_c_repr_type(dict, &t)
}
pub fn encode_morph_type_to_symbol(dict: &mut impl TypeDict, t: &MorphismType) -> String {
format!(
"morph__{}___TO__{}",
get_c_repr_type(dict, &t.strip_halo().src_type),
get_c_repr_type(dict, &t.strip_halo().dst_type)
)
}
pub fn encode_type_to_value(dict: &mut impl TypeDict, t: &laddertypes::TypeTerm) -> String {
let t = t.clone().desugar(dict);
dict.unparse(&t)
}

View file

@ -3,88 +3,44 @@
mod morphism;
mod parser;
mod c_gen;
mod struct_layout;
use {
ariadne::{Color, Label, Report, ReportKind, Source},
chumsky::prelude::*,
laddertypes::{
parser::ParseLadderType, BimapTypeDict, MorphismType
},
std::sync::{Arc, RwLock},
tiny_ansi::TinyAnsi,
crate::{
morphism::LdmcPrimMorph,
morphism::LdmcMorphism,
parser::morphism_base_parser,
}, ariadne::{Color, Label, Report, ReportKind, Source}, clap::Parser, laddertypes::{
morphism::MorphismType, BimapTypeDict, Morphism
}, parser::morphism_type_parser, std::{io::Write, path::PathBuf, sync::{Arc, RwLock}}, tiny_ansi::TinyAnsi, walkdir::WalkDir
}
};
#[derive(Parser, Debug)]
#[command(version, about, long_about = None)]
struct Args {
#[arg(short='b', long)]
morphism_base: Vec<PathBuf>,
#[arg(short='m', long="morph")]
morphisms: Vec<String>,
#[arg(short='o', long)]
output: Option<PathBuf>
}
fn main() {
let args = Args::parse();
let mut type_dict = Arc::new(RwLock::new(BimapTypeDict::new()));
let mut morphism_base = laddertypes::morphism_base::MorphismBase::<LdmcPrimMorph>::new();
let mut morphism_base = laddertypes::MorphismBase::<LdmcMorphism>::new(vec![
//type_dict.parse("Seq~MsbCont").expect(""),
//type_dict.parse("Seq~<ValueTerminated '\\0'>").expect(""),
type_dict.parse("Seq~<LengthPrefix native.UInt64>").expect("")
]);
// 1. load morphism base
let mut mb_paths = args.morphism_base;
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");
// 1.1. pfade ermitteln
let env_var = "MORPHISM_BASE";
let suffix = "morphism-base";
match std::env::var(env_var) {
Ok(path_str) => {
let path = std::path::Path::new(&path_str);
if path.is_dir() {
for entry in WalkDir::new(path)
.into_iter()
.filter_map(Result::ok)
.filter(|e|
e.path().is_file() &&
e.path().extension().map_or(false, |ext| ext == suffix)
)
{
mb_paths.push(entry.path().into());
}
} else {
eprintln!("morphism-base path is not a directory: {:?}", path);
}
}
Err(e) => {
eprintln!("failed to read environment variable {}: {}", env_var, e);
}
}
// 1.2. read files
let mut include_blocks = Vec::new();
let mut include_dependencies = std::collections::HashMap::new();
for mb_path in mb_paths {
let src = std::fs::read_to_string(mb_path.clone()).expect("failed to read morphism base");
use chumsky::Parser;
for mb_path in args {
let src = std::fs::read_to_string(mb_path.clone()).expect("read");
let result = morphism_base_parser(type_dict.clone()).parse(src.clone());
match result {
Ok((includes, morphisms)) => {
eprintln!("[{}] parse ok.", mb_path.to_str().unwrap().bright_yellow());
let include_idx = include_blocks.len();
let mut includes_prefixed = format!("/* from `{}` */", mb_path.display());
includes_prefixed.push_str(&includes);
include_blocks.push(includes_prefixed);
eprintln!("[{}] parse ok.", mb_path.bright_yellow());
println!("{}", includes);
for m in morphisms {
include_dependencies.insert( m.get_type(), include_idx );
morphism_base.add_morphism(m);
morphism_base.add_morphism(LdmcMorphism::Primitive(m));
}
}
Err(errs) => {
@ -104,21 +60,22 @@ fn main() {
}
}
// 2. Generate Morphisms
let mut instances = Vec::new();
for morph_decl in args.morphisms.iter() {
use chumsky::Parser;
if let Ok((name, src_type, dst_type)) = morphism_type_parser(type_dict.clone()).parse(morph_decl.as_str()) {
let ty = MorphismType{ src_type, dst_type };
instances.push( (name, morphism_base.get_morphism_instance( &ty ).expect("failed to find morphism")) );
let src_type = type_dict.parse( src_type_arg.as_str() ).expect("");
let dst_type = type_dict.parse( dst_type_arg.as_str() ).expect("");
let path = morphism_base.find_morphism_path(MorphismType {
src_type: src_type.clone(),
dst_type: dst_type.clone(),
});
match path {
Some(path) => {
c_gen::generate_main(&mut type_dict, path, src_type, dst_type);
}
None => {
eprintln!("Error: could not find morphism path");
std::process::exit(-1);
}
}
let c_source = crate::c_gen::gen_lib::generate_lib(&mut type_dict, include_blocks, include_dependencies, instances).expect("failed to generate library");
if let Some(out_path) = args.output {
let mut file = std::fs::File::create(out_path).expect("failed to open output file");
file.write_all(c_source.as_bytes()).expect("failed to write output file");
} else {
println!("{}", c_source);
}
}

View file

@ -1,16 +1,76 @@
use laddertypes::morphism::{Morphism, MorphismType};
use laddertypes::morphism::Morphism;
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct LdmcPrimMorph {
#[derive(Clone, Debug)]
pub struct LdmcPrimCMorphism {
pub symbol: String,
pub type_args: Vec<(laddertypes::TypeID, String)>,
pub ty: MorphismType,
pub src_type: laddertypes::TypeTerm,
pub dst_type: laddertypes::TypeTerm,
pub c_source: String
}
impl Morphism for LdmcPrimMorph {
fn get_type(&self) -> MorphismType {
self.ty.clone()
#[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
}
}
}

View file

@ -1,7 +1,11 @@
use {
crate::morphism::LdmcPrimMorph, chumsky::{
chumsky::{
prelude::*, text::*
}, laddertypes::{TypeTerm, morphism::MorphismType, parser::*, BimapTypeDict, TypeDict}, std::sync::{Arc, RwLock}
},
std::sync::{Arc, RwLock},
laddertypes::{TypeDict, BimapTypeDict, parser::*},
crate::morphism::LdmcPrimCMorphism
};
/* morphism-base text format:
@ -14,12 +18,12 @@ use {
*/
pub fn morphism_base_parser(
type_dict: Arc<RwLock< BimapTypeDict >>
) -> impl Parser<char, (String, Vec<LdmcPrimMorph>), Error = Simple<char>> {
) -> impl Parser<char, (String, Vec<LdmcPrimCMorphism>), Error = Simple<char>> {
just("```")
.then(take_until(just("```")))
.map(
move |(_a, (b, _c))| {
move |(a, (b, c))| {
b.iter().collect()
}
)
@ -62,13 +66,11 @@ pub fn morphism_base_parser(
let src_type = type_dict.parse(&src_type.iter().collect::<String>()).expect("couldnt parse src type");
let dst_type = type_dict.parse(&dst_type.iter().collect::<String>()).expect("couldnt parse dst type");
LdmcPrimMorph {
LdmcPrimCMorphism {
symbol,
type_args: ty_args,
ty: MorphismType{
src_type,
dst_type
},
src_type,
dst_type,
c_source
}
})
@ -76,25 +78,3 @@ pub fn morphism_base_parser(
)
}
pub fn morphism_type_parser(
mut type_dict: Arc<RwLock< BimapTypeDict >>
) -> impl Parser<char, (String, TypeTerm, TypeTerm), Error = Simple<char>> {
ident()
.padded()
.then(just(":").ignored())
.then(
take_until(just("-->").ignored())
)
.then(take_until(end()))
.map({
let type_dict = type_dict.clone();
move |((name, src_type), dst_type)| {
(
name.0,
type_dict.clone().parse(&src_type.0.iter().collect::<String>()).expect("parse type"),
type_dict.clone().parse(&dst_type.0.iter().collect::<String>()).expect("parse type")
)
}
})
}

View file

@ -1,43 +0,0 @@
use std::collections::HashMap;
pub fn example_substitution() {
let mut γ = HashMap::new();
γ.insert(
type_dict.get_typeid_creat(&"Byte"),
type_dict.parse("<Seq~<StaticLength 8> Bit>").expect("parse")
.apply_subst(&γ)
.clone()
);
γ.insert(
type_dict.get_typeid_creat(&"x86.UInt8"),
type_dict.parse("_2^8 ~ <PosInt 2 LittleEndian> ~ <Seq~<StaticLength 8> <Digit 2> ~ Bit>").expect("parse")
.apply_subst(&γ)
.clone()
);
γ.insert(
type_dict.get_typeid_creat(&"x86.UInt16"),
type_dict.parse("_2^16 ~ <PosInt 256 LittleEndian> ~ <Seq~<StaticLength 2> <Digit 256> ~ x86.UInt8 >").expect("parse")
.apply_subst(&γ)
.clone()
);
γ.insert(
type_dict.get_typeid_creat(&"x86.UInt32"),
type_dict.parse("_2^32 ~ <PosInt 256 LittleEndian> ~ <Seq~<StaticLength 4> <Digit 256> ~ x86.UInt8 >").expect("parse")
.apply_subst(&γ).clone()
);
γ.insert(
type_dict.get_typeid_creat(&"x86.UInt64"),
type_dict.parse("_2^64 ~ <PosInt 256 LittleEndian> ~ <Seq~<StaticLength 8> <Digit 256> ~ x86.UInt8 >").expect("parse")
.apply_subst(&γ).clone()
);
γ.insert(
type_dict.get_typeid_creat(&"x86.Float32"),
type_dict.parse(" ~ IEEE-754.Float32 ~ <Seq~<StaticLength 4> Byte>").expect("parse")
.apply_subst(&γ).clone()
);
γ.insert(
type_dict.get_typeid_creat(&"x86.Float64"),
type_dict.parse(" ~ IEEE-754.Float64 ~ <Seq~<StaticLength 4> Byte>").expect("parse")
.apply_subst(&γ).clone()
);
}

View file

@ -1,244 +0,0 @@
use laddertypes::{parser::*, StructMember, TypeTerm, TypeDict, DesugaredTypeTerm};
#[derive(Clone, Copy, Debug)]
pub enum ObjectSize {
Static(u64),
Dynamic(/* function to get size at runtime */),
Unknown
}
impl std::ops::Add for ObjectSize {
type Output = Self;
fn add(self, rhs: Self) -> Self {
match (self, rhs) {
(ObjectSize::Unknown, _) |
(_, ObjectSize::Unknown)
=> ObjectSize::Unknown,
(ObjectSize::Dynamic(), _) |
(_, ObjectSize::Dynamic())
=> ObjectSize::Dynamic(),
(ObjectSize::Static(s1), ObjectSize::Static(s2)) => ObjectSize::Static(s1 + s2),
}
}
}
impl std::ops::Mul for ObjectSize {
type Output = Self;
fn mul(self, rhs: Self) -> Self {
match (self, rhs) {
(ObjectSize::Unknown, _) |
(_, ObjectSize::Unknown)
=> ObjectSize::Unknown,
(ObjectSize::Dynamic(), _) |
(_, ObjectSize::Dynamic())
=> ObjectSize::Dynamic(),
(ObjectSize::Static(s1), ObjectSize::Static(s2)) => ObjectSize::Static(s1 * s2),
}
}
}
pub fn get_type_size( dict: &mut impl TypeDict, ty: TypeTerm ) -> ObjectSize {
match &ty {
TypeTerm::TypeID(tyid) => {
if tyid == &dict.get_typeid_creat("native.UInt8") { ObjectSize::Static(1) }
else if tyid == &dict.get_typeid_creat("native.UInt16") { ObjectSize::Static(2) }
else if tyid == &dict.get_typeid_creat("native.UInt32") { ObjectSize::Static(4) }
else if tyid == &dict.get_typeid_creat("native.UInt64") { ObjectSize::Static(8) }
else if tyid == &dict.get_typeid_creat("native.Address") { ObjectSize::Static(8) }
else if tyid == &dict.get_typeid_creat("native.Float32") { ObjectSize::Static(4) }
else if tyid == &dict.get_typeid_creat("native.Float64") { ObjectSize::Static(8) }
else {
ObjectSize::Unknown
}
},
TypeTerm::Ladder(rungs) => {
get_type_size(dict, rungs.last().unwrap().clone() )
}
TypeTerm::Struct { struct_repr, members } => {
let layout = StructLayout::parse_sugared(dict, ty).expect("invalid struct");
layout.get_size()
}
TypeTerm::Seq { seq_repr, items } => {
if let Some(seq_repr) = seq_repr {
dict.add_typename("Length".into());
dict.add_typename("LengthType".into());
dict.add_typename("TerminatorValue".into());
if let Ok(σ) = laddertypes::unify(
&seq_repr.clone(),
&dict.parse("<StaticLength Length>").expect("")
) {
if let Some(TypeTerm::Num(len)) = σ.get(&dict.get_typeid(&"Length".into()).expect("")) {
ObjectSize::Static(*len as u64) * get_type_size(dict, items.first().unwrap().clone())
} else {
ObjectSize::Unknown
}
}
else if let Ok(σ) = laddertypes::unify(
&seq_repr.clone(),
&dict.parse("<LengthPrefix LengthType>").expect("")
) {
ObjectSize::Dynamic()
}
else if let Ok(σ) = laddertypes::unify(
&seq_repr.clone(),
&dict.parse("<ValueTerminated TerminatorValue>").expect("")
) {
ObjectSize::Dynamic()
}
else {
ObjectSize::Unknown
}
} else {
ObjectSize::Unknown
}
}
_ => ObjectSize::Unknown
}
}
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum LayoutType {
Aligned,
Packed
}
impl LayoutType {
pub fn parse( dict: &mut impl TypeDict, ty: &DesugaredTypeTerm ) -> Option< LayoutType > {
if ty == &dict.parse_desugared("Aligned").expect("parse") {
Some(LayoutType::Aligned)
} else if ty == &dict.parse_desugared("Packed").expect("parse") {
Some(LayoutType::Packed)
} else {
None
}
}
pub fn unparse(&self, dict: &mut impl TypeDict) -> DesugaredTypeTerm {
match self {
LayoutType::Aligned => dict.parse_desugared("Aligned").unwrap(),
LayoutType::Packed => dict.parse_desugared("Packed").unwrap()
}
}
}
#[derive(Clone)]
pub struct StructLayout {
pub ty: laddertypes::DesugaredTypeTerm,
pub layout: LayoutType,
pub members: Vec< StructMember >,
offsets: std::collections::HashMap< String, u64 >,
size: ObjectSize
}
impl StructLayout {
pub fn get_type(&self) -> DesugaredTypeTerm {
self.ty.clone()
}
pub fn get_size(&self) -> ObjectSize {
self.size
}
pub fn get_offset(&self, name: &String) -> u64 {
*self.offsets.get(name).expect("")
}
pub fn init_offsets(&mut self, dict: &mut impl TypeDict) {
let mut offset = 0;
for StructMember{symbol: field_name, ty: field_type} in self.members.iter() {
//let field_c_type = crate::c_gen::get_c_repr_type(dict, field_type.clone(), true).expect("cant get c-repr for struct field");
match get_type_size( dict, field_type.clone() ) {
ObjectSize::Static(field_size) => {
match self.layout {
LayoutType::Aligned => {
// add padding to get natural alignment of current member
if offset % field_size > 0 {
offset = field_size * ((offset / field_size)+1);
}
}
LayoutType::Packed => {
// no padding
}
}
// take offset
self.offsets.insert(field_name.clone(), offset);
// advance by current size
offset += field_size;
}
ObjectSize::Dynamic() => {
eprintln!("dynamically sized Field in struct!");
self.offsets.insert(field_name.clone(), offset);
self.size = ObjectSize::Dynamic();
return;
}
ObjectSize::Unknown => {
eprintln!("Struct member `{}` has unknown size!", field_name);
self.offsets.insert(field_name.clone(), offset);
self.size = ObjectSize::Unknown;
return;
}
}
}
match self.size {
ObjectSize::Dynamic() => {
}
_ => {
self.size = ObjectSize::Static(offset);
}
}
}
pub fn parse(dict: &mut impl TypeDict, struct_type: &DesugaredTypeTerm) -> Option <Self> {
let st = struct_type.clone().strip().sugar(dict).normalize();
Self::parse_sugared(dict, st)
}
pub fn parse_sugared(dict: &mut impl TypeDict, st: TypeTerm) -> Option <Self> {
eprintln!("{}", st.pretty(dict, 0));
match st.clone() {
TypeTerm::Struct{ struct_repr, members } => {
let mut sl = StructLayout {
ty: st.desugar(dict),
layout: if let Some(sr) = struct_repr {
let sr = sr.desugar(dict);
LayoutType::parse( dict, &sr ).expect("invalid struct layout type")
} else {
eprintln!("choose default struct repr");
LayoutType::Aligned
},
members,
offsets: std::collections::HashMap::new(),
size: ObjectSize::Unknown
};
sl.init_offsets(dict);
Some(sl)
}
_ => {
eprintln!("not a struct");
None
}
}
}
}

View file

@ -8,12 +8,13 @@ run_test_case() {
-----------------------------------------------------------------------------
Running test case ${TEST_NAME}"
ldmc -m "main : ${SRC_TYPE} --> ${DST_TYPE}" -o target/src/${TEST_NAME}.c 2>|.tmp/ldmc_err \
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 -o target/${TEST_NAME} \
|| (echo "... error at compilation:"; return -2);
LEN="$(echo -n "${EXPECT}" | wc -c)"
RESULT="$(echo -n ${INPUT} | ./target/${TEST_NAME} 2>.tmp/target_err | head -c ${LEN})"

79
todo.md
View file

@ -1,79 +0,0 @@
* BUG: cant find morphism when path is trivial, or when
*some* members of a struct have trivial morphism
* BUG: -O3 kills some Morphisms
* BUG: erroneous code generation with Packed struct layout
* type Aliases / typedefs (load from input file)
-- platform specializations
-- shortcuts
* add highest-common-rung to generated morphism names
(to avoid potential ambiguities)
* add bounds to Morphism type:
- subtype bounds
- trait bounds
- value bounds
* data dependence:
- Each Struct creates a Context,
where a struct member becomes a type-variable,
available after it has been parsed from the input buffer.
- need some kind of partial Order over the member data fields,
to express parsing dependencies.
* bounds:
-> ~ UInt64 ---> ~ UInt8
- know that value fits into UInt8 ?
-> <Digit 128> ~ UInt64 --> <Digit 128> ~ UInt8
allows the following path:
<Digit 128> ~ UInt64
-> <Digit 128> ~ Char ~ Ascii ~ native.UInt8
-> <Digit 128> ~ native.UInt8
this will result in 'invalid digits' that are out of the ascii range
and is not wanted.
maybe the Morphism from digit to char should not exist for radix 128 (->value bounds on type vars)?
-fixed by adding explicit <Digit R>~UInt64 -morph-> <Digit R>~UInt8
* type descriptions: signed posints?
- Include minus sign '-' into the <Digit Radix> type ?
- or use [<Digit Radix> | Sign] ?
- or rather <SignedPosInt Radix Endianness> ~ {
sign: <Option Sign~Char>;
digits: <Seq <Digit 10>~Char>
};
- ?
* size estimation & memory allocation
- from each type definition, we need to derive
a form for an "allocation schema",
of which a value instance of that type defines
concrete length values for arrays and members
and thus the total required buffer size.
- in parallel to each morphism we need to know
the output-allocation schema in accordance to
a given allocation schema of the input data.
- Complex morphisms allocate a double buffering
with maximum required size at each point in the chain
- optional: allocation free morphisms for members in struct morphism ?
- In-Place Morphisms
* improve debugability of "no morphism path found"
- find a heuristic to guess "implementation overhead" of
a missing morphism by its type
- Step 1: Calculate Connected Components of src and dst Type ;
- Step 2: For each combination of a vertex-pair from src and dst Components,
calculate the implementation overhead heuristic ;
- Step 3: suggest to the developer the n smallest morphism types that would
bridge the two components
* allow to define (ladder-typed) functions, not just morphisms