diff --git a/vlib/v/gen/c/cgen.v b/vlib/v/gen/c/cgen.v index d731bae40d..6180e9aa6f 100644 --- a/vlib/v/gen/c/cgen.v +++ b/vlib/v/gen/c/cgen.v @@ -197,6 +197,7 @@ mut: comptime_for_field_value ast.StructField // value of the field variable comptime_for_field_type ast.Type // type of the field variable inferred from `$if field.typ is T {}` comptime_var_type_map map[string]ast.Type + comptime_values_stack []CurrentComptimeValues // stores the values from the above on each $for loop, to make nesting them easier prevent_sum_type_unwrapping_once bool // needed for assign new values to sum type // used in match multi branch // TypeOne, TypeTwo {} diff --git a/vlib/v/gen/c/comptime.v b/vlib/v/gen/c/comptime.v index e634524457..ceb3ad37f6 100644 --- a/vlib/v/gen/c/comptime.v +++ b/vlib/v/gen/c/comptime.v @@ -506,6 +506,33 @@ fn (mut g Gen) comptime_if_cond(cond ast.Expr, pkg_exist bool) bool { } } +// + +struct CurrentComptimeValues { + inside_comptime_for_field bool + comptime_for_method string + comptime_for_field_var string + comptime_for_field_value ast.StructField + comptime_for_field_type ast.Type + comptime_var_type_map map[string]ast.Type +} + +fn (mut g Gen) push_existing_comptime_values() { + g.comptime_values_stack << CurrentComptimeValues{g.inside_comptime_for_field, g.comptime_for_method, g.comptime_for_field_var, g.comptime_for_field_value, g.comptime_for_field_type, g.comptime_var_type_map.clone()} +} + +fn (mut g Gen) pop_existing_comptime_values() { + old := g.comptime_values_stack.pop() + g.inside_comptime_for_field = old.inside_comptime_for_field + g.comptime_for_method = old.comptime_for_method + g.comptime_for_field_var = old.comptime_for_field_var + g.comptime_for_field_value = old.comptime_for_field_value + g.comptime_for_field_type = old.comptime_for_field_type + g.comptime_var_type_map = old.comptime_var_type_map.clone() +} + +// + fn (mut g Gen) comptime_for(node ast.ComptimeFor) { sym := g.table.final_sym(g.unwrap_generic(node.typ)) g.writeln('/* \$for ${node.val_var} in ${sym.name}(${node.kind.str()}) */ {') @@ -522,6 +549,7 @@ fn (mut g Gen) comptime_for(node ast.ComptimeFor) { } typ_vweb_result := g.table.find_type_idx('vweb.Result') for method in methods { + g.push_existing_comptime_values() // filter vweb route methods (non-generic method) if method.receiver_type != 0 && method.return_type == typ_vweb_result { rec_sym := g.table.sym(method.receiver_type) @@ -529,6 +557,7 @@ fn (mut g Gen) comptime_for(node ast.ComptimeFor) { if _ := g.table.find_field_with_embeds(rec_sym, 'Context') { if method.generic_names.len > 0 || (method.params.len > 1 && method.attrs.len == 0) { + g.pop_existing_comptime_values() continue } } @@ -589,16 +618,7 @@ fn (mut g Gen) comptime_for(node ast.ComptimeFor) { g.stmts(node.stmts) i++ g.writeln('}') - // - mut delete_keys := []string{} - for key, _ in g.comptime_var_type_map { - if key.starts_with(node.val_var) { - delete_keys << key - } - } - for key in delete_keys { - g.comptime_var_type_map.delete(key) - } + g.pop_existing_comptime_values() } } else if node.kind == .fields { // TODO add fields @@ -607,8 +627,9 @@ fn (mut g Gen) comptime_for(node ast.ComptimeFor) { if sym_info.fields.len > 0 { g.writeln('\tFieldData ${node.val_var} = {0};') } - g.inside_comptime_for_field = true for field in sym_info.fields { + g.push_existing_comptime_values() + g.inside_comptime_for_field = true g.comptime_for_field_var = node.val_var g.comptime_for_field_value = field g.comptime_for_field_type = field.typ @@ -648,10 +669,8 @@ fn (mut g Gen) comptime_for(node ast.ComptimeFor) { g.stmts(node.stmts) i++ g.writeln('}') - g.comptime_for_field_type = 0 + g.pop_existing_comptime_values() } - g.inside_comptime_for_field = false - g.comptime_var_type_map.delete(node.val_var) } } else if node.kind == .attributes { if sym.info is ast.Struct {