cpclib_asm/assembler/
control.rs1use cpclib_tokens::{Expr, ExprElement, FormattedExpr};
2
3use super::{Env, visit_assert};
4use crate::error::AssemblerError;
5use crate::preamble::Z80Span;
6
7#[derive(Debug, Clone, PartialEq, Eq)]
9struct ControlOutputByte {
10 value: u8
12}
13
14#[derive(Debug, Clone, PartialEq, Eq)]
15struct ControlOutputBytes {
16 bytes: Vec<u8>
18}
19
20#[derive(Debug, Clone, PartialEq, Eq)]
21struct ControlOrg {
22 code: u16,
23 output: u16
24}
25
26#[derive(Debug, Clone, PartialEq, Eq)]
27struct ControlAssert {
28 exp: Expr,
29 txt: Option<Vec<FormattedExpr>>,
30 span: Option<Z80Span>
31}
32
33#[derive(Debug, Clone, PartialEq, Eq)]
34enum ControlOutputCommand {
35 Assert(ControlAssert),
36 Byte(ControlOutputByte),
37 Bytes(ControlOutputBytes),
38 Org(ControlOrg)
39}
40
41impl From<ControlAssert> for ControlOutputCommand {
42 fn from(c: ControlAssert) -> Self {
43 Self::Assert(c)
44 }
45}
46
47impl From<ControlOutputByte> for ControlOutputCommand {
48 fn from(b: ControlOutputByte) -> Self {
49 Self::Byte(b)
50 }
51}
52
53impl From<ControlOutputBytes> for ControlOutputCommand {
54 fn from(b: ControlOutputBytes) -> Self {
55 Self::Bytes(b)
56 }
57}
58
59impl From<ControlOrg> for ControlOutputCommand {
60 fn from(value: ControlOrg) -> Self {
61 Self::Org(value)
62 }
63}
64
65#[derive(Debug, Clone, PartialEq, Eq)]
66pub struct ControlOutputStore {
67 pub(crate) remaining_passes: u8,
68 pub(crate) commands: Vec<ControlOutputCommand>
69}
70
71impl ControlAssert {
72 fn execute(&mut self, env: &mut Env) -> Result<(), AssemblerError> {
73 visit_assert(&self.exp, self.txt.as_ref(), env, self.span.as_ref())?;
74 Ok(())
75 }
76}
77
78impl ControlOutputByte {
79 fn execute(&mut self, env: &mut Env) -> Result<(), AssemblerError> {
80 env.output_byte(self.value)?;
81 Ok(())
82 }
83}
84
85impl ControlOutputBytes {
86 fn execute(&mut self, env: &mut Env) -> Result<(), AssemblerError> {
87 env.output_bytes(&self.bytes)?;
88 Ok(())
89 }
90}
91
92impl ControlOrg {
93 fn execute(&mut self, env: &mut Env) -> Result<(), AssemblerError> {
94 env.visit_org_set_arguments(self.code, self.output)
95 }
96}
97
98impl ControlOutputCommand {
99 fn execute(&mut self, env: &mut Env) -> Result<(), AssemblerError> {
100 match self {
101 ControlOutputCommand::Assert(cmd) => cmd.execute(env),
102 ControlOutputCommand::Byte(cmd) => cmd.execute(env),
103 ControlOutputCommand::Bytes(cmd) => cmd.execute(env),
104 ControlOutputCommand::Org(cmd) => cmd.execute(env),
105 _ => unimplemented!()
106 }
107 }
108}
109
110impl ControlOutputStore {
111 pub fn with_passes(passes: u8) -> Self {
112 ControlOutputStore {
113 remaining_passes: passes,
114 commands: Default::default()
115 }
116 }
117
118 pub fn store_byte(&mut self, value: u8) {
119 match self.commands.last_mut() {
120 Some(ControlOutputCommand::Byte(ControlOutputByte { value: previous })) => {
121 let new_command = ControlOutputBytes {
122 bytes: vec![*previous, value]
123 };
124 self.commands.pop();
125 self.commands.push(new_command.into());
126 },
127 Some(ControlOutputCommand::Bytes(ControlOutputBytes { bytes })) => {
128 bytes.push(value);
129 },
130 _ => {
131 self.commands.push(ControlOutputByte { value }.into());
132 }
133 }
134 }
135
136 pub fn store_org(&mut self, code: u16, output: u16) {
137 self.commands.push(ControlOrg { code, output }.into())
138 }
139
140 pub fn store_assert(
141 &mut self,
142 exp: Expr,
143 txt: Option<Vec<FormattedExpr>>,
144 span: Option<Z80Span>
145 ) {
146 self.commands.push(ControlAssert { exp, txt, span }.into())
147 }
148
149 pub fn has_remaining_passes(&self) -> bool {
150 self.remaining_passes > 0
151 }
152
153 pub fn execute(&mut self, env: &mut Env) -> Result<(), AssemblerError> {
154 for cmd in &mut self.commands {
155 cmd.execute(env)?;
156 }
157 Ok(())
158 }
159
160 pub fn new_pass(&mut self) {
161 self.remaining_passes -= 1;
162 self.commands.clear();
163 }
164
165 }