@@ -4,7 +4,7 @@ use super::{
44use fil_utils:: PortAttrs ;
55use struct_variant:: struct_variant;
66
7- #[ derive( Clone ) ]
7+ #[ derive( Clone , Debug ) ]
88/// Access into a bundle
99pub 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
5863impl 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
0 commit comments