Skip to content

Commit 0ef02f4

Browse files
committed
[assembler] Compute block origins with evaluate().
This allows us to delete some code which is specific to evaluating origins.
1 parent f8783ce commit 0ef02f4

File tree

7 files changed

+348
-390
lines changed

7 files changed

+348
-390
lines changed

assembler/src/asmlib/ast.rs

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1400,13 +1400,6 @@ impl Directive {
14001400
}
14011401
}
14021402

1403-
#[derive(Debug, Clone, PartialEq, Eq)]
1404-
pub(crate) struct Block {
1405-
pub(crate) origin: Option<Origin>,
1406-
pub(crate) location: Option<Address>,
1407-
pub(crate) statements: InstructionSequence,
1408-
}
1409-
14101403
#[derive(Debug, Clone, PartialEq, Eq)]
14111404
pub(crate) struct LocatedBlock {
14121405
pub(crate) location: Address,

assembler/src/asmlib/driver.rs

Lines changed: 42 additions & 146 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ mod output;
33
#[cfg(test)]
44
mod tests;
55

6-
use std::cmp::max;
76
use std::collections::BTreeMap;
87
use std::ffi::OsStr;
98
use std::fs::OpenOptions;
@@ -15,19 +14,21 @@ use tracing::{event, span, Level};
1514

1615
use super::ast::*;
1716
use super::eval::extract_final_equalities;
17+
use super::eval::Evaluate;
18+
use super::eval::HereValue;
1819
use super::eval::RcBlock;
1920
use super::lexer;
2021
use super::listing::*;
2122
use super::parser::parse_source_file;
2223
use super::span::*;
2324
use super::state::{NumeralMode, State};
24-
use super::symbol::SymbolName;
2525
use super::symtab::{
26-
assign_default_rc_word_tags, BadSymbolDefinition, FinalSymbolDefinition, FinalSymbolTable,
27-
FinalSymbolType, LookupOperation, SymbolDefinition, SymbolTable,
26+
assign_default_rc_word_tags, BadSymbolDefinition, BlockPosition, FinalSymbolDefinition,
27+
FinalSymbolTable, FinalSymbolType, LookupOperation, SymbolTable,
2828
};
2929
use super::types::*;
3030
use base::prelude::{Address, IndexBy, Unsigned18Bit, Unsigned36Bit};
31+
use base::subword;
3132
pub use output::write_user_program;
3233

3334
#[cfg(test)]
@@ -64,141 +65,57 @@ impl SourceFile {
6465
source_file_body: &str,
6566
symtab: &mut SymbolTable,
6667
) -> Result<Directive, AssemblerFailure> {
67-
type MemoryMap = BTreeMap<BlockIdentifier, (Option<Origin>, LocatedBlock)>;
68-
69-
fn assign_block_positions(
70-
source_file_body: &str,
71-
blocks: BTreeMap<BlockIdentifier, Block>,
72-
symtab: &mut SymbolTable,
73-
) -> Result<MemoryMap, AssemblerFailure> {
74-
let mut no_rc_block = NoRcBlock {};
75-
let mut memory_map: BTreeMap<BlockIdentifier, (Option<Origin>, LocatedBlock)> =
76-
BTreeMap::new();
77-
78-
for (block_id, directive_block) in blocks.into_iter() {
79-
let mut op = LookupOperation::default();
80-
let address: Address =
81-
match symtab.finalise_origin(block_id, &mut no_rc_block, Some(&mut op)) {
82-
Ok(a) => a,
83-
Err(_) => {
84-
return Err(AssemblerFailure::InternalError(format!(
85-
"starting address for {block_id} was not calculated"
86-
)));
87-
}
88-
};
89-
90-
if let Some(Origin::Symbolic(span, symbol_name)) = directive_block.origin.as_ref() {
91-
if !symtab.is_defined(symbol_name) {
92-
if let Err(e) = symtab.define(
93-
*span,
94-
symbol_name.clone(),
95-
SymbolDefinition::Origin(address),
96-
) {
97-
// Inconsistent definition.
98-
return Err(AssemblerFailure::BadProgram(vec![
99-
inconsistent_origin_definition(
100-
source_file_body,
101-
*span,
102-
symbol_name.clone(),
103-
e,
104-
),
105-
]));
106-
}
107-
}
108-
}
109-
110-
memory_map.insert(
111-
block_id,
112-
(
113-
directive_block.origin.clone(),
114-
LocatedBlock {
115-
location: address,
116-
statements: directive_block.statements.clone(),
117-
},
118-
),
119-
);
120-
}
121-
122-
Ok(memory_map)
123-
}
124-
12568
let SourceFile {
12669
punch,
12770
blocks: input_blocks,
12871
equalities,
12972
macros: _,
13073
} = self;
131-
let mut output_blocks = BTreeMap::new();
132-
let mut block_default_location: Address = Origin::default_address();
74+
let mut output_blocks: BTreeMap<BlockIdentifier, (Option<Origin>, LocatedBlock)> =
75+
BTreeMap::new();
76+
77+
let tmp_blocks: Vec<(BlockIdentifier, BlockPosition)> = symtab
78+
.blocks_iter()
79+
.map(|(block_identifier, block_position)| (*block_identifier, block_position.clone()))
80+
.collect();
81+
let mut block_locations: BTreeMap<BlockIdentifier, Address> = BTreeMap::new();
82+
let mut no_rc_allocation = NoRcBlock {};
83+
for (block_identifier, block_position) in tmp_blocks.into_iter() {
84+
let mut op: LookupOperation = Default::default();
85+
match (&block_identifier, &block_position).evaluate(
86+
&HereValue::NotAllowed,
87+
symtab,
88+
&mut no_rc_allocation,
89+
&mut op,
90+
) {
91+
Ok(value) => {
92+
let address: Address = subword::right_half(value).into();
93+
block_locations.insert(block_identifier, address);
94+
}
95+
Err(e) => {
96+
return Err(e.into_assembler_failure(source_file_body));
97+
}
98+
}
99+
}
133100

134101
for (block_id, mblock) in input_blocks
135102
.iter()
136103
.enumerate()
137104
.map(|(id, b)| (BlockIdentifier::from(id), b))
138105
{
139-
// We still include zero-word blocks in the directive output
140-
// so that we don't change the block numbering.
141-
let len = mblock.instruction_count();
142-
let location: Option<Address> = match mblock.origin.as_ref() {
143-
None => {
144-
event!(
145-
Level::DEBUG,
146-
"Locating directive {block_id} having {len} words at default origin {block_default_location:o}",
147-
);
148-
Some(block_default_location)
149-
}
150-
Some(Origin::Literal(_, address)) => {
151-
event!(
152-
Level::DEBUG,
153-
"Locating directive {block_id} having {len} words at origin {address:o}",
154-
);
155-
Some(*address)
156-
}
157-
Some(Origin::Symbolic(span, name)) => {
158-
event!(
159-
Level::DEBUG,
160-
"Locating directive {block_id} having {len} words at symbolic location {name}, which we now known to be {block_default_location}",
161-
);
162-
if !symtab.is_defined(name) {
163-
if let Err(e) = symtab.define(
164-
*span,
165-
name.clone(),
166-
SymbolDefinition::Origin(block_default_location),
167-
) {
168-
return Err(AssemblerFailure::BadProgram(vec![
169-
inconsistent_origin_definition(
170-
source_file_body,
171-
*span,
172-
name.clone(),
173-
e,
174-
),
175-
]));
176-
}
177-
Some(block_default_location)
178-
} else {
179-
None
180-
}
181-
}
182-
};
106+
let location: &Address = block_locations
107+
.get(&block_id)
108+
.expect("all block locations should have been determined");
183109
output_blocks.insert(
184110
block_id,
185-
Block {
186-
origin: mblock.origin.clone(),
187-
location,
188-
statements: mblock.statements.clone(),
189-
},
111+
(
112+
mblock.origin.clone(),
113+
LocatedBlock {
114+
location: *location,
115+
statements: mblock.statements.clone(),
116+
},
117+
),
190118
);
191-
if let Some(loc) = location {
192-
// Some programs could use equates or explicit origin
193-
// specifications to generate blocks that overlap. From
194-
// my understanding of the User Handbook, such programs
195-
// are not rejected. The tape loader will happily load
196-
// such programs. But we don't have clear tests for such
197-
// cases. We can add these if we come across programs
198-
// that seem to do this.
199-
let block_end: Address = loc.index_by(len);
200-
block_default_location = max(block_default_location, block_end);
201-
}
202119
}
203120

204121
let entry_point: Option<Address> = match punch {
@@ -234,11 +151,7 @@ impl SourceFile {
234151
// answers for right now. For example, should the
235152
// existing program be cleared? Should the symbol
236153
// table be cleared?
237-
let directive: Directive = Directive::new(
238-
assign_block_positions(source_file_body, output_blocks, symtab)?,
239-
equalities,
240-
entry_point,
241-
);
154+
let directive: Directive = Directive::new(output_blocks, equalities, entry_point);
242155
Ok(directive)
243156
}
244157
}
@@ -446,23 +359,6 @@ fn assemble_pass2(
446359
})
447360
}
448361

449-
fn inconsistent_origin_definition(
450-
source_file_body: &str,
451-
span: Span,
452-
origin_name: SymbolName,
453-
e: BadSymbolDefinition,
454-
) -> WithLocation<ProgramError> {
455-
(
456-
source_file_body,
457-
ProgramError::InconsistentOriginDefinitions {
458-
origin_name,
459-
span,
460-
msg: e.to_string(),
461-
},
462-
)
463-
.into()
464-
}
465-
466362
struct NoRcBlock {}
467363

468364
impl RcAllocator for NoRcBlock {

0 commit comments

Comments
 (0)