Compare commits

...
Sign in to create a new pull request.

31 commits

Author SHA1 Message Date
cff14cf096
add MorphismInstance::Id 2025-05-29 13:01:23 +02:00
edd3441511
todo.md 2025-05-29 13:01:11 +02:00
dfa364bc0f
length prefix morphism: generic calls to functions with C macro 2025-05-16 13:55:36 +02:00
62f0ff9eac
add array morphisms : StaticLength <--> LengthPrefix 2025-05-16 13:53:19 +02:00
76c005ac8b
morph lenpfx to valterm: make item type generic 2025-05-16 13:51:45 +02:00
0eb8074644
digit morphism: also print Radix in warning 2025-05-16 02:34:18 +02:00
0c9a4ccc8b
example: use -o option in makefile 2025-05-16 02:33:17 +02:00
24f9a0f5b5
C code gen: rename include block to header block 2025-05-14 10:28:31 +02:00
7dd6352760
code generation: only use scanf/printf on newline('\n') terminated strings 2025-05-14 10:20:55 +02:00
692a34c257
main: when loading morphism base, remove . from path suffix variable 2025-05-14 10:19:48 +02:00
ea2504ff07
morphisms: fix bitshift in lenpfx to msb-cont 2025-05-14 10:18:42 +02:00
6f0a0f5927
when generating #defines for values of type variables, distinguish between variables of type 'Type' and others 2025-05-10 16:28:58 +02:00
4a705241fe
manage include blocks & only output required blocks once 2025-05-10 16:27:56 +02:00
efa584dfb5
update test.sh to new cli features 2025-05-10 16:25:36 +02:00
783c70b2e2
add output option in cli arguments 2025-05-10 15:40:49 +02:00
a58ac1a69c
in generation of main function, fix case that input/output buffer is a nullterm string 2025-05-10 15:16:51 +02:00
1116457bcc
add example C program which generates (de)marshaling with ldmc 2025-05-10 15:00:54 +02:00
27ea365755
improve integration
* add command line parsing
* read morphism base directory from environment
* generate C library of multiple morphisms
2025-05-09 03:33:51 +02:00
923fe987dc
fix typedefs 2025-05-07 16:29:45 +02:00
3ed7a19270
adapt changes in lib-laddertypes 2025-05-06 00:39:32 +02:00
6787e607a6
wip 2025-05-01 06:38:17 +02:00
ef819b4711
morphisms: remove 'return 0;' at end since it is now added by default 2025-04-03 16:37:46 +02:00
3f1397735c
improve code generation
- improve usage of FUSE
- implement seq-map for different representations
- fix C-types in morph-function arguments
- collect active types and put typedef into header
- add generate_main() to create stdio-morphism
2025-04-02 23:32:06 +02:00
67cec64dfc
fix codegen for seq-map 2025-04-02 15:01:45 +02:00
98592aa596
fuse results of sub- morphisms in complex morphisms 2025-04-02 14:37:31 +02:00
35b747ea15
fix local src/dst types in complex morphisms 2025-04-02 14:31:47 +02:00
39cba1ee57
improve symbol names in generated c code 2025-04-02 14:11:17 +02:00
583892f10d
wip struct morphisms 2025-04-01 18:23:18 +02:00
d98afc294d
exemplaric platform definitions 2025-03-31 10:29:57 +02:00
bce52e9fcf
replace native.Float/native.Double with native.Float32/native.Float64 2025-03-25 19:38:56 +01:00
21bb33193a
wip struct morphisms 2025-03-24 10:14:25 +01:00
34 changed files with 1596 additions and 783 deletions

View file

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

1
examples/01-uint-example/.gitignore vendored Normal file
View file

@ -0,0 +1 @@
build/

View file

@ -0,0 +1,14 @@
#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

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

View file

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

View file

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

View file

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

View file

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

View file

