Language description
BLISS has many of the features of other modern high-level languages. It has block structure, an automatic stack, and mechanisms for defining and calling recursive routines ... provides a variety of predefined data structures and ... facilities for testing and iteration ...
On the other hand, BLISS omits certain features of other high-level languages. It does not have built-in facilities for input/output, because a system-software project usually develops its own input/output or builds on basic monitor I/O or screen management services ... it permits access to machine-specific features, because system software often requires this. BLISS has characteristics that are unusual among high-level languages. A name ... is uniformly interpreted as the address of that segment rather than the value of the segment ... Also, BLISS is an "expression language" rather than a "statement language".
The BLISS language has the following characteristics:
All constants are full word for the machine being used, e.g. on a 16-bit machine such as the PDP-11, a constant is 16 bits; on a VAX computer, constants are 32 bits, and on a PDP-10, a constant is 36 bits.
A reference to a variable is always to the address of that variable. For example, the instruction Z+8 refers to adding 8 to the address of Z, not to its value. If one needs to add 8 to the value of Z, one must prefix the variable with a period; so one would type .Z+8 to perform this function, which adds 8 to the contents of Z.
Assignment is done with the standard = symbol, e.g. Z=8 – which says to create a full-word constant containing 8, and store it in the location whose address corresponds to that of Z. So Z+12=14 (or, alternatively 12+Z=14 though this form is considered bad practice per the BLISS documentation in Digital) places the constant 14 into the location which is 12 words after the address of Z.
Block statements are similar to those of ALGOL: a block is started with a BEGIN statement and terminated with END. As with ALGOL, statements are separated with the semicolon (";"). When a value is computed, it is saved until the next statement terminator – which means that a value can be computed, assigned to a variable, and carried forward to the next statement, if desired. Alternatively, an open parenthesis may be used to begin a block, with the close parenthesis used to close the block. When parentheses are included in an expression, the standard precedence rules are used, in which parenthesized expressions are computed first,
Conditional execution uses the IF expression, which tests a true-false condition, performs alternative actions, and returns a result.
Comparison uses keywords such as EQL for equality (as opposed to overloading the = symbol for the same purpose), GTR for Greater Than, and NEQ for not equal. For example, the following code will assign the absolute value of Z to the address indicated by Q:
Q = (IF .Z GTR 0 THEN .Z ELSE -.Z);
Identifiers (variables and constants) must be declared before use, typically using the OWN keyword. Declaring a variable normally causes the compiler to allocate space for it; when necessary, a variable may be assigned a fixed machine address via the BIND declaration. This feature is primarily used for accessing either machine registers or certain special addresses.
Subroutines in the language are called routines, and are declared with the keyword ROUTINE.
Macros, which allow for text substitution, are declared with the keyword MACRO.
The language supports arrays, which are referred to as structures, and declared with the keyword VECTOR.
The language supports some high-level programming language constructs such as:
Alternative execution paths via the CASE expression
Looping through use of the INCR expression, which is similar to ALGOL's FOR statement
Built-in string functions
Certain automatic data conversions (number to string, etc.)