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