@ -2,27 +2,37 @@
#include <stdio.h> #include <stdio.h>
#include <stdint.h> #include <stdint.h>
/*
#define DEFINE_LENGTH_PREFIX_ARRAY(LEN_TYPE, ITEM_TYPE) \
typedef struct { \ typedef struct { \
LEN_TYPE len; \ LEN_TYPE len; \
ITEM_TYPE items[]; \ ITEM_TYPE items[]; \
} LengthPrefix_##LEN_TYPE##_Array_##ITEM_TYPE; \ } __Seq__LengthPrefix_##LEN_TYPE##___##ITEM_TYPE##_; \
\ */ \
static inline void length_prefix_##LEN_TYPE##_array_##ITEM_TYPE##_clear( \
LengthPrefix_##LEN_TYPE##_Array_##ITEM_TYPE *data) { \ #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) { \
data->len = 0; \ data->len = 0; \
} \ } \
\ \
static inline void length_prefix_##LEN_TYPE##_array_##ITEM_TYPE##_push( \ static inline void PRESCAN_LENGTH_PREFIX_CALL(LEN_TYPE, ITEM_TYPE, push) \
LengthPrefix_##LEN_TYPE##_Array_##ITEM_TYPE *data, \ (__Seq__LengthPrefix_##LEN_TYPE##___##ITEM_TYPE##_ *data, \
ITEM_TYPE value) { \ ITEM_TYPE value) { \
data->items[data->len++] = value; \ data->items[data->len++] = value; \
} \ } \
\ \
static inline int length_prefix_##LEN_TYPE##_array_##ITEM_TYPE##_reverse( \ static inline int PRESCAN_LENGTH_PREFIX_CALL(LEN_TYPE, ITEM_TYPE, reverse) \
LengthPrefix_##LEN_TYPE##_Array_##ITEM_TYPE const * restrict src, \ ( __Seq__LengthPrefix_##LEN_TYPE##___##ITEM_TYPE##_ const * restrict src, \
LengthPrefix_##LEN_TYPE##_Array_##ITEM_TYPE *restrict dst) { \ __Seq__LengthPrefix_##LEN_TYPE##___##ITEM_TYPE##_ *restrict dst) { \
for (LEN_TYPE i = 0; i < src->len; i++) { \ for (LEN_TYPE i = 0; i < src->len; i++) { \
dst->items[i] = src->items[src->len - 1 - i]; \ dst->items[i] = src->items[src->len - 1 - i]; \
} \ } \
@ -30,60 +40,11 @@
return 0; \ return 0; \
} \ } \
\ \
static inline void length_prefix_##LEN_TYPE##_array_##ITEM_TYPE##_dump( \ static inline void PRESCAN_LENGTH_PREFIX_CALL(LEN_TYPE, ITEM_TYPE, dump) \
LengthPrefix_##LEN_TYPE##_Array_##ITEM_TYPE const * data) { \ ( __Seq__LengthPrefix_##LEN_TYPE##___##ITEM_TYPE##_ const * data) { \
printf("Length: %llu\n", (unsigned long long) data->len); \ printf("Length: %llu\n", (unsigned long long) data->len); \
for (LEN_TYPE i = 0; i < data->len; i++) { \ for (LEN_TYPE i = 0; i < data->len; i++) { \
printf("%llu ", (unsigned long long) data->items[i]); \ printf("%llu ", (unsigned long long) data->items[i]); \
} \ } \
printf("\n"); \ 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,33 +2,21 @@
``` ```
morph_celsius_to_kelvin () morph_celsius_to_kelvin ()
Temperature ~ Celsius ~ ~ native.Float Temperature ~ Celsius ~ ~ native.Float32
--> Temperature ~ Kelvin ~ ~ native.Float --> Temperature ~ Kelvin ~ ~ native.Float32
``` ```*dst = *src + 273.15;```
*dst = *src + 273.15;
return 0;
```
morph_kelvin_to_celsius () morph_kelvin_to_celsius ()
Temperature ~ Kelvin ~ ~ native.Float Temperature ~ Kelvin ~ ~ native.Float32
--> Temperature ~ Celsius ~ ~ native.Float --> Temperature ~ Celsius ~ ~ native.Float32
``` ```*dst = *src - 273.15;```
*dst = *src - 273.15;
return 0;
```
morph_celsius_to_fahrenheit () morph_celsius_to_fahrenheit ()
Temperature ~ Celsius ~ ~ native.Float Temperature ~ Celsius ~ ~ native.Float32
--> Temperature ~ Fahrenheit ~ ~ native.Float --> Temperature ~ Fahrenheit ~ ~ native.Float32
``` ```*dst = (*src * 9.0 / 5.0) + 32.0;```
*dst = (*src * 9.0 / 5.0) + 32.0;
return 0;
```
morph_fahrenheit_to_celsius () morph_fahrenheit_to_celsius ()
Temperature ~ Fahrenheit ~ ~ native.Float Temperature ~ Fahrenheit ~ ~ native.Float32
--> Temperature ~ Celsius ~ ~ native.Float --> Temperature ~ Celsius ~ ~ native.Float32
``` ```*dst = (*src - 32.0) * 5.0 / 9.0;```
*dst = (*src - 32.0) * 5.0 / 9.0;
return 0;
```

