From 21bb33193ab52c87007913f3f93ec802014db2ba Mon Sep 17 00:00:00 2001 From: Michael Sippel <micha@fragmental.art> Date: Mon, 24 Mar 2025 10:14:25 +0100 Subject: [PATCH 01/31] wip struct morphisms --- src/c_gen.rs | 133 ++++++++++++++++++++++++++++------ src/main.rs | 119 +++++++++++++++++++++++++----- src/morphism.rs | 116 +++++++++++++++++++++++++++++- src/struct_layout.rs | 167 +++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 496 insertions(+), 39 deletions(-) create mode 100644 src/struct_layout.rs diff --git a/src/c_gen.rs b/src/c_gen.rs index ac68a93..7f5c7ea 100644 --- a/src/c_gen.rs +++ b/src/c_gen.rs @@ -1,6 +1,6 @@ use { - laddertypes::{TypeDict, TypeTerm, parser::*, unparser::*, morphism::{Morphism, MorphismInstance}}, - crate::morphism::{LdmcPrimCMorphism, LdmcMorphism} + crate::{morphism::{LdmcMorphism, LdmcPrimCMorphism}, struct_layout::{get_type_size, ObjectSize, StructLayout}}, + laddertypes::{morphism::{Morphism, MorphismInstance}, parser::*, unparser::*, TypeDict, TypeTerm}, }; /* @@ -85,7 +85,23 @@ pub fn get_c_repr_type(dict: &mut impl TypeDict, t: laddertypes::TypeTerm, skip_ } } else { - None + + 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 + } } } @@ -205,14 +221,17 @@ 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) ); - morph_inst.m.generate_call(type_dict, &morph_inst.σ, i); + i += 1; } @@ -322,7 +341,42 @@ int {} ( {} const * restrict src, {} * restrict dst ) {{ } impl LdmcMorphism { - pub fn generate_call(&self, dict: &mut impl TypeDict, σ: &std::collections::HashMap<laddertypes::TypeID, laddertypes::TypeTerm>, i: u64) { + 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"); @@ -331,17 +385,16 @@ impl LdmcMorphism { let src_buf = if i%2 == 0 { "bufA" } else { "bufB" }; let dst_buf = if i%2 == 0 { "bufB" } else { "bufA" }; - println!(r#" - {} + 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(); @@ -383,18 +436,17 @@ impl LdmcMorphism { let src_buf = if i%2 == 0 { "bufA" } else { "bufB" }; let dst_buf = if i%2 == 0 { "bufB" } else { "bufA" }; - println!(r#" - {} + 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"); @@ -402,17 +454,54 @@ impl LdmcMorphism { let src_buf = if i%2 == 0 { "bufA" } else { "bufB" }; let dst_buf = if i%2 == 0 { "bufB" } else { "bufA" }; - println!(r#" - {} + 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, σ), - '}'); + 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/main.rs b/src/main.rs index 13b8629..8769384 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,29 +3,25 @@ mod morphism; mod parser; mod c_gen; +mod struct_layout; use { - ariadne::{Color, Label, Report, ReportKind, Source}, - chumsky::prelude::*, - laddertypes::{ - parser::ParseLadderType, BimapTypeDict, MorphismType - }, - std::sync::{Arc, RwLock}, - tiny_ansi::TinyAnsi, - - crate::{ morphism::LdmcMorphism, parser::morphism_base_parser, - } + }, ariadne::{Color, Label, Report, ReportKind, Source}, chumsky::prelude::*, laddertypes::{ + parser::ParseLadderType, unparser::*, BimapTypeDict, MorphismType, 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::MorphismBase::<LdmcMorphism>::new(vec![ + + 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("Seq~<LengthPrefix native.UInt64>").expect(""), + type_dict.parse("Struct").expect("") ]); let mut args = std::env::args().skip(1); @@ -60,14 +56,105 @@ fn main() { } } + let mut γ = HashMap::new(); + γ.insert( + type_dict.get_typeid_creat(&"Byte".into()), + type_dict.parse("<Seq~<StaticLength 8> Bit>").expect("parse") + .apply_substitution(&|k| γ.get(k).cloned()) + .clone() + ); + γ.insert( + type_dict.get_typeid_creat(&"x86.UInt8".into()), + type_dict.parse("ℤ_2^8 ~ <PosInt 2 BigEndian> ~ <Seq~<StaticLength 8> <Digit 2> ~ Bit>").expect("parse") + .apply_substitution(&|k| γ.get(k).cloned()) + .clone() + ); + γ.insert( + type_dict.get_typeid_creat(&"x86.UInt16".into()), + type_dict.parse("ℤ_2^16 ~ <PosInt 256 LittleEndian> ~ <Seq~<StaticLength 2> <Digit 256> ~ x86.UInt8 >").expect("parse") + .apply_substitution(&|k| γ.get(k).cloned()) + .clone() + ); + γ.insert( + type_dict.get_typeid_creat(&"x86.UInt32".into()), + type_dict.parse("ℤ_2^32 ~ <PosInt 256 LittleEndian> ~ <Seq~<StaticLength 4> <Digit 256> ~ x86.UInt8 >").expect("parse") + .apply_substitution(&|k| γ.get(k).cloned()) + .clone() + ); + γ.insert( + type_dict.get_typeid_creat(&"x86.UInt64".into()), + type_dict.parse("ℤ_2^64 ~ <PosInt 256 LittleEndian> ~ <Seq~<StaticLength 8> <Digit 256> ~ x86.UInt8 >").expect("parse") + .apply_substitution(&|k| γ.get(k).cloned()) + .clone() + ); + γ.insert( + type_dict.get_typeid_creat(&"x86.Float".into()), + type_dict.parse("ℝ ~ IEEE-754.Float32 ~ <Seq~<StaticLength 4> Byte>").expect("parse") + .apply_substitution(&|k| γ.get(k).cloned()) + .clone() + ); + 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 > + > + ").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 > + > + ").expect("parse struct type"); + + 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 src_type = type_dict.parse( src_type_arg.as_str() ).expect(""); let dst_type = type_dict.parse( dst_type_arg.as_str() ).expect(""); - let path = morphism_base.find_morphism_path(MorphismType { - src_type: src_type.clone(), - dst_type: dst_type.clone(), - }); + 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) => { diff --git a/src/morphism.rs b/src/morphism.rs index a1f2aab..c5a509f 100644 --- a/src/morphism.rs +++ b/src/morphism.rs @@ -1,5 +1,6 @@ -use laddertypes::morphism::Morphism; +use laddertypes::{morphism::Morphism, morphism_base::MorphismBase}; +use crate::{c_gen::encode_type_to_symbol, struct_layout::StructLayout}; #[derive(Clone, Debug)] pub struct LdmcPrimCMorphism { @@ -10,9 +11,18 @@ pub struct LdmcPrimCMorphism { 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> @@ -20,6 +30,104 @@ pub enum LdmcMorphism { ValueDelimMap{ delim: u64, item_morph: Box<LdmcPrimCMorphism> + }, + StructMap{ + src_struct: StructLayout, + dst_struct: StructLayout, + member_morphisms: Vec<StructFieldMorphism> + } +} + +impl LdmcMorphism { + /* + pub fn into_prim_c_morphism(self, dict: &mut impl laddertypes::TypeDict, symbol: String) -> LdmcPrimCMorphism { + + let src_c_type = ; + let dst_c_type = ; + + let c_source = + format!(" + int {} ( {} const * restrict src, {} * restrict dst ) {{ + {} + return 0; + }} + ", + symbol, src_c_type, dst_c_type, + self.generate_call(dict, &std::collections::HashMap::new(), 0) + ); + + LdmcPrimCMorphism { + symbol, + type_args: Vec::new(), + src_type, + dst_type, + c_source + } + } +*/ + pub fn new_struct_map( + dict: &mut impl laddertypes::TypeDict, + morph_base: &MorphismBase<LdmcMorphism>, + 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 mut member_morphisms = Vec::new(); + + for (field_name, dst_type) in dst_struct.members.iter() { + let mut src_type = None; + for (src_name, st) in src_struct.members.iter() { + if src_name == field_name { + src_type = Some(st.clone()); + } + } + let src_type = src_type.expect(&format!("cant find member {} in src struct", field_name)); + + if src_type == *dst_type { + member_morphisms.push( + StructFieldMorphism { + field_name: field_name.to_string(), + item_morph: None, + src_offset: src_struct.get_offset( field_name ), + dst_offset: dst_struct.get_offset( field_name ), + } + ); + } else { + match morph_base.find_morphism( + &laddertypes::MorphismType { + src_type: src_type.clone(), + dst_type: dst_type.clone() + }, + dict + ) { + Some(item_morph) => { + let morph_symb = format!("morph_{}_to_{}", + encode_type_to_symbol(dict, &src_type), + encode_type_to_symbol(dict, &dst_type) + ); + 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.σ))), + src_offset: src_struct.get_offset( field_name ), + dst_offset: dst_struct.get_offset( field_name ), + } + ); + }, + + None => { + eprintln!("cant map field {}", field_name); + } + } + } + } + + LdmcMorphism::StructMap { + src_struct, dst_struct, + member_morphisms + } } } @@ -47,6 +155,12 @@ impl Morphism for LdmcMorphism { src_type: laddertypes::TypeTerm::App(vec![ value_delim_type.clone(), item_morph.src_type.clone() ]), dst_type: laddertypes::TypeTerm::App(vec![ value_delim_type.clone(), item_morph.dst_type.clone() ]), } + }, + LdmcMorphism::StructMap { src_struct, dst_struct, member_morphisms } => { + laddertypes::MorphismType { + src_type: src_struct.get_type(), + dst_type: dst_struct.get_type() + } } }.normalize() } diff --git a/src/struct_layout.rs b/src/struct_layout.rs new file mode 100644 index 0000000..d961602 --- /dev/null +++ b/src/struct_layout.rs @@ -0,0 +1,167 @@ + +use laddertypes::{parser::*, unparser::*, SugaredStructMember, SugaredTypeTerm, TypeDict, TypeTerm}; + +#[derive(Clone, Copy, Debug)] +pub enum ObjectSize { + Static(u64), + Dynamic(/* function to get size at runtime */), + Unknown +} + + +pub fn get_type_size( dict: &mut impl TypeDict, ty: TypeTerm ) -> ObjectSize { + let ty = ty.clone().get_lnf_vec().last().unwrap().clone(); + + if ty == dict.parse("native.UInt8").expect("") { + return ObjectSize::Static(1); + } + if ty == dict.parse("native.UInt16").expect("") { + return ObjectSize::Static(2); + } + 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); + } + + if let Some(layout) = StructLayout::parse( dict, ty ) { + return layout.get_size(); + } + + ObjectSize::Unknown +} + +#[derive(Clone, Copy, Debug, PartialEq)] +enum LayoutType { + Natural, + Packed +} + +#[derive(Clone, Debug)] +pub struct StructLayout { + ty: laddertypes::TypeTerm, + item_type: laddertypes::TypeTerm, + pub members: Vec< (String, laddertypes::TypeTerm) >, + offsets: std::collections::HashMap< String, u64 >, + size: ObjectSize +} + +impl StructLayout { + pub fn get_type(&self) -> TypeTerm { + self.ty.clone() + } + + pub fn get_size(&self) -> ObjectSize { + self.size + } + + pub fn get_offset(&self, name: &String) -> u64 { + *self.offsets.get(name).expect("") + } + + pub fn calculate_offsets(&mut self, dict: &mut impl TypeDict) { + let layout_type = LayoutType::Natural; + 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"); + 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); + } + } + + // take offset + self.offsets.insert(field_name.clone(), offset); + + // advance by current size + offset += field_size; + } + ObjectSize::Dynamic() => { + eprintln!("dynamically sized Field in struct!"); + self.offsets.insert(field_name.clone(), offset); + self.size = ObjectSize::Dynamic(); + return; + } + ObjectSize::Unknown => { + eprintln!("unknown field size!"); + self.offsets.insert(field_name.clone(), offset); + self.size = ObjectSize::Unknown; + return; + } + } + } + + match self.size { + ObjectSize::Dynamic() => { + + } + _ => { + self.size = ObjectSize::Static(offset); + } + } + } + + 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> { + 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))); + } + + let mut sl = StructLayout { + ty: TypeTerm::unit(), + item_type, + members, + offsets: std::collections::HashMap::new(), + size: ObjectSize::Unknown + }; + + sl.calculate_offsets(dict); + sl.calculate_type(dict); + + Some(sl) + } + + _ => { + eprintln!("not a struct"); + None + } + } + } + + 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); + + } +} From bce52e9fcfd6712306a2479753d44ee80b3045e3 Mon Sep 17 00:00:00 2001 From: Michael Sippel <micha@fragmental.art> Date: Tue, 25 Mar 2025 19:38:56 +0100 Subject: [PATCH 02/31] replace native.Float/native.Double with native.Float32/native.Float64 --- morphisms/angle.morphism-base | 32 ++++++++++++++--------------- morphisms/real.morphism-base | 28 ++++++++++++------------- morphisms/temperature.morphism-base | 16 +++++++-------- 3 files changed, 38 insertions(+), 38 deletions(-) diff --git a/morphisms/angle.morphism-base b/morphisms/angle.morphism-base index 71aba96..5fa3baf 100644 --- a/morphisms/angle.morphism-base +++ b/morphisms/angle.morphism-base @@ -3,16 +3,16 @@ ``` morph_angle_as_degrees_to_turns_float () - Angle ~ Degrees ~ ℝ ~ native.Float ---> Angle ~ Turns ~ ℝ ~ native.Float + Angle ~ Degrees ~ ℝ ~ native.Float32 +--> Angle ~ Turns ~ ℝ ~ native.Float32 ``` *dst = *src / 360.0; return 0; ``` morph_angle_as_degrees_to_turns_double () - Angle ~ Degrees ~ ℝ ~ native.Double ---> Angle ~ Turns ~ ℝ ~ native.Double + Angle ~ Degrees ~ ℝ ~ native.Float64 +--> Angle ~ Turns ~ ℝ ~ native.Float64 ``` *dst = *src / 360.0; return 0; @@ -20,16 +20,16 @@ morph_angle_as_degrees_to_turns_double () morph_angle_as_turns_to_degrees_float () - Angle ~ Turns ~ ℝ ~ native.Float ---> Angle ~ Degrees ~ ℝ ~ native.Float + Angle ~ Turns ~ ℝ ~ native.Float32 +--> Angle ~ Degrees ~ ℝ ~ native.Float32 ``` *dst = *src * 360.0; return 0; ``` morph_angle_as_turns_to_degrees_double () - Angle ~ Turns ~ ℝ ~ native.Double ---> Angle ~ Degrees ~ ℝ ~ native.Double + Angle ~ Turns ~ ℝ ~ native.Float64 +--> Angle ~ Degrees ~ ℝ ~ native.Float64 ``` *dst = *src * 360.0; return 0; @@ -39,16 +39,16 @@ morph_angle_as_turns_to_degrees_double () morph_angle_as_radians_to_turns_float () - Angle ~ Radians ~ ℝ ~ native.Float ---> Angle ~ Turns ~ ℝ ~ native.Float + Angle ~ Radians ~ ℝ ~ native.Float32 +--> Angle ~ Turns ~ ℝ ~ native.Float32 ``` *dst = *src / PHI; return 0; ``` morph_angle_as_radians_to_turns_double () - Angle ~ Radians ~ ℝ ~ native.Double ---> Angle ~ Turns ~ ℝ ~ native.Double + Angle ~ Radians ~ ℝ ~ native.Float64 +--> Angle ~ Turns ~ ℝ ~ native.Float64 ``` *dst = *src / PHI; return 0; @@ -56,16 +56,16 @@ morph_angle_as_radians_to_turns_double () morph_angle_as_turns_to_radians_float () - Angle ~ Turns ~ ℝ ~ native.Float ---> Angle ~ Radians ~ ℝ ~ native.Float + Angle ~ Turns ~ ℝ ~ native.Float32 +--> Angle ~ Radians ~ ℝ ~ native.Float32 ``` *dst = *src * PHI; return 0; ``` morph_angle_as_degrees_to_radians_double () - Angle ~ Turns ~ ℝ ~ native.Double ---> Angle ~ Radians ~ ℝ ~ native.Double + Angle ~ Turns ~ ℝ ~ native.Float64 +--> Angle ~ Radians ~ ℝ ~ native.Float64 ``` *dst = *src * PHI; return 0; diff --git a/morphisms/real.morphism-base b/morphisms/real.morphism-base index 3302f80..4add278 100644 --- a/morphisms/real.morphism-base +++ b/morphisms/real.morphism-base @@ -4,7 +4,7 @@ morph_real_as_decimalstr_to_float () ℝ ~ <PosInt 10 BigEndian> ~ <Seq~<ValueTerminated 0> <Digit 10>~Char~Ascii~native.UInt8> ---> ℝ ~ native.Float +--> ℝ ~ native.Float32 ``` sscanf(src, "%f", dst); return 0; @@ -12,14 +12,14 @@ morph_real_as_decimalstr_to_float () morph_real_as_decimalstr_to_double () ℝ ~ <PosInt 10 BigEndian> ~ <Seq~<ValueTerminated 0> <Digit 10>~Char~Ascii~native.UInt8> ---> ℝ ~ native.Double +--> ℝ ~ native.Float64 ``` sscanf(src, "%lf", dst); return 0; ``` morph_real_as_float_to_decimalstr () - ℝ ~ native.Float + ℝ ~ native.Float32 --> ℝ ~ <PosInt 10 BigEndian> ~ <Seq~<ValueTerminated 0> <Digit 10>~Char~Ascii~native.UInt8> ``` sprintf(dst, "%f", *src); @@ -27,7 +27,7 @@ morph_real_as_float_to_decimalstr () ``` morph_real_as_double_to_decimalstr () - ℝ ~ native.Double + ℝ ~ native.Float64 --> ℝ ~ <PosInt 10 BigEndian> ~ <Seq~<ValueTerminated 0> <Digit 10>~Char~Ascii~native.UInt8> ``` sprintf(dst, "%f", *src); @@ -36,16 +36,16 @@ morph_real_as_double_to_decimalstr () morph_real_as_float_to_double () - ℝ ~ native.Float ---> ℝ ~ native.Double + ℝ ~ native.Float32 +--> ℝ ~ native.Float64 ``` *dst = *src; return 0; ``` morph_real_as_double_to_float () - ℝ ~ native.Double ---> ℝ ~ native.Float + ℝ ~ native.Float64 +--> ℝ ~ native.Float32 ``` fprintf(stderr, "Warning: morphin Double -> Float. Precision loss!"); *dst = *src; @@ -54,7 +54,7 @@ morph_real_as_double_to_float () morph_real_as_u64_to_float () ℝ ~ ℕ ~ native.UInt64 ---> ℝ ~ native.Float +--> ℝ ~ native.Float32 ``` fprintf(stderr, "Warning: morphin UInt64 -> Float. Precision loss!"); *dst = *src; @@ -63,7 +63,7 @@ morph_real_as_u64_to_float () morph_real_as_u64_to_double () ℝ ~ ℕ ~ native.UInt64 ---> ℝ ~ native.Double +--> ℝ ~ native.Float64 ``` fprintf(stderr, "Warning: morphin UInt64 -> Double. Precision loss!"); *dst = *src; @@ -72,14 +72,14 @@ morph_real_as_u64_to_double () morph_real_as_quantized_linear_to_float (Begin: ℝ, End: ℝ, Steps: ℤ) ℝ ~ <QuantizedLinear Begin End Steps> ~ ℕ ~ native.UInt64 ---> ℝ ~ native.Float +--> ℝ ~ native.Float32 ``` *dst = (float)Begin + ( *src * ((float)End - (float)Begin) ) / (float)Steps; return 0; ``` morph_real_as_float_to_quantized_linear (Begin: ℝ, End: ℝ, Steps: ℤ) - ℝ ~ native.Float + ℝ ~ native.Float32 --> ℝ ~ <QuantizedLinear Begin End Steps> ~ ℕ ~ native.UInt64 ``` *dst = ((*src - (float)Begin) * (float)Steps) / ((float)End - (float)Begin); @@ -90,14 +90,14 @@ morph_real_as_float_to_quantized_linear (Begin: ℝ, End: ℝ, Steps: ℤ) morph_real_as_quantized_linear_to_double (Begin: ℝ, End: ℝ, Steps: ℤ) ℝ ~ <QuantizedLinear Begin End Steps> ~ ℕ ~ native.UInt64 ---> ℝ ~ native.Double +--> ℝ ~ native.Float64 ``` *dst = (double)Begin + ( *src * ((double)End - (double)Begin) ) / (double)Steps; return 0; ``` morph_real_as_double_to_quantized_linear (Begin: ℝ, End: ℝ, Steps: ℤ) - ℝ ~ native.Double + ℝ ~ native.Float64 --> ℝ ~ <QuantizedLinear Begin End Steps> ~ ℕ ~ native.UInt64 ``` *dst = ((*src - (double)Begin) * (double)Steps) / ((double)End - (double)Begin); diff --git a/morphisms/temperature.morphism-base b/morphisms/temperature.morphism-base index 7831292..6c682bc 100644 --- a/morphisms/temperature.morphism-base +++ b/morphisms/temperature.morphism-base @@ -2,32 +2,32 @@ ``` morph_celsius_to_kelvin () - Temperature ~ Celsius ~ ℝ ~ native.Float ---> Temperature ~ Kelvin ~ ℝ ~ native.Float + Temperature ~ Celsius ~ ℝ ~ native.Float32 +--> Temperature ~ Kelvin ~ ℝ ~ native.Float32 ``` *dst = *src + 273.15; return 0; ``` morph_kelvin_to_celsius () - Temperature ~ Kelvin ~ ℝ ~ native.Float ---> Temperature ~ Celsius ~ ℝ ~ native.Float + Temperature ~ Kelvin ~ ℝ ~ native.Float32 +--> Temperature ~ Celsius ~ ℝ ~ native.Float32 ``` *dst = *src - 273.15; return 0; ``` morph_celsius_to_fahrenheit () - Temperature ~ Celsius ~ ℝ ~ native.Float ---> Temperature ~ Fahrenheit ~ ℝ ~ native.Float + Temperature ~ Celsius ~ ℝ ~ native.Float32 +--> Temperature ~ Fahrenheit ~ ℝ ~ native.Float32 ``` *dst = (*src * 9.0 / 5.0) + 32.0; return 0; ``` morph_fahrenheit_to_celsius () - Temperature ~ Fahrenheit ~ ℝ ~ native.Float ---> Temperature ~ Celsius ~ ℝ ~ native.Float + Temperature ~ Fahrenheit ~ ℝ ~ native.Float32 +--> Temperature ~ Celsius ~ ℝ ~ native.Float32 ``` *dst = (*src - 32.0) * 5.0 / 9.0; return 0; From d98afc294df8b0d3ff6fb1c4b64a221ef86b29ef Mon Sep 17 00:00:00 2001 From: Michael Sippel <micha@fragmental.art> Date: Mon, 31 Mar 2025 10:29:57 +0200 Subject: [PATCH 03/31] exemplaric platform definitions --- platforms/json.lt | 100 ++++++++++++++++++++++++++++++++++++++++++ platforms/json5.lt | 0 platforms/protobuf.lt | 3 ++ platforms/spapod.lt | 0 platforms/x86.lt | 5 +++ 5 files changed, 108 insertions(+) create mode 100644 platforms/json.lt create mode 100644 platforms/json5.lt create mode 100644 platforms/protobuf.lt create mode 100644 platforms/spapod.lt create mode 100644 platforms/x86.lt diff --git a/platforms/json.lt b/platforms/json.lt new file mode 100644 index 0000000..8e69138 --- /dev/null +++ b/platforms/json.lt @@ -0,0 +1,100 @@ + +type UTF8-String = <Seq Char~Unicode> ~ UTF-8 ~ <Seq~<ValueTerminated 0> native.UInt8> ; + +type SerializedJson.Value = json.Value + ~ <Enum + <Null json.Null ~ SerializedJson.Null > + <String json.String ~ SerializedJson.String > + <Number json.Number ~ SerializedJson.Number > + <Bool json.Bool ~ SerializedJson.Bool > + <Array json.Array ~ SerializedJson.Array > + <Object json.Object ~ SerializedJson.Object >> + ~ <Seq Char> ; + +type SerializedJson.Null = < Struct~<Seq Char> "\"null\"" > ; + +type SerializedJson.String = <Seq Char> + ~ <Struct~<Seq Char> "\"" <Seq Char> "\""> + ~ <Seq Char> ; + +type SerializedJson.Number = ℝ + ~ <PosInt 10 BigEndian> + ~ <Seq <Digit 10> ~ Char> ; + +type SerializedJson.Bool = Bool + ~ <Enum~<Seq Char> + <True~"\"true\"" <>> + <False~"\"false\"" <>>> + ~ <Seq Char> ; + +type SerializedJson.Array = <Struct~<Seq Char> + "[" + <Seq json.Value> + ~ <ValueSep ',' Char> + ~ <Seq Char> + "]" > + ~ <Seq Char> ; + +type SerializedJson.Object = <Struct~<Seq Char> + "{" + <members <Seq + <Struct~<Seq Char> + <key json.String> + ":" + <value json.Value>>>> + "}" + > + ~ <Seq Char>; + +type parsedJson.Value = json.Value ~ <Enum~native.UInt8 + < parsedJson_Null~0 <> > + < parsedJson_String~1 <Ref UTF8-String> ~ native.Address > + < parsedJson_Int~2 ℝ~ℕ~native.UInt64 > + < parsedJson_Float~2 ℝ~native.Float64 > + < parsedJson_Bool~3 Bool ~ native.UInt8 > + + < parsedJson_Array~4 <Ref <Seq ~ <LengthPrefix native.UInt64> + parsedJsonValue + > + > + ~ native.Address > + + < parsedJson_Object~5 <Ref <Seq ~ <LengthPrefix native.UInt64> + <Struct + <key <Ref UTF8-String> ~ native.Address> + <val parsedJsonValue> + > + > + ~ native.Address >> + ~ <Struct + <tag native.UInt8> + native.UInt64 >; + +parse_json_value () + json.Value ~ UTF8-String +--> json.Value ~ parsedJsonValue +``` + + { + dst->tag = PARSED_JSON_NULL; + dst->parsedJson_Null; + } + + { + dst->tag = PARSED_JSON_STRING; + dst->parsedJson_String = malloc(len); + strncpy(dst->parsedJson_String, src, len); + src += len; + } + + { + dst->tag = PARSED_JSON_NUMBER; + + MORPH( + "ℝ ~ ℕ ~ <PosInt 10 BigEndian> ~ <Seq <Digit 10> ~ Char> ~ UTF8-String", + "ℝ ~ ℕ ~ native.UInt64", + src, + &dst->parsedJson_Number + ); + } +``` diff --git a/platforms/json5.lt b/platforms/json5.lt new file mode 100644 index 0000000..e69de29 diff --git a/platforms/protobuf.lt b/platforms/protobuf.lt new file mode 100644 index 0000000..ce273f6 --- /dev/null +++ b/platforms/protobuf.lt @@ -0,0 +1,3 @@ + +type protobuf.Varint = ℕ ~ <PosInt 128 LittleEndian> ~ <Seq~MsbCont <Digit 128> ~ ℤ_128 ~ native.UInt8> ; +type protobuf.String = <Seq Char ~ Unicode> ~ UTF-8 ~ <Seq ~ <LengthPrefix protobuf.Varint> Byte> ; diff --git a/platforms/spapod.lt b/platforms/spapod.lt new file mode 100644 index 0000000..e69de29 diff --git a/platforms/x86.lt b/platforms/x86.lt new file mode 100644 index 0000000..0348efc --- /dev/null +++ b/platforms/x86.lt @@ -0,0 +1,5 @@ + +type x86.UInt64 = ℤ_2/\64 ~ <PosInt 256 LittleEndian> ~ <Seq~<StaticLength 8> <Digit 256> ~ x86.UInt8 >; +type x86.UInt32 = ℤ_2/\32 ~ <PosInt 256 LittleEndian> ~ <Seq~<StaticLength 4> <Digit 256> ~ x86.UInt8 >; +type x86.UInt16 = ℤ_2^16 ~ <PosInt 256 LittleEndian> ~ <Seq~<StaticLength 2> <Digit 256> ~ x86.UInt8 >; +type x86.UInt8 = ℤ_256 ~ <Posint 2 BigEndian> ~ <Seq~<StaticLength 8> <Digit 2> ~ Bit>; From 583892f10d6bf153352d0c16af3ca19e52a066a5 Mon Sep 17 00:00:00 2001 From: Michael Sippel <micha@fragmental.art> Date: Tue, 1 Apr 2025 18:23:18 +0200 Subject: [PATCH 04/31] wip struct morphisms --- src/c_gen.rs | 628 ++++++++++++++++++------------------------- src/c_gen_types.rs | 240 +++++++++++++++++ src/main.rs | 143 +++++----- src/morphism.rs | 85 +++--- src/parser.rs | 22 +- src/struct_layout.rs | 220 ++++++++++----- 6 files changed, 774 insertions(+), 564 deletions(-) create mode 100644 src/c_gen_types.rs 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); - - } } From 39cba1ee57be010c26f13fe82e7ff95e42054ac8 Mon Sep 17 00:00:00 2001 From: Michael Sippel <micha@fragmental.art> Date: Wed, 2 Apr 2025 14:11:17 +0200 Subject: [PATCH 05/31] improve symbol names in generated c code --- src/c_gen.rs | 72 ++++++++++++++++++++++++++++------------------ src/c_gen_types.rs | 13 +++++---- 2 files changed, 51 insertions(+), 34 deletions(-) diff --git a/src/c_gen.rs b/src/c_gen.rs index c64a0f6..5677c73 100644 --- a/src/c_gen.rs +++ b/src/c_gen.rs @@ -1,5 +1,5 @@ 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, 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_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 }; @@ -43,19 +43,14 @@ impl LdmcPrimMorph { 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"); + 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 ) {{ "#, - 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"), + symbol, src_c_symbol, dst_c_symbol, )); s.push_str(&self.c_source); s.push_str(&format!(r#" @@ -72,14 +67,18 @@ int {} ( {} const * restrict src, {} * restrict dst ) {{ pub struct LdmcCTargetMorph { includes: Vec< String >, + active_types: Vec< SugaredTypeTerm >, active_instantiations: Vec< LdmcPrimMorph >, } impl LdmcCTargetMorph { pub fn new() -> Self { LdmcCTargetMorph { - includes: Vec::new(), - active_instantiations: Vec::new() + includes: vec![ + "#include <stdint.h>".into(), + ], + active_instantiations: Vec::new(), + active_types: Vec::new(), } } @@ -92,6 +91,15 @@ impl LdmcCTargetMorph { 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) } @@ -101,6 +109,14 @@ impl LdmcCTargetMorph { source.push_str(&inc); } + 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")); } @@ -119,7 +135,6 @@ impl LdmcCTargetMorph { 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 @@ -138,13 +153,13 @@ impl LdmcCTargetMorph { Ok(LdmcPrimMorph{ symbol: morph.instantiated_symbol_name(dict, σ), type_args: Vec::new(), - ty: morph_inst.get_type(), + ty: morph_inst.get_haloless_type(), c_source }) }, MorphismInstance2::Chain { path } => { - let ty = morph_inst.get_type(); - let symbol = encode_morph_type_to_symbol(dict, &ty); + 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(); @@ -159,8 +174,8 @@ impl LdmcCTargetMorph { 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_c_type = get_c_repr_type(dict, inst.get_type().strip_halo().src_type, true).expect("cant get c-repr type for src type"); + let dst_c_type = get_c_repr_type(dict, inst.get_type().strip_halo().dst_type, 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" }; @@ -187,7 +202,7 @@ impl LdmcCTargetMorph { } MorphismInstance2::MapSeq { ψ, seq_repr, item_morph } => { let i = 0; // <--todo - self.add_instantiation(dict, item_morph.as_ref().clone()); + self.add_instantiation(dict, item_morph.as_ref().clone()).expect("add instantiation"); if let Some(seq_repr) = seq_repr { dict.add_varname("LengthType".into()); @@ -196,15 +211,15 @@ impl LdmcCTargetMorph { 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 ty = morph_inst.get_type().strip_halo(); + let symbol = encode_morph_type_to_symbol(dict, &morph_inst.get_haloless_type()); + let item_morph_symbol = encode_morph_type_to_symbol(dict, &item_morph.get_haloless_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 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"); + let src_c_type = encode_type_to_symbol(dict, &ty.strip_halo().src_type); + let dst_c_type = encode_type_to_symbol(dict, &ty.strip_halo().dst_type); let map_fn = format!("length_prefix_{}_array_map_{}_to_{}", length_c_type, src_item_c_type, dst_item_c_type @@ -238,13 +253,14 @@ impl LdmcCTargetMorph { } }, MorphismInstance2::MapStruct { ψ, struct_repr, member_morph } => { - let ty = morph_inst.get_type(); - let symbol =encode_morph_type_to_symbol(dict, &ty); + 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!(" {} ( &src->{}, &dst->{} ); diff --git a/src/c_gen_types.rs b/src/c_gen_types.rs index 9c0020d..8490ba7 100644 --- a/src/c_gen_types.rs +++ b/src/c_gen_types.rs @@ -14,8 +14,6 @@ pub fn get_c_repr_kind(kind: String) -> Option<String> { /* 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") { @@ -136,7 +134,7 @@ pub fn get_c_repr_type(dict: &mut impl TypeDict, t: SugaredTypeTerm, skip_pointe let field_c_type = get_c_repr_type(dict, ty, false).expect(""); c_type.push_str(&format!(" {} {};\n", field_c_type, - symbol + symbol.replace("-", "_").replace(".","_dot_") )); } @@ -152,7 +150,7 @@ struct {{ for (i, SugaredEnumVariant{ symbol, ty }) in variants.iter().enumerate() { c_type.push_str(&format!( - " {} = {}", symbol.to_uppercase(), i + " {} = {}", symbol.replace("-", "_").replace(".","_dot_").to_uppercase(), i )); if i+1 < variants.len() { @@ -169,7 +167,7 @@ struct {{ 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 + " {} {};\n", variant_c_type, symbol.replace("-", "_").replace(".","_dot_") )); } @@ -198,6 +196,7 @@ pub fn encode_type_to_symbol(dict: &mut impl TypeDict, t: &laddertypes::SugaredT laddertypes::TypeTerm::Char(c) => { match c { '.' => format!("_dot_"), + '-' => format!("_minus_"), _ => format!("{}", (c as u64)) } @@ -207,7 +206,9 @@ pub fn encode_type_to_symbol(dict: &mut impl TypeDict, t: &laddertypes::SugaredT } laddertypes::TypeTerm::TypeID(ty_id) => { if let Some(name) = dict.get_typename(&ty_id) { - format!("{}", name.replace(".", "_dot_")) + name + .replace("-", "_") + .replace(".", "_dot_") } else { format!("") } From 35b747ea15a67d2005a55d8a00c286c0b2b0ae4a Mon Sep 17 00:00:00 2001 From: Michael Sippel <micha@fragmental.art> Date: Wed, 2 Apr 2025 14:31:47 +0200 Subject: [PATCH 06/31] fix local src/dst types in complex morphisms --- src/c_gen.rs | 150 +++------------------------------------------------ 1 file changed, 6 insertions(+), 144 deletions(-) diff --git a/src/c_gen.rs b/src/c_gen.rs index 5677c73..49c69b5 100644 --- a/src/c_gen.rs +++ b/src/c_gen.rs @@ -2,12 +2,6 @@ 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(); @@ -40,9 +34,6 @@ impl LdmcPrimMorph { 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 = 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); @@ -174,8 +165,8 @@ impl LdmcCTargetMorph { 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, inst.get_type().strip_halo().src_type, true).expect("cant get c-repr type for src type"); - let dst_c_type = get_c_repr_type(dict, inst.get_type().strip_halo().dst_type, true).expect("cant get c-repr type for dst type"); + 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" }; @@ -218,8 +209,10 @@ impl LdmcCTargetMorph { 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"); - let src_c_type = encode_type_to_symbol(dict, &ty.strip_halo().src_type); - let dst_c_type = encode_type_to_symbol(dict, &ty.strip_halo().dst_type); + let src_c_type = encode_type_to_symbol(dict, &ty.src_type); + let dst_c_type = encode_type_to_symbol(dict, &ty.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 @@ -285,134 +278,3 @@ impl LdmcCTargetMorph { } } } - - -/* -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> -#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> native.UInt8>").unwrap() - ) { - println!(r#" -printf("%s\n", {});"#, out_buf); - } else if let Ok((halo, σ)) = laddertypes::subtype_unify( - &dst_type, - &type_dict.parse("<Seq~<LengthPrefix native.UInt64> native.UInt8>").unwrap() - ) { - println!(r#" - /* write output - */ - {{ - LengthPrefix_uint64_t_Array_uint8_t * buf = (void*){}; - write(1, {}, sizeof(uint64_t) + buf->len); - }}"#, out_buf, out_buf); - } else { - println!(r#" -write(1, {}, sizeof({}));"#, - out_buf, - out_buf - ); - } - - - println!(r#" -return 0; -}} - "#); - - eprintln!("Success: generated C code"); -} -*/ From 98592aa596b27ae23d0c2930637d6810fa638227 Mon Sep 17 00:00:00 2001 From: Michael Sippel <micha@fragmental.art> Date: Wed, 2 Apr 2025 14:37:31 +0200 Subject: [PATCH 07/31] fuse results of sub- morphisms in complex morphisms --- src/c_gen.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/c_gen.rs b/src/c_gen.rs index 49c69b5..829b526 100644 --- a/src/c_gen.rs +++ b/src/c_gen.rs @@ -67,6 +67,7 @@ impl LdmcCTargetMorph { 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(), @@ -98,6 +99,7 @@ impl LdmcCTargetMorph { let mut source = String::new(); for inc in self.includes { source.push_str(&inc); + source.push('\n'); } for ty in self.active_types { @@ -175,7 +177,7 @@ impl LdmcCTargetMorph { {{ {} const * restrict src = {}; {} * restrict dst = {}; - {} ( src, dst ); + FUSE( {} ( src, dst ) ); }}"#, src_c_type, src_buf, dst_c_type, dst_buf, @@ -224,7 +226,7 @@ impl LdmcCTargetMorph { {{ {} const * restrict src = (void*) {}; {} * restrict dst = (void*) {}; - {} ( {}, src, dst ); + FUSE( {} ( {}, src, dst ); }}"#, src_c_type, src_buf, dst_c_type, dst_buf, @@ -256,7 +258,7 @@ impl LdmcCTargetMorph { let name = name.replace("-", "_").replace(".","_dot_"); c_source.push_str( &format!(" - {} ( &src->{}, &dst->{} ); + FUSE( {} ( &src->{}, &dst->{} ) ); ", inst.symbol, name, name From 67cec64dfc8e142d1694bb75b050ac60f694c113 Mon Sep 17 00:00:00 2001 From: Michael Sippel <micha@fragmental.art> Date: Wed, 2 Apr 2025 15:01:45 +0200 Subject: [PATCH 08/31] fix codegen for seq-map --- src/c_gen.rs | 75 +++++++++++++++++++++++----------------------------- 1 file changed, 33 insertions(+), 42 deletions(-) diff --git a/src/c_gen.rs b/src/c_gen.rs index 829b526..32b3ef4 100644 --- a/src/c_gen.rs +++ b/src/c_gen.rs @@ -194,56 +194,47 @@ impl LdmcCTargetMorph { }) } MorphismInstance2::MapSeq { ψ, seq_repr, item_morph } => { - let i = 0; // <--todo - self.add_instantiation(dict, item_morph.as_ref().clone()).expect("add instantiation"); - if let Some(seq_repr) = seq_repr { + 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()); - 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 = encode_morph_type_to_symbol(dict, &item_morph.get_haloless_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_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"); - 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"); - let src_c_type = encode_type_to_symbol(dict, &ty.src_type); - let dst_c_type = encode_type_to_symbol(dict, &ty.dst_type); + // todo: self.add_active_length_prefix_map() - // 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, + ); - 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*) {}; - FUSE( {} ( {}, 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 - }) + Ok(LdmcPrimMorph{ + symbol, type_args: Vec::new(), ty, + c_source + }) + } else { + eprintln!("Error: Unknown Seq- Representation!!"); + Err(()) + } } else { - eprintln!("Error: Unknown Seq- Representation!!"); + eprintln!("Error: missing Seq- Representation!!"); Err(()) } } else { - eprintln!("Error: missing Seq- Representation!!"); + eprintln!("failed to add item-morph instantiation"); Err(()) } }, From 3f1397735c507b2eb3aa9c6aeb0deb9e9b0866cc Mon Sep 17 00:00:00 2001 From: Michael Sippel <micha@fragmental.art> Date: Wed, 2 Apr 2025 23:32:06 +0200 Subject: [PATCH 09/31] 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 --- src/c_gen.rs | 253 ++++++++++++++++++++++++++++++++++----------- src/c_gen_types.rs | 16 +++ src/main.rs | 86 +-------------- 3 files changed, 210 insertions(+), 145 deletions(-) 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")); } From ef819b4711771aa1894ffee257be04f3b0e43fdf Mon Sep 17 00:00:00 2001 From: Michael Sippel <micha@fragmental.art> Date: Thu, 3 Apr 2025 16:37:46 +0200 Subject: [PATCH 10/31] morphisms: remove 'return 0;' at end since it is now added by default --- morphisms/angle.morphism-base | 42 +++++---------------------- morphisms/digit.morphism-base | 4 --- morphisms/length_prefix.morphism-base | 6 ---- morphisms/posint.morphism-base | 6 ---- morphisms/real.morphism-base | 41 +++++++++----------------- morphisms/temperature.morphism-base | 20 +++---------- morphisms/timepoint.morphism-base | 1 - morphisms/uint.morphism-base | 17 +++++++++++ morphisms/unicode.morphism-base | 4 --- morphisms/value_delim.morphism-base | 6 ---- morphisms/zigzag.morphism-base | 2 -- 11 files changed, 42 insertions(+), 107 deletions(-) create mode 100644 morphisms/uint.morphism-base diff --git a/morphisms/angle.morphism-base b/morphisms/angle.morphism-base index 5fa3baf..e678dde 100644 --- a/morphisms/angle.morphism-base +++ b/morphisms/angle.morphism-base @@ -5,68 +5,42 @@ morph_angle_as_degrees_to_turns_float () Angle ~ Degrees ~ ℝ ~ native.Float32 --> Angle ~ Turns ~ ℝ ~ native.Float32 -``` - *dst = *src / 360.0; - return 0; -``` +```*dst = *src / 360.0;``` morph_angle_as_degrees_to_turns_double () Angle ~ Degrees ~ ℝ ~ native.Float64 --> Angle ~ Turns ~ ℝ ~ native.Float64 -``` - *dst = *src / 360.0; - return 0; -``` +```*dst = *src / 360.0;``` morph_angle_as_turns_to_degrees_float () Angle ~ Turns ~ ℝ ~ native.Float32 --> Angle ~ Degrees ~ ℝ ~ native.Float32 -``` - *dst = *src * 360.0; - return 0; -``` +```*dst = *src * 360.0;``` morph_angle_as_turns_to_degrees_double () Angle ~ Turns ~ ℝ ~ native.Float64 --> Angle ~ Degrees ~ ℝ ~ native.Float64 -``` - *dst = *src * 360.0; - return 0; -``` - - +```*dst = *src * 360.0;``` morph_angle_as_radians_to_turns_float () Angle ~ Radians ~ ℝ ~ native.Float32 --> Angle ~ Turns ~ ℝ ~ native.Float32 -``` - *dst = *src / PHI; - return 0; -``` +```*dst = *src / PHI;``` morph_angle_as_radians_to_turns_double () Angle ~ Radians ~ ℝ ~ native.Float64 --> Angle ~ Turns ~ ℝ ~ native.Float64 -``` - *dst = *src / PHI; - return 0; -``` +```*dst = *src / PHI;``` morph_angle_as_turns_to_radians_float () Angle ~ Turns ~ ℝ ~ native.Float32 --> Angle ~ Radians ~ ℝ ~ native.Float32 -``` - *dst = *src * PHI; - return 0; -``` +```*dst = *src * PHI;``` morph_angle_as_degrees_to_radians_double () Angle ~ Turns ~ ℝ ~ native.Float64 --> Angle ~ Radians ~ ℝ ~ native.Float64 -``` - *dst = *src * PHI; - return 0; -``` +```*dst = *src * PHI;``` diff --git a/morphisms/digit.morphism-base b/morphisms/digit.morphism-base index a92fe61..f037823 100644 --- a/morphisms/digit.morphism-base +++ b/morphisms/digit.morphism-base @@ -60,8 +60,6 @@ morph_digit_as_uint8_to_char (Radix:ℤ_16) fprintf(stderr, "digit %u is out of rage for char\n", *dst); return -1; } - - return 0; ``` morph_digit_as_uint64_to_char (Radix:ℤ_16) @@ -76,6 +74,4 @@ morph_digit_as_uint64_to_char (Radix:ℤ_16) fprintf(stderr, "digit %u is out of rage for char\n", *dst); return -1; } - - return 0; ``` diff --git a/morphisms/length_prefix.morphism-base b/morphisms/length_prefix.morphism-base index 6718c16..1a1b7f5 100644 --- a/morphisms/length_prefix.morphism-base +++ b/morphisms/length_prefix.morphism-base @@ -10,8 +10,6 @@ morph_array_as_valterm_to_lenpfx (Terminator:native.UInt8) length_prefix_uint64_t_array_uint8_t_clear(dst); while( *src != Terminator ) length_prefix_uint64_t_array_uint8_t_push(dst, *src++); - - return 0; ``` @@ -23,8 +21,6 @@ morph_array_as_lenpfx_to_valterm (Terminator:native.UInt8) *dst++ = src->items[i]; *dst = Terminator; - - return 0; ``` morph_array_as_lenpfx_to_continuation_bit (T:Type) @@ -42,6 +38,4 @@ morph_array_as_lenpfx_to_continuation_bit (T:Type) if( i+1 < src->len ) dst[i] |= (1<<(n_bits-1)); } - - return 0; ``` diff --git a/morphisms/posint.morphism-base b/morphisms/posint.morphism-base index 194399b..01248eb 100644 --- a/morphisms/posint.morphism-base +++ b/morphisms/posint.morphism-base @@ -11,7 +11,6 @@ morph_nat_as_u64_to_pos () ``` dst->len = 1; dst->items[0] = *src; - return 0; ``` morph_nat_as_pos_to_u64 (Endianness:Type) @@ -22,7 +21,6 @@ morph_nat_as_pos_to_u64 (Endianness:Type) ~ native.UInt64 ``` *dst = src->items[0]; - return 0; ``` morph_posint_radix_le (SrcRadix:ℤ, DstRadix:ℤ) @@ -52,8 +50,6 @@ morph_posint_radix_le (SrcRadix:ℤ, DstRadix:ℤ) value /= DstRadix; } #endif - - return 0; ``` morph_posint_radix_be (SrcRadix:ℤ, DstRadix:ℤ) @@ -91,8 +87,6 @@ morph_posint_radix_be (SrcRadix:ℤ, DstRadix:ℤ) value /= DstRadix; } #endif - - return 0; ``` morph_posint_endianness (Radix:ℤ) diff --git a/morphisms/real.morphism-base b/morphisms/real.morphism-base index 4add278..5b5b2f7 100644 --- a/morphisms/real.morphism-base +++ b/morphisms/real.morphism-base @@ -5,43 +5,27 @@ morph_real_as_decimalstr_to_float () ℝ ~ <PosInt 10 BigEndian> ~ <Seq~<ValueTerminated 0> <Digit 10>~Char~Ascii~native.UInt8> --> ℝ ~ native.Float32 -``` - sscanf(src, "%f", dst); - return 0; -``` +```sscanf(src, "%f", dst);``` morph_real_as_decimalstr_to_double () ℝ ~ <PosInt 10 BigEndian> ~ <Seq~<ValueTerminated 0> <Digit 10>~Char~Ascii~native.UInt8> --> ℝ ~ native.Float64 -``` - sscanf(src, "%lf", dst); - return 0; -``` +```sscanf(src, "%lf", dst);``` morph_real_as_float_to_decimalstr () ℝ ~ native.Float32 --> ℝ ~ <PosInt 10 BigEndian> ~ <Seq~<ValueTerminated 0> <Digit 10>~Char~Ascii~native.UInt8> -``` - sprintf(dst, "%f", *src); - return 0; -``` +```sprintf(dst, "%f", *src);``` morph_real_as_double_to_decimalstr () ℝ ~ native.Float64 --> ℝ ~ <PosInt 10 BigEndian> ~ <Seq~<ValueTerminated 0> <Digit 10>~Char~Ascii~native.UInt8> -``` - sprintf(dst, "%f", *src); - return 0; -``` - +```sprintf(dst, "%f", *src);``` morph_real_as_float_to_double () ℝ ~ native.Float32 --> ℝ ~ native.Float64 -``` - *dst = *src; - return 0; -``` +```*dst = *src;``` morph_real_as_double_to_float () ℝ ~ native.Float64 @@ -49,7 +33,6 @@ morph_real_as_double_to_float () ``` fprintf(stderr, "Warning: morphin Double -> Float. Precision loss!"); *dst = *src; - return 0; ``` morph_real_as_u64_to_float () @@ -58,7 +41,6 @@ morph_real_as_u64_to_float () ``` fprintf(stderr, "Warning: morphin UInt64 -> Float. Precision loss!"); *dst = *src; - return 0; ``` morph_real_as_u64_to_double () @@ -67,7 +49,14 @@ morph_real_as_u64_to_double () ``` fprintf(stderr, "Warning: morphin UInt64 -> Double. Precision loss!"); *dst = *src; - return 0; +``` + + +morph_real_as_nat_to_quantized_linear () + ℝ ~ ℕ ~ native.UInt64 +--> ℝ ~ <QuantizedLinear 0 1 1> ~ ℕ ~ native.UInt64 +``` + *dst = *src; ``` morph_real_as_quantized_linear_to_float (Begin: ℝ, End: ℝ, Steps: ℤ) @@ -75,7 +64,6 @@ morph_real_as_quantized_linear_to_float (Begin: ℝ, End: ℝ, Steps: ℤ) --> ℝ ~ native.Float32 ``` *dst = (float)Begin + ( *src * ((float)End - (float)Begin) ) / (float)Steps; - return 0; ``` morph_real_as_float_to_quantized_linear (Begin: ℝ, End: ℝ, Steps: ℤ) @@ -83,7 +71,6 @@ morph_real_as_float_to_quantized_linear (Begin: ℝ, End: ℝ, Steps: ℤ) --> ℝ ~ <QuantizedLinear Begin End Steps> ~ ℕ ~ native.UInt64 ``` *dst = ((*src - (float)Begin) * (float)Steps) / ((float)End - (float)Begin); - return 0; ``` @@ -93,7 +80,6 @@ morph_real_as_quantized_linear_to_double (Begin: ℝ, End: ℝ, Steps: ℤ) --> ℝ ~ native.Float64 ``` *dst = (double)Begin + ( *src * ((double)End - (double)Begin) ) / (double)Steps; - return 0; ``` morph_real_as_double_to_quantized_linear (Begin: ℝ, End: ℝ, Steps: ℤ) @@ -101,5 +87,4 @@ morph_real_as_double_to_quantized_linear (Begin: ℝ, End: ℝ, Steps: ℤ) --> ℝ ~ <QuantizedLinear Begin End Steps> ~ ℕ ~ native.UInt64 ``` *dst = ((*src - (double)Begin) * (double)Steps) / ((double)End - (double)Begin); - return 0; ``` diff --git a/morphisms/temperature.morphism-base b/morphisms/temperature.morphism-base index 6c682bc..329a6b0 100644 --- a/morphisms/temperature.morphism-base +++ b/morphisms/temperature.morphism-base @@ -4,31 +4,19 @@ morph_celsius_to_kelvin () Temperature ~ Celsius ~ ℝ ~ native.Float32 --> Temperature ~ Kelvin ~ ℝ ~ native.Float32 -``` - *dst = *src + 273.15; - return 0; -``` +```*dst = *src + 273.15;``` morph_kelvin_to_celsius () Temperature ~ Kelvin ~ ℝ ~ native.Float32 --> Temperature ~ Celsius ~ ℝ ~ native.Float32 -``` - *dst = *src - 273.15; - return 0; -``` +```*dst = *src - 273.15;``` morph_celsius_to_fahrenheit () Temperature ~ Celsius ~ ℝ ~ native.Float32 --> Temperature ~ Fahrenheit ~ ℝ ~ native.Float32 -``` - *dst = (*src * 9.0 / 5.0) + 32.0; - return 0; -``` +```*dst = (*src * 9.0 / 5.0) + 32.0;``` morph_fahrenheit_to_celsius () Temperature ~ Fahrenheit ~ ℝ ~ native.Float32 --> Temperature ~ Celsius ~ ℝ ~ native.Float32 -``` - *dst = (*src - 32.0) * 5.0 / 9.0; - return 0; -``` +```*dst = (*src - 32.0) * 5.0 / 9.0;``` diff --git a/morphisms/timepoint.morphism-base b/morphisms/timepoint.morphism-base index bb66aec..505ed37 100644 --- a/morphisms/timepoint.morphism-base +++ b/morphisms/timepoint.morphism-base @@ -11,5 +11,4 @@ morph_unixtime_to_iso () if (!timeinfo) return -1; strftime((char*)dst, 20, "%Y-%m-%dT%H:%M:%SZ", timeinfo); - return 0; ``` diff --git a/morphisms/uint.morphism-base b/morphisms/uint.morphism-base new file mode 100644 index 0000000..89f8f79 --- /dev/null +++ b/morphisms/uint.morphism-base @@ -0,0 +1,17 @@ +``` +``` + +morph_nat_as_u8_to_u16 () + ℕ ~ native.UInt8 +--> ℕ ~ native.UInt16 +```*dst = *src;``` + +morph_nat_as_u16_to_u32 () + ℕ ~ native.UInt16 +--> ℕ ~ native.UInt32 +```*dst = *src;``` + +morph_nat_as_u32_to_u64 () + ℕ ~ native.UInt32 +--> ℕ ~ native.UInt64 +```*dst = *src;``` diff --git a/morphisms/unicode.morphism-base b/morphisms/unicode.morphism-base index c2854e5..659357b 100644 --- a/morphisms/unicode.morphism-base +++ b/morphisms/unicode.morphism-base @@ -28,7 +28,6 @@ morph_string_as_utf8_to_ascii () } } *dst = 0; - return 0; ``` morph_string_as_ascii_to_utf32 () @@ -39,7 +38,6 @@ morph_string_as_ascii_to_utf32 () ``` while( *src ) { *dst++ = *src++; } *dst = 0; - return 0; ``` morph_string_as_utf8_to_utf32 () @@ -89,6 +87,4 @@ morph_string_as_utf8_to_utf32 () *dst++ = val; *dst++ = 0; - - return 0; ``` diff --git a/morphisms/value_delim.morphism-base b/morphisms/value_delim.morphism-base index a370682..ab66310 100644 --- a/morphisms/value_delim.morphism-base +++ b/morphisms/value_delim.morphism-base @@ -27,8 +27,6 @@ morph_seqseq_valsep_uint8 (T: Type, SrcDelim: T, DstDelim: T) length_prefix_uint64_t_array_uint8_t_push( dst, src->items[i] ); } } - - return 0; ``` @@ -66,8 +64,6 @@ morph_seqseq_as_valsep_to_lenpfx (T: Type, Delim: T, EscKey: T) cur++; } } - - return 0; ``` morph_seqeq_as_lenpfx_to_valsep (T: Type, Delim: T, EscKey: T) @@ -94,6 +90,4 @@ morph_seqeq_as_lenpfx_to_valsep (T: Type, Delim: T, EscKey: T) length_prefix_uint64_t_array_uint8_t_push( Delim ); } } - - return 0; ``` diff --git a/morphisms/zigzag.morphism-base b/morphisms/zigzag.morphism-base index 5a293e2..4196e72 100644 --- a/morphisms/zigzag.morphism-base +++ b/morphisms/zigzag.morphism-base @@ -10,8 +10,6 @@ morph_i64_as_twos_complement_to_zigzag () } else { *dst = (2 * (uint64_t)(- *src)) - 1; } - - return 0; ``` morph_i64_as_zigzag_to_twos_complement () From 6787e607a67dd30482b963660a9a15a34e2d5d96 Mon Sep 17 00:00:00 2001 From: Michael Sippel <micha@fragmental.art> Date: Thu, 1 May 2025 06:38:17 +0200 Subject: [PATCH 11/31] wip --- .../runtime/include/array/length-prefix.h | 61 +---- src/c_gen.rs | 223 +++++++++++------- src/c_gen_types.rs | 148 ++++++------ src/main.rs | 7 +- src/morphism.rs | 170 +------------ src/parser.rs | 8 +- src/struct_layout.rs | 44 ++-- 7 files changed, 240 insertions(+), 421 deletions(-) diff --git a/morphisms/runtime/include/array/length-prefix.h b/morphisms/runtime/include/array/length-prefix.h index 35a4aec..3f039f2 100644 --- a/morphisms/runtime/include/array/length-prefix.h +++ b/morphisms/runtime/include/array/length-prefix.h @@ -7,22 +7,22 @@ typedef struct { \ LEN_TYPE len; \ ITEM_TYPE items[]; \ - } LengthPrefix_##LEN_TYPE##_Array_##ITEM_TYPE; \ + } __Seq__LengthPrefix_##LEN_TYPE##___##ITEM_TYPE##_; \ \ static inline void length_prefix_##LEN_TYPE##_array_##ITEM_TYPE##_clear( \ - LengthPrefix_##LEN_TYPE##_Array_##ITEM_TYPE *data) { \ + __Seq__LengthPrefix_##LEN_TYPE##___##ITEM_TYPE##_ *data) { \ data->len = 0; \ } \ \ static inline void length_prefix_##LEN_TYPE##_array_##ITEM_TYPE##_push( \ - LengthPrefix_##LEN_TYPE##_Array_##ITEM_TYPE *data, \ + __Seq__LengthPrefix_##LEN_TYPE##___##ITEM_TYPE##_ *data, \ ITEM_TYPE value) { \ data->items[data->len++] = value; \ } \ \ static inline int length_prefix_##LEN_TYPE##_array_##ITEM_TYPE##_reverse( \ - LengthPrefix_##LEN_TYPE##_Array_##ITEM_TYPE const * restrict src, \ - LengthPrefix_##LEN_TYPE##_Array_##ITEM_TYPE *restrict dst) { \ + __Seq__LengthPrefix_##LEN_TYPE##___##ITEM_TYPE##_ const * restrict src, \ + __Seq__LengthPrefix_##LEN_TYPE##___##ITEM_TYPE##_ *restrict dst) { \ for (LEN_TYPE i = 0; i < src->len; i++) { \ dst->items[i] = src->items[src->len - 1 - i]; \ } \ @@ -31,59 +31,10 @@ } \ \ static inline void length_prefix_##LEN_TYPE##_array_##ITEM_TYPE##_dump( \ - LengthPrefix_##LEN_TYPE##_Array_##ITEM_TYPE const * data) { \ + __Seq__LengthPrefix_##LEN_TYPE##___##ITEM_TYPE##_ const * data) { \ printf("Length: %llu\n", (unsigned long long) data->len); \ for (LEN_TYPE i = 0; i < data->len; i++) { \ printf("%llu ", (unsigned long long) data->items[i]); \ } \ printf("\n"); \ } - -#define DEFINE_ALL_LENGTH_PREFIX_ARRAYS(LEN_TYPE) \ - DEFINE_LENGTH_PREFIX_ARRAY(LEN_TYPE, uint8_t) \ - DEFINE_LENGTH_PREFIX_ARRAY(LEN_TYPE, uint16_t) \ - DEFINE_LENGTH_PREFIX_ARRAY(LEN_TYPE, uint32_t) \ - DEFINE_LENGTH_PREFIX_ARRAY(LEN_TYPE, uint64_t) - -DEFINE_ALL_LENGTH_PREFIX_ARRAYS(uint8_t) -DEFINE_ALL_LENGTH_PREFIX_ARRAYS(uint16_t) -DEFINE_ALL_LENGTH_PREFIX_ARRAYS(uint32_t) -DEFINE_ALL_LENGTH_PREFIX_ARRAYS(uint64_t) - - -#define DEFINE_LENGTH_PREFIX_ARRAY_MAP(LEN_TYPE, SRC_ITEM_TYPE, DST_ITEM_TYPE) \ - static inline int length_prefix_##LEN_TYPE##_array_map_##SRC_ITEM_TYPE##_to_##DST_ITEM_TYPE( \ - int (*f)(SRC_ITEM_TYPE const * restrict, DST_ITEM_TYPE * restrict), \ - LengthPrefix_##LEN_TYPE##_Array_##SRC_ITEM_TYPE const * restrict src, \ - LengthPrefix_##LEN_TYPE##_Array_##DST_ITEM_TYPE * restrict dst) \ - { \ - if (dst->len < src->len) return -1; /* Ensure enough space */ \ - for (LEN_TYPE i = 0; i < src->len; i++) { \ - if (f(&src->items[i], &dst->items[i]) != 0) return -1; \ - } \ - dst->len = src->len; \ - return 0; \ - } - -#define DEFINE_ALL_MAPS(LEN_TYPE) \ - DEFINE_LENGTH_PREFIX_ARRAY_MAP(LEN_TYPE, uint8_t, uint8_t) \ - DEFINE_LENGTH_PREFIX_ARRAY_MAP(LEN_TYPE, uint8_t, uint16_t) \ - DEFINE_LENGTH_PREFIX_ARRAY_MAP(LEN_TYPE, uint8_t, uint32_t) \ - DEFINE_LENGTH_PREFIX_ARRAY_MAP(LEN_TYPE, uint8_t, uint64_t) \ - DEFINE_LENGTH_PREFIX_ARRAY_MAP(LEN_TYPE, uint16_t, uint8_t) \ - DEFINE_LENGTH_PREFIX_ARRAY_MAP(LEN_TYPE, uint16_t, uint16_t) \ - DEFINE_LENGTH_PREFIX_ARRAY_MAP(LEN_TYPE, uint16_t, uint32_t) \ - DEFINE_LENGTH_PREFIX_ARRAY_MAP(LEN_TYPE, uint16_t, uint64_t) \ - DEFINE_LENGTH_PREFIX_ARRAY_MAP(LEN_TYPE, uint32_t, uint8_t) \ - DEFINE_LENGTH_PREFIX_ARRAY_MAP(LEN_TYPE, uint32_t, uint16_t) \ - DEFINE_LENGTH_PREFIX_ARRAY_MAP(LEN_TYPE, uint32_t, uint32_t) \ - DEFINE_LENGTH_PREFIX_ARRAY_MAP(LEN_TYPE, uint32_t, uint64_t) \ - DEFINE_LENGTH_PREFIX_ARRAY_MAP(LEN_TYPE, uint64_t, uint8_t) \ - DEFINE_LENGTH_PREFIX_ARRAY_MAP(LEN_TYPE, uint64_t, uint16_t) \ - DEFINE_LENGTH_PREFIX_ARRAY_MAP(LEN_TYPE, uint64_t, uint32_t) \ - DEFINE_LENGTH_PREFIX_ARRAY_MAP(LEN_TYPE, uint64_t, uint64_t) - -DEFINE_ALL_MAPS(uint8_t) -DEFINE_ALL_MAPS(uint16_t) -DEFINE_ALL_MAPS(uint32_t) -DEFINE_ALL_MAPS(uint64_t) diff --git a/src/c_gen.rs b/src/c_gen.rs index 41d1c99..0f21ef8 100644 --- a/src/c_gen.rs +++ b/src/c_gen.rs @@ -1,9 +1,16 @@ use { - 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 + crate::{c_gen_types::{encode_morph_type_to_symbol, encode_type_to_value, get_c_repr_arg_type, + get_c_repr_definition, get_c_repr_type}, morphism::LdmcPrimMorph, + struct_layout::{get_type_size, LayoutType, ObjectSize, StructLayout}}, + chumsky::{chain::Chain, primitive::Container}, + laddertypes::{morphism::{MorphismInstance, Morphism, MorphismType}, + parser::*, substitution::Substitution, unparser::*, + EnumVariant, StructMember, TypeTerm, TypeDict, DesugaredTypeTerm}, + std::collections::HashMap }; impl LdmcPrimMorph { - pub fn instantiated_symbol_name(&self, dict: &mut impl TypeDict, σ: &impl SugaredSubstitution) -> String { + pub fn instantiated_symbol_name(&self, dict: &mut impl TypeDict, σ: &impl Substitution) -> String { let mut s = self.symbol.clone(); for (k_id,v) in self.type_args.iter() { @@ -14,7 +21,7 @@ impl LdmcPrimMorph { //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); + let val_str = get_c_repr_type(dict, &val_trm); s.push_str(&format!("_{}_{}", name, val_str)); //} @@ -31,20 +38,26 @@ impl LdmcPrimMorph { } pub fn expected_c_type_signature(&self, dict: &mut impl TypeDict, - σ: &std::collections::HashMap<laddertypes::TypeID, laddertypes::SugaredTypeTerm> + σ: &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.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")) + get_c_repr_definition(dict, self.ty.src_type.clone(), true).expect("cant get c-repr type for src type"), + get_c_repr_definition(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> { + pub fn generate_instantiation(&self, dict: &mut impl TypeDict, σ: &impl Substitution) -> Option<String> { let mut s = String::new(); let symbol = self.instantiated_symbol_name(dict, σ); - 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); + eprintln!("generate instantiation:"); + let ty = self.ty.clone(); + eprintln!("full type: {} ----> {}", ty.src_type.pretty(dict, 0), ty.dst_type.pretty(dict,0)); + let ty = ty.strip_halo().apply_subst(σ); + eprintln!("stripped type: {} ----> {}", ty.src_type.pretty(dict, 0), ty.dst_type.pretty(dict,0)); + + let src_c_symbol = get_c_repr_arg_type(dict, &ty.src_type); + let dst_c_symbol = get_c_repr_arg_type(dict, &ty.dst_type); s.push_str(&format!(r#" int {} ( {} const * restrict src, {} * restrict dst ) {{ @@ -66,8 +79,9 @@ int {} ( {} const * restrict src, {} * restrict dst ) {{ pub struct LdmcCTargetMorph { includes: Vec< String >, - active_types: Vec< SugaredTypeTerm >, + active_types: Vec< TypeTerm >, active_instantiations: Vec< LdmcPrimMorph >, + macro_calls: Vec< String > } impl LdmcCTargetMorph { @@ -75,18 +89,42 @@ impl LdmcCTargetMorph { LdmcCTargetMorph { includes: vec![ "#include <stdint.h>".into(), + "#include <array/length-prefix.h>".into(), "#define FUSE(morph, src, dst) { int result = morph(src,dst); if(result) return result; }".into(), ], active_instantiations: Vec::new(), active_types: Vec::new(), + macro_calls: Vec::new() } } - pub fn add_type(&mut self, ty: SugaredTypeTerm) { + pub fn add_type(&mut self, dict: &mut impl TypeDict, ty: TypeTerm) { + let ty = ty.strip(); if ! self.active_types.contains(&ty) { + eprintln!("add type {:?}", ty); match &ty { - SugaredTypeTerm::Seq { seq_repr, items } =>{ - self.add_type(items.first().unwrap().clone()); + TypeTerm::Seq { seq_repr, items } =>{ + let item_type = items.first().unwrap().clone(); + self.add_type(dict, item_type.clone()); + + if let Some(seq_repr) = seq_repr { + dict.add_varname("LengthType".into()); + if let Ok(σ) = + laddertypes::constraint_system::unify( + seq_repr.as_ref(), + &dict.parse_desugared("<LengthPrefix LengthType>").expect("").sugar(dict) + ) + { + let length_type = σ.get(&dict.get_typeid(&"LengthType".into()).expect("")).expect("cant get Length type"); + self.add_type(dict, length_type.clone()); + self.macro_calls.push( + format!("DEFINE_LENGTH_PREFIX_ARRAY({}, {})\n", + get_c_repr_type(dict, &length_type), + get_c_repr_type(dict, &item_type) + ) + ); + } + } } _=>{} } @@ -97,7 +135,7 @@ impl LdmcCTargetMorph { pub fn add_instantiation( &mut self, dict: &mut impl TypeDict, - morph: MorphismInstance2<LdmcPrimMorph>, + morph: MorphismInstance<LdmcPrimMorph>, ) -> Result<LdmcPrimMorph, ()> { let new_inst = self.bake_morphism(dict, morph)?; if ! self.active_instantiations.contains(&new_inst) { @@ -105,44 +143,58 @@ impl LdmcCTargetMorph { } let ty = new_inst.get_type().strip_halo(); - self.add_type(ty.src_type.get_floor_type().1); - self.add_type(ty.dst_type.get_floor_type().1); + self.add_type(dict, ty.src_type); + self.add_type(dict, ty.dst_type); Ok(new_inst) } - pub fn into_c_source(self, dict: &mut impl TypeDict) -> String { + pub fn into_c_source(mut self, dict: &mut impl TypeDict) -> String { let mut source = String::new(); + self.includes.dedup(); + self.macro_calls.dedup(); + self.active_types.dedup(); + for inc in self.includes { source.push_str(&inc); source.push('\n'); } + source.push('\n'); + for ty in self.active_types { - source.push_str(&format!(" - typedef {} {}; -", - 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))); + if let Some(type_def) = get_c_repr_definition(dict, ty.clone(), false) { + let type_name = get_c_repr_type(dict, &ty); + source.push_str(&format!("typedef {} {};\n", type_def, type_name)); + } else { + eprintln!("cant get c-repr type for type '{}'", ty.pretty(dict,0)); + } } + source.push('\n'); + + + for m in self.macro_calls { + source.push_str(&m); + source.push('\n'); + } + source.push('\n'); 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>, + morph_inst: MorphismInstance<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)); + let ty = morph_inst.get_type(); + let symbol = encode_morph_type_to_symbol(dict, &ty); match &morph_inst { - MorphismInstance2::Primitive { ψ, σ, morph } => { + MorphismInstance::Primitive { ψ, σ, morph } => { let mut c_source = String::new(); for (ty_id, kind) in morph.type_args.iter() { if let laddertypes::TypeID::Var(var_id) = ty_id { @@ -150,7 +202,7 @@ impl LdmcCTargetMorph { //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) { + if let Some(c_repr_type) = get_c_repr_definition(dict, val.clone(), true) { c_repr_type } else { encode_type_to_value(dict, &val) @@ -179,10 +231,7 @@ impl LdmcCTargetMorph { c_source }) }, - MorphismInstance2::Chain { path } => { - let ty = morph_inst.get_type().strip_halo(); - let symbol = encode_morph_type_to_symbol(dict, &ty); - + MorphismInstance::Chain { path } => { let mut c_source = String::new(); if path.len() > 1 { @@ -195,8 +244,8 @@ impl LdmcCTargetMorph { 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_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" }; + let src_buf = if i == 0 { "(void*)src" } else if i%2 == 0 { "(void*)bufA" } else { "(void*)bufB" }; + let dst_buf = if i+1 == path.len() { "(void*)dst" } else if i%2 == 0 { "(void*)bufB" } else { "(void*)bufA" }; c_source.push_str(&format!(r#" FUSE( {}, {}, {} );"#, @@ -213,30 +262,28 @@ impl LdmcCTargetMorph { c_source }) } - MorphismInstance2::MapSeq { ψ, seq_repr, item_morph } => { + MorphismInstance::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), + if let Ok(γ) = laddertypes::constraint_system::unify( + &dict.parse_desugared("<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()); + TypeTerm::Num(l) => { 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 ); + self.add_type( dict, morph_inst.get_type().strip_halo().src_type ); + self.add_type( dict, 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] ); + FUSE( {}, &src->items[i], &dst->items[i] ); }} "#, l, @@ -255,19 +302,16 @@ impl LdmcCTargetMorph { } } - else if let Ok(γ) = laddertypes::unification_sugared::unify( - &dict.parse("<LengthPrefix LengthType>").expect("parse type template").sugar(dict), + else if let Ok(γ) = laddertypes::constraint_system::unify( + &dict.parse_desugared("<LengthPrefix LengthType>").expect("parse type template").sugar(dict), seq_repr.as_ref() ) { // 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_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 ); + self.add_type( dict, morph_inst.get_type().strip_halo().src_type ); + self.add_type( dict, morph_inst.get_type().strip_halo().dst_type ); let c_source = format!(r#" for( size_t i = 0; i < src->len; ++i ) {{ @@ -284,13 +328,11 @@ impl LdmcCTargetMorph { }) } - else if let Ok(γ) = laddertypes::unification_sugared::unify( - &dict.parse("<ValueTerminated TerminatorValue>").expect("parse type template").sugar(dict), + else if let Ok(γ) = laddertypes::constraint_system::unify( + &dict.parse_desugared("<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); @@ -326,9 +368,7 @@ impl LdmcCTargetMorph { 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()); + MorphismInstance::MapStruct { ψ, src_struct_repr, dst_struct_repr, member_morph } => { let mut c_source = String::new(); @@ -337,8 +377,7 @@ impl LdmcCTargetMorph { let name = name.replace("-", "_").replace(".","_dot_"); c_source.push_str( &format!(" - FUSE( {}, &src->{}, &dst->{} ); - ", + FUSE( {}, &src->{}, &dst->{} );", inst.symbol, name, name )); @@ -354,49 +393,53 @@ impl LdmcCTargetMorph { c_source }) } - MorphismInstance2::MapEnum { ψ, enum_repr, variant_morph } => { + MorphismInstance::MapEnum { ψ, enum_repr, variant_morph } => { todo!(); } } } } -pub fn generate_main(dict: &mut impl TypeDict, morph: MorphismInstance2<LdmcPrimMorph>) -> Result<String, ()> { +pub fn generate_main(dict: &mut impl TypeDict, morph: MorphismInstance<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); + match target.add_instantiation(dict, morph) { + Ok(inst) => { + let mut c_source = target.into_c_source(dict); - c_source.push_str(&format!(r#" - #include <unistd.h> + c_source.push_str(&format!(r#" + #include <unistd.h> - int main() {{ - uint8_t bufIn[4096]; - uint8_t bufOut[4096];"#)); + 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));"); + let (src_top, src_floor) = ty.src_type.get_floor_type(); + if src_floor == dict.parse_desugared("<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::constraint_system::subtype_unify( + &ty.src_type, + &dict.parse_desugared("<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) } - - 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));"); + Err(err) => { + eprintln!("failed to create morphism instatiation"); + Err(()) } - 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 0fb3b0d..8c366bb 100644 --- a/src/c_gen_types.rs +++ b/src/c_gen_types.rs @@ -1,5 +1,9 @@ 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} + crate::{morphism::LdmcPrimMorph, struct_layout::{get_type_size, LayoutType, ObjectSize, StructLayout}}, + chumsky::chain::Chain, laddertypes::{morphism::{MorphismInstance, MorphismType}, + parser::*, + substitution::Substitution, + unparser::*, EnumVariant, StructMember, TypeTerm, TypeDict, DesugaredTypeTerm}, std::thread::yield_now }; /* @@ -13,9 +17,9 @@ pub fn get_c_repr_kind(kind: String) -> Option<String> { /* 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> { - match t.get_floor_type().1.strip() { - SugaredTypeTerm::TypeID(tyid) => { +pub fn get_c_repr_definition(dict: &mut impl TypeDict, t: TypeTerm, skip_pointer: bool) -> Option<String> { + match t { + TypeTerm::TypeID(tyid) => { if tyid == dict.get_typeid_creat("native.UInt8") { Some("uint8_t".into()) } else if tyid == dict.get_typeid_creat("native.UInt16") { @@ -35,20 +39,18 @@ pub fn get_c_repr_type(dict: &mut impl TypeDict, t: SugaredTypeTerm, skip_pointe } } - SugaredTypeTerm::Seq{ seq_repr, items } => { - if let Some(sr_sugar) = seq_repr { - let sr = sr_sugar.desugar(dict); - + TypeTerm::Seq{ seq_repr, items } => { + if let Some(seq_repr) = seq_repr { 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"); + let item_c_type : String = get_c_repr_type(dict, &item_type); 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") + if let Ok((ψ, σ)) = laddertypes::constraint_system::subtype_unify( + seq_repr.as_ref(), + &dict.parse_desugared("<StaticLength Length>").expect("parse template type").sugar(dict) ) { let length = match σ.get( @@ -61,46 +63,23 @@ pub fn get_c_repr_type(dict: &mut impl TypeDict, t: SugaredTypeTerm, skip_pointe return None; } }; - Some(format!("{}[{}]", item_c_type, length)) + Some(format!("struct {{ {} items[{}]; }} ", item_c_type, length)) } - else if let Ok(σ) = laddertypes::unify( - &sr, - &dict.parse("<LengthPrefix LengthType>").expect("parse") + else if let Ok((ψ, σ)) = laddertypes::constraint_system::subtype_unify( + seq_repr.as_ref(), + &dict.parse_desugared("<LengthPrefix LengthType>").expect("parse template type").sugar(dict) ) { 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"); + ).expect("no length type specified"); - 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; - } - } + let length_c_type = get_c_repr_type(dict, &length_type); - Some(format!("LengthPrefix_{}_Array_{}", length_c_type, item_c_type)) + Some(format!("struct {{ {} len; {} items[]; }} ", length_c_type, item_c_type)) } - else if let Ok(σ) = laddertypes::unify( - &sr, - &dict.parse("<ValueTerminated TermValue>").expect("") + else if let Ok((ψ, σ)) = laddertypes::constraint_system::subtype_unify( + seq_repr.as_ref(), + &dict.parse_desugared("<ValueTerminated TermValue>").expect("parse template type").sugar(dict) ) { if skip_pointer { Some(item_c_type) @@ -109,7 +88,7 @@ pub fn get_c_repr_type(dict: &mut impl TypeDict, t: SugaredTypeTerm, skip_pointe } } else { - eprintln!("can't get C-repr for sequence type `{}`!", dict.unparse(&sr)); + eprintln!("can't get C-repr for sequence type `{}`!", seq_repr.pretty(dict, 0)); None } } else { @@ -118,7 +97,7 @@ pub fn get_c_repr_type(dict: &mut impl TypeDict, t: SugaredTypeTerm, skip_pointe } } - SugaredTypeTerm::Struct{ struct_repr, members } => { + TypeTerm::Struct{ struct_repr, members } => { let c_struct_attribute = if let Some(sr) = struct_repr { let sr = sr.desugar(dict); @@ -130,8 +109,8 @@ pub fn get_c_repr_type(dict: &mut impl TypeDict, t: SugaredTypeTerm, skip_pointe 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(""); + for StructMember{ symbol, ty } in members { + let field_c_type = get_c_repr_definition(dict, ty, false).expect(""); c_type.push_str(&format!(" {} {};\n", field_c_type, symbol.replace("-", "_").replace(".","_dot_") @@ -142,13 +121,13 @@ pub fn get_c_repr_type(dict: &mut impl TypeDict, t: SugaredTypeTerm, skip_pointe Some(c_type) } - SugaredTypeTerm::Enum { enum_repr, variants } => { + TypeTerm::Enum { enum_repr, variants } => { let mut c_type = format!(" struct {{ enum {{ "); - for (i, SugaredEnumVariant{ symbol, ty }) in variants.iter().enumerate() { + for (i, EnumVariant{ symbol, ty }) in variants.iter().enumerate() { c_type.push_str(&format!( " {} = {}", symbol.replace("-", "_").replace(".","_dot_").to_uppercase(), i )); @@ -164,8 +143,8 @@ struct {{ 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"); + for EnumVariant{ symbol, ty } in variants { + let variant_c_type = get_c_repr_definition(dict, ty, false).expect("cant get C-Repr type for variant"); c_type.push_str(&format!( " {} {};\n", variant_c_type, symbol.replace("-", "_").replace(".","_dot_") )); @@ -178,9 +157,9 @@ struct {{ Some(c_type) } - SugaredTypeTerm::Ladder(rungs) => { + TypeTerm::Ladder(rungs) => { if let Some(t) = rungs.last() { - get_c_repr_type(dict, t.clone(), false) + get_c_repr_definition(dict, t.clone(), false) } else { None } @@ -190,10 +169,11 @@ struct {{ } } -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) => { +pub fn get_c_repr_type(dict: &mut impl TypeDict, t: &laddertypes::TypeTerm)-> String { + let t = t.clone().strip(); + + match t.desugar(dict) { + laddertypes::DesugaredTypeTerm::Char(c) => { match c { '.' => format!("_dot_"), '-' => format!("_minus_"), @@ -201,57 +181,61 @@ pub fn encode_type_to_symbol(dict: &mut impl TypeDict, t: &laddertypes::SugaredT format!("{}", (c as u64)) } }, - laddertypes::TypeTerm::Num(n) => { + laddertypes::DesugaredTypeTerm::Num(n) => { format!("{}", n) } - laddertypes::TypeTerm::TypeID(ty_id) => { + laddertypes::DesugaredTypeTerm::TypeID(ty_id) => { if let Some(name) = dict.get_typename(&ty_id) { name .replace("-", "_") - .replace(".", "_dot_") + .replace(".", "") } else { format!("") } } - laddertypes::TypeTerm::Ladder(rs) | - laddertypes::TypeTerm::App(rs) => { + laddertypes::DesugaredTypeTerm::Ladder(rs) | + laddertypes::DesugaredTypeTerm::App(rs) => { let mut s = String::new(); + s.push('_'); for r in rs { - s.push('_'); - let r = r.sugar(dict); - s.push_str(&encode_type_to_symbol(dict, &r)); + s.push_str(&get_c_repr_type(dict, &r)); + s.push('_'); } s } } } -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()); +pub fn get_c_repr_arg_type(dict: &mut impl TypeDict, t: &laddertypes::TypeTerm)-> String { + let t = t.clone().strip().get_floor_type().1; + dict.add_varname("TerminatorValue".into()); + match &t { + TypeTerm::Seq { seq_repr, items } => { + if let Some(seq_repr) = seq_repr.as_ref() { + if let Ok(ψ) = laddertypes::constraint_system::subtype_unify( + seq_repr, + &dict.parse_desugared("<ValueTerminated TerminatorValue>").expect("").sugar(dict) + ) { + return get_c_repr_type(dict, &items[0].clone().strip().get_floor_type().1); } } } - _=>{} - } - encode_type_to_symbol(dict, t) + _ => {} + } + get_c_repr_type(dict, &t) } -pub fn encode_morph_type_to_symbol(dict: &mut impl TypeDict, t: &SugaredMorphismType) -> String { +pub fn encode_morph_type_to_symbol(dict: &mut impl TypeDict, t: &MorphismType) -> String { format!( - "morph_{}__to_{}", - encode_type_to_symbol(dict, &t.src_type), - encode_type_to_symbol(dict, &t.dst_type) + "morph__{}___TO__{}", + get_c_repr_type(dict, &t.strip_halo().src_type), + get_c_repr_type(dict, &t.strip_halo().dst_type) ) } -pub fn encode_type_to_value(dict: &mut impl TypeDict, t: &laddertypes::SugaredTypeTerm) -> String { +pub fn encode_type_to_value(dict: &mut impl TypeDict, t: &laddertypes::TypeTerm) -> String { let t = t.clone().desugar(dict); dict.unparse(&t) } diff --git a/src/main.rs b/src/main.rs index df68e51..1e418d4 100644 --- a/src/main.rs +++ b/src/main.rs @@ -11,14 +11,15 @@ use { morphism::LdmcPrimMorph, parser::morphism_base_parser, }, 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 + morphism_path::ShortestPathProblem, morphism::{MorphismInstance, Morphism, MorphismType}, + parser::ParseLadderType, unparser::*, BimapTypeDict, TypeTerm, 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_sugared::SugaredMorphismBase::<LdmcPrimMorph>::new(); + let mut morphism_base = laddertypes::morphism_base::MorphismBase::<LdmcPrimMorph>::new(); let mut args = std::env::args().skip(1); let src_type_arg = args.next().expect("src type expected"); @@ -95,7 +96,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 ty = SugaredMorphismType{ src_type: src_type.sugar(&mut type_dict), dst_type: dst_type.sugar(&mut type_dict) }; + let ty = MorphismType{ src_type: src_type, dst_type }; 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")); } diff --git a/src/morphism.rs b/src/morphism.rs index 1fb4199..6e94477 100644 --- a/src/morphism.rs +++ b/src/morphism.rs @@ -1,177 +1,17 @@ -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}; +use laddertypes::{morphism_path::ShortestPathProblem, morphism::{Morphism, MorphismType}, StructMember}; +use crate::{c_gen_types::get_c_repr_type, struct_layout::StructLayout}; #[derive(Clone, Debug, PartialEq, Eq)] pub struct LdmcPrimMorph { pub symbol: String, pub type_args: Vec<(laddertypes::TypeID, String)>, - pub ty: SugaredMorphismType, + pub ty: MorphismType, pub c_source: String } -impl LdmcPrimMorph { - /* - pub fn into_prim_c_morphism(self, dict: &mut impl laddertypes::TypeDict, symbol: String) -> LdmcPrimCMorphism { - - let src_c_type = ; - let dst_c_type = ; - - let c_source = - format!(" - int {} ( {} const * restrict src, {} * restrict dst ) {{ - {} - return 0; - }} - ", - symbol, src_c_type, dst_c_type, - self.generate_call(dict, &std::collections::HashMap::new(), 0) - ); - - LdmcPrimCMorphism { - symbol, - type_args: Vec::new(), - src_type, - dst_type, - c_source - } - } -*/ -/* - - pub fn new_struct_map( - dict: &mut impl laddertypes::TypeDict, - 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 mut member_morphisms = Vec::new(); - - for SugaredStructMember{ symbol: field_name, ty: dst_type } in dst_struct.members.iter() { - let mut src_type = None; - for SugaredStructMember{ symbol: src_name, ty: st } in src_struct.members.iter() { - if src_name == field_name { - src_type = Some(st.clone()); - } - } - let src_type = src_type.expect(&format!("cant find member {} in src struct", field_name)); - - if src_type == *dst_type { - member_morphisms.push( - StructFieldMorphism { - field_name: field_name.to_string(), - item_morph: None, - src_offset: src_struct.get_offset( field_name ), - dst_offset: dst_struct.get_offset( field_name ), - } - ); - } else { - 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) - ); - member_morphisms.push( - StructFieldMorphism { - field_name: field_name.to_string(), - 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 ), - } - ); - }, - - None => { - eprintln!("cant map field {}", field_name); - } - } - } - } - - LdmcPrimMorph::StructMap { - src_struct, dst_struct, - member_morphisms - } - } - */ -} - -impl SugaredMorphism for LdmcPrimMorph { - fn get_type(&self) -> SugaredMorphismType { +impl Morphism for LdmcPrimMorph { + fn get_type(&self) -> MorphismType { self.ty.clone() } } -/* -impl Morphism for LdmcMorphism { - fn weight(&self) -> u64 { - 1 - } - - fn get_type(&self) -> laddertypes::MorphismType { - match self { - LdmcMorphism::Primitive(prim_morph) => - laddertypes::MorphismType { - src_type: prim_morph.src_type.clone().normalize(), - dst_type: prim_morph.dst_type.clone().normalize() - }, - LdmcMorphism::LengthPrefixMap{ length_prefix_type, item_morph } => { - laddertypes::MorphismType { - src_type: laddertypes::TypeTerm::App(vec![ length_prefix_type.clone(), item_morph.src_type.clone() ]), - dst_type: laddertypes::TypeTerm::App(vec![ length_prefix_type.clone(), item_morph.dst_type.clone() ]), - } - }, - LdmcMorphism::ValueDelimMap{ delim, item_morph } => { - let value_delim_type = laddertypes::TypeTerm::App(vec![]); - laddertypes::MorphismType { - src_type: laddertypes::TypeTerm::App(vec![ value_delim_type.clone(), item_morph.src_type.clone() ]), - dst_type: laddertypes::TypeTerm::App(vec![ value_delim_type.clone(), item_morph.dst_type.clone() ]), - } - }, - LdmcMorphism::StructMap { src_struct, dst_struct, member_morphisms } => { - laddertypes::MorphismType { - src_type: src_struct.get_type(), - dst_type: dst_struct.get_type() - } - } - }.normalize() - } - - fn map_morphism(&self, seq_type: laddertypes::TypeTerm) -> Option< Self > { - match self { - LdmcMorphism::Primitive(prim) => { - let item_morph = Box::new(prim.clone()); -/* - if seq_type == self.length_prefix_type { - */ - Some(LdmcMorphism::LengthPrefixMap{ - length_prefix_type: seq_type, - item_morph, - }) - /* - } else if seq_type == self.value_delim_type { - Some(LdmcMorphism::ValueDelimMap { delim, item_morph }) - } else { - None - } - */ - } - _ => None - } - } -} -*/ diff --git a/src/parser.rs b/src/parser.rs index 49320df..9590519 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -1,7 +1,7 @@ use { crate::morphism::LdmcPrimMorph, chumsky::{ prelude::*, text::* - }, laddertypes::{morphism_sugared::SugaredMorphismType, parser::*, BimapTypeDict, TypeDict}, std::sync::{Arc, RwLock} + }, laddertypes::{morphism::MorphismType, parser::*, BimapTypeDict, TypeDict}, std::sync::{Arc, RwLock} }; /* morphism-base text format: @@ -59,13 +59,13 @@ 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").sugar(&mut *type_dict); - let dst_type = type_dict.parse(&dst_type.iter().collect::<String>()).expect("couldnt parse dst type").sugar(&mut *type_dict); + let src_type = type_dict.parse_desugared(&src_type.iter().collect::<String>()).expect("couldnt parse src type").sugar(&mut *type_dict); + let dst_type = type_dict.parse_desugared(&dst_type.iter().collect::<String>()).expect("couldnt parse dst type").sugar(&mut *type_dict); LdmcPrimMorph { symbol, type_args: ty_args, - ty: SugaredMorphismType{ + ty: MorphismType{ src_type, dst_type }, diff --git a/src/struct_layout.rs b/src/struct_layout.rs index 40be995..3847814 100644 --- a/src/struct_layout.rs +++ b/src/struct_layout.rs @@ -1,7 +1,7 @@ use std::ops::Deref; -use laddertypes::{parser::*, unparser::*, SugaredStructMember, SugaredTypeTerm, TypeDict, TypeTerm}; +use laddertypes::{parser::*, unparser::*, StructMember, TypeTerm, TypeDict, DesugaredTypeTerm}; #[derive(Clone, Copy, Debug)] pub enum ObjectSize { @@ -46,9 +46,9 @@ impl std::ops::Mul for ObjectSize { } } -pub fn get_type_size( dict: &mut impl TypeDict, ty: SugaredTypeTerm ) -> ObjectSize { +pub fn get_type_size( dict: &mut impl TypeDict, ty: TypeTerm ) -> ObjectSize { match &ty { - SugaredTypeTerm::TypeID(tyid) => { + TypeTerm::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) } @@ -61,23 +61,23 @@ pub fn get_type_size( dict: &mut impl TypeDict, ty: SugaredTypeTerm ) -> ObjectS } }, - SugaredTypeTerm::Ladder(rungs) => { + TypeTerm::Ladder(rungs) => { get_type_size(dict, rungs.last().unwrap().clone() ) } - SugaredTypeTerm::Struct { struct_repr, members } => { + TypeTerm::Struct { struct_repr, members } => { let layout = StructLayout::parse_sugared(dict, ty).expect("invalid struct"); layout.get_size() } - SugaredTypeTerm::Seq { seq_repr, items } => { + TypeTerm::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), + &seq_repr.clone(), &dict.parse("<StaticLength Length>").expect("") ) { if let Some(TypeTerm::Num(len)) = σ.get(&dict.get_typeid(&"Length".into()).expect("")) { @@ -87,13 +87,13 @@ pub fn get_type_size( dict: &mut impl TypeDict, ty: SugaredTypeTerm ) -> ObjectS } } else if let Ok(σ) = laddertypes::unify( - &seq_repr.clone().desugar(dict), + &seq_repr.clone(), &dict.parse("<LengthPrefix LengthType>").expect("") ) { ObjectSize::Dynamic() } else if let Ok(σ) = laddertypes::unify( - &seq_repr.clone().desugar(dict), + &seq_repr.clone(), &dict.parse("<ValueTerminated TerminatorValue>").expect("") ) { ObjectSize::Dynamic() @@ -118,35 +118,35 @@ pub enum LayoutType { } impl LayoutType { - pub fn parse( dict: &mut impl TypeDict, ty: &TypeTerm ) -> Option< LayoutType > { - if ty == &dict.parse("Aligned").expect("parse") { + pub fn parse( dict: &mut impl TypeDict, ty: &DesugaredTypeTerm ) -> Option< LayoutType > { + if ty == &dict.parse_desugared("Aligned").expect("parse") { Some(LayoutType::Aligned) - } else if ty == &dict.parse("Packed").expect("parse") { + } else if ty == &dict.parse_desugared("Packed").expect("parse") { Some(LayoutType::Packed) } else { None } } - pub fn unparse(&self, dict: &mut impl TypeDict) -> TypeTerm { + pub fn unparse(&self, dict: &mut impl TypeDict) -> DesugaredTypeTerm { match self { - LayoutType::Aligned => dict.parse("Aligned").unwrap(), - LayoutType::Packed => dict.parse("Packed").unwrap() + LayoutType::Aligned => dict.parse_desugared("Aligned").unwrap(), + LayoutType::Packed => dict.parse_desugared("Packed").unwrap() } } } #[derive(Clone)] pub struct StructLayout { - pub ty: laddertypes::TypeTerm, + pub ty: laddertypes::DesugaredTypeTerm, pub layout: LayoutType, - pub members: Vec< SugaredStructMember >, + pub members: Vec< StructMember >, offsets: std::collections::HashMap< String, u64 >, size: ObjectSize } impl StructLayout { - pub fn get_type(&self) -> TypeTerm { + pub fn get_type(&self) -> DesugaredTypeTerm { self.ty.clone() } @@ -161,7 +161,7 @@ impl StructLayout { pub fn init_offsets(&mut self, dict: &mut impl TypeDict) { let mut offset = 0; - for SugaredStructMember{symbol: field_name, ty: field_type} in self.members.iter() { + for StructMember{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) => { @@ -208,15 +208,15 @@ impl StructLayout { } } - pub fn parse(dict: &mut impl TypeDict, struct_type: &TypeTerm) -> Option <Self> { + pub fn parse(dict: &mut impl TypeDict, struct_type: &DesugaredTypeTerm) -> Option <Self> { let st = struct_type.clone().strip().param_normalize().sugar(dict); Self::parse_sugared(dict, st) } - pub fn parse_sugared(dict: &mut impl TypeDict, st: SugaredTypeTerm) -> Option <Self> { + pub fn parse_sugared(dict: &mut impl TypeDict, st: TypeTerm) -> Option <Self> { eprintln!("{}", st.pretty(dict, 0)); match st.clone() { - SugaredTypeTerm::Struct{ struct_repr, members } => { + TypeTerm::Struct{ struct_repr, members } => { let mut sl = StructLayout { ty: st.desugar(dict), layout: if let Some(sr) = struct_repr { From 3ed7a1927042c083c39221781fb5b67eb9dd0dba Mon Sep 17 00:00:00 2001 From: Michael Sippel <micha@fragmental.art> Date: Tue, 6 May 2025 00:39:32 +0200 Subject: [PATCH 12/31] adapt changes in lib-laddertypes --- src/struct_layout.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/struct_layout.rs b/src/struct_layout.rs index 3847814..d07b129 100644 --- a/src/struct_layout.rs +++ b/src/struct_layout.rs @@ -209,7 +209,7 @@ impl StructLayout { } pub fn parse(dict: &mut impl TypeDict, struct_type: &DesugaredTypeTerm) -> Option <Self> { - let st = struct_type.clone().strip().param_normalize().sugar(dict); + let st = struct_type.clone().strip().sugar(dict).normalize(); Self::parse_sugared(dict, st) } From 923fe987dc3df62d368a8a30fb03f0b60cb8eb60 Mon Sep 17 00:00:00 2001 From: Michael Sippel <micha@fragmental.art> Date: Wed, 7 May 2025 16:29:45 +0200 Subject: [PATCH 13/31] fix typedefs --- morphisms/length_prefix.morphism-base | 4 +- morphisms/posint.morphism-base | 12 +- .../runtime/include/array/length-prefix.h | 38 ++-- morphisms/value_delim.morphism-base | 24 +- src/c_gen/gen_main.rs | 49 ++++ src/c_gen/mod.rs | 7 + src/c_gen/morph/mod.rs | 76 +++++++ src/{c_gen.rs => c_gen/morph/target_morph.rs} | 211 +++++------------- src/{c_gen_types.rs => c_gen/types/mod.rs} | 22 +- src/main.rs | 60 +---- src/morphism.rs | 3 +- src/parser.rs | 2 +- src/platform/x86.rs | 43 ++++ src/struct_layout.rs | 3 +- 14 files changed, 309 insertions(+), 245 deletions(-) create mode 100644 src/c_gen/gen_main.rs create mode 100644 src/c_gen/mod.rs create mode 100644 src/c_gen/morph/mod.rs rename src/{c_gen.rs => c_gen/morph/target_morph.rs} (64%) rename src/{c_gen_types.rs => c_gen/types/mod.rs} (90%) create mode 100644 src/platform/x86.rs diff --git a/morphisms/length_prefix.morphism-base b/morphisms/length_prefix.morphism-base index 1a1b7f5..a694931 100644 --- a/morphisms/length_prefix.morphism-base +++ b/morphisms/length_prefix.morphism-base @@ -7,9 +7,9 @@ morph_array_as_valterm_to_lenpfx (Terminator:native.UInt8) <Seq~<ValueTerminated Terminator> native.UInt8> --> <Seq~<LengthPrefix native.UInt64> native.UInt8> ``` - length_prefix_uint64_t_array_uint8_t_clear(dst); + length_prefix_nativeUInt64_array_nativeUInt8_clear(dst); while( *src != Terminator ) - length_prefix_uint64_t_array_uint8_t_push(dst, *src++); + length_prefix_nativeUInt64_array_nativeUInt8_push(dst, *src++); ``` diff --git a/morphisms/posint.morphism-base b/morphisms/posint.morphism-base index 01248eb..9036520 100644 --- a/morphisms/posint.morphism-base +++ b/morphisms/posint.morphism-base @@ -38,15 +38,15 @@ morph_posint_radix_le (SrcRadix:ℤ, DstRadix:ℤ) value += src->items[src->len - i - 1]; } - length_prefix_uint64_t_array_uint64_t_clear( dst ); + length_prefix_nativeUInt64_array_nativeUInt64_clear( dst ); #if DstRadix==0 - length_prefix_uint64_t_array_uint64_t_push( dst, value ); + length_prefix_nativeUInt64_array_nativeUInt64_push( dst, value ); #else if( value == 0 ) { - length_prefix_uint64_t_array_uint64_t_push( dst, 0 ); + length_prefix_nativeUInt64_array_nativeUInt64_push( dst, 0 ); } else while( value > 0 ) { - length_prefix_uint64_t_array_uint64_t_push( dst, value % DstRadix ); + length_prefix_nativeUInt64_array_nativeUInt64_push( dst, value % DstRadix ); value /= DstRadix; } #endif @@ -97,7 +97,7 @@ morph_posint_endianness (Radix:ℤ) ~ <PosInt Radix BigEndian> ~ <Seq~<LengthPrefix native.UInt64> <Digit Radix> ~ native.UInt64> ``` - return length_prefix_uint64_t_array_uint64_t_reverse( src, dst ); + return length_prefix_nativeUInt64_array_nativeUInt64_reverse( src, dst ); ``` morph_posint_endianness (Radix:ℤ) @@ -108,5 +108,5 @@ morph_posint_endianness (Radix:ℤ) ~ <PosInt Radix LittleEndian> ~ <Seq~<LengthPrefix native.UInt64> <Digit Radix> ~ native.UInt64> ``` - return length_prefix_uint64_t_array_uint64_t_reverse( src, dst ); + return length_prefix_nativeUInt64_array_nativeUInt64_reverse( src, dst ); ``` diff --git a/morphisms/runtime/include/array/length-prefix.h b/morphisms/runtime/include/array/length-prefix.h index 3f039f2..e61f8ac 100644 --- a/morphisms/runtime/include/array/length-prefix.h +++ b/morphisms/runtime/include/array/length-prefix.h @@ -2,27 +2,37 @@ #include <stdio.h> #include <stdint.h> +/* +typedef struct { \ + LEN_TYPE len; \ + ITEM_TYPE items[]; \ +} __Seq__LengthPrefix_##LEN_TYPE##___##ITEM_TYPE##_; \ + */ \ + +#define LENGTH_PREFIX_ARRAY_TYPE(LEN_TYPE, ITEM_TYPE) \ + __Seq__LengthPrefix_##LEN_TYPE##___##ITEM_TYPE##_ + +#define LENGTH_PREFIX_ARRAY_CALL(LEN_TYPE, ITEM_TYPE, METHOD) \ + length_prefix_##LEN_TYPE##_array_##ITEM_TYPE##_ ## METHOD + +#define PRESCAN_LENGTH_PREFIX_CALL(LEN, ITEM, METHOD) \ + LENGTH_PREFIX_ARRAY_CALL(LEN, ITEM, METHOD) #define DEFINE_LENGTH_PREFIX_ARRAY(LEN_TYPE, ITEM_TYPE) \ - typedef struct { \ - LEN_TYPE len; \ - ITEM_TYPE items[]; \ - } __Seq__LengthPrefix_##LEN_TYPE##___##ITEM_TYPE##_; \ - \ - static inline void length_prefix_##LEN_TYPE##_array_##ITEM_TYPE##_clear( \ - __Seq__LengthPrefix_##LEN_TYPE##___##ITEM_TYPE##_ *data) { \ + static inline void PRESCAN_LENGTH_PREFIX_CALL(LEN_TYPE, ITEM_TYPE, clear) \ + (__Seq__LengthPrefix_##LEN_TYPE##___##ITEM_TYPE##_ *data) { \ data->len = 0; \ } \ \ - static inline void length_prefix_##LEN_TYPE##_array_##ITEM_TYPE##_push( \ - __Seq__LengthPrefix_##LEN_TYPE##___##ITEM_TYPE##_ *data, \ + static inline void PRESCAN_LENGTH_PREFIX_CALL(LEN_TYPE, ITEM_TYPE, push) \ + (__Seq__LengthPrefix_##LEN_TYPE##___##ITEM_TYPE##_ *data, \ ITEM_TYPE value) { \ data->items[data->len++] = value; \ } \ \ - static inline int length_prefix_##LEN_TYPE##_array_##ITEM_TYPE##_reverse( \ - __Seq__LengthPrefix_##LEN_TYPE##___##ITEM_TYPE##_ const * restrict src, \ - __Seq__LengthPrefix_##LEN_TYPE##___##ITEM_TYPE##_ *restrict dst) { \ + static inline int PRESCAN_LENGTH_PREFIX_CALL(LEN_TYPE, ITEM_TYPE, reverse) \ + ( __Seq__LengthPrefix_##LEN_TYPE##___##ITEM_TYPE##_ const * restrict src, \ + __Seq__LengthPrefix_##LEN_TYPE##___##ITEM_TYPE##_ *restrict dst) { \ for (LEN_TYPE i = 0; i < src->len; i++) { \ dst->items[i] = src->items[src->len - 1 - i]; \ } \ @@ -30,8 +40,8 @@ return 0; \ } \ \ - static inline void length_prefix_##LEN_TYPE##_array_##ITEM_TYPE##_dump( \ - __Seq__LengthPrefix_##LEN_TYPE##___##ITEM_TYPE##_ const * data) { \ + static inline void PRESCAN_LENGTH_PREFIX_CALL(LEN_TYPE, ITEM_TYPE, dump) \ + ( __Seq__LengthPrefix_##LEN_TYPE##___##ITEM_TYPE##_ const * data) { \ printf("Length: %llu\n", (unsigned long long) data->len); \ for (LEN_TYPE i = 0; i < data->len; i++) { \ printf("%llu ", (unsigned long long) data->items[i]); \ diff --git a/morphisms/value_delim.morphism-base b/morphisms/value_delim.morphism-base index ab66310..6e94459 100644 --- a/morphisms/value_delim.morphism-base +++ b/morphisms/value_delim.morphism-base @@ -12,19 +12,19 @@ morph_seqseq_valsep_uint8 (T: Type, SrcDelim: T, DstDelim: T) ~ < ValueSep DstDelim T > ~ < Seq~<LengthPrefix native.UInt64> T > ``` - length_prefix_uint64_t_array_uint8_t_clear( dst ); + PRESCAN_LENGTH_PREFIX_CALL(nativeUInt64, T, clear)( dst ); uint8_t * dst_items = dst->items; for( uint64_t i = 0; i < src->len; ++i ) { if( src->items[i] == SrcDelim ) { - length_prefix_uint64_t_array_uint8_t_push( dst, DstDelim ); + PRESCAN_LENGTH_PREFIX_CALL(nativeUInt64, T, push)( dst, DstDelim ); } else if( src->items[i] == DstDelim ) { if( DstDelim == '\n' ) { - length_prefix_uint64_t_array_uint8_t_push( dst, '\\' ); - length_prefix_uint64_t_array_uint8_t_push( dst, 'n' ); + PRESCAN_LENGTH_PREFIX_CALL(nativeUInt64, T, push)( dst, '\\' ); + PRESCAN_LENGTH_PREFIX_CALL(nativeUInt64, T, push)( dst, 'n' ); } } else { - length_prefix_uint64_t_array_uint8_t_push( dst, src->items[i] ); + PRESCAN_LENGTH_PREFIX_CALL(nativeUInt64, T, push)( dst, src->items[i] ); } } ``` @@ -42,9 +42,9 @@ morph_seqseq_as_valsep_to_lenpfx (T: Type, Delim: T, EscKey: T) ~ native.UInt64 > ``` - length_prefix_uint64_t_array_uint64_t_clear( dst ); + length_prefix_nativeUInt64_array_nativeUInt64_clear( dst ); - struct LengthPrefix_uint64_t_Array_uint8_t * cur_item = NULL; + struct LengthPrefix_nativeUInt64_Array_nativeUInt8 * cur_item = NULL; uint8_t const * start = &src->items[0]; uint8_t const * cur = start; @@ -58,7 +58,7 @@ morph_seqseq_as_valsep_to_lenpfx (T: Type, Delim: T, EscKey: T) cur_item->len = len; memcpy( cur_item->items, start, len ); - length_prefix_uint64_t_array_uint64_t_push( dst, (uint64_t)cur_item ); + length_prefix_nativeUInt64_array_nativeUInt64_push( dst, (uint64_t)cur_item ); start = ++cur; } else { cur++; @@ -77,17 +77,17 @@ morph_seqeq_as_lenpfx_to_valsep (T: Type, Delim: T, EscKey: T) ~ < ValueSep T Delim > ~ < Seq~<LengthPrefix native.UInt64> T > ``` - length_prefix_uint64_t_array_uint8_t_clear( dst ); + length_prefix_nativeUInt64_array_nativeUInt8_clear( dst ); for( uint64_t i = 0; i < src->len; ++i ) { - LengthPrefix_uint64_t_Array_uint8_t * item = src->items[i]; + LengthPrefix_nativeUInt64_Array_nativeUInt8_t * item = src->items[i]; for( uint64_t j = 0; j < item->len; ++j ) { - length_prefix_uint64_t_array_uint8_t_push( items->items[j] ); + length_prefix_nativeUInt64_array_nativeUInt8_push( items->items[j] ); } if( i+1 < src->len ) { - length_prefix_uint64_t_array_uint8_t_push( Delim ); + length_prefix_nativeUInt64_array_nativeUInt8_push( Delim ); } } ``` diff --git a/src/c_gen/gen_main.rs b/src/c_gen/gen_main.rs new file mode 100644 index 0000000..70847ea --- /dev/null +++ b/src/c_gen/gen_main.rs @@ -0,0 +1,49 @@ +use { + laddertypes::{TypeDict, morphism::MorphismInstance, parser::*}, + crate::LdmcPrimMorph, + crate::c_gen::LdmcCTargetMorph, + std::collections::HashMap, +}; + +pub fn generate_main(dict: &mut impl TypeDict, morph: MorphismInstance<LdmcPrimMorph>) -> Result<String, ()> { + let mut target = LdmcCTargetMorph::new(); + let ty = morph.get_type(); + match target.add_instantiation(dict, morph) { + Ok(inst) => { + 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_desugared("<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::constraint_system::subtype_unify( + &ty.src_type, + &dict.parse_desugared("<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) + } + Err(err) => { + eprintln!("failed to create morphism instatiation"); + Err(()) + } + } +} diff --git a/src/c_gen/mod.rs b/src/c_gen/mod.rs new file mode 100644 index 0000000..f8c11f9 --- /dev/null +++ b/src/c_gen/mod.rs @@ -0,0 +1,7 @@ +pub mod types; +pub mod morph; +pub mod gen_main; + +pub use { + morph::target_morph::LdmcCTargetMorph +}; diff --git a/src/c_gen/morph/mod.rs b/src/c_gen/morph/mod.rs new file mode 100644 index 0000000..49510e5 --- /dev/null +++ b/src/c_gen/morph/mod.rs @@ -0,0 +1,76 @@ +pub mod target_morph; + +use { + crate::{ + c_gen::types::{ + get_c_repr_arg_type, + get_c_repr_definition, + get_c_repr_type + }, + morphism::LdmcPrimMorph + }, + laddertypes::{TypeDict, Substitution}, +}; + +impl LdmcPrimMorph { + pub fn instantiated_symbol_name(&self, dict: &mut impl TypeDict, σ: &impl Substitution) -> 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 { + + //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 = get_c_repr_type(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::TypeTerm> + ) -> String { + format!("int {} ({} const * restrict src, {} * restrict dst);", + self.instantiated_symbol_name(dict, σ), + get_c_repr_definition(dict, self.ty.src_type.clone(), true).expect("cant get c-repr type for src type"), + get_c_repr_definition(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 Substitution) -> Option<String> { + let mut s = String::new(); + let symbol = self.instantiated_symbol_name(dict, σ); + + eprintln!("generate instantiation:"); + let ty = self.ty.clone(); + eprintln!("full type: {} ----> {}", ty.src_type.pretty(dict, 0), ty.dst_type.pretty(dict,0)); + let ty = ty.strip_halo().apply_subst(σ); + eprintln!("stripped type: {} ----> {}", ty.src_type.pretty(dict, 0), ty.dst_type.pretty(dict,0)); + + let src_c_symbol = get_c_repr_arg_type(dict, &ty.src_type); + let dst_c_symbol = get_c_repr_arg_type(dict, &ty.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) + } +} diff --git a/src/c_gen.rs b/src/c_gen/morph/target_morph.rs similarity index 64% rename from src/c_gen.rs rename to src/c_gen/morph/target_morph.rs index 0f21ef8..fcb90fb 100644 --- a/src/c_gen.rs +++ b/src/c_gen/morph/target_morph.rs @@ -1,86 +1,22 @@ use { - crate::{c_gen_types::{encode_morph_type_to_symbol, encode_type_to_value, get_c_repr_arg_type, - get_c_repr_definition, get_c_repr_type}, morphism::LdmcPrimMorph, - struct_layout::{get_type_size, LayoutType, ObjectSize, StructLayout}}, - chumsky::{chain::Chain, primitive::Container}, - laddertypes::{morphism::{MorphismInstance, Morphism, MorphismType}, - parser::*, substitution::Substitution, unparser::*, - EnumVariant, StructMember, TypeTerm, TypeDict, DesugaredTypeTerm}, + crate::{ + c_gen::types::{ + encode_morph_type_to_symbol, get_c_repr_definition, get_c_repr_type, encode_type_to_value + }, + morphism::LdmcPrimMorph + }, + laddertypes::{ + parser::*, MorphismInstance, TypeDict, TypeTerm, Morphism + }, std::collections::HashMap }; -impl LdmcPrimMorph { - pub fn instantiated_symbol_name(&self, dict: &mut impl TypeDict, σ: &impl Substitution) -> 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 { - - //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 = get_c_repr_type(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::TypeTerm> - ) -> String { - format!("int {} ({} const * restrict src, {} * restrict dst);", - self.instantiated_symbol_name(dict, σ), - get_c_repr_definition(dict, self.ty.src_type.clone(), true).expect("cant get c-repr type for src type"), - get_c_repr_definition(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 Substitution) -> Option<String> { - let mut s = String::new(); - let symbol = self.instantiated_symbol_name(dict, σ); - - eprintln!("generate instantiation:"); - let ty = self.ty.clone(); - eprintln!("full type: {} ----> {}", ty.src_type.pretty(dict, 0), ty.dst_type.pretty(dict,0)); - let ty = ty.strip_halo().apply_subst(σ); - eprintln!("stripped type: {} ----> {}", ty.src_type.pretty(dict, 0), ty.dst_type.pretty(dict,0)); - - let src_c_symbol = get_c_repr_arg_type(dict, &ty.src_type); - let dst_c_symbol = get_c_repr_arg_type(dict, &ty.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< TypeTerm >, active_instantiations: Vec< LdmcPrimMorph >, + active_lenpfx_types: Vec< (TypeTerm, TypeTerm) >, + typedefs: Vec< String >, macro_calls: Vec< String > } @@ -94,6 +30,8 @@ impl LdmcCTargetMorph { ], active_instantiations: Vec::new(), active_types: Vec::new(), + active_lenpfx_types: Vec::new(), + typedefs: Vec::new(), macro_calls: Vec::new() } } @@ -101,34 +39,51 @@ impl LdmcCTargetMorph { pub fn add_type(&mut self, dict: &mut impl TypeDict, ty: TypeTerm) { let ty = ty.strip(); if ! self.active_types.contains(&ty) { - eprintln!("add type {:?}", ty); - match &ty { - TypeTerm::Seq { seq_repr, items } =>{ - let item_type = items.first().unwrap().clone(); - self.add_type(dict, item_type.clone()); + eprintln!("add type {}", ty.pretty(dict,0)); - if let Some(seq_repr) = seq_repr { - dict.add_varname("LengthType".into()); - if let Ok(σ) = - laddertypes::constraint_system::unify( - seq_repr.as_ref(), - &dict.parse_desugared("<LengthPrefix LengthType>").expect("").sugar(dict) - ) - { - let length_type = σ.get(&dict.get_typeid(&"LengthType".into()).expect("")).expect("cant get Length type"); - self.add_type(dict, length_type.clone()); - self.macro_calls.push( - format!("DEFINE_LENGTH_PREFIX_ARRAY({}, {})\n", - get_c_repr_type(dict, &length_type), - get_c_repr_type(dict, &item_type) + let (ht,ft) = ty.get_floor_type(); + if ht.is_empty() { + + match &ft { + TypeTerm::Seq { seq_repr, items } => { + let item_type = items.first().unwrap().clone(); + self.add_type(dict, item_type.clone()); + + if let Some(seq_repr) = seq_repr { + dict.add_varname("LengthType".into()); + if let Ok(σ) = + laddertypes::constraint_system::unify( + seq_repr.as_ref(), + &dict.parse_desugared("<LengthPrefix LengthType>").expect("").sugar(dict) ) - ); + { + let length_type = σ.get(&dict.get_typeid(&"LengthType".into()).expect("")).expect("cant get Length type"); + self.add_type(dict, length_type.clone()); + self.macro_calls.push( + format!("DEFINE_LENGTH_PREFIX_ARRAY({}, {})\n", + get_c_repr_type(dict, &length_type), + get_c_repr_type(dict, &item_type) + ) + ); + } } } + _ => {} } - _=>{} + + self.active_types.push(ty.clone()); + if let Some(type_def) = get_c_repr_definition(dict, ft, false) { + let type_name = get_c_repr_type(dict, &ty); + self.typedefs.push(format!("typedef {} {};\n", type_def, type_name)); + } else { + eprintln!("cant get c-repr type for type '{}'", ty.pretty(dict,0)); + } + } else { + let type_name = get_c_repr_type(dict, &ty); + let type_def = get_c_repr_type(dict, &ft); + self.add_type(dict, ft); + self.typedefs.push(format!("typedef {} {};\n", type_def, type_name)); } - self.active_types.push(ty.clone()); } } @@ -162,14 +117,10 @@ impl LdmcCTargetMorph { source.push('\n'); - for ty in self.active_types { - if let Some(type_def) = get_c_repr_definition(dict, ty.clone(), false) { - let type_name = get_c_repr_type(dict, &ty); - source.push_str(&format!("typedef {} {};\n", type_def, type_name)); - } else { - eprintln!("cant get c-repr type for type '{}'", ty.pretty(dict,0)); - } + for typedef in self.typedefs { + source.push_str(&typedef); } + source.push('\n'); @@ -201,13 +152,7 @@ impl LdmcCTargetMorph { //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_definition(dict, val.clone(), true) { - c_repr_type - } else { - encode_type_to_value(dict, &val) - }; - + let type_var_value = get_c_repr_type(dict, val); c_source.push_str(&format!(" #define {} {}\n", dict.get_typename(&ty_id).unwrap(), type_var_value)); } //} @@ -399,47 +344,3 @@ impl LdmcCTargetMorph { } } } - -pub fn generate_main(dict: &mut impl TypeDict, morph: MorphismInstance<LdmcPrimMorph>) -> Result<String, ()> { - let mut target = LdmcCTargetMorph::new(); - let ty = morph.get_type(); - match target.add_instantiation(dict, morph) { - Ok(inst) => { - 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_desugared("<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::constraint_system::subtype_unify( - &ty.src_type, - &dict.parse_desugared("<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) - } - Err(err) => { - eprintln!("failed to create morphism instatiation"); - Err(()) - } - } -} diff --git a/src/c_gen_types.rs b/src/c_gen/types/mod.rs similarity index 90% rename from src/c_gen_types.rs rename to src/c_gen/types/mod.rs index 8c366bb..29cb4ec 100644 --- a/src/c_gen_types.rs +++ b/src/c_gen/types/mod.rs @@ -1,9 +1,9 @@ use { - crate::{morphism::LdmcPrimMorph, struct_layout::{get_type_size, LayoutType, ObjectSize, StructLayout}}, - chumsky::chain::Chain, laddertypes::{morphism::{MorphismInstance, MorphismType}, + crate::struct_layout::LayoutType, + chumsky::chain::Chain, laddertypes::{morphism::MorphismType, parser::*, substitution::Substitution, - unparser::*, EnumVariant, StructMember, TypeTerm, TypeDict, DesugaredTypeTerm}, std::thread::yield_now + unparser::*, EnumVariant, StructMember, TypeTerm, TypeDict} }; /* @@ -87,6 +87,16 @@ pub fn get_c_repr_definition(dict: &mut impl TypeDict, t: TypeTerm, skip_pointer Some(format!("{} *", item_c_type)) } } + else if let Ok((ψ, σ)) = laddertypes::constraint_system::subtype_unify( + seq_repr.as_ref(), + &dict.parse_desugared("MsbCont").expect("parse template type").sugar(dict) + ) { + if skip_pointer { + Some(item_c_type) + } else { + Some(format!("{} *", item_c_type)) + } + } else { eprintln!("can't get C-repr for sequence type `{}`!", seq_repr.pretty(dict, 0)); None @@ -219,6 +229,12 @@ pub fn get_c_repr_arg_type(dict: &mut impl TypeDict, t: &laddertypes::TypeTerm)- ) { return get_c_repr_type(dict, &items[0].clone().strip().get_floor_type().1); } + else if let Ok(ψ) = laddertypes::constraint_system::subtype_unify( + seq_repr, + &dict.parse_desugared("MsbCont").expect("").sugar(dict) + ) { + return get_c_repr_type(dict, &items[0].clone().strip().get_floor_type().1); + } } } diff --git a/src/main.rs b/src/main.rs index 1e418d4..01df9a7 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,17 +3,21 @@ mod morphism; mod parser; mod c_gen; -mod c_gen_types; mod struct_layout; use { crate::{ morphism::LdmcPrimMorph, parser::morphism_base_parser, - }, ariadne::{Color, Label, Report, ReportKind, Source}, c_gen::LdmcCTargetMorph, chumsky::prelude::*, laddertypes::{ - morphism_path::ShortestPathProblem, morphism::{MorphismInstance, Morphism, MorphismType}, - parser::ParseLadderType, unparser::*, BimapTypeDict, TypeTerm, TypeDict - }, std::{collections::HashMap, sync::{Arc, RwLock}}, tiny_ansi::TinyAnsi + }, + ariadne::{Color, Label, Report, ReportKind, Source}, + chumsky::prelude::*, + laddertypes::{ + morphism::MorphismType, + parser::ParseLadderType, BimapTypeDict + }, + std::{sync::{Arc, RwLock}}, + tiny_ansi::TinyAnsi }; fn main() { @@ -26,7 +30,7 @@ fn main() { let dst_type_arg = args.next().expect("dst type expected"); for mb_path in args { - let src = std::fs::read_to_string(mb_path.clone()).expect("read"); + let src = std::fs::read_to_string(mb_path.clone()).expect("failed to read morphism base"); let result = morphism_base_parser(type_dict.clone()).parse(src.clone()); match result { Ok((includes, morphisms)) => { @@ -53,50 +57,10 @@ fn main() { } } - let mut γ = HashMap::new(); - γ.insert( - type_dict.get_typeid_creat(&"Byte"), - type_dict.parse("<Seq~<StaticLength 8> Bit>").expect("parse") - .apply_subst(&γ) - .clone() - ); - γ.insert( - type_dict.get_typeid_creat(&"x86.UInt8"), - type_dict.parse("ℤ_2^8 ~ <PosInt 2 BigEndian> ~ <Seq~<StaticLength 8> <Digit 2> ~ Bit>").expect("parse") - .apply_subst(&γ) - .clone() - ); - γ.insert( - 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_subst(&γ) - .clone() - ); - γ.insert( - 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_subst(&γ).clone() - ); - γ.insert( - 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_subst(&γ).clone() - ); - γ.insert( - type_dict.get_typeid_creat(&"x86.Float32"), - type_dict.parse("ℝ ~ IEEE-754.Float32 ~ <Seq~<StaticLength 4> Byte>").expect("parse") - .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 ty = MorphismType{ src_type: src_type, dst_type }; + let ty = MorphismType{ src_type, dst_type }; 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")); + println!("{}", crate::c_gen::gen_main::generate_main(&mut type_dict, m).expect("failed to generate main function")); } diff --git a/src/morphism.rs b/src/morphism.rs index 6e94477..28ea01e 100644 --- a/src/morphism.rs +++ b/src/morphism.rs @@ -1,6 +1,5 @@ -use laddertypes::{morphism_path::ShortestPathProblem, morphism::{Morphism, MorphismType}, StructMember}; -use crate::{c_gen_types::get_c_repr_type, struct_layout::StructLayout}; +use laddertypes::morphism::{Morphism, MorphismType}; #[derive(Clone, Debug, PartialEq, Eq)] pub struct LdmcPrimMorph { diff --git a/src/parser.rs b/src/parser.rs index 9590519..ef2acff 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -19,7 +19,7 @@ pub fn morphism_base_parser( just("```") .then(take_until(just("```"))) .map( - move |(a, (b, c))| { + move |(_a, (b, _c))| { b.iter().collect() } ) diff --git a/src/platform/x86.rs b/src/platform/x86.rs new file mode 100644 index 0000000..aaae9c2 --- /dev/null +++ b/src/platform/x86.rs @@ -0,0 +1,43 @@ +use std::collections::HashMap; + +pub fn example_substitution() { + let mut γ = HashMap::new(); + γ.insert( + type_dict.get_typeid_creat(&"Byte"), + type_dict.parse("<Seq~<StaticLength 8> Bit>").expect("parse") + .apply_subst(&γ) + .clone() + ); + γ.insert( + type_dict.get_typeid_creat(&"x86.UInt8"), + type_dict.parse("ℤ_2^8 ~ <PosInt 2 LittleEndian> ~ <Seq~<StaticLength 8> <Digit 2> ~ Bit>").expect("parse") + .apply_subst(&γ) + .clone() + ); + γ.insert( + 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_subst(&γ) + .clone() + ); + γ.insert( + 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_subst(&γ).clone() + ); + γ.insert( + 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_subst(&γ).clone() + ); + γ.insert( + type_dict.get_typeid_creat(&"x86.Float32"), + type_dict.parse("ℝ ~ IEEE-754.Float32 ~ <Seq~<StaticLength 4> Byte>").expect("parse") + .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() + ); +} diff --git a/src/struct_layout.rs b/src/struct_layout.rs index d07b129..b8816e9 100644 --- a/src/struct_layout.rs +++ b/src/struct_layout.rs @@ -1,7 +1,6 @@ -use std::ops::Deref; -use laddertypes::{parser::*, unparser::*, StructMember, TypeTerm, TypeDict, DesugaredTypeTerm}; +use laddertypes::{parser::*, StructMember, TypeTerm, TypeDict, DesugaredTypeTerm}; #[derive(Clone, Copy, Debug)] pub enum ObjectSize { From 27ea365755ad238ae9a5f2e66d3d820b190feacb Mon Sep 17 00:00:00 2001 From: Michael Sippel <micha@fragmental.art> Date: Fri, 9 May 2025 03:33:18 +0200 Subject: [PATCH 14/31] improve integration * add command line parsing * read morphism base directory from environment * generate C library of multiple morphisms --- Cargo.toml | 2 ++ src/c_gen/gen_lib.rs | 74 ++++++++++++++++++++++++++++++++++++++++ src/c_gen/gen_main.rs | 49 --------------------------- src/c_gen/mod.rs | 2 +- src/main.rs | 78 ++++++++++++++++++++++++++++++++----------- src/parser.rs | 28 ++++++++++++++-- 6 files changed, 161 insertions(+), 72 deletions(-) create mode 100644 src/c_gen/gen_lib.rs delete mode 100644 src/c_gen/gen_main.rs diff --git a/Cargo.toml b/Cargo.toml index 8eace12..c4ca5d9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,3 +8,5 @@ chumsky = "0.9.0" ariadne = "0.2" laddertypes = { path = "../lib-laddertypes", features = ["pretty"] } tiny-ansi = { version = "0.1.0" } +clap = { version = "4.5.37", features = ["derive"] } +walkdir = "2.5.0" diff --git a/src/c_gen/gen_lib.rs b/src/c_gen/gen_lib.rs new file mode 100644 index 0000000..fa2ce88 --- /dev/null +++ b/src/c_gen/gen_lib.rs @@ -0,0 +1,74 @@ +use { + super::types::get_c_repr_arg_type, crate::{c_gen::LdmcCTargetMorph, LdmcPrimMorph}, laddertypes::{morphism::MorphismInstance, parser::*, TypeDict}, std::collections::HashMap +}; + +pub fn generate_lib( + dict: &mut impl TypeDict, + morphisms: Vec< (String, MorphismInstance<LdmcPrimMorph>) > +) -> Result<String, ()> { + let mut target = LdmcCTargetMorph::new(); + let mut wrappers = String::new(); + + for (name, morph) in morphisms { + match target.add_instantiation(dict, morph) { + Ok(inst) => { + if name == "main" { + let mut c_source = String::new(); + c_source.push_str(&format!(r#" + #include <unistd.h> + + int main() {{ + uint8_t bufIn[4096]; + uint8_t bufOut[4096];"#)); + + let (src_top, src_floor) = inst.ty.src_type.get_floor_type(); + if src_floor == dict.parse_desugared("<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::constraint_system::subtype_unify( + &inst.ty.src_type, + &dict.parse_desugared("<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; + }"); + wrappers.push_str(&c_source); + } else { + target.add_type(dict, inst.ty.src_type.clone()); + target.add_type(dict, inst.ty.dst_type.clone()); + + wrappers.push_str(&format!(" + int {} ( + {} const * restrict src, + {} * restrict dst + ) {{ + return {}( (void*)src, (void*)dst ); + }} + ", name, + get_c_repr_arg_type(dict, &inst.ty.src_type), + get_c_repr_arg_type(dict, &inst.ty.dst_type), + inst.instantiated_symbol_name(dict, &HashMap::new()) + )); + } + } + Err(_err) => { + eprintln!("failed to create morphism instatiation"); + return Err(()); + } + } + } + + let mut c_source = target.into_c_source(dict); + c_source.push_str(&wrappers); + + Ok(c_source) +} diff --git a/src/c_gen/gen_main.rs b/src/c_gen/gen_main.rs deleted file mode 100644 index 70847ea..0000000 --- a/src/c_gen/gen_main.rs +++ /dev/null @@ -1,49 +0,0 @@ -use { - laddertypes::{TypeDict, morphism::MorphismInstance, parser::*}, - crate::LdmcPrimMorph, - crate::c_gen::LdmcCTargetMorph, - std::collections::HashMap, -}; - -pub fn generate_main(dict: &mut impl TypeDict, morph: MorphismInstance<LdmcPrimMorph>) -> Result<String, ()> { - let mut target = LdmcCTargetMorph::new(); - let ty = morph.get_type(); - match target.add_instantiation(dict, morph) { - Ok(inst) => { - 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_desugared("<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::constraint_system::subtype_unify( - &ty.src_type, - &dict.parse_desugared("<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) - } - Err(err) => { - eprintln!("failed to create morphism instatiation"); - Err(()) - } - } -} diff --git a/src/c_gen/mod.rs b/src/c_gen/mod.rs index f8c11f9..cf994c5 100644 --- a/src/c_gen/mod.rs +++ b/src/c_gen/mod.rs @@ -1,6 +1,6 @@ pub mod types; pub mod morph; -pub mod gen_main; +pub mod gen_lib; pub use { morph::target_morph::LdmcCTargetMorph diff --git a/src/main.rs b/src/main.rs index 01df9a7..d1e114a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -9,33 +9,66 @@ use { crate::{ morphism::LdmcPrimMorph, parser::morphism_base_parser, - }, - ariadne::{Color, Label, Report, ReportKind, Source}, - chumsky::prelude::*, - laddertypes::{ + }, ariadne::{Color, Label, Report, ReportKind, Source}, chumsky::prelude::*, clap::{Parser, Subcommand}, laddertypes::{ morphism::MorphismType, parser::ParseLadderType, BimapTypeDict - }, - std::{sync::{Arc, RwLock}}, - tiny_ansi::TinyAnsi + }, parser::morphism_type_parser, std::{path::PathBuf, + sync::{Arc, RwLock}}, tiny_ansi::TinyAnsi, + walkdir::WalkDir }; -fn main() { - let mut type_dict = Arc::new(RwLock::new(BimapTypeDict::new())); +#[derive(Parser, Debug)] +#[command(version, about, long_about = None)] +struct Args { + #[arg(short='b', long)] + morphism_base: Vec<PathBuf>, + #[arg(short='m', long="morph")] + morphisms: Vec<String> +} + +fn main() { + let args = Args::parse(); + let mut type_dict = Arc::new(RwLock::new(BimapTypeDict::new())); let mut morphism_base = laddertypes::morphism_base::MorphismBase::<LdmcPrimMorph>::new(); - let mut args = std::env::args().skip(1); - let src_type_arg = args.next().expect("src type expected"); - let dst_type_arg = args.next().expect("dst type expected"); + // 1. load morphism base + let mut mb_paths = args.morphism_base; - for mb_path in args { + // 1.1. pfade ermitteln + let env_var = "MORPHISM_BASE"; + let suffix = ".morphism-base"; + + match std::env::var(env_var) { + Ok(path_str) => { + let path = std::path::Path::new(&path_str); + if path.is_dir() { + for entry in WalkDir::new(path) + .into_iter() + .filter_map(Result::ok) + .filter(|e| e.path().is_file() && e.path().extension().map_or(false, |ext| ext == &suffix[1..])) + { + mb_paths.push(entry.path().into()); + } + } else { + eprintln!("morphism-base path is not a directory: {:?}", path); + } + } + Err(e) => { + eprintln!("failed to read environment variable {}: {}", env_var, e); + } + } + + // 1.2. read files + for mb_path in mb_paths { let src = std::fs::read_to_string(mb_path.clone()).expect("failed to read morphism base"); + + use chumsky::Parser; 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()); + eprintln!("[{}] parse ok.", mb_path.to_str().unwrap().bright_yellow()); for m in morphisms { morphism_base.add_morphism(m); } @@ -57,10 +90,17 @@ 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(""); + // 2. Generate Morphisms + let mut instances = Vec::new(); + for morph_decl in args.morphisms.iter() { + use chumsky::Parser; + if let Ok((name, src_type, dst_type)) = morphism_type_parser(type_dict.clone()).parse(morph_decl.as_str()) { + let ty = MorphismType{ src_type, dst_type }; + instances.push( (name, morphism_base.get_morphism_instance( &ty ).expect("failed to find morphism")) ); + } + } - let ty = MorphismType{ src_type, dst_type }; - let m = morphism_base.get_morphism_instance( &ty ).expect("failed to find morphism"); - println!("{}", crate::c_gen::gen_main::generate_main(&mut type_dict, m).expect("failed to generate main function")); + println!("{}", + crate::c_gen::gen_lib::generate_lib(&mut type_dict, instances).expect("failed to generate main function") + ); } diff --git a/src/parser.rs b/src/parser.rs index ef2acff..24ca0a9 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -1,7 +1,7 @@ use { crate::morphism::LdmcPrimMorph, chumsky::{ prelude::*, text::* - }, laddertypes::{morphism::MorphismType, parser::*, BimapTypeDict, TypeDict}, std::sync::{Arc, RwLock} + }, laddertypes::{TypeTerm, morphism::MorphismType, parser::*, BimapTypeDict, TypeDict}, std::sync::{Arc, RwLock} }; /* morphism-base text format: @@ -59,8 +59,8 @@ pub fn morphism_base_parser( ty_args.push((var_id, kind)); } - let src_type = type_dict.parse_desugared(&src_type.iter().collect::<String>()).expect("couldnt parse src type").sugar(&mut *type_dict); - let dst_type = type_dict.parse_desugared(&dst_type.iter().collect::<String>()).expect("couldnt parse dst type").sugar(&mut *type_dict); + 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"); LdmcPrimMorph { symbol, @@ -76,3 +76,25 @@ pub fn morphism_base_parser( ) } + +pub fn morphism_type_parser( + mut type_dict: Arc<RwLock< BimapTypeDict >> +) -> impl Parser<char, (String, TypeTerm, TypeTerm), Error = Simple<char>> { + ident() + .padded() + .then(just(":").ignored()) + .then( + take_until(just("-->").ignored()) + ) + .then(take_until(end())) + .map({ + let type_dict = type_dict.clone(); + move |((name, src_type), dst_type)| { + ( + name.0, + type_dict.clone().parse(&src_type.0.iter().collect::<String>()).expect("parse type"), + type_dict.clone().parse(&dst_type.0.iter().collect::<String>()).expect("parse type") + ) + } + }) +} From 1116457bcca4f831f525459ce6bbb9b5fe4dbcc9 Mon Sep 17 00:00:00 2001 From: Michael Sippel <micha@fragmental.art> Date: Sat, 10 May 2025 15:00:54 +0200 Subject: [PATCH 15/31] add example C program which generates (de)marshaling with ldmc --- examples/01-uint-example/.gitignore | 1 + examples/01-uint-example/main.c | 14 ++++++++++++++ examples/01-uint-example/makefile | 23 +++++++++++++++++++++++ 3 files changed, 38 insertions(+) create mode 100644 examples/01-uint-example/.gitignore create mode 100644 examples/01-uint-example/main.c create mode 100644 examples/01-uint-example/makefile diff --git a/examples/01-uint-example/.gitignore b/examples/01-uint-example/.gitignore new file mode 100644 index 0000000..567609b --- /dev/null +++ b/examples/01-uint-example/.gitignore @@ -0,0 +1 @@ +build/ diff --git a/examples/01-uint-example/main.c b/examples/01-uint-example/main.c new file mode 100644 index 0000000..2db8422 --- /dev/null +++ b/examples/01-uint-example/main.c @@ -0,0 +1,14 @@ +#include "morphisms.h" + +int main(int argc, char* argv[]) { + if( argc > 1 ) { + uint64_t value; + demarshal( argv[1], &value ); + + uint64_t result = value * value; + + char buf[256]; + marshal( &result, buf ); + printf("%s\n", buf); + } +} diff --git a/examples/01-uint-example/makefile b/examples/01-uint-example/makefile new file mode 100644 index 0000000..528afbf --- /dev/null +++ b/examples/01-uint-example/makefile @@ -0,0 +1,23 @@ +all: build/square +.PHONY: build clean + +build: + mkdir -p build + +build/morphisms.h: build + ldmc \ + -m "marshal: \ + ℕ ~ native.UInt64 \ + --> ℕ ~ <PosInt 10 BigEndian> ~ <Seq~<ValueTerminated 0> <Digit 10>~Char~Ascii~native.UInt8>" \ +\ + -m "demarshal: \ + ℕ ~ <PosInt 10 BigEndian> ~ <Seq~<ValueTerminated 0> <Digit 10>~Char~Ascii~native.UInt8> \ + --> ℕ ~ native.UInt64 " \ +\ + >| build/morphisms.h + +build/square: build build/morphisms.h + gcc -Os -I../../morphisms/runtime/include/ -Ibuild main.c -o build/square + +clean: + rm build/ -rf From a58ac1a69c451e1785edbe0a3b771bdbb9f9aceb Mon Sep 17 00:00:00 2001 From: Michael Sippel <micha@fragmental.art> Date: Sat, 10 May 2025 15:16:51 +0200 Subject: [PATCH 16/31] in generation of main function, fix case that input/output buffer is a nullterm string --- src/c_gen/gen_lib.rs | 17 +++++++++++------ src/main.rs | 15 +++++++++------ 2 files changed, 20 insertions(+), 12 deletions(-) diff --git a/src/c_gen/gen_lib.rs b/src/c_gen/gen_lib.rs index fa2ce88..f8858bb 100644 --- a/src/c_gen/gen_lib.rs +++ b/src/c_gen/gen_lib.rs @@ -21,18 +21,23 @@ pub fn generate_lib( uint8_t bufIn[4096]; uint8_t bufOut[4096];"#)); - let (src_top, src_floor) = inst.ty.src_type.get_floor_type(); - if src_floor == dict.parse_desugared("<Seq~<ValueTerminated 0> native.UInt8>").expect("").sugar(dict) { + if let Ok(_) = laddertypes::subtype_unify( + &inst.ty.src_type, + &dict.parse("<Seq~<ValueTerminated 0> Char~Ascii~native.UInt8>").expect("") + ) { 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()))); + c_source.push_str( + &format!(r#"FUSE( {}, (void const*)bufIn, (void*)bufOut );"#, + inst.instantiated_symbol_name(dict, &HashMap::new())) + ); - if let Ok(ψ) = laddertypes::constraint_system::subtype_unify( - &inst.ty.src_type, - &dict.parse_desugared("<Seq~<ValueTerminated 0> native.UInt8>").expect("").sugar(dict) + if let Ok(ψ) = laddertypes::subtype_unify( + &inst.ty.dst_type, + &dict.parse("<Seq~<ValueTerminated 0> native.UInt8>").expect("") ) { c_source.push_str("printf(\"%s\\n\", bufOut);"); } else { diff --git a/src/main.rs b/src/main.rs index d1e114a..b7111d6 100644 --- a/src/main.rs +++ b/src/main.rs @@ -9,12 +9,15 @@ use { crate::{ morphism::LdmcPrimMorph, parser::morphism_base_parser, - }, ariadne::{Color, Label, Report, ReportKind, Source}, chumsky::prelude::*, clap::{Parser, Subcommand}, laddertypes::{ - morphism::MorphismType, - parser::ParseLadderType, BimapTypeDict - }, parser::morphism_type_parser, std::{path::PathBuf, - sync::{Arc, RwLock}}, tiny_ansi::TinyAnsi, - walkdir::WalkDir + }, + laddertypes::{ + morphism::MorphismType, BimapTypeDict + }, parser::morphism_type_parser, + ariadne::{Color, Label, Report, ReportKind, Source}, + clap::Parser, + walkdir::WalkDir, + tiny_ansi::TinyAnsi, + std::{path::PathBuf, sync::{Arc, RwLock}}, }; #[derive(Parser, Debug)] From 783c70b2e26ba20e0ff6ceabd27d40904522677b Mon Sep 17 00:00:00 2001 From: Michael Sippel <micha@fragmental.art> Date: Sat, 10 May 2025 15:40:49 +0200 Subject: [PATCH 17/31] add output option in cli arguments --- src/main.rs | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/src/main.rs b/src/main.rs index b7111d6..5951618 100644 --- a/src/main.rs +++ b/src/main.rs @@ -17,7 +17,7 @@ use { clap::Parser, walkdir::WalkDir, tiny_ansi::TinyAnsi, - std::{path::PathBuf, sync::{Arc, RwLock}}, + std::{path::PathBuf, sync::{Arc, RwLock}, io::Write}, }; #[derive(Parser, Debug)] @@ -27,7 +27,10 @@ struct Args { morphism_base: Vec<PathBuf>, #[arg(short='m', long="morph")] - morphisms: Vec<String> + morphisms: Vec<String>, + + #[arg(short='o', long)] + output: Option<PathBuf> } fn main() { @@ -103,7 +106,11 @@ fn main() { } } - println!("{}", - crate::c_gen::gen_lib::generate_lib(&mut type_dict, instances).expect("failed to generate main function") - ); + let c_source = crate::c_gen::gen_lib::generate_lib(&mut type_dict, instances).expect("failed to generate library"); + if let Some(out_path) = args.output { + let mut file = std::fs::File::create(out_path).expect("failed to open output file"); + file.write_all(c_source.as_bytes()).expect("failed to write output file"); + } else { + println!("{}", c_source); + } } From efa584dfb5c49ada3d97ce13d75225434f10ab36 Mon Sep 17 00:00:00 2001 From: Michael Sippel <micha@fragmental.art> Date: Sat, 10 May 2025 16:25:36 +0200 Subject: [PATCH 18/31] update test.sh to new cli features --- test/test.sh | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/test/test.sh b/test/test.sh index 0e3fc9b..f33ab02 100755 --- a/test/test.sh +++ b/test/test.sh @@ -8,13 +8,12 @@ run_test_case() { ----------------------------------------------------------------------------- Running test case ${TEST_NAME}" - ldmc "${SRC_TYPE}" "${DST_TYPE}" ../morphisms/*.morphism-base 2>|.tmp/ldmc_err 1>| target/src/${TEST_NAME}.c \ + ldmc -m "main : ${SRC_TYPE} --> ${DST_TYPE}" -o target/src/${TEST_NAME}.c 2>|.tmp/ldmc_err \ || (echo "... error at generation:"; cat .tmp/ldmc_err; return -1); gcc -I../morphisms/runtime/include target/src/${TEST_NAME}.c -o target/${TEST_NAME} \ || (echo "... error at compilation:"; return -2); - LEN="$(echo -n "${EXPECT}" | wc -c)" RESULT="$(echo -n ${INPUT} | ./target/${TEST_NAME} 2>.tmp/target_err | head -c ${LEN})" From 4a705241fe4139d34e2aac852aeeb500fbe6cb64 Mon Sep 17 00:00:00 2001 From: Michael Sippel <micha@fragmental.art> Date: Sat, 10 May 2025 16:27:56 +0200 Subject: [PATCH 19/31] manage include blocks & only output required blocks once --- src/c_gen/gen_lib.rs | 6 ++-- src/c_gen/morph/target_morph.rs | 54 +++++++++++++++++++++++---------- src/main.rs | 27 ++++++++++------- 3 files changed, 58 insertions(+), 29 deletions(-) diff --git a/src/c_gen/gen_lib.rs b/src/c_gen/gen_lib.rs index f8858bb..95359cc 100644 --- a/src/c_gen/gen_lib.rs +++ b/src/c_gen/gen_lib.rs @@ -1,12 +1,14 @@ use { - super::types::get_c_repr_arg_type, crate::{c_gen::LdmcCTargetMorph, LdmcPrimMorph}, laddertypes::{morphism::MorphismInstance, parser::*, TypeDict}, std::collections::HashMap + super::types::get_c_repr_arg_type, crate::{c_gen::LdmcCTargetMorph, LdmcPrimMorph}, laddertypes::{morphism::MorphismInstance, parser::*, MorphismType, TypeDict}, std::collections::HashMap }; pub fn generate_lib( dict: &mut impl TypeDict, + include_blocks: Vec< String >, + include_dependencies: HashMap< MorphismType, usize >, morphisms: Vec< (String, MorphismInstance<LdmcPrimMorph>) > ) -> Result<String, ()> { - let mut target = LdmcCTargetMorph::new(); + let mut target = LdmcCTargetMorph::new( include_blocks, include_dependencies ); let mut wrappers = String::new(); for (name, morph) in morphisms { diff --git a/src/c_gen/morph/target_morph.rs b/src/c_gen/morph/target_morph.rs index fcb90fb..161d6fa 100644 --- a/src/c_gen/morph/target_morph.rs +++ b/src/c_gen/morph/target_morph.rs @@ -1,18 +1,20 @@ use { crate::{ c_gen::types::{ - encode_morph_type_to_symbol, get_c_repr_definition, get_c_repr_type, encode_type_to_value + encode_morph_type_to_symbol, encode_type_to_value, get_c_repr_definition, get_c_repr_kind, get_c_repr_type }, morphism::LdmcPrimMorph }, laddertypes::{ - parser::*, MorphismInstance, TypeDict, TypeTerm, Morphism + parser::*, Morphism, MorphismInstance, MorphismType, TypeDict, TypeTerm }, std::collections::HashMap }; pub struct LdmcCTargetMorph { - includes: Vec< String >, + include_blocks: Vec< String >, + include_dependencies: HashMap< MorphismType, usize >, + active_includes: Vec< usize >, active_types: Vec< TypeTerm >, active_instantiations: Vec< LdmcPrimMorph >, active_lenpfx_types: Vec< (TypeTerm, TypeTerm) >, @@ -21,19 +23,35 @@ pub struct LdmcCTargetMorph { } impl LdmcCTargetMorph { - pub fn new() -> Self { - LdmcCTargetMorph { - includes: vec![ - "#include <stdint.h>".into(), - "#include <array/length-prefix.h>".into(), - "#define FUSE(morph, src, dst) { int result = morph(src,dst); if(result) return result; }".into(), - ], + pub fn add_required_include_block(&mut self, block: String) { + let i = self.include_blocks.len(); + self.active_includes.push(i); + self.include_blocks.push(block); + } + + pub fn new( + include_blocks: Vec< String >, + include_dependencies: HashMap< MorphismType, usize > + ) -> Self { + let mut m = LdmcCTargetMorph { + include_blocks, + include_dependencies, + active_includes: Vec::new(), active_instantiations: Vec::new(), active_types: Vec::new(), active_lenpfx_types: Vec::new(), typedefs: Vec::new(), macro_calls: Vec::new() - } + }; + + m.add_required_include_block( + "/* default ldmc includes */ +#include <stdint.h> +#define FUSE(morph, src, dst) { int result = morph(src,dst); if(result) return result; } + +".into() + ); + m } pub fn add_type(&mut self, dict: &mut impl TypeDict, ty: TypeTerm) { @@ -106,15 +124,14 @@ impl LdmcCTargetMorph { pub fn into_c_source(mut self, dict: &mut impl TypeDict) -> String { let mut source = String::new(); - self.includes.dedup(); + self.active_includes.dedup(); + self.typedefs.dedup(); self.macro_calls.dedup(); - self.active_types.dedup(); - for inc in self.includes { - source.push_str(&inc); + for i in self.active_includes { + source.push_str( &self.include_blocks[i] ); source.push('\n'); } - source.push('\n'); for typedef in self.typedefs { @@ -146,6 +163,11 @@ impl LdmcCTargetMorph { match &morph_inst { MorphismInstance::Primitive { ψ, σ, morph } => { + if let Some(i) = self.include_dependencies.get(&morph.get_type()) { + self.active_includes.push(*i); + } + + let mut c_source = String::new(); for (ty_id, kind) in morph.type_args.iter() { if let laddertypes::TypeID::Var(var_id) = ty_id { diff --git a/src/main.rs b/src/main.rs index 5951618..8e8f40b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -9,15 +9,9 @@ use { crate::{ morphism::LdmcPrimMorph, parser::morphism_base_parser, - }, - laddertypes::{ - morphism::MorphismType, BimapTypeDict - }, parser::morphism_type_parser, - ariadne::{Color, Label, Report, ReportKind, Source}, - clap::Parser, - walkdir::WalkDir, - tiny_ansi::TinyAnsi, - std::{path::PathBuf, sync::{Arc, RwLock}, io::Write}, + }, ariadne::{Color, Label, Report, ReportKind, Source}, clap::Parser, laddertypes::{ + morphism::MorphismType, BimapTypeDict, Morphism + }, parser::morphism_type_parser, std::{io::Write, path::PathBuf, sync::{Arc, RwLock}}, tiny_ansi::TinyAnsi, walkdir::WalkDir }; #[derive(Parser, Debug)] @@ -66,6 +60,10 @@ fn main() { } // 1.2. read files + + let mut include_blocks = Vec::new(); + let mut include_dependencies = std::collections::HashMap::new(); + for mb_path in mb_paths { let src = std::fs::read_to_string(mb_path.clone()).expect("failed to read morphism base"); @@ -73,9 +71,16 @@ 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.to_str().unwrap().bright_yellow()); + + let include_idx = include_blocks.len(); + + let mut includes_prefixed = format!("/* from `{}` */", mb_path.display()); + includes_prefixed.push_str(&includes); + include_blocks.push(includes_prefixed); + for m in morphisms { + include_dependencies.insert( m.get_type(), include_idx ); morphism_base.add_morphism(m); } } @@ -106,7 +111,7 @@ fn main() { } } - let c_source = crate::c_gen::gen_lib::generate_lib(&mut type_dict, instances).expect("failed to generate library"); + let c_source = crate::c_gen::gen_lib::generate_lib(&mut type_dict, include_blocks, include_dependencies, instances).expect("failed to generate library"); if let Some(out_path) = args.output { let mut file = std::fs::File::create(out_path).expect("failed to open output file"); file.write_all(c_source.as_bytes()).expect("failed to write output file"); From 6f0a0f5927f748b0e80ee988a18cbc392103df0d Mon Sep 17 00:00:00 2001 From: Michael Sippel <micha@fragmental.art> Date: Sat, 10 May 2025 16:28:58 +0200 Subject: [PATCH 20/31] when generating #defines for values of type variables, distinguish between variables of type 'Type' and others --- src/c_gen/morph/target_morph.rs | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/src/c_gen/morph/target_morph.rs b/src/c_gen/morph/target_morph.rs index 161d6fa..2eb25b0 100644 --- a/src/c_gen/morph/target_morph.rs +++ b/src/c_gen/morph/target_morph.rs @@ -171,23 +171,21 @@ impl LdmcCTargetMorph { let mut c_source = String::new(); for (ty_id, kind) in morph.type_args.iter() { 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 = get_c_repr_type(dict, val); - c_source.push_str(&format!(" #define {} {}\n", dict.get_typename(&ty_id).unwrap(), type_var_value)); - } - //} + if let Some(val) = σ.get(ty_id) { + let type_var_value = + if kind == "Type" { + get_c_repr_type(dict, val) + } 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() { 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())); - //} + c_source.push_str(&format!("\n #undef {}", dict.get_typename(&ty_id).unwrap())); } } From ea2504ff072458ce95e2d0f912d277707053f1b6 Mon Sep 17 00:00:00 2001 From: Michael Sippel <micha@fragmental.art> Date: Sat, 10 May 2025 17:53:31 +0200 Subject: [PATCH 21/31] morphisms: fix bitshift in lenpfx to msb-cont --- morphisms/length_prefix.morphism-base | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/morphisms/length_prefix.morphism-base b/morphisms/length_prefix.morphism-base index a694931..1700361 100644 --- a/morphisms/length_prefix.morphism-base +++ b/morphisms/length_prefix.morphism-base @@ -29,13 +29,13 @@ morph_array_as_lenpfx_to_continuation_bit (T:Type) ``` for( uint64_t i = 0; i < src->len; ++i ) { const size_t n_bits = 8*sizeof(T); - if( src->items[i] & (1<<(n_bits-1)) ) { - fprintf(stderr, "error: value to high for MsbContinuation\n"); + if( src->items[i] & ((uint64_t)1<<(n_bits-1)) ) { + fprintf(stderr, "error: value has MSB set, while being used in MsbContinuation sequence!\n"); return -1; } dst[i] = src->items[i]; if( i+1 < src->len ) - dst[i] |= (1<<(n_bits-1)); + dst[i] |= ((uint64_t)1<<(n_bits-1)); } ``` From 692a34c2574de8e3f559409e23284feffb4acee5 Mon Sep 17 00:00:00 2001 From: Michael Sippel <micha@fragmental.art> Date: Wed, 14 May 2025 10:19:48 +0200 Subject: [PATCH 22/31] main: when loading morphism base, remove . from path suffix variable --- src/main.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/main.rs b/src/main.rs index 8e8f40b..675c12d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -37,7 +37,7 @@ fn main() { // 1.1. pfade ermitteln let env_var = "MORPHISM_BASE"; - let suffix = ".morphism-base"; + let suffix = "morphism-base"; match std::env::var(env_var) { Ok(path_str) => { @@ -46,7 +46,10 @@ fn main() { for entry in WalkDir::new(path) .into_iter() .filter_map(Result::ok) - .filter(|e| e.path().is_file() && e.path().extension().map_or(false, |ext| ext == &suffix[1..])) + .filter(|e| + e.path().is_file() && + e.path().extension().map_or(false, |ext| ext == suffix) + ) { mb_paths.push(entry.path().into()); } From 7dd6352760b54b438424c9022aa7421b996270b1 Mon Sep 17 00:00:00 2001 From: Michael Sippel <micha@fragmental.art> Date: Wed, 14 May 2025 10:20:55 +0200 Subject: [PATCH 23/31] code generation: only use scanf/printf on newline('\n') terminated strings --- src/c_gen/gen_lib.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/c_gen/gen_lib.rs b/src/c_gen/gen_lib.rs index 95359cc..4615fab 100644 --- a/src/c_gen/gen_lib.rs +++ b/src/c_gen/gen_lib.rs @@ -25,15 +25,15 @@ pub fn generate_lib( if let Ok(_) = laddertypes::subtype_unify( &inst.ty.src_type, - &dict.parse("<Seq~<ValueTerminated 0> Char~Ascii~native.UInt8>").expect("") + &dict.parse("<Seq~<ValueTerminated '\\n'> Char~Ascii~native.UInt8>").expect("") ) { - c_source.push_str("scanf(\"%s\", bufIn);"); + c_source.push_str("scanf(\"%s\", bufIn);\n"); } else { - c_source.push_str("read(0, bufIn, sizeof(bufIn));"); + c_source.push_str("read(0, bufIn, sizeof(bufIn));\n"); } c_source.push_str( - &format!(r#"FUSE( {}, (void const*)bufIn, (void*)bufOut );"#, + &format!(r#"FUSE( {}, (void const*)bufIn, (void*)bufOut );\n"#, inst.instantiated_symbol_name(dict, &HashMap::new())) ); @@ -41,9 +41,9 @@ pub fn generate_lib( &inst.ty.dst_type, &dict.parse("<Seq~<ValueTerminated 0> native.UInt8>").expect("") ) { - c_source.push_str("printf(\"%s\\n\", bufOut);"); + c_source.push_str("printf(\"%s\\n\", bufOut);\n"); } else { - c_source.push_str("write(1, bufOut, sizeof(bufOut));"); + c_source.push_str("write(1, bufOut, sizeof(bufOut));\n"); } c_source.push_str(" return 0; From 24f9a0f5b5c71653b913eb500c08c4f4642d29a6 Mon Sep 17 00:00:00 2001 From: Michael Sippel <micha@fragmental.art> Date: Wed, 14 May 2025 10:28:31 +0200 Subject: [PATCH 24/31] C code gen: rename include block to header block --- src/c_gen/morph/target_morph.rs | 44 ++++++++++++++++----------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/src/c_gen/morph/target_morph.rs b/src/c_gen/morph/target_morph.rs index 2eb25b0..dd075bf 100644 --- a/src/c_gen/morph/target_morph.rs +++ b/src/c_gen/morph/target_morph.rs @@ -12,21 +12,21 @@ use { }; pub struct LdmcCTargetMorph { - include_blocks: Vec< String >, - include_dependencies: HashMap< MorphismType, usize >, - active_includes: Vec< usize >, + header_blocks: Vec< String >, + header_dependencies: HashMap< MorphismType, usize >, + active_headers: Vec< usize >, active_types: Vec< TypeTerm >, - active_instantiations: Vec< LdmcPrimMorph >, + active_morphisms: Vec< LdmcPrimMorph >, active_lenpfx_types: Vec< (TypeTerm, TypeTerm) >, typedefs: Vec< String >, macro_calls: Vec< String > } impl LdmcCTargetMorph { - pub fn add_required_include_block(&mut self, block: String) { - let i = self.include_blocks.len(); - self.active_includes.push(i); - self.include_blocks.push(block); + pub fn add_required_header_block(&mut self, block: String) { + let i = self.header_blocks.len(); + self.active_headers.push(i); + self.header_blocks.push(block); } pub fn new( @@ -34,18 +34,18 @@ impl LdmcCTargetMorph { include_dependencies: HashMap< MorphismType, usize > ) -> Self { let mut m = LdmcCTargetMorph { - include_blocks, - include_dependencies, - active_includes: Vec::new(), - active_instantiations: Vec::new(), + header_blocks: include_blocks, + header_dependencies: include_dependencies, + active_headers: Vec::new(), + active_morphisms: Vec::new(), active_types: Vec::new(), active_lenpfx_types: Vec::new(), typedefs: Vec::new(), macro_calls: Vec::new() }; - m.add_required_include_block( - "/* default ldmc includes */ + m.add_required_header_block( + "/* default ldmc header */ #include <stdint.h> #define FUSE(morph, src, dst) { int result = morph(src,dst); if(result) return result; } @@ -111,8 +111,8 @@ impl LdmcCTargetMorph { morph: MorphismInstance<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()); + if ! self.active_morphisms.contains(&new_inst) { + self.active_morphisms.push(new_inst.clone()); } let ty = new_inst.get_type().strip_halo(); @@ -124,12 +124,12 @@ impl LdmcCTargetMorph { pub fn into_c_source(mut self, dict: &mut impl TypeDict) -> String { let mut source = String::new(); - self.active_includes.dedup(); + self.active_headers.dedup(); self.typedefs.dedup(); self.macro_calls.dedup(); - for i in self.active_includes { - source.push_str( &self.include_blocks[i] ); + for i in self.active_headers { + source.push_str( &self.header_blocks[i] ); source.push('\n'); } source.push('\n'); @@ -147,7 +147,7 @@ impl LdmcCTargetMorph { } source.push('\n'); - for m in self.active_instantiations { + for m in self.active_morphisms { source.push_str(&m.generate_instantiation(dict, &HashMap::new()).expect("cant create function")); } source @@ -163,8 +163,8 @@ impl LdmcCTargetMorph { match &morph_inst { MorphismInstance::Primitive { ψ, σ, morph } => { - if let Some(i) = self.include_dependencies.get(&morph.get_type()) { - self.active_includes.push(*i); + if let Some(i) = self.header_dependencies.get(&morph.get_type()) { + self.active_headers.push(*i); } From 0c9a4ccc8bd8de8158c3c24cbdf4bd1a9374e6c2 Mon Sep 17 00:00:00 2001 From: Michael Sippel <micha@fragmental.art> Date: Fri, 16 May 2025 02:33:17 +0200 Subject: [PATCH 25/31] example: use -o option in makefile --- examples/01-uint-example/makefile | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/examples/01-uint-example/makefile b/examples/01-uint-example/makefile index 528afbf..915101b 100644 --- a/examples/01-uint-example/makefile +++ b/examples/01-uint-example/makefile @@ -8,13 +8,13 @@ build/morphisms.h: build ldmc \ -m "marshal: \ ℕ ~ native.UInt64 \ - --> ℕ ~ <PosInt 10 BigEndian> ~ <Seq~<ValueTerminated 0> <Digit 10>~Char~Ascii~native.UInt8>" \ -\ + --> ℕ ~ <PosInt 10 BigEndian> ~ <Seq~<ValueTerminated 0> <Digit 10>~Char~Ascii~native.UInt8> \ + " \ -m "demarshal: \ ℕ ~ <PosInt 10 BigEndian> ~ <Seq~<ValueTerminated 0> <Digit 10>~Char~Ascii~native.UInt8> \ - --> ℕ ~ native.UInt64 " \ -\ - >| build/morphisms.h + --> ℕ ~ native.UInt64 \ + " \ + -o build/morphisms.h build/square: build build/morphisms.h gcc -Os -I../../morphisms/runtime/include/ -Ibuild main.c -o build/square From 0eb8074644f60eeec0c86945bdb90f658ed62693 Mon Sep 17 00:00:00 2001 From: Michael Sippel <micha@fragmental.art> Date: Fri, 16 May 2025 02:34:18 +0200 Subject: [PATCH 26/31] digit morphism: also print Radix in warning --- morphisms/digit.morphism-base | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/morphisms/digit.morphism-base b/morphisms/digit.morphism-base index f037823..75ab631 100644 --- a/morphisms/digit.morphism-base +++ b/morphisms/digit.morphism-base @@ -36,7 +36,7 @@ morph_digit_as_char_to_uint64 (Radix:ℤ) else if( *src >= 'A' && *src <= 'F') *dst = 0xa + *src - 'A'; else { - fprintf(stderr, "invalid digit 0x%x\n", *src); + fprintf(stderr, "invalid digit 0x%x (radix %u)\n", *src, Radix); return -1; } From 76c005ac8bb743d736cfc62bfd9b6ab23c32a039 Mon Sep 17 00:00:00 2001 From: Michael Sippel <micha@fragmental.art> Date: Fri, 16 May 2025 13:51:45 +0200 Subject: [PATCH 27/31] morph lenpfx to valterm: make item type generic --- morphisms/length_prefix.morphism-base | 6 +++--- morphisms/value_delim.morphism-base | 5 ++++- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/morphisms/length_prefix.morphism-base b/morphisms/length_prefix.morphism-base index 1700361..4a82515 100644 --- a/morphisms/length_prefix.morphism-base +++ b/morphisms/length_prefix.morphism-base @@ -13,9 +13,9 @@ morph_array_as_valterm_to_lenpfx (Terminator:native.UInt8) ``` -morph_array_as_lenpfx_to_valterm (Terminator:native.UInt8) - <Seq~<LengthPrefix native.UInt64> native.UInt8> ---> <Seq~<ValueTerminated Terminator> native.UInt8> +morph_array_as_lenpfx_to_valterm (T: Type, Terminator: T) + <Seq~<LengthPrefix native.UInt64> T> +--> <Seq~<ValueTerminated Terminator> T> ``` for( uint64_t i = 0; i < src->len; ++i ) *dst++ = src->items[i]; diff --git a/morphisms/value_delim.morphism-base b/morphisms/value_delim.morphism-base index 6e94459..1823634 100644 --- a/morphisms/value_delim.morphism-base +++ b/morphisms/value_delim.morphism-base @@ -3,7 +3,7 @@ #include <stdlib.h> ``` -morph_seqseq_valsep_uint8 (T: Type, SrcDelim: T, DstDelim: T) +morph_valsep_delim (T: Type, SrcDelim: T, DstDelim: T) < Seq <Seq T> > ~ < ValueSep SrcDelim T > ~ < Seq~<LengthPrefix native.UInt64> T > @@ -22,6 +22,9 @@ morph_seqseq_valsep_uint8 (T: Type, SrcDelim: T, DstDelim: T) if( DstDelim == '\n' ) { PRESCAN_LENGTH_PREFIX_CALL(nativeUInt64, T, push)( dst, '\\' ); PRESCAN_LENGTH_PREFIX_CALL(nativeUInt64, T, push)( dst, 'n' ); + } else { + PRESCAN_LENGTH_PREFIX_CALL(nativeUInt64, T, push)( dst, '\\' ); + PRESCAN_LENGTH_PREFIX_CALL(nativeUInt64, T, push)( dst, DstDelim ); } } else { PRESCAN_LENGTH_PREFIX_CALL(nativeUInt64, T, push)( dst, src->items[i] ); From 62f0ff9eac914d207eb60a42d193c906be10243f Mon Sep 17 00:00:00 2001 From: Michael Sippel <micha@fragmental.art> Date: Fri, 16 May 2025 13:53:19 +0200 Subject: [PATCH 28/31] add array morphisms : StaticLength <--> LengthPrefix --- morphisms/length_prefix.morphism-base | 32 ++++++++++++++++++++++----- 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/morphisms/length_prefix.morphism-base b/morphisms/length_prefix.morphism-base index 4a82515..70cd3b7 100644 --- a/morphisms/length_prefix.morphism-base +++ b/morphisms/length_prefix.morphism-base @@ -3,15 +3,35 @@ #include <array/length-prefix.h> ``` -morph_array_as_valterm_to_lenpfx (Terminator:native.UInt8) - <Seq~<ValueTerminated Terminator> native.UInt8> ---> <Seq~<LengthPrefix native.UInt64> native.UInt8> +morph_array_as_static_to_lenpfx (Len: ℤ, T: Type) + <Seq~<StaticLength Len> T> +--> <Seq~<LengthPrefix native.UInt64> T> ``` - length_prefix_nativeUInt64_array_nativeUInt8_clear(dst); - while( *src != Terminator ) - length_prefix_nativeUInt64_array_nativeUInt8_push(dst, *src++); + PRESCAN_LENGTH_PREFIX_CALL(nativeUInt64, T, clear)( dst ); + for( nativeUInt64 i = 0; i < Len; ++i ) + PRESCAN_LENGTH_PREFIX_CALL(nativeUInt64, T, push)( dst, src->items[i] ); ``` +morph_array_as_lenpfx_to_static (Len: ℤ, T: Type) + <Seq~<LengthPrefix native.UInt64> T> +--> <Seq~<StaticLength Len> T> +``` + nativeUInt64 i; + for( i = 0; i < Len && i < src->len; ++i ) + dst->items[i] = src->items[i]; + + if( i < Len ) + memset( &dst[i], 0, (Len-i) * sizeof(T) ); +``` + +morph_array_as_valterm_to_lenpfx (T: Type, Terminator:T) + <Seq~<ValueTerminated Terminator> T> +--> <Seq~<LengthPrefix native.UInt64> T> +``` + PRESCAN_LENGTH_PREFIX_CALL(nativeUInt64, T, push)( dst ); + while( *src != Terminator ) + PRESCAN_LENGTH_PREFIX_CALL(nativeUInt64, T, push)( dst, *src++ ); +``` morph_array_as_lenpfx_to_valterm (T: Type, Terminator: T) <Seq~<LengthPrefix native.UInt64> T> From dfa364bc0f73ffa87134ae8fe27587021253dcbd Mon Sep 17 00:00:00 2001 From: Michael Sippel <micha@fragmental.art> Date: Fri, 16 May 2025 13:55:36 +0200 Subject: [PATCH 29/31] length prefix morphism: generic calls to functions with C macro --- morphisms/value_delim.morphism-base | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/morphisms/value_delim.morphism-base b/morphisms/value_delim.morphism-base index 1823634..d4ab039 100644 --- a/morphisms/value_delim.morphism-base +++ b/morphisms/value_delim.morphism-base @@ -47,17 +47,17 @@ morph_seqseq_as_valsep_to_lenpfx (T: Type, Delim: T, EscKey: T) ``` length_prefix_nativeUInt64_array_nativeUInt64_clear( dst ); - struct LengthPrefix_nativeUInt64_Array_nativeUInt8 * cur_item = NULL; + LENGTH_PREFIX_ARRAY_TYPE( nativeUInt64, T ) * cur_item = NULL; - uint8_t const * start = &src->items[0]; - uint8_t const * cur = start; - uint8_t const * end = &src->items[src->len]; + T const * start = &src->items[0]; + T const * cur = start; + T const * end = &src->items[src->len]; while( cur < end ) { if( *cur == Delim || cur+1 == end ) { uint64_t len = cur - start; - cur_item = malloc( sizeof(uint64_t) + sizeof(uint8_t) * len ); + cur_item = malloc( sizeof(uint64_t) + sizeof(T) * len ); cur_item->len = len; memcpy( cur_item->items, start, len ); @@ -80,17 +80,17 @@ morph_seqeq_as_lenpfx_to_valsep (T: Type, Delim: T, EscKey: T) ~ < ValueSep T Delim > ~ < Seq~<LengthPrefix native.UInt64> T > ``` - length_prefix_nativeUInt64_array_nativeUInt8_clear( dst ); + PRESCAN_LENGTH_PREFIX_CALL(nativeUInt64, T, clear)( dst ); for( uint64_t i = 0; i < src->len; ++i ) { - LengthPrefix_nativeUInt64_Array_nativeUInt8_t * item = src->items[i]; + LENGTH_PREFIX_ARRAY_TYPE( nativeUInt64, T ) * item = src->items[i]; for( uint64_t j = 0; j < item->len; ++j ) { - length_prefix_nativeUInt64_array_nativeUInt8_push( items->items[j] ); + PRESCAN_LENGTH_PREFIX_CALL( nativeUInt64, T, push )( items->items[j] ); } if( i+1 < src->len ) { - length_prefix_nativeUInt64_array_nativeUInt8_push( Delim ); + PRESCAN_LENGTH_PREFIX_CALL( nativeUInt64, T, push )( Delim ); } } ``` From edd34415111e77e952e588a34cd6cd4bc3332c1f Mon Sep 17 00:00:00 2001 From: Michael Sippel <micha@fragmental.art> Date: Tue, 27 May 2025 15:38:57 +0200 Subject: [PATCH 30/31] todo.md --- todo.md | 79 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100644 todo.md diff --git a/todo.md b/todo.md new file mode 100644 index 0000000..39dd24f --- /dev/null +++ b/todo.md @@ -0,0 +1,79 @@ +* BUG: cant find morphism when path is trivial, or when + *some* members of a struct have trivial morphism + +* BUG: -O3 kills some Morphisms + +* BUG: erroneous code generation with Packed struct layout + +* type Aliases / typedefs (load from input file) + -- platform specializations + -- shortcuts + +* add highest-common-rung to generated morphism names + (to avoid potential ambiguities) + +* add bounds to Morphism type: + - subtype bounds + - trait bounds + - value bounds + +* data dependence: + - Each Struct creates a Context, + where a struct member becomes a type-variable, + available after it has been parsed from the input buffer. + - need some kind of partial Order over the member data fields, + to express parsing dependencies. + +* bounds: + -> ℕ ~ UInt64 ---> ℕ ~ UInt8 + - know that value fits into UInt8 ? + + -> <Digit 128> ~ UInt64 --> <Digit 128> ~ UInt8 + allows the following path: + <Digit 128> ~ UInt64 + -> <Digit 128> ~ Char ~ Ascii ~ native.UInt8 + -> <Digit 128> ~ native.UInt8 + + this will result in 'invalid digits' that are out of the ascii range + and is not wanted. + maybe the Morphism from digit to char should not exist for radix 128 (->value bounds on type vars)? + -fixed by adding explicit <Digit R>~UInt64 -morph-> <Digit R>~UInt8 + +* type descriptions: signed posints? + - Include minus sign '-' into the <Digit Radix> type ? + - or use [<Digit Radix> | Sign] ? + - or rather <SignedPosInt Radix Endianness> ~ { + sign: <Option Sign~Char>; + digits: <Seq <Digit 10>~Char> + }; + - ? + +* size estimation & memory allocation + - from each type definition, we need to derive + a form for an "allocation schema", + of which a value instance of that type defines + concrete length values for arrays and members + and thus the total required buffer size. + + - in parallel to each morphism we need to know + the output-allocation schema in accordance to + a given allocation schema of the input data. + + - Complex morphisms allocate a double buffering + with maximum required size at each point in the chain + + - optional: allocation free morphisms for members in struct morphism ? + - In-Place Morphisms + + +* improve debugability of "no morphism path found" + - find a heuristic to guess "implementation overhead" of + a missing morphism by its type + - Step 1: Calculate Connected Components of src and dst Type ; + - Step 2: For each combination of a vertex-pair from src and dst Components, + calculate the implementation overhead heuristic ; + - Step 3: suggest to the developer the n smallest morphism types that would + bridge the two components + + +* allow to define (ladder-typed) functions, not just morphisms From cff14cf09624e2d4502e7e0f1b46e2919b24539a Mon Sep 17 00:00:00 2001 From: Michael Sippel <micha@fragmental.art> Date: Wed, 28 May 2025 17:33:22 +0200 Subject: [PATCH 31/31] add MorphismInstance::Id --- src/c_gen/gen_lib.rs | 3 ++- src/c_gen/morph/target_morph.rs | 9 +++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/c_gen/gen_lib.rs b/src/c_gen/gen_lib.rs index 4615fab..13ffa3e 100644 --- a/src/c_gen/gen_lib.rs +++ b/src/c_gen/gen_lib.rs @@ -33,7 +33,8 @@ pub fn generate_lib( } c_source.push_str( - &format!(r#"FUSE( {}, (void const*)bufIn, (void*)bufOut );\n"#, + &format!(r#"FUSE( {}, (void const*)bufIn, (void*)bufOut ); +"#, inst.instantiated_symbol_name(dict, &HashMap::new())) ); diff --git a/src/c_gen/morph/target_morph.rs b/src/c_gen/morph/target_morph.rs index dd075bf..cea7ed4 100644 --- a/src/c_gen/morph/target_morph.rs +++ b/src/c_gen/morph/target_morph.rs @@ -162,6 +162,15 @@ impl LdmcCTargetMorph { let symbol = encode_morph_type_to_symbol(dict, &ty); match &morph_inst { + MorphismInstance::Id { ψ } => { + self.add_required_header_block("#include <string.h>".into()); + Ok(LdmcPrimMorph { + symbol, + type_args: Vec::new(), + ty: MorphismType { src_type: ψ.clone(), dst_type: ψ.clone() }, + c_source: String::from("memcpy(dst, src, sizeof(*src));") + }) + } MorphismInstance::Primitive { ψ, σ, morph } => { if let Some(i) = self.header_dependencies.get(&morph.get_type()) { self.active_headers.push(*i);