diff --git a/src/c_gen.rs b/src/c_gen.rs index 32b3ef4..41d1c99 100644 --- a/src/c_gen.rs +++ b/src/c_gen.rs @@ -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(()) + } +} diff --git a/src/c_gen_types.rs b/src/c_gen_types.rs index 8490ba7..0fb3b0d 100644 --- a/src/c_gen_types.rs +++ b/src/c_gen_types.rs @@ -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_{}", diff --git a/src/main.rs b/src/main.rs index 7ee2bad..df68e51 100644 --- a/src/main.rs +++ b/src/main.rs @@ -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")); }