The semantics of Junior (and REJO) has the standard format of conditional rewriting
rules [11].
One writes:
ß
t,E ---> t',E'
which means that:
The semantic of ß flag is defined by the Execution Context rewriting rules presented at the end of this document. The meaning of this flag changes according to the Junior implementation, for instance, in Storm implementation thare are more than 3 meanings.
Environments
An environment E is made of the following components:
The following notations are defined:
SUSP
|
STOP
|
TERM
|
|
SUSP
|
SUSP
|
SUSP
|
SUSP
|
STOP
|
SUSP
|
STOP
|
STOP
|
TERM
|
SUSP
|
STOP
|
TERM
|
¥1(ø , ß) equals SUSP if ø is STOP and ß is STOP or TERM; it equals ø otherwise. ¥2(ø , ß) equals SUSP if ß is STOP and ø is STOP or TERM; it equals ß otherwise.
E{S := t} associates the frozen instruction t to event S; E{S} is the frozen instruction associated to S.
TERM
Nothing,E ------> Nothing,E
STOP
Stop,E ------> Nothing,E
TERM
Atom(a),E ------> Nothing,E
with the side-effect of executing atomically action a.
TERM
ß
t,E ------> t',E'
u,E' ---> u',E''
----------------------------------------
ß
Seq(t,u),E ---> u',E''
If the first branch is not terminated, then it remains a sequence executing the residual of the first branch:
ß
t,E
---> t',E' ß != TERM
--------------------------------
ß
Seq(t,u),E
---> Seq(t',u),E'
There are two REJO sentences to invoke a reactive methode: in-line and call. In-line is not a Junior instruction; it just puts the Junior instructions in the line where the keyword appears. Unlike in-line sentence, call is really a Junior instruction (called Run) that behaves like another instruction, i.e. it executes a program returned by a Wrapper. In other words, one can see the in-line instruction as the static execution of a reactive method and call as the dynamic execution.
The rewrite rule of Run instructions is the following:
ß
wp ---> t
t,E ---> t', E'
--------------------------------
ß
Run(wp),E --->
t',E'
If both branches of the parallel operator are suspended (which is the initial situation at each instant), then execution can nondeterministically chooses to execute one of them, setting the move flag to indicate that end of instant must be postponed in order to let the other branch a chance to be executed. The two corresponding rules are:
ß
ø
t,E ---> t',E'
--------------------------------------------------------
SUSP
ParSUSP,SUSP(t,u),E ------>
Parß,SUSP(t',u),E'[move=true]
u,E ---> u',E'
--------------------------------------------------------
SUSP
ParSUSP,SUSP(t,u),E ------>
ParSUSP,ø(t,u'),E'[move=true]
If both branches of the parallel operator are suspended, execution can also execute both. The rule which executes the first branch, then the second, is called Merge:
ß
ø
t,E ---> t',E' u,E' ---> u',E''
-------------------------------------------------------
¥(ß,ø)
ParSUSP,SUSP(t,u),E ------>
Parµ1(ß,ø),µ2(ß,ø)(t',u'),E''
The second rule which executes the second branch, then the first one, is called InvMerge:
ø
ß
u,E ---> u',E' t,E' ---> t',E''
-------------------------------------------------------
¥(ß,ø)
ParSUSP,SUSP(t,u),E ------>
Parµ1(ß,ø),µ2(ß,ø)(t',u'),E''
Only one branch is suspended
If only one branch is suspended, then it is simply run (and, in this case, the move flag is left unchanged):
ß
ø
ø!=SUSP t,E ---> t',E'
--------------------------------------------------
¥(ß,ø)
ParSUSP,ø(t,u),E
------> Parµ1(ß,ø),µ2(ß,ø)(t',u),E'
ß!=SUSP u,E ---> u',E'
--------------------------------------------------
¥(ß,ø)
Parß,SUSP(t,u),E
------> Parµ1(ß,ø),µ2(ß,ø)(t,u'),E'
Note that, in all the rules of Par, production of a flag different
from SUSP is only possible when both branches have also produced a flag different
from SUSP; this reflects the synchronous characteristics of the parallel operator
which, at each instant, executes its two branches.
A Loop executes its body and rewrites in a sequence if it does not
terminate immediately:
ß
t,E ---> t',E' ß!=TERM
-------------------------------------
ß
Loop(t),E
---> Seq(t',Loop(t)),E'
When the loop body terminates immediately, the Loop is restarted:
TERM
ß
t,E ------> t',E' Loop(t),E
---> u,E''
-------------------------------------------
ß
Loop(t),E ---> u,E''
Repeat terminates immediately if the counter is less or equal to zero:
n <= 0
-----------------------------------
TERM
Repeat(n,t),E
------> Nothing,E
Otherwise, the semantics is the one of a sequence:
ß
n > 0 Seq(t,Repeat(n-1,t)),E
---> u,E'
----------------------------------------
ß
Repeat(n,t),E
---> u,E'
ß
bw = true t,E
---> t', E'
--------------------------------
ß
If(bw,t,u),E
---> t',E'
The second branch is chosen if the configuration is not satisfied
ß
bw = false
u,E ---> u', E'
--------------------------------
ß
If(bw,t,u),E
---> u',E'
This section presents some definitions used in the reactive instructions to test if an event is present or not.
Configurations
A configuration is either:
Two functions fixed and eval are defined for configurations. A configuration can be evaluated (function eval) only when it is fixed (function fixed):
Fixed
fixed(C,E) is true when configuration C can be evaluated in the environment E:
or fixed(C1,E) and eval(C1,E) = false
or fixed(C2,E) and eval(C2,E) = false
or fixed(C1,E) and eval(C1,E)
or fixed(C2,E) and eval(C2,E)
Note that in the basic case of an event S, fixed(S,E) is true if S is present or if the end of instant is set; this last case means that S is absent.
Eval
eval(C,E) returns the value of configuration C in the environment E:
Auxiliary Functions
Three auxiliary functions are also defined:
Note that unknown(C,E) is true if and only if sat(C,E) and unsat(C,E) are both false.
Note also that in the basic case of an event S, one has:
A Generate statement adds the generated event in the environment and immediately terminates:
TERM
Generate(S),E ------> Nothing,(E+S)[move=true]
sat(C,E)
eoi(E)=false sat(C,E)
eoi(E)=true
--------------------------------
TERM
Await(C),E ------> Nothing,E
--------------------------------
STOP
Await(C),E ------> Nothing,E
Await stops if the configuration is unsatisfied:
unsat(C,E)
--------------------------------
STOP
Await(C),E ------> Await(C),E
Await is suspended if the configuration is unknown:
unknown(C,E)
--------------------------------
SUSP
Await(C),E ------> Await(C),E
ß
sat(C,E) eoi(E)=true
sat(C,E) eoi(E)=false
t,E ---> t',E'
--------------------------------------------
ß
When(C,t,u),E ---> t',E'
-----------------------------
STOP
When(C,t,u),E ------> t,E
The second branch is chosen if the configuration is not satisfied; execution is immediate if unsatisfaction occurs before the end of the current instant, and is delayed to the next instant otherwise:
ß
unsat(C,E) eoi(E)=true
unsat(C,E) eoi(E)=false
u,E ---> u',E'
--------------------------------------------
ß
When(C,t,u),E ---> u',E'
-------------------------------
STOP
When(C,t,u),E ------> u,E
Note that the two previous rules returning STOP when eoi(E) is false basically forbid immediate reaction to events absences. The test is suspended if the configuration is unknown:
unknown(C,E)
---------------------------------------
SUSP
When(C,t,u),E
------> When(C,t,u),E
ß
t,E ---> t',E' ß!=STOP
----------------------------------------
ß
Until(C,t,u),E ---> Until(C,t',u),E'
If the body stops, Until behaves as the auxiliary instruction Until*:
STOP
ß
t,E ------> t',E' Until*(C,t',u),E ---> v,E''
--------------------------------------------------
ß
Until(C,t,u),E ---> v,E''
Note that the body t is executed in both rules; preemption of Until is said to be weak, by contrast with the strong preemption used in the synchronous approach, which basically implies instantaneous reaction to absence.
Until*
The rules for Until* are the following: The handler is immediately executed if the configuration is satisfied before the end of instant:
ß
sat(C,E) eoi(E)=false
u,E ---> u',E'
-------------------------------------------
ß
Until*(C,t,u),E ---> u',E'
Until* stops and rewrites in the handler, if the configuration is satisfied while end of instant is true:
sat(C,E) eoi(E)=true
----------------------------
ß
Until*(C,t,u),E ---> u,E
Until* stops and rewrites in Until, if the configuration is unsatisfied:
unsat(C,E) eoi(E)=true
------------------------------------------
STOP
Until*(C,t,u),E ------> Until(C,t,u),E
Until* is suspended while the configuration is unknown:
unknown(C,E)
-------------------------------------------
SUSP
Until*(C,t,u),E ------> Until*(C,t,u),E
ß
sat(S,E) t,E ---> t',E'
------------------------------------------
ß
Control(S,t),E --->
Control(S,t'),E
Control stops if the event is absent:
unsat(S,E)
------------------------------------------
STOP
Control(S,t),E ------> Control(S,t),E
Control is suspended if the event is unknown:
unknown(S,E)
------------------------------------------
SUSP
Control(S,t),E ------> Control(S,t),E
SUSP
SUSP
SUSP
t,E-S
------> t',E' S !€ E'
----------------------------------------------
SUSP
Local-(S,t),E ------> Local-(S,t'),E'/E[S]
t,E-S ------> t',E' S € E'
----------------------------------------------
SUSP
Local-(S,t),E ------> Local+(S,t'),E'/E[S]
t,E+S ------> t',E'
----------------------------------------------
SUSP
Local+(S,t),E ------> Local+(S,t'),E'/E[S]
When the body terminates or stops, then the local event is reset for the next instant:
ß
t,E-S ---> t',E'
ß=TERM or ß=STOP
----------------------------------------------
ß
Local-(S,t),E ---> Local-(S,t'),E'/E[S]
ß
t,E+S ---> t',E'
ß=TERM or ß=STOP
--------------------------------------------------
beta
Local+(S,t),E ------> Local-(S,t'),E'/E[S]
The semantics of Freezable is close to the one of Until. Freezable behaves as the body if it does not stops:
ß
t,E ---> t',E' ß!=STOP
--------------------------------------------
ß
Freezable(S,t),E
---> Freezable(S,t'),E'
If the body stops, Freezable behaves as the auxiliary instruction Freezable*:
STOP
ß
t,E ------> t',E' Freezable*(S,t'),E'
---> v,E'
----------------------------------------------------
ß
Freezable(S,t),E ---> v,E''
Note that the body t is executed in both rules; As Until, Freezable performs weak preemption.
Freezable*
The rules for Freezable* are the following: The instruction immediately terminates if the freezing event is present before the end of instant:
S € E eoi(E)=false
-----------------------------------------------------
TERM
Freezable*(S,t),E ------> Nothing,E{S:=Par(t,E{S})}
Note that the residual instruction t is put in parallel in the frozen instructions table. The instruction terminates at next instant if the freezing event is present while the end of instant is set:
S € E eoi(E)=true
-----------------------------------------------------
STOP
Freezable*(S,t),E ------> Nothing,E{S:=Par(t,E{S})}
Freezable* stops and rewrites in Freezable, if the freezing event is absent:
S !€ E eoi(E)=true
----------------------------------------------
STOP
Freezable*(S,t),E
------> Freezable(S,t),E
Freezable* is suspended while the freezing event is unknown:
S !€ E eoi(E)=false
-----------------------------------------------
SUSP
Freezable*(S,t),E
------> Freezable*(S,t),E
Execution context rewritings have the forme e => e' meaning that reaction of the execution context e leads to the new execution context e'; b is a boolean which is true if the execution context e' is completely terminated.
Execution Context
An execution context executes one instant of its program in a new fresh environment.
ø
Instant(t),Fresh
---> Instant(t'),E'
--------------------------------------------
ß
ExecContext(t),E
===> ExecContext(t'),E'
In this rule:
Instant
Execution of an instruction during one instant means cyclic execution while it is suspended. Moreover, when execution suspends, end of instant is detected if no new move setting was performed. The instant is terminated when the instruction is stopped or terminated:
ß
t,E ---> t',E' ß!=SUSP
------------------------------------
ß
Instant(t),E
---> Instant(t'),E'
Execution is immediately restarted if SUSP is returned and end of instant is set if no new move setting was performed:
SUSP ß
t,E ------>
t',E' move(E')=false Instant(t'),E'[eoi=true] --->
u,E''
------------------------------------------------------------------------
ß
Instant(t),E ---> u,E''
Execution is immediately restarted if SUSP is returned and move is reset if a move appeared:
SUSP ß
t,E ------>
t',E' move(E')=true Instant(t'),E'[move=false] --->
u,E''
-------------------------------------------------------------------------
ß
Instant(t),E ---> u,E''