IRP Execution Model
Data structures
The dynamic aspect of the execution model processes the main bitspec and irstream of a protocol in a context set by the timer and carrier generator and certain parameters of fixed global scope. Since there can be further bitspecs and irstreams nested within the main irstream, the model uses stacks to keep track of which ones are current at any stage of the processing. The following data structures are used to model these various items.
STRUCT timer
BEGIN
- clock: real-time clock counting microseconds;
- now: the current time on the clock;
- START: operation that sets clock to zero and starts it running;
- STOP: operation that stops the clock;
END
STRUCT carrier generator
BEGIN
- frequency: the frequency in kilohertz of the carrier square wave;
- duty cycle: the duty cycle of the carrier square wave;
- TRANSMIT FOR: an operation that turns on the carrier for a specified time;
- WAIT FOR: an operation that waits with the carrier turned off for a specified time;
END
STRUCT global
BEGIN
- sequencing rule: an enumerated value, either "lsb" or "msb", that specifies the manner in which binary forms are converted to bit sequences;
- duration unit: the unit of time in microseconds in which durations and extents without a suffix are expressed;
END
STRUCT bitspec
BEGIN
- (* The bitspec buffer performs the process of converting binary forms to bit sequences *)
- N: the length of the bit sequences mapped by the bitspec;
- buffer: a FIFO buffer of bits awaiting processing by the bitspec, initially empty; PUSH pushes a binary form into the buffer one bit at a time (conceptually into the right hand end) in the order given by the global sequencing rule, PULL pulls a timeordered bit sequence of N bits out one at a time (conceptually out of the left hand end), earliest bit first;
- MAP: operation that maps bit sequences of length N to their corresponding bare irstreams;
END
STRUCT irstream
BEGIN
- content: the bare irstream (a list of irstream items)
- min count: the minimum number of times that the irstream should be executed, as specified by the repeat marker - in the case of a definite repeat number this is the actual number;
- repeat flag: boolean that is false if the repeat marker gives a definite number and is true if the repeat marker gives only a minimum number;
- bitspec flag: boolean specifying whether or not the irstream immediately follows a bitspec, set during parsing;
- final flag: boolean that controls the ending of an indefinite repeat sequence, tested at the start of a potential repeat execution it the button is then no longer held - if this is false then that repeat is not performed, if it is true then that repeat is performed;
- var3 flag: boolean that is set true during execution of an irstream if during that execution a variation is encountered that has three alternatives - used in the setting of the final flag;
- skip flag: boolean specifying whether processing of the remainder of this irstream should be skipped, initially false - used in the processing of an empty alternative;
- count: the number of transmissions currently made or in progress, initially zero
- start time: a time value set when processing of the irstream starts
END
STRUCT <item> stack
BEGIN
- stack: an ordered list of <item>, conceptually thought of as climbing upward
- pointer: a pointer to a (possibly empty) position in the stack; INCREMENT moves the pointer up one position, DECREMENT moves it down one position
- CREATE: an operation that creates an empty stack of <item> with pointer set to first (bottom) position;
- DESTROY: an operation that deletes a stack, empty or otherwise;
- INSERT INTO: a stack operation in which the <item>s at and beyond the pointer position are moved up one place, a specified new item is inserted at the pointer position and the pointer is then incremented;
- DELETE FROM: a stack operation in which the pointer is decremented, the <item> at the pointer position is deleted and all <item>s beyond the pointer position are moved down one place;
- current: the <item> one position lower than the pointer position (null if the pointer is at the bottom of the stack);
- (* In normal circumstances <item>s will only be added and removed at the top of the stack, in which case INSERT INTO and DELETE FROM correspond to PUSH and PULL. Unless there have been explicit pointer increments or decrements the current <item> will then be the one at the top of the stack. The recursion allowed by IRP notation can however cause <item>s to be inserted part way up. *)
END
Evaluation
The static operation of EVALUATE was described in 14.1 Although evaluation is static in the sense that it is not concerned with the progress of time during execution, evaluations are perfomed in the context of the state of the environment at the time that the EVALUATE operation is called. Successive evaluations of the same item may therefore give different results.
Although the process of evaluation is described by the semantics of the item being evaluated, descriptions are given here for each item type on which EVALUATE can act.
EVALUATE number
BEGIN
- RETURN value of the number as an integer in accordance with number semantics;
END
EVALUATE name
BEGIN
- IF name is bound to a value THEN
- RETURN value;
- ELSE IF name is bound to an expression THEN
- EVALUATE expression AS value;
- RETURN value;
- END IF;
- (* A name that has not been bound explicitly will still return a value. The description of the persistence of the global environment in 14.1 explains how this can be used to model remotes with "state" where this internal state affects the execution of the protocol. *)
END
EVALUATE expression
- Parse the expression in accordance with expression syntax;
- EVALUATE each primary item in the parse tree according to its type;
- Convert any binary form arising from a bitfield to its numerical value in accordance with expression semantics;
- RETURN value given by performing the unary and binary operations in the parse tree in accordance with expression semantics;
END
EVALUATE duration
BEGIN
- EVALUATE its name or number;
- Convert value to a time period in microseconds in accordance with the duration suffix and the duration semantics in the context of the global duration unit and carrier generator frequency;
- RETURN time period in microseconds;
END
EVALUATE extent
BEGIN
- EVALUATE its name or number;
- Convert value to a time period in microseconds in accordance with the extent suffix and the extent semantics in the context of the global duration unit and carrier generator frequency;
- RETURN time period in microseconds;
END
EVALUATE bitfield
BEGIN
- EVALUATE each primary item according to its type;
- Convert bitfield to binary form in accordance with bitfield semantics;
- RETURN binary form
END
Execution
As described in 14.1, execution processing is initiated by the pressing of a button on the conceptual remote control. By means outside the scope of IRP notation, this binds certain names to values in the global environment and sets the carrier generator duty cycle. It then initiates the procedure PROCESS protocol. This section describes the chain of processes that this initiates.
Processing of item types is specified in terms of their parsing by the EBNF syntax and the data structures that represent them in accordance with 14.2. In logical constructions, AND takes precedence over OR. The pronoun ITS is used to identify a part of the parsing structure or data structure of the item being processed, OF is used to identify a part of a different item. For example, the EBNF syntax for a bare irstream is
bare irstream = | irstream item, [",", bare irstream];
So in "PROCESS bare irstream", "IF bare irstream IS NOT EMPTY" refers to the bare irstream being processed (the one on the left of the syntax expression) but "PROCESS ITS bare irstream" refers to the one on the right. In the same context, "PROCESS buffer OF current bitspec" refers to a constituent of the data structure that represents the current bitspec, not to one of the bare irstream being processed. Comments have been made where there is potential ambiguity.
The processes of the execution model now follow.
PROCESS protocol
BEGIN
- CREATE bitspec stack;
- CREATE irstream stack;
- PROCESS ITS generalspec;
- PROCESS ITS definitions;
- START clock;
- PROCESS ITS bitspec;
- PROCESS ITS irstream;
- STOP clock;
- (* The binding of names to values is preserved in the persistence of the environment but the binding of names to bare expressions produced by the processing of definitions is not preserved. *)
- CLEAR ITS definitions;
- DESTROY irstream stack;
- DESTROY bitspec stack;
END
PROCESS generalspec
BEGIN
- SET carrier generator frequency FROM ITS frequency item;
- SET global duration unit FROM ITS unit item;
- SET global sequencing rule FROM ITS order item;
END
PROCESS definitions
BEGIN
- PROCESS ITS definitions list;
END
PROCESS definitions list
BEGIN
- IF definitions list IS NOT EMPTY THEN
- PROCESS ITS (* first *) definition;
- UNLESS ABSENT PROCESS ITS (* remaining *) definitions list;
- END IF
END
PROCESS definition
BEGIN
- BIND ITS name TO ITS bare expression;
END
PROCESS bitspec
BEGIN
- INSERT bitspec INTO bitspec stack;
END
PROCESS irstream
BEGIN
- INSERT irstream INTO irstream stack;
- SET ITS final flag = FALSE;
- SET ITS count = 0;
- DO WHILE ITS count < ITS min count OR (ITS repeat flag IS TRUE AND
- (button still held OR ITS final flag IS TRUE))
- SET ITS var3 flag = FALSE;
- SET ITS skip flag = FALSE;
- INCREMENT ITS count;
- SET ITS start time = now;
- (* Evaluate content in current environment settings *)
- PROCESS ITS bare irstream;
- (* Treat end of bare irstream like item that is not a bitfield *)
- PROCESS buffer OF current bitspec;
- IF NOT (ITS repeat flag IS TRUE AND button still held)
- (* this could never be known in advance to be final *)
- IF (ITS var3 flag IS TRUE OR ITS count EQUALS (ITS min count - 1) )
- AND ITS final flag IS FALSE THEN
- (* next execution needed and known to be final *)
- SET ITS final flag = TRUE;
- ELSE
- (* current execution was final, whether this was known when it started or not *)
- SET ITS final flag = FALSE;
- END IF;
- END IF;
- END DO;
- IF ITS bitspec flag IS TRUE THEN
- (* We have finished with the bitspec that preceded this irstream *)
- DELETE FROM bitspec stack;
- END IF
- DELETE FROM irstream stack;
END
PROCESS bare irstream
BEGIN
- IF skip flag OF current irstream IS FALSE AND bare irstream IS NOT EMPTY THEN
- (* Process first item *)
- IF ITS irstream item IS NOT bitfield THEN
- PROCESS buffer OF current bitspec;
- END IF;
- PROCESS ITS irstream item;
- (* Process the remaining items - if skip flag has just been set then this will be skipped due to the conditional at the start of this process *)
- UNLESS ABSENT PROCESS ITS bare irstream;
- END IF
- (* If the remaining bare irstream is absent, so we have completed the processing, it seems we should process bitspec buffer, treating the end of the recursion as an item other than a bare irstream, but this would be wrong as another bare irstream may follow, starting with a bitfield whose bits need to be concatenated with any left over here. We defer any final processing of the bitspec buffer till the end of the enclosing irstream. *)
END
PROCESS irstream item
BEGIN
- IF irstream item IS duration THEN
- EVALUATE duration AS time period;
- IF duration IS flash duration THEN
- TRANSMIT FOR time period;
- ELSE (* duration is gap duration *)
- WAIT FOR time period;
- END IF;
- ELSE IF irstream item IS extent THEN
- EVALUATE extent AS time period;
- IF now < (start time OF current irstream) + time period THEN
- WAIT UNTIL now = (start time OF current irstream) + time period;
- END IF;
- ELSE IF irstream item IS bitfield THEN
- EVALUATE bitfield AS binary form;
- IF current bitspec IS NULL THEN
- ERROR;
- ELSE
- PUSH binary form INTO buffer OF current bitspec;
- END IF;
- ELSE IF irstream item IS assignment THEN
- EVALUATE ITS expression AS value;
- BIND ITS name TO value;
- ELSE IF irstream item IS variation THEN
- IF number of alternatives in variation IS 3 THEN
- SET var3 flag OF current irstream = TRUE;
- END IF;
- IF count OF current irstream IS 1 THEN
- PROCESS ITS first alternative;
- ELSE IF ITS third alternative IS PRESENT AND final flag OF current irstream IS TRUE THEN
- PROCESS ITS third alternative;
- ELSE
- PROCESS second alternative;
- END IF;
- IF number of alternatives in variation IS 3 THEN
- ELSE IF irstream item IS bitspec THEN
- PROCESS irstream item AS bitspec;
- ELSE IF irstream item IS irstream THEN
- PROCESS irstream item AS irstream;
- END IF;
END
PROCESS alternative
BEGIN
- IF ITS bare irstream IS EMPTY THEN
- SET skip flag OF current irstream = TRUE;
- ELSE
- PROCESS ITS bare irstream
- END IF
END
PROCESS buffer
BEGIN
- (* This buffer is in scope of previous bitspec, if any *)
- IF buffer IS NOT EMPTY THEN
- DECREMENT bitspec stack pointer;
- DO WHILE number of bits in buffer >= N
- PULL bit sequence FROM buffer;
- MAP bit sequence TO bare irstream;
- PROCESS bare irstream;
- END DO;
- (* The current bitspec now was the previous bitspec on entry *)
- IF current bitspec IS NOT NULL THEN
- (* if an attempt has been made to push bits into its buffer, it will already have generated an error *)
- PROCESS buffer OF current bitspec;
- END IF;
- IF number of bits in buffer <> 0 THEN
- (* Consecutive bit sequences have been concatenated by processing of bare irstream so if any bits are left over, it is an error. *)
- ERROR;
- END IF;
- (* Finished with the new current bitspec, restore the old one *)
- INCREMENT bitspec stack pointer;
- END IF;
END;
CLEAR definitions
BEGIN
- CLEAR ITS definitions list;
END
CLEAR definitions list
BEGIN
- IF definitions list IS NOT EMPTY THEN
- CLEAR ITS (* first *) definition;
- UNLESS ABSENT CLEAR ITS (* remaining *) definitions list;
- END IF;
END