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:
parent
71c3b66ecf
commit
32d09544d7
@ -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 {
|
||||
|
@ -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 {
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
}
|
||||
|
29
vlib/v/tests/option_dump_test.v
Normal file
29
vlib/v/tests/option_dump_test.v
Normal 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)
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user