gen: fix generic variadic (#9333)
parent
a08e673581
commit
4b6244c9c1
|
@ -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
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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{
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
[inline]
|
||||
|
|
|
@ -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>() {
|
||||
|
|
Loading…
Reference in New Issue