diff --git a/vlib/v/ast/table.v b/vlib/v/ast/table.v index 67fc9adf30..9ed4023526 100644 --- a/vlib/v/ast/table.v +++ b/vlib/v/ast/table.v @@ -10,26 +10,27 @@ import v.util [heap] pub struct Table { pub mut: - type_symbols []TypeSymbol - type_idxs map[string]int - fns map[string]Fn - dumps map[int]string // needed for efficiently generating all _v_dump_expr_TNAME() functions - imports []string // List of all imports - modules []string // Topologically sorted list of all modules registered by the application - cflags []cflag.CFlag - redefined_fns []string - fn_generic_types map[string][][]Type // for generic functions - interfaces map[int]InterfaceDecl - cmod_prefix string // needed for ast.type_to_str(Type) while vfmt; contains `os.` - is_fmt bool - used_fns map[string]bool // filled in by the checker, when pref.skip_unused = true; - used_consts map[string]bool // filled in by the checker, when pref.skip_unused = true; - used_vweb_types []Type // vweb context types, filled in by checker, when pref.skip_unused = true; - panic_handler FnPanicHandler = default_table_panic_handler - panic_userdata voidptr = voidptr(0) // can be used to pass arbitrary data to panic_handler; - panic_npanics int - cur_fn &FnDecl = 0 // previously stored in Checker.cur_fn and Gen.cur_fn - gostmts int // how many `go` statements there were in the parsed files. + type_symbols []TypeSymbol + type_idxs map[string]int + fns map[string]Fn + dumps map[int]string // needed for efficiently generating all _v_dump_expr_TNAME() functions + imports []string // List of all imports + modules []string // Topologically sorted list of all modules registered by the application + cflags []cflag.CFlag + redefined_fns []string + fn_generic_types map[string][][]Type // for generic functions + interfaces map[int]InterfaceDecl + cmod_prefix string // needed for ast.type_to_str(Type) while vfmt; contains `os.` + is_fmt bool + used_fns map[string]bool // filled in by the checker, when pref.skip_unused = true; + used_consts map[string]bool // filled in by the checker, when pref.skip_unused = true; + used_vweb_types []Type // vweb context types, filled in by checker, when pref.skip_unused = true; + panic_handler FnPanicHandler = default_table_panic_handler + panic_userdata voidptr = voidptr(0) // can be used to pass arbitrary data to panic_handler; + panic_npanics int + cur_fn &FnDecl = 0 // previously stored in Checker.cur_fn and Gen.cur_fn + cur_concrete_types []Type // current concrete types, e.g. + gostmts int // how many `go` statements there were in the parsed files. // When table.gostmts > 0, __VTHREADS__ is defined, which can be checked with `$if threads {` } diff --git a/vlib/v/checker/check_types.v b/vlib/v/checker/check_types.v index af258a925b..063e83e6d8 100644 --- a/vlib/v/checker/check_types.v +++ b/vlib/v/checker/check_types.v @@ -508,9 +508,9 @@ pub fn (mut c Checker) infer_fn_generic_types(f ast.Fn, mut call_expr ast.CallEx info := sym.info as ast.Struct if c.table.cur_fn.generic_names.len > 0 { // in generic fn if gt_name in c.table.cur_fn.generic_names - && c.table.cur_fn.generic_names.len == c.cur_concrete_types.len { + && c.table.cur_fn.generic_names.len == c.table.cur_concrete_types.len { idx := c.table.cur_fn.generic_names.index(gt_name) - typ = c.cur_concrete_types[idx] + typ = c.table.cur_concrete_types[idx] } } else { // in non-generic fn receiver_generic_names := info.generic_types.map(c.table.get_type_symbol(it).name) diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index bdbe52a655..064c9c1f51 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -49,14 +49,13 @@ pub mut: error_lines []int // to avoid printing multiple errors for the same line expected_type ast.Type expected_or_type ast.Type // fn() or { 'this type' } eg. string. expected or block type - // cur_fn &ast.FnDecl // current function - const_decl string - const_deps []string - const_names []string - global_names []string - locked_names []string // vars that are currently locked - rlocked_names []string // vars that are currently read-locked - in_for_count int // if checker is currently in a for loop + const_decl string + const_deps []string + const_names []string + global_names []string + locked_names []string // vars that are currently locked + rlocked_names []string // vars that are currently read-locked + in_for_count int // if checker is currently in a for loop // checked_ident string // to avoid infinite checker loops returns bool scope_returns bool @@ -82,7 +81,6 @@ mut: timers &util.Timers = util.new_timers(false) comptime_fields_type map[string]ast.Type fn_scope &ast.Scope = voidptr(0) - cur_concrete_types []ast.Type // current concrete types, e.g. main_fn_decl_node ast.FnDecl match_exhaustive_cutoff_limit int = 10 // TODO: these are here temporarily and used for deprecations; remove soon @@ -689,7 +687,7 @@ pub fn (mut c Checker) struct_init(mut struct_init ast.StructInit) ast.Type { struct_sym := c.table.get_type_symbol(struct_init.typ) if struct_sym.info is ast.Struct { if struct_sym.info.generic_types.len > 0 && struct_sym.info.concrete_types.len == 0 - && c.cur_concrete_types.len == 0 { + && c.table.cur_concrete_types.len == 0 { c.error('generic struct init must specify type parameter, e.g. Foo', struct_init.pos) } @@ -704,7 +702,7 @@ pub fn (mut c Checker) struct_init(mut struct_init ast.StructInit) ast.Type { return ast.void_type } } - utyp := c.unwrap_generic_struct(struct_init.typ, c.table.cur_fn.generic_names, c.cur_concrete_types) + utyp := c.unwrap_generic_struct(struct_init.typ, c.table.cur_fn.generic_names, c.table.cur_concrete_types) c.ensure_type_exists(utyp, struct_init.pos) or {} type_sym := c.table.get_type_symbol(utyp) if !c.inside_unsafe && type_sym.kind == .sum_type { @@ -713,7 +711,7 @@ pub fn (mut c Checker) struct_init(mut struct_init ast.StructInit) ast.Type { // Make sure the first letter is capital, do not allow e.g. `x := string{}`, // but `x := T{}` is ok. if !c.is_builtin_mod && !c.inside_unsafe && type_sym.language == .v - && c.cur_concrete_types.len == 0 { + && c.table.cur_concrete_types.len == 0 { pos := type_sym.name.last_index('.') or { -1 } first_letter := type_sym.name[pos + 1] if !first_letter.is_capital() { @@ -2220,7 +2218,7 @@ pub fn (mut c Checker) fn_call(mut call_expr ast.CallExpr) ast.Type { concrete_types << concrete_type } } - if !isnil(c.table.cur_fn) && c.cur_concrete_types.len == 0 && has_generic { + if !isnil(c.table.cur_fn) && c.table.cur_concrete_types.len == 0 && has_generic { c.error('generic fn using generic types cannot be called outside of generic fn', call_expr.pos) } @@ -2981,7 +2979,7 @@ pub fn (mut c Checker) return_stmt(mut return_stmt ast.Return) { mut expected_type := c.unwrap_generic(c.expected_type) if expected_type.has_flag(.generic) && c.table.get_type_symbol(expected_type).kind == .struct_ { if t_typ := c.table.resolve_generic_to_concrete(expected_type, c.table.cur_fn.generic_names, - c.cur_concrete_types, true) + c.table.cur_concrete_types, true) { expected_type = t_typ } @@ -3004,7 +3002,7 @@ pub fn (mut c Checker) return_stmt(mut return_stmt ast.Return) { mut expected_types := [expected_type] if expected_type_sym.info is ast.MultiReturn { expected_types = expected_type_sym.info.types - if c.cur_concrete_types.len > 0 { + if c.table.cur_concrete_types.len > 0 { expected_types = expected_types.map(c.unwrap_generic(it)) } } @@ -4561,7 +4559,7 @@ fn (mut c Checker) stmts(stmts []ast.Stmt) { pub fn (mut c Checker) unwrap_generic(typ ast.Type) ast.Type { if typ.has_flag(.generic) { if t_typ := c.table.resolve_generic_to_concrete(typ, c.table.cur_fn.generic_names, - c.cur_concrete_types, false) + c.table.cur_concrete_types, false) { return t_typ } @@ -7063,7 +7061,7 @@ fn (mut c Checker) post_process_generic_fns() { mut node := c.file.generic_fns[i] c.mod = node.mod for concrete_types in c.table.fn_generic_types[node.name] { - c.cur_concrete_types = concrete_types + c.table.cur_concrete_types = concrete_types c.fn_decl(mut node) if node.name == 'vweb.run' { for ct in concrete_types { @@ -7073,13 +7071,13 @@ fn (mut c Checker) post_process_generic_fns() { } } } - c.cur_concrete_types = [] + c.table.cur_concrete_types = [] } } fn (mut c Checker) fn_decl(mut node ast.FnDecl) { c.returns = false - if node.generic_names.len > 0 && c.cur_concrete_types.len == 0 { + if node.generic_names.len > 0 && c.table.cur_concrete_types.len == 0 { // Just remember the generic function for now. // It will be processed later in c.post_process_generic_fns, // after all other normal functions are processed. diff --git a/vlib/v/gen/c/cgen.v b/vlib/v/gen/c/cgen.v index 3667b42a3a..a280086699 100644 --- a/vlib/v/gen/c/cgen.v +++ b/vlib/v/gen/c/cgen.v @@ -124,22 +124,20 @@ mut: is_builtin_mod bool hotcode_fn_names []string embedded_files []ast.EmbeddedFile - // cur_fn ast.FnDecl - cur_concrete_types []ast.Type // current concrete types, e.g. - sql_i int - sql_stmt_name string - sql_bind_name string - sql_idents []string - sql_idents_types []ast.Type - sql_left_type ast.Type - sql_table_name string - sql_fkey string - sql_parent_id string - sql_side SqlExprSide // left or right, to distinguish idents in `name == name` - inside_vweb_tmpl bool - inside_return bool - inside_or_block bool - strs_to_free0 []string // strings.Builder + sql_i int + sql_stmt_name string + sql_bind_name string + sql_idents []string + sql_idents_types []ast.Type + sql_left_type ast.Type + sql_table_name string + sql_fkey string + sql_parent_id string + sql_side SqlExprSide // left or right, to distinguish idents in `name == name` + inside_vweb_tmpl bool + inside_return bool + inside_or_block bool + strs_to_free0 []string // strings.Builder // strs_to_free []string // strings.Builder inside_call bool has_main bool diff --git a/vlib/v/gen/c/fn.v b/vlib/v/gen/c/fn.v index 14637092aa..c8f7dcf24b 100644 --- a/vlib/v/gen/c/fn.v +++ b/vlib/v/gen/c/fn.v @@ -141,7 +141,7 @@ fn (mut g Gen) gen_fn_decl(node &ast.FnDecl, skip bool) { // if g.fileis('vweb.v') { // println('\ngen_fn_decl() $node.name $node.is_generic $g.cur_generic_type') // } - if node.generic_names.len > 0 && g.cur_concrete_types.len == 0 { // need the cur_concrete_type check to avoid inf. recursion + if node.generic_names.len > 0 && g.table.cur_concrete_types.len == 0 { // need the cur_concrete_type check to avoid inf. recursion // loop thru each generic type and generate a function for concrete_types in g.table.fn_generic_types[node.name] { if g.pref.is_verbose { @@ -149,10 +149,10 @@ fn (mut g Gen) gen_fn_decl(node &ast.FnDecl, skip bool) { the_type := syms.map(node.name).join(', ') println('gen fn `$node.name` for type `$the_type`') } - g.cur_concrete_types = concrete_types + g.table.cur_concrete_types = concrete_types g.gen_fn_decl(node, skip) } - g.cur_concrete_types = [] + g.table.cur_concrete_types = [] return } cur_fn_save := g.table.cur_fn @@ -190,11 +190,11 @@ fn (mut g Gen) gen_fn_decl(node &ast.FnDecl, skip bool) { name = c_name(name) } mut type_name := g.typ(node.return_type) - if g.cur_concrete_types.len > 0 { + if g.table.cur_concrete_types.len > 0 { // foo() => foo_T_int(), foo_T_string() etc // Using _T_ to differentiate between get and get_string name += '_T' - for concrete_type in g.cur_concrete_types { + for concrete_type in g.table.cur_concrete_types { gen_name := g.typ(concrete_type) name += '_' + gen_name } @@ -504,7 +504,7 @@ fn (mut g Gen) call_expr(node ast.CallExpr) { pub fn (mut g Gen) unwrap_generic(typ ast.Type) ast.Type { if typ.has_flag(.generic) { if t_typ := g.table.resolve_generic_to_concrete(typ, g.table.cur_fn.generic_names, - g.cur_concrete_types, false) + g.table.cur_concrete_types, false) { return t_typ }