all: minor cleanup of generics (#9744)
parent
dcf4a6b008
commit
466dc4540b
|
@ -9,19 +9,19 @@ import v.util
|
||||||
|
|
||||||
pub struct Table {
|
pub struct Table {
|
||||||
pub mut:
|
pub mut:
|
||||||
type_symbols []TypeSymbol
|
type_symbols []TypeSymbol
|
||||||
type_idxs map[string]int
|
type_idxs map[string]int
|
||||||
fns map[string]Fn
|
fns map[string]Fn
|
||||||
dumps map[int]string // needed for efficiently generating all _v_dump_expr_TNAME() functions
|
dumps map[int]string // needed for efficiently generating all _v_dump_expr_TNAME() functions
|
||||||
imports []string // List of all imports
|
imports []string // List of all imports
|
||||||
modules []string // Topologically sorted list of all modules registered by the application
|
modules []string // Topologically sorted list of all modules registered by the application
|
||||||
cflags []cflag.CFlag
|
cflags []cflag.CFlag
|
||||||
redefined_fns []string
|
redefined_fns []string
|
||||||
fn_gen_types map[string][][]Type // for generic functions
|
fn_generic_types map[string][][]Type // for generic functions
|
||||||
cmod_prefix string // needed for ast.type_to_str(Type) while vfmt; contains `os.`
|
cmod_prefix string // needed for ast.type_to_str(Type) while vfmt; contains `os.`
|
||||||
is_fmt bool
|
is_fmt bool
|
||||||
used_fns map[string]bool // filled in by the checker, when pref.skip_unused = true;
|
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_consts map[string]bool // filled in by the checker, when pref.skip_unused = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Fn {
|
pub struct Fn {
|
||||||
|
@ -859,13 +859,13 @@ pub fn (t &Table) mktyp(typ Type) Type {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (mut t Table) register_fn_gen_type(fn_name string, types []Type) {
|
pub fn (mut t Table) register_fn_generic_types(fn_name string, types []Type) {
|
||||||
mut a := t.fn_gen_types[fn_name]
|
mut a := t.fn_generic_types[fn_name]
|
||||||
if types in a {
|
if types in a {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
a << types
|
a << types
|
||||||
t.fn_gen_types[fn_name] = a
|
t.fn_generic_types[fn_name] = a
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: there is a bug when casting sumtype the other way if its pointer
|
// TODO: there is a bug when casting sumtype the other way if its pointer
|
||||||
|
|
|
@ -475,7 +475,7 @@ pub fn (mut c Checker) string_inter_lit(mut node ast.StringInterLiteral) ast.Typ
|
||||||
return ast.string_type
|
return ast.string_type
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (mut c Checker) infer_fn_types(f ast.Fn, mut call_expr ast.CallExpr) {
|
pub fn (mut c Checker) infer_fn_generic_types(f ast.Fn, mut call_expr ast.CallExpr) {
|
||||||
mut inferred_types := []ast.Type{}
|
mut inferred_types := []ast.Type{}
|
||||||
for gi, gt_name in f.generic_names {
|
for gi, gt_name in f.generic_names {
|
||||||
// skip known types
|
// skip known types
|
||||||
|
@ -565,5 +565,5 @@ pub fn (mut c Checker) infer_fn_types(f ast.Fn, mut call_expr ast.CallExpr) {
|
||||||
inferred_types << typ
|
inferred_types << typ
|
||||||
call_expr.generic_types << typ
|
call_expr.generic_types << typ
|
||||||
}
|
}
|
||||||
c.table.register_fn_gen_type(f.name, inferred_types)
|
c.table.register_fn_generic_types(f.name, inferred_types)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1494,9 +1494,9 @@ pub fn (mut c Checker) method_call(mut call_expr ast.CallExpr) ast.Type {
|
||||||
if has_generic_generic {
|
if has_generic_generic {
|
||||||
if c.mod != '' {
|
if c.mod != '' {
|
||||||
// Need to prepend the module when adding a generic type to a function
|
// Need to prepend the module when adding a generic type to a function
|
||||||
c.table.register_fn_gen_type(c.mod + '.' + call_expr.name, generic_types)
|
c.table.register_fn_generic_types(c.mod + '.' + call_expr.name, generic_types)
|
||||||
} else {
|
} else {
|
||||||
c.table.register_fn_gen_type(call_expr.name, generic_types)
|
c.table.register_fn_generic_types(call_expr.name, generic_types)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// TODO: remove this for actual methods, use only for compiler magic
|
// TODO: remove this for actual methods, use only for compiler magic
|
||||||
|
@ -1715,7 +1715,7 @@ pub fn (mut c Checker) method_call(mut call_expr ast.CallExpr) ast.Type {
|
||||||
}
|
}
|
||||||
if method.generic_names.len != call_expr.generic_types.len {
|
if method.generic_names.len != call_expr.generic_types.len {
|
||||||
// no type arguments given in call, attempt implicit instantiation
|
// no type arguments given in call, attempt implicit instantiation
|
||||||
c.infer_fn_types(method, mut call_expr)
|
c.infer_fn_generic_types(method, mut call_expr)
|
||||||
}
|
}
|
||||||
if call_expr.generic_types.len > 0 && method.return_type != 0 {
|
if call_expr.generic_types.len > 0 && method.return_type != 0 {
|
||||||
if typ := c.table.resolve_generic_by_names(method.return_type, method.generic_names,
|
if typ := c.table.resolve_generic_by_names(method.return_type, method.generic_names,
|
||||||
|
@ -1937,9 +1937,9 @@ pub fn (mut c Checker) fn_call(mut call_expr ast.CallExpr) ast.Type {
|
||||||
if has_generic_generic {
|
if has_generic_generic {
|
||||||
if c.mod != '' {
|
if c.mod != '' {
|
||||||
// Need to prepend the module when adding a generic type to a function
|
// Need to prepend the module when adding a generic type to a function
|
||||||
c.table.register_fn_gen_type(c.mod + '.' + fn_name, generic_types)
|
c.table.register_fn_generic_types(c.mod + '.' + fn_name, generic_types)
|
||||||
} else {
|
} else {
|
||||||
c.table.register_fn_gen_type(fn_name, generic_types)
|
c.table.register_fn_generic_types(fn_name, generic_types)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if fn_name == 'json.encode' {
|
if fn_name == 'json.encode' {
|
||||||
|
@ -2026,7 +2026,7 @@ pub fn (mut c Checker) fn_call(mut call_expr ast.CallExpr) ast.Type {
|
||||||
os_name := 'os.$fn_name'
|
os_name := 'os.$fn_name'
|
||||||
if f := c.table.find_fn(os_name) {
|
if f := c.table.find_fn(os_name) {
|
||||||
if f.generic_names.len == call_expr.generic_types.len {
|
if f.generic_names.len == call_expr.generic_types.len {
|
||||||
c.table.fn_gen_types[os_name] = c.table.fn_gen_types['${call_expr.mod}.$call_expr.name']
|
c.table.fn_generic_types[os_name] = c.table.fn_generic_types['${call_expr.mod}.$call_expr.name']
|
||||||
}
|
}
|
||||||
call_expr.name = os_name
|
call_expr.name = os_name
|
||||||
found = true
|
found = true
|
||||||
|
@ -2220,7 +2220,7 @@ pub fn (mut c Checker) fn_call(mut call_expr ast.CallExpr) ast.Type {
|
||||||
}
|
}
|
||||||
if func.generic_names.len != call_expr.generic_types.len {
|
if func.generic_names.len != call_expr.generic_types.len {
|
||||||
// no type arguments given in call, attempt implicit instantiation
|
// no type arguments given in call, attempt implicit instantiation
|
||||||
c.infer_fn_types(func, mut call_expr)
|
c.infer_fn_generic_types(func, mut call_expr)
|
||||||
}
|
}
|
||||||
if func.generic_names.len > 0 {
|
if func.generic_names.len > 0 {
|
||||||
for i, call_arg in call_expr.args {
|
for i, call_arg in call_expr.args {
|
||||||
|
@ -6326,13 +6326,13 @@ fn (mut c Checker) post_process_generic_fns() {
|
||||||
// Loop thru each generic function concrete type.
|
// Loop thru each generic function concrete type.
|
||||||
// Check each specific fn instantiation.
|
// Check each specific fn instantiation.
|
||||||
for i in 0 .. c.file.generic_fns.len {
|
for i in 0 .. c.file.generic_fns.len {
|
||||||
if c.table.fn_gen_types.len == 0 {
|
if c.table.fn_generic_types.len == 0 {
|
||||||
// no concrete types, so just skip:
|
// no concrete types, so just skip:
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
mut node := c.file.generic_fns[i]
|
mut node := c.file.generic_fns[i]
|
||||||
c.mod = node.mod
|
c.mod = node.mod
|
||||||
for gen_types in c.table.fn_gen_types[node.name] {
|
for gen_types in c.table.fn_generic_types[node.name] {
|
||||||
c.cur_generic_types = gen_types
|
c.cur_generic_types = gen_types
|
||||||
c.fn_decl(mut node)
|
c.fn_decl(mut node)
|
||||||
if node.name in ['vweb.run_app', 'vweb.run'] {
|
if node.name in ['vweb.run_app', 'vweb.run'] {
|
||||||
|
@ -6350,7 +6350,7 @@ fn (mut c Checker) fn_decl(mut node ast.FnDecl) {
|
||||||
// It will be processed later in c.post_process_generic_fns,
|
// It will be processed later in c.post_process_generic_fns,
|
||||||
// after all other normal functions are processed.
|
// after all other normal functions are processed.
|
||||||
// This is done so that all generic function calls can
|
// This is done so that all generic function calls can
|
||||||
// have a chance to populate c.table.fn_gen_types with
|
// have a chance to populate c.table.fn_generic_types with
|
||||||
// the correct concrete types.
|
// the correct concrete types.
|
||||||
c.file.generic_fns << node
|
c.file.generic_fns << node
|
||||||
return
|
return
|
||||||
|
|
|
@ -129,7 +129,7 @@ fn (mut g Gen) gen_fn_decl(node ast.FnDecl, skip bool) {
|
||||||
// }
|
// }
|
||||||
if node.generic_names.len > 0 && g.cur_generic_types.len == 0 { // need the cur_generic_type check to avoid inf. recursion
|
if node.generic_names.len > 0 && g.cur_generic_types.len == 0 { // need the cur_generic_type check to avoid inf. recursion
|
||||||
// loop thru each generic type and generate a function
|
// loop thru each generic type and generate a function
|
||||||
for gen_types in g.table.fn_gen_types[node.name] {
|
for gen_types in g.table.fn_generic_types[node.name] {
|
||||||
if g.pref.is_verbose {
|
if g.pref.is_verbose {
|
||||||
syms := gen_types.map(g.table.get_type_symbol(it))
|
syms := gen_types.map(g.table.get_type_symbol(it))
|
||||||
the_type := syms.map(node.name).join(', ')
|
the_type := syms.map(node.name).join(', ')
|
||||||
|
|
|
@ -46,7 +46,7 @@ pub fn (mut p Parser) call_expr(language ast.Language, mod string) ast.CallExpr
|
||||||
has_generic_generic := generic_types.filter(it.has_flag(.generic)).len > 0
|
has_generic_generic := generic_types.filter(it.has_flag(.generic)).len > 0
|
||||||
if !has_generic_generic {
|
if !has_generic_generic {
|
||||||
// will be added in checker
|
// will be added in checker
|
||||||
p.table.register_fn_gen_type(full_generic_fn_name, generic_types)
|
p.table.register_fn_generic_types(full_generic_fn_name, generic_types)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
p.check(.lpar)
|
p.check(.lpar)
|
||||||
|
|
|
@ -2248,7 +2248,7 @@ fn (mut p Parser) dot_expr(left ast.Expr) ast.Expr {
|
||||||
has_generic_generic := generic_types.filter(it.has_flag(.generic)).len > 0
|
has_generic_generic := generic_types.filter(it.has_flag(.generic)).len > 0
|
||||||
if !has_generic_generic {
|
if !has_generic_generic {
|
||||||
// will be added in checker
|
// will be added in checker
|
||||||
p.table.register_fn_gen_type(field_name, generic_types)
|
p.table.register_fn_generic_types(field_name, generic_types)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if p.tok.kind == .lpar {
|
if p.tok.kind == .lpar {
|
||||||
|
|
Loading…
Reference in New Issue