فهرست منبع

Minor updates and additional documentation

Yentl Van Tendeloo 7 سال پیش
والد
کامیت
fba22f05be
6فایلهای تغییر یافته به همراه232 افزوده شده و 160 حذف شده
  1. 116 124
      doc/actionlanguage.rst
  2. 6 2
      doc/interaction.rst
  3. 15 1
      doc/modeller_modellanguage.rst
  4. 36 12
      doc/modelling.rst
  5. 2 2
      doc/transformations.rst
  6. 57 19
      doc/wrappers.rst

+ 116 - 124
doc/actionlanguage.rst

@@ -282,127 +282,119 @@ Apart from the minimal syntax, the Modelverse supports a wide library of functio
 These functions are all built on top of the previously defined constructs.
 A list of these functions is shown below.
 
-* Boolean function value_eq(a: Element, b: Element)
-* Boolean function value_neq(a: Element, b: Element)
-* Boolean function bool_and(a: Boolean, b: Boolean)
-* Boolean function bool_or(a: Boolean, b: Boolean)
-* Boolean function bool_not(a: Boolean)
-* Element function create_node()
-* Element function create_edge(a: Element, b: Element)
-* Element function create_value(a: Element)
-* Boolean function is_edge(a: Element)
-* Integer function read_nr_out(a: Element)
-* Element function read_out(a: Element, b: Integer)
-* Integer function read_nr_in(a: Element)
-* Element function read_in(a: Element, b: Integer)
-* Element function read_edge_src(a: Element)
-* Element function read_edge_dst(a: Element)
-* Boolean function delete_element(a: Element)
-* Boolean function element_eq(a: Element, b: Element)
-* Boolean function element_neq(a: Element, b: Element)
-* Float function cast_i2f(a: Integer)
-* String function cast_i2s(a: Integer)
-* Boolean function cast_i2b(a: Integer)
-* Integer function cast_f2i(a: Float)
-* Boolean function cast_f2b(a: Float)
-* String function cast_f2s(a: Float)
-* Integer function cast_s2i(a: String)
-* Float function cast_s2f(a: String)
-* Boolean function cast_s2b(a: String)
-* Integer function cast_b2i(a: Boolean)
-* Float function cast_b2f(a: Boolean)
-* String function cast_b2s(a: Boolean)
-* String function cast_e2s(a: Element)
-* String function cast_a2s(a: Action)
-* String function cast_v2s(a: Element)
-* String function cast_id2s(a: Element)
-* Element function dict_add(a: Element, b: Element, c: Element)
-* Element function dict_add_fast(a: Element, b: Element, c: Element)
-* Element function dict_delete(a: Element, b: Element)
-* Element function dict_delete_node(a: Element, b: Element)
-* Element function dict_read(a: Element, b: Element)
-* Element function dict_read_edge(a: Element, b: Element)
-* Element function dict_read_node(a: Element, b: Element)
-* Integer function dict_len(a: Element)
-* Boolean function dict_in(a: Element, b: Element)
-* Boolean function dict_in_node(a: Element, b: Element)
-* Element function dict_keys(a: Element)
-* Float function float_addition(a: Float, b: Float)
-* Float function float_subtraction(a: Float, b: Float)
-* Float function float_multiplication(a: Float, b: Float)
-* Float function float_division(a: Float, b: Float)
-* Float function float_neg(a: Float)
-* Boolean function float_gt(a: Float, b: Float)
-* Boolean function float_gte(a: Float, b: Float)
-* Boolean function float_lt(a: Float, b: Float)
-* Boolean function float_lte(a: Float, b: Float)
-* Integer function integer_addition(a: Integer, b: Integer)
-* Integer function integer_subtraction(a: Integer, b: Integer)
-* Integer function integer_multiplication(a: Integer, b: Integer)
-* Integer function integer_division(a: Integer, b: Integer)
-* Integer function integer_modulo(a: Integer, b: Integer)
-* Boolean function integer_gt(a: Integer, b: Integer)
-* Boolean function integer_gte(a: Integer, b: Integer)
-* Boolean function integer_lt(a: Integer, b: Integer)
-* Boolean function integer_lte(a: Integer, b: Integer)
-* Boolean function integer_neg(a: Integer)
-* Element function list_read(a: Element, b: Integer)
-* Element function list_append(a: Element, b: Element)
-* Element function list_insert(a: Element, b: Element, c: Integer)
-* Element function list_delete(a: Element, b: Integer)
-* Integer function list_len(a: Element)
-* Boolean function list_in(a : Element, b : Element)
-* Element function set_add(a: Element, b: Element)
-* Element function set_add_node(a: Element, b: Element)
-* Element function set_pop(a: Element)
-* Element function set_read(a : Element)
-* Element function set_remove(a: Element, b: Element)
-* Boolean function set_in(a: Element, b: Element)
-* Element function set_remove_node(a: Element, b: Element)
-* Element function set_in_node(a: Element, b: Element)
-* Integer function set_len(a: Element)
-* String function string_join(a: String, b: String)
-* String function string_get(a: String, b: Integer)
-* String function string_substr(a: String, b: Integer, c: Integer)
-* Integer function string_len(a: String)
-* Element function string_split(a: String, b: String)
-* Boolean function string_startswith(a: String, b: String)
-* String function log(a: String)
-* Element function read_root()
-* Element function read_taskroot()
-* Element function input()
-* Element function output(a : Element)
-* Boolean function is_physical_int(a : Element)
-* Boolean function is_physical_float(a : Element)
-* Boolean function is_physical_string(a : Element)
-* Boolean function is_physical_action(a : Element)
-* Boolean function is_physical_boolean(a : Element)
-* Boolean function has_value(a : Element)
-* Float function time()
-* String function hash(a : String)
-* Void function sleep(a : Float)
-* Void function interruptable_sleep(a : Float)
-* Element function exec(a : Element)
-* Element function resolve(var_name : String)
-* Boolean function has_input()
-* Element function list_pop(lst : Element, index : Integer)
-* Element function list_pop_final(lst : Element)
-* Element function set_copy(set : Element)
-* String function set_to_string(set : Element)
-* String function list_to_string(set : Element)
-* String function dict_to_string(dict : Element)
-* Element function set_overlap(sa : Element, sb : Element)
-* Element function set_equality(sa : Element, sb : Element)
-* Element function dict_eq(da : Element, db : Element)
-* Element function dict_copy(dict : Element)
-* Element function set_to_list(s : Element)
-* Element function create_tuple(a : Element, b : Element)
-* Void function dict_overwrite(a : Element, b : Element, c : Element)
-* Void function set_merge(sa : Element, sb : Element)
-* Element function make_reverse_dictionary(dict : Element)
-* Element function set_create()
-* Element function list_create()
-* Element function dict_create()
-* String function reverseKeyLookup(a: Element, b: Element)
-* Element function reverseKeyLookupMulti(a: Element, b: Element)
-* Element function dict_values(dict : Element)
+* *Boolean function value_eq(a: Element, b: Element)*
+* *Boolean function value_neq(a: Element, b: Element)*
+* *Boolean function bool_and(a: Boolean, b: Boolean)*
+* *Boolean function bool_or(a: Boolean, b: Boolean)*
+* *Boolean function bool_not(a: Boolean)*
+* *Element function create_node()*
+* *Element function create_edge(a: Element, b: Element)*
+* *Element function create_value(a: Element)*
+* *Boolean function is_edge(a: Element)*
+* *Integer function read_nr_out(a: Element)*
+* *Element function read_out(a: Element, b: Integer)*
+* *Integer function read_nr_in(a: Element)*
+* *Element function read_in(a: Element, b: Integer)*
+* *Element function read_edge_src(a: Element)*
+* *Element function read_edge_dst(a: Element)*
+* *Boolean function delete_element(a: Element)*
+* *Boolean function element_eq(a: Element, b: Element)*
+* *Boolean function element_neq(a: Element, b: Element)*
+* *Float function cast_float(a: Element)*
+* *String function cast_string(a: Element)*
+* *Boolean function cast_boolean(a: Element)*
+* *Integer function cast_integer(a: Element)*
+* *String function cast_id(a: Element)*
+* *String function cast_value(a: Element)*
+* *Element function dict_add(a: Element, b: Element, c: Element)*
+* *Element function dict_add_fast(a: Element, b: Element, c: Element)*
+* *Element function dict_delete(a: Element, b: Element)*
+* *Element function dict_delete_node(a: Element, b: Element)*
+* *Element function dict_read(a: Element, b: Element)*
+* *Element function dict_read_edge(a: Element, b: Element)*
+* *Element function dict_read_node(a: Element, b: Element)*
+* *Integer function dict_len(a: Element)*
+* *Boolean function dict_in(a: Element, b: Element)*
+* *Boolean function dict_in_node(a: Element, b: Element)*
+* *Element function dict_keys(a: Element)*
+* *Float function float_addition(a: Float, b: Float)*
+* *Float function float_subtraction(a: Float, b: Float)*
+* *Float function float_multiplication(a: Float, b: Float)*
+* *Float function float_division(a: Float, b: Float)*
+* *Float function float_neg(a: Float)*
+* *Boolean function float_gt(a: Float, b: Float)*
+* *Boolean function float_gte(a: Float, b: Float)*
+* *Boolean function float_lt(a: Float, b: Float)*
+* *Boolean function float_lte(a: Float, b: Float)*
+* *Integer function integer_addition(a: Integer, b: Integer)*
+* *Integer function integer_subtraction(a: Integer, b: Integer)*
+* *Integer function integer_multiplication(a: Integer, b: Integer)*
+* *Integer function integer_division(a: Integer, b: Integer)*
+* *Integer function integer_modulo(a: Integer, b: Integer)*
+* *Boolean function integer_gt(a: Integer, b: Integer)*
+* *Boolean function integer_gte(a: Integer, b: Integer)*
+* *Boolean function integer_lt(a: Integer, b: Integer)*
+* *Boolean function integer_lte(a: Integer, b: Integer)*
+* *Boolean function integer_neg(a: Integer)*
+* *Element function list_read(a: Element, b: Integer)*
+* *Element function list_append(a: Element, b: Element)*
+* *Element function list_insert(a: Element, b: Element, c: Integer)*
+* *Element function list_delete(a: Element, b: Integer)*
+* *Integer function list_len(a: Element)*
+* *Boolean function list_in(a : Element, b : Element)*
+* *Element function set_add(a: Element, b: Element)*
+* *Element function set_add_node(a: Element, b: Element)*
+* *Element function set_pop(a: Element)*
+* *Element function set_read(a : Element)*
+* *Element function set_remove(a: Element, b: Element)*
+* *Boolean function set_in(a: Element, b: Element)*
+* *Element function set_remove_node(a: Element, b: Element)*
+* *Element function set_in_node(a: Element, b: Element)*
+* *Integer function set_len(a: Element)*
+* *String function string_join(a: String, b: String)*
+* *String function string_get(a: String, b: Integer)*
+* *String function string_substr(a: String, b: Integer, c: Integer)*
+* *Integer function string_len(a: String)*
+* *Element function string_split(a: String, b: String)*
+* *Boolean function string_startswith(a: String, b: String)*
+* *String function log(a: String)*
+* *Element function read_root()*
+* *Element function read_taskroot()*
+* *Element function input()*
+* *Element function output(a : Element)*
+* *Boolean function is_physical_int(a : Element)*
+* *Boolean function is_physical_float(a : Element)*
+* *Boolean function is_physical_string(a : Element)*
+* *Boolean function is_physical_action(a : Element)*
+* *Boolean function is_physical_boolean(a : Element)*
+* *Boolean function is_physical_none(a : Element)*
+* *Boolean function is_error(a : Element)*
+* *Boolean function has_value(a : Element)*
+* *Float function time()*
+* *String function hash(a : String)*
+* *Void function sleep(a : Float)*
+* *Void function interruptable_sleep(a : Float)*
+* *Element function exec(a : Element)*
+* *Element function resolve(var_name : String)*
+* *Boolean function has_input()*
+* *Element function list_pop(lst : Element, index : Integer)*
+* *Element function list_pop_final(lst : Element)*
+* *Element function set_copy(set : Element)*
+* *String function set_to_string(set : Element)*
+* *String function list_to_string(set : Element)*
+* *String function dict_to_string(dict : Element)*
+* *Element function set_overlap(sa : Element, sb : Element)*
+* *Element function set_equality(sa : Element, sb : Element)*
+* *Element function dict_eq(da : Element, db : Element)*
+* *Element function dict_copy(dict : Element)*
+* *Element function set_to_list(s : Element)*
+* *Element function create_tuple(a : Element, b : Element)*
+* *Void function dict_overwrite(a : Element, b : Element, c : Element)*
+* *Void function set_merge(sa : Element, sb : Element)*
+* *Element function make_reverse_dictionary(dict : Element)*
+* *Element function set_create()*
+* *Element function list_create()*
+* *Element function dict_create()*
+* *String function reverseKeyLookup(a: Element, b: Element)*
+* *Element function reverseKeyLookupMulti(a: Element, b: Element)*
+* *Element function dict_values(dict : Element)*

