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.