feo3boy_opcodes/compiler/
args.rs1use std::any::{Any, TypeId};
4use std::fmt;
5
6use proc_macro2::TokenStream;
7use quote::{quote, ToTokens};
8
9pub type CrateFetcher = fn(&str) -> TokenStream;
11
12pub trait Literal: fmt::Debug + Any {
14 fn constant_value(&self, crates: CrateFetcher) -> TokenStream;
17}
18
19impl Literal for u8 {
20 fn constant_value(&self, _crates: CrateFetcher) -> TokenStream {
21 proc_macro2::Literal::u8_suffixed(*self).into_token_stream()
22 }
23}
24
25impl Literal for u16 {
26 fn constant_value(&self, _crates: CrateFetcher) -> TokenStream {
27 proc_macro2::Literal::u16_suffixed(*self).into_token_stream()
28 }
29}
30
31impl Literal for usize {
32 fn constant_value(&self, _crates: CrateFetcher) -> TokenStream {
33 proc_macro2::Literal::usize_suffixed(*self).into_token_stream()
34 }
35}
36
37impl Literal for bool {
38 fn constant_value(&self, _crates: CrateFetcher) -> TokenStream {
39 if *self {
40 quote! { true }
41 } else {
42 quote! { false }
43 }
44 }
45}
46
47pub struct DynLiteral {
49 literal: Box<dyn Literal>,
50 clone: fn(&dyn Literal) -> Box<dyn Literal>,
51}
52
53impl DynLiteral {
54 pub fn new<L: Literal + Clone>(val: L) -> Self {
55 Self {
56 literal: Box::new(val),
57 clone: Self::dyn_clone::<L>,
58 }
59 }
60
61 fn dyn_clone<L: Literal + Clone>(val: &dyn Literal) -> Box<dyn Literal> {
64 assert!(TypeId::of::<L>() == val.type_id(), "Wrong type");
65 let val = val as *const dyn Literal as *const L;
68 let val = unsafe { &*val };
72 Box::new(val.clone())
73 }
74}
75
76impl Clone for DynLiteral {
77 fn clone(&self) -> Self {
78 let cloned = (self.clone)(self.literal.as_ref());
79 Self {
80 literal: cloned,
81 clone: self.clone,
82 }
83 }
84}
85
86impl fmt::Debug for DynLiteral {
87 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
88 self.literal.fmt(f)
89 }
90}
91
92impl Literal for DynLiteral {
93 fn constant_value(&self, crates: CrateFetcher) -> TokenStream {
94 self.literal.constant_value(crates)
95 }
96}
97
98#[derive(Debug, Clone)]
100pub enum Arg<StackT> {
101 StackValue(StackT),
103 Literal(DynLiteral),
105}