This repo contains code to mirror other repos. It also contains the code that is getting mirrored.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

174 lines
4.4 KiB

  1. from inspect import isclass
  2. from functools import wraps
  3. from .utils import smart_decorator
  4. from .tree import Tree
  5. class Discard(Exception):
  6. pass
  7. class Base:
  8. def _call_userfunc(self, tree):
  9. return getattr(self, tree.data, self.__default__)(tree)
  10. def __default__(self, tree):
  11. "Default operation on tree (for override)"
  12. return tree
  13. class Transformer(Base):
  14. def _transform_children(self, children):
  15. for c in children:
  16. try:
  17. yield self._transform_tree(c) if isinstance(c, Tree) else c
  18. except Discard:
  19. pass
  20. def _transform_tree(self, tree):
  21. tree = Tree(tree.data, list(self._transform_children(tree.children)))
  22. return self._call_userfunc(tree)
  23. def transform(self, tree):
  24. return self._transform_tree(tree)
  25. def __mul__(self, other):
  26. return TransformerChain(self, other)
  27. class TransformerChain(object):
  28. def __init__(self, *transformers):
  29. self.transformers = transformers
  30. def transform(self, tree):
  31. for t in self.transformers:
  32. tree = t.transform(tree)
  33. return tree
  34. def __mul__(self, other):
  35. return TransformerChain(*self.transformers + (other,))
  36. class Transformer_InPlace(Transformer):
  37. def _transform_tree(self, tree): # Cancel recursion
  38. return self._call_userfunc(tree)
  39. def transform(self, tree):
  40. for subtree in tree.iter_subtrees():
  41. subtree.children = list(self._transform_children(subtree.children))
  42. return self._transform_tree(tree)
  43. class Transformer_InPlaceRecursive(Transformer):
  44. def _transform_tree(self, tree):
  45. tree.children = list(self._transform_children(tree.children))
  46. return self._call_userfunc(tree)
  47. class Visitor(Base):
  48. "Bottom-up visitor"
  49. def visit(self, tree):
  50. for subtree in tree.iter_subtrees():
  51. self._call_userfunc(subtree)
  52. return tree
  53. class Visitor_Recursive(Base):
  54. def visit(self, tree):
  55. for child in tree.children:
  56. if isinstance(child, Tree):
  57. self.visit(child)
  58. f = getattr(self, tree.data, self.__default__)
  59. f(tree)
  60. return tree
  61. def visit_children_decor(func):
  62. @wraps(func)
  63. def inner(cls, tree):
  64. values = cls.visit_children(tree)
  65. return func(cls, values)
  66. return inner
  67. class Interpreter(object):
  68. "Top-down visitor"
  69. def visit(self, tree):
  70. return getattr(self, tree.data)(tree)
  71. def visit_children(self, tree):
  72. return [self.visit(child) if isinstance(child, Tree) else child
  73. for child in tree.children]
  74. def __getattr__(self, name):
  75. return self.__default__
  76. def __default__(self, tree):
  77. return self.visit_children(tree)
  78. def _children_args__func(f):
  79. @wraps(f)
  80. def create_decorator(_f, with_self):
  81. if with_self:
  82. def f(self, tree):
  83. return _f(self, tree.children)
  84. else:
  85. def f(args):
  86. return _f(tree.children)
  87. return f
  88. return smart_decorator(f, create_decorator)
  89. def _children_args__class(cls):
  90. def _call_userfunc(self, tree):
  91. # Assumes tree is already transformed
  92. try:
  93. f = getattr(self, tree.data)
  94. except AttributeError:
  95. return self.__default__(tree)
  96. else:
  97. return f(tree.children)
  98. cls._call_userfunc = _call_userfunc
  99. return cls
  100. def children_args(obj):
  101. decorator = _children_args__class if isclass(obj) and issubclass(obj, Base) else _children_args__func
  102. return decorator(obj)
  103. def _children_args_inline__func(f):
  104. @wraps(f)
  105. def create_decorator(_f, with_self):
  106. if with_self:
  107. def f(self, tree):
  108. return _f(self, *tree.children)
  109. else:
  110. def f(args):
  111. return _f(*tree.children)
  112. return f
  113. return smart_decorator(f, create_decorator)
  114. def _children_args_inline__class(cls):
  115. def _call_userfunc(self, tree):
  116. # Assumes tree is already transformed
  117. try:
  118. f = getattr(self, tree.data)
  119. except AttributeError:
  120. return self.__default__(tree)
  121. else:
  122. return f(*tree.children)
  123. cls._call_userfunc = _call_userfunc
  124. return cls
  125. def children_args_inline(obj):
  126. decorator = _children_args_inline__class if isclass(obj) and issubclass(obj, Base) else _children_args_inline__func
  127. return decorator(obj)