RPascal - Documentation
RPascal is a program which consists of several classes which deal with
parsing, evaluating and executing Pascal source code.
Most of these objects exist in several instances, however some are shared
even in recursions, with the necessary protection mechanisms.
This documentation should make it easier to understand the source code
structure.
PascalEvaluator
The evaluator deals with all kinds of term evaluations. Those can occur on
the right side of assignments, in conditions (if, while), and as procedure
arguments.
initialize(engine, parentscope)
Constructs a new PascalEvaluator object which knows about its scope and
the main engine used in the program.
isnumber(s)
Internal helper function. Checks whether an argument is a number in order
to avoid a (probably deeply recursing) variable lookup.
termeval(s)
Evaluates a mathematical term and returns the result as a single number.
The term may well use variables and procedures from the pascal source.
booleval(s)
Evaluates a boolean term, which in most cases will consist of two
mathematical terms and a comparison operator, and returns the result, which
is either true or false.
PascalBlock
The fundamental structural element of Pascal is the block, which is used
in the main program, the procedures, the conditions and loops (if, else,
while, for).
Each such block has one position in the source code hierarchy, and is
assigned the code between begin and end, as well as the variables,
constants, and internal data.
initialize(engine, parentscope, name)
Constructs a new PascalBlock object, using the single engine in use,
the namespace of the parent block, and its own namespace.
write(var, value, const, fallthrough)
Assigns a value to a variable. This value may well be an array in case of
variable procedure parameters. The const flag indicates that this value
may only be assigned once. The fallthrough flag enforces a lookup of
an already existing variable, which will in many cases be further down
the hierarchy tree.
setcondition(type, condition)
Adds a condition type (if, while, for) and the relevant term to a block.
This makes only sense for the appropriate constructs, which are replaced
by pseudo-procedure calls in the parent block.
addparam(param)
Adds a parameter to a procedure declaration. The number of parameters
used must always match the number of times this function was called,
otherwise addvarparam() should be used.
addvarparam(param)
Adds a variable parameter. This should only be used once per block.
The parameter is then passed as an array.
addline(line)
Adds one line of source code to this block. Internally, the whole code
is kept as a single line, separated by semi-colons.
source()
Returns the complete source code line.
condition()
Returns the condition set by setcondition().
conditiontype()
Returns the condition type set by setcondition().
blockdebug()
Internal debug function to output some block structure information.
execute()
Run the code. This function returns false in case an exit was triggered
which will fall through until the first non-conditional block, i.e. until
a procedure is reached.
All assignments, procedure calls, block switches and so forth are handled
here.
read(var)
Returns the value of a previously assigned variable or constant, or
zero in case of an error (together with an error message).
canread(var)
Checks for reading first, so no error message is triggered. This is
however more expensive.
readscope(var)
Internal helper function to return the block to which a variable belongs.
If no such variable exists, nil is returned instead.
tryread(var, doread)
Internal function called by read() and canread(). A variable is read,
in case of success it is returned. If doread is set to false, the success
status is returned instead.
setparams(argarray)
Assigns values to all procedure parameters before calling it. The array
must be of the same size as the previously added parameters, unless variable
parameters are used.
This function is used by call().
saveparams(argarray)
Saves all dynamic block content (i.e., variables) before calling another
block from within. This is necessary in case the same block is called
recursively.
restoreparams(argarray)
Restores all parameters which were previously saved.
call(procedure, argarray)
Handles over control to another block. Before and after calling execute(),
saveparams() and restoreparams() are used accordingly, as well as
setparams() depending on the current scope.
execinternal(procedure)
This is a convenience function which provides all procedures from the
'hidden' namespace. Those are normally available in Pascal, like clrscr,
readln etc.
PascalEngine
This is the main object. It exists once per program instance, and manages
all other objects as well as the pascal source entry point.
initialize
Constructs the object so it becomes usable.
setmain(name)
Indicates the main block to be used. This is normally named 'program',
unless another name has been indicated by the Pascal program statement.
block()
Returns the current block in use.
setblock(name, autocreate)
Changes the block which is set as active. If autocreate is set to true,
an empty block is provided for the given namespace.
enginedebug()
Internal function which outputs some debug information, including all
blocks which this engine manages.
run()
Runs the program. This will immediately hand control over to the main
block as set by setmain().
use(unit)
Advises the program to include some external Pascal units. Currently
unused.
PascalInterpreter
This object handles the entire parsing of blocks and the execution
of commands therein. It does so on a symbol-by-symbol basis, which
makes it suitable for interpreting streams.
initialize(engine, parentscope)
Constructs the PascalInterpreter object. The parentscope is the
block object, which ususally has a 1:1 relationship with the
interpreter.
execute()
Runs the interpreter on the source code of the parent block, using
its variables, constants and procedures accessible in the hierarchy.
debug(s)
Internal function which outputs some progress information, if configured
to do so.
step(word)
Interprets one symbol. Internal states are kept in order to not lose the
information flow.
PascalParser
As opposed to the PascalInterpreter, the PascalParser is a high-level
parser which cares about variable and constant declarations, procedure
signatures, control statements and such.
initialize(engine)
Constructs the object (which usually is only used once, and only at the
beginning of the program execution).
debug(s)
Internal function which outputs some information about the source it
parses, if configured to do so.
parse(sourcefile)
Starts parsing a source file. Of course, multiple files could in theory
be used, however only one will be available in the main namespace.
tokenize(source, execute)
The main parser. It is fed by parse() with the source code, and constructs
all kinds of objects depending on the source content.
normalize(source)
A rough source code formatter which helps the parser not to become
complex. This is currently unused.