this repo has no description
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

doc/ref: annotate CUE code blocks via their triple backticks

I experimented with Hugo and it turns out that triple backticks
with syntax highlighting ignore any text after a space,
so we can abuse that a little to annotate code blocks with intent.

Start documenting and using a few conventions with this trick
as a starting point; the following commits will start using them.

We only tweak the contents of one code block, to make the header
a comment so that we can parse the whole block as valid CUE.

Signed-off-by: Daniel Martí <mvdan@mvdan.cc>
Change-Id: I107105360059fdca10bec15adabb5b3495e1b65f
Reviewed-on: https://review.gerrithub.io/c/cue-lang/cue/+/1232178
Reviewed-by: Roger Peppe <rogpeppe@gmail.com>
Reviewed-by: Marcel van Lohuizen <mpvl@gmail.com>
TryBot-Result: CUEcueckoo <cueckoo@cuelang.org>
Unity-Result: CUE porcuepine <cue.porcuepine@gmail.com>

+98 -74
+98 -74
doc/ref/spec.md
··· 49 49 50 50 ## Notation 51 51 52 + <!-- 53 + We annotate code blocks with syntax highlighting like ```ebnf. 54 + It turns out that we can use a space to add arbitrary text 55 + without breaking syntax highlighting in Hugo, 56 + so we use that to annotate code blocks with intent: 57 + 58 + * `cue` for standalone CUE files which we expect to parse OK; 59 + we do not yet mark what we want to do with them (export, eval, vet) 60 + nor do we record what the expected outcome is yet. 61 + 62 + * `cue untested` for syntax that is CUE-like but invalid. 63 + 64 + * `cue parse` for CUE files which we expect parse OK, 65 + but we do not expect to compile or evaluate correctly. 66 + 67 + * `cue rows` for tables of input-output rows. 68 + Just like `cue`, we do not yet mark what to do with them, 69 + but the output column is generally the expected outcome. 70 + --> 71 + 52 72 The syntax is specified using Extended Backus-Naur Form (EBNF): 53 73 54 74 ```ebnf ··· 203 223 identifier = [ "#" | "_#" ] letter { letter | unicode_digit } . 204 224 ``` 205 225 206 - ``` 226 + ```cue parse 207 227 a 208 228 _x9 209 229 fieldName ··· 318 338 When multiplying a fraction by a multiplier, the result is truncated 319 339 towards zero if it is not an integer. 320 340 321 - ``` 341 + ```cue parse 322 342 42 323 343 1.5G // 1_500_000_000 324 344 1.3Ki // 1.3 * 1024 = trunc(1331.2) = 1331 ··· 337 357 One of the integer part or the fractional part may be elided; one of the decimal 338 358 point or the exponent may be elided. 339 359 340 - ``` 360 + ```cue parse 341 361 0. 342 362 72.40 343 363 072.40 // == 72.40 ··· 473 493 Carriage return characters (`\r`) inside string literals are discarded from 474 494 the string value. 475 495 476 - ``` 496 + ```cue untested 477 497 'a\000\xab' 478 498 '\007' 479 499 '\377' ··· 495 515 496 516 These examples all represent the same string: 497 517 498 - ``` 518 + ```cue parse 499 519 "日本語" // UTF-8 input text 500 520 '日本語' // UTF-8 input text as byte sequence 501 521 "\u65e5\u672c\u8a9e" // the explicit Unicode code points ··· 523 543 A closing triple quote may not appear in the string. 524 544 To include it is suffices to escape one of the quotes. 525 545 526 - ``` 546 + <!-- TODO: should the backslash here work? --> 547 + ```cue untested 527 548 """ 528 549 lily: 529 550 out of the water ··· 539 560 540 561 This represents the same string as: 541 562 542 - ``` 563 + ```cue 543 564 "lily:\nout of the water\nout of itself\n\n" + 544 565 "bass\npicking bugs\noff the moon\n" + 545 566 " — Nick Virgilio, Selected Haiku, 1988" ··· 676 697 (a_0 | ... |a_n) & b ==> a_0&b | ... | a_n&b. 677 698 ``` 678 699 679 - ``` 700 + ```cue rows 680 701 Expression Result 681 702 ({a:1} | {b:2}) & {c:3} {a:1, c:3} | {b:2, c:3} 682 703 (int | string) & "foo" "foo" ··· 819 840 disjunction literals be normalized). 820 841 --> 821 842 822 - ``` 843 + ```cue rows 823 844 Expression Resolves to 824 845 "tcp" | "udp" "tcp" | "udp" 825 846 *"tcp" | "udp" "tcp" ··· 868 889 Top is represented by the underscore character `_`, lexically an identifier. 869 890 Unifying any value `v` with top results in `v` itself. 870 891 871 - ``` 892 + ```cue rows 872 893 Expr Result 873 894 _ & 5 5 874 895 _ & _ _ ··· 887 908 null_lit = "null" . 888 909 ``` 889 910 890 - ``` 911 + ```cue rows 891 912 null & 8 _|_ 892 913 null & _ null 893 914 null & _|_ _|_ ··· 905 926 bool_lit = "true" | "false" . 906 927 ``` 907 928 908 - ``` 929 + ```cue rows 909 930 bool & true true 910 931 true & true true 911 932 true & false _|_ ··· 991 1012 `op a` is the disjunction of every `x` such that `x op a`. 992 1013 993 1014 994 - ``` 1015 + ```cue parse 995 1016 2 & >=2 & <=5 // 2, where 2 is either an int or float. 996 1017 2.5 & >=1 & <=5 // 2.5 997 1018 2 & >=1.0 & <3.0 // 2.0 ··· 1064 1085 attr_token = /* any token except '(', ')', '[', ']', '{', or '}' */ 1065 1086 ``` 1066 1087 1067 - ``` 1088 + ```cue rows 1068 1089 Expression Result 1069 1090 {a: int, a: 1} {a: 1} 1070 1091 {a: int} & {a: 1} {a: 1} ··· 1104 1125 Implementations may error upon encountering a required field constraint 1105 1126 when manifesting CUE as data. 1106 1127 1107 - ``` 1128 + ```cue rows 1108 1129 Expression Result 1109 1130 {foo?: 3} & {foo: 3} {foo: 3} 1110 1131 {foo!: 3} & {foo: 3} {foo: 3} ··· 1165 1186 an expression wrapped in parentheses. 1166 1187 A dynamic field may be marked as optional or required. 1167 1188 1168 - ``` 1189 + ```cue rows 1169 1190 Expression Result 1170 1191 a: "foo" a: "foo" 1171 1192 b: "bar" b: "bar" ··· 1208 1229 The token `...` is a shorthand for `..._`. 1209 1230 _Note_: default constraints of the form `..._` are not yet implemented. 1210 1231 1211 - 1212 - ``` 1232 + <!-- NOTE: default constraints not yet implemented --> 1233 + ```cue untested 1213 1234 a: { 1214 1235 foo: string // foo is a string 1215 1236 [=~"^i"]: int // all other fields starting with i are integers ··· 1292 1313 additionalProperties and additionalItems. 1293 1314 --> 1294 1315 1295 - ``` 1316 + ```cue 1296 1317 intMap: [string]: int 1297 1318 intMap: { 1298 1319 t1: 43 ··· 1311 1332 in this case just `hank`, and unifies the associated constraint 1312 1333 with the matched field, resulting in: 1313 1334 1314 - ``` 1335 + ```cue 1315 1336 nameMap: hank: { 1316 1337 firstName: "Hank" 1317 1338 nickName: "Hank" ··· 1325 1346 Instances of an open struct `p` may contain fields not defined in `p`. 1326 1347 This is makes it easy to add fields, but can lead to bugs: 1327 1348 1328 - ``` 1349 + ```cue 1329 1350 S: { 1330 1351 field1: string 1331 1352 } ··· 1362 1383 implicitly and recursively by [definitions](#definitions-and-hidden-fields). 1363 1384 1364 1385 1365 - ``` 1386 + ```cue 1366 1387 A: close({ 1367 1388 field1: string 1368 1389 field2: string ··· 1417 1438 1418 1439 Syntactically, embeddings may be any expression. 1419 1440 1420 - ``` 1441 + ```cue 1421 1442 S1: { 1422 1443 a: 1 1423 1444 b: 2 ··· 1465 1486 If referencing a definition would always result in an error, implementations 1466 1487 may report this inconsistency at the point of its declaration. 1467 1488 1468 - ``` 1489 + ```cue 1469 1490 #MyStruct: { 1470 1491 sub: field: string 1471 1492 } ··· 1493 1514 ``` 1494 1515 1495 1516 1496 - ``` 1517 + ```cue 1497 1518 #A: {a: int} 1498 1519 1499 1520 B: { ··· 1547 1568 name of the field when mapping to a different language. 1548 1569 1549 1570 1550 - ``` 1571 + ```cue 1551 1572 // Package attribute 1552 1573 @protobuf(proto3) 1553 1574 ··· 1629 1650 Consider removing. 1630 1651 --> 1631 1652 1632 - ``` 1653 + ```cue 1633 1654 // A field alias 1634 1655 foo: X // 4 1635 1656 X="not an identifier": 4 ··· 1653 1674 in which it is declared. 1654 1675 The identifier must be unique within its scope. 1655 1676 1656 - ``` 1677 + ```cue 1657 1678 let x = expr 1658 1679 1659 1680 a: x + 1 ··· 1666 1687 a colon-separated sequence of the two field names, 1667 1688 followed by a colon and the value of that single field. 1668 1689 1669 - ``` 1690 + ```cue 1670 1691 job: myTask: replicas: 2 1671 1692 ``` 1672 1693 expands to 1673 - ``` 1694 + ```cue 1674 1695 job: { 1675 1696 myTask: { 1676 1697 replicas: 2 ··· 1740 1761 1741 1762 Lists can be thought of as structs: 1742 1763 1743 - ``` 1764 + ```cue 1744 1765 List: *null | { 1745 1766 Elem: _ 1746 1767 Tail: List ··· 1750 1771 For closed lists, `Tail` is `null` for the last element, for open lists it is 1751 1772 `*null | List`, defaulting to the shortest variant. 1752 1773 For instance, the open list [ 1, 2, ... ] can be represented as: 1753 - ``` 1774 + ```cue 1754 1775 open: List & { Elem: 1, Tail: { Elem: 2 } } 1755 1776 ``` 1756 1777 and the closed version of this list, [ 1, 2 ], as 1757 - ``` 1778 + ```cue 1758 1779 closed: List & { Elem: 1, Tail: { Elem: 2, Tail: null } } 1759 1780 ``` 1760 1781 ··· 1873 1894 Any identifier starting with `_` is hidden from other packages; 1874 1895 it resides in a separate namespace than namesake identifiers of other packages. 1875 1896 1876 - ``` 1897 + ```cue 1877 1898 package mypackage 1878 1899 1879 1900 foo: string // visible outside mypackage ··· 1907 1928 If this label is an identifier, it binds the field to that identifier, 1908 1929 so the field's value can be referenced by writing the identifier. 1909 1930 String labels are not bound to fields. 1910 - ``` 1931 + ```cue 1911 1932 a: { 1912 1933 b: 2 1913 1934 "s": 3 ··· 1986 2007 which must be [imported](#import-declarations). 1987 2008 The identifier must be declared in the [package block](#blocks) of that package. 1988 2009 1989 - ``` 2010 + ```cue parse 1990 2011 math.Sin // denotes the Sin function in package math 1991 2012 ``` 1992 2013 ··· 2000 2021 Implementations may use a different mechanism to evaluate as long as 2001 2022 these semantics are maintained. 2002 2023 2003 - ``` 2024 + ```cue 2004 2025 a: { 2005 2026 place: string 2006 2027 greeting: "Hello, \(place)!" ··· 2053 2074 TODO: considering allowing decimal_lit for selectors. 2054 2075 ---> 2055 2076 2056 - ``` 2077 + ```cue parse 2057 2078 x 2058 2079 2 2059 2080 (s + ".txt") ··· 2069 2090 For a [primary expression](#primary-expressions) `x` that is not a [package name](#package-clause), 2070 2091 the selector expression 2071 2092 2072 - ``` 2093 + ```cue parse 2073 2094 x.f 2074 2095 ``` 2075 2096 ··· 2117 2138 In the latter case the expression is incomplete. 2118 2139 The operand of a selector may be associated with a default. 2119 2140 2120 - ``` 2141 + ```cue 2121 2142 T: { 2122 2143 x: int 2123 2144 y: 3 ··· 2148 2169 2149 2170 A primary expression of the form 2150 2171 2151 - ``` 2172 + ```cue parse 2152 2173 a[x] 2153 2174 ``` 2154 2175 ··· 2180 2201 - bottom (an error), otherwise 2181 2202 2182 2203 2183 - ``` 2204 + ```cue 2184 2205 a: [ 1, 2 ][1] // 2 2185 2206 b: [ 1, 2 ][2] // _|_ 2186 2207 c: [ 1, 2, ...][2] // _|_ ··· 2264 2285 Binary operators of the same precedence associate from left to right. 2265 2286 For instance, `x / y * z` is the same as `(x / y) * z`. 2266 2287 2267 - ``` 2288 + ```cue parse 2268 2289 +x 2269 2290 23 + 3*x[i] 2270 2291 x <= f() ··· 2309 2330 #### String operators 2310 2331 2311 2332 Strings can be concatenated using the `+` operator: 2312 - ``` 2333 + ```cue parse 2313 2334 s: "hi " + name + " and good bye" 2314 2335 ``` 2315 2336 String addition creates a new string by concatenating the operands. 2316 2337 2317 2338 A string can be repeated by multiplying it: 2318 2339 2319 - ``` 2340 + ```cue parse 2320 2341 s: "etc. "*3 // "etc. etc. etc. " 2321 2342 ``` 2322 2343 ··· 2386 2407 <!-- TODO: Implementations should adopt an algorithm that runs in linear time? --> 2387 2408 <!-- Consider implementing Level 2 of Unicode regular expression. --> 2388 2409 2389 - ``` 2410 + ```cue parse 2390 2411 3 < 4 // true 2391 2412 3 < 4.0 // true 2392 2413 null == 2 // false ··· 2574 2595 of which the values are an instance of the parameter types of `F` 2575 2596 and are evaluated before the function is called. 2576 2597 2577 - ``` 2598 + ```cue parse 2578 2599 a: math.Atan2(x, y) 2579 2600 ``` 2580 2601 ··· 2638 2659 ElseClause = "else" StructLit . 2639 2660 ``` 2640 2661 2641 - ``` 2662 + ```cue 2642 2663 a: [1, 2, 3, 4] 2643 2664 b: [for x in a if x > 1 { x+1 }] // [3, 4, 5] 2644 2665 ··· 2676 2697 - struct: illegal 2677 2698 2678 2699 2679 - ``` 2700 + ```cue 2680 2701 a: "World" 2681 2702 b: "Hello \( a )!" // Hello World! 2682 2703 ``` ··· 2698 2719 interpolation fail, they will be printed as an expression. This allows failing 2699 2720 expressions to be a part of the error message. 2700 2721 2701 - ``` 2722 + ```cue 2702 2723 a: 1/0 | error("infinity and beyond!: \(1/0)") 2703 2724 ``` 2704 2725 ··· 2722 2743 - list.Len(x) 2723 2744 --> 2724 2745 2725 - ``` 2746 + ```cue rows 2726 2747 Expression Result 2727 2748 len("Hellø") 6 2728 2749 len([1, 2, 3]) 3 ··· 2742 2763 the `&` operator to all elements in the list. 2743 2764 It returns top for the empty list. 2744 2765 2745 - ``` 2766 + ```cue rows 2746 2767 Expression: Result 2747 2768 and([a, b]) a & b 2748 2769 and([a]) a ··· 2755 2776 the `|` operator to all elements in the list. 2756 2777 It returns bottom for the empty list. 2757 2778 2758 - ``` 2779 + ```cue rows 2759 2780 Expression: Result 2760 2781 or([a, b]) a | b 2761 2782 or([a]) a ··· 2774 2795 ``` 2775 2796 where `|y|` denotes the absolute value of `y`. 2776 2797 2777 - ``` 2798 + <!-- TODO: check tables like these --> 2799 + ```cue untested 2778 2800 x y div(x, y) mod(x, y) 2779 2801 5 3 1 2 2780 2802 -5 3 -2 1 ··· 2793 2815 2794 2816 with `quo(x, y)` truncated towards zero. 2795 2817 2796 - ``` 2818 + <!-- TODO: check tables like these --> 2819 + ```cue untested 2797 2820 x y quo(x, y) rem(x, y) 2798 2821 5 3 1 2 2799 2822 -5 3 -1 -2 ··· 2836 2859 The validator succeeds if the count satisfies the numeric constraint provided 2837 2860 as the first argument. 2838 2861 2839 - ``` 2862 + ```cue 2840 2863 // Exactly 2 schemas must match 2841 2864 value: "foo" & matchN(2, [string, !="bar", <4]) // true: string and !="bar" match 2842 2865 ··· 2868 2891 otherwise, the "else" schema is applied. 2869 2892 The validator succeeds if the chosen schema unifies successfully with the value. 2870 2893 2871 - ``` 2894 + ```cue 2872 2895 // If value is a string, it must have length > 3; otherwise it must be > 10 2873 2896 value: "hello" & matchIf(string, len(value) > 3, value > 10) // OK; len("hello") is >3 2874 2897 ··· 2891 2914 A _reference cycle_ occurs if a field references itself, either directly or 2892 2915 indirectly. 2893 2916 2894 - ``` 2917 + ```cue 2895 2918 // x references itself 2896 2919 x: x 2897 2920 ··· 2913 2936 and postpone validating `a == e` until after all references 2914 2937 in `e` have been resolved. 2915 2938 2916 - ``` 2939 + ```cue rows 2917 2940 // Config Evaluates to (requiring concrete values) 2918 2941 x: { x: { 2919 2942 a: b + 100 a: _|_ // cycle detected ··· 2940 2963 <!-- Tomabechi's graph unification algorithm 2941 2964 can detect such cycles at near-zero cost. --> 2942 2965 2943 - ``` 2944 - Configuration Evaluated 2945 - // c Cycles in nodes of type struct evaluate 2946 - // ↙︎ ↖ to the fixed point of unifying their 2947 - // a → b values ad infinitum. 2966 + ```cue 2967 + // Configuration Evaluated 2968 + // 2969 + // c Cycles in nodes of type struct evaluate 2970 + // ↙︎ ↖ to the fixed point of unifying their 2971 + // a → b values ad infinitum. 2948 2972 2949 - a: b & { x: 1 } // a: { x: 1, y: 2, z: 3 } 2950 - b: c & { y: 2 } // b: { x: 1, y: 2, z: 3 } 2951 - c: a & { z: 3 } // c: { x: 1, y: 2, z: 3 } 2973 + a: b & { x: 1 } // a: { x: 1, y: 2, z: 3 } 2974 + b: c & { y: 2 } // b: { x: 1, y: 2, z: 3 } 2975 + c: a & { z: 3 } // c: { x: 1, y: 2, z: 3 } 2952 2976 2953 2977 // resolve a b & {x:1} 2954 2978 // substitute b c & {y:2} & {x:1} ··· 2960 2984 This rule also applies to field values that are disjunctions of unification 2961 2985 operations of the above form. 2962 2986 2963 - ``` 2987 + ```cue 2964 2988 a: b&{x:1} | {y:1} // {x:1,y:3,z:2} | {y:1} 2965 2989 b: {x:2} | c&{z:2} // {x:2} | {x:1,y:3,z:2} 2966 2990 c: a&{y:3} | {z:3} // {x:1,y:3,z:2} | {z:3} ··· 2985 3009 2986 3010 A structural cycle is when a node references one of its ancestor nodes. 2987 3011 It is possible to construct a structural cycle by unifying two acyclic values: 2988 - ``` 3012 + ```cue 2989 3013 // acyclic 2990 3014 y: { 2991 3015 f: h: g ··· 3002 3026 Implementations should be able to detect such structural cycles dynamically. 3003 3027 3004 3028 A structural cycle can result in infinite structure or evaluation loops. 3005 - ``` 3029 + ```cue 3006 3030 // infinite structure 3007 3031 a: b: a 3008 3032 ··· 3020 3044 A given node `x`, whose value is composed of the conjuncts `c1 & ... & cn`, 3021 3045 is valid if any of its conjuncts is not cyclic. 3022 3046 3023 - ``` 3047 + ```cue 3024 3048 // Disallowed: a list of infinite length with all elements being 1. 3025 3049 #List: { 3026 3050 head: 1 ··· 3084 3108 SourceFile = { attribute "," } [ PackageClause "," ] { ImportDecl "," } { Declaration "," } . 3085 3109 ``` 3086 3110 3087 - ``` 3111 + ```cue 3088 3112 "Hello \(#place)!" 3089 3113 3090 3114 #place: "world" ··· 3109 3133 package level attributes or doc comments to a CUE file without a package 3110 3134 name. 3111 3135 3112 - ``` 3136 + ```cue 3113 3137 package math 3114 3138 ``` 3115 3139 ··· 3185 3209 3186 3210 <!-- TODO: a better example than lib/math:math, where the suffix is a no-op --> 3187 3211 3188 - ``` 3212 + ```cue untested 3189 3213 Import declaration Local name of Sin 3190 3214 3191 3215 import "lib/math" math.Sin