@@ -8,6 +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
12
type LabelMap = HashMap < String , usize > ;
12
13
13
14
#[ derive( Clone , Debug , PartialEq ) ]
@@ -107,12 +108,18 @@ impl Instruction {
107
108
}
108
109
}
109
110
110
- #[ derive( PartialEq ) ]
111
111
pub struct Core {
112
- instructions : Box < [ Option < Instruction > ] > ,
112
+ instructions : InstructionSet ,
113
113
labels : LabelMap ,
114
114
}
115
115
116
+ impl PartialEq for Core {
117
+ // TODO: should this impl resolve the instructions? Depends on the use case
118
+ fn eq ( & self , other : & Self ) -> bool {
119
+ self . instructions == other. instructions
120
+ }
121
+ }
122
+
116
123
impl Default for Core {
117
124
fn default ( ) -> Self {
118
125
Core :: new ( DEFAULT_CORE_SIZE )
@@ -174,25 +181,39 @@ impl Core {
174
181
self . labels . get ( label) . copied ( )
175
182
}
176
183
184
+ pub fn resolve ( & self ) -> Result < Self , String > {
185
+ let instructions = self
186
+ . instructions
187
+ . iter ( )
188
+ . enumerate ( )
189
+ . map ( |( i, maybe_instruction) | {
190
+ maybe_instruction
191
+ . as_ref ( )
192
+ . map ( |instruction| instruction. resolve ( i, & self . labels ) )
193
+ . transpose ( )
194
+ } )
195
+ . collect :: < Result < InstructionSet , String > > ( ) ?;
196
+
197
+ Ok ( Self {
198
+ instructions,
199
+ ..Default :: default ( )
200
+ } )
201
+ }
202
+
177
203
pub fn dump ( & self ) -> String {
178
204
// TODO: convert to fmt::Display - this will require some upfront
179
205
// validation that all labels are valid, etc
180
206
// It may be desirable to have Debug be a dump() of the load file and
181
207
// Display show the original parsed document (or something like that)
182
- let resolve_result: Result < Vec < _ > , String > = self
183
- . instructions
184
- . iter ( )
185
- . filter ( |& maybe_instruction| maybe_instruction. is_some ( ) )
186
- . map ( |instruction| instruction. as_ref ( ) . unwrap ( ) )
187
- . enumerate ( )
188
- . map ( |( i, instruction) | instruction. resolve ( i, & self . labels ) )
189
- . collect ( ) ;
190
-
191
- match resolve_result {
208
+ match self . resolve ( ) {
192
209
Err ( msg) => msg,
193
- Ok ( resolved) => resolved. iter ( ) . fold ( String :: new ( ) , |result, instruction| {
194
- result + & instruction. to_string ( ) + "\n "
195
- } ) ,
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
+ } ) ,
196
217
}
197
218
}
198
219
}
@@ -240,16 +261,35 @@ mod tests {
240
261
assert ! ( core. label_address( "never_mentioned" ) . is_none( ) ) ;
241
262
}
242
263
243
- // TODO: add test for unresolvable label
244
264
#[ test]
245
- fn resolve_labels ( ) {
246
- let mut core = Core :: new ( 200 ) ;
265
+ fn resolve_failure ( ) {
266
+ let mut core = Core :: new ( 10 ) ;
247
267
248
- core. add_label ( 123 , "baz" . into ( ) ) . expect ( "Should add baz" ) ;
249
268
core. add_label ( 0 , "foo" . into ( ) ) . expect ( "Should add foo" ) ;
250
269
251
270
core. set (
252
271
5 ,
272
+ Instruction {
273
+ field_a : Field {
274
+ value : Value :: Label ( "not_real" . into ( ) ) ,
275
+ ..Default :: default ( )
276
+ } ,
277
+ ..Default :: default ( )
278
+ } ,
279
+ ) ;
280
+
281
+ core. resolve ( ) . expect_err ( "Should fail to resolve" ) ;
282
+ }
283
+
284
+ #[ test]
285
+ fn resolve_labels ( ) {
286
+ let mut core = Core :: new ( 10 ) ;
287
+
288
+ core. add_label ( 0 , "foo" . into ( ) ) . expect ( "Should add foo" ) ;
289
+ core. add_label ( 7 , "baz" . into ( ) ) . expect ( "Should add baz" ) ;
290
+
291
+ core. set (
292
+ 3 ,
253
293
Instruction {
254
294
field_a : Field {
255
295
value : Value :: Label ( "baz" . into ( ) ) ,
@@ -263,16 +303,19 @@ mod tests {
263
303
} ,
264
304
) ;
265
305
266
- let resolved = core. get_resolved ( 5 ) . expect ( "Should resolve instruction" ) ;
306
+ let resolved_core = core. resolve ( ) . expect ( "Should resolve all labels in core" ) ;
307
+
267
308
assert_eq ! (
268
- resolved,
309
+ resolved_core
310
+ . get( 3 )
311
+ . expect( "Should have instruction at pos 5" ) ,
269
312
Instruction {
270
313
field_a: Field {
271
- value: Value :: Literal ( 118 ) ,
314
+ value: Value :: Literal ( 4 ) ,
272
315
..Default :: default ( )
273
316
} ,
274
317
field_b: Field {
275
- value: Value :: Literal ( -5 ) ,
318
+ value: Value :: Literal ( -3 ) ,
276
319
..Default :: default ( )
277
320
} ,
278
321
..Default :: default ( )
0 commit comments