1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
use crate::prog_gen::{
Bin, BinType, FlowCondition, Model, VariableOperation, VariableType, PGM,
};
use crate::Result;
use crate::ast::{Node, Processor, Return};
/// This extracts all definitions for tests, test invocations, pattern sets, bins, etc.
/// and converts them into a program model which is returned.
/// The resultant AST has most of the associated nodes removed but is otherwise unchanged.
/// The model is not considered finalized until after the flow generator for the specific ATE
/// target has run, at that point any ATE-specific extraction into the model will be complete,
/// e.g. to extract pattern references made by test objects.
pub struct ExtractToModel {
model: Model,
}
pub fn run(node: &Node<PGM>, model: Model) -> Result<(Node<PGM>, Model)> {
let mut p = ExtractToModel { model: model };
let ast = node.process(&mut p)?.unwrap();
Ok((ast, p.model))
}
impl Processor<PGM> for ExtractToModel {
fn on_node(&mut self, node: &Node<PGM>) -> crate::Result<Return<PGM>> {
Ok(match &node.attrs {
PGM::ResourcesFilename(name, kind) => {
self.model.set_resources_filename(name.to_owned(), kind);
Return::Unmodified
}
PGM::Condition(cond) => {
match cond {
FlowCondition::IfJob(_ids) | FlowCondition::UnlessJob(_ids) => {
self.model.record_variable_reference(
"JOB".to_string(),
VariableType::Job,
VariableOperation::Reference,
);
}
FlowCondition::IfEnable(ids) | FlowCondition::UnlessEnable(ids) => {
for id in ids {
self.model.record_variable_reference(
id.to_owned(),
VariableType::Enable,
VariableOperation::Reference,
);
}
}
FlowCondition::IfFlag(ids) | FlowCondition::UnlessFlag(ids) => {
for id in ids {
self.model.record_variable_reference(
id.to_owned(),
VariableType::Flag,
VariableOperation::Reference,
);
}
}
_ => {}
}
Return::ProcessChildren
}
PGM::SetFlag(name, _, _) => {
self.model.record_variable_reference(
name.to_owned(),
VariableType::Flag,
VariableOperation::Set,
);
Return::ProcessChildren
}
//PGM::PatternGroup(id, name, _, kind) => Ok(Return::None),
//PGM::PushPattern(id, name, start_label) => Ok(Return::None),
// These will be left in the AST for later consumption by the flow, but they also function
// as un-official bin definitions.
// Any official bin defs in the AST for the same bin number will be combined with the model
// defintion created from here.
PGM::Bin(hardbin, softbin, kind) => {
let flow = self.model.get_flow_mut(None);
if !flow.hardbins.contains_key(hardbin) {
let b = Bin {
number: *hardbin,
description: None,
priority: None,
pass: matches!(kind, BinType::Good),
};
flow.hardbins.insert(*hardbin, b);
}
if let Some(softbin) = softbin {
if !flow.softbins.contains_key(hardbin) {
let b = Bin {
number: *softbin,
description: None,
priority: None,
pass: matches!(kind, BinType::Good),
};
flow.softbins.insert(*softbin, b);
}
}
Return::Unmodified
}
PGM::DefBin(number, is_soft, kind, description, priority) => {
let flow = self.model.get_flow_mut(None);
let collection = match is_soft {
false => &mut flow.hardbins,
true => &mut flow.softbins,
};
if !collection.contains_key(number) {
let b = Bin {
number: *number,
description: description.to_owned(),
priority: priority.to_owned(),
pass: matches!(kind, BinType::Good),
};
collection.insert(*number, b);
} else {
let b = collection.get_mut(number).unwrap();
if let Some(d) = description {
b.description = Some(d.to_owned());
}
if let Some(p) = priority {
b.priority = Some(*p);
}
}
Return::None
}
_ => Return::ProcessChildren,
})
}
}