tricu

An interpreted language for exploring Tree Calculus
Log | Files | Refs | README | LICENSE

native_header.py (2370B)


      1 """Cheap native header audit for build tooling; native tricu owns compilation.
      2 
      3 Recovery rows are deliberately handled separately by bootstrap_generations.
      4 """
      5 import re
      6 
      7 ALIAS = re.compile(r'[A-Za-z_][A-Za-z0-9_-]*\Z')
      8 HASH = re.compile(r'[0-9a-f]{64}\Z')
      9 
     10 
     11 def native_header(source):
     12     """Return ordered edges and (reference, qualifier) imports, without rewriting."""
     13     edges, built, acquired, imports = [], set(), set(), []
     14     for line in source.splitlines():
     15         row = line.split()
     16         if not row or row[0].startswith('--'):
     17             continue
     18         directive = row[0]
     19         if not directive.startswith('!'):
     20             break
     21         ref = None
     22         if directive == '!import':
     23             if len(row) == 2 and not HASH.fullmatch(row[1]):
     24                 ref, qualifier = row[1], row[1]
     25             elif len(row) == 3 and row[2] == '*':
     26                 ref, qualifier = row[1], '*'
     27             elif len(row) == 4 and row[2] == 'as':
     28                 ref, qualifier = row[1], row[3]
     29             else:
     30                 raise ValueError('invalid native import')
     31             if qualifier != '*' and not ALIAS.fullmatch(qualifier):
     32                 raise ValueError('invalid native qualifier')
     33             imports.append((ref, '!Local' if qualifier == '*' else qualifier))
     34         elif directive == '!export':
     35             if len(row) == 4 and row[1:3] == ['*', 'from']:
     36                 ref = row[3]
     37             elif len(row) != 2:
     38                 raise ValueError('invalid native export')
     39         elif directive == '!source':
     40             if len(row) != 2 or not ALIAS.fullmatch(row[1]) or HASH.fullmatch(row[1]):
     41                 raise ValueError('invalid build-only source')
     42             ref = row[1]
     43             if ref in built or ref in acquired:
     44                 raise ValueError('redundant build-only source')
     45             built.add(ref)
     46         else:
     47             raise ValueError('unknown native header directive')
     48         if ref is None:
     49             continue
     50         if not (HASH.fullmatch(ref) or ALIAS.fullmatch(ref)):
     51             raise ValueError('invalid native reference')
     52         if directive != '!source':
     53             if ref in built:
     54                 raise ValueError('redundant build-only source')
     55             acquired.add(ref)
     56         if not HASH.fullmatch(ref) and ref not in edges:
     57             edges.append(ref)
     58     return edges, imports