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