-
Notifications
You must be signed in to change notification settings - Fork 0
/
loop_tree.py
61 lines (52 loc) · 1.71 KB
/
loop_tree.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
from typing import List, BinaryIO, Optional
import leb128
from adt import adt, Case
@adt
class LoopTree:
LEAF: Case[int]
ROLLED_OUT: Case[List[List['LoopTree']]]
CARTESIAN: Case[int, List['LoopTree']]
def num_loops(self) -> int:
return self.match(
LEAF=lambda n: n,
ROLLED_OUT=lambda l: len(l),
CARTESIAN=lambda n, _: n,
)
def num_children(self) -> int:
return self.match(
LEAF=lambda n: 0,
ROLLED_OUT=lambda l: len(l[0]) if l else 0,
CARTESIAN=lambda _, l: len(l),
)
def parse_loop_trees(reader: BinaryIO) -> List[LoopTree]:
trees = []
while True:
tree = parse_loop_tree(reader)
if tree is None:
return trees
trees.append(tree)
def parse_loop_tree(reader: BinaryIO) -> Optional[LoopTree]:
kind = reader.read(1)
if len(kind) == 0:
return None
kind = kind[0]
if kind == 0:
num_loops, _ = leb128.u.decode_reader(reader)
return LoopTree.LEAF(num_loops)
elif kind == 1:
num_loops, _ = leb128.u.decode_reader(reader)
num_children, _ = leb128.u.decode_reader(reader)
matrix = []
for _ in range(num_loops):
children = []
for _ in range(num_children):
children.append(parse_loop_tree(reader))
matrix.append(children)
return LoopTree.ROLLED_OUT(matrix)
elif kind == 2:
num_loops, _ = leb128.u.decode_reader(reader)
num_children, _ = leb128.u.decode_reader(reader)
children = []
for _ in range(num_children):
children.append(parse_loop_tree(reader))
return LoopTree.CARTESIAN(num_loops, children)