Skip to content

Commit b11bae1

Browse files
committed
feat(interop): java.lang.Character complete — full-Unicode surface (47 methods + 70 fields)
Smell-audited: 1: finished-form over ASCII approximation — classification flipped to generated UCD 16.0.0 tables (the D-057 explicitly-out residual, now closed); getName is the one explicit-unsupported member (D-561), not a silent stub; behavior change corpus-locked (154 golden pairs, 0 DIFF). - gen_unicode_case.py also emits General_Category (categoryOf binary search, JVM getType byte values), Bidi_Class (getDirectionality), Bidi_Mirrored, simple-titlecase, contributory properties (PropList: Other_Uppercase/Lowercase/Alphabetic/ID_Start/ID_Continue, Ideographic), and decimal/numeric value tables into unicode_category.zig / unicode_case.zig. - charset.zig classification = the JVM formulas over those tables (isLetter excludes Nl; isUpperCase includes Other_Uppercase; JVM isWhitespace incl. 0x1C-0x1F; digit() takes any Nd + fullwidth letters; getNumericValue handles Nl/No + -2 fractional sentinel). - Character.zig: JVM char/int overload pairs (case folds echo the arg type; out-of-range int = the JVM unassigned answer, not an error); new statics compare/valueOf/isSpace/isSpaceChar/isTitleCase/toTitleCase/ isDefined/isMirrored/isIdeographic/isJavaIdentifier*/isUnicodeIdentifier*/ isIdentifierIgnorable/getType/getDirectionality/codePointBefore/ codePointCount/offsetByCodePoints/reverseBytes; getName raises explicit unsupported (D-561). - Static fields via a new StaticFieldValue .char arm: MIN/MAX_VALUE, radix/size/codepoint bounds, surrogate bounds, 31 category + 24 directionality constants (Character/TYPE skipped: no primitive Class, ADR-0059). - .char instance methods charValue/compareTo on the native descriptor; valueHash .char arm makes (hash \a) = (.hashCode \a) = (Character/hashCode \a) = 97 (clj parity). - compat_tiers.yaml entry refreshed; corpus test/diff/clj_corpus/ character.txt; e2e phase14_character_statics extended (ASCII-era header rewritten).
1 parent 479c783 commit b11bae1

14 files changed

Lines changed: 8262 additions & 177 deletions

File tree

‎.dev/debt.yaml‎

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,24 @@
2424
# md-table-align no longer pads it to ~800 KB of whitespace.
2525

