diff --git a/_includes/cheatsheet-binary.md b/_includes/cheatsheet-binary.md index 19197f0..50631ab 100644 --- a/_includes/cheatsheet-binary.md +++ b/_includes/cheatsheet-binary.md @@ -1,3 +1,57 @@ +For a value *V*, we write «*V*» for the binary encoding of *V*. + +{:.postcard-grammar.binarysyntax} +«`#f`» | = | `80` +«`#t`» | = | `81` + +{:.postcard-grammar.binarysyntax} +«`@`*W* *V*» | = | `85` «*W*» «*V*» +«`#!`*V*» | = | `86` «*V*» + +{:.postcard-grammar.binarysyntax} +«*V*» | = | `87``04` **binary32**(*V*) | if *V* ∈ Float +«*V*» | = | `87``08` **binary64**(*V*) | if *V* ∈ Double + +{:.postcard-grammar.binarysyntax} +«*V*» | = | `B0` **varint**(|**intbytes**(*V*)|) **intbytes**(*V*) | if *V* ∈ SignedInteger +«*V*» | = | `B1` **varint**(|**utf8**(*V*)|) **utf8**(*V*) | if *V* ∈ String +«*V*» | = | `B2` **varint**(|*V*|) *V* | if *V* ∈ ByteString +«*V*» | = | `B3` **varint**(|**utf8**(*V*)|) **utf8**(*V*) | if *V* ∈ Symbol + +{:.postcard-grammar.binarysyntax} +«`<`*L* *F*1 ... *F*m`>`» | = | `B4` «*L*» «*F*1» ... «*F*m» `84` +«`[`*X*1 ... *X*m`]`» | = | `B5` «*X*1» ... «*X*m» `84` +«`#{`*E*1 ... *E*m`}`» | = | `B6` «*E*1» ... «*E*m» `84` +«`{`*K*1`:`*V*1 ... *K*m`:`*V*m`}`» | = | `B7` «*K*1» «*V*1» ... «*K*m» «*V*m» `84` + +{:.postcard-grammar.binarysyntax} +**varint**(*n*) | = | *n* | if *n* < 128 +| | (*n* & 127) | 128 **varint**(*n* >> 7) | if *n* ≥ 128 + +{:.postcard-grammar.binarysyntax} +**intbytes**(*n*) | = | *the empty byte sequence* | if *n* = 0 +| | **signedBigEndian**(*n*) | otherwise +**signedBigEndian**(*n*) | = | *n* & 255 | if -128 ≤ *n* ≤ 127 +| | **signedBigEndian**(*n* >> 8) *n* & 255 | otherwise + +The functions **binary32**(*F*) and **binary64**(*D*) yield big-endian 4- and 8-byte +IEEE 754 binary representations of *F* and +*D*, respectively. + + + + diff --git a/_includes/cheatsheet-text.md b/_includes/cheatsheet-text.md new file mode 100644 index 0000000..6aaf710 --- /dev/null +++ b/_includes/cheatsheet-text.md @@ -0,0 +1,44 @@ +{:.postcard-grammar} +| *Document* | := | *Value* **ws** | +| *Value* | := | **ws** (*Record* | *Collection* | *Atom* | *Embedded* | *Annotated*) | +| *Collection* | := | *Sequence* | *Dictionary* | *Set* | +| *Atom* | := | *Boolean* | *String* | *ByteString* | *QuotedSymbol* | *Symbol* | *Number* | +| **ws** | := | (**space** | **tab** | **cr** | **lf** |`,`) | + +{:.postcard-grammar} +| *Record* | := | `<`*Value*+ **ws**`>` | +| *Sequence* | := | `[`*Value* **ws**`]` | +| *Dictionary* | := | `{` (*Value* **ws**`:`*Value*) **ws**`}` | +| *Set* | := | `#{`*Value* **ws**`}` | + +{:.postcard-grammar} +| *Boolean* | := | `#t`|`#f` | +| *String* | := | `"` (*unescaped* |`|`| (*escaped* |`\"`|`\u`*hex* *hex* *hex* *hex*)) `"` | +| *ByteString* | := | `#"`*binchar* `"`|`#x"` (**ws** | *hex* *hex*) **ws**`"`|`#[` (**ws** | *base64char*) **ws**`]` | +| *QuotedSymbol* | := | `|` (*unescaped* |`"`| (*escaped* |`\|`|`\u`*hex* *hex* *hex* *hex*)) `|` | +| *Symbol* | := | (`A`..`Z`|`a`..`z`|`0`..`9`| *sympunct* | *symuchar*)+ | +| *Number* | := | *Float* | *Double* | *SignedInteger* | +| *Float* | := | *flt* (`f`|`F`) |`#xf"` (**ws** *hex* *hex*)4 **ws**`"` | +| *Double* | := | *flt* |`#xd"` (**ws** *hex* *hex*)8 **ws**`"` | +| *SignedInteger* | := | *int* | + +{:.postcard-grammar} +| *Embedded* | := | `#!`*Value* | +| *Annotated* | := | *Annotation* *Value* | +| *Annotation* | := | `@`*Value* |`;`« any unicode scalar value except **cr** or **lf** » (**cr** | **lf**) | + +{:.postcard-grammar} +| *escaped* | := | `\\`|`\/`|`\b`|`\f`|`\n`|`\r`|`\t` | +| *unescaped* | := | « any unicode scalar value except `"`, `\`, or `|` » | +| *binchar* | := | *binunescaped* | (*escaped* |`\"`|`\x`*hex* *hex*) | +| *binunescaped* | := | « any unicode scalar value between 32 and 126, except `"` or `\` » | +| *base64char* | := | `A`..`Z`|`a`..`z`|`0`..`9`|`+`|`/`|`-`|`_`|`=` | +| *sympunct* | := | `~`|`!`|`$`|`%`|`^`|`&`|`*`|`?`|`_`|`=`|`+`|`-`|`/`|`.` | +| *symuchar* | := | « any scalar value greater than 127 whose Unicode category is Lu, Ll, Lt, Lm, Lo, Mn, Mc, Me, Nd, Nl, No, Pc, Pd, Po, Sc, Sm, Sk, So, or Co » | + +{:.postcard-grammar} +| *flt* | := | *int* ( *frac* *exp* | *frac* | *exp* ) | +| *int* | := | (`-`|`+`) (`0`..`9`)+ | +| *frac* | := | `.` (`0`..`9`)+ | +| *exp* | := | (`e`|`E`) (`-`|`+`) (`0`..`9`)+ | +| *hex* | := | `A`..`F`|`a`..`f`|`0`..`9` | diff --git a/_includes/intbytes.rkt b/_includes/intbytes.rkt new file mode 100644 index 0000000..84be8c2 --- /dev/null +++ b/_includes/intbytes.rkt @@ -0,0 +1,129 @@ +#lang racket + +(define (base-bytes v) + (define byte-count (cond [(zero? v) 0] + [else (define raw-bit-count (+ (integer-length v) 1)) + (quotient (+ raw-bit-count 7) 8)])) + (for/list [(shift (in-range (* byte-count 8) 0 -8))] + (bitwise-bit-field v (- shift 8) shift))) + +(define (mod n d) (modulo n d)) ;; sign equal to sign of d +(define (div n d) (/ (- n (mod n d)) d)) ;; sign equal to sign of n, or zero + +;;--------------------------------------------------------------------------- +;; One +;; +;; (define (intbytes* v) +;; (cond [(zero? v) '()] +;; [(= v -1) '()] +;; [else (append (intbytes* (div v 256)) (list (mod v 256)))])) +;; +;; (define (intbytes v) +;; (define bs (intbytes* v)) +;; (define looks-negative (and (pair? bs) (>= (car bs) 128))) +;; (if (xor (negative? v) looks-negative) +;; (cons (if (negative? v) 255 0) bs) +;; bs)) + +;;--------------------------------------------------------------------------- +;; Two +;; +;; (define (intbytes** v) +;; (cond [(zero? v) '()] +;; [else (append (intbytes** (quotient v 256)) (list (remainder v 256)))])) +;; +;; (define (intbytes* v) +;; (define bs (intbytes** v)) +;; (if (and (pair? bs) (>= (car bs) 128)) +;; (cons 0 bs) +;; bs)) +;; +;; (define (intbytes v) +;; (if (negative? v) +;; (map (lambda (n) (- 255 n)) (intbytes* (- (+ v 1)))) +;; (intbytes* v))) + +;;--------------------------------------------------------------------------- +;; Three +;; +;; (define (intbytes+ v) +;; (cond [(>= v 128) (append (intbytes+ (div v 256)) (list (mod v 256)))] +;; [else (list (mod v 256))])) +;; +;; (define (intbytes- v) +;; (cond [(< v -128) (append (intbytes- (div v 256)) (list (mod v 256)))] +;; [else (list (mod v 256))])) +;; +;; (define (intbytes v) +;; (cond [(negative? v) (intbytes- v)] +;; [(zero? v) '()] +;; [(positive? v) (intbytes+ v)])) + +;;--------------------------------------------------------------------------- +;; Four +;; +;; (define (intbytes* v) +;; (append (if (<= -128 v 127) +;; '() +;; (intbytes* (div v 256))) +;; (list (mod v 256)))) +;; +;; (define (intbytes v) +;; (if (zero? v) +;; '() +;; (intbytes* v))) + +;;--------------------------------------------------------------------------- +;; Five +;; +;; (define (intbytes* v) +;; (if (<= -128 v 127) +;; (list (mod v 256)) +;; (append (intbytes* (div v 256)) (list (mod v 256))))) +;; +;; (define (intbytes v) +;; (if (zero? v) +;; '() +;; (intbytes* v))) + +;;--------------------------------------------------------------------------- +;; Six + +(define (intbytes* v) + (if (<= -128 v 127) + (list (bitwise-and v 255)) + (append (intbytes* (arithmetic-shift v -8)) (list (bitwise-and v 255))))) + +(define (intbytes v) + (if (zero? v) + '() + (intbytes* v))) + +(define cases `( + (-257 (#xfe #xff)) + (-256 (#xff #x00)) + (-255 (#xff #x01)) + (-129 (#xff #x7f)) + (-128 (#x80)) + (-127 (#x81)) + (-2 (#xfe)) + (-1 (#xff)) + (0 ()) + (1 (#x01)) + (127 (#x7f)) + (128 (#x00 #x80)) + (255 (#x00 #xff)) + (256 (#x01 #x00)) + (32767 (#x7f #xff)) + (32768 (#x00 #x80 #x00)) + (65535 (#x00 #xff #xff)) + (65536 (#x01 #x00 #x00)) + )) + +(module+ test + (require rackunit) + (for [(c (in-list cases))] + (match-define (list input output) c) + (writeln (list input output (base-bytes input) (intbytes input))) + (check-equal? output (base-bytes input)) + (check-equal? output (intbytes input)))) diff --git a/_includes/text-examples.md b/_includes/text-examples.md new file mode 100644 index 0000000..45bad9b --- /dev/null +++ b/_includes/text-examples.md @@ -0,0 +1,17 @@ +Here are a few example values, written using the [text +syntax](https://preserves.dev/preserves-text.html): + + Boolean : #t #f + Float : 1.0f 10.4e3f -100.6f + Double : 1.0 10.4e3 -100.6 + Integer : 1 0 -100 + String : "Hello, world!\n" + ByteString : #"bin\x00str\x00" #[YmluAHN0cgA] #x"62696e0073747200" + Symbol : hello-world |hello world| = ! hello? || ... + Record :