+ 6 - 2
doc/interaction.rst

@@ -48,11 +48,14 @@ For most users, there are only three relevant scripts, none of them taking param
 Wrapper
 -------
 
-In addition to these scripts, we provide a simple Python-based wrapper for the Modelverse.
+Most often, however, the Modelverse is not used using the raw interface.
+Therefore, additionally we provide a simple Python-based wrapper for the Modelverse, which can be included in arbitrary scripts.
 As the Modelverse can run as a service, wrappers can be created in any language that supports XML/HTTPRequests.
 By default, a Python wrapper is provided, which is discussed in this documentation.
 This Python wrapper was used by a variety of MvI implementations supported today.
 Tools can include all Modelverse operations merely by including the *modelverse.py* file from the *wrappers* folder.
+It is this interface that is used throughout this documentation, although other interfaces are highly similar.
+Note that the Python interface is a synchronous, and therefore blocking, interface.
 
 The wrapper provides all necessary (meta-)modelling operations that can be used by the MvI.
 As the Modelverse is independent of its (visual/textual) user interface, we only discuss the Modelverse wrapper in this documentation.
@@ -74,7 +77,8 @@ For that, you must start up a Modelverse at your own system by invoking the comm
     python scripts/run_local_modelverse.py
 
 Afterwards, connect to the local Modelverse through the usual *init* operation.
