fabric: UTF-8 decoder (DECODE-UTF8)

Punch list §25 item 4.3.6a complete.
capsules/fabric.4th blocks 4918-4920: UTF8-SEQ-LEN/UTF8-CONT? verbatim
from §27.6.2, DECODE-UTF8 dispatching to four UTF8-ASSEMBLE-N helpers
(1/2/3/4-byte). Factored into helpers after the single-word draft hit
mkcapsule's real 64-char x 16-line block limit. Verified live on
amd64: a 6-byte test buffer (ASCII + deg-sign + em-dash) decoded to
65/176/8212 across three sequential calls, exact match against
hand-computed codepoints, buffer fully consumed. Three-arch acceptance
boot clean, Stadium conservation unaffected.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Robert Allan James
2026-08-09 19:00:36 -04:00
co-authored by Claude Sonnet 5
parent 82e948afe9
commit 24d6b9e20e
13 changed files with 54530 additions and 111 deletions
+23 -20
View File
@@ -1,5 +1,5 @@
# Capsule Block Manifest — Auto-generated
<!-- Generated by mkcapsule --manifest 2026-08-09T22:51:12Z -->
<!-- Generated by mkcapsule --manifest 2026-08-09T22:59:10Z -->
<!-- DO NOT EDIT — re-run mkcapsule --manifest to refresh. -->
<!-- Hand-written justifications and immutability notes live -->
<!-- in MANIFEST.md alongside this auto-generated index. -->
@@ -13,7 +13,7 @@
| `common:msg.4th` | 4055 | `0xa99c5bcd3877f80e` |
| `doe-campaign.4th` | 4060, 4061, 4062, 4063, 4064, 4065 | `0x3d4549142d91ec20` |
| `doe.4th` | 2100, 2101, 2102, 2103, 2104, 2105, 2106, 2107 | `0xb6ecf5374e8ee77c` |
| `fabric.4th` | 4900, 4901, 4902, 4903, 4904, 4905, 4906, 4907, 4908, 4909, 4910, 4911, 4912, 4913, 4914, 4915, 4916, 4917 | `0x5fdcc45bbd8b1402` |
| `fabric.4th` | 4900, 4901, 4902, 4903, 4904, 4905, 4906, 4907, 4908, 4909, 4910, 4911, 4912, 4913, 4914, 4915, 4916, 4917, 4918, 4919, 4920 | `0x8da61551c0d1126a` |
| `hermes:init.4th` | 4100, 4101, 4102, 4103, 4104, 4105, 4106, 4107, 4108, 4109, 4114, 4115, 4116, 4117, 4118, 4119, 4120, 4121, 4142, 4143, 4144, 4145, 4146, 4147, 4148, 4149, 4150, 4151, 4152, 4153, 4154, 4155, 4156, 4157, 4158, 4159, 4175, 4176 | `0x85c7b311d1e5bf97` |
| `init-0.4th` | 2200, 2201 | `0xd0a9550baf786bb3` |
| `init-1.4th` | 4406, 4415, 4425, 4435 | `0x63e251adb0a03613` |
@@ -225,24 +225,27 @@
| 4842 | `init-l8-transition.4th` | `0xbcc1a81976f0a4c9` | ok |
| 4851 | `artemis:init.4th` | `0xc9e92cd18f4c7b49` | ok |
| 4852 | `artemis:init.4th` | `0xc9e92cd18f4c7b49` | ok |
| 4900 | `fabric.4th` | `0x5fdcc45bbd8b1402` | ok |
| 4901 | `fabric.4th` | `0x5fdcc45bbd8b1402` | ok |
| 4902 | `fabric.4th` | `0x5fdcc45bbd8b1402` | ok |
| 4903 | `fabric.4th` | `0x5fdcc45bbd8b1402` | ok |
| 4904 | `fabric.4th` | `0x5fdcc45bbd8b1402` | ok |
| 4905 | `fabric.4th` | `0x5fdcc45bbd8b1402` | ok |
| 4906 | `fabric.4th` | `0x5fdcc45bbd8b1402` | ok |
| 4907 | `fabric.4th` | `0x5fdcc45bbd8b1402` | ok |
| 4908 | `fabric.4th` | `0x5fdcc45bbd8b1402` | ok |
| 4909 | `fabric.4th` | `0x5fdcc45bbd8b1402` | ok |
| 4910 | `fabric.4th` | `0x5fdcc45bbd8b1402` | ok |
| 4911 | `fabric.4th` | `0x5fdcc45bbd8b1402` | ok |
| 4912 | `fabric.4th` | `0x5fdcc45bbd8b1402` | ok |
| 4913 | `fabric.4th` | `0x5fdcc45bbd8b1402` | ok |
| 4914 | `fabric.4th` | `0x5fdcc45bbd8b1402` | ok |
| 4915 | `fabric.4th` | `0x5fdcc45bbd8b1402` | ok |
| 4916 | `fabric.4th` | `0x5fdcc45bbd8b1402` | ok |
| 4917 | `fabric.4th` | `0x5fdcc45bbd8b1402` | ok |
| 4900 | `fabric.4th` | `0x8da61551c0d1126a` | ok |
| 4901 | `fabric.4th` | `0x8da61551c0d1126a` | ok |
| 4902 | `fabric.4th` | `0x8da61551c0d1126a` | ok |
| 4903 | `fabric.4th` | `0x8da61551c0d1126a` | ok |
| 4904 | `fabric.4th` | `0x8da61551c0d1126a` | ok |
| 4905 | `fabric.4th` | `0x8da61551c0d1126a` | ok |
| 4906 | `fabric.4th` | `0x8da61551c0d1126a` | ok |
| 4907 | `fabric.4th` | `0x8da61551c0d1126a` | ok |
| 4908 | `fabric.4th` | `0x8da61551c0d1126a` | ok |
| 4909 | `fabric.4th` | `0x8da61551c0d1126a` | ok |
| 4910 | `fabric.4th` | `0x8da61551c0d1126a` | ok |
| 4911 | `fabric.4th` | `0x8da61551c0d1126a` | ok |
| 4912 | `fabric.4th` | `0x8da61551c0d1126a` | ok |
| 4913 | `fabric.4th` | `0x8da61551c0d1126a` | ok |
| 4914 | `fabric.4th` | `0x8da61551c0d1126a` | ok |
| 4915 | `fabric.4th` | `0x8da61551c0d1126a` | ok |
| 4916 | `fabric.4th` | `0x8da61551c0d1126a` | ok |
| 4917 | `fabric.4th` | `0x8da61551c0d1126a` | ok |
| 4918 | `fabric.4th` | `0x8da61551c0d1126a` | ok |
| 4919 | `fabric.4th` | `0x8da61551c0d1126a` | ok |
| 4920 | `fabric.4th` | `0x8da61551c0d1126a` | ok |
## Conflicts
+42
View File
@@ -197,3 +197,45 @@ VARIABLE GX1 VARIABLE GY1 VARIABLE GX2 VARIABLE GY2
GX2 @ EM-X GY2 @ EM-Y 0
GCOLOR @
LINE ;
Block 4918
( UTF-8 lead-byte classification. Item 4.3.6a. )
: UTF8-SEQ-LEN ( lead -- n ) ( 0 = invalid lead byte )
DUP 128 < IF DROP 1 EXIT THEN
DUP 224 AND 192 = IF DROP 2 EXIT THEN
DUP 240 AND 224 = IF DROP 3 EXIT THEN
DUP 248 AND 240 = IF DROP 4 EXIT THEN
DROP 0 ;
: UTF8-CONT? ( byte -- flag ) ( true if 10xxxxxx )
192 AND 128 = ;
Block 4919
( UTF-8 codepoint assembly, per byte-length. Item 4.3.6a. )
VARIABLE UADDR VARIABLE ULEN VARIABLE ULEAD
VARIABLE USEQLEN VARIABLE UCP
: UTF8-ASSEMBLE-1 ( -- cp ) ULEAD @ ;
: UTF8-ASSEMBLE-2 ( -- cp )
ULEAD @ 31 AND 6 LSHIFT
UADDR @ 1+ C@ 63 AND OR ;
: UTF8-ASSEMBLE-3 ( -- cp )
ULEAD @ 15 AND 12 LSHIFT
UADDR @ 1+ C@ 63 AND 6 LSHIFT OR
UADDR @ 2 + C@ 63 AND OR ;
Block 4920
( UTF8-ASSEMBLE-4 + DECODE-UTF8 dispatch. Item 4.3.6a. )
: UTF8-ASSEMBLE-4 ( -- cp )
ULEAD @ 7 AND 18 LSHIFT
UADDR @ 1+ C@ 63 AND 12 LSHIFT OR
UADDR @ 2 + C@ 63 AND 6 LSHIFT OR
UADDR @ 3 + C@ 63 AND OR ;
: DECODE-UTF8 ( addr u -- codepoint addr' u' )
ULEN ! UADDR !
UADDR @ C@ ULEAD !
ULEAD @ UTF8-SEQ-LEN USEQLEN !
USEQLEN @ 1 = IF UTF8-ASSEMBLE-1 UCP ! ELSE
USEQLEN @ 2 = IF UTF8-ASSEMBLE-2 UCP ! ELSE
USEQLEN @ 3 = IF UTF8-ASSEMBLE-3 UCP ! ELSE
USEQLEN @ 4 = IF UTF8-ASSEMBLE-4 UCP ! ELSE
65533 UCP ! 1 USEQLEN ! THEN THEN THEN THEN
UCP @ UADDR @ USEQLEN @ + ULEN @ USEQLEN @ - ;