From 97edd610b08ab5f51106c22ae01b0fa05acccbea Mon Sep 17 00:00:00 2001 From: Felipe Pena Date: Tue, 16 Sep 2025 14:37:15 -0300 Subject: [PATCH] v: implement comptime regular func params traversing (support `$if T is $function { $for param in T.params {`) (#25322) --- vlib/builtin/builtin.v | 6 ++-- vlib/v/checker/comptime.v | 6 ++-- vlib/v/gen/c/comptime.v | 14 ++++----- vlib/v/markused/walker.v | 2 +- vlib/v/parser/comptime.v | 2 +- vlib/v/tests/comptime/comptime_params_test.v | 30 ++++++++++++++++++++ 6 files changed, 46 insertions(+), 14 deletions(-) create mode 100644 vlib/v/tests/comptime/comptime_params_test.v diff --git a/vlib/builtin/builtin.v b/vlib/builtin/builtin.v index 3a8347f81..f8916a027 100644 --- a/vlib/builtin/builtin.v +++ b/vlib/builtin/builtin.v @@ -88,8 +88,8 @@ fn __print_assert_failure(i &VAssertMetaInfo) { } } -// MethodParam holds type information for function and/or method arguments. -pub struct MethodParam { +// FunctionParam holds type information for function and/or method arguments. +pub struct FunctionParam { pub: typ int name string @@ -100,7 +100,7 @@ pub struct FunctionData { pub: name string attrs []string - args []MethodParam + args []FunctionParam return_type int typ int } diff --git a/vlib/v/checker/comptime.v b/vlib/v/checker/comptime.v index e8d99be0d..e9c0bac40 100644 --- a/vlib/v/checker/comptime.v +++ b/vlib/v/checker/comptime.v @@ -364,11 +364,13 @@ fn (mut c Checker) comptime_for(mut node ast.ComptimeFor) { node.typ_pos) return } - method := c.comptime.comptime_for_method + + func := if sym.info is ast.FnType { &sym.info.func } else { c.comptime.comptime_for_method } + params := if func.is_method { func.params[1..] } else { func.params } // example: fn (mut d MyStruct) add(x int, y int) string // `d` is params[0], `x` is params[1], `y` is params[2] // so we at least has one param (`d`) for method - for param in method.params[1..] { + for param in params { c.push_new_comptime_info() c.comptime.inside_comptime_for = true c.comptime.comptime_for_method_param_var = node.val_var diff --git a/vlib/v/gen/c/comptime.v b/vlib/v/gen/c/comptime.v index 3c811f5a1..f5a6dc810 100644 --- a/vlib/v/gen/c/comptime.v +++ b/vlib/v/gen/c/comptime.v @@ -649,10 +649,10 @@ fn (mut g Gen) comptime_for(node ast.ComptimeFor) { } if method.params.len < 2 { // 0 or 1 (the receiver) args - g.writeln('\t${node.val_var}.args = builtin____new_array_with_default(0, 0, sizeof(MethodParam), 0);') + g.writeln('\t${node.val_var}.args = builtin____new_array_with_default(0, 0, sizeof(FunctionParam), 0);') } else { len := method.params.len - 1 - g.write('\t${node.val_var}.args = builtin__new_array_from_c_array(${len}, ${len}, sizeof(MethodParam), _MOV((MethodParam[${len}]){') + g.write('\t${node.val_var}.args = builtin__new_array_from_c_array(${len}, ${len}, sizeof(FunctionParam), _MOV((FunctionParam[${len}]){') // Skip receiver arg for j, arg in method.params[1..] { typ := arg.typ.idx() @@ -841,12 +841,12 @@ fn (mut g Gen) comptime_for(node ast.ComptimeFor) { } } } else if node.kind == .params { - method := g.comptime.comptime_for_method - - if method.params.len > 0 { - g.writeln('\tMethodParam ${node.val_var} = {0};') + func := if sym.info is ast.FnType { &sym.info.func } else { g.comptime.comptime_for_method } + if func.params.len > 0 { + g.writeln('\tFunctionParam ${node.val_var} = {0};') } - for param in method.params[1..] { + params := if func.is_method { func.params[1..] } else { func.params } + for param in params { g.push_new_comptime_info() g.comptime.inside_comptime_for = true g.comptime.comptime_for_method_param_var = node.val_var diff --git a/vlib/v/markused/walker.v b/vlib/v/markused/walker.v index 263d3e65e..ce63ea569 100644 --- a/vlib/v/markused/walker.v +++ b/vlib/v/markused/walker.v @@ -1354,7 +1354,7 @@ fn (mut w Walker) mark_resource_dependencies() { w.mark_by_sym_name('FunctionData') } if w.uses_ct_params { - w.mark_by_sym_name('MethodParam') + w.mark_by_sym_name('FunctionParam') } if w.uses_ct_values { w.mark_by_sym_name('EnumData') diff --git a/vlib/v/parser/comptime.v b/vlib/v/parser/comptime.v index 67ca8dfd4..51f74bbc3 100644 --- a/vlib/v/parser/comptime.v +++ b/vlib/v/parser/comptime.v @@ -423,7 +423,7 @@ fn (mut p Parser) comptime_for() ast.ComptimeFor { 'params' { p.scope.register(ast.Var{ name: val_var - typ: p.table.find_type('MethodParam') + typ: p.table.find_type('FunctionParam') pos: var_pos }) kind = .params diff --git a/vlib/v/tests/comptime/comptime_params_test.v b/vlib/v/tests/comptime/comptime_params_test.v new file mode 100644 index 000000000..7fff5bdbd --- /dev/null +++ b/vlib/v/tests/comptime/comptime_params_test.v @@ -0,0 +1,30 @@ +fn demo(a int, b string) { +} + +fn g[T](cb T) { + mut params := []FunctionParam{} + $if T is $function { + $for param in T.params { + params << param + } + } + assert params.len == 2 + assert params[0].name == 'a' + assert params[0].typ == 8 + assert params[1].name == 'b' + assert params[1].typ == 21 +} + +fn test_main() { + g(demo) + + mut params := []FunctionParam{} + $for param in demo.params { + params << param + } + assert params.len == 2 + assert params[0].name == 'a' + assert params[0].typ == 8 + assert params[1].name == 'b' + assert params[1].typ == 21 +} -- 2.39.5