Browse Source

Added first version of dynamic traffic light (manager only)

Yentl Van Tendeloo 8 years ago
parent
commit
6a0803374f
3 changed files with 89 additions and 19 deletions
  1. 20 15
      models/SCCD_execute.alc
  2. 62 0
      models/dynamic_trafficlight.mvc
  3. 7 4
      wrappers/test_SCCD.py

+ 20 - 15
models/SCCD_execute.alc

@@ -52,11 +52,12 @@ Element function filter_exists(model : Element, set : Element, attribute_name :
 
 	return result!
 
-Element function expand_current_state(model : Element, state : String, current_states : Element):
+Element function expand_current_state(model : Element, state : String, class_data : Element):
 	// Find the hierarchy of all current states, and select those that contain the currently selected state
 	Element result
+	Element current_states
 	result = create_node()
-	current_states = set_copy(current_states)
+	current_states = set_copy(class_data["states"])
 
 	Element hierarchy
 	String deep_state
@@ -71,15 +72,19 @@ Element function expand_current_state(model : Element, state : String, current_s
 
 	return result!
 
-Element function expand_initial_state(model : Element, state : String):
+Element function expand_initial_state(model : Element, state : String, class_data : Element):
 	String t
 	t = read_type(model, state)
 	if (t == "SCCD/CompositeState"):
 		// Recurse further in the composite
-		return expand_composite_state(model, state)!
+		return expand_composite_state(model, state, class_data)!
 	elif (t == "SCCD/ParallelState"):
 		// Split up all components
-		return expand_parallel_state(model, state)!
+		return expand_parallel_state(model, state, class_data)!
+	elif (t == "SCCD/HistoryState"):
+		// Reset the history
+		// This is not really an initial state, but it is called in exactly the same places
+		return class_data["history"][state]!
 	else:
 		// Probably just an atomic, so return this one only
 		Element result
@@ -87,7 +92,7 @@ Element function expand_initial_state(model : Element, state : String):
 		set_add(result, state)
 		return result!
 
-Element function expand_composite_state(model : Element, composite_state : String):
+Element function expand_composite_state(model : Element, composite_state : String, class_data : Element):
 	// Resolve all initial states from a single composite state
 	String initial
 
@@ -95,9 +100,9 @@ Element function expand_composite_state(model : Element, composite_state : Strin
 	initial = set_pop(filter(model, allAssociationDestinations(model, composite_state, "SCCD/composite_children"), "isInitial", True))
 
 	// Expand the initial state, depending on what it is
-	return expand_initial_state(model, initial)!
+	return expand_initial_state(model, initial, class_data)!
 
-Element function expand_parallel_state(model : Element, parallel_state : String):
+Element function expand_parallel_state(model : Element, parallel_state : String, class_data : Element):
 	// Resolve all initial states from a single parallel state
 	Element children
 	Element result
@@ -107,7 +112,7 @@ Element function expand_parallel_state(model : Element, parallel_state : String)
 	result = create_node()
 
 	while (read_nr_out(children) > 0):
-		set_merge(result, expand_initial_state(model, set_pop(children)))
+		set_merge(result, expand_initial_state(model, set_pop(children), class_data))
 
 	return result!
 
@@ -129,7 +134,7 @@ Void function start_class(model : Element, data : Element, class : String, ident
 	String initial_state
 	// Should only be one behaviour linked to it!
 	initial_state = set_pop(allAssociationDestinations(model, class, "SCCD/behaviour"))
-	dict_add(class_handle, "states", expand_initial_state(model, initial_state))
+	dict_add(class_handle, "states", expand_initial_state(model, initial_state, class_handle))
 
 	// Initialize history for all composite states
 	Element history
@@ -141,7 +146,7 @@ Void function start_class(model : Element, data : Element, class : String, ident
 	cstates = allInstances(model, "SCCD/CompositeState")
 	while (read_nr_out(cstates) > 0):
 		cstate = set_pop(cstates)
-		dict_add(history, cstate, expand_initial_state(model, cstate))
+		dict_add(history, cstate, expand_initial_state(model, cstate, class_handle))
 
 	// Add all attributes
 	Element attributes
@@ -324,8 +329,8 @@ Element function execute_transition(model : Element, data : Element, class : Str
 	// Find new set of states
 	Element target_states
 	Element source_states
-	source_states = expand_current_state(model, readAssociationSource(model, transition), data["classes"][class]["states"])
-	target_states = expand_initial_state(model, readAssociationDestination(model, transition))
+	source_states = expand_current_state(model, readAssociationSource(model, transition), data["classes"][class])
+	target_states = expand_initial_state(model, readAssociationDestination(model, transition), data["classes"][class])
 
 	execute_actions(model, source_states, target_states, data["classes"][class])
 
@@ -368,7 +373,7 @@ Boolean function step_class(model : Element, data : Element, class : String):
 
 				// When leaving an orthogonal component, we must also pop all related states that might be processed in the future!
 				Element leaving
-				leaving = expand_current_state(model, current_state, data["classes"][class]["states"])
+				leaving = expand_current_state(model, current_state, data["classes"][class])
 				set_difference(states, leaving)
 
 				transitioned = True
@@ -548,7 +553,7 @@ Element function get_actions_to_execute(model : Element, source_states : Element
 
 				// Also update the history of this state, which will be important if we have a history state later on
 				if (read_type(model, state) == "SCCD/CompositeState"):
-					dict_overwrite(class_data["history"], state, expand_current_state(model, state, class_data["states"]))
+					dict_overwrite(class_data["history"], state, expand_current_state(model, state, class_data))
 
 	// Add hierarchy_targets actions
 	// Clear visited, just to be safe, though it should not matter

+ 62 - 0
models/dynamic_trafficlight.mvc

@@ -0,0 +1,62 @@
+include "primitives.alh"
+
+Diagram dynamic_trafficlight {
+    name = "Dynamic Traffic Light"
+    author = "Yentl Van Tendeloo"
+}
+
+Class manager {
+    name = "Manager"
+    default = True
+    constructor_body = $
+            Void function constructor(attributes : Element, parameters : Element):
+                dict_add(attributes, "counter", 0)
+                return !
+        $
+
+    {behaviour} CompositeState manager_root {
+        name = "root"
+        isInitial = True
+        {composite_children} BasicState manager_root_start {
+            name = "start"
+            isInitial = True
+        }
+    }
+}
+
+transition (manager_root_start, manager_root_start) {
+    name = "create"
+    event = "create"
+
+    {transition_raises} Raise {
+        scope = "cd"
+        event = "create_instance"
+        parameter = $
+                Element function raise(attributes : Element, parameters : Element):
+                    Element result
+                    result = create_node()
+                    list_append(result, "TrafficLight")
+                    list_append(result, attributes["counter"])
+                    list_append(result, read_root())
+                    dict_overwrite(attributes, "counter", integer_addition(attributes["counter"], 1))
+                    return result!
+            $
+    }
+}
+
+transition (manager_root_start, manager_root_start) {
+    name = "delete"
+    event = "delete"
+
+    {transition_raises} Raise {
+        scope = "cd"
+        event = "delete_instance"
+        parameter = $
+                Element function raise(attributes : Element, parameters : Element):
+                    Element result
+                    result = create_node()
+                    list_append(result, parameters["id"])
+                    return result!
+            $
+    }
+}

+ 7 - 4
wrappers/test_SCCD.py

@@ -5,18 +5,21 @@ from modelverse import *
 init()
 login("admin", "admin")
 
+# Assume that we don't change the SCCD MM
 try:
     model_add("SCCD", "SimpleClassDiagrams", open("models/SCCD.mvc", 'r').read())
-    model_add("my_SCCD", "SCCD", open("integration/code/minimal_SCCD.mvc", 'r').read())
 except ModelExists:
     pass
 
-if "SCCD_execute" in [i[0] for i in model_list()]:
-    print("Detected previous version; removing")
-    model_delete("SCCD_execute")
+# Update the model of the traffic light
+if "my_SCCD" in [i[0] for i in model_list()]:
+    model_delete("my_SCCD")
+model_add("my_SCCD", "SCCD", open("models/dynamic_trafficlight.mvc", 'r').read())
 
+# Add SCCD execution semantics
 transformation_add_AL({"SCCD": "SCCD"}, {}, "SCCD_execute", open("models/SCCD_execute.alc", 'r').read())
 
+# Execute it, while interacting through the console
 def callback(inp):
     print(inp)
     return raw_input()