-Note that, for a local Modelverse, the init can be left empty::
+For a local Modelverse, the init can be left empty.
+This call might block for some time if the Modelverse server is still starting up::
 
     >>> init()
 

+ 15 - 1
doc/modeller_modellanguage.rst

@@ -58,7 +58,7 @@ Example: Finite State Automata
 ------------------------------
 
 Next we use a simple Finite State Automata example model.
-This will introduce two new concepts: hierarchy and code attributes.
+This will introduce two new concepts: hierarchy, long strings, and code attributes.
 
 Hierarchy
 ^^^^^^^^^
@@ -122,6 +122,20 @@ As there is no difference between *Contains* and *Transition*, there is nothing
 In this case, the state *state 1* and *state 2* are actually at the same level, with a transition between them.
 This can get rather confusing, and is therefore discouraged.
 
+Long string attributes
+^^^^^^^^^^^^^^^^^^^^^^
+
+Sometimes longer string values are required in attributes, for example as code blocks or descriptions of elements.
+In this case, three double quotes are used to delimit this string, similar to Python.
+Note that an ordinary double quote is not allowed within this long string attribute, due to limitations of the parser::
+
+    State s1 {
+        description = """
+        This is a lenghty description of the state.
+        In this state, the execution will start.
+        """
+    }
+
 Code
 ^^^^
 

