gen: fix generic variadic (#9333)

pull/9343/head
Enzo 2021-03-16 23:18:43 +01:00 committed by GitHub
parent a08e673581
commit 4b6244c9c1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 60 additions and 54 deletions

View File

@ -1550,12 +1550,6 @@ pub fn ex2fe(x Expr) table.FExpr {
return res
}
// experimental ast.Table
pub struct Table {
// pub mut:
// main_fn_decl_node FnDecl
}
// helper for dealing with `m[k1][k2][k3][k3] = value`
pub fn (mut lx IndexExpr) recursive_mapset_is_setter(val bool) {
lx.is_setter = val

View File

@ -464,6 +464,9 @@ pub fn (mut c Checker) infer_fn_types(f table.Fn, mut call_expr ast.CallExpr) {
}
}
break
} else if param.typ.has_flag(.variadic) {
typ = c.table.mktyp(arg.typ)
break
}
}
if typ == table.void_type {

View File

@ -1975,7 +1975,6 @@ pub fn (mut c Checker) call_fn(mut call_expr ast.CallExpr) table.Type {
c.warn('`error($arg)` can be shortened to just `$arg`', call_expr.pos)
}
}
// TODO: typ optimize.. this node can get processed more than once
if call_expr.expected_arg_types.len == 0 {
for param in f.params {

View File

@ -495,7 +495,6 @@ fn (mut g Gen) method_call(node ast.CallExpr) {
g.write('${dot}_object')
if node.args.len > 0 {
g.write(', ')
// g.call_args(node.args, node.expected_arg_types) // , [])
g.call_args(node)
}
g.write(')')
@ -701,7 +700,6 @@ fn (mut g Gen) method_call(node ast.CallExpr) {
}
*/
// ///////
// g.call_args(node.args, node.expected_arg_types) // , [])
g.call_args(node)
g.write(')')
}
@ -740,7 +738,6 @@ fn (mut g Gen) fn_call(node ast.CallExpr) {
encode_name := js_enc_name(json_type_str)
g.writeln('// json.encode')
g.write('cJSON* $json_obj = ${encode_name}(')
// g.call_args(node.args, node.expected_arg_types) // , [])
if node.args[0].typ.is_ptr() {
g.write('*')
}
@ -762,7 +759,6 @@ fn (mut g Gen) fn_call(node ast.CallExpr) {
g.write('cJSON* $json_obj = json__json_parse(')
// Skip the first argument in json.decode which is a type
// its name was already used to generate the function call
// g.call_args(node.args[1..], node.expected_arg_types) // , [])
g.is_js_call = true
g.call_args(node)
g.is_js_call = false
@ -837,7 +833,6 @@ fn (mut g Gen) fn_call(node ast.CallExpr) {
if g.pref.is_debug && node.name == 'panic' {
paline, pafile, pamod, pafn := g.panic_debug_info(node.pos)
g.write('panic_debug($paline, tos3("$pafile"), tos3("$pamod"), tos3("$pafn"), ')
// g.call_args(node.args, node.expected_arg_types) // , [])
g.call_args(node)
g.write(')')
} else {
@ -850,7 +845,6 @@ fn (mut g Gen) fn_call(node ast.CallExpr) {
if g.is_json_fn {
g.write(json_obj)
} else {
// g.call_args(node.args, node.expected_arg_types) // , tmp_arg_vars_to_free)
g.call_args(node)
}
g.write(')')
@ -935,17 +929,13 @@ fn (mut g Gen) autofree_call_pregen(node ast.CallExpr) {
}
fn (mut g Gen) autofree_call_postgen(node_pos int) {
/*
if g.strs_to_free.len == 0 {
return
}
*/
/*
g.writeln('\n/* strs_to_free3: $g.nr_vars_to_free */')
if g.nr_vars_to_free <= 0 {
return
}
*/
// if g.strs_to_free.len == 0 {
// return
// }
// g.writeln('\n/* strs_to_free3: $g.nr_vars_to_free */')
// if g.nr_vars_to_free <= 0 {
// return
// }
/*
for s in g.strs_to_free {
g.writeln('string_free(&$s);')
@ -996,8 +986,8 @@ fn (mut g Gen) call_args(node ast.CallExpr) {
args := if g.is_js_call { node.args[1..] } else { node.args }
expected_types := node.expected_arg_types
// only v variadic, C variadic args will be appeneded like normal args
is_variadic := expected_types.len > 0
&& expected_types[expected_types.len - 1].has_flag(.variadic) && node.language == .v
is_variadic := expected_types.len > 0 && expected_types.last().has_flag(.variadic)
&& node.language == .v
for i, arg in args {
if is_variadic && i == expected_types.len - 1 {
break
@ -1039,10 +1029,23 @@ fn (mut g Gen) call_args(node ast.CallExpr) {
}
arg_nr := expected_types.len - 1
if is_variadic {
varg_type := expected_types[expected_types.len - 1]
varg_type := expected_types.last()
variadic_count := args.len - arg_nr
arr_sym := g.table.get_type_symbol(varg_type)
arr_info := arr_sym.info as table.Array
mut arr_info := arr_sym.info as table.Array
if varg_type.has_flag(.generic) {
if fn_def := g.table.find_fn(node.name) {
varg_type_name := g.table.type_to_str(varg_type)
for i, fn_gen_name in fn_def.generic_names {
if fn_gen_name == varg_type_name {
arr_info.elem_type = node.generic_types[i]
break
}
}
} else {
g.error('unable to find function $node.name', node.pos)
}
}
elem_type := g.typ(arr_info.elem_type)
if args.len > 0 && args[args.len - 1].expr is ast.ArrayDecompose {
g.expr(args[args.len - 1].expr)

View File

@ -320,7 +320,6 @@ fn (mut p Parser) fn_decl() ast.FnDecl {
scope: 0
}
}
// p.warn('reg method $type_sym.name . $name ()')
type_sym_method_idx = type_sym.register_method(table.Fn{
name: name
params: params
@ -349,7 +348,6 @@ fn (mut p Parser) fn_decl() ast.FnDecl {
if !p.pref.translated && language == .v && name in p.table.fns {
p.table.redefined_fns << name
}
// p.warn('reg functn $name ()')
p.table.register_fn(table.Fn{
name: name
params: params
@ -644,7 +642,6 @@ fn (mut p Parser) fn_args() ([]table.Param, bool, bool) {
|| p.peek_tok.kind == .dot || p.peek_tok.kind == .rpar
// TODO copy pasta, merge 2 branches
if types_only {
// p.warn('types only')
mut arg_no := 1
for p.tok.kind != .rpar {
if p.tok.kind == .eof {
@ -789,7 +786,7 @@ fn (mut p Parser) fn_args() ([]table.Param, bool, bool) {
}
}
if is_variadic {
typ = table.new_type(p.table.find_or_register_array(typ)).set_flag(.variadic)
typ = table.new_type(p.table.find_or_register_array(typ)).derive(typ).set_flag(.variadic)
}
for i, arg_name in arg_names {
args << table.Param{

View File

@ -854,13 +854,13 @@ pub fn (t &Table) mktyp(typ Type) Type {
}
}
pub fn (mut mytable Table) register_fn_gen_type(fn_name string, types []Type) {
mut a := mytable.fn_gen_types[fn_name]
pub fn (mut t Table) register_fn_gen_type(fn_name string, types []Type) {
mut a := t.fn_gen_types[fn_name]
if types in a {
return
}
a << types
mytable.fn_gen_types[fn_name] = a
t.fn_gen_types[fn_name] = a
}
// TODO: there is a bug when casting sumtype the other way if its pointer

View File

@ -425,11 +425,7 @@ pub enum Kind {
}
pub fn (t &TypeSymbol) str() string {
if t.kind in [.array, .array_fixed] {
return t.name.replace('array_', '[]')
} else {
return t.name
}
return t.name
}
[inline]

View File

@ -1,20 +1,9 @@
import simplemodule
fn test_todo() {
}
fn simple<T>(p T) T {
return p
}
fn plus<T>(xxx T, b T) T {
// x := a
// y := b
// ww := ww
// q := xx + 1
return xxx + b
}
fn test_identity() {
assert simple<int>(1) == 1
assert simple<int>(1 + 0) == 1
@ -27,7 +16,15 @@ fn test_identity() {
assert simple<simplemodule.Data>(simplemodule.Data{value: 0}).value == 0
}
fn test_plus() {
fn plus<T>(xxx T, b T) T {
// x := a
// y := b
// ww := ww
// q := xx + 1
return xxx + b
}
fn test_infix_expr() {
a := plus<int>(2, 3)
assert a == 5
assert plus<int>(10, 1) == 11
@ -42,9 +39,26 @@ fn sum<T>(l []T) T {
return r
}
fn test_foo() {
fn test_array() {
b := [1, 2, 3]
assert sum<int>(b) == 6
assert sum(b) == 6
}
fn max<T>(brug string, a ...T) T {
mut max := a[0]
for item in a[1..] {
if max < item {
max = item
}
}
return max
}
fn test_generic_variadic() {
assert max('krkr', 1, 2, 3, 4) == 4
a := [f64(1.2), 3.2, 0.1, 2.2]
assert max('krkr', ...a) == 3.2
assert max('krkr', ...[byte(4), 3, 2, 1]) == 4
}
fn create<T>() {