improve integration

* add command line parsing
* read morphism base directory from environment
* generate C library of multiple morphisms
This commit is contained in:
Michael Sippel 2025-05-09 03:33:18 +02:00
parent 923fe987dc
commit 27ea365755
Signed by: senvas
GPG key ID: F96CF119C34B64A6
6 changed files with 161 additions and 72 deletions

View file

@ -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"

74
src/c_gen/gen_lib.rs Normal file
View file

@ -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)
}

View file

@ -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(())
}
}
}

View file

@ -1,6 +1,6 @@
pub mod types;
pub mod morph;
pub mod gen_main;
pub mod gen_lib;
pub use {
morph::target_morph::LdmcCTargetMorph

View file

@ -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")
);
}

View file

@ -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")
)
}
})
}