From 58a3b6f56a43444feffe35dd64d72d104fbfb07c Mon Sep 17 00:00:00 2001 From: Alexander Medvednikov Date: Sat, 25 Apr 2026 22:59:50 +0300 Subject: [PATCH] toml: fix tests --- vlib/toml/checker/checker.v | 6 +- vlib/toml/parser/parser.v | 108 +++++++++++++++------------ vlib/toml/to/to.v | 22 +++--- vlib/toml/toml.v | 24 ++++-- vlib/v/preludes/test_runner_normal.v | 9 +-- 5 files changed, 94 insertions(+), 75 deletions(-) diff --git a/vlib/toml/checker/checker.v b/vlib/toml/checker/checker.v index 6a26a777e..fe909afff 100644 --- a/vlib/toml/checker/checker.v +++ b/vlib/toml/checker/checker.v @@ -17,6 +17,10 @@ pub const allowed_basic_escape_chars = [`u`, `U`, `b`, `t`, `n`, `f`, `r`, `"`, // utf8_max is the largest inclusive value of the Unicodes scalar value ranges. const utf8_max = 0x10FFFF +fn allowed_basic_escape_char_list() []u8 { + return [u8(`u`), `U`, `b`, `t`, `n`, `f`, `r`, `"`, `\\`] +} + fn toml_parse_time(s string) !time.Time { if s.len > 3 && s[2] == `:` { // complete the partial time, with an arbitrary date: @@ -541,7 +545,7 @@ fn (c &Checker) check_quoted_escapes(q ast.Quoted) ! { continue } } - if next_ch !in allowed_basic_escape_chars { + if next_ch !in allowed_basic_escape_char_list() { st := s.state() return error(@MOD + '.' + @STRUCT + '.' + @FN + ' unknown basic string escape character `${next_ch.ascii_str()}` in `${escape}` (${st.line_nr},${st.col}) in ...${c.excerpt(q.pos)}...') diff --git a/vlib/toml/parser/parser.v b/vlib/toml/parser/parser.v index 0847e5602..8b189448a 100644 --- a/vlib/toml/parser/parser.v +++ b/vlib/toml/parser/parser.v @@ -15,6 +15,18 @@ pub const space_formatting = [token.Kind.whitespace, .tab] pub const keys_and_space_formatting = [token.Kind.whitespace, .tab, .minus, .bare, .quoted, .boolean, .number, .underscore] +fn all_formatting_kinds() []token.Kind { + return [token.Kind.whitespace, .tab, .cr, .nl] +} + +fn space_formatting_kinds() []token.Kind { + return [token.Kind.whitespace, .tab] +} + +fn keys_and_space_formatting_kinds() []token.Kind { + return [token.Kind.whitespace, .tab, .minus, .bare, .quoted, .boolean, .number, .underscore] +} + type DottedKey = []string // str returns the dotted key as a string. @@ -188,7 +200,7 @@ fn (mut p Parser) check(check_token token.Kind) ! { // and return an error if the next token is not one of [.cr, .nl, .hash, .eof]. fn (mut p Parser) peek_for_correct_line_ending_or_fail() ! { // Disallow anything else than [.cr, .nl, .hash, .eof] after any space formatting. - peek_tok, _ := p.peek_over(1, space_formatting)! + peek_tok, _ := p.peek_over(1, space_formatting_kinds())! if peek_tok.kind !in [.cr, .nl, .hash, .eof] { p.next()! // Forward to the peek_tok return error(@MOD + '.' + @STRUCT + '.' + @FN + @@ -475,15 +487,15 @@ pub fn (mut p Parser) dotted_key() !DottedKey { util.printdbg(@MOD + '.' + @STRUCT + '.' + @FN, 'parsing dotted key...') mut dotted_key := DottedKey([]string{}) key := p.key()! - p.ignore_while_peek(space_formatting) + p.ignore_while_peek(space_formatting_kinds()) dotted_key << key.str() for p.peek_tok.kind == .period { p.next()! // . p.check(.period)! - p.ignore_while(space_formatting) + p.ignore_while(space_formatting_kinds()) next_key := p.key()! dotted_key << next_key.text - p.ignore_while_peek(space_formatting) + p.ignore_while_peek(space_formatting_kinds()) } p.next()! util.printdbg(@MOD + '.' + @STRUCT + '.' + @FN, @@ -518,7 +530,7 @@ pub fn (mut p Parser) root_table() ! { } .bare, .boolean, .quoted, .number, .minus, .underscore { // Peek forward as far as we can skipping over space formatting tokens. - peek_tok, _ := p.peek_over(1, keys_and_space_formatting)! + peek_tok, _ := p.peek_over(1, keys_and_space_formatting_kinds())! if peek_tok.kind == .period { dotted_key, val := p.dotted_key_value()! @@ -568,7 +580,7 @@ pub fn (mut p Parser) root_table() ! { t[key.str()] = val } } else { - p.ignore_while(space_formatting) + p.ignore_while(space_formatting_kinds()) key, val := p.key_value()! t := p.find_table()! @@ -590,8 +602,8 @@ pub fn (mut p Parser) root_table() ! { mut peek_tok := p.peek_tok // Disallow `[ [table]]` - if p.tok.kind in space_formatting { - peek_tok, _ = p.peek_over(1, space_formatting)! + if p.tok.kind in space_formatting_kinds() { + peek_tok, _ = p.peek_over(1, space_formatting_kinds())! if peek_tok.kind == .lsbr { return error(@MOD + '.' + @STRUCT + '.' + @FN + ' unexpected "${p.tok.kind}" "${p.tok.lit}" at this (excerpt): "...${p.excerpt()}..."') @@ -599,10 +611,10 @@ pub fn (mut p Parser) root_table() ! { } // Allow `[ d.e.f]` - p.ignore_while(space_formatting) + p.ignore_while(space_formatting_kinds()) // Peek forward as far as we can skipping over space formatting tokens. - peek_tok, _ = p.peek_over(1, keys_and_space_formatting)! + peek_tok, _ = p.peek_over(1, keys_and_space_formatting_kinds())! if p.tok.kind == .lsbr { // Parse `[[table]]` @@ -629,7 +641,7 @@ pub fn (mut p Parser) root_table() ! { // Disallow re-declaring the key p.check_explicitly_declared_array_of_tables(dotted_key)! p.check(.rsbr)! - p.ignore_while(space_formatting) + p.ignore_while(space_formatting_kinds()) arr := p.find_array_of_tables()! if val := arr[p.last_aot_index] { if val is map[string]ast.Value { @@ -678,7 +690,7 @@ pub fn (mut p Parser) root_table() ! { } p.explicit_declared << dotted_key - p.ignore_while(space_formatting) + p.ignore_while(space_formatting_kinds()) util.printdbg(@MOD + '.' + @STRUCT + '.' + @FN, 'setting root map key to `${dotted_key}` at "${p.tok.kind}" "${p.tok.lit}"') p.root_map_key = dotted_key @@ -706,14 +718,14 @@ pub fn (mut p Parser) root_table() ! { p.explicit_declared << dotted_key // Allow [ key ] - p.ignore_while(space_formatting) + p.ignore_while(space_formatting_kinds()) util.printdbg(@MOD + '.' + @STRUCT + '.' + @FN, 'setting root map key to `${dotted_key}` at "${p.tok.kind}" "${p.tok.lit}"') p.root_map_key = dotted_key p.allocate_table(p.root_map_key)! p.next()! - p.ignore_while(space_formatting) + p.ignore_while(space_formatting_kinds()) p.expect(.rsbr)! p.peek_for_correct_line_ending_or_fail()! } @@ -764,7 +776,7 @@ pub fn (mut p Parser) table_contents(mut tbl map[string]ast.Value) ! { } .bare, .quoted, .number, .minus, .underscore { // Peek forward as far as we can skipping over space formatting tokens. - peek_tok, _ := p.peek_over(1, keys_and_space_formatting)! + peek_tok, _ := p.peek_over(1, keys_and_space_formatting_kinds())! if peek_tok.kind == .period { dotted_key, val := p.dotted_key_value()! @@ -778,7 +790,7 @@ pub fn (mut p Parser) table_contents(mut tbl map[string]ast.Value) ! { t[key.str()] = val } } else { - p.ignore_while(space_formatting) + p.ignore_while(space_formatting_kinds()) key, val := p.key_value()! unsafe { @@ -816,7 +828,7 @@ pub fn (mut p Parser) inline_table(mut tbl map[string]ast.Value) ! { util.printdbg(@MOD + '.' + @STRUCT + '.' + @FN, 'parsing token "${p.tok.kind}"') if previous_token_was_value { - p.ignore_while(space_formatting) + p.ignore_while(space_formatting_kinds()) if p.tok.kind != .rcbr { p.expect(.comma)! } @@ -835,7 +847,7 @@ pub fn (mut p Parser) inline_table(mut tbl map[string]ast.Value) ! { continue } .comma { - p.ignore_while_peek(space_formatting) + p.ignore_while_peek(space_formatting_kinds()) if p.peek_tok.kind in [.comma, .rcbr] { p.next()! // Forward to the peek_tok return error(@MOD + '.' + @STRUCT + '.' + @FN + @@ -851,7 +863,7 @@ pub fn (mut p Parser) inline_table(mut tbl map[string]ast.Value) ! { } .bare, .quoted, .number, .minus, .underscore { // Peek forward as far as we can skipping over space formatting tokens. - peek_tok, _ := p.peek_over(1, space_formatting)! + peek_tok, _ := p.peek_over(1, space_formatting_kinds())! if peek_tok.kind == .period { dotted_key, val := p.dotted_key_value()! @@ -877,7 +889,7 @@ pub fn (mut p Parser) inline_table(mut tbl map[string]ast.Value) ! { t[key_str] = val } } else { - p.ignore_while(space_formatting) + p.ignore_while(space_formatting_kinds()) key, val := p.key_value()! key_str := key.str() util.printdbg(@MOD + '.' + @STRUCT + '.' + @FN, @@ -910,9 +922,9 @@ pub fn (mut p Parser) array_of_tables(mut table map[string]ast.Value) ! { p.check(.lsbr)! // '[' bracket // Allow [[ key]] - p.ignore_while(space_formatting) - peek_tok, _ := p.peek_over(1, space_formatting)! - p.ignore_while(space_formatting) + p.ignore_while(space_formatting_kinds()) + peek_tok, _ := p.peek_over(1, space_formatting_kinds())! + p.ignore_while(space_formatting_kinds()) // [[key.key]] horror if peek_tok.kind == .period { @@ -924,13 +936,13 @@ pub fn (mut p Parser) array_of_tables(mut table map[string]ast.Value) ! { p.next()! // Allow [[key ]] - p.ignore_while(space_formatting) + p.ignore_while(space_formatting_kinds()) p.check(.rsbr)! p.peek_for_correct_line_ending_or_fail()! p.expect(.rsbr)! - p.ignore_while(all_formatting) + p.ignore_while(all_formatting_kinds()) dotted_key := DottedKey([key.str()]) dotted_key_str := dotted_key.str() @@ -982,12 +994,12 @@ pub fn (mut p Parser) double_array_of_tables(mut table map[string]ast.Value) ! { 'parsing nested array of tables "${p.tok.kind}" "${p.tok.lit}"') dotted_key := p.dotted_key()! - p.ignore_while(space_formatting) + p.ignore_while(space_formatting_kinds()) p.check(.rsbr)! p.expect(.rsbr)! - p.ignore_while(all_formatting) + p.ignore_while(all_formatting_kinds()) p.check_explicitly_declared(dotted_key)! if is_all_tables(p.root_map, dotted_key) { @@ -1145,13 +1157,13 @@ pub fn (mut p Parser) double_array_of_tables_contents(target_key DottedKey) ![]a for p.tok.kind != .eof { p.next()! util.printdbg(@MOD + '.' + @STRUCT + '.' + @FN, 'parsing token "${p.tok.kind}"') - p.ignore_while(all_formatting) + p.ignore_while(all_formatting_kinds()) // Peek forward as far as we can skipping over space formatting tokens. - peek_tok, peeked_over = p.peek_over(1, space_formatting)! + peek_tok, peeked_over = p.peek_over(1, space_formatting_kinds())! // Peek for occurrence of `[[` if peek_tok.kind == .lsbr { - peek_tok, peeked_over = p.peek_over(peeked_over + 1, space_formatting)! + peek_tok, peeked_over = p.peek_over(peeked_over + 1, space_formatting_kinds())! if peek_tok.kind == .lsbr { mut arr := []ast.Value{} arr << tbl @@ -1162,7 +1174,7 @@ pub fn (mut p Parser) double_array_of_tables_contents(target_key DottedKey) ![]a match p.tok.kind { .bare, .quoted, .number, .minus, .underscore { // Peek forward as far as we can skipping over space formatting tokens. - peek_tok, _ = p.peek_over(1, space_formatting)! + peek_tok, _ = p.peek_over(1, space_formatting_kinds())! if peek_tok.kind == .period { mut dotted_key, val := p.dotted_key_value()! @@ -1197,20 +1209,20 @@ pub fn (mut p Parser) double_array_of_tables_contents(target_key DottedKey) ![]a peek_tok = p.peek_tok // Allow `[ d.e.f]` - p.ignore_while(space_formatting) + p.ignore_while(space_formatting_kinds()) // Peek forward as far as we can skipping over space formatting tokens. - peek_tok, _ = p.peek_over(1, space_formatting)! + peek_tok, _ = p.peek_over(1, space_formatting_kinds())! if peek_tok.kind == .period { // Parse `[d.e.f]` - p.ignore_while(space_formatting) + p.ignore_while(space_formatting_kinds()) dotted_key := p.dotted_key()! implicit_allocation_key = unsafe { dotted_key } if dotted_key.len > 2 { implicit_allocation_key = dotted_key[2..] } - p.ignore_while(space_formatting) + p.ignore_while(space_formatting_kinds()) util.printdbg(@MOD + '.' + @STRUCT + '.' + @FN, 'keys are: dotted `${dotted_key}`, target `${target_key}`, implicit `${implicit_allocation_key}` at "${p.tok.kind}" "${p.tok.lit}"') p.expect(.rsbr)! @@ -1246,28 +1258,28 @@ pub fn (mut p Parser) array() ![]ast.Value { 'parsing token "${p.tok.kind}" "${p.tok.lit}"') if previous_token_was_value { - p.ignore_while(all_formatting) + p.ignore_while(all_formatting_kinds()) if p.tok.kind != .rsbr && p.tok.kind != .hash { p.expect(.comma)! } previous_token_was_value = false } else { if p.tok.kind == .comma { - p.ignore_while_peek(space_formatting) + p.ignore_while_peek(space_formatting_kinds()) if p.peek_tok.kind == .rsbr { return error(@MOD + '.' + @STRUCT + '.' + @FN + ' unexpected empty value in array "${p.tok.kind}" "${p.tok.lit}" at this (excerpt): "...${p.excerpt()}..."') } } } - p.ignore_while(all_formatting) + p.ignore_while(all_formatting_kinds()) match p.tok.kind { .boolean { arr << ast.Value(p.boolean()!) previous_token_was_value = true } .comma { - p.ignore_while_peek(space_formatting) + p.ignore_while_peek(space_formatting_kinds()) // Trailing commas before array close is allowed // so we do not do `if p.peek_tok.kind == .rsbr { ... }` @@ -1291,7 +1303,7 @@ pub fn (mut p Parser) array() ![]ast.Value { util.printdbg(@MOD + '.' + @STRUCT + '.' + @FN, 'skipping comment "${c.text}"') } .lcbr { - p.ignore_while(space_formatting) + p.ignore_while(space_formatting_kinds()) mut t := map[string]ast.Value{} p.inline_table(mut t)! arr << ast.Value(t) @@ -1355,7 +1367,7 @@ pub fn (mut p Parser) key() !ast.Key { pos := p.tok.pos() for p.peek_tok.kind != .assign && p.peek_tok.kind != .period && p.peek_tok.kind != .rsbr { p.next()! - if p.tok.kind !in space_formatting { + if p.tok.kind !in space_formatting_kinds() { lits += p.tok.lit } } @@ -1432,9 +1444,9 @@ pub fn (mut p Parser) key_value() !(ast.Key, ast.Value) { dotted_key := DottedKey([key.str()]) p.explicit_declared << p.build_abs_dotted_key(dotted_key) p.next()! - p.ignore_while(space_formatting) + p.ignore_while(space_formatting_kinds()) p.check(.assign)! // Assignment operator - p.ignore_while(space_formatting) + p.ignore_while(space_formatting_kinds()) value := p.value()! if p.value_is_immutable { if !p.immutable.has(dotted_key) { @@ -1450,12 +1462,12 @@ pub fn (mut p Parser) key_value() !(ast.Key, ast.Value) { // see also `key()` and `value()` pub fn (mut p Parser) dotted_key_value() !(DottedKey, ast.Value) { util.printdbg(@MOD + '.' + @STRUCT + '.' + @FN, 'parsing dotted key value pair...') - p.ignore_while(space_formatting) + p.ignore_while(space_formatting_kinds()) dotted_key := p.dotted_key()! p.explicit_declared << p.build_abs_dotted_key(dotted_key) - p.ignore_while(space_formatting) + p.ignore_while(space_formatting_kinds()) p.check(.assign)! - p.ignore_while(space_formatting) + p.ignore_while(space_formatting_kinds()) value := p.value()! if p.value_is_immutable { if !p.immutable.has(dotted_key) { @@ -1490,7 +1502,7 @@ pub fn (mut p Parser) value() !ast.Value { ast.Value(p.array()!) } .lcbr { - p.ignore_while(space_formatting) + p.ignore_while(space_formatting_kinds()) mut t := map[string]ast.Value{} p.inline_table(mut t)! ast.Value(t) @@ -1535,7 +1547,7 @@ pub fn (mut p Parser) bare() !ast.Bare { mut lits := p.tok.lit pos := p.tok.pos() for p.peek_tok.kind != .assign && p.peek_tok.kind != .period && p.peek_tok.kind != .rsbr - && p.peek_tok.kind !in space_formatting { + && p.peek_tok.kind !in space_formatting_kinds() { p.next()! if p.tok.kind == .bare || p.tok.kind == .minus || p.tok.kind == .underscore { lits += p.tok.lit diff --git a/vlib/toml/to/to.v b/vlib/toml/to/to.v index e144c56dc..29608b1b2 100644 --- a/vlib/toml/to/to.v +++ b/vlib/toml/to/to.v @@ -12,7 +12,7 @@ type DocOrAny = toml.Any | toml.Doc pub fn json(doa DocOrAny) string { match doa { toml.Doc { - return any_to_json(toml.ast_to_any(doa.ast.table)) + return doa.ast.table.str() } toml.Any { return any_to_json(doa) @@ -27,34 +27,34 @@ fn any_to_json(a toml.Any) string { return 'null' } toml.DateTime { - return json2.Any(a.str()).json_str() + return json2.Any(toml.Any(a).string()).json_str() } toml.Date { - return json2.Any(a.str()).json_str() + return json2.Any(toml.Any(a).string()).json_str() } toml.Time { - return json2.Any(a.str()).json_str() + return json2.Any(toml.Any(a).string()).json_str() } string { - return json2.Any(a.str()).json_str() + return json2.Any(toml.Any(a).string()).json_str() } bool { - return json2.Any(bool(a)).json_str() + return json2.Any(toml.Any(a).bool()).json_str() } f32 { - return json2.Any(f32(a)).json_str() + return json2.Any(toml.Any(a).f32()).json_str() } f64 { - return json2.Any(f64(a)).json_str() + return json2.Any(toml.Any(a).f64()).json_str() } i64 { - return json2.Any(i64(a)).json_str() + return json2.Any(toml.Any(a).i64()).json_str() } int { - return json2.Any(int(a)).json_str() + return json2.Any(toml.Any(a).int()).json_str() } u64 { - return json2.Any(u64(a)).json_str() + return json2.Any(toml.Any(a).u64()).json_str() } map[string]toml.Any { mut str := '{' diff --git a/vlib/toml/toml.v b/vlib/toml/toml.v index 07894ea46..1876119e3 100644 --- a/vlib/toml/toml.v +++ b/vlib/toml/toml.v @@ -518,18 +518,26 @@ fn (d Doc) value_(value ast.Value, key []string) Any { // ast_to_any converts `from` ast.Value to toml.Any value. pub fn ast_to_any(value ast.Value) Any { + gc_disable() + defer { + gc_enable() + } + return ast_to_any_(value) +} + +fn ast_to_any_(value ast.Value) Any { match value { ast.Date { - return Any(Date{value.text}) + return Any(Date{value.text.clone()}) } ast.Time { - return Any(Time{value.text}) + return Any(Time{value.text.clone()}) } ast.DateTime { - return Any(DateTime{value.text}) + return Any(DateTime{value.text.clone()}) } ast.Quoted { - return Any(value.text) + return Any(value.text.clone()) } ast.Number { val_text := value.text @@ -563,16 +571,18 @@ pub fn ast_to_any(value ast.Value) Any { m := (value as map[string]ast.Value) mut am := map[string]Any{} for k, v in m { - am[k] = ast_to_any(v) + converted := ast_to_any_(v) + am[k] = converted } return am // return d.get_map_value(m, key_split[1..].join('.')) } []ast.Value { a := (value as []ast.Value) - mut aa := []Any{} + mut aa := []Any{cap: a.len} for val in a { - aa << ast_to_any(val) + converted := ast_to_any_(val) + aa << converted } return aa } diff --git a/vlib/v/preludes/test_runner_normal.v b/vlib/v/preludes/test_runner_normal.v index bed498b8e..800b6a008 100644 --- a/vlib/v/preludes/test_runner_normal.v +++ b/vlib/v/preludes/test_runner_normal.v @@ -19,7 +19,6 @@ pub mut: fname string use_color bool use_relative_paths bool - all_assertsions []&VAssertMetaInfo mut: file_test_info VTestFileMetaInfo fn_test_info VTestFnMetaInfo @@ -46,7 +45,6 @@ fn new_normal_test_runner() &TestRunner { fn (mut runner NormalTestRunner) free() { unsafe { - runner.all_assertsions.free() runner.fname.free() runner.fn_test_info.free() runner.file_test_info.free() @@ -61,9 +59,6 @@ fn normalise_fname(name string) string { } fn (mut runner NormalTestRunner) start(_ntests int) { - unsafe { - runner.all_assertsions = []&VAssertMetaInfo{cap: 1000} - } } fn (mut runner NormalTestRunner) finish() { @@ -111,10 +106,9 @@ fn (mut runner NormalTestRunner) fn_error(line_nr int, file string, _mod string, } } -fn (mut runner NormalTestRunner) assert_pass(i &VAssertMetaInfo) { +fn (mut runner NormalTestRunner) assert_pass(_ &VAssertMetaInfo) { runner.total_assert_passes++ runner.fn_assert_passes++ - runner.all_assertsions << i } fn (mut runner NormalTestRunner) assert_fail(i &VAssertMetaInfo) { @@ -180,5 +174,4 @@ fn (mut runner NormalTestRunner) assert_fail(i &VAssertMetaInfo) { eprintln('${mtitle} ${mvalue}') } eprintln('') - runner.all_assertsions << i } -- 2.39.5