+ 36 - 12
doc/modelling.rst

@@ -10,9 +10,14 @@ Both the *P2T* and *T2P*"arcs have a *weight*.
 This information is stored in the metamodel, which we will define later on.
 For now, assume that the metamodel is stored in the Modelverse using the name *PetriNets*.
 
-Creating a model
+Model Management
 ----------------
 
+Modellers have access to a variety of model management operations, making it possible to create, read, update, and delete complete models.
+
+Create
+^^^^^^
+
 Creating a new instance of PetriNets is simple, and can be done using the *model_add* operation of the wrapper::
 
     >>> model_add("models/my_pn", "formalisms/PetriNets")
@@ -22,6 +27,9 @@ This name is available to all users, and is therefore a unique identifier.
 The second parameter is the metamodel that we want to use to conform to.
 The value needs to be a name that is available in the Modelverse, and readable to the current user.
 
+Read
+^^^^
+
 To get a list of currently available models, users can query the Modelverse with the *model_list* operation::
 
     >>> model_list("")
@@ -42,12 +50,29 @@ Depending on permissions, not all folders can be listed::
     >>> model_list("administration")
     PermissionDenied("administration")
 
+Update
+^^^^^^
+
+Models can be updated in the sense that they can be moved.
+This is the operation *model_move*, which takes a model and moves it to the specified location.
+There is no output to this operation::
+
+    >>> model_move("models/my_pn", "models/my_new_pn")
+
+Delete
+^^^^^^
+
+Finally, models can be deleted using the *model_delete* operations.
+Model deletion is permanent and cannot be reverted::
+
+    >>> model_delete("models/my_pn")
+
 Modifying a model
 -----------------
 
