Step) to check for
breakpoints or single step mode.
Since the contents of the various
variables of the program can potentially have to be sent to the
user, this procedure Step must have access to both
their names and values, and must know about their types,
including for local variables within procedures. Therefore, a
symbol table
must be maintained, that will hold a shadow copy of all variables
and parameters used in the program.
For instance, given the following sample program (line numbers have been added to make it easier to locate the original code in the modified version):
01 program Demo; 02 const NbDays = 7; 03 type WeekDays=(Su,Mo,Tu,We,Th,Fr,Sa); 04 Element=record 05 Name: string; 06 Next: ^Element; 07 end; 08 var Num : real 09 S : string; 10 Day : WeekDays; 11 WorkDays : set of WeekDays; 12 Matrix : array['a'..'z',1..10] of integer; 13 Chain : ^Element; 14 begin 15 Num := 3.1415; 16 S := 'Hi there'; 17 Day := Tu; 18 WorkDays := [Mo..Fr]; 19 Matrix['d',3] := 67; 20 new(Chain); 21 Chain.Name := 'Brown'; 22 Chain.Next := nil; 23 end.A declaration will be added after line 11:
11 WorkDays : set of WeekDays;
www_WorkDays: WeekDays;
to allow the insertion of a loop to scan the values in WorkDays
whenever this variable is changed.
Similarly, two declarations will be added after line 12:
12 Matrix : array['a'..'z',1..10] of integer;
www_Matrix_1: 'a'..'z';
www_Matrix_2: 1..10;
to allow the insertion of two embedded loops to scan the values in
Matrix whenever this variable is changed.
Then, the executable part of the program will look like:
14 begin
- code added here to create symbol table entries
for objects declared in this block
Step;
15 Num := 3.1415;
- code added here to (re)define value of 'Num' in symbol table
Step;
16 S := 'Hi there';
- code added here to (re)define value of 'S' in symbol table
Step;
17 Day := Tu;
- code added here to (re)define value of 'Day' in symbol table
Step;
18 WorkDays := [Mo..Fr];
- code added here to (re)define value of 'WorkDays' in symbol
table (this will be done by checking whether each possible
value in WeekDays is present in WorkDays or not)
Step;
19 Matrix['d',3] := 67;
- code added here to (re)define value of index "3" of
substructure "'d'" in structure Matrix.
Step;
20 new(Chain);
- code added here to indicate that 'Chain' points to a new structure
- code added here to create a new entry for 'Chain^' in symbol table
- code added here to create a new entry for each component of
the 'Chain^' structure.
Step;
21 Chain^.Name := 'Brown';
- code added here to (re)define value of '.Name' component of
dynamic structure 'Chain^'
Step;
22 Chain^.Next := nil;
- code added here to (re)define value of '.Next' component of
dynamic structure 'Chain^'
Step;
- before exiting the block, remove all local objects
from symbol table
23 end;
For the technical reader, full detail
of the final code produced for the example above is available, as
well as a list of the procedures used
in the final code.
All this can seem quite complicated, but it can easily be automated. A tool is currently being developed to parse Pascal code and to add all these calls automatically to the original code. Of course, all these lines that are added to the original code will not be displayed to the user.
For applications written in some interpreted language,
for which the interpreter gives the programmer direct access
to the interpreter's symbol table, the modifications of the
original code would be much simpler than in the scheme we just
described, since only calls to the Step procedure
need to be added to the code.
Synchronization between the server script and the spawned processes
Site Hosting: Bronco