stak_code/ir/
instruction.rs1use crate::Operand;
2#[cfg(feature = "alloc")]
3use alloc::vec::Vec;
4
5#[derive(Debug, Eq, PartialEq)]
7pub enum Instruction {
8 Constant(Operand),
10 Get(Operand),
12 Set(Operand),
14 #[cfg(feature = "alloc")]
16 If(Vec<Instruction>),
17 Nop(u64),
19 Call(u64, Operand),
21 #[cfg(feature = "alloc")]
25 Close(u64, Vec<Instruction>),
26 Skip(u64),
30}
31
32impl Instruction {
33 pub const CONSTANT: u8 = 0;
35 pub const GET: u8 = 1;
37 pub const SET: u8 = 2;
39 pub const IF: u8 = 3;
41 pub const NOP: u8 = 4;
43 pub const CALL: u8 = 5;
45 pub const CLOSE: u8 = 6;
47 pub const SKIP: u8 = 7;
49}
50
51#[cfg(feature = "alloc")]
52mod display {
53 use super::*;
54 use core::fmt::{self, Display, Formatter};
55
56 impl Instruction {
57 pub fn display_slice(instructions: &[Self]) -> impl Display + '_ {
59 DisplayInstructionList::new(instructions, 0)
60 }
61 }
62
63 struct DisplayInstruction<'a> {
64 instruction: &'a Instruction,
65 indent: usize,
66 }
67
68 impl<'a> DisplayInstruction<'a> {
69 const fn new(instruction: &'a Instruction, indent: usize) -> Self {
70 Self {
71 instruction,
72 indent,
73 }
74 }
75 }
76
77 impl<'a> Display for DisplayInstruction<'a> {
78 fn fmt(&self, formatter: &mut Formatter) -> fmt::Result {
79 let indent = self.indent + 1;
80
81 write!(formatter, "- ")?;
82
83 match self.instruction {
84 Instruction::Constant(operand) => write!(formatter, "constant {operand}"),
85 Instruction::Get(operand) => write!(formatter, "get {operand}"),
86 Instruction::Set(operand) => write!(formatter, "set {operand}"),
87 Instruction::If(instructions) => {
88 write!(formatter, "if")?;
89 write!(
90 formatter,
91 "{}",
92 DisplayInstructionList::new(instructions, indent)
93 )
94 }
95 Instruction::Nop(operand) => write!(formatter, "nop {operand}"),
96 Instruction::Call(arity, operand) => {
97 write!(formatter, "call {arity} {operand}")
98 }
99 Instruction::Close(arity, instructions) => {
100 write!(formatter, "close {arity}")?;
101 write!(
102 formatter,
103 "{}",
104 DisplayInstructionList::new(instructions, indent)
105 )
106 }
107 Instruction::Skip(count) => write!(formatter, "skip {count}"),
108 }
109 }
110 }
111
112 struct DisplayInstructionList<'a> {
113 instructions: &'a [Instruction],
114 indent: usize,
115 }
116
117 impl<'a> DisplayInstructionList<'a> {
118 const fn new(instructions: &'a [Instruction], indent: usize) -> Self {
119 Self {
120 instructions,
121 indent,
122 }
123 }
124 }
125
126 impl<'a> Display for DisplayInstructionList<'a> {
127 fn fmt(&self, formatter: &mut Formatter) -> fmt::Result {
128 for instruction in self.instructions {
129 writeln!(formatter)?;
130
131 for _ in 0..self.indent {
132 write!(formatter, " ")?
133 }
134
135 write!(
136 formatter,
137 "{}",
138 DisplayInstruction::new(instruction, self.indent)
139 )?;
140 }
141
142 Ok(())
143 }
144 }
145}