From 6349bd33d3239f3f49376b0673bb53475460a094 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=CA=87=CA=9E=CA=8Cp?= Date: Mon, 25 Nov 2019 22:07:35 -0800 Subject: [PATCH] compiler: Allow `or` usage when assigning to struct fields. (#2893) --- vlib/compiler/gen_c.v | 2 +- vlib/compiler/parser.v | 14 +++++++++++-- vlib/compiler/tests/option_test.v | 34 +++++++++++++++++++++++++++++++ 3 files changed, 47 insertions(+), 3 deletions(-) diff --git a/vlib/compiler/gen_c.v b/vlib/compiler/gen_c.v index 3ce761219e..fef32f0f0b 100644 --- a/vlib/compiler/gen_c.v +++ b/vlib/compiler/gen_c.v @@ -117,7 +117,7 @@ fn (p mut Parser) gen_handle_option_or_else(_typ, name string, fn_call_ph int) s is_mut: false is_used: true }) - if is_assign { + if is_assign && !name.contains('.') { // don't initialize struct fields p.genln('$typ $name;') } p.genln('if (!$tmp .ok) {') diff --git a/vlib/compiler/parser.v b/vlib/compiler/parser.v index d35b2fefcb..b4040d4dfe 100644 --- a/vlib/compiler/parser.v +++ b/vlib/compiler/parser.v @@ -1361,7 +1361,9 @@ fn ($v.name mut $v.typ) $p.cur_fn.name (...) { p.next() p.fspace() pos := p.cgen.cur_line.len + p.is_var_decl = true expr_type := p.bool_expression() + p.is_var_decl = false //if p.expected_type.starts_with('array_') { //p.warn('expecting array got $expr_type') //} @@ -1377,9 +1379,17 @@ fn ($v.name mut $v.typ) $p.cur_fn.name (...) { typ := expr_type.replace('Option_', '') p.cgen.resetln(left + 'opt_ok($expr, sizeof($typ))') } + else if expr_type.starts_with('Option_') && + p.assigned_type == expr_type['Option_'.len..] && p.tok == .key_orelse + { + line := p.cgen.cur_line + vname := line[..pos].replace('=','') // TODO cgen line hack + p.cgen.resetln(line.replace(line[..line.index('=')+1], '')) + p.gen_handle_option_or_else(expr_type, vname, ph) + } else if expr_type[0]==`[` { - // assignment to a fixed_array `mut a:=[3]int a=[1,2,3]!!` - expr := p.cgen.cur_line[pos..].all_after('{').all_before('}') + // assignment to a fixed_array `mut a:=[3]int a=[1,2,3]!!` + expr := p.cgen.cur_line[pos..].all_after('{').all_before('}') // TODO cgen line hack left := p.cgen.cur_line[..pos].all_before('=') cline_pos := p.cgen.cur_line[pos..] etype := cline_pos.all_before(' {') diff --git a/vlib/compiler/tests/option_test.v b/vlib/compiler/tests/option_test.v index c6961d0450..098d822fa0 100644 --- a/vlib/compiler/tests/option_test.v +++ b/vlib/compiler/tests/option_test.v @@ -75,6 +75,40 @@ fn foo_ok() ?int { return 777 } +fn foo_str() ?string { + return 'something' +} + fn test_q() { //assert foo_ok()? == true } + +struct Person { +mut: + name string + age int + title ?string +} + +fn test_field_or() { + name := foo_str() or { + 'nada' + } + assert name == 'something' + + mut p := Person {} + p.name = foo_str() or { + 'nothing' + } + assert p.name == 'something' + + p.age = foo_ok() or { + panic('no age') + } + assert p.age == 777 + + mytitle := p.title or { + 'default' + } + assert mytitle == 'default' +} \ No newline at end of file