|
@@ -6,9 +6,9 @@ include "random.alh"
|
|
|
include "library.alh"
|
|
|
|
|
|
Element function resolve_function(location : String, data : Element):
|
|
|
- if (bool_not(dict_in(data["operations"], location))):
|
|
|
- dict_add(data["operations"], location, get_func_AL_model(import_node(location)))
|
|
|
- return data["operations"][location]!
|
|
|
+ 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
|
|
@@ -57,18 +57,18 @@ Element function filter_exists(model : Element, set : Element, attribute_name :
|
|
|
|
|
|
return result!
|
|
|
|
|
|
-Element function expand_current_state(model : Element, state : String, class_data : Element):
|
|
|
+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 = create_node()
|
|
|
- current_states = set_copy(class_data["states"])
|
|
|
+ current_states = set_copy(data["classes"][data["current_class"]]["states"])
|
|
|
|
|
|
Element hierarchy
|
|
|
String deep_state
|
|
|
while (read_nr_out(current_states) > 0):
|
|
|
deep_state = set_pop(current_states)
|
|
|
- hierarchy = find_hierarchy(model, deep_state)
|
|
|
+ hierarchy = find_hierarchy(model, deep_state, data)
|
|
|
// Got the hierarchy of one of the states
|
|
|
|
|
|
if (set_in(hierarchy, state)):
|
|
@@ -77,19 +77,19 @@ Element function expand_current_state(model : Element, state : String, class_dat
|
|
|
|
|
|
return result!
|
|
|
|
|
|
-Element function expand_initial_state(model : Element, state : String, class_data : Element):
|
|
|
+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, class_data)!
|
|
|
+ return expand_composite_state(model, state, data)!
|
|
|
elif (t == "SCCD/ParallelState"):
|
|
|
// Split up all components
|
|
|
- return expand_parallel_state(model, state, class_data)!
|
|
|
+ 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 class_data["history"][get_parent(model, state)]!
|
|
|
+ return data["classes"][data["current_class"]]["history"][get_parent(model, state)]!
|
|
|
else:
|
|
|
// Probably just an atomic, so return this one only
|
|
|
Element result
|
|
@@ -97,7 +97,7 @@ Element function expand_initial_state(model : Element, state : String, class_dat
|
|
|
set_add(result, state)
|
|
|
return result!
|
|
|
|
|
|
-Element function expand_composite_state(model : Element, composite_state : String, class_data : Element):
|
|
|
+Element function expand_composite_state(model : Element, composite_state : String, data : Element):
|
|
|
// Resolve all initial states from a single composite state
|
|
|
String initial
|
|
|
|
|
@@ -105,9 +105,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, class_data)!
|
|
|
+ return expand_initial_state(model, initial, data)!
|
|
|
|
|
|
-Element function expand_parallel_state(model : Element, parallel_state : String, class_data : Element):
|
|
|
+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
|
|
@@ -117,7 +117,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), class_data))
|
|
|
+ set_merge(result, expand_initial_state(model, set_pop(children), data))
|
|
|
|
|
|
return result!
|
|
|
|
|
@@ -134,6 +134,11 @@ Void function start_class(model : Element, data : Element, class : String, ident
|
|
|
dict_add(class_handle, "type", class)
|
|
|
dict_add(class_handle, "ID", identifier)
|
|
|
dict_add(class_handle, "timers", create_node())
|
|
|
+ dict_add(data["classes"], class_handle["ID"], class_handle)
|
|
|
+
|
|
|
+ String prev_class
|
|
|
+ prev_class = data["current_class"]
|
|
|
+ dict_overwrite(data, "current_class", identifier)
|
|
|
|
|
|
// Add the current state of the class
|
|
|
String initial_state
|
|
@@ -176,13 +181,14 @@ Void function start_class(model : Element, data : Element, class : String, ident
|
|
|
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"]), attributes, data, "")
|
|
|
|
|
|
- dict_add(data["classes"], class_handle["ID"], class_handle)
|
|
|
+ execute_actions(model, init, set_copy(class_handle["states"]), data, "")
|
|
|
+
|
|
|
+ dict_overwrite(data, "current_class", prev_class)
|
|
|
|
|
|
return!
|
|
|
|
|
|
-Element function get_enabled_transitions(model : Element, state : String, data : Element, class : String):
|
|
|
+Element function get_enabled_transitions(model : Element, state : String, data : Element):
|
|
|
// Returns all enabled transitions
|
|
|
Element result
|
|
|
Element to_filter
|
|
@@ -224,9 +230,9 @@ Element function get_enabled_transitions(model : Element, state : String, data :
|
|
|
// 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["classes"][class]["timers"], transition)):
|
|
|
+ if (dict_in(data["classes"][data["current_class"]]["timers"], transition)):
|
|
|
// Registered timer already, let's check if it has expired
|
|
|
- if (float_gt(data["classes"][class]["timers"][transition], data["time_sim"])):
|
|
|
+ if (float_gt(data["classes"][data["current_class"]]["timers"][transition], data["time_sim"])):
|
|
|
// Not enabled yet
|
|
|
continue!
|
|
|
else:
|
|
@@ -248,7 +254,7 @@ Element function get_enabled_transitions(model : Element, state : String, data :
|
|
|
param = set_pop(params)
|
|
|
if (element_neq(cond, read_root())):
|
|
|
// Got a condition to check first
|
|
|
- if (bool_not(cond(data["classes"][class]["attributes"], param))):
|
|
|
+ if (bool_not(cond(data["classes"][data["current_class"]]["attributes"], param))):
|
|
|
// Condition failed, so skip
|
|
|
continue!
|
|
|
// Fine to add this one with the specified parameters
|
|
@@ -257,7 +263,7 @@ Element function get_enabled_transitions(model : Element, state : String, data :
|
|
|
// No event to think about, just add the transition
|
|
|
if (element_neq(cond, read_root())):
|
|
|
// Check the condition first
|
|
|
- if (bool_not(cond(data["classes"][class]["attributes"], read_root()))):
|
|
|
+ if (bool_not(cond(data["classes"][data["current_class"]]["attributes"], read_root()))):
|
|
|
// Condition false, so skip
|
|
|
continue!
|
|
|
// Fine to add this one without event parameters (no event)
|
|
@@ -298,7 +304,7 @@ Void function process_raised_event(model : Element, event : Element, parameter_a
|
|
|
|
|
|
return !
|
|
|
|
|
|
-Element function execute_transition(model : Element, data : Element, class : String, transition_tuple : Element):
|
|
|
+Element function execute_transition(model : Element, data : Element, transition_tuple : Element):
|
|
|
// Execute the script (if any)
|
|
|
Element script
|
|
|
String transition
|
|
@@ -309,7 +315,7 @@ Element function execute_transition(model : Element, data : Element, class : Str
|
|
|
script = read_attribute(model, transition, "script")
|
|
|
if (element_neq(script, read_root())):
|
|
|
script = resolve_function(script, data)
|
|
|
- script(data["classes"][class]["attributes"], event_parameter)
|
|
|
+ script(data["classes"][data["current_class"]]["attributes"], event_parameter)
|
|
|
|
|
|
// Raise events (if any)
|
|
|
Element events
|
|
@@ -323,17 +329,17 @@ Element function execute_transition(model : Element, data : Element, class : Str
|
|
|
if (element_neq(parameter_action, read_root())):
|
|
|
// Got a parameter to evaluate
|
|
|
parameter_action = resolve_function(parameter_action, data)
|
|
|
- parameter_action = parameter_action(data["classes"][class]["attributes"], event_parameter)
|
|
|
+ parameter_action = parameter_action(data["classes"][data["current_class"]]["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["classes"][class])
|
|
|
- target_states = expand_initial_state(model, readAssociationDestination(model, transition), data["classes"][class])
|
|
|
+ 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["classes"][class], data, readAssociationSource(model, transition))
|
|
|
+ execute_actions(model, source_states, target_states, data, readAssociationSource(model, transition))
|
|
|
|
|
|
return target_states!
|
|
|
|
|
@@ -351,7 +357,10 @@ Boolean function step_class(model : Element, data : Element, class : String):
|
|
|
String current_state
|
|
|
Boolean found
|
|
|
|
|
|
- states = set_copy(data["classes"][class]["states"])
|
|
|
+ // Notify everyone of the current class
|
|
|
+ dict_overwrite(data, "current_class", class)
|
|
|
+
|
|
|
+ states = set_copy(data["classes"][data["current_class"]]["states"])
|
|
|
new_states = create_node()
|
|
|
transitioned = False
|
|
|
|
|
@@ -360,21 +369,21 @@ Boolean function step_class(model : Element, data : Element, class : String):
|
|
|
found = False
|
|
|
|
|
|
// Loop over the hierarchy of this state and try to apply transitions
|
|
|
- hierarchy = find_hierarchy(model, state)
|
|
|
+ hierarchy = find_hierarchy(model, state, data)
|
|
|
while (read_nr_out(hierarchy) > 0):
|
|
|
current_state = list_pop(hierarchy, 0)
|
|
|
- transitions = get_enabled_transitions(model, current_state, data, class)
|
|
|
+ transitions = get_enabled_transitions(model, current_state, data)
|
|
|
|
|
|
if (read_nr_out(transitions) > 0):
|
|
|
// Found an enabled transition, so store that one
|
|
|
transition = random_choice(transitions)
|
|
|
|
|
|
// Execute transition
|
|
|
- set_merge(new_states, execute_transition(model, data, class, 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["classes"][class])
|
|
|
+ leaving = expand_current_state(model, current_state, data)
|
|
|
set_difference(states, leaving)
|
|
|
|
|
|
transitioned = True
|
|
@@ -386,7 +395,7 @@ Boolean function step_class(model : Element, data : Element, class : String):
|
|
|
set_add(new_states, state)
|
|
|
|
|
|
// Update states
|
|
|
- dict_overwrite(data["classes"][class], "states", new_states)
|
|
|
+ dict_overwrite(data["classes"][data["current_class"]], "states", new_states)
|
|
|
|
|
|
return transitioned!
|
|
|
|
|
@@ -399,20 +408,22 @@ String function get_parent(model : Element, state : String):
|
|
|
else:
|
|
|
return ""!
|
|
|
|
|
|
-Element function find_hierarchy(model : Element, state : String):
|
|
|
- if (state == ""):
|
|
|
- return create_node()!
|
|
|
- else:
|
|
|
+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
|
|
|
- String parent
|
|
|
-
|
|
|
- parent = get_parent(model, state)
|
|
|
- // We have a parent, so take the parent list first
|
|
|
- result = find_hierarchy(model, parent)
|
|
|
- list_append(result, state)
|
|
|
- return result!
|
|
|
-
|
|
|
-Void function execute_actions(model : Element, source_states : Element, target_states : Element, class_data : Element, data : Element, transition_source : String):
|
|
|
+ if (state == ""):
|
|
|
+ result = create_node()
|
|
|
+ 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 = create_node()
|
|
@@ -431,11 +442,11 @@ Void function execute_actions(model : Element, source_states : Element, target_s
|
|
|
|
|
|
hierarchy_sources = create_node()
|
|
|
while (read_nr_out(source_states) > 0):
|
|
|
- set_add(hierarchy_sources, find_hierarchy(model, set_pop(source_states)))
|
|
|
+ set_add(hierarchy_sources, find_hierarchy(model, set_pop(source_states), data))
|
|
|
|
|
|
hierarchy_targets = create_node()
|
|
|
while (read_nr_out(target_states) > 0):
|
|
|
- set_add(hierarchy_targets, find_hierarchy(model, set_pop(target_states)))
|
|
|
+ set_add(hierarchy_targets, find_hierarchy(model, set_pop(target_states), data))
|
|
|
|
|
|
all_hierarchies = set_copy(hierarchy_sources)
|
|
|
set_merge(all_hierarchies, hierarchy_targets)
|
|
@@ -453,7 +464,7 @@ Void function execute_actions(model : Element, source_states : Element, target_s
|
|
|
|
|
|
if (transition_source != ""):
|
|
|
// Find out the level of the transition_source by fetching its hierarchy
|
|
|
- transition_depth = list_len(find_hierarchy(model, transition_source)) - 1
|
|
|
+ transition_depth = list_len(find_hierarchy(model, transition_source, data)) - 1
|
|
|
|
|
|
// Now check for the least common ancestor
|
|
|
while (bool_not(finished)):
|
|
@@ -557,14 +568,14 @@ Void function execute_actions(model : Element, source_states : Element, target_s
|
|
|
|
|
|
// Set history when leaving
|
|
|
if (read_type(model, state) == "SCCD/CompositeState"):
|
|
|
- dict_overwrite(class_data["history"], state, expand_current_state(model, state, class_data))
|
|
|
+ dict_overwrite(data["classes"][data["current_class"]]["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(class_data["attributes"])
|
|
|
+ action(data["classes"][data["current_class"]]["attributes"])
|
|
|
|
|
|
// Raise events
|
|
|
events = allAssociationDestinations(model, state, "SCCD/onExitRaise")
|
|
@@ -576,7 +587,7 @@ Void function execute_actions(model : Element, source_states : Element, target_s
|
|
|
if (element_neq(parameter_action, read_root())):
|
|
|
// Got a parameter to evaluate
|
|
|
parameter_action = resolve_function(parameter_action, data)
|
|
|
- parameter_action = parameter_action(class_data["attributes"])
|
|
|
+ parameter_action = parameter_action(data["classes"][data["current_class"]]["attributes"])
|
|
|
|
|
|
process_raised_event(model, event, parameter_action, data)
|
|
|
|
|
@@ -584,7 +595,7 @@ Void function execute_actions(model : Element, source_states : Element, target_s
|
|
|
Element timed_transitions
|
|
|
timed_transitions = filter_exists(model, allOutgoingAssociationInstances(model, state, "SCCD/transition"), "after")
|
|
|
while (read_nr_out(timed_transitions) > 0):
|
|
|
- dict_delete(class_data["timers"], set_pop(timed_transitions))
|
|
|
+ dict_delete(data["classes"][data["current_class"]]["timers"], set_pop(timed_transitions))
|
|
|
|
|
|
// Then do entry actions
|
|
|
while (read_nr_out(entry) > 0):
|
|
@@ -595,7 +606,7 @@ Void function execute_actions(model : Element, source_states : Element, target_s
|
|
|
if (element_neq(action, read_root())):
|
|
|
// Got a script, so execute!
|
|
|
action = resolve_function(action, data)
|
|
|
- action(class_data["attributes"])
|
|
|
+ action(data["classes"][data["current_class"]]["attributes"])
|
|
|
|
|
|
// Raise events
|
|
|
events = allAssociationDestinations(model, state, "SCCD/onEntryRaise")
|
|
@@ -607,7 +618,7 @@ Void function execute_actions(model : Element, source_states : Element, target_s
|
|
|
if (element_neq(parameter_action, read_root())):
|
|
|
// Got a parameter to evaluate
|
|
|
parameter_action = resolve_function(parameter_action, data)
|
|
|
- parameter_action = parameter_action(class_data["attributes"])
|
|
|
+ parameter_action = parameter_action(data["classes"][data["current_class"]]["attributes"])
|
|
|
|
|
|
process_raised_event(model, event, parameter_action, data)
|
|
|
|
|
@@ -619,7 +630,7 @@ Void function execute_actions(model : Element, source_states : Element, target_s
|
|
|
while (read_nr_out(timed_transitions) > 0):
|
|
|
transition = set_pop(timed_transitions)
|
|
|
after = resolve_function(read_attribute(model, transition, "after"), data)
|
|
|
- dict_add(class_data["timers"], transition, float_addition(data["time_sim"], after(class_data["attributes"])))
|
|
|
+ dict_add(data["classes"][data["current_class"]]["timers"], transition, float_addition(data["time_sim"], after(data["classes"][data["current_class"]]["attributes"])))
|
|
|
|
|
|
return !
|
|
|
|
|
@@ -662,7 +673,9 @@ Boolean function main(model : Element):
|
|
|
Element data
|
|
|
data = create_node()
|
|
|
dict_add(data, "classes", create_node())
|
|
|
- dict_add(data, "operations", create_node())
|
|
|
+ dict_add(data, "cache_operations", create_node())
|
|
|
+ dict_add(data, "cache_hierarchy", create_node())
|
|
|
+ dict_add(data, "current_class", "")
|
|
|
|
|
|
Float time_0
|
|
|
Float time_sim
|
|
@@ -715,6 +728,7 @@ Boolean function main(model : Element):
|
|
|
|
|
|
time_wallclock = time() - time_0
|
|
|
timeout = time_sim - time_wallclock
|
|
|
+ log("Pause for: " + cast_v2s(timeout))
|
|
|
|
|
|
// We should never get here!
|
|
|
return False!
|