Skip to content

Commit

Permalink
v: unwrap an option value automatically, inside if o != none { (vla…
Browse files Browse the repository at this point in the history
  • Loading branch information
felipensp authored Dec 27, 2023
1 parent 34858c3 commit b944927
Show file tree
Hide file tree
Showing 3 changed files with 90 additions and 5 deletions.
3 changes: 3 additions & 0 deletions vlib/v/checker/if.v
Original file line number Diff line number Diff line change
Expand Up @@ -515,6 +515,9 @@ fn (mut c Checker) smartcast_if_conds(mut node ast.Expr, mut scope ast.Scope) {
if node.op == .and {
c.smartcast_if_conds(mut node.left, mut scope)
c.smartcast_if_conds(mut node.right, mut scope)
} else if node.left is ast.Ident && node.op == .ne && node.right is ast.None {
c.smartcast(mut node.left, node.left_type, node.left_type.clear_flag(.option), mut
scope)
} else if node.op == .key_is {
right_expr := node.right
right_type := match right_expr {
Expand Down
23 changes: 18 additions & 5 deletions vlib/v/gen/c/cgen.v
Original file line number Diff line number Diff line change
Expand Up @@ -4495,19 +4495,27 @@ fn (mut g Gen) ident(node ast.Ident) {
if node.obj.smartcasts.len > 0 {
obj_sym := g.table.sym(node.obj.typ)
if !prevent_sum_type_unwrapping_once {
for _ in node.obj.smartcasts {
for _, typ in node.obj.smartcasts {
is_option_unwrap := is_option && typ == node.obj.typ.clear_flag(.option)
g.write('(')
if obj_sym.kind == .sum_type && !is_auto_heap {
g.write('*')
if is_option {
if !is_option_unwrap {
g.write('*(')
}
styp := g.base_type(node.obj.typ)
g.write('(*(${styp}*)')
g.write('*(${styp}*)')
} else {
g.write('*')
}
} else if g.inside_interface_deref && g.table.is_interface_var(node.obj) {
g.write('*')
} else if is_option {
g.write('*(${g.base_type(node.obj.typ)}*)')
}
}
for i, typ in node.obj.smartcasts {
is_option_unwrap := is_option && typ == node.obj.typ.clear_flag(.option)
cast_sym := g.table.sym(g.unwrap_generic(typ))
if obj_sym.kind == .interface_ && cast_sym.kind == .interface_ {
ptr := '*'.repeat(node.obj.typ.nr_muls())
Expand All @@ -4529,9 +4537,14 @@ fn (mut g Gen) ident(node ast.Ident) {
g.write('${dot}_${sym.cname}')
} else {
if is_option {
g.write('.data)')
g.write('.data')
if !is_option_unwrap {
g.write(')')
}
}
if !is_option_unwrap && obj_sym.kind in [.sum_type, .interface_] {
g.write('${dot}_${cast_sym.cname}')
}
g.write('${dot}_${cast_sym.cname}')
}
}
g.write(')')
Expand Down
69 changes: 69 additions & 0 deletions vlib/v/tests/option_cast_test.v
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
struct Test {
a int
}

type MySum = f64 | int

type MyAlias = Test

fn test_int() {
a := ?int(1)
if a != none {
assert dump(a) == 1
assert true
} else {
assert false
}
}

fn test_struct() {
b := ?Test{
a: 1
}
if b != none {
assert dump(b) == Test{
a: 1
}
assert true
} else {
assert false
}
}

fn test_string() {
c := ?string('foo')
if c != none {
assert dump(c) == 'foo'
assert true
} else {
assert false
}
}

fn test_sum_type() {
d := ?MySum(1.2)
assert d != none

if d != none {
assert dump(d) == MySum(1.2)
assert true
} else {
assert false
}
}

fn test_alias() {
d := ?MyAlias(Test{
a: 1
})
assert d != none

if d != none {
assert dump(d) == Test{
a: 1
}
assert true
} else {
assert false
}
}

0 comments on commit b944927

Please sign in to comment.