1use std::fs::File;
4use std::path::Path;
5use vec_map::VecMap;
6use hlua::{Lua, LuaTable};
7use hlua::functions_read::LuaFunction;
8use save::Save;
9use node::{Node, TestNode, BasicExecutionNode, DamagedExecutionNode, StackMemoryNode, TestInputNode, TestOutputNode, TestImageNode};
10use machine::{NUM_NODES, INPUT_0, Tis100};
11
12const SEED_RANDOM_EXEC: &'static str = "math.randomseed(os.time())";
14
15const LAYOUT_TABLE: &'static str = "layout";
17const LAYOUT_FN: &'static str = "get_layout";
18const LAYOUT_FN_EXEC: &'static str = "layout = get_layout()";
19
20const STREAMS_TABLE: &'static str = "streams";
22const STREAMS_FN: &'static str = "get_streams";
23const STREAMS_FN_EXEC: &'static str = "streams = get_streams()";
24const STREAM_KIND_IDX: u32 = 1;
25const STREAM_NAME_IDX: u32 = 2;
26const STREAM_NODE_IDX: u32 = 3;
27const STREAM_DATA_IDX: u32 = 4;
28
29const STREAM_INPUT: u32 = 0;
31const STREAM_OUTPUT: u32 = 1;
32const STREAM_IMAGE: u32 = 2;
33
34const TILE_COMPUTE: u32 = 0;
36const TILE_MEMORY: u32 = 1;
37const TILE_DAMAGED: u32 = 2;
38
39#[derive(Debug, PartialEq, Eq, Copy, Clone)]
41enum Tile {
42 Compute,
43 Memory,
44 Damaged,
45}
46
47use self::Tile::*;
48
49#[derive(Debug)]
51struct Stream {
52 kind: StreamKind,
53 name: String,
54 node: usize,
55 data: Vec<isize>
56}
57
58#[derive(Debug, PartialEq, Eq, Copy, Clone)]
60enum StreamKind {
61 Input,
62 Output,
63 Image,
64}
65
66use self::StreamKind::*;
67
68pub enum SpecError {
70 SeedRandomFailed,
71 ReadFileFailed,
72 GetLayoutFailed,
73 GetStreamsFailed,
74}
75
76use self::SpecError::*;
77
78pub struct Spec {
82 save: Save,
83 layout: Vec<Tile>,
84 streams: Vec<Stream>,
85}
86
87impl Spec {
88 pub fn from_file(filename: &str, save: Save) -> Result<Spec, SpecError> {
90 let mut lua = Lua::new();
92 lua.openlibs();
93
94 if let Err(_) = lua.execute::<()>(SEED_RANDOM_EXEC) {
95 return Err(SeedRandomFailed);
96 }
97
98 lua.set("STREAM_INPUT", STREAM_INPUT);
99 lua.set("STREAM_OUTPUT", STREAM_OUTPUT);
100 lua.set("STREAM_IMAGE", STREAM_IMAGE);
101 lua.set("TILE_COMPUTE", TILE_COMPUTE);
102 lua.set("TILE_MEMORY", TILE_MEMORY);
103 lua.set("TILE_DAMAGED", TILE_DAMAGED);
104
105 if let Ok(file) = File::open(&Path::new(filename)) {
107 if let Err(_) = lua.execute_from_reader::<(), _>(file) {
108 return Err(ReadFileFailed);
109 }
110 } else {
111 return Err(ReadFileFailed);
112 }
113
114 if let None = lua.get::<LuaFunction<_>, _>(LAYOUT_FN) {
116 return Err(GetLayoutFailed);
117 }
118
119 if let Err(_) = lua.execute::<()>(LAYOUT_FN_EXEC) {
122 return Err(GetLayoutFailed);
123 }
124
125 let mut layout = Vec::new();
127 if let Some(mut layout_table) = lua.get::<LuaTable<_>, _>(LAYOUT_TABLE) {
128 for (_, v) in layout_table.iter::<u32, u32>().filter_map(|e| e) {
129 match v {
130 TILE_COMPUTE => layout.push(Compute),
131 TILE_MEMORY => layout.push(Memory),
132 TILE_DAMAGED => layout.push(Damaged),
133 _ => return Err(GetLayoutFailed),
134 };
135 }
136
137 if layout.len() != NUM_NODES {
138 return Err(GetLayoutFailed);
139 }
140 }
141
142 if let None = lua.get::<LuaFunction<_>, _>(STREAMS_FN) {
144 return Err(GetStreamsFailed);
145 }
146
147 if let Err(_) = lua.execute::<()>(STREAMS_FN_EXEC) {
150 return Err(GetStreamsFailed);
151 }
152
153 let mut streams = Vec::new();
155 if let Some(mut streams_table) = lua.get::<LuaTable<_>, _>(STREAMS_TABLE) {
156 for index in 1..9 {
159 if let Some(mut stream_table) = streams_table.get::<LuaTable<_>, _>(index) {
165 let kind = match stream_table.get::<u32, _>(STREAM_KIND_IDX) {
166 Some(STREAM_INPUT) => Input,
167 Some(STREAM_OUTPUT) => Output,
168 Some(STREAM_IMAGE) => Image,
169 _ => return Err(GetStreamsFailed),
170 };
171
172 let name = match stream_table.get::<String, _>(STREAM_NAME_IDX) {
173 Some(name) => name,
174 None => return Err(GetStreamsFailed),
175 };
176
177 let node = match stream_table.get::<u32, _>(STREAM_NODE_IDX) {
178 Some(node) => node as usize,
179 None => return Err(GetStreamsFailed),
180 };
181
182 let data = match stream_table.get::<LuaTable<_>, _>(STREAM_DATA_IDX) {
183 Some(mut data_table) => {
184 let mut data = Vec::new();
185 for (_, v) in data_table.iter::<u32, i32>().filter_map(|e| e) {
186 data.push(v as isize);
187 }
188 data
189 },
190 None => return Err(GetStreamsFailed),
191 };
192
193 streams.push(Stream {
194 kind: kind,
195 name: name,
196 node: node,
197 data: data,
198 });
199 } else {
200 break;
201 }
202 }
203 }
204
205 Ok(Spec {
206 save: save,
207 layout: layout,
208 streams: streams,
209 })
210 }
211
212 pub fn setup(&mut self, cpu: &mut Tis100) {
214 for (index, &tile) in self.layout.iter().enumerate() {
215 let node: Box<Node> = match tile {
216 Compute => match self.save.get(index) {
217 Some(prog) => Box::new(BasicExecutionNode::with_program(prog.clone())),
218 None => Box::new(BasicExecutionNode::new()),
219 },
220 Memory => Box::new(StackMemoryNode::new()),
221 Damaged => Box::new(DamagedExecutionNode),
222 };
223
224 cpu.add_node(index, node);
225 }
226
227 for stream in self.streams.iter() {
230 if let Input = stream.kind {
231 cpu.add_node(stream.node + INPUT_0, Box::new(TestInputNode::with_data(&stream.data)));
232 }
233 }
234 }
235
236 pub fn tests(&self) -> VecMap<Box<TestNode>> {
238 let mut tests: VecMap<Box<TestNode>> = VecMap::new();
239
240 for stream in self.streams.iter() {
241 match stream.kind {
242 Input => (),
243 Output => {
244 tests.insert(stream.node, Box::new(TestOutputNode::with_data(&stream.data)));
245 },
246 Image => {
247 tests.insert(stream.node, Box::new(TestImageNode::with_data(&stream.data, 30, 18)));
248 },
249 };
250 }
251
252 tests
253 }
254}