diff --git a/src/c_gen.rs b/src/c_gen.rs index 7f5c7ea..c64a0f6 100644 --- a/src/c_gen.rs +++ b/src/c_gen.rs @@ -1,158 +1,286 @@ use { - crate::{morphism::{LdmcMorphism, LdmcPrimCMorphism}, struct_layout::{get_type_size, ObjectSize, StructLayout}}, - laddertypes::{morphism::{Morphism, MorphismInstance}, parser::*, unparser::*, TypeDict, TypeTerm}, + 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, SugaredMorphismType}, parser::*, substitution_sugared::SugaredSubstitution, unparser::*, Substitution, SugaredEnumVariant, SugaredStructMember, SugaredTypeTerm, TypeDict, TypeTerm}, std::collections::HashMap }; -/* -*/ -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("native.UInt8").expect("parse") - || t == &dict.parse("<StaticLength 8 Bit>").expect("parse") - { - Some("uint8_t".into()) - } else if t == &dict.parse("native.UInt16").expect("parse") { - Some("uint16_t".into()) - } else if t == &dict.parse("native.UInt32").expect("parse") { - Some("uint32_t".into()) - } else if t == &dict.parse("native.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()) + + + + +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 { - match t { - laddertypes::TypeTerm::App(args) => { - if args[0] == laddertypes::TypeTerm::TypeID(dict.get_typeid(&"LengthPrefix".into()).unwrap()) - { - let length_c_type : String = get_c_repr_type(dict, args[1].clone(), false)?; - let item_c_type : String = get_c_repr_type(dict, args[2].clone(), false)?; - - match length_c_type.as_str() { - "uint8_t" | - "uint16_t" | - "uint32_t" | - "uint64_t" => {} - _ => { - eprintln!("invalid length type!"); - return None; - } - } - match item_c_type.as_str() { - "uint8_t" | - "uint16_t" | - "uint32_t" | - "uint64_t" => {} - _ => { - eprintln!("invalid item type!"); - return None; - } - } - - Some(format!("LengthPrefix_{}_Array_{}", length_c_type, item_c_type)) - } - 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 { - - if let Some(layout) = StructLayout::parse(dict, t.clone()) { - let mut c_type = String::from("struct {\n"); - - for (field_name, field_type) in layout.members.iter() { - let field_c_type = get_c_repr_type(dict, field_type.clone(), false).expect(""); - c_type.push_str(&format!(" {} {};\n", - field_c_type, - field_name - )); - } - - c_type.push_str("}"); - Some(c_type) - } else { - None - } - } - } - - _ => None + 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); } } } - None => None + 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 src_type = self.ty.src_type.clone().apply_subst(σ).clone(); + let dst_type = self.ty.dst_type.clone().apply_subst(σ).clone(); + + let symbol = encode_morph_type_to_symbol(dict, &self.ty); + let src_c_symbol = encode_type_to_symbol(dict, &self.ty.src_type); + let dst_c_symbol = encode_type_to_symbol(dict, &self.ty.dst_type); + + let src_c_type = get_c_repr_type(dict, self.ty.src_type.clone(), true).expect("cant get c-repr type for src type"); + let dst_c_type = get_c_repr_type(dict, self.ty.dst_type.clone(), true).expect("cant get c-repr type for src type"); + + s.push_str(&format!(r#" +int {} ( {} const * restrict src, {} * restrict dst ) {{ +"#, + self.instantiated_symbol_name(dict, σ), + get_c_repr_type(dict, src_type, true).expect("cant get c-repr-type"), + get_c_repr_type(dict, dst_type, true).expect("cant get c-repr-type"), + )); + s.push_str(&self.c_source); + s.push_str(&format!(r#" + return 0; +}} +"#)); + Some(s) } } -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) + + + +pub struct LdmcCTargetMorph { + includes: Vec< String >, + active_instantiations: Vec< LdmcPrimMorph >, +} + +impl LdmcCTargetMorph { + pub fn new() -> Self { + LdmcCTargetMorph { + includes: Vec::new(), + active_instantiations: Vec::new() } - laddertypes::TypeTerm::TypeID(ty_id) => { - if let Some(name) = dict.get_typename(ty_id) { - format!("{}", name.replace(".", "_dot_")) - } else { - format!("") - } + } + + 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()); } - 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)); + 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); + } + + 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) { + eprintln!("val = {}", val.pretty(dict, 0)); + 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_type(), + c_source + }) + }, + MorphismInstance2::Chain { path } => { + let ty = morph_inst.get_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]; + "#); + } + + 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 = get_c_repr_type(dict, ty.src_type.clone(), true).expect("cant get c-repr type for src type"); + let dst_c_type = get_c_repr_type(dict, ty.dst_type.clone(), true).expect("cant get c-repr type for 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 = {}; + {} ( 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 } => { + let i = 0; // <--todo + 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(); + let symbol = encode_morph_type_to_symbol(dict, &ty); + let item_morph_symbol = encode_morph_type_to_symbol(dict, &item_morph.get_type()); + + 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_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_type().dst_type, true).expect("cant c-repr type for dst item"); + let src_c_type = get_c_repr_type(dict, ty.src_type.clone(), true).expect("cant get c-repr type for src type"); + let dst_c_type = get_c_repr_type(dict, ty.dst_type.clone(), 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 + ); + + let src_buf = if i%2 == 0 { "bufA" } else { "bufB" }; + let dst_buf = if i%2 == 0 { "bufB" } else { "bufA" }; + let c_source = format!(r#" + {{ + {} const * restrict src = (void*) {}; + {} * restrict dst = (void*) {}; + {} ( {}, src, dst ); + }}"#, + src_c_type, src_buf, + dst_c_type, dst_buf, + 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(()) + } + }, + MorphismInstance2::MapStruct { ψ, struct_repr, member_morph } => { + let ty = morph_inst.get_type(); + let symbol =encode_morph_type_to_symbol(dict, &ty); + + let mut c_source = String::new(); + + for (name, morph) in member_morph.iter() { + if let Ok(inst) = self.add_instantiation(dict, morph.clone()) { + c_source.push_str( + &format!(" + {} ( &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!(); } - 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) { +/* +pub fn generate_main( + type_dict: &mut impl TypeDict, + morph: MorphismInstance2<LdmcPrimMorph>, + src_type: TypeTerm, dst_type: TypeTerm +) { let mut i = 0; + + /* todo: collect include files from morphism base */ println!(r#" #include <stdio.h> @@ -271,238 +399,4 @@ 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) { - eprintln!("val = {}", dict.unparse(&val)); - - 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) - }; - - s.push_str(&format!(" #define {} {}\n", dict.get_typename(&ty_id).unwrap(), type_var_value)); - } - } - - 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 into_prim_c_morphism(self, dict: &mut impl laddertypes::TypeDict, symbol: String, σ: &std::collections::HashMap<laddertypes::TypeID, laddertypes::TypeTerm>) -> LdmcPrimCMorphism { - - 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(); - - let src_c_type = get_c_repr_type(dict, src_type.clone(), true).expect("cant get c-repr type for src type"); - let dst_c_type = get_c_repr_type(dict, dst_type.clone(), true).expect("cant get c-repr type for src type"); - - let c_source = - format!(" -typedef {} {}_src_t; - -typedef {} {}_dst_t; - -int {} ( {}_src_t const * restrict src, {}_dst_t * restrict dst ) -{{ -{} - return 0; -}} - ", - src_c_type, symbol, - dst_c_type, symbol, - symbol, symbol, symbol, - self.generate_call(dict, σ, 0) - ); - - LdmcPrimCMorphism { - symbol, - type_args: Vec::new(), - src_type, - dst_type, - c_source - } - } - - pub fn generate_call(&self, dict: &mut impl TypeDict, σ: &std::collections::HashMap<laddertypes::TypeID, laddertypes::TypeTerm>, i: u64) -> String { - 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" }; - - format!(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_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 - ); - - let src_buf = if i%2 == 0 { "bufA" } else { "bufB" }; - let dst_buf = if i%2 == 0 { "bufB" } else { "bufA" }; - format!(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" }; - format!(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, σ) - ) - }, - - LdmcMorphism::StructMap { src_struct, dst_struct, member_morphisms } => { - let mut output = String::new(); - for member_morph in member_morphisms.iter() { - if let Some(m) = member_morph.item_morph.as_ref() { - //let src_c_type = get_c_repr_type(dict, m.src_type.clone(), false).expect("cant get c-repr type for field member"); - //let dst_c_type = get_c_repr_type(dict, m.dst_type.clone(), false).expect("cant get c-repr type for field member"); - - output.push_str(&format!(" {} ( &src->{}, &dst->{} );\n", - m.instantiated_symbol_name(dict, σ), - member_morph.field_name, - member_morph.field_name - )); - } else { - let mut field_type = None; - for (field_name, ft) in src_struct.members.iter() { - if field_name == &member_morph.field_name { - field_type = Some(ft); - } - } - - let field_type = field_type.expect("cant get field member type"); - //if let Some(field_c_type) = get_c_repr_type(dict, field_type.clone(), false).expect("cat get c-repr type for field member"); - - match get_type_size(dict, field_type.clone()) { - ObjectSize::Static(size) => { - output.push_str(&format!(" memcpy( &dst->{}, &src->{}, sizeof(dst->{}) );\n", - member_morph.field_name, member_morph.field_name, member_morph.field_name - )); - } - _ => { - eprintln!("cant assign field of unknown size!"); - } - } - } - } - output - } - } - } -} +*/ diff --git a/src/c_gen_types.rs b/src/c_gen_types.rs new file mode 100644 index 0000000..9c0020d --- /dev/null +++ b/src/c_gen_types.rs @@ -0,0 +1,240 @@ +use { + crate::{morphism::LdmcPrimMorph, struct_layout::{get_type_size, LayoutType, ObjectSize, StructLayout}}, chumsky::chain::Chain, laddertypes::{morphism::{Morphism, MorphismInstance}, morphism_sugared::{MorphismInstance2, SugaredMorphismType}, parser::*, substitution_sugared::SugaredSubstitution, unparser::*, Substitution, SugaredEnumVariant, SugaredStructMember, SugaredTypeTerm, TypeDict, TypeTerm} +}; + +/* +*/ +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: SugaredTypeTerm, skip_pointer: bool) -> Option<String> { + eprintln!("get c repr of {}", t.pretty(dict,0)); + + match t.get_floor_type().1.strip() { + SugaredTypeTerm::TypeID(tyid) => { + if tyid == dict.get_typeid_creat("native.UInt8") { + Some("uint8_t".into()) + } else if tyid == dict.get_typeid_creat("native.UInt16") { + Some("uint16_t".into()) + } else if tyid == dict.get_typeid_creat("native.UInt32") { + Some("uint32_t".into()) + } else if tyid == dict.get_typeid_creat("native.UInt64") { + Some("uint64_t".into()) + } else if tyid == dict.get_typeid_creat("native.Address") { + Some("void*".into()) + } else if tyid == dict.get_typeid_creat("native.Float32") { + Some("float".into()) + } else if tyid == dict.get_typeid_creat("native.Float64") { + Some("double".into()) + } else { + None + } + } + + SugaredTypeTerm::Seq{ seq_repr, items } => { + if let Some(sr_sugar) = seq_repr { + let sr = sr_sugar.desugar(dict); + + let item_type = items.first().expect("no item type specified!").clone(); + let item_c_type : String = get_c_repr_type(dict, item_type, false).expect("cant get item type representation"); + + dict.add_varname("Length".into()); // Kind: Num + dict.add_varname("LengthType".into()); // Kind: Type + dict.add_varname("TermValue".into()); // Kind: Value of Type ItemType + + if let Ok(σ) = laddertypes::unify( + &sr, + &dict.parse("<StaticLength Length>").expect("parse") + ) { + let length = match + σ.get( + &dict.get_typeid(&"Length".into()).expect("no Length ID") + ).expect("no length specified!") + { + TypeTerm::Num(l) => l, + _ => { + eprintln!("invalid Length!"); + return None; + } + }; + Some(format!("{}[{}]", item_c_type, length)) + } + else if let Ok(σ) = laddertypes::unify( + &sr, + &dict.parse("<LengthPrefix LengthType>").expect("parse") + ) { + let length_type = σ.get( + &dict.get_typeid(&"LengthType".into()).expect("no LengthType ID") + ).expect("no length type specified") + .clone() + .sugar(dict); + let length_c_type : String = get_c_repr_type(dict, length_type, false).expect("cant get length type representation"); + + match length_c_type.as_str() { + "uint8_t" | + "uint16_t" | + "uint32_t" | + "uint64_t" => {} + s => { + eprintln!("invalid length type '{}' !", s); + return None; + } + } + match item_c_type.as_str() { + "uint8_t" | + "uint16_t" | + "uint32_t" | + "uint64_t" | + "void*" => {} + s => { + eprintln!("invalid item type '{}'!", s); + return None; + } + } + + Some(format!("LengthPrefix_{}_Array_{}", length_c_type, item_c_type)) + } + else if let Ok(σ) = laddertypes::unify( + &sr, + &dict.parse("<ValueTerminated TermValue>").expect("") + ) { + if skip_pointer { + Some(item_c_type) + } else { + Some(format!("{} *", item_c_type)) + } + } + else { + eprintln!("can't get C-repr for sequence type `{}`!", dict.unparse(&sr)); + None + } + } else { + eprintln!("no sequence-representation type specified!"); + None + } + } + + SugaredTypeTerm::Struct{ struct_repr, members } => { + let c_struct_attribute = + if let Some(sr) = struct_repr { + let sr = sr.desugar(dict); + match LayoutType::parse(dict, &sr).expect("layout type") { + LayoutType::Aligned => "", + LayoutType::Packed => "__attribute((packed))__" + } + } else {""}; + + let mut c_type = format!("struct {} {{\n", c_struct_attribute); + + for SugaredStructMember{ symbol, ty } in members { + let field_c_type = get_c_repr_type(dict, ty, false).expect(""); + c_type.push_str(&format!(" {} {};\n", + field_c_type, + symbol + )); + } + + c_type.push_str("}"); + Some(c_type) + } + + SugaredTypeTerm::Enum { enum_repr, variants } => { + let mut c_type = format!(" +struct {{ + enum {{ +"); + + for (i, SugaredEnumVariant{ symbol, ty }) in variants.iter().enumerate() { + c_type.push_str(&format!( + " {} = {}", symbol.to_uppercase(), i + )); + + if i+1 < variants.len() { + c_type.push_str(",\n"); + } + } + + c_type.push_str(" + } tag; + + union { +"); + + for SugaredEnumVariant{ symbol, ty } in variants { + let variant_c_type = get_c_repr_type(dict, ty, false).expect("cant get C-Repr type for variant"); + c_type.push_str(&format!( + " {} {};\n", variant_c_type, symbol + )); + } + + c_type.push_str(" + }; +}"); + + Some(c_type) + } + + SugaredTypeTerm::Ladder(rungs) => { + if let Some(t) = rungs.last() { + get_c_repr_type(dict, t.clone(), false) + } else { + None + } + } + + _ => { None } + } +} + +pub fn encode_type_to_symbol(dict: &mut impl TypeDict, t: &laddertypes::SugaredTypeTerm)-> String { + let t = t.clone().desugar(dict); + 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('_'); + + let r = r.sugar(dict); + s.push_str(&encode_type_to_symbol(dict, &r)); + } + s + } + } +} + +pub fn encode_morph_type_to_symbol(dict: &mut impl TypeDict, t: &SugaredMorphismType) -> String { + format!( + "morph_{}__to_{}", + encode_type_to_symbol(dict, &t.src_type), + encode_type_to_symbol(dict, &t.dst_type) + ) +} + +pub fn encode_type_to_value(dict: &mut impl TypeDict, t: &laddertypes::SugaredTypeTerm) -> String { + let t = t.clone().desugar(dict); + dict.unparse(&t) +} diff --git a/src/main.rs b/src/main.rs index 8769384..7ee2bad 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,26 +3,22 @@ mod morphism; mod parser; mod c_gen; +mod c_gen_types; mod struct_layout; use { crate::{ - morphism::LdmcMorphism, + morphism::LdmcPrimMorph, parser::morphism_base_parser, - }, ariadne::{Color, Label, Report, ReportKind, Source}, chumsky::prelude::*, laddertypes::{ - parser::ParseLadderType, unparser::*, BimapTypeDict, MorphismType, TypeDict + }, ariadne::{Color, Label, Report, ReportKind, Source}, c_gen::LdmcCTargetMorph, chumsky::prelude::*, laddertypes::{ + morphism_path_sugared::SugaredShortestPathProblem, morphism_sugared::{MorphismInstance2, SugaredMorphism, SugaredMorphismType}, parser::ParseLadderType, unparser::*, BimapTypeDict, MorphismType, SugaredTypeTerm, TypeDict }, std::{collections::HashMap, sync::{Arc, RwLock}}, tiny_ansi::TinyAnsi }; fn main() { let mut type_dict = Arc::new(RwLock::new(BimapTypeDict::new())); - let mut morphism_base = laddertypes::morphism_base::MorphismBase::<LdmcMorphism>::new(vec![ - //type_dict.parse("Seq~MsbCont").expect(""), - //type_dict.parse("Seq~<ValueTerminated '\\0'>").expect(""), - type_dict.parse("Seq~<LengthPrefix native.UInt64>").expect(""), - type_dict.parse("Struct").expect("") - ]); + let mut morphism_base = laddertypes::morphism_base_sugared::SugaredMorphismBase::<LdmcPrimMorph>::new(); let mut args = std::env::args().skip(1); let src_type_arg = args.next().expect("src type expected"); @@ -36,7 +32,7 @@ fn main() { eprintln!("[{}] parse ok.", mb_path.bright_yellow()); println!("{}", includes); for m in morphisms { - morphism_base.add_morphism(LdmcMorphism::Primitive(m)); + morphism_base.add_morphism(m); } } Err(errs) => { @@ -58,86 +54,103 @@ fn main() { let mut γ = HashMap::new(); γ.insert( - type_dict.get_typeid_creat(&"Byte".into()), + type_dict.get_typeid_creat(&"Byte"), type_dict.parse("<Seq~<StaticLength 8> Bit>").expect("parse") - .apply_substitution(&|k| γ.get(k).cloned()) + .apply_subst(&γ) .clone() ); γ.insert( - type_dict.get_typeid_creat(&"x86.UInt8".into()), + type_dict.get_typeid_creat(&"x86.UInt8"), type_dict.parse("ℤ_2^8 ~ <PosInt 2 BigEndian> ~ <Seq~<StaticLength 8> <Digit 2> ~ Bit>").expect("parse") - .apply_substitution(&|k| γ.get(k).cloned()) + .apply_subst(&γ) .clone() ); γ.insert( - type_dict.get_typeid_creat(&"x86.UInt16".into()), + type_dict.get_typeid_creat(&"x86.UInt16"), type_dict.parse("ℤ_2^16 ~ <PosInt 256 LittleEndian> ~ <Seq~<StaticLength 2> <Digit 256> ~ x86.UInt8 >").expect("parse") - .apply_substitution(&|k| γ.get(k).cloned()) + .apply_subst(&γ) .clone() ); γ.insert( - type_dict.get_typeid_creat(&"x86.UInt32".into()), + type_dict.get_typeid_creat(&"x86.UInt32"), type_dict.parse("ℤ_2^32 ~ <PosInt 256 LittleEndian> ~ <Seq~<StaticLength 4> <Digit 256> ~ x86.UInt8 >").expect("parse") - .apply_substitution(&|k| γ.get(k).cloned()) - .clone() + .apply_subst(&γ).clone() ); γ.insert( - type_dict.get_typeid_creat(&"x86.UInt64".into()), + type_dict.get_typeid_creat(&"x86.UInt64"), type_dict.parse("ℤ_2^64 ~ <PosInt 256 LittleEndian> ~ <Seq~<StaticLength 8> <Digit 256> ~ x86.UInt8 >").expect("parse") - .apply_substitution(&|k| γ.get(k).cloned()) - .clone() + .apply_subst(&γ).clone() ); γ.insert( - type_dict.get_typeid_creat(&"x86.Float".into()), + type_dict.get_typeid_creat(&"x86.Float32"), type_dict.parse("ℝ ~ IEEE-754.Float32 ~ <Seq~<StaticLength 4> Byte>").expect("parse") - .apply_substitution(&|k| γ.get(k).cloned()) - .clone() + .apply_subst(&γ).clone() + ); + γ.insert( + type_dict.get_typeid_creat(&"x86.Float64"), + type_dict.parse("ℝ ~ IEEE-754.Float64 ~ <Seq~<StaticLength 4> Byte>").expect("parse") + .apply_subst(&γ).clone() ); + 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 - <Struct.Field online-since TimePoint ~ <TimeSince UnixEpoch> ~ Duration ~ Seconds ~ ℝ ~ <QuantizedLinear 0 1 1000> ~ ℕ ~ native.UInt64 > - <Struct.Field battery-capacity Energy ~ Wh ~ ℝ ~ <QuantizedLinear 0 1 1000> ~ ℕ ~ native.UInt64 > - <Struct.Field battery-charge Energy ~ Wh ~ ℝ ~ <QuantizedLinear 0 1 1000> ~ ℕ ~ native.UInt64 > - <Struct.Field min-sampling-period Duration ~ Seconds ~ ℝ ~ <QuantizedLinear 0 1 1000> ~ ℕ ~ native.UInt32 > - <Struct.Field cur-sampling-period Duration ~ Seconds ~ ℝ ~ <QuantizedLinear 0 1 1000> ~ ℕ ~ native.UInt32 > - <Struct.Field max-chunk-size ℕ ~ native.UInt32 > - <Struct.Field cur-chunk-size ℕ ~ native.UInt32 > - <Struct.Field n-chunks-capacity ℕ ~ native.UInt32 > - <Struct.Field n-full-data-chunks ℕ ~ native.UInt32 > - <Struct.Field n-empty-data-chunks ℕ ~ native.UInt32 > + <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"); - eprintln!("{} - ", - struct_type1.clone().sugar(&mut type_dict).pretty(&type_dict, 0) - ); - - for m in morphism_base.enum_morphisms( &struct_type1 ) { - eprintln!("{:?} -> {:?}", - type_dict.read().unwrap().unparse(&m.get_type().src_type), - type_dict.read().unwrap().unparse(&m.get_type().dst_type) - ); - } - return; - let struct_type2 = type_dict.parse(" - <Struct - - <Struct.Field battery-charge Energy ~ Wh ~ ℝ ~ native.Double > - <Struct.Field battery-capacity Energy ~ Wh ~ ℝ ~ native.Double > - <Struct.Field min-sampling-period Duration ~ Seconds ~ ℝ ~ native.Double > - <Struct.Field cur-sampling-period Duration ~ Seconds ~ ℝ ~ native.Double > - <Struct.Field max-chunk-size ℕ ~ native.UInt32 > - <Struct.Field cur-chunk-size ℕ ~ native.UInt32 > - <Struct.Field n-chunks-capacity ℕ ~ native.UInt32 > - <Struct.Field n-full-data-chunks ℕ ~ native.UInt32 > - <Struct.Field n-empty-data-chunks ℕ ~ native.UInt32 > - - <Struct.Field online-since TimePoint ~ <TimeSince UnixEpoch> ~ Duration ~ Seconds ~ ℝ ~ native.Double > + <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); @@ -145,10 +158,9 @@ fn main() { m.into_prim_c_morphism(&mut type_dict, "morph_my_struct".into(), &HashMap::new()) .c_source ); -return; - let src_type = type_dict.parse( src_type_arg.as_str() ).expect(""); - let dst_type = type_dict.parse( dst_type_arg.as_str() ).expect(""); + +return; let path = laddertypes::morphism_path::ShortestPathProblem::new( &morphism_base, MorphismType { @@ -165,4 +177,5 @@ return; std::process::exit(-1); } } + */ } diff --git a/src/morphism.rs b/src/morphism.rs index c5a509f..1fb4199 100644 --- a/src/morphism.rs +++ b/src/morphism.rs @@ -1,44 +1,16 @@ -use laddertypes::{morphism::Morphism, morphism_base::MorphismBase}; -use crate::{c_gen::encode_type_to_symbol, struct_layout::StructLayout}; +use laddertypes::{morphism::Morphism, morphism_base::MorphismBase, morphism_path::ShortestPathProblem, morphism_sugared::{SugaredMorphism, SugaredMorphismType}, SugaredStructMember}; +use crate::{c_gen_types::encode_type_to_symbol, struct_layout::StructLayout}; -#[derive(Clone, Debug)] -pub struct LdmcPrimCMorphism { +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct LdmcPrimMorph { pub symbol: String, pub type_args: Vec<(laddertypes::TypeID, String)>, - pub src_type: laddertypes::TypeTerm, - pub dst_type: laddertypes::TypeTerm, + pub ty: SugaredMorphismType, pub c_source: String } -#[derive(Clone)] -pub struct StructFieldMorphism { - pub field_name: String, - pub item_morph: Option<Box<LdmcPrimCMorphism>>, - pub src_offset: u64, - pub dst_offset: u64, -} - -#[derive(Clone)] -pub enum LdmcMorphism { - Primitive( LdmcPrimCMorphism ), - //Chain(Vec< LdmcPrimCMorphism >), - LengthPrefixMap{ - length_prefix_type: laddertypes::TypeTerm, - item_morph: Box<LdmcPrimCMorphism> - }, - ValueDelimMap{ - delim: u64, - item_morph: Box<LdmcPrimCMorphism> - }, - StructMap{ - src_struct: StructLayout, - dst_struct: StructLayout, - member_morphisms: Vec<StructFieldMorphism> - } -} - -impl LdmcMorphism { +impl LdmcPrimMorph { /* pub fn into_prim_c_morphism(self, dict: &mut impl laddertypes::TypeDict, symbol: String) -> LdmcPrimCMorphism { @@ -65,20 +37,22 @@ impl LdmcMorphism { } } */ +/* + pub fn new_struct_map( dict: &mut impl laddertypes::TypeDict, - morph_base: &MorphismBase<LdmcMorphism>, + morph_base: &MorphismBase<LdmcPrimMorph>, src: laddertypes::TypeTerm, dst: laddertypes::TypeTerm, ) -> Self { - let src_struct = StructLayout::parse(dict, src).expect("cant parse src struct layout"); - let dst_struct = StructLayout::parse(dict, dst).expect("cant parse dst struct layout"); + let src_struct = StructLayout::parse(dict, &src).expect("cant parse src struct layout"); + let dst_struct = StructLayout::parse(dict, &dst).expect("cant parse dst struct layout"); let mut member_morphisms = Vec::new(); - for (field_name, dst_type) in dst_struct.members.iter() { + for SugaredStructMember{ symbol: field_name, ty: dst_type } in dst_struct.members.iter() { let mut src_type = None; - for (src_name, st) in src_struct.members.iter() { + for SugaredStructMember{ symbol: src_name, ty: st } in src_struct.members.iter() { if src_name == field_name { src_type = Some(st.clone()); } @@ -95,14 +69,19 @@ impl LdmcMorphism { } ); } else { - match morph_base.find_morphism( - &laddertypes::MorphismType { - src_type: src_type.clone(), - dst_type: dst_type.clone() - }, - dict - ) { - Some(item_morph) => { + match ShortestPathProblem::new( + &morph_base, + laddertypes::MorphismType { + src_type: src_type.clone().desugar(dict), + dst_type: dst_type.clone().desugar(dict) + } + ).solve() + { + Some(path) => { + + let src_type = src_type.clone().desugar(dict); + let dst_type = dst_type.clone().desugar(dict); + let morph_symb = format!("morph_{}_to_{}", encode_type_to_symbol(dict, &src_type), encode_type_to_symbol(dict, &dst_type) @@ -110,7 +89,7 @@ impl LdmcMorphism { member_morphisms.push( StructFieldMorphism { field_name: field_name.to_string(), - item_morph: Some(Box::new(item_morph.m.into_prim_c_morphism(dict, morph_symb, &item_morph.σ))), + item_morph: None,//Some(Box::new(item_morph.m.into_prim_c_morphism(dict, morph_symb, &item_morph.σ))), src_offset: src_struct.get_offset( field_name ), dst_offset: dst_struct.get_offset( field_name ), } @@ -124,13 +103,20 @@ impl LdmcMorphism { } } - LdmcMorphism::StructMap { + LdmcPrimMorph::StructMap { src_struct, dst_struct, member_morphisms } } + */ } +impl SugaredMorphism for LdmcPrimMorph { + fn get_type(&self) -> SugaredMorphismType { + self.ty.clone() + } +} +/* impl Morphism for LdmcMorphism { fn weight(&self) -> u64 { 1 @@ -188,3 +174,4 @@ impl Morphism for LdmcMorphism { } } } +*/ diff --git a/src/parser.rs b/src/parser.rs index f45fddf..49320df 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -1,11 +1,7 @@ use { - chumsky::{ + crate::morphism::LdmcPrimMorph, chumsky::{ prelude::*, text::* - }, - std::sync::{Arc, RwLock}, - - laddertypes::{TypeDict, BimapTypeDict, parser::*}, - crate::morphism::LdmcPrimCMorphism + }, laddertypes::{morphism_sugared::SugaredMorphismType, parser::*, BimapTypeDict, TypeDict}, std::sync::{Arc, RwLock} }; /* morphism-base text format: @@ -18,7 +14,7 @@ use { */ pub fn morphism_base_parser( type_dict: Arc<RwLock< BimapTypeDict >> -) -> impl Parser<char, (String, Vec<LdmcPrimCMorphism>), Error = Simple<char>> { +) -> impl Parser<char, (String, Vec<LdmcPrimMorph>), Error = Simple<char>> { just("```") .then(take_until(just("```"))) @@ -63,14 +59,16 @@ pub fn morphism_base_parser( ty_args.push((var_id, kind)); } - let src_type = type_dict.parse(&src_type.iter().collect::<String>()).expect("couldnt parse src type"); - let dst_type = type_dict.parse(&dst_type.iter().collect::<String>()).expect("couldnt parse dst type"); + let src_type = type_dict.parse(&src_type.iter().collect::<String>()).expect("couldnt parse src type").sugar(&mut *type_dict); + let dst_type = type_dict.parse(&dst_type.iter().collect::<String>()).expect("couldnt parse dst type").sugar(&mut *type_dict); - LdmcPrimCMorphism { + LdmcPrimMorph { symbol, type_args: ty_args, - src_type, - dst_type, + ty: SugaredMorphismType{ + src_type, + dst_type + }, c_source } }) diff --git a/src/struct_layout.rs b/src/struct_layout.rs index d961602..40be995 100644 --- a/src/struct_layout.rs +++ b/src/struct_layout.rs @@ -1,4 +1,6 @@ +use std::ops::Deref; + use laddertypes::{parser::*, unparser::*, SugaredStructMember, SugaredTypeTerm, TypeDict, TypeTerm}; #[derive(Clone, Copy, Debug)] @@ -8,43 +10,137 @@ pub enum ObjectSize { Unknown } +impl std::ops::Add for ObjectSize { + type Output = Self; -pub fn get_type_size( dict: &mut impl TypeDict, ty: TypeTerm ) -> ObjectSize { - let ty = ty.clone().get_lnf_vec().last().unwrap().clone(); + fn add(self, rhs: Self) -> Self { + match (self, rhs) { + (ObjectSize::Unknown, _) | + (_, ObjectSize::Unknown) + => ObjectSize::Unknown, - if ty == dict.parse("native.UInt8").expect("") { - return ObjectSize::Static(1); + (ObjectSize::Dynamic(), _) | + (_, ObjectSize::Dynamic()) + => ObjectSize::Dynamic(), + + (ObjectSize::Static(s1), ObjectSize::Static(s2)) => ObjectSize::Static(s1 + s2), + } } - if ty == dict.parse("native.UInt16").expect("") { - return ObjectSize::Static(2); +} + +impl std::ops::Mul for ObjectSize { + type Output = Self; + + fn mul(self, rhs: Self) -> Self { + match (self, rhs) { + (ObjectSize::Unknown, _) | + (_, ObjectSize::Unknown) + => ObjectSize::Unknown, + + (ObjectSize::Dynamic(), _) | + (_, ObjectSize::Dynamic()) + => ObjectSize::Dynamic(), + + (ObjectSize::Static(s1), ObjectSize::Static(s2)) => ObjectSize::Static(s1 * s2), + } } - if ty == dict.parse("native.UInt32").expect("") || - ty == dict.parse("native.Float").expect("") { - return ObjectSize::Static(4); - } - if ty == dict.parse("native.UInt64").expect("") || - ty == dict.parse("native.Double").expect("") { - return ObjectSize::Static(8); +} + +pub fn get_type_size( dict: &mut impl TypeDict, ty: SugaredTypeTerm ) -> ObjectSize { + match &ty { + SugaredTypeTerm::TypeID(tyid) => { + if tyid == &dict.get_typeid_creat("native.UInt8") { ObjectSize::Static(1) } + else if tyid == &dict.get_typeid_creat("native.UInt16") { ObjectSize::Static(2) } + else if tyid == &dict.get_typeid_creat("native.UInt32") { ObjectSize::Static(4) } + else if tyid == &dict.get_typeid_creat("native.UInt64") { ObjectSize::Static(8) } + else if tyid == &dict.get_typeid_creat("native.Address") { ObjectSize::Static(8) } + else if tyid == &dict.get_typeid_creat("native.Float32") { ObjectSize::Static(4) } + else if tyid == &dict.get_typeid_creat("native.Float64") { ObjectSize::Static(8) } + else { + ObjectSize::Unknown + } + }, + + SugaredTypeTerm::Ladder(rungs) => { + get_type_size(dict, rungs.last().unwrap().clone() ) + } + + SugaredTypeTerm::Struct { struct_repr, members } => { + let layout = StructLayout::parse_sugared(dict, ty).expect("invalid struct"); + layout.get_size() + } + + SugaredTypeTerm::Seq { seq_repr, items } => { + if let Some(seq_repr) = seq_repr { + dict.add_typename("Length".into()); + dict.add_typename("LengthType".into()); + dict.add_typename("TerminatorValue".into()); + + if let Ok(σ) = laddertypes::unify( + &seq_repr.clone().desugar(dict), + &dict.parse("<StaticLength Length>").expect("") + ) { + if let Some(TypeTerm::Num(len)) = σ.get(&dict.get_typeid(&"Length".into()).expect("")) { + ObjectSize::Static(*len as u64) * get_type_size(dict, items.first().unwrap().clone()) + } else { + ObjectSize::Unknown + } + } + else if let Ok(σ) = laddertypes::unify( + &seq_repr.clone().desugar(dict), + &dict.parse("<LengthPrefix LengthType>").expect("") + ) { + ObjectSize::Dynamic() + } + else if let Ok(σ) = laddertypes::unify( + &seq_repr.clone().desugar(dict), + &dict.parse("<ValueTerminated TerminatorValue>").expect("") + ) { + ObjectSize::Dynamic() + } + else { + ObjectSize::Unknown + } + } else { + ObjectSize::Unknown + } + } + + _ => ObjectSize::Unknown } - if let Some(layout) = StructLayout::parse( dict, ty ) { - return layout.get_size(); - } - - ObjectSize::Unknown } #[derive(Clone, Copy, Debug, PartialEq)] -enum LayoutType { - Natural, +pub enum LayoutType { + Aligned, Packed } -#[derive(Clone, Debug)] +impl LayoutType { + pub fn parse( dict: &mut impl TypeDict, ty: &TypeTerm ) -> Option< LayoutType > { + if ty == &dict.parse("Aligned").expect("parse") { + Some(LayoutType::Aligned) + } else if ty == &dict.parse("Packed").expect("parse") { + Some(LayoutType::Packed) + } else { + None + } + } + + pub fn unparse(&self, dict: &mut impl TypeDict) -> TypeTerm { + match self { + LayoutType::Aligned => dict.parse("Aligned").unwrap(), + LayoutType::Packed => dict.parse("Packed").unwrap() + } + } +} + +#[derive(Clone)] pub struct StructLayout { - ty: laddertypes::TypeTerm, - item_type: laddertypes::TypeTerm, - pub members: Vec< (String, laddertypes::TypeTerm) >, + pub ty: laddertypes::TypeTerm, + pub layout: LayoutType, + pub members: Vec< SugaredStructMember >, offsets: std::collections::HashMap< String, u64 >, size: ObjectSize } @@ -62,18 +158,22 @@ impl StructLayout { *self.offsets.get(name).expect("") } - pub fn calculate_offsets(&mut self, dict: &mut impl TypeDict) { - let layout_type = LayoutType::Natural; + pub fn init_offsets(&mut self, dict: &mut impl TypeDict) { let mut offset = 0; - for (field_name, field_type) in self.members.iter() { + for SugaredStructMember{symbol: field_name, ty: field_type} in self.members.iter() { //let field_c_type = crate::c_gen::get_c_repr_type(dict, field_type.clone(), true).expect("cant get c-repr for struct field"); match get_type_size( dict, field_type.clone() ) { ObjectSize::Static(field_size) => { - if layout_type == LayoutType::Natural { - // add padding to natural alignment - if offset % field_size > 0 { - offset = field_size * ((offset / field_size)+1); + match self.layout { + LayoutType::Aligned => { + // add padding to get natural alignment of current member + if offset % field_size > 0 { + offset = field_size * ((offset / field_size)+1); + } + } + LayoutType::Packed => { + // no padding } } @@ -90,7 +190,7 @@ impl StructLayout { return; } ObjectSize::Unknown => { - eprintln!("unknown field size!"); + eprintln!("Struct member `{}` has unknown size!", field_name); self.offsets.insert(field_name.clone(), offset); self.size = ObjectSize::Unknown; return; @@ -108,38 +208,30 @@ impl StructLayout { } } - pub fn generate_members(&self, dict: &mut impl TypeDict, prefix: &str, base_ptr: &str) { - let mut offset = 0; - - for (field_name, field_type) in self.members.iter() { - let field_c_type = crate::c_gen::get_c_repr_type(dict, field_type.clone(), true).expect("cant get c-repr for struct field"); - let offset = self.get_offset(field_name); - println!(" {} * restrict {}_{} = {} + {};", - field_c_type, prefix, field_name, base_ptr, offset - ); - } + pub fn parse(dict: &mut impl TypeDict, struct_type: &TypeTerm) -> Option <Self> { + let st = struct_type.clone().strip().param_normalize().sugar(dict); + Self::parse_sugared(dict, st) } - pub fn parse(dict: &mut impl TypeDict, struct_type: TypeTerm) -> Option <Self> { - match struct_type.sugar(dict) { - SugaredTypeTerm::Struct(sugared_members) => { - let mut members = Vec::new(); - let mut item_type = dict.parse("Byte").expect(""); - - for SugaredStructMember{ symbol, ty } in sugared_members { - members.push((symbol, ty.desugar(dict))); - } - + pub fn parse_sugared(dict: &mut impl TypeDict, st: SugaredTypeTerm) -> Option <Self> { + eprintln!("{}", st.pretty(dict, 0)); + match st.clone() { + SugaredTypeTerm::Struct{ struct_repr, members } => { let mut sl = StructLayout { - ty: TypeTerm::unit(), - item_type, + ty: st.desugar(dict), + layout: if let Some(sr) = struct_repr { + let sr = sr.desugar(dict); + LayoutType::parse( dict, &sr ).expect("invalid struct layout type") + } else { + eprintln!("choose default struct repr"); + LayoutType::Aligned + }, + members, offsets: std::collections::HashMap::new(), size: ObjectSize::Unknown }; - - sl.calculate_offsets(dict); - sl.calculate_type(dict); + sl.init_offsets(dict); Some(sl) } @@ -150,18 +242,4 @@ impl StructLayout { } } } - - fn calculate_type(&mut self, dict: &mut impl TypeDict) { - self.ty = - SugaredTypeTerm::Struct( - self.members - .iter() - .cloned() - .map(|(symbol,ty)| - SugaredStructMember{ symbol, ty:ty.sugar(dict) }) - .collect() - ) - .desugar(dict); - - } }