Browse Source

Patched old tests

Yentl Van Tendeloo 6 years ago
parent
commit
a1d0f48d3b

+ 297 - 0
integration/code/CBD_mapper.mvc

@@ -0,0 +1,297 @@
+include "primitives.alh"
+include "modelling.alh"
+include "object_operations.alh"
+
+Composite schedule {
+    {Contains} Success success {}
+    {Contains} Failure failure {}
+
+    {Contains} ForAll update_blocks {
+        LHS {
+            Pre_abstract/Block pre_update_0 {
+                label = "0"
+            }
+            Pre_rendered/Group pre_update_1 {
+                label = "1"
+            }
+            Pre_TracabilityLink (pre_update_0, pre_update_1){
+                label = "2"
+            }
+        }
+        RHS {
+            Post_abstract/Block post_update_0 {
+                label = "0"
+            }
+            Post_rendered/Group post_update_1 {
+                label = "1"
+                value___asid = $
+                    String function value(model : Element, name : String, mapping : Element):
+                        // Update the mapping!
+                        if (read_nr_out(string_split(mapping["0"], "/")) > 1):
+                            return list_read(string_split(mapping["0"], "/"), 1)!
+                        else:
+                            return mapping["0"]!
+                    $
+                value_x = $
+                    Integer function value(model : Element, name : String, mapping : Element):
+                        return read_attribute(model, name, "x")!
+                    $
+                value_y = $
+                    Integer function value(model : Element, name : String, mapping : Element):
+                        return read_attribute(model, name, "y")!
+                    $
+            }
+            Post_TracabilityLink (post_update_0, post_update_1){
+                label = "2"
+            }
+        }
+    }
+
+    {Contains} ForAll render_blocks {
+        LHS {
+            Pre_abstract/Block pre_block_0 {
+                label = "0"
+            }
+
+            constraint = $
+                Boolean function constraint(model : Element, mapping : Element):
+                    Element trace_links
+                    trace_links = allOutgoingAssociationInstances(model, mapping["0"], "TracabilityLink")
+                    if (read_nr_out(trace_links) > 0):
+                        log("Block already connected; ignoring!")
+                        return False!
+                    else:
+                        return True!
+                $
+        }
+        RHS {
+            Post_abstract/Block post_block_0 {
+                label = "0"
+            }
+            Post_rendered/Group post_block_1 {
+                label = "1"
+                value___asid = $
+                    String function value(model : Element, name : String, mapping : Element):
+                        if (list_len(string_split(mapping["0"], "/")) > 1):
+                            return list_read(string_split(mapping["0"], "/"), 1)!
+                        else:
+                            return mapping["0"]!
+                    $
+                value_x = $
+                    Integer function value(model : Element, name : String, mapping : Element):
+                        return 0!
+                    $
+                value_y = $
+                    Integer function value(model : Element, name : String, mapping : Element):
+                        return 0!
+                    $
+            }
+            Post_rendered/Rectangle post_block_2 {
+                label = "2"
+                value_x = $
+                    Integer function value(model : Element, name : String, mapping : Element):
+                        return 0!
+                    $
+                value_y = $
+                    Integer function value(model : Element, name : String, mapping : Element):
+                        return 0!
+                    $
+                value_width = $
+                    Integer function value(model : Element, name : String, mapping : Element):
+                        return 30!
+                    $
+                value_height = $
+                    Integer function value(model : Element, name : String, mapping : Element):
+                        return 30!
+                    $
+                value_lineWidth = $
+                    Integer function value(model : Element, name : String, mapping : Element):
+                        return 2!
+                    $
+                value_lineColour = $
+                    String function value(model : Element, name : String, mapping : Element):
+                        return "black"!
+                    $
+                value_fillColour = $
+                    String function value(model : Element, name : String, mapping : Element):
+                        return "white"!
+                    $
+            }
+            Post_rendered/Text post_block_3 {
+                label = "3"
+                value_x = $
+                    Integer function value(model : Element, name : String, mapping : Element):
+                        return 10!
+                    $
+                value_y = $
+                    Integer function value(model : Element, name : String, mapping : Element):
+                        return 10!
+                    $
+                value_lineWidth = $
+                    Integer function value(model : Element, name : String, mapping : Element):
+                        return 1!
+                    $
+                value_lineColour = $
+                    String function value(model : Element, name : String, mapping : Element):
+                        return "black"!
+                    $
+                value_text = $
+                    String function value(model : Element, name : String, mapping : Element):
+                        String type
+                        type = read_type(model, mapping["0"])
+                        if (type == "abstract/AdditionBlock"):
+                            return "+"!
+                        elif (type == "abstract/NegatorBlock"):
+                            return "-"!
+                        elif (type == "abstract/ConstantBlock"):
+                            return "c"!
+                        elif (type == "abstract/MultiplyBlock"):
+                            return "*"!
+                        elif (type == "abstract/InverseBlock"):
+                            return "/"!
+                        elif (type == "abstract/DerivatorBlock"):
+                            return "d/dx"!
+                        elif (type == "abstract/IntegratorBlock"):
+                            return "1/s"!
+                        elif (type == "abstract/DelayBlock"):
+                            return "DELAY"!
+                        elif (type == "abstract/ProbeBlock"):
+                            return "PROBE"!
+                        else:
+                            return ("Unknown type: " + type)!
+                    $
+            }
+            Post_rendered/contains (post_block_1, post_block_2) {
+                label = "4"
+            }
+            Post_rendered/contains (post_block_1, post_block_3) {
+                label = "5"
+            }
+
+            Post_TracabilityLink (post_block_0, post_block_1) {
+                label = "6"
+            }
+        }
+    }
+
+    {Contains} ForAll remove_connections {
+        LHS {
+            Pre_rendered/Line {
+                label = "0"
+            }
+        }
+        RHS {
+        }
+    }
+
+    {Contains} ForAll render_connections {
+        LHS {
+            Pre_abstract/Block pre_conn_0 {
+                label = "0"
+            }
+
+            Pre_abstract/Block pre_conn_1 {
+                label = "1"
+            }
+
+            Pre_abstract/Link (pre_conn_0, pre_conn_1){
+                label = "2"
+            }
+
+            Pre_rendered/Group pre_conn_3 {
+                label = "3"
+            }
+
+            Pre_rendered/Group pre_conn_4 {
+                label = "4"
+            }
+
+            Pre_TracabilityLink (pre_conn_0, pre_conn_3) {
+                label = "5"
+            }
+            Pre_TracabilityLink (pre_conn_1, pre_conn_4) {
+                label = "6"
+            }
+        }
+        RHS {
+            Post_abstract/Block post_conn_0 {
+                label = "0"
+            }
+
+            Post_abstract/Block post_conn_1 {
+                label = "1"
+            }
+
+            Post_abstract/Link (post_conn_0, post_conn_1){
+                label = "2"
+            }
+
+            Post_rendered/Group post_conn_3 {
+                label = "3"
+            }
+
+            Post_rendered/Group post_conn_4 {
+                label = "4"
+            }
+
+            Post_TracabilityLink (post_conn_0, post_conn_3) {
+                label = "5"
+            }
+            Post_TracabilityLink (post_conn_1, post_conn_4) {
+                label = "6"
+            }
+
+            Post_rendered/Line {
+                label = "7"
+                value___asid = $
+                    String function value(model : Element, name : String, mapping : Element):
+                        if (list_len(string_split(mapping["2"], "/")) > 1):
+                            return list_read(string_split(mapping["2"], "/"), 1)!
+                        else:
+                            return mapping["2"]!
+                    $
+                value_x = $
+                    Integer function value(model : Element, name : String, mapping : Element):
+                        return read_attribute(model, mapping["3"], "x")!
+                    $
+                value_y = $
+                    Integer function value(model : Element, name : String, mapping : Element):
+                        return read_attribute(model, mapping["3"], "y")!
+                    $
+                value_lineWidth = $
+                    Integer function value(model : Element, name : String, mapping : Element):
+                        return 1!
+                    $
+                value_lineColour = $
+                    String function value(model : Element, name : String, mapping : Element):
+                        if (read_type(model, name) == "ICLink"):
+                            return "red"!
+                        else:
+                            return "black"!
+                    $
+                value_targetX = $
+                    Integer function value(model : Element, name : String, mapping : Element):
+                        return read_attribute(model, mapping["4"], "x")!
+                    $
+                value_targetY = $
+                    Integer function value(model : Element, name : String, mapping : Element):
+                        return read_attribute(model, mapping["4"], "y")!
+                    $
+            }
+        }
+    }
+}
+
+Initial (schedule, update_blocks) {}
+
+OnSuccess (update_blocks, render_blocks) {}
+OnFailure (update_blocks, render_blocks) {}
+
+OnSuccess (render_blocks, remove_connections) {}
+OnFailure (render_blocks, remove_connections) {}
+
+OnSuccess (remove_connections, render_connections) {}
+OnFailure (remove_connections, render_connections) {}
+
+OnSuccess (render_connections, success) {}
+OnFailure (render_connections, success) {}

