|  | # Automatically formatted with yapf (https://github.com/google/yapf) | 
|  | """Utility functions for creating and manipulating LLVM 'opt' NPM pipeline objects.""" | 
|  |  | 
|  |  | 
|  | def fromStr(pipeStr): | 
|  | """Create pipeline object from string representation.""" | 
|  | stack = [] | 
|  | curr = [] | 
|  | tok = '' | 
|  | kind = '' | 
|  | for c in pipeStr: | 
|  | if c == ',': | 
|  | if tok != '': | 
|  | curr.append([None, tok]) | 
|  | tok = '' | 
|  | elif c == '(': | 
|  | stack.append([kind, curr]) | 
|  | kind = tok | 
|  | curr = [] | 
|  | tok = '' | 
|  | elif c == ')': | 
|  | if tok != '': | 
|  | curr.append([None, tok]) | 
|  | tok = '' | 
|  | oldKind = kind | 
|  | oldCurr = curr | 
|  | [kind, curr] = stack.pop() | 
|  | curr.append([oldKind, oldCurr]) | 
|  | else: | 
|  | tok += c | 
|  | if tok != '': | 
|  | curr.append([None, tok]) | 
|  | return curr | 
|  |  | 
|  |  | 
|  | def toStr(pipeObj): | 
|  | """Create string representation of pipeline object.""" | 
|  | res = '' | 
|  | lastIdx = len(pipeObj) - 1 | 
|  | for i, c in enumerate(pipeObj): | 
|  | if c[0]: | 
|  | res += c[0] + '(' | 
|  | res += toStr(c[1]) | 
|  | res += ')' | 
|  | else: | 
|  | res += c[1] | 
|  | if i != lastIdx: | 
|  | res += ',' | 
|  | return res | 
|  |  | 
|  |  | 
|  | def count(pipeObj): | 
|  | """Count number of passes (pass-managers excluded) in pipeline object.""" | 
|  | cnt = 0 | 
|  | for c in pipeObj: | 
|  | if c[0]: | 
|  | cnt += count(c[1]) | 
|  | else: | 
|  | cnt += 1 | 
|  | return cnt | 
|  |  | 
|  |  | 
|  | def split(pipeObj, splitIndex): | 
|  | """Create two new pipeline objects by splitting pipeObj in two directly after pass with index splitIndex.""" | 
|  | def splitInt(src, splitIndex, dstA, dstB, idx): | 
|  | for s in src: | 
|  | if s[0]: | 
|  | dstA2 = [] | 
|  | dstB2 = [] | 
|  | idx = splitInt(s[1], splitIndex, dstA2, dstB2, idx) | 
|  | dstA.append([s[0], dstA2]) | 
|  | dstB.append([s[0], dstB2]) | 
|  | else: | 
|  | if idx <= splitIndex: | 
|  | dstA.append([None, s[1]]) | 
|  | else: | 
|  | dstB.append([None, s[1]]) | 
|  | idx += 1 | 
|  | return idx | 
|  |  | 
|  | listA = [] | 
|  | listB = [] | 
|  | splitInt(pipeObj, splitIndex, listA, listB, 0) | 
|  | return [listA, listB] | 
|  |  | 
|  |  | 
|  | def remove(pipeObj, removeIndex): | 
|  | """Create new pipeline object by removing pass with index removeIndex from pipeObj.""" | 
|  | def removeInt(src, removeIndex, dst, idx): | 
|  | for s in src: | 
|  | if s[0]: | 
|  | dst2 = [] | 
|  | idx = removeInt(s[1], removeIndex, dst2, idx) | 
|  | dst.append([s[0], dst2]) | 
|  | else: | 
|  | if idx != removeIndex: | 
|  | dst.append([None, s[1]]) | 
|  | idx += 1 | 
|  | return idx | 
|  |  | 
|  | dst = [] | 
|  | removeInt(pipeObj, removeIndex, dst, 0) | 
|  | return dst | 
|  |  | 
|  |  | 
|  | def copy(srcPipeObj): | 
|  | """Create copy of pipeline object srcPipeObj.""" | 
|  | def copyInt(dst, src): | 
|  | for s in src: | 
|  | if s[0]: | 
|  | dst2 = [] | 
|  | copyInt(dst2, s[1]) | 
|  | dst.append([s[0], dst2]) | 
|  | else: | 
|  | dst.append([None, s[1]]) | 
|  |  | 
|  | dstPipeObj = [] | 
|  | copyInt(dstPipeObj, srcPipeObj) | 
|  | return dstPipeObj | 
|  |  | 
|  |  | 
|  | def prune(srcPipeObj): | 
|  | """Create new pipeline object by removing empty pass-managers (those with count = 0) from srcPipeObj.""" | 
|  | def pruneInt(dst, src): | 
|  | for s in src: | 
|  | if s[0]: | 
|  | if count(s[1]): | 
|  | dst2 = [] | 
|  | pruneInt(dst2, s[1]) | 
|  | dst.append([s[0], dst2]) | 
|  | else: | 
|  | dst.append([None, s[1]]) | 
|  |  | 
|  | dstPipeObj = [] | 
|  | pruneInt(dstPipeObj, srcPipeObj) | 
|  | return dstPipeObj | 
|  |  | 
|  |  | 
|  | if __name__ == "__main__": | 
|  | import unittest | 
|  |  | 
|  | class Test(unittest.TestCase): | 
|  | def test_0(self): | 
|  | pipeStr = 'a,b,A(c,B(d,e),f),g' | 
|  | pipeObj = fromStr(pipeStr) | 
|  |  | 
|  | self.assertEqual(7, count(pipeObj)) | 
|  |  | 
|  | self.assertEqual(pipeObj, pipeObj) | 
|  | self.assertEqual(pipeObj, prune(pipeObj)) | 
|  | self.assertEqual(pipeObj, copy(pipeObj)) | 
|  |  | 
|  | self.assertEqual(pipeStr, toStr(pipeObj)) | 
|  | self.assertEqual(pipeStr, toStr(prune(pipeObj))) | 
|  | self.assertEqual(pipeStr, toStr(copy(pipeObj))) | 
|  |  | 
|  | [pipeObjA, pipeObjB] = split(pipeObj, 3) | 
|  | self.assertEqual('a,b,A(c,B(d))', toStr(pipeObjA)) | 
|  | self.assertEqual('A(B(e),f),g', toStr(pipeObjB)) | 
|  |  | 
|  | self.assertEqual('b,A(c,B(d,e),f),g', toStr(remove(pipeObj, 0))) | 
|  | self.assertEqual('a,b,A(c,B(d,e),f)', toStr(remove(pipeObj, 6))) | 
|  |  | 
|  | pipeObjC = remove(pipeObj, 4) | 
|  | self.assertEqual('a,b,A(c,B(d),f),g', toStr(pipeObjC)) | 
|  | pipeObjC = remove(pipeObjC, 3) | 
|  | self.assertEqual('a,b,A(c,B(),f),g', toStr(pipeObjC)) | 
|  | pipeObjC = prune(pipeObjC) | 
|  | self.assertEqual('a,b,A(c,f),g', toStr(pipeObjC)) | 
|  |  | 
|  | unittest.main() | 
|  | exit(0) |