2025-03-15 19:37:03 +01:00
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 ( " x86.UInt8 " ) . expect ( " parse " )
| | t = = & dict . parse ( " <StaticLength 8 Bit> " ) . expect ( " parse " )
{
Some ( " uint8_t " . into ( ) )
} else if t = = & dict . parse ( " x86.UInt16 " ) . expect ( " parse " ) {
Some ( " uint16_t " . into ( ) )
} else if t = = & dict . parse ( " x86.UInt32 " ) . expect ( " parse " ) {
Some ( " uint32_t " . into ( ) )
} else if t = = & dict . parse ( " x86.UInt64 " ) . expect ( " parse " ) {
Some ( " uint64_t " . into ( ) )
2025-03-18 14:07:14 +01:00
} else if t = = & dict . parse ( " native.Float " ) . expect ( " parse " ) {
Some ( " float " . into ( ) )
} else if t = = & dict . parse ( " native.Double " ) . expect ( " parse " ) {
Some ( " double " . into ( ) )
2025-03-15 19:37:03 +01:00
} else {
match t {
laddertypes ::TypeTerm ::App ( args ) = > {
if args [ 0 ] = = laddertypes ::TypeTerm ::TypeID ( dict . get_typeid ( & " LengthPrefix " . into ( ) ) . unwrap ( ) )
{
let _length_type = args [ 1 ] . clone ( ) ;
let item_c_type : String = get_c_repr_type ( dict , args [ 2 ] . clone ( ) , false ) ? ;
match item_c_type . as_str ( ) {
" uint8_t " = > Some ( format! ( " struct LengthPrefixUInt8Array " ) ) ,
" uint16_t " = > Some ( format! ( " struct LengthPrefixUInt16Array " ) ) ,
" uint32_t " = > Some ( format! ( " struct LengthPrefixUInt32Array " ) ) ,
" uint64_t " = > Some ( format! ( " struct LengthPrefixUInt64Array " ) ) ,
_ = > None
}
}
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 ( ) { {
2025-03-18 14:09:01 +01:00
uint8_t bufA [ 128 ] ;
uint8_t bufB [ 128 ] ;
memset ( bufA , 0 , sizeof ( bufA ) ) ;
memset ( bufB , 0 , sizeof ( bufB ) ) ;
2025-03-15 19:37:03 +01:00
char in_str [ ] = " read :: {} \n " ;
char out_str [ ] = " write:: {} \n " ;
write ( 2 , in_str , strlen ( in_str ) ) ;
write ( 2 , out_str , strlen ( out_str ) ) ;
2025-03-18 14:09:01 +01:00
int l = read ( 0 , bufA , sizeof ( bufA ) ) ;
2025-03-15 19:37:03 +01:00
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> x86.UInt8> " ) . unwrap ( )
) {
println! ( r #"
printf ( " %s \n " , { } ) ; " #, out_buf);
} else if let Ok ( ( halo , σ ) ) = laddertypes ::subtype_unify (
& dst_type ,
& type_dict . parse ( " <Seq~<LengthPrefix x86.UInt64> x86.UInt8> " ) . unwrap ( )
) {
println! ( r #"
/* write output
* /
{ {
struct LengthPrefixUInt8Array * buf = ( void * ) { } ;
write ( 1 , { } , sizeof ( uint64_t ) + buf ->len ) ;
} } " #, out_buf, out_buf);
} else {
println! ( r #"
write ( 1 , { } , { } ) ; " #,
out_buf ,
2025-03-18 14:09:01 +01:00
" sizeof(bufA) "
2025-03-15 19:37:03 +01:00
) ;
}
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 ) {
s . push_str ( & format! ( " #define {} {} \n " , dict . get_typename ( & ty_id ) . unwrap ( ) , encode_type_to_value ( dict , val ) ) ) ;
}
}
s . push_str ( & self . c_source ) ;
for ( ty_id , kind ) in self . type_args . iter ( ) {
s . push_str ( & format! ( " \n #undef {} " , dict . get_typename ( & ty_id ) . unwrap ( ) ) ) ;
}
s . push_str ( & format! ( r #"
} }
" #));
Some ( s )
}
}
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_c_type = get_c_repr_type ( dict , self . get_type ( ) . src_type . clone ( ) . apply_substitution ( & | k | σ . get ( k ) . cloned ( ) ) . clone ( ) , true ) . expect ( " cant get c-repr type for src type " ) ;
let dst_c_type = get_c_repr_type ( dict , self . get_type ( ) . dst_type . clone ( ) . apply_substitution ( & | k | σ . get ( k ) . cloned ( ) ) . clone ( ) , true ) . expect ( " cant get c-repr type for dst type " ) ;
let map_fn = match ( src_c_type . as_str ( ) , dst_c_type . as_str ( ) ) {
( " struct LengthPrefixUInt64Array " , " struct LengthPrefixUInt64Array " ) = > " length_prefix_array_map_64_to_64 " ,
( " struct LengthPrefixUInt8Array " , " struct LengthPrefixUInt64Array " ) = > " length_prefix_array_map_8_to_64 " ,
( " struct LengthPrefixUInt64Array " , " struct LengthPrefixUInt8Array " ) = > " length_prefix_array_map_64_to_8 " ,
( " struct LengthPrefixUInt8Array " , " struct LengthPrefixUInt8Array " ) = > " length_prefix_array_map_8_to_8 " ,
_ = > {
" {{ ERROR: no map function implemented }} "
}
} ;
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 , σ ) ,
'}' ) ;
}
}
}
}