+ 72 - 0
integration/code/MM_rendered_graphical.mvc

@@ -0,0 +1,72 @@
+include "primitives.alh"
+
+SimpleAttribute Natural {
+    name = "Natural"
+}
+SimpleAttribute String {
+    name = "String"
+}
+
+Class GraphicalElement {
+    name = "GraphicalElement"
+    x : Natural
+    y : Natural
+    __asid? : String
+}
+
+Class Group : GraphicalElement {
+    name = "Group"
+}
+
+Class LineElement : GraphicalElement {
+    name = "LineElement"
+    lineWidth : Natural
+    lineColour : String
+}
+
+Class Text : LineElement {
+    name = "Text"
+    text : String
+}
+
+Class Line : LineElement {
+    name = "Line"
+    targetX : Natural
+    targetY : Natural
+}
+
+Class Shape : LineElement {
+    name = "Shape"
+    fillColour : String
+    width : Natural
+    height : Natural
+}
+
+Class Figure : GraphicalElement {
+    name = "Figure"
+    width : Natural
+    height : Natural
+}
+
+Class SVG {
+    name = "SVG"
+    data : String
+}
+
+Class Rectangle : Shape {
+    name = "Rectangle"
+}
+
+Class Ellipse : Shape {
+    name = "Ellipse"
+}
+
+Association contains (Group, GraphicalElement) {
+    name = "contains"
+}
+Association renders (Figure, SVG) {
+    name = "renders"
+    source_lower_cardinality = 1
+    target_lower_cardinality = 1
+    target_upper_cardinality = 1
+}

+ 141 - 0
integration/code/SCCD.mvc

@@ -0,0 +1,141 @@
+include "primitives.alh"
+include "object_operations.alh"
+include "modelling.alh"
+
+SimpleAttribute Action {
+    name = "Action"
+}
+SimpleAttribute Boolean {
+    name = "Boolean"
+}
+SimpleAttribute String {
+    name = "String"
+}
+SimpleAttribute Natural {
+    name = "Natural"
+}
+
+Class Diagram{
+    name = "Diagram"
+    name : String
+    author : String
+    description : String
+    lower_cardinality = 1
+    upper_cardinality = 1
+}
+
+Class Class{
+    name = "Class"
+    name : String
+    constructor_body? : Action
+    destructor? : Action
+    default : Boolean
+    external : Boolean
+}
+
+Association diagram_classes(Diagram, Class){
+    name = "diagram_classes"
+    target_lower_cardinality = 1
+}
+
+Class Attribute{
+    name = "Attribute"
+    name : String
+}
+Association class_attributes(Class, Attribute){
+    name = "class_attributes"
+}
+
+Class Method{
+    name = "Method"
+    name : String
+    body : Action
+}
+
+Association association(Class, Class){
+    name = "association"
+    name : String
+    source_upper_cardinality = 1
+}
+
+Association inheritance(Class, Class){
+    name = "inheritance"
+    priority ?: Natural
+    source_upper_cardinality = 1
+}
+
+Class State{
+    name = "State"
+    name : String
+}
+
+Class BasicState : State{
+    name = "BasicState"
+    isInitial : Boolean
+    onEntryScript? : Action
+    onExitScript? : Action
+}
+
+Class Raise{
+    name = "Raise"
+    event : String
+    scope? : String
+    target? : String
+    parameter? : Action
+}
+Association onEntryRaise (BasicState, Raise) {
+    name = "onEntryRaise"
+}
+Association onExitRaise (BasicState, Raise) {
+    name = "onExitRaise"
+}
+
+Association behaviour(Class, BasicState){
+    name = "behaviour"
+    target_lower_cardinality = 1
+    target_upper_cardinality = 1
+}
+
+Association state_onentry_raises(BasicState, Raise){
+    name = "state_onentry_raises"
+    order : Natural
+}
+Association state_onexit_raises(BasicState, Raise){
+    name = "state_onexit_raises"
+    order : Natural
+}
+
+Class CompositeState : BasicState{
+    name = "CompositeState"
+}
+
+Association composite_children(CompositeState, State){
+    name = "composite_children"
+    source_upper_cardinality = 1
+}
+
+Class ParallelState : BasicState{
+    name = "ParallelState"
+}
+Association parallel_children(ParallelState, CompositeState){
+    name = "parallel_children"
+    source_upper_cardinality = 1
+}
+
+Class HistoryState : State{
+    name = "HistoryState"
+}
+
+Association transition(State, State){
+    name = "transition"
+    name: String
+    cond? : Action
+    script? : Action
+    after? : Action
+    event? : String
+    source_upper_cardinality = 1
+}
+Association transition_raises(transition, Raise){
+    name = "transition_raises"
+    order : Natural
+}

