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
This commit is contained in:
Michael Sippel 2025-04-02 23:32:06 +02:00
parent 67cec64dfc
commit 3f1397735c
Signed by: senvas
GPG key ID: F96CF119C34B64A6
3 changed files with 210 additions and 145 deletions

View file

@ -1,24 +1,31 @@
use {
crate::{c_gen_types::{encode_morph_type_to_symbol, encode_type_to_symbol, encode_type_to_value, get_c_repr_type}, morphism::LdmcPrimMorph, struct_layout::{get_type_size, LayoutType, ObjectSize, StructLayout}}, chumsky::{chain::Chain, primitive::Container}, laddertypes::{morphism::{Morphism, MorphismInstance}, morphism_sugared::{MorphismInstance2, SugaredMorphism, SugaredMorphismType}, parser::*, substitution_sugared::SugaredSubstitution, unparser::*, Substitution, SugaredEnumVariant, SugaredStructMember, SugaredTypeTerm, TypeDict, TypeTerm}, std::collections::HashMap
crate::{c_gen_types::{encode_morph_type_to_symbol, encode_type_to_arg_ty, encode_type_to_symbol, encode_type_to_value, get_c_repr_type}, morphism::LdmcPrimMorph, struct_layout::{get_type_size, LayoutType, ObjectSize, StructLayout}}, chumsky::{chain::Chain, primitive::Container}, laddertypes::{morphism::{Morphism, MorphismInstance}, morphism_sugared::{MorphismInstance2, SugaredMorphism, SugaredMorphismType}, parser::*, substitution_sugared::SugaredSubstitution, unparser::*, Substitution, SugaredEnumVariant, SugaredStructMember, SugaredTypeTerm, TypeDict, TypeTerm}, std::collections::HashMap
};
impl LdmcPrimMorph {
pub fn instantiated_symbol_name(&self, dict: &mut impl TypeDict, σ: &impl SugaredSubstitution) -> 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));
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 = 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 type parameter {} ({})", k, var_id);
}
}
} 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
}
@ -35,8 +42,9 @@ impl LdmcPrimMorph {
pub fn generate_instantiation(&self, dict: &mut impl TypeDict, σ: &impl SugaredSubstitution) -> Option<String> {
let mut s = String::new();
let symbol = self.instantiated_symbol_name(dict, σ);
let src_c_symbol = encode_type_to_symbol(dict, &self.ty.strip_halo().src_type);
let dst_c_symbol = encode_type_to_symbol(dict, &self.ty.strip_halo().dst_type);
let src_c_symbol = encode_type_to_arg_ty(dict, &self.ty.strip_halo().src_type.clone().apply_subst(σ).get_floor_type().1);
let dst_c_symbol = encode_type_to_arg_ty(dict, &self.ty.strip_halo().dst_type.clone().apply_subst(σ).get_floor_type().1);
s.push_str(&format!(r#"
int {} ( {} const * restrict src, {} * restrict dst ) {{
@ -67,13 +75,25 @@ impl LdmcCTargetMorph {
LdmcCTargetMorph {
includes: vec![
"#include <stdint.h>".into(),
"#define FUSE(x) { int result = x; if(result) return result; }".into()
"#define FUSE(morph, src, dst) { int result = morph(src,dst); if(result) return result; }".into(),
],
active_instantiations: Vec::new(),
active_types: Vec::new(),
}
}
pub fn add_type(&mut self, ty: SugaredTypeTerm) {
if ! self.active_types.contains(&ty) {
match &ty {
SugaredTypeTerm::Seq { seq_repr, items } =>{
self.add_type(items.first().unwrap().clone());
}
_=>{}
}
self.active_types.push(ty.clone());
}
}
pub fn add_instantiation(
&mut self,
dict: &mut impl TypeDict,
@ -85,12 +105,8 @@ impl LdmcCTargetMorph {
}
let ty = new_inst.get_type().strip_halo();
if ! self.active_types.contains(&ty.src_type) {
self.active_types.push(ty.src_type);
}
if ! self.active_types.contains(&ty.dst_type) {
self.active_types.push(ty.dst_type);
}
self.add_type(ty.src_type.get_floor_type().1);
self.add_type(ty.dst_type.get_floor_type().1);
Ok(new_inst)
}
@ -106,7 +122,7 @@ impl LdmcCTargetMorph {
source.push_str(&format!("
typedef {} {};
",
get_c_repr_type(dict, ty.clone(), false).expect("cant get c-repr type"),
get_c_repr_type(dict, ty.clone(), false).expect(&format!("cant get c-repr type for type '{}'", ty.pretty(dict,0))),
encode_type_to_symbol(dict, &ty)));
}
@ -122,68 +138,72 @@ impl LdmcCTargetMorph {
dict: &mut impl laddertypes::TypeDict,
morph_inst: MorphismInstance2<LdmcPrimMorph>,
) -> Result<LdmcPrimMorph, ()> {
eprintln!("bake morphism: {}
------> {}", morph_inst.get_haloless_type().src_type.pretty(dict,0), morph_inst.get_haloless_type().dst_type.pretty(dict, 0));
match &morph_inst {
MorphismInstance2::Primitive { ψ, σ, morph } => {
let mut c_source = String::new();
for (ty_id, kind) in morph.type_args.iter() {
if let Some(val) = σ.get(ty_id) {
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)
};
if let laddertypes::TypeID::Var(var_id) = ty_id {
//if morph_inst.get_type().strip_halo().src_type.contains_var(*var_id) ||
//morph_inst.get_type().strip_halo().dst_type.contains_var(*var_id) {
if let Some(val) = σ.get(ty_id) {
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)
};
c_source.push_str(&format!(" #define {} {}\n", dict.get_typename(&ty_id).unwrap(), type_var_value));
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() {
c_source.push_str(&format!("\n #undef {}", dict.get_typename(&ty_id).unwrap()));
if let laddertypes::TypeID::Var(var_id) = ty_id {
//if morph_inst.get_type().strip_halo().src_type.contains_var(*var_id) ||
//morph_inst.get_type().strip_halo().dst_type.contains_var(*var_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_haloless_type(),
ty: morph_inst.get_type().apply_subst(σ).strip_halo(),
c_source
})
},
MorphismInstance2::Chain { path } => {
let ty = morph_inst.get_type().strip_halo();
let symbol = encode_morph_type_to_symbol(dict, &morph_inst.get_haloless_type());
let symbol = encode_morph_type_to_symbol(dict, &ty);
let mut c_source = String::new();
if path.len() > 1 {
c_source.push_str(r#"
uint8_t bufA[128];
uint8_t bufB[128];
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_c_type = encode_type_to_symbol(dict, &inst.get_type().strip_halo().src_type);
let dst_c_type = encode_type_to_symbol(dict, &inst.get_type().strip_halo().dst_type);
let src_buf = if i == 0 { "src" } else if i%2 == 0 { "(void*)bufA" } else { "(void*)bufB" };
let dst_buf = if i+1 == path.len() { "dst" } else if i%2 == 0 { "(void*)bufB" } else { "(void*)bufA" };
c_source.push_str(&format!(r#"
{{
{} const * restrict src = {};
{} * restrict dst = {};
FUSE( {} ( src, dst ) );
}}"#,
src_c_type, src_buf,
dst_c_type, dst_buf,
morph_symbol
FUSE( {}, {}, {} );"#,
morph_symbol, src_buf, dst_buf,
));
} else {
c_source.push_str(&format!("/* ERROR: missing morphism */"));
eprintln!("failed to add instantiation of item morphism");
}
}
@ -196,28 +216,65 @@ impl LdmcCTargetMorph {
MorphismInstance2::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::unification_sugared::unify(
&dict.parse("<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 {
SugaredTypeTerm::Num(l) => {
let ty = morph_inst.get_type().strip_halo();
let symbol = encode_morph_type_to_symbol(dict, &morph_inst.get_type());
let item_morph_symbol = item_morph_inst.instantiated_symbol_name(dict, &HashMap::new());
self.add_type( morph_inst.get_type().strip_halo().src_type );
self.add_type( morph_inst.get_type().strip_halo().dst_type );
let c_source = format!(r#"
for( size_t i = 0; i < {}; ++i ) {{
FUSE( {}, &src[i], &dst[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::unification_sugared::unify(
&dict.parse("<LengthPrefix LengthType>").expect("parse type template").sugar(dict),
seq_repr.as_ref()
) {
let length_type = γ.get(&dict.get_typeid(&"LengthType".into()).expect("")).expect("cant get LengthType");
// todo: assert that length type is native.UIntX
//let length_type = γ.get(&dict.get_typeid(&"LengthType".into()).expect("")).expect("cant get LengthType");
let ty = morph_inst.get_type().strip_halo();
let symbol = encode_morph_type_to_symbol(dict, &morph_inst.get_haloless_type());
let symbol = encode_morph_type_to_symbol(dict, &morph_inst.get_type());
let item_morph_symbol = item_morph_inst.instantiated_symbol_name(dict, &HashMap::new());
let length_c_type = get_c_repr_type(dict, length_type.clone(), true).expect("cant c-repr type for array length");
let src_item_c_type = get_c_repr_type(dict, item_morph.get_haloless_type().src_type, true).expect("cant c-repr type for src item");
let dst_item_c_type = get_c_repr_type(dict, item_morph.get_haloless_type().dst_type, true).expect("cant c-repr type for dst item");
self.add_type( morph_inst.get_type().strip_halo().src_type );
self.add_type( morph_inst.get_type().strip_halo().dst_type );
// todo: self.add_active_length_prefix_map()
let map_fn = format!("length_prefix_{}_array_map_{}_to_{}",
length_c_type, src_item_c_type, dst_item_c_type
);
let c_source = format!(r#"
return {} ( {}, src, dst );"#,
map_fn,
for( size_t i = 0; i < src->len; ++i ) {{
FUSE( {}, &src->items[i], &dst->items[i] );
}}
dst->len = src->len;
"#,
item_morph_symbol,
);
@ -225,7 +282,38 @@ impl LdmcCTargetMorph {
symbol, type_args: Vec::new(), ty,
c_source
})
} else {
}
else if let Ok(γ) = laddertypes::unification_sugared::unify(
&dict.parse("<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 ty = morph_inst.get_type().strip_halo();
let symbol = encode_morph_type_to_symbol(dict, &morph_inst.get_haloless_type());
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(())
}
@ -249,12 +337,13 @@ impl LdmcCTargetMorph {
let name = name.replace("-", "_").replace(".","_dot_");
c_source.push_str(
&format!("
FUSE( {} ( &src->{}, &dst->{} ) );
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(());
}
@ -271,3 +360,43 @@ impl LdmcCTargetMorph {
}
}
}
pub fn generate_main(dict: &mut impl TypeDict, morph: MorphismInstance2<LdmcPrimMorph>) -> Result<String, ()> {
let mut target = LdmcCTargetMorph::new();
let ty = morph.get_type();
if let Ok(inst) = target.add_instantiation(dict, morph) {
let mut c_source = target.into_c_source(dict);
c_source.push_str(&format!(r#"
#include <unistd.h>
int main() {{
uint8_t bufIn[4096];
uint8_t bufOut[4096];"#));
let (src_top, src_floor) = ty.src_type.get_floor_type();
if src_floor == dict.parse("<Seq~<ValueTerminated 0> native.UInt8>").expect("").sugar(dict) {
c_source.push_str("scanf(\"%s\", bufIn);");
} else {
c_source.push_str("read(0, bufIn, sizeof(bufIn));");
}
c_source.push_str(&format!(r#"FUSE( {}, (void const*)bufIn, (void*)bufOut );"#, inst.instantiated_symbol_name(dict, &HashMap::new())));
if let Ok(ψ) = laddertypes::unification_sugared::subtype_unify(
&ty.src_type,
&dict.parse("<Seq~<ValueTerminated 0> native.UInt8>").expect("").sugar(dict)
) {
c_source.push_str("printf(\"%s\\n\", bufOut);");
} else {
c_source.push_str("write(1, bufOut, sizeof(bufOut));");
}
c_source.push_str("
return 0;
}");
Ok(c_source)
} else {
Err(())
}
}

View file

@ -227,6 +227,22 @@ pub fn encode_type_to_symbol(dict: &mut impl TypeDict, t: &laddertypes::SugaredT
}
}
pub fn encode_type_to_arg_ty(dict: &mut impl TypeDict, t: &laddertypes::SugaredTypeTerm) -> String {
match t.get_floor_type().1 {
SugaredTypeTerm::Seq { seq_repr, items } => {
if let Some(seq_repr) = seq_repr {
if seq_repr.as_ref() == &dict.parse("<ValueTerminated 0>").expect("").sugar(dict) {
return encode_type_to_symbol(dict, items.first().unwrap());
}
}
}
_=>{}
}
encode_type_to_symbol(dict, t)
}
pub fn encode_morph_type_to_symbol(dict: &mut impl TypeDict, t: &SugaredMorphismType) -> String {
format!(
"morph_{}__to_{}",

View file

@ -29,8 +29,8 @@ fn main() {
let result = morphism_base_parser(type_dict.clone()).parse(src.clone());
match result {
Ok((includes, morphisms)) => {
println!("{}",includes);
eprintln!("[{}] parse ok.", mb_path.bright_yellow());
println!("{}", includes);
for m in morphisms {
morphism_base.add_morphism(m);
}
@ -95,87 +95,7 @@ fn main() {
let src_type = type_dict.parse( src_type_arg.as_str() ).expect("");
let dst_type = type_dict.parse( dst_type_arg.as_str() ).expect("");
/*
let struct_type1 = type_dict.parse("
<Struct ~ Aligned
<online-since TimePoint ~ <TimeSince UnixEpoch> ~ Duration ~ Seconds ~ ~ <QuantizedLinear 0 1 1000> ~ ~ native.UInt64 >
<capacity Energy ~ Wh ~ ~ <QuantizedLinear 0 1 1000> ~ ~ native.UInt64 >
<battery-charge Energy ~ Wh ~ ~ <QuantizedLinear 0 1 1000> ~ ~ native.UInt64 >
<min-sampling-period Duration ~ Seconds ~ ~ <QuantizedLinear 0 1 1000> ~ ~ native.UInt32 >
<cur-sampling-period Duration ~ Seconds ~ ~ <QuantizedLinear 0 1 1000> ~ ~ native.UInt32 >
<max-chunk-size ~ native.UInt32 >
<cur-chunk-size ~ native.UInt32 >
<n-chunks-capacity ~ native.UInt32 >
<n-full-data-chunks ~ native.UInt32 >
<n-empty-data-chunks ~ native.UInt32 >
>
").expect("parse struct type");
let struct_type2 = type_dict.parse("
<Struct ~ Packed
<battery-charge Energy ~ Wh ~ ~ native.Double >
<battery-capacity Energy ~ Wh ~ ~ native.Double >
<min-sampling-period Duration ~ Seconds ~ ~ native.Double >
<cur-sampling-period Duration ~ Seconds ~ ~ native.Double >
<max-chunk-size ~ native.UInt32 >
<cur-chunk-size ~ native.UInt32 >
<n-chunks-capacity ~ native.UInt32 >
<n-full-data-chunks ~ native.UInt32 >
<n-empty-data-chunks ~ native.UInt32 >
<online-since TimePoint ~ <TimeSince UnixEpoch> ~ Duration ~ Seconds ~ ~ native.Double >
>
").expect("parse struct type");
*/
/*
let struct_type1 = type_dict.parse("
RGB~<Struct
<red ~ <QuantizedLinear 0 1 255> ~ ~ native.UInt8>
<green ~ <QuantizedLinear 0 1 255> ~ ~ native.UInt8>
<blue ~ <QuantizedLinear 0 1 255> ~ ~ native.UInt8>
>
").expect("parse");
let struct_type2 = type_dict.parse("
RGB~<Struct
<red ~ native.Float64>
<green ~ native.Float64>
<blue ~ native.Float64>
>
").expect("parse");
*/
let ty = SugaredMorphismType{ src_type: src_type.sugar(&mut type_dict), dst_type: dst_type.sugar(&mut type_dict) };
let mut target = LdmcCTargetMorph::new();
target.add_instantiation(&mut type_dict, morphism_base.get_morphism_instance( &ty ).expect("cant get instance"));
println!("{}", target.into_c_source(&mut type_dict));
/*
return;
let m = LdmcMorphism::new_struct_map(&mut type_dict, &morphism_base, struct_type1, struct_type2);
println!("{}",
m.into_prim_c_morphism(&mut type_dict, "morph_my_struct".into(), &HashMap::new())
.c_source
);
return;
let path = laddertypes::morphism_path::ShortestPathProblem::new(
&morphism_base,
MorphismType {
src_type: src_type.clone(),
dst_type: dst_type.clone(),
}).solve();
match path {
Some(path) => {
c_gen::generate_main(&mut type_dict, path, src_type, dst_type);
}
None => {
eprintln!("Error: could not find morphism path");
std::process::exit(-1);
}
}
*/
let m = morphism_base.get_morphism_instance( &ty ).expect("failed to find morphism");
println!("{}", crate::c_gen::generate_main(&mut type_dict, m).expect("failed to generate main function"));
}