Skip to content

Commit 5bc82ed

Browse files
authored
v.ast: add Table.update_sym_by_idx/2 (#25373)
1 parent e0d20a0 commit 5bc82ed

3 files changed

Lines changed: 79 additions & 0 deletions

File tree

‎vlib/v/ast/table.v‎

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -835,6 +835,24 @@ pub fn (t &Table) unaliased_type(typ Type) Type {
835835
return typ
836836
}
837837

838+
// update_sym_by_idx replaces the symbol on the `existing_idx`, with the new `sym`
839+
pub fn (mut t Table) update_sym_by_idx(existing_idx int, sym &TypeSymbol) {
840+
t.delete_cached_type_to_str(idx_to_type(existing_idx), 0)
841+
t.type_symbols[existing_idx] = &TypeSymbol{
842+
...sym
843+
idx: existing_idx
844+
size: -1 // enforce recalculation of the size, for future t.type_size(idx) calls
845+
align: -1
846+
}
847+
for mut esym in t.type_symbols {
848+
if esym.size != -1 && esym.info is Alias && esym.info.parent_type == existing_idx {
849+
// make sure to force recalculation, if t.type_size(idx) on an already existing alias is called again:
850+
esym.size = -1
851+
esym.align = -1
852+
}
853+
}
854+
}
855+
838856
fn (mut t Table) rewrite_already_registered_symbol(typ TypeSymbol, existing_idx int) int {
839857
existing_symbol := t.type_symbols[existing_idx]
840858
$if trace_rewrite_already_registered_symbol ? {

‎vlib/v/ast/table_test.v‎

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
import v.ast
2+
import v.pref
3+
import v.parser
4+
5+
fn test_update_sym_by_idx() {
6+
old_size := 47
7+
new_size := 100
8+
b_old_size := 4 * old_size
9+
b_new_size := 4 * new_size
10+
source := 'type T001 = [${old_size}]u32' // u32 is an element type, with a known size, that is not going to change in the future, unlike int
11+
// we will update the `size` & `size_expr` in sym.info for `T001`
12+
mut t := ast.new_table()
13+
parser.parse_text(source, '', mut t, .parse_comments, pref.new_preferences())
14+
15+
// retrieve old sym first:
16+
typ := t.type_idxs['[${old_size}]u32']!
17+
old_str := t.type_to_str(typ)
18+
assert old_str == '[${old_size}]u32'
19+
old_sym := t.sym(typ)
20+
old_info := old_sym.info as ast.ArrayFixed
21+
22+
alias_typ := t.type_idxs['main.T001']!
23+
alias_str := t.type_to_str(alias_typ)
24+
assert alias_str == 'main.T001'
25+
// make sure that the alias type had the correct size before the change (the size is stored in the alias type symbol)
26+
alias_size, _ := t.type_size(alias_typ)
27+
assert alias_size == b_old_size
28+
alias_sym := t.sym(alias_typ)
29+
assert (alias_sym.info as ast.Alias).parent_type == typ
30+
assert alias_sym.size == b_old_size
31+
32+
// update the existing sym
33+
new_info := ast.ArrayFixed{
34+
...old_info
35+
size: new_size
36+
size_expr: ast.empty_expr
37+
}
38+
new_sym := ast.TypeSymbol{
39+
...old_sym
40+
info: new_info
41+
}
42+
t.update_sym_by_idx(typ, new_sym)
43+
new_str := t.type_to_str(typ)
44+
assert new_str == '[${new_size}]u32'
45+
46+
// check again the alias size (it should be indirectly changed as well):
47+
new_alias_sym := t.sym(alias_typ)
48+
assert new_alias_sym.size == -1
49+
new_alias_size, _ := t.type_size(alias_typ)
50+
assert new_alias_size == b_new_size
51+
assert new_alias_sym.size == b_new_size // make sure that `new_alias_sym` is now updated too (since it is a pointer to a symbol value stored in the table)
52+
}

‎vlib/v/ast/types.v‎

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1459,6 +1459,15 @@ fn strip_extra_struct_types(name string) string {
14591459
}
14601460
}
14611461

1462+
// delete_cached_type_to_str remove a `type_to_str` from the cache
1463+
pub fn (t &Table) delete_cached_type_to_str(typ Type, import_aliases_len int) {
1464+
cache_key := (u64(import_aliases_len) << 32) | u64(typ)
1465+
mut mt := unsafe { &Table(t) }
1466+
lock mt.cached_type_to_str {
1467+
mt.cached_type_to_str.delete(cache_key)
1468+
}
1469+
}
1470+
14621471
// import_aliases is a map of imported symbol aliases 'module.Type' => 'Type'
14631472
pub fn (t &Table) type_to_str_using_aliases(typ Type, import_aliases map[string]string) string {
14641473
cache_key := (u64(import_aliases.len) << 32) | u64(typ)

0 commit comments

Comments
 (0)