etk_asm/ops/
imm.rs

1use etk_ops::Immediate;
2
3use num_bigint::{BigInt, Sign};
4
5use snafu::{Backtrace, Snafu};
6
7use std::convert::TryFrom;
8use std::fmt::{self, Debug};
9
10use super::expression::{Expression, Terminal};
11use super::macros::ExpressionMacroInvocation;
12
13/// An error that arises when converting a slice into an immediate.
14#[derive(Snafu, Debug)]
15#[snafu(context(suffix(Context)))]
16pub struct TryFromSliceError {
17    backtrace: Backtrace,
18}
19
20impl From<std::convert::Infallible> for TryFromSliceError {
21    fn from(e: std::convert::Infallible) -> Self {
22        match e {}
23    }
24}
25
26/// An immediate value for push instructions.
27#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
28pub struct Imm {
29    /// An infix tree representing a mathematical expression.
30    pub tree: Expression,
31}
32
33impl Imm {
34    /// Construct an `Imm` with a label.
35    pub fn with_label<S: Into<String>>(s: S) -> Self {
36        Terminal::Label(s.into()).into()
37    }
38
39    /// Construct an `Imm` with a variable.
40    pub fn with_variable<S: Into<String>>(s: S) -> Self {
41        Terminal::Variable(s.into()).into()
42    }
43
44    /// Construct an `Imm` with an expression.
45    pub fn with_expression(e: Expression) -> Self {
46        e.into()
47    }
48
49    /// Construct an `Imm` with an expression macro.
50    pub fn with_macro(m: ExpressionMacroInvocation) -> Self {
51        Expression::Macro(m).into()
52    }
53}
54
55impl From<Vec<u8>> for Imm {
56    fn from(konst: Vec<u8>) -> Self {
57        Imm::from(Terminal::Number(BigInt::from_bytes_be(Sign::Plus, &konst)))
58    }
59}
60
61impl fmt::Display for Imm {
62    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
63        write!(f, "{}", self.tree)
64    }
65}
66
67macro_rules! impl_from {
68    ($ii:literal;) => {
69        impl From<[u8; $ii]> for Imm {
70            fn from(konst: [u8; $ii]) -> Self {
71                Imm::from(Terminal::Number(BigInt::from_bytes_be(
72                    Sign::Plus,
73                    &konst,
74                )))
75            }
76        }
77    };
78
79    ($ii:literal; $ty:ty $(, $rest:ty)* $(,)*) => {
80        impl From<$ty> for Imm {
81            fn from(x: $ty) -> Self {
82                Imm::from(Terminal::Number(x.into()))
83            }
84        }
85
86        impl_from!($ii; $($rest,)*);
87    }
88}
89
90macro_rules! impl_try_from_slice {
91    ($ii:literal) => {
92        impl TryFrom<&[u8]> for Imm {
93            type Error = TryFromSliceError;
94
95            fn try_from(x: &[u8]) -> Result<Self, Self::Error> {
96                if x.len() > $ii {
97                    return TryFromSliceContext.fail();
98                }
99
100                Ok(Imm::from(Terminal::Number(BigInt::from_bytes_be(
101                    Sign::Plus,
102                    x,
103                ))))
104            }
105        }
106    };
107}
108
109impl_from!(1;);
110impl_from!(2;);
111impl_from!(3;);
112impl_from!(4;);
113impl_from!(5;);
114impl_from!(6;);
115impl_from!(7;);
116impl_from!(8;);
117impl_from!(9;);
118impl_from!(10;);
119impl_from!(11;);
120impl_from!(12;);
121impl_from!(13;);
122impl_from!(14;);
123impl_from!(15;);
124impl_from!(16;);
125impl_from!(17;);
126impl_from!(18;);
127impl_from!(19;);
128impl_from!(20;);
129impl_from!(21;);
130impl_from!(22;);
131impl_from!(23;);
132impl_from!(24;);
133impl_from!(25;);
134impl_from!(26;);
135impl_from!(27;);
136impl_from!(28;);
137impl_from!(29;);
138impl_from!(30;);
139impl_from!(31;);
140impl_from!(32; u8, u16, u32, u64, u128);
141
142impl_try_from_slice!(32);
143
144impl From<Expression> for Imm {
145    fn from(tree: Expression) -> Self {
146        Self { tree }
147    }
148}
149
150impl From<Terminal> for Imm {
151    fn from(terminal: Terminal) -> Self {
152        Expression::Terminal(terminal).into()
153    }
154}
155
156impl<const N: usize> Immediate<N> for Imm {}