From b1fa0d25f07682a76fb41d436a0a85185b76d018 Mon Sep 17 00:00:00 2001 From: Alexander Medvednikov Date: Wed, 13 Nov 2019 21:47:05 +0300 Subject: [PATCH] foo()? syntax --- vlib/compiler/comptime.v | 6 ++++-- vlib/compiler/expression.v | 24 +++++++++++++++++++----- vlib/compiler/gen_c.v | 4 ++-- vlib/compiler/main.v | 2 +- vlib/compiler/tests/option_test.v | 8 ++++++++ 5 files changed, 34 insertions(+), 10 deletions(-) diff --git a/vlib/compiler/comptime.v b/vlib/compiler/comptime.v index a9c7824e7b..01c3c6ceb5 100644 --- a/vlib/compiler/comptime.v +++ b/vlib/compiler/comptime.v @@ -103,7 +103,9 @@ fn (p mut Parser) comp_time() { else_returns := p.returns p.returns = if_returns && else_returns //p.gen('/* returns $p.returns */') - } + } else if p.tok == .key_else { + p.error('use `$' + 'else` instead of `else` in comptime if statements') + } } else if p.tok == .key_for { p.next() @@ -234,7 +236,7 @@ fn (p mut Parser) chash() { p.cgen.includes << '#$hash' } } - // Don't parse a non-JS V file (`#-js` flag) + //// Don't parse a non-JS V file (`#-js` flag) else if hash == '-js' { $if js { for p.tok != .eof { diff --git a/vlib/compiler/expression.v b/vlib/compiler/expression.v index eb5885a476..234467fbf2 100644 --- a/vlib/compiler/expression.v +++ b/vlib/compiler/expression.v @@ -221,8 +221,6 @@ fn (p mut Parser) name_expr() string { !p.table.known_fn(name) && !p.table.known_const(name) && !is_c { name = p.prepend_mod(name) - } else { - //println('$name') } // re-check if p.known_var_check_new_var(name) { @@ -331,13 +329,29 @@ fn (p mut Parser) name_expr() string { f = new_f // optional function call `function() or {}`, no return assignment - is_or_else := p.tok == .key_orelse - if !p.is_var_decl && is_or_else { + is_or_else := p.tok == .key_orelse + if p.tok == .question { + // `files := os.ls('.')?` + if p.cur_fn.name != 'main__main' { + p.error('`func()?` syntax can only be used inside `fn main()` for now') + } + p.next() + tmp := p.get_tmp() + p.cgen.set_placeholder(fn_call_ph, '$f.typ $tmp = ') + p.genln(';') + p.genln('if (!${tmp}.ok) v_panic(${tmp}.error);') + typ := f.typ[7..] // option_xxx + p.gen('*($typ*) ${tmp}.data;') + return typ + } + else if !p.is_var_decl && is_or_else { f.typ = p.gen_handle_option_or_else(f.typ, '', fn_call_ph) + p.print_tok() } - else if !p.is_var_decl && !is_or_else && !p.inside_return_expr && + else if !p.is_var_decl && !is_or_else && !p.inside_return_expr && f.typ.starts_with('Option_') { opt_type := f.typ[7..] + p.print_tok() p.error('unhandled option type: `?$opt_type`') } diff --git a/vlib/compiler/gen_c.v b/vlib/compiler/gen_c.v index 59f4b1424a..eaf059e265 100644 --- a/vlib/compiler/gen_c.v +++ b/vlib/compiler/gen_c.v @@ -129,11 +129,11 @@ fn (p mut Parser) gen_handle_option_or_else(_typ, name string, fn_call_ph int) s expr_line := p.cgen.lines[p.cgen.lines.len-2] last_expr := expr_line[last_ph..] p.cgen.lines[p.cgen.lines.len-2] = '' - p.genln('if (!$tmp .ok) {') + p.genln('if (!${tmp}.ok) {') p.genln('$name = $last_expr;') p.genln('}') } else if is_assign { - p.genln('$name = *($typ*) $tmp . data;') + p.genln('$name = *($typ*)${tmp}.data;') } if !p.returns && last_typ != typ && is_assign && p.prev_tok2 != .key_continue && p.prev_tok2 != .key_break { p.error_with_token_index('`or` block must provide a default value or return/exit/continue/break/panic', or_tok_idx) diff --git a/vlib/compiler/main.v b/vlib/compiler/main.v index e2e0482773..ce06cba24c 100644 --- a/vlib/compiler/main.v +++ b/vlib/compiler/main.v @@ -892,7 +892,7 @@ pub fn new_v(args[]string) &V { //println('VROOT=$vroot') // v.exe's parent directory should contain vlib if !os.dir_exists(vroot) || !os.dir_exists(vroot + '/vlib/builtin') { - println('vlib not found, downloading it...') + //println('vlib not found, downloading it...') /* ret := os.system('git clone --depth=1 https://github.com/vlang/v .') if ret != 0 { diff --git a/vlib/compiler/tests/option_test.v b/vlib/compiler/tests/option_test.v index f9250ad38a..c6961d0450 100644 --- a/vlib/compiler/tests/option_test.v +++ b/vlib/compiler/tests/option_test.v @@ -70,3 +70,11 @@ fn test_opt_default() { } assert a == 'default' } + +fn foo_ok() ?int { + return 777 +} + +fn test_q() { + //assert foo_ok()? == true +}