@@ -178,77 +178,123 @@ def main():
178
178
179
179
print ("types verified" )
180
180
181
- print ("calculating recursive type references..." )
181
+ out_direct_deps_filename = "out-direct-deps.txt"
182
+ print ("generating {}..." .format (out_direct_deps_filename ))
183
+ with open (os .path .join (script_dir , out_direct_deps_filename ), "w" ) as file :
184
+ for api in apis :
185
+ table = api_direct_type_refs_table [api ]
186
+ for type_name ,refs in table .top_level .items ():
187
+ file .write ("{}:{}\n " .format (api , type_name ))
188
+ for ref in refs :
189
+ file .write (" {}\n " .format (ref ))
190
+
191
+
192
+ out_recursive_deps_filename = "out-recursive-deps.txt"
193
+ print ("calculating recursive type references (will store in {})..." .format (out_recursive_deps_filename ))
182
194
api_recursive_type_refs_table : Dict [str ,dict [str ,Set [ApiRef ]]] = {}
183
- with open (os .path .join (script_dir , "out-recursive-deps.txt" ), "w" ) as file :
195
+ with open (os .path .join (script_dir , out_recursive_deps_filename ), "w" ) as file :
184
196
for api in apis :
185
197
#print("calculating recursive deps on {}...".format(api))
186
198
direct_type_refs_table = api_direct_type_refs_table [api ]
187
199
recursive_type_refs_table = {}
188
200
for type_name ,refs in direct_type_refs_table .top_level .items ():
189
201
recursive_chains : List [List [ApiRef ]] = []
190
- getRecursiveChains (api_direct_type_refs_table , set (), refs , recursive_chains , None )
191
- file .write ("{}:{} -> {}\n " .format (api , type_name , recursive_chains ))
202
+ getRecursiveChains (api_direct_type_refs_table , set (), refs , recursive_chains , [])
203
+ if len (recursive_chains ) > 0 :
204
+ file .write ("{}:{}\n " .format (api , type_name ))
205
+ for chain in recursive_chains :
206
+ file .write (" {}\n " .format (chain ))
192
207
recursive_type_refs_table [type_name ] = recursive_chains
193
208
api_recursive_type_refs_table [api ] = recursive_type_refs_table
194
209
print ("done calculating recursive type references" )
195
210
196
211
print ("searching for cycles..." )
197
212
full_type_set : Set [ApiRef ] = set ()
198
- cycle_type_set : Set [ApiRef ] = set ()
213
+ api_cycle_type_set : Dict [ApiRef ,List [ApiRef ]] = {}
214
+ #self_cycle_type_set: Dict[ApiRef,List[ApiRef]] = {}
215
+
216
+ def addApiCycleType (type_set , t , cycle ):
217
+ if t in type_set :
218
+ pass
219
+ #print("type {} is in multiple cycles?".format(t))
220
+ else :
221
+ type_set [t ] = cycle
222
+
199
223
with open (os .path .join (script_dir , "out-cycles.txt" ), "w" ) as file :
200
224
for api in apis :
201
225
#print("API: {}".format(api))
202
226
table = api_recursive_type_refs_table [api ]
203
- cycle_count = 0
227
+ api_cycle_count = 0
204
228
for type_name , recursive_chains in table .items ():
205
229
type_api_ref = ApiRef (api , type_name )
206
230
full_type_set .add (type_api_ref )
207
231
for chain in recursive_chains :
208
- state = 0
209
- for ref in chain :
210
- if ref .api == api :
211
- if state == 1 :
212
- state = 2
213
- break
232
+ found_external_type = False
233
+ cycle_len = 0
234
+ for i in range (0 , len (chain )):
235
+ ref = chain [i ]
236
+ if not found_external_type :
237
+ if ref .api != api :
238
+ found_external_type = True
214
239
else :
215
- if state == 0 :
216
- state = 1
217
- if state == 2 :
218
- file .write ("{}:{} CHAIN={}\n " .format (api , type_name , chain ))
219
- cycle_count += 1
220
- cycle_type_set .add (type_api_ref )
221
- for ref in chain :
222
- cycle_type_set .add (ref )
240
+ if ref .api == api :
241
+ cycle_len = i + 1
242
+ break
243
+ if cycle_len > 0 :
244
+ cycle = chain [:cycle_len ]
245
+ file .write ("{}:{} cycle={}\n " .format (api , type_name , cycle ))
246
+ api_cycle_count += 1
247
+
248
+ if cycle [- 1 ] != type_api_ref :
249
+ addApiCycleType (api_cycle_type_set , type_api_ref , cycle )
250
+ for ref in cycle :
251
+ addApiCycleType (api_cycle_type_set , ref , cycle )
223
252
else :
224
253
pass
225
254
#print("NOT CYCLIC: {}:{} CHAIN={}".format(api, type_name, chain))
226
- if cycle_count > 0 :
227
- print ("{:4} cycles: {}:{}" .format (cycle_count , api , type_name ))
255
+ if api_cycle_count > 0 :
256
+ print ("{:4} cycles: {}:{}" .format (api_cycle_count , api , type_name ))
257
+
258
+ print ("{} out of {} types involved in cycles" .format (len (api_cycle_type_set ), len (full_type_set )))
259
+ #print("{} types have self-referential cycles".format(len(self_cycle_type_set)))
228
260
229
- print ("{} out of {} types involved in cycles" .format (len (cycle_type_set ), len (full_type_set )))
261
+ api_types_list = list (api_cycle_type_set )
262
+ api_types_list .sort ()
230
263
with open (os .path .join (script_dir , "out-cycle-types.txt" ), "w" ) as file :
231
- cycle_types_list = list (cycle_type_set )
232
- cycle_types_list .sort ()
233
- for cycle_type in cycle_types_list :
234
- file .write ("{}\n " .format (cycle_type .combined ))
264
+ for cycle_type in api_types_list :
265
+ file .write ("{}\n " .format (cycle_type ))
266
+ for t in api_cycle_type_set [cycle_type ]:
267
+ file .write (" {}\n " .format (t ))
268
+
269
+ # NOTE: this is not all the cycles, just some of the for now
270
+ with open (os .path .join (script_dir , "out-cycle-types.dot" ), "w" ) as file :
271
+ file .write ("digraph type_cycles {\n " )
272
+ handled = set ()
273
+ for cycle_type in api_types_list :
274
+ cycle = api_cycle_type_set [cycle_type ]
275
+ file .write ("\" {}\" -> \" {}\" \n " .format (cycle_type , cycle [0 ]))
276
+ for i in range (1 , len (cycle )):
277
+ file .write ("\" {}\" -> \" {}\" \n " .format (cycle [i - 1 ], cycle [i ]))
278
+ file .write ("}\n " )
279
+ #with open(os.path.join(script_dir, "out-self-cycle-types.txt"), "w") as file:
280
+ # types_list = list(self_cycle_type_set)
281
+ # types_list.sort()
282
+ # for cycle_type in types_list:
283
+ # file.write("{} (first chain {})\n".format(cycle_type.combined, self_cycle_type_set[cycle_type]))
235
284
236
285
print ("done" )
237
286
238
287
239
- def getRecursiveChains (api_direct_type_refs_table : Dict [str ,ApiTypeNameToApiRefMap ], handled : Set [ApiRef ], refs : Set [ApiRef ], result : List [List [ApiRef ]], current_chain : Optional [ List [ApiRef ] ]) -> None :
288
+ def getRecursiveChains (api_direct_type_refs_table : Dict [str ,ApiTypeNameToApiRefMap ], handled : Set [ApiRef ], refs : Set [ApiRef ], result : List [List [ApiRef ]], base_chain : List [ApiRef ]) -> None :
240
289
for ref in refs :
241
290
ref_api_table = api_direct_type_refs_table [ref .api ]
242
- if not isAnonType (ref .name ) and ref .name in ref_api_table .top_level :
291
+ if ( not isAnonType (ref .name )) and ( ref .name in ref_api_table .top_level ) :
243
292
#file.write("\"{}\" -> \"{}\";\n".format(type_name, ref.name))
244
- next_chain = current_chain
245
- if not next_chain :
246
- next_chain = []
247
- result .append (next_chain )
248
- next_chain .append (ref )
249
-
293
+ next_chain = base_chain + [ref ]
250
294
ref_refs = ref_api_table .top_level [ref .name ]
251
- if not ref in handled :
295
+ if (len (ref_refs ) == 0 ) or (ref in handled ):
296
+ result .append (next_chain )
297
+ else :
252
298
handled .add (ref )
253
299
getRecursiveChains (api_direct_type_refs_table , handled , ref_refs , result , next_chain )
254
300
0 commit comments