+ 14 - 0
integration/code/SCCD_Trace.mvc

@@ -0,0 +1,14 @@
+SimpleAttribute Float {
+    name = "Float"
+}
+SimpleAttribute String {
+    name = "String"
+}
+
+Class Event{
+    name = "Event"
+    timestamp : Float
+    name : String
+    parameter : String
+}
+

+ 15 - 15
integration/code/SCCD_all.mvc

@@ -110,7 +110,7 @@ transition (manager_main_parallel_input_1, manager_main_parallel_input_2) {
         scope = "broad"
         event = "create"
         parameter = $
-                Element function raise(attributes : Element, parameters : Element):
+                Element function raises(attributes : Element, parameters : Element):
                     return list_create()!
             $
     }
@@ -127,7 +127,7 @@ transition (manager_main_parallel_input_2, manager_main_parallel_input_3) {
         scope = "broad"
         event = "toggle"
         parameter = $
-                Element function raise(attributes : Element, parameters : Element):
+                Element function raises(attributes : Element, parameters : Element):
                     return list_create()!
             $
     }
@@ -144,7 +144,7 @@ transition (manager_main_parallel_input_3, manager_main_parallel_input_4) {
         scope = "broad"
         event = "create"
         parameter = $
-                Element function raise(attributes : Element, parameters : Element):
+                Element function raises(attributes : Element, parameters : Element):
                     return list_create()!
             $
     }
@@ -161,7 +161,7 @@ transition (manager_main_parallel_input_4, manager_main_parallel_input_5) {
         scope = "broad"
         event = "police_interrupt"
         parameter = $
-                Element function raise(attributes : Element, parameters : Element):
+                Element function raises(attributes : Element, parameters : Element):
                     return list_create()!
             $
     }
@@ -178,7 +178,7 @@ transition (manager_main_parallel_input_5, manager_main_parallel_input_6) {
         scope = "broad"
         event = "toggle"
         parameter = $
-                Element function raise(attributes : Element, parameters : Element):
+                Element function raises(attributes : Element, parameters : Element):
                     return list_create()!
             $
     }
@@ -195,7 +195,7 @@ transition (manager_main_parallel_input_6, manager_main_parallel_input_7) {
         scope = "broad"
         event = "toggle"
         parameter = $
-                Element function raise(attributes : Element, parameters : Element):
+                Element function raises(attributes : Element, parameters : Element):
                     return list_create()!
             $
     }
@@ -212,7 +212,7 @@ transition (manager_main_parallel_input_7, manager_main_parallel_input_8) {
         scope = "broad"
         event = "police_interrupt"
         parameter = $
-                Element function raise(attributes : Element, parameters : Element):
+                Element function raises(attributes : Element, parameters : Element):
                     return list_create()!
             $
     }
@@ -229,7 +229,7 @@ transition (manager_main_parallel_input_8, manager_main_parallel_input_9) {
         scope = "broad"
         event = "delete"
         parameter = $
-                Element function raise(attributes : Element, parameters : Element):
+                Element function raises(attributes : Element, parameters : Element):
                     return list_create()!
             $
     }
@@ -246,7 +246,7 @@ transition (manager_main_parallel_input_9, manager_main_parallel_input_10) {
         scope = "broad"
         event = "delete"
         parameter = $
-                Element function raise(attributes : Element, parameters : Element):
+                Element function raises(attributes : Element, parameters : Element):
                     return list_create()!
             $
     }
@@ -263,7 +263,7 @@ transition (manager_main_parallel_input_10, manager_main_parallel_input_11) {
         scope = "broad"
         event = "exit"
         parameter = $
-                Element function raise(attributes : Element, parameters : Element):
+                Element function raises(attributes : Element, parameters : Element):
                     return list_create()!
             $
     }
@@ -277,7 +277,7 @@ transition (manager_main_parallel_core_start, manager_main_parallel_core_start)
         scope = "cd"
         event = "create_instance"
         parameter = $
-                Element function raise(attributes : Element, parameters : Element):
+                Element function raises(attributes : Element, parameters : Element):
                     Element result
                     result = list_create()
                     list_append(result, "trafficlights")
@@ -307,7 +307,7 @@ transition (manager_main_parallel_core_start, manager_main_parallel_core_start)
         scope = "cd"
         event = "delete_instance"
         parameter = $
-                Element function raise(attributes : Element, parameters : Element):
+                Element function raises(attributes : Element, parameters : Element):
                     Element result
                     result = list_create()
                     list_append(result, "0")
@@ -324,7 +324,7 @@ transition (manager_main_parallel_core_start, manager_main_parallel_core_start)
         scope = "cd"
         event = "delete_instance"
         parameter = $
-                Element function raise(attributes : Element, parameters : Element):
+                Element function raises(attributes : Element, parameters : Element):
                     Element result
                     result = list_create()
                     list_append(result, list_pop_final(attributes["trafficlights"]))
@@ -499,7 +499,7 @@ Class trafficlight {
                             event = "updateTimerValue"
                             scope = "output"
                             parameter = $
-                                    Element function raise(attributes : Element):
+                                    Element function raises(attributes : Element):
                                         return attributes["counter"]!
                                 $
                         }