-Now that we have created our model, we can start modifying it.
-To do so, we have access to several operations offered by the Modelverse.
+Apart from operations at the model management level, where models are considered as atomic, several operations are provided to operate on the model contents.
 We categorize them by their effects on the Modelverse: create, read, or delete.
+Updates are not allowed, and must be expanded in individual delete and create operation.
 Create and delete operations are only allowed when the user has write permission to the model, which users have by default on their own models.
 
 Create
@@ -58,11 +83,11 @@ Create
         >>> instantiate("models/my_pn", "Place")
         __12345
 
-    The operation requires the model on which we are working, and the type of the element you want to instantiate.
-    When successful, the operation returns the identifier that can be used in future operations.
-    This identifier has no value within the model, and should only be used as a handle to that specific model element.
+   The operation requires the model on which we are working, and the type of the element you want to instantiate.
+   When successful, the operation returns the identifier that can be used in future operations.
+   This identifier has no value within the model, and should only be used as a handle to that specific model element.
 
-    When instantiating an edge, the optional *edge* parameter must be passed with the identifiers to connect::
+   When instantiating an edge, the optional *edge* parameter must be passed with the identifiers to connect::
         
         >>> instantiate("models/my_pn", "Place")
         p1
@@ -86,17 +111,17 @@ Create
 Read
 ^^^^
 
-1. *read* reads out basic information about a queried element, such as its type and the source and target (if it is an edge)::
+1. *read_info* reads out basic information about a queried element, such as its type and the source and target (if it is an edge)::
 
         >>> instantiate("models/my_pn", "Place")
         p1
