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()) } 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_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() {{ 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> 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, "sizeof(bufA)" ); } 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, σ), '}'); } } } }