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
use crate::{
ast_map::AstNode,
crate_prelude::*,
hir::{HirNode, NamedParam, PosParam},
ParamEnv,
};
use std::sync::Arc;
#[derive(Debug, Default, Clone, PartialEq, Eq, Hash)]
pub struct PortMapping(Vec<(NodeId, NodeEnvId)>);
impl PortMapping {
pub fn find(&self, node_id: NodeId) -> Option<NodeEnvId> {
self.0
.iter()
.find(|&&(id, _)| id == node_id)
.map(|&(_, id)| id)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum PortMappingSource<'hir> {
ModuleInst {
module: NodeId,
inst: NodeId,
env: ParamEnv,
pos: &'hir [PosParam],
named: &'hir [NamedParam],
},
}
pub(crate) fn compute<'gcx>(
cx: &impl Context<'gcx>,
src: PortMappingSource<'gcx>,
) -> Result<Arc<PortMapping>> {
match src {
PortMappingSource::ModuleInst {
module,
inst: _,
env,
pos,
named,
} => {
let module = match cx.hir_of(module)? {
HirNode::Module(m) => m,
_ => panic!("expected module"),
};
let port_iter = pos
.iter()
.enumerate()
.map(
|(index, &(span, assign_id))| match module.ports.get(index) {
Some(&port_id) => Ok((port_id, (assign_id, env))),
None => {
cx.emit(
DiagBuilder2::error(format!(
"{} only has {} ports(s)",
module.desc_full(),
module.ports.len()
))
.span(span),
);
Err(())
}
},
)
.chain(named.iter().map(|&(_span, name, assign_id)| {
let names: Vec<_> = module
.ports
.iter()
.flat_map(|&id| match cx.ast_of(id) {
Ok(AstNode::Port(&ast::Port::Named { name, .. })) => {
Some((name.name, id))
}
Ok(_) => unreachable!(),
Err(()) => None,
})
.collect();
match names
.iter()
.find(|&(port_name, _)| *port_name == name.value)
{
Some(&(_, port_id)) => Ok((port_id, (assign_id, env))),
None => {
cx.emit(
DiagBuilder2::error(format!(
"no port `{}` in {}",
name,
module.desc_full(),
))
.span(name.span)
.add_note(format!(
"declared ports are {}",
names
.iter()
.map(|&(n, _)| format!("`{}`", n))
.collect::<Vec<_>>()
.join(", ")
)),
);
Err(())
}
}
}));
let ports = port_iter
.filter_map(|err| match err {
Ok((port_id, (Some(assign_id), env))) => Some(Ok((port_id, (assign_id, env)))),
Ok(_) => None,
Err(()) => Some(Err(())),
})
.collect::<Result<Vec<_>>>()?;
Ok(Arc::new(PortMapping(ports)))
}
}
}