RFC 83

Language-machine for data reconfiguration

πŸ“… published December 1970, from ietf

RFC 83: LANGUAGE-MACHINE FOR DATA RECONFIGURATION ✨

Okay bestie, this one is from 1970!! πŸ¦‹ It's from the Network Working Group, written by R. Anderson, A. Harslem and J. Heafner, all from RAND, and it's filed as NIC 5621. The date is 18 December 1970. The header doesn't list a category, and it doesn't say what it obsoletes or updates. So it's a pure, untouched original. πŸ’œ


Introduction πŸŽ€

Okay so in NWG/RFC #80 they brought up the need for data reconfiguration, plus a compiler/executor version of a Form Machine to handle it. 🧚

This note is giving a different take on the Form Machine. The big idea is a syntax-driven interpreter that runs on a grammar, which is just an ordered set of replacement rules. ✨ After the interpreter part come some "real-world" examples of the data reconfigurations that have to happen between RAND consoles and the Remote Job System on the UCLA 360/91. πŸ’… Last but not least, they suggest the Protocol Manager from NWG/RFC #80 could be simplified by using the Form Machine plus two system forms, which get specified up front in the code. πŸ”₯

Caveat: the Form Machine is NOT meant to be a general purpose programming language. Notice there are no declaration statements and stuff. πŸ™ˆ

THE FORM MACHINE 🌸

I. Forms

A form is an ordered set of rules. πŸ’–

F = {R1, ...,Rn}

R1 is the highest priority rule, and Rn is the lowest. πŸ‘‘

The form machine takes five inputs: 1) a list of addresses and lengths that delimit the input stream(s); 2) a list of addresses and lengths that delimit the output area(s); 3) a pointer to a list of form(s); 4) a pointer to where the input stream starts; and 5) a pointer to where the output area starts. ✨ It applies a form to the input string and emits an output string into the output area. Here's how the form gets applied:

  1. Step 1: R1 becomes the current rule.
  2. Step 2: The current rule gets applied to the input data.
  3. Step 3:
    • a) If the rule fails, the rule one priority lower becomes current.
    • b) If the rule succeeds, the rule of highest priority becomes current.
    • c) When the rule of lowest priority fails, the form fails and applying the form to the input data stops. πŸ’€
  4. Step 4: Go back to Step 2. πŸ”

Also, during Step 2, if what's left of the input string isn't enough to satisfy a rule, that rule fails and partial results don't get emitted. And if a rule fills up the output string, applying the form stops. 🫢

II. Rules

A rule is a replacement operation that looks like this:

left-hand-side -> right-hand-side

Both sides are a series of zero or more _terms_ (more on those below) separated by commas. πŸ“

The left-hand side gets matched against the input string at the current position, like a pattern match. If it exactly describes the input, three things happen: 1) the current input position pointer moves forward past the matched input, 2) the right-hand side emits data at the current position in the output string, and 3) the output position pointer moves forward past the emitted data. πŸ¦‹

III. Terms

A term is a variable that either describes the input string to match or the output string to emit. ✨ There are three term formats, and we're gonna go through them one by one, bestie. πŸŽ€

Term Format 1

+---------------------------------------------------------------------+
|                                                                     |
|     name ( data  replication  .   value     :    length    )        |
|            type   expression    expression      expression          |
|                                                                     |
|_____________________________________________________________________|

Any of the fields can be absent. πŸ™ˆ

The _name_ is a symbolic name for the term, same as in any programming language. It's a single lower-case letter, and it has to be unique within a rule. πŸ’…

The _data type_ describes what kind of data the term represents. It's one member of this set: {D, O, X, A, E, B} πŸ’œ

Each data type has its own meaning and implied unit length:

Char.       Meaning               Length
-----       --------              -------
 D          decimal number        1 bit
 O          octal number          3 bits
 X          hexadecimal number    4 bits
 A          ASCII character       8 bits
 E          EBCDIC character      8 bits
 B          binary number         1 bit

The _replication expression_ is a multiplier for the value expression. ✨ It comes in one of two formats. The first is an arithmetic expression built from members of the set {v(name), L(name), numerals, programming variables}. Here v(name) is a value operator that gives a numeric value of the named data type, and L(name) is a length operator that gives a numeric value of the named string length. The programming variable is explained under term format three. The arithmetic operators are {*, /, +, -} and they mean what you'd expect. πŸ”₯ The second format is the terminal '#', which means an arbitrary multiple of the value expression. πŸ‘‘

The _value expression_ is the unit value of a term, written in the format its data type says. It gets repeated according to the replication expression. 🌈 A value expression comes in two formats too: 1) the same as part 1) of the replication expression, where again v(name) produces a numeric value, or 2) a single member of the set {v(name), quoted literal}, where v(name) produces a data type value of E or A. 🧚 (Concatenation is done by using multiple terms, so no need to squish stuff together in one term. ✨)

