Skip to content

Commit 6ffce6a

Browse files
committed
handle pointer type AST in v2 codegen
1 parent 4ca3645 commit 6ffce6a

7 files changed

Lines changed: 98 additions & 0 deletions

File tree

vlib/v2/gen/cleanc/cleanc_test.v

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,18 @@ fn test_record_generic_struct_bindings_filters_lifetime_params() {
113113
assert instances[0].params_key == 'Value'
114114
}
115115

116+
fn test_expr_type_to_c_lowers_pointer_type() {
117+
mut g := Gen.new([])
118+
pointer_type := ast.Expr(ast.Type(ast.PointerType{
119+
base_type: ast.Expr(ast.Ident{
120+
name: 'Foo'
121+
})
122+
}))
123+
assert g.expr_type_to_c(pointer_type) == 'Foo*'
124+
assert g.is_pointer_type(pointer_type)
125+
assert g.receiver_type_to_scope_name(pointer_type) == 'Foo'
126+
}
127+
116128
fn test_fixed_array_elem_type_ready_accepts_primitive_alias() {
117129
mut g := Gen.new([])
118130
g.primitive_type_aliases['sha3__Lane'] = true

vlib/v2/gen/cleanc/flag_enum_codegen_test.v

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,3 +111,41 @@ struct Holder[^a] {
111111
assert csrc.contains('Value value;')
112112
assert !csrc.contains('T value;')
113113
}
114+
115+
fn test_generate_c_lowers_pointer_type_params_receivers_fields_and_generics() {
116+
csrc := generate_c_for_test('
117+
struct Foo {
118+
value int
119+
}
120+
121+
struct Node[T] {
122+
value T
123+
}
124+
125+
struct Holder {
126+
item &Foo
127+
node &Node[Foo]
128+
}
129+
130+
fn ptr_value(foo &Foo) int {
131+
return foo.value
132+
}
133+
134+
fn (foo &Foo) method_value() int {
135+
return foo.value
136+
}
137+
138+
fn main() {
139+
foo := Foo{}
140+
_ := ptr_value(&foo)
141+
_ := foo.method_value()
142+
}
143+
')
144+
assert csrc.contains('Foo* item;')
145+
assert csrc.contains('Node* node;')
146+
assert csrc.contains('Foo value;')
147+
assert csrc.contains('ptr_value(Foo* foo)')
148+
assert csrc.contains('Foo__method_value(Foo* foo)')
149+
assert !csrc.contains('int item;')
150+
assert !csrc.contains('int ptr_value(int foo)')
151+
}

vlib/v2/gen/cleanc/fn.v

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -530,6 +530,9 @@ fn collect_generic_placeholder_names_from_expr(expr ast.Expr, mut seen map[strin
530530
collect_generic_placeholder_names_from_expr(expr.key_type, mut seen, mut out)
531531
collect_generic_placeholder_names_from_expr(expr.value_type, mut seen, mut out)
532532
}
533+
ast.PointerType {
534+
collect_generic_placeholder_names_from_expr(expr.base_type, mut seen, mut out)
535+
}
533536
ast.OptionType {
534537
collect_generic_placeholder_names_from_expr(expr.base_type, mut seen, mut out)
535538
}
@@ -972,6 +975,12 @@ fn infer_generic_type_bindings_from_param(param ast.Expr, concrete types.Type, g
972975
concrete.value_type, generic_params, mut bindings)
973976
}
974977
}
978+
ast.PointerType {
979+
if concrete is types.Pointer {
980+
infer_generic_type_bindings_from_param(param.base_type, concrete.base_type,
981+
generic_params, mut bindings)
982+
}
983+
}
975984
ast.OptionType {
976985
if concrete is types.OptionType {
977986
infer_generic_type_bindings_from_param(param.base_type, concrete.base_type,
@@ -1004,6 +1013,11 @@ fn direct_generic_placeholder_name(e ast.Expr) string {
10041013
ast.ModifierExpr {
10051014
return direct_generic_placeholder_name(e.expr)
10061015
}
1016+
ast.Type {
1017+
if e is ast.PointerType {
1018+
return direct_generic_placeholder_name(e.base_type)
1019+
}
1020+
}
10071021
else {}
10081022
}
10091023

@@ -4946,6 +4960,9 @@ fn expr_has_generic_placeholder(e ast.Expr) bool {
49464960
return expr_has_generic_placeholder(e.key_type)
49474961
|| expr_has_generic_placeholder(e.value_type)
49484962
}
4963+
ast.PointerType {
4964+
return expr_has_generic_placeholder(e.base_type)
4965+
}
49494966
ast.OptionType {
49504967
return expr_has_generic_placeholder(e.base_type)
49514968
}

vlib/v2/gen/cleanc/struct.v

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,9 @@ fn (mut g Gen) propagate_generic_bindings(e ast.Expr, parent_bindings map[string
118118
g.propagate_generic_bindings(param, parent_bindings)
119119
}
120120
}
121+
if e is ast.PointerType {
122+
g.propagate_generic_bindings(e.base_type, parent_bindings)
123+
}
121124
}
122125
ast.PrefixExpr {
123126
g.propagate_generic_bindings(e.expr, parent_bindings)
@@ -187,6 +190,9 @@ fn (mut g Gen) scan_expr_for_generic_types(e ast.Expr) {
187190
g.scan_expr_for_generic_types(e.key_type)
188191
g.scan_expr_for_generic_types(e.value_type)
189192
}
193+
if e is ast.PointerType {
194+
g.scan_expr_for_generic_types(e.base_type)
195+
}
190196
if e is ast.OptionType {
191197
g.scan_expr_for_generic_types(e.base_type)
192198
}

vlib/v2/gen/cleanc/types.v

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -603,6 +603,11 @@ fn (mut g Gen) is_pointer_type(e ast.Expr) bool {
603603
if e is ast.ModifierExpr {
604604
return g.is_pointer_type(e.expr)
605605
}
606+
if e is ast.Type {
607+
if e is ast.PointerType {
608+
return true
609+
}
610+
}
606611
if e is ast.Ident {
607612
if e.name in ['voidptr', 'charptr', 'byteptr'] || e.name.ends_with('ptr') {
608613
return true
@@ -1685,6 +1690,9 @@ fn (g &Gen) receiver_type_to_scope_name(typ ast.Expr) string {
16851690
}
16861691
}
16871692
if typ is ast.Type {
1693+
if typ is ast.PointerType {
1694+
return g.receiver_type_to_scope_name(typ.base_type)
1695+
}
16881696
// Array type: []T -> "[]T"
16891697
if typ is ast.ArrayType {
16901698
elem := g.receiver_type_to_scope_name(typ.elem_type)
@@ -2593,6 +2601,9 @@ fn (mut g Gen) expr_type_to_c(e ast.Expr) string {
25932601
if e is ast.ChannelType {
25942602
return 'chan'
25952603
}
2604+
if e is ast.PointerType {
2605+
return g.expr_type_to_c(e.base_type) + '*'
2606+
}
25962607
if e is ast.TupleType {
25972608
mut elem_types := []string{cap: e.types.len}
25982609
for t in e.types {

vlib/v2/transformer/transformer_test.v

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4206,6 +4206,17 @@ fn test_transformer_preserves_pointer_lifetime_in_v_syntax_but_not_c_names() {
42064206
assert t.type_to_c_name(ptr_type) == 'Fooptr'
42074207
}
42084208

4209+
fn test_transformer_uses_pointer_type_receiver_name_for_scope_key() {
4210+
t := create_test_transformer()
4211+
receiver := ast.Expr(ast.Type(ast.PointerType{
4212+
base_type: ast.Expr(ast.Ident{
4213+
name: 'Ignore'
4214+
})
4215+
lifetime: 'a'
4216+
}))
4217+
assert t.get_receiver_type_name(receiver) == 'Ignore'
4218+
}
4219+
42094220
fn test_transformer_preserves_lifetime_method_signature_and_nested_generic_return_type() {
42104221
files := transform_code_for_test('
42114222
struct Ignore {}

vlib/v2/transformer/types.v

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3090,6 +3090,9 @@ fn (t &Transformer) get_receiver_type_name(typ ast.Expr) string {
30903090
}
30913091
if typ is ast.Type {
30923092
// Handle wrapped type variants (GenericType, etc.)
3093+
if typ is ast.PointerType {
3094+
return t.get_receiver_type_name(typ.base_type)
3095+
}
30933096
if typ is ast.GenericType {
30943097
// Type[T] -> Type
30953098
return t.get_receiver_type_name(typ.name)

0 commit comments

Comments
 (0)