-        >>> read("models/my_pn", "p1")
+        >>> read_info("models/my_pn", "p1")
         ("Place, None)
         >>> instantiate("models/my_pn", "Transition")
         t1
         >>> instantiate("models/my_pn", "P2T", edge=("p1", "t1"))
         p2t1
-        >>> read("models/my_pn", "p2t1")
+        >>> read_info("models/my_pn", "p2t1")
         ("P2T", ("p1", "t1"))
 
 2. *read_attrs* reads out the attributes of a specific element, in a dictionary form.
@@ -159,13 +184,12 @@ Read
 
 9. *connections_between* reads out the set of all association types that can be created between two elements in the model.
    This also takes into account inheritance information.
+   If no associations are allowed, the list is empty.
    For example, to find out which association types can connect a place and transition::
 
         >>> connections_between("models/my_pn", "p1", "t1")
         ["P2T"]
 
-    If no associations are allowed, the list is empty.
-
 10. *all_instances* read out the set of all instances of a specific type in the model.
     For example, to find all Places in our PetriNet model::
 

+ 2 - 2
doc/transformations.rst

@@ -99,8 +99,7 @@ An example specification is shown below, which will copy the highest number of t
 
         constraint = $
             Boolean function constraint(host_model : Element, mapping : Element):
-                return value_eq(read_attribute(host_model, mapping["pn_place_master"], "name"), 
-                                read_attribute(host_model, mapping["pn_place_slave"], "name"))!
+                return value_eq(read_attribute(host_model, mapping["pn_place_master"], "name"), read_attribute(host_model, mapping["pn_place_slave"], "name"))!
                 $
     }
     RHS {
@@ -111,6 +110,7 @@ An example specification is shown below, which will copy the highest number of t
             label = "pn_place_slave"
             value_tokens = $
                 Integer function value(host_model : Element, name : Element, mapping : Element):
+                    return read_attribute(host_model, mapping["pn_place_master"], "tokens")!
                 $
         }
     }

+ 57 - 19
doc/wrappers.rst

@@ -48,7 +48,6 @@ Functions
    * To create a connection to a local Modelverse.
 
      >>> init()
-     Done
 
    * To create a connection to the Modelverse running remotely.
 
@@ -305,13 +304,14 @@ Functions
 
      >>> transformation_add_MANUAL({"pn": "formalisms/PetriNets", "requirements": "formalisms/Requirements"}, {"pn": "formalisms/PetriNets"}, "models/pn_refine_req")
 
-.. function:: transformation_execute_AL(operation_name, input_models_dict, output_models_dict, callback=lambda i: None)
+.. function:: transformation_execute_AL(operation_name, input_models_dict, output_models_dict, statechart=None)
 
    Executes the Action Language model *operation_name* with *input_models_dict* as inputs and *output_models_dict* as outputs.
    For both dicts, the contents describe the mapping between the parameter names of the operation to the names in the Modelverse.
    Values in *input_models_dict* must be existing models, whereas values in *output_models_dict* can be non-existing upon invocation.
-   A *callback* function can be defined when the action language model requires user input or output.
-   This callback function can be used to communicate with the executing action language directly.
+   A *statechart* tuple can be defined when the action language model requires user input or output.
+   This is used to communicate with the executing code directly.
+   For more information about this, refer to the execution of transformations.
 
    Examples:
 
@@ -319,13 +319,6 @@ Functions
 
      >>> transformation_execute_AL("models/pn_analyze", {"pn": "models/my_pn"}, {"graph": "models/my_pn_reachability"})
 
-   * To execute reachability analysis which prompts the user, for example because it is a debugging prompt.
-
-     >>> def callback(value):
-     ...     print(value)       # Prints out the prompt of the execution of the Action Language fragment
-     ...     return raw_input() # Sends a raw request from the user to the Modelverse, consumed in the Action Language
-     >>> transformation_execute_AL("models/pn_simulate", {"pn": "models/my_pn"}, {"graph": "models/my_pn_reachability"}, callback)
-
 .. function:: transformation_execute_MANUAL(operation_name, input_models_dict, output_models_dict, callback=lambda i: None)
 
    Executes the manual model operation *operation_name*.
