File: demystify.py

package info (click to toggle)
actor-framework 0.18.7-1~exp1
  • links: PTS
  • area: main
  • in suites: experimental
  • size: 8,740 kB
  • sloc: cpp: 85,162; sh: 491; python: 187; makefile: 11
file content (118 lines) | stat: -rwxr-xr-x 3,077 bytes parent folder | download | duplicates (5)
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
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
#!/usr/bin/python3

# This script demystifies C++ compiler output for CAF by
# replacing cryptic `typed_mpi<...>` templates with
# `replies_to<...>::with<...>` and `atom_constant<...>`
# with human-readable representation of the actual atom.

import sys

# decodes 6bit characters to ASCII
DECODING_TABLE = ' 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz'

# CAF type strings
ATOM_CONSTANT_SUFFIX = "caf::atom_constant<"

# `pos` points to first character after '<':
#   template_name<...>
#                 ^
# and returns the position of the closing '>'
def end_of_template(x, pos):
  open_templates = 1
  while open_templates > 0:
    if line[pos] == '<':
      open_templates += 1
    elif line[pos] == '>':
      open_templates -= 1
    pos += 1
  # exclude final '>'
  return pos - 1

def next_element(x, pos, last):
  # scan for ',' that isn't inside <...>
  while pos < last and x[pos] != ',':
    if x[pos] == '<':
      pos = end_of_template(x, pos + 1)
    else:
      pos += 1
  return pos

def atom_read(x):
  result = ""
  read_chars = ((x & 0xF000000000000000) >> 60) == 0xF 
  mask = 0x0FC0000000000000
  bitshift = 54
  while bitshift >= 0:
    if read_chars:
      result += DECODING_TABLE[(x & mask) >> bitshift]
    elif ((x & mask) >> bitshift) == 0xF:
      read_chars = True
    bitshift -= 6
    mask = mask >> 6
  return result

def decompose_type_list(x, first, last):
  res = []
  i = first
  n = next_element(x, first, last)
  while i != last:
    res.append(x[i:n])
    # skip following ','
    i = min(n + 2, last)
    n = next_element(x, i, last)
  return res

def stringify(x):
  if x.startswith(ATOM_CONSTANT_SUFFIX):
    begin = len(ATOM_CONSTANT_SUFFIX)
    end = len(x) - 1
    res = "'"
    res += atom_read(int(x[begin:end]))
    res += "'"
    return res
  return x

def stringify_list(xs):
  res = ""
  for index in range(len(xs)):
    if index > 0:
      res += ", "
    res += stringify(xs[index].strip(' '))
  return res
  

def decompose_typed_actor(x, first, last):
  needle = "caf::detail::type_list<"
  # first type list -> input types
  j = x.find(needle, first) + len(needle)
  k = end_of_template(x, j)
  inputs = decompose_type_list(x, j, k)
  # second type list -> outputs
  j = x.find(needle, k) + len(needle)
  k = end_of_template(x, j)
  outputs = decompose_type_list(x, j, k)
  # replace all 'caf::atom_constant<...>' entries in inputs
  res = "replies_to<"
  res += stringify_list(inputs)
  res += ">::with<"
  res += stringify_list(outputs)
  res += ">"
  return res


for line in sys.stdin:
  # replace "std::__1" with "std::" (Clang libc++)
  line = line.replace("std::__1", "std::")
  needle = "caf::typed_mpi<"
  idx = line.find(needle)
  while idx != -1:
    # find end of typed_actor<...>
    first = idx + len(needle)
    last = end_of_template(line, first)
    updated = decompose_typed_actor(line, first, last)
    prefix = line[:idx]
    suffix = line[last:]
    line = prefix + updated + suffix
    idx = line.find(needle, idx + len(updated))
  sys.stdout.write(line.replace("caf::", ""))