gen: fix generic variadic (#9333)
parent
a08e673581
commit
4b6244c9c1
|
@ -1550,12 +1550,6 @@ pub fn ex2fe(x Expr) table.FExpr {
|
||||||
return res
|
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`
|
// helper for dealing with `m[k1][k2][k3][k3] = value`
|
||||||
pub fn (mut lx IndexExpr) recursive_mapset_is_setter(val bool) {
|
pub fn (mut lx IndexExpr) recursive_mapset_is_setter(val bool) {
|
||||||
lx.is_setter = val
|
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
|
break
|
||||||
|
} else if param.typ.has_flag(.variadic) {
|
||||||
|
typ = c.table.mktyp(arg.typ)
|
||||||
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if typ == table.void_type {
|
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)
|
c.warn('`error($arg)` can be shortened to just `$arg`', call_expr.pos)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: typ optimize.. this node can get processed more than once
|
// TODO: typ optimize.. this node can get processed more than once
|
||||||
if call_expr.expected_arg_types.len == 0 {
|
if call_expr.expected_arg_types.len == 0 {
|
||||||
for param in f.params {
|
for param in f.params {
|
||||||
|
|
|
@ -495,7 +495,6 @@ fn (mut g Gen) method_call(node ast.CallExpr) {
|
||||||
g.write('${dot}_object')
|
g.write('${dot}_object')
|
||||||
if node.args.len > 0 {
|
if node.args.len > 0 {
|
||||||
g.write(', ')
|
g.write(', ')
|
||||||
// g.call_args(node.args, node.expected_arg_types) // , [])
|
|
||||||
g.call_args(node)
|
g.call_args(node)
|
||||||
}
|
}
|
||||||
g.write(')')
|
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.call_args(node)
|
||||||
g.write(')')
|
g.write(')')
|
||||||
}
|
}
|
||||||
|
@ -740,7 +738,6 @@ fn (mut g Gen) fn_call(node ast.CallExpr) {
|
||||||
encode_name := js_enc_name(json_type_str)
|
encode_name := js_enc_name(json_type_str)
|
||||||
g.writeln('// json.encode')
|
g.writeln('// json.encode')
|
||||||
g.write('cJSON* $json_obj = ${encode_name}(')
|
g.write('cJSON* $json_obj = ${encode_name}(')
|
||||||
// g.call_args(node.args, node.expected_arg_types) // , [])
|
|
||||||
if node.args[0].typ.is_ptr() {
|
if node.args[0].typ.is_ptr() {
|
||||||
g.write('*')
|
g.write('*')
|
||||||
}
|
}
|
||||||
|
@ -762,7 +759,6 @@ fn (mut g Gen) fn_call(node ast.CallExpr) {
|
||||||
g.write('cJSON* $json_obj = json__json_parse(')
|
g.write('cJSON* $json_obj = json__json_parse(')
|
||||||
// Skip the first argument in json.decode which is a type
|
// Skip the first argument in json.decode which is a type
|
||||||
// its name was already used to generate the function call
|
// 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.is_js_call = true
|
||||||
g.call_args(node)
|
g.call_args(node)
|
||||||
g.is_js_call = false
|
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' {
|
if g.pref.is_debug && node.name == 'panic' {
|
||||||
paline, pafile, pamod, pafn := g.panic_debug_info(node.pos)
|
paline, pafile, pamod, pafn := g.panic_debug_info(node.pos)
|
||||||
g.write('panic_debug($paline, tos3("$pafile"), tos3("$pamod"), tos3("$pafn"), ')
|
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.call_args(node)
|
||||||
g.write(')')
|
g.write(')')
|
||||||
} else {
|
} else {
|
||||||
|
@ -850,7 +845,6 @@ fn (mut g Gen) fn_call(node ast.CallExpr) {
|
||||||
if g.is_json_fn {
|
if g.is_json_fn {
|
||||||
g.write(json_obj)
|
g.write(json_obj)
|
||||||
} else {
|
} else {
|
||||||
// g.call_args(node.args, node.expected_arg_types) // , tmp_arg_vars_to_free)
|
|
||||||
g.call_args(node)
|
g.call_args(node)
|
||||||
}
|
}
|
||||||
g.write(')')
|
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) {
|
fn (mut g Gen) autofree_call_postgen(node_pos int) {
|
||||||
/*
|
// if g.strs_to_free.len == 0 {
|
||||||
if g.strs_to_free.len == 0 {
|
// return
|
||||||
return
|
// }
|
||||||
}
|
// g.writeln('\n/* strs_to_free3: $g.nr_vars_to_free */')
|
||||||
*/
|
// if g.nr_vars_to_free <= 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 {
|
for s in g.strs_to_free {
|
||||||
g.writeln('string_free(&$s);')
|
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 }
|
args := if g.is_js_call { node.args[1..] } else { node.args }
|
||||||
expected_types := node.expected_arg_types
|
expected_types := node.expected_arg_types
|
||||||
// only v variadic, C variadic args will be appeneded like normal args
|
// only v variadic, C variadic args will be appeneded like normal args
|
||||||
is_variadic := expected_types.len > 0
|
is_variadic := expected_types.len > 0 && expected_types.last().has_flag(.variadic)
|
||||||
&& expected_types[expected_types.len - 1].has_flag(.variadic) && node.language == .v
|
&& node.language == .v
|
||||||
for i, arg in args {
|
for i, arg in args {
|
||||||
if is_variadic && i == expected_types.len - 1 {
|
if is_variadic && i == expected_types.len - 1 {
|
||||||
break
|
break
|
||||||
|
@ -1039,10 +1029,23 @@ fn (mut g Gen) call_args(node ast.CallExpr) {
|
||||||
}
|
}
|
||||||
arg_nr := expected_types.len - 1
|
arg_nr := expected_types.len - 1
|
||||||
if is_variadic {
|
if is_variadic {
|
||||||
varg_type := expected_types[expected_types.len - 1]
|
varg_type := expected_types.last()
|
||||||
variadic_count := args.len - arg_nr
|
variadic_count := args.len - arg_nr
|
||||||
arr_sym := g.table.get_type_symbol(varg_type)
|
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)
|
elem_type := g.typ(arr_info.elem_type)
|
||||||
if args.len > 0 && args[args.len - 1].expr is ast.ArrayDecompose {
|
if args.len > 0 && args[args.len - 1].expr is ast.ArrayDecompose {
|
||||||
g.expr(args[args.len - 1].expr)
|
g.expr(args[args.len - 1].expr)
|
||||||
|
|
|
@ -320,7 +320,6 @@ fn (mut p Parser) fn_decl() ast.FnDecl {
|
||||||
scope: 0
|
scope: 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// p.warn('reg method $type_sym.name . $name ()')
|
|
||||||
type_sym_method_idx = type_sym.register_method(table.Fn{
|
type_sym_method_idx = type_sym.register_method(table.Fn{
|
||||||
name: name
|
name: name
|
||||||
params: params
|
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 {
|
if !p.pref.translated && language == .v && name in p.table.fns {
|
||||||
p.table.redefined_fns << name
|
p.table.redefined_fns << name
|
||||||
}
|
}
|
||||||
// p.warn('reg functn $name ()')
|
|
||||||
p.table.register_fn(table.Fn{
|
p.table.register_fn(table.Fn{
|
||||||
name: name
|
name: name
|
||||||
params: params
|
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
|
|| p.peek_tok.kind == .dot || p.peek_tok.kind == .rpar
|
||||||
// TODO copy pasta, merge 2 branches
|
// TODO copy pasta, merge 2 branches
|
||||||
if types_only {
|
if types_only {
|
||||||
// p.warn('types only')
|
|
||||||
mut arg_no := 1
|
mut arg_no := 1
|
||||||
for p.tok.kind != .rpar {
|
for p.tok.kind != .rpar {
|
||||||
if p.tok.kind == .eof {
|
if p.tok.kind == .eof {
|
||||||
|
@ -789,7 +786,7 @@ fn (mut p Parser) fn_args() ([]table.Param, bool, bool) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if is_variadic {
|
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 {
|
for i, arg_name in arg_names {
|
||||||
args << table.Param{
|
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) {
|
pub fn (mut t Table) register_fn_gen_type(fn_name string, types []Type) {
|
||||||
mut a := mytable.fn_gen_types[fn_name]
|
mut a := t.fn_gen_types[fn_name]
|
||||||
if types in a {
|
if types in a {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
a << types
|
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
|
// 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 {
|
pub fn (t &TypeSymbol) str() string {
|
||||||
if t.kind in [.array, .array_fixed] {
|
return t.name
|
||||||
return t.name.replace('array_', '[]')
|
|
||||||
} else {
|
|
||||||
return t.name
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[inline]
|
[inline]
|
||||||
|
|
|
@ -1,20 +1,9 @@
|
||||||
import simplemodule
|
import simplemodule
|
||||||
|
|
||||||
fn test_todo() {
|
|
||||||
}
|
|
||||||
|
|
||||||
fn simple<T>(p T) T {
|
fn simple<T>(p T) T {
|
||||||
return p
|
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() {
|
fn test_identity() {
|
||||||
assert simple<int>(1) == 1
|
assert simple<int>(1) == 1
|
||||||
assert simple<int>(1 + 0) == 1
|
assert simple<int>(1 + 0) == 1
|
||||||
|
@ -27,7 +16,15 @@ fn test_identity() {
|
||||||
assert simple<simplemodule.Data>(simplemodule.Data{value: 0}).value == 0
|
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)
|
a := plus<int>(2, 3)
|
||||||
assert a == 5
|
assert a == 5
|
||||||
assert plus<int>(10, 1) == 11
|
assert plus<int>(10, 1) == 11
|
||||||
|
@ -42,9 +39,26 @@ fn sum<T>(l []T) T {
|
||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_foo() {
|
fn test_array() {
|
||||||
b := [1, 2, 3]
|
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>() {
|
fn create<T>() {
|
||||||
|
|
Loading…
Reference in New Issue