瀏覽代碼

a transition can no longer exit an ancestor parallel state

Simon Van Mierlo 9 年之前
父節點
當前提交
c7519f4b6b
共有 1 個文件被更改,包括 75 次插入73 次删除
  1. 75 73
      src/python_sccd/python_sccd_compiler/path_calculator.py

+ 75 - 73
src/python_sccd/python_sccd_compiler/path_calculator.py

@@ -2,80 +2,82 @@ from sccd.compiler.compiler_exceptions import *
 from sccd.compiler.visitor import Visitor
 
 class PathCalculator(Visitor):
-	""" Computes the states that must be exited and entered for a specific transition if the system is to make
-		that transition. 
-	"""
-	
-	def visit_ClassDiagram(self, class_diagram): 
-		for c in class_diagram.classes :
-			c.accept(self)
+    """ Computes the states that must be exited and entered for a specific transition if the system is to make
+        that transition. 
+    """
+    
+    def visit_ClassDiagram(self, class_diagram): 
+        for c in class_diagram.classes :
+            c.accept(self)
 
-	def visit_Class(self, c):
-		if c.statechart:
-			c.statechart.accept(self)
-		
-	def visit_StateChart(self, statechart):
-		for node in statechart.basics + statechart.composites:
-			node.accept(self)
-					 
-	def visit_StateChartNode(self, node):
-		for transition in node.transitions :
-			transition.accept(self)
-			
-	def visit_StateChartTransition(self, transition):
-		#Find the scope of the transition (lowest common proper ancestor)
-		#TODO: Could it be made more efficient if we calculated the LCA from the source node and just one of the target nodes?
-		LCA = self.calculateLCA(transition)
-		
-		if LCA == None:
-			#raise CompilerException("Transision with source " + transition.parent_node.name + " and target " + transition.target_nodes + " has no lowest common ancestor node.")
-			raise CompilerException("Transision with source '" + transition.parent_node.name + "' and target + '" + transition.target_string + "' has no lowest common ancestor node.")
+    def visit_Class(self, c):
+        if c.statechart:
+            c.statechart.accept(self)
+        
+    def visit_StateChart(self, statechart):
+        for node in statechart.basics + statechart.composites:
+            node.accept(self)
+                     
+    def visit_StateChartNode(self, node):
+        for transition in node.transitions :
+            transition.accept(self)
+            
+    def visit_StateChartTransition(self, transition):
+        #Find the scope of the transition (lowest common proper ancestor)
+        #TODO: Could it be made more efficient if we calculated the LCA from the source node and just one of the target nodes?
+        LCA = self.calculateLCA(transition)
+        
+        if LCA == None:
+            #raise CompilerException("Transision with source " + transition.parent_node.name + " and target " + transition.target_nodes + " has no lowest common ancestor node.")
+            raise CompilerException("Transision with source '" + transition.parent_node.name + "' and target '" + transition.target_string + "' has no lowest common ancestor node.")
 
-		#Calculate exit nodes
-		transition.exit_nodes = [transition.parent_node]
-		for node in transition.parent_node.getAncestors() :
-			if (node == LCA) :
-				break
-			transition.exit_nodes.append(node)
-	   
-		#Calculate enter nodes
-		transition.enter_nodes = []
-		
-		#we then add the branching paths to the other nodes
-		for target_node in transition.target.target_nodes :
-			to_append_list = [(target_node, True)]
-			for anc in target_node.getAncestors() :
-				if anc == LCA : #If we reach the LCA in the ancestor hierarchy we break
-					break;
-				to_add = True;  #boolean value to see if the current ancestor should be added to the result
-				for enter_node_entry in transition.enter_nodes :
-					if anc == enter_node_entry[0] :
-						to_add = False #If we reach an ancestor in the hierarchy that is already listed as enter node, we don't add and break
-						break
-				if to_add:
-					to_append_list.append((anc, False)) #Only the first from the ancestor list should get True
-				else :
-					break
-					
-			to_append_list.reverse() #the enter sequence should be in the reverse order of the ancestor hierarchy
-			transition.enter_nodes.extend(to_append_list)
+        #Calculate exit nodes
+        transition.exit_nodes = [transition.parent_node]
+        for node in transition.parent_node.getAncestors() :
+            if (node == LCA) :
+                break
+            transition.exit_nodes.append(node)
+            if node.is_parallel_state:
+                raise CompilerException("Transision with source '" + transition.parent_node.name + "' and target '" + transition.target_string + "' exits a parallel component.")
+       
+        #Calculate enter nodes
+        transition.enter_nodes = []
+        
+        #we then add the branching paths to the other nodes
+        for target_node in transition.target.target_nodes :
+            to_append_list = [(target_node, True)]
+            for anc in target_node.getAncestors() :
+                if anc == LCA : #If we reach the LCA in the ancestor hierarchy we break
+                    break;
+                to_add = True;  #boolean value to see if the current ancestor should be added to the result
+                for enter_node_entry in transition.enter_nodes :
+                    if anc == enter_node_entry[0] :
+                        to_add = False #If we reach an ancestor in the hierarchy that is already listed as enter node, we don't add and break
+                        break
+                if to_add:
+                    to_append_list.append((anc, False)) #Only the first from the ancestor list should get True
+                else :
+                    break
+                    
+            to_append_list.reverse() #the enter sequence should be in the reverse order of the ancestor hierarchy
+            transition.enter_nodes.extend(to_append_list)
 
-		# Calculate arena
-		current = LCA
-		while not current.is_composite:
-			current = current.parent
-		transition.arena = current
+        # Calculate arena
+        current = LCA
+        while not current.is_composite:
+            current = current.parent
+        transition.arena = current
 
-	def calculateLCA(self, transition):
-		"""
-		Calculates the lowest common ancestor of a transition
-		""" 
-		for anc in transition.parent_node.getAncestors() :
-			all_descendants = True 
-			for node in transition.target.getNodes() :
-				if not node.isDescendantOf(anc) :
-					all_descendants = False
-					break
-			if all_descendants :
-				return anc
-		return None
+    def calculateLCA(self, transition):
+        """
+        Calculates the lowest common ancestor of a transition
+        """ 
+        for anc in transition.parent_node.getAncestors() :
+            all_descendants = True 
+            for node in transition.target.getNodes() :
+                if not node.isDescendantOf(anc) :
+                    all_descendants = False
+                    break
+            if all_descendants :
+                return anc
+        return None