1
0
mirror of https://github.com/vlang/v.git synced 2023-08-10 21:13:21 +03:00

all: move cur_concrete_types to Table (#10269)

This commit is contained in:
yuyi 2021-05-31 22:14:45 +08:00 committed by GitHub
parent 9fc5b9dc54
commit cb19079d53
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 60 additions and 63 deletions

View File

@ -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. <int, string>
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 {`
}

View File

@ -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)

View File

@ -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. <int, string>
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<int>',
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.

View File

@ -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. <int, string>
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

View File

@ -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<T>() => foo_T_int(), foo_T_string() etc
// Using _T_ to differentiate between get<string> 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
}