@@ -8,7 +8,7 @@ pub use types::{AddressMode, Modifier, Opcode, Value};
8
8
9
9
pub const DEFAULT_CORE_SIZE : usize = 8000 ;
10
10
11
- type InstructionSet = Box < [ Option < Instruction > ] > ;
11
+ type Instructions = Box < [ Option < Instruction > ] > ;
12
12
type LabelMap = HashMap < String , usize > ;
13
13
14
14
#[ derive( Clone , Debug , PartialEq ) ]
@@ -109,14 +109,15 @@ impl Instruction {
109
109
}
110
110
111
111
pub struct Core {
112
- instructions : InstructionSet ,
112
+ instructions : Instructions ,
113
+ resolved : Option < Instructions > ,
113
114
labels : LabelMap ,
114
115
}
115
116
116
117
impl PartialEq for Core {
117
- // TODO: should this impl resolve the instructions? Depends on the use case
118
118
fn eq ( & self , other : & Self ) -> bool {
119
- self . instructions == other. instructions
119
+ ( self . resolved . is_some ( ) && self . resolved == other. resolved )
120
+ || self . instructions == other. instructions
120
121
}
121
122
}
122
123
@@ -128,35 +129,35 @@ impl Default for Core {
128
129
129
130
impl fmt:: Debug for Core {
130
131
fn fmt ( & self , formatter : & mut fmt:: Formatter ) -> fmt:: Result {
131
- write ! (
132
- formatter,
133
- "Labels: {:?}\n Core:\n {}" ,
134
- self . labels,
135
- self . dump( )
136
- )
132
+ if self . resolved . is_some ( ) {
133
+ write ! ( formatter, "{}" , self )
134
+ } else {
135
+ write ! ( formatter, "<unresolved core>" )
136
+ }
137
137
}
138
138
}
139
139
140
140
impl Core {
141
141
pub fn new ( core_size : usize ) -> Self {
142
142
Core {
143
143
instructions : vec ! [ None ; core_size] . into_boxed_slice ( ) ,
144
- labels : HashMap :: new ( ) ,
144
+ resolved : None ,
145
+ labels : LabelMap :: new ( ) ,
145
146
}
146
147
}
147
148
148
149
pub fn get ( & self , index : usize ) -> Option < Instruction > {
149
- self . instructions . get ( index) ?. clone ( )
150
- }
151
-
152
- pub fn get_resolved ( & self , index : usize ) -> Result < Instruction , String > {
153
- self . get ( index)
154
- . unwrap_or_default ( )
155
- . resolve ( index, & self . labels )
150
+ match & self . resolved {
151
+ Some ( instructions) => instructions,
152
+ None => & self . instructions ,
153
+ }
154
+ . get ( index) ?
155
+ . clone ( )
156
156
}
157
157
158
158
pub fn set ( & mut self , index : usize , value : Instruction ) {
159
159
self . instructions [ index] = Some ( value) ;
160
+ // TODO need to re-resolve here? Or make caller do it
160
161
}
161
162
162
163
pub fn add_label ( & mut self , index : usize , label : String ) -> Result < ( ) , String > {
@@ -181,8 +182,8 @@ impl Core {
181
182
self . labels . get ( label) . copied ( )
182
183
}
183
184
184
- pub fn resolve ( & self ) -> Result < Self , String > {
185
- let instructions = self
185
+ pub fn resolve ( & mut self ) -> Result < & mut Self , String > {
186
+ let resolved = self
186
187
. instructions
187
188
. iter ( )
188
189
. enumerate ( )
@@ -192,29 +193,29 @@ impl Core {
192
193
. map ( |instruction| instruction. resolve ( i, & self . labels ) )
193
194
. transpose ( )
194
195
} )
195
- . collect :: < Result < InstructionSet , String > > ( ) ?;
196
+ . collect :: < Result < _ , String > > ( ) ?;
196
197
197
- Ok ( Self {
198
- instructions,
199
- ..Default :: default ( )
200
- } )
198
+ self . resolved = Some ( resolved) ;
199
+
200
+ Ok ( self )
201
201
}
202
+ }
202
203
203
- pub fn dump ( & self ) -> String {
204
- // TODO: convert to fmt::Display - this will require some upfront
205
- // validation that all labels are valid, etc
206
- // It may be desirable to have Debug be a dump() of the load file and
207
- // Display show the original parsed document (or something like that)
208
- match self . resolve ( ) {
209
- Err ( msg ) => msg ,
210
- Ok ( core ) => core
211
- . instructions
212
- . iter ( )
213
- . filter_map ( Option :: as_ref)
214
- . fold ( String :: new ( ) , |result, instruction| {
215
- result + & instruction. to_string ( ) + "\n "
216
- } ) ,
217
- }
204
+ impl fmt :: Display for Core {
205
+ fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt :: Result {
206
+ write ! (
207
+ f ,
208
+ "{}" ,
209
+ match & self . resolved {
210
+ None => & self . instructions ,
211
+ Some ( instructions ) => instructions ,
212
+ }
213
+ . iter( )
214
+ . filter_map( Option :: as_ref)
215
+ . fold( String :: new( ) , |result, instruction| {
216
+ result + & instruction. to_string( ) + "\n "
217
+ } )
218
+ )
218
219
}
219
220
}
220
221
@@ -303,12 +304,10 @@ mod tests {
303
304
} ,
304
305
) ;
305
306
306
- let resolved_core = core. resolve ( ) . expect ( "Should resolve all labels in core" ) ;
307
+ core. resolve ( ) . expect ( "Should resolve all labels in core" ) ;
307
308
308
309
assert_eq ! (
309
- resolved_core
310
- . get( 3 )
311
- . expect( "Should have instruction at pos 5" ) ,
310
+ core. get( 3 ) . expect( "Should have instruction at pos 5" ) ,
312
311
Instruction {
313
312
field_a: Field {
314
313
value: Value :: Literal ( 4 ) ,
0 commit comments