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

cgen, checker: fix dump() to return option values (#17563)

This commit is contained in:
Felipe Pena 2023-03-09 15:29:25 -03:00 committed by GitHub
parent 71c3b66ecf
commit 32d09544d7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 78 additions and 15 deletions

View File

@ -312,6 +312,13 @@ fn (mut c Checker) assign_stmt(mut node ast.AssignStmt) {
if right is ast.ComptimeSelector {
left.obj.is_comptime_field = true
left.obj.typ = c.comptime_fields_default_type
} else if right is ast.Ident
&& (right as ast.Ident).obj is ast.Var && (right as ast.Ident).or_expr.kind == .absent {
left.obj.is_comptime_field = ((right as ast.Ident).obj as ast.Var).is_comptime_field
} else if right is ast.DumpExpr
&& (right as ast.DumpExpr).expr is ast.ComptimeSelector {
left.obj.is_comptime_field = true
left.obj.typ = c.comptime_fields_default_type
}
}
ast.GlobalField {

View File

@ -2473,6 +2473,10 @@ pub fn (mut c Checker) expr(node_ ast.Expr) ast.Type {
ast.DumpExpr {
c.expected_type = ast.string_type
node.expr_type = c.expr(node.expr)
if node.expr is ast.Ident && c.is_comptime_var(node.expr) {
node.expr_type = c.comptime_fields_default_type
}
c.check_expr_opt_call(node.expr, node.expr_type)
etidx := node.expr_type.idx()
if etidx == ast.void_type_idx {
@ -2486,8 +2490,13 @@ pub fn (mut c Checker) expr(node_ ast.Expr) ast.Type {
unwrapped_expr_type := c.unwrap_generic(node.expr_type)
tsym := c.table.sym(unwrapped_expr_type)
c.table.dumps[int(unwrapped_expr_type.clear_flag(.option).clear_flag(.result))] = tsym.cname
node.cname = tsym.cname
type_cname := if node.expr_type.has_flag(.option) {
'_option_${tsym.cname}'
} else {
tsym.cname
}
c.table.dumps[int(unwrapped_expr_type.clear_flag(.result))] = type_cname
node.cname = type_cname
return node.expr_type
}
ast.EnumVal {

View File

@ -1,7 +1,7 @@
[vlib/v/checker/tests/comptime_dump_fields_var_test.vv:13] val.$(field.name): c
[vlib/v/checker/tests/comptime_dump_fields_var_test.vv:13] val.$(field.name): d
[vlib/v/checker/tests/comptime_dump_fields_var_test.vv:13] val.$(field.name): Option('d')
[vlib/v/checker/tests/comptime_dump_fields_var_test.vv:13] val.$(field.name): 1
[vlib/v/checker/tests/comptime_dump_fields_var_test.vv:13] val.$(field.name): 0
[vlib/v/checker/tests/comptime_dump_fields_var_test.vv:13] val.$(field.name): Option(0)
[vlib/v/checker/tests/comptime_dump_fields_var_test.vv:13] val.$(field.name): struct {
i: 100
}

View File

@ -88,7 +88,7 @@ fn (mut g Gen) expr_with_opt(expr ast.Expr, expr_typ ast.Type, ret_typ ast.Type)
defer {
g.inside_opt_or_res = old_inside_opt_or_res
}
if expr_typ.has_flag(.option) && ret_typ.has_flag(.option)&& (expr in [ast.Ident, ast.ComptimeSelector, ast.AsCast, ast.CallExpr, ast.MatchExpr, ast.IfExpr, ast.IndexExpr, ast.UnsafeExpr, ast.CastExpr]) {
if expr_typ.has_flag(.option) && ret_typ.has_flag(.option)&& (expr in [ast.DumpExpr, ast.Ident, ast.ComptimeSelector, ast.AsCast, ast.CallExpr, ast.MatchExpr, ast.IfExpr, ast.IndexExpr, ast.UnsafeExpr, ast.CastExpr]) {
if expr in [ast.Ident, ast.CastExpr] {
if expr_typ.idx() != ret_typ.idx() {
return g.expr_opt_with_cast(expr, expr_typ, ret_typ)
@ -239,7 +239,6 @@ fn (mut g Gen) assign_stmt(node_ ast.AssignStmt) {
var_type = g.comptime_var_type_map[key_str] or { var_type }
val_type = var_type
left.obj.typ = var_type
val_type = var_type
}
} else if val is ast.ComptimeCall {
key_str := '${val.method_name}.return_type'
@ -252,6 +251,13 @@ fn (mut g Gen) assign_stmt(node_ ast.AssignStmt) {
var_type = val_type.clear_flag(.option)
left.obj.typ = var_type
}
} else if val is ast.DumpExpr && (val as ast.DumpExpr).expr is ast.ComptimeSelector {
key_str := g.get_comptime_selector_key_type(val.expr as ast.ComptimeSelector)
if key_str != '' {
var_type = g.comptime_var_type_map[key_str] or { var_type }
val_type = var_type
left.obj.typ = var_type
}
}
is_auto_heap = left.obj.is_auto_heap
}

View File

@ -20,7 +20,7 @@ fn (mut g Gen) dump_expr(node ast.DumpExpr) {
if node.expr is ast.Ident {
// var
if node.expr.info is ast.IdentVar && node.expr.language == .v {
name = g.typ(g.unwrap_generic(node.expr.info.typ.clear_flag(.shared_f).clear_flag(.option).clear_flag(.result))).replace('*',
name = g.typ(g.unwrap_generic(node.expr.info.typ.clear_flag(.shared_f).clear_flag(.result))).replace('*',
'')
}
}
@ -32,11 +32,15 @@ fn (mut g Gen) dump_expr(node ast.DumpExpr) {
if node.expr.field_expr.expr.name == g.comptime_for_field_var
&& node.expr.field_expr.field_name == 'name' {
field, _ := g.get_comptime_selector_var_type(node.expr)
name = g.typ(g.unwrap_generic(field.typ.clear_flag(.shared_f).clear_flag(.option).clear_flag(.result)))
name = g.typ(g.unwrap_generic(field.typ.clear_flag(.shared_f).clear_flag(.result)))
expr_type = field.typ
}
}
}
} else if node.expr is ast.Ident && g.is_comptime_var(node.expr) {
expr_type = g.comptime_for_field_type
name = g.typ(g.unwrap_generic(expr_type.clear_flag(.shared_f).clear_flag(.result))).replace('*',
'')
}
if g.table.sym(node.expr_type).language == .c {
@ -49,7 +53,7 @@ fn (mut g Gen) dump_expr(node ast.DumpExpr) {
g.write('&')
g.expr(node.expr)
g.write('->val')
} else if expr_type.has_flag(.option) || expr_type.has_flag(.result) {
} else if expr_type.has_flag(.result) {
old_inside_opt_or_res := g.inside_opt_or_res
g.inside_opt_or_res = true
g.write('(*(${name}*)')
@ -57,7 +61,10 @@ fn (mut g Gen) dump_expr(node ast.DumpExpr) {
g.write('.data)')
g.inside_opt_or_res = old_inside_opt_or_res
} else {
old_inside_opt_or_res := g.inside_opt_or_res
g.inside_opt_or_res = true
g.expr(node.expr)
g.inside_opt_or_res = old_inside_opt_or_res
}
g.write(')')
}
@ -76,13 +83,16 @@ fn (mut g Gen) dump_expr_definitions() {
typ := ast.Type(dump_type)
is_ptr := typ.is_ptr()
deref, _ := deref_kind(str_method_expects_ptr, is_ptr, dump_type)
to_string_fn_name := g.get_str_fn(typ.clear_flag(.shared_f).clear_flag(.option).clear_flag(.result))
to_string_fn_name := g.get_str_fn(typ.clear_flag(.shared_f).clear_flag(.result))
ptr_asterisk := if is_ptr { '*'.repeat(typ.nr_muls()) } else { '' }
mut str_dumparg_type := ''
if dump_sym.kind == .none_ {
str_dumparg_type = 'IError' + ptr_asterisk
} else {
str_dumparg_type = g.cc_type(dump_type, true) + ptr_asterisk
if typ.has_flag(.option) {
str_dumparg_type += '_option_'
}
str_dumparg_type += g.cc_type(dump_type, true) + ptr_asterisk
}
if dump_sym.kind == .function {
fninfo := dump_sym.info as ast.FnType

View File

@ -1,6 +1,6 @@
fn abc[T]() []int {
fn abc[T]() []?int {
a := []?int{len: 2}
mut s := []int{}
mut s := []?int{}
for v in a {
s << dump(v)
}
@ -10,6 +10,8 @@ fn abc[T]() []int {
fn test_main() {
arr := abc[int]()
assert arr.len == 2
assert arr[0] == 0
assert arr[1] == 0
mut t := arr[0]
assert t == none
t = arr[1]
assert t == none
}

View File

@ -0,0 +1,29 @@
struct Test {
a ?string = 'foo'
b ?int = 3
c ?f64 = 1.1
d ?[]int = [1]
e []?int = [?int(2)]
}
fn test_dump_opt1() ? {
a := ?int(0)
b := dump(a)
assert b? == 0
}
fn test_dump_opt2() ? {
c := ?int(none)
d := dump(c)
assert d == none
}
fn test_comptime() ? {
v := Test{}
$for f in Test.fields {
a := dump(v.$(f.name))
b := v.$(f.name)
dump(a)
dump(b)
}
}