View file

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

View file

@ -0,0 +1,17 @@
```
```
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,7 +28,6 @@ morph_string_as_utf8_to_ascii ()
} }
} }
*dst = 0; *dst = 0;
return 0;
``` ```
morph_string_as_ascii_to_utf32 () morph_string_as_ascii_to_utf32 ()
@ -39,7 +38,6 @@ morph_string_as_ascii_to_utf32 ()
``` ```
while( *src ) { *dst++ = *src++; } while( *src ) { *dst++ = *src++; }
*dst = 0; *dst = 0;
return 0;
``` ```
morph_string_as_utf8_to_utf32 () morph_string_as_utf8_to_utf32 ()
@ -89,6 +87,4 @@ morph_string_as_utf8_to_utf32 ()
*dst++ = val; *dst++ = val;
*dst++ = 0; *dst++ = 0;
return 0;
``` ```

View file

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

View file

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

100
platforms/json.lt Normal file
View file

@ -0,0 +1,100 @@
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
);
}
```

0
platforms/json5.lt Normal file
View file

3
platforms/protobuf.lt Normal file
View file

@ -0,0 +1,3 @@
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> ;

0
platforms/spapod.lt Normal file
View file

5
platforms/x86.lt Normal file
View file

@ -0,0 +1,5 @@
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>;

View file

@ -1,419 +0,0 @@
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, σ),
'}');
}
}
}
}

82
src/c_gen/gen_lib.rs Normal file
View file

@ -0,0 +1,82 @@
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)
}

7
src/c_gen/mod.rs Normal file
View file

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

76
src/c_gen/morph/mod.rs Normal file
View file

@ -0,0 +1,76 @@
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

@ -0,0 +1,375 @@
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!();
}
}
}
}

257
src/c_gen/types/mod.rs Normal file
View file

@ -0,0 +1,257 @@
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,44 +3,88 @@
mod morphism; mod morphism;
mod parser; mod parser;
mod c_gen; mod c_gen;
mod struct_layout;
use { use {
ariadne::{Color, Label, Report, ReportKind, Source},
chumsky::prelude::*,
laddertypes::{
parser::ParseLadderType, BimapTypeDict, MorphismType
},
std::sync::{Arc, RwLock},
tiny_ansi::TinyAnsi,
crate::{ crate::{
morphism::LdmcMorphism, morphism::LdmcPrimMorph,
parser::morphism_base_parser, 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() { fn main() {
let args = Args::parse();
let mut type_dict = Arc::new(RwLock::new(BimapTypeDict::new())); let mut type_dict = Arc::new(RwLock::new(BimapTypeDict::new()));
let mut morphism_base = laddertypes::MorphismBase::<LdmcMorphism>::new(vec![ let mut morphism_base = laddertypes::morphism_base::MorphismBase::<LdmcPrimMorph>::new();
//type_dict.parse("Seq~MsbCont").expect(""),
//type_dict.parse("Seq~<ValueTerminated '\\0'>").expect(""),
type_dict.parse("Seq~<LengthPrefix native.UInt64>").expect("")
]);
let mut args = std::env::args().skip(1); // 1. load morphism base
let src_type_arg = args.next().expect("src type expected"); let mut mb_paths = args.morphism_base;
let dst_type_arg = args.next().expect("dst type expected");
for mb_path in args { // 1.1. pfade ermitteln
let src = std::fs::read_to_string(mb_path.clone()).expect("read"); 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;
let result = morphism_base_parser(type_dict.clone()).parse(src.clone()); let result = morphism_base_parser(type_dict.clone()).parse(src.clone());
match result { match result {
Ok((includes, morphisms)) => { Ok((includes, morphisms)) => {
eprintln!("[{}] parse ok.", mb_path.bright_yellow()); eprintln!("[{}] parse ok.", mb_path.to_str().unwrap().bright_yellow());
println!("{}", includes);
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);
for m in morphisms { for m in morphisms {
morphism_base.add_morphism(LdmcMorphism::Primitive(m)); include_dependencies.insert( m.get_type(), include_idx );
morphism_base.add_morphism(m);
} }
} }
Err(errs) => { Err(errs) => {
@ -60,22 +104,21 @@ 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 c_source = crate::c_gen::gen_lib::generate_lib(&mut type_dict, include_blocks, include_dependencies, instances).expect("failed to generate library");
let dst_type = type_dict.parse( dst_type_arg.as_str() ).expect(""); if let Some(out_path) = args.output {
let mut file = std::fs::File::create(out_path).expect("failed to open output file");
let path = morphism_base.find_morphism_path(MorphismType { file.write_all(c_source.as_bytes()).expect("failed to write output file");
src_type: src_type.clone(), } else {
dst_type: dst_type.clone(), println!("{}", c_source);
});
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);
}
} }
} }

View file

@ -1,76 +1,16 @@
use laddertypes::morphism::Morphism; use laddertypes::morphism::{Morphism, MorphismType};
#[derive(Clone, Debug)] #[derive(Clone, Debug, PartialEq, Eq)]
pub struct LdmcPrimCMorphism { pub struct LdmcPrimMorph {
pub symbol: String, pub symbol: String,
pub type_args: Vec<(laddertypes::TypeID, String)>, pub type_args: Vec<(laddertypes::TypeID, String)>,
pub src_type: laddertypes::TypeTerm, pub ty: MorphismType,
pub dst_type: laddertypes::TypeTerm,
pub c_source: String pub c_source: String
} }
#[derive(Clone)] impl Morphism for LdmcPrimMorph {
pub enum LdmcMorphism { fn get_type(&self) -> MorphismType {
Primitive( LdmcPrimCMorphism ), self.ty.clone()
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,11 +1,7 @@
use { use {
chumsky::{ crate::morphism::LdmcPrimMorph, chumsky::{
prelude::*, text::* 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: /* morphism-base text format:
@ -18,12 +14,12 @@ use {
*/ */
pub fn morphism_base_parser( pub fn morphism_base_parser(
type_dict: Arc<RwLock< BimapTypeDict >> type_dict: Arc<RwLock< BimapTypeDict >>
) -> impl Parser<char, (String, Vec<LdmcPrimCMorphism>), Error = Simple<char>> { ) -> impl Parser<char, (String, Vec<LdmcPrimMorph>), Error = Simple<char>> {
just("```") just("```")
.then(take_until(just("```"))) .then(take_until(just("```")))
.map( .map(
move |(a, (b, c))| { move |(_a, (b, _c))| {
b.iter().collect() b.iter().collect()
} }
) )
@ -66,11 +62,13 @@ pub fn morphism_base_parser(
let src_type = type_dict.parse(&src_type.iter().collect::<String>()).expect("couldnt parse src type"); 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"); let dst_type = type_dict.parse(&dst_type.iter().collect::<String>()).expect("couldnt parse dst type");
LdmcPrimCMorphism { LdmcPrimMorph {
symbol, symbol,
type_args: ty_args, type_args: ty_args,
ty: MorphismType{
src_type, src_type,
dst_type, dst_type
},
c_source c_source
} }
}) })
@ -78,3 +76,25 @@ 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")
)
}
})
}

43
src/platform/x86.rs Normal file
View file

@ -0,0 +1,43 @@
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()
);
}

244
src/struct_layout.rs Normal file
View file

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

79
todo.md Normal file
View file

@ -0,0 +1,79 @@
* 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