1
- use std:: { collections :: HashMap , fmt} ;
1
+ use std:: fmt;
2
2
3
+ use lazy_static:: lazy_static;
4
+
5
+ mod program;
3
6
mod types;
4
- pub use types:: { AddressMode , Modifier , Opcode , Value } ;
5
7
6
- pub const DEFAULT_CORE_SIZE : usize = 8000 ;
8
+ pub use program:: { LabelMap , Program } ;
9
+ pub use types:: { AddressMode , Modifier , Opcode , Value } ;
7
10
8
- type Instructions = Box < [ Option < Instruction > ] > ;
9
- type LabelMap = HashMap < String , usize > ;
11
+ lazy_static ! {
12
+ pub static ref DEFAULT_CONSTANTS : LabelMap = {
13
+ let mut constants = LabelMap :: new( ) ;
14
+ constants. insert( "CORESIZE" . into( ) , 8000 ) ;
15
+ constants. insert( "MAXPROCESSES" . into( ) , 8000 ) ;
16
+ constants. insert( "MAXCYCLES" . into( ) , 80_000 ) ;
17
+ constants. insert( "MAXLENGTH" . into( ) , 100 ) ;
18
+ constants. insert( "MINDISTANCE" . into( ) , 100 ) ;
19
+ constants. insert( "ROUNDS" . into( ) , 1 ) ;
20
+
21
+ // TODO: handle command-line constant redefinition and things like
22
+ // CURLINE, VERSION, WARRIORS, PSPACESIZE
23
+ constants
24
+ } ;
25
+ }
10
26
11
27
#[ derive( Clone , Debug , PartialEq ) ]
12
28
pub struct Field {
@@ -105,115 +121,6 @@ impl Instruction {
105
121
}
106
122
}
107
123
108
- pub struct Core {
109
- instructions : Instructions ,
110
- resolved : Option < Instructions > ,
111
- labels : LabelMap ,
112
- }
113
-
114
- impl PartialEq for Core {
115
- fn eq ( & self , other : & Self ) -> bool {
116
- ( self . resolved . is_some ( ) && self . resolved == other. resolved )
117
- || self . instructions == other. instructions
118
- }
119
- }
120
-
121
- impl Default for Core {
122
- fn default ( ) -> Self {
123
- Core :: new ( DEFAULT_CORE_SIZE )
124
- }
125
- }
126
-
127
- impl fmt:: Debug for Core {
128
- fn fmt ( & self , formatter : & mut fmt:: Formatter ) -> fmt:: Result {
129
- if self . resolved . is_some ( ) {
130
- write ! ( formatter, "{}" , self )
131
- } else {
132
- write ! ( formatter, "<unresolved core>" )
133
- }
134
- }
135
- }
136
-
137
- impl Core {
138
- pub fn new ( core_size : usize ) -> Self {
139
- Core {
140
- instructions : vec ! [ None ; core_size] . into_boxed_slice ( ) ,
141
- resolved : None ,
142
- labels : LabelMap :: new ( ) ,
143
- }
144
- }
145
-
146
- pub fn get ( & self , index : usize ) -> Option < Instruction > {
147
- match & self . resolved {
148
- Some ( instructions) => instructions,
149
- None => & self . instructions ,
150
- }
151
- . get ( index) ?
152
- . clone ( )
153
- }
154
-
155
- pub fn set ( & mut self , index : usize , value : Instruction ) {
156
- self . instructions [ index] = Some ( value) ;
157
- // TODO need to re-resolve here? Or make caller do it
158
- }
159
-
160
- pub fn add_label ( & mut self , index : usize , label : String ) -> Result < ( ) , String > {
161
- if index > self . instructions . len ( ) {
162
- return Err ( format ! (
163
- "Address {} is not valid for core of size {}" ,
164
- index,
165
- self . instructions. len( )
166
- ) ) ;
167
- }
168
-
169
- if self . labels . insert ( label. clone ( ) , index) . is_some ( ) {
170
- Err ( format ! ( "Label '{}' already exists" , label) )
171
- } else {
172
- Ok ( ( ) )
173
- }
174
- }
175
-
176
- pub fn label_address ( & self , label : & str ) -> Option < usize > {
177
- self . labels . get ( label) . copied ( )
178
- }
179
-
180
- pub fn resolve ( & mut self ) -> Result < & mut Self , String > {
181
- let resolved = self
182
- . instructions
183
- . iter ( )
184
- . enumerate ( )
185
- . map ( |( i, maybe_instruction) | {
186
- maybe_instruction
187
- . as_ref ( )
188
- . map ( |instruction| instruction. resolve ( i, & self . labels ) )
189
- . transpose ( )
190
- } )
191
- . collect :: < Result < _ , String > > ( ) ?;
192
-
193
- self . resolved = Some ( resolved) ;
194
-
195
- Ok ( self )
196
- }
197
- }
198
-
199
- impl fmt:: Display for Core {
200
- fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
201
- write ! (
202
- f,
203
- "{}" ,
204
- match & self . resolved {
205
- None => & self . instructions,
206
- Some ( instructions) => instructions,
207
- }
208
- . iter( )
209
- . filter_map( Option :: as_ref)
210
- . fold( String :: new( ) , |result, instruction| {
211
- result + & instruction. to_string( ) + "\n "
212
- } )
213
- )
214
- }
215
- }
216
-
217
124
#[ cfg( test) ]
218
125
mod tests {
219
126
use super :: * ;
@@ -235,87 +142,4 @@ mod tests {
235
142
236
143
assert_eq ! ( Instruction :: default ( ) , expected_instruction)
237
144
}
238
-
239
- #[ test]
240
- fn labels ( ) {
241
- let mut core = Core :: new ( 200 ) ;
242
-
243
- core. add_label ( 123 , "baz" . into ( ) ) . expect ( "Should add baz" ) ;
244
- core. add_label ( 0 , "foo" . into ( ) ) . expect ( "Should add foo" ) ;
245
- core. add_label ( 0 , "bar" . into ( ) ) . expect ( "Should add bar" ) ;
246
-
247
- core. add_label ( 256 , "goblin" . into ( ) )
248
- . expect_err ( "Should fail to add labels > 200" ) ;
249
- core. add_label ( 5 , "baz" . into ( ) )
250
- . expect_err ( "Should error duplicate label" ) ;
251
-
252
- assert_eq ! ( core. label_address( "foo" ) . unwrap( ) , 0 ) ;
253
- assert_eq ! ( core. label_address( "bar" ) . unwrap( ) , 0 ) ;
254
-
255
- // The _last_ version of a label will be the one we use
256
- assert_eq ! ( core. label_address( "baz" ) . unwrap( ) , 5 ) ;
257
-
258
- assert ! ( core. label_address( "goblin" ) . is_none( ) ) ;
259
- assert ! ( core. label_address( "never_mentioned" ) . is_none( ) ) ;
260
- }
261
-
262
- #[ test]
263
- fn resolve_failure ( ) {
264
- let mut core = Core :: new ( 10 ) ;
265
-
266
- core. add_label ( 0 , "foo" . into ( ) ) . expect ( "Should add foo" ) ;
267
-
268
- core. set (
269
- 5 ,
270
- Instruction {
271
- field_a : Field {
272
- value : Value :: Label ( "not_real" . into ( ) ) ,
273
- ..Default :: default ( )
274
- } ,
275
- ..Default :: default ( )
276
- } ,
277
- ) ;
278
-
279
- core. resolve ( ) . expect_err ( "Should fail to resolve" ) ;
280
- }
281
-
282
- #[ test]
283
- fn resolve_labels ( ) {
284
- let mut core = Core :: new ( 10 ) ;
285
-
286
- core. add_label ( 0 , "foo" . into ( ) ) . expect ( "Should add foo" ) ;
287
- core. add_label ( 7 , "baz" . into ( ) ) . expect ( "Should add baz" ) ;
288
-
289
- core. set (
290
- 3 ,
291
- Instruction {
292
- field_a : Field {
293
- value : Value :: Label ( "baz" . into ( ) ) ,
294
- ..Default :: default ( )
295
- } ,
296
- field_b : Field {
297
- value : Value :: Label ( "foo" . into ( ) ) ,
298
- ..Default :: default ( )
299
- } ,
300
- ..Default :: default ( )
301
- } ,
302
- ) ;
303
-
304
- core. resolve ( ) . expect ( "Should resolve all labels in core" ) ;
305
-
306
- assert_eq ! (
307
- core. get( 3 ) . expect( "Should have instruction at pos 5" ) ,
308
- Instruction {
309
- field_a: Field {
310
- value: Value :: Literal ( 4 ) ,
311
- ..Default :: default ( )
312
- } ,
313
- field_b: Field {
314
- value: Value :: Literal ( -3 ) ,
315
- ..Default :: default ( )
316
- } ,
317
- ..Default :: default ( )
318
- }
319
- )
320
- }
321
145
}
0 commit comments