The _length expression_ is the length of the field that holds the value expression, after the replication expression has been applied. It has the same formats as a replication expression. πŸ’–

Okay, so here's an example. The term

x(E(7.'F'):L(x))

is named x, is of type EBCDIC, has the value 'FFFFFFF', and is 7 long. ✨ Slay.

Now the term

y(A:8)

on the left-hand side of a rule gets assigned the next 64 bits of input as its value. 🫢 On the right-hand side, though, it only moves the output pointer forward 64 bit positions, because it has no value expression (no contents) to generate data in the output area. πŸ™ˆ

To be continued... πŸŒ™

EXAMPLES OF SOME DATA RECONFIGURATIONS πŸŽ€

okay bestie, these are the example replacement rules for the specific applications people actually need πŸ’… Let's go through them πŸ¦‹

Literal Insertion ✨

To insert a literal, you separate the left-hand-side terms where the insertion goes, then put them on the right. ✨

a(A:10),b(A:70)->(a),(E'LIT':3),(b)

The 80 ASCII characters get emitted in the output area with the EBCDIC literal LIT inserted after the first 10 ASCII characters. Iconic 🫢

Deletion πŸ—‘οΈ

Terms on the left get separated so the right side can leave out the terms you don't want. πŸ’€

(B:7),a(A:10)->(Ev(a):L(a))

Only the 10 ASCII characters get emitted (as EBCDIC) in the output area. The 7 binary digits are discarded. Bye bye πŸ‘‹

Spacing in the Output Buffer 🌸

When there's a pre-formatted output buffer (usually a display buffer), you can get spacing by leaving out the replication and value functions from a term on the right. πŸ’–

a(A:74)->(E:6),(Ev(a):74)

The (E:6) skips 48 bit positions in the output area, then the 74 ASCII characters get converted to EBCDIC and emitted at the current output position. Spacing that's giving perfectly aligned πŸ“

Arbitrary Lengths 🧚

Some devices and programs spit out a variable number of characters per line, and it's really useful to turn those into fixed-length records. 😭

