Skip to main content

az65/assembler/
mod.rs

1use std::{
2    borrow::Borrow,
3    cell::RefCell,
4    fmt::Write,
5    io::{Cursor, Read},
6    iter,
7    marker::PhantomData,
8    path::Path,
9    rc::Rc,
10};
11
12use fxhash::FxHashMap;
13
14use crate::{
15    expr::{Expr, ExprNode},
16    fileman::{FileManager, FileSystem},
17    intern::{PathRef, StrInterner, StrRef},
18    lexer::{
19        ArchTokens, DirectiveName, LabelKind, Lexer, LexerError, SourceLoc, SymbolName, Token,
20    },
21    linker::{Link, Module},
22    symtab::{Symbol, Symtab},
23};
24
25#[cfg(test)]
26mod tests;
27
28macro_rules! asm_err {
29    ($loc:expr, $($arg:tt)*) => {
30        Err(($loc, AssemblerError(format!($($arg)*))))
31    };
32}
33
34enum TokenSource<R, A: ArchTokens> {
35    /// Normal lexer
36    Lexer(Lexer<R, A>),
37    /// Lexer generated by the `@parse` directive
38    ParseLexer(Lexer<Cursor<String>, A>),
39    /// A macro
40    Macro(MacroState<A>),
41}
42
43impl<R: Read, A: ArchTokens> TokenSource<R, A> {
44    pub fn loc(&self) -> SourceLoc {
45        match self {
46            Self::Lexer(lexer) => lexer.loc(),
47            Self::ParseLexer(lexer) => lexer.loc(),
48            Self::Macro(state) => state.loc,
49        }
50    }
51
52    pub fn included_from(&self) -> Option<SourceLoc> {
53        match self {
54            Self::Lexer(lexer) => lexer.included_from(),
55            Self::ParseLexer(lexer) => lexer.included_from(),
56            Self::Macro(state) => state.included_from,
57        }
58    }
59
60    fn next(
61        &mut self,
62        macros: &mut FxHashMap<StrRef, Macro<A>>,
63    ) -> Option<Result<Token<A>, (SourceLoc, AssemblerError)>> {
64        match self {
65            Self::Lexer(lexer) => lexer.next().map(|res| res.map_err(LexerError::into)),
66            Self::ParseLexer(lexer) => lexer.next().map(|res| res.map_err(LexerError::into)),
67            Self::Macro(state) => {
68                let mac = macros.get_mut(&state.name).unwrap();
69
70                loop {
71                    if state.macro_offset >= mac.tokens.len() {
72                        return None;
73                    }
74
75                    if let Some(arg) = state.expanding_macro_arg {
76                        let arg_toks = &state.args[arg];
77                        if state.macro_arg_offset >= arg_toks.len() {
78                            state.expanding_macro_arg = None;
79                            state.macro_offset += 1;
80                            continue;
81                        }
82
83                        // arguments will already be expanded if they contained macro invocations
84                        let tok = arg_toks[state.macro_arg_offset];
85                        state.macro_arg_offset += 1;
86                        state.loc = tok.loc();
87                        return Some(Ok(tok));
88                    }
89
90                    let tok = mac.tokens[state.macro_offset];
91                    match tok {
92                        MacroToken::Token(tok) => {
93                            state.macro_offset += 1;
94                            state.loc = tok.loc();
95                            return Some(Ok(tok));
96                        }
97
98                        MacroToken::Argument { index, .. } => {
99                            state.expanding_macro_arg = Some(index);
100                            state.macro_arg_offset = 0;
101                            continue;
102                        }
103
104                        MacroToken::Entropy { loc } => {
105                            state.macro_offset += 1;
106                            state.loc = loc;
107                            return Some(Ok(Token::String {
108                                loc,
109                                value: state.entropy,
110                            }));
111                        }
112                    }
113                }
114            }
115        }
116    }
117}
118
119#[derive(Copy, Clone, Debug)]
120enum MacroToken<A: ArchTokens> {
121    Token(Token<A>),
122    Argument { index: usize },
123    Entropy { loc: SourceLoc },
124}
125
126struct Macro<A: ArchTokens> {
127    args: Vec<StrRef>,
128    tokens: Vec<MacroToken<A>>,
129}
130
131#[derive(thiserror::Error, Debug)]
132#[error("{0}")]
133pub struct AssemblerError(pub String);
134
135impl From<LexerError> for (SourceLoc, AssemblerError) {
136    fn from(e: LexerError) -> Self {
137        (e.loc(), AssemblerError(format!("{e}")))
138    }
139}
140
141struct MacroState<A: ArchTokens> {
142    name: StrRef,
143    args: Vec<Vec<Token<A>>>,
144    macro_offset: usize,
145    expanding_macro_arg: Option<usize>,
146    macro_arg_offset: usize,
147    loc: SourceLoc,
148    included_from: Option<SourceLoc>,
149    entropy: StrRef,
150}
151
152enum SegmentMode {
153    Code,
154    Addr,
155}
156
157pub struct Assembler<S, R, A: ArchTokens, Z> {
158    file_manager: FileManager<S>,
159    pub(crate) str_interner: Rc<RefCell<StrInterner>>,
160    token_sources: Vec<TokenSource<R, A>>,
161    token_source: Option<TokenSource<R, A>>,
162    cwds: Vec<PathRef>,
163    cwd: Option<PathRef>,
164    macros: FxHashMap<StrRef, Macro<A>>,
165    pub(crate) symtab: Symtab,
166    pub(crate) data: Vec<u8>,
167    seg_mode: SegmentMode,
168    pub(crate) links: Vec<Link>,
169
170    entropy: usize,
171    stash: Option<Token<A>>,
172    loc: Option<SourceLoc>,
173    pub(crate) here: u32,
174    active_namespace: Option<StrRef>,
175    active_macro: Option<StrRef>,
176    if_level: usize,
177
178    marker: PhantomData<Z>,
179}
180
181pub trait ArchAssembler<S, R, A: ArchTokens> {
182    fn parse(
183        asm: &mut Assembler<S, R, A, Self>,
184        name: A::OperationName,
185    ) -> Result<(), (SourceLoc, AssemblerError)>
186    where
187        Self: Sized;
188}
189
190impl<S, R, A, Z> Assembler<S, R, A, Z>
191where
192    S: FileSystem<Reader = R>,
193    R: Read,
194    A: ArchTokens,
195    Z: ArchAssembler<S, R, A>,
196{
197    pub fn new(file_system: S, _: Z) -> Self {
198        Self {
199            file_manager: FileManager::new(file_system),
200            str_interner: Rc::new(RefCell::new(StrInterner::new())),
201            token_sources: Vec::new(),
202            token_source: None,
203            cwds: Vec::new(),
204            cwd: None,
205            macros: FxHashMap::default(),
206            symtab: Symtab::new(),
207            data: Vec::new(),
208            seg_mode: SegmentMode::Code,
209            links: Vec::new(),
210
211            entropy: 0,
212            stash: None,
213            loc: None,
214            here: 0,
215            active_namespace: None,
216            active_macro: None,
217            if_level: 0,
218
219            marker: PhantomData,
220        }
221    }
222
223    pub fn add_search_path<C: AsRef<Path>, P: AsRef<Path>>(
224        &mut self,
225        cwd: C,
226        path: P,
227    ) -> Result<(), AssemblerError> {
228        let path = path.as_ref();
229        self.file_manager.add_search_path(cwd, path).map_err(|e| {
230            AssemblerError(format!(
231                "Failed to find include path \"{}\": {e}",
232                path.display()
233            ))
234        })?;
235        Ok(())
236    }
237
238    pub fn assemble<C: AsRef<Path>, P: AsRef<Path>>(
239        mut self,
240        cwd: C,
241        path: P,
242    ) -> Result<Module<S>, AssemblerError> {
243        let path = path.as_ref();
244        let (pathref, reader) = match self.file_manager.reader(&cwd, path) {
245            Ok(Some(tup)) => tup,
246            Ok(None) => {
247                return Err(AssemblerError(format!(
248                    "File not found: \"{}\"",
249                    path.display()
250                )))
251            }
252            Err(e) => {
253                return Err(AssemblerError(format!(
254                    "Failed to open \"{}\" for reading: {e}",
255                    path.display()
256                )))
257            }
258        };
259
260        self.token_source = Some(TokenSource::Lexer(Lexer::new(
261            self.str_interner.clone(),
262            None,
263            pathref,
264            reader,
265        )));
266        self.cwd = Some(self.file_manager.intern(cwd, "."));
267
268        if let Err((loc, e)) = self.parse_all() {
269            return Err(self.trace_error(loc, e));
270        }
271
272        let Self {
273            str_interner,
274            file_manager,
275            symtab,
276            data,
277            links,
278            ..
279        } = self;
280        Ok(Module::new(str_interner, file_manager, symtab, data, links))
281    }
282
283    #[inline]
284    fn loc(&mut self) -> SourceLoc {
285        self.loc.unwrap()
286    }
287
288    pub(crate) fn peek(&mut self) -> Result<Option<Token<A>>, (SourceLoc, AssemblerError)> {
289        loop {
290            if self.token_source.is_none() {
291                self.token_source = self.token_sources.pop();
292                self.cwd = self.cwds.pop();
293            }
294            match self.stash {
295                Some(_) => return Ok(self.stash),
296
297                None => match &mut self.token_source {
298                    None => return Ok(None),
299
300                    Some(token_source) => {
301                        let tok = token_source.next(&mut self.macros).transpose()?;
302                        // Note: we intentionally do not skip all newlines and comments.
303                        // we want to pass them on to expression parsing! They act as an
304                        // "epsilon" token to terminate a non-terminal expression!
305                        if let Some(Token::Symbol {
306                            name: SymbolName::BackSlash,
307                            ..
308                        }) = tok
309                        {
310                            match token_source.next(&mut self.macros).transpose()? {
311                                None => return self.end_of_input_err(),
312
313                                Some(Token::Comment { .. } | Token::NewLine { .. }) => {
314                                    continue;
315                                }
316
317                                Some(tok) => {
318                                    return asm_err!(
319                                        tok.loc(),
320                                        "Unexpected {}, expected a line break or comment after a backslash",
321                                        tok.as_display(&self.str_interner)
322                                    );
323                                }
324                            }
325                        }
326
327                        // if we arent currently defining a macro
328                        if self.active_macro.is_none() {
329                            // check to see if the current label token is a macro we need to expand
330                            if let Some(Token::Label {
331                                kind: LabelKind::Global,
332                                value,
333                                ..
334                            }) = tok
335                            {
336                                if self.macros.contains_key(&value) {
337                                    let mac = self.expect_macro_invoke(value)?;
338                                    self.token_sources.push(self.token_source.take().unwrap());
339                                    self.cwds.push(self.cwd.unwrap());
340
341                                    self.token_sources.push(TokenSource::Macro(mac));
342                                    self.cwds.push(self.cwd.take().unwrap());
343                                    continue;
344                                }
345                            }
346
347                            // Check for any of the macro-like directives
348                            match tok {
349                                Some(Token::Directive {
350                                    loc,
351                                    name: DirectiveName::String,
352                                }) => {
353                                    self.stash = Some(self.expect_string_directive_arg(loc)?);
354                                    self.loc = Some(loc);
355                                    continue;
356                                }
357
358                                Some(Token::Directive {
359                                    loc,
360                                    name: DirectiveName::Label,
361                                }) => {
362                                    self.stash = Some(self.expect_label_directive_arg(loc)?);
363                                    self.loc = Some(loc);
364                                    continue;
365                                }
366
367                                Some(Token::Directive {
368                                    loc,
369                                    name: DirectiveName::Count,
370                                }) => {
371                                    let mac = self.expect_count_directive(loc)?;
372
373                                    self.token_sources.push(self.token_source.take().unwrap());
374                                    self.cwds.push(self.cwd.unwrap());
375
376                                    self.token_sources.push(TokenSource::Macro(mac));
377                                    self.cwds.push(self.cwd.take().unwrap());
378                                    continue;
379                                }
380
381                                Some(Token::Directive {
382                                    loc,
383                                    name: DirectiveName::GetMeta,
384                                }) => {
385                                    let direct = match self.next()? {
386                                        None => return self.end_of_input_err(),
387
388                                        Some(Token::Label { loc, value, kind }) => match kind {
389                                            LabelKind::Global | LabelKind::Direct => value,
390
391                                            LabelKind::Local => {
392                                                if let Some(namespace) = self.active_namespace {
393                                                    let global_label = {
394                                                        let interner =
395                                                            self.str_interner.as_ref().borrow();
396                                                        let global =
397                                                            interner.get(namespace).unwrap();
398                                                        let label = interner.get(value).unwrap();
399                                                        format!("{global}{label}")
400                                                    };
401                                                    self.str_interner
402                                                        .borrow_mut()
403                                                        .intern(global_label)
404                                                } else {
405                                                    let interner =
406                                                        self.str_interner.as_ref().borrow();
407                                                    let label = interner.get(value).unwrap();
408                                                    return asm_err!(loc, "The local symbol \"{label}\" is being read but there was no global label defined before it");
409                                                }
410                                            }
411                                        },
412
413                                        Some(tok) => {
414                                            return asm_err!(
415                                                tok.loc(),
416                                                "Unexpected {}, expected a label",
417                                                tok.as_display(&self.str_interner)
418                                            )
419                                        }
420                                    };
421
422                                    self.expect_symbol(SymbolName::Comma)?;
423
424                                    let key = match self.next()? {
425                                        None => return self.end_of_input_err(),
426                                        Some(Token::String { value, .. }) => value,
427                                        Some(tok) => {
428                                            return asm_err!(
429                                                tok.loc(),
430                                                "Unexpected {}, expected a metadata key",
431                                                tok.as_display(&self.str_interner)
432                                            );
433                                        }
434                                    };
435
436                                    let mut toks = Vec::new();
437                                    if let Some(sym) = self.symtab.get(direct) {
438                                        if let Some(meta) =
439                                            self.symtab.meta_interner().get(sym.meta())
440                                        {
441                                            for item in meta {
442                                                if item[0] == key {
443                                                    toks.push(MacroToken::Token(Token::String {
444                                                        loc,
445                                                        value: item[1],
446                                                    }));
447                                                }
448                                            }
449                                        }
450                                    } else {
451                                        let mut interner = self.str_interner.borrow_mut();
452                                        let value = interner.intern("");
453                                        toks.push(MacroToken::Token(Token::String { loc, value }));
454                                    }
455
456                                    let (name, entropy) = {
457                                        let mut interner = self.str_interner.borrow_mut();
458                                        let name = interner
459                                            .intern(format!("@metaget Invocation{}", self.entropy));
460                                        let entropy =
461                                            interner.intern(format!("__{}", self.entropy));
462                                        (name, entropy)
463                                    };
464                                    self.entropy += 1;
465                                    self.macros.insert(
466                                        name,
467                                        Macro {
468                                            args: Vec::new(),
469                                            tokens: toks,
470                                        },
471                                    );
472
473                                    self.token_sources.push(self.token_source.take().unwrap());
474                                    self.cwds.push(self.cwd.unwrap());
475
476                                    self.token_sources.push(TokenSource::Macro(MacroState {
477                                        name,
478                                        args: Vec::new(),
479                                        macro_offset: 0,
480                                        expanding_macro_arg: None,
481                                        macro_arg_offset: 0,
482                                        loc,
483                                        included_from: Some(loc),
484                                        entropy,
485                                    }));
486                                    self.cwds.push(self.cwd.take().unwrap());
487                                    continue;
488                                }
489
490                                Some(Token::Directive {
491                                    loc,
492                                    name: DirectiveName::Parse,
493                                }) => {
494                                    let reader = match self.next()? {
495                                        None => return self.end_of_input_err(),
496                                        Some(Token::String { value, .. }) => {
497                                            let interner = self.str_interner.as_ref().borrow();
498                                            // TODO: Not really efficient to clone. but /shrug
499                                            Cursor::new(interner.get(value).unwrap().to_owned())
500                                        }
501                                        Some(tok) => {
502                                            return asm_err!(
503                                                tok.loc(),
504                                                "Unexpected {}, expected a string to parse",
505                                                tok.as_display(&self.str_interner)
506                                            )
507                                        }
508                                    };
509
510                                    self.token_sources.push(self.token_source.take().unwrap());
511                                    self.cwds.push(self.cwd.unwrap());
512
513                                    self.token_sources.push(TokenSource::ParseLexer(Lexer::new(
514                                        self.str_interner.clone(),
515                                        Some(loc),
516                                        loc.pathref,
517                                        reader,
518                                    )));
519                                    self.cwds.push(self.cwd.take().unwrap());
520                                    continue;
521                                }
522
523                                Some(Token::Directive {
524                                    loc,
525                                    name: DirectiveName::Each,
526                                }) => {
527                                    let mut states = self.expect_each_directive(loc)?;
528                                    self.token_sources.push(self.token_source.take().unwrap());
529                                    self.cwds.push(self.cwd.unwrap());
530
531                                    for _ in 0..states.len() {
532                                        self.cwds.push(self.cwd.unwrap());
533                                    }
534                                    self.cwd = None;
535                                    self.token_sources
536                                        .extend(states.drain(..).rev().map(TokenSource::Macro));
537                                    continue;
538                                }
539
540                                Some(Token::Directive {
541                                    loc,
542                                    name: DirectiveName::Hex,
543                                }) => {
544                                    let mac = self.expect_number_directive_arg(
545                                        loc,
546                                        DirectiveName::Hex,
547                                        16,
548                                    )?;
549
550                                    self.token_sources.push(self.token_source.take().unwrap());
551                                    self.cwds.push(self.cwd.unwrap());
552
553                                    self.token_sources.push(TokenSource::Macro(mac));
554                                    self.cwds.push(self.cwd.take().unwrap());
555                                    continue;
556                                }
557
558                                Some(Token::Directive {
559                                    loc,
560                                    name: DirectiveName::Bin,
561                                }) => {
562                                    let mac = self.expect_number_directive_arg(
563                                        loc,
564                                        DirectiveName::Bin,
565                                        2,
566                                    )?;
567
568                                    self.token_sources.push(self.token_source.take().unwrap());
569                                    self.cwds.push(self.cwd.unwrap());
570
571                                    self.token_sources.push(TokenSource::Macro(mac));
572                                    self.cwds.push(self.cwd.take().unwrap());
573                                    continue;
574                                }
575
576                                Some(Token::Directive {
577                                    loc,
578                                    name: DirectiveName::IsDef,
579                                }) => {
580                                    let direct = match self.next()? {
581                                        None => return self.end_of_input_err(),
582
583                                        Some(Token::Label { loc, value, kind }) => match kind {
584                                            LabelKind::Global | LabelKind::Direct => value,
585
586                                            LabelKind::Local => {
587                                                if let Some(namespace) = self.active_namespace {
588                                                    let global_label = {
589                                                        let interner =
590                                                            self.str_interner.as_ref().borrow();
591                                                        let global =
592                                                            interner.get(namespace).unwrap();
593                                                        let label = interner.get(value).unwrap();
594                                                        format!("{global}{label}")
595                                                    };
596                                                    self.str_interner
597                                                        .borrow_mut()
598                                                        .intern(global_label)
599                                                } else {
600                                                    let interner =
601                                                        self.str_interner.as_ref().borrow();
602                                                    let label = interner.get(value).unwrap();
603                                                    return asm_err!(loc, "The local symbol \"{label}\" is being read but there was no global label defined before it");
604                                                }
605                                            }
606                                        },
607
608                                        Some(tok) => {
609                                            return asm_err!(
610                                                tok.loc(),
611                                                "Unexpected {}, expected a label",
612                                                tok.as_display(&self.str_interner)
613                                            )
614                                        }
615                                    };
616                                    let value = if self.symtab.get(direct).is_some() {
617                                        1
618                                    } else {
619                                        0
620                                    };
621                                    self.stash = Some(Token::Number { loc, value });
622                                    self.loc = Some(loc);
623                                    continue;
624                                }
625
626                                _ => {}
627                            }
628                        }
629
630                        self.stash = tok;
631                        self.loc = Some(token_source.loc());
632                        if self.stash.is_none() {
633                            self.token_source = None;
634                            self.cwd = None;
635                        }
636                    }
637                },
638            }
639        }
640    }
641
642    pub(crate) fn next(&mut self) -> Result<Option<Token<A>>, (SourceLoc, AssemblerError)> {
643        self.peek()?;
644        Ok(self.stash.take())
645    }
646
647    fn trace_error(&self, loc: SourceLoc, e: AssemblerError) -> AssemblerError {
648        let mut msg = String::new();
649        let fmt_msg = &mut msg as &mut dyn Write;
650
651        let path = self.file_manager.borrow().path(loc.pathref).unwrap();
652        writeln!(fmt_msg, "In \"{}\"", path.display()).unwrap();
653
654        if let Some(token_source) = self.token_source.as_ref() {
655            let mut included_from = token_source.included_from();
656            for token_source in self.token_sources.iter().rev() {
657                // There are sources on the stack so included_from will be set
658                let loc = included_from.unwrap();
659                let path = self.file_manager.borrow().path(loc.pathref).unwrap();
660                writeln!(
661                    fmt_msg,
662                    "\tIncluded from {}:{}:{}",
663                    path.display(),
664                    loc.line,
665                    if loc.column == 0 { 1 } else { loc.column }
666                )
667                .unwrap();
668                included_from = token_source.included_from();
669            }
670        }
671        writeln!(
672            fmt_msg,
673            "\n{}:{}:{}:",
674            path.file_name().unwrap().to_str().unwrap(),
675            loc.line,
676            if loc.column == 0 { 1 } else { loc.column }
677        )
678        .unwrap();
679        writeln!(fmt_msg, "{e}").unwrap();
680        AssemblerError(msg)
681    }
682
683    #[inline]
684    pub(crate) fn end_of_input_err<T>(&mut self) -> Result<T, (SourceLoc, AssemblerError)> {
685        asm_err!(self.loc(), "Unexpected end of input")
686    }
687
688    #[inline]
689    pub(crate) fn expect_symbol(
690        &mut self,
691        sym: SymbolName,
692    ) -> Result<(), (SourceLoc, AssemblerError)> {
693        match self.next()? {
694            Some(Token::Symbol { loc, name }) => {
695                if name != sym {
696                    asm_err!(loc, "Unexpected symbol: \"{name}\", expected \"{sym}\"")
697                } else {
698                    Ok(())
699                }
700            }
701            Some(tok) => asm_err!(
702                tok.loc(),
703                "Unexpected \"{}\", expected the symbol \"{sym}\"",
704                tok.as_display(&self.str_interner)
705            ),
706            None => self.end_of_input_err(),
707        }
708    }
709
710    #[inline]
711    pub(crate) fn expect_register(
712        &mut self,
713        reg: A::RegisterName,
714    ) -> Result<(), (SourceLoc, AssemblerError)> {
715        match self.next()? {
716            Some(Token::Register { loc, name }) => {
717                if name != reg {
718                    asm_err!(
719                        loc,
720                        "Unexpected register: \"{name}\", expected the register \"{reg}\""
721                    )
722                } else {
723                    Ok(())
724                }
725            }
726            Some(tok) => asm_err!(
727                tok.loc(),
728                "Unexpected {}, expected the register \"{reg}\"",
729                tok.as_display(&self.str_interner)
730            ),
731            None => self.end_of_input_err(),
732        }
733    }
734
735    pub(crate) fn expect_immediate(&mut self) -> Result<(), (SourceLoc, AssemblerError)> {
736        let (loc, expr) = self.expr()?;
737        if let Some(value) = expr.evaluate(&self.symtab, &self.str_interner) {
738            if (value as u32) > (u8::MAX as u32) {
739                return asm_err!(loc, "Expression result ({value}) will not fit in a byte");
740            }
741            self.data.push(value as u8);
742        } else {
743            self.links.push(Link::byte(loc, self.data.len(), expr));
744            self.data.push(0);
745        }
746        Ok(())
747    }
748
749    pub(crate) fn expect_hmem_immediate(&mut self) -> Result<(), (SourceLoc, AssemblerError)> {
750        let (loc, expr) = self.expr()?;
751        if let Some(value) = expr.evaluate(&self.symtab, &self.str_interner) {
752            if (value as u32) > (u8::MAX as u32) {
753                if (value as u32) > (u16::MAX as u32) {
754                    return asm_err!(loc, "Expression result ({value}) will not fit in a word");
755                }
756                if !(0xFF00..=0xFFFF).contains(&value) {
757                    return asm_err!(
758                        loc,
759                        "Expression result ({value}) must be between $FF00 and $FFFF"
760                    );
761                }
762            }
763            self.data.push(value as u8);
764        } else {
765            self.links.push(Link::byte(loc, self.data.len(), expr));
766            self.data.push(0);
767        }
768        Ok(())
769    }
770
771    pub(crate) fn expect_wide_immediate(&mut self) -> Result<(), (SourceLoc, AssemblerError)> {
772        let (loc, expr) = self.expr()?;
773        if let Some(value) = expr.evaluate(&self.symtab, &self.str_interner) {
774            if (value as u32) > (u16::MAX as u32) {
775                return asm_err!(loc, "Expression result ({value}) will not fit in a word");
776            }
777            self.data.extend_from_slice(&(value as u16).to_le_bytes());
778        } else {
779            self.links.push(Link::word(loc, self.data.len(), expr));
780            self.data.push(0);
781            self.data.push(0);
782        }
783        Ok(())
784    }
785
786    pub(crate) fn expect_branch_immediate(&mut self) -> Result<(), (SourceLoc, AssemblerError)> {
787        let (loc, mut expr) = self.expr()?;
788        expr.push(ExprNode::Value(self.here.wrapping_add(2) as i32)); // subtract where the PC will be
789        expr.push(ExprNode::Sub);
790        if let Some(value) = expr.evaluate(&self.symtab, &self.str_interner) {
791            if (value < (i8::MIN as i32)) || (value > (i8::MAX as i32)) {
792                return asm_err!(loc, "Branch distance ({value}) will not fit in a byte");
793            }
794            self.data.push(value as u8);
795        } else {
796            self.links
797                .push(Link::signed_byte(loc, self.data.len(), expr));
798            self.data.push(0);
799        }
800        Ok(())
801    }
802
803    fn expect_macro_invoke(
804        &mut self,
805        name: StrRef,
806    ) -> Result<MacroState<A>, (SourceLoc, AssemblerError)> {
807        let mut args = Vec::new();
808        let arg_count = self.macros.get(&name).unwrap().args.len();
809        let loc = self.loc();
810
811        for i in 0..arg_count {
812            let mut toks = Vec::new();
813
814            let mut brace_depth = 0;
815            loop {
816                match self.next()? {
817                    None => return self.end_of_input_err(),
818
819                    Some(Token::NewLine { .. } | Token::Comment { .. }) => {}
820
821                    Some(
822                        tok @ Token::Symbol {
823                            name: SymbolName::BraceOpen,
824                            ..
825                        },
826                    ) => {
827                        if brace_depth > 0 {
828                            toks.push(tok);
829                        }
830                        brace_depth += 1;
831                    }
832
833                    Some(
834                        tok @ Token::Symbol {
835                            name: SymbolName::BraceClose,
836                            ..
837                        },
838                    ) => {
839                        brace_depth -= 1;
840                        if brace_depth == 0 {
841                            break;
842                        }
843                        toks.push(tok);
844                    }
845
846                    Some(tok) => {
847                        toks.push(tok);
848                        if brace_depth == 0 {
849                            break;
850                        }
851                    }
852                }
853            }
854            args.push(toks);
855            if i < arg_count - 1 {
856                self.expect_symbol(SymbolName::Comma)?;
857            }
858        }
859
860        let entropy = self
861            .str_interner
862            .borrow_mut()
863            .intern(format!("__{}", self.entropy));
864        self.entropy += 1;
865        Ok(MacroState {
866            name,
867            args,
868            macro_offset: 0,
869            expanding_macro_arg: None,
870            macro_arg_offset: 0,
871            loc,
872            included_from: Some(loc),
873            entropy,
874        })
875    }
876
877    fn expect_string_directive_arg(
878        &mut self,
879        loc: SourceLoc,
880    ) -> Result<Token<A>, (SourceLoc, AssemblerError)> {
881        let mut string = String::new();
882        let mut brace_depth = 0;
883        loop {
884            match self.next()? {
885                None => return self.end_of_input_err(),
886
887                Some(Token::NewLine { .. } | Token::Comment { .. }) => {}
888
889                Some(Token::Symbol {
890                    name: SymbolName::BraceOpen,
891                    ..
892                }) => {
893                    if brace_depth > 0 {
894                        string.push('{');
895                    }
896                    brace_depth += 1;
897                }
898
899                Some(Token::Symbol {
900                    name: SymbolName::BraceClose,
901                    ..
902                }) => {
903                    brace_depth -= 1;
904                    if brace_depth == 0 {
905                        break;
906                    }
907                    string.push('}');
908                }
909
910                Some(Token::String { value, .. }) => {
911                    let interner = self.str_interner.as_ref().borrow();
912                    let value = interner.get(value).unwrap();
913                    string.push_str(value);
914                }
915
916                Some(Token::Label { value, .. }) => {
917                    let interner = self.str_interner.as_ref().borrow();
918                    let value = interner.get(value).unwrap();
919                    string.push_str(value);
920                }
921
922                Some(Token::Number { value, .. }) => {
923                    write!(string, "{value:x}").unwrap();
924                }
925
926                Some(Token::Operation { name, .. }) => {
927                    write!(string, "{name}").unwrap();
928                }
929
930                Some(Token::Register { name, .. }) => {
931                    write!(string, "{name}").unwrap();
932                }
933
934                Some(Token::Symbol { name, .. }) => {
935                    write!(string, "{name}").unwrap();
936                }
937
938                Some(tok) => {
939                    return asm_err!(
940                        tok.loc(),
941                        "Cannot stringify token: {}",
942                        tok.as_display(&self.str_interner)
943                    );
944                }
945            }
946            if brace_depth == 0 {
947                break;
948            }
949        }
950        let value = self.str_interner.borrow_mut().intern(&string);
951        Ok(Token::String { loc, value })
952    }
953
954    fn expect_number_directive_arg(
955        &mut self,
956        loc: SourceLoc,
957        directive_name: DirectiveName,
958        base: u32,
959    ) -> Result<MacroState<A>, (SourceLoc, AssemblerError)> {
960        let value = match self.const_expr()? {
961            (_, Some(value)) => {
962                value
963            }
964            (loc, None) => {
965                return asm_err!(
966                    loc,
967                    "The expression following an \"{directive_name}\" directive must be immediately solvable"
968                )
969            }
970        };
971
972        let mut interner = self.str_interner.borrow_mut();
973        let name = interner.intern(format!("{directive_name} Invocation{}", self.entropy));
974        let entropy = interner.intern(format!("__{}", self.entropy));
975        self.entropy += 1;
976        let value = match base {
977            2 => interner.intern(format!("{value:b}")),
978            16 => interner.intern(format!("{value:x}")),
979            _ => unreachable!(),
980        };
981        let mut toks = Vec::new();
982        toks.push(MacroToken::Token(Token::String { loc, value }));
983
984        // There is a weird quirk with @hex / @bin
985        // since it ends in a non-terminal (an expression)
986        // there can be a token still in the stash..
987        // This is a big problem because we need that token
988        // to be placed after the tokens in this invocation
989        if let Some(tok) = self.stash.take() {
990            toks.push(MacroToken::Token(tok));
991        }
992
993        self.macros.insert(
994            name,
995            Macro {
996                args: Vec::new(),
997                tokens: toks,
998            },
999        );
1000
1001        Ok(MacroState {
1002            name,
1003            args: Vec::new(),
1004            macro_offset: 0,
1005            expanding_macro_arg: None,
1006            macro_arg_offset: 0,
1007            loc,
1008            included_from: Some(loc),
1009            entropy,
1010        })
1011    }
1012
1013    fn expect_count_directive(
1014        &mut self,
1015        loc: SourceLoc,
1016    ) -> Result<MacroState<A>, (SourceLoc, AssemblerError)> {
1017        let count = match self.const_expr()? {
1018            (loc, Some(value)) => {
1019                if value < 0 {
1020                    return asm_err!(
1021                        loc,
1022                        "\"@count\" expression result ({value}) must be positive"
1023                    );
1024                }
1025                value as usize
1026            }
1027            (loc, None) => {
1028                return asm_err!(
1029                    loc,
1030                    "The expression following an \"@count\" directive must be immediately solvable"
1031                )
1032            }
1033        };
1034
1035        let (name, entropy) = {
1036            let mut interner = self.str_interner.borrow_mut();
1037            let name = interner.intern(format!("@count Invocation{}", self.entropy));
1038            let entropy = interner.intern(format!("__{}", self.entropy));
1039            (name, entropy)
1040        };
1041        self.entropy += 1;
1042        let mut toks = Vec::new();
1043        for i in 0..count {
1044            toks.push(MacroToken::Token(Token::Number {
1045                loc,
1046                value: i as u32,
1047            }));
1048        }
1049
1050        // There is a weird quirk with @count
1051        // since it ends in a non-terminal (an expression)
1052        // there can be a token still in the stash..
1053        // This is a big problem because we need that token
1054        // to be placed after the tokens in this invocation
1055        if let Some(tok) = self.stash.take() {
1056            toks.push(MacroToken::Token(tok));
1057        }
1058
1059        self.macros.insert(
1060            name,
1061            Macro {
1062                args: Vec::new(),
1063                tokens: toks,
1064            },
1065        );
1066
1067        Ok(MacroState {
1068            name,
1069            args: Vec::new(),
1070            macro_offset: 0,
1071            expanding_macro_arg: None,
1072            macro_arg_offset: 0,
1073            loc,
1074            included_from: Some(loc),
1075            entropy,
1076        })
1077    }
1078
1079    fn expect_label_directive_arg(
1080        &mut self,
1081        loc: SourceLoc,
1082    ) -> Result<Token<A>, (SourceLoc, AssemblerError)> {
1083        let mut string = String::new();
1084        let mut brace_depth = 0;
1085        loop {
1086            match self.next()? {
1087                None => return self.end_of_input_err(),
1088
1089                Some(Token::NewLine { .. } | Token::Comment { .. }) => {}
1090
1091                Some(Token::Symbol {
1092                    name: SymbolName::BraceOpen,
1093                    ..
1094                }) => {
1095                    if brace_depth > 0 {
1096                        string.push('{');
1097                    }
1098                    brace_depth += 1;
1099                }
1100
1101                Some(Token::Symbol {
1102                    name: SymbolName::BraceClose,
1103                    ..
1104                }) => {
1105                    brace_depth -= 1;
1106                    if brace_depth == 0 {
1107                        break;
1108                    }
1109                    string.push('}');
1110                }
1111
1112                Some(Token::String { value, .. }) => {
1113                    let interner = self.str_interner.as_ref().borrow();
1114                    let value = interner.get(value).unwrap();
1115                    string.push_str(value);
1116                }
1117
1118                Some(Token::Label { value, .. }) => {
1119                    let interner = self.str_interner.as_ref().borrow();
1120                    let value = interner.get(value).unwrap();
1121                    string.push_str(value);
1122                }
1123
1124                Some(Token::Number { value, .. }) => {
1125                    write!(string, "{value:x}").unwrap();
1126                }
1127
1128                Some(Token::Operation { name, .. }) => {
1129                    write!(string, "{name}").unwrap();
1130                }
1131
1132                Some(Token::Register { name, .. }) => {
1133                    write!(string, "{name}").unwrap();
1134                }
1135
1136                Some(Token::Symbol { name, .. }) => {
1137                    write!(string, "{name}").unwrap();
1138                }
1139
1140                Some(tok) => {
1141                    return asm_err!(
1142                        tok.loc(),
1143                        "Cannot labelify token: {}",
1144                        tok.as_display(&self.str_interner)
1145                    );
1146                }
1147            }
1148            if brace_depth == 0 {
1149                break;
1150            }
1151        }
1152        if string.split_whitespace().count() > 1 {
1153            return asm_err!(loc, "Malformed label: \"{string}\"");
1154        }
1155        let value = self.str_interner.borrow_mut().intern(&string);
1156        match string.chars().filter(|c| *c == '.').count() {
1157            0 => Ok(Token::Label {
1158                loc,
1159                kind: LabelKind::Global,
1160                value,
1161            }),
1162            1 => {
1163                if string.starts_with('.') {
1164                    Ok(Token::Label {
1165                        loc,
1166                        kind: LabelKind::Local,
1167                        value,
1168                    })
1169                } else {
1170                    Ok(Token::Label {
1171                        loc,
1172                        kind: LabelKind::Direct,
1173                        value,
1174                    })
1175                }
1176            }
1177            _ => asm_err!(loc, "Malformed label: \"{string}\""),
1178        }
1179    }
1180
1181    fn expect_each_directive(
1182        &mut self,
1183        loc: SourceLoc,
1184    ) -> Result<Vec<MacroState<A>>, (SourceLoc, AssemblerError)> {
1185        let arg_value = match self.next()? {
1186            None => return self.end_of_input_err(),
1187
1188            Some(Token::Label { loc, kind, value }) => {
1189                let interner = self.str_interner.as_ref().borrow();
1190                let str_value = interner.get(value).unwrap();
1191                if kind != LabelKind::Global {
1192                    return asm_err!(
1193                        loc,
1194                        "\"@each\" label \"{str_value}\" must be a global label",
1195                    );
1196                }
1197                value
1198            }
1199
1200            Some(tok) => {
1201                return asm_err!(
1202                    tok.loc(),
1203                    "Unexpected {}, expected an \"@each\" token placeholder name",
1204                    tok.as_display(&self.str_interner)
1205                );
1206            }
1207        };
1208
1209        self.expect_symbol(SymbolName::Comma)?;
1210
1211        let mut args = Vec::new();
1212        let mut brace_depth = 0;
1213        loop {
1214            match self.next()? {
1215                None => return self.end_of_input_err(),
1216
1217                Some(Token::NewLine { .. } | Token::Comment { .. }) => {}
1218
1219                Some(
1220                    tok @ Token::Symbol {
1221                        name: SymbolName::BraceOpen,
1222                        ..
1223                    },
1224                ) => {
1225                    if brace_depth > 0 {
1226                        args.push(tok);
1227                    }
1228                    brace_depth += 1;
1229                }
1230
1231                Some(
1232                    tok @ Token::Symbol {
1233                        name: SymbolName::BraceClose,
1234                        ..
1235                    },
1236                ) => {
1237                    brace_depth -= 1;
1238                    if brace_depth == 0 {
1239                        break;
1240                    }
1241                    args.push(tok);
1242                }
1243
1244                Some(tok) => {
1245                    args.push(tok);
1246                }
1247            }
1248            if brace_depth == 0 {
1249                break;
1250            }
1251        }
1252
1253        let (name, entropy) = {
1254            let mut interner = self.str_interner.borrow_mut();
1255            let name = interner.intern(format!("@each Invocation{}", self.entropy));
1256            let entropy = interner.intern(format!("__{}", self.entropy));
1257            (name, entropy)
1258        };
1259        self.entropy += 1;
1260        let mut toks = Vec::new();
1261        loop {
1262            match self.next()? {
1263                None => return self.end_of_input_err(),
1264
1265                Some(Token::Directive {
1266                    name: DirectiveName::EndEach,
1267                    ..
1268                }) => {
1269                    break;
1270                }
1271
1272                Some(Token::Directive {
1273                    loc,
1274                    name: DirectiveName::Entropy,
1275                }) => {
1276                    toks.push(MacroToken::Entropy { loc });
1277                }
1278
1279                Some(Token::Label { kind, value, .. })
1280                    if kind == LabelKind::Global && value == arg_value =>
1281                {
1282                    toks.push(MacroToken::Argument { index: 0 });
1283                }
1284
1285                Some(tok) => {
1286                    toks.push(MacroToken::Token(tok));
1287                }
1288            }
1289        }
1290
1291        self.macros.insert(
1292            name,
1293            Macro {
1294                args: vec![arg_value], // the current token
1295                tokens: toks,
1296            },
1297        );
1298
1299        let mut states = Vec::new();
1300        for arg in args {
1301            states.push(MacroState {
1302                name,
1303                args: vec![vec![arg]],
1304                macro_offset: 0,
1305                expanding_macro_arg: None,
1306                macro_arg_offset: 0,
1307                loc,
1308                included_from: Some(loc),
1309                entropy,
1310            });
1311        }
1312        Ok(states)
1313    }
1314
1315    pub(crate) fn const_expr(
1316        &mut self,
1317    ) -> Result<(SourceLoc, Option<i32>), (SourceLoc, AssemblerError)> {
1318        self.expr()
1319            .map(|(loc, expr)| (loc, expr.evaluate(&self.symtab, &self.str_interner)))
1320    }
1321
1322    pub(crate) fn expr(&mut self) -> Result<(SourceLoc, Expr), (SourceLoc, AssemblerError)> {
1323        let mut nodes = Vec::new();
1324        let loc = self.expr_prec_0(&mut nodes)?;
1325        Ok((loc, Expr::new(nodes)))
1326    }
1327
1328    fn expr_prec_0(
1329        &mut self,
1330        nodes: &mut Vec<ExprNode>,
1331    ) -> Result<SourceLoc, (SourceLoc, AssemblerError)> {
1332        let loc = self.expr_prec_1(nodes)?;
1333
1334        loop {
1335            match self.peek()? {
1336                Some(Token::Symbol {
1337                    name: SymbolName::Question,
1338                    ..
1339                }) => {
1340                    self.next()?;
1341                    self.expr_prec_1(nodes)?;
1342                    if self.peeked_symbol(SymbolName::Colon)?.is_none() {
1343                        return asm_err!(self.loc(), "Expected a \":\" in ternary expression");
1344                    }
1345                    self.next()?;
1346                    self.expr_prec_1(nodes)?;
1347                    nodes.push(ExprNode::Ternary);
1348                    return Ok(loc);
1349                }
1350
1351                _ => return Ok(loc),
1352            }
1353        }
1354    }
1355
1356    fn expr_prec_1(
1357        &mut self,
1358        nodes: &mut Vec<ExprNode>,
1359    ) -> Result<SourceLoc, (SourceLoc, AssemblerError)> {
1360        let loc = self.expr_prec_2(nodes)?;
1361
1362        loop {
1363            match self.peek()? {
1364                Some(Token::Symbol {
1365                    name: SymbolName::DoublePipe,
1366                    ..
1367                }) => {
1368                    self.next()?;
1369                    self.expr_prec_2(nodes)?;
1370                    nodes.push(ExprNode::OrLogical);
1371                }
1372                _ => return Ok(loc),
1373            }
1374        }
1375    }
1376
1377    fn expr_prec_2(
1378        &mut self,
1379        nodes: &mut Vec<ExprNode>,
1380    ) -> Result<SourceLoc, (SourceLoc, AssemblerError)> {
1381        let loc = self.expr_prec_3(nodes)?;
1382
1383        loop {
1384            match self.peek()? {
1385                Some(Token::Symbol {
1386                    name: SymbolName::DoubleAmpersand,
1387                    ..
1388                }) => {
1389                    self.next()?;
1390                    self.expr_prec_3(nodes)?;
1391                    nodes.push(ExprNode::AndLogical);
1392                }
1393                _ => return Ok(loc),
1394            }
1395        }
1396    }
1397
1398    fn expr_prec_3(
1399        &mut self,
1400        nodes: &mut Vec<ExprNode>,
1401    ) -> Result<SourceLoc, (SourceLoc, AssemblerError)> {
1402        let loc = self.expr_prec_4(nodes)?;
1403
1404        loop {
1405            match self.peek()? {
1406                Some(Token::Symbol {
1407                    name: SymbolName::Pipe,
1408                    ..
1409                }) => {
1410                    self.next()?;
1411                    self.expr_prec_4(nodes)?;
1412                    nodes.push(ExprNode::Or);
1413                }
1414                _ => return Ok(loc),
1415            }
1416        }
1417    }
1418
1419    fn expr_prec_4(
1420        &mut self,
1421        nodes: &mut Vec<ExprNode>,
1422    ) -> Result<SourceLoc, (SourceLoc, AssemblerError)> {
1423        let loc = self.expr_prec_5(nodes)?;
1424
1425        loop {
1426            match self.peek()? {
1427                Some(Token::Symbol {
1428                    name: SymbolName::Caret,
1429                    ..
1430                }) => {
1431                    self.next()?;
1432                    self.expr_prec_5(nodes)?;
1433                    nodes.push(ExprNode::Xor);
1434                }
1435                _ => return Ok(loc),
1436            }
1437        }
1438    }
1439
1440    fn expr_prec_5(
1441        &mut self,
1442        nodes: &mut Vec<ExprNode>,
1443    ) -> Result<SourceLoc, (SourceLoc, AssemblerError)> {
1444        let loc = self.expr_prec_6(nodes)?;
1445
1446        loop {
1447            match self.peek()? {
1448                Some(Token::Symbol {
1449                    name: SymbolName::Ampersand,
1450                    ..
1451                }) => {
1452                    self.next()?;
1453                    self.expr_prec_6(nodes)?;
1454                    nodes.push(ExprNode::And);
1455                }
1456                _ => return Ok(loc),
1457            }
1458        }
1459    }
1460
1461    fn expr_prec_6(
1462        &mut self,
1463        nodes: &mut Vec<ExprNode>,
1464    ) -> Result<SourceLoc, (SourceLoc, AssemblerError)> {
1465        let loc = self.expr_prec_7(nodes)?;
1466
1467        loop {
1468            match self.peek()? {
1469                Some(Token::Symbol {
1470                    name: SymbolName::Equal,
1471                    ..
1472                }) => {
1473                    self.next()?;
1474                    self.expr_prec_7(nodes)?;
1475                    nodes.push(ExprNode::Equal);
1476                }
1477                Some(Token::Symbol {
1478                    name: SymbolName::NotEqual,
1479                    ..
1480                }) => {
1481                    self.next()?;
1482                    self.expr_prec_7(nodes)?;
1483                    nodes.push(ExprNode::NotEqual);
1484                }
1485                _ => return Ok(loc),
1486            }
1487        }
1488    }
1489
1490    fn expr_prec_7(
1491        &mut self,
1492        nodes: &mut Vec<ExprNode>,
1493    ) -> Result<SourceLoc, (SourceLoc, AssemblerError)> {
1494        let loc = self.expr_prec_8(nodes)?;
1495
1496        loop {
1497            match self.peek()? {
1498                Some(Token::Symbol {
1499                    name: SymbolName::LessThan,
1500                    ..
1501                }) => {
1502                    self.next()?;
1503                    self.expr_prec_8(nodes)?;
1504                    nodes.push(ExprNode::LessThan);
1505                }
1506                Some(Token::Symbol {
1507                    name: SymbolName::LessEqual,
1508                    ..
1509                }) => {
1510                    self.next()?;
1511                    self.expr_prec_8(nodes)?;
1512                    nodes.push(ExprNode::LessThanEqual);
1513                }
1514                Some(Token::Symbol {
1515                    name: SymbolName::GreaterThan,
1516                    ..
1517                }) => {
1518                    self.next()?;
1519                    self.expr_prec_8(nodes)?;
1520                    nodes.push(ExprNode::GreaterThan);
1521                }
1522                Some(Token::Symbol {
1523                    name: SymbolName::GreaterEqual,
1524                    ..
1525                }) => {
1526                    self.next()?;
1527                    self.expr_prec_8(nodes)?;
1528                    nodes.push(ExprNode::GreaterThanEqual);
1529                }
1530                _ => return Ok(loc),
1531            }
1532        }
1533    }
1534
1535    fn expr_prec_8(
1536        &mut self,
1537        nodes: &mut Vec<ExprNode>,
1538    ) -> Result<SourceLoc, (SourceLoc, AssemblerError)> {
1539        let loc = self.expr_prec_9(nodes)?;
1540
1541        loop {
1542            match self.peek()? {
1543                Some(Token::Symbol {
1544                    name: SymbolName::ShiftLeft,
1545                    ..
1546                }) => {
1547                    self.next()?;
1548                    self.expr_prec_9(nodes)?;
1549                    nodes.push(ExprNode::ShiftLeft);
1550                }
1551                Some(Token::Symbol {
1552                    name: SymbolName::ShiftLeftLogical,
1553                    ..
1554                }) => {
1555                    self.next()?;
1556                    self.expr_prec_9(nodes)?;
1557                    nodes.push(ExprNode::ShiftLeftLogical);
1558                }
1559                Some(Token::Symbol {
1560                    name: SymbolName::ShiftRight,
1561                    ..
1562                }) => {
1563                    self.next()?;
1564                    self.expr_prec_9(nodes)?;
1565                    nodes.push(ExprNode::ShiftRight);
1566                }
1567                Some(Token::Symbol {
1568                    name: SymbolName::ShiftRightLogical,
1569                    ..
1570                }) => {
1571                    self.next()?;
1572                    self.expr_prec_9(nodes)?;
1573                    nodes.push(ExprNode::ShiftRightLogical);
1574                }
1575                _ => return Ok(loc),
1576            }
1577        }
1578    }
1579
1580    fn expr_prec_9(
1581        &mut self,
1582        nodes: &mut Vec<ExprNode>,
1583    ) -> Result<SourceLoc, (SourceLoc, AssemblerError)> {
1584        let loc = self.expr_prec_10(nodes)?;
1585
1586        loop {
1587            match self.peek()? {
1588                Some(Token::Symbol {
1589                    name: SymbolName::Plus,
1590                    ..
1591                }) => {
1592                    self.next()?;
1593                    self.expr_prec_10(nodes)?;
1594                    nodes.push(ExprNode::Add);
1595                }
1596                Some(Token::Symbol {
1597                    name: SymbolName::Minus,
1598                    ..
1599                }) => {
1600                    self.next()?;
1601                    self.expr_prec_10(nodes)?;
1602                    nodes.push(ExprNode::Sub);
1603                }
1604                _ => return Ok(loc),
1605            }
1606        }
1607    }
1608
1609    fn expr_prec_10(
1610        &mut self,
1611        nodes: &mut Vec<ExprNode>,
1612    ) -> Result<SourceLoc, (SourceLoc, AssemblerError)> {
1613        let loc = self.expr_prec_11(nodes)?;
1614
1615        loop {
1616            match self.peek()? {
1617                Some(Token::Symbol {
1618                    name: SymbolName::Star,
1619                    ..
1620                }) => {
1621                    self.next()?;
1622                    self.expr_prec_11(nodes)?;
1623                    nodes.push(ExprNode::Mul);
1624                }
1625                Some(Token::Symbol {
1626                    name: SymbolName::Div,
1627                    ..
1628                }) => {
1629                    self.next()?;
1630                    self.expr_prec_11(nodes)?;
1631                    nodes.push(ExprNode::Div);
1632                }
1633                Some(Token::Symbol {
1634                    name: SymbolName::Mod,
1635                    ..
1636                }) => {
1637                    self.next()?;
1638                    self.expr_prec_11(nodes)?;
1639                    nodes.push(ExprNode::Rem);
1640                }
1641                _ => return Ok(loc),
1642            }
1643        }
1644    }
1645
1646    fn expr_prec_11(
1647        &mut self,
1648        nodes: &mut Vec<ExprNode>,
1649    ) -> Result<SourceLoc, (SourceLoc, AssemblerError)> {
1650        loop {
1651            match self.peek()? {
1652                None => return self.end_of_input_err(),
1653                Some(Token::Symbol {
1654                    loc,
1655                    name: SymbolName::Minus,
1656                }) => {
1657                    self.next()?;
1658                    self.expr_prec_11(nodes)?;
1659                    nodes.push(ExprNode::Neg);
1660                    return Ok(loc);
1661                }
1662                Some(Token::Symbol {
1663                    loc,
1664                    name: SymbolName::Plus,
1665                }) => {
1666                    self.next()?;
1667                    self.expr_prec_11(nodes)?;
1668                    return Ok(loc);
1669                }
1670                Some(Token::Symbol {
1671                    loc,
1672                    name: SymbolName::Bang,
1673                }) => {
1674                    self.next()?;
1675                    self.expr_prec_11(nodes)?;
1676                    nodes.push(ExprNode::NotLogical);
1677                    return Ok(loc);
1678                }
1679                Some(Token::Symbol {
1680                    loc,
1681                    name: SymbolName::Tilde,
1682                }) => {
1683                    self.next()?;
1684                    self.expr_prec_11(nodes)?;
1685                    nodes.push(ExprNode::Invert);
1686                    return Ok(loc);
1687                }
1688                Some(Token::Symbol {
1689                    loc,
1690                    name: SymbolName::LessThan,
1691                }) => {
1692                    self.next()?;
1693                    self.expr_prec_11(nodes)?;
1694                    nodes.push(ExprNode::Lo);
1695                    return Ok(loc);
1696                }
1697                Some(Token::Symbol {
1698                    loc,
1699                    name: SymbolName::GreaterThan,
1700                }) => {
1701                    self.next()?;
1702                    self.expr_prec_11(nodes)?;
1703                    nodes.push(ExprNode::Hi);
1704                    return Ok(loc);
1705                }
1706                Some(Token::Symbol {
1707                    loc,
1708                    name: SymbolName::ParenOpen,
1709                }) => {
1710                    self.next()?;
1711                    self.expr_prec_0(nodes)?;
1712                    if self.peeked_symbol(SymbolName::ParenClose)?.is_none() {
1713                        return asm_err!(self.loc(), "Expected a \")\" to close expression");
1714                    }
1715                    self.next()?;
1716                    return Ok(loc);
1717                }
1718                Some(Token::Number { loc, value }) => {
1719                    self.next()?;
1720                    nodes.push(ExprNode::Value(value as i32));
1721                    return Ok(loc);
1722                }
1723                Some(Token::Directive { loc, name }) => match name {
1724                    DirectiveName::Here => {
1725                        self.next()?;
1726                        nodes.push(ExprNode::Value(self.here as i32));
1727                        return Ok(loc);
1728                    }
1729
1730                    DirectiveName::SizeOf => {
1731                        self.next()?;
1732                        match self.next()? {
1733                            None => return self.end_of_input_err(),
1734
1735                            Some(Token::Label { loc, kind, value }) => {
1736                                let direct = match kind {
1737                                    LabelKind::Global | LabelKind::Direct => value,
1738
1739                                    LabelKind::Local => {
1740                                        if let Some(namespace) = self.active_namespace {
1741                                            let direct_label = {
1742                                                let interner = self.str_interner.as_ref().borrow();
1743                                                let label = interner.get(value).unwrap();
1744                                                let global = interner.get(namespace).unwrap();
1745                                                format!("{global}{label}")
1746                                            };
1747                                            self.str_interner.borrow_mut().intern(direct_label)
1748                                        } else {
1749                                            let interner = self.str_interner.as_ref().borrow();
1750                                            let label = interner.get(value).unwrap();
1751                                            return asm_err!(loc, "The local label \"{label}\" is being evaluated but there was no global label defined before it");
1752                                        }
1753                                    }
1754                                };
1755
1756                                nodes.push(ExprNode::SizeOf(direct));
1757                                // Important to record where in expressions we reference
1758                                // symbols, so we can barf at link time
1759                                self.symtab.touch(direct, loc);
1760                                return Ok(loc);
1761                            }
1762
1763                            Some(tok) => {
1764                                return asm_err!(
1765                                    tok.loc(),
1766                                    "Unexpected {}, expected a struct field label",
1767                                    tok.as_display(&self.str_interner)
1768                                )
1769                            }
1770                        }
1771                    }
1772
1773                    _ => {
1774                        return asm_err!(
1775                            loc,
1776                            "\"{name}\" directives are not allowed in expressions"
1777                        )
1778                    }
1779                },
1780                Some(Token::Label { loc, kind, value }) => {
1781                    self.next()?;
1782                    let direct = match kind {
1783                        LabelKind::Global | LabelKind::Direct => value,
1784
1785                        LabelKind::Local => {
1786                            if let Some(namespace) = self.active_namespace {
1787                                let direct_label = {
1788                                    let interner = self.str_interner.as_ref().borrow();
1789                                    let label = interner.get(value).unwrap();
1790                                    let global = interner.get(namespace).unwrap();
1791                                    format!("{global}{label}")
1792                                };
1793                                self.str_interner.borrow_mut().intern(direct_label)
1794                            } else {
1795                                let interner = self.str_interner.as_ref().borrow();
1796                                let label = interner.get(value).unwrap();
1797                                return asm_err!(loc, "The local label \"{label}\" is being evaluated but there was no global label defined before it");
1798                            }
1799                        }
1800                    };
1801
1802                    if let Some(sym) = self.symtab.get(direct) {
1803                        match sym.inner() {
1804                            Symbol::Value(value) => {
1805                                nodes.push(ExprNode::Value(*value));
1806                            }
1807                            Symbol::Expr(expr) => {
1808                                if let Some(value) = expr.evaluate(&self.symtab, &self.str_interner)
1809                                {
1810                                    nodes.push(ExprNode::Value(value));
1811                                } else {
1812                                    nodes.push(ExprNode::Label(direct));
1813                                }
1814                            }
1815                        }
1816                    } else {
1817                        nodes.push(ExprNode::Label(direct));
1818                    }
1819                    // Important to record where in expressions we reference
1820                    // symbols, so we can barf at link time
1821                    self.symtab.touch(direct, loc);
1822                    return Ok(loc);
1823                }
1824                Some(tok) => {
1825                    return asm_err!(
1826                        tok.loc(),
1827                        "Unexpected {} in expression",
1828                        tok.as_display(&self.str_interner)
1829                    )
1830                }
1831            }
1832        }
1833    }
1834
1835    #[inline]
1836    pub(crate) fn peeked_symbol(
1837        &mut self,
1838        sym: SymbolName,
1839    ) -> Result<Option<Token<A>>, (SourceLoc, AssemblerError)> {
1840        match self.peek()? {
1841            Some(tok @ Token::Symbol { name, .. }) if name == sym => Ok(Some(tok)),
1842            _ => Ok(None),
1843        }
1844    }
1845
1846    fn parse_all(&mut self) -> Result<(), (SourceLoc, AssemblerError)> {
1847        loop {
1848            match self.peek()? {
1849                None => return Ok(()),
1850
1851                // Note: see `peek` for details why we want to check for these!
1852                Some(Token::NewLine { .. } | Token::Comment { .. }) => {
1853                    self.next()?;
1854                }
1855
1856                Some(Token::Label { loc, value, kind }) => {
1857                    let direct = match kind {
1858                        LabelKind::Global => {
1859                            self.active_namespace = Some(value);
1860                            value
1861                        }
1862
1863                        LabelKind::Direct => value,
1864
1865                        LabelKind::Local => {
1866                            if let Some(namespace) = self.active_namespace {
1867                                let direct_label = {
1868                                    let interner = self.str_interner.as_ref().borrow();
1869                                    let label = interner.get(value).unwrap();
1870                                    let global = interner.get(namespace).unwrap();
1871                                    format!("{global}{label}")
1872                                };
1873                                self.str_interner.borrow_mut().intern(direct_label)
1874                            } else {
1875                                let interner = self.str_interner.as_ref().borrow();
1876                                let label = interner.get(value).unwrap();
1877                                return asm_err!(loc, "The local label \"{label}\" is being defined but there was no global label defined before it");
1878                            }
1879                        }
1880                    };
1881
1882                    if self.symtab.get(direct).is_some() {
1883                        let interner = self.str_interner.as_ref().borrow();
1884                        let label = interner.get(direct).unwrap();
1885                        return asm_err!(loc, "The label \"{label}\" was already defined");
1886                    }
1887                    self.symtab.insert(direct, Symbol::Value(self.here as i32));
1888                    self.next()?;
1889
1890                    if self.peeked_symbol(SymbolName::Colon)?.is_some() {
1891                        self.next()?;
1892                    }
1893                }
1894
1895                Some(tok @ Token::Directive { loc, name }) => {
1896                    match name {
1897                        DirectiveName::Org => {
1898                            self.next()?;
1899
1900                            self.here = match self.const_expr()? {
1901                                (loc, Some(value)) => {
1902                                    if (value as u32) > (u16::MAX as u32) {
1903                                        return asm_err!(loc, "\"@org\" expression result ({value}) is not a valid address");
1904                                    }
1905                                    value as u32
1906                                },
1907                                (loc, None) => return asm_err!(loc, "The expression following an \"@org\" directive must be immediately solvable"),
1908                            };
1909                        }
1910
1911                        DirectiveName::Echo => {
1912                            self.next()?;
1913
1914                            match self.peek()? {
1915                                Some(Token::String { value, ..  }) => {
1916                                    self.next()?;
1917                                    let interner = self.str_interner.as_ref().borrow();
1918                                    let value = interner.get(value).unwrap();
1919                                    eprintln!("{value}");
1920                                }
1921
1922                                Some(_) => {
1923                                    match self.const_expr()? {
1924                                        (_, Some(value)) => {
1925                                            eprintln!("{value}");
1926                                        },
1927                                        (loc, None) => return asm_err!(loc, "An expression following an \"@echo\" directive must be immediately solvable"),
1928                                    }
1929                                }
1930
1931                                None => return self.end_of_input_err()
1932                            }
1933                        }
1934
1935                        DirectiveName::Die => {
1936                            self.next()?;
1937
1938                            match self.peek()? {
1939                                None => return self.end_of_input_err(),
1940
1941                                Some(Token::String { value, .. }) => {
1942                                    self.next()?;
1943                                    let interner = self.str_interner.as_ref().borrow();
1944                                    let value = interner.get(value).unwrap();
1945                                    return asm_err!(loc, "{value}");
1946                                }
1947
1948                                Some(_) => {
1949                                    match self.const_expr()? {
1950                                        (_, Some(value)) => return asm_err!(loc, "{value}"),
1951                                        (loc, None) => return asm_err!(loc, "An expression following an \"@die\" directive must be immediately solvable"),
1952                                    }
1953                                }
1954                            }
1955                        }
1956
1957                        DirectiveName::Assert => {
1958                            self.next()?;
1959
1960                            let (loc, expr) = self.expr()?;
1961                            let msg = if self.peeked_symbol(SymbolName::Comma)?.is_some() {
1962                                self.next()?;
1963                                match self.next()? {
1964                                    None => return self.end_of_input_err(),
1965                                    Some(Token::String { value, .. }) => Some(value),
1966                                    Some(tok) => {
1967                                        return asm_err!(
1968                                            tok.loc(),
1969                                            "Unexpected {}, expected a string",
1970                                            tok.as_display(&self.str_interner)
1971                                        );
1972                                    }
1973                                }
1974                            } else {
1975                                None
1976                            };
1977
1978                            if let Some(value) = expr.evaluate(&self.symtab, &self.str_interner) {
1979                                if value == 0 {
1980                                    if let Some(msg) = msg {
1981                                        let interner = self.str_interner.as_ref().borrow();
1982                                        let msg = interner.get(msg).unwrap();
1983                                        return asm_err!(loc, "Assertion failed: {msg}",);
1984                                    } else {
1985                                        return asm_err!(loc, "Assertion failed");
1986                                    }
1987                                }
1988                            } else {
1989                                self.links.push(Link::assert(loc, msg, expr));
1990                            }
1991                        }
1992
1993                        DirectiveName::Defl => {
1994                            self.next()?;
1995
1996                            let (direct, loc) = match self.peek()? {
1997                                None => return self.end_of_input_err(),
1998
1999                                Some(Token::Label { loc, value, kind }) => match kind {
2000                                    LabelKind::Global | LabelKind::Direct => (value, loc),
2001
2002                                    LabelKind::Local => {
2003                                        if let Some(namespace) = self.active_namespace {
2004                                            let global_label = {
2005                                                let interner = self.str_interner.as_ref().borrow();
2006                                                let global = interner.get(namespace).unwrap();
2007                                                let label = interner.get(value).unwrap();
2008                                                format!("{global}{label}")
2009                                            };
2010                                            (
2011                                                self.str_interner.borrow_mut().intern(global_label),
2012                                                loc,
2013                                            )
2014                                        } else {
2015                                            let interner = self.str_interner.as_ref().borrow();
2016                                            let label = interner.get(value).unwrap();
2017                                            return asm_err!(loc, "The local label \"{label}\" is being defined but there was no global label defined before it");
2018                                        }
2019                                    }
2020                                },
2021                                Some(tok) => {
2022                                    return asm_err!(tok.loc(), "A label name is required")
2023                                }
2024                            };
2025                            self.next()?;
2026
2027                            if self.symtab.get(direct).is_some() {
2028                                let interner = self.str_interner.as_ref().borrow();
2029                                let label = interner.get(direct).unwrap();
2030                                return asm_err!(loc, "The label \"{label}\" was already defined");
2031                            }
2032
2033                            self.expect_symbol(SymbolName::Comma)?;
2034                            let (_, expr) = self.expr()?;
2035                            self.symtab.insert(direct, Symbol::Expr(expr));
2036                        }
2037
2038                        DirectiveName::Defn => {
2039                            self.next()?;
2040
2041                            let (direct, loc) = match self.peek()? {
2042                                None => return self.end_of_input_err(),
2043
2044                                Some(Token::Label { loc, value, kind }) => match kind {
2045                                    LabelKind::Global | LabelKind::Direct => (value, loc),
2046
2047                                    LabelKind::Local => {
2048                                        if let Some(namespace) = self.active_namespace {
2049                                            let global_label = {
2050                                                let interner = self.str_interner.as_ref().borrow();
2051                                                let global = interner.get(namespace).unwrap();
2052                                                let label = interner.get(value).unwrap();
2053                                                format!("{global}{label}")
2054                                            };
2055                                            (
2056                                                self.str_interner.borrow_mut().intern(global_label),
2057                                                loc,
2058                                            )
2059                                        } else {
2060                                            let interner = self.str_interner.as_ref().borrow();
2061                                            let label = interner.get(value).unwrap();
2062                                            return asm_err!(loc, "The local constant \"{label}\" is being defined but there was no global label defined before it");
2063                                        }
2064                                    }
2065                                },
2066                                Some(tok) => {
2067                                    return asm_err!(tok.loc(), "A constant name is required")
2068                                }
2069                            };
2070                            self.next()?;
2071
2072                            if self.symtab.get(direct).is_some() {
2073                                let interner = self.str_interner.as_ref().borrow();
2074                                let label = interner.get(direct).unwrap();
2075                                return asm_err!(
2076                                    loc,
2077                                    "The constant \"{label}\" was already defined"
2078                                );
2079                            }
2080
2081                            self.expect_symbol(SymbolName::Comma)?;
2082                            let (_, expr) = self.expr()?;
2083                            self.symtab
2084                                .insert_with_meta(direct, Symbol::Expr(expr), &[]);
2085                        }
2086
2087                        DirectiveName::ReDefl => {
2088                            self.next()?;
2089
2090                            let direct = match self.next()? {
2091                                None => return self.end_of_input_err(),
2092
2093                                Some(Token::Label { loc, value, kind }) => match kind {
2094                                    LabelKind::Global | LabelKind::Direct => value,
2095
2096                                    LabelKind::Local => {
2097                                        if let Some(namespace) = self.active_namespace {
2098                                            let global_label = {
2099                                                let interner = self.str_interner.as_ref().borrow();
2100                                                let global = interner.get(namespace).unwrap();
2101                                                let label = interner.get(value).unwrap();
2102                                                format!("{global}{label}")
2103                                            };
2104                                            self.str_interner.borrow_mut().intern(global_label)
2105                                        } else {
2106                                            let interner = self.str_interner.as_ref().borrow();
2107                                            let label = interner.get(value).unwrap();
2108                                            return asm_err!(loc, "The local label \"{label}\" is being defined but there was no global label defined before it");
2109                                        }
2110                                    }
2111                                },
2112
2113                                Some(tok) => {
2114                                    return asm_err!(
2115                                        tok.loc(),
2116                                        "Unexpected {}, expected a label",
2117                                        tok.as_display(&self.str_interner)
2118                                    )
2119                                }
2120                            };
2121
2122                            self.expect_symbol(SymbolName::Comma)?;
2123                            let (_, expr) = self.expr()?;
2124                            self.symtab.insert(direct, Symbol::Expr(expr));
2125                        }
2126
2127                        DirectiveName::ReDefn => {
2128                            self.next()?;
2129
2130                            let direct = match self.next()? {
2131                                None => return self.end_of_input_err(),
2132
2133                                Some(Token::Label { loc, value, kind }) => match kind {
2134                                    LabelKind::Global | LabelKind::Direct => value,
2135
2136                                    LabelKind::Local => {
2137                                        if let Some(namespace) = self.active_namespace {
2138                                            let global_label = {
2139                                                let interner = self.str_interner.as_ref().borrow();
2140                                                let global = interner.get(namespace).unwrap();
2141                                                let label = interner.get(value).unwrap();
2142                                                format!("{global}{label}")
2143                                            };
2144                                            self.str_interner.borrow_mut().intern(global_label)
2145                                        } else {
2146                                            let interner = self.str_interner.as_ref().borrow();
2147                                            let label = interner.get(value).unwrap();
2148                                            return asm_err!(loc, "The local constant \"{label}\" is being defined but there was no global label defined before it");
2149                                        }
2150                                    }
2151                                },
2152
2153                                Some(tok) => {
2154                                    return asm_err!(
2155                                        tok.loc(),
2156                                        "Unexpected {}, expected a label",
2157                                        tok.as_display(&self.str_interner)
2158                                    )
2159                                }
2160                            };
2161
2162                            self.expect_symbol(SymbolName::Comma)?;
2163                            let (_, expr) = self.expr()?;
2164                            self.symtab
2165                                .insert_with_meta(direct, Symbol::Expr(expr), &[]);
2166                        }
2167
2168                        DirectiveName::UnDef => {
2169                            self.next()?;
2170
2171                            let direct = match self.next()? {
2172                                None => return self.end_of_input_err(),
2173
2174                                Some(Token::Label { loc, value, kind }) => match kind {
2175                                    LabelKind::Global | LabelKind::Direct => value,
2176
2177                                    LabelKind::Local => {
2178                                        if let Some(namespace) = self.active_namespace {
2179                                            let global_label = {
2180                                                let interner = self.str_interner.as_ref().borrow();
2181                                                let global = interner.get(namespace).unwrap();
2182                                                let label = interner.get(value).unwrap();
2183                                                format!("{global}{label}")
2184                                            };
2185                                            self.str_interner.borrow_mut().intern(global_label)
2186                                        } else {
2187                                            let interner = self.str_interner.as_ref().borrow();
2188                                            let label = interner.get(value).unwrap();
2189                                            return asm_err!(loc, "The local symbol \"{label}\" is being undefined but there was no global label defined before it");
2190                                        }
2191                                    }
2192                                },
2193
2194                                Some(tok) => {
2195                                    return asm_err!(
2196                                        tok.loc(),
2197                                        "Unexpected {}, expected a label",
2198                                        tok.as_display(&self.str_interner)
2199                                    )
2200                                }
2201                            };
2202                            self.symtab.remove(direct);
2203                        }
2204
2205                        DirectiveName::Db => {
2206                            self.next()?;
2207
2208                            match self.seg_mode {
2209                                SegmentMode::Addr => {
2210                                    if (self.here as usize) + 1 > (u16::MAX as usize) + 1 {
2211                                        return asm_err!(
2212                                            loc,
2213                                            "\"@db\" bytes extend past address $ffff"
2214                                        );
2215                                    }
2216                                    self.here += 1;
2217                                }
2218
2219                                SegmentMode::Code => loop {
2220                                    match self.peek()? {
2221                                        Some(Token::String { loc, value, .. }) => {
2222                                            self.next()?;
2223                                            let interner = self.str_interner.as_ref().borrow();
2224                                            let bytes = interner.get(value).unwrap().as_bytes();
2225
2226                                            if (self.here as usize) + bytes.len()
2227                                                > (u16::MAX as usize) + 1
2228                                            {
2229                                                return asm_err!(
2230                                                    loc,
2231                                                    "\"@db\" bytes extend past address $ffff"
2232                                                );
2233                                            }
2234                                            self.here += bytes.len() as u32;
2235                                            self.data.extend_from_slice(bytes);
2236                                        }
2237
2238                                        _ => {
2239                                            let (loc, expr) = self.expr()?;
2240                                            if let Some(value) =
2241                                                expr.evaluate(&self.symtab, &self.str_interner)
2242                                            {
2243                                                if (value as u32) > (u8::MAX as u32) {
2244                                                    return asm_err!(loc, "\"@db\" expression result ({value}) will not fit in a byte");
2245                                                }
2246                                                if (self.here as usize) + 1
2247                                                    > (u16::MAX as usize) + 1
2248                                                {
2249                                                    return asm_err!(
2250                                                        loc,
2251                                                        "\"@db\" bytes extend past address $ffff"
2252                                                    );
2253                                                }
2254                                                self.here += 1;
2255                                                self.data.push(value as u8);
2256                                            } else {
2257                                                self.here += 1;
2258                                                self.links.push(Link::byte(
2259                                                    loc,
2260                                                    self.data.len(),
2261                                                    expr,
2262                                                ));
2263                                                self.data.push(0);
2264                                            }
2265                                        }
2266                                    }
2267
2268                                    if self.peeked_symbol(SymbolName::Comma)?.is_some() {
2269                                        self.next()?;
2270                                        continue;
2271                                    }
2272                                    break;
2273                                },
2274                            }
2275                        }
2276
2277                        DirectiveName::Dw => {
2278                            self.next()?;
2279
2280                            match self.seg_mode {
2281                                SegmentMode::Addr => {
2282                                    if (self.here as usize) + 2 > (u16::MAX as usize) + 1 {
2283                                        return asm_err!(
2284                                            loc,
2285                                            "\"@dw\" bytes extend past address $ffff"
2286                                        );
2287                                    }
2288                                    self.here += 2;
2289                                }
2290
2291                                SegmentMode::Code => loop {
2292                                    self.peek()?;
2293                                    let (loc, expr) = self.expr()?;
2294                                    if let Some(value) =
2295                                        expr.evaluate(&self.symtab, &self.str_interner)
2296                                    {
2297                                        if (value as u32) > (u16::MAX as u32) {
2298                                            return asm_err!(
2299                                                loc,
2300                                                "\"@dw\" expression result ({value}) will not fit in a word"
2301                                            );
2302                                        }
2303                                        if (self.here as usize) + 2 > (u16::MAX as usize) + 1 {
2304                                            return asm_err!(
2305                                                loc,
2306                                                "\"@dw\" bytes extend past address $ffff"
2307                                            );
2308                                        }
2309                                        self.here += 2;
2310                                        self.data.extend_from_slice(&(value as u16).to_le_bytes());
2311                                    } else {
2312                                        self.here += 2;
2313                                        self.links.push(Link::word(loc, self.data.len(), expr));
2314                                        self.data.push(0);
2315                                        self.data.push(0);
2316                                    }
2317
2318                                    if self.peeked_symbol(SymbolName::Comma)?.is_some() {
2319                                        self.next()?;
2320                                        continue;
2321                                    }
2322                                    break;
2323                                },
2324                            }
2325                        }
2326
2327                        DirectiveName::Ds => {
2328                            self.next()?;
2329
2330                            let size = match self.const_expr()? {
2331                                (loc, None) => {
2332                                    return asm_err!(
2333                                        loc,
2334                                        "The size of a \"@ds\" directive must be immediately solvable"
2335                                    );
2336                                }
2337                                (loc, Some(size)) => {
2338                                    if (size as u32) > (u16::MAX as u32) {
2339                                        return asm_err!(
2340                                            loc,
2341                                            "\"@ds\" size expression result ({size}) will not fit in a word"
2342                                        );
2343                                    }
2344                                    if (self.here as usize) + (size as usize)
2345                                        > (u16::MAX as usize) + 1
2346                                    {
2347                                        return asm_err!(
2348                                            loc,
2349                                            "\"@ds\" size extends past address $ffff"
2350                                        );
2351                                    }
2352                                    self.here += size as u32;
2353                                    size as usize
2354                                }
2355                            };
2356
2357                            match self.seg_mode {
2358                                SegmentMode::Addr => {}
2359
2360                                SegmentMode::Code => {
2361                                    let value = if self.peeked_symbol(SymbolName::Comma)?.is_some()
2362                                    {
2363                                        self.next()?;
2364                                        let (loc, expr) = self.expr()?;
2365                                        if let Some(value) =
2366                                            expr.evaluate(&self.symtab, &self.str_interner)
2367                                        {
2368                                            if (value as u32) > (u8::MAX as u32) {
2369                                                return asm_err!(
2370                                            loc,
2371                                            "\"@ds\" value expression result ({value}) will not fit in a byte"
2372                                        );
2373                                            }
2374                                            value as u8
2375                                        } else {
2376                                            self.links.push(Link::space(
2377                                                loc,
2378                                                self.data.len(),
2379                                                size,
2380                                                expr,
2381                                            ));
2382                                            0
2383                                        }
2384                                    } else {
2385                                        0
2386                                    };
2387                                    self.data.extend(iter::repeat(value).take(size));
2388                                }
2389                            }
2390                        }
2391
2392                        DirectiveName::Include => {
2393                            self.next()?;
2394                            match self.next()? {
2395                                None => return self.end_of_input_err(),
2396                                Some(Token::String { loc, value }) => {
2397                                    let cwd = self
2398                                        .file_manager
2399                                        .path(self.cwd.unwrap())
2400                                        .unwrap()
2401                                        .to_path_buf();
2402                                    let interner = self.str_interner.as_ref().borrow();
2403                                    let path = interner.get(value).unwrap();
2404                                    let (pathref, reader) =
2405                                        match self.file_manager.reader(&cwd, path) {
2406                                            Ok(Some(tup)) => tup,
2407                                            Ok(None) => {
2408                                                return asm_err!(loc, "File not found: \"{path}\"");
2409                                            }
2410                                            Err(e) => {
2411                                                return asm_err!(
2412                                                    loc,
2413                                                    "Failed to open \"{path}\" for reading: {e}"
2414                                                );
2415                                            }
2416                                        };
2417
2418                                    // Push old path
2419                                    self.token_sources.push(self.token_source.take().unwrap());
2420                                    self.cwds.push(self.cwd.take().unwrap());
2421
2422                                    // Create new lexer and set cwd to file
2423                                    self.token_source = Some(TokenSource::Lexer(Lexer::new(
2424                                        self.str_interner.clone(),
2425                                        Some(loc),
2426                                        pathref,
2427                                        reader,
2428                                    )));
2429                                    let cwd = self
2430                                        .file_manager
2431                                        .path(pathref)
2432                                        .unwrap()
2433                                        .parent()
2434                                        .unwrap()
2435                                        .to_path_buf();
2436                                    self.cwd = Some(self.file_manager.intern(cwd, "."));
2437                                }
2438                                Some(tok) => {
2439                                    return asm_err!(
2440                                        tok.loc(),
2441                                        "Unexpected {}, expected file name string",
2442                                        tok.as_display(&self.str_interner)
2443                                    );
2444                                }
2445                            }
2446                        }
2447
2448                        DirectiveName::Segment => {
2449                            self.next()?;
2450                            match self.next()? {
2451                                None => return self.end_of_input_err(),
2452
2453                                Some(Token::String { loc, value }) => {
2454                                    let interner = self.str_interner.borrow_mut();
2455                                    if interner.eq_some("CODE", value)
2456                                        || interner.eq_some("code", value)
2457                                    {
2458                                        self.seg_mode = SegmentMode::Code
2459                                    } else if interner.eq_some("ADDR", value)
2460                                        || interner.eq_some("addr", value)
2461                                    {
2462                                        self.seg_mode = SegmentMode::Addr
2463                                    } else {
2464                                        let value = interner.get(value).unwrap();
2465                                        return asm_err!(
2466                                            loc,
2467                                            "Unrecognized segment name \"{value}\", only \"CODE\" or \"ADDR\" are valid segment names",
2468                                        );
2469                                    }
2470                                }
2471
2472                                Some(tok) => {
2473                                    return asm_err!(
2474                                        tok.loc(),
2475                                        "Unexpected {}, expected segment name string",
2476                                        tok.as_display(&self.str_interner)
2477                                    );
2478                                }
2479                            }
2480                        }
2481
2482                        DirectiveName::Incbin => {
2483                            if let SegmentMode::Addr = self.seg_mode {
2484                                return asm_err!(
2485                                    self.loc(),
2486                                    "Binary data cannot be included in an \"ADDR\" segment"
2487                                );
2488                            }
2489                            self.next()?;
2490                            match self.next()? {
2491                                None => return self.end_of_input_err(),
2492                                Some(Token::String { loc, value }) => {
2493                                    let cwd = self
2494                                        .file_manager
2495                                        .path(self.cwd.unwrap())
2496                                        .unwrap()
2497                                        .to_path_buf();
2498                                    let interner = self.str_interner.as_ref().borrow();
2499                                    let path = interner.get(value).unwrap();
2500                                    let (pathref, reader) =
2501                                        match self.file_manager.reader(&cwd, path) {
2502                                            Ok(Some(tup)) => tup,
2503                                            Ok(None) => {
2504                                                return asm_err!(loc, "File not found: \"{path}\"");
2505                                            }
2506                                            Err(e) => {
2507                                                return asm_err!(
2508                                                    loc,
2509                                                    "Failed to open \"{path}\" for reading: {e}"
2510                                                );
2511                                            }
2512                                        };
2513
2514                                    let path = self.file_manager.path(pathref).unwrap();
2515                                    for result in reader.bytes() {
2516                                        match result {
2517                                            Ok(b) => {
2518                                                if (self.here as usize) + 1
2519                                                    > (u16::MAX as usize) + 1
2520                                                {
2521                                                    return asm_err!(
2522                                                        loc,
2523                                                        "\"@incbin\" bytes extend past address $ffff"
2524                                                    );
2525                                                }
2526                                                self.here += 1;
2527                                                self.data.push(b);
2528                                            }
2529                                            Err(e) => {
2530                                                return asm_err!(
2531                                                    loc,
2532                                                    "Error reading \"{}\": {e}",
2533                                                    path.display()
2534                                                );
2535                                            }
2536                                        }
2537                                    }
2538                                }
2539                                Some(tok) => {
2540                                    return asm_err!(
2541                                        tok.loc(),
2542                                        "Unexpected {}, expected file name string",
2543                                        tok.as_display(&self.str_interner)
2544                                    );
2545                                }
2546                            }
2547                        }
2548
2549                        DirectiveName::Macro => {
2550                            self.next()?;
2551
2552                            let (value, loc) = match self.next()? {
2553                                None => return self.end_of_input_err(),
2554
2555                                Some(Token::Label {
2556                                    loc,
2557                                    kind: LabelKind::Global,
2558                                    value,
2559                                }) => (value, loc),
2560
2561                                Some(tok) => {
2562                                    return asm_err!(
2563                                        tok.loc(),
2564                                        "Unexpected {}, expected a macro name",
2565                                        tok.as_display(&self.str_interner)
2566                                    );
2567                                }
2568                            };
2569                            if self.macros.contains_key(&value) {
2570                                let interner = self.str_interner.as_ref().borrow();
2571                                let name = interner.get(value).unwrap();
2572                                return asm_err!(loc, "The macro \"{name}\" was already defined");
2573                            }
2574
2575                            self.expect_symbol(SymbolName::Comma)?;
2576
2577                            let args_count = match self.next()? {
2578                                None => return self.end_of_input_err(),
2579                                Some(Token::Number { value, .. }) => value as usize,
2580                                Some(tok) => {
2581                                    return asm_err!(
2582                                        tok.loc(),
2583                                        "Unexpected {}, expected number of macro arguments",
2584                                        tok.as_display(&self.str_interner)
2585                                    );
2586                                }
2587                            };
2588
2589                            let mut args = Vec::new();
2590                            for _ in 0..args_count {
2591                                self.expect_symbol(SymbolName::Comma)?;
2592
2593                                match self.next()? {
2594                                    None => return self.end_of_input_err(),
2595
2596                                    Some(Token::Label { loc, kind, value }) => {
2597                                        let interner = self.str_interner.as_ref().borrow();
2598                                        let str_value = interner.get(value).unwrap();
2599                                        if kind != LabelKind::Global {
2600                                            return asm_err!(
2601                                                loc,
2602                                                "\"@macro\" argument name \"{str_value}\" must be a global label"
2603                                            );
2604                                        }
2605                                        args.push(value);
2606                                    }
2607
2608                                    Some(tok) => {
2609                                        return asm_err!(
2610                                            tok.loc(),
2611                                            "Unexpected {}, expected a macro argument name",
2612                                            tok.as_display(&self.str_interner)
2613                                        );
2614                                    }
2615                                };
2616                            }
2617
2618                            self.active_macro = Some(value);
2619                            let mut toks = Vec::new();
2620                            let mut macro_depth = 0;
2621                            loop {
2622                                match self.next()? {
2623                                    None => return self.end_of_input_err(),
2624                                    Some(Token::Comment { .. } | Token::NewLine { .. }) => {}
2625
2626                                    Some(
2627                                        tok @ Token::Directive {
2628                                            name: DirectiveName::Macro,
2629                                            ..
2630                                        },
2631                                    ) => {
2632                                        macro_depth += 1;
2633                                        toks.push(MacroToken::Token(tok));
2634                                    }
2635
2636                                    Some(
2637                                        tok @ Token::Directive {
2638                                            name: DirectiveName::EndMacro,
2639                                            ..
2640                                        },
2641                                    ) => {
2642                                        if macro_depth == 0 {
2643                                            self.active_macro = None;
2644                                            break;
2645                                        }
2646                                        macro_depth -= 1;
2647                                        toks.push(MacroToken::Token(tok));
2648                                    }
2649
2650                                    Some(Token::Directive {
2651                                        loc,
2652                                        name: DirectiveName::Entropy,
2653                                    }) => {
2654                                        toks.push(MacroToken::Entropy { loc });
2655                                    }
2656
2657                                    Some(Token::Label { kind, value, .. })
2658                                        if kind == LabelKind::Global && args.contains(&value) =>
2659                                    {
2660                                        toks.push(MacroToken::Argument {
2661                                            index: args
2662                                                .iter()
2663                                                .position(|arg| arg == &value)
2664                                                .unwrap(),
2665                                        })
2666                                    }
2667
2668                                    Some(tok) => {
2669                                        toks.push(MacroToken::Token(tok));
2670                                    }
2671                                }
2672                            }
2673
2674                            self.macros.insert(value, Macro { args, tokens: toks });
2675                        }
2676
2677                        DirectiveName::Struct => {
2678                            self.next()?;
2679
2680                            let (value, loc) = match self.next()? {
2681                                None => return self.end_of_input_err(),
2682                                Some(Token::Label {
2683                                    loc,
2684                                    kind: LabelKind::Global,
2685                                    value,
2686                                }) => (value, loc),
2687                                Some(tok) => {
2688                                    return asm_err!(
2689                                        tok.loc(),
2690                                        "Unexpected {}, expected struct name",
2691                                        tok.as_display(&self.str_interner)
2692                                    );
2693                                }
2694                            };
2695
2696                            let old_namespace = self.active_namespace;
2697                            if self.symtab.get(value).is_some() {
2698                                let interner = self.str_interner.as_ref().borrow();
2699                                let label = interner.get(value).unwrap();
2700                                return asm_err!(loc, "The label \"{label}\" was already defined");
2701                            }
2702                            self.active_namespace = Some(value);
2703                            let mut struct_size = 0i32;
2704                            loop {
2705                                match self.next()? {
2706                                    None => return self.end_of_input_err(),
2707                                    Some(Token::NewLine { .. } | Token::Comment { .. }) => {}
2708                                    Some(Token::Directive {
2709                                        name: DirectiveName::Ds,
2710                                        ..
2711                                    }) => match self.peek()? {
2712                                        None => return self.end_of_input_err(),
2713                                        Some(_) => match self.const_expr()? {
2714                                            (loc, None) => {
2715                                                return asm_err!(
2716                                                    loc,
2717                                                    "Padding size must be immediately solvable",
2718                                                );
2719                                            }
2720                                            (_, Some(pad_size)) => {
2721                                                struct_size = struct_size.wrapping_add(pad_size);
2722                                            }
2723                                        },
2724                                    },
2725                                    Some(Token::Directive {
2726                                        name: DirectiveName::Align,
2727                                        ..
2728                                    }) => match self.peek()? {
2729                                        None => return self.end_of_input_err(),
2730                                        Some(_) => match self.const_expr()? {
2731                                            (loc, None) => {
2732                                                return asm_err!(
2733                                                    loc,
2734                                                    "Alignment must be immediately solvable",
2735                                                );
2736                                            }
2737                                            (_, Some(alignment)) => {
2738                                                if alignment < 2 {
2739                                                    return asm_err!(
2740                                                                loc,
2741                                                                "Alignment value ({alignment}) must be greater than 1",
2742                                                            );
2743                                                }
2744                                                let padding = (alignment
2745                                                    - (struct_size % alignment))
2746                                                    % alignment;
2747                                                struct_size = struct_size.wrapping_add(padding);
2748                                            }
2749                                        },
2750                                    },
2751                                    Some(Token::Directive {
2752                                        name: DirectiveName::EndStruct,
2753                                        ..
2754                                    }) => break,
2755                                    Some(Token::Label {
2756                                        loc,
2757                                        kind: LabelKind::Global,
2758                                        value: field,
2759                                    }) => {
2760                                        let direct_label = {
2761                                            let interner = self.str_interner.as_ref().borrow();
2762                                            let global = interner.get(value).unwrap();
2763                                            let label = interner.get(field).unwrap();
2764                                            format!("{global}.{label}")
2765                                        };
2766                                        let direct =
2767                                            self.str_interner.borrow_mut().intern(&direct_label);
2768                                        if self.symtab.get(direct).is_some() {
2769                                            return asm_err!(
2770                                                loc,
2771                                                "The field \"{direct_label}\" was already defined",
2772                                            );
2773                                        }
2774
2775                                        // optional colon
2776                                        if let Some(Token::Symbol {
2777                                            name: SymbolName::Colon,
2778                                            ..
2779                                        }) = self.peek()?
2780                                        {
2781                                            self.next()?;
2782                                        }
2783
2784                                        match self.peek()? {
2785                                            None => return self.end_of_input_err(),
2786                                            Some(Token::Directive {
2787                                                name: DirectiveName::Db,
2788                                                ..
2789                                            }) => {
2790                                                self.next()?;
2791                                                let mut interner = self.str_interner.borrow_mut();
2792                                                let key = interner.intern("@SIZEOF");
2793                                                let value = interner.intern(format!("1"));
2794                                                self.symtab.insert_with_meta(
2795                                                    direct,
2796                                                    Symbol::Value(struct_size),
2797                                                    &[[key, value]],
2798                                                );
2799                                                struct_size = struct_size.wrapping_add(1);
2800                                            }
2801                                            Some(Token::Directive {
2802                                                name: DirectiveName::Dw,
2803                                                ..
2804                                            }) => {
2805                                                self.next()?;
2806                                                let mut interner = self.str_interner.borrow_mut();
2807                                                let key = interner.intern("@SIZEOF");
2808                                                let value = interner.intern(format!("2"));
2809                                                self.symtab.insert_with_meta(
2810                                                    direct,
2811                                                    Symbol::Value(struct_size),
2812                                                    &[[key, value]],
2813                                                );
2814                                                struct_size = struct_size.wrapping_add(2);
2815                                            }
2816                                            Some(_) => match self.const_expr()? {
2817                                                (loc, None) => {
2818                                                    return asm_err!(
2819                                                                loc,
2820                                                                "Field \"{direct_label}\"'s size must be immediately solvable",
2821                                                            );
2822                                                }
2823                                                (_, Some(field_size)) => {
2824                                                    let mut interner =
2825                                                        self.str_interner.borrow_mut();
2826                                                    let key = interner.intern("@SIZEOF");
2827                                                    let value =
2828                                                        interner.intern(format!("{field_size}"));
2829                                                    self.symtab.insert_with_meta(
2830                                                        direct,
2831                                                        Symbol::Value(struct_size),
2832                                                        &[[key, value]],
2833                                                    );
2834                                                    struct_size =
2835                                                        struct_size.wrapping_add(field_size);
2836                                                }
2837                                            },
2838                                        }
2839                                    }
2840                                    Some(tok) => {
2841                                        return asm_err!(
2842                                            tok.loc(),
2843                                            "Unexpected {}, expected field name or \"@endstruct\"",
2844                                            tok.as_display(&self.str_interner)
2845                                        );
2846                                    }
2847                                }
2848                            }
2849                            self.active_namespace = old_namespace;
2850                            self.symtab
2851                                .insert_with_meta(value, Symbol::Value(struct_size), &[]);
2852                        }
2853
2854                        DirectiveName::Align => {
2855                            self.next()?;
2856                            match self.peek()? {
2857                                None => return self.end_of_input_err(),
2858                                Some(_) => match self.const_expr()? {
2859                                    (loc, None) => {
2860                                        return asm_err!(
2861                                            loc,
2862                                            "Alignment must be immediately solvable"
2863                                        );
2864                                    }
2865                                    (loc, Some(alignment)) => {
2866                                        if alignment < 2 {
2867                                            return asm_err!(
2868                                                loc,
2869                                                "Alignment value ({alignment}) must be greater than 1",
2870                                            );
2871                                        }
2872                                        let alignment = alignment as u32;
2873                                        let padding =
2874                                            (alignment - (self.here % alignment)) % alignment;
2875                                        if padding > (u16::MAX as u32) {
2876                                            return asm_err!(
2877                                                loc,
2878                                                "Alignment padding ({padding}) will not fit in a word"
2879                                            );
2880                                        }
2881                                        if (self.here as usize) + (padding as usize)
2882                                            > (u16::MAX as usize) + 1
2883                                        {
2884                                            return asm_err!(
2885                                                loc,
2886                                                "Alignment padding extends past address $ffff"
2887                                            );
2888                                        }
2889                                        self.here += padding;
2890                                        self.data.extend(iter::repeat(0).take(padding as usize));
2891                                    }
2892                                },
2893                            }
2894                        }
2895
2896                        DirectiveName::Meta => {
2897                            self.next()?;
2898
2899                            let mut pairs = Vec::new();
2900                            loop {
2901                                match self.next()? {
2902                                    None => return self.end_of_input_err(),
2903
2904                                    Some(Token::String { value: key, .. }) => match self.next()? {
2905                                        None => return self.end_of_input_err(),
2906
2907                                        Some(Token::String { value, .. }) => {
2908                                            pairs.push([key, value]);
2909                                        }
2910
2911                                        Some(tok) => {
2912                                            return asm_err!(
2913                                                tok.loc(),
2914                                                "Unexpected {}, expected a metadata value",
2915                                                tok.as_display(&self.str_interner)
2916                                            );
2917                                        }
2918                                    },
2919
2920                                    Some(tok) => {
2921                                        return asm_err!(
2922                                            tok.loc(),
2923                                            "Unexpected {}, expected a metadata key",
2924                                            tok.as_display(&self.str_interner)
2925                                        );
2926                                    }
2927                                }
2928
2929                                if self.peeked_symbol(SymbolName::Comma)?.is_none() {
2930                                    break;
2931                                }
2932                                self.next()?;
2933                            }
2934                            self.symtab.set_meta(pairs);
2935                        }
2936
2937                        DirectiveName::EndMeta => {
2938                            self.next()?;
2939                            self.symtab.set_meta(&[]);
2940                        }
2941
2942                        DirectiveName::If => {
2943                            self.next()?;
2944
2945                            let result = match self.const_expr()? {
2946                                (_, Some(value)) => value,
2947                                (loc, None) => {
2948                                    return asm_err!(
2949                                        loc,
2950                                        "The expression following an \"@if\" directive must be immediately solvable"
2951                                    )
2952                                }
2953                            };
2954
2955                            if result != 0 {
2956                                self.if_level += 1;
2957                            } else {
2958                                let mut if_level = 1;
2959                                loop {
2960                                    match self.next()? {
2961                                        None => return self.end_of_input_err(),
2962
2963                                        Some(Token::Directive {
2964                                            name: DirectiveName::If,
2965                                            ..
2966                                        }) => {
2967                                            if_level += 1;
2968                                        }
2969
2970                                        Some(Token::Directive {
2971                                            name: DirectiveName::EndIf,
2972                                            ..
2973                                        }) => {
2974                                            if_level -= 1;
2975                                            if if_level == 0 {
2976                                                break;
2977                                            }
2978                                        }
2979
2980                                        Some(_) => {}
2981                                    }
2982                                }
2983                            }
2984                        }
2985
2986                        DirectiveName::EndIf => {
2987                            self.next()?;
2988                            if self.if_level == 0 {
2989                                return asm_err!(tok.loc(), "Unexpected \"@endif\"");
2990                            }
2991                            self.if_level -= 1;
2992                        }
2993
2994                        _ => {
2995                            return asm_err!(
2996                                tok.loc(),
2997                                "Unexpected {}",
2998                                tok.as_display(&self.str_interner)
2999                            );
3000                        }
3001                    }
3002                }
3003
3004                Some(Token::Operation { name, .. }) => {
3005                    if let SegmentMode::Addr = self.seg_mode {
3006                        return asm_err!(
3007                            self.loc(),
3008                            "Cannot place instructions in an \"ADDR\" segment",
3009                        );
3010                    }
3011
3012                    let old_len = self.data.len();
3013                    <Z as ArchAssembler<S, R, A>>::parse(self, name)?;
3014                    self.here += (self.data.len() - old_len) as u32;
3015                }
3016
3017                Some(tok) => {
3018                    return asm_err!(
3019                        tok.loc(),
3020                        "Unexpected {}",
3021                        tok.as_display(&self.str_interner)
3022                    )
3023                }
3024            }
3025        }
3026    }
3027}