RFC 515
Specifications for Datalanguage, Version 0/9
RFC 515: Specifications for Datalanguage, Version 0/9 ๐
- Network Working Group ๐
- Author: R. Winter, Computer Corporation of America ๐ฉโ๐ป
- NIC 16446, dated 6 June 1973 ๐ฆ
- The header doesn't list a category, and it doesn't obsolete or update anything. โจ
Preface ๐ธ
okay so Datalanguage is the language the Datacomputer speaks ๐ฃ๏ธ The Datacomputer is a data utility system being built for the Arpanet, and it handles data storage and data management for computers on the network. it's giving infrastructure, bestie ๐ง
Version 0/9 is already running at CCA ๐ ngl it's super primitive, but it's still a great chance to get hands-on with the Datacomputer and the core Datalanguage ideas ๐
Later versions will bring in more of the full Datalanguage, which was described earlier in Datalanguage, Working Paper No. 3, Datacomputer Project, October, 1971, NIC 8028 ๐ One big limit in 0/9 is that elementary data items must be fixed-length ASCII strings (--). That gets dropped in Version 0/10, which is being implemented right now ๐ฅ
Once everyone has learned from building these early versions and from using them, a revised spec for the full language will come out ๐
1. Introduction ๐
this doc is the precise, complete spec for Datalanguage, Version 0/9 ๐ It has 11 sections, and this intro is section 1. Section 2 gives the general vibe of what 0/9 can do. Sections 3 and 4 are about data description and the directory. Sections 5 through 8 cover how you express data management operations. Section 9 is about recognising names, and Section 10 is the misc corner. Section 11 has the syntax written out in BNF ๐ง
There's a user manual coming too ๐ It'll teach the language in tutorial form and cover the parts of the Datacomputer-user interface that aren't the language itself โจ
2. Capabilities of Version 0/9 ๐
0/9 can store files, add data to existing files, and delete files ๐๏ธ Retrievals can spit out whole files or just subsets of them. You can pick data out of files by its content, using expressions built from boolean and inequality operators ๐
The file creator gets to decide whether an inversion is built and kept up by the Datacomputer ๐ช An inversion makes selective retrieval faster, but it costs storage space and file maintenance effort. Everyone who isn't the file creator doesn't need to know the inversion exists, or which fields are inverted file keys ๐ The language lets people just say the result they want, and the Datacomputer uses the inversion as much as the request allows ๐
Elementary data items are fixed-length ASCII strings. Files are a restricted kind of hierarchical structure ๐ณ
A lot of the limits in this memo are temporary ๐ซถ Anything marked with 3 asterisks (***) is a restriction that'll be heavily loosened or removed completely in the next version of the software ๐
3. Data Description ๐
A container is a variable whose value is a data object with a general character and arbitrary size. (In Version 0/9, size is restricted. See section 3.4.) Examples of containers in other systems are files, records, fields, groups, and entries ๐ง
The container is not the same thing as the data inside it ๐ For example, allocating space is an operation on a container. Changing the unit price field from 25 to 50 is an operation on the data in a container ๐
A container can enclose other containers. A container that isn't enclosed by another one is called outermost. If container A encloses container B, and no other container inside A also encloses B, then A immediately encloses B ๐ช
A Datalanguage description is a statement of a container's properties ๐
Every container has the attributes ident and type ๐ท๏ธ The ident is the character string users use to refer to the container. The type decides what form the container's value takes. The value can be elementary, or it can be made of other containers. There are 3 types: LIST, STRUCT, and STRING(***). A LIST holds a group of containers that all have the same description. A STRUCT holds a group of containers, and each one has its own description. A STRING is a sequence of ASCII characters. A STRING isn't really an elementary item, but in Version 0/9 it gets treated like one ๐
Some containers can have other attributes too โจ An outermost container has a function. The function says whether the container is for storage or for transmission ๐
Size is a meaningful dimension of the container, and what that means depends on the type ๐ It's used for space allocation and for parsing data streams ๐งฉ
An aggregate container (one that holds other containers) has, as an attribute, the description or descriptions of its components. So if S is a STRUCT containing A, B, and C, then the descriptions of A, B, and C are all attributes of S ๐ซง
A STRING that shows up in certain contexts can have an inversion attribute ๐ This is an access property that isn't really local to the STRING. It's linked to it for convenience ๐ซ
3.1 Ident ๐ชช
The ident of a container is made of alphanumeric characters, and the first one has to be alphabetic. It can't be longer than 100 characters ๐
The elements of a STRUCT must have idents that are unique within that STRUCT ๐
3.2 Function ๐ง
A container's function is FILE, PORT, or TEMPORARY PORT ๐ฏ When the function is FILE, the container is used to store data at the Datacomputer. When the function is PORT, the container is used to transmit data into or out of the Datacomputer. TEMPORARY PORT (which can be shortened to TEMP PORT) acts like a PORT, but its description isn't kept in the Datacomputer past the session it was created in โณ
3.3 Type ๐
Type is LIST, STRUCT, or STRING. These were defined on the preceding page ๐
In an occurrence of a STRUCT, the elements show up in the same order their descriptions show up in the STRUCT description. Every element is present in every occurrence of the STRUCT ๐
An element of a STRUCT or LIST can be a container of any datatype. The outermost container, though, has to be a LIST(***) ๐
3.4 Size ๐
The size of a STRING is how many characters it has. The size of a STRUCT isn't defined (***). The meaning of a LIST's size depends on other properties of that LIST (***) ๐คทโโ๏ธ
Usually, a LIST's size is its number of LIST-members. The outermost-LIST is the exception ๐ For an outermost-LIST with a function of FILE, the size is the number of LIST-members that space should be allocated for. If no size is given in this case, the system works out a default ๐งฎ For an outermost-LIST with a function of PORT, the size gets ignored (***) ๐
Only outermost containers can be bigger than a TENEX page (2560 ASCII characters) (***) ๐ฆ
3.5 Inversion ๐
An inversion is an auxiliary data structure that helps with retrieval by content ๐งฒ
Its main use is fast retrieval of sets of outermost-LIST-members. (This can be extended to other container sets, and it will be after release 1 ๐) Picture a list of weather observations stored as a file on the Datacomputer ๐ฆ๏ธ If you want to retrieve observations by COUNTRY quickly, you mark that in the description of the COUNTRY container. In information retrieval, that makes COUNTRY a key for retrieving observations ๐๏ธ
Keep in mind that the inversion option only affects how efficient retrieval by COUNTRY is. It doesn't affect whether you can retrieve by COUNTRY at all ๐
The inversion option has some restrictions. First, it can only be applied to STRINGs. Second, a STRING with the inversion option has to occur only once in each outermost-LIST-member. Third, it gets ignored when it's applied to STRINGs in PORT descriptions ๐ซ
Eventually there'll be several kinds of inversion option. For now, Version 0/9 only has the 'D' option, which stands for distinct ๐ฆ
3.6 Syntax โ๏ธ
A description is just a list of properties, and they show up in this order:
<ident> <function> <type> <size> <other>
Properties that don't apply get left out. Here's an example:
F FILE LIST (25) A STR (10)
Here 'F' is the <ident>, 'FILE' is the <function>, 'LIST' is the <type>, '(25)' is the size, and 'A STR (10)' is the <other> of this one description. Also, 'A STR (10)' is its own description too: the description for the members of the LIST named F ๐ง
Here's a full description for a file of weather observations, keyed on location ๐
WEATHER FILE LIST
OBSERVATION STRUCT
LOCATION STRUCT
CITY STR (10), I=D
COUNTRY STR (10), I=D
END
TIME STRUCT
YEAR STR (2)
DAY STR (3)
HOUR STR (2)
END
DATE STRUCT
TEMPERATURE STR (3)
RAINFALL STR (3)
HUMIDITY STR (2)
END
END
The ENDs are there to mark where the list of a STRUCT's elements stops ๐ `, I=D' says the string is an inversion key for retrieving outermost-LIST-members ๐
4. Directory ๐
The directory is a system file that keeps the names and descriptions of all user-defined containers ๐๏ธ
It's structured as a tree ๐ฒ Each node has an ident, and idents don't have to be unique. There's exactly one path from the root of the tree to any node. The idents along that path get joined together with periods to make a pathname, and that pathname uniquely identifies the node. For example, A.B.C could be the pathname for a node whose ident is C ๐
In a later version of the software, the directory gets generalised to allow links between nodes. That means it won't really be a tree anymore. For now, though, the tree model is convenient and good enough ๐ซถ
A node can represent a container, or it can just hold a spot in the space of pathnames. When a node represents a container, it can't (for now) have subordinate nodes ๐ โโ๏ธ
Eventually, the plan is to model the directory as a structure of containers, with its description spread throughout that structure ๐งฉ Most operations defined on the directory will be defined on user data, and the other way around too. Access privileges and privacy locks will be part of the data description, and they'll apply to both directory nodes and the data structures below the node level ๐
4.1 CREATE
Okay bestie, so a CREATE-request does one of two things ๐. (a) It adds a node to the directory, and you can optionally hook a PORT or a FILE description onto that node ๐. Or (b) it makes a temporary container that is not entered in the directory. It still has a description, though, and you can reference it in requests โจ. If the description defines a file, CREATE allocates space for that file ๐พ.
To create a node with a description:
CREATE <pathname> <description> ;
To create a node with no description:
CREATE <pathname> ;
Note that the description decides whether or not the container is temporary (see section 3.2 for details) ๐ง.
A CREATE-request adds a single node to the directory, so it's giving one step at a time ๐ซถ. To add CCA.RAW.F to an empty directory, you need three requests:
CREATE CCA ;
CREATE CCA.RAW ;
CREATE CCA.RAW.F ;
Notice that the last ident of the pathname doubles as the first ident of the description ๐:
CREATE CCA.RAW.G FILE LIST A STR (5) ;
So G is both the ident of a node and the ident of an outermost container of type LIST. Iconic double duty ๐.
4.2 DELETE
A DELETE-request deletes a whole tree of nodes, plus any associated descriptions or data ๐๏ธ. The syntax is:
DELETE <pathname> ;
The named node and any subordinates get deleted, no exceptions ๐.
Heads up though: if you want to delete the data but keep the directory entry and description, DELETE should not be used. Use the proper method in section 6.3 instead ๐.
4.3 LIST
The LIST-request is how you display system data you care about ๐. It sends the data you asked for out through the Datalanguage output port ๐.
Several LIST arguments work on the directory. LIST %ALL transmits all pathnames in the directory ๐ธ. LIST %ALL.%SOURCE transmits all descriptions in the directory ๐ฆ. You can use a pathname in place of %ALL:
LIST <pn>.%ALL
This lists pathnames subordinate to <pn> ๐.
LIST <pn>.%SOURCE
This lists descriptions subordinate to the node represented by <pn> ๐.
For details about the LIST-request, see section 10.1 ๐.
5. Opening and closing containers
Containers must be open before you can operate on them ๐.
A container is open the moment it's first created โจ. It stays open until a CLOSE-request closes it explicitly, or a DELETE-request closes it implicitly, or the session ends ๐.
A closed container gets opened by an OPEN-request ๐. A temporary container is always open, and a CLOSE-request deletes it ๐ .
5.1 Modes
An open container has a mode, and it's one of these: READ, WRITE, or APPEND ๐ฆ. The mode decides the meaning and/or legitimacy of certain operations on the container ๐ฅ.
The operation that opens the container sets the mode ๐ง. You can change it any time with a MODE-request ๐ซ. A CREATE leaves the container in WRITE mode โ๏ธ. An OPEN either specifies the mode explicitly or implicitly sets the mode to READ ๐.
5.2 Syntax
To open a container:
OPEN <pathname> <mode> ;
or:
OPEN <pathname> ;
where <mode> is defaulted to READ ๐ผ.
To close a container:
CLOSE <ident> ;
where <ident> is the name of an outermost container ๐.
Two containers with the same outermost <ident> can not be opened at the same time (***) ๐ โโ๏ธ.
To change the mode of an open container:
MODE <ident> <newmode> ;
5.3 LIST
LIST %OPEN transmits the name, mode and connection status of each open outermost container through the Datalanguage output port ๐ฎ. (The Datalanguage output port is the destination where all Datacomputer diagnostics and replies get sent ๐. It gets established when the user first connects to the Datacomputer ๐ซถ.) For details of the LIST-request, see section 10.1 ๐.
6. Assignment
Assignment transfers data from one container to another ๐.
The equal sign ('=') is the symbol for assignment ๐ฐ. The value of the operand on the right of the equal sign gets transferred to the operand on the left โจ. (Eventually, both operands will be weakly-restricted Datalanguage expressions, which may evaluate to sets as well as to single containers. For now, the left must be a container name, and the right may be a container name or a constant ๐ท.)
Assignment is defined for all types of containers ๐. When the containers are aggregates, their elements get paired, and data moves between paired elements ๐งธ. Elements of the target container that don't pair with any source element are handled with a default operation. Currently they get filled with blanks โฌ.
The operands of an assignment must have descriptions that match ๐. The idea of matching is that the descriptions have to be similar enough that it's obvious how to map one into the other ๐บ๏ธ.
6.1 Conditions for legitimate assignment
Assignment must reference objects, not sets. An object is:
- (a) an outermost container, or
- (b) a constant, or
- (c) in the body of a FOR-loop, either
- (c1) a member of a set defined by a FOR-OPERAND, or
- (c2) a container which occurs once in such a member
For a reference of type (c1), the object referenced is taken to be the current member ๐ฏ. For (c2), the object referenced is whatever occurs in the current member ๐ซ. This is explained further in section 7 ๐.
The left operand of an assignment has extra restrictions ๐ง. If it's an outermost container, it must be open in either WRITE- or APPEND-mode. If it's not an outermost container, then the reference is of type (c), which means some FOR-operand has set up a context where the assign-operand is an object. That FOR-operand must be the output-operand of the FOR ๐ง.
When the assign-operand is an outermost container, it must be open. You have to reference that operand by its simple container ident(***), not its directory pathname ๐ .
In the body of a loop nested inside one or more other loops, assignments get restricted even further, because of a 0/9 implementation problem. See section 7.2 for details ๐.
Finally, the descriptions of the operands must match ๐ซถ. If one is a constant, then the other must be a STRING(***). If both are containers, then in the expression:
A = B;
the descriptions of containers A and B match if:
- A and B have the same type
- If A and B are LISTs, then they have equal numbers of LIST-members, or else A is an outermost-LIST.
- If A and B are aggregates, then at least one container immediately enclosed in A matches, and has the same ident as, one container immediately enclosed in B.
6.2 Result of assignment
If the operands are STRINGs, then the value of B, left-justified, replaces the value of A ๐งต. If B is longer than A, the value gets truncated โ๏ธ. If B is shorter than A, then A gets filled on the right with blanks as necessary ๐ซง.
If the operands are STRUCTs, then assignment is defined in terms of the STRUCT members ๐งฉ. If a member of A, mA, matches and has the same name as a member of B, mB, then mB is assigned to mA ๐. If no such mB exists, then mA gets filled with blanks โฌ.
If the operands are LISTs, the result depends on several factors ๐. First, notice that the descriptions of the LIST-members must match ๐. Otherwise, the assignment wouldn't be legitimate by the matching rules of 6.1 ๐ซ.
If A is an outermost-LIST, it can be in either of two modes: WRITE or APPEND ๐. If A is in WRITE-mode, its previous contents are first discarded ๐๏ธ. Then it's handled as though it were in APPEND-mode ๐ฆ.
If A is not an outermost-LIST, then it's always effectively in WRITE-mode ๐ซ.
After taking the mode of A into account, as described above, the procedure is:
- (a) for each member of LIST B, add a new member to the end of A
- (b) assign the current number of B to the new member of A
6.3 Deletion of Data Through Assignment
If A is an outermost container in WRITE-mode, and B is a container with a description that matches A, and if B contains no data, then A=B has the effect of deleting all data from A ๐งน. Note that if A is in APPEND-mode in these circumstances, then A=B is a no-operation (i.e., has no effect) ๐ซ .
7. FOR โจ
okay so FOR is the loop bestie ๐ the syntax looks like this:
FOR <output set spec>, <input set spec> <body> END ;
the output set is optional, so FOR doesn't have to produce anything. when it's left out, the syntax is:
FOR <input set spec> <body> END ;
the operations in the body run once for each member of the input set. any reference in the body to the input set member just means the current input set member ๐ฆ and when there IS an output set, a brand new member gets created and added to it on every iteration (so, once per input member). references to the output set member work the same way: they mean the current one โจ
the output set spec has to be the name of a LIST member. each iteration makes one of those and adds it to its LIST (we call that the output LIST). the body sets the value the new member ends up with. any STRING in that new member that the body doesn't give a value to gets the default value of all blanks ๐
the input set spec has to be an expression that evaluates to a set of LIST-members (more on that in section 7.1 ๐ซถ). each iteration pulls in one of those members, and the FOR wraps up once every member in the set has been processed. the LIST the input members come from is called the input LIST ๐
honestly FOR is basically a fancier version of assignment between two LISTs ๐ it's less concise than plain assignment, but it's way more flexible, and it has two big perks:
- (a) not every input LIST-member has to get copied over. you can pick a subset based on content ๐
- (b) you get explicit control over which values go into the output LIST-members ๐
this is easiest to see with an example ๐ง
P PORT LIST F FILE LIST
R STRUCT R STRUCT
B STR A STRUCT
C STR A1 STR
END A2 STR
B STR
C STR
END
(1) P = F ;
(2) FOR P.R, F.R
P.R = F.R ;
END ;
(3) FOR P.R, F.R WITH A1 EQ 'XY' OR A2 GE 'AB'
B = C ;
C = A2 ;
END
so (1) and (2) are totally the same request ๐ but (3) is a whole different vibe. it picks out a subset of the F.Rs, and the values it gives the P.Rs couldn't come out of the matching rules applied to F and P. so it's not expressible as plain assignment ๐ญ
because FOR is basically assignment between a pair of LISTs, the LISTs it references are mostly held to the same restrictions as assignment. the one exception: the descriptions of the LIST-members don't have to match ๐ธ the restrictions are:
- (a) both LISTs have to be objects in the context where the FOR shows up.
- (b) both LISTs have to be open, or sitting inside open outermost containers.
- (c) if the output LIST is an outermost container, it has to be in WRITE- or APPEND-mode.
- (d) if the output LIST isn't outermost, the LIST that most immediately encloses it has to be the output LIST of an enclosing FOR.
the mode of the output LIST changes the result pretty much the way it would in an assignment. a FOR writing to a LIST in WRITE-mode overwrites whatever was there before, while a FOR writing to a LIST in APPEND-mode adds onto the previous contents ๐
CAUTION TO THE READER: ok so these specs say stuff like 'LISTs referenced by a FOR' to keep things simple, but that phrase isn't 100% accurate. the operands of a FOR are always LIST members, not LISTs. just keeping it real ๐
7.1 Details of input set specification
the input set is specified by a Datalanguage expression that evaluates to a set of LIST-members. the expression can be just the set of all members of a LIST, or a subset of them picked out by content ๐ for example, with this description:
F FILE LIST
R STRUCT
A STR (1)
B STR (2)
END
the expression:
F.R
references every R on the LIST F. but:
F.R WITH A EQ '5'
only references the R's that contain an A with the value '5' โจ the expressions allowed as input set specifications look like this:
<list-member-name> WITH <boolexp>
the <boolexp> is built out of comparison expressions joined together with the Boolean operators AND and OR. and any expression can be negated with NOT ๐ซถ
comparison operators have the highest precedence. next highest is AND, then OR, then NOT. the big picture: comparisons bind tightest, NOT is the weakest ๐ง
the comparison expressions are limited to this form:
<container name> <comop> <constant>
where:
- (a) the <constant> is a string constant wrapped in single quotes (check section 10.2 for more on constants ๐ )
- (b) the <comop> is one of six operators:
EQ equal
NE not equal
LT less than
GT greater than
LE less than or equal to
GE greater than or equal to
- (c) the <container name> is the name of a STRING that shows up once in each LIST-member.
the constant gets truncated or padded with blanks on the right so it's the same size as the container it's being compared to. heads up though: padding on the right isn't always what you want ๐ฌ users will get control over the padding in a future release. and be careful with numbers in Version 0/9. (a number stored as a STRING should really be described as a number. eventually it'll be possible to do that ๐)
7.2 FOR-body
okay two operations are legit inside a FOR-body: FOR and assignment ๐
these are subject to the restrictions from Section 6.1 and from the intro to Section 7. the restrictions boil down to three requirements: (1) the names have to be recognizable (see Section 9 for details), (2) a request has to be consistent about which direction data moves between containers, both within itself and with the MODE of outermost containers, and (3) transfers have to happen between objects, not sets of objects. the first two are permanent, but they'll get weaker in later versions of the language. the last one is temporary and will only show up in early versions ๐ฆ
now for a slightly bizarre restriction ๐ญ it's caused by an implementation problem in Version 0/9, and it hits references made in the body of a loop nested inside another loop. it's not part of the language design and it's not expected to cause real problems for users, but it's here for completeness ๐ธ
an example makes it click. say we have this description:
F LIST
R STRUCT
A STR (3)
BL LIST (3)
B STR (3)
C STR (3)
END
and this request fragment:
FOR ...,R
FOR ...,B
... = A ;
... = C ;
END
END
here's what's going on:
- (a) the outer loop goes through the set of R's in F.
- (b) for each R in F, the inner loop goes through the set of B's in the BL inside that R.
- (c) in the inner loop body, there are references to A and C. neither one lives in B, but both live in R. so the objects the inner loop body uses are defined by the outer loop, not the inner loop. usually that's totally fine, but C is where it gets sticky ๐
- (d) C shows up beyond the end of BL.
the 0/9 compiler can't do either of two things. it can't look ahead far enough to find C before it compiles the loop's code, and it can't, while generating code to loop over the B's in BL, also generate a separate body of code that skips to the end of BL to find C. so it can handle A, since A was located before loop generation starts, but it can't handle C, which needs a little foresight ๐ญ
the request fragment wouldn't cause problems if the description were changed to this:
F LIST
R STRUCT
A STR (3)
C STR (3)
BL LIST (3)
B STR (3)
END
then both A and C get found before the code for the inner loop is generated โจ
8. Data Transmission ๐ซถ
data gets moved from container to container by running assignment and FOR operations ๐ the outermost containers involved in a transfer can be files or ports. if both are files, the transfer stays internal to the Datacomputer. if either one is a port, an address out in the external world is needed to make the transmission happen ๐
that address comes from a CONNECT-request, which links a container (one with the PORT function) to an external address:
CONNECT <ident> TO <address> ;
here <address> is either a host and socket number, or a TENEX file designator (for CCA's TENEX) wrapped in single quotes. the host and socket form looks like this:
<socket> AT <host>
where <socket> is a decimal number, and <host> is either a decimal number or a standard host name. (standard host names don't exist yet, so for now it has to be the TENEX 'standard' name for the host. contact the author for the latest list ๐ง) if <host> is left out, it's taken to be the host the Datalanguage is being sent from ๐
a port's address can be changed by issuing another CONNECT-request ๐ฆ
a DISCONNECT-request just breaks an existing port/address association without setting up a new one. (a CLOSE-request that references an open port runs a DISCONNECT too ๐) the syntax is:
DISCONNECT <ident> ;
a port is disconnected when: (a) no successful CONNECT-request has ever been issued for it, or (b) a DISCONNECT for the port has run since the last successful CONNECT ๐ธ
when a disconnected port gets referenced in an assignment, it gets connected by default to one of two things:
- (a) the connection used to send Datalanguage to the Datacomputer, or
- (b) the connection used to send Datacomputer diagnostics to the user
which one it picks depends on whether the reference is for input or output ๐ those connections are set up by the network user's ICP to the Datacomputer at the start of the session โจ
one more thing: CONNECT and DISCONNECT don't actually open files or network connections ๐ they just make address associations inside the Datacomputer. the files and connections get opened before each request and closed after each request ๐ซถ
9. Names in Datalanguage โจ
okay so a name gets recognized once it's been attached to a specific data container (or a whole set of them) ๐
Datalanguage has mechanisms for recognizing names in context, which means the meaning of a name depends on where it shows up ๐ฆ it's giving main character energy. That's what lets you attach natural meanings to partially qualified names ๐
For example:
WEATHER FILE LIST
STATION STRUCT
CITY STR (15)
STATE STR (15)
DATA LIST (24)
OBSERVATION STRUCT
HOUR STR (2)
TEMPERATURE STR (3)
HUMIDITY STR (2)
PRESSURE STR (4)
END
END
RESULTS PORT LIST
RESULT STRUCT
CITY STR (15)
HOUR STR (2)
TEMPERATURE STR (3)
END
FOR STATION WITH STATE EQ 'CALIFORNIA'
FOR RESULT, OBSERVATION WITH HOUR GT '12'
AND HUMIDITY LT '75'
CITY = CITY ;
HOUR = HOUR ;
TEMPERATURE = TEMPERATURE ;
END ;
END ;
In the assignment CITY = CITY, the first CITY is understood to be RESULT.CITY and the second is understood to be STATION.CITY ๐
9.1 Informal Presentation of Recognition Rules
Ident means exactly what it means in section 3. For example, in this description:
F FILE LIST R STRUCT A STR (1) B STR (1) END
F, R, A and B are idents ๐ธ
A context is a tree whose nodes are idents. In that tree, the terminal nodes are idents of STRINGs. The ident of a LIST is superior to the ident of the LIST-member. The ident of a STRUCT is superior to the idents of the STRUCT elements. The context whose top node is F is said to be the context of F ๐ง
+-----+
! F !
+-----+
!
!
+-----+
! R !
+-----+
!
!
+----------+----------+
! !
! !
+-----+ +-----+
! A ! ! B !
+-----+ +-----+
Figure 9.1-1 The context of F
A pathname is a sequence of idents that names the nodes along a path from one node to another. A full pathname in the context starts at the topmost node, so F.R.B is a full pathname in the context of F. A partial pathname starts at some node other than the topmost one (e.g. R.B, B) ๐
In Datalanguage, you can't skip intermediate nodes. Pathnames like F.B (which leaves out R) are not permitted. So partial pathnames are only partial in that extra names get implied on the left ๐
When recognizing a pathname, PN, in a context, CX, there are three attempts that get made:
- (a) recognition of PN as a full pathname in CX
- (b) recognition of PN as a partial pathname in which only the topmost node of CX is omitted
- (c) recognition of PN as an arbitrary partial pathname occurring only once in CX
The attempts happen in that order, and the recognition process stops at the first one that succeeds ๐ฅ
Here's an example description:
F FILE LIST
R STRUCT
A STR
B STR
S STRUCT
R STR
It defines the context in Figure 9.1-2 ๐ฆ
+-----+
! F !
+-----+
!
!
+-----+
! R !
+-----+
!
!
+----------------+----------------+
! ! !
! ! !
+-----+ +-----+ +-----+
! A ! ! B ! ! S !
+-----+ +-----+ +-----+
!
!
+-----+
! R !
+-----+
Figure 9.1-2 Example Context
In this context, F.R.A is a full pathname, so it's recognized in attempt (a) โจ R is a partial pathname where only the topmost node is omitted, so it's recognized in attempt (b). Be careful here: R gets recognized as a reference to F.R, not to F.R.S.R ๐ And finally, B is an arbitrary partial pathname that occurs only once in the context, so it's recognized in attempt (c) ๐
There are two stacks of contexts: one for names used in an input sense, and one for names used in an output sense. When a name needs recognizing, you first decide whether the reference is an input reference or an output reference. An input reference is (a) the right hand operand of an assign, or (b) a name in the input set spec of a FOR. An output reference is (a) the left operand of an assign, or (b) the output operand of a FOR. Then you search the first context on the appropriate stack, using the procedure from the previous page. If the name is neither recognized nor ambiguous in that context, the search moves on to the next context on the stack. If the name can't be recognized in any context on the appropriate stack, it's unrecognizable ๐ญ
When a stack is empty, the recognition procedure changes. The search continues in a special context: the context of %OPEN. Its top node, %OPEN, is a built-in system ident. Subordinate to %OPEN is a context for each open directory node. Each one represents all the idents defined in the directory nodes that have data descriptions:
F FILE LIST R STRUCT A STR (1) B STR (1)
and:
P PORT LIST R STRUCT A STR (1) B STR (1)
Then the context of %OPEN looks like Figure 9.1-3 ๐
+-------+
! %OPEN !
+-------+
!
!
+-----------+-----------+
! !
! !
+-----+ +-----+
! A ! ! S !
+-----+ +-----+
! !
! !
+-----+ +-----+
! R ! ! R !
+-----+ +-----+
! !
! !
+-----+-----+ +-----+-----+
! ! ! !
! ! ! !
+-----+ +-----+ +-----+ +-----+
! A ! ! B ! ! A ! ! B !
+-----+ +-----+ +-----+ +-----+
Figure 9.1-3 The Context of %OPEN
When a directory node is closed, its corresponding context gets removed from the context of %OPEN. When a node is opened, its associated context gets added as the rightmost context subordinate to %OPEN ๐ซถ
9.2 Context Stack Maintenance
The context stacks are always empty between requests. The FOR-operator is what adds entries to the stacks. FOR A adds the context of A to the input context stack. FOR A, B ... adds the context of A to the output stack and the context of B to the input stack ๐
When you add to an empty stack, FOR adds two contexts instead of one. The second addition is the context of the looparg, and the first addition is the context of the outermost container that encloses the looparg โจ
For example, say you have a context of %OPEN like Figure 9.1-3, and empty context stacks. The fragment FOR F.R ... adds two contexts: (1) the context of F, and (2) the context of F.R ๐
Contexts get removed from the stacks by the END that matches the FOR which added them ๐
10. Miscellaneous Topics โจ
10.1 The LIST-request
The LIST-request gives the user a way to inspect system data they care about. The user can find out the contents of the directory, the source or parsed form of any data description in the system, and the mode and connection status of any open file or port ๐
The LIST operator has a single operand, which can take any of several forms. The operator's action is to output a list of values on the Datalanguage output port ๐ฆ
To output a list of pathnames, the operand used is '%ALL'. When '%ALL' appears alone, all pathnames in the directory get listed. When '%ALL' appears after the last ident in a directory pathname, the full pathnames of all nodes subordinate to the named node get listed ๐ธ
To output one or more source descriptions, use the operand '.%SOURCE'. '.%SOURCE' has to be preceded by one of (a) '%ALL', (b) '%OPEN', or (c) the ident of an open outermost container. The output is either (a) all descriptions, (b) all open descriptions, or (c) one particular open description ๐
To output a parsed description, use the operand '.%DESC' ('%DESCRIPTION' is also accepted). This operand is preceded either by (a) '%OPEN', or (b) the ident of an open outermost container ๐ง
Examples:
Let P be the ident of an open PORT. Let A.B.C be a
directory pathname.
LIST %ALL
LIST A.B.C.%ALL
LIST %OPEN
LIST %ALL.%SOURCE
LIST %OPEN.%SOURCE
LIST P.%SOURCE
LIST %OPEN.%DESC
LIST P.%DESC
Note that 'LIST A.B.C.%SOURCE' is not legal. '.%SOURCE' must be preceded by the ident of an open container, not a pathname ๐ A similar restriction applies to '.%DESC' ๐
10.2 Constants in Datalanguage
A constant of type STRING can go in a Datalanguage request by wrapping it in single quotes:
'ABC'
To include a single quote inside a constant, put a double quote in front of it:
'FATHER"'S'
Same deal for double quotes: precede each one with a double quote:
'JOHN SAID ""HELLO""'
These constants can be used on the right side of comparison operators and of assignment operators that reference strings ๐
Eventually, Datalanguage is going to have facilities for constants of all datatypes. Those constants are simply a special case of the Datalanguage expression, and they'll be allowed wherever such expressions are allowed ๐
10.3 Character Set โจ
Okay bestie, so internally, Version 0/9 of the Datacomputer software works in 7-bit ASCII characters ๐. Its output to the ARPANET gets converted to 8-bit ASCII, and on input from the ARPANET it expects 8-bit characters and converts them down to 7-bit ๐ฆ.
To go from 7- to 8-bit, a '0' bit gets prefixed. To go from 8- to 7-bit, the high-order bit gets checked. If the high-order bit is a '0', the bit is discarded and the character is accepted as a 7-bit character. If the high-order bit is a '1', then the character is discarded ๐.
(Quick reminder, same as everywhere else in this memo: all numerical character codes are in decimal ๐ข.)
The rest of this section is about how codes 0 through 127 get treated when they show up in Datalanguage requests ๐.
Generally, printing characters are fine in requests, and control characters are not. There are some exceptions, which we'll get into below. The printing characters are codes 32-126, and the control characters are codes 0-31 and 127 โจ.
Certain control characters are accepted:
Tab(9)is accepted freely in requests. It functions as a separator (explained below) ๐ธ.EOL(31), meaning end-of-line, is accepted in requests. It works as both a separator and an activator (a). EOL has a special meaning in data, so it should not be introduced into STRING constants(***) ๐ซ.Control-L(12)is an activator and a high-level request delimiter. When it shows up in the input stream, it terminates the processing of any request being handled. It's useful for Datacomputer-user program synchronization ๐ฅ.Control-Z(26)means end-of-session when it's encountered in Datalanguage. It has the properties of Control-L, and on top of that it makes the Datacomputer run an end-of-session procedure. That closes the Datalanguage connections, closes any open files or ports, and so on ๐ญ. The effect is equivalent to a [LOGOUT(which] does not exist yet).- The two-character sequence
<carriage return(13), line feed(10)>is equivalent to EOL, and it gets translated to EOL on input from the network. The reverse sequence, as well as either character on its own, is treated simply as other control characters (ignored) ๐ .
All other control characters are ignored ๐.
The printing characters are split further into four groups: special characters, uppercase letters, lowercase letters, and digits. (The membership of these groups is defined in section 11 ๐.)
Corresponding upper and lower case letters are equivalent in requests, except inside quoted strings ๐.
Certain special characters have a lexical function, which is either break or separator. A break character ends the current lexical item and returns itself as the next item. A separator character ends the current item but doesn't begin a new one, so its only job is to separate items. Multiple separators act like a single separator. You can always insert a separator before or after a break character without changing the meaning of the request ๐ง.
The separators are:
tab(9)space(32)end-of-line(31)
The break characters are:
left parenthesis(40)right parenthesis(41)equals(61)semicolon(59)period(46)comma(44)quote(39)slash(47)
(a) An activator character makes the Datacomputer process whatever it has received since the previous activator or the beginning of the request. The meaning of a request doesn't depend on whether activators are present. However, a request won't be executed until an activator beyond the end of the request is received โณ.
While Version 0/9 defines (carriage return, linefeed) in terms of EOL, network users should not think in terms of sending EOL's to the Datacomputer over the network. EOL isn't part of the network ASCII character set, and it doesn't have a definite permanent place in Datacomputer implementation plans ๐.
10.4 Comments ๐ฌ
Comments can be added to Datalanguage requests. A comment begins with the two-character sequence '/*' and ends with the two-character sequence '*/'. Since slash is a break character, a comment does cause a lexical break, and its overall effect is that of a separator โจ.
10.5 Reserved Identifiers ๐ซ
Certain identifiers are reserved in Datalanguage, so you shouldn't use them to name containers or directory nodes. They are:
AND
APPEND
AT
CLOSE
CONNECT
CREATE
DELETE
DISCONNECT
END
EQ
FILE
FOR
GE
GT
LE
LIST
LT
NODE
NE
NOT
OPEN
OR
PORT
READ
STR
STRUCT
TO
WITH
WRITE
More reserved identifiers will be added in Version 0/10 ๐.
11. Datalanguage Syntax Expressed in BNF ๐งฉ
Okay this part is the grammar, so it's super precise. Every line below is copied exactly as it appears in the original ๐ซถ.
11.1 Requests ๐ฌ
11.1.01 <request> ::= ;
11.1.02 <request> ::= <create>
11.1.03 <request> ::= OPEN <pn> ;
11.1.04 <request> ::= OPEN <pn> <mode> ;
11.1.05 <request> ::= CLOSE <ident> ;
11.1.06 <request> ::= CONNECT <ident> TO <address> ;
11.1.07 <request> ::= DISCONNECT <ident> ;
11.1.08 <request> ::= MODE <ident> <mode> ;
11.1.09 <request> ::= DELETE <pn> ;
11.1.10 <request> ::= LIST <listarg> ;
11.1.11 <request> ::= <sr-request> ;
11.2 Data Description and Creation ๐จ
11.2.01 <create> ::= CREATE <pn>
11.2.02 <create> ::= CREATE <pn> <ftn> LIST <desc>
11.2.03 <create> ::= CREATE <pn> <ftn> LIST <size> <desc>
11.2.04 <desc> ::= <ident> <attributes>
11.2.05 <attributes> ::= LIST <size> <desc>
11.2.06 <attributes> ::= STRUCT <descs> END
11.2.07 <attributes> ::= STR <size>
11.2.08 <attributes> ::= STR <size> ,I=D
11.2.09 <descs> ::= <desc>
11.2.10 <descs> ::= <descs> <desc>
11.2.11 <ftn> ::= PORT
11.2.12 <ftn> ::= FILE
11.2.13 <ftn> ::= TEMP PORT
11.2.14 <ftn> ::= TEMPORARY PORT
11.2.15 <size> ::= ( <integer constant> )
11.3 Data Storage and Retrieval ๐๏ธ
11.3.01 <sr-request> ::= <assign>
11.3.01 <sr-request> ::= <loop>
11.3.03 <assign> ::= <pn> = <object>
11.3.04 <loop> ::= FOR <looparg> <loopbody> END
11.3.05 <looparg> ::= <exp>
11.3.06 <looparg> ::= <pn> , <exp>
11.3.07 <loopbody> ::= <sr-request>
11.3.08 <loopbody> ::= <loopbody1> <sr-request>
11.3.09 <loopbody> ::= <loopbody1>
11.3.10 <loopbody1> ::= <sr-request> ;
11.3.11 <loopbody1> ::= <loopbody1> <sr-request> ;
11.4 Expressions ๐
11.4.01 <exp> ::= <pn>
11.4.02 <exp> ::= <pn> WITH <boolexp>
11.4.03 <boolexp> ::= <pn> <comop> <string constant>
11.4.04 <boolexp> ::= ( <boolexp> )
11.4.05 <boolexp> ::= NOT <boolexp>
11.4.06 <boolexp> ::= <boolexp> AND <boolexp>
11.4.07 <boolexp> ::= <boolexp> OR <boolexp>
11.4.08 <comop> ::= EQ
11.4.09 <comop> ::= NE
11.4.10 <comop> ::= GT
11.4.11 <comop> ::= LT
11.4.12 <comop> ::= GE
11.4.13 <comop> ::= LE
11.5 Miscellaneous ๐ธ
11.5.01 <address> ::= <quote> <TENEX file designator>
<quote>
11.5.02 <address> ::= <socket> AT <host>
11.5.03 <address> ::= <socket>
11.5.04 <socket> ::= <integer constant> //INTERPRETED AS
DECIMAL
11.5.05 <host> ::= <integer constant> //INTERPRETED AS
DECIMAL
11.5.06 <host> ::= ***** TENEX host names *****
11.5.07 <object> ::= <pn>
11.5.08 <object> ::= <string constant>
11.5.09 <mode> ::= READ
11.5.10 <mode> ::= APPEND
11.5.11 <mode> ::= WRITE
11.5.12 <listarg> ::= %ALL
11.5.13 <listarg> ::= <pn>.%ALL
11.5.14 <listarg> ::= %OPEN
11.5.15 <listarg> ::= %ALL.%SOURCE
11.5.16 [<LISTARG>] ::= <IDENT>.%SOURCE
11.5.17 <listarg> ::= %OPEN.%SOURCE
11.5.18 <listarg> ::= %OPEN.%DESC
11.5.19 <listarg> ::= <ident>.%DESC
11.5.20 <pn> ::= <ident>
11.5.21 <pn> ::= <pn>.<ident>
11.5.22 <ident> ::= <letter>
11.5.23 <ident> ::= <ident> <letter>
11.5.24 <ident> ::= <ident> <digit>
11.5.25 <integer constant> ::= <digit>
11.5.26 <integer constant> ::= <integer constant> <digit>
11.5.27 <string constant> ::= <quote> <string conbody>
<quote>
11.5.28 <string conbody> ::= <nonquote>
11.5.28 <string conbody> ::= <string conbody> <nonquote>
11.6 Character Set ๐
okay bestie, this is the alphabet section and it's giving very organised ๐
Every character that can show up in datalanguage gets sorted into a bucket: <separator>, <special>, <letter>, <digit>, <nonquote>, <eol>, plus the little guys like <carriage return>, <line feed>, <quote> and <superquote> ๐ธ The grammar is copied exactly below so nothing gets lost in translation ๐ซถ
11.6.01 <separator> ::= //SPACE(32)
11.6.02 <separator> ::= //TAB(9)
11.6.03 <separator> ::= <eol>
11.6.04 <special> ::= <quote>
11.6.05 <special> ::= <superquote>
11.6.06 <special> ::= <special1>
11.6.07 <letter> ::= A
11.6.08 <letter> ::= B
...............
11.6.09 <letter> ::= Z
11.6.10 <letter> ::= a
11.6.11 <letter> ::= b
...............
11.6.12 <letter> ::= z
11.6.13 <digit> ::= 0
11.6.14 <digit> ::= 1
...............
11.6.15 <digit> ::= 9
11.6.16 <nonquote> ::= <letter>
11.6.17 <nonquote> ::= <digit>
11.6.18 <nonquote> ::= <superquote> <quote>
11.6.19 <nonquote> ::= <superquote> <superquote>
11.6.20 <nonquote> ::= <special1>
11.6.21 <nonquote> ::= <separator>
11.6.22 <eol> ::= //EOL (31)
11.6.23 <eol> ::= <carriage return> <line feed>
11.6.24 <carriage return> ::= //CARRIAGE RETURN (13)
11.6.25 <line feed> ::= //LINE FEED (10)
11.6.26 <quote> ::= ' //SINGLE QUOTE(44)
11.6.27 <superquote> ::= " //DOUBLE QUOTE(34)
11.6.28 <special1> ::= ! //EXCLAMATION POINT(33)
11.6.29 <special1> ::= # //NUMBER SIGN(35)
11.6.30 <special1> ::= $ //DOLLAR SIGN(36)
11.6.31 <special1> ::= % //PERCENT SIGN(37)
11.6.32 <special1> ::= & //AMPERSAND(38)
11.6.33 <special1> ::= ( //LEFT PARENTHESIS(40)
11.6.34 <special1> ::= ) //RIGHT PARENTHESIS(41)
11.6.35 <special1> ::= * //ASTERISK(42)
11.6.36 <special1> ::= + //PLUS SIGN(43)
11.6.37 <special1> ::= , //COMMA(44)
11.6.38 <special1> ::= - //MINUS SIGN(45)
11.6.39 <special1> ::= . //PERIOD(46)
11.6.40 <special1> ::= / //SLASH(47)
11.6.41 <special1> ::= : //COLON(58)
11.6.42 <special1> ::= ; //SEMICOLON(59)
11.6.43 <special1> ::= < //LEFT ANGLE BRACKET(60)
11.6.44 <special1> ::= = //EQUAL SIGN(61)
11.6.45 <special1> ::= > //RIGHT ANGLE BRACKET(62)
11.6.46 <special1> ::= ? //QUESTION MARK(63)
11.6.47 <special1> ::= @ //AT-SIGN(64)
11.6.48 <special1> ::= [ //LEFT SQUARE BRACKET(91)
11.6.49 <special1> ::= //BACK SLASH(92)
11.6.50 <special1> ::= ] //RIGHT SQUARE BRACKET(93)
11.6.51 <special1> ::= ^ //CIRCUMFLEX(94)
11.6.52 <special1> ::= _ //UNDERBAR(95)
11.6.53 <special1> ::= ` //ACCENT GRAVE(96)
11.6.54 <special1> ::= { //LEFT BRACE(123)
11.6.55 <special1> ::= | //VERTICAL BAR(124)
11.6.56 <special1> ::= } //RIGHT BRACE(125)
11.6.57 <special1> ::= ~ //TILDE(126)
<EOF>
[ This RFC was put into machine readable form for entry ]
[ into the online RFC archives by Walter Benton 12/98 ]
๐ฆ where this page comes from
- ietf: rfc515 1973-06
- ๐ girlified by claude-haiku-5-5 on : a language model's rewrite of the original, under its terms