diff --git a/Cargo.toml b/Cargo.toml index c4ca5d9..8eace12 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -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" diff --git a/examples/01-uint-example/.gitignore b/examples/01-uint-example/.gitignore deleted file mode 100644 index 567609b..0000000 --- a/examples/01-uint-example/.gitignore +++ /dev/null @@ -1 +0,0 @@ -build/ diff --git a/examples/01-uint-example/main.c b/examples/01-uint-example/main.c deleted file mode 100644 index 2db8422..0000000 --- a/examples/01-uint-example/main.c +++ /dev/null @@ -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); - } -} diff --git a/examples/01-uint-example/makefile b/examples/01-uint-example/makefile deleted file mode 100644 index 915101b..0000000 --- a/examples/01-uint-example/makefile +++ /dev/null @@ -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 diff --git a/morphisms/angle.morphism-base b/morphisms/angle.morphism-base index e678dde..71aba96 100644 --- a/morphisms/angle.morphism-base +++ b/morphisms/angle.morphism-base @@ -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; +``` diff --git a/morphisms/digit.morphism-base b/morphisms/digit.morphism-base index 75ab631..a92fe61 100644 --- a/morphisms/digit.morphism-base +++ b/morphisms/digit.morphism-base @@ -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; ``` diff --git a/morphisms/length_prefix.morphism-base b/morphisms/length_prefix.morphism-base index 70cd3b7..6718c16 100644 --- a/morphisms/length_prefix.morphism-base +++ b/morphisms/length_prefix.morphism-base @@ -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; ``` diff --git a/morphisms/posint.morphism-base b/morphisms/posint.morphism-base index 9036520..194399b 100644 --- a/morphisms/posint.morphism-base +++ b/morphisms/posint.morphism-base @@ -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 ); ``` diff --git a/morphisms/real.morphism-base b/morphisms/real.morphism-base index 5b5b2f7..3302f80 100644 --- a/morphisms/real.morphism-base +++ b/morphisms/real.morphism-base @@ -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; ``` diff --git a/morphisms/runtime/include/array/length-prefix.h b/morphisms/runtime/include/array/length-prefix.h index e61f8ac..35a4aec 100644 --- a/morphisms/runtime/include/array/length-prefix.h +++ b/morphisms/runtime/include/array/length-prefix.h @@ -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) diff --git a/morphisms/temperature.morphism-base b/morphisms/temperature.morphism-base index 329a6b0..7831292 100644 --- a/morphisms/temperature.morphism-base +++ b/morphisms/temperature.morphism-base @@ -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; +``` diff --git a/morphisms/timepoint.morphism-base b/morphisms/timepoint.morphism-base index 505ed37..bb66aec 100644 --- a/morphisms/timepoint.morphism-base +++ b/morphisms/timepoint.morphism-base @@ -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; ``` diff --git a/morphisms/uint.morphism-base b/morphisms/uint.morphism-base deleted file mode 100644 index 89f8f79..0000000 --- a/morphisms/uint.morphism-base +++ /dev/null @@ -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;``` diff --git a/morphisms/unicode.morphism-base b/morphisms/unicode.morphism-base index 659357b..c2854e5 100644 --- a/morphisms/unicode.morphism-base +++ b/morphisms/unicode.morphism-base @@ -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; ``` diff --git a/morphisms/value_delim.morphism-base b/morphisms/value_delim.morphism-base index d4ab039..a370682 100644 --- a/morphisms/value_delim.morphism-base +++ b/morphisms/value_delim.morphism-base @@ -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; ``` diff --git a/morphisms/zigzag.morphism-base b/morphisms/zigzag.morphism-base index 4196e72..5a293e2 100644 --- a/morphisms/zigzag.morphism-base +++ b/morphisms/zigzag.morphism-base @@ -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 () diff --git a/platforms/json.lt b/platforms/json.lt deleted file mode 100644 index 8e69138..0000000 --- a/platforms/json.lt +++ /dev/null @@ -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 - ); - } -``` diff --git a/platforms/json5.lt b/platforms/json5.lt deleted file mode 100644 index e69de29..0000000 diff --git a/platforms/protobuf.lt b/platforms/protobuf.lt deleted file mode 100644 index ce273f6..0000000 --- a/platforms/protobuf.lt +++ /dev/null @@ -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> ; diff --git a/platforms/spapod.lt b/platforms/spapod.lt deleted file mode 100644 index e69de29..0000000 diff --git a/platforms/x86.lt b/platforms/x86.lt deleted file mode 100644 index 0348efc..0000000 --- a/platforms/x86.lt +++ /dev/null @@ -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>; diff --git a/src/c_gen.rs b/src/c_gen.rs new file mode 100644 index 0000000..ac68a93 --- /dev/null +++ b/src/c_gen.rs @@ -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, σ), + '}'); + } + } + } +} diff --git a/src/c_gen/gen_lib.rs b/src/c_gen/gen_lib.rs deleted file mode 100644 index 13ffa3e..0000000 --- a/src/c_gen/gen_lib.rs +++ /dev/null @@ -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) -} diff --git a/src/c_gen/mod.rs b/src/c_gen/mod.rs deleted file mode 100644 index cf994c5..0000000 --- a/src/c_gen/mod.rs +++ /dev/null @@ -1,7 +0,0 @@ -pub mod types; -pub mod morph; -pub mod gen_lib; - -pub use { - morph::target_morph::LdmcCTargetMorph -}; diff --git a/src/c_gen/morph/mod.rs b/src/c_gen/morph/mod.rs deleted file mode 100644 index 49510e5..0000000 --- a/src/c_gen/morph/mod.rs +++ /dev/null @@ -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) - } -} diff --git a/src/c_gen/morph/target_morph.rs b/src/c_gen/morph/target_morph.rs deleted file mode 100644 index cea7ed4..0000000 --- a/src/c_gen/morph/target_morph.rs +++ /dev/null @@ -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!(); - } - } - } -} diff --git a/src/c_gen/types/mod.rs b/src/c_gen/types/mod.rs deleted file mode 100644 index 29cb4ec..0000000 --- a/src/c_gen/types/mod.rs +++ /dev/null @@ -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) -} diff --git a/src/main.rs b/src/main.rs index 675c12d..13b8629 100644 --- a/src/main.rs +++ b/src/main.rs @@ -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); - } } diff --git a/src/morphism.rs b/src/morphism.rs index 28ea01e..a1f2aab 100644 --- a/src/morphism.rs +++ b/src/morphism.rs @@ -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 + } } } diff --git a/src/parser.rs b/src/parser.rs index 24ca0a9..f45fddf 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -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") - ) - } - }) -} diff --git a/src/platform/x86.rs b/src/platform/x86.rs deleted file mode 100644 index aaae9c2..0000000 --- a/src/platform/x86.rs +++ /dev/null @@ -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() - ); -} diff --git a/src/struct_layout.rs b/src/struct_layout.rs deleted file mode 100644 index b8816e9..0000000 --- a/src/struct_layout.rs +++ /dev/null @@ -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 - } - } - } -} diff --git a/test/test.sh b/test/test.sh index f33ab02..0e3fc9b 100755 --- a/test/test.sh +++ b/test/test.sh @@ -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})" diff --git a/todo.md b/todo.md deleted file mode 100644 index 39dd24f..0000000 --- a/todo.md +++ /dev/null @@ -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