1use std::collections::BTreeMap;
3use std::collections::HashSet;
4use std::fmt::{self, Debug, Display, Formatter};
5
6use base::prelude::*;
7
8use super::ast::{EqualityValue, Origin};
9use super::collections::OneOrMore;
10use super::eval::EvaluationFailure;
11use super::memorymap::{RcAllocator, RcWordAllocationFailure, RcWordKind, RcWordSource};
12use super::source::Source;
13use super::span::{Span, Spanned};
14use super::symbol::{InconsistentSymbolUse, SymbolContext, SymbolName};
15use super::types::{AssemblerFailure, BlockIdentifier, ProgramError};
16
17#[derive(Debug, Default, PartialEq, Eq)]
18pub(crate) struct IndexRegisterAssigner {
19 index_registers_used: Unsigned6Bit,
20}
21
22impl IndexRegisterAssigner {
23 pub(crate) fn assign_index_register(&mut self) -> Option<Unsigned6Bit> {
24 if let Some(n) = self.index_registers_used.checked_add(u6!(1)) {
28 self.index_registers_used = n;
29 Some(n)
30 } else {
31 None
32 }
33 }
34
35 pub(crate) fn is_empty(&self) -> bool {
36 self.index_registers_used == 0
37 }
38}
39
40#[derive(Debug, Default, Clone, PartialEq, Eq)]
48pub(crate) struct ImplicitSymbolTable {
49 definitions: BTreeMap<SymbolName, ImplicitDefinition>,
50}
51
52impl ImplicitSymbolTable {
53 pub(super) fn symbols(&self) -> impl Iterator<Item = &SymbolName> {
54 self.definitions.keys()
55 }
56
57 pub(crate) fn get(&self, name: &SymbolName) -> Option<&ImplicitDefinition> {
58 self.definitions.get(name)
59 }
60
61 pub(super) fn get_mut(&mut self, name: &SymbolName) -> Option<&mut ImplicitDefinition> {
62 self.definitions.get_mut(name)
63 }
64
65 pub(crate) fn remove(&mut self, name: &SymbolName) -> Option<ImplicitDefinition> {
66 self.definitions.remove(name)
67 }
68
69 pub(crate) fn record_usage_context(
70 &mut self,
71 name: &SymbolName,
72 context: &SymbolContext,
73 ) -> Result<(), InconsistentSymbolUse> {
74 self.definitions
75 .entry(name.clone())
76 .or_insert_with(|| ImplicitDefinition::Undefined(context.clone()))
77 .merge_context(name, context.clone())
78 }
79
80 pub(super) fn record_deduced_origin_value(
81 &mut self,
82 name: &SymbolName,
83 value: Address,
84 block_id: BlockIdentifier,
85 span: Span,
86 ) -> Result<(), InconsistentSymbolUse> {
87 let context = SymbolContext::origin(block_id, Origin::Deduced(span, name.clone(), value));
88 self.definitions
89 .entry(name.clone())
90 .or_insert_with(|| ImplicitDefinition::DefaultAssigned(value.into(), context.clone()))
91 .merge_context(name, context)
92 }
93
94 #[cfg(test)]
95 pub(super) fn load_test_definitions<
96 I: IntoIterator<Item = (SymbolName, ImplicitDefinition)>,
97 >(
98 &mut self,
99 defs: I,
100 ) {
101 for (name, definition) in defs {
102 self.definitions.insert(name, definition);
103 }
104 }
105}
106
107#[derive(Debug, Default, Clone, PartialEq, Eq)]
108pub(crate) struct ExplicitSymbolTable {
109 definitions: BTreeMap<SymbolName, ExplicitDefinition>,
110}
111
112#[derive(Debug, Default)]
113pub(crate) struct LookupOperation {
114 pub(super) depends_on: HashSet<SymbolName>,
115 pub(super) deps_in_order: Vec<SymbolName>,
116}
117
118impl Spanned for (&Span, &SymbolName, &ExplicitDefinition) {
120 fn span(&self) -> Span {
121 let r1: &Span = self.0;
122 let r2: Span = self.2.span();
123 assert_eq!(r1, &r2);
124 r2
125 }
126}
127
128impl ExplicitSymbolTable {
129 pub(crate) fn new() -> ExplicitSymbolTable {
130 ExplicitSymbolTable {
131 definitions: Default::default(),
132 }
133 }
134
135 pub(crate) fn get(&self, name: &SymbolName) -> Option<&ExplicitDefinition> {
136 self.definitions.get(name)
137 }
138
139 pub(crate) fn is_defined(&self, name: &SymbolName) -> bool {
140 self.definitions.contains_key(name)
141 }
142
143 pub(crate) fn define(
144 &mut self,
145 name: SymbolName,
146 new_definition: ExplicitDefinition,
147 ) -> Result<(), BadSymbolDefinition> {
148 if let Some(existing) = self.definitions.get_mut(&name) {
149 existing.override_with(name, new_definition)
150 } else {
151 self.definitions.insert(name, new_definition);
152 Ok(())
153 }
154 }
155 pub(crate) fn merge(
156 &mut self,
157 other: ExplicitSymbolTable,
158 ) -> Result<(), OneOrMore<BadSymbolDefinition>> {
159 let mut errors: Vec<BadSymbolDefinition> = Vec::new();
160 for (name, def) in other.definitions {
161 if let Err(e) = self.define(name, def) {
162 errors.push(e);
163 }
164 }
165 match OneOrMore::try_from_vec(errors) {
166 Ok(errors) => Err(errors),
167 Err(_) => Ok(()), }
169 }
170}
171
172#[derive(Debug, PartialEq, Eq)]
173pub(crate) enum FinalSymbolType {
174 Tag,
175 Equality,
176 Default,
177}
178
179#[derive(Debug)]
180pub(crate) enum FinalSymbolDefinition {
181 PositionIndependent(Unsigned36Bit),
182 PositionDependent,
183}
184
185#[derive(Debug, Default)]
186pub(crate) struct FinalSymbolTable {
187 definitions: BTreeMap<SymbolName, (FinalSymbolType, String, FinalSymbolDefinition)>,
188}
189
190impl FinalSymbolTable {
191 pub(crate) fn define(
192 &mut self,
193 name: SymbolName,
194 sym_type: FinalSymbolType,
195 rep: String,
196 def: FinalSymbolDefinition,
197 ) {
198 self.definitions.insert(name, (sym_type, rep, def));
199 }
200
201 pub(crate) fn define_if_undefined(
202 &mut self,
203 name: SymbolName,
204 sym_type: FinalSymbolType,
205 rep: String,
206 def: FinalSymbolDefinition,
207 ) {
208 self.definitions.entry(name).or_insert((sym_type, rep, def));
209 }
210}
211
212impl Display for FinalSymbolTable {
213 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
214 let show = |f: &mut std::fmt::Formatter<'_>,
215 sym_type_wanted: FinalSymbolType,
216 title: &str|
217 -> std::fmt::Result {
218 writeln!(f)?;
219 writeln!(f, "** {title}")?;
220 for (name, (_final_symbol_type, representation, definition)) in self
221 .definitions
222 .iter()
223 .filter(|(_, (symtype, _, _))| symtype == &sym_type_wanted)
224 {
225 match definition {
226 FinalSymbolDefinition::PositionIndependent(word) => {
227 writeln!(f, "{name:20} = {word:012} ** {representation:>20}")?;
228 }
229 FinalSymbolDefinition::PositionDependent => {
230 writeln!(f, "{name:20} = {representation}")?;
231 }
232 }
233 }
234 Ok(())
235 };
236
237 show(f, FinalSymbolType::Tag, "Tags")?;
238 show(f, FinalSymbolType::Equality, "Equalities")?;
239 show(f, FinalSymbolType::Default, "Default-assigned values")?;
240 Ok(())
241 }
242}
243
244#[derive(Debug, PartialEq, Eq, Clone)]
245pub(crate) enum TagDefinition {
246 Unresolved {
247 block_id: BlockIdentifier,
248 block_offset: Unsigned18Bit,
249 span: Span,
250 },
251 Resolved {
252 address: Address,
253 span: Span,
254 },
255}
256
257impl Spanned for TagDefinition {
258 fn span(&self) -> Span {
259 match self {
260 TagDefinition::Unresolved { span, .. } | TagDefinition::Resolved { span, .. } => *span,
261 }
262 }
263}
264
265impl Display for TagDefinition {
266 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
267 match self {
268 TagDefinition::Unresolved {
269 block_id,
270 block_offset,
271 span: _,
272 } => {
273 write!(
274 f,
275 "tag at offset {block_offset} in {block_id} with unspecified address"
276 )
277 }
278 TagDefinition::Resolved { address, span: _ } => {
279 write!(f, "tag with address {address:06o}")
280 }
281 }
282 }
283}
284
285#[derive(Debug, PartialEq, Eq, Clone)]
286pub(crate) enum ExplicitDefinition {
287 Tag(TagDefinition),
288 Equality(EqualityValue),
289 Origin(Origin, BlockIdentifier),
290}
291
292impl Spanned for ExplicitDefinition {
293 fn span(&self) -> Span {
294 match self {
295 ExplicitDefinition::Tag(tag_definition) => tag_definition.span(),
296 ExplicitDefinition::Equality(equality_value) => equality_value.span(),
297 ExplicitDefinition::Origin(origin, _block_identifier) => origin.span(),
298 }
299 }
300}
301
302impl Display for ExplicitDefinition {
303 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
304 match self {
305 ExplicitDefinition::Origin(origin, _block_identifier) => {
306 write!(f, "{origin}")
307 }
308 ExplicitDefinition::Tag(tagdef) => {
309 write!(f, "{tagdef}")
310 }
311 ExplicitDefinition::Equality(inst) => {
312 write!(f, "assignment with value {inst:#?}")
314 }
315 }
316 }
317}
318
319impl ExplicitDefinition {
320 pub(crate) fn override_with(
321 &mut self,
322 name: SymbolName,
323 update: ExplicitDefinition,
324 ) -> Result<(), BadSymbolDefinition> {
325 match (self, update) {
326 (current @ ExplicitDefinition::Equality(_), new @ ExplicitDefinition::Equality(_)) => {
327 *current = new;
329 Ok(())
330 }
331 (current, new) => {
332 if current == &new {
333 Ok(()) } else {
335 Err(BadSymbolDefinition {
336 symbol_name: name,
337 span: new.span(),
338 existing: Box::new(current.clone()),
339 proposed: Box::new(new),
340 })
341 }
342 }
343 }
344 }
345}
346
347#[derive(Debug, PartialEq, Eq, Clone)]
348pub(crate) enum ImplicitDefinition {
349 Undefined(SymbolContext),
350 DefaultAssigned(Unsigned36Bit, SymbolContext),
351}
352
353impl ImplicitDefinition {
354 pub(crate) fn context(&self) -> &SymbolContext {
355 match self {
356 ImplicitDefinition::Undefined(context)
357 | ImplicitDefinition::DefaultAssigned(_, context) => context,
358 }
359 }
360}
361
362impl Display for ImplicitDefinition {
363 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
364 match self {
365 ImplicitDefinition::Undefined(_context) => f.write_str("undefined"),
366 ImplicitDefinition::DefaultAssigned(value, _) => {
367 write!(f, "default-assigned as {value}")
368 }
369 }
370 }
371}
372
373#[derive(Debug, PartialEq, Eq, Clone)]
374pub(crate) struct BadSymbolDefinition {
375 pub(crate) symbol_name: SymbolName,
378 pub(crate) span: Span,
379 pub(crate) existing: Box<ExplicitDefinition>,
385 pub(crate) proposed: Box<ExplicitDefinition>,
386}
387
388impl Spanned for BadSymbolDefinition {
389 fn span(&self) -> Span {
390 self.span
391 }
392}
393
394impl Display for BadSymbolDefinition {
395 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
396 match (&*self.existing, &*self.proposed) {
397 (ExplicitDefinition::Tag(td1), ExplicitDefinition::Tag(td2)) => {
398 write!(
399 f,
400 "{0} is defined more than once, but this is not allowed for tags (tag defitions are {1} and {2})",
401 &self.symbol_name, td1, td2
402 )
403 }
404 _ => {
405 write!(
406 f,
407 "it is not allowed to override the symbol definition of {0} as {1} with a new definition {2}",
408 &self.symbol_name, &self.existing, &self.proposed
409 )
410 }
411 }
412 }
413}
414
415impl std::error::Error for BadSymbolDefinition {}
416
417impl ImplicitDefinition {
418 pub(crate) fn merge_context(
419 &mut self,
420 name: &SymbolName,
421 context: SymbolContext,
422 ) -> Result<(), InconsistentSymbolUse> {
423 match self {
424 ImplicitDefinition::Undefined(current) => current.merge(name, context),
425 ImplicitDefinition::DefaultAssigned(value, existing_context) => {
426 if &context == existing_context {
427 Ok(())
428 } else {
429 panic!(
430 "attempting to change the recorded usage context for {name} after a default value {value:?} has been assigned; previous context was {existing_context:?}, new context is {context:?}"
431 );
432 }
433 }
434 }
435 }
436}
437
438pub(super) fn assign_default_rc_word_tags<R: RcAllocator>(
439 implicit_symtab: &mut ImplicitSymbolTable,
440 rcblock: &mut R,
441 final_symbols: &mut FinalSymbolTable,
442) -> Result<(), RcWordAllocationFailure> {
443 for (name, def) in &mut implicit_symtab.definitions {
444 if let ImplicitDefinition::Undefined(context) = def
445 && context.requires_rc_word_allocation()
446 {
447 let span: Span = *context.any_span();
448 let value = Unsigned36Bit::ZERO;
449 let addr = rcblock.allocate(
450 RcWordSource {
451 span,
452 kind: RcWordKind::DefaultAssignment,
453 },
454 value,
455 )?;
456 final_symbols.define(
457 name.clone(),
458 FinalSymbolType::Equality,
459 value.to_string(),
460 FinalSymbolDefinition::PositionIndependent(value),
461 );
462 *def = ImplicitDefinition::DefaultAssigned(addr.into(), context.clone());
463 }
464 }
465 Ok(())
466}
467
468pub(super) fn record_undefined_symbol_or_return_failure(
469 source_file_body: &Source<'_>,
470 e: EvaluationFailure,
471 undefined_symbols: &mut BTreeMap<SymbolName, ProgramError>,
472) -> Result<(), AssemblerFailure> {
473 match e {
474 EvaluationFailure::SymbolDefinitionLoop {
475 span,
476 deps_in_order,
477 ..
478 } => {
479 undefined_symbols
480 .entry(deps_in_order.first().clone())
481 .or_insert_with(|| ProgramError::SymbolDefinitionLoop {
482 symbol_names: deps_in_order,
483 span,
484 });
485 Ok(())
486 }
487 other => Err(other
488 .into_program_error()
489 .into_assembler_failure(source_file_body)),
490 }
491}