v: simplify handling of function generic parameters (#9673)
parent
78c6e35bde
commit
a2a18ef92c
|
@ -373,7 +373,7 @@ pub:
|
|||
is_builtin bool // this function is defined in builtin/strconv
|
||||
body_pos token.Position // function bodys position
|
||||
file string
|
||||
generic_params []GenericParam
|
||||
generic_names []string
|
||||
is_direct_arr bool // direct array access
|
||||
attrs []Attr
|
||||
skip_gen bool // this function doesn't need to be generated (for example [if foo])
|
||||
|
@ -391,11 +391,6 @@ pub mut:
|
|||
pos token.Position // function declaration position
|
||||
}
|
||||
|
||||
pub struct GenericParam {
|
||||
pub:
|
||||
name string
|
||||
}
|
||||
|
||||
// break, continue
|
||||
pub struct BranchStmt {
|
||||
pub:
|
||||
|
|
|
@ -62,11 +62,11 @@ pub fn (node &FnDecl) stringify(t &Table, cur_mod string, m2a map[string]string)
|
|||
if name in ['+', '-', '*', '/', '%', '<', '>', '==', '!=', '>=', '<='] {
|
||||
f.write_string(' ')
|
||||
}
|
||||
if node.generic_params.len > 0 {
|
||||
if node.generic_names.len > 0 {
|
||||
f.write_string('<')
|
||||
for i, param in node.generic_params {
|
||||
is_last := i == node.generic_params.len - 1
|
||||
f.write_string(param.name)
|
||||
for i, gname in node.generic_names {
|
||||
is_last := i == node.generic_names.len - 1
|
||||
f.write_string(gname)
|
||||
if !is_last {
|
||||
f.write_string(', ')
|
||||
}
|
||||
|
|
|
@ -360,7 +360,7 @@ pub fn (mut c Checker) symmetric_check(left ast.Type, right ast.Type) bool {
|
|||
return c.check_basic(left, right)
|
||||
}
|
||||
|
||||
pub fn (c &Checker) get_default_fmt(ftyp ast.Type, typ ast.Type) byte {
|
||||
pub fn (mut c Checker) get_default_fmt(ftyp ast.Type, typ ast.Type) byte {
|
||||
if ftyp.has_flag(.optional) {
|
||||
return `s`
|
||||
} else if typ.is_float() {
|
||||
|
@ -521,7 +521,7 @@ pub fn (mut c Checker) infer_fn_types(f ast.Fn, mut call_expr ast.CallExpr) {
|
|||
mut param_elem_sym := c.table.get_type_symbol(param_elem_info.elem_type)
|
||||
for {
|
||||
if arg_elem_sym.kind == .array && param_elem_sym.kind == .array
|
||||
&& c.cur_fn.generic_params.filter(it.name == param_elem_sym.name).len == 0 {
|
||||
&& param_elem_sym.name !in c.cur_fn.generic_names {
|
||||
arg_elem_info = arg_elem_sym.info as ast.Array
|
||||
arg_elem_sym = c.table.get_type_symbol(arg_elem_info.elem_type)
|
||||
param_elem_info = param_elem_sym.info as ast.Array
|
||||
|
|
|
@ -514,7 +514,7 @@ pub fn (mut c Checker) struct_init(mut struct_init ast.StructInit) ast.Type {
|
|||
struct_init.pos)
|
||||
}
|
||||
}
|
||||
if type_sym.name.len == 1 && c.cur_fn.generic_params.len == 0 {
|
||||
if type_sym.name.len == 1 && c.cur_fn.generic_names.len == 0 {
|
||||
c.error('unknown struct `$type_sym.name`', struct_init.pos)
|
||||
return 0
|
||||
}
|
||||
|
@ -2495,8 +2495,7 @@ pub fn (mut c Checker) selector_expr(mut selector_expr ast.SelectorExpr) ast.Typ
|
|||
match mut selector_expr.expr {
|
||||
ast.Ident {
|
||||
name := selector_expr.expr.name
|
||||
valid_generic := util.is_generic_type_name(name)
|
||||
&& c.cur_fn.generic_params.filter(it.name == name).len != 0
|
||||
valid_generic := util.is_generic_type_name(name) && name in c.cur_fn.generic_names
|
||||
if valid_generic {
|
||||
name_type = ast.Type(c.table.find_type_idx(name)).set_flag(.generic)
|
||||
}
|
||||
|
@ -4051,13 +4050,10 @@ fn (mut c Checker) stmts(stmts []ast.Stmt) {
|
|||
c.expected_type = ast.void_type
|
||||
}
|
||||
|
||||
pub fn (c &Checker) unwrap_generic(typ ast.Type) ast.Type {
|
||||
pub fn (mut c Checker) unwrap_generic(typ ast.Type) ast.Type {
|
||||
if typ.has_flag(.generic) {
|
||||
sym := c.table.get_type_symbol(typ)
|
||||
for i, generic_param in c.cur_fn.generic_params {
|
||||
if generic_param.name == sym.name {
|
||||
return c.cur_generic_types[i].derive(typ).clear_flag(.generic)
|
||||
}
|
||||
if t_typ := c.table.resolve_generic_by_names(typ, c.cur_fn.generic_names, c.cur_generic_types) {
|
||||
return t_typ
|
||||
}
|
||||
}
|
||||
return typ
|
||||
|
@ -6332,7 +6328,7 @@ fn (mut c Checker) post_process_generic_fns() {
|
|||
|
||||
fn (mut c Checker) fn_decl(mut node ast.FnDecl) {
|
||||
c.returns = false
|
||||
if node.generic_params.len > 0 && c.cur_generic_types.len == 0 {
|
||||
if node.generic_names.len > 0 && c.cur_generic_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.
|
||||
|
|
|
@ -687,7 +687,7 @@ static inline Option_void __Option_${styp}_pushval($styp ch, $el_type e) {
|
|||
}
|
||||
|
||||
// cc_type whether to prefix 'struct' or not (C__Foo -> struct Foo)
|
||||
fn (g &Gen) cc_type(typ ast.Type, is_prefix_struct bool) string {
|
||||
fn (mut g Gen) cc_type(typ ast.Type, is_prefix_struct bool) string {
|
||||
sym := g.table.get_type_symbol(g.unwrap_generic(typ))
|
||||
mut styp := sym.cname
|
||||
// TODO: this needs to be removed; cgen shouldn't resolve generic types (job of checker)
|
||||
|
|
|
@ -64,7 +64,7 @@ fn (mut g Gen) process_fn_decl(node ast.FnDecl) {
|
|||
// We are using prebuilt modules, we do not need to generate
|
||||
// their functions in main.c.
|
||||
if node.mod != 'main' && node.mod != 'help' && !should_bundle_module && !g.pref.is_test
|
||||
&& node.generic_params.len == 0 {
|
||||
&& node.generic_names.len == 0 {
|
||||
skip = true
|
||||
}
|
||||
}
|
||||
|
@ -127,7 +127,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_params.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
|
||||
for gen_types in g.table.fn_gen_types[node.name] {
|
||||
if g.pref.is_verbose {
|
||||
|
@ -475,13 +475,10 @@ fn (mut g Gen) call_expr(node ast.CallExpr) {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn (g &Gen) unwrap_generic(typ ast.Type) ast.Type {
|
||||
pub fn (mut g Gen) unwrap_generic(typ ast.Type) ast.Type {
|
||||
if typ.has_flag(.generic) {
|
||||
sym := g.table.get_type_symbol(typ)
|
||||
for i, generic_param in g.cur_fn.generic_params {
|
||||
if generic_param.name == sym.name {
|
||||
return g.cur_generic_types[i].derive(typ).clear_flag(.generic)
|
||||
}
|
||||
if t_typ := g.table.resolve_generic_by_names(typ, g.cur_fn.generic_names, g.cur_generic_types) {
|
||||
return t_typ
|
||||
}
|
||||
}
|
||||
return typ
|
||||
|
|
|
@ -274,7 +274,7 @@ fn (mut p Parser) fn_decl() ast.FnDecl {
|
|||
}
|
||||
}
|
||||
// <T>
|
||||
generic_params := p.parse_generic_params()
|
||||
generic_names := p.parse_generic_names()
|
||||
// Args
|
||||
args2, are_args_type_only, is_variadic := p.fn_args()
|
||||
params << args2
|
||||
|
@ -338,7 +338,7 @@ fn (mut p Parser) fn_decl() ast.FnDecl {
|
|||
params: params
|
||||
return_type: return_type
|
||||
is_variadic: is_variadic
|
||||
generic_names: generic_params.map(it.name)
|
||||
generic_names: generic_names
|
||||
is_pub: is_pub
|
||||
is_deprecated: is_deprecated
|
||||
is_unsafe: is_unsafe
|
||||
|
@ -367,7 +367,7 @@ fn (mut p Parser) fn_decl() ast.FnDecl {
|
|||
params: params
|
||||
return_type: return_type
|
||||
is_variadic: is_variadic
|
||||
generic_names: generic_params.map(it.name)
|
||||
generic_names: generic_names
|
||||
is_pub: is_pub
|
||||
is_deprecated: is_deprecated
|
||||
is_unsafe: is_unsafe
|
||||
|
@ -422,7 +422,7 @@ fn (mut p Parser) fn_decl() ast.FnDecl {
|
|||
name: rec.name
|
||||
typ: rec.typ
|
||||
}
|
||||
generic_params: generic_params
|
||||
generic_names: generic_names
|
||||
receiver_pos: rec.pos
|
||||
is_method: is_method
|
||||
method_type_pos: rec.type_pos
|
||||
|
@ -517,10 +517,10 @@ fn (mut p Parser) fn_receiver(mut params []ast.Param, mut rec ReceiverParsingInf
|
|||
return
|
||||
}
|
||||
|
||||
fn (mut p Parser) parse_generic_params() []ast.GenericParam {
|
||||
fn (mut p Parser) parse_generic_names() []string {
|
||||
mut param_names := []string{}
|
||||
if p.tok.kind != .lt {
|
||||
return []ast.GenericParam{}
|
||||
return param_names
|
||||
}
|
||||
p.check(.lt)
|
||||
mut first_done := false
|
||||
|
@ -551,7 +551,7 @@ fn (mut p Parser) parse_generic_params() []ast.GenericParam {
|
|||
count++
|
||||
}
|
||||
p.check(.gt)
|
||||
return param_names.map(ast.GenericParam{it})
|
||||
return param_names
|
||||
}
|
||||
|
||||
// is_generic_name returns true if the current token is a generic name.
|
||||
|
|
Loading…
Reference in New Issue