spec: corrections, clarifications, comments

- Tweaked to fix typos or improve readability

- Added some clarifying sentences

- Left comments with open questions

Change-Id: If2f967849859651e05696319beadfe2a2dbae0cb
Reviewed-on: https://cue-review.googlesource.com/c/cue/+/3080
Reviewed-by: Marcel van Lohuizen <mpvl@golang.org>
diff --git a/doc/ref/spec.md b/doc/ref/spec.md
index 6b694f1..026646f 100644
--- a/doc/ref/spec.md
+++ b/doc/ref/spec.md
@@ -594,7 +594,7 @@
 and for any other value `v` for which `v ⊑ a` and `v ⊑ b`
 it holds that `v ⊑ u`.)
 Since CUE values form a lattice, the unification of two CUE values is
-always unique. 
+always unique.
 
 These all follow from the definition of unification:
 - The unification of `a` with itself is always `a`.
@@ -714,10 +714,10 @@
 M2: *(v1, d1) => (v1, d1)
 ```
 
-In general, any operation in CUE involving default values proceeds along the
+In general, any operation `f` in CUE involving default values proceeds along the
 following lines
 ```
-O1: f((v1, d1), ..., (vn, dn))  => (fn(v1, ..., vn), fn(d1, ..., dn))
+O1: f((v1, d1), ..., (vn, dn))  => (f(v1, ..., vn), f(d1, ..., dn))
 ```
 where, with the exception of disjunction, a value `v` without a default
 value is promoted to `(v, v)`.
@@ -885,7 +885,7 @@
 A decimal floating-point literal always has type `float`;
 it is not an instance of `int` even if it is an integral number.
 
-Integer literals are always of type `int and don't match type `float`.
+Integer literals are always of type `int` and don't match type `float`.
 
 Numeric literals are exact values of arbitrary precision.
 If the operation permits it, numbers should be kept in arbitrary precision.
@@ -913,7 +913,7 @@
 The predeclared string type is `string`; it is a defined type.
 
 The length of a string `s` (its size in bytes) can be discovered using
-the built-in function len.
+the built-in function `len`.
 
 
 ### Bytes
@@ -927,7 +927,7 @@
 
 ### Bounds
 
