1mod assembler;
2mod text_section;
3use proc_macro::TokenStream;
4use syn::parse_macro_input;
5
6#[proc_macro]
7pub fn assembler(input: TokenStream) -> TokenStream {
8    let input = parse_macro_input!(input with syn::punctuated::Punctuated::<syn::Expr, syn::Token![,]>::parse_terminated)
10        .into_iter()
11        .collect::<Vec<_>>();
12
13    if input.len() != 2 {
14        panic!("Expected two arguments: architecture name and definition file path");
15    }
16
17    let architecture = if let syn::Expr::Path(path) = &input[0] {
19        if let Some(ident) = path.path.get_ident() {
20            ident.to_string()
21        } else {
22            panic!("Expected architecture identifier");
23        }
24    } else {
25        panic!("Expected architecture identifier");
26    };
27
28    let filename = if let syn::Expr::Lit(syn::ExprLit {
30        lit: syn::Lit::Str(s),
31        ..
32    }) = &input[1]
33    {
34        s.value()
35    } else {
36        panic!("Expected string literal for filename");
37    };
38
39    let raw_definition = monistode_binutils::definition::RawDefinition::from_str(
40        match std::fs::read_to_string(&filename) {
41            Ok(x) => x,
42            Err(e) => panic!("Error reading {}: {}", filename, e),
43        }
44        .as_str(),
45    )
46    .unwrap();
47    let definition = monistode_binutils::definition::Definition::try_from(raw_definition).unwrap();
48    assembler::generate_parser(&definition, &architecture).into()
49}