@@ -343,7 +336,7 @@ Functions
      ...     instantiate(None, "pn/P2T", (p1, t1))
      >>> transformation_execute_MANUAL("models/pn_refine", {"pn": "models/my_pn"}, {"pn": "models/my_pn"}, callback)
 
-.. function:: transformation_execute_MT(operation_name, input_models_dict, output_models_dict, callback=lambda i: None)
+.. function:: transformation_execute_MT(operation_name, input_models_dict, output_models_dict, statechart=None)
 
    Executes the model transformation operation *operation_name*.
    Identical to *transformation_execute_AL*.
@@ -354,13 +347,6 @@ Functions
 
      >>> transformation_execute_MT("models/pn_simulate", {"pn": "models/my_pn"}, {"pn": "models/my_simulated_pn"})
 
-   * To execute a model transformation which prompts the user.
-
-     >>> def callback(value):
-     ...     print(value)
-     ...     return raw_input()
-     >>> transformation_execute_MT("models/pn_simulate_prompt", {"pn": "models/my_pn"}, {"pn": "models/my_simulated_pn"}, callback)
-
 .. function:: process_execute(process_name, prefix, callbacks)
 
    Execute the process model stored as *process_name*.
@@ -368,6 +354,7 @@ Functions
    Note that this applies to the resolution of input models as well.
    Optionally, a dictionary of *callbacks* can be defined with as key the operation that is being executed, and value the actual callback.
    The callbacks must be similarly defined just like how they were defined in the individual *transformation_execute* operations.
+   This means that the callback might very well be a tuple for a statechart instance.
 
    Examples:
 
@@ -1220,6 +1207,57 @@ Below is a list of all exceptions that the wrappers can raise, together with a s
      >>> element_list()
      UnknownMetamodellingHierarchy("models/my_pn")
 
+SCCD
+----
+
+An SCCD interface is created, which has exactly the same interface.
+Actually, the Python interface presented before is built using this SCCD interface.
+The operations are identical and have the same signature, although they are invoked differently.
+
+To make a request to the Modelverse, an event has to be raised called *action*.
+The first parameter of this event is the operation to invoke, as a string (*e.g.*, 'read_info').
+The second parameter specifies an ID that can be used in the response event to identify which event this is the response to.
+The third parameter is unused.
+The fourth parameter is a list of all the parameters to this function (*e.g.*, ["my_pn"]).
+For example::
+
+    <raise event="action">
+        <parameter expr="'read_info'"/>
+        <parameter expr="None"/>
+        <parameter expr="None"/>
+        <parameter expr="['my_pn']"/>
+    </raise>
+
+When this request is processed, the Modelverse will reply with the *mv_result* event, containing the result.
+The first parameter is the ID passed on in the original request.
+The second parameter contains the result.
+It is possible to wait on this event as follows::
+
+    <transition event="mv_result" target=".">
+        <parameter name="ID"/>
+        <parameter name="result"/>
+        <script>
+            print("Response: " + str(result))
+        </script>
+    </transition>
+
+If something went wrong, the event *mv_exception* will be raised instead::
+
+    <transition event="mv_exception" target=".">
+        <parameter name="ID"/>
+        <parameter name="exception_name"/>
+        <parameter name="exception"/>
+        <script>
+            print("Exception: " + str(exception_name))
+            print(exception)
+        </script>
+    </transition>
+
+The use of the SCCD interface is particularly interesting in case asynchronous communication is required.
+In contrast to the Python interface, requests don't block, making it possible to do additional computations in the background, or even work in a multi-threaded context.
+Note, however, that the SCCD interface is more difficult to use with callbacks and other statecharts, as you will have to manually make the linkage with ports.
+For this, we refer to the implementation.
+
 Custom
 ------