tricu

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

haskell_observe.py (2055B)


      1 #!/usr/bin/env python3
      2 """Bounded whole-tree observation of an explicit bundle export via Haskell ABI."""
      3 import argparse
      4 from pathlib import Path
      5 import resource
      6 import sys
      7 from executable_object import FLAT, verify_payload
      8 
      9 sys.path.insert(0, str(Path(__file__).resolve().parent.parent / 'ext/haskell/python'))
     10 from tricu import Library
     11 
     12 
     13 def main():
     14     parser = argparse.ArgumentParser(description=__doc__)
     15     for key in ('library', 'bundle', 'argument', 'output'):
     16         parser.add_argument('--' + key, type=Path, required=True)
     17     parser.add_argument('--export', required=True)
     18     args = parser.parse_args()
     19     # RTS virtual reservation is distinct from the supervisor's 512-MiB RSS cap.
     20     for kind, limit in [(resource.RLIMIT_AS, 1024 * 1024**2),
     21                         (resource.RLIMIT_STACK, 8 * 1024**2),
     22                         (resource.RLIMIT_CPU, 60), (resource.RLIMIT_CORE, 0)]:
     23         resource.setrlimit(kind, (limit, limit))
     24     data = args.argument.read_bytes()
     25     verify_payload(FLAT, data)
     26     with Library(args.library).context() as ctx, ctx.scope() as roots:
     27         stack = []
     28         for tag in reversed(data):
     29             children = [stack.pop() for _ in range(tag)]
     30             value = (roots.leaf, roots.stem, roots.fork)[tag](*children)
     31             for child in children:
     32                 roots.release(child)
     33             stack.append(value)
     34         assert len(stack) == 1
     35         worker = roots.load_bundle(args.bundle.read_bytes(), args.export)
     36         current = roots.apply(worker, stack[0])
     37         todo, output = [current], bytearray()
     38         while todo:
     39             value = todo.pop()
     40             tag = ctx.kind(value)
     41             output.append(tag)
     42             children = [roots.child(value, i) for i in range(tag)]
     43             todo.extend(reversed(children))
     44             roots.release(value)
     45             if len(output) > 1024 * 1024:
     46                 raise ValueError('test output boundary')
     47         verify_payload(FLAT, output)
     48         args.output.write_bytes(output)
     49 
     50 
     51 if __name__ == '__main__':
     52     main()