Skip to main content

chipi_core/
lib.rs

1//! # chipi-core
2//!
3//! Core library for the chipi instruction decoder generator.
4//!
5//! ## Crate structure
6//!
7//! - [`parser`]: parses `.chipi` instruction-spec files into a raw AST.
8//!   See [`types::DecoderDef`].
9//! - [`validate`]: validates and lowers the AST into a language-agnostic IR.
10//!   See [`types::ValidatedDef`].
11//! - [`tree`]: builds an optimal decision tree for instruction dispatch.
12//! - [`backend`]: language-specific code generation backends.
13//! - [`config`]: internal generation and dispatch config types.
14//! - [`codegen`]: Rust decoder/disassembler code generation.
15//! - [`lut_gen`]: Rust emulator dispatch LUT generation.
16//! - [`instr_gen`]: Rust instruction newtype generation.
17//! - [`bindings`]: parser and lowerer for `*.bindings.chipi` configs.
18
19pub mod backend;
20pub mod bindings;
21pub mod codegen;
22pub mod codegen_binja;
23pub mod codegen_cpp;
24pub mod codegen_ida;
25pub mod codegen_python;
26pub mod config;
27pub mod error;
28pub mod format_parser;
29pub mod instr_gen;
30pub mod lut_gen;
31pub mod parser;
32pub mod tree;
33pub mod types;
34pub mod validate;
35
36use std::collections::HashMap;
37
38use error::Errors;
39use types::DecoderDef;
40
41pub use config::Dispatch;
42
43/// Parse a `.chipi` file from a file path and return the decoder definition.
44pub fn parse(input: &str) -> Result<DecoderDef, Box<dyn std::error::Error>> {
45    let path = std::path::Path::new(input);
46    parser::parse_file(path).map_err(|errs| Box::new(Errors(errs)) as Box<dyn std::error::Error>)
47}
48
49/// Parse source text directly without reading from a file.
50pub fn parse_str(source: &str, filename: &str) -> Result<DecoderDef, Vec<error::Error>> {
51    parser::parse(source, filename)
52}
53
54/// Parse source text and generate Rust decoder code.
55/// Returns the generated Rust code as a `String`.
56pub fn generate_from_str(
57    source: &str,
58    filename: &str,
59) -> Result<String, Box<dyn std::error::Error>> {
60    let def = parser::parse(source, filename)
61        .map_err(|errs| Box::new(Errors(errs)) as Box<dyn std::error::Error>)?;
62
63    let validated = validate::validate(&def)
64        .map_err(|errs| Box::new(Errors(errs)) as Box<dyn std::error::Error>)?;
65
66    let tree = tree::build_tree(&validated);
67    let code = codegen::generate_code(&validated, &tree, &HashMap::new(), &HashMap::new());
68
69    Ok(code)
70}