ESCR Program and Callable System

Last updated 28 February 2021


Symbols

Various objects in the ESCR scripting system are given names. These names are referred to as "symbols". Despite the different objects that can be referred to by symbols, there are some common syntax rules and handling of symbols. Symbols refer to objects like variables and subroutines.

Symbol types

There are different types of symbols (not to be confused with data types), with most types having their own namespaces. Each symbol type has a name. These symbol type name keywords are used consistantly in the ESCR system to specify symbol types. Each symbol type has its own namespace, except as noted in the descriptions below. The symbol type names are keywords, and are therefore case-insensitive.

The symbol type names and their meanings are:

VAR

Variables. These are in the same namespace as constants.

Variables have a data type and a value. The value can be changed.

CONST

Constants. These are in the same namespace as variables.

Constants have a data type and a value. The value can not be changed.

VCON

Variable or constant. This symbol type name is only used to indicate that a variable or constant is allowed or requested. Actual symbols are always variables or constants. There is no VCON symbol type.

SUBR

Subroutines. These are invoked with the CALL command.

MACRO

Macros. These function like subroutines, but are invoked implicitly from data lines (not ESCR command lines) in pre-processor mode. Macros serve no purpose in script mode since there is no mechanism to invoke them.

The details of how a macro invocation is detected in data lines and the syntax for passing arguments depend on the application. The default is that the macro name is the first token on a line that does not start in column 1. The first argument is separated from the macro name by a space, with subsequent arguments separated by commas. There may be any number of spaces immediately before or after the commas.

FUNC

Functions. A special syntax is used to identify a function and its arguments. The entire function reference is replaced with the function output. Functions are recognized and expanded on ESCR command lines and in pre-processor data lines.

The syntax for recognizing the start and end of functions depend on the application. The default is that functions are enclosed in brackets [].

CMD

Commands. All lines except blank lines, comment lines, or data lines in pre-processor mode start with a command name as the first token. Commands function like subroutines.

LABEL

Labels. Labels are used to refer to specific locations in source code.

UNSP

Unspecified. Like VCON, this is not actually a symbol type. It can be used in some instances to specify that a symbol type is unknown, or that any type of symbol is allowed.

Versions

It is permissible to create a new symbol of the same name as a existing symbol. If the new symbol is of a different fundamental type (variable as opposed to a subroutine, for example), then there is no conflict since there is a separate name space for each fundamental type. If the new symbol is the same type as a previous one, then a new version of that symbol is created.

Symbol versions are numbered starting with 1, with sequentially increasing numbers for newer versions.

Current version

One version of each symbol, usually the latest, is the "current" version. This version is implicitly referenced when no version information is specified in a symbol reference.

A specific version of a symbol can be referenced either absolutely, or relative to the current version. For example, it is possible to explicitly reference the fixed version 1 of a subroutine, or one version older than the current version.

The current version is sometimes not the latest. When a subroutine is called, for example, the current version of that subroutine symbol becomes the next older version of the subroutine. Therefore, when no version is specified in a subroutine call, the default is calling a chain of subroutines, not recursion. Note that recursion is possible, and requires explicitly calling the version of the subroutine +1 from the current version.

The versions of a symbol can be thought of as a stack. The top of the stack is the newest version. New versions are created and pushed onto the stack. When the current version is deleted, it is popped off the stack and the next previous version becomes current (if the deleted version was current previously).

The difference from a normal stack is that the current is not constrained to always be the top of the stack. This is the case for symbols that represent routines, like subroutines, macros, and commands.

When other than the last version of a symbol is deleted, the newer versions are re-numbered. The versions of a symbol are always numbered sequentially from 1 to the last version without any gaps.

In the ESCR system, this stacking is the mechanism used in place of having local, global, or other, symbol scope. For example, a subroutine creates the variable ii, and deletes it upon exit (there is a mechanism to make this somewhat automatic). Inside the subroutine, an unqualified reference to just ii refers to the variable created upon entry to the subroutine. No harm is done, and there is no ambiguity, if a variable ii also existed in the calling routine.

The effect is largely the same as achieved by namespace scoping, but that versions in other scopes can be accessed when explicitly specified. The syntax to explicitly specify a version other than the current is deliberately not something likely to occur by accident, and is visually obvious.

Syntax

Symbols are specified with the syntax:

name[:type][:version]

Name is the bare symbol name. It must be from 1 to 80 characters. At most, the printable ASCII characters except ":" (colon) are allowed. Specifically, this means character codes from 33 to 127 except for 58 (colon). There are further restrictions dependent on the application. For example, when functions are delimited with [ and ], then these characters are also not allowed to be used in symbol names.

Type explicity specifies the type of symbol. If present, this must be one of the symbol type name keywords shown above. The default for type allows for any symbol type within the context the symbol reference is used in. It is an error to specify a symbol type incompatible with the context.

For example, the CALL command requires a subroutine name symbol as its first argument. Therefore,

  CALL abcd:subr

could be valid, but

  CALL abcd:var

is definitely not valid.

When referring to an existing symbol, and all symbol types are valid, then the symbol types have precedence in the order VAR and CONST, SUBR, MACRO, FUNC, CMD, and LABEL. For example, if both a constant ABC and a subroutine ABC exist and the context does not limit the symbol type, just the symbol reference ABC will refer to the constant. However, CALL ABC will call subroutine ABC since the symbol type of SUBR is implied from context.

Version specifies the version of the symbol. Version must be a integer value, which may be preceeded by "+" or "-".

Without a preceeding "+" or "-", version specifies the absolute version of the symbol. Versions start at 1 and increase by 1 sequentially for each newer version. It is an error to specify a fixed version < 1.

When version starts with "+" or "-", then the integer value is relative to the current version. Positive values indicate newer versions and negative older. Version of +0 or -0 specifies the current version.

When version is not specified, the current version of the symbol is referenced.

For a symbol reference to indicate an existing symbol, the symbol of that name, of that type, and of that version must exist. If any of these is not true, then a non-existing symbol is referenced. That may cause an error, depending on context.

Examples

abcd

The current version of symbol abcd. If multiple symbol types are allowed from context, then this refers to the variable or constant abcd if that exist, else the subroutine abcd, else the macro abcd, etc.

abcd:subr

The current version of subroutine abcd.

abcd:2

Version 2 of abcd. This is a reference to a non-existent symbol even if abcd exists but has no version 2.

abcd:subr:+0

The current version of subroutine abcd.

abcd:subr:-1

The next older version of subroutine abcd.

abcd:subr:+1

The next newer version of subroutine abcd. Inside a subroutine, the current version is the next older version of that subroutine. Calling the "+1" version of the subroutine currently in is calling itself recursively.

abcd:+1

The next newer version of abcd.

If this is the first argument of a CALL command, then it is the same as the previous example, since the SUBR symbol type is implied from context.