ldmc/src/c_gen.rs

280 lines
12 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

use {
crate::{c_gen_types::{encode_morph_type_to_symbol, encode_type_to_symbol, encode_type_to_value, get_c_repr_type}, morphism::LdmcPrimMorph, struct_layout::{get_type_size, LayoutType, ObjectSize, StructLayout}}, chumsky::{chain::Chain, primitive::Container}, laddertypes::{morphism::{Morphism, MorphismInstance}, morphism_sugared::{MorphismInstance2, SugaredMorphism, SugaredMorphismType}, parser::*, substitution_sugared::SugaredSubstitution, unparser::*, Substitution, SugaredEnumVariant, SugaredStructMember, SugaredTypeTerm, TypeDict, TypeTerm}, std::collections::HashMap
};
impl LdmcPrimMorph {
pub fn instantiated_symbol_name(&self, dict: &mut impl TypeDict, σ: &impl SugaredSubstitution) -> String {
let mut s = self.symbol.clone();
for (k_id,v) in self.type_args.iter() {
if let Some(val_trm) = σ.get(k_id) {
if let laddertypes::TypeID::Var(var_id) = k_id {
let name = dict.get_varname(*var_id).unwrap();
let val_str = encode_type_to_symbol(dict, &val_trm);
s.push_str(&format!("_{}_{}", name, val_str));
}
} else {
if let laddertypes::TypeID::Var(var_id) = k_id {
let k = dict.get_varname(*var_id).unwrap();
s.push_str(&format!("_{:?}_MISSING", k));
eprintln!("INCOMPLETE MORPHISM INSTANTIATION, missing type parameter {} ({})", k, var_id);
}
}
}
s
}
pub fn expected_c_type_signature(&self, dict: &mut impl TypeDict,
σ: &std::collections::HashMap<laddertypes::TypeID, laddertypes::SugaredTypeTerm>
) -> String {
format!("int {} ({} const * restrict src, {} * restrict dst);",
self.instantiated_symbol_name(dict, σ),
get_c_repr_type(dict, self.ty.src_type.clone(), true).expect("cant get c-repr type for src type"),
get_c_repr_type(dict, self.ty.dst_type.clone(), true).expect("cant get c-repr type for dst type"))
}
pub fn generate_instantiation(&self, dict: &mut impl TypeDict, σ: &impl SugaredSubstitution) -> Option<String> {
let mut s = String::new();
let symbol = self.instantiated_symbol_name(dict, σ);
let src_c_symbol = encode_type_to_symbol(dict, &self.ty.strip_halo().src_type);
let dst_c_symbol = encode_type_to_symbol(dict, &self.ty.strip_halo().dst_type);
s.push_str(&format!(r#"
int {} ( {} const * restrict src, {} * restrict dst ) {{
"#,
symbol, src_c_symbol, dst_c_symbol,
));
s.push_str(&self.c_source);
s.push_str(&format!(r#"
return 0;
}}
"#));
Some(s)
}
}
pub struct LdmcCTargetMorph {
includes: Vec< String >,
active_types: Vec< SugaredTypeTerm >,
active_instantiations: Vec< LdmcPrimMorph >,
}
impl LdmcCTargetMorph {
pub fn new() -> Self {
LdmcCTargetMorph {
includes: vec![
"#include <stdint.h>".into(),
],
active_instantiations: Vec::new(),
active_types: Vec::new(),
}
}
pub fn add_instantiation(
&mut self,
dict: &mut impl TypeDict,
morph: MorphismInstance2<LdmcPrimMorph>,
) -> Result<LdmcPrimMorph, ()> {
let new_inst = self.bake_morphism(dict, morph)?;
if ! self.active_instantiations.contains(&new_inst) {
self.active_instantiations.push(new_inst.clone());
}
let ty = new_inst.get_type().strip_halo();
if ! self.active_types.contains(&ty.src_type) {
self.active_types.push(ty.src_type);
}
if ! self.active_types.contains(&ty.dst_type) {
self.active_types.push(ty.dst_type);
}
Ok(new_inst)
}
pub fn into_c_source(self, dict: &mut impl TypeDict) -> String {
let mut source = String::new();
for inc in self.includes {
source.push_str(&inc);
}
for ty in self.active_types {
source.push_str(&format!("
typedef {} {};
",
get_c_repr_type(dict, ty.clone(), false).expect("cant get c-repr type"),
encode_type_to_symbol(dict, &ty)));
}
for m in self.active_instantiations {
source.push_str(&m.generate_instantiation(dict, &HashMap::new()).expect("cant create function"));
}
source
}
pub fn bake_morphism(
&mut self,
dict: &mut impl laddertypes::TypeDict,
morph_inst: MorphismInstance2<LdmcPrimMorph>,
) -> Result<LdmcPrimMorph, ()> {
match &morph_inst {
MorphismInstance2::Primitive { ψ, σ, morph } => {
let mut c_source = String::new();
for (ty_id, kind) in morph.type_args.iter() {
if let Some(val) = σ.get(ty_id) {
let type_var_value =
if let Some(c_repr_type) = get_c_repr_type(dict, val.clone(), true) {
c_repr_type
} else {
encode_type_to_value(dict, &val)
};
c_source.push_str(&format!(" #define {} {}\n", dict.get_typename(&ty_id).unwrap(), type_var_value));
}
}
c_source.push_str(&morph.c_source);
for (ty_id, kind) in morph.type_args.iter() {
c_source.push_str(&format!("\n #undef {}", dict.get_typename(&ty_id).unwrap()));
}
Ok(LdmcPrimMorph{
symbol: morph.instantiated_symbol_name(dict, σ),
type_args: Vec::new(),
ty: morph_inst.get_haloless_type(),
c_source
})
},
MorphismInstance2::Chain { path } => {
let ty = morph_inst.get_type().strip_halo();
let symbol = encode_morph_type_to_symbol(dict, &morph_inst.get_haloless_type());
let mut c_source = String::new();
if path.len() > 1 {
c_source.push_str(r#"
uint8_t bufA[128];
uint8_t bufB[128];
"#);
}
for (i,morph) in path.iter().enumerate() {
if let Ok(inst) = self.add_instantiation(dict, morph.clone()) {
let morph_symbol = inst.instantiated_symbol_name(dict, &morph.get_subst());
let src_c_type = encode_type_to_symbol(dict, &inst.get_type().strip_halo().src_type);
let dst_c_type = encode_type_to_symbol(dict, &inst.get_type().strip_halo().dst_type);
let src_buf = if i == 0 { "src" } else if i%2 == 0 { "(void*)bufA" } else { "(void*)bufB" };
let dst_buf = if i+1 == path.len() { "dst" } else if i%2 == 0 { "(void*)bufB" } else { "(void*)bufA" };
c_source.push_str(&format!(r#"
{{
{} const * restrict src = {};
{} * restrict dst = {};
{} ( 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()).expect("add instantiation");
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 = 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 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
);
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().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->{} );
",
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!();
}
}
}
}