1use core::fmt;
2
3use super::{Block, Instruction};
4use crate::{SourceSpan, Span, Spanned};
5
6#[derive(Clone)]
11#[repr(u8)]
12pub enum Op {
13 If {
17 span: SourceSpan,
18 then_blk: Block,
20 else_blk: Block,
22 } = 0,
23 While { span: SourceSpan, body: Block } = 1,
25 Repeat {
30 span: SourceSpan,
31 count: u32,
32 body: Block,
33 } = 2,
34 Inst(Span<Instruction>) = 3,
36}
37
38impl crate::prettier::PrettyPrint for Op {
39 fn render(&self) -> crate::prettier::Document {
40 use crate::prettier::*;
41
42 match self {
43 Self::If { then_blk, else_blk, .. } => {
44 text("if.true")
45 + nl()
46 + then_blk.render()
47 + nl()
48 + text("else")
49 + nl()
50 + else_blk.render()
51 + nl()
52 + text("end")
53 },
54 Self::While { body, .. } => {
55 text("while.true") + nl() + body.render() + nl() + text("end")
56 },
57 Self::Repeat { count, body, .. } => {
58 display(format!("repeat.{count}")) + nl() + body.render() + nl() + text("end")
59 },
60 Self::Inst(inst) => inst.render(),
61 }
62 }
63}
64
65impl fmt::Debug for Op {
66 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
67 match self {
68 Self::If { then_blk, else_blk, .. } => {
69 f.debug_struct("If").field("then", then_blk).field("else", else_blk).finish()
70 },
71 Self::While { body, .. } => f.debug_tuple("While").field(body).finish(),
72 Self::Repeat { count, body, .. } => {
73 f.debug_struct("Repeat").field("count", count).field("body", body).finish()
74 },
75 Self::Inst(inst) => fmt::Debug::fmt(&**inst, f),
76 }
77 }
78}
79
80impl Eq for Op {}
81
82impl PartialEq for Op {
83 fn eq(&self, other: &Self) -> bool {
84 match (self, other) {
85 (
86 Self::If { then_blk: lt, else_blk: le, .. },
87 Self::If { then_blk: rt, else_blk: re, .. },
88 ) => lt == rt && le == re,
89 (Self::While { body: lbody, .. }, Self::While { body: rbody, .. }) => lbody == rbody,
90 (
91 Self::Repeat { count: lcount, body: lbody, .. },
92 Self::Repeat { count: rcount, body: rbody, .. },
93 ) => lcount == rcount && lbody == rbody,
94 (Self::Inst(l), Self::Inst(r)) => l == r,
95 _ => false,
96 }
97 }
98}
99
100impl Spanned for Op {
101 fn span(&self) -> SourceSpan {
102 match self {
103 Self::If { span, .. } | Self::While { span, .. } | Self::Repeat { span, .. } => *span,
104 Self::Inst(spanned) => spanned.span(),
105 }
106 }
107}