1
0
mirror of https://github.com/vlang/v.git synced 2023-08-10 21:13:21 +03:00

ast, cgen: implement sumtype with fntype partly (related #15557) (#15567)

This commit is contained in:
yuyi 2022-08-28 14:12:08 +08:00 committed by GitHub
parent d75c62b806
commit 06e153d429
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 34 additions and 3 deletions

View File

@ -1195,7 +1195,7 @@ pub fn (mut t Table) find_or_register_fn_type(f Fn, is_anon bool, has_decl bool)
cname := if f.name.len == 0 {
'anon_fn_${t.fn_type_signature(f)}'
} else {
util.no_dots(f.name.clone())
util.no_dots(f.name.clone()).replace_each([' ', '', '(', '_', ')', ''])
}
anon := f.name.len == 0 || is_anon
existing_idx := t.type_idxs[name]
@ -1295,6 +1295,9 @@ pub fn (t &Table) sumtype_has_variant(parent Type, variant Type, is_as bool) boo
.alias {
return t.sumtype_check_alias_variant(parent, variant, is_as)
}
.function {
return t.sumtype_check_function_variant(parent_info, variant, is_as)
}
else {
return t.sumtype_check_variant_in_type(parent_info, variant, is_as)
}
@ -1303,6 +1306,15 @@ pub fn (t &Table) sumtype_has_variant(parent Type, variant Type, is_as bool) boo
return false
}
fn (t &Table) sumtype_check_function_variant(parent_info SumType, variant Type, is_as bool) bool {
for v in parent_info.variants {
if '$v.idx' == '$variant.idx' && (!is_as || v.nr_muls() == variant.nr_muls()) {
return true
}
}
return false
}
fn (t &Table) sumtype_check_variant_in_type(parent_info SumType, variant Type, is_as bool) bool {
for v in parent_info.variants {
if v.idx() == variant.idx() && (!is_as || v.nr_muls() == variant.nr_muls()) {

View File

@ -2102,7 +2102,12 @@ fn (mut g Gen) get_sumtype_casting_fn(got_ ast.Type, exp_ ast.Type) string {
fn (mut g Gen) write_sumtype_casting_fn(fun SumtypeCastingFn) {
got, exp := fun.got, fun.exp
got_sym, exp_sym := g.table.sym(got), g.table.sym(exp)
got_cname, exp_cname := got_sym.cname, exp_sym.cname
mut got_cname, exp_cname := got_sym.cname, exp_sym.cname
if got_sym.info is ast.FnType {
if got_sym.info.is_anon {
got_cname = 'anon_fn_${g.table.fn_type_signature(got_sym.info.func)}'
}
}
mut sb := strings.new_builder(128)
sb.writeln('static inline $exp_cname ${fun.fn_name}($got_cname* x) {')
sb.writeln('\t$got_cname* ptr = memdup(x, sizeof($got_cname));')
@ -2231,7 +2236,12 @@ fn (mut g Gen) expr_with_cast(expr ast.Expr, got_type_raw ast.Type, expected_typ
}
// cast to sum type
exp_styp := g.typ(expected_type)
got_styp := g.typ(got_type)
mut got_styp := g.typ(got_type)
if got_sym.info is ast.FnType {
if got_sym.info.is_anon {
got_styp = 'anon_fn_${g.table.fn_type_signature(got_sym.info.func)}'
}
}
if expected_type != ast.void_type {
unwrapped_expected_type := g.unwrap_generic(expected_type)
unwrapped_exp_sym := g.table.sym(unwrapped_expected_type)

View File

@ -0,0 +1 @@
Fns

View File

@ -0,0 +1,8 @@
type Fns = bool | fn (int) int
fn main() {
f := Fns(fn (a int) int {
return a
})
println(typeof(f).name)
}