tricu

A lazy functional language based on Tree Calculus
Log | Files | Refs | README | LICENSE

float_library_extract.py (3888B)


      1 #!/usr/bin/env python3
      2 """Extract library declarations while preserving executable bodies.
      3 
      4 Token dependency scanning conservatively includes matching names, including names
      5 shadowed by local binders. Run explicitly to prepare an extraction and review its
      6 output against the maintained library sources before accepting the changes.
      7 """
      8 import hashlib
      9 import json
     10 from pathlib import Path
     11 import re
     12 
     13 ROOT=Path(__file__).resolve().parent.parent
     14 SOURCES={
     15  'boundary':'bench/float-boundary.tri','working':'bench/float-working.tri',
     16  'chains':'bench/float-chains.tri','ieee':'bench/float-ieee.tri',
     17  'product_quotient':'bench/float-finite-product-quotient.tri',
     18  'finite':'bench/float-finite.tri','adders':'bench/float-adders.tri',
     19  'multiply':'bench/float-multiply.tri','near':'bench/float-near-jam.tri',
     20  'aligned':'bench/float-aligned-quantize.tri','fast':'bench/float-quantize-fast.tri',
     21  'quantize':'bench/float-quantize.tri','pipelines':'bench/float-pipelines.tri',
     22  'kernels':'bench/float-significands.tri','layouts':'bench/float-layouts.tri'}
     23 
     24 
     25 def parsed(path):
     26     text=(ROOT/path).read_text()
     27     imports=dict((alias,module) for module,alias in re.findall(r'^!import (\w+) as (\w+)$',text,re.M))
     28     exports=re.findall(r'^!export ([\w?]+)$',text,re.M)
     29     # Keep executable text verbatim; omit historical benchmark commentary.
     30     body='\n'.join(line for line in text.splitlines() if line and not line.startswith(('!','--')))+'\n'
     31     starts=list(re.finditer(r'^([A-Za-z][\w?]*)[ \t]+[^\n=]*=',body,re.M))
     32     assert starts and starts[0].start()==0,path
     33     defs={m[1]:body[m.start():starts[i+1].start() if i+1<len(starts) else len(body)] for i,m in enumerate(starts)}
     34     assert len(defs)==len(starts),path
     35     return imports,exports,defs
     36 
     37 
     38 def extract():
     39     modules={m:parsed(p) for m,p in SOURCES.items()}
     40     needed=set();external={m:set() for m in modules};pending=[('boundary',n) for n in modules['boundary'][1]]
     41     external['boundary'].update(modules['boundary'][1])
     42     while pending:
     43         m,n=pending.pop()
     44         if (m,n) in needed:continue
     45         needed.add((m,n));imports,_,defs=modules[m];body=defs[n]
     46         for alias,name in re.findall(r'\b(\w+)\.([\w?]+)',body):
     47             target=imports[alias]
     48             if target=='native_math':continue
     49             external[target].add(name);pending.append((target,name))
     50         unqualified=re.sub(r'\b\w+\.[\w?]+','',body)
     51         for name in re.findall(r'[A-Za-z][\w?]*',unqualified):
     52             if name in defs:pending.append((m,name))
     53     report={}
     54     for m,(imports,_,defs) in modules.items():
     55         selected={n:body for n,body in defs.items() if (m,n) in needed}
     56         if not selected:continue
     57         body=''.join(selected.values());used={a for a,_ in re.findall(r'\b(\w+)\.([\w?]+)',body)}
     58         header='-- Pure binary64 implementation; trusted internal helpers.\n'
     59         if m=='boundary':header='-- Binary64 facade: checked word boundaries, trusted constructed values.\n'
     60         for alias,target in imports.items():
     61             if alias in used:header+=f'!import {target if target=="native_math" else "binary64_"+target} as {alias}\n'
     62         for name in sorted(external[m]):header+=f'!export {name}\n'
     63         path='lib/math/binary64.tri' if m=='boundary' else f'lib/math/binary64/{m}.tri'
     64         file=ROOT/path;file.parent.mkdir(parents=True,exist_ok=True);file.write_text(header+'\n'+body)
     65         report[m]=dict(path=path,source=SOURCES[m],source_sha256=hashlib.sha256((ROOT/SOURCES[m]).read_bytes()).hexdigest(),
     66                        sha256=hashlib.sha256(file.read_bytes()).hexdigest(),declarations=list(selected),exports=sorted(external[m]))
     67     (ROOT/'test/float-library-extraction.json').write_text(json.dumps(report,indent=2)+'\n')
     68     print('Extracted',sum(len(r['declarations']) for r in report.values()),'declarations in',len(report),'modules')
     69 
     70 if __name__=='__main__':extract()