-A _bound_, syntactically_ a [unary expression](#Operands), defines
+A _bound_, syntactically a [unary expression](#Operands), defines
 an infinite disjunction of concrete values than can be represented
 as a single comparison.
 
@@ -965,6 +965,17 @@
 The (unique) struct with no fields, written `{}`, has every struct as an
 instance. It can be considered the type of all structs.
 
+```
+{a: 1} ⊑ {}
+{a: 1, b: 1} ⊑ {a: 1}
+{a: 1} ⊑ {a: int}
+{a: 1, b: 1} ⊑ {a: int, b: float}
+
+{} ⋢ {a: 1}
+{a: 2} ⋢ {a: 1}
+{a: 1} ⋢ {b: 1}
+```
+
 A field may be required or optional.
 The successful unification of structs `a` and `b` is a new struct `c` which
 has all fields of both `a` and `b`, where
@@ -993,10 +1004,30 @@
 to explicitly use `_|_` to discard a field, for instance).
 -->
 
+Syntactically, a struct literal may contain multiple fields with
+the same label, the result of which is a single field with the same properties
+as defined as the unification of two fields resulting from unifying two structs.
+
+These examples illustrate required fields only. Examples with
+optional fields follow below.
+
+```
+Expression                             Result (without optional fields)
+{a: int, a: 1}                         {a: 1}
+{a: int} & {a: 1}                      {a: 1}
+{a: >=1 & <=7} & {a: >=5 & <=9}        {a: >=5 & <=7}
+{a: >=1 & <=7, a: >=5 & <=9}           {a: >=5 & <=7}
+
+{a: 1} & {b: 2}                        {a: 1, b: 2}
+{a: 1, b: int} & {b: 2}                {a: 1, b: 2}
+
+{a: 1} & {a: 2}                        _|_
+```
+
 Syntactically, the labels of optional fields are followed by a
 question mark `?`.
 The question mark is not part of the field name.
-Concrete field labels may be an identifier or string, the later of which may be
+Concrete field labels may be an identifier or string, the latter of which may be
 interpolated.
 References within such interpolated strings are resolved within
 the scope of the struct in which the label sequence is
@@ -1013,16 +1044,60 @@
 An optional expression limits this to the set of optional fields which
 labels match the expression.
 -->
-A Bind label binds an identifier to the label name scoped to the field value.
-It also makes all possible labels an optional field set to the
-associated field value.
+A Bind label, written `<identifier>`, is useful for capturing a label as a value
+and for enforcing constraints on all fields of a struct.
+In a field using a bind label, such as
+```
+{
+    <id>: { name: id }
+}
+```
+the label name is bound to the identifier for the scope of the field value, so
+it can be used inside the value to denote the label.
+
+A bind label matches every field of its enclosing struct, so
+```
+{
+    <id>: { name: id }
+    a: { value: 1 }
+}
+```
+evaluates to
+
+```
+{
+    a: { name: "a" }
+    a: { value: 1 }
+}
+```
+Since identical fields in a struct unify, this is equivalent to
+```
+{
+    a: {
+        name: "a"
+        value: 1
+    }
+}
+```
+
+Because bind labels match every field in a struct, they can enforce constraints
+on all fields. The struct
+
+```
+ints: {
+    <_>: int
+}
+```
+can only have integer field values:
+
+```
+ints & { a: 1 } // ok
+ints & { b: "two" } // _|_, because int & "two" == _|_.
+```
+
 The token `...` is a shorthand for `<_>: _`.
 <!-- NOTE: if we allow ...Expr, as in list, it would mean something different. -->
 
-Syntactically, a struct literal may contain multiple fields with
-the same label, the result of which is a single field with the same properties
-as defined as the unification of two fields resulting from unifying two structs.
-
 
 <!-- NOTE:
 A DefinitionDecl does not allow repeated labels. This is to avoid
@@ -1078,6 +1153,10 @@
 ExpressionLabel = BindLabel
 Label           = ConcreteLabel [ "?" ] | ExpressionLabel  "?".
 
+<!-- (jba) According to this grammar, I must write a "?" after a bind label, so
+"<Name>: name" is illegal.
+-->
+
 attribute       = "@" identifier "(" attr_elems ")" .
 attr_elems      = attr_elem { "," attr_elem }
 attr_elem       =  attr_string | attr_label | attr_nest .
@@ -1087,48 +1166,55 @@
 attr_char        = /* an arbitrary Unicode code point except newline, ',', '"', `'`, '#', '=', '(', and ')' */ .
 ```
 
-```
-{a: 1} ⊑ {}
-{a: 1, b: 1} ⊑ {a: 1}
-{a: 1} ⊑ {a: int}
-{a: 1, b: 1} ⊑ {a: int, b: float}
-
-{} ⋢ {a: 1}
-{a: 2} ⋢ {a: 1}
-{a: 1} ⋢ {b: 1}
-```
 
 ```
 Expression                             Result (without optional fields)
-{a: int, a: 1}                         {a: 1}
-{a: int} & {a: 1}                      {a: 1}
-{a: >=1 & <=7} & {a: >=5 & <=9}        {a: >=5 & <=7}
-{a: >=1 & <=7, a: >=5 & <=9}           {a: >=5 & <=7}
-
-{a: 1} & {b: 2}                        {a: 1, b: 2}
-{a: 1, b: int} & {b: 2}                {a: 1, b: 2}
-
-{a: 1} & {a: 2}                        _|_
-
 a: { foo?: string }                    {}
 b: { foo: "bar" }                      { foo: "bar" }
 c: { foo?: *"bar" | string }           {}
-d: { [string]?: string }
 
 d: a & b                               { foo: "bar" }
 e: b & c                               { foo: "bar" }
 f: a & c                               {}
 g: a & { foo?: number }                {}
 h: b & { foo?: number }                _|_
+i: c & { foo: string }                 { foo: "bar" }
 ```
 
-
 #### Closed structs
 
 By default, structs are open to adding fields.
 Instances of an open struct `p` may contain fields not defined in `p`.
+This is makes it easy to add fields, but can lead to bugs:
+
+```
+S: {
+    field1: string
+}
+
+S1: S & { field2: "foo" }
+
+// S1 is { field1: string, field2: "foo" }
+
+
+A: {
+    field1: string
+    field2: string
+}
+
+A1: A & {
+    feild1: "foo"  // "field1" was accidentally misspelled
+}
+
+// A1 is
+//    { field1: string, field2: string, feild1: "foo" }
+// not the intended
+//    { field1: "foo", field2: string }
+```
+
 A _closed struct_ `c` is a struct whose instances may not have regular fields
 not defined in `c`.
+
 Closing a struct is equivalent to adding an optional field with value `_|_`
 for all undefined fields.
 
@@ -1168,10 +1254,12 @@
 })
 ```
 
+<!-- (jba) Somewhere it should be said that optional fields are only
+     interesting inside closed structs. -->
 
 #### Embedding
 
-A struct may contain an _embedded value_, an Operand used
+A struct may contain an _embedded value_, an operand used
 as a declaration, which must evaluate to a struct.
 An embedded value of type struct is unified with the struct in which it is
 embedded, but disregarding the restrictions imposed by closed structs
@@ -1188,10 +1276,39 @@
 A struct resulting from such a unification is closed if either of the involved
 structs were closed.
 
+```
+S1: {
+    a: 1
+    b: 2
+    {
+        c: 3
+    }
+}
+// S1 is { a: 1, b: 2, c: 3 }
+
+S2: close({
+    a: 1
+    b: 2
+    {
+        c: 3
+    }
+})
+// same as close(S1)
+
+S3: {
+    a: 1
+    b: 2
+    close({
+        c: 3
+    })
+}
+// same as S2
+```
+
 
 #### Definitions
 
-A fields of a struct may be declared as a regular field (using `:`)
+A field of a struct may be declared as a regular field (using `:`)
 or as a _definition_ (using `::`).
 Definitions are not emitted as part of the model and are never required
 to be concrete when emitting data.
@@ -1257,6 +1374,7 @@
 D2: D & { a: 12, b: 33 }  // _|_ // cannot define both `a` and `b`
 ```
 
+
 <!---
 JSON fields are usual camelCase. Clashes can be avoided by adopting the
 convention that definitions be TitleCase. Unexported definitions are still
@@ -1269,9 +1387,11 @@
 
 Fields may be associated with attributes.
 Attributes define additional information about a field,
-such as a mapping to a protobuf tag or alternative
+such as a mapping to a protocol buffer <!-- TODO: add link --> tag or alternative
 name of the field when mapping to a different language.
 
+<!-- TODO define attribute syntax here, before getting into semantics. -->
+
 If a field has multiple attributes their identifiers must be unique.
 Attributes accumulate when unifying two fields, removing duplicate entries.
 It is an error for the resulting field to have two different attributes
@@ -1305,6 +1425,8 @@
 // attr:  int    @xml(,attr) @xml(a1,attr) @go(Attr)
 ```
 
+#### Aliases
+
 In addition to fields, a struct literal may also define aliases.
 Aliases name values that can be referred to
 within the [scope](#declarations-and-scopes) of their
@@ -1313,6 +1435,11 @@
 generated data.
 The name of an alias must be unique within the struct literal.
 
+<!-- TODO: explain the difference between aliases and definitions.
+     Now that you have definitions, are aliases really necessary?
+     Consider removing.
+-->
+
 ```
 // The empty struct.
 {}
@@ -1328,6 +1455,8 @@
 }
 ```
 
+#### Shorthand notation for nested structs
+
 A field whose value is a struct with a single field may be written as
 a sequence of the two field names,
 followed by a colon and the value of that single field.
@@ -2829,8 +2958,3 @@
 ### An example package
 
 TODO
-
-
-
-
-