2626
active:
27+
- id: "D-561"
28+
status: |-
29+
open (2026-07-15, Character/* completion cycle). `Character/getName` is
30+
the ONE java.lang.Character static not carried (explicit
31+
feature_not_supported raise; every other static method + field landed
32+
full-Unicode via the generated UCD tables — gen_unicode_case.py).
33+
getName needs the UnicodeData col-1 NAME table: raw ~1MB for ~40K
34+
non-algorithmic names; the JVM ships it word-indexed at ~90KB. DISCHARGE
35+
SHAPE: extend gen_unicode_case.py with a word-dictionary encoding
36+
(names → word-index sequences + algorithmic CJK/Hangul/Tangut ranges),
37+
decode in a new charset helper; JVM parity incl. nil for unassigned.
38+
Weigh the ~100-200KB binary cost against gap area II (Wasm/edge binary
39+
size) before landing — if the cost is judged not worth it, re-classify
40+
as an AD-NNN accepted divergence instead (the raise is explicit, not
41+
silent).
42+
category: "host-surface"
43+
barrier: "none — implementable any time; the open question is the binary-size trade (gap area II), not a technical blocker"
44+
last_reviewed: "2026-07-15"
2745
- id: "D-560"
2846
status: |-
2947
open (2026-07-13, ADR-0150 am1 accepted-cost row). The D-559 fix (the
@@ -2026,9 +2044,12 @@ standing:
20262044
FULL mapping + Final_Sigma (ß→SS, ΣΟΦΟΣ→σοφος); Character/* = SIMPLE
20272045
1:1 (ß stays); regex (?u)/(?iu) = simple-map fold orbit as a
20282046
compile-time alternation (σ~Σ~ς, ß≁"ss"). e2e phase14_unicode_case +
2029-
corpus unicode_case (14 golden). EXPLICITLY OUT (documented, not
2030-
silent): isUpper/isLower/isLetter stay ASCII (needs General_Category
2031-
data — a separate UCD file, add when a consumer pulls per ADR-0134);
2047+
corpus unicode_case (14 golden). The then-EXPLICITLY-OUT residual
2048+
(isUpper/isLower/isLetter ASCII-only pending a General_Category
2049+
consumer) CLOSED 2026-07-15: the Character/* completion cycle landed
2050+
the generated General_Category / contributory-property / bidi /
2051+
numeric tables and flipped charset.zig classification to the JVM
2052+
full-Unicode formulas (corpus clj_corpus/character.txt). Still out:
20322053
non-ASCII inside [...] under (?iu) stays a clean not-implemented
20332054
(byte-bitmap CharClass).
20342055
- **D-049** (structure, USER-OWNED) — ADR-0029 layout-lock F-NNN promotion;

‎.dev/handover.md‎

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,15 @@
3232
notarization) stays user-LOCKED.
3333
- **D-418 + D-559 agent/GC races DISCHARGED (2026-07-13)** — ADR-0150 am1;
3434
accepted cost = **D-560** (trigger-gated — do NOT self-select).
35+
- **java.lang.Character COMPLETE (2026-07-15, user-directed)** — full
36+
static surface (47 methods + 70 static fields) + char instance methods
37+
(charValue/compareTo) + `(hash \a)`=97 clj parity. Classification
38+
flipped ASCII→full-Unicode: gen_unicode_case.py now also generates
39+
General_Category/bidi/props/numeric/mirrored tables (UCD 16.0.0) into
40+
unicode_category.zig; charset.zig evaluates the JVM formulas. The one
41+
member out: `getName` (explicit unsupported, **D-561** — size-heavy
42+
name table vs gap II). Corpus `clj_corpus/character.txt` (154 golden)
43+
locks parity; e2e phase14_character_statics extended.
3544
- **First task on resume**: self-select from the live `active:` list,
3645
easiest-first (D-523's architecture/wasm-demo residual + D-522 drain 3
3746
landed 2026-07-14; D-430 is DISCHARGED — the prior pointer here was

‎data/compat_tiers.yaml‎

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,12 @@ tiers:
174174
phase: 14
175175
files:
176176
surface: runtime/java/lang/Character.zig
177-
methods: [isDigit, isLetter, isLetterOrDigit, isWhitespace, isUpperCase, isLowerCase, toUpperCase, toLowerCase, digit, getNumericValue, forDigit]
177+
# Full static surface (2026-07-15, full-Unicode via generated UCD
178+
# 16.0.0 tables; corpus test/diff/clj_corpus/character.txt locks
179+
# clj parity). getName is explicit-unsupported (D-561). Instance
180+
# methods on .char: charValue / compareTo (+ universal Object).
181+
methods: [isDigit, isLetter, isLetterOrDigit, isWhitespace, isUpperCase, isLowerCase, isTitleCase, isSpaceChar, isDefined, isMirrored, isIdeographic, isAlphabetic, isJavaIdentifierStart, isJavaIdentifierPart, isUnicodeIdentifierStart, isUnicodeIdentifierPart, isIdentifierIgnorable, toUpperCase, toLowerCase, toTitleCase, digit, getNumericValue, getType, getDirectionality, forDigit, codePointAt, codePointBefore, codePointCount, offsetByCodePoints, toChars, toString, charCount, isSurrogate, isHighSurrogate, isLowSurrogate, isISOControl, isBmpCodePoint, isValidCodePoint, isSupplementaryCodePoint, highSurrogate, lowSurrogate, toCodePoint, isSurrogatePair, hashCode, compare, valueOf, isSpace, reverseBytes]
182+
static_fields: [MIN_VALUE, MAX_VALUE, MIN_RADIX, MAX_RADIX, SIZE, BYTES, MIN_CODE_POINT, MAX_CODE_POINT, MIN_SUPPLEMENTARY_CODE_POINT, MIN_HIGH_SURROGATE, MAX_HIGH_SURROGATE, MIN_LOW_SURROGATE, MAX_LOW_SURROGATE, MIN_SURROGATE, MAX_SURROGATE, UNASSIGNED, UPPERCASE_LETTER, LOWERCASE_LETTER, TITLECASE_LETTER, MODIFIER_LETTER, OTHER_LETTER, NON_SPACING_MARK, ENCLOSING_MARK, COMBINING_SPACING_MARK, DECIMAL_DIGIT_NUMBER, LETTER_NUMBER, OTHER_NUMBER, SPACE_SEPARATOR, LINE_SEPARATOR, PARAGRAPH_SEPARATOR, CONTROL, FORMAT, PRIVATE_USE, SURROGATE, DASH_PUNCTUATION, START_PUNCTUATION, END_PUNCTUATION, CONNECTOR_PUNCTUATION, OTHER_PUNCTUATION, MATH_SYMBOL, CURRENCY_SYMBOL, MODIFIER_SYMBOL, OTHER_SYMBOL, INITIAL_QUOTE_PUNCTUATION, FINAL_QUOTE_PUNCTUATION, DIRECTIONALITY_UNDEFINED, DIRECTIONALITY_LEFT_TO_RIGHT, DIRECTIONALITY_RIGHT_TO_LEFT, DIRECTIONALITY_RIGHT_TO_LEFT_ARABIC, DIRECTIONALITY_EUROPEAN_NUMBER, DIRECTIONALITY_EUROPEAN_NUMBER_SEPARATOR, DIRECTIONALITY_EUROPEAN_NUMBER_TERMINATOR, DIRECTIONALITY_ARABIC_NUMBER, DIRECTIONALITY_COMMON_NUMBER_SEPARATOR, DIRECTIONALITY_NONSPACING_MARK, DIRECTIONALITY_BOUNDARY_NEUTRAL, DIRECTIONALITY_PARAGRAPH_SEPARATOR, DIRECTIONALITY_SEGMENT_SEPARATOR, DIRECTIONALITY_WHITESPACE, DIRECTIONALITY_OTHER_NEUTRALS, DIRECTIONALITY_LEFT_TO_RIGHT_EMBEDDING, DIRECTIONALITY_LEFT_TO_RIGHT_OVERRIDE, DIRECTIONALITY_RIGHT_TO_LEFT_EMBEDDING, DIRECTIONALITY_RIGHT_TO_LEFT_OVERRIDE, DIRECTIONALITY_POP_DIRECTIONAL_FORMAT, DIRECTIONALITY_LEFT_TO_RIGHT_ISOLATE, DIRECTIONALITY_RIGHT_TO_LEFT_ISOLATE, DIRECTIONALITY_FIRST_STRONG_ISOLATE, DIRECTIONALITY_POP_DIRECTIONAL_ISOLATE]
178183
clojure_peer_vars: []
179184
- fqn: java.lang.Math
180185
cljw_ns: cljw.java.lang.Math

0 commit comments

Comments
 (0)