cpclib_asm/assembler/
control.rs

1use cpclib_tokens::{Expr, ExprElement, FormattedExpr};
2
3use super::{Env, visit_assert};
4use crate::error::AssemblerError;
5use crate::preamble::Z80Span;
6
7/// This structure store the necessary information to replay the assembled stuff of previous passes when we do not reassemble
8#[derive(Debug, Clone, PartialEq, Eq)]
9struct ControlOutputByte {
10    // The value to output
11    value: u8
12}
13
14#[derive(Debug, Clone, PartialEq, Eq)]
15struct ControlOutputBytes {
16    // The value to output
17    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    // pub fn extend<I: Iterator<Item = ControlOutputCommand> >(&mut self, iter: I) {
166    // self.commands.extend(iter)
167    // }
168}