xfrule.py 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. '''*****************************************************************************
  2. AToMPM - A Tool for Multi-Paradigm Modelling
  3. Copyright (c) 2011 Eugene Syriani
  4. This file is part of AToMPM.
  5. AToMPM is free software: you can redistribute it and/or modify it under the
  6. terms of the GNU Lesser General Public License as published by the Free Software
  7. Foundation, either version 3 of the License, or (at your option) any later
  8. version.
  9. AToMPM is distributed in the hope that it will be useful, but WITHOUT ANY
  10. WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
  11. PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
  12. You should have received a copy of the GNU Lesser General Public License along
  13. with AToMPM. If not, see <http://www.gnu.org/licenses/>.
  14. *****************************************************************************'''
  15. from ..util.infinity import INFINITY
  16. from frule import FRule
  17. from ..tcore.rollbacker import Rollbacker
  18. from ..tcore.resolver import Resolver
  19. class XFRule(FRule):
  20. '''
  21. Applies the transformation on all matches found with roll-back capability.
  22. '''
  23. def __init__(self, LHS, RHS, max_iterations=INFINITY):
  24. '''
  25. Applies the transformation on all matches found with roll-back capability.
  26. @param LHS: The pre-condition pattern (LHS + NACs).
  27. @param RHS: The post-condition pattern (RHS).
  28. @param max_iterations: The maximum number of times to apply the rule.
  29. '''
  30. super(XFRule, self).__init__(LHS, RHS, max_iterations)
  31. # max_iterations=1 because no all matches have been exhausted after first application
  32. self.B = Rollbacker(condition=LHS, max_iterations=1)
  33. def packet_in(self, packet):
  34. self.exception = None
  35. self.is_success = False
  36. # Checkpoint the original packet
  37. self.B.packet_in(packet)
  38. if not self.B.is_success:
  39. self.exception = self.B.exception
  40. return packet
  41. # Match
  42. packet = self.M.packet_in(packet)
  43. if not self.M.is_success:
  44. packet = self.B.restore(packet)
  45. if self.M.exception:
  46. self.exception = self.M.exception
  47. elif self.B.exception:
  48. self.exception = self.B.exception
  49. return packet
  50. # Choose the first match
  51. packet = self.I.packet_in(packet)
  52. if not self.I.is_success:
  53. packet = self.B.restore(packet)
  54. if self.I.exception:
  55. self.exception = self.I.exception
  56. elif self.B.exception:
  57. self.exception = self.B.exception
  58. return packet
  59. while True:
  60. # Rewrite
  61. packet = self.W.packet_in(packet)
  62. if not self.W.is_success:
  63. packet = self.B.restore(packet)
  64. if self.W.exception:
  65. self.exception = self.W.exception
  66. elif self.B.exception:
  67. self.exception = self.B.exception
  68. return packet
  69. # Choose another match
  70. packet = self.I.next_in(packet)
  71. # No more iterations are left
  72. if not self.I.is_success:
  73. if self.I.exception:
  74. packet = self.B.restore(packet)
  75. if self.B.exception:
  76. self.exception = self.B.exception
  77. self.exception = self.I.exception
  78. self.is_success = False
  79. else:
  80. # Output success packet
  81. self.is_success = True
  82. return packet
  83. def next_in(self, packet):
  84. # Only one roll-back
  85. self.exception = None
  86. self.is_success = False
  87. packet = self.B.next_in(packet)
  88. if not self.B.is_success:
  89. self.exception = self.B.exception
  90. return packet
  91. class XFRule_r(XFRule):
  92. '''
  93. Applies the transformation on one match.
  94. '''
  95. def __init__(self, LHS, RHS, max_iterations=INFINITY, external_matches_only=False, custom_resolution=lambda packet: False):
  96. '''
  97. Applies the transformation on all matches found with roll-back capability.
  98. @param LHS: The pre-condition pattern (LHS + NACs).
  99. @param RHS: The post-condition pattern (RHS).
  100. @param max_iterations: The maximum number of times to apply the rule.
  101. @param external_matches_only: Resolve conflicts ignoring the matches found in this FRule.
  102. @param custom_resolution: Override the default resolution function.
  103. '''
  104. super(XFRule_r, self).__init__(LHS, RHS, max_iterations)
  105. self.R = Resolver(external_matches_only=external_matches_only,
  106. custom_resolution=custom_resolution)
  107. def packet_in(self, packet):
  108. self.exception = None
  109. self.is_success = False
  110. # Checkpoint the original packet
  111. self.B.packet_in(packet)
  112. if not self.B.is_success:
  113. self.exception = self.B.exception
  114. return packet
  115. # Match
  116. packet = self.M.packet_in(packet)
  117. if not self.M.is_success:
  118. packet = self.B.restore(packet)
  119. if self.M.exception:
  120. self.exception = self.M.exception
  121. elif self.B.exception:
  122. self.exception = self.B.exception
  123. return packet
  124. # Choose the first match
  125. packet = self.I.packet_in(packet)
  126. if not self.I.is_success:
  127. packet = self.B.restore(packet)
  128. if self.I.exception:
  129. self.exception = self.I.exception
  130. elif self.B.exception:
  131. self.exception = self.B.exception
  132. return packet
  133. while True:
  134. # Rewrite
  135. packet = self.W.packet_in(packet)
  136. if not self.W.is_success:
  137. packet = self.B.restore(packet)
  138. if self.W.exception:
  139. self.exception = self.W.exception
  140. elif self.B.exception:
  141. self.exception = self.B.exception
  142. return packet
  143. # Resolve any conflicts if necessary
  144. packet = self.R.packet_in(packet)
  145. if not self.R.is_success:
  146. self.exception = self.R.exception
  147. return packet
  148. # Choose another match
  149. packet = self.I.next_in(packet)
  150. # No more iterations are left
  151. if not self.I.is_success:
  152. if self.I.exception:
  153. packet = self.B.restore(packet)
  154. if self.B.exception:
  155. self.exception = self.B.exception
  156. self.exception = self.I.exception
  157. self.is_success = False
  158. else:
  159. # Output success packet
  160. self.is_success = True
  161. return packet