@@ -3,7 +3,6 @@ mod output;
33#[ cfg( test) ]
44mod tests;
55
6- use std:: cmp:: max;
76use std:: collections:: BTreeMap ;
87use std:: ffi:: OsStr ;
98use std:: fs:: OpenOptions ;
@@ -15,19 +14,21 @@ use tracing::{event, span, Level};
1514
1615use super :: ast:: * ;
1716use super :: eval:: extract_final_equalities;
17+ use super :: eval:: Evaluate ;
18+ use super :: eval:: HereValue ;
1819use super :: eval:: RcBlock ;
1920use super :: lexer;
2021use super :: listing:: * ;
2122use super :: parser:: parse_source_file;
2223use super :: span:: * ;
2324use super :: state:: { NumeralMode , State } ;
24- use super :: symbol:: SymbolName ;
2525use 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} ;
2929use super :: types:: * ;
3030use base:: prelude:: { Address , IndexBy , Unsigned18Bit , Unsigned36Bit } ;
31+ use base:: subword;
3132pub 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-
466362struct NoRcBlock { }
467363
468364impl RcAllocator for NoRcBlock {
0 commit comments