Skip to content

Commit 3520620

Browse files
Refactor 'program' to be distinct from 'core'
1 parent 0e9e848 commit 3520620

File tree

3 files changed

+275
-208
lines changed

3 files changed

+275
-208
lines changed

src/load_file.rs

Lines changed: 21 additions & 197 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,28 @@
1-
use std::{collections::HashMap, fmt};
1+
use std::fmt;
22

3+
use lazy_static::lazy_static;
4+
5+
mod program;
36
mod types;
4-
pub use types::{AddressMode, Modifier, Opcode, Value};
57

6-
pub const DEFAULT_CORE_SIZE: usize = 8000;
8+
pub use program::{LabelMap, Program};
9+
pub use types::{AddressMode, Modifier, Opcode, Value};
710

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+
}
1026

1127
#[derive(Clone, Debug, PartialEq)]
1228
pub struct Field {
@@ -105,115 +121,6 @@ impl Instruction {
105121
}
106122
}
107123

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-
217124
#[cfg(test)]
218125
mod tests {
219126
use super::*;
@@ -235,87 +142,4 @@ mod tests {
235142

236143
assert_eq!(Instruction::default(), expected_instruction)
237144
}
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-
}
321145
}

0 commit comments

Comments
 (0)