From 7b81a4fdfd72a2f044b825ef91a932a44887d6b9 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 19 Oct 2026 10:52:17 +0700 Subject: [PATCH 1/8] t27o: direct tests for the lexing and reader helpers of rust_convert.t27 -- byte classes, quoted/raw/num ends, op2/op3, item_end, is_tail, skip_arm, the reader predicates and refusals (Closes #10825) Tests only; no non-test line changes. Co-Authored-By: Claude Sonnet 5.5 --- specs/tools/t27o/rust_convert.t27 | 379 ++++++++++++++++++++++++++++++ 1 file changed, 379 insertions(+) diff --git a/specs/tools/t27o/rust_convert.t27 b/specs/tools/t27o/rust_convert.t27 index a6258ab3d2..fd70b8860e 100644 --- a/specs/tools/t27o/rust_convert.t27 +++ b/specs/tools/t27o/rust_convert.t27 @@ -10591,3 +10591,382 @@ test negative_control_an_unsuffixed_literal_does_not_inherit_the_previous_names_ assert(out_is(n, &out, 0, "// t27o: refused fn g (line 1): method `saturating_sub` at line 1\n\nfn g(v: []const u8) -> usize {\n}\n\n")); assert(st[NOK] == 0); } + +// ---------------------------------------------------------------- direct tests (#10825) +// One test per helper family, each helper named and its predicates asserted both ways, with the edges: +// empty text, a token at the last byte, the end of the buffer. + +test byte_classes_hold_on_both_sides_of_each_range { + assert(is_space(B_SPACE)); + assert(is_space(B_TAB)); + assert(is_space(B_NL)); + assert(is_space(B_CR)); + assert(!is_space(0)); + assert(!is_space(11)); + assert(!is_space(12)); + assert(!is_space(B_LOWER_A)); + assert(!is_space(160)); + assert(is_upper(B_UPPER_A)); + assert(is_upper(B_UPPER_Z)); + assert(!is_upper(B_UPPER_A - 1)); + assert(!is_upper(B_UPPER_Z + 1)); + assert(!is_upper(B_LOWER_A)); + assert(!is_upper(B_UNDERSCORE)); + assert(is_alpha(B_LOWER_A)); + assert(is_alpha(B_LOWER_Z)); + assert(is_alpha(B_UPPER_A)); + assert(is_alpha(B_UPPER_Z)); + assert(is_alpha(B_UNDERSCORE)); + assert(!is_alpha(B_LOWER_A - 1)); + assert(!is_alpha(B_LOWER_Z + 1)); + assert(!is_alpha(B_ZERO)); + assert(!is_alpha(B_SPACE)); + assert(!is_alpha(B_DEL)); + assert(is_digit(B_ZERO)); + assert(is_digit(B_NINE)); + assert(!is_digit(B_ZERO - 1)); + assert(!is_digit(B_NINE + 1)); + assert(!is_digit(B_LOWER_A)); + assert(is_word(B_LOWER_A)); + assert(is_word(B_UPPER_Z)); + assert(is_word(B_UNDERSCORE)); + assert(is_word(B_ZERO)); + assert(is_word(B_NINE)); + assert(!is_word(B_DOT)); + assert(!is_word(B_SPACE)); + assert(!is_word(B_COLON)); + assert(!is_word(B_APOS)); +} + +test brackets_open_and_close_are_the_three_kinds { + assert(is_open(B_LPAREN)); + assert(is_open(B_LBRACKET)); + assert(is_open(B_LBRACE)); + assert(!is_open(B_RPAREN)); + assert(!is_open(B_RBRACKET)); + assert(!is_open(B_RBRACE)); + assert(!is_open(B_LT)); + assert(!is_open(B_SPACE)); + assert(is_close(B_RPAREN)); + assert(is_close(B_RBRACKET)); + assert(is_close(B_RBRACE)); + assert(!is_close(B_LPAREN)); + assert(!is_close(B_LBRACKET)); + assert(!is_close(B_LBRACE)); + assert(!is_close(B_GT)); + assert(!is_close(B_SPACE)); +} + +test hex_value_reads_a_digit_in_either_case_and_gives_zero_for_the_rest { + assert(hex_value(B_ZERO) == 0); + assert(hex_value(B_NINE) == 9); + assert(hex_value(B_LOWER_A) == 10); + assert(hex_value(B_LOWER_F) == 15); + assert(hex_value(B_UPPER_A) == 10); + assert(hex_value(B_UPPER_A + 5) == 15); + assert(hex_value(B_LOWER_F + 1) == 0); + assert(hex_value(B_UPPER_A + 6) == 0); + assert(hex_value(B_LOWER_Z) == 0); + assert(hex_value(B_SLASH) == 0); + assert(hex_value(B_COLON) == 0); + assert(hex_value(B_SPACE) == 0); + assert(hex_value(0) == 0); +} + +test quoted_end_runs_past_the_matching_quote_and_skips_escapes { + assert(quoted_end("\"ab\" x", 0) == 4); + assert(quoted_end("\"\" x", 0) == 2); + assert(quoted_end("\"a\\\"b\" x", 0) == 6); + assert(quoted_end("\"a\\\\\" x", 0) == 5); + assert(quoted_end("'x' y", 0) == 3); + assert(quoted_end("'\\'' y", 0) == 4); + assert(quoted_end("x \"ab\"", 2) == 6); + assert(quoted_end("\"abc", 0) == 4); + assert(quoted_end("\"a\\", 0) == 3); + assert(quoted_end("\"", 0) == 1); + assert(quoted_end("'", 0) == 1); +} + +test raw_end_matches_the_hashes_of_the_opening { + assert(raw_end("r\"ab\" x", 0) == 5); + assert(raw_end("r#\"a\"b\"# x", 0) == 8); + assert(raw_end("r##\"a\"#b\"## x", 0) == 11); + assert(raw_end("x r\"a\"", 2) == 6); + assert(raw_end("r\"\"", 0) == 3); + assert(raw_end("r#x", 0) == 1); + assert(raw_end("rx", 0) == 1); + assert(raw_end("r", 0) == 1); + assert(raw_end("r#", 0) == 1); + assert(raw_end("r\"abc", 0) == 5); + assert(raw_end("r#\"a\"", 0) == 5); + assert(raw_end("r#\"a\"#", 0) == 6); +} + +test num_end_takes_digits_fraction_exponent_and_suffix { + assert(num_end("0xFFu8;", 0) == 6); + assert(num_end("0b101 x", 0) == 5); + assert(num_end("0o77;", 0) == 4); + assert(num_end("0x", 0) == 2); + assert(num_end("0", 0) == 1); + assert(num_end("7", 0) == 1); + assert(num_end("12_345u32 ", 0) == 9); + assert(num_end("1.5e-3f64 x", 0) == 9); + assert(num_end("3.14f32", 0) == 7); + assert(num_end("1..2", 0) == 1); + assert(num_end("1.", 0) == 1); + assert(num_end("1.x", 0) == 1); + assert(num_end("1e5", 0) == 3); + assert(num_end("7E3", 0) == 3); + assert(num_end("0e1", 0) == 3); + assert(num_end("1e", 0) == 2); + assert(num_end("1e+", 0) == 2); + assert(num_end("1e+x", 0) == 2); + assert(num_end("a 42;", 2) == 4); + assert(num_end("a 42", 2) == 4); +} + +test op2_and_op3_name_the_compound_operators_and_refuse_the_look_alikes { + assert(op2("==", 0)); + assert(op2("!=", 0)); + assert(op2("<=", 0)); + assert(op2(">=", 0)); + assert(op2("+=", 0)); + assert(op2("-=", 0)); + assert(op2("*=", 0)); + assert(op2("/=", 0)); + assert(op2("%=", 0)); + assert(op2("^=", 0)); + assert(op2("&=", 0)); + assert(op2("|=", 0)); + assert(op2("::", 0)); + assert(op2("->", 0)); + assert(op2("=>", 0)); + assert(op2("&&", 0)); + assert(op2("||", 0)); + assert(op2("<<", 0)); + assert(op2(">>", 0)); + assert(op2("..", 0)); + assert(op2("a ==", 2)); + assert(!op2(".=", 0)); + assert(!op2(":=", 0)); + assert(!op2("~=", 0)); + assert(!op2("!!", 0)); + assert(!op2("**", 0)); + assert(!op2("++", 0)); + assert(!op2("--", 0)); + assert(!op2("//", 0)); + assert(!op2("<>", 0)); + assert(!op2("<-", 0)); + assert(!op2("&|", 0)); + assert(!op2(":a", 0)); + assert(!op2("a=", 0)); + assert(op3("<<=", 0)); + assert(op3(">>=", 0)); + assert(op3("..=", 0)); + assert(op3("...", 0)); + assert(op3("x <<=", 2)); + assert(!op3("<=>", 0)); + assert(!op3("<<<", 0)); + assert(!op3(">>>", 0)); + assert(!op3("..x", 0)); + assert(!op3("<==", 0)); + assert(!op3("&&=", 0)); + assert(!op3("==.", 0)); +} + +test same_at_and_tok_is_compare_a_range_and_a_token { + assert(same_at("abcab", 0, 2, 3)); + assert(!same_at("abcab", 0, 2, 2)); + assert(!same_at("abcab", 0, 3, 3)); + assert(same_at("abcab", 3, 5, 0)); + assert(same_at("abcab", 2, 2, 0)); + assert(same_at("abcab", 4, 2, 0)); + assert(!same_at("abcab", 0, 1, 10)); + assert(!same_at("abcab", 0, 1, 5)); + assert(same_at("abcab", 0, 5, 0)); + assert(tok_is("fn f", 0, "fn")); + assert(!tok_is("fn f", 0, "f")); + assert(!tok_is("fn f", 0, "fn f")); + assert(tok_is("fn f", 3, "f")); + assert(!tok_is("fn f", 3, "fn")); + assert(!tok_is("fn f", 0, "")); + assert(tok_is("a == b", 2, "==")); + assert(!tok_is("a == b", 2, "=")); + assert(tok_is("a::b", 1, "::")); + assert(!tok_is("", 0, "x")); + assert(!tok_is("ab", 2, "b")); +} + +test item_end_stops_past_the_body_or_the_semicolon_and_before_an_enclosing_closer { + assert(item_end("fn f() { 1 } fn g() {}", 0) == 12); + assert(item_end("use a::b; fn x() {}", 0) == 9); + assert(item_end("use a::{b, c}; x", 0) == 14); + assert(item_end("const A: u32 = 5; B", 0) == 17); + assert(item_end("const fn f() {} x", 0) == 15); + assert(item_end("static X: [u8; 2] = [1, 2]; y", 0) == 27); + assert(item_end("type R = Result<(), ()>; y", 0) == 24); + assert(item_end("struct A { x: u8 } y", 0) == 18); + assert(item_end("struct A; y", 0) == 9); + assert(item_end("mod m { fn f() {} } y", 0) == 19); + assert(item_end("impl A { const X: u8 = 1; } y", 0) == 27); + assert(item_end("fn f() { const X: u8 = 1; } y", 0) == 27); + assert(item_end("x }", 0) == 2); + assert(item_end("}", 0) == 0); + assert(item_end("fn f(", 0) == 5); + assert(item_end("fn f() {", 0) == 8); + assert(item_end("", 0) == 0); + assert(item_end("a fn f() {} z", 2) == 11); + assert(skip_item("fn f() {} // c\n fn g() {}", 0) == 17); + assert(skip_item("fn f() {}", 0) == 9); + assert(skip_item("use a; /* c */ b", 0) == 15); + assert(skip_item("", 0) == 0); +} + +test is_tail_is_true_only_for_the_last_statement_of_a_block { + assert(is_tail("a + b }", 0)); + assert(is_tail("f(a, b) }", 0)); + assert(is_tail("{ a } }", 0)); + assert(!is_tail("a + b; c }", 0)); + assert(!is_tail("let x = 5; }", 0)); + assert(!is_tail("x", 0)); + assert(!is_tail("", 0)); + assert(is_tail("if a { b } else { c } }", 0)); + assert(is_tail("if a { b } else if d { e } else { c } }", 0)); + assert(!is_tail("if a { b } c }", 0)); + assert(!is_tail("if a { b } else { c } d }", 0)); + assert(is_tail("while x { y } }", 0)); + assert(is_tail("for i in 0..3 { x; } }", 0)); + assert(is_tail("loop { x } }", 0)); + assert(is_tail("match x { _ => 1 } }", 0)); + assert(is_tail("unsafe { x } }", 0)); + assert(!is_tail("while x { y }", 0)); + assert(!is_tail("match x { _ => 1 } ;", 0)); + assert(!is_tail("if a { b } else { c }; }", 0)); + assert(is_tail("a; b }", 3)); + assert(!is_tail("a; b; }", 3)); +} + +test skip_arm_ends_past_the_body_and_its_comma { + assert(skip_arm("1 => a, 2 => b", 0) == 8); + assert(skip_arm("1 => a, 2 => b", 8) == 14); + assert(skip_arm("1 | 2 => f(a, b), _ => c", 0) == 18); + assert(skip_arm("1 => { a } 2 => b", 0) == 11); + assert(skip_arm("1 => { a }, 2 => b", 0) == 12); + assert(skip_arm("1 => { a, b }, 2", 0) == 15); + assert(skip_arm("_ => c }", 0) == 7); + assert(skip_arm("_ => c", 0) == 6); + assert(skip_arm("x", 0) == 1); + assert(skip_arm("", 0) == 0); + assert(skip_arm("a =>", 0) == 4); + assert(skip_arm("a => ", 0) == 5); +} + +test count_fns_counts_named_fn_items_in_the_range { + assert(count_fns("fn a() {} fn b() {}", 0, 19) == 2); + assert(count_fns("fn a() {} fn b() {}", 0, 10) == 1); + assert(count_fns("fn a() {} fn b() {}", 0, 11) == 2); + assert(count_fns("fn a() {} fn b() {}", 10, 19) == 1); + assert(count_fns("fn a() {} fn b() {}", 11, 19) == 0); + assert(count_fns("fn a() {} fn b() {}", 5, 5) == 0); + assert(count_fns("fn(u8) -> u8", 0, 12) == 0); + assert(count_fns("fn 9", 0, 4) == 0); + assert(count_fns("fnord a", 0, 7) == 0); + assert(count_fns("pub fn _x() {}", 0, 14) == 1); + assert(count_fns("fn", 0, 2) == 0); + assert(count_fns("fn ", 0, 3) == 0); + assert(count_fns("", 0, 0) == 0); + assert(count_fns("impl A { fn m(&self) {} fn n() {} }", 0, 35) == 2); +} + +test the_reader_predicates_bad_live_head_at_and_peek_is { + assert(!bad(0)); + assert(bad(1)); + assert(bad(R_NOTYPE)); + assert(live("ab", 0, 0)); + assert(live("ab", 1, 0)); + assert(!live("ab", 2, 0)); + assert(!live("ab", 0, 1)); + assert(!live("ab", 5, 0)); + assert(!live("", 0, 0)); + assert(head("ab", 0) == B_LOWER_A); + assert(head("ab", 1) == B_LOWER_B); + assert(head("ab", 2) == 0); + assert(head("ab", 99) == 0); + assert(head("", 0) == 0); + assert(at("fn f", 0, "fn")); + assert(!at("fn f", 0, "f")); + assert(!at("fn f", 3, "fn")); + assert(at("fn f", 3, "f")); + assert(!at("fn f", 4, "f")); + assert(peek_is("fn f", 0, "f")); + assert(!peek_is("fn f", 0, "fn")); + assert(peek_is("a // c\n == b", 0, "==")); + assert(!peek_is("fn", 0, "x")); + assert(!peek_is("f", 0, "f")); + assert(peek_is("a b c", 2, "c")); +} + +test step_and_take_move_past_a_token_and_the_blanks_after_it { + var st : [64]usize = [0] ** 64; + st[P] = 0; + step("fn f", &st); + assert(st[P] == 4); + step("fn f", &st); + assert(st[P] == 5); + step("fn f", &st); + assert(st[P] == 5); + st[P] = 0; + step("a // c\n b", &st); + assert(st[P] == 8); + st[P] = 0; + assert(take("fn f", &st, "fn")); + assert(st[P] == 3); + assert(!take("fn f", &st, "fn")); + assert(st[P] == 3); + assert(!take("fn f", &st, "g")); + assert(st[P] == 3); + assert(take("fn f", &st, "f")); + assert(st[P] == 4); + assert(!take("fn f", &st, "f")); + assert(st[P] == 4); + assert(st[ERR] == 0); +} + +test refuse_keeps_the_first_reason_and_want_refuses_a_missing_token { + var st : [64]usize = [0] ** 64; + refuse(&st, R_TYPE, 7, 3, 5); + assert(st[ERR] == R_TYPE); + assert(st[AT] == 7); + assert(st[NLO] == 3); + assert(st[NHI] == 5); + refuse(&st, R_MACRO, 9, 1, 2); + assert(st[ERR] == R_TYPE); + assert(st[AT] == 7); + assert(st[NLO] == 3); + assert(st[NHI] == 5); + var s2 : [64]usize = [0] ** 64; + s2[P] = 3; + refuse_here("fn foo()", &s2, R_METHOD); + assert(s2[ERR] == R_METHOD); + assert(s2[AT] == 3); + assert(s2[NLO] == 3); + assert(s2[NHI] == 6); + refuse_here("fn foo()", &s2, R_CLOSURE); + assert(s2[ERR] == R_METHOD); + var s3 : [64]usize = [0] ** 64; + want("fn f", &s3, "fn"); + assert(s3[ERR] == 0); + assert(s3[P] == 3); + want("fn f", &s3, "g"); + assert(s3[ERR] == R_SYNTAX); + assert(s3[AT] == 3); + assert(s3[NLO] == 3); + assert(s3[NHI] == 4); + assert(s3[P] == 3); + var s4 : [64]usize = [0] ** 64; + s4[P] = 8; + refuse_here("fn foo()", &s4, R_SYNTAX); + assert(s4[ERR] == R_SYNTAX); + assert(s4[AT] == 8); + assert(s4[NHI] == 8); +} From be05e6201b67adf9f81e9693e17da89c7708064e Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 19 Oct 2026 11:02:44 +0700 Subject: [PATCH 2/8] t27o: direct tests for the name table, the declaration index and deps of rust_convert.t27, and a known-defect test for the static mut name (Closes #10825) Tests only; no non-test line changes. The static mut naming defect is #10829. Co-Authored-By: Claude Sonnet 5.5 --- specs/tools/t27o/rust_convert.t27 | 805 ++++++++++++++++++++++++++++++ 1 file changed, 805 insertions(+) diff --git a/specs/tools/t27o/rust_convert.t27 b/specs/tools/t27o/rust_convert.t27 index fd70b8860e..d832d783fc 100644 --- a/specs/tools/t27o/rust_convert.t27 +++ b/specs/tools/t27o/rust_convert.t27 @@ -10970,3 +10970,808 @@ test refuse_keeps_the_first_reason_and_want_refuses_a_missing_token { assert(s4[AT] == 8); assert(s4[NHI] == 8); } + +// ---------------------------------------------------------------- direct tests: the name table, the index + +test same_text_and_named_read_the_name_table_by_kind { + var st : [128]usize = [0] ** 128; + const src : str = "foo bar foo"; + assert(same_text(src, 0, 3, 8, 11)); + assert(!same_text(src, 0, 3, 4, 7)); + assert(!same_text(src, 0, 3, 8, 10)); + assert(!same_text(src, 3, 0, 0, 3)); + assert(!same_text(src, 0, 3, 11, 8)); + assert(same_text(src, 2, 2, 5, 5)); + assert(same_text(src, 3, 4, 7, 8)); + assert(!named(src, &st, K_FN, 0, 3)); + assert(st[HIT] == 0); + add_name(src, &st, K_FN, 0, 3, 0, 0); + assert(st[NNAMES] == 1); + assert(named(src, &st, K_FN, 8, 11)); + assert(st[HIT] == NAMES); + assert(!named(src, &st, K_ITEM, 8, 11)); + assert(st[HIT] == 0); + assert(!named(src, &st, K_FN, 4, 7)); + assert(st[HIT] == 0); + assert(!named(src, &st, K_FN, 0, 2)); + add_name(src, &st, K_ITEM, 4, 7, 0, 0); + assert(st[NNAMES] == 2); + assert(named(src, &st, K_ITEM, 4, 7)); + assert(st[HIT] == NAMES + NAME_SLOTS); + assert(!named(src, &st, K_FN, 4, 7)); + assert(named(src, &st, K_FN, 0, 3)); + assert(st[HIT] == NAMES); +} + +test strloc_in_matches_a_string_local_only_inside_the_body_of_its_fn { + const src : str = "name,name,name"; + var st : [128]usize = [0] ** 128; + add_name(src, &st, K_STRLOC, 0, 4, 5, 10); + assert(!strloc_in(src, &st, 0, 4)); + assert(st[HIT] == 0); + assert(strloc_in(src, &st, 5, 9)); + assert(st[HIT] == NAMES); + assert(!strloc_in(src, &st, 10, 14)); + assert(st[HIT] == 0); + assert(!strloc_in(src, &st, 5, 8)); + var wide : [128]usize = [0] ** 128; + add_name(src, &wide, K_STRLOC, 0, 4, 5, 11); + assert(strloc_in(src, &wide, 10, 14)); + assert(wide[HIT] == NAMES); + assert(!strloc_in(src, &wide, 11, 14)); + var other : [128]usize = [0] ** 128; + add_name(src, &other, K_FN, 0, 4, 5, 10); + assert(!strloc_in(src, &other, 5, 9)); + assert(other[HIT] == 0); + var none : [128]usize = [0] ** 128; + assert(!strloc_in(src, &none, 5, 9)); +} + +test ix_hash_wraps_at_one_million_and_three { + assert(ix_hash("a", 0, 1) == 98); + assert(ix_hash("ab", 0, 2) == 3137); + assert(ix_hash("foo", 0, 3) == 102567); + assert(ix_hash("xfoo", 1, 4) == 102567); + assert(ix_hash("struct", 0, 6) == 565757); + assert(ix_hash("abcdefghij", 0, 10) == 168724); + assert(ix_hash("abcdefghijklmnopqrstuvwxyz", 0, 26) == 52409); + assert(ix_hash("", 0, 0) == 0); + assert(ix_hash("abc", 2, 2) == 0); + assert(ix_hash("abc", 3, 1) == 0); + assert(ix_hash("ab", 0, 2) != ix_hash("ba", 0, 2)); +} + +test ix_link_appends_an_entry_after_the_last_one_of_its_chain { + var st : [64]usize = [0] ** 64; + ix_link(&st, 10, 20); + assert(st[10] == 20); + assert(st[23] == 0); + ix_link(&st, 10, 30); + assert(st[10] == 20); + assert(st[23] == 30); + assert(st[33] == 0); + ix_link(&st, 10, 40); + assert(st[10] == 20); + assert(st[23] == 30); + assert(st[33] == 40); + assert(st[43] == 0); + ix_link(&st, 11, 50); + assert(st[11] == 50); + assert(st[10] == 20); + assert(st[53] == 0); +} + +test ix_enter_takes_four_slots_from_the_top_and_stops_at_half_the_free_room { + var st : [200]usize = [0] ** 200; + st[IXTOP] = 200; + assert(ix_enter(&st, 100, 5, 9, 77)); + assert(st[IXTOP] == 196); + assert(st[196] == 5); + assert(st[197] == 9); + assert(st[198] == 77); + assert(st[199] == 0); + assert(st[100] == 196); + assert(ix_enter(&st, 100, 6, 10, 78)); + assert(st[IXTOP] == 192); + assert(st[192] == 6); + assert(st[193] == 10); + assert(st[194] == 78); + assert(st[195] == 0); + assert(st[199] == 192); + assert(st[100] == 196); + var n : usize = 2; + while (ix_enter(&st, 100, 1, 2, 3)) { n = n + 1; } + assert(n == 17); + assert(st[IXTOP] == 132); + assert(st[131] == 0); + assert(st[130] == 0); + assert(st[129] == 0); + assert(st[128] == 0); + assert(!ix_enter(&st, 100, 1, 2, 3)); + assert(st[IXTOP] == 132); +} + +test ix_add_enters_under_the_bucket_of_the_name_and_skips_an_empty_name { + var st : [200]usize = [0] ** 200; + const src : str = "foo"; + st[IXB] = 60; + st[IXBN] = 4; + st[IXTOP] = 200; + assert(ix_add(src, &st, IXK_FN, 0, 3, 7)); + assert(st[67] == 196); + assert(st[196] == 0); + assert(st[197] == 3); + assert(st[198] == 7); + assert(st[IXTOP] == 196); + assert(ix_add(src, &st, IXK_ITEM, 0, 3, 9)); + assert(st[63] == 192); + assert(ix_add(src, &st, IXK_LET, 0, 3, 11)); + assert(st[71] == 188); + assert(st[IXTOP] == 188); + assert(ix_add(src, &st, IXK_FN, 2, 2, 0)); + assert(ix_add(src, &st, IXK_FN, 3, 1, 0)); + assert(st[IXTOP] == 188); + st[IXTOP] = 100; + assert(!ix_add(src, &st, IXK_FN, 0, 3, 7)); + assert(st[IXTOP] == 100); + assert(ix_add(src, &st, IXK_FN, 3, 3, 7)); +} + +test ix_first_and_ix_next_walk_the_entries_of_one_name_in_file_order { + var st : [1024]usize = [0] ** 1024; + const src : str = "fn f() {}\nstruct S { x: u8 }\nfn f(a: u8) {}\nfn g() {}\nconst K: u8 = 1;\nfn main() { let r = S { x: 1 }; let k = 5; }\n"; + index_decls(src, &st); + assert(st[IXON] == 1); + const f1 : usize = ix_first(src, &st, IXK_FN, 3, 4); + assert(f1 != 0); + assert(st[IXHIT] == f1); + assert(st[f1] == 3); + assert(st[f1 + 1] == 4); + assert(st[f1 + 2] == 0); + const f2 : usize = ix_next(src, &st, f1, 3, 4); + assert(f2 != 0); + assert(f2 != f1); + assert(st[IXHIT] == f2); + assert(st[f2 + 2] == 29); + assert(ix_next(src, &st, f2, 3, 4) == 0); + assert(st[IXHIT] == 0); + const g : usize = ix_first(src, &st, IXK_FN, 47, 48); + assert(g != 0); + assert(st[g + 2] == 44); + assert(ix_next(src, &st, g, 47, 48) == 0); + const s : usize = ix_first(src, &st, IXK_ITEM, 17, 18); + assert(s != 0); + assert(st[s + 2] == 10); + assert(ix_first(src, &st, IXK_FN, 17, 18) == 0); + assert(st[IXHIT] == 0); + const k : usize = ix_first(src, &st, IXK_ITEM, 60, 61); + assert(k != 0); + assert(st[k + 2] == 54); + const r : usize = ix_first(src, &st, IXK_LET, 87, 88); + assert(r != 0); + assert(st[r + 2] == 83); + assert(ix_first(src, &st, IXK_LET, 107, 108) == 0); + st[IXHIT] = 99; + assert(ix_first(src, &st, IXK_FN, 5, 5) == 0); + assert(st[IXHIT] == 0); + st[IXHIT] = 99; + assert(ix_first(src, &st, IXK_FN, 4, 3) == 0); + assert(st[IXHIT] == 0); +} + +test item_kw_names_the_seven_item_keywords { + assert(item_kw("struct", 0, 6)); + assert(item_kw("enum", 0, 4)); + assert(item_kw("type", 0, 4)); + assert(item_kw("trait", 0, 5)); + assert(item_kw("union", 0, 5)); + assert(item_kw("const", 0, 5)); + assert(item_kw("static", 0, 6)); + assert(item_kw("a const b", 2, 7)); + assert(!item_kw("fn", 0, 2)); + assert(!item_kw("let", 0, 3)); + assert(!item_kw("impl", 0, 4)); + assert(!item_kw("mod", 0, 3)); + assert(!item_kw("structs", 0, 7)); + assert(!item_kw("Struct", 0, 6)); + assert(!item_kw("const", 0, 4)); + assert(!item_kw("a const b", 0, 1)); +} + +test let_at_names_the_type_a_let_binds_its_name_to { + assert(let_at("let r = Type::new(1);", 0, 4, 5) == 8); + assert(let_at("let r = Type { x: 1 };", 0, 4, 5) == 8); + assert(let_at("let r = Type(1);", 0, 4, 5) == 8); + assert(let_at("let r : Type = x;", 0, 4, 5) == 8); + assert(let_at("let r: Type = x;", 0, 4, 5) == 7); + assert(let_at("let r: &mut Type = x;", 0, 4, 5) == 12); + assert(let_at("let mut r = Type::new();", 0, 8, 9) == 12); + assert(let_at("let r = &mut Type { };", 0, 4, 5) == 13); + assert(let_at("let r: u32 = 5;", 0, 4, 5) == 15); + assert(let_at("let r = 5;", 0, 4, 5) == 10); + assert(let_at("let r = foo::new();", 0, 4, 5) == 19); + assert(let_at("let r: Type = x;", 0, 4, 5) == 20); + assert(let_at("let r = Type::new(); x", 0, 21, 22) == 22); + assert(let_at("let r = Type::new();", 4, 4, 5) == 20); + assert(let_at("let rr = Type::new();", 0, 4, 5) == 21); +} + +test record_fns_enters_each_fn_of_the_range_as_a_member_of_its_owner { + const src : str = "T fn a() {} fn b() {} fn (x) {}"; + var st : [128]usize = [0] ** 128; + record_fns(src, &st, 2, src.len, 0, 1); + assert(st[NNAMES] == 2); + assert(st[NAMES] == 5); + assert(st[NAMES + 1] == 6); + assert(st[NAMES + 2] == 0); + assert(st[NAMES + 3] == 1); + assert(st[NAMES + 4] == K_MEMBER); + assert(st[NAMES + NAME_SLOTS] == 15); + assert(st[NAMES + NAME_SLOTS + 4] == K_MEMBER); + assert(named(src, &st, K_MEMBER, 5, 6)); + assert(named(src, &st, K_MEMBER, 15, 16)); + assert(!named(src, &st, K_FN, 5, 6)); + var cut : [128]usize = [0] ** 128; + record_fns(src, &cut, 2, 12, 0, 1); + assert(cut[NNAMES] == 1); + var late : [128]usize = [0] ** 128; + record_fns(src, &late, 2, 13, 0, 1); + assert(late[NNAMES] == 2); + var empty : [128]usize = [0] ** 128; + record_fns(src, &empty, 5, 5, 0, 1); + assert(empty[NNAMES] == 0); +} + +test use_names_adds_the_leaves_a_use_brings_from_another_file { + var a : [128]usize = [0] ** 128; + const s1 : str = "use a::b::{c, d as e};"; + use_names(s1, &a, 0, s1.len); + assert(a[NNAMES] == 2); + assert(named(s1, &a, K_EXT, 11, 12)); + assert(named(s1, &a, K_EXT, 19, 20)); + assert(!named(s1, &a, K_EXT, 14, 15)); + assert(!named(s1, &a, K_EXT, 7, 8)); + assert(!named(s1, &a, K_EXT, 4, 5)); + var b : [128]usize = [0] ** 128; + const s2 : str = "use super::x;"; + use_names(s2, &b, 0, s2.len); + assert(b[NNAMES] == 0); + var c : [128]usize = [0] ** 128; + const s3 : str = "use self::x;"; + use_names(s3, &c, 0, s3.len); + assert(c[NNAMES] == 0); + var d : [128]usize = [0] ** 128; + const s4 : str = "use ::std::io;"; + use_names(s4, &d, 0, s4.len); + assert(d[NNAMES] == 1); + assert(named(s4, &d, K_EXT, 11, 13)); + var e : [128]usize = [0] ** 128; + const s5 : str = "use a::Result;"; + use_names(s5, &e, 0, s5.len); + assert(e[NNAMES] == 0); + var f : [128]usize = [0] ** 128; + const s6 : str = "use a::{self, crate, b};"; + use_names(s6, &f, 0, s6.len); + assert(f[NNAMES] == 1); + assert(named(s6, &f, K_EXT, 21, 22)); + var g : [128]usize = [0] ** 128; + const s7 : str = "use a::*;"; + use_names(s7, &g, 0, s7.len); + assert(g[NNAMES] == 0); + var h : [128]usize = [0] ** 128; + const s8 : str = "use a::{b, c};"; + use_names(s8, &h, 0, 11); + assert(h[NNAMES] == 1); + assert(named(s8, &h, K_EXT, 8, 9)); + assert(!named(s8, &h, K_EXT, 11, 12)); + var i : [128]usize = [0] ** 128; + const s9 : str = "use a::b;"; + use_names(s9, &i, 0, s9.len); + assert(i[NNAMES] == 1); + assert(named(s9, &i, K_EXT, 7, 8)); +} + +test declared_names_answer_the_same_with_the_index_on_and_off { + var st : [1024]usize = [0] ** 1024; + const src : str = "struct Pt { x: u32 }\nenum Mode { A }\nconst K: u32 = 1;\nstatic mut S: u8 = 0;\ntype R = u8;\ntrait Tr {}\nunion Un { a: u8 }\nfn foo() {}\nfn bar(a: u8) -> u8 { a }\nimpl Pt { fn m(&self) {} }\nGhost pt\nSelf Option Some None Result Ok Err String Vec\n"; + index_decls(src, &st); + assert(st[IXON] == 1); + const names : [15]str = ["Pt", "Mode", "K", "R", "Tr", "Un", "Self", "Option", "Some", "None", "Result", "Ok", "Err", "String", "Vec"]; + const im : usize = find_tok(src, 0, "impl"); + const lb : usize = find_at(src, im, B_LBRACE); + const m : usize = find_tok(src, lb + 1, "m"); + var mode : usize = 0; + while (mode < 2) { + st[IXON] = 1 - mode; + var i : usize = 0; + while (i < 15) { + const a : usize = find_tok(src, 0, names[i]); + assert(a < src.len); + assert(declared_type(src, &st, a, tok_end(src, a))); + i = i + 1; + } + const ghost : usize = find_tok(src, 0, "Ghost"); + const pt : usize = find_tok(src, 0, "pt"); + const foo : usize = find_tok(src, 0, "foo"); + const bar : usize = find_tok(src, 0, "bar"); + const u32p : usize = find_tok(src, 0, "u32"); + const k : usize = find_tok(src, 0, "K"); + assert(!declared_type(src, &st, ghost, tok_end(src, ghost))); + assert(!declared_type(src, &st, pt, tok_end(src, pt))); + assert(!declared_type(src, &st, foo, tok_end(src, foo))); + assert(!declared_type(src, &st, bar, tok_end(src, bar))); + assert(!declared_type(src, &st, u32p, tok_end(src, u32p))); + assert(!declared_type(src, &st, k, k + 0)); + assert(!declared_type(src, &st, find_tok(src, 0, "Pt"), find_tok(src, 0, "Pt") + 1)); + assert(declared_fn(src, &st, foo, tok_end(src, foo))); + assert(declared_fn(src, &st, bar, tok_end(src, bar))); + assert(declared_fn(src, &st, m, tok_end(src, m))); + assert(!declared_fn(src, &st, foo, foo + 2)); + assert(!declared_fn(src, &st, ghost, tok_end(src, ghost))); + assert(!declared_fn(src, &st, k, tok_end(src, k))); + assert(!declared_fn(src, &st, find_tok(src, 0, "Pt"), tok_end(src, find_tok(src, 0, "Pt")))); + mode = mode + 1; + } +} + +test item_named_checks_the_name_right_after_an_item_keyword { + const src : str = "struct Pt {}\nenum Mode { A }\nconst K: u32 = 1;\ntype R = u8;\nfn foo() {}\n"; + const pt : usize = find_tok(src, 0, "Pt"); + const mode : usize = find_tok(src, 0, "Mode"); + const k : usize = find_tok(src, 0, "K"); + const r : usize = find_tok(src, 0, "R"); + const foo : usize = find_tok(src, 0, "foo"); + assert(item_named(src, find_tok(src, 0, "struct"), pt, tok_end(src, pt))); + assert(item_named(src, find_tok(src, 0, "enum"), mode, tok_end(src, mode))); + assert(item_named(src, find_tok(src, 0, "const"), k, tok_end(src, k))); + assert(item_named(src, find_tok(src, 0, "type"), r, tok_end(src, r))); + assert(!item_named(src, find_tok(src, 0, "struct"), mode, tok_end(src, mode))); + assert(!item_named(src, find_tok(src, 0, "enum"), pt, tok_end(src, pt))); + assert(!item_named(src, find_tok(src, 0, "struct"), pt, pt + 1)); + assert(!item_named(src, find_tok(src, 0, "fn"), foo, tok_end(src, foo))); + assert(!item_named(src, pt, pt, tok_end(src, pt))); + assert(!item_named(src, k, k, tok_end(src, k))); +} + +test known_defect_a_static_mut_is_named_mut_by_item_named_and_const_item { + // #10829: the name after `static mut` is stepped over. item_named takes the `mut` for the name, and a + // refused static mut is recorded as `mut`, so every later fn that spells `mut` is refused with it. + // When that is fixed these asserts flip (item_named true for S, NOK 1). + const src : str = "static mut S: u8 = 0;\n"; + const s : usize = find_tok(src, 0, "S"); + const mt : usize = find_tok(src, 0, "mut"); + assert(!item_named(src, 0, s, tok_end(src, s))); + assert(item_named(src, 0, mt, tok_end(src, mt))); + var out : [512]u8 = undefined; + var st : [1024]usize = [0] ** 1024; + const src2 : str = "static mut COUNT: u32 = 0;\nfn sum(n: u32) -> u32 { let mut t = 0u32; t }"; + body(src2, &out, &st); + assert(st[NFN] == 1); + assert(st[NOK] == 0); + const m2 : usize = find_tok(src2, 0, "mut"); + const c2 : usize = find_tok(src2, 0, "COUNT"); + assert(named(src2, &st, K_ITEM, m2, m2 + 3)); + assert(!named(src2, &st, K_ITEM, c2, c2 + 5)); +} + +test call_keyword_names_the_keywords_that_may_stand_before_a_paren { + assert(call_keyword("if", 0, 2)); + assert(call_keyword("while", 0, 5)); + assert(call_keyword("match", 0, 5)); + assert(call_keyword("return", 0, 6)); + assert(call_keyword("in", 0, 2)); + assert(call_keyword("as", 0, 2)); + assert(call_keyword("let", 0, 3)); + assert(call_keyword("mut", 0, 3)); + assert(call_keyword("move", 0, 4)); + assert(call_keyword("ref", 0, 3)); + assert(call_keyword("break", 0, 5)); + assert(call_keyword("continue", 0, 8)); + assert(call_keyword("where", 0, 5)); + assert(call_keyword("for", 0, 3)); + assert(call_keyword("x for y", 2, 5)); + assert(!call_keyword("fn", 0, 2)); + assert(!call_keyword("loop", 0, 4)); + assert(!call_keyword("else", 0, 4)); + assert(!call_keyword("iff", 0, 3)); + assert(!call_keyword("foo", 0, 3)); + assert(!call_keyword("if", 0, 1)); + assert(!call_keyword("", 0, 0)); +} + +test names_self_and_says_self_ty_find_the_two_spellings_in_a_range { + assert(names_self("fn m(&self) {}", 0, 14)); + assert(names_self("a self b", 0, 8)); + assert(names_self("a self b", 2, 6)); + assert(!names_self("a self b", 0, 2)); + assert(!names_self("a self b", 7, 8)); + assert(!names_self("fn m() { selfish }", 0, 18)); + assert(!names_self("fn m() { Self }", 0, 15)); + assert(!names_self("", 0, 0)); + assert(says_self_ty("fn m() -> Self {}", 0, 17)); + assert(says_self_ty("a Self b", 2, 6)); + assert(!says_self_ty("a Self b", 0, 2)); + assert(!says_self_ty("fn m(&self) {}", 0, 14)); + assert(!says_self_ty("fn m() -> SelfX {}", 0, 18)); + assert(!says_self_ty("", 0, 0)); +} + +test deps_refuses_a_call_of_a_refused_fn_and_an_undeclared_one { + var a : [128]usize = [0] ** 128; + const s1 : str = "foo(1)"; + add_name(s1, &a, K_FN, 0, 3, 0, 0); + deps(s1, &a, 0, s1.len); + assert(a[ERR] == R_DEPENDS); + assert(a[AT] == 0); + assert(a[NLO] == 0); + assert(a[NHI] == 3); + var b : [128]usize = [0] ** 128; + const s2 : str = "foo + 1"; + add_name(s2, &b, K_FN, 0, 3, 0, 0); + deps(s2, &b, 0, s2.len); + assert(b[ERR] == 0); + var c : [128]usize = [0] ** 128; + deps(s1, &c, 0, s1.len); + assert(c[ERR] == R_UNDECL); + assert(c[AT] == 0); + assert(c[NHI] == 3); + var d : [128]usize = [0] ** 128; + const s3 : str = "fn foo() {} fn bar() { foo(1); }"; + deps(s3, &d, 12, s3.len); + assert(d[ERR] == 0); + var e : [128]usize = [0] ** 128; + const s4 : str = "foo(1) bar(2)"; + add_name(s4, &e, K_FN, 0, 3, 0, 0); + add_name(s4, &e, K_FN, 7, 10, 0, 0); + deps(s4, &e, 7, s4.len); + assert(e[ERR] == R_DEPENDS); + assert(e[AT] == 7); + var f : [128]usize = [0] ** 128; + add_name(s4, &f, K_FN, 0, 3, 0, 0); + deps(s4, &f, 0, s4.len); + assert(f[ERR] == R_DEPENDS); + assert(f[AT] == 0); + var g : [128]usize = [0] ** 128; + add_name(s4, &g, K_FN, 0, 3, 0, 0); + g[ERR] = R_TYPE; + deps(s4, &g, 0, s4.len); + assert(g[ERR] == R_TYPE); + assert(g[AT] == 0); + assert(g[NHI] == 0); + var h : [128]usize = [0] ** 128; + const s5 : str = "if (x) { } return (1) match (a) { }"; + deps(s5, &h, 0, s5.len); + assert(h[ERR] == 0); +} + +test deps_reads_a_name_after_a_dot_or_a_path_as_a_member_not_a_free_fn { + var a : [128]usize = [0] ** 128; + const s1 : str = "x.foo(1)"; + add_name(s1, &a, K_FN, 2, 5, 0, 0); + deps(s1, &a, 0, s1.len); + assert(a[ERR] == 0); + var b : [128]usize = [0] ** 128; + add_name(s1, &b, K_MEMBER, 2, 5, 0, 0); + deps(s1, &b, 0, s1.len); + assert(b[ERR] == R_DEPENDS); + assert(b[AT] == 2); + assert(b[NHI] == 5); + var c : [128]usize = [0] ** 128; + const s2 : str = "struct T {} fn f() { T::go(1); }"; + add_name(s2, &c, K_MEMBER, 24, 26, 7, 8); + deps(s2, &c, 12, s2.len); + assert(c[ERR] == R_DEPENDS); + assert(c[AT] == 24); + var d : [128]usize = [0] ** 128; + add_name(s2, &d, K_MEMBER, 24, 26, 3, 4); + deps(s2, &d, 12, s2.len); + assert(d[ERR] == 0); + var e : [128]usize = [0] ** 128; + const s3 : str = "Self::go(1)"; + add_name(s3, &e, K_MEMBER, 6, 8, 0, 4); + deps(s3, &e, 0, s3.len); + assert(e[ERR] == R_DEPENDS); + assert(e[AT] == 6); + var f : [128]usize = [0] ** 128; + add_name(s2, &f, K_FN, 24, 26, 0, 0); + deps(s2, &f, 12, s2.len); + assert(f[ERR] == 0); + var g : [128]usize = [0] ** 128; + const s4 : str = "super::foo(1)"; + add_name(s4, &g, K_FN, 7, 10, 0, 0); + deps(s4, &g, 0, s4.len); + assert(g[ERR] == R_DEPENDS); + assert(g[AT] == 7); + var h : [128]usize = [0] ** 128; + const s5 : str = "self::foo(1)"; + add_name(s5, &h, K_FN, 6, 9, 0, 0); + deps(s5, &h, 0, s5.len); + assert(h[ERR] == R_DEPENDS); + assert(h[AT] == 6); + var i : [128]usize = [0] ** 128; + const s6 : str = "crate::foo(1)"; + add_name(s6, &i, K_FN, 7, 10, 0, 0); + deps(s6, &i, 0, s6.len); + assert(i[ERR] == R_DEPENDS); + var j : [128]usize = [0] ** 128; + const s7 : str = "other::foo(1)"; + add_name(s7, &j, K_FN, 7, 10, 0, 0); + deps(s7, &j, 0, s7.len); + assert(j[ERR] == 0); +} + +test deps_refuses_a_use_of_a_refused_type_a_foreign_name_and_an_undeclared_one { + var a : [128]usize = [0] ** 128; + const s1 : str = "fn f(a: Ghost) {}"; + add_name(s1, &a, K_ITEM, 8, 13, 0, 0); + deps(s1, &a, 0, s1.len); + assert(a[ERR] == R_DEPENDS); + assert(a[AT] == 8); + assert(a[NHI] == 13); + var b : [128]usize = [0] ** 128; + const s2 : str = "struct Ghost {}"; + add_name(s2, &b, K_ITEM, 7, 12, 0, 0); + deps(s2, &b, 0, s2.len); + assert(b[ERR] == 0); + var c : [128]usize = [0] ** 128; + const s3 : str = "struct Ghost { Ghost: u8 }"; + add_name(s3, &c, K_ITEM, 7, 12, 0, 0); + deps(s3, &c, 0, s3.len); + assert(c[ERR] == 0); + var d : [128]usize = [0] ** 128; + const s4 : str = "struct Ghost {} fn f(g: Ghost) {}"; + add_name(s4, &d, K_ITEM, 7, 12, 0, 0); + deps(s4, &d, 0, s4.len); + assert(d[ERR] == R_DEPENDS); + assert(d[AT] == 24); + var e : [128]usize = [0] ** 128; + const s5 : str = "fn f() -> Ext { Ext::new() }"; + add_name(s5, &e, K_EXT, 10, 13, 0, 0); + deps(s5, &e, 0, s5.len); + assert(e[ERR] == R_EXTERNAL); + assert(e[AT] == 10); + var f : [128]usize = [0] ** 128; + const s6 : str = "x::Ext"; + add_name(s6, &f, K_EXT, 3, 6, 0, 0); + deps(s6, &f, 0, s6.len); + assert(f[ERR] == 0); + var g : [128]usize = [0] ** 128; + const s7 : str = "fn f() { Ghost; }"; + deps(s7, &g, 0, s7.len); + assert(g[ERR] == R_UNDECL); + assert(g[AT] == 9); + assert(g[NHI] == 14); + var h : [128]usize = [0] ** 128; + const s8 : str = "struct Ghost {} fn f() { Ghost; }"; + deps(s8, &h, 0, s8.len); + assert(h[ERR] == 0); + var i : [128]usize = [0] ** 128; + const s9 : str = "x.Ghost y::Ghost"; + deps(s9, &i, 0, s9.len); + assert(i[ERR] == 0); +} + +test deps_keeps_a_member_of_a_refused_impl_type_when_it_names_neither_self_nor_the_type { + var a : [128]usize = [0] ** 128; + const s1 : str = "struct Ghost {} impl Ghost { fn m(&self) { } }"; + add_name(s1, &a, K_ITEM, 7, 12, 0, 0); + a[ILO] = 21; + a[IHI] = 26; + deps(s1, &a, 29, s1.len); + assert(a[ERR] == R_DEPENDS); + assert(a[AT] == 35); + var b : [128]usize = [0] ** 128; + const s2 : str = "struct Ghost {} impl Ghost { fn s(a: u8) -> u8 { a } }"; + add_name(s2, &b, K_ITEM, 7, 12, 0, 0); + b[ILO] = 21; + b[IHI] = 26; + deps(s2, &b, 29, s2.len); + assert(b[ERR] == 0); + var c : [128]usize = [0] ** 128; + const s3 : str = "struct Ghost {} impl Ghost { fn t() -> Self { } }"; + add_name(s3, &c, K_ITEM, 7, 12, 0, 0); + c[ILO] = 21; + c[IHI] = 26; + deps(s3, &c, 29, s3.len); + assert(c[ERR] == R_DEPENDS); + assert(c[AT] == 39); + var d : [128]usize = [0] ** 128; + const s4 : str = "struct Ghost {} impl Ghost { fn u() { Self::s(); } fn s() {} }"; + add_name(s4, &d, K_ITEM, 7, 12, 0, 0); + d[ILO] = 21; + d[IHI] = 26; + deps(s4, &d, 29, s4.len); + assert(d[ERR] == 0); + var e : [128]usize = [0] ** 128; + const s5 : str = "struct Ghost {} impl Ghost { fn m(&self) { } }"; + e[ILO] = 21; + e[IHI] = 26; + deps(s5, &e, 29, s5.len); + assert(e[ERR] == 0); + var f : [128]usize = [0] ** 128; + const s6 : str = "impl Ghost { fn m(&self) {} }"; + f[ILO] = 5; + f[IHI] = 10; + deps(s6, &f, 13, s6.len); + assert(f[ERR] == R_UNDECL); + assert(f[AT] == 5); + assert(f[NLO] == 5); + assert(f[NHI] == 10); +} + +test kind_at_reads_the_receiver_of_the_fn_at_a_token { + const src : str = "go\nimpl A { fn go(&mut self) {} }\nimpl B { fn go(x: u8) {} }\nimpl C { fn go(self) {} }\nimpl D { fn go(&self) {} fn go(&mut self) {} }\n"; + assert(kind_at(src, 12, 33, 0, 2) == 2); + assert(kind_at(src, 43, 60, 0, 2) == 0); + assert(kind_at(src, 70, 86, 0, 2) == 1); + assert(kind_at(src, 96, 133, 0, 2) == 1); + assert(kind_at(src, 112, 133, 0, 2) == 2); + assert(kind_at(src, 12, 17, 0, 2) == 0); + assert(kind_at(src, 12, 18, 0, 2) == 0); + assert(kind_at(src, 12, 19, 0, 2) == 2); + assert(kind_at(src, 12, 33, 8, 10) == 0); + assert(kind_at(src, 12, 33, 0, 4) == 0); + assert(kind_at(src, 15, 33, 0, 2) == 0); + assert(kind_at(src, 10, 33, 0, 2) == 0); + assert(kind_at("go fn go(mut self) {}", 3, 21, 0, 2) == 1); + assert(kind_at("go fn go(&'a self) {}", 3, 21, 0, 2) == 1); + assert(kind_at("go fn go(&'a mut self) {}", 3, 25, 0, 2) == 2); + assert(kind_at("go fn go() {}", 3, 13, 0, 2) == 0); + assert(kind_at("go fn go {}", 3, 11, 0, 2) == 0); +} + +test method_kind_and_impl_owner_at_find_the_impl_that_owns_a_method_with_the_index_on_and_off { + var st : [1024]usize = [0] ** 1024; + const src : str = "go\nimpl A { fn go(&mut self) {} }\nimpl B { fn go(x: u8) {} }\nimpl C { fn go(self) {} }\nimpl D { fn go(&self) {} fn go(&mut self) {} }\nimpl T for X { fn go(&self) {} }\nimpl Y { fn go(&self) {} }\n"; + index_decls(src, &st); + assert(st[IXON] == 1); + const ib : usize = find_tok(src, 34, "impl"); + const ic : usize = find_tok(src, 61, "impl"); + const id : usize = find_tok(src, 87, "impl"); + assert(ib == 34); + assert(ic == 61); + assert(id == 87); + const it : usize = find_tok(src, id + 1, "impl"); + const iy : usize = find_tok(src, it + 1, "impl"); + var mode : usize = 0; + while (mode < 2) { + st[IXON] = 1 - mode; + assert(method_kind(src, &st, 10, 33, 0, 2) == 2); + assert(method_kind(src, &st, 3, 34, 0, 2) == 2); + assert(method_kind(src, &st, 41, 60, 0, 2) == 0); + assert(method_kind(src, &st, 68, 86, 0, 2) == 1); + assert(method_kind(src, &st, 94, 133, 0, 2) == 1); + assert(method_kind(src, &st, 112, 133, 0, 2) == 2); + assert(method_kind(src, &st, 94, 112, 0, 2) == 1); + assert(method_kind(src, &st, 0, 3, 0, 2) == 0); + assert(method_kind(src, &st, 33, 43, 0, 2) == 0); + assert(method_kind(src, &st, 70, 70, 0, 2) == 0); + assert(method_kind(src, &st, 70, 86, 0, 2) == 1); + assert(method_kind(src, &st, 71, 86, 0, 2) == 0); + assert(method_kind(src, &st, 0, src.len, 8, 9) == 0); + st[OLO] = 99; + st[OHI] = 98; + st[OKIND] = 97; + assert(impl_owner_at(src, &st, 3, 0, 0, 2, 0, 0, 0)); + assert(st[OLO] == 8); + assert(st[OHI] == 9); + assert(st[OKIND] == 2); + st[OLO] = 99; + st[OHI] = 98; + st[OKIND] = 97; + assert(!impl_owner_at(src, &st, ib, 0, 0, 2, 0, 0, 0)); + assert(st[OLO] == 99); + assert(st[OHI] == 98); + assert(st[OKIND] == 97); + assert(impl_owner_at(src, &st, ic, 0, 0, 2, 0, 0, 0)); + assert(st[OLO] == 66); + assert(st[OKIND] == 1); + assert(impl_owner_at(src, &st, id, 0, 0, 2, 0, 0, 0)); + assert(st[OLO] == 92); + assert(st[OHI] == 93); + assert(st[OKIND] == 1); + assert(!impl_owner_at(src, &st, 0, 0, 0, 2, 0, 0, 0)); + assert(!impl_owner_at(src, &st, 12, 0, 0, 2, 0, 0, 0)); + assert(!impl_owner_at(src, &st, it, 0, 0, 2, 0, 0, 0)); + assert(!impl_owner_at(src, &st, iy, 0, 0, 2, 0, 0, 0)); + assert(impl_owner_at(src, &st, 3, 0, 0, 2, 8, 9, 0)); + assert(!impl_owner_at(src, &st, ic, 0, 0, 2, 8, 9, 0)); + assert(impl_owner_at(src, &st, ic, 1, 0, 2, 8, 9, 0)); + assert(impl_owner_at(src, &st, ic, 0, 0, 2, 66, 67, 0)); + assert(impl_owner_at(src, &st, 3, 0, 0, 2, 0, 0, 33)); + assert(!impl_owner_at(src, &st, 3, 0, 0, 2, 0, 0, 13)); + mode = mode + 1; + } +} + +test owners_agree_holds_with_the_index_and_fails_when_an_impl_entry_is_wrong { + var st : [1024]usize = [0] ** 1024; + const src : str = "go\nimpl A { fn go(&mut self) {} }\nimpl B { fn go(x: u8) {} }\nimpl C { fn go(self) {} }\nimpl D { fn go(&self) {} fn go(&mut self) {} }\n"; + index_decls(src, &st); + assert(st[IXON] == 1); + assert(owners_agree(src, &st, 0, 2, 0, 0)); + assert(owners_agree(src, &st, 0, 2, 8, 9)); + assert(owners_agree(src, &st, 0, 2, 39, 40)); + assert(owners_agree(src, &st, 0, 2, 66, 67)); + assert(owners_agree(src, &st, 0, 2, 92, 93)); + assert(owners_agree(src, &st, 8, 9, 0, 0)); + assert(st[IXON] == 1); + assert(all_names_agree(src, &st)); + var s : usize = st[st[IXB] + IXK_KINDS * st[IXBN]]; + assert(s != 0); + while (s != 0) { + st[s + 1] = 0; + s = st[s + 3]; + } + assert(!owners_agree(src, &st, 0, 2, 0, 0)); + assert(!all_names_agree(src, &st)); + assert(st[IXON] == 1); +} + +test const_hit_const_of_and_the_fn_lookups_read_a_declaration_at_a_token { + const src : str = "const K: u32 = 1;\nstatic mut S : u8 = 0;\nconst fn cf() -> u8 { 1 }\nconst NC = 2;\nfn foo(a: u8) -> u32 { 1 }\nfn bar() {}\nfn baz(a: (u8, u8)) -> Result<(), String> { Ok(()) }\n"; + const k : usize = find_tok(src, 0, "K"); + const kq : usize = find_tok(src, 0, "const"); + const sq : usize = find_tok(src, 0, "static"); + const s : usize = find_tok(src, 0, "S"); + const cf : usize = find_tok(src, 0, "cf"); + const nc : usize = find_tok(src, 0, "NC"); + const foo : usize = find_tok(src, 0, "foo"); + const bar : usize = find_tok(src, 0, "bar"); + const baz : usize = find_tok(src, 0, "baz"); + assert(const_hit(src, kq, k, tok_end(src, k))); + assert(const_hit(src, sq, s, tok_end(src, s))); + assert(!const_hit(src, kq, s, tok_end(src, s))); + assert(!const_hit(src, kq, k, k + 0)); + const cq : usize = find_tok(src, sq + 1, "const"); + const nq : usize = find_tok(src, cq + 1, "const"); + assert(cq == cf - 9); + assert(nq == nc - 6); + assert(!const_hit(src, cq, cf, tok_end(src, cf))); + assert(!const_hit(src, cq, find_tok(src, cq, "fn"), find_tok(src, cq, "fn") + 2)); + assert(!const_hit(src, nq, nc, tok_end(src, nc))); + assert(!const_hit(src, k, k, tok_end(src, k))); + assert(!const_hit(src, foo - 3, foo, tok_end(src, foo))); + assert(word_is(src, const_of(src, kq), tok_end(src, const_of(src, kq)), "u32")); + assert(const_of(src, kq) == 9); + assert(word_is(src, const_of(src, sq), tok_end(src, const_of(src, sq)), "u8")); + assert(tok_is(src, foo - 3, "fn")); + assert(fn_named(src, foo - 3, foo, tok_end(src, foo))); + assert(!fn_named(src, foo - 3, bar, tok_end(src, bar))); + assert(!fn_named(src, foo, foo, tok_end(src, foo))); + assert(!fn_named(src, kq, foo, tok_end(src, foo))); + assert(!fn_named(src, foo - 3, foo, foo + 2)); + assert(fn_named(src, bar - 3, bar, tok_end(src, bar))); + assert(fn_hit(src, foo - 3, foo, tok_end(src, foo))); + assert(!fn_hit(src, foo - 3, bar, tok_end(src, bar))); + assert(!fn_hit(src, foo, foo, tok_end(src, foo))); + assert(word_is(src, fn_ret_of(src, foo - 3), tok_end(src, fn_ret_of(src, foo - 3)), "u32")); + assert(fn_ret_of(src, bar - 3) == src.len); + assert(word_is(src, fn_ret_of(src, baz - 3), tok_end(src, fn_ret_of(src, baz - 3)), "Result")); + assert(word_is(src, fn_ret_of(src, cf - 3), tok_end(src, fn_ret_of(src, cf - 3)), "u8")); +} + +test unit_result_fn_is_true_only_for_a_result_of_unit_or_an_alias_of_one { + var st : [1024]usize = [0] ** 1024; + const src : str = "type R = Result;\nfn ok() -> Result<(), String> { Ok(()) }\nfn val() -> Result { Ok(1) }\nfn none() {}\nfn al() -> R<()> { Ok(()) }\nfn al2() -> R { Ok(1) }\nfn opt() -> Option<()> { None }\nfn num() -> u8 { 1 }\n"; + const r : usize = find_tok(src, 0, "R"); + add_name(src, &st, K_RALIAS, r, tok_end(src, r), 0, 0); + const names : [8]str = ["ok", "val", "none", "al", "al2", "opt", "num", "ghost"]; + const want : [8]bool = [true, false, false, true, false, false, false, false]; + var i : usize = 0; + while (i < 8) { + const n : usize = find_tok(src, 0, names[i]); + if (i < 7) { + assert(n < src.len); + assert(unit_result_fn(src, &st, n, tok_end(src, n)) == want[i]); + } else { + assert(n == src.len); + } + i = i + 1; + } + var bare : [1024]usize = [0] ** 1024; + const al : usize = find_tok(src, 0, "al"); + assert(!unit_result_fn(src, &bare, al, tok_end(src, al))); + const ok : usize = find_tok(src, 0, "ok"); + assert(unit_result_fn(src, &bare, ok, tok_end(src, ok))); +} From 45099fce17db64c05204887d5be0d7201bc77695 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 19 Oct 2026 11:06:04 +0700 Subject: [PATCH 3/8] t27o: direct tests for the output writers and the type reader of rust_convert.t27 -- put_*, insert/wrap, reserved, prim/heap, angles, result_ty, param_slice, nested_elem, ty (Closes #10825) Tests only; no non-test line changes. Co-Authored-By: Claude Sonnet 5.5 --- specs/tools/t27o/rust_convert.t27 | 783 ++++++++++++++++++++++++++++++ 1 file changed, 783 insertions(+) diff --git a/specs/tools/t27o/rust_convert.t27 b/specs/tools/t27o/rust_convert.t27 index d832d783fc..cda1cfbbaf 100644 --- a/specs/tools/t27o/rust_convert.t27 +++ b/specs/tools/t27o/rust_convert.t27 @@ -11775,3 +11775,786 @@ test unit_result_fn_is_true_only_for_a_result_of_unit_or_an_alias_of_one { const ok : usize = find_tok(src, 0, "ok"); assert(unit_result_fn(src, &bare, ok, tok_end(src, ok))); } + +// ---------------------------------------------------------------- direct tests: the output writers + +test put_src_and_put_text_copy_a_range_and_put_text_keeps_the_comment_ascii { + var out : [64]u8 = undefined; + var st : [64]usize = [0] ** 64; + put_src("hello", &st, &out, 1, 4); + assert(out_is(st[W], &out, 0, "ell")); + put_src("hi", &st, &out, 0, 9); + assert(out_is(st[W], &out, 0, "ellhi")); + put_src("hi", &st, &out, 2, 2); + put_src("hi", &st, &out, 1, 0); + assert(st[W] == 5); + clear(&st); + put_text("abc def", &st, &out, 0, 7, 100); + assert(out_is(st[W], &out, 0, "abc def")); + clear(&st); + put_text("abcdef", &st, &out, 1, 6, 3); + assert(out_is(st[W], &out, 0, "bcd")); + clear(&st); + put_text("abcdef", &st, &out, 2, 4, 100); + assert(out_is(st[W], &out, 0, "cd")); + clear(&st); + put_text("abc", &st, &out, 0, 9, 100); + assert(out_is(st[W], &out, 0, "abc")); + clear(&st); + put_text("abc", &st, &out, 0, 3, 0); + assert(st[W] == 0); + var buf : [16]u8 = [0] ** 16; + var bs : [64]usize = [0] ** 64; + put(&bs, &buf, B_LOWER_A); + put(&bs, &buf, B_TAB); + put(&bs, &buf, B_LOWER_B); + put(&bs, &buf, 195); + put(&bs, &buf, 169); + put(&bs, &buf, B_LOWER_A + 2); + put(&bs, &buf, B_DEL); + put(&bs, &buf, 240); + put(&bs, &buf, 159); + put(&bs, &buf, 146); + put(&bs, &buf, 128); + put(&bs, &buf, B_SPACE); + put_text(buf[0 .. bs[W]], &st, &out, 0, bs[W], 100); + assert(out_is(st[W], &out, 0, "a?b?c?? ")); +} + +test put_num_writes_decimal_digits { + var out : [64]u8 = undefined; + var st : [64]usize = [0] ** 64; + put_num(&st, &out, 0); + assert(out_is(st[W], &out, 0, "0")); + put_num(&st, &out, 7); + put_num(&st, &out, 10); + put_num(&st, &out, 105); + put_num(&st, &out, 9); + assert(out_is(st[W], &out, 0, "07101059")); + clear(&st); + put_num(&st, &out, 12345); + assert(out_is(st[W], &out, 0, "12345")); + clear(&st); + put_num(&st, &out, 4294967296); + assert(out_is(st[W], &out, 0, "4294967296")); + clear(&st); + var small : [3]u8 = undefined; + put_num(&st, &small, 12345); + assert(st[W] == 5); + assert(small[0] == B_ZERO + 1); + assert(small[2] == B_ZERO + 3); +} + +test newline_writes_one_indent_of_four_spaces_per_level { + var out : [64]u8 = undefined; + var st : [64]usize = [0] ** 64; + newline(&st, &out); + assert(out_is(st[W], &out, 0, "\n")); + clear(&st); + st[IND] = 1; + newline(&st, &out); + assert(out_is(st[W], &out, 0, "\n ")); + clear(&st); + st[IND] = 3; + newline(&st, &out); + assert(out_is(st[W], &out, 0, "\n ")); + newline(&st, &out); + assert(st[W] == 26); +} + +test out_at_out_has_and_out_op_space_read_what_was_written { + var out : [64]u8 = undefined; + var st : [64]usize = [0] ** 64; + puts(&st, &out, "a,b"); + assert(out_at(3, &out, 0) == B_LOWER_A); + assert(out_at(3, &out, 1) == B_COMMA); + assert(out_at(3, &out, 2) == B_LOWER_B); + assert(out_at(3, &out, 3) == 0); + assert(out_at(3, &out, 99) == 0); + assert(out_at(2, &out, 2) == 0); + assert(out_at(0, &out, 0) == 0); + var tiny : [2]u8 = undefined; + tiny[0] = B_LOWER_A; + tiny[1] = B_LOWER_B; + assert(out_at(5, &tiny, 1) == B_LOWER_B); + assert(out_at(5, &tiny, 2) == 0); + assert(out_has(3, &out, 0, B_COMMA)); + assert(out_has(3, &out, 1, B_COMMA)); + assert(!out_has(3, &out, 2, B_COMMA)); + assert(!out_has(3, &out, 3, B_COMMA)); + assert(!out_has(1, &out, 0, B_COMMA)); + assert(out_has(2, &out, 0, B_COMMA)); + assert(!out_has(3, &out, 0, B_SEMI)); + assert(!out_has(0, &out, 0, B_LOWER_A)); + assert(out_has(5, &tiny, 1, B_LOWER_B)); + assert(!out_has(5, &tiny, 2, B_LOWER_B)); + clear(&st); + puts(&st, &out, "a b"); + assert(out_op_space(st[W], &out, 0)); + assert(!out_op_space(st[W], &out, 2)); + assert(!out_op_space(1, &out, 0)); + assert(out_op_space(2, &out, 0)); + clear(&st); + puts(&st, &out, "f(a b)"); + assert(!out_op_space(st[W], &out, 0)); + clear(&st); + puts(&st, &out, "[x y] {a b}"); + assert(out_op_space(st[W], &out, 0)); + assert(!out_op_space(5, &out, 0)); + assert(!out_op_space(st[W], &out, 6)); + clear(&st); + puts(&st, &out, "\"a b\""); + assert(!out_op_space(st[W], &out, 0)); + clear(&st); + puts(&st, &out, "'a b'"); + assert(!out_op_space(st[W], &out, 0)); + clear(&st); + puts(&st, &out, "\"a\\\" b\""); + assert(!out_op_space(st[W], &out, 0)); + clear(&st); + puts(&st, &out, "\"a\\\" b\" c"); + assert(out_op_space(st[W], &out, 0)); + clear(&st); + puts(&st, &out, ") a"); + assert(out_op_space(st[W], &out, 0)); + clear(&st); + puts(&st, &out, "abc"); + assert(!out_op_space(st[W], &out, 0)); + assert(!out_op_space(0, &out, 0)); +} + +test open_gap_insert_insert_src_and_wrap_edit_the_output_in_place { + var out : [16]u8 = undefined; + var st : [64]usize = [0] ** 64; + puts(&st, &out, "abc"); + assert(open_gap(&st, &out, 1, 2)); + assert(st[W] == 5); + assert(out[0] == B_LOWER_A); + assert(out[3] == B_LOWER_B); + assert(out[4] == B_LOWER_A + 2); + clear(&st); + puts(&st, &out, "abc"); + assert(open_gap(&st, &out, 3, 2)); + assert(st[W] == 5); + assert(out[2] == B_LOWER_A + 2); + clear(&st); + puts(&st, &out, "abc"); + insert(&st, &out, 1, "XY"); + assert(out_is(st[W], &out, 0, "aXYbc")); + clear(&st); + puts(&st, &out, "abc"); + insert(&st, &out, 0, "XY"); + assert(out_is(st[W], &out, 0, "XYabc")); + clear(&st); + puts(&st, &out, "abc"); + insert(&st, &out, 3, "XY"); + assert(out_is(st[W], &out, 0, "abcXY")); + clear(&st); + puts(&st, &out, "abc"); + insert(&st, &out, 1, ""); + assert(out_is(st[W], &out, 0, "abc")); + clear(&st); + puts(&st, &out, "abc"); + insert_src("xyz", &st, &out, 1, 0, 2); + assert(out_is(st[W], &out, 0, "axybc")); + insert_src("xyz", &st, &out, 5, 2, 3); + assert(out_is(st[W], &out, 0, "axybcz")); + insert_src("xyz", &st, &out, 0, 1, 1); + assert(st[W] == 6); + clear(&st); + puts(&st, &out, "a+b"); + wrap(&st, &out, 0); + assert(out_is(st[W], &out, 0, "(a+b)")); + clear(&st); + puts(&st, &out, "a+b"); + wrap(&st, &out, 2); + assert(out_is(st[W], &out, 0, "a+(b)")); + clear(&st); + puts(&st, &out, "a+b"); + wrap(&st, &out, 3); + assert(out_is(st[W], &out, 0, "a+b()")); + var tiny : [4]u8 = undefined; + clear(&st); + puts(&st, &tiny, "abc"); + assert(!open_gap(&st, &tiny, 1, 2)); + assert(st[W] == 5); + assert(tiny[1] == B_LOWER_B); + assert(tiny[2] == B_LOWER_A + 2); + clear(&st); + puts(&st, &tiny, "abc"); + insert(&st, &tiny, 1, "XY"); + assert(st[W] == 5); + assert(tiny[1] == B_LOWER_B); + clear(&st); + puts(&st, &tiny, "abc"); + insert_src("xyz", &st, &tiny, 1, 0, 2); + assert(st[W] == 5); + assert(tiny[1] == B_LOWER_B); +} + +test reserved_names_get_a_trailing_underscore_from_put_ident_and_insert_ident { + const words : [27]str = ["and", "or", "test", "var", "error", "null", "undefined", "switch", "orelse", "try", "defer", "comptime", "module", "invariant", "bench", "catch", "unreachable", "anytype", "opaque", "packed", "export", "inline", "align", "noreturn", "errdefer", "spec", "void"]; + var i : usize = 0; + while (i < 27) { + assert(reserved(words[i], 0, words[i].len)); + i = i + 1; + } + assert(!reserved("fn", 0, 2)); + assert(!reserved("x", 0, 1)); + assert(!reserved("ands", 0, 4)); + assert(!reserved("Test", 0, 4)); + assert(!reserved("testing", 0, 7)); + assert(!reserved("", 0, 0)); + assert(!reserved("an", 0, 2)); + assert(reserved("a test", 2, 6)); + assert(!reserved("a test", 2, 5)); + var out : [64]u8 = undefined; + var st : [64]usize = [0] ** 64; + put_ident("void x", &st, &out, 0, 4); + assert(out_is(st[W], &out, 0, "void_")); + put_ident("void x", &st, &out, 5, 6); + assert(out_is(st[W], &out, 0, "void_x")); + clear(&st); + puts(&st, &out, "ab"); + insert_ident("test", &st, &out, 1, 0, 4); + assert(out_is(st[W], &out, 0, "atest_b")); + clear(&st); + puts(&st, &out, "ab"); + insert_ident("x", &st, &out, 1, 0, 1); + assert(out_is(st[W], &out, 0, "axb")); + clear(&st); + puts(&st, &out, "ab"); + insert_ident("fn", &st, &out, 2, 0, 2); + assert(out_is(st[W], &out, 0, "abfn")); +} + +test put_impl_and_put_owner_write_the_impl_type_for_self { + var out : [64]u8 = undefined; + var st : [64]usize = [0] ** 64; + const src : str = "Self Pt void"; + st[ILO] = 5; + st[IHI] = 7; + put_impl(src, &st, &out); + assert(out_is(st[W], &out, 0, "Pt")); + put_owner(src, &st, &out, 0, 4); + assert(out_is(st[W], &out, 0, "PtPt")); + assert(st[ERR] == 0); + put_owner(src, &st, &out, 5, 7); + assert(out_is(st[W], &out, 0, "PtPtPt")); + put_owner(src, &st, &out, 8, 12); + assert(out_is(st[W], &out, 0, "PtPtPtvoid_")); + assert(st[ERR] == 0); + var bare : [64]usize = [0] ** 64; + var o2 : [64]u8 = undefined; + put_owner(src, &bare, &o2, 0, 4); + assert(bare[ERR] == R_PATH); + assert(bare[AT] == 0); + assert(bare[NLO] == 0); + assert(bare[NHI] == 4); + assert(bare[W] == 0); +} + +test clear_zeroes_the_state_slots_and_keeps_the_rest_and_reverse_flips_a_range { + var st : [128]usize = [7] ** 128; + clear(&st); + var i : usize = 0; + while (i < STATE) { + assert(st[i] == 0); + i = i + 1; + } + assert(st[STATE] == 7); + assert(st[NAMES] == 7); + assert(st[127] == 7); + var out : [8]u8 = undefined; + var ws : [64]usize = [0] ** 64; + puts(&ws, &out, "abcde"); + reverse(&out, 0, 5); + assert(out_is(ws[W], &out, 0, "edcba")); + reverse(&out, 1, 4); + assert(out_is(ws[W], &out, 0, "ebcda")); + reverse(&out, 2, 3); + assert(out_is(ws[W], &out, 0, "ebcda")); + reverse(&out, 2, 2); + assert(out_is(ws[W], &out, 0, "ebcda")); + reverse(&out, 3, 5); + assert(out_is(ws[W], &out, 0, "ebcad")); +} + +test prim_int_type_and_heap_type_sort_the_type_words { + const ints : [11]str = ["u8", "u16", "u32", "u64", "u128", "i8", "i16", "i32", "i64", "i128", "isize"]; + var i : usize = 0; + while (i < 11) { + assert(int_type(ints[i], 0, ints[i].len)); + assert(prim(ints[i], 0, ints[i].len)); + assert(!heap_type(ints[i], 0, ints[i].len)); + i = i + 1; + } + assert(!int_type("usize", 0, 5)); + assert(prim("usize", 0, 5)); + assert(prim("bool", 0, 4)); + assert(prim("f32", 0, 3)); + assert(prim("f64", 0, 3)); + assert(!int_type("bool", 0, 4)); + assert(!int_type("f32", 0, 3)); + assert(!prim("char", 0, 4)); + assert(!prim("str", 0, 3)); + assert(!prim("String", 0, 6)); + assert(!prim("u7", 0, 2)); + assert(!prim("u8x", 0, 3)); + assert(!prim("", 0, 0)); + assert(prim("x u8", 2, 4)); + assert(!int_type("x u8", 2, 3)); + const heap : [18]str = ["String", "Vec", "Box", "Rc", "Arc", "HashMap", "HashSet", "BTreeMap", "BTreeSet", "VecDeque", "RefCell", "Cell", "PathBuf", "Path", "str", "impl", "dyn", "fn"]; + var h : usize = 0; + while (h < 18) { + assert(heap_type(heap[h], 0, heap[h].len)); + assert(!prim(heap[h], 0, heap[h].len)); + h = h + 1; + } + assert(!heap_type("Option", 0, 6)); + assert(!heap_type("Result", 0, 6)); + assert(!heap_type("Pt", 0, 2)); + assert(!heap_type("usize", 0, 5)); + assert(!heap_type("Strin", 0, 5)); + assert(!heap_type("string", 0, 6)); + assert(!heap_type("", 0, 0)); +} + +test close_angle_closes_one_level_and_leaves_the_second_of_a_double { + var st : [64]usize = [0] ** 64; + close_angle("> x", &st); + assert(st[ERR] == 0); + assert(st[P] == 2); + clear(&st); + close_angle(">> x", &st); + assert(st[ERR] == 0); + assert(st[P] == 1); + close_angle(">> x", &st); + assert(st[ERR] == 0); + assert(st[P] == 3); + clear(&st); + close_angle(">= 5", &st); + assert(st[ERR] == 0); + assert(st[P] == 1); + clear(&st); + close_angle(">>= 5", &st); + assert(st[ERR] == 0); + assert(st[P] == 1); + clear(&st); + close_angle("x", &st); + assert(st[ERR] == R_SYNTAX); + assert(st[AT] == 0); + assert(st[NHI] == 1); + assert(st[P] == 0); + clear(&st); + close_angle("", &st); + assert(st[ERR] == R_SYNTAX); + clear(&st); + close_angle(",>", &st); + assert(st[ERR] == R_SYNTAX); + assert(st[P] == 0); +} + +test skip_angle_skips_to_the_angle_that_closes_the_list { + var st : [64]usize = [0] ** 64; + skip_angle("u8> x", &st); + assert(st[P] == 4); + assert(st[ERR] == 0); + clear(&st); + skip_angle("Vec> x", &st); + assert(st[P] == 9); + clear(&st); + skip_angle("u8>> x", &st); + assert(st[P] == 3); + clear(&st); + skip_angle("A>> x", &st); + assert(st[P] == 9); + clear(&st); + skip_angle("A, C> x", &st); + assert(st[P] == 9); + clear(&st); + skip_angle("u8", &st); + assert(st[P] == 2); + clear(&st); + skip_angle("", &st); + assert(st[P] == 0); + clear(&st); + skip_angle(">", &st); + assert(st[P] == 1); + clear(&st); + st[P] = 3; + skip_angle("a b> c", &st); + assert(st[P] == 5); +} + +test result_ty_writes_an_optional_or_a_bool_and_drops_the_error_type { + var out : [64]u8 = undefined; + var st : [64]usize = [0] ** 64; + const s1 : str = "Result x"; + st[P] = 6; + result_ty(s1, &st, &out, 0, 6); + assert(out_is(st[W], &out, 0, "?u8")); + assert(st[ERR] == 0); + assert(st[P] == 19); + clear(&st); + const s2 : str = "Result<(), String> x"; + st[P] = 6; + result_ty(s2, &st, &out, 0, 6); + assert(out_is(st[W], &out, 0, "bool")); + assert(st[ERR] == 0); + assert(st[P] == 19); + clear(&st); + const s3 : str = "R x"; + st[P] = 1; + result_ty(s3, &st, &out, 0, 1); + assert(out_is(st[W], &out, 0, "?u8")); + assert(st[ERR] == 0); + assert(st[P] == 6); + clear(&st); + const s4 : str = "R<()> x"; + st[P] = 1; + result_ty(s4, &st, &out, 0, 1); + assert(out_is(st[W], &out, 0, "bool")); + assert(st[P] == 6); + clear(&st); + const s5 : str = "Result, E> x"; + st[P] = 6; + result_ty(s5, &st, &out, 0, 6); + assert(st[ERR] == R_TYPE); + assert(st[AT] == 0); + assert(st[NLO] == 0); + assert(st[NHI] == 6); + clear(&st); + const s6 : str = "Result", &st, &out); + assert(out_is(st[W], &out, 0, "?u8")); + assert(st[ERR] == 0); + assert(st[P] == 10); + clear(&st); + ty("Option x", &st, &out); + assert(out_is(st[W], &out, 0, "?Pt")); + assert(st[P] == 11); + clear(&st); + ty("Option<()>", &st, &out); + assert(st[ERR] == R_TYPE); + assert(st[AT] == 7); + clear(&st); + ty("Option>", &st, &out); + assert(st[ERR] == R_TYPE); + assert(st[AT] == 0); + assert(st[NHI] == 6); + clear(&st); + ty("Result", &st, &out); + assert(out_is(st[W], &out, 0, "?u8")); + assert(st[ERR] == 0); + assert(st[P] == 18); + clear(&st); + ty("Result<(), String>", &st, &out); + assert(out_is(st[W], &out, 0, "bool")); + clear(&st); + ty("Result", &st, &out); + assert(out_is(st[W], &out, 0, "?Pt")); + clear(&st); + const alias : str = "R"; + add_name(alias, &st, K_RALIAS, 0, 1, 0, 0); + ty(alias, &st, &out); + assert(out_is(st[W], &out, 0, "?u8")); + assert(st[ERR] == 0); + clear(&st); + ty(alias, &st, &out); + assert(st[ERR] == R_TYPE); + clear(&st); + ty("Foo", &st, &out); + assert(st[ERR] == R_TYPE); + assert(st[AT] == 0); + assert(st[NHI] == 3); + clear(&st); + ty("a::B", &st, &out); + assert(st[ERR] == R_TYPE); + assert(st[NHI] == 1); + clear(&st); + ty("Self", &st, &out); + assert(st[ERR] == R_PATH); + clear(&st); + const sf : str = "Pt Self"; + st[ILO] = 0; + st[IHI] = 2; + st[P] = 3; + ty(sf, &st, &out); + assert(out_is(st[W], &out, 0, "Pt")); + assert(st[ERR] == 0); +} + +test ty_refuses_an_owned_heap_type_and_reads_a_parameters_string_and_vec_as_slices { + var out : [64]u8 = undefined; + var st : [128]usize = [0] ** 128; + const heaps : [6]str = ["String", "Vec", "Box", "HashMap", "Rc", "Path"]; + var i : usize = 0; + while (i < 6) { + clear(&st); + ty(heaps[i], &st, &out); + assert(st[ERR] == R_TYPE); + assert(st[AT] == 0); + assert(st[W] == 0); + i = i + 1; + } + clear(&st); + st[PARAMTY] = 1; + ty("String", &st, &out); + assert(out_is(st[W], &out, 0, "[]const u8")); + assert(st[ERR] == 0); + assert(st[PARAMTY] == 0); + clear(&st); + st[PARAMTY] = 1; + ty("&String", &st, &out); + assert(out_is(st[W], &out, 0, "[]const u8")); + assert(st[ERR] == 0); + clear(&st); + st[PARAMTY] = 1; + ty("&Vec", &st, &out); + assert(out_is(st[W], &out, 0, "[]const u8")); + assert(st[ERR] == 0); + assert(st[P] == 8); + clear(&st); + st[PARAMTY] = 1; + ty("Vec", &st, &out); + assert(out_is(st[W], &out, 0, "[]const u32")); + clear(&st); + st[PARAMTY] = 1; + ty("&mut String", &st, &out); + assert(st[ERR] == R_TYPE); + assert(st[AT] == 5); + clear(&st); + st[PARAMTY] = 1; + ty("&mut Vec", &st, &out); + assert(st[ERR] == R_TYPE); + clear(&st); + st[PARAMTY] = 1; + ty("&mut u8", &st, &out); + assert(st[ERR] == R_MUTREF); + clear(&st); + st[PARAMTY] = 1; + ty("Box", &st, &out); + assert(st[ERR] == R_TYPE); + clear(&st); + st[PARAMTY] = 1; + ty("&str", &st, &out); + assert(out_is(st[W], &out, 0, "[]const u8")); + assert(st[PARAMTY] == 0); + clear(&st); + st[PARAMTY] = 1; + ty("[String; 2]", &st, &out); + assert(st[ERR] == R_TYPE); +} From 9c5b076363680c8fe53bfefacb78f2ffbdfa6257 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 19 Oct 2026 11:15:35 +0700 Subject: [PATCH 4/8] t27o: direct tests for the class helpers of rust_convert.t27 -- literal/type/name/receiver/expression classes, struct lookups, std table find, and a known-defect test for str_chain (Closes #10825) Tests only; no non-test line changes. The str_chain field-open defect is #10834. Co-Authored-By: Claude Sonnet 5.5 --- specs/tools/t27o/rust_convert.t27 | 669 ++++++++++++++++++++++++++++++ 1 file changed, 669 insertions(+) diff --git a/specs/tools/t27o/rust_convert.t27 b/specs/tools/t27o/rust_convert.t27 index cda1cfbbaf..446d4718b1 100644 --- a/specs/tools/t27o/rust_convert.t27 +++ b/specs/tools/t27o/rust_convert.t27 @@ -12558,3 +12558,672 @@ test ty_refuses_an_owned_heap_type_and_reads_a_parameters_string_and_vec_as_slic ty("[String; 2]", &st, &out); assert(st[ERR] == R_TYPE); } + +// ---------------------------------------------------------------- direct tests: types and classes + +test ends_with_and_suffix_len_read_the_type_suffix_of_a_number { + assert(ends_with("5u8", 0, 3, "u8")); + assert(ends_with("abc", 0, 3, "bc")); + assert(ends_with("xabc", 1, 4, "bc")); + assert(!ends_with("u8", 0, 2, "u8")); + assert(!ends_with("abc", 0, 3, "ac")); + assert(!ends_with("abc", 1, 3, "bc")); + assert(!ends_with("abc", 0, 3, "abcd")); + assert(ends_with("abc", 0, 3, "")); + const sfx : [18]str = ["7u8", "7i8", "7u16", "7i16", "7u32", "7i32", "7u64", "7i64", "7u128", "7i128", "7usize", "7isize", "1.0f32", "1.0f64", "7f32", "0b1u8", "0x1u8", "1_000u32"]; + const len : [18]usize = [2, 2, 3, 3, 3, 3, 3, 3, 4, 4, 5, 5, 3, 3, 3, 2, 2, 3]; + var i : usize = 0; + while (i < 18) { + assert(suffix_len(sfx[i], 0, sfx[i].len) == len[i]); + i = i + 1; + } + const none : [8]str = ["5", "0x1f32", "0xf64", "5x8", "7u9", "u8", "5.0", "12"]; + var j : usize = 0; + while (j < 8) { + assert(suffix_len(none[j], 0, none[j].len) == 0); + j = j + 1; + } + assert(suffix_len("", 0, 0) == 0); + assert(suffix_len("a 7u8", 2, 5) == 2); + assert(suffix_len("a 7u8", 2, 3) == 0); + assert(suffix_len("7u8", 2, 1) == 0); +} + +test literal_class_tells_an_integer_from_a_float_and_a_suffix_names_the_type { + var st : [64]usize = [0] ** 64; + const ints : [9]str = ["5", "1_000", "0x1e", "0b11", "0o7", "0xFFu8", "12i128", "5u8", "0x1f32"]; + var i : usize = 0; + while (i < 9) { + assert(literal_class(ints[i], &st, 0) == C_INT); + i = i + 1; + } + const floats : [8]str = ["1.5", "1e3", "1E3", "2.5e-3", "7f32", "1.5f64", "1.0f32", "0e1"]; + var j : usize = 0; + while (j < 8) { + assert(literal_class(floats[j], &st, 0) == C_FLOAT); + j = j + 1; + } + st[TYLO] = 99; + st[TYHI] = 98; + assert(literal_class("5", &st, 0) == C_INT); + assert(st[TYLO] == 99); + assert(st[TYHI] == 98); + assert(literal_class("5u8", &st, 0) == C_INT); + assert(st[TYLO] == 1); + assert(st[TYHI] == 3); + assert(literal_class("a 1.5f64", &st, 2) == C_FLOAT); + assert(st[TYLO] == 5); + assert(st[TYHI] == 8); + assert(literal_class("0xFFu8", &st, 0) == C_INT); + assert(st[TYLO] == 4); + assert(st[TYHI] == 6); +} + +test type_class_classes_a_type_token_and_names_its_integer_or_element_type { + var st : [64]usize = [0] ** 64; + assert(type_class("str", &st, 0) == C_STR); + assert(type_class("String", &st, 0) == C_STR); + assert(type_class("&str", &st, 0) == C_STR); + assert(type_class("&'a mut String", &st, 0) == C_STR); + assert(type_class("bool", &st, 0) == C_BOOL); + assert(type_class("&bool", &st, 0) == C_BOOL); + assert(type_class("Pt", &st, 0) == C_ANY); + assert(type_class("Option", &st, 0) == C_ANY); + assert(type_class("Vec", &st, 0) == C_ANY); + assert(type_class("", &st, 0) == C_ANY); + assert(type_class("f64", &st, 0) == C_FLOAT); + assert(st[TYLO] == 0); + assert(st[TYHI] == 3); + assert(type_class("&f32", &st, 0) == C_FLOAT); + assert(st[TYLO] == 1); + assert(st[TYHI] == 4); + const ints : [6]str = ["u8", "u128", "i16", "isize", "usize", "i64"]; + var i : usize = 0; + while (i < 6) { + clear(&st); + assert(type_class(ints[i], &st, 0) == C_INT); + assert(st[TYLO] == 0); + assert(st[TYHI] == ints[i].len); + i = i + 1; + } + clear(&st); + assert(type_class("&&u32", &st, 0) == C_INT); + assert(st[TYLO] == 2); + assert(st[TYHI] == 5); + clear(&st); + assert(type_class("[u8; 4]", &st, 0) == C_SLICE); + assert(st[TYARR] == 1); + assert(st[TYLO] == 1); + assert(st[TYHI] == 3); + clear(&st); + assert(type_class("&[u8; 4]", &st, 0) == C_SLICE); + assert(st[TYARR] == 0); + assert(st[TYLO] == 2); + clear(&st); + assert(type_class("&[u32]", &st, 0) == C_SLICE); + assert(st[TYARR] == 0); + assert(st[TYHI] - st[TYLO] == 3); + clear(&st); + assert(type_class("[u8]", &st, 0) == C_SLICE); + assert(st[TYARR] == 0); + clear(&st); + assert(type_class("Vec", &st, 0) == C_SLICE); + assert(st[TYLO] == 4); + assert(st[TYHI] == 7); + assert(st[TYARR] == 0); + clear(&st); + assert(type_class("x: &mut [u8]", &st, 3) == C_SLICE); + assert(st[TYLO] == 9); +} + +test struct_hit_struct_brace_and_struct_open_find_a_struct_head { + const src : str = "struct Node { x: u8 }\nstruct W(u8, bool);\nstruct U;\nstruct Node2 { y: u8 }\n"; + assert(struct_hit(src, 0, 7, 11, false)); + assert(struct_hit(src, 0, 7, 11, true)); + assert(!struct_hit(src, 0, 29, 30, false)); + assert(!struct_hit(src, 22, 29, 30, false)); + assert(struct_hit(src, 22, 29, 30, true)); + assert(!struct_hit(src, 42, 49, 50, false)); + assert(!struct_hit(src, 42, 49, 50, true)); + assert(!struct_hit(src, 0, 7, 10, false)); + assert(!struct_hit(src, 0, 29, 30, true)); + assert(!struct_hit(src, 7, 7, 11, false)); + assert(!struct_hit(src, 52, 7, 11, true)); + assert(struct_hit(src, 52, 59, 64, true)); + assert(struct_brace(src, 0) == 12); + assert(struct_brace(src, 22) == 30); + assert(struct_brace(src, 52) == 65); + var st : [1024]usize = [0] ** 1024; + index_decls(src, &st); + assert(st[IXON] == 1); + var mode : usize = 0; + while (mode < 2) { + st[IXON] = 1 - mode; + assert(struct_open(src, &st, 7, 11) == 12); + assert(struct_open(src, &st, 29, 30) == 30); + assert(struct_open(src, &st, 49, 50) == src.len); + assert(struct_open(src, &st, 59, 64) == 65); + assert(struct_open(src, &st, 7, 10) == src.len); + assert(struct_open(src, &st, 7, 7) == src.len); + assert(find_struct(src, &st, 29, 30) == src.len); + assert(find_struct(src, &st, 7, 11) == 12); + mode = mode + 1; + } +} + +test field_type_decl_type_and_fn_end_read_declarations_by_position { + var st : [64]usize = [0] ** 64; + const s : str = "struct A { pub x: u8, #[a] y: bool, pub(crate) z: [u8; 2] }\nstruct W(u8, pub bool);\nstruct E {}"; + const o : usize = find_at(s, 0, B_LBRACE); + assert(o == 9); + const t0 : usize = field_type(s, &st, o, 0); + assert(t0 == 18); + assert(st[TYLO] == 15); + assert(st[TYHI] == 16); + const t1 : usize = field_type(s, &st, o, 1); + assert(t1 == 30); + assert(word_is(s, st[TYLO], st[TYHI], "y")); + const t2 : usize = field_type(s, &st, o, 2); + assert(tok_is(s, t2, "[")); + assert(word_is(s, st[TYLO], st[TYHI], "z")); + assert(field_type(s, &st, o, 3) == s.len); + const w : usize = find_at(s, 60, B_LPAREN); + assert(s[w] == B_LPAREN); + assert(field_type(s, &st, w, 0) == w + 1); + assert(st[TYLO] == 0); + assert(st[TYHI] == 0); + assert(tok_is(s, field_type(s, &st, w, 1), "bool")); + assert(field_type(s, &st, w, 2) == s.len); + const e : usize = s.len - 2; + assert(s[e] == B_LBRACE); + assert(field_type(s, &st, e, 0) == s.len); + const d : str = "fn f(a: u32, s: &str) { let a: u8 = 1; let b = a::x; let aa: bool = true; }"; + assert(decl_type(d, 0, 75, 5, 6) == 31); + assert(decl_type(d, 0, 21, 5, 6) == 8); + assert(decl_type(d, 22, 75, 5, 6) == 31); + assert(decl_type(d, 0, 75, 13, 14) == 16); + assert(decl_type(d, 0, 75, 57, 59) == 61); + assert(decl_type(d, 0, 75, 43, 44) == 75); + assert(decl_type(d, 0, 5, 5, 6) == 75); + assert(decl_type(d, 0, 0, 5, 6) == 75); + const fe : str = "fn f() { 1 } fn g(); fn h() {}"; + assert(fn_end(fe, 0) == 12); + assert(fn_end(fe, 21) == 30); + assert(fn_end("fn f()", 0) == 6); + assert(fn_end("fn f() { {} }", 0) == 13); +} + +test raw_str_at_lit_at_and_listed_read_literals_and_word_lists { + assert(raw_str_at("r\"x\"", 0)); + assert(raw_str_at("r#\"x\"#", 0)); + assert(raw_str_at("r##\"x\"##", 0)); + assert(raw_str_at("b r\"x\"", 2)); + assert(!raw_str_at("r#x", 0)); + assert(!raw_str_at("rx", 0)); + assert(!raw_str_at("r", 0)); + assert(!raw_str_at("r#", 0)); + assert(!raw_str_at("\"x\"", 0)); + assert(!raw_str_at("r\"x\"", 5)); + assert(!raw_str_at("r\"x\"", 1)); + assert(lit_at("\"x\"", 0)); + assert(lit_at("'a'", 0)); + assert(lit_at("b\"x\"", 0)); + assert(lit_at("b'a'", 0)); + assert(lit_at("r\"x\"", 0)); + assert(lit_at("r#\"x\"#", 0)); + assert(lit_at("x \"y\"", 2)); + assert(!lit_at("bx", 0)); + assert(!lit_at("r#x", 0)); + assert(!lit_at("x", 0)); + assert(!lit_at("1", 0)); + assert(!lit_at("b", 0)); + assert(!lit_at("\"x\"", 3)); + assert(!lit_at("", 0)); + assert(listed(" u32 u64 ", "u32")); + assert(listed(" u32 u64 ", "u64")); + assert(listed(" a b ", "a")); + assert(listed(" a b ", "b")); + assert(!listed(" a b", "b")); + assert(!listed(" u32 u64 ", "u3")); + assert(!listed(" u32 u64 ", "u")); + assert(!listed(" u32 u64 ", "32")); + assert(!listed(" u32 u64 ", "")); + assert(!listed("", "u32")); + assert(!listed(" ", "u32")); + assert(!listed(" u32 ", "u32x")); +} + +test std_bool_find_and_let_int_read_the_std_table_and_a_typed_let { + const bools : [15]str = ["is_empty", "starts_with", "ends_with", "contains", "is_some", "is_none", "is_ok", "is_err", "eq", "is_ascii_alphabetic", "is_ascii_alphanumeric", "is_ascii_digit", "all", "is_finite", "is_ascii"]; + var i : usize = 0; + while (i < 15) { + assert(std_bool(bools[i], 0, bools[i].len)); + i = i + 1; + } + const not : [7]str = ["len", "is_", "contain", "iter", "is_empty_", "IS_EMPTY", "unwrap"]; + var j : usize = 0; + while (j < 7) { + assert(!std_bool(not[j], 0, not[j].len)); + j = j + 1; + } + assert(!std_bool("", 0, 0)); + assert(std_bool("x is_ok", 2, 7)); + assert(!std_bool("x is_ok", 2, 6)); + assert(find("len", C_ANY, "") == 0); + assert(find("len", C_STR, "") == 0); + assert(find("abs", C_FLOAT, "") == 6); + assert(find("abs", C_INT, "i32") == 7); + assert(find("abs", C_INT, "u32") == STD_N); + assert(find("abs", C_ANY, "") == STD_N); + assert(find("min", C_ANY, "") == 8); + assert(find("cmp::min", C_ANY, "") == 10); + assert(find("trim", C_STR, "") == 18); + assert(find("trim", C_INT, "") == STD_N); + assert(find("contains", C_STR, "") == 23); + assert(find("contains", C_SLICE, "u8") == 24); + assert(find("contains", C_SLICE, "u32") == STD_N); + assert(find("parse", C_STR, "u32") == 25); + assert(find("parse", C_STR, "f32") == STD_N); + assert(find("sum", C_SLICE, "u32") == STD_N); + assert(find("iter.sum", C_SLICE, "u32") == 26); + assert(find("iter.sum", C_SLICE, "u8") == STD_N); + assert(find("starts_with", C_STR, "") == 21); + assert(find("is_ok", C_BOOL, "") == 32); + assert(find("is_ok", C_ANY, "") == 34); + assert(find("is_ok", C_INT, "") == 34); + assert(find("get", C_SLICE, "u8") == 71); + assert(find("get", C_SLICE, "bool") == STD_N); + assert(find("pow", C_INT, "u32") == 58); + assert(find("pow", C_INT, "f64") == STD_N); + assert(find("sqrt", C_FLOAT, "") == 63); + assert(find("unwrap_or", C_ANY, "") == 73); + assert(find("contains.char", C_STR, "") == 72); + assert(find("contains.char", C_ANY, "") == STD_N); + assert(find("count_ones", C_INT, "u16") == 55); + assert(find("nosuch", C_ANY, "") == STD_N); + assert(find("", C_ANY, "") == STD_N); + var st : [64]usize = [0] ** 64; + assert(let_int(" u32", &st, 1) == 1); + assert(let_int(" usize", &st, 1) == 1); + assert(let_int(" i8", &st, 1) == 1); + assert(let_int(" Result", &st, 1) == 8); + assert(let_int(" Option", &st, 1) == 8); + assert(let_int(" Option", &st, 1) == 8); + assert(let_int(" Result<(), E>", &st, 1) == 14); + assert(let_int(" Vec", &st, 1) == 9); + assert(let_int(" bool", &st, 1) == 5); + assert(let_int(" Result", &st, 1) == 15); + assert(let_int(" R", &st, 1) == 7); + assert(let_int("u32", &st, 0) == 3); + assert(let_int(" u32", &st, 4) == 4); + assert(let_int(" u32", &st, 9) == 4); + const al : str = " R Q"; + add_name(al, &st, K_RALIAS, 1, 2, 0, 0); + assert(let_int(al, &st, 1) == 3); + assert(let_int(al, &st, 8) == 14); +} + +test cast_class_and_len_tail_read_the_last_step_of_a_group_and_a_len_call { + var st : [64]usize = [0] ** 64; + assert(cast_class("(n as u64)", &st, 0) == C_INT); + assert(st[TYLO] == 6); + assert(st[TYHI] == 9); + clear(&st); + assert(cast_class("(n as f64)", &st, 0) == C_FLOAT); + assert(st[TYLO] == 6); + assert(cast_class("(n as usize)", &st, 0) == C_INT); + assert(cast_class("(n as i128)", &st, 0) == C_INT); + assert(cast_class("(n as u8 as u16)", &st, 0) == C_INT); + assert(cast_class("(n as char)", &st, 0) == C_ANY); + assert(cast_class("(n as bool)", &st, 0) == C_ANY); + assert(cast_class("(a + b)", &st, 0) == C_ANY); + assert(cast_class("(a as u8 + 1)", &st, 0) == C_ANY); + assert(cast_class("((a as u8))", &st, 0) == C_ANY); + assert(cast_class("(x)", &st, 0) == C_ANY); + assert(cast_class("()", &st, 0) == C_ANY); + assert(cast_class("f ( n as u32 )", &st, 2) == C_INT); + assert(len_tail("v.len()", 0, 7) == 2); + assert(len_tail("s.trim().len()", 0, 14) == 9); + assert(len_tail(".len()", 0, 6) == 1); + assert(len_tail("a.len() b", 0, 7) == 2); + assert(len_tail("b . len ( )", 0, 12) == 5); + assert(len_tail("v.len", 0, 5) == 5); + assert(len_tail("len()", 0, 5) == 5); + assert(len_tail("a.len(1)", 0, 8) == 8); + assert(len_tail("x.len() + 1", 0, 11) == 11); + assert(len_tail("a.len(", 0, 6) == 6); + assert(len_tail("", 0, 0) == 0); + assert(len_tail("a.len() b", 0, 9) == 9); + assert(len_tail("a.len() b", 2, 7) == 9); +} + +test ret_class_ret_step_and_callee_class_class_what_a_call_gives { + var st : [1024]usize = [0] ** 1024; + const src : str = "fn size() -> usize { 1 }\nfn flag() -> bool { true }\nfn both() -> bool { true }\nimpl A { fn both(&self) -> u8 { 1 } }\nfn none() { }\nfn is_empty(x: u8) -> u8 { x }\nfn is_ok() -> bool { true }\nnope starts_with frob\n"; + index_decls(src, &st); + assert(st[IXON] == 1); + const sz : usize = find_tok(src, 0, "size"); + const fl : usize = find_tok(src, 0, "flag"); + const no : usize = find_tok(src, 0, "none"); + const bo : usize = find_tok(src, 0, "both"); + const ie : usize = find_tok(src, 0, "is_empty"); + const ik : usize = find_tok(src, 0, "is_ok"); + const nope : usize = find_tok(src, 0, "nope"); + const sw : usize = find_tok(src, 0, "starts_with"); + const fr : usize = find_tok(src, 0, "frob"); + assert(tok_is(src, sz - 3, "fn")); + var mode : usize = 0; + while (mode < 2) { + st[IXON] = 1 - mode; + assert(ret_class(src, &st, sz, tok_end(src, sz)) == C_INT); + assert(ret_class(src, &st, fl, tok_end(src, fl)) == C_BOOL); + assert(ret_class(src, &st, bo, tok_end(src, bo)) == C_ANY); + assert(ret_class(src, &st, no, tok_end(src, no)) == C_NONE); + assert(ret_class(src, &st, nope, tok_end(src, nope)) == C_NONE); + assert(ret_class(src, &st, ie, tok_end(src, ie)) == C_INT); + assert(callee_class(src, &st, sz, tok_end(src, sz), false) == C_INT); + assert(callee_class(src, &st, sz, tok_end(src, sz), true) == C_INT); + assert(callee_class(src, &st, fl, tok_end(src, fl), false) == C_BOOL); + assert(callee_class(src, &st, ie, tok_end(src, ie), true) == C_ANY); + assert(callee_class(src, &st, ie, tok_end(src, ie), false) == C_INT); + assert(callee_class(src, &st, ik, tok_end(src, ik), true) == C_BOOL); + assert(callee_class(src, &st, no, tok_end(src, no), false) == C_ANY); + assert(callee_class(src, &st, no, tok_end(src, no), true) == C_ANY); + assert(callee_class(src, &st, bo, tok_end(src, bo), true) == C_ANY); + assert(callee_class(src, &st, sw, tok_end(src, sw), true) == C_BOOL); + assert(callee_class(src, &st, sw, tok_end(src, sw), false) == C_ANY); + assert(callee_class(src, &st, fr, tok_end(src, fr), true) == C_ANY); + mode = mode + 1; + } + const s0 : usize = sz - 3; + assert(ret_step(src, &st, s0, sz, tok_end(src, sz), C_NONE) == C_INT); + assert(ret_step(src, &st, s0, sz, tok_end(src, sz), C_INT) == C_INT); + assert(ret_step(src, &st, s0, sz, tok_end(src, sz), C_BOOL) == C_ANY); + assert(ret_step(src, &st, s0, sz, tok_end(src, sz), C_ANY) == C_ANY); + assert(ret_step(src, &st, fl - 3, sz, tok_end(src, sz), C_BOOL) == C_BOOL); + assert(ret_step(src, &st, no - 3, no, tok_end(src, no), C_NONE) == C_NONE); + assert(ret_step(src, &st, no - 3, no, tok_end(src, no), C_INT) == C_INT); + assert(ret_step(src, &st, sz, sz, tok_end(src, sz), C_NONE) == C_NONE); +} + +test chain_class_and_expr_class_tell_the_class_of_an_operand_and_of_an_expression { + const head : str = "struct Node { v: u8, name: bool }\nstruct W(u8, bool);\nstruct Tx { value: &'static str }\nconst LIMIT: u32 = 9;\nfn size() -> usize { 1 }\nfn flag() -> bool { true }\nfn done() -> Result<(), E> { Ok(()) }\nfn txt() -> &str { \"a\" }\nfn f(a: u32, b: u32, ok: bool, s: &str, r: f64, n: &Node, w: &W, v: &[u8], x: &Tx) { "; + const chains : [38]str = ["a", "ok", "!ok", "-a", "&s", "&mut s", "*s", "true", "false", "matches!(a, 1)", "cfg!(unix)", "(a)", "(a + b)", "5u8", "5", "size()", "n.v", "n.name", "n.zz", "w.0", "w.1", "w.2", "w.10", "LIMIT", "a + b", "a b", "v[0]", "g()", "\"x\"", "'c'", "r\"x\"", "b\"x\"", "s.is_empty()", "s.len()", "txt()", "flag()", "true x", "matches!(a, 1) x"]; + const chain_want : [38]u8 = [C_INT, C_BOOL, C_BOOL, C_INT, C_STR, C_STR, C_STR, C_BOOL, C_BOOL, C_BOOL, C_BOOL, C_INT, C_INT, C_INT, C_ANY, C_INT, C_INT, C_BOOL, C_ANY, C_INT, C_BOOL, C_ANY, C_ANY, C_INT, C_ANY, C_ANY, C_ANY, C_ANY, C_ANY, C_ANY, C_ANY, C_ANY, C_BOOL, C_ANY, C_STR, C_BOOL, C_ANY, C_ANY]; + var buf : [1024]u8 = [0] ** 1024; + var st : [1024]usize = [0] ** 1024; + var i : usize = 0; + while (i < 38) { + var bs : [64]usize = [0] ** 64; + puts(&bs, &buf, head); + const a : usize = bs[W]; + puts(&bs, &buf, chains[i]); + const b : usize = bs[W]; + puts(&bs, &buf, "; }"); + const src : []const u8 = buf[0 .. bs[W]]; + clear(&st); + st[FLO] = find_tok(src, 0, "f") - 3; + assert(chain_class(src, &st, a, b, true) == chain_want[i]); + i = i + 1; + } + const exprs : [49]str = ["a + b", "a - 1", "a * b / 2 % 3", "a << 2", "a == b", "a != b", "a < b", "a >= b", "ok && flag()", "ok || a > 1", "a + b == 3", "a == 1 && ok", "!ok", "!a", "-a", "a as u8", "a as usize", "a as f64", "a as bool", "a & b", "a | b", "a ^ 1", "ok & flag()", "s & s", "(a + b)", "((a))", "a", "ok", "s", "r", "n", "size()", "txt()", "s.is_empty()", "n.v", "w.0", "5u8", "5", "a b", "|x| x", "move || a", "if a { b }", "g()", "Foo::BAR", "LIMIT", "done()", "&s", "x?", "matches!(a, 1)"]; + const expr_want : [49]u8 = [C_INT, C_INT, C_INT, C_INT, C_BOOL, C_BOOL, C_BOOL, C_BOOL, C_BOOL, C_BOOL, C_BOOL, C_BOOL, C_BOOL, C_INT, C_INT, C_INT, C_INT, C_ANY, C_ANY, C_INT, C_INT, C_INT, C_BOOL, C_ANY, C_INT, C_INT, C_INT, C_BOOL, C_STR, C_FLOAT, C_ANY, C_INT, C_STR, C_BOOL, C_INT, C_INT, C_INT, C_ANY, C_ANY, C_ANY, C_ANY, C_ANY, C_ANY, C_ANY, C_INT, C_ANY, C_STR, C_ANY, C_BOOL]; + var j : usize = 0; + while (j < 49) { + var bs : [64]usize = [0] ** 64; + puts(&bs, &buf, head); + const a : usize = bs[W]; + puts(&bs, &buf, exprs[j]); + const b : usize = bs[W]; + puts(&bs, &buf, "; }"); + const src : []const u8 = buf[0 .. bs[W]]; + clear(&st); + st[FLO] = find_tok(src, 0, "f") - 3; + assert(expr_class(src, &st, a, b, true) == expr_want[j]); + j = j + 1; + } +} + +test class_of_a_name_is_not_looked_up_when_deep_is_off { + const head : str = "struct Node { v: u8, name: bool }\nconst LIMIT: u32 = 9;\nfn size() -> usize { 1 }\nfn flag() -> bool { true }\nfn f(a: u32, ok: bool, s: &str, n: &Node) { "; + const exprs : [14]str = ["a", "ok", "!ok", "(a)", "size()", "flag()", "s.is_empty()", "n.v", "LIMIT", "5u8", "true", "matches!(a, 1)", "a + 1", "a == 1"]; + const want : [14]u8 = [C_ANY, C_ANY, C_ANY, C_ANY, C_INT, C_BOOL, C_BOOL, C_ANY, C_ANY, C_INT, C_BOOL, C_BOOL, C_INT, C_BOOL]; + var buf : [512]u8 = [0] ** 512; + var st : [1024]usize = [0] ** 1024; + var i : usize = 0; + while (i < 14) { + var bs : [64]usize = [0] ** 64; + puts(&bs, &buf, head); + const a : usize = bs[W]; + puts(&bs, &buf, exprs[i]); + const b : usize = bs[W]; + puts(&bs, &buf, "; }"); + const src : []const u8 = buf[0 .. bs[W]]; + clear(&st); + st[FLO] = find_tok(src, 0, "f") - 3; + if (i < 12) { assert(chain_class(src, &st, a, b, false) == want[i]); } + assert(expr_class(src, &st, a, b, false) == want[i]); + i = i + 1; + } +} + +test name_class_reads_a_parameter_a_const_a_typed_let_and_the_literal_a_let_binds { + const head : str = "struct Node { v: u8, name: bool }\nconst LIMIT: u32 = 9;\nfn size() -> usize { 1 }\nfn flag() -> bool { true }\nfn f(a: u32, ok: bool, s: &str, r: f64, n: &Node, v: &[u8]) { let k = 5; let z = 1.5; let t = \"x\"; let h = a == 1; let on = true; let sz = size(); let tr = s.trim(); let q = flag(); let m = 7u8; let mut n2 = 0; let g2 = g(); let x: u16 = 4; "; + const names : [24]str = ["a", "ok", "s", "r", "v", "n", "k", "z", "t", "h", "on", "sz", "tr", "q", "m", "n2", "g2", "x", "LIMIT", "nope", "u8", "f64", "bool", "usize"]; + const want : [24]u8 = [C_INT, C_BOOL, C_STR, C_FLOAT, C_SLICE, C_ANY, C_INT, C_FLOAT, C_STR, C_BOOL, C_BOOL, C_INT, C_STR, C_BOOL, C_INT, C_INT, C_ANY, C_INT, C_INT, C_ANY, C_INT, C_FLOAT, C_BOOL, C_INT]; + var buf : [1024]u8 = [0] ** 1024; + var st : [1024]usize = [0] ** 1024; + var i : usize = 0; + while (i < 24) { + var bs : [64]usize = [0] ** 64; + puts(&bs, &buf, head); + const a : usize = bs[W]; + puts(&bs, &buf, names[i]); + const b : usize = bs[W]; + puts(&bs, &buf, "; }"); + const src : []const u8 = buf[0 .. bs[W]]; + clear(&st); + st[FLO] = find_tok(src, 0, "f") - 3; + assert(name_class(src, &st, a, b, false) == want[i]); + i = i + 1; + } + var st2 : [1024]usize = [0] ** 1024; + const shadow : str = "fn f() { let n = 3; let n = n; n }"; + assert(name_class(shadow, &st2, 28, 29, false) == C_INT); + const arm : str = "fn g(s: &str) { let t = s.trim(); match t { \"a\" => 1, other => 2 } }"; + assert(name_class(arm, &st2, 54, 59, false) == C_STR); + const arm2 : str = "fn g(s: &str) { match s.trim() { \"a\" => 1, other => 2 } }"; + assert(name_class(arm2, &st2, 43, 48, false) == C_ANY); + const arm3 : str = "fn g(n: u8) { match n { 1 => 1, Other => 2 } }"; + assert(name_class(arm3, &st2, 32, 37, false) == C_ANY); +} + +test name_class_of_a_field_reads_the_impl_types_struct { + var st : [1024]usize = [0] ** 1024; + const src : str = "struct Node { v: u8, name: bool, t: &'static str }\nimpl Node { fn m(&self) { self.v; self.name; self.t; self.zz; } }\n"; + st[ILO] = 56; + st[IHI] = 60; + assert(word_is(src, st[ILO], st[IHI], "Node")); + assert(name_class(src, &st, 82, 83, true) == C_INT); + assert(name_class(src, &st, 90, 94, true) == C_BOOL); + assert(name_class(src, &st, 101, 102, true) == C_STR); + assert(name_class(src, &st, 109, 111, true) == C_ANY); + var bare : [1024]usize = [0] ** 1024; + assert(name_class(src, &bare, 82, 83, true) == C_ANY); + var ghost : [1024]usize = [0] ** 1024; + ghost[ILO] = 82; + ghost[IHI] = 83; + assert(name_class(src, &ghost, 82, 83, true) == C_ANY); +} + +test recv_class_classes_a_receiver_and_names_its_integer_type { + const head : str = "struct Node { v: u8, name: bool }\nstruct Tx { value: &'static str }\nconst LIMIT: u32 = 9;\nfn size() -> usize { 1 }\nfn flag() -> bool { true }\nfn done() -> Result<(), E> { Ok(()) }\nfn txt() -> &str { \"a\" }\nfn f(a: u32, ok: bool, s: &str, r: f64, n: &Node, v: &[u8], x: &Tx) { "; + const recvs : [34]str = ["a", "ok", "s", "r", "v", "n", "5", "5u8", "1.5", "\"x\"", "r\"x\"", "(a as u64)", "(a as f64)", "(a + 1)", "s.len()", "v.len()", "n.v", "n.name", "n.zz", "s.trim()", "s.trim().trim_start()", "s.trim().len()", "size()", "flag()", "done()", "txt()", "g()", "a + 1", "r * 2.0", "s[1..]", "x + y", "LIMIT", "x.value.trim()", "x.value"]; + const want : [34]u8 = [C_INT, C_BOOL, C_STR, C_FLOAT, C_SLICE, C_ANY, C_INT, C_INT, C_FLOAT, C_STR, C_STR, C_INT, C_FLOAT, C_INT, C_INT, C_INT, C_INT, C_BOOL, C_ANY, C_STR, C_STR, C_INT, C_INT, C_BOOL, C_BOOL, C_STR, C_ANY, C_INT, C_FLOAT, C_STR, C_ANY, C_INT, C_STR, C_STR]; + const ty : [34]str = ["u32", "", "", "f64", "u8", "", "", "u8", "", "", "", "u64", "f64", "u32", "", "", "u8", "", "", "", "", "", "usize", "", "", "", "", "u32", "f64", "", "", "u32", "", ""]; + var buf : [1024]u8 = [0] ** 1024; + var st : [1024]usize = [0] ** 1024; + var i : usize = 0; + while (i < 34) { + var bs : [64]usize = [0] ** 64; + puts(&bs, &buf, head); + const a : usize = bs[W]; + puts(&bs, &buf, recvs[i]); + const b : usize = bs[W]; + puts(&bs, &buf, "; }"); + const src : []const u8 = buf[0 .. bs[W]]; + clear(&st); + st[FLO] = find_tok(src, 0, "f") - 3; + assert(recv_class(src, &st, a, b) == want[i]); + if (ty[i].len == 0) { + assert(st[TYHI] == st[TYLO]); + } else { + assert(word_is(src, st[TYLO], st[TYHI], ty[i])); + } + i = i + 1; + } +} + +test recv_class_marks_a_len_call_and_an_array_and_reads_self_fields { + var st : [1024]usize = [0] ** 1024; + const lens : str = "fn f(s: &str, v: &[u8]) { s.len(); v.len(); s.trim().len(); }"; + assert(recv_class(lens, &st, 26, 33) == C_INT); + assert(st[TYARR] == 2); + assert(st[TYLO] == 0); + assert(st[TYHI] == 0); + assert(recv_class(lens, &st, 35, 42) == C_INT); + assert(st[TYARR] == 2); + assert(recv_class(lens, &st, 44, 58) == C_INT); + assert(st[TYARR] == 2); + const own : str = "fn len(x: u8) -> bool { true }\nfn f(s: &str) { s.len(); }"; + assert(recv_class(own, &st, 47, 54) != C_INT); + assert(st[TYARR] == 0); + const arr : str = "fn f(a: [u8; 4], b: &[u8; 4], c: &[u8]) { a; b; c; }"; + assert(recv_class(arr, &st, 42, 43) == C_SLICE); + assert(st[TYARR] == 1); + assert(word_is(arr, st[TYLO], st[TYHI], "u8")); + assert(recv_class(arr, &st, 45, 46) == C_SLICE); + assert(st[TYARR] == 0); + assert(recv_class(arr, &st, 48, 49) == C_SLICE); + assert(st[TYARR] == 0); + assert(recv_class(arr, &st, 48, 48) == C_ANY); + assert(recv_class(arr, &st, 60, 70) == C_ANY); + assert(recv_class("", &st, 0, 0) == C_ANY); + const sf : str = "struct Node { v: u8, name: bool }\nimpl Node { fn m(&self) { self.v; self.name; self.zz; } }\n"; + var si : [1024]usize = [0] ** 1024; + si[ILO] = 39; + si[IHI] = 43; + assert(word_is(sf, si[ILO], si[IHI], "Node")); + assert(recv_class(sf, &si, 60, 66) == C_INT); + assert(word_is(sf, si[TYLO], si[TYHI], "u8")); + assert(recv_class(sf, &si, 68, 77) == C_BOOL); + assert(recv_class(sf, &si, 79, 86) == C_ANY); +} + +test field_of_class_reads_the_field_of_the_struct_a_name_is_declared_with { + const head : str = "struct Node { v: u8, name: bool, ratio: f64 }\nstruct Tx { value: &'static str }\nconst ORIGIN: Node = Node { v: 0, name: false, ratio: 0.0 };\nconst LIMIT: u32 = 9;\nfn f(a: u32, n: &Node, m: &'a mut Node, x: &Tx) { "; + const objs : [10]str = ["n", "n", "n", "n", "m", "x", "a", "q", "ORIGIN", "LIMIT"]; + const fields : [10]str = ["v", "name", "ratio", "zz", "v", "value", "v", "v", "name", "v"]; + const want : [10]u8 = [C_INT, C_BOOL, C_FLOAT, C_ANY, C_INT, C_STR, C_ANY, C_ANY, C_BOOL, C_ANY]; + var buf : [1024]u8 = [0] ** 1024; + var st : [1024]usize = [0] ** 1024; + var i : usize = 0; + while (i < 10) { + var bs : [64]usize = [0] ** 64; + puts(&bs, &buf, head); + const xa : usize = bs[W]; + puts(&bs, &buf, objs[i]); + const xe : usize = bs[W]; + puts(&bs, &buf, "."); + const fa : usize = bs[W]; + puts(&bs, &buf, fields[i]); + const fe : usize = bs[W]; + puts(&bs, &buf, "; }"); + const src : []const u8 = buf[0 .. bs[W]]; + clear(&st); + st[FLO] = find_tok(src, 0, "f") - 3; + assert(field_of_class(src, &st, xa, xe, fa, fe) == want[i]); + i = i + 1; + } +} + +test str_chain_follows_a_text_through_the_text_keeping_methods { + const head : str = "struct Tx { value: &'static str }\nfn txt() -> &str { \"a\" }\nfn f(a: u32, s: &str, x: &Tx) { let t = "; + const inits : [14]str = ["s", "s.trim()", "s.clone().as_str()", "s.trim().trim_start()", "s.chars()", "s.trim_start_matches(\"x\")", "s.trim_end().trim_end_matches(\"y\")", "s.trim().len()", "a.trim()", "s.len()", "\"x\"", "txt()", "s.trim", "s.trim( ).clone"]; + const want : [14]bool = [true, true, true, true, true, true, true, false, false, false, false, false, false, false]; + var buf : [1024]u8 = [0] ** 1024; + var st : [1024]usize = [0] ** 1024; + var i : usize = 0; + while (i < 14) { + var bs : [64]usize = [0] ** 64; + puts(&bs, &buf, head); + const a : usize = bs[W]; + puts(&bs, &buf, inits[i]); + const b : usize = bs[W]; + puts(&bs, &buf, "; }"); + const src : []const u8 = buf[0 .. bs[W]]; + clear(&st); + st[FLO] = find_tok(src, 0, "f") - 3; + assert(str_chain(src, &st, a, b) == want[i]); + i = i + 1; + } + var bs2 : [64]usize = [0] ** 64; + puts(&bs2, &buf, head); + const a2 : usize = bs2[W]; + puts(&bs2, &buf, "s.trim(); }"); + const src2 : []const u8 = buf[0 .. bs2[W]]; + clear(&st); + st[FLO] = find_tok(src2, 0, "f") - 3; + assert(str_chain(src2, &st, a2, a2 + 8)); + assert(!str_chain(src2, &st, a2, a2 + 7)); + assert(str_chain(src2, &st, a2, a2 + 1)); + assert(!str_chain(src2, &st, src2.len, src2.len)); + assert(!str_chain(src2, &st, a2 + 1, a2 + 8)); +} + +test known_defect_str_chain_does_not_open_with_a_text_field { + // #10834: str_chain asks for a `(` after the field name, so `x.value.trim()` (a text field of x's struct, + // trimmed) is not a text chain here although recv_class reads the same chain as one; the `let t = x.value.trim();` + // binding is then no text. When that is fixed the first assert flips. + const head : str = "struct Tx { value: &'static str }\nfn f(x: &Tx) { let t = "; + var buf : [256]u8 = [0] ** 256; + var bs : [64]usize = [0] ** 64; + puts(&bs, &buf, head); + const a : usize = bs[W]; + puts(&bs, &buf, "x.value.trim()"); + const b : usize = bs[W]; + puts(&bs, &buf, "; }"); + const src : []const u8 = buf[0 .. bs[W]]; + var st : [1024]usize = [0] ** 1024; + st[FLO] = find_tok(src, 0, "f") - 3; + assert(!str_chain(src, &st, a, b)); + assert(field_of_class(src, &st, a, a + 1, a + 2, a + 7) == C_STR); + assert(recv_class(src, &st, a, b) == C_STR); +} + +test head_struct_names_the_struct_a_receiver_is_of { + const head : str = "struct Node { v: u8 }\nstruct W(u8);\nstruct Tx { value: &'static str }\nconst ORIGIN: Node = Node { v: 0 };\nfn f(n: &Node, w: &W, x: &'a mut Tx, a: u32, r: f64) { let l = Node::make(); let u = 5; "; + const names : [10]str = ["n", "w", "x", "a", "r", "ORIGIN", "l", "u", "q", "self"]; + var buf : [1024]u8 = [0] ** 1024; + var st : [1024]usize = [0] ** 1024; + var i : usize = 0; + while (i < 10) { + var bs : [64]usize = [0] ** 64; + puts(&bs, &buf, head); + const xa : usize = bs[W]; + puts(&bs, &buf, names[i]); + const xe : usize = bs[W]; + puts(&bs, &buf, "; }"); + const src : []const u8 = buf[0 .. bs[W]]; + clear(&st); + const node : usize = find_at(src, 0, B_LBRACE); + const wp : usize = find_at(src, 0, B_LPAREN); + const tx : usize = find_at(src, find_tok(src, 0, "Tx"), B_LBRACE); + const flo : usize = find_tok(src, 0, "f") - 3; + const nn : usize = find_tok(src, 0, "Node"); + const want : [10]usize = [node, wp, tx, src.len, src.len, node, node, src.len, src.len, node]; + assert(head_struct(src, &st, flo, nn, nn + 4, xa, xe) == want[i]); + assert(head_struct(src, &st, flo, nn, nn, xa, xe) == (if (i == 9) { src.len } else { want[i] })); + i = i + 1; + } +} From bbe936a99ba2a444235282cbdacb687c03620878 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 19 Oct 2026 11:30:03 +0700 Subject: [PATCH 5/8] t27o: direct tests for the expression engine and the literal writers of rust_convert.t27 -- operators, calls, std methods, paths, literals, cfg, plus known-defect tests for the int_type_names splice alias (Closes #10825) Tests only; no non-test line changes. The splice alias defect is #10843. Co-Authored-By: Claude Sonnet 5.5 --- specs/tools/t27o/rust_convert.t27 | 1478 +++++++++++++++++++++++++++++ 1 file changed, 1478 insertions(+) diff --git a/specs/tools/t27o/rust_convert.t27 b/specs/tools/t27o/rust_convert.t27 index 446d4718b1..1e3a5d44b3 100644 --- a/specs/tools/t27o/rust_convert.t27 +++ b/specs/tools/t27o/rust_convert.t27 @@ -13227,3 +13227,1481 @@ test head_struct_names_the_struct_a_receiver_is_of { i = i + 1; } } + +// ---------------------------------------------------------------- direct tests: expression helpers + +test op_level_and_keep_bare_order_the_binary_operators { + const ops : [28]str = ["<", ">", "|", "^", "&", "+", "-", "*", "/", "%", "||", "&&", "==", "!=", "<=", ">=", "<<", ">>", "as", "!", "=", ".", ",", "+=", "->", "=>", "::", ".."]; + const lvl : [28]usize = [L_CMP, L_CMP, L_BOR, L_XOR, L_BAND, L_ADD, L_ADD, L_MUL, L_MUL, L_MUL, L_OR, L_AND, L_CMP, L_CMP, L_CMP, L_CMP, L_SHIFT, L_SHIFT, L_AS, 0, 0, 0, 0, 0, 0, 0, 0, 0]; + var i : usize = 0; + while (i < 28) { + assert(op_level(ops[i], 0, ops[i].len) == lvl[i]); + i = i + 1; + } + assert(op_level("ab", 0, 2) == 0); + assert(op_level("a + b", 2, 3) == L_ADD); + assert(op_level("a + b", 0, 1) == 0); + assert(op_level("x as", 2, 4) == L_AS); + assert(op_level("ass", 0, 3) == 0); + assert(keep_bare(L_ATOM, L_OR, true)); + assert(keep_bare(L_ATOM, L_UNARY, false)); + assert(keep_bare(L_UNARY, L_MUL, false)); + assert(keep_bare(L_ADD, L_ADD, true)); + assert(!keep_bare(L_ADD, L_ADD, false)); + assert(keep_bare(L_OR, L_OR, true)); + assert(!keep_bare(L_CMP, L_CMP, true)); + assert(!keep_bare(L_AS, L_AS, true)); + assert(keep_bare(L_MUL, L_ADD, false)); + assert(!keep_bare(L_ADD, L_MUL, true)); + assert(keep_bare(L_AND, L_OR, false)); + assert(!keep_bare(L_OR, L_AND, true)); + assert(keep_bare(L_CMP, L_AND, false)); + assert(keep_bare(L_ADD, L_SHIFT, false)); + assert(!keep_bare(L_SHIFT, L_ADD, true)); + assert(!keep_bare(L_BOR, L_OR, true)); + assert(!keep_bare(L_XOR, L_AND, false)); + assert(!keep_bare(L_BAND, L_CMP, true)); + assert(!keep_bare(L_AS, L_MUL, true)); + assert(!keep_bare(L_ADD, L_BOR, true)); + assert(!keep_bare(L_MUL, L_BAND, false)); + assert(!keep_bare(L_CMP, L_XOR, false)); + assert(keep_bare(L_BOR, L_BOR, true)); + assert(!keep_bare(L_BOR, L_BOR, false)); +} + +test str_tok_bit_use_mod_and_wrap_pct_small_helpers { + assert(str_tok("\"x\"", 0)); + assert(str_tok("b\"x\"", 0)); + assert(str_tok("a \"x\"", 2)); + assert(!str_tok("b'x'", 0)); + assert(!str_tok("x", 0)); + assert(!str_tok("b", 0)); + assert(!str_tok("br\"x\"", 0)); + assert(!str_tok("\"x\"", 3)); + assert(!str_tok("", 0)); + assert(bit(0) == 1); + assert(bit(1) == 2); + assert(bit(4) == 16); + assert(bit(10) == 1024); + assert(bit(20) == 1048576); + var st : [64]usize = [0] ** 64; + use_mod(&st, 0); + assert(st[USES] == 0); + use_mod(&st, 1); + assert(st[USES] == 2); + use_mod(&st, 1); + assert(st[USES] == 2); + use_mod(&st, 3); + assert(st[USES] == 10); + use_mod(&st, 4); + assert(st[USES] == 26); + use_mod(&st, 3); + use_mod(&st, 0); + assert(st[USES] == 26); + assert(wrap_pct("(# *% $)", 4)); + assert(wrap_pct("(# +% $)", 4)); + assert(wrap_pct("(# -% $)", 4)); + assert(!wrap_pct("abs_%(#)", 4)); + assert(!wrap_pct("%", 0)); + assert(!wrap_pct("(# /% $)", 4)); + assert(!wrap_pct("", 0)); +} + +test insert_byte_put_char_text_and_out_holds_edit_and_read_the_output { + var out : [16]u8 = undefined; + var st : [64]usize = [0] ** 64; + puts(&st, &out, "ac"); + insert_byte(&st, &out, 1, B_LOWER_B); + assert(out_is(st[W], &out, 0, "abc")); + insert_byte(&st, &out, 0, B_LOWER_Z); + assert(out_is(st[W], &out, 0, "zabc")); + insert_byte(&st, &out, 4, B_LOWER_Z); + assert(out_is(st[W], &out, 0, "zabcz")); + var tiny : [3]u8 = undefined; + var ts : [64]usize = [0] ** 64; + puts(&ts, &tiny, "ac"); + insert_byte(&ts, &tiny, 1, B_LOWER_B); + insert_byte(&ts, &tiny, 0, B_LOWER_Z); + assert(ts[W] == 4); + assert(tiny[0] == B_LOWER_A); + assert(tiny[1] == B_LOWER_B); + assert(tiny[2] == B_LOWER_A + 2); + assert(out_holds("abc", 0, "ab")); + assert(out_holds("abc", 1, "bc")); + assert(out_holds("abc", 0, "abc")); + assert(out_holds("abc", 3, "")); + assert(out_holds("abc", 0, "")); + assert(!out_holds("abc", 2, "cd")); + assert(!out_holds("abc", 0, "ac")); + assert(!out_holds("abc", 4, "")); + assert(!out_holds("abc", 0, "abcd")); + assert(!out_holds("", 0, "a")); + const lits : [7]str = ["'('", "'a'", "'\\n'", "'\\\\'", "'\"'", "'\\\"'", "'\\''"]; + const want : [7]str = ["\"(\"", "\"a\"", "\"\\n\"", "\"\\\\\"", "\"\\\"\"", "\"\\\"\"", "\"\\'\""]; + var i : usize = 0; + while (i < 7) { + clear(&st); + put_char_text(lits[i], &st, &out); + assert(out_is(st[W], &out, 0, want[i])); + assert(st[P] == lits[i].len); + assert(st[ERR] == 0); + i = i + 1; + } + clear(&st); + st[P] = 2; + put_char_text("x 'b' y", &st, &out); + assert(out_is(st[W], &out, 0, "\"b\"")); + assert(st[P] == 5); +} + +test pure_callee_and_pure_out_accept_only_the_std_tables_helpers { + assert(pure_callee("@min(a, b)", 0)); + assert(pure_callee("rust_std::abs_i32(x)", 0)); + assert(pure_callee("type_text::same(a, b)", 0)); + assert(pure_callee("toolchain::starts_with(a, b)", 0)); + assert(pure_callee("x @abs(y)", 2)); + assert(!pure_callee("rust_std::append_uint(o, v)", 0)); + assert(!pure_callee("foo(x)", 0)); + assert(!pure_callee("rust_std(x)", 0)); + assert(!pure_callee("rust_stdx::f(x)", 0)); + assert(pure_out("(a + b)", 0, 7)); + assert(pure_out("a + b", 0, 5)); + assert(pure_out("@abs(x)", 0, 7)); + assert(pure_out("type_text::trim_lo(x, 0, x.len)", 0, 31)); + assert(pure_out("(@abs(x) + (y))", 0, 15)); + assert(pure_out("rust_std::pow_u32(x, 2)", 0, 23)); + assert(!pure_out("foo(x)", 0, 6)); + assert(!pure_out("rust_std::append_uint(o, v)", 0, 27)); + assert(!pure_out("f.g(x)", 0, 6)); + assert(!pure_out("a + foo(x)", 0, 10)); + assert(!pure_out("(@abs(foo(x)))", 0, 14)); + assert(pure_out("foo(x)", 0, 0)); + assert(pure_out("foo(x)", 4, 6)); + assert(pure_out("foo(x)", 0, 99)); + assert(pure_out("", 0, 0)); + assert(find_ty("pow", C_INT, "u32", 0, 3, false) == 58); + assert(find_ty("pow", C_INT, "f64", 0, 3, false) == STD_N); + assert(find_ty("pow", C_INT, "f64", 0, 3, true) == 58); + assert(find_ty("pow", C_INT, "", 0, 0, true) == 58); + assert(find_ty("len", C_STR, "", 0, 0, false) == 0); + assert(find_ty("abs", C_INT, "x i32", 2, 5, false) == 7); + assert(find_ty("abs", C_INT, "x u32", 2, 5, false) == STD_N); +} + +test array_local_finds_a_name_declared_as_an_array_or_a_read_only_vec { + const src : str = "fn f() { let a: [u8; 4] = x; let b = [1, 2]; let c = vec![1, 2]; let d: Vec = vec![1]; let e = 5; a; b; c; d; e; x; }"; + assert(array_local(src, 0, 102, 103)); + assert(array_local(src, 0, 105, 106)); + assert(array_local(src, 0, 108, 109)); + assert(array_local(src, 0, 111, 112)); + assert(!array_local(src, 0, 114, 115)); + assert(!array_local(src, 0, 117, 118)); + assert(!array_local(src, 9, 114, 115)); + assert(!array_local(src, 121, 102, 103)); + assert(!array_local(src, 0, 12, 13)); + assert(!array_local(src, 0, 0, 0)); + assert(array_local(src, 0, 102, 103) == array_local(src, 5, 102, 103)); + assert(!array_local(src, 40, 102, 103)); +} + +test init_at_and_vec_init_read_the_value_of_a_let { + assert(init_at("let a = 5;", 0) == 8); + assert(init_at("let a: u8 = 5;", 0) == 12); + assert(init_at("let a = vec![1];", 4) == 8); + assert(init_at("let a;", 0) == 6); + assert(init_at("let a == b;", 0) == 11); + assert(init_at("let a = (b = 1);", 0) == 8); + assert(init_at("x = 1; let b = 2;", 7) == 15); + assert(init_at("", 0) == 0); + assert(vec_init("vec![1, 2];", 0)); + assert(vec_init("vec![0; 3];", 0)); + assert(vec_init("vec ! [1];", 0)); + assert(vec_init("a = vec![1];", 4)); + assert(!vec_init("vec![1] x", 0)); + assert(!vec_init("vec![1]", 0)); + assert(!vec_init("vec![1].len();", 0)); + assert(!vec_init("vec(1);", 0)); + assert(!vec_init("vec!(1);", 0)); + assert(!vec_init("x;", 0)); + assert(!vec_init("vec![1];", 8)); + assert(!vec_init("", 0)); +} + +test open_before_empty_ref_and_param_at_read_an_argument_list { + assert(open_before("f(a)", 2) == 1); + assert(open_before("f( a)", 3) == 1); + assert(open_before("f(\n\ta)", 4) == 1); + assert(open_before("f(a, b)", 5) == 7); + assert(open_before("a", 0) == 1); + assert(open_before("(a)", 1) == 0); + assert(open_before("f[a]", 2) == 4); + assert(empty_ref("&[],", 0)); + assert(empty_ref("&[])", 0)); + assert(empty_ref("& [ ] )", 0)); + assert(empty_ref("f(&[], x)", 2)); + assert(!empty_ref("&[] x", 0)); + assert(!empty_ref("&[1],", 0)); + assert(!empty_ref("[],", 0)); + assert(!empty_ref("&x,", 0)); + assert(!empty_ref("&[]", 0)); + assert(!empty_ref("&mut [],", 0)); + assert(!empty_ref("&[", 0)); + assert(!empty_ref("&", 0)); + assert(!empty_ref("", 0)); + assert(param_at("fn f(a: u8, b: &[u8], c: u32) {}", 4, 0) == 5); + assert(param_at("fn f(a: u8, b: &[u8], c: u32) {}", 4, 1) == 12); + assert(param_at("fn f(a: u8, b: &[u8], c: u32) {}", 4, 2) == 22); + assert(param_at("fn f(a: u8, b: &[u8], c: u32) {}", 4, 3) == 32); + assert(param_at("fn f(a: Vec, b: u8) {}", 4, 0) == 26); + assert(param_at("fn f(a: Vec, b: u8) {}", 4, 1) == 26); + assert(param_at("fn f(a: (u8, u8), b: u8) {}", 4, 1) == 18); + assert(param_at("fn f(&self, x: u8) {}", 4, 0) == 5); + assert(param_at("fn f(&self, x: u8) {}", 4, 1) == 12); + assert(param_at("fn f() {}", 4, 0) == 9); + assert(param_at("fn f(a: u8,) {}", 4, 0) == 5); + assert(param_at("fn f(a: u8,) {}", 4, 1) == 15); +} + +test decl_slice_elem_and_slice_param_elem_find_the_element_type_of_a_slice_parameter { + const d : str = "fn f(a: u8, v: &[u32], w: &'a [i8], x: &mut [u8], y: &[&str], z: &[u8; 4], t: u8) {}"; + assert(decl_slice_elem(d, 4, false, 1) == 17); + assert(decl_slice_elem(d, 4, false, 2) == 31); + assert(decl_slice_elem(d, 4, false, 0) == d.len); + assert(decl_slice_elem(d, 4, false, 3) == d.len); + assert(decl_slice_elem(d, 4, false, 4) == d.len); + assert(decl_slice_elem(d, 4, false, 5) == d.len); + assert(decl_slice_elem(d, 4, false, 6) == d.len); + assert(decl_slice_elem(d, 4, false, 99) == d.len); + assert(decl_slice_elem(d, 4, true, 0) == d.len); + assert(decl_slice_elem("fn m(&self, a: &[u8], b: u8) {}", 4, true, 0) == 17); + assert(decl_slice_elem("fn m(&self, a: &[u8], b: u8) {}", 4, true, 1) == 31); + assert(decl_slice_elem("fn m(&'a mut self, a: &[u8]) {}", 4, true, 0) == 24); + assert(decl_slice_elem("fn m(self, a: &[u16]) {}", 4, true, 0) == 16); + assert(decl_slice_elem("fn m(&mut self, a: &[u16]) {}", 4, true, 0) == 21); + assert(decl_slice_elem("fn m(a: &[u8]) {}", 4, true, 0) == 17); + assert(decl_slice_elem("fn m(a: &[u8]) {}", 4, false, 0) == 10); + assert(decl_slice_elem("fn m(a u8) {}", 4, false, 0) == 13); + const s : str = "fn g(v: &[u8]) {}\nfn g(v: &[u8]) {}\nfn h(v: &[u8]) {}\nfn h(v: &[u32]) {}\nfn k(v: u8) {}\nfn q(a: u8, v: &[u16]) {}\nimpl A { fn q(&self, v: &[u16]) {} }\ng h k q none\n"; + assert(slice_param_elem(s, 151, 152, false, 0) == 28); + assert(slice_param_elem(s, 153, 154, false, 0) == s.len); + assert(slice_param_elem(s, 155, 156, false, 0) == s.len); + assert(slice_param_elem(s, 157, 158, false, 1) == 140); + assert(slice_param_elem(s, 157, 158, true, 0) == s.len); + assert(slice_param_elem(s, 159, 163, false, 0) == s.len); + assert(slice_param_elem(s, 151, 152, false, 1) == s.len); +} + +test site_elem_empty_arg_and_arg_expr_write_an_empty_slice_of_the_parameters_type { + const s : str = "impl A { fn m(&self, v: &[u8]) {} }\nfn g(v: &[u8]) {}\nfn f(a: A) { g(&[]); a.m(&[]); a..g(&[]); h(&[]); }"; + assert(site_elem(s, 68, 0) == 46); + assert(site_elem(s, 78, 0) == 26); + assert(site_elem(s, 89, 0) == 46); + assert(site_elem(s, 97, 0) == s.len); + assert(site_elem(s, 68, 1) == s.len); + assert(site_elem(s, s.len, 0) == s.len); + assert(site_elem(s, 0, 0) == s.len); + assert(site_elem("fn g(v: &[u8]) {}\nfn f() { g (&[]); }", 29, 0) == 10); + const e : str = "fn g(v: &[u8], x: u8) {}\nfn f() { g(&[], 1); g(2, &[]); h(&[]); }"; + var out : [64]u8 = undefined; + var st : [64]usize = [0] ** 64; + st[P] = 36; + empty_arg(e, &st, &out, 35, 0); + assert(out_is(st[W], &out, 0, "[0]u8{}")); + assert(st[ERR] == 0); + assert(st[P] == 39); + clear(&st); + st[P] = 50; + empty_arg(e, &st, &out, 46, 1); + assert(st[ERR] == R_EMPTY); + assert(st[AT] == 50); + assert(st[NLO] == 50); + assert(st[NHI] == 53); + assert(st[W] == 0); + clear(&st); + st[P] = 58; + empty_arg(e, &st, &out, 57, 0); + assert(st[ERR] == R_EMPTY); + clear(&st); + st[P] = 36; + arg_expr(e, &st, &out, 35, 0); + assert(out_is(st[W], &out, 0, "[0]u8{}")); + clear(&st); + st[P] = 2; + arg_expr("f(x, 2 + y)", &st, &out, 1, 0); + assert(out_is(st[W], &out, 0, "x")); + assert(st[P] == 3); + clear(&st); + st[P] = 5; + arg_expr("f(x, 2 + y)", &st, &out, 1, 1); + assert(out_is(st[W], &out, 0, "2 + y")); + clear(&st); + no_args("()", &st); + assert(st[ERR] == 0); + assert(st[P] == 2); + clear(&st); + no_args("(x)", &st); + assert(st[ERR] == R_SYNTAX); + assert(st[AT] == 1); + clear(&st); + no_args("x", &st); + assert(st[ERR] == R_SYNTAX); + assert(st[AT] == 0); +} + +test all_closure_digit_closure_and_char_var_read_the_closure_and_the_char_a_needle_names { + assert(all_closure("(|c| c.is_ascii_digit())", 0) == 1); + assert(all_closure("(|c: char| c.is_ascii_digit())", 0) == 1); + assert(all_closure("( | ch | ch.is_ascii_digit() )", 0) == 1); + assert(all_closure("(|c| c.is_ascii_alphanumeric() || c == '_')", 0) == 2); + assert(all_closure("(|c: char| c.is_ascii_alphanumeric() || c == '_' )", 0) == 2); + assert(all_closure("x(|c| c.is_ascii_digit())", 1) == 1); + assert(all_closure("(|c| d.is_ascii_digit())", 0) == 0); + assert(all_closure("(|c: u8| c.is_ascii_digit())", 0) == 0); + assert(all_closure("(|c| c.is_ascii_digit() && x)", 0) == 0); + assert(all_closure("(|c| c.is_ascii_alphanumeric() || c == 'x')", 0) == 0); + assert(all_closure("(|c| c.is_ascii_alphanumeric() || d == '_')", 0) == 0); + assert(all_closure("(|c| c.is_ascii_alphanumeric() || c == '_'", 0) == 0); + assert(all_closure("(|c| c.is_ascii_alphabetic())", 0) == 0); + assert(all_closure("(c)", 0) == 0); + assert(all_closure("(|1| 1)", 0) == 0); + assert(all_closure("(|c", 0) == 0); + assert(all_closure("(", 0) == 0); + assert(all_closure("", 0) == 0); + assert(digit_closure("(|c| c.is_ascii_digit())", 0)); + assert(digit_closure("(|c: char| c.is_ascii_digit())", 0)); + assert(!digit_closure("(|c| c.is_ascii_alphanumeric() || c == '_')", 0)); + assert(!digit_closure("(|c| c)", 0)); + assert(!digit_closure("(x)", 0)); + const src : str = "fn f(c: char, n: u32) { s.contains(c); s.contains(n); s.contains(c, d); s.contains('x'); s.contains(z); s.contains(c ); }"; + assert(char_var(src, 0, 35)); + assert(!char_var(src, 0, 50)); + assert(!char_var(src, 0, 65)); + assert(!char_var(src, 0, 83)); + assert(!char_var(src, 0, 100)); + assert(char_var(src, 0, 115)); + assert(!char_var(src, 0, src.len)); + assert(!char_var(src, 0, 0)); + assert(!char_var(src, 40, 35)); +} + +// ---------------------------------------------------------------- direct tests: the expression engine + +test expr_writes_operators_with_the_parentheses_t27_needs { + const head : str = "struct Node { v: u8, name: bool }\nstruct W(u8, bool);\nconst LIMIT: u32 = 9;\nfn size() -> usize { 1 }\nfn g(x: u32) -> u32 { x }\nfn f(a: u32, b: u32, ok: bool, s: &str, n: &Node, w: &W, v: &[u8]) { "; + const ins : [40]str = ["a + b * 2", "(a + b) * 2", "a - (b - 1)", "a - b - 1", "a * b + 1", "a == b && ok", "ok || a > 1", "a << 2 + 1", "a & b == 3", "a as u64 + 1", "a as u8", "a | b ^ 1", "-a", "-(a + 1)", "!ok", "!a", "!(a == 1)", "!(a & 1)", "*s", "&s", "&v", "n.v", "w.0", "n.v + 1", "v[0]", "size()", "g(a, b + 1)", "g(a,)", "Some(a)", "Some(a + 1)", "None", "true", "LIMIT", "5u8", "1_000", "'x'", "b'x'", "\"x\"", "a != b || a < b", "a % 3 / 2"]; + const outs : [40]str = ["a + b * 2", "(a + b) * 2", "a - (b - 1)", "a - b - 1", "a * b + 1", "a == b and ok", "ok or a > 1", "a << 2 + 1", "(a & b) == 3", "(a as u64) + 1", "a as u8", "a | (b ^ 1)", "-a", "(0 - (a + 1))", "!ok", "~a", "((a == 1) == false)", "~(a & 1)", "s", "s", "v", "n.v", "w._0", "n.v + 1", "v[0]", "size()", "g(a, b + 1)", "g(a)", "a", "(a + 1)", "null", "true", "LIMIT", "@as(u8, 5)", "1000", "'x'", "'x'", "\"x\"", "a != b or a < b", "a % 3 / 2"]; + var buf : [1024]u8 = [0] ** 1024; + var st : [1024]usize = [0] ** 1024; + var out : [256]u8 = undefined; + var i : usize = 0; + while (i < 40) { + var bs : [64]usize = [0] ** 64; + puts(&bs, &buf, head); + const a : usize = bs[W]; + puts(&bs, &buf, ins[i]); + const b : usize = bs[W]; + puts(&bs, &buf, "; }"); + const src : []const u8 = buf[0 .. bs[W]]; + clear(&st); + st[FLO] = find_tok(src, 0, "f") - 3; + st[P] = a; + expr(src, &st, &out, false); + assert(st[ERR] == 0); + assert(out_is(st[W], &out, 0, outs[i])); + assert(st[P] == b); + i = i + 1; + } +} + +test expr_writes_texts_ranges_paths_literals_and_cfg { + const head : str = "struct Node { v: u8, name: bool }\nfn g(x: u32) -> u32 { x }\nfn f(a: u32, b: u32, s: &str, n: &Node, v: &[u8]) { "; + const ins : [41]str = ["s == \"x\"", "\"x\" == s", "s != \"x\"", "s == r\"x\"", "s == b\"x\"", "v[1..3]", "v[..2]", "v[1..]", "v[..=2]", "v[1..=a]", "v[..]", "s[a..]", "v[a + 1..b]", "u32::MAX", "i8::MIN", "u8::MIN", "i64::MAX", "Node::new(1)", "Node::Kind", "Node::MAX_SIZE", "cmp::max(a, b)", "std::cmp::min(a, b)", "super::g(a)", "self::LIMIT", "crate::g(a)", "Node { v: 1, name }", "Node { }", "[1, 2, 3]", "[0; 4]", "[a; b + 1]", "(a)", "s.len()", "s.is_empty()", "a.wrapping_add(b)", "a.pow(2)", "cfg!(unix)", "cfg!(windows)", "cfg!(not(windows))", "cfg!(all(unix, target_os = \"linux\"))", "cfg!(any(windows, target_os = \"macos\"))", "n.name"]; + const outs : [41]str = ["type_text::same(s, \"x\")", "type_text::same(\"x\", s)", "!type_text::same(s, \"x\")", "type_text::same(s, \"x\")", "type_text::same(s, \"x\")", "v[1 .. 3]", "v[0 .. 2]", "v[1 .. v.len]", "v[0 .. 2 + 1]", "v[1 .. a + 1]", "v", "s[a .. s.len]", "v[a + 1 .. b]", "4294967295", "(-128)", "0", "9223372036854775807", "Node_new(1)", "Node.Kind", "Node_MAX_SIZE", "@max(a, b)", "@min(a, b)", "g(a)", "LIMIT", "g(a)", "Node{ .v = 1, .name = name }", "Node{}", "[1, 2, 3]", "[0] ** 4", "[a] ** (b + 1)", "(a)", "s.len", "(s.len == 0)", "(a +% b)", "rust_std::pow_u32(a, 2)", "true", "false", "true", "true", "false", "n.name"]; + var buf : [1024]u8 = [0] ** 1024; + var st : [1024]usize = [0] ** 1024; + var out : [256]u8 = undefined; + var i : usize = 0; + while (i < 41) { + var bs : [64]usize = [0] ** 64; + puts(&bs, &buf, head); + const a : usize = bs[W]; + puts(&bs, &buf, ins[i]); + const b : usize = bs[W]; + puts(&bs, &buf, "; }"); + const src : []const u8 = buf[0 .. bs[W]]; + clear(&st); + st[FLO] = find_tok(src, 0, "f") - 3; + st[P] = a; + expr(src, &st, &out, false); + assert(st[ERR] == 0); + assert(out_is(st[W], &out, 0, outs[i])); + assert(st[P] == b); + i = i + 1; + } +} + +test expr_refuses_with_the_construct_it_cannot_write { + const head : str = "struct Node { v: u8, name: bool }\nfn f(a: u32, s: &str, n: &Node, v: &[u8]) { "; + const ins : [24]str = ["a +", "|x| x", "move || a", "if a { b }", "{ a }", "unsafe { a }", "foo!(a)", "(a, b)", "()", "Foo(a)", "a?", "a as i128", "&mut s", "a.0.1", "n.v::", "u32::new()", "f64::MAX", "a::b::c", "Vec::::new()", "foo::bar(1)", "[]", "r#x", "a.(", "[1, 2"]; + const code : [24]usize = [R_SYNTAX, R_CLOSURE, R_CLOSURE, R_VALUE, R_VALUE, R_UNSAFE, R_MACRO, R_TUPLE, R_TUPLE, R_TUPLE, R_TRY, R_TYPE, R_MUTREF, R_TUPLE, R_GENERIC, R_PATH, R_PATH, R_PATH, R_GENERIC, R_EXTERNAL, R_EMPTY, R_LITERAL, R_TUPLE, R_SYNTAX]; + const off : [24]usize = [3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 5, 5, 2, 6, 0, 0, 0, 5, 0, 0, 0, 2, 5]; + var buf : [1024]u8 = [0] ** 1024; + var st : [1024]usize = [0] ** 1024; + var out : [256]u8 = undefined; + var i : usize = 0; + while (i < 24) { + var bs : [64]usize = [0] ** 64; + puts(&bs, &buf, head); + const a : usize = bs[W]; + puts(&bs, &buf, ins[i]); + puts(&bs, &buf, "; }"); + const src : []const u8 = buf[0 .. bs[W]]; + clear(&st); + st[FLO] = find_tok(src, 0, "f") - 3; + st[P] = a; + expr(src, &st, &out, false); + assert(st[ERR] == code[i]); + assert(st[AT] == a + off[i]); + i = i + 1; + } +} + +test expr_bp_stops_before_an_operator_below_its_level_and_ns_keeps_a_name_from_a_struct_literal { + var out : [64]u8 = undefined; + var st : [64]usize = [0] ** 64; + assert(expr_bp("a + b", &st, &out, L_MUL, false) == L_ATOM); + assert(out_is(st[W], &out, 0, "a")); + assert(st[P] == 2); + clear(&st); + assert(expr_bp("a + b", &st, &out, L_OR, false) == L_ADD); + assert(out_is(st[W], &out, 0, "a + b")); + assert(st[P] == 5); + clear(&st); + assert(expr_bp("a + b", &st, &out, L_ADD, false) == L_ADD); + assert(out_is(st[W], &out, 0, "a + b")); + clear(&st); + assert(expr_bp("a + b", &st, &out, L_ADD + 1, false) == L_ATOM); + assert(out_is(st[W], &out, 0, "a")); + clear(&st); + assert(expr_bp("a == b", &st, &out, L_OR, true) == L_CMP); + assert(out_is(st[W], &out, 0, "a == b")); + clear(&st); + assert(expr_bp("a && b || c", &st, &out, L_OR, false) == L_OR); + assert(out_is(st[W], &out, 0, "a and b or c")); + clear(&st); + assert(expr_bp("a && b || c", &st, &out, L_AND, false) == L_AND); + assert(out_is(st[W], &out, 0, "a and b")); + clear(&st); + assert(expr_bp("Pt { x: 1 }", &st, &out, L_OR, true) == L_ATOM); + assert(out_is(st[W], &out, 0, "Pt")); + assert(st[P] == 3); + clear(&st); + assert(expr_bp("Pt { x: 1 }", &st, &out, L_OR, false) == L_ATOM); + assert(out_is(st[W], &out, 0, "Pt{ .x = 1 }")); + assert(st[P] == 11); + clear(&st); + st[ERR] = R_MACRO; + assert(expr_bp("a + b", &st, &out, L_OR, false) == L_ATOM); + assert(st[W] == 0); + assert(st[ERR] == R_MACRO); + clear(&st); + assert(expr_bp("a + ", &st, &out, L_OR, false) == L_ADD); + assert(st[ERR] == R_SYNTAX); +} + +test unary_and_postfix_write_prefixes_fields_indexes_and_the_try_mark { + var out : [64]u8 = undefined; + var st : [64]usize = [0] ** 64; + assert(unary("-x", &st, &out, false) == L_UNARY); + assert(out_is(st[W], &out, 0, "-x")); + clear(&st); + assert(unary("-(x)", &st, &out, false) == L_ATOM); + assert(out_is(st[W], &out, 0, "(0 - (x))")); + clear(&st); + assert(unary("*p", &st, &out, false) == L_ATOM); + assert(out_is(st[W], &out, 0, "p")); + clear(&st); + st[SELFMUT] = 1; + assert(unary("*self", &st, &out, false) == L_ATOM); + assert(out_is(st[W], &out, 0, "self.*")); + clear(&st); + assert(unary("*self", &st, &out, false) == L_ATOM); + assert(out_is(st[W], &out, 0, "self")); + clear(&st); + assert(unary("&x", &st, &out, false) == L_ATOM); + assert(out_is(st[W], &out, 0, "x")); + clear(&st); + assert(unary("&&x", &st, &out, false) == L_ATOM); + assert(out_is(st[W], &out, 0, "x")); + clear(&st); + assert(unary("&mut x", &st, &out, false) == L_ATOM); + assert(st[ERR] == R_MUTREF); + assert(st[AT] == 5); + clear(&st); + st[ERR] = R_MACRO; + assert(unary("-x", &st, &out, false) == L_ATOM); + assert(st[W] == 0); + clear(&st); + assert(unary("--x", &st, &out, false) == L_UNARY); + assert(out_is(st[W], &out, 0, "--x")); + clear(&st); + assert(postfix("a.b", &st, &out, false) == L_ATOM); + assert(out_is(st[W], &out, 0, "a.b")); + assert(st[P] == 3); + clear(&st); + assert(postfix("a.0", &st, &out, false) == L_ATOM); + assert(out_is(st[W], &out, 0, "a._0")); + clear(&st); + assert(postfix("a.b.c[1].d", &st, &out, false) == L_ATOM); + assert(out_is(st[W], &out, 0, "a.b.c[1].d")); + assert(st[ERR] == 0); + clear(&st); + assert(postfix("a[1][2]", &st, &out, false) == L_ATOM); + assert(out_is(st[W], &out, 0, "a[1][2]")); + clear(&st); + assert(postfix("a?", &st, &out, false) == L_ATOM); + assert(st[ERR] == R_TRY); + assert(st[AT] == 1); + clear(&st); + st[QOK] = 1; + assert(postfix("a?", &st, &out, false) == L_ATOM); + assert(st[ERR] == 0); + assert(out_is(st[W], &out, 0, "a")); + assert(st[P] == 1); + clear(&st); + assert(postfix("a.0.1", &st, &out, false) == L_ATOM); + assert(st[ERR] == R_TUPLE); + clear(&st); + assert(postfix("a. 1", &st, &out, false) == L_ATOM); + assert(out_is(st[W], &out, 0, "a._1")); + clear(&st); + assert(postfix("a.b::", &st, &out, false) == L_ATOM); + assert(st[ERR] == R_GENERIC); + assert(st[AT] == 6); + clear(&st); + assert(postfix("a.void", &st, &out, false) == L_ATOM); + assert(out_is(st[W], &out, 0, "a.void_")); +} + +test call_args_args_list_index_and_range_hi_write_the_bracketed_parts { + var out : [64]u8 = undefined; + var st : [64]usize = [0] ** 64; + call_args("(a, b)", &st, &out); + assert(out_is(st[W], &out, 0, "(a, b)")); + assert(st[P] == 6); + clear(&st); + call_args("()", &st, &out); + assert(out_is(st[W], &out, 0, "()")); + clear(&st); + call_args("(a,)", &st, &out); + assert(out_is(st[W], &out, 0, "(a)")); + clear(&st); + call_args("(f(a), b + 1)", &st, &out); + assert(out_is(st[W], &out, 0, "(f(a), b + 1)")); + clear(&st); + call_args("(a", &st, &out); + assert(st[ERR] == R_SYNTAX); + assert(st[AT] == 2); + clear(&st); + call_args("a)", &st, &out); + assert(st[ERR] == R_SYNTAX); + assert(st[AT] == 0); + clear(&st); + st[P] = 1; + args_list("(a, b)", &st, &out); + assert(out_is(st[W], &out, 0, "a, b")); + assert(st[P] == 5); + clear(&st); + st[P] = 1; + args_list("(a, b, )", &st, &out); + assert(out_is(st[W], &out, 0, "a, b")); + assert(st[P] == 7); + clear(&st); + index("[i]", &st, &out, 0); + assert(out_is(st[W], &out, 0, "[i]")); + assert(st[P] == 3); + clear(&st); + index("[1..3]", &st, &out, 0); + assert(out_is(st[W], &out, 0, "[1 .. 3]")); + clear(&st); + index("[..2]", &st, &out, 0); + assert(out_is(st[W], &out, 0, "[0 .. 2]")); + clear(&st); + index("[..=2]", &st, &out, 0); + assert(out_is(st[W], &out, 0, "[0 .. 2 + 1]")); + clear(&st); + index("[1..=n]", &st, &out, 0); + assert(out_is(st[W], &out, 0, "[1 .. n + 1]")); + clear(&st); + puts(&st, &out, "xs"); + index("[a..]", &st, &out, 0); + assert(out_is(st[W], &out, 0, "xs[a .. xs.len]")); + clear(&st); + puts(&st, &out, "xs"); + index("[..]", &st, &out, 0); + assert(out_is(st[W], &out, 0, "xs")); + assert(st[P] == 4); + clear(&st); + index("[a", &st, &out, 0); + assert(st[ERR] == R_SYNTAX); + clear(&st); + range_hi("n", &st, &out, false, false); + assert(out_is(st[W], &out, 0, "n")); + clear(&st); + range_hi("n", &st, &out, true, false); + assert(out_is(st[W], &out, 0, "n + 1")); + clear(&st); + range_hi("a & b", &st, &out, true, false); + assert(out_is(st[W], &out, 0, "(a & b) + 1")); + clear(&st); + range_hi("a + b", &st, &out, true, false); + assert(out_is(st[W], &out, 0, "a + b + 1")); + clear(&st); + range_hi("a == b", &st, &out, true, false); + assert(out_is(st[W], &out, 0, "(a == b) + 1")); +} + +test method_calls_go_to_the_impl_or_to_the_std_table { + const head : str = "struct A { x: u8 }\nimpl A { fn get(&self) -> u8 { self.x } fn add(&self, k: u8) -> u8 { k } fn bump(&mut self) { } }\nfn f(a: u32, b: u32, i: i32, r: f64, s: &str, v: &[u8], o: Option, w: A) { "; + const ins : [31]str = ["w.get()", "w.add(1)", "w.bump()", "s.starts_with(|c: char| c.is_ascii_digit())", "s.chars().all(|c| c.is_ascii_digit())", "s.chars().all(|c| c.is_ascii_alphanumeric() || c == '_')", "v.iter().sum::()", "v.contains(&3)", "[1, 2].contains(&a)", "s.contains('x')", "s.ends_with('x')", "s.starts_with(\"ab\")", "s.find('x')", "a.min(b)", "i.abs()", "a.checked_add(b)", "a.saturating_sub(b)", "a.count_ones()", "r.sqrt()", "o.unwrap()", "o.is_some()", "o.is_none()", "o.unwrap_or(0)", "s.parse::()", "s.len() + v.len()", "s.chars()", "s.clone()", "v.len()", "[1, 2, 3].contains(&a)", "[\"a\", \"b\"].contains(&s)", "a.wrapping_mul(b)"]; + const outs : [31]str = ["A_get(w)", "A_add(w, 1)", "A_bump(&w)", "rust_std::starts_with_digit(s)", "rust_std::chars_all_digit(s)", "rust_std::chars_all_word(s)", "rust_std::sum_u32(v)", "rust_std::bytes_contain(v, 3)", "(a == 1 or a == 2)", "rust_std::str_contains(s, \"x\")", "toolchain::ends_with(s, \"x\")", "toolchain::starts_with(s, \"ab\")", "rust_std::find_byte(s, 'x')", "@min(a, b)", "rust_std::abs_i32(i)", "rust_std::checked_add_u32(a, b)", "rust_std::saturating_sub_u32(a, b)", "rust_std::count_ones_u32(a)", "@sqrt(r)", "o.?", "(o != null)", "(o == null)", "if (o != null) { o.? } else { 0 }", "rust_std::parse_u32(s)", "s.len + v.len", "s", "s", "v.len", "(a == 1 or a == 2 or a == 3)", "(type_text::same(s, \"a\") or type_text::same(s, \"b\"))", "(a *% b)"]; + var buf : [1024]u8 = [0] ** 1024; + var st : [1024]usize = [0] ** 1024; + var out : [256]u8 = undefined; + var i : usize = 0; + while (i < 31) { + var bs : [64]usize = [0] ** 64; + puts(&bs, &buf, head); + const a : usize = bs[W]; + puts(&bs, &buf, ins[i]); + const b : usize = bs[W]; + puts(&bs, &buf, "; }"); + const src : []const u8 = buf[0 .. bs[W]]; + clear(&st); + st[FLO] = find_tok(src, 0, "f") - 3; + st[P] = a; + expr(src, &st, &out, false); + assert(st[ERR] == 0); + assert(out_is(st[W], &out, 0, outs[i])); + assert(st[P] == b); + i = i + 1; + } +} + +test method_refuses_what_the_table_does_not_map_and_names_the_method { + const head : str = "struct A { x: u8 }\nimpl A { fn get(&self) -> u8 { self.x } }\nfn f(a: u32, b: u32, r: f64, s: &str, z: &[u32], o: Option, w: A) { "; + const ins : [10]str = ["a.foo()", "r.ln()", "a.abs()", "z.contains(&a)", "o.unwrap_or(w.get())", "1 + o.unwrap_or(0)", "s.parse::", "s.len().foo()", "a.to_ascii_lowercase()", "r.is_nan()"]; + const code : [10]usize = [R_METHOD, R_LIBM, R_METHOD, R_SLICEGEN, R_METHOD, R_METHOD, R_GENERIC, R_METHOD, R_METHOD, R_METHOD]; + const off : [10]usize = [2, 2, 2, 2, 2, 6, 10, 8, 2, 2]; + var buf : [1024]u8 = [0] ** 1024; + var st : [1024]usize = [0] ** 1024; + var out : [256]u8 = undefined; + var i : usize = 0; + while (i < 10) { + var bs : [64]usize = [0] ** 64; + puts(&bs, &buf, head); + const a : usize = bs[W]; + puts(&bs, &buf, ins[i]); + puts(&bs, &buf, "; }"); + const src : []const u8 = buf[0 .. bs[W]]; + clear(&st); + st[FLO] = find_tok(src, 0, "f") - 3; + st[P] = a; + expr(src, &st, &out, false); + assert(st[ERR] == code[i]); + assert(st[AT] == a + off[i]); + i = i + 1; + } +} + +test method_called_directly_writes_the_std_form_around_the_receiver_already_written { + const src : str = "fn f(v: &[u8], a: u32) { v.len(); a.pow(2); v.foo(); v.iter().enumerate(); }"; + var out : [64]u8 = undefined; + var st : [64]usize = [0] ** 64; + puts(&st, &out, "v"); + st[P] = 30; + method(src, &st, &out, 0, 25, 26, 27, 30, 0, 0); + assert(out_is(st[W], &out, 0, "v.len")); + assert(st[P] == 32); + assert(st[ERR] == 0); + clear(&st); + puts(&st, &out, "a"); + st[P] = 39; + method(src, &st, &out, 0, 34, 35, 36, 39, 0, 0); + assert(out_is(st[W], &out, 0, "rust_std::pow_u32(a, 2)")); + assert(st[P] == 42); + assert((st[USES] / 2) % 2 == 1); + clear(&st); + puts(&st, &out, "v"); + st[P] = 49; + method(src, &st, &out, 0, 44, 45, 46, 49, 0, 0); + assert(st[ERR] == R_METHOD); + assert(st[AT] == 46); + clear(&st); + puts(&st, &out, "v"); + st[FORHDR] = 1; + st[P] = 59; + method(src, &st, &out, 0, 53, 54, 55, 59, 0, 0); + assert(out_is(st[W], &out, 0, "v")); + assert(st[ERR] == 0); + assert(st[ENUMSEEN] == 0); + assert(st[P] == 61); + clear(&st); + puts(&st, &out, "v"); + st[FORHDR] = 1; + st[P] = 71; + method(src, &st, &out, 0, 53, 61, 62, 71, 0, 0); + assert(out_is(st[W], &out, 0, "v")); + assert(st[ENUMSEEN] == 1); + assert(st[P] == 73); +} + +test expand_writes_the_entry_form_around_the_receiver_and_the_argument { + var out : [128]u8 = undefined; + var st : [64]usize = [0] ** 64; + puts(&st, &out, "v"); + st[P] = 5; + expand("v.len()", &st, &out, 0, 0, 0, 1, 0, 0, C_SLICE); + assert(out_is(st[W], &out, 0, "v.len")); + assert(st[P] == 7); + assert(st[ERR] == 0); + clear(&st); + puts(&st, &out, "x"); + st[P] = 5; + expand("x.pow(2) u32", &st, &out, 0, 58, 0, 1, 9, 12, C_INT); + assert(out_is(st[W], &out, 0, "rust_std::pow_u32(x, 2)")); + assert(st[P] == 9); + assert(st[USES] == 2); + clear(&st); + puts(&st, &out, "x"); + st[P] = 5; + st[TYARR] = 2; + expand("x.pow(2)", &st, &out, 0, 58, 0, 1, 0, 0, C_INT); + assert(out_is(st[W], &out, 0, "rust_std::pow_usize(x, 2)")); + clear(&st); + puts(&st, &out, "s"); + st[P] = 6; + expand("s.trim()", &st, &out, 0, 18, 0, 1, 0, 0, C_STR); + assert(out_is(st[W], &out, 0, "s[type_text::trim_lo(s, 0, s.len) .. type_text::trim_hi(s, type_text::trim_lo(s, 0, s.len), s.len)]")); + assert(st[USES] == 16); + clear(&st); + puts(&st, &out, "r"); + st[P] = 11; + expand("r.unwrap_or(d)", &st, &out, 0, 73, 0, 1, 0, 0, C_ANY); + assert(out_is(st[W], &out, 0, "if (r != null) { r.? } else { d }")); + assert(st[P] == 14); + clear(&st); + puts(&st, &out, "s"); + st[P] = 11; + expand("s.ends_with('x')", &st, &out, 0, 22, 0, 1, 0, 0, C_STR); + assert(out_is(st[W], &out, 0, "toolchain::ends_with(s, \"x\")")); + assert(st[USES] == 4); + clear(&st); + puts(&st, &out, "s"); + st[P] = 11; + expand("s.ends_with(\"ab\")", &st, &out, 0, 22, 0, 1, 0, 0, C_STR); + assert(out_is(st[W], &out, 0, "toolchain::ends_with(s, \"ab\")")); + clear(&st); + puts(&st, &out, "a"); + st[P] = 10; + st[TYARR] = 1; + expand("a.contains(&3)", &st, &out, 0, 24, 0, 1, 0, 0, C_SLICE); + assert(out_is(st[W], &out, 0, "rust_std::bytes_contain(&a, 3)")); + clear(&st); + puts(&st, &out, "a"); + st[P] = 10; + expand("a.contains(&3)", &st, &out, 0, 24, 0, 1, 0, 0, C_SLICE); + assert(out_is(st[W], &out, 0, "rust_std::bytes_contain(a, 3)")); + clear(&st); + puts(&st, &out, "r"); + st[P] = 7; + expand("r.ok_or(e)", &st, &out, 0, 37, 0, 1, 0, 0, C_ANY); + assert(out_is(st[W], &out, 0, "r")); + assert(st[P] == 10); + assert(st[ERR] == 0); + clear(&st); + puts(&st, &out, "x"); + st[P] = 14; + expand("x.wrapping_add(a + b)", &st, &out, 0, 12, 0, 1, 0, 0, C_INT); + assert(out_is(st[W], &out, 0, "(x +% (a + b))")); + clear(&st); + puts(&st, &out, "x"); + st[P] = 14; + expand("x.wrapping_add(b)", &st, &out, 0, 12, 0, 1, 0, 0, C_INT); + assert(out_is(st[W], &out, 0, "(x +% b)")); + clear(&st); + puts(&st, &out, "x"); + st[P] = 14; + expand("x.wrapping_add(f(b))", &st, &out, 0, 12, 0, 1, 0, 0, C_INT); + assert(out_is(st[W], &out, 0, "(x +% f(b))")); + clear(&st); + puts(&st, &out, "x"); + st[P] = 14; + expand("x.wrapping_add b", &st, &out, 0, 12, 0, 1, 0, 0, C_INT); + assert(st[ERR] == R_SYNTAX); +} + +test unroll_contains_writes_a_constant_array_as_a_chain_of_comparisons { + var out : [128]u8 = undefined; + var st : [64]usize = [0] ** 64; + puts(&st, &out, "[1, 2]"); + st[P] = 15; + assert(unroll_contains("[1, 2].contains(&x)", &st, &out, 0, 0, 6)); + assert(out_is(st[W], &out, 0, "(x == 1 or x == 2)")); + assert(st[P] == 19); + assert(st[NEQ] == 0); + clear(&st); + const k : str = "const K: [u32; 3] = [1, 2, 3];\nfn f(x: u32) { K.contains(&x) }"; + puts(&st, &out, "K"); + st[P] = 56; + assert(unroll_contains(k, &st, &out, 0, 46, 47)); + assert(out_is(st[W], &out, 0, "(x == 1 or x == 2 or x == 3)")); + assert(st[P] == 61); + clear(&st); + puts(&st, &out, "[\"a\", \"b\"]"); + st[P] = 19; + assert(unroll_contains("[\"a\", \"b\"].contains(&x)", &st, &out, 0, 0, 10)); + assert(out_is(st[W], &out, 0, "(type_text::same(x, \"a\") or type_text::same(x, \"b\"))")); + assert(st[NEQ] == 1); + clear(&st); + puts(&st, &out, "[1, 2]"); + st[P] = 15; + assert(unroll_contains("[1, 2].contains(&'a')", &st, &out, 0, 0, 6)); + assert(out_is(st[W], &out, 0, "('a' == 1 or 'a' == 2)")); + clear(&st); + puts(&st, &out, "[0; 3]"); + st[P] = 15; + assert(!unroll_contains("[0; 3].contains(&x)", &st, &out, 0, 0, 6)); + assert(st[W] == 6); + assert(st[P] == 15); + clear(&st); + puts(&st, &out, "[1, 2]"); + st[P] = 15; + assert(!unroll_contains("[1, 2].contains(&(a + 1))", &st, &out, 0, 0, 6)); + assert(st[W] == 6); + clear(&st); + puts(&st, &out, "[1, 2]"); + st[P] = 15; + assert(!unroll_contains("[1, 2].contains(&x, y)", &st, &out, 0, 0, 6)); + assert(st[W] == 6); + clear(&st); + puts(&st, &out, "v"); + st[P] = 10; + assert(!unroll_contains("v.contains(&x)", &st, &out, 0, 0, 1)); + assert(st[W] == 1); +} + +// ---------------------------------------------------------------- direct tests: literals, paths and literals of items + +test put_digits_put_number_and_upper_const_write_number_literals { + var out : [64]u8 = undefined; + var st : [64]usize = [0] ** 64; + put_digits("1_000", &st, &out, 0, 5); + assert(out_is(st[W], &out, 0, "1000")); + clear(&st); + put_digits("a1_2", &st, &out, 1, 4); + assert(out_is(st[W], &out, 0, "12")); + clear(&st); + put_digits("__", &st, &out, 0, 2); + assert(st[W] == 0); + const nums : [10]str = ["5", "5u8", "1_000i64", "0xFFu8", "1.5f32", "0x1f32", "7usize", "1_0", "0b1_0u16", "2.5e-3"]; + const want : [10]str = ["5", "@as(u8, 5)", "@as(i64, 1000)", "@as(u8, 0xFF)", "@as(f32, 1.5)", "0x1f32", "@as(usize, 7)", "10", "@as(u16, 0b10)", "2.5e-3"]; + var i : usize = 0; + while (i < 10) { + clear(&st); + put_number(nums[i], &st, &out, 0, nums[i].len); + assert(out_is(st[W], &out, 0, want[i])); + i = i + 1; + } + assert(upper_const("MAX", 0, 3)); + assert(upper_const("MAX_SIZE", 0, 8)); + assert(upper_const("A1_B", 0, 4)); + assert(upper_const("_A", 0, 2)); + assert(upper_const("12", 0, 2)); + assert(upper_const("x MAX", 2, 5)); + assert(!upper_const("Ab", 0, 2)); + assert(!upper_const("A", 0, 1)); + assert(!upper_const("ab", 0, 2)); + assert(!upper_const("A-B", 0, 3)); + assert(!upper_const("", 0, 0)); + assert(!upper_const("Kind", 0, 4)); + assert(!upper_const("MAx", 0, 3)); +} + +test put_char_writes_char_and_byte_literals_and_refuses_the_rest { + var out : [64]u8 = undefined; + var st : [64]usize = [0] ** 64; + const ok : [16]str = ["'a'", "b'a'", "'\\n'", "'\\t'", "'\\r'", "'\\\\'", "'\\''", "'\\\"'", "' '", "'\\0'", "'\\x41'", "b'\\xff'", "'\\x0a'", "b'\\x7F'", "'\"'", "b'\\0'"]; + const want : [16]str = ["'a'", "'a'", "'\\n'", "'\\t'", "'\\r'", "'\\\\'", "'\\''", "'\\\"'", "' '", "0", "65", "255", "10", "127", "'\"'", "0"]; + var i : usize = 0; + while (i < 16) { + clear(&st); + put_char(ok[i], &st, &out, 0, ok[i].len); + assert(st[ERR] == 0); + assert(out_is(st[W], &out, 0, want[i])); + i = i + 1; + } + const bad : [8]str = ["''", "'ab'", "'\\u{41}'", "'\\q'", "'\\x4'", "b''", "'\\nx'", "'"]; + var j : usize = 0; + while (j < 8) { + clear(&st); + put_char(bad[j], &st, &out, 0, bad[j].len); + assert(st[ERR] == R_LITERAL); + assert(st[AT] == 0); + assert(st[NLO] == 0); + assert(st[NHI] == bad[j].len); + j = j + 1; + } + var buf : [16]u8 = [0] ** 16; + var bs : [64]usize = [0] ** 64; + put(&bs, &buf, B_APOS); + put(&bs, &buf, 1); + put(&bs, &buf, B_APOS); + clear(&st); + put_char(buf[0 .. 3], &st, &out, 0, 3); + assert(st[ERR] == R_LITERAL); + var b2 : [16]u8 = [0] ** 16; + var s2 : [64]usize = [0] ** 64; + put(&s2, &b2, B_APOS); + put(&s2, &b2, B_DEL); + put(&s2, &b2, B_APOS); + clear(&st); + put_char(b2[0 .. 3], &st, &out, 0, 3); + assert(st[ERR] == R_LITERAL); + clear(&st); + put_char("x 'q' y", &st, &out, 2, 5); + assert(out_is(st[W], &out, 0, "'q'")); +} + +test string_escape_is_cont_cont_end_and_put_string_join_and_check_a_text { + assert(string_escape(B_LOWER_N)); + assert(string_escape(B_LOWER_T)); + assert(string_escape(B_BACKSLASH)); + assert(string_escape(B_QUOTE)); + assert(!string_escape(B_LOWER_R)); + assert(!string_escape(B_ZERO)); + assert(!string_escape(B_APOS)); + assert(!string_escape(B_LOWER_X)); + assert(!string_escape(B_LOWER_U)); + assert(!string_escape(0)); + assert(is_cont("a\\\n b", 1, 6)); + assert(!is_cont("a\\\nb", 1, 2)); + assert(!is_cont("ab\n", 1, 3)); + assert(!is_cont("a\\b", 1, 3)); + assert(!is_cont("a\\", 1, 2)); + assert(!is_cont("a\\\n", 1, 1)); + var cr : [16]u8 = [0] ** 16; + var cs : [64]usize = [0] ** 64; + puts(&cs, &cr, "a\\"); + put(&cs, &cr, B_CR); + put(&cs, &cr, B_NL); + puts(&cs, &cr, "b"); + assert(is_cont(cr[0 .. 5], 1, 5)); + assert(!is_cont(cr[0 .. 5], 1, 3)); + var lone : [16]u8 = [0] ** 16; + var ls : [64]usize = [0] ** 64; + puts(&ls, &lone, "a\\"); + put(&ls, &lone, B_CR); + puts(&ls, &lone, "b"); + assert(!is_cont(lone[0 .. 4], 1, 4)); + assert(cont_end("a\\\n \t b", 1, 9) == 8); + assert(cont_end("a\\\nb", 1, 4) == 3); + assert(cont_end("a\\\n ", 1, 6) == 6); + assert(cont_end("a\\\n ", 1, 4) == 4); + var out : [64]u8 = undefined; + var st : [64]usize = [0] ** 64; + put_string("\"abc\"", &st, &out, 0, 5); + assert(out_is(st[W], &out, 0, "\"abc\"")); + clear(&st); + put_string("\"a\\n\\t\\\\\\\"b\"", &st, &out, 0, 12); + assert(out_is(st[W], &out, 0, "\"a\\n\\t\\\\\\\"b\"")); + clear(&st); + put_string("b\"x\"", &st, &out, 0, 4); + assert(out_is(st[W], &out, 0, "\"x\"")); + clear(&st); + put_string("\"ab\\\n cd\"", &st, &out, 0, 11); + assert(out_is(st[W], &out, 0, "\"abcd\"")); + clear(&st); + put_string("\"a\\rb\"", &st, &out, 0, 6); + assert(st[ERR] == R_LITERAL); + assert(st[AT] == 0); + assert(st[NLO] == 2); + assert(st[NHI] == 4); + clear(&st); + put_string("\"a\\0b\"", &st, &out, 0, 6); + assert(st[ERR] == R_LITERAL); + clear(&st); + put_string("\"a\\'b\"", &st, &out, 0, 6); + assert(st[ERR] == R_LITERAL); + clear(&st); + put_string("\"\"", &st, &out, 0, 2); + assert(out_is(st[W], &out, 0, "\"\"")); + clear(&st); + put_string("r\"a\\b\"", &st, &out, 0, 6); + assert(out_is(st[W], &out, 0, "\"a\\\\b\"")); + var ctl : [16]u8 = [0] ** 16; + var ts : [64]usize = [0] ** 64; + put(&ts, &ctl, B_QUOTE); + put(&ts, &ctl, 7); + put(&ts, &ctl, B_QUOTE); + clear(&st); + put_string(ctl[0 .. 3], &st, &out, 0, 3); + assert(st[ERR] == R_LITERAL); + assert(st[NLO] == 0); + assert(st[NHI] == 3); +} + +test put_raw_string_rewrites_the_text_with_the_escapes_t27_reads { + var out : [64]u8 = undefined; + var st : [64]usize = [0] ** 64; + put_raw_string("r\"ab\"", &st, &out, 0, 5); + assert(out_is(st[W], &out, 0, "\"ab\"")); + clear(&st); + put_raw_string("r#\"a\"b\"#", &st, &out, 0, 8); + assert(out_is(st[W], &out, 0, "\"a\\\"b\"")); + clear(&st); + put_raw_string("r\"a\\b\"", &st, &out, 0, 6); + assert(out_is(st[W], &out, 0, "\"a\\\\b\"")); + clear(&st); + put_raw_string("r\"\"", &st, &out, 0, 3); + assert(out_is(st[W], &out, 0, "\"\"")); + clear(&st); + put_raw_string("r\"a\nb\tc\"", &st, &out, 0, 8); + assert(out_is(st[W], &out, 0, "\"a\\nb\\tc\"")); + clear(&st); + var crlf : [16]u8 = [0] ** 16; + var cs : [64]usize = [0] ** 64; + puts(&cs, &crlf, "r\"a"); + put(&cs, &crlf, B_CR); + put(&cs, &crlf, B_NL); + puts(&cs, &crlf, "b\""); + put_raw_string(crlf[0 .. cs[W]], &st, &out, 0, cs[W]); + assert(out_is(st[W], &out, 0, "\"a\\nb\"")); + clear(&st); + put_raw_string("r\"abc", &st, &out, 0, 5); + assert(st[ERR] == R_LITERAL); + clear(&st); + put_raw_string("r#\"abc\"", &st, &out, 0, 7); + assert(st[ERR] == R_LITERAL); + assert(st[NHI] == 7); + clear(&st); + var ctl : [16]u8 = [0] ** 16; + var ts : [64]usize = [0] ** 64; + puts(&ts, &ctl, "r\""); + put(&ts, &ctl, 7); + puts(&ts, &ctl, "\""); + put_raw_string(ctl[0 .. 4], &st, &out, 0, 4); + assert(st[ERR] == R_LITERAL); +} + +test put_limit_writes_the_extremes_of_an_integer_type { + const tys : [13]str = ["u8", "u16", "u32", "u64", "usize", "u128", "i8", "i16", "i32", "i64", "isize", "i128", "f64"]; + const maxs : [13]str = ["255", "65535", "4294967295", "18446744073709551615", "18446744073709551615", "340282366920938463463374607431768211455", "127", "32767", "2147483647", "9223372036854775807", "9223372036854775807", "170141183460469231731687303715884105727", ""]; + const mins : [13]str = ["0", "0", "0", "0", "0", "0", "(-128)", "(-32768)", "(-2147483648)", "(-9223372036854775808)", "(-9223372036854775808)", "(-170141183460469231731687303715884105728)", ""]; + var out : [64]u8 = undefined; + var st : [64]usize = [0] ** 64; + var i : usize = 0; + while (i < 13) { + clear(&st); + const hit : bool = put_limit(tys[i], &st, &out, 0, tys[i].len, true); + assert(hit == (i < 12)); + assert(out_is(st[W], &out, 0, maxs[i])); + clear(&st); + const lo : bool = put_limit(tys[i], &st, &out, 0, tys[i].len, false); + assert(lo == (i < 12)); + assert(out_is(st[W], &out, 0, mins[i])); + i = i + 1; + } + clear(&st); + assert(!put_limit("bool", &st, &out, 0, 4, true)); + assert(!put_limit("", &st, &out, 0, 0, false)); + assert(st[W] == 0); +} + +test path_prefix_path_and_the_module_paths_write_a_qualified_name { + assert(path_prefix("crate", 0, 5)); + assert(path_prefix("self", 0, 4)); + assert(path_prefix("super", 0, 5)); + assert(path_prefix("std", 0, 3)); + assert(path_prefix("core", 0, 4)); + assert(!path_prefix("cmp", 0, 3)); + assert(!path_prefix("Self", 0, 4)); + assert(!path_prefix("selff", 0, 5)); + assert(!path_prefix("", 0, 0)); + var out : [64]u8 = undefined; + var st : [128]usize = [0] ** 128; + st[P] = 5; + path("super::f(1)", &st, &out, 0, 5); + assert(out_is(st[W], &out, 0, "f(1)")); + assert(st[ERR] == 0); + clear(&st); + st[P] = 3; + path("std::cmp::max(a, b)", &st, &out, 0, 3); + assert(out_is(st[W], &out, 0, "@max(a, b)")); + clear(&st); + st[P] = 4; + path("Node::new(1)", &st, &out, 0, 4); + assert(out_is(st[W], &out, 0, "Node_new(1)")); + clear(&st); + st[P] = 4; + path("Node::Kind", &st, &out, 0, 4); + assert(out_is(st[W], &out, 0, "Node.Kind")); + clear(&st); + st[P] = 4; + path("Node::LIMIT", &st, &out, 0, 4); + assert(out_is(st[W], &out, 0, "Node_LIMIT")); + clear(&st); + st[P] = 3; + path("u32::MAX", &st, &out, 0, 3); + assert(out_is(st[W], &out, 0, "4294967295")); + clear(&st); + st[P] = 5; + path("super::", &st, &out, 0, 5); + assert(st[ERR] == R_PATH); + clear(&st); + st[P] = 3; + path("foo::bar(1)", &st, &out, 0, 3); + assert(st[ERR] == R_EXTERNAL); + clear(&st); + st[P] = 4; + path("Node::", &st, &out, 0, 4); + assert(st[ERR] == R_GENERIC); + clear(&st); + const m : str = "x::f(1) tri/t27b/source_text"; + add_name(m, &st, K_MODPATH, 0, 1, 8, 28); + st[P] = 1; + path(m, &st, &out, 0, 1); + assert(out_is(st[W], &out, 0, "source_text::f(1)")); + assert(st[ERR] == 0); + assert(st[NAMES + 4] == K_MODUSED); + var st2 : [128]usize = [0] ** 128; + const m2 : str = "x::f(1) tri/t27b/source_text fn f() {}"; + add_name(m2, &st2, K_MODPATH, 0, 1, 8, 28); + st2[P] = 1; + path(m2, &st2, &out, 0, 1); + assert(st2[ERR] == R_CLASH); + assert(st2[AT] == 3); + var st4 : [128]usize = [0] ** 128; + const m4 : str = "x::f tri/t27b/source_text"; + add_name(m4, &st4, K_MODPATH, 0, 1, 5, 25); + st4[P] = 1; + path(m4, &st4, &out, 0, 1); + assert(out_is(st4[W], &out, 0, "source_text::f")); +} + +test struct_lit_array_lit_and_tuple_lit_write_the_aggregate_forms { + var out : [64]u8 = undefined; + var st : [64]usize = [0] ** 64; + st[P] = 3; + struct_lit("Pt { x: 1, y }", &st, &out, 0, 2); + assert(out_is(st[W], &out, 0, "Pt{ .x = 1, .y = y }")); + assert(st[P] == 14); + clear(&st); + st[P] = 3; + struct_lit("Pt { }", &st, &out, 0, 2); + assert(out_is(st[W], &out, 0, "Pt{}")); + clear(&st); + st[P] = 3; + struct_lit("Pt { x: 1, }", &st, &out, 0, 2); + assert(out_is(st[W], &out, 0, "Pt{ .x = 1 }")); + clear(&st); + st[P] = 3; + struct_lit("Pt { var: 1 }", &st, &out, 0, 2); + assert(out_is(st[W], &out, 0, "Pt{ .var_ = 1 }")); + clear(&st); + st[P] = 3; + struct_lit("Pt { ..d }", &st, &out, 0, 2); + assert(st[ERR] == R_UPDATE); + assert(st[AT] == 5); + clear(&st); + st[P] = 3; + struct_lit("Pt { 1 }", &st, &out, 0, 2); + assert(st[ERR] == R_SYNTAX); + assert(st[AT] == 5); + clear(&st); + st[P] = 3; + struct_lit("Pt { x: 1", &st, &out, 0, 2); + assert(st[ERR] == R_SYNTAX); + clear(&st); + st[ILO] = 0; + st[IHI] = 2; + st[P] = 8; + struct_lit("Pt Self { x }", &st, &out, 3, 7); + assert(out_is(st[W], &out, 0, "Pt{ .x = x }")); + clear(&st); + st[P] = 0; + array_lit("[1, 2]", &st, &out); + assert(out_is(st[W], &out, 0, "[1, 2]")); + assert(st[P] == 6); + clear(&st); + array_lit("[0; 4]", &st, &out); + assert(out_is(st[W], &out, 0, "[0] ** 4")); + clear(&st); + array_lit("[a; b + 1]", &st, &out); + assert(out_is(st[W], &out, 0, "[a] ** (b + 1)")); + clear(&st); + array_lit("[1, 2,]", &st, &out); + assert(out_is(st[W], &out, 0, "[1, 2]")); + clear(&st); + array_lit("[1,]", &st, &out); + assert(out_is(st[W], &out, 0, "[1]")); + clear(&st); + array_lit("[]", &st, &out); + assert(st[ERR] == R_EMPTY); + assert(st[AT] == 0); + assert(st[NHI] == 2); + clear(&st); + array_lit("[1, 2", &st, &out); + assert(st[ERR] == R_SYNTAX); + clear(&st); + const tl : str = "W(1, true) W"; + add_name(tl, &st, K_TUPLE, 11, 12, 0, 0); + st[P] = 1; + tuple_lit(tl, &st, &out, 0, 1); + assert(out_is(st[W], &out, 0, "W{ ._0 = 1, ._1 = true }")); + assert(st[P] == 11); + clear(&st); + st[P] = 1; + tuple_lit("W()", &st, &out, 0, 1); + assert(out_is(st[W], &out, 0, "W{}")); + clear(&st); + st[P] = 1; + tuple_lit("W(1,)", &st, &out, 0, 1); + assert(out_is(st[W], &out, 0, "W{ ._0 = 1 }")); + clear(&st); + st[P] = 1; + tuple_lit("W(1", &st, &out, 0, 1); + assert(st[ERR] == R_SYNTAX); +} + +test put_last_put_path_and_pred_end_read_a_path_and_a_cfg_predicate { + var out : [64]u8 = undefined; + var st : [64]usize = [0] ** 64; + put_last("a/b/c", &st, &out, 0, 5); + assert(out_is(st[W], &out, 0, "c")); + clear(&st); + put_last("a::b::c", &st, &out, 0, 7); + assert(out_is(st[W], &out, 0, "c")); + clear(&st); + put_last("abc", &st, &out, 0, 3); + assert(out_is(st[W], &out, 0, "abc")); + clear(&st); + put_last("a/", &st, &out, 0, 2); + assert(st[W] == 0); + clear(&st); + put_last("x a/b y", &st, &out, 2, 5); + assert(out_is(st[W], &out, 0, "b")); + clear(&st); + put_path("tri/t27b/x", &st, &out, 0, 10); + assert(out_is(st[W], &out, 0, "tri::t27b::x")); + clear(&st); + put_path("a", &st, &out, 0, 1); + assert(out_is(st[W], &out, 0, "a")); + clear(&st); + put_path("a/b", &st, &out, 1, 3); + assert(out_is(st[W], &out, 0, "::b")); + assert(pred_end("unix", 0) == 4); + assert(pred_end("not(unix)", 0) == 9); + assert(pred_end("target_os = \"linux\"", 0) == 19); + assert(pred_end("all(unix, x) y", 0) == 12); + assert(pred_end("unix, windows", 0) == 4); + assert(pred_end("a(b(c)) d", 0) == 7); +} + +test cfg_eval_reads_a_cfg_predicate_on_the_default_host { + const yes : [20]str = ["unix", "debug_assertions", "target_os = \"linux\"", "target_family = \"unix\"", "target_arch = \"x86_64\"", "target_pointer_width = \"64\"", "target_endian = \"little\"", "target_env = \"gnu\"", "target_vendor = \"unknown\"", "panic = \"unwind\"", "not(windows)", "not(test)", "all(unix, target_os = \"linux\")", "any(windows, unix)", "all()", "all(unix)", "not(not(unix))", "all(unix, not(any(windows, test)))", "any(all(windows, unix), unix)", "all(unix, debug_assertions, target_arch = \"x86_64\")"]; + var i : usize = 0; + while (i < 20) { + assert(cfg_eval(yes[i], 0)); + i = i + 1; + } + const no : [21]str = ["windows", "test", "feature = \"x\"", "target_os = \"macos\"", "target_arch = \"aarch64\"", "target_pointer_width = \"32\"", "target_endian = \"big\"", "target_env = \"msvc\"", "panic = \"abort\"", "not(unix)", "all(unix, windows)", "any(windows, macos)", "any()", "foo(unix)", "unknown = \"x\"", "not(all(unix, debug_assertions))", "all(unix, any(windows, test))", "target_os", "", "all(windows, unix)", "any(windows, test, feature = \"x\")"]; + var j : usize = 0; + while (j < 21) { + assert(!cfg_eval(no[j], 0)); + j = j + 1; + } + assert(cfg_eval("x unix", 2)); + assert(!cfg_eval("unix windows", 5)); +} + +test known_defect_the_splice_refusal_reads_the_alias_not_the_module_path { + // #10843: path refuses a call into int_type_names only when the mod is itself named int_type_names; the + // check reads the alias of the K_MODPATH entry, not the #[path] module. When that is fixed the second + // half flips (R_SPLICE for the alias x too). + var out : [64]u8 = undefined; + var named_ok : [128]usize = [0] ** 128; + const m1 : str = "int_type_names::f(1) tri/t27b/int_type_names"; + add_name(m1, &named_ok, K_MODPATH, 0, 14, 22, 44); + named_ok[P] = 14; + path(m1, &named_ok, &out, 0, 14); + assert(named_ok[ERR] == R_SPLICE); + assert(named_ok[AT] == 0); + var aliased : [128]usize = [0] ** 128; + const m2 : str = "x::f(1) tri/t27b/int_type_names"; + add_name(m2, &aliased, K_MODPATH, 0, 1, 8, 31); + aliased[P] = 1; + path(m2, &aliased, &out, 0, 1); + assert(aliased[ERR] == 0); + assert(out_is(aliased[W], &out, 0, "int_type_names::f(1)")); +} + +test result_value_and_matches_macro_write_ok_err_and_a_pattern_condition { + var out : [128]u8 = undefined; + var st : [64]usize = [0] ** 64; + st[FAILK] = F_NULL; + st[P] = 2; + result_value("Ok(x)", &st, &out, true, 0, 2); + assert(out_is(st[W], &out, 0, "x")); + assert(st[P] == 5); + assert(st[ERR] == 0); + clear(&st); + st[FAILK] = F_NULL; + st[P] = 2; + result_value("Ok(x + 1)", &st, &out, true, 0, 2); + assert(out_is(st[W], &out, 0, "(x + 1)")); + clear(&st); + st[FAILK] = F_NULL; + st[P] = 2; + result_value("Ok(-x)", &st, &out, true, 0, 2); + assert(out_is(st[W], &out, 0, "-x")); + clear(&st); + st[FAILK] = F_NULL; + st[P] = 3; + result_value("Err(e)", &st, &out, false, 0, 3); + assert(out_is(st[W], &out, 0, "null")); + assert(st[P] == 6); + clear(&st); + st[FAILK] = F_NULL; + st[P] = 3; + result_value("Err(f(x, y)) z", &st, &out, false, 0, 3); + assert(out_is(st[W], &out, 0, "null")); + assert(st[P] == 13); + clear(&st); + st[FAILK] = F_FALSE; + st[P] = 2; + result_value("Ok(())", &st, &out, true, 0, 2); + assert(out_is(st[W], &out, 0, "true")); + assert(st[P] == 6); + clear(&st); + st[FAILK] = F_FALSE; + st[P] = 3; + result_value("Err(e)", &st, &out, false, 0, 3); + assert(out_is(st[W], &out, 0, "false")); + clear(&st); + st[FAILK] = F_FALSE; + st[P] = 2; + result_value("Ok(1)", &st, &out, true, 0, 2); + assert(st[ERR] == R_SYNTAX); + clear(&st); + st[P] = 2; + result_value("Ok(x)", &st, &out, true, 0, 2); + assert(st[ERR] == R_TYPE); + assert(st[AT] == 0); + assert(st[NHI] == 2); + assert(st[W] == 0); + clear(&st); + st[P] = 3; + result_value("Err(e)", &st, &out, false, 0, 3); + assert(st[ERR] == R_TYPE); + const head : str = "enum Mode { A, B }\nfn g(x: u32) -> u32 { x }\nfn f(a: u32, ok: bool, s: &str, c: u8, m: Mode, o: Option) { "; + const ins : [11]str = ["matches!(a, 1 | 2)", "matches!(s, \"a\" | \"b\")", "matches!(c, b'a'..=b'z')", "matches!(m, Mode::A)", "matches!(o, None)", "matches!(ok, true)", "matches!(g(a), 1)", "matches!(a + 1, 1)", "matches!(a, 1 if ok)", "matches!(o, Some(x))", "matches!(m, Mode::A(x))"]; + const outs : [11]str = ["(a == 1 or a == 2)", "(type_text::same(s, \"a\") or type_text::same(s, \"b\"))", "((c >= 'a' and c <= 'z'))", "(m == Mode.A)", "(o == null)", "(ok == true)", "(g(a) == 1)", "((a + 1) == 1)", "", "", ""]; + const code : [11]usize = [0, 0, 0, 0, 0, 0, 0, 0, R_PATTERN, R_PATTERN, R_DATA]; + var buf : [1024]u8 = [0] ** 1024; + var i : usize = 0; + while (i < 11) { + var bs : [64]usize = [0] ** 64; + puts(&bs, &buf, head); + const a : usize = bs[W]; + puts(&bs, &buf, ins[i]); + puts(&bs, &buf, "; }"); + const src : []const u8 = buf[0 .. bs[W]]; + clear(&st); + st[FLO] = find_tok(src, 0, "f") - 3; + st[P] = a; + expr(src, &st, &out, false); + assert(st[ERR] == code[i]); + if (code[i] == 0) { assert(out_is(st[W], &out, 0, outs[i])); } + i = i + 1; + } +} + +test primary_writes_one_atom_and_refuses_what_is_not_one { + var out : [64]u8 = undefined; + var st : [64]usize = [0] ** 64; + const ok : [14]str = ["(a)", "5u8", "true", "false", "None", "Some(a)", "x", "f(1)", "'a'", "\"s\"", "r\"s\"", "[1]", "cfg!(unix)", "b'z'"]; + const want : [14]str = ["(a)", "@as(u8, 5)", "true", "false", "null", "a", "x", "f(1)", "'a'", "\"s\"", "\"s\"", "[1]", "true", "'z'"]; + var i : usize = 0; + while (i < 14) { + clear(&st); + primary(ok[i], &st, &out, false); + assert(st[ERR] == 0); + assert(out_is(st[W], &out, 0, want[i])); + assert(st[P] == ok[i].len); + i = i + 1; + } + clear(&st); + primary("Pt { x }", &st, &out, false); + assert(out_is(st[W], &out, 0, "Pt{ .x = x }")); + clear(&st); + primary("Pt { x }", &st, &out, true); + assert(out_is(st[W], &out, 0, "Pt")); + assert(st[P] == 3); + clear(&st); + st[ILO] = 5; + st[IHI] = 7; + primary("Self Pt", &st, &out, false); + assert(out_is(st[W], &out, 0, "Pt")); + clear(&st); + primary("", &st, &out, false); + assert(st[ERR] == R_SYNTAX); + clear(&st); + primary(")", &st, &out, false); + assert(st[ERR] == R_SYNTAX); + clear(&st); + primary("r#x", &st, &out, false); + assert(st[ERR] == R_LITERAL); + assert(st[NHI] == 2); + clear(&st); + primary("()", &st, &out, false); + assert(st[ERR] == R_TUPLE); + clear(&st); + primary("(a, b)", &st, &out, false); + assert(st[ERR] == R_TUPLE); + clear(&st); + primary("Foo(1)", &st, &out, false); + assert(st[ERR] == R_TUPLE); + clear(&st); + primary("cfg!x", &st, &out, false); + assert(st[ERR] == R_MACRO); + clear(&st); + primary("vec![1]", &st, &out, false); + assert(st[ERR] == R_MACRO); + clear(&st); + primary("while x { }", &st, &out, false); + assert(st[ERR] == R_VALUE); + clear(&st); + primary("for x in y { }", &st, &out, false); + assert(st[ERR] == R_VALUE); + clear(&st); + primary("loop { }", &st, &out, false); + assert(st[ERR] == R_VALUE); + clear(&st); + primary("unsafe { }", &st, &out, false); + assert(st[ERR] == R_UNSAFE); + clear(&st); + primary("||", &st, &out, false); + assert(st[ERR] == R_CLOSURE); + clear(&st); + primary("@", &st, &out, false); + assert(st[ERR] == R_SYNTAX); + clear(&st); + st[ERR] = R_PATH; + primary("x", &st, &out, false); + assert(st[W] == 0); + assert(st[ERR] == R_PATH); + clear(&st); + primary("std::f(1)", &st, &out, false); + assert(out_is(st[W], &out, 0, "f(1)")); +} From 1f9ab34043eb2be1aeb59e1e0e949da7f9bc1054 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 19 Oct 2026 11:45:07 +0700 Subject: [PATCH 6/8] t27o: direct tests for the statements of rust_convert.t27 -- blocks, lets, ?, vec! locals, if / if let / while let, for forms, match, asserts and result asserts (Closes #10825) Tests only; no non-test line changes. Co-Authored-By: Claude Sonnet 5.5 --- specs/tools/t27o/rust_convert.t27 | 974 ++++++++++++++++++++++++++++++ 1 file changed, 974 insertions(+) diff --git a/specs/tools/t27o/rust_convert.t27 b/specs/tools/t27o/rust_convert.t27 index 1e3a5d44b3..bb60a96adb 100644 --- a/specs/tools/t27o/rust_convert.t27 +++ b/specs/tools/t27o/rust_convert.t27 @@ -14705,3 +14705,977 @@ test primary_writes_one_atom_and_refuses_what_is_not_one { primary("std::f(1)", &st, &out, false); assert(out_is(st[W], &out, 0, "f(1)")); } + +// ---------------------------------------------------------------- direct tests: statements + +test open_block_close_block_block_stmts_and_tail_of_write_a_braced_body { + var out : [128]u8 = undefined; + var st : [64]usize = [0] ** 64; + assert(open_block("{ x }", &st, &out)); + assert(out_is(st[W], &out, 0, "{")); + assert(st[IND] == 1); + assert(st[P] == 2); + clear(&st); + assert(!open_block("x", &st, &out)); + assert(st[ERR] == R_SYNTAX); + assert(st[AT] == 0); + assert(st[W] == 0); + assert(st[IND] == 0); + clear(&st); + st[ERR] = R_MACRO; + assert(!open_block("{ x }", &st, &out)); + assert(st[ERR] == R_MACRO); + assert(st[W] == 0); + clear(&st); + st[IND] = 2; + close_block("}", &st, &out); + assert(out_is(st[W], &out, 0, "\n }")); + assert(st[IND] == 1); + assert(st[P] == 1); + clear(&st); + st[IND] = 1; + close_block("}", &st, &out); + assert(out_is(st[W], &out, 0, "\n}")); + assert(st[IND] == 0); + clear(&st); + block("{ g(a); g(b); }", &st, &out, M_STMT); + assert(out_is(st[W], &out, 0, "{\n g(a);\n g(b);\n}")); + assert(st[ERR] == 0); + assert(st[P] == 15); + clear(&st); + block("{ a + 1 }", &st, &out, M_RET); + assert(out_is(st[W], &out, 0, "{\n return a + 1;\n}")); + clear(&st); + block("{ ; ; g(a); }", &st, &out, M_STMT); + assert(out_is(st[W], &out, 0, "{\n g(a);\n}")); + clear(&st); + block("{ }", &st, &out, M_STMT); + assert(out_is(st[W], &out, 0, "{\n}")); + clear(&st); + block("x", &st, &out, M_STMT); + assert(st[ERR] == R_SYNTAX); + clear(&st); + st[IND] = 1; + st[P] = 0; + stmts("g(a); g(b) }", &st, &out, M_STMT); + assert(out_is(st[W], &out, 0, "\n g(a);\n g(b);")); + assert(st[P] == 11); + clear(&st); + stmts("g(a); g(b) }", &st, &out, M_RET); + assert(out_is(st[W], &out, 0, "\ng(a);\nreturn g(b);")); + clear(&st); + puts(&st, &out, "a + 1"); + tail_of("x", &st, &out, 0, M_RET); + assert(out_is(st[W], &out, 0, "return a + 1;")); + clear(&st); + puts(&st, &out, "a + 1"); + tail_of("x", &st, &out, 0, M_STMT); + assert(out_is(st[W], &out, 0, "a + 1;")); + clear(&st); + puts(&st, &out, "a + 1"); + st[TLO] = 2; + st[THI] = 3; + tail_of("r r", &st, &out, 0, M_SET); + assert(out_is(st[W], &out, 0, "r = a + 1;")); + clear(&st); + puts(&st, &out, "a + 1"); + st[TLO] = 0; + st[THI] = 4; + tail_of("void", &st, &out, 0, M_SET); + assert(out_is(st[W], &out, 0, "void_ = a + 1;")); +} + +test stmt_writes_one_statement_in_each_of_its_forms { + const head : str = "struct Node { v: u8 }\nconst C: u32 = 3;\nfn g(x: u32) -> u32 { x }\nfn f(a: u32, b: u32, ok: bool, s: &str, r: u32) { "; + const ins : [35]str = ["let k = 5;", "let mut k = 5;", "let k: u8 = 5;", "let k = 5u8;", "let k: u8;", "let _ = a;", "a = a + 1;", "a += 1;", "a <<= 2;", "g(a);", "return a;", "return;", "break;", "continue;", "if a > 1 { g(a); }", "if a > 1 { g(a); } else { g(b); }", "if a > 1 { g(a); } else if a > 2 { g(b); }", "while a < 3 { a += 1; }", "loop { break; }", "for i in 0..4 { g(i); }", "match a { 1 => { g(1); } _ => { g(2); } }", "assert!(a > 1);", "assert_eq!(a, 1);", "assert_ne!(a, b, \"m\");", "const D: u8 = 1;", "let k: u32 = if ok { 1 } else { 2 };", "let a: [u8; 0] = [];", "a + 1", "g(a)", "if ok { 1 } else { 2 }", "x.0 = 1;", "debug_assert!(ok);", "a;", "s;", "if ok { return; }"]; + const outs : [35]str = ["const k = 5;", "var k = 5;", "const k : u8 = 5;", "const k : u8 = 5;", "var k : u8 = undefined;", "_ = a;", "a = a + 1;", "a += 1;", "a <<= 2;", "g(a);", "return a;", "return;", "break;", "continue;", "if (a > 1) {\n g(a);\n }", "if (a > 1) {\n g(a);\n } else {\n g(b);\n }", "if (a > 1) {\n g(a);\n } else if (a > 2) {\n g(b);\n }", "while (a < 3) {\n a += 1;\n }", "while (true) {\n break;\n }", "for i in 0..4 {\n g(i);\n }", "if (a == 1) {\n g(1);\n } else {\n g(2);\n }", "assert(a > 1);", "assert(a == 1);", "assert(a != b);", "const D : u8 = 1;", "var k : u32 = undefined;\n if (ok) {\n k = 1;\n } else {\n k = 2;\n }", "const a : [0]u8 = [];", "a + 1;", "g(a);", "if (ok) {\n 1;\n } else {\n 2;\n }", "x._0 = 1;", "assert(ok);", "a;", "s;", "if (ok) {\n return;\n }"]; + var buf : [1024]u8 = [0] ** 1024; + var st : [1024]usize = [0] ** 1024; + var out : [512]u8 = undefined; + var i : usize = 0; + while (i < 35) { + var bs : [64]usize = [0] ** 64; + puts(&bs, &buf, head); + const a : usize = bs[W]; + puts(&bs, &buf, ins[i]); + puts(&bs, &buf, " }"); + const src : []const u8 = buf[0 .. bs[W]]; + clear(&st); + st[FLO] = find_tok(src, 0, "f") - 3; + st[IND] = 1; + st[P] = a; + stmt(src, &st, &out, M_STMT); + assert(st[ERR] == 0); + assert(out_is(st[W], &out, 0, outs[i])); + i = i + 1; + } +} + +test let_forms_ends_in_try_and_the_early_return_of_a_question_mark { + assert(value_form("if a { }", 0)); + assert(value_form("match a { }", 0)); + assert(value_form("loop { }", 0)); + assert(value_form("{ a }", 0)); + assert(value_form("unsafe { a }", 0)); + assert(!value_form("while a { }", 0)); + assert(!value_form("for a in b { }", 0)); + assert(!value_form("a", 0)); + assert(!value_form("iff", 0)); + assert(!value_form("", 0)); + assert(assign_op("=", 0)); + assert(assign_op("+=", 0)); + assert(assign_op("-=", 0)); + assert(assign_op("*=", 0)); + assert(assign_op("/=", 0)); + assert(assign_op("%=", 0)); + assert(assign_op("^=", 0)); + assert(assign_op("&=", 0)); + assert(assign_op("|=", 0)); + assert(assign_op("<<=", 0)); + assert(assign_op(">>=", 0)); + assert(assign_op("a += 1", 2)); + assert(!assign_op("==", 0)); + assert(!assign_op("!=", 0)); + assert(!assign_op("<=", 0)); + assert(!assign_op(">=", 0)); + assert(!assign_op("=>", 0)); + assert(!assign_op("<", 0)); + assert(!assign_op("", 0)); + assert(ends_in_try("f(x)?;", 0)); + assert(ends_in_try("let a = f()?;", 0)); + assert(ends_in_try("f(x)? ;", 0)); + assert(!ends_in_try("f(x);", 0)); + assert(!ends_in_try("f(x)? + 1;", 0)); + assert(!ends_in_try("f(x)?", 0)); + assert(!ends_in_try(";", 0)); + assert(!ends_in_try("", 0)); + assert(ends_in_try("a; f(x)?;", 3)); + const src : str = "fn ok() -> Result<(), E> { Ok(()) }\nfn val() -> Result { Ok(1) }\nfn t() { ok(); val(); T::ok(); x.ok(); ok; }"; + var st : [1024]usize = [0] ** 1024; + assert(unit_result_call(src, &st, 81)); + assert(!unit_result_call(src, &st, 87)); + assert(unit_result_call(src, &st, 94)); + assert(unit_result_call(src, &st, 103)); + assert(!unit_result_call(src, &st, 111)); + assert(!unit_result_call(src, &st, 0)); + assert(!unit_result_call(src, &st, src.len)); + assert(!unit_result_call("5(", &st, 0)); + var out : [128]u8 = undefined; + var ws : [64]usize = [0] ** 64; + put_fail(&ws, &out); + assert(out_is(ws[W], &out, 0, "return null;")); + clear(&ws); + ws[FAILK] = F_FALSE; + put_fail(&ws, &out); + assert(out_is(ws[W], &out, 0, "return false;")); + clear(&ws); + ws[FAILK] = F_NULL; + put_fail(&ws, &out); + assert(out_is(ws[W], &out, 0, "return null;")); + clear(&ws); + ws[IND] = 1; + puts(&ws, &out, "x"); + early_return(&ws, &out, 0, " == null"); + assert(out_is(ws[W], &out, 0, "if (x == null) {\n return null;\n }")); + assert(ws[IND] == 1); + clear(&ws); + ws[FAILK] = F_FALSE; + puts(&ws, &out, "(y)"); + early_return(&ws, &out, 0, " == false"); + assert(out_is(ws[W], &out, 0, "if ((y) == false) {\n return false;\n}")); +} + +test try_stmt_and_let_try_return_early_when_the_value_failed { + const src : str = "fn ok() -> Result<(), E> { Ok(()) }\nfn val(x: u8) -> Result { Ok(x) }\nfn t() { val(1)?; ok()?; val(2 + 3)?; let r = val(4)?; let q: u8 = val(5)?; }"; + var out : [256]u8 = undefined; + var st : [1024]usize = [0] ** 1024; + st[FAILK] = F_NULL; + st[IND] = 1; + st[P] = 86; + try_stmt(src, &st, &out); + assert(st[ERR] == 0); + assert(out_is(st[W], &out, 0, "if (val(1) == null) {\n return null;\n }")); + assert(st[P] == 95); + clear(&st); + st[FAILK] = F_FALSE; + st[IND] = 1; + st[P] = 95; + try_stmt(src, &st, &out); + assert(out_is(st[W], &out, 0, "if ((ok()) == false) {\n return false;\n }")); + clear(&st); + st[FAILK] = F_NULL; + st[IND] = 1; + st[P] = 102; + try_stmt(src, &st, &out); + assert(out_is(st[W], &out, 0, "if ((val(2 + 3)) == null) {\n return null;\n }")); + clear(&st); + st[P] = 86; + try_stmt(src, &st, &out); + assert(st[ERR] == R_TRY); + assert(st[W] == 0); + clear(&st); + st[FAILK] = F_NULL; + st[IND] = 1; + st[P] = 121; + let_try(src, &st, &out, false, 119, 120, 123); + assert(st[ERR] == 0); + assert(out_is(st[W], &out, 0, "const r_t27o = val(4);\n if (r_t27o == null) {\n return null;\n }\n const r = r_t27o.?;")); + clear(&st); + st[FAILK] = F_NULL; + st[IND] = 1; + st[P] = 137; + let_try(src, &st, &out, true, 136, 137, 144); + assert(out_is(st[W], &out, 0, "const q_t27o = val(5);\n if (q_t27o == null) {\n return null;\n }\n var q : u8 = q_t27o.?;")); + clear(&st); + st[P] = 121; + let_try(src, &st, &out, false, 119, 120, 123); + assert(st[ERR] == R_TRY); + assert(st[AT] == 123); + const s2 : str = "fn ok() -> Result<(), E> { Ok(()) }\nfn t() { let r = ok()?; }"; + clear(&st); + st[FAILK] = F_FALSE; + st[P] = 51; + let_try(s2, &st, &out, false, 49, 50, 53); + assert(st[ERR] == R_TRY); +} + +test vec_mention_vec_use_vec_scope_end_and_vec_life_tell_how_a_vec_is_used { + const srcs : [23]str = ["v.len()", "v.push(1)", "&mut v", "v = x", "v[0] = 1", "v[0]", "v[0].f = 1", "&v", "f(v)", "for x in v {", "x.v", "S { v: 1 }", "return v;", "v[1][2] += 1", "v.iter_mut()", "&&v", "v.len", "v.concat()", "v.sort()", "x = v", "for x in v.iter() {", "a::v", "v;"]; + const qs : [23]usize = [0, 0, 5, 0, 0, 0, 0, 1, 2, 9, 2, 4, 7, 0, 0, 2, 0, 0, 0, 4, 9, 3, 0]; + const want : [23]usize = [VU_READ, VU_CHANGED, VU_CHANGED, VU_CHANGED, VU_CHANGED, VU_READ, VU_CHANGED, VU_READ, VU_MOVED, VU_READ, VU_READ, VU_READ, VU_MOVED, VU_CHANGED, VU_CHANGED, VU_READ, VU_READ, VU_READ, VU_CHANGED, VU_MOVED, VU_READ, VU_READ, VU_MOVED]; + var i : usize = 0; + while (i < 23) { + const src : str = srcs[i]; + var prev : usize = src.len; + var p : usize = 0; + while (p < qs[i]) { + prev = p; + p = skip_ws(src, tok_end(src, p)); + } + assert(p == qs[i]); + assert(vec_mention(src, prev, qs[i], tok_end(src, qs[i])) == want[i]); + i = i + 1; + } + const bodies : [8]str = ["g(&v); v.len(); v[0];", "g(&v); h(v);", "h(v); v.push(1);", "g(&v); w.push(1);", "vv.push(1); v.len();", "g(&mut v);", "let v = 1; v.push(2);", ""]; + const uses : [8]usize = [VU_READ, VU_MOVED, VU_CHANGED, VU_READ, VU_READ, VU_CHANGED, VU_CHANGED, VU_READ]; + var buf : [128]u8 = [0] ** 128; + var j : usize = 0; + while (j < 8) { + var bs : [64]usize = [0] ** 64; + puts(&bs, &buf, bodies[j]); + const hi : usize = bs[W]; + puts(&bs, &buf, " v"); + const src : []const u8 = buf[0 .. bs[W]]; + assert(vec_use(src, 0, hi, hi + 1, hi + 2) == uses[j]); + j = j + 1; + } + assert(vec_use("h(v); v.push(1); v", 0, 5, 17, 18) == VU_MOVED); + assert(vec_use("h(v); v.push(1); v", 5, 14, 17, 18) == VU_CHANGED); + assert(vec_use("h(v); v.push(1); v", 6, 6, 17, 18) == VU_READ); + const sc : str = "g(&v); let v = 1; h(v); let mut v = 2; v"; + assert(vec_scope_end(sc, 0, sc.len, 39, 40) == 7); + assert(vec_scope_end(sc, 8, sc.len, 39, 40) == 24); + assert(vec_scope_end(sc, 0, 5, 39, 40) == 5); + assert(vec_scope_end("g(&v); let vv = 1; v", 0, 20, 19, 20) == 20); + assert(vec_scope_end("g(&v); v", 0, 8, 7, 8) == 8); + assert(vec_life("g(&v); let v = h(v); v", 0, 20, 21, 22) == VU_MOVED); + assert(vec_life("g(&v); let v = g(&v); v", 0, 21, 22, 23) == VU_READ); + assert(vec_life("g(&v); v.len(); v", 0, 15, 16, 17) == VU_READ); + assert(vec_life("g(&v); v.push(1); v", 0, 17, 18, 19) == VU_CHANGED); + assert(vec_life("g(&v); h(v); let v = 1; v", 0, 23, 24, 25) == VU_MOVED); + assert(vec_life("g(&v); let v = 1; v.push(1); v", 0, 28, 29, 30) == VU_READ); +} + +test paren_around_arg_slot_and_list_count_read_a_call_site { + const s : str = "f(a, g(b), c)"; + assert(paren_around(s, 0, 7) == 6); + assert(paren_around(s, 0, 11) == 1); + assert(paren_around(s, 0, 2) == 1); + assert(paren_around(s, 2, 11) == s.len); + assert(paren_around(s, 0, 0) == s.len); + assert(paren_around(s, 0, 13) == s.len); + const t : str = "f(a, g(b, c), d)"; + assert(arg_slot(t, 1, 2) == 0); + assert(arg_slot(t, 1, 5) == 1); + assert(arg_slot(t, 1, 14) == 2); + assert(arg_slot(t, 1, 7) == t.len); + assert(arg_slot(t, 1, 10) == t.len); + assert(arg_slot(t, 1, 1) == 0); + assert(arg_slot(t, 1, 15) == 2); + assert(arg_slot("f(a), g(b)", 1, 7) == 10); + assert(arg_slot("f(a, b[1, 2], c)", 1, 14) == 2); + assert(list_count("1, 2, 3", 0, 7) == 3); + assert(list_count("1, 2, 3,", 0, 8) == 3); + assert(list_count("1", 0, 1) == 1); + assert(list_count("", 0, 0) == 0); + assert(list_count("f(1, 2), 3", 0, 10) == 2); + assert(list_count("[1, 2], [3]", 0, 11) == 2); + assert(list_count("a, b", 3, 4) == 1); + var st : [64]usize = [0] ** 64; + const consts : str = "const N: usize = 3; N"; + assert(vec_len_ok("3", &st, 0, 1)); + assert(!vec_len_ok("3usize", &st, 0, 6)); + assert(vec_len_ok(consts, &st, 20, 21)); + assert(!vec_len_ok("N", &st, 0, 1)); + assert(!vec_len_ok("n", &st, 0, 1)); + assert(!vec_len_ok("3 + 1", &st, 0, 5)); + assert(!vec_len_ok("", &st, 0, 0)); + assert(!vec_len_ok("a.len()", &st, 0, 7)); + assert(vec_len_ok("12", &st, 0, 2)); +} + +test ret_word_vec_first_type_and_put_vec_elem_name_the_element_type_of_a_vec { + const defs : str = "enum Mode { A, B }\nstruct Node { v: u8 }\nstruct Pt { x: u8 }\nfn mk() -> Pt { Pt { x: 1 } }\nfn sf() -> Self { }\nfn gen() -> Vec { }\nfn none() { }\nfn two() -> u8 { 1 }\nfn two() -> u16 { 1 }\nfn same() -> u8 { 1 }\nfn same() -> u8 { 2 }\n"; + var out : [64]u8 = undefined; + var st : [1024]usize = [0] ** 1024; + const mk : usize = find_tok(defs, 0, "mk"); + const sf : usize = find_tok(defs, 0, "sf"); + const gen : usize = find_tok(defs, 0, "gen"); + const none : usize = find_tok(defs, 0, "none"); + const two : usize = find_tok(defs, 0, "two"); + const same : usize = find_tok(defs, 0, "same"); + const pt : usize = find_tok(defs, mk, "Pt"); + assert(ret_word(defs, mk, mk + 2) == pt); + assert(ret_word(defs, sf, sf + 2) == defs.len); + assert(ret_word(defs, gen, gen + 3) == defs.len); + assert(ret_word(defs, none, none + 4) == defs.len); + assert(ret_word(defs, two, two + 3) == defs.len); + assert(word_is(defs, ret_word(defs, same, same + 4), tok_end(defs, ret_word(defs, same, same + 4)), "u8")); + assert(ret_word(defs, 0, 4) == defs.len); + const firsts : [12]str = ["5u8", "5", "-5i32", "\"a\"", "r\"a\"", "true", "Mode::A", "Node { v: 1 }", "mk()", "sf()", "x", "Other::A"]; + const wants : [12]str = ["u8", "", "i32", "[]const u8", "[]const u8", "bool", "Mode", "Node", "Pt", "", "", ""]; + var i : usize = 0; + while (i < 12) { + var buf : [256]u8 = [0] ** 256; + var bs : [64]usize = [0] ** 64; + puts(&bs, &buf, defs); + const e0 : usize = bs[W]; + puts(&bs, &buf, firsts[i]); + puts(&bs, &buf, " ]"); + const src : []const u8 = buf[0 .. bs[W]]; + clear(&st); + const ok : bool = vec_first_type(src, &st, &out, e0); + assert(ok == (wants[i].len > 0)); + assert(out_is(st[W], &out, 0, wants[i])); + i = i + 1; + } + clear(&st); + st[P] = 0; + put_elem_ty("x u32", &st, &out, 2); + assert(out_is(st[W], &out, 0, "u32")); + assert(st[P] == 0); + clear(&st); + st[P] = 1; + put_elem_ty("&str", &st, &out, 0); + assert(out_is(st[W], &out, 0, "[]const u8")); + assert(st[P] == 1); + const typed : str = "Vec = vec![1]"; + clear(&st); + st[LETTY] = 0; + assert(put_vec_elem(typed, &st, &out, true, 14, 0, 0, 0, 0)); + assert(out_is(st[W], &out, 0, "u16")); + const un : str = "Vec<_> = vec![1u8]"; + clear(&st); + st[LETTY] = 0; + assert(put_vec_elem(un, &st, &out, true, 14, 0, 0, 0, 0)); + assert(out_is(st[W], &out, 0, "u8")); + clear(&st); + assert(!put_vec_elem("vec![1]", &st, &out, false, 5, 7, 7, 0, 1)); + assert(st[W] == 0); + const call : str = "fn g(a: &[u16]) {}\nlet v = vec![1]; g(&v);"; + clear(&st); + assert(put_vec_elem(call, &st, &out, false, 32, 35, 42, 23, 24)); + assert(out_is(st[W], &out, 0, "u16")); +} + +test vec_arg_elem_reads_the_parameter_the_first_borrow_of_a_vec_lands_on { + const head : str = "fn g(a: &[u16], n: u8) {}\nfn f() { let v = vec![1, 2]; "; + const calls : [6]str = ["g(&v, 1);", "g(1, &v);", "h(&v);", "g(&v + 1, 2);", "k(g(&v, 1));", "x; g(&v);"]; + const found : [6]bool = [true, false, false, false, true, true]; + var buf : [256]u8 = [0] ** 256; + var i : usize = 0; + while (i < 6) { + var bs : [64]usize = [0] ** 64; + puts(&bs, &buf, head); + const lo : usize = bs[W]; + puts(&bs, &buf, calls[i]); + const hi : usize = bs[W]; + puts(&bs, &buf, " }"); + const src : []const u8 = buf[0 .. bs[W]]; + const el : usize = vec_arg_elem(src, lo, hi, 39, 40); + if (found[i]) { + assert(el == 10); + } else { + assert(el == src.len); + } + i = i + 1; + } +} + +test let_vec_writes_a_read_only_vec_as_a_typed_array_and_refuses_the_rest { + const head : str = "enum Mode { A, B }\nstruct Node { v: u8 }\nstruct Pt { x: u8 }\nfn mk() -> Pt { Pt { x: 1 } }\nfn g(a: &[u16]) {}\nfn h(a: &[u8]) {}\nfn f(n: usize) { "; + const ins : [20]str = ["let v = vec![1u8, 2, 3]; h(&v);", "let v: Vec = vec![1, 2]; g(&v);", "let mut v = vec![0u8; 4]; h(&v);", "let v = vec![1, 2]; g(&v);", "let v: Vec = vec![]; h(&v);", "let v = vec![\"a\", \"b\"]; x(&v);", "let v = vec![true]; x(&v);", "let v = vec![Mode::A, Mode::B]; x(&v);", "let v = vec![Node { v: 1 }]; x(&v);", "let v = vec![mk()]; x(&v);", "let v = vec![0u8; 3]; h(&v);", "let v = vec![1u8]; v.push(2);", "let v = vec![1u8]; x(v);", "let v = vec![1, 2]; v.len();", "let v = vec![1u8; n]; h(&v);", "let v = vec![1u8; 3 + 1]; h(&v);", "let v = vec![-1i32, 2]; x(&v);", "let v = vec![1u8, 2,]; h(&v);", "let v = vec![0u8; 2]; v[0] = 1;", "let v: Vec<_> = vec![1u8]; h(&v);"]; + const outs : [20]str = ["const v : [3]u8 = [@as(u8, 1), 2, 3];", "const v : [2]u16 = [1, 2];", "var v : [4]u8 = [@as(u8, 0)] ** 4;", "const v : [2]u16 = [1, 2];", "const v : [0]u8 = [];", "const v : [2][]const u8 = [\"a\", \"b\"];", "const v : [1]bool = [true];", "const v : [2]Mode = [Mode.A, Mode.B];", "const v : [1]Node = [Node{ .v = 1 }];", "const v : [1]Pt = [mk()];", "const v : [3]u8 = [@as(u8, 0)] ** 3;", "", "", "", "", "", "const v : [2]i32 = [-@as(i32, 1), 2];", "const v : [2]u8 = [@as(u8, 1), 2];", "", "const v : [1]u8 = [@as(u8, 1)];"]; + const code : [20]usize = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, R_VECMUT, R_VECMOVE, R_VECTYPE, R_VECTYPE, R_VECTYPE, 0, 0, R_VECMUT, 0]; + var buf : [1024]u8 = [0] ** 1024; + var st : [1024]usize = [0] ** 1024; + var out : [256]u8 = undefined; + var i : usize = 0; + while (i < 20) { + var bs : [64]usize = [0] ** 64; + puts(&bs, &buf, head); + const a : usize = bs[W]; + puts(&bs, &buf, ins[i]); + puts(&bs, &buf, " }"); + const src : []const u8 = buf[0 .. bs[W]]; + clear(&st); + st[FLO] = find_tok(src, 0, "f") - 3; + st[P] = a; + stmt(src, &st, &out, M_STMT); + assert(st[ERR] == code[i]); + if (code[i] == 0) { assert(out_is(st[W], &out, 0, outs[i])); } + i = i + 1; + } + const direct : str = "fn g(a: &[u16]) {}\nfn f() { let v = vec![1, 2]; g(&v); }"; + clear(&st); + st[FLO] = 19; + st[P] = 34; + let_vec(direct, &st, &out, false, 32, 33, false, 36); + assert(st[ERR] == 0); + assert(out_is(st[W], &out, 0, "const v : [2]u16 = [1, 2];")); +} + +test let_stmt_let_value_expr_stmt_and_local_const_write_a_binding { + var out : [128]u8 = undefined; + var st : [1024]usize = [0] ** 1024; + const rows : [10]str = ["let k = 5;", "let mut k = 5;", "let k: u8 = 5;", "let k = 5u8;", "let k: u8;", "let _ = a;", "let _x = a;", "let k: [u8; 0] = [];", "let k: u32 = if a { 1 } else { 2 };", "let _q = f(a);"]; + const want : [10]str = ["const k = 5;", "var k = 5;", "const k : u8 = 5;", "const k : u8 = 5;", "var k : u8 = undefined;", "_ = a;", "_ = a;", "const k : [0]u8 = [];", "var k : u32 = undefined;\nif (a) {\n k = 1;\n} else {\n k = 2;\n}", "_ = f(a);"]; + var i : usize = 0; + while (i < 10) { + clear(&st); + let_stmt(rows[i], &st, &out); + assert(st[ERR] == 0); + assert(out_is(st[W], &out, 0, want[i])); + i = i + 1; + } + clear(&st); + let_stmt("let k;", &st, &out); + assert(st[ERR] == R_VALUE); + assert(st[AT] == 4); + clear(&st); + let_stmt("let (a, b) = x;", &st, &out); + assert(st[ERR] == R_TUPLE); + clear(&st); + let_stmt("let k = if a { 1 } else { 2 };", &st, &out); + assert(st[ERR] == R_VALUE); + clear(&st); + let_stmt("let k: u8 = loop { break; };", &st, &out); + assert(st[ERR] == R_VALUE); + clear(&st); + st[P] = 5; + let_value("let k: u8 = 5;", &st, &out, false, 4, 5, true, 12); + assert(out_is(st[W], &out, 0, "const k : u8 = 5;")); + assert(st[P] == 14); + clear(&st); + st[P] = 6; + let_value("let k = 5u8;", &st, &out, false, 4, 5, false, 8); + assert(out_is(st[W], &out, 0, "const k : u8 = 5;")); + clear(&st); + st[P] = 5; + let_value("let k;", &st, &out, false, 4, 5, false, 6); + assert(st[ERR] == R_VALUE); + clear(&st); + st[P] = 5; + let_value("let k: u8;", &st, &out, true, 4, 5, true, 10); + assert(out_is(st[W], &out, 0, "var k : u8 = undefined;")); + clear(&st); + expr_stmt("a = a + 1;", &st, &out); + assert(out_is(st[W], &out, 0, "a = a + 1")); + assert(st[P] == 9); + clear(&st); + expr_stmt("a <<= 2;", &st, &out); + assert(out_is(st[W], &out, 0, "a <<= 2")); + clear(&st); + expr_stmt("g(a);", &st, &out); + assert(out_is(st[W], &out, 0, "g(a)")); + clear(&st); + expr_stmt("a.b = 1;", &st, &out); + assert(out_is(st[W], &out, 0, "a.b = 1")); + clear(&st); + local_const("const D: u8 = 1;", &st, &out); + assert(out_is(st[W], &out, 0, "const D : u8 = 1;")); + clear(&st); + local_const("const var: u8 = 1;", &st, &out); + assert(out_is(st[W], &out, 0, "const var_ : u8 = 1;")); + clear(&st); + local_const("const D = 1;", &st, &out); + assert(st[ERR] == R_SYNTAX); +} + +test return_jump_if_else_and_the_if_let_forms_write_their_blocks { + var out : [256]u8 = undefined; + var st : [1024]usize = [0] ** 1024; + return_stmt("return a;", &st, &out); + assert(out_is(st[W], &out, 0, "return a;")); + assert(st[P] == 9); + clear(&st); + return_stmt("return;", &st, &out); + assert(out_is(st[W], &out, 0, "return;")); + clear(&st); + return_stmt("return a + 1; x", &st, &out); + assert(out_is(st[W], &out, 0, "return a + 1;")); + assert(st[P] == 14); + clear(&st); + return_stmt("return }", &st, &out); + assert(out_is(st[W], &out, 0, "return;")); + clear(&st); + jump_stmt("break;", &st, &out, 0, 5); + assert(out_is(st[W], &out, 0, "break;")); + assert(st[P] == 6); + clear(&st); + jump_stmt("continue }", &st, &out, 0, 8); + assert(out_is(st[W], &out, 0, "continue;")); + clear(&st); + jump_stmt("break 1;", &st, &out, 0, 5); + assert(st[ERR] == R_LABEL); + assert(st[AT] == 6); + clear(&st); + jump_stmt("break 'a;", &st, &out, 0, 5); + assert(st[ERR] == R_LABEL); + const ifs : [8]str = ["if a > 1 { g(a); }", "if a { g(a); } else { g(b); }", "if a { g(a); } else if b { g(b); } else { g(c); }", "if a { 1 } else { 2 }", "if let Some(x) = o { g(x); }", "if let Some(x) = o { g(x); } else { g(0); }", "if a { }", "if a + b > 1 { g(a); }"]; + const ifw : [8]str = ["if (a > 1) {\n g(a);\n}", "if (a) {\n g(a);\n} else {\n g(b);\n}", "if (a) {\n g(a);\n} else if (b) {\n g(b);\n} else {\n g(c);\n}", "if (a) {\n return 1;\n} else {\n return 2;\n}", "if (o != null) {\n const x = o.?;\n g(x);\n}", "if (o != null) {\n const x = o.?;\n g(x);\n} else {\n g(0);\n}", "if (a) {\n}", "if (a + b > 1) {\n g(a);\n}"]; + const ifm : [8]u8 = [M_STMT, M_STMT, M_STMT, M_RET, M_STMT, M_STMT, M_STMT, M_STMT]; + var i : usize = 0; + while (i < 8) { + clear(&st); + if_stmt(ifs[i], &st, &out, ifm[i]); + assert(st[ERR] == 0); + assert(out_is(st[W], &out, 0, ifw[i])); + i = i + 1; + } + clear(&st); + st[P] = 15; + else_chain("if a { g(a); } else { g(b); }", &st, &out, M_STMT); + assert(out_is(st[W], &out, 0, " else {\n g(b);\n}")); + clear(&st); + st[P] = 15; + else_chain("if a { g(a); } else if b { g(b); }", &st, &out, M_STMT); + assert(out_is(st[W], &out, 0, " else if (b) {\n g(b);\n}")); + clear(&st); + st[P] = 15; + else_chain("if a { g(a); } else if let Some(x) = o { }", &st, &out, M_STMT); + assert(st[ERR] == R_IFLET); + clear(&st); + else_chain("x", &st, &out, M_STMT); + assert(st[W] == 0); + assert(st[P] == 0); + assert(named_in_block("e { g(e); }", 2, 0, 1)); + assert(named_in_block("e { { e } }", 2, 0, 1)); + assert(!named_in_block("e { g(f); }", 2, 0, 1)); + assert(!named_in_block("e { }", 2, 0, 1)); + assert(!named_in_block("e { ee }", 2, 0, 1)); + assert(!named_in_block("e { x } e", 2, 0, 1)); +} + +test if_let_and_while_let_read_a_call_once_and_unwrap_it { + const defs : str = "fn ok() -> Result<(), E> { Ok(()) }\nfn h(a: u8) -> Option { None }\n"; + var buf : [512]u8 = [0] ** 512; + var out : [256]u8 = undefined; + var st : [1024]usize = [0] ** 1024; + const ins : [13]str = ["let Some(x) = o { g(x); }", "let Ok(x) = o { g(x); }", "let Some(x) = h(a) { g(x); }", "let Err(e) = o { }", "let Err(_) = o { }", "let Err(e) = ok() { }", "let Some(x) = o + 1 { g(x); }", "let Some(x) = o { g(x); } else { g(0); }", "let Err(e) = o { g(e); }", "let Some((a, b)) = o { }", "let Some(1) = o { }", "let Foo(x) = o { }", "let Some(_) = o { }"]; + const want : [13]str = ["if (o != null) {\n const x = o.?;\n g(x);\n}", "if (o != null) {\n const x = o.?;\n g(x);\n}", "const x_t27o = h(a);\nif (x_t27o != null) {\n const x = x_t27o.?;\n g(x);\n}", "if (o == null) {\n}", "if (o == null) {\n}", "if ((ok()) == false) {\n}", "if ((o + 1) != null) {\n const x = (o + 1).?;\n g(x);\n}", "if (o != null) {\n const x = o.?;\n g(x);\n} else {\n g(0);\n}", "", "", "", "", "if (o != null) {\n const _ = o.?;\n}"]; + const code : [13]usize = [0, 0, 0, 0, 0, 0, 0, 0, R_IFLET, R_TUPLE, R_IFLET, R_IFLET, 0]; + var i : usize = 0; + while (i < 13) { + var bs : [64]usize = [0] ** 64; + puts(&bs, &buf, defs); + const a : usize = bs[W]; + puts(&bs, &buf, ins[i]); + const src : []const u8 = buf[0 .. bs[W]]; + clear(&st); + st[P] = a; + if_let(src, &st, &out, M_STMT); + assert(st[ERR] == code[i]); + if (code[i] == 0) { assert(out_is(st[W], &out, 0, want[i])); } + i = i + 1; + } + const wl : [5]str = ["let Some(x) = it() { g(x); }", "let Ok(x) = it() { }", "let Err(e) = it() { }", "let Some((a, b)) = it() { }", "let Some(1) = it() { }"]; + const wcode : [5]usize = [0, 0, R_IFLET, R_TUPLE, R_IFLET]; + const wwant : [2]str = ["while (true) {\n const x_t27o = it();\n if (x_t27o == null) {\n break;\n }\n const x = x_t27o.?;\n g(x);\n}", "while (true) {\n const x_t27o = it();\n if (x_t27o == null) {\n break;\n }\n const x = x_t27o.?;\n}"]; + var j : usize = 0; + while (j < 5) { + clear(&st); + while_let(wl[j], &st, &out); + assert(st[ERR] == wcode[j]); + if (j < 2) { assert(out_is(st[W], &out, 0, wwant[j])); } + j = j + 1; + } +} + +test each_slice_for_each_array_for_and_for_stmt_write_the_loop_forms { + var out : [256]u8 = undefined; + var st : [1024]usize = [0] ** 1024; + each_slice("v.iter() {", &st, &out); + assert(out_is(st[W], &out, 0, "v")); + assert(st[FORHDR] == 0); + assert(st[ERR] == 0); + clear(&st); + each_slice("&v {", &st, &out); + assert(out_is(st[W], &out, 0, "v")); + clear(&st); + each_slice("&mut v {", &st, &out); + assert(st[ERR] == R_MUTREF); + clear(&st); + each_slice("v.iter().enumerate() {", &st, &out); + assert(out_is(st[W], &out, 0, "v")); + assert(st[ENUMSEEN] == 1); + assert(st[FORHDR] == 0); + clear(&st); + each_slice("v {", &st, &out); + assert(out_is(st[W], &out, 0, "v")); + assert(st[ENUMSEEN] == 0); + clear(&st); + st[P] = 9; + for_each("for x in v { g(x); }", &st, &out, 0, 0, 4, 5); + assert(out_is(st[W], &out, 0, "for x in v {\n g(x);\n}")); + assert(st[ERR] == 0); + clear(&st); + st[P] = 14; + for_each("for (i, x) in v.iter().enumerate() { g(x); }", &st, &out, 5, 6, 8, 9); + assert(out_is(st[W], &out, 0, "for i in 0..v.len {\n const x = v[i];\n g(x);\n}")); + clear(&st); + st[P] = 9; + for_each("for x in v.iter().enumerate() { }", &st, &out, 0, 0, 4, 5); + assert(st[ERR] == R_ITER); + clear(&st); + st[P] = 14; + for_each("for (i, x) in v { }", &st, &out, 5, 6, 8, 9); + assert(st[ERR] == R_ITER); + clear(&st); + st[P] = 9; + for_each("for x in [1, 2] { }", &st, &out, 0, 0, 4, 5); + assert(st[ERR] == R_ITER); + const fa : str = "for v in [1u8, 2] { g(v); }"; + clear(&st); + array_for(fa, &st, &out, 0, 4, 5, 9); + assert(out_is(st[W], &out, 0, "const t27o_a1 : [2]u8 = [@as(u8, 1), 2];\nfor v in t27o_a1 {\n g(v);\n}")); + assert(st[ERR] == 0); + const fb : str = "for v in [\"a\", \"b\", \"c\"] { }"; + clear(&st); + array_for(fb, &st, &out, 0, 4, 5, 9); + assert(out_is(st[W], &out, 0, "const t27o_a1 : [3][]const u8 = [\"a\", \"b\", \"c\"];\nfor v in t27o_a1 {\n}")); + const fc : str = "enum M { A, B }\nfor v in [M::A, M::B] { }"; + clear(&st); + array_for(fc, &st, &out, 16, 20, 21, 25); + assert(out_is(st[W], &out, 0, "const t27o_a2 : [2]M = [M.A, M.B];\nfor v in t27o_a2 {\n}")); + const fd : str = "for v in [true, false] { }"; + clear(&st); + array_for(fd, &st, &out, 0, 4, 5, 9); + assert(out_is(st[W], &out, 0, "const t27o_a1 : [2]bool = [true, false];\nfor v in t27o_a1 {\n}")); + const bad : [5]str = ["for v in [1, 2] { }", "for v in [] { }", "for v in [0u8; 3] { }", "for v in [1u8, 2] ", "for v in [a, b] { }"]; + var i : usize = 0; + while (i < 5) { + clear(&st); + array_for(bad[i], &st, &out, 0, 4, 5, 9); + assert(st[ERR] == R_ITER); + i = i + 1; + } + const fs : [14]str = ["for i in 0..4 { g(i); }", "for i in 0..=4 { }", "for i in 1..n { }", "for i in 0..m { }", "for x in v { }", "for (i, x) in v.iter().enumerate() { }", "for x in [1u8, 2] { }", "for x in &[1u8, 2] { }", "for _ in 0..3 { }", "for x in &v { }", "for x in v.iter() { }", "for i in 0..v.len() { }", "for (i, x) in 0..3 { }", "for (1, x) in v { }"]; + const fw : [14]str = ["for i in 0..4 {\n g(i);\n}", "for i in 0..4 + 1 {\n}", "for i in 1..n {\n}", "for i_t27o in 0..m {\n const i : u32 = i_t27o as u32;\n}", "for x in v {\n}", "for i in 0..v.len {\n const x = v[i];\n}", "const t27o_a1 : [2]u8 = [@as(u8, 1), 2];\nfor x in t27o_a1 {\n}", "const t27o_a1 : [2]u8 = [@as(u8, 1), 2];\nfor x in t27o_a1 {\n}", "for _ in 0..3 {\n}", "for x in v {\n}", "for x in v {\n}", "for i in 0..v.len {\n}", "", ""]; + const fc2 : [14]usize = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, R_TUPLE, R_TUPLE]; + var buf : [256]u8 = [0] ** 256; + var j : usize = 0; + while (j < 14) { + var bs : [64]usize = [0] ** 64; + puts(&bs, &buf, "fn f(n: usize, m: u32, v: &[u8]) { "); + const a : usize = bs[W]; + puts(&bs, &buf, fs[j]); + puts(&bs, &buf, " }"); + const src : []const u8 = buf[0 .. bs[W]]; + clear(&st); + st[FLO] = 0; + st[P] = a; + for_stmt(src, &st, &out); + assert(st[ERR] == fc2[j]); + if (fc2[j] == 0) { assert(out_is(st[W], &out, 0, fw[j])); } + j = j + 1; + } +} + +test put_scrut_pattern_and_patterns_write_a_match_arm_as_a_condition { + var out : [128]u8 = undefined; + var st : [64]usize = [0] ** 64; + st[P] = 7; + put_scrut("a + 1 ;", &st, &out, 0, 0, false); + assert(out_is(st[W], &out, 0, "a + 1")); + assert(st[P] == 7); + clear(&st); + put_scrut("a + 1 ;", &st, &out, 0, 0, true); + assert(out_is(st[W], &out, 0, "(a + 1)")); + clear(&st); + put_scrut("a + 1 ;", &st, &out, 0, 5, true); + assert(out_is(st[W], &out, 0, "m5")); + clear(&st); + put_scrut("x", &st, &out, 0, 12, false); + assert(out_is(st[W], &out, 0, "m12")); + const pats : [20]str = ["1", "-1", "'a'", "b'a'", "1..=5", "-3..=-1", "'a'..='z'", "\"s\"", "r\"s\"", "true", "false", "None", "Mode::A", "Mode::MAX", "Other", "Mode::A(v)", "Mode::A::B", "Some(v)", "(a, b)", "v"]; + const want : [20]str = ["x == 1", "x == -1", "x == 'a'", "x == 'a'", "(x >= 1 and x <= 5)", "(x >= -3 and x <= -1)", "(x >= 'a' and x <= 'z')", "type_text::same(x, \"s\")", "type_text::same(x, \"s\")", "x == true", "x == false", "x == null", "x == Mode.A", "x == Mode_MAX", "x == Other", "", "", "", "", ""]; + const code : [20]usize = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, R_DATA, R_DATA, R_PATTERN, R_PATTERN, R_PATTERN]; + var buf : [128]u8 = [0] ** 128; + var i : usize = 0; + while (i < 20) { + var bs : [64]usize = [0] ** 64; + puts(&bs, &buf, "x { "); + puts(&bs, &buf, pats[i]); + const src : []const u8 = buf[0 .. bs[W]]; + clear(&st); + st[P] = 4; + pattern(src, &st, &out, 0, 0, false); + assert(st[ERR] == code[i]); + if (code[i] == 0) { assert(out_is(st[W], &out, 0, want[i])); } + i = i + 1; + } + clear(&st); + st[P] = 3; + pattern("x {", &st, &out, 0, 0, false); + assert(st[ERR] == R_SYNTAX); + clear(&st); + st[P] = 8; + pattern("a + 1 { 2", &st, &out, 0, 0, true); + assert(out_is(st[W], &out, 0, "(a + 1) == 2")); + clear(&st); + st[P] = 4; + pattern("x { 1 | 2 | 3", &st, &out, 0, 0, false); + assert(out_is(st[W], &out, 0, "x == 1")); + clear(&st); + st[P] = 4; + patterns("x { 1 | 2 | 3", &st, &out, 0, 0, false); + assert(out_is(st[W], &out, 0, "x == 1 or x == 2 or x == 3")); + assert(st[P] == 13); + clear(&st); + st[P] = 4; + patterns("x { 1..=5 | 9", &st, &out, 0, 0, false); + assert(out_is(st[W], &out, 0, "(x >= 1 and x <= 5) or x == 9")); + clear(&st); + st[P] = 4; + patterns("x { \"a\" | \"b\"", &st, &out, 0, 0, false); + assert(out_is(st[W], &out, 0, "type_text::same(x, \"a\") or type_text::same(x, \"b\")")); + assert(st[NEQ] == 1); + clear(&st); + st[P] = 4; + patterns("x { Some(v) | 2", &st, &out, 0, 0, false); + assert(st[ERR] == R_PATTERN); + clear(&st); + st[P] = 4; + patterns("x { 1 | 2", &st, &out, 0, 3, false); + assert(out_is(st[W], &out, 0, "m3 == 1 or m3 == 2")); +} + +test arm_expr_and_match_stmt_write_the_arms_of_a_match { + var out : [256]u8 = undefined; + var st : [1024]usize = [0] ** 1024; + const arms : [9]str = ["return a, _ => 0 }", "break, _ => 0 }", "continue }", "g(a), _ => 0 }", "if a { 1 } else { 2 } }", "assert!(a) }", "() }", "a + 1 }", "match a { 1 => 2, _ => 3 } }"]; + const modes : [9]u8 = [M_STMT, M_STMT, M_STMT, M_RET, M_RET, M_STMT, M_STMT, M_SET, M_RET]; + const want : [9]str = ["return a;", "break;", "continue;", "return g(a);", "if (a) {\n return 1;\n} else {\n return 2;\n}", "assert(a);", "", "a = a + 1;", "if (a == 1) {\n return 2;\n} else {\n return 3;\n}"]; + var i : usize = 0; + while (i < 9) { + clear(&st); + st[TLO] = 0; + st[THI] = 1; + arm_expr(arms[i], &st, &out, modes[i]); + assert(st[ERR] == 0); + assert(out_is(st[W], &out, 0, want[i])); + i = i + 1; + } + const ms : [9]str = ["match a { 1 => g(1), _ => g(2) }", "match a { 1 => { g(1); } 2 | 3 => { g(2); } _ => { g(3); } }", "match g(a) { 1 => 1, _ => 2 }", "match a { 1 => 1, n => n }", "match a { _ => 1 }", "match s { \"x\" => 1, \"y\" => 2, _ => 3 }", "match a { 1 => 1, 2 => 2 }", "match a { 1 if ok => 1, _ => 2 }", "match a 1 => 1"]; + const mm : [9]u8 = [M_STMT, M_STMT, M_RET, M_RET, M_STMT, M_RET, M_RET, M_RET, M_RET]; + const mw : [9]str = ["if (a == 1) {\n g(1);\n} else {\n g(2);\n}", "if (a == 1) {\n g(1);\n} else if (a == 2 or a == 3) {\n g(2);\n} else {\n g(3);\n}", "const m1 = g(a);\nif (m1 == 1) {\n return 1;\n} else {\n return 2;\n}", "if (a == 1) {\n return 1;\n} else {\n const n = a;\n return n;\n}", "if (true) {\n 1;\n}", "if (type_text::same(s, \"x\")) {\n return 1;\n} else if (type_text::same(s, \"y\")) {\n return 2;\n} else {\n return 3;\n}", "if (a == 1) {\n return 1;\n} else {\n return 2;\n}", "", ""]; + const mc : [9]usize = [0, 0, 0, 0, 0, 0, 0, R_PATTERN, R_SYNTAX]; + var j : usize = 0; + while (j < 9) { + clear(&st); + match_stmt(ms[j], &st, &out, mm[j]); + assert(st[ERR] == mc[j]); + if (mc[j] == 0) { assert(out_is(st[W], &out, 0, mw[j])); } + j = j + 1; + } +} + +test impl_header_struct_value_and_the_result_asserts_read_an_impl_and_a_comparison { + var st : [1024]usize = [0] ** 1024; + impl_header("impl Pt { }", &st, 0); + assert(st[OLO] == 5); + assert(st[OHI] == 7); + impl_header("impl Pt { }", &st, 0); + assert(st[OLO] == 8); + assert(st[OHI] == 10); + impl_header("impl Default for Pt { }", &st, 0); + assert(st[OLO] == 17); + assert(st[OHI] == 19); + impl_header("impl Tr for Pt { }", &st, 0); + assert(st[OLO] == 18); + impl_header("x impl Pt { }", &st, 2); + assert(st[OLO] == 7); + const defs : str = "struct Pt { x: u8 }\nstruct W(u8);\nfn mk() -> Pt { Pt { x: 1 } }\nfn nm() -> u8 { 1 }\nimpl Pt { fn new() -> Self { Pt { x: 0 } } }\n"; + var p : [1024]usize = [0] ** 1024; + const w : usize = find_tok(defs, 0, "W"); + add_name(defs, &p, K_TUPLE, w, w + 1, 0, 0); + const rows : [10]str = ["Pt { x: 1 }", "W(1)", "mk()", "nm()", "Pt::new()", "p.mk()", "x", "5", "Q { }", "Q(1)"]; + const want : [10]bool = [true, true, true, false, true, true, false, false, false, false]; + var buf : [256]u8 = [0] ** 256; + var i : usize = 0; + while (i < 10) { + var bs : [64]usize = [0] ** 64; + puts(&bs, &buf, defs); + const e : usize = bs[W]; + puts(&bs, &buf, rows[i]); + const src : []const u8 = buf[0 .. bs[W]]; + assert(struct_value(src, &p, e) == want[i]); + i = i + 1; + } + assert(!struct_value(defs, &p, defs.len)); + assert(result_arg("f(x), Ok(1)", 0) == 6); + assert(result_arg("f(x), Err(e)", 0) == 6); + assert(result_arg("f(x), 1", 0) == 7); + assert(result_arg("f(x)", 0) == 4); + assert(result_arg("a, Ok", 0) == 5); + assert(result_arg("a, Ok()", 0) == 3); + assert(result_arg("a, b, Ok(1)", 0) == 11); + var out : [128]u8 = undefined; + var ws : [64]usize = [0] ** 64; + put_result_ref("a + 1", &ws, &out, 0, false, true, 3); + assert(out_is(ws[W], &out, 0, "(a + 1)")); + clear(&ws); + put_result_ref("a + 1", &ws, &out, 0, false, false, 3); + assert(out_is(ws[W], &out, 0, "a + 1")); + clear(&ws); + put_result_ref("a + 1", &ws, &out, 0, true, true, 3); + assert(out_is(ws[W], &out, 0, "t27o_r3")); + clear(&ws); + ws[P] = 3; + put_result_ref("a + 1", &ws, &out, 0, false, false, 3); + assert(ws[P] == 3); +} + +test macro_stmt_writes_the_assert_forms_and_result_asserts { + const head : str = "struct Pt { x: u8 }\nfn g(x: u32) -> Result { Ok(x) }\nfn ok() -> Result<(), E> { Ok(()) }\nfn f(a: u32, b: u32, s: &str, o: Option) { "; + const ins : [22]str = ["assert!(a > 1);", "assert!(a > 1, \"msg\");", "assert_eq!(a, 1);", "assert_ne!(a, b);", "assert_eq!(a + 1, b);", "assert_eq!(s, \"x\");", "assert_ne!(s, \"x\");", "assert_eq!(\"x\", s);", "assert_eq!(a, b, \"m {}\", a);", "debug_assert!(a);", "debug_assert_eq!(a, b);", "debug_assert_ne!(a, b);", "assert_eq!(g(a), Err(e));", "assert_ne!(g(a), Err(e));", "assert_eq!(ok(), Ok(()));", "assert_eq!(ok(), Err(e));", "assert_ne!(ok(), Ok(()));", "assert_eq!(o, Ok(1));", "assert_eq!(a, Pt { x: 1 });", "println!(\"x\");", "assert_eq!(ok(), Ok(1));", "assert!(a);"]; + const outs : [22]str = ["assert(a > 1);", "assert(a > 1);", "assert(a == 1);", "assert(a != b);", "assert(a + 1 == b);", "assert(type_text::same(s, \"x\"));", "assert(!type_text::same(s, \"x\"));", "assert(type_text::same(\"x\", s));", "assert(a == b);", "assert(a);", "assert(a == b);", "assert(a != b);", "// t27o: Err payload dropped (Result is ?T)\n assert(g(a) == null);", "// t27o: Err payload dropped (Result is ?T)\n assert(g(a) != null);", "assert((ok()) == true);", "// t27o: Err payload dropped (Result<(), E> is a bool)\n assert((ok()) == false);", "assert((ok()) == false);", "assert(o != null);\n assert(o.? == 1);", "", "", "", "assert(a);"]; + const code : [22]usize = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, R_STRUCTEQ, R_MACRO, R_TYPE, 0]; + var buf : [1024]u8 = [0] ** 1024; + var st : [1024]usize = [0] ** 1024; + var out : [512]u8 = undefined; + var i : usize = 0; + while (i < 22) { + var bs : [64]usize = [0] ** 64; + puts(&bs, &buf, head); + const a : usize = bs[W]; + puts(&bs, &buf, ins[i]); + puts(&bs, &buf, " }"); + const src : []const u8 = buf[0 .. bs[W]]; + clear(&st); + st[FLO] = find_tok(src, 0, "f") - 3; + st[IND] = 1; + st[P] = a; + macro_stmt(src, &st, &out, a, tok_end(src, a)); + assert(st[ERR] == code[i]); + if (code[i] == 0) { assert(out_is(st[W], &out, 0, outs[i])); } + i = i + 1; + } +} + +test result_assert_reads_a_call_once_into_a_temp_named_by_the_position_of_its_ok { + const head : str = "fn g(x: u32) -> Result { Ok(x) }\nfn f(a: u32) { "; + const ins : [2]str = ["assert_eq!(g(a), Ok(1));", "assert_ne!(g(a), Ok(1));"]; + var buf : [256]u8 = [0] ** 256; + var st : [1024]usize = [0] ** 1024; + var out : [512]u8 = undefined; + var want : [512]u8 = [0] ** 512; + var i : usize = 0; + while (i < 2) { + var bs : [64]usize = [0] ** 64; + puts(&bs, &buf, head); + const a : usize = bs[W]; + puts(&bs, &buf, ins[i]); + puts(&bs, &buf, " }"); + const src : []const u8 = buf[0 .. bs[W]]; + const r : usize = find_tok(src, a + 11, "Ok"); + assert(r < src.len); + var ws : [64]usize = [0] ** 64; + if (i == 0) { + puts(&ws, &want, "const t27o_r"); + put_num(&ws, &want, r); + puts(&ws, &want, " = g(a);\n assert(t27o_r"); + put_num(&ws, &want, r); + puts(&ws, &want, " != null);\n assert(t27o_r"); + put_num(&ws, &want, r); + puts(&ws, &want, ".? == 1);"); + } else { + puts(&ws, &want, "const t27o_r"); + put_num(&ws, &want, r); + puts(&ws, &want, " = g(a);\n assert(t27o_r"); + put_num(&ws, &want, r); + puts(&ws, &want, " == null or t27o_r"); + put_num(&ws, &want, r); + puts(&ws, &want, ".? != 1);"); + } + clear(&st); + st[FLO] = find_tok(src, 0, "f") - 3; + st[IND] = 1; + st[P] = a + 11; + result_assert(src, &st, &out, r, i == 1); + assert(st[ERR] == 0); + assert(out_is(st[W], &out, 0, want[0 .. ws[W]])); + i = i + 1; + } +} + +test alone_as_value_and_matches_macro_called_directly { + var out : [64]u8 = undefined; + var st : [64]usize = [0] ** 64; + puts(&st, &out, "x = y"); + assert(alone_as_value("y.f();", &out, 4, 3)); + assert(alone_as_value("y.f(),", &out, 4, 3)); + assert(alone_as_value("y.f() }", &out, 4, 3)); + assert(!alone_as_value("y.f() + 1;", &out, 4, 3)); + assert(!alone_as_value("y.f() * 2.0;", &out, 4, 3)); + clear(&st); + puts(&st, &out, "\n r"); + assert(alone_as_value("r.f();", &out, 5, 3)); + clear(&st); + puts(&st, &out, "r"); + assert(alone_as_value("r.f();", &out, 0, 3)); + clear(&st); + puts(&st, &out, "a r"); + assert(!alone_as_value("r.f();", &out, 2, 3)); + clear(&st); + puts(&st, &out, "x == r"); + assert(!alone_as_value("r.f();", &out, 5, 3)); + clear(&st); + puts(&st, &out, "a + = r"); + assert(!alone_as_value("r.f();", &out, 6, 3)); + clear(&st); + puts(&st, &out, "x = y"); + assert(!alone_as_value("y.f();", &out, 99, 3)); + clear(&st); + puts(&st, &out, "x = y"); + assert(!alone_as_value("y.f()", &out, 4, 3)); + clear(&st); + st[P] = 7; + matches_macro("matches!(a, 1 | 2)", &st, &out, 0, 7); + assert(out_is(st[W], &out, 0, "(a == 1 or a == 2)")); + assert(st[P] == 18); + assert(st[ERR] == 0); + clear(&st); + st[P] = 7; + matches_macro("matches!(a + 1, 1)", &st, &out, 0, 7); + assert(out_is(st[W], &out, 0, "((a + 1) == 1)")); + clear(&st); + st[P] = 7; + matches_macro("matches!(a, 1 if ok)", &st, &out, 0, 7); + assert(st[ERR] == R_PATTERN); + clear(&st); + st[P] = 7; + matches_macro("matches!(a)", &st, &out, 0, 7); + assert(st[ERR] == R_SYNTAX); +} From 0279c7a125a01bee53a9ee922d64f4cdac4e7337 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 19 Oct 2026 12:07:38 +0700 Subject: [PATCH 7/8] t27o: direct tests for the item helpers and the oracle writer of rust_convert.t27 -- docs, reasons, refusals, derives, params, fn heads, stubs, sample values, calls and recorded fields (Closes #10825) Tests only; no non-test line changes. The 64-bit unsigned sampling defect is #10864. Co-Authored-By: Claude Sonnet 5.5 --- specs/tools/t27o/rust_convert.t27 | 981 ++++++++++++++++++++++++++++++ 1 file changed, 981 insertions(+) diff --git a/specs/tools/t27o/rust_convert.t27 b/specs/tools/t27o/rust_convert.t27 index bb60a96adb..a8f9252131 100644 --- a/specs/tools/t27o/rust_convert.t27 +++ b/specs/tools/t27o/rust_convert.t27 @@ -15679,3 +15679,984 @@ test alone_as_value_and_matches_macro_called_directly { matches_macro("matches!(a)", &st, &out, 0, 7); assert(st[ERR] == R_SYNTAX); } + +// ---------------------------------------------------------------- direct tests: items and refusals + +test put_docs_writes_the_doc_lines_above_an_item_and_nothing_else { + var out : [128]u8 = undefined; + var st : [64]usize = [0] ** 64; + put_docs("/// doc one\n/// doc two\nfn f() {}", &st, &out, 24); + assert(out_is(st[W], &out, 0, "/// doc one\n/// doc two\n")); + clear(&st); + put_docs(" /// a\n fn f()", &st, &out, 14); + assert(out_is(st[W], &out, 0, "/// a\n")); + clear(&st); + put_docs("//// x\n/// y\nfn f", &st, &out, 13); + assert(out_is(st[W], &out, 0, "/// y\n")); + clear(&st); + put_docs("// no\n/// a\n/// b\nfn f", &st, &out, 18); + assert(out_is(st[W], &out, 0, "/// a\n/// b\n")); + clear(&st); + put_docs("x fn f", &st, &out, 2); + assert(st[W] == 0); + put_docs("/// a\n\nfn f", &st, &out, 7); + assert(st[W] == 0); + put_docs("// c\nfn f", &st, &out, 5); + assert(st[W] == 0); + put_docs("fn f", &st, &out, 0); + assert(st[W] == 0); + put_docs("/// x \nfn f", &st, &out, 8); + assert(out_is(st[W], &out, 0, "/// x\n")); + clear(&st); + st[MODE] = M_SOURCE; + put_docs("/// a\nfn f", &st, &out, 6); + assert(st[W] == 0); + clear(&st); + var buf : [32]u8 = [0] ** 32; + var bs : [64]usize = [0] ** 64; + puts(&bs, &buf, "/// a"); + put(&bs, &buf, 195); + put(&bs, &buf, 169); + put(&bs, &buf, B_LOWER_B); + put(&bs, &buf, B_NL); + const at : usize = bs[W]; + puts(&bs, &buf, "fn f"); + put_docs(buf[0 .. bs[W]], &st, &out, at); + assert(out_is(st[W], &out, 0, "/// a?b\n")); +} + +test put_reason_names_the_refusal_and_the_text_it_points_at { + const codes : [38]usize = [R_SYNTAX, R_GENERIC, R_TRAIT, R_CLOSURE, R_TRY, R_MACRO, R_TYPE, R_METHOD, R_TUPLE, R_IFLET, R_ITER, R_PATTERN, R_MUTREF, R_DEREF, R_VALUE, R_LITERAL, R_LABEL, R_ITEM, R_UNSAFE, R_PATH, R_WHERE, R_SELFMUT, R_UPDATE, R_DATA, R_DEPENDS, R_EXTERNAL, R_UNDECL, R_CLASH, R_STRUCTEQ, R_STRUSE, R_SPLICE, R_EMPTY, R_NOTYPE, R_VECMUT, R_VECMOVE, R_VECTYPE, R_LIBM, R_SLICEGEN]; + const why : [38]str = ["syntax", "generics", "trait impl", "closure", "? operator", "macro", "type", "method", "tuple", "if let / while let", "for over an iterator", "match pattern", "&mut of a value", "deref", "block as a value", "literal", "label or break value", "item", "unsafe", "path", "where clause", "mut self", "struct update", "enum variant with data", "uses refused", "uses external", "undeclared", "a used module's name, declared here too (use splices flat, see #7176)", "== of structs", "an owned String outside the out-buffer form", "a used module's own use t27c does not splice (its type_text:: names stay unresolved, the gap specs/compiler/int_type_names.t27 records)", "empty slice with no known element type", "`!` of an operand whose type t27o cannot tell", "a vec! the fn changes (push, resize, assign into, &mut)", "a vec! the fn hands on or returns", "a vec! whose element type or length t27o cannot tell", "libm function not bit-exact", "slice contains on"]; + var out : [512]u8 = undefined; + var st : [64]usize = [0] ** 64; + var w : [512]u8 = [0] ** 512; + var i : usize = 0; + while (i < 38) { + clear(&st); + st[ERR] = codes[i]; + st[AT] = 3; + st[NLO] = 3; + st[NHI] = 5; + put_reason("ab\ncd", &st, &out); + var ws : [64]usize = [0] ** 64; + puts(&ws, &w, why[i]); + puts(&ws, &w, " `cd` at line 2"); + if (codes[i] == R_SLICEGEN) { puts(&ws, &w, ": no generic helper, and per-type copies are refused by the DRY ratchet"); } + assert(out_is(st[W], &out, 0, w[0 .. ws[W]])); + i = i + 1; + } + clear(&st); + st[ERR] = 99; + put_reason("ab", &st, &out); + assert(out_is(st[W], &out, 0, "syntax `` at line 1")); + clear(&st); + st[ERR] = R_TYPE; + st[NLO] = 0; + st[NHI] = 50; + put_reason("aaaaaaaaaabbbbbbbbbbccccccccccddddddddddeeeeeeeeee", &st, &out); + assert(out_is(st[W], &out, 0, "type `aaaaaaaaaabbbbbbbbbbccccccccccdddddddddd` at line 1")); + clear(&st); + st[ERR] = R_TYPE; + st[AT] = 6; + st[NLO] = 6; + st[NHI] = 8; + put_reason("a\nb\nc\nxy", &st, &out); + assert(out_is(st[W], &out, 0, "type `xy` at line 4")); +} + +test put_refusal_and_skip_refused_write_the_comment_that_stands_for_a_refused_item { + var out : [256]u8 = undefined; + var st : [64]usize = [0] ** 64; + const src : str = "fn foo() { x }\nfn bar() {}"; + st[ERR] = R_TYPE; + st[AT] = 11; + st[NLO] = 11; + st[NHI] = 12; + put_refusal(src, &st, &out, "fn", 3, 6, 0); + assert(out_is(st[W], &out, 0, "// t27o: refused fn foo (line 1): type `x` at line 1\n\n")); + clear(&st); + st[ERR] = R_MACRO; + st[AT] = 15; + st[NLO] = 15; + st[NHI] = 17; + put_refusal(src, &st, &out, "const", 18, 21, 15); + assert(out_is(st[W], &out, 0, "// t27o: refused const bar (line 2): macro `fn` at line 2\n\n")); + const items : str = "trait T { fn a(); fn b(); }\nunion U { a: u8 }\nfn z() {}"; + clear(&st); + skip_refused(items, &st, &out, 0, 0, 5, R_ITEM); + assert(out_is(st[W], &out, 0, "// t27o: refused trait (line 1): item `trait` at line 1; 2 fn inside\n\n")); + assert(st[NFN] == 2); + assert(st[ERR] == 0); + assert(st[P] == 28); + clear(&st); + skip_refused(items, &st, &out, 28, 28, 33, R_ITEM); + assert(out_is(st[W], &out, 0, "// t27o: refused union (line 2): item `union` at line 2\n\n")); + assert(st[NFN] == 0); + assert(st[P] == 46); + clear(&st); + st[MODE] = M_SOURCE; + skip_refused(items, &st, &out, 0, 0, 5, R_ITEM); + assert(st[W] == 0); + assert(st[NFN] == 2); + assert(st[P] == 28); +} + +test std_derive_host_word_host_attr_and_put_item_source_keep_the_harness_compilable { + const ds : [9]str = ["Debug", "Clone", "Copy", "PartialEq", "Eq", "Hash", "PartialOrd", "Ord", "Default"]; + var i : usize = 0; + while (i < 9) { + assert(std_derive(ds[i], 0, ds[i].len)); + i = i + 1; + } + assert(!std_derive("Serialize", 0, 9)); + assert(!std_derive("Deserialize", 0, 11)); + assert(!std_derive("debug", 0, 5)); + assert(!std_derive("Debugx", 0, 6)); + assert(!std_derive("", 0, 0)); + assert(host_word("no_std", 0, 6)); + assert(host_word("no_main", 0, 7)); + assert(host_word("deny", 0, 4)); + assert(host_word("forbid", 0, 6)); + assert(!host_word("allow", 0, 5)); + assert(!host_word("warn", 0, 4)); + assert(!host_word("no_stdx", 0, 7)); + assert(!host_word("", 0, 0)); + const yes : [6]str = ["#![no_std]", "#![cfg_attr(not(test), no_std)]", "#![cfg_attr(a, allow(b), deny(c))]", "#![deny(x)]", "#![forbid(unsafe_code)]", "#![no_main]"]; + var j : usize = 0; + while (j < 6) { + assert(host_attr(yes[j], 2)); + j = j + 1; + } + const no : [6]str = ["#![allow(x)]", "#![cfg_attr(not(no_std), allow(x))]", "#![cfg_attr(a, allow(b))]", "#![cfg_attr(a)]", "#![cfg_attr]", "#![]"]; + var k : usize = 0; + while (k < 6) { + assert(!host_attr(no[k], 2)); + k = k + 1; + } + var out : [128]u8 = undefined; + var st : [64]usize = [0] ** 64; + const a : str = "#[derive(Debug, Serialize, Clone)]\nstruct S { x: u8 }"; + put_item_source(a, &st, &out, 0, a.len); + assert(out_is(st[W], &out, 0, "#[derive(Debug, Clone)]\nstruct S { x: u8 }")); + clear(&st); + const b : str = "#[inline]\nfn f() {}"; + put_item_source(b, &st, &out, 0, b.len); + assert(out_is(st[W], &out, 0, "\nfn f() {}")); + clear(&st); + const c : str = "#[derive(Serialize)]\nstruct S;"; + put_item_source(c, &st, &out, 0, c.len); + assert(out_is(st[W], &out, 0, "\nstruct S;")); + clear(&st); + const d : str = "#![no_std]\nfn f() {}"; + put_item_source(d, &st, &out, 0, d.len); + assert(out_is(st[W], &out, 0, "\nfn f() {}")); + clear(&st); + const e : str = "#![allow(x)]\nfn f() {}"; + put_item_source(e, &st, &out, 0, e.len); + assert(out_is(st[W], &out, 0, "#![allow(x)]\nfn f() {}")); + clear(&st); + const f : str = "fn f() { #[cfg(a)] x(); }"; + put_item_source(f, &st, &out, 0, f.len); + assert(out_is(st[W], &out, 0, "fn f() { x(); }")); + clear(&st); + const g : str = "x #[derive(Clone)] y"; + put_item_source(g, &st, &out, 2, g.len); + assert(out_is(st[W], &out, 0, "#[derive(Clone)] y")); + clear(&st); + put_item_source(a, &st, &out, 0, 0); + assert(st[W] == 0); +} + +test item_done_decides_what_a_converted_or_refused_item_leaves_in_each_mode { + var out : [128]u8 = undefined; + var st : [64]usize = [0] ** 64; + const src : str = "struct S { x: u8 } foo"; + puts(&st, &out, "XXXX"); + st[ERR] = R_TYPE; + st[AT] = 11; + st[NLO] = 11; + st[NHI] = 13; + item_done(src, &st, &out, "struct", 0, 2, 19, 22, 0); + assert(out_is(st[W], &out, 0, "XX// t27o: refused struct foo (line 1): type `x:` at line 1\n\n")); + clear(&st); + puts(&st, &out, "XXXX"); + st[ERR] = R_TYPE; + st[MODE] = M_SOURCE; + item_done(src, &st, &out, "struct", 0, 2, 19, 22, 0); + assert(st[W] == 2); + clear(&st); + puts(&st, &out, "XXXX"); + item_done(src, &st, &out, "struct", 0, 2, 19, 22, 0); + assert(out_is(st[W], &out, 0, "XXXX")); + clear(&st); + puts(&st, &out, "XXXX"); + st[MODE] = M_SOURCE; + item_done(src, &st, &out, "struct", 0, 2, 19, 22, 0); + assert(out_is(st[W], &out, 0, "XXstruct S { x: u8 }\n\n")); + clear(&st); + puts(&st, &out, "XXXX"); + st[MODE] = M_CALLS; + item_done(src, &st, &out, "struct", 0, 2, 19, 22, 0); + assert(out_is(st[W], &out, 0, "XX")); +} + +test generics_param_params_and_the_param_drops_write_a_signature { + var out : [128]u8 = undefined; + var st : [64]usize = [0] ** 64; + st[P] = 0; + generics("<'a, 'b> x", &st); + assert(st[ERR] == 0); + assert(st[P] == 9); + clear(&st); + generics("<'a> x", &st); + assert(st[ERR] == 0); + assert(st[P] == 5); + clear(&st); + generics(" x", &st); + assert(st[ERR] == R_GENERIC); + assert(st[AT] == 0); + assert(st[NHI] == 1); + clear(&st); + generics("<'a, T> x", &st); + assert(st[ERR] == R_GENERIC); + clear(&st); + generics(" x", &st); + assert(st[ERR] == R_GENERIC); + clear(&st); + st[P] = 2; + generics("f <'a> x", &st); + assert(st[ERR] == 0); + assert(st[P] == 7); + const rows : [14]str = ["a: u8", "mut a: u8", "a: String", "mut a: String", "a: &str", "self", "&self", "&mut self", "&'a self", "mut self", "self: Box", "&a: u8", "_: u8", "void: u8"]; + const want : [14]str = ["a: u8", "a_in: u8", "a: []const u8", "", "a: []const u8", "self: Pt", "self: Pt", "self: *Pt", "self: Pt", "", "", "", "", "void_: u8"]; + const code : [14]usize = [0, 0, 0, R_TYPE, 0, 0, 0, 0, 0, R_SELFMUT, R_SYNTAX, R_PATTERN, R_PATTERN, 0]; + var i : usize = 0; + while (i < 14) { + var buf : [64]u8 = [0] ** 64; + var bs : [64]usize = [0] ** 64; + puts(&bs, &buf, "Pt "); + puts(&bs, &buf, rows[i]); + const src : []const u8 = buf[0 .. bs[W]]; + clear(&st); + st[ILO] = 0; + st[IHI] = 2; + st[P] = 3; + param(src, &st, &out); + assert(st[ERR] == code[i]); + if (code[i] == 0) { assert(out_is(st[W], &out, 0, want[i])); } + i = i + 1; + } + clear(&st); + st[ILO] = 0; + st[IHI] = 2; + st[P] = 3; + param("Pt &mut self", &st, &out); + assert(st[SELFMUT] == 1); + clear(&st); + st[P] = 0; + param("&self", &st, &out); + assert(st[ERR] == R_SYNTAX); + clear(&st); + st[ILO] = 0; + st[IHI] = 2; + st[STUBBING] = 1; + st[P] = 3; + param("Pt &self", &st, &out); + assert(out_is(st[W], &out, 0, "self_: Pt")); + clear(&st); + params("(a: u8, b: u32)", &st, &out); + assert(out_is(st[W], &out, 0, "a: u8, b: u32")); + assert(st[P] == 15); + clear(&st); + params("()", &st, &out); + assert(st[W] == 0); + assert(st[ERR] == 0); + clear(&st); + params("(a: u8,)", &st, &out); + assert(out_is(st[W], &out, 0, "a: u8")); + clear(&st); + params("(a: u8 b: u8)", &st, &out); + assert(st[ERR] == R_SYNTAX); + clear(&st); + params("(a: u8", &st, &out); + assert(st[ERR] == R_SYNTAX); + clear(&st); + params("a: u8)", &st, &out); + assert(st[ERR] == R_SYNTAX); + clear(&st); + st[IND] = 1; + mut_params("(mut a: u8, b: u8, mut c: u32)", &st, &out, 0); + assert(out_is(st[W], &out, 0, "\n var a : u8 = a_in;\n var c : u32 = c_in;")); + assert(st[P] == 0); + clear(&st); + mut_params("(a: u8, b: u8)", &st, &out, 0); + assert(st[W] == 0); + clear(&st); + mut_params("(mut self, a: u8)", &st, &out, 0); + assert(st[W] == 0); + clear(&st); + mut_params("(a: u8, mut b: u8)", &st, &out, 0); + assert(out_is(st[W], &out, 0, "\nvar b : u8 = b_in;")); + assert(mentions("x y z", 0, 5, 2, 3)); + assert(mentions("x y z", 0, 5, 4, 5)); + assert(!mentions("x y z", 0, 5, 0, 0)); + assert(!mentions("x y z", 0, 3, 4, 5)); + assert(!mentions("x yy z", 0, 6, 2, 3)); + assert(!mentions("", 0, 0, 0, 0)); + clear(&st); + st[IND] = 1; + unused_params("(a: u8, b: u8, _c: u8, mut m: u8, &self, d: &u8) { a }", &st, &out, 0, 49, 54); + assert(out_is(st[W], &out, 0, "\n _ = b;\n _ = _c;\n _ = d;")); + clear(&st); + unused_params("(a: u8) { a }", &st, &out, 0, 8, 13); + assert(st[W] == 0); + clear(&st); + unused_params("(a: u8) { }", &st, &out, 0, 8, 11); + assert(out_is(st[W], &out, 0, "\n_ = a;")); + clear(&st); + unused_params("(_: u8, self) { }", &st, &out, 0, 14, 17); + assert(st[W] == 0); + clear(&st); + unused_params("()", &st, &out, 0, 2, 2); + assert(st[W] == 0); +} + +test fn_head_and_stub_write_the_signature_of_a_fn_and_of_a_refused_one { + var out : [128]u8 = undefined; + var st : [1024]usize = [0] ** 1024; + const rows : [11]str = ["fn f(a: u8) -> u32 { a }", "fn f() { }", "fn f() -> () { }", "fn f() -> Option { None }", "fn f() -> Result { Ok(1) }", "fn f() -> Result<(), E> { Ok(()) }", "fn f(self_: u8, b: &str) -> bool { true }", "fn f(a: u8) -> Vec { }", "fn f(x: Ghost) { }", "fn f() -> Option<(u8, u8)> { None }", "fn f(a: u8) -> void { }"]; + const want : [11]str = ["fn f(a: u8) -> u32", "fn f() -> void", "fn f() -> void", "fn f() -> ?u8", "fn f() -> ?u8", "fn f() -> bool", "fn f(self_: u8, b: []const u8) -> bool", "", "fn f(x: Ghost) -> void", "", "fn f(a: u8) -> void_"]; + const mode : [11]u8 = [M_RET, M_STMT, M_STMT, M_RET, M_RET, M_RET, M_RET, M_RET, M_STMT, M_RET, M_RET]; + const failk : [11]usize = [F_NONE, F_NONE, F_NONE, F_NULL, F_NULL, F_FALSE, F_NONE, F_NONE, F_NONE, F_NULL, F_NONE]; + const code : [11]usize = [0, 0, 0, 0, 0, 0, 0, R_TYPE, 0, R_TYPE, 0]; + var i : usize = 0; + while (i < 11) { + clear(&st); + st[P] = 4; + const m : u8 = fn_head(rows[i], &st, &out, false, 3, 4); + assert(st[ERR] == code[i]); + if (code[i] == 0) { + assert(out_is(st[W], &out, 0, want[i])); + assert(m == mode[i]); + assert(st[FAILK] == failk[i]); + } + i = i + 1; + } + clear(&st); + st[P] = 4; + fn_head("fn f() { }", &st, &out, true, 3, 4); + assert(out_is(st[W], &out, 0, "pub fn f() -> void")); + clear(&st); + st[ILO] = 0; + st[IHI] = 2; + st[P] = 7; + fn_head("Pt fn f(&self) { }", &st, &out, false, 6, 7); + assert(out_is(st[W], &out, 0, "fn Pt_f(self: Pt) -> void")); + clear(&st); + st[OUTFORM] = 1; + st[P] = 4; + assert(fn_head("fn f(a: &str) -> String { }", &st, &out, true, 3, 4) == M_RET); + assert(out_is(st[W], &out, 0, "pub fn f(a: []const u8, out: []u8) -> usize")); + assert(st[P] == 24); + clear(&st); + st[OUTFORM] = 1; + st[P] = 4; + assert(fn_head("fn f() -> String { }", &st, &out, false, 3, 4) == M_RET); + assert(out_is(st[W], &out, 0, "fn f(out: []u8) -> usize")); + const alias : str = "R fn f() -> R<()> { }"; + clear(&st); + add_name(alias, &st, K_RALIAS, 0, 1, 0, 0); + st[P] = 10; + fn_head(alias, &st, &out, false, 9, 10); + assert(out_is(st[W], &out, 0, "fn f() -> bool")); + assert(st[FAILK] == F_FALSE); + const s1 : str = "fn f(a: u8) -> u32 { a + 1 }"; + clear(&st); + stub(s1, &st, &out, false, 3, 4, 4, 0); + assert(out_is(st[W], &out, 0, "fn f(a: u8) -> u32 {\n}\n\n")); + assert(st[NSTUB] == 1); + assert(st[ERR] == 0); + assert(st[STUBBING] == 0); + clear(&st); + stub(s1, &st, &out, true, 3, 4, 4, 0); + assert(out_is(st[W], &out, 0, "pub fn f(a: u8) -> u32 {\n}\n\n")); + const s2 : str = "fn f(a: T) -> T { a }"; + clear(&st); + stub(s2, &st, &out, false, 3, 4, 4, 0); + assert(st[W] == 0); + assert(st[NSTUB] == 0); + assert(st[ERR] == 0); + const s3 : str = "fn f(a: Ghost) { }"; + clear(&st); + add_name(s3, &st, K_ITEM, 8, 13, 0, 0); + stub(s3, &st, &out, false, 3, 4, 4, 0); + assert(st[W] == 0); + assert(st[NSTUB] == 0); + const s4 : str = "struct Pt { x: u8 }\nfn f(&self) -> u8 { 1 }"; + clear(&st); + st[ILO] = 7; + st[IHI] = 9; + stub(s4, &st, &out, false, 23, 24, 24, 20); + assert(out_is(st[W], &out, 0, "fn Pt_f(self_: Pt) -> u8 {\n}\n\n")); + const s5 : str = "fn f(a: u8) -> u8;"; + clear(&st); + stub(s5, &st, &out, false, 3, 4, 4, 0); + assert(st[W] == 0); + assert(st[NSTUB] == 0); +} + +// ---------------------------------------------------------------- direct tests: the oracle writer + +test vkind_and_its_helpers_sort_a_type_into_the_kind_the_oracle_samples { + const head : str = "enum Mode { A, B, C }\n"; + const tys : [32]str = ["u8", "u128", "usize", "i64", "isize", "bool", "f64", "f32", "String", "Vec", "Vec", "Self", "Mode", "Ghost", "[u8; 4]", "[String; 4]", "&str", "&'a str", "&mut str", "&String", "&Vec", "&[u8]", "&[u32]", "&mut [u32]", "&mut [u8]", "&[u8; 3]", "&[bool]", "&[&str]", "&Mode", "&Ghost", "&&str", "char"]; + const want : [32]usize = [V_UNSIGNED, V_UNSIGNED, V_UNSIGNED, V_SIGNED, V_SIGNED, V_BOOL, V_FLOAT, V_FLOAT, V_STRING, V_VEC, V_NONE, V_ENUM, V_ENUM, V_NONE, V_ARRAY, V_NONE, V_STR, V_STR, V_NONE, V_RSTRING, V_RVEC, V_BYTES, V_SLICE, V_MSLICE, V_MSLICE, V_ARRAY, V_SLICE, V_NONE, V_ENUM, V_NONE, V_NONE, V_NONE]; + var buf : [128]u8 = [0] ** 128; + var i : usize = 0; + while (i < 32) { + var bs : [64]usize = [0] ** 64; + puts(&bs, &buf, head); + const q : usize = bs[W]; + puts(&bs, &buf, tys[i]); + const src : []const u8 = buf[0 .. bs[W]]; + assert(vkind(src, q) == want[i]); + i = i + 1; + } + assert(slice_elem_kind("[u8]", 0) == V_UNSIGNED); + assert(slice_elem_kind("[i32]", 0) == V_SIGNED); + assert(slice_elem_kind("[f64]", 0) == V_FLOAT); + assert(slice_elem_kind("[bool]", 0) == V_BOOL); + assert(slice_elem_kind("[&str]", 0) == V_NONE); + assert(slice_elem_kind("[u8; 2]", 0) == V_NONE); + assert(slice_elem_kind("[String]", 0) == V_NONE); + assert(array_elem_kind("[u8; 2]", 0) == V_UNSIGNED); + assert(array_elem_kind("[bool; 2]", 0) == V_BOOL); + assert(array_elem_kind("[f32; 2]", 0) == V_FLOAT); + assert(array_elem_kind("[u8]", 0) == V_NONE); + assert(array_elem_kind("[String; 2]", 0) == V_NONE); + assert(vec_u8("Vec", 3)); + assert(vec_u8("Vec ", 3)); + assert(!vec_u8("Vec", 3)); + assert(!vec_u8("Vec", 3)); + assert(arr_lb("&[u8]", 0) == 1); + assert(arr_lb("&'a mut [u8]", 0) == 8); + assert(arr_lb("[u8; 2]", 0) == 0); + assert(arr_lb("&mut [u8]", 0) == 5); + assert(arr_lb("&Mode", 0) == 1); + assert(arr_lb("x", 0) == 0); + assert(type_word("&str", 0) == 1); + assert(type_word("&'a str", 0) == 4); + assert(type_word("str", 0) == 0); + assert(type_word("u8", 0) == 0); + assert(type_word("&mut str", 0) == 1); + assert(enum_at("&Mode", 5, 5, 0) == 1); + assert(enum_at("Self", 7, 11, 0) == 7); + assert(enum_at("&Self", 7, 11, 0) == 7); + assert(enum_at("Self", 7, 7, 0) == 0); + assert(enum_at("Mode", 7, 11, 0) == 0); +} + +test find_enum_enum_variant_and_vlen_count_the_variants_an_enum_has { + const src : str = "enum Mode { A, #[x] B, C }\nenum Other;\nenum M2 { }\nenum Tr { A, B, }"; + assert(find_enum(src, 5, 9) == 10); + assert(find_enum(src, 5, 8) == src.len); + assert(find_enum(src, 32, 37) == src.len); + assert(find_enum(src, 44, 46) == 47); + assert(find_enum(src, 56, 58) == 59); + assert(find_enum(src, 0, 4) == src.len); + assert(find_enum(src, 5, 5) == src.len); + assert(enum_variant(src, 10, 0, true) == 3); + assert(enum_variant(src, 47, 0, true) == 0); + assert(enum_variant(src, 59, 0, true) == 2); + assert(tok_is(src, enum_variant(src, 10, 0, false), "A")); + assert(tok_is(src, enum_variant(src, 10, 1, false), "B")); + assert(tok_is(src, enum_variant(src, 10, 2, false), "C")); + assert(tok_is(src, enum_variant(src, 10, 3, false), "A")); + assert(tok_is(src, enum_variant(src, 10, 7, false), "B")); + assert(enum_variant(src, 47, 5, false) == src.len); + const w : str = "enum Mode { A, B, C } Mode [u8; 3] [bool; 2] &[bool] Ghost"; + const m : usize = find_tok(w, 21, "Mode"); + const a : usize = 27; + const b : usize = 35; + const sl : usize = 46; + assert(vlen(w, 0, 0, V_ENUM, m) == 3); + assert(vlen(w, 0, 0, V_ENUM, w.len - 5) == 1); + const w2 : str = "enum Mode { A, B, C } Self"; + assert(vlen(w2, 5, 9, V_ENUM, 22) == 3); + assert(vlen(w2, 0, 0, V_ENUM, 22) == 1); + assert(vlen(w, 0, 0, V_ARRAY, a) == 7); + assert(vlen(w, 0, 0, V_ARRAY, b) == 2); + assert(vlen(w, 0, 0, V_SLICE, sl - 1) == 2); + assert(vlen(w, 0, 0, V_MSLICE, sl - 1) == 2); + assert(vlen(w, 0, 0, V_BOOL, 0) == 2); + assert(vlen(w, 0, 0, V_FLOAT, 0) == 5); + assert(vlen(w, 0, 0, V_BYTES, 0) == 5); + assert(vlen(w, 0, 0, V_VEC, 0) == 5); + assert(vlen(w, 0, 0, V_RVEC, 0) == 5); + assert(vlen(w, 0, 0, V_STR, 0) == 8); + assert(vlen(w, 0, 0, V_STRING, 0) == 8); + assert(vlen(w, 0, 0, V_RSTRING, 0) == 8); + assert(vlen(w, 0, 0, V_UNSIGNED, 0) == 7); + assert(vlen(w, 0, 0, V_SIGNED, 0) == 7); +} + +test int_type_width_int_type_signed_and_int_ok_say_what_an_integer_type_holds { + const names : [14]str = ["u8", "i8", "u16", "i16", "u32", "i32", "u64", "i64", "u128", "i128", "usize", "isize", "bool", "f32"]; + const width : [14]usize = [8, 8, 16, 16, 32, 32, 64, 64, 64, 64, 64, 64, 0, 0]; + const signed : [14]bool = [false, true, false, true, false, true, false, true, false, true, false, true, false, false]; + var i : usize = 0; + while (i < 14) { + assert(int_type_width(names[i], 0) == width[i]); + assert(int_type_signed(names[i], 0) == signed[i]); + i = i + 1; + } + assert(int_type_width("", 0) == 0); + assert(int_type_width("x u16", 2) == 16); + assert(int_type_signed("x i16", 2)); + assert(!int_type_signed("x u16", 2)); + assert(int_ok(8, false, 255, false)); + assert(!int_ok(8, false, 256, false)); + assert(!int_ok(8, false, 0, true)); + assert(int_ok(8, false, 0, false)); + assert(int_ok(16, false, 65535, false)); + assert(!int_ok(16, false, 65536, false)); + assert(int_ok(32, false, 4294967295, false)); + assert(!int_ok(32, false, 4294967296, false)); + assert(int_ok(8, true, 127, false)); + assert(!int_ok(8, true, 128, false)); + assert(int_ok(8, true, 128, true)); + assert(!int_ok(8, true, 129, true)); + assert(int_ok(8, true, 0, true)); + assert(int_ok(32, true, 2147483647, false)); + assert(!int_ok(32, true, 2147483648, false)); + assert(int_ok(32, true, 2147483648, true)); + assert(!int_ok(32, true, 2147483649, true)); + assert(int_ok(64, true, 5, false)); + assert(int_ok(64, true, 4611686018427387903, false)); + assert(int_ok(64, true, 4611686018427387903, true)); + assert(int_ok(128, true, 5, false)); + assert(int_ok(128, true, 5, true)); +} + +test dcount_and_scount_count_the_samples_a_parameter_holds_and_cache_the_count { + var st : [1024]usize = [0] ** 1024; + const hi : str = "fn hi(x: u8) -> bool { x == 255 }"; + const hq : usize = 9; + const hb : usize = find_at(hi, 0, B_LBRACE); + st[FBLO] = hb + 1; + st[FBHI] = block_end(hi, hb) - 1; + assert(dcount(hi, &st, V_UNSIGNED, hq, 7) == 2); + assert(dcount(hi, &st, V_UNSIGNED, hq, 63) == 1); + assert(dcount(hi, &st, V_UNSIGNED, hq, 64) == 0); + assert(dcount(hi, &st, V_BOOL, hq, 2) == 0); + const tx : str = "fn t(x: &str) -> bool { x == \"a\" || x == \"b\" || x == \"c\" }"; + const tb : usize = find_at(tx, 0, B_LBRACE); + var t : [1024]usize = [0] ** 1024; + t[FBLO] = tb + 1; + t[FBHI] = block_end(tx, tb) - 1; + assert(dcount(tx, &t, V_STR, 8, 8) == 6); + assert(dcount(tx, &t, V_STR, 8, 62) == 2); + assert(dcount(tx, &t, V_STR, 8, 64) == 0); + assert(scount(hi, &st, V_UNSIGNED, hq, false, 7) == 7); + assert(scount(hi, &st, V_BOOL, hq, true, 2) == 2); + assert(st[CCNT] == 0); + assert(scount(hi, &st, V_UNSIGNED, hq, true, 7) == 9); + assert(st[CKIND] == V_UNSIGNED); + assert(st[CTQ] == hq); + assert(st[CFB] == st[FBLO]); + assert(st[CCNT] == 9); + st[CCNT] = 99; + assert(scount(hi, &st, V_UNSIGNED, hq, true, 7) == 99); + st[CKIND] = V_SIGNED; + assert(scount(hi, &st, V_UNSIGNED, hq, true, 7) == 9); + assert(st[CKIND] == V_UNSIGNED); + st[FBLO] = st[FBLO] + 1; + st[CCNT] = 99; + assert(scount(hi, &st, V_UNSIGNED, hq, true, 7) != 99); +} + +test put_quote_and_put_value_write_a_sample_in_rust_and_in_t27 { + var out : [128]u8 = undefined; + var st : [64]usize = [0] ** 64; + put_quote(&st, &out, true); + assert(out_is(st[W], &out, 0, "\"")); + clear(&st); + put_quote(&st, &out, false); + assert(out_is(st[W], &out, 0, "\\\"")); + const head : str = "enum Mode { A, B, C }\n"; + const tys : [40]str = ["u8", "u8", "u8", "u8", "u8", "u8", "u8", "u8", "i32", "i32", "i32", "i32", "i32", "i32", "i32", "bool", "bool", "bool", "f64", "f64", "f64", "f64", "f64", "&str", "&str", "&str", "&str", "&str", "&str", "&str", "&str", "&[u8]", "&String", "&Vec", "String", "Vec", "Mode", "Mode", "Mode", "Mode"]; + const kinds : [40]usize = [V_UNSIGNED, V_UNSIGNED, V_UNSIGNED, V_UNSIGNED, V_UNSIGNED, V_UNSIGNED, V_UNSIGNED, V_UNSIGNED, V_SIGNED, V_SIGNED, V_SIGNED, V_SIGNED, V_SIGNED, V_SIGNED, V_SIGNED, V_BOOL, V_BOOL, V_BOOL, V_FLOAT, V_FLOAT, V_FLOAT, V_FLOAT, V_FLOAT, V_STR, V_STR, V_STR, V_STR, V_STR, V_STR, V_STR, V_STR, V_BYTES, V_RSTRING, V_RVEC, V_STRING, V_VEC, V_ENUM, V_ENUM, V_ENUM, V_ENUM]; + const idx : [40]usize = [0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 5, 6, 7, 1, 1, 1, 1, 1, 0, 1, 2, 4]; + const rust : [40]str = ["0", "1", "2", "7", "10", "100", "255", "0", "0", "1", "-1", "7", "-100", "2147483647", "(-2147483648)", "false", "true", "false", "0.0", "1.0", "-1.5", "2.5", "100.0", "\"\"", "\"a\"", "\"abc\"", "\"0\"", "\"42\"", "\"0x1f\"", "\"a b\"", "\"-7\"", "b\"a\"", "&String::from(\"a\")", "&b\"a\".to_vec()", "String::from(\"a\")", "b\"a\".to_vec()", "Mode::A", "Mode::B", "Mode::C", "Mode::B"]; + const t27 : [40]str = ["0", "1", "2", "7", "10", "100", "255", "0", "0", "1", "-1", "7", "-100", "2147483647", "(-2147483648)", "false", "true", "false", "0.0", "1.0", "-1.5", "2.5", "100.0", "\\\"\\\"", "\\\"a\\\"", "\\\"abc\\\"", "\\\"0\\\"", "\\\"42\\\"", "\\\"0x1f\\\"", "\\\"a b\\\"", "\\\"-7\\\"", "\\\"a\\\"", "\\\"a\\\"", "\\\"a\\\"", "\\\"a\\\"", "\\\"a\\\"", "Mode.A", "Mode.B", "Mode.C", "Mode.B"]; + var buf : [128]u8 = [0] ** 128; + var i : usize = 0; + while (i < 40) { + var bs : [64]usize = [0] ** 64; + puts(&bs, &buf, head); + const q : usize = bs[W]; + puts(&bs, &buf, tys[i]); + const src : []const u8 = buf[0 .. bs[W]]; + clear(&st); + put_value(src, &st, &out, kinds[i], q, idx[i], true, false); + assert(out_is(st[W], &out, 0, rust[i])); + clear(&st); + put_value(src, &st, &out, kinds[i], q, idx[i], false, false); + assert(out_is(st[W], &out, 0, t27[i])); + i = i + 1; + } +} + +test put_value_arrays_slices_and_derived_samples_and_the_local_array_arguments { + var out : [128]u8 = undefined; + var st : [1024]usize = [0] ** 1024; + put_value("[u8; 3]", &st, &out, V_ARRAY, 0, 1, true, false); + assert(out_is(st[W], &out, 0, "[1; 3]")); + clear(&st); + put_value("&[u8; 3]", &st, &out, V_ARRAY, 0, 1, true, false); + assert(out_is(st[W], &out, 0, "&[1; 3]")); + clear(&st); + put_value("[u8; 3]", &st, &out, V_ARRAY, 0, 1, false, false); + assert(out_is(st[W], &out, 0, "[@as(u8, 1)] ** 3")); + clear(&st); + put_value("[bool; N]", &st, &out, V_ARRAY, 0, 1, false, false); + assert(out_is(st[W], &out, 0, "[true] ** N")); + clear(&st); + put_value("[i16; 2]", &st, &out, V_ARRAY, 0, 2, true, false); + assert(out_is(st[W], &out, 0, "[-1; 2]")); + clear(&st); + put_value("&[u8]", &st, &out, V_SLICE, 0, 2, true, false); + assert(out_is(st[W], &out, 0, "&[2; 3]")); + clear(&st); + put_value("&mut [u8]", &st, &out, V_MSLICE, 0, 2, true, false); + assert(out_is(st[W], &out, 0, "&mut [2; 3]")); + clear(&st); + put_value("&[u8]", &st, &out, V_SLICE, 0, 2, false, false); + assert(out_is(st[W], &out, 0, "[@as(u8, 2)] ** 3")); + clear(&st); + put_value("&[bool]", &st, &out, V_SLICE, 0, 1, false, false); + assert(out_is(st[W], &out, 0, "[true] ** 3")); + const hi : str = "fn hi(x: u8) -> bool { x == 255 }"; + const hb : usize = find_at(hi, 0, B_LBRACE); + clear(&st); + st[FBLO] = hb + 1; + st[FBHI] = block_end(hi, hb) - 1; + put_value(hi, &st, &out, V_UNSIGNED, 9, 7, true, true); + assert(out_is(st[W], &out, 0, "254")); + clear(&st); + st[FBLO] = hb + 1; + st[FBHI] = block_end(hi, hb) - 1; + put_value(hi, &st, &out, V_UNSIGNED, 9, 8, false, true); + assert(out_is(st[W], &out, 0, "255")); + clear(&st); + st[FBLO] = hb + 1; + st[FBHI] = block_end(hi, hb) - 1; + put_value(hi, &st, &out, V_UNSIGNED, 9, 7, true, false); + assert(out_is(st[W], &out, 0, "0")); + const lo : str = "fn lo(x: i32) -> bool { x == -3 }"; + const lb : usize = find_at(lo, 0, B_LBRACE); + clear(&st); + st[FBLO] = lb + 1; + st[FBHI] = block_end(lo, lb) - 1; + put_value(lo, &st, &out, V_SIGNED, 9, 7, true, true); + assert(out_is(st[W], &out, 0, "(-4)")); + const tx : str = "fn t(x: &str) -> bool { x == \"hi\" }"; + const tb : usize = find_at(tx, 0, B_LBRACE); + clear(&st); + st[FBLO] = tb + 1; + st[FBHI] = block_end(tx, tb) - 1; + put_value(tx, &st, &out, V_STR, 9, 8, true, true); + assert(out_is(st[W], &out, 0, "\"hi\"")); + clear(&st); + st[FBLO] = tb + 1; + st[FBHI] = block_end(tx, tb) - 1; + put_value(tx, &st, &out, V_STR, 9, 9, false, true); + assert(out_is(st[W], &out, 0, "\\\" hi \\\"")); + clear(&st); + st[FBLO] = tb + 1; + st[FBHI] = block_end(tx, tb) - 1; + put_value(tx, &st, &out, V_STR, 9, 10, false, true); + assert(out_is(st[W], &out, 0, "\\\"\\\"")); + assert(local_arg(V_ARRAY)); + assert(local_arg(V_SLICE)); + assert(local_arg(V_MSLICE)); + assert(!local_arg(V_UNSIGNED)); + assert(!local_arg(V_BYTES)); + assert(!local_arg(V_NONE)); + clear(&st); + put_arg("[u8; 3]", &st, &out, V_ARRAY, 0, 1, 2, 1, false); + assert(out_is(st[W], &out, 0, "t27o_2_1")); + clear(&st); + put_arg("&[u8; 3]", &st, &out, V_ARRAY, 0, 1, 2, 1, false); + assert(out_is(st[W], &out, 0, "&t27o_2_1")); + clear(&st); + put_arg("&mut [u8]", &st, &out, V_MSLICE, 0, 1, 0, 3, false); + assert(out_is(st[W], &out, 0, "&t27o_0_3")); + clear(&st); + put_arg("&[u8]", &st, &out, V_SLICE, 0, 1, 7, 0, false); + assert(out_is(st[W], &out, 0, "&t27o_7_0")); + clear(&st); + put_arg("[u8; 3]", &st, &out, V_ARRAY, 0, 1, 2, 1, true); + assert(out_is(st[W], &out, 0, "[1; 3]")); + clear(&st); + put_arg("u8", &st, &out, V_UNSIGNED, 0, 3, 2, 1, false); + assert(out_is(st[W], &out, 0, "7")); + clear(&st); + put_arg("u8", &st, &out, V_UNSIGNED, 0, 3, 2, 1, true); + assert(out_is(st[W], &out, 0, "7")); + clear(&st); + put_pre("[u8; 3]", &st, &out, V_ARRAY, 0, 1, 2, 1); + assert(out_is(st[W], &out, 0, " const t27o_2_1 : [3]u8 = [@as(u8, 1)] ** 3;\\n")); + clear(&st); + put_pre("&mut [u16]", &st, &out, V_MSLICE, 0, 2, 0, 0); + assert(out_is(st[W], &out, 0, " var t27o_0_0 : [3]u16 = [@as(u16, 2)] ** 3;\\n")); + clear(&st); + put_pre("&[bool]", &st, &out, V_SLICE, 0, 1, 4, 2); + assert(out_is(st[W], &out, 0, " const t27o_4_2 : [3]bool = [true] ** 3;\\n")); + clear(&st); + put_pre("[bool; 2]", &st, &out, V_ARRAY, 0, 0, 1, 0); + assert(out_is(st[W], &out, 0, " const t27o_1_0 : [2]bool = [false] ** 2;\\n")); + clear(&st); + put_pre("u8", &st, &out, V_UNSIGNED, 0, 1, 2, 1); + assert(st[W] == 0); + clear(&st); + put_dc(&st, &out, true); + assert(out_is(st[W], &out, 0, "d, c")); + clear(&st); + put_dc(&st, &out, false); + assert(out_is(st[W], &out, 0, "c")); +} + +test put_call_writes_one_sampled_call_in_rust_and_in_t27 { + var out : [256]u8 = undefined; + var st : [64]usize = [0] ** 64; + const f : str = "fn f(a: u8, b: bool, c: &str, d: [u8; 2], e: i16) { }"; + put_call(f, &st, &out, 3, 4, 1, V_UNSIGNED, 8, 0, 0, 0, 0, 0, 0, 0, 0, 3, false, true, false); + assert(out_is(st[W], &out, 0, "f(7)")); + clear(&st); + put_call(f, &st, &out, 3, 4, 2, V_UNSIGNED, 8, V_BOOL, 15, 0, 0, 0, 0, 0, 0, 1, false, true, false); + assert(out_is(st[W], &out, 0, "f(1, false)")); + clear(&st); + put_call(f, &st, &out, 3, 4, 3, V_UNSIGNED, 8, V_BOOL, 15, V_STR, 24, 0, 0, 0, 0, 0, false, true, false); + assert(out_is(st[W], &out, 0, "f(0, true, \"abc\")")); + clear(&st); + put_call(f, &st, &out, 3, 4, 3, V_UNSIGNED, 8, V_BOOL, 15, V_STR, 24, 0, 0, 0, 0, 0, false, false, false); + assert(out_is(st[W], &out, 0, "f(0, true, \\\"abc\\\")")); + clear(&st); + put_call(f, &st, &out, 3, 4, 4, V_UNSIGNED, 8, V_BOOL, 15, V_STR, 24, V_ARRAY, 33, 0, 0, 2, false, true, false); + assert(out_is(st[W], &out, 0, "f(2, true, \"42\", [100; 2])")); + clear(&st); + put_call(f, &st, &out, 3, 4, 4, V_UNSIGNED, 8, V_BOOL, 15, V_STR, 24, V_ARRAY, 33, 0, 0, 2, false, false, false); + assert(out_is(st[W], &out, 0, "f(2, true, \\\"42\\\", t27o_2_3)")); + clear(&st); + put_call(f, &st, &out, 3, 4, 5, V_UNSIGNED, 8, V_BOOL, 15, V_STR, 24, V_ARRAY, 33, V_SIGNED, 45, 0, false, true, false); + assert(out_is(st[W], &out, 0, "f(0, true, \"abc\", [7; 2], -100)")); + clear(&st); + put_call(f, &st, &out, 3, 4, 5, V_UNSIGNED, 8, V_BOOL, 15, V_STR, 24, V_ARRAY, 33, V_SIGNED, 45, 3, false, true, false); + assert(out_is(st[W], &out, 0, "f(7, false, \"0x1f\", [255; 2], 0)")); + clear(&st); + put_call(f, &st, &out, 3, 4, 1, V_UNSIGNED, 8, 0, 0, 0, 0, 0, 0, 0, 0, 1, false, false, true); + assert(out_is(st[W], &out, 0, "f(1, t27o_o1[0 .. 256])")); + clear(&st); + put_call(f, &st, &out, 3, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, false, true, false); + assert(out_is(st[W], &out, 0, "f()")); + const m : str = "enum Mode { A, B }\nimpl Mode { fn m(&self, x: u8) -> u8 { x } }"; + clear(&st); + st[ILO] = 24; + st[IHI] = 28; + put_call(m, &st, &out, 34, 35, 2, V_ENUM, 24, V_UNSIGNED, 46, 0, 0, 0, 0, 0, 0, 1, true, true, false); + assert(out_is(st[W], &out, 0, "Mode::B.m(2)")); + clear(&st); + st[ILO] = 24; + st[IHI] = 28; + put_call(m, &st, &out, 34, 35, 2, V_ENUM, 24, V_UNSIGNED, 46, 0, 0, 0, 0, 0, 0, 1, true, false, false); + assert(out_is(st[W], &out, 0, "Mode_m(Mode.B, 2)")); + clear(&st); + st[ILO] = 24; + st[IHI] = 28; + put_call(m, &st, &out, 34, 35, 1, V_UNSIGNED, 46, 0, 0, 0, 0, 0, 0, 0, 0, 2, false, true, false); + assert(out_is(st[W], &out, 0, "Mode::m(2)")); + clear(&st); + st[ILO] = 24; + st[IHI] = 28; + put_call(m, &st, &out, 34, 35, 1, V_UNSIGNED, 46, 0, 0, 0, 0, 0, 0, 0, 0, 2, false, false, false); + assert(out_is(st[W], &out, 0, "Mode_m(2)")); + assert(NO_IX == 999999); + clear(&st); + put_rv("fb", &st, &out, "r", 0, 0, NO_IX, NO_IX); + assert(out_is(st[W], &out, 0, "r")); + clear(&st); + put_rv("fb", &st, &out, "r", 0, 2, NO_IX, NO_IX); + assert(out_is(st[W], &out, 0, "r.fb")); + clear(&st); + put_rv("fb", &st, &out, "r", 0, 2, 1, NO_IX); + assert(out_is(st[W], &out, 0, "r.1")); + clear(&st); + put_rv("fb", &st, &out, "x", 0, 2, NO_IX, 3); + assert(out_is(st[W], &out, 0, "x.fb[3]")); + clear(&st); + put_rv("fb", &st, &out, "x", 0, 0, NO_IX, 0); + assert(out_is(st[W], &out, 0, "x[0]")); + clear(&st); + put_tv("fb", &st, &out, false, 0, 0, NO_IX, NO_IX); + assert(st[W] == 0); + clear(&st); + put_tv("fb", &st, &out, true, 0, 0, NO_IX, NO_IX); + assert(out_is(st[W], &out, 0, ".?")); + clear(&st); + put_tv("fb", &st, &out, true, 0, 2, NO_IX, NO_IX); + assert(out_is(st[W], &out, 0, ".?.fb")); + clear(&st); + put_tv("fb", &st, &out, false, 0, 2, 1, NO_IX); + assert(out_is(st[W], &out, 0, "._1")); + clear(&st); + put_tv("fb", &st, &out, false, 0, 2, NO_IX, 3); + assert(out_is(st[W], &out, 0, ".fb[3]")); + clear(&st); + put_tv("var", &st, &out, false, 0, 3, NO_IX, NO_IX); + assert(out_is(st[W], &out, 0, ".var_")); +} + +test put_print_and_put_fields_write_the_line_that_records_a_value { + var out : [512]u8 = undefined; + var st : [64]usize = [0] ** 64; + put_print("fld", &st, &out, V_UNSIGNED, 0, "r", false, false, 0, 0, NO_IX, NO_IX); + assert(out_is(st[W], &out, 0, "v.push(format!(\" assert({} == {:?});\", c, r)); ")); + clear(&st); + put_print("fld", &st, &out, V_UNSIGNED, 0, "r", false, true, 0, 0, NO_IX, NO_IX); + assert(out_is(st[W], &out, 0, "v.push(format!(\"{} assert({} == {:?});\", d, c, r)); ")); + clear(&st); + put_print("fld", &st, &out, V_SIGNED, 0, "x", true, false, 0, 0, NO_IX, NO_IX); + assert(out_is(st[W], &out, 0, "v.push(format!(\" assert({}.? == {:?});\", c, x)); ")); + clear(&st); + put_print("fld", &st, &out, V_BOOL, 0, "r", false, false, 0, 3, NO_IX, NO_IX); + assert(out_is(st[W], &out, 0, "v.push(format!(\" assert({}.fld == {:?});\", c, r.fld)); ")); + clear(&st); + put_print("fld", &st, &out, V_BOOL, 0, "r", false, false, 0, 0, 1, NO_IX); + assert(out_is(st[W], &out, 0, "v.push(format!(\" assert({}._1 == {:?});\", c, r.1)); ")); + clear(&st); + put_print("fld", &st, &out, V_UNSIGNED, 0, "r", false, false, 0, 3, NO_IX, 2); + assert(out_is(st[W], &out, 0, "v.push(format!(\" assert({}.fld[2] == {:?});\", c, r.fld[2])); ")); + clear(&st); + put_print("fld", &st, &out, V_FLOAT, 0, "r", false, false, 0, 0, NO_IX, NO_IX); + assert(out_is(st[W], &out, 0, "if r.is_finite() { v.push(format!(\" assert({} == {:?});\", c, r)); } ")); + clear(&st); + put_print("fld", &st, &out, V_STR, 0, "r", false, false, 0, 0, NO_IX, NO_IX); + assert(out_is(st[W], &out, 0, "if r.bytes().all(|b| b >= 32 && b < 127 && b != 34 && b != 92) { v.push(format!(\" assert(type_text::same({}, {:?}));\", c, r)); } ")); + clear(&st); + put_print("enum Mode { A, B }", &st, &out, V_ENUM, 5, "r", false, false, 0, 0, NO_IX, NO_IX); + assert(out_is(st[W], &out, 0, "v.push(format!(\" assert({} == Mode.{});\", c, match r { Mode::A => \"A\", Mode::B => \"B\", })); ")); + const s2 : str = "struct S2 { a: u8, arr: [bool; 2] }"; + clear(&st); + put_fields(s2, &st, &out, 10, "r", false, false); + assert(out_is(st[W], &out, 0, "v.push(format!(\" assert({}.a == {:?});\", c, r.a)); v.push(format!(\" assert({}.arr[0] == {:?});\", c, r.arr[0])); v.push(format!(\" assert({}.arr[1] == {:?});\", c, r.arr[1])); ")); + const w : str = "struct W(u8, bool);"; + clear(&st); + put_fields(w, &st, &out, 8, "x", true, true); + assert(out_is(st[W], &out, 0, "v.push(format!(\"{} assert({}.?._0 == {:?});\", d, c, x.0)); v.push(format!(\"{} assert({}.?._1 == {:?});\", d, c, x.1)); ")); + const e : str = "enum Mode { A, B }\nstruct M { e: Mode }"; + clear(&st); + put_fields(e, &st, &out, 28, "r", false, false); + assert(out_is(st[W], &out, 0, "v.push(format!(\" assert({}.e == Mode.{});\", c, match r.e { Mode::A => \"A\", Mode::B => \"B\", })); ")); +} + +test field_kind_array_len_and_fields_printable_decide_what_the_oracle_can_record { + const head : str = "enum Mode { A, B }\nx: "; + const tys : [18]str = ["u8", "usize", "i8", "bool", "f32", "&'static str", "&str", "Mode", "Ghost", "[u8; 3]", "[Mode; 2]", "[[u8; 2]; 2]", "[String; 2]", "[u8; N]", "String", "Vec", "&[u8]", "[f64; 16]"]; + const want : [18]usize = [V_UNSIGNED, V_UNSIGNED, V_SIGNED, V_BOOL, V_FLOAT, V_STR, V_STR, V_ENUM, V_NONE, V_ARRAY, V_ARRAY, V_NONE, V_NONE, V_NONE, V_NONE, V_NONE, V_NONE, V_ARRAY]; + var buf : [128]u8 = [0] ** 128; + var i : usize = 0; + while (i < 18) { + var bs : [64]usize = [0] ** 64; + puts(&bs, &buf, head); + const t : usize = bs[W]; + puts(&bs, &buf, tys[i]); + const src : []const u8 = buf[0 .. bs[W]]; + assert(field_kind(src, 0, 0, t) == want[i]); + i = i + 1; + } + const selfp : str = "enum Mode { A, B } Self"; + assert(field_kind(selfp, 5, 9, 19) == V_ENUM); + assert(field_kind(selfp, 0, 0, 19) == V_NONE); + assert(array_len("[u8; 3]", 0) == 3); + assert(array_len("[u8; 16]", 0) == 16); + assert(array_len("[u8; 0]", 0) == 0); + assert(array_len("[u8; N]", 0) == 0); + assert(array_len("x [bool; 12]", 2) == 12); + const defs : str = "enum Mode { A, B }\nstruct S { a: u8, b: bool, e: Mode, arr: [u8; 2], t: &'static str, f: f64 }\nstruct W(u8, bool);\nstruct Bad { a: u8, s: String }\nstruct Big { a: [u8; 17] }\nstruct E {}\n"; + var st : [64]usize = [0] ** 64; + assert(fields_printable(defs, &st, 28)); + assert(fields_printable(defs, &st, 103)); + assert(!fields_printable(defs, &st, 126)); + assert(!fields_printable(defs, &st, 158)); + assert(!fields_printable(defs, &st, 183)); +} + +test vectors_writes_the_harness_calls_of_one_fn_and_nothing_for_a_fn_it_cannot_sample { + var out : [2048]u8 = undefined; + var st : [1024]usize = [0] ** 1024; + const b : str = "fn f(a: bool) -> bool { a }"; + vectors(b, &st, &out, 3, 4, 4); + assert(out_is(st[W], &out, 0, " {\n let mut v: Vec = Vec::new();\n if let Ok(r) = std::panic::catch_unwind(|| f(false)) { let c = \"f(false)\"; v.push(format!(\" assert({} == {:?});\", c, r)); }\n if let Ok(r) = std::panic::catch_unwind(|| f(true)) { let c = \"f(true)\"; v.push(format!(\" assert({} == {:?});\", c, r)); }\n if !v.is_empty() { println!(\"test oracle_f {{\"); for l in &v { println!(\"{}\", l); } println!(\"}}\\n\"); }\n }\n")); + const o : str = "fn g(a: bool) -> Option { Some(a) }"; + clear(&st); + vectors(o, &st, &out, 3, 4, 4); + assert(out_is(st[W], &out, 0, " {\n let mut v: Vec = Vec::new();\n if let Ok(r) = std::panic::catch_unwind(|| g(false)) { let c = \"g(false)\"; match r { Some(x) => { v.push(format!(\" assert({}.? == {:?});\", c, x)); } None => v.push(format!(\" assert({} == null);\", c)) } }\n if let Ok(r) = std::panic::catch_unwind(|| g(true)) { let c = \"g(true)\"; match r { Some(x) => { v.push(format!(\" assert({}.? == {:?});\", c, x)); } None => v.push(format!(\" assert({} == null);\", c)) } }\n if !v.is_empty() { println!(\"test oracle_g {{\"); for l in &v { println!(\"{}\", l); } println!(\"}}\\n\"); }\n }\n")); + const r : str = "fn h(a: bool) -> Result<(), E> { Ok(()) }"; + clear(&st); + vectors(r, &st, &out, 3, 4, 4); + assert(out_is(st[W], &out, 0, " {\n let mut v: Vec = Vec::new();\n if let Ok(r) = std::panic::catch_unwind(|| h(false)) { let c = \"h(false)\"; match r { Ok(()) => v.push(format!(\" assert({});\", c)), Err(_) => v.push(format!(\" assert(({}) == false);\", c)) } }\n if let Ok(r) = std::panic::catch_unwind(|| h(true)) { let c = \"h(true)\"; match r { Ok(()) => v.push(format!(\" assert({});\", c)), Err(_) => v.push(format!(\" assert(({}) == false);\", c)) } }\n if !v.is_empty() { println!(\"test oracle_h {{\"); for l in &v { println!(\"{}\", l); } println!(\"}}\\n\"); }\n }\n")); + const none : [10]str = ["fn f(a: Vec) -> u8 { 0 }", "fn f(a: u8) { }", "fn f(a: u8) -> () { }", "fn f(a: u8) -> Vec { v }", "fn f(a: u8, mut b: u8) -> u8 { a }", "fn f(a: u8, b: u8, c: u8, d: u8, e: u8, g: u8) -> u8 { a }", "fn f(a: Ghost) -> u8 { 0 }", "fn f(self) -> u8 { 0 }", "fn f(a: u8) -> [u8; 2] { [a; 2] }", "fn f(a: u8) -> &[u8] { s }"]; + var i : usize = 0; + while (i < 10) { + clear(&st); + vectors(none[i], &st, &out, 3, 4, 4); + assert(st[W] == 0); + i = i + 1; + } + clear(&st); + vectors(b, &st, &out, 3, 4, 3); + assert(st[W] == 0); + const s : str = "struct Pt { x: u8 }\nfn mk(a: u8) -> Pt { Pt { x: a } }"; + clear(&st); + vectors(s, &st, &out, 23, 25, 25); + assert(st[W] > 0); + assert(out_holds(&out, 0, " {\n let mut v: Vec = Vec::new();\n if let Ok(r) = std::panic::catch_unwind(|| mk(0))")); + assert(out_has(st[W], &out, 0, B_LPAREN)); + clear(&st); + const bad : str = "struct Bad { s: String }\nfn mk(a: u8) -> Bad { Bad { s: a } }"; + vectors(bad, &st, &out, 28, 30, 30); + assert(st[W] == 0); + assert(ret_is_string("(a: u8) -> String {", 0)); + assert(ret_is_string("(a: u8) -> String { x }", 0)); + assert(!ret_is_string("(a: u8) -> String ", 0)); + assert(!ret_is_string("(a: u8) -> &str {", 0)); + assert(!ret_is_string("(a: u8) -> Option {", 0)); + assert(!ret_is_string("(a: u8) {", 0)); + assert(!ret_is_string("a: u8) -> String {", 0)); + assert(str_lit_len("\"abc\"", 0) == 3); + assert(str_lit_len("\"a\\nb\"", 0) == 3); + assert(str_lit_len("\"\"", 0) == 0); + assert(str_lit_len("\"a\\\n b\"", 0) == 2); + assert(str_lit_len("\"\\\"\"", 0) == 1); + assert(str_lit_len("x \"ab\"", 2) == 2); + assert(seq_at("a b c d", 0, "a b c") == 6); + assert(seq_at("a b c d", 0, "a b") == 4); + assert(seq_at("a b c", 0, "a x") == 5); + assert(seq_at("a b", 0, "") == 0); + assert(seq_at("a b", 2, "b") == 3); + assert(seq_at("a b", 0, " a b ") == 3); + assert(seq_at("a b", 5, "a") == 3); + assert(seq_at(". collect :: < Vec < _ >> ( ) . join ( \"x\")", 0, ". collect :: < Vec < _ >> ( ) . join ( ") == 39); + assert(ends_stmt("a;", 0)); + assert(ends_stmt("a ,", 0)); + assert(ends_stmt("a }", 0)); + assert(ends_stmt("x = f(a);", 7)); + assert(!ends_stmt("x = f(a);", 4)); + assert(!ends_stmt("a b", 0)); + assert(!ends_stmt("a", 0)); + assert(!ends_stmt("a ) ;", 0)); +} From bf74fb41000bf05141658605bc8de1f3e30b4f22 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 19 Oct 2026 12:34:02 +0700 Subject: [PATCH 8/8] t27o: direct tests for the out-buffer form, the item writers and the passes of rust_convert.t27 -- coverage 100 %; gen-rust test count and seal re-saved (Closes #10825) Tests only; no non-test line changes. t27c coverage: 360 of 360 functions named by a test (was 32). t27b 290 / 290, test-report vacuous 0 of 290, the seal of rust_convert.t27 re-saved and verified; the seals of rust_std, spice_convert, golden, ledger, service and install still verify. The regenerated gen/rust/tools/t27o/rust_convert.rs differs by one comment line (the count of tests it does not lower). Co-Authored-By: Claude Sonnet 5.5 --- .trinity/seals/t27o_T27oRust.json | 16 +- gen/rust/tools/t27o/rust_convert.rs | 2 +- specs/tools/t27o/rust_convert.t27 | 975 ++++++++++++++++++++++++++++ 3 files changed, 984 insertions(+), 9 deletions(-) diff --git a/.trinity/seals/t27o_T27oRust.json b/.trinity/seals/t27o_T27oRust.json index d93e496bb3..6b19cde333 100644 --- a/.trinity/seals/t27o_T27oRust.json +++ b/.trinity/seals/t27o_T27oRust.json @@ -2,23 +2,23 @@ "built_by": "t27c-bootstrap@0.5.2+ea35d9b72", "closure": [], "config": "gen=c,rust,verilog,zig;tests=zig", - "gen_hash_c": "sha256:ba1f66e21d989982d79ee41c7913ef3937b1a716632e1650c0f552ce56044ff5", - "gen_hash_rust": "sha256:a2cad2a0e3bb75c1df629d761d91debbe7ca34c1bf2a9ed6e720928ff2ced311", - "gen_hash_verilog": "sha256:dfc8a0c23a672fea3f010c7a6a4fa0790565f15d74d245d8824214f53e4595af", - "gen_hash_zig": "sha256:7736f857fb377c908dd4f0dfdd20aeea04ffb6024ce384a19a59a2b5c8bc5770", + "gen_hash_c": "sha256:27e4105ea1818cd9656f4b2bf72425213254ced23c0be9c3d244710d6fe5edb2", + "gen_hash_rust": "sha256:919dc613502d5c25810b958a036ac8422ea7a836bb513e0e033bf93a03db2036", + "gen_hash_verilog": "sha256:ee8237f39b07d795d71793f91ad289b04601c0cc18d193329ec8a5554173d5f7", + "gen_hash_zig": "sha256:459d4de242bb3c57fcd1d3cdbaf3bf4a6fa7bd5603c400f962178ee1098ac5f5", "module": "T27oRust", "ring": 12, "seal_schema": 2, - "sealed_at": "2026-10-19T03:25:15Z", + "sealed_at": "2026-10-19T05:31:45Z", "sealed_by": "t27c-bootstrap@0.5.2", - "spec_hash": "sha256:a0e477ab019f977b889abd108fb797fa82dde39c4d0d594e33e4c86b38fbe935", + "spec_hash": "sha256:b01dc84ffec00c49315231af4ab32b216412dd09298204831a545cd1ab09f9cd", "spec_path": "specs/tools/t27o/rust_convert.t27", "tests": { "failed": 0, "failing": [], "forced": false, - "passed": 129, - "total": 129, + "passed": 290, + "total": 290, "vacuous": 0 }, "toolchain": { diff --git a/gen/rust/tools/t27o/rust_convert.rs b/gen/rust/tools/t27o/rust_convert.rs index 5a62697752..54e7e46ad0 100644 --- a/gen/rust/tools/t27o/rust_convert.rs +++ b/gen/rust/tools/t27o/rust_convert.rs @@ -1,6 +1,6 @@ // Generated from .t27 spec // DO NOT EDIT — generated by t27c -// NOT LOWERED BY THIS BACKEND: 129 test(s), 0 invariant(s), 0 function(s) with no body. +// NOT LOWERED BY THIS BACKEND: 290 test(s), 0 invariant(s), 0 function(s) with no body. // This backend emits declarations only. The spec's checks live in // the Zig and Verilog outputs; do not read this file as verified. diff --git a/specs/tools/t27o/rust_convert.t27 b/specs/tools/t27o/rust_convert.t27 index a8f9252131..755e9dca35 100644 --- a/specs/tools/t27o/rust_convert.t27 +++ b/specs/tools/t27o/rust_convert.t27 @@ -16660,3 +16660,978 @@ test vectors_writes_the_harness_calls_of_one_fn_and_nothing_for_a_fn_it_cannot_s assert(!ends_stmt("a", 0)); assert(!ends_stmt("a ) ;", 0)); } + +// ---------------------------------------------------------------- direct tests: the out-buffer form + +test str_let_init_dot_is_push_param_named_out_chars_iter_and_fmt_arg_end_read_the_forms { + const inits : [14]str = ["String::new()", "String::with_capacity(8)", "String::from(\"a\")", "String::other()", "format!(\"a\")", "s.to_string();", "\"lit\".to_string();", "s.to_string() + 1", "s.len()", "x", "String", "s.to_string()", "7", "format"]; + const want : [14]usize = [1, 2, 3, 0, 4, 3, 3, 0, 0, 0, 0, 0, 0, 0]; + var i : usize = 0; + while (i < 14) { + assert(str_let_init(inits[i], 0) == want[i]); + i = i + 1; + } + assert(str_let_init("", 0) == 0); + assert(str_let_init("x = String::new()", 4) == 1); + assert(str_let_init("x", 5) == 0); + assert(dot_is_push("s.push(c)", 1)); + assert(dot_is_push("s.push_str(c)", 1)); + assert(dot_is_push("s . push (c)", 2)); + assert(!dot_is_push("s.pop()", 1)); + assert(!dot_is_push("s.push", 1)); + assert(!dot_is_push("s.pushed(c)", 1)); + assert(!dot_is_push("s.", 1)); + assert(param_named_out("(out: u8)", 0)); + assert(param_named_out("(a: u8, out: u8)", 0)); + assert(param_named_out("(a: (u8, u8), out: &mut [u8])", 0)); + assert(!param_named_out("(a: u8)", 0)); + assert(!param_named_out("(output: u8)", 0)); + assert(!param_named_out("(out)", 0)); + assert(!param_named_out("()", 0)); + assert(!param_named_out("(a: u8, outer: u8)", 0)); + assert(chars_iter("s.chars() {", 0) == 0); + assert(chars_iter("for c in s.chars() {", 9) == 9); + assert(chars_iter("s.chars().rev() {", 0) == 17); + assert(chars_iter("s.bytes() {", 0) == 11); + assert(chars_iter("s {", 0) == 3); + assert(chars_iter("1.chars() {", 0) == 11); + assert(chars_iter("s.chars(x) {", 0) == 12); + assert(fmt_arg_end("(a, b)", 1, 6) == 2); + assert(fmt_arg_end("(a, b)", 4, 6) == 5); + assert(fmt_arg_end("(f(a, b), c)", 1, 12) == 8); + assert(fmt_arg_end("(g[1, 2], c)", 1, 12) == 8); + assert(fmt_arg_end("(a)", 1, 3) == 2); + assert(fmt_arg_end("(a", 1, 2) == 2); + assert(fmt_arg_end("(a + {1, 2}, b)", 1, 15) == 11); + const classes : [26]str = ["str", "String", "char", "bool", "u8", "u16", "u32", "u64", "usize", "i8", "i16", "i32", "i64", "isize", "u128", "i128", "f64", "f32", "Mode", "", "&str", "strx", "Strin", "boolean", "uu8", "i"]; + const cw : [26]usize = [2, 2, 6, 7, 4, 4, 4, 4, 4, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; + var j : usize = 0; + while (j < 26) { + assert(word_to_class(classes[j], 0) == cw[j]); + j = j + 1; + } + assert(word_to_class("x u32", 2) == 4); +} + +test option_inner_if_let_type_text_init_and_the_name_classes_read_the_types_the_out_form_needs { + const s : str = "fn g() -> Option { None }\nfn h() -> u8 { 1 }\nfn k(a: (u8, u8)) -> Option { None }\nz g h k"; + assert(option_inner(s, 94, 95) == 17); + assert(option_inner(s, 96, 97) == s.len); + assert(option_inner(s, 98, 99) == 77); + assert(option_inner(s, 92, 93) == s.len); + assert(option_inner("", 0, 0) == 0); + const t : str = "fn g() -> Option { None }\nfn f() { if let Some(x) = g() { x; } }"; + assert(if_let_type(t, 62, 63, 30) == 17); + assert(if_let_type(t, 62, 63, 61) == t.len); + assert(if_let_type(t, 36, 37, 30) == t.len); + const t2 : str = "fn g() -> Option<&str> { None }\nfn f() { if let Some(x) = m::g() { x; } }"; + assert(if_let_type(t2, 67, 68, 32) == 17); + const t3 : str = "fn f() { if let Some(x) = other() { x; } }"; + assert(if_let_type(t3, 36, 37, 0) == t3.len); + const u : str = "fn f(s: &str, n: u8) { let t = s.trim(); let u = s.len(); let v = s.trim().trim_start(); let w = s.trim().len(); let z = n.trim(); }"; + assert(text_init(u, 0, 31, 39)); + assert(!text_init(u, 0, 49, 56)); + assert(text_init(u, 0, 66, 87)); + assert(!text_init(u, 0, 97, 111)); + assert(!text_init(u, 0, 121, 129)); + assert(!text_init(u, 0, 31, 69 - 1)); + assert(!text_init(u, 0, u.len, u.len)); + assert(!text_init(u, 0, 0, 2)); + const w : str = "fn f(s: &str, n: u8, i: i16, c: char, ok: bool, r: f64) { let t = s.trim(); let u = String::from(\"a\"); let v: String = x; let k = 5; t; u; v; k; s; n; i; c; ok; r; }"; + var st : [1024]usize = [0] ** 1024; + assert(let_init_class(w, 133, 134, 0) == 2); + assert(let_init_class(w, 136, 137, 0) == 2); + assert(let_init_class(w, 139, 140, 0) == 0); + assert(let_init_class(w, 142, 143, 0) == 0); + assert(let_init_class(w, 145, 146, 0) == 0); + assert(let_init_class(w, 133, 134, 140) == 0); + assert(fmt_name_class(w, 133, 134, 0) == 2); + assert(fmt_name_class(w, 136, 137, 0) == 2); + assert(fmt_name_class(w, 139, 140, 0) == 2); + assert(fmt_name_class(w, 142, 143, 0) == 0); + assert(fmt_name_class(w, 145, 146, 0) == 2); + assert(fmt_name_class(w, 148, 149, 0) == 4); + assert(fmt_name_class(w, 151, 152, 0) == 9); + assert(fmt_name_class(w, 154, 155, 0) == 6); + assert(fmt_name_class(w, 157, 159, 0) == 7); + assert(fmt_name_class(w, 161, 162, 0) == 0); + assert(fmt_name_class(t, 62, 63, 30) == 4); + assert(fmt_name_class(t2, 67, 68, 32) == 2); + assert(st[W] == 0); + const x : str = "struct Pt { name: &'static str, x: u8 }\nstruct Q { x: u8 }\nfn f() -> Pt {}\nGhost pt"; + assert(struct_text(x, &st, 0, 0, 7)); + assert(!struct_text(x, &st, 0, 0, 47)); + assert(struct_text(x, &st, 0, 0, 69)); + assert(!struct_text(x, &st, 0, 0, 75)); + assert(!struct_text(x, &st, 0, 0, 81)); + assert(!struct_text(x, &st, 0, 0, x.len)); + const sf : str = "struct Pt { name: &'static str }\nSelf"; + assert(struct_text(sf, &st, 7, 9, 33)); + assert(!struct_text(sf, &st, 0, 0, 33)); +} + +test put_out_text_lit_piece_and_out_text_from_append_text_to_the_buffer { + var out : [256]u8 = undefined; + var st : [64]usize = [0] ** 64; + put_out_text("\"abc\"", &st, &out, 0, 5); + assert(out_is(st[W], &out, 0, "t27o_w = rust_std::append_text(out, t27o_w, \"abc\");")); + assert(st[USES] == 2); + clear(&st); + put_out_text("name", &st, &out, 0, 4); + assert(out_is(st[W], &out, 0, "t27o_w = rust_std::append_text(out, t27o_w, name);")); + clear(&st); + put_out_text("r\"x\"", &st, &out, 0, 4); + assert(out_is(st[W], &out, 0, "t27o_w = rust_std::append_text(out, t27o_w, \"x\");")); + clear(&st); + put_out_text("void", &st, &out, 0, 4); + assert(out_is(st[W], &out, 0, "t27o_w = rust_std::append_text(out, t27o_w, void_);")); + clear(&st); + put_out_text("5", &st, &out, 0, 1); + assert(st[ERR] == R_STRUSE); + assert(st[AT] == 0); + assert(st[W] == 0); + clear(&st); + put_out_text("\"a\\rb\"", &st, &out, 0, 6); + assert(st[ERR] == R_LITERAL); + clear(&st); + put_out_lit(&st, &out, "true"); + assert(out_is(st[W], &out, 0, "t27o_w = rust_std::append_text(out, t27o_w, \"true\");")); + assert(st[USES] == 2); + clear(&st); + put_out_piece("abc", &st, &out, 0, 3); + assert(out_is(st[W], &out, 0, "t27o_w = rust_std::append_text(out, t27o_w, \"abc\");")); + clear(&st); + put_out_piece("x a\\nb y", &st, &out, 2, 6); + assert(out_is(st[W], &out, 0, "t27o_w = rust_std::append_text(out, t27o_w, \"a\\nb\");")); + clear(&st); + put_out_piece("", &st, &out, 0, 0); + assert(out_is(st[W], &out, 0, "t27o_w = rust_std::append_text(out, t27o_w, \"\");")); + clear(&st); + put_out_piece("a\\\n b", &st, &out, 0, 7); + assert(out_is(st[W], &out, 0, "t27o_w = rust_std::append_text(out, t27o_w, \"ab\");")); + clear(&st); + put_out_piece("a\\xb", &st, &out, 0, 4); + assert(st[ERR] == R_LITERAL); + assert(st[AT] == 0); + assert(st[NLO] == 1); + assert(st[NHI] == 3); + assert(st[W] == 0); + clear(&st); + put_out_piece("ab\\", &st, &out, 0, 3); + assert(st[ERR] == R_LITERAL); + clear(&st); + put_out_piece("a\tb", &st, &out, 0, 3); + assert(st[ERR] == R_LITERAL); + assert(text_value_end("String::from(\"a\"); x", 0) == 19); + assert(text_value_end("s.to_string(); x", 0) == 13); + assert(text_value_end("\"lit\".to_string(); x", 0) == 17); + assert(text_value_end("String::new(); x", 0) == 15); + clear(&st); + out_text_from("String::from(\"a\")", &st, &out, 0); + assert(out_is(st[W], &out, 0, "t27o_w = rust_std::append_text(out, t27o_w, \"a\");")); + clear(&st); + out_text_from("s.to_string()", &st, &out, 0); + assert(out_is(st[W], &out, 0, "t27o_w = rust_std::append_text(out, t27o_w, s);")); + clear(&st); + out_text_from("\"lit\".to_string()", &st, &out, 0); + assert(out_is(st[W], &out, 0, "t27o_w = rust_std::append_text(out, t27o_w, \"lit\");")); + clear(&st); + out_text_from("String::from( x )", &st, &out, 0); + assert(out_is(st[W], &out, 0, "t27o_w = rust_std::append_text(out, t27o_w, x);")); + clear(&st); + out_text_from("String::from()", &st, &out, 0); + assert(st[ERR] == R_STRUSE); + assert(st[AT] == 0); + clear(&st); + out_text_from("String::from(5)", &st, &out, 0); + assert(st[ERR] == R_STRUSE); +} + +test out_fmt_arg_and_out_format_append_each_hole_of_a_format_string { + const head : str = "fn f(s: &str, n: u32, i: i32, c: char, ok: bool, r: f64) -> String { "; + const args : [17]str = ["\"lit\"", "r\"x\"", "'c'", "true", "false", "5", "-5", "5u8", "s", "n", "i", "c", "ok", "r", "n + 1", "ghost", "'\\q'"]; + const want : [17]str = ["t27o_w = rust_std::append_text(out, t27o_w, \"lit\");", "t27o_w = rust_std::append_text(out, t27o_w, \"x\");", "t27o_w = rust_std::append_char(out, t27o_w, 'c');", "t27o_w = rust_std::append_text(out, t27o_w, \"true\");", "t27o_w = rust_std::append_text(out, t27o_w, \"false\");", "t27o_w = rust_std::append_uint(out, t27o_w, 5);", "t27o_w = rust_std::append_int(out, t27o_w, -5);", "t27o_w = rust_std::append_uint(out, t27o_w, @as(u8, 5));", "t27o_w = rust_std::append_text(out, t27o_w, s);", "t27o_w = rust_std::append_uint(out, t27o_w, n as u64);", "t27o_w = rust_std::append_int(out, t27o_w, i as i64);", "t27o_w = rust_std::append_char(out, t27o_w, c);", "if (ok) { t27o_w = rust_std::append_text(out, t27o_w, \"true\"); } else { t27o_w = rust_std::append_text(out, t27o_w, \"false\"); }", "", "", "", ""]; + const code : [17]usize = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, R_STRUSE, R_STRUSE, R_STRUSE, R_LITERAL]; + var buf : [256]u8 = [0] ** 256; + var st : [1024]usize = [0] ** 1024; + var out : [512]u8 = undefined; + var i : usize = 0; + while (i < 17) { + var bs : [64]usize = [0] ** 64; + puts(&bs, &buf, head); + const a : usize = bs[W]; + puts(&bs, &buf, args[i]); + const b : usize = bs[W]; + puts(&bs, &buf, " }"); + const src : []const u8 = buf[0 .. bs[W]]; + clear(&st); + st[FLO] = 0; + out_fmt_arg(src, &st, &out, a, b); + assert(st[ERR] == code[i]); + if (code[i] == 0) { assert(out_is(st[W], &out, 0, want[i])); } + i = i + 1; + } + const fmts : [8]str = ["format!(\"v={}!\", n)", "format!(\"{}\", s)", "format!(\"a{{b}}c\")", "format!(\"a\\n{}\", n)", "format!(\"{} {}\", n, s)", "format!(\"{:?}\", n)", "format!(\"{}\")", "format!(s)"]; + const fw : [8]str = ["t27o_w = rust_std::append_text(out, t27o_w, \"v=\");\nt27o_w = rust_std::append_uint(out, t27o_w, n as u64);\nt27o_w = rust_std::append_text(out, t27o_w, \"!\");\n", "t27o_w = rust_std::append_text(out, t27o_w, s);\n", "t27o_w = rust_std::append_text(out, t27o_w, \"a\");\nt27o_w = rust_std::append_text(out, t27o_w, \"{\");\nt27o_w = rust_std::append_text(out, t27o_w, \"b\");\nt27o_w = rust_std::append_text(out, t27o_w, \"}\");\nt27o_w = rust_std::append_text(out, t27o_w, \"c\");\n", "t27o_w = rust_std::append_text(out, t27o_w, \"a\\n\");\nt27o_w = rust_std::append_uint(out, t27o_w, n as u64);\n", "t27o_w = rust_std::append_uint(out, t27o_w, n as u64);\nt27o_w = rust_std::append_text(out, t27o_w, \" \");\nt27o_w = rust_std::append_text(out, t27o_w, s);\n", "", "", ""]; + const fc : [8]usize = [0, 0, 0, 0, 0, R_STRUSE, R_STRUSE, R_STRUSE]; + var j : usize = 0; + while (j < 8) { + var bs : [64]usize = [0] ** 64; + puts(&bs, &buf, head); + const a : usize = bs[W]; + puts(&bs, &buf, fmts[j]); + puts(&bs, &buf, " }"); + const src : []const u8 = buf[0 .. bs[W]]; + clear(&st); + st[FLO] = 0; + out_format(src, &st, &out, a, false); + assert(st[ERR] == fc[j]); + if (fc[j] == 0) { assert(out_is(st[W], &out, 0, fw[j])); } + j = j + 1; + } + var bs2 : [64]usize = [0] ** 64; + puts(&bs2, &buf, head); + const a2 : usize = bs2[W]; + puts(&bs2, &buf, "format!(\"{}\", s) }"); + const src2 : []const u8 = buf[0 .. bs2[W]]; + clear(&st); + out_format(src2, &st, &out, a2, true); + assert(out_is(st[W], &out, 0, "t27o_w = rust_std::append_text(out, t27o_w, s);\nreturn t27o_w;")); + assert(st[P] == src2.len - 1); + clear(&st); + st[IND] = 1; + out_format(src2, &st, &out, a2, false); + assert(out_is(st[W], &out, 0, "t27o_w = rust_std::append_text(out, t27o_w, s);\n ")); +} + +test out_str_push_out_str_plus_and_out_piece_call_append_to_the_buffer { + var out : [256]u8 = undefined; + var st : [64]usize = [0] ** 64; + out_str_push("'x');", &st, &out, 0); + assert(out_is(st[W], &out, 0, "t27o_w = rust_std::append_char(out, t27o_w, 'x');")); + assert(st[P] == 5); + clear(&st); + out_str_push("'x') y", &st, &out, 0); + assert(st[P] == 5); + const bc : str = "c);"; + clear(&st); + add_name(bc, &st, K_BYTECHAR, 0, 1, 0, 0); + out_str_push(bc, &st, &out, 0); + assert(out_is(st[W], &out, 0, "out[t27o_w] = c;\nt27o_w = t27o_w + 1;")); + assert(st[P] == 3); + const cv : str = "fn f(c: char, u: u8) { s.push(c); s.push(u); }"; + clear(&st); + st[FLO] = 0; + out_str_push(cv, &st, &out, 30); + assert(out_is(st[W], &out, 0, "t27o_w = rust_std::append_char(out, t27o_w, c);")); + clear(&st); + st[FLO] = 0; + out_str_push(cv, &st, &out, 41); + assert(st[ERR] == R_STRUSE); + assert(st[AT] == 41); + clear(&st); + out_str_push("5);", &st, &out, 0); + assert(st[ERR] == R_STRUSE); + clear(&st); + out_str_plus("\"y\";", &st, &out, 0); + assert(out_is(st[W], &out, 0, "t27o_w = rust_std::append_text(out, t27o_w, \"y\");")); + assert(st[P] == 4); + clear(&st); + out_str_plus("t);", &st, &out, 0); + assert(out_is(st[W], &out, 0, "t27o_w = rust_std::append_text(out, t27o_w, t);")); + assert(st[P] == 3); + clear(&st); + out_str_plus("5;", &st, &out, 0); + assert(st[ERR] == R_STRUSE); + clear(&st); + out_piece_call("piece s", &st, &out, 0, 5, 7, 6, 7); + assert(out_is(st[W], &out, 0, "t27o_w = t27o_w + piece(s[t27o_s7 .. t27o_i7], out[t27o_w .. out.len]);\n")); + clear(&st); + st[ILO] = 6; + st[IHI] = 7; + out_piece_call("piece s", &st, &out, 0, 5, 12, 6, 7); + assert(out_is(st[W], &out, 0, "t27o_w = t27o_w + s_piece(s[t27o_s12 .. t27o_i12], out[t27o_w .. out.len]);\n")); +} + +test string_out_form_finds_the_string_locals_and_the_out_str_statements_write_their_appends { + var out : [512]u8 = undefined; + var st : [1024]usize = [0] ** 1024; + const b : str = "fn b(a: &str, c: char) -> String { let mut s = String::new(); s.push('x'); s.push_str(a); s += \"y\"; s.push(c); s }"; + assert(string_out_form(b, &st, 35, b.len)); + assert(st[NNAMES] == 1); + assert(named(b, &st, K_STRLOC, 43, 44)); + assert(strloc_in(b, &st, 62, 63)); + assert(!strloc_in(b, &st, 3, 4)); + st[FLO] = 0; + st[OUTFORM] = 1; + st[P] = 35; + assert(out_str_stmt(b, &st, &out, M_STMT)); + assert(st[W] == 0); + assert(st[P] == 62); + assert(out_str_stmt(b, &st, &out, M_STMT)); + assert(st[P] == 75); + assert(out_str_stmt(b, &st, &out, M_STMT)); + assert(st[P] == 90); + assert(out_str_stmt(b, &st, &out, M_STMT)); + assert(st[P] == 100); + assert(out_str_stmt(b, &st, &out, M_STMT)); + assert(st[P] == 111); + assert(out_str_stmt(b, &st, &out, M_RET)); + assert(st[ERR] == 0); + assert(st[P] == 113); + assert(out_is(st[W], &out, 0, "t27o_w = rust_std::append_char(out, t27o_w, 'x');t27o_w = rust_std::append_text(out, t27o_w, a);t27o_w = rust_std::append_text(out, t27o_w, \"y\");t27o_w = rust_std::append_char(out, t27o_w, c);return t27o_w;")); + const bad : [3]str = ["fn f() -> String { let mut s = String::new(); s.len(); s }", "fn f() -> String { let s: String = foo(); s }", "fn f(a: &str) -> String { let mut s = String::new(); a.len(); s }"]; + const ok : [3]bool = [false, false, true]; + var i : usize = 0; + while (i < 3) { + var w : [1024]usize = [0] ** 1024; + assert(string_out_form(bad[i], &w, find_at(bad[i], 0, B_LBRACE) + 2, bad[i].len) == ok[i]); + if (!ok[i]) { assert(w[ERR] == R_STRUSE); } + i = i + 1; + } + var d : [1024]usize = [0] ** 1024; + const nl : str = "fn f(a: &str) -> String { a.to_string() }"; + assert(string_out_form(nl, &d, 25, nl.len)); + assert(d[NNAMES] == 0); + const lets : [8]str = ["let mut s = String::new(); x", "let s = String::with_capacity(n); x", "let s = String::from(\"a\"); x", "let s = format!(\"{}\", a); x", "let s = a.to_string(); x", "let n2 = 5; x", "let s: String = foo(); x", "let s: u8 = 5; x"]; + const lw : [8]str = ["", "_ = n;\n", "t27o_w = rust_std::append_text(out, t27o_w, \"a\");\n", "t27o_w = rust_std::append_text(out, t27o_w, a);\n\n", "t27o_w = rust_std::append_text(out, t27o_w, a);\n", "", "", ""]; + const lr : [8]bool = [true, true, true, true, true, false, true, false]; + var buf : [128]u8 = [0] ** 128; + var j : usize = 0; + while (j < 8) { + var bs : [64]usize = [0] ** 64; + puts(&bs, &buf, "fn f(a: &str, n: u32) -> String { "); + const p : usize = bs[W]; + puts(&bs, &buf, lets[j]); + const src : []const u8 = buf[0 .. bs[W]]; + clear(&st); + st[FLO] = 0; + st[P] = p; + assert(out_str_let(src, &st, &out) == lr[j]); + if (j == 6) { + assert(st[ERR] == R_STRUSE); + } else { + assert(st[ERR] == 0); + assert(out_is(st[W], &out, 0, lw[j])); + } + if (lr[j] and j != 6) { assert(st[P] == src.len - 1); } + if (!lr[j]) { assert(st[P] == p); } + j = j + 1; + } +} + +test out_str_return_and_out_split_join_write_the_hand_back_of_a_string { + var out : [512]u8 = undefined; + var st : [1024]usize = [0] ** 1024; + const rows : [8]str = ["return s;", "return s }", "return format!(\"{}\", a);", "return a.to_string();", "return String::new();", "return;", "return 5;", "return s.len();"]; + const want : [8]str = ["return t27o_w;", "return t27o_w;", "t27o_w = rust_std::append_text(out, t27o_w, a);\nreturn t27o_w;", "t27o_w = rust_std::append_text(out, t27o_w, a);\nreturn t27o_w;", "return t27o_w;", "", "", ""]; + const rr : [8]bool = [true, true, true, true, true, false, true, true]; + const rc : [8]usize = [0, 0, 0, 0, 0, 0, R_STRUSE, R_STRUSE]; + var buf : [256]u8 = [0] ** 256; + var i : usize = 0; + while (i < 8) { + var bs : [64]usize = [0] ** 64; + puts(&bs, &buf, "fn r(a: &str, n: u32) -> String { let mut s = String::new(); "); + const p : usize = bs[W]; + puts(&bs, &buf, rows[i]); + puts(&bs, &buf, " }"); + const src : []const u8 = buf[0 .. bs[W]]; + clear(&st); + st[FLO] = 0; + add_name(src, &st, K_STRLOC, 42, 43, 38, src.len); + st[P] = p; + assert(out_str_return(src, &st, &out) == rr[i]); + assert(st[ERR] == rc[i]); + if (rc[i] == 0 and rr[i]) { + assert(out_is(st[W], &out, 0, want[i])); + if (i == 1) { assert(st[P] == src.len - 3); } else { assert(st[P] == src.len - 1); } + } + if (!rr[i]) { assert(st[P] == p); } + i = i + 1; + } + const tails : [6]str = ["format!(\"{}\", a)", "a.to_string()", "String::new()", "String::with_capacity(n)", "s", "n + 1"]; + const tw : [6]str = ["t27o_w = rust_std::append_text(out, t27o_w, a);\nreturn t27o_w;", "t27o_w = rust_std::append_text(out, t27o_w, a);\nreturn t27o_w;", "return t27o_w;", "_ = n;\nreturn t27o_w;", "return t27o_w;", ""]; + const tr : [6]bool = [true, true, true, true, true, false]; + var j : usize = 0; + while (j < 6) { + var bs : [64]usize = [0] ** 64; + puts(&bs, &buf, "fn r(a: &str, n: u32) -> String { let mut s = String::new(); "); + const p : usize = bs[W]; + puts(&bs, &buf, tails[j]); + puts(&bs, &buf, " }"); + const src : []const u8 = buf[0 .. bs[W]]; + clear(&st); + st[FLO] = 0; + add_name(src, &st, K_STRLOC, 42, 43, 38, src.len); + st[P] = p; + assert(out_str_stmt(src, &st, &out, M_RET) == tr[j]); + assert(st[ERR] == 0); + if (tr[j]) { assert(out_is(st[W], &out, 0, tw[j])); } + j = j + 1; + } + clear(&st); + st[FLO] = 0; + st[P] = 0; + assert(!out_str_stmt("", &st, &out, M_STMT)); + const j2 : str = "fn piece(p: &str) -> String { p.to_string() }\nfn j(s: &str) -> String { s.split(\",\").map(piece).collect::>().join(\"-\") }"; + clear(&st); + add_name(j2, &st, K_STRFN, 3, 8, 0, 0); + st[FLO] = 46; + st[P] = 72; + assert(out_split_join(j2, &st, &out, true)); + assert(st[ERR] == 0); + assert(out_is(st[W], &out, 0, "var t27o_i2 : usize = 0;\nvar t27o_s2 : usize = 0;\nwhile (t27o_i2 < s.len) {\n if (toolchain::starts_with(s[t27o_i2 .. s.len], \",\")) {\n t27o_w = t27o_w + piece(s[t27o_s2 .. t27o_i2], out[t27o_w .. out.len]);\n t27o_w = rust_std::append_text(out, t27o_w, \"-\");\n t27o_i2 = t27o_i2 + 1;\n t27o_s2 = t27o_i2;\n } else {\n t27o_i2 = t27o_i2 + 1;\n }\n}\nt27o_w = t27o_w + piece(s[t27o_s2 .. t27o_i2], out[t27o_w .. out.len]);\nreturn t27o_w;")); + assert(st[USES] == 6); + clear(&st); + add_name(j2, &st, K_STRFN, 3, 8, 0, 0); + st[FLO] = 46; + st[P] = 72; + assert(out_split_join(j2, &st, &out, false)); + assert(!out_has(st[W], &out, 0, B_QMARK)); + clear(&st); + st[FLO] = 46; + st[P] = 72; + assert(out_split_join(j2, &st, &out, true)); + assert(st[ERR] == R_STRUSE); + clear(&st); + st[FLO] = 46; + st[P] = 50; + assert(!out_split_join(j2, &st, &out, true)); + assert(st[W] == 0); +} + +// ---------------------------------------------------------------- direct tests: module paths, the table prescan and the report + +test skip_attrs_gen_path_gen_mod_name_and_result_alias_read_attributes_and_aliases { + var st : [64]usize = [0] ** 64; + skip_attrs("#[a] #[b(c)] x", &st); + assert(st[P] == 13); + clear(&st); + skip_attrs("x #[a]", &st); + assert(st[P] == 0); + clear(&st); + skip_attrs("#[a]", &st); + assert(st[P] == 4); + clear(&st); + skip_attrs("#[a] #", &st); + assert(st[P] == 6); + clear(&st); + st[ERR] = R_MACRO; + skip_attrs("#[a] x", &st); + assert(st[P] == 0); + const gp : str = "../../gen/rust/tri/t27b/source_text.rs"; + assert(gen_path(gp, 0, gp.len) == 15); + assert(gen_path("gen/rust/a.rs", 0, 13) == 9); + assert(gen_path("../gen/rust/x.rs", 0, 16) == 12); + assert(gen_path("../gen/rust/x.t27", 0, 17) == 17); + assert(gen_path("../src/x.rs", 0, 11) == 11); + assert(gen_path("gen/rust/.rs", 0, 12) == 12); + assert(gen_path("x ../gen/rust/y.rs", 2, 18) == 14); + assert(gen_path("", 0, 0) == 0); + const g : str = "#[path = \"../gen/rust/x/y.rs\"]\nmod y;\nmod z;"; + assert(gen_mod_name(g, 35, 36)); + assert(!gen_mod_name(g, 42, 43)); + const h : str = "#[path = \"../gen/rust/a.rs\"] #[allow(dead_code)] mod a;"; + assert(gen_mod_name(h, 53, 54)); + const n : str = "mod a;"; + assert(!gen_mod_name(n, 4, 5)); + const o : str = "#[path = \"../src/a.rs\"]\nmod a;"; + assert(!gen_mod_name(o, 28, 29)); + const q : str = "#[path = \"../gen/rust/a.rs\"]\nfn x() {}\nmod a;"; + assert(!gen_mod_name(q, 43, 44)); + assert(!gen_mod_name("", 0, 0)); + assert(result_alias("type R = Result;", 0)); + assert(result_alias("type R = Result", 0)); + assert(result_alias("type R = Result;", 0)); + assert(!result_alias("type R = Option;", 0)); + assert(!result_alias("type X;", 0)); + assert(!result_alias("type R = u8; Result", 0)); + assert(!result_alias("type", 0)); +} + +test prescan_and_reused_enter_the_names_a_file_declares_before_its_items { + const s : str = "//@t27o reuse foo tri/t27b/source_text\nstruct W(u8);\ntype R = Result;\nstruct S { a: u8 }\n"; + var st : [1024]usize = [0] ** 1024; + prescan(s, &st); + assert(st[IXON] == 1); + assert(st[NNAMES] == 3); + assert(st[NAMES + 4] == K_TUPLE); + assert(word_is(s, st[NAMES], st[NAMES + 1], "W")); + assert(st[NAMES + NAME_SLOTS + 4] == K_RALIAS); + assert(word_is(s, st[NAMES + NAME_SLOTS], st[NAMES + NAME_SLOTS + 1], "R")); + assert(st[NAMES + 2 * NAME_SLOTS + 4] == K_REUSE); + assert(word_is(s, st[NAMES + 2 * NAME_SLOTS], st[NAMES + 2 * NAME_SLOTS + 1], "foo")); + assert(word_is(s, st[NAMES + 2 * NAME_SLOTS + 2], st[NAMES + 2 * NAME_SLOTS + 3], "tri/t27b/source_text")); + assert(reused(s, &st, 14, 17)); + assert(st[HIT] == NAMES + 2 * NAME_SLOTS); + assert(!reused(s, &st, 46, 47)); + assert(st[HIT] == 0); + st[NAMES + 2 * NAME_SLOTS + 4] = K_REUSED; + assert(reused(s, &st, 14, 17)); + const m : str = "//@t27o reuse Pt_get tri/t27b/x\nimpl Pt { fn get(&self) {} }\nPt get"; + var im : [1024]usize = [0] ** 1024; + prescan(m, &im); + assert(im[NNAMES] == 1); + const pt : usize = find_tok(m, 0, "Pt"); + const get : usize = find_tok(m, pt, "get"); + assert(!reused(m, &im, get, get + 3)); + im[ILO] = pt; + im[IHI] = pt + 2; + assert(reused(m, &im, get, get + 3)); + assert(!reused(m, &im, pt, pt + 2)); + assert(!reused(m, &im, get, get + 2)); + var none : [1024]usize = [0] ** 1024; + prescan("fn f() {}\n//@t27o reuse nopath\n//@t27o reuse \n//@t27o reuse g p\n", &none); + assert(none[NNAMES] == 1); + var tiny : [64]usize = [0] ** 64; + prescan(s, &tiny); + assert(tiny[IXON] == 0); + assert(tiny[NNAMES] == 1); +} + +test stub_out_has_put_report_and_put_uses_finish_the_output { + assert(stub_out_has("struct Pt;\n\nstruct Q;", 21, "Pt Q", 0, 2)); + assert(stub_out_has("struct Pt;\n\nstruct Q;", 21, "Pt Q", 3, 4)); + assert(!stub_out_has("struct Pt;\n\nstruct Q;", 20, "Pt Q", 3, 4)); + assert(!stub_out_has("struct Ptx;", 11, "Pt", 0, 2)); + assert(!stub_out_has("struct P;", 9, "Pt", 0, 2)); + assert(!stub_out_has("", 0, "Pt", 0, 2)); + assert(!stub_out_has("struct Pt", 9, "Pt", 0, 2)); + assert(!stub_out_has("struct Pt;", 9, "Pt", 0, 2)); + assert(stub_out_has("struct Pt;", 10, "Pt", 0, 2)); + assert(!stub_out_has("xstruct Pt;", 11, "Qt", 0, 2)); + var out : [256]u8 = undefined; + var st : [128]usize = [0] ** 128; + st[NFN] = 3; + st[NOK] = 2; + st[NTEST] = 1; + st[NTS] = 1; + st[NSTUB] = 1; + put_report(&st, &out); + assert(out_is(st[W], &out, 0, "// t27o: 3 fn seen, 2 converted (1 of 1 tests), 1 refused (1 kept as stubs); coverage 66%\n")); + clear(&st); + st[NFN] = 4; + st[NOK] = 4; + st[NREUSE] = 2; + st[NCFG] = 1; + put_report(&st, &out); + assert(out_is(st[W], &out, 0, "// t27o: 4 fn seen, 4 converted (0 of 0 tests), 2 reused, 0 refused (0 kept as stubs); 1 cfg-off fn dropped; coverage 100%\n")); + clear(&st); + put_report(&st, &out); + assert(out_is(st[W], &out, 0, "// t27o: 0 fn seen, 0 converted (0 of 0 tests), 0 refused (0 kept as stubs); coverage unknown: no fn seen\n")); + clear(&st); + st[NFN] = 7; + st[NOK] = 0; + put_report(&st, &out); + assert(out_is(st[W], &out, 0, "// t27o: 7 fn seen, 0 converted (0 of 0 tests), 7 refused (0 kept as stubs); coverage 0%\n")); + clear(&st); + puts(&st, &out, "AB"); + st[USEPOS] = 1; + put_uses("", &st, &out); + assert(out_is(st[W], &out, 0, "AB")); + clear(&st); + puts(&st, &out, "HEADER\nBODY\n"); + st[USEPOS] = 7; + st[USES] = 2; + put_uses("", &st, &out); + assert(out_is(st[W], &out, 0, "HEADER\nuse tools::t27o::rust_std;\n\nBODY\n")); + clear(&st); + puts(&st, &out, "HEADER\nBODY\n"); + st[USEPOS] = 7; + st[USES] = 6; + st[NEQ] = 1; + put_uses("", &st, &out); + assert(out_is(st[W], &out, 0, "HEADER\nuse tools::t27o::rust_std;\nuse hosting::toolchain;\nuse tri::t27b::type_text;\n\nBODY\n")); + clear(&st); + puts(&st, &out, "H\nB\n"); + st[USEPOS] = 2; + st[NEQ] = 1; + put_uses("", &st, &out); + assert(out_is(st[W], &out, 0, "H\nuse tri::t27b::type_text;\n\nB\n")); + const paths : str = "tri/t27b/a tri/t27b/a compiler/b"; + clear(&st); + puts(&st, &out, "H\nB\n"); + st[USEPOS] = 2; + add_name(paths, &st, K_MODUSED, 0, 1, 0, 10); + add_name(paths, &st, K_MODUSED, 2, 3, 11, 21); + add_name(paths, &st, K_REUSED, 4, 5, 22, 32); + add_name(paths, &st, K_MODPATH, 6, 7, 0, 10); + put_uses(paths, &st, &out); + assert(out_is(st[W], &out, 0, "H\nuse tri::t27b::a;\nuse compiler/b;\n\nB\n")); + clear(&st); + var small : [4]u8 = undefined; + puts(&st, &small, "ab"); + st[USEPOS] = 1; + st[USES] = 2; + put_uses("", &st, &small); + assert(st[W] > 4); + assert(small[0] == B_LOWER_A); +} + +// ---------------------------------------------------------------- direct tests: the item writers and the passes + +test fn_item_writes_a_fn_a_test_a_reused_fn_and_a_refused_fn_with_its_stub { + var out : [2048]u8 = undefined; + var st : [1024]usize = [0] ** 1024; + const f : str = "pub fn f(a: u8) -> u8 { a }"; + st[P] = 4; + fn_item(f, &st, &out, 0, false, true); + assert(out_is(st[W], &out, 0, "pub fn f(a: u8) -> u8 {\n return a;\n}\n\n")); + assert(st[NFN] == 1); + assert(st[NOK] == 1); + assert(st[NTS] == 0); + assert(st[P] == f.len); + assert(st[ERR] == 0); + clear(&st); + const t : str = "fn t() { assert!(true); }"; + st[P] = 0; + fn_item(t, &st, &out, 0, true, false); + assert(out_is(st[W], &out, 0, "test t {\n assert(true);\n}\n\n")); + assert(st[NTS] == 1); + assert(st[NTEST] == 1); + assert(st[NOK] == 1); + clear(&st); + const r : str = "fn f(a: u8) -> u8 { Ghost }"; + st[P] = 0; + fn_item(r, &st, &out, 0, false, false); + assert(out_is(st[W], &out, 0, "// t27o: refused fn f (line 1): undeclared `Ghost` at line 1\n\nfn f(a: u8) -> u8 {\n}\n\n")); + assert(st[NFN] == 1); + assert(st[NOK] == 0); + assert(st[NSTUB] == 1); + assert(st[ERR] == 0); + assert(named(r, &st, K_FN, 3, 4)); + clear(&st); + const rt : str = "fn t() { Ghost; }"; + st[P] = 0; + fn_item(rt, &st, &out, 0, true, false); + assert(out_is(st[W], &out, 0, "// t27o: refused fn t (line 1): undeclared `Ghost` at line 1\n\n")); + assert(st[NSTUB] == 0); + assert(st[NTEST] == 0); + assert(st[NTS] == 1); + clear(&st); + const g : str = "fn f(a: T) -> T { a }"; + st[P] = 0; + fn_item(g, &st, &out, 0, false, false); + assert(out_is(st[W], &out, 0, "// t27o: refused fn f (line 1): generics `<` at line 1\n\n")); + assert(st[NSTUB] == 0); + const ru : str = "//@t27o reuse f tri/t27b/source_text\nfn f(a: u8) -> u8 { a }"; + clear(&st); + prescan(ru, &st); + st[P] = 37; + fn_item(ru, &st, &out, 37, false, false); + assert(out_is(st[W], &out, 0, "// t27o: f is source_text::f of tri/t27b/source_text, with the same I/O on the oracle vectors: used, not written again\n\n")); + assert(st[NOK] == 1); + assert(st[NREUSE] == 1); + assert(st[NAMES + 4] == K_REUSED); + const o : str = "fn tag(n: u32) -> String { format!(\"<{}>\", n) }"; + clear(&st); + st[IXON] = 0; + st[P] = 0; + fn_item(o, &st, &out, 0, false, false); + assert(out_is(st[W], &out, 0, "fn tag(n: u32, out: []u8) -> usize {\n var t27o_w : usize = 0;\n t27o_w = rust_std::append_text(out, t27o_w, \"<\");\n t27o_w = rust_std::append_uint(out, t27o_w, n as u64);\n t27o_w = rust_std::append_text(out, t27o_w, \">\");\n return t27o_w;\n}\n\n")); + assert(st[NEQ] == 1); + assert(st[OUTFORM] == 0); + clear(&st); + st[IXON] = 0; + st[MODE] = M_SOURCE; + st[P] = 4; + fn_item(f, &st, &out, 0, false, true); + assert(out_is(st[W], &out, 0, "pub fn f(a: u8) -> u8 { a }\n\n")); + clear(&st); + st[IXON] = 0; + st[MODE] = M_CALLS; + st[P] = 4; + fn_item(f, &st, &out, 0, false, true); + assert(st[W] > 0); + assert(out_holds(&out, 0, " {\n let mut v: Vec = Vec::new();\n if let Ok(r) = std::panic::catch_unwind(|| f(0))")); + clear(&st); + st[IXON] = 0; + st[MODE] = M_CALLS; + st[P] = 0; + fn_item(t, &st, &out, 0, true, false); + assert(st[W] == 0); + const im : str = "struct Pt { x: u8 }\nimpl Pt { fn get(&self) -> u8 { 1 } }"; + clear(&st); + st[IXON] = 0; + st[ILO] = 25; + st[IHI] = 27; + st[P] = 30; + fn_item(im, &st, &out, 30, false, false); + assert(out_is(st[W], &out, 0, "fn Pt_get(self_: Pt) -> u8 {\n return 1;\n}\n\n")); + const mu : str = "struct Pt { x: u8 }\nimpl Pt { fn bump(&mut self, k: u8) { self.x = k; } }"; + clear(&st); + st[IXON] = 0; + st[ILO] = 25; + st[IHI] = 27; + st[P] = 30; + fn_item(mu, &st, &out, 30, false, false); + assert(out_is(st[W], &out, 0, "fn Pt_bump(self: *Pt, k: u8) -> void {\n self.x = k;\n}\n\n")); + const unused : str = "fn f(a: u8, mut b: u8) -> u8 { b }"; + clear(&st); + st[IXON] = 0; + st[P] = 0; + fn_item(unused, &st, &out, 0, false, false); + assert(out_is(st[W], &out, 0, "fn f(a: u8, b_in: u8) -> u8 {\n _ = a;\n var b : u8 = b_in;\n return b;\n}\n\n")); +} + +test const_item_struct_item_and_enum_item_write_the_declarations { + var out : [1024]u8 = undefined; + var st : [1024]usize = [0] ** 1024; + const rows : [14]str = ["pub const K: u8 = 1;", "static S: u8 = 2;", "const L: &str = \"x\";", "const A: [u8; 2] = [1, 2];", "const G: Ghost = 1;", "const var: u8 = 1;", "pub struct S { pub a: u8, b: bool }", "struct W(u8, bool);", "struct U;", "struct G { a: T }", "struct B { s: String }", "pub enum E { A, B = 5, C }", "enum D { A(u8) }", "enum G2 { A }"]; + const kinds : [14]usize = [0, 0, 0, 0, 1, 0, 2, 2, 2, 2, 2, 3, 3, 3]; + const want : [14]str = ["pub const K : u8 = 1;\n\n", "const S : u8 = 2;\n\n", "const L : []const u8 = \"x\";\n\n", "const A : [2]u8 = [1, 2];\n\n", "// t27o: refused const G (line 1): undeclared `Ghost` at line 1\n\n", "const var_ : u8 = 1;\n\n", "pub const S = struct {\n a : u8,\n b : bool,\n};\n\n", "const W = struct {\n _0 : u8,\n _1 : bool,\n};\n\n", "const U = struct {};\n\n", "// t27o: refused struct G (line 1): generics `<` at line 1\n\n", "// t27o: refused struct B (line 1): type `String` at line 1\n\n", "pub const E = enum(u32) {\n A,\n B = 5,\n C,\n};\n\n", "// t27o: refused enum D (line 1): enum variant with data `A` at line 1\n\n", "// t27o: refused enum G2 (line 1): generics `<` at line 1\n\n"]; + var i : usize = 0; + while (i < 14) { + clear(&st); + st[IXON] = 0; + const is_pub : bool = tok_is(rows[i], 0, "pub"); + var p : usize = 0; + if (is_pub) { p = 4; } + st[P] = p; + if (kinds[i] == 0 or kinds[i] == 1) { + const_item(rows[i], &st, &out, 0, is_pub); + } else if (kinds[i] == 2) { + struct_item(rows[i], &st, &out, 0, is_pub); + } else { + enum_item(rows[i], &st, &out, 0, is_pub); + } + assert(st[ERR] == 0); + assert(out_is(st[W], &out, 0, want[i])); + assert(st[P] == rows[i].len); + i = i + 1; + } + clear(&st); + st[P] = 0; + const_item("static mut S: u8 = 0;", &st, &out, 0, false); + assert(out_is(st[W], &out, 0, "// t27o: refused const mut (line 1): item `mut` at line 1\n\n")); + clear(&st); + const k : str = "const G: Ghost = 1;"; + st[P] = 0; + const_item(k, &st, &out, 0, false); + assert(named(k, &st, K_ITEM, 6, 7)); + clear(&st); + const sg : str = "struct B { s: String }"; + st[P] = 0; + struct_item(sg, &st, &out, 0, false); + assert(named(sg, &st, K_ITEM, 7, 8)); + clear(&st); + const ed : str = "enum D { A(u8) }"; + st[P] = 0; + enum_item(ed, &st, &out, 0, false); + assert(named(ed, &st, K_ITEM, 5, 6)); + const im : str = "struct Pt { x: u8 }\nimpl Pt { const K: u8 = 1; }"; + clear(&st); + st[ILO] = 25; + st[IHI] = 27; + st[P] = 30; + const_item(im, &st, &out, 30, false); + assert(out_is(st[W], &out, 0, "const Pt_K : u8 = 1;\n\n")); + clear(&st); + st[MODE] = M_SOURCE; + st[P] = 0; + struct_item("#[derive(Debug, Serialize)]\nstruct S { a: u8 }", &st, &out, 0, false); + assert(st[W] == 0); + const ds : str = "/// the k\nconst K: u8 = 1;"; + clear(&st); + st[P] = 10; + const_item(ds, &st, &out, 10, false); + assert(out_is(st[W], &out, 0, "/// the k\nconst K : u8 = 1;\n\n")); +} + +test impl_item_and_impl_body_write_the_members_of_an_inherent_impl_and_refuse_the_rest { + var out : [1024]u8 = undefined; + var st : [1024]usize = [0] ** 1024; + const head : str = "struct Pt { x: u8 }\n"; + const rows : [9]str = ["impl Pt { fn get(&self) -> u8 { 1 } }", "impl Pt { fn a() -> u8 { 1 } fn b() -> u8 { 2 } }", "impl Default for Pt { fn default() -> Self { Pt { x: 0 } } }", "impl Tr for Pt { fn m(&self) { } }", "impl Pt { fn a() { } }", "impl<'a> Pt { fn a() -> u8 { 1 } }", "impl Pt", "impl Pt { fn a() { } }", "impl Pt { }"]; + const want : [9]str = ["fn Pt_get(self_: Pt) -> u8 {\n return 1;\n}\n\n", "fn Pt_a() -> u8 {\n return 1;\n}\n\nfn Pt_b() -> u8 {\n return 2;\n}\n\n", "fn Pt_default() -> Pt {\n return Pt{ .x = 0 };\n}\n\n", "// t27o: refused Tr (line 2): trait impl `Tr` at line 2; 1 fn inside\n\n", "// t27o: refused impl (line 2): generics `impl` at line 2; 1 fn inside\n\n", "fn Pt_a() -> u8 {\n return 1;\n}\n\n", "// t27o: refused impl (line 2): syntax `impl` at line 2\n\n", "// t27o: refused Pt (line 2): generics `Pt` at line 2; 1 fn inside\n\n", ""]; + var buf : [256]u8 = [0] ** 256; + var i : usize = 0; + while (i < 9) { + var bs : [64]usize = [0] ** 64; + puts(&bs, &buf, head); + const a : usize = bs[W]; + puts(&bs, &buf, rows[i]); + const src : []const u8 = buf[0 .. bs[W]]; + clear(&st); + st[IXON] = 0; + st[P] = a; + impl_item(src, &st, &out, a); + assert(st[ERR] == 0); + assert(out_is(st[W], &out, 0, want[i])); + assert(st[ILO] == 0); + assert(st[IHI] == 0); + i = i + 1; + } + const s : str = "struct Pt { x: u8 }\nimpl Pt { fn a() -> u8 { 1 } }"; + clear(&st); + st[IXON] = 0; + st[P] = 30; + impl_body(s, &st, &out, 20, 28, 25, 27); + assert(out_is(st[W], &out, 0, "fn Pt_a() -> u8 {\n return 1;\n}\n\n")); + assert(st[P] == s.len); + assert(st[ILO] == 0); + assert(st[IHI] == 0); + clear(&st); + st[IXON] = 0; + st[MODE] = M_SOURCE; + st[P] = 30; + impl_body(s, &st, &out, 20, 28, 25, 27); + assert(out_is(st[W], &out, 0, "impl Pt {\nfn a() -> u8 { 1 }\n\n}\n\n")); + clear(&st); + st[IXON] = 0; + st[MODE] = M_SOURCE; + add_name(s, &st, K_ITEM, 25, 27, 0, 0); + st[P] = 30; + impl_body(s, &st, &out, 20, 28, 25, 27); + assert(out_is(st[W], &out, 0, "impl Pt {\nfn a() -> u8 { 1 }\n\n}\n\nstruct Pt;\n\n")); + const r : str = "struct Pt { x: u8 }\nimpl Pt { fn a() -> u8 { Ghost } }"; + clear(&st); + st[IXON] = 0; + st[MODE] = M_SOURCE; + st[P] = 30; + impl_body(r, &st, &out, 20, 28, 25, 27); + assert(st[W] == 0); +} + +test item_and_items_read_attributes_and_dispatch_to_the_item_writers { + var out : [1024]u8 = undefined; + var st : [1024]usize = [0] ** 1024; + const rows : [16]str = ["#[test]\nfn t() { assert!(true); }", "#[cfg(unix)]\nfn f() -> u8 { 1 }", "#[cfg(windows)]\nfn f() -> u8 { 1 }", "#[cfg(test)]\nfn f() -> u8 { 1 }", "use a::b;", "mod m { fn f() -> u8 { 1 } }", "mod x;", "type R = Result;", "trait T { fn a(); }", "union U { a: u8 }", "extern crate foo;", "pub(crate) fn f() { }", "const fn f() -> u8 { 1 }", "pub struct S { a: u8 }", "#[derive(Debug)]\nenum E { A }", "/// doc\nfn f() { }"]; + const want : [16]str = ["test t {\n assert(true);\n}\n\n", "fn f() -> u8 {\n return 1;\n}\n\n", "// t27o: cfg(windows) is off on the default host (not test, no features or --cfg; linux x86_64, debug): fn f dropped\n\n", "fn f() -> u8 {\n return 1;\n}\n\n", "", "fn f() -> u8 {\n return 1;\n}\n\n", "", "", "// t27o: refused trait (line 1): item `trait` at line 1; 1 fn inside\n\n", "// t27o: refused union (line 1): item `union` at line 1\n\n", "", "pub fn f() -> void {\n}\n\n", "fn f() -> u8 {\n return 1;\n}\n\n", "pub const S = struct {\n a : u8,\n};\n\n", "const E = enum(u32) {\n A,\n};\n\n", "/// doc\nfn f() -> void {\n}\n\n"]; + var i : usize = 0; + while (i < 16) { + clear(&st); + st[IXON] = 0; + st[P] = skip_ws(rows[i], 0); + item(rows[i], &st, &out); + assert(st[ERR] == 0); + assert(out_is(st[W], &out, 0, want[i])); + assert(st[P] == rows[i].len); + i = i + 1; + } + clear(&st); + item("", &st, &out); + assert(st[W] == 0); + clear(&st); + item("#[cfg(windows)]\nfn f() -> u8 { 1 }", &st, &out); + assert(st[NCFG] == 1); + assert(st[NFN] == 0); + clear(&st); + item("use a::{b, c};", &st, &out); + assert(st[NNAMES] == 2); + clear(&st); + const px : str = "#[path = \"../gen/rust/tri/x.rs\"]\nmod x;"; + item(px, &st, &out); + assert(st[NNAMES] == 1); + assert(st[NAMES + 4] == K_MODPATH); + assert(word_is(px, st[NAMES + 2], st[NAMES + 3], "tri/x")); + clear(&st); + item("trait T { fn a(); }", &st, &out); + assert(st[NFN] == 1); + assert(st[NNAMES] == 1); + assert(st[NAMES + 4] == K_ITEM); + clear(&st); + st[MODE] = M_SOURCE; + item("#[path = \"../gen/rust/tri/x.rs\"]\nmod x;", &st, &out); + assert(out_is(st[W], &out, 0, "#[path = \"../gen/rust/tri/x.rs\"]\nmod x;\n\n")); + clear(&st); + st[MODE] = M_SOURCE; + item("type R = Result;", &st, &out); + assert(out_is(st[W], &out, 0, "type R = Result;\n\n")); + clear(&st); + st[IXON] = 0; + items("fn a() -> u8 { 1 } fn b() -> u8 { 2 }", &st, &out, false); + assert(out_is(st[W], &out, 0, "fn a() -> u8 {\n return 1;\n}\n\nfn b() -> u8 {\n return 2;\n}\n\n")); + assert(st[NFN] == 2); + clear(&st); + st[IXON] = 0; + st[P] = 0; + items("fn a() -> u8 { 1 } } fn b() -> u8 { 2 }", &st, &out, true); + assert(out_is(st[W], &out, 0, "fn a() -> u8 {\n return 1;\n}\n\n")); + assert(st[P] == 19); + clear(&st); + st[IXON] = 0; + items("fn a() -> u8 { 1 } } fn b() -> u8 { 2 }", &st, &out, false); + assert(st[NFN] == 2); + clear(&st); + st[IXON] = 0; + items("@ fn a() -> u8 { 1 }", &st, &out, false); + assert(st[NFN] >= 1); + clear(&st); + items("", &st, &out, false); + assert(st[W] == 0); +} + +test ret_has_str_one_pass_and_passes_decide_the_text_use_and_run_the_passes_to_a_fixed_point { + const defs : str = "struct Pt { name: &'static str, x: u8 }\nstruct Q { x: u8 }\n"; + const rows : [10]str = ["(a: u8) -> &str { s }", "(a: u8) -> String { s }", "(a: u8) -> Option<&str> { s }", "(a: u8) -> Pt { p }", "(a: u8) -> Q { q }", "(a: u8) -> u8 { a }", "(a: u8) { }", "(a: u8) -> Result { s }", "(a: u8) -> Ghost { g }", "(a: u8) -> Self { s }"]; + const want : [10]bool = [true, true, true, true, false, false, false, false, false, true]; + var buf : [256]u8 = [0] ** 256; + var st : [1024]usize = [0] ** 1024; + var i : usize = 0; + while (i < 10) { + var bs : [64]usize = [0] ** 64; + puts(&bs, &buf, defs); + const pn : usize = bs[W]; + puts(&bs, &buf, rows[i]); + const src : []const u8 = buf[0 .. bs[W]]; + clear(&st); + st[IXON] = 0; + if (i == 9) { + st[ILO] = 7; + st[IHI] = 9; + } + assert(ret_has_str(src, &st, st[ILO], st[IHI], pn) == want[i]); + i = i + 1; + } + assert(!ret_has_str("fn f() -> &str { s }", &st, 0, 0, 0)); + assert(!ret_has_str("", &st, 0, 0, 0)); + var out : [1024]u8 = undefined; + const a : str = "fn f() -> u8 { 1 }"; + clear(&st); + st[IXON] = 0; + one_pass(a, "m", &out, &st, false); + assert(out_is(st[W], &out, 0, "fn f() -> u8 {\n return 1;\n}\n\n")); + assert(st[NOK] == 1); + assert(st[USEPOS] == 0); + clear(&st); + st[IXON] = 0; + one_pass(a, "m", &out, &st, true); + assert(out_is(st[W], &out, 0, "// SPDX-License-Identifier: Apache-2.0\n; m.t27 -- converted from Rust by t27o (Ouroboros), specs/tools/t27o/rust_convert.t27; read it before it lands.\n; ASCII only (L3)\n\nmodule m;\n\nfn f() -> u8 {\n return 1;\n}\n\n// t27o: 1 fn seen, 1 converted (0 of 0 tests), 0 refused (0 kept as stubs); coverage 100%\n")); + clear(&st); + st[IXON] = 0; + one_pass(" // c\nfn f() -> u8 { 1 }", "m", &out, &st, false); + assert(out_is(st[W], &out, 0, "fn f() -> u8 {\n return 1;\n}\n\n")); + const m : str = "x::f(1) tri/t27b/a //@t27o reuse g tri/t27b/b"; + clear(&st); + st[IXON] = 0; + add_name(m, &st, K_MODUSED, 0, 1, 8, 18); + add_name(m, &st, K_REUSED, 25, 26, 33, 45); + add_name(m, &st, K_FN, 20, 21, 0, 0); + one_pass("", "m", &out, &st, false); + assert(st[NNAMES] == 3); + assert(st[NAMES + 4] == K_MODPATH); + assert(st[NAMES + NAME_SLOTS + 4] == K_REUSE); + assert(st[NAMES + 2 * NAME_SLOTS + 4] == K_FN); + assert(st[W] == 0); + const c : str = "fn a() -> u8 { b() }\nfn b() -> u8 { c() }\n"; + clear(&st); + assert(passes(c, "", &out, &st, false) == st[W]); + assert(out_is(st[W], &out, 0, "// t27o: refused fn a (line 1): uses refused `b` at line 1\n\nfn a() -> u8 {\n}\n\n// t27o: refused fn b (line 2): undeclared `c` at line 2\n\nfn b() -> u8 {\n}\n\n")); + assert(st[NOK] == 0); + assert(st[NFN] == 2); + assert(st[NSTUB] == 2); + clear(&st); + assert(passes(a, "", &out, &st, false) == 32); + assert(st[NOK] == 1); + clear(&st); + assert(passes("", "", &out, &st, false) == 0); + clear(&st); + const w : usize = passes(a, "m", &out, &st, true); + assert(w == st[W]); + assert(out_holds(&out, 0, "// SPDX-License-Identifier: Apache-2.0\n; m.t27 -- converted from Rust")); + var small : [8]u8 = undefined; + clear(&st); + assert(passes(a, "", &small, &st, false) == 32); + assert(small[0] == B_LOWER_F); +}