@@ -512,7 +512,7 @@ Class trafficlight {
                         {onEntryRaise} Raise {
                             event = "updateTimerValue"
                             parameter = $
-                                    Element function raise(attributes : Element):
+                                    Element function raises(attributes : Element):
                                         return attributes["counter"]!
                                 $
                         }

+ 810 - 0
integration/code/SCCD_execute.alc

@@ -0,0 +1,810 @@
+include "primitives.alh"
+include "modelling.alh"
+include "object_operations.alh"
+include "utils.alh"
+include "random.alh"
+include "library.alh"
+include "io.alh"
+
+Boolean afap = False
+
+Element function resolve_function(location : String, data : Element):
+	if (bool_not(dict_in(data["cache_operations"], location))):
+		dict_add(data["cache_operations"], location, get_func_AL_model(import_node(location)))
+	return data["cache_operations"][location]!
+
+Void function print_states(model : Element, data : Element):
+	Element classes
+	Element states
+	Element class
+	String state
+
+	log("Current states:")
+	classes = dict_keys(data["classes"])
+	while (set_len(classes) > 0):
+		class = set_pop(classes)
+		class = data["classes"][class]
+		log(string_join(string_join(string_join("  ", class["ID"]), " : "), read_attribute(model, class["type"], "name")))
+		log("	Attributes: " + dict_to_string(class["attributes"]))
+
+		states = set_copy(class["states"])
+		log("	States:")
+		while (set_len(states) > 0):
+			state = set_pop(states)
+			log(string_join("		", read_attribute(model, state, "name")))
+
+	return!
+
+Element function filter(model : Element, set : Element, attribute_name : String, attribute_value : Element):
+	Element keys
+	String key
+	Element result
+
+	result = set_create()
+	while (set_len(set) > 0):
+		key = set_pop(set)
+		if (value_eq(read_attribute(model, key, attribute_name), attribute_value)):
+			set_add(result, key)
+
+	return result!
+
+Element function filter_exists(model : Element, set : Element, attribute_name : String):
+	Element keys
+	String key
+	Element result
+
+	result = set_create()
+	while (set_len(set) > 0):
+		key = set_pop(set)
+		if (element_neq(read_attribute(model, key, attribute_name), read_root())):
+			set_add(result, key)
+
+	return result!
+
+Element function expand_current_state(model : Element, state : String, data : Element):
+	// Find the hierarchy of all current states, and select those that contain the currently selected state
+	Element result
+	Element current_states
+	result = set_create()
+	current_states = set_copy(data["current_class_handle"]["states"])
+
+	Element hierarchy
+	String deep_state
+	while (set_len(current_states) > 0):
+		deep_state = set_pop(current_states)
+		hierarchy = find_hierarchy(model, deep_state, data)
+		// Got the hierarchy of one of the states
+
+		if (list_in(hierarchy, state)):
+			// This hierarchy contains the root state we are checking for, so add to set
+			set_add(result, deep_state)
+
+	return result!
+
+Element function expand_initial_state(model : Element, state : String, data : Element):
+	String t
+	t = read_type(model, state)
+	if (t == "SCCD/CompositeState"):
+		// Recurse further in the composite
+		return expand_composite_state(model, state, data)!
+	elif (t == "SCCD/ParallelState"):
+		// Split up all components
+		return expand_parallel_state(model, state, 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 data["current_class_handle"]["history"][get_parent(model, state)]!
+	else:
+		// Probably just an atomic, so return this one only
+		Element result
+		result = set_create()
+		set_add(result, state)
+		return result!
+
+Element function expand_composite_state(model : Element, composite_state : String, data : Element):
+	// Resolve all initial states from a single composite state
+	String initial
+
+	// Fetch the initial state
+	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, data)!
+
+Element function expand_parallel_state(model : Element, parallel_state : String, data : Element):
+	// Resolve all initial states from a single parallel state
+	Element children
+	Element result
+	Element expanded_children
+
+	children = allAssociationDestinations(model, parallel_state, "SCCD/parallel_children")
+	result = set_create()
+
+	while (set_len(children) > 0):
+		set_merge(result, expand_initial_state(model, set_pop(children), data))
+
+	return result!
+
+Void function delete_class(model : Element, data : Element, identifier : String):
+	// Stop a specific class instance, with attached statechart, from executing
+	dict_delete(data["classes"], identifier)
+
+String function start_class(model : Element, data : Element, class : String, parameters : Element):
+	// Start up the class and assign its initial state to it
+
+	// First find an empty identifier
+	String identifier
+	identifier = cast_string(dict_len(data["classes"]))
+
+	// Create the data structure for a running class
+	Element class_handle
+	class_handle = dict_create()
+	dict_add(class_handle, "type", class)
+	dict_add(class_handle, "ID", identifier)
+	dict_add(class_handle, "events", set_create())
+	dict_add(class_handle, "new_events", set_create())
+	dict_add(class_handle, "timers", dict_create())
+	dict_add(data["classes"], class_handle["ID"], class_handle)
+
+	String prev_class
+	prev_class = data["current_class"]
+	dict_overwrite(data, "current_class", identifier)
+	dict_overwrite(data, "current_class_handle", data["classes"][identifier])
+
+	// Add the current state of the class
+	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, class_handle))
+
+	// Initialize history for all composite states
+	Element history
+	Element cstates
+	String cstate
+
+	history = dict_create()
+	dict_add(class_handle, "history", history)
+	cstates = allInstances(model, "SCCD/CompositeState")
+	while (set_len(cstates) > 0):
+		cstate = set_pop(cstates)
+		dict_add(history, cstate, expand_initial_state(model, cstate, class_handle))
+
+	// Add all attributes
+	Element attributes
+	attributes = dict_create()
+	Element attrs
+	attrs = allAssociationDestinations(model, class, "SCCD/class_attributes")
+	while (set_len(attrs) > 0):
+		dict_add(attributes, read_attribute(model, set_pop(attrs), "name"), read_root())
+	dict_add(class_handle, "attributes", attributes)
+
+	// Invoke constructor
+	Element constructor
+	constructor = read_attribute(model, class, "constructor_body")
+	if (element_neq(constructor, read_root())):
+		// Constructor, so execute
+		constructor = resolve_function(constructor, data)
+		constructor(attributes, parameters)
+
+	// Execute all entry actions
+	Element init
+	init = set_create()
+	set_add(init, "")
+	// Initial state before initialization is the set with an empty hierarchy
+	// Empty set would not find any difference between the source and target
+
+	execute_actions(model, init, set_copy(class_handle["states"]), data, "")
+
+	dict_overwrite(data, "current_class", prev_class)
+	dict_overwrite(data, "current_class_handle", data["classes"][prev_class])
+
+	return identifier!
+
+Element function get_enabled_transitions(model : Element, state : String, data : Element):
+	// Returns all enabled transitions
+	Element result
+	Element to_filter
+	String attr
+	String transition
+	Element cond
+	String evt_name
+	Element evt
+	Element events
+	Element event_names
+	Element event_parameters
+
+	result = set_create()
+	to_filter = allOutgoingAssociationInstances(model, state, "SCCD/transition")
+
+	event_names = set_create()
+	event_parameters = set_create()
+	events = set_copy(data["current_class_handle"]["events"])
+	while (set_len(events) > 0):
+		evt = set_pop(events)
+		evt_name = list_read(evt, 0)
+
+		if (bool_not(set_in(event_names, evt_name))):
+			// Not yet registered the event
+			set_add(event_names, evt_name)
+			dict_add(event_parameters, evt_name, set_create())
+		// Add event parameters
+		set_add_node(event_parameters[evt_name], list_read(evt, 1))
+
+	while (set_len(to_filter) > 0):
+		transition = set_pop(to_filter)
+
+		// Check event
+		attr = read_attribute(model, transition, "event")
+		if (bool_not(bool_or(element_eq(attr, read_root()), set_in(event_names, attr)))):
+			// At least one enabled event is found
+			continue!
+
+		// Check after
+		// Only an after if there was no event!
+		if (bool_and(element_eq(attr, read_root()), read_attribute(model, transition, "after"))):
+			if (dict_in(data["current_class_handle"]["timers"], transition)):
+				// Registered timer already, let's check if it has expired
+				if (float_gt(data["current_class_handle"]["timers"][transition], data["time_sim"])):
+					// Not enabled yet
+					continue!
+			else:
+				// Not registered even, so not enabled either
+				continue!
+
+		// Check condition, but depends on whether there was an event or not
+		cond = read_attribute(model, transition, "cond")
+		if (element_neq(cond, read_root())):
+			// Got a condition, so resolve
+			cond = resolve_function(cond, data)
+
+		if (element_neq(attr, read_root())):
+			// We have an event to take into account!
+			Element params
+			Element param
+			params = set_copy(event_parameters[attr])
+			while (set_len(params) > 0):
+				param = set_pop(params)
+				if (element_neq(cond, read_root())):
+					// Got a condition to check first
+					if (bool_not(cond(data["current_class_handle"]["attributes"], param))):
+						// Condition failed, so skip
+						continue!
+				// Fine to add this one with the specified parameters
+				set_add_node(result, create_tuple(transition, param))
+		else:
+			// No event to think about, just add the transition
+			if (element_neq(cond, read_root())):
+				// Check the condition first
+				if (bool_not(cond(data["current_class_handle"]["attributes"], read_root()))):
+					// Condition false, so skip
+					continue!
+			// Fine to add this one without event parameters (no event)
+			set_add_node(result, create_tuple(transition, read_root()))
+
+	return result!
+
+Void function process_raised_event(model : Element, event : Element, parameter_action : Element, data : Element):
+	String scope
+	scope = read_attribute(model, event, "scope")
+	if (scope == "cd"):
+		// Is an event for us internally, so don't append
+		// Instead, we process it directly
+		String operation
+		operation = read_attribute(model, event, "event")
+		if (operation == "create_instance"):
+			// Start up a new class of the desired type
+
+			// Parameters of this call:
+			// class -- type of the class to instantiate
+			// identifier -- name of this instance, for future reference
+			// parameters -- parameters for constructor
+			String class
+			String identifier
+			Element parameters
+			class = set_pop(filter(model, allInstances(model, "SCCD/Class"), "name", list_read(parameter_action, 1)))
+			parameters = list_read(parameter_action, 2)
+			identifier = start_class(model, data, class, parameters)
+
+			// Notify the creator of the ID of the created instance
+			Element lst
+			lst = list_create()
+			list_append(lst, identifier)
+			set_add_node(data["current_class_handle"]["new_events"], create_tuple("instance_created", lst))
+
+		elif (operation == "delete_instance"):
+			// Delete the requested class
+			String identifier
+			identifier = list_read(parameter_action, 0)
+			delete_class(model, data, identifier)
+			set_add_node(data["current_class_handle"]["new_events"], create_tuple("instance_deleted", parameter_action))
+
+	elif (scope == "broad"):
+		// Send to all classes
+		Element classes
+		classes = dict_keys(data["classes"])
+		while(set_len(classes) > 0):
+			set_add_node(data["classes"][set_pop(classes)]["new_events"], create_tuple(read_attribute(model, event, "event"), parameter_action))
+
+	elif (scope == "narrow"):
+		// Send to the specified class only
+		Element func
+		func = resolve_function(read_attribute(model, event, "target"), data)
+		String dest
+		dest = func(data["current_class_handle"]["attributes"])
+		set_add_node(data["classes"][dest]["new_events"], create_tuple(read_attribute(model, event, "event"), parameter_action))
+
+	elif (scope == "output"):
+		// Store it in the output event model
+		String evt
+
+		if (bool_not(afap)):
+			Element val
+			val = dict_create()
+			dict_add(val, "timestamp", data["time_sim"])
+			dict_add(val, "name", read_attribute(model, event, "event"))
+			dict_add(val, "parameter", parameter_action)
+
+			output("EVENT: " + dict_to_string(val))
+
+		evt = instantiate_node(model, "trace/Event", "")
+		instantiate_attribute(model, evt, "timestamp", data["time_sim"])
+		instantiate_attribute(model, evt, "name", read_attribute(model, event, "event"))
+		instantiate_attribute(model, evt, "parameter", parameter_action)
+
+	else:
+		// Same as local
+		set_add_node(data["current_class_handle"]["new_events"], create_tuple(read_attribute(model, event, "event"), parameter_action))
+
+	return !
+
+Element function execute_transition(model : Element, data : Element, transition_tuple : Element):
+	// Execute the script (if any)
+	Element script
+	String transition
+	Element event_parameter
+	transition = list_read(transition_tuple, 0)
+	event_parameter = list_read(transition_tuple, 1)
+
+	script = read_attribute(model, transition, "script")
+	if (element_neq(script, read_root())):
+		script = resolve_function(script, data)
+		script(data["current_class_handle"]["attributes"], event_parameter)
+
+	// Raise events (if any)
+	Element events
+	String event
+	events = allAssociationDestinations(model, transition, "SCCD/transition_raises")
+	while (set_len(events) > 0):
+		event = set_pop(events)
+
+		Element parameter_action
+		parameter_action = read_attribute(model, event, "parameter")
+		if (element_neq(parameter_action, read_root())):
+			// Got a parameter to evaluate
+			parameter_action = resolve_function(parameter_action, data)
+			parameter_action = parameter_action(data["current_class_handle"]["attributes"], event_parameter)
+
+		process_raised_event(model, event, parameter_action, data)
+
+	// Find new set of states
+	Element target_states
+	Element source_states
+	source_states = expand_current_state(model, readAssociationSource(model, transition), data)
+	target_states = expand_initial_state(model, readAssociationDestination(model, transition), data)
+
+	execute_actions(model, source_states, target_states, data, readAssociationSource(model, transition))
+
+	return target_states!
+
+Boolean function step_class(model : Element, data : Element, class : String):
+	// Find enabled transitions in a class and execute it, updating the state
+	// Iterate over all current states, searching for enabled transitions
+	// Search for enabled transitions in higher levels as well!
+	Element states
+	Element new_states
+	String state
+	Element transitions
+	String transition
+	Boolean transitioned
+	Element hierarchy
+	String current_state
+	Boolean found
+
+	if (bool_not(dict_in(data["classes"], class))):
+		// Seems like this class was removed, so stop execution
+		return False!
+
+	// Notify everyone of the current class
+	dict_overwrite(data, "current_class", class)
+	dict_overwrite(data, "current_class_handle", data["classes"][class])
+
+	states = set_copy(data["current_class_handle"]["states"])
+	new_states = set_create()
+	transitioned = False
+
+	while (set_len(states) > 0):
+		state = set_pop(states)
+		found = False
+
+		// Loop over the hierarchy of this state and try to apply transitions
+		hierarchy = find_hierarchy(model, state, data)
+		while (list_len(hierarchy) > 0):
+			current_state = list_pop(hierarchy, 0)
+			transitions = get_enabled_transitions(model, current_state, data)
+
+			if (set_len(transitions) > 0):
+				// Found an enabled transition, so store that one
+				transition = random_choice(set_to_list(transitions))
+				
+				// Execute transition
+				set_merge(new_states, execute_transition(model, data, transition))
+
+				// 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)
+				set_subtract(states, leaving)
+
+				transitioned = True
+				found = True
+				break!
+
+		if (bool_not(found)):
+			// Nothing found, so stay in the current state
+			set_add(new_states, state)
+			
+	// Update states
+	dict_overwrite(data["current_class_handle"], "states", new_states)
+
+	return transitioned!
+
+String function get_parent(model : Element, state : String):
+	Element tmp_set
+	tmp_set = allAssociationOrigins(model, state, "SCCD/composite_children")
+	set_merge(tmp_set, allAssociationOrigins(model, state, "SCCD/parallel_children"))
+	if (set_len(tmp_set) > 0):
+		return set_pop(tmp_set)!
+	else:
+		return ""!
+
+Element function find_hierarchy(model : Element, state : String, data : Element):
+	// Try to cache as much as possible!
+	if (bool_not(dict_in(data["cache_hierarchy"], state))):
+		Element result
+		if (state == ""):
+			result = list_create()
+		else:
+			String parent
+			parent = get_parent(model, state)
+			// We have a parent, so take the parent list first
+			result = find_hierarchy(model, parent, data)
+			list_append(result, state)
+		dict_add(data["cache_hierarchy"], state, result)
+	return dict_copy(data["cache_hierarchy"][state])!
+
+Void function execute_actions(model : Element, source_states : Element, target_states : Element, data : Element, transition_source : String):
+	Element exit
+	Element entry
+	exit = list_create()
+	entry = list_create()
+
+	source_states = set_copy(source_states)
+	target_states = set_copy(target_states)
+
+	// Add all exit and entry actions to the list of actions to execute
+	// Do this by finding the common parent, and then doing all exit actions up to that node, and all entry actions up to the target_state
+
+	// First, find the hierarchy!
+	Element hierarchy_sources
+	Element hierarchy_targets
+	Element all_hierarchies
+
+	hierarchy_sources = set_create()
+	while (set_len(source_states) > 0):
+		set_add_node(hierarchy_sources, find_hierarchy(model, set_pop(source_states), data))
+
+	hierarchy_targets = set_create()
+	while (set_len(target_states) > 0):
+		set_add_node(hierarchy_targets, find_hierarchy(model, set_pop(target_states), data))
+
+	all_hierarchies = set_copy(hierarchy_sources)
+	set_merge(all_hierarchies, hierarchy_targets)
+
+	// Difference these all lists, finding the first common entry
+	Element iter_hierarchies
+	Integer i
+	String current
+	Element hierarchy
+	Boolean finished
+	Integer transition_depth
+	Integer lca_depth
+	lca_depth = 0
+	finished = False
+
+	if (transition_source != ""):
+		// Find out the level of the transition_source by fetching its hierarchy
+		transition_depth = list_len(find_hierarchy(model, transition_source, data)) - 1
+
+		// Now check for the least common ancestor
+		while (bool_not(finished)):
+			// Check the i-th element in both and see if they are equal
+			current = ""
+			iter_hierarchies = set_copy(all_hierarchies)
+			while (set_len(iter_hierarchies) > 0):
+				hierarchy = set_pop(iter_hierarchies)
+
+				// Exhausted one of the lists
+				if (lca_depth >= list_len(hierarchy)):
+					finished = True
+					break!
+
+				// Reached the same level as transition depth already, so no need to increase
+				if (lca_depth == transition_depth):
+					finished = True
+					break!
+
+				// First entry, so read out value as reference
+				if (current == ""):
+					current = list_read(hierarchy, lca_depth)
+
+				// Check with reference element
+				if (bool_not(value_eq(list_read(hierarchy, lca_depth), current))):
+					finished = True
+					break!
+
+			// i-th element equal for all hierarchies, so go to next element
+			if (bool_not(finished)):
+				lca_depth = lca_depth + 1
+
+		if (lca_depth < transition_depth):
+			i = lca_depth
+		else:
+			i = transition_depth
+
+	else:
+		// Initial, so just set i to zero
+		i = 0
+
+	// Found the first differing element at position i
+
+	// All elements remaining in hierarchy_source are to be traversed in REVERSE order for the exit actions
+	// All elements remaining in hierarchy_target are to be traversed in NORMAL order for the entry actions
+	// This is not that simple either, as we need to consider that some actions might already have been added to the list...
+
+	// Add hierarchy_sources actions
+	String state
+	Element visited
+	Element action
+	Element spliced_hierarchy
+	Element hierarchy_source
+	Element hierarchy_target
+	visited = set_create()
+	while (set_len(hierarchy_sources) > 0):
+		// Get one of these hierarchies
+		hierarchy_source = set_pop(hierarchy_sources)
+		spliced_hierarchy = list_splice(hierarchy_source, i, list_len(hierarchy_source))
+		while (list_len(spliced_hierarchy) > 0):
+			state = list_pop(spliced_hierarchy, list_len(spliced_hierarchy) - 1)
+			if (set_in(visited, state)):
+				// Already added this state, so don't bother
+				continue!
+			else:
+				// New state, so prepend it to the list
+				// Prepend, instead of append, as we want to do these operations in reverse order!
+				list_insert(exit, state, 0)
+
+				// Add this state as visited
+				set_add(visited, state)
+
+	// Add hierarchy_targets actions
+	// Clear visited, just to be safe, though it should not matter
+	visited = set_create()
+	while (set_len(hierarchy_targets) > 0):
+		// Get one of these hierarchies
+		hierarchy_target = set_pop(hierarchy_targets)
+		spliced_hierarchy = list_splice(hierarchy_target, i, list_len(hierarchy_target))
+		while (list_len(spliced_hierarchy) > 0):
+			state = list_pop(spliced_hierarchy, list_len(spliced_hierarchy) - 1)
+			if (set_in(visited, state)):
+				// Already added this state, so don't bother
+				continue!
+			else:
+				// New state, so append it to the list
+				// Append, instead of prepend, as we want to do these operations in normal order!
+				list_append(entry, state)
+
+				// Add this state as visited, even though there might not have been an associated action
+				set_add(visited, state)
+
+	// Now we have a list of traversed states!
+	// Start executing all their operations in order
+
+	Element events
+	String event
+	// First do exit actions
+	while (list_len(exit) > 0):
+		state = list_pop(exit, 0)
+
+		// Set history when leaving
+		if (read_type(model, state) == "SCCD/CompositeState"):
+			dict_overwrite(data["current_class_handle"]["history"], state, expand_current_state(model, state, data))
+
+		// Do exit actions
+		action = read_attribute(model, state, "onExitScript")
+		if (element_neq(action, read_root())):
+			// Got a script, so execute!
+			action = resolve_function(action, data)
+			action(data["current_class_handle"]["attributes"])
+
+		// Raise events
+		events = allAssociationDestinations(model, state, "SCCD/onExitRaise")
+		while (set_len(events) > 0):
+			event = set_pop(events)
+
+			Element parameter_action
+			parameter_action = read_attribute(model, event, "parameter")
+			if (element_neq(parameter_action, read_root())):
+				// Got a parameter to evaluate
+				parameter_action = resolve_function(parameter_action, data)
+				parameter_action = parameter_action(data["current_class_handle"]["attributes"])
+
+			process_raised_event(model, event, parameter_action, data)
+
+		// Unschedule after events
+		Element timed_transitions
+		timed_transitions = filter_exists(model, allOutgoingAssociationInstances(model, state, "SCCD/transition"), "after")
+		while (set_len(timed_transitions) > 0):
+			dict_delete(data["current_class_handle"]["timers"], set_pop(timed_transitions))
+
+	// Then do entry actions
+	while (list_len(entry) > 0):
+		state = list_pop(entry, 0)
+
+		// Do entry actions
+		action = read_attribute(model, state, "onEntryScript")
+		if (element_neq(action, read_root())):
+			// Got a script, so execute!
+			action = resolve_function(action, data)
+			action(data["current_class_handle"]["attributes"])
+
+		// Raise events
+		events = allAssociationDestinations(model, state, "SCCD/onEntryRaise")
+		while (set_len(events) > 0):
+			event = set_pop(events)
+
+			Element parameter_action
+			parameter_action = read_attribute(model, event, "parameter")
+			if (element_neq(parameter_action, read_root())):
+				// Got a parameter to evaluate
+				parameter_action = resolve_function(parameter_action, data)
+				parameter_action = parameter_action(data["current_class_handle"]["attributes"])
+
+			process_raised_event(model, event, parameter_action, data)
+
+		// Schedule after events
+		Element timed_transitions
+		String transition
+		Element after
+		timed_transitions = filter_exists(model, allOutgoingAssociationInstances(model, state, "SCCD/transition"), "after")
+		while (set_len(timed_transitions) > 0):
+			transition = set_pop(timed_transitions)
+			after = resolve_function(read_attribute(model, transition, "after"), data)
+			dict_add(data["current_class_handle"]["timers"], transition, float_addition(data["time_sim"], after(data["current_class_handle"]["attributes"])))
+
+	return !
+
+Float function step(model : Element, data : Element):
+	// Step through all classes
+	Element classes
+	Element class
+	Float t_min
+	Float t_current
+	Boolean transitioned
+	Element keys
+	String key
+
+	t_min = 999999.0
+	classes = dict_keys(data["classes"])
+
+	transitioned = False
+	while (set_len(classes) > 0):
+		class = set_pop(classes)
+		if (step_class(model, data, class)):
+			transitioned = True
+
+		if (bool_not(transitioned)):
+			// Find minimum timer for this class, and store that
+			keys = dict_keys(data["classes"][class]["timers"])
+			while (set_len(keys) > 0):
+				key = set_pop(keys)
+				t_current = data["classes"][class]["timers"][key]
+				if (t_current < t_min):
+					t_min = t_current
+
+	if (transitioned):
+		// Do another step, as we can transition
+		return data["time_sim"]!
+	else:
+		return t_min!
+
+Boolean function main(model : Element):
+	// Executes the provided SCCD model
+	Element data
+	data = dict_create()
+	dict_add(data, "classes", dict_create())
+	dict_add(data, "cache_operations", dict_create())
+	dict_add(data, "cache_hierarchy", dict_create())
+	dict_add(data, "current_class", "")
+	
+	Float time_0
+	Float time_sim
+	Float time_wallclock
+	time_0 = time()
+	time_sim = 0.0
+	dict_add(data, "time_sim", 0.0)
+
+	// Prepare for input
+	output("Ready for input!")
+
+	// Find initial
+	String default_class
+	default_class = set_pop(filter(model, allInstances(model, "SCCD/Class"), "default", True))
+
+	// Start up the default class
+	String identifier
+	identifier = start_class(model, data, default_class, read_root())
+
+	// Notify this class itself of its ID
+	Element lst
+	lst = list_create()
+	list_append(lst, identifier)
+	set_add_node(data["current_class_handle"]["new_events"], create_tuple("instance_created", lst))
+
+	Float timeout
+	Element interrupt
+	timeout = 0.0
+	while (True):
+		if (afap):
+			timeout = 0.0
+		interrupt = input_timeout(timeout)
+
+		if (value_eq(interrupt, "#EXIT#")):
+			// Stop execution
+			return True!
+
+		if (element_neq(interrupt, read_root())):
+			// Send out, as otherwise the client doesn't get a dialog
+			output("Processed event, ready for more!")
+
+			// Update the simulated time to the time of interrupt
+			time_sim = time() - time_0
+
+		Element classes
+		classes = dict_keys(data["classes"])
+		while(set_len(classes) > 0):
+			String class
+			class = set_pop(classes)
+			dict_overwrite(data["classes"][class], "events", data["classes"][class]["new_events"])
+			dict_overwrite(data["classes"][class], "new_events", set_create())
+
+			if (element_neq(interrupt, read_root())):
+				// Got interrupt, so append it already
+				set_add_node(data["classes"][class]["events"], create_tuple(interrupt, read_root()))
+
+		// Else we timeout, and thus keep the time_sim
+		dict_overwrite(data, "time_sim", time_sim)
+
+		time_sim = step(model, data)
+
+		if (float_gt(time_sim, data["time_sim"])):
+			print_states(model, data)
+
+		if (dict_len(data["classes"]) == 0):
+			// No more active classes left: terminate!
+			log("Finished SCCD execution")
+			break!
+
+		time_wallclock = time() - time_0
+		timeout = time_sim - time_wallclock
+
+	// We have finished without error
+	return True!

