|  | # 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) |