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 " )
2025-03-20 16:28:16 +01:00
| | t = = & dict . parse ( " native.UInt8 " ) . expect ( " parse " )
2025-03-15 19:37:03 +01:00
| | t = = & dict . parse ( " <StaticLength 8 Bit> " ) . expect ( " parse " )
{
Some ( " uint8_t " . into ( ) )
2025-03-20 16:28:16 +01:00
} else if t = = & dict . parse ( " native.UInt16 " ) . expect ( " parse " ) {
2025-03-15 19:37:03 +01:00
Some ( " uint16_t " . into ( ) )
2025-03-20 16:28:16 +01:00
} else if t = = & dict . parse ( " native.UInt32 " ) . expect ( " parse " ) {
2025-03-15 19:37:03 +01:00
Some ( " uint32_t " . into ( ) )
2025-03-20 16:28:16 +01:00
} else if t = = & dict . parse ( " native.UInt64 " ) . expect ( " parse " ) {
2025-03-15 19:37:03 +01:00
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 ( ) )
{
2025-03-20 16:16:41 +01:00
let length_c_type : String = get_c_repr_type ( dict , args [ 1 ] . clone ( ) , false ) ? ;
2025-03-15 19:37:03 +01:00
let item_c_type : String = get_c_repr_type ( dict , args [ 2 ] . clone ( ) , false ) ? ;
2025-03-20 16:16:41 +01:00
match length_c_type . as_str ( ) {
" uint8_t " |
" uint16_t " |
" uint32_t " |
" uint64_t " = > { }
_ = > {
eprintln! ( " invalid length type! " ) ;
return None ;
}
}
2025-03-15 19:37:03 +01:00
match item_c_type . as_str ( ) {
2025-03-20 16:16:41 +01:00
" uint8_t " |
" uint16_t " |
" uint32_t " |
" uint64_t " = > { }
_ = > {
eprintln! ( " invalid item type! " ) ;
return None ;
}
2025-03-15 19:37:03 +01:00
}
2025-03-20 16:16:41 +01:00
Some ( format! ( " LengthPrefix_ {} _Array_ {} " , length_c_type , item_c_type ) )
2025-03-15 19:37:03 +01:00
}
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-20 16:16:41 +01:00
//fprintf(stderr, "read %d bytes\n", l);
2025-03-15 19:37:03 +01:00
" #,
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 ,
2025-03-20 16:28:16 +01:00
& type_dict . parse ( " <Seq~<ValueTerminated 0> native.UInt8> " ) . unwrap ( )
2025-03-15 19:37:03 +01:00
) {
println! ( r #"
printf ( " %s \n " , { } ) ; " #, out_buf);
} else if let Ok ( ( halo , σ ) ) = laddertypes ::subtype_unify (
& dst_type ,
2025-03-20 16:28:16 +01:00
& type_dict . parse ( " <Seq~<LengthPrefix native.UInt64> native.UInt8> " ) . unwrap ( )
2025-03-15 19:37:03 +01:00
) {
println! ( r #"
/* write output
* /
{ {
2025-03-20 16:16:41 +01:00
LengthPrefix_uint64_t_Array_uint8_t * buf = ( void * ) { } ;
2025-03-15 19:37:03 +01:00
write ( 1 , { } , sizeof ( uint64_t ) + buf ->len ) ;
} } " #, out_buf, out_buf);
} else {
println! ( r #"
2025-03-20 16:16:41 +01:00
write ( 1 , { } , sizeof ( { } ) ) ; " #,
2025-03-15 19:37:03 +01:00
out_buf ,
2025-03-20 16:16:41 +01:00
out_buf
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 } = > {
2025-03-20 16:16:41 +01:00
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
) ;
2025-03-15 19:37:03 +01:00
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 , σ ) ,
'}' ) ;
}
}
}
}