1use cpclib_asm::preamble::*;
2use proc_macro::TokenStream;
3use quote::ToTokens;
4use syn::parse::{Parse, ParseStream};
5use syn::{Result, parse_macro_input};
6mod tokens;
7
8struct AssemblyMacroInput {
11 code: String
13}
14
15mod kw {
16 syn::custom_keyword!(fname);
17}
18
19impl Parse for AssemblyMacroInput {
23 fn parse(input: ParseStream) -> Result<Self> {
24 let lookahead = input.lookahead1();
25 if lookahead.peek(kw::fname) {
26 input.parse::<kw::fname>()?;
27 input.parse::<syn::Token![:]>()?;
28 let fname = (input.parse::<syn::LitStr>()?).value();
29 let content = std::fs::read_to_string(&fname).map_err(|e| {
30 syn::Error::new(
31 proc_macro2::Span::call_site(),
32 format!("Unable to load {fname}.\n{e}")
33 )
34 })?;
35
36 Ok(AssemblyMacroInput { code: content })
37 }
38 else if lookahead.peek(syn::LitStr) {
39 Ok(AssemblyMacroInput {
40 code: (input.parse::<syn::LitStr>()?).value()
41 })
42 }
43 else {
44 Err(lookahead.error())
45 }
46 }
47}
48
49#[proc_macro]
50pub fn parse_z80(tokens: TokenStream) -> TokenStream {
56 let input = parse_macro_input!(tokens as AssemblyMacroInput);
57 let listing = get_listing(input);
58
59 match listing {
60 Ok(listing) => {
61 use tokens::*;
62 let mut stream = proc_macro2::TokenStream::new();
63 listing.to_tokens(&mut stream);
64 stream.into()
65 },
66 Err(e) => {
67 panic!("[ERROR] {e:?}");
68 }
69 }
70}
71
72fn get_listing(
73 input: AssemblyMacroInput
74) -> std::result::Result<Listing, cpclib_asm::error::AssemblerError> {
75 Listing::from_str(&input.code)
76}
77
78#[proc_macro]
80pub fn assemble(tokens: TokenStream) -> TokenStream {
81 let input = parse_macro_input!(tokens as AssemblyMacroInput);
82 let listing = get_listing(input);
83
84 match listing {
85 Ok(listing) => {
86 match listing.to_bytes() {
87 Ok(ref bytes) => {
88 let mut tokens = proc_macro2::TokenStream::default();
89 proc_macro2::Literal::byte_string(bytes).to_tokens(&mut tokens);
90 tokens.into()
91 },
92
93 Err(e) => {
94 panic!("Unable to assemble the provided code. {e:?}");
95 }
96 }
97 },
98 Err(e) => {
99 panic!("[ERROR] {e:?}");
100 }
101 }
102}