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
mod mice;
mod reloading;
use ::proc_macro::TokenStream;

#[proc_macro]
pub fn decl_ops(input: TokenStream) -> TokenStream {
    mice::decl_ops(input)
}

#[proc_macro_attribute]
pub fn reloadable(attr: TokenStream, item: TokenStream) -> TokenStream {
    reloading::reloadable(attr.into(), item.into()).into()
}

#[proc_macro_derive(Bytecode, attributes())]
pub fn bytecode(item: TokenStream) -> TokenStream {
    mice::stack_bytecode::bytecode(::syn::parse_macro_input!(item as ::syn::DeriveInput)).into()
}

/// Derive a bytecode encoding for an instruction enum.
/// Currently supports a single byte instruction prefix, plus
/// arbitrary width immediate arguments.
///
/// The `#[view(...)]` helper attribute declares the name of the
/// bytecode instruction view type, which can be used like a
/// `&mut YourInstructionType` into an existing bytecode buffer.
///
/// The `#[ty(...)]` helper attribute declares the types of
/// arguments taken from the stack, and its return type.
/// It can be omitted where an instruction does not use the stack.
/// Can be written `#[ty(read: a)]` to signify that the instruction
/// only *reads* the stack without altering it, and the type
/// of value it expects to read.
///
/// The `#[unfold(...)]` helper attribute indicates that an immediate
/// argument to an instruction should be placed inside of the
/// instruction prefix itself- called "unfolding" as this is
/// like unfolding an enum's variants into its containing enum.
/// This only works for enums and integer ranges.
/// For integer ranges, this consumes 1 more tag value than
/// there are inside the unfolded range- to flag whether
/// the argument is inside the prefix or not.
#[proc_macro_derive(BytecodeInstruction, attributes(ty, unfold))]
pub fn bytecode_instruction(item: TokenStream) -> TokenStream {
    let item = ::syn::parse_macro_input!(item as ::syn::DeriveInput);
    mice::stack_bytecode::bytecode_instruction(item).into()
}