Skip to content

Commit 9205254

Browse files
committed
simplify port representation
1 parent 6441e2c commit 9205254

File tree

4 files changed

+130
-69
lines changed

4 files changed

+130
-69
lines changed

crates/ast/src/control.rs

Lines changed: 102 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use super::{
44
use fil_utils::PortAttrs;
55
use struct_variant::struct_variant;
66

7-
#[derive(Clone)]
7+
#[derive(Clone, Debug)]
88
/// Access into a bundle
99
pub struct Access {
1010
pub start: Expr,
@@ -33,76 +33,128 @@ impl From<Expr> for Access {
3333
}
3434
}
3535

36-
/// A port mentioned in the program
37-
// XXX(rachit): the bundle and non-bundle variants can be unified because
38-
// astconv treats them the same anyways.
39-
#[derive(Clone)]
40-
pub enum Port {
41-
/// A port on this component
42-
This(Loc<Id>),
43-
/// A port on an invoke
44-
InvPort { invoke: Loc<Id>, name: Loc<Id> },
45-
/// A port represented by an index into a bundle
46-
Bundle {
47-
name: Loc<Id>,
48-
access: Vec<Loc<Access>>,
49-
},
50-
/// A bundle port on an invocation
51-
InvBundle {
52-
invoke: Loc<Id>,
53-
port: Loc<Id>,
54-
access: Vec<Loc<Access>>,
55-
},
36+
impl std::fmt::Display for Access {
37+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
38+
// For now, always show as range. Could add logic to detect single indices.
39+
write!(f, "{}:{}", self.start, self.end)
40+
}
41+
}
42+
43+
/// Unified port representation
44+
#[derive(Clone, Debug)]
45+
pub struct Port {
46+
/// Base port reference
47+
pub base: PortRef,
48+
/// Optional array/bundle access
49+
pub access: Vec<Loc<Access>>,
50+
/// Source location for error reporting
51+
pub loc: fil_utils::GPosIdx,
52+
}
53+
54+
/// Base port reference
55+
#[derive(Clone, Debug, PartialEq)]
56+
pub enum PortRef {
57+
/// Reference to a port on 'this' component
58+
This { port: Loc<Id> },
59+
/// Reference to a port on an instance or invoke
60+
Instance { instance: Loc<Id>, port: Loc<Id> },
5661
}
5762

5863
impl Port {
64+
/// Create a simple port reference (this.port)
65+
pub fn this_port(port: Loc<Id>) -> Self {
66+
let loc = port.pos();
67+
Port {
68+
base: PortRef::This { port },
69+
access: Vec::new(),
70+
loc,
71+
}
72+
}
73+
74+
/// Create an instance port reference (inst.port)
75+
pub fn instance_port(instance: Loc<Id>, port: Loc<Id>) -> Self {
76+
let loc = instance.pos(); // Using first location, could union if needed
77+
Port {
78+
base: PortRef::Instance { instance, port },
79+
access: Vec::new(),
80+
loc,
81+
}
82+
}
83+
84+
/// Add array/bundle access to a port
85+
pub fn with_access(mut self, access: Vec<Loc<Access>>) -> Self {
86+
self.access = access;
87+
self
88+
}
89+
90+
/// Check if this is a bundle access
91+
pub fn is_bundle(&self) -> bool {
92+
!self.access.is_empty()
93+
}
94+
95+
/// Get the instance name if this is an instance port
96+
pub fn instance(&self) -> Option<&Loc<Id>> {
97+
match &self.base {
98+
PortRef::Instance { instance, .. } => Some(instance),
99+
_ => None,
100+
}
101+
}
102+
103+
/// Get the port name
104+
pub fn port_name(&self) -> &Loc<Id> {
105+
match &self.base {
106+
PortRef::This { port } => port,
107+
PortRef::Instance { port, .. } => port,
108+
}
109+
}
110+
111+
// Legacy constructors for backwards compatibility during migration
59112
pub fn inv_port(comp: Loc<Id>, name: Loc<Id>) -> Self {
60-
Port::InvPort { invoke: comp, name }
113+
Self::instance_port(comp, name)
61114
}
62115

63116
pub fn this(p: Loc<Id>) -> Self {
64-
Port::This(p)
117+
Self::this_port(p)
65118
}
66119

67120
pub fn bundle(name: Loc<Id>, access: Vec<Loc<Access>>) -> Self {
68-
Port::Bundle { name, access }
121+
Self::this_port(name).with_access(access)
69122
}
70123

71124
pub fn inv_bundle(
72125
invoke: Loc<Id>,
73126
port: Loc<Id>,
74127
access: Vec<Loc<Access>>,
75128
) -> Self {
76-
Port::InvBundle {
77-
invoke,
78-
port,
79-
access,
129+
Self::instance_port(invoke, port).with_access(access)
130+
}
131+
132+
pub fn resolve_exprs(mut self, bindings: &Binding<Expr>) -> Self {
133+
if !self.access.is_empty() {
134+
self.access = self
135+
.access
136+
.into_iter()
137+
.map(|i| i.map(|i| i.resolve(bindings)))
138+
.collect();
80139
}
140+
self
81141
}
142+
}
82143

83-
pub fn resolve_exprs(self, bindings: &Binding<Expr>) -> Self {
84-
match self {
85-
Port::Bundle { name, access } => Port::Bundle {
86-
name,
87-
access: access
88-
.into_iter()
89-
.map(|i| i.map(|i| i.resolve(bindings)))
90-
.collect(),
91-
},
92-
Port::InvBundle {
93-
invoke,
94-
port,
95-
access,
96-
} => Port::InvBundle {
97-
invoke,
98-
port,
99-
access: access
100-
.into_iter()
101-
.map(|i| i.map(|a| a.resolve(bindings)))
102-
.collect(),
103-
},
104-
_ => self,
144+
impl std::fmt::Display for Port {
145+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
146+
match &self.base {
147+
PortRef::This { port } => write!(f, "{}", port),
148+
PortRef::Instance { instance, port } => {
149+
write!(f, "{}.{}", instance, port)
150+
}
151+
}?;
152+
153+
for access in &self.access {
154+
write!(f, "{{{}}}", access)?;
105155
}
156+
157+
Ok(())
106158
}
107159
}
108160

crates/ast/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ pub use component::{Component, Extern, Namespace};
1616
pub use constraint::{Constraint, OrderConstraint, OrderOp};
1717
pub use control::{
1818
Access, Bundle, BundleType, Command, Connect, Exists, Fact, ForLoop, If,
19-
Instance, Invoke, ParamLet, Port,
19+
Instance, Invoke, ParamLet, Port, PortRef,
2020
};
2121
pub use expr::{Expr, Fn, Op};
2222
pub use fil_utils::Id;

crates/filament/src/main.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ use fil_ir as ir;
55
use filament::ir_passes::BuildDomination;
66
use filament::{ast_pass_pipeline, ir_pass_pipeline, log_pass, log_time};
77
use filament::{
8-
ast_passes as ap, ast_visitor::Visitor as AstVisitor, cmdline, ir_passes as ip, ir_visitor::Visitor as IrVisitor, resolver::Resolver,
8+
ast_passes as ap, ast_visitor::Visitor as AstVisitor, cmdline,
9+
ir_passes as ip, ir_visitor::Visitor as IrVisitor, resolver::Resolver,
910
};
1011
use serde::Deserialize;
1112
use std::collections::HashMap;

crates/ir/src/from_ast/astconv.rs

Lines changed: 25 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -517,54 +517,62 @@ impl BuildCtx<'_> {
517517
port: ast::Port,
518518
dir: ir::Direction,
519519
) -> BuildRes<ir::Access> {
520-
let acc = match port {
521-
ast::Port::This(n) => {
520+
let acc = match (&port.base, &port.access[..]) {
521+
(ast::PortRef::This { port: name }, []) => {
522522
// NOTE: The AST does not distinguish between ports
523523
// defined by the signature and locally defined ports so we
524524
// must search both.
525-
let owner = OwnedPort::Sig(dir, n.clone());
525+
let owner = OwnedPort::Sig(dir, name.clone());
526526
let port = if let Some(port) = self.find_port(&owner) {
527527
port
528528
} else {
529-
let owner = OwnedPort::Local(n);
529+
let owner = OwnedPort::Local(name.clone());
530530
self.get_port(&owner)?
531531
};
532532

533533
ir::Access::port(port, self.comp())
534534
}
535-
ast::Port::InvPort { invoke, name } => {
535+
(
536+
ast::PortRef::Instance {
537+
instance: invoke,
538+
port: name,
539+
},
540+
[],
541+
) => {
536542
let inv = self.get_inv(&invoke)?;
537-
let owner = OwnedPort::Inv(inv, dir, name);
543+
let owner = OwnedPort::Inv(inv, dir, name.clone());
538544
ir::Access::port(self.get_port(&owner)?, self.comp())
539545
}
540-
ast::Port::Bundle { name, access } => {
546+
(ast::PortRef::This { port: name }, access) => {
541547
// NOTE(rachit): The AST does not distinguish between bundles
542548
// defined by the signature and locally defined bundles so we
543549
// must search both.
544550
let owner = OwnedPort::Sig(dir, name.clone());
545551
let port = if let Some(p) = self.find_port(&owner) {
546552
p
547553
} else {
548-
let owner = OwnedPort::Local(name);
554+
let owner = OwnedPort::Local(name.clone());
549555
self.get_port(&owner)?
550556
};
551557
let ranges = access
552-
.into_iter()
553-
.map(|a| self.access(a.take()))
558+
.iter()
559+
.map(|a| self.access(a.clone().take()))
554560
.collect::<BuildRes<Vec<_>>>()?;
555561
ir::Access { port, ranges }
556562
}
557-
ast::Port::InvBundle {
558-
invoke,
559-
port,
563+
(
564+
ast::PortRef::Instance {
565+
instance: invoke,
566+
port,
567+
},
560568
access,
561-
} => {
569+
) => {
562570
let inv = self.get_inv(&invoke)?;
563-
let owner = OwnedPort::Inv(inv, dir, port);
571+
let owner = OwnedPort::Inv(inv, dir, port.clone());
564572
let port = self.get_port(&owner)?;
565573
let ranges = access
566-
.into_iter()
567-
.map(|a| self.access(a.take()))
574+
.iter()
575+
.map(|a| self.access(a.clone().take()))
568576
.collect::<BuildRes<Vec<_>>>()?;
569577
ir::Access { port, ranges }
570578
}

0 commit comments

Comments
 (0)