// uniesc_test — in-language behavior rows for \u / \U / \x escapes, // migrated from test/wcc/110_uniesc_run.c (task #12 proof-of-path). The // compiler-under-test compiles THIS file, so a miscompile of an escape // decode fails the assert in-language rather than via an external runner. // // Each row's literal is the exact escape form from the C source (not the // raw multibyte character): the feature under test is the escape-decode // path (ref/hare/hare/lex/lex.ha:347 lex_unicode + appendrune in // lex_string), distinct from source-UTF-8 decoding. A rune literal carries // the raw codepoint; a string literal UTF-8-encodes it into 1-4 bytes; \x // >=0x80 shares the codepoint path so it widens to its multibyte form. // // Carve-out: the C file's trailing .wwi round-trip case (an exported // wide-rune `def` re-serialized byte-exact) is an external-observer // residue and stays in C — not migrated here. package uniesc_test; import strings; // One rune row: the escape literal must decode to codepoint `cp`. type runecase = struct { lit: rune, cp: u32, }; // rune_u_2byte (é -> U+00E9) and rune_U_emoji (\U0001F600 -> U+1F600, // the >0xFFFF case that forced the int-cast spelling pre-#50). @test fn rune_escapes() void = { let rows: [2]runecase = [ runecase { lit = '\u00e9', cp = 233u32 }, runecase { lit = '\U0001F600', cp = 128512u32 }, ]; let i: i32 = 0; for (i < len(rows)) { assert((rows[i].lit: u32) == rows[i].cp); i += 1; }; }; // One string row: the escape literal must UTF-8-encode to `n` bytes // b0..b3 (unused tail bytes are 0 and guarded by the `n` check). type strcase = struct { lit: str, n: i32, b0: u8, b1: u8, b2: u8, b3: u8, }; // str_u_2byte (é -> C3 A9), str_u_3byte (€ -> E2 82 AC), // str_U_4byte (\U0001F600 -> F0 9F 98 80), str_x_widens (\xe9 -> C3 A9, // the >=0x80 \x byte that now widens to its 2-byte UTF-8 form). @test fn string_escapes() void = { let rows: [4]strcase = [ strcase { lit = "\u00e9", n = 2, b0 = 0xc3u8, b1 = 0xa9u8, b2 = 0u8, b3 = 0u8 }, strcase { lit = "\u20ac", n = 3, b0 = 0xe2u8, b1 = 0x82u8, b2 = 0xacu8, b3 = 0u8 }, strcase { lit = "\U0001F600", n = 4, b0 = 0xf0u8, b1 = 0x9fu8, b2 = 0x98u8, b3 = 0x80u8 }, strcase { lit = "\xe9", n = 2, b0 = 0xc3u8, b1 = 0xa9u8, b2 = 0u8, b3 = 0u8 }, ]; let i: i32 = 0; for (i < len(rows)) { let b: []u8 = strings.toutf8(rows[i].lit); assert(len(b) == rows[i].n); assert(b[0] == rows[i].b0); if (rows[i].n > 1) { assert(b[1] == rows[i].b1); }; if (rows[i].n > 2) { assert(b[2] == rows[i].b2); }; if (rows[i].n > 3) { assert(b[3] == rows[i].b3); }; i += 1; }; };