xsrule.py 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  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 srule import SRule
  17. from ..tcore.rollbacker import Rollbacker
  18. from ..tcore.resolver import Resolver
  19. class XSRule(SRule):
  20. '''
  21. Applies the transformation as long as matches can be 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 match.
  29. '''
  30. super(XSRule, 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()
  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()
  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()
  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. # Rule has been applied once, so it's a success anyway
  70. self.is_success = True
  71. if self.I.iterations == self.I.max_iterations:
  72. return packet
  73. # Re-Match
  74. packet = self.M.packet_in(packet)
  75. if not self.M.is_success:
  76. self.exception = self.M.exception
  77. return packet
  78. # Choose another match
  79. packet = self.I.next_in(packet)
  80. # No more iterations are left
  81. if not self.I.is_success:
  82. if self.I.exception:
  83. packet = self.B.restore()
  84. if self.B.exception:
  85. self.exception = self.B.exception
  86. self.exception = self.I.exception
  87. self.is_success = False
  88. return packet
  89. def next_in(self, packet):
  90. # Only one roll-back
  91. self.exception = None
  92. self.is_success = False
  93. packet = self.B.next_in(packet)
  94. if not self.B.is_success:
  95. self.exception = self.B.exception
  96. return packet
  97. class XSRule_r(XSRule):
  98. '''
  99. Applies the transformation as long as matches can be found with roll-back capability.
  100. '''
  101. def __init__(self, LHS, RHS, max_iterations=INFINITY, external_matches_only=False, custom_resolution=lambda packet: False):
  102. '''
  103. Applies the transformation as long as matches can be found with roll-back capability.
  104. @param LHS: The pre-condition pattern (LHS + NACs).
  105. @param RHS: The post-condition pattern (RHS).
  106. @param max_iterations: The maximum number of times to apply the rule.
  107. @param external_matches_only: Resolve conflicts ignoring the matches found in this FRule.
  108. @param custom_resolution: Override the default resolution function.
  109. '''
  110. super(XSRule_r, self).__init__(LHS, RHS, max_iterations)
  111. self.R = Resolver(external_matches_only=external_matches_only,
  112. custom_resolution=custom_resolution)
  113. def packet_in(self, packet):
  114. self.exception = None
  115. self.is_success = False
  116. # Checkpoint the original packet
  117. self.B.packet_in(packet)
  118. if not self.B.is_success:
  119. self.exception = self.B.exception
  120. return packet
  121. # Match
  122. packet = self.M.packet_in(packet)
  123. if not self.M.is_success:
  124. packet = self.B.restore()
  125. if self.M.exception:
  126. self.exception = self.M.exception
  127. elif self.B.exception:
  128. self.exception = self.B.exception
  129. return packet
  130. # Choose the first match
  131. packet = self.I.packet_in(packet)
  132. if not self.I.is_success:
  133. packet = self.B.restore()
  134. if self.I.exception:
  135. self.exception = self.I.exception
  136. elif self.B.exception:
  137. self.exception = self.B.exception
  138. return packet
  139. while True:
  140. # Rewrite
  141. packet = self.W.packet_in(packet)
  142. if not self.W.is_success:
  143. packet = self.B.restore()
  144. if self.W.exception:
  145. self.exception = self.W.exception
  146. elif self.B.exception:
  147. self.exception = self.B.exception
  148. return packet
  149. # Resolve any conflicts if necessary
  150. packet = self.R.packet_in(packet)
  151. if not self.R.is_success:
  152. self.exception = self.R.exception
  153. return packet
  154. # Rule has been applied once, so it's a success anyway
  155. self.is_success = True
  156. if self.I.iterations == self.I.max_iterations:
  157. return packet
  158. # Re-Match
  159. packet = self.M.packet_in(packet)
  160. if not self.M.is_success:
  161. self.exception = self.M.exception
  162. return packet
  163. # Choose another match
  164. packet = self.I.next_in(packet)
  165. # No more iterations are left
  166. if not self.I.is_success:
  167. if self.I.exception:
  168. packet = self.B.restore()
  169. if self.B.exception:
  170. self.exception = self.B.exception
  171. self.exception = self.I.exception
  172. self.is_success = False
  173. return packet