+ 5 - 7
unit/test_all.py

@@ -307,13 +307,13 @@ class TestModelverse(unittest.TestCase):
 
     def test_render(self):
         model_add("test/CausalBlockDiagrams", "formalisms/SimpleClassDiagrams", open("integration/code/cbd_design.mvc", 'r').read())
-        model_add("test/MM_rendered_graphical", "formalisms/SimpleClassDiagrams", open("models/MM_rendered_graphical.mvc", 'r').read())
+        model_add("test/MM_rendered_graphical", "formalisms/SimpleClassDiagrams", open("integration/code/MM_rendered_graphical.mvc", 'r').read())
         model_add("test/my_CBD", "test/CausalBlockDiagrams", open("integration/code/my_cbd.mvc", 'r').read())
 
         def add_tracability(model):
             instantiate(model, "Association", ("abstract/Block", "rendered/Group"), ID="TracabilityLink")
 
-        transformation_add_MT({"abstract": "test/CausalBlockDiagrams", "rendered": "test/MM_rendered_graphical"}, {"abstract": "test/CausalBlockDiagrams", "rendered": "test/MM_rendered_graphical"}, "test/render_graphical_CBD", open("models/CBD_mapper.mvc", 'r').read(), add_tracability)
+        transformation_add_MT({"abstract": "test/CausalBlockDiagrams", "rendered": "test/MM_rendered_graphical"}, {"abstract": "test/CausalBlockDiagrams", "rendered": "test/MM_rendered_graphical"}, "test/render_graphical_CBD", open("integration/code/CBD_mapper.mvc", 'r').read(), add_tracability)
         result = model_render("test/my_CBD", "test/render_graphical_CBD", "test/my_perceptualized_CBD")
 
         assert len(result) == 23
