3.1.6. About expressions and variables
Expressions can occur in six different positions in a Perspectives source text (illustrated in the next paragraph). An expression is like a function, applied to either a role instance or a context instance. Until now we’ve glossed over the question: to what instance is an expression applied, in execution time? The next paragraph is devoted to answering that question, but first we turn our attention to a number of standard variables. These variables take on a single value in runtime.
For convenience, we can use in any expression the standard variable origin. Its runtime value is always the context- or role instance that the expression is applied to. The name ‘origin’ reflects the path-like character of an expression: you can trace it from context to role and vice versa, through the network of types of your model. Runtime, these are paths laid out through the network of connected instances. Below we will show how you can determine the type of origin from the model source text. It will turn out to be either the current context, current subject, or current object.
Furthermore, we can always include the standard variable currentcontext in an expression. It’s type is the current context as we’ve used the concept above, in the lexical analysis of source texts.
In an action and an automatic action delegated by some user role, we can use the standard variable currentactor. It’s type is, unsurprisingly, the current subject of lexical analysis.
Finally, in a notify construct we can use the standard variable notifieduser that, again, has the current subject type.
3.1.6.1. What expressions are applied to
The definition of a calculated role
Given this model:
case C
role R = <expression>
<expression> is applied to the current context, which is an instance of C. The same holds for the other types of context (domain, party, activity). The value of origin is that same instance, and so is the value of currentcontext. Invariant: currentcontext == origin.
The definition of a calculated property
Given this model:
case C
thing R
property P = <expression>
<expression> is applied to the current object, which is an instance of R. The same holds for the other role types (context, external and user). The value of origin is that same instance, and the value of currentcontext is an instance of C. Invariant: currentcontext == origin >> context. NB: a (calculated) property is always embedded directly in the body of an enumerated role.
The condition of a context state
Given this model:
case C
state S = <expression>
<expression> is applied to the current context, which is an instance of C. The same holds for the other types of context (domain, party, activity). The value of origin is that same instance, and so is the value of currentcontext. Invariant: currentcontext == origin.
The condition of a role state
Given this model:
case C
thing R
state S = <expression>
<expression> is applied to the current object, which is an instance of R. The same holds for the other role types (context, external and user). The value of origin is that same instance, and the value of currentcontext is an instance of C. Invariant: currentcontext == origin >> context.
The object of a perspective
Given this model:
case C
user U
perspective on <expression>
<expression> is applied to the current context, which is an instance of C. The value of origin is that same instance, and so is the value of currentcontext. Invariant: currentcontext == origin.
Expressions in do
Given this model:
case C
thing R
property SomeProperty
user U
perspective on R
on entry of object state
do
SomeProperty = <expression>
<expression> is applied to an instance of R. This requires some explanation. Why not to an instance of U?
Let’s start with the question: what is the current state in the line that holds <expression>? Moving in from the outside: the body of case C has context state. But in the body of user U we have subject state. The body of on entry of object state changes that to the state of the current object. So what is the current object, at this position? It is determined by perspective on R, hence our <expression> is in the (root) state of role R: it is the current state for that expression. As a consequence, <expression> is applied to the thing that can be in that state, hence it is applied to an instance of R.
This turns out to be the way to find out, from analysis of the source text, the type of thing that an expression in the body of a do is applied to. Find the current state: the expression is applied to instances of the type that can be in that state.
Because we have context state, subject state and object state, expressions in the body of do can be applied to contexts, user roles and other roles.
origin consequently can be a context instance or a role instance.
There is another standard variable available for use in expressions in a do: currentactor. It is an instance of the current user for that expression, which, in our example, is U.
Finally, we have currentcontext: it is an instance of C.
Consider this variation on the example model:
case C
thing R
property SomeProperty
user U
perspective on R
on entry
do
SomeProperty = <expression>
(we’ve omitted the of object state after on entry). Consequently, the current state for <expression> is user state and so <expression> will be applied to an instance of U. As U has no property SomeProperty, the system will complain about this and not accept your model.
Expressions in do for a remote (calculated) perspective
Given this model:
case C1
thing R1
property SomeProperty
context C2S filledBy C2
case C2
user U
perspective on extern >> binder C2S >> context >> R1
on entry of object state
do
SomeProperty = <expression>
<expression> is applied to instances of C1$R1 (meaning: R1 in C1), so origin is an instance of R1. currentcontext is an instance of C2, currentactor is an instance of U, just as we’ve seen before. Now take a look at origin >> context. Does it equal currentcontext? No!
This is new. In many of the examples above, we had the invariant currentcontext == origin >> context (and in the other cases, currentcontext == origin). But here, it is not so. This is exactly the meaning of a ‘remote perspective’: the user has a perspective on a role outside the current context. For <expression>, this remote role is the origin.
Having both origin and currentcontext, we can access both contexts in our expression if we need to: the current context from our lexical analysis (the context ‘as we see it’ surrounding the expression), and the context of the resource that the expression is applied to (the origin).
Expressions in do for a remote (calculated) user
Consider this model:
case C1
user U1
context C2S filledBy C2
case C2
thing R
property SomeProperty
user U2 = extern >> binder C2S >> context >> U1
perspective on R
on entry of object state
do
SomeProperty = <expression>
Instead of having a remote object role, we now have a remote user role. This is reflected in the types and values of the standard variables: currentactor is an instance of C1$U1. currentactor >> context is not equal to currentcontext; the former is an instance of C1, the latter an instance of C2. origin is an instance of R.
Expressions in action
Given this model:
case C
thing R
property SomeProperty
user U
perspective on R
action
SomeProperty = <expression>
Is <expression> applied to an instance of U, or an instance of R? As with do, we have to ask ourselves: what is the current state for <expression>? Our state rules say that current state in the body of user is subject state (perspective on changes the current object, but does not change the current state). Hence, <expression> is applied to an instance of U and the system complains that U does not have property SomeProperty.
Now examine a variation on this model:
case C
thing R
property SomeProperty
user U
perspective on R
in object state
action
SomeProperty = <expression>
The system accepts this, because we’ve changed the current state to object state and so <expression> is applied to the current object, which is an instance of R.
In short: the rules for expressions in do apply to action as well, including the treatment of currentactor.
Expressions in notify
Given this model:
case C
thing R
property SomeProperty
property Name
state S = exists Name and exists SomeProperty
user U
property Nickname
perspective on R
on entry of object state S
notify
“Hello {notifieduser >> Nickname}. instance {Name} of R now has value {SomeProperty}
The expressions in the notification are applied to an instance of R, so origin holds that instance. notifieduser is an instance of the type of the current subject, which is U since we did not specify otherwise (given another user role U1, we might have written notify U1). currentcontext will be an instance of C.
In short: the rules for expressions in do apply to notify as well, but instead of currentactor we have notifieduser.
3.1.6.2. Summing up: what expressions are applied to
The table below summarises what expressions are applied to (and that resource is always available inside the expression as the origin variable). The standard variable currentcontext is also always available in each expression.
Expressions in | Applied to | standard variables other than origin and currentcontext |
---|---|---|
The definition of a calculated role |
Current context |
|
The definition of a calculated property |
Current object |
|
The condition of a context state |
Current context |
|
The condition of a role state |
Current object |
|
The object of a perspective |
Current context |
|
Expressions in do and action |
The resource in current state |
currentactor |
Expressions in notify |
The resource in current state |
notifieduser |
3.1.6.3. Delegate to a functional user role only!
We’ve seen that resources that expressions in action and in do are applied to, are determined by the same rules. Yet there is a difference between automated actions and actions that must be executed by hand. Automated actions are delegated by a user role. Suppose that this role could have more than one instance (as specified with the keyword Relational). We then would have a situation in which multiple PDR installations would execute the same action and claim the authorship of the changes to ‘their’ user!
Instead, we stipulate that the user role on whose behalf an action is executed automatically, must be functional. This obviously also holds for calculated user roles, but that may be less easy to see. Luckily, the system checks this for us and flags down the model if the calculation could result in more than one user instance.
3.1.6.4. Why perspective sets no state
You may have wondered why perspective on sets the current object, but does not change the current state. Consider this model:
domain SomeModel
case C
thing R
property SomeProperty (Boolean)
user U
perspective on R
action MyAction
SomeProperty = true
Its intended meaning seems clear: user U has an action called MyAction in her perspective on R. However, the system will raise an error to the effect that U does not have property SomeProperty. Let’s analyse why: the current state at the lexical position of MyAction is set by the user U declaration, so MyAction is subject state. Hence, the action holds for that state and will be applied to the current subject, being an instance of U. We can easily fix that:
domain ActionExample
case C
thing R
property SomeProperty (Boolean)
user U
perspective on R
in object state
action MyAction
SomeProperty = true
Now MyAction is in object state and will be applied to an instance of R. All is well.
This seems a perfect argument to have perspective on change the current state as well. But then we would run into problems with this model:
domain Parties
case Party
thing Wishes
user Guest
perspective on Wishes
all roleverbs
The current state for the line all roleverbs would become object state, meaning that the perspective holds for the root state of Wishes rather than the root state of Guest. That is not very intuitive. As models will usually be a lot more about specifying perspectives than actions, we have decided to construct the language in favour of the former. Hence we must use in object state for an action in the ActionExample model.