Skip to main content

aprender_contracts_cli/commands/
tla.rs

1use std::path::Path;
2
3use provable_contracts::graph::dependency_graph;
4use provable_contracts::schema::{parse_contract, Contract};
5use provable_contracts::tla_gen::generate_tla_module;
6
7pub fn run(contract_dir: &Path) -> Result<(), Box<dyn std::error::Error>> {
8    let mut contracts: Vec<(String, Contract)> = Vec::new();
9
10    let entries = std::fs::read_dir(contract_dir)?;
11    for entry in entries {
12        let entry = entry?;
13        let path = entry.path();
14        if path.extension().and_then(|e| e.to_str()) == Some("yaml") {
15            let stem = path
16                .file_stem()
17                .and_then(|s| s.to_str())
18                .unwrap_or("unknown")
19                .to_string();
20            match parse_contract(&path) {
21                Ok(c) => contracts.push((stem, c)),
22                Err(e) => {
23                    eprintln!("warning: skipping {}: {e}", path.display());
24                }
25            }
26        }
27    }
28
29    contracts.sort_by(|a, b| a.0.cmp(&b.0));
30
31    let refs: Vec<(String, &Contract)> = contracts.iter().map(|(s, c)| (s.clone(), c)).collect();
32    let graph = dependency_graph(&refs);
33
34    let module_name = contract_dir
35        .file_name()
36        .and_then(|s| s.to_str())
37        .unwrap_or("Contracts");
38    let module_name = module_name
39        .chars()
40        .filter(|c| c.is_alphanumeric())
41        .collect::<String>();
42    let module_name = if module_name.is_empty() {
43        "Contracts".to_string()
44    } else {
45        // Capitalize first letter
46        let mut chars = module_name.chars();
47        match chars.next() {
48            None => "Contracts".to_string(),
49            Some(first) => first.to_uppercase().collect::<String>() + chars.as_str(),
50        }
51    };
52
53    let output = generate_tla_module(&module_name, &refs, &graph);
54    print!("{output}");
55
56    Ok(())
57}