@@ -325,14 +325,13 @@ class TestModelverse(unittest.TestCase):
         model_delete("tracability")
         model_delete("type mappings/tracability")
 
-    """
     def test_SCCD_basic(self):
-        model_add("test/SCCD", "formalisms/SimpleClassDiagrams", open("models/SCCD.mvc", 'r').read())
-        model_add("test/SCCD_Trace", "formalisms/SimpleClassDiagrams", open("models/SCCD_Trace.mvc", 'r').read())
+        model_add("test/SCCD", "formalisms/SimpleClassDiagrams", open("integration/code/SCCD.mvc", 'r').read())
+        model_add("test/SCCD_Trace", "formalisms/SimpleClassDiagrams", open("integration/code/SCCD_Trace.mvc", 'r').read())
 
         model_add("test/my_SCCD", "test/SCCD", open("integration/code/SCCD_all.mvc", 'r').read())
 
-        transformation_add_AL({"SCCD": "test/SCCD"}, {"trace": "test/SCCD_Trace"}, "test/SCCD_execute_afap", open("models/SCCD_execute.alc", 'r').read().replace("afap = False", "afap = True"))
+        transformation_add_AL({"SCCD": "test/SCCD"}, {"trace": "test/SCCD_Trace"}, "test/SCCD_execute_afap", open("integration/code/SCCD_execute.alc", 'r').read().replace("afap = False", "afap = True"))
         transformation_execute_AL("test/SCCD_execute_afap", {"SCCD": "test/my_SCCD"}, {"trace": "test/my_SCCD_trace"})
 
         print("Executed AL")
@@ -392,7 +391,6 @@ class TestModelverse(unittest.TestCase):
                           (147.9, "displayNone"),
                           (148.4, "displayYellow"),
                          ]
-    """
 
     def test_switch_MM(self):
         model_add("test/PetriNet", "formalisms/SimpleClassDiagrams", open("integration/code/pn_design.mvc", "r").read())

+ 1 - 1
wrappers/modelverse_SCCD.py

@@ -1,7 +1,7 @@
 """
 Generated by Statechart compiler by Glenn De Jonghe, Joeri Exelmans, Simon Van Mierlo, and Yentl Van Tendeloo (for the inspiration)
 
-Date:   Fri May 18 12:04:24 2018
+Date:   Fri May 18 13:09:29 2018
 
 Model author: Yentl Van Tendeloo
 Model name:   MvK Server