@@ -291,12 +291,17 @@ def build_elixir(root):
291291
292292def run_elixir (exs_path , graph_cfg , B , k , trials , seed , maxw , timeout_s = 0 ):
293293 gtype = graph_cfg ['type' ]
294+ if gtype == 'ba' :
295+ # Elixir implementation currently lacks BA support; skip to avoid hard failures
296+ print (f"[info] Elixir impl does not support graph type \" { gtype } \" yet; skipping" , file = sys .stderr )
297+ return []
294298 args = ['elixir' , str (exs_path ), '--trials' , str (trials ), '--k' , str (k ), '--B' , str (B ), '--seed' , str (seed ), '--maxw' , str (maxw ), '--graph' , gtype ]
295299 if gtype == 'grid' :
296300 args += ['--rows' , str (graph_cfg ['rows' ]), '--cols' , str (graph_cfg ['cols' ])]
297301 elif gtype == 'er' :
298302 args += ['--n' , str (graph_cfg ['n' ]), '--p' , str (graph_cfg ['p' ])]
299303 elif gtype == 'ba' :
304+ # See above early return; keep branch for completeness if support is added later
300305 args += ['--n' , str (graph_cfg ['n' ]), '--m0' , str (graph_cfg .get ('m0' ,5 )), '--m' , str (graph_cfg .get ('m' ,5 ))]
301306 else :
302307 return []
@@ -305,6 +310,9 @@ def run_elixir(exs_path, graph_cfg, B, k, trials, seed, maxw, timeout_s=0):
305310 except subprocess .TimeoutExpired :
306311 print (f'[warn] elixir run timed out: { args } ' , file = sys .stderr )
307312 return []
313+ except subprocess .CalledProcessError as e :
314+ print (f'[warn] elixir run failed (exit { e .returncode } ); skipping: { args } ' , file = sys .stderr )
315+ return []
308316 rows = [json .loads (line ) for line in p .stdout .splitlines () if line .strip ()]
309317 for r in rows :
310318 r ['graph_cfg' ] = graph_cfg
@@ -320,6 +328,9 @@ def build_erlang(root):
320328
321329def run_erlang (beam_path , graph_cfg , B , k , trials , seed , maxw , timeout_s = 0 ):
322330 gtype = graph_cfg ['type' ]
331+ if gtype == 'ba' :
332+ print (f"[info] Erlang impl does not support graph type \" { gtype } \" yet; skipping" , file = sys .stderr )
333+ return []
323334 args = ['erl' , '-noshell' , '-pa' , str (beam_path .parent ), '-s' , 'bmssp' , 'main' , '-s' , 'init' , 'stop' , '-extra' , '--trials' , str (trials ), '--k' , str (k ), '--B' , str (B ), '--seed' , str (seed ), '--maxw' , str (maxw ), '--graph' , gtype ]
324335 if gtype == 'grid' :
325336 args += ['--rows' , str (graph_cfg ['rows' ]), '--cols' , str (graph_cfg ['cols' ])]
@@ -334,6 +345,9 @@ def run_erlang(beam_path, graph_cfg, B, k, trials, seed, maxw, timeout_s=0):
334345 except subprocess .TimeoutExpired :
335346 print (f'[warn] erlang run timed out: { args } ' , file = sys .stderr )
336347 return []
348+ except subprocess .CalledProcessError as e :
349+ print (f'[warn] erlang run failed (exit { e .returncode } ); skipping: { args } ' , file = sys .stderr )
350+ return []
337351 rows = [json .loads (line ) for line in p .stdout .splitlines () if line .strip ()]
338352 for r in rows :
339353 r ['graph_cfg' ] = graph_cfg
@@ -395,6 +409,8 @@ def main():
395409 ap .add_argument ('--smoke' , action = 'store_true' , help = 'use bench/smoke_matrix.yaml and enforce basic invariants' )
396410 ap .add_argument ('--parity' , action = 'store_true' , help = 'check simple cross-impl parity on grid graphs' )
397411 ap .add_argument ('--shared-inputs' , action = 'store_true' , help = 'use canonical shared graph+sources files for supported implementations' )
412+ ap .add_argument ('--include-impls' , default = '' , help = 'comma-separated list of impl keys to include (rust,c,cpp,kotlin,crystal,elixir,erlang,nim)' )
413+ ap .add_argument ('--exclude-impls' , default = '' , help = 'comma-separated list of impl keys to exclude' )
398414 args = ap .parse_args ()
399415
400416 # build
@@ -405,39 +421,52 @@ def main():
405421 subprocess .run (['cargo' , 'build' , '-p' , 'bmssp' ], cwd = ROOT , check = True )
406422 rust_bin = ROOT / 'target' / 'debug' / 'bmssp-cli'
407423
424+ # Impl filters
425+ all_keys = {'rust' ,'c' ,'cpp' ,'kotlin' ,'crystal' ,'elixir' ,'erlang' ,'nim' }
426+ inc = set (x .strip () for x in args .include_impls .split (',' ) if x .strip ()) or set (all_keys )
427+ exc = set (x .strip () for x in args .exclude_impls .split (',' ) if x .strip ())
428+ sel = (inc & all_keys ) - exc
429+
408430 crystal_bin = None
409431 try :
410- crystal_bin = build_crystal (ROOT )
432+ if 'crystal' in sel :
433+ crystal_bin = build_crystal (ROOT )
411434 except Exception as e :
412435 print (f'[warn] crystal build skipped: { e } ' , file = sys .stderr )
413436 c_bin = None
414437 try :
415- c_bin = build_c (ROOT )
438+ if 'c' in sel :
439+ c_bin = build_c (ROOT )
416440 except Exception as e :
417441 print (f'[warn] c build skipped: { e } ' , file = sys .stderr )
418442 cpp_bin = None
419443 try :
420- cpp_bin = build_cpp (ROOT )
444+ if 'cpp' in sel :
445+ cpp_bin = build_cpp (ROOT )
421446 except Exception as e :
422447 print (f'[warn] cpp build skipped: { e } ' , file = sys .stderr )
423448 kotlin_jar = None
424449 try :
425- kotlin_jar = build_kotlin (ROOT )
450+ if 'kotlin' in sel :
451+ kotlin_jar = build_kotlin (ROOT )
426452 except Exception as e :
427453 print (f'[warn] kotlin build skipped: { e } ' , file = sys .stderr )
428454 elixir_exs = None
429455 try :
430- elixir_exs = build_elixir (ROOT )
456+ if 'elixir' in sel :
457+ elixir_exs = build_elixir (ROOT )
431458 except Exception as e :
432459 print (f'[warn] elixir build skipped: { e } ' , file = sys .stderr )
433460 erlang_beam = None
434461 try :
435- erlang_beam = build_erlang (ROOT )
462+ if 'erlang' in sel :
463+ erlang_beam = build_erlang (ROOT )
436464 except Exception as e :
437465 print (f'[warn] erlang build skipped: { e } ' , file = sys .stderr )
438466 nim_bin = None
439467 try :
440- nim_bin = build_nim (ROOT )
468+ if 'nim' in sel :
469+ nim_bin = build_nim (ROOT )
441470 except Exception as e :
442471 print (f'[warn] nim build skipped: { e } ' , file = sys .stderr )
443472
@@ -509,41 +538,46 @@ def maybe_validate_and_add(rows):
509538 for B in cfg ['bounds' ]:
510539 for k in cfg ['sources_k' ]:
511540 # Rust: run serially across thread counts to avoid CPU contention
512- for th in threads_list :
513- shared = None
514- if args .shared_inputs :
515- shared = generate_shared_inputs (g , k , cfg ['seed' ], cfg ['maxw' ], out_dir )
516- rows = run_rust (g , B , k , cfg ['trials' ], cfg ['seed' ], cfg ['maxw' ], th , rust_bin , timeout_s = args .timeout_seconds , shared_inputs = shared )
517- maybe_validate_and_add (rows )
541+ if 'rust' in sel :
542+ for th in threads_list :
543+ shared = None
544+ if args .shared_inputs :
545+ shared = generate_shared_inputs (g , k , cfg ['seed' ], cfg ['maxw' ], out_dir )
546+ rows = run_rust (g , B , k , cfg ['trials' ], cfg ['seed' ], cfg ['maxw' ], th , rust_bin , timeout_s = args .timeout_seconds , shared_inputs = shared )
547+ maybe_validate_and_add (rows )
518548
519549 # Prepare non-Rust tasks
520550 tasks = []
521- if crystal_bin is not None :
551+ if 'crystal' in sel and crystal_bin is not None :
522552 # Crystal: no shared-input support yet
523553 tasks .append ((run_crystal , (crystal_bin , g , B , k , cfg ['trials' ], cfg ['seed' ], cfg ['maxw' ], args .timeout_seconds )))
524- if c_bin is not None :
554+ if 'c' in sel and c_bin is not None :
525555 shared = None
526556 if args .shared_inputs :
527557 shared = generate_shared_inputs (g , k , cfg ['seed' ], cfg ['maxw' ], out_dir )
528558 tasks .append ((run_c , (c_bin , g , B , k , cfg ['trials' ], cfg ['seed' ], cfg ['maxw' ], args .timeout_seconds , shared )))
529- if cpp_bin is not None :
559+ if 'cpp' in sel and cpp_bin is not None :
530560 shared = None
531561 if args .shared_inputs :
532562 shared = generate_shared_inputs (g , k , cfg ['seed' ], cfg ['maxw' ], out_dir )
533563 tasks .append ((run_cpp , (cpp_bin , g , B , k , cfg ['trials' ], cfg ['seed' ], cfg ['maxw' ], args .timeout_seconds , shared )))
534- if kotlin_jar is not None :
564+ if 'kotlin' in sel and kotlin_jar is not None :
535565 tasks .append ((run_kotlin , (kotlin_jar , g , B , k , cfg ['trials' ], cfg ['seed' ], cfg ['maxw' ], args .timeout_seconds )))
536- if elixir_exs is not None :
566+ if 'elixir' in sel and elixir_exs is not None :
537567 tasks .append ((run_elixir , (elixir_exs , g , B , k , cfg ['trials' ], cfg ['seed' ], cfg ['maxw' ], args .timeout_seconds )))
538- if erlang_beam is not None :
568+ if 'erlang' in sel and erlang_beam is not None :
539569 tasks .append ((run_erlang , (erlang_beam , g , B , k , cfg ['trials' ], cfg ['seed' ], cfg ['maxw' ], args .timeout_seconds )))
540- if nim_bin is not None :
570+ if 'nim' in sel and nim_bin is not None :
541571 tasks .append ((run_nim , (nim_bin , g , B , k , cfg ['trials' ], cfg ['seed' ], cfg ['maxw' ], args .timeout_seconds )))
542572
543573 if tasks :
544574 if args .jobs <= 1 :
545575 for func , pargs in tasks :
546- rows = func (* pargs )
576+ try :
577+ rows = func (* pargs )
578+ except Exception as e :
579+ print (f'[warn] task failed: { e } ' , file = sys .stderr )
580+ rows = []
547581 maybe_validate_and_add (rows )
548582 else :
549583 with ThreadPoolExecutor (max_workers = max (1 , args .jobs )) as ex :
0 commit comments