*l(ID:3921/:::002)

L6 for the 360 


Carnegie Mellon University 1967

Pronounced "Star Ell"

List-processing language, implementation of L6 for 360.


Related languages
L6 => *l   Evolution of
*l => *n   Evolution of
*l => l*   Alias

References:
  • Newell, Alan, Jay Earley and Fred Haney "*l manual" Carnegie Institute of Technology June 26, 1967 view details Extract: Introduction
    Introduction
    *l is a set of system 360 macros designed to perform the basic tasks that appear in many list processing and systems programming applications.  It is based on L6, a list processing language designed by K. Knowlton of the Bell Laboratories.  According to Knowlton, the purpose of L6 was to permit users to "get much closer to machine code in order to write faster running programs, to use storage more efficiently, and to build a wider variety of data structures." The goals of *l are approximately the same.  As implemented at Carnegie-Mellon University, *l contains most of the important facilities of L6, except the available space mechanism.  This was omitted purposely because it or other available space schemes can be programmed rather easily in *l.  *l also contains a number of additions to L6:  block operations, dynamic bounds on fields and blocks, the meta-language.
    One objective in the design of *l has been to give the programmer control over the code  that is produced.  This is accomplished by making the internal workings available to the user and by allowing him to alter any of the internal macros for his own use either directly or by using the metalanguage.
    *l provides two basic data structures, the block and field, which may be compounded into arbitrarily complex high-level data structures.  Data within these structures is referenced by indexing or by chains of pointers which lead to desired storage locations.  The language also includes a basic set of arithmetic and logic operations, data comparisons and tests, control operations, and input/output operations. Extract: Data Structures
    Data Structures
    A block is a set of contiguous words or bytes which are to be treated as a unit.  Two types of blocks may be defined.  A base block is an actual set of words or bytes in memory; it is declared by giving the address of its origin and its length.  A block, on the other hand, is not a specific piece of memory, but rather a type of structure, whose origin is specified at run time when it is used.  The declarations are as follows:
    BLOCK block (origin and length in words) BBLOCK base block (origin and length in words) YBLOCK block (origin and length in bytes) YBBLOCK base block (origin and length in bytes)
    Note that a Y indicates that data is given in bytes rather than words.  A base block declaration defines a block by specifying its name, extent, and the address of the origin [leftmost byte]. A block declaration specifies the name and extent of a block, but the origin must be specified at run time in relation to an outer block. Examples:
    BBLOCK B,(LOC,8) YBLOCK C,(4,40)
    Base block B contains 8 words with origin at location LOG. C is a block of 40 bytes with origin at the number 4 byte of an implied outer block.
    The other data structure of *1 is the field.  A field is a set of contiguous bits within a full word.  Like a block, a field may have explicit or implicit origins.  Its origin is always specified in words.
    Examples:   BFIELD D, PLACE
    FIELD  C,0,(18,31)
    The base field D is a full-word at location PLACE.  Field C is bits 18-31, inclusive, of the beginning word of some implied outer block. Whenever C is used, its origin must be specified by the context.  All numbering of bytes, bits and words starts at 0.
    Extract: Definitions
    Definitions
      ::- | | ::= |$| ::= ::=
    ::= ,(,) ::= | ::= ::= ::= FIELD ,,(,)|
    BFIELD , Examples:
    BLOCK  B,(3,5)
    BBLOCK DM(LOC,XYZ)
    FIELD  A,l,(18,31)
    BFIELD B.LOC
    The syntactic form represents an assembler constant, any expression which is a legal operand of a SETA instruction, or an assembler symbol,as defined by the System 360 Assembler Language Manual.  Usual these will be decimal numbers or assembler names which have been assigned locations in the assembly.  The $ may be used to resolve ambiguity (see Operations).  If a quantity is to be used as an address and it is less than a full address then it is as if it were extended with O's on the left.
    The origin of a block or field and the size of a block may be specified either statically or dynamically.  If it is specified statically by an assembler expression, this value is fixed for the assembly.  If it is specified dynamically by a field sequence F (see below), the origin of the block will be the current contents of field F at the time that the block is accessed.  This means that these sizes and locations can be changed at run time.  Since this is implemented using index registers, it is ready-made for use in accessing tables and arrays. The origins of base blocks and base fields may not be specified dynamically.
    A field consists of the low bit, the high bit, and all bits between.  A base field is always one full-word.  We soon expect to allow the location of a base field or base block to be a general register or registers.  This will allow *1 to produce much better code and will also aid in communication between *1 and assembler language code. Extract: Sequences
    Sequences
    |
      ::=   []|
      ::=
    ::=
    ::= |
    ::=
    ::=
    ::= |
    ::=
    A sequence is a chain of block and field names which leads to a block or field.  The first name in the sequence and only the first must be a base field or base block name.  Each field is assumed to contain a pointer to a location in memory.  An implied block is assumed to exist there with that location as its 0  word.
    The value of the sequence is calculated in the following way: First a block is accessed.  If the sequence starts with a base field we access the implied block which that points to; if it starts with a base block we access that block.  If the next name is a block name B, we then access the B sub-block of that block.  If the next name is a field name F, we access the F field of the block and then access the implied block pointed to by that field.  In either case we now have a block again, so the process is repeated.  This continues through the sequence until the last name gives us either a block or field as a value. In the case that a field is last, we do not access its implied block.
    A field sequence points to a field () within a block
    ().  A block sequence points to a sub-block () of an outer block ().
    Examples:
    BFIELD W, ...
    BBLOCK C, (...,5)
    FIELD A, 1, (0,15)
    FIELD Zl, 0, (21,26)
    BLOCK BIG, (2,4)
    BLOCK Q, (2,2)
    To calculate WA[BIG]QZ1 we go through the following chain:

    To calculate CAQ we do:

    Note that one may concatenate single letter names (or single letters followed by digit strings) to form sequences without punctuation.  Other names, however, require [ ] around them.
    Extract: Operations
    Operations
    ::=->-> | <- <-
    ::= ( , ::= (-?,)
    ::= +|*|-|/|MOD|^|v|xv
    , )
    ::= |
    ::= (,*-,
    ,<-o,)
    The operators have the following meanings:

    OPERATOR                                        MEANING
    <-              Logical move or store
    +               Add
    -               Subtract
    *               Multiply
    /               Divide
    MOD             Remainder
    ^               Logical and
    V               Logical or
    XV              Logical exclusive or
    ?.              Logical complement
    ->->            Shift right
    <-<-            Shift left
    <-o             Store pointer

    When a field operation is performed the field sequence and quantity are combined according to the field operator and the result replaces the contents of the field specified by the field sequence.  The arithmetic operations will work correctly for non-negative integers and for negative integers which are kept in full word fields.
    The store operation will store a constant, or the contents of the field or block on the right, into the field or block on the left.  The information is stored right justified in a field and right justified beginning at the last word or byte of a block.  The rest of the field or block is cleared.  If a block or quantity is stored into a block or field which is too small, it may clobber contiguous information.  The convention of not making a check for any kind of error holds throughout the language, so that a minimal amount of code will be produced.  Any user who wants these checks can insert them using the meta-language.
    In a pointer operation it is assumed that the right hand operand points to a location in memory.  It causes the left field to point to that location. When the right operand is a field sequence, the pointer operation is the same as a store.  When the right operand is a block sequence, it causes the left field to point to the beginning of the block.
    The MOD operator produces the remainder upon division of the field sequence by the quantity.
    Shift operations cause the contents of the field specified by the field sequence to be shifted the number of bits specified by the quantity.  Q's are supplied when bits are vacated by the shift, but any non-zero bits which are
    made to overlap other fields within the same word may cause trouble can be
    checked using the meta-language.
    Examples:
    (ABF,+,4)     adds 4 to ABF.
    (ABF,V,AZF)   unites the contents of AZF into ABF.
    (?.,ABCFG)     complements ABCFG.
    (->->3,AB)    shifts the contents of AB 3 bits to the right.
    Note:  If the sequence of characters that specifies a quantity has a valid interpretation as a sequence, then it is treated as a sequence.  Assembler expressions which might be misconstrued as sequences must be preceded by $.  Thus if NAME is an assembler label , and N is a base block or base field and A, M, and E are blocks or fields then
    (W,<-,NAME)    treats NAME as a sequence while (W,<-,$NAME)   treats it as an assembler label.
    Extract: Input/Output and Data Conversion
    Input/Output and Data Conversion
    ::= | OUTPUT
    ::= IN|OUT
    ::= B<-D|D<-B
    ::= ( ,)
    Any base block may be declared as an input area, an output area, or both. Its declaration must occur before it is used in an I/O operation.  The IN operation causes a card to be read and stored in the specified base block.  The OUT operation causes the contents of the specified base block to be printed on the system print device.  As with other operations, no check is made to see that the I/O area is of the right size.
    The B<-D operation converts the contents of the right-hand field from the zoned decimal format to binary format and stores the result in the left-hand field.  D<-B converts the right field from binary to zoned decimal and stores the result in the left-hand field.  (Note that B<-D is a single symbol and is not (B,<-,D) which is a store operation.)
    Extract: Tests
    Tests
    ::= >|<|<=|=>
    ::= (,,)
    ::= =|/=
    ::= =o|/=o
    ::= (,,)| (,,) | () | ()
    ::= |
    Tests only have meaning when they occur in test statements (see the following section).
    The equality test checks to see if the contents of two fields or blocks are the same.  In case they are not of the same size, the smaller one is padded on the left with zeroes.  This is analogous to the store operation (i.e., after storing one field or block into a larger one, an equality test on them will yield true).
    A pointer test =o is true when the field sequence and sequence designate the same storage location.
    The logical test () is true if the designated field or block is non-zero.  The ?? symbol indicates reversal of the sense of the test.



    Extract: Branching and the Composition of a Program
    Branching and the Composition of a Program
    ::= (GOTO,)
    ::= ||COMPLEMENT OPERATION>|||
    || CONVERSION OPERATION>
    ::= |,
    ::= IF|IFANY
    ::= ,|
    ::= ,THEN,
    :; = |
    ::= ||DO
    : := |
    Examples:
    LABEL1   IFANY   (ABF,=,ABE), (ABF,=o,G),THEN,(ABH,«-BIG), (GOTO,LABEL2)
    DO      (X,+,3),(Y,*,5),(ABCF,«-,AG)
    The control operation, GOTO, specifies an unconditional branch to the storage location designated by the operand.  Normally this will be the identifier of a labeled statement, but this address may be computed, since a field sequence may be used as the operand.
    All operations of the operation sequence of an IF statement are executed if the logical value of every test of the test sequence is true.  Otherwise control passes to the next statement in the program.  The operations specified by an IFANY statement are executed if at least one test of the test sequence is true. Since negatives of all tests exist, "IF NONE" and "IF NOT ALL" are not needed.
    If an operation sequence is preceded by DO, the operations in the sequence are performed unconditionally from left to right. Extract: Implementation and the Meta-LanguageImplementation and the Meta-Language
    Implementation and the Meta-Language
    The current implementation of *l consists of about 70 macros.  Only a few of their names occur in the *l language described in the preceding sections. When one of these macros occurs in a program a sequence of nested macro calls produces the code required to perform the required task.  It is not unusual for a simple *l operation; e.g., the «- operation, to produce 15 or more macro calls. Most of these calls are for *l internal macros; that is, those whose names do not appear in the *l syntax.  However, there is no reason, in general, why a program should not call one of the underlying macros if it serves the programmer's purpose.  An effort has been made to make these internal features available to users.  They are described in detail in a separate paper, *l Internal Specifications.
    Included in *l is a language - the meta-language - which may be used to regulate or alter the code produced by *l macros.  Users who want to use this feature of *l may want to acquaint themselves with the internal operation of the language, by using the internal specs and/or a listing of the macros.  The metalanguage will be explained in a subsequent version of the manual. Extract: Conversational languages
    The situation normally faced by the designer of a system is that he has a set of distinct facilities ? such as languages, editors, debuggers, timing packages, and cross-reference programs. Each of these is created with a separate set of linguistic and interactive conventions. There is integration only at the level of the underlying operating system, seen by the user-designer as a single uniform command language. On the other hand, general interactive systems from JOSS (Shaw 1965) onward have adopted the other position by integrating all the facilities with the main language system. LISP, APL and l-* belong in this latter category, along with a less well-known system called LCC (Perlis, Mitchell, and VanZoeren 1965). Though at heart a JOSS-like system, LCC has many of the features of a standard HLL, and thus represents 3 rather unique marriage of HLL constructs with the philosophy of complete integration.
  • Research in Information Processing and Computer Science. Final technical rept. 1968-1970. Carnegie Mellon Univ Pittsburgh Pa Dept of Computer Science Aug 70 view details Abstract: Three team programming efforts during the past two years have been the development of BLISS - a system building language on the PDP-10; LCZ - a conversational system on the IBM/360; and L* - a system building language on the PDP-10. A number of additional individual programming language and system efforts have also been accomplished by graduate students as their doctoral dissertation work