@@ -5,9 +5,10 @@ use std::collections::{HashMap, VecDeque};
55use std:: path:: { Path , PathBuf } ;
66use std:: sync:: Arc ;
77
8- use crate :: error:: ErrorCollector ;
9- use crate :: parse:: { self , ParseFromStrWithErrors } ;
8+ use crate :: error:: { ErrorCollector , Span } ;
9+ use crate :: parse:: { self , ParseFromStrWithErrors , Visibility } ;
1010use crate :: resolution:: LibConfig ;
11+ use crate :: str:: Identifier ;
1112
1213/// Represents a single, isolated file in the SimplicityHL project.
1314/// In this architecture, a file and a module are the exact same thing.
@@ -22,13 +23,22 @@ pub struct Module {
2223pub struct ProjectGraph {
2324 /// Arena Pattern: the data itself lives here.
2425 /// A flat vector guarantees that module data is stored contiguously in memory.
25- pub modules : Vec < Module > ,
26+ pub ( self ) modules : Vec < Module > ,
27+
28+ /// The configuration environment.
29+ /// Used to resolve xternal library dependencies and invoke their associated functions.
30+ pub config : Arc < LibConfig > ,
2631
2732 /// Fast lookup: File Path -> Module ID.
2833 /// A reverse index mapping absolute file paths to their internal IDs.
2934 /// This solves the duplication problem, ensuring each file is only parsed once.
3035 pub lookup : HashMap < PathBuf , usize > ,
3136
37+ /// Fast lookup: Module ID -> File Path.
38+ /// A direct index mapping internal IDs back to their absolute file paths.
39+ /// This serves as the exact inverse of the `lookup` map.
40+ pub paths : Vec < PathBuf > ,
41+
3242 /// The Adjacency List: Defines the Directed acyclic Graph (DAG) of imports.
3343 ///
3444 /// The Key (`usize`) is the ID of a "Parent" module (the file doing the importing).
@@ -39,6 +49,18 @@ pub struct ProjectGraph {
3949 pub dependencies : HashMap < usize , Vec < usize > > ,
4050}
4151
52+ #[ derive( Clone , Debug ) ]
53+ pub struct Resolution {
54+ pub visibility : Visibility ,
55+ }
56+
57+ pub struct Program {
58+ //pub graph: ProjectGraph,
59+ pub items : Arc < [ parse:: Item ] > ,
60+ pub scope_items : Vec < HashMap < Identifier , Resolution > > ,
61+ pub span : Span ,
62+ }
63+
4264#[ derive( Debug ) ]
4365pub enum C3Error {
4466 CycleDetected ( Vec < usize > ) ,
@@ -91,15 +113,16 @@ fn merge(mut seqs: Vec<Vec<usize>>) -> Option<Vec<usize>> {
91113}
92114
93115impl ProjectGraph {
94- pub fn new ( lib_cfg : & LibConfig , root_program : & parse:: Program ) -> Result < Self , String > {
116+ pub fn new ( config : Arc < LibConfig > , root_program : & parse:: Program ) -> Result < Self , String > {
95117 let mut modules: Vec < Module > = vec ! [ Module {
96118 parsed_program: root_program. clone( ) ,
97119 } ] ;
98120 let mut lookup: HashMap < PathBuf , usize > = HashMap :: new ( ) ;
121+ let mut paths: Vec < PathBuf > = vec ! [ config. root_path. clone( ) ] ;
99122 let mut dependencies: HashMap < usize , Vec < usize > > = HashMap :: new ( ) ;
100123
101124 let root_id = 0 ;
102- lookup. insert ( lib_cfg . root_path . clone ( ) , root_id) ;
125+ lookup. insert ( config . root_path . clone ( ) , root_id) ;
103126 dependencies. insert ( root_id, Vec :: new ( ) ) ;
104127
105128 // Implementation of the standard BFS algorithm with memoization and queue
@@ -112,7 +135,7 @@ impl ProjectGraph {
112135
113136 for elem in current_program. items ( ) {
114137 if let parse:: Item :: Use ( use_decl) = elem {
115- if let Ok ( path) = lib_cfg . get_full_path ( use_decl) {
138+ if let Ok ( path) = config . get_full_path ( use_decl) {
116139 pending_imports. push ( path) ;
117140 }
118141 }
@@ -140,6 +163,7 @@ impl ProjectGraph {
140163 parsed_program : program,
141164 } ) ;
142165 lookup. insert ( path. clone ( ) , last_ind) ;
166+ paths. push ( path. clone ( ) ) ;
143167 dependencies. entry ( curr_id) . or_default ( ) . push ( last_ind) ;
144168
145169 queue. push_back ( last_ind) ;
@@ -148,7 +172,9 @@ impl ProjectGraph {
148172
149173 Ok ( Self {
150174 modules,
175+ config,
151176 lookup,
177+ paths,
152178 dependencies,
153179 } )
154180 }
@@ -212,4 +238,115 @@ impl ProjectGraph {
212238
213239 Ok ( result)
214240 }
241+
242+ fn process_use_item (
243+ scope_items : & mut [ HashMap < Identifier , Resolution > ] ,
244+ file_id : usize ,
245+ ind : usize ,
246+ elem : & Identifier ,
247+ use_decl_visibility : Visibility ,
248+ ) -> Result < ( ) , String > {
249+ if matches ! (
250+ scope_items[ ind] [ elem] . visibility,
251+ parse:: Visibility :: Private
252+ ) {
253+ return Err ( format ! (
254+ "Function {} is private and cannot be used." ,
255+ elem. as_inner( )
256+ ) ) ;
257+ }
258+
259+ scope_items[ file_id] . insert (
260+ elem. clone ( ) ,
261+ Resolution {
262+ visibility : use_decl_visibility,
263+ } ,
264+ ) ;
265+
266+ Ok ( ( ) )
267+ }
268+
269+ fn register_def (
270+ items : & mut Vec < parse:: Item > ,
271+ scope : & mut HashMap < Identifier , Resolution > ,
272+ item : & parse:: Item ,
273+ name : Identifier ,
274+ vis : & parse:: Visibility ,
275+ ) {
276+ items. push ( item. clone ( ) ) ;
277+ scope. insert (
278+ name,
279+ Resolution {
280+ visibility : vis. clone ( ) ,
281+ } ,
282+ ) ;
283+ }
284+
285+ // TODO: @LesterEvSe, consider processing more than one error at a time
286+ fn build_program ( & self , order : & Vec < usize > ) -> Result < Program , String > {
287+ let mut items: Vec < parse:: Item > = Vec :: new ( ) ;
288+ let mut scope_items: Vec < HashMap < Identifier , Resolution > > =
289+ vec ! [ HashMap :: new( ) ; order. len( ) ] ;
290+
291+ for & file_id in order {
292+ let program_items = self . modules [ file_id] . parsed_program . items ( ) ;
293+
294+ for elem in program_items {
295+ match elem {
296+ parse:: Item :: Use ( use_decl) => {
297+ let full_path = self . config . get_full_path ( use_decl) ?;
298+ let ind = self . lookup [ & full_path] ;
299+ let visibility = use_decl. visibility ( ) ;
300+
301+ let use_targets = match use_decl. items ( ) {
302+ parse:: UseItems :: Single ( elem) => std:: slice:: from_ref ( elem) ,
303+ parse:: UseItems :: List ( elems) => elems. as_slice ( ) ,
304+ } ;
305+
306+ for target in use_targets {
307+ ProjectGraph :: process_use_item (
308+ & mut scope_items,
309+ file_id,
310+ ind,
311+ target,
312+ visibility. clone ( ) ,
313+ ) ?;
314+ }
315+ }
316+ parse:: Item :: TypeAlias ( alias) => {
317+ Self :: register_def (
318+ & mut items,
319+ & mut scope_items[ file_id] ,
320+ elem,
321+ alias. name ( ) . clone ( ) . into ( ) ,
322+ alias. visibility ( ) ,
323+ ) ;
324+ }
325+ parse:: Item :: Function ( function) => {
326+ Self :: register_def (
327+ & mut items,
328+ & mut scope_items[ file_id] ,
329+ elem,
330+ function. name ( ) . clone ( ) . into ( ) ,
331+ function. visibility ( ) ,
332+ ) ;
333+ }
334+ parse:: Item :: Module => { }
335+ }
336+ }
337+ }
338+
339+ Ok ( Program {
340+ items : items. into ( ) ,
341+ scope_items,
342+ span : * self . modules [ 0 ] . parsed_program . as_ref ( ) ,
343+ } )
344+ }
345+
346+ pub fn resolve_complication_order ( & self ) -> Result < Program , String > {
347+ // TODO: @LesterEvSe, resolve errors more appropriately
348+ let mut order = self . c3_linearize ( ) . unwrap ( ) ;
349+ order. reverse ( ) ;
350+ self . build_program ( & order)
351+ }
215352}
0 commit comments