a(A:#) -> (Ev(a):74)

The ASCII characters get truncated or padded as needed and converted to EBCDIC in a 74 character field. Fixed length, no drama πŸ’…

Transposition πŸ”„

Fields that need transposing should be isolated as terms on the left. 🌈

a(X:2),b(A:#)->(Ev(b):L(b)),(a)

String Length Computation πŸ”’

Some formats need the string length as part of the data stream. This can be done with the length function. πŸ‘‘

a(E:10),b(X'FF':2)->(BL(a)+L(b)+8:8),(Av(a):L(a)),(b)

The length term is emitted first, in an 8 bit field. In this case the length includes the length field as well as the ASCII character field. ngl that's a lot of math for one line πŸ™ˆ

Expansion and Compression of repeated Symbols πŸ”

The following rule packs repeated symbols. πŸ¦‹

a(E:1), b(E#*v(a):L(b)) -> (BL(b)+1:8),(a)

Given the input string below, three successive applications of the rule emit the output string shown. πŸ’œ

Input: XXXXYYZZZZZZZ

Output: 4X2Y7Z

APPLICATION OF THE FORM MACHINE TO PROGRAM PROTOCOLS 🧠

The Protocol Manager mentioned in NWG/RFC #80 needs a few really interesting features that come from the Form Machine I've been describing. πŸ”₯

Sometimes during a protocol dialog it's fine to get either an accept on connection A or an allocation on connect B. The order is sometimes unimportant. The defined procedure for applying rules allows for order independence, so no drama if things show up in a different order ✨

A logger might send us a socket number inside a regular message. That socket number is meant to be the first of a contiguous set of sockets we can use to set up connections with some program. We want to pull the socket number field out of the regular message, maybe convert it to another format, and add to it to get the other socket names. As a result of the regular message, we want to emit several INIT system calls that include the socket numbers we just computed. The value operator and the arithmetic operators of the Form Machine can handle this, and it's so satisfying πŸ₯Ή

A third property of the Form Machine that matters for protocols is inter- and intra-rule binding, which is how you resolve context sensitive information. In general we want rules to be order independent, but sometimes we want to impose an ordering. Using the logger in NWG/RFC #66 as an example: the close that the logger sends can mean two different things depending on context. If the close is sent before the regular message containing the socket number, it means call refused. If the regular message comes before the close, the call is accepted. Since the close has contextual meaning, we have to bind it to the regular message so we don't end up introducing IF and THEN into the Form Machine language. πŸ™ƒ

Let's pretend for a moment that we can express system calls in Form Machine notation. (The notation below is for illustration only and is not part of the Form Machine language.) We have two ways to bind the regular message to the close. With intra-rule binding, we insist that the close be preceded by a regular message:

Reg. Msg , Close ->

Now let's assume the remote party needs an echo after each transmission. Since we have to emit an echo after receiving the regular message and before the close is sent, we have to use inter-rule binding. This can be done with the programming variable. It gets assigned a value when the regular message is received, and the value is tested when the close is received:

Reg. Msg -> Echo , ([lambda]+1)
Close, ([lambda]=1) ->

To show inter-rule binding via the programming variable, the connection protocol in NWG/RFC #66 could be represented by passing the following form to a protocol manager. (The notation below is for illustration only and is not part of the Form Machine language.)

  1. Send an INIT(RTS).
1. ->INIT(parameters) , ([alpha]<-0)
  1. Send an allocate in response to the connection completion (an STR received).
2.  INIT(parameters) -> ALLOCATE(parameters)
  1. When the messages bearing link numbers are received, set an internal indicator. (The extraction of the link is not illustrated.)
3.  Reg. Msg (parameters) -> ([alpha]<-1)
  1. When the close is received following the regular message [2], it's checked to see that the regular message was received before establishing the duplex connection. If the close is received with no regular message preceding it (call refused), the form will fail (since no rules is satisfied).
4.  CLOSE(parameters),([alpha]=1) ->
                             INIT(parameters),INIT(parameters)

This protocol can be handled by a single form containing four replacement rules. We've looked at similar representations for more complex protocol sequences too. Protocol sequences like these, stored by name, are an asset to the user, who can request a predefined sequence to be executed automatically. Main character energy πŸ‘‘

Two System Forms to Handle Protocol Statements πŸ’Œ

Let's assume we have a Protocol Manager that manages protocol sequences between consoles and the Network. The consoles generate and accept EBCDIC character strings, and the Network transmits binary digits. The console user has a language similar to system calls, which lets them create and store protocol sequences via Protocol Manager. At the same time, they can indicate which commands are expected to be sent and which are expected to be received. On command, the Protocol Manager can execute this sequence with the Network, generating commands and validating the ones it receives. Let's also assume the Protocol Manager shows the console user the dialog as it progresses. πŸ‘€

To translate between console and Network when generating, comparing, and displaying commands, the Protocol Manager can use the Form Machine. Two system forms are needed (see Fig. 1). One is a console-to-Network set of rules containing EBCDIC to binary for all legal commands. The other is a mirror image for Network-to-console.

REQUEST πŸ™

Language design isn't our forte, so we'd love comments from people with more experience than us. πŸ₯Ί

                           System form:
                             C -> N
                           +----------+
                           | one rule |
                           | for each |
                           | legal    |
                           | command  |
                   +-------|- - - - - |<----+
                   |       +----------+     |
            Binary |                        | EBCDIC
                   |                        |
   +----------+    |                        |      +----------+
   |          |<---+                        +------|          |
   | Network  |                                    | Consoles |
   |          |----+                        +----->|          |
   +----------+    |                        |      +----------+
                   | Binary          EBCDIC |
                   |                        |
                   |                        |
                   |       System form:     |
                   |          N -> C        |
                   |       +----------+     |
                   +------>|- - - - - |-----+
                           | one rule |
                           | for each |
                           | legal    |
                           | response |
                           +----------+

Figure 1 -- Application of System Form for Protocol Management πŸ–ΌοΈ

Distribution List πŸ’•

  • Alfred Cocanower - MERIT
  • Gerry Cole - SDC
  • Les Earnest - Stanford
  • Bill English - SRI
  • James Forgie - Lincoln Laboratory
  • Jennings Computer Center - Case
  • Nico Haberman - Carnegie-Melon
  • Robert Kahn - BB&N
  • Peggy Karp - MITRE
  • Benita Kirstel - UCLA
  • Tom Lawrence - RADC/ISIM
  • James Madden - University of Illinois
  • George Mealy - Harvard
  • Thomas O'Sullivan - Raytheon
  • Larry Roberts - ARPA
  • Ron Stoughton - UCSB
  • Albert Vezza- MIT
  • Barry Wessler - Utah

[The original document included non-ASCII characters. The Greek letters Alpha and Lambda have been spelled out and enclosed in square brackets "[ ]". A curly "l" character has been replaced by capital L. Left and right arrows have been replaced by "<-" and "->" respectively. RFC-Editor]

[This RFC was put into machine readable form for entry into the online RFC archives by Lorrie Shiota, 10/01]

πŸ“¦ where this page comes from