{'fraction_non_alphanumeric': 0.03441966592044085, 'fraction_numerical': 0.005058550025830894, 'mean_word_length': 4.247007002484753, 'pattern_counts': {'":': 0, '<': 0, '<?xml version=': 0, '>': 1, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 19, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
Instruction sequences with dynamically instantiated instructions

We study sequential programs that are instruction sequences with dynamically instantiated instructions. We define the meaning of such programs in two different ways. In either case, we give a translation by which each program with dynamically instantiated instructions is turned into a program without them that exhibits on execution the same behaviour by interaction with some service. The complexity of the translations differ considerably, whereas the services concerned are equally simple. However, the service concerned in the case of the simpler translation is far more powerful than the service concerned in the other case.


Introduction
In this paper, we study sequential programs that are instruction sequences with dynamically instantiated instructions. With that we carry on the line of research with which a start was made in [3]. The object pursued with this line of research is the development of a theoretical understanding of possible forms of sequential programs, starting from the simplest form. The view is taken that sequential programs in the simplest form are sequences of instructions. Program algebra, an algebra of programs in which programs are looked upon as sequences of instructions, is taken for the basis of the development aimed at.
The approach to define the meaning of programs followed in this line of research is called projection semantics. It explains the meaning of programs in terms of known programs instead of more or less sophisticated mathematical objects that represent behaviours of programs under execution. The main advantage of projection semantics is that it does not require a lot of mathematical background. Over and above that, the view is taken that the behaviours of sequential programs under execution are threads as considered in basic thread algebra [3]. 1 Therefore, the meaning of the programs considered in program algebra is explained in terms of threads. The experience gained so far leads us to believe that sequential programs are nothing but linear representations of threads.
Sequential programs in the form of assembly programs up to and including sequential programs in the form of structured programs are covered in [3]. However, although they are found in existing assembly programming practice, indirect jump instructions are not considered. In [5], several kinds of indirect jump instructions are considered, including a kind by which recursive method calls can easily be explained. Dynamic instruction instantiation is a programming feature that is not suggested by existing programming practice. However, from the viewpoint that sequential programs are nothing but linear representations of threads, it is a genuine programming feature. It is a useful programming feature as well, as will be illustrated by means of an example in the paper. Therefore, we consider a theoretical understanding of instruction sequences with dynamically instantiated instructions relevant to programming.
We believe that interaction with services provided by an execution environment is inherent in the behaviour of programs under execution. Intuitively, some service provides for dynamic instruction instantiation. In this paper, we define the meaning of programs with dynamically instantiated instructions in two different ways. In either case, we give a translation by which each program with dynamically instantiated instructions is turned into a program without them that exhibits on execution the same behaviour by interaction with some service. In one case, the service concerned provides in effect for the dynamic instruction instantiation and, in the other case, it is largely achieved by the translated programs. We consider it useful to treat both cases because of the considerable difference in complexity of the two translations.
A thread proceeds by doing steps in a sequential fashion. A thread may do certain steps only for the sake of having itself affected by some service. The interaction between behaviours of programs under execution and some service referred to above is an interaction with that purpose. In [7], the use mechanism is introduced to allow for such a kind of interaction between threads and services. In this paper, we will use a generalization of the use mechanism, called the action transforming use mechanism, to have behaviours of programs under execution affected by services. This generalization is reminiscent of the state operator introduced in [1].
A hierarchy of program notations rooted in program algebra is introduced in [3]. In this paper, we embroider on one program notation that belongs to this hierarchy. The program notation in question, called PGLD, is a very simple program notation which is close to existing assembly languages. The hierarchy also includes a program notation, called PGLS, that supports structured programming by offering a rendering of conditional and loop constructs instead of (unstructured) jump instructions. Each PGLS program can be translated into a semantically equivalent PGLD program by means of the projection semantics of PGLS and some intermediate program notations.
This paper is organized as follows. First, we review basic thread algebra, program algebra, and program notation PGLD (Sections 2, 3, and 4). Next, we provide a simple classification of services that will be used in subsequent sections (Section 5). After that, we extend basic thread algebra with the action transforming use mechanism and introduce a state-based approach to describe services (Sections 6 and 7). Then, we give a state-based description of a service that can provide for dynamic instruction instantiation and use that service to define the meaning of the programs from a variant of the program notation PGLD with dynamically instantiated instructions (Sections 8 and 9). Following this, we introduce a concrete notation for basic instructions that covers dynamically instantiated instructions and use that notation to illustrate the usefulness of dynamic instruction instantiation (Section 10). Thereupon, we give a state-based description of a register file service and use that service to define the meaning of the programs from the variant of the program notation PGLD with dynamically instantiated instructions in another way (Sections 11 and 12). Finally, we discuss the semantic approaches followed in the preceding sections and make some concluding remarks (Sections 13 and 14).

Basic Thread Algebra
In this section, we review BTA (Basic Thread Algebra), a form of process algebra which is concerned with the behaviours that sequential programs exhibit on execution. The behaviours concerned are called threads. BTA was first presented in [3]. In that paper, as well as several other papers, BTA is called BPPA (Basic Polarized Process Algebra).
In BTA, it is assumed that there is a fixed but arbitrary finite set of basic actions A with tau ∈ A. We write A tau for A ∪ {tau}. The members of A tau are referred to as actions.
A thread performs basic actions in a sequential fashion. The intuition is that each basic action performed by a thread is taken as a command to be processed by a service provided by the execution environment of the thread. The processing of a command may involve a change of state of the service concerned. At completion of the processing of the command, the service produces a reply value and returns that reply value to the thread. The reply value is either T or F and determines how the thread proceeds.
Although BTA is one-sorted, we make this sort explicit. The reason for this is that we will extend BTA with an additional sort in Section 6.
The algebraic theory BTA has one sort: the sort T of threads. To build terms of sort T, BTA has the following constants and operators: the inaction constant D : T; Table 1. Axiom of BTA the termination constant S : T; -for each a ∈ A tau , the binary postconditional composition operator a : T × T → T.
Terms of sort T are built as usual (see e.g. [16,17]). Throughout the paper, we assume that there are infinitely many variables of sort T, including x, y, z.
We use infix notation for postconditional composition. We introduce action prefixing as an abbreviation: a • p, where p is a term of sort T, abbreviates p a p.
The thread denoted by a closed term of the form p a q will first perform a, and then proceed as the thread denoted by p if the processing of a leads to the reply T (called a positive reply) and proceed as the thread denoted by q if the processing of a leads to the reply F (called a negative reply). The action tau plays a special role. It is a concrete internal action: the processing of tau will never involve a state change and always lead to a positive reply, but notwithstanding all that its presence matters. The threads denoted by D and S will become inactive and terminate, respectively.
BTA has only one axiom. This axiom is given in Table 1. Using the abbreviation introduced above, axiom T1 can be written as follows: Each closed BTA term of sort T denotes a finite thread, i.e. a thread that will become inactive or terminate after it has performed finitely many actions. Infinite threads can be described by guarded recursion specifications.
A guarded recursive specification over BTA is a set of recursion equations E = {X = p X | X ∈ V }, where V is a set of variables of sort T and each p X is a term of the form D, S or p a q with p and q BTA terms of sort T that contain only variables from V . We write V(E) for the set of all variables that occur on the left-hand side of an equation in E. We are only interested in models of BTA in which guarded recursive specifications have unique solutions, such as the projective limit model of BTA presented in [2]. A thread that is the solution of a finite guarded recursive specification over BTA is called a finite-state thread.
We extend BTA with guarded recursion by adding constants for solutions of guarded recursive specifications and axioms concerning these additional constants. For each guarded recursive specification E and each X ∈ V(E), we add a constant of sort T standing for the unique solution of E for X to the constants of BTA. The constant standing for the unique solution of E for X is denoted by X|E . Moreover, we add the axioms for guarded recursion given in Table 2 to BTA, where we write t X |E for t X with, for all Y ∈ V(E), all occurrences of Y in t X replaced by Y |E . In this table, X, t X and E stand for an arbitrary variable of sort T, an arbitrary BTA term of sort T and an arbitrary guarded recursive specification over BTA, respectively. Side conditions are added to restrict the variables, terms and guarded recursive specifications for which X, t X and E stand. RDP stands for recursive definition principle and RSP stands for recursive specification principle. The equations X|E = t X |E for a fixed E express that the constants X|E make up a solution of E. The conditional equations E ⇒ X = X|E express that this solution is the only one. It is easily demonstrated that RDP and RSP hold in the model of BTA based on projective sequences outlined in [3] (cf. Theorem 1 from [8]). We will use the following abbreviation: a ω , where a ∈ A tau , abbreviates X|{X = a • X} .
We will write BTA+REC for BTA extended with the constants for solutions of guarded recursive specifications and axioms RDP and RSP.
In [4], we show that the threads considered in BTA+REC can be viewed as processes that are definable over ACP [12].

Program Algebra
In this section, we review PGA (ProGram Algebra), an algebra of sequential programs based on the idea that sequential programs are in essence sequences of instructions. PGA provides a program notation for finite-state threads.
In PGA, it is assumed that there is a fixed but arbitrary finite set A of basic instructions. PGA has the following primitive instructions: for each a ∈ A, a plain basic instruction a; -for each a ∈ A, a positive test instruction +a; -for each a ∈ A, a negative test instruction −a; -for each l ∈ N, a forward jump instruction #l; -a termination instruction !.
We write I for the set of all primitive instructions.
The intuition is that the execution of a basic instruction a may modify a state and produces T or F at its completion. In the case of a positive test instruction +a, basic instruction a is executed and execution proceeds with the next primitive instruction if T is produced; otherwise, the next primitive instruction is skipped and execution proceeds with the primitive instruction following the skipped one. In the case where T is produced and there is not at least one subsequent primitive instruction and in the case where F is produced and there are not at least two subsequent primitive instructions, inaction occurs. In the case of a negative test instruction −a, the role of the value produced is reversed. In the case of a plain basic instruction a, the value produced is disregarded: execution always proceeds as if T is produced. The effect of a forward jump instruction #l is that execution proceeds with the l-th next instruction of the program concerned. If l equals 0 or the l-th next instruction does not exist, then #l results in inaction. The effect of the termination instruction ! is that execution terminates. PGA has the following constants and operators: for each u ∈ I, an instruction constant u ; -the binary concatenation operator ; ; -the unary repetition operator ω .
Terms are built as usual. Throughout the paper, we assume that there are infinitely many variables, including x, y, z.
We use infix notation for concatenation and postfix notation for repetition. Closed PGA terms are considered to denote programs. The intuition is that a program is in essence a non-empty, finite or infinite sequence of primitive instructions. These sequences are called single pass instruction sequences because PGA has been designed to enable single pass execution of instruction sequences: each instruction can be dropped after it has been executed. Programs are considered to be equal if they represent the same single pass instruction sequence. The axioms for instruction sequence equivalence are given in Table 3. In this table, n stands for an arbitrary natural number greater than 0. For each n > 0, the term x n is defined by induction on n as follows: x 1 = x and x n+1 = x ; x n . The unfolding equation x ω = x ; x ω is derivable. Each closed PGA term is derivably equal to a term in canonical form, i.e. a term of the form P or P ; Q ω , where P and Q are closed PGA terms that do not contain the repetition operator.
Each closed PGA term is considered to denote a program of which the behaviour is a finite-state thread, taking the set A of basic instructions for the set A of actions. The thread extraction operation | | assigns a thread to each program. The thread extraction operation is defined by the equations given in Table 4 (for a ∈ A, l ∈ N and u ∈ I) and the rule given in Table 5. This rule is expressed in terms of the structural congruence predicate ∼ = , which is defined by the formulas given in Table 6 (for n, m, l ∈ N and u 1 , . . . , u n , v 1 , . . . , v m+1 ∈ I).
The equations given in Table 4 do not cover the case where there is an infinite chain of forward jumps. Programs are structural congruent if they are the same after removing all chains of forward jumps in favour of single jumps. Because an infinite chain of forward jumps corresponds to #0, the rule from Table 5 can be read as follows: if x starts with an infinite chain of forward jumps, then |x| equals D. It is easy to see that the thread extraction operation assigns the same thread to structurally congruent programs. Therefore, the rule from Table 5 can be replaced by the following generalization: x ∼ = y ⇒ |x| = |y|.  Table 5. Rule for infinite jump chains Table 6. Defining formulas for structural congruence predicate #n + 1 ; u1 ; . . . ; un ; #0 ∼ = #0 ; u1 ; . . . ; un ; #0 #n + 1 ; u1 ; . . . ; un ; #m ∼ = #m + n + 1 ; u1 ; . . . ; un ; #m Let E be a finite guarded recursive specification over BTA, and let P X be a closed PGA term for each X ∈ V(E). Let E ′ be the set of equations that results from replacing in E all occurrences of X by |P X | for each X ∈ V(E). If E ′ can be obtained by applications of axioms PGA1-PGA4, the defining equations for the thread extraction operation and the rule for infinite jump chains, then |P X | is the solution of E for X. Such a finite guarded recursive specification can always be found. Thus, the behaviour of each closed PGA term is a thread that is definable by a finite guarded recursive specification over BTA. Moreover, each finite guarded recursive specification over BTA can be translated to a closed PGA term of which the behaviour is the solution of the finite guarded recursive specification concerned (see Proposition 2 of [15]).
Closed PGA terms are loosely called PGA programs. PGA programs in which the repetition operator does not occur are called finite PGA programs.

The Program Notation PGLD
In this section, we review a program notation which is rooted in PGA. This program notation, called PGLD, belongs to a hierarchy of program notations introduced in [3]. PGLD is close to existing assembly languages. It has absolute jump instructions and no explicit termination instruction.
In PGLD, as in PGA, it is assumed that there is a fixed but arbitrary finite set of basic instructions A. Again, the intuition is that the execution of a basic instruction a may modify a state and produces T or F at its completion.
PGLD has the following primitive instructions: for each a ∈ A, a plain basic instruction a; -for each a ∈ A, a positive test instruction +a; -for each a ∈ A, a negative test instruction −a; -for each l ∈ N, a direct absolute jump instruction ##l.
PGLD programs have the form u 1 ; . . . ; u k , where u 1 , . . . , u k are primitive instructions of PGLD. We write P PGLD for the set of all PGLD programs. The plain basic instructions, the positive test instructions, and the negative test instructions are as in PGA. The effect of a direct absolute jump instruction ##l is that execution proceeds with the l-th instruction of the program concerned. If ##l is itself the l-th instruction, then inaction occurs. If l equals 0 or l is greater than the length of the program, then termination occurs.
We define the meaning of PGLD programs by means of a function pgld2pga from the set of all PGLD programs to the set of all PGA programs. This function is defined by where the auxiliary functions φ j from the set of all primitive instructions of PGLD to the set of all primitive instructions of PGA are defined as follows Let P be a PGLD program. Then pgld2pga(P ) represents the meaning of P as a PGA program. The intended behaviour of P under execution is the behaviour of pgld2pga(P ) under execution. That is, the behaviour of P under execution, written |P | PGLD , is |pgld2pga(P )|.
We use the phrase projection semantics to refer to the approach to semantics followed in this section. The meaning function pgld2pga is called a projection.

A Classification of Services
In this short section, we provide a classification of services. It is a simplified version of the classification given in [9] and will be used in subsequent sections.
A distinction is made between target services and para-target services: -A service is a target service if the result of the processing of commands by the service is partly observable externally. Reading input data from a keyboard, showing output data on a screen and writing persistent data in permanent memory are typical examples of using a target service. -A service is a para-target service if the result of the processing of commands by the service is wholly unobservable externally. Setting a timer and transferring data by means of a Java pipe are typical examples of using a para-target service.
The overall intuition about threads, target services and para-target services is that: a thread is the behaviour exhibited by a sequential program on execution; -a thread interacts with services provided by the execution environment in question; -the intentions about the resulting behaviour pertain only to interaction with target services; -interaction with para-target services takes place only in as far as it is needed to obtain the intended behaviour in relation to target services.
One of the assumptions made in thread algebra is that para-target services are deterministic. The exclusion of non-deterministic para-target services is a simplification. We believe however that this simplification is adequate in the cases that we address: para-target services that keep data for a thread. Of course, it is inadequate in cases where services such as dice-playing services are taken into consideration. Another assumption is that target services are non-deterministic. The reason for this assumption is that the dependence of target services on external conditions make it appear to threads that they behave non-deterministically.

An Action Transforming Use Mechanism
A thread may perform certain basic actions only for the sake of having itself affected by a service. When processing a basic action performed by a thread, a service affects that thread in one of the following ways: (i) by returning a reply value to the thread at completion of the processing of the basic action; (ii) by turning the processed basic action into another basic action. In this section, we introduce an action transforming use mechanism, which allows for para-target services to affect threads in either way. We will only use the action transforming use mechanism to have program behaviours affected by a para-target service.
The action transforming use mechanism is a generalization of the version of the use mechanism introduced in [7]. 2 It is assumed that there is a fixed but arbitrary finite set of foci F and a fixed but arbitrary finite set of methods M. Each focus plays the role of a name of a service provided by the execution environment that can be requested to process a command. Each method plays the role of a command proper. For the set A of basic actions, we take the set {f.m | f ∈ F, m ∈ M}. Performing a basic action f.m is taken as making a request to the service named f to process command m.
We introduce yet another sort: the sort S of services. However, we will not introduce constants and operators to build terms of this sort. We identify paratarget services with pairs (H 1 , H 2 ), where H 1 : M + → {T, F, M, B} and H 2 : M + → A tau , satisfying the following conditions: 3 M stands for meaningless and B stands for blocked. M is used to indicate that a request to process a command is accepted, but that no reply is produced. B is used to indicate that a request to process a command is rejected. Let H be a para-target service, and let The three conditions imposed on para-target services can be paraphrased as follows: Table 7. Axioms for action transforming use operators if it is possible that no reply is produced at completion of the processing of a command, then it is impossible that a positive or negative reply is produced at completion of the processing of that command; -after a request to process a command has been rejected, any request to process a command will be rejected; -a reply is produced at completion of the processing of a command if and only if the command is turned into tau.
For each f ∈ F, we introduce the binary action transforming use operator / f : T × S → T. Intuitively, p / f H is the thread that results from processing all basic actions performed by thread p that are of the form f.m by the paratarget service H. When a basic action of the form f.m performed by thread p is processed by the para-target service H, it is turned into another action and, if this action is tau, postconditional composition is removed in favour of action prefixing on the basis of the reply value produced.
The axioms for the action transforming use operators are given in Table 7. In this table, f and g stand for arbitrary foci from F and m stands for an arbitrary method from M. Axioms ATU3 and ATU4 express that the action tau and basic actions of the form g.m, where f = g, are not processed. Axioms ATU5-ATU7 express that a thread is affected by a para-target service as described above when a basic action of the form f.m performed by the thread is processed by the service. Axiom ATU8 expresses that inaction occurs when a basic action to be processed is not accepted.
Let T stand for either BTA or BTA+REC. Then we will write T +ATU for T , taking the set {f.m | f ∈ F, m ∈ M} for A, extended with the action transforming use operators and the axioms from Table 7.
The use mechanism introduced in [7] deals in essence with para-target services H for which it holds that af (H)(α) = tau for all α ∈ M + . For these services, the action transforming use mechanism coincides with the use mechanism from [7].
τtau(x a y) = τtau(x) a τtau(y) TT4 The action tau is an internal action whose presence matters. To conceal its presence in the case where it does not matter after all, we also introduce the unary abstraction operator τ tau : T → T.
The axioms for the abstraction operator are given in Table 8. In this table, a stands for an arbitrary basic action from A.
Abstraction can for instance be appropriate in cases where tau arises from turning actions of an auxiliary nature into tau by means of the action transforming use mechanism. In subsequent sections, abstraction will only be used in such cases. Unlike the use mechanism introduced in [7], the use mechanism introduced in [11] incorporates abstraction.
Let T stand for either BTA+REC or BTA+REC+ATU. Then we will write T +ABSTR for T extended with the abstraction operator and the axioms from Table 8.

State-Based Description of Para-Target Services
In this section, we introduce the state-based approach to describe families of para-target services that will be used in Sections 8 and 11. This approach is similar to the approach to describe state machines introduced in [11].
In this approach, a family of para-target services is described by satisfying the following conditions: The set S contains the states in which the services may be, and the functions eff , yld and act give, for each method m and state s, the state, reply and action, respectively, that result from processing m in state s.
We define, for each s ∈ S, a cumulative effect function ceff s : M * → S in terms of s and eff as follows: We define, for each s ∈ S, a para-target service H s in terms of ceff s , yld and act as follows: H s is called the para-target service with initial state s described by S, eff , yld and act . We say that {H s | s ∈ S} is the family of para-target services described by S, eff , yld and act . The conditions that are imposed on S, eff , yld and act imply that, for each s ∈ S, H s is indeed a para-target service. It is worth mentioning that ∂ ∂m H s = H eff (m,s) , rf (H s )( m ) = yld (m, s), and af (H s )( m ) = act (m, s).

Method-to-Action Translator Services
In this section, we give a state-based description of the very simple family of para-target services that constitute a register-file-dependent method-to-action translator of which the register file consists of registers that can contain natural numbers up to some bound. This method-to-action translator will be used in Section 9 to describe the behaviour of programs in a variant of PGLD with dynamically instantiated instructions.
It is assumed that fixed but arbitrary positive numbers I, N ∈ N have been given. I is considered the number of registers in the register file and N is considered the greatest natural number that can be contained in the registers of the register file. The functions from [1, I]  It is also assumed that a fixed but arbitrary set A proto ⊆ M and a fixed but arbitrary function θ : A proto × ([1, I] → [0, N ]) → A have been given. A proto is considered the set of methods that are transformable to basic actions and θ is regarded to give, for each method m in A proto and function s : [1, I] → [0, N ], the basic action into which m is turned in the case where the state of the register file is s. The methods that belong to A proto are called proto-actions because they are the methods that are turned into basic actions by the register-file-dependent method-to-action translator.
The register-file-dependent method-to-action translator services accept the following methods: We write RFDT init for RFDT [ . The special state ↑ added above to the proper states of the register file is a state in which any request to process a method is rejected. The existence of such a blocking state is required to guarantee that S, eff , yld and act describe a para-target service.
The following proposition states rigorously that the methods that belong to A proto are exactly the methods that are turned into basic actions.
Proof. This follows immediately from the definition of the register-file-dependent method-to-action translator services.

PGLD with Dynamically Instantiated Instructions
In this section, we introduce a variant of PGLD with dynamically instantiated instructions. This variant is called PGLD dii . In Section 10, the usefulness of dynamic instruction instantiation will be illustrated by means of an example. In PGLD dii , it is assumed that there is a fixed but arbitrary finite set of foci F with rfdt ∈ F and a fixed but arbitrary finite set of methods M. Moreover, we adopt the assumptions made about register-file-dependent method-to-action translator services in Section 8. The set {f.m | f ∈ F, m ∈ M \ A proto } is taken as the set A of basic instructions. In the setting of PGLD dii , we use the term proto-instruction instead of proto-action and write A proto instead of A proto . A proto-instruction is what becomes a basic instruction by dynamic instantiation.
PGLD dii has the following primitive instructions in addition to the primitive instructions of PGLD: for each e ∈ A proto , a plain basic proto-instruction e; -for each e ∈ A proto , a positive test proto-instruction +e; -for each e ∈ A proto , a negative test proto-instruction −e.
The effect of a plain basic proto-instruction e is the same as the effect of the plain basic instruction θ(e, s), where s is the state of the register file involved in the instantiation of proto-instructions. The effect of a positive or negative test proto-instruction is similar.
Recall that the content of register i can be set to n by means of the basic instruction rfdt.set:i:n. Initially, its content is 0.
We define the meaning of PGLD dii programs by means of a function pglddii2pgld from the set of all PGLD dii programs to the set of all PGLD programs. This function is defined by where the auxiliary function ψ from the set of all primitive instructions of PGLD dii to the set of all primitive instructions of PGLD is defined as follows: The idea is that each proto-instruction can be replaced by an instruction in which the proto-instruction is taken for the method. Let P be a PGLD dii program. Then pglddii2pgld(P ) represents the meaning of P as a PGLD program. The intended behaviour of P under execution is the behaviour of pglddii2pgld(P ) under execution on interaction with a register-file-dependent method-to-action translator when abstracted from tau. That is, the behaviour of P under execution, written |P | PGLD dii , is τ tau (|pglddii2pgld(P )| PGLD / rfdt RFDT init ).

Concrete Proto-Instructions
At a fairly concrete level, basic instructions and proto-instructions are strings of characters. In [3], a concrete notation for basic instructions is introduced for the case where each basic instruction consists of a focus and a method. Here, we extend that concrete notation to cover proto-instructions. The resulting concrete notation will be used in examples of the use of PGLD dii .
First of all, we distinguish neutral strings and active strings. A neutral string is an empty string or a string of one or more characters of which the first character is a letter or a colon and each of the remaining characters is a letter, a digit or a colon. An active string is a string of two or more characters of which the first character is an asterisk and each of the remaining characters is a digit.
A concrete proto-instruction is a string of the form f ′ .m ′ , where f ′ and m ′ are non-empty strings of characters in which neutral strings and active strings alternate, starting with a neutral string of which the first character is a letter, and at least one active string occurs.
A concrete focus is a neutral string of which the first character is a letter. A concrete method is either a neutral string of which the first character is a letter or a concrete proto-instruction. A concrete instruction is a string of the form f.m, where f is a concrete focus and m is a concrete method.
The intention is that instantiation of a concrete proto-instruction amounts to simultaneously replacing all active strings occurring in it by strings according to some assignment of strings to active strings. The assignment concerned must be such that concrete proto-instructions are turned into concrete instructions.
To accomplish the assignments of strings to active strings, all active strings of interest must be of the form * δ, where δ is the decimal representation of some i ∈ [1, I]. Moreover, an encoding of the assignable strings by numbers in [0, N ] must be given. Then each state of the register file being involved in PGLD dii induces an assignment as follows: for each active string of interest, say * δ, the string assigned to it is the one that is encoded by the content of the register with the number of which δ is the decimal representation.
The concrete notation for basic instructions introduced above is sufficiently expressive for all applications that we have in mind. The assignable strings are in many cases binary or decimal representations of numbers in the interval [0, N ]. In such cases, it is most natural to encode the representations simply by the numbers that they represent. Example 1. Consider a program that on execution reads digit by digit the binary representation of a password and then performs an action to have the password checked by some para-target service. The binary representation of a password is a character sequence of a fixed length, say n, of which all characters are among the binary digits 0 and 1. The program reads in the binary digits which make up the binary representation of the password by performing actions that are processed by a target service. Suppose that the service used for reading in binary digits only accepts methods of the form getb and returns the reply F if the next binary digit is 0 and T if the next binary digit is 1. Moreover, suppose that the service used for checking passwords only accepts methods of the form chk:pw , where pw is the binary representation of a password. The focus stdin is used below as a name of the former service and the focus passw is used below as a name of the latter service.
In PGLD dii , where proto-instructions are available, the program has to distinguish among only 2·n cases. In PGLD, where no proto-instructions are available, the program has to distinguish among 2 n cases.

Register File Services
In this section, we give a state-based description of the very simple family of para-target services that constitute a register file consisting of registers that can contain natural numbers up to some bound. This register file will be used in Section 12 to describe the behaviour of programs in PGLD dii . As in Section 8, it is assumed that fixed but arbitrary positive numbers I, N ∈ N have been given. I is considered the number of registers in the register file and N is considered the greatest natural number that can be contained in the registers of the register file.
The register file services accept the following methods: for each i ∈ [1, I] and n ∈ [0, N ], a register set method set:i:n; -for each i ∈ [1, I] and n ∈ [0, N ], a register test method eq:i:n.
We write M rf for the set {set:i:n, eq:i: The methods accepted by register services can be explained as follows: set:i:n : the content of register i becomes n, the reply is T, and set:i:n is turned into tau; -eq:i:n : the content of the register does not change, the reply is T if the content of register i equals n and F otherwise, and eq:i:n is turned into tau. We write RF init for RF [

An Alternative Semantics for PGLD dii
In this section, we discuss an alternative semantics for PGLD dii . Unlike the meaning of PGLD dii programs that we defined in Section 9, we define the alternative meaning of PGLD dii programs only for the case where I = 1. The generalization of the definition to arbitrary I is obvious, but leads to a definition that is hard to read.
The idea is that each proto-instruction can be replaced by an instruction sequence of which the execution leads to the execution of the intended instruction after the content of the register has been found by a linear search. Because the length of the replacing instruction sequence is greater than 1, the direct absolute jump instructions are adjusted so as to compensate for the introduction of additional instructions. Obviously, the linear search for the content of the register can be replaced by a binary search.
Henceforth, we will proceed as if pglddii2pgld ′ has been defined for arbitrary I.
Let P be a PGLD dii program. Then pglddii2pgld ′ (P ) represents an alternative meaning of P as a PGLD program. The alternative behaviour of P under execution is the behaviour of pglddii2pgld ′ (P ) under execution on interaction with a register file when abstracted from tau. That is, the alternative behaviour of P under execution, written |P | ′ PGLD dii , is τ tau (|pglddii2pgld ′ (P )| PGLD / rf RF init ). Let b 1 , b 2 and b 3 be either 0 or 1. Suppose that the three bits read in at the beginning of the execution of these programs are b 1 , b 2 and b 3 , in that order. In the case of the former program, it is easy to check that the instruction +rfdt.passw.chk: * 1: * 2: * 3 will be executed while the contents of registers 1, 2 and 3 are b 1 , b 2 and b 3 , respectively. In the case of the latter program, it is easy to check that the instruction +passw.chk:b 1 b 2 b 3 will be executed after execution of some test and jump instructions. This strongly suggests that the programs are "behaviourally equivalent".
The following theorem states rigorously that, for any PGLD dii program, the behaviour under execution coincides with the alternative behaviour under execution.
Strictly speaking, we prove this theorem in the algebraic theory obtained by: (i) combining PGA with BTA+REC+ATU+ABSTR, resulting in a theory with three sorts: a sort P of programs, a sort T of threads, and a sort S of services; (ii) extending the result by taking | | for an additional operator from sort P to sort T and taking the semantic equations and rule defining thread extraction for additional axioms. We write T for the set of all closed terms of sort T from the language of the resulting theory.
In the proof, we make use of an auxiliary function | , | : N × P PGLD → T which gives, for each natural number i and PGLD program u 1 ; . . . ; u k , a closed term of sort T that denotes the behaviour of u 1 ; . . . ; u k when executed from position i if 1 ≤ i ≤ k and S otherwise. This function is defined as follows: |i, u 1 ; . . . ; u k | = |φ i (u i ) ; . . . ; φ k (u k ) ; ! ; ! ; (φ 1 (u 1 ) ; . . . ; φ k (u k ) ; ! ; !) ω | (where φ j is as in the definition of pgld2pga). It follows easily from the definition of | , | and the axioms of PGA that if 1 ≤ i ≤ k: |i, u 1 ; . . . ; u k | = a • |i + 1, u 1 ; . . . ; u k | if u i = a , |i, u 1 ; . . . ; u k | = |i + 1, u 1 ; . . . ; u k | a |i + 2, u 1 ; . . . ; u k | if u i = +a , |i, u 1 ; . . . ; u k | = |i + 2, u 1 ; . . . ; u k | a |i + 1, Let v 1 , . . . , v k be primitive instructions of PGLD dii , let i are as in the definitions of pglddii2pgld and pglddii2pgld ′ ), and let β : T → T ′ be the bijection defined by For each p ′ ∈ T , write β * (p ′ ) for p ′ with, for all p ∈ T , all occurrences of p in p ′ replaced by β(p). Then, using the equations concerning the auxiliary function | , | given above, it is straightforward to prove that there exists a set E consisting of one derivable equation p = p ′ for each p ∈ T such that, for all equations p = p ′ in E: the equation β(p) = β * (p ′ ) is derivable; -p ′ ∈ T only if p ′ can be rewritten to a p ′′ ∈ T using the equations in E from left to right.
are solutions of the same guarded recursive specification. Because guarded recursive specifications have unique solutions, it follows immediately that |v 1 ; . . .

Discussion of Semantic Approaches
In Sections 9 and 12, the meaning of PGLD dii programs is explained by means of different translations into PGLD programs. In both sections, the intended behaviour of a PGLD dii program under execution is described as the behaviour of the translated program under execution on interaction with some para-target service. The translation from Section 9 is extremely simple, but the translation from Section 12 is fairly complicated. The para-target service used in Section 9 to describe the behaviour of a PGLD dii program and the one used in Section 12 are equally simple. However, the former service is far more powerful: it turns a processed method into a basic action if the method corresponds to a protoinstruction. By its power, the translation can be kept simple if that service is used. Because of the simpler translation of PGLD dii programs into PGLD programs and the equally simple para-target service used, the approach followed in Section 9 to define the meaning of PGLD dii programs is preferable. A manifestation of the difference in complexity of the translations of PGLD dii programs from Sections 9 and 12 is that the former translation replaces each primitive instruction of PGLD dii by one primitive instruction of PGLD, whereas the latter translation gives rise to a combinatorial explosion. Recall that I stands for the number of registers involved in the instantiation of proto-instructions and N stands for the greatest natural number that can be contained in those registers. The translation from Section 12 replaces each primitive instruction of PGLD dii that is not a proto-instruction by one primitive instruction of PGLD as well, but replaces each proto-instruction by a sequence of (2 · N + 1) · I i=1 (N + 1) i−1 + 3 · ((N + 1) I − 1) + 1 = (5 · N + 1) · (((N + 1) I − 1)/N ) + 1 primitive instructions of PGLD.
If a new programming feature is added to a known program notation such as PGLD and the starting point of the approach to define the meaning of the programs from the extended program notation is translation of those programs into programs from the known program notation, then we can conceive of several approaches: give a translation by which each program from the extended program notation is translated into a program from the known program notation that exhibits on execution the same behaviour; -give a translation by which each program from the extended program notation is translated into a program from the known program notation that exhibits on execution the same behaviour by interaction with a given paratarget service that does not turn any processed method into a basic action; -give a translation by which each program from the extended program notation is translated into a program from the known program notation that exhibits on execution the same behaviour by interaction with a given paratarget service that turns certain processed methods into basic actions.
We consider an approach earlier in this list preferable provided that the translation concerned does not become too complicated. In the case where the translation becomes too complicated with all three approaches, it is desirable to look for another starting point. This may end up in direct thread extraction, i.e. assigning a thread to each program as this was done for PGA in Section 3.
In the case of PGLD dii , it is obvious that the first approach in the list given above does not work. However, it is virtually impossible to find out that the third approach is preferable to the second one without actually producing definitions of the meaning of PGLD dii programs according to both approaches.

Conclusions
We have studied sequential programs that are instruction sequences with dynamically instantiated instructions. We have defined the meaning of the programs concerned in two different ways, which both involve a translation into programs that are instruction sequences without dynamically instantiated instructions. In one of the two ways, the translation is very simple and does not lead to increase in the length of a program or the number of steps needed by a program. That way is considered the preferred one. The preferred way made it necessary for the use mechanism that was introduced in [7] to be generalized. In [6], we demonstrate that dynamic instruction instantiation is a useful programming feature.
In this paper, we have followed the approach of projection semantics, starting from the perception of a program as an instruction sequence. This means that programs are considered at a much lower level than usual in theoretical computer science. This allows for bringing the interface between software and hardware better into the picture, which becomes increasingly important to a growing number of developments related to computer architecture. The usual approaches to define the meaning of programs, such as operational semantics, denotational semantics and axiomatic semantics, are based on the view that the details of program execution should be abstracted from as much as possible. This makes comparisons with those approaches virtually impossible.
In [10], we have modelled and analysed micro-architectures with pipelined instruction processing in the setting of program algebra, basic thread algebra, and Maurer computers [13,14]. In that work, which we consider a preparatory step in the development of a formal approach to design new micro-architectures, dynamically instantiated instructions were not taken into account. An option for future work is to look at the effect of dynamically instantiated instructions on pipelined instruction processing.