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 }; 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)); } } 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::SugaredTypeTerm> ) -> String { format!("int {} ({} const * restrict src, {} * restrict dst);", self.instantiated_symbol_name(dict, σ), get_c_repr_type(dict, self.ty.src_type.clone(), true).expect("cant get c-repr type for src type"), get_c_repr_type(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 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); 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) } } pub struct LdmcCTargetMorph { includes: Vec< String >, active_types: Vec< SugaredTypeTerm >, active_instantiations: Vec< LdmcPrimMorph >, } impl LdmcCTargetMorph { pub fn new() -> Self { LdmcCTargetMorph { includes: vec![ "#include <stdint.h>".into(), "#define FUSE(x) { int result = x; if(result) return result; }".into() ], active_instantiations: Vec::new(), active_types: Vec::new(), } } pub fn add_instantiation( &mut self, dict: &mut impl TypeDict, morph: MorphismInstance2<LdmcPrimMorph>, ) -> Result<LdmcPrimMorph, ()> { let new_inst = self.bake_morphism(dict, morph)?; if ! self.active_instantiations.contains(&new_inst) { self.active_instantiations.push(new_inst.clone()); } 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); } Ok(new_inst) } pub fn into_c_source(self, dict: &mut impl TypeDict) -> String { let mut source = String::new(); for inc in self.includes { source.push_str(&inc); source.push('\n'); } for ty in self.active_types { source.push_str(&format!(" typedef {} {}; ", get_c_repr_type(dict, ty.clone(), false).expect("cant get c-repr type"), encode_type_to_symbol(dict, &ty))); } for m in self.active_instantiations { 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: MorphismInstance2<LdmcPrimMorph>, ) -> Result<LdmcPrimMorph, ()> { 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) }; 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())); } Ok(LdmcPrimMorph{ symbol: morph.instantiated_symbol_name(dict, σ), type_args: Vec::new(), ty: morph_inst.get_haloless_type(), 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 mut c_source = String::new(); if path.len() > 1 { c_source.push_str(r#" uint8_t bufA[128]; uint8_t bufB[128]; "#); } 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 )); } else { eprintln!("failed to add instantiation of item morphism"); } } Ok(LdmcPrimMorph { symbol, type_args: Vec::new(), ty, c_source }) } 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("LengthType".into()); 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"); 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 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"); // 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, item_morph_symbol, ); 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(()) } }, MorphismInstance2::MapStruct { ψ, struct_repr, member_morph } => { let ty = morph_inst.get_type().strip_halo(); let symbol =encode_morph_type_to_symbol(dict, &morph_inst.get_haloless_type()); 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 { eprintln!("failed to create morphism instantiation for struct member"); return Err(()); } } Ok(LdmcPrimMorph{ symbol, type_args: Vec::new(), ty, c_source }) } MorphismInstance2::MapEnum { ψ, enum_repr, variant_morph } => { todo!(); } } } }