xfrule.py 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. '''This file is part of AToMPM - A Tool for Multi-Paradigm Modelling
  2. Copyright 2011 by the AToMPM team and licensed under the LGPL
  3. See COPYING.lesser and README.md in the root of this project for full details'''
  4. from ..util.infinity import INFINITY
  5. from frule import FRule
  6. from ..tcore.rollbacker import Rollbacker
  7. from ..tcore.resolver import Resolver
  8. class XFRule(FRule):
  9. '''
  10. Applies the transformation on all matches found with roll-back capability.
  11. '''
  12. def __init__(self, LHS, RHS, max_iterations=INFINITY):
  13. '''
  14. Applies the transformation on all matches found with roll-back capability.
  15. @param LHS: The pre-condition pattern (LHS + NACs).
  16. @param RHS: The post-condition pattern (RHS).
  17. @param max_iterations: The maximum number of times to apply the rule.
  18. '''
  19. super(XFRule, self).__init__(LHS, RHS, max_iterations)
  20. # max_iterations=1 because no all matches have been exhausted after first application
  21. self.B = Rollbacker(condition=LHS, max_iterations=1)
  22. def packet_in(self, packet):
  23. self.exception = None
  24. self.is_success = False
  25. # Checkpoint the original packet
  26. self.B.packet_in(packet)
  27. if not self.B.is_success:
  28. self.exception = self.B.exception
  29. return packet
  30. # Match
  31. packet = self.M.packet_in(packet)
  32. if not self.M.is_success:
  33. packet = self.B.restore(packet)
  34. if self.M.exception:
  35. self.exception = self.M.exception
  36. elif self.B.exception:
  37. self.exception = self.B.exception
  38. return packet
  39. # Choose the first match
  40. packet = self.I.packet_in(packet)
  41. if not self.I.is_success:
  42. packet = self.B.restore(packet)
  43. if self.I.exception:
  44. self.exception = self.I.exception
  45. elif self.B.exception:
  46. self.exception = self.B.exception
  47. return packet
  48. while True:
  49. # Rewrite
  50. packet = self.W.packet_in(packet)
  51. if not self.W.is_success:
  52. packet = self.B.restore(packet)
  53. if self.W.exception:
  54. self.exception = self.W.exception
  55. elif self.B.exception:
  56. self.exception = self.B.exception
  57. return packet
  58. # Choose another match
  59. packet = self.I.next_in(packet)
  60. # No more iterations are left
  61. if not self.I.is_success:
  62. if self.I.exception:
  63. packet = self.B.restore(packet)
  64. if self.B.exception:
  65. self.exception = self.B.exception
  66. self.exception = self.I.exception
  67. self.is_success = False
  68. else:
  69. # Output success packet
  70. self.is_success = True
  71. return packet
  72. def next_in(self, packet):
  73. # Only one roll-back
  74. self.exception = None
  75. self.is_success = False
  76. packet = self.B.next_in(packet)
  77. if not self.B.is_success:
  78. self.exception = self.B.exception
  79. return packet
  80. class XFRule_r(XFRule):
  81. '''
  82. Applies the transformation on one match.
  83. '''
  84. def __init__(self, LHS, RHS, max_iterations=INFINITY, external_matches_only=False, custom_resolution=lambda packet: False):
  85. '''
  86. Applies the transformation on all matches found with roll-back capability.
  87. @param LHS: The pre-condition pattern (LHS + NACs).
  88. @param RHS: The post-condition pattern (RHS).
  89. @param max_iterations: The maximum number of times to apply the rule.
  90. @param external_matches_only: Resolve conflicts ignoring the matches found in this FRule.
  91. @param custom_resolution: Override the default resolution function.
  92. '''
  93. super(XFRule_r, self).__init__(LHS, RHS, max_iterations)
  94. self.R = Resolver(external_matches_only=external_matches_only,
  95. custom_resolution=custom_resolution)
  96. def packet_in(self, packet):
  97. self.exception = None
  98. self.is_success = False
  99. # Checkpoint the original packet
  100. self.B.packet_in(packet)
  101. if not self.B.is_success:
  102. self.exception = self.B.exception
  103. return packet
  104. # Match
  105. packet = self.M.packet_in(packet)
  106. if not self.M.is_success:
  107. packet = self.B.restore(packet)
  108. if self.M.exception:
  109. self.exception = self.M.exception
  110. elif self.B.exception:
  111. self.exception = self.B.exception
  112. return packet
  113. # Choose the first match
  114. packet = self.I.packet_in(packet)
  115. if not self.I.is_success:
  116. packet = self.B.restore(packet)
  117. if self.I.exception:
  118. self.exception = self.I.exception
  119. elif self.B.exception:
  120. self.exception = self.B.exception
  121. return packet
  122. while True:
  123. # Rewrite
  124. packet = self.W.packet_in(packet)
  125. if not self.W.is_success:
  126. packet = self.B.restore(packet)
  127. if self.W.exception:
  128. self.exception = self.W.exception
  129. elif self.B.exception:
  130. self.exception = self.B.exception
  131. return packet
  132. # Resolve any conflicts if necessary
  133. packet = self.R.packet_in(packet)
  134. if not self.R.is_success:
  135. self.exception = self.R.exception
  136. return packet
  137. # Choose another match
  138. packet = self.I.next_in(packet)
  139. # No more iterations are left
  140. if not self.I.is_success:
  141. if self.I.exception:
  142. packet = self.B.restore(packet)
  143. if self.B.exception:
  144. self.exception = self.B.exception
  145. self.exception = self.I.exception
  146. self.is_success = False
  147. else:
  148. # Output success packet
  149. self.is_success = True
  150. return packet