-- Copyright © 2026 Lingenic LLC. All rights reserved.
-- Licensed under the Lingenic Source-Available License v2.3.
-- Production use requires a separate license from Licensor.
-- See LICENSE.md and COPYRIGHT in the project root.
--
-------------------------------------------------------------------------------
-- Lingenic-Text
-- Formally Verified Unicode Text Processing Library
--
-- Normalization ghost specification (UAX #15).
--
-- CCC values, Quick Check values, Hangul syllable constants and
-- predicates, canonical ordering predicate. All expression functions
-- for solver unfolding.
-------------------------------------------------------------------------------
package Lingenic_Text.Normalization_Spec
with SPARK_Mode, Pure
is
---------------------------------------------------------------------------
-- Canonical_Combining_Class (0 .. 254)
-- 0 = starter, non-zero = non-starter (reorderable)
---------------------------------------------------------------------------
subtype CCC_Value is Natural range 0 .. 254;
function Is_Starter (CCC : CCC_Value) return Boolean
is (CCC = 0);
---------------------------------------------------------------------------
-- Quick Check values
---------------------------------------------------------------------------
type QC_Value is (QC_Yes, QC_No, QC_Maybe);
---------------------------------------------------------------------------
-- Normalization forms
---------------------------------------------------------------------------
type Normalization_Form is (NFD, NFC, NFKD, NFKC);
function Is_Canonical (Form : Normalization_Form) return Boolean
is (Form = NFD or Form = NFC);
function Is_Compose (Form : Normalization_Form) return Boolean
is (Form = NFC or Form = NFKC);
---------------------------------------------------------------------------
-- Hangul syllable constants (Unicode Standard, Section 3.12)
---------------------------------------------------------------------------
SBase : constant := 16#AC00#;
LBase : constant := 16#1100#;
VBase : constant := 16#1161#;
TBase : constant := 16#11A7#;
LCount : constant := 19;
VCount : constant := 21;
TCount : constant := 28;
NCount : constant := VCount * TCount; -- 588
SCount : constant := LCount * NCount; -- 11172
function Is_Hangul_Syllable (CP : Codepoint) return Boolean
is (CP >= SBase and then CP < SBase + SCount);
function Is_Hangul_LV (CP : Codepoint) return Boolean
is (Is_Hangul_Syllable (CP)
and then (CP - SBase) mod TCount = 0);
function Is_Hangul_L (CP : Codepoint) return Boolean
is (CP >= LBase and then CP < LBase + LCount);
function Is_Hangul_V (CP : Codepoint) return Boolean
is (CP >= VBase and then CP < VBase + VCount);
function Is_Hangul_T (CP : Codepoint) return Boolean
is (CP > TBase and then CP <= TBase + TCount - 1);
---------------------------------------------------------------------------
-- Canonical ordering
--
-- Within a segment of non-starters between two starters, CCC values
-- must be in non-decreasing order.
---------------------------------------------------------------------------
function CCC_Ordered (A, B : CCC_Value) return Boolean
is (A <= B);
end Lingenic_Text.Normalization_Spec;